Compare commits
No commits in common. "a398641172fae4755781cc7d46223c1c36dfa5e6" and "8b2422dd1b5ae461dd8ebed7f5936fc6c7f96942" have entirely different histories.
a398641172
...
8b2422dd1b
68 changed files with 553 additions and 6084 deletions
|
@ -1,13 +1,3 @@
|
||||||
*
|
*
|
||||||
!src/
|
!src/
|
||||||
!pom.xml
|
!pom.xml
|
||||||
!ui/package*.json
|
|
||||||
!ui/postcss.config.js
|
|
||||||
!ui/tailwind.config.js
|
|
||||||
!ui/env.d..ts
|
|
||||||
!ui/vite.config.ts
|
|
||||||
!ui/tsconfig.json
|
|
||||||
!ui/tsconfig.node.json
|
|
||||||
!ui/index.html
|
|
||||||
!ui/public/
|
|
||||||
!ui/src/
|
|
14
Dockerfile
14
Dockerfile
|
@ -1,4 +1,4 @@
|
||||||
# Stage 1: Build java application
|
# Stage 1: Build the application
|
||||||
FROM docker.io/maven:3.9-eclipse-temurin-19 AS maven
|
FROM docker.io/maven:3.9-eclipse-temurin-19 AS maven
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY pom.xml .
|
COPY pom.xml .
|
||||||
|
@ -7,19 +7,9 @@ RUN mvn package
|
||||||
COPY src/ /app/src/
|
COPY src/ /app/src/
|
||||||
RUN mvn package
|
RUN mvn package
|
||||||
|
|
||||||
# Stage 2: Build vuejs application
|
# Stage 2: Create the jlink app
|
||||||
FROM docker.io/node:18-slim AS vuejs
|
|
||||||
WORKDIR /app
|
|
||||||
COPY ./ui/package* .
|
|
||||||
RUN npm ci
|
|
||||||
COPY ./ui .
|
|
||||||
RUN npm run build-only
|
|
||||||
|
|
||||||
# Stage 3: Create the jlink app
|
|
||||||
FROM docker.io/eclipse-temurin:19-jdk
|
FROM docker.io/eclipse-temurin:19-jdk
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY --from=maven /app/target/dchat-*-fat.jar /app/dchat.jar
|
COPY --from=maven /app/target/dchat-*-fat.jar /app/dchat.jar
|
||||||
COPY --from=vuejs /app/dist /app/ui/dist
|
|
||||||
|
|
||||||
EXPOSE 8080
|
|
||||||
CMD ["java", "--enable-preview", "-jar", "/app/dchat.jar"]
|
CMD ["java", "--enable-preview", "-jar", "/app/dchat.jar"]
|
||||||
|
|
|
@ -22,6 +22,12 @@ and navigate into it.
|
||||||
Change the environment variable inside the `docker-compose.yml`.
|
Change the environment variable inside the `docker-compose.yml`.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
|
podman-compose pull
|
||||||
|
podman-compose start db
|
||||||
|
podman cp schema.sql dchat_db_1:/schema.sql
|
||||||
|
podman exec -it dchat_db_1 /bin/bash
|
||||||
|
psql --user dchat dchat < schema.sql
|
||||||
|
exit
|
||||||
podman-compose up -d
|
podman-compose up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,8 @@ services:
|
||||||
- POSTGRES_PASSWORD=<postgres-password>
|
- POSTGRES_PASSWORD=<postgres-password>
|
||||||
- POSTGRES_URL=jdbc:postgresql://db:5432/dchat
|
- POSTGRES_URL=jdbc:postgresql://db:5432/dchat
|
||||||
- API_PORT=8080
|
- API_PORT=8080
|
||||||
|
- API_USERNAME=<api-username>
|
||||||
|
- API_PASSWORD=<api-password>
|
||||||
db:
|
db:
|
||||||
image: docker.io/postgres:15-alpine
|
image: docker.io/postgres:15-alpine
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
2
pom.xml
2
pom.xml
|
@ -40,7 +40,7 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.javalin</groupId>
|
<groupId>io.javalin</groupId>
|
||||||
<artifactId>javalin</artifactId>
|
<artifactId>javalin</artifactId>
|
||||||
<version>5.5.0</version>
|
<version>5.4.2</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- logging -->
|
<!-- logging -->
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|
|
@ -86,39 +86,4 @@ BEGIN;
|
||||||
ALTER TABLE user_configs
|
ALTER TABLE user_configs
|
||||||
ADD COLUMN IF NOT EXISTS context_length INT NOT NULL DEFAULT 5;
|
ADD COLUMN IF NOT EXISTS context_length INT NOT NULL DEFAULT 5;
|
||||||
|
|
||||||
COMMIT;
|
COMMIT
|
||||||
|
|
||||||
-- Add time to config to know when it was added
|
|
||||||
BEGIN;
|
|
||||||
|
|
||||||
ALTER TABLE server_configs
|
|
||||||
ADD COLUMN IF NOT EXISTS time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP;
|
|
||||||
|
|
||||||
ALTER TABLE user_configs
|
|
||||||
ADD COLUMN IF NOT EXISTS time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP;
|
|
||||||
|
|
||||||
COMMIT;
|
|
||||||
|
|
||||||
-- Remove obsolete allowed tables that are being replaced the configs tables
|
|
||||||
BEGIN;
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS allowed_servers;
|
|
||||||
DROP TABLE IF EXISTS allowed_users;
|
|
||||||
|
|
||||||
COMMIT;
|
|
||||||
|
|
||||||
BEGIN;
|
|
||||||
|
|
||||||
ALTER TABLE server_configs
|
|
||||||
ALTER COLUMN server_id TYPE text USING server_id::text;
|
|
||||||
|
|
||||||
ALTER TABLE server_messages
|
|
||||||
ALTER COLUMN server_id TYPE text USING server_id::text;
|
|
||||||
|
|
||||||
ALTER TABLE user_configs
|
|
||||||
ALTER COLUMN user_id TYPE text USING user_id::text;
|
|
||||||
|
|
||||||
ALTER TABLE user_messages
|
|
||||||
ALTER COLUMN user_id TYPE text USING user_id::text;
|
|
||||||
|
|
||||||
COMMIT;
|
|
|
@ -1,36 +0,0 @@
|
||||||
package de.hhhammer.dchat;
|
|
||||||
|
|
||||||
import de.hhhammer.dchat.migration.DBMigrationException;
|
|
||||||
import de.hhhammer.dchat.migration.MigrationExecutor;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
public class DBMigrator implements Runnable {
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(DBMigrator.class);
|
|
||||||
private final MigrationExecutor migrationExecutor;
|
|
||||||
private final String resourcePath;
|
|
||||||
|
|
||||||
public DBMigrator(MigrationExecutor migrationExecutor, String resourcePath) {
|
|
||||||
this.migrationExecutor = migrationExecutor;
|
|
||||||
this.resourcePath = resourcePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
logger.info("Starting db migration");
|
|
||||||
ClassLoader classLoader = getClass().getClassLoader();
|
|
||||||
try (InputStream inputStream = classLoader.getResourceAsStream(this.resourcePath)) {
|
|
||||||
if (inputStream == null) {
|
|
||||||
logger.error("Migration file not found: " + resourcePath);
|
|
||||||
throw new RuntimeException("Migration file not found");
|
|
||||||
}
|
|
||||||
migrationExecutor.migrate(inputStream);
|
|
||||||
} catch (IOException | DBMigrationException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
logger.info("Finished migration");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -56,7 +56,7 @@ public class DiscordBot implements Runnable {
|
||||||
if (server.isEmpty()) {
|
if (server.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var tokens = this.serverDBService.tokensOfLast30Days(String.valueOf(server.get().getId()));
|
var tokens = this.serverDBService.tokensOfLast30Days(server.get().getId());
|
||||||
interactionOriginalResponseUpdater.setContent("" + tokens).update();
|
interactionOriginalResponseUpdater.setContent("" + tokens).update();
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -2,26 +2,22 @@ package de.hhhammer.dchat;
|
||||||
|
|
||||||
import de.hhhammer.dchat.db.ServerDBService;
|
import de.hhhammer.dchat.db.ServerDBService;
|
||||||
import de.hhhammer.dchat.db.UserDBService;
|
import de.hhhammer.dchat.db.UserDBService;
|
||||||
import de.hhhammer.dchat.migration.MigrationExecutor;
|
|
||||||
import de.hhhammer.dchat.openai.ChatGPTService;
|
import de.hhhammer.dchat.openai.ChatGPTService;
|
||||||
|
import de.hhhammer.dchat.web.JavalinConfig;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.net.http.HttpClient;
|
import java.net.http.HttpClient;
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
public class Main {
|
public class Main {
|
||||||
private static final Logger logger = LoggerFactory.getLogger(Main.class);
|
private static final Logger logger = LoggerFactory.getLogger(Main.class);
|
||||||
private static final String DB_MIGRATION_PATH = "db/schema.sql";
|
|
||||||
private final DiscordBot discordBot;
|
private final DiscordBot discordBot;
|
||||||
private final WebAPI webAPI;
|
private final WebAPI webAPI;
|
||||||
private final DBMigrator dbMigrator;
|
|
||||||
|
|
||||||
public Main(DiscordBot discordBot, WebAPI webAPI, DBMigrator dbMigrator) {
|
public Main(DiscordBot discordBot, WebAPI webAPI) {
|
||||||
this.discordBot = discordBot;
|
this.discordBot = discordBot;
|
||||||
this.webAPI = webAPI;
|
this.webAPI = webAPI;
|
||||||
this.dbMigrator = dbMigrator;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -43,8 +39,13 @@ public class Main {
|
||||||
logger.error("Missing environment variables: POSTGRES_USER and/or POSTGRES_PASSWORD and/or POSTGRES_URL");
|
logger.error("Missing environment variables: POSTGRES_USER and/or POSTGRES_PASSWORD and/or POSTGRES_URL");
|
||||||
System.exit(1);
|
System.exit(1);
|
||||||
}
|
}
|
||||||
|
String apiUsername = System.getenv("API_USERNAME");
|
||||||
String apiPortStr = System.getenv("API_PORT") != null ? System.getenv("API_PORT") : "8080";
|
String apiPassword = System.getenv("API_PASSWORD");
|
||||||
|
if (apiUsername == null || apiPassword == null) {
|
||||||
|
logger.error("Missing environment variables: API_USERNAME and/or API_PASSWORD");
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
String apiPortStr = System.getenv("PAI_PORT") != null ? System.getenv("API_PORT") : "8080";
|
||||||
int apiPort = Integer.parseInt(apiPortStr);
|
int apiPort = Integer.parseInt(apiPortStr);
|
||||||
|
|
||||||
var chatGPTService = new ChatGPTService(openaiApiKey, HttpClient.newHttpClient());
|
var chatGPTService = new ChatGPTService(openaiApiKey, HttpClient.newHttpClient());
|
||||||
|
@ -52,20 +53,16 @@ public class Main {
|
||||||
var userDBService = new UserDBService(postgresUrl, postgresUser, postgresPassword);
|
var userDBService = new UserDBService(postgresUrl, postgresUser, postgresPassword);
|
||||||
|
|
||||||
var discordBot = new DiscordBot(serverDBService, userDBService, chatGPTService, discordApiKey);
|
var discordBot = new DiscordBot(serverDBService, userDBService, chatGPTService, discordApiKey);
|
||||||
var webAPI = new WebAPI(serverDBService, userDBService, apiPort);
|
var javalinConfig = new JavalinConfig(apiPort, apiUsername, apiPassword);
|
||||||
var dbMigrator = new DBMigrator(new MigrationExecutor(postgresUrl, postgresUser, postgresPassword), DB_MIGRATION_PATH);
|
var webAPI = new WebAPI(serverDBService, userDBService, javalinConfig);
|
||||||
new Main(discordBot, webAPI, dbMigrator).run();
|
new Main(discordBot, webAPI).run();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run() {
|
public void run() {
|
||||||
logger.info("Starting services...");
|
logger.info("Starting services...");
|
||||||
try (var executor = Executors.newFixedThreadPool(2)) {
|
try (var executor = Executors.newFixedThreadPool(2)) {
|
||||||
var migrationResult = executor.submit(dbMigrator);
|
|
||||||
migrationResult.get();
|
|
||||||
executor.submit(discordBot);
|
executor.submit(discordBot);
|
||||||
executor.submit(webAPI);
|
executor.submit(webAPI);
|
||||||
} catch (ExecutionException | InterruptedException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,11 +2,13 @@ package de.hhhammer.dchat;
|
||||||
|
|
||||||
import de.hhhammer.dchat.db.ServerDBService;
|
import de.hhhammer.dchat.db.ServerDBService;
|
||||||
import de.hhhammer.dchat.db.UserDBService;
|
import de.hhhammer.dchat.db.UserDBService;
|
||||||
|
import de.hhhammer.dchat.web.JavalinConfig;
|
||||||
|
import de.hhhammer.dchat.web.server.AllowedCrudHandler;
|
||||||
import de.hhhammer.dchat.web.server.ConfigCrudHandler;
|
import de.hhhammer.dchat.web.server.ConfigCrudHandler;
|
||||||
|
import de.hhhammer.dchat.web.user.AllowedUserCrudHandler;
|
||||||
import de.hhhammer.dchat.web.user.ConfigUserCrudHandler;
|
import de.hhhammer.dchat.web.user.ConfigUserCrudHandler;
|
||||||
import io.javalin.Javalin;
|
import io.javalin.Javalin;
|
||||||
import io.javalin.http.HttpStatus;
|
import io.javalin.http.HttpStatus;
|
||||||
import io.javalin.http.staticfiles.Location;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -17,12 +19,12 @@ public class WebAPI implements Runnable {
|
||||||
private static final Logger logger = LoggerFactory.getLogger(WebAPI.class);
|
private static final Logger logger = LoggerFactory.getLogger(WebAPI.class);
|
||||||
private final ServerDBService serverDBService;
|
private final ServerDBService serverDBService;
|
||||||
private final UserDBService userDBService;
|
private final UserDBService userDBService;
|
||||||
private final int port;
|
private final JavalinConfig javalinConfig;
|
||||||
|
|
||||||
public WebAPI(ServerDBService serverDBService, UserDBService userDBService, int port) {
|
public WebAPI(ServerDBService serverDBService, UserDBService userDBService, JavalinConfig javalinConfig) {
|
||||||
this.serverDBService = serverDBService;
|
this.serverDBService = serverDBService;
|
||||||
this.userDBService = userDBService;
|
this.userDBService = userDBService;
|
||||||
this.port = port;
|
this.javalinConfig = javalinConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -32,10 +34,17 @@ public class WebAPI implements Runnable {
|
||||||
config.plugins.enableDevLogging();
|
config.plugins.enableDevLogging();
|
||||||
config.http.prefer405over404 = true; // return 405 instead of 404 if path is mapped to different HTTP method
|
config.http.prefer405over404 = true; // return 405 instead of 404 if path is mapped to different HTTP method
|
||||||
config.http.defaultContentType = "application/json";
|
config.http.defaultContentType = "application/json";
|
||||||
config.staticFiles.add(staticFileConfig -> {
|
config.accessManager((handler, context, set) -> {
|
||||||
staticFileConfig.hostedPath = "/";
|
var creds = context.basicAuthCredentials();
|
||||||
staticFileConfig.location = Location.EXTERNAL;
|
if (creds == null) {
|
||||||
staticFileConfig.directory = "./ui/dist/";
|
context.status(HttpStatus.UNAUTHORIZED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!javalinConfig.username().equals(creds.getUsername()) || !javalinConfig.password().equals(creds.getPassword())) {
|
||||||
|
context.status(HttpStatus.UNAUTHORIZED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
handler.handle(context);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
||||||
|
@ -46,28 +55,22 @@ public class WebAPI implements Runnable {
|
||||||
event.serverStopping(() -> logger.info("Stopping web service"));
|
event.serverStopping(() -> logger.info("Stopping web service"));
|
||||||
event.serverStopped(() -> logger.info("Stopped web service"));
|
event.serverStopped(() -> logger.info("Stopped web service"));
|
||||||
});
|
});
|
||||||
app.before(ctx -> {
|
|
||||||
ctx.header("Access-Control-Allow-Origin", "*");
|
app.get("/", ctx -> ctx.result("""
|
||||||
ctx.header("Access-Control-Allow-Methods", "*");
|
{ "message": "Hello World"}
|
||||||
});
|
"""));
|
||||||
app.after(ctx -> {
|
|
||||||
if (!ctx.path().startsWith("/api") && (ctx.status().equals(HttpStatus.NOT_FOUND) || ctx.status().equals(HttpStatus.METHOD_NOT_ALLOWED))) {
|
|
||||||
ctx.redirect("/index.html");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
app.options("*", ctx -> ctx.status(HttpStatus.OK));
|
|
||||||
|
|
||||||
app.routes(() -> {
|
app.routes(() -> {
|
||||||
path("api", () -> {
|
path("server", () -> {
|
||||||
path("servers", () -> {
|
crud("allowed/{id}", new AllowedCrudHandler(this.serverDBService));
|
||||||
crud("configs/{id}", new ConfigCrudHandler(this.serverDBService));
|
crud("configs/{id}", new ConfigCrudHandler(this.serverDBService));
|
||||||
});
|
});
|
||||||
path("users", () -> {
|
path("user", () -> {
|
||||||
|
crud("allowed/{id}", new AllowedUserCrudHandler(this.userDBService));
|
||||||
crud("configs/{id}", new ConfigUserCrudHandler(this.userDBService));
|
crud("configs/{id}", new ConfigUserCrudHandler(this.userDBService));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
app.start(this.port);
|
app.start(this.javalinConfig.port());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package de.hhhammer.dchat.db;
|
package de.hhhammer.dchat.db;
|
||||||
|
|
||||||
|
import de.hhhammer.dchat.db.models.server.AllowedServer;
|
||||||
import de.hhhammer.dchat.db.models.server.ServerConfig;
|
import de.hhhammer.dchat.db.models.server.ServerConfig;
|
||||||
import de.hhhammer.dchat.db.models.server.ServerMessage;
|
import de.hhhammer.dchat.db.models.server.ServerMessage;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -24,7 +25,116 @@ public class ServerDBService {
|
||||||
this.password = password;
|
this.password = password;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<ServerConfig> getConfig(String serverId) {
|
public boolean isAllowed(long serverId) {
|
||||||
|
var getAllowedServerSql = """
|
||||||
|
SELECT * FROM allowed_servers WHERE server_id = ?
|
||||||
|
""";
|
||||||
|
try (Connection con = DriverManager.getConnection(this.jdbcConnectionString, this.username, this.password);
|
||||||
|
PreparedStatement pstmt = con.prepareStatement(getAllowedServerSql)
|
||||||
|
) {
|
||||||
|
pstmt.setLong(1, serverId);
|
||||||
|
ResultSet result = pstmt.executeQuery();
|
||||||
|
Iterable<AllowedServer> iterable = () -> new ResultSetIterator<>(result, new AllowedServer.AllowedServerResultSetTransformer());
|
||||||
|
return StreamSupport.stream(iterable.spliterator(), false).count() == 1;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
logger.error("Searching for allowed server with id: " + serverId, e);
|
||||||
|
} catch (ResultSetIteratorException e) {
|
||||||
|
logger.error("Iterating over AllowedServer ResultSet for server with id: " + serverId, e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<AllowedServer> getAllowedBy(long id) throws DBException {
|
||||||
|
var getAllowedServerSql = """
|
||||||
|
SELECT * FROM allowed_servers WHERE id = ?
|
||||||
|
""";
|
||||||
|
try (Connection con = DriverManager.getConnection(this.jdbcConnectionString, this.username, this.password);
|
||||||
|
PreparedStatement pstmt = con.prepareStatement(getAllowedServerSql)
|
||||||
|
) {
|
||||||
|
pstmt.setLong(1, id);
|
||||||
|
ResultSet result = pstmt.executeQuery();
|
||||||
|
Iterable<AllowedServer> iterable = () -> new ResultSetIterator<>(result, new AllowedServer.AllowedServerResultSetTransformer());
|
||||||
|
return StreamSupport.stream(iterable.spliterator(), false).findFirst();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new DBException("Not found allowed server entry with id: " + id, e);
|
||||||
|
} catch (ResultSetIteratorException e) {
|
||||||
|
throw new DBException("Iterating over AllowedServer ResultSet searching for id: " + id, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<AllowedServer> getAllAllowed() throws DBException {
|
||||||
|
var getAllowedServerSql = """
|
||||||
|
SELECT * FROM allowed_servers
|
||||||
|
""";
|
||||||
|
try (Connection con = DriverManager.getConnection(this.jdbcConnectionString, this.username, this.password);
|
||||||
|
PreparedStatement pstmt = con.prepareStatement(getAllowedServerSql)
|
||||||
|
) {
|
||||||
|
ResultSet result = pstmt.executeQuery();
|
||||||
|
Iterable<AllowedServer> iterable = () -> new ResultSetIterator<>(result, new AllowedServer.AllowedServerResultSetTransformer());
|
||||||
|
return StreamSupport.stream(iterable.spliterator(), false).toList();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new DBException("Not found allowed server entries", e);
|
||||||
|
} catch (ResultSetIteratorException e) {
|
||||||
|
throw new DBException("Iterating over AllowedServer ResultSet", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addAllowed(AllowedServer.NewAllowedServer newAllowedServer) throws DBException {
|
||||||
|
var insertAllowedServerSql = """
|
||||||
|
INSERT INTO allowed_servers (server_id, comment) VALUES (?, ?)
|
||||||
|
""";
|
||||||
|
try (Connection con = DriverManager.getConnection(this.jdbcConnectionString, this.username, this.password);
|
||||||
|
PreparedStatement pstmt = con.prepareStatement(insertAllowedServerSql)
|
||||||
|
) {
|
||||||
|
pstmt.setLong(1, newAllowedServer.serverId());
|
||||||
|
pstmt.setString(2, newAllowedServer.comment());
|
||||||
|
int affectedRows = pstmt.executeUpdate();
|
||||||
|
if (affectedRows == 0) {
|
||||||
|
logger.error("No server inserted to allowed_servers with id: " + newAllowedServer.serverId());
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new DBException("Allowing new server with id: " + newAllowedServer.serverId(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateAllowed(long id, AllowedServer.NewAllowedServer newAllowedServer) throws DBException {
|
||||||
|
var insertAllowedServerSql = """
|
||||||
|
UPDATE allowed_servers SET comment = ?, server_id = ? WHERE id = ?
|
||||||
|
""";
|
||||||
|
try (Connection con = DriverManager.getConnection(this.jdbcConnectionString, this.username, this.password);
|
||||||
|
PreparedStatement pstmt = con.prepareStatement(insertAllowedServerSql)
|
||||||
|
) {
|
||||||
|
pstmt.setString(1, newAllowedServer.comment());
|
||||||
|
pstmt.setLong(2, newAllowedServer.serverId());
|
||||||
|
pstmt.setLong(3, id);
|
||||||
|
int affectedRows = pstmt.executeUpdate();
|
||||||
|
if (affectedRows == 0) {
|
||||||
|
logger.error("No comment updated on server with id: " + newAllowedServer.serverId());
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new DBException("Updating comment on allowed server with id: " + newAllowedServer.serverId(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteAllowed(long id) throws DBException {
|
||||||
|
var insertAllowedServerSql = """
|
||||||
|
DELETE FROM allowed_servers WHERE id = ?
|
||||||
|
""";
|
||||||
|
try (Connection con = DriverManager.getConnection(this.jdbcConnectionString, this.username, this.password);
|
||||||
|
PreparedStatement pstmt = con.prepareStatement(insertAllowedServerSql)
|
||||||
|
) {
|
||||||
|
pstmt.setLong(1, id);
|
||||||
|
int affectedRows = pstmt.executeUpdate();
|
||||||
|
if (affectedRows == 0) {
|
||||||
|
logger.error("No server deleted with id: " + id);
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new DBException("Deleting allowed server with id: " + id, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<ServerConfig> getConfig(long serverId) {
|
||||||
var getServerConfig = """
|
var getServerConfig = """
|
||||||
SELECT * FROM server_configs WHERE server_id = ?
|
SELECT * FROM server_configs WHERE server_id = ?
|
||||||
""";
|
""";
|
||||||
|
@ -32,7 +142,7 @@ public class ServerDBService {
|
||||||
.getConnection(this.jdbcConnectionString, this.username, this.password);
|
.getConnection(this.jdbcConnectionString, this.username, this.password);
|
||||||
PreparedStatement pstmt = con.prepareStatement(getServerConfig)
|
PreparedStatement pstmt = con.prepareStatement(getServerConfig)
|
||||||
) {
|
) {
|
||||||
pstmt.setString(1, serverId);
|
pstmt.setLong(1, serverId);
|
||||||
ResultSet resultSet = pstmt.executeQuery();
|
ResultSet resultSet = pstmt.executeQuery();
|
||||||
Iterable<ServerConfig> iterable = () -> new ResultSetIterator<>(resultSet, new ServerConfig.ServerConfigResultSetTransformer());
|
Iterable<ServerConfig> iterable = () -> new ResultSetIterator<>(resultSet, new ServerConfig.ServerConfigResultSetTransformer());
|
||||||
return StreamSupport.stream(iterable.spliterator(), false).findFirst();
|
return StreamSupport.stream(iterable.spliterator(), false).findFirst();
|
||||||
|
@ -89,7 +199,7 @@ public class ServerDBService {
|
||||||
.getConnection(this.jdbcConnectionString, this.username, this.password);
|
.getConnection(this.jdbcConnectionString, this.username, this.password);
|
||||||
PreparedStatement pstmt = con.prepareStatement(getServerConfig)
|
PreparedStatement pstmt = con.prepareStatement(getServerConfig)
|
||||||
) {
|
) {
|
||||||
pstmt.setString(1, newServerConfig.serverId());
|
pstmt.setLong(1, newServerConfig.serverId());
|
||||||
pstmt.setString(2, newServerConfig.systemMessage());
|
pstmt.setString(2, newServerConfig.systemMessage());
|
||||||
pstmt.setInt(3, newServerConfig.rateLimit());
|
pstmt.setInt(3, newServerConfig.rateLimit());
|
||||||
int affectedRows = pstmt.executeUpdate();
|
int affectedRows = pstmt.executeUpdate();
|
||||||
|
@ -111,7 +221,7 @@ public class ServerDBService {
|
||||||
) {
|
) {
|
||||||
pstmt.setString(1, newServerConfig.systemMessage());
|
pstmt.setString(1, newServerConfig.systemMessage());
|
||||||
pstmt.setInt(2, newServerConfig.rateLimit());
|
pstmt.setInt(2, newServerConfig.rateLimit());
|
||||||
pstmt.setString(3, newServerConfig.serverId());
|
pstmt.setLong(3, newServerConfig.serverId());
|
||||||
pstmt.setLong(4, id);
|
pstmt.setLong(4, id);
|
||||||
int affectedRows = pstmt.executeUpdate();
|
int affectedRows = pstmt.executeUpdate();
|
||||||
if (affectedRows == 0) {
|
if (affectedRows == 0) {
|
||||||
|
@ -140,7 +250,7 @@ public class ServerDBService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int countMessagesInLastMinute(String serverId) {
|
public int countMessagesInLastMinute(long serverId) {
|
||||||
var getServerConfig = """
|
var getServerConfig = """
|
||||||
SELECT count(*) FROM server_messages WHERE server_id = ? AND time <= ? and time >= ?
|
SELECT count(*) FROM server_messages WHERE server_id = ? AND time <= ? and time >= ?
|
||||||
""";
|
""";
|
||||||
|
@ -148,7 +258,7 @@ public class ServerDBService {
|
||||||
.getConnection(this.jdbcConnectionString, this.username, this.password);
|
.getConnection(this.jdbcConnectionString, this.username, this.password);
|
||||||
PreparedStatement pstmt = con.prepareStatement(getServerConfig)
|
PreparedStatement pstmt = con.prepareStatement(getServerConfig)
|
||||||
) {
|
) {
|
||||||
pstmt.setString(1, serverId);
|
pstmt.setLong(1, serverId);
|
||||||
var now = Instant.now();
|
var now = Instant.now();
|
||||||
pstmt.setTimestamp(2, Timestamp.from(now));
|
pstmt.setTimestamp(2, Timestamp.from(now));
|
||||||
pstmt.setTimestamp(3, Timestamp.from(now.minus(1, ChronoUnit.MINUTES)));
|
pstmt.setTimestamp(3, Timestamp.from(now.minus(1, ChronoUnit.MINUTES)));
|
||||||
|
@ -172,7 +282,7 @@ public class ServerDBService {
|
||||||
.getConnection(this.jdbcConnectionString, this.username, this.password);
|
.getConnection(this.jdbcConnectionString, this.username, this.password);
|
||||||
PreparedStatement pstmt = con.prepareStatement(getServerConfig)
|
PreparedStatement pstmt = con.prepareStatement(getServerConfig)
|
||||||
) {
|
) {
|
||||||
pstmt.setString(1, serverMessage.serverId());
|
pstmt.setLong(1, serverMessage.serverId());
|
||||||
pstmt.setLong(2, serverMessage.userId());
|
pstmt.setLong(2, serverMessage.userId());
|
||||||
pstmt.setInt(3, serverMessage.tokens());
|
pstmt.setInt(3, serverMessage.tokens());
|
||||||
int affectedRows = pstmt.executeUpdate();
|
int affectedRows = pstmt.executeUpdate();
|
||||||
|
@ -184,7 +294,7 @@ public class ServerDBService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public long tokensOfLast30Days(String serverId) {
|
public long tokensOfLast30Days(long serverId) {
|
||||||
var countTokensOfLast30Days = """
|
var countTokensOfLast30Days = """
|
||||||
SELECT sum(tokens) FROM server_messages WHERE server_id = ? AND time < ? AND time >= ?
|
SELECT sum(tokens) FROM server_messages WHERE server_id = ? AND time < ? AND time >= ?
|
||||||
""";
|
""";
|
||||||
|
@ -192,7 +302,7 @@ public class ServerDBService {
|
||||||
.getConnection(this.jdbcConnectionString, this.username, this.password);
|
.getConnection(this.jdbcConnectionString, this.username, this.password);
|
||||||
PreparedStatement pstmt = con.prepareStatement(countTokensOfLast30Days)
|
PreparedStatement pstmt = con.prepareStatement(countTokensOfLast30Days)
|
||||||
) {
|
) {
|
||||||
pstmt.setString(1, serverId);
|
pstmt.setLong(1, serverId);
|
||||||
var now = Instant.now();
|
var now = Instant.now();
|
||||||
pstmt.setTimestamp(2, Timestamp.from(now));
|
pstmt.setTimestamp(2, Timestamp.from(now));
|
||||||
pstmt.setTimestamp(3, Timestamp.from(now.minus(30, ChronoUnit.DAYS)));
|
pstmt.setTimestamp(3, Timestamp.from(now.minus(30, ChronoUnit.DAYS)));
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package de.hhhammer.dchat.db;
|
package de.hhhammer.dchat.db;
|
||||||
|
|
||||||
|
import de.hhhammer.dchat.db.models.user.AllowedUser;
|
||||||
import de.hhhammer.dchat.db.models.user.UserConfig;
|
import de.hhhammer.dchat.db.models.user.UserConfig;
|
||||||
import de.hhhammer.dchat.db.models.user.UserMessage;
|
import de.hhhammer.dchat.db.models.user.UserMessage;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -24,7 +25,115 @@ public class UserDBService {
|
||||||
this.password = password;
|
this.password = password;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<UserConfig> getConfig(String userId) {
|
public boolean isAllowed(long userId) {
|
||||||
|
var getAllowedServerSql = """
|
||||||
|
SELECT * FROM allowed_users WHERE user_id = ?
|
||||||
|
""";
|
||||||
|
try (Connection con = DriverManager.getConnection(this.jdbcConnectionString, this.username, this.password);
|
||||||
|
PreparedStatement pstmt = con.prepareStatement(getAllowedServerSql)
|
||||||
|
) {
|
||||||
|
pstmt.setLong(1, userId);
|
||||||
|
ResultSet result = pstmt.executeQuery();
|
||||||
|
Iterable<AllowedUser> iterable = () -> new ResultSetIterator<>(result, new AllowedUser.AllowedUserResultSetTransformer());
|
||||||
|
return StreamSupport.stream(iterable.spliterator(), false).count() == 1;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
logger.error("Searching for allowed user with id: " + userId, e);
|
||||||
|
} catch (ResultSetIteratorException e) {
|
||||||
|
logger.error("Iterating over AllowedServer ResultSet for user with id: " + userId, e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<AllowedUser> getAllowedBy(long id) throws DBException {
|
||||||
|
var getAllowedServerSql = """
|
||||||
|
SELECT * FROM allowed_users WHERE id = ?
|
||||||
|
""";
|
||||||
|
try (Connection con = DriverManager.getConnection(this.jdbcConnectionString, this.username, this.password);
|
||||||
|
PreparedStatement pstmt = con.prepareStatement(getAllowedServerSql)
|
||||||
|
) {
|
||||||
|
pstmt.setLong(1, id);
|
||||||
|
ResultSet result = pstmt.executeQuery();
|
||||||
|
Iterable<AllowedUser> iterable = () -> new ResultSetIterator<>(result, new AllowedUser.AllowedUserResultSetTransformer());
|
||||||
|
return StreamSupport.stream(iterable.spliterator(), false).findFirst();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new DBException("Searching for allowed with id: " + id, e);
|
||||||
|
} catch (ResultSetIteratorException e) {
|
||||||
|
throw new DBException("Iterating over AllowedServer ResultSet with id: " + id, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<AllowedUser> getAllAllowed() throws DBException {
|
||||||
|
var getAllowedServerSql = """
|
||||||
|
SELECT * FROM allowed_users
|
||||||
|
""";
|
||||||
|
try (Connection con = DriverManager.getConnection(this.jdbcConnectionString, this.username, this.password);
|
||||||
|
PreparedStatement pstmt = con.prepareStatement(getAllowedServerSql)
|
||||||
|
) {
|
||||||
|
ResultSet result = pstmt.executeQuery();
|
||||||
|
Iterable<AllowedUser> iterable = () -> new ResultSetIterator<>(result, new AllowedUser.AllowedUserResultSetTransformer());
|
||||||
|
return StreamSupport.stream(iterable.spliterator(), false).toList();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new DBException("Searching all allowed users", e);
|
||||||
|
} catch (ResultSetIteratorException e) {
|
||||||
|
throw new DBException("Iterating over all AllowedServer ResultSet ", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addAllowed(AllowedUser.NewAllowedUser newAllowedUser) throws DBException {
|
||||||
|
var insertAllowedServerSql = """
|
||||||
|
INSERT INTO allowed_users (user_id, comment) VALUES (?, ?)
|
||||||
|
""";
|
||||||
|
try (Connection con = DriverManager.getConnection(this.jdbcConnectionString, this.username, this.password);
|
||||||
|
PreparedStatement pstmt = con.prepareStatement(insertAllowedServerSql)
|
||||||
|
) {
|
||||||
|
pstmt.setLong(1, newAllowedUser.userId());
|
||||||
|
pstmt.setString(2, newAllowedUser.comment());
|
||||||
|
int affectedRows = pstmt.executeUpdate();
|
||||||
|
if (affectedRows == 0) {
|
||||||
|
logger.error("No server inserted to allowed_users with id: " + newAllowedUser.userId());
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new DBException("Allowing new user with id: " + newAllowedUser.userId(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateAllowed(long id, AllowedUser.NewAllowedUser newAllowedUser) throws DBException {
|
||||||
|
var insertAllowedServerSql = """
|
||||||
|
UPDATE allowed_users SET comment = ? WHERE id = ?
|
||||||
|
""";
|
||||||
|
try (Connection con = DriverManager.getConnection(this.jdbcConnectionString, this.username, this.password);
|
||||||
|
PreparedStatement pstmt = con.prepareStatement(insertAllowedServerSql)
|
||||||
|
) {
|
||||||
|
pstmt.setString(1, newAllowedUser.comment());
|
||||||
|
pstmt.setLong(2, id);
|
||||||
|
int affectedRows = pstmt.executeUpdate();
|
||||||
|
if (affectedRows == 0) {
|
||||||
|
logger.error("No comment updated on user with id: " + newAllowedUser.userId());
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new DBException("Updating comment on allowed user with id: " + id, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteAllowed(long id) throws DBException {
|
||||||
|
var insertAllowedServerSql = """
|
||||||
|
DELETE FROM allowed_users WHERE id = ?
|
||||||
|
""";
|
||||||
|
try (Connection con = DriverManager.getConnection(this.jdbcConnectionString, this.username, this.password);
|
||||||
|
PreparedStatement pstmt = con.prepareStatement(insertAllowedServerSql)
|
||||||
|
) {
|
||||||
|
pstmt.setLong(1, id);
|
||||||
|
int affectedRows = pstmt.executeUpdate();
|
||||||
|
if (affectedRows == 0) {
|
||||||
|
logger.error("No user deleted with id: " + id);
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new DBException("Deleting allowed user with id: " + id, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<UserConfig> getConfig(long userId) {
|
||||||
var getServerConfig = """
|
var getServerConfig = """
|
||||||
SELECT * FROM user_configs WHERE user_id = ?
|
SELECT * FROM user_configs WHERE user_id = ?
|
||||||
""";
|
""";
|
||||||
|
@ -32,7 +141,7 @@ public class UserDBService {
|
||||||
.getConnection(this.jdbcConnectionString, this.username, this.password);
|
.getConnection(this.jdbcConnectionString, this.username, this.password);
|
||||||
PreparedStatement pstmt = con.prepareStatement(getServerConfig)
|
PreparedStatement pstmt = con.prepareStatement(getServerConfig)
|
||||||
) {
|
) {
|
||||||
pstmt.setString(1, userId);
|
pstmt.setLong(1, userId);
|
||||||
ResultSet resultSet = pstmt.executeQuery();
|
ResultSet resultSet = pstmt.executeQuery();
|
||||||
Iterable<UserConfig> iterable = () -> new ResultSetIterator<>(resultSet, new UserConfig.UserConfigResultSetTransformer());
|
Iterable<UserConfig> iterable = () -> new ResultSetIterator<>(resultSet, new UserConfig.UserConfigResultSetTransformer());
|
||||||
return StreamSupport.stream(iterable.spliterator(), false).findFirst();
|
return StreamSupport.stream(iterable.spliterator(), false).findFirst();
|
||||||
|
@ -90,7 +199,7 @@ public class UserDBService {
|
||||||
.getConnection(this.jdbcConnectionString, this.username, this.password);
|
.getConnection(this.jdbcConnectionString, this.username, this.password);
|
||||||
PreparedStatement pstmt = con.prepareStatement(getServerConfig)
|
PreparedStatement pstmt = con.prepareStatement(getServerConfig)
|
||||||
) {
|
) {
|
||||||
pstmt.setString(1, newUserConfig.userId());
|
pstmt.setLong(1, newUserConfig.userId());
|
||||||
pstmt.setString(2, newUserConfig.systemMessage());
|
pstmt.setString(2, newUserConfig.systemMessage());
|
||||||
pstmt.setInt(3, newUserConfig.contextLength());
|
pstmt.setInt(3, newUserConfig.contextLength());
|
||||||
pstmt.setInt(4, newUserConfig.rateLimit());
|
pstmt.setInt(4, newUserConfig.rateLimit());
|
||||||
|
@ -105,7 +214,7 @@ public class UserDBService {
|
||||||
|
|
||||||
public void updateConfig(long id, UserConfig.NewUserConfig newUserConfig) throws DBException {
|
public void updateConfig(long id, UserConfig.NewUserConfig newUserConfig) throws DBException {
|
||||||
var getServerConfig = """
|
var getServerConfig = """
|
||||||
UPDATE user_configs SET system_message = ?, context_length = ?, rate_limit = ?, user_id = ? WHERE id = ?
|
UPDATE user_configs SET system_message = ?, context_length = ?, rate_limit = ? WHERE id = ?
|
||||||
""";
|
""";
|
||||||
try (Connection con = DriverManager
|
try (Connection con = DriverManager
|
||||||
.getConnection(this.jdbcConnectionString, this.username, this.password);
|
.getConnection(this.jdbcConnectionString, this.username, this.password);
|
||||||
|
@ -114,8 +223,7 @@ public class UserDBService {
|
||||||
pstmt.setString(1, newUserConfig.systemMessage());
|
pstmt.setString(1, newUserConfig.systemMessage());
|
||||||
pstmt.setInt(2, newUserConfig.rateLimit());
|
pstmt.setInt(2, newUserConfig.rateLimit());
|
||||||
pstmt.setLong(3, newUserConfig.contextLength());
|
pstmt.setLong(3, newUserConfig.contextLength());
|
||||||
pstmt.setString(4, newUserConfig.userId());
|
pstmt.setLong(4, id);
|
||||||
pstmt.setLong(5, id);
|
|
||||||
int affectedRows = pstmt.executeUpdate();
|
int affectedRows = pstmt.executeUpdate();
|
||||||
if (affectedRows == 0) {
|
if (affectedRows == 0) {
|
||||||
logger.error("No config update with id: " + id);
|
logger.error("No config update with id: " + id);
|
||||||
|
@ -143,7 +251,7 @@ public class UserDBService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int countMessagesInLastMinute(String userId) {
|
public int countMessagesInLastMinute(long userId) {
|
||||||
var getServerConfig = """
|
var getServerConfig = """
|
||||||
SELECT count(*) FROM user_messages WHERE user_id = ? AND time <= ? and time >= ?
|
SELECT count(*) FROM user_messages WHERE user_id = ? AND time <= ? and time >= ?
|
||||||
""";
|
""";
|
||||||
|
@ -151,7 +259,7 @@ public class UserDBService {
|
||||||
.getConnection(this.jdbcConnectionString, this.username, this.password);
|
.getConnection(this.jdbcConnectionString, this.username, this.password);
|
||||||
PreparedStatement pstmt = con.prepareStatement(getServerConfig)
|
PreparedStatement pstmt = con.prepareStatement(getServerConfig)
|
||||||
) {
|
) {
|
||||||
pstmt.setString(1, userId);
|
pstmt.setLong(1, userId);
|
||||||
var now = Instant.now();
|
var now = Instant.now();
|
||||||
pstmt.setTimestamp(2, Timestamp.from(now));
|
pstmt.setTimestamp(2, Timestamp.from(now));
|
||||||
pstmt.setTimestamp(3, Timestamp.from(now.minus(1, ChronoUnit.MINUTES)));
|
pstmt.setTimestamp(3, Timestamp.from(now.minus(1, ChronoUnit.MINUTES)));
|
||||||
|
@ -175,7 +283,7 @@ public class UserDBService {
|
||||||
.getConnection(this.jdbcConnectionString, this.username, this.password);
|
.getConnection(this.jdbcConnectionString, this.username, this.password);
|
||||||
PreparedStatement pstmt = con.prepareStatement(getServerConfig)
|
PreparedStatement pstmt = con.prepareStatement(getServerConfig)
|
||||||
) {
|
) {
|
||||||
pstmt.setString(1, newUserMessage.userId());
|
pstmt.setLong(1, newUserMessage.userId());
|
||||||
pstmt.setString(2, newUserMessage.question());
|
pstmt.setString(2, newUserMessage.question());
|
||||||
pstmt.setString(3, newUserMessage.answer());
|
pstmt.setString(3, newUserMessage.answer());
|
||||||
pstmt.setInt(4, newUserMessage.tokens());
|
pstmt.setInt(4, newUserMessage.tokens());
|
||||||
|
@ -188,7 +296,7 @@ public class UserDBService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public long tokensOfLast30Days(String userId) {
|
public long tokensOfLast30Days(long userId) {
|
||||||
var countTokensOfLast30Days = """
|
var countTokensOfLast30Days = """
|
||||||
SELECT sum(tokens) FROM user_messages WHERE user_id = ? AND time < ? AND time >= ?
|
SELECT sum(tokens) FROM user_messages WHERE user_id = ? AND time < ? AND time >= ?
|
||||||
""";
|
""";
|
||||||
|
@ -196,7 +304,7 @@ public class UserDBService {
|
||||||
.getConnection(this.jdbcConnectionString, this.username, this.password);
|
.getConnection(this.jdbcConnectionString, this.username, this.password);
|
||||||
PreparedStatement pstmt = con.prepareStatement(countTokensOfLast30Days)
|
PreparedStatement pstmt = con.prepareStatement(countTokensOfLast30Days)
|
||||||
) {
|
) {
|
||||||
pstmt.setString(1, userId);
|
pstmt.setLong(1, userId);
|
||||||
var now = Instant.now();
|
var now = Instant.now();
|
||||||
pstmt.setTimestamp(2, Timestamp.from(now));
|
pstmt.setTimestamp(2, Timestamp.from(now));
|
||||||
pstmt.setTimestamp(3, Timestamp.from(now.minus(30, ChronoUnit.DAYS)));
|
pstmt.setTimestamp(3, Timestamp.from(now.minus(30, ChronoUnit.DAYS)));
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
package de.hhhammer.dchat.db.models.server;
|
||||||
|
|
||||||
|
import de.hhhammer.dchat.db.ResultSetTransformer;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
|
public record AllowedServer(long id, long serverId, Instant time, @Nullable String comment) {
|
||||||
|
|
||||||
|
public static class AllowedServerResultSetTransformer implements ResultSetTransformer<AllowedServer> {
|
||||||
|
@Override
|
||||||
|
public AllowedServer transform(ResultSet resultSet) throws SQLException {
|
||||||
|
var id = resultSet.getLong("id");
|
||||||
|
var serverId = resultSet.getLong("server_id");
|
||||||
|
var time = resultSet.getTimestamp("time").toInstant();
|
||||||
|
var comment = resultSet.getString("comment");
|
||||||
|
return new AllowedServer(id, serverId, time, comment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public record NewAllowedServer(long serverId, @Nullable String comment) {
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,29 +1,25 @@
|
||||||
package de.hhhammer.dchat.db.models.server;
|
package de.hhhammer.dchat.db.models.server;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
|
||||||
import de.hhhammer.dchat.db.ResultSetTransformer;
|
import de.hhhammer.dchat.db.ResultSetTransformer;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.time.Instant;
|
|
||||||
|
|
||||||
public record ServerConfig(long id, String serverId, String systemMessage, int rateLimit, Instant time) {
|
public record ServerConfig(long id, long serverId, String systemMessage, int rateLimit) {
|
||||||
|
|
||||||
public static class ServerConfigResultSetTransformer implements ResultSetTransformer<ServerConfig> {
|
public static class ServerConfigResultSetTransformer implements ResultSetTransformer<ServerConfig> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ServerConfig transform(ResultSet resultSet) throws SQLException {
|
public ServerConfig transform(ResultSet resultSet) throws SQLException {
|
||||||
var id = resultSet.getLong("id");
|
var id = resultSet.getLong("id");
|
||||||
var serverId = resultSet.getString("server_id");
|
var serverId = resultSet.getLong("server_id");
|
||||||
var systemMessage = resultSet.getString("system_message");
|
var systemMessage = resultSet.getString("system_message");
|
||||||
var rateLimit = resultSet.getInt("rate_limit");
|
var rateLimit = resultSet.getInt("rate_limit");
|
||||||
var time = resultSet.getTimestamp("time").toInstant();
|
return new ServerConfig(id, serverId, systemMessage, rateLimit);
|
||||||
return new ServerConfig(id, serverId, systemMessage, rateLimit, time);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
public record NewServerConfig(long serverId, String systemMessage, @Nullable int rateLimit) {
|
||||||
public record NewServerConfig(String serverId, String systemMessage, @Nullable int rateLimit) {
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,19 @@
|
||||||
package de.hhhammer.dchat.db.models.server;
|
package de.hhhammer.dchat.db.models.server;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
|
||||||
import de.hhhammer.dchat.db.ResultSetTransformer;
|
import de.hhhammer.dchat.db.ResultSetTransformer;
|
||||||
|
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
|
|
||||||
public record ServerMessage(long id, String serverId, long userId, int tokens, Instant time) {
|
public record ServerMessage(long id, long serverId, long userId, int tokens, Instant time) {
|
||||||
|
|
||||||
public static class ServerMessageResultSetTransformer implements ResultSetTransformer<ServerMessage> {
|
public static class ServerMessageResultSetTransformer implements ResultSetTransformer<ServerMessage> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ServerMessage transform(ResultSet resultSet) throws SQLException {
|
public ServerMessage transform(ResultSet resultSet) throws SQLException {
|
||||||
var id = resultSet.getLong("id");
|
var id = resultSet.getLong("id");
|
||||||
var serverId = resultSet.getString("server_id");
|
var serverId = resultSet.getLong("server_id");
|
||||||
var userId = resultSet.getLong("user_id");
|
var userId = resultSet.getLong("user_id");
|
||||||
var tokens = resultSet.getInt("tokens");
|
var tokens = resultSet.getInt("tokens");
|
||||||
var time = resultSet.getTimestamp("time").toInstant();
|
var time = resultSet.getTimestamp("time").toInstant();
|
||||||
|
@ -22,7 +21,6 @@ public record ServerMessage(long id, String serverId, long userId, int tokens, I
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
public record NewServerMessage(long serverId, long userId, int tokens) {
|
||||||
public record NewServerMessage(String serverId, long userId, int tokens) {
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
package de.hhhammer.dchat.db.models.user;
|
||||||
|
|
||||||
|
import de.hhhammer.dchat.db.ResultSetTransformer;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
|
public record AllowedUser(long id, long userId, Instant time, @Nullable String comment) {
|
||||||
|
|
||||||
|
public static class AllowedUserResultSetTransformer implements ResultSetTransformer<AllowedUser> {
|
||||||
|
@Override
|
||||||
|
public AllowedUser transform(ResultSet resultSet) throws SQLException {
|
||||||
|
var id = resultSet.getLong("id");
|
||||||
|
var userId = resultSet.getLong("user_id");
|
||||||
|
var time = resultSet.getTimestamp("time").toInstant();
|
||||||
|
var comment = resultSet.getString("comment");
|
||||||
|
return new AllowedUser(id, userId, time, comment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public record NewAllowedUser(long userId, @Nullable String comment) {
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,31 +1,27 @@
|
||||||
package de.hhhammer.dchat.db.models.user;
|
package de.hhhammer.dchat.db.models.user;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
|
||||||
import de.hhhammer.dchat.db.ResultSetTransformer;
|
import de.hhhammer.dchat.db.ResultSetTransformer;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.time.Instant;
|
|
||||||
|
|
||||||
public record UserConfig(long id, String userId, String systemMessage, int contextLength, int rateLimit, Instant time) {
|
public record UserConfig(long id, long userId, String systemMessage, int contextLength, int rateLimit) {
|
||||||
|
|
||||||
public static class UserConfigResultSetTransformer implements ResultSetTransformer<UserConfig> {
|
public static class UserConfigResultSetTransformer implements ResultSetTransformer<UserConfig> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UserConfig transform(ResultSet resultSet) throws SQLException {
|
public UserConfig transform(ResultSet resultSet) throws SQLException {
|
||||||
var id = resultSet.getLong("id");
|
var id = resultSet.getLong("id");
|
||||||
var userId = resultSet.getString("user_id");
|
var userId = resultSet.getLong("user_id");
|
||||||
var systemMessage = resultSet.getString("system_message");
|
var systemMessage = resultSet.getString("system_message");
|
||||||
var contextLength = resultSet.getInt("context_length");
|
var contextLength = resultSet.getInt("context_length");
|
||||||
var rateLimit = resultSet.getInt("rate_limit");
|
var rateLimit = resultSet.getInt("rate_limit");
|
||||||
var time = resultSet.getTimestamp("time").toInstant();
|
return new UserConfig(id, userId, systemMessage, contextLength, rateLimit);
|
||||||
return new UserConfig(id, userId, systemMessage, contextLength, rateLimit, time);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
public record NewUserConfig(long userId, String systemMessage, @Nullable int contextLength,
|
||||||
public record NewUserConfig(String userId, String systemMessage, @Nullable int contextLength,
|
|
||||||
@Nullable int rateLimit) {
|
@Nullable int rateLimit) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,19 @@
|
||||||
package de.hhhammer.dchat.db.models.user;
|
package de.hhhammer.dchat.db.models.user;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
|
||||||
import de.hhhammer.dchat.db.ResultSetTransformer;
|
import de.hhhammer.dchat.db.ResultSetTransformer;
|
||||||
|
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
|
|
||||||
public record UserMessage(long id, String userId, String question, String answer, int tokens, Instant time) {
|
public record UserMessage(long id, long userId, String question, String answer, int tokens, Instant time) {
|
||||||
|
|
||||||
public static class UserMessageResultSetTransformer implements ResultSetTransformer<UserMessage> {
|
public static class UserMessageResultSetTransformer implements ResultSetTransformer<UserMessage> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UserMessage transform(ResultSet resultSet) throws SQLException {
|
public UserMessage transform(ResultSet resultSet) throws SQLException {
|
||||||
var id = resultSet.getLong("id");
|
var id = resultSet.getLong("id");
|
||||||
var userId = resultSet.getString("user_id");
|
var userId = resultSet.getLong("user_id");
|
||||||
var question = resultSet.getString("question");
|
var question = resultSet.getString("question");
|
||||||
var answer = resultSet.getString("answer");
|
var answer = resultSet.getString("answer");
|
||||||
var tokens = resultSet.getInt("tokens");
|
var tokens = resultSet.getInt("tokens");
|
||||||
|
@ -23,7 +22,6 @@ public record UserMessage(long id, String userId, String question, String answer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
public record NewUserMessage(long userId, String question, String answer, int tokens) {
|
||||||
public record NewUserMessage(String userId, String question, String answer, int tokens) {
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ public class MessageCreateHandler implements MessageCreateListener {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.messageHandler.exceedsRate(event)) {
|
if (this.messageHandler.exceedsRate(event)) {
|
||||||
event.getChannel().sendMessage("Rate limit hit - cooling down...");
|
event.getChannel().sendMessage("Rate limit hit - cooling down now...");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.messageHandler.handle(event);
|
this.messageHandler.handle(event);
|
||||||
|
|
|
@ -29,8 +29,6 @@ public class ServerMessageHandler implements MessageHandler {
|
||||||
@Override
|
@Override
|
||||||
public void handle(MessageCreateEvent event) {
|
public void handle(MessageCreateEvent event) {
|
||||||
String content = extractContent(event);
|
String content = extractContent(event);
|
||||||
var serverId = event.getServer().get().getId();
|
|
||||||
var systemMessage = this.serverDBService.getConfig(String.valueOf(serverId)).get().systemMessage();
|
|
||||||
var request = event.getMessage().getType() == MessageType.REPLY ?
|
var request = event.getMessage().getType() == MessageType.REPLY ?
|
||||||
new ChatGPTRequestBuilder()
|
new ChatGPTRequestBuilder()
|
||||||
.contextRequest(event.getMessage()
|
.contextRequest(event.getMessage()
|
||||||
|
@ -39,8 +37,8 @@ public class ServerMessageHandler implements MessageHandler {
|
||||||
.flatMap(m -> m)
|
.flatMap(m -> m)
|
||||||
.map(Message::getReadableContent)
|
.map(Message::getReadableContent)
|
||||||
.stream().toList(),
|
.stream().toList(),
|
||||||
content, systemMessage) :
|
content) :
|
||||||
new ChatGPTRequestBuilder().simpleRequest(content, systemMessage);
|
new ChatGPTRequestBuilder().simpleRequest(content);
|
||||||
try {
|
try {
|
||||||
var response = this.chatGPTService.submit(request);
|
var response = this.chatGPTService.submit(request);
|
||||||
if (response.choices().size() < 1) {
|
if (response.choices().size() < 1) {
|
||||||
|
@ -58,22 +56,21 @@ public class ServerMessageHandler implements MessageHandler {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isAllowed(MessageCreateEvent event) {
|
public boolean isAllowed(MessageCreateEvent event) {
|
||||||
if (event.getServer().isEmpty()) {
|
if (event.getServer().isPresent()) {
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var serverId = event.getServer().get().getId();
|
var serverId = event.getServer().get().getId();
|
||||||
var config = this.serverDBService.getConfig(String.valueOf(serverId));
|
var allowed = this.serverDBService.isAllowed(serverId);
|
||||||
if (config.isEmpty()) {
|
if (!allowed) {
|
||||||
logger.debug("Not allowed with id: " + serverId);
|
logger.debug("Not allowed with id: " + serverId);
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
return true;
|
return allowed;
|
||||||
|
}
|
||||||
|
// only support server messages
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean exceedsRate(MessageCreateEvent event) {
|
public boolean exceedsRate(MessageCreateEvent event) {
|
||||||
var serverId = String.valueOf(event.getServer().get().getId());
|
var serverId = event.getServer().get().getId();
|
||||||
var config = this.serverDBService.getConfig(serverId);
|
var config = this.serverDBService.getConfig(serverId);
|
||||||
if (config.isEmpty()) {
|
if (config.isEmpty()) {
|
||||||
logger.error("Missing configuration for server with id: " + serverId);
|
logger.error("Missing configuration for server with id: " + serverId);
|
||||||
|
@ -94,7 +91,7 @@ public class ServerMessageHandler implements MessageHandler {
|
||||||
var serverId = event.getServer().map(DiscordEntity::getId).get();
|
var serverId = event.getServer().map(DiscordEntity::getId).get();
|
||||||
var userId = event.getMessageAuthor().getId();
|
var userId = event.getMessageAuthor().getId();
|
||||||
|
|
||||||
var serverMessage = new ServerMessage.NewServerMessage(String.valueOf(serverId), userId, tokens);
|
var serverMessage = new ServerMessage.NewServerMessage(serverId, userId, tokens);
|
||||||
this.serverDBService.addMessage(serverMessage);
|
this.serverDBService.addMessage(serverMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,9 +24,7 @@ public class UserMessageHandler implements MessageHandler {
|
||||||
@Override
|
@Override
|
||||||
public void handle(MessageCreateEvent event) {
|
public void handle(MessageCreateEvent event) {
|
||||||
String content = event.getReadableMessageContent();
|
String content = event.getReadableMessageContent();
|
||||||
var userId = event.getMessageAuthor().getId();
|
var request = new ChatGPTRequestBuilder().simpleRequest(content);
|
||||||
var systemMessage = this.userDBService.getConfig(String.valueOf(userId)).get().systemMessage();
|
|
||||||
var request = new ChatGPTRequestBuilder().simpleRequest(content, systemMessage);
|
|
||||||
try {
|
try {
|
||||||
var response = this.chatGPTService.submit(request);
|
var response = this.chatGPTService.submit(request);
|
||||||
if (response.choices().size() < 1) {
|
if (response.choices().size() < 1) {
|
||||||
|
@ -49,17 +47,16 @@ public class UserMessageHandler implements MessageHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
var userId = event.getMessageAuthor().getId();
|
var userId = event.getMessageAuthor().getId();
|
||||||
var config = this.userDBService.getConfig(String.valueOf(userId));
|
var allowed = this.userDBService.isAllowed(userId);
|
||||||
if (config.isEmpty()) {
|
if (!allowed) {
|
||||||
logger.debug("Not allowed with id: " + userId);
|
logger.debug("Not allowed with id: " + userId);
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
return true;
|
return allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean exceedsRate(MessageCreateEvent event) {
|
public boolean exceedsRate(MessageCreateEvent event) {
|
||||||
var userId = String.valueOf(event.getMessageAuthor().getId());
|
var userId = event.getMessageAuthor().getId();
|
||||||
var config = this.userDBService.getConfig(userId);
|
var config = this.userDBService.getConfig(userId);
|
||||||
if (config.isEmpty()) {
|
if (config.isEmpty()) {
|
||||||
logger.error("Missing configuration for userId with id: " + userId);
|
logger.error("Missing configuration for userId with id: " + userId);
|
||||||
|
@ -79,7 +76,7 @@ public class UserMessageHandler implements MessageHandler {
|
||||||
private void logUserMessage(MessageCreateEvent event, String question, String answer, int tokens) {
|
private void logUserMessage(MessageCreateEvent event, String question, String answer, int tokens) {
|
||||||
var userId = event.getMessageAuthor().getId();
|
var userId = event.getMessageAuthor().getId();
|
||||||
|
|
||||||
var userMessage = new UserMessage.NewUserMessage(String.valueOf(userId), question, answer, tokens);
|
var userMessage = new UserMessage.NewUserMessage(userId, question, answer, tokens);
|
||||||
this.userDBService.addMessage(userMessage);
|
this.userDBService.addMessage(userMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
package de.hhhammer.dchat.migration;
|
|
||||||
|
|
||||||
public class DBMigrationException extends Exception {
|
|
||||||
public DBMigrationException(Throwable cause) {
|
|
||||||
super(cause);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
package de.hhhammer.dchat.migration;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.sql.Connection;
|
|
||||||
import java.sql.DriverManager;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.sql.Statement;
|
|
||||||
|
|
||||||
public class MigrationExecutor {
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(MigrationExecutor.class);
|
|
||||||
private final String jdbcConnectionString;
|
|
||||||
private final String username;
|
|
||||||
private final String password;
|
|
||||||
|
|
||||||
public MigrationExecutor(String jdbcConnectionString, String username, String password) {
|
|
||||||
this.jdbcConnectionString = jdbcConnectionString;
|
|
||||||
this.username = username;
|
|
||||||
this.password = password;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void migrate(InputStream input) throws DBMigrationException {
|
|
||||||
try (Connection con = DriverManager
|
|
||||||
.getConnection(this.jdbcConnectionString, this.username, this.password);
|
|
||||||
Statement stmp = con.createStatement();
|
|
||||||
) {
|
|
||||||
String content = new String(input.readAllBytes(), StandardCharsets.UTF_8);
|
|
||||||
stmp.execute(content);
|
|
||||||
} catch (SQLException | IOException e) {
|
|
||||||
throw new DBMigrationException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -7,11 +7,14 @@ import java.util.List;
|
||||||
|
|
||||||
public class ChatGPTRequestBuilder {
|
public class ChatGPTRequestBuilder {
|
||||||
private final String model = "gpt-3.5-turbo";
|
private final String model = "gpt-3.5-turbo";
|
||||||
|
private final String systemMessage = """
|
||||||
|
You are Jarvis, a helpful and friendly AI. People interact with you over Discord, a chatting platform. Your default language to answer is German. You format your responses in markdown and your answers don´t need to be formal.
|
||||||
|
""";
|
||||||
|
|
||||||
public ChatGPTRequestBuilder() {
|
public ChatGPTRequestBuilder() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChatGPTRequest simpleRequest(String content, String systemMessage) {
|
public ChatGPTRequest simpleRequest(String content) {
|
||||||
return new ChatGPTRequest(
|
return new ChatGPTRequest(
|
||||||
model,
|
model,
|
||||||
List.of(new ChatGPTRequest.Message("system", systemMessage), new ChatGPTRequest.Message("user", content)),
|
List.of(new ChatGPTRequest.Message("system", systemMessage), new ChatGPTRequest.Message("user", content)),
|
||||||
|
@ -19,7 +22,7 @@ public class ChatGPTRequestBuilder {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChatGPTRequest contextRequest(List<String> contextMessages, String message, String systemMessage) {
|
public ChatGPTRequest contextRequest(List<String> contextMessages, String message) {
|
||||||
List<ChatGPTRequest.Message> messages = new ArrayList<>();
|
List<ChatGPTRequest.Message> messages = new ArrayList<>();
|
||||||
messages.add(new ChatGPTRequest.Message("system", systemMessage));
|
messages.add(new ChatGPTRequest.Message("system", systemMessage));
|
||||||
var context = contextMessages.stream()
|
var context = contextMessages.stream()
|
||||||
|
|
4
src/main/java/de/hhhammer/dchat/web/JavalinConfig.java
Normal file
4
src/main/java/de/hhhammer/dchat/web/JavalinConfig.java
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
package de.hhhammer.dchat.web;
|
||||||
|
|
||||||
|
public record JavalinConfig(int port, String username, String password) {
|
||||||
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
package de.hhhammer.dchat.web.server;
|
||||||
|
|
||||||
|
import de.hhhammer.dchat.db.DBException;
|
||||||
|
import de.hhhammer.dchat.db.ServerDBService;
|
||||||
|
import de.hhhammer.dchat.db.models.server.AllowedServer;
|
||||||
|
import io.javalin.apibuilder.CrudHandler;
|
||||||
|
import io.javalin.http.Context;
|
||||||
|
import io.javalin.http.HttpStatus;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class AllowedCrudHandler implements CrudHandler {
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(AllowedCrudHandler.class);
|
||||||
|
|
||||||
|
private final ServerDBService serverDBService;
|
||||||
|
|
||||||
|
public AllowedCrudHandler(ServerDBService serverDBService) {
|
||||||
|
this.serverDBService = serverDBService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void create(@NotNull Context context) {
|
||||||
|
var body = context.bodyAsClass(AllowedServer.NewAllowedServer.class);
|
||||||
|
try {
|
||||||
|
this.serverDBService.addAllowed(body);
|
||||||
|
} catch (DBException e) {
|
||||||
|
logger.error("Adding new allowed server", e);
|
||||||
|
context.status(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
context.status(HttpStatus.CREATED);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delete(@NotNull Context context, @NotNull String s) {
|
||||||
|
try {
|
||||||
|
this.serverDBService.deleteAllowed(Long.parseLong(s));
|
||||||
|
context.status(HttpStatus.NO_CONTENT);
|
||||||
|
} catch (DBException e) {
|
||||||
|
logger.error("Deleting server with id: " + s, e);
|
||||||
|
context.status(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void getAll(@NotNull Context context) {
|
||||||
|
try {
|
||||||
|
var allowedServers = this.serverDBService.getAllAllowed();
|
||||||
|
context.json(allowedServers);
|
||||||
|
} catch (DBException e) {
|
||||||
|
logger.error("Getting all allowed servers", e);
|
||||||
|
context.status(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void getOne(@NotNull Context context, @NotNull String s) {
|
||||||
|
var id = Long.parseLong(s);
|
||||||
|
try {
|
||||||
|
var server = this.serverDBService.getAllowedBy(id);
|
||||||
|
if (server.isEmpty()) {
|
||||||
|
context.status(HttpStatus.NOT_FOUND);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
context.json(server.get());
|
||||||
|
} catch (DBException e) {
|
||||||
|
logger.error("Searching with id: " + s, e);
|
||||||
|
context.status(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(@NotNull Context context, @NotNull String idString) {
|
||||||
|
var newAllowedServer = context.bodyAsClass(AllowedServer.NewAllowedServer.class);
|
||||||
|
var id = Long.parseLong(idString);
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.serverDBService.updateAllowed(id, newAllowedServer);
|
||||||
|
} catch (DBException e) {
|
||||||
|
logger.error("Updating allowed server with id: " + idString, e);
|
||||||
|
context.status(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
package de.hhhammer.dchat.web.user;
|
||||||
|
|
||||||
|
import de.hhhammer.dchat.db.DBException;
|
||||||
|
import de.hhhammer.dchat.db.UserDBService;
|
||||||
|
import de.hhhammer.dchat.db.models.user.AllowedUser;
|
||||||
|
import io.javalin.apibuilder.CrudHandler;
|
||||||
|
import io.javalin.http.Context;
|
||||||
|
import io.javalin.http.HttpStatus;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class AllowedUserCrudHandler implements CrudHandler {
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(AllowedUserCrudHandler.class);
|
||||||
|
|
||||||
|
private final UserDBService userDBService;
|
||||||
|
|
||||||
|
public AllowedUserCrudHandler(UserDBService userDBService) {
|
||||||
|
this.userDBService = userDBService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void create(@NotNull Context context) {
|
||||||
|
var body = context.bodyAsClass(AllowedUser.NewAllowedUser.class);
|
||||||
|
try {
|
||||||
|
this.userDBService.addAllowed(body);
|
||||||
|
} catch (DBException e) {
|
||||||
|
logger.error("Adding new server configuration", e);
|
||||||
|
context.status(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
context.status(HttpStatus.CREATED);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delete(@NotNull Context context, @NotNull String s) {
|
||||||
|
try {
|
||||||
|
this.userDBService.deleteAllowed(Long.parseLong(s));
|
||||||
|
context.status(HttpStatus.NO_CONTENT);
|
||||||
|
} catch (DBException e) {
|
||||||
|
logger.error("Deleting configuration with id: " + s, e);
|
||||||
|
context.status(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void getAll(@NotNull Context context) {
|
||||||
|
try {
|
||||||
|
var allowedServers = this.userDBService.getAllAllowed();
|
||||||
|
context.json(allowedServers);
|
||||||
|
} catch (DBException e) {
|
||||||
|
logger.error("Getting all server configs", e);
|
||||||
|
context.status(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void getOne(@NotNull Context context, @NotNull String s) {
|
||||||
|
var id = Long.parseLong(s);
|
||||||
|
try {
|
||||||
|
var server = this.userDBService.getAllowedBy(id);
|
||||||
|
if (server.isEmpty()) {
|
||||||
|
context.status(HttpStatus.NOT_FOUND);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
context.json(server.get());
|
||||||
|
} catch (DBException e) {
|
||||||
|
logger.error("Searching for config with id: " + s, e);
|
||||||
|
context.status(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(@NotNull Context context, @NotNull String idString) {
|
||||||
|
var body = context.bodyAsClass(AllowedUser.NewAllowedUser.class);
|
||||||
|
var id = Long.parseLong(idString);
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.userDBService.updateAllowed(id, body);
|
||||||
|
} catch (DBException e) {
|
||||||
|
logger.error("Updating allowed server with id: " + idString, e);
|
||||||
|
context.status(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,12 +0,0 @@
|
||||||
*
|
|
||||||
!Caddyfile
|
|
||||||
!package*.json
|
|
||||||
!postcss.config.js
|
|
||||||
!tailwind.config.js
|
|
||||||
!env.d..ts
|
|
||||||
!vite.config.ts
|
|
||||||
!tsconfig.json
|
|
||||||
!tsconfig.node.json
|
|
||||||
!index.html
|
|
||||||
!public/
|
|
||||||
!src/
|
|
28
ui/.gitignore
vendored
28
ui/.gitignore
vendored
|
@ -1,28 +0,0 @@
|
||||||
# Logs
|
|
||||||
logs
|
|
||||||
*.log
|
|
||||||
npm-debug.log*
|
|
||||||
yarn-debug.log*
|
|
||||||
yarn-error.log*
|
|
||||||
pnpm-debug.log*
|
|
||||||
lerna-debug.log*
|
|
||||||
|
|
||||||
node_modules
|
|
||||||
.DS_Store
|
|
||||||
dist
|
|
||||||
dist-ssr
|
|
||||||
coverage
|
|
||||||
*.local
|
|
||||||
|
|
||||||
/cypress/videos/
|
|
||||||
/cypress/screenshots/
|
|
||||||
|
|
||||||
# Editor directories and files
|
|
||||||
.vscode/*
|
|
||||||
!.vscode/extensions.json
|
|
||||||
.idea
|
|
||||||
*.suo
|
|
||||||
*.ntvs*
|
|
||||||
*.njsproj
|
|
||||||
*.sln
|
|
||||||
*.sw?
|
|
3
ui/.vscode/extensions.json
vendored
3
ui/.vscode/extensions.json
vendored
|
@ -1,3 +0,0 @@
|
||||||
{
|
|
||||||
"recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"]
|
|
||||||
}
|
|
11
ui/Caddyfile
11
ui/Caddyfile
|
@ -1,11 +0,0 @@
|
||||||
{$SITE_ADDRESS} {
|
|
||||||
basicauth * {
|
|
||||||
{$AUTH_PASSWORD} {$AUTH_PASSWORD}
|
|
||||||
}
|
|
||||||
|
|
||||||
encode zstd gzip
|
|
||||||
|
|
||||||
root * /app
|
|
||||||
try_files {path} /index.html
|
|
||||||
file_server
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
FROM docker.io/node:18-slim AS build
|
|
||||||
WORKDIR /app
|
|
||||||
COPY ./package* .
|
|
||||||
RUN npm ci
|
|
||||||
COPY . .
|
|
||||||
RUN npm run build-only
|
|
||||||
|
|
||||||
FROM docker.io/caddy:2-alpine
|
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
COPY ./Caddyfile /
|
|
||||||
COPY --from=build /app/dist /app
|
|
||||||
|
|
||||||
EXPOSE 80
|
|
||||||
|
|
||||||
CMD ["caddy", "run", "--config", "/Caddyfile"]
|
|
40
ui/README.md
40
ui/README.md
|
@ -1,40 +0,0 @@
|
||||||
# dchat-ui
|
|
||||||
|
|
||||||
This template should help get you started developing with Vue 3 in Vite.
|
|
||||||
|
|
||||||
## Recommended IDE Setup
|
|
||||||
|
|
||||||
[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).
|
|
||||||
|
|
||||||
## Type Support for `.vue` Imports in TS
|
|
||||||
|
|
||||||
TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types.
|
|
||||||
|
|
||||||
If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps:
|
|
||||||
|
|
||||||
1. Disable the built-in TypeScript Extension
|
|
||||||
1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette
|
|
||||||
2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)`
|
|
||||||
2. Reload the VSCode window by running `Developer: Reload Window` from the command palette.
|
|
||||||
|
|
||||||
## Customize configuration
|
|
||||||
|
|
||||||
See [Vite Configuration Reference](https://vitejs.dev/config/).
|
|
||||||
|
|
||||||
## Project Setup
|
|
||||||
|
|
||||||
```sh
|
|
||||||
npm install
|
|
||||||
```
|
|
||||||
|
|
||||||
### Compile and Hot-Reload for Development
|
|
||||||
|
|
||||||
```sh
|
|
||||||
npm run dev
|
|
||||||
```
|
|
||||||
|
|
||||||
### Type-Check, Compile and Minify for Production
|
|
||||||
|
|
||||||
```sh
|
|
||||||
npm run build
|
|
||||||
```
|
|
31
ui/build.sh
31
ui/build.sh
|
@ -1,31 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
REPO="git.hhhammer.de/hamburghammer/dchat-ui"
|
|
||||||
AUTHORS="Augusto Dwenger J. <dwenger@posteo.de>"
|
|
||||||
URL="https://${REPO}"
|
|
||||||
VENDOR="hamburghammer"
|
|
||||||
TITLE="dchat-ui"
|
|
||||||
DESCRIPTION="The Web-UI for dchat a Discord bot to chat with ChatGPT from OpenAI"
|
|
||||||
CREATED=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
||||||
REVISION=$(git rev-parse HEAD)
|
|
||||||
|
|
||||||
IMAGE_LATEST="${REPO}:latest"
|
|
||||||
|
|
||||||
# shellcheck disable=SC2086
|
|
||||||
podman build \
|
|
||||||
$DOCKER_BUILD_ARGS \
|
|
||||||
-t $IMAGE_LATEST \
|
|
||||||
--label "org.opencontainers.image.revision=${REVISION}" \
|
|
||||||
--label "org.opencontainers.image.version=${TAG}" \
|
|
||||||
--label "org.opencontainers.image.authors=${AUTHORS}" \
|
|
||||||
--label "org.opencontainers.image.created=${CREATED}" \
|
|
||||||
--label "org.opencontainers.image.source=${URL}" \
|
|
||||||
--label "org.opencontainers.image.vendor=${VENDOR}" \
|
|
||||||
--label "org.opencontainers.image.title=${TITLE}" \
|
|
||||||
--label "org.opencontainers.image.description=${DESCRIPTION}" \
|
|
||||||
. || exit $?
|
|
||||||
|
|
||||||
if [ "$PUSH_LATEST" == "1" ]; then
|
|
||||||
podman push "${IMAGE_LATEST}"
|
|
||||||
fi
|
|
||||||
|
|
1
ui/env.d.ts
vendored
1
ui/env.d.ts
vendored
|
@ -1 +0,0 @@
|
||||||
/// <reference types="vite/client" />
|
|
|
@ -1,13 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<link rel="icon" href="/favicon.ico">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>Vite App</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="app"></div>
|
|
||||||
<script type="module" src="/src/main.ts"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
5046
ui/package-lock.json
generated
5046
ui/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -1,29 +0,0 @@
|
||||||
{
|
|
||||||
"name": "dchat-ui",
|
|
||||||
"version": "0.0.0",
|
|
||||||
"private": true,
|
|
||||||
"scripts": {
|
|
||||||
"dev": "vite",
|
|
||||||
"build": "run-p type-check build-only",
|
|
||||||
"preview": "vite preview",
|
|
||||||
"build-only": "vite build",
|
|
||||||
"type-check": "vue-tsc --noEmit"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"daisyui": "^2.51.5",
|
|
||||||
"vue": "^3.2.47",
|
|
||||||
"vue-router": "^4.1.6"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@types/node": "^18.14.2",
|
|
||||||
"@vitejs/plugin-vue": "^4.0.0",
|
|
||||||
"@vue/tsconfig": "^0.1.3",
|
|
||||||
"autoprefixer": "^10.4.14",
|
|
||||||
"npm-run-all": "^4.1.5",
|
|
||||||
"postcss": "^8.4.22",
|
|
||||||
"tailwindcss": "^3.3.1",
|
|
||||||
"typescript": "~4.8.4",
|
|
||||||
"vite": "^4.1.4",
|
|
||||||
"vue-tsc": "^1.2.0"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
module.exports = {
|
|
||||||
plugins: {
|
|
||||||
tailwindcss: {},
|
|
||||||
autoprefixer: {},
|
|
||||||
},
|
|
||||||
}
|
|
Binary file not shown.
Before Width: | Height: | Size: 4.2 KiB |
|
@ -1,37 +0,0 @@
|
||||||
<script setup lang="ts">
|
|
||||||
import { RouterView } from 'vue-router'
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<header>
|
|
||||||
<div class="navbar bg-base-100">
|
|
||||||
<div class="flex-1">
|
|
||||||
<a class="btn btn-ghost normal-case text-xl">
|
|
||||||
<RouterLink to="/">dchat</RouterLink>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<div class="flex-none">
|
|
||||||
<ul class="menu menu-horizontal px-1">
|
|
||||||
<li class="m-1">
|
|
||||||
<RouterLink to="/servers">Servers</RouterLink>
|
|
||||||
</li>
|
|
||||||
<li class="m-1">
|
|
||||||
<RouterLink to="/users">Users</RouterLink>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
<Suspense>
|
|
||||||
<RouterView />
|
|
||||||
</Suspense>
|
|
||||||
<footer class="footer footer-center p-4 bg-base-300 text-base-content">
|
|
||||||
<div>
|
|
||||||
<p>Copyright © 2023 Augusto Dwenger J.</p>
|
|
||||||
<p>This website is licensed under the <a href="https://git.hhhammer.de/hamburghammer/dchat/raw/branch/main/LICENSE"
|
|
||||||
class="link">MIT License</a>
|
|
||||||
and uses open source software. View the <a href="https://git.hhhammer.de/hamburghammer/dchat" class="link">source
|
|
||||||
code</a> on Forgejo.</p>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
</template>
|
|
|
@ -1,3 +0,0 @@
|
||||||
@tailwind base;
|
|
||||||
@tailwind components;
|
|
||||||
@tailwind utilities;
|
|
|
@ -1 +0,0 @@
|
||||||
@import './base.css';
|
|
|
@ -1,36 +0,0 @@
|
||||||
<script setup lang="ts">
|
|
||||||
export interface Props {
|
|
||||||
modalId: string | number,
|
|
||||||
openModal: { class: string, label: string },
|
|
||||||
isDestructive?: boolean,
|
|
||||||
submitAction: () => Promise<void>,
|
|
||||||
cancelAction?: () => Promise<void>,
|
|
||||||
onLoadAction?: () => Promise<void>
|
|
||||||
}
|
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
|
||||||
isDestructive: false,
|
|
||||||
cancelAction: () => Promise.resolve(),
|
|
||||||
onLoadAction: () => Promise.resolve()
|
|
||||||
})
|
|
||||||
const modalId = "modal-" + props.modalId
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<!-- The button to open modal -->
|
|
||||||
<label v-bind:for="modalId" v-bind:class="props.openModal.class" @click="props.onLoadAction">
|
|
||||||
{{ props.openModal.label }}
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<!-- Put this part before </body> tag -->
|
|
||||||
<input type="checkbox" v-bind:id="modalId" class="modal-toggle" />
|
|
||||||
<div class="modal">
|
|
||||||
<div class="modal-box">
|
|
||||||
<slot />
|
|
||||||
<div class="modal-action">
|
|
||||||
<label v-if="props.isDestructive" v-bind:for="modalId" class="btn btn-error" @click="props.submitAction">Delete</label>
|
|
||||||
<label v-else v-bind:for="modalId" class="btn btn-success" @click="props.submitAction">Save</label>
|
|
||||||
<label v-bind:for="modalId" class="btn" @click="props.cancelAction">Cancel</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
|
@ -1,35 +0,0 @@
|
||||||
<script lang="ts" setup>
|
|
||||||
// index arg being the index number of the row
|
|
||||||
type ActionFunction = (index: number) => void
|
|
||||||
const { tableHeader, tableRows, showActions } = defineProps<{
|
|
||||||
tableHeader: string[],
|
|
||||||
tableRows: any[][],
|
|
||||||
showActions: boolean
|
|
||||||
}>()
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<div class="overflow-x-auto">
|
|
||||||
<table class="table w-full">
|
|
||||||
<!-- head -->
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<template v-for="header in tableHeader">
|
|
||||||
<th>{{ header }}</th>
|
|
||||||
</template>
|
|
||||||
<th v-if="showActions">Action</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<!-- row -->
|
|
||||||
<tr v-for="row in tableRows">
|
|
||||||
<template v-for="data in row">
|
|
||||||
<th>{{ data }}</th>
|
|
||||||
</template>
|
|
||||||
<th>
|
|
||||||
<slot name="action" :row="row" />
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
|
@ -1,4 +0,0 @@
|
||||||
<script setup lang="ts">
|
|
||||||
const {id} = defineProps<{id: any}>()
|
|
||||||
debugger
|
|
||||||
</script>
|
|
|
@ -1,34 +0,0 @@
|
||||||
<script setup lang="ts">
|
|
||||||
import ModalComponent from '@/components/ModalComponent.vue';
|
|
||||||
import type { ServerConfig } from "@/models/server";
|
|
||||||
import { addConfig } from '@/services/ServerConfigs';
|
|
||||||
import { ref } from 'vue'
|
|
||||||
|
|
||||||
const modalId = "addServerConfig"
|
|
||||||
|
|
||||||
const newConfig = ref<ServerConfig | Record<string, never>>({})
|
|
||||||
const submitAction = async () => {
|
|
||||||
if (!newConfig) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return addConfig(newConfig.value as ServerConfig)
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<ModalComponent :modalId="modalId" :openModal="{ class: 'btn btn-circle btn-success', label: 'Add' }"
|
|
||||||
:submitAction="submitAction">
|
|
||||||
<h1 class="text-xl normal-case">Add Server Config</h1>
|
|
||||||
<div class="m-2">
|
|
||||||
<label class="mr-4">Server ID</label>
|
|
||||||
<input v-model="newConfig.serverId" class="input input-bordered w-full max-w-xs" />
|
|
||||||
</div>
|
|
||||||
<div class="m-2">
|
|
||||||
<label class="mr-4">System Message</label>
|
|
||||||
<textarea v-model="newConfig.systemMessage" class="textarea textarea-bordered w-2/3 h-2/3" />
|
|
||||||
</div>
|
|
||||||
<div class="m-2">
|
|
||||||
<label class="mr-4">Rate Limit</label>
|
|
||||||
<input v-model.number="newConfig.rateLimit" class="input input-bordered w-full max-w-xs" />
|
|
||||||
</div>
|
|
||||||
</ModalComponent>
|
|
||||||
</template>
|
|
|
@ -1,17 +0,0 @@
|
||||||
<script setup lang="ts">
|
|
||||||
import ModalComponent from '@/components/ModalComponent.vue';
|
|
||||||
import { deleteConfig } from '@/services/ServerConfigs';
|
|
||||||
|
|
||||||
const { id } = defineProps<{ id: number }>()
|
|
||||||
|
|
||||||
const submitAction = async () => {
|
|
||||||
return deleteConfig(id)
|
|
||||||
}
|
|
||||||
const modalId = "delete-" + id
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<ModalComponent :modalId="modalId" :openModal="{ class: 'btn btn-sm btn-error m-1', label: 'Delete' }"
|
|
||||||
:submitAction="submitAction" :isDestructive="true">
|
|
||||||
<h1 class="text-xl normal-case">Are you sure?</h1>
|
|
||||||
</ModalComponent>
|
|
||||||
</template>
|
|
|
@ -1,41 +0,0 @@
|
||||||
<script setup lang="ts">
|
|
||||||
import ModalComponent from '@/components/ModalComponent.vue';
|
|
||||||
import { getConfig } from '@/services/ServerConfigs'
|
|
||||||
import { ref } from 'vue';
|
|
||||||
import type { ServerConfig } from '@/models/server';
|
|
||||||
import { updateConfig } from '@/services/ServerConfigs';
|
|
||||||
|
|
||||||
const { id } = defineProps<{ id: number }>()
|
|
||||||
|
|
||||||
const configToEdit = ref<ServerConfig | Record<string, never>>({})
|
|
||||||
const submitAction = async () => {
|
|
||||||
return updateConfig(id, configToEdit.value as ServerConfig)
|
|
||||||
|
|
||||||
}
|
|
||||||
const onLoadAction = async () => {
|
|
||||||
configToEdit.value = await getConfig(id)
|
|
||||||
}
|
|
||||||
const modalId = "edit-" + id
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<ModalComponent :modalId="modalId" :openModal="{ class: 'btn btn-sm btn-info m-1', label: 'Edit' }"
|
|
||||||
:submitAction="submitAction" :onLoadAction="onLoadAction">
|
|
||||||
<h1 class="text-xl normal-case">Edit Server Config</h1>
|
|
||||||
<div class="m-2">
|
|
||||||
<label class="mr-4">ID</label>
|
|
||||||
<input v-model.number="configToEdit.id" class="input input-bordered w-full max-w-xs" disabled />
|
|
||||||
</div>
|
|
||||||
<div class="m-2">
|
|
||||||
<label class="mr-4">Server ID</label>
|
|
||||||
<input v-model="configToEdit.serverId" class="input input-bordered w-full max-w-xs" />
|
|
||||||
</div>
|
|
||||||
<div class="m-2">
|
|
||||||
<label class="mr-4">System Message</label>
|
|
||||||
<textarea v-model="configToEdit.systemMessage" class="textarea textarea-bordered w-2/3 h-2/3" />
|
|
||||||
</div>
|
|
||||||
<div class="m-2">
|
|
||||||
<label class="mr-4">Rate Limit</label>
|
|
||||||
<input v-model.number="configToEdit.rateLimit" class="input input-bordered w-full max-w-xs" />
|
|
||||||
</div>
|
|
||||||
</ModalComponent>
|
|
||||||
</template>
|
|
|
@ -1,35 +0,0 @@
|
||||||
<script setup lang="ts">
|
|
||||||
import ModalComponent from '@/components/ModalComponent.vue';
|
|
||||||
import type { UserConfig } from "@/models/user";
|
|
||||||
import { ref } from 'vue'
|
|
||||||
import { addConfig } from '@/services/UserConfigs';
|
|
||||||
|
|
||||||
const modalId = "addUserConfig"
|
|
||||||
|
|
||||||
const newConfig = ref<UserConfig | Record<string, never>>({})
|
|
||||||
const submitAction = async () => {
|
|
||||||
return addConfig(newConfig.value as UserConfig)
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<ModalComponent :modalId="modalId" :openModal="{ class: 'btn btn-circle btn-success', label: 'Add' }"
|
|
||||||
:submitAction="submitAction">
|
|
||||||
<h1 class="text-xl normal-case">Add User Config</h1>
|
|
||||||
<div class="m-2">
|
|
||||||
<label class="mr-4">User ID</label>
|
|
||||||
<input v-model="newConfig.userId" class="input input-bordered w-full max-w-xs" />
|
|
||||||
</div>
|
|
||||||
<div class="m-2">
|
|
||||||
<label class="mr-4">System Message</label>
|
|
||||||
<textarea v-model="newConfig.systemMessage" class="textarea textarea-bordered w-2/3 h-2/3" />
|
|
||||||
</div>
|
|
||||||
<div class="m-2">
|
|
||||||
<label class="mr-4">Context Length</label>
|
|
||||||
<input v-model.number="newConfig.contextLength" class="input input-bordered w-full max-w-xs" />
|
|
||||||
</div>
|
|
||||||
<div class="m-2">
|
|
||||||
<label class="mr-4">Rate Limit</label>
|
|
||||||
<input v-model.number="newConfig.rateLimit" class="input input-bordered w-full max-w-xs" />
|
|
||||||
</div>
|
|
||||||
</ModalComponent>
|
|
||||||
</template>
|
|
|
@ -1,17 +0,0 @@
|
||||||
<script setup lang="ts">
|
|
||||||
import ModalComponent from '@/components/ModalComponent.vue';
|
|
||||||
import { deleteConfig } from '@/services/UserConfigs';
|
|
||||||
|
|
||||||
const { id } = defineProps<{ id: number }>()
|
|
||||||
|
|
||||||
const submitAction = async () => {
|
|
||||||
return deleteConfig(id)
|
|
||||||
}
|
|
||||||
const modalId = "delete-" + id
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<ModalComponent :modalId="modalId" :openModal="{ class: 'btn btn-sm btn-error m-1', label: 'Delete' }"
|
|
||||||
:submitAction="submitAction" :isDestructive="true">
|
|
||||||
<h1 class="text-xl normal-case">Are you sure?</h1>
|
|
||||||
</ModalComponent>
|
|
||||||
</template>
|
|
|
@ -1,44 +0,0 @@
|
||||||
<script setup lang="ts">
|
|
||||||
import ModalComponent from '@/components/ModalComponent.vue';
|
|
||||||
import { getConfig } from '@/services/UserConfigs'
|
|
||||||
import { ref } from 'vue';
|
|
||||||
import type { UserConfig } from '@/models/user';
|
|
||||||
import { updateConfig } from '@/services/UserConfigs';
|
|
||||||
|
|
||||||
const { id } = defineProps<{ id: number }>()
|
|
||||||
|
|
||||||
const configToEdit = ref<UserConfig | Record<string, never>>({})
|
|
||||||
const submitAction = async () => {
|
|
||||||
return updateConfig(id, configToEdit.value as UserConfig)
|
|
||||||
}
|
|
||||||
const onLoadAction = async () => {
|
|
||||||
configToEdit.value = await getConfig(id)
|
|
||||||
}
|
|
||||||
const modalId = "edit-" + id
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<ModalComponent :modalId="modalId" :openModal="{ class: 'btn btn-sm btn-info m-1', label: 'Edit' }"
|
|
||||||
:submitAction="submitAction" :onLoadAction="onLoadAction">
|
|
||||||
<h1 class="text-xl normal-case">Edit User Config</h1>
|
|
||||||
<div class="m-2">
|
|
||||||
<label class="mr-4">ID</label>
|
|
||||||
<input v-model.number="configToEdit.id" class="input input-bordered w-full max-w-xs" disabled />
|
|
||||||
</div>
|
|
||||||
<div class="m-2">
|
|
||||||
<label class="mr-4">User ID</label>
|
|
||||||
<input v-model="configToEdit.userId" class="input input-bordered w-full max-w-xs" />
|
|
||||||
</div>
|
|
||||||
<div class="m-2">
|
|
||||||
<label class="mr-4">System Message</label>
|
|
||||||
<textarea v-model="configToEdit.systemMessage" class="textarea textarea-bordered w-2/3 h-2/3" />
|
|
||||||
</div>
|
|
||||||
<div class="m-2">
|
|
||||||
<label class="mr-4">Context Length</label>
|
|
||||||
<input v-model.number="configToEdit.contextLength" class="input input-bordered w-full max-w-xs" />
|
|
||||||
</div>
|
|
||||||
<div class="m-2">
|
|
||||||
<label class="mr-4">Rate Limit</label>
|
|
||||||
<input v-model.number="configToEdit.rateLimit" class="input input-bordered w-full max-w-xs" />
|
|
||||||
</div>
|
|
||||||
</ModalComponent>
|
|
||||||
</template>
|
|
|
@ -1,11 +0,0 @@
|
||||||
import { createApp } from 'vue'
|
|
||||||
import App from '@/App.vue'
|
|
||||||
import router from './router'
|
|
||||||
|
|
||||||
import './assets/main.css'
|
|
||||||
|
|
||||||
const app = createApp(App)
|
|
||||||
|
|
||||||
app.use(router)
|
|
||||||
|
|
||||||
app.mount('#app')
|
|
|
@ -1,8 +0,0 @@
|
||||||
export type ServerConfig = {
|
|
||||||
id: number,
|
|
||||||
serverId: string,
|
|
||||||
systemMessage: string,
|
|
||||||
rateLimit: number,
|
|
||||||
time: string
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
export type UserConfig = {
|
|
||||||
id: number,
|
|
||||||
userId: string,
|
|
||||||
systemMessage: string,
|
|
||||||
contextLength: number,
|
|
||||||
rateLimit: number,
|
|
||||||
time: string
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
import { createRouter, createWebHistory } from 'vue-router'
|
|
||||||
import HomeView from '@/views/HomeView.vue'
|
|
||||||
import IndexServersView from '@/views/servers/IndexServersView.vue'
|
|
||||||
import ServerConfigsView from '@/views/servers/ServerConfigsView.vue'
|
|
||||||
import IndexUsersView from '@/views/users/IndexUsersView.vue'
|
|
||||||
import UserConfigsView from '@/views/users/UserConfigsView.vue'
|
|
||||||
|
|
||||||
const routerConfig = createRouter({
|
|
||||||
history: createWebHistory(import.meta.env.BASE_URL),
|
|
||||||
routes: [
|
|
||||||
{
|
|
||||||
path: '/',
|
|
||||||
name: 'home',
|
|
||||||
component: HomeView
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/servers',
|
|
||||||
name: 'servers',
|
|
||||||
component: IndexServersView
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/servers/configs',
|
|
||||||
name: 'serverConfigs',
|
|
||||||
component: ServerConfigsView
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/users',
|
|
||||||
name: 'users',
|
|
||||||
component: IndexUsersView
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/users/configs',
|
|
||||||
name: 'userConfigs',
|
|
||||||
component: UserConfigsView
|
|
||||||
}
|
|
||||||
]
|
|
||||||
})
|
|
||||||
|
|
||||||
export default routerConfig
|
|
|
@ -1,39 +0,0 @@
|
||||||
import type { ServerConfig } from "@/models/server";
|
|
||||||
|
|
||||||
const configUrl = "http://localhost:7070/api/servers/configs/"
|
|
||||||
|
|
||||||
export async function getConfigs(): Promise<ServerConfig[]> {
|
|
||||||
return fetch(configUrl)
|
|
||||||
.then(shouldBeSuccess)
|
|
||||||
.then(res => res.json())
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getConfig(id: number): Promise<ServerConfig> {
|
|
||||||
return fetch(configUrl + id)
|
|
||||||
.then(shouldBeSuccess)
|
|
||||||
.then(res => res.json())
|
|
||||||
}
|
|
||||||
|
|
||||||
export function updateConfig(id: number, config: ServerConfig): Promise<void> {
|
|
||||||
return fetch(configUrl + id, { method: "PATCH", body: JSON.stringify(config) })
|
|
||||||
.then(shouldBeSuccess)
|
|
||||||
.then()
|
|
||||||
}
|
|
||||||
|
|
||||||
export function addConfig(config: ServerConfig): Promise<void> {
|
|
||||||
debugger
|
|
||||||
return fetch(configUrl, { method: "POST", body: JSON.stringify(config) })
|
|
||||||
.then(shouldBeSuccess)
|
|
||||||
.then()
|
|
||||||
}
|
|
||||||
|
|
||||||
export function deleteConfig(id: number): Promise<void> {
|
|
||||||
return fetch(configUrl + id, { method: "DELETE" })
|
|
||||||
.then(shouldBeSuccess)
|
|
||||||
.then()
|
|
||||||
}
|
|
||||||
|
|
||||||
function shouldBeSuccess(res: Response): Response {
|
|
||||||
if (res.status >= 200 && res.status < 300) return res
|
|
||||||
throw new Error(`Expected success status code but got: ${res.status} ${res.statusText}`)
|
|
||||||
}
|
|
|
@ -1,40 +0,0 @@
|
||||||
import type { UserConfig } from '@/models/user'
|
|
||||||
|
|
||||||
const configUrl = "http://localhost:7070/api/users/configs/"
|
|
||||||
|
|
||||||
export async function getConfigs(): Promise<UserConfig[]> {
|
|
||||||
return fetch(configUrl)
|
|
||||||
.then(shouldBeSuccess)
|
|
||||||
.then(res => res.json())
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getConfig(id: number): Promise<UserConfig> {
|
|
||||||
return fetch(configUrl + id)
|
|
||||||
.then(shouldBeSuccess)
|
|
||||||
.then(res => res.json())
|
|
||||||
}
|
|
||||||
|
|
||||||
export function updateConfig(id: number, config: UserConfig): Promise<void> {
|
|
||||||
return fetch(configUrl + id, { method: "PATCH", body: JSON.stringify(config) })
|
|
||||||
.then(shouldBeSuccess)
|
|
||||||
.then()
|
|
||||||
}
|
|
||||||
|
|
||||||
export function addConfig(config: UserConfig): Promise<void> {
|
|
||||||
debugger
|
|
||||||
return fetch(configUrl, { method: "POST", body: JSON.stringify(config) })
|
|
||||||
.then(shouldBeSuccess)
|
|
||||||
.then()
|
|
||||||
}
|
|
||||||
|
|
||||||
export function deleteConfig(id: number): Promise<void> {
|
|
||||||
return fetch(configUrl + id, { method: "DELETE" })
|
|
||||||
.then(shouldBeSuccess)
|
|
||||||
.then()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function shouldBeSuccess(res: Response): Response {
|
|
||||||
if (res.status >= 200 && res.status < 300) return res
|
|
||||||
throw new Error(`Expected success status code but got: ${res.status} ${res.statusText}`)
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
<template>
|
|
||||||
<h1 class="text-xl normal-case m-5">Overview</h1>
|
|
||||||
<div class="flex justify-center m-4">
|
|
||||||
<div class="flex flex-col space-y-2">
|
|
||||||
<RouterLink to="/servers">
|
|
||||||
<button class="btn btn-wide btn-outline">Servers</button>
|
|
||||||
</RouterLink>
|
|
||||||
<RouterLink to="/users">
|
|
||||||
<button class="btn btn-wide btn-outline">Users</button>
|
|
||||||
</RouterLink>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
|
@ -1,5 +0,0 @@
|
||||||
<script setup lang="ts">
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
|
|
||||||
</template>
|
|
|
@ -1,12 +0,0 @@
|
||||||
<script setup lang="ts">
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<h1 class="text-xl normal-case m-5">Server overview</h1>
|
|
||||||
<div class="flex justify-center m-4">
|
|
||||||
<div class="flex flex-col space-y-2">
|
|
||||||
<RouterLink to="/servers/configs">
|
|
||||||
<button class="btn btn-wide btn-outline">Configs</button>
|
|
||||||
</RouterLink>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
|
@ -1,27 +0,0 @@
|
||||||
<script setup lang="ts">
|
|
||||||
import TableComponent from '@/components/TableComponent.vue';
|
|
||||||
import AddServerConfig from '@/components/server/AddServerConfig.vue';
|
|
||||||
import { getConfigs } from '@/services/ServerConfigs'
|
|
||||||
import EditServerConfig from '@/components/server/EditServerConfig.vue';
|
|
||||||
import DeleteServerConfig from '@/components/server/DeleteServerConfig.vue';
|
|
||||||
|
|
||||||
const trimSystemMessage = (str: string) => str.length > 50 ? str.slice(0, 47) + "..." : str
|
|
||||||
|
|
||||||
const serverConfigs = await getConfigs()
|
|
||||||
|
|
||||||
const tableHeader = ["ID", "Server ID", "System Message", "Rate limit", "Created"]
|
|
||||||
const tableRows = serverConfigs.map(config => [config.id, config.serverId, trimSystemMessage(config.systemMessage), config.rateLimit, config.time])
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<div class="flex justify-between m-5">
|
|
||||||
<h1 class="text-xl normal-case">Server Configs</h1>
|
|
||||||
<AddServerConfig />
|
|
||||||
</div>
|
|
||||||
<TableComponent v-if="serverConfigs.length" :tableHeader="tableHeader" :tableRows="tableRows" :showActions="true">
|
|
||||||
<template #action="action">
|
|
||||||
<EditServerConfig :id="action.row[0]" />
|
|
||||||
<DeleteServerConfig :id="action.row[0]" />
|
|
||||||
</template>
|
|
||||||
</TableComponent>
|
|
||||||
<p v-else class="m-5">No server configs</p>
|
|
||||||
</template>
|
|
|
@ -1,12 +0,0 @@
|
||||||
<script setup lang="ts">
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<h1 class="text-xl normal-case m-5">Server overview</h1>
|
|
||||||
<div class="flex justify-center m-4">
|
|
||||||
<div class="flex flex-col space-y-2">
|
|
||||||
<RouterLink to="/users/configs">
|
|
||||||
<button class="btn btn-wide btn-outline">Configs</button>
|
|
||||||
</RouterLink>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
|
@ -1,27 +0,0 @@
|
||||||
<script setup lang="ts">
|
|
||||||
import TableComponent from '@/components/TableComponent.vue';
|
|
||||||
import AddUserConfig from '@/components/user/AddUserConfig.vue';
|
|
||||||
import { getConfigs } from '@/services/UserConfigs'
|
|
||||||
import EditUserConfig from '@/components/user/EditUserConfig.vue';
|
|
||||||
import DeleteServerConfig from '@/components/server/DeleteServerConfig.vue';
|
|
||||||
|
|
||||||
const trimSystemMessage = (str: string) => str.length > 50 ? str.slice(0, 47) + "..." : str
|
|
||||||
|
|
||||||
const userConfigs = await getConfigs()
|
|
||||||
|
|
||||||
const tableHeader = ["ID", "User ID", "System Message", "Context Length", "Rate limit", "Created"]
|
|
||||||
const tableRows = userConfigs.map(config => [config.id, config.userId, trimSystemMessage(config.systemMessage), config.contextLength, config.rateLimit, config.time])
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<div class="flex justify-between m-5">
|
|
||||||
<h1 class="text-xl normal-case">User Configs</h1>
|
|
||||||
<AddUserConfig />
|
|
||||||
</div>
|
|
||||||
<TableComponent v-if="userConfigs.length" :tableHeader="tableHeader" :tableRows="tableRows" :showActions="true">
|
|
||||||
<template #action="action">
|
|
||||||
<EditUserConfig :id="action.row[0]" />
|
|
||||||
<DeleteServerConfig :id="action.row[0]" />
|
|
||||||
</template>
|
|
||||||
</TableComponent>
|
|
||||||
<p v-else class="m-5">No user configs</p>
|
|
||||||
</template>
|
|
|
@ -1,9 +0,0 @@
|
||||||
/** @type {import('tailwindcss').Config} */
|
|
||||||
module.exports = {
|
|
||||||
content: ["./index.html", "./src/**/*.{vue,js,ts,jsx,tsx}"],
|
|
||||||
theme: {
|
|
||||||
extend: {},
|
|
||||||
},
|
|
||||||
plugins: [require("daisyui")],
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
{
|
|
||||||
"extends": "@vue/tsconfig/tsconfig.web.json",
|
|
||||||
"include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
|
|
||||||
"compilerOptions": {
|
|
||||||
"baseUrl": ".",
|
|
||||||
"paths": {
|
|
||||||
"@/*": ["./src/*"]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
"references": [
|
|
||||||
{
|
|
||||||
"path": "./tsconfig.node.json"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
{
|
|
||||||
"extends": "@vue/tsconfig/tsconfig.node.json",
|
|
||||||
"include": ["vite.config.*", "vitest.config.*", "cypress.config.*", "playwright.config.*"],
|
|
||||||
"compilerOptions": {
|
|
||||||
"composite": true,
|
|
||||||
"types": ["node"]
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
import { fileURLToPath, URL } from 'node:url'
|
|
||||||
|
|
||||||
import { defineConfig } from 'vite'
|
|
||||||
import vue from '@vitejs/plugin-vue'
|
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
|
||||||
export default defineConfig({
|
|
||||||
plugins: [vue()],
|
|
||||||
resolve: {
|
|
||||||
alias: {
|
|
||||||
'@': fileURLToPath(new URL('./src', import.meta.url))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
Loading…
Reference in a new issue