Compare commits
62 Commits
renovate/o
...
0f54fe856e
| Author | SHA1 | Date | |
|---|---|---|---|
| 0f54fe856e | |||
| 5a7f884703 | |||
| e5c5993fb2 | |||
| d331c48ced | |||
| 84ff5a752e | |||
| 4f408fb5f9 | |||
| 1384259187 | |||
| 82698ec5fe | |||
| 0762068465 | |||
| cc9aee3441 | |||
| 86c7c30d8f | |||
| 19e3cde7e6 | |||
| 72f9bb4eb5 | |||
| 407ca279f5 | |||
| 9eefa4b958 | |||
| 9278b485d9 | |||
| 5a2205e567 | |||
| 3212ceb03c | |||
| a80b2cc5a9 | |||
| d087de1d01 | |||
| 99fc980e00 | |||
| 02627ab732 | |||
| dead16f338 | |||
| 2f51f9d40c | |||
| 5f5fc8d3a8 | |||
| 4c98182da7 | |||
| 9e57a3a426 | |||
| 2bf08c27b7 | |||
| b085efeccb | |||
| d8604c7ae5 | |||
| e83d7de7f5 | |||
| dfa25e54f3 | |||
| d1dc71dde9 | |||
| 6fcd3b4cdf | |||
| deb7d83e64 | |||
| 010a25fd66 | |||
| 7c2530c88b | |||
| 20665f4862 | |||
| ecfa3cded8 | |||
| 90e0c4ddf9 | |||
| fd9fe4ead6 | |||
| 6cdd44da29 | |||
| 3dd30a3a89 | |||
| 5c8bad2b02 | |||
| b23bc30fc0 | |||
| 018e24034f | |||
|
|
1a19a9ea06 | ||
|
|
495f164552 | ||
|
|
fd100649a7 | ||
|
|
b3990ff04f | ||
|
|
f5238ced89 | ||
|
|
f0ee565185 | ||
|
|
a21d179308 | ||
|
|
36ad728bbc | ||
|
|
1a6fe6465c | ||
|
|
f0004dc555 | ||
|
|
8ddf0ab80d | ||
|
|
660e18d1f4 | ||
|
|
db943f7e05 | ||
|
|
cb49bda84a | ||
|
|
b318b9f22b | ||
|
|
1447f8c177 |
19
pom.xml
19
pom.xml
@@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>wtf.beatrice.hidekobot</groupId>
|
||||
<artifactId>HidekoBot</artifactId>
|
||||
<version>0.5.0</version>
|
||||
<version>0.5.11</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>16</maven.compiler.source>
|
||||
@@ -18,7 +18,7 @@
|
||||
<dependency>
|
||||
<groupId>net.dv8tion</groupId>
|
||||
<artifactId>JDA</artifactId>
|
||||
<version>5.0.0-alpha.22</version>
|
||||
<version>5.0.0-beta.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
@@ -40,6 +40,21 @@
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
<version>1.33</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jsoup</groupId>
|
||||
<artifactId>jsoup</artifactId>
|
||||
<version>1.15.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-text</artifactId>
|
||||
<version>1.10.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.vdurmont</groupId>
|
||||
<artifactId>emoji-java</artifactId>
|
||||
<version>5.1.1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ import wtf.beatrice.hidekobot.util.Logger;
|
||||
import java.awt.*;
|
||||
import java.lang.reflect.Field;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Random;
|
||||
|
||||
public class Cache
|
||||
{
|
||||
@@ -23,6 +24,10 @@ public class Cache
|
||||
private static final String botPrefix = "hideko";
|
||||
private static final Logger logger = new Logger(Cache.class);
|
||||
|
||||
// the Random instance that we should always use when looking for an RNG based thing.
|
||||
// the seed is updated periodically.
|
||||
private static final Random randomInstance = new Random();
|
||||
|
||||
private static PropertiesSource propertiesSource = null;
|
||||
private static ConfigurationSource configurationSource = null;
|
||||
private static DatabaseSource databaseSource = null;
|
||||
@@ -60,6 +65,14 @@ public class Cache
|
||||
*/
|
||||
public static int[] getSupportedAvatarResolutions() { return supportedAvatarResolutions; }
|
||||
|
||||
public static Random getRandom() {
|
||||
return randomInstance;
|
||||
}
|
||||
|
||||
public static void setRandomSeed(long seed) {
|
||||
randomInstance.setSeed(seed);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the bot has been started with the verbose argument.
|
||||
*
|
||||
|
||||
@@ -18,8 +18,10 @@ import wtf.beatrice.hidekobot.listeners.SlashCommandCompletionListener;
|
||||
import wtf.beatrice.hidekobot.listeners.SlashCommandListener;
|
||||
import wtf.beatrice.hidekobot.runnables.ExpiredMessageTask;
|
||||
import wtf.beatrice.hidekobot.runnables.HeartBeatTask;
|
||||
import wtf.beatrice.hidekobot.runnables.RandomSeedTask;
|
||||
import wtf.beatrice.hidekobot.runnables.StatusUpdateTask;
|
||||
import wtf.beatrice.hidekobot.util.CommandUtil;
|
||||
import wtf.beatrice.hidekobot.util.Logger;
|
||||
import wtf.beatrice.hidekobot.util.SlashCommandUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.time.LocalDateTime;
|
||||
@@ -121,18 +123,28 @@ public class HidekoBot
|
||||
slashCommandListener.registerCommand(new DieCommand());
|
||||
slashCommandListener.registerCommand(new HelpCommand());
|
||||
slashCommandListener.registerCommand(new InviteCommand());
|
||||
slashCommandListener.registerCommand(new MagicBallCommand());
|
||||
slashCommandListener.registerCommand(new PingCommand());
|
||||
slashCommandListener.registerCommand(new SayCommand());
|
||||
slashCommandListener.registerCommand(new UrbanDictionaryCommand());
|
||||
Cache.setSlashCommandListener(slashCommandListener);
|
||||
Cache.setSlashCommandCompletionListener(slashCommandCompletionListener);
|
||||
|
||||
// register message commands
|
||||
MessageCommandListener messageCommandListener = new MessageCommandListener();
|
||||
messageCommandListener.registerCommand(new HelloCommand());
|
||||
messageCommandListener.registerCommand(new wtf.beatrice.hidekobot.commands.message.InviteCommand());
|
||||
messageCommandListener.registerCommand(new wtf.beatrice.hidekobot.commands.message.AliasCommand());
|
||||
messageCommandListener.registerCommand(new wtf.beatrice.hidekobot.commands.message.AvatarCommand());
|
||||
messageCommandListener.registerCommand(new wtf.beatrice.hidekobot.commands.message.BotInfoCommand());
|
||||
messageCommandListener.registerCommand(new wtf.beatrice.hidekobot.commands.message.CoinFlipCommand());
|
||||
messageCommandListener.registerCommand(new wtf.beatrice.hidekobot.commands.message.ClearCommand());
|
||||
messageCommandListener.registerCommand(new wtf.beatrice.hidekobot.commands.message.DiceRollCommand());
|
||||
messageCommandListener.registerCommand(new wtf.beatrice.hidekobot.commands.message.HelpCommand());
|
||||
messageCommandListener.registerCommand(new wtf.beatrice.hidekobot.commands.message.InviteCommand());
|
||||
messageCommandListener.registerCommand(new wtf.beatrice.hidekobot.commands.message.LoveCalculatorCommand());
|
||||
messageCommandListener.registerCommand(new wtf.beatrice.hidekobot.commands.message.MagicBallCommand());
|
||||
messageCommandListener.registerCommand(new wtf.beatrice.hidekobot.commands.message.SayCommand());
|
||||
messageCommandListener.registerCommand(new wtf.beatrice.hidekobot.commands.message.UrbanDictionaryCommand());
|
||||
Cache.setMessageCommandListener(messageCommandListener);
|
||||
|
||||
// register listeners
|
||||
@@ -144,11 +156,10 @@ public class HidekoBot
|
||||
// update slash commands (delayed)
|
||||
final boolean finalForceUpdateCommands = forceUpdateCommands;
|
||||
Executors.newSingleThreadScheduledExecutor().schedule(() -> // todo: try-with-resources
|
||||
SlashCommandUtil.updateSlashCommands(finalForceUpdateCommands), 1, TimeUnit.SECONDS);
|
||||
CommandUtil.updateSlashCommands(finalForceUpdateCommands), 1, TimeUnit.SECONDS);
|
||||
|
||||
// set the bot's status
|
||||
jda.getPresence().setStatus(OnlineStatus.ONLINE);
|
||||
jda.getPresence().setActivity(Activity.playing("Hatsune Miku: Project DIVA"));
|
||||
|
||||
// connect to database
|
||||
logger.log("Connecting to database...");
|
||||
@@ -172,6 +183,10 @@ public class HidekoBot
|
||||
scheduler.scheduleAtFixedRate(expiredMessageTask, 5, 5, TimeUnit.SECONDS); //every 5 seconds
|
||||
HeartBeatTask heartBeatTask = new HeartBeatTask();
|
||||
scheduler.scheduleAtFixedRate(heartBeatTask, 10, 30, TimeUnit.SECONDS); //every 30 seconds
|
||||
StatusUpdateTask statusUpdateTask = new StatusUpdateTask();
|
||||
scheduler.scheduleAtFixedRate(statusUpdateTask, 0, 60 * 5, TimeUnit.SECONDS); // every 5 minutes
|
||||
RandomSeedTask randomSeedTask = new RandomSeedTask();
|
||||
scheduler.scheduleAtFixedRate(randomSeedTask, 0, 60, TimeUnit.SECONDS); // every minute
|
||||
|
||||
// register shutdown interrupt signal listener for proper shutdown.
|
||||
Signal.handle(new Signal("INT"), signal -> shutdown());
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package wtf.beatrice.hidekobot.commands.base;
|
||||
|
||||
import wtf.beatrice.hidekobot.objects.commands.MessageCommand;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
public class Alias
|
||||
{
|
||||
public static String generateNiceAliases(MessageCommand command)
|
||||
{
|
||||
LinkedList<String> aliases = command.getCommandLabels();
|
||||
StringBuilder aliasesStringBuilder = new StringBuilder();
|
||||
for(int i = 0; i < aliases.size(); i++)
|
||||
{
|
||||
aliasesStringBuilder.append("`").append(aliases.get(i)).append("`");
|
||||
|
||||
if(i + 1 != aliases.size())
|
||||
aliasesStringBuilder.append(", "); // separate with comma except on last iteration
|
||||
}
|
||||
|
||||
return aliasesStringBuilder.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package wtf.beatrice.hidekobot.commands.base;
|
||||
|
||||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
import net.dv8tion.jda.api.entities.User;
|
||||
import wtf.beatrice.hidekobot.Cache;
|
||||
|
||||
public class Avatar
|
||||
{
|
||||
public static int parseResolution(int resolution)
|
||||
{
|
||||
int[] acceptedSizes = Cache.getSupportedAvatarResolutions();
|
||||
|
||||
// method to find closest value to accepted values
|
||||
int distance = Math.abs(acceptedSizes[0] - resolution);
|
||||
int idx = 0;
|
||||
for(int c = 1; c < acceptedSizes.length; c++){
|
||||
int cdistance = Math.abs(acceptedSizes[c] - resolution);
|
||||
if(cdistance < distance){
|
||||
idx = c;
|
||||
distance = cdistance;
|
||||
}
|
||||
}
|
||||
|
||||
return acceptedSizes[idx];
|
||||
}
|
||||
|
||||
public static MessageEmbed buildEmbed(int resolution, User user)
|
||||
{
|
||||
int[] acceptedSizes = Cache.getSupportedAvatarResolutions();
|
||||
EmbedBuilder embedBuilder = new EmbedBuilder();
|
||||
|
||||
embedBuilder.setColor(Cache.getBotColor());
|
||||
embedBuilder.setTitle("Profile picture");
|
||||
|
||||
embedBuilder.addField("User", "<@" + user.getId() + ">", false);
|
||||
|
||||
embedBuilder.addField("Current resolution", resolution + " × " + resolution, false);
|
||||
|
||||
// string builder to create a string that links to all available resolutions
|
||||
StringBuilder links = new StringBuilder();
|
||||
for(int pos = 0; pos < acceptedSizes.length; pos++)
|
||||
{
|
||||
int currSize = acceptedSizes[pos];
|
||||
|
||||
String currLink = user.getEffectiveAvatar().getUrl(currSize);
|
||||
|
||||
links.append("[").append(currSize).append("px](").append(currLink).append(")");
|
||||
if(pos + 1 != acceptedSizes.length) // don't add a separator on the last iteration
|
||||
{
|
||||
links.append(" | ");
|
||||
}
|
||||
}
|
||||
|
||||
embedBuilder.addField("Available resolutions", links.toString(), false);
|
||||
|
||||
|
||||
|
||||
embedBuilder.setImage(user.getEffectiveAvatar().getUrl(resolution));
|
||||
return embedBuilder.build();
|
||||
}
|
||||
}
|
||||
@@ -7,10 +7,8 @@ import net.dv8tion.jda.api.entities.channel.Channel;
|
||||
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
|
||||
import net.dv8tion.jda.api.entities.emoji.Emoji;
|
||||
import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent;
|
||||
import net.dv8tion.jda.api.interactions.InteractionHook;
|
||||
import net.dv8tion.jda.api.interactions.components.buttons.Button;
|
||||
import wtf.beatrice.hidekobot.Cache;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -46,12 +44,15 @@ public class ClearChat
|
||||
return null;
|
||||
}
|
||||
|
||||
public static int delete(int toDeleteAmount, long startingMessageId, MessageChannel channel)
|
||||
public static int delete(int toDeleteAmount,
|
||||
long startingMessageId,
|
||||
MessageChannel channel)
|
||||
{
|
||||
// int to keep track of how many messages we actually deleted.
|
||||
int deleted = 0;
|
||||
|
||||
int limit = 95; //discord limits this method to range 2-100. we set it to 95 to be safe.
|
||||
int limit = 95; //discord limits this method to only 2<x<100 deletions per run.
|
||||
// we set this slightly lower to be safe, and iterate as needed.
|
||||
|
||||
// increase the count by 1, because we technically aren't clearing the first ID ever
|
||||
// which is actually the slash command's ID and not a message.
|
||||
@@ -149,12 +150,13 @@ public class ClearChat
|
||||
|
||||
public static Button getDismissButton()
|
||||
{
|
||||
return Button.primary("clear_dismiss", "Dismiss")
|
||||
return Button.primary("generic_dismiss", "Dismiss")
|
||||
.withEmoji(Emoji.fromUnicode("❌"));
|
||||
}
|
||||
|
||||
public static String parseAmount(int deleted)
|
||||
{
|
||||
|
||||
if(deleted < 1)
|
||||
{
|
||||
return "\uD83D\uDE22 Couldn't clear any message!";
|
||||
@@ -166,27 +168,7 @@ public class ClearChat
|
||||
}
|
||||
}
|
||||
|
||||
private void respond(Object responseFlowObj, String content)
|
||||
{
|
||||
if(responseFlowObj instanceof InteractionHook) {
|
||||
((InteractionHook) responseFlowObj).editOriginal(content).queue();
|
||||
} else if (responseFlowObj instanceof Message) {
|
||||
((Message) responseFlowObj).reply(content).queue();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void dismissMessage(ButtonInteractionEvent event)
|
||||
{
|
||||
|
||||
if(!(Cache.getDatabaseSource().isUserTrackedFor(event.getUser().getId(), event.getMessageId())))
|
||||
{
|
||||
event.reply("❌ You did not run this command!").setEphemeral(true).queue();
|
||||
} else
|
||||
{
|
||||
event.getInteraction().getMessage().delete().queue();
|
||||
}
|
||||
}
|
||||
// cap the amount to avoid abuse.
|
||||
public static int getMaxAmount() { return 1000; }
|
||||
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ public class CoinFlip
|
||||
|
||||
public static Button getReflipButton() {
|
||||
return Button.primary("coinflip_reflip", "Flip again")
|
||||
.withEmoji(Emoji.fromFormatted("\uD83E\uDE99"));
|
||||
.withEmoji(Emoji.fromUnicode("\uD83E\uDE99"));
|
||||
}
|
||||
|
||||
public static String genRandom()
|
||||
@@ -61,8 +61,6 @@ public class CoinFlip
|
||||
|
||||
public static void trackAndRestrict(Message replyMessage, User user)
|
||||
{
|
||||
String replyMessageId = replyMessage.getId();
|
||||
|
||||
Cache.getDatabaseSource().queueDisabling(replyMessage);
|
||||
Cache.getDatabaseSource().trackRanCommandReply(replyMessage, user);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
package wtf.beatrice.hidekobot.commands.base;
|
||||
|
||||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
import net.dv8tion.jda.api.entities.User;
|
||||
import wtf.beatrice.hidekobot.Cache;
|
||||
import wtf.beatrice.hidekobot.util.RandomUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class MagicBall
|
||||
{
|
||||
|
||||
public static LinkedList<String> getLabels()
|
||||
{
|
||||
return new LinkedList<>(Arrays.asList("8ball", "8b", "eightball", "magicball"));
|
||||
}
|
||||
|
||||
private final static List<String> answers = new ArrayList<>(
|
||||
Arrays.asList("It is certain.",
|
||||
"It is decidedly so.",
|
||||
"Without a doubt.",
|
||||
"Yes, definitely.",
|
||||
"That would be a yes.",
|
||||
"As I see it, yes.",
|
||||
"Most likely.",
|
||||
"Looks like it.",
|
||||
"Yes.",
|
||||
"Signs point to yes.",
|
||||
"Reply hazy, try again.",
|
||||
"Ask again later.",
|
||||
"Better not tell you now.",
|
||||
"Seems uncertain.",
|
||||
"Concentrate and ask again.",
|
||||
"Don't count on it.",
|
||||
"My answer is no.",
|
||||
"My sources say no.",
|
||||
"Outlook not so good.",
|
||||
"Very doubtful."));
|
||||
|
||||
public static String getRandomAnswer()
|
||||
{
|
||||
int answerPos = RandomUtil.getRandomNumber(0, answers.size() - 1);
|
||||
return answers.get(answerPos);
|
||||
}
|
||||
|
||||
public static MessageEmbed generateEmbed(String question, User author)
|
||||
{
|
||||
// add a question mark at the end, if missing.
|
||||
// this might not always apply but it's fun
|
||||
if(!question.endsWith("?")) question += "?";
|
||||
|
||||
String answer = getRandomAnswer();
|
||||
|
||||
EmbedBuilder embedBuilder = new EmbedBuilder();
|
||||
embedBuilder.setAuthor(author.getAsTag(), null, author.getAvatarUrl());
|
||||
embedBuilder.setTitle("Magic Ball");
|
||||
embedBuilder.setColor(Cache.getBotColor());
|
||||
embedBuilder.addField("❓ Question", question, false);
|
||||
embedBuilder.addField("\uD83C\uDFB1 Answer", answer, false);
|
||||
|
||||
return embedBuilder.build();
|
||||
}
|
||||
}
|
||||
11
src/main/java/wtf/beatrice/hidekobot/commands/base/Say.java
Normal file
11
src/main/java/wtf/beatrice/hidekobot/commands/base/Say.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package wtf.beatrice.hidekobot.commands.base;
|
||||
|
||||
import net.dv8tion.jda.api.Permission;
|
||||
|
||||
public class Say
|
||||
{
|
||||
|
||||
public static Permission getPermission() {
|
||||
return Permission.MESSAGE_MANAGE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,320 @@
|
||||
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.text.StringEscapeUtils;
|
||||
import org.apache.commons.text.WordUtils;
|
||||
import org.jsoup.nodes.Element;
|
||||
import org.jsoup.select.Elements;
|
||||
import wtf.beatrice.hidekobot.Cache;
|
||||
import wtf.beatrice.hidekobot.datasources.DatabaseSource;
|
||||
import wtf.beatrice.hidekobot.util.SerializationUtil;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class UrbanDictionary
|
||||
{
|
||||
|
||||
public static LinkedList<String> 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("generic_dismiss", "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 getTermNotFoundError()
|
||||
{
|
||||
return "\uD83D\uDE22 I couldn't find that term!";
|
||||
}
|
||||
|
||||
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, ChangeType changeType)
|
||||
{
|
||||
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(changeType == ChangeType.NEXT)
|
||||
page++;
|
||||
else if(changeType == ChangeType.PREVIOUS)
|
||||
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<ItemComponent> 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<String> plaintextMeanings;
|
||||
final LinkedList<String> plaintextExamples;
|
||||
final LinkedList<String> contributorsNames;
|
||||
final LinkedList<String> 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 = SerializationUtil.deserializeBase64(serializedMeanings);
|
||||
this.plaintextExamples = SerializationUtil.deserializeBase64(serializedExamples);
|
||||
this.contributorsNames = SerializationUtil.deserializeBase64(serializedContributors);
|
||||
this.submissionDates = SerializationUtil.deserializeBase64(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("<br\\s*?>", "\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("<br\\s*?>", "\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("</a>") + 4);
|
||||
|
||||
contributorsNames.add(htmlContributorName
|
||||
.replaceAll("<.*?>", "")); // remove all html tags;
|
||||
|
||||
submissionDates.add(htmlSubmitDate
|
||||
.replaceAll("<.*?>", "")); // remove all html tags;
|
||||
}
|
||||
}
|
||||
|
||||
serializedMeanings = SerializationUtil.serializeBase64(plaintextMeanings);
|
||||
serializedExamples = SerializationUtil.serializeBase64(plaintextExamples);
|
||||
serializedContributors = SerializationUtil.serializeBase64(contributorsNames);
|
||||
serializedDates = SerializationUtil.serializeBase64(submissionDates);
|
||||
|
||||
pages = submissionDates.size();
|
||||
}
|
||||
|
||||
public List<String> getPlaintextMeanings() {
|
||||
return this.plaintextMeanings;
|
||||
}
|
||||
|
||||
public List<String> getPlaintextExamples() {
|
||||
return this.plaintextExamples;
|
||||
}
|
||||
|
||||
public List<String> getContributorsNames() {
|
||||
return this.contributorsNames;
|
||||
}
|
||||
|
||||
public List<String> 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;
|
||||
}
|
||||
}
|
||||
|
||||
public enum ChangeType
|
||||
{
|
||||
NEXT,
|
||||
PREVIOUS;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package wtf.beatrice.hidekobot.commands.message;
|
||||
|
||||
import net.dv8tion.jda.api.Permission;
|
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import wtf.beatrice.hidekobot.Cache;
|
||||
import wtf.beatrice.hidekobot.commands.base.Alias;
|
||||
import wtf.beatrice.hidekobot.objects.commands.CommandCategory;
|
||||
import wtf.beatrice.hidekobot.objects.commands.MessageCommand;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class AliasCommand implements MessageCommand
|
||||
{
|
||||
|
||||
@Override
|
||||
public LinkedList<String> getCommandLabels() {
|
||||
return new LinkedList<>(Arrays.asList("alias", "aliases"));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<Permission> getPermissions() {
|
||||
return null; // anyone can use it
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean passRawArgs() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public CommandCategory getCategory() {
|
||||
return CommandCategory.TOOLS;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "See other command aliases.";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getUsage() {
|
||||
return "<command>";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runCommand(MessageReceivedEvent event, String label, String[] args)
|
||||
{
|
||||
if(args.length == 0)
|
||||
{
|
||||
event.getMessage().reply("\uD83D\uDE20 Hey, you have to specify a command!").queue();
|
||||
return;
|
||||
}
|
||||
|
||||
String commandLabel = args[0].toLowerCase();
|
||||
MessageCommand command = Cache.getMessageCommandListener().getRegisteredCommand(commandLabel);
|
||||
if(command == null)
|
||||
{
|
||||
event.getMessage().reply("Unrecognized command: `" + commandLabel + "`!").queue(); // todo prettier
|
||||
return;
|
||||
}
|
||||
|
||||
String aliases = Alias.generateNiceAliases(command);
|
||||
aliases = "Aliases for **" + command.getCommandLabels().get(0) + "**: " + aliases;
|
||||
|
||||
event.getMessage()
|
||||
.reply(aliases)
|
||||
.queue();
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package wtf.beatrice.hidekobot.commands.message;
|
||||
|
||||
import net.dv8tion.jda.api.Permission;
|
||||
import net.dv8tion.jda.api.entities.Mentions;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
import net.dv8tion.jda.api.entities.User;
|
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import wtf.beatrice.hidekobot.Cache;
|
||||
import wtf.beatrice.hidekobot.HidekoBot;
|
||||
import wtf.beatrice.hidekobot.commands.base.Avatar;
|
||||
import wtf.beatrice.hidekobot.objects.commands.CommandCategory;
|
||||
import wtf.beatrice.hidekobot.objects.commands.MessageCommand;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class AvatarCommand implements MessageCommand
|
||||
{
|
||||
|
||||
@Override
|
||||
public LinkedList<String> getCommandLabels() {
|
||||
return new LinkedList<>(Collections.singletonList("avatar"));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<Permission> getPermissions() {
|
||||
return null; // anyone can use it
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean passRawArgs() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Get someone's avatar, or your own. You can additionally specify a resolution.";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getUsage() {
|
||||
return "[mentioned user] [resolution]";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public CommandCategory getCategory() {
|
||||
return CommandCategory.TOOLS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runCommand(MessageReceivedEvent event, String label, String[] args)
|
||||
{
|
||||
int[] acceptedSizes = Cache.getSupportedAvatarResolutions();
|
||||
|
||||
User user;
|
||||
int resolution = -1;
|
||||
|
||||
// we have no specific order for user and resolution, so let's try parsing any arg as resolution
|
||||
// (mentions are handled differently by a specific method)
|
||||
boolean resFound = false;
|
||||
|
||||
for (String arg : args) {
|
||||
try {
|
||||
int givenRes = Integer.parseInt(arg);
|
||||
resolution = Avatar.parseResolution(givenRes);
|
||||
resFound = true;
|
||||
break;
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
// fallback in case we didn't find any specified resolution
|
||||
if(!resFound) resolution = Avatar.parseResolution(512);
|
||||
|
||||
// check if someone is mentioned
|
||||
Mentions mentions = event.getMessage().getMentions();
|
||||
if(mentions.getMentions().isEmpty())
|
||||
{
|
||||
user = event.getAuthor();
|
||||
} else
|
||||
{
|
||||
String mentionedId = mentions.getMentions().get(0).getId();
|
||||
user = HidekoBot.getAPI().retrieveUserById(mentionedId).complete();
|
||||
}
|
||||
|
||||
// in case of issues, fallback to the sender
|
||||
if(user == null) user = event.getAuthor();
|
||||
|
||||
// send a response
|
||||
MessageEmbed embed = Avatar.buildEmbed(resolution, user);
|
||||
event.getMessage().replyEmbeds(embed).queue();
|
||||
}
|
||||
}
|
||||
@@ -3,9 +3,11 @@ package wtf.beatrice.hidekobot.commands.message;
|
||||
import net.dv8tion.jda.api.Permission;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import wtf.beatrice.hidekobot.Cache;
|
||||
import wtf.beatrice.hidekobot.commands.base.BotInfo;
|
||||
import wtf.beatrice.hidekobot.objects.commands.CommandCategory;
|
||||
import wtf.beatrice.hidekobot.objects.commands.MessageCommand;
|
||||
|
||||
import java.util.Collections;
|
||||
@@ -31,6 +33,24 @@ public class BotInfoCommand implements MessageCommand
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Get general info about the bot.";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getUsage() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public CommandCategory getCategory() {
|
||||
return CommandCategory.TOOLS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runCommand(MessageReceivedEvent event, String label, String[] args) {
|
||||
|
||||
|
||||
@@ -4,8 +4,11 @@ import net.dv8tion.jda.api.Permission;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||
import net.dv8tion.jda.api.interactions.components.buttons.Button;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import wtf.beatrice.hidekobot.Cache;
|
||||
import wtf.beatrice.hidekobot.commands.base.ClearChat;
|
||||
import wtf.beatrice.hidekobot.objects.commands.CommandCategory;
|
||||
import wtf.beatrice.hidekobot.objects.commands.MessageCommand;
|
||||
|
||||
import java.util.Collections;
|
||||
@@ -28,6 +31,24 @@ public class ClearCommand implements MessageCommand
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public CommandCategory getCategory() {
|
||||
return CommandCategory.MODERATION;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Clear the current channel's chat history.";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getUsage() {
|
||||
return "[amount]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runCommand(MessageReceivedEvent event, String label, String[] args)
|
||||
{
|
||||
@@ -43,7 +64,18 @@ public class ClearCommand implements MessageCommand
|
||||
// get the amount from the command args.
|
||||
Integer toDeleteAmount;
|
||||
if (args.length == 0) toDeleteAmount = 1;
|
||||
else toDeleteAmount = Integer.parseInt(args[0]);
|
||||
else
|
||||
{
|
||||
try {
|
||||
toDeleteAmount = Integer.parseInt(args[0]);
|
||||
} catch (NumberFormatException e)
|
||||
{
|
||||
toDeleteAmount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// cap the amount to avoid abuse.
|
||||
if(toDeleteAmount > ClearChat.getMaxAmount()) toDeleteAmount = 0;
|
||||
|
||||
error = ClearChat.checkDeleteAmount(toDeleteAmount);
|
||||
if (error != null) {
|
||||
@@ -64,14 +96,16 @@ public class ClearCommand implements MessageCommand
|
||||
|
||||
// edit the message text and attach a button.
|
||||
Button dismiss = ClearChat.getDismissButton();
|
||||
// ^ todo: maybe the dismiss button should also delete the original message sent by the user?
|
||||
// todo: but then, we need to differentiate between command type in the database, and store
|
||||
// todo: that message's id too.
|
||||
botMessage = botMessage.editMessage(content).setActionRow(dismiss).complete();
|
||||
Message finalMessage = event.getChannel().sendMessage(content).setActionRow(dismiss).complete();
|
||||
|
||||
// add the message to database.
|
||||
Cache.getDatabaseSource().queueDisabling(botMessage);
|
||||
Cache.getDatabaseSource().trackRanCommandReply(botMessage, event.getAuthor());
|
||||
Cache.getDatabaseSource().queueDisabling(finalMessage);
|
||||
Cache.getDatabaseSource().trackRanCommandReply(finalMessage, event.getAuthor());
|
||||
|
||||
// delete the sender's message.
|
||||
event.getMessage().delete().queue();
|
||||
// delete the "clearing" info message.
|
||||
botMessage.delete().queue();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,10 @@ package wtf.beatrice.hidekobot.commands.message;
|
||||
|
||||
import net.dv8tion.jda.api.Permission;
|
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import wtf.beatrice.hidekobot.commands.base.CoinFlip;
|
||||
import wtf.beatrice.hidekobot.objects.commands.CommandCategory;
|
||||
import wtf.beatrice.hidekobot.objects.commands.MessageCommand;
|
||||
|
||||
import java.util.Arrays;
|
||||
@@ -29,6 +31,24 @@ public class CoinFlipCommand implements MessageCommand
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Flip a coin.";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getUsage() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public CommandCategory getCategory() {
|
||||
return CommandCategory.FUN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runCommand(MessageReceivedEvent event, String label, String[] args) {
|
||||
|
||||
|
||||
@@ -0,0 +1,205 @@
|
||||
package wtf.beatrice.hidekobot.commands.message;
|
||||
|
||||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import net.dv8tion.jda.api.Permission;
|
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import wtf.beatrice.hidekobot.Cache;
|
||||
import wtf.beatrice.hidekobot.objects.Dice;
|
||||
import wtf.beatrice.hidekobot.objects.commands.CommandCategory;
|
||||
import wtf.beatrice.hidekobot.objects.commands.MessageCommand;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class DiceRollCommand implements MessageCommand
|
||||
{
|
||||
@Override
|
||||
public LinkedList<String> getCommandLabels() {
|
||||
return new LinkedList<>(Arrays.asList("diceroll", "droll", "roll"));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<Permission> getPermissions() {
|
||||
return null; // anyone can use it
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean passRawArgs() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Roll dice. You can roll multiple dice at the same time." +
|
||||
"\nExamples:" +
|
||||
"\n - `d8 10` to roll an 8-sided die 10 times." +
|
||||
"\n - `d12 3 d5 10` to roll a 12-sided die 3 times, and then a 5-sided die 10 times." +
|
||||
"\n - `30` to roll a standard 6-sided die 30 times." +
|
||||
"\n - `d10` to roll a 10-sided die once.";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getUsage() {
|
||||
return "[dice size] [rolls]";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public CommandCategory getCategory() {
|
||||
return CommandCategory.FUN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runCommand(MessageReceivedEvent event, String label, String[] args)
|
||||
{
|
||||
LinkedHashMap<Dice, Integer> dicesToRoll = new LinkedHashMap<>();
|
||||
String diceRegex = "d[0-9]+";
|
||||
String amountRegex = "[0-9]+";
|
||||
|
||||
Dice currentDice = null;
|
||||
int currentAmount;
|
||||
UUID lastPushedDice = null;
|
||||
int totalRolls = 0;
|
||||
|
||||
for(String arg : args)
|
||||
{
|
||||
if(totalRolls > 200)
|
||||
{
|
||||
event.getMessage().reply("Too many total rolls!").queue();
|
||||
return;
|
||||
}
|
||||
|
||||
if(arg.matches(amountRegex))
|
||||
{
|
||||
currentAmount = Integer.parseInt(arg);
|
||||
|
||||
if(currentDice == null)
|
||||
{
|
||||
currentDice = new Dice(6);
|
||||
} else {
|
||||
currentDice = new Dice(currentDice);
|
||||
}
|
||||
|
||||
if(currentAmount > 100)
|
||||
{
|
||||
event.getMessage().reply("Too many rolls (`" + currentAmount + "`)!").queue();
|
||||
return;
|
||||
}
|
||||
|
||||
lastPushedDice = currentDice.getUUID();
|
||||
dicesToRoll.put(currentDice, currentAmount);
|
||||
totalRolls += currentAmount;
|
||||
}
|
||||
else if(arg.matches(diceRegex))
|
||||
{
|
||||
int sides = Integer.parseInt(arg.substring(1));
|
||||
|
||||
if(sides > 10000)
|
||||
{
|
||||
event.getMessage().reply("Too many sides (`" + sides + "`)!").queue();
|
||||
return;
|
||||
}
|
||||
|
||||
if(args.length == 1)
|
||||
{
|
||||
dicesToRoll.put(new Dice(sides), 1);
|
||||
totalRolls++;
|
||||
} else
|
||||
{
|
||||
if(currentDice != null)
|
||||
{
|
||||
if(lastPushedDice == null || !lastPushedDice.equals(currentDice.getUUID()))
|
||||
{
|
||||
dicesToRoll.put(currentDice, 1);
|
||||
lastPushedDice = currentDice.getUUID();
|
||||
totalRolls++;
|
||||
}
|
||||
}
|
||||
|
||||
currentDice = new Dice(sides);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(lastPushedDice == null)
|
||||
{
|
||||
if(currentDice != null)
|
||||
{
|
||||
dicesToRoll.put(currentDice, 1);
|
||||
totalRolls++;
|
||||
}
|
||||
} else
|
||||
{
|
||||
if(!lastPushedDice.equals(currentDice.getUUID()))
|
||||
{
|
||||
dicesToRoll.put(new Dice(currentDice), 1);
|
||||
totalRolls++;
|
||||
}
|
||||
}
|
||||
|
||||
LinkedList<Dice> rolledDices = new LinkedList<>();
|
||||
|
||||
// in case no dice was specified (or invalid), roll a standard 6-sided dice.
|
||||
if(dicesToRoll.isEmpty())
|
||||
{
|
||||
Dice standardDice = new Dice(6);
|
||||
dicesToRoll.put(standardDice, 1);
|
||||
totalRolls = 1;
|
||||
}
|
||||
|
||||
for(Dice dice : dicesToRoll.keySet())
|
||||
{
|
||||
for(int roll = 0; roll < dicesToRoll.get(dice); roll++)
|
||||
{
|
||||
dice.roll();
|
||||
rolledDices.add(new Dice(dice));
|
||||
}
|
||||
}
|
||||
|
||||
EmbedBuilder embedBuilder = new EmbedBuilder();
|
||||
|
||||
embedBuilder.setColor(Cache.getBotColor());
|
||||
embedBuilder.setAuthor(event.getAuthor().getAsTag(), null, event.getAuthor().getAvatarUrl());
|
||||
embedBuilder.setTitle("Dice Roll");
|
||||
|
||||
StringBuilder message = new StringBuilder();
|
||||
int total = 0;
|
||||
|
||||
int previousDiceSides = 0;
|
||||
for (Dice dice : rolledDices) {
|
||||
int diceSize = dice.getSides();
|
||||
|
||||
if (previousDiceSides != diceSize) {
|
||||
message.append("\nd").append(diceSize).append(": ");
|
||||
previousDiceSides = diceSize;
|
||||
} else if (previousDiceSides != 0) {
|
||||
message.append(", ");
|
||||
}
|
||||
|
||||
message.append("`").append(dice.getValue()).append("`");
|
||||
|
||||
total += dice.getValue();
|
||||
}
|
||||
|
||||
// discord doesn't allow embed fields to be longer than 1024 and errors out
|
||||
if(message.length() > 1024)
|
||||
{
|
||||
event.getMessage().reply("Too many rolls!").queue();
|
||||
return;
|
||||
}
|
||||
|
||||
embedBuilder.addField("\uD83C\uDFB2 Rolls", message.toString(), false);
|
||||
|
||||
String rolls = totalRolls == 1 ? "roll" : "rolls";
|
||||
|
||||
embedBuilder.addField("✨ Total", totalRolls + " " + rolls + ": " + total, false);
|
||||
|
||||
|
||||
event.getMessage().replyEmbeds(embedBuilder.build()).queue();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,6 +2,9 @@ package wtf.beatrice.hidekobot.commands.message;
|
||||
|
||||
import net.dv8tion.jda.api.Permission;
|
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import wtf.beatrice.hidekobot.objects.commands.CommandCategory;
|
||||
import wtf.beatrice.hidekobot.objects.commands.MessageCommand;
|
||||
|
||||
import java.util.Arrays;
|
||||
@@ -24,6 +27,24 @@ public class HelloCommand implements MessageCommand
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Get pinged by the bot.";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getUsage() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public CommandCategory getCategory() {
|
||||
return CommandCategory.FUN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runCommand(MessageReceivedEvent event, String label, String[] args)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
package wtf.beatrice.hidekobot.commands.message;
|
||||
|
||||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import net.dv8tion.jda.api.Permission;
|
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||
import org.apache.commons.text.WordUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import wtf.beatrice.hidekobot.Cache;
|
||||
import wtf.beatrice.hidekobot.commands.base.Alias;
|
||||
import wtf.beatrice.hidekobot.commands.base.Say;
|
||||
import wtf.beatrice.hidekobot.objects.commands.CommandCategory;
|
||||
import wtf.beatrice.hidekobot.objects.commands.MessageCommand;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class HelpCommand implements MessageCommand
|
||||
{
|
||||
|
||||
|
||||
@Override
|
||||
public LinkedList<String> getCommandLabels() {
|
||||
return new LinkedList<>(Collections.singletonList("help"));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<Permission> getPermissions() { return null; }
|
||||
|
||||
@Override
|
||||
public boolean passRawArgs() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Get general help on the bot. Specify a command if you want specific help about that command.";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getUsage() {
|
||||
return "[command]";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public CommandCategory getCategory() {
|
||||
return CommandCategory.TOOLS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runCommand(MessageReceivedEvent event, String label, String[] args)
|
||||
{
|
||||
LinkedHashMap<CommandCategory, LinkedList<MessageCommand>> commandCategories = new LinkedHashMap<>();
|
||||
|
||||
if(args.length == 0)
|
||||
{
|
||||
for(CommandCategory category : CommandCategory.values())
|
||||
{
|
||||
LinkedList<MessageCommand> commandsOfThisCategory = new LinkedList<>();
|
||||
for (MessageCommand command : Cache.getMessageCommandListener().getRegisteredCommands())
|
||||
{
|
||||
if(command.getCategory().equals(category))
|
||||
{
|
||||
commandsOfThisCategory.add(command);
|
||||
}
|
||||
}
|
||||
|
||||
commandCategories.put(category, commandsOfThisCategory);
|
||||
}
|
||||
|
||||
EmbedBuilder embedBuilder = new EmbedBuilder();
|
||||
embedBuilder.setColor(Cache.getBotColor());
|
||||
embedBuilder.setTitle("Bot Help");
|
||||
|
||||
embedBuilder.addField("General Help",
|
||||
"Type `" + Cache.getBotPrefix() + " help [command]` to get help on a specific command." +
|
||||
"\nYou will find a list of commands organized in categories below.",
|
||||
false);
|
||||
|
||||
for(CommandCategory category : commandCategories.keySet())
|
||||
{
|
||||
StringBuilder commandsList = new StringBuilder();
|
||||
LinkedList<MessageCommand> commandsOfThisCategory = commandCategories.get(category);
|
||||
|
||||
for(int pos = 0; pos < commandsOfThisCategory.size(); pos++)
|
||||
{
|
||||
MessageCommand command = commandsOfThisCategory.get(pos);
|
||||
commandsList.append("`").append(command.getCommandLabels().get(0)).append("`");
|
||||
|
||||
if(pos + 1 != commandsOfThisCategory.size())
|
||||
commandsList.append(", "); // separate with comma except on last run
|
||||
}
|
||||
|
||||
String niceCategoryName = category.name().replace("_", " ");
|
||||
niceCategoryName = WordUtils.capitalizeFully(niceCategoryName);
|
||||
niceCategoryName = category.getEmoji() + " " + niceCategoryName;
|
||||
|
||||
embedBuilder.addField(niceCategoryName, commandsList.toString(), false);
|
||||
}
|
||||
|
||||
event.getMessage().replyEmbeds(embedBuilder.build()).queue();
|
||||
} else {
|
||||
|
||||
String commandLabel = args[0].toLowerCase();
|
||||
MessageCommand command = Cache.getMessageCommandListener().getRegisteredCommand(commandLabel);
|
||||
if(command == null)
|
||||
{
|
||||
event.getMessage().reply("Unrecognized command: `" + commandLabel + "`!").queue(); // todo prettier
|
||||
return;
|
||||
}
|
||||
|
||||
commandLabel = command.getCommandLabels().get(0);
|
||||
String usage = "`" + Cache.getBotPrefix() + " " + commandLabel;
|
||||
String internalUsage = command.getUsage();
|
||||
if(internalUsage != null) usage += " " + internalUsage;
|
||||
usage += "`";
|
||||
|
||||
String aliases = Alias.generateNiceAliases(command);
|
||||
|
||||
List<Permission> permissions = command.getPermissions();
|
||||
StringBuilder permissionsStringBuilder = new StringBuilder();
|
||||
if(permissions == null)
|
||||
{
|
||||
permissionsStringBuilder = new StringBuilder("Available to everyone");
|
||||
} else {
|
||||
for(int i = 0; i < permissions.size(); i++)
|
||||
{
|
||||
Permission permission = permissions.get(i);
|
||||
permissionsStringBuilder.append("**").append(permission.getName()).append("**");
|
||||
|
||||
if(i + 1 != permissions.size())
|
||||
permissionsStringBuilder.append(", "); // separate with comma expect on last iteration
|
||||
}
|
||||
}
|
||||
|
||||
String title = command.getCategory().getEmoji() +
|
||||
" \"" + WordUtils.capitalizeFully(commandLabel + "\" help");
|
||||
|
||||
EmbedBuilder embedBuilder = new EmbedBuilder();
|
||||
|
||||
embedBuilder.setColor(Cache.getBotColor());
|
||||
embedBuilder.setTitle(title);
|
||||
|
||||
embedBuilder.addField("Description", command.getDescription(), false);
|
||||
embedBuilder.addField("Usage", usage, false);
|
||||
embedBuilder.addField("Aliases", aliases, false);
|
||||
embedBuilder.addField("Permissions", permissionsStringBuilder.toString(), false);
|
||||
|
||||
event.getMessage().replyEmbeds(embedBuilder.build()).queue();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,8 +5,10 @@ import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
import net.dv8tion.jda.api.entities.emoji.Emoji;
|
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||
import net.dv8tion.jda.api.interactions.components.buttons.Button;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import wtf.beatrice.hidekobot.commands.base.Invite;
|
||||
import wtf.beatrice.hidekobot.objects.commands.CommandCategory;
|
||||
import wtf.beatrice.hidekobot.objects.commands.MessageCommand;
|
||||
|
||||
import java.util.Collections;
|
||||
@@ -32,6 +34,24 @@ public class InviteCommand implements MessageCommand
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Get the bot's invite link.";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getUsage() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public CommandCategory getCategory() {
|
||||
return CommandCategory.MODERATION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runCommand(MessageReceivedEvent event, String label, String[] args)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
package wtf.beatrice.hidekobot.commands.message;
|
||||
|
||||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import net.dv8tion.jda.api.Permission;
|
||||
import net.dv8tion.jda.api.entities.IMentionable;
|
||||
import net.dv8tion.jda.api.entities.Mentions;
|
||||
import net.dv8tion.jda.api.entities.User;
|
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import wtf.beatrice.hidekobot.Cache;
|
||||
import wtf.beatrice.hidekobot.HidekoBot;
|
||||
import wtf.beatrice.hidekobot.objects.commands.CommandCategory;
|
||||
import wtf.beatrice.hidekobot.objects.commands.MessageCommand;
|
||||
import wtf.beatrice.hidekobot.util.RandomUtil;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class LoveCalculatorCommand implements MessageCommand
|
||||
{
|
||||
|
||||
|
||||
@Override
|
||||
public LinkedList<String> getCommandLabels()
|
||||
{
|
||||
return new LinkedList<>(Arrays.asList("lovecalc", "lovecalculator", "lc"));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<Permission> getPermissions() {
|
||||
return null; //anyone can use it
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean passRawArgs() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Calculate how much two people love each other. You can mention two people or just one.";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getUsage() {
|
||||
return "<person 1> [person 2]";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public CommandCategory getCategory() {
|
||||
return CommandCategory.FUN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runCommand(MessageReceivedEvent event, String label, String[] args)
|
||||
{
|
||||
|
||||
Mentions mentionsObj = event.getMessage().getMentions();
|
||||
List<IMentionable> mentions = mentionsObj.getMentions();
|
||||
|
||||
|
||||
if(args.length == 0 || mentions.isEmpty())
|
||||
{
|
||||
event.getMessage()
|
||||
.reply("\uD83D\uDE22 I need to know who to check! Please mention them.")
|
||||
.queue();
|
||||
return;
|
||||
}
|
||||
|
||||
User user1, user2;
|
||||
|
||||
String mentionedUserId = mentions.get(0).getId();
|
||||
user1 = HidekoBot.getAPI().retrieveUserById(mentionedUserId).complete();
|
||||
|
||||
if(mentions.size() == 1)
|
||||
{
|
||||
user2 = event.getAuthor();
|
||||
} else {
|
||||
mentionedUserId = mentions.get(1).getId();
|
||||
user2 = HidekoBot.getAPI().retrieveUserById(mentionedUserId).complete();
|
||||
}
|
||||
|
||||
int loveAmount = RandomUtil.getRandomNumber(0, 100);
|
||||
|
||||
String formattedAmount = loveAmount + "%";
|
||||
if(loveAmount <= 30) formattedAmount += "... \uD83D\uDE22";
|
||||
else if(loveAmount < 60) formattedAmount += "! \uD83E\uDDD0";
|
||||
else if(loveAmount < 75) formattedAmount += "!!! \uD83E\uDD73";
|
||||
else formattedAmount = "✨ " + formattedAmount + "!!! \uD83D\uDE0D\uD83D\uDCA5";
|
||||
|
||||
EmbedBuilder embedBuilder = new EmbedBuilder();
|
||||
embedBuilder.setColor(Cache.getBotColor());
|
||||
embedBuilder.setAuthor(event.getAuthor().getAsTag(), null, event.getAuthor().getAvatarUrl());
|
||||
embedBuilder.setTitle("Love Calculator");
|
||||
|
||||
embedBuilder.addField("\uD83D\uDC65 People",
|
||||
user1.getAsMention() + " & " + user2.getAsMention(),
|
||||
false);
|
||||
|
||||
embedBuilder.addField("❤️\u200D\uD83D\uDD25 Match",
|
||||
formattedAmount,
|
||||
false);
|
||||
|
||||
event.getChannel().sendMessageEmbeds(embedBuilder.build()).queue();
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package wtf.beatrice.hidekobot.commands.message;
|
||||
|
||||
import net.dv8tion.jda.api.Permission;
|
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import wtf.beatrice.hidekobot.commands.base.MagicBall;
|
||||
import wtf.beatrice.hidekobot.objects.commands.CommandCategory;
|
||||
import wtf.beatrice.hidekobot.objects.commands.MessageCommand;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class MagicBallCommand implements MessageCommand
|
||||
{
|
||||
|
||||
@Override
|
||||
public LinkedList<String> getCommandLabels() {
|
||||
return MagicBall.getLabels();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<Permission> getPermissions() {
|
||||
return null; // anyone can use it
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean passRawArgs() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Ask a question to the Magic Ball.";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getUsage() {
|
||||
return "<question>";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public CommandCategory getCategory() {
|
||||
return CommandCategory.FUN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runCommand(MessageReceivedEvent event, String label, String[] args)
|
||||
{
|
||||
if(args.length == 0)
|
||||
{
|
||||
event.getMessage().reply("You need to specify a question!").queue();
|
||||
return;
|
||||
}
|
||||
|
||||
StringBuilder questionBuilder = new StringBuilder();
|
||||
for(int i = 0; i < args.length; i++)
|
||||
{
|
||||
String arg = args[i];
|
||||
questionBuilder.append(arg);
|
||||
if(i + 1 != args.length) // don't add a separator on the last iteration
|
||||
questionBuilder.append(" ");
|
||||
}
|
||||
|
||||
String question = questionBuilder.toString();
|
||||
|
||||
|
||||
event.getChannel().sendMessageEmbeds(MagicBall.generateEmbed(question, event.getAuthor())).queue();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package wtf.beatrice.hidekobot.commands.message;
|
||||
|
||||
import net.dv8tion.jda.api.Permission;
|
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import wtf.beatrice.hidekobot.commands.base.Say;
|
||||
import wtf.beatrice.hidekobot.objects.commands.CommandCategory;
|
||||
import wtf.beatrice.hidekobot.objects.commands.MessageCommand;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class SayCommand implements MessageCommand
|
||||
{
|
||||
|
||||
|
||||
@Override
|
||||
public LinkedList<String> getCommandLabels() {
|
||||
return new LinkedList<>(Collections.singletonList("say"));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<Permission> getPermissions() { return Collections.singletonList(Say.getPermission()); }
|
||||
|
||||
@Override
|
||||
public boolean passRawArgs() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Make the bot say something for you.";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getUsage() {
|
||||
return "<text>";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public CommandCategory getCategory() {
|
||||
return CommandCategory.TOOLS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runCommand(MessageReceivedEvent event, String label, String[] args)
|
||||
{
|
||||
|
||||
String messageContent;
|
||||
if(args.length != 0 && !args[0].isEmpty())
|
||||
{
|
||||
messageContent = args[0];
|
||||
} else {
|
||||
event.getMessage().reply("\uD83D\uDE20 Hey, you have to tell me what to say!")
|
||||
.queue();
|
||||
return;
|
||||
}
|
||||
|
||||
event.getChannel().sendMessage(messageContent).queue();
|
||||
event.getMessage().delete().queue();
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package wtf.beatrice.hidekobot.commands.message;
|
||||
|
||||
import net.dv8tion.jda.api.Permission;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||
import net.dv8tion.jda.api.interactions.components.buttons.Button;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Document;
|
||||
import org.jsoup.select.Elements;
|
||||
import wtf.beatrice.hidekobot.commands.base.UrbanDictionary;
|
||||
import wtf.beatrice.hidekobot.objects.commands.CommandCategory;
|
||||
import wtf.beatrice.hidekobot.objects.commands.MessageCommand;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class UrbanDictionaryCommand implements MessageCommand
|
||||
{
|
||||
|
||||
@Override
|
||||
public LinkedList<String> getCommandLabels() {
|
||||
return UrbanDictionary.getCommandLabels();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<Permission> getPermissions() {
|
||||
return null; //anyone can use it
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean passRawArgs() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Look something up in the Urban Dictionary.";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getUsage() {
|
||||
return "<query>";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public CommandCategory getCategory() {
|
||||
return CommandCategory.FUN;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void runCommand(MessageReceivedEvent event, String label, String[] args)
|
||||
{
|
||||
if(args.length == 0)
|
||||
{
|
||||
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 i = 0; i < args.length; i++) {
|
||||
String arg = args[i];
|
||||
termBuilder.append(arg);
|
||||
|
||||
if(i + 1 != args.length) // add spaces between args, but not on the last run
|
||||
termBuilder.append(" ");
|
||||
}
|
||||
|
||||
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(UrbanDictionary.getTermNotFoundError()).queue();
|
||||
return;
|
||||
}
|
||||
|
||||
Elements definitions = doc.getElementsByClass("definition");
|
||||
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 = UrbanDictionary.getNextPageButton();
|
||||
if(search.getPages() == 1) nextPageBtnLocal = nextPageBtnLocal.asDisabled();
|
||||
|
||||
event.getChannel()
|
||||
.sendMessageEmbeds(embed)
|
||||
.addActionRow(UrbanDictionary.getPreviousPageButton().asDisabled(),
|
||||
//disabled by default because we're on page 0
|
||||
nextPageBtnLocal,
|
||||
UrbanDictionary.getDeleteButton())
|
||||
.queue(message -> UrbanDictionary.track(message, event.getAuthor(), search, term));
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package wtf.beatrice.hidekobot.commands.slash;
|
||||
|
||||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
import net.dv8tion.jda.api.entities.User;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import net.dv8tion.jda.api.interactions.commands.OptionMapping;
|
||||
@@ -8,7 +8,7 @@ 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 org.jetbrains.annotations.NotNull;
|
||||
import wtf.beatrice.hidekobot.Cache;
|
||||
import wtf.beatrice.hidekobot.commands.base.Avatar;
|
||||
import wtf.beatrice.hidekobot.objects.commands.SlashCommandImpl;
|
||||
|
||||
public class AvatarCommand extends SlashCommandImpl
|
||||
@@ -31,9 +31,6 @@ public class AvatarCommand extends SlashCommandImpl
|
||||
User user;
|
||||
int resolution;
|
||||
|
||||
int[] acceptedSizes = Cache.getSupportedAvatarResolutions();
|
||||
|
||||
|
||||
OptionMapping userArg = event.getOption("user");
|
||||
if(userArg != null)
|
||||
{
|
||||
@@ -45,57 +42,12 @@ public class AvatarCommand extends SlashCommandImpl
|
||||
OptionMapping sizeArg = event.getOption("size");
|
||||
if(sizeArg != null)
|
||||
{
|
||||
resolution = sizeArg.getAsInt();
|
||||
|
||||
// method to find closest value to accepted values
|
||||
int distance = Math.abs(acceptedSizes[0] - resolution);
|
||||
int idx = 0;
|
||||
for(int c = 1; c < acceptedSizes.length; c++){
|
||||
int cdistance = Math.abs(acceptedSizes[c] - resolution);
|
||||
if(cdistance < distance){
|
||||
idx = c;
|
||||
distance = cdistance;
|
||||
}
|
||||
}
|
||||
resolution = acceptedSizes[idx];
|
||||
|
||||
resolution = Avatar.parseResolution(sizeArg.getAsInt());
|
||||
} else {
|
||||
resolution = 512;
|
||||
resolution = Avatar.parseResolution(512);
|
||||
}
|
||||
|
||||
EmbedBuilder embedBuilder = new EmbedBuilder();
|
||||
|
||||
// embed processing
|
||||
{
|
||||
embedBuilder.setColor(Cache.getBotColor());
|
||||
embedBuilder.setTitle("Profile picture");
|
||||
|
||||
embedBuilder.addField("User", "<@" + user.getId() + ">", false);
|
||||
|
||||
embedBuilder.addField("Current resolution", resolution + " × " + resolution, false);
|
||||
|
||||
// string builder to create a string that links to all available resolutions
|
||||
StringBuilder links = new StringBuilder();
|
||||
for(int pos = 0; pos < acceptedSizes.length; pos++)
|
||||
{
|
||||
int currSize = acceptedSizes[pos];
|
||||
|
||||
String currLink = user.getEffectiveAvatar().getUrl(currSize);
|
||||
|
||||
links.append("[").append(currSize).append("px](").append(currLink).append(")");
|
||||
if(pos + 1 != acceptedSizes.length) // don't add a separator on the last iteration
|
||||
{
|
||||
links.append(" | ");
|
||||
}
|
||||
}
|
||||
|
||||
embedBuilder.addField("Available resolutions", links.toString(), false);
|
||||
|
||||
|
||||
|
||||
embedBuilder.setImage(user.getEffectiveAvatar().getUrl(resolution));
|
||||
}
|
||||
|
||||
event.getHook().editOriginalEmbeds(embedBuilder.build()).queue();
|
||||
MessageEmbed embed = Avatar.buildEmbed(resolution, user);
|
||||
event.getHook().editOriginalEmbeds(embed).queue();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,6 +44,9 @@ public class ClearCommand extends SlashCommandImpl
|
||||
OptionMapping amountOption = event.getOption("amount");
|
||||
int toDeleteAmount = amountOption == null ? 1 : amountOption.getAsInt();
|
||||
|
||||
// cap the amount to avoid abuse.
|
||||
if(toDeleteAmount > ClearChat.getMaxAmount()) toDeleteAmount = 0;
|
||||
|
||||
error = ClearChat.checkDeleteAmount(toDeleteAmount);
|
||||
if(error != null)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
package wtf.beatrice.hidekobot.commands.slash;
|
||||
|
||||
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 org.jetbrains.annotations.NotNull;
|
||||
import wtf.beatrice.hidekobot.commands.base.MagicBall;
|
||||
import wtf.beatrice.hidekobot.objects.commands.SlashCommandImpl;
|
||||
|
||||
public class MagicBallCommand extends SlashCommandImpl
|
||||
{
|
||||
@Override
|
||||
public CommandData getSlashCommandData()
|
||||
{
|
||||
|
||||
return Commands.slash(MagicBall.getLabels().get(0),
|
||||
"Ask a question to the magic ball.")
|
||||
.addOption(OptionType.STRING, "question",
|
||||
"The question to ask.",
|
||||
true,
|
||||
false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runSlashCommand(@NotNull SlashCommandInteractionEvent event)
|
||||
{
|
||||
// get the asked question
|
||||
OptionMapping textOption = event.getOption("question");
|
||||
String question = "";
|
||||
if(textOption != null)
|
||||
{
|
||||
question = textOption.getAsString();
|
||||
}
|
||||
|
||||
if(textOption == null || question.isEmpty())
|
||||
{
|
||||
event.reply("\uD83D\uDE20 Hey, you have to ask me a question!")
|
||||
.setEphemeral(true)
|
||||
.queue();
|
||||
return;
|
||||
}
|
||||
|
||||
MessageEmbed response = MagicBall.generateEmbed(question, event.getUser());
|
||||
event.replyEmbeds(response).queue();
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
package wtf.beatrice.hidekobot.commands.slash;
|
||||
|
||||
import net.dv8tion.jda.api.Permission;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions;
|
||||
@@ -9,6 +8,7 @@ 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 org.jetbrains.annotations.NotNull;
|
||||
import wtf.beatrice.hidekobot.commands.base.Say;
|
||||
import wtf.beatrice.hidekobot.objects.commands.SlashCommandImpl;
|
||||
|
||||
public class SayCommand extends SlashCommandImpl
|
||||
@@ -22,7 +22,7 @@ public class SayCommand extends SlashCommandImpl
|
||||
"The message to send.",
|
||||
true,
|
||||
false)
|
||||
.setDefaultPermissions(DefaultMemberPermissions.enabledFor(Permission.MESSAGE_MANAGE));
|
||||
.setDefaultPermissions(DefaultMemberPermissions.enabledFor(Say.getPermission()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
package wtf.beatrice.hidekobot.commands.slash;
|
||||
|
||||
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.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.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.getTermNotFoundError())
|
||||
.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));
|
||||
}
|
||||
}
|
||||
@@ -81,6 +81,12 @@ public class DatabaseSource
|
||||
* | 39402849302 | 39402849302 | 39402849302 | 39402849302 | PRIVATE |
|
||||
* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
* TABLE 3: urban_dictionary
|
||||
* -----------------------------------------------------------------------------------------------------
|
||||
* | message_id | page | meanings | examples | contributors | dates | term |
|
||||
* -----------------------------------------------------------------------------------------------------
|
||||
* | 39402849302 | 0 | base64 | base64 | base64 | base64 | miku |
|
||||
* -----------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
//todo: javadocs
|
||||
@@ -104,6 +110,16 @@ public class DatabaseSource
|
||||
"channel_type TEXT NOT NULL" + // channel type (PRIVATE, FORUM, ...)
|
||||
");");
|
||||
|
||||
newTables.add("CREATE TABLE IF NOT EXISTS urban_dictionary (" +
|
||||
"message_id TEXT NOT NULL, " + // message id of the bot's response
|
||||
"page INTEGER NOT NULL," + // page that we are currently on
|
||||
"meanings TEXT NOT NULL," + // list of all meanings, serialized and encoded
|
||||
"examples TEXT NOT NULL, " + // list of all examples, serialized and encoded
|
||||
"contributors TEXT NOT NULL, " + // list of all contributors, serialized and encoded
|
||||
"dates TEXT NOT NULL, " + // list of all submission dates, serialized and encoded
|
||||
"term TEXT NOT NULL" + // the term that was searched
|
||||
");");
|
||||
|
||||
for(String sql : newTables)
|
||||
{
|
||||
try (Statement stmt = dbConnection.createStatement()) {
|
||||
@@ -301,6 +317,17 @@ public class DatabaseSource
|
||||
return false;
|
||||
}
|
||||
|
||||
query = "DELETE FROM urban_dictionary WHERE message_id = ?;";
|
||||
try(PreparedStatement preparedStatement = dbConnection.prepareStatement(query))
|
||||
{
|
||||
preparedStatement.setString(1, messageId);
|
||||
preparedStatement.execute();
|
||||
} catch (SQLException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -373,5 +400,220 @@ public class DatabaseSource
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean trackUrban(String meanings, String examples,
|
||||
String contributors, String dates,
|
||||
Message message, String term)
|
||||
{
|
||||
|
||||
String query = "INSERT INTO urban_dictionary " +
|
||||
"(message_id, page, meanings, examples, contributors, dates, term) VALUES " +
|
||||
" (?, ?, ?, ?, ?, ?, ?);";
|
||||
|
||||
try(PreparedStatement preparedStatement = dbConnection.prepareStatement(query))
|
||||
{
|
||||
preparedStatement.setString(1, message.getId());
|
||||
preparedStatement.setInt(2, 0);
|
||||
preparedStatement.setString(3, meanings);
|
||||
preparedStatement.setString(4, examples);
|
||||
preparedStatement.setString(5, contributors);
|
||||
preparedStatement.setString(6, dates);
|
||||
preparedStatement.setString(7, term);
|
||||
|
||||
preparedStatement.executeUpdate();
|
||||
|
||||
return true;
|
||||
} catch (SQLException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getUrbanPage(String messageId)
|
||||
{
|
||||
String query = "SELECT page " +
|
||||
"FROM urban_dictionary " +
|
||||
"WHERE message_id = ?;";
|
||||
|
||||
try(PreparedStatement preparedStatement = dbConnection.prepareStatement(query))
|
||||
{
|
||||
preparedStatement.setString(1, messageId);
|
||||
ResultSet resultSet = preparedStatement.executeQuery();
|
||||
if(resultSet.isClosed()) return 0;
|
||||
while(resultSet.next())
|
||||
{
|
||||
return resultSet.getInt("page");
|
||||
}
|
||||
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public String getUrbanMeanings(String messageId)
|
||||
{
|
||||
String query = "SELECT meanings " +
|
||||
"FROM urban_dictionary " +
|
||||
"WHERE message_id = ?;";
|
||||
|
||||
try(PreparedStatement preparedStatement = dbConnection.prepareStatement(query))
|
||||
{
|
||||
preparedStatement.setString(1, messageId);
|
||||
ResultSet resultSet = preparedStatement.executeQuery();
|
||||
if(resultSet.isClosed()) return null;
|
||||
while(resultSet.next())
|
||||
{
|
||||
return resultSet.getString("meanings");
|
||||
}
|
||||
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getUrbanExamples(String messageId)
|
||||
{
|
||||
String query = "SELECT examples " +
|
||||
"FROM urban_dictionary " +
|
||||
"WHERE message_id = ?;";
|
||||
|
||||
try(PreparedStatement preparedStatement = dbConnection.prepareStatement(query))
|
||||
{
|
||||
preparedStatement.setString(1, messageId);
|
||||
ResultSet resultSet = preparedStatement.executeQuery();
|
||||
if(resultSet.isClosed()) return null;
|
||||
while(resultSet.next())
|
||||
{
|
||||
return resultSet.getString("examples");
|
||||
}
|
||||
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getUrbanContributors(String messageId)
|
||||
{
|
||||
String query = "SELECT contributors " +
|
||||
"FROM urban_dictionary " +
|
||||
"WHERE message_id = ?;";
|
||||
|
||||
try(PreparedStatement preparedStatement = dbConnection.prepareStatement(query))
|
||||
{
|
||||
preparedStatement.setString(1, messageId);
|
||||
ResultSet resultSet = preparedStatement.executeQuery();
|
||||
if(resultSet.isClosed()) return null;
|
||||
while(resultSet.next())
|
||||
{
|
||||
return resultSet.getString("contributors");
|
||||
}
|
||||
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getUrbanDates(String messageId)
|
||||
{
|
||||
String query = "SELECT dates " +
|
||||
"FROM urban_dictionary " +
|
||||
"WHERE message_id = ?;";
|
||||
|
||||
try(PreparedStatement preparedStatement = dbConnection.prepareStatement(query))
|
||||
{
|
||||
preparedStatement.setString(1, messageId);
|
||||
ResultSet resultSet = preparedStatement.executeQuery();
|
||||
if(resultSet.isClosed()) return null;
|
||||
while(resultSet.next())
|
||||
{
|
||||
return resultSet.getString("dates");
|
||||
}
|
||||
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getUrbanTerm(String messageId)
|
||||
{
|
||||
String query = "SELECT term " +
|
||||
"FROM urban_dictionary " +
|
||||
"WHERE message_id = ?;";
|
||||
|
||||
try(PreparedStatement preparedStatement = dbConnection.prepareStatement(query))
|
||||
{
|
||||
preparedStatement.setString(1, messageId);
|
||||
ResultSet resultSet = preparedStatement.executeQuery();
|
||||
if(resultSet.isClosed()) return null;
|
||||
while(resultSet.next())
|
||||
{
|
||||
return resultSet.getString("term");
|
||||
}
|
||||
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean setUrbanPage(String messageId, int page)
|
||||
{
|
||||
String query = "UPDATE urban_dictionary " +
|
||||
"SET page = ? " +
|
||||
"WHERE message_id = ?;";
|
||||
|
||||
try(PreparedStatement preparedStatement = dbConnection.prepareStatement(query))
|
||||
{
|
||||
preparedStatement.setInt(1, page);
|
||||
preparedStatement.setString(2, messageId);
|
||||
preparedStatement.executeUpdate();
|
||||
|
||||
return true;
|
||||
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean resetExpiryTimestamp(String messageId)
|
||||
{
|
||||
LocalDateTime expiryTime = LocalDateTime.now().plusSeconds(Cache.getExpiryTimeSeconds());
|
||||
|
||||
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(Cache.getExpiryTimestampFormat());
|
||||
String expiryTimeFormatted = dateTimeFormatter.format(expiryTime);
|
||||
|
||||
String query = "UPDATE pending_disabled_messages " +
|
||||
"SET expiry_timestamp = ? " +
|
||||
"WHERE message_id = ?;";
|
||||
|
||||
try(PreparedStatement preparedStatement = dbConnection.prepareStatement(query))
|
||||
{
|
||||
preparedStatement.setString(1, expiryTimeFormatted);
|
||||
preparedStatement.setString(2, messageId);
|
||||
preparedStatement.executeUpdate();
|
||||
|
||||
return true;
|
||||
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -2,8 +2,9 @@ package wtf.beatrice.hidekobot.listeners;
|
||||
|
||||
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.util.CommandUtil;
|
||||
|
||||
public class ButtonInteractionListener extends ListenerAdapter
|
||||
{
|
||||
@@ -17,8 +18,12 @@ public class ButtonInteractionListener extends ListenerAdapter
|
||||
// coinflip
|
||||
case "coinflip_reflip" -> CoinFlip.buttonReFlip(event);
|
||||
|
||||
// clearchat command
|
||||
case "clear_dismiss" -> ClearChat.dismissMessage(event);
|
||||
// generic dismiss button
|
||||
case "generic_dismiss" -> CommandUtil.delete(event);
|
||||
|
||||
// urban dictionary navigation
|
||||
case "urban_nextpage" -> UrbanDictionary.changePage(event, UrbanDictionary.ChangeType.NEXT);
|
||||
case "urban_previouspage" -> UrbanDictionary.changePage(event, UrbanDictionary.ChangeType.PREVIOUS);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -7,14 +7,13 @@ import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel;
|
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||
import net.dv8tion.jda.api.hooks.ListenerAdapter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import wtf.beatrice.hidekobot.Cache;
|
||||
import wtf.beatrice.hidekobot.objects.commands.CommandCategory;
|
||||
import wtf.beatrice.hidekobot.objects.commands.MessageCommand;
|
||||
import wtf.beatrice.hidekobot.objects.comparators.MessageCommandAliasesComparator;
|
||||
import wtf.beatrice.hidekobot.util.Logger;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.TreeMap;
|
||||
import java.util.*;
|
||||
|
||||
public class MessageCommandListener extends ListenerAdapter
|
||||
{
|
||||
@@ -23,6 +22,10 @@ public class MessageCommandListener extends ListenerAdapter
|
||||
private final TreeMap<LinkedList<String>, MessageCommand> registeredCommands =
|
||||
new TreeMap<LinkedList<String>, MessageCommand>(new MessageCommandAliasesComparator());
|
||||
|
||||
// map commands and their categories.
|
||||
// this is not strictly needed but it's better to have it so we avoid looping every time we need to check the cat.
|
||||
LinkedHashMap<CommandCategory, LinkedList<MessageCommand>> commandCategories = new LinkedHashMap<>();
|
||||
|
||||
private final String commandRegex = "(?i)^(hideko|hde)\\b";
|
||||
// (?i) -> case insensitive flag
|
||||
// ^ -> start of string (not in middle of a sentence)
|
||||
@@ -57,10 +60,14 @@ public class MessageCommandListener extends ListenerAdapter
|
||||
@Override
|
||||
public void onMessageReceived(@NotNull MessageReceivedEvent event)
|
||||
{
|
||||
String eventMessage = event.getMessage().getContentDisplay();
|
||||
// check if a bot is sending this message, and ignore it
|
||||
if(event.getAuthor().isBot()) return;
|
||||
|
||||
// warning: we are getting the RAW value of the message content, not the DISPLAY value!
|
||||
String eventMessage = event.getMessage().getContentRaw();
|
||||
|
||||
// check if the sent message matches the bot activation regex (prefix, name, ...)
|
||||
if(!eventMessage.toLowerCase().matches(commandRegex + ".*"))
|
||||
if(!eventMessage.toLowerCase().matches(commandRegex + "((.|\\n)*)"))
|
||||
return;
|
||||
|
||||
// generate args from the string
|
||||
@@ -74,7 +81,9 @@ public class MessageCommandListener extends ListenerAdapter
|
||||
// it will be the whole text as a single element.
|
||||
if(argsString.isEmpty())
|
||||
{
|
||||
event.getMessage().reply("Hello there! ✨").queue();
|
||||
event.getMessage()
|
||||
.reply("Hello there! ✨ Type `" + Cache.getBotPrefix() + " help` to get started!")
|
||||
.queue();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -87,7 +96,11 @@ public class MessageCommandListener extends ListenerAdapter
|
||||
|
||||
if(commandObject == null)
|
||||
{
|
||||
/* temporarily disabled because when people talk about the bot, it replies with this spammy message.
|
||||
|
||||
event.getMessage().reply("Unrecognized command: `" + commandLabel + "`!").queue(); // todo prettier
|
||||
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -120,8 +133,9 @@ public class MessageCommandListener extends ListenerAdapter
|
||||
String[] commandArgs;
|
||||
if(commandObject.passRawArgs())
|
||||
{
|
||||
|
||||
// remove first argument, which is the command label
|
||||
argsString = argsString.replaceAll("^[\\S]+\\s+", "");
|
||||
argsString = argsString.replaceAll("^[\\S]+\\s*", "");
|
||||
// pass all other arguments as a single argument as the first array element
|
||||
commandArgs = new String[]{argsString};
|
||||
}
|
||||
|
||||
45
src/main/java/wtf/beatrice/hidekobot/objects/Dice.java
Normal file
45
src/main/java/wtf/beatrice/hidekobot/objects/Dice.java
Normal file
@@ -0,0 +1,45 @@
|
||||
package wtf.beatrice.hidekobot.objects;
|
||||
|
||||
import wtf.beatrice.hidekobot.util.RandomUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class Dice
|
||||
{
|
||||
private final int sides;
|
||||
private int value = 0;
|
||||
private final UUID uuid;
|
||||
|
||||
public Dice(int sides)
|
||||
{
|
||||
this.sides = sides;
|
||||
this.uuid = UUID.randomUUID();
|
||||
}
|
||||
|
||||
public Dice(Dice old)
|
||||
{
|
||||
this.sides = old.sides;
|
||||
this.value = old.value;
|
||||
this.uuid = UUID.randomUUID();
|
||||
}
|
||||
|
||||
public int getValue()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
public int getSides()
|
||||
{
|
||||
return sides;
|
||||
}
|
||||
|
||||
public void roll()
|
||||
{
|
||||
value = RandomUtil.getRandomNumber(1, sides);
|
||||
}
|
||||
|
||||
public UUID getUUID()
|
||||
{
|
||||
return uuid;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package wtf.beatrice.hidekobot.objects.commands;
|
||||
|
||||
public enum CommandCategory
|
||||
{
|
||||
MODERATION("️\uD83D\uDC40"),
|
||||
FUN("\uD83C\uDFB2"),
|
||||
TOOLS("\uD83D\uDEE0"),
|
||||
|
||||
;
|
||||
|
||||
private String emoji;
|
||||
CommandCategory(String emoji)
|
||||
{
|
||||
this.emoji = emoji;
|
||||
}
|
||||
|
||||
public String getEmoji() { return emoji; }
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package wtf.beatrice.hidekobot.objects.commands;
|
||||
|
||||
import net.dv8tion.jda.api.Permission;
|
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.LinkedList;
|
||||
@@ -39,6 +40,31 @@ public interface MessageCommand
|
||||
*/
|
||||
boolean passRawArgs();
|
||||
|
||||
/**
|
||||
* Say what category this command belongs to.
|
||||
*
|
||||
* @return the command category.
|
||||
*/
|
||||
@NotNull
|
||||
CommandCategory getCategory();
|
||||
|
||||
/**
|
||||
* Say what this command does.
|
||||
*
|
||||
* @return a String explaining what this command does.
|
||||
*/
|
||||
@NotNull
|
||||
String getDescription();
|
||||
|
||||
/**
|
||||
* Say how people should use this command.
|
||||
*
|
||||
* @return a String explaining how to use the command, excluding the bot prefix and command name. Null if no parameter is needed
|
||||
*/
|
||||
@Nullable
|
||||
String getUsage();
|
||||
|
||||
|
||||
/**
|
||||
* Run the command logic by parsing the event and replying accordingly.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package wtf.beatrice.hidekobot.runnables;
|
||||
|
||||
import wtf.beatrice.hidekobot.Cache;
|
||||
|
||||
public class RandomSeedTask implements Runnable
|
||||
{
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Cache.setRandomSeed(System.currentTimeMillis());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package wtf.beatrice.hidekobot.runnables;
|
||||
|
||||
import net.dv8tion.jda.api.entities.Activity;
|
||||
import wtf.beatrice.hidekobot.Cache;
|
||||
import wtf.beatrice.hidekobot.HidekoBot;
|
||||
import wtf.beatrice.hidekobot.util.RandomUtil;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class StatusUpdateTask implements Runnable
|
||||
{
|
||||
|
||||
List<String> statuses = Arrays.asList(
|
||||
"Hatsune Miku: Project DIVA",
|
||||
"Wii Sports",
|
||||
"Excel",
|
||||
"Mii Channel",
|
||||
"Wii Speak",
|
||||
"MineTest",
|
||||
"Mario Kart Wii"
|
||||
);
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
int randomPos = RandomUtil.getRandomNumber(0, statuses.size() - 1);
|
||||
String status = statuses.get(randomPos) + " | " + Cache.getBotPrefix() + " help";
|
||||
HidekoBot.getAPI().getPresence().setActivity(Activity.playing(status));
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,48 @@
|
||||
package wtf.beatrice.hidekobot.util;
|
||||
|
||||
import net.dv8tion.jda.api.JDA;
|
||||
import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent;
|
||||
import net.dv8tion.jda.api.interactions.commands.Command;
|
||||
import net.dv8tion.jda.api.interactions.commands.build.CommandData;
|
||||
import wtf.beatrice.hidekobot.Cache;
|
||||
import wtf.beatrice.hidekobot.HidekoBot;
|
||||
import wtf.beatrice.hidekobot.listeners.MessageCommandListener;
|
||||
import wtf.beatrice.hidekobot.objects.commands.SlashCommand;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class SlashCommandUtil
|
||||
public class CommandUtil
|
||||
{
|
||||
|
||||
private static final Logger logger = new Logger(MessageCommandListener.class);
|
||||
private static final Logger logger = new Logger(CommandUtil.class);
|
||||
|
||||
/**
|
||||
* Function to delete a message when a user clicks the "delete" button attached to that message.
|
||||
* This will check in the database if that user ran the command originally.
|
||||
*
|
||||
* @param event the button interaction event.
|
||||
*/
|
||||
public static void delete(ButtonInteractionEvent event)
|
||||
{
|
||||
// check if the user interacting is the same one who ran the command
|
||||
if (!(Cache.getDatabaseSource().isUserTrackedFor(event.getUser().getId(), event.getMessageId()))) {
|
||||
event.reply("❌ You did not run this command!").setEphemeral(true).queue();
|
||||
return;
|
||||
}
|
||||
|
||||
// delete the message
|
||||
event.getInteraction().getMessage().delete().queue();
|
||||
// no need to manually untrack it from database, it will be purged on the next planned check.
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Method to update slash commands registered on Discord's side.
|
||||
* It runs automatically every time the bot starts, but only updates the commands in case differences
|
||||
* are found, unless forced.
|
||||
*
|
||||
* @param force a boolean specifying if the update should be forced even if no differences were found.
|
||||
*/
|
||||
public static void updateSlashCommands(boolean force)
|
||||
{
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
package wtf.beatrice.hidekobot.util;
|
||||
|
||||
import wtf.beatrice.hidekobot.Cache;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class RandomUtil
|
||||
{
|
||||
private static final Random random = new Random();
|
||||
|
||||
|
||||
/**
|
||||
* Returns a random integer picked in a range.
|
||||
*
|
||||
@@ -29,7 +28,7 @@ public class RandomUtil
|
||||
int difference = (max - min) + 1;
|
||||
|
||||
// find a number between 0 and our range (eg. 5 -> 8 = 0 -> 3)
|
||||
int randomTemp = random.nextInt(difference);
|
||||
int randomTemp = Cache.getRandom().nextInt(difference);
|
||||
|
||||
// add the minimum value, so we are sure to be in the original range (0->5, 1->6, 2->7, 3->8)
|
||||
return randomTemp + min;
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package wtf.beatrice.hidekobot.util;
|
||||
|
||||
import org.apache.commons.lang3.SerializationException;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Base64;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class SerializationUtil
|
||||
{
|
||||
|
||||
public static String serializeBase64(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 e) {
|
||||
throw new SerializationException("Error during serialization", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static LinkedList deserializeBase64(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user