diff --git a/src/main/java/me/youhavetrouble/noted/Main.java b/src/main/java/me/youhavetrouble/noted/Main.java index f64cfbf..49df4d2 100644 --- a/src/main/java/me/youhavetrouble/noted/Main.java +++ b/src/main/java/me/youhavetrouble/noted/Main.java @@ -184,6 +184,24 @@ public class Main { ) .setContexts(InteractionContextType.BOT_DM) ).queue(); + + jda.upsertCommand(Commands.slash("add-alias", "Add alias to a note") + .setIntegrationTypes(IntegrationType.USER_INSTALL) + .addOptions( + new OptionData(OptionType.STRING, "alias", "Existing alias of a note", true, true), + new OptionData(OptionType.STRING, "new-alias", "New alias for the note", true) + ) + .setContexts(InteractionContextType.BOT_DM) + ).queue(); + + jda.upsertCommand(Commands.slash("delete-alias", "Remove alias to a note") + .setIntegrationTypes(IntegrationType.USER_INSTALL) + .addOptions( + new OptionData(OptionType.STRING, "alias", "Existing alias of a note", true, true) + ) + .setContexts(InteractionContextType.BOT_DM) + ).queue(); + } private static void loadProperties() { diff --git a/src/main/java/me/youhavetrouble/noted/Storage.java b/src/main/java/me/youhavetrouble/noted/Storage.java index 280c92c..9b1d1cc 100644 --- a/src/main/java/me/youhavetrouble/noted/Storage.java +++ b/src/main/java/me/youhavetrouble/noted/Storage.java @@ -37,7 +37,7 @@ public class Storage { 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)); + config.setMaximumPoolSize(Math.min(4, Runtime.getRuntime().availableProcessors() / 4)); dataSource = new HikariDataSource(config); try (Connection connection = dataSource.getConnection()) { @@ -174,11 +174,39 @@ public class Storage { aliases.add(alias); return Status.SUCCESS; } catch (SQLException e) { - logger.warning("Failed to add alias"); + logger.warning(e.getMessage()); return Status.ALIAS_EXISTS; } } + public Status deleteAlias(@NotNull String alias) { + try (Connection connection = dataSource.getConnection()) { + + Note note = getNote(alias); + if (note == null) { + return Status.ALIAS_NOT_FOUND; + } + + PreparedStatement statement = connection.prepareStatement("SELECT COUNT(*) FROM aliases WHERE alias = ?"); + statement.setString(1, alias); + ResultSet resultSet = statement.executeQuery(); + if (resultSet.next()) { + if (resultSet.getInt(1) <= 1) { + // Only one alias left, don't allow deletion + return Status.ALIAS_IS_REQUIRED; + } + } + + statement = connection.prepareStatement("DELETE FROM aliases WHERE alias = ?"); + statement.setString(1, alias); + statement.executeUpdate(); + aliases.remove(alias); + return Status.SUCCESS; + } catch (SQLException e) { + return Status.ERROR; + } + } + public Set getAliases() { try (Connection connection = dataSource.getConnection()) { PreparedStatement statement = connection.prepareStatement("SELECT alias FROM aliases"); @@ -239,6 +267,7 @@ public class Storage { SUCCESS, ALIAS_EXISTS, ALIAS_NOT_FOUND, + ALIAS_IS_REQUIRED, ERROR } diff --git a/src/main/java/me/youhavetrouble/noted/listener/SlashCommandListener.java b/src/main/java/me/youhavetrouble/noted/listener/SlashCommandListener.java index 38a1434..d04bed6 100644 --- a/src/main/java/me/youhavetrouble/noted/listener/SlashCommandListener.java +++ b/src/main/java/me/youhavetrouble/noted/listener/SlashCommandListener.java @@ -3,6 +3,7 @@ package me.youhavetrouble.noted.listener; import me.youhavetrouble.noted.Main; import me.youhavetrouble.noted.Storage; import me.youhavetrouble.noted.note.Note; +import net.dv8tion.jda.api.entities.User; import net.dv8tion.jda.api.events.interaction.command.CommandAutoCompleteInteractionEvent; import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; @@ -73,8 +74,7 @@ public class SlashCommandListener extends ListenerAdapter { switch (event.getName()) { case "add-note" -> { - Long adminId = Main.getAdminId(); - if (adminId == null || !adminId.equals(event.getUser().getIdLong())) { + if (!isAdmin(event.getUser())) { event.reply("You do not have permission to use this command.") .setEphemeral(true) .queue(); @@ -83,8 +83,7 @@ public class SlashCommandListener extends ListenerAdapter { addNote(event); } case "edit-note" -> { - Long adminId = Main.getAdminId(); - if (adminId == null || !adminId.equals(event.getUser().getIdLong())) { + if (!isAdmin(event.getUser())) { event.reply("You do not have permission to use this command.") .setEphemeral(true) .queue(); @@ -93,8 +92,7 @@ public class SlashCommandListener extends ListenerAdapter { editNote(event); } case "delete-note" -> { - Long adminId = Main.getAdminId(); - if (adminId == null || !adminId.equals(event.getUser().getIdLong())) { + if (!isAdmin(event.getUser())) { event.reply("You do not have permission to use this command.") .setEphemeral(true) .queue(); @@ -102,6 +100,24 @@ public class SlashCommandListener extends ListenerAdapter { } deleteNote(event); } + case "add-alias" -> { + if (!isAdmin(event.getUser())) { + event.reply("You do not have permission to use this command.") + .setEphemeral(true) + .queue(); + return; + } + addAlias(event); + } + case "delete-alias" -> { + if (!isAdmin(event.getUser())) { + event.reply("You do not have permission to use this command.") + .setEphemeral(true) + .queue(); + return; + } + deleteAlias(event); + } default -> event.reply("Unknown command.") .setEphemeral(true) @@ -109,6 +125,11 @@ public class SlashCommandListener extends ListenerAdapter { } } + private boolean isAdmin(User user) { + Long adminId = Main.getAdminId(); + return adminId != null && adminId.equals(user.getIdLong()); + } + private void getNote(SlashCommandInteractionEvent event, String noteAlias, boolean ephemeral) { Note note = Main.getStorage().getNote(noteAlias); if (note == null) { @@ -341,4 +362,81 @@ public class SlashCommandListener extends ListenerAdapter { } } + private void addAlias(SlashCommandInteractionEvent event) { + OptionMapping noteAliasMapping = event.getOption("alias"); + if (noteAliasMapping == null) { + event.reply("Please provide a note alias.") + .setEphemeral(true) + .queue(); + return; + } + OptionMapping newAliasMapping = event.getOption("new-alias"); + if (newAliasMapping == null) { + event.reply("Please provide a new alias.") + .setEphemeral(true) + .queue(); + return; + } + + String noteAlias = noteAliasMapping.getAsString(); + + Note note = Main.getStorage().getNote(noteAlias); + if (note == null) { + event.reply("Note with alias %s not found.".formatted(noteAlias)) + .setEphemeral(true) + .queue(); + return; + } + + Storage.Status status = Main.getStorage().addAlias(newAliasMapping.getAsString(), note.id); + if (status == Storage.Status.SUCCESS) { + aliases.add(newAliasMapping.getAsString()); + event.reply("Alias added.") + .setEphemeral(true) + .queue(); + } else if (status == Storage.Status.ALIAS_EXISTS) { + event.reply("Alias already exists.") + .setEphemeral(true) + .queue(); + } else { + event.reply("Failed to add alias.") + .setEphemeral(true) + .queue(); + } + + } + + private void deleteAlias(SlashCommandInteractionEvent event) { + OptionMapping aliasMapping = event.getOption("alias"); + if (aliasMapping == null) { + event.reply("Please provide a alias.") + .setEphemeral(true) + .queue(); + return; + } + + String alias = aliasMapping.getAsString(); + + Storage.Status status = Main.getStorage().deleteAlias(alias); + System.out.print(status); + switch (status) { + case SUCCESS -> { + aliases.remove(alias); + event.reply("Alias deleted.") + .setEphemeral(true) + .queue(); + } + case ALIAS_NOT_FOUND -> event.reply("Provided alias does not exist.") + .setEphemeral(true) + .queue(); + case ALIAS_IS_REQUIRED -> event.reply("At least one alias per note is required.") + .setEphemeral(true) + .queue(); + case null, default -> event.reply("Failed to delete alias.") + .setEphemeral(true) + .queue(); + } + + } + }