Compare commits

...

5 commits

Author SHA1 Message Date
7f3ec2276f discord-rest: Add new module for discord rest api interaction 2024-11-15 21:50:36 +01:00
16bcc6fdf3 misc: Make JUnit to a default dependency
Also removes the debug logback dependency from discord-ws since it
can now be tested with the bot package.
2024-11-15 21:04:11 +01:00
355cd01ee3 bot: Add discord websocket constructor
To test the module boundries.
2024-11-12 17:26:39 +01:00
1a21d25861 discord-ws: Remove retry interface from constructor
The interface currently lies in a package which is not exported through
the module system and exporting the package is not a good solution.
2024-11-12 17:24:04 +01:00
1d56ce0511 discord-ws: Restructure for usage with java module system 2024-11-12 17:12:04 +01:00
27 changed files with 161 additions and 81 deletions

View file

@ -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>

View file

@ -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!");
}
}

View 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
View 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>

View file

@ -0,0 +1,7 @@
package de.hhhammer.dchat.discord.rest;
public class Main {
public static void main(String[] args) {
System.out.println("Hello world!");
}
}

View file

@ -0,0 +1,7 @@
module de.hhhammer.dchat.discord.rest {
requires java.net.http;
requires org.json;
requires org.slf4j;
}

View file

@ -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>

View file

@ -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);
}
}

View file

@ -1,4 +1,4 @@
package de.hhhammer.dchat;
package de.hhhammer.dchat.discord.ws;
import org.json.JSONObject;
import org.slf4j.Logger;

View file

@ -0,0 +1,7 @@
package de.hhhammer.dchat.discord.ws;
public interface Retryer {
public int nextRetryInSeconds();
public boolean hasRetriesLeft();
}

View file

@ -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();

View file

@ -1,4 +1,4 @@
package de.hhhammer.dchat;
package de.hhhammer.dchat.discord.ws.connection;
public record ConnectionConfig(String gatewayUrl, ConnectionInitiator connectionInitiator) {
}

View file

@ -1,4 +1,4 @@
package de.hhhammer.dchat;
package de.hhhammer.dchat.discord.ws.connection;
import java.net.http.WebSocket;

View file

@ -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(

View file

@ -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()

View file

@ -1,4 +1,4 @@
package de.hhhammer.dchat;
package de.hhhammer.dchat.discord.ws.connection;
import java.net.http.WebSocket;

View file

@ -1,4 +1,4 @@
package de.hhhammer.dchat;
package de.hhhammer.dchat.discord.ws.connection;
import java.net.http.WebSocket;

View file

@ -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 {

View file

@ -1,4 +1,4 @@
package de.hhhammer.dchat.model;
package de.hhhammer.dchat.discord.ws.connection.event;
import org.json.JSONObject;

View file

@ -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;

View file

@ -1,4 +1,4 @@
package de.hhhammer.dchat.model;
package de.hhhammer.dchat.discord.ws.connection.event;
public sealed interface EventType {
String value();

View file

@ -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;

View file

@ -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();

View 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;
}

View file

@ -1,4 +1,4 @@
package de.hhhammer.dchat;
package de.hhhammer.dchat.discord.ws;
import org.json.JSONObject;
import org.junit.jupiter.api.Test;

View file

@ -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
View file

@ -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>