Start implementing bot info command
continuous-integration/drone/push Build is failing Details

This commit is contained in:
Bea 2022-11-21 12:19:35 +01:00
parent 6e9291c535
commit 79c8f1a95e
6 changed files with 178 additions and 80 deletions

View File

@ -1,9 +1,16 @@
package wtf.beatrice.hidekobot; package wtf.beatrice.hidekobot;
import net.dv8tion.jda.api.interactions.commands.Command;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import wtf.beatrice.hidekobot.database.DatabaseManager; import wtf.beatrice.hidekobot.database.DatabaseManager;
import wtf.beatrice.hidekobot.listeners.MessageLogger; import wtf.beatrice.hidekobot.listeners.MessageLogger;
import java.awt.*;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
public class Configuration public class Configuration
{ {
@ -20,6 +27,16 @@ public class Configuration
// note: discord sets interactions' expiry time to 15 minutes by default, so we can't go higher than that. // note: discord sets interactions' expiry time to 15 minutes by default, so we can't go higher than that.
private final static long expiryTimeSeconds = 60L; private final static long expiryTimeSeconds = 60L;
// used to count eg. uptime
private static LocalDateTime startupTime;
private static final String botVersion = "0.1.1-slash"; // we should probably find a way to make this consistent with Maven
private static final String botName = "HidekoBot";
private static final Color botColor = Color.PINK;
private static final List<Command> registeredCommands = new ArrayList<>();
private final static String defaultInviteLink = private final static String defaultInviteLink =
"https://discord.com/api/oauth2/authorize?client_id=%userid%&scope=bot+applications.commands&permissions=8"; "https://discord.com/api/oauth2/authorize?client_id=%userid%&scope=bot+applications.commands&permissions=8";
@ -134,4 +151,64 @@ public class Configuration
*/ */
public static long getExpiryTimeSeconds() { return expiryTimeSeconds; } public static long getExpiryTimeSeconds() { return expiryTimeSeconds; }
public static String getBotName() { return botName; };
/**
* Get the bot's version.
*
* @return a String of the bot version.
*/
public static String getBotVersion() { return botVersion; }
/**
* Get the bot's global color.
*
* @return the Color object.
*/
public static Color getBotColor() { return botColor; }
/**
* Set the list of registered commands. They will be sorted alphabetically.
*
* @param commands a list of registered commands.
*/
public static void setRegisteredCommands(List<Command> commands)
{
// sort alphabetically by field getName()
List<Command> tempList = commands
.stream()
.sorted(Comparator.comparing(Command::getName))
.toList();
registeredCommands.addAll(tempList);
}
/**
* Get a list of all bot registered commands, sorted alphabetically.
*
* @return a copy of the List.
*/
public static List<Command> getRegisteredCommands()
{
return new ArrayList<>(registeredCommands);
}
/**
* Set the bot's startup time. Generally only used at boot time.
*
* @param time a LocalDateTime of the startup moment.
*/
public static void setStartupTime(LocalDateTime time)
{ startupTime = time; }
/**
* Get the time of when the bot was started up.
*
* @return a LocalDateTime object of the startup instant.
*/
public static LocalDateTime getStartupTime() { return startupTime; }
} }

View File

