diff --git a/bot/config.py b/bot/config.py index 8af5d29e..89e36eda 100644 --- a/bot/config.py +++ b/bot/config.py @@ -78,11 +78,6 @@ class Tags(BaseModel): required_role_id: int # [lvl 30] Engineer -class Timathon(BaseModel): - channel_id: int - participant_role_id: int - - class Hastebin(BaseModel): base_url: str @@ -112,7 +107,6 @@ class Settings(BaseSettings): moderation: Moderation reaction_roles: ReactionRoles tags: Tags - timathon: Timathon hastebin: Hastebin errors: ErrorHandling custom_roles: CustomRoles diff --git a/bot/extensions/adventofcode/utils.py b/bot/extensions/adventofcode/utils.py index ef3921ea..49f449de 100644 --- a/bot/extensions/adventofcode/utils.py +++ b/bot/extensions/adventofcode/utils.py @@ -2,6 +2,7 @@ from typing import Optional, Union from zoneinfo import ZoneInfo +import aiohttp import discord from async_lru import alru_cache from pydantic import BaseModel, validator @@ -76,7 +77,7 @@ class Member(BaseModel): local_score: int @validator("name", pre=True) - def set_name_to_anonymous(cls, val: Optional[str]) -> str: + def check_username(cls, val: Optional[str]) -> str: if val is None: return "Anonymous User" return val @@ -88,11 +89,18 @@ async def fetch_leaderboard(local: bool = False) -> Union[str, dict]: if local: url += f"/private/view/{LEADERBOARD_ID}.json" - async with http.session.get(url, headers=AOC_REQUEST_HEADERS, raise_for_status=True) as resp: + async with http.session.get(url, headers=AOC_REQUEST_HEADERS) as resp: if resp.status == 200: if local: - response = await resp.json() + try: + response = await resp.json() + except aiohttp.ContentTypeError: + response = "Failed to get leaderboard data. Please check that the leaderboard code is correct." else: response = await resp.text() + elif resp.status == 500: + response = "Failed to get leaderboard data. Please check that the session cookie is correct." + else: + response = "Failed to get leaderboard data. Please check that all the env values are correct." return response diff --git a/bot/extensions/adventofcode/views.py b/bot/extensions/adventofcode/views.py index 13e7da4d..5d92caf9 100644 --- a/bot/extensions/adventofcode/views.py +++ b/bot/extensions/adventofcode/views.py @@ -22,17 +22,21 @@ async def home(self, interaction: core.InteractionType, _button: ui.Button): @discord.ui.button( label="Local Leaderboard", style=discord.ButtonStyle.gray, emoji="👥", custom_id=LOCAL_LEADERBOARD_CUSTOM_ID ) - async def local_leaderboard(self, interaction: core.InteractionType, button: ui.Button): + async def local_leaderboard(self, interaction: core.InteractionType, _button: ui.Button): leaderboard = await fetch_leaderboard(local=True) - members = [Member(**member_data) for member_data in leaderboard["members"].values()] - embed = discord.Embed( title=f"{interaction.guild.name} Advent of Code Leaderboard", colour=0x68C290, url=f"https://adventofcode.com/{YEAR}/leaderboard/private/view/{LEADERBOARD_ID}", ) + if isinstance(leaderboard, str): + embed.description = leaderboard + return await interaction.response.edit_message(embed=embed, view=self) + + members = [Member(**member_data) for member_data in leaderboard["members"].values()] + leaderboard = { "owner_id": leaderboard["owner_id"], "event": leaderboard["event"], @@ -53,9 +57,8 @@ async def local_leaderboard(self, interaction: core.InteractionType, button: ui. @discord.ui.button( label="Global Leaderboard", style=discord.ButtonStyle.gray, emoji="🌎", custom_id=GLOBAL_LEADERBOARD_CUSTOM_ID ) - async def global_leaderboard(self, interaction: core.InteractionType, button: ui.Button): + async def global_leaderboard(self, interaction: core.InteractionType, _button: ui.Button): raw_html = await fetch_leaderboard(local=False) - soup = BeautifulSoup(raw_html, "html.parser") embed = discord.Embed( title="Advent of Code Global Leaderboard", @@ -63,6 +66,11 @@ async def global_leaderboard(self, interaction: core.InteractionType, button: ui url=f"https://adventofcode.com/{YEAR}/leaderboard", ) + if raw_html.startswith("Failed to get leaderboard data."): + embed.description = raw_html + return await interaction.response.edit_message(embed=embed, view=self) + + soup = BeautifulSoup(raw_html, "html.parser") if soup.find("p").text == "Nothing to show on the leaderboard... yet.": embed.description = "The global leaderboard is not available yet. Please try again later." return await interaction.response.edit_message(embed=embed, view=self) diff --git a/bot/extensions/challenges/commands.py b/bot/extensions/challenges/commands.py index fdd05ba7..707a3242 100644 --- a/bot/extensions/challenges/commands.py +++ b/bot/extensions/challenges/commands.py @@ -75,10 +75,6 @@ def submit_channel(self) -> discord.TextChannel | None: def submissions_channel(self) -> discord.TextChannel | None: return self.bot.guild.get_channel(settings.challenges.submissions_channel_id) - @property - def games_channel(self) -> discord.TextChannel | None: - return self.bot.guild.get_channel(settings.bot.games_channel_id) - @app_commands.command() async def clear_winners(self, interaction: core.InteractionType): """Clears the winner role from all members that have it.""" @@ -150,7 +146,7 @@ async def announce(self, interaction: core.InteractionType): """Send an announcement in the info channel mentioning the winners.""" text = ( - f"{self.winner_role.mention} 🥞 have been given out, go deposit them in {self.games_channel.mention}." + f"{self.winner_role.mention} 🥞 have been given out, go deposit them in <#{settings.bot.games_channel_id}>." f"\nAnalysis for the challenge will be available shortly in {self.info_channel.mention}." ) await self.info_channel.send(text, allowed_mentions=discord.AllowedMentions(roles=[self.winner_role])) diff --git a/example.env b/example.env index 5c9adeb0..b165b9f5 100644 --- a/example.env +++ b/example.env @@ -1,34 +1,30 @@ # -------- Config # --- AoC -AOC__CHANNEL_ID=0 -AOC__ROLE_ID=0 -AOC__LEADERBOARD_CODE = 975452-d90a48b0 -AOC__SESSION_COOKIE=... +AOC__CHANNEL_ID= +AOC__ROLE_ID= +AOC__LEADERBOARD_CODE=975452-d90a48b0 +AOC__SESSION_COOKIE= # --- Bots - -# List[int] # [#bot-commands, #commands] (main bot-commands channel at index 0) -# Leave no sapce or use double quotes `"` e.g: "[0, 0]" -BOT__COMMANDS_CHANNELS_IDS=[0,0] -BOT__GAMES_CHANNEL_ID=0 +BOT__GAMES_CHANNEL_ID= BOT__TOKEN= # --- CHALLENGES -CHALLENGES__CHANNEL_ID=0 -CHALLENGES__DISCUSSION_CHANNEL_ID=0 -CHALLENGES__HOST_HELPER_ROLE_ID=0 -CHALLENGES__HOST_ROLE_ID=0 -CHALLENGES__INFO_CHANNEL_ID=0 -CHALLENGES__PARTICIPANT_ROLE_ID=0 -CHALLENGES__SUBMISSIONS_CHANNEL_ID=0 -CHALLENGES__SUBMITTED_ROLE_ID=0 -CHALLENGES__SUBMIT_CHANNEL_ID=0 -CHALLENGES__WINNER_ROLE_ID=0 +CHALLENGES__CHANNEL_ID= +CHALLENGES__DISCUSSION_CHANNEL_ID= +CHALLENGES__HOST_HELPER_ROLE_ID= +CHALLENGES__HOST_ROLE_ID= +CHALLENGES__INFO_CHANNEL_ID= +CHALLENGES__PARTICIPANT_ROLE_ID= +CHALLENGES__SUBMISSIONS_CHANNEL_ID= +CHALLENGES__SUBMITTED_ROLE_ID= +CHALLENGES__SUBMIT_CHANNEL_ID= +CHALLENGES__WINNER_ROLE_ID= # --- COC -COC__CHANNEL_ID=0 -COC__MESSAGE_ID=0 -COC__ROLE_ID=0 +COC__CHANNEL_ID= +COC__MESSAGE_ID= +COC__ROLE_ID= # --- Postgres POSTGRES__MAX_POOL_CONNECTIONS=10 @@ -37,7 +33,7 @@ POSTGRES__URI= # --- Guild GUILD__ID= -GUILD__WELCOMES_CHANNEL_ID=0 +GUILD__WELCOMES_CHANNEL_ID= # --- Moderation # List[int], # Leave no sapce or use double quotes `"` e.g: "[0, 0]" @@ -45,8 +41,8 @@ MODERATION__ADMIN_ROLES_IDS= MODERATION__STAFF_ROLE_ID= # --- Notification -NOTIFICATION__CHANNEL_ID=0 -NOTIFICATION__ROLE_ID=0 +NOTIFICATION__CHANNEL_ID= +NOTIFICATION__ROLE_ID= # --- Reaction Roles # Access to reaction roles @@ -57,19 +53,15 @@ REACTION_ROLES__ROLES={"0":0} REACTION_ROLES__MESSAGE_ID=0 # --- Tags -TAGS__LOG_CHANNEL_ID=0 +TAGS__LOG_CHANNEL_ID= # Access to tag commands -TAGS__REQUIRED_ROLE_ID=0 - -# --- Timathon -TIMATHON__CHANNEL_ID=0 -TIMATHON__PARTICIPANT_ROLE_ID=0 +TAGS__REQUIRED_ROLE_ID= # --- Custom Roles -CUSTOM_ROLES__LOG_CHANNEL_ID=0 -CUSTOM_ROLES__DIVIDER_ROLE_ID=0 +CUSTOM_ROLES__LOG_CHANNEL_ID= +CUSTOM_ROLES__DIVIDER_ROLE_ID= # --- Youtube YOUTUBE__CHANNEL_ID=UC4JX40jDee_tINbkjycV4Sg -YOUTUBE__TEXT_CHANNEL_ID=0 -YOUTUBE__ROLE_ID=0 +YOUTUBE__TEXT_CHANNEL_ID= +YOUTUBE__ROLE_ID=