Skip to content

Commit ce08953

Browse files
Fixed thanks-closing & fixed rare race condition
1 parent 83c9e9f commit ce08953

File tree

1 file changed

+64
-34
lines changed

1 file changed

+64
-34
lines changed

src/main/java/net/javadiscord/javabot/systems/help/HelpListener.java

Lines changed: 64 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import net.javadiscord.javabot.data.h2db.DbActions;
2323
import net.javadiscord.javabot.systems.help.dao.HelpAccountRepository;
2424
import net.javadiscord.javabot.systems.help.dao.HelpTransactionRepository;
25-
import net.javadiscord.javabot.systems.user_preferences.UserPreferenceService;
2625
import net.javadiscord.javabot.util.ExceptionLogger;
2726
import net.javadiscord.javabot.util.Responses;
2827
import org.jetbrains.annotations.NotNull;
@@ -32,11 +31,13 @@
3231

3332
import java.util.ArrayList;
3433
import java.util.HashMap;
34+
import java.util.HashSet;
3535
import java.util.List;
3636
import java.util.Map;
37+
import java.util.Set;
3738

3839
/**
39-
* Listens for all events releated to the forum help channel system.
40+
* Listens for all events related to the forum help channel system.
4041
*/
4142
@RequiredArgsConstructor
4243
@AutoDetectableComponentHandler({HelpManager.HELP_THANKS_IDENTIFIER, HelpManager.HELP_CLOSE_IDENTIFIER, HelpManager.HELP_GUIDELINES_IDENTIFIER})
@@ -45,16 +46,33 @@ public class HelpListener extends ListenerAdapter implements ButtonHandler {
4546
/**
4647
* A static Map that holds all messages that was sent in a specific reserved forum channel.
4748
*/
48-
public static final Map<Long, List<Message>> HELP_POST_MESSAGES = new HashMap<>();
49+
protected static final Map<Long, List<Message>> HELP_POST_MESSAGES = new HashMap<>();
50+
private static final Set<Long> newPosts;
51+
52+
static {
53+
newPosts = new HashSet<>();
54+
}
4955

5056
private final BotConfig botConfig;
5157
private final HelpAccountRepository helpAccountRepository;
5258
private final HelpTransactionRepository helpTransactionRepository;
53-
private final UserPreferenceService userPreferenceService;
5459
private final DbActions dbActions;
5560

5661
@Override
5762
public void onMessageReceived(@NotNull MessageReceivedEvent event) {
63+
// listen for the posts initial message. Why this has to be done is further described in
64+
// https://canary.discord.com/channels/125227483518861312/1053705384466059354/1053705384466059354
65+
if (newPosts.contains(event.getChannel().getIdLong())) {
66+
HelpConfig config = botConfig.get(event.getGuild()).getHelpConfig();
67+
ThreadChannel post = event.getChannel().asThreadChannel();
68+
// send post buttons
69+
post.sendMessageComponents(ActionRow.of(
70+
Button.primary(ComponentIdBuilder.build(HelpManager.HELP_CLOSE_IDENTIFIER, post.getIdLong()), "Close Post"),
71+
Button.secondary(ComponentIdBuilder.build(HelpManager.HELP_GUIDELINES_IDENTIFIER), "View Help Guidelines")
72+
)).queue(success -> post.sendMessageFormat(config.getReservedChannelMessageTemplate(), UserSnowflake.fromId(post.getOwnerId()).getAsMention(), config.getInactivityTimeoutMinutes()).queue());
73+
newPosts.remove(event.getChannel().getIdLong());
74+
return;
75+
}
5876
if (event.getMessage().getAuthor().isSystem() || event.getMessage().getAuthor().isBot()) {
5977
return;
6078
}
@@ -85,11 +103,9 @@ public void onChannelCreate(@NotNull ChannelCreateEvent event) {
85103
if (isInvalidHelpForumChannel(post.getParentChannel().asForumChannel())) {
86104
return;
87105
}
88-
// send post buttons
89-
post.sendMessageComponents(ActionRow.of(
90-
Button.primary(ComponentIdBuilder.build(HelpManager.HELP_CLOSE_IDENTIFIER, post.getIdLong()), "Close Post"),
91-
Button.secondary(ComponentIdBuilder.build(HelpManager.HELP_GUIDELINES_IDENTIFIER), "View Help Guidelines")
92-
)).queue(success -> post.sendMessageFormat(config.getReservedChannelMessageTemplate(), UserSnowflake.fromId(post.getOwnerId()).getAsMention(), config.getInactivityTimeoutMinutes()).queue());
106+
// add thread id to a temporary cache to avoid potential missing author message
107+
// more info on why this has to be done: https://canary.discord.com/channels/125227483518861312/1053705384466059354/1053705384466059354
108+
newPosts.add(event.getChannel().getIdLong());
93109
}
94110

95111
@Override
@@ -105,8 +121,10 @@ public void handleButton(@NotNull ButtonInteractionEvent event, @NotNull Button
105121
HelpManager manager = new HelpManager(post, dbActions, botConfig, helpAccountRepository, helpTransactionRepository);
106122
switch (id[0]) {
107123
case HelpManager.HELP_THANKS_IDENTIFIER -> handleHelpThanksInteraction(event, manager, id);
108-
case HelpManager.HELP_GUIDELINES_IDENTIFIER -> handleReplyGuidelines(event, post.getParentChannel().asForumChannel());
124+
case HelpManager.HELP_GUIDELINES_IDENTIFIER ->
125+
handleReplyGuidelines(event, post.getParentChannel().asForumChannel());
109126
case HelpManager.HELP_CLOSE_IDENTIFIER -> handlePostClose(event, manager);
127+
default -> event.reply("Unknown interaction.").queue();
110128
}
111129
}
112130

@@ -128,34 +146,46 @@ private void handleHelpThanksInteraction(@NotNull ButtonInteractionEvent event,
128146
return;
129147
}
130148
switch (id[2]) {
131-
case "done" -> {
132-
List<Button> buttons = event.getMessage().getButtons();
133-
// immediately delete the message
134-
event.getMessage().delete().queue(s -> {
135-
// close post
136-
manager.close(event, false, null);
137-
// add experience
138-
try {
139-
HelpExperienceService service = new HelpExperienceService(botConfig, helpAccountRepository, helpTransactionRepository);
140-
Map<Long, Double> experience = HelpManager.calculateExperience(HELP_POST_MESSAGES.get(post.getIdLong()), post.getOwnerIdLong(), config);
141-
for (Map.Entry<Long, Double> entry : experience.entrySet()) {
142-
service.performTransaction(entry.getKey(), entry.getValue(), config.getGuild());
143-
}
144-
} catch (DataAccessException e) {
145-
ExceptionLogger.capture(e, getClass().getName());
146-
}
147-
// thank all helpers
148-
buttons.stream().filter(ActionComponent::isDisabled)
149-
.filter(b -> b.getId() != null)
150-
.forEach(b -> manager.thankHelper(event, post, Long.parseLong(ComponentIdBuilder.split(b.getId())[2])));
151-
});
152-
153-
}
149+
case "done" -> handleThanksCloseButton(event, manager, post, config);
154150
case "cancel" -> event.getMessage().delete().queue();
155-
default -> event.editButton(event.getButton().asDisabled()).queue();
151+
default -> {
152+
List<Button> thankButtons = event.getMessage().getButtons().stream()
153+
.filter(b -> b.getId() != null &&
154+
!ComponentIdBuilder.split(b.getId())[2].equals("done") &&
155+
!ComponentIdBuilder.split(b.getId())[2].equals("cancel")
156+
).toList();
157+
if (thankButtons.stream().filter(Button::isDisabled).count() == thankButtons.size() - 1) {
158+
handleThanksCloseButton(event, manager, post, config);
159+
} else {
160+
event.editButton(event.getButton().asDisabled()).queue();
161+
}
162+
}
156163
}
157164
}
158165

166+
private void handleThanksCloseButton(@NotNull ButtonInteractionEvent event, HelpManager manager, ThreadChannel post, HelpConfig config) {
167+
List<Button> buttons = event.getMessage().getButtons();
168+
// immediately delete the message
169+
event.getMessage().delete().queue(s -> {
170+
// close post
171+
manager.close(event, false, null);
172+
// add experience
173+
try {
174+
HelpExperienceService service = new HelpExperienceService(botConfig, helpAccountRepository, helpTransactionRepository);
175+
Map<Long, Double> experience = HelpManager.calculateExperience(HELP_POST_MESSAGES.get(post.getIdLong()), post.getOwnerIdLong(), config);
176+
for (Map.Entry<Long, Double> entry : experience.entrySet()) {
177+
service.performTransaction(entry.getKey(), entry.getValue(), config.getGuild());
178+
}
179+
} catch (DataAccessException e) {
180+
ExceptionLogger.capture(e, getClass().getName());
181+
}
182+
// thank all helpers
183+
buttons.stream().filter(ActionComponent::isDisabled)
184+
.filter(b -> b.getId() != null)
185+
.forEach(b -> manager.thankHelper(event, post, Long.parseLong(ComponentIdBuilder.split(b.getId())[2])));
186+
});
187+
}
188+
159189
private void handleReplyGuidelines(@NotNull IReplyCallback callback, @NotNull ForumChannel channel) {
160190
callback.replyEmbeds(new EmbedBuilder()
161191
.setTitle("Help Guidelines")

0 commit comments

Comments
 (0)