adding notes

This commit is contained in:
2024-08-06 23:14:28 +02:00
parent 0b8607d03b
commit 784f11206d
5 changed files with 214 additions and 15 deletions
@@ -8,6 +8,7 @@ import net.dv8tion.jda.api.interactions.InteractionContextType;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.build.Commands; import net.dv8tion.jda.api.interactions.commands.build.Commands;
import net.dv8tion.jda.api.interactions.commands.build.OptionData; import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.jetbrains.annotations.Nullable;
import java.io.*; import java.io.*;
import java.util.Collections; import java.util.Collections;
@@ -22,6 +23,7 @@ public class 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; private static Storage storage;
private static Long adminId;
public static JDA jda; public static JDA jda;
public static void main(String[] args) throws InterruptedException { public static void main(String[] args) throws InterruptedException {
@@ -43,6 +45,8 @@ public class Main {
logger.info("Starting " + version); logger.info("Starting " + version);
adminId = Long.parseLong(properties.getProperty("ADMIN_USER_ID"));
jda = JDABuilder.createLight(properties.getProperty("DISCORD_TOKEN"), Collections.emptyList()) jda = JDABuilder.createLight(properties.getProperty("DISCORD_TOKEN"), Collections.emptyList())
.setCallbackPool(Executors.newVirtualThreadPerTaskExecutor()) .setCallbackPool(Executors.newVirtualThreadPerTaskExecutor())
.setActivity(Activity.customStatus("Notekeeping...")) .setActivity(Activity.customStatus("Notekeeping..."))
@@ -58,8 +62,24 @@ public class Main {
new OptionData(OptionType.BOOLEAN, "ephermeal", "Whether the note should be ephermal").setRequired(false) new OptionData(OptionType.BOOLEAN, "ephermeal", "Whether the note should be ephermal").setRequired(false)
) )
.setContexts(InteractionContextType.BOT_DM, InteractionContextType.GUILD, InteractionContextType.PRIVATE_CHANNEL) .setContexts(InteractionContextType.BOT_DM, InteractionContextType.GUILD, InteractionContextType.PRIVATE_CHANNEL)
) ).queue();
.queue();
jda.upsertCommand(Commands.slash("add-note", "Add a note")
.setIntegrationTypes(IntegrationType.GUILD_INSTALL, IntegrationType.USER_INSTALL)
.addOptions(
new OptionData(OptionType.STRING, "alias", "An alias for the note").setRequired(true),
new OptionData(OptionType.STRING, "title", "The title of the note").setRequired(true),
new OptionData(OptionType.STRING, "content", "The content of the note").setRequired(true),
new OptionData(OptionType.STRING, "image-url", "The image URL of the note").setRequired(false),
new OptionData(OptionType.STRING, "thumbnail-url", "The thumbnail URL of the note").setRequired(false),
new OptionData(OptionType.STRING, "color", "The color of the note").setRequired(false),
new OptionData(OptionType.STRING, "author", "The author of the note").setRequired(false),
new OptionData(OptionType.STRING, "author-url", "The author URL of the note").setRequired(false),
new OptionData(OptionType.STRING, "footer", "The footer of the note").setRequired(false),
new OptionData(OptionType.STRING, "footer-url", "The footer URL of the note").setRequired(false)
)
.setContexts(InteractionContextType.BOT_DM)
).queue();
} }
@@ -89,10 +109,19 @@ public class Main {
} }
} }
@Nullable
public static Long getAdminId() {
return adminId;
}
public static String getVersion() { public static String getVersion() {
return version; return version;
} }
public static Storage getStorage() {
return storage;
}
private static void shutdown() { private static void shutdown() {
jda.shutdown(); jda.shutdown();
storage.shutdown(); storage.shutdown();
@@ -19,7 +19,6 @@ public class SlashCommandListener extends ListenerAdapter {
.queue(); .queue();
return; return;
} }
boolean ephemeral; boolean ephemeral;
try { try {
ephemeral = ephemeralOption != null && ephemeralOption.getAsBoolean(); ephemeral = ephemeralOption != null && ephemeralOption.getAsBoolean();
@@ -32,6 +31,29 @@ public class SlashCommandListener extends ListenerAdapter {
String noteId = noteIdOption.getAsString(); String noteId = noteIdOption.getAsString();
getNote(event, noteId, ephemeral); getNote(event, noteId, ephemeral);
} }
case "add-note" -> {
Long adminId = Main.getAdminId();
if (adminId == null || !adminId.equals(event.getUser().getIdLong())) {
event.reply("You do not have permission to use this command.")
.setEphemeral(true)
.queue();
return;
}
OptionMapping aliasOption = event.getOption("alias");
OptionMapping titleOption = event.getOption("title");
OptionMapping contentOption = event.getOption("content");
if (titleOption == null || contentOption == null || aliasOption == null) {
event.reply("Please provide a alias, title and content.")
.setEphemeral(true)
.queue();
return;
}
String alias = aliasOption.getAsString();
String title = titleOption.getAsString();
String content = contentOption.getAsString();
addNote(event, alias, title, content);
}
default -> event.reply("Unknown command.") default -> event.reply("Unknown command.")
.setEphemeral(true) .setEphemeral(true)
@@ -39,17 +61,40 @@ public class SlashCommandListener extends ListenerAdapter {
} }
} }
private void getNote(SlashCommandInteractionEvent event, String noteId, boolean ephemeral) { private void getNote(SlashCommandInteractionEvent event, String noteAlias, boolean ephemeral) {
Note note = Note.cache.getIfPresent(noteId); Note note = Main.getStorage().getNote(noteAlias);
if (note == null) { if (note == null) {
event.reply("Note with ID %s not found.".formatted(noteId)) event.reply("Note with ID %s not found.".formatted(noteAlias))
.setEphemeral(true) .setEphemeral(true)
.queue(); .queue();
return; return;
} }
event.replyEmbeds(note.toEmbed()) event.replyEmbeds(note.toEmbed())
.setEphemeral(ephemeral) .setEphemeral(ephemeral)
.queue(); .queue();
} }
private void addNote(SlashCommandInteractionEvent event, String noteAlias, String title, String description) {
Note note = Note.createNew(title, description);
Storage.Status status = Main.getStorage().addNote(note, noteAlias);
if (status == Storage.Status.ALIAS_EXISTS) {
event.reply("Alias already exists.")
.setEphemeral(true)
.queue();
return;
}
if (status == Storage.Status.ERROR) {
event.reply("An error occurred.")
.setEphemeral(true)
.queue();
return;
}
event.reply("Note added.")
.setEphemeral(true)
.queue();
}
} }
@@ -2,11 +2,18 @@ package me.youhavetrouble.noted;
import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource; import com.zaxxer.hikari.HikariDataSource;
import me.youhavetrouble.noted.note.Note;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.sql.DataSource; import javax.sql.DataSource;
import java.awt.*;
import java.io.File; import java.io.File;
import java.sql.Connection; import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.UUID;
import java.util.logging.Logger; import java.util.logging.Logger;
@@ -77,4 +84,105 @@ public class Storage {
} }
} }
public Status addNote(@NotNull Note note, @NotNull String alias) {
try (Connection connection = dataSource.getConnection()) {
connection.setAutoCommit(false);
PreparedStatement statement = connection.prepareStatement("""
INSERT INTO notes (id, title, title_url, description, image_url, thumbnail_url, color, author, author_url, footer, footer_url)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""");
statement.setString(1, note.id.toString());
statement.setString(2, note.title);
statement.setString(3, note.titleUrl);
statement.setString(4, note.content);
statement.setString(5, note.imageUrl);
statement.setString(6, note.thumbnailUrl);
statement.setInt(7, note.color != null ? note.color.getRGB() : 0);
statement.setString(8, note.author);
statement.setString(9, note.authorUrl);
statement.setString(10, note.footer);
statement.setString(11, note.footerUrl);
statement.executeUpdate();
statement = connection.prepareStatement("""
INSERT INTO aliases (alias, note_id)
VALUES (?, ?)
""");
statement.setString(1, alias);
statement.setString(2, note.id.toString());
statement.executeUpdate();
connection.commit();
return Status.SUCCESS;
} catch (SQLException e) {
if (e.getErrorCode() == 19) {
return Status.ALIAS_EXISTS;
}
return Status.ERROR;
}
}
public Status addAlias(@NotNull String alias, @NotNull UUID noteId) throws RuntimeException {
try (Connection connection = dataSource.getConnection()) {
PreparedStatement statement = connection.prepareStatement("""
INSERT INTO aliases (alias, note_id)
VALUES (?, ?)
""");
statement.setString(1, alias);
statement.setString(2, noteId.toString());
statement.executeUpdate();
return Status.SUCCESS;
} catch (SQLException e) {
logger.warning("Failed to add alias");
return Status.ALIAS_EXISTS;
}
}
@Nullable
public Note getNote(@NotNull String alias) {
try (Connection connection = dataSource.getConnection()) {
PreparedStatement statement = connection.prepareStatement("""
SELECT * FROM notes
WHERE id = (
SELECT note_id FROM aliases
WHERE alias = ?
)
""");
statement.setString(1, alias);
ResultSet resultSet = statement.executeQuery();
Color color = null;
try {
color = new Color(resultSet.getInt("color"));
} catch (SQLException ignored) {
}
return new Note(
UUID.fromString(resultSet.getString("id")),
resultSet.getString("title"),
resultSet.getString("title_url"),
resultSet.getString("description"),
resultSet.getString("image_url"),
resultSet.getString("thumbnail_url"),
color,
resultSet.getString("author"),
resultSet.getString("author_url"),
resultSet.getString("footer"),
resultSet.getString("footer_url")
);
} catch (SQLException e) {
logger.warning("Failed to get note");
return null;
}
}
public enum Status {
SUCCESS,
ALIAS_EXISTS,
ALIAS_NOT_FOUND,
ERROR
}
} }
@@ -1,22 +1,16 @@
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; import java.util.UUID;
public class Note { public class Note {
public static final Cache<String, Note> cache = Caffeine.newBuilder() public final UUID id;
.maximumSize(100)
.expireAfterWrite(Duration.ofMinutes(1))
.build();
public final String title; public final String title;
public final String titleUrl; public final String titleUrl;
public final String content; public final String content;
@@ -28,7 +22,8 @@ public class Note {
public final String footer; public final String footer;
public final String footerUrl; public final String footerUrl;
private Note( public Note(
@NotNull UUID id,
@NotNull String title, @NotNull String title,
@Nullable String titleUrl, @Nullable String titleUrl,
@NotNull String content, @NotNull String content,
@@ -40,6 +35,7 @@ public class Note {
@Nullable String footer, @Nullable String footer,
@Nullable String footerUrl @Nullable String footerUrl
) { ) {
this.id = id;
this.title = title; this.title = title;
this.titleUrl = titleUrl; this.titleUrl = titleUrl;
this.content = content; this.content = content;
@@ -64,4 +60,24 @@ public class Note {
.build(); .build();
} }
public static Note createNew(
@NotNull String title,
@NotNull String content
) {
UUID id = UUID.randomUUID();
return new Note(
id,
title,
null,
content,
null,
null,
null,
null,
null,
null,
null
);
}
} }
+1
View File
@@ -1 +1,2 @@
DISCORD_TOKEN=your_bot_token_here DISCORD_TOKEN=your_bot_token_here
ADMIN_USER_ID=your_user_id_here