-
-
Notifications
You must be signed in to change notification settings - Fork 102
tag qol #602
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 qol #602
Changes from 7 commits
4ff1dc1
53ed3f0
a2c7a63
4632190
82725aa
f45bf2e
c6885a2
d3e9e5d
1217a4e
f0ac722
0e6e8fc
9cfdc39
e137e05
94d1353
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,15 +1,19 @@ | ||
| package org.togetherjava.tjbot.commands.tags; | ||
|
|
||
| import net.dv8tion.jda.api.EmbedBuilder; | ||
| import net.dv8tion.jda.api.entities.IMentionable; | ||
| import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; | ||
| import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; | ||
| import net.dv8tion.jda.api.interactions.callbacks.IReplyCallback; | ||
| import net.dv8tion.jda.api.interactions.commands.OptionMapping; | ||
| import net.dv8tion.jda.api.interactions.commands.OptionType; | ||
| import net.dv8tion.jda.api.requests.restaction.interactions.ReplyCallbackAction; | ||
| import org.togetherjava.tjbot.commands.CommandVisibility; | ||
| import org.togetherjava.tjbot.commands.SlashCommandAdapter; | ||
|
|
||
| import java.time.Instant; | ||
| import java.util.List; | ||
| import java.util.Objects; | ||
| import java.util.Optional; | ||
|
|
||
| /** | ||
| * Implements the {@code /tag} command which lets the bot respond content of a tag that has been | ||
|
|
@@ -46,20 +50,40 @@ public void onSlashCommand(SlashCommandInteractionEvent event) { | |
| String id = Objects.requireNonNull(event.getOption(ID_OPTION)).getAsString(); | ||
| OptionMapping replyToUserOption = event.getOption(REPLY_TO_USER_OPTION); | ||
|
|
||
| if (tagSystem.handleIsUnknownTag(id, event)) { | ||
| if (tagSystem.handleIsUnknownTag(id, event, super::generateComponentId, | ||
| replyToUserOption)) { | ||
| return; | ||
| } | ||
|
|
||
| ReplyCallbackAction message = event | ||
| .replyEmbeds(new EmbedBuilder().setDescription(tagSystem.getTag(id).orElseThrow()) | ||
| .setFooter(event.getUser().getName() + " • used " + event.getCommandString()) | ||
| .setTimestamp(Instant.now()) | ||
| .setColor(TagSystem.AMBIENT_COLOR) | ||
| .build()); | ||
| sendTagReply(event, event.getUser().getName(), id, Optional.of(event.getCommandString()), | ||
| Optional.ofNullable(replyToUserOption) | ||
| .map(OptionMapping::getAsUser) | ||
| .map(IMentionable::getAsMention)); | ||
| } | ||
|
|
||
| if (replyToUserOption != null) { | ||
| message = message.setContent(replyToUserOption.getAsUser().getAsMention()); | ||
| @Override | ||
| public void onButtonClick(ButtonInteractionEvent event, List<String> args) { | ||
| if (!TagSystem.TAG_SUGGESTION_INDICATOR.equals(args.get(0))) { | ||
Zabuzard marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| return; | ||
| } | ||
| message.queue(); | ||
|
|
||
| sendTagReply(event, event.getUser().getName(), args.get(1), Optional.empty(), | ||
| Optional.ofNullable(args.get(2))); | ||
| } | ||
|
|
||
| /** | ||
| * Sends the reply for a successfull /tag use (i.e. the given tag exists) | ||
|
||
| */ | ||
| @SuppressWarnings("OptionalUsedAsFieldOrParameterType") | ||
Zabuzard marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| private void sendTagReply(IReplyCallback callback, String userName, String tag, | ||
| Optional<String> commandString, Optional<String> replyToUser) { | ||
| callback | ||
| .replyEmbeds(new EmbedBuilder().setDescription(tagSystem.getTag(tag).orElseThrow()) | ||
| .setFooter(userName + commandString.map(s -> " • used " + s).orElse("")) | ||
| .setTimestamp(Instant.now()) | ||
| .setColor(TagSystem.AMBIENT_COLOR) | ||
| .build()) | ||
| .setContent(replyToUser.orElse("")) | ||
| .queue(); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,23 +2,38 @@ | |
|
|
||
| import net.dv8tion.jda.api.entities.Emoji; | ||
| import net.dv8tion.jda.api.interactions.callbacks.IReplyCallback; | ||
| import net.dv8tion.jda.api.interactions.commands.OptionMapping; | ||
| import net.dv8tion.jda.api.interactions.components.ActionRow; | ||
| import net.dv8tion.jda.api.interactions.components.buttons.Button; | ||
| import net.dv8tion.jda.api.interactions.components.buttons.ButtonStyle; | ||
| import org.apache.commons.collections4.ListUtils; | ||
| import org.togetherjava.tjbot.commands.utils.StringDistances; | ||
| import org.togetherjava.tjbot.db.Database; | ||
| import org.togetherjava.tjbot.db.generated.tables.Tags; | ||
| import org.togetherjava.tjbot.db.generated.tables.records.TagsRecord; | ||
|
|
||
| import javax.annotation.Nullable; | ||
| import java.awt.Color; | ||
| import java.util.Optional; | ||
| import java.util.Set; | ||
| import java.util.*; | ||
| import java.util.function.Function; | ||
| import java.util.stream.Collectors; | ||
|
|
||
| /** | ||
| * The core of the tag system. Provides methods to read and create tags, directly tied to the | ||
| * underlying database. | ||
| */ | ||
| public final class TagSystem { | ||
| /** | ||
| * The amount of candidates that are suggested as buttons in the message that tells the user | ||
| * that the tag they tried accessing doesn't exist | ||
Zabuzard marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| */ | ||
| private static final int CANDIDATE_SUGGESTIONS_PER_USAGE = 5; | ||
Zabuzard marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| /** | ||
| * todo document | ||
| */ | ||
| static final String TAG_SUGGESTION_INDICATOR = "tag suggestion"; | ||
|
|
||
Zabuzard marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| /** | ||
| * The ambient color to use for tag system related messages. | ||
| */ | ||
|
|
@@ -57,17 +72,40 @@ static Button createDeleteButton(String componentId) { | |
| * @param event the event to send messages with | ||
| * @return whether the given tag is unknown to the system | ||
| */ | ||
| boolean handleIsUnknownTag(String id, IReplyCallback event) { | ||
| boolean handleIsUnknownTag(String id, IReplyCallback event, | ||
| Function<String[], String> componentIdGenerator, | ||
| @Nullable OptionMapping userToReplyTo) { | ||
Zabuzard marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| if (hasTag(id)) { | ||
| return false; | ||
| } | ||
| String suggestionText = StringDistances.closestMatch(id, getAllIds()) | ||
| .map(", did you perhaps mean '%s'?"::formatted) | ||
| .orElse("."); | ||
|
|
||
| event.reply("Could not find any tag with id '%s'%s".formatted(id, suggestionText)) | ||
| List<String> candidates = getAllIds().stream() | ||
| .sorted(Comparator | ||
| .comparingInt(candidate -> StringDistances.editDistance(id, candidate))) | ||
| .limit(CANDIDATE_SUGGESTIONS_PER_USAGE) | ||
| .toList(); | ||
| List<ActionRow> rows = new ArrayList<>(); | ||
| List<List<String>> partition = ListUtils.partition(candidates, 5); | ||
|
||
|
|
||
| for (List<String> part : partition) { | ||
|
||
| rows.add( | ||
| ActionRow | ||
| .of(part.stream() | ||
| .map(i -> Button.secondary(componentIdGenerator.apply(new String[] { | ||
| TAG_SUGGESTION_INDICATOR, i, | ||
| userToReplyTo != null ? userToReplyTo.getAsUser().getAsMention() | ||
| : null}), | ||
| i)) | ||
| .toList())); | ||
| } | ||
|
|
||
| event | ||
| .reply("Could not find any tag with id '%s'%s" | ||
| .formatted(id, candidates.isEmpty() ? "." : ", did you perhaps mean any of the following?")) | ||
| .setEphemeral(true) | ||
| .addActionRows(rows) | ||
| .queue(); | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.