Oprettelse af en Discord Bot med Discord4J + Spring Boot

1. Oversigt

Discord4J er et open source Java-bibliotek, der primært kan bruges til hurtigt at få adgang til Discord Bot API. Det integreres stærkt med Project Reactor for at give en fuldstændig ikke-blokerende reaktiv API.

Vi bruger Discord4J i denne vejledning til at oprette en simpel Discord-bot, der kan reagere på en foruddefineret kommando. Vi bygger botten oven på Spring Boot for at demonstrere, hvor let det ville være at skalere vores bot på tværs af mange andre funktioner aktiveret af Spring Boot.

Når vi er færdige, vil denne bot være i stand til at lytte efter en kommando kaldet “! Todo” og vil udskrive en statisk defineret opgaveliste.

2. Opret en Discord-applikation

For at vores bot kan modtage opdateringer fra Discord og sende svar i kanaler, skal vi oprette en Discord-applikation i Discord Developer Portal og indstille den til at være en bot. Dette er en simpel proces. Da Discord tillader oprettelse af flere applikationer eller bots under en enkelt udviklerkonto, er du velkommen til at prøve dette flere gange med forskellige indstillinger.

Her er trinene til oprettelse af en ny applikation:

  • Log ind på Discord Developer Portal
  • Klik på "Ny applikation" under fanen Applikationer
  • Indtast et navn til vores bot, og klik på "Opret"
  • Upload et appikon og en beskrivelse, og klik på "Gem ændringer"

Nu hvor der findes en applikation, skal vi blot tilføje bot-funktionalitet til den. Dette genererer det bot-token, som Discord4J kræver.

Her er trinene til at omdanne en applikation til en bot:

  • Under applikationsfanen skal du vælge vores applikation (hvis den ikke allerede er valgt).
  • Klik på "Tilføj bot" på fanen Bot, og bekræft, at vi vil gøre det.

Nu hvor vores applikation er blevet en rigtig bot, skal du kopiere tokenet, så vi kan tilføje det til vores applikationsegenskaber. Pas på ikke at dele dette token offentligt, da en anden ville være i stand til at udføre ondsindet kode, mens han efterligner vores bot.

Vi er nu klar til at skrive noget kode!

3. Opret en Spring Boot-app

Efter konstruktion af en ny Spring Boot-app skal vi være sikre på at inkludere Discord4J-kerneafhængigheden:

 com.discord4j discord4j-core 3.1.1 

Discord4J fungerer ved at initialisere en GatewayDiscordClient med bot-tokenet, vi oprettede tidligere. Dette klientobjekt giver os mulighed for at registrere begivenhedslyttere og konfigurere mange ting, men i det mindste skal vi i det mindste ringe til Log på() metode. Dette viser vores bot som værende online.

Lad os først tilføje vores bot-token til vores ansøgning.yml fil:

token: 'vores-token-her'

Lad os derefter injicere det i en @Konfiguration klasse, hvor vi kan instantiere vores GatewayDiscordClient:

@Configuration public class BotConfiguration {@Value ("$ {token}") private String token; @Bean offentlig GatewayDiscordClient gatewayDiscordClient () {returner DiscordClientBuilder.create (token) .build () .login () .block (); }}

På dette tidspunkt vil vores bot blive betragtet som online, men den gør ikke noget endnu. Lad os tilføje nogle funktioner.

4. Tilføj begivenhedslyttere

Det mest almindelige træk ved en chatbot er kommandoen. Dette er en abstraktion set i CLI'er, hvor en bruger skriver noget tekst for at udløse bestemte funktioner. Vi kan opnå dette i vores Discord-bot ved at lytte efter nye meddelelser, som brugerne sender, og svare med intelligente svar, når det er relevant.

Der er mange typer begivenheder, som vi kan lytte til. At registrere en lytter er dog det samme for dem alle, så lad os først oprette en grænseflade til alle vores begivenhedslyttere:

import discord4j.core.event.domain.Event; offentlig grænseflade EventListener {Logger LOG = LoggerFactory.getLogger (EventListener.class); Klasse getEventType (); Mono-udførelse (T-begivenhed); standard Mono handleError (fejl, der kan kastes) {LOG.error ("Kan ikke behandle" + getEventType (). getSimpleName (), fejl); returner Mono.empty (); }}

Nu kan vi implementere denne grænseflade for så mange discord4j.core.event.domain.Event udvidelser, som vi ønsker.

Før vi implementerer vores første begivenhedslytter, lad os ændre vores klient @Bønne konfiguration for at forvente en liste over EventListener så det kan registrere alle, der findes i foråret ApplicationContext:

@Bean offentlig GatewayDiscordClient gatewayDiscordClient (Liste eventListeners) {GatewayDiscordClient-klient = DiscordClientBuilder.create (token) .build () .login () .block (); for (EventListener-lytter: eventListeners) {client.on (listener.getEventType ()) .flatMap (lytter :: execute) .onErrorResume (lytter :: handleError). abonner (); } returnere klient; }

Nu er alt, hvad vi skal gøre for at registrere lyttere til begivenheder, at implementere vores interface og kommentere det med Spring's @Komponent-baserede stereotype kommentarer. Registreringen sker nu automatisk for os!

Vi kunne have valgt at registrere hver begivenhed separat og eksplicit. Det er dog generelt bedre at tage en mere modulær tilgang til bedre skalerbarhed af kode.

Vores opsætning af lytter til begivenheder er nu afsluttet, men boten gør stadig ikke noget endnu, så lad os tilføje nogle begivenheder at lytte til.

