Discord Bot avec fonction d'enregistrement commençant par Python: (1) Introduction discord.py

introduction

Dans cet article, nous allons créer plusieurs fois un Discord Bot en Python avec des capacités d'enregistrement à partir de zéro.

discord.py est une bibliothèque de wrapper pour l'API de Discord. Dans cet article, nous allons le diviser en plusieurs fois, de la création d'un Bot avec discord.py à l'ajout de vos propres fonctions. L'ordre est de commencer par la construction de l'environnement, d'implémenter un ensemble de fonctions, puis d'implémenter la fonction d'enregistrement.

En ajoutant des explications sur diverses choses, c'est devenu un article ridiculement long, alors j'ai décidé de le publier séparément.

Nous prévoyons d'écrire un total de 7 fois et avons fini d'écrire jusqu'à 5 articles.

  1. Discord Bot avec fonction d'enregistrement commençant par Python: (1) Mise en route discord.py
  2. Discord Bot avec fonction d'enregistrement commençant par Python: (2) Fonction pratique (extension Bot, Cog, Embed)
  3. Discord Bot avec fonction d'enregistrement commençant par Python: (3) Coopération avec la base de données
  4. Discord Bot avec fonction d'enregistrement commençant par Python: (4) Lire des fichiers musicaux
  5. Discord Bot avec fonction d'enregistrement commençant par Python: (5) Exploitez directement l'API Discord

Il peut y avoir une erreur dans la méthode d'implémentation dans cet article. Dans ce cas, veuillez l'indiquer dans la section des commentaires.

Comment en êtes-vous arrivé à écrire cet article

discord.py a toutes les fonctions qui peuvent atteindre l'endroit qui démange. Par exemple, lorsque vous voulez faire de la musique ** lecture ** Bot, vous devez à l'origine "vous authentifier avec WebSocket → vous connecter à WebSocket pour Voice Channel et vous préparer à envoyer de la voix → établir une connexion UDP et Opus encoder avec RTP Vous devez effectuer un traitement compliqué tel que "crypter et envoyer 20 ms de données musicales" [^ 1], mais ce discord.py a toutes ces fonctions implémentées et peut être utilisé facilement.

[^ 1]: Vous n'avez pas besoin de lire maintenant l'intérieur de ce support de clé. Il est normal de reconnaître que vous faites des choses difficiles.

Cependant, concernant la fonction ** enregistrement ** (réception de données audio),

https://github.com/Rapptz/discord.py/issues/1094

Comme mentionné dans ce numéro, il y a eu des demandes de mise en œuvre depuis plusieurs années, mais la RP au chef de famille n'a pas encore été effectuée. Pour le moment, la fonction d'enregistrement elle-même semble être implémentée dans Discord.js, qui est un wrapper pour la version JS. Si ce n'était pas impossible, j'ai essayé de l'implémenter moi-même, alors j'ai commencé à penser à écrire un article d'introduction sur discord.py avec une introduction.

Remarques

Veuillez consulter ici pour Pipenv.

Veuillez voir ici pour docker-compose.

Environnement

Créer un bot

Tout d'abord, créez un bot à partir du [portail de développement] de Discord (https://discord.com/developers/applications). Créez un nom à partir de la nouvelle application. (Le nom du Bot est DBot ici)

Image from Gyazo

Lorsque la création est terminée, l'écran ressemblera à ceci. Vous pouvez également modifier l'image de l'icône.

Ensuite, émettez les jetons requis pour créer le Bot. Si ce jeton est divulgué ** Par exemple, si le jeton est divulgué pour un bot avec des privilèges d'administrateur, un tiers peut faire fonctionner le serveur avec les privilèges d'administrateur pour tous les serveurs auxquels le bot est ajouté. Ce sera possible. Il est nécessaire de le gérer avec le plus grand soin afin qu'il ne fuit jamais. ** **

Pour émettre un token, sélectionnez [Add Bot] dans le menu Bot.

Image from Gyazo

Pour le jeton Bot, cliquez sur le bouton ci-dessous à partir de l'écran après avoir créé l'écran Bot.

Image from Gyazo

Ceci termine la création du Bot, mais l'URL d'authentification pour l'ajout du Bot au serveur n'a pas été émise. Vous pouvez émettre l'URL d'authentification à partir du menu OAuth2.

Image from Gyazo

