mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-09 16:13:31 +01:00
Start/Stop speaking events on UDP packets (#3578)
* Start/Stop speaking using incomming UDP packets * Fix ESLint errors * Updates for styling consistency Co-Authored-By: Gryffon Bellish <owenbellish@gmail.com> * Minor improvements * Acutally use previousTimeout * Use BaseClient setTimeout and refresh() * Update README to match node version for refresh() * Update comment to match startSpeaking * Correctly report Priority bit * Fix ESlint errors
This commit is contained in:
@@ -38,7 +38,7 @@ discord.js is a powerful [Node.js](https://nodejs.org) module that allows you to
|
||||
- 100% coverage of the Discord API
|
||||
|
||||
## Installation
|
||||
**Node.js 10.0.0 or newer is required.**
|
||||
**Node.js 10.2.0 or newer is required.**
|
||||
Ignore any warnings about unmet peer dependencies, as they're all optional.
|
||||
|
||||
Without voice support: `npm install discordjs/discord.js`
|
||||
|
||||
@@ -422,7 +422,7 @@ class VoiceConnection extends EventEmitter {
|
||||
udp.on('error', err => this.emit('error', err));
|
||||
ws.on('ready', this.onReady.bind(this));
|
||||
ws.on('sessionDescription', this.onSessionDescription.bind(this));
|
||||
ws.on('speaking', this.onSpeaking.bind(this));
|
||||
ws.on('startSpeaking', this.onStartSpeaking.bind(this));
|
||||
|
||||
this.sockets.ws.connect();
|
||||
}
|
||||
@@ -465,16 +465,19 @@ class VoiceConnection extends EventEmitter {
|
||||
});
|
||||
}
|
||||
|
||||
onStartSpeaking({ user_id, ssrc, speaking }) {
|
||||
this.ssrcMap.set(+ssrc, { userID: user_id, speaking: speaking });
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked when a speaking event is received.
|
||||
* @param {Object} data The received data
|
||||
* @private
|
||||
*/
|
||||
onSpeaking({ user_id, ssrc, speaking }) {
|
||||
onSpeaking({ user_id, speaking }) {
|
||||
speaking = new Speaking(speaking).freeze();
|
||||
const guild = this.channel.guild;
|
||||
const user = this.client.users.get(user_id);
|
||||
this.ssrcMap.set(+ssrc, user_id);
|
||||
const old = this._speaking.get(user_id);
|
||||
this._speaking.set(user_id, speaking);
|
||||
/**
|
||||
@@ -504,7 +507,7 @@ class VoiceConnection extends EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
play() {} // eslint-disable-line no-empty-function
|
||||
play() { } // eslint-disable-line no-empty-function
|
||||
}
|
||||
|
||||
PlayInterface.applyToClass(VoiceConnection);
|
||||
|
||||
@@ -201,9 +201,9 @@ class VoiceWebSocket extends EventEmitter {
|
||||
/**
|
||||
* Emitted whenever a speaking packet is received.
|
||||
* @param {Object} data
|
||||
* @event VoiceWebSocket#speaking
|
||||
* @event VoiceWebSocket#startSpeaking
|
||||
*/
|
||||
this.emit('speaking', packet.d);
|
||||
this.emit('startSpeaking', packet.d);
|
||||
break;
|
||||
default:
|
||||
/**
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
const secretbox = require('../util/Secretbox');
|
||||
const EventEmitter = require('events');
|
||||
|
||||
// The delay between packets when a user is considered to have stopped speaking
|
||||
// https://github.com/discordjs/discord.js/issues/3524#issuecomment-540373200
|
||||
const DISCORD_SPEAKING_DELAY = 250;
|
||||
|
||||
class Readable extends require('stream').Readable { _read() {} } // eslint-disable-line no-empty-function
|
||||
|
||||
class PacketHandler extends EventEmitter {
|
||||
@@ -11,6 +15,7 @@ class PacketHandler extends EventEmitter {
|
||||
this.nonce = Buffer.alloc(24);
|
||||
this.receiver = receiver;
|
||||
this.streams = new Map();
|
||||
this.speakingTimeouts = new Map();
|
||||
}
|
||||
|
||||
get connection() {
|
||||
@@ -72,13 +77,29 @@ class PacketHandler extends EventEmitter {
|
||||
return packet;
|
||||
}
|
||||
|
||||
userFromSSRC(ssrc) { return this.connection.client.users.get(this.connection.ssrcMap.get(ssrc)); }
|
||||
|
||||
push(buffer) {
|
||||
const ssrc = buffer.readUInt32BE(8);
|
||||
const user = this.userFromSSRC(ssrc);
|
||||
if (!user) return;
|
||||
let stream = this.streams.get(user.id);
|
||||
const userStat = this.connection.ssrcMap.get(ssrc);
|
||||
if (!userStat) return;
|
||||
|
||||
let speakingTimeout = this.speakingTimeouts.get(ssrc);
|
||||
if (typeof speakingTimeout === 'undefined') {
|
||||
this.connection.onSpeaking({ user_id: userStat.userID, ssrc: ssrc, speaking: userStat.speaking });
|
||||
speakingTimeout = this.receiver.connection.client.setTimeout(() => {
|
||||
try {
|
||||
this.connection.onSpeaking({ user_id: userStat.userID, ssrc: ssrc, speaking: 0 });
|
||||
this.receiver.connection.client.clearTimeout(speakingTimeout);
|
||||
this.speakingTimeouts.delete(ssrc);
|
||||
} catch (ex) {
|
||||
// Connection already closed, ignore
|
||||
}
|
||||
}, DISCORD_SPEAKING_DELAY);
|
||||
this.speakingTimeouts.set(ssrc, speakingTimeout);
|
||||
} else {
|
||||
speakingTimeout.refresh();
|
||||
}
|
||||
|
||||
let stream = this.streams.get(userStat.userID);
|
||||
if (!stream) return;
|
||||
stream = stream.stream;
|
||||
const opusPacket = this.parseBuffer(buffer);
|
||||
|
||||
Reference in New Issue
Block a user