From b4c80fe56a4e307be7cb0930736747c019eca76c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beatrice=20Dellac=C3=A0?= Date: Tue, 20 Dec 2022 02:17:27 +0100 Subject: [PATCH] Make urban command support slash too --- .../wtf/beatrice/hidekobot/HidekoBot.java | 1 + .../commands/base/UrbanDictionary.java | 357 ++++++++++++++++++ .../message/UrbanDictionaryCommand.java | 269 +------------ .../commands/slash/MagicBallCommand.java | 2 - .../slash/UrbanDictionaryCommand.java | 84 +++++ .../listeners/ButtonInteractionListener.java | 7 +- 6 files changed, 464 insertions(+), 256 deletions(-) create mode 100644 src/main/java/wtf/beatrice/hidekobot/commands/base/UrbanDictionary.java create mode 100644 src/main/java/wtf/beatrice/hidekobot/commands/slash/UrbanDictionaryCommand.java diff --git a/src/main/java/wtf/beatrice/hidekobot/HidekoBot.java b/src/main/java/wtf/beatrice/hidekobot/HidekoBot.java index dbf2bc1..94913a3 100644 --- a/src/main/java/wtf/beatrice/hidekobot/HidekoBot.java +++ b/src/main/java/wtf/beatrice/hidekobot/HidekoBot.java @@ -124,6 +124,7 @@ public class HidekoBot slashCommandListener.registerCommand(new MagicBallCommand()); slashCommandListener.registerCommand(new PingCommand()); slashCommandListener.registerCommand(new SayCommand()); + slashCommandListener.registerCommand(new UrbanDictionaryCommand()); Cache.setSlashCommandListener(slashCommandListener); Cache.setSlashCommandCompletionListener(slashCommandCompletionListener); diff --git a/src/main/java/wtf/beatrice/hidekobot/commands/base/UrbanDictionary.java b/src/main/java/wtf/beatrice/hidekobot/commands/base/UrbanDictionary.java new file mode 100644 index 0000000..e933537 --- /dev/null +++ b/src/main/java/wtf/beatrice/hidekobot/commands/base/UrbanDictionary.java @@ -0,0 +1,357 @@ +package wtf.beatrice.hidekobot.commands.base; + +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.entities.MessageEmbed; +import net.dv8tion.jda.api.entities.User; +import net.dv8tion.jda.api.entities.emoji.Emoji; +import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; +import net.dv8tion.jda.api.interactions.components.ActionRow; +import net.dv8tion.jda.api.interactions.components.ItemComponent; +import net.dv8tion.jda.api.interactions.components.buttons.Button; +import org.apache.commons.lang3.SerializationException; +import org.apache.commons.text.StringEscapeUtils; +import org.apache.commons.text.WordUtils; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; +import wtf.beatrice.hidekobot.Cache; +import wtf.beatrice.hidekobot.datasources.DatabaseSource; + +import java.io.*; +import java.util.*; + +public class UrbanDictionary +{ + + public static LinkedList getCommandLabels() + { return new LinkedList<>(Arrays.asList("urban", "urbandictionary", "ud")); } + + + public static String getBaseUrl() { + return "https://www.urbandictionary.com/define.php?term="; + } + + public static Button getPreviousPageButton() + { + return Button.primary("urban_previouspage", "Back") + .withEmoji(Emoji.fromFormatted("⬅️")); + } + + public static Button getNextPageButton() + { + return Button.primary("urban_nextpage", "Next") + .withEmoji(Emoji.fromFormatted("➡️")); + } + + public static Button getDeleteButton() + { + return Button.danger("urban_delete", "Delete") + .withEmoji(Emoji.fromFormatted("\uD83D\uDDD1️")); + } + + public static String getNoArgsError() { + return "\uD83D\uDE22 I need to know what to search for!"; + } + + public static String sanitizeArgs(String term, boolean forUrl) + { + term = term.replaceAll("[^\\d\\w\\s]", ""); // only keep letters, numbers and spaces + term = WordUtils.capitalizeFully(term); // Make Every Word Start With A Capital Letter + if(forUrl) term = term.replaceAll("\\s+", "+"); // replace all whitespaces with + for the url + if (term.length() > 64) term = term.substring(0, 64); // cut it to length to avoid abuse + return term; + } + + public static String generateUrl(String term) + { + return getBaseUrl() + sanitizeArgs(term, true); + } + + public static MessageEmbed buildEmbed(String term, + String url, + User author, + UrbanSearch search, + int page) + { + + EmbedBuilder embedBuilder = new EmbedBuilder(); + embedBuilder.setColor(Cache.getBotColor()); + embedBuilder.setTitle(term + ", on Urban Dictionary", url); + embedBuilder.setAuthor(author.getAsTag(), null, author.getAvatarUrl()); + embedBuilder.addField("Definition", search.getPlaintextMeanings().get(page), false); + embedBuilder.addField("Example", search.getPlaintextExamples().get(page), false); + embedBuilder.addField("Submission", + "*Entry " + (page+1) + " | Sent by " + search.getContributorsNames().get(page) + + " on " + search.getSubmissionDates().get(page) + "*", + false); + + return embedBuilder.build(); + } + + public static String serialize(List dataList) { + + try (ByteArrayOutputStream bo = new ByteArrayOutputStream(); + ObjectOutputStream so = new ObjectOutputStream(bo)) { + so.writeObject(dataList); + so.flush(); + return Base64.getEncoder().encodeToString(bo.toByteArray()); + } + catch (IOException ignored) {} + return null; + } + + public static LinkedList deserialize(String dataStr) { + + byte[] b = Base64.getDecoder().decode(dataStr); + ByteArrayInputStream bi = new ByteArrayInputStream(b); + ObjectInputStream si; + try { + si = new ObjectInputStream(bi); + return LinkedList.class.cast(si.readObject()); + } + catch (IOException | ClassNotFoundException e) { + throw new SerializationException("Error during deserialization", e); + } + } + + public static String getNoTermFoundError() + { + return "\uD83D\uDE22 I couldn't find that term!"; + } + + + public static void delete(ButtonInteractionEvent event) + { + String messageId = event.getMessageId(); + DatabaseSource database = Cache.getDatabaseSource(); + + // check if the user interacting is the same one who ran the command + if (!(database.isUserTrackedFor(event.getUser().getId(), messageId))) { + event.reply("❌ You did not run this command!").setEphemeral(true).queue(); + return; + } + + event.getInteraction().getMessage().delete().queue(); + } + + public static void track(Message message, User user, UrbanSearch search, String sanitizedTerm) + { + Cache.getDatabaseSource().queueDisabling(message); + Cache.getDatabaseSource().trackRanCommandReply(message, user); + Cache.getDatabaseSource().trackUrban(search.getSerializedMeanings(), + search.getSerializedExamples(), + search.getSerializedContributors(), + search.getSerializedDates(), + message, + sanitizedTerm); + } + + + public static void changePage(ButtonInteractionEvent event, boolean increase) + { + String messageId = event.getMessageId(); + DatabaseSource database = Cache.getDatabaseSource(); + + // check if the user interacting is the same one who ran the command + if (!(database.isUserTrackedFor(event.getUser().getId(), messageId))) { + event.reply("❌ You did not run this command!").setEphemeral(true).queue(); + return; + } + + // get current page and calculate how many pages there are + int page = Cache.getDatabaseSource().getUrbanPage(messageId); + + String term = database.getUrbanTerm(messageId); + String url = generateUrl(term); + + // get serialized parameters + String serializedMeanings = database.getUrbanMeanings(messageId); + String serializedExamples = database.getUrbanExamples(messageId); + String serializedContributors = database.getUrbanContributors(messageId); + String serializedDates = database.getUrbanDates(messageId); + + // construct object by passing serialized parameters + UrbanSearch search = new UrbanSearch(serializedMeanings, + serializedExamples, serializedContributors, serializedDates); + + // move to new page + if(increase) + page++; + else page--; + + term = UrbanDictionary.sanitizeArgs(term, false); + + // generate embed with new results + MessageEmbed updatedEmbed = UrbanDictionary.buildEmbed(term, url, event.getUser(), search, page); + + // get all attached components and check which ones need to be enabled or disabled + List components = new ArrayList<>(); + + if(page > 0) + { + components.add(UrbanDictionary.getPreviousPageButton().asEnabled()); + } else { + components.add(UrbanDictionary.getPreviousPageButton().asDisabled()); + } + + if(page + 1 == search.getPages()) + { + components.add(UrbanDictionary.getNextPageButton().asDisabled()); + } else { + components.add(UrbanDictionary.getNextPageButton().asEnabled()); + } + + // update the components on the object + components.add(UrbanDictionary.getDeleteButton()); + ActionRow currentRow = ActionRow.of(components); + + // update the message + event.editComponents(currentRow).setEmbeds(updatedEmbed).queue(); + database.setUrbanPage(messageId, page); + database.resetExpiryTimestamp(messageId); + } + + public static class UrbanSearch + { + final LinkedList plaintextMeanings; + final LinkedList plaintextExamples; + final LinkedList contributorsNames; + final LinkedList submissionDates; + + final String serializedMeanings; + final String serializedExamples; + final String serializedContributors; + final String serializedDates; + + final int pages; + + public UrbanSearch(String serializedMeanings, + String serializedExamples, + String serializedContributors, + String serializedDates) + { + this.serializedMeanings = serializedMeanings; + this.serializedExamples = serializedExamples; + this.serializedContributors = serializedContributors; + this.serializedDates = serializedDates; + + this.plaintextMeanings = UrbanDictionary.deserialize(serializedMeanings); + this.plaintextExamples = UrbanDictionary.deserialize(serializedExamples); + this.contributorsNames = UrbanDictionary.deserialize(serializedContributors); + this.submissionDates = UrbanDictionary.deserialize(serializedDates); + + this.pages = submissionDates.size(); + } + + public UrbanSearch(Elements definitions) + { + plaintextMeanings = new LinkedList<>(); + plaintextExamples = new LinkedList<>(); + contributorsNames = new LinkedList<>(); + submissionDates = new LinkedList<>(); + + for(Element definition : definitions) + { + Elements meaningSingleton = definition.getElementsByClass("meaning"); + if(meaningSingleton.isEmpty()) + { + plaintextMeanings.add(" "); + } else + { + Element meaning = meaningSingleton.get(0); + String text = meaning.html() + .replaceAll("", "\n") // keep newlines + .replaceAll("<.*?>", ""); // remove all other html tags + // this is used to fix eg. & being shown literally instead of being parsed + text = StringEscapeUtils.unescapeHtml4(text); + // discord only allows 1024 characters for embed fields + if(text.length() > 1024) text = text.substring(0, 1020) + "..."; + plaintextMeanings.add(text); + } + + Elements exampleSingleton = definition.getElementsByClass("example"); + + if(exampleSingleton.isEmpty()) + { + plaintextExamples.add(" "); + } else + { + Element example = exampleSingleton.get(0); + String text = example.html() + .replaceAll("", "\n") // keep newlines + .replaceAll("<.*?>", ""); // remove all other html tags + // this is used to fix eg. & being shown literally instead of being parsed + text = StringEscapeUtils.unescapeHtml4(text); + // discord only allows 1024 characters for embed fields + if(text.length() > 1024) text = text.substring(0, 1020) + "..."; + plaintextExamples.add(text); + } + + Elements contributorSingleton = definition.getElementsByClass("contributor"); + if(contributorSingleton.isEmpty()) + { + contributorsNames.add("Unknown"); + } else + { + Element contributor = contributorSingleton.get(0); + + String htmlContributor = contributor.html(); + String htmlContributorName = contributor.select("a").html(); + String htmlSubmitDate = htmlContributor.substring( + htmlContributor.indexOf("") + 4); + + contributorsNames.add(htmlContributorName + .replaceAll("<.*?>", "")); // remove all html tags; + + submissionDates.add(htmlSubmitDate + .replaceAll("<.*?>", "")); // remove all html tags; + } + } + + serializedMeanings = serialize(plaintextMeanings); + serializedExamples = serialize(plaintextExamples); + serializedContributors = serialize(contributorsNames); + serializedDates = serialize(submissionDates); + + pages = submissionDates.size(); + } + + public List getPlaintextMeanings() { + return this.plaintextMeanings; + } + + public List getPlaintextExamples() { + return this.plaintextExamples; + } + + public List getContributorsNames() { + return this.contributorsNames; + } + + public List getSubmissionDates() { + return this.submissionDates; + } + + public String getSerializedMeanings() { + return serializedMeanings; + } + + public String getSerializedExamples() { + return serializedExamples; + } + + public String getSerializedContributors() { + return serializedContributors; + } + + public String getSerializedDates() { + return serializedDates; + } + + public int getPages() { + return pages; + } + } + +} diff --git a/src/main/java/wtf/beatrice/hidekobot/commands/message/UrbanDictionaryCommand.java b/src/main/java/wtf/beatrice/hidekobot/commands/message/UrbanDictionaryCommand.java index 000b159..59b7550 100644 --- a/src/main/java/wtf/beatrice/hidekobot/commands/message/UrbanDictionaryCommand.java +++ b/src/main/java/wtf/beatrice/hidekobot/commands/message/UrbanDictionaryCommand.java @@ -1,24 +1,20 @@ package wtf.beatrice.hidekobot.commands.message; -import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.entities.MessageEmbed; -import net.dv8tion.jda.api.entities.User; -import net.dv8tion.jda.api.entities.emoji.Emoji; import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; import net.dv8tion.jda.api.events.message.MessageReceivedEvent; import net.dv8tion.jda.api.interactions.components.ActionRow; import net.dv8tion.jda.api.interactions.components.ItemComponent; import net.dv8tion.jda.api.interactions.components.buttons.Button; -import org.apache.commons.lang3.SerializationException; import org.apache.commons.text.StringEscapeUtils; -import org.apache.commons.text.WordUtils; import org.jetbrains.annotations.Nullable; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; import wtf.beatrice.hidekobot.Cache; +import wtf.beatrice.hidekobot.commands.base.UrbanDictionary; import wtf.beatrice.hidekobot.datasources.DatabaseSource; import wtf.beatrice.hidekobot.objects.commands.MessageCommand; @@ -30,7 +26,7 @@ public class UrbanDictionaryCommand implements MessageCommand @Override public LinkedList getCommandLabels() { - return new LinkedList<>(Arrays.asList("urban", "urbandictionary", "ud")); + return UrbanDictionary.getCommandLabels(); } @Nullable @@ -44,284 +40,55 @@ public class UrbanDictionaryCommand implements MessageCommand return false; } - static final String baseUrl = "https://www.urbandictionary.com/define.php?term="; - static final Button previousPageButton = Button.primary("urban_previouspage", "Back") - .withEmoji(Emoji.fromFormatted("⬅️")); - static final Button nextPageButton = Button.primary("urban_nextpage", "Next") - .withEmoji(Emoji.fromFormatted("➡️")); - static final Button deleteButton = Button.danger("urban_delete", "Delete") - .withEmoji(Emoji.fromFormatted("\uD83D\uDDD1️")); - private static MessageEmbed buildEmbed(String term, - String url, - User author, - String meaning, - String example, - String contributor, - String date, - int page) - { - EmbedBuilder embedBuilder = new EmbedBuilder(); - embedBuilder.setColor(Cache.getBotColor()); - embedBuilder.setTitle(term + ", on Urban Dictionary", url); - embedBuilder.setAuthor(author.getAsTag(), null, author.getAvatarUrl()); - embedBuilder.addField("Definition", meaning, false); - embedBuilder.addField("Example", example, false); - embedBuilder.addField("Submission", - "*Entry " + (page+1) + " | Sent by " + contributor + " on " + date + "*", - false); - return embedBuilder.build(); - } @Override public void runCommand(MessageReceivedEvent event, String label, String[] args) { if(args.length == 0) { - event.getMessage().reply("\uD83D\uDE22 I need to know what to search for!").queue(); + event.getMessage().reply(UrbanDictionary.getNoArgsError()).queue(); return; } - // sanitize args by only keeping letters and numbers, and adding "+" instead of spaces for HTML parsing StringBuilder termBuilder = new StringBuilder(); - for(int pos = 0; pos < args.length; pos++) - { - String arg = args[pos]; - - arg = arg.replaceAll("[^\\d\\w]", ""); + for (int i = 0; i < args.length; i++) { + String arg = args[i]; termBuilder.append(arg); - if(pos + 1 != args.length) - termBuilder.append("+"); // add everywhere except on last iteration + if(i + 1 != args.length) // add spaces between args, but not on the last run + termBuilder.append(" "); } - String term = termBuilder.toString(); - - // cut it to length to avoid abuse - if (term.length() > 64) term = term.substring(0, 64); - - String url = baseUrl + term; + String term = UrbanDictionary.sanitizeArgs(termBuilder.toString(), false); + String url = UrbanDictionary.generateUrl(term); Document doc; try { doc = Jsoup.connect(url).get(); } catch (IOException e) { - event.getMessage().reply("\uD83D\uDE22 I couldn't find that term!").queue(); + event.getMessage().reply(UrbanDictionary.getNoTermFoundError()).queue(); return; } - List plaintextMeanings = new ArrayList<>(); - List plaintextExamples = new ArrayList<>(); - List contributorsNames = new ArrayList<>(); - List submissionDates = new ArrayList<>(); - Elements definitions = doc.getElementsByClass("definition"); - for(Element definition : definitions) - { - Elements meaningSingleton = definition.getElementsByClass("meaning"); - if(meaningSingleton.isEmpty()) - { - plaintextMeanings.add(" "); - } else - { - Element meaning = meaningSingleton.get(0); - String text = meaning.html() - .replaceAll("", "\n") // keep newlines - .replaceAll("<.*?>", ""); // remove all other html tags - // this is used to fix eg. & being shown literally instead of being parsed - text = StringEscapeUtils.unescapeHtml4(text); - // discord only allows 1024 characters for embed fields - if(text.length() > 1024) text = text.substring(0, 1020) + "..."; - plaintextMeanings.add(text); - } - - Elements exampleSingleton = definition.getElementsByClass("example"); - - if(exampleSingleton.isEmpty()) - { - plaintextExamples.add(" "); - } else - { - Element example = exampleSingleton.get(0); - String text = example.html() - .replaceAll("", "\n") // keep newlines - .replaceAll("<.*?>", ""); // remove all other html tags - // this is used to fix eg. & being shown literally instead of being parsed - text = StringEscapeUtils.unescapeHtml4(text); - // discord only allows 1024 characters for embed fields - if(text.length() > 1024) text = text.substring(0, 1020) + "..."; - plaintextExamples.add(text); - } - - Elements contributorSingleton = definition.getElementsByClass("contributor"); - if(contributorSingleton.isEmpty()) - { - contributorsNames.add("Unknown"); - } else - { - Element contributor = contributorSingleton.get(0); - - String htmlContributor = contributor.html(); - String htmlContributorName = contributor.select("a").html(); - String htmlSubmitDate = htmlContributor.substring( - htmlContributor.indexOf("") + 4); - - contributorsNames.add(htmlContributorName - .replaceAll("<.*?>", "")); // remove all html tags; - - submissionDates.add(htmlSubmitDate - .replaceAll("<.*?>", "")); // remove all html tags; - } - } - - // make it nice to look at, compared to the html value - - final String finalTerm = term; - term = WordUtils.capitalizeFully(term.replaceAll("\\+", " ")); - - String serializedMeanings = serialize(plaintextMeanings); - String serializedExamples = serialize(plaintextExamples); - String serializedContributors = serialize(contributorsNames); - String serializedDates = serialize(submissionDates); + UrbanDictionary.UrbanSearch search = new UrbanDictionary.UrbanSearch(definitions); + MessageEmbed embed = UrbanDictionary.buildEmbed(term, url, event.getAuthor(), search, 0); // disable next page if we only have one result - Button nextPageBtnLocal = nextPageButton; - if(submissionDates.size() == 1) nextPageBtnLocal = nextPageBtnLocal.asDisabled(); + Button nextPageBtnLocal = UrbanDictionary.getNextPageButton(); + if(search.getPages() == 1) nextPageBtnLocal = nextPageBtnLocal.asDisabled(); - MessageEmbed embed = buildEmbed(term, url, event.getAuthor(), plaintextMeanings.get(0), - plaintextExamples.get(0), contributorsNames.get(0), submissionDates.get(0), 0); - - // copy term for async thing event.getChannel() .sendMessageEmbeds(embed) - .addActionRow(previousPageButton.asDisabled(), //disabled by default because we're on page 0 + .addActionRow(UrbanDictionary.getPreviousPageButton().asDisabled(), + //disabled by default because we're on page 0 nextPageBtnLocal, - deleteButton) - .queue(message -> - { + UrbanDictionary.getDeleteButton()) + .queue(message -> UrbanDictionary.track(message, event.getAuthor(), search, term)); - Cache.getDatabaseSource().queueDisabling(message); - Cache.getDatabaseSource().trackRanCommandReply(message, event.getAuthor()); - Cache.getDatabaseSource().trackUrban(serializedMeanings, - serializedExamples, - serializedContributors, - serializedDates, - message, - finalTerm); - }); - - } - - private String serialize(List dataList) { - - try (ByteArrayOutputStream bo = new ByteArrayOutputStream(); - ObjectOutputStream so = new ObjectOutputStream(bo)) { - so.writeObject(dataList); - so.flush(); - return Base64.getEncoder().encodeToString(bo.toByteArray()); - } - catch (IOException ignored) {} - return null; - } - - private static ArrayList deserialize(String dataStr) { - - byte[] b = Base64.getDecoder().decode(dataStr); - ByteArrayInputStream bi = new ByteArrayInputStream(b); - ObjectInputStream si; - try { - si = new ObjectInputStream(bi); - return ArrayList.class.cast(si.readObject()); - } - catch (IOException | ClassNotFoundException e) { - throw new SerializationException("Error during deserialization", e); - } - } - - public static void delete(ButtonInteractionEvent event) - { - String messageId = event.getMessageId(); - DatabaseSource database = Cache.getDatabaseSource(); - - // check if the user interacting is the same one who ran the command - if (!(database.isUserTrackedFor(event.getUser().getId(), messageId))) { - event.reply("❌ You did not run this command!").setEphemeral(true).queue(); - return; - } - - event.getInteraction().getMessage().delete().queue(); - } - - public static void changePage(ButtonInteractionEvent event, boolean increase) - { - String messageId = event.getMessageId(); - DatabaseSource database = Cache.getDatabaseSource(); - - // check if the user interacting is the same one who ran the command - if (!(database.isUserTrackedFor(event.getUser().getId(), messageId))) { - event.reply("❌ You did not run this command!").setEphemeral(true).queue(); - return; - } - - // get current page and calculate how many pages there are - int page = Cache.getDatabaseSource().getUrbanPage(messageId); - int pages; - - - String serializedMeanings = database.getUrbanMeanings(messageId); - List meanings = deserialize(serializedMeanings); - String serializedExamples = database.getUrbanExamples(messageId); - List examples = deserialize(serializedExamples); - String serializedContributors = database.getUrbanContributors(messageId); - List contributors = deserialize(serializedContributors); - String serializedDates = database.getUrbanDates(messageId); - List dates = deserialize(serializedDates); - String term = database.getUrbanTerm(messageId); - String url = baseUrl + term; - - // count how many pages there are - pages = meanings.size(); - - // move to new page - if(increase) - page++; - else page--; - - term = WordUtils.capitalizeFully(term.replaceAll("\\+", " ")); - - MessageEmbed updatedEmbed = buildEmbed(term, url, event.getUser(), - meanings.get(page), examples.get(page), contributors.get(page), - dates.get(page), page); - - - - List components = new ArrayList<>(); - - if(page > 0) - { - components.add(previousPageButton.asEnabled()); - } else { - components.add(previousPageButton.asDisabled()); - } - - if(page + 1 == pages) - { - components.add(nextPageButton.asDisabled()); - } else { - components.add(nextPageButton.asEnabled()); - } - - components.add(deleteButton); - - ActionRow currentRow = ActionRow.of(components); - List actionRows = new ArrayList<>(Collections.singletonList(currentRow)); - - event.getMessage().editMessageEmbeds(updatedEmbed).complete(); - event.editComponents(actionRows).complete(); - database.setUrbanPage(messageId, page); - database.resetExpiryTimestamp(messageId); } } diff --git a/src/main/java/wtf/beatrice/hidekobot/commands/slash/MagicBallCommand.java b/src/main/java/wtf/beatrice/hidekobot/commands/slash/MagicBallCommand.java index f98b807..b6526b6 100644 --- a/src/main/java/wtf/beatrice/hidekobot/commands/slash/MagicBallCommand.java +++ b/src/main/java/wtf/beatrice/hidekobot/commands/slash/MagicBallCommand.java @@ -28,8 +28,6 @@ public class MagicBallCommand extends SlashCommandImpl @Override public void runSlashCommand(@NotNull SlashCommandInteractionEvent event) { - MessageChannel channel = event.getChannel(); - // get the asked question OptionMapping textOption = event.getOption("question"); String question = ""; diff --git a/src/main/java/wtf/beatrice/hidekobot/commands/slash/UrbanDictionaryCommand.java b/src/main/java/wtf/beatrice/hidekobot/commands/slash/UrbanDictionaryCommand.java new file mode 100644 index 0000000..41dc954 --- /dev/null +++ b/src/main/java/wtf/beatrice/hidekobot/commands/slash/UrbanDictionaryCommand.java @@ -0,0 +1,84 @@ +package wtf.beatrice.hidekobot.commands.slash; + +import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.entities.MessageEmbed; +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.interactions.commands.build.CommandData; +import net.dv8tion.jda.api.interactions.commands.build.Commands; +import net.dv8tion.jda.api.interactions.components.ActionRow; +import net.dv8tion.jda.api.interactions.components.LayoutComponent; +import net.dv8tion.jda.api.interactions.components.buttons.Button; +import org.jetbrains.annotations.NotNull; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.select.Elements; +import wtf.beatrice.hidekobot.Cache; +import wtf.beatrice.hidekobot.commands.base.UrbanDictionary; +import wtf.beatrice.hidekobot.objects.commands.SlashCommandImpl; + +import java.io.IOException; + +public class UrbanDictionaryCommand extends SlashCommandImpl +{ + @Override + public CommandData getSlashCommandData() + { + + return Commands.slash(UrbanDictionary.getCommandLabels().get(0), + "Look up a term on Urban Dictionary.") + .addOption(OptionType.STRING, "term", "The term to look up", true); + } + + @Override + public void runSlashCommand(@NotNull SlashCommandInteractionEvent event) + { + event.deferReply().queue(); + + // get the term to look up + OptionMapping textOption = event.getOption("term"); + String term = ""; + if(textOption != null) + { + term = textOption.getAsString(); + } + + if(textOption == null || term.isEmpty()) + { + event.reply(UrbanDictionary.getNoArgsError()) + .setEphemeral(true) + .queue(); + return; + } + + final String sanitizedTerm = UrbanDictionary.sanitizeArgs(term, false); + String url = UrbanDictionary.generateUrl(sanitizedTerm); + + Document doc; + + try { + doc = Jsoup.connect(url).get(); + } catch (IOException e) { + event.reply(UrbanDictionary.getNoTermFoundError()) + .setEphemeral(true) + .queue(); + return; + } + + Elements definitions = doc.getElementsByClass("definition"); + UrbanDictionary.UrbanSearch search = new UrbanDictionary.UrbanSearch(definitions); + MessageEmbed embed = UrbanDictionary.buildEmbed(sanitizedTerm, url, event.getUser(), search, 0); + + // disable next page if we only have one result + Button nextPageBtnLocal = UrbanDictionary.getNextPageButton(); + if(search.getPages() == 1) nextPageBtnLocal = nextPageBtnLocal.asDisabled(); + + ActionRow actionRow = ActionRow.of(UrbanDictionary.getPreviousPageButton().asDisabled(), + //disabled by default because we're on page 0 + nextPageBtnLocal, + UrbanDictionary.getDeleteButton()); + event.getHook().editOriginalEmbeds(embed).setComponents(actionRow).queue(message -> + UrbanDictionary.track(message, event.getUser(), search, sanitizedTerm)); + } +} diff --git a/src/main/java/wtf/beatrice/hidekobot/listeners/ButtonInteractionListener.java b/src/main/java/wtf/beatrice/hidekobot/listeners/ButtonInteractionListener.java index c115276..dc73b7f 100644 --- a/src/main/java/wtf/beatrice/hidekobot/listeners/ButtonInteractionListener.java +++ b/src/main/java/wtf/beatrice/hidekobot/listeners/ButtonInteractionListener.java @@ -4,6 +4,7 @@ import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; import wtf.beatrice.hidekobot.commands.base.ClearChat; import wtf.beatrice.hidekobot.commands.base.CoinFlip; +import wtf.beatrice.hidekobot.commands.base.UrbanDictionary; import wtf.beatrice.hidekobot.commands.message.UrbanDictionaryCommand; public class ButtonInteractionListener extends ListenerAdapter @@ -22,9 +23,9 @@ public class ButtonInteractionListener extends ListenerAdapter case "clear_dismiss" -> ClearChat.dismissMessage(event); // urban dictionary navigation - case "urban_nextpage" -> UrbanDictionaryCommand.changePage(event, true); - case "urban_previouspage" -> UrbanDictionaryCommand.changePage(event, false); - case "urban_delete" -> UrbanDictionaryCommand.delete(event); + case "urban_nextpage" -> UrbanDictionary.changePage(event, true); + case "urban_previouspage" -> UrbanDictionary.changePage(event, false); + case "urban_delete" -> UrbanDictionary.delete(event); }