From 34cbd15ba9c3427ba85e633444369ef7dd91ee23 Mon Sep 17 00:00:00 2001 From: Jakub Kuczys Date: Fri, 6 Mar 2026 01:51:22 +0100 Subject: [PATCH] Stop waiting for update check on bot startup (#6687) --- redbot/core/_events.py | 36 ++++++++++++++++++---------- redbot/core/core_commands.py | 6 ++++- redbot/core/utils/_internal_utils.py | 33 ++++++++++++++++--------- 3 files changed, 51 insertions(+), 24 deletions(-) diff --git a/redbot/core/_events.py b/redbot/core/_events.py index ae2830699..2ee86e9bd 100644 --- a/redbot/core/_events.py +++ b/redbot/core/_events.py @@ -176,14 +176,15 @@ def init_events(bot, cli_flags): if bot.intents.members: # Lets avoid 0 Unique Users table_counts.add_row("Unique Users", str(users)) - outdated_red_message = "" - rich_outdated_message = "" - pypi_version, py_version_req = await fetch_latest_red_version_info() - outdated = pypi_version and pypi_version > red_version_info - if outdated: - outdated_red_message, rich_outdated_message = get_outdated_red_messages( - pypi_version, py_version_req - ) + fetch_version_task = asyncio.create_task(fetch_latest_red_version_info()) + log.info("Fetching information about latest Red version...") + try: + await asyncio.wait_for(asyncio.shield(fetch_version_task), timeout=5) + except asyncio.TimeoutError: + log.info("Version information will continue to be fetched in the background...") + except Exception: + # these will be logged later + pass rich_console = rich.get_console() rich_console.print(INTRO, style="red", markup=False, highlight=False) @@ -209,12 +210,23 @@ def init_events(bot, cli_flags): rich_console.print( f"Looking for a quick guide on setting up Red? Checkout {Text('https://start.discord.red', style='link https://start.discord.red}')}" ) - if rich_outdated_message: - rich_console.print(rich_outdated_message) bot._red_ready.set() - if outdated_red_message: - await send_to_owners_with_prefix_replaced(bot, outdated_red_message) + + try: + pypi_version, py_version_req = await fetch_version_task + except (aiohttp.ClientError, asyncio.TimeoutError) as exc: + log.error("Failed to fetch latest version information from PyPI.", exc_info=exc) + except (KeyError, ValueError) as exc: + log.error("Failed to parse version metadata received from PyPI.", exc_info=exc) + else: + outdated = pypi_version and pypi_version > red_version_info + if outdated: + outdated_red_message, rich_outdated_message = get_outdated_red_messages( + pypi_version, py_version_req + ) + rich_console.print(rich_outdated_message) + await send_to_owners_with_prefix_replaced(bot, outdated_red_message) @bot.event async def on_command_completion(ctx: commands.Context): diff --git a/redbot/core/core_commands.py b/redbot/core/core_commands.py index 854b2e1ff..f8525e0a4 100644 --- a/redbot/core/core_commands.py +++ b/redbot/core/core_commands.py @@ -424,7 +424,11 @@ class Core(commands.commands._RuleDropper, commands.Cog, CoreLogic): owner = app_info.owner custom_info = await self.bot._config.custom_info() - pypi_version, py_version_req = await fetch_latest_red_version_info() + try: + pypi_version, __ = await fetch_latest_red_version_info() + except (aiohttp.ClientError, TimeoutError) as exc: + log.error("Failed to fetch latest version information from PyPI.", exc_info=exc) + pypi_version = None outdated = pypi_version and pypi_version > red_version_info if embed_links: diff --git a/redbot/core/utils/_internal_utils.py b/redbot/core/utils/_internal_utils.py index 088136203..a8a49ec72 100644 --- a/redbot/core/utils/_internal_utils.py +++ b/redbot/core/utils/_internal_utils.py @@ -326,18 +326,29 @@ def expected_version(current: str, expected: str) -> bool: return Requirement(f"x{expected}").specifier.contains(current, prereleases=True) -async def fetch_latest_red_version_info() -> Tuple[Optional[VersionInfo], Optional[str]]: - try: - async with aiohttp.ClientSession() as session: - async with session.get("https://pypi.org/pypi/Red-DiscordBot/json") as r: - data = await r.json() - except (aiohttp.ClientError, asyncio.TimeoutError): - return None, None - else: - release = VersionInfo.from_str(data["info"]["version"]) - required_python = data["info"]["requires_python"] +async def fetch_latest_red_version_info() -> Tuple[VersionInfo, Optional[str]]: + """ + Fetch information about latest Red release on PyPI. - return release, required_python + Raises + ------ + aiohttp.ClientError + An error occurred during request to PyPI. + TimeoutError + The request to PyPI timed out. + ValueError + An invalid version string was returned in PyPI metadata. + KeyError + The PyPI metadata is missing some of the required information. + """ + async with aiohttp.ClientSession() as session: + async with session.get("https://pypi.org/pypi/Red-DiscordBot/json") as r: + data = await r.json() + + release = VersionInfo.from_str(data["info"]["version"]) + required_python = data["info"]["requires_python"] + + return release, required_python def deprecated_removed(