Résolution de la gestion de la time zone

!aide ajouté
This commit is contained in:
Mow
2025-11-02 20:05:17 +01:00
parent eb9bf0e67e
commit 18a883c27b
2 changed files with 115 additions and 64 deletions

View File

@@ -130,6 +130,7 @@ 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']: if command_name in ['!aide', '!help']:
await handle_staff_help_command(message, bot) await handle_staff_help_command(message, bot)
return return

View File

@@ -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,24 +653,55 @@ 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('proton_db_enable_enable'):
public_commands.append(
"**🎮 ProtonDB**\n"
"• `!protondb <nom du jeu>` ou `!pdb <nom du jeu>`\n"
"Recherche un jeu sur ProtonDB pour vérifier sa compatibilité Linux\n"
"Ex: `!pdb Elden Ring`"
)
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(
name="📝 Commandes publiques",
value="Aucune commande publique configurée pour le moment.",
inline=False
)
if is_staff:
embed.add_field(
name="━━━━━━━━━━━━━━━━━━━━━━━━━━━━",
value="**🛠️ COMMANDES STAFF**",
inline=False
)
if ConfigurationHelper().getValue('moderation_enable'): if ConfigurationHelper().getValue('moderation_enable'):
value = ( value = (
"• `!averto @utilisateur [raison]`\n" "• `!averto @utilisateur [raison]`\n"
@@ -661,7 +713,6 @@ async def handle_staff_help_command(message: Message, bot):
"`!warnings @User`" "`!warnings @User`"
) )
embed.add_field(name="⚠️ Avertissements", value=value, inline=False) embed.add_field(name="⚠️ Avertissements", value=value, inline=False)
# Inspect
embed.add_field( embed.add_field(
name="🔎 Inspection", name="🔎 Inspection",
value=("• `!inspect @utilisateur` ou `!inspect <id>`\n" value=("• `!inspect @utilisateur` ou `!inspect <id>`\n"
@@ -669,7 +720,6 @@ async def handle_staff_help_command(message: Message, bot):
inline=False inline=False
) )
# Bans / Unban
if ConfigurationHelper().getValue('moderation_ban_enable'): if ConfigurationHelper().getValue('moderation_ban_enable'):
value = ( value = (
"• `!ban @utilisateur [raison]`\n" "• `!ban @utilisateur [raison]`\n"
@@ -682,7 +732,6 @@ async def handle_staff_help_command(message: Message, bot):
) )
embed.add_field(name="🔨 Ban / Unban", value=value, inline=False) embed.add_field(name="🔨 Ban / Unban", value=value, inline=False)
# Kick
if ConfigurationHelper().getValue('moderation_kick_enable'): if ConfigurationHelper().getValue('moderation_kick_enable'):
value = ( value = (
"• `!kick @utilisateur [raison]`\n" "• `!kick @utilisateur [raison]`\n"
@@ -692,6 +741,7 @@ async def handle_staff_help_command(message: Message, bot):
try: try:
sent = await message.channel.send(embed=embed) sent = await message.channel.send(embed=embed)
if is_staff:
asyncio.create_task(delete_after_delay(sent)) asyncio.create_task(delete_after_delay(sent))
except Exception: except Exception:
pass pass
@@ -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: