Compare commits
5 commits
33aeb356a4
...
7f3ec2276f
Author | SHA1 | Date | |
---|---|---|---|
7f3ec2276f | |||
16bcc6fdf3 | |||
355cd01ee3 | |||
1a21d25861 | |||
1d56ce0511 |
27 changed files with 161 additions and 81 deletions
|
@ -15,7 +15,7 @@
|
|||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>de.hhhammer.dchat</groupId>
|
||||
<artifactId>discord</artifactId>
|
||||
<artifactId>discord-ws</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package de.hhhammer.dchat.bot;
|
||||
|
||||
import de.hhhammer.dchat.discord.ws.EventHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -7,6 +8,12 @@ public final class App {
|
|||
private static final Logger logger = LoggerFactory.getLogger(App.class);
|
||||
|
||||
public static void main(final String[] args) {
|
||||
logger.error("Currently not implemented!");
|
||||
final String discordApiKey = System.getenv("DISCORD_API_KEY");
|
||||
if (discordApiKey == null) {
|
||||
logger.error("Missing environment variables: DISCORD_API_KEY");
|
||||
System.exit(1);
|
||||
}
|
||||
final var eventHandler = new EventHandler.LogEventHandler();
|
||||
logger.error("Currently not implemented!");
|
||||
}
|
||||
}
|
||||
|
|
4
bot/src/main/java/module-info.java
Normal file
4
bot/src/main/java/module-info.java
Normal file
|
@ -0,0 +1,4 @@
|
|||
module de.hhhammer.dchat.bot {
|
||||
requires de.hhhammer.dchat.discord.ws;
|
||||
requires org.slf4j;
|
||||
}
|
23
discord-rest/pom.xml
Normal file
23
discord-rest/pom.xml
Normal file
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>de.hhhammer.dchat</groupId>
|
||||
<artifactId>dchat</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>discord-rest</artifactId>
|
||||
<name>discord-rest</name>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.json</groupId>
|
||||
<artifactId>json</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -0,0 +1,7 @@
|
|||
package de.hhhammer.dchat.discord.rest;
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Hello world!");
|
||||
}
|
||||
}
|
7
discord-rest/src/main/java/module-info.java
Normal file
7
discord-rest/src/main/java/module-info.java
Normal file
|
@ -0,0 +1,7 @@
|
|||
module de.hhhammer.dchat.discord.rest {
|
||||
|
||||
requires java.net.http;
|
||||
|
||||
requires org.json;
|
||||
requires org.slf4j;
|
||||
}
|
|
@ -7,8 +7,8 @@
|
|||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>discord</artifactId>
|
||||
<name>discord</name>
|
||||
<artifactId>discord-ws</artifactId>
|
||||
<name>discord-ws</name>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
|
@ -17,14 +17,5 @@
|
|||
<groupId>org.json</groupId>
|
||||
<artifactId>json</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -0,0 +1,37 @@
|
|||
package de.hhhammer.dchat.discord.ws;
|
||||
|
||||
import de.hhhammer.dchat.discord.ws.connection.BackoffRetryer;
|
||||
import de.hhhammer.dchat.discord.ws.connection.ConnectionManager;
|
||||
import de.hhhammer.dchat.discord.ws.connection.Connector;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public final class DiscordWebSocket {
|
||||
private static final Logger logger = LoggerFactory.getLogger(DiscordWebSocket.class);
|
||||
private static final String DISCORD_API_URL = "wss://gateway.discord.gg/?v=10&encoding=json";
|
||||
private final String discordApiKey;
|
||||
private final EventHandler eventHandler;
|
||||
private final Retryer retryer;
|
||||
|
||||
public DiscordWebSocket(final String discordApiKey, final EventHandler eventHandler) {
|
||||
this.discordApiKey = discordApiKey;
|
||||
this.eventHandler = eventHandler;
|
||||
this.retryer = new BackoffRetryer();
|
||||
}
|
||||
|
||||
public static void main(final String[] args) throws InterruptedException {
|
||||
final String discordApiKey = System.getenv("DISCORD_API_KEY");
|
||||
if (discordApiKey == null) {
|
||||
logger.error("Missing environment variables: DISCORD_API_KEY");
|
||||
System.exit(1);
|
||||
}
|
||||
final var eventHandler = new EventHandler.LogEventHandler();
|
||||
final var instance = new DiscordWebSocket(discordApiKey, eventHandler);
|
||||
instance.start();
|
||||
}
|
||||
|
||||
public void start() {
|
||||
final var connector = new Connector(eventHandler);
|
||||
final var connectionManager = new ConnectionManager(DISCORD_API_URL, discordApiKey, retryer);
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package de.hhhammer.dchat;
|
||||
package de.hhhammer.dchat.discord.ws;
|
||||
|
||||
import org.json.JSONObject;
|
||||
import org.slf4j.Logger;
|
|
@ -0,0 +1,7 @@
|
|||
package de.hhhammer.dchat.discord.ws;
|
||||
|
||||
public interface Retryer {
|
||||
public int nextRetryInSeconds();
|
||||
|
||||
public boolean hasRetriesLeft();
|
||||
}
|
|
@ -1,12 +1,22 @@
|
|||
package de.hhhammer.dchat;
|
||||
package de.hhhammer.dchat.discord.ws.connection;
|
||||
|
||||
import de.hhhammer.dchat.discord.ws.Retryer;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public final class Retryer {
|
||||
private static final int maxRetries = 5;
|
||||
public final class BackoffRetryer implements Retryer {
|
||||
private static final int delayInSeconds = 10;
|
||||
private static final int backoffMultiplier = 2;
|
||||
private final AtomicInteger tries = new AtomicInteger();
|
||||
private final int maxRetries;
|
||||
|
||||
public BackoffRetryer(final int maxRetries) {
|
||||
this.maxRetries = maxRetries;
|
||||
}
|
||||
|
||||
public BackoffRetryer() {
|
||||
this(5);
|
||||
}
|
||||
|
||||
public int nextRetryInSeconds() {
|
||||
final int currentTry = tries.getAndIncrement();
|
|
@ -1,4 +1,4 @@
|
|||
package de.hhhammer.dchat;
|
||||
package de.hhhammer.dchat.discord.ws.connection;
|
||||
|
||||
public record ConnectionConfig(String gatewayUrl, ConnectionInitiator connectionInitiator) {
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package de.hhhammer.dchat;
|
||||
package de.hhhammer.dchat.discord.ws.connection;
|
||||
|
||||
import java.net.http.WebSocket;
|
||||
|
|
@ -1,9 +1,10 @@
|
|||
package de.hhhammer.dchat;
|
||||
package de.hhhammer.dchat.discord.ws.connection;
|
||||
|
||||
import de.hhhammer.dchat.model.CloseEvent;
|
||||
import de.hhhammer.dchat.discord.ws.Retryer;
|
||||
import de.hhhammer.dchat.discord.ws.connection.event.CloseEvent;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.function.Function;
|
||||
|
||||
|
||||
public final class ConnectionManager {
|
||||
private final String initGatewayUrl;
|
||||
|
@ -16,7 +17,7 @@ public final class ConnectionManager {
|
|||
this.retryer = retryer;
|
||||
}
|
||||
|
||||
public void start(final Function<ConnectionConfig, CloseEvent> connector) throws InterruptedException {
|
||||
public void start(final Connector connector) throws InterruptedException {
|
||||
while (retryer.hasRetriesLeft()) {
|
||||
connect(connector);
|
||||
final int reconnectDelayInSeconds = retryer.nextRetryInSeconds();
|
||||
|
@ -24,11 +25,11 @@ public final class ConnectionManager {
|
|||
}
|
||||
}
|
||||
|
||||
private void connect(final Function<ConnectionConfig, CloseEvent> connector) {
|
||||
private void connect(final Connector connector) {
|
||||
ConnectionConfig mutConnectionConfig = new ConnectionConfig(initGatewayUrl, new IdendificationConnectionInitiator(token));
|
||||
boolean isResumable = true;
|
||||
while (isResumable) {
|
||||
final CloseEvent closeEvent = connector.apply(mutConnectionConfig);
|
||||
final CloseEvent closeEvent = connector.connect(mutConnectionConfig);
|
||||
isResumable = switch (closeEvent) {
|
||||
case CloseEvent.ResumableCloseEvent resumableCloseEvent -> {
|
||||
mutConnectionConfig = new ConnectionConfig(
|
|
@ -1,21 +1,21 @@
|
|||
package de.hhhammer.dchat;
|
||||
package de.hhhammer.dchat.discord.ws.connection;
|
||||
|
||||
import de.hhhammer.dchat.model.CloseEvent;
|
||||
import de.hhhammer.dchat.discord.ws.EventHandler;
|
||||
import de.hhhammer.dchat.discord.ws.connection.event.CloseEvent;
|
||||
import de.hhhammer.dchat.discord.ws.connection.listener.DiscordListener;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.http.HttpClient;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.function.Function;
|
||||
|
||||
public final class Connector implements Function<ConnectionConfig, CloseEvent> {
|
||||
public final class Connector {
|
||||
private final EventHandler eventHandler;
|
||||
|
||||
public Connector(final EventHandler eventHandler) {
|
||||
this.eventHandler = eventHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CloseEvent apply(final ConnectionConfig connectionConfig) {
|
||||
public CloseEvent connect(final ConnectionConfig connectionConfig) {
|
||||
final ArrayBlockingQueue<CloseEvent> closeEventQueue = new ArrayBlockingQueue<>(1);
|
||||
try (final HttpClient client = HttpClient.newHttpClient()) {
|
||||
client.newWebSocketBuilder()
|
|
@ -1,4 +1,4 @@
|
|||
package de.hhhammer.dchat;
|
||||
package de.hhhammer.dchat.discord.ws.connection;
|
||||
|
||||
import java.net.http.WebSocket;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package de.hhhammer.dchat;
|
||||
package de.hhhammer.dchat.discord.ws.connection;
|
||||
|
||||
import java.net.http.WebSocket;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package de.hhhammer.dchat.model;
|
||||
package de.hhhammer.dchat.discord.ws.connection.event;
|
||||
|
||||
public sealed interface CloseEvent {
|
||||
record UnresumableCloseEvent() implements CloseEvent {
|
|
@ -1,4 +1,4 @@
|
|||
package de.hhhammer.dchat.model;
|
||||
package de.hhhammer.dchat.discord.ws.connection.event;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
|
@ -1,7 +1,5 @@
|
|||
package de.hhhammer.dchat;
|
||||
package de.hhhammer.dchat.discord.ws.connection.event;
|
||||
|
||||
import de.hhhammer.dchat.model.Event;
|
||||
import de.hhhammer.dchat.model.EventType;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package de.hhhammer.dchat.model;
|
||||
package de.hhhammer.dchat.discord.ws.connection.event;
|
||||
|
||||
public sealed interface EventType {
|
||||
String value();
|
|
@ -1,8 +1,11 @@
|
|||
package de.hhhammer.dchat;
|
||||
package de.hhhammer.dchat.discord.ws.connection.listener;
|
||||
|
||||
import de.hhhammer.dchat.model.CloseEvent;
|
||||
import de.hhhammer.dchat.model.Event;
|
||||
import de.hhhammer.dchat.model.EventType;
|
||||
import de.hhhammer.dchat.discord.ws.EventHandler;
|
||||
import de.hhhammer.dchat.discord.ws.connection.ConnectionInitiator;
|
||||
import de.hhhammer.dchat.discord.ws.connection.event.CloseEvent;
|
||||
import de.hhhammer.dchat.discord.ws.connection.event.Event;
|
||||
import de.hhhammer.dchat.discord.ws.connection.event.EventDeserializer;
|
||||
import de.hhhammer.dchat.discord.ws.connection.event.EventType;
|
||||
import org.json.JSONObject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -30,11 +33,11 @@ public final class DiscordListener implements WebSocket.Listener {
|
|||
private final EventHandler eventHandler;
|
||||
private final BlockingQueue<CloseEvent> closeEventQueue;
|
||||
|
||||
public DiscordListener(final TextCollector textCollector,
|
||||
final EventDeserializer eventDeserializer,
|
||||
final ConnectionInitiator connectionInitiator,
|
||||
final EventHandler eventHandler,
|
||||
final BlockingQueue<CloseEvent> closeEventQueue) {
|
||||
DiscordListener(final TextCollector textCollector,
|
||||
final EventDeserializer eventDeserializer,
|
||||
final ConnectionInitiator connectionInitiator,
|
||||
final EventHandler eventHandler,
|
||||
final BlockingQueue<CloseEvent> closeEventQueue) {
|
||||
this.textCollector = textCollector;
|
||||
this.eventDeserializer = eventDeserializer;
|
||||
this.connectionInitiator = connectionInitiator;
|
|
@ -1,11 +1,11 @@
|
|||
package de.hhhammer.dchat;
|
||||
package de.hhhammer.dchat.discord.ws.connection.listener;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public final class TextCollector {
|
||||
final class TextCollector {
|
||||
private static final Logger logger = LoggerFactory.getLogger(TextCollector.class);
|
||||
private final StringBuilder stringBuilder = new StringBuilder();
|
||||
|
8
discord-ws/src/main/java/module-info.java
Normal file
8
discord-ws/src/main/java/module-info.java
Normal file
|
@ -0,0 +1,8 @@
|
|||
module de.hhhammer.dchat.discord.ws {
|
||||
exports de.hhhammer.dchat.discord.ws;
|
||||
|
||||
requires java.net.http;
|
||||
|
||||
requires org.json;
|
||||
requires org.slf4j;
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package de.hhhammer.dchat;
|
||||
package de.hhhammer.dchat.discord.ws;
|
||||
|
||||
import org.json.JSONObject;
|
||||
import org.junit.jupiter.api.Test;
|
|
@ -1,22 +0,0 @@
|
|||
package de.hhhammer.dchat;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public final class DiscordBotWebSocket {
|
||||
private static final Logger logger = LoggerFactory.getLogger(DiscordBotWebSocket.class);
|
||||
private static final String DISCORD_API_URL = "wss://gateway.discord.gg/?v=10&encoding=json";
|
||||
|
||||
public static void main(final String[] args) throws InterruptedException {
|
||||
final String discordApiKey = System.getenv("DISCORD_API_KEY");
|
||||
if (discordApiKey == null) {
|
||||
logger.error("Missing environment variables: DISCORD_API_KEY");
|
||||
System.exit(1);
|
||||
}
|
||||
final var eventHandler = new EventHandler.LogEventHandler();
|
||||
final var connector = new Connector(eventHandler);
|
||||
final var retryer = new Retryer();
|
||||
final var connectionManager = new ConnectionManager(DISCORD_API_URL, discordApiKey, retryer);
|
||||
connectionManager.start(connector);
|
||||
}
|
||||
}
|
15
pom.xml
15
pom.xml
|
@ -42,6 +42,11 @@
|
|||
<groupId>org.jetbrains</groupId>
|
||||
<artifactId>annotations</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
|
@ -76,13 +81,6 @@
|
|||
<artifactId>json</artifactId>
|
||||
<version>20240303</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson</groupId>
|
||||
<artifactId>jackson-bom</artifactId>
|
||||
<version>2.18.1</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
<build>
|
||||
|
@ -98,6 +96,7 @@
|
|||
</build>
|
||||
<modules>
|
||||
<module>bot</module>
|
||||
<module>discord</module>
|
||||
<module>discord-ws</module>
|
||||
<module>discord-rest</module>
|
||||
</modules>
|
||||
</project>
|
Loading…
Reference in a new issue