Add purge embeds feature
All checks were successful
Docker Build and Push (Multi-architecture) / build-and-push (push) Successful in 31s

This commit is contained in:
2025-09-22 16:16:23 +00:00
parent c6590f008e
commit 01f6f2b201
3 changed files with 153 additions and 3 deletions

View File

@@ -1,7 +1,8 @@
.gitea
.gitignore
.env
__pycache__
.venv
__pycache__/
md_images/
*.pyc
*.pyo

4
.gitignore vendored
View File

@@ -175,10 +175,10 @@ cython_debug/
.pypirc
# Logs
/logs
logs/
# Embeds
/embed
embed/
# Config file
config.ini

View File

@@ -1062,6 +1062,155 @@ async def refresh_embeds(interaction: discord.Interaction):
ephemeral=True
)
@bot.tree.command(name="purge_embeds", description="Permanently delete all server status embeds (admin only)")
async def purge_embeds(interaction: discord.Interaction):
"""
Slash command to permanently purge all server status embeds from Discord channels.
This command performs a complete cleanup of all tracked server status embeds by:
1. Iterating through all tracked embed locations in embed_locations.json
2. Attempting to delete each embed message from its respective Discord channel
3. Clearing the embed tracking file and internal state tracking
4. Providing real-time progress updates during the operation
Args:
interaction: Discord interaction object representing the command invocation
Workflow:
- Validates administrator permissions
- Checks if any embeds are currently tracked
- Sends initial progress embed
- Processes each embed sequentially with error handling
- Updates progress embed in real-time
- Saves cleared tracking data to disk
- Sends final results with comprehensive statistics
Safety:
- Only affects tracked embeds (won't delete arbitrary messages)
- Maintains logs for audit purposes
- Provides rollback protection through immediate tracking removal
- Includes rate limiting to avoid Discord API limits
Returns:
None: Sends follow-up messages with operation results
"""
if not await check_allowed_guild(interaction):
return
logger.info(f"Purge embeds command invoked by {interaction.user.name}")
await interaction.response.defer(ephemeral=True)
# Require administrator permissions
if not interaction.user.guild_permissions.administrator:
logger.warning(f"Unauthorized purge attempt by {interaction.user.name}")
await interaction.followup.send(
"You need administrator permissions to purge all embeds.",
ephemeral=True
)
return
try:
logger.info("Starting embed purge per admin request")
# Variables to track purge statistics
deleted_count = 0
not_found_count = 0
error_count = 0
total_embeds = len(bot.embed_locations)
if total_embeds == 0:
await interaction.followup.send(
"No embeds are currently being tracked. Nothing to purge.",
ephemeral=True
)
return
# Create progress embed
progress_embed = discord.Embed(
title="🔄 Purging Server Embeds",
description=f"Processing {total_embeds} embeds...",
color=discord.Color.orange()
)
progress_embed.add_field(name="Deleted", value="0", inline=True)
progress_embed.add_field(name="Not Found", value="0", inline=True)
progress_embed.add_field(name="Errors", value="0", inline=True)
progress_embed.set_footer(text="This may take a while...")
progress_message = await interaction.followup.send(embed=progress_embed, ephemeral=True)
# Process each tracked embed
for server_id, location in list(bot.embed_locations.items()):
try:
channel = bot.get_channel(int(location['channel_id']))
if channel:
try:
message = await channel.fetch_message(int(location['message_id']))
await message.delete()
deleted_count += 1
logger.debug(f"Successfully purged embed for server {server_id}")
except discord.NotFound:
not_found_count += 1
logger.debug(f"Embed for server {server_id} already deleted")
except discord.Forbidden:
error_count += 1
logger.error(f"Permission denied when deleting embed for server {server_id}")
except Exception as e:
error_count += 1
logger.error(f"Error deleting embed for server {server_id}: {str(e)}")
else:
not_found_count += 1
logger.warning(f"Channel not found for server {server_id}")
# Remove from tracking immediately
bot.embed_locations.pop(server_id, None)
bot.previous_states.pop(server_id, None) # Also clean up state tracking
# Update progress every 5 embeds or for the last one
if (deleted_count + not_found_count + error_count) % 5 == 0 or \
(deleted_count + not_found_count + error_count) == total_embeds:
progress_embed.description = f"Processed {deleted_count + not_found_count + error_count}/{total_embeds} embeds"
progress_embed.set_field_at(0, name="Deleted", value=str(deleted_count), inline=True)
progress_embed.set_field_at(1, name="Not Found", value=str(not_found_count), inline=True)
progress_embed.set_field_at(2, name="Errors", value=str(error_count), inline=True)
await progress_message.edit(embed=progress_embed)
# Small delay to avoid rate limits
await asyncio.sleep(0.3)
except Exception as e:
error_count += 1
logger.error(f"Unexpected error processing server {server_id}: {str(e)}")
# Save the cleared embed locations
await bot.save_embed_locations()
# Create results embed
result_embed = discord.Embed(
title="✅ Embed Purge Complete",
color=discord.Color.green(),
timestamp=datetime.now()
)
result_embed.add_field(name="Total Tracked", value=str(total_embeds), inline=True)
result_embed.add_field(name="✅ Successfully Deleted", value=str(deleted_count), inline=True)
result_embed.add_field(name="❌ Already Missing", value=str(not_found_count), inline=True)
result_embed.add_field(name="⚠️ Errors", value=str(error_count), inline=True)
result_embed.add_field(name="📊 Success Rate",
value=f"{((deleted_count + not_found_count) / total_embeds * 100):.1f}%",
inline=True)
result_embed.set_footer(text="Embed tracking file has been cleared")
await progress_message.edit(embed=result_embed)
logger.info(f"Embed purge completed: {deleted_count} deleted, {not_found_count} not found, {error_count} errors")
except Exception as e:
logger.error(f"Embed purge failed: {str(e)}")
await interaction.followup.send(
f"❌ Failed to purge embeds: {str(e)}",
ephemeral=True
)
# ==============================================
# BOT EVENTS
# ==============================================