Skip to content

Commit eb002e5

Browse files
committed
add modal for reason when closing
1 parent 2eb1971 commit eb002e5

File tree

2 files changed

+77
-23
lines changed

2 files changed

+77
-23
lines changed

src/main/java/net/discordjug/javabot/Bot.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,12 @@ private void registerComponentHandlers(@NotNull ApplicationContext ctx) {
112112
List<IdMapping<StringSelectMenuHandler>> stringSelectMappings = new ArrayList<>();
113113
for (Object handler : interactionHandlers.values()) {
114114
AutoDetectableComponentHandler annotation = handler.getClass().getAnnotation(AutoDetectableComponentHandler.class);
115-
String[] keys = annotation.value();
116-
addComponentHandler(buttonMappings, keys, handler, ButtonHandler.class);
117-
addComponentHandler(modalMappings, keys, handler, ModalHandler.class);
118-
addComponentHandler(stringSelectMappings, keys, handler, StringSelectMenuHandler.class);
115+
if (annotation != null) {//superclasses are annotated, ignore
116+
String[] keys = annotation.value();
117+
addComponentHandler(buttonMappings, keys, handler, ButtonHandler.class);
118+
addComponentHandler(modalMappings, keys, handler, ModalHandler.class);
119+
addComponentHandler(stringSelectMappings, keys, handler, StringSelectMenuHandler.class);
120+
}
119121
}
120122
dih4jda.addButtonMappings(buttonMappings.toArray(IdMapping[]::new));
121123
dih4jda.addModalMappings(modalMappings.toArray(IdMapping[]::new));

src/main/java/net/discordjug/javabot/systems/help/commands/UnreserveCommand.java

Lines changed: 71 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,45 @@
11
package net.discordjug.javabot.systems.help.commands;
22

3+
import java.util.List;
4+
5+
import org.jetbrains.annotations.NotNull;
6+
7+
import net.discordjug.javabot.annotations.AutoDetectableComponentHandler;
38
import net.discordjug.javabot.data.config.BotConfig;
49
import net.discordjug.javabot.data.h2db.DbActions;
510
import net.discordjug.javabot.systems.help.HelpManager;
611
import net.discordjug.javabot.systems.help.dao.HelpAccountRepository;
712
import net.discordjug.javabot.systems.help.dao.HelpTransactionRepository;
813
import net.discordjug.javabot.systems.user_preferences.UserPreferenceService;
14+
import net.discordjug.javabot.util.ExceptionLogger;
915
import net.discordjug.javabot.util.Responses;
1016
import net.dv8tion.jda.api.entities.channel.ChannelType;
1117
import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel;
18+
import net.dv8tion.jda.api.entities.channel.unions.MessageChannelUnion;
19+
import net.dv8tion.jda.api.events.interaction.ModalInteractionEvent;
1220
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
13-
import net.dv8tion.jda.api.interactions.commands.CommandInteraction;
21+
import net.dv8tion.jda.api.interactions.Interaction;
22+
import net.dv8tion.jda.api.interactions.callbacks.IReplyCallback;
1423
import net.dv8tion.jda.api.interactions.commands.OptionMapping;
1524
import net.dv8tion.jda.api.interactions.commands.OptionType;
1625
import net.dv8tion.jda.api.interactions.commands.build.Commands;
17-
18-
import org.jetbrains.annotations.NotNull;
26+
import net.dv8tion.jda.api.interactions.components.ActionRow;
27+
import net.dv8tion.jda.api.interactions.components.text.TextInput;
28+
import net.dv8tion.jda.api.interactions.components.text.TextInputStyle;
29+
import net.dv8tion.jda.api.interactions.modals.Modal;
30+
import net.dv8tion.jda.api.interactions.modals.ModalMapping;
1931
import xyz.dynxsty.dih4jda.interactions.commands.application.SlashCommand;
32+
import xyz.dynxsty.dih4jda.interactions.components.ModalHandler;
33+
import xyz.dynxsty.dih4jda.util.ComponentIdBuilder;
2034

2135
/**
2236
* A simple command that can be used inside reserved help channels to
2337
* immediately unreserve them, instead of waiting for a timeout.
2438
*/
25-
public class UnreserveCommand extends SlashCommand {
39+
@AutoDetectableComponentHandler(UnreserveCommand.UNRESERVE_ID)
40+
public class UnreserveCommand extends SlashCommand implements ModalHandler {
41+
private static final String UNRESERVE_ID = "unreserve";
42+
private static final String REASON_ID = "reason";
2643
private final BotConfig botConfig;
2744
private final DbActions dbActions;
2845
private final HelpAccountRepository helpAccountRepository;
@@ -43,40 +60,75 @@ public UnreserveCommand(BotConfig botConfig, DbActions dbActions, HelpTransactio
4360
this.helpAccountRepository = helpAccountRepository;
4461
this.helpTransactionRepository = helpTransactionRepository;
4562
this.preferenceService = preferenceService;
46-
setCommandData(Commands.slash("unreserve", "Unreserves this post marking your question/issue as resolved.")
63+
setCommandData(Commands.slash(UNRESERVE_ID, "Unreserves this post marking your question/issue as resolved.")
4764
.setGuildOnly(true)
48-
.addOption(OptionType.STRING, "reason", "The reason why you're unreserving this channel", false)
65+
.addOption(OptionType.STRING, REASON_ID, "The reason why you're unreserving this channel", false)
4966
);
5067
}
5168

5269
@Override
5370
public void execute(@NotNull SlashCommandInteractionEvent event) {
71+
String reason = event.getOption(REASON_ID, null, OptionMapping::getAsString);
72+
onCloseRequest(event, event, event.getChannel(), reason, ()->{
73+
TextInput reasonInput = TextInput
74+
.create(REASON_ID, "Reason", TextInputStyle.SHORT)
75+
.setRequiredRange(11, 100)
76+
.setRequired(true)
77+
.setPlaceholder("Please enter the reason you are closing this post here")
78+
.build();
79+
Modal modal = Modal
80+
.create(ComponentIdBuilder.build(UNRESERVE_ID), "Close post")
81+
.addComponents(ActionRow.of(
82+
reasonInput))
83+
.build();
84+
event.replyModal(modal).queue();
85+
});
86+
}
87+
88+
@Override
89+
public void handleModal(ModalInteractionEvent event, List<ModalMapping> values) {
90+
values
91+
.stream()
92+
.filter(mapping -> REASON_ID.equals(mapping.getId()))
93+
.map(mapping -> mapping.getAsString())
94+
.findAny()
95+
.ifPresentOrElse(reason -> {
96+
onCloseRequest(event, event, event.getChannel(), reason, ()->{
97+
Responses.error(event, "An error occured - The reason field is missing.").queue();
98+
ExceptionLogger.capture(new IllegalStateException("A reason was expected but not present"), getClass().getName());
99+
});
100+
}, () -> Responses.warning(event, "A reason must be provided").queue());
101+
102+
}
103+
104+
private void onCloseRequest(Interaction interaction, IReplyCallback replyCallback, MessageChannelUnion channel, String reason, Runnable noReasonHandler) {
105+
ChannelType channelType = channel.getType();
54106
// check whether the channel type is either text or thread (possible forum post?)
55-
if (event.getChannelType() != ChannelType.TEXT && event.getChannelType() != ChannelType.GUILD_PUBLIC_THREAD) {
56-
replyInvalidChannel(event);
107+
if (channelType != ChannelType.TEXT && channelType != ChannelType.GUILD_PUBLIC_THREAD) {
108+
replyInvalidChannel(replyCallback);
57109
return;
58110
}
59-
ThreadChannel postThread = event.getChannel().asThreadChannel();
111+
ThreadChannel postThread = channel.asThreadChannel();
60112
if (postThread.getParentChannel().getType() != ChannelType.FORUM) {
61-
replyInvalidChannel(event);
113+
replyInvalidChannel(replyCallback);
114+
return;
62115
}
63116
HelpManager manager = new HelpManager(postThread, dbActions, botConfig, helpAccountRepository, helpTransactionRepository, preferenceService);
64-
if (manager.isForumEligibleToBeUnreserved(event.getInteraction())) {
65-
String reason = event.getOption("reason", null, OptionMapping::getAsString);
66-
if (event.getUser().getIdLong() != postThread.getOwnerIdLong() && reason == null) {
67-
Responses.warning(event, "Could not close this post", "Closing a post of another user requires a reason to be set.").queue();
117+
if (manager.isForumEligibleToBeUnreserved(interaction)) {
118+
if (replyCallback.getUser().getIdLong() != postThread.getOwnerIdLong() && reason == null) {
119+
noReasonHandler.run();
68120
return;
69121
}
70-
manager.close(event,
71-
event.getUser().getIdLong() == manager.getPostThread().getOwnerIdLong(),
122+
manager.close(replyCallback,
123+
replyCallback.getUser().getIdLong() == manager.getPostThread().getOwnerIdLong(),
72124
reason);
73125
} else {
74-
Responses.warning(event, "Could not close this post", "You're not allowed to close this post.").queue();
126+
Responses.warning(replyCallback, "Could not close this post", "You're not allowed to close this post.").queue();
75127
}
76128
}
77129

78-
private void replyInvalidChannel(CommandInteraction interaction) {
79-
Responses.warning(interaction, "Invalid Channel",
130+
private void replyInvalidChannel(IReplyCallback replyCallback) {
131+
Responses.warning(replyCallback, "Invalid Channel",
80132
"This command may only be used in either the text-channel-based help system, or in our new forum help system.")
81133
.queue();
82134
}

0 commit comments

Comments
 (0)