Vicy_Publique/commandes/annonces_sessions.py

223 lines
10 KiB
Python
Raw Permalink Normal View History

2026-08-16 19:37:15 +02:00
import discord
from discord import app_commands
from discord.ext import commands, tasks
import dateparser
from datetime import datetime, timezone
from utils.guild_config import get_role_id
2026-08-16 19:37:15 +02:00
presence_data = {}
class PresenceView(discord.ui.View):
def __init__(self, message_id):
super().__init__(timeout=None)
self.message_id = message_id
async def update_message(self, interaction, state):
user_id = interaction.user.id
if self.message_id not in presence_data:
presence_data[self.message_id] = {
"present": set(), "absent": set(), "retard": set(),
"date": None, "sent_dm": False,
"reminder1": None, "reminder2": None,
"reminder1_sent": False, "reminder2_sent": False,
"channel_id": None, "guild_id": None
}
for key in ["present", "absent", "retard"]:
presence_data[self.message_id][key].discard(user_id)
presence_data[self.message_id][state].add(user_id)
n_present = len(presence_data[self.message_id]["present"])
n_absent = len(presence_data[self.message_id]["absent"])
n_retard = len(presence_data[self.message_id]["retard"])
msg = await interaction.channel.fetch_message(self.message_id)
lines = msg.content.split('\n')
# On modifie uniquement les lignes de présence
for i, line in enumerate(lines):
if line.startswith("> - Je serai présent"):
lines[i] = f"> - Je serai présent : <:check:1297296859206778911> **({n_present})**"
elif line.startswith("> - Je serai absent"):
lines[i] = f"> - Je serai absent : <:uncheck:1297296882778902598> **({n_absent})**"
elif line.startswith("> - Je serai en retard"):
lines[i] = f"> - Je serai en retard : ⏰ **({n_retard})**"
new_content = '\n'.join(lines)
await msg.edit(content=new_content, view=self)
@discord.ui.button(label="Présent", style=discord.ButtonStyle.success, emoji="✅", custom_id="presence_present")
async def present(self, interaction: discord.Interaction, button: discord.ui.Button):
await self.update_message(interaction, "present")
await interaction.response.send_message("Merci, tu as été noté comme **présent** à la session RP !", ephemeral=True)
@discord.ui.button(label="Absent", style=discord.ButtonStyle.danger, emoji="❌", custom_id="presence_absent")
async def absent(self, interaction: discord.Interaction, button: discord.ui.Button):
await self.update_message(interaction, "absent")
await interaction.response.send_message("Merci, tu as été noté comme **absent** à la session RP.", ephemeral=True)
@discord.ui.button(label="En retard", style=discord.ButtonStyle.primary, emoji="⏰", custom_id="presence_retard")
async def retard(self, interaction: discord.Interaction, button: discord.ui.Button):
await self.update_message(interaction, "retard")
await interaction.response.send_message("Merci, tu as été noté comme **en retard** pour la session RP.", ephemeral=True)
class AnnonceSession(commands.Cog):
def __init__(self, bot):
self.bot = bot
self.check_sessions.start()
def cog_unload(self):
self.check_sessions.cancel()
@app_commands.command(
name="annonce_session",
description="Annonce une session RP avec image, rappels et boutons de présence."
)
@app_commands.describe(
date="Date de la session (ex: Vendredi 20 Juin à 20h45)",
reminder1="Date/heure du 1er rappel (ex: Jeudi 19 Juin à 19h)",
reminder2="Date/heure du 2e rappel (ex: Vendredi 20 Juin à 15h)",
image="Image à joindre (obligatoire)"
)
async def annonce_session(
self,
interaction: discord.Interaction,
date: str,
reminder1: str,
reminder2: str,
image: discord.Attachment
):
if not image.content_type or not image.content_type.startswith("image/"):
await interaction.response.send_message(
"❌ Le fichier joint doit être une image valide.", ephemeral=True
)
return
# On parse toutes les dates en Europe/Paris
session_date = dateparser.parse(
date, languages=['fr'],
settings={"TIMEZONE": "Europe/Paris", "RETURN_AS_TIMEZONE_AWARE": True}
)
reminder1_date = dateparser.parse(
reminder1, languages=['fr'],
settings={"TIMEZONE": "Europe/Paris", "RETURN_AS_TIMEZONE_AWARE": True}
)
reminder2_date = dateparser.parse(
reminder2, languages=['fr'],
settings={"TIMEZONE": "Europe/Paris", "RETURN_AS_TIMEZONE_AWARE": True}
)
if not session_date or not reminder1_date or not reminder2_date:
await interaction.response.send_message(
"❌ Une des dates n'a pas été comprise. Vérifie le format.", ephemeral=True
)
return
session_date = session_date.astimezone(timezone.utc)
reminder1_date = reminder1_date.astimezone(timezone.utc)
reminder2_date = reminder2_date.astimezone(timezone.utc)
ping_role_id = get_role_id(interaction.guild.id, "citoyen")
reminder_role_id = get_role_id(interaction.guild.id, "session_reminders")
2026-08-16 19:37:15 +02:00
message = (
"# <:VV:1339237574593609780> - **SESSION VICTORIA’S VICE**\n"
"\n"
"```📅 - HORAIRE DE LA SESSION```\n"
f"> - Nous vous donnons rendez-vous le **{date}** pour une **session officielle** sur Victoria’s Vice. 🗓️\n"
"---\n"
"```🤔 - COMMENT REJOINDRE LA SESSION ?```\n"
"> - Pour lancer la Map, veuillez entrer le code ci-dessous sur la barre de recherche de Fortnite, par la suite lancer la Map en **public** afin de pouvoir nous rejoindre.\n"
"> - **`CODE DE LA MAP`** <:arrow:1297491509201080362> [0986-1836-1625]\n"
"> - **`LIEN DIRECT DE LA MAP`** <:arrow:1297491509201080362> <https://play.fn.gg/island/0986-1836-1625>\n"
"---\n"
"```🖐 - SEREZ-VOUS PRÉSENT(E) EN SESSION ?```\n"
"> - Je serai présent : <:check:1297296859206778911> **(0)**\n"
"> - Je serai absent : <:uncheck:1297296882778902598> **(0)**\n"
"> - Je serai en retard : ⏰ **(0)**\n"
"---"
f"> - **`PING`** : <@&{ping_role_id}>"
2026-08-16 19:37:15 +02:00
)
await interaction.response.send_message(
content=message,
files=[await image.to_file()]
)
msg = await interaction.original_response()
presence_data[msg.id] = {
"present": set(),
"absent": set(),
"retard": set(),
"date": session_date,
"sent_dm": False,
"reminder1": reminder1_date,
"reminder2": reminder2_date,
"reminder1_sent": False,
"reminder2_sent": False,
"channel_id": msg.channel.id,
"guild_id": msg.guild.id
}
await msg.edit(view=PresenceView(msg.id))
@app_commands.command(
name="liste_presence",
description="Liste les présences pour une session RP."
)
@app_commands.describe(
message_id="ID du message d'annonce"
)
async def liste_presence(self, interaction: discord.Interaction, message_id: str):
try:
mid = int(message_id)
except ValueError:
await interaction.response.send_message("ID de message invalide.", ephemeral=True)
return
if mid not in presence_data:
await interaction.response.send_message("Aucune donnée de présence pour ce message.", ephemeral=True)
return
data = presence_data[mid]
def mentions(ids):
return ', '.join(f"<@{uid}>" for uid in ids) if ids else "Aucun"
await interaction.response.send_message(
f"**Présents ({len(data['present'])})** : {mentions(data['present'])}\n"
f"**Absents ({len(data['absent'])})** : {mentions(data['absent'])}\n"
f"**En retard ({len(data['retard'])})** : {mentions(data['retard'])}",
ephemeral=True
)
@tasks.loop(seconds=30)
async def check_sessions(self):
now = datetime.now(timezone.utc)
for msg_id, data in list(presence_data.items()):
# Premier rappel
if data.get("reminder1") and not data.get("reminder1_sent", False) and now >= data["reminder1"]:
await self.send_reminder(data, msg_id, "Premier rappel !")
data["reminder1_sent"] = True
# Deuxième rappel
if data.get("reminder2") and not data.get("reminder2_sent", False) and now >= data["reminder2"]:
await self.send_reminder(data, msg_id, "Deuxième rappel !")
data["reminder2_sent"] = True
# Envoi du MP à l'heure de la session
if data["date"] and not data.get("sent_dm", False) and now >= data["date"]:
for user_id in data["present"]:
try:
user = await self.bot.fetch_user(user_id)
channel = self.bot.get_channel(data["channel_id"])
if channel:
msg = await channel.fetch_message(msg_id)
await user.send(f"La session RP commence ! Voici le lien de l'annonce : {msg.jump_url}")
except Exception as e:
print(f"Erreur lors de l'envoi du DM à {user_id} : {e}")
data["sent_dm"] = True
async def send_reminder(self, data, msg_id, label):
channel = self.bot.get_channel(data["channel_id"])
if channel:
msg = await channel.fetch_message(msg_id)
reminder_role_id = get_role_id(data.get("guild_id", 0), "session_reminders")
2026-08-16 19:37:15 +02:00
await channel.send(
f"<@&{reminder_role_id}> ⏰ **{label}**\nLa session RP approche !\nAnnonce : {msg.jump_url}"
2026-08-16 19:37:15 +02:00
)
@check_sessions.before_loop
async def before_check_sessions(self):
await self.bot.wait_until_ready()
async def setup(bot):
await bot.add_cog(AnnonceSession(bot))