Refonte du systeme d'avertissement et devient un moderation_event

Ajout de la commande !ban !kick !unban !listevent

Ajout du role ID dans le panel , et possibilité d'activé les commandes via le panel
This commit is contained in:
Mow
2025-10-15 22:29:41 +02:00
parent aff236fd0c
commit fd172e2ea0
8 changed files with 610 additions and 32 deletions

View File

@@ -40,12 +40,14 @@ class Commande(db.Model):
trigger = db.Column(db.String(32), unique=True) trigger = db.Column(db.String(32), unique=True)
response = db.Column(db.String(2000)) response = db.Column(db.String(2000))
class Warning(db.Model): class ModerationEvent(db.Model):
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
type = db.Column(db.String(32))
username = db.Column(db.String(256)) username = db.Column(db.String(256))
discord_id = db.Column(db.String(64)) discord_id = db.Column(db.String(64))
created_at = db.Column(db.DateTime) created_at = db.Column(db.DateTime)
reason = db.Column(db.String(1024)) reason = db.Column(db.String(1024))
staff_id = db.Column(db.String(64)) staff_id = db.Column(db.String(64))
staff_name = db.Column(db.String(256)) staff_name = db.Column(db.String(256))
duration = db.Column(db.Integer)

View File

@@ -46,12 +46,14 @@ CREATE TABLE IF NOT EXISTS `commande` (
`response` VARCHAR(2000) NOT NULL `response` VARCHAR(2000) NOT NULL
); );
CREATE TABLE IF NOT EXISTS `warning` ( CREATE TABLE IF NOT EXISTS `moderation_event` (
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
`type` VARCHAR(32) NOT NULL,
`username` VARCHAR(256) NOT NULL, `username` VARCHAR(256) NOT NULL,
`discord_id` VARCHAR(64) NOT NULL, `discord_id` VARCHAR(64) NOT NULL,
`created_at` DATETIME NOT NULL, `created_at` DATETIME NOT NULL,
`reason` VARCHAR(1024) NOT NULL, `reason` VARCHAR(1024) NOT NULL,
`staff_id` VARCHAR(64) NOT NULL, `staff_id` VARCHAR(64) NOT NULL,
`staff_name` VARCHAR(256) NOT NULL `staff_name` VARCHAR(256) NOT NULL,
`duration` INTEGER NULL
); );

View File

@@ -8,7 +8,7 @@ from database.helpers import ConfigurationHelper
from database.models import Configuration, Humeur, Commande from database.models import Configuration, Humeur, Commande
from discord import Message, TextChannel from discord import Message, TextChannel
from discordbot.humblebundle import checkHumbleBundleAndNotify from discordbot.humblebundle import checkHumbleBundleAndNotify
from discordbot.command import handle_warning_command from discordbot.command import handle_warning_command, handle_remove_warning_command, handle_list_warnings_command, handle_ban_command, handle_kick_command, handle_unban_command
from protondb import searhProtonDb from protondb import searhProtonDb
class DiscordBot(discord.Client): class DiscordBot(discord.Client):
@@ -65,10 +65,32 @@ async def on_message(message: Message):
return return
command_name = message.content.split()[0] command_name = message.content.split()[0]
if command_name in ['!averto', '!av', '!avertissement', '!warn']: if ConfigurationHelper().getValue('moderation_enable'):
await handle_warning_command(message, bot) if command_name in ['!averto', '!av', '!avertissement', '!warn']:
return await handle_warning_command(message, bot)
return
if command_name in ['!delaverto', '!removewarn', '!unwarn']:
await handle_remove_warning_command(message, bot)
return
if command_name in ['!listevent', '!listwarn', '!warnings']:
await handle_list_warnings_command(message, bot)
return
if ConfigurationHelper().getValue('moderation_ban_enable'):
if command_name == '!ban':
await handle_ban_command(message, bot)
return
if command_name == '!unban':
await handle_unban_command(message, bot)
return
if ConfigurationHelper().getValue('moderation_kick_enable'):
if command_name == '!kick':
await handle_kick_command(message, bot)
return
commande = Commande.query.filter_by(discord_enable=True, trigger=command_name).first() commande = Commande.query.filter_by(discord_enable=True, trigger=command_name).first()
if commande: if commande:

