Skip to content

Commit 51f997f

Browse files
committed
wip: create dynamic voice channel system
1 parent 34e42d5 commit 51f997f

File tree

3 files changed

+134
-3
lines changed

3 files changed

+134
-3
lines changed

application/config.json.template

+5-1
Original file line numberDiff line numberDiff line change
@@ -115,5 +115,9 @@
115115
"fallbackChannelPattern": "java-news-and-changes",
116116
"pollIntervalInMinutes": 10
117117
},
118-
"memberCountCategoryPattern": "Info"
118+
"memberCountCategoryPattern": "Info",
119+
"dynamicVoiceChannelPattern": [
120+
"Gaming",
121+
"Chit Chat"
122+
]
119123
}

application/src/main/java/org/togetherjava/tjbot/features/Features.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ public static Collection<Feature> createFeatures(JDA jda, Database database, Con
148148
features.add(new PinnedNotificationRemover(config));
149149

150150
// Voice receivers
151-
features.add(new DynamicVoiceListener());
151+
features.add(new DynamicVoiceListener(config));
152152

153153
// Event receivers
154154
features.add(new RejoinModerationRoleListener(actionsStore, config));
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,141 @@
11
package org.togetherjava.tjbot.features.dynamicvc;
22

3+
import net.dv8tion.jda.api.entities.Guild;
4+
import net.dv8tion.jda.api.entities.channel.concrete.VoiceChannel;
5+
import net.dv8tion.jda.api.entities.channel.unions.AudioChannelUnion;
36
import net.dv8tion.jda.api.events.guild.voice.GuildVoiceUpdateEvent;
7+
import org.apache.commons.lang3.tuple.Pair;
48
import org.jetbrains.annotations.NotNull;
59

10+
import org.togetherjava.tjbot.config.Config;
611
import org.togetherjava.tjbot.features.VoiceReceiverAdapter;
712

13+
import java.util.HashMap;
14+
import java.util.List;
15+
import java.util.Map;
16+
import java.util.function.Predicate;
17+
import java.util.regex.Matcher;
18+
import java.util.regex.Pattern;
19+
import java.util.stream.IntStream;
20+
import java.util.stream.Stream;
21+
822
public class DynamicVoiceListener extends VoiceReceiverAdapter {
923

24+
private final Map<String, Predicate<String>> patterns = new HashMap<>();
25+
private static final Pattern channelTopicPattern = Pattern.compile("(\\s+\\d+)$");
26+
27+
public DynamicVoiceListener(Config config) {
28+
config.getDynamicVoiceChannelPatterns()
29+
.forEach(pattern -> patterns.put(pattern, Pattern.compile(pattern).asMatchPredicate()));
30+
}
31+
1032
@Override
1133
public void onVoiceUpdate(@NotNull GuildVoiceUpdateEvent event) {
12-
// TODO: Complete
34+
AudioChannelUnion joinChannel = event.getChannelJoined();
35+
AudioChannelUnion leftChannel = event.getChannelLeft();
36+
37+
if (joinChannel != null && leftChannel != null) {
38+
if (!getChannelTopic(joinChannel.getName())
39+
.equals(getChannelTopic(leftChannel.getName()))) {
40+
handleTopicUpdate(event, joinChannel);
41+
handleTopicUpdate(event, leftChannel);
42+
return;
43+
}
44+
}
45+
46+
if (joinChannel != null) {
47+
handleTopicUpdate(event, joinChannel);
48+
} else if (leftChannel != null) {
49+
handleTopicUpdate(event, leftChannel);
50+
}
51+
}
52+
53+
private void handleTopicUpdate(GuildVoiceUpdateEvent event, AudioChannelUnion channel) {
54+
if (channel == null) {
55+
return;
56+
}
57+
58+
Guild guild = event.getGuild();
59+
String channelTopic = getChannelTopic(channel.getName());
60+
61+
if (patterns.get(channelTopic) == null) {
62+
return;
63+
}
64+
65+
long emptyChannelsCount = getEmptyChannelsCountFromTopic(guild, channelTopic);
66+
67+
if (emptyChannelsCount == 0) {
68+
createVoiceChannelFromTopic(channel, getChannelCountFromTopic(guild, channelTopic));
69+
} else if (emptyChannelsCount != 1) {
70+
removeDuplicateEmptyChannels(guild, channelTopic);
71+
}
72+
}
73+
74+
private static void createVoiceChannelFromTopic(AudioChannelUnion originalChannel,
75+
long topicChannelsCount) {
76+
String channelTopic = getChannelTopic(originalChannel.getName());
77+
78+
originalChannel.createCopy()
79+
.setName(getNumberedChannelTopic(channelTopic, topicChannelsCount + 1))
80+
.setPosition(originalChannel.getPositionRaw())
81+
.queue();
82+
83+
}
84+
85+
private void removeDuplicateEmptyChannels(Guild guild, String channelTopic) {
86+
List<VoiceChannel> channelsToRemove = getVoiceChannelsFromTopic(guild, channelTopic)
87+
.filter(channel -> channel.getMembers().isEmpty())
88+
.toList();
89+
90+
channelsToRemove.subList(1, channelsToRemove.size())
91+
.forEach(channel -> channel.delete().queue(success -> {
92+
List<VoiceChannel> channels =
93+
getVoiceChannelsFromTopic(guild, channelTopic).toList();
94+
95+
IntStream.range(0, channels.size())
96+
.asLongStream()
97+
.mapToObj(number -> Pair.of(number + 1, channels.get((int) number)))
98+
.filter(pair -> pair.getLeft() != 1)
99+
.forEach(pair -> {
100+
long number = pair.getLeft();
101+
VoiceChannel voiceChannel = pair.getRight();
102+
String voiceChannelNameTopic = getChannelTopic(voiceChannel.getName());
103+
104+
voiceChannel.getManager()
105+
.setName(getNumberedChannelTopic(voiceChannelNameTopic, number))
106+
.queue();
107+
});
108+
}));
109+
}
110+
111+
private long getChannelCountFromTopic(Guild guild, String channelTopic) {
112+
return getVoiceChannelsFromTopic(guild, channelTopic).count();
113+
}
114+
115+
private Stream<VoiceChannel> getVoiceChannelsFromTopic(Guild guild, String channelTopic) {
116+
return guild.getVoiceChannels()
117+
.stream()
118+
.filter(channel -> patterns.get(channelTopic).test(getChannelTopic(channel.getName())));
119+
}
120+
121+
private long getEmptyChannelsCountFromTopic(Guild guild, String channelTopic) {
122+
return getVoiceChannelsFromTopic(guild, channelTopic)
123+
.map(channel -> channel.getMembers().size())
124+
.filter(number -> number == 0)
125+
.count();
126+
}
127+
128+
private static String getChannelTopic(String channelName) {
129+
Matcher matcher = channelTopicPattern.matcher(channelName);
130+
131+
if (matcher.find()) {
132+
return matcher.replaceAll("");
133+
}
134+
135+
return channelName;
136+
}
137+
138+
private static String getNumberedChannelTopic(String channelTopic, long id) {
139+
return String.format("%s %d", channelTopic, id);
13140
}
14141
}

0 commit comments

Comments
 (0)