fix interactions
All checks were successful
Deploy to Dokku / docker (ubuntu-latest) (push) Successful in 1m19s

This commit is contained in:
Lee 2024-07-09 23:02:12 +01:00
parent f1bc2b2aaa
commit 96e7518f72
9 changed files with 319 additions and 212 deletions

@ -191,10 +191,5 @@
<artifactId>mcutils-java-library</artifactId> <artifactId>mcutils-java-library</artifactId>
<version>1.2.4</version> <version>1.2.4</version>
</dependency> </dependency>
<dependency>
<groupId>com.github.ygimenez</groupId>
<artifactId>Pagination-Utils</artifactId>
<version>4.0.6</version>
</dependency>
</dependencies> </dependencies>
</project> </project>

@ -8,6 +8,7 @@ import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.IntegrationType; import net.dv8tion.jda.api.interactions.IntegrationType;
import net.dv8tion.jda.api.interactions.InteractionContextType; import net.dv8tion.jda.api.interactions.InteractionContextType;
import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData; import net.dv8tion.jda.api.interactions.commands.build.OptionData;
@ -66,6 +67,7 @@ public abstract class BatCommand {
} }
info = new InternalCommandInfo(getClass().getAnnotation(CommandInfo.class)); info = new InternalCommandInfo(getClass().getAnnotation(CommandInfo.class));
commandData = new CommandDataImpl(info.getName(), info.getDescription()) commandData = new CommandDataImpl(info.getName(), info.getDescription())
.setDefaultPermissions(DefaultMemberPermissions.enabledFor(info.getPermissions()))
.setIntegrationTypes(info.isUserInstall() ? .setIntegrationTypes(info.isUserInstall() ?
EnumSet.of(IntegrationType.USER_INSTALL) : EnumSet.of(IntegrationType.USER_INSTALL) :
EnumSet.of(IntegrationType.GUILD_INSTALL) EnumSet.of(IntegrationType.GUILD_INSTALL)

@ -5,6 +5,10 @@ import lombok.Getter;
import lombok.NonNull; import lombok.NonNull;
import net.dv8tion.jda.api.entities.emoji.Emoji; import net.dv8tion.jda.api.entities.emoji.Emoji;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
/** /**
* @author Fascinated (fascinated7) * @author Fascinated (fascinated7)
*/ */
@ -43,4 +47,13 @@ public enum Category {
} }
return null; return null;
} }
/**
* Gets the categories sorted by their name
*
* @return the sorted categories
*/
public static List<Category> getSortedByName() {
return Arrays.stream(Category.values()).sorted(Comparator.comparing(Category::getName)).toList();
}
} }

