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.
@@ -0,0 +1,3 @@
1
+ import { Player } from "../Player";
2
+ import { UnresolvedSearchResult } from "../Utils";
3
+ export declare const bandCampSearch: (player: Player, query: string, requestUser: unknown) => Promise<UnresolvedSearchResult>;
@@ -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 delay
99
- * @param decay
98
+ * @param delays
99
+ * @param gains
100
100
  * @returns
101
101
  */
102
- toggleReverb(delay?: number, decay?: number): Promise<boolean>;
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
- delay: number;
280
- decay: number;
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 = 1
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
- //if(!this.filters.rotating) delete sendData.rotating;
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 (this.player.node.info && !this.player.node.info?.filters?.includes?.(key))
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
- this.filters.echo = this.data.echo.decay !== 0 || this.data.echo.delay !== 0;
134
- this.filters.reverb = this.data.reverb.decay !== 0 || this.data.reverb.delay !== 0;
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
- // disable all filters
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
- echo: {
179
- delay: 0,
180
- decay: 0
181
- },
182
- reverb: {
183
- delay: 0,
184
- decay: 0
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 = 1, decay = 0.5) {
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.echo.delay = this.filters.echo ? 0 : delay;
362
- this.data.echo.decay = this.filters.echo ? 0 : decay;
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 delay
370
- * @param decay
400
+ * @param delays
401
+ * @param gains
371
402
  * @returns
372
403
  */
373
- async toggleReverb(delay = 1, decay = 0.5) {
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.reverb.delay = this.filters.reverb ? 0 : delay;
377
- this.data.reverb.decay = this.filters.reverb ? 0 : decay;
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.echo)
358
- player.filterManager.data.echo = data.playerOptions.filters.echo;
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 LavalinkSearchPlatform = "ytsearch" | "ytmsearch" | "scsearch" | LavaSrcSearchPlatform | DuncteSearchPlatform;
19
- 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";
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, player.LavalinkManager.utils);
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, this);
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.sourceManagers.includes("youtube")) {
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.sourceManagers.includes("soundcloud")) {
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.sourceManagers.includes("bandcamp")) {
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.sourceManagers.includes("twitch")) {
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.sourceManagers.includes("vimeo")) {
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.sourceManagers.includes("tiktok")) {
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.sourceManagers.includes("mixcloud")) {
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.sourceManagers.includes("spotify")) {
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.sourceManagers.includes("applemusic")) {
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.sourceManagers.includes("deezer")) {
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.sourceManagers.includes("deezer") && !node.info.sourceManagers.includes("http")) {
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.sourceManagers.includes("yandexmusic")) {
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 (source === "amsearch" && !node.info.sourceManagers.includes("applemusic")) {
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.sourceManagers.includes("deezer")) {
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.sourceManagers.includes("deezer")) {
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.sourceManagers.includes("deezer") && !node.info.sourceManagers.includes("http")) {
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.sourceManagers.includes("deezer") && !node.info.sourceManagers.includes("http")) {
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.sourceManagers.includes("soundcloud")) {
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.plugins.find(c => c.name.toLowerCase().includes(LavalinkManagerStatics_1.LavalinkPlugins.DuncteBot_Plugin.toLowerCase()))) {
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.plugins.find(c => c.name.toLowerCase().includes(LavalinkManagerStatics_1.LavalinkPlugins.GoogleCloudTTS.toLowerCase()))) {
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.sourceManagers.includes("ftts") || node.info.sourceManagers.includes("flowery-tts") || node.info.sourceManagers.includes("flowerytts"))) {
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.sourceManagers.includes("yandexmusic")) {
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.includes("youtube")) {
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.sourceManagers.includes("youtube")) {
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, utils) {
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 !== "bandcamp" && sourceName !== "twitch" && sourceName !== "flowery-tts" ? sourceName : player.LavalinkManager.options?.playerOptions?.defaultSearchPlatform,
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.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));
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.duration >= (data.info.duration - 1500)) && (track.info.duration <= (data.info.duration + 1500)));
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.isrc === data.info.isrc);
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
  }
@@ -0,0 +1,3 @@
1
+ import { Player } from "../Player";
2
+ import { UnresolvedSearchResult } from "../Utils";
3
+ export declare const bandCampSearch: (player: Player, query: string, requestUser: unknown) => Promise<UnresolvedSearchResult>;