Harden auto room lifecycle and persistence
This commit is contained in:
+13
-1
@@ -210,6 +210,19 @@ class YouTubeVideoHistory(db.Model):
|
|||||||
detected_at = db.Column(db.DateTime, default=datetime.utcnow)
|
detected_at = db.Column(db.DateTime, default=datetime.utcnow)
|
||||||
|
|
||||||
|
|
||||||
|
class AutoRoom(db.Model):
|
||||||
|
"""État persistant des salons vocaux temporaires."""
|
||||||
|
__tablename__ = 'auto_room'
|
||||||
|
guild_id = db.Column(db.String(32), primary_key=True)
|
||||||
|
voice_channel_id = db.Column(db.String(32), primary_key=True)
|
||||||
|
owner_id = db.Column(db.String(32), nullable=False)
|
||||||
|
control_message_id = db.Column(db.String(32))
|
||||||
|
access_mode = db.Column(db.String(16), nullable=False, default='open')
|
||||||
|
whitelist = db.Column(db.Text, nullable=False, default='[]')
|
||||||
|
blacklist = db.Column(db.Text, nullable=False, default='[]')
|
||||||
|
managed_member_ids = db.Column(db.Text, nullable=False, default='[]')
|
||||||
|
|
||||||
|
|
||||||
class FreeLootEntry(db.Model):
|
class FreeLootEntry(db.Model):
|
||||||
__tablename__ = 'freeloot_entry'
|
__tablename__ = 'freeloot_entry'
|
||||||
entry_id = db.Column(db.String(256), primary_key=True)
|
entry_id = db.Column(db.String(256), primary_key=True)
|
||||||
@@ -259,4 +272,3 @@ class ModShoutboxMessage(db.Model):
|
|||||||
author = db.Column(db.String(64), nullable=False)
|
author = db.Column(db.String(64), nullable=False)
|
||||||
message = db.Column(db.String(500), nullable=False)
|
message = db.Column(db.String(500), nullable=False)
|
||||||
created_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
|
created_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
|
||||||
|
|
||||||
|
|||||||
@@ -193,6 +193,18 @@ CREATE TABLE IF NOT EXISTS `youtube_video_history` (
|
|||||||
FOREIGN KEY (`notification_id`) REFERENCES `youtube_notification`(`id`) ON DELETE CASCADE
|
FOREIGN KEY (`notification_id`) REFERENCES `youtube_notification`(`id`) ON DELETE CASCADE
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS `auto_room` (
|
||||||
|
`guild_id` VARCHAR(32) NOT NULL,
|
||||||
|
`voice_channel_id` VARCHAR(32) NOT NULL UNIQUE,
|
||||||
|
`owner_id` VARCHAR(32) NOT NULL,
|
||||||
|
`control_message_id` VARCHAR(32),
|
||||||
|
`access_mode` VARCHAR(16) NOT NULL DEFAULT 'open',
|
||||||
|
`whitelist` TEXT NOT NULL DEFAULT '[]',
|
||||||
|
`blacklist` TEXT NOT NULL DEFAULT '[]',
|
||||||
|
`managed_member_ids` TEXT NOT NULL DEFAULT '[]',
|
||||||
|
PRIMARY KEY (`guild_id`, `voice_channel_id`)
|
||||||
|
);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `freeloot_entry` (
|
CREATE TABLE IF NOT EXISTS `freeloot_entry` (
|
||||||
entry_id VARCHAR(256) PRIMARY KEY
|
entry_id VARCHAR(256) PRIMARY KEY
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ from discordbot.welcome import sendWelcomeMessage, sendLeaveMessage, updateInvit
|
|||||||
from discordbot.rules_ack import assign_rules_arrival_on_join, register_persistent_rules_view
|
from discordbot.rules_ack import assign_rules_arrival_on_join, register_persistent_rules_view
|
||||||
from discordbot.patreon import checkPatreonPosts
|
from discordbot.patreon import checkPatreonPosts
|
||||||
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, cleanup_orphaned_auto_rooms
|
from discordbot.auto_rooms import on_voice_state_update_auto_rooms, on_raw_reaction_add_auto_rooms, on_message_auto_rooms, cleanup_orphaned_auto_rooms, restore_auto_rooms
|
||||||
from discordbot.protondb_discord import protondb_slash_command, pdb_slash_command
|
from discordbot.protondb_discord import protondb_slash_command, pdb_slash_command
|
||||||
|
|
||||||
class DiscordBot(discord.Client):
|
class DiscordBot(discord.Client):
|
||||||
@@ -97,6 +97,7 @@ class DiscordBot(discord.Client):
|
|||||||
for guild in self.guilds:
|
for guild in self.guilds:
|
||||||
await updateInviteCache(guild)
|
await updateInviteCache(guild)
|
||||||
|
|
||||||
|
await restore_auto_rooms(self)
|
||||||
await cleanup_orphaned_auto_rooms(self)
|
await cleanup_orphaned_auto_rooms(self)
|
||||||
|
|
||||||
# on_ready est rappelé après une reconnexion : ne pas démarrer plusieurs
|
# on_ready est rappelé après une reconnexion : ne pas démarrer plusieurs
|
||||||
|
|||||||
+119
-29
@@ -1,11 +1,15 @@
|
|||||||
# discordbot/auto_rooms.py — Auto rooms : message et réactions dans la partie texte du salon vocal (onglet Discussion)
|
# discordbot/auto_rooms.py — Auto rooms : message et réactions dans la partie texte du salon vocal (onglet Discussion)
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
|
import json
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
import discord
|
import discord
|
||||||
from discord import Member, VoiceState
|
from discord import Member, VoiceState
|
||||||
|
from database import db
|
||||||
from database.helpers import ConfigurationHelper
|
from database.helpers import ConfigurationHelper
|
||||||
|
from database.models import AutoRoom
|
||||||
|
from webapp import webapp
|
||||||
|
|
||||||
# (guild_id, owner_id) -> room_data (voice_channel_id, control_message_id, whitelist, blacklist, access_mode)
|
# (guild_id, owner_id) -> room_data (voice_channel_id, control_message_id, whitelist, blacklist, access_mode)
|
||||||
_rooms: dict[tuple[int, int], dict] = {}
|
_rooms: dict[tuple[int, int], dict] = {}
|
||||||
@@ -131,12 +135,41 @@ def _set_room(guild_id: int, owner_id: int, data: dict):
|
|||||||
mid = data.get("control_message_id")
|
mid = data.get("control_message_id")
|
||||||
if mid:
|
if mid:
|
||||||
_control_message_ids[mid] = (guild_id, owner_id)
|
_control_message_ids[mid] = (guild_id, owner_id)
|
||||||
|
_persist_room(guild_id, owner_id, data)
|
||||||
|
|
||||||
|
|
||||||
def _del_room(guild_id: int, owner_id: int):
|
def _del_room(guild_id: int, owner_id: int):
|
||||||
data = _rooms.pop(_room_key(guild_id, owner_id), None)
|
data = _rooms.pop(_room_key(guild_id, owner_id), None)
|
||||||
if data and data.get("control_message_id"):
|
if data and data.get("control_message_id"):
|
||||||
_control_message_ids.pop(data["control_message_id"], None)
|
_control_message_ids.pop(data["control_message_id"], None)
|
||||||
|
if data:
|
||||||
|
with webapp.app_context():
|
||||||
|
AutoRoom.query.filter_by(guild_id=str(guild_id), voice_channel_id=str(data["voice_channel_id"])).delete()
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
|
||||||
|
def _persist_room(guild_id: int, owner_id: int, data: dict):
|
||||||
|
"""Sauvegarde l'état nécessaire à la reprise après redémarrage."""
|
||||||
|
with webapp.app_context():
|
||||||
|
record = AutoRoom.query.filter_by(
|
||||||
|
guild_id=str(guild_id), voice_channel_id=str(data["voice_channel_id"])
|
||||||
|
).first()
|
||||||
|
if not record:
|
||||||
|
record = AutoRoom(guild_id=str(guild_id), voice_channel_id=str(data["voice_channel_id"]))
|
||||||
|
db.session.add(record)
|
||||||
|
record.owner_id = str(owner_id)
|
||||||
|
record.control_message_id = str(data["control_message_id"]) if data.get("control_message_id") else None
|
||||||
|
record.access_mode = data.get("access_mode", "open")
|
||||||
|
record.whitelist = json.dumps(sorted(data.get("whitelist", set())))
|
||||||
|
record.blacklist = json.dumps(sorted(data.get("blacklist", set())))
|
||||||
|
record.managed_member_ids = json.dumps(sorted(data.get("managed_member_ids", set())))
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
|
||||||
|
def _auto_rooms_config() -> tuple[bool, int]:
|
||||||
|
with webapp.app_context():
|
||||||
|
config = ConfigurationHelper()
|
||||||
|
return bool(config.getValue("auto_rooms_enable")), config.getIntValue("auto_rooms_channel_id")
|
||||||
|
|
||||||
|
|
||||||
def _find_room_by_channel(guild_id: int, channel_id: int) -> Optional[tuple[int, dict]]:
|
def _find_room_by_channel(guild_id: int, channel_id: int) -> Optional[tuple[int, dict]]:
|
||||||
@@ -158,7 +191,7 @@ def _find_room_by_message(message_id: int) -> Optional[tuple[int, int, dict]]:
|
|||||||
return (guild_id, owner_id, data)
|
return (guild_id, owner_id, data)
|
||||||
|
|
||||||
|
|
||||||
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, room: dict):
|
||||||
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 = dict(channel.overwrites) # Récupérer les overwrites existants
|
||||||
@@ -175,10 +208,11 @@ async def _apply_access_mode(channel: discord.VoiceChannel, mode: str, whitelist
|
|||||||
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
|
# Ne toucher qu'aux overwrites créés par l'auto room, jamais aux droits
|
||||||
|
# ajoutés manuellement par la modération.
|
||||||
for target in list(overwrites.keys()):
|
for target in list(overwrites.keys()):
|
||||||
if target != everyone and isinstance(target, discord.Member):
|
if target != everyone and isinstance(target, discord.Member):
|
||||||
if target.id not in blacklist:
|
if target.id in room.get("managed_member_ids", set()) and target.id not in blacklist:
|
||||||
overwrites.pop(target, None)
|
overwrites.pop(target, None)
|
||||||
# Ajouter les overwrites pour la blacklist
|
# Ajouter les overwrites pour la blacklist
|
||||||
for uid in blacklist:
|
for uid in blacklist:
|
||||||
@@ -188,10 +222,9 @@ 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()):
|
for target in list(overwrites.keys()):
|
||||||
if target != everyone and isinstance(target, discord.Member):
|
if target != everyone and isinstance(target, discord.Member):
|
||||||
if target.id not in whitelist:
|
if target.id in room.get("managed_member_ids", set()) and target.id not in whitelist:
|
||||||
overwrites.pop(target, None)
|
overwrites.pop(target, None)
|
||||||
# Ajouter les overwrites pour la whitelist
|
# Ajouter les overwrites pour la whitelist
|
||||||
for uid in whitelist:
|
for uid in whitelist:
|
||||||
@@ -201,10 +234,9 @@ 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()):
|
for target in list(overwrites.keys()):
|
||||||
if target != everyone and isinstance(target, discord.Member):
|
if target != everyone and isinstance(target, discord.Member):
|
||||||
if target.id not in whitelist:
|
if target.id in room.get("managed_member_ids", set()) and target.id not in whitelist:
|
||||||
overwrites.pop(target, None)
|
overwrites.pop(target, None)
|
||||||
# Ajouter les overwrites pour la whitelist
|
# Ajouter les overwrites pour la whitelist
|
||||||
for uid in whitelist:
|
for uid in whitelist:
|
||||||
@@ -214,6 +246,7 @@ async def _apply_access_mode(channel: discord.VoiceChannel, mode: str, whitelist
|
|||||||
|
|
||||||
overwrites[everyone] = everyone_ow
|
overwrites[everyone] = everyone_ow
|
||||||
await channel.edit(overwrites=overwrites)
|
await channel.edit(overwrites=overwrites)
|
||||||
|
room["managed_member_ids"] = set(blacklist if mode == "open" else whitelist)
|
||||||
|
|
||||||
|
|
||||||
async def _handle_reaction_action(bot: discord.Client, guild_id: int, owner_id: int, action: str, channel):
|
async def _handle_reaction_action(bot: discord.Client, guild_id: int, owner_id: int, action: str, channel):
|
||||||
@@ -229,7 +262,8 @@ 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()), room)
|
||||||
|
_persist_room(guild_id, owner_id, room)
|
||||||
# Mettre à jour le cadenas dans le nom du channel
|
# Mettre à jour le cadenas dans le nom du channel
|
||||||
try:
|
try:
|
||||||
base_name = voice_channel.name.rstrip(" 🔓🔒🔐")
|
base_name = voice_channel.name.rstrip(" 🔓🔒🔐")
|
||||||
@@ -361,14 +395,24 @@ _AUTO_ROOM_NAME_PATTERN = re.compile(r"^Salon de .+ [🔓🔒🔐]$")
|
|||||||
|
|
||||||
async def cleanup_orphaned_auto_rooms(bot: discord.Client):
|
async def cleanup_orphaned_auto_rooms(bot: discord.Client):
|
||||||
"""Supprime les auto rooms orphelines (vides) au démarrage du bot."""
|
"""Supprime les auto rooms orphelines (vides) au démarrage du bot."""
|
||||||
config = ConfigurationHelper()
|
enabled, trigger_channel_id = _auto_rooms_config()
|
||||||
if not config.getValue("auto_rooms_enable"):
|
if not enabled:
|
||||||
return
|
return
|
||||||
trigger_channel_id = config.getIntValue("auto_rooms_channel_id")
|
|
||||||
if not trigger_channel_id:
|
if not trigger_channel_id:
|
||||||
return
|
return
|
||||||
|
|
||||||
deleted = 0
|
deleted = 0
|
||||||
|
# Les rooms persistées sont connues même si leur nom a été modifié manuellement.
|
||||||
|
for (guild_id, owner_id), room in list(_rooms.items()):
|
||||||
|
channel = bot.get_channel(room["voice_channel_id"])
|
||||||
|
if isinstance(channel, discord.VoiceChannel) and not channel.members:
|
||||||
|
try:
|
||||||
|
await channel.delete(reason="Nettoyage auto room vide au démarrage")
|
||||||
|
_del_room(guild_id, owner_id)
|
||||||
|
deleted += 1
|
||||||
|
except discord.HTTPException:
|
||||||
|
pass
|
||||||
|
|
||||||
for guild in bot.guilds:
|
for guild in bot.guilds:
|
||||||
trigger_channel = guild.get_channel(trigger_channel_id)
|
trigger_channel = guild.get_channel(trigger_channel_id)
|
||||||
if not trigger_channel or not trigger_channel.category:
|
if not trigger_channel or not trigger_channel.category:
|
||||||
@@ -382,6 +426,9 @@ async def cleanup_orphaned_auto_rooms(bot: discord.Client):
|
|||||||
if len(channel.members) == 0:
|
if len(channel.members) == 0:
|
||||||
try:
|
try:
|
||||||
await channel.delete(reason="Nettoyage auto room orpheline au démarrage")
|
await channel.delete(reason="Nettoyage auto room orpheline au démarrage")
|
||||||
|
result = _find_room_by_channel(guild.id, channel.id)
|
||||||
|
if result:
|
||||||
|
_del_room(guild.id, result[0])
|
||||||
deleted += 1
|
deleted += 1
|
||||||
except discord.HTTPException:
|
except discord.HTTPException:
|
||||||
pass
|
pass
|
||||||
@@ -389,11 +436,40 @@ async def cleanup_orphaned_auto_rooms(bot: discord.Client):
|
|||||||
logging.info(f"Nettoyage auto rooms : {deleted} salon(s) orphelin(s) supprimé(s)")
|
logging.info(f"Nettoyage auto rooms : {deleted} salon(s) orphelin(s) supprimé(s)")
|
||||||
|
|
||||||
|
|
||||||
|
async def restore_auto_rooms(bot: discord.Client):
|
||||||
|
"""Recharge les salons encore existants après un redémarrage du bot."""
|
||||||
|
with webapp.app_context():
|
||||||
|
records = AutoRoom.query.all()
|
||||||
|
for record in records:
|
||||||
|
guild = bot.get_guild(int(record.guild_id))
|
||||||
|
channel = guild.get_channel(int(record.voice_channel_id)) if guild else None
|
||||||
|
if not isinstance(channel, discord.VoiceChannel):
|
||||||
|
with webapp.app_context():
|
||||||
|
db.session.delete(db.session.merge(record))
|
||||||
|
db.session.commit()
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
whitelist = set(json.loads(record.whitelist or "[]"))
|
||||||
|
blacklist = set(json.loads(record.blacklist or "[]"))
|
||||||
|
managed_member_ids = set(json.loads(record.managed_member_ids or "[]"))
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
whitelist, blacklist, managed_member_ids = set(), set(), set()
|
||||||
|
_set_room(int(record.guild_id), int(record.owner_id), {
|
||||||
|
"guild_id": int(record.guild_id),
|
||||||
|
"voice_channel_id": int(record.voice_channel_id),
|
||||||
|
"control_message_id": int(record.control_message_id) if record.control_message_id else None,
|
||||||
|
"owner_id": int(record.owner_id),
|
||||||
|
"whitelist": whitelist,
|
||||||
|
"blacklist": blacklist,
|
||||||
|
"managed_member_ids": managed_member_ids,
|
||||||
|
"access_mode": record.access_mode or "open",
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
async def on_voice_state_update_auto_rooms(bot: discord.Client, member: Member, before: VoiceState, after: VoiceState):
|
async def on_voice_state_update_auto_rooms(bot: discord.Client, member: Member, before: VoiceState, after: VoiceState):
|
||||||
config = ConfigurationHelper()
|
enabled, trigger_channel_id = _auto_rooms_config()
|
||||||
if not config.getValue("auto_rooms_enable"):
|
if not enabled:
|
||||||
return
|
return
|
||||||
trigger_channel_id = config.getIntValue("auto_rooms_channel_id")
|
|
||||||
if not trigger_channel_id:
|
if not trigger_channel_id:
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -403,13 +479,11 @@ async def on_voice_state_update_auto_rooms(bot: discord.Client, member: Member,
|
|||||||
existing_room = _get_room(guild.id, member.id)
|
existing_room = _get_room(guild.id, member.id)
|
||||||
if existing_room:
|
if existing_room:
|
||||||
old_channel = bot.get_channel(existing_room["voice_channel_id"])
|
old_channel = bot.get_channel(existing_room["voice_channel_id"])
|
||||||
_del_room(guild.id, member.id)
|
|
||||||
if old_channel and isinstance(old_channel, discord.VoiceChannel):
|
if old_channel and isinstance(old_channel, discord.VoiceChannel):
|
||||||
if len(old_channel.members) == 0:
|
# Ne jamais abandonner une room encore occupée : le propriétaire y retourne.
|
||||||
try:
|
await member.move_to(old_channel)
|
||||||
await old_channel.delete(reason="Auto room remplacée")
|
return
|
||||||
except discord.HTTPException:
|
_del_room(guild.id, member.id)
|
||||||
pass
|
|
||||||
|
|
||||||
category = after.channel.category
|
category = after.channel.category
|
||||||
channel_name = f"Salon de {member.display_name} {_status_emoji('open')}"
|
channel_name = f"Salon de {member.display_name} {_status_emoji('open')}"
|
||||||
@@ -429,10 +503,15 @@ async def on_voice_state_update_auto_rooms(bot: discord.Client, member: Member,
|
|||||||
"owner_id": member.id,
|
"owner_id": member.id,
|
||||||
"whitelist": set(),
|
"whitelist": set(),
|
||||||
"blacklist": set(),
|
"blacklist": set(),
|
||||||
|
"managed_member_ids": set(),
|
||||||
"access_mode": "open",
|
"access_mode": "open",
|
||||||
}
|
}
|
||||||
|
|
||||||
control_message_id = await send_control_panel(bot, guild.id, member, new_channel, room_data)
|
control_message_id = await send_control_panel(bot, guild.id, member, new_channel, room_data)
|
||||||
|
if not control_message_id:
|
||||||
|
await new_channel.delete(reason="Panneau Auto Room impossible à créer")
|
||||||
|
await member.move_to(after.channel)
|
||||||
|
return
|
||||||
room_data["control_message_id"] = control_message_id
|
room_data["control_message_id"] = control_message_id
|
||||||
_set_room(guild.id, member.id, room_data)
|
_set_room(guild.id, member.id, room_data)
|
||||||
|
|
||||||
@@ -445,12 +524,13 @@ async def on_voice_state_update_auto_rooms(bot: discord.Client, member: Member,
|
|||||||
if result:
|
if result:
|
||||||
owner_id, room = result
|
owner_id, room = result
|
||||||
remaining = [m for m in before.channel.members if m.id != member.id]
|
remaining = [m for m in before.channel.members if m.id != member.id]
|
||||||
if member.id == owner_id:
|
if member.id == owner_id and remaining:
|
||||||
|
new_owner = remaining[0]
|
||||||
_del_room(guild.id, owner_id)
|
_del_room(guild.id, owner_id)
|
||||||
try:
|
room["owner_id"] = new_owner.id
|
||||||
await before.channel.delete(reason="Propriétaire parti (auto room)")
|
_set_room(guild.id, new_owner.id, room)
|
||||||
except discord.HTTPException:
|
await before.channel.send(f"👑 {new_owner.mention} est maintenant propriétaire du salon.")
|
||||||
pass
|
await _update_control_panel(bot, guild.id, new_owner.id, before.channel)
|
||||||
elif len(remaining) == 0:
|
elif len(remaining) == 0:
|
||||||
_del_room(guild.id, owner_id)
|
_del_room(guild.id, owner_id)
|
||||||
try:
|
try:
|
||||||
@@ -463,7 +543,8 @@ 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.)."""
|
"""Gère les messages dans les salons vocaux pour les actions (statut, liste blanche/noire, etc.)."""
|
||||||
if message.author.bot:
|
if message.author.bot:
|
||||||
return
|
return
|
||||||
if not ConfigurationHelper().getValue("auto_rooms_enable"):
|
enabled, _ = _auto_rooms_config()
|
||||||
|
if not enabled:
|
||||||
return
|
return
|
||||||
|
|
||||||
# Vérifier si c'est dans un salon vocal (partie texte)
|
# Vérifier si c'est dans un salon vocal (partie texte)
|
||||||
@@ -515,7 +596,11 @@ async def on_message_auto_rooms(bot: discord.Client, message: discord.Message):
|
|||||||
whitelist.add(target.id)
|
whitelist.add(target.id)
|
||||||
await message.channel.send(f"✅ {target.mention} a été ajouté à la liste blanche.")
|
await message.channel.send(f"✅ {target.mention} a été ajouté à la liste blanche.")
|
||||||
room["whitelist"] = whitelist
|
room["whitelist"] = whitelist
|
||||||
await _apply_access_mode(voice_channel, room.get("access_mode", "open"), whitelist, room.get("blacklist", set()))
|
blacklist = room.get("blacklist", set())
|
||||||
|
blacklist.discard(target.id)
|
||||||
|
room["blacklist"] = blacklist
|
||||||
|
await _apply_access_mode(voice_channel, room.get("access_mode", "open"), whitelist, blacklist, room)
|
||||||
|
_persist_room(message.guild.id, owner_id, room)
|
||||||
await _update_control_panel(bot, message.guild.id, owner_id, message.channel)
|
await _update_control_panel(bot, message.guild.id, owner_id, message.channel)
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -532,7 +617,11 @@ async def on_message_auto_rooms(bot: discord.Client, message: discord.Message):
|
|||||||
blacklist.add(target.id)
|
blacklist.add(target.id)
|
||||||
await message.channel.send(f"✅ {target.mention} a été ajouté à la liste noire.")
|
await message.channel.send(f"✅ {target.mention} a été ajouté à la liste noire.")
|
||||||
room["blacklist"] = blacklist
|
room["blacklist"] = blacklist
|
||||||
await _apply_access_mode(voice_channel, room.get("access_mode", "open"), room.get("whitelist", set()), blacklist)
|
whitelist = room.get("whitelist", set())
|
||||||
|
whitelist.discard(target.id)
|
||||||
|
room["whitelist"] = whitelist
|
||||||
|
await _apply_access_mode(voice_channel, room.get("access_mode", "open"), whitelist, blacklist, room)
|
||||||
|
_persist_room(message.guild.id, owner_id, room)
|
||||||
await _update_control_panel(bot, message.guild.id, owner_id, message.channel)
|
await _update_control_panel(bot, message.guild.id, owner_id, message.channel)
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -568,7 +657,8 @@ async def on_raw_reaction_add_auto_rooms(bot: discord.Client, payload: discord.R
|
|||||||
"""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:
|
||||||
return
|
return
|
||||||
if not ConfigurationHelper().getValue("auto_rooms_enable"):
|
enabled, _ = _auto_rooms_config()
|
||||||
|
if not enabled:
|
||||||
return
|
return
|
||||||
room_info = _find_room_by_message(payload.message_id)
|
room_info = _find_room_by_message(payload.message_id)
|
||||||
if not room_info:
|
if not room_info:
|
||||||
|
|||||||
Reference in New Issue
Block a user