diff --git a/README.md b/README.md index cabab54..404b444 100644 --- a/README.md +++ b/README.md @@ -79,24 +79,21 @@ from discord_progress_bar import ProgressBarManager # Create a Discord bot with emoji caching enabled bot = discord.Bot(cache_app_emojis=True) -progress_bar_manager = None -progress_bar = None +# Create the progress bar manager (doesn't load emojis yet) +progress_manager = ProgressBarManager(bot) @bot.event async def on_ready(): - """Initialize the ProgressBarManager when the bot is ready.""" - global progress_bar_manager, progress_bar + """Load emojis when the bot is ready.""" + await progress_manager.load() + print(f"Logged in as {bot.user}") - # Initialize the progress bar manager - progress_bar_manager = await ProgressBarManager(bot) - # Get a progress bar with the "green" style - progress_bar = await progress_bar_manager.progress_bar("green") - -@bot.slash_command() +@bot.command() async def show_progress(ctx, percent: float = 0.5): """Display a progress bar with the specified percentage.""" - await ctx.respond(f"Progress: {progress_bar.partial(percent)}") + progress_bar = await progress_manager.progress_bar("green", length=10) + await ctx.send(f"Progress: {progress_bar.partial(percent)}") # Run your bot bot.run("YOUR_TOKEN") @@ -233,14 +230,22 @@ This is required for the `ProgressBarManager` to properly load and manage emojis ### Progress Bar Manager Initialization -Initialize the `ProgressBarManager` after your bot is ready: +Create a `ProgressBarManager` instance when your bot starts, and load emojis in the +`on_ready` event: ```python -@discord.Cog.listener() -async def on_ready(self) -> None: - self.progress_bar_manager = await ProgressBarManager(self.bot) +# Create the manager (doesn't load emojis yet) +progress_manager = ProgressBarManager(bot) + +@bot.event +async def on_ready(): + """Load emojis from the server after the bot is ready.""" + await progress_manager.load() ``` +This approach ensures that your bot can properly initialize and load emojis once it's +connected to Discord. + ### Custom Progress Bar Styles You can create custom progress bar styles by providing your own emoji images: diff --git a/examples/basic.py b/examples/basic.py index 3a06a27..6001946 100644 --- a/examples/basic.py +++ b/examples/basic.py @@ -17,22 +17,27 @@ bot = discord.Bot(cache_app_emojis=True) class MyCog(discord.Cog): def __init__(self, bot: discord.Bot) -> None: self.bot: discord.Bot = bot - self.progress_bar_manager: ProgressBarManager - self.progress_bar: ProgressBar + self.progress_bar_manager: ProgressBarManager = ProgressBarManager(self.bot) + self.progress_bar: ProgressBar | None = None @discord.Cog.listener() async def on_ready(self) -> None: print(f"Logged in as {bot.user} (ID: {bot.user.id})") # pyright: ignore [reportOptionalMemberAccess] print("------") - self.progress_bar_manager = await ProgressBarManager(self.bot) + await self.progress_bar_manager.load() self.progress_bar = await self.progress_bar_manager.progress_bar("green", length=10) print("Progress bar manager loaded.") @discord.slash_command() # pyright: ignore [reportUntypedFunctionDecorator] async def get_progress_bar(self, ctx: discord.ApplicationContext, percent: float | None = None) -> None: """Send a progress bar message.""" - if percent is None: + if not self.progress_bar: + await ctx.respond("Progress bar manager is not loaded yet.") + return + + if percent is None or percent > 1: percent = 1 + await ctx.respond(f"Progress: {self.progress_bar.partial(percent)}") diff --git a/src/discord_progress_bar/progress_bar.py b/src/discord_progress_bar/progress_bar.py index 96a6b48..b0ad056 100644 --- a/src/discord_progress_bar/progress_bar.py +++ b/src/discord_progress_bar/progress_bar.py @@ -2,7 +2,7 @@ # SPDX-License-Identifier: MIT from collections import defaultdict -from typing import Self, cast +from typing import cast import aiofile import aiohttp @@ -67,20 +67,25 @@ class ProgressBarManager: def __init__(self, bot: discord.Bot) -> None: self._bot: discord.Bot = bot self._emojis: dict[str, ProgressBarEmojiMapping] = defaultdict(dict) - - async def __new__(cls, bot: discord.Bot) -> Self: - obj = super().__new__(cls) - obj.__init__(bot) - await obj.load() - return obj + self._loaded: bool = False async def load(self) -> None: - await self._bot.wait_until_ready() + """Load emojis from the Discord server. + + This method should be called after the bot is ready. + Typically called in your bot's on_ready event. + """ for emoji in self._bot.app_emojis: if emoji.name.startswith("pb_"): key: str = emoji.name.split("_")[1] part: ProgressBarPart = cast("ProgressBarPart", int(emoji.name.split("_")[2])) self._emojis[key][part] = emoji + self._loaded = True + + @property + def loaded(self) -> bool: + """Check if the manager has been loaded.""" + return self._loaded async def create_emojis_from_urls(self, name: str, emojis: ProgressBarUrlMapping) -> None: async with aiohttp.ClientSession() as session: @@ -107,9 +112,27 @@ class ProgressBarManager: self._emojis[name][key] = emoji async def progress_bar(self, name: str, *, length: int = 5) -> ProgressBar: + """Get a progress bar by name. + + Args: + name: The name of the progress bar. + length: The length of the progress bar (default is 5). + + Returns: + A ProgressBar instance with the specified emojis. + + Raises: + ValueError: If the progress bar is not found + RuntimeError: If the manager is not loaded. + + """ + if not self.loaded: + raise RuntimeError("ProgressBarManager has not been loaded yet. Call load() first.") + if name not in self._emojis: if default := DEFAULT_PROGRESS_BARS.get(name): await self.create_emojis_from_urls(name, default) else: raise ValueError(f"Progress bar {name} not found.") + return ProgressBar(self._emojis[name], length=length)