From b24921d8ba3df6540c6b1e4d219835dd44b8f188 Mon Sep 17 00:00:00 2001 From: ddorn Date: Mon, 27 Apr 2020 11:43:16 +0200 Subject: [PATCH] :recycle: move Tirage things to a Cog --- src/cogs/__init__.py | 2 + src/cogs/tirages.py | 154 +++++++++++++++++++++++++++++++++++++--- src/tfjm_discord_bot.py | 129 ++------------------------------- 3 files changed, 153 insertions(+), 132 deletions(-) diff --git a/src/cogs/__init__.py b/src/cogs/__init__.py index bb404a4..3dc3149 100644 --- a/src/cogs/__init__.py +++ b/src/cogs/__init__.py @@ -2,3 +2,5 @@ This package contains all the cogs (groups of commands) of the TFJM² bot. """ + +from .tirages import TirageCog diff --git a/src/cogs/tirages.py b/src/cogs/tirages.py index a60aa99..b5d66dc 100644 --- a/src/cogs/tirages.py +++ b/src/cogs/tirages.py @@ -6,7 +6,8 @@ from typing import Type import discord import yaml -from discord.ext.commands import Context +from discord.ext import commands +from discord.ext.commands import Context, group, Cog from discord.utils import get from src.constants import * @@ -103,14 +104,10 @@ class Tirage(yaml.YAMLObject): await self.phase.start(ctx) async def end(self, ctx): - - from src.tfjm_discord_bot import tirages - - del tirages[self.channel] - - # Allow everyone to send messages again - send = discord.PermissionOverwrite() # reset - await ctx.channel.edit(overwrites={ctx.guild.default_role: send}) + if False: + # Allow everyone to send messages again + send = discord.PermissionOverwrite() # reset + await ctx.channel.edit(overwrites={ctx.guild.default_role: send}) tl = [] if TIRAGES_FILE.exists(): @@ -519,3 +516,142 @@ class TirageOrderPhase(OrderPhase): "comme ceci `!dice 100`. " "L'ordre des tirages suivants sera l'ordre croissant des lancers. " ) + + +class TirageCog(Cog, name="Tirages"): + def __init__(self, bot): + self.bot: commands.Bot = bot + + # We retrieve the global variable. + # We don't want tirages to be ust an attribute + # as we want them to outlive the Cog, for instance + # if the cog is reloaded turing a tirage. + from src.tfjm_discord_bot import tirages + + self.tirages = tirages + + @group( + name="draw", aliases=["d", "tirage"], + ) + async def draw_group(self, ctx: Context) -> None: + """Commandes pour les tirages.""" + + @draw_group.command( + name="start", usage="équipe1 équipe2 équipe3 (équipe4)", + ) + @commands.has_role(ORGA_ROLE) + async def start(self, ctx: Context, *teams): + """ + Commence un tirage avec 3 ou 4 équipes. + + Cette commande attend trois trigrammes d'équipes, par ex: + + !draw start AAA BBB CCC + """ + + channel: discord.TextChannel = ctx.channel + channel_id = channel.id + if channel_id in self.tirages: + raise TfjmError("Il y a déjà un tirage en cours sur cette Channel.") + + if len(teams) not in (3, 4): + raise TfjmError("Il faut 3 ou 4 équipes pour un tirage.") + + roles = {role.name for role in ctx.guild.roles} + for team in teams: + if team not in roles: + raise TfjmError( + "Le nom de l'équipe doit être exactement celui du rôle." + ) + + # Here all data should be valid + + # Prevent everyone from writing except Capitaines, Orga, CNO, Benevole + if False: + read = discord.PermissionOverwrite(send_messages=False) + send = discord.PermissionOverwrite(send_messages=True) + r = lambda role_name: get(ctx.guild.roles, name=role_name) + overwrites = { + ctx.guild.default_role: read, + r(CAPTAIN_ROLE): send, + r(BENEVOLE_ROLE): send, + } + await channel.edit(overwrites=overwrites) + + await ctx.send( + "Nous allons commencer le tirage du premier tour. " + "Seuls les capitaines de chaque équipe peuvent désormais écrire ici. " + "Merci de d'envoyer seulement ce que est nécessaire et suffisant au " + "bon déroulement du tournoi. Vous pouvez à tout moment poser toute question " + "si quelque chose n'est pas clair ou ne va pas. \n\n" + "Pour plus de détails sur le déroulement du tirgae au sort, le règlement " + "est accessible sur https://tfjm.org/reglement." + ) + + self.tirages[channel_id] = Tirage(ctx, channel_id, teams) + await self.tirages[channel_id].phase.start(ctx) + + @draw_group.command( + name="abort", help="Annule le tirage en cours.", + ) + @commands.has_role(ORGA_ROLE) + async def abort_draw_cmd(self, ctx): + channel_id = ctx.channel.id + if channel_id in self.tirages: + await self.tirages[channel_id].end(ctx) + await ctx.send("Le tirage est annulé.") + + @draw_group.command(name="skip", aliases=["s"]) + @commands.has_role(CNO_ROLE) + async def draw_skip(self, ctx, *teams): + channel = ctx.channel.id + self.tirages[channel] = tirage = Tirage(ctx, channel, teams) + + tirage.phase = TiragePhase(tirage, round=1) + for i, team in enumerate(tirage.teams): + team.tirage_order = [i + 1, i + 1] + team.passage_order = [i + 1, i + 1] + team.accepted_problems = [PROBLEMS[i], PROBLEMS[-i - 1]] + tirage.teams[0].rejected = [{PROBLEMS[3]}, set(PROBLEMS[4:8])] + tirage.teams[1].rejected = [{PROBLEMS[7]}, set()] + + await ctx.send(f"Skipping to {tirage.phase.__class__.__name__}.") + await tirage.phase.start(ctx) + await tirage.update_phase(ctx) + + @draw_group.command(name="show") + async def show_cmd(self, ctx: Context, arg: str): + if not TIRAGES_FILE.exists(): + await ctx.send("Il n'y a pas encore eu de tirages.") + return + + with open(TIRAGES_FILE) as f: + tirages = list(yaml.load_all(f)) + + if arg.lower() == "all": + msg = "\n".join( + f"{i}: {', '.join(team.name for team in tirage.teams)}" + for i, tirage in enumerate(tirages) + ) + await ctx.send( + "Voici in liste de tous les tirages qui ont été faits. " + "Vous pouvez en consulter un en particulier avec `!show ID`." + ) + await ctx.send(msg) + else: + try: + n = int(arg) + if n < 0: + raise ValueError + tirage = tirages[n] + except (ValueError, IndexError): + await ctx.send( + f"`{arg}` n'est pas un identifiant valide. " + f"Les identifiants valides sont visibles avec `!show all`" + ) + else: + await tirage.show(ctx) + + +def setup(bot): + bot.add_cog(TirageCog(bot)) diff --git a/src/tfjm_discord_bot.py b/src/tfjm_discord_bot.py index fff9e1f..2250394 100644 --- a/src/tfjm_discord_bot.py +++ b/src/tfjm_discord_bot.py @@ -1,107 +1,21 @@ #!/bin/python -import asyncio import code import random import sys import traceback -from collections import defaultdict, namedtuple from pprint import pprint -from typing import Dict, Type import discord -import yaml from discord.ext import commands from discord.ext.commands import Context -from discord.utils import get -from src.cogs.tirages import Tirage, TiragePhase from src.constants import * from src.errors import TfjmError, UnwantedCommand +bot = commands.Bot("!", help_command=commands.MinimalHelpCommand(no_category="Autres")) -bot = commands.Bot( - "!", help_command=commands.DefaultHelpCommand(no_category="Commandes") -) - -# global variable to hold every running tirage -tirages: Dict[int, Tirage] = {} - - -@bot.command( - name="start-draw", - help="Commence un tirage avec 3 ou 4 équipes.", - usage="équipe1 équipe2 équipe3 (équipe4)", -) -@commands.has_role(ORGA_ROLE) -async def start_draw(ctx: Context, *teams): - channel: discord.TextChannel = ctx.channel - channel_id = channel.id - if channel_id in tirages: - raise TfjmError("Il y a déjà un tirage en cours sur cette Channel.") - - if len(teams) not in (3, 4): - raise TfjmError("Il faut 3 ou 4 équipes pour un tirage.") - - roles = {role.name for role in ctx.guild.roles} - for team in teams: - if team not in roles: - raise TfjmError("Le nom de l'équipe doit être exactement celui du rôle.") - - # Here all data should be valid - - # Prevent everyone from writing except Capitaines, Orga, CNO, Benevole - read = discord.PermissionOverwrite(send_messages=False) - send = discord.PermissionOverwrite(send_messages=True) - r = lambda role_name: get(ctx.guild.roles, name=role_name) - overwrites = { - ctx.guild.default_role: read, - r(CAPTAIN_ROLE): send, - r(BENEVOLE_ROLE): send, - } - await channel.edit(overwrites=overwrites) - - await ctx.send( - "Nous allons commencer le tirage du premier tour. " - "Seuls les capitaines de chaque équipe peuvent désormais écrire ici. " - "Merci de d'envoyer seulement ce que est nécessaire et suffisant au " - "bon déroulement du tournoi. Vous pouvez à tout moment poser toute question " - "si quelque chose n'est pas clair ou ne va pas. \n\n" - "Pour plus de détails sur le déroulement du tirgae au sort, le règlement " - "est accessible sur https://tfjm.org/reglement." - ) - - tirages[channel_id] = Tirage(ctx, channel_id, teams) - await tirages[channel_id].phase.start(ctx) - - -@bot.command( - name="abort-draw", help="Annule le tirage en cours.", -) -@commands.has_role(ORGA_ROLE) -async def abort_draw_cmd(ctx): - channel_id = ctx.channel.id - if channel_id in tirages: - await tirages[channel_id].end(ctx) - await ctx.send("Le tirage est annulé.") - - -@bot.command(name="draw-skip", aliases=["skip"]) -@commands.has_role(CNO_ROLE) -async def draw_skip(ctx, *teams): - channel = ctx.channel.id - tirages[channel] = tirage = Tirage(ctx, channel, teams) - - tirage.phase = TiragePhase(tirage, round=1) - for i, team in enumerate(tirage.teams): - team.tirage_order = [i + 1, i + 1] - team.passage_order = [i + 1, i + 1] - team.accepted_problems = [PROBLEMS[i], PROBLEMS[-i - 1]] - tirage.teams[0].rejected = [{PROBLEMS[3]}, set(PROBLEMS[4:8])] - tirage.teams[1].rejected = [{PROBLEMS[7]}, set()] - - await ctx.send(f"Skipping to {tirage.phase.__class__.__name__}.") - await tirage.phase.start(ctx) - await tirage.update_phase(ctx) +# Variable globale qui contient les tirages. +tirages = {} @bot.event @@ -178,40 +92,6 @@ async def refuse_cmd(ctx): await ctx.send(f"{ctx.author.mention} nie tout en block !") -@bot.command(name="show") -async def show_cmd(ctx: Context, arg: str): - if not TIRAGES_FILE.exists(): - await ctx.send("Il n'y a pas encore eu de tirages.") - return - - with open(TIRAGES_FILE) as f: - tirages = list(yaml.load_all(f)) - - if arg.lower() == "all": - msg = "\n".join( - f"{i}: {', '.join(team.name for team in tirage.teams)}" - for i, tirage in enumerate(tirages) - ) - await ctx.send( - "Voici in liste de tous les tirages qui ont été faits. " - "Vous pouvez en consulter un en particulier avec `!show ID`." - ) - await ctx.send(msg) - else: - try: - n = int(arg) - if n < 0: - raise ValueError - tirage = tirages[n] - except (ValueError, IndexError): - await ctx.send( - f"`{arg}` n'est pas un identifiant valide. " - f"Les identifiants valides sont visibles avec `!show all`" - ) - else: - await tirage.show(ctx) - - @bot.command(name="interrupt") @commands.has_role(CNO_ROLE) async def interrupt_cmd(ctx): @@ -260,5 +140,8 @@ async def on_command_error(ctx: Context, error, *args, **kwargs): await ctx.send(msg) +bot.load_extension("src.cogs.tirages") + + if __name__ == "__main__": bot.run(TOKEN)