Skip to content

Commit 8828212

Browse files
committed
Added beginning of stateless help channel management.
1 parent 2b6f6e7 commit 8828212

File tree

6 files changed

+163
-1
lines changed

6 files changed

+163
-1
lines changed

src/main/java/com/javadiscord/javabot/Bot.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import com.javadiscord.javabot.data.H2DataSource;
44
import com.javadiscord.javabot.events.*;
5+
import com.javadiscord.javabot.help.HelpChannelListener;
6+
import com.javadiscord.javabot.help.HelpChannelUpdater;
57
import com.javadiscord.javabot.properties.config.BotConfig;
68
import net.dv8tion.jda.api.JDA;
79
import net.dv8tion.jda.api.JDABuilder;
@@ -16,6 +18,7 @@
1618
import java.util.TimeZone;
1719
import java.util.concurrent.Executors;
1820
import java.util.concurrent.ScheduledExecutorService;
21+
import java.util.concurrent.TimeUnit;
1922

2023
/**
2124
* The main class where the bot is initialized.
@@ -74,6 +77,7 @@ public static void main(String[] args) throws Exception {
7477
.addEventListeners(slashCommands)
7578
.build();
7679
addEventListeners(jda);
80+
asyncPool.scheduleAtFixedRate(new HelpChannelUpdater(jda), 1, 1, TimeUnit.SECONDS);
7781
}
7882

7983
/**
@@ -92,7 +96,8 @@ private static void addEventListeners(JDA jda) {
9296
new AutoMod(),
9397
new SubmissionListener(),
9498
new StarboardListener(),
95-
new InteractionListener()
99+
new InteractionListener(),
100+
new HelpChannelListener()
96101
);
97102
}
98103
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.javadiscord.javabot.help;
2+
3+
import com.javadiscord.javabot.Bot;
4+
import net.dv8tion.jda.api.entities.Category;
5+
import net.dv8tion.jda.api.entities.TextChannel;
6+
import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent;
7+
import net.dv8tion.jda.api.hooks.ListenerAdapter;
8+
import org.jetbrains.annotations.NotNull;
9+
10+
/**
11+
* This listener is responsible for handling messages that are sent in one or
12+
* more designated help channels.
13+
*/
14+
public class HelpChannelListener extends ListenerAdapter {
15+
@Override
16+
public void onGuildMessageReceived(@NotNull GuildMessageReceivedEvent event) {
17+
if (event.getAuthor().isBot() || event.getAuthor().isSystem()) return;
18+
19+
var config = Bot.config.get(event.getGuild()).getHelp();
20+
TextChannel channel = event.getChannel();
21+
Category category = channel.getParent();
22+
if (category == null) return;
23+
if (channel.getName().startsWith(config.getOpenChannelPrefix())) {
24+
String rawChannelName = channel.getName().substring(config.getOpenChannelPrefix().length());
25+
channel.getManager().setName(config.getReservedChannelPrefix() + rawChannelName).queue();
26+
channel.getManager().setPosition(category.getTextChannels().size()).queue();
27+
}
28+
}
29+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package com.javadiscord.javabot.help;
2+
3+
import com.javadiscord.javabot.properties.config.guild.HelpConfig;
4+
import net.dv8tion.jda.api.entities.Message;
5+
import net.dv8tion.jda.api.entities.TextChannel;
6+
7+
import java.util.List;
8+
9+
public class HelpChannelManager {
10+
/**
11+
* Opens a text channel so that it is ready for a new question.
12+
* @param channel The channel to open.
13+
* @param config The configuration properties.
14+
*/
15+
public void open(TextChannel channel, HelpConfig config) {
16+
String rawName = channel.getName().substring(config.getReservedChannelPrefix().length());
17+
channel.getManager().setName(config.getOpenChannelPrefix() + rawName).queue();
18+
channel.getManager().setPosition(0).queue();
19+
removeAllMessages(channel);
20+
}
21+
22+
/**
23+
* Utility method to remove all messages from a channel.
24+
* @param channel The channel to remove messages from.
25+
*/
26+
private void removeAllMessages(TextChannel channel) {
27+
List<Message> messages;
28+
do {
29+
messages = channel.getHistory().retrievePast(50).complete();
30+
if (messages.isEmpty()) break;
31+
if (messages.size() == 1) {
32+
channel.deleteMessageById(messages.get(0).getIdLong()).complete();
33+
} else {
34+
channel.deleteMessages(messages).complete();
35+
}
36+
} while (!messages.isEmpty());
37+
}
38+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package com.javadiscord.javabot.help;
2+
3+
import com.javadiscord.javabot.Bot;
4+
import com.javadiscord.javabot.properties.config.guild.HelpConfig;
5+
import net.dv8tion.jda.api.JDA;
6+
import net.dv8tion.jda.api.entities.Message;
7+
import net.dv8tion.jda.api.entities.TextChannel;
8+
import net.dv8tion.jda.api.entities.User;
9+
10+
import java.time.OffsetDateTime;
11+
12+
public class HelpChannelUpdater implements Runnable {
13+
private final JDA jda;
14+
private final HelpChannelManager channelManager;
15+
16+
public HelpChannelUpdater(JDA jda) {
17+
this.jda = jda;
18+
this.channelManager = new HelpChannelManager();
19+
}
20+
21+
22+
@Override
23+
public void run() {
24+
for (var guild : this.jda.getGuilds()) {
25+
var config = Bot.config.get(guild).getHelp();
26+
var channels = guild.getTextChannels();
27+
for (var channel : channels) {
28+
if (channel.getName().startsWith(config.getReservedChannelPrefix())) {
29+
this.checkReservedChannel(channel, config);
30+
}
31+
}
32+
}
33+
}
34+
35+
private void checkReservedChannel(TextChannel channel, HelpConfig config) {
36+
channel.getHistoryFromBeginning(1).queue(history -> {
37+
if (history.isEmpty()) {
38+
// Revert to open channel.
39+
this.channelManager.open(channel, config);
40+
} else {
41+
Message firstMsg = history.getRetrievedHistory().get(0);
42+
var channelBecomesInactiveAt = firstMsg.getTimeCreated().plusSeconds(config.getInactivityTimeoutSeconds());
43+
if (OffsetDateTime.now().isAfter(channelBecomesInactiveAt)) {
44+
User user = firstMsg.getAuthor();
45+
}
46+
}
47+
});
48+
}
49+
}

src/main/java/com/javadiscord/javabot/properties/config/GuildConfig.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ public class GuildConfig {
2727
private transient Path file;
2828

2929
private SlashCommandConfig slashCommand;
30+
private HelpConfig help;
3031
private ModerationConfig moderation;
3132
private QOTWConfig qotw;
3233
private WelcomeConfig welcome;
@@ -38,6 +39,7 @@ public GuildConfig(Guild guild, Path file) {
3839
this.file = file;
3940
// Initialize all config items.
4041
this.slashCommand = new SlashCommandConfig();
42+
this.help = new HelpConfig();
4143
this.moderation = new ModerationConfig();
4244
this.qotw = new QOTWConfig();
4345
this.welcome = new WelcomeConfig();
@@ -50,6 +52,7 @@ public GuildConfig(Guild guild, Path file) {
5052
private void setGuild(Guild guild) {
5153
this.guild = guild;
5254
this.slashCommand.setGuildConfig(this);
55+
this.help.setGuildConfig(this);
5356
this.moderation.setGuildConfig(this);
5457
this.qotw.setGuildConfig(this);
5558
this.welcome.setGuildConfig(this);
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package com.javadiscord.javabot.properties.config.guild;
2+
3+
import com.javadiscord.javabot.properties.config.GuildConfigItem;
4+
import lombok.Data;
5+
import lombok.EqualsAndHashCode;
6+
7+
@Data
8+
@EqualsAndHashCode(callSuper = true)
9+
public class HelpConfig extends GuildConfigItem {
10+
/**
11+
* The string which is prefixed to any open help channel, where users are
12+
* free to ask a question.
13+
*/
14+
private String openChannelPrefix = "\uD83D\uDFE2";
15+
16+
/**
17+
* The string which is prefixed to any reserved help channel, where a user
18+
* has already asked a question and is in the process of getting an answer.
19+
*/
20+
private String reservedChannelPrefix = "⛔";
21+
22+
/**
23+
* The string which is prefixed to any inactive reserved help channel, where
24+
* a user has asked a question but the channel has been inactive for a set
25+
* amount of time.
26+
*/
27+
private String inactiveChannelPrefix = "\uD83D\uDFE0";
28+
29+
/**
30+
* The number of seconds of inactivity before a channel is considered inactive.
31+
*/
32+
private int inactivityTimeoutSeconds = 1_800;
33+
34+
/**
35+
* The number of seconds to wait between each help channel update check.
36+
*/
37+
private long updateIntervalSeconds = 60;
38+
}

0 commit comments

Comments
 (0)