Compare commits

..

3 Commits

231
bot.py
View File

@ -45,6 +45,8 @@ CANTONS = {
"ZH": "Zurich", "ZH": "Zurich",
} }
EQUIPES = ["rouge", "vert"]
CodeCanton = Literal["AG", "AI", "AR", "BE", "BL", "BS", "FR", "GE", "GL", "GR", "JU", "LU", "NE", CodeCanton = Literal["AG", "AI", "AR", "BE", "BL", "BS", "FR", "GE", "GL", "GR", "JU", "LU", "NE",
"NW", "OW", "SG", "SH", "SO", "SZ", "TH", "TI", "UR", "VD", "VS", "ZG", "ZH"] "NW", "OW", "SG", "SH", "SO", "SZ", "TH", "TI", "UR", "VD", "VS", "ZG", "ZH"]
Couleur = Literal["rouge", "vert"] Couleur = Literal["rouge", "vert"]
@ -53,7 +55,8 @@ Couleur = Literal["rouge", "vert"]
intents = discord.Intents.default() intents = discord.Intents.default()
intents.message_content = True intents.message_content = True
bot = commands.Bot(command_prefix='$', intents=intents) PREFIX = '$'
bot = commands.Bot(command_prefix=PREFIX, intents=intents)
DATA_FILE = Path(__file__).parent / "data.json" DATA_FILE = Path(__file__).parent / "data.json"
if DATA_FILE.exists(): if DATA_FILE.exists():
@ -61,10 +64,10 @@ if DATA_FILE.exists():
data = json.load(data_file) data = json.load(data_file)
else: else:
data = { data = {
'equipes': {'rouge': [], 'vert': []}, 'equipes': {equipe: [] for equipe in EQUIPES},
'cantons': {code_canton: {'capture': None, 'verrouille': False} for code_canton in CANTONS.keys()}, 'cantons': {code_canton: {'capture': None, 'verrouille': False} for code_canton in CANTONS.keys()},
'defis': { 'defis': {
'mains': {'rouge': [], 'vert': []}, 'mains': {equipe: [] for equipe in EQUIPES},
'tires_capture': [], 'tires_capture': [],
'tires_competition': [], 'tires_competition': [],
} }
@ -122,7 +125,7 @@ async def capturer(ctx: commands.Context, canton: CodeCanton, *, couleur: Couleu
if author_id in membres_equipe: if author_id in membres_equipe:
break break
else: else:
raise commands.BadArgument("Vous n'appartez à aucune équipe. Merci de faire `$equipe [rouge|vert]`.") raise commands.BadArgument(f"Vous n'appartez à aucune équipe. Merci de faire `{PREFIX}equipe [{"|".join(EQUIPES)}]`.")
data['cantons'][canton]['capture'] = couleur data['cantons'][canton]['capture'] = couleur
with DATA_FILE.open('w') as data_file: with DATA_FILE.open('w') as data_file:
json.dump(data, data_file, indent=2) json.dump(data, data_file, indent=2)
@ -146,7 +149,7 @@ async def verrouiller(ctx: commands.Context, canton: CodeCanton, *, couleur: Cou
if author_id in membres_equipe: if author_id in membres_equipe:
break break
else: else:
raise commands.BadArgument("Vous n'appartez à aucune équipe. Merci de faire `$equipe [rouge|vert]`.") raise commands.BadArgument(f"Vous n'appartez à aucune équipe. Merci de faire `{PREFIX}equipe [{"|".join(EQUIPES)}]`.")
data['cantons'][canton]['capture'] = couleur data['cantons'][canton]['capture'] = couleur
data['cantons'][canton]['verrouille'] = True data['cantons'][canton]['verrouille'] = True
with DATA_FILE.open('w') as data_file: with DATA_FILE.open('w') as data_file:
@ -184,56 +187,56 @@ async def defis(ctx: commands.Context, *, type_defi: Literal['capture', 'competi
@bot.command() @bot.command()
async def description(ctx: commands.Context, type_defi: Literal['capture', 'competition'] = "capture"): async def description(ctx: commands.Context, type_defi: Literal['capture', 'competition'] = "capture", id_defi: int | None = None):
defis = DEFIS[type_defi] defis = DEFIS[type_defi]
embeds = [] embeds = []
for page in range((len(defis) - 1) // 25 + 1): if id_defi is not None:
defis_page = defis[page * 25:(page + 1) * 25] embed = discord.Embed(title=f"Description du défi {id_defi}", colour=discord.Colour.gold())
embed = discord.Embed(title=f"Description des défis", colour=discord.Colour.gold()) try:
embed.set_footer(f"Page {page}/{(len(defis) - 1) // 25 + 1}") defi = next(defi for defi in defis if defi['id'] == id_defi)
for defi in defis_page: except StopIteration:
embed.add_field(name=f"{defi['nom']} (n°{defi['id']})", value=defi['description'], inline=False) raise commands.BadArgument(f"Le défi de {type_defi}{id_defi} n'existe pas.")
embed.add_field(name=f"{defi['nom']}", value=defi['description'], inline=False)
embeds.append(embed) embeds.append(embed)
else:
for page in range((len(defis) - 1) // 25 + 1):
defis_page = defis[page * 25:(page + 1) * 25]
embed = discord.Embed(title=f"Description des défis", colour=discord.Colour.gold())
embed.set_footer(text=f"Page {page + 1}/{(len(defis) - 1) // 25 + 1}")
for defi in defis_page:
embed.add_field(name=f"{defi['nom']} (n°{defi['id']})", value=defi['description'], inline=False)
embeds.append(embed)
await ctx.send(embeds=embeds) await ctx.send(embeds=embeds)
@bot.command() @bot.command()
async def tirage(ctx: commands.Context, nb_defis: int = 7): async def tirage(ctx: commands.Context, nb_defis: int = 5):
if data['defis']['mains']['rouge'] or data['defis']['mains']['vert']: if any(data['defis']['mains'][equipe] for equipe in EQUIPES):
raise commands.BadArgument("Les mains sont déjà initialisées") raise commands.BadArgument("Les mains sont déjà initialisées")
defis_libres = copy.deepcopy(DEFIS['capture']) defis_libres = copy.deepcopy(DEFIS['capture'])
for equipe in ('rouge', 'vert'): for equipe in EQUIPES:
for _i in range(nb_defis): for _i in range(nb_defis):
defi = random.choice(defis_libres) defi = random.choice(defis_libres)
defis_libres.remove(defi) defis_libres.remove(defi)
data['defis']['mains'][equipe].append(defi['id']) data['defis']['mains'][equipe].append(defi['id'])
data['defis']['tires_capture'].append(defi['id']) data['defis']['tires_capture'].append(defi['id'])
main = data['defis']['mains'][equipe]
embeds = []
colour = discord.Color.red() if equipe == "rouge" else discord.Color.green()
for id_defi in main:
defi = next(defi for defi in DEFIS['capture'] if defi['id'] == id_defi)
embed = discord.Embed(title=defi['nom'], description=defi['description'], colour=colour)
embed.set_footer(text=f"Défi n°{defi['id']}")
embeds.append(embed)
for member_id in data['equipes'][equipe]: for member_id in data['equipes'][equipe]:
channel_dm = await bot.create_dm(namedtuple("User", "id")(member_id)) await afficher_main(ctx, author_id=member_id)
await channel_dm.send("Vos défis en main :", embeds=embeds)
with DATA_FILE.open('w') as data_file: with DATA_FILE.open('w') as data_file:
json.dump(data, data_file, indent=2) json.dump(data, data_file, indent=2)
await ctx.send("Les mains de départ ont bien été tirées ! Le contenu vous a été envoyé en MP.") await ctx.send("Les mains de départ ont bien été tirées ! Le contenu vous a été envoyé en MP.")
@bot.command() @bot.command(name="main")
async def main(ctx: commands.Context): async def afficher_main(ctx: commands.Context, mode: Literal['public', 'prive'] = "prive", author_id: int | None = None):
author_id = ctx.author.id author_id = author_id or ctx.author.id
for couleur, membres_equipe in data['equipes'].items(): for couleur, membres_equipe in data['equipes'].items():
if author_id in membres_equipe: if author_id in membres_equipe:
break break
else: else:
raise commands.BadArgument("Vous n'appartez à aucune équipe. Merci de faire `$equipe [rouge|vert]`.") raise commands.BadArgument(f"Vous n'appartez à aucune équipe. Merci de faire `{PREFIX}equipe [{"|".join(EQUIPES)}]`.")
main = data['defis']['mains'][couleur] main = data['defis']['mains'][couleur]
embeds = [] embeds = []
@ -243,13 +246,177 @@ async def main(ctx: commands.Context):
embed = discord.Embed(title=defi['nom'], description=defi['description'], colour=colour) embed = discord.Embed(title=defi['nom'], description=defi['description'], colour=colour)
embed.set_footer(text=f"Défi n°{defi['id']}") embed.set_footer(text=f"Défi n°{defi['id']}")
embeds.append(embed) embeds.append(embed)
channel_dm = await bot.create_dm(ctx.author) if mode == "public":
await channel_dm.send("Vos défis en main :", embeds=embeds) await ctx.send(f"Défis de l'équipe **{couleur}** :", embeds=embeds)
else:
channel_dm = await bot.create_dm(ctx.author)
await channel_dm.send("Vos défis en main :", embeds=embeds)
@bot.command()
async def terminer(ctx: commands.Context, id_defi: int):
if all(id_defi != defi['id'] for defi in DEFIS['capture']):
raise commands.BadArgument(f"Erreur : Le défi {id_defi_1} n'existe pas")
author_id = ctx.author.id
for equipe, membres_equipe in data['equipes'].items():
if author_id in membres_equipe:
break
else:
raise commands.BadArgument(f"Vous n'appartez à aucune équipe. Merci de faire `{PREFIX}equipe [{"|".join(EQUIPES)}]`.")
main = data['defis']['mains'][equipe]
if id_defi not in main:
raise commands.BadArgument(f"Le défi {id_defi} n'est pas dans votre main. Faites `{PREFIX}main` pour afficher votre main.")
nouveau_defi = random.choice([defi for defi in DEFIS['capture'] if defi['id'] not in data['defis']['tires_capture']])
main.remove(id_defi)
main.append(nouveau_defi['id'])
data['defis']['tires_capture'].append(nouveau_defi['id'])
with DATA_FILE.open('w') as data_file:
json.dump(data, data_file, indent=2)
colour = discord.Color.red() if equipe == "rouge" else discord.Color.green()
embed = discord.Embed(title=nouveau_defi['nom'], description=nouveau_defi['description'], colour=colour)
embed.set_footer(text=f"Défi n°{nouveau_defi['id']}")
await ctx.send("**Votre nouveau défi en main :**", embed=embed)
for member_id in data['equipes'][equipe]:
await afficher_main(ctx, author_id=member_id)
@bot.command()
async def echange(ctx: commands.Context, id_defi_1: int, id_defi_2: int):
if all(id_defi_1 != defi['id'] for defi in DEFIS['capture']):
raise commands.BadArgument(f"Erreur : Le défi {id_defi_1} n'existe pas")
if all(id_defi_2 != defi['id'] for defi in DEFIS['capture']):
raise commands.BadArgument(f"Erreur : Le défi {id_defi_2} n'existe pas")
defi_1 = next(defi for defi in DEFIS['capture'] if defi['id'] == id_defi_1)
defi_2 = next(defi for defi in DEFIS['capture'] if defi['id'] == id_defi_2)
equipe_1, equipe_2 = None, None
for equipe in EQUIPES:
main = data['defis']['mains'][equipe]
if id_defi_1 in main:
equipe_1 = equipe
if id_defi_2 in main:
equipe_2 = equipe
if equipe_1 is None and equipe_2 is None:
raise commands.BadArgument("Erreur : Aucun des deux défis n'est fait par une équipe")
elif equipe_1 == equipe_2:
raise commands.BadArgument(f"Erreur : Les défis {id_defi_1} et {id_defi_2} sont tous les deux fait par la même équipe {equipe_1}")
if equipe_1 is not None:
data['defis']['mains'][equipe_1].remove(id_defi_1)
data['defis']['mains'][equipe_1].append(id_defi_2)
else:
tires_capture = data['defis']['tires_capture']
if id_defi_1 not in tires_capture:
tires_capture.append(id_defi_1)
if id_defi_2 in tires_capture:
tires_capture.remove(id_defi_2)
if equipe_2 is not None:
data['defis']['mains'][equipe_2].remove(id_defi_2)
data['defis']['mains'][equipe_2].append(id_defi_1)
else:
tires_capture = data['defis']['tires_capture']
if id_defi_1 in tires_capture:
tires_capture.remove(id_defi_1)
if id_defi_2 not in tires_capture:
tires_capture.append(id_defi_2)
with DATA_FILE.open('w') as data_file:
json.dump(data, data_file, indent=2)
if equipe_1 is not None and equipe_2 is not None:
await ctx.send(f"Le défi **{defi_1['nom']}** de l'équipe **{equipe_1}** et le défi **{defi_2['nom']}** de l'équipe **{equipe_2}** ont été échangés !")
else:
await ctx.send(f"Les défis **{defi_1['nom']}** et **{defi_2['nom']}** ont été échangés !")
@bot.command()
async def melanger(ctx: commands.Context, nb_defis: int = 5):
author_id = ctx.author.id
for equipe, membres_equipe in data['equipes'].items():
if author_id in membres_equipe:
break
else:
raise commands.BadArgument(f"Vous n'appartez à aucune équipe. Merci de faire `{PREFIX}equipe [{"|".join(EQUIPES)}]`.")
main = data['defis']['mains'][equipe]
for _i in range(nb_defis):
nouveau_defi = random.choice([defi for defi in DEFIS['capture'] if defi['id'] not in data['defis']['tires_capture']])
main.append(nouveau_defi['id'])
data['defis']['tires_capture'].append(nouveau_defi['id'])
with DATA_FILE.open('w') as data_file:
json.dump(data, data_file, indent=2)
await ctx.send(f"Main de l'équipe {equipe} mélangée !")
for member_id in data['equipes'][equipe]:
await afficher_main(ctx, author_id=member_id)
async def de(ctx: commands.Context, nb_faces: int = 6):
resultat = random.randint(1, nb_faces + 1)
await ctx.reply(f":dice: Résultat du dé à {nb_faces} faces : **{resultat}**")
@bot.command()
async def debug(ctx: commands.Context, keys: str, *, set_value: str | None = None):
keys = keys.split('.')
parent = None
out = data
for key in keys:
if key not in out:
raise commands.BadArgument(f"Clé {key} absente du dictionnaire, valeurs possibles : {out.keys()}")
parent = out
last_key = key
out = out[key]
data_json = json.dumps(out, indent=2)
if set_value is None:
await ctx.reply(f"```json\n{data_json}\n```", ephemeral=True)
else:
new_data = json.loads(set_value)
new_data_json = json.dumps(new_data, indent=2)
parent[last_key] = new_data
await ctx.reply(f"Anciennes données :\n```json\n{data_json}\n```Nouvelles données :\n```json\n{new_data_json}\n```\nFaites `{PREFIX}save` pour sauvegarder, ou `{PREFIX}` reload pour rollback.", ephemeral=True)
@bot.command()
async def reload(ctx: commands.Context):
global data, DEFIS
with DATA_FILE.open() as data_file:
data = json.load(data_file)
with DEFIS_FILE.open() as defis_file:
DEFIS = json.load(defis_file)
await ctx.reply("Configuration rechargée.", ephemeral=True)
@bot.command()
async def save(ctx: commands.Context):
with DATA_FILE.open('w') as data_file:
json.dump(data, data_file, indent=2)
await ctx.reply("Configuration sauvegardée.", ephemeral=True)
@carte.error
@reset.error
@equipe.error @equipe.error
async def equipe_error(ctx, error): @defis.error
@description.error
@tirage.error
@afficher_main.error
@terminer.error
@echange.error
@melanger.error
@debug.error
@reload.error
@save.error
async def on_error(ctx, error):
with DATA_FILE.open() as data_file:
data = json.load(data_file)
await ctx.send(str(error)) await ctx.send(str(error))
if not isinstance(error, commands.BadArgument):
raise error
bot.run(DISCORD_TOKEN) bot.run(DISCORD_TOKEN)