Ejemplo n.º 1
0
Archivo: _cog.py Proyecto: Kronifer/bot
    async def init_available(self) -> None:
        """Initialise the Available category with channels."""
        log.trace("Initialising the Available category with channels.")

        channels = list(_channel.get_category_channels(
            self.available_category))
        missing = constants.HelpChannels.max_available - len(channels)

        # If we've got less than `max_available` channel available, we should add some.
        if missing > 0:
            log.trace(
                f"Moving {missing} missing channels to the Available category."
            )
            for _ in range(missing):
                await self.move_to_available()

        # If for some reason we have more than `max_available` channels available,
        # we should move the superfluous ones over to dormant.
        elif missing < 0:
            log.trace(
                f"Moving {abs(missing)} superfluous available channels over to the Dormant category."
            )
            for channel in channels[:abs(missing)]:
                await self.unclaim_channel(
                    channel, closed_on=_channel.ClosingReason.CLEANUP)

        self.available_help_channels = set(
            _channel.get_category_channels(self.available_category))

        # Getting channels that need to be included in the dynamic message.
        await self.update_available_help_channels()
        log.trace("Dynamic available help message updated.")
Ejemplo n.º 2
0
Archivo: _cog.py Proyecto: lxnn/bot
    def report_stats(self) -> None:
        """Report the channel count stats."""
        total_in_use = sum(1 for _ in _channel.get_category_channels(self.in_use_category))
        total_available = sum(1 for _ in _channel.get_category_channels(self.available_category))
        total_dormant = sum(1 for _ in _channel.get_category_channels(self.dormant_category))

        self.bot.stats.gauge("help.total.in_use", total_in_use)
        self.bot.stats.gauge("help.total.available", total_available)
        self.bot.stats.gauge("help.total.dormant", total_dormant)
Ejemplo n.º 3
0
    async def init_cog(self) -> None:
        """Initialise the help channel system."""
        log.trace(
            "Waiting for the guild to be available before initialisation.")
        await self.bot.wait_until_guild_available()

        log.trace("Initialising the cog.")
        await self.init_categories()
        await _cooldown.check_cooldowns(self.scheduler)

        self.channel_queue = self.create_channel_queue()
        self.name_queue = _name.create_name_queue(
            self.available_category,
            self.in_use_category,
            self.dormant_category,
        )

        log.trace("Moving or rescheduling in-use channels.")
        for channel in _channel.get_category_channels(self.in_use_category):
            await self.move_idle_channel(channel, has_task=False)

        # Prevent the command from being used until ready.
        # The ready event wasn't used because channels could change categories between the time
        # the command is invoked and the cog is ready (e.g. if move_idle_channel wasn't called yet).
        # This may confuse users. So would potentially long delays for the cog to become ready.
        self.close_command.enabled = True

        await self.init_available()
        _stats.report_counts()

        log.info("Cog is ready!")
Ejemplo n.º 4
0
def report_counts() -> None:
    """Report channel count stats of each help category."""
    for name in ("in_use", "available", "dormant"):
        id_ = getattr(constants.Categories, f"help_{name}")
        category = bot.instance.get_channel(id_)

        if category:
            total = ilen(_channel.get_category_channels(category))
            bot.instance.stats.gauge(f"help.total.{name}", total)
        else:
            log.warning(
                f"Couldn't find category {name!r} to track channel count stats."
            )
Ejemplo n.º 5
0
    async def get_available_candidate(self) -> discord.TextChannel:
        """
        Return a dormant channel to turn into an available channel and change the
        message in the help instructions channel to match the new available channels.

        If no channel is available, wait indefinitely until one becomes available.
        """
        log.trace("Getting an available channel candidate.")

        try:
            channel = self.channel_queue.get_nowait()
        except asyncio.QueueEmpty:
            log.info(
                "No candidate channels in the queue; creating a new channel.")
            channel = await self.create_dormant()

            if not channel:
                log.info(
                    "Couldn't create a candidate channel; waiting to get one from the queue."
                )
                notify_channel = self.bot.get_channel(
                    constants.HelpChannels.notify_channel)
                last_notification = await _message.notify(
                    notify_channel, self.last_notification)
                if last_notification:
                    self.last_notification = last_notification
                    self.bot.stats.incr("help.out_of_channel_alerts")
                channel = await self.wait_for_dormant_channel()
        message = await channel.fetch_message(channel.last_message_id)
        channels = _channel.get_category_channels(
            constants.Categories.help_available)
        string = AVAILABLE_CHANNELS_MESSAGE.format(len(channels),
                                                   ", ".join(channels))
        # Attempt to get the message from channel.history if last_message_id fails.
        if message is None:
            history = await channel.history()
            try:
                message = await history.flatten()[0]
            except IndexError:
                pass
        # Edit the message if it exists, send it if it doesn't.
        if message is None:
            log.info(
                "Couldn't fetch the latest message in the help instructions message; creating one."
            )
            await channel.send(string)
        else:
            await message.edit(string)

        return channel
