lavalink-client 2.3.1 → 2.3.3
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 +31 -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/Player.d.ts +0 -1
- package/dist/cjs/structures/Player.js +73 -6
- 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 +68 -18
- 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/Player.d.ts +0 -1
- package/dist/esm/structures/Player.js +73 -6
- 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 +68 -18
- package/dist/types/structures/Constants.d.ts +44 -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 +1 -1
|
@@ -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
|
}
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.queueTrackEnd = exports.MiniMap = exports.ManagerUtils = exports.parseLavalinkConnUrl = exports.NodeSymbol = exports.QueueSymbol = exports.UnresolvedTrackSymbol = exports.TrackSymbol = void 0;
|
|
4
4
|
const node_url_1 = require("node:url");
|
|
5
5
|
const types_1 = require("node:util/types");
|
|
6
|
+
const Constants_1 = require("./Constants");
|
|
6
7
|
const LavalinkManagerStatics_1 = require("./LavalinkManagerStatics");
|
|
7
8
|
exports.TrackSymbol = Symbol("LC-Track");
|
|
8
9
|
exports.UnresolvedTrackSymbol = Symbol("LC-Track-Unresolved");
|
|
@@ -75,6 +76,14 @@ class ManagerUtils {
|
|
|
75
76
|
return r;
|
|
76
77
|
}
|
|
77
78
|
catch (error) {
|
|
79
|
+
if (this.LavalinkManager?.options?.advancedOptions?.enableDebugEvents) {
|
|
80
|
+
this.LavalinkManager?.emit("debug", Constants_1.DebugEvents.BuildTrackError, {
|
|
81
|
+
error: error,
|
|
82
|
+
functionLayer: "ManagerUtils > buildTrack()",
|
|
83
|
+
message: "Error while building track",
|
|
84
|
+
state: "error",
|
|
85
|
+
});
|
|
86
|
+
}
|
|
78
87
|
throw new RangeError(`Argument "data" is not a valid track: ${error.message}`);
|
|
79
88
|
}
|
|
80
89
|
}
|
|
@@ -133,7 +142,14 @@ class ManagerUtils {
|
|
|
133
142
|
: requester;
|
|
134
143
|
}
|
|
135
144
|
catch (e) {
|
|
136
|
-
|
|
145
|
+
if (this.LavalinkManager?.options?.advancedOptions?.enableDebugEvents) {
|
|
146
|
+
this.LavalinkManager?.emit("debug", Constants_1.DebugEvents.TransformRequesterFunctionFailed, {
|
|
147
|
+
error: e,
|
|
148
|
+
functionLayer: "ManagerUtils > getTransformedRequester()",
|
|
149
|
+
message: "Your custom transformRequesterFunction failed to execute, please check your function for errors.",
|
|
150
|
+
state: "error",
|
|
151
|
+
});
|
|
152
|
+
}
|
|
137
153
|
return requester;
|
|
138
154
|
}
|
|
139
155
|
}
|
|
@@ -199,62 +215,96 @@ class ManagerUtils {
|
|
|
199
215
|
return typeof data === "object" && !("info" in data) && typeof data.title === "string";
|
|
200
216
|
}
|
|
201
217
|
async getClosestTrack(data, player) {
|
|
202
|
-
|
|
218
|
+
try {
|
|
219
|
+
return getClosestTrack(data, player);
|
|
220
|
+
}
|
|
221
|
+
catch (e) {
|
|
222
|
+
if (this.LavalinkManager?.options?.advancedOptions?.enableDebugEvents) {
|
|
223
|
+
this.LavalinkManager?.emit("debug", Constants_1.DebugEvents.GetClosestTrackFailed, {
|
|
224
|
+
error: e,
|
|
225
|
+
functionLayer: "ManagerUtils > getClosestTrack()",
|
|
226
|
+
message: "Failed to resolve track because the getClosestTrack function failed.",
|
|
227
|
+
state: "error",
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
throw e;
|
|
231
|
+
}
|
|
203
232
|
}
|
|
204
233
|
validateQueryString(node, queryString, sourceString) {
|
|
205
234
|
if (!node.info)
|
|
206
235
|
throw new Error("No Lavalink Node was provided");
|
|
207
236
|
if (!node.info.sourceManagers?.length)
|
|
208
237
|
throw new Error("Lavalink Node, has no sourceManagers enabled");
|
|
238
|
+
if (!queryString.trim().length)
|
|
239
|
+
throw new Error(`Query string is empty, please provide a valid query string.`);
|
|
209
240
|
if (sourceString === "speak" && queryString.length > 100)
|
|
210
|
-
|
|
211
|
-
|
|
241
|
+
throw new Error(`Query is speak, which is limited to 100 characters.`);
|
|
242
|
+
// checks for blacklisted links / domains / queries
|
|
243
|
+
if (this.LavalinkManager.options?.linksBlacklist?.length > 0) {
|
|
244
|
+
if (this.LavalinkManager.options?.advancedOptions?.enableDebugEvents) {
|
|
245
|
+
this.LavalinkManager.emit("debug", Constants_1.DebugEvents.ValidatingBlacklistLinks, {
|
|
246
|
+
state: "log",
|
|
247
|
+
message: `Validating Query against LavalinkManager.options.linksBlacklist, query: "${queryString}"`,
|
|
248
|
+
functionLayer: "(LavalinkNode > node | player) > search() > validateQueryString()",
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
if (this.LavalinkManager.options?.linksBlacklist.some(v => (typeof v === "string" && (queryString.toLowerCase().includes(v.toLowerCase()) || v.toLowerCase().includes(queryString.toLowerCase()))) || (0, types_1.isRegExp)(v) && v.test(queryString))) {
|
|
212
252
|
throw new Error(`Query string contains a link / word which is blacklisted.`);
|
|
213
253
|
}
|
|
254
|
+
}
|
|
214
255
|
if (!/^https?:\/\//.test(queryString))
|
|
215
256
|
return;
|
|
216
257
|
else if (this.LavalinkManager.options?.linksAllowed === false)
|
|
217
258
|
throw new Error("Using links to make a request is not allowed.");
|
|
218
259
|
// checks for if the query is whitelisted (should only work for links, so it skips the check for no link queries)
|
|
219
|
-
if (this.LavalinkManager.options?.linksWhitelist?.length > 0
|
|
220
|
-
|
|
260
|
+
if (this.LavalinkManager.options?.linksWhitelist?.length > 0) {
|
|
261
|
+
if (this.LavalinkManager.options?.advancedOptions?.enableDebugEvents) {
|
|
262
|
+
this.LavalinkManager.emit("debug", Constants_1.DebugEvents.ValidatingWhitelistLinks, {
|
|
263
|
+
state: "log",
|
|
264
|
+
message: `Link was provided to the Query, validating against LavalinkManager.options.linksWhitelist, query: "${queryString}"`,
|
|
265
|
+
functionLayer: "(LavalinkNode > node | player) > search() > validateQueryString()",
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
if (!this.LavalinkManager.options?.linksWhitelist.some(v => (typeof v === "string" && (queryString.toLowerCase().includes(v.toLowerCase()) || v.toLowerCase().includes(queryString.toLowerCase()))) || (0, types_1.isRegExp)(v) && v.test(queryString))) {
|
|
269
|
+
throw new Error(`Query string contains a link / word which isn't whitelisted.`);
|
|
270
|
+
}
|
|
221
271
|
}
|
|
222
272
|
// missing links: beam.pro local getyarn.io clypit pornhub reddit ocreamix soundgasm
|
|
223
273
|
if ((LavalinkManagerStatics_1.SourceLinksRegexes.YoutubeMusicRegex.test(queryString) || LavalinkManagerStatics_1.SourceLinksRegexes.YoutubeRegex.test(queryString)) && !node.info?.sourceManagers?.includes("youtube")) {
|
|
224
|
-
throw new Error("Lavalink Node has not 'youtube' enabled");
|
|
274
|
+
throw new Error("Query / Link Provided for this Source but Lavalink Node has not 'youtube' enabled");
|
|
225
275
|
}
|
|
226
276
|
if ((LavalinkManagerStatics_1.SourceLinksRegexes.SoundCloudMobileRegex.test(queryString) || LavalinkManagerStatics_1.SourceLinksRegexes.SoundCloudRegex.test(queryString)) && !node.info?.sourceManagers?.includes("soundcloud")) {
|
|
227
|
-
throw new Error("Lavalink Node has not 'soundcloud' enabled");
|
|
277
|
+
throw new Error("Query / Link Provided for this Source but Lavalink Node has not 'soundcloud' enabled");
|
|
228
278
|
}
|
|
229
279
|
if (LavalinkManagerStatics_1.SourceLinksRegexes.bandcamp.test(queryString) && !node.info?.sourceManagers?.includes("bandcamp")) {
|
|
230
|
-
throw new Error("Lavalink Node has not 'bandcamp' enabled (introduced with lavaplayer 2.2.0 or lavalink 4.0.6)");
|
|
280
|
+
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)");
|
|
231
281
|
}
|
|
232
282
|
if (LavalinkManagerStatics_1.SourceLinksRegexes.TwitchTv.test(queryString) && !node.info?.sourceManagers?.includes("twitch")) {
|
|
233
|
-
throw new Error("Lavalink Node has not 'twitch' enabled");
|
|
283
|
+
throw new Error("Query / Link Provided for this Source but Lavalink Node has not 'twitch' enabled");
|
|
234
284
|
}
|
|
235
285
|
if (LavalinkManagerStatics_1.SourceLinksRegexes.vimeo.test(queryString) && !node.info?.sourceManagers?.includes("vimeo")) {
|
|
236
|
-
throw new Error("Lavalink Node has not 'vimeo' enabled");
|
|
286
|
+
throw new Error("Query / Link Provided for this Source but Lavalink Node has not 'vimeo' enabled");
|
|
237
287
|
}
|
|
238
288
|
if (LavalinkManagerStatics_1.SourceLinksRegexes.tiktok.test(queryString) && !node.info?.sourceManagers?.includes("tiktok")) {
|
|
239
|
-
throw new Error("Lavalink Node has not 'tiktok' enabled");
|
|
289
|
+
throw new Error("Query / Link Provided for this Source but Lavalink Node has not 'tiktok' enabled");
|
|
240
290
|
}
|
|
241
291
|
if (LavalinkManagerStatics_1.SourceLinksRegexes.mixcloud.test(queryString) && !node.info?.sourceManagers?.includes("mixcloud")) {
|
|
242
|
-
throw new Error("Lavalink Node has not 'mixcloud' enabled");
|
|
292
|
+
throw new Error("Query / Link Provided for this Source but Lavalink Node has not 'mixcloud' enabled");
|
|
243
293
|
}
|
|
244
294
|
if (LavalinkManagerStatics_1.SourceLinksRegexes.AllSpotifyRegex.test(queryString) && !node.info?.sourceManagers?.includes("spotify")) {
|
|
245
|
-
throw new Error("Lavalink Node has not 'spotify' enabled");
|
|
295
|
+
throw new Error("Query / Link Provided for this Source but Lavalink Node has not 'spotify' enabled");
|
|
246
296
|
}
|
|
247
297
|
if (LavalinkManagerStatics_1.SourceLinksRegexes.appleMusic.test(queryString) && !node.info?.sourceManagers?.includes("applemusic")) {
|
|
248
|
-
throw new Error("Lavalink Node has not 'applemusic' enabled");
|
|
298
|
+
throw new Error("Query / Link Provided for this Source but Lavalink Node has not 'applemusic' enabled");
|
|
249
299
|
}
|
|
250
300
|
if (LavalinkManagerStatics_1.SourceLinksRegexes.AllDeezerRegex.test(queryString) && !node.info?.sourceManagers?.includes("deezer")) {
|
|
251
|
-
throw new Error("Lavalink Node has not 'deezer' enabled");
|
|
301
|
+
throw new Error("Query / Link Provided for this Source but Lavalink Node has not 'deezer' enabled");
|
|
252
302
|
}
|
|
253
303
|
if (LavalinkManagerStatics_1.SourceLinksRegexes.AllDeezerRegex.test(queryString) && node.info?.sourceManagers?.includes("deezer") && !node.info?.sourceManagers?.includes("http")) {
|
|
254
|
-
throw new Error("Lavalink Node has not 'http' enabled, which is required to have 'deezer' to work");
|
|
304
|
+
throw new Error("Query / Link Provided for this Source but Lavalink Node has not 'http' enabled, which is required to have 'deezer' to work");
|
|
255
305
|
}
|
|
256
306
|
if (LavalinkManagerStatics_1.SourceLinksRegexes.musicYandex.test(queryString) && !node.info?.sourceManagers?.includes("yandexmusic")) {
|
|
257
|
-
throw new Error("Lavalink Node has not 'yandexmusic' enabled");
|
|
307
|
+
throw new Error("Query / Link Provided for this Source but Lavalink Node has not 'yandexmusic' enabled");
|
|
258
308
|
}
|
|
259
309
|
return;
|
|
260
310
|
}
|
|
@@ -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,3 +1,45 @@
|
|
|
1
|
+
export var DebugEvents;
|
|
2
|
+
(function (DebugEvents) {
|
|
3
|
+
DebugEvents["SetSponsorBlock"] = "SetSponsorBlock";
|
|
4
|
+
DebugEvents["DeleteSponsorBlock"] = "DeleteSponsorBlock";
|
|
5
|
+
DebugEvents["TrackEndReplaced"] = "TrackEndReplaced";
|
|
6
|
+
DebugEvents["AutoplayNoSongsAdded"] = "AutoplayNoSongsAdded";
|
|
7
|
+
DebugEvents["AutoplayThresholdSpamLimiter"] = "AutoplayThresholdSpamLimiter";
|
|
8
|
+
DebugEvents["TriggerQueueEmptyInterval"] = "TriggerQueueEmptyInterval";
|
|
9
|
+
DebugEvents["QueueEnded"] = "QueueEnded";
|
|
10
|
+
DebugEvents["TrackStartNewSongsOnly"] = "TrackStartNewSongsOnly";
|
|
11
|
+
DebugEvents["TrackStartNoTrack"] = "TrackStartNoTrack";
|
|
12
|
+
DebugEvents["ResumingFetchingError"] = "ResumingFetchingError";
|
|
13
|
+
DebugEvents["PlayerUpdateNoPlayer"] = "PlayerUpdateNoPlayer";
|
|
14
|
+
DebugEvents["PlayerUpdateFilterFixApply"] = "PlayerUpdateFilterFixApply";
|
|
15
|
+
DebugEvents["PlayerUpdateSuccess"] = "PlayerUpdateSuccess";
|
|
16
|
+
DebugEvents["HeartBeatTriggered"] = "HeartBeatTriggered";
|
|
17
|
+
DebugEvents["NoSocketOnDestroy"] = "NoSocketOnDestroy";
|
|
18
|
+
DebugEvents["SocketTerminateHeartBeatTimeout"] = "SocketTerminateHeartBeatTimeout";
|
|
19
|
+
DebugEvents["TryingConnectWhileConnected"] = "TryingConnectWhileConnected";
|
|
20
|
+
DebugEvents["LavaSearchNothingFound"] = "LavaSearchNothingFound";
|
|
21
|
+
DebugEvents["SearchNothingFound"] = "SearchNothingFound";
|
|
22
|
+
DebugEvents["ValidatingBlacklistLinks"] = "ValidatingBlacklistLinks";
|
|
23
|
+
DebugEvents["ValidatingWhitelistLinks"] = "ValidatingWhitelistLinks";
|
|
24
|
+
DebugEvents["TrackErrorMaxTracksErroredPerTime"] = "TrackErrorMaxTracksErroredPerTime";
|
|
25
|
+
DebugEvents["TrackStuckMaxTracksErroredPerTime"] = "TrackStuckMaxTracksErroredPerTime";
|
|
26
|
+
DebugEvents["PlayerDestroyingSomewhereElse"] = "PlayerDestroyingSomewhereElse";
|
|
27
|
+
DebugEvents["PlayerCreateNodeNotFound"] = "PlayerCreateNodeNotFound";
|
|
28
|
+
DebugEvents["PlayerPlayQueueEmptyTimeoutClear"] = "PlayerPlayQueueEmptyTimeoutClear";
|
|
29
|
+
DebugEvents["PlayerPlayWithTrackReplace"] = "PlayerPlayWithTrackReplace";
|
|
30
|
+
DebugEvents["PlayerPlayUnresolvedTrack"] = "PlayerPlayUnresolvedTrack";
|
|
31
|
+
DebugEvents["PlayerPlayUnresolvedTrackFailed"] = "PlayerPlayUnresolvedTrackFailed";
|
|
32
|
+
DebugEvents["PlayerVolumeAsFilter"] = "PlayerVolumeAsFilter";
|
|
33
|
+
DebugEvents["BandcampSearchLokalEngine"] = "BandcampSearchLokalEngine";
|
|
34
|
+
DebugEvents["PlayerChangeNode"] = "PlayerChangeNode";
|
|
35
|
+
DebugEvents["BuildTrackError"] = "BuildTrackError";
|
|
36
|
+
DebugEvents["TransformRequesterFunctionFailed"] = "TransformRequesterFunctionFailed";
|
|
37
|
+
DebugEvents["GetClosestTrackFailed"] = "GetClosestTrackFailed";
|
|
38
|
+
DebugEvents["PlayerDeleteInsteadOfDestroy"] = "PlayerDeleteInsteadOfDestroy";
|
|
39
|
+
DebugEvents["FailedToConnectToNodes"] = "FailedToConnectToNodes";
|
|
40
|
+
DebugEvents["NoAudioDebug"] = "NoAudioDebug";
|
|
41
|
+
DebugEvents["PlayerAutoReconnect"] = "PlayerAutoReconnect";
|
|
42
|
+
})(DebugEvents || (DebugEvents = {}));
|
|
1
43
|
export var DestroyReasons;
|
|
2
44
|
(function (DestroyReasons) {
|
|
3
45
|
DestroyReasons["QueueEmpty"] = "QueueEmpty";
|
|
@@ -10,6 +52,8 @@ export var DestroyReasons;
|
|
|
10
52
|
DestroyReasons["ChannelDeleted"] = "ChannelDeleted";
|
|
11
53
|
DestroyReasons["DisconnectAllNodes"] = "DisconnectAllNodes";
|
|
12
54
|
DestroyReasons["ReconnectAllNodes"] = "ReconnectAllNodes";
|
|
55
|
+
DestroyReasons["TrackErrorMaxTracksErroredPerTime"] = "TrackErrorMaxTracksErroredPerTime";
|
|
56
|
+
DestroyReasons["TrackStuckMaxTracksErroredPerTime"] = "TrackStuckMaxTracksErroredPerTime";
|
|
13
57
|
})(DestroyReasons || (DestroyReasons = {}));
|
|
14
58
|
;
|
|
15
59
|
export const validSponsorBlocks = ["sponsor", "selfpromo", "interaction", "intro", "outro", "preview", "music_offtopic", "filler"];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { EventEmitter } from "events";
|
|
2
|
-
import { DestroyReasons } from "./Constants";
|
|
2
|
+
import { DebugEvents, DestroyReasons } from "./Constants";
|
|
3
3
|
import { NodeManager } from "./NodeManager";
|
|
4
4
|
import { Player } from "./Player";
|
|
5
5
|
import { DefaultQueueStore } from "./Queue";
|
|
@@ -89,9 +89,15 @@ export class LavalinkManager extends EventEmitter {
|
|
|
89
89
|
volumeDecrementer: options?.playerOptions?.volumeDecrementer ?? 1,
|
|
90
90
|
requesterTransformer: options?.playerOptions?.requesterTransformer ?? null,
|
|
91
91
|
useUnresolvedData: options?.playerOptions?.useUnresolvedData ?? false,
|
|
92
|
+
minAutoPlayMs: options?.playerOptions?.minAutoPlayMs ?? 10000,
|
|
93
|
+
maxErrorsPerTime: {
|
|
94
|
+
threshold: options?.playerOptions?.maxErrorsPerTime?.threshold ?? 35000,
|
|
95
|
+
maxAmount: options?.playerOptions?.maxErrorsPerTime?.maxAmount ?? 3
|
|
96
|
+
}
|
|
92
97
|
},
|
|
93
98
|
linksWhitelist: options?.linksWhitelist ?? [],
|
|
94
99
|
linksBlacklist: options?.linksBlacklist ?? [],
|
|
100
|
+
linksAllowed: options?.linksAllowed ?? true,
|
|
95
101
|
autoSkip: options?.autoSkip ?? true,
|
|
96
102
|
autoSkipOnResolveError: options?.autoSkipOnResolveError ?? true,
|
|
97
103
|
emitNewSongsOnly: options?.emitNewSongsOnly ?? false,
|
|
@@ -101,6 +107,7 @@ export class LavalinkManager extends EventEmitter {
|
|
|
101
107
|
queueStore: options?.queueOptions?.queueStore ?? new DefaultQueueStore(),
|
|
102
108
|
},
|
|
103
109
|
advancedOptions: {
|
|
110
|
+
enableDebugEvents: options?.advancedOptions?.enableDebugEvents ?? false,
|
|
104
111
|
maxFilterFixDuration: options?.advancedOptions?.maxFilterFixDuration ?? 600000,
|
|
105
112
|
debugOptions: {
|
|
106
113
|
logCustomSearches: options?.advancedOptions?.debugOptions?.logCustomSearches ?? false,
|
|
@@ -304,8 +311,13 @@ export class LavalinkManager extends EventEmitter {
|
|
|
304
311
|
if (oldPlayer.voiceChannelId === "string" && oldPlayer.connected && !oldPlayer.get("internal_destroywithoutdisconnect")) {
|
|
305
312
|
if (!this.options?.advancedOptions?.debugOptions?.playerDestroy?.dontThrowError)
|
|
306
313
|
throw new Error(`Use Player#destroy() not LavalinkManager#deletePlayer() to stop the Player ${JSON.stringify(oldPlayer.toJSON?.())}`);
|
|
307
|
-
else
|
|
308
|
-
|
|
314
|
+
else if (this.options?.advancedOptions?.enableDebugEvents) {
|
|
315
|
+
this.emit("debug", DebugEvents.PlayerDeleteInsteadOfDestroy, {
|
|
316
|
+
state: "warn",
|
|
317
|
+
message: "Use Player#destroy() not LavalinkManager#deletePlayer() to stop the Player",
|
|
318
|
+
functionLayer: "LavalinkManager > deletePlayer()",
|
|
319
|
+
});
|
|
320
|
+
}
|
|
309
321
|
}
|
|
310
322
|
return this.players.delete(guildId);
|
|
311
323
|
}
|
|
@@ -358,8 +370,13 @@ export class LavalinkManager extends EventEmitter {
|
|
|
358
370
|
}
|
|
359
371
|
if (success > 0)
|
|
360
372
|
this.initiated = true;
|
|
361
|
-
else
|
|
362
|
-
|
|
373
|
+
else if (this.options?.advancedOptions?.enableDebugEvents) {
|
|
374
|
+
this.emit("debug", DebugEvents.FailedToConnectToNodes, {
|
|
375
|
+
state: "error",
|
|
376
|
+
message: "Failed to connect to at least 1 Node",
|
|
377
|
+
functionLayer: "LavalinkManager > init()",
|
|
378
|
+
});
|
|
379
|
+
}
|
|
363
380
|
return this;
|
|
364
381
|
}
|
|
365
382
|
/**
|
|
@@ -379,11 +396,25 @@ export class LavalinkManager extends EventEmitter {
|
|
|
379
396
|
*/
|
|
380
397
|
async sendRawData(data) {
|
|
381
398
|
if (!this.initiated) {
|
|
399
|
+
if (this.options?.advancedOptions?.enableDebugEvents) {
|
|
400
|
+
this.emit("debug", DebugEvents.NoAudioDebug, {
|
|
401
|
+
state: "log",
|
|
402
|
+
message: "Manager is not initated yet",
|
|
403
|
+
functionLayer: "LavalinkManager > sendRawData()",
|
|
404
|
+
});
|
|
405
|
+
}
|
|
382
406
|
if (this.options?.advancedOptions?.debugOptions?.noAudio === true)
|
|
383
407
|
console.debug("Lavalink-Client-Debug | NO-AUDIO [::] sendRawData function, manager is not initated yet");
|
|
384
408
|
return;
|
|
385
409
|
}
|
|
386
410
|
if (!("t" in data)) {
|
|
411
|
+
if (this.options?.advancedOptions?.enableDebugEvents) {
|
|
412
|
+
this.emit("debug", DebugEvents.NoAudioDebug, {
|
|
413
|
+
state: "error",
|
|
414
|
+
message: "No 't' in payload-data of the raw event:",
|
|
415
|
+
functionLayer: "LavalinkManager > sendRawData()",
|
|
416
|
+
});
|
|
417
|
+
}
|
|
387
418
|
if (this.options?.advancedOptions?.debugOptions?.noAudio === true)
|
|
388
419
|
console.debug("Lavalink-Client-Debug | NO-AUDIO [::] sendRawData function, no 't' in payload-data of the raw event:", data);
|
|
389
420
|
return;
|
|
@@ -401,22 +432,50 @@ export class LavalinkManager extends EventEmitter {
|
|
|
401
432
|
if (["VOICE_STATE_UPDATE", "VOICE_SERVER_UPDATE"].includes(data.t)) {
|
|
402
433
|
const update = ("d" in data ? data.d : data);
|
|
403
434
|
if (!update) {
|
|
435
|
+
if (this.options?.advancedOptions?.enableDebugEvents) {
|
|
436
|
+
this.emit("debug", DebugEvents.NoAudioDebug, {
|
|
437
|
+
state: "warn",
|
|
438
|
+
message: `No Update data found in payload :: ${JSON.stringify(data, null, 2)}`,
|
|
439
|
+
functionLayer: "LavalinkManager > sendRawData()",
|
|
440
|
+
});
|
|
441
|
+
}
|
|
404
442
|
if (this.options?.advancedOptions?.debugOptions?.noAudio === true)
|
|
405
443
|
console.debug("Lavalink-Client-Debug | NO-AUDIO [::] sendRawData function, no update data found in payload:", data);
|
|
406
444
|
return;
|
|
407
445
|
}
|
|
408
446
|
if (!("token" in update) && !("session_id" in update)) {
|
|
447
|
+
if (this.options?.advancedOptions?.enableDebugEvents) {
|
|
448
|
+
this.emit("debug", DebugEvents.NoAudioDebug, {
|
|
449
|
+
state: "error",
|
|
450
|
+
message: `No 'token' nor 'session_id' found in payload :: ${JSON.stringify(data, null, 2)}`,
|
|
451
|
+
functionLayer: "LavalinkManager > sendRawData()",
|
|
452
|
+
});
|
|
453
|
+
}
|
|
409
454
|
if (this.options?.advancedOptions?.debugOptions?.noAudio === true)
|
|
410
455
|
console.debug("Lavalink-Client-Debug | NO-AUDIO [::] sendRawData function, no 'token' nor 'session_id' found in payload:", data);
|
|
411
456
|
return;
|
|
412
457
|
}
|
|
413
458
|
const player = this.getPlayer(update.guild_id);
|
|
414
459
|
if (!player) {
|
|
460
|
+
if (this.options?.advancedOptions?.enableDebugEvents) {
|
|
461
|
+
this.emit("debug", DebugEvents.NoAudioDebug, {
|
|
462
|
+
state: "warn",
|
|
463
|
+
message: `No Lavalink Player found via key: 'guild_id' of update-data :: ${JSON.stringify(update, null, 2)}`,
|
|
464
|
+
functionLayer: "LavalinkManager > sendRawData()",
|
|
465
|
+
});
|
|
466
|
+
}
|
|
415
467
|
if (this.options?.advancedOptions?.debugOptions?.noAudio === true)
|
|
416
468
|
console.debug("Lavalink-Client-Debug | NO-AUDIO [::] sendRawData function, No Lavalink Player found via key: 'guild_id' of update-data:", update);
|
|
417
469
|
return;
|
|
418
470
|
}
|
|
419
471
|
if (player.get("internal_destroystatus") === true) {
|
|
472
|
+
if (this.options?.advancedOptions?.enableDebugEvents) {
|
|
473
|
+
this.emit("debug", DebugEvents.NoAudioDebug, {
|
|
474
|
+
state: "warn",
|
|
475
|
+
message: `Player is in a destroying state. can't signal the voice states`,
|
|
476
|
+
functionLayer: "LavalinkManager > sendRawData()",
|
|
477
|
+
});
|
|
478
|
+
}
|
|
420
479
|
if (this.options?.advancedOptions?.debugOptions?.noAudio === true)
|
|
421
480
|
console.debug("Lavalink-Client-Debug | NO-AUDIO [::] sendRawData function, Player is in a destroying state. can't signal the voice states");
|
|
422
481
|
return;
|
|
@@ -434,12 +493,24 @@ export class LavalinkManager extends EventEmitter {
|
|
|
434
493
|
}
|
|
435
494
|
}
|
|
436
495
|
});
|
|
496
|
+
if (this.options?.advancedOptions?.enableDebugEvents) {
|
|
497
|
+
this.emit("debug", DebugEvents.NoAudioDebug, {
|
|
498
|
+
state: "log",
|
|
499
|
+
message: `Sent updatePlayer for voice token session :: ${JSON.stringify({ voice: { token: update.token, endpoint: update.endpoint, sessionId: player.voice?.sessionId, }, update }, null, 2)}`,
|
|
500
|
+
functionLayer: "LavalinkManager > sendRawData()",
|
|
501
|
+
});
|
|
502
|
+
}
|
|
437
503
|
if (this.options?.advancedOptions?.debugOptions?.noAudio === true)
|
|
438
504
|
console.debug("Lavalink-Client-Debug | NO-AUDIO [::] sendRawData function, Sent updatePlayer for voice token session", { voice: { token: update.token, endpoint: update.endpoint, sessionId: player.voice?.sessionId, } });
|
|
439
505
|
return;
|
|
440
506
|
}
|
|
441
507
|
/* voice state update */
|
|
442
508
|
if (update.user_id !== this.options?.client.id) {
|
|
509
|
+
this.emit("debug", DebugEvents.NoAudioDebug, {
|
|
510
|
+
state: "warn",
|
|
511
|
+
message: `voice update user is not equal to provided client id of the LavalinkManager.options.client.id :: user: "${update.user_id}" manager client id: "${this.options?.client.id}"`,
|
|
512
|
+
functionLayer: "LavalinkManager > sendRawData()",
|
|
513
|
+
});
|
|
443
514
|
if (this.options?.advancedOptions?.debugOptions?.noAudio === true)
|
|
444
515
|
console.debug("Lavalink-Client-Debug | NO-AUDIO [::] sendRawData function, voice update user is not equal to provided client id of the manageroptions#client#id", "user:", update.user_id, "manager client id:", this.options?.client.id);
|
|
445
516
|
return;
|
|
@@ -458,7 +529,11 @@ export class LavalinkManager extends EventEmitter {
|
|
|
458
529
|
if (this.options?.playerOptions?.onDisconnect?.autoReconnect === true) {
|
|
459
530
|
try {
|
|
460
531
|
const positionPrevios = player.position;
|
|
461
|
-
|
|
532
|
+
this.emit("debug", DebugEvents.PlayerAutoReconnect, {
|
|
533
|
+
state: "log",
|
|
534
|
+
message: `Auto reconnecting player because LavalinkManager.options.playerOptions.onDisconnect.autoReconnect is true`,
|
|
535
|
+
functionLayer: "LavalinkManager > sendRawData()",
|
|
536
|
+
});
|
|
462
537
|
await player.connect();
|
|
463
538
|
// replay the current playing stream
|
|
464
539
|
await player.play({
|