Dans SCOPE, sélectionnez bot et dans BOT PERMISSIONS, sélectionnez Bot autorité. Il n'y a aucun problème si vous mettez l'autorité "Administrateur" dans la phase de développement. Il existe de nombreux Bot existants qui nécessitent un administrateur, mais cela peut donner une impression légèrement dangereuse simplement parce que c'est un bot qui nécessite des privilèges d'administrateur, il peut donc être nécessaire de le réviser lorsqu'il est ouvert au public.

Vous pouvez inviter le Bot sur le serveur en cliquant sur l'URL qui apparaît au centre de l'écran. ** Pour installer Bot, vous devez disposer de l'autorité de gestion du serveur que vous souhaitez installer. ** [^ 2]

[^ 2]: propriétaire du serveur ou utilisateur avec le rôle "d'administrateur" ou "d'administrateur de serveur"

Structure du répertoire

Dans ce projet, nous développerons sur la base de la structure de répertoires suivante. Vous n'avez pas encore besoin de le créer car il sera créé dans l'ordre.

.
|- src                      #Toutes les racines du code source pour les services
|  |- app                   #Code source de l'application
|  |  |- [bot name]         #Choisissez le nom du Bot comme vous le souhaitez.
|  |  |  |- cogs            # discord.Collectez des fichiers pour ajouter des fonctions à py dans ce dossier
|  |  |  |- core            #La définition de Bot lui-même, les fonctions auxiliaires, les extensions, etc. sont résumées ici.
|  |  |  |- __init__.py     #Traiter comme un module
|  |  |  |- __main__.py     #Fichier pour le démarrage
|  |  |
|  |  |- config.ini         #Différents réglages sont effectués à l'extérieur du module
|  |  |- Pipfile            # (Il est généré automatiquement pour que vous n'ayez pas à le créer)
|  |  |- entrypoint.dev.sh
|  |
|  |- dev.dockerfile
|
|- docker-compose.dev.yml

Si vous voulez simplement l'exécuter, vous n'avez besoin que d'un seul fichier, mais ici nous avons une structure de répertoires légèrement compliquée en supposant que vous souhaitez exécuter un service plus important.

Tout d'abord, exécutez Python. Créez un environnement virtuel avec Pipenv et exécutez Bot dans cet environnement.

$ mkdir src
$ cd src
$ mkdir app
$ cd app
$ mkdir dbot
$ echo 'print("Yay")' > ./dbot/__main__.py
$ pipenv --python 3.8.2

Ceci complète l'environnement Python. J'utilise un nom de fichier spécial appelé __main __. Py, mais en écrivant du code Python dans ce fichier L'appel à __main __. Py

#Si Python est à l'origine sur votre PC
$ python -m dbot
Yay

#Lors de l'exécution dans l'environnement Pipenv créé
$ pipenv run python -m dbot

Vous pouvez le faire avec. Si vous souhaitez exécuter votre propre module, celui-ci est plus propre et meilleur.

Déplaçons le Bot!

Maintenant que vous pouvez exécuter le code Python, installons en fait discord.py et faisons fonctionner Bot.

J'ai divisé les répertoires en détail dans la section précédente, mais dans cet article, le but est de vérifier le fonctionnement, donc j'écrirai tout le code dans __main __. Py.

$ pipenv install discord.py[voice]

Une fois l'installation terminée, éditez __main __. Py avec un éditeur.

__main__.py


import discord

#Une chaîne de caractères comme celle-ci est un jeton(Le jeton ci-dessous convient)
TOKEN = "MTE0NTE0MzY0MzY0ODEwOTMx.Adiade.Oosak0_Majide_Hampana1tteee"

#Créer un objet pour déplacer le Bot
client = discord.Client()


@client.event
async def on_ready():
    #Cette fonction est appelée lorsque le Bot est prêt à démarrer
    print("Commencé")


@client.event
async def on_message(message):
    #Cette fonction est affiché lorsqu'un message est envoyé
    #Message contient diverses informations sur le message envoyé par l'utilisateur.

    #Ne répondez pas aux messages du Bot
    if message.author.bot:
        return

    print("Le message a été envoyé")
    print("expéditeur", message.author.display_name)
    print("Contenu", message.content)

    #Si une phrase avec le contenu Yay est envoyée...
    if message.author != client and message.content == 'Yay':
        #Renvoyer le message au canal auquel le message a été envoyé
        await message.channel.send("You're on discord.py!")

