Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tag sorting and searching #490

Merged
merged 2 commits into from
Jun 24, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -84,13 +84,13 @@ public class CustomTagManager {
Set<RestAction<?>> actions = new HashSet<>();
if (tag.isEmbed()) {
if (tag.isReply()) {
actions.add(event.getHook().sendMessageEmbeds(tag.toEmbed()));
actions.add(event.replyEmbeds(tag.toEmbed()));
} else {
actions.add(event.getChannel().sendMessageEmbeds(tag.toEmbed()));
}
} else {
if (tag.isReply()) {
actions.add(event.getHook().sendMessage(tag.getResponse()).setAllowedMentions(List.of()));
actions.add(event.reply(tag.getResponse()).setAllowedMentions(List.of()));
} else {
actions.add(event.getChannel().sendMessage(tag.getResponse()).setAllowedMentions(List.of()));
}
Original file line number Diff line number Diff line change
@@ -18,7 +18,7 @@
import java.util.stream.Collectors;

/**
* <h3>This class represents the /tags command.</h3>
* <h3>This class represents the /tag list command.</h3>
*/
public class TagListSubcommand extends TagsSubcommand {
private final ExecutorService asyncPool;
@@ -43,11 +43,16 @@ public ReplyCallbackAction handleCustomTagsSubcommand(@NotNull SlashCommandInter
asyncPool.execute(()->{
try {
List<CustomTag> tags = customTagRepository.getCustomTagsByGuildId(event.getGuild().getIdLong());
String tagList = tags.stream().map(CustomTag::getName).map(MarkdownUtil::monospace).collect(Collectors.joining(", "));
String tagList = tags
.stream()
.map(CustomTag::getName)
.map(MarkdownUtil::monospace)
.collect(Collectors.joining(", "));
Responses.info(event.getHook(), "Custom Tag List",
String.format(tagList.length() > 0 ? tagList : "No Custom Tags created yet.")).queue();
} catch (DataAccessException e) {
ExceptionLogger.capture(e, TagListSubcommand.class.getSimpleName());
Responses.error(event.getHook(), "An error occured trying to list tags").queue();
}
});
return event.deferReply(false);
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package net.discordjug.javabot.systems.staff_commands.tags.commands;

import java.sql.SQLException;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.stream.Collectors;

import net.discordjug.javabot.data.config.BotConfig;
import net.discordjug.javabot.systems.staff_commands.tags.dao.CustomTagRepository;
import net.discordjug.javabot.systems.staff_commands.tags.model.CustomTag;
import net.discordjug.javabot.util.ExceptionLogger;
import net.discordjug.javabot.util.Responses;
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.SubcommandData;
import net.dv8tion.jda.api.requests.restaction.interactions.InteractionCallbackAction;
import net.dv8tion.jda.api.utils.MarkdownUtil;
import org.jetbrains.annotations.NotNull;
import org.springframework.dao.DataAccessException;

/**
* The /tag search command which lists all tags matching a query.
*/
public class TagSearchSubcommand extends TagsSubcommand {

private final ExecutorService asyncPool;
private final CustomTagRepository customTagRepository;

/**
* The constructor of this class, which sets the corresponding {@link net.dv8tion.jda.api.interactions.commands.build.SlashCommandData}.
* @param botConfig The main configuration of the bot.
* @param asyncPool Thread pool for asynchronous operations.
* @param customTagRepository The repository for accessing tags in the database.
*/
public TagSearchSubcommand(BotConfig botConfig, ExecutorService asyncPool, CustomTagRepository customTagRepository) {
super(botConfig);
this.asyncPool = asyncPool;
this.customTagRepository = customTagRepository;
setCommandData(
new SubcommandData("search", "Searches for tags using a query")
.addOption(OptionType.STRING, "query", "The search query", true));
setRequiredStaff(false);
}

@Override
protected InteractionCallbackAction<?> handleCustomTagsSubcommand(@NotNull SlashCommandInteractionEvent event)
throws SQLException {

String query = event.getOption("query", "", OptionMapping::getAsString);

asyncPool.execute(()->{
try {
List<CustomTag> tags = customTagRepository.search(event.getGuild().getIdLong(), query);
String tagList = tags
.stream()
.map(CustomTag::getName)
.map(MarkdownUtil::monospace)
.collect(Collectors.joining(", "));
Responses.info(event.getHook(), "Custom tags containing \"" + query + "\"",
String.format(tagList.length() > 0 ? tagList : "No Custom Tags have been found.")).queue();
} catch (DataAccessException e) {
ExceptionLogger.capture(e, TagListSubcommand.class.getSimpleName());
Responses.error(event.getHook(), "An error occured trying to search for tags").queue();
}
});
return event.deferReply(false);
}

}
Original file line number Diff line number Diff line change
@@ -11,14 +11,14 @@
import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.build.SubcommandData;
import net.dv8tion.jda.api.requests.restaction.interactions.ReplyCallbackAction;
import net.dv8tion.jda.api.requests.RestAction;

import org.jetbrains.annotations.NotNull;

import java.util.Optional;

/**
* <h3>This class represents the /tag command.</h3>
* <h3>This class represents the /tag view command.</h3>
*/
public class TagViewSubcommand extends TagsSubcommand implements AutoCompletable {
private final CustomTagManager tagManager;
@@ -38,18 +38,17 @@ public TagViewSubcommand(CustomTagManager tagManager, BotConfig botConfig) {
}

@Override
public ReplyCallbackAction handleCustomTagsSubcommand(@NotNull SlashCommandInteractionEvent event) {
public RestAction<?> handleCustomTagsSubcommand(@NotNull SlashCommandInteractionEvent event) {
OptionMapping nameMapping = event.getOption("name");
if (nameMapping == null) {
return Responses.replyMissingArguments(event);
}
Optional<CustomTag> tagOptional = tagManager.getByName(event.getGuild().getIdLong(), nameMapping.getAsString());
if (tagOptional.isPresent()) {
CustomTagManager.handleCustomTag(event, tagOptional.get()).queue();
return CustomTagManager.handleCustomTag(event, tagOptional.get());
} else {
Responses.error(event.getHook(), "Could not find Custom Tag with name `%s`.", nameMapping.getAsString()).queue();
return Responses.error(event, "Could not find Custom Tag with name `%s`.", nameMapping.getAsString());
}
return event.deferReply(false);
}

@Override
Original file line number Diff line number Diff line change
@@ -13,11 +13,12 @@ public class TagsCommand extends SlashCommand {
* adds the corresponding {@link net.dv8tion.jda.api.interactions.commands.Command.Subcommand}s.
* @param tagViewSubcommand /tag view
* @param tagListSubcommand /tag list
* @param tagSearchSubcommand /tag search
*/
public TagsCommand(TagViewSubcommand tagViewSubcommand, TagListSubcommand tagListSubcommand) {
public TagsCommand(TagViewSubcommand tagViewSubcommand, TagListSubcommand tagListSubcommand, TagSearchSubcommand tagSearchSubcommand) {
setCommandData(Commands.slash("tag", "Commands for interacting with Custom Tags.")
.setGuildOnly(true)
);
addSubcommands(tagViewSubcommand, tagListSubcommand);
addSubcommands(tagViewSubcommand, tagListSubcommand, tagSearchSubcommand);
}
}
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@
import net.discordjug.javabot.util.ExceptionLogger;
import net.discordjug.javabot.util.Responses;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import net.dv8tion.jda.api.requests.restaction.interactions.InteractionCallbackAction;
import net.dv8tion.jda.api.requests.RestAction;

import org.jetbrains.annotations.NotNull;

@@ -45,5 +45,5 @@ protected void setRequiredStaff(boolean requireStaff) {
this.requireStaff = requireStaff;
}

protected abstract InteractionCallbackAction<?> handleCustomTagsSubcommand(@NotNull SlashCommandInteractionEvent event) throws SQLException;
protected abstract RestAction<?> handleCustomTagsSubcommand(@NotNull SlashCommandInteractionEvent event) throws SQLException;
}
Original file line number Diff line number Diff line change
@@ -117,9 +117,23 @@ public Optional<CustomTag> findById(long id) throws DataAccessException {
* @return A List with all custom commands.
*/
public List<CustomTag> getCustomTagsByGuildId(long guildId) {
return jdbcTemplate.query("SELECT * FROM custom_tags WHERE guild_id = ?", (rs, row)->this.read(rs),
return jdbcTemplate.query("SELECT * FROM custom_tags WHERE guild_id = ? ORDER BY name", (rs, row)->this.read(rs),
guildId);
}

/**
* Gets all custom commands for the given guild matching a specified query.
* A tag matches the query if the name or reply contains the query.
*
* @param guildId The id of the guild.
* @param query The search query.
* @return A List with all custom commands.
*/
public List<CustomTag> search(long guildId, String query) {
String enhancedQuery = "%" + query + "%";
return jdbcTemplate.query("SELECT * FROM custom_tags WHERE guild_id = ? AND (name LIKE ? OR response LIKE ?) ORDER BY name", (rs, row)->this.read(rs),
guildId, enhancedQuery, enhancedQuery);
}

/**
* Reads the given {@link ResultSet} and constructs a new {@link CustomTag} object.