Stvaranje Discord bota s Discord4J + Spring Boot

1. Pregled

Discord4J je Java biblioteka otvorenog koda koja se prvenstveno može koristiti za brzi pristup Discord Bot API-ju. Snažno se integrira s Project Reactor-om kako bi pružio potpuno neblokirajući reaktivni API.

U ovom ćemo uputstvu upotrijebiti Discord4J za stvaranje jednostavnog bona za Discord koji može odgovoriti na unaprijed definiranu naredbu. Izgradit ćemo bota na vrhu Spring Boota kako bismo pokazali kako bi bilo lako prilagoditi našeg bota mnogim drugim značajkama koje omogućuje Spring Boot.

Kad završimo, ovaj će bot moći preslušati naredbu koja se zove "! Todo" i ispisat će statički definirani popis obveza.

2. Stvorite Discord aplikaciju

Da bi naš bot primao ažuriranja s Discord-a i objavljivao odgovore na kanalima, morat ćemo stvoriti Discord-ovu aplikaciju na Discord Developer Portal-u i postaviti ga za bota. Ovo je jednostavan postupak. Budući da Discord omogućuje stvaranje više aplikacija ili botova pod jednim računom programera, slobodno to pokušajte više puta s različitim postavkama.

Evo koraka za stvaranje nove aplikacije:

  • Prijavite se na portal za programere Discord
  • Na kartici Aplikacije kliknite "Nova aplikacija"
  • Unesite ime za našeg bota i kliknite "Stvori"
  • Prenesite ikonu aplikacije i opis te kliknite "Spremi promjene"

Sad kad aplikacija postoji, jednostavno joj moramo dodati funkcionalnost bota. Ovo će generirati bot token koji Discord4J zahtijeva.

Evo koraka za pretvaranje aplikacije u bota:

  • Na kartici Aplikacije odaberite našu aplikaciju (ako već nije odabrana).
  • Na kartici Bot kliknite "Add Bot" i potvrdite da to želimo učiniti.

Sada kada je naša aplikacija postala pravi bot, kopirajte token da bismo ga mogli dodati u svojstva aplikacije. Pazite da ovaj token ne podijelite javno jer bi netko drugi mogao izvršiti zlonamjerni kod dok se lažno predstavlja kao naš bot.

Sada smo spremni za pisanje koda!

3. Stvorite Spring Boot App

Nakon konstrukcije nove aplikacije Spring Boot, moramo biti sigurni da smo uključili ovisnost jezgre Discord4J:

 com.discord4j discord4j-core 3.1.1 

Discord4J radi inicijalizacijom a GatewayDiscordClient s bot tokenom koji smo stvorili ranije. Ovaj klijentski objekt omogućuje nam registraciju slušatelja događaja i konfiguriranje mnogih stvari, ali u najmanju ruku, moramo barem nazvati prijaviti se() metoda. Ovo će prikazati našeg bota kao da je online.

Prvo, dodajmo svoj bot žeton na naš primjena.iml datoteka:

token: 'naš-token-ovdje'

Dalje, ubrizgajmo ga u @Konfiguracija klase u kojoj možemo instancirati svoj GatewayDiscordClient:

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

U ovom trenutku naš bi se bot smatrao mrežnim, ali još uvijek ne čini ništa. Dodajmo malo funkcionalnosti.

4. Dodajte slušatelje događaja

Najčešća značajka chatbota je naredba. Ovo je apstrakcija viđena u CLI-ima gdje korisnik upisuje neki tekst kako bi pokrenuo određene funkcije. To možemo postići u našem discord botu slušajući nove poruke koje korisnici šalju i odgovarajući inteligentnim odgovorima kada je to prikladno.

Postoje mnoge vrste događaja koje možemo slušati. Međutim, registracija slušatelja jednaka je za sve njih, pa napravimo prvo sučelje za sve naše slušatelje događaja:

uvoz discord4j.core.event.domain.Event; javno sučelje EventListener {Logger LOG = LoggerFactory.getLogger (EventListener.class); Klasa getEventType (); Mono izvršenje (T događaj); zadana Mono handleError (pogreška koja se može baciti) {LOG.error ("Nije moguće obraditi" + getEventType (). getSimpleName (), pogreška); return Mono.empty (); }}

Sada ovo sučelje možemo implementirati za toliko njih discord4j.core.event.domain.Događaj proširenja kako želimo.

Prije nego što implementiramo svoj prvi slušatelj događaja, izmijenimo svog klijenta @Grah konfiguracija za očekivati ​​popis EventListener tako da može registrirati sve pronađene u proljeće ApplicationContext:

@Bean public GatewayDiscordClient gatewayDiscordClient (Popis eventListeners) {GatewayDiscordClient client = DiscordClientBuilder.create (token) .build () .login () .block (); za (slušatelj EventListener: eventListeners) {client.on (listener.getEventType ()) .flatMap (listener :: execute) .onErrorResume (listener :: handleError) .subscribe (); } povrat klijenta; }

Sada sve što moramo učiniti da bismo registrirali slušatelje događaja je da implementiramo naše sučelje i označimo ga Springovim @Komponentanapomene na temelju stereotipa. Registracija će se sada automatski dogoditi za nas!

Mogli smo odabrati da svaki događaj prijavimo odvojeno i eksplicitno. Međutim, općenito je bolje zauzeti modularniji pristup radi veće skalabilnosti koda.

Postavljanje našeg slušatelja događaja sada je gotovo, ali bot još uvijek ne poduzima ništa, pa dodajmo neke događaje koje ćemo slušati.

4.1. Obrada naredbi

