mirror of
https://github.com/skylanix/MamieHenriette.git
synced 2026-02-16 13:00:39 +01:00
Résolution de la gestion de la time zone
!aide ajouté
This commit is contained in:
@@ -130,9 +130,10 @@ async def on_message(message: Message):
|
|||||||
if command_name == '!inspect':
|
if command_name == '!inspect':
|
||||||
await handle_inspect_command(message, bot)
|
await handle_inspect_command(message, bot)
|
||||||
return
|
return
|
||||||
if command_name in ['!aide', '!help']:
|
|
||||||
await handle_staff_help_command(message, bot)
|
if command_name in ['!aide', '!help']:
|
||||||
return
|
await handle_staff_help_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:
|
||||||
|
|||||||
@@ -1,13 +1,33 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
import time
|
import time
|
||||||
|
import os
|
||||||
import discord
|
import discord
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
|
from zoneinfo import ZoneInfo
|
||||||
from database import db
|
from database import db
|
||||||
from database.helpers import ConfigurationHelper
|
from database.helpers import ConfigurationHelper
|
||||||
from database.models import ModerationEvent
|
from database.models import ModerationEvent
|
||||||
from discord import Message
|
from discord import Message
|
||||||
|
|
||||||
|
def _get_local_tz():
|
||||||
|
tz_name = os.environ.get('APP_TZ') or os.environ.get('TZ') or 'Europe/Paris'
|
||||||
|
try:
|
||||||
|
return ZoneInfo(tz_name)
|
||||||
|
except Exception:
|
||||||
|
try:
|
||||||
|
return datetime.now().astimezone().tzinfo or timezone.utc
|
||||||
|
except Exception:
|
||||||
|
return timezone.utc
|
||||||
|
|
||||||
|
def _to_local(dt: datetime) -> datetime | None:
|
||||||
|
if not dt:
|
||||||
|
return None
|
||||||
|
if dt.tzinfo is None:
|
||||||
|
# Assume stored in UTC if naive
|
||||||
|
dt = dt.replace(tzinfo=timezone.utc)
|
||||||
|
return dt.astimezone(_get_local_tz())
|
||||||
|
|
||||||
def get_staff_role_ids():
|
def get_staff_role_ids():
|
||||||
staff_roles = ConfigurationHelper().getValue('moderation_staff_role_ids')
|
staff_roles = ConfigurationHelper().getValue('moderation_staff_role_ids')
|
||||||
if staff_roles:
|
if staff_roles:
|
||||||
@@ -87,7 +107,7 @@ def create_warning_event(target_user, reason: str, staff_member):
|
|||||||
type='warning',
|
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.now(timezone.utc),
|
||||||
reason=reason,
|
reason=reason,
|
||||||
staff_id=str(staff_member.id),
|
staff_id=str(staff_member.id),
|
||||||
staff_name=staff_member.name
|
staff_name=staff_member.name
|
||||||
@@ -177,7 +197,7 @@ async def send_event_deleted_confirmation(channel, event: ModerationEvent, moder
|
|||||||
title="✅ Événement supprimé",
|
title="✅ Événement supprimé",
|
||||||
description=f"L'événement de type **{event.type}** pour **{event.username}** (ID: {event.id}) a été supprimé.",
|
description=f"L'événement de type **{event.type}** pour **{event.username}** (ID: {event.id}) a été supprimé.",
|
||||||
color=discord.Color.green(),
|
color=discord.Color.green(),
|
||||||
timestamp=datetime.utcnow()
|
timestamp=datetime.now(timezone.utc)
|
||||||
)
|
)
|
||||||
embed.add_field(name="🛡️ Modérateur", value=f"{moderator.name}\n`{moderator.id}`", inline=True)
|
embed.add_field(name="🛡️ Modérateur", value=f"{moderator.name}\n`{moderator.id}`", inline=True)
|
||||||
embed.set_footer(text="Mamie Henriette")
|
embed.set_footer(text="Mamie Henriette")
|
||||||
@@ -234,11 +254,12 @@ def create_events_list_embed(events: list, page_num: int, per_page: int):
|
|||||||
title="📋 Liste des événements de modération",
|
title="📋 Liste des événements de modération",
|
||||||
description=f"Total : {len(events)} événement(s)",
|
description=f"Total : {len(events)} événement(s)",
|
||||||
color=discord.Color.blue(),
|
color=discord.Color.blue(),
|
||||||
timestamp=datetime.utcnow()
|
timestamp=datetime.now(timezone.utc)
|
||||||
)
|
)
|
||||||
|
|
||||||
for event in page_events:
|
for event in page_events:
|
||||||
date_str = event.created_at.strftime('%d/%m/%Y %H:%M') if event.created_at else 'N/A'
|
local_dt = _to_local(event.created_at)
|
||||||
|
date_str = local_dt.strftime('%d/%m/%Y %H:%M') if local_dt else 'N/A'
|
||||||
embed.add_field(
|
embed.add_field(
|
||||||
name=f"ID {event.id} - {event.type.upper()} - {event.username}",
|
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}",
|
value=f"**Discord ID:** `{event.discord_id}`\n**Date:** {date_str}\n**Raison:** {event.reason}\n**Staff:** {event.staff_name}",
|
||||||
@@ -351,7 +372,7 @@ def _create_ban_event(target_user, reason: str, staff_member):
|
|||||||
type='ban',
|
type='ban',
|
||||||
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.now(timezone.utc),
|
||||||
reason=reason,
|
reason=reason,
|
||||||
staff_id=str(staff_member.id),
|
staff_id=str(staff_member.id),
|
||||||
staff_name=staff_member.name
|
staff_name=staff_member.name
|
||||||
@@ -364,7 +385,7 @@ async def _process_ban_success(message: Message, target_user, reason: str):
|
|||||||
member = message.guild.get_member(target_user.id)
|
member = message.guild.get_member(target_user.id)
|
||||||
joined_days = None
|
joined_days = None
|
||||||
if member and member.joined_at:
|
if member and member.joined_at:
|
||||||
delta = datetime.utcnow() - member.joined_at.replace(tzinfo=None)
|
delta = datetime.now(timezone.utc) - (member.joined_at if member.joined_at.tzinfo else member.joined_at.replace(tzinfo=timezone.utc))
|
||||||
joined_days = delta.days
|
joined_days = delta.days
|
||||||
try:
|
try:
|
||||||
await message.guild.ban(target_user, reason=reason)
|
await message.guild.ban(target_user, reason=reason)
|
||||||
@@ -473,7 +494,7 @@ async def _process_unban_success(message: Message, bot, target_user, discord_id:
|
|||||||
type='unban',
|
type='unban',
|
||||||
username=username,
|
username=username,
|
||||||
discord_id=discord_id,
|
discord_id=discord_id,
|
||||||
created_at=datetime.utcnow(),
|
created_at=datetime.now(timezone.utc),
|
||||||
reason=reason,
|
reason=reason,
|
||||||
staff_id=str(message.author.id),
|
staff_id=str(message.author.id),
|
||||||
staff_name=message.author.name
|
staff_name=message.author.name
|
||||||
@@ -586,7 +607,7 @@ async def handle_ban_list_command(message: Message, bot):
|
|||||||
title="🔨 Utilisateurs bannis",
|
title="🔨 Utilisateurs bannis",
|
||||||
description=f"Total : {len(bans)} utilisateur(s) banni(s)",
|
description=f"Total : {len(bans)} utilisateur(s) banni(s)",
|
||||||
color=discord.Color.red(),
|
color=discord.Color.red(),
|
||||||
timestamp=datetime.utcnow()
|
timestamp=datetime.now(timezone.utc)
|
||||||
)
|
)
|
||||||
for entry in page_bans:
|
for entry in page_bans:
|
||||||
user = entry.user
|
user = entry.user
|
||||||
@@ -632,67 +653,96 @@ async def handle_ban_list_command(message: Message, bot):
|
|||||||
await safe_delete_message(message)
|
await safe_delete_message(message)
|
||||||
|
|
||||||
async def handle_staff_help_command(message: Message, bot):
|
async def handle_staff_help_command(message: Message, bot):
|
||||||
if not has_staff_role(message.author.roles):
|
is_staff = has_staff_role(message.author.roles)
|
||||||
embed = discord.Embed(
|
|
||||||
title="❌ Accès refusé",
|
|
||||||
description="Cette commande est réservée au staff.",
|
|
||||||
color=discord.Color.red()
|
|
||||||
)
|
|
||||||
await message.channel.send(embed=embed)
|
|
||||||
return
|
|
||||||
|
|
||||||
embed = discord.Embed(
|
embed = discord.Embed(
|
||||||
title="🛠️ Aide staff",
|
title="📚 Aide - Commandes disponibles",
|
||||||
description="Commandes de modération disponibles",
|
description="Liste de toutes les commandes disponibles",
|
||||||
color=discord.Color.blurple(),
|
color=discord.Color.blurple(),
|
||||||
timestamp=datetime.utcnow()
|
timestamp=datetime.now(timezone.utc)
|
||||||
)
|
)
|
||||||
|
embed.set_thumbnail(url=bot.user.display_avatar.url)
|
||||||
embed.set_footer(text=f"Demandé par {message.author.name}")
|
embed.set_footer(text=f"Demandé par {message.author.name}")
|
||||||
|
|
||||||
# Avertissements
|
public_commands = []
|
||||||
if ConfigurationHelper().getValue('moderation_enable'):
|
|
||||||
value = (
|
if ConfigurationHelper().getValue('proton_db_enable_enable'):
|
||||||
"• `!averto @utilisateur [raison]`\n"
|
public_commands.append(
|
||||||
"• `!delaverto <id>`\n"
|
"**🎮 ProtonDB**\n"
|
||||||
"• `!warnings` ou `!warnings @utilisateur`\n"
|
"• `!protondb <nom du jeu>` ou `!pdb <nom du jeu>`\n"
|
||||||
"Exemples:\n"
|
"Recherche un jeu sur ProtonDB pour vérifier sa compatibilité Linux\n"
|
||||||
"`!averto @User Spam`\n"
|
"Ex: `!pdb Elden Ring`"
|
||||||
"`!delaverto 12`\n"
|
|
||||||
"`!warnings @User`"
|
|
||||||
)
|
)
|
||||||
embed.add_field(name="⚠️ Avertissements", value=value, inline=False)
|
|
||||||
# Inspect
|
from database.models import Commande
|
||||||
|
custom_commands = Commande.query.filter_by(discord_enable=True).all()
|
||||||
|
if custom_commands:
|
||||||
|
commands_list = []
|
||||||
|
for cmd in custom_commands:
|
||||||
|
commands_list.append(f"• `{cmd.trigger}`")
|
||||||
|
custom_text = "\n".join(commands_list[:10])
|
||||||
|
if len(custom_commands) > 10:
|
||||||
|
custom_text += f"\n*... et {len(custom_commands) - 10} autres*"
|
||||||
|
public_commands.append(f"**🤖 Commandes personnalisées**\n{custom_text}")
|
||||||
|
|
||||||
|
if public_commands:
|
||||||
|
for cmd_text in public_commands:
|
||||||
|
embed.add_field(name="\u200b", value=cmd_text, inline=False)
|
||||||
|
else:
|
||||||
embed.add_field(
|
embed.add_field(
|
||||||
name="🔎 Inspection",
|
name="📝 Commandes publiques",
|
||||||
value=("• `!inspect @utilisateur` ou `!inspect <id>`\n"
|
value="Aucune commande publique configurée pour le moment.",
|
||||||
"Ex: `!inspect @User`"),
|
|
||||||
inline=False
|
inline=False
|
||||||
)
|
)
|
||||||
|
|
||||||
# Bans / Unban
|
if is_staff:
|
||||||
if ConfigurationHelper().getValue('moderation_ban_enable'):
|
embed.add_field(
|
||||||
value = (
|
name="━━━━━━━━━━━━━━━━━━━━━━━━━━━━",
|
||||||
"• `!ban @utilisateur [raison]`\n"
|
value="**🛠️ COMMANDES STAFF**",
|
||||||
"• `!unban <discord_id>` ou `!unban #<sanction_id> [raison]`\n"
|
inline=False
|
||||||
"• `!banlist`\n"
|
|
||||||
"Exemples:\n"
|
|
||||||
"`!ban @User Toxicité`\n"
|
|
||||||
"`!unban 123456789012345678 Erreur`\n"
|
|
||||||
"`!unban #5 Appel accepté`"
|
|
||||||
)
|
)
|
||||||
embed.add_field(name="🔨 Ban / Unban", value=value, inline=False)
|
|
||||||
|
if ConfigurationHelper().getValue('moderation_enable'):
|
||||||
|
value = (
|
||||||
|
"• `!averto @utilisateur [raison]`\n"
|
||||||
|
"• `!delaverto <id>`\n"
|
||||||
|
"• `!warnings` ou `!warnings @utilisateur`\n"
|
||||||
|
"Exemples:\n"
|
||||||
|
"`!averto @User Spam`\n"
|
||||||
|
"`!delaverto 12`\n"
|
||||||
|
"`!warnings @User`"
|
||||||
|
)
|
||||||
|
embed.add_field(name="⚠️ Avertissements", value=value, inline=False)
|
||||||
|
embed.add_field(
|
||||||
|
name="🔎 Inspection",
|
||||||
|
value=("• `!inspect @utilisateur` ou `!inspect <id>`\n"
|
||||||
|
"Ex: `!inspect @User`"),
|
||||||
|
inline=False
|
||||||
|
)
|
||||||
|
|
||||||
# Kick
|
if ConfigurationHelper().getValue('moderation_ban_enable'):
|
||||||
if ConfigurationHelper().getValue('moderation_kick_enable'):
|
value = (
|
||||||
value = (
|
"• `!ban @utilisateur [raison]`\n"
|
||||||
"• `!kick @utilisateur [raison]`\n"
|
"• `!unban <discord_id>` ou `!unban #<sanction_id> [raison]`\n"
|
||||||
"Exemple: `!kick @User Spam`"
|
"• `!banlist`\n"
|
||||||
)
|
"Exemples:\n"
|
||||||
embed.add_field(name="👢 Kick", value=value, inline=False)
|
"`!ban @User Toxicité`\n"
|
||||||
|
"`!unban 123456789012345678 Erreur`\n"
|
||||||
|
"`!unban #5 Appel accepté`"
|
||||||
|
)
|
||||||
|
embed.add_field(name="🔨 Ban / Unban", value=value, inline=False)
|
||||||
|
|
||||||
|
if ConfigurationHelper().getValue('moderation_kick_enable'):
|
||||||
|
value = (
|
||||||
|
"• `!kick @utilisateur [raison]`\n"
|
||||||
|
"Exemple: `!kick @User Spam`"
|
||||||
|
)
|
||||||
|
embed.add_field(name="👢 Kick", value=value, inline=False)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
sent = await message.channel.send(embed=embed)
|
sent = await message.channel.send(embed=embed)
|
||||||
asyncio.create_task(delete_after_delay(sent))
|
if is_staff:
|
||||||
|
asyncio.create_task(delete_after_delay(sent))
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
await safe_delete_message(message)
|
await safe_delete_message(message)
|
||||||
@@ -729,7 +779,7 @@ async def _process_kick_success(message: Message, target_member, reason: str):
|
|||||||
return
|
return
|
||||||
joined_days = None
|
joined_days = None
|
||||||
if member_obj.joined_at:
|
if member_obj.joined_at:
|
||||||
delta = datetime.utcnow() - member_obj.joined_at.replace(tzinfo=None)
|
delta = datetime.now(timezone.utc) - (member_obj.joined_at if member_obj.joined_at.tzinfo else member_obj.joined_at.replace(tzinfo=timezone.utc))
|
||||||
joined_days = delta.days
|
joined_days = delta.days
|
||||||
try:
|
try:
|
||||||
await message.guild.kick(member_obj, reason=reason)
|
await message.guild.kick(member_obj, reason=reason)
|
||||||
@@ -745,7 +795,7 @@ async def _process_kick_success(message: Message, target_member, reason: str):
|
|||||||
type='kick',
|
type='kick',
|
||||||
username=target_member.name,
|
username=target_member.name,
|
||||||
discord_id=str(target_member.id),
|
discord_id=str(target_member.id),
|
||||||
created_at=datetime.utcnow(),
|
created_at=datetime.now(timezone.utc),
|
||||||
reason=reason,
|
reason=reason,
|
||||||
staff_id=str(message.author.id),
|
staff_id=str(message.author.id),
|
||||||
staff_name=message.author.name
|
staff_name=message.author.name
|
||||||
@@ -821,7 +871,7 @@ def create_inspect_embed(user, member, join_date, days_on_server, account_age, w
|
|||||||
embed = discord.Embed(
|
embed = discord.Embed(
|
||||||
title=f"🔍 Inspection de {user.name}",
|
title=f"🔍 Inspection de {user.name}",
|
||||||
color=discord.Color.blue(),
|
color=discord.Color.blue(),
|
||||||
timestamp=datetime.utcnow()
|
timestamp=datetime.now(timezone.utc)
|
||||||
)
|
)
|
||||||
|
|
||||||
embed.set_thumbnail(url=user.display_avatar.url)
|
embed.set_thumbnail(url=user.display_avatar.url)
|
||||||
@@ -830,14 +880,14 @@ def create_inspect_embed(user, member, join_date, days_on_server, account_age, w
|
|||||||
if account_age is not None:
|
if account_age is not None:
|
||||||
embed.add_field(
|
embed.add_field(
|
||||||
name="📅 Compte créé",
|
name="📅 Compte créé",
|
||||||
value=f"{user.created_at.strftime('%d/%m/%Y')}\n({format_days_to_age(account_age)})",
|
value=f"{_to_local(user.created_at).strftime('%d/%m/%Y')}\n({format_days_to_age(account_age)})",
|
||||||
inline=True
|
inline=True
|
||||||
)
|
)
|
||||||
|
|
||||||
if member and join_date:
|
if member and join_date:
|
||||||
embed.add_field(
|
embed.add_field(
|
||||||
name="📥 Rejoint le serveur",
|
name="📥 Rejoint le serveur",
|
||||||
value=f"{join_date.strftime('%d/%m/%Y à %H:%M')}\n({format_days_to_age(days_on_server)})",
|
value=f"{_to_local(join_date).strftime('%d/%m/%Y à %H:%M')}\n({format_days_to_age(days_on_server)})",
|
||||||
inline=True
|
inline=True
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -858,7 +908,7 @@ def create_inspect_embed(user, member, join_date, days_on_server, account_age, w
|
|||||||
if warnings:
|
if warnings:
|
||||||
recent_warnings = warnings[:3]
|
recent_warnings = warnings[:3]
|
||||||
warnings_detail = "\n".join([
|
warnings_detail = "\n".join([
|
||||||
f"• ID {w.id} - {w.created_at.strftime('%d/%m/%Y')} - {w.reason[:50]}{'...' if len(w.reason) > 50 else ''}"
|
f"• ID {w.id} - {_to_local(w.created_at).strftime('%d/%m/%Y')} - {w.reason[:50]}{'...' if len(w.reason) > 50 else ''}"
|
||||||
for w in recent_warnings
|
for w in recent_warnings
|
||||||
])
|
])
|
||||||
if len(warnings) > 3:
|
if len(warnings) > 3:
|
||||||
|
|||||||
Reference in New Issue
Block a user