This commit is contained in:
Slipstream 2025-05-03 20:31:29 -06:00
parent bfedd1d048
commit 0c4f00d747
Signed by: slipstream
GPG Key ID: 13E498CE010AC6FD
2 changed files with 634 additions and 82 deletions

View File

@ -3,12 +3,24 @@ from discord.ext import commands
from discord import app_commands
import random
class ModerationCog(commands.Cog):
class FakeModerationCog(commands.Cog):
"""Fake moderation commands that don't actually perform any actions."""
def __init__(self, bot):
self.bot = bot
# Create the main command group for this cog
self.fakemod_group = app_commands.Group(
name="fakemod",
description="Fake moderation commands that don't actually perform any actions"
)
# Register commands
self.register_commands()
# Add command group to the bot's tree
self.bot.tree.add_command(self.fakemod_group)
# Helper method for generating responses
async def _fake_moderation_response(self, action, target, reason=None, duration=None):
"""Generate a fake moderation response."""
@ -52,7 +64,142 @@ class ModerationCog(commands.Cog):
return random.choice(responses.get(action, [f"Action performed on {target}"]))
# --- Ban Commands ---
def register_commands(self):
"""Register all commands for this cog"""
# --- Ban Command ---
ban_command = app_commands.Command(
name="ban",
description="Pretends to ban a member from the server",
callback=self.fakemod_ban_callback,
parent=self.fakemod_group
)
app_commands.describe(
member="The member to pretend to ban",
duration="The fake duration of the ban (e.g., '1d', '7d')",
reason="The fake reason for the ban"
)(ban_command)
self.fakemod_group.add_command(ban_command)
# --- Unban Command ---
unban_command = app_commands.Command(
name="unban",
description="Pretends to unban a user from the server",
callback=self.fakemod_unban_callback,
parent=self.fakemod_group
)
app_commands.describe(
user="The user to pretend to unban (username or ID)",
reason="The fake reason for the unban"
)(unban_command)
self.fakemod_group.add_command(unban_command)
# --- Kick Command ---
kick_command = app_commands.Command(
name="kick",
description="Pretends to kick a member from the server",
callback=self.fakemod_kick_callback,
parent=self.fakemod_group
)
app_commands.describe(
member="The member to pretend to kick",
reason="The fake reason for the kick"
)(kick_command)
self.fakemod_group.add_command(kick_command)
# --- Mute Command ---
mute_command = app_commands.Command(
name="mute",
description="Pretends to mute a member in the server",
callback=self.fakemod_mute_callback,
parent=self.fakemod_group
)
app_commands.describe(
member="The member to pretend to mute",
duration="The fake duration of the mute (e.g., '1h', '30m')",
reason="The fake reason for the mute"
)(mute_command)
self.fakemod_group.add_command(mute_command)
# --- Unmute Command ---
unmute_command = app_commands.Command(
name="unmute",
description="Pretends to unmute a member in the server",
callback=self.fakemod_unmute_callback,
parent=self.fakemod_group
)
app_commands.describe(
member="The member to pretend to unmute",
reason="The fake reason for the unmute"
)(unmute_command)
self.fakemod_group.add_command(unmute_command)
# --- Timeout Command ---
timeout_command = app_commands.Command(
name="timeout",
description="Pretends to timeout a member in the server",
callback=self.fakemod_timeout_callback,
parent=self.fakemod_group
)
app_commands.describe(
member="The member to pretend to timeout",
duration="The fake duration of the timeout (e.g., '1h', '30m')",
reason="The fake reason for the timeout"
)(timeout_command)
self.fakemod_group.add_command(timeout_command)
# --- Warn Command ---
warn_command = app_commands.Command(
name="warn",
description="Pretends to warn a member in the server",
callback=self.fakemod_warn_callback,
parent=self.fakemod_group
)
app_commands.describe(
member="The member to pretend to warn",
reason="The fake reason for the warning"
)(warn_command)
self.fakemod_group.add_command(warn_command)
# --- Command Callbacks ---
async def fakemod_ban_callback(self, interaction: discord.Interaction, member: discord.Member, duration: str = None, reason: str = None):
"""Pretends to ban a member from the server."""
response = await self._fake_moderation_response("ban", member.mention, reason, duration)
await interaction.response.send_message(response)
async def fakemod_unban_callback(self, interaction: discord.Interaction, user: str, reason: str = None):
"""Pretends to unban a user from the server."""
response = await self._fake_moderation_response("unban", user, reason)
await interaction.response.send_message(response)
async def fakemod_kick_callback(self, interaction: discord.Interaction, member: discord.Member, reason: str = None):
"""Pretends to kick a member from the server."""
response = await self._fake_moderation_response("kick", member.mention, reason)
await interaction.response.send_message(response)
async def fakemod_mute_callback(self, interaction: discord.Interaction, member: discord.Member, duration: str = None, reason: str = None):
"""Pretends to mute a member in the server."""
response = await self._fake_moderation_response("mute", member.mention, reason, duration)
await interaction.response.send_message(response)
async def fakemod_unmute_callback(self, interaction: discord.Interaction, member: discord.Member, reason: str = None):
"""Pretends to unmute a member in the server."""
response = await self._fake_moderation_response("unmute", member.mention, reason)
await interaction.response.send_message(response)
async def fakemod_timeout_callback(self, interaction: discord.Interaction, member: discord.Member, duration: str = None, reason: str = None):
"""Pretends to timeout a member in the server."""
response = await self._fake_moderation_response("timeout", member.mention, reason, duration)
await interaction.response.send_message(response)
async def fakemod_warn_callback(self, interaction: discord.Interaction, member: discord.Member, reason: str = None):
"""Pretends to warn a member in the server."""
response = await self._fake_moderation_response("warn", member.mention, reason)
await interaction.response.send_message(response)
# --- Legacy Command Handlers (for prefix commands) ---
@commands.command(name="ban")
async def ban(self, ctx: commands.Context, member: discord.Member = None, duration: str = None, *, reason: str = None):
"""Pretends to ban a member from the server."""
@ -63,18 +210,6 @@ class ModerationCog(commands.Cog):
response = await self._fake_moderation_response("ban", member.mention, reason, duration)
await ctx.reply(response)
@app_commands.command(name="ban", description="Pretends to ban a member from the server")
@app_commands.describe(
member="The member to ban",
duration="The duration of the ban (e.g., '1d', '7d')",
reason="The reason for the ban"
)
async def ban_slash(self, interaction: discord.Interaction, member: discord.Member, duration: str = None, reason: str = None):
"""Slash command version of ban."""
response = await self._fake_moderation_response("ban", member.mention, reason, duration)
await interaction.response.send_message(response)
# --- Kick Commands ---
@commands.command(name="kick")
async def kick(self, ctx: commands.Context, member: discord.Member = None, *, reason: str = None):
"""Pretends to kick a member from the server."""
@ -85,17 +220,6 @@ class ModerationCog(commands.Cog):
response = await self._fake_moderation_response("kick", member.mention, reason)
await ctx.reply(response)
@app_commands.command(name="kick", description="Pretends to kick a member from the server")
@app_commands.describe(
member="The member to kick",
reason="The reason for the kick"
)
async def kick_slash(self, interaction: discord.Interaction, member: discord.Member, reason: str = None):
"""Slash command version of kick."""
response = await self._fake_moderation_response("kick", member.mention, reason)
await interaction.response.send_message(response)
# --- Mute Commands ---
@commands.command(name="mute")
async def mute(self, ctx: commands.Context, member: discord.Member = None, duration: str = None, *, reason: str = None):
"""Pretends to mute a member in the server."""
@ -106,18 +230,6 @@ class ModerationCog(commands.Cog):
response = await self._fake_moderation_response("mute", member.mention, reason, duration)
await ctx.reply(response)
@app_commands.command(name="mute", description="Pretends to mute a member in the server")
@app_commands.describe(
member="The member to mute",
duration="The duration of the mute (e.g., '1h', '30m')",
reason="The reason for the mute"
)
async def mute_slash(self, interaction: discord.Interaction, member: discord.Member, duration: str = None, reason: str = None):
"""Slash command version of mute."""
response = await self._fake_moderation_response("mute", member.mention, reason, duration)
await interaction.response.send_message(response)
# --- Timeout Commands ---
@commands.command(name="timeout")
async def timeout(self, ctx: commands.Context, member: discord.Member = None, duration: str = None, *, reason: str = None):
"""Pretends to timeout a member in the server."""
@ -128,18 +240,6 @@ class ModerationCog(commands.Cog):
response = await self._fake_moderation_response("timeout", member.mention, reason, duration)
await ctx.reply(response)
@app_commands.command(name="timeout", description="Pretends to timeout a member in the server")
@app_commands.describe(
member="The member to timeout",
duration="The duration of the timeout (e.g., '1h', '30m')",
reason="The reason for the timeout"
)
async def timeout_slash(self, interaction: discord.Interaction, member: discord.Member, duration: str = None, reason: str = None):
"""Slash command version of timeout."""
response = await self._fake_moderation_response("timeout", member.mention, reason, duration)
await interaction.response.send_message(response)
# --- Warn Commands ---
@commands.command(name="warn")
async def warn(self, ctx: commands.Context, member: discord.Member = None, *, reason: str = None):
"""Pretends to warn a member in the server."""
@ -150,17 +250,6 @@ class ModerationCog(commands.Cog):
response = await self._fake_moderation_response("warn", member.mention, reason)
await ctx.reply(response)
@app_commands.command(name="warn", description="Pretends to warn a member in the server")
@app_commands.describe(
member="The member to warn",
reason="The reason for the warning"
)
async def warn_slash(self, interaction: discord.Interaction, member: discord.Member, reason: str = None):
"""Slash command version of warn."""
response = await self._fake_moderation_response("warn", member.mention, reason)
await interaction.response.send_message(response)
# --- Unban Commands ---
@commands.command(name="unban")
async def unban(self, ctx: commands.Context, user: str = None, *, reason: str = None):
"""Pretends to unban a user from the server."""
@ -172,17 +261,6 @@ class ModerationCog(commands.Cog):
response = await self._fake_moderation_response("unban", user, reason)
await ctx.reply(response)
@app_commands.command(name="unban", description="Pretends to unban a user from the server")
@app_commands.describe(
user="The user to unban (username or ID)",
reason="The reason for the unban"
)
async def unban_slash(self, interaction: discord.Interaction, user: str, reason: str = None):
"""Slash command version of unban."""
response = await self._fake_moderation_response("unban", user, reason)
await interaction.response.send_message(response)
# --- Unmute Commands ---
@commands.command(name="unmute")
async def unmute(self, ctx: commands.Context, member: discord.Member = None, *, reason: str = None):
"""Pretends to unmute a member in the server."""
@ -193,19 +271,9 @@ class ModerationCog(commands.Cog):
response = await self._fake_moderation_response("unmute", member.mention, reason)
await ctx.reply(response)
@app_commands.command(name="unmute", description="Pretends to unmute a member in the server")
@app_commands.describe(
member="The member to unmute",
reason="The reason for the unmute"
)
async def unmute_slash(self, interaction: discord.Interaction, member: discord.Member, reason: str = None):
"""Slash command version of unmute."""
response = await self._fake_moderation_response("unmute", member.mention, reason)
await interaction.response.send_message(response)
@commands.Cog.listener()
async def on_ready(self):
print(f'{self.__class__.__name__} cog has been loaded.')
async def setup(bot: commands.Bot):
await bot.add_cog(ModerationCog(bot))
await bot.add_cog(FakeModerationCog(bot))