Da bismo dobili korisničku naredbu, možemo slušati dvije različite vrste događaja: MessageCreateEvent za nove poruke i MessageUpdateEvent za ažurirane poruke. Možda želimo poslušati samo nove poruke, ali kao priliku za učenje pretpostavimo da želimo podržati obje vrste događaja za svog bota. To će pružiti dodatni sloj robusnosti koji bi naši korisnici mogli cijeniti.

Oba objekta događaja sadrže sve relevantne informacije o svakom događaju. Posebno nas zanima sadržaj poruke, autor poruke i kanal na koji je objavljena. Srećom, sve ove točke podataka žive u Poruka objekt koji pružaju obje ove vrste događaja.

Jednom kad imamo Poruka, možemo provjeriti autora da se uvjeri da nije bot, možemo provjeriti sadržaj poruke kako bi se uvjerili da se podudara s našom naredbom i možemo koristiti kanal poruke za slanje odgovora.

Budući da u potpunosti možemo operirati od oba događaja preko njihovih Poruka objekte, stavimo svu nizvodnu logiku na zajedničko mjesto kako bi je mogli koristiti oba slušatelja događaja:

uvoz discord4j.core.object.entity.Message; javna apstraktna klasa MessageListener {public Mono processCommand (Message eventMessage) {return Mono.just (eventMessage) .filter (message -> message.getAuthor (). map (user ->! user.isBot ()). orElse (false)) .filter (message -> message.getContent (). equalsIgnoreCase ("! todo")) .flatMap (Message :: getChannel) .flatMap (channel -> channel.createMessage ("Što raditi danas: \ n - napišite bota \ n - ručati \ n - igrati igru ​​")). then (); }}

Ovdje se puno događa, ali ovo je najosnovniji oblik naredbe i odgovora. Ovaj pristup koristi reaktivni funkcionalni dizajn, ali moguće je to napisati na tradicionalniji imperativni način blok().

Skaliranje kroz više botovskih naredbi, pozivanje različitih usluga ili spremišta podataka ili čak korištenje uloga Discord kao autorizacija za određene naredbe uobičajeni su dijelovi dobre arhitekture bot naredbi. Budući da našim slušateljima upravlja proljeće @Serviss, mogli bismo lako ubrizgati druge grahice pod vodstvom proljeća da se pobrinu za te zadatke. Međutim, u ovom se članku nećemo pozabaviti ničim od toga.

4.2. EventListener

Da bismo primali nove poruke od korisnika, moramo ih poslušati MessageCreateEvent. Budući da logika obrade naredbi već živi u MessageListener, možemo ga proširiti kako bismo naslijedili tu funkcionalnost. Također, moramo implementirati naše EventListener sučelje u skladu s našim dizajnom registracije:

@Service javna klasa MessageCreateListener proširuje MessageListener implementira EventListener {@Override javna klasa getEventType () {return MessageCreateEvent.class; } @Override javno Mono izvršavanje (MessageCreateEvent događaj) {return processCommand (event.getMessage ()); }}

Nasljeđivanjem, poruka se prenosi na naše processCommand () metoda gdje se javljaju sve provjere i odgovori.

U ovom trenutku, naš bot će primiti i odgovoriti na naredbu "! Todo". Međutim, ako korisnik ispravi svoju pogrešno upisanu naredbu, bot neće odgovoriti. Podržimo ovaj slučaj upotrebe s drugim slušačem događaja.

4.3. EventListener

The MessageUpdateEvent emitira se kada korisnik uređuje poruku. Možemo slušati ovaj događaj kako bi prepoznali naredbe, slično kao što slušamo MessageCreateEvent.

U naše svrhe ovaj događaj nam je stalo samo ako je promijenjen sadržaj poruke. Možemo zanemariti druge slučajeve ovog događaja. Srećom, možemo koristiti isContentChanged () metoda za filtriranje takvih slučajeva:

@Service javna klasa MessageUpdateListener proširuje MessageListener implementira EventListener {@Override javna klasa getEventType () {return MessageUpdateEvent.class; } @Override public Mono execute (MessageUpdateEvent event) {return Mono.just (event) .filter (MessageUpdateEvent :: isContentChanged) .flatMap (MessageUpdateEvent :: getMessage) .flatMap (super :: processCommand); }}

U ovom slučaju, od getMessage () vraća se Mono umjesto sirovog Poruka, moramo koristiti flatMap () poslati ga našoj superklasi.

5. Testirajte bota u neskladu

Sad kad imamo funkcionalnog discord bota, možemo ga pozvati na Discord poslužitelj i testirati.

Da bismo stvorili vezu s pozivnicom, moramo odrediti koja dopuštenja bot zahtijeva za pravilno funkcioniranje. Popularni nezavisni kalkulator diskonturnih dozvola često se koristi za generiranje veze s potrebnim dopuštenjima. Iako se ne preporučuje za produkciju, jednostavno možemo odabrati "Administrator" za potrebe testiranja i ne brinuti se zbog ostalih dozvola. Jednostavno navedite ID klijenta za našeg bota (koji se nalazi na portalu Discord Developer Portal) i upotrijebite generiranu vezu kako biste pozvali našeg bota na poslužitelj.

Ako ne dodijelimo administratorska dopuštenja botu, možda ćemo trebati podesiti dopuštenja kanala kako bi bot mogao čitati i pisati na kanalu.

Bot sada odgovara na poruku "! Todo" i kada se poruka uređuje tako da kaže "! Todo":

6. Pregled

Ovaj je vodič opisao sve potrebne korake za stvaranje diskontnog bota pomoću biblioteke Discord4J i Spring Boot-a. Na kraju je opisano kako postaviti osnovnu skalabilnu strukturu naredbe i odgovora za bota.

Potpuni i radni bot potražite u izvornom kodu na GitHubu. Za njegovo pokretanje potreban je valjani bot token.