modified: bot.py
This commit is contained in:
354
bot.py
354
bot.py
@@ -321,7 +321,7 @@ def load_user_data_from_mysql(user_id, guild_id):
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Count warnings from user_warnings table
|
# Count warnings from user_warnings table
|
||||||
warning_count_query = "SELECT COUNT(*) FROM user_warnings WHERE user_id = %s AND guild_id = %s"
|
warning_count_query = "SELECT COUNT(*) FROM user_warnings WHERE user_id = %s AND guild_id = %s AND aktiv = TRUE"
|
||||||
cursor.execute(warning_count_query, (user_id, guild_id))
|
cursor.execute(warning_count_query, (user_id, guild_id))
|
||||||
warning_count = cursor.fetchone()[0]
|
warning_count = cursor.fetchone()[0]
|
||||||
user_data["warns"] = warning_count
|
user_data["warns"] = warning_count
|
||||||
@@ -2106,6 +2106,8 @@ async def modhelp(ctx):
|
|||||||
"`/unmute <user>` - Manually unmute a user\n"
|
"`/unmute <user>` - Manually unmute a user\n"
|
||||||
"`/modinfo [user]` - View comprehensive user information\n"
|
"`/modinfo [user]` - View comprehensive user information\n"
|
||||||
"`/viewwarn <warning_id>` - View detailed warning information\n"
|
"`/viewwarn <warning_id>` - View detailed warning information\n"
|
||||||
|
"`/removewarn <warning_id>` - Deactivate a warning (Level 6+)\n"
|
||||||
|
"`/restorewarn <warning_id>` - Reactivate a warning (Level 6+)\n"
|
||||||
"`/modstats [user]` - View moderation statistics\n"
|
"`/modstats [user]` - View moderation statistics\n"
|
||||||
"`/processes <action> [type]` - Manage active processes\n"
|
"`/processes <action> [type]` - Manage active processes\n"
|
||||||
"`/startgiveaway` - Create server giveaways\n"
|
"`/startgiveaway` - Create server giveaways\n"
|
||||||
@@ -2793,14 +2795,14 @@ async def save_warning_to_database(user_id, guild_id, moderator_id, reason, time
|
|||||||
insert_query = """
|
insert_query = """
|
||||||
INSERT INTO user_warnings (user_id, guild_id, moderator_id, reason, message_id,
|
INSERT INTO user_warnings (user_id, guild_id, moderator_id, reason, message_id,
|
||||||
message_content, message_attachments, message_author_id,
|
message_content, message_attachments, message_author_id,
|
||||||
message_channel_id, context_messages, created_at)
|
message_channel_id, context_messages, aktiv, created_at)
|
||||||
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
|
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
cursor.execute(insert_query, (
|
cursor.execute(insert_query, (
|
||||||
user_id, guild_id, moderator_id, reason, message_id_db,
|
user_id, guild_id, moderator_id, reason, message_id_db,
|
||||||
message_content, message_attachments, message_author_id,
|
message_content, message_attachments, message_author_id,
|
||||||
message_channel_id, context_messages, timestamp
|
message_channel_id, context_messages, True, timestamp
|
||||||
))
|
))
|
||||||
connection.commit()
|
connection.commit()
|
||||||
|
|
||||||
@@ -2839,10 +2841,12 @@ def create_warnings_table():
|
|||||||
message_author_id BIGINT NULL,
|
message_author_id BIGINT NULL,
|
||||||
message_channel_id BIGINT NULL,
|
message_channel_id BIGINT NULL,
|
||||||
context_messages LONGTEXT NULL,
|
context_messages LONGTEXT NULL,
|
||||||
|
aktiv BOOLEAN DEFAULT TRUE,
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
INDEX idx_user_guild (user_id, guild_id),
|
INDEX idx_user_guild (user_id, guild_id),
|
||||||
INDEX idx_created_at (created_at),
|
INDEX idx_created_at (created_at),
|
||||||
INDEX idx_message_id (message_id)
|
INDEX idx_message_id (message_id),
|
||||||
|
INDEX idx_aktiv (aktiv)
|
||||||
)
|
)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -2856,7 +2860,9 @@ def create_warnings_table():
|
|||||||
"ALTER TABLE user_warnings ADD COLUMN message_author_id BIGINT NULL",
|
"ALTER TABLE user_warnings ADD COLUMN message_author_id BIGINT NULL",
|
||||||
"ALTER TABLE user_warnings ADD COLUMN message_channel_id BIGINT NULL",
|
"ALTER TABLE user_warnings ADD COLUMN message_channel_id BIGINT NULL",
|
||||||
"ALTER TABLE user_warnings ADD COLUMN context_messages LONGTEXT NULL",
|
"ALTER TABLE user_warnings ADD COLUMN context_messages LONGTEXT NULL",
|
||||||
"ALTER TABLE user_warnings ADD INDEX idx_message_id (message_id)"
|
"ALTER TABLE user_warnings ADD COLUMN aktiv BOOLEAN DEFAULT TRUE",
|
||||||
|
"ALTER TABLE user_warnings ADD INDEX idx_message_id (message_id)",
|
||||||
|
"ALTER TABLE user_warnings ADD INDEX idx_aktiv (aktiv)"
|
||||||
]
|
]
|
||||||
|
|
||||||
for alter_query in alter_queries:
|
for alter_query in alter_queries:
|
||||||
@@ -2877,8 +2883,14 @@ def create_warnings_table():
|
|||||||
if connection:
|
if connection:
|
||||||
close_database_connection(connection)
|
close_database_connection(connection)
|
||||||
|
|
||||||
async def get_user_warnings(user_id, guild_id):
|
async def get_user_warnings(user_id, guild_id, active_only=True):
|
||||||
"""Retrieves all warning records for a user"""
|
"""Retrieves warning records for a user
|
||||||
|
|
||||||
|
Args:
|
||||||
|
user_id: Discord user ID
|
||||||
|
guild_id: Discord guild ID
|
||||||
|
active_only: If True, only returns active warnings. If False, returns all warnings.
|
||||||
|
"""
|
||||||
connection = None
|
connection = None
|
||||||
cursor = None
|
cursor = None
|
||||||
try:
|
try:
|
||||||
@@ -2887,11 +2899,11 @@ async def get_user_warnings(user_id, guild_id):
|
|||||||
|
|
||||||
select_query = """
|
select_query = """
|
||||||
SELECT id, moderator_id, reason, created_at, message_id, message_content,
|
SELECT id, moderator_id, reason, created_at, message_id, message_content,
|
||||||
message_attachments, message_author_id, message_channel_id, context_messages
|
message_attachments, message_author_id, message_channel_id, context_messages, aktiv
|
||||||
FROM user_warnings
|
FROM user_warnings
|
||||||
WHERE user_id = %s AND guild_id = %s
|
WHERE user_id = %s AND guild_id = %s {}
|
||||||
ORDER BY created_at DESC
|
ORDER BY created_at DESC
|
||||||
"""
|
""".format("AND aktiv = TRUE" if active_only else "")
|
||||||
|
|
||||||
cursor.execute(select_query, (user_id, guild_id))
|
cursor.execute(select_query, (user_id, guild_id))
|
||||||
results = cursor.fetchall()
|
results = cursor.fetchall()
|
||||||
@@ -2908,7 +2920,8 @@ async def get_user_warnings(user_id, guild_id):
|
|||||||
"message_attachments": row[6],
|
"message_attachments": row[6],
|
||||||
"message_author_id": row[7],
|
"message_author_id": row[7],
|
||||||
"message_channel_id": row[8],
|
"message_channel_id": row[8],
|
||||||
"context_messages": row[9]
|
"context_messages": row[9],
|
||||||
|
"aktiv": row[10]
|
||||||
})
|
})
|
||||||
|
|
||||||
return warnings
|
return warnings
|
||||||
@@ -2922,6 +2935,66 @@ async def get_user_warnings(user_id, guild_id):
|
|||||||
if connection:
|
if connection:
|
||||||
close_database_connection(connection)
|
close_database_connection(connection)
|
||||||
|
|
||||||
|
async def deactivate_warning(warning_id):
|
||||||
|
"""Deactivates a warning by setting aktiv to FALSE"""
|
||||||
|
connection = None
|
||||||
|
cursor = None
|
||||||
|
try:
|
||||||
|
connection = connect_to_database()
|
||||||
|
cursor = connection.cursor()
|
||||||
|
|
||||||
|
update_query = "UPDATE user_warnings SET aktiv = FALSE WHERE id = %s"
|
||||||
|
cursor.execute(update_query, (warning_id,))
|
||||||
|
connection.commit()
|
||||||
|
|
||||||
|
if cursor.rowcount > 0:
|
||||||
|
logger.info(f"Deactivated warning with ID {warning_id}")
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
logger.warning(f"No warning found with ID {warning_id}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error deactivating warning: {e}")
|
||||||
|
if connection:
|
||||||
|
connection.rollback()
|
||||||
|
return False
|
||||||
|
finally:
|
||||||
|
if cursor:
|
||||||
|
cursor.close()
|
||||||
|
if connection:
|
||||||
|
close_database_connection(connection)
|
||||||
|
|
||||||
|
async def reactivate_warning(warning_id):
|
||||||
|
"""Reactivates a warning by setting aktiv to TRUE"""
|
||||||
|
connection = None
|
||||||
|
cursor = None
|
||||||
|
try:
|
||||||
|
connection = connect_to_database()
|
||||||
|
cursor = connection.cursor()
|
||||||
|
|
||||||
|
update_query = "UPDATE user_warnings SET aktiv = TRUE WHERE id = %s"
|
||||||
|
cursor.execute(update_query, (warning_id,))
|
||||||
|
connection.commit()
|
||||||
|
|
||||||
|
if cursor.rowcount > 0:
|
||||||
|
logger.info(f"Reactivated warning with ID {warning_id}")
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
logger.warning(f"No warning found with ID {warning_id}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error reactivating warning: {e}")
|
||||||
|
if connection:
|
||||||
|
connection.rollback()
|
||||||
|
return False
|
||||||
|
finally:
|
||||||
|
if cursor:
|
||||||
|
cursor.close()
|
||||||
|
if connection:
|
||||||
|
close_database_connection(connection)
|
||||||
|
|
||||||
async def get_message_data(channel, message_id, context_range=3):
|
async def get_message_data(channel, message_id, context_range=3):
|
||||||
"""Retrieves and processes message data for warning documentation with context messages"""
|
"""Retrieves and processes message data for warning documentation with context messages"""
|
||||||
try:
|
try:
|
||||||
@@ -3509,8 +3582,8 @@ async def account(ctx, user: discord.User = None):
|
|||||||
# Get guild settings for thresholds
|
# Get guild settings for thresholds
|
||||||
guild_settings = get_guild_settings(ctx.guild.id)
|
guild_settings = get_guild_settings(ctx.guild.id)
|
||||||
|
|
||||||
# Get detailed warning records
|
# Get detailed warning records (active warnings only for user view)
|
||||||
warning_records = await get_user_warnings(target_user.id, ctx.guild.id)
|
warning_records = await get_user_warnings(target_user.id, ctx.guild.id, active_only=True)
|
||||||
|
|
||||||
# Warning information with threshold
|
# Warning information with threshold
|
||||||
warn_threshold = guild_settings.get("max_warn_threshold", 3)
|
warn_threshold = guild_settings.get("max_warn_threshold", 3)
|
||||||
@@ -3680,8 +3753,8 @@ async def modinfo(ctx, user: discord.User = None):
|
|||||||
guild_settings = get_guild_settings(ctx.guild.id)
|
guild_settings = get_guild_settings(ctx.guild.id)
|
||||||
warn_threshold = guild_settings.get("max_warn_threshold", 3)
|
warn_threshold = guild_settings.get("max_warn_threshold", 3)
|
||||||
|
|
||||||
# Get detailed warning records
|
# Get detailed warning records (all warnings for moderator view)
|
||||||
warning_records = await get_user_warnings(user.id, ctx.guild.id)
|
warning_records = await get_user_warnings(user.id, ctx.guild.id, active_only=False)
|
||||||
|
|
||||||
# Create main embed
|
# Create main embed
|
||||||
embed = discord.Embed(
|
embed = discord.Embed(
|
||||||
@@ -3778,7 +3851,9 @@ async def modinfo(ctx, user: discord.User = None):
|
|||||||
if len(reason) > 50:
|
if len(reason) > 50:
|
||||||
reason = reason[:47] + "..."
|
reason = reason[:47] + "..."
|
||||||
|
|
||||||
warning_line = f"`{warning_date}` **{mod_name}**: {reason}"
|
# Add status indicator
|
||||||
|
status_indicator = "🟢" if record.get("aktiv", True) else "🔴"
|
||||||
|
warning_line = f"`{warning_date}` {status_indicator} **{mod_name}**: {reason}"
|
||||||
|
|
||||||
# Add message indicator and content preview if available
|
# Add message indicator and content preview if available
|
||||||
if record.get("message_id"):
|
if record.get("message_id"):
|
||||||
@@ -3792,6 +3867,8 @@ async def modinfo(ctx, user: discord.User = None):
|
|||||||
if len(warning_records) > 3:
|
if len(warning_records) > 3:
|
||||||
warning_history += f"*... and {len(warning_records) - 3} more warning(s)*"
|
warning_history += f"*... and {len(warning_records) - 3} more warning(s)*"
|
||||||
|
|
||||||
|
warning_history += f"\n🟢 = Active Warning | 🔴 = Deactivated Warning"
|
||||||
|
|
||||||
embed.add_field(name="📋 Recent Warnings", value=warning_history, inline=False)
|
embed.add_field(name="📋 Recent Warnings", value=warning_history, inline=False)
|
||||||
|
|
||||||
# Server activity (if member)
|
# Server activity (if member)
|
||||||
@@ -3899,7 +3976,7 @@ async def viewwarn(ctx, warning_id: int):
|
|||||||
|
|
||||||
select_query = """
|
select_query = """
|
||||||
SELECT user_id, guild_id, moderator_id, reason, created_at, message_id,
|
SELECT user_id, guild_id, moderator_id, reason, created_at, message_id,
|
||||||
message_content, message_attachments, message_author_id, message_channel_id, context_messages
|
message_content, message_attachments, message_author_id, message_channel_id, context_messages, aktiv
|
||||||
FROM user_warnings
|
FROM user_warnings
|
||||||
WHERE id = %s AND guild_id = %s
|
WHERE id = %s AND guild_id = %s
|
||||||
"""
|
"""
|
||||||
@@ -3917,7 +3994,7 @@ async def viewwarn(ctx, warning_id: int):
|
|||||||
return
|
return
|
||||||
|
|
||||||
# Parse result
|
# Parse result
|
||||||
user_id, guild_id, moderator_id, reason, created_at, message_id, message_content, message_attachments, message_author_id, message_channel_id, context_messages = result
|
user_id, guild_id, moderator_id, reason, created_at, message_id, message_content, message_attachments, message_author_id, message_channel_id, context_messages, aktiv = result
|
||||||
|
|
||||||
# Get user and moderator objects
|
# Get user and moderator objects
|
||||||
warned_user = await client.fetch_user(user_id)
|
warned_user = await client.fetch_user(user_id)
|
||||||
@@ -3933,6 +4010,13 @@ async def viewwarn(ctx, warning_id: int):
|
|||||||
embed.add_field(name="👤 Warned User", value=f"{warned_user.mention}\n`{warned_user.id}`", inline=True)
|
embed.add_field(name="👤 Warned User", value=f"{warned_user.mention}\n`{warned_user.id}`", inline=True)
|
||||||
embed.add_field(name="👮 Moderator", value=f"{moderator.mention}\n`{moderator.id}`", inline=True)
|
embed.add_field(name="👮 Moderator", value=f"{moderator.mention}\n`{moderator.id}`", inline=True)
|
||||||
embed.add_field(name="📅 Date", value=f"<t:{int(created_at.timestamp())}:F>", inline=True)
|
embed.add_field(name="📅 Date", value=f"<t:{int(created_at.timestamp())}:F>", inline=True)
|
||||||
|
|
||||||
|
# Add status field
|
||||||
|
status_text = "🟢 **Active**" if aktiv else "🔴 **Deactivated**"
|
||||||
|
embed.add_field(name="📊 Status", value=status_text, inline=True)
|
||||||
|
embed.add_field(name="🆔 Warning ID", value=f"`{warning_id}`", inline=True)
|
||||||
|
embed.add_field(name="", value="", inline=True) # Empty field for spacing
|
||||||
|
|
||||||
embed.add_field(name="📝 Reason", value=reason, inline=False)
|
embed.add_field(name="📝 Reason", value=reason, inline=False)
|
||||||
|
|
||||||
# Add message information if available
|
# Add message information if available
|
||||||
@@ -4046,6 +4130,238 @@ async def viewwarn(ctx, warning_id: int):
|
|||||||
)
|
)
|
||||||
await send_response(embed=embed)
|
await send_response(embed=embed)
|
||||||
|
|
||||||
|
@client.hybrid_command()
|
||||||
|
async def removewarn(ctx, warning_id: int):
|
||||||
|
"""Deactivates a warning (makes it hidden from /account but keeps data) (Requires Permission Level 6 or higher)
|
||||||
|
|
||||||
|
Usage: /removewarn 123
|
||||||
|
"""
|
||||||
|
# Check if it's a slash command and defer if needed
|
||||||
|
is_slash_command = hasattr(ctx, 'interaction') and ctx.interaction
|
||||||
|
if is_slash_command:
|
||||||
|
await ctx.defer()
|
||||||
|
|
||||||
|
# Helper function for sending responses
|
||||||
|
async def send_response(content=None, embed=None, ephemeral=False, file=None):
|
||||||
|
try:
|
||||||
|
if is_slash_command:
|
||||||
|
await ctx.followup.send(content=content, embed=embed, ephemeral=ephemeral, file=file)
|
||||||
|
else:
|
||||||
|
await ctx.send(content=content, embed=embed, file=file)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error sending response: {e}")
|
||||||
|
try:
|
||||||
|
await ctx.send(content=content, embed=embed, file=file)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Check permissions
|
||||||
|
user_data = await load_user_data(ctx.author.id, ctx.guild.id)
|
||||||
|
if user_data["permission"] < 6:
|
||||||
|
embed = discord.Embed(
|
||||||
|
title="❌ Insufficient Permissions",
|
||||||
|
description="You need Level 6 or higher permissions to deactivate warnings.",
|
||||||
|
color=0xff0000
|
||||||
|
)
|
||||||
|
await send_response(embed=embed, ephemeral=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
# Get warning info first
|
||||||
|
connection = connect_to_database()
|
||||||
|
cursor = connection.cursor()
|
||||||
|
|
||||||
|
cursor.execute("SELECT user_id, guild_id, reason, aktiv FROM user_warnings WHERE id = %s", (warning_id,))
|
||||||
|
warning_data = cursor.fetchone()
|
||||||
|
|
||||||
|
if not warning_data:
|
||||||
|
embed = discord.Embed(
|
||||||
|
title="❌ Warning Not Found",
|
||||||
|
description=f"No warning found with ID `{warning_id}`.",
|
||||||
|
color=0xff0000
|
||||||
|
)
|
||||||
|
await send_response(embed=embed, ephemeral=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
if warning_data[1] != ctx.guild.id:
|
||||||
|
embed = discord.Embed(
|
||||||
|
title="❌ Invalid Warning",
|
||||||
|
description="This warning doesn't belong to this server.",
|
||||||
|
color=0xff0000
|
||||||
|
)
|
||||||
|
await send_response(embed=embed, ephemeral=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
if not warning_data[3]: # Already inactive
|
||||||
|
embed = discord.Embed(
|
||||||
|
title="⚠️ Warning Already Inactive",
|
||||||
|
description=f"Warning `{warning_id}` is already deactivated.",
|
||||||
|
color=0xffa500
|
||||||
|
)
|
||||||
|
await send_response(embed=embed, ephemeral=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
# Deactivate the warning
|
||||||
|
success = await deactivate_warning(warning_id)
|
||||||
|
|
||||||
|
if success:
|
||||||
|
try:
|
||||||
|
target_user = await client.fetch_user(warning_data[0])
|
||||||
|
user_name = target_user.display_name
|
||||||
|
except:
|
||||||
|
user_name = f"User {warning_data[0]}"
|
||||||
|
|
||||||
|
embed = discord.Embed(
|
||||||
|
title="✅ Warning Deactivated",
|
||||||
|
description=f"Warning `{warning_id}` for {user_name} has been deactivated.\n\n**Reason:** {warning_data[2]}\n\nThe warning is now hidden from `/account` but data is preserved for admin review.",
|
||||||
|
color=0x00ff00
|
||||||
|
)
|
||||||
|
await send_response(embed=embed)
|
||||||
|
|
||||||
|
# Log the action
|
||||||
|
await log_moderation_action(
|
||||||
|
ctx.guild.id,
|
||||||
|
f"Warning `{warning_id}` deactivated by {ctx.author.display_name}",
|
||||||
|
ctx.author
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
embed = discord.Embed(
|
||||||
|
title="❌ Error",
|
||||||
|
description="Failed to deactivate warning. Please try again.",
|
||||||
|
color=0xff0000
|
||||||
|
)
|
||||||
|
await send_response(embed=embed)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error in removewarn command: {e}")
|
||||||
|
embed = discord.Embed(
|
||||||
|
title="❌ Error",
|
||||||
|
description="An error occurred while deactivating the warning.",
|
||||||
|
color=0xff0000
|
||||||
|
)
|
||||||
|
await send_response(embed=embed)
|
||||||
|
finally:
|
||||||
|
if cursor:
|
||||||
|
cursor.close()
|
||||||
|
if connection:
|
||||||
|
close_database_connection(connection)
|
||||||
|
|
||||||
|
@client.hybrid_command()
|
||||||
|
async def restorewarn(ctx, warning_id: int):
|
||||||
|
"""Reactivates a previously deactivated warning (Requires Permission Level 6 or higher)
|
||||||
|
|
||||||
|
Usage: /restorewarn 123
|
||||||
|
"""
|
||||||
|
# Check if it's a slash command and defer if needed
|
||||||
|
is_slash_command = hasattr(ctx, 'interaction') and ctx.interaction
|
||||||
|
if is_slash_command:
|
||||||
|
await ctx.defer()
|
||||||
|
|
||||||
|
# Helper function for sending responses
|
||||||
|
async def send_response(content=None, embed=None, ephemeral=False, file=None):
|
||||||
|
try:
|
||||||
|
if is_slash_command:
|
||||||
|
await ctx.followup.send(content=content, embed=embed, ephemeral=ephemeral, file=file)
|
||||||
|
else:
|
||||||
|
await ctx.send(content=content, embed=embed, file=file)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error sending response: {e}")
|
||||||
|
try:
|
||||||
|
await ctx.send(content=content, embed=embed, file=file)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Check permissions
|
||||||
|
user_data = await load_user_data(ctx.author.id, ctx.guild.id)
|
||||||
|
if user_data["permission"] < 6:
|
||||||
|
embed = discord.Embed(
|
||||||
|
title="❌ Insufficient Permissions",
|
||||||
|
description="You need Level 6 or higher permissions to reactivate warnings.",
|
||||||
|
color=0xff0000
|
||||||
|
)
|
||||||
|
await send_response(embed=embed, ephemeral=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
# Get warning info first
|
||||||
|
connection = connect_to_database()
|
||||||
|
cursor = connection.cursor()
|
||||||
|
|
||||||
|
cursor.execute("SELECT user_id, guild_id, reason, aktiv FROM user_warnings WHERE id = %s", (warning_id,))
|
||||||
|
warning_data = cursor.fetchone()
|
||||||
|
|
||||||
|
if not warning_data:
|
||||||
|
embed = discord.Embed(
|
||||||
|
title="❌ Warning Not Found",
|
||||||
|
description=f"No warning found with ID `{warning_id}`.",
|
||||||
|
color=0xff0000
|
||||||
|
)
|
||||||
|
await send_response(embed=embed, ephemeral=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
if warning_data[1] != ctx.guild.id:
|
||||||
|
embed = discord.Embed(
|
||||||
|
title="❌ Invalid Warning",
|
||||||
|
description="This warning doesn't belong to this server.",
|
||||||
|
color=0xff0000
|
||||||
|
)
|
||||||
|
await send_response(embed=embed, ephemeral=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
if warning_data[3]: # Already active
|
||||||
|
embed = discord.Embed(
|
||||||
|
title="⚠️ Warning Already Active",
|
||||||
|
description=f"Warning `{warning_id}` is already active.",
|
||||||
|
color=0xffa500
|
||||||
|
)
|
||||||
|
await send_response(embed=embed, ephemeral=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
# Reactivate the warning
|
||||||
|
success = await reactivate_warning(warning_id)
|
||||||
|
|
||||||
|
if success:
|
||||||
|
try:
|
||||||
|
target_user = await client.fetch_user(warning_data[0])
|
||||||
|
user_name = target_user.display_name
|
||||||
|
except:
|
||||||
|
user_name = f"User {warning_data[0]}"
|
||||||
|
|
||||||
|
embed = discord.Embed(
|
||||||
|
title="✅ Warning Reactivated",
|
||||||
|
description=f"Warning `{warning_id}` for {user_name} has been reactivated.\n\n**Reason:** {warning_data[2]}\n\nThe warning is now visible in `/account` again.",
|
||||||
|
color=0x00ff00
|
||||||
|
)
|
||||||
|
await send_response(embed=embed)
|
||||||
|
|
||||||
|
# Log the action
|
||||||
|
await log_moderation_action(
|
||||||
|
ctx.guild.id,
|
||||||
|
f"Warning `{warning_id}` reactivated by {ctx.author.display_name}",
|
||||||
|
ctx.author
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
embed = discord.Embed(
|
||||||
|
title="❌ Error",
|
||||||
|
description="Failed to reactivate warning. Please try again.",
|
||||||
|
color=0xff0000
|
||||||
|
)
|
||||||
|
await send_response(embed=embed)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error in restorewarn command: {e}")
|
||||||
|
embed = discord.Embed(
|
||||||
|
title="❌ Error",
|
||||||
|
description="An error occurred while reactivating the warning.",
|
||||||
|
color=0xff0000
|
||||||
|
)
|
||||||
|
await send_response(embed=embed)
|
||||||
|
finally:
|
||||||
|
if cursor:
|
||||||
|
cursor.close()
|
||||||
|
if connection:
|
||||||
|
close_database_connection(connection)
|
||||||
|
|
||||||
@client.hybrid_command()
|
@client.hybrid_command()
|
||||||
async def mute(ctx, user: discord.User, duration: str, reason: str = "No reason provided", message_id: str = None, context_range: int = 3):
|
async def mute(ctx, user: discord.User, duration: str, reason: str = "No reason provided", message_id: str = None, context_range: int = 3):
|
||||||
"""Mutes a user for a specified duration (Requires Permission Level 5 or higher)
|
"""Mutes a user for a specified duration (Requires Permission Level 5 or higher)
|
||||||
|
|||||||
Reference in New Issue
Block a user