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.
@@ -49,19 +49,19 @@ class FilterManager {
49
49
  },
50
50
  vibrato: {
51
51
  frequency: 0,
52
- depth: 0 // 0 < x = 1
52
+ depth: 0 // 0 < x <= 1
53
53
  },
54
54
  pluginFilters: {
55
- /*"lavalink-filter-plugin": {
56
- echo: {
57
- delay: 0,
58
- decay: 0
59
- },
60
- reverb: {
61
- delays: [0.037, 0.042, 0.048, 0.053],
62
- gains: [0.84, 0.83, 0.82, 0.81]
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
+ }
63
64
  }
64
- }*/
65
65
  },
66
66
  channelMix: exports.audioOutputsData.stereo,
67
67
  /*distortion: {
@@ -98,6 +98,10 @@ class FilterManager {
98
98
  delete sendData.pluginFilters?.["lavalink-filter-plugin"]?.echo;
99
99
  if (!this.filters.reverb)
100
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;
101
105
  if (!this.filters.lowPass)
102
106
  delete sendData.lowPass;
103
107
  if (!this.filters.karaoke)
@@ -111,9 +115,16 @@ class FilterManager {
111
115
  if (!this.player.node.sessionId)
112
116
  throw new Error("The Lavalink-Node is either not ready or not up to date");
113
117
  sendData.equalizer = [...this.equalizerBands];
118
+ if (sendData.equalizer.length === 0)
119
+ delete sendData.equalizer;
114
120
  for (const key of [...Object.keys(sendData)]) {
115
121
  // delete disabled filters
116
- 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))
117
128
  delete sendData[key];
118
129
  }
119
130
  const now = performance.now();
@@ -166,7 +177,7 @@ class FilterManager {
166
177
  this.filters.karaoke = false;
167
178
  this.filters.volume = false;
168
179
  this.filters.audioOutput = "stereo";
169
- // disable all filters
180
+ // reset all filter datas
170
181
  for (const [key, value] of Object.entries({
171
182
  volume: 1,
172
183
  lowPass: {
@@ -183,13 +194,17 @@ class FilterManager {
183
194
  pitch: 1,
184
195
  rate: 1 // 0 = x
185
196
  },
186
- echo: {
187
- delay: 0,
188
- decay: 0
189
- },
190
- reverb: {
191
- delays: [],
192
- gains: []
197
+ pluginFilters: {
198
+ "lavalink-filter-plugin": {
199
+ echo: {
200
+ delay: 0,
201
+ decay: 0
202
+ },
203
+ reverb: {
204
+ delays: [],
205
+ gains: []
206
+ },
207
+ }
193
208
  },
194
209
  rotation: {
195
210
  rotationHz: 0
@@ -363,7 +378,7 @@ class FilterManager {
363
378
  * @param decay
364
379
  * @returns
365
380
  */