@ -0,0 +1,118 @@
package cc.fascinated.bat.common;
import cc.fascinated.bat.event.EventListener;
import cc.fascinated.bat.model.BatGuild;
import cc.fascinated.bat.model.BatUser;
import cc.fascinated.bat.service.InteractionService;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NonNull;
import net.dv8tion.jda.api.entities.emoji.Emoji;
import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent;
import net.dv8tion.jda.api.events.interaction.component.StringSelectInteractionEvent;
import net.dv8tion.jda.api.interactions.components.ActionComponent;
import net.dv8tion.jda.api.interactions.components.ActionRow;
import net.dv8tion.jda.api.interactions.components.ComponentInteraction;
import net.dv8tion.jda.api.interactions.components.ItemComponent;
import net.dv8tion.jda.api.interactions.components.buttons.Button;
import net.dv8tion.jda.api.interactions.components.selections.SelectMenu;
import net.dv8tion.jda.api.interactions.components.selections.SelectOption;
import net.dv8tion.jda.api.interactions.components.selections.StringSelectMenu;
import net.dv8tion.jda.api.utils.data.SerializableData;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import static net.dv8tion.jda.api.interactions.components.Component.Type.STRING_SELECT;
/**
* @author Fascinated (fascinated7)
*/
@Getter
public class InteractionBuilder {
/**
* The button interactions
*/
private final Map<Button, Consumer<ButtonInteractionEvent>> buttonInteractions = new HashMap<>();
/**
* The select menu interactions
*/
private final Map<SelectOption, Consumer<StringSelectInteractionEvent>> selectMenuInteractions = new HashMap<>();
/**
* The select menu id
*/
private String selectMenuId;
public InteractionBuilder() {
InteractionService.INSTANCE.addInteractionBuilder(this);
}
/**
* Adds a button to the interaction builder
*
* @param display The display of the button
* @param onClick The consumer to run when the button is clicked
* @return - The interaction builder
*/
public InteractionBuilder addButton(String display, Consumer<ButtonInteractionEvent> onClick) {
String id = StringUtils.randomString(8);
this.buttonInteractions.put(Button.primary(id, display), onClick);
return this;
}
/**
* Adds a URL button to the interaction builder
*
* @param display The display of the button
* @param url The url to open when the button is clicked
* @return - The interaction builder
*/
public InteractionBuilder addUrlButton(String display, String url, Emoji emoji) {
this.buttonInteractions.put(Button.link(url, display).withEmoji(emoji), event -> {});
return this;
}
/**
* Adds a string selection to the interaction builder
*
* @param display the name of the selection
* @param description the description of the selection
* @param emoji the emoji of the selection
* @param onClick the consumer to run when the selection is clicked
* @return the interaction builder
*/
public InteractionBuilder addStringSelect(String display, String description, Emoji emoji, Consumer<StringSelectInteractionEvent> onClick) {
String id = StringUtils.randomString(8);
this.selectMenuInteractions.put(SelectOption.of(display, id).withDescription(description).withEmoji(emoji), onClick);
return this;
}
/**
* Builds the interactions into an action row
*
* @return The action row
*/
public List<ActionRow> build() {
List<ActionRow> components = new ArrayList<>();
if (!this.getButtonInteractions().isEmpty()) {
List<Button> buttons = new ArrayList<>(this.getButtonInteractions().keySet());
components.add(ActionRow.of(buttons));
}
if (!this.getSelectMenuInteractions().isEmpty()) {
List<SelectOption> options = new ArrayList<>(this.getSelectMenuInteractions().keySet());
String id = StringUtils.randomString(8);
this.selectMenuId = id;
components.add(ActionRow.of(StringSelectMenu.create(id)
.addOptions(options)
.build()));
}
return components;
}
}

