lavalink-client 1.2.5 → 2.0.0
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/README.md +51 -0
- package/dist/cjs/structures/LavalinkManager.d.ts +2 -0
- package/dist/cjs/structures/LavalinkManager.js +3 -0
- package/dist/cjs/structures/Node.d.ts +42 -4
- package/dist/cjs/structures/Node.js +42 -14
- package/dist/cjs/structures/NodeManager.d.ts +12 -2
- package/dist/cjs/structures/NodeManager.js +1 -1
- package/dist/cjs/structures/Player.d.ts +25 -10
- package/dist/cjs/structures/Player.js +51 -23
- package/dist/cjs/structures/Track.d.ts +7 -1
- package/dist/cjs/structures/Utils.d.ts +75 -19
- package/dist/esm/structures/LavalinkManager.d.ts +2 -0
- package/dist/esm/structures/LavalinkManager.js +3 -0
- package/dist/esm/structures/Node.d.ts +42 -4
- package/dist/esm/structures/Node.js +42 -14
- package/dist/esm/structures/NodeManager.d.ts +12 -2
- package/dist/esm/structures/NodeManager.js +1 -1
- package/dist/esm/structures/Player.d.ts +25 -10
- package/dist/esm/structures/Player.js +51 -23
- package/dist/esm/structures/Track.d.ts +7 -1
- package/dist/esm/structures/Utils.d.ts +75 -19
- package/dist/types/structures/LavalinkManager.d.ts +2 -0
- package/dist/types/structures/Node.d.ts +42 -4
- package/dist/types/structures/NodeManager.d.ts +12 -2
- package/dist/types/structures/Player.d.ts +25 -10
- package/dist/types/structures/Track.d.ts +7 -1
- package/dist/types/structures/Utils.d.ts +75 -19
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { LavalinkFilterData } from "./Filters";
|
|
2
2
|
import { LavalinkManager } from "./LavalinkManager";
|
|
3
3
|
import { LavalinkNode, LavalinkNodeOptions, NodeStats } from "./Node";
|
|
4
|
-
import {
|
|
4
|
+
import { LavalinkPlayOptions, Player } from "./Player";
|
|
5
5
|
import { LavalinkTrack, PluginInfo, Track, UnresolvedQuery, UnresolvedTrack } from "./Track";
|
|
6
6
|
export declare const TrackSymbol: unique symbol;
|
|
7
7
|
export declare const UnresolvedTrackSymbol: unique symbol;
|
|
@@ -247,17 +247,29 @@ export type State = "CONNECTED" | "CONNECTING" | "DISCONNECTED" | "DISCONNECTING
|
|
|
247
247
|
export type PlayerEventType = "TrackStartEvent" | "TrackEndEvent" | "TrackExceptionEvent" | "TrackStuckEvent" | "WebSocketClosedEvent" | SponsorBlockSegmentEventType;
|
|
248
248
|
export type TrackEndReason = "finished" | "loadFailed" | "stopped" | "replaced" | "cleanup";
|
|
249
249
|
export interface InvalidLavalinkRestRequest {
|
|
250
|
+
/** Rest Request Data for when it was made */
|
|
250
251
|
timestamp: number;
|
|
252
|
+
/** Status of the request */
|
|
251
253
|
status: number;
|
|
254
|
+
/** Specific Errro which was sent */
|
|
252
255
|
error: string;
|
|
256
|
+
/** Specific Message which was created */
|
|
253
257
|
message?: string;
|
|
258
|
+
/** The specific error trace from the request */
|
|
259
|
+
trace?: unknown;
|
|
260
|
+
/** Path of where it's from */
|
|
254
261
|
path: string;
|
|
255
262
|
}
|
|
256
263
|
export interface LavalinkPlayerVoice {
|
|
264
|
+
/** The Voice Token */
|
|
257
265
|
token: string;
|
|
266
|
+
/** The Voice Server Endpoint */
|
|
258
267
|
endpoint: string;
|
|
268
|
+
/** The Voice SessionId */
|
|
259
269
|
sessionId: string;
|
|
270
|
+
/** Wether or not the player is connected */
|
|
260
271
|
connected?: boolean;
|
|
272
|
+
/** The Ping to the voice server */
|
|
261
273
|
ping?: number;
|
|
262
274
|
}
|
|
263
275
|
export interface LavalinkPlayerVoiceOptions extends Omit<LavalinkPlayerVoice, 'connected' | 'ping'> {
|
|
@@ -296,84 +308,121 @@ export interface RoutePlanner {
|
|
|
296
308
|
};
|
|
297
309
|
}
|
|
298
310
|
export interface Session {
|
|
311
|
+
/** Wether or not session is resuming or not */
|
|
299
312
|
resuming: boolean;
|
|
313
|
+
/** For how long a session is lasting while not connected */
|
|
300
314
|
timeout: number;
|
|
301
315
|
}
|
|
302
316
|
export interface GuildShardPayload {
|
|
303
317
|
/** The OP code */
|
|
304
318
|
op: number;
|
|
319
|
+
/** Data to send */
|
|
305
320
|
d: {
|
|
321
|
+
/** Guild id to apply voice settings */
|
|
306
322
|
guild_id: string;
|
|
323
|
+
/** channel to move/connect to, or null to leave it */
|
|
307
324
|
channel_id: string | null;
|
|
325
|
+
/** wether or not mute yourself */
|
|
308
326
|
self_mute: boolean;
|
|
327
|
+
/** wether or not deafen yourself */
|
|
309
328
|
self_deaf: boolean;
|
|
310
329
|
};
|
|
311
330
|
}
|
|
312
331
|
export interface PlayerUpdateInfo {
|
|
332
|
+
/** guild id of the player */
|
|
313
333
|
guildId: string;
|
|
314
|
-
|
|
334
|
+
/** Player options to provide to lavalink */
|
|
335
|
+
playerOptions: LavalinkPlayOptions;
|
|
336
|
+
/** Whether or not replace the current track with the new one (true is recommended) */
|
|
315
337
|
noReplace?: boolean;
|
|
316
338
|
}
|
|
317
339
|
export interface LavalinkPlayer {
|
|
340
|
+
/** Guild Id of the player */
|
|
318
341
|
guildId: string;
|
|
319
|
-
track
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
identifier: string;
|
|
323
|
-
title: string;
|
|
324
|
-
author: string;
|
|
325
|
-
length: number;
|
|
326
|
-
artworkUrl: string | null;
|
|
327
|
-
uri: string;
|
|
328
|
-
sourceName: string;
|
|
329
|
-
isSeekable: boolean;
|
|
330
|
-
isStream: boolean;
|
|
331
|
-
isrc: string | null;
|
|
332
|
-
position?: number;
|
|
333
|
-
};
|
|
334
|
-
};
|
|
342
|
+
/** IF playing a track, all of the track information */
|
|
343
|
+
track?: LavalinkTrack;
|
|
344
|
+
/** Lavalink volume (mind volumedecrementer) */
|
|
335
345
|
volume: number;
|
|
346
|
+
/** Wether it's paused or not */
|
|
336
347
|
paused: boolean;
|
|
348
|
+
/** Voice Endpoint data */
|
|
337
349
|
voice: LavalinkPlayerVoice;
|
|
350
|
+
/** All Audio Filters */
|
|
338
351
|
filters: Partial<LavalinkFilterData>;
|
|
352
|
+
/** Lavalink-Voice-State Variables */
|
|
353
|
+
state: {
|
|
354
|
+
/** Time since connection established */
|
|
355
|
+
time: number;
|
|
356
|
+
/** Position of the track */
|
|
357
|
+
position: number;
|
|
358
|
+
/** COnnected or not */
|
|
359
|
+
connected: boolean;
|
|
360
|
+
/** Ping to voice server */
|
|
361
|
+
ping: number;
|
|
362
|
+
};
|
|
339
363
|
}
|
|
340
364
|
export interface ChannelDeletePacket {
|
|
365
|
+
/** Packet key for channel delete */
|
|
341
366
|
t: "CHANNEL_DELETE";
|
|
367
|
+
/** data which is sent and relevant */
|
|
342
368
|
d: {
|
|
369
|
+
/** guild id */
|
|
343
370
|
guild_id: string;
|
|
371
|
+
/** Channel id */
|
|
344
372
|
id: string;
|
|
345
373
|
};
|
|
346
374
|
}
|
|
347
375
|
export interface VoiceState {
|
|
376
|
+
/** OP key from lavalink */
|
|
348
377
|
op: "voiceUpdate";
|
|
378
|
+
/** GuildId provided by lavalink */
|
|
349
379
|
guildId: string;
|
|
380
|
+
/** Event data */
|
|
350
381
|
event: VoiceServer;
|
|
382
|
+
/** Session Id of the voice connection */
|
|
351
383
|
sessionId?: string;
|
|
384
|
+
/** guild id of the voice channel */
|
|
352
385
|
guild_id: string;
|
|
386
|
+
/** user id from the voice connection */
|
|
353
387
|
user_id: string;
|
|
388
|
+
/** Session Id of the voice connection */
|
|
354
389
|
session_id: string;
|
|
390
|
+
/** Voice Channel Id */
|
|
355
391
|
channel_id: string;
|
|
356
392
|
}
|
|
393
|
+
/** The Base64 decodes tring by lavalink */
|
|
357
394
|
export type Base64 = string;
|
|
358
395
|
export interface VoiceServer {
|
|
396
|
+
/** Voice Token */
|
|
359
397
|
token: string;
|
|
398
|
+
/** Guild Id of the voice server connection */
|
|
360
399
|
guild_id: string;
|
|
400
|
+
/** Server Endpoint */
|
|
361
401
|
endpoint: string;
|
|
362
402
|
}
|
|
363
403
|
export interface VoicePacket {
|
|
404
|
+
/** Voice Packet Keys to send */
|
|
364
405
|
t?: "VOICE_SERVER_UPDATE" | "VOICE_STATE_UPDATE";
|
|
406
|
+
/** Voice Packets to send */
|
|
365
407
|
d: VoiceState | VoiceServer;
|
|
366
408
|
}
|
|
367
409
|
export interface NodeMessage extends NodeStats {
|
|
410
|
+
/** The type of the event */
|
|
368
411
|
type: PlayerEventType;
|
|
412
|
+
/** what ops are applying to that event */
|
|
369
413
|
op: "stats" | "playerUpdate" | "event";
|
|
414
|
+
/** The specific guild id for that message */
|
|
370
415
|
guildId: string;
|
|
371
416
|
}
|
|
372
417
|
export declare function queueTrackEnd(player: Player): Promise<Track>;
|
|
418
|
+
/** Specific types to filter for lavasearch, will be filtered to correct types */
|
|
373
419
|
export type LavaSearchType = "track" | "album" | "artist" | "playlist" | "text" | "tracks" | "albums" | "artists" | "playlists" | "texts";
|
|
374
420
|
export interface LavaSearchFilteredResponse {
|
|
421
|
+
/** The Information of a playlist provided by lavasearch */
|
|
375
422
|
info: PlaylistInfo;
|
|
423
|
+
/** additional plugin information */
|
|
376
424
|
pluginInfo: PluginInfo;
|
|
425
|
+
/** List of tracks */
|
|
377
426
|
tracks: Track[];
|
|
378
427
|
}
|
|
379
428
|
export interface LavaSearchResponse {
|
|
@@ -393,13 +442,20 @@ export interface LavaSearchResponse {
|
|
|
393
442
|
/** Addition result data provided by plugins */
|
|
394
443
|
pluginInfo: PluginInfo;
|
|
395
444
|
}
|
|
445
|
+
/** SearchQuery Object for raw lavalink requests */
|
|
396
446
|
export type SearchQuery = {
|
|
447
|
+
/** lavalink search Query / identifier string */
|
|
397
448
|
query: string;
|
|
449
|
+
/** Source to append to the search query string */
|
|
398
450
|
source?: SearchPlatform;
|
|
399
|
-
} | string;
|
|
451
|
+
} | /** Our just the search query / identifier string */ string;
|
|
452
|
+
/** SearchQuery Object for Lavalink LavaSearch Plugin requests */
|
|
400
453
|
export type LavaSearchQuery = {
|
|
454
|
+
/** lavalink search Query / identifier string */
|
|
401
455
|
query: string;
|
|
456
|
+
/** Source to append to the search query string */
|
|
402
457
|
source: LavaSrcSearchPlatformBase;
|
|
458
|
+
/** The Types to filter the search to */
|
|
403
459
|
types?: LavaSearchType[];
|
|
404
460
|
};
|
|
405
461
|
export {};
|
|
@@ -56,6 +56,8 @@ export interface ManagerOptions {
|
|
|
56
56
|
playerOptions?: ManagerPlayerOptions;
|
|
57
57
|
/** If it should skip to the next Track on TrackEnd / TrackError etc. events */
|
|
58
58
|
autoSkip?: boolean;
|
|
59
|
+
/** If it should skip to the next Track if track.resolve errors while trying to play a track. */
|
|
60
|
+
autoSkipOnResolveError?: boolean;
|
|
59
61
|
/** If it should emit only new (unique) songs and not when a looping track (or similar) is plaid, default false */
|
|
60
62
|
emitNewSongsOnly?: boolean;
|
|
61
63
|
/** Only allow link requests with links either matching some of that regExp or including some of that string */
|
|
@@ -37,6 +37,7 @@ export class LavalinkManager extends EventEmitter {
|
|
|
37
37
|
linksWhitelist: options?.linksWhitelist ?? [],
|
|
38
38
|
linksBlacklist: options?.linksBlacklist ?? [],
|
|
39
39
|
autoSkip: options?.autoSkip ?? true,
|
|
40
|
+
autoSkipOnResolveError: options?.autoSkipOnResolveError ?? true,
|
|
40
41
|
emitNewSongsOnly: options?.emitNewSongsOnly ?? false,
|
|
41
42
|
queueOptions: {
|
|
42
43
|
maxPreviousTracks: options?.queueOptions?.maxPreviousTracks ?? 25,
|
|
@@ -62,6 +63,8 @@ export class LavalinkManager extends EventEmitter {
|
|
|
62
63
|
// if(typeof options?.client !== "object" || typeof options?.client.id !== "string") throw new SyntaxError("ManagerOption.client = { id: string, username?:string } was not provided, which is required");
|
|
63
64
|
if (options?.autoSkip && typeof options?.autoSkip !== "boolean")
|
|
64
65
|
throw new SyntaxError("ManagerOption.autoSkip must be either false | true aka boolean");
|
|
66
|
+
if (options?.autoSkipOnResolveError && typeof options?.autoSkipOnResolveError !== "boolean")
|
|
67
|
+
throw new SyntaxError("ManagerOption.autoSkipOnResolveError must be either false | true aka boolean");
|
|
65
68
|
if (options?.emitNewSongsOnly && typeof options?.emitNewSongsOnly !== "boolean")
|
|
66
69
|
throw new SyntaxError("ManagerOption.emitNewSongsOnly must be either false | true aka boolean");
|
|
67
70
|
if (!options?.nodes || !Array.isArray(options?.nodes) || !options?.nodes.every(node => this.utils.isNodeOptions(node)))
|
|
@@ -78,29 +78,49 @@ export interface NodeStats extends BaseNodeStats {
|
|
|
78
78
|
frameStats: FrameStats;
|
|
79
79
|
}
|
|
80
80
|
export interface LavalinkInfo {
|
|
81
|
+
/** The version of this Lavalink server */
|
|
81
82
|
version: VersionObject;
|
|
83
|
+
/** The millisecond unix timestamp when this Lavalink jar was built */
|
|
82
84
|
buildTime: number;
|
|
85
|
+
/** The git information of this Lavalink server */
|
|
83
86
|
git: GitObject;
|
|
87
|
+
/** The JVM version this Lavalink server runs on */
|
|
84
88
|
jvm: string;
|
|
89
|
+
/** The Lavaplayer version being used by this server */
|
|
85
90
|
lavaplayer: string;
|
|
91
|
+
/** The enabled source managers for this server */
|
|
86
92
|
sourceManagers: string[];
|
|
93
|
+
/** The enabled filters for this server */
|
|
87
94
|
filters: string[];
|
|
95
|
+
/** The enabled plugins for this server */
|
|
88
96
|
plugins: PluginObject[];
|
|
89
97
|
}
|
|
90
98
|
export interface VersionObject {
|
|
99
|
+
/** The full version string of this Lavalink server */
|
|
91
100
|
semver: string;
|
|
101
|
+
/** The major version of this Lavalink server */
|
|
92
102
|
major: number;
|
|
103
|
+
/** The minor version of this Lavalink server */
|
|
93
104
|
minor: number;
|
|
105
|
+
/** The patch version of this Lavalink server */
|
|
94
106
|
patch: internal;
|
|
107
|
+
/** The pre-release version according to semver as a . separated list of identifiers */
|
|
95
108
|
preRelease?: string;
|
|
109
|
+
/** The build metadata according to semver as a . separated list of identifiers */
|
|
110
|
+
build?: string;
|
|
96
111
|
}
|
|
97
112
|
export interface GitObject {
|
|
113
|
+
/** The branch this Lavalink server was built on */
|
|
98
114
|
branch: string;
|
|
115
|
+
/** The commit this Lavalink server was built on */
|
|
99
116
|
commit: string;
|
|
117
|
+
/** The millisecond unix timestamp for when the commit was created */
|
|
100
118
|
commitTime: string;
|
|
101
119
|
}
|
|
102
120
|
export interface PluginObject {
|
|
121
|
+
/** The name of the plugin */
|
|
103
122
|
name: string;
|
|
123
|
+
/** The version of the plugin */
|
|
104
124
|
version: string;
|
|
105
125
|
}
|
|
106
126
|
export declare class LavalinkNode {
|
|
@@ -110,6 +130,11 @@ export declare class LavalinkNode {
|
|
|
110
130
|
calls: number;
|
|
111
131
|
stats: NodeStats;
|
|
112
132
|
sessionId?: string | null;
|
|
133
|
+
/** Wether the node resuming is enabled or not */
|
|
134
|
+
resuming: {
|
|
135
|
+
enabled: boolean;
|
|
136
|
+
timeout: number | null;
|
|
137
|
+
};
|
|
113
138
|
/** Actual Lavalink Information of the Node */
|
|
114
139
|
info: LavalinkInfo | null;
|
|
115
140
|
/** The Node Manager of this Node */
|
|
@@ -126,10 +151,17 @@ export declare class LavalinkNode {
|
|
|
126
151
|
private version;
|
|
127
152
|
/**
|
|
128
153
|
* Create a new Node
|
|
129
|
-
* @param options
|
|
130
|
-
* @param manager
|
|
154
|
+
* @param options Lavalink Node Options
|
|
155
|
+
* @param manager Node Manager
|
|
131
156
|
*/
|
|
132
157
|
constructor(options: LavalinkNodeOptions, manager: NodeManager);
|
|
158
|
+
/**
|
|
159
|
+
* Raw Request util function
|
|
160
|
+
* @param endpoint endpoint string
|
|
161
|
+
* @param modify modify the request
|
|
162
|
+
* @returns
|
|
163
|
+
*/
|
|
164
|
+
private rawRequest;
|
|
133
165
|
/**
|
|
134
166
|
* Makes an API call to the Node
|
|
135
167
|
* @param endpoint The endpoint that we will make the call to
|
|
@@ -137,8 +169,14 @@ export declare class LavalinkNode {
|
|
|
137
169
|
* @returns The returned data
|
|
138
170
|
*/
|
|
139
171
|
request(endpoint: string, modify?: ModifyRequest, parseAsText?: boolean): Promise<unknown>;
|
|
172
|
+
/**
|
|
173
|
+
* Search something raw on the node, please note only add tracks to players of that node
|
|
174
|
+
* @param query SearchQuery Object
|
|
175
|
+
* @param requestUser Request User for creating the player(s)
|
|
176
|
+
* @returns Searchresult
|
|
177
|
+
*/
|
|
140
178
|
search(query: SearchQuery, requestUser: unknown): Promise<SearchResult>;
|
|
141
|
-
lavaSearch(query: LavaSearchQuery, requestUser: unknown): Promise<SearchResult | LavaSearchResponse>;
|
|
179
|
+
lavaSearch(query: LavaSearchQuery, requestUser: unknown, throwOnEmpty?: boolean): Promise<SearchResult | LavaSearchResponse>;
|
|
142
180
|
/**
|
|
143
181
|
* Update the Player State on the Lavalink Server
|
|
144
182
|
* @param data
|
|
@@ -179,7 +217,7 @@ export declare class LavalinkNode {
|
|
|
179
217
|
* @param resuming Whether resuming is enabled for this session or not
|
|
180
218
|
* @param timeout The timeout in seconds (default is 60s)
|
|
181
219
|
*/
|
|
182
|
-
updateSession(resuming?: boolean, timeout?: number): Promise<Session>;
|
|
220
|
+
updateSession(resuming?: boolean, timeout?: number): Promise<InvalidLavalinkRestRequest | Session>;
|
|
183
221
|
/**
|
|
184
222
|
* Decode Track or Tracks
|
|
185
223
|
*/
|
|
@@ -31,6 +31,8 @@ export class LavalinkNode {
|
|
|
31
31
|
}
|
|
32
32
|
};
|
|
33
33
|
sessionId = null;
|
|
34
|
+
/** Wether the node resuming is enabled or not */
|
|
35
|
+
resuming = { enabled: true, timeout: null };
|
|
34
36
|
/** Actual Lavalink Information of the Node */
|
|
35
37
|
info = null;
|
|
36
38
|
/** The Node Manager of this Node */
|
|
@@ -47,8 +49,8 @@ export class LavalinkNode {
|
|
|
47
49
|
version = "v4";
|
|
48
50
|
/**
|
|
49
51
|
* Create a new Node
|
|
50
|
-
* @param options
|
|
51
|
-
* @param manager
|
|
52
|
+
* @param options Lavalink Node Options
|
|
53
|
+
* @param manager Node Manager
|
|
52
54
|
*/
|
|
53
55
|
constructor(options, manager) {
|
|
54
56
|
this.options = {
|
|
@@ -67,12 +69,12 @@ export class LavalinkNode {
|
|
|
67
69
|
Object.defineProperty(this, NodeSymbol, { configurable: true, value: true });
|
|
68
70
|
}
|
|
69
71
|
/**
|
|
70
|
-
*
|
|
71
|
-
* @param endpoint
|
|
72
|
-
* @param modify
|
|
73
|
-
* @returns
|
|
72
|
+
* Raw Request util function
|
|
73
|
+
* @param endpoint endpoint string
|
|
74
|
+
* @param modify modify the request
|
|
75
|
+
* @returns
|
|
74
76
|
*/
|
|
75
|
-
async
|
|
77
|
+
async rawRequest(endpoint, modify) {
|
|
76
78
|
const options = {
|
|
77
79
|
path: `/${this.version}/${endpoint.replace(/^\//gm, "")}`,
|
|
78
80
|
method: "GET",
|
|
@@ -87,12 +89,28 @@ export class LavalinkNode {
|
|
|
87
89
|
options.path = url.pathname + url.search;
|
|
88
90
|
const request = await this.rest.request(options);
|
|
89
91
|
this.calls++;
|
|
92
|
+
return { request, options };
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Makes an API call to the Node
|
|
96
|
+
* @param endpoint The endpoint that we will make the call to
|
|
97
|
+
* @param modify Used to modify the request before being sent
|
|
98
|
+
* @returns The returned data
|
|
99
|
+
*/
|
|
100
|
+
async request(endpoint, modify, parseAsText = false) {
|
|
101
|
+
const { request, options } = await this.rawRequest(endpoint, modify);
|
|
90
102
|
if (options.method === "DELETE")
|
|
91
103
|
return;
|
|
92
104
|
if (request.statusCode === 404)
|
|
93
|
-
throw new Error(`Node Request resulted into an error, request-
|
|
105
|
+
throw new Error(`Node Request resulted into an error, request-PATH: ${options.path} | headers: ${JSON.stringify(request.headers)}`);
|
|
94
106
|
return parseAsText ? await request.body.text() : await request.body.json();
|
|
95
107
|
}
|
|
108
|
+
/**
|
|
109
|
+
* Search something raw on the node, please note only add tracks to players of that node
|
|
110
|
+
* @param query SearchQuery Object
|
|
111
|
+
* @param requestUser Request User for creating the player(s)
|
|
112
|
+
* @returns Searchresult
|
|
113
|
+
*/
|
|
96
114
|
async search(query, requestUser) {
|
|
97
115
|
const Query = this.NodeManager.LavalinkManager.utils.transformQuery(query);
|
|
98
116
|
this.NodeManager.LavalinkManager.utils.validateQueryString(this, Query.query, Query.source);
|
|
@@ -109,7 +127,7 @@ export class LavalinkNode {
|
|
|
109
127
|
else
|
|
110
128
|
uri += encodeURIComponent(decodeURIComponent(Query.query));
|
|
111
129
|
const res = await this.request(uri);
|
|
112
|
-
// transform the data which can be Error, Track or Track[] to enfore [Track]
|
|
130
|
+
// transform the data which can be Error, Track or Track[] to enfore [Track]
|
|
113
131
|
const resTracks = res.loadType === "playlist" ? res.data?.tracks : res.loadType === "track" ? [res.data] : res.loadType === "search" ? Array.isArray(res.data) ? res.data : [res.data] : [];
|
|
114
132
|
return {
|
|
115
133
|
loadType: res.loadType,
|
|
@@ -126,7 +144,7 @@ export class LavalinkNode {
|
|
|
126
144
|
tracks: (resTracks.length ? resTracks.map(t => this.NodeManager.LavalinkManager.utils.buildTrack(t, requestUser)) : [])
|
|
127
145
|
};
|
|
128
146
|
}
|
|
129
|
-
async lavaSearch(query, requestUser) {
|
|
147
|
+
async lavaSearch(query, requestUser, throwOnEmpty = false) {
|
|
130
148
|
const Query = this.NodeManager.LavalinkManager.utils.transformLavaSearchQuery(query);
|
|
131
149
|
if (Query.source)
|
|
132
150
|
this.NodeManager.LavalinkManager.utils.validateSourceString(this, Query.source);
|
|
@@ -138,7 +156,10 @@ export class LavalinkNode {
|
|
|
138
156
|
throw new RangeError(`there is no lavasearch-plugin available in the lavalink node: ${this.id}`);
|
|
139
157
|
if (!this.info.plugins.find(v => v.name === "lavasrc-plugin"))
|
|
140
158
|
throw new RangeError(`there is no lavasrc-plugin available in the lavalink node: ${this.id}`);
|
|
141
|
-
const
|
|
159
|
+
const { request } = await this.rawRequest(`/loadsearch?query=${Query.source ? `${Query.source}:` : ""}${encodeURIComponent(Query.query)}${Query.types?.length ? `&types=${Query.types.join(",")}` : ""}`);
|
|
160
|
+
if (throwOnEmpty === true)
|
|
161
|
+
throw new Error("Nothing found");
|
|
162
|
+
const res = (request.statusCode === 204 ? {} : await request.body.json());
|
|
142
163
|
return {
|
|
143
164
|
tracks: res.tracks?.map(v => this.NodeManager.LavalinkManager.utils.buildTrack(v, requestUser)) || [],
|
|
144
165
|
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)) })) || [],
|
|
@@ -161,12 +182,10 @@ export class LavalinkNode {
|
|
|
161
182
|
r.method = "PATCH";
|
|
162
183
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
163
184
|
r.headers["Content-Type"] = "application/json";
|
|
164
|
-
if (data.playerOptions.track)
|
|
165
|
-
delete data.playerOptions.track;
|
|
166
185
|
r.body = JSON.stringify(data.playerOptions);
|
|
167
186
|
if (data.noReplace) {
|
|
168
187
|
const url = new URL(`${this.poolAddress}${r.path}`);
|
|
169
|
-
url.searchParams.append("noReplace", data.noReplace
|
|
188
|
+
url.searchParams.append("noReplace", data.noReplace === true && typeof data.noReplace === "boolean" ? "true" : "false");
|
|
170
189
|
r.path = url.pathname + url.search;
|
|
171
190
|
}
|
|
172
191
|
});
|
|
@@ -272,6 +291,10 @@ export class LavalinkNode {
|
|
|
272
291
|
data.resuming = resuming;
|
|
273
292
|
if (typeof timeout === "number" && timeout > 0)
|
|
274
293
|
data.timeout = timeout;
|
|
294
|
+
this.resuming = {
|
|
295
|
+
enabled: typeof resuming === "boolean" ? resuming : false,
|
|
296
|
+
timeout: typeof resuming === "boolean" && resuming === true ? timeout : null,
|
|
297
|
+
};
|
|
275
298
|
return await this.request(`/sessions/${this.sessionId}`, r => {
|
|
276
299
|
r.method = "PATCH";
|
|
277
300
|
r.headers = { Authorization: this.options.authorization, 'Content-Type': 'application/json' };
|
|
@@ -322,6 +345,7 @@ export class LavalinkNode {
|
|
|
322
345
|
* @returns
|
|
323
346
|
*/
|
|
324
347
|
async fetchVersion() {
|
|
348
|
+
// need to adjust path for no-prefix version info
|
|
325
349
|
return await this.request(`/version`, r => { r.path = "/version"; }, true);
|
|
326
350
|
}
|
|
327
351
|
/**
|
|
@@ -556,6 +580,10 @@ export class LavalinkNode {
|
|
|
556
580
|
break;
|
|
557
581
|
case "ready": // payload: { resumed: false, sessionId: 'ytva350aevn6n9n8', op: 'ready' }
|
|
558
582
|
this.sessionId = payload.sessionId;
|
|
583
|
+
this.resuming.enabled = payload.resumed;
|
|
584
|
+
if (payload.resumed === true) {
|
|
585
|
+
this.NodeManager.emit("resumed", this, payload, await this.fetchAllPlayers());
|
|
586
|
+
}
|
|
559
587
|
break;
|
|
560
588
|
default:
|
|
561
589
|
this.NodeManager.emit("error", this, new Error(`Unexpected op "${payload.op}" with data`), payload);
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import { EventEmitter } from "stream";
|
|
3
|
-
import { LavalinkNode, LavalinkNodeOptions } from "./Node";
|
|
4
3
|
import { LavalinkManager } from "./LavalinkManager";
|
|
5
|
-
import {
|
|
4
|
+
import { LavalinkNode, LavalinkNodeOptions } from "./Node";
|
|
6
5
|
import { DestroyReasonsType } from "./Player";
|
|
6
|
+
import { LavalinkPlayer, MiniMap } from "./Utils";
|
|
7
7
|
type LavalinkNodeIdentifier = string;
|
|
8
8
|
interface NodeManagerEvents {
|
|
9
9
|
/**
|
|
@@ -44,6 +44,16 @@ interface NodeManagerEvents {
|
|
|
44
44
|
* @event Manager.nodeManager#raw
|
|
45
45
|
*/
|
|
46
46
|
"raw": (node: LavalinkNode, payload: unknown) => void;
|
|
47
|
+
/**
|
|
48
|
+
* Emits when the node connects resumed. You then need to create all players within this event for your usecase.
|
|
49
|
+
* Aka for that you need to be able to save player data like vc channel + text channel in a db and then sync it again
|
|
50
|
+
* @event Manager.nodeManager#nodeResumed
|
|
51
|
+
*/
|
|
52
|
+
"resumed": (node: LavalinkNode, paylaod: {
|
|
53
|
+
resumed: true;
|
|
54
|
+
sessionId: string;
|
|
55
|
+
op: "ready";
|
|
56
|
+
}, players: LavalinkPlayer[]) => void;
|
|
47
57
|
}
|
|
48
58
|
export declare interface NodeManager {
|
|
49
59
|
on<U extends keyof NodeManagerEvents>(event: U, listener: NodeManagerEvents[U]): this;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { EventEmitter } from "stream";
|
|
2
2
|
import { LavalinkNode } from "./Node";
|
|
3
|
-
import { MiniMap } from "./Utils";
|
|
4
3
|
import { DestroyReasons } from "./Player";
|
|
4
|
+
import { MiniMap } from "./Utils";
|
|
5
5
|
export class NodeManager extends EventEmitter {
|
|
6
6
|
nodes = new MiniMap();
|
|
7
7
|
constructor(LavalinkManager) {
|
|
@@ -3,7 +3,7 @@ import { LavalinkManager } from "./LavalinkManager";
|
|
|
3
3
|
import { LavalinkNode, SponsorBlockSegment } from "./Node";
|
|
4
4
|
import { Queue } from "./Queue";
|
|
5
5
|
import { Track, UnresolvedTrack } from "./Track";
|
|
6
|
-
import { LavalinkPlayerVoiceOptions, LavaSearchQuery, SearchQuery } from "./Utils";
|
|
6
|
+
import { Base64, LavalinkPlayerVoiceOptions, LavaSearchQuery, SearchQuery } from "./Utils";
|
|
7
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>;
|
|
@@ -51,27 +51,42 @@ export interface PlayerOptions {
|
|
|
51
51
|
/** If a volume should be applied via filters instead of lavalink-volume */
|
|
52
52
|
applyVolumeAsFilter?: boolean;
|
|
53
53
|
}
|
|
54
|
-
export
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
encodedTrack?: string | null;
|
|
59
|
-
/** Encoded Track to use&search, instead of the queue system (yt only)... */
|
|
60
|
-
identifier?: string;
|
|
54
|
+
export type anyObject = {
|
|
55
|
+
[key: string | number]: string | number | null | anyObject;
|
|
56
|
+
};
|
|
57
|
+
export interface BasePlayOptions {
|
|
61
58
|
/** The position to start the track. */
|
|
62
59
|
position?: number;
|
|
63
60
|
/** The position to end the track. */
|
|
64
61
|
endTime?: number;
|
|
65
|
-
/** Whether to not replace the track if a play payload is sent. */
|
|
66
|
-
noReplace?: boolean;
|
|
67
62
|
/** If to start "paused" */
|
|
68
63
|
paused?: boolean;
|
|
69
64
|
/** The Volume to start with */
|
|
70
65
|
volume?: number;
|
|
71
66
|
/** The Lavalink Filters to use | only with the new REST API */
|
|
72
67
|
filters?: Partial<LavalinkFilterData>;
|
|
68
|
+
/** Voice Update for Lavalink */
|
|
73
69
|
voice?: LavalinkPlayerVoiceOptions;
|
|
74
70
|
}
|
|
71
|
+
export interface LavalinkPlayOptions extends BasePlayOptions {
|
|
72
|
+
/** Which Track to play | don't provide, if it should pick from the Queue */
|
|
73
|
+
track?: {
|
|
74
|
+
/** The track encoded base64 string to use instead of the one from the queue system */
|
|
75
|
+
encoded?: Base64 | null;
|
|
76
|
+
/** The identifier of the track to use */
|
|
77
|
+
identifier?: string;
|
|
78
|
+
/** Custom User Data for the track to provide, will then be on the userData object from the track */
|
|
79
|
+
userData?: anyObject;
|
|
80
|
+
/** The Track requester for when u provide encodedTrack / identifer */
|
|
81
|
+
requester?: unknown;
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
export interface PlayOptions extends LavalinkPlayOptions {
|
|
85
|
+
/** Whether to not replace the track if a play payload is sent. */
|
|
86
|
+
noReplace?: boolean;
|
|
87
|
+
/** Which Track to play | don't provide, if it should pick from the Queue */
|
|
88
|
+
clientTrack?: Track | UnresolvedTrack;
|
|
89
|
+
}
|
|
75
90
|
export interface Player {
|
|
76
91
|
filterManager: FilterManager;
|
|
77
92
|
LavalinkManager: LavalinkManager;
|