discordjs / discord.js

A powerful JavaScript library for interacting with the Discord API
https://discord.js.org
Apache License 2.0
25.31k stars 3.97k forks source link

VoiceConnection stuck in signalling state about a minute after creating it #9185

Closed Theiremi closed 1 year ago

Theiremi commented 1 year ago

Which package is this bug report for?

voice

Issue description

I've noticed a bug that seems to affect also some other users (see #8482). All the VoiceConnection works as intended the first minute, and then stop playing anything. The player subscribed switch in AutoPaused and the connection stays signalling state indefinitely.

After looking at the code (https://github.com/discordjs/discord.js/blob/main/packages/voice/src/VoiceConnection.ts), it seems that the only way for it to go back to ready state is to receive a message from discord api, that then create events that can put status back in ready state. But, if I understand correctly, this discord message never comes(line 335), so an event is not created through the function configureNetworking(line 338, 420), and the state cannot change to ready(line 484). That's a messy explanation, and maybe false btw, but I've tried my best to understand.

Code sample

let voice_connection = Voice.joinVoiceChannel({
    adapterCreator: guild.voiceAdapterCreator,
    guildId: guild_id,
    channelId: channel_id,
    selfDeaf: true,
    selfMute: false
});

let player = new Voice.AudioPlayer({noSubscriber: Voice.NoSubscriberBehavior.Pause});
voice_connection.subscribe(player);

let resource = Voice.createAudioResource(local_file_or_stream);
player.play(resource);

Package version

14.7.0

Node.js version

18.7.0; 18.14.2; 19.7.0 and maybe others

Operating system

Windows, WSL, Ubuntu, Debian...

Priority this issue should have

Medium (should be fixed soon)

Which partials do you have configured?

Not applicable (subpackage bug)

Which gateway intents are you subscribing to?

Guilds, GuildVoiceStates

I have tested this issue on a development release

No response

Theiremi commented 1 year ago

I've also found a workaround to this problem :

Add this.configureNetworking(); on the line 355 of this file : https://github.com/discordjs/discord.js/blob/main/packages/voice/src/VoiceConnection.ts Or Add this.configureNetworking(); on the line 1361 of the file located at node_modules/@discordjs/voice/dist/index.js

FloPMT commented 1 year ago

I've also found a workaround to this problem :

Add this.configureNetworking(); on the line 355 of this file : https://github.com/discordjs/discord.js/blob/main/packages/voice/src/VoiceConnection.ts Or Add this.configureNetworking(); on the line 1361 of the file located at node_modules/@discordjs/voice/dist/index.js

Thank you! This sort of helps as it seems to restart the stream after a few seconds of it being autopaused. But that's not really a solution where I'd create a PR because the stream still stops after each minute. What's weird is that even with noSubscriber: NoSubscriberBehavior.Play it pauses playback. Just the status doesn't update and remains "playing".

image
potatojuicemachine commented 1 year ago

I have the same problem. It started to happen today without me changing anything in the code. So probably discord changing something on their side of the connection πŸ€”. @Theiremi your solution works for me but now i have a short pause every minute while playling.

vittee commented 1 year ago

I have the exact same issue, after trying to figure out what could possibly be the problem I found that this happen only on some voice servers.

I was trying to override voice channel region between Singapore and Hong Kong. The problem will not occur if the channel endpoint has the number greater than around 10,000

e.g. singapore1172 -> Has problem singapore4221 -> Has problem singapore11001 -> Working just fine

You can enable debugging in VoiceConnection by setting debug field to true when calling joinVoiceChannel() function

const voiceConnection = joinVoiceChannel({
  debug: true,
  channelId,
  guildId,
  adapterCreator: voiceAdapterCreator
});

voiceConnection.on('debug', (m) => {
  console.log('Voice Debug:', m);
});

I got this debug message when the connection was closed

Voice Debug: [NW] state change:
from {"code":4,"ws":true,"connectionOptions":{"endpoint":"singapore4221.discord.media:443"},"udp":true,"speaking":true,"packetsPlayed":2996}}
to {"code":5,"ws":true,"connectionOptions":{"endpoint":"singapore4221.discord.media:443"},"udp":true},"speaking":true,"packetsPlayed":2996}}

Voice Debug: [NW] [WS] >> {"op":7,"d":{...}}
Voice Debug: [NW] [WS] << {"op":8,"d":{"v":4,"heartbeat_interval":13750.0}}

Voice Debug: [NW] state change:
from {"code":5,"ws":true,"connectionOptions":{"endpoint":"singapore4221.discord.media:443"},"udp":true,"speaking":true,"packetsPlayed":2996}}}
to {"code":6,"ws":false,"udp":false}

Networking status code 4 is "Ready", 5 is "Resuming" and 6 is "Closed"

After looking at VoiceConnection code: https://github.com/discordjs/discord.js/blob/main/packages/voice/src/VoiceConnection.ts#L442-L467

I can see that it handles disconnection properly but somehow re-signalling/rejoining is not working as expected.

The solution I could find right now is try to override server region to other regions until you get a voice server with number greater than 10,000 in its name, but the server will change again if the channel is empty.

Theiremi commented 1 year ago

I've noticed a pause too, i guess there is a problem on discord side causing the connection to crash every minute. The pause happens during the time needed to reconnect so we probably can't get better solution for now πŸ˜₯

Theiremi commented 1 year ago

I have the exact same issue, after trying to figure out what could possibly be the problem I found that this happen only on some voice servers.

I was trying to override voice channel region between Singapore and Hong Kong. The problem will not occur if the channel endpoint has the number greater than around 10,000

e.g. singapore1172 -> Has problem singapore4221 -> Has problem singapore11001 -> Working just fine

You can enable debugging in VoiceConnection by setting debug field to true when calling joinVoiceChannel() function

const voiceConnection = joinVoiceChannel({
  debug: true,
  channelId,
  guildId,
  adapterCreator: voiceAdapterCreator
});

voiceConnection.on('debug', (m) => {
  console.log('Voice Debug:', m);
});

I got this debug message when the connection was closed

Voice Debug: [NW] state change:
from {"code":4,"ws":true,"connectionOptions":{"endpoint":"singapore4221.discord.media:443"},"udp":true,"speaking":true,"packetsPlayed":2996}}
to {"code":5,"ws":true,"connectionOptions":{"endpoint":"singapore4221.discord.media:443"},"udp":true},"speaking":true,"packetsPlayed":2996}}

Voice Debug: [NW] [WS] >> {"op":7,"d":{...}}
Voice Debug: [NW] [WS] << {"op":8,"d":{"v":4,"heartbeat_interval":13750.0}}

Voice Debug: [NW] state change:
from {"code":5,"ws":true,"connectionOptions":{"endpoint":"singapore4221.discord.media:443"},"udp":true,"speaking":true,"packetsPlayed":2996}}}
to {"code":6,"ws":false,"udp":false}

Networking status code 4 is "Ready", 5 is "Resuming" and 6 is "Closed"

After looking at VoiceConnection code: https://github.com/discordjs/discord.js/blob/main/packages/voice/src/VoiceConnection.ts#L442-L467

I can see that it handles disconnection properly but somehow re-signalling/rejoining is not working as expected.

The solution I could find right now is try to override server region to other regions until you get a voice server with number greater than 10,000 in its name, but the server will change again if the channel is empty.

Interesting, it seems to confirm that the issue is coming from discord

vittee commented 1 year ago

I tried to override my voice channel to Singapore and I got singapore11014. It is working just fine, no disconnection at all.

FloPMT commented 1 year ago

I tried to override my voice channel to Singapore and I got singapore11014. It is working just fine, no disconnection at all.

Could you share how you do it? Thanks!

Theiremi commented 1 year ago

Do you know if overriding the server region can only be done by end users or if it's possible to make a patch in our bots too ?

vittee commented 1 year ago

I think you must have administrative permission on the server you want to override and it can only be done via Discord app itself.

image

image

Theiremi commented 1 year ago

Ok so i've made an announce in my server linking to your solution to help end users

Jiralite commented 1 year ago

I believe this was a Discord issue that should be resolved now. Can you guys check (on a new connection, if possible (restart your bot)) if you can still reproduce this?

FloPMT commented 1 year ago

I think you must have administrative permission on the server you want to override and it can only be done via Discord app itself.

image

image

I found that it's possible programmatically with the right permissions: voiceChannel.setRTCRegion('singapore');

This doesn't fix the problem for me however.

FloPMT commented 1 year ago

I believe this was a Discord issue that should be resolved now. Can you guys check (on a new connection, if possible (restart your bot)) if you can still reproduce this?

Unfortunately still have the same issue.

potatojuicemachine commented 1 year ago

I wasn't able to switch the region on the server so I made this as a temporary workaround:

this.connection.on('stateChange', (old_state, new_state) => {
            this.logger.logMessage('join', 'Connection state change from', old_state.status, 'to', new_state.status)
            if (old_state.status === VoiceConnectionStatus.Ready && new_state.status === VoiceConnectionStatus.Connecting) {
                connection.configureNetworking();
            }
        })

The little pause is shorter then on this solution. Maybe this helps anyopne looking for a temporary solution.

vittee commented 1 year ago

I think you must have administrative permission on the server you want to override and it can only be done via Discord app itself. image image

I found that it's possible programmatically with the right permissions: voiceChannel.setRTCRegion('singapore');

This doesn't fix the problem for me however.

Thanks, would try that.

BTW, overriding the region to Singapore does not fix the problem, you need to keep changing it until you get server which has number greater than 10,000 in its name.

This one is working fine for me image

Theiremi commented 1 year ago

I believe this was a Discord issue that should be resolved now. Can you guys check (on a new connection, if possible (restart your bot)) if you can still reproduce this?

I can't test on a fresh instance for now, but still happens for me too

Theiremi commented 1 year ago

I wasn't able to switch the region on the server so I made this as a temporary workaround:

this.connection.on('stateChange', (old_state, new_state) => {
            this.logger.logMessage('join', 'Connection state change from', old_state.status, 'to', new_state.status)
            if (old_state.status === VoiceConnectionStatus.Ready && new_state.status === VoiceConnectionStatus.Connecting) {
                connection.configureNetworking();
            }
        })

The little pause is shorter then on this solution. Maybe this helps anyopne looking for a temporary solution.

That's actually also a much simpler solution as it doesn't require modifying module code πŸ˜„

vittee commented 1 year ago

I believe this was a Discord issue that should be resolved now. Can you guys check (on a new connection, if possible (restart your bot)) if you can still reproduce this?

Still happens on singapore8142, but works fine on singapore11014

potatojuicemachine commented 1 year ago

I believe this was a Discord issue that should be resolved now. Can you guys check (on a new connection, if possible (restart your bot)) if you can still reproduce this?

Restarted my bot several times. Still same issue.

YenBenGrey commented 1 year ago

I wasn't able to switch the region on the server so I made this as a temporary workaround:

this.connection.on('stateChange', (old_state, new_state) => {
            this.logger.logMessage('join', 'Connection state change from', old_state.status, 'to', new_state.status)
            if (old_state.status === VoiceConnectionStatus.Ready && new_state.status === VoiceConnectionStatus.Connecting) {
                connection.configureNetworking();
            }
        })

The little pause is shorter then on this solution. Maybe this helps anyopne looking for a temporary solution.

That's actually also a much simpler solution as it doesn't require modifying module code πŸ˜„

Imagine you have no idea about how to write code? Where would you put this so that things work again in Discord?

dzlandis commented 1 year ago

Also experiencing this same issue! I have changed nothing with my code. This problem has been causing my bot's features to not work correctly after initially connecting to a voice channel for about a minute. This should have high priority!

AcidRain999 commented 1 year ago

I wasn't able to switch the region on the server so I made this as a temporary workaround:

this.connection.on('stateChange', (old_state, new_state) => {
            this.logger.logMessage('join', 'Connection state change from', old_state.status, 'to', new_state.status)
            if (old_state.status === VoiceConnectionStatus.Ready && new_state.status === VoiceConnectionStatus.Connecting) {
                connection.configureNetworking();
            }
        })

The little pause is shorter then on this solution. Maybe this helps anyopne looking for a temporary solution.

not sure where to put that fix but the other one referenced was easy to put in and sorta fixes it

Positive2022 commented 1 year ago

I believe this was a Discord issue that should be resolved now. Can you guys check (on a new connection, if possible (restart your bot)) if you can still reproduce this?

Discord recently did a new update that is causing this issue Message Link: https://discord.com/channels/613425648685547541/697138785317814292/1080623873629884486 Edit: You have to join .gg/discord-developers server to see this message.

We recently pushed out a change related to Voice Connections that broke apps sending 70-byte UDP packets to the voice server when using IP Discovery. While the documentation and deprecation were updated in December 2019, there wasn't communication around the the change starting to roll out so we've temporarily reverted the change to give developers more time to handle the breaking change.

Jiralite commented 1 year ago

I don't think so:

https://github.com/discordjs/discord.js/blob/dc142c47e4021d6d37712453cc2fad6e4fe4e9f7/packages/voice/src/networking/VoiceUDPSocket.ts#L206

It seems we already support this.

potatojuicemachine commented 1 year ago

Imagine you have no idea about how to write code? Where would you put this so that things work again in Discord?

Well if you don't know how to write code, you propably don't use this discord.js. But as there is at least one person that doesn't know where to put this, you are probably right.

not sure where to put that fix but the other one referenced was easy to put in and sorta fixes it

Put this after you created your connection. For me it looks something like this:

const connection = joinVoiceChannel({
            channelId: channel_id,
            guildId: guild_id,
            adapterCreator: this.voice_channel.guild.voiceAdapterCreator,
            selfDeaf: true,
            selfMute: false
        });
connection.on('stateChange', (old_state, new_state) => {
            if (old_state.status === VoiceConnectionStatus.Ready && new_state.status === VoiceConnectionStatus.Connecting) {
                connection.configureNetworking();
            }
        })
potatojuicemachine commented 1 year ago

Discord recently did a new update that is causing this issue Message Link: https://discord.com/channels/613425648685547541/697138785317814292/1080623873629884486

We recently pushed out a change related to Voice Connections that broke apps sending 70-byte UDP packets to the voice server when using IP Discovery. While the documentation and deprecation were updated in December 2019, there wasn't communication around the the change starting to roll out so we've temporarily reverted the change to give developers more time to handle the breaking change.

I am not sure how to folow that link. For me it says "No text channels" is there a discord server I have to join?

Positive2022 commented 1 year ago

Discord recently did a new update that is causing this issue Message Link: https://discord.com/channels/613425648685547541/697138785317814292/1080623873629884486 We recently pushed out a change related to Voice Connections that broke apps sending 70-byte UDP packets to the voice server when using IP Discovery. While the documentation and deprecation were updated in December 2019, there wasn't communication around the the change starting to roll out so we've temporarily reverted the change to give developers more time to handle the breaking change.

I am not sure how to folow that link. For me it says "No text channels" is there a discord server I have to join?

This is a message from Discord Developers Server. .gg/discord-developers

vittee commented 1 year ago

After investigation I am sure that this is a bug in @discordjs/voice that affecting some voice servers.

The VoiceUDPSocket object implemented some undocumented keepAlive functionality which sends a keepAlive counter packed in a 8-bytes data every 5 seconds interval, and it expects a reply from voice server.

But somehow some of the voice servers out there did not response back with the keepAlive counter, resulting in the keepAlives array to grow and eventually reach the 12 length limit, which took exactly 60 seconds.

https://github.com/discordjs/discord.js/blob/dc142c47e4021d6d37712453cc2fad6e4fe4e9f7/packages/voice/src/networking/VoiceUDPSocket.ts#L39-L47

This code sets up the keepAlive functionality. https://github.com/discordjs/discord.js/blob/dc142c47e4021d6d37712453cc2fad6e4fe4e9f7/packages/voice/src/networking/VoiceUDPSocket.ts#L117-L120

This method expects a keepAlive counter data response from the voice server. https://github.com/discordjs/discord.js/blob/dc142c47e4021d6d37712453cc2fad6e4fe4e9f7/packages/voice/src/networking/VoiceUDPSocket.ts#L130-L143

Here are some debugging logs from VoiceUDPSocket connected to singapore63 voice server which affected by this issue.

1677785882271 [VoiceUDPSocket onMessage] 52
1677785883272 [VoiceUDPSocket onMessage] 52
1677785884271 [VoiceUDPSocket onMessage] 52
1677785885271 [VoiceUDPSocket onMessage] 52
1677785886271 [VoiceUDPSocket onMessage] 52
1677785886600 [VoiceUDPSocket keepAlive] this.keepAlives.length >= KEEP_ALIVE_LIMIT 11 12
1677785887271 [VoiceUDPSocket onMessage] 52
1677785888271 [VoiceUDPSocket onMessage] 52
1677785889271 [VoiceUDPSocket onMessage] 52
1677785890271 [VoiceUDPSocket onMessage] 52
1677785891271 [VoiceUDPSocket onMessage] 52
1677785891601 [VoiceUDPSocket keepAlive] this.keepAlives.length >= KEEP_ALIVE_LIMIT 12 12
--------------- VoiceUDPSocket destroy called Error
    at EventEmitter.destroy
    at EventEmitter.keepAlive
    at Timeout._onTimeout
    at listOnTimeout (node:internal/timers:564:17)
    at process.processTimers (node:internal/timers:507:7)
UDP SOCKET CLOSED

As you can see, there is no 8-bytes response and the VoiceUDPSocket.destroy() method was called by the keepAlive method.

I managed to find an unaffected voice server which is singapore11050, and here are the logs

1677786081734 [VoiceUDPSocket keepAlive] this.keepAlives.length >= KEEP_ALIVE_LIMIT 1 12
1677786081766 [VoiceUDPSocket onMessage] 8
1677786082613 [VoiceUDPSocket onMessage] 52
1677786083613 [VoiceUDPSocket onMessage] 52
1677786084612 [VoiceUDPSocket onMessage] 52
1677786085613 [VoiceUDPSocket onMessage] 52
1677786086612 [VoiceUDPSocket onMessage] 52
1677786086736 [VoiceUDPSocket keepAlive] this.keepAlives.length >= KEEP_ALIVE_LIMIT 1 12
1677786086767 [VoiceUDPSocket onMessage] 8
1677786087612 [VoiceUDPSocket onMessage] 52
1677786088612 [VoiceUDPSocket onMessage] 52
1677786089613 [VoiceUDPSocket onMessage] 52
1677786090633 [VoiceUDPSocket onMessage] 52
1677786091633 [VoiceUDPSocket onMessage] 52
1677786091735 [VoiceUDPSocket keepAlive] this.keepAlives.length >= KEEP_ALIVE_LIMIT 1 12

The voice server did response back with expected data so keepAlives array will never grow and I didn't experience a disconnection from this server.

vittee commented 1 year ago

A workaround is to remove keepAlive timer/interval.

You can do this without patching @discordjs/voice in node_modules.

Simply put the following code for a voiceConnection object.

const networkStateChangeHandler = (oldNetworkState: any, newNetworkState: any) => {
  const newUdp = Reflect.get(newNetworkState, 'udp');
  clearInterval(newUdp?.keepAliveInterval);
}

voiceConnection.on('stateChange', (oldState, newState) => {
  const oldNetworking = Reflect.get(oldState, 'networking');
  const newNetworking = Reflect.get(newState, 'networking');

  oldNetworking?.off('stateChange', networkStateChangeHandler);
  newNetworking?.on('stateChange', networkStateChangeHandler);
});

This is TypeScript, for JavaScript simply remove all type annotations.

Thanks to @ramsydx for the updated version.

manuel-rw commented 1 year ago

A workaround is to remove keepAlive timer/interval.

You can do this without patching @discordjs/voice in node_modules.

Simply put the following code for a voiceConnection object

voiceConnection.on('stateChange', (oldState, newState) => {
  const oldNetworking = Reflect.get(oldState, 'networking');
  const newNetworking = Reflect.get(newState, 'networking');

  const networkStateChangeHandler = (oldNetworkState: any, newNetworkState: any) => {
    const newUdp = Reflect.get(newNetworkState, 'udp');
    clearInterval(newUdp?.keepAliveInterval);
  }

  oldNetworking?.off('stateChange', networkStateChangeHandler);
  newNetworking?.on('stateChange', networkStateChangeHandler);
});

This is TypeScript, for JavaScript simply remove all type annotations.

Can confirm that this fixes the issue on my bot πŸ‘ I am on us-east1460.

dzlandis commented 1 year ago

@vittee Have you made a pull request anywhere to fix this problem if it's a @discordjs/voice issue?

vittee commented 1 year ago

@vittee Have you made a pull request anywhere to fix this problem if it's a @discordjs/voice issue?

I did not create a PR, as I'm not sure why they implemented this keepAlive thing in the first place, and why this is only happening on some servers.

npackr commented 1 year ago

Thanks to @vittee & @AcidRain999, the problem has been fixed and works fine on my project. Below is exactly what I have used:

    const oldNetworking = Reflect.get(oldState, 'networking');
    const newNetworking = Reflect.get(newState, 'networking');
    const networkStateChangeHandler = (oldNetworkState, newNetworkState) => {
      const newUdp = Reflect.get(newNetworkState, 'udp');
      clearInterval(newUdp?.keepAliveInterval);
    }
    oldNetworking?.off('stateChange', networkStateChangeHandler);
    newNetworking?.on('stateChange', networkStateChangeHandler);
    if (oldState.status === VoiceConnectionStatus.Ready && newState.status === VoiceConnectionStatus.Connecting) {
      connection.configureNetworking();
    }
  });
davidzeng0 commented 1 year ago

The fix is leet cafe

https://github.com/davidzeng0/voice/commit/2a06cd4fd9d58626311944cc54f5fca5d891e57f

Here is a snippet from discord_voice.node's source code

image

