Discord Bot mit Aufnahmefunktion beginnend mit Python: (1) Einführung discord.py

Einführung

In diesem Artikel erstellen wir mehrmals einen Discord Bot in Python mit Aufnahmefunktionen von Grund auf neu.

discord.py ist eine Wrapper-Bibliothek für die Discord-API. In diesem Artikel werden wir es in mehrere Bereiche unterteilen, von der Erstellung eines Bots mit discord.py bis zum Hinzufügen eigener Funktionen. Die Reihenfolge besteht darin, mit der Umgebungskonstruktion zu beginnen, eine Reihe von Funktionen zu implementieren und dann die Aufzeichnungsfunktion zu implementieren.

Als ich Erklärungen zu verschiedenen Dingen hinzufügte, wurde es ein lächerlich langer Artikel, und ich beschloss, ihn separat zu veröffentlichen.

Wir planen insgesamt 7 Mal zu schreiben und haben bis zu 5 Artikel fertig geschrieben.

  1. Discord Bot mit Aufnahmefunktion beginnend mit Python: (1) Introductory discord.py
  2. Discord Bot mit Aufnahmefunktion beginnend mit Python: (2) Praktische Funktion (Bot-Erweiterung, Cog, Embed)
  3. Discord Bot mit Aufnahmefunktion beginnend mit Python: (3) Zusammenarbeit mit der Datenbank
  4. Discord Bot mit Aufnahmefunktion beginnend mit Python: (4) Musikdateien abspielen
  5. Discord Bot mit Aufnahmefunktion ab Python: (5) Discord API direkt bedienen

Möglicherweise liegt ein Fehler in der Implementierungsmethode in diesem Artikel vor. In diesem Fall weisen Sie bitte im Kommentarbereich darauf hin.

Wie sind Sie zu diesem Artikel gekommen?

discord.py hat alle Funktionen, die den juckenden Ort erreichen können. Wenn Sie beispielsweise Musik machen möchten ** Wiedergabe ** Bot, sollten Sie sich ursprünglich "mit WebSocket authentifizieren → sich mit WebSocket for Voice Channel verbinden und sich auf das Senden von Sprache vorbereiten → UDP-Verbindung herstellen und Opus mit RTP codieren Sie müssen eine komplizierte Verarbeitung wie "20 ms Musikdaten verschlüsseln und senden" [^ 1] ausführen, aber diese discord.py hat alle diese Funktionen implementiert und kann einfach verwendet werden.

[^ 1]: Sie müssen das Innere dieser Schlüsselhalterung jetzt nicht lesen. Es ist in Ordnung zu erkennen, dass Sie schwierige Dinge tun.

In Bezug auf die ** Aufnahmefunktion ** (Empfang von Audiodaten)

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

Wie in dieser Ausgabe erwähnt, gab es seit mehreren Jahren Stimmen, die eine Implementierung forderten, aber PR für die Hauptfamilie wurde noch nicht durchgeführt. Derzeit scheint die Aufnahmefunktion selbst in Discord.js implementiert zu sein, einem Wrapper für die JS-Version. Wenn es nicht unmöglich war, habe ich versucht, es selbst zu implementieren, und habe darüber nachgedacht, einen Einführungsartikel auf discord.py zusammen mit einer Einführung zu schreiben.

Vorsichtsmaßnahmen

Siehe hier für Pipenv.

Informationen zum Docker-Compose finden Sie unter hier.

Umgebung

Einen Bot erstellen

