Skip to content

Commit

Permalink
use discord embeds and truncate by default
Browse files Browse the repository at this point in the history
  • Loading branch information
katrinafyi committed Nov 30, 2024
1 parent 4c75618 commit 40fb182
Showing 1 changed file with 108 additions and 32 deletions.
140 changes: 108 additions & 32 deletions uqcsbot/advent.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import os
from datetime import datetime
from random import choices
from typing import Callable, Dict, Iterable, List, Optional, Literal
from typing import Any, Callable, Dict, Iterable, List, Optional, Literal
import requests
from requests.exceptions import RequestException

Expand All @@ -20,6 +20,7 @@
InvalidHTTPSCode,
ADVENT_DAYS,
CACHE_TIME,
HL_COLOUR,
parse_leaderboard_column_string,
print_leaderboard,
render_leaderboard_to_image,
Expand Down Expand Up @@ -137,6 +138,109 @@
}


class LeaderboardView(discord.ui.View):
INITIAL_VISIBLE_ROWS = 20

def __init__(
self,
bot: UQCSBot,
code: int,
year: int,
day: Optional[Day],
members: list[Member],
leaderboard_style: str,
sortby: Optional[SortingMethod],
):
super().__init__(timeout=300)
# constant within one embed
self.bot = bot
self.code = code
self.year = year
self.day = day
self.all_members = members
self.leaderboard_style = leaderboard_style
self.sortby = sortby
self.timestamp = datetime.now()

# can be changed by interaction
self.visible_members = members[: self.INITIAL_VISIBLE_ROWS]
self.show_text = False

@property
def is_truncated(self):
return len(self.visible_members) < len(self.all_members)

def make_message_arguments(self) -> Dict[str, Any]:
view_url = LEADERBOARD_VIEW_URL.format(year=self.year, code=self.code)

leaderboard = print_leaderboard(
parse_leaderboard_column_string(self.leaderboard_style, self.bot),
self.visible_members,
self.day,
)

title = (
"Advent of Code UQCS Leaderboard"
if self.code == UQCS_LEADERBOARD
else f"Advent of Code Leaderboard `{self.code}`"
)
title = f":star: {title} :trophy:"
if self.day:
title += f" \u2014 Day {self.day}"

notes: List[str] = []
if self.day:
notes.append(f"sorted by {self.sortby}")
if self.is_truncated:
notes.append(f"top {len(self.visible_members)} shown")
body = f"({", ".join(notes)})" if notes else ""

basename = f"advent_{self.code}_{self.year}_{self.day}"

embed = discord.Embed(
title=title,
url=view_url,
description=body,
colour=discord.Colour.from_str(HL_COLOUR),
timestamp=self.timestamp,
)

if not self.show_text:
scoreboard_image = render_leaderboard_to_image(leaderboard)
file = discord.File(io.BytesIO(scoreboard_image), basename + ".png")
embed.set_image(url=f"attachment://{file.filename}")
else:
scoreboard_text = render_leaderboard_to_text(leaderboard)
file = discord.File(
io.BytesIO(scoreboard_text.encode("utf-8")), basename + ".txt"
)

self.show_all_interaction.disabled = not self.is_truncated
self.get_text_interaction.label = (
"Show as image" if self.show_text else "Show as text"
)

return {
"attachments": [file],
"embed": embed,
"view": self,
}

@discord.ui.button(label="Show all", style=discord.ButtonStyle.gray)
async def show_all_interaction(
self, inter: discord.Interaction, btn: discord.ui.Button["LeaderboardView"]
):
self.visible_members = self.all_members
await inter.response.edit_message(**self.make_message_arguments())

@discord.ui.button(label="Show text", style=discord.ButtonStyle.gray)
async def get_text_interaction(
self, inter: discord.Interaction, btn: discord.ui.Button["LeaderboardView"]
):
self.show_text = not self.show_text
await inter.response.edit_message(**self.make_message_arguments())


class Advent(commands.Cog):
"""
All of the commands related to Advent of Code (AOC).
Expand Down Expand Up @@ -505,13 +609,7 @@ async def leaderboard_command(
)
return

if code == UQCS_LEADERBOARD:
message = ":star: *Advent of Code UQCS Leaderboard* :trophy:"
else:
message = f":star: *Advent of Code Leaderboard {code}* :trophy:"

if day:
message += f"\n:calendar: *Day {day}* (Sorted By {sortby})"
members = [member for member in members if member.attempted_day(day)]
members.sort(key=lambda m: sorting_functions_for_day[sortby](m, day))
else:
Expand All @@ -522,38 +620,16 @@ async def leaderboard_command(
]
members.sort(key=sorting_functions_for_month[sortby])

view_url = LEADERBOARD_VIEW_URL.format(year=year, code=code)
message += f"\n{view_url}"

if not members:
await interaction.edit_original_response(
content="This leaderboard contains no people."
)
return

leaderboard = print_leaderboard(
parse_leaderboard_column_string(leaderboard_style, self.bot),
members,
day,
)

scoreboard_text = render_leaderboard_to_text(leaderboard)
scoreboard_image = render_leaderboard_to_image(leaderboard)
basename = f"advent_{code}_{year}_{day}"

await interaction.edit_original_response(
content=message,
attachments=[
discord.File(
io.BytesIO(scoreboard_text.encode("utf-8")),
filename=f"{basename}.txt",
),
discord.File(
io.BytesIO(scoreboard_image),
filename=f"{basename}.png",
),
],
view = LeaderboardView(
self.bot, code, year, day, members, leaderboard_style, sortby
)
await interaction.edit_original_response(**view.make_message_arguments())

@advent_command_group.command(name="register")
@app_commands.describe(
Expand Down

0 comments on commit 40fb182

Please sign in to comment.