From 73d5bd63c2b0cd12341e071f2686f1d64808facb Mon Sep 17 00:00:00 2001 From: Suraj Kumar Date: Mon, 26 Jan 2026 15:39:25 +0000 Subject: [PATCH 1/4] fix: add caffeine cache to prevent double fire --- .../tjbot/features/voicechat/DynamicVoiceChat.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) 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 6adcc7b8d7..0c854b0e7a 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 @@ -1,5 +1,7 @@ package org.togetherjava.tjbot.features.voicechat; +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.Member; @@ -20,6 +22,7 @@ import org.togetherjava.tjbot.features.VoiceReceiverAdapter; import java.util.Optional; +import java.util.concurrent.TimeUnit; /** * Handles dynamic voice channel creation and deletion based on user activity. @@ -34,6 +37,9 @@ public final class DynamicVoiceChat extends VoiceReceiverAdapter { private final VoiceChatCleanupStrategy voiceChatCleanupStrategy; private final DynamicVoiceChatConfig dynamicVoiceChannelConfig; + private final Cache deletedChannels = + Caffeine.newBuilder().expireAfterWrite(5, TimeUnit.MINUTES).build(); + /** * Creates a new instance of {@code DynamicVoiceChat} * @@ -78,6 +84,12 @@ private void handleVoiceChannelJoin(GuildVoiceUpdateEvent event, } private void handleVoiceChannelLeave(AudioChannelUnion channelLeft) { + long channelId = channelLeft.getIdLong(); + + if (Boolean.TRUE.equals(deletedChannels.getIfPresent(channelId))) { + return; + } + if (!eventHappenOnDynamicRootChannel(channelLeft)) { logger.debug("Event happened on left channel {}", channelLeft); @@ -92,6 +104,7 @@ private void handleVoiceChannelLeave(AudioChannelUnion channelLeft) { archiveDynamicVoiceChannel(channelLeft); } else { channelLeft.delete().queue(); + deletedChannels.put(channelId, true); } }); } From f8dc6479f3020cca505b16b906795a95ecc1b217 Mon Sep 17 00:00:00 2001 From: Suraj Kumar Date: Mon, 26 Jan 2026 15:40:16 +0000 Subject: [PATCH 2/4] fix: check is bot only on join --- .../tjbot/features/voicechat/DynamicVoiceChat.java | 6 +----- 1 file changed, 1 insertion(+), 5 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 0c854b0e7a..ba8ae2edc6 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 @@ -59,14 +59,10 @@ public void onVoiceUpdate(GuildVoiceUpdateEvent event) { Member member = event.getMember(); User user = member.getUser(); - if (user.isBot()) { - return; - } - AudioChannelUnion channelJoined = event.getChannelJoined(); AudioChannelUnion channelLeft = event.getChannelLeft(); - if (channelJoined != null && isVoiceChannel(channelJoined)) { + if (channelJoined != null && isVoiceChannel(channelJoined) && !user.isBot()) { handleVoiceChannelJoin(event, channelJoined); } From 10b13c8a43d2bc9d387f6a449698d4574cb175ce Mon Sep 17 00:00:00 2001 From: Suraj Kumar Date: Mon, 26 Jan 2026 16:00:58 +0000 Subject: [PATCH 3/4] feat: add synchronized keyword --- .../togetherjava/tjbot/features/voicechat/DynamicVoiceChat.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 ba8ae2edc6..cb5ac52ee6 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 @@ -79,7 +79,7 @@ private void handleVoiceChannelJoin(GuildVoiceUpdateEvent event, } } - private void handleVoiceChannelLeave(AudioChannelUnion channelLeft) { + private synchronized void handleVoiceChannelLeave(AudioChannelUnion channelLeft) { long channelId = channelLeft.getIdLong(); if (Boolean.TRUE.equals(deletedChannels.getIfPresent(channelId))) { From 443faeac0c918c3441637de01553d8ccfec0a492 Mon Sep 17 00:00:00 2001 From: Suraj Kumar Date: Mon, 26 Jan 2026 16:05:42 +0000 Subject: [PATCH 4/4] chore: try-catch the delete for extra protection --- .../tjbot/features/voicechat/DynamicVoiceChat.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) 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 cb5ac52ee6..9294d6dcd0 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 @@ -99,8 +99,12 @@ private synchronized void handleVoiceChannelLeave(AudioChannelUnion channelLeft) if (messages.size() > 1) { archiveDynamicVoiceChannel(channelLeft); } else { - channelLeft.delete().queue(); deletedChannels.put(channelId, true); + try { + channelLeft.delete().queue(); + } catch (Exception _) { + // Ignore + } } }); }