From 1a68248a0ba1ff6808c8272e6c3a8d844589ec61 Mon Sep 17 00:00:00 2001 From: 0t4u <61939142+0t4u@users.noreply.github.com> Date: Sat, 10 Aug 2024 16:15:57 +0800 Subject: [PATCH] chore: lint files --- src/Constants.ts | 18 +++--- src/Shoukaku.ts | 34 +++++------ src/Utils.ts | 5 +- src/connectors/Connector.ts | 17 +++--- src/connectors/libs/DiscordJS.ts | 1 + src/connectors/libs/Eris.ts | 1 + src/connectors/libs/OceanicJS.ts | 1 + src/connectors/libs/Seyfert.ts | 11 ++-- src/connectors/libs/index.ts | 2 +- src/guild/Connection.ts | 34 +++++------ src/guild/Player.ts | 102 ++++++++++++++++--------------- src/node/Node.ts | 54 ++++++++-------- src/node/Rest.ts | 83 +++++++++++++------------ 13 files changed, 190 insertions(+), 173 deletions(-) diff --git a/src/Constants.ts b/src/Constants.ts index 53467ea2..d69dbecc 100644 --- a/src/Constants.ts +++ b/src/Constants.ts @@ -7,27 +7,27 @@ export enum State { CONNECTED, RECONNECTING, DISCONNECTING, - DISCONNECTED + DISCONNECTED, } export enum VoiceState { SESSION_READY, SESSION_ID_MISSING, SESSION_ENDPOINT_MISSING, - SESSION_FAILED_UPDATE + SESSION_FAILED_UPDATE, } export enum OpCodes { PLAYER_UPDATE = 'playerUpdate', STATS = 'stats', EVENT = 'event', - READY = 'ready' + READY = 'ready', } -export enum Versions { - REST_VERSION = 4, - WEBSOCKET_VERSION = 4 -} +export const Versions = { + REST_VERSION: 4, + WEBSOCKET_VERSION: 4, +}; export const ShoukakuDefaults: Required = { resume: false, @@ -43,7 +43,7 @@ export const ShoukakuDefaults: Required = { nodeResolver: (nodes) => [ ...nodes.values() ] .filter(node => node.state === State.CONNECTED) .sort((a, b) => a.penalties - b.penalties) - .shift() + .shift(), }; export const ShoukakuClientInfo = `${Info.name}/${Info.version} (${Info.repository.url})`; @@ -53,5 +53,5 @@ export const NodeDefaults: NodeOption = { url: '', auth: '', secure: false, - group: undefined + group: undefined, }; diff --git a/src/Shoukaku.ts b/src/Shoukaku.ts index 5b363ca5..c899a27f 100644 --- a/src/Shoukaku.ts +++ b/src/Shoukaku.ts @@ -5,13 +5,13 @@ import { Connector } from './connectors/Connector'; import { Constructor, mergeDefault } from './Utils'; import { Player } from './guild/Player'; import { Rest } from './node/Rest'; -import { Connection } from './guild/Connection.js'; +import { Connection } from './guild/Connection'; export interface Structures { /** * A custom structure that extends the Rest class */ - rest?: Constructor; + rest?: Constructor; /** * A custom structure that extends the Player class */ @@ -85,7 +85,7 @@ export interface ShoukakuOptions { /** * Node Resolver to use if you want to customize it */ - nodeResolver?: (nodes: Map, connection?: Connection) => Node|undefined; + nodeResolver?: (nodes: Map, connection?: Connection) => Node | undefined; } export interface VoiceChannelOptions { @@ -134,17 +134,17 @@ export interface ShoukakuEvents { 'raw': [name: string, json: unknown]; } -export declare interface Shoukaku { +export declare interface IShoukaku { on(event: K, listener: (...args: ShoukakuEvents[K]) => void): this; once(event: K, listener: (...args: ShoukakuEvents[K]) => void): this; off(event: K, listener: (...args: ShoukakuEvents[K]) => void): this; - emit(event: string | symbol, ...args: any[]): boolean; + emit(event: string | symbol, ...args: unknown[]): boolean; } /** * Main Shoukaku class */ -export class Shoukaku extends EventEmitter { +export class Shoukaku extends EventEmitter implements IShoukaku { /** * Discord library connector */ @@ -168,7 +168,7 @@ export class Shoukaku extends EventEmitter { /** * Shoukaku instance identifier */ - public id: string|null; + public id: string | null; /** * @param connector A Discord library connector * @param nodes An array that conforms to the NodeOption type that specifies nodes to connect to @@ -187,7 +187,7 @@ export class Shoukaku extends EventEmitter { constructor(connector: Connector, nodes: NodeOption[], options: ShoukakuOptions = {}) { super(); this.connector = connector.set(this); - this.options = mergeDefault(ShoukakuDefaults, options); + this.options = mergeDefault(ShoukakuDefaults, options); this.nodes = new Map(); this.connections = new Map(); this.players = new Map(); @@ -214,13 +214,13 @@ export class Shoukaku extends EventEmitter { */ public addNode(options: NodeOption): void { const node = new Node(this, options); - node.on('debug', (...args) => this.emit('debug', node.name, ...args)); - node.on('reconnecting', (...args) => this.emit('reconnecting', node.name, ...args)); - node.on('error', (...args) => this.emit('error', node.name, ...args)); - node.on('close', (...args) => this.emit('close', node.name, ...args)); - node.on('ready', (...args) => this.emit('ready', node.name, ...args)); - node.on('raw', (...args) => this.emit('raw', node.name, ...args)); - node.once('disconnect', (...args) => this.clean(node, ...args)); + node.on('debug', (...args: unknown[]) => this.emit('debug', node.name, ...args)); + node.on('reconnecting', (...args: unknown[]) => this.emit('reconnecting', node.name, ...args)); + node.on('error', (...args: unknown[]) => this.emit('error', node.name, ...args)); + node.on('close', (...args: unknown[]) => this.emit('close', node.name, ...args)); + node.on('ready', (...args: unknown[]) => this.emit('ready', node.name, ...args)); + node.on('raw', (...args: unknown[]) => this.emit('raw', node.name, ...args)); + node.once('disconnect', (...args: unknown[]) => this.clean(node, ...args)); node.connect(); this.nodes.set(node.name, node); } @@ -263,7 +263,7 @@ export class Shoukaku extends EventEmitter { const player = this.options.structures.player ? new this.options.structures.player(connection.guildId, node) : new Player(connection.guildId, node); const onUpdate = (state: VoiceState) => { if (state !== VoiceState.SESSION_READY) return; - player.sendServerUpdate(connection); + void player.sendServerUpdate(connection); }; await player.sendServerUpdate(connection); connection.on('connectionUpdate', onUpdate); @@ -291,7 +291,7 @@ export class Shoukaku extends EventEmitter { if (player) { try { await player.destroy(); - } catch (_) { /* empty */ } + } catch { /* empty */ } player.clean(); this.players.delete(guildId); } diff --git a/src/Utils.ts b/src/Utils.ts index 26d31c58..989290a3 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -1,4 +1,4 @@ -export type Constructor = new (...args: any[]) => T; +export type Constructor = new (...args: unknown[]) => T; /** * Merge the default options to user input @@ -6,7 +6,8 @@ export type Constructor = new (...args: any[]) => T; * @param given User input * @returns Merged options */ -export function mergeDefault(def: T, given: T): Required { +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function mergeDefault>(def: T, given: T): Required { if (!given) return def as Required; const defaultKeys: (keyof T)[] = Object.keys(def); for (const key in given) { diff --git a/src/connectors/Connector.ts b/src/connectors/Connector.ts index f3437e08..99c22e79 100644 --- a/src/connectors/Connector.ts +++ b/src/connectors/Connector.ts @@ -1,6 +1,8 @@ +/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access */ import { NodeOption, Shoukaku } from '../Shoukaku'; import { NodeDefaults } from '../Constants'; import { mergeDefault } from '../Utils'; +import { ServerUpdate, StateUpdatePartial } from '../guild/Connection'; export interface ConnectorMethods { sendPacket: any; @@ -11,8 +13,9 @@ export const AllowedPackets = [ 'VOICE_STATE_UPDATE', 'VOICE_SERVER_UPDATE' ]; export abstract class Connector { protected readonly client: any; - protected manager: Shoukaku|null; + protected manager: Shoukaku | null; constructor(client: any) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment this.client = client; this.manager = null; } @@ -28,19 +31,19 @@ export abstract class Connector { } protected raw(packet: any): void { - if (!AllowedPackets.includes(packet.t)) return; - const guildId = packet.d.guild_id; + if (!AllowedPackets.includes(packet.t as string)) return; + const guildId = packet.d.guild_id as string; const connection = this.manager!.connections.get(guildId); if (!connection) return; - if (packet.t === 'VOICE_SERVER_UPDATE') return connection.setServerUpdate(packet.d); - const userId = packet.d.user_id; + if (packet.t === 'VOICE_SERVER_UPDATE') return connection.setServerUpdate(packet.d as ServerUpdate); + const userId = packet.d.user_id as string; if (userId !== this.manager!.id) return; - connection.setStateUpdate(packet.d); + connection.setStateUpdate(packet.d as StateUpdatePartial); } abstract getId(): string; - abstract sendPacket(shardId: number, payload: any, important: boolean): void; + abstract sendPacket(shardId: number, payload: unknown, important: boolean): void; abstract listen(nodes: NodeOption[]): void; } diff --git a/src/connectors/libs/DiscordJS.ts b/src/connectors/libs/DiscordJS.ts index 49544cd9..1ba08469 100644 --- a/src/connectors/libs/DiscordJS.ts +++ b/src/connectors/libs/DiscordJS.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-return, @typescript-eslint/no-explicit-any */ import { Connector } from '../Connector'; import { NodeOption } from '../../Shoukaku'; diff --git a/src/connectors/libs/Eris.ts b/src/connectors/libs/Eris.ts index 17e06edc..6f7fc33a 100644 --- a/src/connectors/libs/Eris.ts +++ b/src/connectors/libs/Eris.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-return, @typescript-eslint/no-explicit-any */ import { Connector } from '../Connector'; import { NodeOption } from '../../Shoukaku'; diff --git a/src/connectors/libs/OceanicJS.ts b/src/connectors/libs/OceanicJS.ts index 0379df5c..7d41cccb 100644 --- a/src/connectors/libs/OceanicJS.ts +++ b/src/connectors/libs/OceanicJS.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-return, @typescript-eslint/no-explicit-any */ import { Connector } from '../Connector'; import { NodeOption } from '../../Shoukaku'; diff --git a/src/connectors/libs/Seyfert.ts b/src/connectors/libs/Seyfert.ts index ddddf2ea..1499664c 100644 --- a/src/connectors/libs/Seyfert.ts +++ b/src/connectors/libs/Seyfert.ts @@ -1,9 +1,10 @@ +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-return, @typescript-eslint/no-explicit-any */ import { Connector } from '../Connector'; import { NodeOption } from '../../Shoukaku'; export class Seyfert extends Connector { // sendPacket is where your library send packets to Discord Gateway - public sendPacket(shardId: number, payload: any, important: boolean): void { + public sendPacket(shardId: number, payload: unknown, important: boolean): void { return this.client.gateway.send(shardId, payload); } // getId is a getter where the lib stores the client user (the one logged in as a bot) id @@ -13,13 +14,13 @@ export class Seyfert extends Connector { // Listen attaches the event listener to the library you are using public listen(nodes: NodeOption[]): void { this.client.events.values.RAW = { - data: { name: "raw" }, + data: { name: 'raw' }, run: (packet: any) => { // Only attach to ready event once, refer to your library for its ready event - if (packet.t === "READY") return this.ready(nodes); + if (packet.t === 'READY') return this.ready(nodes); // Attach to the raw websocket event, this event must be 1:1 on spec with dapi (most libs implement this) return this.raw(packet); - } - } + }, + }; } } \ No newline at end of file diff --git a/src/connectors/libs/index.ts b/src/connectors/libs/index.ts index 4b1bedea..1d53e9b8 100644 --- a/src/connectors/libs/index.ts +++ b/src/connectors/libs/index.ts @@ -1,4 +1,4 @@ export * from './DiscordJS'; export * from './Eris'; export * from './OceanicJS'; -export * from "./Seyfert" \ No newline at end of file +export * from './Seyfert'; \ No newline at end of file diff --git a/src/guild/Connection.ts b/src/guild/Connection.ts index 28bd4568..c5646948 100644 --- a/src/guild/Connection.ts +++ b/src/guild/Connection.ts @@ -1,6 +1,6 @@ import { EventEmitter, once } from 'events'; import { State, VoiceState } from '../Constants'; -import { Shoukaku, VoiceChannelOptions } from '../Shoukaku.js'; +import { Shoukaku, VoiceChannelOptions } from '../Shoukaku'; /** * Represents the partial payload from a stateUpdate event @@ -36,8 +36,7 @@ export class Connection extends EventEmitter { /** * VoiceChannelId of the connection that is being managed by this instance */ - public channelId: string|null; - + public channelId: string | null; /** * ShardId where this connection sends data on */ @@ -53,23 +52,23 @@ export class Connection extends EventEmitter { /** * Id of the voice channel where this instance was connected before the current channelId */ - public lastChannelId: string|null; + public lastChannelId: string | null; /** * Id of the currently active voice channel connection */ - public sessionId: string|null; + public sessionId: string | null; /** * Region of connected voice channel */ - public region: string|null; + public region: string | null; /** * Last region of the connected voice channel */ - public lastRegion: string|null; + public lastRegion: string | null; /** * Cached serverUpdate event from Lavalink */ - public serverUpdate: ServerUpdate|null; + public serverUpdate: ServerUpdate | null; /** * Connection state */ @@ -149,15 +148,16 @@ export class Connection extends EventEmitter { const timeout = setTimeout(() => controller.abort(), this.manager.options.voiceConnectionTimeout * 1000); try { - const [ status ] = await once(this, 'connectionUpdate', { signal: controller.signal }); + const [ status ] = await once(this, 'connectionUpdate', { signal: controller.signal }) as [ VoiceState ]; if (status !== VoiceState.SESSION_READY) { - switch(status) { + switch (status) { case VoiceState.SESSION_ID_MISSING: throw new Error('The voice connection is not established due to missing session id'); case VoiceState.SESSION_ENDPOINT_MISSING: throw new Error('The voice connection is not established due to missing connection endpoint'); } } this.state = State.CONNECTED; - } catch (error: any) { + } catch (e: unknown) { + const error = e as Error; this.debug(`[Voice] (event: K, listener: (...args: PlayerEvents[K]) => void): this; once(event: K, listener: (...args: PlayerEvents[K]) => void): this; off(event: K, listener: (...args: PlayerEvents[K]) => void): this; @@ -172,7 +172,7 @@ export declare interface Player { /** * Wrapper object around Lavalink */ -export class Player extends EventEmitter { +export class Player extends EventEmitter implements IPlayer { /** * GuildId of this player */ @@ -184,7 +184,7 @@ export class Player extends EventEmitter { /** * Base64 encoded data of the current track */ - public track: string|null; + public track: string | null; /** * Global volume of the player */ @@ -227,7 +227,7 @@ export class Player extends EventEmitter { guildId: this.guildId, playerOptions: { track: { - encoded: this.track + encoded: this.track, }, position: this.position, paused: this.paused, @@ -235,10 +235,10 @@ export class Player extends EventEmitter { voice: { token: connection.serverUpdate!.token, endpoint: connection.serverUpdate!.endpoint, - sessionId: connection.sessionId! + sessionId: connection.sessionId!, }, - volume: this.volume - } + volume: this.volume, + }, }; } @@ -249,7 +249,7 @@ export class Player extends EventEmitter { */ public async move(name?: string): Promise { const connection = this.node.manager.connections.get(this.guildId); - const node = this.node.manager.nodes.get(name!) || this.node.manager.getIdealNode(connection); + const node = this.node.manager.nodes.get(name!) ?? this.node.manager.getIdealNode(connection); if (!node && ![ ...this.node.manager.nodes.values() ].some(node => node.state === State.CONNECTED)) throw new Error('No available nodes to move to'); @@ -266,7 +266,7 @@ export class Player extends EventEmitter { this.node = node; await this.resume(); return true; - } catch (error) { + } catch { this.node = lastNode!; await this.resume(); return false; @@ -285,7 +285,7 @@ export class Player extends EventEmitter { * @param playable Options for playing this track * @param noReplace Set it to true if you don't want to replace the currently playing track */ - public playTrack(playerOptions: PlayOptions, noReplace: boolean = false): Promise { + public playTrack(playerOptions: PlayOptions, noReplace = false): Promise { return this.update(playerOptions, noReplace); } @@ -300,7 +300,7 @@ export class Player extends EventEmitter { * Pause or unpause the currently playing track * @param paused Boolean value to specify whether to pause or unpause the current bot user */ - public setPaused(paused: boolean = true): Promise { + public setPaused(paused = true): Promise { return this.update({ paused }); } @@ -324,7 +324,8 @@ export class Player extends EventEmitter { * Sets the filter volume of the player * @param volume Target volume 0.0-5.0 */ - async setFilterVolume(volume: number): Promise { + // eslint-disable-next-line require-await + async setFilterVolume(volume: number): Promise { return this.setFilters({ volume }); } @@ -332,6 +333,7 @@ export class Player extends EventEmitter { * Change the equalizer settings applied to the currently playing track * @param equalizer An array of objects that conforms to the Bands type that define volumes at different frequencies */ + // eslint-disable-next-line require-await public async setEqualizer(equalizer: Band[]): Promise { return this.setFilters({ equalizer }); } @@ -341,7 +343,7 @@ export class Player extends EventEmitter { * @param karaoke An object that conforms to the KaraokeSettings type that defines a range of frequencies to mute */ public setKaraoke(karaoke?: KaraokeSettings): Promise { - return this.setFilters({ karaoke: karaoke || null }); + return this.setFilters({ karaoke: karaoke ?? null }); } /** @@ -349,7 +351,7 @@ export class Player extends EventEmitter { * @param timescale An object that conforms to the TimescaleSettings type that defines the time signature to play the audio at */ public setTimescale(timescale?: TimescaleSettings): Promise { - return this.setFilters({ timescale: timescale || null }); + return this.setFilters({ timescale: timescale ?? null }); } /** @@ -357,7 +359,7 @@ export class Player extends EventEmitter { * @param tremolo An object that conforms to the FreqSettings type that defines an oscillation in volume */ public setTremolo(tremolo?: FreqSettings): Promise { - return this.setFilters({ tremolo: tremolo || null }); + return this.setFilters({ tremolo: tremolo ?? null }); } /** @@ -365,7 +367,7 @@ export class Player extends EventEmitter { * @param vibrato An object that conforms to the FreqSettings type that defines an oscillation in pitch */ public setVibrato(vibrato?: FreqSettings): Promise { - return this.setFilters({ vibrato: vibrato || null }); + return this.setFilters({ vibrato: vibrato ?? null }); } /** @@ -373,7 +375,7 @@ export class Player extends EventEmitter { * @param rotation An object that conforms to the RotationSettings type that defines the frequency of audio rotating round the listener */ public setRotation(rotation?: RotationSettings): Promise { - return this.setFilters({ rotation: rotation || null }); + return this.setFilters({ rotation: rotation ?? null }); } /** @@ -382,7 +384,7 @@ export class Player extends EventEmitter { * @returns The current player instance */ public setDistortion(distortion?: DistortionSettings): Promise { - return this.setFilters({ distortion: distortion || null }); + return this.setFilters({ distortion: distortion ?? null }); } /** @@ -390,7 +392,7 @@ export class Player extends EventEmitter { * @param channelMix An object that conforms to ChannelMixSettings that defines how much the left and right channels affect each other (setting all factors to 0.5 causes both channels to get the same audio) */ public setChannelMix(channelMix?: ChannelMixSettings): Promise { - return this.setFilters({ channelMix: channelMix || null }); + return this.setFilters({ channelMix: channelMix ?? null }); } /** @@ -398,7 +400,7 @@ export class Player extends EventEmitter { * @param lowPass An object that conforms to LowPassSettings that defines the amount of suppression on higher frequencies */ public setLowPass(lowPass?: LowPassSettings): Promise { - return this.setFilters({ lowPass: lowPass || null }); + return this.setFilters({ lowPass: lowPass ?? null }); } /** @@ -432,7 +434,7 @@ export class Player extends EventEmitter { * @param options An object that conforms to ResumeOptions that specify behavior on resuming * @param noReplace Set it to true if you don't want to replace the currently playing track */ - public async resume(options: ResumeOptions = {}, noReplace: boolean = false): Promise { + public async resume(options: ResumeOptions = {}, noReplace = false): Promise { const data = this.data; if (typeof options.position === 'number') @@ -454,16 +456,16 @@ export class Player extends EventEmitter { * @param playerOptions Options to update the player data * @param noReplace Set it to true if you don't want to replace the currently playing track */ - public async update(playerOptions: UpdatePlayerOptions, noReplace: boolean = false): Promise { + public async update(playerOptions: UpdatePlayerOptions, noReplace = false): Promise { const data = { guildId: this.guildId, noReplace, - playerOptions - } + playerOptions, + }; await this.node.rest.updatePlayer(data); - if (!noReplace) this.paused = false + if (!noReplace) this.paused = false; if (playerOptions.filters) { const filters = { ...this.filters, ...playerOptions.filters }; @@ -471,7 +473,7 @@ export class Player extends EventEmitter { } if (typeof playerOptions.track !== 'undefined') - this.track = playerOptions.track.encoded || null; + this.track = playerOptions.track.encoded ?? null; if (typeof playerOptions.paused === 'boolean') this.paused = playerOptions.paused; if (typeof playerOptions.volume === 'number') @@ -503,9 +505,9 @@ export class Player extends EventEmitter { voice: { token: connection.serverUpdate!.token, endpoint: connection.serverUpdate!.endpoint, - sessionId: connection.sessionId! - } - } + sessionId: connection.sessionId!, + }, + }, }; await this.node.rest.updatePlayer(playerUpdate); } @@ -525,29 +527,29 @@ export class Player extends EventEmitter { * @param json JSON data from Lavalink * @internal */ - public onPlayerEvent(json: TrackStartEvent|TrackEndEvent|TrackStuckEvent|TrackExceptionEvent|WebSocketClosedEvent): void { + public onPlayerEvent(json: TrackStartEvent | TrackEndEvent | TrackStuckEvent | TrackExceptionEvent | WebSocketClosedEvent): void { switch (json.type) { - case 'TrackStartEvent': + case PlayerEventType.TRACK_START_EVENT: if (this.track) this.track = json.track.encoded; this.emit('start', json); break; - case 'TrackEndEvent': + case PlayerEventType.TRACK_END_EVENT: this.emit('end', json); break; - case 'TrackStuckEvent': + case PlayerEventType.TRACK_STUCK_EVENT: this.emit('stuck', json); break; - case 'TrackExceptionEvent': + case PlayerEventType.TRACK_EXCEPTION_EVENT: this.emit('exception', json); break; - case 'WebSocketClosedEvent': + case PlayerEventType.WEBSOCKET_CLOSED_EVENT: this.emit('closed', json); break; default: this.node.emit( 'debug', this.node.name, - `[Player] -> [Node] : Unknown Player Event Type, Data => ${JSON.stringify(json)}` + `[Player] -> [Node] : Unknown Player Event Type, Data => ${JSON.stringify(json)}`, ); } } diff --git a/src/node/Node.ts b/src/node/Node.ts index cacec587..60ee8f36 100644 --- a/src/node/Node.ts +++ b/src/node/Node.ts @@ -21,12 +21,12 @@ export interface Stats { reservable: number; used: number; free: number; - allocated: number + allocated: number; }; frameStats: { sent: number; deficit: number; - nulled: number + nulled: number; }; cpu: { cores: number; @@ -36,7 +36,7 @@ export interface Stats { uptime: number; } -export type NodeInfoVersion = { +export interface NodeInfoVersion { semver: string; major: number; minor: number; @@ -45,18 +45,18 @@ export type NodeInfoVersion = { build?: string; } -export type NodeInfoGit = { +export interface NodeInfoGit { branch: string; commit: string; commitTime: number; } -export type NodeInfoPlugin = { +export interface NodeInfoPlugin { name: string; version: string; } -export type NodeInfo = { +export interface NodeInfo { version: NodeInfoVersion; buildTime: number; git: NodeInfoGit; @@ -76,7 +76,7 @@ export interface ResumableHeaders { 'Session-Id': string; } -export interface NonResumableHeaders extends Omit {} +export type NonResumableHeaders = Omit; /** * Represents a Lavalink node @@ -121,19 +121,19 @@ export class Node extends EventEmitter { /** * Statistics from Lavalink */ - public stats: Stats|null; + public stats: Stats | null; /** * Information about lavalink node */ - public info: NodeInfo|null; + public info: NodeInfo | null; /** * Websocket instance */ - public ws: Websocket|null; + public ws: Websocket | null; /** * SessionId of this Lavalink connection (not to be confused with Discord SessionId) */ - public sessionId: string|null; + public sessionId: string | null; /** * Boolean that represents if the node has initialized once */ @@ -154,7 +154,7 @@ export class Node extends EventEmitter { constructor(manager: Shoukaku, options: NodeOption) { super(); this.manager = manager; - this.rest = new (this.manager.options.structures.rest || Rest)(this, options); + this.rest = new (this.manager.options.structures.rest ?? Rest)(this, options); this.name = options.name; this.group = options.group; this.version = `/v${Versions.WEBSOCKET_VERSION}`; @@ -207,11 +207,11 @@ export class Node extends EventEmitter { this.state = State.CONNECTING; - const headers: NonResumableHeaders|ResumableHeaders = { + const headers: NonResumableHeaders | ResumableHeaders = { 'Client-Name': ShoukakuClientInfo, 'User-Agent': this.manager.options.userAgent, 'Authorization': this.auth, - 'User-Id': this.manager.id + 'User-Id': this.manager.id, }; if (this.sessionId) headers['Session-Id'] = this.sessionId; @@ -223,7 +223,7 @@ export class Node extends EventEmitter { this.ws.once('upgrade', response => this.open(response)); this.ws.once('close', (...args) => this.close(...args)); this.ws.on('error', error => this.error(error)); - this.ws.on('message', data => this.message(data).catch(error => this.error(error))); + this.ws.on('message', data => void this.message(data).catch(error => this.error(error))); } /** @@ -254,15 +254,16 @@ export class Node extends EventEmitter { * @internal */ private async message(message: unknown): Promise { - const json: Ready|Stats|PlayerUpdate|TrackStartEvent|TrackEndEvent|TrackStuckEvent|TrackExceptionEvent|WebSocketClosedEvent = JSON.parse(message as string); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const json: Ready | Stats | PlayerUpdate | TrackStartEvent | TrackEndEvent | TrackStuckEvent | TrackExceptionEvent | WebSocketClosedEvent = JSON.parse(message as string); if (!json) return; this.emit('raw', json); - switch(json.op) { + switch (json.op) { case OpCodes.STATS: this.emit('debug', `[Socket] <- [${this.name}] : Node Status Update | Server Load: ${this.penalties}`); this.stats = json; break; - case OpCodes.READY: + case OpCodes.READY: { if (!json.sessionId) { this.emit('debug', `[Socket] -> [${this.name}] : No session id found from ready op? disconnecting and reconnecting to avoid issues`); return this.internalDisconnect(1000); @@ -290,8 +291,9 @@ export class Node extends EventEmitter { this.emit('debug', `[Socket] -> [${this.name}] : Resuming configured!`); } break; + } case OpCodes.EVENT: - case OpCodes.PLAYER_UPDATE: + case OpCodes.PLAYER_UPDATE: { const player = this.manager.players.get(json.guildId); if (!player) return; if (json.op === OpCodes.EVENT) @@ -299,6 +301,7 @@ export class Node extends EventEmitter { else player.onPlayerUpdate(json); break; + } default: this.emit('debug', `[Player] -> [Node] : Unknown Message Op, Data => ${JSON.stringify(json)}`); } @@ -313,16 +316,17 @@ export class Node extends EventEmitter { this.emit('debug', `[Socket] <-/-> [${this.name}] : Connection Closed, Code: ${code || 'Unknown Code'}`); this.emit('close', code, reason); if (this.shouldClean) - this.clean(); + void this.clean(); else - this.reconnect(); + void this.reconnect(); } /** * To emit error events easily * @param error error message */ - public error(error: Error|unknown): void { + // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents + public error(error: Error | unknown): void { this.emit('error', error); } @@ -338,14 +342,14 @@ export class Node extends EventEmitter { if (this.ws) this.ws.close(code, reason); else - this.clean(); + void this.clean(); } /** * Destroys the websocket connection * @internal */ - private destroy(count: number = 0): void { + private destroy(count = 0): void { this.ws?.removeAllListeners(); this.ws?.close(); this.ws = null; @@ -406,7 +410,7 @@ export class Node extends EventEmitter { await Promise.allSettled([ ...playersWithData.map(player => player.resume()), - ...playersWithoutData.map(player => this.manager.leaveVoiceChannel(player.guildId)) + ...playersWithoutData.map(player => this.manager.leaveVoiceChannel(player.guildId)), ]); } diff --git a/src/node/Rest.ts b/src/node/Rest.ts index 849d4d7e..8500d5a5 100644 --- a/src/node/Rest.ts +++ b/src/node/Rest.ts @@ -10,7 +10,7 @@ export enum LoadType { PLAYLIST = 'playlist', SEARCH = 'search', EMPTY = 'empty', - ERROR = 'error' + ERROR = 'error', } export interface Track { @@ -27,7 +27,7 @@ export interface Track { artworkUrl?: string; isrc?: string; sourceName: string; - } + }; pluginInfo: unknown; } @@ -36,7 +36,7 @@ export interface Playlist { info: { name: string; selectedTrack: number; - } + }; pluginInfo: unknown; tracks: Track[]; } @@ -48,28 +48,28 @@ export interface Exception { } export interface TrackResult { - loadType: LoadType.TRACK, - data: Track + loadType: LoadType.TRACK; + data: Track; } export interface PlaylistResult { - loadType: LoadType.PLAYLIST, - data: Playlist + loadType: LoadType.PLAYLIST; + data: Playlist; } export interface SearchResult { - loadType: LoadType.SEARCH, - data: Track[] + loadType: LoadType.SEARCH; + data: Track[]; } export interface EmptyResult { - loadType: LoadType.EMPTY, - data: {} + loadType: LoadType.EMPTY; + data: Record; } export interface ErrorResult { - loadType: LoadType.ERROR, - data: Exception + loadType: LoadType.ERROR; + data: Exception; } export type LavalinkResponse = TrackResult | PlaylistResult | SearchResult | EmptyResult | ErrorResult; @@ -101,22 +101,22 @@ export interface LavalinkPlayerVoice { endpoint: string; sessionId: string; connected?: boolean; - ping?: number + ping?: number; } -export interface LavalinkPlayerVoiceOptions extends Omit {} +export type LavalinkPlayerVoiceOptions = Omit; export interface LavalinkPlayer { - guildId: string, - track?: Track, + guildId: string; + track?: Track; volume: number; paused: boolean; - voice: LavalinkPlayerVoice - filters: FilterOptions + voice: LavalinkPlayerVoice; + filters: FilterOptions; } export interface UpdatePlayerTrackOptions { - encoded?: string|null; + encoded?: string | null; identifier?: string; userData?: unknown; } @@ -208,7 +208,7 @@ export class Rest { public resolve(identifier: string): Promise { const options = { endpoint: '/loadtracks', - options: { params: { identifier }} + options: { params: { identifier }}, }; return this.fetch(options); } @@ -221,7 +221,7 @@ export class Rest { public decode(track: string): Promise { const options = { endpoint: '/decodetrack', - options: { params: { track }} + options: { params: { track }}, }; return this.fetch(options); } @@ -233,7 +233,7 @@ export class Rest { public async getPlayers(): Promise { const options = { endpoint: `/sessions/${this.sessionId}/players`, - options: {} + options: {}, }; return await this.fetch(options) ?? []; } @@ -245,7 +245,7 @@ export class Rest { public getPlayer(guildId: string): Promise { const options = { endpoint: `/sessions/${this.sessionId}/players/${guildId}`, - options: {} + options: {}, }; return this.fetch(options); } @@ -260,10 +260,10 @@ export class Rest { endpoint: `/sessions/${this.sessionId}/players/${data.guildId}`, options: { method: 'PATCH', - params: { noReplace: data.noReplace?.toString() || 'false' }, + params: { noReplace: data.noReplace?.toString() ?? 'false' }, headers: { 'Content-Type': 'application/json' }, - body: data.playerOptions as Record - } + body: data.playerOptions as Record, + }, }; return this.fetch(options); } @@ -275,7 +275,7 @@ export class Rest { public async destroyPlayer(guildId: string): Promise { const options = { endpoint: `/sessions/${this.sessionId}/players/${guildId}`, - options: { method: 'DELETE' } + options: { method: 'DELETE' }, }; await this.fetch(options); } @@ -292,8 +292,8 @@ export class Rest { options: { method: 'PATCH', headers: { 'Content-Type': 'application/json' }, - body: { resuming, timeout } - } + body: { resuming, timeout }, + }, }; return this.fetch(options); } @@ -305,7 +305,7 @@ export class Rest { public stats(): Promise { const options = { endpoint: '/stats', - options: {} + options: {}, }; return this.fetch(options); } @@ -317,7 +317,7 @@ export class Rest { public getRoutePlannerStatus(): Promise { const options = { endpoint: '/routeplanner/status', - options: {} + options: {}, }; return this.fetch(options); } @@ -332,8 +332,8 @@ export class Rest { options: { method: 'POST', headers: { 'Content-Type': 'application/json' }, - body: { address } - } + body: { address }, + }, }; await this.fetch(options); } @@ -341,12 +341,12 @@ export class Rest { /** * Get Lavalink info */ - public getLavalinkInfo(): Promise { + public getLavalinkInfo(): Promise { const options = { endpoint: '/info', options: { - headers: { 'Content-Type': 'application/json' } - } + headers: { 'Content-Type': 'application/json' }, + }, }; return this.fetch(options); } @@ -361,7 +361,7 @@ export class Rest { const { endpoint, options } = fetchOptions; let headers = { 'Authorization': this.auth, - 'User-Agent': this.node.manager.options.userAgent + 'User-Agent': this.node.manager.options.userAgent, }; if (options.headers) headers = { ...headers, ...options.headers }; @@ -373,12 +373,12 @@ export class Rest { const abortController = new AbortController(); const timeout = setTimeout(() => abortController.abort(), this.node.manager.options.restTimeout * 1000); - const method = options.method?.toUpperCase() || 'GET'; + const method = options.method?.toUpperCase() ?? 'GET'; const finalFetchOptions: FinalFetchOptions = { method, headers, - signal: abortController.signal + signal: abortController.signal, }; if (![ 'GET', 'HEAD' ].includes(method) && options.body) @@ -388,12 +388,15 @@ export class Rest { .finally(() => clearTimeout(timeout)); if (!request.ok) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment const response = await request .json() .catch(() => null); + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access if (!response?.message) throw new Error(`Rest request failed with response code: ${request.status}`); else + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access throw new Error(`Rest request failed with response code: ${request.status} | message: ${response.message}`); } try {