From b847a795b0186c4b3f0d1d6287e1871ad5cace3f Mon Sep 17 00:00:00 2001 From: Joniii Date: Thu, 28 Mar 2024 12:02:38 +0100 Subject: [PATCH 1/8] Add clientName property to Node class and update connect method --- src/Node/Node.ts | 42 ++++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/src/Node/Node.ts b/src/Node/Node.ts index d3c6968c..49f2d409 100644 --- a/src/Node/Node.ts +++ b/src/Node/Node.ts @@ -84,6 +84,7 @@ export class Node { public attempt: number; public stats: NodeStats | null; public options: NodeGroup; + public clientName: string; /** * The Node class that is used to connect to a lavalink node * @param poru Poru @@ -111,29 +112,34 @@ export class Node { this.attempt = 0; this.isConnected = false; this.stats = null; - } + this.clientName = options.clientName || config.clientName; + }; /** * Connects to the lavalink node * @returns {void} */ - public connect(): void { - if (this.ws) this.ws.close(); - if (!this.poru.nodes.get(this.name)) { - this.poru.nodes.set(this.name, this) - } - const headers = { - Authorization: this.password, - "User-Id": this.poru.userId, - "Client-Name": config.clientName, - }; - if (this.resumeKey) headers["Resume-Key"] = this.resumeKey; - this.ws = new WebSocket(`${this.socketURL}`, { headers }); - this.ws.on("open", this.open.bind(this)); - this.ws.on("error", this.error.bind(this)); - this.ws.on("message", this.message.bind(this)); - this.ws.on("close", this.close.bind(this)); - } + public async connect(): Promise { + return new Promise((resolve, reject) => { + if (this.isConnected) return resolve(true); + if (this.ws) this.ws.close(); + if (!this.poru.nodes.get(this.name)) { + this.poru.nodes.set(this.name, this) + } + const headers = { + Authorization: this.password, + "User-Id": this.poru.userId, + "Client-Name": this.clientName, + }; + if (this.resumeKey) headers["Resume-Key"] = this.resumeKey; + this.ws = new WebSocket(`${this.socketURL}`, { headers }); + this.ws.on("open", this.open.bind(this)); + this.ws.on("error", this.error.bind(this)); + this.ws.on("message", this.message.bind(this)); + this.ws.on("close", this.close.bind(this)); + resolve(true); + }) + }; /** * Handles the message event From 989765f2f89fb404a81c5ac67524f8e9e62a74d1 Mon Sep 17 00:00:00 2001 From: Joniii Date: Thu, 28 Mar 2024 12:02:42 +0100 Subject: [PATCH 2/8] Add Packet types for Voice State and Voice Server Updates --- src/Poru.ts | 51 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 15 deletions(-) diff --git a/src/Poru.ts b/src/Poru.ts index 06150d4d..1bc47dc5 100644 --- a/src/Poru.ts +++ b/src/Poru.ts @@ -6,6 +6,7 @@ import { Response, LoadTrackResponse } from "./guild/Response"; import { Plugin } from "./Plugin"; import { Track, trackData } from "./guild/Track"; import { Filters } from "./Player/Filters"; +import { IVoiceServer, SetStateUpdate } from "./Player/Connection"; export type Constructor = new (...args: any[]) => T; @@ -18,6 +19,25 @@ export interface NodeGroup { region?: string[]; } +export type Packet = PacketVoiceStateUpdate | PacketVoiceServerUpdate | AnyOtherPacket; + +interface PacketVoiceStateUpdate { + op: number; + d: SetStateUpdate; + t: "VOICE_STATE_UPDATE"; +}; + +interface PacketVoiceServerUpdate { + op: number; + d: IVoiceServer; + t: "VOICE_SERVER_UPDATE"; +}; + +interface AnyOtherPacket { + op: number; + d: any; + t: string; +}; export interface ResolveOptions { query: string; @@ -102,6 +122,7 @@ export interface PoruOptions { reconnectTries?: number | null; useCustomFilters?: boolean; send?: Function | null; + clientName?: string; } export interface ConnectionOptions { @@ -264,7 +285,6 @@ export class Poru extends EventEmitter { * @param {any} client - VoiceClient used for connecting to Lavalink node server. * @param {NodeGroup[]} nodes - Array of node groups. * @param {PoruOptions} options - Configuration options for Poru. - * @returns {Poru} The Poru instance. */ constructor(client: any, nodes: NodeGroup[], options: PoruOptions) { super(); @@ -282,15 +302,14 @@ export class Poru extends EventEmitter { /** * Initializes Poru and adds nodes. */ - public init() { + public async init() { if (this.isActivated) return this; this.userId = this.client.user.id; - this._nodes.forEach((node) => this.addNode(node)); + this._nodes.forEach(async (node) => await this.addNode(node)); this.isActivated = true; if (this.options.plugins) { this.options.plugins.forEach((plugin) => { - plugin.load(this); }); } @@ -298,33 +317,33 @@ export class Poru extends EventEmitter { switch (this.options.library) { case "discord.js": { - this.send = (packet: any) => { + this.send = (packet: Packet) => { const guild = this.client.guilds.cache.get(packet.d.guild_id); if (guild) guild.shard?.send(packet); }; - this.client.on("raw", async (packet: any) => { + this.client.on("raw", async (packet: Packet) => { this.packetUpdate(packet); }); break; } case "eris": { - this.send = (packet: any) => { + this.send = (packet: Packet) => { const guild = this.client.guilds.get(packet.d.guild_id); if (guild) guild.shard.sendWS(packet?.op, packet?.d); }; - this.client.on("rawWS", async (packet: any) => { + this.client.on("rawWS", async (packet: Packet) => { this.packetUpdate(packet); }); break; } case "oceanic": { - this.send = (packet: any) => { + this.send = (packet: Packet) => { const guild = this.client.guilds.get(packet.d.guild_id); if (guild) guild.shard.send(packet?.op, packet?.d); }; - this.client.on("packet", async (packet: any) => { + this.client.on("packet", async (packet: Packet) => { this.packetUpdate(packet); }); break; @@ -337,16 +356,18 @@ export class Poru extends EventEmitter { break; } } - } + }; /** * Handles Voice State Update and Voice Server Update packets. - * @param {any} packet - Packet from Discord API. + * @param {Packet} packet - Packet from Discord API. * @returns {void} */ - public packetUpdate(packet: any): void { + public packetUpdate(packet: Packet): void { if (!["VOICE_STATE_UPDATE", "VOICE_SERVER_UPDATE"].includes(packet.t)) return; + if (!("guild_id" in packet.d)) return; + const player = this.players.get(packet.d.guild_id); if (!player) return; @@ -364,10 +385,10 @@ export class Poru extends EventEmitter { * @param {NodeGroup} options - Node group options. * @returns {Node} The added Node instance. */ - public addNode(options: NodeGroup): Node { + public async addNode(options: NodeGroup): Promise { const node = new Node(this, options, this.options); this.nodes.set(options.name, node); - node.connect(); + await node.connect(); return node; } From 67c2d49c1d202d7ad7e863e344cd527d140f92a2 Mon Sep 17 00:00:00 2001 From: Joniii Date: Thu, 28 Mar 2024 12:02:47 +0100 Subject: [PATCH 3/8] Update endpoint property to be optional in IVoiceServer interface --- src/Player/Connection.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Player/Connection.ts b/src/Player/Connection.ts index 152697cc..f6e1edeb 100644 --- a/src/Player/Connection.ts +++ b/src/Player/Connection.ts @@ -3,7 +3,7 @@ import { Player } from "./Player"; export interface IVoiceServer { token: string; sessionId: string; - endpoint: string; + endpoint?: string; }; type TYear = `${number}${number}${number}${number}`; From 25033962eab70d4f27efe6324e9746d9f19d5850 Mon Sep 17 00:00:00 2001 From: Joniii Date: Thu, 28 Mar 2024 18:18:38 +0100 Subject: [PATCH 4/8] Update clientName to include version in Node.ts --- src/Node/Node.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Node/Node.ts b/src/Node/Node.ts index 49f2d409..df6fcc77 100644 --- a/src/Node/Node.ts +++ b/src/Node/Node.ts @@ -112,7 +112,7 @@ export class Node { this.attempt = 0; this.isConnected = false; this.stats = null; - this.clientName = options.clientName || config.clientName; + this.clientName = options.clientName || `${config.clientName}/${config.version}`; }; /** From c904d1315201e3b04f94909ac168d448882cafa0 Mon Sep 17 00:00:00 2001 From: Joniii Date: Thu, 28 Mar 2024 18:18:45 +0100 Subject: [PATCH 5/8] Update version number in config.ts --- src/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config.ts b/src/config.ts index d608f216..f7f3eea5 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,4 +1,4 @@ export enum Config { - version = 4, + version = 5, clientName = "Poru" } \ No newline at end of file From 546a76a52e61d460bda854dbdf11a4a09f060392 Mon Sep 17 00:00:00 2001 From: Joniii Date: Thu, 28 Mar 2024 21:28:16 +0100 Subject: [PATCH 6/8] Refactor connect method in Node class --- src/Node/Node.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Node/Node.ts b/src/Node/Node.ts index df6fcc77..234b440d 100644 --- a/src/Node/Node.ts +++ b/src/Node/Node.ts @@ -120,7 +120,7 @@ export class Node { * @returns {void} */ public async connect(): Promise { - return new Promise((resolve, reject) => { + return new Promise((resolve) => { if (this.isConnected) return resolve(true); if (this.ws) this.ws.close(); if (!this.poru.nodes.get(this.name)) { From db9a4c07f404e102b707ef30301871bfc9c7dea9 Mon Sep 17 00:00:00 2001 From: Joniii Date: Thu, 28 Mar 2024 21:28:30 +0100 Subject: [PATCH 7/8] Refactor resolve method in Player and Poru classes to optimize it --- src/Player/Player.ts | 16 ++-------------- src/Poru.ts | 17 +++-------------- 2 files changed, 5 insertions(+), 28 deletions(-) diff --git a/src/Player/Player.ts b/src/Player/Player.ts index cc3fb179..a413c9b2 100644 --- a/src/Player/Player.ts +++ b/src/Player/Player.ts @@ -550,20 +550,8 @@ export class Player extends EventEmitter { * @returns {Promise} - A Promise that resolves to a Response object containing the resolved tracks. */ public async resolve({ query, source, requester }: ResolveOptions): Promise { - const regex = /^https?:\/\// - - if (regex.test(query)) { - const response = await this.node.rest.get( - `/v4/loadtracks?identifier=${encodeURIComponent(query)}` - ) - return new Response(response, requester) - } else { - const track = `${source || "ytsearch"}:${query}` - const response = await this.node.rest.get( - `/v4/loadtracks?identifier=${encodeURIComponent(track)}` - ) - return new Response(response, requester) - } + const response = await this.node.rest.get(`/v4/loadtracks?identifier=${encodeURIComponent((query.startsWith('https://') ? '' : source || 'ytsearch:') + query)}`) + return new Response(response, requester); }; /** diff --git a/src/Poru.ts b/src/Poru.ts index 1bc47dc5..6abceb7c 100644 --- a/src/Poru.ts +++ b/src/Poru.ts @@ -511,20 +511,9 @@ export class Poru extends EventEmitter { if (!node) node = this.leastUsedNodes[0]; if (!node) throw new Error("No nodes are available."); - const regex = /^https?:\/\//; - - if (regex.test(query)) { - let response = await node.rest.get( - `/v4/loadtracks?identifier=${encodeURIComponent(query)}` - ); - return new Response(response, requester); - } else { - let track = `${source || "ytsearch"}:${query}`; - let response = await node.rest.get( - `/v4/loadtracks?identifier=${encodeURIComponent(track)}` - ); - return new Response(response, requester); - } + + const response = await node.rest.get(`/v4/loadtracks?identifier=${encodeURIComponent((query.startsWith('https://') ? '' : source || 'ytsearch:') + query)}`) + return new Response(response, requester); } /** From a6f48917276eec854e9a2c312ef2076664b08a63 Mon Sep 17 00:00:00 2001 From: Joniii Date: Fri, 29 Mar 2024 10:03:32 +0100 Subject: [PATCH 8/8] Fix query string concatenation in resolve method --- src/Player/Player.ts | 2 +- src/Poru.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Player/Player.ts b/src/Player/Player.ts index a413c9b2..5c0685cf 100644 --- a/src/Player/Player.ts +++ b/src/Player/Player.ts @@ -550,7 +550,7 @@ export class Player extends EventEmitter { * @returns {Promise} - A Promise that resolves to a Response object containing the resolved tracks. */ public async resolve({ query, source, requester }: ResolveOptions): Promise { - const response = await this.node.rest.get(`/v4/loadtracks?identifier=${encodeURIComponent((query.startsWith('https://') ? '' : source || 'ytsearch:') + query)}`) + const response = await this.node.rest.get(`/v4/loadtracks?identifier=${encodeURIComponent((query.startsWith('https://') ? '' : `${source || 'ytsearch'}:`) + query)}`) return new Response(response, requester); }; diff --git a/src/Poru.ts b/src/Poru.ts index 6abceb7c..86389450 100644 --- a/src/Poru.ts +++ b/src/Poru.ts @@ -512,7 +512,7 @@ export class Poru extends EventEmitter { if (!node) node = this.leastUsedNodes[0]; if (!node) throw new Error("No nodes are available."); - const response = await node.rest.get(`/v4/loadtracks?identifier=${encodeURIComponent((query.startsWith('https://') ? '' : source || 'ytsearch:') + query)}`) + const response = await node.rest.get(`/v4/loadtracks?identifier=${encodeURIComponent((query.startsWith('https://') ? '' : `${source || 'ytsearch'}:`) + query)}`) return new Response(response, requester); }