lavalink-client 1.1.10 → 1.1.12
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/CustomSearches/BandCampSearch.d.ts +3 -0
- package/dist/cjs/structures/CustomSearches/BandCampSearch.js +36 -0
- package/dist/cjs/structures/Filters.d.ts +12 -5
- package/dist/cjs/structures/Filters.js +71 -32
- package/dist/cjs/structures/LavalinkManagerStatics.js +4 -1
- package/dist/cjs/structures/Node.d.ts +2 -1
- package/dist/cjs/structures/Node.js +21 -2
- package/dist/cjs/structures/Player.d.ts +2 -2
- package/dist/cjs/structures/Player.js +6 -1
- package/dist/cjs/structures/Utils.d.ts +11 -2
- package/dist/cjs/structures/Utils.js +41 -39
- package/dist/esm/structures/CustomSearches/BandCampSearch.d.ts +3 -0
- package/dist/esm/structures/CustomSearches/BandCampSearch.js +32 -0
- package/dist/esm/structures/Filters.d.ts +12 -5
- package/dist/esm/structures/Filters.js +71 -32
- package/dist/esm/structures/LavalinkManagerStatics.js +4 -1
- package/dist/esm/structures/Node.d.ts +2 -1
- package/dist/esm/structures/Node.js +21 -2
- package/dist/esm/structures/Player.d.ts +2 -2
- package/dist/esm/structures/Player.js +6 -1
- package/dist/esm/structures/Utils.d.ts +11 -2
- package/dist/esm/structures/Utils.js +41 -39
- package/dist/types/structures/CustomSearches/BandCampSearch.d.ts +3 -0
- package/dist/types/structures/Filters.d.ts +12 -5
- package/dist/types/structures/Node.d.ts +2 -1
- package/dist/types/structures/Player.d.ts +2 -2
- package/dist/types/structures/Utils.d.ts +11 -2
- package/package.json +1 -1
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.bandCampSearch = void 0;
|
|
4
|
+
const undici_1 = require("undici");
|
|
5
|
+
const http_1 = require("http");
|
|
6
|
+
const bandCampSearch = async (player, query, requestUser) => {
|
|
7
|
+
let error = null;
|
|
8
|
+
let tracks = [];
|
|
9
|
+
try {
|
|
10
|
+
const data = await (0, undici_1.fetch)(`https://bandcamp.com/api/nusearch/2/autocomplete?q=${encodeURIComponent(query)}`, {
|
|
11
|
+
headers: {
|
|
12
|
+
'User-Agent': 'android-async-http/1.4.1 (http://loopj.com/android-async-http)',
|
|
13
|
+
'Cookie': '$Version=1'
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
const json = await data.json();
|
|
17
|
+
tracks = json?.results?.filter(x => !!x && typeof x === "object" && "type" in x && x.type === "t").map?.(item => player.LavalinkManager.utils.buildUnresolvedTrack({
|
|
18
|
+
uri: item.url || item.uri,
|
|
19
|
+
artworkUrl: item.img,
|
|
20
|
+
author: item.band_name,
|
|
21
|
+
title: item.name,
|
|
22
|
+
identifier: item.id ? `${item.id}` : item.url?.split("/").reverse()[0],
|
|
23
|
+
}, http_1.request));
|
|
24
|
+
}
|
|
25
|
+
catch (e) {
|
|
26
|
+
error = e;
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
loadType: "search",
|
|
30
|
+
exception: error,
|
|
31
|
+
pluginInfo: {},
|
|
32
|
+
playlist: null,
|
|
33
|
+
tracks: tracks
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
exports.bandCampSearch = bandCampSearch;
|
|
@@ -95,11 +95,11 @@ export declare class FilterManager {
|
|
|
95
95
|
toggleEcho(delay?: number, decay?: number): Promise<boolean>;
|
|
96
96
|
/**
|
|
97
97
|
* Enabels / Disables the Echo effect, IMPORTANT! Only works with the correct Lavalink Plugin installed. (Optional: provide your Own Data)
|
|
98
|
-
* @param
|
|
99
|
-
* @param
|
|
98
|
+
* @param delays
|
|
99
|
+
* @param gains
|
|
100
100
|
* @returns
|
|
101
101
|
*/
|
|
102
|
-
toggleReverb(
|
|
102
|
+
toggleReverb(delays?: number[], gains?: number[]): Promise<boolean>;
|
|
103
103
|
/**
|
|
104
104
|
* Enables / Disabels a Nightcore-like filter Effect. Disables/Overwrides both: custom and Vaporwave Filter
|
|
105
105
|
* @param speed
|
|
@@ -276,8 +276,8 @@ export interface EchoFilter {
|
|
|
276
276
|
* A Plugin Filter
|
|
277
277
|
*/
|
|
278
278
|
export interface ReverbFilter {
|
|
279
|
-
|
|
280
|
-
|
|
279
|
+
delays: number[];
|
|
280
|
+
gains: number[];
|
|
281
281
|
}
|
|
282
282
|
/**
|
|
283
283
|
* Filter Data stored in the Client and partially sent to Lavalink
|
|
@@ -292,6 +292,13 @@ export interface FilterData {
|
|
|
292
292
|
distortion?: DistortionFilter;
|
|
293
293
|
channelMix?: ChannelMixFilter;
|
|
294
294
|
lowPass?: LowPassFilter;
|
|
295
|
+
pluginFilters?: Record<PluginFiltersKey, PluginFiltersValues>;
|
|
296
|
+
}
|
|
297
|
+
export type PluginFiltersKey = "lavalink-filter-plugin" | string;
|
|
298
|
+
export interface PluginFiltersValues extends LavalinkFiltersPlugin {
|
|
299
|
+
[key: string]: any;
|
|
300
|
+
}
|
|
301
|
+
export interface LavalinkFiltersPlugin {
|
|
295
302
|
echo: EchoFilter;
|
|
296
303
|
reverb: ReverbFilter;
|
|
297
304
|
}
|
|
@@ -40,14 +40,6 @@ class FilterManager {
|
|
|
40
40
|
pitch: 1,
|
|
41
41
|
rate: 1 // 0 = x
|
|
42
42
|
},
|
|
43
|
-
echo: {
|
|
44
|
-
delay: 0,
|
|
45
|
-
decay: 0
|
|
46
|
-
},
|
|
47
|
-
reverb: {
|
|
48
|
-
delay: 0,
|
|
49
|
-
decay: 0
|
|
50
|
-
},
|
|
51
43
|
rotation: {
|
|
52
44
|
rotationHz: 0
|
|
53
45
|
},
|
|
@@ -57,7 +49,19 @@ class FilterManager {
|
|
|
57
49
|
},
|
|
58
50
|
vibrato: {
|
|
59
51
|
frequency: 0,
|
|
60
|
-
depth: 0 // 0 < x
|
|
52
|
+
depth: 0 // 0 < x <= 1
|
|
53
|
+
},
|
|
54
|
+
pluginFilters: {
|
|
55
|
+
"lavalink-filter-plugin": {
|
|
56
|
+
echo: {
|
|
57
|
+
delay: 0,
|
|
58
|
+
decay: 0 // 0 < 1
|
|
59
|
+
},
|
|
60
|
+
reverb: {
|
|
61
|
+
delays: [],
|
|
62
|
+
gains: [] // [0.84, 0.83, 0.82, 0.81]
|
|
63
|
+
}
|
|
64
|
+
}
|
|
61
65
|
},
|
|
62
66
|
channelMix: exports.audioOutputsData.stereo,
|
|
63
67
|
/*distortion: {
|
|
@@ -83,30 +87,44 @@ class FilterManager {
|
|
|
83
87
|
*/
|
|
84
88
|
async applyPlayerFilters() {
|
|
85
89
|
const sendData = { ...this.data };
|
|
90
|
+
this.checkFiltersState();
|
|
86
91
|
if (!this.filters.volume)
|
|
87
92
|
delete sendData.volume;
|
|
88
93
|
if (!this.filters.tremolo)
|
|
89
94
|
delete sendData.tremolo;
|
|
90
95
|
if (!this.filters.vibrato)
|
|
91
96
|
delete sendData.vibrato;
|
|
92
|
-
//if(!this.filters.karaoke) delete sendData.karaoke;
|
|
93
97
|
if (!this.filters.echo)
|
|
94
|
-
delete sendData.echo;
|
|
98
|
+
delete sendData.pluginFilters?.["lavalink-filter-plugin"]?.echo;
|
|
95
99
|
if (!this.filters.reverb)
|
|
96
|
-
delete sendData.reverb;
|
|
100
|
+
delete sendData.pluginFilters?.["lavalink-filter-plugin"]?.reverb;
|
|
101
|
+
if (sendData.pluginFilters?.["lavalink-filter-plugin"] && Object.values(sendData.pluginFilters?.["lavalink-filter-plugin"]).length === 0)
|
|
102
|
+
delete sendData.pluginFilters["lavalink-filter-plugin"];
|
|
103
|
+
if (sendData.pluginFilters && Object.values(sendData.pluginFilters).length === 0)
|
|
104
|
+
delete sendData.pluginFilters;
|
|
97
105
|
if (!this.filters.lowPass)
|
|
98
106
|
delete sendData.lowPass;
|
|
99
107
|
if (!this.filters.karaoke)
|
|
100
108
|
delete sendData.karaoke;
|
|
101
|
-
|
|
109
|
+
if (!this.filters.rotation)
|
|
110
|
+
delete sendData.rotation;
|
|
102
111
|
if (this.filters.audioOutput === "stereo")
|
|
103
112
|
delete sendData.channelMix;
|
|
113
|
+
if (Object.values(this.data.timescale).every(v => v === 1))
|
|
114
|
+
delete sendData.timescale;
|
|
104
115
|
if (!this.player.node.sessionId)
|
|
105
116
|
throw new Error("The Lavalink-Node is either not ready or not up to date");
|
|
106
117
|
sendData.equalizer = [...this.equalizerBands];
|
|
118
|
+
if (sendData.equalizer.length === 0)
|
|
119
|
+
delete sendData.equalizer;
|
|
107
120
|
for (const key of [...Object.keys(sendData)]) {
|
|
108
121
|
// delete disabled filters
|
|
109
|
-
if (
|
|
122
|
+
if (key === "pluginFilters") {
|
|
123
|
+
for (const key of [...Object.keys(sendData.pluginFilters)]) {
|
|
124
|
+
// if (this.player.node.info && !this.player.node.info?.plugins?.find?.(v => v.name === key)) delete sendData[key];
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
else if (this.player.node.info && !this.player.node.info?.filters?.includes?.(key))
|
|
110
128
|
delete sendData[key];
|
|
111
129
|
}
|
|
112
130
|
const now = performance.now();
|
|
@@ -130,8 +148,9 @@ class FilterManager {
|
|
|
130
148
|
this.filters.rotation = this.data.rotation.rotationHz !== 0;
|
|
131
149
|
this.filters.vibrato = this.data.vibrato.frequency !== 0 || this.data.vibrato.depth !== 0;
|
|
132
150
|
this.filters.tremolo = this.data.tremolo.frequency !== 0 || this.data.tremolo.depth !== 0;
|
|
133
|
-
|
|
134
|
-
this.filters.
|
|
151
|
+
const lavalinkFilterData = (this.data.pluginFilters?.["lavalink-filter-plugin"] || { echo: { decay: 0, delay: 0 }, reverb: { gains: [], delays: [] } });
|
|
152
|
+
this.filters.echo = lavalinkFilterData.echo.decay !== 0 || lavalinkFilterData.echo.delay !== 0;
|
|
153
|
+
this.filters.reverb = lavalinkFilterData.reverb?.delays?.length !== 0 || lavalinkFilterData.reverb?.gains?.length !== 0;
|
|
135
154
|
this.filters.lowPass = this.data.lowPass.smoothing !== 0;
|
|
136
155
|
this.filters.karaoke = Object.values(this.data.karaoke).some(v => v !== 0);
|
|
137
156
|
if ((this.filters.nightcore || this.filters.vaporwave) && oldFilterTimescale) {
|
|
@@ -158,7 +177,7 @@ class FilterManager {
|
|
|
158
177
|
this.filters.karaoke = false;
|
|
159
178
|
this.filters.volume = false;
|
|
160
179
|
this.filters.audioOutput = "stereo";
|
|
161
|
-
//
|
|
180
|
+
// reset all filter datas
|
|
162
181
|
for (const [key, value] of Object.entries({
|
|
163
182
|
volume: 1,
|
|
164
183
|
lowPass: {
|
|
@@ -175,13 +194,17 @@ class FilterManager {
|
|
|
175
194
|
pitch: 1,
|
|
176
195
|
rate: 1 // 0 = x
|
|
177
196
|
},
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
197
|
+
pluginFilters: {
|
|
198
|
+
"lavalink-filter-plugin": {
|
|
199
|
+
echo: {
|
|
200
|
+
delay: 0,
|
|
201
|
+
decay: 0
|
|
202
|
+
},
|
|
203
|
+
reverb: {
|
|
204
|
+
delays: [],
|
|
205
|
+
gains: []
|
|
206
|
+
},
|
|
207
|
+
}
|
|
185
208
|
},
|
|
186
209
|
rotation: {
|
|
187
210
|
rotationHz: 0
|
|
@@ -355,26 +378,42 @@ class FilterManager {
|
|
|
355
378
|
* @param decay
|
|
356
379
|
* @returns
|
|
357
380
|
*/
|
|
358
|
-
async toggleEcho(delay =
|
|
381
|
+
async toggleEcho(delay = 4, decay = 0.8) {
|
|
359
382
|
if (this.player.node.info && !this.player.node.info?.filters?.includes("echo"))
|
|
360
383
|
throw new Error("Node#Info#filters does not include the 'echo' Filter (Node has it not enable aka not installed!)");
|
|
361
|
-
this.data
|
|
362
|
-
|
|
384
|
+
if (!this.data)
|
|
385
|
+
this.data = {};
|
|
386
|
+
if (!this.data.pluginFilters)
|
|
387
|
+
this.data.pluginFilters = {};
|
|
388
|
+
if (!this.data.pluginFilters["lavalink-filter-plugin"])
|
|
389
|
+
this.data.pluginFilters["lavalink-filter-plugin"] = { echo: { decay: 0, delay: 0 }, reverb: { delays: [], gains: [] } };
|
|
390
|
+
if (!this.data.pluginFilters["lavalink-filter-plugin"].echo)
|
|
391
|
+
this.data.pluginFilters["lavalink-filter-plugin"].echo = { decay: 0, delay: 0 };
|
|
392
|
+
this.data.pluginFilters["lavalink-filter-plugin"].echo.delay = this.filters.echo ? 0 : delay;
|
|
393
|
+
this.data.pluginFilters["lavalink-filter-plugin"].echo.decay = this.filters.echo ? 0 : decay;
|
|
363
394
|
this.filters.echo = !this.filters.echo;
|
|
364
395
|
await this.applyPlayerFilters();
|
|
365
396
|
return this.filters.echo;
|
|
366
397
|
}
|
|
367
398
|
/**
|
|
368
399
|
* Enabels / Disables the Echo effect, IMPORTANT! Only works with the correct Lavalink Plugin installed. (Optional: provide your Own Data)
|
|
369
|
-
* @param
|
|
370
|
-
* @param
|
|
400
|
+
* @param delays
|
|
401
|
+
* @param gains
|
|
371
402
|
* @returns
|
|
372
403
|
*/
|
|
373
|
-
async toggleReverb(
|
|
404
|
+
async toggleReverb(delays = [0.037, 0.042, 0.048, 0.053], gains = [0.84, 0.83, 0.82, 0.81]) {
|
|
374
405
|
if (this.player.node.info && !this.player.node.info?.filters?.includes("reverb"))
|
|
375
406
|
throw new Error("Node#Info#filters does not include the 'reverb' Filter (Node has it not enable aka not installed!)");
|
|
376
|
-
this.data
|
|
377
|
-
|
|
407
|
+
if (!this.data)
|
|
408
|
+
this.data = {};
|
|
409
|
+
if (!this.data.pluginFilters)
|
|
410
|
+
this.data.pluginFilters = {};
|
|
411
|
+
if (!this.data.pluginFilters["lavalink-filter-plugin"])
|
|
412
|
+
this.data.pluginFilters["lavalink-filter-plugin"] = { echo: { decay: 0, delay: 0 }, reverb: { delays: [], gains: [] } };
|
|
413
|
+
if (!this.data.pluginFilters["lavalink-filter-plugin"].reverb)
|
|
414
|
+
this.data.pluginFilters["lavalink-filter-plugin"].reverb = { delays: [], gains: [] };
|
|
415
|
+
this.data.pluginFilters["lavalink-filter-plugin"].reverb.delays = this.filters.reverb ? [] : delays;
|
|
416
|
+
this.data.pluginFilters["lavalink-filter-plugin"].reverb.gains = this.filters.reverb ? [] : gains;
|
|
378
417
|
this.filters.reverb = !this.filters.reverb;
|
|
379
418
|
await this.applyPlayerFilters();
|
|
380
419
|
return this.filters.reverb;
|
|
@@ -40,7 +40,10 @@ exports.DefaultSources = {
|
|
|
40
40
|
// speak PLUGIN
|
|
41
41
|
"speak": "speak",
|
|
42
42
|
"tts": "tts",
|
|
43
|
-
"ftts": "ftts"
|
|
43
|
+
"ftts": "ftts",
|
|
44
|
+
// Client sided search platforms
|
|
45
|
+
"bandcamp": "bcsearch",
|
|
46
|
+
"bcsearch": "bcsearch",
|
|
44
47
|
};
|
|
45
48
|
exports.LavalinkPlugins = {
|
|
46
49
|
DuncteBot_Plugin: "DuncteBot-plugin",
|
|
@@ -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 } from "./Utils";
|
|
5
|
+
import { InvalidLavalinkRestRequest, LavalinkPlayer, PlayerUpdateInfo, RoutePlanner, Session, Base64, SearchResult } from "./Utils";
|
|
6
6
|
import { DestroyReasonsType } from "./Player";
|
|
7
7
|
import { Track } from "./Track";
|
|
8
8
|
/** Modifies any outgoing REST requests. */
|
|
@@ -135,6 +135,7 @@ 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(querySourceString: string, requestUser: unknown): Promise<SearchResult>;
|
|
138
139
|
/**
|
|
139
140
|
* Update the Player State on the Lavalink Server
|
|
140
141
|
* @param data
|
|
@@ -96,6 +96,25 @@ class LavalinkNode {
|
|
|
96
96
|
throw new Error(`Node Request resulted into an error, request-URL: ${url} | headers: ${JSON.stringify(request.headers)}`);
|
|
97
97
|
return parseAsText ? await request.body.text() : await request.body.json();
|
|
98
98
|
}
|
|
99
|
+
async search(querySourceString, requestUser) {
|
|
100
|
+
const res = await this.request(`/loadsearch?query=${encodeURIComponent(decodeURIComponent(querySourceString))}`);
|
|
101
|
+
// transform the data which can be Error, Track or Track[] to enfore [Track]
|
|
102
|
+
const resTracks = res.loadType === "playlist" ? res.data?.tracks : res.loadType === "track" ? [res.data] : res.loadType === "search" ? Array.isArray(res.data) ? res.data : [res.data] : [];
|
|
103
|
+
return {
|
|
104
|
+
loadType: res.loadType,
|
|
105
|
+
exception: res.loadType === "error" ? res.data : null,
|
|
106
|
+
pluginInfo: res.pluginInfo || {},
|
|
107
|
+
playlist: res.loadType === "playlist" ? {
|
|
108
|
+
title: res.data.info?.name || res.data.pluginInfo?.name || null,
|
|
109
|
+
author: res.data.info?.author || res.data.pluginInfo?.author || null,
|
|
110
|
+
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,
|
|
111
|
+
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,
|
|
112
|
+
selectedTrack: typeof res.data?.info?.selectedTrack !== "number" || res.data?.info?.selectedTrack === -1 ? null : resTracks[res.data?.info?.selectedTrack] ? this.NodeManager.LavalinkManager.utils.buildTrack(resTracks[res.data?.info?.selectedTrack], requestUser) : null,
|
|
113
|
+
duration: resTracks.length ? resTracks.reduce((acc, cur) => acc + (cur?.info?.duration || 0), 0) : 0,
|
|
114
|
+
} : null,
|
|
115
|
+
tracks: (resTracks.length ? resTracks.map(t => this.NodeManager.LavalinkManager.utils.buildTrack(t, requestUser)) : [])
|
|
116
|
+
};
|
|
117
|
+
}
|
|
99
118
|
/**
|
|
100
119
|
* Update the Player State on the Lavalink Server
|
|
101
120
|
* @param data
|
|
@@ -354,8 +373,8 @@ class LavalinkNode {
|
|
|
354
373
|
player.filterManager.data.timescale = data.playerOptions.filters.timescale;
|
|
355
374
|
if (data.playerOptions.filters.distortion)
|
|
356
375
|
player.filterManager.data.distortion = data.playerOptions.filters.distortion;
|
|
357
|
-
if (data.playerOptions.filters.
|
|
358
|
-
player.filterManager.data.
|
|
376
|
+
if (data.playerOptions.filters.pluginFilters)
|
|
377
|
+
player.filterManager.data.pluginFilters = data.playerOptions.filters.pluginFilters;
|
|
359
378
|
if (data.playerOptions.filters.vibrato)
|
|
360
379
|
player.filterManager.data.vibrato = data.playerOptions.filters.vibrato;
|
|
361
380
|
if (data.playerOptions.filters.volume)
|
|
@@ -142,7 +142,7 @@ export declare class Player {
|
|
|
142
142
|
query: string;
|
|
143
143
|
source: LavaSrcSearchPlatformBase;
|
|
144
144
|
types?: LavaSearchType[];
|
|
145
|
-
}, requestUser: unknown): Promise<SearchResult | LavaSearchResponse>;
|
|
145
|
+
}, requestUser: unknown): Promise<import("./Utils").UnresolvedSearchResult | SearchResult | LavaSearchResponse>;
|
|
146
146
|
/**
|
|
147
147
|
*
|
|
148
148
|
* @param query Query for your data
|
|
@@ -151,7 +151,7 @@ export declare class Player {
|
|
|
151
151
|
search(query: {
|
|
152
152
|
query: string;
|
|
153
153
|
source?: SearchPlatform;
|
|
154
|
-
} | string, requestUser: unknown): Promise<SearchResult>;
|
|
154
|
+
} | string, requestUser: unknown): Promise<import("./Utils").UnresolvedSearchResult | SearchResult>;
|
|
155
155
|
/**
|
|
156
156
|
* Pause the player
|
|
157
157
|
*/
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Player = exports.DestroyReasons = void 0;
|
|
4
|
+
const BandCampSearch_1 = require("./CustomSearches/BandCampSearch");
|
|
4
5
|
const Filters_1 = require("./Filters");
|
|
5
6
|
const LavalinkManagerStatics_1 = require("./LavalinkManagerStatics");
|
|
6
7
|
const Queue_1 = require("./Queue");
|
|
@@ -261,6 +262,9 @@ class Player {
|
|
|
261
262
|
this.LavalinkManager.utils.validateQueryString(this.node, Query.source);
|
|
262
263
|
else if (Query.source)
|
|
263
264
|
this.LavalinkManager.utils.validateSourceString(this.node, Query.source);
|
|
265
|
+
if (["bcsearch", "bandcamp"].includes(Query.source)) {
|
|
266
|
+
return await (0, BandCampSearch_1.bandCampSearch)(this, Query.query, requestUser);
|
|
267
|
+
}
|
|
264
268
|
// 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
|
|
265
269
|
// request the data
|
|
266
270
|
const res = await this.node.request(`/loadtracks?identifier=${!/^https?:\/\//.test(Query.query) ? `${Query.source}:${Query.source === "ftts" ? "//" : ""}` : ""}${encodeURIComponent(Query.query)}`);
|
|
@@ -414,7 +418,6 @@ class Player {
|
|
|
414
418
|
const data = this.toJSON();
|
|
415
419
|
await this.node.destroyPlayer(this.guildId);
|
|
416
420
|
this.node = updateNode;
|
|
417
|
-
await this.connect();
|
|
418
421
|
const now = performance.now();
|
|
419
422
|
await this.node.updatePlayer({
|
|
420
423
|
guildId: this.guildId,
|
|
@@ -424,6 +427,8 @@ class Player {
|
|
|
424
427
|
volume: Math.round(Math.max(Math.min(data.volume, 1000), 0)),
|
|
425
428
|
paused: data.paused,
|
|
426
429
|
filters: { ...data.filters, equalizer: data.equalizer },
|
|
430
|
+
voice: this.voice,
|
|
431
|
+
// track: this.queue.current,
|
|
427
432
|
},
|
|
428
433
|
});
|
|
429
434
|
this.ping.lavalink = Math.round((performance.now() - now) / 10) / 100;
|
|
@@ -15,8 +15,10 @@ export type FloatNumber = Opaque<number, 'Float'>;
|
|
|
15
15
|
export type LavaSrcSearchPlatformBase = "spsearch" | "sprec" | "amsearch" | "dzsearch" | "dzisrc" | "ymsearch";
|
|
16
16
|
export type LavaSrcSearchPlatform = LavaSrcSearchPlatformBase | "ftts";
|
|
17
17
|
export type DuncteSearchPlatform = "speak" | "tts";
|
|
18
|
-
export type
|
|
19
|
-
export type
|
|
18
|
+
export type LavalinkClientSearchPlatform = "bcsearch";
|
|
19
|
+
export type LavalinkClientSearchPlatformResolve = "bandcamp";
|
|
20
|
+
export type LavalinkSearchPlatform = "ytsearch" | "ytmsearch" | "scsearch" | LavaSrcSearchPlatform | DuncteSearchPlatform | LavalinkClientSearchPlatform;
|
|
21
|
+
export type ClientSearchPlatform = "youtube" | "yt" | "youtube music" | "youtubemusic" | "ytm" | "soundcloud" | "sc" | "am" | "apple music" | "applemusic" | "apple" | "sp" | "spsuggestion" | "spotify" | "dz" | "deezer" | "yandex" | "yandex music" | "yandexmusic" | LavalinkClientSearchPlatformResolve | LavalinkClientSearchPlatform;
|
|
20
22
|
export type SearchPlatform = LavalinkSearchPlatform | ClientSearchPlatform;
|
|
21
23
|
export type SourcesRegex = "YoutubeRegex" | "YoutubeMusicRegex" | "SoundCloudRegex" | "SoundCloudMobileRegex" | "DeezerTrackRegex" | "DeezerArtistRegex" | "DeezerEpisodeRegex" | "DeezerMixesRegex" | "DeezerPageLinkRegex" | "DeezerPlaylistRegex" | "DeezerAlbumRegex" | "AllDeezerRegex" | "AllDeezerRegexWithoutPageLink" | "SpotifySongRegex" | "SpotifyPlaylistRegex" | "SpotifyArtistRegex" | "SpotifyEpisodeRegex" | "SpotifyShowRegex" | "SpotifyAlbumRegex" | "AllSpotifyRegex" | "mp3Url" | "m3uUrl" | "m3u8Url" | "mp4Url" | "m4aUrl" | "wavUrl" | "aacpUrl" | "tiktok" | "mixcloud" | "musicYandex" | "radiohost" | "bandcamp" | "appleMusic" | "TwitchTv" | "vimeo";
|
|
22
24
|
export interface PlaylistInfo {
|
|
@@ -42,6 +44,13 @@ export interface SearchResult {
|
|
|
42
44
|
playlist: PlaylistInfo | null;
|
|
43
45
|
tracks: Track[];
|
|
44
46
|
}
|
|
47
|
+
export interface UnresolvedSearchResult {
|
|
48
|
+
loadType: LoadTypes;
|
|
49
|
+
exception: Exception | null;
|
|
50
|
+
pluginInfo: PluginInfo;
|
|
51
|
+
playlist: PlaylistInfo | null;
|
|
52
|
+
tracks: UnresolvedTrack[];
|
|
53
|
+
}
|
|
45
54
|
export declare class ManagerUtils {
|
|
46
55
|
LavalinkManager: LavalinkManager | null;
|
|
47
56
|
constructor(LavalinkManager?: LavalinkManager);
|
|
@@ -56,7 +56,7 @@ class ManagerUtils {
|
|
|
56
56
|
info: query.info ? query.info : query.title ? query : undefined,
|
|
57
57
|
requester: typeof this.LavalinkManager?.options?.playerOptions?.requesterTransformer === "function" ? this.LavalinkManager?.options?.playerOptions?.requesterTransformer((query?.requester || requester)) : requester,
|
|
58
58
|
async resolve(player) {
|
|
59
|
-
const closest = await getClosestTrack(this, player
|
|
59
|
+
const closest = await getClosestTrack(this, player);
|
|
60
60
|
if (!closest)
|
|
61
61
|
throw new SyntaxError("No closest Track found");
|
|
62
62
|
Object.getOwnPropertyNames(this).forEach(prop => delete this[prop]);
|
|
@@ -148,7 +148,7 @@ class ManagerUtils {
|
|
|
148
148
|
return typeof data === "object" && !("info" in data) && typeof data.title === "string";
|
|
149
149
|
}
|
|
150
150
|
async getClosestTrack(data, player) {
|
|
151
|
-
return getClosestTrack(data, player
|
|
151
|
+
return getClosestTrack(data, player);
|
|
152
152
|
}
|
|
153
153
|
validateQueryString(node, queryString) {
|
|
154
154
|
if (!node.info)
|
|
@@ -156,40 +156,40 @@ 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;
|
|
@@ -200,40 +200,42 @@ class ManagerUtils {
|
|
|
200
200
|
const source = LavalinkManagerStatics_1.DefaultSources[sourceString.toLowerCase().trim()];
|
|
201
201
|
if (!source)
|
|
202
202
|
throw new Error(`Lavalink Node SearchQuerySource: '${sourceString}' is not available`);
|
|
203
|
-
if (
|
|
203
|
+
if (!node.info)
|
|
204
|
+
throw new Error("Lavalink Node does not have any info cached yet, not ready yet!");
|
|
205
|
+
if (source === "amsearch" && !node.info?.sourceManagers?.includes("applemusic")) {
|
|
204
206
|
throw new Error("Lavalink Node has not 'applemusic' enabled, which is required to have 'amsearch' work");
|
|
205
207
|
}
|
|
206
|
-
if (source === "dzisrc" && !node.info
|
|
208
|
+
if (source === "dzisrc" && !node.info?.sourceManagers?.includes("deezer")) {
|
|
207
209
|
throw new Error("Lavalink Node has not 'deezer' enabled, which is required to have 'dzisrc' work");
|
|
208
210
|
}
|
|
209
|
-
if (source === "dzsearch" && !node.info
|
|
211
|
+
if (source === "dzsearch" && !node.info?.sourceManagers?.includes("deezer")) {
|
|
210
212
|
throw new Error("Lavalink Node has not 'deezer' enabled, which is required to have 'dzsearch' work");
|
|
211
213
|
}
|
|
212
|
-
if (source === "dzisrc" && node.info
|
|
214
|
+
if (source === "dzisrc" && node.info?.sourceManagers?.includes("deezer") && !node.info?.sourceManagers?.includes("http")) {
|
|
213
215
|
throw new Error("Lavalink Node has not 'http' enabled, which is required to have 'dzisrc' to work");
|
|
214
216
|
}
|
|
215
|
-
if (source === "dzsearch" && node.info
|
|
217
|
+
if (source === "dzsearch" && node.info?.sourceManagers?.includes("deezer") && !node.info?.sourceManagers?.includes("http")) {
|
|
216
218
|
throw new Error("Lavalink Node has not 'http' enabled, which is required to have 'dzsearch' to work");
|
|
217
219
|
}
|
|
218
|
-
if (source === "scsearch" && !node.info
|
|
220
|
+
if (source === "scsearch" && !node.info?.sourceManagers?.includes("soundcloud")) {
|
|
219
221
|
throw new Error("Lavalink Node has not 'soundcloud' enabled, which is required to have 'scsearch' work");
|
|
220
222
|
}
|
|
221
|
-
if (source === "speak" && !node.info
|
|
223
|
+
if (source === "speak" && !node.info?.plugins?.find(c => c.name.toLowerCase().includes(LavalinkManagerStatics_1.LavalinkPlugins.DuncteBot_Plugin.toLowerCase()))) {
|
|
222
224
|
throw new Error("Lavalink Node has not 'speak' enabled, which is required to have 'speak' work");
|
|
223
225
|
}
|
|
224
|
-
if (source === "tts" && !node.info
|
|
226
|
+
if (source === "tts" && !node.info?.plugins?.find(c => c.name.toLowerCase().includes(LavalinkManagerStatics_1.LavalinkPlugins.GoogleCloudTTS.toLowerCase()))) {
|
|
225
227
|
throw new Error("Lavalink Node has not 'tts' enabled, which is required to have 'tts' work");
|
|
226
228
|
}
|
|
227
|
-
if (source === "ftts" && !(node.info
|
|
229
|
+
if (source === "ftts" && !(node.info?.sourceManagers?.includes("ftts") || node.info?.sourceManagers?.includes("flowery-tts") || node.info?.sourceManagers?.includes("flowerytts"))) {
|
|
228
230
|
throw new Error("Lavalink Node has not 'flowery-tts' enabled, which is required to have 'ftts' work");
|
|
229
231
|
}
|
|
230
|
-
if (source === "ymsearch" && !node.info
|
|
232
|
+
if (source === "ymsearch" && !node.info?.sourceManagers?.includes("yandexmusic")) {
|
|
231
233
|
throw new Error("Lavalink Node has not 'yandexmusic' enabled, which is required to have 'ymsearch' work");
|
|
232
234
|
}
|
|
233
|
-
if (source === "ytmsearch" && !node.info.sourceManagers
|
|
235
|
+
if (source === "ytmsearch" && !node.info.sourceManagers?.includes("youtube")) {
|
|
234
236
|
throw new Error("Lavalink Node has not 'youtube' enabled, which is required to have 'ytmsearch' work");
|
|
235
237
|
}
|
|
236
|
-
if (source === "ytsearch" && !node.info
|
|
238
|
+
if (source === "ytsearch" && !node.info?.sourceManagers?.includes("youtube")) {
|
|
237
239
|
throw new Error("Lavalink Node has not 'youtube' enabled, which is required to have 'ytsearch' work");
|
|
238
240
|
}
|
|
239
241
|
return;
|
|
@@ -315,12 +317,12 @@ async function applyUnresolvedData(resTrack, data, utils) {
|
|
|
315
317
|
resTrack.info[key] = data.info[key]; // add non-existing values
|
|
316
318
|
return resTrack;
|
|
317
319
|
}
|
|
318
|
-
async function getClosestTrack(data, player
|
|
320
|
+
async function getClosestTrack(data, player) {
|
|
319
321
|
if (!player || !player.node)
|
|
320
322
|
throw new RangeError("No player with a lavalink node was provided");
|
|
321
|
-
if (utils.isTrack(data))
|
|
322
|
-
return utils.buildTrack(data, data.requester);
|
|
323
|
-
if (!utils.isUnresolvedTrack(data))
|
|
323
|
+
if (player.LavalinkManager.utils.isTrack(data))
|
|
324
|
+
return player.LavalinkManager.utils.buildTrack(data, data.requester);
|
|
325
|
+
if (!player.LavalinkManager.utils.isUnresolvedTrack(data))
|
|
324
326
|
throw new RangeError("Track is not an unresolved Track");
|
|
325
327
|
if (!data?.info?.title && typeof data.encoded !== "string" && !data.info.uri)
|
|
326
328
|
throw new SyntaxError("the track uri / title / encoded Base64 string is required for unresolved tracks");
|
|
@@ -330,31 +332,31 @@ async function getClosestTrack(data, player, utils) {
|
|
|
330
332
|
if (typeof data.encoded === "string") {
|
|
331
333
|
const r = await player.node.decode.singleTrack(data.encoded, data.requester);
|
|
332
334
|
if (r)
|
|
333
|
-
return applyUnresolvedData(r, data, utils);
|
|
335
|
+
return applyUnresolvedData(r, data, player.LavalinkManager.utils);
|
|
334
336
|
}
|
|
335
337
|
// try to fetch the track via a uri if possible
|
|
336
338
|
if (typeof data.info.uri === "string") {
|
|
337
|
-
const r = await player.search({ query: data?.info?.uri }, data.requester).then(v => v.tracks[0]);
|
|
339
|
+
const r = await player.search({ query: data?.info?.uri }, data.requester).then(v => v.tracks?.[0]);
|
|
338
340
|
if (r)
|
|
339
|
-
return applyUnresolvedData(r, data, utils);
|
|
341
|
+
return applyUnresolvedData(r, data, player.LavalinkManager.utils);
|
|
340
342
|
}
|
|
341
343
|
// search the track as closely as possible
|
|
342
344
|
const query = [data.info?.title, data.info?.author].filter(str => !!str).join(" by ");
|
|
343
345
|
const sourceName = data.info?.sourceName;
|
|
344
346
|
return await player.search({
|
|
345
|
-
query, source: sourceName !== "
|
|
346
|
-
}, data.requester).then(res => {
|
|
347
|
+
query, source: sourceName !== "twitch" && sourceName !== "flowery-tts" ? sourceName : player.LavalinkManager.options?.playerOptions?.defaultSearchPlatform,
|
|
348
|
+
}, data.requester).then((res) => {
|
|
347
349
|
let trackToUse = null;
|
|
348
350
|
// try to find via author name
|
|
349
351
|
if (data.info.author && !trackToUse)
|
|
350
|
-
trackToUse = res.tracks.find(track => [data.info
|
|
352
|
+
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));
|
|
351
353
|
// try to find via duration
|
|
352
354
|
if (data.info.duration && !trackToUse)
|
|
353
|
-
trackToUse = res.tracks.find(track => (track.info
|
|
355
|
+
trackToUse = res.tracks.find(track => (track.info?.duration >= (data.info?.duration - 1500)) && (track?.info.duration <= (data.info?.duration + 1500)));
|
|
354
356
|
// try to find via isrc
|
|
355
357
|
if (data.info.isrc && !trackToUse)
|
|
356
|
-
trackToUse = res.tracks.find(track => track.info
|
|
358
|
+
trackToUse = res.tracks.find(track => track.info?.isrc === data.info?.isrc);
|
|
357
359
|
// apply unresolved data and return the track
|
|
358
|
-
return applyUnresolvedData(trackToUse || res.tracks[0], data, utils);
|
|
360
|
+
return applyUnresolvedData(trackToUse || res.tracks[0], data, player.LavalinkManager.utils);
|
|
359
361
|
});
|
|
360
362
|
}
|