client.run(TOKEN)

Si vous pouvez entrer jusqu'à ce point, enregistrez-le et réexécutez.

Quand il démarre et que la console affiche «Démarré», essayez de taper le mot Yay sur le serveur où le Bot est réellement installé.

Image from Gyazo

Ce qui suit est affiché sur la console.

$ pipenv run python -m dbot
Commencé
Le message a été envoyé
Administrateur de l'expéditeur
Contenu Yay

Yay! You're on discord.py!

C'est un code très court, mais c'est suffisant pour faire fonctionner un simple Bot. Voici quelques suppléments.

Dans ce code, il y a des endroits où @ client.event est attaché au-dessus de la fonction [^ 3] appelée ʻa sync def on_Nanchara`. Ceux-ci sont basés sur les fonctions de Python, et chacun d'eux

[^ 3]: Strictement parlant, ʻa sync def ~~ `est une fonction collout

Il y a une fonction / une signification. Si vous êtes un débutant, il est normal de reconnaître que vous devez écrire ceci pour le moment.

En ajoutant un décorateur @ client.event à une fonction qui commence par ʻon_, comme ʻon_ready, ʻon_message`, ** lorsqu'un événement spécifique se produit **, ** effectuer un traitement spécifique **, etc. Peut être facilement décrit. Une liste des événements pris en charge peut être trouvée sur la page de référence de l'API (il y en a plusieurs).

https://discordpy.readthedocs.io/ja/latest/api.html#event-reference

De plus, il y a des endroits où ʻawait est utilisé pour appeler des fonctions, mais comment déterminer si une fonction nécessite ʻawait est Page de référence. Dans l'explication de la fonction de /latest/api.html)

This function is a coroutine.

S'il y a un endroit où il est écrit, la fonction doit être préfixée avec ʻawait`.

