lavalink-client 2.2.0 → 2.2.2
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 +116 -15
- package/dist/cjs/structures/Filters.d.ts +1 -1
- package/dist/cjs/structures/Filters.js +9 -9
- package/dist/cjs/structures/LavalinkManager.d.ts +24 -7
- package/dist/cjs/structures/LavalinkManager.js +15 -2
- package/dist/cjs/structures/LavalinkManagerStatics.d.ts +3 -0
- package/dist/cjs/structures/LavalinkManagerStatics.js +4 -1
- package/dist/cjs/structures/Node.d.ts +307 -22
- package/dist/cjs/structures/Node.js +328 -72
- package/dist/cjs/structures/NodeManager.js +3 -1
- package/dist/cjs/structures/Player.d.ts +44 -8
- package/dist/cjs/structures/Player.js +27 -18
- package/dist/cjs/structures/Queue.d.ts +47 -0
- package/dist/cjs/structures/Queue.js +104 -1
- package/dist/cjs/structures/Track.d.ts +1 -0
- package/dist/cjs/structures/Utils.d.ts +3 -0
- package/dist/cjs/structures/Utils.js +6 -4
- package/dist/esm/structures/Filters.d.ts +1 -1
- package/dist/esm/structures/Filters.js +9 -9
- package/dist/esm/structures/LavalinkManager.d.ts +24 -7
- package/dist/esm/structures/LavalinkManager.js +15 -2
- package/dist/esm/structures/LavalinkManagerStatics.d.ts +3 -0
- package/dist/esm/structures/LavalinkManagerStatics.js +4 -1
- package/dist/esm/structures/Node.d.ts +307 -22
- package/dist/esm/structures/Node.js +328 -72
- package/dist/esm/structures/NodeManager.js +3 -1
- package/dist/esm/structures/Player.d.ts +44 -8
- package/dist/esm/structures/Player.js +27 -18
- package/dist/esm/structures/Queue.d.ts +47 -0
- package/dist/esm/structures/Queue.js +104 -1
- package/dist/esm/structures/Track.d.ts +1 -0
- package/dist/esm/structures/Utils.d.ts +3 -0
- package/dist/esm/structures/Utils.js +6 -4
- package/dist/types/structures/Filters.d.ts +1 -1
- package/dist/types/structures/LavalinkManager.d.ts +24 -7
- package/dist/types/structures/LavalinkManagerStatics.d.ts +3 -0
- package/dist/types/structures/Node.d.ts +307 -22
- package/dist/types/structures/Player.d.ts +44 -8
- package/dist/types/structures/Queue.d.ts +47 -0
- package/dist/types/structures/Track.d.ts +1 -0
- package/dist/types/structures/Utils.d.ts +3 -0
- package/package.json +2 -3
|
@@ -7,11 +7,15 @@ const ws_1 = tslib_1.__importDefault(require("ws"));
|
|
|
7
7
|
const Player_1 = require("./Player");
|
|
8
8
|
const Utils_1 = require("./Utils");
|
|
9
9
|
exports.validSponsorBlocks = ["sponsor", "selfpromo", "interaction", "intro", "outro", "preview", "music_offtopic", "filler"];
|
|
10
|
+
/**
|
|
11
|
+
* Lavalink Node creator class
|
|
12
|
+
*/
|
|
10
13
|
class LavalinkNode {
|
|
11
14
|
/** The provided Options of the Node */
|
|
12
15
|
options;
|
|
13
16
|
/** The amount of rest calls the node has made. */
|
|
14
17
|
calls = 0;
|
|
18
|
+
/** Stats from lavalink, will be updated via an interval by lavalink. */
|
|
15
19
|
stats = {
|
|
16
20
|
players: 0,
|
|
17
21
|
playingPlayers: 0,
|
|
@@ -33,6 +37,7 @@ class LavalinkNode {
|
|
|
33
37
|
sent: 0,
|
|
34
38
|
}
|
|
35
39
|
};
|
|
40
|
+
/** The current sessionId, only present when connected */
|
|
36
41
|
sessionId = null;
|
|
37
42
|
/** Wether the node resuming is enabled or not */
|
|
38
43
|
resuming = { enabled: true, timeout: null };
|
|
@@ -52,6 +57,14 @@ class LavalinkNode {
|
|
|
52
57
|
* Create a new Node
|
|
53
58
|
* @param options Lavalink Node Options
|
|
54
59
|
* @param manager Node Manager
|
|
60
|
+
*
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```ts
|
|
64
|
+
* // don't create a node manually, instead use:
|
|
65
|
+
*
|
|
66
|
+
* client.lavalink.nodeManager.createNode(options)
|
|
67
|
+
* ```
|
|
55
68
|
*/
|
|
56
69
|
constructor(options, manager) {
|
|
57
70
|
this.options = {
|
|
@@ -68,11 +81,43 @@ class LavalinkNode {
|
|
|
68
81
|
this.options.regions = (this.options.regions || []).map(a => a.toLowerCase());
|
|
69
82
|
Object.defineProperty(this, Utils_1.NodeSymbol, { configurable: true, value: true });
|
|
70
83
|
}
|
|
84
|
+
/**
|
|
85
|
+
* Parse url params correctly for lavalink requests, including support for urls and uris.
|
|
86
|
+
* @param url input url object
|
|
87
|
+
* @param extraQueryUrlParams UrlSearchParams to use in a encodedURI, useful for example for flowertts
|
|
88
|
+
* @returns the url as a valid string
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```ts
|
|
92
|
+
* player.node.getRequestingUrl(new URL(`http://localhost:2333/v4/loadtracks?identifier=Never gonna give you up`));
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
getRequestingUrl(url, extraQueryUrlParams) {
|
|
96
|
+
if (!url.searchParams.size)
|
|
97
|
+
return `${url.origin}${url.pathname}`;
|
|
98
|
+
const keysToAdd = [];
|
|
99
|
+
for (const [paramKey, paramValue] of url.searchParams.entries()) {
|
|
100
|
+
const decoded = decodeURIComponent(paramValue).trim(); // double decoding, once internally, a second time if decoded by provided user.
|
|
101
|
+
if (decoded.includes("://") && !/^https?:\/\//.test(decoded)) { // uri, but not url.
|
|
102
|
+
const [key, ...values] = decoded.split("://");
|
|
103
|
+
keysToAdd.push(`${paramKey}=${encodeURI(`${key}://${encodeURIComponent(values.join("://"))}${extraQueryUrlParams && extraQueryUrlParams?.size > 0 ? `?${extraQueryUrlParams.toString()}` : ""}`)}`);
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
keysToAdd.push(`${paramKey}=${encodeURIComponent(decoded)}`);
|
|
107
|
+
}
|
|
108
|
+
return `${url.origin}${url.pathname}?${keysToAdd.join("&")}`;
|
|
109
|
+
}
|
|
71
110
|
/**
|
|
72
111
|
* Raw Request util function
|
|
73
112
|
* @param endpoint endpoint string
|
|
74
113
|
* @param modify modify the request
|
|
75
|
-
* @
|
|
114
|
+
* @param extraQueryUrlParams UrlSearchParams to use in a encodedURI, useful for example for flowertts
|
|
115
|
+
* @returns object containing request and option information
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* ```ts
|
|
119
|
+
* player.node.rawRequest(`/loadtracks?identifier=Never gonna give you up`, (options) => options.method = "GET");
|
|
120
|
+
* ```
|
|
76
121
|
*/
|
|
77
122
|
async rawRequest(endpoint, modify) {
|
|
78
123
|
const options = {
|
|
@@ -86,16 +131,23 @@ class LavalinkNode {
|
|
|
86
131
|
modify?.(options);
|
|
87
132
|
const url = new URL(`${this.restAddress}${options.path}`);
|
|
88
133
|
url.searchParams.append("trace", "true");
|
|
134
|
+
const urlToUse = this.getRequestingUrl(url, options?.extraQueryUrlParams);
|
|
89
135
|
delete options.path;
|
|
90
|
-
|
|
136
|
+
delete options.extraQueryUrlParams;
|
|
137
|
+
const request = await fetch(urlToUse, options);
|
|
91
138
|
this.calls++;
|
|
92
139
|
return { request, options };
|
|
93
140
|
}
|
|
94
141
|
/**
|
|
95
|
-
* Makes an API call to the Node
|
|
142
|
+
* Makes an API call to the Node. Should only be used for manual parsing like for not supported plugins
|
|
96
143
|
* @param endpoint The endpoint that we will make the call to
|
|
97
144
|
* @param modify Used to modify the request before being sent
|
|
98
145
|
* @returns The returned data
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* ```ts
|
|
149
|
+
* player.node.request(`/loadtracks?identifier=Never gonna give you up`, (options) => options.method = "GET", false);
|
|
150
|
+
* ```
|
|
99
151
|
*/
|
|
100
152
|
async request(endpoint, modify, parseAsText = false) {
|
|
101
153
|
const { request, options } = await this.rawRequest(endpoint, modify);
|
|
@@ -109,9 +161,17 @@ class LavalinkNode {
|
|
|
109
161
|
* Search something raw on the node, please note only add tracks to players of that node
|
|
110
162
|
* @param query SearchQuery Object
|
|
111
163
|
* @param requestUser Request User for creating the player(s)
|
|
164
|
+
* @param throwOnEmpty Wether to throw on an empty result or not
|
|
112
165
|
* @returns Searchresult
|
|
166
|
+
*
|
|
167
|
+
* @example
|
|
168
|
+
* ```ts
|
|
169
|
+
* // use player.search() instead
|
|
170
|
+
* player.node.search({ query: "Never gonna give you up by Rick Astley", source: "soundcloud" }, interaction.user);
|
|
171
|
+
* player.node.search({ query: "https://deezer.com/track/123456789" }, interaction.user);
|
|
172
|
+
* ```
|
|
113
173
|
*/
|
|
114
|
-
async search(query, requestUser) {
|
|
174
|
+
async search(query, requestUser, throwOnEmpty = false) {
|
|
115
175
|
const Query = this.NodeManager.LavalinkManager.utils.transformQuery(query);
|
|
116
176
|
this.NodeManager.LavalinkManager.utils.validateQueryString(this, Query.query, Query.source);
|
|
117
177
|
if (Query.source)
|
|
@@ -121,19 +181,25 @@ class LavalinkNode {
|
|
|
121
181
|
}
|
|
122
182
|
let uri = `/loadtracks?identifier=`;
|
|
123
183
|
if (/^https?:\/\//.test(Query.query) || ["http", "https", "link", "uri"].includes(Query.source)) { // if it's a link simply encode it
|
|
124
|
-
uri += encodeURIComponent(
|
|
184
|
+
uri += encodeURIComponent(Query.query);
|
|
125
185
|
}
|
|
126
186
|
else { // if not make a query out of it
|
|
127
187
|
if (Query.source !== "local")
|
|
128
188
|
uri += `${Query.source}:`; // only add the query source string if it's not a local track
|
|
129
189
|
if (Query.source === "ftts")
|
|
130
|
-
uri += `//${encodeURIComponent(
|
|
190
|
+
uri += `//${encodeURIComponent(Query.query)}`;
|
|
131
191
|
else
|
|
132
|
-
uri += encodeURIComponent(
|
|
192
|
+
uri += encodeURIComponent(Query.query);
|
|
133
193
|
}
|
|
134
|
-
const res = await this.request(uri)
|
|
194
|
+
const res = await this.request(uri, (options) => {
|
|
195
|
+
if (typeof query === "object" && typeof query.extraQueryUrlParams?.size === "number" && query.extraQueryUrlParams?.size > 0) {
|
|
196
|
+
options.extraQueryUrlParams = query.extraQueryUrlParams;
|
|
197
|
+
}
|
|
198
|
+
});
|
|
135
199
|
// transform the data which can be Error, Track or Track[] to enfore [Track]
|
|
136
200
|
const resTracks = res.loadType === "playlist" ? res.data?.tracks : res.loadType === "track" ? [res.data] : res.loadType === "search" ? Array.isArray(res.data) ? res.data : [res.data] : [];
|
|
201
|
+
if (throwOnEmpty === true && (res.loadType === "empty" || !resTracks.length))
|
|
202
|
+
throw new Error("Nothing found");
|
|
137
203
|
return {
|
|
138
204
|
loadType: res.loadType,
|
|
139
205
|
exception: res.loadType === "error" ? res.data : null,
|
|
@@ -150,6 +216,19 @@ class LavalinkNode {
|
|
|
150
216
|
tracks: (resTracks.length ? resTracks.map(t => this.NodeManager.LavalinkManager.utils.buildTrack(t, requestUser)) : [])
|
|
151
217
|
};
|
|
152
218
|
}
|
|
219
|
+
/**
|
|
220
|
+
* Search something using the lavaSearchPlugin (filtered searches by types)
|
|
221
|
+
* @param query LavaSearchQuery Object
|
|
222
|
+
* @param requestUser Request User for creating the player(s)
|
|
223
|
+
* @param throwOnEmpty Wether to throw on an empty result or not
|
|
224
|
+
* @returns LavaSearchresult
|
|
225
|
+
*
|
|
226
|
+
* @example
|
|
227
|
+
* ```ts
|
|
228
|
+
* // use player.search() instead
|
|
229
|
+
* player.node.lavaSearch({ types: ["playlist", "album"], query: "Rick Astley", source: "spotify" }, interaction.user);
|
|
230
|
+
* ```
|
|
231
|
+
*/
|
|
153
232
|
async lavaSearch(query, requestUser, throwOnEmpty = false) {
|
|
154
233
|
const Query = this.NodeManager.LavalinkManager.utils.transformLavaSearchQuery(query);
|
|
155
234
|
if (Query.source)
|
|
@@ -163,9 +242,9 @@ class LavalinkNode {
|
|
|
163
242
|
if (!this.info.plugins.find(v => v.name === "lavasrc-plugin"))
|
|
164
243
|
throw new RangeError(`there is no lavasrc-plugin available in the lavalink node: ${this.id}`);
|
|
165
244
|
const { request } = await this.rawRequest(`/loadsearch?query=${Query.source ? `${Query.source}:` : ""}${encodeURIComponent(Query.query)}${Query.types?.length ? `&types=${Query.types.join(",")}` : ""}`);
|
|
166
|
-
if (throwOnEmpty === true)
|
|
167
|
-
throw new Error("Nothing found");
|
|
168
245
|
const res = (request.status === 204 ? {} : await request.json());
|
|
246
|
+
if (throwOnEmpty === true && !Object.entries(res).flat().filter(Boolean).length)
|
|
247
|
+
throw new Error("Nothing found");
|
|
169
248
|
return {
|
|
170
249
|
tracks: res.tracks?.map(v => this.NodeManager.LavalinkManager.utils.buildTrack(v, requestUser)) || [],
|
|
171
250
|
albums: res.albums?.map(v => ({ info: v.info, pluginInfo: v?.plugin || v.pluginInfo, tracks: v.tracks.map(v => this.NodeManager.LavalinkManager.utils.buildTrack(v, requestUser)) })) || [],
|
|
@@ -177,8 +256,14 @@ class LavalinkNode {
|
|
|
177
256
|
}
|
|
178
257
|
/**
|
|
179
258
|
* Update the Player State on the Lavalink Server
|
|
180
|
-
* @param data
|
|
181
|
-
* @returns
|
|
259
|
+
* @param data data to send to lavalink and sync locally
|
|
260
|
+
* @returns result from lavalink
|
|
261
|
+
*
|
|
262
|
+
* @example
|
|
263
|
+
* ```ts
|
|
264
|
+
* // use player.search() instead
|
|
265
|
+
* player.node.updatePlayer({ guildId: player.guildId, playerOptions: { paused: true } }); // example to pause it
|
|
266
|
+
* ```
|
|
182
267
|
*/
|
|
183
268
|
async updatePlayer(data) {
|
|
184
269
|
if (!this.sessionId)
|
|
@@ -200,7 +285,13 @@ class LavalinkNode {
|
|
|
200
285
|
/**
|
|
201
286
|
* Destroys the Player on the Lavalink Server
|
|
202
287
|
* @param guildId
|
|
203
|
-
* @returns
|
|
288
|
+
* @returns request result
|
|
289
|
+
*
|
|
290
|
+
* @example
|
|
291
|
+
* ```ts
|
|
292
|
+
* // use player.destroy() instead
|
|
293
|
+
* player.node.destroyPlayer(player.guildId);
|
|
294
|
+
* ```
|
|
204
295
|
*/
|
|
205
296
|
async destroyPlayer(guildId) {
|
|
206
297
|
if (!this.sessionId)
|
|
@@ -210,7 +301,15 @@ class LavalinkNode {
|
|
|
210
301
|
/**
|
|
211
302
|
* Connect to the Lavalink Node
|
|
212
303
|
* @param sessionId Provide the Session Id of the previous connection, to resume the node and it's player(s)
|
|
213
|
-
* @returns
|
|
304
|
+
* @returns void
|
|
305
|
+
*
|
|
306
|
+
* @example
|
|
307
|
+
* ```ts
|
|
308
|
+
* player.node.connect(); // if provided on bootup in managerOptions#nodes, this will be called automatically when doing lavalink.init()
|
|
309
|
+
*
|
|
310
|
+
* // or connect from a resuming session:
|
|
311
|
+
* player.node.connect("sessionId");
|
|
312
|
+
* ```
|
|
214
313
|
*/
|
|
215
314
|
connect(sessionId) {
|
|
216
315
|
if (this.connected)
|
|
@@ -230,20 +329,37 @@ class LavalinkNode {
|
|
|
230
329
|
this.socket.on("message", this.message.bind(this));
|
|
231
330
|
this.socket.on("error", this.error.bind(this));
|
|
232
331
|
}
|
|
233
|
-
/**
|
|
332
|
+
/**
|
|
333
|
+
* Get the id of the node
|
|
334
|
+
*
|
|
335
|
+
* @example
|
|
336
|
+
* ```ts
|
|
337
|
+
* const nodeId = player.node.id;
|
|
338
|
+
* console.log("node id is: ", nodeId)
|
|
339
|
+
* ```
|
|
340
|
+
*/
|
|
234
341
|
get id() {
|
|
235
342
|
return this.options.id || `${this.options.host}:${this.options.port}`;
|
|
236
343
|
}
|
|
237
344
|
/**
|
|
238
345
|
* Destroys the Node-Connection (Websocket) and all player's of the node
|
|
239
|
-
* @
|
|
346
|
+
* @param destroyReason Destroyreason to use when destroying the players
|
|
347
|
+
* @param deleteNode wether to delete the nodte from the nodes list too, if false it will emit a disconnect. @default true
|
|
348
|
+
* @returns void
|
|
349
|
+
*
|
|
350
|
+
* @example
|
|
351
|
+
* ```ts
|
|
352
|
+
* player.node.destroy("custom Player Destroy Reason", true);
|
|
353
|
+
* ```
|
|
240
354
|
*/
|
|
241
355
|
destroy(destroyReason, deleteNode = true) {
|
|
242
356
|
if (!this.connected)
|
|
243
357
|
return;
|
|
244
|
-
const players = this.NodeManager.LavalinkManager.players.filter(p => p.node.id
|
|
358
|
+
const players = this.NodeManager.LavalinkManager.players.filter(p => p.node.id === this.id);
|
|
245
359
|
if (players)
|
|
246
|
-
players.forEach(p =>
|
|
360
|
+
players.forEach(p => {
|
|
361
|
+
p.destroy(destroyReason || Player_1.DestroyReasons.NodeDestroy);
|
|
362
|
+
});
|
|
247
363
|
this.socket.close(1000, "Node-Destroy");
|
|
248
364
|
this.socket.removeAllListeners();
|
|
249
365
|
this.socket = null;
|
|
@@ -258,14 +374,47 @@ class LavalinkNode {
|
|
|
258
374
|
}
|
|
259
375
|
return;
|
|
260
376
|
}
|
|
261
|
-
/**
|
|
377
|
+
/**
|
|
378
|
+
* Returns if connected to the Node.
|
|
379
|
+
*
|
|
380
|
+
* @example
|
|
381
|
+
* ```ts
|
|
382
|
+
* const isConnected = player.node.connected;
|
|
383
|
+
* console.log("node is connected: ", isConnected ? "yes" : "no")
|
|
384
|
+
* ```
|
|
385
|
+
*/
|
|
262
386
|
get connected() {
|
|
263
387
|
if (!this.socket)
|
|
264
388
|
return false;
|
|
265
389
|
return this.socket.readyState === ws_1.default.OPEN;
|
|
266
390
|
}
|
|
391
|
+
/**
|
|
392
|
+
* Returns the current ConnectionStatus
|
|
393
|
+
*
|
|
394
|
+
* @example
|
|
395
|
+
* ```ts
|
|
396
|
+
* try {
|
|
397
|
+
* const statusOfConnection = player.node.connectionStatus;
|
|
398
|
+
* console.log("node's connection status is:", statusOfConnection)
|
|
399
|
+
* } catch (error) {
|
|
400
|
+
* console.error("no socket available?", error)
|
|
401
|
+
* }
|
|
402
|
+
* ```
|
|
403
|
+
*/
|
|
404
|
+
get connectionStatus() {
|
|
405
|
+
if (!this.socket)
|
|
406
|
+
throw new Error("no websocket was initialized yet");
|
|
407
|
+
return ["CONNECTING", "OPEN", "CLOSING", "CLOSED"][this.socket.readyState] || "UNKNOWN";
|
|
408
|
+
}
|
|
267
409
|
/**
|
|
268
410
|
* Gets all Players of a Node
|
|
411
|
+
* @returns array of players inside of lavalink
|
|
412
|
+
*
|
|
413
|
+
* @example
|
|
414
|
+
* ```ts
|
|
415
|
+
* const node = lavalink.nodes.get("NODEID");
|
|
416
|
+
* const playersOfLavalink = await node?.fetchAllPlayers();
|
|
417
|
+
* ```
|
|
269
418
|
*/
|
|
270
419
|
async fetchAllPlayers() {
|
|
271
420
|
if (!this.sessionId)
|
|
@@ -278,6 +427,13 @@ class LavalinkNode {
|
|
|
278
427
|
}
|
|
279
428
|
/**
|
|
280
429
|
* Gets specific Player Information
|
|
430
|
+
* @returns lavalink player object if player exists on lavalink
|
|
431
|
+
*
|
|
432
|
+
* @example
|
|
433
|
+
* ```ts
|
|
434
|
+
* const node = lavalink.nodes.get("NODEID");
|
|
435
|
+
* const playerInformation = await node?.fetchPlayer("guildId");
|
|
436
|
+
* ```
|
|
281
437
|
*/
|
|
282
438
|
async fetchPlayer(guildId) {
|
|
283
439
|
if (!this.sessionId)
|
|
@@ -288,6 +444,13 @@ class LavalinkNode {
|
|
|
288
444
|
* Updates the session with and enables/disables resuming and timeout
|
|
289
445
|
* @param resuming Whether resuming is enabled for this session or not
|
|
290
446
|
* @param timeout The timeout in seconds (default is 60s)
|
|
447
|
+
* @returns the result of the request
|
|
448
|
+
*
|
|
449
|
+
* @example
|
|
450
|
+
* ```ts
|
|
451
|
+
* const node = player.node || lavalink.nodes.get("NODEID");
|
|
452
|
+
* await node?.updateSession(true, 180e3); // will enable resuming for 180seconds
|
|
453
|
+
* ```
|
|
291
454
|
*/
|
|
292
455
|
async updateSession(resuming, timeout) {
|
|
293
456
|
if (!this.sessionId)
|
|
@@ -312,20 +475,35 @@ class LavalinkNode {
|
|
|
312
475
|
*/
|
|
313
476
|
decode = {
|
|
314
477
|
/**
|
|
315
|
-
* Decode a single track into its info
|
|
316
|
-
* @param encoded
|
|
317
|
-
* @
|
|
478
|
+
* Decode a single track into its info
|
|
479
|
+
* @param encoded valid encoded base64 string from a track
|
|
480
|
+
* @param requester the requesteruser for building the track
|
|
481
|
+
* @returns decoded track from lavalink
|
|
482
|
+
*
|
|
483
|
+
* @example
|
|
484
|
+
* ```ts
|
|
485
|
+
* const encodedBase64 = 'QAACDgMACk5vIERpZ2dpdHkAC0JsYWNrc3RyZWV0AAAAAAAEo4AABjkxNjQ5NgABAB9odHRwczovL2RlZXplci5jb20vdHJhY2svOTE2NDk2AQBpaHR0cHM6Ly9lLWNkbnMtaW1hZ2VzLmR6Y2RuLm5ldC9pbWFnZXMvY292ZXIvZGFlN2EyNjViNzlmYjcxMjc4Y2RlMjUwNDg0OWQ2ZjcvMTAwMHgxMDAwLTAwMDAwMC04MC0wLTAuanBnAQAMVVNJUjE5NjAwOTc4AAZkZWV6ZXIBAChObyBEaWdnaXR5OiBUaGUgVmVyeSBCZXN0IE9mIEJsYWNrc3RyZWV0AQAjaHR0cHM6Ly93d3cuZGVlemVyLmNvbS9hbGJ1bS8xMDMyNTQBACJodHRwczovL3d3dy5kZWV6ZXIuY29tL2FydGlzdC8xODYxAQBqaHR0cHM6Ly9lLWNkbnMtaW1hZ2VzLmR6Y2RuLm5ldC9pbWFnZXMvYXJ0aXN0L2YxNmNhYzM2ZmVjMzkxZjczN2I3ZDQ4MmY1YWM3M2UzLzEwMDB4MTAwMC0wMDAwMDAtODAtMC0wLmpwZwEAT2h0dHBzOi8vY2RuLXByZXZpZXctYS5kemNkbi5uZXQvc3RyZWFtL2MtYTE1Yjg1NzFhYTYyMDBjMDQ0YmY1OWM3NmVkOTEyN2MtNi5tcDMAAAAAAAAAAAA=';
|
|
486
|
+
* const track = await player.node.decode.singleTrack(encodedBase64, interaction.user);
|
|
487
|
+
* ```
|
|
318
488
|
*/
|
|
319
489
|
singleTrack: async (encoded, requester) => {
|
|
320
490
|
if (!encoded)
|
|
321
491
|
throw new SyntaxError("No encoded (Base64 string) was provided");
|
|
322
492
|
// return the decoded + builded track
|
|
323
|
-
return this.NodeManager.LavalinkManager.utils
|
|
493
|
+
return this.NodeManager.LavalinkManager.utils?.buildTrack(await this.request(`/decodetrack?encodedTrack=${encodeURIComponent(encoded.replace(/\s/g, ""))}`), requester);
|
|
324
494
|
},
|
|
325
495
|
/**
|
|
496
|
+
* Decodes multiple tracks into their info
|
|
497
|
+
* @param encodeds valid encoded base64 string array from all tracks
|
|
498
|
+
* @param requester the requesteruser for building the tracks
|
|
499
|
+
* @returns array of all tracks you decoded
|
|
326
500
|
*
|
|
327
|
-
* @
|
|
328
|
-
*
|
|
501
|
+
* @example
|
|
502
|
+
* ```ts
|
|
503
|
+
* const encodedBase64_1 = 'QAACDgMACk5vIERpZ2dpdHkAC0JsYWNrc3RyZWV0AAAAAAAEo4AABjkxNjQ5NgABAB9odHRwczovL2RlZXplci5jb20vdHJhY2svOTE2NDk2AQBpaHR0cHM6Ly9lLWNkbnMtaW1hZ2VzLmR6Y2RuLm5ldC9pbWFnZXMvY292ZXIvZGFlN2EyNjViNzlmYjcxMjc4Y2RlMjUwNDg0OWQ2ZjcvMTAwMHgxMDAwLTAwMDAwMC04MC0wLTAuanBnAQAMVVNJUjE5NjAwOTc4AAZkZWV6ZXIBAChObyBEaWdnaXR5OiBUaGUgVmVyeSBCZXN0IE9mIEJsYWNrc3RyZWV0AQAjaHR0cHM6Ly93d3cuZGVlemVyLmNvbS9hbGJ1bS8xMDMyNTQBACJodHRwczovL3d3dy5kZWV6ZXIuY29tL2FydGlzdC8xODYxAQBqaHR0cHM6Ly9lLWNkbnMtaW1hZ2VzLmR6Y2RuLm5ldC9pbWFnZXMvYXJ0aXN0L2YxNmNhYzM2ZmVjMzkxZjczN2I3ZDQ4MmY1YWM3M2UzLzEwMDB4MTAwMC0wMDAwMDAtODAtMC0wLmpwZwEAT2h0dHBzOi8vY2RuLXByZXZpZXctYS5kemNkbi5uZXQvc3RyZWFtL2MtYTE1Yjg1NzFhYTYyMDBjMDQ0YmY1OWM3NmVkOTEyN2MtNi5tcDMAAAAAAAAAAAA=';
|
|
504
|
+
* const encodedBase64_2 = 'QAABJAMAClRhbGsgYSBMb3QACjQwNHZpbmNlbnQAAAAAAAHr1gBxTzpodHRwczovL2FwaS12Mi5zb3VuZGNsb3VkLmNvbS9tZWRpYS9zb3VuZGNsb3VkOnRyYWNrczo4NTE0MjEwNzYvMzUyYTRiOTAtNzYxOS00M2E5LWJiOGItMjIxMzE0YzFjNjNhL3N0cmVhbS9obHMAAQAsaHR0cHM6Ly9zb3VuZGNsb3VkLmNvbS80MDR2aW5jZW50L3RhbGstYS1sb3QBADpodHRwczovL2kxLnNuZGNkbi5jb20vYXJ0d29ya3MtRTN1ek5Gc0Y4QzBXLTAtb3JpZ2luYWwuanBnAQAMUVpITkExOTg1Nzg0AApzb3VuZGNsb3VkAAAAAAAAAAA=';
|
|
505
|
+
* const tracks = await player.node.decode.multipleTracks([encodedBase64_1, encodedBase64_2], interaction.user);
|
|
506
|
+
* ```
|
|
329
507
|
*/
|
|
330
508
|
multipleTracks: async (encodeds, requester) => {
|
|
331
509
|
if (!Array.isArray(encodeds) || !encodeds.every(v => typeof v === "string" && v.length > 1))
|
|
@@ -341,14 +519,24 @@ class LavalinkNode {
|
|
|
341
519
|
};
|
|
342
520
|
/**
|
|
343
521
|
* Request Lavalink statistics.
|
|
344
|
-
* @returns
|
|
522
|
+
* @returns the lavalink node stats
|
|
523
|
+
*
|
|
524
|
+
* @example
|
|
525
|
+
* ```ts
|
|
526
|
+
* const lavalinkStats = await player.node.fetchStats();
|
|
527
|
+
* ```
|
|
345
528
|
*/
|
|
346
529
|
async fetchStats() {
|
|
347
530
|
return await this.request(`/stats`);
|
|
348
531
|
}
|
|
349
532
|
/**
|
|
350
533
|
* Request Lavalink version.
|
|
351
|
-
* @returns
|
|
534
|
+
* @returns the current used lavalink version
|
|
535
|
+
*
|
|
536
|
+
* @example
|
|
537
|
+
* ```ts
|
|
538
|
+
* const lavalinkVersion = await player.node.fetchVersion();
|
|
539
|
+
* ```
|
|
352
540
|
*/
|
|
353
541
|
async fetchVersion() {
|
|
354
542
|
// need to adjust path for no-prefix version info
|
|
@@ -356,7 +544,14 @@ class LavalinkNode {
|
|
|
356
544
|
}
|
|
357
545
|
/**
|
|
358
546
|
* Request Lavalink information.
|
|
359
|
-
* @returns
|
|
547
|
+
* @returns lavalink info object
|
|
548
|
+
*
|
|
549
|
+
* @example
|
|
550
|
+
* ```ts
|
|
551
|
+
* const lavalinkInfo = await player.node.fetchInfo();
|
|
552
|
+
* const availablePlugins:string[] = lavalinkInfo.plugins.map(plugin => plugin.name);
|
|
553
|
+
* const availableSources:string[] = lavalinkInfo.sourceManagers;
|
|
554
|
+
* ```
|
|
360
555
|
*/
|
|
361
556
|
async fetchInfo() {
|
|
362
557
|
return await this.request(`/info`);
|
|
@@ -366,7 +561,15 @@ class LavalinkNode {
|
|
|
366
561
|
*/
|
|
367
562
|
routePlannerApi = {
|
|
368
563
|
/**
|
|
369
|
-
* Get routplanner Info from Lavalink
|
|
564
|
+
* Get routplanner Info from Lavalink for ip rotation
|
|
565
|
+
* @returns the status of the routeplanner
|
|
566
|
+
*
|
|
567
|
+
* @example
|
|
568
|
+
* ```ts
|
|
569
|
+
* const routePlannerStatus = await player.node.routePlannerApi.getStatus();
|
|
570
|
+
* const usedBlock = routePlannerStatus.details?.ipBlock;
|
|
571
|
+
* const currentIp = routePlannerStatus.currentAddress;
|
|
572
|
+
* ```
|
|
370
573
|
*/
|
|
371
574
|
getStatus: async () => {
|
|
372
575
|
if (!this.sessionId)
|
|
@@ -374,8 +577,14 @@ class LavalinkNode {
|
|
|
374
577
|
return await this.request(`/routeplanner/status`);
|
|
375
578
|
},
|
|
376
579
|
/**
|
|
377
|
-
* Release blacklisted IP address into pool of IPs
|
|
580
|
+
* Release blacklisted IP address into pool of IPs for ip rotation
|
|
378
581
|
* @param address IP address
|
|
582
|
+
* @returns request data of the request
|
|
583
|
+
*
|
|
584
|
+
* @example
|
|
585
|
+
* ```ts
|
|
586
|
+
* await player.node.routePlannerApi.unmarkFailedAddress("ipv6address");
|
|
587
|
+
* ```
|
|
379
588
|
*/
|
|
380
589
|
unmarkFailedAddress: async (address) => {
|
|
381
590
|
if (!this.sessionId)
|
|
@@ -389,6 +598,12 @@ class LavalinkNode {
|
|
|
389
598
|
},
|
|
390
599
|
/**
|
|
391
600
|
* Release all blacklisted IP addresses into pool of IPs
|
|
601
|
+
* @returns request data of the request
|
|
602
|
+
*
|
|
603
|
+
* @example
|
|
604
|
+
* ```ts
|
|
605
|
+
* await player.node.routePlannerApi.unmarkAllFailedAddresses();
|
|
606
|
+
* ```
|
|
392
607
|
*/
|
|
393
608
|
unmarkAllFailedAddresses: async () => {
|
|
394
609
|
if (!this.sessionId)
|
|
@@ -400,7 +615,7 @@ class LavalinkNode {
|
|
|
400
615
|
});
|
|
401
616
|
}
|
|
402
617
|
};
|
|
403
|
-
/**
|
|
618
|
+
/** @private Utils for validating the */
|
|
404
619
|
validate() {
|
|
405
620
|
if (!this.options.authorization)
|
|
406
621
|
throw new SyntaxError("LavalinkNode requires 'authorization'");
|
|
@@ -409,6 +624,12 @@ class LavalinkNode {
|
|
|
409
624
|
if (!this.options.port)
|
|
410
625
|
throw new SyntaxError("LavalinkNode requires 'port'");
|
|
411
626
|
}
|
|
627
|
+
/**
|
|
628
|
+
* Sync the data of the player you make an action to lavalink to
|
|
629
|
+
* @param data data to use to update the player
|
|
630
|
+
* @param res result data from lavalink, to override, if available
|
|
631
|
+
* @returns boolean
|
|
632
|
+
*/
|
|
412
633
|
syncPlayerData(data, res) {
|
|
413
634
|
if (typeof data === "object" && typeof data?.guildId === "string" && typeof data.playerOptions === "object" && Object.keys(data.playerOptions).length > 1) {
|
|
414
635
|
const player = this.NodeManager.LavalinkManager.getPlayer(data.guildId);
|
|
@@ -419,8 +640,9 @@ class LavalinkNode {
|
|
|
419
640
|
player.playing = !data.playerOptions.paused;
|
|
420
641
|
}
|
|
421
642
|
if (typeof data.playerOptions.position === "number") {
|
|
422
|
-
player.position = data.playerOptions.position;
|
|
643
|
+
// player.position = data.playerOptions.position;
|
|
423
644
|
player.lastPosition = data.playerOptions.position;
|
|
645
|
+
player.lastPositionChange = Date.now();
|
|
424
646
|
}
|
|
425
647
|
if (typeof data.playerOptions.voice !== "undefined")
|
|
426
648
|
player.voice = data.playerOptions.voice;
|
|
@@ -471,9 +693,22 @@ class LavalinkNode {
|
|
|
471
693
|
}
|
|
472
694
|
return true;
|
|
473
695
|
}
|
|
696
|
+
/**
|
|
697
|
+
* Get the rest Adress for making requests
|
|
698
|
+
*/
|
|
474
699
|
get restAddress() {
|
|
475
700
|
return `http${this.options.secure ? "s" : ""}://${this.options.host}:${this.options.port}`;
|
|
476
701
|
}
|
|
702
|
+
/**
|
|
703
|
+
* Reconnect to the lavalink node
|
|
704
|
+
* @param instaReconnect @default false wether to instantly try to reconnect
|
|
705
|
+
* @returns void
|
|
706
|
+
*
|
|
707
|
+
* @example
|
|
708
|
+
* ```ts
|
|
709
|
+
* await player.node.reconnect();
|
|
710
|
+
* ```
|
|
711
|
+
*/
|
|
477
712
|
reconnect(instaReconnect = false) {
|
|
478
713
|
if (instaReconnect) {
|
|
479
714
|
if (this.reconnectAttempts >= this.options.retryAmount) {
|
|
@@ -501,6 +736,7 @@ class LavalinkNode {
|
|
|
501
736
|
this.reconnectAttempts++;
|
|
502
737
|
}, this.options.retryDelay || 1000);
|
|
503
738
|
}
|
|
739
|
+
/** @private util function for handling opening events from websocket */
|
|
504
740
|
async open() {
|
|
505
741
|
if (this.reconnectTimeout)
|
|
506
742
|
clearTimeout(this.reconnectTimeout);
|
|
@@ -513,16 +749,19 @@ class LavalinkNode {
|
|
|
513
749
|
}
|
|
514
750
|
this.NodeManager.emit("connect", this);
|
|
515
751
|
}
|
|
752
|
+
/** @private util function for handling closing events from websocket */
|
|
516
753
|
close(code, reason) {
|
|
517
754
|
this.NodeManager.emit("disconnect", this, { code, reason });
|
|
518
755
|
if (code !== 1000 || reason !== "Node-Destroy")
|
|
519
756
|
this.reconnect();
|
|
520
757
|
}
|
|
758
|
+
/** @private util function for handling error events from websocket */
|
|
521
759
|
error(error) {
|
|
522
760
|
if (!error)
|
|
523
761
|
return;
|
|
524
762
|
this.NodeManager.emit("error", this, error);
|
|
525
763
|
}
|
|
764
|
+
/** @private util function for handling message events from websocket */
|
|
526
765
|
async message(d) {
|
|
527
766
|
if (Array.isArray(d))
|
|
528
767
|
d = Buffer.concat(d);
|
|
@@ -543,42 +782,15 @@ class LavalinkNode {
|
|
|
543
782
|
if (!player)
|
|
544
783
|
return;
|
|
545
784
|
const oldPlayer = player?.toJSON();
|
|
546
|
-
|
|
547
|
-
clearInterval(player.get("internal_updateInterval"));
|
|
548
|
-
// override the position
|
|
549
|
-
player.position = payload.state.position || 0;
|
|
785
|
+
player.lastPositionChange = Date.now();
|
|
550
786
|
player.lastPosition = payload.state.position || 0;
|
|
551
787
|
player.connected = payload.state.connected;
|
|
552
788
|
player.ping.ws = payload.state.ping >= 0 ? payload.state.ping : player.ping.ws <= 0 && player.connected ? null : player.ping.ws || 0;
|
|
553
789
|
if (!player.createdTimeStamp && payload.state.time)
|
|
554
790
|
player.createdTimeStamp = payload.state.time;
|
|
555
|
-
if (
|
|
556
|
-
player.
|
|
557
|
-
|
|
558
|
-
if (player.filterManager.filterUpdatedState >= 1) {
|
|
559
|
-
player.filterManager.filterUpdatedState++;
|
|
560
|
-
const maxMins = 8;
|
|
561
|
-
const currentDuration = player.queue.current?.info?.duration || 0;
|
|
562
|
-
if (currentDuration <= maxMins * 6e4 || (0, path_1.isAbsolute)(player.queue.current?.info?.uri)) {
|
|
563
|
-
if (player.filterManager.filterUpdatedState >= ((this.NodeManager.LavalinkManager.options.playerOptions.clientBasedPositionUpdateInterval || 250) > 400 ? 2 : 3)) {
|
|
564
|
-
player.filterManager.filterUpdatedState = 0;
|
|
565
|
-
player.seek(player.position);
|
|
566
|
-
}
|
|
567
|
-
}
|
|
568
|
-
else {
|
|
569
|
-
player.filterManager.filterUpdatedState = 0;
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
}, this.NodeManager.LavalinkManager.options.playerOptions.clientBasedPositionUpdateInterval || 250));
|
|
573
|
-
}
|
|
574
|
-
else {
|
|
575
|
-
if (player.filterManager.filterUpdatedState >= 1) { // if no interval but instafix available, findable via the "filterUpdatedState" property
|
|
576
|
-
const maxMins = 8;
|
|
577
|
-
const currentDuration = player.queue.current?.info?.duration || 0;
|
|
578
|
-
if (currentDuration <= maxMins * 6e4 || (0, path_1.isAbsolute)(player.queue.current?.info?.uri))
|
|
579
|
-
player.seek(player.position);
|
|
580
|
-
player.filterManager.filterUpdatedState = 0;
|
|
581
|
-
}
|
|
791
|
+
if (player.filterManager.filterUpdatedState === true && ((player.queue.current?.info?.duration || 0) <= (player.LavalinkManager.options.advancedOptions.maxFilterFixDuration || 600000) || (0, path_1.isAbsolute)(player.queue.current?.info?.uri))) {
|
|
792
|
+
player.filterManager.filterUpdatedState = false;
|
|
793
|
+
await player.seek(player.position);
|
|
582
794
|
}
|
|
583
795
|
this.NodeManager.LavalinkManager.emit("playerUpdate", oldPlayer, player);
|
|
584
796
|
}
|
|
@@ -598,7 +810,7 @@ class LavalinkNode {
|
|
|
598
810
|
return;
|
|
599
811
|
}
|
|
600
812
|
}
|
|
601
|
-
|
|
813
|
+
/** @private middleware util function for handling all kind of events from websocket */
|
|
602
814
|
async handleEvent(payload) {
|
|
603
815
|
if (!payload.guildId)
|
|
604
816
|
return;
|
|
@@ -625,7 +837,7 @@ class LavalinkNode {
|
|
|
625
837
|
this.SponsorBlockSegmentLoaded(player, player.queue.current, payload);
|
|
626
838
|
break;
|
|
627
839
|
case "SegmentSkipped":
|
|
628
|
-
this.
|
|
840
|
+
this.SponsorBlockSegmentSkipped(player, player.queue.current, payload);
|
|
629
841
|
break;
|
|
630
842
|
case "ChaptersLoaded":
|
|
631
843
|
this.SponsorBlockChaptersLoaded(player, player.queue.current, payload);
|
|
@@ -639,7 +851,7 @@ class LavalinkNode {
|
|
|
639
851
|
}
|
|
640
852
|
return;
|
|
641
853
|
}
|
|
642
|
-
|
|
854
|
+
/** @private util function for handling trackStart event */
|
|
643
855
|
trackStart(player, track, payload) {
|
|
644
856
|
player.playing = true;
|
|
645
857
|
player.paused = false;
|
|
@@ -648,6 +860,7 @@ class LavalinkNode {
|
|
|
648
860
|
return;
|
|
649
861
|
return this.NodeManager.LavalinkManager.emit("trackStart", player, track, payload);
|
|
650
862
|
}
|
|
863
|
+
/** @private util function for handling trackEnd event */
|
|
651
864
|
async trackEnd(player, track, payload) {
|
|
652
865
|
// If there are no songs in the queue
|
|
653
866
|
if (!player.queue.tracks.length && (player.repeatMode === "off" || player.get("internal_stopPlaying")))
|
|
@@ -669,7 +882,7 @@ class LavalinkNode {
|
|
|
669
882
|
// remove tracks from the queue
|
|
670
883
|
if (player.repeatMode !== "track" || player.get("internal_skipped"))
|
|
671
884
|
await (0, Utils_1.queueTrackEnd)(player);
|
|
672
|
-
else if (player.queue.current) { // If there was a current Track already and repeatmode === true, add it to the queue.
|
|
885
|
+
else if (player.queue.current && !player.queue.current?.pluginInfo?.clientData?.previousTrack) { // If there was a current Track already and repeatmode === true, add it to the queue.
|
|
673
886
|
player.queue.previous.unshift(player.queue.current);
|
|
674
887
|
if (player.queue.previous.length > player.queue.options.maxPreviousTracks)
|
|
675
888
|
player.queue.previous.splice(player.queue.options.maxPreviousTracks, player.queue.previous.length);
|
|
@@ -684,6 +897,7 @@ class LavalinkNode {
|
|
|
684
897
|
// play track if autoSkip is true
|
|
685
898
|
return this.NodeManager.LavalinkManager.options.autoSkip && player.play({ noReplace: true });
|
|
686
899
|
}
|
|
900
|
+
/** @private util function for handling trackStuck event */
|
|
687
901
|
async trackStuck(player, track, payload) {
|
|
688
902
|
this.NodeManager.LavalinkManager.emit("trackStuck", player, track, payload);
|
|
689
903
|
// If there are no songs in the queue
|
|
@@ -697,6 +911,7 @@ class LavalinkNode {
|
|
|
697
911
|
// play track if autoSkip is true
|
|
698
912
|
return (this.NodeManager.LavalinkManager.options.autoSkip && player.queue.current) && player.play({ noReplace: true });
|
|
699
913
|
}
|
|
914
|
+
/** @private util function for handling trackError event */
|
|
700
915
|
async trackError(player, track, payload) {
|
|
701
916
|
this.NodeManager.LavalinkManager.emit("trackError", player, track, payload);
|
|
702
917
|
return; // get's handled by trackEnd
|
|
@@ -711,23 +926,37 @@ class LavalinkNode {
|
|
|
711
926
|
// play track if autoSkip is true
|
|
712
927
|
return (this.NodeManager.LavalinkManager.options.autoSkip && player.queue.current) && player.play({ noReplace: true });
|
|
713
928
|
}
|
|
929
|
+
/** @private util function for handling socketClosed event */
|
|
714
930
|
socketClosed(player, payload) {
|
|
715
931
|
return this.NodeManager.LavalinkManager.emit("playerSocketClosed", player, payload);
|
|
716
932
|
}
|
|
717
|
-
|
|
933
|
+
/** @private util function for handling SponsorBlock Segmentloaded event */
|
|
718
934
|
SponsorBlockSegmentLoaded(player, track, payload) {
|
|
719
935
|
return this.NodeManager.LavalinkManager.emit("SegmentsLoaded", player, track, payload);
|
|
720
936
|
}
|
|
721
|
-
|
|
937
|
+
/** @private util function for handling SponsorBlock SegmentSkipped event */
|
|
938
|
+
SponsorBlockSegmentSkipped(player, track, payload) {
|
|
722
939
|
return this.NodeManager.LavalinkManager.emit("SegmentSkipped", player, track, payload);
|
|
723
940
|
}
|
|
941
|
+
/** @private util function for handling SponsorBlock Chaptersloaded event */
|
|
724
942
|
SponsorBlockChaptersLoaded(player, track, payload) {
|
|
725
943
|
return this.NodeManager.LavalinkManager.emit("ChaptersLoaded", player, track, payload);
|
|
726
944
|
}
|
|
945
|
+
/** @private util function for handling SponsorBlock Chaptersstarted event */
|
|
727
946
|
SponsorBlockChapterStarted(player, track, payload) {
|
|
728
947
|
return this.NodeManager.LavalinkManager.emit("ChapterStarted", player, track, payload);
|
|
729
948
|
}
|
|
730
|
-
|
|
949
|
+
/**
|
|
950
|
+
* Get the current sponsorblocks for the sponsorblock plugin
|
|
951
|
+
* @param player passthrough the player
|
|
952
|
+
* @returns sponsorblock seggment from lavalink
|
|
953
|
+
*
|
|
954
|
+
* @example
|
|
955
|
+
* ```ts
|
|
956
|
+
* // use it on the player via player.getSponsorBlock();
|
|
957
|
+
* const sponsorBlockSegments = await player.node.getSponsorBlock(player);
|
|
958
|
+
* ```
|
|
959
|
+
*/
|
|
731
960
|
async getSponsorBlock(player) {
|
|
732
961
|
// no plugin enabled
|
|
733
962
|
if (!this.info.plugins.find(v => v.name === "sponsorblock-plugin"))
|
|
@@ -735,6 +964,17 @@ class LavalinkNode {
|
|
|
735
964
|
// do the request
|
|
736
965
|
return await this.request(`/sessions/${this.sessionId}/players/${player.guildId}/sponsorblock/categories`);
|
|
737
966
|
}
|
|
967
|
+
/**
|
|
968
|
+
* Set the current sponsorblocks for the sponsorblock plugin
|
|
969
|
+
* @param player passthrough the player
|
|
970
|
+
* @returns void
|
|
971
|
+
*
|
|
972
|
+
* @example
|
|
973
|
+
* ```ts
|
|
974
|
+
* // use it on the player via player.setSponsorBlock();
|
|
975
|
+
* const sponsorBlockSegments = await player.node.setSponsorBlock(player, ["sponsor", "selfpromo"]);
|
|
976
|
+
* ```
|
|
977
|
+
*/
|
|
738
978
|
async setSponsorBlock(player, segments = ["sponsor", "selfpromo"]) {
|
|
739
979
|
// no plugin enabled
|
|
740
980
|
if (!this.info.plugins.find(v => v.name === "sponsorblock-plugin"))
|
|
@@ -753,6 +993,17 @@ class LavalinkNode {
|
|
|
753
993
|
});
|
|
754
994
|
return;
|
|
755
995
|
}
|
|
996
|
+
/**
|
|
997
|
+
* Delete the sponsorblock plugins
|
|
998
|
+
* @param player passthrough the player
|
|
999
|
+
* @returns void
|
|
1000
|
+
*
|
|
1001
|
+
* @example
|
|
1002
|
+
* ```ts
|
|
1003
|
+
* // use it on the player via player.deleteSponsorBlock();
|
|
1004
|
+
* const sponsorBlockSegments = await player.node.deleteSponsorBlock(player);
|
|
1005
|
+
* ```
|
|
1006
|
+
*/
|
|
756
1007
|
async deleteSponsorBlock(player) {
|
|
757
1008
|
// no plugin enabled
|
|
758
1009
|
if (!this.info.plugins.find(v => v.name === "sponsorblock-plugin"))
|
|
@@ -763,7 +1014,7 @@ class LavalinkNode {
|
|
|
763
1014
|
});
|
|
764
1015
|
return;
|
|
765
1016
|
}
|
|
766
|
-
|
|
1017
|
+
/** private util function for handling the queue end event */
|
|
767
1018
|
async queueEnd(player, track, payload) {
|
|
768
1019
|
// add previous track to the queue!
|
|
769
1020
|
player.queue.current = null;
|
|
@@ -780,7 +1031,12 @@ class LavalinkNode {
|
|
|
780
1031
|
}
|
|
781
1032
|
}
|
|
782
1033
|
player.set("internal_autoplayStopPlaying", undefined);
|
|
783
|
-
|
|
1034
|
+
if (track && !track?.pluginInfo?.clientData?.previousTrack) { // If there was a current Track already and repeatmode === true, add it to the queue.
|
|
1035
|
+
player.queue.previous.unshift(track);
|
|
1036
|
+
if (player.queue.previous.length > player.queue.options.maxPreviousTracks)
|
|
1037
|
+
player.queue.previous.splice(player.queue.options.maxPreviousTracks, player.queue.previous.length);
|
|
1038
|
+
await player.queue.utils.save();
|
|
1039
|
+
}
|
|
784
1040
|
if (payload?.reason !== "stopped") {
|
|
785
1041
|
await player.queue.utils.save();
|
|
786
1042
|
}
|