fix: Bug - Voice states doesn't get cleared for all users on leave
Broadcast a cleared voice_state when voice-active sockets drop and reset mute/deafen flags on disconnect or reconnect so stale session state cannot leak to other clients. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -134,6 +134,59 @@ function clearVoiceActiveForOderId(oderId: string, exceptConnectionId?: string):
|
||||
});
|
||||
}
|
||||
|
||||
function readVoiceStateServerId(snapshot: Record<string, unknown> | undefined): string | undefined {
|
||||
if (!snapshot) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const nestedVoiceState = snapshot['voiceState'];
|
||||
|
||||
if (nestedVoiceState && typeof nestedVoiceState === 'object') {
|
||||
const nestedServerId = readMessageId((nestedVoiceState as { serverId?: unknown }).serverId);
|
||||
|
||||
if (nestedServerId) {
|
||||
return nestedServerId;
|
||||
}
|
||||
}
|
||||
|
||||
return readMessageId(snapshot['serverId']);
|
||||
}
|
||||
|
||||
/** Broadcast a cleared voice_state when a voice-active socket disappears without a graceful leave. */
|
||||
export function finalizeVoiceDisconnectForConnection(connectionId: string): void {
|
||||
const user = connectedUsers.get(connectionId);
|
||||
|
||||
if (!user?.authenticated || (!user.voiceActive && !user.voiceStateSnapshot)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const serverId = readVoiceStateServerId(user.voiceStateSnapshot) ?? user.viewedServerId;
|
||||
|
||||
if (serverId && user.serverIds.has(serverId)) {
|
||||
broadcastToServer(
|
||||
serverId,
|
||||
{
|
||||
type: 'voice_state',
|
||||
serverId,
|
||||
oderId: user.oderId,
|
||||
displayName: normalizeDisplayName(user.displayName),
|
||||
voiceState: {
|
||||
isConnected: false,
|
||||
isMuted: false,
|
||||
isDeafened: false,
|
||||
isSpeaking: false
|
||||
}
|
||||
},
|
||||
{ excludeConnectionId: connectionId }
|
||||
);
|
||||
}
|
||||
|
||||
user.voiceActive = false;
|
||||
user.voiceStateSnapshot = undefined;
|
||||
connectedUsers.set(connectionId, user);
|
||||
clearVoiceActiveForOderId(user.oderId, connectionId);
|
||||
}
|
||||
|
||||
function sendVoiceStateSnapshotToConnection(user: ConnectedUser, snapshot: Record<string, unknown>): void {
|
||||
user.ws.send(JSON.stringify({
|
||||
type: 'voice_state',
|
||||
|
||||
Reference in New Issue
Block a user