Initial commit: bot Discord Vicy V1.8
This commit is contained in:
commit
56958c5832
70 changed files with 8469 additions and 0 deletions
220
commandes/annonces_sessions.py
Normal file
220
commandes/annonces_sessions.py
Normal file
|
|
@ -0,0 +1,220 @@
|
|||
import discord
|
||||
from discord import app_commands
|
||||
from discord.ext import commands, tasks
|
||||
import dateparser
|
||||
from datetime import datetime, timezone
|
||||
|
||||
ROLE_PING_ID = 1278319901651632138 # ID du rôle citoyen # Rôle pour l'annonce principale
|
||||
REMINDER_ROLE_ID = 1303750986900439151 # ID du rôle rappels sessions # Rôle pour les rappels (à adapter !)
|
||||
|
||||
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)
|
||||
|
||||
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`** : <@&{ROLE_PING_ID}>"
|
||||
)
|
||||
|
||||
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)
|
||||
await channel.send(
|
||||
f"<@&{REMINDER_ROLE_ID}> ⏰ **{label}**\nLa session RP approche !\nAnnonce : {msg.jump_url}"
|
||||
)
|
||||
|
||||
@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))
|
||||
Loading…
Add table
Add a link
Reference in a new issue