From b0ee138e5aed0d9f440a2e431e045bc944aae254 Mon Sep 17 00:00:00 2001 From: mortifia Date: Mon, 13 Jul 2026 04:23:27 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20restriction=20fine=20du=20bot=20dev/tes?= =?UTF-8?q?t=20par=20liste=20de=20salons=20et/ou=20cat=C3=A9gorie=20(#88)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RESTRICT_TO_CHANNEL_ID accepte désormais une liste de salons séparés par des virgules (un seul identifiant, sans virgule, reste rétrocompatible). Nouvelle variable RESTRICT_TO_CATEGORY_ID : tout salon rangé dans cette catégorie Discord est autorisé, en plus de ceux listés dans RESTRICT_TO_CHANNEL_ID. Permet d'ajouter de nouveaux salons de dev/test à la catégorie sans redéployer ni reconfigurer le bot. Les deux variables sont indépendantes et optionnelles ; ni l'une ni l'autre définie (cas de la prod) laisse le comportement inchangé. ctx.channel.category_id est lu via getattr avec une valeur par défaut pour ne pas planter sur les DM (qui n'ont pas cette catégorie). docker-compose.dev.yml utilise maintenant RESTRICT_TO_CATEGORY_ID pointant sur la catégorie de salons de test dédiée. Closes #88 --- README.md | 14 +++++++++-- docker-compose.dev.yml | 15 +++++++++--- src/bot/urbot.py | 55 ++++++++++++++++++++++++++++++++++-------- 3 files changed, 68 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 4cc92a7..7008975 100755 --- a/README.md +++ b/README.md @@ -26,8 +26,9 @@ 4. [MAINTENANCE](#maintenance-) 5. [DÉVELOPPEMENT](#développement-) -- 5.1 [Grafcet Bot_Planning](#grafcet-bot_planning-) -- 5.2 [Grafcet Bot_Presentation](#grafcet-bot_presentation-) +- 5.1 [Instance de dev/test](#instance-de-devtest-) +- 5.2 [Grafcet Bot_Planning](#grafcet-bot_planning-) +- 5.3 [Grafcet Bot_Presentation](#grafcet-bot_presentation-) 6. [CRÉDITS, PARTICIPANTS ET ORGANISATION](#crédits-participants-et-organisation) @@ -202,6 +203,15 @@ Le projet fonctionne grâce à cinq langages, qui sont **Python**, **XML** (eXte Une question particulière ? L'association Union des Rôlistes est disponible aux adresses mentionnées à la dernière section du fichier. +--- +### Instance de dev/test : +Pour tester des changements sans impacter la prod, une instance de dev/test peut être lancée via `docker-compose.dev.yml` avec un jeton Discord distinct. Cette instance peut être restreinte à un sous-ensemble de salons grâce à deux variables d'environnement, toutes deux facultatives et indépendantes (voir `src/bot/urbot.py`) : + +- `RESTRICT_TO_CHANNEL_ID` : un ou plusieurs identifiants de salon Discord, séparés par des virgules (ex: `123456789012345678,987654321098765432`). Un seul identifiant, sans virgule, reste valide. +- `RESTRICT_TO_CATEGORY_ID` : l'identifiant d'une catégorie Discord. Tout salon rangé dans cette catégorie est autorisé, en plus de ceux listés dans `RESTRICT_TO_CHANNEL_ID`. Cela permet d'ajouter de nouveaux salons de dev/test à la catégorie sans avoir à redéployer ou reconfigurer le bot. + +Si aucune des deux variables n'est définie (cas de la prod), le bot répond normalement dans tous les salons. Si les deux sont définies, un salon est autorisé s'il correspond à l'une **ou** l'autre condition. + --- ### Grafcet Bot_Planning : Grafcet simple pour Bot_Planning diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index 3369345..abcbc4f 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -13,7 +13,14 @@ services: volumes: - ./.bot_token:/usr/local/src/URbot/.bot_token:ro environment: - # Salon Discord auquel restreindre les réponses du bot (voir - # src/bot/urbot.py) — laisser vide/absent pour un comportement - # normal (tous les salons, comme la prod). - - RESTRICT_TO_CHANNEL_ID=1526011382418641079 + # Catégorie Discord dont tous les salons sont autorisés (voir + # src/bot/urbot.py) — laisser vide/absent pour un comportement normal + # (tous les salons, comme la prod). Les nouveaux salons de dev/test + # ajoutés à cette catégorie deviennent utilisables sans redéployer + # ni reconfigurer le bot. + - RESTRICT_TO_CATEGORY_ID=1526025031384301599 + # Salon(s) Discord supplémentaires autorisés même hors de la + # catégorie ci-dessus, séparés par des virgules si plusieurs. + # Optionnel, indépendant de RESTRICT_TO_CATEGORY_ID. Exemple + # (désactivé) : + # - RESTRICT_TO_CHANNEL_ID=1526011382418641079,1526011382418641080 diff --git a/src/bot/urbot.py b/src/bot/urbot.py index 65229f7..6c496ea 100755 --- a/src/bot/urbot.py +++ b/src/bot/urbot.py @@ -128,19 +128,54 @@ def main(): logging.basicConfig(level=logging.INFO) ur_bot = URBot() - # Restreint le bot à un seul salon si RESTRICT_TO_CHANNEL_ID est défini - # (instance de dev/test) ; n'affecte pas la prod, qui ne définit pas - # cette variable. Vérification globale : s'applique à toutes les - # commandes de tous les cogs, sans toucher à leur code. - restrict_channel_id = os.environ.get('RESTRICT_TO_CHANNEL_ID') - if restrict_channel_id: - restrict_channel_id = int(restrict_channel_id) + # Restreint le bot à un ensemble de salons et/ou à une catégorie si + # RESTRICT_TO_CHANNEL_ID et/ou RESTRICT_TO_CATEGORY_ID sont définis + # (instance de dev/test) ; n'affecte pas la prod, qui ne définit ni + # l'une ni l'autre de ces variables. Vérification globale : s'applique + # à toutes les commandes de tous les cogs, sans toucher à leur code. + # + # RESTRICT_TO_CHANNEL_ID accepte une liste de salons séparés par des + # virgules (un seul identifiant, sans virgule, reste valide). + # RESTRICT_TO_CATEGORY_ID désigne une catégorie Discord : tout salon + # qui y est rangé est autorisé, ce qui permet d'ajouter de nouveaux + # salons de dev/test sans redéployer ni reconfigurer le bot. + # Si les deux variables sont définies, un salon est autorisé s'il + # correspond à l'une OU l'autre condition. + restrict_channel_ids_raw = os.environ.get('RESTRICT_TO_CHANNEL_ID') + restrict_category_id_raw = os.environ.get('RESTRICT_TO_CATEGORY_ID') + + restrict_channel_ids = None + if restrict_channel_ids_raw: + restrict_channel_ids = { + int(channel_id.strip()) + for channel_id in restrict_channel_ids_raw.split(',') + if channel_id.strip() + } + + restrict_category_id = None + if restrict_category_id_raw: + restrict_category_id = int(restrict_category_id_raw) + + if restrict_channel_ids or restrict_category_id is not None: @ur_bot.check def restrict_to_channel(ctx): - return ctx.channel.id == restrict_channel_id - - log(f"Restreint au salon {restrict_channel_id}") + if restrict_channel_ids and ctx.channel.id in restrict_channel_ids: + return True + if restrict_category_id is not None: + # ctx.channel peut être un DMChannel, qui n'a pas de + # category_id : on échoue simplement le test au lieu de + # planter. + if getattr(ctx.channel, 'category_id', None) == restrict_category_id: + return True + return False + + restriction_desc = [] + if restrict_channel_ids: + restriction_desc.append(f"salons {sorted(restrict_channel_ids)}") + if restrict_category_id is not None: + restriction_desc.append(f"catégorie {restrict_category_id}") + log(f"Restreint aux {' et '.join(restriction_desc)}") log("Loading cogs...") # adds the "cogs" folder to the import path