diff --git a/discord4j/.gitignore b/discord4j/.gitignore new file mode 100644 index 0000000000..b56f1dd0d0 --- /dev/null +++ b/discord4j/.gitignore @@ -0,0 +1,33 @@ +README.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/discord4j/pom.xml b/discord4j/pom.xml new file mode 100644 index 0000000000..7687f63ad5 --- /dev/null +++ b/discord4j/pom.xml @@ -0,0 +1,63 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.3.5.RELEASE + + + com.baeldung + discord4j-bot + 0.0.1-SNAPSHOT + discord4j-bot + Demo Discord bot using Discord4J + Spring Boot + + + 1.8 + + + + + org.springframework.boot + spring-boot-starter + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.junit.vintage + junit-vintage-engine + + + + + + com.discord4j + discord4j-core + 3.1.1 + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + + + diff --git a/discord4j/src/main/java/com/baeldung/discordbot/BotConfiguration.java b/discord4j/src/main/java/com/baeldung/discordbot/BotConfiguration.java new file mode 100644 index 0000000000..a60005e9b5 --- /dev/null +++ b/discord4j/src/main/java/com/baeldung/discordbot/BotConfiguration.java @@ -0,0 +1,48 @@ +package com.baeldung.discordbot; + +import com.baeldung.discordbot.events.EventListener; +import discord4j.core.DiscordClientBuilder; +import discord4j.core.GatewayDiscordClient; +import discord4j.core.event.domain.Event; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.List; + +@Configuration +public class BotConfiguration { + + private static final Logger log = LoggerFactory.getLogger( BotConfiguration.class ); + + @Value("${token}") + private String token; + + @Bean + public GatewayDiscordClient gatewayDiscordClient(List> eventListeners) { + GatewayDiscordClient client = null; + + try { + client = DiscordClientBuilder.create(token) + .build() + .login() + .block(); + + for(EventListener listener : eventListeners) { + client.on(listener.getEventType()) + .flatMap(listener::execute) + .onErrorResume(listener::handleError) + .subscribe(); + } + + client.onDisconnect().block(); + } + catch ( Exception exception ) { + log.error( "Be sure to use a valid bot token!", exception ); + } + + return client; + } +} diff --git a/discord4j/src/main/java/com/baeldung/discordbot/DiscordBotApplication.java b/discord4j/src/main/java/com/baeldung/discordbot/DiscordBotApplication.java new file mode 100644 index 0000000000..069a36635c --- /dev/null +++ b/discord4j/src/main/java/com/baeldung/discordbot/DiscordBotApplication.java @@ -0,0 +1,12 @@ +package com.baeldung.discordbot; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class DiscordBotApplication { + + public static void main(String[] args) { + SpringApplication.run(DiscordBotApplication.class, args); + } +} diff --git a/discord4j/src/main/java/com/baeldung/discordbot/events/EventListener.java b/discord4j/src/main/java/com/baeldung/discordbot/events/EventListener.java new file mode 100644 index 0000000000..ca4c79de0d --- /dev/null +++ b/discord4j/src/main/java/com/baeldung/discordbot/events/EventListener.java @@ -0,0 +1,19 @@ +package com.baeldung.discordbot.events; + +import discord4j.core.event.domain.Event; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import reactor.core.publisher.Mono; + +public interface EventListener { + + Logger LOG = LoggerFactory.getLogger(EventListener.class); + + Class getEventType(); + Mono execute(T event); + + default Mono handleError(Throwable error) { + LOG.error("Unable to process " + getEventType().getSimpleName(), error); + return Mono.empty(); + } +} diff --git a/discord4j/src/main/java/com/baeldung/discordbot/events/MessageCreateListener.java b/discord4j/src/main/java/com/baeldung/discordbot/events/MessageCreateListener.java new file mode 100644 index 0000000000..f545489804 --- /dev/null +++ b/discord4j/src/main/java/com/baeldung/discordbot/events/MessageCreateListener.java @@ -0,0 +1,19 @@ +package com.baeldung.discordbot.events; + +import discord4j.core.event.domain.message.MessageCreateEvent; +import org.springframework.stereotype.Service; +import reactor.core.publisher.Mono; + +@Service +public class MessageCreateListener extends MessageListener implements EventListener { + + @Override + public Class getEventType() { + return MessageCreateEvent.class; + } + + @Override + public Mono execute(MessageCreateEvent event) { + return processCommand(event.getMessage()); + } +} diff --git a/discord4j/src/main/java/com/baeldung/discordbot/events/MessageListener.java b/discord4j/src/main/java/com/baeldung/discordbot/events/MessageListener.java new file mode 100644 index 0000000000..e1f48468be --- /dev/null +++ b/discord4j/src/main/java/com/baeldung/discordbot/events/MessageListener.java @@ -0,0 +1,19 @@ +package com.baeldung.discordbot.events; + +import discord4j.core.object.entity.Message; +import reactor.core.publisher.Mono; + +public abstract class 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("Things to do today:\n" + + " - write a bot\n" + + " - eat lunch\n" + + " - play a game")) + .then(); + } +} diff --git a/discord4j/src/main/java/com/baeldung/discordbot/events/MessageUpdateListener.java b/discord4j/src/main/java/com/baeldung/discordbot/events/MessageUpdateListener.java new file mode 100644 index 0000000000..62802d4903 --- /dev/null +++ b/discord4j/src/main/java/com/baeldung/discordbot/events/MessageUpdateListener.java @@ -0,0 +1,22 @@ +package com.baeldung.discordbot.events; + +import discord4j.core.event.domain.message.MessageUpdateEvent; +import org.springframework.stereotype.Service; +import reactor.core.publisher.Mono; + +@Service +public class MessageUpdateListener extends MessageListener implements EventListener { + + @Override + public Class getEventType() { + return MessageUpdateEvent.class; + } + + @Override + public Mono execute(MessageUpdateEvent event) { + return Mono.just(event) + .filter(MessageUpdateEvent::isContentChanged) + .flatMap(MessageUpdateEvent::getMessage) + .flatMap(super::processCommand); + } +} diff --git a/discord4j/src/main/resources/application.yml b/discord4j/src/main/resources/application.yml new file mode 100644 index 0000000000..e2079e33b4 --- /dev/null +++ b/discord4j/src/main/resources/application.yml @@ -0,0 +1 @@ +token: 'our-token-here' diff --git a/discord4j/src/test/java/com/baeldung/discordbot/DiscordBotLiveTest.java b/discord4j/src/test/java/com/baeldung/discordbot/DiscordBotLiveTest.java new file mode 100644 index 0000000000..8d9a285748 --- /dev/null +++ b/discord4j/src/test/java/com/baeldung/discordbot/DiscordBotLiveTest.java @@ -0,0 +1,12 @@ +package com.baeldung.discordbot; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +public class DiscordBotLiveTest { + + @Test + public void contextTest() { + } +} diff --git a/pom.xml b/pom.xml index cba7e33b03..6c96d8d77e 100644 --- a/pom.xml +++ b/pom.xml @@ -397,6 +397,7 @@ ddd deeplearning4j + discord4j disruptor dozer drools @@ -909,6 +910,7 @@ ddd deeplearning4j + discord4j disruptor dozer drools