484
cogs/real_moderation_cog.py Normal file
View File

@ -0,0 +1,484 @@
import discord
from discord.ext import commands
from discord import app_commands
import datetime
import logging
from typing import Optional, Union, List
# Configure logging
logger = logging.getLogger(__name__)
class ModerationCog(commands.Cog):
"""Real moderation commands that perform actual moderation actions."""
def __init__(self, bot):
self.bot = bot
# Create the main command group for this cog
self.moderate_group = app_commands.Group(
name="moderate",
description="Moderation commands for server management"
)
# Register commands
self.register_commands()
# Add command group to the bot's tree
self.bot.tree.add_command(self.moderate_group)
def register_commands(self):
"""Register all commands for this cog"""
# --- Ban Command ---
ban_command = app_commands.Command(
name="ban",
description="Ban a member from the server",
callback=self.moderate_ban_callback,
parent=self.moderate_group
)
app_commands.describe(
member="The member to ban",
reason="The reason for the ban",
delete_days="Number of days of messages to delete (0-7)"
)(ban_command)
self.moderate_group.add_command(ban_command)
# --- Unban Command ---
unban_command = app_commands.Command(
name="unban",
description="Unban a user from the server",
callback=self.moderate_unban_callback,
parent=self.moderate_group
)
app_commands.describe(
user_id="The ID of the user to unban",
reason="The reason for the unban"
)(unban_command)
self.moderate_group.add_command(unban_command)
# --- Kick Command ---
kick_command = app_commands.Command(
name="kick",
description="Kick a member from the server",
callback=self.moderate_kick_callback,
parent=self.moderate_group
)
app_commands.describe(
member="The member to kick",
reason="The reason for the kick"
)(kick_command)
self.moderate_group.add_command(kick_command)
# --- Timeout Command ---
timeout_command = app_commands.Command(
name="timeout",
description="Timeout a member in the server",
callback=self.moderate_timeout_callback,
parent=self.moderate_group
)
app_commands.describe(
member="The member to timeout",
duration="The duration of the timeout (e.g., '1d', '2h', '30m', '60s')",
reason="The reason for the timeout"
)(timeout_command)
self.moderate_group.add_command(timeout_command)
# --- Remove Timeout Command ---
remove_timeout_command = app_commands.Command(
name="removetimeout",
description="Remove a timeout from a member",
callback=self.moderate_remove_timeout_callback,
parent=self.moderate_group
)
app_commands.describe(
member="The member to remove timeout from",
reason="The reason for removing the timeout"
)(remove_timeout_command)
self.moderate_group.add_command(remove_timeout_command)
# --- Purge Command ---
purge_command = app_commands.Command(
name="purge",
description="Delete a specified number of messages from a channel",
callback=self.moderate_purge_callback,
parent=self.moderate_group
)
app_commands.describe(
amount="Number of messages to delete (1-100)",
user="Optional: Only delete messages from this user"
)(purge_command)
self.moderate_group.add_command(purge_command)
# --- Warn Command ---
warn_command = app_commands.Command(
name="warn",
description="Warn a member in the server",
callback=self.moderate_warn_callback,
parent=self.moderate_group
)
app_commands.describe(
member="The member to warn",
reason="The reason for the warning"
)(warn_command)
self.moderate_group.add_command(warn_command)
# Helper method for parsing duration strings
def _parse_duration(self, duration_str: str) -> Optional[datetime.timedelta]:
"""Parse a duration string like '1d', '2h', '30m' into a timedelta."""
if not duration_str:
return None
try:
# Extract the number and unit
amount = int(''.join(filter(str.isdigit, duration_str)))
unit = ''.join(filter(str.isalpha, duration_str)).lower()
if unit == 'd' or unit == 'day' or unit == 'days':
return datetime.timedelta(days=amount)
elif unit == 'h' or unit == 'hour' or unit == 'hours':
return datetime.timedelta(hours=amount)
elif unit == 'm' or unit == 'min' or unit == 'minute' or unit == 'minutes':
return datetime.timedelta(minutes=amount)
elif unit == 's' or unit == 'sec' or unit == 'second' or unit == 'seconds':
return datetime.timedelta(seconds=amount)
else:
return None
except (ValueError, TypeError):
return None
# --- Command Callbacks ---
async def moderate_ban_callback(self, interaction: discord.Interaction, member: discord.Member, reason: str = None, delete_days: int = 0):
"""Ban a member from the server."""
# Check if the user has permission to ban members
if not interaction.user.guild_permissions.ban_members:
await interaction.response.send_message("❌ You don't have permission to ban members.", ephemeral=True)
return
# Check if the bot has permission to ban members
if not interaction.guild.me.guild_permissions.ban_members:
await interaction.response.send_message("❌ I don't have permission to ban members.", ephemeral=True)
return
# Check if the user is trying to ban themselves
if member.id == interaction.user.id:
await interaction.response.send_message("❌ You cannot ban yourself.", ephemeral=True)
return
# Check if the user is trying to ban the bot
if member.id == self.bot.user.id:
await interaction.response.send_message("❌ I cannot ban myself.", ephemeral=True)
return
# Check if the user is trying to ban someone with a higher role
if interaction.user.top_role <= member.top_role and interaction.user.id != interaction.guild.owner_id:
await interaction.response.send_message("❌ You cannot ban someone with a higher or equal role.", ephemeral=True)
return
# Check if the bot can ban the member (role hierarchy)
if interaction.guild.me.top_role <= member.top_role:
await interaction.response.send_message("❌ I cannot ban someone with a higher or equal role than me.", ephemeral=True)
return
# Ensure delete_days is within valid range (0-7)
delete_days = max(0, min(7, delete_days))
# Perform the ban
try:
await member.ban(reason=reason, delete_message_days=delete_days)
# Log the action
logger.info(f"User {member} (ID: {member.id}) was banned from {interaction.guild.name} (ID: {interaction.guild.id}) by {interaction.user} (ID: {interaction.user.id}). Reason: {reason}")
# Send confirmation message
await interaction.response.send_message(f"🔨 **Banned {member.mention}**! Reason: {reason or 'No reason provided'}")
except discord.Forbidden:
await interaction.response.send_message("❌ I don't have permission to ban this member.", ephemeral=True)
except discord.HTTPException as e:
await interaction.response.send_message(f"❌ An error occurred while banning the member: {e}", ephemeral=True)
async def moderate_unban_callback(self, interaction: discord.Interaction, user_id: str, reason: str = None):
"""Unban a user from the server."""
# Check if the user has permission to ban members (which includes unbanning)
if not interaction.user.guild_permissions.ban_members:
await interaction.response.send_message("❌ You don't have permission to unban users.", ephemeral=True)
return
# Check if the bot has permission to ban members (which includes unbanning)
if not interaction.guild.me.guild_permissions.ban_members:
await interaction.response.send_message("❌ I don't have permission to unban users.", ephemeral=True)
return
# Validate user ID
try:
user_id_int = int(user_id)
except ValueError:
await interaction.response.send_message("❌ Invalid user ID. Please provide a valid user ID.", ephemeral=True)
return
# Check if the user is banned
try:
ban_entry = await interaction.guild.fetch_ban(discord.Object(id=user_id_int))
banned_user = ban_entry.user
except discord.NotFound:
await interaction.response.send_message("❌ This user is not banned.", ephemeral=True)
return
except discord.Forbidden:
await interaction.response.send_message("❌ I don't have permission to view the ban list.", ephemeral=True)
return
except discord.HTTPException as e:
await interaction.response.send_message(f"❌ An error occurred while checking the ban list: {e}", ephemeral=True)
return
# Perform the unban
try:
await interaction.guild.unban(banned_user, reason=reason)
# Log the action
logger.info(f"User {banned_user} (ID: {banned_user.id}) was unbanned from {interaction.guild.name} (ID: {interaction.guild.id}) by {interaction.user} (ID: {interaction.user.id}). Reason: {reason}")
# Send confirmation message
await interaction.response.send_message(f"🔓 **Unbanned {banned_user}**! Reason: {reason or 'No reason provided'}")
except discord.Forbidden:
await interaction.response.send_message("❌ I don't have permission to unban this user.", ephemeral=True)
except discord.HTTPException as e:
await interaction.response.send_message(f"❌ An error occurred while unbanning the user: {e}", ephemeral=True)
async def moderate_kick_callback(self, interaction: discord.Interaction, member: discord.Member, reason: str = None):
"""Kick a member from the server."""
# Check if the user has permission to kick members
if not interaction.user.guild_permissions.kick_members:
await interaction.response.send_message("❌ You don't have permission to kick members.", ephemeral=True)
return
# Check if the bot has permission to kick members
if not interaction.guild.me.guild_permissions.kick_members:
await interaction.response.send_message("❌ I don't have permission to kick members.", ephemeral=True)
return
# Check if the user is trying to kick themselves
if member.id == interaction.user.id:
await interaction.response.send_message("❌ You cannot kick yourself.", ephemeral=True)
return
# Check if the user is trying to kick the bot
if member.id == self.bot.user.id:
await interaction.response.send_message("❌ I cannot kick myself.", ephemeral=True)
return
# Check if the user is trying to kick someone with a higher role
if interaction.user.top_role <= member.top_role and interaction.user.id != interaction.guild.owner_id:
await interaction.response.send_message("❌ You cannot kick someone with a higher or equal role.", ephemeral=True)
return
# Check if the bot can kick the member (role hierarchy)
if interaction.guild.me.top_role <= member.top_role:
await interaction.response.send_message("❌ I cannot kick someone with a higher or equal role than me.", ephemeral=True)
return
# Perform the kick
try:
await member.kick(reason=reason)
# Log the action
logger.info(f"User {member} (ID: {member.id}) was kicked from {interaction.guild.name} (ID: {interaction.guild.id}) by {interaction.user} (ID: {interaction.user.id}). Reason: {reason}")
# Send confirmation message
await interaction.response.send_message(f"👢 **Kicked {member.mention}**! Reason: {reason or 'No reason provided'}")
except discord.Forbidden:
await interaction.response.send_message("❌ I don't have permission to kick this member.", ephemeral=True)
except discord.HTTPException as e:
await interaction.response.send_message(f"❌ An error occurred while kicking the member: {e}", ephemeral=True)
async def moderate_timeout_callback(self, interaction: discord.Interaction, member: discord.Member, duration: str, reason: str = None):
"""Timeout a member in the server."""
# Check if the user has permission to moderate members
if not interaction.user.guild_permissions.moderate_members:
await interaction.response.send_message("❌ You don't have permission to timeout members.", ephemeral=True)
return
# Check if the bot has permission to moderate members
if not interaction.guild.me.guild_permissions.moderate_members:
await interaction.response.send_message("❌ I don't have permission to timeout members.", ephemeral=True)
return
# Check if the user is trying to timeout themselves
if member.id == interaction.user.id:
await interaction.response.send_message("❌ You cannot timeout yourself.", ephemeral=True)
return
# Check if the user is trying to timeout the bot
if member.id == self.bot.user.id:
await interaction.response.send_message("❌ I cannot timeout myself.", ephemeral=True)
return
# Check if the user is trying to timeout someone with a higher role
if interaction.user.top_role <= member.top_role and interaction.user.id != interaction.guild.owner_id:
await interaction.response.send_message("❌ You cannot timeout someone with a higher or equal role.", ephemeral=True)
return
# Check if the bot can timeout the member (role hierarchy)
if interaction.guild.me.top_role <= member.top_role:
await interaction.response.send_message("❌ I cannot timeout someone with a higher or equal role than me.", ephemeral=True)
return
# Parse the duration
delta = self._parse_duration(duration)
if not delta:
await interaction.response.send_message("❌ Invalid duration format. Please use formats like '1d', '2h', '30m', or '60s'.", ephemeral=True)
return
# Check if the duration is within Discord's limits (max 28 days)
max_timeout = datetime.timedelta(days=28)
if delta > max_timeout:
await interaction.response.send_message("❌ Timeout duration cannot exceed 28 days.", ephemeral=True)
return
# Calculate the end time
until = discord.utils.utcnow() + delta
# Perform the timeout
try:
await member.timeout(until, reason=reason)
# Log the action
logger.info(f"User {member} (ID: {member.id}) was timed out in {interaction.guild.name} (ID: {interaction.guild.id}) by {interaction.user} (ID: {interaction.user.id}) for {duration}. Reason: {reason}")
# Send confirmation message
await interaction.response.send_message(f"⏰ **Timed out {member.mention}** for {duration}! Reason: {reason or 'No reason provided'}")
except discord.Forbidden:
await interaction.response.send_message("❌ I don't have permission to timeout this member.", ephemeral=True)
except discord.HTTPException as e:
await interaction.response.send_message(f"❌ An error occurred while timing out the member: {e}", ephemeral=True)
async def moderate_remove_timeout_callback(self, interaction: discord.Interaction, member: discord.Member, reason: str = None):
"""Remove a timeout from a member."""
# Check if the user has permission to moderate members
if not interaction.user.guild_permissions.moderate_members:
await interaction.response.send_message("❌ You don't have permission to remove timeouts.", ephemeral=True)
return
# Check if the bot has permission to moderate members
if not interaction.guild.me.guild_permissions.moderate_members:
await interaction.response.send_message("❌ I don't have permission to remove timeouts.", ephemeral=True)
return
# Check if the member is timed out
if not member.timed_out_until:
await interaction.response.send_message("❌ This member is not timed out.", ephemeral=True)
return
# Perform the timeout removal
try:
await member.timeout(None, reason=reason)
# Log the action
logger.info(f"Timeout was removed from user {member} (ID: {member.id}) in {interaction.guild.name} (ID: {interaction.guild.id}) by {interaction.user} (ID: {interaction.user.id}). Reason: {reason}")
# Send confirmation message
await interaction.response.send_message(f"⏰ **Removed timeout from {member.mention}**! Reason: {reason or 'No reason provided'}")
except discord.Forbidden:
await interaction.response.send_message("❌ I don't have permission to remove the timeout from this member.", ephemeral=True)
except discord.HTTPException as e:
await interaction.response.send_message(f"❌ An error occurred while removing the timeout: {e}", ephemeral=True)
async def moderate_purge_callback(self, interaction: discord.Interaction, amount: int, user: Optional[discord.Member] = None):
"""Delete a specified number of messages from a channel."""
# Check if the user has permission to manage messages
if not interaction.user.guild_permissions.manage_messages:
await interaction.response.send_message("❌ You don't have permission to purge messages.", ephemeral=True)
return
# Check if the bot has permission to manage messages
if not interaction.guild.me.guild_permissions.manage_messages:
await interaction.response.send_message("❌ I don't have permission to purge messages.", ephemeral=True)
return
# Validate the amount
if amount < 1 or amount > 100:
await interaction.response.send_message("❌ You can only purge between 1 and 100 messages at a time.", ephemeral=True)
return
# Defer the response since this might take a moment
await interaction.response.defer(ephemeral=True)
# Perform the purge
try:
if user:
# Delete messages from a specific user
def check(message):
return message.author.id == user.id
deleted = await interaction.channel.purge(limit=amount, check=check)
# Log the action
logger.info(f"{len(deleted)} messages from user {user} (ID: {user.id}) were purged from channel {interaction.channel.name} (ID: {interaction.channel.id}) in {interaction.guild.name} (ID: {interaction.guild.id}) by {interaction.user} (ID: {interaction.user.id}).")
# Send confirmation message
await interaction.followup.send(f"🧹 **Purged {len(deleted)} messages** from {user.mention}!", ephemeral=True)
else:
# Delete messages from anyone
deleted = await interaction.channel.purge(limit=amount)
# Log the action
logger.info(f"{len(deleted)} messages were purged from channel {interaction.channel.name} (ID: {interaction.channel.id}) in {interaction.guild.name} (ID: {interaction.guild.id}) by {interaction.user} (ID: {interaction.user.id}).")
# Send confirmation message
await interaction.followup.send(f"🧹 **Purged {len(deleted)} messages**!", ephemeral=True)
except discord.Forbidden:
await interaction.followup.send("❌ I don't have permission to delete messages in this channel.", ephemeral=True)
except discord.HTTPException as e:
await interaction.followup.send(f"❌ An error occurred while purging messages: {e}", ephemeral=True)
async def moderate_warn_callback(self, interaction: discord.Interaction, member: discord.Member, reason: str):
"""Warn a member in the server."""
# Check if the user has permission to kick members (using kick permission as a baseline for warning)
if not interaction.user.guild_permissions.kick_members:
await interaction.response.send_message("❌ You don't have permission to warn members.", ephemeral=True)
return
# Check if the user is trying to warn themselves
if member.id == interaction.user.id:
await interaction.response.send_message("❌ You cannot warn yourself.", ephemeral=True)
return
# Check if the user is trying to warn the bot
if member.id == self.bot.user.id:
await interaction.response.send_message("❌ I cannot warn myself.", ephemeral=True)
return
# Check if the user is trying to warn someone with a higher role
if interaction.user.top_role <= member.top_role and interaction.user.id != interaction.guild.owner_id:
await interaction.response.send_message("❌ You cannot warn someone with a higher or equal role.", ephemeral=True)
return
# Log the warning
logger.info(f"User {member} (ID: {member.id}) was warned in {interaction.guild.name} (ID: {interaction.guild.id}) by {interaction.user} (ID: {interaction.user.id}). Reason: {reason}")
# Send warning message in the channel
await interaction.response.send_message(f"⚠️ **{member.mention} has been warned**! Reason: {reason}")
# Try to DM the user about the warning
try:
embed = discord.Embed(
title="Warning Notice",
description=f"You have been warned in **{interaction.guild.name}**",
color=discord.Color.yellow()
)
embed.add_field(name="Reason", value=reason, inline=False)
embed.add_field(name="Moderator", value=interaction.user.name, inline=False)
embed.set_footer(text=f"Server ID: {interaction.guild.id}{discord.utils.utcnow().strftime('%Y-%m-%d %H:%M:%S')} UTC")
await member.send(embed=embed)
except discord.Forbidden:
# User has DMs closed, ignore
pass
except Exception as e:
logger.error(f"Error sending warning DM to {member} (ID: {member.id}): {e}")
@commands.Cog.listener()
async def on_ready(self):
print(f'{self.__class__.__name__} cog has been loaded.')
async def setup(bot: commands.Bot):
await bot.add_cog(ModerationCog(bot))