@ -16,6 +16,7 @@ import wtf.beatrice.hidekobot.utils.Logger;
import wtf.beatrice.hidekobot.utils.SlashCommandsUtil; import wtf.beatrice.hidekobot.utils.SlashCommandsUtil;
import java.io.File; import java.io.File;
import java.time.LocalDateTime;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@ -26,7 +27,6 @@ import java.util.concurrent.TimeUnit;
public class HidekoBot public class HidekoBot
{ {
private static String botToken; private static String botToken;
private static final String version = "0.1.1-slash"; // we should probably find a way to make this consistent with Maven
private static JDA jda; private static JDA jda;
@ -120,13 +120,16 @@ public class HidekoBot
int periodicDelay = 5; int periodicDelay = 5;
scheduler.scheduleAtFixedRate(task, initDelay, periodicDelay, TimeUnit.SECONDS); scheduler.scheduleAtFixedRate(task, initDelay, periodicDelay, TimeUnit.SECONDS);
// print the bot logo.
logger.log("\n\n" + logger.getLogo() + "\nv" + version + " - bot is ready!\n", 2);
// register shutdown interrupt signal listener for proper shutdown. // register shutdown interrupt signal listener for proper shutdown.
Signal.handle(new Signal("INT"), signal -> shutdown()); Signal.handle(new Signal("INT"), signal -> shutdown());
// set startup time.
Configuration.setStartupTime(LocalDateTime.now());
// print the bot logo.
logger.log("\n\n" + logger.getLogo() + "\nv" + Configuration.getBotVersion() + " - bot is ready!\n", 2);
// log the invite-link to console so noob users can just click on it. // log the invite-link to console so noob users can just click on it.
logger.log("Bot User ID: " + botUserId, 3); logger.log("Bot User ID: " + botUserId, 3);
logger.log("Invite Link: " + Configuration.getInviteUrl(), 4); logger.log("Invite Link: " + Configuration.getInviteUrl(), 4);

View File

@ -7,13 +7,12 @@ import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import wtf.beatrice.hidekobot.Configuration; import wtf.beatrice.hidekobot.Configuration;
import java.awt.*;
public class AvatarCommand public class AvatarCommand
{ {
public void runSlashCommand(@NotNull SlashCommandInteractionEvent event) public void runSlashCommand(@NotNull SlashCommandInteractionEvent event)
{ {
// defer reply because this might take a moment
event.deferReply().queue(); event.deferReply().queue();
User user; User user;
@ -55,7 +54,7 @@ public class AvatarCommand
// embed processing // embed processing
{ {
embedBuilder.setColor(Color.PINK); embedBuilder.setColor(Configuration.getBotColor());
embedBuilder.setTitle("Profile picture"); embedBuilder.setTitle("Profile picture");
embedBuilder.addField("User", "<@" + user.getId() + ">", false); embedBuilder.addField("User", "<@" + user.getId() + ">", false);

View File

@ -0,0 +1,85 @@
package wtf.beatrice.hidekobot.commands.slash;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import net.dv8tion.jda.api.interactions.commands.Command;
import org.jetbrains.annotations.NotNull;
import wtf.beatrice.hidekobot.Configuration;
import wtf.beatrice.hidekobot.HidekoBot;
import java.lang.management.ManagementFactory;
import java.text.DecimalFormat;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;
public class BotInfoCommand
{
public void runSlashCommand(@NotNull SlashCommandInteractionEvent event)
{
// defer reply because this might take a moment
event.deferReply().queue();
List<Command> registeredCommands = Configuration.getRegisteredCommands();
EmbedBuilder embedBuilder = new EmbedBuilder();
// embed processing
{
embedBuilder.setColor(Configuration.getBotColor());
embedBuilder.setTitle(Configuration.getBotName());
// thumbnail
String botAvatarUrl = HidekoBot.getAPI().getSelfUser().getAvatarUrl();
if(botAvatarUrl != null) embedBuilder.setThumbnail(botAvatarUrl);
// commands list field
StringBuilder commandsListBuilder = new StringBuilder();
commandsListBuilder.append(registeredCommands.size()).append( " total - ");
for(int i = 0; i < registeredCommands.size(); i++)
{
Command cmd = registeredCommands.get(i);
commandsListBuilder.append("`" + cmd.getName() + "`");
if(i + 1 != registeredCommands.size()) // don't add comma in last iteration
{
commandsListBuilder.append(", ");
}
}
embedBuilder.addField("Commands", commandsListBuilder.toString(), false);
// version field
embedBuilder.addField("Version", "v" + Configuration.getBotVersion(), true);
// jvm version field
String jvmVersion = ManagementFactory.getRuntimeMXBean().getVmVersion();
embedBuilder.addField("JVM Version", "v" + jvmVersion, true);
// used ram field
long usedRamBytes = (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory());
double usedRamMB = usedRamBytes / 1024.0 / 1024.0; // bytes -> kB -> MB
DecimalFormat ramMBFormatter = new DecimalFormat("#.##");
embedBuilder.addField("RAM Usage", ramMBFormatter.format(usedRamMB) + " MB", true);
// author field
String authorMention = "<@" + Configuration.getBotOwnerId() + ">";
embedBuilder.addField("Author", authorMention, true);
// uptime field
LocalDateTime now = LocalDateTime.now();
long uptimeSeconds = ChronoUnit.SECONDS.between(Configuration.getStartupTime(), now);
Duration uptime = Duration.ofSeconds(uptimeSeconds);
uptime.toDaysPart() // todo
embedBuilder.addField("Uptime", "seconds: " + uptime, true);
}
event.getHook().editOriginalEmbeds(embedBuilder.build()).queue();
}
}

View File

@ -13,6 +13,7 @@ public class SlashCommandListener extends ListenerAdapter
{ {
switch (event.getName().toLowerCase()) { switch (event.getName().toLowerCase()) {
case "avatar" -> new AvatarCommand().runSlashCommand(event); case "avatar" -> new AvatarCommand().runSlashCommand(event);
case "botinfo" -> new BotInfoCommand().runSlashCommand(event);
case "clear" -> new ClearChatCommand().runSlashCommand(event); case "clear" -> new ClearChatCommand().runSlashCommand(event);
case "coinflip" -> new CoinFlipCommand().runSlashCommand(event); case "coinflip" -> new CoinFlipCommand().runSlashCommand(event);
case "die" -> new DieCommand().runSlashCommand(event); case "die" -> new DieCommand().runSlashCommand(event);

View File

@ -7,6 +7,7 @@ import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions;
import net.dv8tion.jda.api.interactions.commands.OptionType; 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.CommandData;
import net.dv8tion.jda.api.interactions.commands.build.Commands; import net.dv8tion.jda.api.interactions.commands.build.Commands;
import wtf.beatrice.hidekobot.Configuration;
import wtf.beatrice.hidekobot.HidekoBot; import wtf.beatrice.hidekobot.HidekoBot;
import wtf.beatrice.hidekobot.listeners.MessageListener; import wtf.beatrice.hidekobot.listeners.MessageListener;
@ -23,7 +24,8 @@ public class SlashCommandsUtil
add(Commands.slash("avatar", "Get someone's profile picture.") add(Commands.slash("avatar", "Get someone's profile picture.")
.addOption(OptionType.USER, "user", "User you want to grab the avatar of.") .addOption(OptionType.USER, "user", "User you want to grab the avatar of.")
.addOption(OptionType.INTEGER, "size", "The size of the returned image.", false, true)); .addOption(OptionType.INTEGER, "size", "The size of the returned image.", false, true));
add(Commands.slash("die", "Stop the bot's process") add(Commands.slash("botinfo", "Get info about the bot."));
add(Commands.slash("die", "Stop the bot's process.")
.setDefaultPermissions(DefaultMemberPermissions.DISABLED)); .setDefaultPermissions(DefaultMemberPermissions.DISABLED));
add(Commands.slash("clear", "Clear the current channel's chat.") add(Commands.slash("clear", "Clear the current channel's chat.")
.addOption(OptionType.INTEGER, "amount", "The amount of messages to delete.") .addOption(OptionType.INTEGER, "amount", "The amount of messages to delete.")
@ -118,76 +120,7 @@ public class SlashCommandsUtil
logger.log("Commands updated. New total: " + allCommands.size() + "."); logger.log("Commands updated. New total: " + allCommands.size() + ".");
} }
// cache the registered commands.
Configuration.setRegisteredCommands(jdaInstance.retrieveCommands().complete());
/*
List<CommandData> toAdd = new ArrayList<>();
List<Command> toDelete = new ArrayList<>();
List<Command> registeredCommands = jdaInstance.retrieveCommands().complete();
// for each command that we have already registered...
for(Command currRegCmd : registeredCommands)
{
// queue it for removal.
boolean toRemove = true;
// iterate through all "recognized" commands
for(CommandData cmdData : allCommands)
{
// if we find the same command...
if(cmdData.getName().equals(currRegCmd.getName()))
{
// then don't remove it
toRemove = false;
// and quit the loop since we found it.
break;
}
}
// if no match was found, queue this command for removal.
if(toRemove) toDelete.add(currRegCmd);
}
// for each "recognized" valid command
for(CommandData currCmdData : allCommands)
{
// queue it for registration.
boolean toRegister = true;
// iterate through all already registered commands.
for(Command cmd : registeredCommands)
{
// if this command was already registered...
if(cmd.getName().equals(currCmdData.getName()))
{
// flag that we don't need to register it
toRegister = false;
// and quit the loop since we found a match.
break;
}
}
// if no match was found, queue this command for registration.
if(toRegister) toAdd.add(currCmdData);
}
logger.log("Found " + registeredCommands.size() + " commands.");
// remove all commands queued for removal.
for(Command cmd : toDelete)
{
jdaInstance.deleteCommandById(cmd.getId()).queue();
}
logger.log("Deleted " + toDelete.size() + " commands.");
// register all new commands.
jdaInstance.updateCommands().addCommands(toAdd).queue();
logger.log("Registered " + toAdd.size() + " new commands.");
*/
} }
} }