From 82a0f70dd9e5d1474ca72021b87a900236834966 Mon Sep 17 00:00:00 2001 From: excale Date: Tue, 14 Sep 2021 02:45:55 +0200 Subject: [PATCH 01/46] Maintenance mode, MessageCommands * Added maintenance mode, where only MessageCommands work * Added MessageCommands, the old command format typed in chat without slash --- .../excale/vgreeter/VGreeterApplication.java | 28 ++- .../vgreeter/commands/AltnameCommand.java | 3 +- .../vgreeter/commands/CommandRegister.java | 93 -------- .../vgreeter/commands/PlaytestCommand.java | 3 +- .../vgreeter/commands/ProbabilityCommand.java | 3 +- .../vgreeter/commands/RestartCommand.java | 39 ++++ .../vgreeter/commands/TrackIndexCommand.java | 3 +- .../vgreeter/commands/TracknameCommand.java | 3 +- .../vgreeter/commands/UploadCommand.java | 167 +++++++++++-- .../vgreeter/commands/UploadHelpCommand.java | 36 +++ .../commands/core/AbstractMessageCommand.java | 39 ++++ .../AbstractSlashCommand.java} | 7 +- .../commands/core/CommandRegister.java | 144 ++++++++++++ .../services/DiscordEventHandlerService.java | 220 ------------------ .../vgreeter/services/DiscordService.java | 31 ++- .../services/VoiceChannelHandler.java | 99 ++++++++ .../vgreeter/utilities/ArgumentsParser.java | 90 +++++++ 17 files changed, 651 insertions(+), 357 deletions(-) delete mode 100644 src/main/java/ovh/excale/vgreeter/commands/CommandRegister.java create mode 100644 src/main/java/ovh/excale/vgreeter/commands/RestartCommand.java create mode 100644 src/main/java/ovh/excale/vgreeter/commands/UploadHelpCommand.java create mode 100644 src/main/java/ovh/excale/vgreeter/commands/core/AbstractMessageCommand.java rename src/main/java/ovh/excale/vgreeter/commands/{AbstractCommand.java => core/AbstractSlashCommand.java} (79%) create mode 100644 src/main/java/ovh/excale/vgreeter/commands/core/CommandRegister.java delete mode 100644 src/main/java/ovh/excale/vgreeter/services/DiscordEventHandlerService.java create mode 100644 src/main/java/ovh/excale/vgreeter/services/VoiceChannelHandler.java create mode 100644 src/main/java/ovh/excale/vgreeter/utilities/ArgumentsParser.java diff --git a/src/main/java/ovh/excale/vgreeter/VGreeterApplication.java b/src/main/java/ovh/excale/vgreeter/VGreeterApplication.java index 05c7c5d..2c055be 100644 --- a/src/main/java/ovh/excale/vgreeter/VGreeterApplication.java +++ b/src/main/java/ovh/excale/vgreeter/VGreeterApplication.java @@ -11,11 +11,14 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; +import org.springframework.context.ConfigurableApplicationContext; @SpringBootApplication public class VGreeterApplication implements CommandLineRunner, ApplicationContextAware { - private static ApplicationContext ctx; + @Value("${env.VGREETER_MAINTENANCE:false}") + private static boolean maintenance; + private static ConfigurableApplicationContext ctx; public static void main(String[] args) { @@ -25,6 +28,27 @@ public static void main(String[] args) { } + public static void restart(boolean maintenance) { + + Thread thread = new Thread(() -> { + ctx.close(); + ctx = SpringApplication.run(VGreeterApplication.class); + // TODO: MAINTENANCE AS APPLICATION ARGUMENT + VGreeterApplication.setMaintenance(maintenance); + }); + + thread.setDaemon(false); + thread.start(); + } + + public static boolean isInMaintenance() { + return maintenance; + } + + public static void setMaintenance(boolean maintenanceOn) { + maintenance = maintenanceOn; + } + public static ApplicationContext getApplicationContext() { return ctx; } @@ -44,7 +68,7 @@ public void run(String[] args) { @Override public void setApplicationContext(@NotNull ApplicationContext context) throws BeansException { - ctx = context; + ctx = (ConfigurableApplicationContext) context; } } diff --git a/src/main/java/ovh/excale/vgreeter/commands/AltnameCommand.java b/src/main/java/ovh/excale/vgreeter/commands/AltnameCommand.java index f1120d1..7a5e4f3 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/AltnameCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/AltnameCommand.java @@ -6,13 +6,14 @@ import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.requests.restaction.interactions.ReplyAction; import ovh.excale.vgreeter.VGreeterApplication; +import ovh.excale.vgreeter.commands.core.AbstractSlashCommand; import ovh.excale.vgreeter.models.UserModel; import ovh.excale.vgreeter.repositories.UserRepository; import java.util.Optional; import java.util.regex.Pattern; -public class AltnameCommand extends AbstractCommand { +public class AltnameCommand extends AbstractSlashCommand { private static final Pattern ALTNAME_PATTERN = Pattern.compile("[\\w\\d-_]{3,}"); diff --git a/src/main/java/ovh/excale/vgreeter/commands/CommandRegister.java b/src/main/java/ovh/excale/vgreeter/commands/CommandRegister.java deleted file mode 100644 index 0604d44..0000000 --- a/src/main/java/ovh/excale/vgreeter/commands/CommandRegister.java +++ /dev/null @@ -1,93 +0,0 @@ -package ovh.excale.vgreeter.commands; - -import net.dv8tion.jda.api.events.GenericEvent; -import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; -import net.dv8tion.jda.api.exceptions.ErrorResponseException; -import net.dv8tion.jda.api.hooks.EventListener; -import net.dv8tion.jda.api.interactions.commands.build.CommandData; -import net.dv8tion.jda.api.requests.restaction.interactions.ReplyAction; -import org.jetbrains.annotations.NotNull; -import org.springframework.stereotype.Service; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -@Service -public class CommandRegister { - - private final Map commands; - private final Listener listener; - - private CommandRegister() { - commands = new HashMap<>(); - listener = new Listener(); - } - - public CommandRegister register(AbstractCommand command) { - - commands.put(command.getName(), command); - if(command.hasListener()) - listener.register(command.getListener()); - - return this; - - } - - public CommandData[] getData() { - return commands - .values() - .stream() - .map(AbstractCommand::getData) - .toArray(CommandData[]::new); - } - - public Listener getListener() { - return listener; - } - - private class Listener implements EventListener { - - public Set commandListeners; - - protected Listener() { - commandListeners = new HashSet<>(); - } - - protected void register(EventListener listener) { - commandListeners.add(listener); - } - - @Override - public void onEvent(@NotNull GenericEvent genericEvent) { - - if(genericEvent instanceof SlashCommandEvent) - onSlashCommand((SlashCommandEvent) genericEvent); - else - for(EventListener commandListener : commandListeners) - commandListener.onEvent(genericEvent); - - } - - private void onSlashCommand(SlashCommandEvent event) { - - AbstractCommand command = commands.get(event.getName()); - ReplyAction action; - - if(command == null) - action = event - .reply("No such command") - .setEphemeral(true); - else - action = command.execute(event); - - try { - action.queue(); - } catch(ErrorResponseException ignored) { - } - } - - } - -} diff --git a/src/main/java/ovh/excale/vgreeter/commands/PlaytestCommand.java b/src/main/java/ovh/excale/vgreeter/commands/PlaytestCommand.java index 46c996b..f4e65f6 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/PlaytestCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/PlaytestCommand.java @@ -11,6 +11,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import ovh.excale.vgreeter.VGreeterApplication; +import ovh.excale.vgreeter.commands.core.AbstractSlashCommand; import ovh.excale.vgreeter.models.TrackModel; import ovh.excale.vgreeter.repositories.TrackRepository; import ovh.excale.vgreeter.services.DiscordService; @@ -19,7 +20,7 @@ import java.util.Optional; import java.util.Set; -public class PlaytestCommand extends AbstractCommand { +public class PlaytestCommand extends AbstractSlashCommand { private static final Logger logger = LoggerFactory.getLogger(PlaytestCommand.class); diff --git a/src/main/java/ovh/excale/vgreeter/commands/ProbabilityCommand.java b/src/main/java/ovh/excale/vgreeter/commands/ProbabilityCommand.java index f2bb88c..cea7a25 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/ProbabilityCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/ProbabilityCommand.java @@ -8,12 +8,13 @@ import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.requests.restaction.interactions.ReplyAction; import ovh.excale.vgreeter.VGreeterApplication; +import ovh.excale.vgreeter.commands.core.AbstractSlashCommand; import ovh.excale.vgreeter.models.GuildModel; import ovh.excale.vgreeter.repositories.GuildRepository; import java.util.Optional; -public class ProbabilityCommand extends AbstractCommand { +public class ProbabilityCommand extends AbstractSlashCommand { private final GuildRepository guildRepo; diff --git a/src/main/java/ovh/excale/vgreeter/commands/RestartCommand.java b/src/main/java/ovh/excale/vgreeter/commands/RestartCommand.java new file mode 100644 index 0000000..28dc546 --- /dev/null +++ b/src/main/java/ovh/excale/vgreeter/commands/RestartCommand.java @@ -0,0 +1,39 @@ +package ovh.excale.vgreeter.commands; + +import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.events.message.priv.PrivateMessageReceivedEvent; +import net.dv8tion.jda.api.requests.RestAction; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import ovh.excale.vgreeter.VGreeterApplication; +import ovh.excale.vgreeter.commands.core.AbstractMessageCommand; +import ovh.excale.vgreeter.utilities.ArgumentsParser; + +// TODO: OWNER/MOD ONLY +public class RestartCommand extends AbstractMessageCommand { + + public RestartCommand() { + super("restart", ""); + } + + @Override + public @Nullable RestAction execute(@NotNull PrivateMessageReceivedEvent event) { + + Message message = event.getMessage(); + ArgumentsParser arguments = new ArgumentsParser(message.getContentRaw()); + + boolean maintenance = arguments.getArgumentBoolean(1, false); + String restartMessage = maintenance ? "*Restarting on maintenance mode...*" : "*Restarting...*"; + + message + .reply(restartMessage) + .complete(); + + VGreeterApplication.restart(maintenance); + + // TODO: SUCCESS MESSAGE ON COMPLETE + + return null; + } + +} diff --git a/src/main/java/ovh/excale/vgreeter/commands/TrackIndexCommand.java b/src/main/java/ovh/excale/vgreeter/commands/TrackIndexCommand.java index a0bc3ec..10d2a6e 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/TrackIndexCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/TrackIndexCommand.java @@ -17,6 +17,7 @@ import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; import ovh.excale.vgreeter.VGreeterApplication; +import ovh.excale.vgreeter.commands.core.AbstractSlashCommand; import ovh.excale.vgreeter.models.TrackModel; import ovh.excale.vgreeter.repositories.TrackRepository; @@ -25,7 +26,7 @@ import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; -public class TrackIndexCommand extends AbstractCommand { +public class TrackIndexCommand extends AbstractSlashCommand { public static final String BUTTON_COMMAND = "trackindex:"; diff --git a/src/main/java/ovh/excale/vgreeter/commands/TracknameCommand.java b/src/main/java/ovh/excale/vgreeter/commands/TracknameCommand.java index ef439f0..201a9e7 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/TracknameCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/TracknameCommand.java @@ -5,6 +5,7 @@ import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.requests.restaction.interactions.ReplyAction; import ovh.excale.vgreeter.VGreeterApplication; +import ovh.excale.vgreeter.commands.core.AbstractSlashCommand; import ovh.excale.vgreeter.models.TrackModel; import ovh.excale.vgreeter.models.UserModel; import ovh.excale.vgreeter.repositories.TrackRepository; @@ -12,7 +13,7 @@ import java.util.Optional; import java.util.regex.Pattern; -public class TracknameCommand extends AbstractCommand { +public class TracknameCommand extends AbstractSlashCommand { private static final Pattern TRACKNAME_PATTERN = Pattern.compile("[\\w\\d-_]+"); diff --git a/src/main/java/ovh/excale/vgreeter/commands/UploadCommand.java b/src/main/java/ovh/excale/vgreeter/commands/UploadCommand.java index 56ffc2d..9835d0e 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/UploadCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/UploadCommand.java @@ -1,35 +1,156 @@ package ovh.excale.vgreeter.commands; -import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; -import net.dv8tion.jda.api.requests.restaction.interactions.ReplyAction; +import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.entities.User; +import net.dv8tion.jda.api.events.message.priv.PrivateMessageReceivedEvent; +import net.dv8tion.jda.api.requests.RestAction; +import org.gagravarr.ogg.OggFile; +import org.gagravarr.opus.OpusFile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import ovh.excale.vgreeter.VGreeterApplication; +import ovh.excale.vgreeter.commands.core.AbstractMessageCommand; +import ovh.excale.vgreeter.models.TrackModel; +import ovh.excale.vgreeter.models.UserModel; +import ovh.excale.vgreeter.repositories.TrackRepository; +import ovh.excale.vgreeter.repositories.UserRepository; +import ovh.excale.vgreeter.services.TrackService; -public class UploadCommand extends AbstractCommand { +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.UncheckedIOException; +import java.util.Arrays; +import java.util.List; +import java.util.Locale; +import java.util.Optional; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class UploadCommand extends AbstractMessageCommand { + + private static final Logger logger = LoggerFactory.getLogger(UploadCommand.class); + private static final Pattern TRACK_NAME_PATTERN = Pattern.compile("([\\w\\d-_]+)\\.opus"); + + private final UserRepository userRepo; + private final TrackService trackService; public UploadCommand() { - super("upload", "Show help to upload a track"); + super("upload", ""); + + userRepo = VGreeterApplication + .getApplicationContext() + .getBean(UserRepository.class); + + trackService = VGreeterApplication + .getApplicationContext() + .getBean(TrackService.class); + } @Override - public ReplyAction execute(SlashCommandEvent event) { - - //noinspection StringBufferReplaceableByString - StringBuilder sb = new StringBuilder(); - - sb.append("To upload a new track, you first have to set an altname with `/altname`.") - .append('\n') - .append("Then send me (DM) a file with the following requirements:") - .append('\n') - .append(" • The filename can only contain alphanumeric characters, dashes `-` and underscores `_`, ") - .append("followed by `.opus`. (ex. `faina-catcall.opus`)") - .append('\n') - .append(" • The track must be opus-encoded (48KHz, 20ms packets)") - .append('\n') - .append(" • As now, the file size must be under 40KB and you can only upload 3 tracks") - .append('\n') - .append("In the future there might be loyalty programs to increase these limitations."); - - return event.reply(sb.toString()); + public @Nullable RestAction execute(@NotNull PrivateMessageReceivedEvent event) { + + // TODO: COMMAND PARAMETERS + + User user = event.getAuthor(); + if(user.isBot()) + return null; + + Message message = event.getMessage(); + Optional opt = userRepo.findById(user.getIdLong()); + + boolean hasNotAltname = !opt.isPresent() || opt + .get() + .getAltname() == null; + + if(hasNotAltname) + return message.reply("You must set an `/altname` first to upload a track"); + + UserModel userModel = opt.get(); + + List attachments = message.getAttachments(); + if(attachments.isEmpty()) + return message.reply("The track must be **opus encoded**"); + + Message.Attachment attachment = attachments.get(0); + String filename = attachment.getFileName(); + int size = attachment.getSize(); + + if(size > TrackService.DEFAULT_MAX_TRACK_SIZE) + return message.reply("The file is too big (Max. " + TrackService.DEFAULT_MAX_TRACK_SIZE + ")"); + + Matcher filenameMatcher = TRACK_NAME_PATTERN.matcher(filename.toLowerCase(Locale.ROOT)); + if(!filenameMatcher.matches()) + return message.reply("Filename or extension invalid (filename must be alphanumeric" + + " and can only contain *dashes* `-` and *underscores* `_`, extension must be `.opus`)"); + + InputStream in; + try { + + in = attachment + .retrieveInputStream() + .join(); + + } catch(Exception e) { + + logger.warn("Error while retrieving Track InputStream", e); + return message.reply( + "There has been an internal error while computing the file, please retry. " + + "If the error persists, contact a developer"); + + } + + byte[] data = new byte[size]; + try { + + int read = 0, c; + do { + + c = in.read(data, read, size - read); + if(c > 0) + read += c; + + } while(c > 0); + + in.close(); + + if(read != size) { + logger.warn("Size mismatch while reading InputStream. Expected size: " + size + ", read: " + read); + data = Arrays.copyOfRange(data, 0, read); + } + + new OpusFile(new OggFile(new ByteArrayInputStream(data))); + + // TODO: USE TRACK_SERVICE + TrackRepository trackRepo = trackService.getTrackRepo(); + String trackName = filenameMatcher.group(1); + + if(trackRepo.existsByNameAndUploader(trackName, userModel)) + return message.reply("You've already uploaded a track with the same name"); + + TrackModel track = new TrackModel() + .setName(filenameMatcher.group(1)) + .setUploader(userModel) + .setSize((long) data.length) + .setData(data); + trackRepo.save(track); + + } catch(IOException e) { + + logger.warn("Error while reading Track InputStream", e); + return message.reply( + "There has been an internal error while computing the file, please retry. " + + "If the error persists, contact a developer"); + + } catch(IllegalArgumentException e) { + // Not an opus track + return message.reply("The track is not **opus-encoded**."); + } + return message.reply("Track successfully inserted!"); } } diff --git a/src/main/java/ovh/excale/vgreeter/commands/UploadHelpCommand.java b/src/main/java/ovh/excale/vgreeter/commands/UploadHelpCommand.java new file mode 100644 index 0000000..1a43bd1 --- /dev/null +++ b/src/main/java/ovh/excale/vgreeter/commands/UploadHelpCommand.java @@ -0,0 +1,36 @@ +package ovh.excale.vgreeter.commands; + +import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; +import net.dv8tion.jda.api.requests.restaction.interactions.ReplyAction; +import ovh.excale.vgreeter.commands.core.AbstractSlashCommand; + +public class UploadHelpCommand extends AbstractSlashCommand { + + public UploadHelpCommand() { + super("upload", "Show help to upload a track"); + } + + @Override + public ReplyAction execute(SlashCommandEvent event) { + + //noinspection StringBufferReplaceableByString + StringBuilder sb = new StringBuilder(); + + sb.append("To upload a new track, you first have to set an altname with `/altname`.") + .append('\n') + .append("Then send me (DM) a file with the following requirements:") + .append('\n') + .append(" • The filename can only contain alphanumeric characters, dashes `-` and underscores `_`, ") + .append("followed by `.opus`. (ex. `faina-catcall.opus`)") + .append('\n') + .append(" • The track must be opus-encoded (48KHz, 20ms packets)") + .append('\n') + .append(" • As now, the file size must be under 40KB and you can only upload 3 tracks") + .append('\n') + .append("In the future there might be loyalty programs to increase these limitations."); + + return event.reply(sb.toString()); + + } + +} diff --git a/src/main/java/ovh/excale/vgreeter/commands/core/AbstractMessageCommand.java b/src/main/java/ovh/excale/vgreeter/commands/core/AbstractMessageCommand.java new file mode 100644 index 0000000..9b56621 --- /dev/null +++ b/src/main/java/ovh/excale/vgreeter/commands/core/AbstractMessageCommand.java @@ -0,0 +1,39 @@ +package ovh.excale.vgreeter.commands.core; + +import net.dv8tion.jda.api.events.message.priv.PrivateMessageReceivedEvent; +import net.dv8tion.jda.api.hooks.EventListener; +import net.dv8tion.jda.api.requests.RestAction; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public abstract class AbstractMessageCommand { + + public static final String PREFIX = "vg:"; + + private final String name; + private final String description; + + protected AbstractMessageCommand(String name, String description) { + this.name = name; + this.description = description; + } + + public abstract @Nullable RestAction execute(@NotNull PrivateMessageReceivedEvent event); + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public boolean hasListener() { + return false; + } + + public @Nullable EventListener getListener() { + return null; + } + +} diff --git a/src/main/java/ovh/excale/vgreeter/commands/AbstractCommand.java b/src/main/java/ovh/excale/vgreeter/commands/core/AbstractSlashCommand.java similarity index 79% rename from src/main/java/ovh/excale/vgreeter/commands/AbstractCommand.java rename to src/main/java/ovh/excale/vgreeter/commands/core/AbstractSlashCommand.java index b761b64..3cc222d 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/AbstractCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/core/AbstractSlashCommand.java @@ -1,4 +1,4 @@ -package ovh.excale.vgreeter.commands; +package ovh.excale.vgreeter.commands.core; import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; import net.dv8tion.jda.api.hooks.EventListener; @@ -7,13 +7,14 @@ import org.jetbrains.annotations.Nullable; import ovh.excale.vgreeter.utilities.CommandBuilder; -public abstract class AbstractCommand { +// TODO: MERGE AbstractSlashCommand AND AbstractMessageCommand WITH A PARENT AbstractCommand CLASS +public abstract class AbstractSlashCommand { private final String name; private final String description; private final CommandBuilder builder; - protected AbstractCommand(String name, String description) { + protected AbstractSlashCommand(String name, String description) { this.name = name; this.description = description; diff --git a/src/main/java/ovh/excale/vgreeter/commands/core/CommandRegister.java b/src/main/java/ovh/excale/vgreeter/commands/core/CommandRegister.java new file mode 100644 index 0000000..f26a521 --- /dev/null +++ b/src/main/java/ovh/excale/vgreeter/commands/core/CommandRegister.java @@ -0,0 +1,144 @@ +package ovh.excale.vgreeter.commands.core; + +import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.events.GenericEvent; +import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; +import net.dv8tion.jda.api.events.message.priv.PrivateMessageReceivedEvent; +import net.dv8tion.jda.api.exceptions.ErrorResponseException; +import net.dv8tion.jda.api.hooks.EventListener; +import net.dv8tion.jda.api.interactions.commands.build.CommandData; +import net.dv8tion.jda.api.requests.RestAction; +import net.dv8tion.jda.api.requests.restaction.interactions.ReplyAction; +import org.jetbrains.annotations.NotNull; +import org.springframework.stereotype.Service; +import ovh.excale.vgreeter.VGreeterApplication; + +import java.util.*; + +@Service +public class CommandRegister { + + private final Map slashCommands; + private final Map messageCommands; + private final RegisterListener registerListener; + + private CommandRegister() { + slashCommands = new HashMap<>(); + messageCommands = new HashMap<>(); + registerListener = new RegisterListener(); + } + + public CommandRegister register(AbstractSlashCommand command) { + + slashCommands.put(command.getName(), command); + if(command.hasListener()) + registerListener.register(command.getListener()); + + return this; + } + + public CommandRegister register(AbstractMessageCommand command) { + + messageCommands.put(command.getName(), command); + if(command.hasListener()) + registerListener.register(command.getListener()); + + return this; + } + + public CommandData[] getSlashCommandsData() { + return slashCommands + .values() + .stream() + .map(AbstractSlashCommand::getData) + .toArray(CommandData[]::new); + } + + public RegisterListener getListener() { + return registerListener; + } + + private class RegisterListener implements EventListener { + + public Set commandListeners; + + protected RegisterListener() { + commandListeners = new HashSet<>(); + } + + protected void register(EventListener listener) { + commandListeners.add(listener); + } + + @Override + public void onEvent(@NotNull GenericEvent genericEvent) { + + if(genericEvent instanceof SlashCommandEvent) + + onSlashCommand((SlashCommandEvent) genericEvent); + + else if(genericEvent instanceof PrivateMessageReceivedEvent) { + + PrivateMessageReceivedEvent messageEvent = (PrivateMessageReceivedEvent) genericEvent; + String message = messageEvent + .getMessage() + .getContentRaw() + .toLowerCase(Locale.ROOT); + + if(message.startsWith(AbstractMessageCommand.PREFIX)) + onMessageCommand(messageEvent); + + } + + for(EventListener commandListener : commandListeners) + commandListener.onEvent(genericEvent); + + } + + private void onMessageCommand(PrivateMessageReceivedEvent event) { + + Message message = event.getMessage(); + String messageContent = message + .getContentRaw() + .toLowerCase(Locale.ROOT) + .replaceFirst(AbstractMessageCommand.PREFIX, ""); + String[] split = messageContent.split(" "); + + AbstractMessageCommand command = messageCommands.get(split[0]); + + Optional + .ofNullable(command) + .map(c -> c.execute(event)) + .ifPresent(RestAction::queue); + + } + + private void onSlashCommand(SlashCommandEvent event) { + + if(VGreeterApplication.isInMaintenance()) { + event + .reply("The bot is currently under maintenance") + .setEphemeral(true) + .queue(); + return; + } + + AbstractSlashCommand command = slashCommands.get(event.getName()); + ReplyAction action; + + if(command == null) + action = event + .reply("No such command") + .setEphemeral(true); + else + action = command.execute(event); + + try { + action.queue(); + } catch(ErrorResponseException ignored) { + } + } + + } + +} diff --git a/src/main/java/ovh/excale/vgreeter/services/DiscordEventHandlerService.java b/src/main/java/ovh/excale/vgreeter/services/DiscordEventHandlerService.java deleted file mode 100644 index 29e8949..0000000 --- a/src/main/java/ovh/excale/vgreeter/services/DiscordEventHandlerService.java +++ /dev/null @@ -1,220 +0,0 @@ -package ovh.excale.vgreeter.services; - -import net.dv8tion.jda.api.entities.*; -import net.dv8tion.jda.api.events.guild.voice.GuildVoiceJoinEvent; -import net.dv8tion.jda.api.events.guild.voice.GuildVoiceLeaveEvent; -import net.dv8tion.jda.api.events.message.priv.PrivateMessageReceivedEvent; -import net.dv8tion.jda.api.exceptions.InsufficientPermissionException; -import net.dv8tion.jda.api.hooks.ListenerAdapter; -import net.dv8tion.jda.api.managers.AudioManager; -import org.gagravarr.ogg.OggFile; -import org.gagravarr.opus.OpusFile; -import org.jetbrains.annotations.NotNull; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Service; -import ovh.excale.vgreeter.models.GuildModel; -import ovh.excale.vgreeter.models.TrackModel; -import ovh.excale.vgreeter.models.UserModel; -import ovh.excale.vgreeter.repositories.GuildRepository; -import ovh.excale.vgreeter.repositories.TrackRepository; -import ovh.excale.vgreeter.repositories.UserRepository; -import ovh.excale.vgreeter.utilities.TrackPlayer; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.UncheckedIOException; -import java.util.*; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -@Service -public class DiscordEventHandlerService extends ListenerAdapter { - - private final static Logger logger = LoggerFactory.getLogger(DiscordEventHandlerService.class); - private static final Pattern TRACK_NAME_PATTERN = Pattern.compile("([\\w\\d-_]+)\\.opus"); - - private final UserRepository userRepo; - private final GuildRepository guildRepo; - private final TrackService trackService; - - private final Random random; - - public DiscordEventHandlerService(UserRepository userRepo, GuildRepository guildRepo, TrackService trackService) { - this.userRepo = userRepo; - this.guildRepo = guildRepo; - this.trackService = trackService; - random = new Random(); - } - - @Override - public void onGuildVoiceJoin(@NotNull GuildVoiceJoinEvent event) { - - Guild guild = event.getGuild(); - User user = event.getMember() - .getUser(); - - Set guildLocks = DiscordService.getGuildVoiceLocks(); - if(user.isBot() || guildLocks.contains(guild.getIdLong())) - return; - - int joinProbability; - - Optional opt = guildRepo.findById(guild.getIdLong()); - if(opt.isPresent()) - joinProbability = opt.get() - .getJoinProbability(); - else { - GuildModel guildModel = new GuildModel(guild.getIdLong()); - joinProbability = guildModel.getJoinProbability(); - guildRepo.save(guildModel); - } - - if(random.nextInt(100) + 1 > joinProbability) - return; - - TrackPlayer trackPlayer = new TrackPlayer(trackService.randomTrack()); - if(!trackPlayer.canProvide()) { - logger.error("TrackPlayer cannot provide"); - return; - } - - VoiceChannel channel = event.getChannelJoined(); - AudioManager audioManager = event.getGuild() - .getAudioManager(); - - trackPlayer.setTrackEndAction(audioManager::closeAudioConnection); - - try { - audioManager.setSendingHandler(trackPlayer); - audioManager.openAudioConnection(channel); - guildLocks.add(guild.getIdLong()); - } catch(InsufficientPermissionException ignored) { - } - - } - - @Override - public void onGuildVoiceLeave(@NotNull GuildVoiceLeaveEvent event) { - - Guild guild = event.getGuild(); - User user = event.getMember() - .getUser(); - SelfUser selfUser = event.getJDA() - .getSelfUser(); - - Set guildLocks = DiscordService.getGuildVoiceLocks(); - if(user.getIdLong() == selfUser.getIdLong()) - guildLocks.remove(guild.getIdLong()); - - } - - @Override - public void onPrivateMessageReceived(@NotNull PrivateMessageReceivedEvent event) { - - User user = event.getAuthor(); - if(user.isBot()) - return; - - Message message = event.getMessage(); - Optional opt = userRepo.findById(user.getIdLong()); - - if(!opt.isPresent() || opt.get() - .getAltname() == null) { - message.reply("You must set an `/altname` first to upload a track") - .queue(); - return; - } - - UserModel userModel = opt.get(); - - List attachments = message.getAttachments(); - if(attachments.isEmpty()) { - message.reply("To upload a track you must send me an **opus encoded** file") - .queue(); - return; - } - - Message.Attachment attachment = attachments.get(0); - String filename = attachment.getFileName(); - int size = attachment.getSize(); - - if(size > TrackService.DEFAULT_MAX_TRACK_SIZE) { - message.reply("The file is too big") - .queue(); - return; - } - - Matcher filenameMatcher = TRACK_NAME_PATTERN.matcher(filename.toLowerCase(Locale.ROOT)); - if(!filenameMatcher.matches()) { - message.reply( - "Filename or extension invalid (filename must be alphanumeric and can only contain *dashes* `-` and *underscores* `_`, extension must be `.opus`)") - .queue(); - return; - } - - attachment.retrieveInputStream() - .thenAcceptAsync(in -> { - - byte[] data = new byte[size]; - - try { - - int read = 0, c; - - do { - c = in.read(data, read, size - read); - if(c > 0) - read += c; - } while(c > 0); - - in.close(); - - if(read != size) { - logger.warn("Size mismatch while reading InputStream. Expected size: " + size + ", read: " + - read); - data = Arrays.copyOfRange(data, 0, read); - } - - new OpusFile(new OggFile(new ByteArrayInputStream(data))); - - // TODO: USE TRACK_SERVICE - TrackRepository trackRepo = trackService.getTrackRepo(); - String trackname = filenameMatcher.group(1); - - if(trackRepo.existsByNameAndUploader(trackname, userModel)) { - message.reply("You've already uploaded a track with the same name") - .queue(); - return; - } - - TrackModel track = new TrackModel().setName(filenameMatcher.group(1)) - .setUploader(userModel) - .setSize((long) data.length) - .setData(data); - trackRepo.save(track); - - message.reply("Track successfully inserted!") - .queue(); - - } catch(IOException e) { - throw new UncheckedIOException(e); - } catch(IllegalArgumentException e) { - - // Not an opus track - message.reply("The provided file is not an **opus-encoded** track.") - .queue(); - - } - }) - .exceptionally(e -> { - message.reply( - "There has been an internal error while computing the file, please retry or contact a developer") - .queue(); - logger.warn("Error while opening OpusFile", e); - return null; - }); - - } - -} diff --git a/src/main/java/ovh/excale/vgreeter/services/DiscordService.java b/src/main/java/ovh/excale/vgreeter/services/DiscordService.java index a98b429..639f41c 100644 --- a/src/main/java/ovh/excale/vgreeter/services/DiscordService.java +++ b/src/main/java/ovh/excale/vgreeter/services/DiscordService.java @@ -12,6 +12,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Service; import ovh.excale.vgreeter.commands.*; +import ovh.excale.vgreeter.commands.core.CommandRegister; import javax.security.auth.login.LoginException; import java.util.Collections; @@ -27,13 +28,14 @@ public class DiscordService { private final JDA jda; - public DiscordService(DiscordEventHandlerService eventHandler, CommandRegister commands, + public DiscordService(VoiceChannelHandler eventHandler, CommandRegister commands, @Value("${env.DISCORD_TOKEN}") String token) throws LoginException, InterruptedException { - jda = JDABuilder.create(token, - GatewayIntent.GUILD_VOICE_STATES, - GatewayIntent.DIRECT_MESSAGES, - GatewayIntent.GUILD_VOICE_STATES) + jda = JDABuilder + .create(token, + GatewayIntent.GUILD_VOICE_STATES, + GatewayIntent.DIRECT_MESSAGES, + GatewayIntent.GUILD_VOICE_STATES) .disableCache(CacheFlag.ACTIVITY, CacheFlag.ONLINE_STATUS, CacheFlag.CLIENT_STATUS, @@ -45,15 +47,22 @@ public DiscordService(DiscordEventHandlerService eventHandler, CommandRegister c .awaitReady(); - jda.updateCommands() - .addCommands(commands.register(new ProbabilityCommand()) + jda + .updateCommands() + .addCommands(commands + // SLASH COMMANDS + .register(new ProbabilityCommand()) .register(new AltnameCommand()) - .register(new UploadCommand()) + .register(new UploadHelpCommand()) .register(new PlaytestCommand()) .register(new TracknameCommand()) .register(new TrackIndexCommand()) - .getData()) - .queue(commandList -> logger.info("[Registered commands] " + commandList.stream() + // MESSAGE COMMANDS + .register(new RestartCommand()) + .register(new UploadCommand()) + .getSlashCommandsData()) + .queue(commandList -> logger.info("[Registered SlashCommands] " + commandList + .stream() .map(Command::getName) .collect(Collectors.joining(", "))), e -> logger.warn("Couldn't update commands", e)); @@ -65,7 +74,7 @@ public static Set getGuildVoiceLocks() { return guildVoiceLocks; } - @Bean + @Bean(destroyMethod = "shutdown") public JDA getJda() { return jda; } diff --git a/src/main/java/ovh/excale/vgreeter/services/VoiceChannelHandler.java b/src/main/java/ovh/excale/vgreeter/services/VoiceChannelHandler.java new file mode 100644 index 0000000..011f8a2 --- /dev/null +++ b/src/main/java/ovh/excale/vgreeter/services/VoiceChannelHandler.java @@ -0,0 +1,99 @@ +package ovh.excale.vgreeter.services; + +import net.dv8tion.jda.api.entities.*; +import net.dv8tion.jda.api.events.guild.voice.GuildVoiceJoinEvent; +import net.dv8tion.jda.api.events.guild.voice.GuildVoiceLeaveEvent; +import net.dv8tion.jda.api.exceptions.InsufficientPermissionException; +import net.dv8tion.jda.api.hooks.ListenerAdapter; +import net.dv8tion.jda.api.managers.AudioManager; +import org.jetbrains.annotations.NotNull; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; +import ovh.excale.vgreeter.models.GuildModel; +import ovh.excale.vgreeter.repositories.GuildRepository; +import ovh.excale.vgreeter.utilities.TrackPlayer; + +import java.util.*; + +@Service +public class VoiceChannelHandler extends ListenerAdapter { + + private final static Logger logger = LoggerFactory.getLogger(VoiceChannelHandler.class); + + private final GuildRepository guildRepo; + private final TrackService trackService; + + private final Random random; + + public VoiceChannelHandler(GuildRepository guildRepo, TrackService trackService) { + this.guildRepo = guildRepo; + this.trackService = trackService; + random = new Random(); + } + + // TODO: DISABLE VOICE EVENT HANDLING UNDER MAINTENANCE + + @Override + public void onGuildVoiceJoin(@NotNull GuildVoiceJoinEvent event) { + + Guild guild = event.getGuild(); + User user = event.getMember() + .getUser(); + + Set guildLocks = DiscordService.getGuildVoiceLocks(); + if(user.isBot() || guildLocks.contains(guild.getIdLong())) + return; + + int joinProbability; + + Optional opt = guildRepo.findById(guild.getIdLong()); + if(opt.isPresent()) + joinProbability = opt.get() + .getJoinProbability(); + else { + GuildModel guildModel = new GuildModel(guild.getIdLong()); + joinProbability = guildModel.getJoinProbability(); + guildRepo.save(guildModel); + } + + if(random.nextInt(100) + 1 > joinProbability) + return; + + TrackPlayer trackPlayer = new TrackPlayer(trackService.randomTrack()); + if(!trackPlayer.canProvide()) { + logger.error("TrackPlayer cannot provide"); + return; + } + + VoiceChannel channel = event.getChannelJoined(); + AudioManager audioManager = event.getGuild() + .getAudioManager(); + + trackPlayer.setTrackEndAction(audioManager::closeAudioConnection); + + try { + audioManager.setSendingHandler(trackPlayer); + audioManager.openAudioConnection(channel); + guildLocks.add(guild.getIdLong()); + } catch(InsufficientPermissionException ignored) { + } + + } + + @Override + public void onGuildVoiceLeave(@NotNull GuildVoiceLeaveEvent event) { + + Guild guild = event.getGuild(); + User user = event.getMember() + .getUser(); + SelfUser selfUser = event.getJDA() + .getSelfUser(); + + Set guildLocks = DiscordService.getGuildVoiceLocks(); + if(user.getIdLong() == selfUser.getIdLong()) + guildLocks.remove(guild.getIdLong()); + + } + +} diff --git a/src/main/java/ovh/excale/vgreeter/utilities/ArgumentsParser.java b/src/main/java/ovh/excale/vgreeter/utilities/ArgumentsParser.java new file mode 100644 index 0000000..3f2e9cb --- /dev/null +++ b/src/main/java/ovh/excale/vgreeter/utilities/ArgumentsParser.java @@ -0,0 +1,90 @@ +package ovh.excale.vgreeter.utilities; + +import org.jetbrains.annotations.NotNull; + +import java.util.Arrays; +import java.util.Optional; +import java.util.function.Function; + +// TODO: USER/MEMBER PARSE +public class ArgumentsParser { + + private final String rawArguments; + private final String[] splitArguments; + + public ArgumentsParser(String rawArguments) { + this.rawArguments = rawArguments; + splitArguments = rawArguments + .replaceAll(" {2,}", " ") + .trim() + .split(" "); + } + + public String getRawArguments() { + return rawArguments; + } + + public String[] getSplitArguments() { + return splitArguments; + } + + public Optional getArgumentCast(int index, Function parser) { + + Optional opt = Optional.empty(); + if(index < splitArguments.length) + try { + + opt = Optional.of(parser.apply(splitArguments[index])); + + } catch(Exception ignored) { + } + + return opt; + } + + public Optional getArgumentString(int index) { + return getArgumentCast(index, String::toString); + } + + public @NotNull String getArgumentString(int index, @NotNull String defValue) { + return getArgumentString(index).orElse(defValue); + } + + public Optional getArgumentInteger(int index) { + return getArgumentCast(index, Integer::parseInt); + } + + public int getArgumentInteger(int index, int defValue) { + return getArgumentInteger(index).orElse(defValue); + } + + public Optional getArgumentLong(int index) { + return getArgumentCast(index, Long::parseLong); + } + + public long getArgumentLong(int index, long defValue) { + return getArgumentLong(index).orElse(defValue); + } + + public Optional getArgumentBoolean(int index) { + return getArgumentCast(index, Boolean::parseBoolean); + } + + public boolean getArgumentBoolean(int index, boolean defValue) { + return getArgumentBoolean(index).orElse(defValue); + } + + public Optional getArgumentText(int index) { + + Optional opt = Optional.empty(); + if(index < splitArguments.length) + opt = Optional.of(String.join(" ", Arrays.copyOfRange(splitArguments, index, splitArguments.length))); + + return opt; + } + + public @NotNull String getArgumentText(int index, @NotNull String defValue) { + return getArgumentText(index).orElse(defValue); + } + +} From c906d3f4374794ae545765d70a5317c3ceb78025 Mon Sep 17 00:00:00 2001 From: excale Date: Tue, 14 Sep 2021 21:29:27 +0200 Subject: [PATCH 02/46] Improved maintenance mode --- .../excale/vgreeter/VGreeterApplication.java | 37 ++++++++++++++----- .../vgreeter/commands/RestartCommand.java | 25 +++++++++---- 2 files changed, 45 insertions(+), 17 deletions(-) diff --git a/src/main/java/ovh/excale/vgreeter/VGreeterApplication.java b/src/main/java/ovh/excale/vgreeter/VGreeterApplication.java index 2c055be..5d2890b 100644 --- a/src/main/java/ovh/excale/vgreeter/VGreeterApplication.java +++ b/src/main/java/ovh/excale/vgreeter/VGreeterApplication.java @@ -1,6 +1,7 @@ package ovh.excale.vgreeter; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; @@ -16,8 +17,7 @@ @SpringBootApplication public class VGreeterApplication implements CommandLineRunner, ApplicationContextAware { - @Value("${env.VGREETER_MAINTENANCE:false}") - private static boolean maintenance; + private static Boolean maintenance; private static ConfigurableApplicationContext ctx; public static void main(String[] args) { @@ -28,25 +28,42 @@ public static void main(String[] args) { } - public static void restart(boolean maintenance) { + // TODO: DON'T CONNECT TO DB DURING MAINTENANCE + + // keep previous maintenance state + public static void restart(@Nullable final Runnable then, @Nullable final Boolean maintenance) { + + // TODO: log("Restarting app") Thread thread = new Thread(() -> { ctx.close(); - ctx = SpringApplication.run(VGreeterApplication.class); - // TODO: MAINTENANCE AS APPLICATION ARGUMENT - VGreeterApplication.setMaintenance(maintenance); + + VGreeterApplication.maintenance = maintenance != null ? maintenance : VGreeterApplication.maintenance; + + SpringApplication app = new SpringApplication(VGreeterApplication.class); + app.setBannerMode(Banner.Mode.OFF); + app.run(); + + if(then != null) + then.run(); + }); thread.setDaemon(false); thread.start(); + } - public static boolean isInMaintenance() { - return maintenance; + public static void restart(@NotNull Runnable then) { + restart(then, null); } - public static void setMaintenance(boolean maintenanceOn) { - maintenance = maintenanceOn; + public static void restart(boolean maintenance) { + restart(null, maintenance); + } + + public static boolean isInMaintenance() { + return maintenance; } public static ApplicationContext getApplicationContext() { diff --git a/src/main/java/ovh/excale/vgreeter/commands/RestartCommand.java b/src/main/java/ovh/excale/vgreeter/commands/RestartCommand.java index 28dc546..ec920b4 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/RestartCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/RestartCommand.java @@ -1,5 +1,6 @@ package ovh.excale.vgreeter.commands; +import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.events.message.priv.PrivateMessageReceivedEvent; import net.dv8tion.jda.api.requests.RestAction; @@ -17,21 +18,31 @@ public RestartCommand() { } @Override - public @Nullable RestAction execute(@NotNull PrivateMessageReceivedEvent event) { + public @Nullable RestAction execute(@NotNull final PrivateMessageReceivedEvent event) { Message message = event.getMessage(); ArgumentsParser arguments = new ArgumentsParser(message.getContentRaw()); - boolean maintenance = arguments.getArgumentBoolean(1, false); + boolean maintenance = arguments + .getArgumentString(1) + .map("maintenance"::equalsIgnoreCase) + .orElse(false); String restartMessage = maintenance ? "*Restarting on maintenance mode...*" : "*Restarting...*"; - message - .reply(restartMessage) + message.reply(restartMessage) + // Wait for message to be sent and then restart .complete(); - VGreeterApplication.restart(maintenance); - - // TODO: SUCCESS MESSAGE ON COMPLETE + //noinspection ConstantConditions + VGreeterApplication.restart(() -> VGreeterApplication + .getApplicationContext() + .getBean(JDA.class) + .getUserById(event + .getAuthor() + .getIdLong()) + .openPrivateChannel() + .flatMap(dm -> dm.sendMessage("*Done!*")) + .queue(), maintenance); return null; } From 681f15080308badd6c87c2a168044cd1aa1beefd Mon Sep 17 00:00:00 2001 From: excale Date: Tue, 14 Sep 2021 22:11:13 +0200 Subject: [PATCH 03/46] Implemented Lombok --- pom.xml | 8 ++ .../excale/vgreeter/VGreeterApplication.java | 8 +- .../vgreeter/commands/AltnameCommand.java | 5 +- .../vgreeter/commands/PlaytestCommand.java | 6 +- .../vgreeter/commands/ProbabilityCommand.java | 5 +- .../vgreeter/commands/UploadCommand.java | 34 ++++----- .../excale/vgreeter/models/GuildModel.java | 37 ++++------ .../excale/vgreeter/models/TrackModel.java | 73 ++++--------------- .../ovh/excale/vgreeter/models/UserModel.java | 46 ++++-------- .../vgreeter/services/DiscordService.java | 11 ++- .../services/VoiceChannelHandler.java | 22 ++++-- .../vgreeter/utilities/TrackPlayer.java | 8 +- 12 files changed, 102 insertions(+), 161 deletions(-) diff --git a/pom.xml b/pom.xml index 92f5d7b..fedcd76 100644 --- a/pom.xml +++ b/pom.xml @@ -79,6 +79,14 @@ 42.2.22 + + + org.projectlombok + lombok + 1.18.20 + provided + + diff --git a/src/main/java/ovh/excale/vgreeter/VGreeterApplication.java b/src/main/java/ovh/excale/vgreeter/VGreeterApplication.java index 5d2890b..ef5d7b2 100644 --- a/src/main/java/ovh/excale/vgreeter/VGreeterApplication.java +++ b/src/main/java/ovh/excale/vgreeter/VGreeterApplication.java @@ -1,9 +1,8 @@ package ovh.excale.vgreeter; +import lombok.extern.log4j.Log4j2; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.Banner; @@ -14,6 +13,7 @@ import org.springframework.context.ApplicationContextAware; import org.springframework.context.ConfigurableApplicationContext; +@Log4j2 @SpringBootApplication public class VGreeterApplication implements CommandLineRunner, ApplicationContextAware { @@ -70,17 +70,15 @@ public static ApplicationContext getApplicationContext() { return ctx; } - public final Logger logger; public final String version; public VGreeterApplication(@Value("${application.version}") String version) { this.version = version; - logger = LoggerFactory.getLogger(VGreeterApplication.class); } @Override public void run(String[] args) { - logger.info("Running on version {}", version); + log.info("Running on version {}", version); } @Override diff --git a/src/main/java/ovh/excale/vgreeter/commands/AltnameCommand.java b/src/main/java/ovh/excale/vgreeter/commands/AltnameCommand.java index 7a5e4f3..a661b8c 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/AltnameCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/AltnameCommand.java @@ -48,7 +48,10 @@ public ReplyAction execute(SlashCommandEvent event) { if(!userRepo.existsByAltname(name)) { UserModel userModel = userRepo.findById(user.getIdLong()) - .orElseGet(() -> new UserModel(user.getIdLong())); + .orElseGet(() -> UserModel + .builder() + .snowflake(user.getIdLong()) + .build()); userModel.setAltname(name); userRepo.save(userModel); diff --git a/src/main/java/ovh/excale/vgreeter/commands/PlaytestCommand.java b/src/main/java/ovh/excale/vgreeter/commands/PlaytestCommand.java index f4e65f6..3c520a4 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/PlaytestCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/PlaytestCommand.java @@ -1,5 +1,6 @@ package ovh.excale.vgreeter.commands; +import lombok.extern.log4j.Log4j2; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.VoiceChannel; @@ -20,10 +21,9 @@ import java.util.Optional; import java.util.Set; +@Log4j2 public class PlaytestCommand extends AbstractSlashCommand { - private static final Logger logger = LoggerFactory.getLogger(PlaytestCommand.class); - public PlaytestCommand() { super("playtest", "Test a track"); @@ -71,7 +71,7 @@ public ReplyAction execute(SlashCommandEvent event) { TrackPlayer trackPlayer = new TrackPlayer(opt.get()); if(!trackPlayer.canProvide()) { - logger.error("TrackPlayer cannot provide"); + log.error("TrackPlayer cannot provide"); return event.reply("There has been an internal error, retry or contact a developer.") .setEphemeral(true); } diff --git a/src/main/java/ovh/excale/vgreeter/commands/ProbabilityCommand.java b/src/main/java/ovh/excale/vgreeter/commands/ProbabilityCommand.java index cea7a25..7c85957 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/ProbabilityCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/ProbabilityCommand.java @@ -43,7 +43,10 @@ public ReplyAction execute(SlashCommandEvent event) { Member member = event.getMember(); Optional opt = guildRepo.findById(guild.getIdLong()); - GuildModel guildModel = opt.orElseGet(() -> new GuildModel(guild.getIdLong())); + GuildModel guildModel = opt.orElseGet(() -> GuildModel + .builder() + .id(guild.getIdLong()) + .build()); int prevProbab = guildModel.getJoinProbability(); ReplyAction reply; diff --git a/src/main/java/ovh/excale/vgreeter/commands/UploadCommand.java b/src/main/java/ovh/excale/vgreeter/commands/UploadCommand.java index 9835d0e..20be746 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/UploadCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/UploadCommand.java @@ -1,5 +1,6 @@ package ovh.excale.vgreeter.commands; +import lombok.extern.log4j.Log4j2; import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.User; import net.dv8tion.jda.api.events.message.priv.PrivateMessageReceivedEvent; @@ -8,8 +9,6 @@ import org.gagravarr.opus.OpusFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import ovh.excale.vgreeter.VGreeterApplication; import ovh.excale.vgreeter.commands.core.AbstractMessageCommand; import ovh.excale.vgreeter.models.TrackModel; @@ -21,7 +20,6 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; -import java.io.UncheckedIOException; import java.util.Arrays; import java.util.List; import java.util.Locale; @@ -29,9 +27,9 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +@Log4j2 public class UploadCommand extends AbstractMessageCommand { - private static final Logger logger = LoggerFactory.getLogger(UploadCommand.class); private static final Pattern TRACK_NAME_PATTERN = Pattern.compile("([\\w\\d-_]+)\\.opus"); private final UserRepository userRepo; @@ -96,10 +94,9 @@ public UploadCommand() { } catch(Exception e) { - logger.warn("Error while retrieving Track InputStream", e); - return message.reply( - "There has been an internal error while computing the file, please retry. " + - "If the error persists, contact a developer"); + log.warn("Error while retrieving Track InputStream", e); + return message.reply("There has been an internal error while computing the file, please retry. " + + "If the error persists, contact a developer"); } @@ -118,7 +115,7 @@ public UploadCommand() { in.close(); if(read != size) { - logger.warn("Size mismatch while reading InputStream. Expected size: " + size + ", read: " + read); + log.warn("Size mismatch while reading InputStream. Expected size: " + size + ", read: " + read); data = Arrays.copyOfRange(data, 0, read); } @@ -131,19 +128,20 @@ public UploadCommand() { if(trackRepo.existsByNameAndUploader(trackName, userModel)) return message.reply("You've already uploaded a track with the same name"); - TrackModel track = new TrackModel() - .setName(filenameMatcher.group(1)) - .setUploader(userModel) - .setSize((long) data.length) - .setData(data); + TrackModel track = TrackModel + .builder() + .name(filenameMatcher.group(1)) + .uploader(userModel) + .size((long) data.length) + .data(data) + .build(); trackRepo.save(track); } catch(IOException e) { - logger.warn("Error while reading Track InputStream", e); - return message.reply( - "There has been an internal error while computing the file, please retry. " + - "If the error persists, contact a developer"); + log.warn("Error while reading Track InputStream", e); + return message.reply("There has been an internal error while computing the file, please retry. " + + "If the error persists, contact a developer"); } catch(IllegalArgumentException e) { // Not an opus track diff --git a/src/main/java/ovh/excale/vgreeter/models/GuildModel.java b/src/main/java/ovh/excale/vgreeter/models/GuildModel.java index 08a4d74..ab0977f 100644 --- a/src/main/java/ovh/excale/vgreeter/models/GuildModel.java +++ b/src/main/java/ovh/excale/vgreeter/models/GuildModel.java @@ -1,10 +1,18 @@ package ovh.excale.vgreeter.models; +import lombok.*; + import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Setter +@Getter +@ToString @Entity @Table(name = "guild") public class GuildModel { @@ -16,33 +24,14 @@ public class GuildModel { private Long id; @Column(name = "join_probability") - private Integer joinProbability; + private Integer joinProbability = DEFAULT_JOIN_PROBABILITY; - public GuildModel() { - joinProbability = DEFAULT_JOIN_PROBABILITY; - } + @SuppressWarnings("unused") + public static class GuildModelBuilder { - public GuildModel(Long id) { - this.id = id; - joinProbability = DEFAULT_JOIN_PROBABILITY; - } - - public Long getId() { - return id; - } - - public GuildModel setId(Long id) { - this.id = id; - return this; - } - - public Integer getJoinProbability() { - return joinProbability; - } + @SuppressWarnings({ "FieldMayBeFinal", "unused" }) + private Integer joinProbability = DEFAULT_JOIN_PROBABILITY; - public GuildModel setJoinProbability(Integer joinProbability) { - this.joinProbability = joinProbability; - return this; } } diff --git a/src/main/java/ovh/excale/vgreeter/models/TrackModel.java b/src/main/java/ovh/excale/vgreeter/models/TrackModel.java index ab760c4..6596e88 100644 --- a/src/main/java/ovh/excale/vgreeter/models/TrackModel.java +++ b/src/main/java/ovh/excale/vgreeter/models/TrackModel.java @@ -1,5 +1,6 @@ package ovh.excale.vgreeter.models; +import lombok.*; import org.gagravarr.ogg.OggPacketReader; import javax.persistence.*; @@ -7,6 +8,12 @@ import java.sql.Timestamp; import java.time.Instant; +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Setter +@Getter +@ToString @Entity @Table(name = "track") public class TrackModel { @@ -24,75 +31,27 @@ public class TrackModel { private Long size; @Basic - private Timestamp uploadDate; + private Timestamp uploadDate = Timestamp.from(Instant.now()); + @ToString.Exclude @Basic(fetch = FetchType.LAZY) private byte[] data; + @ToString.Exclude @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "uploader_id") private UserModel uploader; - public TrackModel() { - uploadDate = Timestamp.from(Instant.now()); - } - - public Long getId() { - return id; - } - - public TrackModel setId(Long id) { - this.id = id; - return this; - } - - public String getName() { - return name; - } - - public TrackModel setName(String name) { - this.name = name; - return this; - } - - public Long getSize() { - return size; - } - - public TrackModel setSize(Long size) { - this.size = size; - return this; - } - - public byte[] getData() { - return data; - } - - public TrackModel setData(byte[] data) { - this.data = data; - return this; - } - - public UserModel getUploader() { - return uploader; - } - - public TrackModel setUploader(UserModel uploader) { - this.uploader = uploader; - return this; + public OggPacketReader getPacketReader() { + return new OggPacketReader(new ByteArrayInputStream(getData())); } - public Timestamp getUploadDate() { - return uploadDate; - } + @SuppressWarnings("unused") + public static class TrackModelBuilder { - public TrackModel setUploadDate(Timestamp uploadDate) { - this.uploadDate = uploadDate; - return this; - } + @SuppressWarnings({ "FieldMayBeFinal", "unused" }) + private Timestamp uploadDate = Timestamp.from(Instant.now()); - public OggPacketReader getPacketReader() { - return new OggPacketReader(new ByteArrayInputStream(getData())); } } diff --git a/src/main/java/ovh/excale/vgreeter/models/UserModel.java b/src/main/java/ovh/excale/vgreeter/models/UserModel.java index 463b273..6631d9f 100644 --- a/src/main/java/ovh/excale/vgreeter/models/UserModel.java +++ b/src/main/java/ovh/excale/vgreeter/models/UserModel.java @@ -1,7 +1,15 @@ package ovh.excale.vgreeter.models; +import lombok.*; + import javax.persistence.*; +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Setter +@Getter +@ToString @Entity @Table(name = "\"user\"") public class UserModel { @@ -14,42 +22,14 @@ public class UserModel { @Basic @Column(name = "tracks_max") - private Integer trackMaxSize; - - public UserModel() { - trackMaxSize = 64 * 1024; - } + private Integer trackMaxSize = 64 * 1024; - public UserModel(long snowflake) { - this.snowflake = snowflake; - trackMaxSize = 64 * 1024; - } + @SuppressWarnings("unused") + public static class UserModelBuilder { - public Long getSnowflake() { - return snowflake; - } - - public UserModel setSnowflake(Long snowflake) { - this.snowflake = snowflake; - return this; - } - - public String getAltname() { - return altname; - } - - public UserModel setAltname(String altname) { - this.altname = altname; - return this; - } - - public Integer getTrackMaxSize() { - return trackMaxSize; - } + @SuppressWarnings({ "FieldMayBeFinal", "unused" }) + private Integer trackMaxSize = 64 * 1024; - public UserModel setTrackMaxSize(Integer maxTracks) { - this.trackMaxSize = maxTracks; - return this; } } diff --git a/src/main/java/ovh/excale/vgreeter/services/DiscordService.java b/src/main/java/ovh/excale/vgreeter/services/DiscordService.java index 639f41c..887cdf9 100644 --- a/src/main/java/ovh/excale/vgreeter/services/DiscordService.java +++ b/src/main/java/ovh/excale/vgreeter/services/DiscordService.java @@ -1,13 +1,12 @@ package ovh.excale.vgreeter.services; +import lombok.extern.log4j.Log4j2; import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.JDABuilder; import net.dv8tion.jda.api.entities.Activity; import net.dv8tion.jda.api.interactions.commands.Command; import net.dv8tion.jda.api.requests.GatewayIntent; import net.dv8tion.jda.api.utils.cache.CacheFlag; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Service; @@ -20,10 +19,10 @@ import java.util.Set; import java.util.stream.Collectors; +@Log4j2 @Service public class DiscordService { - private static final Logger logger = LoggerFactory.getLogger(DiscordService.class); private static final Set guildVoiceLocks = Collections.synchronizedSet(new HashSet<>()); private final JDA jda; @@ -61,12 +60,12 @@ public DiscordService(VoiceChannelHandler eventHandler, CommandRegister commands .register(new RestartCommand()) .register(new UploadCommand()) .getSlashCommandsData()) - .queue(commandList -> logger.info("[Registered SlashCommands] " + commandList + .queue(commandList -> log.info("[Registered SlashCommands] " + commandList .stream() .map(Command::getName) - .collect(Collectors.joining(", "))), e -> logger.warn("Couldn't update commands", e)); + .collect(Collectors.joining(", "))), e -> log.warn("Couldn't update commands", e)); - logger.info("JDA connected"); + log.info("JDA connected"); } diff --git a/src/main/java/ovh/excale/vgreeter/services/VoiceChannelHandler.java b/src/main/java/ovh/excale/vgreeter/services/VoiceChannelHandler.java index 011f8a2..a586f2a 100644 --- a/src/main/java/ovh/excale/vgreeter/services/VoiceChannelHandler.java +++ b/src/main/java/ovh/excale/vgreeter/services/VoiceChannelHandler.java @@ -1,26 +1,29 @@ package ovh.excale.vgreeter.services; -import net.dv8tion.jda.api.entities.*; +import lombok.extern.log4j.Log4j2; +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.SelfUser; +import net.dv8tion.jda.api.entities.User; +import net.dv8tion.jda.api.entities.VoiceChannel; import net.dv8tion.jda.api.events.guild.voice.GuildVoiceJoinEvent; import net.dv8tion.jda.api.events.guild.voice.GuildVoiceLeaveEvent; import net.dv8tion.jda.api.exceptions.InsufficientPermissionException; import net.dv8tion.jda.api.hooks.ListenerAdapter; import net.dv8tion.jda.api.managers.AudioManager; import org.jetbrains.annotations.NotNull; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import ovh.excale.vgreeter.models.GuildModel; import ovh.excale.vgreeter.repositories.GuildRepository; import ovh.excale.vgreeter.utilities.TrackPlayer; -import java.util.*; +import java.util.Optional; +import java.util.Random; +import java.util.Set; +@Log4j2 @Service public class VoiceChannelHandler extends ListenerAdapter { - private final static Logger logger = LoggerFactory.getLogger(VoiceChannelHandler.class); - private final GuildRepository guildRepo; private final TrackService trackService; @@ -52,7 +55,10 @@ public void onGuildVoiceJoin(@NotNull GuildVoiceJoinEvent event) { joinProbability = opt.get() .getJoinProbability(); else { - GuildModel guildModel = new GuildModel(guild.getIdLong()); + GuildModel guildModel = GuildModel + .builder() + .id(guild.getIdLong()) + .build(); joinProbability = guildModel.getJoinProbability(); guildRepo.save(guildModel); } @@ -62,7 +68,7 @@ public void onGuildVoiceJoin(@NotNull GuildVoiceJoinEvent event) { TrackPlayer trackPlayer = new TrackPlayer(trackService.randomTrack()); if(!trackPlayer.canProvide()) { - logger.error("TrackPlayer cannot provide"); + log.error("TrackPlayer cannot provide"); return; } diff --git a/src/main/java/ovh/excale/vgreeter/utilities/TrackPlayer.java b/src/main/java/ovh/excale/vgreeter/utilities/TrackPlayer.java index 03ed9e3..cc806f2 100644 --- a/src/main/java/ovh/excale/vgreeter/utilities/TrackPlayer.java +++ b/src/main/java/ovh/excale/vgreeter/utilities/TrackPlayer.java @@ -1,11 +1,10 @@ package ovh.excale.vgreeter.utilities; +import lombok.extern.log4j.Log4j2; import net.dv8tion.jda.api.audio.AudioSendHandler; import org.gagravarr.ogg.OggPacket; import org.gagravarr.ogg.OggPacketReader; import org.jetbrains.annotations.Nullable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import ovh.excale.vgreeter.models.TrackModel; import java.io.IOException; @@ -16,10 +15,9 @@ import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; +@Log4j2 public class TrackPlayer implements AudioSendHandler { - private final static Logger logger = LoggerFactory.getLogger(TrackPlayer.class); - private final TrackModel track; private final Iterator packetIterator; private Runnable trackEndAction; @@ -37,7 +35,7 @@ public TrackPlayer(TrackModel track) { while((packet = packetReader.getNextPacket()) != null) packetList.add(packet); } catch(IOException e) { - logger.error(e.getMessage(), e); + log.error(e.getMessage(), e); } } From 9a5de712bc8f82a722ac3be85fe3b7b58eb8605f Mon Sep 17 00:00:00 2001 From: excale Date: Tue, 14 Sep 2021 22:15:56 +0200 Subject: [PATCH 04/46] Log when restarting --- src/main/java/ovh/excale/vgreeter/VGreeterApplication.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/ovh/excale/vgreeter/VGreeterApplication.java b/src/main/java/ovh/excale/vgreeter/VGreeterApplication.java index ef5d7b2..093a832 100644 --- a/src/main/java/ovh/excale/vgreeter/VGreeterApplication.java +++ b/src/main/java/ovh/excale/vgreeter/VGreeterApplication.java @@ -33,7 +33,7 @@ public static void main(String[] args) { // keep previous maintenance state public static void restart(@Nullable final Runnable then, @Nullable final Boolean maintenance) { - // TODO: log("Restarting app") + log.info("Restarting app"); Thread thread = new Thread(() -> { ctx.close(); From 14fb5d2fca250ded88053a173ce92d509e030667 Mon Sep 17 00:00:00 2001 From: excale Date: Sun, 17 Oct 2021 00:46:34 +0200 Subject: [PATCH 05/46] Fixed a bug where the bot wouldn't "hello world" on restart --- .../vgreeter/commands/RestartCommand.java | 12 +++++++----- .../vgreeter/services/DiscordService.java | 19 +++++++++---------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/main/java/ovh/excale/vgreeter/commands/RestartCommand.java b/src/main/java/ovh/excale/vgreeter/commands/RestartCommand.java index ec920b4..e026f3c 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/RestartCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/RestartCommand.java @@ -2,6 +2,7 @@ import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.entities.User; import net.dv8tion.jda.api.events.message.priv.PrivateMessageReceivedEvent; import net.dv8tion.jda.api.requests.RestAction; import org.jetbrains.annotations.NotNull; @@ -33,14 +34,15 @@ public RestartCommand() { // Wait for message to be sent and then restart .complete(); - //noinspection ConstantConditions + final long authorId = event + .getAuthor() + .getIdLong(); + VGreeterApplication.restart(() -> VGreeterApplication .getApplicationContext() .getBean(JDA.class) - .getUserById(event - .getAuthor() - .getIdLong()) - .openPrivateChannel() + .retrieveUserById(authorId) + .flatMap(User::openPrivateChannel) .flatMap(dm -> dm.sendMessage("*Done!*")) .queue(), maintenance); diff --git a/src/main/java/ovh/excale/vgreeter/services/DiscordService.java b/src/main/java/ovh/excale/vgreeter/services/DiscordService.java index 887cdf9..5f37b7a 100644 --- a/src/main/java/ovh/excale/vgreeter/services/DiscordService.java +++ b/src/main/java/ovh/excale/vgreeter/services/DiscordService.java @@ -1,5 +1,6 @@ package ovh.excale.vgreeter.services; +import lombok.Getter; import lombok.extern.log4j.Log4j2; import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.JDABuilder; @@ -23,6 +24,7 @@ @Service public class DiscordService { + @Getter private static final Set guildVoiceLocks = Collections.synchronizedSet(new HashSet<>()); private final JDA jda; @@ -45,8 +47,9 @@ public DiscordService(VoiceChannelHandler eventHandler, CommandRegister commands .build() .awaitReady(); + log.info("JDA connected"); - jda + String commandListString = jda .updateCommands() .addCommands(commands // SLASH COMMANDS @@ -60,17 +63,13 @@ public DiscordService(VoiceChannelHandler eventHandler, CommandRegister commands .register(new RestartCommand()) .register(new UploadCommand()) .getSlashCommandsData()) - .queue(commandList -> log.info("[Registered SlashCommands] " + commandList - .stream() - .map(Command::getName) - .collect(Collectors.joining(", "))), e -> log.warn("Couldn't update commands", e)); - - log.info("JDA connected"); + .complete() + .stream() + .map(Command::getName) + .collect(Collectors.joining(", ")); - } + log.info("[Registered SlashCommands] " + commandListString); - public static Set getGuildVoiceLocks() { - return guildVoiceLocks; } @Bean(destroyMethod = "shutdown") From c1a59cc1da07ac13e9bdf0ce21a188bcb6b32ed1 Mon Sep 17 00:00:00 2001 From: excale Date: Sun, 17 Oct 2021 00:46:42 +0200 Subject: [PATCH 06/46] More Lombok --- .../commands/core/AbstractMessageCommand.java | 12 ++++-------- .../commands/core/AbstractSlashCommand.java | 18 ++++++------------ 2 files changed, 10 insertions(+), 20 deletions(-) diff --git a/src/main/java/ovh/excale/vgreeter/commands/core/AbstractMessageCommand.java b/src/main/java/ovh/excale/vgreeter/commands/core/AbstractMessageCommand.java index 9b56621..1b3baa2 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/core/AbstractMessageCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/core/AbstractMessageCommand.java @@ -1,5 +1,6 @@ package ovh.excale.vgreeter.commands.core; +import lombok.Getter; import net.dv8tion.jda.api.events.message.priv.PrivateMessageReceivedEvent; import net.dv8tion.jda.api.hooks.EventListener; import net.dv8tion.jda.api.requests.RestAction; @@ -10,7 +11,10 @@ public abstract class AbstractMessageCommand { public static final String PREFIX = "vg:"; + @Getter private final String name; + + @Getter private final String description; protected AbstractMessageCommand(String name, String description) { @@ -20,14 +24,6 @@ protected AbstractMessageCommand(String name, String description) { public abstract @Nullable RestAction execute(@NotNull PrivateMessageReceivedEvent event); - public String getName() { - return name; - } - - public String getDescription() { - return description; - } - public boolean hasListener() { return false; } diff --git a/src/main/java/ovh/excale/vgreeter/commands/core/AbstractSlashCommand.java b/src/main/java/ovh/excale/vgreeter/commands/core/AbstractSlashCommand.java index 3cc222d..d3e34f7 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/core/AbstractSlashCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/core/AbstractSlashCommand.java @@ -1,5 +1,6 @@ package ovh.excale.vgreeter.commands.core; +import lombok.Getter; import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; import net.dv8tion.jda.api.hooks.EventListener; import net.dv8tion.jda.api.interactions.commands.build.CommandData; @@ -10,8 +11,13 @@ // TODO: MERGE AbstractSlashCommand AND AbstractMessageCommand WITH A PARENT AbstractCommand CLASS public abstract class AbstractSlashCommand { + @Getter private final String name; + + @Getter private final String description; + + @Getter private final CommandBuilder builder; protected AbstractSlashCommand(String name, String description) { @@ -26,18 +32,6 @@ protected AbstractSlashCommand(String name, String description) { public abstract ReplyAction execute(SlashCommandEvent event); - public String getName() { - return name; - } - - public String getDescription() { - return description; - } - - protected CommandBuilder getBuilder() { - return builder; - } - public CommandData getData() { return builder.build(); } From f552386f8b09cf46f03a5b2a910c4377f0a5cf15 Mon Sep 17 00:00:00 2001 From: excale Date: Sun, 17 Oct 2021 01:00:11 +0200 Subject: [PATCH 07/46] Added reload button on TrackIndex --- .../vgreeter/commands/TrackIndexCommand.java | 21 ++++++++++--------- .../ovh/excale/vgreeter/utilities/Emojis.java | 13 ++++++++++++ 2 files changed, 24 insertions(+), 10 deletions(-) create mode 100644 src/main/java/ovh/excale/vgreeter/utilities/Emojis.java diff --git a/src/main/java/ovh/excale/vgreeter/commands/TrackIndexCommand.java b/src/main/java/ovh/excale/vgreeter/commands/TrackIndexCommand.java index 10d2a6e..cae1f47 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/TrackIndexCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/TrackIndexCommand.java @@ -1,7 +1,6 @@ package ovh.excale.vgreeter.commands; import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.entities.Emoji; import net.dv8tion.jda.api.events.interaction.ButtonClickEvent; import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; import net.dv8tion.jda.api.hooks.EventListener; @@ -20,6 +19,7 @@ import ovh.excale.vgreeter.commands.core.AbstractSlashCommand; import ovh.excale.vgreeter.models.TrackModel; import ovh.excale.vgreeter.repositories.TrackRepository; +import ovh.excale.vgreeter.utilities.Emojis; import java.awt.*; import java.util.Optional; @@ -59,9 +59,8 @@ public ReplyAction execute(SlashCommandEvent event) { .reply("Page option must be positive!") .setEphemeral(true); - Page trackPage = trackRepo.findAll(PageRequest.of(humanBasedPage - 1, - 15, - Sort.by(Sort.Direction.ASC, "id"))); + Page trackPage = trackRepo.findAll( + PageRequest.of(humanBasedPage - 1, 15, Sort.by(Sort.Direction.ASC, "id"))); if(trackPage.isEmpty()) return event @@ -114,13 +113,16 @@ private Component[] computeButtons(Page trackPage) { int zeroBasedPage = trackPage.getNumber(); Button prevButton = Button - .secondary(BUTTON_COMMAND + (zeroBasedPage), Emoji.fromUnicode("\u25C0")) + .secondary(BUTTON_COMMAND + zeroBasedPage, Emojis.PREVIOUS) .withDisabled(!trackPage.hasPrevious()); + Button nextButton = Button - .secondary(BUTTON_COMMAND + (zeroBasedPage + 2), Emoji.fromUnicode("\u25B6")) + .secondary(BUTTON_COMMAND + (zeroBasedPage + 2), Emojis.NEXT) .withDisabled(!trackPage.hasNext()); - return new Component[] { prevButton, nextButton }; + Button reloadButton = Button.secondary(BUTTON_COMMAND + (zeroBasedPage + 1), Emojis.RELOAD); + + return new Component[] { prevButton, nextButton, reloadButton }; } @@ -156,9 +158,8 @@ public void onButtonClick(@NotNull ButtonClickEvent event) { return; } - Page trackPage = trackRepo.findAll(PageRequest.of(humanBasedPage - 1, - 15, - Sort.by(Sort.Direction.ASC, "id"))); + Page trackPage = trackRepo.findAll( + PageRequest.of(humanBasedPage - 1, 15, Sort.by(Sort.Direction.ASC, "id"))); if(trackPage.isEmpty()) { event diff --git a/src/main/java/ovh/excale/vgreeter/utilities/Emojis.java b/src/main/java/ovh/excale/vgreeter/utilities/Emojis.java new file mode 100644 index 0000000..05e08f3 --- /dev/null +++ b/src/main/java/ovh/excale/vgreeter/utilities/Emojis.java @@ -0,0 +1,13 @@ +package ovh.excale.vgreeter.utilities; + +import net.dv8tion.jda.api.entities.Emoji; + +public class Emojis { + + public static final Emoji PREVIOUS = Emoji.fromUnicode("\u25C0"); + + public static final Emoji NEXT = Emoji.fromUnicode("\u25B6"); + + public static final Emoji RELOAD = Emoji.fromUnicode("U+1F504"); + +} From e986f4a273b8d53faf22d481910517069f5f0915 Mon Sep 17 00:00:00 2001 From: excale Date: Sun, 17 Oct 2021 01:05:52 +0200 Subject: [PATCH 08/46] Get Maintenance Flag on application creation --- src/main/java/ovh/excale/vgreeter/VGreeterApplication.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/ovh/excale/vgreeter/VGreeterApplication.java b/src/main/java/ovh/excale/vgreeter/VGreeterApplication.java index 093a832..bfa68a2 100644 --- a/src/main/java/ovh/excale/vgreeter/VGreeterApplication.java +++ b/src/main/java/ovh/excale/vgreeter/VGreeterApplication.java @@ -72,8 +72,10 @@ public static ApplicationContext getApplicationContext() { public final String version; - public VGreeterApplication(@Value("${application.version}") String version) { + public VGreeterApplication(@Value("${application.version}") String version, + @Value("${env.MAINTENANCE:false}") boolean maintenance) { this.version = version; + VGreeterApplication.maintenance = maintenance; } @Override From 6e2582269de4ead8ba49548982304585d4ab4b5e Mon Sep 17 00:00:00 2001 From: excale Date: Sun, 17 Oct 2021 01:14:05 +0200 Subject: [PATCH 09/46] Added a close button to TrackIndex --- .../vgreeter/commands/TrackIndexCommand.java | 19 +++++++++++++++++-- .../ovh/excale/vgreeter/utilities/Emojis.java | 2 ++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/main/java/ovh/excale/vgreeter/commands/TrackIndexCommand.java b/src/main/java/ovh/excale/vgreeter/commands/TrackIndexCommand.java index cae1f47..24a5f85 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/TrackIndexCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/TrackIndexCommand.java @@ -122,7 +122,9 @@ private Component[] computeButtons(Page trackPage) { Button reloadButton = Button.secondary(BUTTON_COMMAND + (zeroBasedPage + 1), Emojis.RELOAD); - return new Component[] { prevButton, nextButton, reloadButton }; + Button closeButton = Button.secondary(BUTTON_COMMAND + "close", Emojis.CLOSE); + + return new Component[] { prevButton, nextButton, reloadButton, closeButton }; } @@ -136,8 +138,21 @@ public void onButtonClick(@NotNull ButtonClickEvent event) { String stringPage = event .getComponentId() .replace(BUTTON_COMMAND, ""); - int humanBasedPage; + // Close TrackIndex action + if(stringPage.equalsIgnoreCase("close")) { + + //noinspection ConstantConditions + event + .getMessage() + .delete() + .queue(); + return; + + } + + // Index page + int humanBasedPage; try { humanBasedPage = Integer.parseInt(stringPage); diff --git a/src/main/java/ovh/excale/vgreeter/utilities/Emojis.java b/src/main/java/ovh/excale/vgreeter/utilities/Emojis.java index 05e08f3..2c4c512 100644 --- a/src/main/java/ovh/excale/vgreeter/utilities/Emojis.java +++ b/src/main/java/ovh/excale/vgreeter/utilities/Emojis.java @@ -10,4 +10,6 @@ public class Emojis { public static final Emoji RELOAD = Emoji.fromUnicode("U+1F504"); + public static final Emoji CLOSE = Emoji.fromUnicode("U+1F1FD"); + } From 3c6b1b776a98e93bd7b55cb2bdeb44b061f44fbe Mon Sep 17 00:00:00 2001 From: excale Date: Sun, 17 Oct 2021 01:22:25 +0200 Subject: [PATCH 10/46] Version upgrade --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index fedcd76..1255b10 100644 --- a/pom.xml +++ b/pom.xml @@ -13,7 +13,7 @@ ovh.excale vgreeter - 2.3.0 + 2.4.0 VGreeter Let the bot greet your friends when they join vocal chat on Discord! From 742981ac8ed307b24ba3773eaf361547f8ac1afd Mon Sep 17 00:00:00 2001 From: excale Date: Mon, 18 Oct 2021 20:29:43 +0200 Subject: [PATCH 11/46] Added uploaded tracks to UserModel --- src/main/java/ovh/excale/vgreeter/models/UserModel.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/ovh/excale/vgreeter/models/UserModel.java b/src/main/java/ovh/excale/vgreeter/models/UserModel.java index 6631d9f..9c00987 100644 --- a/src/main/java/ovh/excale/vgreeter/models/UserModel.java +++ b/src/main/java/ovh/excale/vgreeter/models/UserModel.java @@ -3,6 +3,7 @@ import lombok.*; import javax.persistence.*; +import java.util.Set; @Builder @AllArgsConstructor @@ -24,6 +25,10 @@ public class UserModel { @Column(name = "tracks_max") private Integer trackMaxSize = 64 * 1024; + @ToString.Exclude + @OneToMany(fetch = FetchType.LAZY, mappedBy = "uploader") + private Set tracks; + @SuppressWarnings("unused") public static class UserModelBuilder { From 026df48b24445f15d60cf2dc2e24f4defe545c57 Mon Sep 17 00:00:00 2001 From: excale Date: Tue, 19 Oct 2021 21:25:43 +0200 Subject: [PATCH 12/46] Added TrackRemove command --- .../vgreeter/commands/TrackRemoveCommand.java | 70 +++++++++++++++++++ .../excale/vgreeter/models/TrackModel.java | 3 + .../vgreeter/services/DiscordService.java | 12 ++-- 3 files changed, 77 insertions(+), 8 deletions(-) create mode 100644 src/main/java/ovh/excale/vgreeter/commands/TrackRemoveCommand.java diff --git a/src/main/java/ovh/excale/vgreeter/commands/TrackRemoveCommand.java b/src/main/java/ovh/excale/vgreeter/commands/TrackRemoveCommand.java new file mode 100644 index 0000000..3c4004d --- /dev/null +++ b/src/main/java/ovh/excale/vgreeter/commands/TrackRemoveCommand.java @@ -0,0 +1,70 @@ +package ovh.excale.vgreeter.commands; + +import net.dv8tion.jda.api.entities.User; +import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; +import net.dv8tion.jda.api.interactions.commands.OptionType; +import net.dv8tion.jda.api.requests.restaction.interactions.ReplyAction; +import ovh.excale.vgreeter.VGreeterApplication; +import ovh.excale.vgreeter.commands.core.AbstractSlashCommand; +import ovh.excale.vgreeter.models.TrackModel; +import ovh.excale.vgreeter.repositories.TrackRepository; +import ovh.excale.vgreeter.repositories.UserRepository; + +import java.util.Optional; + +public class TrackRemoveCommand extends AbstractSlashCommand { + + private final TrackRepository trackRepo; + + public TrackRemoveCommand() { + super("trackremove", "Delete a track"); + this + .getBuilder() + .addOptionRequired("trackid", "The track to remove", OptionType.INTEGER); + + trackRepo = VGreeterApplication + .getApplicationContext() + .getBean(TrackRepository.class); + + } + + @Override + public ReplyAction execute(SlashCommandEvent event) { + + ReplyAction reply; + User user = event.getUser(); + + //noinspection ConstantConditions + long trackId = event + .getOption("trackid") + .getAsLong(); + + Optional opt = trackRepo.findById(trackId); + if(!opt.isPresent()) + reply = event + .reply("No track with such id") + .setEphemeral(true); + else { + + TrackModel track = opt.get(); + Long userId = user.getIdLong(); + + if(!userId.equals(track.getUploaderId())) + reply = event + .reply("You're not the uploader of track `" + trackId + "`") + .setEphemeral(true); + else { + + trackRepo.delete(track); + reply = event + .reply("Track `" + trackId + "` deleted successfully") + .setEphemeral(true); + + } + + } + + return reply; + } + +} diff --git a/src/main/java/ovh/excale/vgreeter/models/TrackModel.java b/src/main/java/ovh/excale/vgreeter/models/TrackModel.java index 6596e88..769ec2b 100644 --- a/src/main/java/ovh/excale/vgreeter/models/TrackModel.java +++ b/src/main/java/ovh/excale/vgreeter/models/TrackModel.java @@ -42,6 +42,9 @@ public class TrackModel { @JoinColumn(name = "uploader_id") private UserModel uploader; + @Column(name = "uploader_id", insertable = false, updatable = false) + private Long uploaderId; + public OggPacketReader getPacketReader() { return new OggPacketReader(new ByteArrayInputStream(getData())); } diff --git a/src/main/java/ovh/excale/vgreeter/services/DiscordService.java b/src/main/java/ovh/excale/vgreeter/services/DiscordService.java index 5f37b7a..bd755ba 100644 --- a/src/main/java/ovh/excale/vgreeter/services/DiscordService.java +++ b/src/main/java/ovh/excale/vgreeter/services/DiscordService.java @@ -33,15 +33,10 @@ public DiscordService(VoiceChannelHandler eventHandler, CommandRegister commands @Value("${env.DISCORD_TOKEN}") String token) throws LoginException, InterruptedException { jda = JDABuilder - .create(token, - GatewayIntent.GUILD_VOICE_STATES, - GatewayIntent.DIRECT_MESSAGES, + .create(token, GatewayIntent.GUILD_VOICE_STATES, GatewayIntent.DIRECT_MESSAGES, GatewayIntent.GUILD_VOICE_STATES) - .disableCache(CacheFlag.ACTIVITY, - CacheFlag.ONLINE_STATUS, - CacheFlag.CLIENT_STATUS, - CacheFlag.MEMBER_OVERRIDES, - CacheFlag.EMOTE) + .disableCache(CacheFlag.ACTIVITY, CacheFlag.ONLINE_STATUS, CacheFlag.CLIENT_STATUS, + CacheFlag.MEMBER_OVERRIDES, CacheFlag.EMOTE) .setActivity(Activity.listening("people")) .addEventListeners(eventHandler, commands.getListener()) .build() @@ -59,6 +54,7 @@ public DiscordService(VoiceChannelHandler eventHandler, CommandRegister commands .register(new PlaytestCommand()) .register(new TracknameCommand()) .register(new TrackIndexCommand()) + .register(new TrackRemoveCommand()) // MESSAGE COMMANDS .register(new RestartCommand()) .register(new UploadCommand()) From ddba38a6322385049d8725c64d6f290e67afb543 Mon Sep 17 00:00:00 2001 From: excale Date: Tue, 19 Oct 2021 21:30:43 +0200 Subject: [PATCH 13/46] Moved related commands to 'commands.track' package --- .../excale/vgreeter/commands/{ => track}/PlaytestCommand.java | 4 +--- .../vgreeter/commands/{ => track}/TrackIndexCommand.java | 2 +- .../vgreeter/commands/{ => track}/TrackRemoveCommand.java | 3 +-- .../vgreeter/commands/{ => track}/TracknameCommand.java | 2 +- .../excale/vgreeter/commands/{ => track}/UploadCommand.java | 2 +- .../java/ovh/excale/vgreeter/services/DiscordService.java | 1 + 6 files changed, 6 insertions(+), 8 deletions(-) rename src/main/java/ovh/excale/vgreeter/commands/{ => track}/PlaytestCommand.java (96%) rename src/main/java/ovh/excale/vgreeter/commands/{ => track}/TrackIndexCommand.java (99%) rename src/main/java/ovh/excale/vgreeter/commands/{ => track}/TrackRemoveCommand.java (94%) rename src/main/java/ovh/excale/vgreeter/commands/{ => track}/TracknameCommand.java (98%) rename src/main/java/ovh/excale/vgreeter/commands/{ => track}/UploadCommand.java (99%) diff --git a/src/main/java/ovh/excale/vgreeter/commands/PlaytestCommand.java b/src/main/java/ovh/excale/vgreeter/commands/track/PlaytestCommand.java similarity index 96% rename from src/main/java/ovh/excale/vgreeter/commands/PlaytestCommand.java rename to src/main/java/ovh/excale/vgreeter/commands/track/PlaytestCommand.java index 3c520a4..ff22ad1 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/PlaytestCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/track/PlaytestCommand.java @@ -1,4 +1,4 @@ -package ovh.excale.vgreeter.commands; +package ovh.excale.vgreeter.commands.track; import lombok.extern.log4j.Log4j2; import net.dv8tion.jda.api.entities.Guild; @@ -9,8 +9,6 @@ import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.managers.AudioManager; import net.dv8tion.jda.api.requests.restaction.interactions.ReplyAction; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import ovh.excale.vgreeter.VGreeterApplication; import ovh.excale.vgreeter.commands.core.AbstractSlashCommand; import ovh.excale.vgreeter.models.TrackModel; diff --git a/src/main/java/ovh/excale/vgreeter/commands/TrackIndexCommand.java b/src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java similarity index 99% rename from src/main/java/ovh/excale/vgreeter/commands/TrackIndexCommand.java rename to src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java index 24a5f85..65a2b99 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/TrackIndexCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java @@ -1,4 +1,4 @@ -package ovh.excale.vgreeter.commands; +package ovh.excale.vgreeter.commands.track; import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.events.interaction.ButtonClickEvent; diff --git a/src/main/java/ovh/excale/vgreeter/commands/TrackRemoveCommand.java b/src/main/java/ovh/excale/vgreeter/commands/track/TrackRemoveCommand.java similarity index 94% rename from src/main/java/ovh/excale/vgreeter/commands/TrackRemoveCommand.java rename to src/main/java/ovh/excale/vgreeter/commands/track/TrackRemoveCommand.java index 3c4004d..4d805b7 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/TrackRemoveCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/track/TrackRemoveCommand.java @@ -1,4 +1,4 @@ -package ovh.excale.vgreeter.commands; +package ovh.excale.vgreeter.commands.track; import net.dv8tion.jda.api.entities.User; import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; @@ -8,7 +8,6 @@ import ovh.excale.vgreeter.commands.core.AbstractSlashCommand; import ovh.excale.vgreeter.models.TrackModel; import ovh.excale.vgreeter.repositories.TrackRepository; -import ovh.excale.vgreeter.repositories.UserRepository; import java.util.Optional; diff --git a/src/main/java/ovh/excale/vgreeter/commands/TracknameCommand.java b/src/main/java/ovh/excale/vgreeter/commands/track/TracknameCommand.java similarity index 98% rename from src/main/java/ovh/excale/vgreeter/commands/TracknameCommand.java rename to src/main/java/ovh/excale/vgreeter/commands/track/TracknameCommand.java index 201a9e7..a045ae7 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/TracknameCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/track/TracknameCommand.java @@ -1,4 +1,4 @@ -package ovh.excale.vgreeter.commands; +package ovh.excale.vgreeter.commands.track; import net.dv8tion.jda.api.entities.User; import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; diff --git a/src/main/java/ovh/excale/vgreeter/commands/UploadCommand.java b/src/main/java/ovh/excale/vgreeter/commands/track/UploadCommand.java similarity index 99% rename from src/main/java/ovh/excale/vgreeter/commands/UploadCommand.java rename to src/main/java/ovh/excale/vgreeter/commands/track/UploadCommand.java index 20be746..bf024fb 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/UploadCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/track/UploadCommand.java @@ -1,4 +1,4 @@ -package ovh.excale.vgreeter.commands; +package ovh.excale.vgreeter.commands.track; import lombok.extern.log4j.Log4j2; import net.dv8tion.jda.api.entities.Message; diff --git a/src/main/java/ovh/excale/vgreeter/services/DiscordService.java b/src/main/java/ovh/excale/vgreeter/services/DiscordService.java index bd755ba..97758cd 100644 --- a/src/main/java/ovh/excale/vgreeter/services/DiscordService.java +++ b/src/main/java/ovh/excale/vgreeter/services/DiscordService.java @@ -13,6 +13,7 @@ import org.springframework.stereotype.Service; import ovh.excale.vgreeter.commands.*; import ovh.excale.vgreeter.commands.core.CommandRegister; +import ovh.excale.vgreeter.commands.track.*; import javax.security.auth.login.LoginException; import java.util.Collections; From 0a914f877407466ded0c23a03954bcfa59982adb Mon Sep 17 00:00:00 2001 From: excale Date: Tue, 19 Oct 2021 21:31:06 +0200 Subject: [PATCH 14/46] Renamed TrackUpload command --- .../track/{UploadCommand.java => TrackUploadCommand.java} | 4 ++-- .../java/ovh/excale/vgreeter/services/DiscordService.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename src/main/java/ovh/excale/vgreeter/commands/track/{UploadCommand.java => TrackUploadCommand.java} (97%) diff --git a/src/main/java/ovh/excale/vgreeter/commands/track/UploadCommand.java b/src/main/java/ovh/excale/vgreeter/commands/track/TrackUploadCommand.java similarity index 97% rename from src/main/java/ovh/excale/vgreeter/commands/track/UploadCommand.java rename to src/main/java/ovh/excale/vgreeter/commands/track/TrackUploadCommand.java index bf024fb..7dffb44 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/track/UploadCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/track/TrackUploadCommand.java @@ -28,14 +28,14 @@ import java.util.regex.Pattern; @Log4j2 -public class UploadCommand extends AbstractMessageCommand { +public class TrackUploadCommand extends AbstractMessageCommand { private static final Pattern TRACK_NAME_PATTERN = Pattern.compile("([\\w\\d-_]+)\\.opus"); private final UserRepository userRepo; private final TrackService trackService; - public UploadCommand() { + public TrackUploadCommand() { super("upload", ""); userRepo = VGreeterApplication diff --git a/src/main/java/ovh/excale/vgreeter/services/DiscordService.java b/src/main/java/ovh/excale/vgreeter/services/DiscordService.java index 97758cd..8d58aec 100644 --- a/src/main/java/ovh/excale/vgreeter/services/DiscordService.java +++ b/src/main/java/ovh/excale/vgreeter/services/DiscordService.java @@ -58,7 +58,7 @@ public DiscordService(VoiceChannelHandler eventHandler, CommandRegister commands .register(new TrackRemoveCommand()) // MESSAGE COMMANDS .register(new RestartCommand()) - .register(new UploadCommand()) + .register(new TrackUploadCommand()) .getSlashCommandsData()) .complete() .stream() From e549c14b8b8f8633d1b4a9047fd304c8c042104a Mon Sep 17 00:00:00 2001 From: excale Date: Tue, 19 Oct 2021 21:32:09 +0200 Subject: [PATCH 15/46] Version upgrade --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1255b10..110a9f4 100644 --- a/pom.xml +++ b/pom.xml @@ -13,7 +13,7 @@ ovh.excale vgreeter - 2.4.0 + 2.5.0 VGreeter Let the bot greet your friends when they join vocal chat on Discord! From 102676908ec3b4c142e73a7e90e58653e4f38708 Mon Sep 17 00:00:00 2001 From: excale Date: Tue, 19 Oct 2021 21:35:04 +0200 Subject: [PATCH 16/46] Set TrackIndex's reply as ephimeral --- .../excale/vgreeter/commands/track/TrackIndexCommand.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java b/src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java index 65a2b99..5a9be66 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java @@ -76,11 +76,9 @@ public ReplyAction execute(SlashCommandEvent event) { .setActionRow(computeButtons(trackPage)) .queueAfter(2, TimeUnit.SECONDS); - String userMention = event - .getUser() - .getAsMention(); - - return event.reply("Track Index requested by " + userMention); + return event + .reply("Here's your track index!") + .setEphemeral(true); } From 30254c257d5e7f4a8355d908201f8f80333b509a Mon Sep 17 00:00:00 2001 From: excale Date: Tue, 19 Oct 2021 21:35:27 +0200 Subject: [PATCH 17/46] Version upgrade --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 110a9f4..fc82ed2 100644 --- a/pom.xml +++ b/pom.xml @@ -13,7 +13,7 @@ ovh.excale vgreeter - 2.5.0 + 2.5.1 VGreeter Let the bot greet your friends when they join vocal chat on Discord! From 6fb7a7b3df18e735f706f876e5c7f5b7c6003aff Mon Sep 17 00:00:00 2001 From: excale Date: Thu, 21 Oct 2021 22:42:20 +0200 Subject: [PATCH 18/46] Excluded .env from jar build --- pom.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pom.xml b/pom.xml index fc82ed2..2b5a631 100644 --- a/pom.xml +++ b/pom.xml @@ -104,6 +104,9 @@ src/main/resources false + + .env + src/main/resources-filtered From da6f623fad17dbabde6655f6f25beecd3ace3a0c Mon Sep 17 00:00:00 2001 From: excale Date: Fri, 22 Oct 2021 22:59:18 +0200 Subject: [PATCH 19/46] Removed fulfilled TODO --- .../ovh/excale/vgreeter/commands/track/TrackIndexCommand.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java b/src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java index 5a9be66..ed2784d 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java @@ -126,7 +126,6 @@ private Component[] computeButtons(Page trackPage) { } - // TODO: CLOSE INDEX BUTTON public class ButtonClickListener extends ListenerAdapter { @Override From 71c1f00a905fa1f52193ea78e4eb62402465e4dc Mon Sep 17 00:00:00 2001 From: Emanuele Scaccia Date: Mon, 3 Jan 2022 23:56:10 +0100 Subject: [PATCH 20/46] feat: Added options to TrackIndex --- pom.xml | 6 +- .../commands/track/TrackIndexCommand.java | 244 ++++++++++++++---- .../repositories/TrackRepository.java | 6 + .../vgreeter/services/DiscordService.java | 5 +- .../vgreeter/utilities/ArgumentsParser.java | 5 + 5 files changed, 214 insertions(+), 52 deletions(-) diff --git a/pom.xml b/pom.xml index 2b5a631..088d820 100644 --- a/pom.xml +++ b/pom.xml @@ -104,9 +104,9 @@ src/main/resources false - - .env - + + + src/main/resources-filtered diff --git a/src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java b/src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java index ed2784d..3e1a114 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java @@ -1,10 +1,12 @@ package ovh.excale.vgreeter.commands.track; import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.entities.User; import net.dv8tion.jda.api.events.interaction.ButtonClickEvent; import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; import net.dv8tion.jda.api.hooks.EventListener; import net.dv8tion.jda.api.hooks.ListenerAdapter; +import net.dv8tion.jda.api.interactions.Interaction; import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.components.Button; @@ -19,23 +21,43 @@ import ovh.excale.vgreeter.commands.core.AbstractSlashCommand; import ovh.excale.vgreeter.models.TrackModel; import ovh.excale.vgreeter.repositories.TrackRepository; +import ovh.excale.vgreeter.utilities.ArgumentsParser; import ovh.excale.vgreeter.utilities.Emojis; import java.awt.*; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; import java.util.Optional; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; public class TrackIndexCommand extends AbstractSlashCommand { - public static final String BUTTON_COMMAND = "trackindex:"; + public static final String BUTTON_COMMAND = "trackindex"; + + public static final String SUBCOMMAND_ALL = "all"; + public static final String SUBCOMMAND_NAME = "name"; + public static final String SUBCOMMAND_USER = "user"; private final TrackRepository trackRepo; private final ButtonClickListener buttonListener; public TrackIndexCommand() { super("trackindex", "List all the tracks"); - getBuilder().addOption("page", "Page number", OptionType.INTEGER); + // TODO: + getBuilder() + // [SUB] all + .subcommand(SUBCOMMAND_ALL, "Search for all tracks") + .addOption("page", "Page number", OptionType.INTEGER) + // [SUB] name + .subcommand(SUBCOMMAND_NAME, "Search for all tracks with something in the name") + .addOptionRequired("name", "Track name", OptionType.STRING) + .addOption("page", "Page number", OptionType.INTEGER) + // [SUB] user + .subcommand(SUBCOMMAND_USER, "Search for tracks by a user") + .addOptionRequired("user", "The user to query for", OptionType.USER) + .addOption("page", "Page number", OptionType.INTEGER); trackRepo = VGreeterApplication .getApplicationContext() @@ -59,8 +81,41 @@ public ReplyAction execute(SlashCommandEvent event) { .reply("Page option must be positive!") .setEphemeral(true); - Page trackPage = trackRepo.findAll( - PageRequest.of(humanBasedPage - 1, 15, Sort.by(Sort.Direction.ASC, "id"))); + Page trackPage; + String subcommand = event.getSubcommandName(); + + //noinspection ConstantConditions + switch(subcommand) { + + case SUBCOMMAND_ALL: + trackPage = trackRepo.findAll( + PageRequest.of(humanBasedPage - 1, 15, Sort.by(Sort.Direction.ASC, "id"))); + break; + + case SUBCOMMAND_NAME: + //noinspection ConstantConditions + String optionName = event + .getOption("name") + .getAsString(); + trackPage = trackRepo.findAllByNameLike(optionName, + PageRequest.of(humanBasedPage - 1, 15, Sort.by(Sort.Direction.ASC, "id"))); + break; + + case SUBCOMMAND_USER: + //noinspection ConstantConditions + User optionUser = event + .getOption("user") + .getAsUser(); + trackPage = trackRepo.findAllByUploaderIdIs(optionUser.getIdLong(), + PageRequest.of(humanBasedPage - 1, 15, Sort.by(Sort.Direction.ASC, "id"))); + break; + + default: + return event + .reply("Unknown option `" + event.getSubcommandName() + "`") + .setEphemeral(true); + + } if(trackPage.isEmpty()) return event @@ -73,7 +128,7 @@ public ReplyAction execute(SlashCommandEvent event) { event .getChannel() .sendMessage(eb.build()) - .setActionRow(computeButtons(trackPage)) + .setActionRow(computeButtons(trackPage, subcommand)) .queueAfter(2, TimeUnit.SECONDS); return event @@ -106,79 +161,172 @@ public boolean hasListener() { } - private Component[] computeButtons(Page trackPage) { + // TODO: json as component_id + private Component[] computeButtons(Page trackPage, String subcommand, Object... args) { int zeroBasedPage = trackPage.getNumber(); + String joinedArgs = (args.length == 0) + ? "" + : Arrays + .stream(args) + .map(Object::toString) + .collect(Collectors.joining(":")); Button prevButton = Button - .secondary(BUTTON_COMMAND + zeroBasedPage, Emojis.PREVIOUS) + .secondary(String.format("%s:%s:%s", BUTTON_COMMAND, subcommand, + argsAppendPageNumber(joinedArgs, zeroBasedPage)), Emojis.PREVIOUS) .withDisabled(!trackPage.hasPrevious()); Button nextButton = Button - .secondary(BUTTON_COMMAND + (zeroBasedPage + 2), Emojis.NEXT) + .secondary(String.format("%s:%s:%s", BUTTON_COMMAND, subcommand, + argsAppendPageNumber(joinedArgs, zeroBasedPage + 2)), Emojis.NEXT) .withDisabled(!trackPage.hasNext()); - Button reloadButton = Button.secondary(BUTTON_COMMAND + (zeroBasedPage + 1), Emojis.RELOAD); + Button reloadButton = Button.secondary(String.format("%s:%s:%s", BUTTON_COMMAND, subcommand, + argsAppendPageNumber(joinedArgs, zeroBasedPage + 1)), Emojis.RELOAD); - Button closeButton = Button.secondary(BUTTON_COMMAND + "close", Emojis.CLOSE); + Button closeButton = Button.secondary(String.format("%s:%s", BUTTON_COMMAND, "close"), Emojis.CLOSE); return new Component[] { prevButton, nextButton, reloadButton, closeButton }; } + private static String argsAppendPageNumber(String joinedArgs, int page) { + + if(joinedArgs.isEmpty()) + return String.valueOf(page); + else + return joinedArgs + ":" + page; + + } + + private static void replyEphemeralWith(String message, Interaction event) { + event + .reply(message) + .setEphemeral(true) + .queue(); + } + public class ButtonClickListener extends ListenerAdapter { @Override public void onButtonClick(@NotNull ButtonClickEvent event) { - // TODO: COMPONENT_ID COMMAND CHECK - String stringPage = event - .getComponentId() - .replace(BUTTON_COMMAND, ""); - - // Close TrackIndex action - if(stringPage.equalsIgnoreCase("close")) { + // 0: command, 1: subcommand, 2+:args + ArgumentsParser parser = new ArgumentsParser(event.getComponentId(), ":"); - //noinspection ConstantConditions - event - .getMessage() - .delete() - .queue(); + String command = parser.getArgumentString(0, ""); + if(!command.equalsIgnoreCase(BUTTON_COMMAND)) return; - } + List args = new LinkedList<>(); + Page trackPage; + int zeroBasedPage; - // Index page - int humanBasedPage; - try { + String subcommand = parser.getArgumentString(1, ""); + switch(subcommand) { - humanBasedPage = Integer.parseInt(stringPage); + case "close": + //noinspection ConstantConditions + event + .getMessage() + .delete() + .queue(); + return; - } catch(NumberFormatException e) { - event - .reply("Invalid button") - .setEphemeral(true) - .queue(); - return; - } + case SUBCOMMAND_ALL: - if(humanBasedPage < 1) { - event - .reply("Invalid button") - .setEphemeral(true) - .queue(); - return; - } + zeroBasedPage = parser + .getArgumentInteger(2) + .map(i -> i - 1) + .orElse(0); + + if(zeroBasedPage < 1) { + + replyEphemeralWith("Invalid button", event); + return; + + } + + args.add(zeroBasedPage); + + trackPage = trackRepo.findAll(PageRequest.of(zeroBasedPage, 15, Sort.by(Sort.Direction.ASC, "id"))); - Page trackPage = trackRepo.findAll( - PageRequest.of(humanBasedPage - 1, 15, Sort.by(Sort.Direction.ASC, "id"))); + break; + + case SUBCOMMAND_NAME: + + Optional optStr = parser.getArgumentString(2); + if(!optStr.isPresent()) { + + replyEphemeralWith("Invalid button", event); + return; + + } + + String trackSubname = optStr.get(); + zeroBasedPage = parser + .getArgumentInteger(3) + .map(i -> i - 1) + .orElse(0); + + if(zeroBasedPage < 1) { + + replyEphemeralWith("Invalid button", event); + return; + + } + + args.add(trackSubname); + args.add(zeroBasedPage); + + trackPage = trackRepo.findAllByNameLike(trackSubname, + PageRequest.of(zeroBasedPage, 15, Sort.by(Sort.Direction.ASC, "id"))); + + break; + + case SUBCOMMAND_USER: + + Optional optLong = parser.getArgumentLong(2); + if(!optLong.isPresent()) { + + replyEphemeralWith("Invalid button", event); + return; + + } + + long uploaderId = optLong.get(); + zeroBasedPage = parser + .getArgumentInteger(3) + .map(i -> i - 1) + .orElse(0); + + if(zeroBasedPage < 1) { + + replyEphemeralWith("Invalid button", event); + return; + + } + + args.add(uploaderId); + args.add(zeroBasedPage); + + trackPage = trackRepo.findAllByUploaderIdIs(uploaderId, + PageRequest.of(zeroBasedPage, 15, Sort.by(Sort.Direction.ASC, "id"))); + + break; + + default: + replyEphemeralWith("Unknown option `" + subcommand + "`", event); + return; + + } if(trackPage.isEmpty()) { - event - .reply("Empty page") - .setEphemeral(true) - .queue(); + + replyEphemeralWith("Empty page", event); return; + } EmbedBuilder eb = computeEmbed(trackPage); @@ -190,7 +338,7 @@ public void onButtonClick(@NotNull ButtonClickEvent event) { .and(event .getChannel() .sendMessage(eb.build()) - .setActionRow(computeButtons(trackPage))) + .setActionRow(computeButtons(trackPage, subcommand, args.toArray()))) .queue(); } diff --git a/src/main/java/ovh/excale/vgreeter/repositories/TrackRepository.java b/src/main/java/ovh/excale/vgreeter/repositories/TrackRepository.java index 874433d..f5e3e71 100644 --- a/src/main/java/ovh/excale/vgreeter/repositories/TrackRepository.java +++ b/src/main/java/ovh/excale/vgreeter/repositories/TrackRepository.java @@ -1,5 +1,7 @@ package ovh.excale.vgreeter.repositories; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.stereotype.Repository; import ovh.excale.vgreeter.models.TrackModel; @@ -10,4 +12,8 @@ public interface TrackRepository extends PagingAndSortingRepository findAllByNameLike(String name, Pageable pageable); + + Page findAllByUploaderIdIs(long userId, Pageable pageable); + } diff --git a/src/main/java/ovh/excale/vgreeter/services/DiscordService.java b/src/main/java/ovh/excale/vgreeter/services/DiscordService.java index 8d58aec..bb447a3 100644 --- a/src/main/java/ovh/excale/vgreeter/services/DiscordService.java +++ b/src/main/java/ovh/excale/vgreeter/services/DiscordService.java @@ -11,7 +11,10 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Service; -import ovh.excale.vgreeter.commands.*; +import ovh.excale.vgreeter.commands.AltnameCommand; +import ovh.excale.vgreeter.commands.ProbabilityCommand; +import ovh.excale.vgreeter.commands.RestartCommand; +import ovh.excale.vgreeter.commands.UploadHelpCommand; import ovh.excale.vgreeter.commands.core.CommandRegister; import ovh.excale.vgreeter.commands.track.*; diff --git a/src/main/java/ovh/excale/vgreeter/utilities/ArgumentsParser.java b/src/main/java/ovh/excale/vgreeter/utilities/ArgumentsParser.java index 3f2e9cb..9eba0d6 100644 --- a/src/main/java/ovh/excale/vgreeter/utilities/ArgumentsParser.java +++ b/src/main/java/ovh/excale/vgreeter/utilities/ArgumentsParser.java @@ -20,6 +20,11 @@ public ArgumentsParser(String rawArguments) { .split(" "); } + public ArgumentsParser(String rawArguments, String splitRegex) { + this.rawArguments = rawArguments; + splitArguments = rawArguments.split(splitRegex); + } + public String getRawArguments() { return rawArguments; } From 5725cfd1dd3154aa677d523101e50bea2de52dd8 Mon Sep 17 00:00:00 2001 From: Emanuele Scaccia Date: Tue, 4 Jan 2022 00:38:25 +0100 Subject: [PATCH 21/46] feat: Added command to download track feat: Broke track index --- .../commands/track/TrackDownloadCommand.java | 62 +++++++++++++++++++ .../commands/track/TrackIndexCommand.java | 1 + .../vgreeter/services/DiscordService.java | 3 +- 3 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 src/main/java/ovh/excale/vgreeter/commands/track/TrackDownloadCommand.java diff --git a/src/main/java/ovh/excale/vgreeter/commands/track/TrackDownloadCommand.java b/src/main/java/ovh/excale/vgreeter/commands/track/TrackDownloadCommand.java new file mode 100644 index 0000000..e6bd48b --- /dev/null +++ b/src/main/java/ovh/excale/vgreeter/commands/track/TrackDownloadCommand.java @@ -0,0 +1,62 @@ +package ovh.excale.vgreeter.commands.track; + +import net.dv8tion.jda.api.MessageBuilder; +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.entities.MessageChannel; +import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; +import net.dv8tion.jda.api.interactions.commands.OptionType; +import net.dv8tion.jda.api.requests.restaction.interactions.ReplyAction; +import ovh.excale.vgreeter.VGreeterApplication; +import ovh.excale.vgreeter.commands.core.AbstractSlashCommand; +import ovh.excale.vgreeter.models.TrackModel; +import ovh.excale.vgreeter.repositories.TrackRepository; + +import java.util.Optional; + +public class TrackDownloadCommand extends AbstractSlashCommand { + + private final TrackRepository trackRepo; + + public TrackDownloadCommand() { + super("trackdownload", "download command placeholder"); + + this.getBuilder() + .addOptionRequired("trackid", "The track to download", OptionType.INTEGER); + + trackRepo = VGreeterApplication.getApplicationContext() + .getBean(TrackRepository.class); + + } + + // TODO: 30sec cooldown (whole-guild scope) on download, probably with stopwatch and queue + + @Override + public ReplyAction execute(SlashCommandEvent event) { + + Guild guild = event.getGuild(); + MessageChannel channel = event.getChannel(); + + if(guild == null) + return event.reply("This command can be executed in a guild only") + .setEphemeral(true); + + //noinspection ConstantConditions + long trackId = Long.parseLong(event.getOption("trackid") + .getAsString()); + + Optional opt = trackRepo.findById(trackId); + + if(!opt.isPresent()) + return event.reply("No track with such id") + .setEphemeral(true); + + TrackModel track = opt.get(); + Message message = new MessageBuilder(String.format("Track `#%d`", track.getId())).build(); + + return event.reply(message) + .addFile(track.getData(), track.getName() + ".opus"); + + } + +} diff --git a/src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java b/src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java index 3e1a114..2c02405 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java @@ -161,6 +161,7 @@ public boolean hasListener() { } + // TODO: cyclic prev/next (first/last page) // TODO: json as component_id private Component[] computeButtons(Page trackPage, String subcommand, Object... args) { diff --git a/src/main/java/ovh/excale/vgreeter/services/DiscordService.java b/src/main/java/ovh/excale/vgreeter/services/DiscordService.java index bb447a3..5d0ac86 100644 --- a/src/main/java/ovh/excale/vgreeter/services/DiscordService.java +++ b/src/main/java/ovh/excale/vgreeter/services/DiscordService.java @@ -48,7 +48,7 @@ public DiscordService(VoiceChannelHandler eventHandler, CommandRegister commands log.info("JDA connected"); - String commandListString = jda + String commandListString = jda.getGuildById(386229289449684994L) .updateCommands() .addCommands(commands // SLASH COMMANDS @@ -59,6 +59,7 @@ public DiscordService(VoiceChannelHandler eventHandler, CommandRegister commands .register(new TracknameCommand()) .register(new TrackIndexCommand()) .register(new TrackRemoveCommand()) + .register(new TrackDownloadCommand()) // MESSAGE COMMANDS .register(new RestartCommand()) .register(new TrackUploadCommand()) From 12a146aa55266ff07de4744205b5a7b5aeb85af5 Mon Sep 17 00:00:00 2001 From: Emanuele Scaccia Date: Tue, 4 Jan 2022 00:40:45 +0100 Subject: [PATCH 22/46] fix: removed single-guild mode (used for develop purpose) --- src/main/java/ovh/excale/vgreeter/services/DiscordService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/ovh/excale/vgreeter/services/DiscordService.java b/src/main/java/ovh/excale/vgreeter/services/DiscordService.java index 5d0ac86..a64b129 100644 --- a/src/main/java/ovh/excale/vgreeter/services/DiscordService.java +++ b/src/main/java/ovh/excale/vgreeter/services/DiscordService.java @@ -48,7 +48,7 @@ public DiscordService(VoiceChannelHandler eventHandler, CommandRegister commands log.info("JDA connected"); - String commandListString = jda.getGuildById(386229289449684994L) + String commandListString = jda .updateCommands() .addCommands(commands // SLASH COMMANDS From 5bb6c533b6341ebd54e3b6707f88e326129a0563 Mon Sep 17 00:00:00 2001 From: Emanuele Scaccia Date: Wed, 2 Feb 2022 23:18:59 +0100 Subject: [PATCH 23/46] feat: TrackIndex now comes right after command reply --- .../commands/core/AbstractSlashCommand.java | 4 +++- .../commands/core/CommandRegister.java | 2 +- .../commands/track/TrackIndexCommand.java | 19 +++++++------------ 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/src/main/java/ovh/excale/vgreeter/commands/core/AbstractSlashCommand.java b/src/main/java/ovh/excale/vgreeter/commands/core/AbstractSlashCommand.java index d3e34f7..06651e7 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/core/AbstractSlashCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/core/AbstractSlashCommand.java @@ -4,7 +4,9 @@ import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; import net.dv8tion.jda.api.hooks.EventListener; import net.dv8tion.jda.api.interactions.commands.build.CommandData; +import net.dv8tion.jda.api.requests.RestAction; import net.dv8tion.jda.api.requests.restaction.interactions.ReplyAction; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import ovh.excale.vgreeter.utilities.CommandBuilder; @@ -30,7 +32,7 @@ protected AbstractSlashCommand(String name, String description) { } - public abstract ReplyAction execute(SlashCommandEvent event); + public abstract @NotNull RestAction execute(SlashCommandEvent event); public CommandData getData() { return builder.build(); diff --git a/src/main/java/ovh/excale/vgreeter/commands/core/CommandRegister.java b/src/main/java/ovh/excale/vgreeter/commands/core/CommandRegister.java index f26a521..361ccc3 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/core/CommandRegister.java +++ b/src/main/java/ovh/excale/vgreeter/commands/core/CommandRegister.java @@ -124,7 +124,7 @@ private void onSlashCommand(SlashCommandEvent event) { } AbstractSlashCommand command = slashCommands.get(event.getName()); - ReplyAction action; + RestAction action; if(command == null) action = event diff --git a/src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java b/src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java index 2c02405..90e7bfe 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java @@ -11,7 +11,7 @@ import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.components.Button; import net.dv8tion.jda.api.interactions.components.Component; -import net.dv8tion.jda.api.requests.restaction.interactions.ReplyAction; +import net.dv8tion.jda.api.requests.RestAction; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.springframework.data.domain.Page; @@ -29,7 +29,6 @@ import java.util.LinkedList; import java.util.List; import java.util.Optional; -import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; public class TrackIndexCommand extends AbstractSlashCommand { @@ -68,7 +67,7 @@ public TrackIndexCommand() { } @Override - public ReplyAction execute(SlashCommandEvent event) { + public @NotNull RestAction execute(SlashCommandEvent event) { int humanBasedPage = Optional .ofNullable(event.getOption("page")) @@ -125,15 +124,11 @@ public ReplyAction execute(SlashCommandEvent event) { EmbedBuilder eb = computeEmbed(trackPage); // TODO: CHECK PERMS AND MESSAGECHANNEL - event - .getChannel() - .sendMessage(eb.build()) - .setActionRow(computeButtons(trackPage, subcommand)) - .queueAfter(2, TimeUnit.SECONDS); - - return event - .reply("Here's your track index!") - .setEphemeral(true); + return event.reply("Here's your track index!") + .setEphemeral(true) + .and(event.getChannel() + .sendMessage(eb.build()) + .setActionRow(computeButtons(trackPage, subcommand))); } From 7c990e5210a275d2cf59c482761698101ef2eb5c Mon Sep 17 00:00:00 2001 From: Emanuele Scaccia Date: Thu, 3 Feb 2022 03:14:15 +0100 Subject: [PATCH 24/46] feat: TrackIndex now with filters (track name, uploader...) feat: Using json for button arguments --- pom.xml | 7 + .../commands/track/TrackIndexCommand.java | 204 +++++++++--------- 2 files changed, 103 insertions(+), 108 deletions(-) diff --git a/pom.xml b/pom.xml index 088d820..a2e3e7b 100644 --- a/pom.xml +++ b/pom.xml @@ -65,6 +65,13 @@ 1.2.5 + + + com.fasterxml.jackson.core + jackson-databind + 2.13.1 + + me.paulschwarz diff --git a/src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java b/src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java index 90e7bfe..b3f0b4b 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java @@ -1,7 +1,10 @@ package ovh.excale.vgreeter.commands.track; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectReader; +import lombok.SneakyThrows; +import lombok.extern.log4j.Log4j2; import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.entities.User; import net.dv8tion.jda.api.events.interaction.ButtonClickEvent; import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; import net.dv8tion.jda.api.hooks.EventListener; @@ -21,20 +24,15 @@ import ovh.excale.vgreeter.commands.core.AbstractSlashCommand; import ovh.excale.vgreeter.models.TrackModel; import ovh.excale.vgreeter.repositories.TrackRepository; -import ovh.excale.vgreeter.utilities.ArgumentsParser; import ovh.excale.vgreeter.utilities.Emojis; import java.awt.*; -import java.util.Arrays; -import java.util.LinkedList; -import java.util.List; -import java.util.Optional; +import java.util.*; import java.util.stream.Collectors; +@Log4j2 public class TrackIndexCommand extends AbstractSlashCommand { - public static final String BUTTON_COMMAND = "trackindex"; - public static final String SUBCOMMAND_ALL = "all"; public static final String SUBCOMMAND_NAME = "name"; public static final String SUBCOMMAND_USER = "user"; @@ -81,32 +79,47 @@ public TrackIndexCommand() { .setEphemeral(true); Page trackPage; + Map options = new HashMap<>(); + String subcommand = event.getSubcommandName(); + options.put("command", getName()); + options.put("subcommand", subcommand); //noinspection ConstantConditions switch(subcommand) { case SUBCOMMAND_ALL: + trackPage = trackRepo.findAll( PageRequest.of(humanBasedPage - 1, 15, Sort.by(Sort.Direction.ASC, "id"))); + break; case SUBCOMMAND_NAME: + //noinspection ConstantConditions - String optionName = event + String trackName = event .getOption("name") .getAsString(); - trackPage = trackRepo.findAllByNameLike(optionName, + + options.put("track_name", trackName); + trackPage = trackRepo.findAllByNameLike(trackName, PageRequest.of(humanBasedPage - 1, 15, Sort.by(Sort.Direction.ASC, "id"))); + break; case SUBCOMMAND_USER: + //noinspection ConstantConditions - User optionUser = event + long userId = event .getOption("user") - .getAsUser(); - trackPage = trackRepo.findAllByUploaderIdIs(optionUser.getIdLong(), + .getAsUser() + .getIdLong(); + + options.put("user_id", Long.toString(userId)); + trackPage = trackRepo.findAllByUploaderIdIs(userId, PageRequest.of(humanBasedPage - 1, 15, Sort.by(Sort.Direction.ASC, "id"))); + break; default: @@ -128,7 +141,7 @@ public TrackIndexCommand() { .setEphemeral(true) .and(event.getChannel() .sendMessage(eb.build()) - .setActionRow(computeButtons(trackPage, subcommand))); + .setActionRow(computeButtons(trackPage, options))); } @@ -157,45 +170,34 @@ public boolean hasListener() { } // TODO: cyclic prev/next (first/last page) - // TODO: json as component_id - private Component[] computeButtons(Page trackPage, String subcommand, Object... args) { + @SneakyThrows + private Component[] computeButtons(Page trackPage, Map options) { + ObjectMapper json = new ObjectMapper(); int zeroBasedPage = trackPage.getNumber(); - String joinedArgs = (args.length == 0) - ? "" - : Arrays - .stream(args) - .map(Object::toString) - .collect(Collectors.joining(":")); - - Button prevButton = Button - .secondary(String.format("%s:%s:%s", BUTTON_COMMAND, subcommand, - argsAppendPageNumber(joinedArgs, zeroBasedPage)), Emojis.PREVIOUS) + + // button + options.put("page", Integer.toString(zeroBasedPage - 1)); + Button prevButton = Button.secondary(json.writeValueAsString(options), Emojis.PREVIOUS) .withDisabled(!trackPage.hasPrevious()); - Button nextButton = Button - .secondary(String.format("%s:%s:%s", BUTTON_COMMAND, subcommand, - argsAppendPageNumber(joinedArgs, zeroBasedPage + 2)), Emojis.NEXT) + // button + options.put("page", Integer.toString(zeroBasedPage + 1)); + Button nextButton = Button.secondary(json.writeValueAsString(options), Emojis.NEXT) .withDisabled(!trackPage.hasNext()); - Button reloadButton = Button.secondary(String.format("%s:%s:%s", BUTTON_COMMAND, subcommand, - argsAppendPageNumber(joinedArgs, zeroBasedPage + 1)), Emojis.RELOAD); + // button + options.put("page", Integer.toString(zeroBasedPage)); + Button reloadButton = Button.secondary(json.writeValueAsString(options), Emojis.RELOAD); - Button closeButton = Button.secondary(String.format("%s:%s", BUTTON_COMMAND, "close"), Emojis.CLOSE); + Map closeCommand = new HashMap<>(); + closeCommand.put("command", "close"); + Button closeButton = Button.secondary(json.writeValueAsString(closeCommand), Emojis.CLOSE); return new Component[] { prevButton, nextButton, reloadButton, closeButton }; } - private static String argsAppendPageNumber(String joinedArgs, int page) { - - if(joinedArgs.isEmpty()) - return String.valueOf(page); - else - return joinedArgs + ":" + page; - - } - private static void replyEphemeralWith(String message, Interaction event) { event .reply(message) @@ -205,46 +207,62 @@ private static void replyEphemeralWith(String message, Interaction event) { public class ButtonClickListener extends ListenerAdapter { + @SneakyThrows @Override public void onButtonClick(@NotNull ButtonClickEvent event) { - // 0: command, 1: subcommand, 2+:args - ArgumentsParser parser = new ArgumentsParser(event.getComponentId(), ":"); + ObjectReader jsonParser = new ObjectMapper() + .readerForMapOf(String.class); + String rawJson = event.getComponentId(); + + Map commandOptions = jsonParser.readValue(rawJson); + String commandName = commandOptions.get("command"); - String command = parser.getArgumentString(0, ""); - if(!command.equalsIgnoreCase(BUTTON_COMMAND)) + if(commandName == null) { + replyEphemeralWith("Invalid button", event); + log.debug("Invalid button (commandName) -> " + rawJson); return; + } - List args = new LinkedList<>(); - Page trackPage; - int zeroBasedPage; + // TODO: GENERIC CLOSE "BUTTON COMMAND" (listener) + if(commandName.equalsIgnoreCase("close")) { + //noinspection ConstantConditions + event + .getMessage() + .delete() + .queue(); + return; + } - String subcommand = parser.getArgumentString(1, ""); - switch(subcommand) { + // TODO: AUTOMATIC "BUTTON COMMAND" FORWARDING + if(!commandName.equalsIgnoreCase(getName())) + return; - case "close": - //noinspection ConstantConditions - event - .getMessage() - .delete() - .queue(); - return; + String pageString = commandOptions.get("page"); + try { - case SUBCOMMAND_ALL: + if(Integer.parseInt(pageString) < 0) + throw new NullPointerException(); - zeroBasedPage = parser - .getArgumentInteger(2) - .map(i -> i - 1) - .orElse(0); + } catch(NumberFormatException | NullPointerException e) { + replyEphemeralWith("Invalid button", event); + log.debug("Invalid button (page) -> " + rawJson); + return; + } - if(zeroBasedPage < 1) { + Page trackPage; + int zeroBasedPage = Integer.parseInt(pageString); + String subcommand = commandOptions.get("subcommand"); - replyEphemeralWith("Invalid button", event); - return; + if(subcommand == null) { + replyEphemeralWith("Invalid button", event); + log.debug("Invalid button (subcommand) -> " + rawJson); + return; + } - } + switch(subcommand) { - args.add(zeroBasedPage); + case SUBCOMMAND_ALL: trackPage = trackRepo.findAll(PageRequest.of(zeroBasedPage, 15, Sort.by(Sort.Direction.ASC, "id"))); @@ -252,62 +270,32 @@ public void onButtonClick(@NotNull ButtonClickEvent event) { case SUBCOMMAND_NAME: - Optional optStr = parser.getArgumentString(2); - if(!optStr.isPresent()) { - - replyEphemeralWith("Invalid button", event); - return; - - } - - String trackSubname = optStr.get(); - zeroBasedPage = parser - .getArgumentInteger(3) - .map(i -> i - 1) - .orElse(0); - - if(zeroBasedPage < 1) { - + String trackName = commandOptions.get("track_name"); + if(trackName == null) { replyEphemeralWith("Invalid button", event); + log.debug("Invalid button (trackName) -> " + rawJson); return; - } - args.add(trackSubname); - args.add(zeroBasedPage); - - trackPage = trackRepo.findAllByNameLike(trackSubname, + trackPage = trackRepo.findAllByNameLike(trackName, PageRequest.of(zeroBasedPage, 15, Sort.by(Sort.Direction.ASC, "id"))); break; case SUBCOMMAND_USER: - Optional optLong = parser.getArgumentLong(2); - if(!optLong.isPresent()) { + long userId; + try { - replyEphemeralWith("Invalid button", event); - return; - - } - - long uploaderId = optLong.get(); - zeroBasedPage = parser - .getArgumentInteger(3) - .map(i -> i - 1) - .orElse(0); - - if(zeroBasedPage < 1) { + userId = Long.parseLong(commandOptions.get("user_id")); + } catch(NumberFormatException | NullPointerException e) { replyEphemeralWith("Invalid button", event); + log.debug("Invalid button (userId) -> " + rawJson); return; - } - args.add(uploaderId); - args.add(zeroBasedPage); - - trackPage = trackRepo.findAllByUploaderIdIs(uploaderId, + trackPage = trackRepo.findAllByUploaderIdIs(userId, PageRequest.of(zeroBasedPage, 15, Sort.by(Sort.Direction.ASC, "id"))); break; @@ -334,7 +322,7 @@ public void onButtonClick(@NotNull ButtonClickEvent event) { .and(event .getChannel() .sendMessage(eb.build()) - .setActionRow(computeButtons(trackPage, subcommand, args.toArray()))) + .setActionRow(computeButtons(trackPage, commandOptions))) .queue(); } From c54b5c7973461a2bd115e7e548232cda2b682a6f Mon Sep 17 00:00:00 2001 From: Emanuele Scaccia Date: Thu, 3 Feb 2022 03:59:36 +0100 Subject: [PATCH 25/46] feat: Added filter notes on title and footer in TrackIndex --- .../commands/track/TrackIndexCommand.java | 46 ++++++++++++++++--- 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java b/src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java index b3f0b4b..8f1390e 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java @@ -27,7 +27,9 @@ import ovh.excale.vgreeter.utilities.Emojis; import java.awt.*; -import java.util.*; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; import java.util.stream.Collectors; @Log4j2 @@ -81,6 +83,8 @@ public TrackIndexCommand() { Page trackPage; Map options = new HashMap<>(); + String titleAppendix = null; + String footerAppendix = null; String subcommand = event.getSubcommandName(); options.put("command", getName()); options.put("subcommand", subcommand); @@ -97,11 +101,15 @@ public TrackIndexCommand() { case SUBCOMMAND_NAME: + //noinspection ConstantConditions String trackName = event .getOption("name") .getAsString(); + titleAppendix = "Name"; + footerAppendix = "Filter: \"" + trackName + "\""; + options.put("track_name", trackName); trackPage = trackRepo.findAllByNameLike(trackName, PageRequest.of(humanBasedPage - 1, 15, Sort.by(Sort.Direction.ASC, "id"))); @@ -116,6 +124,14 @@ public TrackIndexCommand() { .getAsUser() .getIdLong(); + String userTag = event.getJDA() + .retrieveUserById(userId) + .complete() + .getAsTag(); + + titleAppendix = "User"; + footerAppendix = "Filter: " + userTag; + options.put("user_id", Long.toString(userId)); trackPage = trackRepo.findAllByUploaderIdIs(userId, PageRequest.of(humanBasedPage - 1, 15, Sort.by(Sort.Direction.ASC, "id"))); @@ -134,7 +150,7 @@ public TrackIndexCommand() { .reply("Empty page") .setEphemeral(true); - EmbedBuilder eb = computeEmbed(trackPage); + EmbedBuilder eb = computeEmbed(trackPage, titleAppendix, footerAppendix); // TODO: CHECK PERMS AND MESSAGECHANNEL return event.reply("Here's your track index!") @@ -155,11 +171,15 @@ public boolean hasListener() { return buttonListener; } - private @NotNull EmbedBuilder computeEmbed(Page trackPage) { + private @NotNull EmbedBuilder computeEmbed(Page trackPage, @Nullable String titleAppendix, @Nullable String footerAppendix) { + + String pageCount = "Page " + (trackPage.getNumber() + 1) + "/" + trackPage.getTotalPages(); + String footer = footerAppendix == null ? pageCount : pageCount + " | " + footerAppendix; + String title = titleAppendix == null ? "Track Index" : "Track Index (" + titleAppendix + ")"; return new EmbedBuilder() - .setTitle("Track Index") - .setFooter("Page " + (trackPage.getNumber() + 1) + "/" + trackPage.getTotalPages()) + .setTitle(title) + .setFooter(footer) .setColor(Color.BLUE) .setDescription(trackPage .getContent() @@ -260,6 +280,9 @@ public void onButtonClick(@NotNull ButtonClickEvent event) { return; } + String titleAppendix = null; + String footerAppendix = null; + switch(subcommand) { case SUBCOMMAND_ALL: @@ -277,6 +300,9 @@ public void onButtonClick(@NotNull ButtonClickEvent event) { return; } + titleAppendix = "Name"; + footerAppendix = "Filter: \"" + trackName + "\""; + trackPage = trackRepo.findAllByNameLike(trackName, PageRequest.of(zeroBasedPage, 15, Sort.by(Sort.Direction.ASC, "id"))); @@ -295,6 +321,14 @@ public void onButtonClick(@NotNull ButtonClickEvent event) { return; } + String userTag = event.getJDA() + .retrieveUserById(userId) + .complete() + .getAsTag(); + + titleAppendix = "User"; + footerAppendix = "Filter: " + userTag; + trackPage = trackRepo.findAllByUploaderIdIs(userId, PageRequest.of(zeroBasedPage, 15, Sort.by(Sort.Direction.ASC, "id"))); @@ -313,7 +347,7 @@ public void onButtonClick(@NotNull ButtonClickEvent event) { } - EmbedBuilder eb = computeEmbed(trackPage); + EmbedBuilder eb = computeEmbed(trackPage, titleAppendix, footerAppendix); //noinspection ConstantConditions event From f580cb9945b0ad137a584ebefe4112d9bfc8b922 Mon Sep 17 00:00:00 2001 From: Emanuele Scaccia Date: Thu, 3 Feb 2022 04:06:54 +0100 Subject: [PATCH 26/46] feat: Added cyclic TrackIndex pages (from first to last and vice versa) --- .../vgreeter/commands/track/TrackIndexCommand.java | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java b/src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java index 8f1390e..0524acb 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java @@ -189,7 +189,6 @@ public boolean hasListener() { } - // TODO: cyclic prev/next (first/last page) @SneakyThrows private Component[] computeButtons(Page trackPage, Map options) { @@ -197,14 +196,12 @@ private Component[] computeButtons(Page trackPage, Map button - options.put("page", Integer.toString(zeroBasedPage - 1)); - Button prevButton = Button.secondary(json.writeValueAsString(options), Emojis.PREVIOUS) - .withDisabled(!trackPage.hasPrevious()); + options.put("page", Integer.toString(trackPage.hasPrevious() ? zeroBasedPage - 1 : trackPage.getTotalPages() - 1)); + Button prevButton = Button.secondary(json.writeValueAsString(options), Emojis.PREVIOUS); // button - options.put("page", Integer.toString(zeroBasedPage + 1)); - Button nextButton = Button.secondary(json.writeValueAsString(options), Emojis.NEXT) - .withDisabled(!trackPage.hasNext()); + options.put("page", Integer.toString(!trackPage.isLast() ? zeroBasedPage + 1 : 0)); + Button nextButton = Button.secondary(json.writeValueAsString(options), Emojis.NEXT); // button options.put("page", Integer.toString(zeroBasedPage)); From c8fee0c209df857c01c71320aee5de6660106165 Mon Sep 17 00:00:00 2001 From: Emanuele Scaccia Date: Thu, 3 Feb 2022 04:08:32 +0100 Subject: [PATCH 27/46] Version upgrade (minor) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a2e3e7b..52add2a 100644 --- a/pom.xml +++ b/pom.xml @@ -13,7 +13,7 @@ ovh.excale vgreeter - 2.5.1 + 2.6.0 VGreeter Let the bot greet your friends when they join vocal chat on Discord! From 3b904a2427ee644d5e6022e47f0d22d52e78dfd3 Mon Sep 17 00:00:00 2001 From: Emanuele Scaccia Date: Thu, 3 Feb 2022 14:37:17 +0100 Subject: [PATCH 28/46] fix: Fixed TrackIndex name filter always returning blank page --- .../vgreeter/commands/track/TrackIndexCommand.java | 13 +++++++++++-- .../vgreeter/repositories/TrackRepository.java | 4 +++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java b/src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java index 0524acb..1100707 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java @@ -107,11 +107,12 @@ public TrackIndexCommand() { .getOption("name") .getAsString(); + String formattedTrackName = "%" + trackName.replaceAll("\\s+", "%") + "%"; titleAppendix = "Name"; footerAppendix = "Filter: \"" + trackName + "\""; options.put("track_name", trackName); - trackPage = trackRepo.findAllByNameLike(trackName, + trackPage = trackRepo.findAllByNameQuery(formattedTrackName, PageRequest.of(humanBasedPage - 1, 15, Sort.by(Sort.Direction.ASC, "id"))); break; @@ -195,20 +196,26 @@ private Component[] computeButtons(Page trackPage, Map button options.put("page", Integer.toString(trackPage.hasPrevious() ? zeroBasedPage - 1 : trackPage.getTotalPages() - 1)); + options.put("emoji", Emojis.PREVIOUS.getName()); Button prevButton = Button.secondary(json.writeValueAsString(options), Emojis.PREVIOUS); // button options.put("page", Integer.toString(!trackPage.isLast() ? zeroBasedPage + 1 : 0)); + options.put("emoji", Emojis.NEXT.getName()); Button nextButton = Button.secondary(json.writeValueAsString(options), Emojis.NEXT); // button options.put("page", Integer.toString(zeroBasedPage)); + options.put("emoji", Emojis.RELOAD.getName()); Button reloadButton = Button.secondary(json.writeValueAsString(options), Emojis.RELOAD); Map closeCommand = new HashMap<>(); closeCommand.put("command", "close"); + closeCommand.put("emoji", Emojis.CLOSE.getName()); Button closeButton = Button.secondary(json.writeValueAsString(closeCommand), Emojis.CLOSE); return new Component[] { prevButton, nextButton, reloadButton, closeButton }; @@ -297,10 +304,12 @@ public void onButtonClick(@NotNull ButtonClickEvent event) { return; } + + String formattedTrackName = "%" + trackName.replaceAll("\\s+", "%") + "%"; titleAppendix = "Name"; footerAppendix = "Filter: \"" + trackName + "\""; - trackPage = trackRepo.findAllByNameLike(trackName, + trackPage = trackRepo.findAllByNameQuery(formattedTrackName, PageRequest.of(zeroBasedPage, 15, Sort.by(Sort.Direction.ASC, "id"))); break; diff --git a/src/main/java/ovh/excale/vgreeter/repositories/TrackRepository.java b/src/main/java/ovh/excale/vgreeter/repositories/TrackRepository.java index f5e3e71..55a0b3a 100644 --- a/src/main/java/ovh/excale/vgreeter/repositories/TrackRepository.java +++ b/src/main/java/ovh/excale/vgreeter/repositories/TrackRepository.java @@ -2,6 +2,7 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.stereotype.Repository; import ovh.excale.vgreeter.models.TrackModel; @@ -12,7 +13,8 @@ public interface TrackRepository extends PagingAndSortingRepository findAllByNameLike(String name, Pageable pageable); + @Query("select t from TrackModel t where lower(t.name) like lower(?1)") + Page findAllByNameQuery(String name, Pageable pageable); Page findAllByUploaderIdIs(long userId, Pageable pageable); From 7f28b5d98666947785c05c0dd20cf4165ed8e26b Mon Sep 17 00:00:00 2001 From: Emanuele Scaccia Date: Thu, 3 Feb 2022 23:33:34 +0100 Subject: [PATCH 29/46] fix: Upgraded PostgreSQL version for security reasons --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 52add2a..ac5275c 100644 --- a/pom.xml +++ b/pom.xml @@ -83,7 +83,7 @@ org.postgresql postgresql - 42.2.22 + 42.2.25 From 281b78a9a3a56468ac2610be9627bb4fcf608a35 Mon Sep 17 00:00:00 2001 From: Emanuele Scaccia Date: Fri, 4 Feb 2022 02:08:34 +0100 Subject: [PATCH 30/46] feat: Merged AbstractSlashCommand and AbstractMessageCommand into one superclass AbstractCommand, with possibility to expand to other Event types (i.e. buttons, reactions) --- .../commands/core/AbstractCommand.java | 38 +++++ .../commands/core/AbstractMessageCommand.java | 33 ++-- .../commands/core/AbstractSlashCommand.java | 29 ++-- .../commands/core/CommandRegister.java | 142 +++++++----------- 4 files changed, 116 insertions(+), 126 deletions(-) create mode 100644 src/main/java/ovh/excale/vgreeter/commands/core/AbstractCommand.java diff --git a/src/main/java/ovh/excale/vgreeter/commands/core/AbstractCommand.java b/src/main/java/ovh/excale/vgreeter/commands/core/AbstractCommand.java new file mode 100644 index 0000000..3244b95 --- /dev/null +++ b/src/main/java/ovh/excale/vgreeter/commands/core/AbstractCommand.java @@ -0,0 +1,38 @@ +package ovh.excale.vgreeter.commands.core; + +import lombok.Getter; +import net.dv8tion.jda.api.events.Event; +import net.dv8tion.jda.api.events.GenericEvent; +import net.dv8tion.jda.api.hooks.EventListener; +import net.dv8tion.jda.api.requests.RestAction; +import org.jetbrains.annotations.Nullable; + +@Getter +public abstract class AbstractCommand { + + protected final String name; + protected final String description; + + private final Class typeClass; + + protected AbstractCommand(String name, String description, Class typeClass) { + this.name = name; + this.description = description; + this.typeClass = typeClass; + } + + public abstract RestAction execute(EventType event); + + public abstract boolean accepts(GenericEvent eventType); + + // TODO: implement method in individual commands + public /*abstract*/ boolean bypassesMaintenance() { return true; } + + public boolean hasListener() { + return false; + } + + public @Nullable EventListener getListener() { + return null; + } +} diff --git a/src/main/java/ovh/excale/vgreeter/commands/core/AbstractMessageCommand.java b/src/main/java/ovh/excale/vgreeter/commands/core/AbstractMessageCommand.java index 1b3baa2..8a1ad52 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/core/AbstractMessageCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/core/AbstractMessageCommand.java @@ -1,35 +1,36 @@ package ovh.excale.vgreeter.commands.core; -import lombok.Getter; +import net.dv8tion.jda.api.events.GenericEvent; import net.dv8tion.jda.api.events.message.priv.PrivateMessageReceivedEvent; -import net.dv8tion.jda.api.hooks.EventListener; import net.dv8tion.jda.api.requests.RestAction; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public abstract class AbstractMessageCommand { +import java.util.Locale; - public static final String PREFIX = "vg:"; - - @Getter - private final String name; +public abstract class AbstractMessageCommand extends AbstractCommand { - @Getter - private final String description; + public static final String PREFIX = "vg:"; protected AbstractMessageCommand(String name, String description) { - this.name = name; - this.description = description; + super(name, description, PrivateMessageReceivedEvent.class); } + @Override public abstract @Nullable RestAction execute(@NotNull PrivateMessageReceivedEvent event); - public boolean hasListener() { - return false; - } + public boolean accepts(GenericEvent event) { + + if(!(event instanceof PrivateMessageReceivedEvent)) + return false; + + String msgContent = ((PrivateMessageReceivedEvent) event) + .getMessage() + .getContentRaw() + .toLowerCase(Locale.ROOT); + + return msgContent.startsWith(PREFIX + name); - public @Nullable EventListener getListener() { - return null; } } diff --git a/src/main/java/ovh/excale/vgreeter/commands/core/AbstractSlashCommand.java b/src/main/java/ovh/excale/vgreeter/commands/core/AbstractSlashCommand.java index 06651e7..f4e0a7c 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/core/AbstractSlashCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/core/AbstractSlashCommand.java @@ -1,30 +1,21 @@ package ovh.excale.vgreeter.commands.core; import lombok.Getter; +import net.dv8tion.jda.api.events.GenericEvent; import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; -import net.dv8tion.jda.api.hooks.EventListener; import net.dv8tion.jda.api.interactions.commands.build.CommandData; import net.dv8tion.jda.api.requests.RestAction; -import net.dv8tion.jda.api.requests.restaction.interactions.ReplyAction; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import ovh.excale.vgreeter.utilities.CommandBuilder; // TODO: MERGE AbstractSlashCommand AND AbstractMessageCommand WITH A PARENT AbstractCommand CLASS -public abstract class AbstractSlashCommand { - - @Getter - private final String name; - - @Getter - private final String description; +public abstract class AbstractSlashCommand extends AbstractCommand { @Getter private final CommandBuilder builder; protected AbstractSlashCommand(String name, String description) { - this.name = name; - this.description = description; + super(name, description, SlashCommandEvent.class); builder = CommandBuilder .create(name) @@ -32,18 +23,16 @@ protected AbstractSlashCommand(String name, String description) { } + @Override public abstract @NotNull RestAction execute(SlashCommandEvent event); - public CommandData getData() { - return builder.build(); - } - - public boolean hasListener() { - return false; + @Override + public boolean accepts(GenericEvent event) { + return event instanceof SlashCommandEvent && name.equals(((SlashCommandEvent) event).getName()); } - public @Nullable EventListener getListener() { - return null; + public CommandData getData() { + return builder.build(); } } diff --git a/src/main/java/ovh/excale/vgreeter/commands/core/CommandRegister.java b/src/main/java/ovh/excale/vgreeter/commands/core/CommandRegister.java index 361ccc3..026e262 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/core/CommandRegister.java +++ b/src/main/java/ovh/excale/vgreeter/commands/core/CommandRegister.java @@ -1,68 +1,64 @@ package ovh.excale.vgreeter.commands.core; -import net.dv8tion.jda.api.entities.Message; +import com.sun.javafx.sg.prism.NGExternalNode; +import lombok.SneakyThrows; import net.dv8tion.jda.api.events.GenericEvent; import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; -import net.dv8tion.jda.api.events.message.priv.PrivateMessageReceivedEvent; -import net.dv8tion.jda.api.exceptions.ErrorResponseException; import net.dv8tion.jda.api.hooks.EventListener; import net.dv8tion.jda.api.interactions.commands.build.CommandData; import net.dv8tion.jda.api.requests.RestAction; -import net.dv8tion.jda.api.requests.restaction.interactions.ReplyAction; import org.jetbrains.annotations.NotNull; import org.springframework.stereotype.Service; -import ovh.excale.vgreeter.VGreeterApplication; +import java.lang.reflect.Method; import java.util.*; +import java.util.stream.Stream; @Service public class CommandRegister { - private final Map slashCommands; - private final Map messageCommands; - private final RegisterListener registerListener; + private final ListenerRegister listenerRegister; + private final Map, Set>> masterRecord; private CommandRegister() { - slashCommands = new HashMap<>(); - messageCommands = new HashMap<>(); - registerListener = new RegisterListener(); + listenerRegister = new ListenerRegister(); + masterRecord = new HashMap<>(); } - public CommandRegister register(AbstractSlashCommand command) { + public > CommandRegister register(Command command) { - slashCommands.put(command.getName(), command); - if(command.hasListener()) - registerListener.register(command.getListener()); - - return this; - } + Class commandType = command.getTypeClass(); + //noinspection unchecked + Set commandSet = (Set) masterRecord.computeIfAbsent(commandType, k -> new HashSet<>()); - public CommandRegister register(AbstractMessageCommand command) { - - messageCommands.put(command.getName(), command); + commandSet.add(command); if(command.hasListener()) - registerListener.register(command.getListener()); + listenerRegister.register(command.getListener()); return this; + } public CommandData[] getSlashCommandsData() { - return slashCommands - .values() - .stream() + + //noinspection unchecked + return Optional.ofNullable((Set) masterRecord.get(SlashCommandEvent.class)) + .map(Collection::stream) + .orElseGet(Stream::empty) .map(AbstractSlashCommand::getData) .toArray(CommandData[]::new); + } - public RegisterListener getListener() { - return registerListener; + public ListenerRegister getListener() { + return listenerRegister; } - private class RegisterListener implements EventListener { + private class ListenerRegister implements EventListener { public Set commandListeners; - protected RegisterListener() { + protected ListenerRegister() { commandListeners = new HashSet<>(); } @@ -70,75 +66,41 @@ protected void register(EventListener listener) { commandListeners.add(listener); } + @SneakyThrows @Override - public void onEvent(@NotNull GenericEvent genericEvent) { - - if(genericEvent instanceof SlashCommandEvent) - - onSlashCommand((SlashCommandEvent) genericEvent); - - else if(genericEvent instanceof PrivateMessageReceivedEvent) { - - PrivateMessageReceivedEvent messageEvent = (PrivateMessageReceivedEvent) genericEvent; - String message = messageEvent - .getMessage() - .getContentRaw() - .toLowerCase(Locale.ROOT); - - if(message.startsWith(AbstractMessageCommand.PREFIX)) - onMessageCommand(messageEvent); + public void onEvent(@NotNull GenericEvent event) { + + AbstractCommand abstractCommand = masterRecord.entrySet() + .stream() + .filter(entry -> entry.getKey() + .isInstance(event)) + .map(Map.Entry::getValue) + .flatMap(Collection::stream) + .filter(command -> command.accepts(event)) + .findFirst() + .orElse(null); + + if(abstractCommand != null) { + + //noinspection OptionalGetWithoutIsPresent + Method execMethod = Arrays.stream(abstractCommand.getClass() + .getDeclaredMethods()) + .filter(method -> method.getName() + .equals("execute")) + .findFirst() + .get(); + + Optional.ofNullable(execMethod.invoke(abstractCommand, event)) + .map(result -> ((RestAction) result)) + .ifPresent(RestAction::queue); } for(EventListener commandListener : commandListeners) - commandListener.onEvent(genericEvent); + commandListener.onEvent(event); } - private void onMessageCommand(PrivateMessageReceivedEvent event) { - - Message message = event.getMessage(); - String messageContent = message - .getContentRaw() - .toLowerCase(Locale.ROOT) - .replaceFirst(AbstractMessageCommand.PREFIX, ""); - String[] split = messageContent.split(" "); - - AbstractMessageCommand command = messageCommands.get(split[0]); - - Optional - .ofNullable(command) - .map(c -> c.execute(event)) - .ifPresent(RestAction::queue); - - } - - private void onSlashCommand(SlashCommandEvent event) { - - if(VGreeterApplication.isInMaintenance()) { - event - .reply("The bot is currently under maintenance") - .setEphemeral(true) - .queue(); - return; - } - - AbstractSlashCommand command = slashCommands.get(event.getName()); - RestAction action; - - if(command == null) - action = event - .reply("No such command") - .setEphemeral(true); - else - action = command.execute(event); - - try { - action.queue(); - } catch(ErrorResponseException ignored) { - } - } - } } From 0187a3fb454a79adbe2d3dd151f1face69f1897b Mon Sep 17 00:00:00 2001 From: Emanuele Scaccia Date: Fri, 4 Feb 2022 02:10:44 +0100 Subject: [PATCH 31/46] other: added TODO --- .../ovh/excale/vgreeter/commands/track/TrackIndexCommand.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java b/src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java index 1100707..befd97d 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java @@ -229,6 +229,7 @@ private static void replyEphemeralWith(String message, Interaction event) { .queue(); } + // TODO: turn this listener into a command (TrackIndexButtonCommand) public class ButtonClickListener extends ListenerAdapter { @SneakyThrows From ccaaeea1667b97cdb66e4f80ed92cff7482ae1cd Mon Sep 17 00:00:00 2001 From: Emanuele Scaccia Date: Fri, 4 Feb 2022 12:19:33 +0100 Subject: [PATCH 32/46] refactor: moved commands into each respective command type package --- .../commands/{ => message}/RestartCommand.java | 2 +- .../{track => message}/TrackUploadCommand.java | 2 +- .../commands/{ => slash}/AltnameCommand.java | 2 +- .../commands/{track => slash}/PlaytestCommand.java | 2 +- .../commands/{ => slash}/ProbabilityCommand.java | 2 +- .../{track => slash}/TrackDownloadCommand.java | 2 +- .../{track => slash}/TrackIndexCommand.java | 2 +- .../TrackNameCommand.java} | 6 +++--- .../{track => slash}/TrackRemoveCommand.java | 2 +- .../commands/{ => slash}/UploadHelpCommand.java | 2 +- .../excale/vgreeter/services/DiscordService.java | 13 +++++++------ 11 files changed, 19 insertions(+), 18 deletions(-) rename src/main/java/ovh/excale/vgreeter/commands/{ => message}/RestartCommand.java (97%) rename src/main/java/ovh/excale/vgreeter/commands/{track => message}/TrackUploadCommand.java (98%) rename src/main/java/ovh/excale/vgreeter/commands/{ => slash}/AltnameCommand.java (98%) rename src/main/java/ovh/excale/vgreeter/commands/{track => slash}/PlaytestCommand.java (98%) rename src/main/java/ovh/excale/vgreeter/commands/{ => slash}/ProbabilityCommand.java (98%) rename src/main/java/ovh/excale/vgreeter/commands/{track => slash}/TrackDownloadCommand.java (97%) rename src/main/java/ovh/excale/vgreeter/commands/{track => slash}/TrackIndexCommand.java (99%) rename src/main/java/ovh/excale/vgreeter/commands/{track/TracknameCommand.java => slash/TrackNameCommand.java} (94%) rename src/main/java/ovh/excale/vgreeter/commands/{track => slash}/TrackRemoveCommand.java (97%) rename src/main/java/ovh/excale/vgreeter/commands/{ => slash}/UploadHelpCommand.java (96%) diff --git a/src/main/java/ovh/excale/vgreeter/commands/RestartCommand.java b/src/main/java/ovh/excale/vgreeter/commands/message/RestartCommand.java similarity index 97% rename from src/main/java/ovh/excale/vgreeter/commands/RestartCommand.java rename to src/main/java/ovh/excale/vgreeter/commands/message/RestartCommand.java index e026f3c..938dc0c 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/RestartCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/message/RestartCommand.java @@ -1,4 +1,4 @@ -package ovh.excale.vgreeter.commands; +package ovh.excale.vgreeter.commands.message; import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.entities.Message; diff --git a/src/main/java/ovh/excale/vgreeter/commands/track/TrackUploadCommand.java b/src/main/java/ovh/excale/vgreeter/commands/message/TrackUploadCommand.java similarity index 98% rename from src/main/java/ovh/excale/vgreeter/commands/track/TrackUploadCommand.java rename to src/main/java/ovh/excale/vgreeter/commands/message/TrackUploadCommand.java index 7dffb44..84df117 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/track/TrackUploadCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/message/TrackUploadCommand.java @@ -1,4 +1,4 @@ -package ovh.excale.vgreeter.commands.track; +package ovh.excale.vgreeter.commands.message; import lombok.extern.log4j.Log4j2; import net.dv8tion.jda.api.entities.Message; diff --git a/src/main/java/ovh/excale/vgreeter/commands/AltnameCommand.java b/src/main/java/ovh/excale/vgreeter/commands/slash/AltnameCommand.java similarity index 98% rename from src/main/java/ovh/excale/vgreeter/commands/AltnameCommand.java rename to src/main/java/ovh/excale/vgreeter/commands/slash/AltnameCommand.java index a661b8c..a335fab 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/AltnameCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/slash/AltnameCommand.java @@ -1,4 +1,4 @@ -package ovh.excale.vgreeter.commands; +package ovh.excale.vgreeter.commands.slash; import net.dv8tion.jda.api.entities.User; import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; diff --git a/src/main/java/ovh/excale/vgreeter/commands/track/PlaytestCommand.java b/src/main/java/ovh/excale/vgreeter/commands/slash/PlaytestCommand.java similarity index 98% rename from src/main/java/ovh/excale/vgreeter/commands/track/PlaytestCommand.java rename to src/main/java/ovh/excale/vgreeter/commands/slash/PlaytestCommand.java index ff22ad1..b5c446c 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/track/PlaytestCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/slash/PlaytestCommand.java @@ -1,4 +1,4 @@ -package ovh.excale.vgreeter.commands.track; +package ovh.excale.vgreeter.commands.slash; import lombok.extern.log4j.Log4j2; import net.dv8tion.jda.api.entities.Guild; diff --git a/src/main/java/ovh/excale/vgreeter/commands/ProbabilityCommand.java b/src/main/java/ovh/excale/vgreeter/commands/slash/ProbabilityCommand.java similarity index 98% rename from src/main/java/ovh/excale/vgreeter/commands/ProbabilityCommand.java rename to src/main/java/ovh/excale/vgreeter/commands/slash/ProbabilityCommand.java index 7c85957..c65dae7 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/ProbabilityCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/slash/ProbabilityCommand.java @@ -1,4 +1,4 @@ -package ovh.excale.vgreeter.commands; +package ovh.excale.vgreeter.commands.slash; import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.entities.Guild; diff --git a/src/main/java/ovh/excale/vgreeter/commands/track/TrackDownloadCommand.java b/src/main/java/ovh/excale/vgreeter/commands/slash/TrackDownloadCommand.java similarity index 97% rename from src/main/java/ovh/excale/vgreeter/commands/track/TrackDownloadCommand.java rename to src/main/java/ovh/excale/vgreeter/commands/slash/TrackDownloadCommand.java index e6bd48b..05c5029 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/track/TrackDownloadCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/slash/TrackDownloadCommand.java @@ -1,4 +1,4 @@ -package ovh.excale.vgreeter.commands.track; +package ovh.excale.vgreeter.commands.slash; import net.dv8tion.jda.api.MessageBuilder; import net.dv8tion.jda.api.entities.Guild; diff --git a/src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java b/src/main/java/ovh/excale/vgreeter/commands/slash/TrackIndexCommand.java similarity index 99% rename from src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java rename to src/main/java/ovh/excale/vgreeter/commands/slash/TrackIndexCommand.java index befd97d..ad9b41c 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/track/TrackIndexCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/slash/TrackIndexCommand.java @@ -1,4 +1,4 @@ -package ovh.excale.vgreeter.commands.track; +package ovh.excale.vgreeter.commands.slash; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectReader; diff --git a/src/main/java/ovh/excale/vgreeter/commands/track/TracknameCommand.java b/src/main/java/ovh/excale/vgreeter/commands/slash/TrackNameCommand.java similarity index 94% rename from src/main/java/ovh/excale/vgreeter/commands/track/TracknameCommand.java rename to src/main/java/ovh/excale/vgreeter/commands/slash/TrackNameCommand.java index a045ae7..94a85ce 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/track/TracknameCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/slash/TrackNameCommand.java @@ -1,4 +1,4 @@ -package ovh.excale.vgreeter.commands.track; +package ovh.excale.vgreeter.commands.slash; import net.dv8tion.jda.api.entities.User; import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; @@ -13,13 +13,13 @@ import java.util.Optional; import java.util.regex.Pattern; -public class TracknameCommand extends AbstractSlashCommand { +public class TrackNameCommand extends AbstractSlashCommand { private static final Pattern TRACKNAME_PATTERN = Pattern.compile("[\\w\\d-_]+"); private final TrackRepository trackRepo; - public TracknameCommand() { + public TrackNameCommand() { super("trackname", "Edit the name of a track"); this.getBuilder() diff --git a/src/main/java/ovh/excale/vgreeter/commands/track/TrackRemoveCommand.java b/src/main/java/ovh/excale/vgreeter/commands/slash/TrackRemoveCommand.java similarity index 97% rename from src/main/java/ovh/excale/vgreeter/commands/track/TrackRemoveCommand.java rename to src/main/java/ovh/excale/vgreeter/commands/slash/TrackRemoveCommand.java index 4d805b7..5209ad3 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/track/TrackRemoveCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/slash/TrackRemoveCommand.java @@ -1,4 +1,4 @@ -package ovh.excale.vgreeter.commands.track; +package ovh.excale.vgreeter.commands.slash; import net.dv8tion.jda.api.entities.User; import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; diff --git a/src/main/java/ovh/excale/vgreeter/commands/UploadHelpCommand.java b/src/main/java/ovh/excale/vgreeter/commands/slash/UploadHelpCommand.java similarity index 96% rename from src/main/java/ovh/excale/vgreeter/commands/UploadHelpCommand.java rename to src/main/java/ovh/excale/vgreeter/commands/slash/UploadHelpCommand.java index 1a43bd1..c125ebf 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/UploadHelpCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/slash/UploadHelpCommand.java @@ -1,4 +1,4 @@ -package ovh.excale.vgreeter.commands; +package ovh.excale.vgreeter.commands.slash; import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; import net.dv8tion.jda.api.requests.restaction.interactions.ReplyAction; diff --git a/src/main/java/ovh/excale/vgreeter/services/DiscordService.java b/src/main/java/ovh/excale/vgreeter/services/DiscordService.java index a64b129..a37c4df 100644 --- a/src/main/java/ovh/excale/vgreeter/services/DiscordService.java +++ b/src/main/java/ovh/excale/vgreeter/services/DiscordService.java @@ -11,12 +11,13 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Service; -import ovh.excale.vgreeter.commands.AltnameCommand; -import ovh.excale.vgreeter.commands.ProbabilityCommand; -import ovh.excale.vgreeter.commands.RestartCommand; -import ovh.excale.vgreeter.commands.UploadHelpCommand; +import ovh.excale.vgreeter.commands.slash.AltnameCommand; +import ovh.excale.vgreeter.commands.slash.ProbabilityCommand; +import ovh.excale.vgreeter.commands.message.RestartCommand; +import ovh.excale.vgreeter.commands.slash.UploadHelpCommand; import ovh.excale.vgreeter.commands.core.CommandRegister; -import ovh.excale.vgreeter.commands.track.*; +import ovh.excale.vgreeter.commands.message.TrackUploadCommand; +import ovh.excale.vgreeter.commands.slash.*; import javax.security.auth.login.LoginException; import java.util.Collections; @@ -56,7 +57,7 @@ public DiscordService(VoiceChannelHandler eventHandler, CommandRegister commands .register(new AltnameCommand()) .register(new UploadHelpCommand()) .register(new PlaytestCommand()) - .register(new TracknameCommand()) + .register(new TrackNameCommand()) .register(new TrackIndexCommand()) .register(new TrackRemoveCommand()) .register(new TrackDownloadCommand()) From 01711d4106ea7e62fd68685d15930718efc5f381 Mon Sep 17 00:00:00 2001 From: Emanuele Scaccia Date: Fri, 4 Feb 2022 14:07:40 +0100 Subject: [PATCH 33/46] refactor: Moved command-related classes to `command.core` package refactor: Moved track-related classes to `track` package --- .../vgreeter/commands/core/AbstractSlashCommand.java | 1 - .../{utilities => commands/core}/CommandBuilder.java | 2 +- .../excale/vgreeter/commands/slash/PlaytestCommand.java | 2 +- .../java/ovh/excale/vgreeter/services/TrackService.java | 7 +++---- .../ovh/excale/vgreeter/services/VoiceChannelHandler.java | 2 +- .../excale/vgreeter/{utilities => track}/TrackPlayer.java | 2 +- 6 files changed, 7 insertions(+), 9 deletions(-) rename src/main/java/ovh/excale/vgreeter/{utilities => commands/core}/CommandBuilder.java (98%) rename src/main/java/ovh/excale/vgreeter/{utilities => track}/TrackPlayer.java (97%) diff --git a/src/main/java/ovh/excale/vgreeter/commands/core/AbstractSlashCommand.java b/src/main/java/ovh/excale/vgreeter/commands/core/AbstractSlashCommand.java index f4e0a7c..773a482 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/core/AbstractSlashCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/core/AbstractSlashCommand.java @@ -6,7 +6,6 @@ import net.dv8tion.jda.api.interactions.commands.build.CommandData; import net.dv8tion.jda.api.requests.RestAction; import org.jetbrains.annotations.NotNull; -import ovh.excale.vgreeter.utilities.CommandBuilder; // TODO: MERGE AbstractSlashCommand AND AbstractMessageCommand WITH A PARENT AbstractCommand CLASS public abstract class AbstractSlashCommand extends AbstractCommand { diff --git a/src/main/java/ovh/excale/vgreeter/utilities/CommandBuilder.java b/src/main/java/ovh/excale/vgreeter/commands/core/CommandBuilder.java similarity index 98% rename from src/main/java/ovh/excale/vgreeter/utilities/CommandBuilder.java rename to src/main/java/ovh/excale/vgreeter/commands/core/CommandBuilder.java index 7933847..fc6f6d6 100644 --- a/src/main/java/ovh/excale/vgreeter/utilities/CommandBuilder.java +++ b/src/main/java/ovh/excale/vgreeter/commands/core/CommandBuilder.java @@ -1,4 +1,4 @@ -package ovh.excale.vgreeter.utilities; +package ovh.excale.vgreeter.commands.core; import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.build.CommandData; diff --git a/src/main/java/ovh/excale/vgreeter/commands/slash/PlaytestCommand.java b/src/main/java/ovh/excale/vgreeter/commands/slash/PlaytestCommand.java index b5c446c..fe77d5c 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/slash/PlaytestCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/slash/PlaytestCommand.java @@ -14,7 +14,7 @@ import ovh.excale.vgreeter.models.TrackModel; import ovh.excale.vgreeter.repositories.TrackRepository; import ovh.excale.vgreeter.services.DiscordService; -import ovh.excale.vgreeter.utilities.TrackPlayer; +import ovh.excale.vgreeter.track.TrackPlayer; import java.util.Optional; import java.util.Set; diff --git a/src/main/java/ovh/excale/vgreeter/services/TrackService.java b/src/main/java/ovh/excale/vgreeter/services/TrackService.java index 7f8848a..08fbce3 100644 --- a/src/main/java/ovh/excale/vgreeter/services/TrackService.java +++ b/src/main/java/ovh/excale/vgreeter/services/TrackService.java @@ -1,5 +1,6 @@ package ovh.excale.vgreeter.services; +import lombok.Getter; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.stereotype.Service; @@ -11,12 +12,14 @@ public class TrackService { public static final int DEFAULT_MAX_TRACK_SIZE = 1024 * 64; + @Getter private final TrackRepository trackRepo; public TrackService(TrackRepository trackRepo) { this.trackRepo = trackRepo; } + // TODO: nullsafe public TrackModel randomTrack() { long qty = trackRepo.count(); @@ -31,8 +34,4 @@ public TrackModel randomTrack() { return track; } - public TrackRepository getTrackRepo() { - return trackRepo; - } - } diff --git a/src/main/java/ovh/excale/vgreeter/services/VoiceChannelHandler.java b/src/main/java/ovh/excale/vgreeter/services/VoiceChannelHandler.java index a586f2a..87bb3b9 100644 --- a/src/main/java/ovh/excale/vgreeter/services/VoiceChannelHandler.java +++ b/src/main/java/ovh/excale/vgreeter/services/VoiceChannelHandler.java @@ -14,7 +14,7 @@ import org.springframework.stereotype.Service; import ovh.excale.vgreeter.models.GuildModel; import ovh.excale.vgreeter.repositories.GuildRepository; -import ovh.excale.vgreeter.utilities.TrackPlayer; +import ovh.excale.vgreeter.track.TrackPlayer; import java.util.Optional; import java.util.Random; diff --git a/src/main/java/ovh/excale/vgreeter/utilities/TrackPlayer.java b/src/main/java/ovh/excale/vgreeter/track/TrackPlayer.java similarity index 97% rename from src/main/java/ovh/excale/vgreeter/utilities/TrackPlayer.java rename to src/main/java/ovh/excale/vgreeter/track/TrackPlayer.java index cc806f2..ae04a98 100644 --- a/src/main/java/ovh/excale/vgreeter/utilities/TrackPlayer.java +++ b/src/main/java/ovh/excale/vgreeter/track/TrackPlayer.java @@ -1,4 +1,4 @@ -package ovh.excale.vgreeter.utilities; +package ovh.excale.vgreeter.track; import lombok.extern.log4j.Log4j2; import net.dv8tion.jda.api.audio.AudioSendHandler; From 57e363687925ecffd509b3ea6ee1dd827e5cda24 Mon Sep 17 00:00:00 2001 From: Emanuele Scaccia Date: Sat, 5 Feb 2022 20:27:51 +0100 Subject: [PATCH 34/46] feature: Created TrackIndex class, which wraps all db/filter logic and discord components creation, acts independently from commands refactor: Divided TrackIndexCommand into TrackIndexSlashCommand and TrackIndexButtonCommand feature: Created CommandOptions, which wraps a command's info and acts as an interface for json feature: Created CloseEmbedCommand, for a generic close button --- .../commands/button/CloseEmbedCommand.java | 27 ++ .../button/TrackIndexButtonCommand.java | 61 +++ .../commands/core/AbstractButtonCommand.java | 37 ++ .../commands/core/AbstractCommand.java | 1 - .../commands/core/AbstractSlashCommand.java | 1 - .../commands/core/CommandKeyword.java | 73 ++++ .../commands/core/CommandOptions.java | 95 +++++ .../commands/slash/TrackIndexCommand.java | 373 ------------------ .../slash/TrackIndexSlashCommand.java | 87 ++++ .../vgreeter/services/DiscordService.java | 7 +- .../ovh/excale/vgreeter/track/TrackIndex.java | 167 ++++++++ 11 files changed, 553 insertions(+), 376 deletions(-) create mode 100644 src/main/java/ovh/excale/vgreeter/commands/button/CloseEmbedCommand.java create mode 100644 src/main/java/ovh/excale/vgreeter/commands/button/TrackIndexButtonCommand.java create mode 100644 src/main/java/ovh/excale/vgreeter/commands/core/AbstractButtonCommand.java create mode 100644 src/main/java/ovh/excale/vgreeter/commands/core/CommandKeyword.java create mode 100644 src/main/java/ovh/excale/vgreeter/commands/core/CommandOptions.java delete mode 100644 src/main/java/ovh/excale/vgreeter/commands/slash/TrackIndexCommand.java create mode 100644 src/main/java/ovh/excale/vgreeter/commands/slash/TrackIndexSlashCommand.java create mode 100644 src/main/java/ovh/excale/vgreeter/track/TrackIndex.java diff --git a/src/main/java/ovh/excale/vgreeter/commands/button/CloseEmbedCommand.java b/src/main/java/ovh/excale/vgreeter/commands/button/CloseEmbedCommand.java new file mode 100644 index 0000000..462ec9c --- /dev/null +++ b/src/main/java/ovh/excale/vgreeter/commands/button/CloseEmbedCommand.java @@ -0,0 +1,27 @@ +package ovh.excale.vgreeter.commands.button; + +import net.dv8tion.jda.api.events.interaction.ButtonClickEvent; +import net.dv8tion.jda.api.requests.RestAction; +import org.jetbrains.annotations.NotNull; +import ovh.excale.vgreeter.commands.core.AbstractButtonCommand; + +public class CloseEmbedCommand extends AbstractButtonCommand { + + public CloseEmbedCommand() { + super("close", "Close and embed or a message"); + } + + @Override + public @NotNull RestAction execute(@NotNull ButtonClickEvent event) { + + // noinspection ConstantConditions + return event.getMessage() + .delete() + .reason("Embed closed by " + event.getUser() + .getAsMention()) + .onErrorFlatMap(t -> event.reply("Cannot close embed") + .map(hook -> null)); + + } + +} diff --git a/src/main/java/ovh/excale/vgreeter/commands/button/TrackIndexButtonCommand.java b/src/main/java/ovh/excale/vgreeter/commands/button/TrackIndexButtonCommand.java new file mode 100644 index 0000000..51d1c83 --- /dev/null +++ b/src/main/java/ovh/excale/vgreeter/commands/button/TrackIndexButtonCommand.java @@ -0,0 +1,61 @@ +package ovh.excale.vgreeter.commands.button; + +import lombok.SneakyThrows; +import lombok.extern.log4j.Log4j2; +import net.dv8tion.jda.api.events.interaction.ButtonClickEvent; +import net.dv8tion.jda.api.interactions.Interaction; +import net.dv8tion.jda.api.requests.RestAction; +import net.dv8tion.jda.api.requests.restaction.interactions.ReplyAction; +import org.jetbrains.annotations.NotNull; +import ovh.excale.vgreeter.commands.core.AbstractButtonCommand; +import ovh.excale.vgreeter.commands.core.CommandOptions; +import ovh.excale.vgreeter.track.TrackIndex; + +@Log4j2 +public class TrackIndexButtonCommand extends AbstractButtonCommand { + + private static final String KEY_TRACK = "trackname"; + private static final String KEY_USER = "user"; + + public TrackIndexButtonCommand() { + super("trackindex", "List all the tracks"); + } + + @SneakyThrows + @Override + public @NotNull RestAction execute(ButtonClickEvent event) { + + CommandOptions command = CommandOptions.fromJson(event.getComponentId()); + //noinspection DuplicatedCode + TrackIndex index = new TrackIndex(command); + + try { + + index.fetch(); + + } catch(IllegalArgumentException e) { + return replyEphemeralWith(e.getMessage(), event); + } catch(Exception e) { + log.error(e.getMessage(), e); + return replyEphemeralWith("There has been an internal error", event); + } + + if(index.isEmpty()) + return replyEphemeralWith("Empty page", event); + + //noinspection ConstantConditions + return event.getMessage() + .delete() + .and(event.getChannel() + .sendMessage(index.buildEmbed() + .build()) + .setActionRow(index.buildButtons())); + + } + + private static ReplyAction replyEphemeralWith(String message, Interaction event) { + return event.reply(message) + .setEphemeral(true); + } + +} diff --git a/src/main/java/ovh/excale/vgreeter/commands/core/AbstractButtonCommand.java b/src/main/java/ovh/excale/vgreeter/commands/core/AbstractButtonCommand.java new file mode 100644 index 0000000..c57b41e --- /dev/null +++ b/src/main/java/ovh/excale/vgreeter/commands/core/AbstractButtonCommand.java @@ -0,0 +1,37 @@ +package ovh.excale.vgreeter.commands.core; + +import com.fasterxml.jackson.core.JsonProcessingException; +import net.dv8tion.jda.api.events.GenericEvent; +import net.dv8tion.jda.api.events.interaction.ButtonClickEvent; +import net.dv8tion.jda.api.requests.RestAction; +import org.jetbrains.annotations.NotNull; + +public abstract class AbstractButtonCommand extends AbstractCommand { + + protected AbstractButtonCommand(String name, String description) { + super(name, description, ButtonClickEvent.class); + } + + @Override + public abstract @NotNull RestAction execute(@NotNull ButtonClickEvent event); + + @Override + public boolean accepts(GenericEvent event) { + + if(!(event instanceof ButtonClickEvent)) + return false; + + CommandOptions command; + try { + + command = CommandOptions.fromJson(((ButtonClickEvent) event).getComponentId()); + + } catch(JsonProcessingException e) { + return false; + } + + return name.equalsIgnoreCase(command.getCommand()); + + } + +} diff --git a/src/main/java/ovh/excale/vgreeter/commands/core/AbstractCommand.java b/src/main/java/ovh/excale/vgreeter/commands/core/AbstractCommand.java index 3244b95..ea8918e 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/core/AbstractCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/core/AbstractCommand.java @@ -1,7 +1,6 @@ package ovh.excale.vgreeter.commands.core; import lombok.Getter; -import net.dv8tion.jda.api.events.Event; import net.dv8tion.jda.api.events.GenericEvent; import net.dv8tion.jda.api.hooks.EventListener; import net.dv8tion.jda.api.requests.RestAction; diff --git a/src/main/java/ovh/excale/vgreeter/commands/core/AbstractSlashCommand.java b/src/main/java/ovh/excale/vgreeter/commands/core/AbstractSlashCommand.java index 773a482..1d6dd64 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/core/AbstractSlashCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/core/AbstractSlashCommand.java @@ -7,7 +7,6 @@ import net.dv8tion.jda.api.requests.RestAction; import org.jetbrains.annotations.NotNull; -// TODO: MERGE AbstractSlashCommand AND AbstractMessageCommand WITH A PARENT AbstractCommand CLASS public abstract class AbstractSlashCommand extends AbstractCommand { @Getter diff --git a/src/main/java/ovh/excale/vgreeter/commands/core/CommandKeyword.java b/src/main/java/ovh/excale/vgreeter/commands/core/CommandKeyword.java new file mode 100644 index 0000000..6147740 --- /dev/null +++ b/src/main/java/ovh/excale/vgreeter/commands/core/CommandKeyword.java @@ -0,0 +1,73 @@ +package ovh.excale.vgreeter.commands.core; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.KeyDeserializer; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.std.StdKeySerializers; +import com.fasterxml.jackson.databind.ser.std.StdKeySerializers.StringKeySerializer; +import lombok.Getter; +import lombok.experimental.Accessors; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +public enum CommandKeyword { + + TRACK_NAME("tn", "trackName"), + USER_ID("uid", "userId"); + + public static final String COMMAND = "cmd"; + public static final String SUBCOMMAND = "scmd"; + public static final String PAGE = "p"; + + + private static final Map encodeRecord; + private static final Map decodeRecord; + + static { + + encodeRecord = new HashMap<>(); + decodeRecord = new HashMap<>(); + + for(CommandKeyword keyword : values()) { + encodeRecord.put(keyword.ext, keyword.key); + decodeRecord.put(keyword.key, keyword.ext); + } + } + + public final String key; + public final String ext; + + CommandKeyword(String key, String ext) { + this.key = key; + this.ext = ext; + } + + public String getKey() { + return key; + } + + public String getExt() { + return ext; + } + + public static class KeywordDecoder extends KeyDeserializer { + + @Override + public Object deserializeKey(String key, DeserializationContext deserializationContext) { + return decodeRecord.getOrDefault(key, key); + } + + } + + public static class KeywordEncoder extends StringKeySerializer { + + @Override + public void serialize(Object ext, JsonGenerator g, SerializerProvider provider) throws IOException { + g.writeFieldName(encodeRecord.getOrDefault(ext.toString(), ext.toString())); + } + + } +} diff --git a/src/main/java/ovh/excale/vgreeter/commands/core/CommandOptions.java b/src/main/java/ovh/excale/vgreeter/commands/core/CommandOptions.java new file mode 100644 index 0000000..6eeb6b9 --- /dev/null +++ b/src/main/java/ovh/excale/vgreeter/commands/core/CommandOptions.java @@ -0,0 +1,95 @@ +package ovh.excale.vgreeter.commands.core; + +import com.fasterxml.jackson.annotation.*; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectReader; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; +import ovh.excale.vgreeter.commands.core.CommandKeyword.KeywordDecoder; +import ovh.excale.vgreeter.commands.core.CommandKeyword.KeywordEncoder; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; + +import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_EMPTY; + +@JsonInclude(NON_EMPTY) +@Accessors(chain = true) +@Getter +@Setter +public class CommandOptions { + + private static final ObjectMapper objWriter = new ObjectMapper(); + private static final ObjectReader objReader = objWriter.readerFor(CommandOptions.class); + + public static CommandOptions fromJson(String payload) throws JsonProcessingException { + return objReader.readValue(payload); + } + + @JsonProperty(CommandKeyword.COMMAND) + private final String command; + + @JsonProperty(CommandKeyword.SUBCOMMAND) + private final String subcommand; + + @JsonProperty(CommandKeyword.PAGE) + private Integer page; + + @Getter(AccessLevel.NONE) + @Setter(AccessLevel.NONE) + @JsonAnySetter + @JsonAnyGetter + @JsonSerialize(keyUsing = KeywordEncoder.class) + @JsonDeserialize(keyUsing = KeywordDecoder.class) + private final Map extendedOptions; + + public CommandOptions(String command) { + this(command, null); + } + + @JsonCreator + public CommandOptions(@JsonProperty(CommandKeyword.COMMAND) String command, + @JsonProperty(CommandKeyword.SUBCOMMAND) String subcommand) { + this.command = Objects.requireNonNull(command); + this.subcommand = subcommand; + extendedOptions = new HashMap<>(); + } + + public boolean hasSubcommand() { + return subcommand != null && !subcommand.isEmpty(); + } + + @JsonIgnore + public int getPageSafe() { + return page != null ? page : 1; + } + + public Optional getOption(String key) { + return Optional.ofNullable(extendedOptions.get(key)); + } + + public CommandOptions putOption(String key, Object value) { + extendedOptions.put(key, value.toString()); + return this; + } + + public String json() throws JsonProcessingException { + return objWriter.writeValueAsString(this); + } + + @Override + public String toString() { + return "CommandOptions{" + "command='" + command + '\'' + ", subcommand='" + subcommand + '\'' + ", page=" + + page + ", extendedOptions=" + extendedOptions + '}'; + } + +} + + diff --git a/src/main/java/ovh/excale/vgreeter/commands/slash/TrackIndexCommand.java b/src/main/java/ovh/excale/vgreeter/commands/slash/TrackIndexCommand.java deleted file mode 100644 index ad9b41c..0000000 --- a/src/main/java/ovh/excale/vgreeter/commands/slash/TrackIndexCommand.java +++ /dev/null @@ -1,373 +0,0 @@ -package ovh.excale.vgreeter.commands.slash; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.ObjectReader; -import lombok.SneakyThrows; -import lombok.extern.log4j.Log4j2; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.events.interaction.ButtonClickEvent; -import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; -import net.dv8tion.jda.api.hooks.EventListener; -import net.dv8tion.jda.api.hooks.ListenerAdapter; -import net.dv8tion.jda.api.interactions.Interaction; -import net.dv8tion.jda.api.interactions.commands.OptionMapping; -import net.dv8tion.jda.api.interactions.commands.OptionType; -import net.dv8tion.jda.api.interactions.components.Button; -import net.dv8tion.jda.api.interactions.components.Component; -import net.dv8tion.jda.api.requests.RestAction; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Sort; -import ovh.excale.vgreeter.VGreeterApplication; -import ovh.excale.vgreeter.commands.core.AbstractSlashCommand; -import ovh.excale.vgreeter.models.TrackModel; -import ovh.excale.vgreeter.repositories.TrackRepository; -import ovh.excale.vgreeter.utilities.Emojis; - -import java.awt.*; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; -import java.util.stream.Collectors; - -@Log4j2 -public class TrackIndexCommand extends AbstractSlashCommand { - - public static final String SUBCOMMAND_ALL = "all"; - public static final String SUBCOMMAND_NAME = "name"; - public static final String SUBCOMMAND_USER = "user"; - - private final TrackRepository trackRepo; - private final ButtonClickListener buttonListener; - - public TrackIndexCommand() { - super("trackindex", "List all the tracks"); - // TODO: - getBuilder() - // [SUB] all - .subcommand(SUBCOMMAND_ALL, "Search for all tracks") - .addOption("page", "Page number", OptionType.INTEGER) - // [SUB] name - .subcommand(SUBCOMMAND_NAME, "Search for all tracks with something in the name") - .addOptionRequired("name", "Track name", OptionType.STRING) - .addOption("page", "Page number", OptionType.INTEGER) - // [SUB] user - .subcommand(SUBCOMMAND_USER, "Search for tracks by a user") - .addOptionRequired("user", "The user to query for", OptionType.USER) - .addOption("page", "Page number", OptionType.INTEGER); - - trackRepo = VGreeterApplication - .getApplicationContext() - .getBean(TrackRepository.class); - - buttonListener = new ButtonClickListener(); - - } - - @Override - public @NotNull RestAction execute(SlashCommandEvent event) { - - int humanBasedPage = Optional - .ofNullable(event.getOption("page")) - .map(OptionMapping::getAsLong) - .map(Long::intValue) - .orElse(1); - - if(humanBasedPage < 1) - return event - .reply("Page option must be positive!") - .setEphemeral(true); - - Page trackPage; - Map options = new HashMap<>(); - - String titleAppendix = null; - String footerAppendix = null; - String subcommand = event.getSubcommandName(); - options.put("command", getName()); - options.put("subcommand", subcommand); - - //noinspection ConstantConditions - switch(subcommand) { - - case SUBCOMMAND_ALL: - - trackPage = trackRepo.findAll( - PageRequest.of(humanBasedPage - 1, 15, Sort.by(Sort.Direction.ASC, "id"))); - - break; - - case SUBCOMMAND_NAME: - - - //noinspection ConstantConditions - String trackName = event - .getOption("name") - .getAsString(); - - String formattedTrackName = "%" + trackName.replaceAll("\\s+", "%") + "%"; - titleAppendix = "Name"; - footerAppendix = "Filter: \"" + trackName + "\""; - - options.put("track_name", trackName); - trackPage = trackRepo.findAllByNameQuery(formattedTrackName, - PageRequest.of(humanBasedPage - 1, 15, Sort.by(Sort.Direction.ASC, "id"))); - - break; - - case SUBCOMMAND_USER: - - //noinspection ConstantConditions - long userId = event - .getOption("user") - .getAsUser() - .getIdLong(); - - String userTag = event.getJDA() - .retrieveUserById(userId) - .complete() - .getAsTag(); - - titleAppendix = "User"; - footerAppendix = "Filter: " + userTag; - - options.put("user_id", Long.toString(userId)); - trackPage = trackRepo.findAllByUploaderIdIs(userId, - PageRequest.of(humanBasedPage - 1, 15, Sort.by(Sort.Direction.ASC, "id"))); - - break; - - default: - return event - .reply("Unknown option `" + event.getSubcommandName() + "`") - .setEphemeral(true); - - } - - if(trackPage.isEmpty()) - return event - .reply("Empty page") - .setEphemeral(true); - - EmbedBuilder eb = computeEmbed(trackPage, titleAppendix, footerAppendix); - - // TODO: CHECK PERMS AND MESSAGECHANNEL - return event.reply("Here's your track index!") - .setEphemeral(true) - .and(event.getChannel() - .sendMessage(eb.build()) - .setActionRow(computeButtons(trackPage, options))); - - } - - @Override - public boolean hasListener() { - return true; - } - - @Override - public @Nullable EventListener getListener() { - return buttonListener; - } - - private @NotNull EmbedBuilder computeEmbed(Page trackPage, @Nullable String titleAppendix, @Nullable String footerAppendix) { - - String pageCount = "Page " + (trackPage.getNumber() + 1) + "/" + trackPage.getTotalPages(); - String footer = footerAppendix == null ? pageCount : pageCount + " | " + footerAppendix; - String title = titleAppendix == null ? "Track Index" : "Track Index (" + titleAppendix + ")"; - - return new EmbedBuilder() - .setTitle(title) - .setFooter(footer) - .setColor(Color.BLUE) - .setDescription(trackPage - .getContent() - .stream() - .map(track -> "**#" + track.getId() + "** *" + track.getName() + "*") - .collect(Collectors.joining("\n"))); - - } - - @SneakyThrows - private Component[] computeButtons(Page trackPage, Map options) { - - ObjectMapper json = new ObjectMapper(); - int zeroBasedPage = trackPage.getNumber(); - - // TODO: disable prev/next buttons on 1 page - - // button - options.put("page", Integer.toString(trackPage.hasPrevious() ? zeroBasedPage - 1 : trackPage.getTotalPages() - 1)); - options.put("emoji", Emojis.PREVIOUS.getName()); - Button prevButton = Button.secondary(json.writeValueAsString(options), Emojis.PREVIOUS); - - // button - options.put("page", Integer.toString(!trackPage.isLast() ? zeroBasedPage + 1 : 0)); - options.put("emoji", Emojis.NEXT.getName()); - Button nextButton = Button.secondary(json.writeValueAsString(options), Emojis.NEXT); - - // button - options.put("page", Integer.toString(zeroBasedPage)); - options.put("emoji", Emojis.RELOAD.getName()); - Button reloadButton = Button.secondary(json.writeValueAsString(options), Emojis.RELOAD); - - Map closeCommand = new HashMap<>(); - closeCommand.put("command", "close"); - closeCommand.put("emoji", Emojis.CLOSE.getName()); - Button closeButton = Button.secondary(json.writeValueAsString(closeCommand), Emojis.CLOSE); - - return new Component[] { prevButton, nextButton, reloadButton, closeButton }; - - } - - private static void replyEphemeralWith(String message, Interaction event) { - event - .reply(message) - .setEphemeral(true) - .queue(); - } - - // TODO: turn this listener into a command (TrackIndexButtonCommand) - public class ButtonClickListener extends ListenerAdapter { - - @SneakyThrows - @Override - public void onButtonClick(@NotNull ButtonClickEvent event) { - - ObjectReader jsonParser = new ObjectMapper() - .readerForMapOf(String.class); - String rawJson = event.getComponentId(); - - Map commandOptions = jsonParser.readValue(rawJson); - String commandName = commandOptions.get("command"); - - if(commandName == null) { - replyEphemeralWith("Invalid button", event); - log.debug("Invalid button (commandName) -> " + rawJson); - return; - } - - // TODO: GENERIC CLOSE "BUTTON COMMAND" (listener) - if(commandName.equalsIgnoreCase("close")) { - //noinspection ConstantConditions - event - .getMessage() - .delete() - .queue(); - return; - } - - // TODO: AUTOMATIC "BUTTON COMMAND" FORWARDING - if(!commandName.equalsIgnoreCase(getName())) - return; - - String pageString = commandOptions.get("page"); - try { - - if(Integer.parseInt(pageString) < 0) - throw new NullPointerException(); - - } catch(NumberFormatException | NullPointerException e) { - replyEphemeralWith("Invalid button", event); - log.debug("Invalid button (page) -> " + rawJson); - return; - } - - Page trackPage; - int zeroBasedPage = Integer.parseInt(pageString); - String subcommand = commandOptions.get("subcommand"); - - if(subcommand == null) { - replyEphemeralWith("Invalid button", event); - log.debug("Invalid button (subcommand) -> " + rawJson); - return; - } - - String titleAppendix = null; - String footerAppendix = null; - - switch(subcommand) { - - case SUBCOMMAND_ALL: - - trackPage = trackRepo.findAll(PageRequest.of(zeroBasedPage, 15, Sort.by(Sort.Direction.ASC, "id"))); - - break; - - case SUBCOMMAND_NAME: - - String trackName = commandOptions.get("track_name"); - if(trackName == null) { - replyEphemeralWith("Invalid button", event); - log.debug("Invalid button (trackName) -> " + rawJson); - return; - } - - - String formattedTrackName = "%" + trackName.replaceAll("\\s+", "%") + "%"; - titleAppendix = "Name"; - footerAppendix = "Filter: \"" + trackName + "\""; - - trackPage = trackRepo.findAllByNameQuery(formattedTrackName, - PageRequest.of(zeroBasedPage, 15, Sort.by(Sort.Direction.ASC, "id"))); - - break; - - case SUBCOMMAND_USER: - - long userId; - try { - - userId = Long.parseLong(commandOptions.get("user_id")); - - } catch(NumberFormatException | NullPointerException e) { - replyEphemeralWith("Invalid button", event); - log.debug("Invalid button (userId) -> " + rawJson); - return; - } - - String userTag = event.getJDA() - .retrieveUserById(userId) - .complete() - .getAsTag(); - - titleAppendix = "User"; - footerAppendix = "Filter: " + userTag; - - trackPage = trackRepo.findAllByUploaderIdIs(userId, - PageRequest.of(zeroBasedPage, 15, Sort.by(Sort.Direction.ASC, "id"))); - - break; - - default: - replyEphemeralWith("Unknown option `" + subcommand + "`", event); - return; - - } - - if(trackPage.isEmpty()) { - - replyEphemeralWith("Empty page", event); - return; - - } - - EmbedBuilder eb = computeEmbed(trackPage, titleAppendix, footerAppendix); - - //noinspection ConstantConditions - event - .getMessage() - .delete() - .and(event - .getChannel() - .sendMessage(eb.build()) - .setActionRow(computeButtons(trackPage, commandOptions))) - .queue(); - - } - - } - -} diff --git a/src/main/java/ovh/excale/vgreeter/commands/slash/TrackIndexSlashCommand.java b/src/main/java/ovh/excale/vgreeter/commands/slash/TrackIndexSlashCommand.java new file mode 100644 index 0000000..bd6d03f --- /dev/null +++ b/src/main/java/ovh/excale/vgreeter/commands/slash/TrackIndexSlashCommand.java @@ -0,0 +1,87 @@ +package ovh.excale.vgreeter.commands.slash; + +import lombok.extern.log4j.Log4j2; +import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; +import net.dv8tion.jda.api.interactions.Interaction; +import net.dv8tion.jda.api.interactions.commands.OptionMapping; +import net.dv8tion.jda.api.interactions.commands.OptionType; +import net.dv8tion.jda.api.requests.RestAction; +import net.dv8tion.jda.api.requests.restaction.interactions.ReplyAction; +import org.jetbrains.annotations.NotNull; +import ovh.excale.vgreeter.commands.core.AbstractSlashCommand; +import ovh.excale.vgreeter.commands.core.CommandOptions; +import ovh.excale.vgreeter.track.TrackIndex; + +import java.util.Optional; + +import static ovh.excale.vgreeter.track.TrackIndex.*; + +@Log4j2 +public class TrackIndexSlashCommand extends AbstractSlashCommand { + + private static final String KEY_TRACK = "trackname"; + private static final String KEY_USER = "user"; + + public TrackIndexSlashCommand() { + super("trackindex", "List all the tracks"); + + getBuilder() + // [SUB] all + .subcommand(FILTER_ALL, "Search for all tracks") + .addOption("page", "Page number", OptionType.INTEGER) + // [SUB] name + .subcommand(FILTER_NAME, "Search for all tracks with something in the name") + .addOptionRequired(KEY_TRACK, "Track name", OptionType.STRING) + .addOption("page", "Page number", OptionType.INTEGER) + // [SUB] user + .subcommand(FILTER_USER, "Search for tracks by a user") + .addOptionRequired(KEY_USER, "The user to query for", OptionType.USER) + .addOption("page", "Page number", OptionType.INTEGER); + + } + + @Override + public @NotNull RestAction execute(SlashCommandEvent event) { + + int page = Optional.ofNullable(event.getOption("page")) + .map(OptionMapping::getAsLong) + .map(Long::intValue) + .orElse(1); + + CommandOptions command = new CommandOptions(event.getName(), event.getSubcommandName()).setPage(page); + event.getOptions() + .stream() + .filter(option -> !"page".equals(option.getName())) + .forEach(option -> command.putOption(option.getName(), option.getAsString())); + + //noinspection DuplicatedCode + TrackIndex index = new TrackIndex(command); + try { + + index.fetch(); + + } catch(IllegalArgumentException e) { + return replyEphemeralWith(e.getMessage(), event); + } catch(Exception e) { + log.error(e.getMessage(), e); + return replyEphemeralWith("There has been an internal error", event); + } + + if(index.isEmpty()) + return replyEphemeralWith("Empty page", event); + + return event.reply("Here's your track index") + .setEphemeral(true) + .and(event.getChannel() + .sendMessage(index.buildEmbed() + .build()) + .setActionRow(index.buildButtons())); + + } + + private static ReplyAction replyEphemeralWith(String message, Interaction event) { + return event.reply(message) + .setEphemeral(true); + } + +} diff --git a/src/main/java/ovh/excale/vgreeter/services/DiscordService.java b/src/main/java/ovh/excale/vgreeter/services/DiscordService.java index a37c4df..4799509 100644 --- a/src/main/java/ovh/excale/vgreeter/services/DiscordService.java +++ b/src/main/java/ovh/excale/vgreeter/services/DiscordService.java @@ -11,6 +11,8 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Service; +import ovh.excale.vgreeter.commands.button.CloseEmbedCommand; +import ovh.excale.vgreeter.commands.button.TrackIndexButtonCommand; import ovh.excale.vgreeter.commands.slash.AltnameCommand; import ovh.excale.vgreeter.commands.slash.ProbabilityCommand; import ovh.excale.vgreeter.commands.message.RestartCommand; @@ -58,12 +60,15 @@ public DiscordService(VoiceChannelHandler eventHandler, CommandRegister commands .register(new UploadHelpCommand()) .register(new PlaytestCommand()) .register(new TrackNameCommand()) - .register(new TrackIndexCommand()) + .register(new TrackIndexSlashCommand()) .register(new TrackRemoveCommand()) .register(new TrackDownloadCommand()) // MESSAGE COMMANDS .register(new RestartCommand()) .register(new TrackUploadCommand()) + // BUTTON COMMANDS + .register(new CloseEmbedCommand()) + .register(new TrackIndexButtonCommand()) .getSlashCommandsData()) .complete() .stream() diff --git a/src/main/java/ovh/excale/vgreeter/track/TrackIndex.java b/src/main/java/ovh/excale/vgreeter/track/TrackIndex.java new file mode 100644 index 0000000..6c59d6c --- /dev/null +++ b/src/main/java/ovh/excale/vgreeter/track/TrackIndex.java @@ -0,0 +1,167 @@ +package ovh.excale.vgreeter.track; + +import lombok.Getter; +import lombok.Setter; +import lombok.SneakyThrows; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.interactions.components.Button; +import net.dv8tion.jda.api.interactions.components.Component; +import org.jetbrains.annotations.NotNull; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; +import ovh.excale.vgreeter.VGreeterApplication; +import ovh.excale.vgreeter.commands.core.CommandOptions; +import ovh.excale.vgreeter.models.TrackModel; +import ovh.excale.vgreeter.repositories.TrackRepository; +import ovh.excale.vgreeter.utilities.Emojis; + +import java.awt.*; +import java.util.Objects; +import java.util.stream.Collectors; + +import static ovh.excale.vgreeter.commands.core.CommandKeyword.TRACK_NAME; +import static ovh.excale.vgreeter.commands.core.CommandKeyword.USER_ID; + +public class TrackIndex { + + public static final String FILTER_ALL = "all"; + public static final String FILTER_NAME = "name"; + public static final String FILTER_USER = "user"; + public static final int DEFAULT_PAGE_SIZE = 15; + + private final CommandOptions options; + private final TrackRepository trackRepo; + private Page trackPage; + + @Setter + @Getter + private Color embedColor; + private String filterContent; + + @Setter + @Getter + private int pageSize; + + public TrackIndex(CommandOptions options) { + this.options = Objects.requireNonNull(options); + trackRepo = VGreeterApplication.getApplicationContext() + .getBean(TrackRepository.class); + + trackPage = null; + filterContent = null; + embedColor = Color.BLUE; + pageSize = DEFAULT_PAGE_SIZE; + + } + + private void trackPageCheck() throws IllegalStateException { + if(trackPage == null) + throw new IllegalStateException(); + } + + public boolean isEmpty() { + return trackPage == null || !trackPage.hasContent(); + } + + public void fetch() throws IllegalArgumentException { + + int humanBasedPage = options.getPageSafe(); + if(humanBasedPage < 1) + throw new IllegalArgumentException("Page option must be positive"); + + Sort sorting = Sort.by(Sort.Direction.ASC, "id"); + String filter = options.hasSubcommand() ? options.getSubcommand() : FILTER_ALL; + + switch(filter) { + + case FILTER_ALL: + + trackPage = trackRepo.findAll(PageRequest.of(humanBasedPage - 1, pageSize, sorting)); + + break; + + case FILTER_NAME: + + String trackName = options.getOption(TRACK_NAME.ext) + .orElseThrow(() -> new IllegalArgumentException("Missing parameter " + TRACK_NAME.ext)); + filterContent = trackName; + + String formattedTrackName = "%" + trackName.replaceAll("\\s+", "%") + "%"; + trackPage = trackRepo.findAllByNameQuery(formattedTrackName, + PageRequest.of(humanBasedPage - 1, pageSize, sorting)); + + break; + + case FILTER_USER: + + long userId = options.getOption(USER_ID.ext) + .map(Long::valueOf) + .orElseThrow(() -> new IllegalArgumentException("Missing parameter " + USER_ID.ext)); + + filterContent = String.format("<@%d>", userId); + trackPage = trackRepo.findAllByUploaderIdIs(userId, + PageRequest.of(humanBasedPage - 1, pageSize, sorting)); + + break; + + default: + throw new IllegalArgumentException("Unknown filter " + filter); + + } + + } + + public @NotNull EmbedBuilder buildEmbed() { + + trackPageCheck(); + + String filterOut = (filterContent != null) ? "\n\n| _**Filter:** " + filterContent + "_" : ""; + + return new EmbedBuilder() + .setTitle("TrackIndex") + .setFooter("Page " + (trackPage.getNumber() + 1) + "/" + trackPage.getTotalPages()) + .setColor(embedColor) + .setDescription(trackPage.getContent() + .stream() + .map(track -> "**#" + track.getId() + "** *" + track.getName() + "*") + .collect(Collectors.joining("\n")) + .concat(filterOut)); + + } + + @SneakyThrows + public Component[] buildButtons() { + + trackPageCheck(); + + int zeroBasedPage = trackPage.getNumber(); + boolean enablePageChange = trackPage.getTotalPages() != 1; + + // button + options.setPage(trackPage.hasPrevious() ? zeroBasedPage : trackPage.getTotalPages()); + Button prevButton = Button.secondary(enablePageChange ? options.json() : "{\"_\":0}", Emojis.PREVIOUS) + .withDisabled(!enablePageChange); + + System.out.println(options.json()); + + // button + options.setPage(!trackPage.isLast() ? zeroBasedPage + 2 : 0); + Button nextButton = Button.secondary(enablePageChange ? options.json() : "{\"_\":1}", Emojis.NEXT); + + System.out.println(options.json()); + + // button + options.setPage(zeroBasedPage + 1); + Button reloadButton = Button.secondary(options.json(), Emojis.RELOAD); + + System.out.println(options.json()); + + CommandOptions closeCommand = new CommandOptions("close"); + Button closeButton = Button.secondary(closeCommand.json(), Emojis.CLOSE); + + return new Component[] { prevButton, nextButton, reloadButton, closeButton }; + + } + +} From d8332a757996b8965062256aeddca7ef9d84ab7e Mon Sep 17 00:00:00 2001 From: Emanuele Scaccia Date: Sun, 6 Feb 2022 02:45:35 +0100 Subject: [PATCH 35/46] refactor: Unified command options keys fix: Discord's command option key must be lowercase --- .../commands/button/TrackIndexButtonCommand.java | 3 --- .../excale/vgreeter/commands/core/CommandKeyword.java | 8 ++------ .../commands/slash/TrackIndexSlashCommand.java | 10 +++++----- 3 files changed, 7 insertions(+), 14 deletions(-) diff --git a/src/main/java/ovh/excale/vgreeter/commands/button/TrackIndexButtonCommand.java b/src/main/java/ovh/excale/vgreeter/commands/button/TrackIndexButtonCommand.java index 51d1c83..c59b671 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/button/TrackIndexButtonCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/button/TrackIndexButtonCommand.java @@ -14,9 +14,6 @@ @Log4j2 public class TrackIndexButtonCommand extends AbstractButtonCommand { - private static final String KEY_TRACK = "trackname"; - private static final String KEY_USER = "user"; - public TrackIndexButtonCommand() { super("trackindex", "List all the tracks"); } diff --git a/src/main/java/ovh/excale/vgreeter/commands/core/CommandKeyword.java b/src/main/java/ovh/excale/vgreeter/commands/core/CommandKeyword.java index 6147740..20e5a15 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/core/CommandKeyword.java +++ b/src/main/java/ovh/excale/vgreeter/commands/core/CommandKeyword.java @@ -4,10 +4,7 @@ import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.KeyDeserializer; import com.fasterxml.jackson.databind.SerializerProvider; -import com.fasterxml.jackson.databind.ser.std.StdKeySerializers; import com.fasterxml.jackson.databind.ser.std.StdKeySerializers.StringKeySerializer; -import lombok.Getter; -import lombok.experimental.Accessors; import java.io.IOException; import java.util.HashMap; @@ -15,14 +12,13 @@ public enum CommandKeyword { - TRACK_NAME("tn", "trackName"), - USER_ID("uid", "userId"); + TRACK_NAME("tn", "trackname"), + USER_ID("u", "user"); public static final String COMMAND = "cmd"; public static final String SUBCOMMAND = "scmd"; public static final String PAGE = "p"; - private static final Map encodeRecord; private static final Map decodeRecord; diff --git a/src/main/java/ovh/excale/vgreeter/commands/slash/TrackIndexSlashCommand.java b/src/main/java/ovh/excale/vgreeter/commands/slash/TrackIndexSlashCommand.java index bd6d03f..ae53030 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/slash/TrackIndexSlashCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/slash/TrackIndexSlashCommand.java @@ -9,19 +9,19 @@ import net.dv8tion.jda.api.requests.restaction.interactions.ReplyAction; import org.jetbrains.annotations.NotNull; import ovh.excale.vgreeter.commands.core.AbstractSlashCommand; +import ovh.excale.vgreeter.commands.core.CommandKeyword; import ovh.excale.vgreeter.commands.core.CommandOptions; import ovh.excale.vgreeter.track.TrackIndex; import java.util.Optional; +import static ovh.excale.vgreeter.commands.core.CommandKeyword.TRACK_NAME; +import static ovh.excale.vgreeter.commands.core.CommandKeyword.USER_ID; import static ovh.excale.vgreeter.track.TrackIndex.*; @Log4j2 public class TrackIndexSlashCommand extends AbstractSlashCommand { - private static final String KEY_TRACK = "trackname"; - private static final String KEY_USER = "user"; - public TrackIndexSlashCommand() { super("trackindex", "List all the tracks"); @@ -31,11 +31,11 @@ public TrackIndexSlashCommand() { .addOption("page", "Page number", OptionType.INTEGER) // [SUB] name .subcommand(FILTER_NAME, "Search for all tracks with something in the name") - .addOptionRequired(KEY_TRACK, "Track name", OptionType.STRING) + .addOptionRequired(TRACK_NAME.ext, "Track name", OptionType.STRING) .addOption("page", "Page number", OptionType.INTEGER) // [SUB] user .subcommand(FILTER_USER, "Search for tracks by a user") - .addOptionRequired(KEY_USER, "The user to query for", OptionType.USER) + .addOptionRequired(USER_ID.ext, "The user to query for", OptionType.USER) .addOption("page", "Page number", OptionType.INTEGER); } From ee2b3d0ff48a16c997b8140edc3e9fc84b9eefbf Mon Sep 17 00:00:00 2001 From: Emanuele Scaccia Date: Sun, 6 Feb 2022 02:47:05 +0100 Subject: [PATCH 36/46] fix: TrackIndex's next button not disabling on one page only --- src/main/java/ovh/excale/vgreeter/track/TrackIndex.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/ovh/excale/vgreeter/track/TrackIndex.java b/src/main/java/ovh/excale/vgreeter/track/TrackIndex.java index 6c59d6c..da09e38 100644 --- a/src/main/java/ovh/excale/vgreeter/track/TrackIndex.java +++ b/src/main/java/ovh/excale/vgreeter/track/TrackIndex.java @@ -147,7 +147,8 @@ public Component[] buildButtons() { // button options.setPage(!trackPage.isLast() ? zeroBasedPage + 2 : 0); - Button nextButton = Button.secondary(enablePageChange ? options.json() : "{\"_\":1}", Emojis.NEXT); + Button nextButton = Button.secondary(enablePageChange ? options.json() : "{\"_\":1}", Emojis.NEXT) + .withDisabled(!enablePageChange); System.out.println(options.json()); From dbff7f33e45b3b3c1a71e3d12b799eec5d98913d Mon Sep 17 00:00:00 2001 From: Emanuele Scaccia Date: Sun, 6 Feb 2022 02:47:35 +0100 Subject: [PATCH 37/46] refactor: Removed useless sout's --- src/main/java/ovh/excale/vgreeter/track/TrackIndex.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/main/java/ovh/excale/vgreeter/track/TrackIndex.java b/src/main/java/ovh/excale/vgreeter/track/TrackIndex.java index da09e38..92669d1 100644 --- a/src/main/java/ovh/excale/vgreeter/track/TrackIndex.java +++ b/src/main/java/ovh/excale/vgreeter/track/TrackIndex.java @@ -143,21 +143,15 @@ public Component[] buildButtons() { Button prevButton = Button.secondary(enablePageChange ? options.json() : "{\"_\":0}", Emojis.PREVIOUS) .withDisabled(!enablePageChange); - System.out.println(options.json()); - // button options.setPage(!trackPage.isLast() ? zeroBasedPage + 2 : 0); Button nextButton = Button.secondary(enablePageChange ? options.json() : "{\"_\":1}", Emojis.NEXT) .withDisabled(!enablePageChange); - System.out.println(options.json()); - // button options.setPage(zeroBasedPage + 1); Button reloadButton = Button.secondary(options.json(), Emojis.RELOAD); - System.out.println(options.json()); - CommandOptions closeCommand = new CommandOptions("close"); Button closeButton = Button.secondary(closeCommand.json(), Emojis.CLOSE); From 6f0fe654d21a208af2907f89de3515de38ebc704 Mon Sep 17 00:00:00 2001 From: Emanuele Scaccia Date: Sun, 6 Feb 2022 02:50:46 +0100 Subject: [PATCH 38/46] refactor: Removed useless gets on CommandKeyword --- .../ovh/excale/vgreeter/commands/core/CommandKeyword.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/main/java/ovh/excale/vgreeter/commands/core/CommandKeyword.java b/src/main/java/ovh/excale/vgreeter/commands/core/CommandKeyword.java index 20e5a15..25895dc 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/core/CommandKeyword.java +++ b/src/main/java/ovh/excale/vgreeter/commands/core/CommandKeyword.java @@ -41,14 +41,6 @@ public enum CommandKeyword { this.ext = ext; } - public String getKey() { - return key; - } - - public String getExt() { - return ext; - } - public static class KeywordDecoder extends KeyDeserializer { @Override From 9baaa17e7041a6bde496662f2cfda5a32038e01a Mon Sep 17 00:00:00 2001 From: Emanuele Scaccia Date: Sun, 6 Feb 2022 02:57:41 +0100 Subject: [PATCH 39/46] other: added TODOs --- .../java/ovh/excale/vgreeter/commands/core/CommandKeyword.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/ovh/excale/vgreeter/commands/core/CommandKeyword.java b/src/main/java/ovh/excale/vgreeter/commands/core/CommandKeyword.java index 25895dc..2a57d2d 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/core/CommandKeyword.java +++ b/src/main/java/ovh/excale/vgreeter/commands/core/CommandKeyword.java @@ -12,6 +12,8 @@ public enum CommandKeyword { + // TODO: ADD OTHER PARAMETERS (e.g. track_id) + // TODO: CHANGE CASE TO snake_case (track_name) TRACK_NAME("tn", "trackname"), USER_ID("u", "user"); From f5b24a3b8c72022536cc538488d37ffe426f3f46 Mon Sep 17 00:00:00 2001 From: excale Date: Sun, 6 Feb 2022 11:34:53 +0100 Subject: [PATCH 40/46] fix: Removed useless javafx import that made build fail --- .../java/ovh/excale/vgreeter/commands/core/CommandRegister.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/ovh/excale/vgreeter/commands/core/CommandRegister.java b/src/main/java/ovh/excale/vgreeter/commands/core/CommandRegister.java index 026e262..ced713a 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/core/CommandRegister.java +++ b/src/main/java/ovh/excale/vgreeter/commands/core/CommandRegister.java @@ -1,6 +1,5 @@ package ovh.excale.vgreeter.commands.core; -import com.sun.javafx.sg.prism.NGExternalNode; import lombok.SneakyThrows; import net.dv8tion.jda.api.events.GenericEvent; import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; From c5a71ad9ca2f78f5eef2970688f23c456d36a68a Mon Sep 17 00:00:00 2001 From: excale Date: Sun, 6 Feb 2022 11:36:02 +0100 Subject: [PATCH 41/46] Version upgrade (major) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index ac5275c..1511a17 100644 --- a/pom.xml +++ b/pom.xml @@ -13,7 +13,7 @@ ovh.excale vgreeter - 2.6.0 + 2.7.0 VGreeter Let the bot greet your friends when they join vocal chat on Discord! From 4992d7285e22925f1729da4e69abe839a44d3b7e Mon Sep 17 00:00:00 2001 From: Danifascio <300602Daniele> Date: Sun, 6 Feb 2022 12:23:53 +0100 Subject: [PATCH 42/46] prove releases --- pom.xml | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1511a17..5201eb5 100644 --- a/pom.xml +++ b/pom.xml @@ -13,13 +13,17 @@ ovh.excale vgreeter - 2.7.0 + 2.7.0-SNAPSHOT VGreeter Let the bot greet your friends when they join vocal chat on Discord! https://github.com/devExcale/VGreeter jar + + scm:git:${project.url} + + 1.8 8 @@ -129,6 +133,24 @@ 2.5.2 + + org.apache.maven.plugins + maven-scm-plugin + 1.5 + + ${project.url}/tags + ${project.artifactId}.${project.version} + + + + create-tag + + tag + + + + + From 37bd199c4a40f71a09ecd7f0177cf4d940ec47cb Mon Sep 17 00:00:00 2001 From: Excale Date: Sat, 11 Apr 2026 23:54:38 +0200 Subject: [PATCH 43/46] Reworked application for Java 25 and JDA 4 --- pom.xml | 46 ++++++++++------- .../commands/button/CloseEmbedCommand.java | 18 +++---- .../button/TrackIndexButtonCommand.java | 21 ++++---- .../commands/core/AbstractButtonCommand.java | 12 ++--- .../commands/core/AbstractMessageCommand.java | 16 +++--- .../commands/core/AbstractSlashCommand.java | 10 ++-- .../commands/core/CommandBuilder.java | 8 +-- .../commands/core/CommandRegister.java | 8 +-- .../commands/message/RestartCommand.java | 4 +- .../commands/message/TrackUploadCommand.java | 7 +-- .../commands/slash/AltnameCommand.java | 8 +-- .../commands/slash/PlaytestCommand.java | 12 +++-- .../commands/slash/ProbabilityCommand.java | 8 +-- .../commands/slash/TrackDownloadCommand.java | 16 +++--- .../slash/TrackIndexSlashCommand.java | 19 +++---- .../commands/slash/TrackNameCommand.java | 6 +-- .../commands/slash/TrackRemoveCommand.java | 8 +-- .../commands/slash/UploadHelpCommand.java | 6 +-- .../excale/vgreeter/models/GuildModel.java | 8 +-- .../excale/vgreeter/models/TrackModel.java | 2 +- .../ovh/excale/vgreeter/models/UserModel.java | 2 +- .../repositories/GuildRepository.java | 4 +- .../repositories/TrackRepository.java | 4 +- .../vgreeter/repositories/UserRepository.java | 4 +- .../vgreeter/services/DiscordService.java | 38 ++++++++++---- .../services/VoiceChannelHandler.java | 50 +++++++------------ .../ovh/excale/vgreeter/track/TrackIndex.java | 7 ++- .../ovh/excale/vgreeter/utilities/Emojis.java | 12 +++-- .../resources-filtered/application.properties | 1 - 29 files changed, 187 insertions(+), 178 deletions(-) diff --git a/pom.xml b/pom.xml index 5201eb5..220ebed 100644 --- a/pom.xml +++ b/pom.xml @@ -7,13 +7,13 @@ org.springframework.boot spring-boot-starter-parent - 2.5.2 + 4.0.4 ovh.excale vgreeter - 2.7.0-SNAPSHOT + 26.4.0-SNAPSHOT VGreeter Let the bot greet your friends when they join vocal chat on Discord! @@ -25,10 +25,9 @@ - 1.8 - 8 - 8 + 25 UTF-8 + 0.1.8 @@ -47,7 +46,27 @@ net.dv8tion JDA - 4.3.0_277 + 6.4.1 + + + club.minnced + jdave-api + ${jdave.version} + + + club.minnced + jdave-native-win-x86-64 + ${jdave.version} + + + club.minnced + jdave-native-linux-x86-64 + ${jdave.version} + + + club.minnced + jdave-native-linux-aarch64 + ${jdave.version} @@ -66,14 +85,12 @@ ch.qos.logback logback-classic - 1.2.5 com.fasterxml.jackson.core jackson-databind - 2.13.1 @@ -87,27 +104,19 @@ org.postgresql postgresql - 42.2.25 + 42.7.7 org.projectlombok lombok - 1.18.20 + 1.18.44 provided - - - dv8tion - m2-dv8tion - https://m2.dv8tion.net/releases - - - ${project.name}-${project.version} @@ -130,7 +139,6 @@ org.springframework.boot spring-boot-maven-plugin - 2.5.2 diff --git a/src/main/java/ovh/excale/vgreeter/commands/button/CloseEmbedCommand.java b/src/main/java/ovh/excale/vgreeter/commands/button/CloseEmbedCommand.java index 462ec9c..e40af6b 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/button/CloseEmbedCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/button/CloseEmbedCommand.java @@ -1,6 +1,8 @@ package ovh.excale.vgreeter.commands.button; -import net.dv8tion.jda.api.events.interaction.ButtonClickEvent; +import java.util.Collections; + +import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; import net.dv8tion.jda.api.requests.RestAction; import org.jetbrains.annotations.NotNull; import ovh.excale.vgreeter.commands.core.AbstractButtonCommand; @@ -12,15 +14,11 @@ public CloseEmbedCommand() { } @Override - public @NotNull RestAction execute(@NotNull ButtonClickEvent event) { - - // noinspection ConstantConditions - return event.getMessage() - .delete() - .reason("Embed closed by " + event.getUser() - .getAsMention()) - .onErrorFlatMap(t -> event.reply("Cannot close embed") - .map(hook -> null)); + public @NotNull RestAction execute(@NotNull ButtonInteractionEvent event) { + + return event.editMessage("Closed") + .setEmbeds(Collections.emptyList()) + .setComponents(Collections.emptyList()); } diff --git a/src/main/java/ovh/excale/vgreeter/commands/button/TrackIndexButtonCommand.java b/src/main/java/ovh/excale/vgreeter/commands/button/TrackIndexButtonCommand.java index c59b671..0c593be 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/button/TrackIndexButtonCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/button/TrackIndexButtonCommand.java @@ -2,15 +2,17 @@ import lombok.SneakyThrows; import lombok.extern.log4j.Log4j2; -import net.dv8tion.jda.api.events.interaction.ButtonClickEvent; -import net.dv8tion.jda.api.interactions.Interaction; +import net.dv8tion.jda.api.components.actionrow.ActionRow; +import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; +import net.dv8tion.jda.api.interactions.callbacks.IReplyCallback; import net.dv8tion.jda.api.requests.RestAction; -import net.dv8tion.jda.api.requests.restaction.interactions.ReplyAction; import org.jetbrains.annotations.NotNull; import ovh.excale.vgreeter.commands.core.AbstractButtonCommand; import ovh.excale.vgreeter.commands.core.CommandOptions; import ovh.excale.vgreeter.track.TrackIndex; +import java.util.Arrays; + @Log4j2 public class TrackIndexButtonCommand extends AbstractButtonCommand { @@ -20,7 +22,7 @@ public TrackIndexButtonCommand() { @SneakyThrows @Override - public @NotNull RestAction execute(ButtonClickEvent event) { + public @NotNull RestAction execute(ButtonInteractionEvent event) { CommandOptions command = CommandOptions.fromJson(event.getComponentId()); //noinspection DuplicatedCode @@ -40,17 +42,12 @@ public TrackIndexButtonCommand() { if(index.isEmpty()) return replyEphemeralWith("Empty page", event); - //noinspection ConstantConditions - return event.getMessage() - .delete() - .and(event.getChannel() - .sendMessage(index.buildEmbed() - .build()) - .setActionRow(index.buildButtons())); + return event.editMessageEmbeds(index.buildEmbed().build()) + .setComponents(ActionRow.of(Arrays.asList(index.buildButtons()))); } - private static ReplyAction replyEphemeralWith(String message, Interaction event) { + private static RestAction replyEphemeralWith(String message, IReplyCallback event) { return event.reply(message) .setEphemeral(true); } diff --git a/src/main/java/ovh/excale/vgreeter/commands/core/AbstractButtonCommand.java b/src/main/java/ovh/excale/vgreeter/commands/core/AbstractButtonCommand.java index c57b41e..bea6466 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/core/AbstractButtonCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/core/AbstractButtonCommand.java @@ -2,29 +2,29 @@ import com.fasterxml.jackson.core.JsonProcessingException; import net.dv8tion.jda.api.events.GenericEvent; -import net.dv8tion.jda.api.events.interaction.ButtonClickEvent; +import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; import net.dv8tion.jda.api.requests.RestAction; import org.jetbrains.annotations.NotNull; -public abstract class AbstractButtonCommand extends AbstractCommand { +public abstract class AbstractButtonCommand extends AbstractCommand { protected AbstractButtonCommand(String name, String description) { - super(name, description, ButtonClickEvent.class); + super(name, description, ButtonInteractionEvent.class); } @Override - public abstract @NotNull RestAction execute(@NotNull ButtonClickEvent event); + public abstract @NotNull RestAction execute(@NotNull ButtonInteractionEvent event); @Override public boolean accepts(GenericEvent event) { - if(!(event instanceof ButtonClickEvent)) + if(!(event instanceof ButtonInteractionEvent)) return false; CommandOptions command; try { - command = CommandOptions.fromJson(((ButtonClickEvent) event).getComponentId()); + command = CommandOptions.fromJson(((ButtonInteractionEvent) event).getComponentId()); } catch(JsonProcessingException e) { return false; diff --git a/src/main/java/ovh/excale/vgreeter/commands/core/AbstractMessageCommand.java b/src/main/java/ovh/excale/vgreeter/commands/core/AbstractMessageCommand.java index 8a1ad52..d96ca01 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/core/AbstractMessageCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/core/AbstractMessageCommand.java @@ -1,30 +1,34 @@ package ovh.excale.vgreeter.commands.core; import net.dv8tion.jda.api.events.GenericEvent; -import net.dv8tion.jda.api.events.message.priv.PrivateMessageReceivedEvent; +import net.dv8tion.jda.api.events.message.MessageReceivedEvent; import net.dv8tion.jda.api.requests.RestAction; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Locale; -public abstract class AbstractMessageCommand extends AbstractCommand { +public abstract class AbstractMessageCommand extends AbstractCommand { public static final String PREFIX = "vg:"; protected AbstractMessageCommand(String name, String description) { - super(name, description, PrivateMessageReceivedEvent.class); + super(name, description, MessageReceivedEvent.class); } @Override - public abstract @Nullable RestAction execute(@NotNull PrivateMessageReceivedEvent event); + public abstract @Nullable RestAction execute(@NotNull MessageReceivedEvent event); public boolean accepts(GenericEvent event) { - if(!(event instanceof PrivateMessageReceivedEvent)) + if(!(event instanceof MessageReceivedEvent)) return false; - String msgContent = ((PrivateMessageReceivedEvent) event) + MessageReceivedEvent messageEvent = (MessageReceivedEvent) event; + if(messageEvent.isFromGuild()) + return false; + + String msgContent = messageEvent .getMessage() .getContentRaw() .toLowerCase(Locale.ROOT); diff --git a/src/main/java/ovh/excale/vgreeter/commands/core/AbstractSlashCommand.java b/src/main/java/ovh/excale/vgreeter/commands/core/AbstractSlashCommand.java index 1d6dd64..76f4515 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/core/AbstractSlashCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/core/AbstractSlashCommand.java @@ -2,18 +2,18 @@ import lombok.Getter; import net.dv8tion.jda.api.events.GenericEvent; -import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; +import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; import net.dv8tion.jda.api.interactions.commands.build.CommandData; import net.dv8tion.jda.api.requests.RestAction; import org.jetbrains.annotations.NotNull; -public abstract class AbstractSlashCommand extends AbstractCommand { +public abstract class AbstractSlashCommand extends AbstractCommand { @Getter private final CommandBuilder builder; protected AbstractSlashCommand(String name, String description) { - super(name, description, SlashCommandEvent.class); + super(name, description, SlashCommandInteractionEvent.class); builder = CommandBuilder .create(name) @@ -22,11 +22,11 @@ protected AbstractSlashCommand(String name, String description) { } @Override - public abstract @NotNull RestAction execute(SlashCommandEvent event); + public abstract @NotNull RestAction execute(SlashCommandInteractionEvent event); @Override public boolean accepts(GenericEvent event) { - return event instanceof SlashCommandEvent && name.equals(((SlashCommandEvent) event).getName()); + return event instanceof SlashCommandInteractionEvent && name.equals(((SlashCommandInteractionEvent) event).getName()); } public CommandData getData() { diff --git a/src/main/java/ovh/excale/vgreeter/commands/core/CommandBuilder.java b/src/main/java/ovh/excale/vgreeter/commands/core/CommandBuilder.java index fc6f6d6..62989ba 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/core/CommandBuilder.java +++ b/src/main/java/ovh/excale/vgreeter/commands/core/CommandBuilder.java @@ -2,7 +2,9 @@ import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.build.CommandData; +import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData; import net.dv8tion.jda.api.interactions.commands.build.SubcommandData; +import net.dv8tion.jda.api.interactions.commands.build.Commands; import java.util.LinkedList; import java.util.List; @@ -14,7 +16,7 @@ public static CommandBuilderPrototype create(String name) { return new CommandBuilderPrototype(name); } - private final CommandData commandData; + private final SlashCommandData commandData; private final List subcommands; private SubcommandData currentSubcommand; @@ -22,7 +24,7 @@ public static CommandBuilderPrototype create(String name) { private CommandBuilder(String name, String description) { - commandData = new CommandData(name, description); + commandData = Commands.slash(name, description); subcommands = new LinkedList<>(); currentSubcommand = null; @@ -68,7 +70,7 @@ public CommandBuilder subcommand(String name, String description) { return this; } - public CommandData build() { + public SlashCommandData build() { if(subcommand != null && subcommand) commandData.addSubcommands(subcommands); diff --git a/src/main/java/ovh/excale/vgreeter/commands/core/CommandRegister.java b/src/main/java/ovh/excale/vgreeter/commands/core/CommandRegister.java index ced713a..48c8e55 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/core/CommandRegister.java +++ b/src/main/java/ovh/excale/vgreeter/commands/core/CommandRegister.java @@ -2,7 +2,7 @@ import lombok.SneakyThrows; import net.dv8tion.jda.api.events.GenericEvent; -import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; +import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; import net.dv8tion.jda.api.hooks.EventListener; import net.dv8tion.jda.api.interactions.commands.build.CommandData; import net.dv8tion.jda.api.requests.RestAction; @@ -24,11 +24,11 @@ private CommandRegister() { masterRecord = new HashMap<>(); } - public > CommandRegister register(Command command) { + public > CommandRegister register(C command) { Class commandType = command.getTypeClass(); //noinspection unchecked - Set commandSet = (Set) masterRecord.computeIfAbsent(commandType, k -> new HashSet<>()); + Set commandSet = (Set) masterRecord.computeIfAbsent(commandType, k -> new HashSet<>()); commandSet.add(command); if(command.hasListener()) @@ -41,7 +41,7 @@ public > CommandRegister register(Command com public CommandData[] getSlashCommandsData() { //noinspection unchecked - return Optional.ofNullable((Set) masterRecord.get(SlashCommandEvent.class)) + return Optional.ofNullable((Set) masterRecord.get(SlashCommandInteractionEvent.class)) .map(Collection::stream) .orElseGet(Stream::empty) .map(AbstractSlashCommand::getData) diff --git a/src/main/java/ovh/excale/vgreeter/commands/message/RestartCommand.java b/src/main/java/ovh/excale/vgreeter/commands/message/RestartCommand.java index 938dc0c..32517f0 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/message/RestartCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/message/RestartCommand.java @@ -3,7 +3,7 @@ import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.User; -import net.dv8tion.jda.api.events.message.priv.PrivateMessageReceivedEvent; +import net.dv8tion.jda.api.events.message.MessageReceivedEvent; import net.dv8tion.jda.api.requests.RestAction; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -19,7 +19,7 @@ public RestartCommand() { } @Override - public @Nullable RestAction execute(@NotNull final PrivateMessageReceivedEvent event) { + public @Nullable RestAction execute(@NotNull final MessageReceivedEvent event) { Message message = event.getMessage(); ArgumentsParser arguments = new ArgumentsParser(message.getContentRaw()); diff --git a/src/main/java/ovh/excale/vgreeter/commands/message/TrackUploadCommand.java b/src/main/java/ovh/excale/vgreeter/commands/message/TrackUploadCommand.java index 84df117..7e5d2c9 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/message/TrackUploadCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/message/TrackUploadCommand.java @@ -3,7 +3,7 @@ import lombok.extern.log4j.Log4j2; import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.User; -import net.dv8tion.jda.api.events.message.priv.PrivateMessageReceivedEvent; +import net.dv8tion.jda.api.events.message.MessageReceivedEvent; import net.dv8tion.jda.api.requests.RestAction; import org.gagravarr.ogg.OggFile; import org.gagravarr.opus.OpusFile; @@ -49,7 +49,7 @@ public TrackUploadCommand() { } @Override - public @Nullable RestAction execute(@NotNull PrivateMessageReceivedEvent event) { + public @Nullable RestAction execute(@NotNull MessageReceivedEvent event) { // TODO: COMMAND PARAMETERS @@ -89,7 +89,8 @@ public TrackUploadCommand() { try { in = attachment - .retrieveInputStream() + .getProxy() + .download() .join(); } catch(Exception e) { diff --git a/src/main/java/ovh/excale/vgreeter/commands/slash/AltnameCommand.java b/src/main/java/ovh/excale/vgreeter/commands/slash/AltnameCommand.java index a335fab..6e7eed7 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/slash/AltnameCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/slash/AltnameCommand.java @@ -1,10 +1,10 @@ package ovh.excale.vgreeter.commands.slash; import net.dv8tion.jda.api.entities.User; -import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; +import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionType; -import net.dv8tion.jda.api.requests.restaction.interactions.ReplyAction; +import net.dv8tion.jda.api.requests.RestAction; import ovh.excale.vgreeter.VGreeterApplication; import ovh.excale.vgreeter.commands.core.AbstractSlashCommand; import ovh.excale.vgreeter.models.UserModel; @@ -31,9 +31,9 @@ public AltnameCommand() { } @Override - public ReplyAction execute(SlashCommandEvent event) { + public RestAction execute(SlashCommandInteractionEvent event) { - ReplyAction reply; + RestAction reply; User user = event.getUser(); String name = Optional.ofNullable(event.getOption("username")) diff --git a/src/main/java/ovh/excale/vgreeter/commands/slash/PlaytestCommand.java b/src/main/java/ovh/excale/vgreeter/commands/slash/PlaytestCommand.java index fe77d5c..3be7ae1 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/slash/PlaytestCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/slash/PlaytestCommand.java @@ -3,12 +3,12 @@ import lombok.extern.log4j.Log4j2; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.Member; -import net.dv8tion.jda.api.entities.VoiceChannel; -import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; +import net.dv8tion.jda.api.entities.channel.unions.AudioChannelUnion; +import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; import net.dv8tion.jda.api.exceptions.InsufficientPermissionException; import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.managers.AudioManager; -import net.dv8tion.jda.api.requests.restaction.interactions.ReplyAction; +import net.dv8tion.jda.api.requests.RestAction; import ovh.excale.vgreeter.VGreeterApplication; import ovh.excale.vgreeter.commands.core.AbstractSlashCommand; import ovh.excale.vgreeter.models.TrackModel; @@ -31,7 +31,7 @@ public PlaytestCommand() { } @Override - public ReplyAction execute(SlashCommandEvent event) { + public RestAction execute(SlashCommandInteractionEvent event) { Guild guild = event.getGuild(); Member member = event.getMember(); @@ -46,7 +46,7 @@ public ReplyAction execute(SlashCommandEvent event) { .setEphemeral(true); //noinspection ConstantConditions - VoiceChannel channel = member.getVoiceState() + AudioChannelUnion channel = member.getVoiceState() .getChannel(); if(channel == null) @@ -82,6 +82,8 @@ public ReplyAction execute(SlashCommandEvent event) { audioManager.openAudioConnection(channel); guildLocks.add(guild.getIdLong()); } catch(InsufficientPermissionException ignored) { + return event.reply("The bot is missing permission to connect or speak in that voice channel") + .setEphemeral(true); } return event.reply("Playing track `#" + trackId + "`") diff --git a/src/main/java/ovh/excale/vgreeter/commands/slash/ProbabilityCommand.java b/src/main/java/ovh/excale/vgreeter/commands/slash/ProbabilityCommand.java index c65dae7..f143f1b 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/slash/ProbabilityCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/slash/ProbabilityCommand.java @@ -3,10 +3,10 @@ import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.Member; -import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; +import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionType; -import net.dv8tion.jda.api.requests.restaction.interactions.ReplyAction; +import net.dv8tion.jda.api.requests.RestAction; import ovh.excale.vgreeter.VGreeterApplication; import ovh.excale.vgreeter.commands.core.AbstractSlashCommand; import ovh.excale.vgreeter.models.GuildModel; @@ -33,7 +33,7 @@ public ProbabilityCommand() { } @Override - public ReplyAction execute(SlashCommandEvent event) { + public RestAction execute(SlashCommandInteractionEvent event) { Guild guild = event.getGuild(); @@ -49,7 +49,7 @@ public ReplyAction execute(SlashCommandEvent event) { .build()); int prevProbab = guildModel.getJoinProbability(); - ReplyAction reply; + RestAction reply; String subcommand = Optional.ofNullable(event.getSubcommandName()) .orElse(""); diff --git a/src/main/java/ovh/excale/vgreeter/commands/slash/TrackDownloadCommand.java b/src/main/java/ovh/excale/vgreeter/commands/slash/TrackDownloadCommand.java index 05c5029..178a3e2 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/slash/TrackDownloadCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/slash/TrackDownloadCommand.java @@ -1,12 +1,10 @@ package ovh.excale.vgreeter.commands.slash; -import net.dv8tion.jda.api.MessageBuilder; import net.dv8tion.jda.api.entities.Guild; -import net.dv8tion.jda.api.entities.Message; -import net.dv8tion.jda.api.entities.MessageChannel; -import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; +import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; import net.dv8tion.jda.api.interactions.commands.OptionType; -import net.dv8tion.jda.api.requests.restaction.interactions.ReplyAction; +import net.dv8tion.jda.api.requests.RestAction; +import net.dv8tion.jda.api.utils.FileUpload; import ovh.excale.vgreeter.VGreeterApplication; import ovh.excale.vgreeter.commands.core.AbstractSlashCommand; import ovh.excale.vgreeter.models.TrackModel; @@ -32,10 +30,9 @@ public TrackDownloadCommand() { // TODO: 30sec cooldown (whole-guild scope) on download, probably with stopwatch and queue @Override - public ReplyAction execute(SlashCommandEvent event) { + public RestAction execute(SlashCommandInteractionEvent event) { Guild guild = event.getGuild(); - MessageChannel channel = event.getChannel(); if(guild == null) return event.reply("This command can be executed in a guild only") @@ -52,10 +49,9 @@ public ReplyAction execute(SlashCommandEvent event) { .setEphemeral(true); TrackModel track = opt.get(); - Message message = new MessageBuilder(String.format("Track `#%d`", track.getId())).build(); - return event.reply(message) - .addFile(track.getData(), track.getName() + ".opus"); + return event.reply(String.format("Track `#%d`", track.getId())) + .addFiles(FileUpload.fromData(track.getData(), track.getName() + ".opus")); } diff --git a/src/main/java/ovh/excale/vgreeter/commands/slash/TrackIndexSlashCommand.java b/src/main/java/ovh/excale/vgreeter/commands/slash/TrackIndexSlashCommand.java index ae53030..3ee1c74 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/slash/TrackIndexSlashCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/slash/TrackIndexSlashCommand.java @@ -1,18 +1,18 @@ package ovh.excale.vgreeter.commands.slash; import lombok.extern.log4j.Log4j2; -import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; -import net.dv8tion.jda.api.interactions.Interaction; +import net.dv8tion.jda.api.components.actionrow.ActionRow; +import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; +import net.dv8tion.jda.api.interactions.callbacks.IReplyCallback; import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.requests.RestAction; -import net.dv8tion.jda.api.requests.restaction.interactions.ReplyAction; import org.jetbrains.annotations.NotNull; import ovh.excale.vgreeter.commands.core.AbstractSlashCommand; -import ovh.excale.vgreeter.commands.core.CommandKeyword; import ovh.excale.vgreeter.commands.core.CommandOptions; import ovh.excale.vgreeter.track.TrackIndex; +import java.util.Arrays; import java.util.Optional; import static ovh.excale.vgreeter.commands.core.CommandKeyword.TRACK_NAME; @@ -41,7 +41,7 @@ public TrackIndexSlashCommand() { } @Override - public @NotNull RestAction execute(SlashCommandEvent event) { + public @NotNull RestAction execute(SlashCommandInteractionEvent event) { int page = Optional.ofNullable(event.getOption("page")) .map(OptionMapping::getAsLong) @@ -70,16 +70,13 @@ public TrackIndexSlashCommand() { if(index.isEmpty()) return replyEphemeralWith("Empty page", event); - return event.reply("Here's your track index") + return event.replyEmbeds(index.buildEmbed().build()) .setEphemeral(true) - .and(event.getChannel() - .sendMessage(index.buildEmbed() - .build()) - .setActionRow(index.buildButtons())); + .addComponents(ActionRow.of(Arrays.asList(index.buildButtons()))); } - private static ReplyAction replyEphemeralWith(String message, Interaction event) { + private static RestAction replyEphemeralWith(String message, IReplyCallback event) { return event.reply(message) .setEphemeral(true); } diff --git a/src/main/java/ovh/excale/vgreeter/commands/slash/TrackNameCommand.java b/src/main/java/ovh/excale/vgreeter/commands/slash/TrackNameCommand.java index 94a85ce..e437a6f 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/slash/TrackNameCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/slash/TrackNameCommand.java @@ -1,9 +1,9 @@ package ovh.excale.vgreeter.commands.slash; import net.dv8tion.jda.api.entities.User; -import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; +import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; import net.dv8tion.jda.api.interactions.commands.OptionType; -import net.dv8tion.jda.api.requests.restaction.interactions.ReplyAction; +import net.dv8tion.jda.api.requests.RestAction; import ovh.excale.vgreeter.VGreeterApplication; import ovh.excale.vgreeter.commands.core.AbstractSlashCommand; import ovh.excale.vgreeter.models.TrackModel; @@ -33,7 +33,7 @@ public TrackNameCommand() { } @Override - public ReplyAction execute(SlashCommandEvent event) { + public RestAction execute(SlashCommandInteractionEvent event) { //noinspection ConstantConditions long trackId = Long.parseLong(event.getOption("trackid") diff --git a/src/main/java/ovh/excale/vgreeter/commands/slash/TrackRemoveCommand.java b/src/main/java/ovh/excale/vgreeter/commands/slash/TrackRemoveCommand.java index 5209ad3..ad00c7a 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/slash/TrackRemoveCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/slash/TrackRemoveCommand.java @@ -1,9 +1,9 @@ package ovh.excale.vgreeter.commands.slash; import net.dv8tion.jda.api.entities.User; -import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; +import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; import net.dv8tion.jda.api.interactions.commands.OptionType; -import net.dv8tion.jda.api.requests.restaction.interactions.ReplyAction; +import net.dv8tion.jda.api.requests.RestAction; import ovh.excale.vgreeter.VGreeterApplication; import ovh.excale.vgreeter.commands.core.AbstractSlashCommand; import ovh.excale.vgreeter.models.TrackModel; @@ -28,9 +28,9 @@ public TrackRemoveCommand() { } @Override - public ReplyAction execute(SlashCommandEvent event) { + public RestAction execute(SlashCommandInteractionEvent event) { - ReplyAction reply; + RestAction reply; User user = event.getUser(); //noinspection ConstantConditions diff --git a/src/main/java/ovh/excale/vgreeter/commands/slash/UploadHelpCommand.java b/src/main/java/ovh/excale/vgreeter/commands/slash/UploadHelpCommand.java index c125ebf..4948774 100644 --- a/src/main/java/ovh/excale/vgreeter/commands/slash/UploadHelpCommand.java +++ b/src/main/java/ovh/excale/vgreeter/commands/slash/UploadHelpCommand.java @@ -1,7 +1,7 @@ package ovh.excale.vgreeter.commands.slash; -import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; -import net.dv8tion.jda.api.requests.restaction.interactions.ReplyAction; +import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; +import net.dv8tion.jda.api.requests.RestAction; import ovh.excale.vgreeter.commands.core.AbstractSlashCommand; public class UploadHelpCommand extends AbstractSlashCommand { @@ -11,7 +11,7 @@ public UploadHelpCommand() { } @Override - public ReplyAction execute(SlashCommandEvent event) { + public RestAction execute(SlashCommandInteractionEvent event) { //noinspection StringBufferReplaceableByString StringBuilder sb = new StringBuilder(); diff --git a/src/main/java/ovh/excale/vgreeter/models/GuildModel.java b/src/main/java/ovh/excale/vgreeter/models/GuildModel.java index ab0977f..d657eb2 100644 --- a/src/main/java/ovh/excale/vgreeter/models/GuildModel.java +++ b/src/main/java/ovh/excale/vgreeter/models/GuildModel.java @@ -2,10 +2,10 @@ import lombok.*; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.Table; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Table; @Builder @AllArgsConstructor diff --git a/src/main/java/ovh/excale/vgreeter/models/TrackModel.java b/src/main/java/ovh/excale/vgreeter/models/TrackModel.java index 769ec2b..8312332 100644 --- a/src/main/java/ovh/excale/vgreeter/models/TrackModel.java +++ b/src/main/java/ovh/excale/vgreeter/models/TrackModel.java @@ -3,7 +3,7 @@ import lombok.*; import org.gagravarr.ogg.OggPacketReader; -import javax.persistence.*; +import jakarta.persistence.*; import java.io.ByteArrayInputStream; import java.sql.Timestamp; import java.time.Instant; diff --git a/src/main/java/ovh/excale/vgreeter/models/UserModel.java b/src/main/java/ovh/excale/vgreeter/models/UserModel.java index 9c00987..f966e17 100644 --- a/src/main/java/ovh/excale/vgreeter/models/UserModel.java +++ b/src/main/java/ovh/excale/vgreeter/models/UserModel.java @@ -2,7 +2,7 @@ import lombok.*; -import javax.persistence.*; +import jakarta.persistence.*; import java.util.Set; @Builder diff --git a/src/main/java/ovh/excale/vgreeter/repositories/GuildRepository.java b/src/main/java/ovh/excale/vgreeter/repositories/GuildRepository.java index ef3a6e4..2ca7c51 100644 --- a/src/main/java/ovh/excale/vgreeter/repositories/GuildRepository.java +++ b/src/main/java/ovh/excale/vgreeter/repositories/GuildRepository.java @@ -1,10 +1,10 @@ package ovh.excale.vgreeter.repositories; -import org.springframework.data.repository.CrudRepository; +import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; import ovh.excale.vgreeter.models.GuildModel; @Repository -public interface GuildRepository extends CrudRepository { +public interface GuildRepository extends JpaRepository { } diff --git a/src/main/java/ovh/excale/vgreeter/repositories/TrackRepository.java b/src/main/java/ovh/excale/vgreeter/repositories/TrackRepository.java index 55a0b3a..8c978fa 100644 --- a/src/main/java/ovh/excale/vgreeter/repositories/TrackRepository.java +++ b/src/main/java/ovh/excale/vgreeter/repositories/TrackRepository.java @@ -3,13 +3,13 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.PagingAndSortingRepository; +import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; import ovh.excale.vgreeter.models.TrackModel; import ovh.excale.vgreeter.models.UserModel; @Repository -public interface TrackRepository extends PagingAndSortingRepository { +public interface TrackRepository extends JpaRepository { boolean existsByNameAndUploader(String name, UserModel uploader); diff --git a/src/main/java/ovh/excale/vgreeter/repositories/UserRepository.java b/src/main/java/ovh/excale/vgreeter/repositories/UserRepository.java index 6f1c23e..662e412 100644 --- a/src/main/java/ovh/excale/vgreeter/repositories/UserRepository.java +++ b/src/main/java/ovh/excale/vgreeter/repositories/UserRepository.java @@ -1,11 +1,11 @@ package ovh.excale.vgreeter.repositories; -import org.springframework.data.repository.CrudRepository; +import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; import ovh.excale.vgreeter.models.UserModel; @Repository -public interface UserRepository extends CrudRepository { +public interface UserRepository extends JpaRepository { boolean existsByAltname(String altname); diff --git a/src/main/java/ovh/excale/vgreeter/services/DiscordService.java b/src/main/java/ovh/excale/vgreeter/services/DiscordService.java index 4799509..ac2187a 100644 --- a/src/main/java/ovh/excale/vgreeter/services/DiscordService.java +++ b/src/main/java/ovh/excale/vgreeter/services/DiscordService.java @@ -2,8 +2,10 @@ import lombok.Getter; import lombok.extern.log4j.Log4j2; +import club.minnced.discord.jdave.interop.JDaveSessionFactory; import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.JDABuilder; +import net.dv8tion.jda.api.audio.AudioModuleConfig; import net.dv8tion.jda.api.entities.Activity; import net.dv8tion.jda.api.interactions.commands.Command; import net.dv8tion.jda.api.requests.GatewayIntent; @@ -21,7 +23,6 @@ import ovh.excale.vgreeter.commands.message.TrackUploadCommand; import ovh.excale.vgreeter.commands.slash.*; -import javax.security.auth.login.LoginException; import java.util.Collections; import java.util.HashSet; import java.util.Set; @@ -36,18 +37,33 @@ public class DiscordService { private final JDA jda; - public DiscordService(VoiceChannelHandler eventHandler, CommandRegister commands, - @Value("${env.DISCORD_TOKEN}") String token) throws LoginException, InterruptedException { + public DiscordService( + VoiceChannelHandler eventHandler, + CommandRegister commands, + @Value("${env.DISCORD_TOKEN}") String token + ) throws InterruptedException { jda = JDABuilder - .create(token, GatewayIntent.GUILD_VOICE_STATES, GatewayIntent.DIRECT_MESSAGES, - GatewayIntent.GUILD_VOICE_STATES) - .disableCache(CacheFlag.ACTIVITY, CacheFlag.ONLINE_STATUS, CacheFlag.CLIENT_STATUS, - CacheFlag.MEMBER_OVERRIDES, CacheFlag.EMOTE) - .setActivity(Activity.listening("people")) - .addEventListeners(eventHandler, commands.getListener()) - .build() - .awaitReady(); + .create( + token, + GatewayIntent.GUILD_VOICE_STATES, + GatewayIntent.DIRECT_MESSAGES, + GatewayIntent.MESSAGE_CONTENT + ) + .disableCache( + CacheFlag.ACTIVITY, + CacheFlag.ONLINE_STATUS, + CacheFlag.CLIENT_STATUS, + CacheFlag.MEMBER_OVERRIDES, + CacheFlag.EMOJI + ) + .setActivity(Activity.listening("people")) + .addEventListeners(eventHandler, commands.getListener()) + .setAudioModuleConfig( + new AudioModuleConfig().withDaveSessionFactory(new JDaveSessionFactory()) + ) + .build() + .awaitReady(); log.info("JDA connected"); diff --git a/src/main/java/ovh/excale/vgreeter/services/VoiceChannelHandler.java b/src/main/java/ovh/excale/vgreeter/services/VoiceChannelHandler.java index 87bb3b9..c281ba6 100644 --- a/src/main/java/ovh/excale/vgreeter/services/VoiceChannelHandler.java +++ b/src/main/java/ovh/excale/vgreeter/services/VoiceChannelHandler.java @@ -4,9 +4,8 @@ import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.SelfUser; import net.dv8tion.jda.api.entities.User; -import net.dv8tion.jda.api.entities.VoiceChannel; -import net.dv8tion.jda.api.events.guild.voice.GuildVoiceJoinEvent; -import net.dv8tion.jda.api.events.guild.voice.GuildVoiceLeaveEvent; +import net.dv8tion.jda.api.entities.channel.unions.AudioChannelUnion; +import net.dv8tion.jda.api.events.guild.voice.GuildVoiceUpdateEvent; import net.dv8tion.jda.api.exceptions.InsufficientPermissionException; import net.dv8tion.jda.api.hooks.ListenerAdapter; import net.dv8tion.jda.api.managers.AudioManager; @@ -38,13 +37,21 @@ public VoiceChannelHandler(GuildRepository guildRepo, TrackService trackService) // TODO: DISABLE VOICE EVENT HANDLING UNDER MAINTENANCE @Override - public void onGuildVoiceJoin(@NotNull GuildVoiceJoinEvent event) { + public void onGuildVoiceUpdate(@NotNull GuildVoiceUpdateEvent event) { Guild guild = event.getGuild(); - User user = event.getMember() - .getUser(); - + User user = event.getMember().getUser(); Set guildLocks = DiscordService.getGuildVoiceLocks(); + + if(event.getChannelLeft() != null) { + SelfUser selfUser = event.getJDA().getSelfUser(); + if(user.getIdLong() == selfUser.getIdLong()) + guildLocks.remove(guild.getIdLong()); + } + + if(event.getChannelJoined() == null) + return; + if(user.isBot() || guildLocks.contains(guild.getIdLong())) return; @@ -52,13 +59,9 @@ public void onGuildVoiceJoin(@NotNull GuildVoiceJoinEvent event) { Optional opt = guildRepo.findById(guild.getIdLong()); if(opt.isPresent()) - joinProbability = opt.get() - .getJoinProbability(); + joinProbability = opt.get().getJoinProbability(); else { - GuildModel guildModel = GuildModel - .builder() - .id(guild.getIdLong()) - .build(); + GuildModel guildModel = GuildModel.builder().id(guild.getIdLong()).build(); joinProbability = guildModel.getJoinProbability(); guildRepo.save(guildModel); } @@ -72,10 +75,8 @@ public void onGuildVoiceJoin(@NotNull GuildVoiceJoinEvent event) { return; } - VoiceChannel channel = event.getChannelJoined(); - AudioManager audioManager = event.getGuild() - .getAudioManager(); - + AudioChannelUnion channel = event.getChannelJoined(); + AudioManager audioManager = guild.getAudioManager(); trackPlayer.setTrackEndAction(audioManager::closeAudioConnection); try { @@ -83,23 +84,10 @@ public void onGuildVoiceJoin(@NotNull GuildVoiceJoinEvent event) { audioManager.openAudioConnection(channel); guildLocks.add(guild.getIdLong()); } catch(InsufficientPermissionException ignored) { + // The bot doesn't have permissions to connect to the Voice Channel, do nothing } } - @Override - public void onGuildVoiceLeave(@NotNull GuildVoiceLeaveEvent event) { - - Guild guild = event.getGuild(); - User user = event.getMember() - .getUser(); - SelfUser selfUser = event.getJDA() - .getSelfUser(); - - Set guildLocks = DiscordService.getGuildVoiceLocks(); - if(user.getIdLong() == selfUser.getIdLong()) - guildLocks.remove(guild.getIdLong()); - - } } diff --git a/src/main/java/ovh/excale/vgreeter/track/TrackIndex.java b/src/main/java/ovh/excale/vgreeter/track/TrackIndex.java index 92669d1..5e98947 100644 --- a/src/main/java/ovh/excale/vgreeter/track/TrackIndex.java +++ b/src/main/java/ovh/excale/vgreeter/track/TrackIndex.java @@ -4,8 +4,7 @@ import lombok.Setter; import lombok.SneakyThrows; import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.interactions.components.Button; -import net.dv8tion.jda.api.interactions.components.Component; +import net.dv8tion.jda.api.components.buttons.Button; import org.jetbrains.annotations.NotNull; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; @@ -131,7 +130,7 @@ public void fetch() throws IllegalArgumentException { } @SneakyThrows - public Component[] buildButtons() { + public Button[] buildButtons() { trackPageCheck(); @@ -155,7 +154,7 @@ public Component[] buildButtons() { CommandOptions closeCommand = new CommandOptions("close"); Button closeButton = Button.secondary(closeCommand.json(), Emojis.CLOSE); - return new Component[] { prevButton, nextButton, reloadButton, closeButton }; + return new Button[] { prevButton, nextButton, reloadButton, closeButton }; } diff --git a/src/main/java/ovh/excale/vgreeter/utilities/Emojis.java b/src/main/java/ovh/excale/vgreeter/utilities/Emojis.java index 2c4c512..39348cd 100644 --- a/src/main/java/ovh/excale/vgreeter/utilities/Emojis.java +++ b/src/main/java/ovh/excale/vgreeter/utilities/Emojis.java @@ -1,15 +1,17 @@ package ovh.excale.vgreeter.utilities; -import net.dv8tion.jda.api.entities.Emoji; +import lombok.NoArgsConstructor; +import net.dv8tion.jda.api.entities.emoji.Emoji; +@NoArgsConstructor(access = lombok.AccessLevel.PRIVATE) public class Emojis { - public static final Emoji PREVIOUS = Emoji.fromUnicode("\u25C0"); + public static final Emoji PREVIOUS = Emoji.fromUnicode("◀"); - public static final Emoji NEXT = Emoji.fromUnicode("\u25B6"); + public static final Emoji NEXT = Emoji.fromUnicode("▶"); - public static final Emoji RELOAD = Emoji.fromUnicode("U+1F504"); + public static final Emoji RELOAD = Emoji.fromUnicode("🔄"); - public static final Emoji CLOSE = Emoji.fromUnicode("U+1F1FD"); + public static final Emoji CLOSE = Emoji.fromUnicode("❌"); } diff --git a/src/main/resources-filtered/application.properties b/src/main/resources-filtered/application.properties index 158743f..4224120 100644 --- a/src/main/resources-filtered/application.properties +++ b/src/main/resources-filtered/application.properties @@ -6,7 +6,6 @@ spring.datasource.username: ${env.DATASOURCE_USERNAME} spring.datasource.password: ${env.DATASOURCE_PASSWORD} spring.datasource.hikari.keepalive-time: 30000 spring.datasource.driver-class-name: org.postgresql.Driver -spring.jpa.database-platform: org.hibernate.dialect.PostgreSQL10Dialect # Custom properties application.name: @project.name@ From ff2ab2902203dddcccd9adc60a19715bc73791af Mon Sep 17 00:00:00 2001 From: Excale Date: Sun, 12 Apr 2026 16:52:41 +0200 Subject: [PATCH 44/46] ci: PR Validation, Release & Publish --- .github/workflows/pr-validation.yml | 25 +++++++++++++ .github/workflows/release-publish.yml | 54 +++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 .github/workflows/pr-validation.yml create mode 100644 .github/workflows/release-publish.yml diff --git a/.github/workflows/pr-validation.yml b/.github/workflows/pr-validation.yml new file mode 100644 index 0000000..8f6f94a --- /dev/null +++ b/.github/workflows/pr-validation.yml @@ -0,0 +1,25 @@ +name: PR Validation + +on: + pull_request: + branches: + - master + +jobs: + test: + runs-on: ubuntu-latest + + steps: + + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up JDK 25 + uses: actions/setup-java@v4 + with: + java-version: '25' + distribution: 'temurin' + cache: 'maven' + + - name: Run Maven Tests + run: mvn clean test diff --git a/.github/workflows/release-publish.yml b/.github/workflows/release-publish.yml new file mode 100644 index 0000000..591228d --- /dev/null +++ b/.github/workflows/release-publish.yml @@ -0,0 +1,54 @@ +name: Release & Publish + +on: + pull_request: + types: + - closed + branches: + - master + +jobs: + release: + if: github.event.pull_request.merged == true && github.head_ref == 'develop' + runs-on: ubuntu-latest + + steps: + + - name: Checkout master branch + uses: actions/checkout@v4 + with: + ref: master + token: ${{ secrets.PAT_TOKEN }} + + - name: Set up JDK 25 + uses: actions/setup-java@v4 + with: + java-version: '25' + distribution: 'temurin' + cache: 'maven' + + - name: Remove SNAPSHOT from POM + id: bump_version + run: | + mvn versions:set -DremoveSnapshot=true -DgenerateBackupPoms=false + NEW_VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout) + echo "VERSION=$NEW_VERSION" >> $GITHUB_ENV + + - name: Commit and Push to Master + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git commit -am "chore: release version ${{ env.VERSION }}" + git push origin master + + - name: Package Application + # Tests are skipped because they already passed in the PR Validation workflow + run: mvn clean package -DskipTests + + - name: Publish GitHub Release + uses: softprops/action-gh-release@v2 + with: + tag_name: v${{ env.VERSION }} + name: Release v${{ env.VERSION }} + files: target/*.jar + generate_release_notes: true From 756c8487fdae062e28c4c1423f179d3ee092361a Mon Sep 17 00:00:00 2001 From: Excale Date: Sun, 12 Apr 2026 16:59:12 +0200 Subject: [PATCH 45/46] refactor: Implement correctly lombok builder defaults (@Builder.Default) --- .../java/ovh/excale/vgreeter/models/GuildModel.java | 10 ++-------- .../java/ovh/excale/vgreeter/models/TrackModel.java | 8 +------- .../java/ovh/excale/vgreeter/models/UserModel.java | 8 +------- 3 files changed, 4 insertions(+), 22 deletions(-) diff --git a/src/main/java/ovh/excale/vgreeter/models/GuildModel.java b/src/main/java/ovh/excale/vgreeter/models/GuildModel.java index d657eb2..4cae578 100644 --- a/src/main/java/ovh/excale/vgreeter/models/GuildModel.java +++ b/src/main/java/ovh/excale/vgreeter/models/GuildModel.java @@ -23,15 +23,9 @@ public class GuildModel { @Column(name = "id_guild") private Long id; + @Builder.Default @Column(name = "join_probability") private Integer joinProbability = DEFAULT_JOIN_PROBABILITY; - @SuppressWarnings("unused") - public static class GuildModelBuilder { - - @SuppressWarnings({ "FieldMayBeFinal", "unused" }) - private Integer joinProbability = DEFAULT_JOIN_PROBABILITY; - - } - } + diff --git a/src/main/java/ovh/excale/vgreeter/models/TrackModel.java b/src/main/java/ovh/excale/vgreeter/models/TrackModel.java index 8312332..2164565 100644 --- a/src/main/java/ovh/excale/vgreeter/models/TrackModel.java +++ b/src/main/java/ovh/excale/vgreeter/models/TrackModel.java @@ -30,6 +30,7 @@ public class TrackModel { @Basic private Long size; + @Builder.Default @Basic private Timestamp uploadDate = Timestamp.from(Instant.now()); @@ -49,12 +50,5 @@ public OggPacketReader getPacketReader() { return new OggPacketReader(new ByteArrayInputStream(getData())); } - @SuppressWarnings("unused") - public static class TrackModelBuilder { - - @SuppressWarnings({ "FieldMayBeFinal", "unused" }) - private Timestamp uploadDate = Timestamp.from(Instant.now()); - - } } diff --git a/src/main/java/ovh/excale/vgreeter/models/UserModel.java b/src/main/java/ovh/excale/vgreeter/models/UserModel.java index f966e17..fe81fdf 100644 --- a/src/main/java/ovh/excale/vgreeter/models/UserModel.java +++ b/src/main/java/ovh/excale/vgreeter/models/UserModel.java @@ -21,6 +21,7 @@ public class UserModel { @Basic private String altname; + @Builder.Default @Basic @Column(name = "tracks_max") private Integer trackMaxSize = 64 * 1024; @@ -29,12 +30,5 @@ public class UserModel { @OneToMany(fetch = FetchType.LAZY, mappedBy = "uploader") private Set tracks; - @SuppressWarnings("unused") - public static class UserModelBuilder { - - @SuppressWarnings({ "FieldMayBeFinal", "unused" }) - private Integer trackMaxSize = 64 * 1024; - - } } From 94f6d4fdd53a4647e4a43a5ff5f7c16c300d01a3 Mon Sep 17 00:00:00 2001 From: Excale Date: Sun, 12 Apr 2026 16:59:24 +0200 Subject: [PATCH 46/46] refactor: Update Maven configuration for compiler and remove unused SCM plugin --- pom.xml | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/pom.xml b/pom.xml index 220ebed..2f68f52 100644 --- a/pom.xml +++ b/pom.xml @@ -124,9 +124,6 @@ src/main/resources false - - - src/main/resources-filtered @@ -136,27 +133,31 @@ - - org.springframework.boot - spring-boot-maven-plugin - - org.apache.maven.plugins - maven-scm-plugin - 1.5 + maven-compiler-plugin + 3.14.1 - ${project.url}/tags - ${project.artifactId}.${project.version} + ${java.version} + full + + + org.projectlombok + lombok + 1.18.44 + + + org.springframework.boot + spring-boot-configuration-processor + ${project.parent.version} + + - - - create-tag - - tag - - - + + + + org.springframework.boot + spring-boot-maven-plugin