From 192cec689aee68bc9dbd4daf21fbdb9a7209f42c Mon Sep 17 00:00:00 2001 From: Hampus Date: Mon, 28 Sep 2026 19:50:47 +0200 Subject: [PATCH] fix(app): keep voice connections of one session across channels (#3023) --- .../engine/VoiceGatewayStateMachine.test.ts | 22 +++++++++++++++++++ .../voice/engine/VoiceGatewayStateMachine.ts | 1 + 2 files changed, 23 insertions(+) diff --git a/fluxer_app/src/features/voice/engine/VoiceGatewayStateMachine.test.ts b/fluxer_app/src/features/voice/engine/VoiceGatewayStateMachine.test.ts index 8b5a0038b..a63a62626 100644 --- a/fluxer_app/src/features/voice/engine/VoiceGatewayStateMachine.test.ts +++ b/fluxer_app/src/features/voice/engine/VoiceGatewayStateMachine.test.ts @@ -210,6 +210,28 @@ describe('VoiceGatewayStateMachine', () => { expectProjectionConsistent(snapshot.context); }); + it('keeps same-session connections in different channels', () => { + const snapshot = transition(createVoiceGatewayStateSnapshot(), { + type: 'guild.create', + guild: guild('guild-1', [ + voiceState({connection_id: 'connection-a', session_id: 'session-a', channel_id: 'channel-1'}), + voiceState({connection_id: 'connection-b', session_id: 'session-a', channel_id: 'channel-2'}), + ]), + }); + + expectConnection(snapshot.context, 'connection-a', { + guild_id: 'guild-1', + channel_id: 'channel-1', + user_id: 'user-1', + }); + expectConnection(snapshot.context, 'connection-b', { + guild_id: 'guild-1', + channel_id: 'channel-2', + user_id: 'user-1', + }); + expectProjectionConsistent(snapshot.context); + }); + it('deletes all user connections in a guild', () => { let snapshot = createVoiceGatewayStateSnapshot(); snapshot = transition(snapshot, { diff --git a/fluxer_app/src/features/voice/engine/VoiceGatewayStateMachine.ts b/fluxer_app/src/features/voice/engine/VoiceGatewayStateMachine.ts index 0e7790538..76138de14 100644 --- a/fluxer_app/src/features/voice/engine/VoiceGatewayStateMachine.ts +++ b/fluxer_app/src/features/voice/engine/VoiceGatewayStateMachine.ts @@ -200,6 +200,7 @@ function removeStaleSessionConnections( for (const [connectionId, existing] of Object.entries(indexedGuildStates)) { if (connectionId === voiceState.connection_id) continue; if (existing.session_id !== voiceState.session_id) continue; + if (existing.channel_id !== voiceState.channel_id) continue; next = removeConnection(next, connectionId); } return next;