2026-05-06 17:07:09 +02:00
import disnake
from disnake . ext import commands
2026-05-01 16:44:50 +02:00
import sqlite3
import os
from datetime import datetime , timedelta
import re
2026-05-06 17:07:09 +02:00
class ModReasonModal ( disnake . ui . Modal ) :
2026-05-01 16:44:50 +02:00
def __init__ ( self , parent_view , action_type ) :
2026-05-09 18:42:42 +02:00
super ( ) . __init__ ( title = f " Raison pour { action_type } " , components = [ ] )
2026-05-01 16:44:50 +02:00
self . parent_view = parent_view
self . action_type = action_type
2026-05-06 17:07:09 +02:00
self . reason = disnake . ui . TextInput (
2026-05-01 16:44:50 +02:00
label = " Raison " ,
placeholder = " Entrez la raison ici... " ,
required = True ,
max_length = 500
)
2026-05-09 18:42:42 +02:00
self . append_component ( self . reason )
2026-05-01 16:44:50 +02:00
if action_type == " TIMEOUT " :
2026-05-06 17:07:09 +02:00
self . duration = disnake . ui . TextInput (
2026-05-01 16:44:50 +02:00
label = " Durée (ex: 1h, 30m, 1d) " ,
placeholder = " 1h " ,
required = True ,
max_length = 10
)
2026-05-09 18:42:42 +02:00
self . append_component ( self . duration )
2026-05-01 16:44:50 +02:00
2026-05-06 17:07:09 +02:00
async def callback ( self , interaction : disnake . Interaction ) :
2026-05-01 16:44:50 +02:00
reason = self . reason . value
member = self . parent_view . member
2026-05-06 17:07:09 +02:00
cog = interaction . bot . get_cog ( " Moderation " )
2026-05-01 16:44:50 +02:00
if not cog :
return await interaction . response . send_message ( " ❌ Erreur interne. " , ephemeral = True )
if self . action_type == " WARN " :
await cog . warn ( interaction , member , reason )
elif self . action_type == " TIMEOUT " :
await cog . timeout ( interaction , member , self . duration . value , reason )
elif self . action_type == " KICK " :
await cog . kick ( interaction , member , reason )
elif self . action_type == " BAN " :
await cog . ban ( interaction , member , reason )
await self . parent_view . update_panel ( interaction )
2026-05-06 17:07:09 +02:00
class ModPanelView ( disnake . ui . View ) :
2026-05-01 16:44:50 +02:00
def __init__ ( self , member , moderator , db_path ) :
super ( ) . __init__ ( timeout = 120 )
self . member = member
self . moderator = moderator
self . db_path = db_path
2026-05-06 17:07:09 +02:00
async def update_panel ( self , interaction : disnake . Interaction ) :
2026-05-01 16:44:50 +02:00
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 ( )
2026-05-06 17:07:09 +02:00
embed = disnake . Embed (
2026-05-01 16:44:50 +02:00
title = f " 🛡️ Panel de Modération - { self . member . name } " ,
description = f " Gestion de l ' utilisateur { self . member . mention } " ,
2026-05-06 17:07:09 +02:00
color = disnake . Color . blue ( ) ,
2026-05-01 16:44:50 +02:00
timestamp = datetime . now ( )
)
embed . set_thumbnail ( url = self . member . display_avatar . url )
embed . add_field ( name = " 👤 Utilisateur " , value = f " ID: ` { self . member . id } ` \n Tag: ` { self . member } ` " , inline = True )
embed . add_field ( name = " ⚠️ Avertissements " , value = f " Actifs: ** { warn_count } ** " , inline = True )
embed . add_field ( name = " 📅 Dates " , value = f " Rejoint: <t: { int ( self . member . joined_at . timestamp ( ) ) } :R> \n Créé: <t: { int ( self . member . created_at . timestamp ( ) ) } :R> " , inline = False )
if not interaction . response . is_done ( ) :
await interaction . response . edit_message ( embed = embed , view = self )
else :
await interaction . edit_original_response ( embed = embed , view = self )
2026-05-06 17:07:09 +02:00
@disnake.ui.button ( label = " Avertir " , style = disnake . ButtonStyle . secondary , emoji = " ⚠️ " )
2026-05-09 18:42:42 +02:00
async def warn_btn ( self , button : disnake . ui . Button , interaction : disnake . Interaction ) :
2026-05-01 16:44:50 +02:00
await interaction . response . send_modal ( ModReasonModal ( self , " WARN " ) )
2026-05-06 17:07:09 +02:00
@disnake.ui.button ( label = " Timeout " , style = disnake . ButtonStyle . secondary , emoji = " ⏳ " )
2026-05-09 18:42:42 +02:00
async def timeout_btn ( self , button : disnake . ui . Button , interaction : disnake . Interaction ) :
2026-05-01 16:44:50 +02:00
await interaction . response . send_modal ( ModReasonModal ( self , " TIMEOUT " ) )
2026-05-06 17:07:09 +02:00
@disnake.ui.button ( label = " Expulser " , style = disnake . ButtonStyle . secondary , emoji = " 👢 " )
2026-05-09 18:42:42 +02:00
async def kick_btn ( self , button : disnake . ui . Button , interaction : disnake . Interaction ) :
2026-05-01 16:44:50 +02:00
await interaction . response . send_modal ( ModReasonModal ( self , " KICK " ) )
2026-05-06 17:07:09 +02:00
@disnake.ui.button ( label = " Bannir " , style = disnake . ButtonStyle . danger , emoji = " 🔨 " )
2026-05-09 18:42:42 +02:00
async def ban_btn ( self , button : disnake . ui . Button , interaction : disnake . Interaction ) :
2026-05-01 16:44:50 +02:00
await interaction . response . send_modal ( ModReasonModal ( self , " BAN " ) )
2026-05-06 17:07:09 +02:00
@disnake.ui.button ( label = " Historique " , style = disnake . ButtonStyle . primary , emoji = " 📜 " )
2026-05-09 18:42:42 +02:00
async def history_btn ( self , button : disnake . ui . Button , interaction : disnake . Interaction ) :
2026-05-06 17:07:09 +02:00
cog = interaction . bot . get_cog ( " Moderation " )
2026-05-01 16:44:50 +02:00
await cog . history ( interaction , self . member )
2026-05-06 17:07:09 +02:00
@disnake.ui.button ( label = " Clear Warns " , style = disnake . ButtonStyle . danger , emoji = " 🧹 " )
2026-05-09 18:42:42 +02:00
async def clear_btn ( self , button : disnake . ui . Button , interaction : disnake . Interaction ) :
2026-05-06 17:07:09 +02:00
cog = interaction . bot . get_cog ( " Moderation " )
2026-05-01 16:44:50 +02:00
await cog . clearwarns ( interaction , self . member , reason = " Nettoyage via Panel " )
await self . update_panel ( interaction )
2026-05-06 17:07:09 +02:00
class ModConfigModal ( disnake . ui . Modal ) :
2026-05-01 16:44:50 +02:00
def __init__ ( self , field_name , current_value ) :
2026-05-09 18:42:42 +02:00
super ( ) . __init__ ( components = [ ] , title = f " Modifier { field_name } " )
2026-05-01 16:44:50 +02:00
self . field_name = field_name
2026-05-06 17:07:09 +02:00
self . input = disnake . ui . TextInput (
2026-05-01 16:44:50 +02:00
label = field_name ,
2026-05-09 18:42:42 +02:00
value = str ( current_value ) ,
2026-05-01 16:44:50 +02:00
placeholder = " Entrez une valeur numérique... " ,
required = True
)
2026-05-09 18:42:42 +02:00
self . append_component ( self . input )
2026-05-01 16:44:50 +02:00
2026-05-06 17:07:09 +02:00
async def callback ( self , interaction : disnake . Interaction ) :
2026-05-01 16:44:50 +02:00
value = self . input . value
2026-05-06 17:07:09 +02:00
cog = interaction . bot . get_cog ( " Moderation " )
2026-05-01 16:44:50 +02:00
mapping = {
" Limite Timeout " : " warn_limit_timeout " ,
" Limite Kick " : " warn_limit_kick " ,
" Limite Ban " : " warn_limit_ban " ,
" Durée Timeout (s) " : " timeout_duration "
}
if not value . isdigit ( ) :
return await interaction . response . send_message ( " ❌ Veuillez entrer un nombre valide. " , ephemeral = True )
db_field = mapping . get ( self . field_name )
conn = sqlite3 . connect ( cog . db_path )
cursor = conn . cursor ( )
cursor . execute ( f " UPDATE mod_config SET { db_field } = ? WHERE guild_id = ? " , ( int ( value ) , interaction . guild_id ) )
conn . commit ( )
conn . close ( )
await interaction . response . send_message ( f " ✅ { self . field_name } mis à jour sur ** { value } **. " , ephemeral = True )
2026-05-06 17:07:09 +02:00
class ModConfigView ( disnake . ui . View ) :
2026-05-01 16:44:50 +02:00
def __init__ ( self , guild_id , db_path ) :
super ( ) . __init__ ( timeout = 60 )
self . guild_id = guild_id
self . db_path = db_path
2026-05-06 17:07:09 +02:00
@disnake.ui.button ( label = " Log Channel " , style = disnake . ButtonStyle . primary , emoji = " 📁 " )
2026-05-09 18:42:42 +02:00
async def log_btn ( self , button : disnake . ui . Button , interaction : disnake . Interaction ) :
2026-05-06 17:07:09 +02:00
view = disnake . ui . View ( )
select = disnake . ui . ChannelSelect (
2026-05-01 16:44:50 +02:00
placeholder = " Sélectionnez le salon de logs... " ,
2026-05-06 17:07:09 +02:00
channel_types = [ disnake . ChannelType . text ]
2026-05-01 16:44:50 +02:00
)
2026-05-06 17:07:09 +02:00
async def select_callback ( interaction : disnake . Interaction ) :
2026-05-01 16:44:50 +02:00
channel = select . values [ 0 ]
conn = sqlite3 . connect ( self . db_path )
cursor = conn . cursor ( )
cursor . execute ( " UPDATE mod_config SET log_channel_id = ? WHERE guild_id = ? " , ( channel . id , interaction . guild_id ) )
conn . commit ( ) ; conn . close ( )
await interaction . response . send_message ( f " ✅ Salon de logs défini sur { channel . mention } " , ephemeral = True )
select . callback = select_callback
view . add_item ( select )
await interaction . response . send_message ( " Choisissez le salon de logs : " , view = view , ephemeral = True )
2026-05-06 17:07:09 +02:00
@disnake.ui.button ( label = " Paliers Warns " , style = disnake . ButtonStyle . secondary , emoji = " ⚖️ " )
2026-05-09 18:42:42 +02:00
async def limits_btn ( self , button : disnake . ui . Button , interaction : disnake . Interaction ) :
2026-05-01 16:44:50 +02:00
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 ( )
2026-05-06 17:07:09 +02:00
view = disnake . ui . View ( )
2026-05-01 16:44:50 +02:00
2026-05-06 17:07:09 +02:00
btn_t = disnake . ui . Button ( label = f " Timeout ( { res [ 0 ] } ) " , style = disnake . ButtonStyle . secondary )
2026-05-01 16:44:50 +02:00
btn_t . callback = lambda i : i . response . send_modal ( ModConfigModal ( " Limite Timeout " , res [ 0 ] ) )
2026-05-06 17:07:09 +02:00
btn_k = disnake . ui . Button ( label = f " Kick ( { res [ 1 ] } ) " , style = disnake . ButtonStyle . secondary )
2026-05-01 16:44:50 +02:00
btn_k . callback = lambda i : i . response . send_modal ( ModConfigModal ( " Limite Kick " , res [ 1 ] ) )
2026-05-06 17:07:09 +02:00
btn_b = disnake . ui . Button ( label = f " Ban ( { res [ 2 ] } ) " , style = disnake . ButtonStyle . secondary )
2026-05-01 16:44:50 +02:00
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 )
2026-05-06 17:07:09 +02:00
@disnake.ui.button ( label = " Durée Timeout " , style = disnake . ButtonStyle . secondary , emoji = " ⏱️ " )
2026-05-09 18:42:42 +02:00
async def duration_btn ( self , button : disnake . ui . Button , interaction : disnake . Interaction ) :
2026-05-01 16:44:50 +02:00
conn = sqlite3 . connect ( self . db_path )
cursor = conn . cursor ( )
cursor . execute ( " SELECT timeout_duration FROM mod_config WHERE guild_id = ? " , ( self . guild_id , ) )
res = cursor . fetchone ( ) ; conn . close ( )
await interaction . response . send_modal ( ModConfigModal ( " Durée Timeout (s) " , res [ 0 ] ) )
class Moderation ( commands . Cog ) :
def __init__ ( self , bot ) :
self . bot = bot
self . db_path = os . path . join ( os . path . dirname ( __file__ ) , " .. " , " config.db " )
self . _init_db ( )
def _init_db ( self ) :
conn = sqlite3 . connect ( self . db_path )
cursor = conn . cursor ( )
cursor . execute ( ''' CREATE TABLE IF NOT EXISTS sanctions (id INTEGER PRIMARY KEY AUTOINCREMENT, guild_id INTEGER, user_id INTEGER, moderator_id INTEGER, type TEXT, reason TEXT, timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, duration INTEGER, status TEXT DEFAULT ' ACTIVE ' ) ''' )
cursor . execute ( ''' CREATE TABLE IF NOT EXISTS mod_config (guild_id INTEGER PRIMARY KEY, log_channel_id INTEGER, warn_limit_timeout INTEGER DEFAULT 3, warn_limit_kick INTEGER DEFAULT 5, warn_limit_ban INTEGER DEFAULT 10, timeout_duration INTEGER DEFAULT 3600) ''' )
conn . commit ( ) ; conn . close ( )
def parse_duration ( self , duration_str : str ) - > int :
if not duration_str : return 0
units = { ' s ' : 1 , ' m ' : 60 , ' h ' : 3600 , ' d ' : 86400 , ' w ' : 604800 }
total_seconds = 0
matches = re . findall ( r ' ( \ d+)([smhdw]) ' , duration_str . lower ( ) )
for value , unit in matches : total_seconds + = int ( value ) * units [ unit ]
return total_seconds
async def send_mod_log ( self , guild , embed ) :
conn = sqlite3 . connect ( self . db_path )
cursor = conn . cursor ( )
cursor . execute ( ' SELECT log_channel_id FROM mod_config WHERE guild_id = ? ' , ( guild . id , ) )
result = cursor . fetchone ( ) ; conn . close ( )
if result and result [ 0 ] :
log_channel = guild . get_channel ( result [ 0 ] )
if log_channel : await log_channel . send ( embed = embed )
2026-05-06 17:07:09 +02:00
@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 ) :
2026-05-01 16:44:50 +02:00
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 ( )
2026-05-06 17:07:09 +02:00
embed = disnake . Embed ( title = f " 🛡️ Panel de Modération - { member . name } " , description = f " Gestion de { member . mention } " , color = disnake . Color . blue ( ) , timestamp = datetime . now ( ) )
2026-05-01 16:44:50 +02:00
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 )
2026-05-06 17:07:09 +02:00
@commands.slash_command ( name = " modconfig " , description = " Configuration de la modération " )
@commands.has_permissions ( administrator = True )
async def modconfig ( self , interaction : disnake . ApplicationCommandInteraction ) :
2026-05-01 16:44:50 +02:00
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 ( )
2026-05-06 17:07:09 +02:00
embed = disnake . Embed ( title = " ⚙️ Configuration Modération " , description = " Modifiez les paramètres ci-dessous. " , color = disnake . Color . blue ( ) )
2026-05-01 16:44:50 +02:00
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 )
2026-05-06 17:07:09 +02:00
async def warn ( self , interaction : disnake . Interaction , member : disnake . Member , reason : str ) :
2026-05-01 16:44:50 +02:00
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 ) )
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 ]
cursor . execute ( ' SELECT warn_limit_timeout, warn_limit_kick, warn_limit_ban, timeout_duration FROM mod_config WHERE guild_id = ? ' , ( interaction . guild_id , ) )
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 )
2026-05-06 17:07:09 +02:00
await self . send_mod_log ( interaction . guild , disnake . Embed ( title = " ⚠️ Avertissement " , description = f " Membre: { member . mention } \n Raison: { reason } \n Total: { warn_count } " , color = disnake . Color . orange ( ) ) )
2026-05-01 16:44:50 +02:00
try : await member . send ( f " ⚠️ Avertissement sur ** { interaction . guild . name } ** \n Raison: { 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 " )
2026-05-06 17:07:09 +02:00
elif warn_count > = l_t : await member . timeout ( duration = timedelta ( seconds = dur ) , reason = f " Auto: { warn_count } warns " )
2026-05-01 16:44:50 +02:00
2026-05-06 17:07:09 +02:00
async def timeout ( self , interaction : disnake . Interaction , member : disnake . Member , duration_str : str , reason : str ) :
2026-05-01 16:44:50 +02:00
secs = self . parse_duration ( duration_str )
if secs < = 0 : return await interaction . response . send_message ( " ❌ Durée invalide. " , ephemeral = True )
2026-05-06 17:07:09 +02:00
await member . timeout ( duration = timedelta ( seconds = secs ) , reason = reason )
2026-05-01 16:44:50 +02:00
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 )
2026-05-06 17:07:09 +02:00
async def kick ( self , interaction : disnake . Interaction , member : disnake . Member , reason : str ) :
2026-05-01 16:44:50 +02:00
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 ) )
conn . commit ( ) ; conn . close ( )
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 )
2026-05-06 17:07:09 +02:00
async def ban ( self , interaction : disnake . Interaction , user : disnake . User , reason : str ) :
2026-05-01 16:44:50 +02:00
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 ) )
conn . commit ( ) ; conn . close ( )
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 )
2026-05-06 17:07:09 +02:00
async def history ( self , interaction : disnake . Interaction , user : disnake . User ) :
2026-05-01 16:44:50 +02:00
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 )
2026-05-06 17:07:09 +02:00
embed = disnake . Embed ( title = f " 📜 Historique de { user . name } " , color = disnake . Color . blue ( ) )
2026-05-01 16:44:50 +02:00
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 )
2026-05-06 17:07:09 +02:00
async def clearwarns ( self , interaction : disnake . Interaction , member : disnake . Member , reason : str ) :
2026-05-01 16:44:50 +02:00
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 ( )
if not interaction . response . is_done ( ) : await interaction . response . send_message ( f " ✅ Warns de { member . name } effacés. " , ephemeral = True )
else : await interaction . followup . send ( f " ✅ Warns de { member . name } effacés. " , ephemeral = True )
2026-05-09 18:42:42 +02:00
def setup ( bot ) :
bot . add_cog ( Moderation ( bot ) )