Code source de lgrez.features.annexe

"""lg-rez / features / Commandes annexes

Commandes diverses qu'on ne savait pas où ranger

"""

import random
import requests
import traceback
import datetime
import asyncio

from discord.ext import commands
from akinator.async_aki import Akinator
import akinator

from lgrez.blocs import tools
from lgrez.blocs.bdd import session, Joueurs


[docs]class Annexe(commands.Cog): """Annexe - Commandes annexes aux usages divers""" @commands.command() async def roll(self, ctx, *, XdY): """Lance un ou plusieurs dés Args: XdY: dés à lancer + modifieurs, au format ``XdY + XdY + ... + Z - Z ...`` avec X le nombre de dés, Y le nombre de faces et Z les modifieurs (constants). Examples: - ``!roll 1d6`` -> lance un dé à 6 faces - ``!roll 1d20 +3`` -> lance un dé à 20 faces, ajoute 3 au résultat - ``!roll 1d20 + 2d6 -8`` -> lance un dé 20 plus deux dés 6, enlève 8 au résultat """ dices = XdY.replace(' ', '').replace('-', '+-').split('+') # "1d6 + 5 - 2" -> ["1d6", "5", "-2"] r = "" s = 0 try: for dice in dices: if 'd' in dice: nb, faces = dice.split('d', maxsplit=1) for i in range(int(nb)): v = random.randrange(int(faces)) + 1 s += v r += f" + {v}{tools.sub_chiffre(int(faces), True)}₎" else: v = int(dice) s += v r += f" {'-' if v < 0 else '+'} {abs(v)}" r += f" = {tools.emoji_chiffre(s, True)}" except Exception: await ctx.send(f"Pattern non reconu. Utilisez {tools.code('!help roll')} pour plus d'informations.") else: await tools.send_blocs(ctx, r[3:]) @commands.command(aliases=["cf", "pf"]) async def coinflip(self, ctx): """Renvoie le résultat d'un tirage à Pile ou Face (aléatoire) Pile je gagne, face tu perds. """ await ctx.send(random.choice(["Pile", "Face"])) @commands.command(aliases=["pong"]) async def ping(self, ctx): """Envoie un ping au bot Pong """ ts_rec = datetime.datetime.utcnow() delta_rec = ts_rec - ctx.message.created_at # Temps de réception = temps entre création message et sa réception pingpong = ctx.invoked_with.replace("i", "x").replace("I", "X").replace("o", "i").replace("O", "I").replace("x", "o").replace("X", "O") cont = ( f" Réception : {delta_rec.total_seconds()*1000:4.0f} ms\n" f" Latence : {ctx.bot.latency*1000:4.0f} ms\n" ) mess = await ctx.send(f"!{pingpong}\n" + tools.code_bloc(cont + " (...)")) ts_ret = datetime.datetime.utcnow() delta_ret = ts_ret - mess.created_at # Retour information message réponse créé delta_env = ts_ret - ts_rec - delta_ret # Temps d'envoi = temps entre réception 1er message (traitement quasi instantané) et création 2e, moins temps de retour d'information delta_tot = delta_rec + delta_ret + delta_env # Total = temps entre création message !pong et réception information réponse envoyée await mess.edit(content=f"!{pingpong}\n" + tools.code_bloc(cont + f" Envoi : {delta_env.total_seconds()*1000:4.0f} ms\n" f" Retour : {delta_ret.total_seconds()*1000:4.0f} ms\n" f"——————————————————————\n" f" Total : {delta_tot.total_seconds()*1000:4.0f} ms" )) @commands.command() @tools.mjs_only async def addhere(self, ctx, *joueurs): """Ajoute les membres au chan courant (COMMANDE MJ) Args: *joueurs: membres à ajouter, chacun entouré par des guillemets si nom + prénom Si ``*joueurs`` est un seul élément, il peut être de la forme ``<crit>=<filtre>`` tel que décrit dans l'aide de ``!send``. """ ts_debut = ctx.message.created_at - datetime.timedelta(microseconds=1) if len(joueurs) == 1 and "=" in joueurs[0]: # Si critère : on remplace joueurs crit, filtre = joueurs[0].split("=", maxsplit=1) if hasattr(Joueurs, crit): joueurs = Joueurs.query.filter(getattr(Joueurs, crit) == filtre).all() else: await ctx.send(f"Critère \"{crit}\" incorrect. !help {ctx.invoked_with} pour plus d'infos.") return else: # Sinon, si noms / mentions joueurs = [await tools.boucle_query_joueur(ctx, cible) for cible in joueurs] for joueur in joueurs: member = ctx.guild.get_member(joueur.discord_id) assert member, f"Member {joueur} introuvable" await ctx.channel.set_permissions(member, read_messages=True, send_messages=True) await ctx.send(f"{joueur.nom} ajouté") mess = await ctx.send("Fini, purge les messages ?") if await tools.yes_no(ctx.bot, mess): await ctx.channel.purge(after=ts_debut) @commands.command() @tools.mjs_only async def purge(self, ctx, N=None): """Supprime tous les messages de ce chan (COMMANDE MJ) Args: N: nombre de messages à supprimer (défaut : tous) """ if N: mess = await ctx.send(f"Supprimer les {N} messages les plus récents de ce chan ? (celui-ci inclus)") else: mess = await ctx.send(f"Supprimer tous les messages de ce chan ?") if await tools.yes_no(ctx.bot, mess): await ctx.channel.purge(limit=int(N) if N else None) @commands.command() async def akinator(self, ctx): """J'ai glissé chef Implémentation directe de https://pypi.org/project/akinator.py """ # Un jour mettre ça dans des embeds avec les https://fr.akinator.com/bundles/elokencesite/images/akitudes_670x1096/<akitude>.png croppées, <akitude> in ["defi", "serein", "inspiration_legere", "inspiration_forte", "confiant", "mobile", "leger_decouragement", "vrai_decouragement", "deception", "triomphe"] await ctx.send(f"Vous avez demandé à être mis en relation avec {tools.ital('Akinator : Le Génie du web')}.\nVeuillez patienter...") async with ctx.typing(): # Connection aki = Akinator() question = await aki.start_game(language="fr") exit = False while not exit and aki.progression <= 80: mess = await ctx.send(f"({aki.step + 1}) {question}") reponse = await tools.wait_for_react_clic(ctx.bot, mess, {"👍":"yes", "🤷":"idk", "👎":"no", "⏭️":"stop"}) if reponse == "stop": exit = True else: async with ctx.typing(): question = await aki.answer(reponse) async with ctx.typing(): await aki.win() mess = await ctx.send(f"Tu penses à {tools.bold(aki.first_guess['name'])} ({tools.ital(aki.first_guess['description'])}) !\nJ'ai bon ?\n{aki.first_guess['absolute_picture_path']}") if await tools.yes_no(ctx.bot, mess): await ctx.send("Yay\nhttps://fr.akinator.com/bundles/elokencesite/images/akitudes_670x1096/triomphe.png") else: await ctx.send("Oof\nhttps://fr.akinator.com/bundles/elokencesite/images/akitudes_670x1096/deception.png") @commands.command() async def xkcd(self, ctx, N): """J'ai aussi glissé chef, mais un peu moins Args: N: numéro du comic """ async with ctx.typing(): r = requests.get(f"https://xkcd.com/{N}/info.0.json") if not r: await ctx.send("Paramètre incorrect ou service non accessible.") return url = r.json().get("img") if not url: await ctx.send("Paramètre incorrect ou service non accessible.") return await ctx.send(url)