lavalink-client 1.1.1 → 1.1.3
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/Node.js +2 -0
- package/dist/cjs/structures/Player.d.ts +8 -3
- package/dist/cjs/structures/Player.js +48 -7
- package/dist/cjs/structures/Track.d.ts +15 -1
- package/dist/cjs/structures/Utils.d.ts +31 -2
- package/dist/cjs/structures/Utils.js +14 -10
- package/dist/esm/structures/Node.js +2 -0
- package/dist/esm/structures/Player.d.ts +8 -3
- package/dist/esm/structures/Player.js +48 -7
- package/dist/esm/structures/Track.d.ts +15 -1
- package/dist/esm/structures/Utils.d.ts +31 -2
- package/dist/esm/structures/Utils.js +14 -10
- package/dist/types/structures/Player.d.ts +8 -3
- package/dist/types/structures/Track.d.ts +15 -1
- package/dist/types/structures/Utils.d.ts +31 -2
- package/package.json +1 -1
|
@@ -91,6 +91,8 @@ class LavalinkNode {
|
|
|
91
91
|
this.calls++;
|
|
92
92
|
if (options.method === "DELETE")
|
|
93
93
|
return;
|
|
94
|
+
if (request.statusCode === 404)
|
|
95
|
+
throw new Error(`Node Request resulted into an error, request-URL: ${url} | headers: ${JSON.stringify(request.headers)}`);
|
|
94
96
|
return parseAsText ? await request.body.text() : await request.body.json();
|
|
95
97
|
}
|
|
96
98
|
/**
|
|
@@ -2,8 +2,8 @@ import { EQBand, FilterData, FilterManager, LavalinkFilterData } from "./Filters
|
|
|
2
2
|
import { LavalinkManager } from "./LavalinkManager";
|
|
3
3
|
import { LavalinkNode } from "./Node";
|
|
4
4
|
import { Queue } from "./Queue";
|
|
5
|
-
import { Track } from "./Track";
|
|
6
|
-
import { LavalinkPlayerVoiceOptions, SearchPlatform, SearchResult } from "./Utils";
|
|
5
|
+
import { Track, UnresolvedTrack } from "./Track";
|
|
6
|
+
import { LavalinkPlayerVoiceOptions, SearchPlatform, SearchResult, LavaSearchType, LavaSearchResponse, LavaSrcSearchPlatformBase } from "./Utils";
|
|
7
7
|
type PlayerDestroyReasons = "QueueEmpty" | "NodeDestroy" | "NodeDeleted" | "LavalinkNoVoice" | "NodeReconnectFail" | "PlayerReconnectFail" | "Disconnected" | "ChannelDeleted";
|
|
8
8
|
export type DestroyReasonsType = PlayerDestroyReasons | string;
|
|
9
9
|
export declare const DestroyReasons: Record<PlayerDestroyReasons, PlayerDestroyReasons>;
|
|
@@ -43,7 +43,7 @@ export interface PlayerOptions {
|
|
|
43
43
|
}
|
|
44
44
|
export interface PlayOptions {
|
|
45
45
|
/** Which Track to play | don't provide, if it should pick from the Queue */
|
|
46
|
-
track?: Track;
|
|
46
|
+
track?: Track | UnresolvedTrack;
|
|
47
47
|
/** Encoded Track to use, instead of the queue system... */
|
|
48
48
|
encodedTrack?: string | null;
|
|
49
49
|
/** Encoded Track to use&search, instead of the queue system (yt only)... */
|
|
@@ -138,6 +138,11 @@ 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<SearchResult | LavaSearchResponse>;
|
|
141
146
|
/**
|
|
142
147
|
*
|
|
143
148
|
* @param query Query for your data
|
|
@@ -123,7 +123,9 @@ class Player {
|
|
|
123
123
|
clearTimeout(this.get("internal_queueempty"));
|
|
124
124
|
this.set("internal_queueempty", undefined);
|
|
125
125
|
}
|
|
126
|
-
if (options?.track && this.LavalinkManager.utils.isTrack(options?.track)) {
|
|
126
|
+
if (options?.track && (this.LavalinkManager.utils.isTrack(options?.track) || this.LavalinkManager.utils.isUnresolvedTrack(options.track))) {
|
|
127
|
+
if (this.LavalinkManager.utils.isUnresolvedTrack(options.track))
|
|
128
|
+
await options.track.resolve(this);
|
|
127
129
|
await this.queue.add(options?.track, 0);
|
|
128
130
|
await (0, Utils_1.queueTrackEnd)(this);
|
|
129
131
|
}
|
|
@@ -131,13 +133,17 @@ class Player {
|
|
|
131
133
|
await (0, Utils_1.queueTrackEnd)(this);
|
|
132
134
|
// @ts-ignore
|
|
133
135
|
if (this.queue.current && this.LavalinkManager.utils.isUnresolvedTrack(this.queue.current)) {
|
|
134
|
-
try {
|
|
135
|
-
this.queue.current = await this.
|
|
136
|
+
try { // @ts-ignore
|
|
137
|
+
this.queue.current = await this.queue.current.resolve(this);
|
|
136
138
|
}
|
|
137
139
|
catch (error) {
|
|
138
140
|
this.LavalinkManager.emit("trackError", this, this.queue.current, error);
|
|
141
|
+
if (options && "track" in options)
|
|
142
|
+
delete options.track;
|
|
143
|
+
if (options && "encodedTrack" in options)
|
|
144
|
+
delete options.encodedTrack;
|
|
139
145
|
if (this.queue.tracks[0])
|
|
140
|
-
return this.play();
|
|
146
|
+
return this.play(options);
|
|
141
147
|
return;
|
|
142
148
|
}
|
|
143
149
|
}
|
|
@@ -202,6 +208,37 @@ class Player {
|
|
|
202
208
|
this.ping.lavalink = Math.round((performance.now() - now) / 10) / 100;
|
|
203
209
|
return;
|
|
204
210
|
}
|
|
211
|
+
async lavaSearch(query, requestUser) {
|
|
212
|
+
// transform the query object
|
|
213
|
+
const Query = {
|
|
214
|
+
query: typeof query === "string" ? query : query.query,
|
|
215
|
+
types: query.types ? ["track", "playlist", "artist", "album", "text"].filter(v => query.types?.find(x => x.toLowerCase().startsWith(v))) : ["track", "playlist", "artist", "album", "text"],
|
|
216
|
+
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
|
|
217
|
+
};
|
|
218
|
+
// if user does player.search("ytsearch:Hello")
|
|
219
|
+
const foundSource = [...Object.keys(LavalinkManagerStatics_1.DefaultSources)].find(source => Query.query.toLowerCase().startsWith(`${source}:`.toLowerCase()))?.trim?.()?.toLowerCase?.();
|
|
220
|
+
if (foundSource && LavalinkManagerStatics_1.DefaultSources[foundSource]) {
|
|
221
|
+
Query.source = LavalinkManagerStatics_1.DefaultSources[foundSource]; // set the source to ytsearch:
|
|
222
|
+
Query.query = Query.query.slice(`${foundSource}:`.length, Query.query.length); // remove ytsearch: from the query
|
|
223
|
+
}
|
|
224
|
+
if (Query.source)
|
|
225
|
+
this.LavalinkManager.utils.validateSourceString(this.node, Query.source);
|
|
226
|
+
if (!["spsearch", "sprec", "amsearch", "dzsearch", "dzisrc", "ytmsearch", "ytsearch"].includes(Query.source))
|
|
227
|
+
throw new SyntaxError(`Query.source must be a source from LavaSrc: "spsearch" | "sprec" | "amsearch" | "dzsearch" | "dzisrc" | "ytmsearch" | "ytsearch"`);
|
|
228
|
+
if (/^https?:\/\//.test(Query.query))
|
|
229
|
+
return await this.search({ query: Query.query, source: Query.source }, requestUser);
|
|
230
|
+
if (!this.node.info.plugins.find(v => v.name === "lavasearch-plugin"))
|
|
231
|
+
throw new RangeError(`there is no lavasearch-plugin available in the lavalink node: ${this.node.id}`);
|
|
232
|
+
const res = await this.node.request(`/loadsearch?query=${Query.source ? `${Query.source}:` : ""}${encodeURIComponent(Query.query)}${Query.types?.length ? `&types=${Query.types.join(",")}` : ""}`);
|
|
233
|
+
return {
|
|
234
|
+
tracks: res.tracks?.map(v => this.LavalinkManager.utils.buildTrack(v, requestUser)) || [],
|
|
235
|
+
albums: res.albums?.map(v => ({ info: v.info, pluginInfo: v?.plugin || v.pluginInfo, tracks: v.tracks.map(v => this.LavalinkManager.utils.buildTrack(v, requestUser)) })) || [],
|
|
236
|
+
artists: res.artists?.map(v => ({ info: v.info, pluginInfo: v?.plugin || v.pluginInfo, tracks: v.tracks.map(v => this.LavalinkManager.utils.buildTrack(v, requestUser)) })) || [],
|
|
237
|
+
playlists: res.playlists?.map(v => ({ info: v.info, pluginInfo: v?.plugin || v.pluginInfo, tracks: v.tracks.map(v => this.LavalinkManager.utils.buildTrack(v, requestUser)) })) || [],
|
|
238
|
+
texts: res.texts?.map(v => ({ text: v.text, pluginInfo: v?.plugin || v.pluginInfo })) || [],
|
|
239
|
+
pluginInfo: res.pluginInfo || res?.plugin
|
|
240
|
+
};
|
|
241
|
+
}
|
|
205
242
|
/**
|
|
206
243
|
*
|
|
207
244
|
* @param query Query for your data
|
|
@@ -211,14 +248,18 @@ class Player {
|
|
|
211
248
|
// transform the query object
|
|
212
249
|
const Query = {
|
|
213
250
|
query: typeof query === "string" ? query : query.query,
|
|
214
|
-
source: LavalinkManagerStatics_1.DefaultSources[(typeof query === "string" ? undefined : query.source) ?? this.LavalinkManager.options.playerOptions.defaultSearchPlatform] ?? (typeof query === "string" ? undefined : query.source) ?? this.LavalinkManager.options.playerOptions.defaultSearchPlatform
|
|
251
|
+
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
|
|
215
252
|
};
|
|
216
253
|
// if user does player.search("ytsearch:Hello")
|
|
217
|
-
const foundSource = [...Object.keys(LavalinkManagerStatics_1.DefaultSources)].find(source => Query.query
|
|
254
|
+
const foundSource = [...Object.keys(LavalinkManagerStatics_1.DefaultSources)].find(source => Query.query?.toLowerCase?.()?.startsWith(`${source}:`.toLowerCase()))?.trim?.()?.toLowerCase?.();
|
|
218
255
|
if (foundSource && LavalinkManagerStatics_1.DefaultSources[foundSource]) {
|
|
219
256
|
Query.source = LavalinkManagerStatics_1.DefaultSources[foundSource]; // set the source to ytsearch:
|
|
220
|
-
Query.query = Query.query.
|
|
257
|
+
Query.query = Query.query.slice(`${foundSource}:`.length, Query.query.length); // remove ytsearch: from the query
|
|
221
258
|
}
|
|
259
|
+
if (/^https?:\/\//.test(Query.query))
|
|
260
|
+
this.LavalinkManager.utils.validatedQueryString(this.node, Query.source);
|
|
261
|
+
else if (Query.source)
|
|
262
|
+
this.LavalinkManager.utils.validateSourceString(this.node, Query.source);
|
|
222
263
|
// 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
|
|
223
264
|
// request the data
|
|
224
265
|
const res = await this.node.request(`/loadtracks?identifier=${!/^https?:\/\//.test(Query.query) ? `${Query.source}:${Query.source === "ftts" ? "//" : ""}` : ""}${encodeURIComponent(Query.query)}`);
|
|
@@ -17,7 +17,21 @@ export interface TrackInfo {
|
|
|
17
17
|
}
|
|
18
18
|
export interface PluginInfo {
|
|
19
19
|
/** The Type provided by a plugin */
|
|
20
|
-
type?: string;
|
|
20
|
+
type?: "album" | "playlist" | "artist" | "recommendations" | string;
|
|
21
|
+
/** The Identifier provided by a plugin */
|
|
22
|
+
albumName?: string;
|
|
23
|
+
/** The url of the album art */
|
|
24
|
+
albumArtUrl?: string;
|
|
25
|
+
/** The url of the artist */
|
|
26
|
+
artistUrl?: string;
|
|
27
|
+
/** The url of the artist artwork */
|
|
28
|
+
artistArtworkUrl?: string;
|
|
29
|
+
/** The url of the preview */
|
|
30
|
+
previewUrl?: string;
|
|
31
|
+
/** Whether the track is a preview */
|
|
32
|
+
isPreview?: boolean;
|
|
33
|
+
/** The total number of tracks in the playlist */
|
|
34
|
+
totalTracks?: number;
|
|
21
35
|
/** The Identifier provided by a plugin */
|
|
22
36
|
identifier?: string;
|
|
23
37
|
/** The ArtworkUrl provided by a plugin */
|
|
@@ -7,13 +7,18 @@ export declare const TrackSymbol: unique symbol;
|
|
|
7
7
|
export declare const UnresolvedTrackSymbol: unique symbol;
|
|
8
8
|
export declare const QueueSymbol: unique symbol;
|
|
9
9
|
export declare const NodeSymbol: unique symbol;
|
|
10
|
-
export type
|
|
10
|
+
export type LavaSrcSearchPlatformBase = "spsearch" | "sprec" | "amsearch" | "dzsearch" | "dzisrc" | "ymsearch";
|
|
11
|
+
export type LavaSrcSearchPlatform = LavaSrcSearchPlatformBase | "ftts";
|
|
12
|
+
export type DuncteSearchPlatform = "speak" | "tts";
|
|
13
|
+
export type LavalinkSearchPlatform = "ytsearch" | "ytmsearch" | "scsearch" | LavaSrcSearchPlatform | DuncteSearchPlatform;
|
|
11
14
|
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";
|
|
12
15
|
export type SearchPlatform = LavalinkSearchPlatform | ClientSearchPlatform;
|
|
13
16
|
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";
|
|
14
17
|
export interface PlaylistInfo {
|
|
15
18
|
/** The playlist title. */
|
|
16
19
|
title: string;
|
|
20
|
+
/** The playlist name (if provided instead of title) */
|
|
21
|
+
name: string;
|
|
17
22
|
/** The Playlist Author */
|
|
18
23
|
author?: string;
|
|
19
24
|
/** The Playlist Thumbnail */
|
|
@@ -72,7 +77,8 @@ export declare class ManagerUitls {
|
|
|
72
77
|
* @param requester
|
|
73
78
|
*/
|
|
74
79
|
buildUnresolvedTrack(query: UnresolvedQuery | UnresolvedTrack, requester: unknown): UnresolvedTrack;
|
|
75
|
-
|
|
80
|
+
validatedQueryString(node: LavalinkNode, queryString: string): void;
|
|
81
|
+
validateSourceString(node: LavalinkNode, sourceString: SearchPlatform): void;
|
|
76
82
|
}
|
|
77
83
|
/**
|
|
78
84
|
* @internal
|
|
@@ -282,4 +288,27 @@ export interface NodeMessage extends NodeStats {
|
|
|
282
288
|
guildId: string;
|
|
283
289
|
}
|
|
284
290
|
export declare function queueTrackEnd(player: Player): Promise<Track>;
|
|
291
|
+
export type LavaSearchType = "track" | "album" | "artist" | "playlist" | "text" | "tracks" | "albums" | "artists" | "playlists" | "texts";
|
|
292
|
+
export interface LavaSearchFilteredResponse {
|
|
293
|
+
info: PlaylistInfo;
|
|
294
|
+
pluginInfo: PluginInfo;
|
|
295
|
+
tracks: Track[];
|
|
296
|
+
}
|
|
297
|
+
export interface LavaSearchResponse {
|
|
298
|
+
/** An array of tracks, only present if track is in types */
|
|
299
|
+
tracks: Track[];
|
|
300
|
+
/** An array of albums, only present if album is in types */
|
|
301
|
+
albums: LavaSearchFilteredResponse[];
|
|
302
|
+
/** An array of artists, only present if artist is in types */
|
|
303
|
+
artists: LavaSearchFilteredResponse[];
|
|
304
|
+
/** An array of playlists, only present if playlist is in types */
|
|
305
|
+
playlists: LavaSearchFilteredResponse[];
|
|
306
|
+
/** An array of text results, only present if text is in types */
|
|
307
|
+
texts: {
|
|
308
|
+
text: string;
|
|
309
|
+
pluginInfo: PluginInfo;
|
|
310
|
+
}[];
|
|
311
|
+
/** Addition result data provided by plugins */
|
|
312
|
+
pluginInfo: PluginInfo;
|
|
313
|
+
}
|
|
285
314
|
export {};
|
|
@@ -112,7 +112,7 @@ class ManagerUitls {
|
|
|
112
112
|
return false;
|
|
113
113
|
if (data[exports.UnresolvedTrackSymbol] === true)
|
|
114
114
|
return true;
|
|
115
|
-
return typeof data === "object" && "info" in data && typeof data.info.title === "string" && typeof data.resolve === "function";
|
|
115
|
+
return typeof data === "object" && (("info" in data && typeof data.info.title === "string") || typeof data.encoded === "string") && typeof data.resolve === "function";
|
|
116
116
|
}
|
|
117
117
|
/**
|
|
118
118
|
* Checks if the provided argument is a valid UnresolvedTrack.
|
|
@@ -134,7 +134,7 @@ class ManagerUitls {
|
|
|
134
134
|
throw new RangeError('Argument "query" must be present.');
|
|
135
135
|
const unresolvedTrack = {
|
|
136
136
|
encoded: query.encoded || undefined,
|
|
137
|
-
info: query.info
|
|
137
|
+
info: query.info ? query.info : query.title ? query : undefined,
|
|
138
138
|
requester: typeof this.manager.options?.playerOptions?.requesterTransformer === "function" ? this.manager.options?.playerOptions?.requesterTransformer((query?.requester || requester)) : requester,
|
|
139
139
|
async resolve(player) {
|
|
140
140
|
const closest = await getClosestTrack(this, player, player.LavalinkManager.utils);
|
|
@@ -145,10 +145,12 @@ class ManagerUitls {
|
|
|
145
145
|
return;
|
|
146
146
|
}
|
|
147
147
|
};
|
|
148
|
+
if (!this.isUnresolvedTrack(unresolvedTrack))
|
|
149
|
+
throw SyntaxError("Could not build Unresolved Track");
|
|
148
150
|
Object.defineProperty(unresolvedTrack, exports.UnresolvedTrackSymbol, { configurable: true, value: true });
|
|
149
151
|
return unresolvedTrack;
|
|
150
152
|
}
|
|
151
|
-
|
|
153
|
+
validatedQueryString(node, queryString) {
|
|
152
154
|
if (!node.info)
|
|
153
155
|
throw new Error("No Lavalink Node was provided");
|
|
154
156
|
if (!node.info.sourceManagers?.length)
|
|
@@ -190,12 +192,14 @@ class ManagerUitls {
|
|
|
190
192
|
if (LavalinkManagerStatics_1.SourceLinksRegexes.musicYandex.test(queryString) && !node.info.sourceManagers.includes("yandexmusic")) {
|
|
191
193
|
throw new Error("Lavalink Node has not 'yandexmusic' enabled");
|
|
192
194
|
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
validateSourceString(node, sourceString) {
|
|
198
|
+
if (!sourceString)
|
|
199
|
+
throw new Error(`No SourceString was provided`);
|
|
200
|
+
const source = LavalinkManagerStatics_1.DefaultSources[sourceString.toLowerCase()] || Object.values(LavalinkManagerStatics_1.DefaultSources).find(v => v.toLowerCase() === sourceString?.toLowerCase());
|
|
197
201
|
if (!source)
|
|
198
|
-
throw new Error(`Lavalink Node SearchQuerySource: '${
|
|
202
|
+
throw new Error(`Lavalink Node SearchQuerySource: '${sourceString}' is not available`);
|
|
199
203
|
if (source === "amsearch" && !node.info.sourceManagers.includes("applemusic")) {
|
|
200
204
|
throw new Error("Lavalink Node has not 'applemusic' enabled, which is required to have 'amsearch' work");
|
|
201
205
|
}
|
|
@@ -320,8 +324,8 @@ async function getClosestTrack(data, player, utils) {
|
|
|
320
324
|
return utils.buildTrack(data, data.requester);
|
|
321
325
|
if (!utils.isUnresolvedTrack(data))
|
|
322
326
|
throw new RangeError("Track is not an unresolved Track");
|
|
323
|
-
if (!data?.info?.title)
|
|
324
|
-
throw new SyntaxError("the track title is required for unresolved tracks");
|
|
327
|
+
if (!data?.info?.title && typeof data.encoded !== "string" && !data.info.uri)
|
|
328
|
+
throw new SyntaxError("the track uri / title / encoded Base64 string is required for unresolved tracks");
|
|
325
329
|
if (!data.requester)
|
|
326
330
|
throw new SyntaxError("The requester is required");
|
|
327
331
|
// try to decode the track, if possible
|
|
@@ -87,6 +87,8 @@ export class LavalinkNode {
|
|
|
87
87
|
this.calls++;
|
|
88
88
|
if (options.method === "DELETE")
|
|
89
89
|
return;
|
|
90
|
+
if (request.statusCode === 404)
|
|
91
|
+
throw new Error(`Node Request resulted into an error, request-URL: ${url} | headers: ${JSON.stringify(request.headers)}`);
|
|
90
92
|
return parseAsText ? await request.body.text() : await request.body.json();
|
|
91
93
|
}
|
|
92
94
|
/**
|
|
@@ -2,8 +2,8 @@ import { EQBand, FilterData, FilterManager, LavalinkFilterData } from "./Filters
|
|
|
2
2
|
import { LavalinkManager } from "./LavalinkManager";
|
|
3
3
|
import { LavalinkNode } from "./Node";
|
|
4
4
|
import { Queue } from "./Queue";
|
|
5
|
-
import { Track } from "./Track";
|
|
6
|
-
import { LavalinkPlayerVoiceOptions, SearchPlatform, SearchResult } from "./Utils";
|
|
5
|
+
import { Track, UnresolvedTrack } from "./Track";
|
|
6
|
+
import { LavalinkPlayerVoiceOptions, SearchPlatform, SearchResult, LavaSearchType, LavaSearchResponse, LavaSrcSearchPlatformBase } from "./Utils";
|
|
7
7
|
type PlayerDestroyReasons = "QueueEmpty" | "NodeDestroy" | "NodeDeleted" | "LavalinkNoVoice" | "NodeReconnectFail" | "PlayerReconnectFail" | "Disconnected" | "ChannelDeleted";
|
|
8
8
|
export type DestroyReasonsType = PlayerDestroyReasons | string;
|
|
9
9
|
export declare const DestroyReasons: Record<PlayerDestroyReasons, PlayerDestroyReasons>;
|
|
@@ -43,7 +43,7 @@ export interface PlayerOptions {
|
|
|
43
43
|
}
|
|
44
44
|
export interface PlayOptions {
|
|
45
45
|
/** Which Track to play | don't provide, if it should pick from the Queue */
|
|
46
|
-
track?: Track;
|
|
46
|
+
track?: Track | UnresolvedTrack;
|
|
47
47
|
/** Encoded Track to use, instead of the queue system... */
|
|
48
48
|
encodedTrack?: string | null;
|
|
49
49
|
/** Encoded Track to use&search, instead of the queue system (yt only)... */
|
|
@@ -138,6 +138,11 @@ 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<SearchResult | LavaSearchResponse>;
|
|
141
146
|
/**
|
|
142
147
|
*
|
|
143
148
|
* @param query Query for your data
|
|
@@ -120,7 +120,9 @@ export class Player {
|
|
|
120
120
|
clearTimeout(this.get("internal_queueempty"));
|
|
121
121
|
this.set("internal_queueempty", undefined);
|
|
122
122
|
}
|
|
123
|
-
if (options?.track && this.LavalinkManager.utils.isTrack(options?.track)) {
|
|
123
|
+
if (options?.track && (this.LavalinkManager.utils.isTrack(options?.track) || this.LavalinkManager.utils.isUnresolvedTrack(options.track))) {
|
|
124
|
+
if (this.LavalinkManager.utils.isUnresolvedTrack(options.track))
|
|
125
|
+
await options.track.resolve(this);
|
|
124
126
|
await this.queue.add(options?.track, 0);
|
|
125
127
|
await queueTrackEnd(this);
|
|
126
128
|
}
|
|
@@ -128,13 +130,17 @@ export class Player {
|
|
|
128
130
|
await queueTrackEnd(this);
|
|
129
131
|
// @ts-ignore
|
|
130
132
|
if (this.queue.current && this.LavalinkManager.utils.isUnresolvedTrack(this.queue.current)) {
|
|
131
|
-
try {
|
|
132
|
-
this.queue.current = await this.
|
|
133
|
+
try { // @ts-ignore
|
|
134
|
+
this.queue.current = await this.queue.current.resolve(this);
|
|
133
135
|
}
|
|
134
136
|
catch (error) {
|
|
135
137
|
this.LavalinkManager.emit("trackError", this, this.queue.current, error);
|
|
138
|
+
if (options && "track" in options)
|
|
139
|
+
delete options.track;
|
|
140
|
+
if (options && "encodedTrack" in options)
|
|
141
|
+
delete options.encodedTrack;
|
|
136
142
|
if (this.queue.tracks[0])
|
|
137
|
-
return this.play();
|
|
143
|
+
return this.play(options);
|
|
138
144
|
return;
|
|
139
145
|
}
|
|
140
146
|
}
|
|
@@ -199,6 +205,37 @@ export class Player {
|
|
|
199
205
|
this.ping.lavalink = Math.round((performance.now() - now) / 10) / 100;
|
|
200
206
|
return;
|
|
201
207
|
}
|
|
208
|
+
async lavaSearch(query, requestUser) {
|
|
209
|
+
// transform the query object
|
|
210
|
+
const Query = {
|
|
211
|
+
query: typeof query === "string" ? query : query.query,
|
|
212
|
+
types: query.types ? ["track", "playlist", "artist", "album", "text"].filter(v => query.types?.find(x => x.toLowerCase().startsWith(v))) : ["track", "playlist", "artist", "album", "text"],
|
|
213
|
+
source: DefaultSources[(typeof query === "string" ? undefined : query.source?.trim?.()?.toLowerCase?.()) ?? this.LavalinkManager.options.playerOptions.defaultSearchPlatform.toLowerCase()] ?? (typeof query === "string" ? undefined : query.source?.trim?.()?.toLowerCase?.()) ?? this.LavalinkManager.options.playerOptions.defaultSearchPlatform
|
|
214
|
+
};
|
|
215
|
+
// if user does player.search("ytsearch:Hello")
|
|
216
|
+
const foundSource = [...Object.keys(DefaultSources)].find(source => Query.query.toLowerCase().startsWith(`${source}:`.toLowerCase()))?.trim?.()?.toLowerCase?.();
|
|
217
|
+
if (foundSource && DefaultSources[foundSource]) {
|
|
218
|
+
Query.source = DefaultSources[foundSource]; // set the source to ytsearch:
|
|
219
|
+
Query.query = Query.query.slice(`${foundSource}:`.length, Query.query.length); // remove ytsearch: from the query
|
|
220
|
+
}
|
|
221
|
+
if (Query.source)
|
|
222
|
+
this.LavalinkManager.utils.validateSourceString(this.node, Query.source);
|
|
223
|
+
if (!["spsearch", "sprec", "amsearch", "dzsearch", "dzisrc", "ytmsearch", "ytsearch"].includes(Query.source))
|
|
224
|
+
throw new SyntaxError(`Query.source must be a source from LavaSrc: "spsearch" | "sprec" | "amsearch" | "dzsearch" | "dzisrc" | "ytmsearch" | "ytsearch"`);
|
|
225
|
+
if (/^https?:\/\//.test(Query.query))
|
|
226
|
+
return await this.search({ query: Query.query, source: Query.source }, requestUser);
|
|
227
|
+
if (!this.node.info.plugins.find(v => v.name === "lavasearch-plugin"))
|
|
228
|
+
throw new RangeError(`there is no lavasearch-plugin available in the lavalink node: ${this.node.id}`);
|
|
229
|
+
const res = await this.node.request(`/loadsearch?query=${Query.source ? `${Query.source}:` : ""}${encodeURIComponent(Query.query)}${Query.types?.length ? `&types=${Query.types.join(",")}` : ""}`);
|
|
230
|
+
return {
|
|
231
|
+
tracks: res.tracks?.map(v => this.LavalinkManager.utils.buildTrack(v, requestUser)) || [],
|
|
232
|
+
albums: res.albums?.map(v => ({ info: v.info, pluginInfo: v?.plugin || v.pluginInfo, tracks: v.tracks.map(v => this.LavalinkManager.utils.buildTrack(v, requestUser)) })) || [],
|
|
233
|
+
artists: res.artists?.map(v => ({ info: v.info, pluginInfo: v?.plugin || v.pluginInfo, tracks: v.tracks.map(v => this.LavalinkManager.utils.buildTrack(v, requestUser)) })) || [],
|
|
234
|
+
playlists: res.playlists?.map(v => ({ info: v.info, pluginInfo: v?.plugin || v.pluginInfo, tracks: v.tracks.map(v => this.LavalinkManager.utils.buildTrack(v, requestUser)) })) || [],
|
|
235
|
+
texts: res.texts?.map(v => ({ text: v.text, pluginInfo: v?.plugin || v.pluginInfo })) || [],
|
|
236
|
+
pluginInfo: res.pluginInfo || res?.plugin
|
|
237
|
+
};
|
|
238
|
+
}
|
|
202
239
|
/**
|
|
203
240
|
*
|
|
204
241
|
* @param query Query for your data
|
|
@@ -208,14 +245,18 @@ export class Player {
|
|
|
208
245
|
// transform the query object
|
|
209
246
|
const Query = {
|
|
210
247
|
query: typeof query === "string" ? query : query.query,
|
|
211
|
-
source: DefaultSources[(typeof query === "string" ? undefined : query.source) ?? this.LavalinkManager.options.playerOptions.defaultSearchPlatform] ?? (typeof query === "string" ? undefined : query.source) ?? this.LavalinkManager.options.playerOptions.defaultSearchPlatform
|
|
248
|
+
source: DefaultSources[(typeof query === "string" ? undefined : query.source?.trim?.()?.toLowerCase?.()) ?? this.LavalinkManager.options.playerOptions.defaultSearchPlatform.toLowerCase()] ?? (typeof query === "string" ? undefined : query.source?.trim?.()?.toLowerCase?.()) ?? this.LavalinkManager.options.playerOptions.defaultSearchPlatform
|
|
212
249
|
};
|
|
213
250
|
// if user does player.search("ytsearch:Hello")
|
|
214
|
-
const foundSource = [...Object.keys(DefaultSources)].find(source => Query.query
|
|
251
|
+
const foundSource = [...Object.keys(DefaultSources)].find(source => Query.query?.toLowerCase?.()?.startsWith(`${source}:`.toLowerCase()))?.trim?.()?.toLowerCase?.();
|
|
215
252
|
if (foundSource && DefaultSources[foundSource]) {
|
|
216
253
|
Query.source = DefaultSources[foundSource]; // set the source to ytsearch:
|
|
217
|
-
Query.query = Query.query.
|
|
254
|
+
Query.query = Query.query.slice(`${foundSource}:`.length, Query.query.length); // remove ytsearch: from the query
|
|
218
255
|
}
|
|
256
|
+
if (/^https?:\/\//.test(Query.query))
|
|
257
|
+
this.LavalinkManager.utils.validatedQueryString(this.node, Query.source);
|
|
258
|
+
else if (Query.source)
|
|
259
|
+
this.LavalinkManager.utils.validateSourceString(this.node, Query.source);
|
|
219
260
|
// 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
|
|
220
261
|
// request the data
|
|
221
262
|
const res = await this.node.request(`/loadtracks?identifier=${!/^https?:\/\//.test(Query.query) ? `${Query.source}:${Query.source === "ftts" ? "//" : ""}` : ""}${encodeURIComponent(Query.query)}`);
|
|
@@ -17,7 +17,21 @@ export interface TrackInfo {
|
|
|
17
17
|
}
|
|
18
18
|
export interface PluginInfo {
|
|
19
19
|
/** The Type provided by a plugin */
|
|
20
|
-
type?: string;
|
|
20
|
+
type?: "album" | "playlist" | "artist" | "recommendations" | string;
|
|
21
|
+
/** The Identifier provided by a plugin */
|
|
22
|
+
albumName?: string;
|
|
23
|
+
/** The url of the album art */
|
|
24
|
+
albumArtUrl?: string;
|
|
25
|
+
/** The url of the artist */
|
|
26
|
+
artistUrl?: string;
|
|
27
|
+
/** The url of the artist artwork */
|
|
28
|
+
artistArtworkUrl?: string;
|
|
29
|
+
/** The url of the preview */
|
|
30
|
+
previewUrl?: string;
|
|
31
|
+
/** Whether the track is a preview */
|
|
32
|
+
isPreview?: boolean;
|
|
33
|
+
/** The total number of tracks in the playlist */
|
|
34
|
+
totalTracks?: number;
|
|
21
35
|
/** The Identifier provided by a plugin */
|
|
22
36
|
identifier?: string;
|
|
23
37
|
/** The ArtworkUrl provided by a plugin */
|
|
@@ -7,13 +7,18 @@ export declare const TrackSymbol: unique symbol;
|
|
|
7
7
|
export declare const UnresolvedTrackSymbol: unique symbol;
|
|
8
8
|
export declare const QueueSymbol: unique symbol;
|
|
9
9
|
export declare const NodeSymbol: unique symbol;
|
|
10
|
-
export type
|
|
10
|
+
export type LavaSrcSearchPlatformBase = "spsearch" | "sprec" | "amsearch" | "dzsearch" | "dzisrc" | "ymsearch";
|
|
11
|
+
export type LavaSrcSearchPlatform = LavaSrcSearchPlatformBase | "ftts";
|
|
12
|
+
export type DuncteSearchPlatform = "speak" | "tts";
|
|
13
|
+
export type LavalinkSearchPlatform = "ytsearch" | "ytmsearch" | "scsearch" | LavaSrcSearchPlatform | DuncteSearchPlatform;
|
|
11
14
|
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";
|
|
12
15
|
export type SearchPlatform = LavalinkSearchPlatform | ClientSearchPlatform;
|
|
13
16
|
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";
|
|
14
17
|
export interface PlaylistInfo {
|
|
15
18
|
/** The playlist title. */
|
|
16
19
|
title: string;
|
|
20
|
+
/** The playlist name (if provided instead of title) */
|
|
21
|
+
name: string;
|
|
17
22
|
/** The Playlist Author */
|
|
18
23
|
author?: string;
|
|
19
24
|
/** The Playlist Thumbnail */
|
|
@@ -72,7 +77,8 @@ export declare class ManagerUitls {
|
|
|
72
77
|
* @param requester
|
|
73
78
|
*/
|
|
74
79
|
buildUnresolvedTrack(query: UnresolvedQuery | UnresolvedTrack, requester: unknown): UnresolvedTrack;
|
|
75
|
-
|
|
80
|
+
validatedQueryString(node: LavalinkNode, queryString: string): void;
|
|
81
|
+
validateSourceString(node: LavalinkNode, sourceString: SearchPlatform): void;
|
|
76
82
|
}
|
|
77
83
|
/**
|
|
78
84
|
* @internal
|
|
@@ -282,4 +288,27 @@ export interface NodeMessage extends NodeStats {
|
|
|
282
288
|
guildId: string;
|
|
283
289
|
}
|
|
284
290
|
export declare function queueTrackEnd(player: Player): Promise<Track>;
|
|
291
|
+
export type LavaSearchType = "track" | "album" | "artist" | "playlist" | "text" | "tracks" | "albums" | "artists" | "playlists" | "texts";
|
|
292
|
+
export interface LavaSearchFilteredResponse {
|
|
293
|
+
info: PlaylistInfo;
|
|
294
|
+
pluginInfo: PluginInfo;
|
|
295
|
+
tracks: Track[];
|
|
296
|
+
}
|
|
297
|
+
export interface LavaSearchResponse {
|
|
298
|
+
/** An array of tracks, only present if track is in types */
|
|
299
|
+
tracks: Track[];
|
|
300
|
+
/** An array of albums, only present if album is in types */
|
|
301
|
+
albums: LavaSearchFilteredResponse[];
|
|
302
|
+
/** An array of artists, only present if artist is in types */
|
|
303
|
+
artists: LavaSearchFilteredResponse[];
|
|
304
|
+
/** An array of playlists, only present if playlist is in types */
|
|
305
|
+
playlists: LavaSearchFilteredResponse[];
|
|
306
|
+
/** An array of text results, only present if text is in types */
|
|
307
|
+
texts: {
|
|
308
|
+
text: string;
|
|
309
|
+
pluginInfo: PluginInfo;
|
|
310
|
+
}[];
|
|
311
|
+
/** Addition result data provided by plugins */
|
|
312
|
+
pluginInfo: PluginInfo;
|
|
313
|
+
}
|
|
285
314
|
export {};
|
|
@@ -109,7 +109,7 @@ export class ManagerUitls {
|
|
|
109
109
|
return false;
|
|
110
110
|
if (data[UnresolvedTrackSymbol] === true)
|
|
111
111
|
return true;
|
|
112
|
-
return typeof data === "object" && "info" in data && typeof data.info.title === "string" && typeof data.resolve === "function";
|
|
112
|
+
return typeof data === "object" && (("info" in data && typeof data.info.title === "string") || typeof data.encoded === "string") && typeof data.resolve === "function";
|
|
113
113
|
}
|
|
114
114
|
/**
|
|
115
115
|
* Checks if the provided argument is a valid UnresolvedTrack.
|
|
@@ -131,7 +131,7 @@ export class ManagerUitls {
|
|
|
131
131
|
throw new RangeError('Argument "query" must be present.');
|
|
132
132
|
const unresolvedTrack = {
|
|
133
133
|
encoded: query.encoded || undefined,
|
|
134
|
-
info: query.info
|
|
134
|
+
info: query.info ? query.info : query.title ? query : undefined,
|
|
135
135
|
requester: typeof this.manager.options?.playerOptions?.requesterTransformer === "function" ? this.manager.options?.playerOptions?.requesterTransformer((query?.requester || requester)) : requester,
|
|
136
136
|
async resolve(player) {
|
|
137
137
|
const closest = await getClosestTrack(this, player, player.LavalinkManager.utils);
|
|
@@ -142,10 +142,12 @@ export class ManagerUitls {
|
|
|
142
142
|
return;
|
|
143
143
|
}
|
|
144
144
|
};
|
|
145
|
+
if (!this.isUnresolvedTrack(unresolvedTrack))
|
|
146
|
+
throw SyntaxError("Could not build Unresolved Track");
|
|
145
147
|
Object.defineProperty(unresolvedTrack, UnresolvedTrackSymbol, { configurable: true, value: true });
|
|
146
148
|
return unresolvedTrack;
|
|
147
149
|
}
|
|
148
|
-
|
|
150
|
+
validatedQueryString(node, queryString) {
|
|
149
151
|
if (!node.info)
|
|
150
152
|
throw new Error("No Lavalink Node was provided");
|
|
151
153
|
if (!node.info.sourceManagers?.length)
|
|
@@ -187,12 +189,14 @@ export class ManagerUitls {
|
|
|
187
189
|
if (SourceLinksRegexes.musicYandex.test(queryString) && !node.info.sourceManagers.includes("yandexmusic")) {
|
|
188
190
|
throw new Error("Lavalink Node has not 'yandexmusic' enabled");
|
|
189
191
|
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
validateSourceString(node, sourceString) {
|
|
195
|
+
if (!sourceString)
|
|
196
|
+
throw new Error(`No SourceString was provided`);
|
|
197
|
+
const source = DefaultSources[sourceString.toLowerCase()] || Object.values(DefaultSources).find(v => v.toLowerCase() === sourceString?.toLowerCase());
|
|
194
198
|
if (!source)
|
|
195
|
-
throw new Error(`Lavalink Node SearchQuerySource: '${
|
|
199
|
+
throw new Error(`Lavalink Node SearchQuerySource: '${sourceString}' is not available`);
|
|
196
200
|
if (source === "amsearch" && !node.info.sourceManagers.includes("applemusic")) {
|
|
197
201
|
throw new Error("Lavalink Node has not 'applemusic' enabled, which is required to have 'amsearch' work");
|
|
198
202
|
}
|
|
@@ -314,8 +318,8 @@ async function getClosestTrack(data, player, utils) {
|
|
|
314
318
|
return utils.buildTrack(data, data.requester);
|
|
315
319
|
if (!utils.isUnresolvedTrack(data))
|
|
316
320
|
throw new RangeError("Track is not an unresolved Track");
|
|
317
|
-
if (!data?.info?.title)
|
|
318
|
-
throw new SyntaxError("the track title is required for unresolved tracks");
|
|
321
|
+
if (!data?.info?.title && typeof data.encoded !== "string" && !data.info.uri)
|
|
322
|
+
throw new SyntaxError("the track uri / title / encoded Base64 string is required for unresolved tracks");
|
|
319
323
|
if (!data.requester)
|
|
320
324
|
throw new SyntaxError("The requester is required");
|
|
321
325
|
// try to decode the track, if possible
|
|
@@ -2,8 +2,8 @@ import { EQBand, FilterData, FilterManager, LavalinkFilterData } from "./Filters
|
|
|
2
2
|
import { LavalinkManager } from "./LavalinkManager";
|
|
3
3
|
import { LavalinkNode } from "./Node";
|
|
4
4
|
import { Queue } from "./Queue";
|
|
5
|
-
import { Track } from "./Track";
|
|
6
|
-
import { LavalinkPlayerVoiceOptions, SearchPlatform, SearchResult } from "./Utils";
|
|
5
|
+
import { Track, UnresolvedTrack } from "./Track";
|
|
6
|
+
import { LavalinkPlayerVoiceOptions, SearchPlatform, SearchResult, LavaSearchType, LavaSearchResponse, LavaSrcSearchPlatformBase } from "./Utils";
|
|
7
7
|
type PlayerDestroyReasons = "QueueEmpty" | "NodeDestroy" | "NodeDeleted" | "LavalinkNoVoice" | "NodeReconnectFail" | "PlayerReconnectFail" | "Disconnected" | "ChannelDeleted";
|
|
8
8
|
export type DestroyReasonsType = PlayerDestroyReasons | string;
|
|
9
9
|
export declare const DestroyReasons: Record<PlayerDestroyReasons, PlayerDestroyReasons>;
|
|
@@ -43,7 +43,7 @@ export interface PlayerOptions {
|
|
|
43
43
|
}
|
|
44
44
|
export interface PlayOptions {
|
|
45
45
|
/** Which Track to play | don't provide, if it should pick from the Queue */
|
|
46
|
-
track?: Track;
|
|
46
|
+
track?: Track | UnresolvedTrack;
|
|
47
47
|
/** Encoded Track to use, instead of the queue system... */
|
|
48
48
|
encodedTrack?: string | null;
|
|
49
49
|
/** Encoded Track to use&search, instead of the queue system (yt only)... */
|
|
@@ -138,6 +138,11 @@ 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<SearchResult | LavaSearchResponse>;
|
|
141
146
|
/**
|
|
142
147
|
*
|
|
143
148
|
* @param query Query for your data
|
|
@@ -17,7 +17,21 @@ export interface TrackInfo {
|
|
|
17
17
|
}
|
|
18
18
|
export interface PluginInfo {
|
|
19
19
|
/** The Type provided by a plugin */
|
|
20
|
-
type?: string;
|
|
20
|
+
type?: "album" | "playlist" | "artist" | "recommendations" | string;
|
|
21
|
+
/** The Identifier provided by a plugin */
|
|
22
|
+
albumName?: string;
|
|
23
|
+
/** The url of the album art */
|
|
24
|
+
albumArtUrl?: string;
|
|
25
|
+
/** The url of the artist */
|
|
26
|
+
artistUrl?: string;
|
|
27
|
+
/** The url of the artist artwork */
|
|
28
|
+
artistArtworkUrl?: string;
|
|
29
|
+
/** The url of the preview */
|
|
30
|
+
previewUrl?: string;
|
|
31
|
+
/** Whether the track is a preview */
|
|
32
|
+
isPreview?: boolean;
|
|
33
|
+
/** The total number of tracks in the playlist */
|
|
34
|
+
totalTracks?: number;
|
|
21
35
|
/** The Identifier provided by a plugin */
|
|
22
36
|
identifier?: string;
|
|
23
37
|
/** The ArtworkUrl provided by a plugin */
|
|
@@ -7,13 +7,18 @@ export declare const TrackSymbol: unique symbol;
|
|
|
7
7
|
export declare const UnresolvedTrackSymbol: unique symbol;
|
|
8
8
|
export declare const QueueSymbol: unique symbol;
|
|
9
9
|
export declare const NodeSymbol: unique symbol;
|
|
10
|
-
export type
|
|
10
|
+
export type LavaSrcSearchPlatformBase = "spsearch" | "sprec" | "amsearch" | "dzsearch" | "dzisrc" | "ymsearch";
|
|
11
|
+
export type LavaSrcSearchPlatform = LavaSrcSearchPlatformBase | "ftts";
|
|
12
|
+
export type DuncteSearchPlatform = "speak" | "tts";
|
|
13
|
+
export type LavalinkSearchPlatform = "ytsearch" | "ytmsearch" | "scsearch" | LavaSrcSearchPlatform | DuncteSearchPlatform;
|
|
11
14
|
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";
|
|
12
15
|
export type SearchPlatform = LavalinkSearchPlatform | ClientSearchPlatform;
|
|
13
16
|
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";
|
|
14
17
|
export interface PlaylistInfo {
|
|
15
18
|
/** The playlist title. */
|
|
16
19
|
title: string;
|
|
20
|
+
/** The playlist name (if provided instead of title) */
|
|
21
|
+
name: string;
|
|
17
22
|
/** The Playlist Author */
|
|
18
23
|
author?: string;
|
|
19
24
|
/** The Playlist Thumbnail */
|
|
@@ -72,7 +77,8 @@ export declare class ManagerUitls {
|
|
|
72
77
|
* @param requester
|
|
73
78
|
*/
|
|
74
79
|
buildUnresolvedTrack(query: UnresolvedQuery | UnresolvedTrack, requester: unknown): UnresolvedTrack;
|
|
75
|
-
|
|
80
|
+
validatedQueryString(node: LavalinkNode, queryString: string): void;
|
|
81
|
+
validateSourceString(node: LavalinkNode, sourceString: SearchPlatform): void;
|
|
76
82
|
}
|
|
77
83
|
/**
|
|
78
84
|
* @internal
|
|
@@ -282,4 +288,27 @@ export interface NodeMessage extends NodeStats {
|
|
|
282
288
|
guildId: string;
|
|
283
289
|
}
|
|
284
290
|
export declare function queueTrackEnd(player: Player): Promise<Track>;
|
|
291
|
+
export type LavaSearchType = "track" | "album" | "artist" | "playlist" | "text" | "tracks" | "albums" | "artists" | "playlists" | "texts";
|
|
292
|
+
export interface LavaSearchFilteredResponse {
|
|
293
|
+
info: PlaylistInfo;
|
|
294
|
+
pluginInfo: PluginInfo;
|
|
295
|
+
tracks: Track[];
|
|
296
|
+
}
|
|
297
|
+
export interface LavaSearchResponse {
|
|
298
|
+
/** An array of tracks, only present if track is in types */
|
|
299
|
+
tracks: Track[];
|
|
300
|
+
/** An array of albums, only present if album is in types */
|
|
301
|
+
albums: LavaSearchFilteredResponse[];
|
|
302
|
+
/** An array of artists, only present if artist is in types */
|
|
303
|
+
artists: LavaSearchFilteredResponse[];
|
|
304
|
+
/** An array of playlists, only present if playlist is in types */
|
|
305
|
+
playlists: LavaSearchFilteredResponse[];
|
|
306
|
+
/** An array of text results, only present if text is in types */
|
|
307
|
+
texts: {
|
|
308
|
+
text: string;
|
|
309
|
+
pluginInfo: PluginInfo;
|
|
310
|
+
}[];
|
|
311
|
+
/** Addition result data provided by plugins */
|
|
312
|
+
pluginInfo: PluginInfo;
|
|
313
|
+
}
|
|
285
314
|
export {};
|
package/package.json
CHANGED