lavalink-client 1.1.11 → 1.1.14
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/dist/cjs/structures/Filters.js +39 -20
- package/dist/cjs/structures/Node.d.ts +4 -3
- package/dist/cjs/structures/Node.js +64 -9
- package/dist/cjs/structures/NodeManager.d.ts +16 -0
- package/dist/cjs/structures/NodeManager.js +53 -0
- package/dist/cjs/structures/Player.d.ts +4 -11
- package/dist/cjs/structures/Player.js +7 -63
- package/dist/cjs/structures/Utils.d.ts +18 -0
- package/dist/cjs/structures/Utils.js +52 -24
- package/dist/esm/structures/Filters.js +39 -20
- package/dist/esm/structures/Node.d.ts +4 -3
- package/dist/esm/structures/Node.js +64 -9
- package/dist/esm/structures/NodeManager.d.ts +16 -0
- package/dist/esm/structures/NodeManager.js +53 -0
- package/dist/esm/structures/Player.d.ts +4 -11
- package/dist/esm/structures/Player.js +7 -63
- package/dist/esm/structures/Utils.d.ts +18 -0
- package/dist/esm/structures/Utils.js +52 -24
- package/dist/types/structures/Node.d.ts +4 -3
- package/dist/types/structures/NodeManager.d.ts +16 -0
- package/dist/types/structures/Player.d.ts +4 -11
- package/dist/types/structures/Utils.d.ts +18 -0
- package/package.json +1 -1
|
@@ -156,84 +156,112 @@ class ManagerUtils {
|
|
|
156
156
|
if (!node.info.sourceManagers?.length)
|
|
157
157
|
throw new Error("Lavalink Node, has no sourceManagers enabled");
|
|
158
158
|
// missing links: beam.pro local getyarn.io clypit pornhub reddit ocreamix soundgasm
|
|
159
|
-
if ((LavalinkManagerStatics_1.SourceLinksRegexes.YoutubeMusicRegex.test(queryString) || LavalinkManagerStatics_1.SourceLinksRegexes.YoutubeRegex.test(queryString)) && !node.info
|
|
159
|
+
if ((LavalinkManagerStatics_1.SourceLinksRegexes.YoutubeMusicRegex.test(queryString) || LavalinkManagerStatics_1.SourceLinksRegexes.YoutubeRegex.test(queryString)) && !node.info?.sourceManagers?.includes("youtube")) {
|
|
160
160
|
throw new Error("Lavalink Node has not 'youtube' enabled");
|
|
161
161
|
}
|
|
162
|
-
if ((LavalinkManagerStatics_1.SourceLinksRegexes.SoundCloudMobileRegex.test(queryString) || LavalinkManagerStatics_1.SourceLinksRegexes.SoundCloudRegex.test(queryString)) && !node.info
|
|
162
|
+
if ((LavalinkManagerStatics_1.SourceLinksRegexes.SoundCloudMobileRegex.test(queryString) || LavalinkManagerStatics_1.SourceLinksRegexes.SoundCloudRegex.test(queryString)) && !node.info?.sourceManagers?.includes("soundcloud")) {
|
|
163
163
|
throw new Error("Lavalink Node has not 'soundcloud' enabled");
|
|
164
164
|
}
|
|
165
|
-
if (LavalinkManagerStatics_1.SourceLinksRegexes.bandcamp.test(queryString) && !node.info
|
|
165
|
+
if (LavalinkManagerStatics_1.SourceLinksRegexes.bandcamp.test(queryString) && !node.info?.sourceManagers?.includes("bandcamp")) {
|
|
166
166
|
throw new Error("Lavalink Node has not 'bandcamp' enabled");
|
|
167
167
|
}
|
|
168
|
-
if (LavalinkManagerStatics_1.SourceLinksRegexes.TwitchTv.test(queryString) && !node.info
|
|
168
|
+
if (LavalinkManagerStatics_1.SourceLinksRegexes.TwitchTv.test(queryString) && !node.info?.sourceManagers?.includes("twitch")) {
|
|
169
169
|
throw new Error("Lavalink Node has not 'twitch' enabled");
|
|
170
170
|
}
|
|
171
|
-
if (LavalinkManagerStatics_1.SourceLinksRegexes.vimeo.test(queryString) && !node.info
|
|
171
|
+
if (LavalinkManagerStatics_1.SourceLinksRegexes.vimeo.test(queryString) && !node.info?.sourceManagers?.includes("vimeo")) {
|
|
172
172
|
throw new Error("Lavalink Node has not 'vimeo' enabled");
|
|
173
173
|
}
|
|
174
|
-
if (LavalinkManagerStatics_1.SourceLinksRegexes.tiktok.test(queryString) && !node.info
|
|
174
|
+
if (LavalinkManagerStatics_1.SourceLinksRegexes.tiktok.test(queryString) && !node.info?.sourceManagers?.includes("tiktok")) {
|
|
175
175
|
throw new Error("Lavalink Node has not 'tiktok' enabled");
|
|
176
176
|
}
|
|
177
|
-
if (LavalinkManagerStatics_1.SourceLinksRegexes.mixcloud.test(queryString) && !node.info
|
|
177
|
+
if (LavalinkManagerStatics_1.SourceLinksRegexes.mixcloud.test(queryString) && !node.info?.sourceManagers?.includes("mixcloud")) {
|
|
178
178
|
throw new Error("Lavalink Node has not 'mixcloud' enabled");
|
|
179
179
|
}
|
|
180
|
-
if (LavalinkManagerStatics_1.SourceLinksRegexes.AllSpotifyRegex.test(queryString) && !node.info
|
|
180
|
+
if (LavalinkManagerStatics_1.SourceLinksRegexes.AllSpotifyRegex.test(queryString) && !node.info?.sourceManagers?.includes("spotify")) {
|
|
181
181
|
throw new Error("Lavalink Node has not 'spotify' enabled");
|
|
182
182
|
}
|
|
183
|
-
if (LavalinkManagerStatics_1.SourceLinksRegexes.appleMusic.test(queryString) && !node.info
|
|
183
|
+
if (LavalinkManagerStatics_1.SourceLinksRegexes.appleMusic.test(queryString) && !node.info?.sourceManagers?.includes("applemusic")) {
|
|
184
184
|
throw new Error("Lavalink Node has not 'applemusic' enabled");
|
|
185
185
|
}
|
|
186
|
-
if (LavalinkManagerStatics_1.SourceLinksRegexes.AllDeezerRegex.test(queryString) && !node.info
|
|
186
|
+
if (LavalinkManagerStatics_1.SourceLinksRegexes.AllDeezerRegex.test(queryString) && !node.info?.sourceManagers?.includes("deezer")) {
|
|
187
187
|
throw new Error("Lavalink Node has not 'deezer' enabled");
|
|
188
188
|
}
|
|
189
|
-
if (LavalinkManagerStatics_1.SourceLinksRegexes.AllDeezerRegex.test(queryString) && node.info
|
|
189
|
+
if (LavalinkManagerStatics_1.SourceLinksRegexes.AllDeezerRegex.test(queryString) && node.info?.sourceManagers?.includes("deezer") && !node.info?.sourceManagers?.includes("http")) {
|
|
190
190
|
throw new Error("Lavalink Node has not 'http' enabled, which is required to have 'deezer' to work");
|
|
191
191
|
}
|
|
192
|
-
if (LavalinkManagerStatics_1.SourceLinksRegexes.musicYandex.test(queryString) && !node.info
|
|
192
|
+
if (LavalinkManagerStatics_1.SourceLinksRegexes.musicYandex.test(queryString) && !node.info?.sourceManagers?.includes("yandexmusic")) {
|
|
193
193
|
throw new Error("Lavalink Node has not 'yandexmusic' enabled");
|
|
194
194
|
}
|
|
195
195
|
return;
|
|
196
196
|
}
|
|
197
|
+
transformQuery(query) {
|
|
198
|
+
const Query = {
|
|
199
|
+
query: typeof query === "string" ? query : query.query,
|
|
200
|
+
source: LavalinkManagerStatics_1.DefaultSources[(typeof query === "string" ? undefined : query.source?.trim?.()?.toLowerCase?.()) ?? this.LavalinkManager?.options?.playerOptions?.defaultSearchPlatform?.toLowerCase?.()] ?? (typeof query === "string" ? undefined : query.source?.trim?.()?.toLowerCase?.()) ?? this.LavalinkManager?.options?.playerOptions?.defaultSearchPlatform?.toLowerCase?.()
|
|
201
|
+
};
|
|
202
|
+
const foundSource = Object.keys(LavalinkManagerStatics_1.DefaultSources).find(source => Query.query?.toLowerCase?.()?.startsWith(`${source}:`.toLowerCase()))?.trim?.()?.toLowerCase?.();
|
|
203
|
+
if (foundSource && LavalinkManagerStatics_1.DefaultSources[foundSource]) {
|
|
204
|
+
Query.source = LavalinkManagerStatics_1.DefaultSources[foundSource]; // set the source to ytsearch:
|
|
205
|
+
Query.query = Query.query.slice(`${foundSource}:`.length, Query.query.length); // remove ytsearch: from the query
|
|
206
|
+
}
|
|
207
|
+
return Query;
|
|
208
|
+
}
|
|
209
|
+
transformLavaSearchQuery(query) {
|
|
210
|
+
// transform the query object
|
|
211
|
+
const Query = {
|
|
212
|
+
query: typeof query === "string" ? query : query.query,
|
|
213
|
+
types: query.types ? ["track", "playlist", "artist", "album", "text"].filter(v => query.types?.find(x => x.toLowerCase().startsWith(v))) : ["track", "playlist", "artist", "album", /*"text"*/],
|
|
214
|
+
source: LavalinkManagerStatics_1.DefaultSources[(typeof query === "string" ? undefined : query.source?.trim?.()?.toLowerCase?.()) ?? this.LavalinkManager?.options?.playerOptions?.defaultSearchPlatform?.toLowerCase?.()] ?? (typeof query === "string" ? undefined : query.source?.trim?.()?.toLowerCase?.()) ?? this.LavalinkManager?.options?.playerOptions?.defaultSearchPlatform?.toLowerCase?.()
|
|
215
|
+
};
|
|
216
|
+
const foundSource = Object.keys(LavalinkManagerStatics_1.DefaultSources).find(source => Query.query.toLowerCase().startsWith(`${source}:`.toLowerCase()))?.trim?.()?.toLowerCase?.();
|
|
217
|
+
if (foundSource && LavalinkManagerStatics_1.DefaultSources[foundSource]) {
|
|
218
|
+
Query.source = LavalinkManagerStatics_1.DefaultSources[foundSource]; // set the source to ytsearch:
|
|
219
|
+
Query.query = Query.query.slice(`${foundSource}:`.length, Query.query.length); // remove ytsearch: from the query
|
|
220
|
+
}
|
|
221
|
+
return Query;
|
|
222
|
+
}
|
|
197
223
|
validateSourceString(node, sourceString) {
|
|
198
224
|
if (!sourceString)
|
|
199
225
|
throw new Error(`No SourceString was provided`);
|
|
200
226
|
const source = LavalinkManagerStatics_1.DefaultSources[sourceString.toLowerCase().trim()];
|
|
201
227
|
if (!source)
|
|
202
228
|
throw new Error(`Lavalink Node SearchQuerySource: '${sourceString}' is not available`);
|
|
203
|
-
if (
|
|
229
|
+
if (!node.info)
|
|
230
|
+
throw new Error("Lavalink Node does not have any info cached yet, not ready yet!");
|
|
231
|
+
if (source === "amsearch" && !node.info?.sourceManagers?.includes("applemusic")) {
|
|
204
232
|
throw new Error("Lavalink Node has not 'applemusic' enabled, which is required to have 'amsearch' work");
|
|
205
233
|
}
|
|
206
|
-
if (source === "dzisrc" && !node.info
|
|
234
|
+
if (source === "dzisrc" && !node.info?.sourceManagers?.includes("deezer")) {
|
|
207
235
|
throw new Error("Lavalink Node has not 'deezer' enabled, which is required to have 'dzisrc' work");
|
|
208
236
|
}
|
|
209
|
-
if (source === "dzsearch" && !node.info
|
|
237
|
+
if (source === "dzsearch" && !node.info?.sourceManagers?.includes("deezer")) {
|
|
210
238
|
throw new Error("Lavalink Node has not 'deezer' enabled, which is required to have 'dzsearch' work");
|
|
211
239
|
}
|
|
212
|
-
if (source === "dzisrc" && node.info
|
|
240
|
+
if (source === "dzisrc" && node.info?.sourceManagers?.includes("deezer") && !node.info?.sourceManagers?.includes("http")) {
|
|
213
241
|
throw new Error("Lavalink Node has not 'http' enabled, which is required to have 'dzisrc' to work");
|
|
214
242
|
}
|
|
215
|
-
if (source === "dzsearch" && node.info
|
|
243
|
+
if (source === "dzsearch" && node.info?.sourceManagers?.includes("deezer") && !node.info?.sourceManagers?.includes("http")) {
|
|
216
244
|
throw new Error("Lavalink Node has not 'http' enabled, which is required to have 'dzsearch' to work");
|
|
217
245
|
}
|
|
218
|
-
if (source === "scsearch" && !node.info
|
|
246
|
+
if (source === "scsearch" && !node.info?.sourceManagers?.includes("soundcloud")) {
|
|
219
247
|
throw new Error("Lavalink Node has not 'soundcloud' enabled, which is required to have 'scsearch' work");
|
|
220
248
|
}
|
|
221
|
-
if (source === "speak" && !node.info
|
|
249
|
+
if (source === "speak" && !node.info?.plugins?.find(c => c.name.toLowerCase().includes(LavalinkManagerStatics_1.LavalinkPlugins.DuncteBot_Plugin.toLowerCase()))) {
|
|
222
250
|
throw new Error("Lavalink Node has not 'speak' enabled, which is required to have 'speak' work");
|
|
223
251
|
}
|
|
224
|
-
if (source === "tts" && !node.info
|
|
252
|
+
if (source === "tts" && !node.info?.plugins?.find(c => c.name.toLowerCase().includes(LavalinkManagerStatics_1.LavalinkPlugins.GoogleCloudTTS.toLowerCase()))) {
|
|
225
253
|
throw new Error("Lavalink Node has not 'tts' enabled, which is required to have 'tts' work");
|
|
226
254
|
}
|
|
227
|
-
if (source === "ftts" && !(node.info
|
|
255
|
+
if (source === "ftts" && !(node.info?.sourceManagers?.includes("ftts") || node.info?.sourceManagers?.includes("flowery-tts") || node.info?.sourceManagers?.includes("flowerytts"))) {
|
|
228
256
|
throw new Error("Lavalink Node has not 'flowery-tts' enabled, which is required to have 'ftts' work");
|
|
229
257
|
}
|
|
230
|
-
if (source === "ymsearch" && !node.info
|
|
258
|
+
if (source === "ymsearch" && !node.info?.sourceManagers?.includes("yandexmusic")) {
|
|
231
259
|
throw new Error("Lavalink Node has not 'yandexmusic' enabled, which is required to have 'ymsearch' work");
|
|
232
260
|
}
|
|
233
|
-
if (source === "ytmsearch" && !node.info.sourceManagers
|
|
261
|
+
if (source === "ytmsearch" && !node.info.sourceManagers?.includes("youtube")) {
|
|
234
262
|
throw new Error("Lavalink Node has not 'youtube' enabled, which is required to have 'ytmsearch' work");
|
|
235
263
|
}
|
|
236
|
-
if (source === "ytsearch" && !node.info
|
|
264
|
+
if (source === "ytsearch" && !node.info?.sourceManagers?.includes("youtube")) {
|
|
237
265
|
throw new Error("Lavalink Node has not 'youtube' enabled, which is required to have 'ytsearch' work");
|
|
238
266
|
}
|
|
239
267
|
return;
|
|
@@ -46,19 +46,19 @@ export class FilterManager {
|
|
|
46
46
|
},
|
|
47
47
|
vibrato: {
|
|
48
48
|
frequency: 0,
|
|
49
|
-
depth: 0 // 0 < x
|
|
49
|
+
depth: 0 // 0 < x <= 1
|
|
50
50
|
},
|
|
51
51
|
pluginFilters: {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
52
|
+
"lavalink-filter-plugin": {
|
|
53
|
+
echo: {
|
|
54
|
+
delay: 0,
|
|
55
|
+
decay: 0 // 0 < 1
|
|
56
|
+
},
|
|
57
|
+
reverb: {
|
|
58
|
+
delays: [],
|
|
59
|
+
gains: [] // [0.84, 0.83, 0.82, 0.81]
|
|
60
|
+
}
|
|
60
61
|
}
|
|
61
|
-
}*/
|
|
62
62
|
},
|
|
63
63
|
channelMix: audioOutputsData.stereo,
|
|
64
64
|
/*distortion: {
|
|
@@ -95,6 +95,10 @@ export class FilterManager {
|
|
|
95
95
|
delete sendData.pluginFilters?.["lavalink-filter-plugin"]?.echo;
|
|
96
96
|
if (!this.filters.reverb)
|
|
97
97
|
delete sendData.pluginFilters?.["lavalink-filter-plugin"]?.reverb;
|
|
98
|
+
if (sendData.pluginFilters?.["lavalink-filter-plugin"] && Object.values(sendData.pluginFilters?.["lavalink-filter-plugin"]).length === 0)
|
|
99
|
+
delete sendData.pluginFilters["lavalink-filter-plugin"];
|
|
100
|
+
if (sendData.pluginFilters && Object.values(sendData.pluginFilters).length === 0)
|
|
101
|
+
delete sendData.pluginFilters;
|
|
98
102
|
if (!this.filters.lowPass)
|
|
99
103
|
delete sendData.lowPass;
|
|
100
104
|
if (!this.filters.karaoke)
|
|
@@ -108,9 +112,16 @@ export class FilterManager {
|
|
|
108
112
|
if (!this.player.node.sessionId)
|
|
109
113
|
throw new Error("The Lavalink-Node is either not ready or not up to date");
|
|
110
114
|
sendData.equalizer = [...this.equalizerBands];
|
|
115
|
+
if (sendData.equalizer.length === 0)
|
|
116
|
+
delete sendData.equalizer;
|
|
111
117
|
for (const key of [...Object.keys(sendData)]) {
|
|
112
118
|
// delete disabled filters
|
|
113
|
-
if (
|
|
119
|
+
if (key === "pluginFilters") {
|
|
120
|
+
for (const key of [...Object.keys(sendData.pluginFilters)]) {
|
|
121
|
+
// if (this.player.node.info && !this.player.node.info?.plugins?.find?.(v => v.name === key)) delete sendData[key];
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
else if (this.player.node.info && !this.player.node.info?.filters?.includes?.(key))
|
|
114
125
|
delete sendData[key];
|
|
115
126
|
}
|
|
116
127
|
const now = performance.now();
|
|
@@ -163,7 +174,7 @@ export class FilterManager {
|
|
|
163
174
|
this.filters.karaoke = false;
|
|
164
175
|
this.filters.volume = false;
|
|
165
176
|
this.filters.audioOutput = "stereo";
|
|
166
|
-
//
|
|
177
|
+
// reset all filter datas
|
|
167
178
|
for (const [key, value] of Object.entries({
|
|
168
179
|
volume: 1,
|
|
169
180
|
lowPass: {
|
|
@@ -180,13 +191,17 @@ export class FilterManager {
|
|
|
180
191
|
pitch: 1,
|
|
181
192
|
rate: 1 // 0 = x
|
|
182
193
|
},
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
194
|
+
pluginFilters: {
|
|
195
|
+
"lavalink-filter-plugin": {
|
|
196
|
+
echo: {
|
|
197
|
+
delay: 0,
|
|
198
|
+
decay: 0
|
|
199
|
+
},
|
|
200
|
+
reverb: {
|
|
201
|
+
delays: [],
|
|
202
|
+
gains: []
|
|
203
|
+
},
|
|
204
|
+
}
|
|
190
205
|
},
|
|
191
206
|
rotation: {
|
|
192
207
|
rotationHz: 0
|
|
@@ -360,7 +375,7 @@ export class FilterManager {
|
|
|
360
375
|
* @param decay
|
|
361
376
|
* @returns
|
|
362
377
|
*/
|
|
363
|
-
async toggleEcho(delay =
|
|
378
|
+
async toggleEcho(delay = 4, decay = 0.8) {
|
|
364
379
|
if (this.player.node.info && !this.player.node.info?.filters?.includes("echo"))
|
|
365
380
|
throw new Error("Node#Info#filters does not include the 'echo' Filter (Node has it not enable aka not installed!)");
|
|
366
381
|
if (!this.data)
|
|
@@ -369,6 +384,8 @@ export class FilterManager {
|
|
|
369
384
|
this.data.pluginFilters = {};
|
|
370
385
|
if (!this.data.pluginFilters["lavalink-filter-plugin"])
|
|
371
386
|
this.data.pluginFilters["lavalink-filter-plugin"] = { echo: { decay: 0, delay: 0 }, reverb: { delays: [], gains: [] } };
|
|
387
|
+
if (!this.data.pluginFilters["lavalink-filter-plugin"].echo)
|
|
388
|
+
this.data.pluginFilters["lavalink-filter-plugin"].echo = { decay: 0, delay: 0 };
|
|
372
389
|
this.data.pluginFilters["lavalink-filter-plugin"].echo.delay = this.filters.echo ? 0 : delay;
|
|
373
390
|
this.data.pluginFilters["lavalink-filter-plugin"].echo.decay = this.filters.echo ? 0 : decay;
|
|
374
391
|
this.filters.echo = !this.filters.echo;
|
|
@@ -390,6 +407,8 @@ export class FilterManager {
|
|
|
390
407
|
this.data.pluginFilters = {};
|
|
391
408
|
if (!this.data.pluginFilters["lavalink-filter-plugin"])
|
|
392
409
|
this.data.pluginFilters["lavalink-filter-plugin"] = { echo: { decay: 0, delay: 0 }, reverb: { delays: [], gains: [] } };
|
|
410
|
+
if (!this.data.pluginFilters["lavalink-filter-plugin"].reverb)
|
|
411
|
+
this.data.pluginFilters["lavalink-filter-plugin"].reverb = { delays: [], gains: [] };
|
|
393
412
|
this.data.pluginFilters["lavalink-filter-plugin"].reverb.delays = this.filters.reverb ? [] : delays;
|
|
394
413
|
this.data.pluginFilters["lavalink-filter-plugin"].reverb.gains = this.filters.reverb ? [] : gains;
|
|
395
414
|
this.filters.reverb = !this.filters.reverb;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { Dispatcher, Pool } from "undici";
|
|
3
3
|
import { NodeManager } from "./NodeManager";
|
|
4
4
|
import internal from "stream";
|
|
5
|
-
import { InvalidLavalinkRestRequest, LavalinkPlayer, PlayerUpdateInfo, RoutePlanner, Session, Base64, SearchResult } from "./Utils";
|
|
5
|
+
import { InvalidLavalinkRestRequest, LavalinkPlayer, PlayerUpdateInfo, RoutePlanner, Session, Base64, SearchResult, LavaSearchResponse, LavaSearchQuery, SearchQuery } from "./Utils";
|
|
6
6
|
import { DestroyReasonsType } from "./Player";
|
|
7
7
|
import { Track } from "./Track";
|
|
8
8
|
/** Modifies any outgoing REST requests. */
|
|
@@ -135,7 +135,8 @@ export declare class LavalinkNode {
|
|
|
135
135
|
* @returns The returned data
|
|
136
136
|
*/
|
|
137
137
|
request(endpoint: string, modify?: ModifyRequest, parseAsText?: boolean): Promise<unknown>;
|
|
138
|
-
search(
|
|
138
|
+
search(query: SearchQuery, requestUser: unknown): Promise<SearchResult>;
|
|
139
|
+
lavaSearch(query: LavaSearchQuery, requestUser: unknown): Promise<SearchResult | LavaSearchResponse>;
|
|
139
140
|
/**
|
|
140
141
|
* Update the Player State on the Lavalink Server
|
|
141
142
|
* @param data
|
|
@@ -160,7 +161,7 @@ export declare class LavalinkNode {
|
|
|
160
161
|
* Destroys the Node-Connection (Websocket) and all player's of the node
|
|
161
162
|
* @returns
|
|
162
163
|
*/
|
|
163
|
-
destroy(destroyReason?: DestroyReasonsType): void;
|
|
164
|
+
destroy(destroyReason?: DestroyReasonsType, deleteNode?: boolean): void;
|
|
164
165
|
/** Returns if connected to the Node. */
|
|
165
166
|
get connected(): boolean;
|
|
166
167
|
/**
|
|
@@ -92,8 +92,23 @@ export class LavalinkNode {
|
|
|
92
92
|
throw new Error(`Node Request resulted into an error, request-URL: ${url} | headers: ${JSON.stringify(request.headers)}`);
|
|
93
93
|
return parseAsText ? await request.body.text() : await request.body.json();
|
|
94
94
|
}
|
|
95
|
-
async search(
|
|
96
|
-
const
|
|
95
|
+
async search(query, requestUser) {
|
|
96
|
+
const Query = this.NodeManager.LavalinkManager.utils.transformQuery(query);
|
|
97
|
+
if (/^https?:\/\//.test(Query.query))
|
|
98
|
+
this.NodeManager.LavalinkManager.utils.validateQueryString(this, Query.source);
|
|
99
|
+
else if (Query.source)
|
|
100
|
+
this.NodeManager.LavalinkManager.utils.validateSourceString(this, Query.source);
|
|
101
|
+
if (["bcsearch", "bandcamp"].includes(Query.source)) {
|
|
102
|
+
throw new Error("Bandcamp Search only works on the player!");
|
|
103
|
+
}
|
|
104
|
+
let uri = `/loadtracks?identifier=`;
|
|
105
|
+
if (!/^https?:\/\//.test(Query.query))
|
|
106
|
+
uri += `${Query.source}:`;
|
|
107
|
+
if (Query.source === "ftts")
|
|
108
|
+
uri += `//${encodeURIComponent(encodeURI(decodeURIComponent(Query.query)))}`;
|
|
109
|
+
else
|
|
110
|
+
uri += encodeURIComponent(decodeURIComponent(Query.query));
|
|
111
|
+
const res = await this.request(uri);
|
|
97
112
|
// transform the data which can be Error, Track or Track[] to enfore [Track]
|
|
98
113
|
const resTracks = res.loadType === "playlist" ? res.data?.tracks : res.loadType === "track" ? [res.data] : res.loadType === "search" ? Array.isArray(res.data) ? res.data : [res.data] : [];
|
|
99
114
|
return {
|
|
@@ -111,6 +126,28 @@ export class LavalinkNode {
|
|
|
111
126
|
tracks: (resTracks.length ? resTracks.map(t => this.NodeManager.LavalinkManager.utils.buildTrack(t, requestUser)) : [])
|
|
112
127
|
};
|
|
113
128
|
}
|
|
129
|
+
async lavaSearch(query, requestUser) {
|
|
130
|
+
const Query = this.NodeManager.LavalinkManager.utils.transformLavaSearchQuery(query);
|
|
131
|
+
if (Query.source)
|
|
132
|
+
this.NodeManager.LavalinkManager.utils.validateSourceString(this, Query.source);
|
|
133
|
+
if (/^https?:\/\//.test(Query.query))
|
|
134
|
+
return await this.search({ query: Query.query, source: Query.source }, requestUser);
|
|
135
|
+
if (!["spsearch", "sprec", "amsearch", "dzsearch", "dzisrc", "ytmsearch", "ytsearch"].includes(Query.source))
|
|
136
|
+
throw new SyntaxError(`Query.source must be a source from LavaSrc: "spsearch" | "sprec" | "amsearch" | "dzsearch" | "dzisrc" | "ytmsearch" | "ytsearch"`);
|
|
137
|
+
if (!this.info.plugins.find(v => v.name === "lavasearch-plugin"))
|
|
138
|
+
throw new RangeError(`there is no lavasearch-plugin available in the lavalink node: ${this.id}`);
|
|
139
|
+
if (!this.info.plugins.find(v => v.name === "lavasrc-plugin"))
|
|
140
|
+
throw new RangeError(`there is no lavasrc-plugin available in the lavalink node: ${this.id}`);
|
|
141
|
+
const res = await this.request(`/loadsearch?query=${Query.source ? `${Query.source}:` : ""}${encodeURIComponent(Query.query)}${Query.types?.length ? `&types=${Query.types.join(",")}` : ""}`);
|
|
142
|
+
return {
|
|
143
|
+
tracks: res.tracks?.map(v => this.NodeManager.LavalinkManager.utils.buildTrack(v, requestUser)) || [],
|
|
144
|
+
albums: res.albums?.map(v => ({ info: v.info, pluginInfo: v?.plugin || v.pluginInfo, tracks: v.tracks.map(v => this.NodeManager.LavalinkManager.utils.buildTrack(v, requestUser)) })) || [],
|
|
145
|
+
artists: res.artists?.map(v => ({ info: v.info, pluginInfo: v?.plugin || v.pluginInfo, tracks: v.tracks.map(v => this.NodeManager.LavalinkManager.utils.buildTrack(v, requestUser)) })) || [],
|
|
146
|
+
playlists: res.playlists?.map(v => ({ info: v.info, pluginInfo: v?.plugin || v.pluginInfo, tracks: v.tracks.map(v => this.NodeManager.LavalinkManager.utils.buildTrack(v, requestUser)) })) || [],
|
|
147
|
+
texts: res.texts?.map(v => ({ text: v.text, pluginInfo: v?.plugin || v.pluginInfo })) || [],
|
|
148
|
+
pluginInfo: res.pluginInfo || res?.plugin
|
|
149
|
+
};
|
|
150
|
+
}
|
|
114
151
|
/**
|
|
115
152
|
* Update the Player State on the Lavalink Server
|
|
116
153
|
* @param data
|
|
@@ -164,7 +201,7 @@ export class LavalinkNode {
|
|
|
164
201
|
}
|
|
165
202
|
this.socket = new WebSocket(`ws${this.options.secure ? "s" : ""}://${this.options.host}:${this.options.port}/v4/websocket`, { headers });
|
|
166
203
|
this.socket.on("open", this.open.bind(this));
|
|
167
|
-
this.socket.on("close", this.close
|
|
204
|
+
this.socket.on("close", (code, reason) => this.close(code, reason?.toString()));
|
|
168
205
|
this.socket.on("message", this.message.bind(this));
|
|
169
206
|
this.socket.on("error", this.error.bind(this));
|
|
170
207
|
}
|
|
@@ -176,19 +213,24 @@ export class LavalinkNode {
|
|
|
176
213
|
* Destroys the Node-Connection (Websocket) and all player's of the node
|
|
177
214
|
* @returns
|
|
178
215
|
*/
|
|
179
|
-
destroy(destroyReason) {
|
|
216
|
+
destroy(destroyReason, deleteNode = true) {
|
|
180
217
|
if (!this.connected)
|
|
181
218
|
return;
|
|
182
219
|
const players = this.NodeManager.LavalinkManager.players.filter(p => p.node.id == this.id);
|
|
183
220
|
if (players)
|
|
184
221
|
players.forEach(p => p.destroy(destroyReason || DestroyReasons.NodeDestroy));
|
|
185
|
-
this.socket.close(1000, "
|
|
222
|
+
this.socket.close(1000, "Node-Destroy");
|
|
186
223
|
this.socket.removeAllListeners();
|
|
187
224
|
this.socket = null;
|
|
188
225
|
this.reconnectAttempts = 1;
|
|
189
226
|
clearTimeout(this.reconnectTimeout);
|
|
190
|
-
|
|
191
|
-
|
|
227
|
+
if (deleteNode) {
|
|
228
|
+
this.NodeManager.emit("destroy", this, destroyReason);
|
|
229
|
+
this.NodeManager.nodes.delete(this.id);
|
|
230
|
+
}
|
|
231
|
+
else {
|
|
232
|
+
this.NodeManager.emit("disconnect", this, { code: 1000, reason: destroyReason });
|
|
233
|
+
}
|
|
192
234
|
return;
|
|
193
235
|
}
|
|
194
236
|
/** Returns if connected to the Node. */
|
|
@@ -402,7 +444,20 @@ export class LavalinkNode {
|
|
|
402
444
|
get poolAddress() {
|
|
403
445
|
return `http${this.options.secure ? "s" : ""}://${this.options.host}:${this.options.port}`;
|
|
404
446
|
}
|
|
405
|
-
reconnect() {
|
|
447
|
+
reconnect(instaReconnect = false) {
|
|
448
|
+
if (instaReconnect) {
|
|
449
|
+
if (this.reconnectAttempts >= this.options.retryAmount) {
|
|
450
|
+
const error = new Error(`Unable to connect after ${this.options.retryAmount} attempts.`);
|
|
451
|
+
this.NodeManager.emit("error", this, error);
|
|
452
|
+
return this.destroy(DestroyReasons.NodeReconnectFail);
|
|
453
|
+
}
|
|
454
|
+
this.socket.removeAllListeners();
|
|
455
|
+
this.socket = null;
|
|
456
|
+
this.NodeManager.emit("reconnecting", this);
|
|
457
|
+
this.connect();
|
|
458
|
+
this.reconnectAttempts++;
|
|
459
|
+
return;
|
|
460
|
+
}
|
|
406
461
|
this.reconnectTimeout = setTimeout(() => {
|
|
407
462
|
if (this.reconnectAttempts >= this.options.retryAmount) {
|
|
408
463
|
const error = new Error(`Unable to connect after ${this.options.retryAmount} attempts.`);
|
|
@@ -433,7 +488,7 @@ export class LavalinkNode {
|
|
|
433
488
|
}
|
|
434
489
|
close(code, reason) {
|
|
435
490
|
this.NodeManager.emit("disconnect", this, { code, reason });
|
|
436
|
-
if (code !== 1000 || reason !== "
|
|
491
|
+
if (code !== 1000 || reason !== "Node-Destroy")
|
|
437
492
|
this.reconnect();
|
|
438
493
|
}
|
|
439
494
|
error(error) {
|
|
@@ -54,6 +54,22 @@ export declare interface NodeManager {
|
|
|
54
54
|
export declare class NodeManager extends EventEmitter {
|
|
55
55
|
nodes: MiniMap<string, LavalinkNode>;
|
|
56
56
|
constructor(LavalinkManager: LavalinkManager);
|
|
57
|
+
/**
|
|
58
|
+
* Disconnects all Nodes from lavalink ws sockets
|
|
59
|
+
* @param deleteAllNodes if the nodes should also be deleted from nodeManager.nodes
|
|
60
|
+
* @returns amount of disconnected Nodes
|
|
61
|
+
*/
|
|
62
|
+
disconnectAll(deleteAllNodes?: boolean): Promise<number>;
|
|
63
|
+
/**
|
|
64
|
+
* Connects all not connected nodes
|
|
65
|
+
* @returns Amount of connected Nodes
|
|
66
|
+
*/
|
|
67
|
+
connectAll(): Promise<number>;
|
|
68
|
+
/**
|
|
69
|
+
* Forcefully reconnects all nodes
|
|
70
|
+
* @returns amount of nodes
|
|
71
|
+
*/
|
|
72
|
+
reconnectAll(): Promise<number>;
|
|
57
73
|
createNode(options: LavalinkNodeOptions): LavalinkNode;
|
|
58
74
|
leastUsedNodes(sortType?: "memory" | "cpuLavalink" | "cpuSystem" | "calls" | "playingPlayers" | "players"): LavalinkNode[];
|
|
59
75
|
deleteNode(node: LavalinkNodeIdentifier | LavalinkNode): void;
|
|
@@ -10,6 +10,59 @@ export class NodeManager extends EventEmitter {
|
|
|
10
10
|
if (this.LavalinkManager.options.nodes)
|
|
11
11
|
this.LavalinkManager.options.nodes.forEach(node => this.createNode(node));
|
|
12
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* Disconnects all Nodes from lavalink ws sockets
|
|
15
|
+
* @param deleteAllNodes if the nodes should also be deleted from nodeManager.nodes
|
|
16
|
+
* @returns amount of disconnected Nodes
|
|
17
|
+
*/
|
|
18
|
+
async disconnectAll(deleteAllNodes = false) {
|
|
19
|
+
if (!this.nodes.size)
|
|
20
|
+
throw new Error("There are no nodes to disconnect (no nodes in the nodemanager)");
|
|
21
|
+
if (!this.nodes.filter(v => v.connected).size)
|
|
22
|
+
throw new Error("There are no nodes to disconnect (all nodes disconnected)");
|
|
23
|
+
let counter = 0;
|
|
24
|
+
for (const node of [...this.nodes.values()]) {
|
|
25
|
+
if (!node.connected)
|
|
26
|
+
continue;
|
|
27
|
+
await node.destroy(DestroyReasons.DisconnectAllNodes, deleteAllNodes);
|
|
28
|
+
counter++;
|
|
29
|
+
}
|
|
30
|
+
return counter;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Connects all not connected nodes
|
|
34
|
+
* @returns Amount of connected Nodes
|
|
35
|
+
*/
|
|
36
|
+
async connectAll() {
|
|
37
|
+
if (!this.nodes.size)
|
|
38
|
+
throw new Error("There are no nodes to connect (no nodes in the nodemanager)");
|
|
39
|
+
if (!this.nodes.filter(v => !v.connected).size)
|
|
40
|
+
throw new Error("There are no nodes to connect (all nodes connected)");
|
|
41
|
+
let counter = 0;
|
|
42
|
+
for (const node of [...this.nodes.values()]) {
|
|
43
|
+
if (node.connected)
|
|
44
|
+
continue;
|
|
45
|
+
await node.connect();
|
|
46
|
+
counter++;
|
|
47
|
+
}
|
|
48
|
+
return counter;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Forcefully reconnects all nodes
|
|
52
|
+
* @returns amount of nodes
|
|
53
|
+
*/
|
|
54
|
+
async reconnectAll() {
|
|
55
|
+
if (!this.nodes.size)
|
|
56
|
+
throw new Error("There are no nodes to reconnect (no nodes in the nodemanager)");
|
|
57
|
+
let counter = 0;
|
|
58
|
+
for (const node of [...this.nodes.values()]) {
|
|
59
|
+
const sessionId = node.sessionId ? `${node.sessionId}` : undefined;
|
|
60
|
+
await node.destroy(DestroyReasons.ReconnectAllNodes, false);
|
|
61
|
+
await node.connect(sessionId);
|
|
62
|
+
counter++;
|
|
63
|
+
}
|
|
64
|
+
return counter;
|
|
65
|
+
}
|
|
13
66
|
createNode(options) {
|
|
14
67
|
if (this.nodes.has(options.id || `${options.host}:${options.port}`))
|
|
15
68
|
return this.nodes.get(options.id || `${options.host}:${options.port}`);
|
|
@@ -3,8 +3,8 @@ import { LavalinkManager } from "./LavalinkManager";
|
|
|
3
3
|
import { LavalinkNode } from "./Node";
|
|
4
4
|
import { Queue } from "./Queue";
|
|
5
5
|
import { Track, UnresolvedTrack } from "./Track";
|
|
6
|
-
import { LavalinkPlayerVoiceOptions,
|
|
7
|
-
type PlayerDestroyReasons = "QueueEmpty" | "NodeDestroy" | "NodeDeleted" | "LavalinkNoVoice" | "NodeReconnectFail" | "PlayerReconnectFail" | "Disconnected" | "ChannelDeleted";
|
|
6
|
+
import { LavalinkPlayerVoiceOptions, SearchResult, LavaSearchResponse, LavaSearchQuery, SearchQuery } from "./Utils";
|
|
7
|
+
type PlayerDestroyReasons = "QueueEmpty" | "NodeDestroy" | "NodeDeleted" | "LavalinkNoVoice" | "NodeReconnectFail" | "PlayerReconnectFail" | "Disconnected" | "ChannelDeleted" | "ReconnectAllNodes" | "DisconnectAllNodes";
|
|
8
8
|
export type DestroyReasonsType = PlayerDestroyReasons | string;
|
|
9
9
|
export declare const DestroyReasons: Record<PlayerDestroyReasons, PlayerDestroyReasons>;
|
|
10
10
|
export interface PlayerJson {
|
|
@@ -138,20 +138,13 @@ export declare class Player {
|
|
|
138
138
|
* @param ignoreVolumeDecrementer If it should ignore the volumedecrementer option
|
|
139
139
|
*/
|
|
140
140
|
setVolume(volume: number, ignoreVolumeDecrementer?: boolean): Promise<void>;
|
|
141
|
-
lavaSearch(query:
|
|
142
|
-
query: string;
|
|
143
|
-
source: LavaSrcSearchPlatformBase;
|
|
144
|
-
types?: LavaSearchType[];
|
|
145
|
-
}, requestUser: unknown): Promise<import("./Utils").UnresolvedSearchResult | SearchResult | LavaSearchResponse>;
|
|
141
|
+
lavaSearch(query: LavaSearchQuery, requestUser: unknown): Promise<SearchResult | LavaSearchResponse>;
|
|
146
142
|
/**
|
|
147
143
|
*
|
|
148
144
|
* @param query Query for your data
|
|
149
145
|
* @param requestUser
|
|
150
146
|
*/
|
|
151
|
-
search(query:
|
|
152
|
-
query: string;
|
|
153
|
-
source?: SearchPlatform;
|
|
154
|
-
} | string, requestUser: unknown): Promise<import("./Utils").UnresolvedSearchResult | SearchResult>;
|
|
147
|
+
search(query: SearchQuery, requestUser: unknown): Promise<import("./Utils").UnresolvedSearchResult | SearchResult>;
|
|
155
148
|
/**
|
|
156
149
|
* Pause the player
|
|
157
150
|
*/
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { bandCampSearch } from "./CustomSearches/BandCampSearch";
|
|
2
2
|
import { FilterManager } from "./Filters";
|
|
3
|
-
import { DefaultSources } from "./LavalinkManagerStatics";
|
|
4
3
|
import { Queue, QueueSaver } from "./Queue";
|
|
5
4
|
import { queueTrackEnd } from "./Utils";
|
|
6
5
|
export const DestroyReasons = {
|
|
@@ -11,7 +10,9 @@ export const DestroyReasons = {
|
|
|
11
10
|
NodeReconnectFail: "NodeReconnectFail",
|
|
12
11
|
Disconnected: "Disconnected",
|
|
13
12
|
PlayerReconnectFail: "PlayerReconnectFail",
|
|
14
|
-
ChannelDeleted: "ChannelDeleted"
|
|
13
|
+
ChannelDeleted: "ChannelDeleted",
|
|
14
|
+
DisconnectAllNodes: "DisconnectAllNodes",
|
|
15
|
+
ReconnectAllNodes: "ReconnectAllNodes"
|
|
15
16
|
};
|
|
16
17
|
export class Player {
|
|
17
18
|
/** The Guild Id of the Player */
|
|
@@ -208,35 +209,7 @@ export class Player {
|
|
|
208
209
|
return;
|
|
209
210
|
}
|
|
210
211
|
async lavaSearch(query, requestUser) {
|
|
211
|
-
|
|
212
|
-
const Query = {
|
|
213
|
-
query: typeof query === "string" ? query : query.query,
|
|
214
|
-
types: query.types ? ["track", "playlist", "artist", "album", "text"].filter(v => query.types?.find(x => x.toLowerCase().startsWith(v))) : ["track", "playlist", "artist", "album", "text"],
|
|
215
|
-
source: DefaultSources[(typeof query === "string" ? undefined : query.source?.trim?.()?.toLowerCase?.()) ?? this.LavalinkManager.options.playerOptions.defaultSearchPlatform.toLowerCase()] ?? (typeof query === "string" ? undefined : query.source?.trim?.()?.toLowerCase?.()) ?? this.LavalinkManager.options.playerOptions.defaultSearchPlatform
|
|
216
|
-
};
|
|
217
|
-
// if user does player.search("ytsearch:Hello")
|
|
218
|
-
const foundSource = Object.keys(DefaultSources).find(source => Query.query.toLowerCase().startsWith(`${source}:`.toLowerCase()))?.trim?.()?.toLowerCase?.();
|
|
219
|
-
if (foundSource && DefaultSources[foundSource]) {
|
|
220
|
-
Query.source = DefaultSources[foundSource]; // set the source to ytsearch:
|
|
221
|
-
Query.query = Query.query.slice(`${foundSource}:`.length, Query.query.length); // remove ytsearch: from the query
|
|
222
|
-
}
|
|
223
|
-
if (Query.source)
|
|
224
|
-
this.LavalinkManager.utils.validateSourceString(this.node, Query.source);
|
|
225
|
-
if (!["spsearch", "sprec", "amsearch", "dzsearch", "dzisrc", "ytmsearch", "ytsearch"].includes(Query.source))
|
|
226
|
-
throw new SyntaxError(`Query.source must be a source from LavaSrc: "spsearch" | "sprec" | "amsearch" | "dzsearch" | "dzisrc" | "ytmsearch" | "ytsearch"`);
|
|
227
|
-
if (/^https?:\/\//.test(Query.query))
|
|
228
|
-
return await this.search({ query: Query.query, source: Query.source }, requestUser);
|
|
229
|
-
if (!this.node.info.plugins.find(v => v.name === "lavasearch-plugin"))
|
|
230
|
-
throw new RangeError(`there is no lavasearch-plugin available in the lavalink node: ${this.node.id}`);
|
|
231
|
-
const res = await this.node.request(`/loadsearch?query=${Query.source ? `${Query.source}:` : ""}${encodeURIComponent(Query.query)}${Query.types?.length ? `&types=${Query.types.join(",")}` : ""}`);
|
|
232
|
-
return {
|
|
233
|
-
tracks: res.tracks?.map(v => this.LavalinkManager.utils.buildTrack(v, requestUser)) || [],
|
|
234
|
-
albums: res.albums?.map(v => ({ info: v.info, pluginInfo: v?.plugin || v.pluginInfo, tracks: v.tracks.map(v => this.LavalinkManager.utils.buildTrack(v, requestUser)) })) || [],
|
|
235
|
-
artists: res.artists?.map(v => ({ info: v.info, pluginInfo: v?.plugin || v.pluginInfo, tracks: v.tracks.map(v => this.LavalinkManager.utils.buildTrack(v, requestUser)) })) || [],
|
|
236
|
-
playlists: res.playlists?.map(v => ({ info: v.info, pluginInfo: v?.plugin || v.pluginInfo, tracks: v.tracks.map(v => this.LavalinkManager.utils.buildTrack(v, requestUser)) })) || [],
|
|
237
|
-
texts: res.texts?.map(v => ({ text: v.text, pluginInfo: v?.plugin || v.pluginInfo })) || [],
|
|
238
|
-
pluginInfo: res.pluginInfo || res?.plugin
|
|
239
|
-
};
|
|
212
|
+
return this.node.lavaSearch(query, requestUser);
|
|
240
213
|
}
|
|
241
214
|
/**
|
|
242
215
|
*
|
|
@@ -244,43 +217,14 @@ export class Player {
|
|
|
244
217
|
* @param requestUser
|
|
245
218
|
*/
|
|
246
219
|
async search(query, requestUser) {
|
|
247
|
-
|
|
248
|
-
const Query = {
|
|
249
|
-
query: typeof query === "string" ? query : query.query,
|
|
250
|
-
source: DefaultSources[(typeof query === "string" ? undefined : query.source?.trim?.()?.toLowerCase?.()) ?? this.LavalinkManager.options.playerOptions.defaultSearchPlatform.toLowerCase()] ?? (typeof query === "string" ? undefined : query.source?.trim?.()?.toLowerCase?.()) ?? this.LavalinkManager.options.playerOptions.defaultSearchPlatform
|
|
251
|
-
};
|
|
252
|
-
// if user does player.search("ytsearch:Hello")
|
|
253
|
-
const foundSource = Object.keys(DefaultSources).find(source => Query.query?.toLowerCase?.()?.startsWith(`${source}:`.toLowerCase()))?.trim?.()?.toLowerCase?.();
|
|
254
|
-
if (foundSource && DefaultSources[foundSource]) {
|
|
255
|
-
Query.source = DefaultSources[foundSource]; // set the source to ytsearch:
|
|
256
|
-
Query.query = Query.query.slice(`${foundSource}:`.length, Query.query.length); // remove ytsearch: from the query
|
|
257
|
-
}
|
|
220
|
+
const Query = this.LavalinkManager.utils.transformQuery(query);
|
|
258
221
|
if (/^https?:\/\//.test(Query.query))
|
|
259
222
|
this.LavalinkManager.utils.validateQueryString(this.node, Query.source);
|
|
260
223
|
else if (Query.source)
|
|
261
224
|
this.LavalinkManager.utils.validateSourceString(this.node, Query.source);
|
|
262
|
-
if (["bcsearch", "bandcamp"].includes(Query.source))
|
|
225
|
+
if (["bcsearch", "bandcamp"].includes(Query.source))
|
|
263
226
|
return await bandCampSearch(this, Query.query, requestUser);
|
|
264
|
-
|
|
265
|
-
// ftts query parameters: ?voice=Olivia&audio_format=ogg_opus&translate=False&silence=1000&speed=1.0 | example raw get query: https://api.flowery.pw/v1/tts?voice=Olivia&audio_format=ogg_opus&translate=False&silence=0&speed=1.0&text=Hello%20World
|
|
266
|
-
// request the data
|
|
267
|
-
const res = await this.node.request(`/loadtracks?identifier=${!/^https?:\/\//.test(Query.query) ? `${Query.source}:${Query.source === "ftts" ? "//" : ""}` : ""}${encodeURIComponent(Query.query)}`);
|
|
268
|
-
// transform the data which can be Error, Track or Track[] to enfore [Track]
|
|
269
|
-
const resTracks = res.loadType === "playlist" ? res.data?.tracks : res.loadType === "track" ? [res.data] : res.loadType === "search" ? Array.isArray(res.data) ? res.data : [res.data] : [];
|
|
270
|
-
return {
|
|
271
|
-
loadType: res.loadType,
|
|
272
|
-
exception: res.loadType === "error" ? res.data : null,
|
|
273
|
-
pluginInfo: res.pluginInfo || {},
|
|
274
|
-
playlist: res.loadType === "playlist" ? {
|
|
275
|
-
title: res.data.info?.name || res.data.pluginInfo?.name || null,
|
|
276
|
-
author: res.data.info?.author || res.data.pluginInfo?.author || null,
|
|
277
|
-
thumbnail: (res.data.info?.artworkUrl) || (res.data.pluginInfo?.artworkUrl) || ((typeof res.data?.info?.selectedTrack !== "number" || res.data?.info?.selectedTrack === -1) ? null : resTracks[res.data?.info?.selectedTrack] ? (resTracks[res.data?.info?.selectedTrack]?.info?.artworkUrl || resTracks[res.data?.info?.selectedTrack]?.info?.pluginInfo?.artworkUrl) : null) || null,
|
|
278
|
-
uri: res.data.info?.url || res.data.info?.uri || res.data.info?.link || res.data.pluginInfo?.url || res.data.pluginInfo?.uri || res.data.pluginInfo?.link || null,
|
|
279
|
-
selectedTrack: typeof res.data?.info?.selectedTrack !== "number" || res.data?.info?.selectedTrack === -1 ? null : resTracks[res.data?.info?.selectedTrack] ? this.LavalinkManager.utils.buildTrack(resTracks[res.data?.info?.selectedTrack], requestUser) : null,
|
|
280
|
-
duration: resTracks.length ? resTracks.reduce((acc, cur) => acc + (cur?.info?.duration || 0), 0) : 0,
|
|
281
|
-
} : null,
|
|
282
|
-
tracks: resTracks.length ? resTracks.map(t => this.LavalinkManager.utils.buildTrack(t, requestUser)) : []
|
|
283
|
-
};
|
|
227
|
+
return this.node.search(Query, requestUser);
|
|
284
228
|
}
|
|
285
229
|
/**
|
|
286
230
|
* Pause the player
|