View File

@@ -1,24 +1,80 @@
import discord import discord
import asyncio
from datetime import datetime from datetime import datetime
from database import db from database import db
from database.models import Warning from database.helpers import ConfigurationHelper
from database.models import ModerationEvent
from discord import Message from discord import Message
STAFF_ROLE_ID = 581990740431732738 def get_staff_role_id():
staff_role = ConfigurationHelper().getValue('moderation_staff_role_id')
return int(staff_role) if staff_role else 581990740431732738
def get_embed_delete_delay():
delay = ConfigurationHelper().getValue('moderation_embed_delete_delay')
return int(delay) if delay else 0
async def delete_after_delay(message):
delay = get_embed_delete_delay()
if delay > 0:
await asyncio.sleep(delay)
try:
await message.delete()
except:
pass
async def handle_warning_command(message: Message, bot): async def handle_warning_command(message: Message, bot):
if not any(role.id == STAFF_ROLE_ID for role in message.author.roles): if not any(role.id == get_staff_role_id() for role in message.author.roles):
embed = discord.Embed(
title="❌ Accès refusé",
description="Vous n'avez pas les permissions nécessaires pour utiliser cette commande.",
color=discord.Color.red()
)
await message.channel.send(embed=embed)
return return
parts = message.content.split(maxsplit=2) parts = message.content.split(maxsplit=2)
if len(parts) < 2 or not message.mentions: if len(parts) < 2:
embed = discord.Embed(
title="📋 Utilisation de la commande",
description="**Syntaxe :** `!averto @utilisateur [raison]` ou `!averto <id> [raison]`",
color=discord.Color.blue()
)
embed.add_field(name="Exemples", value="• `!averto @User Spam dans le chat`\n• `!warn 123456789012345678 Comportement inapproprié`\n• `!av @User`", inline=False)
embed.add_field(name="Aliases", value="`!averto`, `!av`, `!avertissement`, `!warn`", inline=False)
await message.channel.send(embed=embed)
return return
target_user = message.mentions[0] target_user = None
reason = parts[2] if len(parts) > 2 else "Sans raison" if message.mentions:
target_user = message.mentions[0]
reason = parts[2] if len(parts) > 2 else "Sans raison"
else:
try:
user_id = int(parts[1])
target_user = await bot.fetch_user(user_id)
reason = parts[2] if len(parts) > 2 else "Sans raison"
except (ValueError, discord.NotFound):
embed = discord.Embed(
title="❌ Erreur",
description="Utilisateur introuvable. Vérifiez la mention ou l'ID Discord.",
color=discord.Color.red()
)
await message.channel.send(embed=embed)
return
warning = Warning( if not target_user:
embed = discord.Embed(
title="❌ Erreur",
description="Impossible de trouver l'utilisateur.",
color=discord.Color.red()
)
await message.channel.send(embed=embed)
return
event = ModerationEvent(
type='warning',
username=target_user.name, username=target_user.name,
discord_id=str(target_user.id), discord_id=str(target_user.id),
created_at=datetime.utcnow(), created_at=datetime.utcnow(),
@@ -26,19 +82,452 @@ async def handle_warning_command(message: Message, bot):
staff_id=str(message.author.id), staff_id=str(message.author.id),
staff_name=message.author.name staff_name=message.author.name
) )
db.session.add(warning) db.session.add(event)
db.session.commit() db.session.commit()
embed = discord.Embed( embed = discord.Embed(
title="⚠️ Avertissement", title="⚠️ Sanction",
description=f"{target_user.mention} a reçu un avertissement de la part de l'équipe de modération", description=f"L'utilisateur **{target_user.name}** (`@{target_user.name}`) a été **averti**.",
color=discord.Color.red(), color=discord.Color.orange()
)
if reason != "Sans raison":
embed.add_field(name="Raison", value=reason, inline=False)
sent_message = await message.channel.send(embed=embed)
await message.delete()
asyncio.create_task(delete_after_delay(sent_message))
async def handle_remove_warning_command(message: Message, bot):
if not any(role.id == get_staff_role_id() for role in message.author.roles):
embed = discord.Embed(
title="❌ Accès refusé",
description="Vous n'avez pas les permissions nécessaires pour utiliser cette commande.",
color=discord.Color.red()
)
await message.channel.send(embed=embed)
return
parts = message.content.split(maxsplit=1)
if len(parts) < 2:
embed = discord.Embed(
title="📋 Utilisation de la commande",
description="**Syntaxe :** `!delaverto <id>`",
color=discord.Color.blue()
)
embed.add_field(name="Exemples", value="• `!delaverto 5`\n• `!removewarn 12`", inline=False)
embed.add_field(name="Aliases", value="`!delaverto`, `!removewarn`, `!delwarn`", inline=False)
await message.channel.send(embed=embed)
return
try:
event_id = int(parts[1])
except ValueError:
embed = discord.Embed(
title="❌ Erreur",
description="L'ID doit être un nombre entier.",
color=discord.Color.red()
)
await message.channel.send(embed=embed)
return
event = ModerationEvent.query.filter_by(id=event_id).first()
if not event:
embed = discord.Embed(
title="❌ Erreur",
description=f"Aucun événement de modération trouvé avec l'ID `{event_id}`.",
color=discord.Color.red()
)
await message.channel.send(embed=embed)
return
username = event.username
event_type = event.type
db.session.delete(event)
db.session.commit()
embed = discord.Embed(
title="✅ Événement supprimé",
description=f"L'événement de type **{event_type}** pour **{username}** (ID: {event_id}) a été supprimé.",
color=discord.Color.green(),
timestamp=datetime.utcnow() timestamp=datetime.utcnow()
) )
embed.add_field(name="👤 Utilisateur", value=f"{target_user.name}\n`{target_user.id}`", inline=True) embed.add_field(name="🛡️ Modérateur", value=f"{message.author.name}\n`{message.author.id}`", inline=True)
#embed.add_field(name="🛡️ Modérateur", value=f"{message.author.name}\n`{message.author.id}`", inline=True)
embed.add_field(name="📝 Raison", value=reason, inline=False)
embed.set_footer(text="Mamie Henriette") embed.set_footer(text="Mamie Henriette")
await message.channel.send(embed=embed) await message.channel.send(embed=embed)
await message.delete() await message.delete()
async def handle_list_warnings_command(message: Message, bot):
if not any(role.id == get_staff_role_id() for role in message.author.roles):
embed = discord.Embed(
title="❌ Accès refusé",
description="Vous n'avez pas les permissions nécessaires pour utiliser cette commande.",
color=discord.Color.red()
)
await message.channel.send(embed=embed)
return
parts = message.content.split(maxsplit=1)
user_filter = None
if len(parts) > 1 and message.mentions:
user_filter = str(message.mentions[0].id)
if user_filter:
events = ModerationEvent.query.filter_by(discord_id=user_filter).order_by(ModerationEvent.created_at.desc()).all()
else:
events = ModerationEvent.query.order_by(ModerationEvent.created_at.desc()).all()
if not events:
embed = discord.Embed(
title="📋 Liste des événements",
description="Aucun événement de modération trouvé.",
color=discord.Color.blue()
)
await message.channel.send(embed=embed)
return
page = 0
per_page = 5
max_page = (len(events) - 1) // per_page
def create_embed(page_num):
start = page_num * per_page
end = start + per_page
page_events = events[start:end]
embed = discord.Embed(
title="📋 Liste des événements de modération",
description=f"Total : {len(events)} événement(s)",
color=discord.Color.blue(),
timestamp=datetime.utcnow()
)
for event in page_events:
date_str = event.created_at.strftime('%d/%m/%Y %H:%M') if event.created_at else 'N/A'
embed.add_field(
name=f"ID {event.id} - {event.type.upper()} - {event.username}",
value=f"**Discord ID:** `{event.discord_id}`\n**Date:** {date_str}\n**Raison:** {event.reason}\n**Staff:** {event.staff_name}",
inline=False
)
embed.set_footer(text=f"Page {page_num + 1}/{max_page + 1}")
return embed
msg = await message.channel.send(embed=create_embed(page))
if max_page > 0:
await msg.add_reaction('⬅️')
await msg.add_reaction('➡️')
await msg.add_reaction('')
def check(reaction, user):
return user == message.author and str(reaction.emoji) in ['⬅️', '➡️', ''] and reaction.message.id == msg.id
while True:
try:
reaction, user = await bot.wait_for('reaction_add', timeout=60.0, check=check)
if str(reaction.emoji) == '':
await msg.delete()
break
elif str(reaction.emoji) == '➡️' and page < max_page:
page += 1
await msg.edit(embed=create_embed(page))
elif str(reaction.emoji) == '⬅️' and page > 0:
page -= 1
await msg.edit(embed=create_embed(page))
await msg.remove_reaction(reaction, user)
except:
break
if msg:
try:
await msg.clear_reactions()
except:
pass
await message.delete()
async def handle_ban_command(message: Message, bot):
if not any(role.id == get_staff_role_id() for role in message.author.roles):
embed = discord.Embed(
title="❌ Accès refusé",
description="Vous n'avez pas les permissions nécessaires pour utiliser cette commande.",
color=discord.Color.red()
)
await message.channel.send(embed=embed)
return
parts = message.content.split(maxsplit=2)
if len(parts) < 2:
embed = discord.Embed(
title="📋 Utilisation de la commande",
description="**Syntaxe :** `!ban @utilisateur [raison]` ou `!ban <id> [raison]`",
color=discord.Color.blue()
)
embed.add_field(name="Exemples", value="• `!ban @User Spam répété`\n• `!ban 123456789012345678 Comportement toxique`", inline=False)
await message.channel.send(embed=embed)
return
target_user = None
if message.mentions:
target_user = message.mentions[0]
reason = parts[2] if len(parts) > 2 else "Sans raison"
else:
try:
user_id = int(parts[1])
target_user = await bot.fetch_user(user_id)
reason = parts[2] if len(parts) > 2 else "Sans raison"
except (ValueError, discord.NotFound):
embed = discord.Embed(
title="❌ Erreur",
description="Utilisateur introuvable. Vérifiez la mention ou l'ID Discord.",
color=discord.Color.red()
)
await message.channel.send(embed=embed)
return
if not target_user:
embed = discord.Embed(
title="❌ Erreur",
description="Impossible de trouver l'utilisateur.",
color=discord.Color.red()
)
await message.channel.send(embed=embed)
return
member = message.guild.get_member(target_user.id)
joined_days = None
if member and member.joined_at:
delta = datetime.utcnow() - member.joined_at.replace(tzinfo=None)
joined_days = delta.days
try:
await message.guild.ban(target_user, reason=reason)
except discord.Forbidden:
embed = discord.Embed(
title="❌ Erreur",
description="Je n'ai pas les permissions nécessaires pour bannir cet utilisateur.",
color=discord.Color.red()
)
await message.channel.send(embed=embed)
return
event = ModerationEvent(
type='ban',
username=target_user.name,
discord_id=str(target_user.id),
created_at=datetime.utcnow(),
reason=reason,
staff_id=str(message.author.id),
staff_name=message.author.name
)
db.session.add(event)
db.session.commit()
embed = discord.Embed(
title="⚠️ Sanction",
description=f"L'utilisateur **{target_user.name}** (`@{target_user.name}`) a été **banni**.",
color=discord.Color.red()
)
embed.add_field(name="ID Discord", value=f"`{target_user.id}`", inline=False)
if joined_days is not None:
embed.add_field(name="Membre depuis", value=f"{joined_days} jour{'s' if joined_days > 1 else ''}", inline=False)
if reason != "Sans raison":
embed.add_field(name="Raison", value=reason, inline=False)
sent_message = await message.channel.send(embed=embed)
await message.delete()
asyncio.create_task(delete_after_delay(sent_message))
async def handle_kick_command(message: Message, bot):
if not any(role.id == get_staff_role_id() for role in message.author.roles):
embed = discord.Embed(
title="❌ Accès refusé",
description="Vous n'avez pas les permissions nécessaires pour utiliser cette commande.",
color=discord.Color.red()
)
await message.channel.send(embed=embed)
return
parts = message.content.split(maxsplit=2)
if len(parts) < 2 or not message.mentions:
embed = discord.Embed(
title="📋 Utilisation de la commande",
description="**Syntaxe :** `!kick @utilisateur [raison]`",
color=discord.Color.blue()
)
embed.add_field(name="Exemples", value="• `!kick @User Spam dans le chat`\n• `!kick @User Comportement inapproprié`", inline=False)
await message.channel.send(embed=embed)
return
target_member = message.mentions[0]
reason = parts[2] if len(parts) > 2 else "Sans raison"
member_obj = message.guild.get_member(target_member.id)
if not member_obj:
embed = discord.Embed(
title="❌ Erreur",
description="L'utilisateur n'est pas membre du serveur.",
color=discord.Color.red()
)
await message.channel.send(embed=embed)
return
joined_days = None
if member_obj.joined_at:
delta = datetime.utcnow() - member_obj.joined_at.replace(tzinfo=None)
joined_days = delta.days
try:
await message.guild.kick(member_obj, reason=reason)
except discord.Forbidden:
embed = discord.Embed(
title="❌ Erreur",
description="Je n'ai pas les permissions nécessaires pour expulser cet utilisateur.",
color=discord.Color.red()
)
await message.channel.send(embed=embed)
return
event = ModerationEvent(
type='kick',
username=target_member.name,
discord_id=str(target_member.id),
created_at=datetime.utcnow(),
reason=reason,
staff_id=str(message.author.id),
staff_name=message.author.name
)
db.session.add(event)
db.session.commit()
embed = discord.Embed(
title="⚠️ Sanction",
description=f"L'utilisateur **{target_member.name}** (`@{target_member.name}`) a été **expulsé**.",
color=discord.Color.orange()
)
if joined_days is not None:
embed.add_field(name="Membre depuis", value=f"{joined_days} jour{'s' if joined_days > 1 else ''}", inline=False)
if reason != "Sans raison":
embed.add_field(name="Raison", value=reason, inline=False)
sent_message = await message.channel.send(embed=embed)
await message.delete()
asyncio.create_task(delete_after_delay(sent_message))
async def handle_unban_command(message: Message, bot):
if not any(role.id == get_staff_role_id() for role in message.author.roles):
embed = discord.Embed(
title="❌ Accès refusé",
description="Vous n'avez pas les permissions nécessaires pour utiliser cette commande.",
color=discord.Color.red()
)
await message.channel.send(embed=embed)
return
parts = message.content.split(maxsplit=2)
if len(parts) < 2:
embed = discord.Embed(
title="📋 Utilisation de la commande",
description="**Syntaxe :** `!unban <discord_id>` ou `!unban #<sanction_id> [raison]`",
color=discord.Color.blue()
)
embed.add_field(name="Exemples", value="• `!unban 123456789012345678`\n• `!unban #5 Appel accepté`", inline=False)
await message.channel.send(embed=embed)
return
reason = parts[2] if len(parts) > 2 else "Sans raison"
target_user = None
discord_id = None
if parts[1].startswith('#'):
try:
sanction_id = int(parts[1][1:])
event = ModerationEvent.query.filter_by(id=sanction_id, type='ban').first()
if not event:
embed = discord.Embed(
title="❌ Erreur",
description=f"Aucune sanction de ban trouvée avec l'ID #{sanction_id}.",
color=discord.Color.red()
)
await message.channel.send(embed=embed)
return
discord_id = event.discord_id
try:
target_user = await bot.fetch_user(int(discord_id))
except discord.NotFound:
pass
except ValueError:
embed = discord.Embed(
title="❌ Erreur",
description="ID de sanction invalide.",
color=discord.Color.red()
)
await message.channel.send(embed=embed)
return
else:
try:
discord_id = parts[1]
target_user = await bot.fetch_user(int(discord_id))
except (ValueError, discord.NotFound):
embed = discord.Embed(
title="❌ Erreur",
description="ID Discord invalide ou utilisateur introuvable.",
color=discord.Color.red()
)
await message.channel.send(embed=embed)
return
try:
await message.guild.unban(discord.Object(id=int(discord_id)), reason=reason)
except discord.NotFound:
embed = discord.Embed(
title="❌ Erreur",
description="Cet utilisateur n'est pas banni.",
color=discord.Color.red()
)
await message.channel.send(embed=embed)
return
except discord.Forbidden:
embed = discord.Embed(
title="❌ Erreur",
description="Je n'ai pas les permissions nécessaires pour débannir cet utilisateur.",
color=discord.Color.red()
)
await message.channel.send(embed=embed)
return
username = target_user.name if target_user else f"ID: {discord_id}"
event = ModerationEvent(
type='unban',
username=username,
discord_id=discord_id,
created_at=datetime.utcnow(),
reason=reason,
staff_id=str(message.author.id),
staff_name=message.author.name
)
db.session.add(event)
db.session.commit()
embed = discord.Embed(
title="⚠️ Sanction",
description=f"L'utilisateur **{username}** (`@{username}`) a été **débanni**.",
color=discord.Color.green()
)
if reason != "Sans raison":
embed.add_field(name="Raison", value=reason, inline=False)
sent_message = await message.channel.send(embed=embed)
await message.delete()
asyncio.create_task(delete_after_delay(sent_message))

