From 169d4cfdd3f6fef330fa79aab76947393de42eca Mon Sep 17 00:00:00 2001 From: Zeroquinc Date: Tue, 21 May 2024 21:17:39 +0200 Subject: [PATCH] feature: make toggle for more compact embeds --- config/config_example.py | 1 + src/discord.py | 11 +++++++++++ src/trophies.py | 31 +++++++++++++++++-------------- utils/datetime.py | 2 +- utils/image.py | 33 +++++++-------------------------- 5 files changed, 37 insertions(+), 41 deletions(-) diff --git a/config/config_example.py b/config/config_example.py index e1db8d2..87e443d 100644 --- a/config/config_example.py +++ b/config/config_example.py @@ -4,6 +4,7 @@ TROPHIES_CHANNEL_ID = '' PLATINUM_CHANNEL_ID = '' TROPHIES_INTERVAL = 60 +COMPACT_EMBED = True # The delay before starting the tasks, useful for debugging, otherwise it will start within the first 15th minute TASK_START_DELAY = { diff --git a/src/discord.py b/src/discord.py index 72ce68b..5e0c738 100644 --- a/src/discord.py +++ b/src/discord.py @@ -25,6 +25,17 @@ async def create_trophy_embed(trophy, trophy_title_info, client, current, total_ embed.set_author(name="A Trophy Unlocked", icon_url=trophy_title.title_icon_url) return embed +async def create_simple_trophy_embed(trophy, trophy_title_info, client, current, total_trophies): + trophy_title = trophy_title_info['trophy_title'] + game_url = format_title(trophy_title.title_name) # format the title name into a URL + most_common_color = await get_discord_color(trophy.trophy_icon_url) + completion = current + percentage = (completion / total_trophies) * 100 + embed = discord.Embed(description=f"**{trophy.trophy_name} {replace_trophy_with_emoji(trophy.trophy_type.name.lower())} {trophy.trophy_earn_rate}%**\n{trophy.trophy_detail}\n\n[{trophy_title.title_name}]({game_url})", color=most_common_color) + embed.set_thumbnail(url=trophy.trophy_icon_url) + embed.set_footer(text=f"{format_date(trophy.earned_date_time)} • {completion}/{total_trophies} ({percentage:.2f}%)", icon_url=client.profile_picture_url) + return embed + async def create_platinum_embed(trophy, trophy_title_info, client, formatted_time_diff): trophy_title = trophy_title_info['trophy_title'] game_url = format_title(trophy_title.title_name) # format the title name into a URL diff --git a/src/trophies.py b/src/trophies.py index dc3a5ad..43f9868 100644 --- a/src/trophies.py +++ b/src/trophies.py @@ -1,21 +1,28 @@ from datetime import timedelta from psnawp_api import PSNAWP -from src.discord import create_trophy_embed, create_platinum_embed, send_trophy_embeds, send_platinum_embeds +from src.discord import create_trophy_embed, create_simple_trophy_embed, create_platinum_embed, send_trophy_embeds, send_platinum_embeds from utils.datetime import calculate_total_time, get_current_time -from config.config import PSNTOKEN, TROPHIES_INTERVAL +from config.config import PSNTOKEN, TROPHIES_INTERVAL, COMPACT_EMBED from utils.custom_logger import logger psnawp = PSNAWP(PSNTOKEN) +profile_picture = {} def get_client(): client = psnawp.me() - logger.info(f"Calling Sony API for profile information for user {client.online_id}") - profile_legacy = client.get_profile_legacy() - profile_picture_url = profile_legacy['profile']['personalDetail']['profilePictureUrls'][0]['profilePictureUrl'] - client.profile_picture_url = profile_picture_url + online_id = client.online_id + if online_id in profile_picture: + client.profile_picture_url = profile_picture[online_id] + logger.info(f"Loaded profile picture from cache for user {online_id}") + else: + logger.info(f"Calling Sony API for profile information for user {online_id}") + profile_legacy = client.get_profile_legacy() + profile_picture_url = profile_legacy['profile']['personalDetail']['profilePictureUrls'][0]['profilePictureUrl'] + client.profile_picture_url = profile_picture_url + profile_picture[online_id] = profile_picture_url return client def get_recent_titles(client, hours=24): @@ -62,23 +69,19 @@ async def get_earned_and_recent_trophies(client, title_id, platform, TROPHIES_IN async def create_trophy_and_platinum_embeds(client, earned_trophies, recent_trophies, total_trophies): trophy_embeds = [] platinum_embeds = [] - # Calculate total trophies earned (after filtering) total_trophies_earned = len(earned_trophies) - # Calculate the starting count starting_count = total_trophies_earned - len(recent_trophies) for i, (trophy, trophy_title) in enumerate(recent_trophies): - # Pass total_trophies to create_trophy_embed function - embed = await create_trophy_embed(trophy, trophy_title, client, starting_count + i + 1, total_trophies) + if COMPACT_EMBED: + embed = await create_simple_trophy_embed(trophy, trophy_title, client, starting_count + i + 1, total_trophies) + else: + embed = await create_trophy_embed(trophy, trophy_title, client, starting_count + i + 1, total_trophies) trophy_embeds.append((trophy.earned_date_time, embed)) if trophy.trophy_type.name.lower() == 'platinum': - # Get the oldest and newest trophy oldest_trophy = earned_trophies[0] newest_trophy = earned_trophies[-1] - # Calculate the time difference time_diff = newest_trophy[0].earned_date_time - oldest_trophy[0].earned_date_time - # Format the time difference formatted_time_diff = calculate_total_time(time_diff) - # Pass formatted_time_diff to create_platinum_embed function embed = await create_platinum_embed(trophy, trophy_title, client, formatted_time_diff) platinum_embeds.append((trophy.earned_date_time, embed)) return trophy_embeds, platinum_embeds diff --git a/utils/datetime.py b/utils/datetime.py index 975b649..ebbddf3 100644 --- a/utils/datetime.py +++ b/utils/datetime.py @@ -88,4 +88,4 @@ def format_date(date: datetime) -> str: """ amsterdam_tz = pytz.timezone('Europe/Amsterdam') date = date.astimezone(amsterdam_tz) - return date.strftime("%d/%m/%y at %H:%M:%S") \ No newline at end of file + return date.strftime("%d/%m/%y %H:%M:%S") \ No newline at end of file diff --git a/utils/image.py b/utils/image.py index 6c51f33..13d917d 100644 --- a/utils/image.py +++ b/utils/image.py @@ -2,31 +2,24 @@ import requests from io import BytesIO import numpy as np -from sklearn.cluster import KMeans import asyncio -def is_colorful(color, tolerance=20, saturation_threshold=50): +def is_colorful(color): r, g, b = color - saturation = np.std([r, g, b]) - return ( - saturation > saturation_threshold and - (abs(r - g) >= tolerance or abs(r - b) >= tolerance or abs(g - b) >= tolerance) - ) + return np.std([r, g, b]) -async def get_discord_color(image_url, num_colors=10, crop_percentage=0.5): +async def get_discord_color(image_url, crop_percentage=0.5): loop = asyncio.get_event_loop() return await loop.run_in_executor( None, get_discord_color_blocking, image_url, - num_colors, crop_percentage, ) -def get_discord_color_blocking(image_url, num_colors=10, crop_percentage=0.5): +def get_discord_color_blocking(image_url, crop_percentage=0.5): response = requests.get(image_url) img = Image.open(BytesIO(response.content)) - width, height = img.size crop_width = int(width * crop_percentage) crop_height = int(height * crop_percentage) @@ -34,22 +27,10 @@ def get_discord_color_blocking(image_url, num_colors=10, crop_percentage=0.5): top = (height - crop_height) // 2 right = left + crop_width bottom = top + crop_height - img = img.crop((left, top, right, bottom)) - - img = img.resize((img.width // 2, img.height // 2)) - img = img.convert("RGB") - img_array = np.array(img) img_flattened = img_array.reshape(-1, 3) - - kmeans = KMeans(n_clusters=num_colors) - kmeans.fit(img_flattened) - - counts = np.bincount(kmeans.labels_) - sorted_colors = sorted([(count, color) for count, color in zip(counts, kmeans.cluster_centers_) if is_colorful(color)], reverse=True) - - dominant_color = sorted_colors[0][1] if len(sorted_colors) != 0 else kmeans.cluster_centers_[np.argmax(counts)] - - return int('0x{:02x}{:02x}{:02x}'.format(*dominant_color.astype(int)), 16) \ No newline at end of file + colorfulness = np.apply_along_axis(is_colorful, 1, img_flattened) + most_colorful_color = img_flattened[np.argmax(colorfulness)] + return int('0x{:02x}{:02x}{:02x}'.format(*most_colorful_color), 16) \ No newline at end of file