feat: Enhance emoji and sticker update listeners to process changes more efficiently
This commit is contained in:
parent
aadfac5045
commit
d7341b3ec2
115
gurt/cog.py
115
gurt/cog.py
@ -268,57 +268,76 @@ class GurtCog(commands.Cog, name="Gurt"): # Added explicit Cog name
|
||||
self.user_relationships[user_id_1][user_id_2] = new_score
|
||||
# print(f"Updated relationship {user_id_1}-{user_id_2}: {current_score:.1f} -> {new_score:.1f} ({change:+.1f})") # Debug log
|
||||
|
||||
async def _process_single_emoji(self, emoji: discord.Emoji):
|
||||
"""Processes a single emoji: generates description if needed and updates EmojiManager."""
|
||||
try:
|
||||
name_key = f":{emoji.name}:"
|
||||
emoji_url = str(emoji.url)
|
||||
guild_id = emoji.guild.id # Get guild_id from the emoji object
|
||||
|
||||
existing_emoji = await self.emoji_manager.get_emoji(name_key)
|
||||
if existing_emoji and \
|
||||
existing_emoji.get("id") == str(emoji.id) and \
|
||||
existing_emoji.get("url") == emoji_url and \
|
||||
existing_emoji.get("description") and \
|
||||
existing_emoji.get("description") != "No description generated.":
|
||||
# print(f"Skipping already processed emoji: {name_key} in guild {emoji.guild.name}")
|
||||
return
|
||||
|
||||
print(f"Generating description for emoji: {name_key} in guild {emoji.guild.name}")
|
||||
mime_type = "image/gif" if emoji.animated else "image/png"
|
||||
description = await api.generate_image_description(self, emoji_url, emoji.name, "emoji", mime_type)
|
||||
await self.emoji_manager.add_emoji(name_key, str(emoji.id), emoji.animated, guild_id, emoji_url, description or "No description generated.")
|
||||
await asyncio.sleep(1) # Rate limiting
|
||||
except Exception as e:
|
||||
print(f"Error processing single emoji {emoji.name} (ID: {emoji.id}) in guild {emoji.guild.name}: {e}")
|
||||
|
||||
async def _process_single_sticker(self, sticker: discord.StickerItem):
|
||||
"""Processes a single sticker: generates description if needed and updates EmojiManager."""
|
||||
try:
|
||||
name_key = f":{sticker.name}:"
|
||||
sticker_url = str(sticker.url)
|
||||
guild_id = sticker.guild_id # Stickers have guild_id directly
|
||||
|
||||
existing_sticker = await self.emoji_manager.get_sticker(name_key)
|
||||
if existing_sticker and \
|
||||
existing_sticker.get("id") == str(sticker.id) and \
|
||||
existing_sticker.get("url") == sticker_url and \
|
||||
existing_sticker.get("description") and \
|
||||
existing_sticker.get("description") not in ["No description generated.", "Lottie animation, visual description not applicable."]:
|
||||
# print(f"Skipping already processed sticker: {name_key} in guild ID {guild_id}")
|
||||
return
|
||||
|
||||
print(f"Generating description for sticker: {sticker.name} (ID: {sticker.id}) in guild ID {guild_id}")
|
||||
description_to_add = "No description generated."
|
||||
if sticker.format == discord.StickerFormatType.png or sticker.format == discord.StickerFormatType.apng:
|
||||
mime_type = "image/png"
|
||||
description = await api.generate_image_description(self, sticker_url, sticker.name, "sticker", mime_type)
|
||||
description_to_add = description or "No description generated."
|
||||
elif sticker.format == discord.StickerFormatType.lottie:
|
||||
description_to_add = "Lottie animation, visual description not applicable."
|
||||
else:
|
||||
print(f"Skipping sticker {sticker.name} due to unsupported format: {sticker.format}")
|
||||
description_to_add = f"Unsupported format: {sticker.format}, visual description not applicable."
|
||||
|
||||
await self.emoji_manager.add_sticker(name_key, str(sticker.id), guild_id, sticker_url, description_to_add)
|
||||
await asyncio.sleep(1) # Rate limiting
|
||||
except Exception as e:
|
||||
print(f"Error processing single sticker {sticker.name} (ID: {sticker.id}) in guild ID {sticker.guild_id}: {e}")
|
||||
|
||||
async def _fetch_and_process_guild_assets(self, guild: discord.Guild):
|
||||
"""Iterates through a guild's emojis and stickers, generates descriptions, and updates EmojiManager."""
|
||||
print(f"Processing assets for guild: {guild.name} ({guild.id})")
|
||||
processed_count = 0
|
||||
# Emojis
|
||||
for emoji in guild.emojis:
|
||||
try:
|
||||
name_key = f":{emoji.name}:"
|
||||
emoji_url = str(emoji.url)
|
||||
mime_type = "image/gif" if emoji.animated else "image/png"
|
||||
"""Iterates through a guild's emojis and stickers, and processes each one concurrently."""
|
||||
print(f"Queueing asset processing for guild: {guild.name} ({guild.id})")
|
||||
emoji_tasks = [asyncio.create_task(self._process_single_emoji(emoji)) for emoji in guild.emojis]
|
||||
sticker_tasks = [asyncio.create_task(self._process_single_sticker(sticker)) for sticker in guild.stickers]
|
||||
|
||||
# Check if already processed with a description to avoid re-processing unless necessary
|
||||
existing_emoji = await self.emoji_manager.get_emoji(name_key)
|
||||
if existing_emoji and existing_emoji.get("url") == emoji_url and existing_emoji.get("description") and existing_emoji.get("description") != "No description generated.":
|
||||
# print(f"Skipping already processed emoji: {name_key} in guild {guild.name}")
|
||||
continue
|
||||
all_tasks = emoji_tasks + sticker_tasks
|
||||
if all_tasks:
|
||||
await asyncio.gather(*all_tasks, return_exceptions=True) # Wait for all tasks for this guild to complete
|
||||
print(f"Finished concurrent asset processing for guild: {guild.name} ({guild.id}). Processed {len(all_tasks)} potential items.")
|
||||
else:
|
||||
print(f"No emojis or stickers to process for guild: {guild.name} ({guild.id})")
|
||||
|
||||
print(f"Generating description for emoji: {name_key} in guild {guild.name}")
|
||||
description = await api.generate_image_description(self, emoji_url, emoji.name, "emoji", mime_type)
|
||||
await self.emoji_manager.add_emoji(name_key, str(emoji.id), emoji.animated, guild.id, emoji_url, description or "No description generated.")
|
||||
processed_count +=1
|
||||
await asyncio.sleep(1) # Rate limiting
|
||||
except Exception as e:
|
||||
print(f"Error processing emoji {emoji.name} in guild {guild.name}: {e}")
|
||||
|
||||
# Stickers
|
||||
for sticker in guild.stickers:
|
||||
try:
|
||||
name_key = f":{sticker.name}:"
|
||||
sticker_url = str(sticker.url)
|
||||
|
||||
existing_sticker = await self.emoji_manager.get_sticker(name_key)
|
||||
if existing_sticker and existing_sticker.get("url") == sticker_url and existing_sticker.get("description") and existing_sticker.get("description") not in ["No description generated.", "Lottie animation, visual description not applicable."]:
|
||||
# print(f"Skipping already processed sticker: {name_key} in guild {guild.name}")
|
||||
continue
|
||||
|
||||
print(f"Generating description for sticker: {sticker.name} in guild {guild.name}")
|
||||
if sticker.format == discord.StickerFormatType.png or sticker.format == discord.StickerFormatType.apng:
|
||||
mime_type = "image/png" # APNG is also fine as image/png for Gemini
|
||||
description = await api.generate_image_description(self, sticker_url, sticker.name, "sticker", mime_type)
|
||||
await self.emoji_manager.add_sticker(name_key, str(sticker.id), guild.id, sticker_url, description or "No description generated.")
|
||||
elif sticker.format == discord.StickerFormatType.lottie:
|
||||
await self.emoji_manager.add_sticker(name_key, str(sticker.id), guild.id, sticker_url, "Lottie animation, visual description not applicable.")
|
||||
else:
|
||||
print(f"Skipping sticker {sticker.name} due to unsupported format: {sticker.format}")
|
||||
await self.emoji_manager.add_sticker(name_key, str(sticker.id), guild.id, sticker_url, f"Unsupported format: {sticker.format}, visual description not applicable.")
|
||||
processed_count += 1
|
||||
await asyncio.sleep(1) # Rate limiting
|
||||
except Exception as e:
|
||||
print(f"Error processing sticker {sticker.name} in guild {guild.name}: {e}")
|
||||
print(f"Finished processing {processed_count} new/updated assets for guild: {guild.name} ({guild.id})")
|
||||
|
||||
async def initial_emoji_sticker_scan(self):
|
||||
"""Scans all guilds GURT is in on startup for emojis and stickers."""
|
||||
|
@ -650,15 +650,78 @@ async def on_guild_join_listener(cog: 'GurtCog', guild: discord.Guild):
|
||||
async def on_guild_emojis_update_listener(cog: 'GurtCog', guild: discord.Guild, before: List[discord.Emoji], after: List[discord.Emoji]):
|
||||
"""Listener function for on_guild_emojis_update."""
|
||||
print(f"Emojis updated in guild: {guild.name} ({guild.id}). Before: {len(before)}, After: {len(after)}")
|
||||
# For simplicity and to ensure all changes (add, remove, name change) are caught,
|
||||
# re-process all emojis for the guild.
|
||||
# A more optimized approach could diff 'before' and 'after' lists.
|
||||
print(f"Re-processing all emojis for guild: {guild.name}")
|
||||
asyncio.create_task(cog._fetch_and_process_guild_assets(guild)) # This will re-process stickers too, which is fine.
|
||||
|
||||
before_map = {emoji.id: emoji for emoji in before}
|
||||
after_map = {emoji.id: emoji for emoji in after}
|
||||
|
||||
tasks = []
|
||||
|
||||
# Process added emojis
|
||||
for emoji_id, emoji_obj in after_map.items():
|
||||
if emoji_id not in before_map:
|
||||
print(f"New emoji added: {emoji_obj.name} ({emoji_id}) in guild {guild.name}")
|
||||
tasks.append(asyncio.create_task(cog._process_single_emoji(emoji_obj)))
|
||||
else:
|
||||
# Check for changes in existing emojis (e.g., name change)
|
||||
# The _process_single_emoji method already checks if a description exists and is valid.
|
||||
# If the name changes, the old key won't match, so it will be treated as new by the manager if name is key.
|
||||
# If ID is the primary key for checking existence, then a name change might need explicit handling.
|
||||
# Current EmojiManager uses name as key, so a name change means old is gone, new is added.
|
||||
# If an emoji's URL or other relevant properties change, _process_single_emoji will handle it.
|
||||
before_emoji = before_map[emoji_id]
|
||||
if before_emoji.name != emoji_obj.name or str(before_emoji.url) != str(emoji_obj.url):
|
||||
print(f"Emoji changed: {before_emoji.name} -> {emoji_obj.name} or URL changed in guild {guild.name}")
|
||||
# Remove old entry if name changed, as EmojiManager uses name as key
|
||||
if before_emoji.name != emoji_obj.name:
|
||||
await cog.emoji_manager.remove_emoji(f":{before_emoji.name}:")
|
||||
tasks.append(asyncio.create_task(cog._process_single_emoji(emoji_obj)))
|
||||
|
||||
|
||||
# Process removed emojis
|
||||
for emoji_id, emoji_obj in before_map.items():
|
||||
if emoji_id not in after_map:
|
||||
print(f"Emoji removed: {emoji_obj.name} ({emoji_id}) from guild {guild.name}")
|
||||
await cog.emoji_manager.remove_emoji(f":{emoji_obj.name}:") # Remove by name key
|
||||
|
||||
if tasks:
|
||||
print(f"Queued {len(tasks)} tasks for emoji updates in guild {guild.name}")
|
||||
await asyncio.gather(*tasks, return_exceptions=True)
|
||||
else:
|
||||
print(f"No new or significantly changed emojis to process in guild {guild.name}")
|
||||
|
||||
|
||||
async def on_guild_stickers_update_listener(cog: 'GurtCog', guild: discord.Guild, before: List[discord.StickerItem], after: List[discord.StickerItem]):
|
||||
"""Listener function for on_guild_stickers_update."""
|
||||
print(f"Stickers updated in guild: {guild.name} ({guild.id}). Before: {len(before)}, After: {len(after)}")
|
||||
# Similar to emojis, re-process all assets for simplicity.
|
||||
print(f"Re-processing all stickers (and emojis) for guild: {guild.name}")
|
||||
asyncio.create_task(cog._fetch_and_process_guild_assets(guild))
|
||||
|
||||
before_map = {sticker.id: sticker for sticker in before}
|
||||
after_map = {sticker.id: sticker for sticker in after}
|
||||
tasks = []
|
||||
|
||||
# Process added or changed stickers
|
||||
for sticker_id, sticker_obj in after_map.items():
|
||||
if sticker_id not in before_map:
|
||||
print(f"New sticker added: {sticker_obj.name} ({sticker_id}) in guild {guild.name}")
|
||||
tasks.append(asyncio.create_task(cog._process_single_sticker(sticker_obj)))
|
||||
else:
|
||||
before_sticker = before_map[sticker_id]
|
||||
# Check for relevant changes (name, URL, format)
|
||||
if before_sticker.name != sticker_obj.name or \
|
||||
str(before_sticker.url) != str(sticker_obj.url) or \
|
||||
before_sticker.format != sticker_obj.format:
|
||||
print(f"Sticker changed: {before_sticker.name} -> {sticker_obj.name} or URL/format changed in guild {guild.name}")
|
||||
if before_sticker.name != sticker_obj.name:
|
||||
await cog.emoji_manager.remove_sticker(f":{before_sticker.name}:")
|
||||
tasks.append(asyncio.create_task(cog._process_single_sticker(sticker_obj)))
|
||||
|
||||
# Process removed stickers
|
||||
for sticker_id, sticker_obj in before_map.items():
|
||||
if sticker_id not in after_map:
|
||||
print(f"Sticker removed: {sticker_obj.name} ({sticker_id}) from guild {guild.name}")
|
||||
await cog.emoji_manager.remove_sticker(f":{sticker_obj.name}:")
|
||||
|
||||
if tasks:
|
||||
print(f"Queued {len(tasks)} tasks for sticker updates in guild {guild.name}")
|
||||
await asyncio.gather(*tasks, return_exceptions=True)
|
||||
else:
|
||||
print(f"No new or significantly changed stickers to process in guild {guild.name}")
|
||||
|
Loading…
x
Reference in New Issue
Block a user