View File

@@ -17,6 +17,12 @@ def updateConfiguration():
ConfigurationHelper().createOrUpdate('humble_bundle_enable', False) ConfigurationHelper().createOrUpdate('humble_bundle_enable', False)
if (request.form.get("proton_db_api_id") != None and request.form.get("proton_db_enable_enable") == None) : if (request.form.get("proton_db_api_id") != None and request.form.get("proton_db_enable_enable") == None) :
ConfigurationHelper().createOrUpdate('proton_db_enable_enable', False) ConfigurationHelper().createOrUpdate('proton_db_enable_enable', False)
if (request.form.get("moderation_staff_role_id") != None and request.form.get("moderation_enable") == None) :
ConfigurationHelper().createOrUpdate('moderation_enable', False)
if (request.form.get("moderation_staff_role_id") != None and request.form.get("moderation_ban_enable") == None) :
ConfigurationHelper().createOrUpdate('moderation_ban_enable', False)
if (request.form.get("moderation_staff_role_id") != None and request.form.get("moderation_kick_enable") == None) :
ConfigurationHelper().createOrUpdate('moderation_kick_enable', False)
db.session.commit() db.session.commit()
return redirect(request.referrer) return redirect(request.referrer)

View File

@@ -1,9 +1,24 @@
from flask import render_template from flask import render_template, request, redirect, url_for
from webapp import webapp from webapp import webapp
from database.models import Warning from database import db
from database.models import ModerationEvent
@webapp.route("/moderation") @webapp.route("/moderation")
def moderation(): def moderation():
warnings = Warning.query.order_by(Warning.created_at.desc()).all() events = ModerationEvent.query.order_by(ModerationEvent.created_at.desc()).all()
return render_template("moderation.html", warnings=warnings) return render_template("moderation.html", events=events)
@webapp.route("/moderation/update/<int:event_id>", methods=['POST'])
def update_moderation_event(event_id):
event = ModerationEvent.query.get_or_404(event_id)
event.reason = request.form.get('reason')
db.session.commit()
return redirect(url_for('moderation'))
@webapp.route("/moderation/delete/<int:event_id>")
def delete_moderation_event(event_id):
event = ModerationEvent.query.get_or_404(event_id)
db.session.delete(event)
db.session.commit()
return redirect(url_for('moderation'))