Erstellen Sie zunächst einen Bot aus dem [Entwicklerportal] von Discord (https://discord.com/developers/applications). Erstellen Sie einen Namen aus der neuen Anwendung. (Der Name des Bots ist hier DBot)

Image from Gyazo

Wenn die Erstellung abgeschlossen ist, sieht der Bildschirm folgendermaßen aus. Sie können auch das Symbolbild ändern.

Geben Sie als Nächstes die Token aus, die zum Erstellen des Bots erforderlich sind. Wenn dieses Token durchgesickert ist ** Wenn das Token beispielsweise für einen Bot mit Administratorrechten durchgesickert ist, kann ein Dritter den Server mit den Administratorrechten für alle Server betreiben, denen der Bot hinzugefügt wurde. Es wird möglich sein. Es ist mit größter Sorgfalt zu handhaben, damit es niemals ausläuft. ** **.

Um ein Token auszustellen, wählen Sie im Bot-Menü die Option [Bot hinzufügen].

Image from Gyazo

Klicken Sie für das Bot-Token auf die Schaltfläche unten auf dem Bildschirm, nachdem Sie den Bot-Bildschirm erstellt haben.

Image from Gyazo

Damit ist die Erstellung des Bots abgeschlossen, aber die Authentifizierungs-URL zum Hinzufügen des Bots zum Server wurde nicht ausgegeben. Sie können die Authentifizierungs-URL über das OAuth2-Menü eingeben.

Image from Gyazo

Wählen Sie in SCOPE bot aus und wählen Sie in BOT PERMISSIONS die Berechtigung Bot aus. Es ist kein Problem, wenn Sie die Berechtigung "Administrator" in die Entwicklungsphase einfügen. Es gibt viele vorhandene Bot, für die ein Administrator erforderlich ist. Dies kann jedoch einen leicht gefährlichen Eindruck erwecken, nur weil es sich um einen Bot handelt, für den Administratorrechte erforderlich sind. Daher muss er möglicherweise überprüft werden, wenn er für die Öffentlichkeit geöffnet wird.

Sie können den Bot zum Server einladen, indem Sie auf die URL klicken, die in der Mitte des Bildschirms angezeigt wird. ** Um Bot installieren zu können, benötigen Sie die Verwaltungsberechtigung des Servers, den Sie installieren möchten. ** [^ 2]

[^ 2]: Serverbesitzer oder Benutzer mit der Rolle "Administrator" oder "Serveradministrator"

Verzeichnisaufbau

In diesem Projekt werden wir basierend auf der folgenden Verzeichnisstruktur entwickeln. Sie müssen es noch nicht erstellen, da es in der richtigen Reihenfolge erstellt wird.

.
|- src                      #Alle Wurzeln des Quellcodes für Dienste
|  |- app                   #Quellcode für die Anwendung
|  |  |- [bot name]         #Wählen Sie den Namen des Bots nach Ihren Wünschen.
|  |  |  |- cogs            # discord.Sammeln Sie Dateien zum Hinzufügen von Funktionen zu py in diesem Ordner
|  |  |  |- core            #Die Definition von Bot selbst, Hilfsfunktionen, Erweiterungen usw. sind hier zusammengefasst.
|  |  |  |- __init__.py     #Als Modul behandeln
|  |  |  |- __main__.py     #Datei zum Starten
|  |  |
|  |  |- config.ini         #Außerhalb des Moduls werden verschiedene Einstellungen vorgenommen
|  |  |- Pipfile            # (Es wird automatisch generiert, sodass Sie es nicht erstellen müssen)
|  |  |- entrypoint.dev.sh
|  |
|  |- dev.dockerfile
|
|- docker-compose.dev.yml

Wenn Sie es nur ausführen möchten, benötigen Sie nur eine Datei. Hier haben wir jedoch eine etwas komplizierte Verzeichnisstruktur, vorausgesetzt, Sie möchten einen größeren Dienst ausführen.

Führen Sie zunächst Python aus. Erstellen Sie mit Pipenv eine virtuelle Umgebung und führen Sie Bot in dieser Umgebung aus.

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

Dies vervollständigt die Python-Umgebung. Ich verwende einen speziellen Dateinamen mit dem Namen "__main __. Py", aber indem ich Python-Code in diese Datei schreibe Der Aufruf an __main __. Py`

#Wenn Python ursprünglich auf Ihrem PC installiert ist
$ python -m dbot
Yay

#Beim Ausführen in der erstellten Pipenv-Umgebung
$ pipenv run python -m dbot

Sie können es mit tun. Wenn Sie ein selbst erstelltes Modul ausführen, ist dieses sauberer und besser.

Bewegen wir den Bot!

Nachdem Sie den Python-Code ausführen können, installieren wir die Datei discord.py, damit Bot funktioniert.

Ich habe die Verzeichnisse im vorherigen Abschnitt detailliert unterteilt, aber in diesem Artikel soll der Vorgang überprüft werden, sodass ich den gesamten Code in "__main __. Py" schreibe.

$ pipenv install discord.py[voice]

Bearbeiten Sie nach Abschluss der Installation "__main __. Py" mit einem Editor.

__main__.py


import discord

#Eine solche Zeichenfolge ist ein Token(Das folgende Token ist geeignet)
TOKEN = "MTE0NTE0MzY0MzY0ODEwOTMx.Adiade.Oosak0_Majide_Hampana1tteee"

#Erstellen eines Objekts zum Verschieben des Bots
client = discord.Client()


@client.event
async def on_ready():
    #Diese Funktion wird aufgerufen, wenn der Bot startbereit ist
    print("Gestartet")


@client.event
async def on_message(message):
    #Diese Funktion wird angezeigt, wenn eine Nachricht gesendet wird
    #Die Nachricht enthält verschiedene Informationen zu der vom Benutzer gesendeten Nachricht.

    #Antworten Sie nicht auf Nachrichten von Bot
    if message.author.bot:
        return

    print("Nachricht wurde gesendet")
    print("Absender", message.author.display_name)
    print("Inhalt", message.content)

    #Wenn ein Satz mit dem Inhalt Yay gesendet wird...
    if message.author != client and message.content == 'Yay':
        #Senden Sie die Nachricht an den Kanal zurück, an den die Nachricht gesendet wurde
        await message.channel.send("You're on discord.py!")

client.run(TOKEN)

Wenn Sie bis zu diesem Punkt eingeben können, speichern Sie es und führen Sie es erneut aus.

Wenn es startet und die Konsole "Gestartet" anzeigt, geben Sie das Wort Yay auf dem Server ein, auf dem der Bot tatsächlich installiert ist.

Image from Gyazo

Folgendes wird auf der Konsole angezeigt.

$ pipenv run python -m dbot
Gestartet
Nachricht wurde gesendet
Absender Admin
Inhalt Yay

Yay! You're on discord.py!

Es ist ein sehr kurzer Code, aber jetzt funktioniert ein einfacher Bot. Nachfolgend einige Ergänzungen.

In diesem Code gibt es einige Stellen, an denen @ client.event an die Funktion [^ 3] angehängt ist, die async def on_Nanchara heißt. Diese basieren auf den Funktionen von Python und jeder von ihnen

[^ 3]: Genau genommen ist "async def ~~" eine Collout-Funktion

Es gibt eine Funktion / Bedeutung. Wenn Sie ein Anfänger sind, ist es in Ordnung zu erkennen, dass Sie dies vorerst schreiben sollten.

Durch Hinzufügen eines Dekorators "@ client.event" zu einer Funktion, die mit "on_" beginnt, wie "on_ready", "on_message", ** wenn ein bestimmtes Ereignis eintritt **, ** einen bestimmten Prozess ausführen ** Kann leicht beschrieben werden. Eine Liste der unterstützten Ereignisse finden Sie auf der API-Referenzseite (es gibt einige).

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

Es gibt auch Stellen, an denen "Warten" zum Aufrufen der Funktion verwendet wird. Wie Sie jedoch feststellen können, ob für diese Funktion "Warten" erforderlich ist, finden Sie unter Referenzseite. In der Erklärung zur Funktion von /latest/api.html)

This function is a coroutine.

Wenn es einen Ort gibt, an dem es geschrieben ist, muss der Funktion "await" vorangestellt werden.

In discord.py können auch Informationen wie der Inhalt der Nachricht und der Absender der Nachricht als Klasseneigenschaften erfasst werden. Selbst wenn Sie den tatsächlichen Status des Codes nicht kennen, ist es daher leicht zu verstehen, welche Art von Verarbeitung ausgeführt wird, wenn Sie sich nur den Code ansehen. Auf der anderen Seite müssen Sie, bis Sie sich daran gewöhnt haben, als Referenz prüfen, welche Eigenschaft oder Methode in welcher Klasse enthalten ist. ([Ergänzung](# 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) führt einen Teil der Klasse discord.py ein.)

Kurz gesagt, wenn Sie in Schwierigkeiten sind, schauen Sie sich die Referenz an. Die Antwort ist 95% dort. ** RTFM !!! **

Auch hier haben wir das Ereignis definiert, indem wir "discord.Client" direkt instanziiert haben. Die gleiche Verarbeitung ist jedoch auch dann möglich, wenn Sie Ihre eigene Klasse definieren, die "discord.Client" erbt. (Diese Schreibmethode wird für die Referenzseite verwendet.)

__main__.py


import discord

TOKEN = "..."


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

    async def on_message(self, message):
        if message.author.bot:
            return
        print("Nachricht wurde gesendet")
        print("Absender", message.author.display_name)
        print("Inhalt", message.content)
        if message.content == 'Yay':
            await message.channel.send("You're on discord.py!")


Bot().run(TOKEN)

Lassen Sie uns diesen Dienst vorerst auf dem Docker-Container ausführen, vorausgesetzt, wir werden später Bot-Funktionen hinzufügen.

Erstellen eines Docker-Containers

Erstellen Sie drei Arten von Docker-bezogenen Dateien, wie im Beispiel für die Verzeichniskonfiguration am Anfang gezeigt. Da es "dev" heißt, erwägen wir, die Umgebung während der Entwicklung und Produktion zu trennen.

Wie schreibe ich eine Docker-Datei? Erstellen Sie nach B9) ein Image zur Ausführung, nachdem Sie das Python-Paket mit dem Builder installiert haben.

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

Im Build-Teil des Images zur Ausführung werden nodemon und ffmpeg in der Mitte installiert. nodemon wird verwendet, um Dateiänderungen zu erkennen und neu zu starten, ohne den Bot während der Entwicklung anhalten und neu starten zu müssen, und ffmpeg wird verwendet, um medienbezogene Verarbeitungen wie die Musikwiedergabe durchzuführen.

entrypoint.dev.sh wird mit nodemon gestartet.

shell:entrypoint.dev.sh


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

Zum Schluss schreiben Sie docker-compose.dev.yml wie folgt

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

Mit diesen Einstellungen wird das folgende "src" auf dem "Bot" des Containers gemountet. Wenn das Skript auf dem Host aktualisiert wird, wird die Änderung erkannt und der Bot neu gestartet. Mithilfe der Docker-Umgebung können Sie diese problemlos erweitern, wenn Sie später eine Datenbank oder eine Webfront hinzufügen möchten.

Kehren Sie nach dem bisherigen Schreiben zum Projektstamm zurück und führen Sie den folgenden Befehl aus.

$ chmod +x ./src/app/entrypoint.dev.sh
$ docker-compose -f docker-compose.dev.yml -p dev build #Ein Bild erstellen
$ docker-compose -f docker-compose.dev.yml -p dev up #Anlaufen

Es hat eine lange Beschreibung von "docker-compose -f docker-compose.dev.yml -p dev", aber es ist notwendig, es so zu beschreiben, da die Umgebung geteilt ist. Wenn es problematisch ist, können Sie glücklich sein, wenn Sie ein Skript wie das folgende erstellen

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

Nachdem Sie den Start bestätigt haben, versuchen wir, "__main __. Py" zu bearbeiten.

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  |Gestartet
dbot_1  | [nodemon] restarting due to changes...
dbot_1  | [nodemon] starting `python -m dbot`
dbot_1  |Es hat begonnen

Als der Bot den Save erkannte, wurde er neu gestartet. Dies ermöglicht eine deutliche Verbesserung der Entwicklungseffizienz.

Am Ende

In diesem Artikel haben wir eine Umgebung eingerichtet, die für die grundlegende Konstruktion und Entwicklung von Bot geeignet ist.

Das nächste Mal werde ich das Design für die Erstellung eines größeren Bots und die eingebetteten Elemente erläutern, die in diesem Artikel nicht vorgestellt werden.

Ergänzung

1. Häufig verwendete Klassen

Es werden nicht alle Funktionsargumente aufgelistet, sondern nur häufig verwendete.

discord.Message

Zum Vergrößern klicken

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

Name des Anwesens Schimmel Erläuterung
id int Eindeutige Kennung
author discord.Member Die Person, die die Nachricht gepostet hat
content str Nachrichteninhalt
guild discord.Guild Der Server, auf dem die Nachricht veröffentlicht wurde(Gilde)
channel Wenn es auf dem Server wardiscord.TextChannel Der Kanal, in dem die Nachricht gepostet wurde(DM usw. wird eine andere Klasse sein, aber ich werde es hier nicht erwähnen)
mentions List[discord.Member] Liste der Personen, die Erwähnungen übersprungen haben
reactions List[discord.Reaction] Piktogrammreaktion auf die Nachricht
created_at datetime.datetime Datum und Uhrzeit veröffentlichen
edited_at Optional[datetime.datetime] Datum und Uhrzeit bearbeiten(Wenn unbearbeitetNone)
jump_url str Link, um zu dieser Nachricht zu springen
await delete()
Löschen Sie die
-Nachricht.
Bot muss über die Berechtigung zur Nachrichtenverwaltung nachdenken.
await edit(content: str, ...)
Bearbeiten Sie die
-Nachricht. Geben Sie mit dem Schlüsselwort
als edit (content = "hoge") an.
Es muss eine Nachricht sein, die von Bot selbst gepostet wurde.
wartet auf add_reaction (emoji: str usw.)
Reaktion auf Nachricht hinzufügen
Unicode-Piktogramme können wie folgt eingegeben werden: ramen:
warten auf remove_reaction (emoji: str usw., member: discord.Member)
Löscht die angegebene Piktogrammreaktion des angegebenen Elements
wartet auf clear_reaction (emoji: str usw.)
Löschen Sie die angegebene Piktogrammreaktion

discord.Member

Zum Vergrößern klicken
Name des Anwesens Schimmel Erläuterung
id int Eindeutige Kennung
name str Nutzername
nick Optional[str] Auf dem Server festgelegter Name
display_name str Wenn es Nick gibt, Nick,Wenn nicht Name
mention str Eine Zeichenfolge, um ein Mitglied zu erwähnen
guild discord.Guild Der Server, zu dem das Mitglied gehört
roles List[discord.Role] Liste aller Rollen der Mitglieder
top_role discord.Role Die beste Rolle des Mitglieds
avatar_url str URL des Avatar-Bildes
joined_at datetime.datetime Datum und Uhrzeit des Beitritts des Mitglieds zum Server
created_at datetime.datetime Das Datum, an dem das Mitglied das Discord-Konto registriert hat

Der Grund der folgenden Methode wird im Überwachungsprotokoll angezeigt.

await ban(reason: Optional[str], ...)
BAN das
-Mitglied vom Server.
Eine BAN-Berechtigung ist erforderlich, und der Benutzer kann dem Server erst beitreten, wenn nicht gesperrt ist
await unban(reason: Optional[str], ...)
Geben Sie das BAN des Mitglieds frei, das vom Server gesperrt hat.
BAN-Berechtigung ist erforderlich, und nach Ausführung des Prozesses kann der Benutzer dem Server beitreten
await kick(reason: Optional[str], ...)
Verbannt den Benutzer vom Server
Kickberechtigung ist erforderlich.
await add_roles(*roles: discord.Role)
Geben Sie dem Benutzer eine Rolle
Die Rollen, die zugewiesen werden können, unterliegen den folgenden Einschränkungen.
1. Kann nicht ohne Rollenverwaltungsrechte ausgeführt werden
2. Rollen wie Bot und Server Booster können nicht gewährt werden
3. Von den Rollen, die der Bot hat, können Rollen, die höher als die höchste Rolle sind, nicht angehängt werden
await remove_roles(*roles: discord.Role)
Stiehlt Benutzern Rollen

discord.TextChannel

Zum Vergrößern klicken
Name des Anwesens Schimmel Erläuterung
id int Eindeutige Kennung
name str Kanal Name
guild discord.Guild Server mit Kanal
members List[discord.Member] Liste der Mitglieder, die die Berechtigung zum Anzeigen des Kanals haben
mention str Eine Zeichenfolge, die dem Kanal gegenüber erwähnt werden soll
created_at datetime.datetime Erstellungsdatum und -zeit
await send(content: str, embed: discord.Embed, file: discord.File)
Nachricht senden
await purge(limit: int, check)
Löschen Sie die Nachricht
Suchen Sie nach Grenzwertnachrichten und löschen Sie die Nachricht, die entspricht
Wenn die Argumentprüfung Keine lautet, werden alle Nachrichten ohne Fragen gelöscht. Wenn Sie jedoch discord.Message als Argument verwenden und eine Funktion angeben, die True für die zu löschende Nachricht zurückgibt, wird die Bedingung angegeben und gelöscht. Ich kann es schaffen
history(limit: int = 100) -> AsyncIterator
Nachrichtenverlauf abrufen
Seien Sie vorsichtig, da die Grammatik eindeutig ist

Rufen Sie "async for ... in ~~" wie folgt auf.

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

discord.Guild

Zum Vergrößern klicken
Name des Anwesens Schimmel Erläuterung
id int Eindeutige Kennung
name str Servername
icon_url str URL des Serversymbols
owner discord.Member Serverbesitzer
member_count int Anzahl der Mitglieder
text_channels List[discord.TextChannel] Alle Textkanäle im Server
members List[discord.Member] Alle Mitglieder im Server
roles List[discord.Role] Alle Rollen im Server
emojis List[discord.Emoji] Liste der vom Server erstellten Piktogramme
created_at datetime.datetime Erstellungsdatum und -zeit

Es gibt verschiedene Methoden, aber ich werde sie später vorstellen.

<! - Link Anhangsspalte unten->

Recommended Posts