Author SHA1 Message Date
Mow910 942b23c956 Merge pull request #6 from Mow910/discord-transfert-msg
Ajout de la sélection de tags pour les posts dans les forums lors du …
2026-02-14 20:33:44 +01:00
Mow910 3450cd031c Merge pull request #5 from Mow910/discord-transfert-msg
Ajout de la commande contextuelle "Déplacer le message" pour transfér…
2026-02-14 19:37:32 +01:00
Mow910 252e169af5 Merge pull request #4 from Mow910/discord-transfert-msg
Discord transfert msg
2026-02-14 18:34:03 +01:00
3 changed files with 71 additions and 300 deletions
+1 -5
View File
@@ -27,7 +27,7 @@ from discordbot.moderation import (
) )
from discordbot.welcome import sendWelcomeMessage, sendLeaveMessage, updateInviteCache from discordbot.welcome import sendWelcomeMessage, sendLeaveMessage, updateInviteCache
from discordbot.youtube import checkYouTubeVideos from discordbot.youtube import checkYouTubeVideos
from discordbot.auto_rooms import on_voice_state_update_auto_rooms, on_raw_reaction_add_auto_rooms, on_message_auto_rooms from discordbot.auto_rooms import on_voice_state_update_auto_rooms, on_raw_reaction_add_auto_rooms
from protondb import searhProtonDb from protondb import searhProtonDb
class DiscordBot(discord.Client): class DiscordBot(discord.Client):
@@ -151,10 +151,6 @@ bot = DiscordBot(intents=intents)
async def on_message(message: Message): async def on_message(message: Message):
if message.author == bot.user: if message.author == bot.user:
return return
# Gestion des messages dans les auto rooms (avant le check des commandes !)
await on_message_auto_rooms(bot, message)
if not message.content.startswith('!'): if not message.content.startswith('!'):
return return
command_name = message.content.split()[0] command_name = message.content.split()[0]
+69 -294
View File
@@ -16,14 +16,13 @@ _control_message_ids: dict[int, tuple[int, int]] = {}
REACTIONS = [ REACTIONS = [
("🔓", "open", "Ouvert"), ("🔓", "open", "Ouvert"),
("🔒", "closed", "Fermé"), ("🔒", "closed", "Fermé"),
("🔐", "private", "Privé"), ("🛡️", "private", "Privé"),
("", "whitelist", "Liste blanche"), ("", "whitelist", "Liste blanche"),
("🚫", "blacklist", "Liste noire"), ("🚫", "blacklist", "Liste noire"),
("🧹", "purge", "Purge"), ("🧹", "purge", "Purge"),
("👑", "transfer", "Propriété"), ("👑", "transfer", "Propriété"),
("🎤", "speak", "Micro"), ("🎤", "speak", "Micro"),
("📹", "stream", "Vidéo"), ("📹", "stream", "Vidéo"),
("📊", "soundboards", "Soundboards"),
("📝", "status", "Statut"), ("📝", "status", "Statut"),
] ]
@@ -35,85 +34,40 @@ def _status_display(access_mode: str) -> str:
if access_mode == "closed": if access_mode == "closed":
return "🔒 Fermé" return "🔒 Fermé"
if access_mode == "private": if access_mode == "private":
return "🔐 Privé" return "🔒 Privé"
return "🔓 Ouvert" return "🔓 Ouvert"
def _status_emoji(access_mode: str) -> str: def _status_emoji(access_mode: str) -> str:
"""Emoji cadenas seul pour le nom du channel.""" """Emoji cadenas seul pour le nom du channel."""
if access_mode == "private":
return "🔐"
return "🔓" if access_mode == "open" else "🔒" return "🔓" if access_mode == "open" else "🔒"
def _build_control_embed(owner: Member, voice_channel: discord.VoiceChannel, access_mode: str, room: dict = None) -> discord.Embed: def _build_control_embed(owner: Member, voice_channel: discord.VoiceChannel, access_mode: str) -> discord.Embed:
"""Construit l'embed de config avec infos du salon.""" """Construit lembed de config avec infos du salon."""
embed = discord.Embed( embed = discord.Embed(
title="⚙️ Configuration du salon", title="Configuration du salon",
description=( description=(
"Voici l'espace de configuration de votre salon vocal temporaire. " "Voici lespace de configuration de votre salon vocal. "
"Les différentes options disponibles vous permettent de personnaliser les permissions de votre salon selon vos préférences." "Utilisez les réactions ci-dessous — seul le propriétaire peut réagir."
), ),
color=discord.Color.orange() color=discord.Color.blurple()
) )
members_count = len(voice_channel.members)
# Récupération des infos user_limit = voice_channel.user_limit or 0
whitelist = room.get("whitelist", set()) if room else set() limit_text = f"{user_limit} max" if user_limit else "Illimitée"
blacklist = room.get("blacklist", set()) if room else set() members_text = f"{members_count} / {user_limit}" if user_limit else str(members_count)
whitelist_text = f"{len(whitelist)} membre(s)" if whitelist else "Aucun" bitrate_kbps = (voice_channel.bitrate or 0) // 1000
blacklist_text = f"{len(blacklist)} membre(s)" if blacklist else "Aucun"
embed.add_field(name="Propriétaire", value=owner.mention, inline=True)
# Section Propriétaire embed.add_field(name="Statut du salon", value=_status_display(access_mode), inline=True)
embed.add_field( embed.add_field(name="Nom du salon", value=voice_channel.name, inline=True)
name=f"👤 Propriétaire du salon : {owner.display_name}", embed.add_field(name="Membres", value=members_text, inline=True)
value="", embed.add_field(name="Limite", value=limit_text, inline=True)
inline=False embed.add_field(name="Bitrate", value=f"{bitrate_kbps} kbps", inline=True)
) embed.add_field(name="Accès", value="🔓 Ouvert · 🔒 Fermé · 🛡️ Privé", inline=False)
embed.add_field(name="Listes", value="✅ Liste blanche · 🚫 Liste noire", inline=False)
# Section Modes d'accès embed.add_field(name="Actions", value="🧹 Purge · 👑 Propriété · 🎤 Micro · 📹 Vidéo · 📝 Statut", inline=False)
mode_open = "🔓 **Ouvert**\nLe salon sera ouvert à tous les membres, sauf ceux figurant sur la liste noire."
mode_closed = "🔒 **Fermé**\nLe salon sera visible de tous, mais seulement accessible à la liste blanche."
mode_private = "🔐 **Privé**\nLe salon ne sera visible et accessible qu'aux membres de la liste blanche."
embed.add_field(name=mode_open, value="", inline=True)
embed.add_field(name=mode_closed, value="", inline=True)
embed.add_field(name=mode_private, value="", inline=True)
# Section Listes
embed.add_field(
name="📝 **Liste blanche**",
value=f"Les membres présents dans cette liste pourront toujours rejoindre le salon.\n\n{whitelist_text}",
inline=True
)
embed.add_field(
name="🚫 **Liste noire**",
value=f"Les membres présents dans cette liste ne pourront jamais rejoindre le salon.\n\n{blacklist_text}",
inline=True
)
embed.add_field(name="\u200b", value="", inline=True) # Spacer
# Section Purge
embed.add_field(
name="🧹 **Purge**",
value="Déconnecter tous les membres du salon vocal à l'exception de ceux présents dans la liste blanche.",
inline=False
)
# Section Transfert
embed.add_field(
name="👑 **Transférer**",
value="Transférer la gestion du salon au membre de votre choix.",
inline=False
)
# Note importante
embed.add_field(
name="💡",
value="Les membres de la liste blanche ne sont pas impactés par les permissions refusées aux membres.",
inline=False
)
embed.set_footer(text="Réagissez avec les émojis ci-dessous pour configurer votre salon")
return embed return embed
@@ -160,26 +114,11 @@ def _find_room_by_message(message_id: int) -> Optional[tuple[int, int, dict]]:
async def _apply_access_mode(channel: discord.VoiceChannel, mode: str, whitelist: set, blacklist: set): async def _apply_access_mode(channel: discord.VoiceChannel, mode: str, whitelist: set, blacklist: set):
guild = channel.guild guild = channel.guild
everyone = guild.default_role everyone = guild.default_role
overwrites = dict(channel.overwrites) # Récupérer les overwrites existants overwrites = {}
# Préserver les permissions existantes pour everyone (stream, speak, soundboards, etc.)
existing_everyone_ow = overwrites.get(everyone, discord.PermissionOverwrite())
everyone_ow = discord.PermissionOverwrite() everyone_ow = discord.PermissionOverwrite()
# Copier les permissions importantes qui ne doivent pas être écrasées
everyone_ow.stream = existing_everyone_ow.stream
everyone_ow.speak = existing_everyone_ow.speak
everyone_ow.use_soundboard = existing_everyone_ow.use_soundboard
if mode == "open": if mode == "open":
everyone_ow.connect = True everyone_ow.connect = True
everyone_ow.view_channel = True everyone_ow.view_channel = True
# Retirer les overwrites des membres qui ne sont plus dans la blacklist
for target in list(overwrites.keys()):
if target != everyone and isinstance(target, discord.Member):
if target.id not in blacklist:
overwrites.pop(target, None)
# Ajouter les overwrites pour la blacklist
for uid in blacklist: for uid in blacklist:
m = guild.get_member(uid) m = guild.get_member(uid)
if m: if m:
@@ -187,12 +126,6 @@ async def _apply_access_mode(channel: discord.VoiceChannel, mode: str, whitelist
elif mode == "closed": elif mode == "closed":
everyone_ow.connect = False everyone_ow.connect = False
everyone_ow.view_channel = True everyone_ow.view_channel = True
# Retirer les overwrites des membres qui ne sont plus dans la whitelist
for target in list(overwrites.keys()):
if target != everyone and isinstance(target, discord.Member):
if target.id not in whitelist:
overwrites.pop(target, None)
# Ajouter les overwrites pour la whitelist
for uid in whitelist: for uid in whitelist:
m = guild.get_member(uid) m = guild.get_member(uid)
if m: if m:
@@ -200,17 +133,10 @@ async def _apply_access_mode(channel: discord.VoiceChannel, mode: str, whitelist
elif mode == "private": elif mode == "private":
everyone_ow.connect = False everyone_ow.connect = False
everyone_ow.view_channel = False everyone_ow.view_channel = False
# Retirer les overwrites des membres qui ne sont plus dans la whitelist
for target in list(overwrites.keys()):
if target != everyone and isinstance(target, discord.Member):
if target.id not in whitelist:
overwrites.pop(target, None)
# Ajouter les overwrites pour la whitelist
for uid in whitelist: for uid in whitelist:
m = guild.get_member(uid) m = guild.get_member(uid)
if m: if m:
overwrites[m] = discord.PermissionOverwrite(connect=True, view_channel=True) overwrites[m] = discord.PermissionOverwrite(connect=True, view_channel=True)
overwrites[everyone] = everyone_ow overwrites[everyone] = everyone_ow
await channel.edit(overwrites=overwrites) await channel.edit(overwrites=overwrites)
@@ -219,7 +145,7 @@ async def _handle_reaction_action(bot: discord.Client, guild_id: int, owner_id:
"""channel = salon vocal (partie texte / onglet Discussion).""" """channel = salon vocal (partie texte / onglet Discussion)."""
room = _get_room(guild_id, owner_id) room = _get_room(guild_id, owner_id)
if not room: if not room:
await channel.send("Ce salon n'existe plus.") await channel.send("Ce salon nexiste plus.")
return return
voice_channel = bot.get_channel(room["voice_channel_id"]) voice_channel = bot.get_channel(room["voice_channel_id"])
if not voice_channel or not isinstance(voice_channel, discord.VoiceChannel): if not voice_channel or not isinstance(voice_channel, discord.VoiceChannel):
@@ -229,27 +155,36 @@ async def _handle_reaction_action(bot: discord.Client, guild_id: int, owner_id:
if action in ("open", "closed", "private"): if action in ("open", "closed", "private"):
room["access_mode"] = action room["access_mode"] = action
await _apply_access_mode(voice_channel, action, room.get("whitelist", set()), room.get("blacklist", set())) await _apply_access_mode(voice_channel, action, room.get("whitelist", set()), room.get("blacklist", set()))
await channel.send(f"✅ Accès du salon défini sur **{_status_display(action)}**.") # Mettre à jour le cadenas dans le nom du channel
# Mettre à jour l'embed try:
await _update_control_panel(bot, guild_id, owner_id, channel) base_name = voice_channel.name.rstrip(" 🔓🔒")
new_name = f"{base_name} {_status_emoji(action)}"
await voice_channel.edit(name=new_name)
except discord.HTTPException:
pass
await channel.send(f"Accès du salon défini sur **{action}**.")
# Mettre à jour uniquement le statut (cadenas) dans le message de config
control_message_id = room.get("control_message_id")
if control_message_id:
try:
msg = await channel.fetch_message(control_message_id)
if msg.embeds:
embed = msg.embeds[0].copy()
for i, f in enumerate(embed.fields):
if f.name == "Statut du salon":
embed.set_field_at(i, name="Statut du salon", value=_status_display(action), inline=f.inline)
break
else:
embed.add_field(name="Statut du salon", value=_status_display(action), inline=False)
await msg.edit(embed=embed)
except discord.HTTPException:
pass
elif action == "whitelist": elif action == "whitelist":
whitelist = room.get("whitelist", set()) await channel.send("Liste blanche : mentionnez un membre pour lajouter/retirer.")
whitelist_text = ", ".join([f"<@{uid}>" for uid in whitelist]) if whitelist else "Aucun membre"
await channel.send(
f"**📝 Liste blanche actuelle :** {whitelist_text}\n\n"
f"Mentionnez un membre pour l'ajouter ou le retirer de la liste blanche."
)
room["awaiting_whitelist"] = True
elif action == "blacklist": elif action == "blacklist":
blacklist = room.get("blacklist", set()) await channel.send("Liste noire : mentionnez un membre pour lajouter/retirer.")
blacklist_text = ", ".join([f"<@{uid}>" for uid in blacklist]) if blacklist else "Aucun membre"
await channel.send(
f"**🚫 Liste noire actuelle :** {blacklist_text}\n\n"
f"Mentionnez un membre pour l'ajouter ou le retirer de la liste noire."
)
room["awaiting_blacklist"] = True
elif action == "purge": elif action == "purge":
whitelist = room.get("whitelist", set()) whitelist = room.get("whitelist", set())
@@ -262,80 +197,30 @@ async def _handle_reaction_action(bot: discord.Client, guild_id: int, owner_id:
kicked += 1 kicked += 1
except discord.HTTPException: except discord.HTTPException:
pass pass
await channel.send(f"🧹 Purge effectuée : {kicked} membre(s) déconnecté(s).") await channel.send(f"Purge effectuée : {kicked} membre(s) déconnecté(s).")
elif action == "transfer": elif action == "transfer":
await channel.send( await channel.send("Transférer le salon : mentionnez le membre à qui donner la propriété.")
f"**👑 Transfert de propriété**\n\n"
f"Mentionnez le membre à qui vous souhaitez transférer la gestion du salon."
)
room["awaiting_transfer"] = True
elif action in ("speak", "stream", "soundboards"): elif action in ("speak", "stream"):
everyone = voice_channel.guild.default_role everyone = voice_channel.guild.default_role
overwrites = dict(voice_channel.overwrites) overwrites = dict(voice_channel.overwrites)
ow = overwrites.get(everyone) or discord.PermissionOverwrite() ow = overwrites.get(everyone) or discord.PermissionOverwrite()
# BUG FIX : Par défaut, Discord autorise stream, speak et soundboards
# Si la permission n'est pas explicitement définie (None), on considère qu'elle est True
current = getattr(ow, action) current = getattr(ow, action)
if current is None: setattr(ow, action, not current if current is not None else False)
# Permission non définie = autorisée par défaut dans Discord
# On veut la désactiver lors du premier clic
setattr(ow, action, False)
new_value = False
else:
# Permission définie, on l'inverse
setattr(ow, action, not current)
new_value = not current
overwrites[everyone] = ow overwrites[everyone] = ow
await voice_channel.edit(overwrites=overwrites) await voice_channel.edit(overwrites=overwrites)
label = "Micro" if action == "speak" else "Vidéo"
labels = {"speak": "Micro", "stream": "Vidéo/Partage d'écran", "soundboards": "Soundboards"} await channel.send(f"{label} : {'autorisé' if getattr(ow, action) else 'désactivé'} pour tous.")
label = labels.get(action, action.capitalize())
await channel.send(f"{label} : {'autorisé' if new_value else 'désactivé'} pour tous.")
elif action == "status": elif action == "status":
current_status = voice_channel.status or "Aucun statut défini" status_text = _status_display(room.get("access_mode", "open"))
await channel.send( await channel.send(f"Statut du salon : {status_text}\nRépondez avec le nouveau nom du salon pour le modifier.")
f"**Statut actuel du salon :** {current_status}\n\n"
f"Pour modifier le statut du salon (le texte affiché en haut du salon vocal), "
f"répondez avec le nouveau statut (max 500 caractères).\n"
f"💡 Pour supprimer le statut, répondez avec `clear` ou `effacer`."
)
room["awaiting_status"] = True
async def _update_control_panel(bot: discord.Client, guild_id: int, owner_id: int, channel): async def send_control_panel(bot: discord.Client, guild_id: int, owner: Member, voice_channel: discord.VoiceChannel) -> Optional[int]:
"""Met à jour le panneau de contrôle avec les nouvelles informations.""" """Envoie le message de config avec réactions dans la partie texte du salon vocal (onglet Discussion). Seul le proprio peut réagir. Retourne lid du message."""
room = _get_room(guild_id, owner_id) embed = _build_control_embed(owner, voice_channel, "open")
if not room:
return
control_message_id = room.get("control_message_id")
if not control_message_id:
return
voice_channel = bot.get_channel(room["voice_channel_id"])
if not voice_channel or not isinstance(voice_channel, discord.VoiceChannel):
return
owner = voice_channel.guild.get_member(owner_id)
if not owner:
return
try:
msg = await channel.fetch_message(control_message_id)
embed = _build_control_embed(owner, voice_channel, room.get("access_mode", "open"), room)
await msg.edit(embed=embed)
except discord.HTTPException:
pass
async def send_control_panel(bot: discord.Client, guild_id: int, owner: Member, voice_channel: discord.VoiceChannel, room: dict) -> Optional[int]:
"""Envoie le message de config avec réactions dans la partie texte du salon vocal (onglet Discussion). Seul le proprio peut réagir. Retourne l'id du message."""
embed = _build_control_embed(owner, voice_channel, "open", room)
try: try:
# Message dans la partie texte du vocal (onglet Discussion à droite) # Message dans la partie texte du vocal (onglet Discussion à droite)
@@ -344,7 +229,7 @@ async def send_control_panel(bot: discord.Client, guild_id: int, owner: Member,
await msg.add_reaction(emoji) await msg.add_reaction(emoji)
return msg.id return msg.id
except discord.HTTPException as e: except discord.HTTPException as e:
logging.error(f"Impossible d'envoyer le panneau Auto Room dans le vocal : {e}") logging.error(f"Impossible denvoyer le panneau Auto Room dans le vocal : {e}")
return None return None
@@ -360,8 +245,8 @@ async def on_voice_state_update_auto_rooms(bot: discord.Client, member: Member,
if after.channel and after.channel.id == trigger_channel_id: if after.channel and after.channel.id == trigger_channel_id:
category = after.channel.category category = after.channel.category
# Nom du salon (simple, sans emoji pour éviter le rate limiting) # Nom du salon avec statut (cadenas) à la création
channel_name = f"Salon de {member.display_name}" channel_name = f"Salon de {member.display_name} {_status_emoji('open')}"
try: try:
new_channel = await guild.create_voice_channel( new_channel = await guild.create_voice_channel(
name=channel_name, name=channel_name,
@@ -369,22 +254,16 @@ async def on_voice_state_update_auto_rooms(bot: discord.Client, member: Member,
reason="Auto room" reason="Auto room"
) )
await member.move_to(new_channel) await member.move_to(new_channel)
control_message_id = await send_control_panel(bot, guild.id, member, new_channel)
# Créer la room data d'abord _set_room(guild.id, member.id, {
room_data = {
"guild_id": guild.id, "guild_id": guild.id,
"voice_channel_id": new_channel.id, "voice_channel_id": new_channel.id,
"control_message_id": None, # Sera mis à jour après "control_message_id": control_message_id,
"owner_id": member.id, "owner_id": member.id,
"whitelist": set(), "whitelist": set(),
"blacklist": set(), "blacklist": set(),
"access_mode": "open", "access_mode": "open",
} })
control_message_id = await send_control_panel(bot, guild.id, member, new_channel, room_data)
room_data["control_message_id"] = control_message_id
_set_room(guild.id, member.id, room_data)
logging.info(f"Auto room créé : {new_channel.name} pour {member.display_name}") logging.info(f"Auto room créé : {new_channel.name} pour {member.display_name}")
except discord.HTTPException as e: except discord.HTTPException as e:
logging.error(f"Erreur création auto room : {e}") logging.error(f"Erreur création auto room : {e}")
@@ -408,110 +287,6 @@ async def on_voice_state_update_auto_rooms(bot: discord.Client, member: Member,
pass pass
async def on_message_auto_rooms(bot: discord.Client, message: discord.Message):
"""Gère les messages dans les salons vocaux pour les actions (statut, liste blanche/noire, etc.)."""
if message.author.bot:
return
if not ConfigurationHelper().getValue("auto_rooms_enable"):
return
# Vérifier si c'est dans un salon vocal (partie texte)
if not isinstance(message.channel, discord.VoiceChannel):
return
# Trouver si c'est une auto room
result = _find_room_by_channel(message.guild.id, message.channel.id)
if not result:
return
owner_id, room = result
# Seul le propriétaire peut interagir
if message.author.id != owner_id:
return
voice_channel = message.channel
# Gestion du statut de salon
if room.get("awaiting_status"):
room["awaiting_status"] = False
new_status = message.content.strip()
try:
if new_status.lower() in ("clear", "effacer", "supprimer", "delete"):
await voice_channel.edit(status=None)
await message.channel.send("✅ Le statut du salon a été supprimé.")
elif len(new_status) > 500:
await message.channel.send("❌ Le statut ne peut pas dépasser 500 caractères.")
room["awaiting_status"] = True # Réessayer
else:
await voice_channel.edit(status=new_status)
await message.channel.send(f"✅ Le statut du salon a été mis à jour : **{new_status}**")
except discord.HTTPException as e:
await message.channel.send(f"❌ Erreur lors de la modification du statut : {e}")
return
# Gestion de la liste blanche (si en attente)
if room.get("awaiting_whitelist"):
room["awaiting_whitelist"] = False
if message.mentions:
target = message.mentions[0]
whitelist = room.get("whitelist", set())
if target.id in whitelist:
whitelist.remove(target.id)
await message.channel.send(f"{target.mention} a été retiré de la liste blanche.")
else:
whitelist.add(target.id)
await message.channel.send(f"{target.mention} a été ajouté à la liste blanche.")
room["whitelist"] = whitelist
await _apply_access_mode(voice_channel, room.get("access_mode", "open"), whitelist, room.get("blacklist", set()))
await _update_control_panel(bot, message.guild.id, owner_id, message.channel)
return
# Gestion de la liste noire (si en attente)
if room.get("awaiting_blacklist"):
room["awaiting_blacklist"] = False
if message.mentions:
target = message.mentions[0]
blacklist = room.get("blacklist", set())
if target.id in blacklist:
blacklist.remove(target.id)
await message.channel.send(f"{target.mention} a été retiré de la liste noire.")
else:
blacklist.add(target.id)
await message.channel.send(f"{target.mention} a été ajouté à la liste noire.")
room["blacklist"] = blacklist
await _apply_access_mode(voice_channel, room.get("access_mode", "open"), room.get("whitelist", set()), blacklist)
await _update_control_panel(bot, message.guild.id, owner_id, message.channel)
return
# Gestion du transfert de propriété (si en attente)
if room.get("awaiting_transfer"):
room["awaiting_transfer"] = False
if message.mentions:
new_owner = message.mentions[0]
if new_owner.id == owner_id:
await message.channel.send("❌ Vous êtes déjà le propriétaire du salon.")
return
# Transférer la propriété
old_owner_id = owner_id
_del_room(message.guild.id, old_owner_id)
room["owner_id"] = new_owner.id
_set_room(message.guild.id, new_owner.id, room)
# Renommer le salon (optionnel, peut être commenté pour éviter rate limit)
try:
new_name = f"Salon de {new_owner.display_name}"
await voice_channel.edit(name=new_name)
except discord.HTTPException as e:
logging.warning(f"Impossible de renommer le salon lors du transfert : {e}")
await message.channel.send(f"✅ La propriété du salon a été transférée à {new_owner.mention}.")
await _update_control_panel(bot, message.guild.id, new_owner.id, message.channel)
return
async def on_raw_reaction_add_auto_rooms(bot: discord.Client, payload: discord.RawReactionActionEvent): async def on_raw_reaction_add_auto_rooms(bot: discord.Client, payload: discord.RawReactionActionEvent):
"""Seul le propriétaire peut réagir ; on retire la réaction des autres.""" """Seul le propriétaire peut réagir ; on retire la réaction des autres."""
if payload.user_id == bot.user.id: if payload.user_id == bot.user.id:
+1 -1
View File
@@ -218,7 +218,7 @@
{{ 'Enregistrer' if notification else 'Ajouter la notification' }} {{ 'Enregistrer' if notification else 'Ajouter la notification' }}
</button> </button>
{% if notification %} {% if notification %}
<a href="{{ url_for('openYouTube') }}" <a href="{{ url_for('youtube') }}"
class="px-6 py-2.5 bg-gray-200 dark:bg-gray-600 hover:bg-gray-300 dark:hover:bg-gray-500 text-gray-700 dark:text-gray-200 font-medium rounded-lg transition-colors"> class="px-6 py-2.5 bg-gray-200 dark:bg-gray-600 hover:bg-gray-300 dark:hover:bg-gray-500 text-gray-700 dark:text-gray-200 font-medium rounded-lg transition-colors">
Annuler Annuler
</a> </a>