From a62f773c0a3e31b0cb6a47800db1ef9c00d02cc1 Mon Sep 17 00:00:00 2001 From: tj-wazei <158822022+tj-wazei@users.noreply.github.com> Date: Sat, 24 Jan 2026 15:57:35 +0000 Subject: [PATCH] fix: DynamicVoiceChat throwing an exception when event occurs in non-voice channel (#1391) Co-authored-by: Suraj Kumar --- .../features/voicechat/DynamicVoiceChat.java | 67 +++++++++++-------- 1 file changed, 38 insertions(+), 29 deletions(-) diff --git a/application/src/main/java/org/togetherjava/tjbot/features/voicechat/DynamicVoiceChat.java b/application/src/main/java/org/togetherjava/tjbot/features/voicechat/DynamicVoiceChat.java index c349d6b95a..98098896b8 100644 --- a/application/src/main/java/org/togetherjava/tjbot/features/voicechat/DynamicVoiceChat.java +++ b/application/src/main/java/org/togetherjava/tjbot/features/voicechat/DynamicVoiceChat.java @@ -3,9 +3,8 @@ import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.Member; -import net.dv8tion.jda.api.entities.MessageEmbed; -import net.dv8tion.jda.api.entities.MessageHistory; import net.dv8tion.jda.api.entities.User; +import net.dv8tion.jda.api.entities.channel.ChannelType; import net.dv8tion.jda.api.entities.channel.concrete.Category; import net.dv8tion.jda.api.entities.channel.concrete.VoiceChannel; import net.dv8tion.jda.api.entities.channel.middleman.AudioChannel; @@ -13,7 +12,6 @@ import net.dv8tion.jda.api.events.guild.voice.GuildVoiceUpdateEvent; import net.dv8tion.jda.api.managers.channel.middleman.AudioChannelManager; import net.dv8tion.jda.api.requests.RestAction; -import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -51,7 +49,7 @@ public DynamicVoiceChat(Config config) { } @Override - public void onVoiceUpdate(@NotNull GuildVoiceUpdateEvent event) { + public void onVoiceUpdate(GuildVoiceUpdateEvent event) { Member member = event.getMember(); User user = member.getUser(); @@ -62,18 +60,28 @@ public void onVoiceUpdate(@NotNull GuildVoiceUpdateEvent event) { AudioChannelUnion channelJoined = event.getChannelJoined(); AudioChannelUnion channelLeft = event.getChannelLeft(); - if (channelJoined != null && eventHappenOnDynamicRootChannel(channelJoined)) { + if (channelJoined != null && isVoiceChannel(channelJoined)) { + handleVoiceChannelJoin(event, channelJoined); + } + + if (channelLeft != null && isVoiceChannel(channelLeft)) { + handleVoiceChannelLeave(channelLeft); + } + } + + private void handleVoiceChannelJoin(GuildVoiceUpdateEvent event, + AudioChannelUnion channelJoined) { + if (eventHappenOnDynamicRootChannel(channelJoined)) { logger.debug("Event happened on joined channel {}", channelJoined); createDynamicVoiceChannel(event, channelJoined.asVoiceChannel()); } + } - if (channelLeft != null && !eventHappenOnDynamicRootChannel(channelLeft)) { + private void handleVoiceChannelLeave(AudioChannelUnion channelLeft) { + if (!eventHappenOnDynamicRootChannel(channelLeft)) { logger.debug("Event happened on left channel {}", channelLeft); - MessageHistory messageHistory = channelLeft.asVoiceChannel().getHistory(); - messageHistory.retrievePast(2).queue(messages -> { - // Don't forget that there is always one - // embed message sent by the bot every time. + channelLeft.asVoiceChannel().getHistory().retrievePast(2).queue(messages -> { if (messages.size() > 1) { archiveDynamicVoiceChannel(channelLeft); } else { @@ -89,8 +97,7 @@ private boolean eventHappenOnDynamicRootChannel(AudioChannelUnion channel) { .anyMatch(pattern -> pattern.matcher(channel.getName()).matches()); } - private void createDynamicVoiceChannel(@NotNull GuildVoiceUpdateEvent event, - VoiceChannel channel) { + private void createDynamicVoiceChannel(GuildVoiceUpdateEvent event, VoiceChannel channel) { Guild guild = event.getGuild(); Member member = event.getMember(); String newChannelName = "%s's %s".formatted(member.getEffectiveName(), channel.getName()); @@ -140,11 +147,8 @@ private void archiveDynamicVoiceChannel(AudioChannelUnion channel) { .and(channel.getPermissionContainer().getManager().clearOverridesAdded()); if (archiveCategoryOptional.isEmpty()) { - logger.warn("Could not find archive category. Attempting to create one..."); - channel.getGuild() - .createCategory(dynamicVoiceChannelConfig.archiveCategoryPattern()) - .queue(newCategory -> restActionChain.and(channelManager.setParent(newCategory)) - .queue()); + logger.error("Could not find category matching {}", + dynamicVoiceChannelConfig.archiveCategoryPattern()); return; } @@ -155,17 +159,22 @@ private void archiveDynamicVoiceChannel(AudioChannelUnion channel) { err -> logger.error("Could not archive dynamic voice chat", err))); } - private void sendWarningEmbed(VoiceChannel channel) { - MessageEmbed messageEmbed = new EmbedBuilder() - .addField("👋 Heads up!", - """ - This is a **temporary** voice chat channel. Messages sent here will be *cleared* once \ - the channel is deleted when everyone leaves. If you need to keep something important, \ - make sure to save it elsewhere. 💬 - """, - false) - .build(); - - channel.sendMessageEmbeds(messageEmbed).queue(); + private static void sendWarningEmbed(VoiceChannel channel) { + channel + .sendMessageEmbeds( + new EmbedBuilder() + .addField("👋 Heads up!", + """ + This is a **temporary** voice chat channel. Messages sent here will be *cleared* once \ + the channel is deleted when everyone leaves. If you need to keep something important, \ + make sure to save it elsewhere. 💬 + """, + false) + .build()) + .queue(); + } + + private static boolean isVoiceChannel(AudioChannelUnion channel) { + return channel.getType() == ChannelType.VOICE; } }