4.1. Kommandabehandling

For at modtage en brugers kommando kan vi lytte til to forskellige begivenhedstyper: MessageCreateEvent for nye beskeder og MessageUpdateEvent for opdaterede beskeder. Vi vil måske kun lytte efter nye beskeder, men som en læringsmulighed, lad os antage, at vi vil støtte begge slags begivenheder til vores bot. Dette giver et ekstra lag af robusthed, som vores brugere måske sætter pris på.

Begge begivenhedsobjekter indeholder alle relevante oplysninger om hver begivenhed. Vi er især interesserede i meddelelsens indhold, forfatteren af ​​meddelelsen og den kanal, den blev sendt til. Heldigvis lever alle disse datapunkter i Besked objekt, som begge disse begivenhedstyper giver.

Når vi har den Besked, vi kan kontrollere forfatteren for at sikre, at det ikke er en bot, vi kan kontrollere meddelelsesindholdet for at sikre, at det matcher vores kommando, og vi kan bruge meddelelsens kanal til at sende et svar.

Da vi fuldt ud kan operere fra begge begivenheder gennem deres Besked objekter, lad os lægge al downstream-logik på et fælles sted, så begge begivenhedslyttere kan bruge det:

import discord4j.core.object.entity.Message; offentlig abstrakt klasse MessageListener {public Mono processCommand (Message eventMessage) {return Mono.just (eventMessage). filter (message -> message.getAuthor (). map (user ->! user.isBot ()). orElse (false)) filter. \ n - spis frokost \ n - spil et spil ")). derefter (); }}

Der foregår meget her, men dette er den mest basale form for en kommando og et svar. Denne tilgang bruger et reaktivt funktionelt design, men det er muligt at skrive dette på en mere traditionel imperativ måde ved hjælp af blok().

Skalering på tværs af flere bot-kommandoer, påberåbelse af forskellige tjenester eller datalagre eller endda brug af Discord-roller som autorisation til bestemte kommandoer er almindelige dele af en god bot-kommandoarkitektur. Da vores lyttere styres af foråret @Services, vi kunne let injicere andre fjederstyrede bønner for at tage os af disse opgaver. Vi tackler dog ikke noget af dette i denne artikel.

4.2. EventListener

For at modtage nye beskeder fra en bruger skal vi lytte til MessageCreateEvent. Da kommandobehandlingslogikken allerede lever i MessageListener, kan vi udvide det til at arve denne funktionalitet. Vi er også nødt til at implementere vores EventListener interface til at overholde vores registreringsdesign:

@Service offentlig klasse MessageCreateListener udvider MessageListener implementerer EventListener {@Override public Class getEventType () {return MessageCreateEvent.class; } @ Override public Mono execute (MessageCreateEvent event) {return processCommand (event.getMessage ()); }}

Gennem arv videregives budskabet til vores processCommand () metode, hvor alle verifikationer og svar forekommer.

På dette tidspunkt vil vores bot modtage og svare på kommandoen “! Todo”. Men hvis en bruger korrigerer deres forkert indtastede kommando, svarer boten ikke. Lad os støtte denne brugssag med en anden begivenhedslytter.

4.3. EventListener

Det MessageUpdateEvent udsendes, når en bruger redigerer en besked. Vi kan lytte til denne begivenhed for at genkende kommandoer, ligesom hvordan vi lytter efter MessageCreateEvent.

Til vores formål bekymrer vi os kun om denne begivenhed, hvis meddelelsesindholdet blev ændret. Vi kan ignorere andre forekomster af denne begivenhed. Heldigvis kan vi bruge isContentChanged () metode til at filtrere sådanne forekomster ud:

@Service public class MessageUpdateListener udvider MessageListener implementerer EventListener {@Override public Class getEventType () {return MessageUpdateEvent.class; } @Override offentlig Mono-udførelse (MessageUpdateEvent-begivenhed) {returner Mono.just (event) .filter (MessageUpdateEvent :: isContentChanged) .flatMap (MessageUpdateEvent :: getMessage) .flatMap (super :: processCommand); }}

I dette tilfælde siden getMessage () vender tilbage Mono i stedet for en rå Besked, vi skal bruge flatMap () at sende det til vores superklasse.

5. Test Bot i uoverensstemmelse

Nu hvor vi har en fungerende Discord-bot, kan vi invitere den til en Discord-server og teste den.

For at oprette et invitationslink skal vi specificere hvilke tilladelser boten kræver for at fungere korrekt. En populær tredjeparts lommeregner til diskordstilladelser bruges ofte til at generere et invitationslink med de nødvendige tilladelser. Selvom det ikke anbefales til produktion, kan vi blot vælge "Administrator" til testformål og ikke bekymre os om de andre tilladelser. Du skal blot angive klient-id til vores bot (findes i Discord Developer Portal) og bruge det genererede link til at invitere vores bot til en server.

Hvis vi ikke giver administratortilladelser til bot, er vi muligvis nødt til at tilpasse kanalrettigheder, så bot kan læse og skrive i en kanal.

Bot reagerer nu på meddelelsen "! Todo", og når en besked redigeres for at sige "! Todo":

6. Oversigt

Denne vejledning beskrev alle de nødvendige trin til oprettelse af en Discord-bot ved hjælp af Discord4J-biblioteket og Spring Boot. Endelig beskrev den, hvordan man opretter en grundlæggende skalerbar kommando- og reaktionsstruktur til bot.

For en komplet og fungerende bot, se kildekoden over på GitHub. Et gyldigt bot-token kræves for at køre det.