mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-10 00:23:30 +01:00
Clean up more voice stuff
This commit is contained in:
@@ -4,6 +4,114 @@ const Constants = require('../../util/Constants');
|
||||
const VoiceConnection = require('./VoiceConnection');
|
||||
const EventEmitter = require('events').EventEmitter;
|
||||
|
||||
/**
|
||||
* Manages all the voice stuff for the Client
|
||||
* @private
|
||||
*/
|
||||
class ClientVoiceManager {
|
||||
constructor(client) {
|
||||
/**
|
||||
* The client that instantiated this voice manager
|
||||
* @type {Client}
|
||||
*/
|
||||
this.client = client;
|
||||
|
||||
/**
|
||||
* A collection mapping connection IDs to the Connection objects
|
||||
* @type {Collection<string, VoiceConnection>}
|
||||
*/
|
||||
this.connections = new Collection();
|
||||
|
||||
/**
|
||||
* Pending connection attempts, maps Guild ID to VoiceChannel
|
||||
* @type {Collection<string, VoiceChannel>}
|
||||
*/
|
||||
this.pending = new Collection();
|
||||
|
||||
this.client.on('self.voiceServer', this.onVoiceServer.bind(this));
|
||||
this.client.on('self.voiceStateUpdate', this.onVoiceStateUpdate.bind(this));
|
||||
}
|
||||
|
||||
onVoiceServer(data) {
|
||||
if (this.pending.has(data.guild_id)) this.pending.get(data.guild_id).setTokenAndEndpoint(data.token, data.endpoint);
|
||||
}
|
||||
|
||||
onVoiceStateUpdate(data) {
|
||||
if (this.pending.has(data.guild_id)) this.pending.get(data.guild_id).setSessionID(data.session_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a request to the main gateway to join a voice channel
|
||||
* @param {VoiceChannel} channel The channel to join
|
||||
* @param {Object} [options] The options to provide
|
||||
*/
|
||||
sendVoiceStateUpdate(channel, options = {}) {
|
||||
if (!this.client.user) throw new Error('Unable to join because there is no client user.');
|
||||
|
||||
if (channel.permissionsFor) {
|
||||
const permissions = channel.permissionsFor(this.client.user);
|
||||
if (permissions) {
|
||||
if (!permissions.hasPermission('CONNECT')) {
|
||||
throw new Error('You do not have permission to connect to this voice channel.');
|
||||
}
|
||||
} else {
|
||||
throw new Error('There is no permission set for the client user in this channel - are they part of the guild?');
|
||||
}
|
||||
} else {
|
||||
throw new Error('Channel does not support permissionsFor; is it really a voice channel?');
|
||||
}
|
||||
|
||||
options = mergeDefault({
|
||||
guild_id: channel.guild.id,
|
||||
channel_id: channel.id,
|
||||
self_mute: false,
|
||||
self_deaf: false,
|
||||
}, options);
|
||||
|
||||
this.client.ws.send({
|
||||
op: Constants.OPCodes.VOICE_STATE_UPDATE,
|
||||
d: options,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up a request to join a voice channel
|
||||
* @param {VoiceChannel} channel The voice channel to join
|
||||
* @returns {Promise<VoiceConnection>}
|
||||
*/
|
||||
joinChannel(channel) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (this.pending.get(channel.guild.id)) throw new Error('Already connecting to this guild\'s voice server.');
|
||||
|
||||
const existingConnection = this.connections.get(channel.guild.id);
|
||||
if (existingConnection) {
|
||||
if (existingConnection.channel.id !== channel.id) {
|
||||
this.sendVoiceStateUpdate(channel);
|
||||
this.connections.get(channel.guild.id).channel = channel;
|
||||
}
|
||||
resolve(existingConnection);
|
||||
return;
|
||||
}
|
||||
|
||||
const pendingConnection = new PendingVoiceConnection(this, channel);
|
||||
this.pending.set(channel.guild.id, pendingConnection);
|
||||
|
||||
pendingConnection.on('fail', reason => {
|
||||
this.pending.delete(channel.guild.id);
|
||||
reject(reason);
|
||||
});
|
||||
|
||||
pendingConnection.on('pass', voiceConnection => {
|
||||
this.pending.delete(channel.guild.id);
|
||||
this.connections.set(channel.guild.id, voiceConnection);
|
||||
voiceConnection.once('ready', () => resolve(voiceConnection));
|
||||
voiceConnection.once('error', reject);
|
||||
voiceConnection.once('disconnect', () => this.connections.delete(channel.guild.id));
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a Pending Voice Connection
|
||||
* @private
|
||||
@@ -136,112 +244,4 @@ class PendingVoiceConnection extends EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Manages all the voice stuff for the Client
|
||||
* @private
|
||||
*/
|
||||
class ClientVoiceManager {
|
||||
constructor(client) {
|
||||
/**
|
||||
* The client that instantiated this voice manager
|
||||
* @type {Client}
|
||||
*/
|
||||
this.client = client;
|
||||
|
||||
/**
|
||||
* A collection mapping connection IDs to the Connection objects
|
||||
* @type {Collection<string, VoiceConnection>}
|
||||
*/
|
||||
this.connections = new Collection();
|
||||
|
||||
/**
|
||||
* Pending connection attempts, maps Guild ID to VoiceChannel
|
||||
* @type {Collection<string, VoiceChannel>}
|
||||
*/
|
||||
this.pending = new Collection();
|
||||
|
||||
this.client.on('self.voiceServer', this.onVoiceServer.bind(this));
|
||||
this.client.on('self.voiceStateUpdate', this.onVoiceStateUpdate.bind(this));
|
||||
}
|
||||
|
||||
onVoiceServer(data) {
|
||||
if (this.pending.has(data.guild_id)) this.pending.get(data.guild_id).setTokenAndEndpoint(data.token, data.endpoint);
|
||||
}
|
||||
|
||||
onVoiceStateUpdate(data) {
|
||||
if (this.pending.has(data.guild_id)) this.pending.get(data.guild_id).setSessionID(data.session_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a request to the main gateway to join a voice channel
|
||||
* @param {VoiceChannel} channel The channel to join
|
||||
* @param {Object} [options] The options to provide
|
||||
*/
|
||||
sendVoiceStateUpdate(channel, options = {}) {
|
||||
if (!this.client.user) throw new Error('Unable to join because there is no client user.');
|
||||
|
||||
if (channel.permissionsFor) {
|
||||
const permissions = channel.permissionsFor(this.client.user);
|
||||
if (permissions) {
|
||||
if (!permissions.hasPermission('CONNECT')) {
|
||||
throw new Error('You do not have permission to connect to this voice channel.');
|
||||
}
|
||||
} else {
|
||||
throw new Error('There is no permission set for the client user in this channel - are they part of the guild?');
|
||||
}
|
||||
} else {
|
||||
throw new Error('Channel does not support permissionsFor; is it really a voice channel?');
|
||||
}
|
||||
|
||||
options = mergeDefault({
|
||||
guild_id: channel.guild.id,
|
||||
channel_id: channel.id,
|
||||
self_mute: false,
|
||||
self_deaf: false,
|
||||
}, options);
|
||||
|
||||
this.client.ws.send({
|
||||
op: Constants.OPCodes.VOICE_STATE_UPDATE,
|
||||
d: options,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up a request to join a voice channel
|
||||
* @param {VoiceChannel} channel The voice channel to join
|
||||
* @returns {Promise<VoiceConnection>}
|
||||
*/
|
||||
joinChannel(channel) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (this.pending.get(channel.guild.id)) throw new Error('Already connecting to this guild\'s voice server.');
|
||||
|
||||
const existingConnection = this.connections.get(channel.guild.id);
|
||||
if (existingConnection) {
|
||||
if (existingConnection.channel.id !== channel.id) {
|
||||
this.sendVoiceStateUpdate(channel);
|
||||
this.connections.get(channel.guild.id).channel = channel;
|
||||
}
|
||||
resolve(existingConnection);
|
||||
return;
|
||||
}
|
||||
|
||||
const pendingConnection = new PendingVoiceConnection(this, channel);
|
||||
this.pending.set(channel.guild.id, pendingConnection);
|
||||
|
||||
pendingConnection.on('fail', reason => {
|
||||
this.pending.delete(channel.guild.id);
|
||||
reject(reason);
|
||||
});
|
||||
|
||||
pendingConnection.on('pass', voiceConnection => {
|
||||
this.pending.delete(channel.guild.id);
|
||||
this.connections.set(channel.guild.id, voiceConnection);
|
||||
voiceConnection.once('ready', () => resolve(voiceConnection));
|
||||
voiceConnection.once('error', reject);
|
||||
voiceConnection.once('disconnect', () => this.connections.delete(channel.guild.id));
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ClientVoiceManager;
|
||||
|
||||
@@ -61,7 +61,7 @@ class VoiceWebSocket extends EventEmitter {
|
||||
if (this.dead) return;
|
||||
if (this.ws) this.reset();
|
||||
if (this.attempts > 5) {
|
||||
this.emit('error', new Error(`too many connection attempts (${this.attempts})`));
|
||||
this.emit('error', new Error(`Too many connection attempts (${this.attempts}).`));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -85,17 +85,12 @@ class VoiceWebSocket extends EventEmitter {
|
||||
*/
|
||||
send(data) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
|
||||
this.ws.send(data, null, error => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
resolve(data);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
reject(new Error(`Voice websocket not open to send ${data}.`));
|
||||
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
|
||||
throw new Error(`Voice websocket not open to send ${data}.`);
|
||||
}
|
||||
this.ws.send(data, null, error => {
|
||||
if (error) reject(error); else resolve(data);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -126,7 +121,7 @@ class VoiceWebSocket extends EventEmitter {
|
||||
session_id: this.voiceConnection.authentication.session_id,
|
||||
},
|
||||
}).catch(() => {
|
||||
this.emit('error', new Error('tried to send join packet but WebSocket not open'));
|
||||
this.emit('error', new Error('Tried to send join packet, but the WebSocket is not open.'));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -208,7 +203,7 @@ class VoiceWebSocket extends EventEmitter {
|
||||
*/
|
||||
setHeartbeat(interval) {
|
||||
if (!interval || isNaN(interval)) {
|
||||
this.onError(new Error('tried to set voice heartbeat but no valid interval was specified'));
|
||||
this.onError(new Error('Tried to set voice heartbeat but no valid interval was specified.'));
|
||||
return;
|
||||
}
|
||||
if (this.heartbeatInterval) {
|
||||
@@ -217,7 +212,7 @@ class VoiceWebSocket extends EventEmitter {
|
||||
* @param {string} warn the warning
|
||||
* @event VoiceWebSocket#warn
|
||||
*/
|
||||
this.emit('warn', 'a voice heartbeat interval is being overwritten');
|
||||
this.emit('warn', 'A voice heartbeat interval is being overwritten');
|
||||
clearInterval(this.heartbeatInterval);
|
||||
}
|
||||
this.heartbeatInterval = this.client.setInterval(this.sendHeartbeat.bind(this), interval);
|
||||
@@ -228,7 +223,7 @@ class VoiceWebSocket extends EventEmitter {
|
||||
*/
|
||||
clearHeartbeat() {
|
||||
if (!this.heartbeatInterval) {
|
||||
this.emit('warn', 'tried to clear a heartbeat interval that does not exist');
|
||||
this.emit('warn', 'Tried to clear a heartbeat interval that does not exist');
|
||||
return;
|
||||
}
|
||||
clearInterval(this.heartbeatInterval);
|
||||
@@ -239,11 +234,10 @@ class VoiceWebSocket extends EventEmitter {
|
||||
* Sends a heartbeat packet
|
||||
*/
|
||||
sendHeartbeat() {
|
||||
this.sendPacket({ op: Constants.VoiceOPCodes.HEARTBEAT, d: null })
|
||||
.catch(() => {
|
||||
this.emit('warn', 'tried to send heartbeat, but connection is not open');
|
||||
this.clearHeartbeat();
|
||||
});
|
||||
this.sendPacket({ op: Constants.VoiceOPCodes.HEARTBEAT, d: null }).catch(() => {
|
||||
this.emit('warn', 'Tried to send heartbeat, but connection is not open');
|
||||
this.clearHeartbeat();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user