start storage implementation
This commit is contained in:
@@ -88,6 +88,23 @@
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.xerial</groupId>
|
||||
<artifactId>sqlite-jdbc</artifactId>
|
||||
<version>3.46.0.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.zaxxer</groupId>
|
||||
<artifactId>HikariCP</artifactId>
|
||||
<version>5.1.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.ben-manes.caffeine</groupId>
|
||||
<artifactId>caffeine</artifactId>
|
||||
<version>3.1.8</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -13,12 +13,15 @@ import java.io.*;
|
||||
import java.util.Collections;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
|
||||
public class Main {
|
||||
|
||||
private static final Logger logger = Logger.getLogger("Main");
|
||||
private static final Properties properties = new Properties();
|
||||
private static String version = "Unknown version";
|
||||
private static Storage storage;
|
||||
public static JDA jda;
|
||||
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
@@ -28,13 +31,17 @@ public class Main {
|
||||
if (resource != null) {
|
||||
version = new String(resource.readAllBytes());
|
||||
} else {
|
||||
System.err.println("Version file missing.");
|
||||
logger.severe("Version file missing.");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
System.out.println("Starting " + version);
|
||||
storage = new Storage();
|
||||
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(Main::shutdown));
|
||||
|
||||
logger.info("Starting " + version);
|
||||
|
||||
jda = JDABuilder.createLight(properties.getProperty("DISCORD_TOKEN"), Collections.emptyList())
|
||||
.setCallbackPool(Executors.newVirtualThreadPerTaskExecutor())
|
||||
@@ -73,7 +80,7 @@ public class Main {
|
||||
try (InputStream resource = Main.class.getClassLoader().getResourceAsStream("noted.properites");
|
||||
OutputStream outputStream = new FileOutputStream(file)) {
|
||||
if (resource == null) {
|
||||
System.err.println("Default noted.properties missing.");
|
||||
logger.severe("Default noted.properties missing.");
|
||||
return;
|
||||
}
|
||||
outputStream.write(resource.readAllBytes());
|
||||
@@ -86,4 +93,9 @@ public class Main {
|
||||
return version;
|
||||
}
|
||||
|
||||
private static void shutdown() {
|
||||
jda.shutdown();
|
||||
storage.shutdown();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,7 +4,6 @@ import me.youhavetrouble.noted.note.Note;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import net.dv8tion.jda.api.hooks.ListenerAdapter;
|
||||
import net.dv8tion.jda.api.interactions.commands.OptionMapping;
|
||||
import net.dv8tion.jda.api.requests.restaction.interactions.ReplyCallbackAction;
|
||||
|
||||
public class SlashCommandListener extends ListenerAdapter {
|
||||
|
||||
@@ -15,35 +14,42 @@ public class SlashCommandListener extends ListenerAdapter {
|
||||
OptionMapping noteIdOption = event.getOption("note-id");
|
||||
OptionMapping ephemeralOption = event.getOption("ephemeral");
|
||||
if (noteIdOption == null) {
|
||||
event.reply("Please provide a note ID.").setEphemeral(true).queue();
|
||||
event.reply("Please provide a note ID.")
|
||||
.setEphemeral(true)
|
||||
.queue();
|
||||
return;
|
||||
}
|
||||
Note note = new Note(
|
||||
"Sample Note Title",
|
||||
null,
|
||||
"Bottom text",
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
ReplyCallbackAction action = event.replyEmbeds(note.toEmbed());
|
||||
if (ephemeralOption != null && ephemeralOption.getAsBoolean()) {
|
||||
action = action.setEphemeral(true);
|
||||
}
|
||||
action.queue();
|
||||
|
||||
}
|
||||
|
||||
default -> {
|
||||
event.reply("Unknown command.").setEphemeral(true).queue();
|
||||
boolean ephemeral;
|
||||
try {
|
||||
ephemeral = ephemeralOption != null && ephemeralOption.getAsBoolean();
|
||||
} catch (IllegalArgumentException e) {
|
||||
event.reply("Invalid value for ephemeral.")
|
||||
.setEphemeral(true)
|
||||
.queue();
|
||||
return;
|
||||
}
|
||||
String noteId = noteIdOption.getAsString();
|
||||
getNote(event, noteId, ephemeral);
|
||||
}
|
||||
|
||||
default -> event.reply("Unknown command.")
|
||||
.setEphemeral(true)
|
||||
.queue();
|
||||
}
|
||||
}
|
||||
|
||||
private void getNote(SlashCommandInteractionEvent event, String noteId, boolean ephemeral) {
|
||||
Note note = Note.cache.getIfPresent(noteId);
|
||||
if (note == null) {
|
||||
event.reply("Note with ID %s not found.".formatted(noteId))
|
||||
.setEphemeral(true)
|
||||
.queue();
|
||||
return;
|
||||
}
|
||||
event.replyEmbeds(note.toEmbed())
|
||||
.setEphemeral(ephemeral)
|
||||
.queue();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
package me.youhavetrouble.noted;
|
||||
|
||||
import com.zaxxer.hikari.HikariConfig;
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.io.File;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
|
||||
|
||||
public class Storage {
|
||||
|
||||
private final Logger logger = Logger.getLogger("Storage");
|
||||
|
||||
private final DataSource dataSource;
|
||||
|
||||
public Storage() {
|
||||
File dataFolder = new File("data");
|
||||
if (!dataFolder.exists()) {
|
||||
if (!dataFolder.mkdir()) {
|
||||
throw new RuntimeException("Failed to create data folder");
|
||||
}
|
||||
}
|
||||
HikariConfig config = new HikariConfig();
|
||||
config.setPoolName("DataSQLitePool");
|
||||
config.setDriverClassName("org.sqlite.JDBC");
|
||||
config.setJdbcUrl("jdbc:sqlite:data/data.db");
|
||||
config.setConnectionTestQuery("SELECT 1");
|
||||
config.setMaxLifetime(60000); // 60 Sec
|
||||
config.setMaximumPoolSize(Math.min(1, Runtime.getRuntime().availableProcessors() / 4));
|
||||
dataSource = new HikariDataSource(config);
|
||||
|
||||
try (Connection connection = dataSource.getConnection()) {
|
||||
connection.createStatement().execute("PRAGMA journal_mode=WAL;");
|
||||
} catch (SQLException e) {
|
||||
logger.warning("Failed to set journal mode to WAL");
|
||||
}
|
||||
|
||||
createTables();
|
||||
|
||||
}
|
||||
|
||||
protected void shutdown() {
|
||||
if (dataSource instanceof HikariDataSource) {
|
||||
((HikariDataSource) dataSource).close();
|
||||
}
|
||||
}
|
||||
|
||||
private void createTables() {
|
||||
try (Connection connection = dataSource.getConnection()) {
|
||||
connection.createStatement().execute("""
|
||||
CREATE TABLE IF NOT EXISTS notes (
|
||||
id VARCHAR(36) NOT NULL PRIMARY KEY,
|
||||
title VARCHAR(256),
|
||||
title_url VARCHAR(2000),
|
||||
description VARCHAR(4096),
|
||||
image_url VARCHAR(2000),
|
||||
thumbnail_url VARCHAR(2000),
|
||||
color INTEGER,
|
||||
author VARCHAR(256),
|
||||
author_url VARCHAR(2000),
|
||||
footer VARCHAR(256),
|
||||
footer_url VARCHAR(2000)
|
||||
)
|
||||
""");
|
||||
connection.createStatement().execute("""
|
||||
CREATE TABLE IF NOT EXISTS aliases (
|
||||
alias VARCHAR(256) NOT NULL UNIQUE PRIMARY KEY,
|
||||
note_id VARCHAR(36) NOT NULL
|
||||
)
|
||||
""");
|
||||
} catch (SQLException e) {
|
||||
logger.warning("Failed to create tables");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,12 +1,34 @@
|
||||
package me.youhavetrouble.noted.note;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Cache;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import java.awt.Color;
|
||||
import java.time.Duration;
|
||||
|
||||
public record Note(
|
||||
public class Note {
|
||||
|
||||
public static final Cache<String, Note> cache = Caffeine.newBuilder()
|
||||
.maximumSize(100)
|
||||
.expireAfterWrite(Duration.ofMinutes(1))
|
||||
.build();
|
||||
|
||||
public final String title;
|
||||
public final String titleUrl;
|
||||
public final String content;
|
||||
public final String imageUrl;
|
||||
public final String thumbnailUrl;
|
||||
public final Color color;
|
||||
public final String author;
|
||||
public final String authorUrl;
|
||||
public final String footer;
|
||||
public final String footerUrl;
|
||||
|
||||
private Note(
|
||||
@NotNull String title,
|
||||
@Nullable String titleUrl,
|
||||
@NotNull String content,
|
||||
@@ -18,6 +40,17 @@ public record Note(
|
||||
@Nullable String footer,
|
||||
@Nullable String footerUrl
|
||||
) {
|
||||
this.title = title;
|
||||
this.titleUrl = titleUrl;
|
||||
this.content = content;
|
||||
this.imageUrl = imageUrl;
|
||||
this.thumbnailUrl = thumbnailUrl;
|
||||
this.color = color;
|
||||
this.author = author;
|
||||
this.authorUrl = authorUrl;
|
||||
this.footer = footer;
|
||||
this.footerUrl = footerUrl;
|
||||
}
|
||||
|
||||
public MessageEmbed toEmbed() {
|
||||
return new EmbedBuilder()
|
||||
|
||||
Reference in New Issue
Block a user