De plus, dans discord.py, des informations telles que le contenu du message et l'expéditeur du message peuvent être acquises en tant que propriétés de classe. Par conséquent, même si vous ne connaissez pas l'état réel du code, il est facile de comprendre quel type de traitement est effectué simplement en regardant le code. D'autre part, jusqu'à ce que vous vous y habituiez, vous devez regarder quelle propriété ou méthode se trouve dans quelle classe comme référence. ([Supplément](# 1-% E3% 82% 88% E3% 81% 8F% E4% BD% BF% E3% 81% 86% E3% 82% AF% E3% 83% A9% E3% 82% B9% E3% 81% A8% E3% 82% A4% E3% 83% 99% E3% 83% B3% E3% 83% 88) présente certaines des classes discord.py.)

Bref, si vous avez des ennuis, jetez un œil à la référence. La réponse est à 95% là-bas. ** RTFM !!! **

De plus, ici, nous avons défini l'événement en instanciant directement discord.Client, mais le même traitement est possible même si vous définissez votre propre classe qui hérite de discord.Client. (Cette méthode d'écriture est utilisée pour la page de référence.)

__main__.py


import discord

TOKEN = "..."


class Bot(discord.Client):
    async def on_ready(self):
        print("Commencé")

    async def on_message(self, message):
        if message.author.bot:
            return
        print("Le message a été envoyé")
        print("expéditeur", message.author.display_name)
        print("Contenu", message.content)
        if message.content == 'Yay':
            await message.channel.send("You're on discord.py!")


Bot().run(TOKEN)

Pour le moment, exécutons ce service sur le conteneur Docker, en supposant que nous ajouterons des fonctions Bot plus tard.

Créer un conteneur Docker

Créez trois types de fichiers liés à Docker comme indiqué dans l'exemple de configuration de répertoire au début. Comme il s'appelle dev, nous envisageons de séparer l'environnement pendant le développement et la production.

Comment écrire Dockerfile est [cet article](https://qiita.com/Aruneko/items/796d7eeb61e1f36ae4a0#dockerfile%E3%81%AE%E6%9B%B8%E3%81%8D%E6%96% Après B9), créez une image à exécuter après avoir installé le package Python avec builder.

dev.dockerfile


FROM python:3.8 as builder
WORKDIR /bot
RUN apt update -y && \
    apt upgrade -y
COPY ./app/Pipfile ./app/Pipfile.lock /bot/
RUN pip install pipenv && \
    pipenv install --system

FROM python:3.8-slim
WORKDIR /bot
RUN apt update -y && \
    apt upgrade -y && \
    apt install -y nodejs npm curl && \
    npm install -g n && \
    n stable && \
    apt purge -y nodejs npm && \
    apt install -y ffmpeg && \
    apt autoremove -y
RUN npm install -g nodemon

ENV PYTHONBUFFERED=1
COPY --from=builder /usr/local/lib/python3.8/site-packages /usr/local/lib/python3.8/site-packages

COPY . /bot

Dans la partie construction de l'image pour l'exécution, nodemon et ffmpeg sont installés au milieu. nodemon est utilisé pour détecter les modifications de fichiers et redémarrer sans avoir à arrêter et redémarrer le Bot pendant le développement, et ffmpeg est utilisé pour effectuer des traitements liés aux médias tels que la lecture de musique.

ʻEntrypoint.dev.sh` commence à utiliser nodemon.

shell:entrypoint.dev.sh


nodemon --signal SIGINT -e py,ini --exec python -m dbot

Enfin, écrivez docker-compose.dev.yml comme suit

yml:docker-compose.dev.yml


version: "3.8"
services: 
  dbot:
    build:
      context: ./src
      dockerfile: dev.dockerfile
    tty: true
    working_dir: /bot/app
    entrypoint: bash ./entrypoint.dev.sh
    volumes:
      - ./src:/bot

Avec ces paramètres, le src suivant sera monté sur le bot du conteneur, et lorsque le script est mis à jour sur l'hôte, le changement sera détecté et le Bot sera redémarré. En utilisant l'environnement docker, il est possible de l'étendre facilement lorsque vous souhaitez ajouter une base de données ou une façade Web ultérieurement.

Après avoir écrit jusqu'à présent, revenez à la racine du projet et exécutez la commande suivante.

$ chmod +x ./src/app/entrypoint.dev.sh
$ docker-compose -f docker-compose.dev.yml -p dev build #Créer une image
$ docker-compose -f docker-compose.dev.yml -p dev up #Commencez

Il a une longue description de docker-compose -f docker-compose.dev.yml -p dev, mais il est nécessaire de le décrire comme ceci car l'environnement est divisé. Si c'est gênant, vous pouvez être heureux si vous créez un script comme celui-ci

run.sh


#!/bin/bash
cmd="docker-compose -f docker-compose.$1.yml -p $1 ${@:2}"
echo $cmd
eval $cmd
$ ./run.sh dev build
$ ./run.sh dev up

Après avoir confirmé le démarrage, éditons __main __. Py comme un essai.

dbot_1  | [nodemon] 2.0.4
dbot_1  | [nodemon] to restart at any time, enter `rs`
dbot_1  | [nodemon] watching path(s): *.*
dbot_1  | [nodemon] watching extensions: py,ini
dbot_1  | [nodemon] starting `python -m dbot`
dbot_1  |Commencé
dbot_1  | [nodemon] restarting due to changes...
dbot_1  | [nodemon] starting `python -m dbot`
dbot_1  |Il a commencé

Détectant la sauvegarde, le Bot a été redémarré. Cela permet d'améliorer considérablement l'efficacité du développement.

À la fin

Dans cet article, nous avons mis en place un environnement adapté à la construction et au développement de Bot de base.

La prochaine fois, j'expliquerai la conception pour créer un bot plus grand et les éléments intégrés qui ne sont pas présentés dans cet article.

Supplément

1. Classes fréquemment utilisées

Tous les arguments de fonction ne sont pas répertoriés, mais seuls les arguments fréquemment utilisés sont sélectionnés.

discord.Message

Cliquez pour développer

https://discordpy.readthedocs.io/ja/latest/api.html#message

Nom de la propriété Moule La description
id int Identifiant unique
author discord.Member La personne qui a publié le message
content str Contenu du message
guild discord.Guild Le serveur sur lequel le message a été publié(guilde)
channel Si c'était dans le serveurdiscord.TextChannel La chaîne sur laquelle le message a été publié(DM etc. sera une autre classe, mais je ne le mentionnerai pas ici)
mentions List[discord.Member] Liste des personnes qui ont ignoré les mentions
reactions List[discord.Reaction] Réaction du pictogramme au message
created_at datetime.datetime Date et heure de publication
edited_at Optional[datetime.datetime] Modifier la date et l'heure(Si non éditéNone)
jump_url str Lien pour accéder à ce message
await delete()
Supprimer le message
.
Bot doit penser à l'autorité de gestion des messages.
await edit(content: str, ...)
Modifiez le message
. Spécifiez avec le mot-clé
comme edit (content = "hoge") .
Ce doit être un message posté par Bot lui-même.
attendre add_reaction (emoji: str etc.)
Ajouter une réaction au message
Les pictogrammes Unicode peuvent être saisis tels quels: ramen:
attendez remove_reaction (emoji: str etc., membre: discord.Member)
Supprimer la réaction de pictogramme spécifiée du membre spécifié
attend clear_reaction (emoji: str etc.)
Supprimer la réaction de pictogramme spécifiée

discord.Member

Cliquez pour développer
Nom de la propriété Moule La description
id int Identifiant unique
name str Nom d'utilisateur
nick Optional[str] Nom défini sur le serveur
display_name str S'il y a nick, nick,Si ce n'est pas le nom
mention str Une chaîne pour mentionner un membre
guild discord.Guild Le serveur auquel appartient le membre
roles List[discord.Role] Liste de tous les rôles des membres
top_role discord.Role Meilleur rôle du membre
avatar_url str URL de l'image de l'avatar
joined_at datetime.datetime Date et heure auxquelles le membre a rejoint le serveur
created_at datetime.datetime La date à laquelle le membre a enregistré le compte Discord

La raison de la méthode suivante est affichée dans le journal d'audit.

await ban(reason: Optional[str], ...)
BAN le membre
du serveur.
L’autorisation BAN est requise et l’utilisateur ne pourra pas rejoindre le serveur tant qu’il n’a pas été interdit
await unban(reason: Optional[str], ...)
Libérez le BAN du membre qui a banni du serveur.
l'autorisation BAN est requise et après l'exécution du processus, l'utilisateur peut rejoindre le serveur
await kick(reason: Optional[str], ...)
Exilez l'utilisateur du serveur
L'autorité Kick est requise.
await add_roles(*roles: discord.Role)
Donner un rôle à l'utilisateur
Les rôles qui peuvent être attribués ont les restrictions suivantes.
1. Ne peut pas être exécuté sans les privilèges de gestion des rôles
2. Les rôles tels que Bot et Server Booster ne peuvent pas être accordés
3. Parmi les jets que possède le Bot, les jets supérieurs au résultat le plus élevé ne peuvent pas être attachés
await remove_roles(*roles: discord.Role)
vole des rôles aux utilisateurs

discord.TextChannel

Cliquez pour développer
Nom de la propriété Moule La description
id int Identifiant unique
name str Nom du canal
guild discord.Guild Serveur avec canal
members List[discord.Member] Liste des membres autorisés à voir la chaîne
mention str Une chaîne à mentionner à la chaîne
created_at datetime.datetime Date et heure de création
await send(content: str, embed: discord.Embed, file: discord.File)
Envoyer un message
await purge(limit: int, check)
Supprimer le message
Rechercher des messages de limite et supprimer le message correspondant à la vérification Si la vérification de l'argument
est None, tous les messages sont supprimés sans aucune question, mais en prenant discord.Message comme argument et en donnant une fonction qui renvoie True pour le message à supprimer, la condition est spécifiée et supprimée. Je peux le faire.
history(limit: int = 100) -> AsyncIterator
Obtenir l'historique des messages
Attention car la grammaire est unique

Appelez ʻasync for ... in ~~ `comme suit.

async for message in channel.history():
    print(messane.author.name)

discord.Guild

Cliquez pour développer
Nom de la propriété Moule La description
id int Identifiant unique
name str nom du serveur
icon_url str URL de l'icône du serveur
owner discord.Member Propriétaire du serveur
member_count int Nombre de membres
text_channels List[discord.TextChannel] Tous les canaux de texte du serveur
members List[discord.Member] Tous les membres du serveur
roles List[discord.Role] Tous les rôles sur le serveur
emojis List[discord.Emoji] Liste des pictogrammes créés par le serveur
created_at datetime.datetime Date et heure de création

Il existe différentes méthodes, mais je les présenterai plus tard.

<! - Lier la colonne des pièces jointes ci-dessous->

Recommended Posts