View File

@@ -55,4 +55,32 @@
</select> </select>
<input type="Submit" value="Définir"> <input type="Submit" value="Définir">
</form> </form>
<h2>Modération Discord</h2>
<form action="{{ url_for('updateConfiguration') }}" method="POST">
<label for="moderation_enable">Activer les avertissements</label>
<input type="checkbox" name="moderation_enable" {% if configuration.getValue('moderation_enable') %}
checked="checked" {% endif %}>
<label>Activer les commandes d'avertissement (!averto, !delaverto, !listaverto)</label>
<label for="moderation_ban_enable">Activer le ban</label>
<input type="checkbox" name="moderation_ban_enable" {% if configuration.getValue('moderation_ban_enable') %}
checked="checked" {% endif %}>
<label>Activer les commandes de bannissement (!ban, !unban)</label>
<label for="moderation_kick_enable">Activer le kick</label>
<input type="checkbox" name="moderation_kick_enable" {% if configuration.getValue('moderation_kick_enable') %}
checked="checked" {% endif %}>
<label>Activer la commande d'expulsion (!kick)</label>
<label for="moderation_staff_role_id">ID du rôle Staff</label>
<input name="moderation_staff_role_id" type="text" value="{{ configuration.getValue('moderation_staff_role_id') }}"
placeholder="581990740431732738" />
<label for="moderation_embed_delete_delay">Délai de suppression des embeds (en secondes, 0 = ne pas supprimer)</label>
<input name="moderation_embed_delete_delay" type="number" value="{{ configuration.getValue('moderation_embed_delete_delay') or '0' }}"
placeholder="0" min="0" />
<input type="Submit" value="Définir">
</form>
{% endblock %} {% endblock %}

