start storage implementation
This commit is contained in:
@@ -88,6 +88,23 @@
|
|||||||
</exclusion>
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</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>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
@@ -13,12 +13,15 @@ import java.io.*;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
|
||||||
public class Main {
|
public class Main {
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.getLogger("Main");
|
||||||
private static final Properties properties = new Properties();
|
private static final Properties properties = new Properties();
|
||||||
private static String version = "Unknown version";
|
private static String version = "Unknown version";
|
||||||
|
private static Storage storage;
|
||||||
public static JDA jda;
|
public static JDA jda;
|
||||||
|
|
||||||
public static void main(String[] args) throws InterruptedException {
|
public static void main(String[] args) throws InterruptedException {
|
||||||
@@ -28,13 +31,17 @@ public class Main {
|
|||||||
if (resource != null) {
|
if (resource != null) {
|
||||||
version = new String(resource.readAllBytes());
|
version = new String(resource.readAllBytes());
|
||||||
} else {
|
} else {
|
||||||
System.err.println("Version file missing.");
|
logger.severe("Version file missing.");
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(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())
|
jda = JDABuilder.createLight(properties.getProperty("DISCORD_TOKEN"), Collections.emptyList())
|
||||||
.setCallbackPool(Executors.newVirtualThreadPerTaskExecutor())
|
.setCallbackPool(Executors.newVirtualThreadPerTaskExecutor())
|
||||||
@@ -73,7 +80,7 @@ public class Main {
|
|||||||
try (InputStream resource = Main.class.getClassLoader().getResourceAsStream("noted.properites");
|
try (InputStream resource = Main.class.getClassLoader().getResourceAsStream("noted.properites");
|
||||||
OutputStream outputStream = new FileOutputStream(file)) {
|
OutputStream outputStream = new FileOutputStream(file)) {
|
||||||
if (resource == null) {
|
if (resource == null) {
|
||||||
System.err.println("Default noted.properties missing.");
|
logger.severe("Default noted.properties missing.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
outputStream.write(resource.readAllBytes());
|
outputStream.write(resource.readAllBytes());
|
||||||
@@ -86,4 +93,9 @@ public class Main {
|
|||||||
return version;
|
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.events.interaction.command.SlashCommandInteractionEvent;
|
||||||
import net.dv8tion.jda.api.hooks.ListenerAdapter;
|
import net.dv8tion.jda.api.hooks.ListenerAdapter;
|
||||||
import net.dv8tion.jda.api.interactions.commands.OptionMapping;
|
import net.dv8tion.jda.api.interactions.commands.OptionMapping;
|
||||||
import net.dv8tion.jda.api.requests.restaction.interactions.ReplyCallbackAction;
|
|
||||||
|
|
||||||
public class SlashCommandListener extends ListenerAdapter {
|
public class SlashCommandListener extends ListenerAdapter {
|
||||||
|
|
||||||
@@ -15,35 +14,42 @@ public class SlashCommandListener extends ListenerAdapter {
|
|||||||
OptionMapping noteIdOption = event.getOption("note-id");
|
OptionMapping noteIdOption = event.getOption("note-id");
|
||||||
OptionMapping ephemeralOption = event.getOption("ephemeral");
|
OptionMapping ephemeralOption = event.getOption("ephemeral");
|
||||||
if (noteIdOption == null) {
|
if (noteIdOption == null) {
|
||||||
event.reply("Please provide a note ID.").setEphemeral(true).queue();
|
event.reply("Please provide a note ID.")
|
||||||
|
.setEphemeral(true)
|
||||||
|
.queue();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Note note = new Note(
|
|
||||||
"Sample Note Title",
|
|
||||||
null,
|
|
||||||
"Bottom text",
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null
|
|
||||||
);
|
|
||||||
|
|
||||||
ReplyCallbackAction action = event.replyEmbeds(note.toEmbed());
|
boolean ephemeral;
|
||||||
if (ephemeralOption != null && ephemeralOption.getAsBoolean()) {
|
try {
|
||||||
action = action.setEphemeral(true);
|
ephemeral = ephemeralOption != null && ephemeralOption.getAsBoolean();
|
||||||
}
|
} catch (IllegalArgumentException e) {
|
||||||
action.queue();
|
event.reply("Invalid value for ephemeral.")
|
||||||
|
.setEphemeral(true)
|
||||||
}
|
.queue();
|
||||||
|
|
||||||
default -> {
|
|
||||||
event.reply("Unknown command.").setEphemeral(true).queue();
|
|
||||||
return;
|
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;
|
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.EmbedBuilder;
|
||||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import java.awt.Color;
|
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,
|
@NotNull String title,
|
||||||
@Nullable String titleUrl,
|
@Nullable String titleUrl,
|
||||||
@NotNull String content,
|
@NotNull String content,
|
||||||
@@ -18,6 +40,17 @@ public record Note(
|
|||||||
@Nullable String footer,
|
@Nullable String footer,
|
||||||
@Nullable String footerUrl
|
@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() {
|
public MessageEmbed toEmbed() {
|
||||||
return new EmbedBuilder()
|
return new EmbedBuilder()
|
||||||
|
|||||||
Reference in New Issue
Block a user