Compare commits
No commits in common. "654aca86cc6c1be827d5a321b20ea182832cd7b1" and "2ab3c5e01dc160d3c0a075d39421cb99ba00d87c" have entirely different histories.
654aca86cc
...
2ab3c5e01d
11 changed files with 23 additions and 39 deletions
13
.env.example
Normal file
13
.env.example
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
# No need to change
|
||||||
|
POSTGRES_DB=dchat
|
||||||
|
# "db" being the name of the postgresql service inside the docker-compose.yml, "5432" is the port on which postgres
|
||||||
|
# listens for new connections and "dchat" is the database name.
|
||||||
|
POSTGRES_URL=jdbc:postgresql://db:5432/dchat
|
||||||
|
|
||||||
|
# Please change
|
||||||
|
DISCORD_API_KEY=<discord-api-key>
|
||||||
|
OPENAI_API_KEY=<openai-api-key>
|
||||||
|
|
||||||
|
# Those values can not change after the first start
|
||||||
|
POSTGRES_USER=<postgres-user>
|
||||||
|
POSTGRES_PASSWORD=<postgres-password>
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -126,6 +126,5 @@ fabric.properties
|
||||||
.idea/caches/build_file_checksums.ser
|
.idea/caches/build_file_checksums.ser
|
||||||
|
|
||||||
.env
|
.env
|
||||||
dchat.properties
|
|
||||||
|
|
||||||
data/
|
data/
|
||||||
|
|
|
@ -46,6 +46,7 @@
|
||||||
<!--Remove unneeded files and symbols to reduce the image size and performance-->
|
<!--Remove unneeded files and symbols to reduce the image size and performance-->
|
||||||
<noHeaderFiles>true</noHeaderFiles>
|
<noHeaderFiles>true</noHeaderFiles>
|
||||||
<noManPages>true</noManPages>
|
<noManPages>true</noManPages>
|
||||||
|
<stripDebug>true</stripDebug>
|
||||||
<!--Compression is not needed since we unzip it in our OCI build-->
|
<!--Compression is not needed since we unzip it in our OCI build-->
|
||||||
<compress>zip-0</compress>
|
<compress>zip-0</compress>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|
|
@ -10,7 +10,6 @@ import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
|
|
||||||
public final class MessageService {
|
public final class MessageService {
|
||||||
|
@ -28,12 +27,12 @@ public final class MessageService {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void process(final String messageContent, final String referencedMessageContent, final String guildId, final String channelId, final String originalMessageId) {
|
public void process(final String messageContent, final String referencedMessageContent, final String guildId, final String channelId, final String originalMessageId) {
|
||||||
final var chatGPTRequest = new ChatGPTRequestBuilder().contextRequest(referencedMessageContent, messageContent, systemMessage);
|
final var chatGPTRequest = new ChatGPTRequestBuilder().contextRequest(referencedMessageContent, messageContent, "system msg");
|
||||||
process(chatGPTRequest, channelId, originalMessageId, guildId);
|
process(chatGPTRequest, channelId, originalMessageId, guildId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void process(final String messageContent, final String guildId, final String channelId, final String originalMessageId) {
|
public void process(final String messageContent, final String guildId, final String channelId, final String originalMessageId) {
|
||||||
final var chatGPTRequest = new ChatGPTRequestBuilder().contextRequest(messageContent, systemMessage);
|
final var chatGPTRequest = new ChatGPTRequestBuilder().contextRequest(messageContent, "system msg");
|
||||||
process(chatGPTRequest, channelId, originalMessageId, guildId);
|
process(chatGPTRequest, channelId, originalMessageId, guildId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,11 +46,6 @@ public final class MessageService {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// FIXME: We should find a solution to not block the main thread without loosing the started thread.
|
executorService.submit(callable);
|
||||||
try {
|
|
||||||
executorService.submit(callable).get();
|
|
||||||
} catch (InterruptedException | ExecutionException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,15 +22,12 @@ public final class DiscordRest {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void postMessage(final String channelId, final Message message) throws IOException, InterruptedException {
|
public void postMessage(final String channelId, final Message message) throws IOException, InterruptedException {
|
||||||
final String data = message.toJson();
|
|
||||||
logger.trace("Submitting new discord message: {}", data);
|
|
||||||
final var uri = URI.create(DISCORD_URL + "/channels/%s/messages".formatted(channelId));
|
final var uri = URI.create(DISCORD_URL + "/channels/%s/messages".formatted(channelId));
|
||||||
final HttpRequest request = HttpRequest.newBuilder()
|
final HttpRequest request = HttpRequest.newBuilder()
|
||||||
.uri(uri)
|
.uri(uri)
|
||||||
.header("Authorization", "Bot " + discordApiKey)
|
.header("Authorization", "Bot " + discordApiKey)
|
||||||
.header("User-Agent", USER_AGENT)
|
.header("User-Agent", USER_AGENT)
|
||||||
.header("Content-Type", "application/json")
|
.POST(HttpRequest.BodyPublishers.ofString(message.toJson()))
|
||||||
.POST(HttpRequest.BodyPublishers.ofString(data))
|
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
final HttpResponse<Void> response = httpClient.send(request, HttpResponse.BodyHandlers.discarding());
|
final HttpResponse<Void> response = httpClient.send(request, HttpResponse.BodyHandlers.discarding());
|
||||||
|
|
|
@ -1,12 +1,8 @@
|
||||||
package de.hhhammer.dchat.discord.ws.connection;
|
package de.hhhammer.dchat.discord.ws.connection;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.net.http.WebSocket;
|
import java.net.http.WebSocket;
|
||||||
|
|
||||||
public final class ResumeConnectionInitiator implements ConnectionInitiator {
|
public final class ResumeConnectionInitiator implements ConnectionInitiator {
|
||||||
private static final Logger logger = LoggerFactory.getLogger(ResumeConnectionInitiator.class);
|
|
||||||
private final String token;
|
private final String token;
|
||||||
private final String sessionId;
|
private final String sessionId;
|
||||||
private final int lastSequence;
|
private final int lastSequence;
|
||||||
|
@ -20,7 +16,6 @@ public final class ResumeConnectionInitiator implements ConnectionInitiator {
|
||||||
@Override
|
@Override
|
||||||
public void initiate(final WebSocket webSocket) {
|
public void initiate(final WebSocket webSocket) {
|
||||||
final String identifyPayload = "{\"op\": 6, \"d\": {\"token\": \"" + token + "\", \"session_id\": \"" + sessionId + "\", \"seq\": " + lastSequence + "}}";
|
final String identifyPayload = "{\"op\": 6, \"d\": {\"token\": \"" + token + "\", \"session_id\": \"" + sessionId + "\", \"seq\": " + lastSequence + "}}";
|
||||||
logger.debug("Resuming connection");
|
|
||||||
webSocket.sendText(identifyPayload, true);
|
webSocket.sendText(identifyPayload, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,7 +68,7 @@ public final class DiscordListener implements WebSocket.Listener {
|
||||||
final String text = optText.get();
|
final String text = optText.get();
|
||||||
final Event event = eventDeserializer.deserialize(text);
|
final Event event = eventDeserializer.deserialize(text);
|
||||||
final int currentSequence = event.sequence();
|
final int currentSequence = event.sequence();
|
||||||
if (currentSequence != 0) lastSeq.set(currentSequence);
|
lastSeq.set(currentSequence);
|
||||||
if (!(event.type() instanceof EventType.Empty)) {
|
if (!(event.type() instanceof EventType.Empty)) {
|
||||||
if (event.type() instanceof EventType.Ready) {
|
if (event.type() instanceof EventType.Ready) {
|
||||||
final JSONObject payload = event.data();
|
final JSONObject payload = event.data();
|
||||||
|
@ -109,7 +109,6 @@ public final class DiscordListener implements WebSocket.Listener {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletionStage<?> onClose(final WebSocket webSocket, final int statusCode, final String reason) {
|
public CompletionStage<?> onClose(final WebSocket webSocket, final int statusCode, final String reason) {
|
||||||
logger.info("Connection closed: {}: {}", statusCode, reason);
|
|
||||||
switch (statusCode) {
|
switch (statusCode) {
|
||||||
case 0, 4000, 4001, 4002, 4005, 4008 ->
|
case 0, 4000, 4001, 4002, 4005, 4008 ->
|
||||||
this.closeEventQueue.add(new CloseEvent.ResumableCloseEvent(this.resumeGatewayUrl.get(), this.sessionId.get(), lastSeq.get()));
|
this.closeEventQueue.add(new CloseEvent.ResumableCloseEvent(this.resumeGatewayUrl.get(), this.sessionId.get(), lastSeq.get()));
|
||||||
|
@ -142,7 +141,6 @@ public final class DiscordListener implements WebSocket.Listener {
|
||||||
final int intSeq = lastSeq.get();
|
final int intSeq = lastSeq.get();
|
||||||
final String stringSeq = intSeq != 0 ? String.valueOf(intSeq) : "null";
|
final String stringSeq = intSeq != 0 ? String.valueOf(intSeq) : "null";
|
||||||
// Send heartbeat
|
// Send heartbeat
|
||||||
logger.debug("Sending heartbeat: {}",stringSeq);
|
|
||||||
webSocket.sendText("{\"op\": 1, \"d\": %s}".formatted(stringSeq), true);
|
webSocket.sendText("{\"op\": 1, \"d\": %s}".formatted(stringSeq), true);
|
||||||
receivedAck.set(false);
|
receivedAck.set(false);
|
||||||
TimeUnit.MILLISECONDS.sleep(heartbeatInterval);
|
TimeUnit.MILLISECONDS.sleep(heartbeatInterval);
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
services:
|
services:
|
||||||
bot:
|
bot:
|
||||||
image: git.hhhammer.de/hamburghammer/dchat/bot:latest
|
image: git.hhhammer.de/hamburghammer/dchat/bot:latest
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
build:
|
build:
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
context: .
|
context: .
|
||||||
|
target: bot
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
|
||||||
DCHAT_CONFIG_FILE: "/opt/dchat/dchat.properties"
|
|
||||||
volumes:
|
|
||||||
- ./dchat.properties:/opt/dchat/dchat.properties:ro
|
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
dchat.discord-api-key=xxx
|
|
||||||
dchat.openai-api-key=xxx
|
|
||||||
dchat.bot-id=xxx
|
|
||||||
# comma separated list
|
|
||||||
dchat.allowed-guild-ids=foo,bar
|
|
||||||
# not allowed to contain "!
|
|
||||||
dchat.system-message=
|
|
|
@ -2,8 +2,6 @@ package de.hhhammer.dchat.openai.rest;
|
||||||
|
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
@ -13,7 +11,6 @@ import java.net.http.HttpResponse;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
|
||||||
public final class ChatGPTService {
|
public final class ChatGPTService {
|
||||||
private static final Logger logger = LoggerFactory.getLogger(ChatGPTService.class);
|
|
||||||
private final String apiKey;
|
private final String apiKey;
|
||||||
private final HttpClient httpClient;
|
private final HttpClient httpClient;
|
||||||
|
|
||||||
|
@ -24,7 +21,6 @@ public final class ChatGPTService {
|
||||||
|
|
||||||
public String submit(final ChatGPTRequest chatGPTRequest) throws IOException, InterruptedException, ResponseException {
|
public String submit(final ChatGPTRequest chatGPTRequest) throws IOException, InterruptedException, ResponseException {
|
||||||
final String data = chatGPTRequest.toJson().toString();
|
final String data = chatGPTRequest.toJson().toString();
|
||||||
logger.trace("Submitting new ChatGPT request: {}", data);
|
|
||||||
final URI uri = URI.create("https://api.openai.com/v1/chat/completions");
|
final URI uri = URI.create("https://api.openai.com/v1/chat/completions");
|
||||||
final HttpRequest request = HttpRequest.newBuilder(uri)
|
final HttpRequest request = HttpRequest.newBuilder(uri)
|
||||||
.POST(HttpRequest.BodyPublishers.ofString(data))
|
.POST(HttpRequest.BodyPublishers.ofString(data))
|
||||||
|
@ -38,7 +34,7 @@ public final class ChatGPTService {
|
||||||
throw new ResponseException("Response status code was not 200: " + response.statusCode());
|
throw new ResponseException("Response status code was not 200: " + response.statusCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
final var responseJson = new JSONObject(response.body());
|
final var responseJson = new JSONObject(response);
|
||||||
final JSONArray choices = responseJson.getJSONArray("choices");
|
final JSONArray choices = responseJson.getJSONArray("choices");
|
||||||
return getResponse(choices);
|
return getResponse(choices);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,5 +5,4 @@ module de.hhhammer.dchat.openai.rest {
|
||||||
|
|
||||||
requires org.json;
|
requires org.json;
|
||||||
requires static org.jetbrains.annotations;
|
requires static org.jetbrains.annotations;
|
||||||
requires org.slf4j;
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue