fix: voice connection

This commit is contained in:
Elysia
2024-07-25 10:50:46 +07:00
parent eb96d562ba
commit c193116100
4 changed files with 30 additions and 18 deletions

View File

@@ -1,6 +1,5 @@
'use strict'; 'use strict';
const { Collection } = require('@discordjs/collection');
const VoiceConnection = require('./VoiceConnection'); const VoiceConnection = require('./VoiceConnection');
const { Error } = require('../../errors'); const { Error } = require('../../errors');
const { Events } = require('../../util/Constants'); const { Events } = require('../../util/Constants');
@@ -20,10 +19,10 @@ class ClientVoiceManager {
Object.defineProperty(this, 'client', { value: client }); Object.defineProperty(this, 'client', { value: client });
/** /**
* A collection mapping connection IDs to the Connection objects * A current connection objects
* @type {Collection<Snowflake, VoiceConnection>} * @type {?VoiceConnection}
*/ */
this.connections = new Collection(); this.connection = null;
/** /**
* Maps guild ids to voice adapters created for use with @discordjs/voice. * Maps guild ids to voice adapters created for use with @discordjs/voice.
@@ -49,7 +48,7 @@ class ClientVoiceManager {
channel_id || guild_id channel_id || guild_id
} token: ${token} endpoint: ${endpoint}`, } token: ${token} endpoint: ${endpoint}`,
); );
const connection = this.connections.get(guild_id || channel_id); // DMs Call const connection = this.connection;
if (connection) connection.setTokenAndEndpoint(token, endpoint); if (connection) connection.setTokenAndEndpoint(token, endpoint);
// Djs / voice // Djs / voice
if (payload.guild_id) { if (payload.guild_id) {
@@ -61,12 +60,12 @@ class ClientVoiceManager {
onVoiceStateUpdate(payload) { onVoiceStateUpdate(payload) {
const { guild_id, session_id, channel_id } = payload; const { guild_id, session_id, channel_id } = payload;
const connection = this.connections.get(guild_id || channel_id); // DMs Call const connection = this.connection;
this.client.emit('debug', `[VOICE] connection? ${!!connection}, ${guild_id} ${session_id} ${channel_id}`); this.client.emit('debug', `[VOICE] connection? ${!!connection}, ${guild_id} ${session_id} ${channel_id}`);
if (!connection) return; if (!connection) return;
if (!channel_id) { if (!channel_id) {
connection._disconnect(); connection._disconnect();
this.connections.delete(guild_id || channel_id); this.connection = null;
return; return;
} }
const channel = this.client.channels.cache.get(channel_id); const channel = this.client.channels.cache.get(channel_id);
@@ -95,21 +94,22 @@ class ClientVoiceManager {
/** /**
* Sets up a request to join a voice channel. * Sets up a request to join a voice channel.
* @param {VoiceChannel | StageChannel | DMChannel | GroupDMChannel} channel The voice channel to join * @param {VoiceChannel | StageChannel | DMChannel | GroupDMChannel | Snowflake} channel The voice channel to join
* @param {JoinChannelConfig} config Config to join voice channel * @param {JoinChannelConfig} config Config to join voice channel
* @returns {Promise<VoiceConnection>} * @returns {Promise<VoiceConnection>}
*/ */
joinChannel(channel, config = {}) { joinChannel(channel, config = {}) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
channel = this.client.channels.resolve(channel);
if (!['DM', 'GROUP_DM'].includes(channel.type) && !channel.joinable) { if (!['DM', 'GROUP_DM'].includes(channel.type) && !channel.joinable) {
throw new Error('VOICE_JOIN_CHANNEL', channel.full); throw new Error('VOICE_JOIN_CHANNEL', channel.full);
} }
let connection = this.connections.get(channel.guild?.id || channel.id); let connection = this.connection;
if (connection) { if (connection) {
if (connection.channel.id !== channel.id) { if (connection.channel.id !== channel.id) {
this.connections.get(channel.guild?.id || channel.id).updateChannel(channel); this.connection.updateChannel(channel);
} }
resolve(connection); resolve(connection);
return; return;
@@ -124,11 +124,11 @@ class ClientVoiceManager {
self_deaf: Boolean(config.selfDeaf), self_deaf: Boolean(config.selfDeaf),
self_video: Boolean(config.selfVideo), self_video: Boolean(config.selfVideo),
}); });
this.connections.set(channel.guild?.id || channel.id, connection); this.connection = connection;
} }
connection.once('failed', reason => { connection.once('failed', reason => {
this.connections.delete(channel.guild?.id || channel.id); this.connection = null;
reject(reason); reject(reason);
}); });
@@ -139,7 +139,9 @@ class ClientVoiceManager {
resolve(connection); resolve(connection);
connection.removeListener('error', reject); connection.removeListener('error', reject);
}); });
connection.once('disconnect', () => this.connections.delete(channel.guild?.id || channel.id)); connection.once('disconnect', () => {
this.connection = null;
});
}); });
}); });
} }

View File

@@ -440,8 +440,8 @@ class VoiceConnection extends EventEmitter {
this.emit('closing'); this.emit('closing');
this.emit('debug', 'disconnect() triggered'); this.emit('debug', 'disconnect() triggered');
clearTimeout(this.connectTimeout); clearTimeout(this.connectTimeout);
const conn = this.voiceManager.connections.get(this.channel.guild?.id || this.channel.id); const conn = this.voiceManager.connection;
if (conn === this) this.voiceManager.connections.delete(this.channel.guild?.id || this.channel.id); if (conn === this) this.voiceManager.connection = null;
this.sendVoiceStateUpdate({ this.sendVoiceStateUpdate({
channel_id: null, channel_id: null,
}); });

View File

@@ -18,7 +18,17 @@ const libs = {
}), }),
}; };
exports.methods = {}; function NoLib() {
throw new Error(
'Cannot play audio as no valid encryption package is installed.\n- Install sodium, libsodium-wrappers, or tweetnacl.',
);
}
exports.methods = {
open: NoLib,
close: NoLib,
random: NoLib,
};
(async () => { (async () => {
for (const libName of Object.keys(libs)) { for (const libName of Object.keys(libs)) {

4
typings/index.d.ts vendored
View File

@@ -882,10 +882,10 @@ export class ClientVoiceManager {
private constructor(client: Client); private constructor(client: Client);
public readonly client: Client; public readonly client: Client;
public adapters: Map<Snowflake, InternalDiscordGatewayAdapterLibraryMethods>; public adapters: Map<Snowflake, InternalDiscordGatewayAdapterLibraryMethods>;
public connections: Collection<Snowflake, VoiceConnection>; public connection: VoiceConnection | null;
public joinChannel( public joinChannel(
channel: VoiceChannel | StageChannel | DMChannel | GroupDMChannel, channel: VoiceBasedChannel | DMChannel | GroupDMChannel | Snowflake,
config?: JoinChannelConfig, config?: JoinChannelConfig,
): Promise<VoiceConnection>; ): Promise<VoiceConnection>;
} }