I would PR @discordjs/voice but its archived :(

Happy fixing!

davidzeng0 commented 1 year ago

That, and this commit https://github.com/davidzeng0/voice/commit/db413382a1ca4f168e54b01d2ebb7e9a997892c3

should fix signalling stall.

dzlandis commented 1 year ago

@davidzeng0 the discordjs/voice repo was moved into a monorepo in this repository I believe. You can make a pull request for it in this repository.

matthewfucation commented 1 year ago

A workaround is to remove keepAlive timer/interval.

You can do this without patching @discordjs/voice in node_modules.

Simply put the following code for a voiceConnection object

voiceConnection.on('stateChange', (oldState, newState) => {
  const oldNetworking = Reflect.get(oldState, 'networking');
  const newNetworking = Reflect.get(newState, 'networking');

  const networkStateChangeHandler = (oldNetworkState: any, newNetworkState: any) => {
    const newUdp = Reflect.get(newNetworkState, 'udp');
    clearInterval(newUdp?.keepAliveInterval);
  }

  oldNetworking?.off('stateChange', networkStateChangeHandler);
  newNetworking?.on('stateChange', networkStateChangeHandler);
});

This is TypeScript, for JavaScript simply remove all type annotations.

I'm a bit confused as to where to put this? Tried following this and a few threads about this same issue and got a bit lost.

npackr commented 1 year ago

A workaround is to remove keepAlive timer/interval. You can do this without patching @discordjs/voice in node_modules. Simply put the following code for a voiceConnection object

voiceConnection.on('stateChange', (oldState, newState) => {
  const oldNetworking = Reflect.get(oldState, 'networking');
  const newNetworking = Reflect.get(newState, 'networking');

  const networkStateChangeHandler = (oldNetworkState: any, newNetworkState: any) => {
    const newUdp = Reflect.get(newNetworkState, 'udp');
    clearInterval(newUdp?.keepAliveInterval);
  }

  oldNetworking?.off('stateChange', networkStateChangeHandler);
  newNetworking?.on('stateChange', networkStateChangeHandler);
});

This is TypeScript, for JavaScript simply remove all type annotations.

I'm a bit confused as to where to put this? Tried following this and a few threads about this same issue and got a bit lost.

Add it after you create or get the voiceConnection. Ex:

const connection = joinVoiceChannel({ channelId: channel.id, guildId: guild.id, adapterCreator: guild.voiceAdapterCreator });
connection.on('stateChange', async (oldState, newState) => {
    ...
});
smclean117 commented 1 year ago

A workaround is to remove keepAlive timer/interval. You can do this without patching @discordjs/voice in node_modules. Simply put the following code for a voiceConnection object

voiceConnection.on('stateChange', (oldState, newState) => {
  const oldNetworking = Reflect.get(oldState, 'networking');
  const newNetworking = Reflect.get(newState, 'networking');

  const networkStateChangeHandler = (oldNetworkState: any, newNetworkState: any) => {
    const newUdp = Reflect.get(newNetworkState, 'udp');
    clearInterval(newUdp?.keepAliveInterval);
  }

  oldNetworking?.off('stateChange', networkStateChangeHandler);
  newNetworking?.on('stateChange', networkStateChangeHandler);
});

This is TypeScript, for JavaScript simply remove all type annotations.

I'm a bit confused as to where to put this? Tried following this and a few threads about this same issue and got a bit lost.

Add it after you create or get the voiceConnection. Ex:

const connection = joinVoiceChannel({ channelId: channel.id, guildId: guild.id, adapterCreator: guild.voiceAdapterCreator });
connection.on('stateChange', async (oldState, newState) => {
   ...
});

I cannot locate the file that contains "joinVoiceChannel" to then add this line, will it be part of the node-module discord.js files or part of the root bots files?

npackr commented 1 year ago

A workaround is to remove keepAlive timer/interval. You can do this without patching @discordjs/voice in node_modules. Simply put the following code for a voiceConnection object

voiceConnection.on('stateChange', (oldState, newState) => {
  const oldNetworking = Reflect.get(oldState, 'networking');
  const newNetworking = Reflect.get(newState, 'networking');

  const networkStateChangeHandler = (oldNetworkState: any, newNetworkState: any) => {
    const newUdp = Reflect.get(newNetworkState, 'udp');
    clearInterval(newUdp?.keepAliveInterval);
  }

  oldNetworking?.off('stateChange', networkStateChangeHandler);
  newNetworking?.on('stateChange', networkStateChangeHandler);
});

This is TypeScript, for JavaScript simply remove all type annotations.

I'm a bit confused as to where to put this? Tried following this and a few threads about this same issue and got a bit lost.

Add it after you create or get the voiceConnection. Ex:

const connection = joinVoiceChannel({ channelId: channel.id, guildId: guild.id, adapterCreator: guild.voiceAdapterCreator });
connection.on('stateChange', async (oldState, newState) => {
   ...
});

I cannot locate the file that contains "joinVoiceChannel" to then add this line, will it be part of the node-module discord.js files or part of the root bots files?

Your bot's file. You need to joinVoiceChannel before subscribing to a player and playing music. Are you use any library to play music?

smclean117 commented 1 year ago

A workaround is to remove keepAlive timer/interval. You can do this without patching @discordjs/voice in node_modules. Simply put the following code for a voiceConnection object

voiceConnection.on('stateChange', (oldState, newState) => {
  const oldNetworking = Reflect.get(oldState, 'networking');
  const newNetworking = Reflect.get(newState, 'networking');

  const networkStateChangeHandler = (oldNetworkState: any, newNetworkState: any) => {
    const newUdp = Reflect.get(newNetworkState, 'udp');
    clearInterval(newUdp?.keepAliveInterval);
  }

  oldNetworking?.off('stateChange', networkStateChangeHandler);
  newNetworking?.on('stateChange', networkStateChangeHandler);
});

This is TypeScript, for JavaScript simply remove all type annotations.

I'm a bit confused as to where to put this? Tried following this and a few threads about this same issue and got a bit lost.

Add it after you create or get the voiceConnection. Ex:

const connection = joinVoiceChannel({ channelId: channel.id, guildId: guild.id, adapterCreator: guild.voiceAdapterCreator });
connection.on('stateChange', async (oldState, newState) => {
   ...
});

I cannot locate the file that contains "joinVoiceChannel" to then add this line, will it be part of the node-module discord.js files or part of the root bots files?

Your bot's file. You need to joinVoiceChannel before subscribing to a player and playing music. Are you use any library to play music?

Honestly I'm not sure how to answer that question, I've been using this repo https://github.com/TannerGabriel/discord-bot and maintaining my own bot on a pi4.

I'll keep searching for the appropriate file to change. Thanks.

vittee commented 1 year ago

@smclean117 Your project uses discord-player, I can see that it has an open issue related to this.

Please see: https://github.com/Androz2091/discord-player/issues/1630#issuecomment-1452877967

ghost commented 1 year ago

A workaround is to remove keepAlive timer/interval.

You can do this without patching @discordjs/voice in node_modules.

Simply put the following code for a voiceConnection object

voiceConnection.on('stateChange', (oldState, newState) => {
  const oldNetworking = Reflect.get(oldState, 'networking');
  const newNetworking = Reflect.get(newState, 'networking');

  const networkStateChangeHandler = (oldNetworkState: any, newNetworkState: any) => {
    const newUdp = Reflect.get(newNetworkState, 'udp');
    clearInterval(newUdp?.keepAliveInterval);
  }

  oldNetworking?.off('stateChange', networkStateChangeHandler);
  newNetworking?.on('stateChange', networkStateChangeHandler);
});

This is TypeScript, for JavaScript simply remove all type annotations.

Thanks a lot!!! I was fixing it for a 5 hours... You have saved my day!

smclean117 commented 1 year ago

@smclean117 Your project uses discord-player, I can see that it has an open issue related to this.

Please see: https://github.com/Androz2091/discord-player/issues/1630#issuecomment-1452877967

Thanks, all sorted now πŸ™πŸ»

davidzeng0 commented 1 year ago

PR created, thanks for letting me know, @dzlandis

vittee commented 1 year ago

PR created, thanks for letting me know

Thanks, I've looked at your commits and saw that the keepAlive is not removed but instead implement with the actual payload used in the official Discord App.

vittee commented 1 year ago

@davidzeng0 I'm not quite sure if this is a good idea, Discord uses that magic number for some reasons.

davidzeng0 commented 1 year ago

@davidzeng0 I'm not quite sure if this is a good idea, Discord uses that magic number for some reasons.

I think it's okay since it translates to "leet cafe" which makes me inclined to think Discord just wanted a magic number to differentiate heartbeats. If they changed it, it would brick all of their clients as well. I have checked a few months ago to find the same magic constant in their older module before they updated their voice servers. And either way, I believe it's still best to patch the issue for now and work on a more "permanent" fix later.

vittee commented 1 year ago

I agree.

Discord should have been describing this in their documentations. πŸ˜΅β€πŸ’«