Skip to content

Commit 6a7f285

Browse files
Merge pull request #298 from andrewlalis/andrew/update_helpping
Improved help-ping command
2 parents e5e70fd + 43b1de2 commit 6a7f285

File tree

1 file changed

+79
-21
lines changed

1 file changed

+79
-21
lines changed

src/main/java/net/javadiscord/javabot/systems/help/commands/HelpPingCommand.java

Lines changed: 79 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,14 @@
88
import net.javadiscord.javabot.command.ResponseException;
99
import net.javadiscord.javabot.command.Responses;
1010
import net.javadiscord.javabot.command.interfaces.SlashCommand;
11+
import net.javadiscord.javabot.data.config.GuildConfig;
1112
import net.javadiscord.javabot.systems.help.HelpChannelManager;
13+
import net.javadiscord.javabot.systems.help.model.ChannelReservation;
1214

1315
import java.util.EnumSet;
1416
import java.util.Map;
17+
import java.util.Optional;
18+
import java.util.Set;
1519
import java.util.concurrent.ConcurrentHashMap;
1620
import java.util.concurrent.TimeUnit;
1721

@@ -26,39 +30,44 @@ public class HelpPingCommand implements SlashCommand {
2630
private final Map<Member, Long> lastPingTimes;
2731

2832
/**
29-
* Constructor that initializes and handles the cooldown map.
33+
* Constructor that initializes a scheduled cache cleanup for this
34+
* command's built-in {@link HelpPingCommand#lastPingTimes} cache.
3035
*/
3136
public HelpPingCommand() {
3237
lastPingTimes = new ConcurrentHashMap<>();
33-
Bot.asyncPool.scheduleWithFixedDelay(() -> {
34-
var membersToRemove = lastPingTimes.entrySet().stream().filter(entry -> {
35-
var config = Bot.config.get(entry.getKey().getGuild()).getHelp();
36-
long timeoutMillis = config.getHelpPingTimeoutSeconds() * 1000L;
37-
return entry.getValue() + timeoutMillis < System.currentTimeMillis();
38-
}).map(Map.Entry::getKey).toList();
39-
for (var member : membersToRemove) {
40-
lastPingTimes.remove(member);
41-
}
42-
}, CACHE_CLEANUP_DELAY, CACHE_CLEANUP_DELAY, TimeUnit.SECONDS);
38+
Bot.asyncPool.scheduleWithFixedDelay(this::cleanTimeoutCache, CACHE_CLEANUP_DELAY, CACHE_CLEANUP_DELAY, TimeUnit.SECONDS);
4339
}
4440

4541
@Override
4642
public ReplyCallbackAction handleSlashCommandInteraction(SlashCommandInteractionEvent event) throws ResponseException {
4743
Guild guild = event.getGuild();
4844
if (guild == null) return Responses.warning(event, WRONG_CHANNEL_MSG);
49-
var channelManager = new HelpChannelManager(Bot.config.get(guild).getHelp());
45+
GuildConfig config = Bot.config.get(guild);
46+
var channelManager = new HelpChannelManager(config.getHelp());
5047
if (channelManager.isReserved(event.getTextChannel())) {
51-
Long lastPing = lastPingTimes.get(event.getMember());
52-
if (lastPing != null && lastPing + channelManager.getConfig().getHelpPingTimeoutSeconds() * 1000L > System.currentTimeMillis()) {
48+
Optional<ChannelReservation> optionalReservation = channelManager.getReservationForChannel(event.getTextChannel().getIdLong());
49+
if (optionalReservation.isEmpty()) {
50+
return Responses.warning(event, "Could not fetch the channel reservation.");
51+
}
52+
ChannelReservation reservation = optionalReservation.get();
53+
Member member = event.getMember();
54+
if (member == null) {
55+
return Responses.warning(event, "No member information was available for this event.");
56+
}
57+
if (isHelpPingForbiddenForMember(reservation, member, config)) {
58+
return Responses.warning(event, "Sorry, but only the person who reserved this channel, or staff and helpers, may use this command.");
59+
}
60+
if (isHelpPingTimeoutElapsed(member, config)) {
61+
lastPingTimes.put(event.getMember(), System.currentTimeMillis());
62+
Role role = channelManager.getConfig().getHelpPingRole();
63+
event.getChannel().sendMessage(role.getAsMention())
64+
.allowedMentions(EnumSet.of(Message.MentionType.ROLE))
65+
.setEmbeds(this.buildAuthorEmbed(event.getUser()))
66+
.queue();
67+
return event.replyFormat("Successfully pinged " + role.getAsMention()).setEphemeral(true);
68+
} else {
5369
return Responses.warning(event, "Sorry, but you can only use this command occasionally. Please try again later.");
5470
}
55-
lastPingTimes.put(event.getMember(), System.currentTimeMillis());
56-
Role role = channelManager.getConfig().getHelpPingRole();
57-
event.getChannel().sendMessage(role.getAsMention())
58-
.allowedMentions(EnumSet.of(Message.MentionType.ROLE))
59-
.setEmbeds(this.buildAuthorEmbed(event.getUser()))
60-
.queue();
61-
return event.replyFormat("Successfully pinged " + role.getAsMention()).setEphemeral(true);
6271
} else {
6372
return Responses.warning(event, WRONG_CHANNEL_MSG);
6473
}
@@ -69,4 +78,53 @@ private MessageEmbed buildAuthorEmbed(User author) {
6978
.setTitle("Requested by " + author.getAsTag())
7079
.build();
7180
}
81+
82+
/**
83+
* Determines if a user is forbidden from sending a help-ping command due
84+
* to their status in the server.
85+
* @param reservation The channel reservation for the channel they're
86+
* trying to send the command in.
87+
* @param member The member.
88+
* @param config The guild config.
89+
* @return True if the user is forbidden from sending the command.
90+
*/
91+
private boolean isHelpPingForbiddenForMember(ChannelReservation reservation, Member member, GuildConfig config) {
92+
Set<Role> allowedRoles = Set.of(config.getModeration().getStaffRole(), config.getHelp().getHelperRole());
93+
return !(
94+
reservation.getUserId() == member.getUser().getIdLong() ||
95+
member.getRoles().stream().anyMatch(allowedRoles::contains) ||
96+
member.isOwner()
97+
);
98+
}
99+
100+
/**
101+
* Determines if the user's timeout has elapsed (or doesn't exist), which
102+
* implies that it's fine for the user to send the command.
103+
* @param member The member.
104+
* @param config The guild config.
105+
* @return True if the user's timeout has elapsed or doesn't exist, or
106+
* false if the user should NOT send the command because of their timeout.
107+
*/
108+
private boolean isHelpPingTimeoutElapsed(Member member, GuildConfig config) {
109+
Long lastPing = lastPingTimes.get(member);
110+
return lastPing == null ||
111+
lastPing + config.getHelp().getHelpPingTimeoutSeconds() * 1000L < System.currentTimeMillis();
112+
}
113+
114+
/**
115+
* Method that cleans out any entries from the list of last ping times if
116+
* their timeout is no longer valid.
117+
*/
118+
private void cleanTimeoutCache() {
119+
// Find the list of members whose last ping time was old enough that they should be removed from the cache.
120+
var membersToRemove = lastPingTimes.entrySet().stream().filter(entry -> {
121+
var config = Bot.config.get(entry.getKey().getGuild()).getHelp();
122+
long timeoutMillis = config.getHelpPingTimeoutSeconds() * 1000L;
123+
return entry.getValue() + timeoutMillis < System.currentTimeMillis();
124+
}).map(Map.Entry::getKey).toList();
125+
// Remove each member from the map.
126+
for (var member : membersToRemove) {
127+
lastPingTimes.remove(member);
128+
}
129+
}
72130
}

0 commit comments

Comments
 (0)