Add kick and timeout actions to AI mod panel

This commit is contained in:
Codex 2025-06-06 18:01:01 +00:00 committed by Slipstream
parent e57dc63e80
commit 0f5b18d0f9
Signed by: slipstream
GPG Key ID: 13E498CE010AC6FD

View File

@ -277,6 +277,144 @@ class AIModerationCog(commands.Cog):
super().__init__(timeout=3600)
self.parent = parent
self.target = target
self.message: discord.Message | None = None
# --- Helper Modals ---
class BanModal(discord.ui.Modal, title="Ban User"):
reason = discord.ui.TextInput(
label="Reason",
placeholder="Reason for ban",
style=discord.TextStyle.paragraph,
required=False,
max_length=512,
)
def __init__(self, view: "AIModerationCog.QuickActionView"):
super().__init__()
self.view = view
async def on_submit(self, interaction: discord.Interaction):
if not interaction.user.guild_permissions.ban_members:
await interaction.response.send_message(
"You lack permission to ban members.", ephemeral=True
)
return
try:
await self.view.target.ban(
reason=self.reason.value or "Escalated via mod panel"
)
await interaction.response.send_message(
f"Banned {self.view.target.mention}.", ephemeral=True
)
except Exception as e: # noqa: BLE001
await interaction.response.send_message(
f"Failed to ban: {e}", ephemeral=True
)
self.view.disable_all_items()
if self.view.message:
await self.view.message.edit(view=self.view)
class KickModal(discord.ui.Modal, title="Kick User"):
reason = discord.ui.TextInput(
label="Reason",
placeholder="Reason for kick",
style=discord.TextStyle.paragraph,
required=False,
max_length=512,
)
def __init__(self, view: "AIModerationCog.QuickActionView"):
super().__init__()
self.view = view
async def on_submit(self, interaction: discord.Interaction):
if not interaction.user.guild_permissions.kick_members:
await interaction.response.send_message(
"You lack permission to kick members.", ephemeral=True
)
return
try:
await self.view.target.kick(
reason=self.reason.value or "Escalated via mod panel"
)
await interaction.response.send_message(
f"Kicked {self.view.target.mention}.", ephemeral=True
)
except Exception as e: # noqa: BLE001
await interaction.response.send_message(
f"Failed to kick: {e}", ephemeral=True
)
self.view.disable_all_items()
if self.view.message:
await self.view.message.edit(view=self.view)
class TimeoutModal(discord.ui.Modal, title="Timeout User"):
duration = discord.ui.TextInput(
label="Duration",
placeholder="e.g. 10m, 1h, 1d",
required=True,
max_length=10,
)
reason = discord.ui.TextInput(
label="Reason",
placeholder="Reason for timeout",
style=discord.TextStyle.paragraph,
required=False,
max_length=512,
)
def __init__(self, view: "AIModerationCog.QuickActionView"):
super().__init__()
self.view = view
@staticmethod
def parse_duration(duration_str: str) -> datetime.timedelta | None:
if not duration_str:
return None
try:
amount = int("".join(filter(str.isdigit, duration_str)))
unit = "".join(filter(str.isalpha, duration_str)).lower()
if unit in {"d", "day", "days"}:
return datetime.timedelta(days=amount)
if unit in {"h", "hour", "hours"}:
return datetime.timedelta(hours=amount)
if unit in {"m", "min", "minute", "minutes"}:
return datetime.timedelta(minutes=amount)
if unit in {"s", "sec", "second", "seconds"}:
return datetime.timedelta(seconds=amount)
except (ValueError, TypeError):
return None
return None
async def on_submit(self, interaction: discord.Interaction):
if not interaction.user.guild_permissions.moderate_members:
await interaction.response.send_message(
"You lack permission to timeout members.", ephemeral=True
)
return
delta = self.parse_duration(self.duration.value)
if not delta or delta > datetime.timedelta(days=28):
await interaction.response.send_message(
"Invalid duration. Use formats like '10m', '1h', '1d'",
ephemeral=True,
)
return
try:
until = discord.utils.utcnow() + delta
await self.view.target.timeout(
until, reason=self.reason.value or "Escalated via mod panel"
)
await interaction.response.send_message(
f"Timed out {self.view.target.mention} for {self.duration.value}.",
ephemeral=True,
)
except Exception as e: # noqa: BLE001
await interaction.response.send_message(
f"Failed to timeout: {e}", ephemeral=True
)
self.view.disable_all_items()
if self.view.message:
await self.view.message.edit(view=self.view)
@discord.ui.button(label="Escalate Ban", style=discord.ButtonStyle.danger)
async def escalate(
@ -287,17 +425,32 @@ class AIModerationCog(commands.Cog):
"You lack permission to ban members.", ephemeral=True
)
return
try:
await self.target.ban(reason="Escalated via mod panel")
self.message = interaction.message
await interaction.response.send_modal(self.BanModal(self))
@discord.ui.button(label="Kick", style=discord.ButtonStyle.primary)
async def kick(
self, interaction: discord.Interaction, button: discord.ui.Button
):
if not interaction.user.guild_permissions.kick_members:
await interaction.response.send_message(
f"Banned {self.target.mention}.", ephemeral=True
"You lack permission to kick members.", ephemeral=True
)
except Exception as e: # noqa: BLE001
return
self.message = interaction.message
await interaction.response.send_modal(self.KickModal(self))
@discord.ui.button(label="Timeout", style=discord.ButtonStyle.secondary)
async def timeout(
self, interaction: discord.Interaction, button: discord.ui.Button
):
if not interaction.user.guild_permissions.moderate_members:
await interaction.response.send_message(
f"Failed to ban: {e}", ephemeral=True
"You lack permission to timeout members.", ephemeral=True
)
self.disable_all_items()
await interaction.message.edit(view=self)
return
self.message = interaction.message
await interaction.response.send_modal(self.TimeoutModal(self))
@discord.ui.button(label="Ignore", style=discord.ButtonStyle.secondary)
async def ignore(