Esempio n. 1
0
    async def on_message(self, message: discord.Message) -> None:
        """Move an available channel to the In Use category and replace it with a dormant one."""
        if message.author.bot:
            return  # Ignore messages sent by bots.

        channel = message.channel

        await self.check_for_answer(message)

        is_available = channel_utils.is_in_category(
            channel, constants.Categories.help_available)
        if not is_available or self.is_excluded_channel(channel):
            return  # Ignore messages outside the Available category or in excluded channels.

        log.trace(
            "Waiting for the cog to be ready before processing messages.")
        await self.ready.wait()

        log.trace(
            "Acquiring lock to prevent a channel from being processed twice..."
        )
        async with self.on_message_lock:
            log.trace(f"on_message lock acquired for {message.id}.")

            if not channel_utils.is_in_category(
                    channel, constants.Categories.help_available):
                log.debug(
                    f"Message {message.id} will not make #{channel} ({channel.id}) in-use "
                    f"because another message in the channel already triggered that."
                )
                return

            log.info(
                f"Channel #{channel} was claimed by `{message.author.id}`.")
            await self.move_to_in_use(channel)
            await self.revoke_send_permissions(message.author)

            await self.pin(message)

            # Add user with channel for dormant check.
            await self.help_channel_claimants.set(channel.id,
                                                  message.author.id)

            self.bot.stats.incr("help.claimed")

            # Must use a timezone-aware datetime to ensure a correct POSIX timestamp.
            timestamp = datetime.now(timezone.utc).timestamp()
            await self.claim_times.set(channel.id, timestamp)

            await self.unanswered.set(channel.id, True)

            log.trace(f"Releasing on_message lock for {message.id}.")

        # Move a dormant channel to the Available category to fill in the gap.
        # This is done last and outside the lock because it may wait indefinitely for a channel to
        # be put in the queue.
        await self.move_to_available()
Esempio n. 2
0
    async def on_message_delete(self, msg: discord.Message) -> None:
        """
        Reschedule an in-use channel to become dormant sooner if the channel is empty.

        The new time for the dormant task is configured with `HelpChannels.deleted_idle_minutes`.
        """
        await self.init_task

        if not channel_utils.is_in_category(msg.channel,
                                            constants.Categories.help_in_use):
            return

        if not await _message.is_empty(msg.channel):
            return

        log.info(
            f"Claimant of #{msg.channel} ({msg.author}) deleted message, channel is empty now. Rescheduling task."
        )

        # Cancel existing dormant task before scheduling new.
        self.scheduler.cancel(msg.channel.id)

        delay = constants.HelpChannels.deleted_idle_minutes * 60
        self.scheduler.schedule_later(delay, msg.channel.id,
                                      self.move_idle_channel(msg.channel))
Esempio n. 3
0
File: _cog.py Progetto: Kronifer/bot
    async def on_message(self, message: discord.Message) -> None:
        """Move an available channel to the In Use category and replace it with a dormant one."""
        if message.author.bot:
            return  # Ignore messages sent by bots.

        await self.init_task

        if channel_utils.is_in_category(message.channel,
                                        constants.Categories.help_available):
            if not _channel.is_excluded_channel(message.channel):
                await self.claim_channel(message)

        elif channel_utils.is_in_category(message.channel,
                                          constants.Categories.help_in_use):
            await self.notify_session_participants(message)
            await _message.update_message_caches(message)
Esempio n. 4
0
    async def on_message(self, message: Message) -> None:
        """Report message events in the server to statsd."""
        if message.guild is None:
            return

        if message.guild.id != Guild.id:
            return

        if is_in_category(message.channel, Categories.modmail):
            if message.channel.id != Channels.incidents:
                # Do not report modmail channels to stats, there are too many
                # of them for interesting statistics to be drawn out of this.
                return

        reformatted_name = message.channel.name.replace('-', '_')

        if CHANNEL_NAME_OVERRIDES.get(message.channel.id):
            reformatted_name = CHANNEL_NAME_OVERRIDES.get(message.channel.id)

        reformatted_name = "".join(char for char in reformatted_name
                                   if char in ALLOWED_CHARS)

        stat_name = f"channels.{reformatted_name}"
        self.bot.stats.incr(stat_name)

        # Increment the total message count
        self.bot.stats.incr("messages")
Esempio n. 5
0
async def check_for_answer(message: discord.Message) -> None:
    """Checks for whether new content in a help channel comes from non-claimants."""
    channel = message.channel

    # Confirm the channel is an in use help channel
    if is_in_category(channel, constants.Categories.help_in_use):
        log.trace(f"Checking if #{channel} ({channel.id}) has been answered.")

        # Check if there is an entry in unanswered
        if await _caches.unanswered.contains(channel.id):
            claimant_id = await _caches.claimants.get(channel.id)
            if not claimant_id:
                # The mapping for this channel doesn't exist, we can't do anything.
                return

            # Check the message did not come from the claimant
            if claimant_id != message.author.id:
                # Mark the channel as answered
                await _caches.unanswered.set(channel.id, False)
Esempio n. 6
0
async def update_message_caches(message: discord.Message) -> None:
    """Checks the source of new content in a help channel and updates the appropriate cache."""
    channel = message.channel

    # Confirm the channel is an in use help channel
    if is_in_category(channel, constants.Categories.help_in_use):
        log.trace(f"Checking if #{channel} ({channel.id}) has had a reply.")

        claimant_id = await _caches.claimants.get(channel.id)
        if not claimant_id:
            # The mapping for this channel doesn't exist, we can't do anything.
            return

        # datetime.timestamp() would assume it's local, despite d.py giving a (naïve) UTC time.
        timestamp = Arrow.fromdatetime(message.created_at).timestamp()

        # Overwrite the appropriate last message cache depending on the author of the message
        if message.author.id == claimant_id:
            await _caches.claimant_last_message_times.set(
                channel.id, timestamp)
        else:
            await _caches.non_claimant_last_message_times.set(
                channel.id, timestamp)