From d176c60b1de457133252d386008340b01b21a028 Mon Sep 17 00:00:00 2001 From: kagchi Date: Tue, 5 Dec 2023 20:07:32 +0700 Subject: [PATCH] chore: save progress --- packages/core/package.json | 4 +- packages/core/src/Structures/BasePlayer.ts | 40 ++++++------ packages/core/src/Structures/Node.ts | 71 ++++++++-------------- packages/core/src/index.ts | 5 -- packages/core/src/typings/index.ts | 32 ++-------- packages/types/package.json | 4 +- packages/types/src/index.ts | 10 +++ packages/utilities/package.json | 4 +- packages/utilities/src/index.ts | 6 +- pnpm-lock.yaml | 14 +++-- 10 files changed, 84 insertions(+), 106 deletions(-) diff --git a/packages/core/package.json b/packages/core/package.json index 669e1d0..bbd2350 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -41,11 +41,13 @@ "@discordjs/collection": "^2.0.0", "@kirishima/fetch": "workspace:^", "@kirishima/rest": "workspace:^", + "@kirishima/types": "workspace:^", + "@kirishima/utilities": "workspace:^", "@kirishima/ws": "workspace:^", "@sapphire/async-queue": "^1.5.1", "@sapphire/utilities": "^3.14.0", "discord-api-types": "^0.37.65", - "lavalink-api-types": "^2.0.0", + "lavalink-api-types": "^2.0.1", "undici": "^5.28.2", "ws": "^8.14.2" } diff --git a/packages/core/src/Structures/BasePlayer.ts b/packages/core/src/Structures/BasePlayer.ts index 342c673..1169942 100644 --- a/packages/core/src/Structures/BasePlayer.ts +++ b/packages/core/src/Structures/BasePlayer.ts @@ -1,35 +1,38 @@ import { GatewayVoiceServerUpdateDispatch, GatewayVoiceStateUpdateDispatch } from "discord-api-types/gateway/v9"; import { Snowflake } from "discord-api-types/globals"; -import { WebsocketOpEnum } from "lavalink-api-types"; -import { KirishimaPlayerOptions, KirishimaNode, createVoiceChannelJoinPayload, Kirishima } from "../index.js"; +import { shardPayload } from "@kirishima/utilities"; +import { KirishimaNode, Kirishima } from "../index.js"; +import { PlayerOptions } from "@kirishima/types"; +import { Routes } from "lavalink-api-types/v4"; +import { GatewayVoiceServerUpdateDispatchData, GatewayVoiceState } from "discord-api-types/v10"; export class BasePlayer { - public get voiceState() { + public get voiceState(): GatewayVoiceState | undefined { return this.node.voiceStates.get(this.options.guildId); } - public get voiceServer() { + public get voiceServer(): GatewayVoiceServerUpdateDispatchData | undefined { return this.node.voiceServers.get(this.options.guildId); } - public constructor(public options: KirishimaPlayerOptions, public kirishima: Kirishima, public node: KirishimaNode) { } + public constructor(public options: PlayerOptions, public kirishima: Kirishima, public node: KirishimaNode) { } - public async connect() { - await this.kirishima.options.send(this.options, createVoiceChannelJoinPayload(this.options)); + public async connect(): Promise { + await this.kirishima.options.send(this.options, shardPayload(this.options)); return this; } - public async disconnect() { - await this.kirishima.options.send(this.options, createVoiceChannelJoinPayload(this.options, true)); + public async disconnect(): Promise { + await this.kirishima.options.send(this.options, shardPayload(this.options, true)); return this; } - public async setServerUpdate(packet: GatewayVoiceServerUpdateDispatch) { + public async setServerUpdate(packet: GatewayVoiceServerUpdateDispatch): Promise { this.node.voiceServers.set(packet.d.guild_id, packet.d); return this.sendVoiceUpdate(packet.d.guild_id); } - public async setStateUpdate(packet: GatewayVoiceStateUpdateDispatch) { + public async setStateUpdate(packet: GatewayVoiceStateUpdateDispatch): Promise { if (packet.d.user_id !== this.kirishima.options.clientId) return; if (packet.d.channel_id && packet.d.guild_id) { @@ -44,16 +47,17 @@ export class BasePlayer { } } - public async sendVoiceUpdate(guildId: Snowflake) { + public async sendVoiceUpdate(guildId: Snowflake): Promise { const voiceState = this.node.voiceStates.get(guildId); const event = this.node.voiceServers.get(guildId); - if (event && voiceState) { - await this.node.ws.send({ - op: WebsocketOpEnum.VOICE_UPDATE, - guildId, - sessionId: voiceState.session_id, - event + if (event && voiceState && this.node.sessionId) { + await this.node.rest.patch(Routes.player(this.node.sessionId, guildId), { + body: JSON.stringify({ + token: event.token, + endpoint: event.endpoint, + sessionId: voiceState.session_id + }) }); } } diff --git a/packages/core/src/Structures/Node.ts b/packages/core/src/Structures/Node.ts index 621b3fd..e5d4b1b 100644 --- a/packages/core/src/Structures/Node.ts +++ b/packages/core/src/Structures/Node.ts @@ -1,32 +1,34 @@ +/* eslint-disable @typescript-eslint/no-unnecessary-condition */ import { WebSocket } from "ws"; import { Gateway } from "@kirishima/ws"; import { REST } from "@kirishima/rest"; import { KirishimaNodeOptions } from "../typings/index.js"; import { Kirishima } from "./Kirishima.js"; import { GatewayVoiceServerUpdateDispatch, GatewayVoiceStateUpdateDispatch } from "discord-api-types/gateway/v9"; -import { LavalinkStatsPayload, WebsocketOpEnum } from "lavalink-api-types"; -import { BasePlayer } from "./BasePlayer.js"; import { Collection } from "@discordjs/collection"; import { Snowflake } from "discord-api-types/globals"; +import { StatsPayload, WebSocketOp } from "lavalink-api-types/v4"; +import { BasePlayer } from "./BasePlayer.js"; export class KirishimaNode { public ws!: Gateway; public rest!: REST; - public stats: LavalinkStatsPayload | undefined; + public stats: StatsPayload | undefined; + public sessionId: string | null = null; public reconnect: { attempts: number; timeout?: NodeJS.Timeout } = { attempts: 0 }; public voiceServers = new Collection(); public voiceStates = new Collection(); - public constructor(public options: KirishimaNodeOptions, public kirishima: Kirishima) { } + public constructor(public options: KirishimaNodeOptions, public kirishima: Kirishima) { + this.rest = new REST(`${this.options.url.endsWith("443") || this.options.secure ? "https" : "http"}://${this.options.url}`, { + Authorization: this.options.password ??= "youshallnotpass" + }); + } - public get connected() { - if (!this.ws) return false; + public get connected(): boolean { return this.ws.connection?.readyState === WebSocket.OPEN; } public async connect(): Promise { - this.rest ??= new REST(`${this.options.url.endsWith("443") || this.options.secure ? "https" : "http"}://${this.options.url}`, { - Authorization: this.options.password ??= "youshallnotpass" - }); if (this.connected) return this; const headers = { Authorization: this.options.password ??= "youshallnotpass", @@ -34,8 +36,6 @@ export class KirishimaNode { "Client-Name": this.kirishima.options.clientName ??= "Kirishima NodeJS Lavalink Client (https://github.com/kirishima-ship/core)" }; - // @ts-expect-error If you know how to fix this, please open a PR. - if (this.kirishima.options.node?.resumeKey) headers["Resume-Key"] = this.kirishima.options.node.resumeKey; this.ws = new Gateway(`${this.options.url.endsWith("443") || this.options.secure ? "wss" : "ws"}://${this.options.url}`, headers); await this.ws.connect(); this.ws.on("open", () => this.open.bind(this)); @@ -45,24 +45,17 @@ export class KirishimaNode { return this; } - public disconnect() { + public disconnect(): void { this.ws.connection?.close(1000, "Disconnected by user"); if (this.reconnect.timeout) clearTimeout(this.reconnect.timeout); } - public open(gateway: Gateway) { + public open(gateway: Gateway): void { this.reconnect.attempts = 0; - if (this.kirishima.options.node?.resumeKey && this.kirishima.options.node.resumeTimeout) { - void this.ws.send({ - op: WebsocketOpEnum.CONFIGURE_RESUMING, - key: this.kirishima.options.node.resumeKey, - timeout: this.kirishima.options.node.resumeTimeout - }); - } this.kirishima.emit("nodeConnect", this, gateway); } - public close(gateway: Gateway, close: number) { + public close(gateway: Gateway, close: number): void { this.kirishima.emit("nodeDisconnect", this, gateway, close); if (this.kirishima.options.node && this.kirishima.options.node.reconnectOnDisconnect) { if (this.reconnect.attempts < (this.kirishima.options.node.reconnectAttempts ?? 3)) { @@ -77,41 +70,27 @@ export class KirishimaNode { } } - public error(gateway: Gateway, error: Error) { + public error(gateway: Gateway, error: Error): void { this.kirishima.emit("nodeError", this, gateway, error); } - public message(gateway: Gateway, raw: string) { + public message(gateway: Gateway, raw: Record): void { try { - const message = JSON.parse(raw); - this.kirishima.emit("nodeRaw", this, gateway, message); - if (message.op === WebsocketOpEnum.STATS) this.stats = message; + if (raw.op === WebSocketOp.Ready) { + this.sessionId = raw.sessionId as string; + } } catch (e) { this.kirishima.emit("nodeError", this, gateway, e); } } - public toJSON() { - return { - identifier: this.options.identifier, - url: this.options.url, - secure: this.options.secure, - password: this.options.password, - group: this.options.group - }; + public async handleVoiceServerUpdate(packet: GatewayVoiceServerUpdateDispatch): Promise { + const player = await this.kirishima.options.fetchPlayer!(packet.d.guild_id) as unknown as BasePlayer | undefined; + if (player) await player.setServerUpdate(packet); } - public async handleVoiceServerUpdate(packet: GatewayVoiceServerUpdateDispatch) { - const player = (await this.kirishima.options.fetchPlayer!(packet.d.guild_id)) as BasePlayer; - if (player) { - await player.setServerUpdate(packet); - } - } - - public async handleVoiceStateUpdate(packet: GatewayVoiceStateUpdateDispatch) { - const player = (await this.kirishima.options.fetchPlayer!(packet.d.guild_id!)) as BasePlayer; - if (player) { - await player.setStateUpdate(packet); - } + public async handleVoiceStateUpdate(packet: GatewayVoiceStateUpdateDispatch): Promise { + const player = await this.kirishima.options.fetchPlayer!(packet.d.guild_id!) as unknown as BasePlayer | undefined; + if (player) await player.setStateUpdate(packet); } } diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 1051933..c590fe3 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -2,14 +2,9 @@ export * from "./Structures/Node.js"; export * from "./Structures/Structure.js"; export * from "./Structures/Player.js"; export * from "./Structures/Kirishima.js"; -export * from "./Structures/PartialTrack.js"; -export * from "./Structures/Track.js"; export * from "./Structures/Filter.js"; export * from "./Structures/Plugin.js"; export * from "./Structures/BasePlayer.js"; export * from "./typings/index.js"; -export * from "./Util/createVoiceChannelJoinPayload.js"; -export * from "./Util/isPartialTrack.js"; -export * from "./Util/isTrack.js"; diff --git a/packages/core/src/typings/index.ts b/packages/core/src/typings/index.ts index 1ee6a5f..f2f4818 100644 --- a/packages/core/src/typings/index.ts +++ b/packages/core/src/typings/index.ts @@ -1,12 +1,10 @@ import { Awaitable } from "@sapphire/utilities"; -import { GatewayOpcodes } from "discord-api-types/gateway/v9"; import { KirishimaNode } from "../Structures/Node.js"; import { KirishimaPlayer } from "../Structures/Player.js"; -import { KirishimaPartialTrack } from "../Structures/PartialTrack.js"; import { KirishimaFilter } from "../Structures/Filter.js"; import { KirishimaPlugin } from "../Structures/Plugin.js"; -import { Exception, LoadTypeEnum } from "lavalink-api-types"; -import { Track } from "lavalink-api-types/v4" +import { PlayerOptions, ShardPayload } from "@kirishima/types"; +import { BasePlayer } from "src/index.js"; export interface KirishimaOptions { clientId?: string; @@ -19,35 +17,15 @@ export interface KirishimaOptions { reconnectInterval?: number; reconnectAttempts?: number; }; - send: (options: KirishimaPlayerOptions, payload: payload) => Awaitable; - /** @description customize-able spawn-player handler, allow you to set it to collection or even redis. */ + send: (options: PlayerOptions, payload: ShardPayload) => Awaitable; spawnPlayer?: SpawnPlayerOptionHook; - /** @description Used for getting global player, most likely used when `VOICE_SERVER_UPDATE` and `VOICE_SERVER_UPDATE` emits. note: you must provide same major method when customizing player handler. */ fetchPlayer?: PlayerOptionHook; plugins?: KirishimaPlugin[]; } -export type SpawnPlayerOptionHook = (guildId: string, options: KirishimaPlayerOptions, node: KirishimaNode) => Awaitable; +export type SpawnPlayerOptionHook = (guildId: string, options: PlayerOptions, node: KirishimaNode) => Awaitable; -export type PlayerOptionHook = (guildId: string) => Awaitable; -export interface payload { - op: GatewayOpcodes; - d: { - guild_id: string; - channel_id: string | null; - self_deaf: boolean; - self_mute: boolean; - }; -} - -export interface KirishimaPlayerOptions { - guildId: string; - shardId?: number; - channelId: string; - textChannelId?: string; - selfDeaf?: boolean; - selfMute?: boolean; -} +export type PlayerOptionHook = (guildId: string) => Awaitable; export interface KirishimaNodeOptions { identifier?: string; diff --git a/packages/types/package.json b/packages/types/package.json index d5010bb..de0c6fb 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -41,6 +41,8 @@ "plugin:@typescript-eslint/recommended", "@hazmi35/eslint-config/typescript" ], - "rules": {} + "rules": { + "@typescript-eslint/naming-convention": "off" + } } } \ No newline at end of file diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index 0ab2fb9..25d48f5 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -6,3 +6,13 @@ export interface PlayerOptions { selfDeaf?: boolean; selfMute?: boolean; } + +export interface ShardPayload { + op: number; + d: { + guild_id: string; + channel_id: string | null; + self_deaf: boolean; + self_mute: boolean; + }; +} diff --git a/packages/utilities/package.json b/packages/utilities/package.json index f9ced79..b5f64a9 100644 --- a/packages/utilities/package.json +++ b/packages/utilities/package.json @@ -41,7 +41,9 @@ "plugin:@typescript-eslint/recommended", "@hazmi35/eslint-config/typescript" ], - "rules": {} + "rules": { + "@typescript-eslint/naming-convention": "off" + } }, "dependencies": { "@kirishima/types": "workspace:^", diff --git a/packages/utilities/src/index.ts b/packages/utilities/src/index.ts index 0dc58ff..ec341cd 100644 --- a/packages/utilities/src/index.ts +++ b/packages/utilities/src/index.ts @@ -1,7 +1,7 @@ import { GatewayOpcodes } from "discord-api-types/v10"; -import { PlayerOptions } from "@kirishima/types"; +import { PlayerOptions, ShardPayload } from "@kirishima/types"; -export function createVoiceChannelJoinPayload(options: PlayerOptions, leave?: boolean) { +export function shardPayload(options: PlayerOptions, leave?: boolean): ShardPayload { return { op: GatewayOpcodes.VoiceStateUpdate, d: { @@ -11,4 +11,4 @@ export function createVoiceChannelJoinPayload(options: PlayerOptions, leave?: bo self_mute: options.selfMute ??= false } }; -} \ No newline at end of file +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 37a18f2..10f6b44 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -26,6 +26,12 @@ importers: '@kirishima/rest': specifier: workspace:^ version: link:../rest + '@kirishima/types': + specifier: workspace:^ + version: link:../types + '@kirishima/utilities': + specifier: workspace:^ + version: link:../utilities '@kirishima/ws': specifier: workspace:^ version: link:../ws @@ -39,8 +45,8 @@ importers: specifier: ^0.37.65 version: 0.37.65 lavalink-api-types: - specifier: ^2.0.0 - version: 2.0.0 + specifier: ^2.0.1 + version: 2.0.1 undici: specifier: ^5.28.2 version: 5.28.2 @@ -1069,8 +1075,8 @@ packages: tslib: 2.6.2 dev: false - /lavalink-api-types@2.0.0: - resolution: {integrity: sha512-+MtQ9neGPEfxHW3O3wmtPffJBOwwUN3XBDdvbWN483DQ4Ps7ipehIz+K+f5208CH4bAcFH26LBH9eBlDNT2mEA==} + /lavalink-api-types@2.0.1: + resolution: {integrity: sha512-asTRKnTKhSLOg4xknqj6kvJFKTfLuINNj8W/8V+W0d48Yd2dTwN8/4TBEYl+g/hQfky1h9vbK8Okx2CCra27Aw==} engines: {node: '>=20.0.0', npm: '>=7.0.0'} dev: false