From 3088fbfaa419df909908e00d2c9af9dec62d6206 Mon Sep 17 00:00:00 2001 From: Aleksa Vuckovic Date: Wed, 10 Jun 2026 22:06:29 +0200 Subject: Reject /play early when voice channel is full Discord silently drops the bot's op 4 join when the channel user limit is reached and the bot lacks Move Members, causing a 30s AbortError timeout. Check voiceChannel.full upfront and return a clear error to the user. Also revert the voice-join diagnostic logging added while investigating. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/handlers/playCommand.js | 35 ++--------------------------------- 1 file changed, 2 insertions(+), 33 deletions(-) (limited to 'src/handlers') diff --git a/src/handlers/playCommand.js b/src/handlers/playCommand.js index 365f4f6..c61e009 100644 --- a/src/handlers/playCommand.js +++ b/src/handlers/playCommand.js @@ -129,50 +129,19 @@ async function createVoiceConnection(voiceChannel, interaction) { const maxAttempts = 2; for (let attempt = 1; attempt <= maxAttempts; attempt++) { - const guild = voiceChannel.guild; - const botMember = guild.members.me; - const botVoiceState = botMember?.voice; - console.log(`[JOIN ATTEMPT ${attempt}] Guild: ${guildId}, Channel: ${voiceChannel.id}, Shard status: ${guild.shard?.status}, Shard id: ${guild.shardId}`); - console.log(`[BOT INFO] id: ${guild.client.user?.id}, voice channelId: ${botVoiceState?.channelId ?? 'null'}, sessionId: ${botVoiceState?.sessionId ?? 'null'}, serverDeaf: ${botVoiceState?.serverDeaf}, serverMute: ${botVoiceState?.serverMute}, selfDeaf: ${botVoiceState?.selfDeaf}, selfMute: ${botVoiceState?.selfMute}`); - console.log(`[CHANNEL INFO] name: ${voiceChannel.name}, type: ${voiceChannel.type}, userLimit: ${voiceChannel.userLimit}, full: ${voiceChannel.full}, joinable: ${voiceChannel.joinable}, members: ${voiceChannel.members?.size}, rtcRegion: ${voiceChannel.rtcRegion}`); - - const baseAdapterCreator = guild.voiceAdapterCreator; - const adapterCreator = (methods) => { - const adapter = baseAdapterCreator(methods); - const originalSendPayload = adapter.sendPayload; - adapter.sendPayload = (data) => { - const result = originalSendPayload(data); - console.log(`[ADAPTER sendPayload] op=${data?.op}, sent=${result}, shard=${guild.shard?.status}, payload=${JSON.stringify(data?.d)}`); - return result; - }; - const originalDestroy = adapter.destroy; - adapter.destroy = () => { - console.log(`[ADAPTER destroy]`); - return originalDestroy(); - }; - return adapter; - }; - const connection = joinVoiceChannel({ channelId: voiceChannel.id, guildId, - adapterCreator, + adapterCreator: voiceChannel.guild.voiceAdapterCreator, selfDeaf: true, }); - const stateLogger = (oldState, newState) => { - console.log(`[VOICE STATE] Guild: ${guildId}, ${oldState.status} -> ${newState.status}${newState.reason ? ` (reason: ${newState.reason})` : ''}${newState.closeCode ? ` (closeCode: ${newState.closeCode})` : ''}`); - }; - connection.on('stateChange', stateLogger); - try { await entersState(connection, VoiceConnectionStatus.Ready, 30000); - connection.off('stateChange', stateLogger); return connection; } catch (error) { lastError = error; - console.error(`Failed to join voice channel (attempt ${attempt}/${maxAttempts}), last state: ${connection.state?.status}:`, error); - connection.off('stateChange', stateLogger); + console.error(`Failed to join voice channel (attempt ${attempt}/${maxAttempts}):`, error); try { connection.destroy(); } catch (e) { -- cgit v1.2.3