예제 #1
0
    async def info(self, ctx):
        channel_info = await self.get_channel_config(ctx.channel.id)
        if not channel_info:
            return await ctx.send(
                embed=util.info_embed("Phone status", "Not a phone channel"))
        addr = channel_info['id']
        title = f"{addr} status"

        fields = []

        now = datetime.utcnow()

        def delta(ts):
            return util.format_timedelta(datetime.utcfromtimestamp(ts), now)

        incoming = await self.bot.database.execute_fetchall(
            "SELECT * FROM calls WHERE to_id = ?", (addr, ))
        fields.extend(
            map(
                lambda x: [
                    "Incoming call",
                    f"From {x['from_id']} - for {delta(x['start_time'])}"
                ], incoming))
        outgoing = await self.bot.database.execute_fetchall(
            "SELECT * FROM calls WHERE from_id = ?", (addr, ))
        fields.extend(
            map(
                lambda x: [
                    "Outgoing call",
                    f"To {x['to_id']} - for {delta(x['start_time'])}"
                ], outgoing))
        await ctx.send(embed=util.info_embed(
            title, f"Connected: {len(incoming) + len(outgoing)}", fields))
예제 #2
0
    async def hangup(self, ctx):
        channel_info = await self.get_channel_config(ctx.channel.id)
        addr = channel_info["id"]
        if not channel_info:
            return await ctx.send(
                embed=util.error_embed("Not in a phone channel."))
        from_here = await self.bot.database.execute_fetchone(
            "SELECT * FROM calls WHERE from_id = ?", (addr, ))
        to_here = await self.bot.database.execute_fetchone(
            "SELECT * FROM calls WHERE to_id = ?", (addr, ))
        if (not to_here) and (not from_here):
            return await ctx.send(
                embed=util.error_embed("No calls are active."))

        other = None
        if from_here:
            other = from_here["to_id"]
            await self.bot.database.execute(
                "DELETE FROM calls WHERE from_id = ? AND to_id = ?",
                (addr, other))
        elif to_here:
            other = to_here["from_id"]
            await self.bot.database.execute(
                "DELETE FROM calls WHERE to_id = ? AND from_id = ?",
                (addr, other))
        await self.bot.database.commit()
        other_channel = (await self.get_addr_config(other))["channel_id"]
        await eventbus.remove_bridge_link(self.bot.database,
                                          ("discord", other_channel),
                                          ("discord", ctx.channel.id))

        await asyncio.gather(
            ctx.send(embed=util.info_embed("Hung up",
                                           f"Call to {other} disconnected.")),
            self.bot.get_channel(other_channel).send(embed=util.info_embed(
                "Hung up", f"Call to {addr} disconnected.")))
예제 #3
0
    async def dial(self, ctx, address):
        # basic checks - ensure this is a phone channel and has no other open calls
        channel_info = await self.get_channel_config(ctx.channel.id)
        if not channel_info:
            return await ctx.send(
                embed=util.error_embed("Not in a phone channel."))
        originating_address = channel_info["id"]
        if address == originating_address:
            return await ctx.send(embed=util.error_embed(
                "A channel cannot dial itself. That means *you*, Gibson."))
        recv_info = await self.get_addr_config(address)
        if not recv_info:
            return await ctx.send(embed=util.error_embed(
                "Destination address not found. Please check for typos and/or antimemes."
            ))

        current_call = await self.bot.database.execute_fetchone(
            "SELECT * FROM calls WHERE from_id = ?", (originating_address, ))
        if current_call:
            return await ctx.send(embed=util.error_embed(
                f"A call is already open (to {current_call['to_id']}) from this channel. Currently, only one outgoing call is permitted at a time."
            ))

        # post embed in the receiving channel prompting people to accept/decline call
        recv_channel = self.bot.get_channel(recv_info["channel_id"])
        _, call_message = await asyncio.gather(
            ctx.send(embed=util.info_embed("Outgoing call",
                                           f"Dialing {address}...")),
            recv_channel.send(embed=util.info_embed(
                "Incoming call",
                f"Call from {originating_address}. Click :white_check_mark: to accept or :negative_squared_cross_mark: to decline."
            )))
        # add clickable reactions to it
        await asyncio.gather(call_message.add_reaction("✅"),
                             call_message.add_reaction("❎"))

        def check(re, u):
            return (str(re.emoji) == "✅"
                    or str(re.emoji) == "❎") and u != self.bot.user

        reaction = None
        # wait until someone clicks the reactions, or time out and say so
        try:
            reaction, user = await self.bot.wait_for(
                "reaction_add",
                timeout=util.config["call_timeout"],
                check=check)
        except asyncio.TimeoutError:
            await asyncio.gather(
                ctx.send(embed=util.error_embed(
                    "Timed out",
                    "Outgoing call timed out - the other end did not pick up.")
                         ),
                recv_channel.send(embed=util.error_embed(
                    "Timed out", "Call timed out - no response in time")))

        await asyncio.gather(call_message.remove_reaction("✅", self.bot.user),
                             call_message.remove_reaction("❎", self.bot.user))
        em = str(reaction.emoji) if reaction else "❎"
        if em == "✅":  # accept call
            await self.bot.database.execute(
                "INSERT INTO calls VALUES (?, ?, ?)",
                (originating_address, address, util.timestamp()))
            await self.bot.database.commit()
            await eventbus.add_bridge_link(self.bot.database,
                                           ("discord", ctx.channel.id),
                                           ("discord", recv_channel.id),
                                           "telephone")
            await asyncio.gather(
                ctx.send(embed=util.info_embed(
                    "Outgoing call", "Call accepted and connected.")),
                recv_channel.send(embed=util.info_embed(
                    "Incoming call", "Call accepted and connected.")))
        elif em == "❎":  # drop call
            await ctx.send(embed=util.error_embed("Your call was declined.",
                                                  "Call declined"))