Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
2.3 [BOT_PRESENTATION](#bot_presentation)
- 2.2.2 [Utilisation](#utilisation--1)

2.4 [CONFIGURATION DES COMMANDES](#configuration-des-commandes)

3. [INSTALLER ET CONFIGURER LE PROJET EN ENTIER](#installer-et-configurer-le-projet-en-entier)
- 3.1 [Prérequis](#prérequis-)
- 3.2 [Démarche](#démarche-)
Expand Down Expand Up @@ -91,6 +93,22 @@ En message privé, il reçoit un lien web vers un formulaire figurant des questi
3. Une fois publique, la présentation est encore modifiable ; il suffit d'y répondre sur discord avec la commande **$edit**.


---
## Configuration des commandes
Certaines commandes nécessitent un salon Discord au nom précis, muni d'un webhook, ainsi que des permissions particulières pour le bot. Sans cette configuration, la commande échoue avec un message d'erreur explicite dans le salon ou en MP.

| Commande | Salon requis | Configurable dans | Permission Discord nécessaire |
|---|---|---|---|
| **$jdr**, **$edit** (annonces de partie) | Un salon nommé exactement `planning-jdr`, muni d'au moins un webhook | `Bot_Planning_python/src/cog_planning/settings.py` (`announcement_channel`) | *Gérer les webhooks* sur ce salon |
| **$prez** | Un salon nommé exactement `presentation`, muni d'au moins un webhook | `Bot_Presentation/src/cog_presentation/settings.py` (`announcement_channel`) | *Gérer les webhooks* sur ce salon |
| **$cal**, **$site** | Aucun (le bot envoie un lien fixe en MP) | URLs `calendar_url`/`site_url` dans `cog_planning/settings.py` | Aucune |
| Toutes | — | — | *Gérer les messages* recommandée : sans elle, les messages temporaires (confirmations envoyées dans le salon) ne s'autodétruisent plus après quelques secondes, mais les commandes continuent de fonctionner normalement |

Le nom du salon attendu (`announcement_channel`) est fixé dans le code : créez un salon portant exactement ce nom, ou modifiez la valeur dans le `settings.py` correspondant avant de builder l'image.

Voir aussi la section [Démarche](#démarche-) ci-dessous pour la liste complète des permissions à accorder au bot lors de son invitation sur un serveur.


---
---
## Installer et configurer le projet en entier
Expand Down
18 changes: 10 additions & 8 deletions src/bot/cog_about.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,18 @@ async def send_info_msg(self, ctx, with_credits=False):
# generates the descriptions for all the subservices of the bot
services = "\n\n".join(
formatted_template(templates, 'service_template.txt',
name=cog.get_name(),
version=cog.get_version(),
credits=cog.get_credits() if with_credits else "")
name=colorize(cog.get_name(), HEADING_COLOR),
version=colorize(cog.get_version(), COMMAND_COLOR),
credits=colorize(cog.get_credits(), DESCRIPTION_COLOR) if with_credits else "")

for name, cog in self.bot.cogs.items() if isinstance(cog, MyCog)
)

# sends the message
await ctx.send(code_block(formatted_template(templates, 'version_template.txt',
version=self.bot.get_version(),
name=self.bot.get_name(),
# sends the message. Les titres sont colores+soulignes via ANSI (HEADING_COLOR inclut
# deja le code de soulignement) plutot que via des '====='/'-----' litteraux : les
# templates ne calculent donc plus de longueur de soulignement a partir de ces lignes.
await ctx.send(ansi_block(formatted_template(templates, 'version_template.txt',
version=colorize(self.bot.get_version(), COMMAND_COLOR),
name=colorize(self.bot.get_name(), HEADING_COLOR),
services=services,
credits=self.bot.get_credits() if with_credits else "")))
credits=colorize(self.bot.get_credits(), DESCRIPTION_COLOR) if with_credits else "")))
7 changes: 5 additions & 2 deletions src/bot/cog_general.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from discord.ext import commands
from Bot_Base.src.urpy.localization import Localization
from Bot_Base.src.urpy.my_commands import MyBot
from Bot_Base.src.urpy.utils import colored_message, SUCCESS_COLOR, ERROR_COLOR
import strings

# UR_Bot © 2020 by "Association Union des Rôlistes & co" is licensed under Attribution-NonCommercial-ShareAlike 4.0
Expand Down Expand Up @@ -52,9 +53,11 @@ async def cancel(self, ctx):
async def lang(self, ctx: commands.Context, language):
"""Switches to specified language"""
if self.localization.set_user_language(ctx.author.id):
await ctx.send(_("Your language has successfully been set to {language}!").format(language=language))
await ctx.send(colored_message(
_("Your language has successfully been set to {language}!").format(language=language),
SUCCESS_COLOR))
else:
await ctx.send(_("Sorry, I don't know this language!"))
await ctx.send(colored_message(_("Sorry, I don't know this language!"), ERROR_COLOR))

def add_to_command(self, command: str, *callbacks):
"""Adds a callback to the specified command. It will be called on command invocation."""
Expand Down
3 changes: 2 additions & 1 deletion src/bot/info/credits.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
Lyss <delpratflo@cy-tech.fr>
Maestro#8364 <yoyou20@hotmail.fr>
Maestro#8364 <yoyou20@hotmail.fr>
Mortifia
1 change: 0 additions & 1 deletion src/bot/templates/service_template.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
{name}
------
-> version : {version}
{credits}
1 change: 0 additions & 1 deletion src/bot/templates/version_template.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
{name}
======
-> Version : {version}
{credits}

Expand Down
28 changes: 19 additions & 9 deletions src/urpy/help.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
# Ask a derogation at Contact.unionrolistes@gmail.com

from Bot_Base.src.urpy.localization import lcl
from Bot_Base.src.urpy.utils import HEADING_COLOR, COMMAND_COLOR, DESCRIPTION_COLOR, RESET_COLOR

_ = lcl

Expand All @@ -15,7 +16,9 @@ def __init__(self, localization, **options):
super().__init__(
help=lcl('Shows this message'),
commands_heading=lcl('Commands:'),
no_category=lcl('No Category'), **options) # TODO 'No Category' in french
no_category=lcl('No Category'), # TODO 'No Category' in french
paginator=commands.Paginator(prefix='```ansi', suffix='```'),
**options)
global _
# This check is necessary cause HelpCommand is deeply copied every time in discord api. """
if _ is lcl:
Expand All @@ -31,25 +34,27 @@ def add_command_formatting(self, command):
"""

if command.description:
self.paginator.add_line(_(command.description), empty=True)
self.paginator.add_line(f'{DESCRIPTION_COLOR}{_(command.description)}{RESET_COLOR}', empty=True)

signature = self.get_command_signature(command)
self.paginator.add_line(signature, empty=True)
self.paginator.add_line(f'{COMMAND_COLOR}{signature}{RESET_COLOR}', empty=True)
# 'domain = getattr(command.cog, 'domain', None)' ; la variable n'est jamais utilisée. À laisser au cas où ça
# servirait un futur développeur.
if command.help:
try:
self.paginator.add_line(_(command.help), empty=True)
self.paginator.add_line(f'{DESCRIPTION_COLOR}{_(command.help)}{RESET_COLOR}', empty=True)
except RuntimeError:
self.paginator.add_line(DESCRIPTION_COLOR)
for line in command.help.splitlines():
self.paginator.add_line(line) # TODO localization here
self.paginator.add_line()
self.paginator.add_line(RESET_COLOR)

def get_ending_note(self):
""":class:`str`: Returns help command's ending note. This is mainly useful to override for i18n purposes."""
command_name = self.invoked_with
return _(f"Type {self.clean_prefix}{command_name} command for more info on a command.\n"
note = _(f"Type {self.clean_prefix}{command_name} command for more info on a command.\n"
f"You can also type {self.clean_prefix}{command_name} category for more info on a category.")
return f'{DESCRIPTION_COLOR}{note}{RESET_COLOR}'
# Une erreur se produit sur 'self.clean_prefix'.
# En effet, l'IDE demande la création de cette méthode dans la classe.

Expand All @@ -58,7 +63,7 @@ def add_indented_commands(self, instructions, *, heading, max_size=None):
return
if heading.startswith('\u200b'):
heading = _(heading[1:-1]) + ':'
self.paginator.add_line(_(heading[:-1]) + heading[-1])
self.paginator.add_line(f'{HEADING_COLOR}{_(heading[:-1])}{RESET_COLOR}{heading[-1]}')
max_size = max_size or self.get_max_size(instructions)

get_width = discord.utils._string_width # Erreur : 'Access to a protected member _string_width of a module'.
Expand All @@ -67,14 +72,19 @@ def add_indented_commands(self, instructions, *, heading, max_size=None):
# servirait un futur développeur.
name = command.name
width = max_size - (get_width(name) - len(name))
entry = '{0}{1:<{width}} {2}'.format(self.indent * ' ', name, _(command.short_doc), width=width)
# le padding se calcule sur le nom brut : les codes ANSI ajoutes ensuite ne comptent pas
# dans la largeur visible, mais fausseraient l'alignement s'ils etaient inclus dans le format.
padded_name = '{0:<{width}}'.format(name, width=width)
entry = '{0}{1}{2}{3} {4}{5}{6}'.format(
self.indent * ' ', COMMAND_COLOR, padded_name, RESET_COLOR,
DESCRIPTION_COLOR, _(command.short_doc), RESET_COLOR)
self.paginator.add_line(self.shorten_text(entry))

async def send_cog_help(self, cog):
# 'domain = getattr(cog, 'domain', None)' ; la variable n'est jamais utilisée. À laisser au cas où ça
# servirait un futur développeur.
if cog.description:
self.paginator.add_line(_(cog.description), empty=True)
self.paginator.add_line(f'{DESCRIPTION_COLOR}{_(cog.description)}{RESET_COLOR}', empty=True)
filtered = await self.filter_commands(cog.get_commands(), sort=self.sort_commands)
self.add_indented_commands(filtered, heading=_(self.commands_heading))

Expand Down
35 changes: 34 additions & 1 deletion src/urpy/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,32 @@ async def get_informations(msg: discord.Message):
return infos


# Couleurs "dim" (2;3x) rendues par le client Discord dans un code block ```ansi.
HEADING_COLOR = '\x1b[2;34;4m' # bleu, souligne
COMMAND_COLOR = '\x1b[2;33m' # jaune
DESCRIPTION_COLOR = '\x1b[2;36m' # cyan
SUCCESS_COLOR = '\x1b[2;32m' # vert
ERROR_COLOR = '\x1b[2;31m' # rouge
RESET_COLOR = '\x1b[0m'


def code_block(s):
return f"```{s}```"


def ansi_block(s):
return f"```ansi\n{s}```"


def colorize(s, color=DESCRIPTION_COLOR):
return f'{color}{s}{RESET_COLOR}'


def colored_message(s, color=SUCCESS_COLOR):
"""Wraps a plain bot message in a colored ```ansi code block."""
return ansi_block(colorize(s, color))


def edit_fmt(s):
return f"\\|~ {s} ~|"

Expand Down Expand Up @@ -90,7 +112,18 @@ def formatted_template(template_pckg, template_name, **kwargs):
if match.group(4):
new_line += match.group(4)[0] * size_last_line
# formats text that doesn't symbolize an underline
new_line += match.group(5).format(**kwargs)
formatted = match.group(5).format(**kwargs)
# une valeur substituee (ex: credits multi-auteurs) peut contenir plusieurs
# lignes ; sans reappliquer l'indentation de la ligne du template a chacune
# d'elles, seule la premiere serait indentee. Le saut de ligne final de la
# ligne elle-meme (pas celui d'une valeur substituee) est laisse de cote pour
# ne pas indenter ce qui suit sur la ligne suivante du template.
indent = match.group(1)
if '\n' in formatted:
has_trailing_newline = formatted.endswith('\n')
body = formatted[:-1] if has_trailing_newline else formatted
formatted = body.replace('\n', '\n' + indent) + ('\n' if has_trailing_newline else '')
new_line += formatted

size_last_line = len(new_line.strip())

Expand Down
Loading