View File

@@ -2,25 +2,39 @@
{% block content %} {% block content %}
<h1>Modération Discord</h1> <h1>Modération Discord</h1>
<p>Liste des avertissements émis sur le serveur Discord.</p> <p>Historique des actions de modération sur le serveur Discord.</p>
<table> <table>
<thead> <thead>
<tr> <tr>
<th>ID</th>
<th>Type</th>
<th>Utilisateur</th> <th>Utilisateur</th>
<th>Discord ID</th> <th>Discord ID</th>
<th>Date & Heure</th> <th>Date & Heure</th>
<th>Raison</th> <th>Raison</th>
<th>Staff</th> <th>Staff</th>
<th>Actions</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for warning in warnings %} {% for event in events %}
<tr> <tr>
<td>{{ warning.username }}</td> <td>{{ event.id }}</td>
<td>{{ warning.discord_id }}</td> <td>{{ event.type }}</td>
<td>{{ warning.created_at.strftime('%d/%m/%Y %H:%M') if warning.created_at else 'N/A' }}</td> <td>{{ event.username }}</td>
<td>{{ warning.reason }}</td> <td>{{ event.discord_id }}</td>
<td>{{ warning.staff_name }}</td> <td>{{ event.created_at.strftime('%d/%m/%Y %H:%M') if event.created_at else 'N/A' }}</td>
<td>
<form action="{{ url_for('update_moderation_event', event_id = event.id) }}" method="POST" style="margin: 0;">
<input name="reason" type="text" value="{{ event.reason }}" style="width: 100%;" />
</form>
</td>
<td>{{ event.staff_name }}</td>
<td>
<a href="javascript:void(0)" onclick="this.parentElement.parentElement.querySelector('form').submit()">Modifier</a>
|
<a href="{{ url_for('delete_moderation_event', event_id = event.id) }}" onclick="return confirm('Êtes-vous sûr de vouloir supprimer cet événement ?')">🗑️ Supprimer</a>
</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>