Tutorial Piscord¶
Introduction¶
Que permet piscord ?¶
Piscord permet, au même titre que Discord.py, de faire des bots discord. Seulement, l’avantage est que Piscord simplifie la création de bots sur plusieurs points.
Tout d’abord, la programmation avec Piscord est synchrone, ce qui en simplifie l’utilisation, surtout par des personnes pas forcément expertes en python
Ensuite, la librairie n’est pas forcément bloquante. Cela permet de faire plusieurs bots en un script, de lancer un serveur web en même temps.. A peu près ce que l’on veut.
Enfin, nous essayons de faire que ce soit le plus simple possible de faire un dialogue avec le web. Il y a notamment une classe (OAuth) qui est la pour permettre d’utiliser la connexion avec discord facilement en faisant un site, et d’exploiter ces données comme un bot le ferais.
Quels sont les prérequis pour l’utiliser ?¶
Les prérequis demandés pour utiliser piscord sont simples
- Savoir lire une doc (ce que vous êtes en train de faire)
- Connaitres les bases (variables, boucles, comparaison, fonctions)
- Savoir utiliser des classes
- Savoir débugguer
De plus, connaitre les décorateurs est utile mais pas indispensable vu qu’ils sont utilisés partout mais l’on ne s’attarde pas sur leur fonctionnement.
Comment installer piscord ?¶
Pour installer la librairie, cela est très simple, il suffit de l’installer avec pip, (pip install -U piscord). Cela va installer les dépendances de cette dernière, pour vous permettre de l’utiliser directement après.
Ensuite, dans votre code python, utilisez import piscord, from piscord import * ou from piscord import things selon comment vous voulez l’utiliser.
First Bot¶
Mettre en ligne le bot¶
Pour mettre en ligne votre premier bot, récupérez le token de ce dernier et faites comme ceci :
from piscord import Bot
# Import de la classe Bot a partir de la librairie
bot = Bot("Token")
# Création d'un Bot avec votre token
@bot.event
def on_ready(ready):
print(f"Bot {ready.user.name} Connected")
# Créer un event correpondant à celui de "on_ready" (quand le bot est connecté a discord), et dire que le bot est lancé.
bot.run()
# Lancer le bot en mode bloquant
Information :¶
Vous avez deux façons de créer un event : - En utilisant @bot.event et en renommant la fonction du nom de l’event - En utilisant @bot.event(“nom_de_l_event”) et en renommant la fonction comme vous le souhaitez
Ce qui donne ça :
@bot.event
def on_ready(ready):...
ou
@bot.event("on_ready")
def ready(ready):...
Aussi, vous pouvez lancer le bot en mode bloquant (le code après ne sera pas exécuté) ou non bloquant.
bot.run()
# Manière bloquante, a utiliser si l'on ne compte rien faire en même temps que lancer le bot.
bot.start()
# Manière non bloquante, si on lance d'autres bots après, ou un serveur web en parallèle.
Ping Pong¶
Une manière souvent utilisé pour illustrer la création d’un pemier bot est une commande (“ping”) qui fera répondre une autre (“pong”) au bot. Voyons comment le faire avec Piscord :
from piscord import Bot
bot = Bot("Token")
@bot.event
def on_ready(ready):
print(f"Bot {ready.user.name} Connected")
@bot.event
def on_message(message):
if message.content == "!ping":
message.channel.send("Pong !")
# Quand un message est envoyé, on vérifie si son contenu est "!ping".
# Si c'est le cas, on envoi dans le salon le message "Pong !"
bot.run()
Objet Message¶
Quand on déclare un event, on récupère en argument un objet Event nous permettant de récupérer des informations de ce dernier.
Pour les voir je vous invite a aller consulter [La Documentation au sujet des Messages](https://piscord.astremy.com/#Message). Sinon, voyons ensemble les plus utiles :
Message.content
# Le contenu du message, ce qu'à saisi l'utilisateur. Cela permet d'identifier des éventuels commandes, gros mots...
# C'est le message en lui-même (une chaine de caractères).
Message.author
# L'auteur du message. Un objet User se rapportant à l'utilsateur qui a éxécuté la commande,
# permettant d'avoir diverses informations sur lui (pseudo, id..)
Message.channel
# Le salon dans lequel a été envoyé le message. Permet d'y renvoyer un message,
# Ou de récupérer des informations sur le salon.
Message.guild
# Le serveur dans lequel a été envoyé le message.
# Permet d'en récupérer des informations.
Un bot basique¶
Voici un exemple un peu plus développé de l’utilisation de l’argument (je ne montre pas tout le code, seulement la partie event) :
@bot.event
def on_message(message):
if message.content == "!infos":
if message.guild:
server = message.guild.name
else:
server = "Aucun, nous sommes en messages privés"
message.channel.send(f"Informations :\nUtilisateur : {message.author}\nServeur : {server}")
Envoyer des messages¶
Pour envoyer un message, il y a deux façons de s’y prendre
channel.send(message)
# Façon largement préférée, facile d'utilisation et simple à comprendre.
bot.send_message(channel_id, message)
# Ancienne forme, dépréciée, a utiliser le moins possible, sauf dans des cas très précis.
Dans ce tutoriel, on s’attardera sur la première forme.
Le premier argument de channel.send() est le contenu (content) du message. Il n’est pas obligé d’être spécifié en tant que kwarg (sous forme Channel.send(content = “contenu”)) mais peut simplement être mis directement Channel.send(“contenu”).
Cependant, pour le reste des arguments, il faut spécifier le nom.
Arguments¶
Il y a différents arguments que l’on peut mettre dans le send :
- tts : Une valeur True ou False, si le message envoyé est un text-to-speech.
- files : Une liste des nom de fichiers que l’on souhaite envoyer (si l’on en envoie).
- embed : Un embed, nous verrons plus loin comment en faire.
- allowed_mentions : Un objet Allowed_Mentions, nous verrons également comment le faire plus loin.
### Allowed_Mentions
Les mentions autorisés permettent d’empêcher que le bot mentionne par mégarde quelque-chose qu’il ne devrait pas (ex : mentionner everyone parce qu’il a les perms et qu’un malin lui fait répéter une mention qu’il ne peut pas utiliser).
Il a plusieurs paramètres : Parse : Parse est essentiel quand on joue avec la classe. Elle indique les types de mentions a autoriser, même si on doit les détailler après. C’est une liste qui peut prendre les arguments que l’on veut selon ce que l’on souhaite faire.
- “everyone” : Autorise les mentions d’@everyone et @here
- “users” : Permet de mentionner les utilisateurs.
- “roles” : Permet de mentionner les rôles.
Ainsi, par exemple, vous pouvez faire :
Allowed_Mentions.parse = []
# Supprime toutes les mentions
Allowed_Mentions.parse = ["everyone"]
# Ne permet au bot de mentionner seulement everyone/here (s'il en as les permissions)
Users : Users est un paramètre de la classe qui, si on ne permet pas de mentionner tous les utilisateurs (en mettant “users”), permet de quand même en mentionner, mais en précisant les id des utilisateurs a laisser (avec un maximum de 100).
Roles : Roles est comme Users, mais pour les rôles. Si on ne permet pas au bot de mentionner tous les rôles, permet de spécifier l’id des rôles a pouvoir mentionner quand même.
Exemple¶
Voici un exemple de commande que l’on peut faire, ou cela se trouve utile :
@bot.event
def on_message(message):
content = message.content.split()
if content[0] == "!me":
if len(content) > 1:
allow = Allowed_Mentions() # ou Allowed_Mentions({}) selon la version.
allow.parse = []
allow.users = [message.author.id]
message.channel.send(" ".join(content[1:]),allowed_mentions=allow.to_json())
# Envoie le message que l'utilisateur a mis après la commande !me, tout en ne pouvant mentionner que l'auteur de la commande.
Les embeds¶
Les embeds sont quelque chose de très importants par rapport au messages, et mérite que l’on s’y attarde.
Ces derniers ont de nombreuses propriétés, et l’on s’attardera pas sur toutes. Pour plus d’informations, visitez [La Documentation relative aux Embed](https://piscord.astremy.com/#Embed) ou [Les informations de Discord sur les Embed](https://discord.com/developers/docs/resources/channel#embed-object).
Voici les plus utiles :
- title : Une chaine de caractère correspondante au titre de l’Embed.
- description : Le texte dans l’Embed.
- color : La couleur de l’Embed (sous format hexadécimal passé en décimal).
- Image : Un objet image correspondant à une image principale de l’Embed. (Voir la documentation)
De plus, les Embed ont ce que l’on appelle les fields. Ce sont des zones qui contiennent chacun leur titre et texte que l’on met dans un Embed. Pour ajouter un field a un embed, on utilise Embed.add_field(name = name, value = value, inline = inline)
Exemple¶
embed = Embed() # Crée l'embed
embed.title = "Description des commandes" # Défini le titre de l'embed
embed.color = 3375070 # Défini la couleur
embed.add_field(name="!me",value="Commande qui répète du texte, en ne pouvant mentionner que soit-même")
# Le name correspond au titre du field, la value à son contenu. Mettre inline = True permet de faire revenir le bloc a la ligne.
embed.add_field(name="!ping",value="Commande de base qui répond 'Pong !'")
Channel.send(embed=embed.to_json())
Quand l’on envoie un embed dans un channel, il ne faut pas oublier de mettre un .to_json, comme pour le Allowed_Mentions.
Les Permissions¶
Comment fonctionnent les permissions ?¶
Sur discord, il existe plusieurs niveaus de permissions donnant accès
aux utilisateurs à certaines fonctionnalitées.
Par exemple, prennons la permission KICK_MEMBERS donnera le droit
à l’utilisateur de kick un membre du serveur actuel. Mais comment
peut-on par exemple, vérifier les permissions que possède un membre ?
from piscord import Bot, Permission
bot = Bot("Token")
@bot.event
def on_message(message):
everyone = message.guild.roles[0]
# On récupère le rôle @everyone
print(everyone.permissions)
# On affiche dans la console les permissions du rôle
bot.run()
Comme vous pouvez le remarquer si vous testez le bout de code plus haut, on ne reçois dans la console qu’un simple nombre. En fait, ce nombre correspond à la valeur décimal des permissions qui sont exprimées en binaire. Comment cette fois si, vérifier si une personne possède une permission en particulier ? Reprenons le code plus haut :
@bot.event
def on_message(message):
everyone = message.guild.roles[0]
# On récupère le rôle @everyone
if everyone.permissions == Permission.SPEAK:
# On vérifie si la permissions accordée au rôle everyone est bien celle de parler
print("Le rôle everyone peut bien parler dans les channels vocaux")
Exemple d’utilisation¶
Voici un exemple de commande utilisant les permissions, une commande pour kick :
@bot.event
def on_message(message):
mes = message.content.split()
# On récupère le contenu du message, qu'on sépare en liste de mot
if mes[0] == "!kick":
perm = False
for role in message.author.roles:
# On parcourt la liste des rôles du membre
if role.permissions in (Permission.KICK_MEMBERS, Permission.ADMINISTRATORS):
# On vérifie si le rôle en question à les perms pour kick (admin ou kick)
perm = True
break
if perm:
if len(message.mentions):
# On vérifie si un user à été mentionné
member = message.mentions[0]
bot.get_element(message.guild.members, id=member.id).kick()
# On récupère l'objet Member correspondant à la mention et on kick le membre
message.channel.send(f"{message.mentions[0]} has been kicked")
else:
message.channel.send("You have to mentions a member")
else:
message.channel.send("You do not have the permissions")
Quelques opérateurs sur les Permissions¶
Comme vu dans l’exemple précédent, il existe plusieurs opérateur
permettant de faire des vérifications de permissions. Il en existe
actuellement 3. Le +, le -, et le ==.
Reprenons l’exemple plus haut :
if role.permissions == Permission.KICK_MEMBERS + Permission.ADMINISTRATORS:
...
Ici, grâce à l’opérateur + et ==, on peut vérifier si le les
permissions du role voulu sont bien KICK_MEMBERS et
ADMINISTRATORS.
Le dernier opérateur peut être utile dans le cas des Overwrite par
exemple, que nous verrons juste après.
Ainsi, le + rajoute une permission si elle n’existe pas, le -
l’enlève si elle existe, et le == vérifie si le rôle a les permissions.
Aussi, on peut avoir des variantes comme le += qui permet d’ajouter
la permission en la réaffectant. On peut également vérifier si un rôle a une
permissions dans une liste de permissions donné avec le mot clé in.
Par exemple :
if role.permissions in (Permission.KICK_MEMBERS, Permission.ADMINISTRATORS):
...
Ici, on va vérifier si le rôle voulu possède au moins la permission KICK_MEMBERS ou ADMINISTRATORS.
Les Overwrites¶
L’objet Overwrite permet, comme son nom l’indique, de réecrire les
permissions de quelque chose, comme un membre, un rôle, ou un channel.
Nous resterons ici sur le cas des channels.
L’objet Channel possède un attribut permettant de récupérer les
Overwrite de ce channel. Cet attribut est
Channel.permission_overwrite, et il retourne une liste d’un élément,
étant les Overwrite de ce dit channel.
Ainsi, on peut récupérer les permissions que possède le rôle @everyone
d’un channel, et les modifier. Voyons un exemple. Admettons que nous
voulons enlever la permission au rôle @everyone de parler sur un channel
voulu
# Admettons être dans l'event on_message
perms = message.channel.permission_overwrites[0]
# On récupère l'Overwrite du channel
allow = perms.allow - Permission.SEND_MESSAGE
# On définit les permissions autorisées, ici toutes les permissions du channel, en enlevant celle de parler
deny = perms.deny + Permission.SEND_MESSAGE
# On définit les permissions interdites, ici toutes les permissions du channel, en ajoutant celle de parler
perms.edit(allow=allow, deny=deny)
# Enfin, on applique les changement au channel en utilisant la méthode edit de l'objet Overwrite
Ici, dans la variable allow, on peut voir que l’on fait une soustraction de 2 permissions.
Ainsi, on récupère la valeur des permissions du rôle @everyone,
et on y soustrait la permission Permission.SEND_MESSAGES pour enfin appliquer les changements.
Les Commandes¶
Présentation du Handler¶
Par défaut, on crée des commandes avec piscord en détectant un message spécifique, comme !ping ou n’importe quoi du genre. Seulement, il y a un outil pour simplifier la création de commandes : Le Handler. Le Handler est un outil qui va récupérer l’event on_message et l’utiliser pour y trouver la commande que l’on souhaite et la rediriger automatiquement vers la fonction correspondante.
Comment l’utilise-t-on ?¶
from piscord import Handler
bot = Handler("Token","Prefix")
@bot.command
def ping(message):
message.channel.send("Pong !")
bot.run()
Que fait ce bout de code ?
Il crée un bot qui est géré par le Handler, et avec un certain prefix, ce qui va permettre de créer des commandes, ce qu’il fait juste en-dessous avec le @bot.command. Le nom de la fonction après est le nom de la commande. Cela sera détecter quand on fera la commande et renverra à la fonction.
Par exemple, si le prefix est “!”, le bot réagira à !ping.
Load et Unload de Commandes¶
Vous pouvez mettre vos commandes dans des fichiers exterieur et les load et unload a volonté.
Pour cela, mettez tout vos fichiers de commande dans un dossier commands/. Ensuite, dans
votre fichier de bot, vous avez juste a utiliser bot.load_module("Name") et bot.unload_module("Name")
Voici ce que cela pourrais donner:
from piscord import Handler
bot = Handler("Token","Prefix")
@bot.event
def on_ready(ctx):
bot.load_module("moderation") # Load le fichier présent à commands/moderation.py
bot.load_module("economy") # Load le fichier présent à commands/economy.py
@bot.command
def unload_mod(message):
bot.unload_module("moderation")
bot.run()
Caution
Petites précisions
Vous ne pouvez pas définir d’event ou load/unload un module dans un fichier.
De plus, utilisez dedans bot pour définir vos commandes, c’est celui
mis en place pour que la commande puisse bien s’unload.