@ -1,10 +1,13 @@
package cc.fascinated.bat.features.base.commands.general; package cc.fascinated.bat.features.base.commands.general;
import cc.fascinated.bat.Consts; import cc.fascinated.bat.Consts;
import cc.fascinated.bat.Emojis;
import cc.fascinated.bat.command.BatCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.Category; import cc.fascinated.bat.command.Category;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.DescriptionBuilder;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.common.InteractionBuilder;
import cc.fascinated.bat.event.EventListener; import cc.fascinated.bat.event.EventListener;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.model.BatGuild;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.model.BatUser;
@ -13,28 +16,23 @@ import lombok.NonNull;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.MessageEmbed; import net.dv8tion.jda.api.entities.MessageEmbed;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; 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.StringSelectInteractionEvent;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.SubcommandData;
import net.dv8tion.jda.api.interactions.components.ActionRow;
import net.dv8tion.jda.api.interactions.components.LayoutComponent;
import net.dv8tion.jda.api.interactions.components.buttons.Button;
import net.dv8tion.jda.api.interactions.components.buttons.ButtonStyle;
import net.dv8tion.jda.api.interactions.components.selections.SelectOption;
import net.dv8tion.jda.api.interactions.components.selections.StringSelectMenu;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.util.ArrayList; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* @author Fascinated (fascinated7) * @author Fascinated (fascinated7)
*/ */
@Component @Component
@CommandInfo(name = "help", description = "View the bots command categories.", guildOnly = false, userInstall = true, category = Category.GENERAL) @CommandInfo(
name = "help",
description = "View the bots command categories",
userInstall = true,
category = Category.GENERAL
)
public class HelpCommand extends BatCommand implements EventListener { public class HelpCommand extends BatCommand implements EventListener {
private final CommandService commandService; private final CommandService commandService;
@ -45,68 +43,52 @@ public class HelpCommand extends BatCommand implements EventListener {
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) {
event.replyEmbeds(createHomeEmbed(event.isFromGuild())).addComponents(createHomeActions(event.isFromGuild())).queue(); InteractionBuilder interactionBuilder = new InteractionBuilder();
} interactionBuilder.addUrlButton("Invite Me", Consts.INVITE_URL, null);
interactionBuilder.addUrlButton("Support Server", Consts.SUPPORT_INVITE_URL, null);
@Override interactionBuilder.addStringSelect("Home", "Return Home", Emojis.HOME_EMOJI, (buttonEvent) -> {
public void onStringSelectInteraction(BatGuild guild, @NonNull BatUser user, @NonNull StringSelectInteractionEvent event) { buttonEvent.editMessageEmbeds(createHomeEmbed(event.isFromGuild())).queue();
if (!event.getComponentId().startsWith("help")) { });
return; for (Category category : Category.getSortedByName()) {
} List<BatCommand> categoryCommands = commandService.getCommandsByCategory(category, event.isFromGuild());
if (categoryCommands.isEmpty()) {
// Get the item continue;
String item = event.getSelectedOptions().get(0).getValue();
if (item.equalsIgnoreCase("help-home")) {
event.editMessageEmbeds(createHomeEmbed(event.isFromGuild())).queue();
return;
}
// Get the category
Category category = Category.getByName(item.split("-")[1]);
if (category == null) {
event.reply("Invalid category selected.")
.setEphemeral(true)
.queue();
return;
}
// Send the category
StringBuilder commands = new StringBuilder();
List<BatCommand> categoryCommands = commandService.getCommandsByCategory(category, event.isFromGuild());
if (categoryCommands.isEmpty()) {
commands = new StringBuilder("No commands available in this category.");
} else {
for (BatCommand command : categoryCommands) {
if (!command.getSubCommands().isEmpty()) {
for (Map.Entry<String, BatCommand> entry : command.getSubCommands().entrySet()) {
BatCommand subCommand = entry.getValue();
SubcommandData subcommandData = subCommand.getSubcommandData();
commands.append("</%s %s:%s> - %s\n".formatted(
command.getInfo().getName(),
subcommandData.getName(),
subCommand.getSnowflake(),
subcommandData.getDescription()
));
}
continue;
}
commands.append("</%s:%s> - %s\n".formatted(
command.getInfo().getName(),
command.getSnowflake(),
command.getInfo().getDescription()
));
} }
interactionBuilder.addStringSelect(
category.getName(),
"View commands in the %s category".formatted(category.getName()),
category.getEmoji(),
(buttonEvent) -> {
DescriptionBuilder description = new DescriptionBuilder(null);
description.appendLine("Commands in the **%s** Category".formatted(category.getName()), false);
description.emptyLine();
for (BatCommand command : categoryCommands) {
if (!command.getSubCommands().isEmpty()) {
for (BatCommand subCommand : command.getSubCommands().values()) {
description.appendLine("`%s %s` - %s".formatted(
command.getInfo().getName(),
subCommand.getInfo().getName(),
subCommand.getInfo().getDescription()
), true);
}
continue;
}
description.appendLine("`%s` - %s".formatted(
command.getInfo().getName(),
command.getInfo().getDescription()
), true);
}
buttonEvent.editMessageEmbeds(EmbedUtils.genericEmbed()
.setDescription(description.build())
.build()).queue();
});
} }
int subCommands = categoryCommands.stream().mapToInt(command -> command.getSubCommands().size()).sum();
event.editMessageEmbeds(EmbedUtils.genericEmbed()
.setAuthor("%s Category".formatted(category.getName())) event.replyEmbeds(createHomeEmbed(event.isFromGuild())).addComponents(interactionBuilder.build()).queue();
.setDescription("%s command%s (with %s sub-command%s)\n\n**Commands:**\n%s".formatted(
categoryCommands.size(),
categoryCommands.size() == 1 ? "" : "s",
subCommands,
subCommands == 1 ? "" : "s",
commands.toString()
)).build()).queue();
} }
/** /**
@ -131,7 +113,7 @@ public class HelpCommand extends BatCommand implements EventListener {
return EmbedUtils.genericEmbed() return EmbedUtils.genericEmbed()
.setDescription(""" .setDescription("""
**Welcome to the Bat Help Menu!**%s **Welcome to the Bat Help Menu!**%s
%s %s
*View our [TOS](%s) and [Privacy Policy](%s) for more information.* *View our [TOS](%s) and [Privacy Policy](%s) for more information.*
""".formatted( """.formatted(
@ -142,38 +124,4 @@ public class HelpCommand extends BatCommand implements EventListener {
)) ))
.build(); .build();
} }
/**
* Creates the home actions for the help command
*
* @return The layout components
*/
private LayoutComponent[] createHomeActions(boolean ranInsideGuild) {
List<SelectOption> options = new ArrayList<>();
options.add(SelectOption.of("Home", "help-home")
.withEmoji(Emoji.fromUnicode("U+1F3E0"))
.withDescription("Return to the Home menu")
);
for (Category category : Category.values()) {
if (commandService.getCommandsByCategory(category, ranInsideGuild).isEmpty()) {
continue;
}
options.add(SelectOption.of(category.getName(), "help-" + category.getName())
.withEmoji(category.getEmoji())
.withDescription("View commands in the %s category".formatted(category.getName()))
);
}
return new LayoutComponent[]{
ActionRow.of(
Button.of(ButtonStyle.LINK, Consts.INVITE_URL, "Invite"),
Button.of(ButtonStyle.LINK, Consts.SUPPORT_INVITE_URL, "Support")
),
ActionRow.of(
StringSelectMenu.create("help-menu")
.addOptions(options)
.build()
)
};
}
} }