Ejemplo n.º 6
0
def _get_used_names(*categories: discord.CategoryChannel) -> t.Set[str]:
    """Return names which are already being used by channels in `categories`."""
    log.trace("Getting channel names which are already being used.")

    names = set()
    for cat in categories:
        for channel in get_category_channels(cat):
            names.add(channel.name)

    if len(names) > MAX_CHANNELS_PER_CATEGORY:
        log.warning(
            f"Too many help channels ({len(names)}) already exist! "
            f"Discord only supports {MAX_CHANNELS_PER_CATEGORY} in a category."
        )

    log.trace(f"Got {len(names)} used names: {names}")
    return names
Ejemplo n.º 7
0
    def create_channel_queue(self) -> asyncio.Queue:
        """
        Return a queue of dormant channels to use for getting the next available channel.

        The channels are added to the queue in a random order.
        """
        log.trace("Creating the channel queue.")

        channels = list(_channel.get_category_channels(self.dormant_category))
        random.shuffle(channels)

        log.trace("Populating the channel queue with channels.")
        queue = asyncio.Queue()
        for channel in channels:
            queue.put_nowait(channel)

        return queue
Ejemplo n.º 8
0
Archivo: _cog.py Proyecto: lxnn/bot
    async def init_available(self) -> None:
        """Initialise the Available category with channels."""
        log.trace("Initialising the Available category with channels.")

        channels = list(_channel.get_category_channels(self.available_category))
        missing = constants.HelpChannels.max_available - len(channels)

        # If we've got less than `max_available` channel available, we should add some.
        if missing > 0:
            log.trace(f"Moving {missing} missing channels to the Available category.")
            for _ in range(missing):
                await self.move_to_available()

        # If for some reason we have more than `max_available` channels available,
        # we should move the superfluous ones over to dormant.
        elif missing < 0:
            log.trace(f"Moving {abs(missing)} superfluous available channels over to the Dormant category.")
            for channel in channels[:abs(missing)]:
                await self.move_to_dormant(channel, "auto")
Ejemplo n.º 9
0
Archivo: _cog.py Proyecto: Kronifer/bot
    async def init_cog(self) -> None:
        """Initialise the help channel system."""
        log.trace(
            "Waiting for the guild to be available before initialisation.")
        await self.bot.wait_until_guild_available()

        log.trace("Initialising the cog.")
        self.guild = self.bot.get_guild(constants.Guild.id)
        self.cooldown_role = self.guild.get_role(constants.Roles.help_cooldown)

        await self.init_categories()

        self.channel_queue = self.create_channel_queue()
        self.name_queue = _name.create_name_queue(
            self.available_category,
            self.in_use_category,
            self.dormant_category,
        )

        log.trace("Moving or rescheduling in-use channels.")
        for channel in _channel.get_category_channels(self.in_use_category):
            await self.move_idle_channel(channel, has_task=False)

        # Prevent the command from being used until ready.
        # The ready event wasn't used because channels could change categories between the time
        # the command is invoked and the cog is ready (e.g. if move_idle_channel wasn't called yet).
        # This may confuse users. So would potentially long delays for the cog to become ready.
        self.close_command.enabled = True

        # Acquiring the dynamic message ID, if it exists within the cache.
        log.trace("Attempting to fetch How-to-get-help dynamic message ID.")
        self.dynamic_message = await _caches.dynamic_message.get("message_id")

        await self.init_available()
        _stats.report_counts()

        log.info("Cog is ready!")