lavalink-client 2.5.6 → 2.5.8
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 +9 -2
- package/dist/index.d.mts +3036 -0
- package/dist/index.d.ts +3036 -0
- package/dist/index.js +4965 -0
- package/dist/index.mjs +4904 -0
- package/package.json +22 -25
- package/dist/cjs/index.d.ts +0 -16
- package/dist/cjs/index.js +0 -19
- package/dist/cjs/package.json +0 -3
- package/dist/cjs/structures/Constants.d.ts +0 -90
- package/dist/cjs/structures/Constants.js +0 -296
- package/dist/cjs/structures/CustomSearches/BandCampSearch.d.ts +0 -3
- package/dist/cjs/structures/CustomSearches/BandCampSearch.js +0 -39
- package/dist/cjs/structures/Filters.d.ts +0 -169
- package/dist/cjs/structures/Filters.js +0 -700
- package/dist/cjs/structures/LavalinkManager.d.ts +0 -232
- package/dist/cjs/structures/LavalinkManager.js +0 -621
- package/dist/cjs/structures/LavalinkManagerStatics.d.ts +0 -15
- package/dist/cjs/structures/LavalinkManagerStatics.js +0 -149
- package/dist/cjs/structures/Node.d.ts +0 -523
- package/dist/cjs/structures/Node.js +0 -1605
- package/dist/cjs/structures/NodeManager.d.ts +0 -100
- package/dist/cjs/structures/NodeManager.js +0 -224
- package/dist/cjs/structures/Player.d.ts +0 -223
- package/dist/cjs/structures/Player.js +0 -807
- package/dist/cjs/structures/Queue.d.ts +0 -186
- package/dist/cjs/structures/Queue.js +0 -390
- package/dist/cjs/structures/Types/Filters.d.ts +0 -190
- package/dist/cjs/structures/Types/Filters.js +0 -2
- package/dist/cjs/structures/Types/Manager.d.ts +0 -271
- package/dist/cjs/structures/Types/Manager.js +0 -2
- package/dist/cjs/structures/Types/Node.d.ts +0 -238
- package/dist/cjs/structures/Types/Node.js +0 -2
- package/dist/cjs/structures/Types/Player.d.ts +0 -114
- package/dist/cjs/structures/Types/Player.js +0 -2
- package/dist/cjs/structures/Types/Queue.d.ts +0 -34
- package/dist/cjs/structures/Types/Queue.js +0 -2
- package/dist/cjs/structures/Types/Track.d.ts +0 -134
- package/dist/cjs/structures/Types/Track.js +0 -2
- package/dist/cjs/structures/Types/Utils.d.ts +0 -440
- package/dist/cjs/structures/Types/Utils.js +0 -2
- package/dist/cjs/structures/Utils.d.ts +0 -116
- package/dist/cjs/structures/Utils.js +0 -567
- package/dist/esm/index.d.ts +0 -16
- package/dist/esm/index.js +0 -16
- package/dist/esm/package.json +0 -3
- package/dist/esm/structures/Constants.d.ts +0 -90
- package/dist/esm/structures/Constants.js +0 -293
- package/dist/esm/structures/CustomSearches/BandCampSearch.d.ts +0 -3
- package/dist/esm/structures/CustomSearches/BandCampSearch.js +0 -35
- package/dist/esm/structures/Filters.d.ts +0 -169
- package/dist/esm/structures/Filters.js +0 -696
- package/dist/esm/structures/LavalinkManager.d.ts +0 -232
- package/dist/esm/structures/LavalinkManager.js +0 -617
- package/dist/esm/structures/LavalinkManagerStatics.d.ts +0 -15
- package/dist/esm/structures/LavalinkManagerStatics.js +0 -146
- package/dist/esm/structures/Node.d.ts +0 -523
- package/dist/esm/structures/Node.js +0 -1600
- package/dist/esm/structures/NodeManager.d.ts +0 -100
- package/dist/esm/structures/NodeManager.js +0 -220
- package/dist/esm/structures/Player.d.ts +0 -223
- package/dist/esm/structures/Player.js +0 -803
- package/dist/esm/structures/Queue.d.ts +0 -186
- package/dist/esm/structures/Queue.js +0 -384
- package/dist/esm/structures/Types/Filters.d.ts +0 -190
- package/dist/esm/structures/Types/Filters.js +0 -1
- package/dist/esm/structures/Types/Manager.d.ts +0 -271
- package/dist/esm/structures/Types/Manager.js +0 -1
- package/dist/esm/structures/Types/Node.d.ts +0 -238
- package/dist/esm/structures/Types/Node.js +0 -1
- package/dist/esm/structures/Types/Player.d.ts +0 -114
- package/dist/esm/structures/Types/Player.js +0 -1
- package/dist/esm/structures/Types/Queue.d.ts +0 -34
- package/dist/esm/structures/Types/Queue.js +0 -1
- package/dist/esm/structures/Types/Track.d.ts +0 -134
- package/dist/esm/structures/Types/Track.js +0 -1
- package/dist/esm/structures/Types/Utils.d.ts +0 -440
- package/dist/esm/structures/Types/Utils.js +0 -1
- package/dist/esm/structures/Utils.d.ts +0 -116
- package/dist/esm/structures/Utils.js +0 -559
- package/dist/types/index.d.ts +0 -16
- package/dist/types/structures/Constants.d.ts +0 -90
- package/dist/types/structures/CustomSearches/BandCampSearch.d.ts +0 -3
- package/dist/types/structures/Filters.d.ts +0 -169
- package/dist/types/structures/LavalinkManager.d.ts +0 -232
- package/dist/types/structures/LavalinkManagerStatics.d.ts +0 -15
- package/dist/types/structures/Node.d.ts +0 -523
- package/dist/types/structures/NodeManager.d.ts +0 -100
- package/dist/types/structures/Player.d.ts +0 -223
- package/dist/types/structures/Queue.d.ts +0 -186
- package/dist/types/structures/Types/Filters.d.ts +0 -190
- package/dist/types/structures/Types/Manager.d.ts +0 -271
- package/dist/types/structures/Types/Node.d.ts +0 -238
- package/dist/types/structures/Types/Player.d.ts +0 -114
- package/dist/types/structures/Types/Queue.d.ts +0 -34
- package/dist/types/structures/Types/Track.d.ts +0 -134
- package/dist/types/structures/Types/Utils.d.ts +0 -440
- package/dist/types/structures/Utils.d.ts +0 -116
|
@@ -1,559 +0,0 @@
|
|
|
1
|
-
import { URL } from "node:url";
|
|
2
|
-
import { isRegExp } from "node:util/types";
|
|
3
|
-
import { DebugEvents } from "./Constants.js";
|
|
4
|
-
import { DefaultSources, LavalinkPlugins, SourceLinksRegexes } from "./LavalinkManagerStatics.js";
|
|
5
|
-
export const TrackSymbol = Symbol("LC-Track");
|
|
6
|
-
export const UnresolvedTrackSymbol = Symbol("LC-Track-Unresolved");
|
|
7
|
-
export const QueueSymbol = Symbol("LC-Queue");
|
|
8
|
-
export const NodeSymbol = Symbol("LC-Node");
|
|
9
|
-
/** @hidden */
|
|
10
|
-
const escapeRegExp = (str) => str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
11
|
-
/**
|
|
12
|
-
* Parses Node Connection Url: "lavalink://<nodeId>:<nodeAuthorization(Password)>@<NodeHost>:<NodePort>"
|
|
13
|
-
* @param connectionUrl
|
|
14
|
-
* @returns
|
|
15
|
-
*/
|
|
16
|
-
export function parseLavalinkConnUrl(connectionUrl) {
|
|
17
|
-
if (!connectionUrl.startsWith("lavalink://"))
|
|
18
|
-
throw new Error(`ConnectionUrl (${connectionUrl}) must start with 'lavalink://'`);
|
|
19
|
-
const parsed = new URL(connectionUrl);
|
|
20
|
-
return {
|
|
21
|
-
authorization: parsed.password,
|
|
22
|
-
id: parsed.username,
|
|
23
|
-
host: parsed.hostname,
|
|
24
|
-
port: Number(parsed.port),
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
export class ManagerUtils {
|
|
28
|
-
LavalinkManager = undefined;
|
|
29
|
-
constructor(LavalinkManager) {
|
|
30
|
-
this.LavalinkManager = LavalinkManager;
|
|
31
|
-
}
|
|
32
|
-
buildPluginInfo(data, clientData = {}) {
|
|
33
|
-
return {
|
|
34
|
-
clientData: clientData,
|
|
35
|
-
...(data.pluginInfo || data.plugin),
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
buildTrack(data, requester) {
|
|
39
|
-
if (!data?.encoded || typeof data.encoded !== "string")
|
|
40
|
-
throw new RangeError("Argument 'data.encoded' must be present.");
|
|
41
|
-
if (!data.info)
|
|
42
|
-
throw new RangeError("Argument 'data.info' must be present.");
|
|
43
|
-
try {
|
|
44
|
-
let transformedRequester = typeof requester === "object"
|
|
45
|
-
? this.getTransformedRequester(requester)
|
|
46
|
-
: undefined;
|
|
47
|
-
if (!transformedRequester && typeof data?.userData?.requester === "object" && data.userData.requester !== null) {
|
|
48
|
-
transformedRequester = this.getTransformedRequester(data.userData.requester);
|
|
49
|
-
}
|
|
50
|
-
const r = {
|
|
51
|
-
encoded: data.encoded,
|
|
52
|
-
info: {
|
|
53
|
-
identifier: data.info.identifier,
|
|
54
|
-
title: data.info.title,
|
|
55
|
-
author: data.info.author,
|
|
56
|
-
duration: data.info?.duration || data.info?.length,
|
|
57
|
-
artworkUrl: data.info.artworkUrl || data.pluginInfo?.artworkUrl || data.plugin?.artworkUrl,
|
|
58
|
-
uri: data.info.uri,
|
|
59
|
-
sourceName: data.info.sourceName,
|
|
60
|
-
isSeekable: data.info.isSeekable,
|
|
61
|
-
isStream: data.info.isStream,
|
|
62
|
-
isrc: data.info.isrc,
|
|
63
|
-
},
|
|
64
|
-
userData: {
|
|
65
|
-
...data.userData,
|
|
66
|
-
requester: transformedRequester
|
|
67
|
-
},
|
|
68
|
-
pluginInfo: this.buildPluginInfo(data, "clientData" in data ? data.clientData : {}),
|
|
69
|
-
requester: transformedRequester || this.getTransformedRequester(this.LavalinkManager?.options?.client),
|
|
70
|
-
};
|
|
71
|
-
Object.defineProperty(r, TrackSymbol, { configurable: true, value: true });
|
|
72
|
-
return r;
|
|
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
|
-
}
|
|
83
|
-
throw new RangeError(`Argument "data" is not a valid track: ${error.message}`);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* Builds a UnresolvedTrack to be resolved before being played .
|
|
88
|
-
* @param query
|
|
89
|
-
* @param requester
|
|
90
|
-
*/
|
|
91
|
-
buildUnresolvedTrack(query, requester) {
|
|
92
|
-
if (typeof query === "undefined")
|
|
93
|
-
throw new RangeError('Argument "query" must be present.');
|
|
94
|
-
const unresolvedTrack = {
|
|
95
|
-
encoded: query.encoded || undefined,
|
|
96
|
-
info: query.info ? query.info : query.title ? query : undefined,
|
|
97
|
-
pluginInfo: this.buildPluginInfo(query),
|
|
98
|
-
requester: this.getTransformedRequester(requester),
|
|
99
|
-
async resolve(player) {
|
|
100
|
-
const closest = await getClosestTrack(this, player);
|
|
101
|
-
if (!closest)
|
|
102
|
-
throw new SyntaxError("No closest Track found");
|
|
103
|
-
for (const prop of Object.getOwnPropertyNames(this))
|
|
104
|
-
delete this[prop];
|
|
105
|
-
// delete symbol
|
|
106
|
-
delete this[UnresolvedTrackSymbol];
|
|
107
|
-
// assign new symbol
|
|
108
|
-
Object.defineProperty(this, TrackSymbol, { configurable: true, value: true });
|
|
109
|
-
return Object.assign(this, closest);
|
|
110
|
-
}
|
|
111
|
-
};
|
|
112
|
-
if (!this.isUnresolvedTrack(unresolvedTrack))
|
|
113
|
-
throw SyntaxError("Could not build Unresolved Track");
|
|
114
|
-
Object.defineProperty(unresolvedTrack, UnresolvedTrackSymbol, { configurable: true, value: true });
|
|
115
|
-
return unresolvedTrack;
|
|
116
|
-
}
|
|
117
|
-
/**
|
|
118
|
-
* Validate if a data is equal to a node
|
|
119
|
-
* @param data
|
|
120
|
-
*/
|
|
121
|
-
isNode(data) {
|
|
122
|
-
if (!data)
|
|
123
|
-
return false;
|
|
124
|
-
const keys = Object.getOwnPropertyNames(Object.getPrototypeOf(data));
|
|
125
|
-
if (!keys.includes("constructor"))
|
|
126
|
-
return false;
|
|
127
|
-
if (!keys.length)
|
|
128
|
-
return false;
|
|
129
|
-
// all required functions
|
|
130
|
-
if (!["connect", "destroy", "destroyPlayer", "fetchAllPlayers", "fetchInfo", "fetchPlayer", "fetchStats", "fetchVersion", "request", "updatePlayer", "updateSession"].every(v => keys.includes(v)))
|
|
131
|
-
return false;
|
|
132
|
-
return true;
|
|
133
|
-
}
|
|
134
|
-
getTransformedRequester(requester) {
|
|
135
|
-
try {
|
|
136
|
-
return typeof this.LavalinkManager?.options?.playerOptions?.requesterTransformer === "function"
|
|
137
|
-
? this.LavalinkManager?.options?.playerOptions?.requesterTransformer(requester)
|
|
138
|
-
: requester;
|
|
139
|
-
}
|
|
140
|
-
catch (e) {
|
|
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
|
-
}
|
|
149
|
-
return requester;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
/**
|
|
153
|
-
* Validate if a data is equal to node options
|
|
154
|
-
* @param data
|
|
155
|
-
*/
|
|
156
|
-
isNodeOptions(data) {
|
|
157
|
-
if (!data || typeof data !== "object" || Array.isArray(data))
|
|
158
|
-
return false;
|
|
159
|
-
if (typeof data.host !== "string" || !data.host.length)
|
|
160
|
-
return false;
|
|
161
|
-
if (typeof data.port !== "number" || isNaN(data.port) || data.port < 0 || data.port > 65535)
|
|
162
|
-
return false;
|
|
163
|
-
if (typeof data.authorization !== "string" || !data.authorization.length)
|
|
164
|
-
return false;
|
|
165
|
-
if ("secure" in data && typeof data.secure !== "boolean" && data.secure !== undefined)
|
|
166
|
-
return false;
|
|
167
|
-
if ("sessionId" in data && typeof data.sessionId !== "string" && data.sessionId !== undefined)
|
|
168
|
-
return false;
|
|
169
|
-
if ("id" in data && typeof data.id !== "string" && data.id !== undefined)
|
|
170
|
-
return false;
|
|
171
|
-
if ("regions" in data && (!Array.isArray(data.regions) || !data.regions.every(v => typeof v === "string") && data.regions !== undefined))
|
|
172
|
-
return false;
|
|
173
|
-
if ("poolOptions" in data && typeof data.poolOptions !== "object" && data.poolOptions !== undefined)
|
|
174
|
-
return false;
|
|
175
|
-
if ("retryAmount" in data && (typeof data.retryAmount !== "number" || isNaN(data.retryAmount) || data.retryAmount <= 0 && data.retryAmount !== undefined))
|
|
176
|
-
return false;
|
|
177
|
-
if ("retryDelay" in data && (typeof data.retryDelay !== "number" || isNaN(data.retryDelay) || data.retryDelay <= 0 && data.retryDelay !== undefined))
|
|
178
|
-
return false;
|
|
179
|
-
if ("requestTimeout" in data && (typeof data.requestTimeout !== "number" || isNaN(data.requestTimeout) || data.requestTimeout <= 0 && data.requestTimeout !== undefined))
|
|
180
|
-
return false;
|
|
181
|
-
return true;
|
|
182
|
-
}
|
|
183
|
-
/**
|
|
184
|
-
* Validate if a data is equal to a track
|
|
185
|
-
* @param data the Track to validate
|
|
186
|
-
* @returns
|
|
187
|
-
*/
|
|
188
|
-
isTrack(data) {
|
|
189
|
-
if (!data)
|
|
190
|
-
return false;
|
|
191
|
-
if (data[TrackSymbol] === true)
|
|
192
|
-
return true;
|
|
193
|
-
return typeof data?.encoded === "string" && typeof data?.info === "object" && !("resolve" in data);
|
|
194
|
-
}
|
|
195
|
-
/**
|
|
196
|
-
* Checks if the provided argument is a valid UnresolvedTrack.
|
|
197
|
-
* @param track
|
|
198
|
-
*/
|
|
199
|
-
isUnresolvedTrack(data) {
|
|
200
|
-
if (!data)
|
|
201
|
-
return false;
|
|
202
|
-
if (data[UnresolvedTrackSymbol] === true)
|
|
203
|
-
return true;
|
|
204
|
-
return typeof data === "object" && (("info" in data && typeof data.info.title === "string") || typeof data.encoded === "string") && "resolve" in data && typeof data.resolve === "function";
|
|
205
|
-
}
|
|
206
|
-
/**
|
|
207
|
-
* Checks if the provided argument is a valid UnresolvedTrack.
|
|
208
|
-
* @param track
|
|
209
|
-
*/
|
|
210
|
-
isUnresolvedTrackQuery(data) {
|
|
211
|
-
return typeof data === "object" && !("info" in data) && typeof data.title === "string";
|
|
212
|
-
}
|
|
213
|
-
async getClosestTrack(data, player) {
|
|
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
|
-
}
|
|
228
|
-
}
|
|
229
|
-
validateQueryString(node, queryString, sourceString) {
|
|
230
|
-
if (!node.info)
|
|
231
|
-
throw new Error("No Lavalink Node was provided");
|
|
232
|
-
if (!node.info.sourceManagers?.length)
|
|
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.`);
|
|
236
|
-
if (sourceString === "speak" && queryString.length > 100)
|
|
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))) {
|
|
248
|
-
throw new Error(`Query string contains a link / word which is blacklisted.`);
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
if (!/^https?:\/\//.test(queryString))
|
|
252
|
-
return;
|
|
253
|
-
else if (this.LavalinkManager.options?.linksAllowed === false)
|
|
254
|
-
throw new Error("Using links to make a request is not allowed.");
|
|
255
|
-
// checks for if the query is whitelisted (should only work for links, so it skips the check for no link queries)
|
|
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
|
-
}
|
|
267
|
-
}
|
|
268
|
-
// missing links: beam.pro local getyarn.io clypit pornhub reddit ocreamix soundgasm
|
|
269
|
-
if ((SourceLinksRegexes.YoutubeMusicRegex.test(queryString) || SourceLinksRegexes.YoutubeRegex.test(queryString)) && !node.info?.sourceManagers?.includes("youtube")) {
|
|
270
|
-
throw new Error("Query / Link Provided for this Source but Lavalink Node has not 'youtube' enabled");
|
|
271
|
-
}
|
|
272
|
-
if ((SourceLinksRegexes.SoundCloudMobileRegex.test(queryString) || SourceLinksRegexes.SoundCloudRegex.test(queryString)) && !node.info?.sourceManagers?.includes("soundcloud")) {
|
|
273
|
-
throw new Error("Query / Link Provided for this Source but Lavalink Node has not 'soundcloud' enabled");
|
|
274
|
-
}
|
|
275
|
-
if (SourceLinksRegexes.bandcamp.test(queryString) && !node.info?.sourceManagers?.includes("bandcamp")) {
|
|
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)");
|
|
277
|
-
}
|
|
278
|
-
if (SourceLinksRegexes.TwitchTv.test(queryString) && !node.info?.sourceManagers?.includes("twitch")) {
|
|
279
|
-
throw new Error("Query / Link Provided for this Source but Lavalink Node has not 'twitch' enabled");
|
|
280
|
-
}
|
|
281
|
-
if (SourceLinksRegexes.vimeo.test(queryString) && !node.info?.sourceManagers?.includes("vimeo")) {
|
|
282
|
-
throw new Error("Query / Link Provided for this Source but Lavalink Node has not 'vimeo' enabled");
|
|
283
|
-
}
|
|
284
|
-
if (SourceLinksRegexes.tiktok.test(queryString) && !node.info?.sourceManagers?.includes("tiktok")) {
|
|
285
|
-
throw new Error("Query / Link Provided for this Source but Lavalink Node has not 'tiktok' enabled");
|
|
286
|
-
}
|
|
287
|
-
if (SourceLinksRegexes.mixcloud.test(queryString) && !node.info?.sourceManagers?.includes("mixcloud")) {
|
|
288
|
-
throw new Error("Query / Link Provided for this Source but Lavalink Node has not 'mixcloud' enabled");
|
|
289
|
-
}
|
|
290
|
-
if (SourceLinksRegexes.AllSpotifyRegex.test(queryString) && !node.info?.sourceManagers?.includes("spotify")) {
|
|
291
|
-
throw new Error("Query / Link Provided for this Source but Lavalink Node has not 'spotify' enabled");
|
|
292
|
-
}
|
|
293
|
-
if (SourceLinksRegexes.appleMusic.test(queryString) && !node.info?.sourceManagers?.includes("applemusic")) {
|
|
294
|
-
throw new Error("Query / Link Provided for this Source but Lavalink Node has not 'applemusic' enabled");
|
|
295
|
-
}
|
|
296
|
-
if (SourceLinksRegexes.AllDeezerRegex.test(queryString) && !node.info?.sourceManagers?.includes("deezer")) {
|
|
297
|
-
throw new Error("Query / Link Provided for this Source but Lavalink Node has not 'deezer' enabled");
|
|
298
|
-
}
|
|
299
|
-
if (SourceLinksRegexes.musicYandex.test(queryString) && !node.info?.sourceManagers?.includes("yandexmusic")) {
|
|
300
|
-
throw new Error("Query / Link Provided for this Source but Lavalink Node has not 'yandexmusic' enabled");
|
|
301
|
-
}
|
|
302
|
-
if (SourceLinksRegexes.jiosaavn.test(queryString) && !node.info?.sourceManagers?.includes("jiosaavn")) {
|
|
303
|
-
throw new Error("Query / Link Provided for this Source but Lavalink Node has not 'jiosaavn' (via jiosaavn-plugin) enabled");
|
|
304
|
-
}
|
|
305
|
-
if (SourceLinksRegexes.tidal.test(queryString) && !node.info?.sourceManagers?.includes("tidal")) {
|
|
306
|
-
throw new Error("Query / Link Provided for this Source but Lavalink Node has not 'tidal' enabled");
|
|
307
|
-
}
|
|
308
|
-
return;
|
|
309
|
-
}
|
|
310
|
-
transformQuery(query) {
|
|
311
|
-
const sourceOfQuery = typeof query === "string" ? undefined : (DefaultSources[(query.source?.trim?.()?.toLowerCase?.()) ?? this.LavalinkManager?.options?.playerOptions?.defaultSearchPlatform?.toLowerCase?.()] ?? (query.source?.trim?.()?.toLowerCase?.()));
|
|
312
|
-
const Query = {
|
|
313
|
-
query: typeof query === "string" ? query : query.query,
|
|
314
|
-
extraQueryUrlParams: typeof query !== "string" ? query.extraQueryUrlParams : undefined,
|
|
315
|
-
source: sourceOfQuery ?? this.LavalinkManager?.options?.playerOptions?.defaultSearchPlatform?.toLowerCase?.()
|
|
316
|
-
};
|
|
317
|
-
const foundSource = Object.keys(DefaultSources).find(source => Query.query?.toLowerCase?.()?.startsWith(`${source}:`.toLowerCase()))?.trim?.()?.toLowerCase?.();
|
|
318
|
-
// ignore links...
|
|
319
|
-
if (foundSource && !["https", "http"].includes(foundSource) && DefaultSources[foundSource]) {
|
|
320
|
-
Query.source = DefaultSources[foundSource]; // set the source to ytsearch:
|
|
321
|
-
Query.query = Query.query.slice(`${foundSource}:`.length, Query.query.length); // remove ytsearch: from the query
|
|
322
|
-
}
|
|
323
|
-
return Query;
|
|
324
|
-
}
|
|
325
|
-
transformLavaSearchQuery(query) {
|
|
326
|
-
// transform the query object
|
|
327
|
-
const sourceOfQuery = typeof query === "string" ? undefined : (DefaultSources[(query.source?.trim?.()?.toLowerCase?.()) ?? this.LavalinkManager?.options?.playerOptions?.defaultSearchPlatform?.toLowerCase?.()] ?? (query.source?.trim?.()?.toLowerCase?.()));
|
|
328
|
-
const Query = {
|
|
329
|
-
query: typeof query === "string" ? query : query.query,
|
|
330
|
-
types: query.types ? ["track", "playlist", "artist", "album", "text"].filter(v => query.types?.find(x => x.toLowerCase().startsWith(v))) : ["track", "playlist", "artist", "album", /*"text"*/],
|
|
331
|
-
source: sourceOfQuery ?? this.LavalinkManager?.options?.playerOptions?.defaultSearchPlatform?.toLowerCase?.()
|
|
332
|
-
};
|
|
333
|
-
const foundSource = Object.keys(DefaultSources).find(source => Query.query.toLowerCase().startsWith(`${source}:`.toLowerCase()))?.trim?.()?.toLowerCase?.();
|
|
334
|
-
if (foundSource && DefaultSources[foundSource]) {
|
|
335
|
-
Query.source = DefaultSources[foundSource]; // set the source to ytsearch:
|
|
336
|
-
Query.query = Query.query.slice(`${foundSource}:`.length, Query.query.length); // remove ytsearch: from the query
|
|
337
|
-
}
|
|
338
|
-
return Query;
|
|
339
|
-
}
|
|
340
|
-
validateSourceString(node, sourceString) {
|
|
341
|
-
if (!sourceString)
|
|
342
|
-
throw new Error(`No SourceString was provided`);
|
|
343
|
-
const source = DefaultSources[sourceString.toLowerCase().trim()];
|
|
344
|
-
if (!source)
|
|
345
|
-
throw new Error(`Lavalink Node SearchQuerySource: '${sourceString}' is not available`);
|
|
346
|
-
if (!node.info)
|
|
347
|
-
throw new Error("Lavalink Node does not have any info cached yet, not ready yet!");
|
|
348
|
-
if (source === "amsearch" && !node.info?.sourceManagers?.includes("applemusic")) {
|
|
349
|
-
throw new Error("Lavalink Node has not 'applemusic' enabled, which is required to have 'amsearch' work");
|
|
350
|
-
}
|
|
351
|
-
if (source === "dzisrc" && !node.info?.sourceManagers?.includes("deezer")) {
|
|
352
|
-
throw new Error("Lavalink Node has not 'deezer' enabled, which is required to have 'dzisrc' work");
|
|
353
|
-
}
|
|
354
|
-
if (source === "dzsearch" && !node.info?.sourceManagers?.includes("deezer")) {
|
|
355
|
-
throw new Error("Lavalink Node has not 'deezer' enabled, which is required to have 'dzsearch' work");
|
|
356
|
-
}
|
|
357
|
-
if (source === "dzisrc" && node.info?.sourceManagers?.includes("deezer") && !node.info?.sourceManagers?.includes("http")) {
|
|
358
|
-
throw new Error("Lavalink Node has not 'http' enabled, which is required to have 'dzisrc' to work");
|
|
359
|
-
}
|
|
360
|
-
if (source === "jsrec" && !node.info?.sourceManagers?.includes("jiosaavn")) {
|
|
361
|
-
throw new Error("Lavalink Node has not 'jiosaavn' (via jiosaavn-plugin) enabled, which is required to have 'jsrec' to work");
|
|
362
|
-
}
|
|
363
|
-
if (source === "jssearch" && !node.info?.sourceManagers?.includes("jiosaavn")) {
|
|
364
|
-
throw new Error("Lavalink Node has not 'jiosaavn' (via jiosaavn-plugin) enabled, which is required to have 'jssearch' to work");
|
|
365
|
-
}
|
|
366
|
-
if (source === "scsearch" && !node.info?.sourceManagers?.includes("soundcloud")) {
|
|
367
|
-
throw new Error("Lavalink Node has not 'soundcloud' enabled, which is required to have 'scsearch' work");
|
|
368
|
-
}
|
|
369
|
-
if (source === "speak" && !node.info?.plugins?.find(c => c.name.toLowerCase().includes(LavalinkPlugins.DuncteBot_Plugin.toLowerCase()))) {
|
|
370
|
-
throw new Error("Lavalink Node has not 'speak' enabled, which is required to have 'speak' work");
|
|
371
|
-
}
|
|
372
|
-
if (source === "tdsearch" && !node.info?.sourceManagers?.includes("tidal")) {
|
|
373
|
-
throw new Error("Lavalink Node has not 'tidal' enabled, which is required to have 'tdsearch' work");
|
|
374
|
-
}
|
|
375
|
-
if (source === "tdrec" && !node.info?.sourceManagers?.includes("tidal")) {
|
|
376
|
-
throw new Error("Lavalink Node has not 'tidal' enabled, which is required to have 'tdrec' work");
|
|
377
|
-
}
|
|
378
|
-
if (source === "tts" && !node.info?.plugins?.find(c => c.name.toLowerCase().includes(LavalinkPlugins.GoogleCloudTTS.toLowerCase()))) {
|
|
379
|
-
throw new Error("Lavalink Node has not 'tts' enabled, which is required to have 'tts' work");
|
|
380
|
-
}
|
|
381
|
-
if (source === "ftts" && !(node.info?.sourceManagers?.includes("ftts") || node.info?.sourceManagers?.includes("flowery-tts") || node.info?.sourceManagers?.includes("flowerytts"))) {
|
|
382
|
-
throw new Error("Lavalink Node has not 'flowery-tts' enabled, which is required to have 'ftts' work");
|
|
383
|
-
}
|
|
384
|
-
if (source === "ymsearch" && !node.info?.sourceManagers?.includes("yandexmusic")) {
|
|
385
|
-
throw new Error("Lavalink Node has not 'yandexmusic' enabled, which is required to have 'ymsearch' work");
|
|
386
|
-
}
|
|
387
|
-
if (source === "ytmsearch" && !node.info.sourceManagers?.includes("youtube")) {
|
|
388
|
-
throw new Error("Lavalink Node has not 'youtube' enabled, which is required to have 'ytmsearch' work");
|
|
389
|
-
}
|
|
390
|
-
if (source === "ytsearch" && !node.info?.sourceManagers?.includes("youtube")) {
|
|
391
|
-
throw new Error("Lavalink Node has not 'youtube' enabled, which is required to have 'ytsearch' work");
|
|
392
|
-
}
|
|
393
|
-
if (source === "vksearch" && !node.info?.sourceManagers?.includes("vkmusic")) {
|
|
394
|
-
throw new Error("Lavalink Node has not 'vkmusic' enabled, which is required to have 'vksearch' work");
|
|
395
|
-
}
|
|
396
|
-
if (source === "vkrec" && !node.info?.sourceManagers?.includes("vkmusic")) {
|
|
397
|
-
throw new Error("Lavalink Node has not 'vkmusic' enabled, which is required to have 'vkrec' work");
|
|
398
|
-
}
|
|
399
|
-
if (source === "qbsearch" && !node.info?.sourceManagers?.includes("qobuz")) {
|
|
400
|
-
throw new Error("Lavalink Node has not 'qobuz' enabled, which is required to have 'qbsearch' work");
|
|
401
|
-
}
|
|
402
|
-
if (source === "qbisrc" && !node.info?.sourceManagers?.includes("qobuz")) {
|
|
403
|
-
throw new Error("Lavalink Node has not 'qobuz' enabled, which is required to have 'qbisrc' work");
|
|
404
|
-
}
|
|
405
|
-
if (source === "qbrec" && !node.info?.sourceManagers?.includes("qobuz")) {
|
|
406
|
-
throw new Error("Lavalink Node has not 'qobuz' enabled, which is required to have 'qbrec' work");
|
|
407
|
-
}
|
|
408
|
-
return;
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
export class MiniMap extends Map {
|
|
412
|
-
constructor(data = []) {
|
|
413
|
-
super(data);
|
|
414
|
-
}
|
|
415
|
-
filter(fn, thisArg) {
|
|
416
|
-
if (typeof thisArg !== 'undefined')
|
|
417
|
-
fn = fn.bind(thisArg);
|
|
418
|
-
const results = new this.constructor[Symbol.species]();
|
|
419
|
-
for (const [key, val] of this) {
|
|
420
|
-
if (fn(val, key, this))
|
|
421
|
-
results.set(key, val);
|
|
422
|
-
}
|
|
423
|
-
return results;
|
|
424
|
-
}
|
|
425
|
-
toJSON() {
|
|
426
|
-
return [...this.entries()];
|
|
427
|
-
}
|
|
428
|
-
map(fn, thisArg) {
|
|
429
|
-
if (typeof thisArg !== 'undefined')
|
|
430
|
-
fn = fn.bind(thisArg);
|
|
431
|
-
const iter = this.entries();
|
|
432
|
-
return Array.from({ length: this.size }, () => {
|
|
433
|
-
const [key, value] = iter.next().value;
|
|
434
|
-
return fn(value, key, this);
|
|
435
|
-
});
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
export async function queueTrackEnd(player, dontShiftQueue = false) {
|
|
439
|
-
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.
|
|
440
|
-
player.queue.previous.unshift(player.queue.current);
|
|
441
|
-
if (player.queue.previous.length > player.queue.options.maxPreviousTracks)
|
|
442
|
-
player.queue.previous.splice(player.queue.options.maxPreviousTracks, player.queue.previous.length);
|
|
443
|
-
await player.queue.utils.save();
|
|
444
|
-
}
|
|
445
|
-
// and if repeatMode == queue, add it back to the queue!
|
|
446
|
-
if (player.repeatMode === "queue" && player.queue.current)
|
|
447
|
-
player.queue.tracks.push(player.queue.current);
|
|
448
|
-
// change the current Track to the next upcoming one
|
|
449
|
-
const nextSong = dontShiftQueue ? null : player.queue.tracks.shift();
|
|
450
|
-
try {
|
|
451
|
-
if (nextSong && player.LavalinkManager.utils.isUnresolvedTrack(nextSong))
|
|
452
|
-
await nextSong.resolve(player);
|
|
453
|
-
player.queue.current = nextSong || null;
|
|
454
|
-
// save it in the DB
|
|
455
|
-
await player.queue.utils.save();
|
|
456
|
-
}
|
|
457
|
-
catch (error) {
|
|
458
|
-
if (player.LavalinkManager.options?.advancedOptions?.enableDebugEvents) {
|
|
459
|
-
player.LavalinkManager.emit("debug", DebugEvents.PlayerPlayUnresolvedTrackFailed, {
|
|
460
|
-
state: "error",
|
|
461
|
-
error: error,
|
|
462
|
-
message: `queueTrackEnd Util was called, tried to resolve the next track, but failed to find the closest matching song`,
|
|
463
|
-
functionLayer: "Player > play() > resolve currentTrack",
|
|
464
|
-
});
|
|
465
|
-
}
|
|
466
|
-
player.LavalinkManager.emit("trackError", player, player.queue.current, error);
|
|
467
|
-
// try to play the next track if possible
|
|
468
|
-
if (!dontShiftQueue && player.LavalinkManager.options?.autoSkipOnResolveError === true && player.queue.tracks[0])
|
|
469
|
-
return queueTrackEnd(player);
|
|
470
|
-
}
|
|
471
|
-
// return the new current Track
|
|
472
|
-
return player.queue.current;
|
|
473
|
-
}
|
|
474
|
-
async function applyUnresolvedData(resTrack, data, utils) {
|
|
475
|
-
if (!resTrack?.info || !data?.info)
|
|
476
|
-
return;
|
|
477
|
-
if (data.info.uri)
|
|
478
|
-
resTrack.info.uri = data.info.uri;
|
|
479
|
-
if (utils?.LavalinkManager?.options?.playerOptions?.useUnresolvedData === true) { // overwrite values
|
|
480
|
-
if (data.info.artworkUrl?.length)
|
|
481
|
-
resTrack.info.artworkUrl = data.info.artworkUrl;
|
|
482
|
-
if (data.info.title?.length)
|
|
483
|
-
resTrack.info.title = data.info.title;
|
|
484
|
-
if (data.info.author?.length)
|
|
485
|
-
resTrack.info.author = data.info.author;
|
|
486
|
-
}
|
|
487
|
-
else { // only overwrite if undefined / invalid
|
|
488
|
-
if ((resTrack.info.title === 'Unknown title' || resTrack.info.title === "Unspecified description") && resTrack.info.title != data.info.title)
|
|
489
|
-
resTrack.info.title = data.info.title;
|
|
490
|
-
if (resTrack.info.author !== data.info.author)
|
|
491
|
-
resTrack.info.author = data.info.author;
|
|
492
|
-
if (resTrack.info.artworkUrl !== data.info.artworkUrl)
|
|
493
|
-
resTrack.info.artworkUrl = data.info.artworkUrl;
|
|
494
|
-
}
|
|
495
|
-
for (const key of Object.keys(data.info))
|
|
496
|
-
if (typeof resTrack.info[key] === "undefined" && key !== "resolve" && data.info[key])
|
|
497
|
-
resTrack.info[key] = data.info[key]; // add non-existing values
|
|
498
|
-
return resTrack;
|
|
499
|
-
}
|
|
500
|
-
async function getClosestTrack(data, player) {
|
|
501
|
-
if (!player || !player.node)
|
|
502
|
-
throw new RangeError("No player with a lavalink node was provided");
|
|
503
|
-
if (player.LavalinkManager.utils.isTrack(data))
|
|
504
|
-
return player.LavalinkManager.utils.buildTrack(data, data.requester);
|
|
505
|
-
if (!player.LavalinkManager.utils.isUnresolvedTrack(data))
|
|
506
|
-
throw new RangeError("Track is not an unresolved Track");
|
|
507
|
-
if (!data?.info?.title && typeof data.encoded !== "string" && !data.info.uri)
|
|
508
|
-
throw new SyntaxError("the track uri / title / encoded Base64 string is required for unresolved tracks");
|
|
509
|
-
if (!data.requester)
|
|
510
|
-
throw new SyntaxError("The requester is required");
|
|
511
|
-
// try to decode the track, if possible
|
|
512
|
-
if (typeof data.encoded === "string") {
|
|
513
|
-
const r = await player.node.decode.singleTrack(data.encoded, data.requester);
|
|
514
|
-
if (r)
|
|
515
|
-
return applyUnresolvedData(r, data, player.LavalinkManager.utils);
|
|
516
|
-
}
|
|
517
|
-
// try to fetch the track via a uri if possible
|
|
518
|
-
if (typeof data.info.uri === "string") {
|
|
519
|
-
const r = await player.search({ query: data?.info?.uri }, data.requester).then(v => v.tracks?.[0]);
|
|
520
|
-
if (r)
|
|
521
|
-
return applyUnresolvedData(r, data, player.LavalinkManager.utils);
|
|
522
|
-
}
|
|
523
|
-
// search the track as closely as possible
|
|
524
|
-
const query = [data.info?.title, data.info?.author].filter(str => !!str).join(" by ");
|
|
525
|
-
const sourceName = data.info?.sourceName;
|
|
526
|
-
return await player.search({
|
|
527
|
-
query, source: sourceName !== "twitch" && sourceName !== "flowery-tts" ? sourceName : player.LavalinkManager.options?.playerOptions?.defaultSearchPlatform,
|
|
528
|
-
}, data.requester).then((res) => {
|
|
529
|
-
let trackToUse = null;
|
|
530
|
-
// try to find via author name
|
|
531
|
-
if (data.info.author && !trackToUse)
|
|
532
|
-
trackToUse = res.tracks.find(track => [data.info?.author || "", `${data.info?.author} - Topic`].some(name => new RegExp(`^${escapeRegExp(name)}$`, "i").test(track.info?.author)) || new RegExp(`^${escapeRegExp(data.info?.title)}$`, "i").test(track.info?.title));
|
|
533
|
-
// try to find via duration
|
|
534
|
-
if (data.info.duration && !trackToUse)
|
|
535
|
-
trackToUse = res.tracks.find(track => (track.info?.duration >= (data.info?.duration - 1500)) && (track?.info.duration <= (data.info?.duration + 1500)));
|
|
536
|
-
// try to find via isrc
|
|
537
|
-
if (data.info.isrc && !trackToUse)
|
|
538
|
-
trackToUse = res.tracks.find(track => track.info?.isrc === data.info?.isrc);
|
|
539
|
-
// apply unresolved data and return the track
|
|
540
|
-
return applyUnresolvedData(trackToUse || res.tracks[0], data, player.LavalinkManager.utils);
|
|
541
|
-
});
|
|
542
|
-
}
|
|
543
|
-
export function safeStringify(obj, padding = 0) {
|
|
544
|
-
const seen = new WeakSet();
|
|
545
|
-
return JSON.stringify(obj, (key, value) => {
|
|
546
|
-
if (typeof value === "function")
|
|
547
|
-
return undefined; // Funktion skippen
|
|
548
|
-
if (typeof value === "symbol")
|
|
549
|
-
return undefined; // Symbol skippen
|
|
550
|
-
if (typeof value === "bigint")
|
|
551
|
-
return value.toString(); // BigInt to String
|
|
552
|
-
if (typeof value === "object" && value !== null) {
|
|
553
|
-
if (seen.has(value))
|
|
554
|
-
return "[Circular]";
|
|
555
|
-
seen.add(value);
|
|
556
|
-
}
|
|
557
|
-
return value;
|
|
558
|
-
}, padding);
|
|
559
|
-
}
|
package/dist/types/index.d.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
export * from "./structures/LavalinkManager";
|
|
2
|
-
export * from "./structures/Filters";
|
|
3
|
-
export * from "./structures/LavalinkManagerStatics";
|
|
4
|
-
export * from "./structures/Node";
|
|
5
|
-
export * from "./structures/NodeManager";
|
|
6
|
-
export * from "./structures/Player";
|
|
7
|
-
export * from "./structures/Queue";
|
|
8
|
-
export * from "./structures/Utils";
|
|
9
|
-
export * from "./structures/Types/Track";
|
|
10
|
-
export * from "./structures/Types/Utils";
|
|
11
|
-
export * from "./structures/Types/Filters";
|
|
12
|
-
export * from "./structures/Types/Player";
|
|
13
|
-
export * from "./structures/Types/Queue";
|
|
14
|
-
export * from "./structures/Types/Node";
|
|
15
|
-
export * from "./structures/Constants";
|
|
16
|
-
export * from "./structures/Types/Manager";
|