mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-13 10:03:31 +01:00
refactor: use eslint-config-neon for packages. (#8579)
Co-authored-by: Noel <buechler.noel@outlook.com>
This commit is contained in:
@@ -1,15 +1,19 @@
|
||||
/* eslint-disable jsdoc/check-param-names */
|
||||
/* eslint-disable id-length */
|
||||
/* eslint-disable @typescript-eslint/unbound-method */
|
||||
/* eslint-disable @typescript-eslint/method-signature-style */
|
||||
import { Buffer } from 'node:buffer';
|
||||
import { EventEmitter } from 'node:events';
|
||||
import { VoiceOpcodes } from 'discord-api-types/voice/v4';
|
||||
import type { CloseEvent } from 'ws';
|
||||
import { VoiceUDPSocket } from './VoiceUDPSocket';
|
||||
import { VoiceWebSocket } from './VoiceWebSocket';
|
||||
import * as secretbox from '../util/Secretbox';
|
||||
import { noop } from '../util/util';
|
||||
import { VoiceUDPSocket } from './VoiceUDPSocket';
|
||||
import { VoiceWebSocket } from './VoiceWebSocket';
|
||||
|
||||
// The number of audio channels required by Discord
|
||||
const CHANNELS = 2;
|
||||
const TIMESTAMP_INC = (48000 / 100) * CHANNELS;
|
||||
const TIMESTAMP_INC = (48_000 / 100) * CHANNELS;
|
||||
const MAX_NONCE_SIZE = 2 ** 32 - 1;
|
||||
|
||||
export const SUPPORTED_ENCRYPTION_MODES = ['xsalsa20_poly1305_lite', 'xsalsa20_poly1305_suffix', 'xsalsa20_poly1305'];
|
||||
@@ -35,8 +39,8 @@ export enum NetworkingStatusCode {
|
||||
*/
|
||||
export interface NetworkingOpeningWsState {
|
||||
code: NetworkingStatusCode.OpeningWs;
|
||||
ws: VoiceWebSocket;
|
||||
connectionOptions: ConnectionOptions;
|
||||
ws: VoiceWebSocket;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -44,8 +48,8 @@ export interface NetworkingOpeningWsState {
|
||||
*/
|
||||
export interface NetworkingIdentifyingState {
|
||||
code: NetworkingStatusCode.Identifying;
|
||||
ws: VoiceWebSocket;
|
||||
connectionOptions: ConnectionOptions;
|
||||
ws: VoiceWebSocket;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -54,10 +58,10 @@ export interface NetworkingIdentifyingState {
|
||||
*/
|
||||
export interface NetworkingUdpHandshakingState {
|
||||
code: NetworkingStatusCode.UdpHandshaking;
|
||||
ws: VoiceWebSocket;
|
||||
udp: VoiceUDPSocket;
|
||||
connectionOptions: ConnectionOptions;
|
||||
connectionData: Pick<ConnectionData, 'ssrc'>;
|
||||
connectionOptions: ConnectionOptions;
|
||||
udp: VoiceUDPSocket;
|
||||
ws: VoiceWebSocket;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,10 +69,10 @@ export interface NetworkingUdpHandshakingState {
|
||||
*/
|
||||
export interface NetworkingSelectingProtocolState {
|
||||
code: NetworkingStatusCode.SelectingProtocol;
|
||||
ws: VoiceWebSocket;
|
||||
udp: VoiceUDPSocket;
|
||||
connectionOptions: ConnectionOptions;
|
||||
connectionData: Pick<ConnectionData, 'ssrc'>;
|
||||
connectionOptions: ConnectionOptions;
|
||||
udp: VoiceUDPSocket;
|
||||
ws: VoiceWebSocket;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,11 +81,11 @@ export interface NetworkingSelectingProtocolState {
|
||||
*/
|
||||
export interface NetworkingReadyState {
|
||||
code: NetworkingStatusCode.Ready;
|
||||
ws: VoiceWebSocket;
|
||||
udp: VoiceUDPSocket;
|
||||
connectionOptions: ConnectionOptions;
|
||||
connectionData: ConnectionData;
|
||||
connectionOptions: ConnectionOptions;
|
||||
preparedPacket?: Buffer | undefined;
|
||||
udp: VoiceUDPSocket;
|
||||
ws: VoiceWebSocket;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,11 +94,11 @@ export interface NetworkingReadyState {
|
||||
*/
|
||||
export interface NetworkingResumingState {
|
||||
code: NetworkingStatusCode.Resuming;
|
||||
ws: VoiceWebSocket;
|
||||
udp: VoiceUDPSocket;
|
||||
connectionOptions: ConnectionOptions;
|
||||
connectionData: ConnectionData;
|
||||
connectionOptions: ConnectionOptions;
|
||||
preparedPacket?: Buffer | undefined;
|
||||
udp: VoiceUDPSocket;
|
||||
ws: VoiceWebSocket;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -109,13 +113,13 @@ export interface NetworkingClosedState {
|
||||
* The various states that a networking instance can be in.
|
||||
*/
|
||||
export type NetworkingState =
|
||||
| NetworkingOpeningWsState
|
||||
| NetworkingClosedState
|
||||
| NetworkingIdentifyingState
|
||||
| NetworkingUdpHandshakingState
|
||||
| NetworkingSelectingProtocolState
|
||||
| NetworkingOpeningWsState
|
||||
| NetworkingReadyState
|
||||
| NetworkingResumingState
|
||||
| NetworkingClosedState;
|
||||
| NetworkingSelectingProtocolState
|
||||
| NetworkingUdpHandshakingState;
|
||||
|
||||
/**
|
||||
* Details required to connect to the Discord voice gateway. These details
|
||||
@@ -123,11 +127,11 @@ export type NetworkingState =
|
||||
* and VOICE_STATE_UPDATE packets.
|
||||
*/
|
||||
interface ConnectionOptions {
|
||||
endpoint: string;
|
||||
serverId: string;
|
||||
userId: string;
|
||||
sessionId: string;
|
||||
token: string;
|
||||
endpoint: string;
|
||||
userId: string;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -135,15 +139,15 @@ interface ConnectionOptions {
|
||||
* the connection, timing information for playback of streams.
|
||||
*/
|
||||
export interface ConnectionData {
|
||||
ssrc: number;
|
||||
encryptionMode: string;
|
||||
secretKey: Uint8Array;
|
||||
sequence: number;
|
||||
timestamp: number;
|
||||
packetsPlayed: number;
|
||||
nonce: number;
|
||||
nonceBuffer: Buffer;
|
||||
packetsPlayed: number;
|
||||
secretKey: Uint8Array;
|
||||
sequence: number;
|
||||
speaking: boolean;
|
||||
ssrc: number;
|
||||
timestamp: number;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -186,16 +190,17 @@ function chooseEncryptionMode(options: string[]): string {
|
||||
if (!option) {
|
||||
throw new Error(`No compatible encryption modes. Available include: ${options.join(', ')}`);
|
||||
}
|
||||
|
||||
return option;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a random number that is in the range of n bits.
|
||||
*
|
||||
* @param n - The number of bits
|
||||
* @param numberOfBits - The number of bits
|
||||
*/
|
||||
function randomNBit(n: number) {
|
||||
return Math.floor(Math.random() * 2 ** n);
|
||||
function randomNBit(numberOfBits: number) {
|
||||
return Math.floor(Math.random() * 2 ** numberOfBits);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -207,7 +212,7 @@ export class Networking extends EventEmitter {
|
||||
/**
|
||||
* The debug logger function, if debugging is enabled.
|
||||
*/
|
||||
private readonly debug: null | ((message: string) => void);
|
||||
private readonly debug: ((message: string) => void) | null;
|
||||
|
||||
/**
|
||||
* Creates a new Networking instance.
|
||||
@@ -287,7 +292,6 @@ export class Networking extends EventEmitter {
|
||||
* Creates a new WebSocket to a Discord Voice gateway.
|
||||
*
|
||||
* @param endpoint - The endpoint to connect to
|
||||
* @param debug - Whether to enable debug logging
|
||||
*/
|
||||
private createWebSocket(endpoint: string) {
|
||||
const ws = new VoiceWebSocket(`wss://${endpoint}?v=4`, Boolean(this.debug));
|
||||
@@ -351,7 +355,7 @@ export class Networking extends EventEmitter {
|
||||
* @param code - The close code
|
||||
*/
|
||||
private onWsClose({ code }: CloseEvent) {
|
||||
const canResume = code === 4015 || code < 4000;
|
||||
const canResume = code === 4_015 || code < 4_000;
|
||||
if (canResume && this.state.code === NetworkingStatusCode.Ready) {
|
||||
this.state = {
|
||||
...this.state,
|
||||
@@ -400,6 +404,7 @@ export class Networking extends EventEmitter {
|
||||
udp
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
||||
.performIPDiscovery(ssrc)
|
||||
// eslint-disable-next-line promise/prefer-await-to-then
|
||||
.then((localConfig) => {
|
||||
if (this.state.code !== NetworkingStatusCode.UdpHandshaking) return;
|
||||
this.state.ws.sendPacket({
|
||||
@@ -419,6 +424,7 @@ export class Networking extends EventEmitter {
|
||||
code: NetworkingStatusCode.SelectingProtocol,
|
||||
};
|
||||
})
|
||||
// eslint-disable-next-line promise/prefer-await-to-then, promise/prefer-await-to-callbacks
|
||||
.catch((error: Error) => this.emit('error', error));
|
||||
|
||||
this.state = {
|
||||
@@ -489,15 +495,14 @@ export class Networking extends EventEmitter {
|
||||
* @remarks
|
||||
* Calling this method while there is already a prepared audio packet that has not yet been dispatched
|
||||
* will overwrite the existing audio packet. This should be avoided.
|
||||
*
|
||||
* @param opusPacket - The Opus packet to encrypt
|
||||
*
|
||||
* @returns The audio packet that was prepared
|
||||
*/
|
||||
public prepareAudioPacket(opusPacket: Buffer) {
|
||||
const state = this.state;
|
||||
if (state.code !== NetworkingStatusCode.Ready) return;
|
||||
state.preparedPacket = this.createAudioPacket(opusPacket, state.connectionData);
|
||||
// eslint-disable-next-line consistent-return
|
||||
return state.preparedPacket;
|
||||
}
|
||||
|
||||
@@ -513,6 +518,7 @@ export class Networking extends EventEmitter {
|
||||
state.preparedPacket = undefined;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -598,6 +604,7 @@ export class Networking extends EventEmitter {
|
||||
const random = secretbox.methods.random(24, connectionData.nonceBuffer);
|
||||
return [secretbox.methods.close(opusPacket, random, secretKey), random];
|
||||
}
|
||||
|
||||
return [secretbox.methods.close(opusPacket, nonce, secretKey)];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/* eslint-disable @typescript-eslint/method-signature-style */
|
||||
import { createSocket, Socket } from 'node:dgram';
|
||||
import { Buffer } from 'node:buffer';
|
||||
import { createSocket, type Socket } from 'node:dgram';
|
||||
import { EventEmitter } from 'node:events';
|
||||
import { isIPv4 } from 'node:net';
|
||||
|
||||
@@ -13,8 +14,8 @@ export interface SocketConfig {
|
||||
}
|
||||
|
||||
interface KeepAlive {
|
||||
value: number;
|
||||
timestamp: number;
|
||||
value: number;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -25,7 +26,7 @@ interface KeepAlive {
|
||||
export function parseLocalPacket(message: Buffer): SocketConfig {
|
||||
const packet = Buffer.from(message);
|
||||
|
||||
const ip = packet.slice(8, packet.indexOf(0, 8)).toString('utf-8');
|
||||
const ip = packet.slice(8, packet.indexOf(0, 8)).toString('utf8');
|
||||
|
||||
if (!isIPv4(ip)) {
|
||||
throw new Error('Malformed IP address');
|
||||
@@ -100,7 +101,7 @@ export class VoiceUDPSocket extends EventEmitter {
|
||||
/**
|
||||
* The debug logger function, if debugging is enabled.
|
||||
*/
|
||||
private readonly debug: null | ((message: string) => void);
|
||||
private readonly debug: ((message: string) => void) | null;
|
||||
|
||||
/**
|
||||
* Creates a new VoiceUDPSocket.
|
||||
@@ -137,6 +138,7 @@ export class VoiceUDPSocket extends EventEmitter {
|
||||
// Delete all keep alives up to and including the received one
|
||||
this.keepAlives.splice(0, index);
|
||||
}
|
||||
|
||||
// Propagate the message
|
||||
this.emit('message', buffer);
|
||||
}
|
||||
@@ -169,7 +171,7 @@ export class VoiceUDPSocket extends EventEmitter {
|
||||
* @param buffer - The buffer to send
|
||||
*/
|
||||
public send(buffer: Buffer) {
|
||||
return this.socket.send(buffer, this.remote.port, this.remote.ip);
|
||||
this.socket.send(buffer, this.remote.port, this.remote.ip);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -179,6 +181,7 @@ export class VoiceUDPSocket extends EventEmitter {
|
||||
try {
|
||||
this.socket.close();
|
||||
} catch {}
|
||||
|
||||
clearInterval(this.keepAliveInterval);
|
||||
}
|
||||
|
||||
@@ -187,7 +190,7 @@ export class VoiceUDPSocket extends EventEmitter {
|
||||
*
|
||||
* @param ssrc - The SSRC received from Discord
|
||||
*/
|
||||
public performIPDiscovery(ssrc: number): Promise<SocketConfig> {
|
||||
public async performIPDiscovery(ssrc: number): Promise<SocketConfig> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const listener = (message: Buffer) => {
|
||||
try {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* eslint-disable @typescript-eslint/method-signature-style */
|
||||
import { EventEmitter } from 'node:events';
|
||||
import { VoiceOpcodes } from 'discord-api-types/voice/v4';
|
||||
import WebSocket, { MessageEvent } from 'ws';
|
||||
import WebSocket, { type MessageEvent } from 'ws';
|
||||
|
||||
export interface VoiceWebSocket extends EventEmitter {
|
||||
on(event: 'error', listener: (error: Error) => void): this;
|
||||
@@ -56,7 +56,7 @@ export class VoiceWebSocket extends EventEmitter {
|
||||
/**
|
||||
* The debug logger function, if debugging is enabled.
|
||||
*/
|
||||
private readonly debug: null | ((message: string) => void);
|
||||
private readonly debug: ((message: string) => void) | null;
|
||||
|
||||
/**
|
||||
* The underlying WebSocket of this wrapper.
|
||||
@@ -71,11 +71,11 @@ export class VoiceWebSocket extends EventEmitter {
|
||||
public constructor(address: string, debug: boolean) {
|
||||
super();
|
||||
this.ws = new WebSocket(address);
|
||||
this.ws.onmessage = (e) => this.onMessage(e);
|
||||
this.ws.onopen = (e) => this.emit('open', e);
|
||||
this.ws.onmessage = (err) => this.onMessage(err);
|
||||
this.ws.onopen = (err) => this.emit('open', err);
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
||||
this.ws.onerror = (e: Error | WebSocket.ErrorEvent) => this.emit('error', e instanceof Error ? e : e.error);
|
||||
this.ws.onclose = (e) => this.emit('close', e);
|
||||
this.ws.onerror = (err: Error | WebSocket.ErrorEvent) => this.emit('error', err instanceof Error ? err : err.error);
|
||||
this.ws.onclose = (err) => this.emit('close', err);
|
||||
|
||||
this.lastHeartbeatAck = 0;
|
||||
this.lastHeartbeatSend = 0;
|
||||
@@ -90,10 +90,10 @@ export class VoiceWebSocket extends EventEmitter {
|
||||
try {
|
||||
this.debug?.('destroyed');
|
||||
this.setHeartbeatInterval(-1);
|
||||
this.ws.close(1000);
|
||||
this.ws.close(1_000);
|
||||
} catch (error) {
|
||||
const e = error as Error;
|
||||
this.emit('error', e);
|
||||
const err = error as Error;
|
||||
this.emit('error', err);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,8 +113,8 @@ export class VoiceWebSocket extends EventEmitter {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||
packet = JSON.parse(event.data);
|
||||
} catch (error) {
|
||||
const e = error as Error;
|
||||
this.emit('error', e);
|
||||
const err = error as Error;
|
||||
this.emit('error', err);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -137,10 +137,11 @@ export class VoiceWebSocket extends EventEmitter {
|
||||
try {
|
||||
const stringified = JSON.stringify(packet);
|
||||
this.debug?.(`>> ${stringified}`);
|
||||
return this.ws.send(stringified);
|
||||
this.ws.send(stringified);
|
||||
return;
|
||||
} catch (error) {
|
||||
const e = error as Error;
|
||||
this.emit('error', e);
|
||||
const err = error as Error;
|
||||
this.emit('error', err);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,8 +152,9 @@ export class VoiceWebSocket extends EventEmitter {
|
||||
this.lastHeartbeatSend = Date.now();
|
||||
this.missedHeartbeats++;
|
||||
const nonce = this.lastHeartbeatSend;
|
||||
return this.sendPacket({
|
||||
this.sendPacket({
|
||||
op: VoiceOpcodes.Heartbeat,
|
||||
// eslint-disable-next-line id-length
|
||||
d: nonce,
|
||||
});
|
||||
}
|
||||
@@ -171,6 +173,7 @@ export class VoiceWebSocket extends EventEmitter {
|
||||
this.ws.close();
|
||||
this.setHeartbeatInterval(-1);
|
||||
}
|
||||
|
||||
this.sendHeartbeat();
|
||||
}, ms);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user