366
- async toggleEcho(delay = 1, decay = 0.5) {
381
+ async toggleEcho(delay = 4, decay = 0.8) {
367
382
  if (this.player.node.info && !this.player.node.info?.filters?.includes("echo"))
368
383
  throw new Error("Node#Info#filters does not include the 'echo' Filter (Node has it not enable aka not installed!)");
369
384
  if (!this.data)
@@ -372,6 +387,8 @@ class FilterManager {
372
387
  this.data.pluginFilters = {};
373
388
  if (!this.data.pluginFilters["lavalink-filter-plugin"])
374
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 };
375
392
  this.data.pluginFilters["lavalink-filter-plugin"].echo.delay = this.filters.echo ? 0 : delay;
376
393
  this.data.pluginFilters["lavalink-filter-plugin"].echo.decay = this.filters.echo ? 0 : decay;
377
394
  this.filters.echo = !this.filters.echo;
@@ -393,6 +410,8 @@ class FilterManager {
393
410
  this.data.pluginFilters = {};
394
411
  if (!this.data.pluginFilters["lavalink-filter-plugin"])
395
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: [] };
396
415
  this.data.pluginFilters["lavalink-filter-plugin"].reverb.delays = this.filters.reverb ? [] : delays;
397
416
  this.data.pluginFilters["lavalink-filter-plugin"].reverb.gains = this.filters.reverb ? [] : gains;
398
417
  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(querySourceString: string, requestUser: unknown): Promise<SearchResult>;
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
  /**
@@ -96,8 +96,23 @@ 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))}`);
99
+ async search(query, requestUser) {
100
+ const Query = this.NodeManager.LavalinkManager.utils.transformQuery(query);
101
+ if (/^https?:\/\//.test(Query.query))
102
+ this.NodeManager.LavalinkManager.utils.validateQueryString(this, Query.source);
103
+ else if (Query.source)
104
+ this.NodeManager.LavalinkManager.utils.validateSourceString(this, Query.source);
105
+ if (["bcsearch", "bandcamp"].includes(Query.source)) {
106
+ throw new Error("Bandcamp Search only works on the player!");
107
+ }
108
+ let uri = `/loadtracks?identifier=`;
109
+ if (!/^https?:\/\//.test(Query.query))
110
+ uri += `${Query.source}:`;
111
+ if (Query.source === "ftts")
112
+ uri += `//${encodeURIComponent(encodeURI(decodeURIComponent(Query.query)))}`;
113
+ else
114
+ uri += encodeURIComponent(decodeURIComponent(Query.query));
115
+ const res = await this.request(uri);
101
116
  // transform the data which can be Error, Track or Track[] to enfore [Track]
102
117
  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
118
  return {
@@ -115,6 +130,28 @@ class LavalinkNode {
115
130
  tracks: (resTracks.length ? resTracks.map(t => this.NodeManager.LavalinkManager.utils.buildTrack(t, requestUser)) : [])
116
131
  };
117
132
  }
133
+ async lavaSearch(query, requestUser) {
134
+ const Query = this.NodeManager.LavalinkManager.utils.transformLavaSearchQuery(query);
135
+ if (Query.source)
136
+ this.NodeManager.LavalinkManager.utils.validateSourceString(this, Query.source);
137
+ if (/^https?:\/\//.test(Query.query))
138
+ return await this.search({ query: Query.query, source: Query.source }, requestUser);
139
+ if (!["spsearch", "sprec", "amsearch", "dzsearch", "dzisrc", "ytmsearch", "ytsearch"].includes(Query.source))
140
+ throw new SyntaxError(`Query.source must be a source from LavaSrc: "spsearch" | "sprec" | "amsearch" | "dzsearch" | "dzisrc" | "ytmsearch" | "ytsearch"`);
141
+ if (!this.info.plugins.find(v => v.name === "lavasearch-plugin"))
142
+ throw new RangeError(`there is no lavasearch-plugin available in the lavalink node: ${this.id}`);
143
+ if (!this.info.plugins.find(v => v.name === "lavasrc-plugin"))
144
+ throw new RangeError(`there is no lavasrc-plugin available in the lavalink node: ${this.id}`);
145
+ const res = await this.request(`/loadsearch?query=${Query.source ? `${Query.source}:` : ""}${encodeURIComponent(Query.query)}${Query.types?.length ? `&types=${Query.types.join(",")}` : ""}`);
146
+ return {
147
+ tracks: res.tracks?.map(v => this.NodeManager.LavalinkManager.utils.buildTrack(v, requestUser)) || [],
148
+ 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)) })) || [],
149
+ 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)) })) || [],
150
+ 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)) })) || [],
151
+ texts: res.texts?.map(v => ({ text: v.text, pluginInfo: v?.plugin || v.pluginInfo })) || [],
152
+ pluginInfo: res.pluginInfo || res?.plugin
153
+ };
154
+ }
118
155
  /**
119
156
  * Update the Player State on the Lavalink Server
120
157
  * @param data
@@ -168,7 +205,7 @@ class LavalinkNode {
168
205
  }
169
206
  this.socket = new ws_1.default(`ws${this.options.secure ? "s" : ""}://${this.options.host}:${this.options.port}/v4/websocket`, { headers });
170
207
  this.socket.on("open", this.open.bind(this));
171
- this.socket.on("close", this.close.bind(this));
208
+ this.socket.on("close", (code, reason) => this.close(code, reason?.toString()));
172
209
  this.socket.on("message", this.message.bind(this));
173
210
  this.socket.on("error", this.error.bind(this));
174
211
  }
@@ -180,19 +217,24 @@ class LavalinkNode {
180
217
  * Destroys the Node-Connection (Websocket) and all player's of the node
181
218
  * @returns
182
219
  */
183
- destroy(destroyReason) {
220
+ destroy(destroyReason, deleteNode = true) {
184
221
  if (!this.connected)
185
222
  return;
186
223
  const players = this.NodeManager.LavalinkManager.players.filter(p => p.node.id == this.id);
187
224
  if (players)
188
225
  players.forEach(p => p.destroy(destroyReason || Player_1.DestroyReasons.NodeDestroy));
189
- this.socket.close(1000, "destroy");
226
+ this.socket.close(1000, "Node-Destroy");
190
227
  this.socket.removeAllListeners();
191
228
  this.socket = null;
192
229
  this.reconnectAttempts = 1;
193
230
  clearTimeout(this.reconnectTimeout);
194
- this.NodeManager.emit("destroy", this, destroyReason);
195
- this.NodeManager.nodes.delete(this.id);
231
+ if (deleteNode) {
232
+ this.NodeManager.emit("destroy", this, destroyReason);
233
+ this.NodeManager.nodes.delete(this.id);
234
+ }
235
+ else {
236
+ this.NodeManager.emit("disconnect", this, { code: 1000, reason: destroyReason });
237
+ }
196
238
  return;
197
239
  }
198
240
  /** Returns if connected to the Node. */
@@ -406,7 +448,20 @@ class LavalinkNode {
406
448
  get poolAddress() {
407
449
  return `http${this.options.secure ? "s" : ""}://${this.options.host}:${this.options.port}`;
408
450
  }
409
- reconnect() {
451
+ reconnect(instaReconnect = false) {
452
+ if (instaReconnect) {
453
+ if (this.reconnectAttempts >= this.options.retryAmount) {
454
+ const error = new Error(`Unable to connect after ${this.options.retryAmount} attempts.`);
455
+ this.NodeManager.emit("error", this, error);
456
+ return this.destroy(Player_1.DestroyReasons.NodeReconnectFail);
457
+ }
458
+ this.socket.removeAllListeners();
459
+ this.socket = null;
460
+ this.NodeManager.emit("reconnecting", this);
461
+ this.connect();
462
+ this.reconnectAttempts++;
463
+ return;
464
+ }
410
465
  this.reconnectTimeout = setTimeout(() => {
411
466
  if (this.reconnectAttempts >= this.options.retryAmount) {
412
467
  const error = new Error(`Unable to connect after ${this.options.retryAmount} attempts.`);
@@ -437,7 +492,7 @@ class LavalinkNode {
437
492
  }
438
493
  close(code, reason) {
439
494
  this.NodeManager.emit("disconnect", this, { code, reason });
440
- if (code !== 1000 || reason !== "destroy")
495
+ if (code !== 1000 || reason !== "Node-Destroy")
441
496
  this.reconnect();
442
497
  }
443
498
  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;
@@ -13,6 +13,59 @@ class NodeManager extends stream_1.EventEmitter {
13
13
  if (this.LavalinkManager.options.nodes)
14
14
  this.LavalinkManager.options.nodes.forEach(node => this.createNode(node));
15
15
  }
16
+ /**
17
+ * Disconnects all Nodes from lavalink ws sockets
18
+ * @param deleteAllNodes if the nodes should also be deleted from nodeManager.nodes
19
+ * @returns amount of disconnected Nodes
20
+ */
21
+ async disconnectAll(deleteAllNodes = false) {
22
+ if (!this.nodes.size)
23
+ throw new Error("There are no nodes to disconnect (no nodes in the nodemanager)");
24
+ if (!this.nodes.filter(v => v.connected).size)
25
+ throw new Error("There are no nodes to disconnect (all nodes disconnected)");
26
+ let counter = 0;
27
+ for (const node of [...this.nodes.values()]) {
28
+ if (!node.connected)
29
+ continue;
30
+ await node.destroy(Player_1.DestroyReasons.DisconnectAllNodes, deleteAllNodes);
31
+ counter++;
32
+ }
33
+ return counter;
34
+ }
35
+ /**
36
+ * Connects all not connected nodes
37
+ * @returns Amount of connected Nodes
38
+ */
39
+ async connectAll() {
40
+ if (!this.nodes.size)
41
+ throw new Error("There are no nodes to connect (no nodes in the nodemanager)");
42
+ if (!this.nodes.filter(v => !v.connected).size)
43
+ throw new Error("There are no nodes to connect (all nodes connected)");
44
+ let counter = 0;
45
+ for (const node of [...this.nodes.values()]) {
46
+ if (node.connected)
47
+ continue;
48
+ await node.connect();
49
+ counter++;
50
+ }
51
+ return counter;
52
+ }
53
+ /**
54
+ * Forcefully reconnects all nodes
55
+ * @returns amount of nodes
56
+ */
57
+ async reconnectAll() {
58
+ if (!this.nodes.size)
59
+ throw new Error("There are no nodes to reconnect (no nodes in the nodemanager)");
60
+ let counter = 0;
61
+ for (const node of [...this.nodes.values()]) {
62
+ const sessionId = node.sessionId ? `${node.sessionId}` : undefined;
63
+ await node.destroy(Player_1.DestroyReasons.ReconnectAllNodes, false);
64
+ await node.connect(sessionId);
65
+ counter++;
66
+ }
67
+ return counter;
68
+ }
16
69
  createNode(options) {
17
70
  if (this.nodes.has(options.id || `${options.host}:${options.port}`))
18
71
  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, SearchPlatform, SearchResult, LavaSearchType, LavaSearchResponse, LavaSrcSearchPlatformBase } from "./Utils";
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
  */
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Player = exports.DestroyReasons = void 0;
4
4
  const BandCampSearch_1 = require("./CustomSearches/BandCampSearch");
5
5
  const Filters_1 = require("./Filters");
6
- const LavalinkManagerStatics_1 = require("./LavalinkManagerStatics");
7
6
  const Queue_1 = require("./Queue");
8
7
  const Utils_1 = require("./Utils");
9
8
  exports.DestroyReasons = {
@@ -14,7 +13,9 @@ exports.DestroyReasons = {
14
13
  NodeReconnectFail: "NodeReconnectFail",
15
14
  Disconnected: "Disconnected",
16
15
  PlayerReconnectFail: "PlayerReconnectFail",
17
- ChannelDeleted: "ChannelDeleted"
16
+ ChannelDeleted: "ChannelDeleted",
17
+ DisconnectAllNodes: "DisconnectAllNodes",
18
+ ReconnectAllNodes: "ReconnectAllNodes"
18
19
  };
19
20
  class Player {
20
21
  /** The Guild Id of the Player */
@@ -211,35 +212,7 @@ class Player {
211
212
  return;
212
213
  }
213
214
  async lavaSearch(query, requestUser) {
214
- // transform the query object
215
- const Query = {
216
- query: typeof query === "string" ? query : query.query,
217
- types: query.types ? ["track", "playlist", "artist", "album", "text"].filter(v => query.types?.find(x => x.toLowerCase().startsWith(v))) : ["track", "playlist", "artist", "album", "text"],
218
- 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
219
- };
220
- // if user does player.search("ytsearch:Hello")
221
- const foundSource = Object.keys(LavalinkManagerStatics_1.DefaultSources).find(source => Query.query.toLowerCase().startsWith(`${source}:`.toLowerCase()))?.trim?.()?.toLowerCase?.();
222
- if (foundSource && LavalinkManagerStatics_1.DefaultSources[foundSource]) {
223
- Query.source = LavalinkManagerStatics_1.DefaultSources[foundSource]; // set the source to ytsearch:
224
- Query.query = Query.query.slice(`${foundSource}:`.length, Query.query.length); // remove ytsearch: from the query
225
- }
226
- if (Query.source)
227
- this.LavalinkManager.utils.validateSourceString(this.node, Query.source);
228
- if (!["spsearch", "sprec", "amsearch", "dzsearch", "dzisrc", "ytmsearch", "ytsearch"].includes(Query.source))
229
- throw new SyntaxError(`Query.source must be a source from LavaSrc: "spsearch" | "sprec" | "amsearch" | "dzsearch" | "dzisrc" | "ytmsearch" | "ytsearch"`);
230
- if (/^https?:\/\//.test(Query.query))
231
- return await this.search({ query: Query.query, source: Query.source }, requestUser);
232
- if (!this.node.info.plugins.find(v => v.name === "lavasearch-plugin"))
233
- throw new RangeError(`there is no lavasearch-plugin available in the lavalink node: ${this.node.id}`);
234
- const res = await this.node.request(`/loadsearch?query=${Query.source ? `${Query.source}:` : ""}${encodeURIComponent(Query.query)}${Query.types?.length ? `&types=${Query.types.join(",")}` : ""}`);
235
- return {
236
- tracks: res.tracks?.map(v => this.LavalinkManager.utils.buildTrack(v, requestUser)) || [],
237
- albums: res.albums?.map(v => ({ info: v.info, pluginInfo: v?.plugin || v.pluginInfo, tracks: v.tracks.map(v => this.LavalinkManager.utils.buildTrack(v, requestUser)) })) || [],
238
- artists: res.artists?.map(v => ({ info: v.info, pluginInfo: v?.plugin || v.pluginInfo, tracks: v.tracks.map(v => this.LavalinkManager.utils.buildTrack(v, requestUser)) })) || [],
239
- playlists: res.playlists?.map(v => ({ info: v.info, pluginInfo: v?.plugin || v.pluginInfo, tracks: v.tracks.map(v => this.LavalinkManager.utils.buildTrack(v, requestUser)) })) || [],
240
- texts: res.texts?.map(v => ({ text: v.text, pluginInfo: v?.plugin || v.pluginInfo })) || [],
241
- pluginInfo: res.pluginInfo || res?.plugin
242
- };
215
+ return this.node.lavaSearch(query, requestUser);
243
216
  }
244
217
  /**
245
218
  *
@@ -247,43 +220,14 @@ class Player {
247
220
  * @param requestUser
248
221
  */
249
222
  async search(query, requestUser) {
250
- // transform the query object
251
- const Query = {
252
- query: typeof query === "string" ? query : query.query,
253
- 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
254
- };
255
- // if user does player.search("ytsearch:Hello")
256
- const foundSource = Object.keys(LavalinkManagerStatics_1.DefaultSources).find(source => Query.query?.toLowerCase?.()?.startsWith(`${source}:`.toLowerCase()))?.trim?.()?.toLowerCase?.();
257
- if (foundSource && LavalinkManagerStatics_1.DefaultSources[foundSource]) {
258
- Query.source = LavalinkManagerStatics_1.DefaultSources[foundSource]; // set the source to ytsearch:
259
- Query.query = Query.query.slice(`${foundSource}:`.length, Query.query.length); // remove ytsearch: from the query
260
- }
223
+ const Query = this.LavalinkManager.utils.transformQuery(query);
261
224
  if (/^https?:\/\//.test(Query.query))
262
225
  this.LavalinkManager.utils.validateQueryString(this.node, Query.source);
263
226
  else if (Query.source)
264
227
  this.LavalinkManager.utils.validateSourceString(this.node, Query.source);
265
- if (["bcsearch", "bandcamp"].includes(Query.source)) {
228
+ if (["bcsearch", "bandcamp"].includes(Query.source))
266
229
  return await (0, BandCampSearch_1.bandCampSearch)(this, Query.query, requestUser);
267
- }
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
269
- // request the data
270
- const res = await this.node.request(`/loadtracks?identifier=${!/^https?:\/\//.test(Query.query) ? `${Query.source}:${Query.source === "ftts" ? "//" : ""}` : ""}${encodeURIComponent(Query.query)}`);
271
- // transform the data which can be Error, Track or Track[] to enfore [Track]
272
- const resTracks = res.loadType === "playlist" ? res.data?.tracks : res.loadType === "track" ? [res.data] : res.loadType === "search" ? Array.isArray(res.data) ? res.data : [res.data] : [];
273
- return {
274
- loadType: res.loadType,
275
- exception: res.loadType === "error" ? res.data : null,
276
- pluginInfo: res.pluginInfo || {},
277
- playlist: res.loadType === "playlist" ? {
278
- title: res.data.info?.name || res.data.pluginInfo?.name || null,
279
- author: res.data.info?.author || res.data.pluginInfo?.author || null,
280
- 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,
281
- 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,
282
- 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,
283
- duration: resTracks.length ? resTracks.reduce((acc, cur) => acc + (cur?.info?.duration || 0), 0) : 0,
284
- } : null,
285
- tracks: resTracks.length ? resTracks.map(t => this.LavalinkManager.utils.buildTrack(t, requestUser)) : []
286
- };
230
+ return this.node.search(Query, requestUser);
287
231
  }
288
232
  /**
289
233
  * Pause the player
@@ -89,6 +89,15 @@ export declare class ManagerUtils {
89
89
  isUnresolvedTrackQuery(data: UnresolvedQuery | any): boolean;
90
90
  getClosestTrack(data: UnresolvedTrack, player: Player): Promise<Track | undefined>;
91
91
  validateQueryString(node: LavalinkNode, queryString: string): void;
92
+ transformQuery(query: SearchQuery): {
93
+ query: string;
94
+ source: any;
95
+ };
96
+ transformLavaSearchQuery(query: LavaSearchQuery): {
97
+ query: string;
98
+ types: string[];
99
+ source: any;
100
+ };
92
101
  validateSourceString(node: LavalinkNode, sourceString: SearchPlatform): void;
93
102
  }
94
103
  /**
@@ -322,4 +331,13 @@ export interface LavaSearchResponse {
322
331
  /** Addition result data provided by plugins */
323
332
  pluginInfo: PluginInfo;
324
333
  }
334
+ export type SearchQuery = {
335
+ query: string;
336
+ source?: SearchPlatform;
337
+ } | string;
338
+ export type LavaSearchQuery = {
339
+ query: string;
340
+ source: LavaSrcSearchPlatformBase;
341
+ types?: LavaSearchType[];
342
+ };
325
343
  export {};