diff options
author | 2023-08-23 10:34:26 +0100 | |
---|---|---|
committer | 2023-08-23 10:34:26 +0100 | |
commit | 1817b2d41b2b0f1a178055f1bc640f2bc06957c9 (patch) | |
tree | 1fb65b1dd1c8185bab4874dfc8fe5e272f20de3d | |
parent | Corrected attribute name to fetch github url in extensions.py (#1348) (diff) | |
parent | Merge branch 'main' into snakes-cleanup (diff) |
Merge pull request #1323 from python-discord/snakes-cleanup
Snakes cleanup
-rw-r--r-- | bot/exts/fun/snakes/_snakes_cog.py | 32 | ||||
-rw-r--r-- | bot/utils/__init__.py | 51 | ||||
-rw-r--r-- | bot/utils/pagination.py | 4 |
3 files changed, 38 insertions, 49 deletions
diff --git a/bot/exts/fun/snakes/_snakes_cog.py b/bot/exts/fun/snakes/_snakes_cog.py index 05ab7bfd..82496629 100644 --- a/bot/exts/fun/snakes/_snakes_cog.py +++ b/bot/exts/fun/snakes/_snakes_cog.py @@ -11,8 +11,8 @@ from functools import partial from io import BytesIO from typing import Any -import async_timeout from PIL import Image, ImageDraw, ImageFont +from aiohttp import ClientTimeout from discord import Colour, Embed, File, Member, Message, Reaction from discord.errors import HTTPException from discord.ext.commands import Cog, CommandError, Context, bot_has_permissions, group @@ -241,8 +241,11 @@ class Snakes(Cog): # Draw the text onto the final image draw = ImageDraw.Draw(full_image) for line in textwrap.wrap(description, 36): - draw.text([margin + 4, offset], line, font=CARD["font"]) - offset += CARD["font"].getsize(line)[1] + draw.text((margin + 4, offset), line, font=CARD["font"]) + + _left, top, _right, bottom = CARD["font"].getbbox(line) + # Height of the text + 4px spacing + offset += bottom - top + 4 # Get the image contents as a BufferIO object buffer = BytesIO() @@ -279,8 +282,8 @@ class Snakes(Cog): if params is None: params = {} - async with async_timeout.timeout(10), self.bot.http_session.get(url, params=params) as response: - return await response.json() + async with self.bot.http_session.get(url, params=params, timeout=ClientTimeout(total=10)) as response: + return await response.json() def _get_random_long_message(self, messages: list[str], retries: int = 10) -> str: """ @@ -986,21 +989,28 @@ class Snakes(Cog): """ # Get the snake data we need if not name: - name_obj = await self._get_snake_name() - name = name_obj["scientific"] - content = await self._get_snek(name) + for _ in range(3): + name_obj = await self._get_snake_name() + name = name_obj["scientific"] + content = await self._get_snek(name) + if len(content["image_list"]) > 0: + break elif isinstance(name, dict): content = name - else: content = await self._get_snek(name) + try: + image_url = content["image_list"][0] + except IndexError: + await ctx.send("No images found for this snake.") + return + # Make the card async with ctx.typing(): - stream = BytesIO() - async with async_timeout.timeout(10), self.bot.http_session.get(content["image_list"][0]) as response: + async with self.bot.http_session.get(image_url, timeout=ClientTimeout(total=10)) as response: stream.write(await response.read()) stream.seek(0) diff --git a/bot/utils/__init__.py b/bot/utils/__init__.py index 2a4acd96..f1ae0e75 100644 --- a/bot/utils/__init__.py +++ b/bot/utils/__init__.py @@ -7,6 +7,7 @@ from datetime import UTC, datetime import discord from discord.ext.commands import BadArgument, Context +from pydis_core.utils.scheduling import create_task from bot.constants import Client, Month from bot.utils.pagination import LinePaginator @@ -55,52 +56,30 @@ async def disambiguate( choices = (f"{index}: {entry}" for index, entry in enumerate(entries, start=1)) def check(message: discord.Message) -> bool: - return ( - message.content.isdecimal() - and message.author == ctx.author - and message.channel == ctx.channel - ) + return message.author == ctx.author and message.channel == ctx.channel - try: - if embed is None: - embed = discord.Embed() + if embed is None: + embed = discord.Embed() - coro1 = ctx.bot.wait_for("message", check=check, timeout=timeout) - coro2 = LinePaginator.paginate( + # Run the paginator in the background, this means it will continue to work after the user has + # selected an option, and stopping it wont prevent the user from selecting an option, both + # of which are fine and make implementation simpler. + create_task( + LinePaginator.paginate( choices, ctx, embed=embed, max_lines=entries_per_page, - empty=empty, max_size=6000, timeout=9000 + empty=empty, max_size=6000, timeout=timeout ) + ) - # wait_for timeout will go to except instead of the wait_for thing as I expected - futures = [asyncio.ensure_future(coro1), asyncio.ensure_future(coro2)] - done, pending = await asyncio.wait(futures, return_when=asyncio.FIRST_COMPLETED, loop=ctx.bot.loop) - - # :yert: - result = next(iter(done)).result() - - # Pagination was canceled - result is None - if result is None: - for coro in pending: - coro.cancel() - raise BadArgument("Canceled.") - - # Pagination was not initiated, only one page - if result.author == ctx.bot.user: - # Continue the wait_for - result = await next(iter(pending)) - - # Love that duplicate code - for coro in pending: - coro.cancel() + try: + message = await ctx.bot.wait_for("message", check=check, timeout=timeout) except asyncio.TimeoutError: raise BadArgument("Timed out.") - # Guaranteed to not error because of isdecimal() in check - index = int(result.content) - try: + index = int(message.content) return entries[index - 1] - except IndexError: + except (ValueError, IndexError): raise BadArgument("Invalid choice.") diff --git a/bot/utils/pagination.py b/bot/utils/pagination.py index c6cd7d12..58115fd6 100644 --- a/bot/utils/pagination.py +++ b/bot/utils/pagination.py @@ -90,7 +90,7 @@ class LinePaginator(Paginator): cls, lines: Iterable[str], ctx: Context, embed: Embed, prefix: str = "", suffix: str = "", max_lines: int | None = None, max_size: int = 500, empty: bool = True, - restrict_to_user: User = None, timeout: int = 300, footer_text: str | None = None, + restrict_to_user: User = None, timeout: float = 300, footer_text: str | None = None, url: str | None = None, exception_on_empty_embed: bool = False ) -> None: """ @@ -308,7 +308,7 @@ class ImagePaginator(Paginator): @classmethod async def paginate(cls, pages: list[tuple[str, str]], ctx: Context, embed: Embed, - prefix: str = "", suffix: str = "", timeout: int = 300, + prefix: str = "", suffix: str = "", timeout: float = 300, exception_on_empty_embed: bool = False) -> None: """ Use a paginator and set of reactions to provide pagination over a set of title/image pairs. |