@ -5,6 +5,8 @@ import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.DescriptionBuilder; import cc.fascinated.bat.common.DescriptionBuilder;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.common.InteractionBuilder;
import cc.fascinated.bat.common.StringUtils;
import cc.fascinated.bat.event.EventListener; import cc.fascinated.bat.event.EventListener;
import cc.fascinated.bat.features.logging.LogCategory; import cc.fascinated.bat.features.logging.LogCategory;
import cc.fascinated.bat.features.logging.LogProfile; import cc.fascinated.bat.features.logging.LogProfile;
@ -17,9 +19,11 @@ import net.dv8tion.jda.api.entities.MessageEmbed;
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent;
import net.dv8tion.jda.api.events.interaction.component.StringSelectInteractionEvent;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.components.ActionRow; import net.dv8tion.jda.api.interactions.components.ActionRow;
import net.dv8tion.jda.api.interactions.components.buttons.Button; import net.dv8tion.jda.api.interactions.components.selections.SelectOption;
import net.dv8tion.jda.api.interactions.components.selections.StringSelectMenu;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.util.ArrayList; import java.util.ArrayList;
@ -33,62 +37,36 @@ import java.util.List;
public class ListSubCommand extends BatCommand implements EventListener { public class ListSubCommand extends BatCommand implements EventListener {
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) {
List<Button> buttons = new ArrayList<>();
buttons.add(Button.primary("logs-home", "Home").withEmoji(Emojis.HOME_EMOJI));
for (LogCategory category : LogCategory.values()) {
buttons.add(Button.primary("logs:list:%s".formatted(category.name().toLowerCase()), category.getName()).withEmoji(category.getEmoji()));
}
event.replyEmbeds(getHelpMessage()).addComponents(ActionRow.of(buttons)).queue();
}
@Override
public void onButtonInteraction(BatGuild guild, @NonNull BatUser user, @NonNull ButtonInteractionEvent event) {
if (guild == null || event.getMember() == null) {
return;
}
// Not a log button
if (!event.getComponentId().startsWith("logs")) {
return;
}
// No permissions
if (!event.getMember().hasPermission(this.getInfo().getPermissions())) {
event.reply("%s, you cannot use this button.".formatted(user.getDiscordUser().getAsMention()))
.setEphemeral(true)
.queue();
return;
}
// Home
if (event.getComponentId().equals("logs-home")) {
event.editMessageEmbeds(getHelpMessage()).queue();
return;
}
// Category
String[] split = event.getComponentId().split(":");
if (split.length != 3) {
return;
}
LogProfile profile = guild.getLogProfile(); LogProfile profile = guild.getLogProfile();
LogCategory category = LogCategory.getLogCategory(split[2].toUpperCase());
if (category == null) { InteractionBuilder interactionBuilder = new InteractionBuilder();
return; interactionBuilder.addStringSelect("Home", "Return Home", Emojis.HOME_EMOJI, (buttonEvent) -> {
buttonEvent.editMessageEmbeds(getHelpMessage()).queue();
});
for (LogCategory category : LogCategory.values()) {
List<LogType> logEvents = LogType.getLogTypesByCategory(category.getName());
DescriptionBuilder description = new DescriptionBuilder(null);
description.appendLine("Log channels for the `%s` category".formatted(category.getName()), false);
description.emptyLine();
for (LogType logType : logEvents) {
if (logType.getCategory() != category) {
continue;
}
TextChannel logChannel = profile.getLogChannel(logType);
description.appendLine("%s: %s".formatted(logType.getName(), logChannel == null ? "Not Set" : logChannel.getAsMention()), true);
}
interactionBuilder.addStringSelect(
category.getName(),
"View log events in the %s category".formatted(category.getName()),
category.getEmoji(),
(buttonEvent) -> buttonEvent.editMessageEmbeds(EmbedUtils.genericEmbed().setDescription(description.build()).build()).queue()
);
} }
List<LogType> logEvents = LogType.getLogTypesByCategory(category.getName());
DescriptionBuilder description = new DescriptionBuilder(null); event.replyEmbeds(getHelpMessage()).addComponents(interactionBuilder.build()).queue();
description.appendLine("Log channels for the `%s` category".formatted(category.getName()), false);
description.emptyLine();
for (LogType logType : logEvents) {
if (logType.getCategory() != category) {
continue;
}
TextChannel logChannel = profile.getLogChannel(logType);
description.appendLine("%s: %s".formatted(logType.getName(), logChannel == null ? "Not Set" : logChannel.getAsMention()), true);
}
event.editMessageEmbeds(EmbedUtils.genericEmbed().setDescription(description.build()).build()).queue();
} }
/** /**
@ -106,7 +84,7 @@ public class ListSubCommand extends BatCommand implements EventListener {
To remove a log channel, it's the same as setting it, To remove a log channel, it's the same as setting it,
but with `/logs remove` instead of `/logs set` but with `/logs remove` instead of `/logs set`
\s \s
*Use the buttons below to see the log events for each category* *Use the menu below to see the log events for each category*
""", false).build()).build(); """, false).build()).build();
} }
} }

@ -9,13 +9,9 @@ import cc.fascinated.bat.features.moderation.punish.PunishmentProfile;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.model.BatGuild;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.model.BatUser;
import cc.fascinated.bat.service.UserService; import cc.fascinated.bat.service.UserService;
import com.github.ygimenez.method.Pages;
import com.github.ygimenez.model.InteractPage;
import com.github.ygimenez.model.Page;
import lombok.NonNull; import lombok.NonNull;
import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.MessageEmbed;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
@ -24,7 +20,6 @@ import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
@ -64,46 +59,28 @@ public class PunishHistoryCommand extends BatCommand {
PunishmentProfile profile = guild.getPunishmentProfile(); PunishmentProfile profile = guild.getPunishmentProfile();
List<Punishment> punishments = profile.getPunishments(targetUser); List<Punishment> punishments = profile.getPunishments(targetUser);
List<Page> pages = new ArrayList<>(); // todo: pagination
int totalPages = (int) Math.ceil((double) punishments.size() / PUNISHMENTS_PER_PAGE); DescriptionBuilder history = new DescriptionBuilder("Punishment history for %s".formatted(targetUser.getDiscordUser().getAsMention()));
if (!punishments.isEmpty()) {
if (totalPages >= 1) { for (int i = 0; i < Math.min(punishments.size(), 10); i++) {
for (int i = 0; i < totalPages; i++) { Punishment punishment = punishments.get(i);
int fromIndex = i * PUNISHMENTS_PER_PAGE; BatUser issuer = userService.getUser(punishment.getIssuer());
int toIndex = Math.min(fromIndex + PUNISHMENTS_PER_PAGE, punishments.size()); history.appendLine("> **[%s%s]** <t:%s:R> Reason: `%s` | Issuer: %s%s".formatted(
List<Punishment> subList = punishments.subList(fromIndex, toIndex); punishment.getEndDate() != null ? "TEMP-" : "",
DescriptionBuilder history = new DescriptionBuilder("Punishment history for %s".formatted(targetUser.getDiscordUser().getAsMention())); punishment.getType().name(),
punishment.getIssuedDate().toInstant().getEpochSecond(),
for (Punishment punishment : subList) { punishment.getReason() == null ? "N/A" : punishment.getReason(),
BatUser issuer = userService.getUser(punishment.getIssuer()); issuer.getDiscordUser().getAsMention(),
history.appendLine("> **[%s%s]** <t:%s:R> Reason: `%s` | Issuer: %s%s".formatted( punishment.isExpired() ? " **(Expired)**" : ""
punishment.getEndDate() != null ? "TEMP-" : "", ), false);
punishment.getType().name(),
punishment.getIssuedDate().toInstant().getEpochSecond(),
punishment.getReason() == null ? "N/A" : punishment.getReason(),
issuer.getDiscordUser().getAsMention(),
punishment.isExpired() ? " **(Expired)**" : ""
), false);
}
pages.add(InteractPage.of(EmbedUtils.successEmbed()
.setDescription(history.build())
.setFooter("Page %d/%d".formatted(i + 1, totalPages))
.build()));
} }
} else { } else {
pages.add(InteractPage.of(EmbedUtils.successEmbed() history.appendLine("No punishments found", false);
.setDescription("No punishments found for %s".formatted(targetUser.getDiscordUser().getAsMention()))
.build()));
} }
event.replyEmbeds((MessageEmbed) pages.get(0).getContent()).queue(success -> { event.replyEmbeds(EmbedUtils.genericEmbed()
if (pages.size() < 2) { // If there is only one page, we don't need to paginate .setDescription(history.build())
return; .build()
} ).queue();
success.retrieveOriginal().queue(message -> {
Pages.paginate(message, pages, true, (interactedUser) -> interactedUser.getIdLong() == user.getDiscordUser().getIdLong());
});
});
} }
} }

@ -4,8 +4,6 @@ import cc.fascinated.bat.common.NumberFormatter;
import cc.fascinated.bat.common.TimerUtils; import cc.fascinated.bat.common.TimerUtils;
import cc.fascinated.bat.config.Config; import cc.fascinated.bat.config.Config;
import cc.fascinated.bat.event.EventListener; import cc.fascinated.bat.event.EventListener;
import com.github.ygimenez.method.Pages;
import com.github.ygimenez.model.PaginatorBuilder;
import lombok.Getter; import lombok.Getter;
import lombok.NonNull; import lombok.NonNull;
import lombok.extern.log4j.Log4j2; import lombok.extern.log4j.Log4j2;
@ -62,7 +60,6 @@ public class DiscordService implements EventListener {
CacheFlag.ONLINE_STATUS CacheFlag.ONLINE_STATUS
).build() ).build()
.awaitReady(); .awaitReady();
Pages.activate(PaginatorBuilder.createSimplePaginator(JDA)); // Activate the paginator
log.info("Connected to Discord as {}", JDA.getSelfUser().getEffectiveName()); log.info("Connected to Discord as {}", JDA.getSelfUser().getEffectiveName());
TimerUtils.scheduleRepeating(this::updateActivity, 0, 1000 * 60 * 2); TimerUtils.scheduleRepeating(this::updateActivity, 0, 1000 * 60 * 2);
} }

@ -0,0 +1,79 @@
package cc.fascinated.bat.service;
import cc.fascinated.bat.common.InteractionBuilder;
import cc.fascinated.bat.event.EventListener;
import cc.fascinated.bat.model.BatGuild;
import cc.fascinated.bat.model.BatUser;
import lombok.NonNull;
import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent;
import net.dv8tion.jda.api.events.interaction.component.StringSelectInteractionEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import net.dv8tion.jda.api.interactions.components.buttons.Button;
import net.dv8tion.jda.api.interactions.components.selections.SelectOption;
import org.jetbrains.annotations.NotNull;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Consumer;
/**
* @author Fascinated (fascinated7)
*/
@Service
@DependsOn("discordService")
public class InteractionService extends ListenerAdapter {
public static InteractionService INSTANCE;
/**
* The interactions to handle
*/
private final List<InteractionBuilder> interactions = new ArrayList<>();
public InteractionService() {
INSTANCE = this;
DiscordService.JDA.addEventListener(this);
}
/**
* Adds an interaction builder to the service
*
* @param interactionBuilder - The interaction builder to add
*/
public void addInteractionBuilder(@NonNull InteractionBuilder interactionBuilder) {
this.interactions.add(interactionBuilder);
}
@Override
public void onButtonInteraction(@NotNull ButtonInteractionEvent event) {
for (InteractionBuilder interactionBuilder : interactions) {
for (Map.Entry<Button, Consumer<ButtonInteractionEvent>> entry : interactionBuilder.getButtonInteractions().entrySet()) {
Button button = entry.getKey();
if (!Objects.equals(button.getId(), event.getComponentId())) {
continue;
}
entry.getValue().accept(event);
break;
}
}
}
@Override
public void onStringSelectInteraction(@NotNull StringSelectInteractionEvent event) {
for (InteractionBuilder interactionBuilder : interactions) {
if (!Objects.equals(interactionBuilder.getSelectMenuId(), event.getComponentId())) {
continue;
}
for (Map.Entry<SelectOption, Consumer<StringSelectInteractionEvent>> entry : interactionBuilder.getSelectMenuInteractions().entrySet()) {
SelectOption selectOption = entry.getKey();
if (selectOption.getValue().equals(event.getSelectedOptions().get(0).getValue())) {
entry.getValue().accept(event);
break;
}
}
}
}
}