mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-16 03:23:29 +01:00
chore: run format
This commit is contained in:
@@ -343,7 +343,10 @@ describe('State transitions', () => {
|
||||
// Run through a few packet cycles
|
||||
for (let index = 1; index <= 5; index++) {
|
||||
expect(player.state.status).toEqual(AudioPlayerStatus.Playing);
|
||||
if (player.state.status !== AudioPlayerStatus.Playing) throw new Error('Error');
|
||||
if (player.state.status !== AudioPlayerStatus.Playing) {
|
||||
throw new Error('Error');
|
||||
}
|
||||
|
||||
expect(player.state.playbackDuration).toStrictEqual((index - 1) * 20);
|
||||
expect(player.state.missedFrames).toEqual(index - 1);
|
||||
player['_stepDispatch']();
|
||||
|
||||
@@ -79,7 +79,9 @@ describe('demuxProbe', () => {
|
||||
test('Detects WebM', async () => {
|
||||
const stream = Readable.from(gen(10), { objectMode: false });
|
||||
webmWrite.mockImplementation(function mock(data: Buffer) {
|
||||
if (data[0] === 5) this.emit('head', validHead);
|
||||
if (data[0] === 5) {
|
||||
this.emit('head', validHead);
|
||||
}
|
||||
} as any);
|
||||
const probe = await demuxProbe(stream);
|
||||
expect(probe.type).toEqual(StreamType.WebmOpus);
|
||||
@@ -89,7 +91,9 @@ describe('demuxProbe', () => {
|
||||
test('Detects Ogg', async () => {
|
||||
const stream = Readable.from(gen(10), { objectMode: false });
|
||||
oggWrite.mockImplementation(function mock(data: Buffer) {
|
||||
if (data[0] === 5) this.emit('head', validHead);
|
||||
if (data[0] === 5) {
|
||||
this.emit('head', validHead);
|
||||
}
|
||||
} as any);
|
||||
const probe = await demuxProbe(stream);
|
||||
expect(probe.type).toEqual(StreamType.OggOpus);
|
||||
@@ -99,7 +103,9 @@ describe('demuxProbe', () => {
|
||||
test('Rejects invalid OpusHead', async () => {
|
||||
const stream = Readable.from(gen(10), { objectMode: false });
|
||||
oggWrite.mockImplementation(function mock(data: Buffer) {
|
||||
if (data[0] === 5) this.emit('head', invalidHead);
|
||||
if (data[0] === 5) {
|
||||
this.emit('head', invalidHead);
|
||||
}
|
||||
} as any);
|
||||
const probe = await demuxProbe(stream);
|
||||
expect(probe.type).toEqual(StreamType.Arbitrary);
|
||||
|
||||
@@ -35,7 +35,10 @@ groups.set('default', new Map());
|
||||
|
||||
function getOrCreateGroup(group: string) {
|
||||
const existing = groups.get(group);
|
||||
if (existing) return existing;
|
||||
if (existing) {
|
||||
return existing;
|
||||
}
|
||||
|
||||
const map = new Map<string, VoiceConnection>();
|
||||
groups.set(group, map);
|
||||
return map;
|
||||
@@ -114,7 +117,9 @@ const audioPlayers: AudioPlayer[] = [];
|
||||
* the next audio frame.
|
||||
*/
|
||||
function audioCycleStep() {
|
||||
if (nextTime === -1) return;
|
||||
if (nextTime === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
nextTime += FRAME_LENGTH;
|
||||
const available = audioPlayers.filter((player) => player.checkPlayable());
|
||||
@@ -165,7 +170,10 @@ export function hasAudioPlayer(target: AudioPlayer) {
|
||||
* @param player - The player to track
|
||||
*/
|
||||
export function addAudioPlayer(player: AudioPlayer) {
|
||||
if (hasAudioPlayer(player)) return player;
|
||||
if (hasAudioPlayer(player)) {
|
||||
return player;
|
||||
}
|
||||
|
||||
audioPlayers.push(player);
|
||||
if (audioPlayers.length === 1) {
|
||||
nextTime = Date.now();
|
||||
@@ -180,10 +188,15 @@ export function addAudioPlayer(player: AudioPlayer) {
|
||||
*/
|
||||
export function deleteAudioPlayer(player: AudioPlayer) {
|
||||
const index = audioPlayers.indexOf(player);
|
||||
if (index === -1) return;
|
||||
if (index === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
audioPlayers.splice(index, 1);
|
||||
if (audioPlayers.length === 0) {
|
||||
nextTime = -1;
|
||||
if (audioCycleInterval !== undefined) clearTimeout(audioCycleInterval);
|
||||
if (audioCycleInterval !== undefined) {
|
||||
clearTimeout(audioCycleInterval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -312,14 +312,18 @@ export class VoiceConnection extends EventEmitter {
|
||||
oldNetworking.destroy();
|
||||
}
|
||||
|
||||
if (newNetworking) this.updateReceiveBindings(newNetworking.state, oldNetworking?.state);
|
||||
if (newNetworking) {
|
||||
this.updateReceiveBindings(newNetworking.state, oldNetworking?.state);
|
||||
}
|
||||
}
|
||||
|
||||
if (newState.status === VoiceConnectionStatus.Ready) {
|
||||
this.rejoinAttempts = 0;
|
||||
} else if (newState.status === VoiceConnectionStatus.Destroyed) {
|
||||
for (const stream of this.receiver.subscriptions.values()) {
|
||||
if (!stream.destroyed) stream.destroy();
|
||||
if (!stream.destroyed) {
|
||||
stream.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -368,9 +372,17 @@ export class VoiceConnection extends EventEmitter {
|
||||
private addStatePacket(packet: GatewayVoiceStateUpdateDispatchData) {
|
||||
this.packets.state = packet;
|
||||
|
||||
if (packet.self_deaf !== undefined) this.joinConfig.selfDeaf = packet.self_deaf;
|
||||
if (packet.self_mute !== undefined) this.joinConfig.selfMute = packet.self_mute;
|
||||
if (packet.channel_id) this.joinConfig.channelId = packet.channel_id;
|
||||
if (packet.self_deaf !== undefined) {
|
||||
this.joinConfig.selfDeaf = packet.self_deaf;
|
||||
}
|
||||
|
||||
if (packet.self_mute !== undefined) {
|
||||
this.joinConfig.selfMute = packet.self_mute;
|
||||
}
|
||||
|
||||
if (packet.channel_id) {
|
||||
this.joinConfig.channelId = packet.channel_id;
|
||||
}
|
||||
/*
|
||||
the channel_id being null doesn't necessarily mean it was intended for the client to leave the voice channel
|
||||
as it may have disconnected due to network failure. This will be gracefully handled once the voice websocket
|
||||
@@ -417,7 +429,9 @@ export class VoiceConnection extends EventEmitter {
|
||||
*/
|
||||
public configureNetworking() {
|
||||
const { server, state } = this.packets;
|
||||
if (!server || !state || this.state.status === VoiceConnectionStatus.Destroyed || !server.endpoint) return;
|
||||
if (!server || !state || this.state.status === VoiceConnectionStatus.Destroyed || !server.endpoint) {
|
||||
return;
|
||||
}
|
||||
|
||||
const networking = new Networking(
|
||||
{
|
||||
@@ -460,7 +474,10 @@ export class VoiceConnection extends EventEmitter {
|
||||
* @param code - The close code
|
||||
*/
|
||||
private onNetworkingClose(code: number) {
|
||||
if (this.state.status === VoiceConnectionStatus.Destroyed) return;
|
||||
if (this.state.status === VoiceConnectionStatus.Destroyed) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If networking closes, try to connect to the voice channel again.
|
||||
if (code === 4_014) {
|
||||
// Disconnected - networking is already destroyed here
|
||||
@@ -494,9 +511,13 @@ export class VoiceConnection extends EventEmitter {
|
||||
*/
|
||||
private onNetworkingStateChange(oldState: NetworkingState, newState: NetworkingState) {
|
||||
this.updateReceiveBindings(newState, oldState);
|
||||
if (oldState.code === newState.code) return;
|
||||
if (this.state.status !== VoiceConnectionStatus.Connecting && this.state.status !== VoiceConnectionStatus.Ready)
|
||||
if (oldState.code === newState.code) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.state.status !== VoiceConnectionStatus.Connecting && this.state.status !== VoiceConnectionStatus.Ready) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (newState.code === NetworkingStatusCode.Ready) {
|
||||
this.state = {
|
||||
@@ -545,7 +566,10 @@ export class VoiceConnection extends EventEmitter {
|
||||
*/
|
||||
public prepareAudioPacket(buffer: Buffer) {
|
||||
const state = this.state;
|
||||
if (state.status !== VoiceConnectionStatus.Ready) return;
|
||||
if (state.status !== VoiceConnectionStatus.Ready) {
|
||||
return;
|
||||
}
|
||||
|
||||
return state.networking.prepareAudioPacket(buffer);
|
||||
}
|
||||
|
||||
@@ -554,7 +578,10 @@ export class VoiceConnection extends EventEmitter {
|
||||
*/
|
||||
public dispatchAudio() {
|
||||
const state = this.state;
|
||||
if (state.status !== VoiceConnectionStatus.Ready) return;
|
||||
if (state.status !== VoiceConnectionStatus.Ready) {
|
||||
return;
|
||||
}
|
||||
|
||||
return state.networking.dispatchAudio();
|
||||
}
|
||||
|
||||
@@ -565,7 +592,10 @@ export class VoiceConnection extends EventEmitter {
|
||||
*/
|
||||
public playOpusPacket(buffer: Buffer) {
|
||||
const state = this.state;
|
||||
if (state.status !== VoiceConnectionStatus.Ready) return;
|
||||
if (state.status !== VoiceConnectionStatus.Ready) {
|
||||
return;
|
||||
}
|
||||
|
||||
state.networking.prepareAudioPacket(buffer);
|
||||
return state.networking.dispatchAudio();
|
||||
}
|
||||
@@ -644,7 +674,10 @@ export class VoiceConnection extends EventEmitter {
|
||||
|
||||
const notReady = this.state.status !== VoiceConnectionStatus.Ready;
|
||||
|
||||
if (notReady) this.rejoinAttempts++;
|
||||
if (notReady) {
|
||||
this.rejoinAttempts++;
|
||||
}
|
||||
|
||||
Object.assign(this.joinConfig, joinConfig);
|
||||
if (this.state.adapter.sendPayload(createJoinVoiceChannelPayload(this.joinConfig))) {
|
||||
if (notReady) {
|
||||
@@ -673,7 +706,10 @@ export class VoiceConnection extends EventEmitter {
|
||||
* @param enabled - Whether or not to show as speaking
|
||||
*/
|
||||
public setSpeaking(enabled: boolean) {
|
||||
if (this.state.status !== VoiceConnectionStatus.Ready) return false;
|
||||
if (this.state.status !== VoiceConnectionStatus.Ready) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-confusing-void-expression
|
||||
return this.state.networking.setSpeaking(enabled);
|
||||
}
|
||||
@@ -685,7 +721,9 @@ export class VoiceConnection extends EventEmitter {
|
||||
* @returns The created subscription
|
||||
*/
|
||||
public subscribe(player: AudioPlayer) {
|
||||
if (this.state.status === VoiceConnectionStatus.Destroyed) return;
|
||||
if (this.state.status === VoiceConnectionStatus.Destroyed) {
|
||||
return;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/dot-notation
|
||||
const subscription = player['subscribe'](this);
|
||||
|
||||
@@ -458,7 +458,10 @@ export class AudioPlayer extends EventEmitter {
|
||||
* @returns `true` if the player was successfully paused, otherwise `false`
|
||||
*/
|
||||
public pause(interpolateSilence = true) {
|
||||
if (this.state.status !== AudioPlayerStatus.Playing) return false;
|
||||
if (this.state.status !== AudioPlayerStatus.Playing) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.state = {
|
||||
...this.state,
|
||||
status: AudioPlayerStatus.Paused,
|
||||
@@ -473,7 +476,10 @@ export class AudioPlayer extends EventEmitter {
|
||||
* @returns `true` if the player was successfully unpaused, otherwise `false`
|
||||
*/
|
||||
public unpause() {
|
||||
if (this.state.status !== AudioPlayerStatus.Paused) return false;
|
||||
if (this.state.status !== AudioPlayerStatus.Paused) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.state = {
|
||||
...this.state,
|
||||
status: AudioPlayerStatus.Playing,
|
||||
@@ -490,7 +496,10 @@ export class AudioPlayer extends EventEmitter {
|
||||
* @returns `true` if the player will come to a stop, otherwise `false`
|
||||
*/
|
||||
public stop(force = false) {
|
||||
if (this.state.status === AudioPlayerStatus.Idle) return false;
|
||||
if (this.state.status === AudioPlayerStatus.Idle) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (force || this.state.resource.silencePaddingFrames === 0) {
|
||||
this.state = {
|
||||
status: AudioPlayerStatus.Idle,
|
||||
@@ -509,7 +518,9 @@ export class AudioPlayer extends EventEmitter {
|
||||
*/
|
||||
public checkPlayable() {
|
||||
const state = this._state;
|
||||
if (state.status === AudioPlayerStatus.Idle || state.status === AudioPlayerStatus.Buffering) return false;
|
||||
if (state.status === AudioPlayerStatus.Idle || state.status === AudioPlayerStatus.Buffering) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the stream has been destroyed or is no longer readable, then transition to the Idle state.
|
||||
if (!state.resource.readable) {
|
||||
@@ -531,7 +542,9 @@ export class AudioPlayer extends EventEmitter {
|
||||
const state = this._state;
|
||||
|
||||
// Guard against the Idle state
|
||||
if (state.status === AudioPlayerStatus.Idle || state.status === AudioPlayerStatus.Buffering) return;
|
||||
if (state.status === AudioPlayerStatus.Idle || state.status === AudioPlayerStatus.Buffering) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Dispatch any audio packets that were prepared in the previous cycle
|
||||
for (const connection of this.playable) {
|
||||
@@ -549,7 +562,9 @@ export class AudioPlayer extends EventEmitter {
|
||||
const state = this._state;
|
||||
|
||||
// Guard against the Idle state
|
||||
if (state.status === AudioPlayerStatus.Idle || state.status === AudioPlayerStatus.Buffering) return;
|
||||
if (state.status === AudioPlayerStatus.Idle || state.status === AudioPlayerStatus.Buffering) {
|
||||
return;
|
||||
}
|
||||
|
||||
// List of connections that can receive the packet
|
||||
const playable = this.playable;
|
||||
|
||||
@@ -123,10 +123,16 @@ export class AudioResource<Metadata = unknown> {
|
||||
* while there are silence padding frames left to play.
|
||||
*/
|
||||
public get readable() {
|
||||
if (this.silenceRemaining === 0) return false;
|
||||
if (this.silenceRemaining === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const real = this.playStream.readable;
|
||||
if (!real) {
|
||||
if (this.silenceRemaining === -1) this.silenceRemaining = this.silencePaddingFrames;
|
||||
if (this.silenceRemaining === -1) {
|
||||
this.silenceRemaining = this.silencePaddingFrames;
|
||||
}
|
||||
|
||||
return this.silenceRemaining !== 0;
|
||||
}
|
||||
|
||||
@@ -274,7 +280,10 @@ export function createAudioResource<Metadata>(
|
||||
const transformerPipeline = findPipeline(inputType, needsInlineVolume ? VOLUME_CONSTRAINT : NO_CONSTRAINT);
|
||||
|
||||
if (transformerPipeline.length === 0) {
|
||||
if (typeof input === 'string') throw new Error(`Invalid pipeline constructed for string resource '${input}'`);
|
||||
if (typeof input === 'string') {
|
||||
throw new TypeError(`Invalid pipeline constructed for string resource '${input}'`);
|
||||
}
|
||||
|
||||
// No adjustments required
|
||||
return new AudioResource<Metadata>(
|
||||
[],
|
||||
@@ -285,7 +294,9 @@ export function createAudioResource<Metadata>(
|
||||
}
|
||||
|
||||
const streams = transformerPipeline.map((edge) => edge.transformer(input));
|
||||
if (typeof input !== 'string') streams.unshift(input);
|
||||
if (typeof input !== 'string') {
|
||||
streams.unshift(input);
|
||||
}
|
||||
|
||||
return new AudioResource<Metadata>(
|
||||
transformerPipeline,
|
||||
|
||||
@@ -110,7 +110,10 @@ let NODES: Map<StreamType, Node> | null = null;
|
||||
*/
|
||||
export function getNode(type: StreamType) {
|
||||
const node = (NODES ??= initializeNodes()).get(type);
|
||||
if (!node) throw new Error(`Node type '${type}' does not exist!`);
|
||||
if (!node) {
|
||||
throw new Error(`Node type '${type}' does not exist!`);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -243,7 +246,10 @@ function findPath(
|
||||
|
||||
let currentBest: Step | undefined;
|
||||
for (const edge of from.edges) {
|
||||
if (currentBest && edge.cost > currentBest.cost) continue;
|
||||
if (currentBest && edge.cost > currentBest.cost) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const next = findPath(edge.to, constraints, goal, [...path, edge], depth - 1);
|
||||
const cost = edge.cost + next.cost;
|
||||
if (!currentBest || cost < currentBest.cost) {
|
||||
|
||||
@@ -135,11 +135,12 @@ export class DAVESession extends EventEmitter {
|
||||
public session: SessionMethods | undefined;
|
||||
|
||||
public constructor(protocolVersion: number, userId: string, channelId: string, options: DAVESessionOptions) {
|
||||
if (Davey === null)
|
||||
if (Davey === null) {
|
||||
throw new Error(
|
||||
`Cannot utilize the DAVE protocol as the @snazzah/davey package has not been installed.
|
||||
- Use the generateDependencyReport() function for more information.\n`,
|
||||
);
|
||||
}
|
||||
|
||||
super();
|
||||
|
||||
@@ -166,7 +167,10 @@ export class DAVESession extends EventEmitter {
|
||||
* @throws Will throw if there is not an active session or the user id provided is invalid or not in the session.
|
||||
*/
|
||||
public async getVerificationCode(userId: string): Promise<string> {
|
||||
if (!this.session) throw new Error('Session not available');
|
||||
if (!this.session) {
|
||||
throw new Error('Session not available');
|
||||
}
|
||||
|
||||
return this.session.getVerificationCode(userId);
|
||||
}
|
||||
|
||||
@@ -197,7 +201,10 @@ export class DAVESession extends EventEmitter {
|
||||
* @param externalSender - The external sender
|
||||
*/
|
||||
public setExternalSender(externalSender: Buffer) {
|
||||
if (!this.session) throw new Error('No session available');
|
||||
if (!this.session) {
|
||||
throw new Error('No session available');
|
||||
}
|
||||
|
||||
this.session.setExternalSender(externalSender);
|
||||
this.emit('debug', 'Set MLS external sender');
|
||||
}
|
||||
@@ -216,7 +223,10 @@ export class DAVESession extends EventEmitter {
|
||||
if (data.transition_id === 0) {
|
||||
this.executeTransition(data.transition_id);
|
||||
} else {
|
||||
if (data.protocol_version === 0) this.session?.setPassthroughMode(true, TRANSITION_EXPIRY_PENDING_DOWNGRADE);
|
||||
if (data.protocol_version === 0) {
|
||||
this.session?.setPassthroughMode(true, TRANSITION_EXPIRY_PENDING_DOWNGRADE);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -285,7 +295,10 @@ export class DAVESession extends EventEmitter {
|
||||
* @param transitionId - The transition id to invalidate
|
||||
*/
|
||||
public recoverFromInvalidTransition(transitionId: number) {
|
||||
if (this.reinitializing) return;
|
||||
if (this.reinitializing) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.emit('debug', `Invalidating transition ${transitionId}`);
|
||||
this.reinitializing = true;
|
||||
this.consecutiveFailures = 0;
|
||||
@@ -301,7 +314,10 @@ export class DAVESession extends EventEmitter {
|
||||
* @returns The payload to send back to the voice server, if there is one
|
||||
*/
|
||||
public processProposals(payload: Buffer, connectedClients: Set<string>): Buffer | undefined {
|
||||
if (!this.session) throw new Error('No session available');
|
||||
if (!this.session) {
|
||||
throw new Error('No session available');
|
||||
}
|
||||
|
||||
const optype = payload.readUInt8(0) as 0 | 1;
|
||||
const { commit, welcome } = this.session.processProposals(
|
||||
optype,
|
||||
@@ -309,7 +325,10 @@ export class DAVESession extends EventEmitter {
|
||||
Array.from(connectedClients),
|
||||
);
|
||||
this.emit('debug', 'MLS proposals processed');
|
||||
if (!commit) return;
|
||||
if (!commit) {
|
||||
return;
|
||||
}
|
||||
|
||||
return welcome ? Buffer.concat([commit, welcome]) : commit;
|
||||
}
|
||||
|
||||
@@ -320,7 +339,10 @@ export class DAVESession extends EventEmitter {
|
||||
* @returns The transaction id and whether it was successful
|
||||
*/
|
||||
public processCommit(payload: Buffer): TransitionResult {
|
||||
if (!this.session) throw new Error('No session available');
|
||||
if (!this.session) {
|
||||
throw new Error('No session available');
|
||||
}
|
||||
|
||||
const transitionId = payload.readUInt16BE(0);
|
||||
try {
|
||||
this.session.processCommit(payload.subarray(2));
|
||||
@@ -347,7 +369,10 @@ export class DAVESession extends EventEmitter {
|
||||
* @returns The transaction id and whether it was successful
|
||||
*/
|
||||
public processWelcome(payload: Buffer): TransitionResult {
|
||||
if (!this.session) throw new Error('No session available');
|
||||
if (!this.session) {
|
||||
throw new Error('No session available');
|
||||
}
|
||||
|
||||
const transitionId = payload.readUInt16BE(0);
|
||||
try {
|
||||
this.session.processWelcome(payload.subarray(2));
|
||||
@@ -373,7 +398,10 @@ export class DAVESession extends EventEmitter {
|
||||
* @param packet - The packet to encrypt
|
||||
*/
|
||||
public encrypt(packet: Buffer) {
|
||||
if (this.protocolVersion === 0 || !this.session?.ready || packet.equals(SILENCE_FRAME)) return packet;
|
||||
if (this.protocolVersion === 0 || !this.session?.ready || packet.equals(SILENCE_FRAME)) {
|
||||
return packet;
|
||||
}
|
||||
|
||||
return this.session.encryptOpus(packet);
|
||||
}
|
||||
|
||||
@@ -386,7 +414,10 @@ export class DAVESession extends EventEmitter {
|
||||
*/
|
||||
public decrypt(packet: Buffer, userId: string) {
|
||||
const canDecrypt = this.session?.ready && (this.protocolVersion !== 0 || this.session?.canPassthrough(userId));
|
||||
if (packet.equals(SILENCE_FRAME) || !canDecrypt || !this.session) return packet;
|
||||
if (packet.equals(SILENCE_FRAME) || !canDecrypt || !this.session) {
|
||||
return packet;
|
||||
}
|
||||
|
||||
try {
|
||||
const buffer = this.session.decrypt(userId, Davey.MediaType.AUDIO, packet);
|
||||
this.consecutiveFailures = 0;
|
||||
@@ -396,8 +427,11 @@ export class DAVESession extends EventEmitter {
|
||||
this.consecutiveFailures++;
|
||||
this.emit('debug', `Failed to decrypt a packet (${this.consecutiveFailures} consecutive fails)`);
|
||||
if (this.consecutiveFailures > this.failureTolerance) {
|
||||
if (this.lastTransitionId) this.recoverFromInvalidTransition(this.lastTransitionId);
|
||||
else throw error;
|
||||
if (this.lastTransitionId) {
|
||||
this.recoverFromInvalidTransition(this.lastTransitionId);
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
} else if (this.reinitializing) {
|
||||
this.emit('debug', 'Failed to decrypt a packet (reinitializing session)');
|
||||
|
||||
@@ -487,7 +487,10 @@ export class Networking extends EventEmitter {
|
||||
.performIPDiscovery(ssrc)
|
||||
// eslint-disable-next-line promise/prefer-await-to-then
|
||||
.then((localConfig) => {
|
||||
if (this.state.code !== NetworkingStatusCode.UdpHandshaking) return;
|
||||
if (this.state.code !== NetworkingStatusCode.UdpHandshaking) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.state.ws.sendPacket({
|
||||
op: VoiceOpcodes.SelectProtocol,
|
||||
d: {
|
||||
@@ -551,9 +554,11 @@ export class Networking extends EventEmitter {
|
||||
this.state.code === NetworkingStatusCode.Resuming)
|
||||
) {
|
||||
const { connectionData } = this.state;
|
||||
if (packet.op === VoiceOpcodes.ClientsConnect)
|
||||
for (const id of packet.d.user_ids) connectionData.connectedClients.add(id);
|
||||
else {
|
||||
if (packet.op === VoiceOpcodes.ClientsConnect) {
|
||||
for (const id of packet.d.user_ids) {
|
||||
connectionData.connectedClients.add(id);
|
||||
}
|
||||
} else {
|
||||
connectionData.connectedClients.delete(packet.d.user_id);
|
||||
}
|
||||
} else if (
|
||||
@@ -562,18 +567,24 @@ export class Networking extends EventEmitter {
|
||||
) {
|
||||
if (packet.op === VoiceOpcodes.DavePrepareTransition) {
|
||||
const sendReady = this.state.dave.prepareTransition(packet.d);
|
||||
if (sendReady)
|
||||
if (sendReady) {
|
||||
this.state.ws.sendPacket({
|
||||
op: VoiceOpcodes.DaveTransitionReady,
|
||||
d: { transition_id: packet.d.transition_id },
|
||||
});
|
||||
}
|
||||
|
||||
if (packet.d.transition_id === 0) {
|
||||
this.emit('transitioned', 0);
|
||||
}
|
||||
} else if (packet.op === VoiceOpcodes.DaveExecuteTransition) {
|
||||
const transitioned = this.state.dave.executeTransition(packet.d.transition_id);
|
||||
if (transitioned) this.emit('transitioned', packet.d.transition_id);
|
||||
} else if (packet.op === VoiceOpcodes.DavePrepareEpoch) this.state.dave.prepareEpoch(packet.d);
|
||||
if (transitioned) {
|
||||
this.emit('transitioned', packet.d.transition_id);
|
||||
}
|
||||
} else if (packet.op === VoiceOpcodes.DavePrepareEpoch) {
|
||||
this.state.dave.prepareEpoch(packet.d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -588,26 +599,32 @@ export class Networking extends EventEmitter {
|
||||
this.state.dave.setExternalSender(message.payload);
|
||||
} else if (message.op === VoiceOpcodes.DaveMlsProposals) {
|
||||
const payload = this.state.dave.processProposals(message.payload, this.state.connectionData.connectedClients);
|
||||
if (payload) this.state.ws.sendBinaryMessage(VoiceOpcodes.DaveMlsCommitWelcome, payload);
|
||||
if (payload) {
|
||||
this.state.ws.sendBinaryMessage(VoiceOpcodes.DaveMlsCommitWelcome, payload);
|
||||
}
|
||||
} else if (message.op === VoiceOpcodes.DaveMlsAnnounceCommitTransition) {
|
||||
const { transitionId, success } = this.state.dave.processCommit(message.payload);
|
||||
if (success) {
|
||||
if (transitionId === 0) this.emit('transitioned', transitionId);
|
||||
else
|
||||
if (transitionId === 0) {
|
||||
this.emit('transitioned', transitionId);
|
||||
} else {
|
||||
this.state.ws.sendPacket({
|
||||
op: VoiceOpcodes.DaveTransitionReady,
|
||||
d: { transition_id: transitionId },
|
||||
});
|
||||
}
|
||||
}
|
||||
} else if (message.op === VoiceOpcodes.DaveMlsWelcome) {
|
||||
const { transitionId, success } = this.state.dave.processWelcome(message.payload);
|
||||
if (success) {
|
||||
if (transitionId === 0) this.emit('transitioned', transitionId);
|
||||
else
|
||||
if (transitionId === 0) {
|
||||
this.emit('transitioned', transitionId);
|
||||
} else {
|
||||
this.state.ws.sendPacket({
|
||||
op: VoiceOpcodes.DaveTransitionReady,
|
||||
d: { transition_id: transitionId },
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -619,8 +636,9 @@ export class Networking extends EventEmitter {
|
||||
* @param keyPackage - The new key package
|
||||
*/
|
||||
private onDaveKeyPackage(keyPackage: Buffer) {
|
||||
if (this.state.code === NetworkingStatusCode.SelectingProtocol || this.state.code === NetworkingStatusCode.Ready)
|
||||
if (this.state.code === NetworkingStatusCode.SelectingProtocol || this.state.code === NetworkingStatusCode.Ready) {
|
||||
this.state.ws.sendBinaryMessage(VoiceOpcodes.DaveMlsKeyPackage, keyPackage);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -629,11 +647,12 @@ export class Networking extends EventEmitter {
|
||||
* @param transitionId - The transition to invalidate
|
||||
*/
|
||||
private onDaveInvalidateTransition(transitionId: number) {
|
||||
if (this.state.code === NetworkingStatusCode.SelectingProtocol || this.state.code === NetworkingStatusCode.Ready)
|
||||
if (this.state.code === NetworkingStatusCode.SelectingProtocol || this.state.code === NetworkingStatusCode.Ready) {
|
||||
this.state.ws.sendPacket({
|
||||
op: VoiceOpcodes.DaveMlsInvalidCommitWelcome,
|
||||
d: { transition_id: transitionId },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -675,7 +694,10 @@ export class Networking extends EventEmitter {
|
||||
*/
|
||||
public prepareAudioPacket(opusPacket: Buffer) {
|
||||
const state = this.state;
|
||||
if (state.code !== NetworkingStatusCode.Ready) return;
|
||||
if (state.code !== NetworkingStatusCode.Ready) {
|
||||
return;
|
||||
}
|
||||
|
||||
state.preparedPacket = this.createAudioPacket(opusPacket, state.connectionData, state.dave);
|
||||
return state.preparedPacket;
|
||||
}
|
||||
@@ -686,7 +708,10 @@ export class Networking extends EventEmitter {
|
||||
*/
|
||||
public dispatchAudio() {
|
||||
const state = this.state;
|
||||
if (state.code !== NetworkingStatusCode.Ready) return false;
|
||||
if (state.code !== NetworkingStatusCode.Ready) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (state.preparedPacket !== undefined) {
|
||||
this.playAudioPacket(state.preparedPacket);
|
||||
state.preparedPacket = undefined;
|
||||
@@ -703,13 +728,22 @@ export class Networking extends EventEmitter {
|
||||
*/
|
||||
private playAudioPacket(audioPacket: Buffer) {
|
||||
const state = this.state;
|
||||
if (state.code !== NetworkingStatusCode.Ready) return;
|
||||
if (state.code !== NetworkingStatusCode.Ready) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { connectionData } = state;
|
||||
connectionData.packetsPlayed++;
|
||||
connectionData.sequence++;
|
||||
connectionData.timestamp += TIMESTAMP_INC;
|
||||
if (connectionData.sequence >= 2 ** 16) connectionData.sequence = 0;
|
||||
if (connectionData.timestamp >= 2 ** 32) connectionData.timestamp = 0;
|
||||
if (connectionData.sequence >= 2 ** 16) {
|
||||
connectionData.sequence = 0;
|
||||
}
|
||||
|
||||
if (connectionData.timestamp >= 2 ** 32) {
|
||||
connectionData.timestamp = 0;
|
||||
}
|
||||
|
||||
this.setSpeaking(true);
|
||||
state.udp.send(audioPacket);
|
||||
}
|
||||
@@ -722,8 +756,14 @@ export class Networking extends EventEmitter {
|
||||
*/
|
||||
public setSpeaking(speaking: boolean) {
|
||||
const state = this.state;
|
||||
if (state.code !== NetworkingStatusCode.Ready) return;
|
||||
if (state.connectionData.speaking === speaking) return;
|
||||
if (state.code !== NetworkingStatusCode.Ready) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (state.connectionData.speaking === speaking) {
|
||||
return;
|
||||
}
|
||||
|
||||
state.connectionData.speaking = speaking;
|
||||
state.ws.sendPacket({
|
||||
op: VoiceOpcodes.Speaking,
|
||||
@@ -777,7 +817,10 @@ export class Networking extends EventEmitter {
|
||||
|
||||
// Both supported encryption methods want the nonce to be an incremental integer
|
||||
connectionData.nonce++;
|
||||
if (connectionData.nonce > MAX_NONCE_SIZE) connectionData.nonce = 0;
|
||||
if (connectionData.nonce > MAX_NONCE_SIZE) {
|
||||
connectionData.nonce = 0;
|
||||
}
|
||||
|
||||
connectionData.nonceBuffer.writeUInt32BE(connectionData.nonce, 0);
|
||||
|
||||
// 4 extra bytes of padding on the end of the encrypted packet
|
||||
|
||||
@@ -152,7 +152,10 @@ export class VoiceUDPSocket extends EventEmitter {
|
||||
return new Promise((resolve, reject) => {
|
||||
const listener = (message: Buffer) => {
|
||||
try {
|
||||
if (message.readUInt16BE(0) !== 2) return;
|
||||
if (message.readUInt16BE(0) !== 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
const packet = parseLocalPacket(message);
|
||||
this.socket.off('message', listener);
|
||||
resolve(packet);
|
||||
|
||||
@@ -220,7 +220,10 @@ export class VoiceWebSocket extends EventEmitter {
|
||||
* @param ms - The interval in milliseconds. If negative, the interval will be unset
|
||||
*/
|
||||
public setHeartbeatInterval(ms: number) {
|
||||
if (this.heartbeatInterval !== undefined) clearInterval(this.heartbeatInterval);
|
||||
if (this.heartbeatInterval !== undefined) {
|
||||
clearInterval(this.heartbeatInterval);
|
||||
}
|
||||
|
||||
if (ms > 0) {
|
||||
this.heartbeatInterval = setInterval(() => {
|
||||
if (this.lastHeartbeatSend !== 0 && this.missedHeartbeats >= 3) {
|
||||
|
||||
@@ -55,7 +55,10 @@ export class SSRCMap extends EventEmitter {
|
||||
};
|
||||
|
||||
this.map.set(data.audioSSRC, newValue);
|
||||
if (!existing) this.emit('create', newValue);
|
||||
if (!existing) {
|
||||
this.emit('create', newValue);
|
||||
}
|
||||
|
||||
this.emit('update', existing, newValue);
|
||||
}
|
||||
|
||||
|
||||
@@ -84,7 +84,9 @@ export class VoiceReceiver {
|
||||
|
||||
let headerSize = 12;
|
||||
const first = buffer.readUint8();
|
||||
if ((first >> 4) & 0x01) headerSize += 4;
|
||||
if ((first >> 4) & 0x01) {
|
||||
headerSize += 4;
|
||||
}
|
||||
|
||||
// The unencrypted RTP header contains 12 bytes, HEADER_EXTENSION and the extension size
|
||||
const header = buffer.subarray(0, headerSize);
|
||||
@@ -135,7 +137,9 @@ export class VoiceReceiver {
|
||||
*/
|
||||
private parsePacket(buffer: Buffer, mode: string, nonce: Buffer, secretKey: Uint8Array, userId: string) {
|
||||
let packet: Buffer = this.decrypt(buffer, mode, nonce, secretKey);
|
||||
if (!packet) throw new Error('Failed to parse packet');
|
||||
if (!packet) {
|
||||
throw new Error('Failed to parse packet');
|
||||
}
|
||||
|
||||
// Strip decrypted RTP Header Extension if present
|
||||
// The header is only indicated in the original data, so compare with buffer first
|
||||
@@ -151,7 +155,9 @@ export class VoiceReceiver {
|
||||
this.voiceConnection.state.networking.state.code === NetworkingStatusCode.Resuming)
|
||||
) {
|
||||
const daveSession = this.voiceConnection.state.networking.state.dave;
|
||||
if (daveSession) packet = daveSession.decrypt(packet, userId)!;
|
||||
if (daveSession) {
|
||||
packet = daveSession.decrypt(packet, userId)!;
|
||||
}
|
||||
}
|
||||
|
||||
return packet;
|
||||
@@ -164,16 +170,23 @@ export class VoiceReceiver {
|
||||
* @internal
|
||||
*/
|
||||
public onUdpMessage(msg: Buffer) {
|
||||
if (msg.length <= 8) return;
|
||||
if (msg.length <= 8) {
|
||||
return;
|
||||
}
|
||||
|
||||
const ssrc = msg.readUInt32BE(8);
|
||||
|
||||
const userData = this.ssrcMap.get(ssrc);
|
||||
if (!userData) return;
|
||||
if (!userData) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.speaking.onPacket(userData.userId);
|
||||
|
||||
const stream = this.subscriptions.get(userData.userId);
|
||||
if (!stream) return;
|
||||
if (!stream) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.connectionData.encryptionMode && this.connectionData.nonceBuffer && this.connectionData.secretKey) {
|
||||
try {
|
||||
@@ -184,7 +197,9 @@ export class VoiceReceiver {
|
||||
this.connectionData.secretKey,
|
||||
userData.userId,
|
||||
);
|
||||
if (packet) stream.push(packet);
|
||||
if (packet) {
|
||||
stream.push(packet);
|
||||
}
|
||||
} catch (error) {
|
||||
stream.destroy(error as Error);
|
||||
}
|
||||
@@ -199,7 +214,9 @@ export class VoiceReceiver {
|
||||
*/
|
||||
public subscribe(userId: string, options?: Partial<AudioReceiveStreamOptions>) {
|
||||
const existing = this.subscriptions.get(userId);
|
||||
if (existing) return existing;
|
||||
if (existing) {
|
||||
return existing;
|
||||
}
|
||||
|
||||
const stream = new AudioReceiveStream({
|
||||
...createDefaultAudioReceiveStreamOptions(),
|
||||
|
||||
@@ -16,11 +16,17 @@ function findPackageJSON(
|
||||
packageName: string,
|
||||
depth: number,
|
||||
): { name: string; version: string } | undefined {
|
||||
if (depth === 0) return undefined;
|
||||
if (depth === 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const attemptedPath = resolve(dir, './package.json');
|
||||
try {
|
||||
const pkg = require(attemptedPath);
|
||||
if (pkg.name !== packageName) throw new Error('package.json does not match');
|
||||
if (pkg.name !== packageName) {
|
||||
throw new Error('package.json does not match');
|
||||
}
|
||||
|
||||
return pkg;
|
||||
} catch {
|
||||
return findPackageJSON(resolve(dir, '..'), packageName, depth - 1);
|
||||
|
||||
Reference in New Issue
Block a user