From ecbf84b817575042a6043d4f0e71518762bd3a69 Mon Sep 17 00:00:00 2001 From: Luke Schmitt <45839909+LukeSchmitt96@users.noreply.github.com> Date: Sun, 10 Sep 2023 22:27:10 -0500 Subject: [PATCH] Add unique films command Closes #37. --- .gitignore | 1 + movie_bet_bot/models/client/client.py | 9 ++++- movie_bet_bot/models/commands/__init__.py | 3 +- movie_bet_bot/models/commands/commands.py | 41 +++++++++++++++++++++++ movie_bet_bot/models/movies/movies.py | 32 +++++++++++++++++- movie_bet_bot/utils/images.py | 35 +++++++++++++++++-- 6 files changed, 116 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 7e25222..9c7b024 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ db.yaml update_image.png avg_watchtimes.png +unique_films.png data/ # Byte-compiled / optimized / DLL files diff --git a/movie_bet_bot/models/client/client.py b/movie_bet_bot/models/client/client.py index 8e5bcce..12418a6 100644 --- a/movie_bet_bot/models/client/client.py +++ b/movie_bet_bot/models/client/client.py @@ -3,7 +3,12 @@ import discord from apscheduler.schedulers.asyncio import AsyncIOScheduler -from movie_bet_bot.models.commands import create_average_watchtimes, create_help, create_standings +from movie_bet_bot.models.commands import ( + create_average_watchtimes, + create_help, + create_standings, + create_unique_films, +) from movie_bet_bot.models.movies import movies from movie_bet_bot.utils import constants from movie_bet_bot.utils.images import html_to_image @@ -103,6 +108,8 @@ def create_commands(self) -> None: create_standings(self) # create standings command create_average_watchtimes(self) + # create unique films command + create_unique_films(self) def add_command(self, name: str, description: str) -> None: """Add a command to the list of commands. diff --git a/movie_bet_bot/models/commands/__init__.py b/movie_bet_bot/models/commands/__init__.py index fe71747..c06df57 100644 --- a/movie_bet_bot/models/commands/__init__.py +++ b/movie_bet_bot/models/commands/__init__.py @@ -1,7 +1,8 @@ -from .commands import create_average_watchtimes, create_help, create_standings +from .commands import create_average_watchtimes, create_help, create_standings, create_unique_films __all__ = [ "create_average_watchtimes", "create_help", "create_standings", + "create_unique_films", ] diff --git a/movie_bet_bot/models/commands/commands.py b/movie_bet_bot/models/commands/commands.py index ea00ea6..53d03d7 100644 --- a/movie_bet_bot/models/commands/commands.py +++ b/movie_bet_bot/models/commands/commands.py @@ -120,3 +120,44 @@ async def average_watchtimes( # add a command to the list of commands bot.add_command(name, description) + + +def create_unique_films(bot): + """ + Create the unique films command. + + :param bot: client.MovieBetBot to add unique films command to + """ + + # name of the unique films command + name = "unique_films" + + # description of the average watchtime command + description = "Get the number of unique films for each member." + + @bot.command_tree.command(name=name, description=description) + async def unique_films( + interaction: discord.Interaction, + ): + """Do unique films command callback""" + print("Running Unique Films Command") + await interaction.response.defer() + error: bool = True + if bot.contest is not None: + # get the image of the unique films + (image_html, image_size) = bot.contest.to_unique_films_image_html() + # create a new discord.File from html_to_image-provided filepath + file = discord.File( + html_to_image(html=image_html, out="unique_films.png", size=image_size) + ) + if file is not None: + # sends the file + print("Sending Unique Films File") + error = False + await interaction.followup.send(file=file) + if error: + print("Could not get unique films") + await interaction.followup.send("Could not get unique films") + + # add a command to the list of commands + bot.add_command(name, description) diff --git a/movie_bet_bot/models/movies/movies.py b/movie_bet_bot/models/movies/movies.py index 67277ce..ae08f7c 100644 --- a/movie_bet_bot/models/movies/movies.py +++ b/movie_bet_bot/models/movies/movies.py @@ -561,7 +561,6 @@ def to_avg_watchtimes_image_html(self) -> Tuple[str, Tuple[int, int]]: html_members = "" # html str w/ all member's films watched since last update for member in self.members: - print(f"Generating image component for member '{member.name}'.") html_member = images.build_html_avg_watchtime_block_from_member( member=member, ) @@ -570,3 +569,34 @@ def to_avg_watchtimes_image_html(self) -> Tuple[str, Tuple[int, int]]: members=html_members, ) return (image_html, (480, html_height)) + + def to_unique_films_image_html(self) -> Tuple[str, Tuple[int, int]]: + + """ + Create image from unique films. + + :return: tuple where the first element is a string containing the raw html used to generate + an image and the second element is a tuple containing the size of the image + """ + print("Generating unique films image of this contest.") + # height of created image + html_height = constants.IMAGE_BASE_HEIGHT + # html str w/ current scores, num of films watched since last update + html_members = "" + # html str w/ all member's films watched since last update + for member in self.members: + unique_films = set() + other_films = set() + for other_member in self.members: + if member is other_member: + continue + other_films.update(other_member.filmlist.films) + unique_films = member.filmlist.films.difference(other_films) + print(len(unique_films)) + html_member = images.build_html_unique_films_block_from_member( + member=member, + num_unique_films=len(unique_films), + ) + html_members += html_member + image_html = images.build_html_unique_films_block(members=html_members) + return (image_html, (480, html_height)) diff --git a/movie_bet_bot/utils/images.py b/movie_bet_bot/utils/images.py index 03cf55d..a7e6587 100644 --- a/movie_bet_bot/utils/images.py +++ b/movie_bet_bot/utils/images.py @@ -134,10 +134,9 @@ def build_html_avg_watchtimes_block( updates_head_class="hidden", updates_head="", updates_class="hidden", - title_class="hidden", + title_class="", members_class="", hr_class="hidden", - time="", ) @@ -154,3 +153,35 @@ def build_html_avg_watchtime_block_from_member(member: movies.Member) -> str: films_since_last_update="", ) return html_member + + +def build_html_unique_films_block_from_member(member: movies.Member, num_unique_films: int) -> str: + # html str w/ current score, num of films watched since last update + html_member = "" + # format member section of standings template to add member + html_member += build_html_standings_member_block( + place=map_place(member.place), + name=member.name, + num_films_watched=num_unique_films, + hours_class="", + hours_watched="", + films_since_last_update="", + ) + return html_member + + +def build_html_unique_films_block( + members: str, +): + return constants.HTML_STANDINGS_TEMPLATE.format( + head=constants.HTML_HEAD, + title="Unique Films", + members=members, + updates="", + updates_head_class="hidden", + updates_head="", + updates_class="hidden", + title_class="", + members_class="", + hr_class="hidden", + )