Migration de Kuby vers disnake

This commit is contained in:
Mathis 2026-05-06 17:07:09 +02:00
parent dc6e235f27
commit c8c579eefe
36 changed files with 1205 additions and 1253 deletions

View file

@ -1,18 +1,17 @@
import discord
from discord.ext import commands
from discord import app_commands
import disnake
from disnake.ext import commands
import sqlite3
import os
from datetime import datetime, timedelta
import re
class ModReasonModal(discord.ui.Modal):
class ModReasonModal(disnake.ui.Modal):
def __init__(self, parent_view, action_type):
super().__init__(title=f"Raison pour {action_type}")
self.parent_view = parent_view
self.action_type = action_type
self.reason = discord.ui.TextInput(
self.reason = disnake.ui.TextInput(
label="Raison",
placeholder="Entrez la raison ici...",
required=True,
@ -21,7 +20,7 @@ class ModReasonModal(discord.ui.Modal):
self.add_item(self.reason)
if action_type == "TIMEOUT":
self.duration = discord.ui.TextInput(
self.duration = disnake.ui.TextInput(
label="Durée (ex: 1h, 30m, 1d)",
placeholder="1h",
required=True,
@ -29,11 +28,11 @@ class ModReasonModal(discord.ui.Modal):
)
self.add_item(self.duration)
async def on_submit(self, interaction: discord.Interaction):
async def callback(self, interaction: disnake.Interaction):
reason = self.reason.value
member = self.parent_view.member
cog = interaction.client.get_cog("Moderation")
cog = interaction.bot.get_cog("Moderation")
if not cog:
return await interaction.response.send_message("❌ Erreur interne.", ephemeral=True)
@ -48,24 +47,24 @@ class ModReasonModal(discord.ui.Modal):
await self.parent_view.update_panel(interaction)
class ModPanelView(discord.ui.View):
class ModPanelView(disnake.ui.View):
def __init__(self, member, moderator, db_path):
super().__init__(timeout=120)
self.member = member
self.moderator = moderator
self.db_path = db_path
async def update_panel(self, interaction: discord.Interaction):
async def update_panel(self, interaction: disnake.Interaction):
conn = sqlite3.connect(self.db_path)
cursor = conn.cursor()
cursor.execute('SELECT COUNT(*) FROM sanctions WHERE guild_id = ? AND user_id = ? AND type = "WARN" AND status = "ACTIVE"', (interaction.guild_id, self.member.id))
warn_count = cursor.fetchone()[0]
conn.close()
embed = discord.Embed(
embed = disnake.Embed(
title=f"🛡️ Panel de Modération - {self.member.name}",
description=f"Gestion de l'utilisateur {self.member.mention}",
color=discord.Color.blue(),
color=disnake.Color.blue(),
timestamp=datetime.now()
)
embed.set_thumbnail(url=self.member.display_avatar.url)
@ -78,38 +77,38 @@ class ModPanelView(discord.ui.View):
else:
await interaction.edit_original_response(embed=embed, view=self)
@discord.ui.button(label="Avertir", style=discord.ButtonStyle.secondary, emoji="⚠️")
async def warn_btn(self, interaction: discord.Interaction, button: discord.ui.Button):
@disnake.ui.button(label="Avertir", style=disnake.ButtonStyle.secondary, emoji="⚠️")
async def warn_btn(self, interaction: disnake.Interaction, button: disnake.ui.Button):
await interaction.response.send_modal(ModReasonModal(self, "WARN"))
@discord.ui.button(label="Timeout", style=discord.ButtonStyle.secondary, emoji="")
async def timeout_btn(self, interaction: discord.Interaction, button: discord.ui.Button):
@disnake.ui.button(label="Timeout", style=disnake.ButtonStyle.secondary, emoji="")
async def timeout_btn(self, interaction: disnake.Interaction, button: disnake.ui.Button):
await interaction.response.send_modal(ModReasonModal(self, "TIMEOUT"))
@discord.ui.button(label="Expulser", style=discord.ButtonStyle.secondary, emoji="👢")
async def kick_btn(self, interaction: discord.Interaction, button: discord.ui.Button):
@disnake.ui.button(label="Expulser", style=disnake.ButtonStyle.secondary, emoji="👢")
async def kick_btn(self, interaction: disnake.Interaction, button: disnake.ui.Button):
await interaction.response.send_modal(ModReasonModal(self, "KICK"))
@discord.ui.button(label="Bannir", style=discord.ButtonStyle.danger, emoji="🔨")
async def ban_btn(self, interaction: discord.Interaction, button: discord.ui.Button):
@disnake.ui.button(label="Bannir", style=disnake.ButtonStyle.danger, emoji="🔨")
async def ban_btn(self, interaction: disnake.Interaction, button: disnake.ui.Button):
await interaction.response.send_modal(ModReasonModal(self, "BAN"))
@discord.ui.button(label="Historique", style=discord.ButtonStyle.primary, emoji="📜")
async def history_btn(self, interaction: discord.Interaction, button: discord.ui.Button):
cog = interaction.client.get_cog("Moderation")
@disnake.ui.button(label="Historique", style=disnake.ButtonStyle.primary, emoji="📜")
async def history_btn(self, interaction: disnake.Interaction, button: disnake.ui.Button):
cog = interaction.bot.get_cog("Moderation")
await cog.history(interaction, self.member)
@discord.ui.button(label="Clear Warns", style=discord.ButtonStyle.danger, emoji="🧹")
async def clear_btn(self, interaction: discord.Interaction, button: discord.ui.Button):
cog = interaction.client.get_cog("Moderation")
@disnake.ui.button(label="Clear Warns", style=disnake.ButtonStyle.danger, emoji="🧹")
async def clear_btn(self, interaction: disnake.Interaction, button: disnake.ui.Button):
cog = interaction.bot.get_cog("Moderation")
await cog.clearwarns(interaction, self.member, reason="Nettoyage via Panel")
await self.update_panel(interaction)
class ModConfigModal(discord.ui.Modal):
class ModConfigModal(disnake.ui.Modal):
def __init__(self, field_name, current_value):
super().__init__(title=f"Modifier {field_name}")
self.field_name = field_name
self.input = discord.ui.TextInput(
self.input = disnake.ui.TextInput(
label=field_name,
default=str(current_value),
placeholder="Entrez une valeur numérique...",
@ -117,9 +116,9 @@ class ModConfigModal(discord.ui.Modal):
)
self.add_item(self.input)
async def on_submit(self, interaction: discord.Interaction):
async def callback(self, interaction: disnake.Interaction):
value = self.input.value
cog = interaction.client.get_cog("Moderation")
cog = interaction.bot.get_cog("Moderation")
mapping = {
"Limite Timeout": "warn_limit_timeout",
@ -140,21 +139,21 @@ class ModConfigModal(discord.ui.Modal):
await interaction.response.send_message(f"{self.field_name} mis à jour sur **{value}**.", ephemeral=True)
class ModConfigView(discord.ui.View):
class ModConfigView(disnake.ui.View):
def __init__(self, guild_id, db_path):
super().__init__(timeout=60)
self.guild_id = guild_id
self.db_path = db_path
@discord.ui.button(label="Log Channel", style=discord.ButtonStyle.primary, emoji="📁")
async def log_btn(self, interaction: discord.Interaction, button: discord.ui.Button):
view = discord.ui.View()
select = discord.ui.ChannelSelect(
@disnake.ui.button(label="Log Channel", style=disnake.ButtonStyle.primary, emoji="📁")
async def log_btn(self, interaction: disnake.Interaction, button: disnake.ui.Button):
view = disnake.ui.View()
select = disnake.ui.ChannelSelect(
placeholder="Sélectionnez le salon de logs...",
channel_types=[discord.ChannelType.text]
channel_types=[disnake.ChannelType.text]
)
async def select_callback(interaction: discord.Interaction):
async def select_callback(interaction: disnake.Interaction):
channel = select.values[0]
conn = sqlite3.connect(self.db_path)
cursor = conn.cursor()
@ -166,29 +165,29 @@ class ModConfigView(discord.ui.View):
view.add_item(select)
await interaction.response.send_message("Choisissez le salon de logs :", view=view, ephemeral=True)
@discord.ui.button(label="Paliers Warns", style=discord.ButtonStyle.secondary, emoji="⚖️")
async def limits_btn(self, interaction: discord.Interaction, button: discord.ui.Button):
@disnake.ui.button(label="Paliers Warns", style=disnake.ButtonStyle.secondary, emoji="⚖️")
async def limits_btn(self, interaction: disnake.Interaction, button: disnake.ui.Button):
conn = sqlite3.connect(self.db_path)
cursor = conn.cursor()
cursor.execute("SELECT warn_limit_timeout, warn_limit_kick, warn_limit_ban FROM mod_config WHERE guild_id = ?", (self.guild_id,))
res = cursor.fetchone(); conn.close()
view = discord.ui.View()
view = disnake.ui.View()
btn_t = discord.ui.Button(label=f"Timeout ({res[0]})", style=discord.ButtonStyle.secondary)
btn_t = disnake.ui.Button(label=f"Timeout ({res[0]})", style=disnake.ButtonStyle.secondary)
btn_t.callback = lambda i: i.response.send_modal(ModConfigModal("Limite Timeout", res[0]))
btn_k = discord.ui.Button(label=f"Kick ({res[1]})", style=discord.ButtonStyle.secondary)
btn_k = disnake.ui.Button(label=f"Kick ({res[1]})", style=disnake.ButtonStyle.secondary)
btn_k.callback = lambda i: i.response.send_modal(ModConfigModal("Limite Kick", res[1]))
btn_b = discord.ui.Button(label=f"Ban ({res[2]})", style=discord.ButtonStyle.secondary)
btn_b = disnake.ui.Button(label=f"Ban ({res[2]})", style=disnake.ButtonStyle.secondary)
btn_b.callback = lambda i: i.response.send_modal(ModConfigModal("Limite Ban", res[2]))
view.add_item(btn_t); view.add_item(btn_k); view.add_item(btn_b)
await interaction.response.send_message("Quelle limite modifier ?", view=view, ephemeral=True)
@discord.ui.button(label="Durée Timeout", style=discord.ButtonStyle.secondary, emoji="⏱️")
async def duration_btn(self, interaction: discord.Interaction, button: discord.ui.Button):
@disnake.ui.button(label="Durée Timeout", style=disnake.ButtonStyle.secondary, emoji="⏱️")
async def duration_btn(self, interaction: disnake.Interaction, button: disnake.ui.Button):
conn = sqlite3.connect(self.db_path)
cursor = conn.cursor()
cursor.execute("SELECT timeout_duration FROM mod_config WHERE guild_id = ?", (self.guild_id,))
@ -225,38 +224,38 @@ class Moderation(commands.Cog):
log_channel = guild.get_channel(result[0])
if log_channel: await log_channel.send(embed=embed)
@app_commands.command(name="modpanel", description="Ouvre le panel de modération pour un membre")
@app_commands.checks.has_permissions(moderate_members=True)
async def modpanel(self, interaction: discord.Interaction, member: discord.Member):
@commands.slash_command(name="modpanel", description="Ouvre le panel de modération pour un membre")
@commands.has_permissions(moderate_members=True)
async def modpanel(self, interaction: disnake.ApplicationCommandInteraction, member: disnake.Member):
if member.top_role >= interaction.user.top_role and interaction.user.id != interaction.guild.owner_id:
return await interaction.response.send_message("❌ Impossible de gérer ce membre.", ephemeral=True)
conn = sqlite3.connect(self.db_path)
cursor = conn.cursor()
cursor.execute('SELECT COUNT(*) FROM sanctions WHERE guild_id = ? AND user_id = ? AND type = "WARN" AND status = "ACTIVE"', (interaction.guild_id, member.id))
warn_count = cursor.fetchone()[0]; conn.close()
embed = discord.Embed(title=f"🛡️ Panel de Modération - {member.name}", description=f"Gestion de {member.mention}", color=discord.Color.blue(), timestamp=datetime.now())
embed = disnake.Embed(title=f"🛡️ Panel de Modération - {member.name}", description=f"Gestion de {member.mention}", color=disnake.Color.blue(), timestamp=datetime.now())
embed.set_thumbnail(url=member.display_avatar.url)
embed.add_field(name="👤 Utilisateur", value=f"ID: `{member.id}`", inline=True)
embed.add_field(name="⚠️ Avertissements", value=f"Actifs: **{warn_count}**", inline=True)
view = ModPanelView(member, interaction.user, self.db_path)
await interaction.response.send_message(embed=embed, view=view, ephemeral=True)
@app_commands.command(name="modconfig", description="Configuration de la modération")
@app_commands.checks.has_permissions(administrator=True)
async def modconfig(self, interaction: discord.Interaction):
@commands.slash_command(name="modconfig", description="Configuration de la modération")
@commands.has_permissions(administrator=True)
async def modconfig(self, interaction: disnake.ApplicationCommandInteraction):
conn = sqlite3.connect(self.db_path)
cursor = conn.cursor()
cursor.execute('INSERT OR IGNORE INTO mod_config (guild_id) VALUES (?)', (interaction.guild_id,))
cursor.execute('SELECT log_channel_id, warn_limit_timeout, warn_limit_kick, warn_limit_ban, timeout_duration FROM mod_config WHERE guild_id = ?', (interaction.guild_id,))
res = cursor.fetchone(); conn.commit(); conn.close()
embed = discord.Embed(title="⚙️ Configuration Modération", description="Modifiez les paramètres ci-dessous.", color=discord.Color.blue())
embed = disnake.Embed(title="⚙️ Configuration Modération", description="Modifiez les paramètres ci-dessous.", color=disnake.Color.blue())
embed.add_field(name="📁 Logs", value=f"<#{res[0]}>" if res[0] else "Non défini", inline=False)
embed.add_field(name="⚖️ Paliers", value=f"Timeout: **{res[1]}**, Kick: **{res[2]}**, Ban: **{res[3]}**", inline=False)
embed.add_field(name="⏱️ Durée Timeout Auto", value=f"**{res[4]}s**", inline=False)
view = ModConfigView(interaction.guild_id, self.db_path)
await interaction.response.send_message(embed=embed, view=view, ephemeral=True)
async def warn(self, interaction: discord.Interaction, member: discord.Member, reason: str):
async def warn(self, interaction: disnake.Interaction, member: disnake.Member, reason: str):
conn = sqlite3.connect(self.db_path)
cursor = conn.cursor()
cursor.execute('INSERT INTO sanctions (guild_id, user_id, moderator_id, type, reason) VALUES (?, ?, ?, ?, ?)', (interaction.guild_id, member.id, interaction.user.id, 'WARN', reason))
@ -266,26 +265,26 @@ class Moderation(commands.Cog):
config = cursor.fetchone(); conn.commit(); conn.close()
if not interaction.response.is_done(): await interaction.response.send_message(f"{member.mention} averti ({warn_count}).", ephemeral=True)
else: await interaction.followup.send(f"{member.mention} averti ({warn_count}).", ephemeral=True)
await self.send_mod_log(interaction.guild, discord.Embed(title="⚠️ Avertissement", description=f"Membre: {member.mention}\nRaison: {reason}\nTotal: {warn_count}", color=discord.Color.orange()))
await self.send_mod_log(interaction.guild, disnake.Embed(title="⚠️ Avertissement", description=f"Membre: {member.mention}\nRaison: {reason}\nTotal: {warn_count}", color=disnake.Color.orange()))
try: await member.send(f"⚠️ Avertissement sur **{interaction.guild.name}**\nRaison: {reason}")
except: pass
if config:
l_t, l_k, l_b, dur = config
if warn_count >= l_b: await member.ban(reason=f"Auto: {warn_count} warns")
elif warn_count >= l_k: await member.kick(reason=f"Auto: {warn_count} warns")
elif warn_count >= l_t: await member.timeout(timedelta(seconds=dur), reason=f"Auto: {warn_count} warns")
elif warn_count >= l_t: await member.timeout(duration=timedelta(seconds=dur), reason=f"Auto: {warn_count} warns")
async def timeout(self, interaction: discord.Interaction, member: discord.Member, duration_str: str, reason: str):
async def timeout(self, interaction: disnake.Interaction, member: disnake.Member, duration_str: str, reason: str):
secs = self.parse_duration(duration_str)
if secs <= 0: return await interaction.response.send_message("❌ Durée invalide.", ephemeral=True)
await member.timeout(timedelta(seconds=secs), reason=reason)
await member.timeout(duration=timedelta(seconds=secs), reason=reason)
conn = sqlite3.connect(self.db_path); cursor = conn.cursor()
cursor.execute('INSERT INTO sanctions (guild_id, user_id, moderator_id, type, reason, duration) VALUES (?, ?, ?, ?, ?, ?)', (interaction.guild_id, member.id, interaction.user.id, 'TIMEOUT', reason, secs))
conn.commit(); conn.close()
if not interaction.response.is_done(): await interaction.response.send_message(f"{member.mention} mis en sourdine.", ephemeral=True)
else: await interaction.followup.send(f"{member.mention} mis en sourdine.", ephemeral=True)
async def kick(self, interaction: discord.Interaction, member: discord.Member, reason: str):
async def kick(self, interaction: disnake.Interaction, member: disnake.Member, reason: str):
await member.kick(reason=reason)
conn = sqlite3.connect(self.db_path); cursor = conn.cursor()
cursor.execute('INSERT INTO sanctions (guild_id, user_id, moderator_id, type, reason) VALUES (?, ?, ?, ?, ?)', (interaction.guild_id, member.id, interaction.user.id, 'KICK', reason))
@ -293,7 +292,7 @@ class Moderation(commands.Cog):
if not interaction.response.is_done(): await interaction.response.send_message(f"{member.name} expulsé.", ephemeral=True)
else: await interaction.followup.send(f"{member.name} expulsé.", ephemeral=True)
async def ban(self, interaction: discord.Interaction, user: discord.User, reason: str):
async def ban(self, interaction: disnake.Interaction, user: disnake.User, reason: str):
await interaction.guild.ban(user, reason=reason)
conn = sqlite3.connect(self.db_path); cursor = conn.cursor()
cursor.execute('INSERT INTO sanctions (guild_id, user_id, moderator_id, type, reason) VALUES (?, ?, ?, ?, ?)', (interaction.guild_id, user.id, interaction.user.id, 'BAN', reason))
@ -301,20 +300,20 @@ class Moderation(commands.Cog):
if not interaction.response.is_done(): await interaction.response.send_message(f"{user.name} banni.", ephemeral=True)
else: await interaction.followup.send(f"{user.name} banni.", ephemeral=True)
async def history(self, interaction: discord.Interaction, user: discord.User):
async def history(self, interaction: disnake.Interaction, user: disnake.User):
conn = sqlite3.connect(self.db_path); cursor = conn.cursor()
cursor.execute('SELECT id, type, reason, timestamp FROM sanctions WHERE guild_id = ? AND user_id = ? ORDER BY timestamp DESC', (interaction.guild_id, user.id))
results = cursor.fetchall(); conn.close()
if not results:
if not interaction.response.is_done(): return await interaction.response.send_message(" Aucun historique.", ephemeral=True)
else: return await interaction.followup.send(" Aucun historique.", ephemeral=True)
embed = discord.Embed(title=f"📜 Historique de {user.name}", color=discord.Color.blue())
embed = disnake.Embed(title=f"📜 Historique de {user.name}", color=disnake.Color.blue())
for s_id, s_type, reason, ts in results[:10]:
embed.add_field(name=f"#{s_id} - {s_type}", value=f"**Date:** {ts}\n**Raison:** {reason}", inline=False)
if not interaction.response.is_done(): await interaction.response.send_message(embed=embed, ephemeral=True)
else: await interaction.followup.send(embed=embed, ephemeral=True)
async def clearwarns(self, interaction: discord.Interaction, member: discord.Member, reason: str):
async def clearwarns(self, interaction: disnake.Interaction, member: disnake.Member, reason: str):
conn = sqlite3.connect(self.db_path); cursor = conn.cursor()
cursor.execute('UPDATE sanctions SET status = "REVOKED" WHERE guild_id = ? AND user_id = ? AND type = "WARN"', (interaction.guild_id, member.id))
conn.commit(); conn.close()