lavalink-client 2.2.2 → 2.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +95 -1
- package/dist/cjs/index.d.ts +8 -1
- package/dist/cjs/index.js +8 -1
- package/dist/cjs/structures/Constants.d.ts +40 -0
- package/dist/cjs/structures/Constants.js +244 -0
- package/dist/cjs/structures/CustomSearches/BandCampSearch.d.ts +2 -2
- package/dist/cjs/structures/Filters.d.ts +2 -217
- package/dist/cjs/structures/Filters.js +8 -232
- package/dist/cjs/structures/LavalinkManager.d.ts +31 -166
- package/dist/cjs/structures/LavalinkManager.js +59 -7
- package/dist/cjs/structures/LavalinkManagerStatics.d.ts +1 -1
- package/dist/cjs/structures/Node.d.ts +15 -156
- package/dist/cjs/structures/Node.js +131 -49
- package/dist/cjs/structures/NodeManager.d.ts +54 -52
- package/dist/cjs/structures/NodeManager.js +74 -4
- package/dist/cjs/structures/Player.d.ts +31 -124
- package/dist/cjs/structures/Player.js +77 -43
- package/dist/cjs/structures/Queue.d.ts +66 -42
- package/dist/cjs/structures/Queue.js +69 -11
- package/dist/cjs/structures/Types/Filters.d.ts +190 -0
- package/dist/cjs/structures/Types/Manager.d.ts +184 -0
- package/dist/cjs/structures/Types/Manager.js +2 -0
- package/dist/cjs/structures/Types/Node.d.ts +216 -0
- package/dist/cjs/structures/Types/Node.js +2 -0
- package/dist/cjs/structures/Types/Player.d.ts +108 -0
- package/dist/cjs/structures/Types/Player.js +2 -0
- package/dist/cjs/structures/Types/Queue.d.ts +34 -0
- package/dist/cjs/structures/Types/Queue.js +2 -0
- package/dist/cjs/structures/{Track.d.ts → Types/Track.d.ts} +3 -2
- package/dist/{structures → cjs/structures/Types}/Track.js +2 -2
- package/dist/cjs/structures/Types/Utils.d.ts +367 -0
- package/dist/cjs/structures/Types/Utils.js +2 -0
- package/dist/cjs/structures/Utils.d.ts +13 -369
- package/dist/cjs/structures/Utils.js +35 -14
- package/dist/esm/index.d.ts +8 -1
- package/dist/esm/index.js +8 -1
- package/dist/esm/structures/Constants.d.ts +40 -0
- package/dist/esm/structures/Constants.js +241 -0
- package/dist/esm/structures/CustomSearches/BandCampSearch.d.ts +2 -2
- package/dist/esm/structures/Filters.d.ts +2 -217
- package/dist/esm/structures/Filters.js +3 -227
- package/dist/esm/structures/LavalinkManager.d.ts +31 -166
- package/dist/esm/structures/LavalinkManager.js +57 -5
- package/dist/esm/structures/LavalinkManagerStatics.d.ts +1 -1
- package/dist/esm/structures/Node.d.ts +15 -156
- package/dist/esm/structures/Node.js +122 -40
- package/dist/esm/structures/NodeManager.d.ts +54 -52
- package/dist/esm/structures/NodeManager.js +71 -1
- package/dist/esm/structures/Player.d.ts +31 -124
- package/dist/esm/structures/Player.js +76 -42
- package/dist/esm/structures/Queue.d.ts +66 -42
- package/dist/esm/structures/Queue.js +69 -11
- package/dist/esm/structures/Types/Filters.d.ts +190 -0
- package/dist/esm/structures/Types/Manager.d.ts +184 -0
- package/dist/esm/structures/Types/Manager.js +1 -0
- package/dist/esm/structures/Types/Node.d.ts +216 -0
- package/dist/esm/structures/Types/Node.js +1 -0
- package/dist/esm/structures/Types/Player.d.ts +108 -0
- package/dist/esm/structures/Types/Player.js +1 -0
- package/dist/esm/structures/Types/Queue.d.ts +34 -0
- package/dist/esm/structures/Types/Queue.js +1 -0
- package/dist/esm/structures/{Track.d.ts → Types/Track.d.ts} +3 -2
- package/dist/esm/structures/Types/Track.js +1 -0
- package/dist/esm/structures/Types/Utils.d.ts +367 -0
- package/dist/esm/structures/Types/Utils.js +1 -0
- package/dist/esm/structures/Utils.d.ts +13 -369
- package/dist/esm/structures/Utils.js +35 -14
- package/dist/types/index.d.ts +8 -1
- package/dist/types/structures/Constants.d.ts +40 -0
- package/dist/types/structures/CustomSearches/BandCampSearch.d.ts +2 -2
- package/dist/types/structures/Filters.d.ts +2 -217
- package/dist/types/structures/LavalinkManager.d.ts +31 -166
- package/dist/types/structures/LavalinkManagerStatics.d.ts +1 -1
- package/dist/types/structures/Node.d.ts +15 -156
- package/dist/types/structures/NodeManager.d.ts +54 -52
- package/dist/types/structures/Player.d.ts +31 -124
- package/dist/types/structures/Queue.d.ts +66 -42
- package/dist/types/structures/Types/Filters.d.ts +190 -0
- package/dist/types/structures/Types/Manager.d.ts +184 -0
- package/dist/types/structures/Types/Node.d.ts +216 -0
- package/dist/types/structures/Types/Player.d.ts +108 -0
- package/dist/types/structures/Types/Queue.d.ts +34 -0
- package/dist/types/structures/{Track.d.ts → Types/Track.d.ts} +3 -2
- package/dist/types/structures/Types/Utils.d.ts +367 -0
- package/dist/types/structures/Utils.d.ts +13 -369
- package/package.json +1 -1
- package/dist/index.d.ts +0 -10
- package/dist/index.js +0 -13
- package/dist/structures/Filters.d.ts +0 -230
- package/dist/structures/Filters.js +0 -472
- package/dist/structures/LavalinkManager.d.ts +0 -47
- package/dist/structures/LavalinkManager.js +0 -36
- package/dist/structures/LavalinkManagerStatics.d.ts +0 -3
- package/dist/structures/LavalinkManagerStatics.js +0 -76
- package/dist/structures/Node.d.ts +0 -171
- package/dist/structures/Node.js +0 -462
- package/dist/structures/NodeManager.d.ts +0 -58
- package/dist/structures/NodeManager.js +0 -25
- package/dist/structures/Player.d.ts +0 -101
- package/dist/structures/Player.js +0 -232
- package/dist/structures/PlayerManager.d.ts +0 -62
- package/dist/structures/PlayerManager.js +0 -26
- package/dist/structures/Queue.d.ts +0 -93
- package/dist/structures/Queue.js +0 -160
- package/dist/structures/QueueManager.d.ts +0 -77
- package/dist/structures/QueueManager.js +0 -74
- package/dist/structures/Track.d.ts +0 -27
- package/dist/structures/Utils.d.ts +0 -183
- package/dist/structures/Utils.js +0 -43
- /package/dist/cjs/structures/{Track.js → Types/Filters.js} +0 -0
- /package/dist/esm/structures/{Track.js → Types/Filters.js} +0 -0
|
@@ -1,162 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
/** Ability to manipulate fetch requests */
|
|
8
|
-
export type ModifyRequest = (options: RequestInit & {
|
|
9
|
-
path: string;
|
|
10
|
-
extraQueryUrlParams?: URLSearchParams;
|
|
11
|
-
}) => void;
|
|
12
|
-
export declare const validSponsorBlocks: string[];
|
|
13
|
-
export type SponsorBlockSegment = "sponsor" | "selfpromo" | "interaction" | "intro" | "outro" | "preview" | "music_offtopic" | "filler";
|
|
14
|
-
/**
|
|
15
|
-
* Node Options for creating a lavalink node
|
|
16
|
-
*/
|
|
17
|
-
export interface LavalinkNodeOptions {
|
|
18
|
-
/** The Lavalink Server-Ip / Domain-URL */
|
|
19
|
-
host: string;
|
|
20
|
-
/** The Lavalink Connection Port */
|
|
21
|
-
port: number;
|
|
22
|
-
/** The Lavalink Password / Authorization-Key */
|
|
23
|
-
authorization: string;
|
|
24
|
-
/** Does the Server use ssl (https) */
|
|
25
|
-
secure?: boolean;
|
|
26
|
-
/** RESUME THE PLAYER? by providing a sessionid on the node-creation */
|
|
27
|
-
sessionId?: string;
|
|
28
|
-
/** Add a Custom ID to the node, for later use */
|
|
29
|
-
id?: string;
|
|
30
|
-
/** Voice Regions of this Node */
|
|
31
|
-
regions?: string[];
|
|
32
|
-
/** The retryAmount for the node. */
|
|
33
|
-
retryAmount?: number;
|
|
34
|
-
/** The retryDelay for the node. */
|
|
35
|
-
retryDelay?: number;
|
|
36
|
-
/** signal for cancelling requests - default: AbortSignal.timeout(options.requestSignalTimeoutMS || 10000) - put <= 0 to disable */
|
|
37
|
-
requestSignalTimeoutMS?: number;
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Memory Stats object from lavalink
|
|
41
|
-
*/
|
|
42
|
-
export interface MemoryStats {
|
|
43
|
-
/** The free memory of the allocated amount. */
|
|
44
|
-
free: number;
|
|
45
|
-
/** The used memory of the allocated amount. */
|
|
46
|
-
used: number;
|
|
47
|
-
/** The total allocated memory. */
|
|
48
|
-
allocated: number;
|
|
49
|
-
/** The reservable memory. */
|
|
50
|
-
reservable: number;
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* CPU Stats object from lavalink
|
|
54
|
-
*/
|
|
55
|
-
export interface CPUStats {
|
|
56
|
-
/** The core amount the host machine has. */
|
|
57
|
-
cores: number;
|
|
58
|
-
/** The system load. */
|
|
59
|
-
systemLoad: number;
|
|
60
|
-
/** The lavalink load. */
|
|
61
|
-
lavalinkLoad: number;
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* FrameStats Object from lavalink
|
|
65
|
-
*/
|
|
66
|
-
export interface FrameStats {
|
|
67
|
-
/** The amount of sent frames. */
|
|
68
|
-
sent?: number;
|
|
69
|
-
/** The amount of nulled frames. */
|
|
70
|
-
nulled?: number;
|
|
71
|
-
/** The amount of deficit frames. */
|
|
72
|
-
deficit?: number;
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* BaseNodeStats object from Lavalink
|
|
76
|
-
*/
|
|
77
|
-
export interface BaseNodeStats {
|
|
78
|
-
/** The amount of players on the node. */
|
|
79
|
-
players: number;
|
|
80
|
-
/** The amount of playing players on the node. */
|
|
81
|
-
playingPlayers: number;
|
|
82
|
-
/** The uptime for the node. */
|
|
83
|
-
uptime: number;
|
|
84
|
-
/** The memory stats for the node. */
|
|
85
|
-
memory: MemoryStats;
|
|
86
|
-
/** The cpu stats for the node. */
|
|
87
|
-
cpu: CPUStats;
|
|
88
|
-
/** The frame stats for the node. */
|
|
89
|
-
frameStats: FrameStats;
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* Interface for nodeStats from lavalink
|
|
93
|
-
*/
|
|
94
|
-
export interface NodeStats extends BaseNodeStats {
|
|
95
|
-
/** The frame stats for the node. */
|
|
96
|
-
frameStats: FrameStats;
|
|
97
|
-
}
|
|
98
|
-
/**
|
|
99
|
-
* Entire lavalink information object from lavalink
|
|
100
|
-
*/
|
|
101
|
-
export interface LavalinkInfo {
|
|
102
|
-
/** The version of this Lavalink server */
|
|
103
|
-
version: VersionObject;
|
|
104
|
-
/** The millisecond unix timestamp when this Lavalink jar was built */
|
|
105
|
-
buildTime: number;
|
|
106
|
-
/** The git information of this Lavalink server */
|
|
107
|
-
git: GitObject;
|
|
108
|
-
/** The JVM version this Lavalink server runs on */
|
|
109
|
-
jvm: string;
|
|
110
|
-
/** The Lavaplayer version being used by this server */
|
|
111
|
-
lavaplayer: string;
|
|
112
|
-
/** The enabled source managers for this server */
|
|
113
|
-
sourceManagers: string[];
|
|
114
|
-
/** The enabled filters for this server */
|
|
115
|
-
filters: string[];
|
|
116
|
-
/** The enabled plugins for this server */
|
|
117
|
-
plugins: PluginObject[];
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* Lavalink's version object from lavalink
|
|
121
|
-
*/
|
|
122
|
-
export interface VersionObject {
|
|
123
|
-
/** The full version string of this Lavalink server */
|
|
124
|
-
semver: string;
|
|
125
|
-
/** The major version of this Lavalink server */
|
|
126
|
-
major: number;
|
|
127
|
-
/** The minor version of this Lavalink server */
|
|
128
|
-
minor: number;
|
|
129
|
-
/** The patch version of this Lavalink server */
|
|
130
|
-
patch: internal;
|
|
131
|
-
/** The pre-release version according to semver as a . separated list of identifiers */
|
|
132
|
-
preRelease?: string;
|
|
133
|
-
/** The build metadata according to semver as a . separated list of identifiers */
|
|
134
|
-
build?: string;
|
|
135
|
-
}
|
|
136
|
-
/**
|
|
137
|
-
* Git information object from lavalink
|
|
138
|
-
*/
|
|
139
|
-
export interface GitObject {
|
|
140
|
-
/** The branch this Lavalink server was built on */
|
|
141
|
-
branch: string;
|
|
142
|
-
/** The commit this Lavalink server was built on */
|
|
143
|
-
commit: string;
|
|
144
|
-
/** The millisecond unix timestamp for when the commit was created */
|
|
145
|
-
commitTime: string;
|
|
146
|
-
}
|
|
147
|
-
/**
|
|
148
|
-
* Lavalink's plugins object from lavalink's plugin
|
|
149
|
-
*/
|
|
150
|
-
export interface PluginObject {
|
|
151
|
-
/** The name of the plugin */
|
|
152
|
-
name: string;
|
|
153
|
-
/** The version of the plugin */
|
|
154
|
-
version: string;
|
|
155
|
-
}
|
|
1
|
+
import type { Player } from "./Player";
|
|
2
|
+
import type { DestroyReasonsType } from "./Types/Player";
|
|
3
|
+
import type { Track } from "./Types/Track";
|
|
4
|
+
import type { Base64, InvalidLavalinkRestRequest, LavalinkPlayer, LavaSearchQuery, LavaSearchResponse, PlayerUpdateInfo, RoutePlanner, SearchQuery, SearchResult, Session } from "./Types/Utils";
|
|
5
|
+
import type { NodeManager } from "./NodeManager";
|
|
6
|
+
import type { BaseNodeStats, LavalinkInfo, LavalinkNodeOptions, ModifyRequest, NodeStats, SponsorBlockSegment } from "./Types/Node";
|
|
156
7
|
/**
|
|
157
8
|
* Lavalink Node creator class
|
|
158
9
|
*/
|
|
159
10
|
export declare class LavalinkNode {
|
|
11
|
+
private heartBeatPingTimestamp;
|
|
12
|
+
private heartBeatPongTimestamp;
|
|
13
|
+
get heartBeatPing(): number;
|
|
14
|
+
private heartBeatInterval?;
|
|
15
|
+
private pingTimeout?;
|
|
160
16
|
/** The provided Options of the Node */
|
|
161
17
|
options: LavalinkNodeOptions;
|
|
162
18
|
/** The amount of rest calls the node has made. */
|
|
@@ -300,6 +156,7 @@ export declare class LavalinkNode {
|
|
|
300
156
|
* ```
|
|
301
157
|
*/
|
|
302
158
|
connect(sessionId?: string): void;
|
|
159
|
+
private heartBeat;
|
|
303
160
|
/**
|
|
304
161
|
* Get the id of the node
|
|
305
162
|
*
|
|
@@ -332,6 +189,7 @@ export declare class LavalinkNode {
|
|
|
332
189
|
* ```
|
|
333
190
|
*/
|
|
334
191
|
get connected(): boolean;
|
|
192
|
+
isAlive: boolean;
|
|
335
193
|
/**
|
|
336
194
|
* Returns the current ConnectionStatus
|
|
337
195
|
*
|
|
@@ -356,7 +214,7 @@ export declare class LavalinkNode {
|
|
|
356
214
|
* const playersOfLavalink = await node?.fetchAllPlayers();
|
|
357
215
|
* ```
|
|
358
216
|
*/
|
|
359
|
-
fetchAllPlayers(): Promise<LavalinkPlayer[]>;
|
|
217
|
+
fetchAllPlayers(): Promise<LavalinkPlayer[] | InvalidLavalinkRestRequest>;
|
|
360
218
|
/**
|
|
361
219
|
* Gets specific Player Information
|
|
362
220
|
* @returns lavalink player object if player exists on lavalink
|
|
@@ -517,6 +375,7 @@ export declare class LavalinkNode {
|
|
|
517
375
|
private message;
|
|
518
376
|
/** @private middleware util function for handling all kind of events from websocket */
|
|
519
377
|
private handleEvent;
|
|
378
|
+
private getTrackOfPayload;
|
|
520
379
|
/** @private util function for handling trackStart event */
|
|
521
380
|
private trackStart;
|
|
522
381
|
/** @private util function for handling trackEnd event */
|
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.LavalinkNode =
|
|
3
|
+
exports.LavalinkNode = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const path_1 = require("path");
|
|
6
6
|
const ws_1 = tslib_1.__importDefault(require("ws"));
|
|
7
|
-
const
|
|
7
|
+
const Constants_1 = require("./Constants");
|
|
8
8
|
const Utils_1 = require("./Utils");
|
|
9
|
-
exports.validSponsorBlocks = ["sponsor", "selfpromo", "interaction", "intro", "outro", "preview", "music_offtopic", "filler"];
|
|
10
9
|
/**
|
|
11
10
|
* Lavalink Node creator class
|
|
12
11
|
*/
|
|
13
12
|
class LavalinkNode {
|
|
13
|
+
heartBeatPingTimestamp = 0;
|
|
14
|
+
heartBeatPongTimestamp = 0;
|
|
15
|
+
get heartBeatPing() {
|
|
16
|
+
return this.heartBeatPongTimestamp - this.heartBeatPingTimestamp;
|
|
17
|
+
}
|
|
18
|
+
heartBeatInterval;
|
|
19
|
+
pingTimeout;
|
|
14
20
|
/** The provided Options of the Node */
|
|
15
21
|
options;
|
|
16
22
|
/** The amount of rest calls the node has made. */
|
|
@@ -70,8 +76,11 @@ class LavalinkNode {
|
|
|
70
76
|
this.options = {
|
|
71
77
|
secure: false,
|
|
72
78
|
retryAmount: 5,
|
|
73
|
-
retryDelay:
|
|
79
|
+
retryDelay: 10e3,
|
|
74
80
|
requestSignalTimeoutMS: 10000,
|
|
81
|
+
heartBeatInterval: 30000,
|
|
82
|
+
closeOnError: true,
|
|
83
|
+
enablePingOnStatsCheck: true,
|
|
75
84
|
...options
|
|
76
85
|
};
|
|
77
86
|
this.NodeManager = manager;
|
|
@@ -150,6 +159,8 @@ class LavalinkNode {
|
|
|
150
159
|
* ```
|
|
151
160
|
*/
|
|
152
161
|
async request(endpoint, modify, parseAsText = false) {
|
|
162
|
+
if (!this.connected)
|
|
163
|
+
throw new Error("The node is not connected to the Lavalink Server!, Please call node.connect() first!");
|
|
153
164
|
const { request, options } = await this.rawRequest(endpoint, modify);
|
|
154
165
|
if (["DELETE", "PUT"].includes(options.method))
|
|
155
166
|
return;
|
|
@@ -234,7 +245,7 @@ class LavalinkNode {
|
|
|
234
245
|
if (Query.source)
|
|
235
246
|
this.NodeManager.LavalinkManager.utils.validateSourceString(this, Query.source);
|
|
236
247
|
if (/^https?:\/\//.test(Query.query))
|
|
237
|
-
return
|
|
248
|
+
return this.search({ query: Query.query, source: Query.source }, requestUser);
|
|
238
249
|
if (!["spsearch", "sprec", "amsearch", "dzsearch", "dzisrc", "ytmsearch", "ytsearch"].includes(Query.source))
|
|
239
250
|
throw new SyntaxError(`Query.source must be a source from LavaSrc: "spsearch" | "sprec" | "amsearch" | "dzsearch" | "dzisrc" | "ytmsearch" | "ytsearch"`);
|
|
240
251
|
if (!this.info.plugins.find(v => v.name === "lavasearch-plugin"))
|
|
@@ -296,7 +307,7 @@ class LavalinkNode {
|
|
|
296
307
|
async destroyPlayer(guildId) {
|
|
297
308
|
if (!this.sessionId)
|
|
298
309
|
throw new Error("The Lavalink-Node is either not ready, or not up to date!");
|
|
299
|
-
return
|
|
310
|
+
return this.request(`/sessions/${this.sessionId}/players/${guildId}`, r => { r.method = "DELETE"; });
|
|
300
311
|
}
|
|
301
312
|
/**
|
|
302
313
|
* Connect to the Lavalink Node
|
|
@@ -328,6 +339,17 @@ class LavalinkNode {
|
|
|
328
339
|
this.socket.on("close", (code, reason) => this.close(code, reason?.toString()));
|
|
329
340
|
this.socket.on("message", this.message.bind(this));
|
|
330
341
|
this.socket.on("error", this.error.bind(this));
|
|
342
|
+
// this.socket.on("ping", () => this.heartBeat("ping")); // lavalink doesn'T send ping periodically, therefore we use the stats message
|
|
343
|
+
}
|
|
344
|
+
heartBeat() {
|
|
345
|
+
if (this.pingTimeout)
|
|
346
|
+
clearTimeout(this.pingTimeout);
|
|
347
|
+
this.pingTimeout = setTimeout(() => {
|
|
348
|
+
if (!this.socket)
|
|
349
|
+
return console.error("Node-Ping-Acknowledge-Timeout - Socket not available - maybe reconnecting?");
|
|
350
|
+
this.isAlive = false;
|
|
351
|
+
this.socket.terminate();
|
|
352
|
+
}, 65000); // the stats endpoint get's sent every 60s. se wee add a 5s buffer to make sure we don't miss any stats message
|
|
331
353
|
}
|
|
332
354
|
/**
|
|
333
355
|
* Get the id of the node
|
|
@@ -358,7 +380,7 @@ class LavalinkNode {
|
|
|
358
380
|
const players = this.NodeManager.LavalinkManager.players.filter(p => p.node.id === this.id);
|
|
359
381
|
if (players)
|
|
360
382
|
players.forEach(p => {
|
|
361
|
-
p.destroy(destroyReason ||
|
|
383
|
+
p.destroy(destroyReason || Constants_1.DestroyReasons.NodeDestroy);
|
|
362
384
|
});
|
|
363
385
|
this.socket.close(1000, "Node-Destroy");
|
|
364
386
|
this.socket.removeAllListeners();
|
|
@@ -388,6 +410,7 @@ class LavalinkNode {
|
|
|
388
410
|
return false;
|
|
389
411
|
return this.socket.readyState === ws_1.default.OPEN;
|
|
390
412
|
}
|
|
413
|
+
isAlive = false;
|
|
391
414
|
/**
|
|
392
415
|
* Returns the current ConnectionStatus
|
|
393
416
|
*
|
|
@@ -419,11 +442,7 @@ class LavalinkNode {
|
|
|
419
442
|
async fetchAllPlayers() {
|
|
420
443
|
if (!this.sessionId)
|
|
421
444
|
throw new Error("The Lavalink-Node is either not ready, or not up to date!");
|
|
422
|
-
|
|
423
|
-
if (!Array.isArray(players))
|
|
424
|
-
return [];
|
|
425
|
-
else
|
|
426
|
-
return players;
|
|
445
|
+
return this.request(`/sessions/${this.sessionId}/players`) || [];
|
|
427
446
|
}
|
|
428
447
|
/**
|
|
429
448
|
* Gets specific Player Information
|
|
@@ -438,7 +457,7 @@ class LavalinkNode {
|
|
|
438
457
|
async fetchPlayer(guildId) {
|
|
439
458
|
if (!this.sessionId)
|
|
440
459
|
throw new Error("The Lavalink-Node is either not ready, or not up to date!");
|
|
441
|
-
return
|
|
460
|
+
return this.request(`/sessions/${this.sessionId}/players/${guildId}`);
|
|
442
461
|
}
|
|
443
462
|
/**
|
|
444
463
|
* Updates the session with and enables/disables resuming and timeout
|
|
@@ -464,7 +483,7 @@ class LavalinkNode {
|
|
|
464
483
|
enabled: typeof resuming === "boolean" ? resuming : false,
|
|
465
484
|
timeout: typeof resuming === "boolean" && resuming === true ? timeout : null,
|
|
466
485
|
};
|
|
467
|
-
return
|
|
486
|
+
return this.request(`/sessions/${this.sessionId}`, r => {
|
|
468
487
|
r.method = "PATCH";
|
|
469
488
|
r.headers = { Authorization: this.options.authorization, 'Content-Type': 'application/json' };
|
|
470
489
|
r.body = JSON.stringify(data);
|
|
@@ -688,7 +707,7 @@ class LavalinkNode {
|
|
|
688
707
|
if (!player)
|
|
689
708
|
return;
|
|
690
709
|
if (typeof res?.voice?.connected === "boolean" && res.voice.connected === false)
|
|
691
|
-
return player.destroy(
|
|
710
|
+
return player.destroy(Constants_1.DestroyReasons.LavalinkNoVoice);
|
|
692
711
|
player.ping.ws = res?.voice?.ping || player?.ping.ws;
|
|
693
712
|
}
|
|
694
713
|
return true;
|
|
@@ -710,11 +729,12 @@ class LavalinkNode {
|
|
|
710
729
|
* ```
|
|
711
730
|
*/
|
|
712
731
|
reconnect(instaReconnect = false) {
|
|
732
|
+
this.NodeManager.emit("reconnectinprogress", this);
|
|
713
733
|
if (instaReconnect) {
|
|
714
734
|
if (this.reconnectAttempts >= this.options.retryAmount) {
|
|
715
735
|
const error = new Error(`Unable to connect after ${this.options.retryAmount} attempts.`);
|
|
716
736
|
this.NodeManager.emit("error", this, error);
|
|
717
|
-
return this.destroy(
|
|
737
|
+
return this.destroy(Constants_1.DestroyReasons.NodeReconnectFail);
|
|
718
738
|
}
|
|
719
739
|
this.socket.removeAllListeners();
|
|
720
740
|
this.socket = null;
|
|
@@ -727,7 +747,7 @@ class LavalinkNode {
|
|
|
727
747
|
if (this.reconnectAttempts >= this.options.retryAmount) {
|
|
728
748
|
const error = new Error(`Unable to connect after ${this.options.retryAmount} attempts.`);
|
|
729
749
|
this.NodeManager.emit("error", this, error);
|
|
730
|
-
return this.destroy(
|
|
750
|
+
return this.destroy(Constants_1.DestroyReasons.NodeReconnectFail);
|
|
731
751
|
}
|
|
732
752
|
this.socket.removeAllListeners();
|
|
733
753
|
this.socket = null;
|
|
@@ -738,6 +758,29 @@ class LavalinkNode {
|
|
|
738
758
|
}
|
|
739
759
|
/** @private util function for handling opening events from websocket */
|
|
740
760
|
async open() {
|
|
761
|
+
this.isAlive = true;
|
|
762
|
+
// trigger heartbeat-ping timeout - this is to check wether the client lost connection without knowing it
|
|
763
|
+
if (this.options.enablePingOnStatsCheck)
|
|
764
|
+
this.heartBeat();
|
|
765
|
+
if (this.heartBeatInterval)
|
|
766
|
+
clearInterval(this.heartBeatInterval);
|
|
767
|
+
if (this.options.heartBeatInterval > 0) {
|
|
768
|
+
// everytime a pong happens, set this.isAlive to true
|
|
769
|
+
this.socket.on("pong", () => {
|
|
770
|
+
this.heartBeatPongTimestamp = performance.now();
|
|
771
|
+
this.isAlive = true;
|
|
772
|
+
});
|
|
773
|
+
// every x ms send a ping to lavalink to retrieve a pong later on
|
|
774
|
+
this.heartBeatInterval = setInterval(() => {
|
|
775
|
+
if (!this.socket)
|
|
776
|
+
return console.error("Node-Heartbeat-Interval - Socket not available - maybe reconnecting?");
|
|
777
|
+
if (!this.isAlive)
|
|
778
|
+
this.close(500, "Node-Heartbeat-Timeout");
|
|
779
|
+
this.isAlive = false;
|
|
780
|
+
this.heartBeatPingTimestamp = performance.now();
|
|
781
|
+
this.socket.ping();
|
|
782
|
+
}, this.options.heartBeatInterval || 30000);
|
|
783
|
+
}
|
|
741
784
|
if (this.reconnectTimeout)
|
|
742
785
|
clearTimeout(this.reconnectTimeout);
|
|
743
786
|
// reset the reconnect attempts amount
|
|
@@ -751,6 +794,12 @@ class LavalinkNode {
|
|
|
751
794
|
}
|
|
752
795
|
/** @private util function for handling closing events from websocket */
|
|
753
796
|
close(code, reason) {
|
|
797
|
+
if (this.pingTimeout)
|
|
798
|
+
clearTimeout(this.pingTimeout);
|
|
799
|
+
if (this.heartBeatInterval)
|
|
800
|
+
clearInterval(this.heartBeatInterval);
|
|
801
|
+
if (code === 1006 && !reason)
|
|
802
|
+
reason = "Socket got terminated due to no ping connection";
|
|
754
803
|
this.NodeManager.emit("disconnect", this, { code, reason });
|
|
755
804
|
if (code !== 1000 || reason !== "Node-Destroy")
|
|
756
805
|
this.reconnect();
|
|
@@ -760,6 +809,14 @@ class LavalinkNode {
|
|
|
760
809
|
if (!error)
|
|
761
810
|
return;
|
|
762
811
|
this.NodeManager.emit("error", this, error);
|
|
812
|
+
if (this.options.closeOnError) {
|
|
813
|
+
if (this.heartBeatInterval)
|
|
814
|
+
clearInterval(this.heartBeatInterval);
|
|
815
|
+
if (this.pingTimeout)
|
|
816
|
+
clearTimeout(this.pingTimeout);
|
|
817
|
+
this.socket?.close(500, "Node-Error - Force Reconnect");
|
|
818
|
+
}
|
|
819
|
+
;
|
|
763
820
|
}
|
|
764
821
|
/** @private util function for handling message events from websocket */
|
|
765
822
|
async message(d) {
|
|
@@ -773,6 +830,8 @@ class LavalinkNode {
|
|
|
773
830
|
this.NodeManager.emit("raw", this, payload);
|
|
774
831
|
switch (payload.op) {
|
|
775
832
|
case "stats":
|
|
833
|
+
if (this.options.enablePingOnStatsCheck)
|
|
834
|
+
this.heartBeat(); // lavalink doesn'T send "ping" periodically, therefore we use the stats message to check for a ping
|
|
776
835
|
delete payload.op;
|
|
777
836
|
this.stats = { ...payload };
|
|
778
837
|
break;
|
|
@@ -802,7 +861,13 @@ class LavalinkNode {
|
|
|
802
861
|
this.sessionId = payload.sessionId;
|
|
803
862
|
this.resuming.enabled = payload.resumed;
|
|
804
863
|
if (payload.resumed === true) {
|
|
805
|
-
|
|
864
|
+
try {
|
|
865
|
+
this.NodeManager.emit("resumed", this, payload, await this.fetchAllPlayers());
|
|
866
|
+
}
|
|
867
|
+
catch (e) {
|
|
868
|
+
console.error("Failed to fetch players for resumed event, falling back without players array", e);
|
|
869
|
+
this.NodeManager.emit("resumed", this, payload, []);
|
|
870
|
+
}
|
|
806
871
|
}
|
|
807
872
|
break;
|
|
808
873
|
default:
|
|
@@ -812,7 +877,7 @@ class LavalinkNode {
|
|
|
812
877
|
}
|
|
813
878
|
/** @private middleware util function for handling all kind of events from websocket */
|
|
814
879
|
async handleEvent(payload) {
|
|
815
|
-
if (!payload
|
|
880
|
+
if (!payload?.guildId)
|
|
816
881
|
return;
|
|
817
882
|
const player = this.NodeManager.LavalinkManager.getPlayer(payload.guildId);
|
|
818
883
|
if (!player)
|
|
@@ -851,39 +916,51 @@ class LavalinkNode {
|
|
|
851
916
|
}
|
|
852
917
|
return;
|
|
853
918
|
}
|
|
919
|
+
async getTrackOfPayload(payload) {
|
|
920
|
+
return "track" in payload
|
|
921
|
+
? this.NodeManager.LavalinkManager.utils.buildTrack(payload.track, undefined)
|
|
922
|
+
: null;
|
|
923
|
+
}
|
|
854
924
|
/** @private util function for handling trackStart event */
|
|
855
|
-
trackStart(player, track, payload) {
|
|
925
|
+
async trackStart(player, track, payload) {
|
|
856
926
|
player.playing = true;
|
|
857
927
|
player.paused = false;
|
|
858
928
|
// don't emit the event if previous track == new track aka track loop
|
|
859
929
|
if (this.NodeManager.LavalinkManager.options?.emitNewSongsOnly === true && player.queue.previous[0]?.info?.identifier === track?.info?.identifier)
|
|
860
930
|
return;
|
|
861
|
-
|
|
931
|
+
if (!player.queue.current) {
|
|
932
|
+
player.queue.current = await this.getTrackOfPayload(payload);
|
|
933
|
+
if (player.queue.current)
|
|
934
|
+
await player.queue.utils.save();
|
|
935
|
+
}
|
|
936
|
+
return this.NodeManager.LavalinkManager.emit("trackStart", player, player.queue.current, payload);
|
|
862
937
|
}
|
|
863
938
|
/** @private util function for handling trackEnd event */
|
|
864
939
|
async trackEnd(player, track, payload) {
|
|
940
|
+
const trackToUse = track || await this.getTrackOfPayload(payload);
|
|
941
|
+
// If a track was forcibly played
|
|
942
|
+
if (payload.reason === "replaced") {
|
|
943
|
+
return this.NodeManager.LavalinkManager.emit("trackEnd", player, trackToUse, payload);
|
|
944
|
+
}
|
|
865
945
|
// If there are no songs in the queue
|
|
866
946
|
if (!player.queue.tracks.length && (player.repeatMode === "off" || player.get("internal_stopPlaying")))
|
|
867
947
|
return this.queueEnd(player, track, payload);
|
|
868
|
-
// If a track was forcibly played
|
|
869
|
-
if (payload.reason === "replaced")
|
|
870
|
-
return this.NodeManager.LavalinkManager.emit("trackEnd", player, track, payload);
|
|
871
948
|
// If a track had an error while starting
|
|
872
949
|
if (["loadFailed", "cleanup"].includes(payload.reason)) {
|
|
873
950
|
await (0, Utils_1.queueTrackEnd)(player);
|
|
874
951
|
// if no track available, end queue
|
|
875
952
|
if (!player.queue.current)
|
|
876
|
-
return this.queueEnd(player,
|
|
953
|
+
return this.queueEnd(player, trackToUse, payload);
|
|
877
954
|
// fire event
|
|
878
|
-
this.NodeManager.LavalinkManager.emit("trackEnd", player,
|
|
955
|
+
this.NodeManager.LavalinkManager.emit("trackEnd", player, trackToUse, payload);
|
|
879
956
|
// play track if autoSkip is true
|
|
880
957
|
return this.NodeManager.LavalinkManager.options.autoSkip && player.play({ noReplace: true });
|
|
881
958
|
}
|
|
882
959
|
// remove tracks from the queue
|
|
883
960
|
if (player.repeatMode !== "track" || player.get("internal_skipped"))
|
|
884
961
|
await (0, Utils_1.queueTrackEnd)(player);
|
|
885
|
-
else if (
|
|
886
|
-
player.queue.previous.unshift(
|
|
962
|
+
else if (trackToUse && !trackToUse?.pluginInfo?.clientData?.previousTrack) { // If there was a current Track already and repeatmode === true, add it to the queue.
|
|
963
|
+
player.queue.previous.unshift(trackToUse);
|
|
887
964
|
if (player.queue.previous.length > player.queue.options.maxPreviousTracks)
|
|
888
965
|
player.queue.previous.splice(player.queue.options.maxPreviousTracks, player.queue.previous.length);
|
|
889
966
|
await player.queue.utils.save();
|
|
@@ -891,60 +968,65 @@ class LavalinkNode {
|
|
|
891
968
|
player.set("internal_skipped", false);
|
|
892
969
|
// if no track available, end queue
|
|
893
970
|
if (!player.queue.current)
|
|
894
|
-
return this.queueEnd(player,
|
|
971
|
+
return this.queueEnd(player, trackToUse, payload);
|
|
895
972
|
// fire event
|
|
896
|
-
this.NodeManager.LavalinkManager.emit("trackEnd", player,
|
|
973
|
+
this.NodeManager.LavalinkManager.emit("trackEnd", player, trackToUse, payload);
|
|
897
974
|
// play track if autoSkip is true
|
|
898
975
|
return this.NodeManager.LavalinkManager.options.autoSkip && player.play({ noReplace: true });
|
|
899
976
|
}
|
|
900
977
|
/** @private util function for handling trackStuck event */
|
|
901
978
|
async trackStuck(player, track, payload) {
|
|
902
|
-
this.NodeManager.LavalinkManager.emit("trackStuck", player, track, payload);
|
|
979
|
+
this.NodeManager.LavalinkManager.emit("trackStuck", player, track || await this.getTrackOfPayload(payload), payload);
|
|
903
980
|
// If there are no songs in the queue
|
|
904
981
|
if (!player.queue.tracks.length && (player.repeatMode === "off" || player.get("internal_stopPlaying")))
|
|
905
|
-
return this.queueEnd(player, track, payload);
|
|
982
|
+
return this.queueEnd(player, track || await this.getTrackOfPayload(payload), payload);
|
|
906
983
|
// remove the current track, and enqueue the next one
|
|
907
984
|
await (0, Utils_1.queueTrackEnd)(player);
|
|
908
985
|
// if no track available, end queue
|
|
909
986
|
if (!player.queue.current)
|
|
910
|
-
return this.queueEnd(player, track, payload);
|
|
987
|
+
return this.queueEnd(player, track || await this.getTrackOfPayload(payload), payload);
|
|
911
988
|
// play track if autoSkip is true
|
|
912
989
|
return (this.NodeManager.LavalinkManager.options.autoSkip && player.queue.current) && player.play({ noReplace: true });
|
|
913
990
|
}
|
|
914
991
|
/** @private util function for handling trackError event */
|
|
915
992
|
async trackError(player, track, payload) {
|
|
916
|
-
this.NodeManager.LavalinkManager.emit("trackError", player, track, payload);
|
|
993
|
+
this.NodeManager.LavalinkManager.emit("trackError", player, track || await this.getTrackOfPayload(payload), payload);
|
|
917
994
|
return; // get's handled by trackEnd
|
|
918
995
|
// If there are no songs in the queue
|
|
919
996
|
if (!player.queue.tracks.length && (player.repeatMode === "off" || player.get("internal_stopPlaying")))
|
|
920
|
-
return this.queueEnd(player, track, payload);
|
|
997
|
+
return this.queueEnd(player, track || await this.getTrackOfPayload(payload), payload);
|
|
921
998
|
// remove the current track, and enqueue the next one
|
|
922
999
|
await (0, Utils_1.queueTrackEnd)(player);
|
|
923
1000
|
// if no track available, end queue
|
|
924
1001
|
if (!player.queue.current)
|
|
925
|
-
return this.queueEnd(player, track, payload);
|
|
1002
|
+
return this.queueEnd(player, track || await this.getTrackOfPayload(payload), payload);
|
|
926
1003
|
// play track if autoSkip is true
|
|
927
1004
|
return (this.NodeManager.LavalinkManager.options.autoSkip && player.queue.current) && player.play({ noReplace: true });
|
|
928
1005
|
}
|
|
929
1006
|
/** @private util function for handling socketClosed event */
|
|
930
1007
|
socketClosed(player, payload) {
|
|
931
|
-
|
|
1008
|
+
this.NodeManager.LavalinkManager.emit("playerSocketClosed", player, payload);
|
|
1009
|
+
// i don't think this is needed.
|
|
1010
|
+
// this.socket = null;
|
|
1011
|
+
// // causing a socket reconnect
|
|
1012
|
+
// this.connect();
|
|
1013
|
+
return;
|
|
932
1014
|
}
|
|
933
1015
|
/** @private util function for handling SponsorBlock Segmentloaded event */
|
|
934
|
-
SponsorBlockSegmentLoaded(player, track, payload) {
|
|
935
|
-
return this.NodeManager.LavalinkManager.emit("SegmentsLoaded", player, track, payload);
|
|
1016
|
+
async SponsorBlockSegmentLoaded(player, track, payload) {
|
|
1017
|
+
return this.NodeManager.LavalinkManager.emit("SegmentsLoaded", player, track || await this.getTrackOfPayload(payload), payload);
|
|
936
1018
|
}
|
|
937
1019
|
/** @private util function for handling SponsorBlock SegmentSkipped event */
|
|
938
|
-
SponsorBlockSegmentSkipped(player, track, payload) {
|
|
939
|
-
return this.NodeManager.LavalinkManager.emit("SegmentSkipped", player, track, payload);
|
|
1020
|
+
async SponsorBlockSegmentSkipped(player, track, payload) {
|
|
1021
|
+
return this.NodeManager.LavalinkManager.emit("SegmentSkipped", player, track || await this.getTrackOfPayload(payload), payload);
|
|
940
1022
|
}
|
|
941
1023
|
/** @private util function for handling SponsorBlock Chaptersloaded event */
|
|
942
|
-
SponsorBlockChaptersLoaded(player, track, payload) {
|
|
943
|
-
return this.NodeManager.LavalinkManager.emit("ChaptersLoaded", player, track, payload);
|
|
1024
|
+
async SponsorBlockChaptersLoaded(player, track, payload) {
|
|
1025
|
+
return this.NodeManager.LavalinkManager.emit("ChaptersLoaded", player, track || await this.getTrackOfPayload(payload), payload);
|
|
944
1026
|
}
|
|
945
1027
|
/** @private util function for handling SponsorBlock Chaptersstarted event */
|
|
946
|
-
SponsorBlockChapterStarted(player, track, payload) {
|
|
947
|
-
return this.NodeManager.LavalinkManager.emit("ChapterStarted", player, track, payload);
|
|
1028
|
+
async SponsorBlockChapterStarted(player, track, payload) {
|
|
1029
|
+
return this.NodeManager.LavalinkManager.emit("ChapterStarted", player, track || await this.getTrackOfPayload(payload), payload);
|
|
948
1030
|
}
|
|
949
1031
|
/**
|
|
950
1032
|
* Get the current sponsorblocks for the sponsorblock plugin
|
|
@@ -983,8 +1065,8 @@ class LavalinkNode {
|
|
|
983
1065
|
if (!segments.length)
|
|
984
1066
|
throw new RangeError("No Segments provided. Did you ment to use 'deleteSponsorBlock'?");
|
|
985
1067
|
// a not valid segment
|
|
986
|
-
if (segments.some(v => !
|
|
987
|
-
throw new SyntaxError(`You provided a sponsorblock which isn't valid, valid ones are: ${
|
|
1068
|
+
if (segments.some(v => !Constants_1.validSponsorBlocks.includes(v.toLowerCase())))
|
|
1069
|
+
throw new SyntaxError(`You provided a sponsorblock which isn't valid, valid ones are: ${Constants_1.validSponsorBlocks.map(v => `'${v}'`).join(", ")}`);
|
|
988
1070
|
// do the request
|
|
989
1071
|
await this.request(`/sessions/${this.sessionId}/players/${player.guildId}/sponsorblock/categories`, (r) => {
|
|
990
1072
|
r.method = "PUT";
|
|
@@ -1042,14 +1124,14 @@ class LavalinkNode {
|
|
|
1042
1124
|
}
|
|
1043
1125
|
if (typeof this.NodeManager.LavalinkManager.options.playerOptions?.onEmptyQueue?.destroyAfterMs === "number" && !isNaN(this.NodeManager.LavalinkManager.options.playerOptions.onEmptyQueue?.destroyAfterMs) && this.NodeManager.LavalinkManager.options.playerOptions.onEmptyQueue?.destroyAfterMs >= 0) {
|
|
1044
1126
|
if (this.NodeManager.LavalinkManager.options.playerOptions.onEmptyQueue?.destroyAfterMs === 0)
|
|
1045
|
-
return player.destroy(
|
|
1127
|
+
return player.destroy(Constants_1.DestroyReasons.QueueEmpty);
|
|
1046
1128
|
else {
|
|
1047
1129
|
if (player.get("internal_queueempty")) {
|
|
1048
1130
|
clearTimeout(player.get("internal_queueempty"));
|
|
1049
1131
|
player.set("internal_queueempty", undefined);
|
|
1050
1132
|
}
|
|
1051
1133
|
player.set("internal_queueempty", setTimeout(() => {
|
|
1052
|
-
player.destroy(
|
|
1134
|
+
player.destroy(Constants_1.DestroyReasons.QueueEmpty);
|
|
1053
1135
|
}, this.NodeManager.LavalinkManager.options.playerOptions.onEmptyQueue?.destroyAfterMs));
|
|
1054
1136
|
}
|
|
1055
1137
|
}
|