move util to service
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/promote/production Build is passing

This commit is contained in:
2025-09-05 01:35:15 +02:00
parent f80a49995b
commit 29f486566b
7 changed files with 29 additions and 29 deletions

View File

@@ -0,0 +1,247 @@
package wtf.beatrice.hidekobot.services;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.entities.channel.ChannelType;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
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 net.dv8tion.jda.api.interactions.components.LayoutComponent;
import net.dv8tion.jda.api.requests.RestAction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import wtf.beatrice.hidekobot.Cache;
import wtf.beatrice.hidekobot.HidekoBot;
import wtf.beatrice.hidekobot.objects.commands.SlashCommand;
import java.util.ArrayList;
import java.util.List;
@Component
public class CommandService
{
private static final Logger LOGGER = LoggerFactory.getLogger(CommandService.class);
private final DatabaseService databaseService;
public CommandService(@Autowired DatabaseService databaseService)
{
this.databaseService = databaseService;
}
/**
* 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 void deleteUserLinkedMessage(ButtonInteractionEvent event)
{
// check if the user interacting is the same one who ran the command
if (!databaseService.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 void updateSlashCommands(boolean force)
{
// populate commands list from registered commands
List<CommandData> allCommands = new ArrayList<>();
for (SlashCommand cmd : Cache.getSlashCommandListener().getRegisteredCommands())
{
allCommands.add(cmd.getSlashCommandData());
}
JDA jdaInstance = HidekoBot.getAPI();
// get all the already registered commands
List<Command> registeredCommands = jdaInstance.retrieveCommands().complete();
boolean update = false;
if (force)
{
update = true;
} else
{
// for each command that we have already registered...
for (Command currRegCmd : registeredCommands)
{
boolean found = false;
// iterate through all "recognized" commands
for (CommandData cmdData : allCommands)
{
// if we find the same command...
if (cmdData.getName().equals(currRegCmd.getName()))
{
// quit the loop since we found it.
found = true;
break;
}
}
// if no match was found, we need to send an updated command list because
// an old command was probably removed.
if (!found)
{
update = true;
// quit the loop since we only need to trigger this once.
break;
}
}
// if an update is not already queued...
if (!update)
{
// for each "recognized" valid command
for (CommandData currCmdData : allCommands)
{
boolean found = false;
// iterate through all already registered commands.
for (Command cmd : registeredCommands)
{
// if this command was already registered...
if (cmd.getName().equals(currCmdData.getName()))
{
// quit the loop since we found a match.
found = true;
break;
}
}
// if no match was found, we need to send an updated command list because
// a new command was probably added.
if (!found)
{
update = true;
// quit the loop since we only need to trigger this once.
break;
}
}
}
}
LOGGER.info("Found {} commands.", registeredCommands.size());
if (update)
{
// send updated command list.
jdaInstance.updateCommands().addCommands(allCommands).queue();
LOGGER.info("Commands updated. New total: {}.", allCommands.size());
}
}
/**
* Method to disable all buttons from an expired message.
*
* @param messageId the message id to disable.
*/
public void disableExpired(String messageId)
{
String channelId = databaseService.getQueuedExpiringMessageChannel(messageId);
// todo: warning, the following method + related if check are thread-locking.
// todo: we should probably merge the two tables somehow, since they have redundant information.
ChannelType msgChannelType = databaseService.getTrackedMessageChannelType(messageId);
MessageChannel textChannel = null;
// this should never happen, but only message channels are supported.
if (!msgChannelType.isMessage())
{
databaseService.untrackExpiredMessage(messageId);
return;
}
// if this is a DM
if (!(msgChannelType.isGuild()))
{
String userId = databaseService.getTrackedReplyUserId(messageId);
User user = userId == null ? null : HidekoBot.getAPI().retrieveUserById(userId).complete();
if (user == null)
{
// if user is not found, consider it expired
// (deleted profile, or blocked the bot)
databaseService.untrackExpiredMessage(messageId);
return;
}
textChannel = user.openPrivateChannel().complete();
} else
{
String guildId = databaseService.getQueuedExpiringMessageGuild(messageId);
Guild guild = guildId == null ? null : HidekoBot.getAPI().getGuildById(guildId);
if (guild == null)
{
// if guild is not found, consider it expired
// (server was deleted or bot was kicked)
databaseService.untrackExpiredMessage(messageId);
return;
}
textChannel = guild.getTextChannelById(channelId);
}
if (textChannel == null)
{
// if channel is not found, count it as expired
// (channel was deleted or bot permissions restricted)
databaseService.untrackExpiredMessage(messageId);
return;
}
RestAction<Message> retrieveAction = textChannel.retrieveMessageById(messageId);
if (Cache.isVerbose()) LOGGER.info("cleaning up: {}", messageId);
retrieveAction.queue(
message -> {
if (message == null)
{
databaseService.untrackExpiredMessage(messageId);
return;
}
List<LayoutComponent> components = message.getComponents();
List<LayoutComponent> newComponents = new ArrayList<>();
for (LayoutComponent component : components)
{
component = component.asDisabled();
newComponents.add(component);
}
message.editMessageComponents(newComponents).queue();
databaseService.untrackExpiredMessage(messageId);
},
error -> databaseService.untrackExpiredMessage(messageId));
}
}