From 4d2ef6fa82385d33b853065c1e6629bfa8d2768f Mon Sep 17 00:00:00 2001 From: Lilac-Rose Date: Sat, 4 Oct 2025 23:30:21 +0200 Subject: [PATCH] Updated moderation files to fixed 'interaction failed' on action confirm --- moderation/ban.py | 40 ++++++++++++++++---------------- moderation/kick.py | 40 ++++++++++++++++---------------- moderation/mute.py | 57 ++++++++++++++++++++++------------------------ moderation/warn.py | 38 +++++++++++++++---------------- 4 files changed, 84 insertions(+), 91 deletions(-) diff --git a/moderation/ban.py b/moderation/ban.py index 5e777eb..8a9f6aa 100644 --- a/moderation/ban.py +++ b/moderation/ban.py @@ -1,7 +1,7 @@ import discord from discord.ext import commands -from .loader import ModerationBase from discord.ui import View, Button +from .loader import ModerationBase class BanCommand(ModerationBase): @@ -12,44 +12,42 @@ class BanCommand(ModerationBase): view = View(timeout=30) confirmed = {"value": False} - async def yes_callback(interaction): + async def yes_callback(interaction: discord.Interaction): + if interaction.user != ctx.author: + await interaction.response.send_message("You can’t confirm this action.", ephemeral=True) + return confirmed["value"] = True + await interaction.response.edit_message(content="✅ Confirmed.", view=None) view.stop() - await interaction.response.edit_message(content="Confirmed.", view=None) - async def no_callback(interaction): + async def no_callback(interaction: discord.Interaction): + if interaction.user != ctx.author: + await interaction.response.send_message("You can’t cancel this action.", ephemeral=True) + return confirmed["value"] = False + await interaction.response.edit_message(content="❌ Cancelled.", view=None) view.stop() - await interaction.response.edit_message(content="Cancelled.", view=None) - view.add_item(Button(label="Yes", style=discord.ButtonStyle.green, custom_id="yes")) - view.add_item(Button(label="No", style=discord.ButtonStyle.red, custom_id="no")) + yes_button = Button(label="Yes", style=discord.ButtonStyle.green) + no_button = Button(label="No", style=discord.ButtonStyle.red) + yes_button.callback = yes_callback + no_button.callback = no_callback - async def button_listener(interaction): - if interaction.custom_id == "yes": - await yes_callback(interaction) - else: - await no_callback(interaction) + view.add_item(yes_button) + view.add_item(no_button) - for item in view.children: - item.callback = button_listener - - await ctx.send(f"Are you sure you want to ban {user.mention}? Reason: {reason}", view=view) + await ctx.send(f"Are you sure you want to ban {user.mention}? Reason: {reason or 'No reason provided'}", view=view) await view.wait() if not confirmed["value"]: return - # DM user try: - await user.send(f"You have been **banned** in {ctx.guild.name}. Reason: {reason or 'No reason provided'}") + await user.send(f"You have been **banned** from **{ctx.guild.name}**.\nReason: {reason or 'No reason provided'}") except: await ctx.send("Could not DM the user.") - # Ban await ctx.guild.ban(user, reason=reason) await ctx.send(f"{user.mention} has been banned.") - - # Log infraction await self.log_infraction(ctx.guild.id, user.id, ctx.author.id, "ban", reason) async def setup(bot: commands.Bot): diff --git a/moderation/kick.py b/moderation/kick.py index 501da4b..a056876 100644 --- a/moderation/kick.py +++ b/moderation/kick.py @@ -1,7 +1,7 @@ import discord from discord.ext import commands -from .loader import ModerationBase from discord.ui import View, Button +from .loader import ModerationBase class KickCommand(ModerationBase): @@ -12,44 +12,42 @@ class KickCommand(ModerationBase): view = View(timeout=30) confirmed = {"value": False} - async def yes_callback(interaction): + async def yes_callback(interaction: discord.Interaction): + if interaction.user != ctx.author: + await interaction.response.send_message("You can’t confirm this action.", ephemeral=True) + return confirmed["value"] = True + await interaction.response.edit_message(content="✅ Confirmed.", view=None) view.stop() - await interaction.response.edit_message(content="Confirmed.", view=None) - async def no_callback(interaction): + async def no_callback(interaction: discord.Interaction): + if interaction.user != ctx.author: + await interaction.response.send_message("You can’t cancel this action.", ephemeral=True) + return confirmed["value"] = False + await interaction.response.edit_message(content="❌ Cancelled.", view=None) view.stop() - await interaction.response.edit_message(content="Cancelled.", view=None) - view.add_item(Button(label="Yes", style=discord.ButtonStyle.green, custom_id="yes")) - view.add_item(Button(label="No", style=discord.ButtonStyle.red, custom_id="no")) + yes_button = Button(label="Yes", style=discord.ButtonStyle.green) + no_button = Button(label="No", style=discord.ButtonStyle.red) + yes_button.callback = yes_callback + no_button.callback = no_callback - async def button_listener(interaction): - if interaction.custom_id == "yes": - await yes_callback(interaction) - else: - await no_callback(interaction) + view.add_item(yes_button) + view.add_item(no_button) - for item in view.children: - item.callback = button_listener - - await ctx.send(f"Are you sure you want to kick {user.mention}? Reason: {reason}", view=view) + await ctx.send(f"Are you sure you want to kick {user.mention}? Reason: {reason or 'No reason provided'}", view=view) await view.wait() if not confirmed["value"]: return - # DM user try: - await user.send(f"You have been **kicked** from {ctx.guild.name}. Reason: {reason or 'No reason provided'}") + await user.send(f"You have been **kicked** from **{ctx.guild.name}**.\nReason: {reason or 'No reason provided'}") except: await ctx.send("Could not DM the user.") - # Kick await ctx.guild.kick(user, reason=reason) await ctx.send(f"{user.mention} has been kicked.") - - # Log infraction await self.log_infraction(ctx.guild.id, user.id, ctx.author.id, "kick", reason) async def setup(bot: commands.Bot): diff --git a/moderation/mute.py b/moderation/mute.py index 0a0f90e..f0267e7 100644 --- a/moderation/mute.py +++ b/moderation/mute.py @@ -1,10 +1,10 @@ import discord -from discord.ext import commands, tasks -from .loader import ModerationBase +from discord.ext import commands from discord.ui import View, Button import asyncio import re -from datetime import datetime, timedelta +from datetime import timedelta +from .loader import ModerationBase MUTE_ROLE_ID = 982702037517090836 @@ -17,8 +17,9 @@ class MuteCommand(ModerationBase): # Parse duration match = re.match(r"(\d+)([wdh])", duration.lower()) if not match: - await ctx.send("Invalid duration format. Use 1w, 5d, 48h etc.") + await ctx.send("Invalid duration format. Use **1w**, **5d**, **48h**, etc.") return + value, unit = match.groups() value = int(value) if unit == "w": @@ -27,68 +28,64 @@ class MuteCommand(ModerationBase): delta = timedelta(days=value) elif unit == "h": delta = timedelta(hours=value) - else: - await ctx.send("Unknown time unit. Use w, d, or h.") - return view = View(timeout=30) confirmed = {"value": False} - async def yes_callback(interaction): + async def yes_callback(interaction: discord.Interaction): + if interaction.user != ctx.author: + await interaction.response.send_message("You can’t confirm this action.", ephemeral=True) + return confirmed["value"] = True + await interaction.response.edit_message(content="✅ Confirmed.", view=None) view.stop() - await interaction.response.edit_message(content="Confirmed", view=None) - async def no_callback(interaction): + async def no_callback(interaction: discord.Interaction): + if interaction.user != ctx.author: + await interaction.response.send_message("You can’t cancel this action.", ephemeral=True) + return confirmed["value"] = False + await interaction.response.edit_message(content="❌ Cancelled.", view=None) view.stop() - await interaction.response.edit_message(content="Cancelled", view=None) - view.add_item(Button(label="Yes", style=discord.ButtonStyle.green, custom_id="yes")) - view.add_item(Button(label="No", style=discord.ButtonStyle.red, custom_id="no")) + yes_button = Button(label="Yes", style=discord.ButtonStyle.green) + no_button = Button(label="No", style=discord.ButtonStyle.red) + yes_button.callback = yes_callback + no_button.callback = no_callback - async def button_listener(interaction): - if interaction.custom_id == "yes": - await yes_callback(interaction) - else: - await no_callback(interaction) + view.add_item(yes_button) + view.add_item(no_button) - for item in view.children: - item.callback = button_listener - - await ctx.send(f"Are you sure you want to mute {user.mention} for {duration}? Reason: {reason}", view=view) + await ctx.send(f"Are you sure you want to mute {user.mention} for **{duration}**? Reason: {reason or 'No reason provided'}", view=view) await view.wait() if not confirmed["value"]: return - # Add role mute_role = ctx.guild.get_role(MUTE_ROLE_ID) if not mute_role: await ctx.send("Mute role not found in server.") return + await user.add_roles(mute_role, reason=reason) - # DM user try: - await user.send(f"You have been muted in {ctx.guild.name} for {duration}. Reason: {reason or 'No reason provided'}") + await user.send(f"You have been muted in **{ctx.guild.name}** for **{duration}**.\nReason: {reason or 'No reason provided'}") except: await ctx.send("Could not DM the user.") - # Log infraction await self.log_infraction(ctx.guild.id, user.id, ctx.author.id, "mute", reason) - - await ctx.send(f"{user.mention} has been muted for {duration}") + await ctx.send(f"{user.mention} has been muted for **{duration}**.") # Schedule unmute async def unmute_later(): await asyncio.sleep(delta.total_seconds()) try: await user.remove_roles(mute_role, reason="Mute duration expired") - await ctx.send(f"{user.mention} has been unmuted (duration expired)") + await ctx.send(f"{user.mention} has been unmuted (duration expired).") except: pass asyncio.create_task(unmute_later()) async def setup(bot: commands.Bot): - await bot.add_cog(MuteCommand(bot)) \ No newline at end of file + await bot.add_cog(MuteCommand(bot)) diff --git a/moderation/warn.py b/moderation/warn.py index 4a9d094..49620ab 100644 --- a/moderation/warn.py +++ b/moderation/warn.py @@ -1,7 +1,7 @@ import discord from discord.ext import commands -from .loader import ModerationBase from discord.ui import View, Button +from .loader import ModerationBase class WarnCommand(ModerationBase): @@ -12,40 +12,40 @@ class WarnCommand(ModerationBase): view = View(timeout=30) confirmed = {"value": False} - async def yes_callback(interaction): + async def yes_callback(interaction: discord.Interaction): + if interaction.user != ctx.author: + await interaction.response.send_message("You can’t confirm this action.", ephemeral=True) + return confirmed["value"] = True + await interaction.response.edit_message(content="✅ Confirmed.", view=None) view.stop() - await interaction.response.edit_message(content="Confirmed.", view=None) - async def no_callback(interaction): + async def no_callback(interaction: discord.Interaction): + if interaction.user != ctx.author: + await interaction.response.send_message("You can’t cancel this action.", ephemeral=True) + return confirmed["value"] = False + await interaction.response.edit_message(content="❌ Cancelled.", view=None) view.stop() - await interaction.response.edit_message(content="Cancelled.", view=None) - view.add_item(Button(label="Yes", style=discord.ButtonStyle.green, custom_id="yes")) - view.add_item(Button(label="No", style=discord.ButtonStyle.red, custom_id="no")) + yes_button = Button(label="Yes", style=discord.ButtonStyle.green) + no_button = Button(label="No", style=discord.ButtonStyle.red) + yes_button.callback = yes_callback + no_button.callback = no_callback - async def button_listener(interaction): - if interaction.custom_id == "yes": - await yes_callback(interaction) - else: - await no_callback(interaction) + view.add_item(yes_button) + view.add_item(no_button) - for item in view.children: - item.callback = button_listener - - await ctx.send(f"Are you sure you want to warn {user.mention}? Reason: {reason}", view=view) + await ctx.send(f"Are you sure you want to warn {user.mention}? Reason: {reason or 'No reason provided'}", view=view) await view.wait() if not confirmed["value"]: return - # DM user try: - await user.send(f"You have been **warned** in {ctx.guild.name}. Reason: {reason or 'No reason provided'}") + await user.send(f"You have been **warned** in **{ctx.guild.name}**.\nReason: {reason or 'No reason provided'}") except: await ctx.send("Could not DM the user.") - # Log infraction await self.log_infraction(ctx.guild.id, user.id, ctx.author.id, "warn", reason) await ctx.send(f"{user.mention} has been warned.")