22
33import net .dv8tion .jda .api .JDA ;
44import net .dv8tion .jda .api .entities .channel .Channel ;
5+ import net .dv8tion .jda .api .entities .channel .unions .AudioChannelUnion ;
6+ import net .dv8tion .jda .api .events .guild .voice .GuildVoiceDeafenEvent ;
7+ import net .dv8tion .jda .api .events .guild .voice .GuildVoiceMuteEvent ;
8+ import net .dv8tion .jda .api .events .guild .voice .GuildVoiceStreamEvent ;
9+ import net .dv8tion .jda .api .events .guild .voice .GuildVoiceUpdateEvent ;
10+ import net .dv8tion .jda .api .events .guild .voice .GuildVoiceVideoEvent ;
511import net .dv8tion .jda .api .events .interaction .ModalInteractionEvent ;
612import net .dv8tion .jda .api .events .interaction .command .CommandAutoCompleteInteractionEvent ;
713import net .dv8tion .jda .api .events .interaction .command .MessageContextInteractionEvent ;
1622import net .dv8tion .jda .api .hooks .ListenerAdapter ;
1723import net .dv8tion .jda .api .interactions .callbacks .IReplyCallback ;
1824import net .dv8tion .jda .api .interactions .components .ComponentInteraction ;
25+ import org .jetbrains .annotations .NotNull ;
26+ import org .jetbrains .annotations .Nullable ;
1927import org .jetbrains .annotations .Unmodifiable ;
2028import org .slf4j .Logger ;
2129import org .slf4j .LoggerFactory ;
3240import org .togetherjava .tjbot .features .UserContextCommand ;
3341import org .togetherjava .tjbot .features .UserInteractionType ;
3442import org .togetherjava .tjbot .features .UserInteractor ;
43+ import org .togetherjava .tjbot .features .VoiceReceiver ;
3544import org .togetherjava .tjbot .features .componentids .ComponentId ;
3645import org .togetherjava .tjbot .features .componentids .ComponentIdParser ;
3746import org .togetherjava .tjbot .features .componentids .ComponentIdStore ;
@@ -75,6 +84,7 @@ public final class BotCore extends ListenerAdapter implements CommandProvider {
7584 private final ComponentIdParser componentIdParser ;
7685 private final ComponentIdStore componentIdStore ;
7786 private final Map <Pattern , MessageReceiver > channelNameToMessageReceiver = new HashMap <>();
87+ private final Map <Pattern , VoiceReceiver > channelNameToVoiceReceiver = new HashMap <>();
7888
7989 /**
8090 * Creates a new command system which uses the given database to allow commands to persist data.
@@ -96,6 +106,13 @@ public BotCore(JDA jda, Database database, Config config) {
96106 .forEach (messageReceiver -> channelNameToMessageReceiver
97107 .put (messageReceiver .getChannelNamePattern (), messageReceiver ));
98108
109+ // Voice receivers
110+ features .stream ()
111+ .filter (VoiceReceiver .class ::isInstance )
112+ .map (VoiceReceiver .class ::cast )
113+ .forEach (voiceReceiver -> channelNameToVoiceReceiver
114+ .put (voiceReceiver .getChannelNamePattern (), voiceReceiver ));
115+
99116 // Event receivers
100117 features .stream ()
101118 .filter (EventReceiver .class ::isInstance )
@@ -238,6 +255,76 @@ public void onMessageDelete(final MessageDeleteEvent event) {
238255 }
239256 }
240257
258+ /**
259+ * @param joinChannel the join channel
260+ * @param leftChannel the leave channel
261+ * @return the join channel if not null, otherwise the leave channel, otherwise an empty
262+ * optional
263+ */
264+ private Optional <Channel > calculateSubscribeTarget (@ Nullable AudioChannelUnion joinChannel ,
265+ @ Nullable AudioChannelUnion leftChannel ) {
266+ if (joinChannel != null ) {
267+ return Optional .of (joinChannel );
268+ }
269+
270+ return Optional .ofNullable (leftChannel );
271+ }
272+
273+ @ Override
274+ public void onGuildVoiceUpdate (@ NotNull GuildVoiceUpdateEvent event ) {
275+ calculateSubscribeTarget (event .getChannelJoined (), event .getChannelLeft ())
276+ .ifPresent (channel -> getVoiceReceiversSubscribedTo (channel )
277+ .forEach (voiceReceiver -> voiceReceiver .onVoiceUpdate (event )));
278+ }
279+
280+ @ Override
281+ public void onGuildVoiceVideo (@ NotNull GuildVoiceVideoEvent event ) {
282+ AudioChannelUnion channel = event .getVoiceState ().getChannel ();
283+
284+ if (channel == null ) {
285+ return ;
286+ }
287+
288+ getVoiceReceiversSubscribedTo (channel )
289+ .forEach (voiceReceiver -> voiceReceiver .onVideoToggle (event ));
290+ }
291+
292+ @ Override
293+ public void onGuildVoiceStream (@ NotNull GuildVoiceStreamEvent event ) {
294+ AudioChannelUnion channel = event .getVoiceState ().getChannel ();
295+
296+ if (channel == null ) {
297+ return ;
298+ }
299+
300+ getVoiceReceiversSubscribedTo (channel )
301+ .forEach (voiceReceiver -> voiceReceiver .onStreamToggle (event ));
302+ }
303+
304+ @ Override
305+ public void onGuildVoiceMute (@ NotNull GuildVoiceMuteEvent event ) {
306+ AudioChannelUnion channel = event .getVoiceState ().getChannel ();
307+
308+ if (channel == null ) {
309+ return ;
310+ }
311+
312+ getVoiceReceiversSubscribedTo (channel )
313+ .forEach (voiceReceiver -> voiceReceiver .onMuteToggle (event ));
314+ }
315+
316+ @ Override
317+ public void onGuildVoiceDeafen (@ NotNull GuildVoiceDeafenEvent event ) {
318+ AudioChannelUnion channel = event .getVoiceState ().getChannel ();
319+
320+ if (channel == null ) {
321+ return ;
322+ }
323+
324+ getVoiceReceiversSubscribedTo (channel )
325+ .forEach (voiceReceiver -> voiceReceiver .onDeafenToggle (event ));
326+ }
327+
241328 private Stream <MessageReceiver > getMessageReceiversSubscribedTo (Channel channel ) {
242329 String channelName = channel .getName ();
243330 return channelNameToMessageReceiver .entrySet ()
@@ -248,6 +335,16 @@ private Stream<MessageReceiver> getMessageReceiversSubscribedTo(Channel channel)
248335 .map (Map .Entry ::getValue );
249336 }
250337
338+ private Stream <VoiceReceiver > getVoiceReceiversSubscribedTo (Channel channel ) {
339+ String channelName = channel .getName ();
340+ return channelNameToVoiceReceiver .entrySet ()
341+ .stream ()
342+ .filter (patternAndReceiver -> patternAndReceiver .getKey ()
343+ .matcher (channelName )
344+ .matches ())
345+ .map (Map .Entry ::getValue );
346+ }
347+
251348 @ Override
252349 public void onSlashCommandInteraction (SlashCommandInteractionEvent event ) {
253350 String name = event .getName ();
0 commit comments