Mise à jour du système d'absence staff

This commit is contained in:
Mathis 2026-05-16 20:02:53 +02:00
parent ae2347c7ce
commit d8b2f06f86
3 changed files with 108 additions and 105 deletions

View file

@ -152,23 +152,30 @@ class AbsenceModal(disnake.ui.Modal):
now = get_paris_now() now = get_paris_now()
etat = "à venir" if debut > now else "en cours" etat = "à venir" if debut > now else "en cours"
# Message dans le salon # Message dans le salon avec V2 Components
absence_message = await channel.send( components = [
f"# ABSENCE STAFF :\n" disnake.ui.Container(
f"- **Pseudo Discord** : {interaction.user.mention}\n" disnake.ui.Section(
f"- **Durée prévue** : {duree_str}\n" f"# ABSENCE STAFF\n**👤 Membre** : {interaction.user.mention}",
f"- **Débute le** : {self.date_debut.value} (Paris)\n" accessory=disnake.ui.Thumbnail(interaction.user.display_avatar.url)
f"- **Termine le** : {self.date_fin.value} (Paris)\n" ),
f"- **Motif** : {self.motif.value}\n" disnake.ui.Separator(),
f"- **Mention du supérieur hiérarchique** : {self.superieur.mention if self.superieur else 'Aucun'}" disnake.ui.TextDisplay(f"**⏳ Durée** : {duree_str}"),
disnake.ui.TextDisplay(f"**📅 Période** : `{val_debut}` ➔ `{val_fin}`"),
disnake.ui.TextDisplay(f"**📝 Motif** : {motif}"),
disnake.ui.TextDisplay(f"**🛡️ Supérieur** : {self.superieur.mention if self.superieur else 'Aucun'}")
) )
]
absence_message = await channel.send(components=components)
# Enregistrement # Enregistrement
guild_abs[str(interaction.user.id)] = { guild_abs[str(interaction.user.id)] = {
"pseudo": interaction.user.name, "pseudo": interaction.user.name,
"debut": self.date_debut.value, "avatar_url": interaction.user.display_avatar.url,
"fin": self.date_fin.value, "debut": val_debut,
"motif": self.motif.value, "fin": val_fin,
"duree": duree_str,
"motif": motif,
"superieur": self.superieur.mention if self.superieur else "Aucun", "superieur": self.superieur.mention if self.superieur else "Aucun",
"message_id": absence_message.id, "message_id": absence_message.id,
"etat": etat "etat": etat
@ -190,63 +197,55 @@ class AbsenceModal(disnake.ui.Modal):
await interaction.response.send_message("✅ Absence enregistrée avec succès !", ephemeral=True) await interaction.response.send_message("✅ Absence enregistrée avec succès !", ephemeral=True)
class AbsenceConfigView(disnake.ui.View): class AbsenceConfigView(disnake.ui.View):
def __init__(self, guild_id: int): def __init__(self, guild_id: int, bot):
super().__init__(timeout=60) super().__init__(timeout=300)
self.guild_id = guild_id self.guild_id = guild_id
self.bot = bot
@disnake.ui.button(label="Définir le Salon", style=disnake.ButtonStyle.primary, emoji="📁") @disnake.ui.channel_select(placeholder="Sélectionnez le salon d'affichage", min_values=1, max_values=1)
async def set_channel(self, button: disnake.ui.Button, interaction: disnake.Interaction): async def select_channel(self, select: disnake.ui.ChannelSelect, interaction: disnake.MessageInteraction):
await interaction.response.send_message("Mentionne le salon ici (ou envoie son ID) :", ephemeral=True) channel = select.values[0]
def check(m):
return m.author == interaction.user and m.channel == interaction.channel
try:
msg = await interaction.bot.wait_for('message', check=check, timeout=30)
channel = None
if msg.channel_mentions:
channel = msg.channel_mentions[0]
elif msg.content.isdigit():
channel = interaction.guild.get_channel(int(msg.content))
if not channel:
return await interaction.followup.send("❌ Salon invalide.", ephemeral=True)
settings = load_settings(self.guild_id) settings = load_settings(self.guild_id)
settings["absence_channel_id"] = channel.id settings["absence_channel_id"] = channel.id
save_settings(self.guild_id, settings) save_settings(self.guild_id, settings)
# Update the original message with new settings
embed = self._get_updated_embed(settings, interaction.guild)
await interaction.response.edit_message(embed=embed, view=self)
await interaction.followup.send(f"✅ Salon d'absence configuré sur {channel.mention}", ephemeral=True) await interaction.followup.send(f"✅ Salon d'absence configuré sur {channel.mention}", ephemeral=True)
try: await msg.delete()
except: pass
except asyncio.TimeoutError:
await interaction.followup.send("❌ Temps écoulé.", ephemeral=True)
@disnake.ui.button(label="Définir le Rôle", style=disnake.ButtonStyle.primary, emoji="🎭")
async def set_role(self, button: disnake.ui.Button, interaction: disnake.Interaction):
await interaction.response.send_message("Mentionne le rôle ici (ou envoie son ID) :", ephemeral=True)
def check(m):
return m.author == interaction.user and m.channel == interaction.channel
try:
msg = await interaction.bot.wait_for('message', check=check, timeout=30)
role = None
if msg.role_mentions:
role = msg.role_mentions[0]
elif msg.content.isdigit():
role = interaction.guild.get_role(int(msg.content))
if not role:
return await interaction.followup.send("❌ Rôle invalide.", ephemeral=True)
@disnake.ui.role_select(placeholder="Sélectionnez le rôle d'absence", min_values=1, max_values=1)
async def select_role(self, select: disnake.ui.RoleSelect, interaction: disnake.MessageInteraction):
role = select.values[0]
settings = load_settings(self.guild_id) settings = load_settings(self.guild_id)
settings["absence_role_id"] = role.id settings["absence_role_id"] = role.id
save_settings(self.guild_id, settings) save_settings(self.guild_id, settings)
# Update the original message with new settings
embed = self._get_updated_embed(settings, interaction.guild)
await interaction.response.edit_message(embed=embed, view=self)
await interaction.followup.send(f"✅ Rôle d'absence configuré sur **{role.name}**", ephemeral=True) await interaction.followup.send(f"✅ Rôle d'absence configuré sur **{role.name}**", ephemeral=True)
try: await msg.delete()
except: pass def _get_updated_embed(self, settings, guild):
except asyncio.TimeoutError: channel_id = settings.get("absence_channel_id")
await interaction.followup.send("❌ Temps écoulé.", ephemeral=True) role_id = settings.get("absence_role_id")
embed = disnake.Embed(
title="⚙️ Configuration des Absences Staff",
description="Utilisez les menus déroulants ci-dessous pour configurer le système.",
color=disnake.Color.blue()
)
embed.add_field(
name="📁 Salon d'affichage",
value=f"<#{channel_id}>" if channel_id else "❌ Non configuré",
inline=True
)
embed.add_field(
name="🎭 Rôle d'absence",
value=f"<@&{role_id}>" if role_id else "❌ Non configuré",
inline=True
)
return embed
class Absence(commands.Cog): class Absence(commands.Cog):
def __init__(self, bot): def __init__(self, bot):
@ -285,29 +284,55 @@ class Absence(commands.Cog):
inline=True inline=True
) )
await interaction.response.send_message(embed=embed, view=AbsenceConfigView(interaction.guild.id), ephemeral=True) await interaction.response.send_message(embed=embed, view=AbsenceConfigView(interaction.guild.id, self.bot), ephemeral=True)
async def strike_absence_message(self, guild: disnake.Guild, channel_id: int, message_id: int): async def strike_absence_message(self, guild: disnake.Guild, channel_id: int, message_id: int, info: dict = None):
"""Modifie le message d'absence pour le barrer au lieu de le supprimer""" """Modifie le message d'absence pour le barrer au lieu de le supprimer"""
channel = guild.get_channel(channel_id) channel = guild.get_channel(channel_id)
if not channel: if not channel:
try: try: channel = await guild.fetch_channel(channel_id)
channel = await guild.fetch_channel(channel_id) except: return
except:
return
try: try:
msg = await channel.fetch_message(message_id) msg = await channel.fetch_message(message_id)
content = msg.content
if "~~" in content: # Déjà barré # Gestion des Rich Components V2
if info:
avatar_url = info.get("avatar_url")
if avatar_url:
header_component = disnake.ui.Section(
f"## ~~ABSENCE STAFF [TERMINÉ]~~\n~~**👤 Membre** : {info.get('pseudo', 'Inconnu')}~~",
accessory=disnake.ui.Thumbnail(avatar_url)
)
else:
header_component = disnake.ui.TextDisplay(f"## ~~ABSENCE STAFF [TERMINÉ]~~\n~~**👤 Membre** : {info.get('pseudo', 'Inconnu')}~~")
components = [
disnake.ui.Container(
header_component,
disnake.ui.Separator(),
disnake.ui.TextDisplay(f"~~**⏳ Durée** : {info.get('duree', 'N/A')}~~"),
disnake.ui.TextDisplay(f"~~**📅 Période** : {info.get('debut')}{info.get('fin')}~~"),
disnake.ui.TextDisplay(f"~~**📝 Motif** : {info.get('motif')}~~"),
disnake.ui.TextDisplay(f"~~**🛡️ Supérieur** : {info.get('superieur', 'Aucun')}~~")
)
]
print(f"[DEBUG] Tentative d'édition du message V2 {message_id}")
try:
await msg.edit(components=components)
print(f"[DEBUG] Succès édition V2")
except Exception as e:
print(f"[DEBUG] Erreur édition V2: {e}")
return return
# Ancien format (Texte simple) - fallback
content = msg.content
if not content or "~~" in content: return
lines = content.split("\n") lines = content.split("\n")
new_lines = [] new_lines = []
for line in lines: for line in lines:
if line.startswith("# "): if line.startswith("# "):
# Conserver le style header mais barrer le texte
new_lines.append(f"# ~~{line[2:].strip()}~~ [TERMINÉ]") new_lines.append(f"# ~~{line[2:].strip()}~~ [TERMINÉ]")
elif line.strip(): elif line.strip():
new_lines.append(f"~~{line}~~") new_lines.append(f"~~{line}~~")
@ -335,7 +360,7 @@ class Absence(commands.Cog):
channel_id = settings.get("absence_channel_id") channel_id = settings.get("absence_channel_id")
if channel_id and message_id: if channel_id and message_id:
await self.strike_absence_message(interaction.guild, int(channel_id), int(message_id)) await self.strike_absence_message(interaction.guild, int(channel_id), int(message_id), info)
# Retrait du rôle # Retrait du rôle
role_id = settings.get("absence_role_id") role_id = settings.get("absence_role_id")
@ -470,7 +495,7 @@ class Absence(commands.Cog):
message_id = info.get("message_id") message_id = info.get("message_id")
channel_id = settings.get("absence_channel_id") channel_id = settings.get("absence_channel_id")
if channel_id and message_id: if channel_id and message_id:
await self.strike_absence_message(guild, int(channel_id), int(message_id)) await self.strike_absence_message(guild, int(channel_id), int(message_id), info)
to_remove.append(user_id_str) to_remove.append(user_id_str)
changed = True changed = True
@ -507,7 +532,7 @@ class Absence(commands.Cog):
settings = load_settings(message.guild.id) settings = load_settings(message.guild.id)
channel_id = settings.get("absence_channel_id") channel_id = settings.get("absence_channel_id")
absence_url = f"https://disnake.com/channels/{message.guild.id}/{channel_id}/{msg_id}" if channel_id and msg_id else "" absence_url = f"https://discord.com/channels/{message.guild.id}/{channel_id}/{msg_id}" if channel_id and msg_id else ""
reply_text = f"⚠️ {message.author.mention}, cet utilisateur est actuellement absent." reply_text = f"⚠️ {message.author.mention}, cet utilisateur est actuellement absent."
if absence_url: if absence_url:

