Cog-Creators / Red-DiscordBot

A multi-function Discord bot
https://docs.discord.red
GNU General Public License v3.0
4.69k stars 2.3k forks source link

Optimize Trivia list loading #6336

Open Jackenmen opened 4 months ago

Jackenmen commented 4 months ago

Description of the changes

To support listing descriptions in [p]trivia list, there's a need for further optimizations in the list loading process.

Optimizations made:

The latter change is supposed to help us support retrieval of the actually needed fields without having to validate schema of the whole file, for example:

def _get_list_description(path: pathlib.Path) -> str:
    """
    Returns a trivia list description from the given path.

    Raises
    ------
    InvalidListError
        Parsing of list's YAML file failed.
    """
    trivia_dict = get_list(path, validate_schema=False)
    return str(trivia_dict.get("DESCRIPTION", ""))

@Kreusada here's an example of how we can optimally get trivia descriptions for [p]trivia list output (10 per page in this example + cache for previously generated pages) when you work on it:

import pathlib
from typing import Dict, List

from redbot.vendored.discord.ext import menus as dpy_menus
from redbot.core.utils import views
from redbot.core.utils.chat_formatting import bold, italics

class _TriviasSource(dpy_menus.ListPageSource):
    def __init__(self, items: List[pathlib.Path]):
        super().__init__(items, per_page=10)
        self._cache: Dict[int, str] = {}

    async def get_page(self, page_number: int) -> str:
        cached = self._cache.get(page_number)
        if cached is not None:
            return cached

        categories = await super().get_page(page_number)
        entries = []
        for path in categories:
            description = _get_list_description(path)
            if len(description) > 100:
                description = f"{description[:99]}\N{HORIZONTAL ELLIPSIS}"
            elif not description:
                description = italics(_("No description provided for this category."))

            entries.append(f"- {bold(path.stem)} - {description}")

        ret = "\n".join(entries)
        self._cache[page_number] = ret
        return ret

    async def format_page(
        self, view: discord.ui.View, page: views._ACCEPTABLE_PAGE_TYPES
    ) -> views._ACCEPTABLE_PAGE_TYPES:
        return page

# ...

# in `[p]trivia list` implementation:
items = self._all_lists()
menu = views.SimpleMenu(items)
menu._source = _TriviasSource(items)
await menu.start(ctx)

Have the changes in this PR been tested?

Yes