lavalink-client 2.3.1 → 2.3.4
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 +35 -22
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/structures/Constants.d.ts +44 -1
- package/dist/cjs/structures/Constants.js +45 -1
- package/dist/cjs/structures/LavalinkManager.js +80 -5
- package/dist/cjs/structures/Node.js +202 -20
- package/dist/cjs/structures/NodeManager.d.ts +1 -1
- package/dist/cjs/structures/NodeManager.js +2 -2
- package/dist/cjs/structures/Player.d.ts +0 -1
- package/dist/cjs/structures/Player.js +98 -8
- package/dist/cjs/structures/Queue.js +29 -2
- package/dist/cjs/structures/Types/Manager.d.ts +25 -0
- package/dist/cjs/structures/Types/Queue.d.ts +1 -1
- package/dist/cjs/structures/Utils.js +89 -23
- package/dist/esm/package.json +3 -0
- package/dist/esm/structures/Constants.d.ts +44 -1
- package/dist/esm/structures/Constants.js +44 -0
- package/dist/esm/structures/LavalinkManager.js +81 -6
- package/dist/esm/structures/Node.js +203 -21
- package/dist/esm/structures/NodeManager.d.ts +1 -1
- package/dist/esm/structures/NodeManager.js +1 -1
- package/dist/esm/structures/Player.d.ts +0 -1
- package/dist/esm/structures/Player.js +98 -8
- package/dist/esm/structures/Queue.js +29 -2
- package/dist/esm/structures/Types/Manager.d.ts +25 -0
- package/dist/esm/structures/Types/Queue.d.ts +1 -1
- package/dist/esm/structures/Utils.js +89 -23
- package/dist/types/structures/Constants.d.ts +44 -1
- package/dist/types/structures/NodeManager.d.ts +1 -1
- package/dist/types/structures/Player.d.ts +0 -1
- package/dist/types/structures/Types/Manager.d.ts +25 -0
- package/dist/types/structures/Types/Queue.d.ts +1 -1
- package/package.json +13 -6
|
@@ -286,11 +286,18 @@ export class Queue {
|
|
|
286
286
|
* ```
|
|
287
287
|
*/
|
|
288
288
|
async remove(removeQueryTrack) {
|
|
289
|
+
const oldStored = typeof this.queueChanges?.tracksRemoved === "function" ? this.utils.toJSON() : null;
|
|
289
290
|
if (typeof removeQueryTrack === "number") {
|
|
290
291
|
const toRemove = this.tracks[removeQueryTrack];
|
|
291
292
|
if (!toRemove)
|
|
292
293
|
return null;
|
|
293
294
|
const removed = this.tracks.splice(removeQueryTrack, 1);
|
|
295
|
+
// Log if available
|
|
296
|
+
if (typeof this.queueChanges?.tracksRemoved === "function")
|
|
297
|
+
try {
|
|
298
|
+
this.queueChanges.tracksRemoved(this.guildId, removed, removeQueryTrack, oldStored, this.utils.toJSON());
|
|
299
|
+
}
|
|
300
|
+
catch (e) { /* */ }
|
|
294
301
|
await this.utils.save();
|
|
295
302
|
return { removed };
|
|
296
303
|
}
|
|
@@ -298,11 +305,18 @@ export class Queue {
|
|
|
298
305
|
if (removeQueryTrack.every(v => typeof v === "number")) {
|
|
299
306
|
const removed = [];
|
|
300
307
|
for (const i of removeQueryTrack) {
|
|
301
|
-
if (this.tracks[i])
|
|
308
|
+
if (this.tracks[i]) {
|
|
302
309
|
removed.push(...this.tracks.splice(i, 1));
|
|
310
|
+
}
|
|
303
311
|
}
|
|
304
312
|
if (!removed.length)
|
|
305
313
|
return null;
|
|
314
|
+
// Log if available
|
|
315
|
+
if (typeof this.queueChanges?.tracksRemoved === "function")
|
|
316
|
+
try {
|
|
317
|
+
this.queueChanges.tracksRemoved(this.guildId, removed, removeQueryTrack, oldStored, this.utils.toJSON());
|
|
318
|
+
}
|
|
319
|
+
catch (e) { /* */ }
|
|
306
320
|
await this.utils.save();
|
|
307
321
|
return { removed };
|
|
308
322
|
}
|
|
@@ -317,9 +331,16 @@ export class Queue {
|
|
|
317
331
|
return null;
|
|
318
332
|
const removed = [];
|
|
319
333
|
for (const { i } of tracksToRemove) {
|
|
320
|
-
if (this.tracks[i])
|
|
334
|
+
if (this.tracks[i]) {
|
|
321
335
|
removed.push(...this.tracks.splice(i, 1));
|
|
336
|
+
}
|
|
322
337
|
}
|
|
338
|
+
// Log if available
|
|
339
|
+
if (typeof this.queueChanges?.tracksRemoved === "function")
|
|
340
|
+
try {
|
|
341
|
+
this.queueChanges.tracksRemoved(this.guildId, removed, tracksToRemove.map(v => v.i), oldStored, this.utils.toJSON());
|
|
342
|
+
}
|
|
343
|
+
catch (e) { /* */ }
|
|
323
344
|
await this.utils.save();
|
|
324
345
|
return { removed };
|
|
325
346
|
}
|
|
@@ -332,6 +353,12 @@ export class Queue {
|
|
|
332
353
|
if (toRemove < 0)
|
|
333
354
|
return null;
|
|
334
355
|
const removed = this.tracks.splice(toRemove, 1);
|
|
356
|
+
// Log if available
|
|
357
|
+
if (typeof this.queueChanges?.tracksRemoved === "function")
|
|
358
|
+
try {
|
|
359
|
+
this.queueChanges.tracksRemoved(this.guildId, removed, toRemove, oldStored, this.utils.toJSON());
|
|
360
|
+
}
|
|
361
|
+
catch (e) { /* */ }
|
|
335
362
|
await this.utils.save();
|
|
336
363
|
return { removed };
|
|
337
364
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { DebugEvents } from "../Constants";
|
|
1
2
|
import type { Player } from "../Player";
|
|
2
3
|
import type { LavalinkNodeOptions } from "./Node";
|
|
3
4
|
import type { DestroyReasonsType, PlayerJson } from "./Player";
|
|
@@ -100,6 +101,19 @@ export interface LavalinkManagerEvents {
|
|
|
100
101
|
* @event Manager#trackError
|
|
101
102
|
*/
|
|
102
103
|
"ChaptersLoaded": (player: Player, track: Track | UnresolvedTrack | null, payload: SponsorBlockChaptersLoaded) => void;
|
|
104
|
+
/**
|
|
105
|
+
* Lavalink-Client Debug Event
|
|
106
|
+
* Emitted for several erros, and logs within lavalink-client, if managerOptions.advancedOptions.enableDebugEvents is true
|
|
107
|
+
* Useful for debugging the lavalink-client
|
|
108
|
+
*
|
|
109
|
+
* @event Manager#debug
|
|
110
|
+
*/
|
|
111
|
+
"debug": (eventKey: DebugEvents, eventData: {
|
|
112
|
+
message: string;
|
|
113
|
+
state: "log" | "warn" | "error";
|
|
114
|
+
error?: Error | string;
|
|
115
|
+
functionLayer: string;
|
|
116
|
+
}) => void;
|
|
103
117
|
}
|
|
104
118
|
/**
|
|
105
119
|
* The Bot client Options needed for the manager
|
|
@@ -131,6 +145,15 @@ export interface ManagerPlayerOptions {
|
|
|
131
145
|
/** Instantly destroy player (overrides autoReconnect) | Don't provide == disable feature*/
|
|
132
146
|
destroyPlayer?: boolean;
|
|
133
147
|
};
|
|
148
|
+
/** Minimum time to play the song before autoPlayFunction is executed (prevents error spamming) Set to 0 to disable it @default 10000 */
|
|
149
|
+
minAutoPlayMs?: number;
|
|
150
|
+
/** Allows you to declare how many tracks are allowed to error/stuck within a time-frame before player is destroyed @default "{threshold: 35000, maxAmount: 3 }" */
|
|
151
|
+
maxErrorsPerTime?: {
|
|
152
|
+
/** The threshold time to count errors (recommended is 35s) */
|
|
153
|
+
threshold: number;
|
|
154
|
+
/** The max amount of errors within the threshold time which are allowed before destroying the player (when errors > maxAmount -> player.destroy()) */
|
|
155
|
+
maxAmount: number;
|
|
156
|
+
};
|
|
134
157
|
onEmptyQueue?: {
|
|
135
158
|
/** Get's executed onEmptyQueue -> You can do any track queue previous transformations, if you add a track to the queue -> it will play it, if not queueEnd will execute! */
|
|
136
159
|
autoPlayFunction?: (player: Player, lastPlayedTrack: Track) => Promise<void>;
|
|
@@ -166,6 +189,8 @@ export interface ManagerOptions {
|
|
|
166
189
|
advancedOptions?: {
|
|
167
190
|
/** Max duration for that the filter fix duration works (in ms) - default is 8mins */
|
|
168
191
|
maxFilterFixDuration?: number;
|
|
192
|
+
/** Enable Debug event */
|
|
193
|
+
enableDebugEvents?: boolean;
|
|
169
194
|
/** optional */
|
|
170
195
|
debugOptions?: {
|
|
171
196
|
/** For logging custom searches */
|
|
@@ -28,7 +28,7 @@ export interface QueueChangesWatcher {
|
|
|
28
28
|
/** get a Value (MUST RETURN UNPARSED!) */
|
|
29
29
|
tracksAdd: (guildId: string, tracks: (Track | UnresolvedTrack)[], position: number, oldStoredQueue: StoredQueue, newStoredQueue: StoredQueue) => void;
|
|
30
30
|
/** Set a value inside a guildId (MUST BE UNPARSED) */
|
|
31
|
-
tracksRemoved: (guildId: string, tracks: (Track | UnresolvedTrack)[], position: number, oldStoredQueue: StoredQueue, newStoredQueue: StoredQueue) => void;
|
|
31
|
+
tracksRemoved: (guildId: string, tracks: (Track | UnresolvedTrack)[], position: number | number[], oldStoredQueue: StoredQueue, newStoredQueue: StoredQueue) => void;
|
|
32
32
|
/** Set a value inside a guildId (MUST BE UNPARSED) */
|
|
33
33
|
shuffled: (guildId: string, oldStoredQueue: StoredQueue, newStoredQueue: StoredQueue) => void;
|
|
34
34
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { URL } from "node:url";
|
|
2
2
|
import { isRegExp } from "node:util/types";
|
|
3
|
+
import { DebugEvents } from "./Constants";
|
|
3
4
|
import { DefaultSources, LavalinkPlugins, SourceLinksRegexes } from "./LavalinkManagerStatics";
|
|
4
5
|
export const TrackSymbol = Symbol("LC-Track");
|
|
5
6
|
export const UnresolvedTrackSymbol = Symbol("LC-Track-Unresolved");
|
|
@@ -71,6 +72,14 @@ export class ManagerUtils {
|
|
|
71
72
|
return r;
|
|
72
73
|
}
|
|
73
74
|
catch (error) {
|
|
75
|
+
if (this.LavalinkManager?.options?.advancedOptions?.enableDebugEvents) {
|
|
76
|
+
this.LavalinkManager?.emit("debug", DebugEvents.BuildTrackError, {
|
|
77
|
+
error: error,
|
|
78
|
+
functionLayer: "ManagerUtils > buildTrack()",
|
|
79
|
+
message: "Error while building track",
|
|
80
|
+
state: "error",
|
|
81
|
+
});
|
|
82
|
+
}
|
|
74
83
|
throw new RangeError(`Argument "data" is not a valid track: ${error.message}`);
|
|
75
84
|
}
|
|
76
85
|
}
|
|
@@ -129,7 +138,14 @@ export class ManagerUtils {
|
|
|
129
138
|
: requester;
|
|
130
139
|
}
|
|
131
140
|
catch (e) {
|
|
132
|
-
|
|
141
|
+
if (this.LavalinkManager?.options?.advancedOptions?.enableDebugEvents) {
|
|
142
|
+
this.LavalinkManager?.emit("debug", DebugEvents.TransformRequesterFunctionFailed, {
|
|
143
|
+
error: e,
|
|
144
|
+
functionLayer: "ManagerUtils > getTransformedRequester()",
|
|
145
|
+
message: "Your custom transformRequesterFunction failed to execute, please check your function for errors.",
|
|
146
|
+
state: "error",
|
|
147
|
+
});
|
|
148
|
+
}
|
|
133
149
|
return requester;
|
|
134
150
|
}
|
|
135
151
|
}
|
|
@@ -195,62 +211,96 @@ export class ManagerUtils {
|
|
|
195
211
|
return typeof data === "object" && !("info" in data) && typeof data.title === "string";
|
|
196
212
|
}
|
|
197
213
|
async getClosestTrack(data, player) {
|
|
198
|
-
|
|
214
|
+
try {
|
|
215
|
+
return getClosestTrack(data, player);
|
|
216
|
+
}
|
|
217
|
+
catch (e) {
|
|
218
|
+
if (this.LavalinkManager?.options?.advancedOptions?.enableDebugEvents) {
|
|
219
|
+
this.LavalinkManager?.emit("debug", DebugEvents.GetClosestTrackFailed, {
|
|
220
|
+
error: e,
|
|
221
|
+
functionLayer: "ManagerUtils > getClosestTrack()",
|
|
222
|
+
message: "Failed to resolve track because the getClosestTrack function failed.",
|
|
223
|
+
state: "error",
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
throw e;
|
|
227
|
+
}
|
|
199
228
|
}
|
|
200
229
|
validateQueryString(node, queryString, sourceString) {
|
|
201
230
|
if (!node.info)
|
|
202
231
|
throw new Error("No Lavalink Node was provided");
|
|
203
232
|
if (!node.info.sourceManagers?.length)
|
|
204
233
|
throw new Error("Lavalink Node, has no sourceManagers enabled");
|
|
234
|
+
if (!queryString.trim().length)
|
|
235
|
+
throw new Error(`Query string is empty, please provide a valid query string.`);
|
|
205
236
|
if (sourceString === "speak" && queryString.length > 100)
|
|
206
|
-
|
|
207
|
-
|
|
237
|
+
throw new Error(`Query is speak, which is limited to 100 characters.`);
|
|
238
|
+
// checks for blacklisted links / domains / queries
|
|
239
|
+
if (this.LavalinkManager.options?.linksBlacklist?.length > 0) {
|
|
240
|
+
if (this.LavalinkManager.options?.advancedOptions?.enableDebugEvents) {
|
|
241
|
+
this.LavalinkManager.emit("debug", DebugEvents.ValidatingBlacklistLinks, {
|
|
242
|
+
state: "log",
|
|
243
|
+
message: `Validating Query against LavalinkManager.options.linksBlacklist, query: "${queryString}"`,
|
|
244
|
+
functionLayer: "(LavalinkNode > node | player) > search() > validateQueryString()",
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
if (this.LavalinkManager.options?.linksBlacklist.some(v => (typeof v === "string" && (queryString.toLowerCase().includes(v.toLowerCase()) || v.toLowerCase().includes(queryString.toLowerCase()))) || isRegExp(v) && v.test(queryString))) {
|
|
208
248
|
throw new Error(`Query string contains a link / word which is blacklisted.`);
|
|
209
249
|
}
|
|
250
|
+
}
|
|
210
251
|
if (!/^https?:\/\//.test(queryString))
|
|
211
252
|
return;
|
|
212
253
|
else if (this.LavalinkManager.options?.linksAllowed === false)
|
|
213
254
|
throw new Error("Using links to make a request is not allowed.");
|
|
214
255
|
// checks for if the query is whitelisted (should only work for links, so it skips the check for no link queries)
|
|
215
|
-
if (this.LavalinkManager.options?.linksWhitelist?.length > 0
|
|
216
|
-
|
|
256
|
+
if (this.LavalinkManager.options?.linksWhitelist?.length > 0) {
|
|
257
|
+
if (this.LavalinkManager.options?.advancedOptions?.enableDebugEvents) {
|
|
258
|
+
this.LavalinkManager.emit("debug", DebugEvents.ValidatingWhitelistLinks, {
|
|
259
|
+
state: "log",
|
|
260
|
+
message: `Link was provided to the Query, validating against LavalinkManager.options.linksWhitelist, query: "${queryString}"`,
|
|
261
|
+
functionLayer: "(LavalinkNode > node | player) > search() > validateQueryString()",
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
if (!this.LavalinkManager.options?.linksWhitelist.some(v => (typeof v === "string" && (queryString.toLowerCase().includes(v.toLowerCase()) || v.toLowerCase().includes(queryString.toLowerCase()))) || isRegExp(v) && v.test(queryString))) {
|
|
265
|
+
throw new Error(`Query string contains a link / word which isn't whitelisted.`);
|
|
266
|
+
}
|
|
217
267
|
}
|
|
218
268
|
// missing links: beam.pro local getyarn.io clypit pornhub reddit ocreamix soundgasm
|
|
219
269
|
if ((SourceLinksRegexes.YoutubeMusicRegex.test(queryString) || SourceLinksRegexes.YoutubeRegex.test(queryString)) && !node.info?.sourceManagers?.includes("youtube")) {
|
|
220
|
-
throw new Error("Lavalink Node has not 'youtube' enabled");
|
|
270
|
+
throw new Error("Query / Link Provided for this Source but Lavalink Node has not 'youtube' enabled");
|
|
221
271
|
}
|
|
222
272
|
if ((SourceLinksRegexes.SoundCloudMobileRegex.test(queryString) || SourceLinksRegexes.SoundCloudRegex.test(queryString)) && !node.info?.sourceManagers?.includes("soundcloud")) {
|
|
223
|
-
throw new Error("Lavalink Node has not 'soundcloud' enabled");
|
|
273
|
+
throw new Error("Query / Link Provided for this Source but Lavalink Node has not 'soundcloud' enabled");
|
|
224
274
|
}
|
|
225
275
|
if (SourceLinksRegexes.bandcamp.test(queryString) && !node.info?.sourceManagers?.includes("bandcamp")) {
|
|
226
|
-
throw new Error("Lavalink Node has not 'bandcamp' enabled (introduced with lavaplayer 2.2.0 or lavalink 4.0.6)");
|
|
276
|
+
throw new Error("Query / Link Provided for this Source but Lavalink Node has not 'bandcamp' enabled (introduced with lavaplayer 2.2.0 or lavalink 4.0.6)");
|
|
227
277
|
}
|
|
228
278
|
if (SourceLinksRegexes.TwitchTv.test(queryString) && !node.info?.sourceManagers?.includes("twitch")) {
|
|
229
|
-
throw new Error("Lavalink Node has not 'twitch' enabled");
|
|
279
|
+
throw new Error("Query / Link Provided for this Source but Lavalink Node has not 'twitch' enabled");
|
|
230
280
|
}
|
|
231
281
|
if (SourceLinksRegexes.vimeo.test(queryString) && !node.info?.sourceManagers?.includes("vimeo")) {
|
|
232
|
-
throw new Error("Lavalink Node has not 'vimeo' enabled");
|
|
282
|
+
throw new Error("Query / Link Provided for this Source but Lavalink Node has not 'vimeo' enabled");
|
|
233
283
|
}
|
|
234
284
|
if (SourceLinksRegexes.tiktok.test(queryString) && !node.info?.sourceManagers?.includes("tiktok")) {
|
|
235
|
-
throw new Error("Lavalink Node has not 'tiktok' enabled");
|
|
285
|
+
throw new Error("Query / Link Provided for this Source but Lavalink Node has not 'tiktok' enabled");
|
|
236
286
|
}
|
|
237
287
|
if (SourceLinksRegexes.mixcloud.test(queryString) && !node.info?.sourceManagers?.includes("mixcloud")) {
|
|
238
|
-
throw new Error("Lavalink Node has not 'mixcloud' enabled");
|
|
288
|
+
throw new Error("Query / Link Provided for this Source but Lavalink Node has not 'mixcloud' enabled");
|
|
239
289
|
}
|
|
240
290
|
if (SourceLinksRegexes.AllSpotifyRegex.test(queryString) && !node.info?.sourceManagers?.includes("spotify")) {
|
|
241
|
-
throw new Error("Lavalink Node has not 'spotify' enabled");
|
|
291
|
+
throw new Error("Query / Link Provided for this Source but Lavalink Node has not 'spotify' enabled");
|
|
242
292
|
}
|
|
243
293
|
if (SourceLinksRegexes.appleMusic.test(queryString) && !node.info?.sourceManagers?.includes("applemusic")) {
|
|
244
|
-
throw new Error("Lavalink Node has not 'applemusic' enabled");
|
|
294
|
+
throw new Error("Query / Link Provided for this Source but Lavalink Node has not 'applemusic' enabled");
|
|
245
295
|
}
|
|
246
296
|
if (SourceLinksRegexes.AllDeezerRegex.test(queryString) && !node.info?.sourceManagers?.includes("deezer")) {
|
|
247
|
-
throw new Error("Lavalink Node has not 'deezer' enabled");
|
|
297
|
+
throw new Error("Query / Link Provided for this Source but Lavalink Node has not 'deezer' enabled");
|
|
248
298
|
}
|
|
249
299
|
if (SourceLinksRegexes.AllDeezerRegex.test(queryString) && node.info?.sourceManagers?.includes("deezer") && !node.info?.sourceManagers?.includes("http")) {
|
|
250
|
-
throw new Error("Lavalink Node has not 'http' enabled, which is required to have 'deezer' to work");
|
|
300
|
+
throw new Error("Query / Link Provided for this Source but Lavalink Node has not 'http' enabled, which is required to have 'deezer' to work");
|
|
251
301
|
}
|
|
252
302
|
if (SourceLinksRegexes.musicYandex.test(queryString) && !node.info?.sourceManagers?.includes("yandexmusic")) {
|
|
253
|
-
throw new Error("Lavalink Node has not 'yandexmusic' enabled");
|
|
303
|
+
throw new Error("Query / Link Provided for this Source but Lavalink Node has not 'yandexmusic' enabled");
|
|
254
304
|
}
|
|
255
305
|
return;
|
|
256
306
|
}
|
|
@@ -371,11 +421,27 @@ export async function queueTrackEnd(player) {
|
|
|
371
421
|
player.queue.tracks.push(player.queue.current);
|
|
372
422
|
// change the current Track to the next upcoming one
|
|
373
423
|
const nextSong = player.queue.tracks.shift();
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
424
|
+
try {
|
|
425
|
+
if (player.LavalinkManager.utils.isUnresolvedTrack(nextSong))
|
|
426
|
+
await nextSong.resolve(player);
|
|
427
|
+
player.queue.current = nextSong || null;
|
|
428
|
+
// save it in the DB
|
|
429
|
+
await player.queue.utils.save();
|
|
430
|
+
}
|
|
431
|
+
catch (error) {
|
|
432
|
+
if (player.LavalinkManager.options?.advancedOptions?.enableDebugEvents) {
|
|
433
|
+
player.LavalinkManager.emit("debug", DebugEvents.PlayerPlayUnresolvedTrackFailed, {
|
|
434
|
+
state: "error",
|
|
435
|
+
error: error,
|
|
436
|
+
message: `queueTrackEnd Util was called, tried to resolve the next track, but failed to find the closest matching song`,
|
|
437
|
+
functionLayer: "Player > play() > resolve currentTrack",
|
|
438
|
+
});
|
|
439
|
+
}
|
|
440
|
+
player.LavalinkManager.emit("trackError", player, player.queue.current, error);
|
|
441
|
+
// try to play the next track if possible
|
|
442
|
+
if (player.LavalinkManager.options?.autoSkipOnResolveError === true && player.queue.tracks[0])
|
|
443
|
+
return queueTrackEnd(player);
|
|
444
|
+
}
|
|
379
445
|
// return the new current Track
|
|
380
446
|
return player.queue.current;
|
|
381
447
|
}
|
|
@@ -1,4 +1,45 @@
|
|
|
1
1
|
import type { AudioOutputs, ChannelMixFilter, EQBand } from "./Types/Filters";
|
|
2
|
+
export declare enum DebugEvents {
|
|
3
|
+
SetSponsorBlock = "SetSponsorBlock",
|
|
4
|
+
DeleteSponsorBlock = "DeleteSponsorBlock",
|
|
5
|
+
TrackEndReplaced = "TrackEndReplaced",
|
|
6
|
+
AutoplayNoSongsAdded = "AutoplayNoSongsAdded",
|
|
7
|
+
AutoplayThresholdSpamLimiter = "AutoplayThresholdSpamLimiter",
|
|
8
|
+
TriggerQueueEmptyInterval = "TriggerQueueEmptyInterval",
|
|
9
|
+
QueueEnded = "QueueEnded",
|
|
10
|
+
TrackStartNewSongsOnly = "TrackStartNewSongsOnly",
|
|
11
|
+
TrackStartNoTrack = "TrackStartNoTrack",
|
|
12
|
+
ResumingFetchingError = "ResumingFetchingError",
|
|
13
|
+
PlayerUpdateNoPlayer = "PlayerUpdateNoPlayer",
|
|
14
|
+
PlayerUpdateFilterFixApply = "PlayerUpdateFilterFixApply",
|
|
15
|
+
PlayerUpdateSuccess = "PlayerUpdateSuccess",
|
|
16
|
+
HeartBeatTriggered = "HeartBeatTriggered",
|
|
17
|
+
NoSocketOnDestroy = "NoSocketOnDestroy",
|
|
18
|
+
SocketTerminateHeartBeatTimeout = "SocketTerminateHeartBeatTimeout",
|
|
19
|
+
TryingConnectWhileConnected = "TryingConnectWhileConnected",
|
|
20
|
+
LavaSearchNothingFound = "LavaSearchNothingFound",
|
|
21
|
+
SearchNothingFound = "SearchNothingFound",
|
|
22
|
+
ValidatingBlacklistLinks = "ValidatingBlacklistLinks",
|
|
23
|
+
ValidatingWhitelistLinks = "ValidatingWhitelistLinks",
|
|
24
|
+
TrackErrorMaxTracksErroredPerTime = "TrackErrorMaxTracksErroredPerTime",
|
|
25
|
+
TrackStuckMaxTracksErroredPerTime = "TrackStuckMaxTracksErroredPerTime",
|
|
26
|
+
PlayerDestroyingSomewhereElse = "PlayerDestroyingSomewhereElse",
|
|
27
|
+
PlayerCreateNodeNotFound = "PlayerCreateNodeNotFound",
|
|
28
|
+
PlayerPlayQueueEmptyTimeoutClear = "PlayerPlayQueueEmptyTimeoutClear",
|
|
29
|
+
PlayerPlayWithTrackReplace = "PlayerPlayWithTrackReplace",
|
|
30
|
+
PlayerPlayUnresolvedTrack = "PlayerPlayUnresolvedTrack",
|
|
31
|
+
PlayerPlayUnresolvedTrackFailed = "PlayerPlayUnresolvedTrackFailed",
|
|
32
|
+
PlayerVolumeAsFilter = "PlayerVolumeAsFilter",
|
|
33
|
+
BandcampSearchLokalEngine = "BandcampSearchLokalEngine",
|
|
34
|
+
PlayerChangeNode = "PlayerChangeNode",
|
|
35
|
+
BuildTrackError = "BuildTrackError",
|
|
36
|
+
TransformRequesterFunctionFailed = "TransformRequesterFunctionFailed",
|
|
37
|
+
GetClosestTrackFailed = "GetClosestTrackFailed",
|
|
38
|
+
PlayerDeleteInsteadOfDestroy = "PlayerDeleteInsteadOfDestroy",
|
|
39
|
+
FailedToConnectToNodes = "FailedToConnectToNodes",
|
|
40
|
+
NoAudioDebug = "NoAudioDebug",
|
|
41
|
+
PlayerAutoReconnect = "PlayerAutoReconnect"
|
|
42
|
+
}
|
|
2
43
|
export declare enum DestroyReasons {
|
|
3
44
|
QueueEmpty = "QueueEmpty",
|
|
4
45
|
NodeDestroy = "NodeDestroy",
|
|
@@ -9,7 +50,9 @@ export declare enum DestroyReasons {
|
|
|
9
50
|
PlayerReconnectFail = "PlayerReconnectFail",
|
|
10
51
|
ChannelDeleted = "ChannelDeleted",
|
|
11
52
|
DisconnectAllNodes = "DisconnectAllNodes",
|
|
12
|
-
ReconnectAllNodes = "ReconnectAllNodes"
|
|
53
|
+
ReconnectAllNodes = "ReconnectAllNodes",
|
|
54
|
+
TrackErrorMaxTracksErroredPerTime = "TrackErrorMaxTracksErroredPerTime",
|
|
55
|
+
TrackStuckMaxTracksErroredPerTime = "TrackStuckMaxTracksErroredPerTime"
|
|
13
56
|
}
|
|
14
57
|
export declare const validSponsorBlocks: string[];
|
|
15
58
|
/** The audio Outputs Data map declaration */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
-
import { EventEmitter } from "
|
|
2
|
+
import { EventEmitter } from "events";
|
|
3
3
|
import { LavalinkNode } from "./Node";
|
|
4
4
|
import { MiniMap } from "./Utils";
|
|
5
5
|
import type { LavalinkNodeIdentifier, LavalinkNodeOptions, NodeManagerEvents } from "./Types/Node";
|
|
@@ -134,7 +134,6 @@ export declare class Player {
|
|
|
134
134
|
* @param repeatMode
|
|
135
135
|
*/
|
|
136
136
|
setRepeatMode(repeatMode: RepeatMode): Promise<this>;
|
|
137
|
-
1: any;
|
|
138
137
|
/**
|
|
139
138
|
* Skip the current song, or a specific amount of songs
|
|
140
139
|
* @param amount provide the index of the next track to skip to
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { DebugEvents } from "../Constants";
|
|
1
2
|
import type { Player } from "../Player";
|
|
2
3
|
import type { LavalinkNodeOptions } from "./Node";
|
|
3
4
|
import type { DestroyReasonsType, PlayerJson } from "./Player";
|
|
@@ -100,6 +101,19 @@ export interface LavalinkManagerEvents {
|
|
|
100
101
|
* @event Manager#trackError
|
|
101
102
|
*/
|
|
102
103
|
"ChaptersLoaded": (player: Player, track: Track | UnresolvedTrack | null, payload: SponsorBlockChaptersLoaded) => void;
|
|
104
|
+
/**
|
|
105
|
+
* Lavalink-Client Debug Event
|
|
106
|
+
* Emitted for several erros, and logs within lavalink-client, if managerOptions.advancedOptions.enableDebugEvents is true
|
|
107
|
+
* Useful for debugging the lavalink-client
|
|
108
|
+
*
|
|
109
|
+
* @event Manager#debug
|
|
110
|
+
*/
|
|
111
|
+
"debug": (eventKey: DebugEvents, eventData: {
|
|
112
|
+
message: string;
|
|
113
|
+
state: "log" | "warn" | "error";
|
|
114
|
+
error?: Error | string;
|
|
115
|
+
functionLayer: string;
|
|
116
|
+
}) => void;
|
|
103
117
|
}
|
|
104
118
|
/**
|
|
105
119
|
* The Bot client Options needed for the manager
|
|
@@ -131,6 +145,15 @@ export interface ManagerPlayerOptions {
|
|
|
131
145
|
/** Instantly destroy player (overrides autoReconnect) | Don't provide == disable feature*/
|
|
132
146
|
destroyPlayer?: boolean;
|
|
133
147
|
};
|
|
148
|
+
/** Minimum time to play the song before autoPlayFunction is executed (prevents error spamming) Set to 0 to disable it @default 10000 */
|
|
149
|
+
minAutoPlayMs?: number;
|
|
150
|
+
/** Allows you to declare how many tracks are allowed to error/stuck within a time-frame before player is destroyed @default "{threshold: 35000, maxAmount: 3 }" */
|
|
151
|
+
maxErrorsPerTime?: {
|
|
152
|
+
/** The threshold time to count errors (recommended is 35s) */
|
|
153
|
+
threshold: number;
|
|
154
|
+
/** The max amount of errors within the threshold time which are allowed before destroying the player (when errors > maxAmount -> player.destroy()) */
|
|
155
|
+
maxAmount: number;
|
|
156
|
+
};
|
|
134
157
|
onEmptyQueue?: {
|
|
135
158
|
/** Get's executed onEmptyQueue -> You can do any track queue previous transformations, if you add a track to the queue -> it will play it, if not queueEnd will execute! */
|
|
136
159
|
autoPlayFunction?: (player: Player, lastPlayedTrack: Track) => Promise<void>;
|
|
@@ -166,6 +189,8 @@ export interface ManagerOptions {
|
|
|
166
189
|
advancedOptions?: {
|
|
167
190
|
/** Max duration for that the filter fix duration works (in ms) - default is 8mins */
|
|
168
191
|
maxFilterFixDuration?: number;
|
|
192
|
+
/** Enable Debug event */
|
|
193
|
+
enableDebugEvents?: boolean;
|
|
169
194
|
/** optional */
|
|
170
195
|
debugOptions?: {
|
|
171
196
|
/** For logging custom searches */
|
|
@@ -28,7 +28,7 @@ export interface QueueChangesWatcher {
|
|
|
28
28
|
/** get a Value (MUST RETURN UNPARSED!) */
|
|
29
29
|
tracksAdd: (guildId: string, tracks: (Track | UnresolvedTrack)[], position: number, oldStoredQueue: StoredQueue, newStoredQueue: StoredQueue) => void;
|
|
30
30
|
/** Set a value inside a guildId (MUST BE UNPARSED) */
|
|
31
|
-
tracksRemoved: (guildId: string, tracks: (Track | UnresolvedTrack)[], position: number, oldStoredQueue: StoredQueue, newStoredQueue: StoredQueue) => void;
|
|
31
|
+
tracksRemoved: (guildId: string, tracks: (Track | UnresolvedTrack)[], position: number | number[], oldStoredQueue: StoredQueue, newStoredQueue: StoredQueue) => void;
|
|
32
32
|
/** Set a value inside a guildId (MUST BE UNPARSED) */
|
|
33
33
|
shuffled: (guildId: string, oldStoredQueue: StoredQueue, newStoredQueue: StoredQueue) => void;
|
|
34
34
|
}
|
package/package.json
CHANGED
|
@@ -1,21 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lavalink-client",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.4",
|
|
4
4
|
"description": "Easy, flexible and feature-rich lavalink@v4 Client. Both for Beginners and Proficients.",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
7
7
|
"types": "dist/types/index.d.js",
|
|
8
8
|
"scripts": {
|
|
9
9
|
"build": "npm run build:cjs && npm run build:esm && npm run build:types",
|
|
10
|
-
"build:cjs": "node tools/cleanup cjs && tsc -p config/tsconfig.cjs.json",
|
|
11
|
-
"build:esm": "node tools/cleanup esm && tsc -p config/tsconfig.esm.json",
|
|
12
|
-
"build:types": "node tools/cleanup types && tsc -p config/tsconfig.types.json",
|
|
10
|
+
"build:cjs": "node tools/cleanup cjs && tsc -p config/tsconfig.cjs.json && tsc-alias -p config/tsconfig.cjs.json && node tools/fixup cjs",
|
|
11
|
+
"build:esm": "node tools/cleanup esm && tsc -p config/tsconfig.esm.json && tsc-alias -p config/tsconfig.esm.json && node tools/fixup esm",
|
|
12
|
+
"build:types": "node tools/cleanup types && tsc -p config/tsconfig.types.json && tsc-alias -p config/tsconfig.types.json",
|
|
13
13
|
"clean": "node tools/cleanup",
|
|
14
14
|
"lint": "eslint .",
|
|
15
15
|
"lint:fix": "npm run lint -- --fix",
|
|
16
16
|
"test": "node -v",
|
|
17
17
|
"docs": "npx typedoc"
|
|
18
18
|
},
|
|
19
|
+
"exports": {
|
|
20
|
+
"require": "./dist/cjs/index.js",
|
|
21
|
+
"import": "./dist/esm/index.js",
|
|
22
|
+
"types": "./dist/types/index.d.js",
|
|
23
|
+
"default": "./dist/cjs/index.js"
|
|
24
|
+
},
|
|
19
25
|
"publishConfig": {
|
|
20
26
|
"access": "public"
|
|
21
27
|
},
|
|
@@ -52,7 +58,7 @@
|
|
|
52
58
|
"@typescript-eslint/eslint-plugin": "^6.4.0",
|
|
53
59
|
"@typescript-eslint/parser": "^6.4.0",
|
|
54
60
|
"eslint": "^8.47.0",
|
|
55
|
-
"
|
|
61
|
+
"tsc-alias": "^1.8.10",
|
|
56
62
|
"typedoc": "^0.25.4",
|
|
57
63
|
"typedoc-theme-hierarchy": "^4.1.2",
|
|
58
64
|
"typescript": "^5.1.6"
|
|
@@ -62,6 +68,7 @@
|
|
|
62
68
|
"ws": "^8.13.0"
|
|
63
69
|
},
|
|
64
70
|
"engines": {
|
|
65
|
-
"node": ">=18.0.0"
|
|
71
|
+
"node": ">=18.0.0",
|
|
72
|
+
"bun": ">=1.0.0"
|
|
66
73
|
}
|
|
67
74
|
}
|