View file

@ -14,18 +14,9 @@ class WhitelistMonitor(commands.Cog):
self.whitelist_file = "data/whitelist.json" self.whitelist_file = "data/whitelist.json"
self.persistent_views_added = False self.persistent_views_added = False
self.big_permissions = [ self.big_permissions = [
disnake.Permissions.administrator, "administrator", "manage_guild", "manage_roles", "manage_channels",
disnake.Permissions.manage_guild, "kick_members", "ban_members", "manage_messages", "moderate_members",
disnake.Permissions.manage_roles, "manage_nicknames", "manage_emojis", "manage_webhooks", "view_audit_log"
disnake.Permissions.manage_channels,
disnake.Permissions.kick_members,
disnake.Permissions.ban_members,
disnake.Permissions.manage_messages,
disnake.Permissions.moderate_members,
disnake.Permissions.manage_nicknames,
disnake.Permissions.manage_emojis,
disnake.Permissions.manage_webhooks,
disnake.Permissions.view_audit_log
] ]
def load_whitelist(self) -> Dict[str, List[str]]: def load_whitelist(self) -> Dict[str, List[str]]:
@ -72,11 +63,8 @@ class WhitelistMonitor(commands.Cog):
def has_big_permissions(self, role: disnake.Role) -> bool: def has_big_permissions(self, role: disnake.Role) -> bool:
"""Check if role has significant permissions.""" """Check if role has significant permissions."""
permissions = role.permissions perms = role.permissions
for perm in self.big_permissions: return any(getattr(perms, p, False) for p in self.big_permissions)
if permissions.administrator or getattr(permissions, perm.name, False):
return True
return False
async def send_whitelist_notification(self, member: disnake.Member, removed_roles: List[disnake.Role]): async def send_whitelist_notification(self, member: disnake.Member, removed_roles: List[disnake.Role]):
"""Send DM notification to user about whitelist member losing roles.""" """Send DM notification to user about whitelist member losing roles."""

View file

@ -1,13 +1,3 @@
{ {
"1369669999345537145": { "1369669999345537145": {}
"971446412690722826": {
"pseudo": "gameurpro12",
"debut": null,
"fin": null,
"motif": null,
"superieur": "<@353942721997832195>",
"message_id": 1505246281935618138,
"etat": "à venir"
}
}
} }