Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update advent of code #286

Merged
merged 8 commits into from
Nov 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions bot/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -112,7 +107,6 @@ class Settings(BaseSettings):
moderation: Moderation
reaction_roles: ReactionRoles
tags: Tags
timathon: Timathon
hastebin: Hastebin
errors: ErrorHandling
custom_roles: CustomRoles
Expand Down
7 changes: 3 additions & 4 deletions bot/extensions/adventofcode/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,15 @@

from bot import core
from bot.extensions.adventofcode.utils import home_embed
from bot.extensions.adventofcode.views import CreateAdventOfCodeView
from bot.extensions.adventofcode.views import AdventOfCodeView


class AdventOfCode(commands.Cog):
def __init__(self, bot):
self.bot = bot
self._create_aoc_view = CreateAdventOfCodeView(timeout=None)
self.bot.add_view(self._create_aoc_view)
self.bot.add_view(AdventOfCodeView())

@app_commands.command(name="advent-of-code")
async def advent_of_code(self, interaction: core.InteractionType):
"""Returns information about the Advent of Code"""
await interaction.response.send_message(embed=home_embed(), ephemeral=True, view=self._create_aoc_view)
await interaction.response.send_message(embed=home_embed(), ephemeral=True, view=AdventOfCodeView())
18 changes: 12 additions & 6 deletions bot/extensions/adventofcode/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -88,11 +89,16 @@ 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:
return await resp.json()
except aiohttp.ContentTypeError:
return "Failed to get leaderboard data. Please check that the leaderboard code is correct."
else:
response = await resp.text()

return response
return await resp.text()
elif resp.status == 500:
return "Failed to get leaderboard data. Please check that the session cookie is correct."
else:
return "Failed to get leaderboard data. Please check that all the env values are correct."
28 changes: 22 additions & 6 deletions bot/extensions/adventofcode/views.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
import re
import typing as t
from datetime import datetime
from zoneinfo import ZoneInfo

import discord
from bs4 import BeautifulSoup
from discord import ui
from discord.ui import Item

from bot import core
from bot.extensions.adventofcode.utils import LEADERBOARD_ID, YEAR, Member, fetch_leaderboard, home_embed, ordinal


class CreateAdventOfCodeView(ui.View):
class AdventOfCodeView(ui.View):
def __init__(self):
super().__init__(timeout=None)

HOME_CUSTOM_ID = "extensions:adventofcode:home"
LOCAL_LEADERBOARD_CUSTOM_ID = "extensions:adventofcode:local"
GLOBAL_LEADERBOARD_CUSTOM_ID = "extensions:adventofcode:global"
Expand All @@ -22,17 +27,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"],
Expand All @@ -53,16 +62,20 @@ 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",
colour=0x68C290,
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)
Expand Down Expand Up @@ -98,3 +111,6 @@ async def global_leaderboard(self, interaction: core.InteractionType, button: ui
embed.description = s_desc

await interaction.response.edit_message(embed=embed, view=self)

async def on_error(self, interaction: core.InteractionType, _error: Exception, _item: Item[t.Any], /) -> None:
await interaction.client.on_error("adventofcode_view")
6 changes: 1 addition & 5 deletions bot/extensions/challenges/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -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."""
Expand Down Expand Up @@ -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]))
Expand Down
6 changes: 2 additions & 4 deletions bot/extensions/polls/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@
class Polls(commands.GroupCog, group_name="poll"):
def __init__(self, bot: core.DiscordBot):
self.bot = bot

self._create_poll_view = CreatePollView(timeout=None)
self.bot.add_view(self._create_poll_view)
self.bot.add_view(CreatePollView())

@app_commands.command()
@app_commands.describe(question="Your question")
Expand All @@ -26,7 +24,7 @@ async def new(self, interaction: core.InteractionType, question: str):
color=discord.colour.Color.gold(),
)
embed.set_footer(text=f"Poll by {interaction.user.display_name}")
await interaction.response.send_message(embed=embed, ephemeral=True, view=self._create_poll_view)
await interaction.response.send_message(embed=embed, ephemeral=True, view=CreatePollView())

@app_commands.command()
async def show(
Expand Down
8 changes: 7 additions & 1 deletion bot/extensions/polls/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ async def on_submit(self, interaction: discord.Interaction) -> None:

embed.add_field(name=f"{str(emojis[field_count])} {self.name}", value=self.description, inline=False)
field_count += 1
view = CreatePollView()

view = CreatePollView()
add_choice_btn = discord.utils.get(view.children, custom_id=CreatePollView.ADD_CUSTOM_ID)
create_poll_btn = discord.utils.get(view.children, custom_id=CreatePollView.CREATE_CUSTOM_ID)
delete_select = discord.utils.find(lambda child: isinstance(child, discord.ui.Select), view.children)
Expand Down Expand Up @@ -82,6 +82,9 @@ async def callback(self, interaction: core.InteractionType):


class CreatePollView(ui.View):
def __init__(self):
super().__init__(timeout=None)

ADD_CUSTOM_ID = "extensions:polls:add"
DELETE_CUSTOM_ID = "extensions:polls:delete"
CREATE_CUSTOM_ID = "extensions:polls:create"
Expand Down Expand Up @@ -115,3 +118,6 @@ async def create_poll(self, interaction: core.InteractionType, _button: ui.Butto

for i in range(0, len(embed.fields)):
await message.add_reaction(emojis[i])

async def on_error(self, interaction: core.InteractionType, _error: Exception, _item: ui.Item[t.Any], /) -> None:
await interaction.client.on_error("poll_view")
62 changes: 27 additions & 35 deletions example.env
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -37,16 +33,16 @@ 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]"
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
Expand All @@ -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=
Loading