Nice help !

This commit is contained in:
ddorn 2020-04-27 12:28:30 +02:00
parent b24921d8ba
commit 823587b163
4 changed files with 193 additions and 66 deletions

View File

@ -4,3 +4,4 @@ of the TFJM² bot.
"""
from .tirages import TirageCog
from .help import TfjmHelpCommand

86
src/cogs/help.py Normal file
View File

@ -0,0 +1,86 @@
from discord.ext.commands import MinimalHelpCommand
# This is mostly a copy paste of MinimalHelpCommand
# With updated defaults and styles to match what I like
class TfjmHelpCommand(MinimalHelpCommand):
def __init__(self, **options):
options.setdefault("no_category", "Autres")
super().__init__(**options)
def get_opening_note(self):
"""Text at the beginning of the help command."""
command_name = self.invoked_with
return (
"`{0}{1} [commande]` permet d'avoir plus d'info sur une commande.\n"
"Vous pouvez aussi utiliser `{0}{1} [catégorie]` "
"pour plus d'infos sur une catégorie.".format(
self.clean_prefix, command_name
)
)
def get_command_signature(self, command):
return "`%s`" % super().get_command_signature(command)
def add_bot_commands_formatting(self, commands, heading):
"""Adds the minified bot heading with commands to the output.
The formatting should be added to the :attr:`paginator`.
The default implementation is a bold underline heading followed
by commands separated by an EN SPACE (U+2002) in the next line.
Parameters
-----------
commands: Sequence[:class:`Command`]
A list of commands that belong to the heading.
heading: :class:`str`
The heading to add to the line.
"""
if commands:
# U+2002 Middle Dot
self.paginator.add_line("__**%s**__" % heading)
for c in commands:
self.add_subcommand_formatting(c)
self.paginator.add_line()
def add_subcommand_formatting(self, command):
"""Adds formatting information on a subcommand.
The formatting should be added to the :attr:`paginator`.
The default implementation is the prefix and the :attr:`Command.qualified_name`
optionally followed by an En dash and the command's :attr:`Command.short_doc`.
Parameters
-----------
command: :class:`Command`
The command to show information of.
"""
fmt = "`{0}{1}` \N{EN DASH} {2}" if command.short_doc else "`{0}{1}`"
self.paginator.add_line(
fmt.format(self.clean_prefix, command.qualified_name, command.short_doc)
)
def add_aliases_formatting(self, aliases):
"""Adds the formatting information on a command's aliases.
The formatting should be added to the :attr:`paginator`.
The default implementation is the :attr:`aliases_heading` bolded
followed by a comma separated list of aliases.
This is not called if there are no aliases to format.
Parameters
-----------
aliases: Sequence[:class:`str`]
A list of aliases to format.
"""
aliases_str = ", ".join("`%s`" % a for a in aliases)
self.paginator.add_line(
"**%s** %s" % (self.aliases_heading, aliases_str), empty=True
)

View File

@ -530,11 +530,78 @@ class TirageCog(Cog, name="Tirages"):
self.tirages = tirages
# ---------- Commandes hors du groupe draw ----------- #
@commands.command(
name="dice", aliases=["de", "", "roll"], usage="n",
)
async def dice(self, ctx: Context, n: int):
"""Lance un dé à `n` faces."""
channel = ctx.channel.id
if channel in self.tirages:
await self.tirages[channel].dice(ctx, n)
else:
if n < 1:
raise TfjmError(f"Je ne peux pas lancer un dé à {n} faces, désolé.")
dice = random.randint(1, n)
await ctx.send(
f"Le dé à {n} face{'s' * (n > 1)} s'est arrêté sur... **{dice}**"
)
@commands.command(
name="random-problem",
aliases=["rp", "problème-aléatoire", "probleme-aleatoire", "pa"],
)
async def random_problem(self, ctx: Context):
"""Choisit un problème parmi ceux de cette année."""
channel = ctx.channel.id
if channel in self.tirages:
await self.tirages[channel].choose_problem(ctx)
else:
problem = random.choice(PROBLEMS)
await ctx.send(f"Le problème tiré est... **{problem}**")
@commands.command(
name="oui", aliases=["accept", "yes", "o", "accepte", "ouiiiiiii"],
)
async def accept_cmd(self, ctx):
"""
Accepte le problème qui vient d'être tiré.
Sans effet si il n'y a pas de tirage en cours.
"""
channel = ctx.channel.id
if channel in self.tirages:
await self.tirages[channel].accept(ctx, True)
else:
await ctx.send(f"{ctx.author.mention} approuve avec vigeur !")
@commands.command(
name="non", aliases=["refuse", "no", "n", "nope", "jaaamais"],
)
async def refuse_cmd(self, ctx):
"""
Refuse le problème qui vient d'être tiré.
Sans effet si il n'y a pas de tirage en cours.
"""
channel = ctx.channel.id
if channel in self.tirages:
await self.tirages[channel].accept(ctx, False)
else:
await ctx.send(f"{ctx.author.mention} nie tout en block !")
# ---------- Commandes du groupe draw ----------- #
@group(
name="draw", aliases=["d", "tirage"],
)
async def draw_group(self, ctx: Context) -> None:
"""Commandes pour les tirages."""
"""Groupe de commandes pour les tirages."""
@draw_group.command(
name="start", usage="équipe1 équipe2 équipe3 (équipe4)",
@ -596,6 +663,13 @@ class TirageCog(Cog, name="Tirages"):
)
@commands.has_role(ORGA_ROLE)
async def abort_draw_cmd(self, ctx):
"""
Annule le tirage en cours.
Le tirage ne pourra pas être continué. Si besoin,
n'hésitez pas à appeller un @dev : il peut réparer
plus de choses qu'on imagine (mais moins qu'on voudrait).
"""
channel_id = ctx.channel.id
if channel_id in self.tirages:
await self.tirages[channel_id].end(ctx)
@ -604,6 +678,7 @@ class TirageCog(Cog, name="Tirages"):
@draw_group.command(name="skip", aliases=["s"])
@commands.has_role(CNO_ROLE)
async def draw_skip(self, ctx, *teams):
"""Skip certaines phases du tirage."""
channel = ctx.channel.id
self.tirages[channel] = tirage = Tirage(ctx, channel, teams)
@ -620,7 +695,15 @@ class TirageCog(Cog, name="Tirages"):
await tirage.update_phase(ctx)
@draw_group.command(name="show")
async def show_cmd(self, ctx: Context, arg: str):
async def show_cmd(self, ctx: Context, tirage_id: str):
"""
Affiche le résumé d'un tirage
Les ID de tirages valides sont visibles avec
`!draw show all` et les details avec `!draw show 42`
(si l'ID qui vous intéresse est 42).
"""
if not TIRAGES_FILE.exists():
await ctx.send("Il n'y a pas encore eu de tirages.")
return
@ -628,7 +711,7 @@ class TirageCog(Cog, name="Tirages"):
with open(TIRAGES_FILE) as f:
tirages = list(yaml.load_all(f))
if arg.lower() == "all":
if tirage_id.lower() == "all":
msg = "\n".join(
f"{i}: {', '.join(team.name for team in tirage.teams)}"
for i, tirage in enumerate(tirages)
@ -640,13 +723,13 @@ class TirageCog(Cog, name="Tirages"):
await ctx.send(msg)
else:
try:
n = int(arg)
n = int(tirage_id)
if n < 0:
raise ValueError
tirage = tirages[n]
except (ValueError, IndexError):
await ctx.send(
f"`{arg}` n'est pas un identifiant valide. "
f"`{tirage_id}` n'est pas un identifiant valide. "
f"Les identifiants valides sont visibles avec `!show all`"
)
else:

View File

@ -9,10 +9,11 @@ import discord
from discord.ext import commands
from discord.ext.commands import Context
from src.cogs import TfjmHelpCommand
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=TfjmHelpCommand())
# Variable globale qui contient les tirages.
tirages = {}
@ -23,78 +24,34 @@ async def on_ready():
print(f"{bot.user} has connected to Discord!")
@bot.command(
name="dice",
help="Lance un dé à `n` faces. ",
aliases=["de", "", "roll"],
usage="n",
)
async def dice(ctx: Context, n: int):
channel = ctx.channel.id
if channel in tirages:
await tirages[channel].dice(ctx, n)
else:
if n < 1:
raise TfjmError(f"Je ne peux pas lancer un dé à {n} faces, désolé.")
dice = random.randint(1, n)
await ctx.send(f"Le dé à {n} face{'s'*(n>1)} s'est arrêté sur... **{dice}**")
@bot.command(
name="choose",
help="Choisit une option parmi tous les arguments.",
usage="choix1 choix2...",
usage='choix1 choix2 "choix 3"...',
aliases=["choice", "choix", "ch"],
)
async def choose(ctx: Context, *args):
"""
Choisit une option parmi tous les arguments.
Pour les options qui contiennent une espace,
il suffit de mettre des guillemets (`"`) autour.
"""
choice = random.choice(args)
await ctx.send(f"J'ai choisi... **{choice}**")
@bot.command(
name="random-problem",
help="Choisit un problème parmi ceux de cette année.",
aliases=["rp", "problème-aléatoire", "probleme-aleatoire", "pa"],
)
async def random_problem(ctx: Context):
channel = ctx.channel.id
if channel in tirages:
await tirages[channel].choose_problem(ctx)
else:
problem = random.choice(PROBLEMS)
await ctx.send(f"Le problème tiré est... **{problem}**")
@bot.command(
name="accept",
help="Accepte le problème qui vient d'être tiré. \n Ne fonctionne que lors d'un tirage.",
aliases=["oui", "yes", "o", "accepte", "ouiiiiiii"],
)
async def accept_cmd(ctx):
channel = ctx.channel.id
if channel in tirages:
await tirages[channel].accept(ctx, True)
else:
await ctx.send(f"{ctx.author.mention} approuve avec vigeur !")
@bot.command(
name="refuse",
help="Refuse le problème qui vient d'être tiré. \n Ne fonctionne que lors d'un tirage.",
aliases=["non", "no", "n", "nope", "jaaamais"],
)
async def refuse_cmd(ctx):
channel = ctx.channel.id
if channel in tirages:
await tirages[channel].accept(ctx, False)
else:
await ctx.send(f"{ctx.author.mention} nie tout en block !")
@bot.command(name="interrupt")
@commands.has_role(CNO_ROLE)
async def interrupt_cmd(ctx):
"""
:warning: Ouvre une console un @dev m'a lancé. :warning:
A utiliser en dernier recours:
- le bot sera inactif pendant ce temps.
- toutes les commandes seront executées à sa reprise.
"""
await ctx.send(
"J'ai été arrêté et une console interactive a été ouverte là où je tourne. "
"Toutes les commandes rateront tant que cette console est ouverte.\n"