lavalink-client 2.2.0 → 2.2.2
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 +116 -15
- package/dist/cjs/structures/Filters.d.ts +1 -1
- package/dist/cjs/structures/Filters.js +9 -9
- package/dist/cjs/structures/LavalinkManager.d.ts +24 -7
- package/dist/cjs/structures/LavalinkManager.js +15 -2
- package/dist/cjs/structures/LavalinkManagerStatics.d.ts +3 -0
- package/dist/cjs/structures/LavalinkManagerStatics.js +4 -1
- package/dist/cjs/structures/Node.d.ts +307 -22
- package/dist/cjs/structures/Node.js +328 -72
- package/dist/cjs/structures/NodeManager.js +3 -1
- package/dist/cjs/structures/Player.d.ts +44 -8
- package/dist/cjs/structures/Player.js +27 -18
- package/dist/cjs/structures/Queue.d.ts +47 -0
- package/dist/cjs/structures/Queue.js +104 -1
- package/dist/cjs/structures/Track.d.ts +1 -0
- package/dist/cjs/structures/Utils.d.ts +3 -0
- package/dist/cjs/structures/Utils.js +6 -4
- package/dist/esm/structures/Filters.d.ts +1 -1
- package/dist/esm/structures/Filters.js +9 -9
- package/dist/esm/structures/LavalinkManager.d.ts +24 -7
- package/dist/esm/structures/LavalinkManager.js +15 -2
- package/dist/esm/structures/LavalinkManagerStatics.d.ts +3 -0
- package/dist/esm/structures/LavalinkManagerStatics.js +4 -1
- package/dist/esm/structures/Node.d.ts +307 -22
- package/dist/esm/structures/Node.js +328 -72
- package/dist/esm/structures/NodeManager.js +3 -1
- package/dist/esm/structures/Player.d.ts +44 -8
- package/dist/esm/structures/Player.js +27 -18
- package/dist/esm/structures/Queue.d.ts +47 -0
- package/dist/esm/structures/Queue.js +104 -1
- package/dist/esm/structures/Track.d.ts +1 -0
- package/dist/esm/structures/Utils.d.ts +3 -0
- package/dist/esm/structures/Utils.js +6 -4
- package/dist/types/structures/Filters.d.ts +1 -1
- package/dist/types/structures/LavalinkManager.d.ts +24 -7
- package/dist/types/structures/LavalinkManagerStatics.d.ts +3 -0
- package/dist/types/structures/Node.d.ts +307 -22
- package/dist/types/structures/Player.d.ts +44 -8
- package/dist/types/structures/Queue.d.ts +47 -0
- package/dist/types/structures/Track.d.ts +1 -0
- package/dist/types/structures/Utils.d.ts +3 -0
- package/package.json +2 -3
|
@@ -8,7 +8,9 @@ export class NodeManager extends EventEmitter {
|
|
|
8
8
|
super();
|
|
9
9
|
this.LavalinkManager = LavalinkManager;
|
|
10
10
|
if (this.LavalinkManager.options.nodes)
|
|
11
|
-
this.LavalinkManager.options.nodes.forEach(node =>
|
|
11
|
+
this.LavalinkManager.options.nodes.forEach(node => {
|
|
12
|
+
this.createNode(node);
|
|
13
|
+
});
|
|
12
14
|
}
|
|
13
15
|
/**
|
|
14
16
|
* Disconnects all Nodes from lavalink ws sockets
|
|
@@ -4,28 +4,58 @@ import { LavalinkNode, SponsorBlockSegment } from "./Node";
|
|
|
4
4
|
import { Queue } from "./Queue";
|
|
5
5
|
import { Track, UnresolvedTrack } from "./Track";
|
|
6
6
|
import { Base64, LavalinkPlayerVoiceOptions, LavaSearchQuery, SearchQuery } from "./Utils";
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
export declare enum DestroyReasons {
|
|
8
|
+
QueueEmpty = "QueueEmpty",
|
|
9
|
+
NodeDestroy = "NodeDestroy",
|
|
10
|
+
NodeDeleted = "NodeDeleted",
|
|
11
|
+
LavalinkNoVoice = "LavalinkNoVoice",
|
|
12
|
+
NodeReconnectFail = "NodeReconnectFail",
|
|
13
|
+
Disconnected = "Disconnected",
|
|
14
|
+
PlayerReconnectFail = "PlayerReconnectFail",
|
|
15
|
+
ChannelDeleted = "ChannelDeleted",
|
|
16
|
+
DisconnectAllNodes = "DisconnectAllNodes",
|
|
17
|
+
ReconnectAllNodes = "ReconnectAllNodes"
|
|
18
|
+
}
|
|
19
|
+
export type DestroyReasonsType = keyof typeof DestroyReasons | string;
|
|
10
20
|
export interface PlayerJson {
|
|
21
|
+
/** Guild Id where the player was playing in */
|
|
11
22
|
guildId: string;
|
|
23
|
+
/** Options provided to the player */
|
|
12
24
|
options: PlayerOptions;
|
|
25
|
+
/** Voice Channel Id the player was playing in */
|
|
13
26
|
voiceChannelId: string;
|
|
27
|
+
/** Text Channel Id the player was synced to */
|
|
14
28
|
textChannelId?: string;
|
|
29
|
+
/** Position the player was at */
|
|
15
30
|
position: number;
|
|
31
|
+
/** Lavalink's position the player was at */
|
|
16
32
|
lastPosition: number;
|
|
33
|
+
/** Last time the position was sent from lavalink */
|
|
34
|
+
lastPositionChange: number;
|
|
35
|
+
/** Volume in % from the player (without volumeDecrementer) */
|
|
17
36
|
volume: number;
|
|
37
|
+
/** Real Volume used in lavalink (with the volumeDecrementer) */
|
|
18
38
|
lavalinkVolume: number;
|
|
39
|
+
/** The repeatmode from the player */
|
|
19
40
|
repeatMode: RepeatMode;
|
|
41
|
+
/** Pause state */
|
|
20
42
|
paused: boolean;
|
|
43
|
+
/** Wether the player was playing or not */
|
|
21
44
|
playing: boolean;
|
|
45
|
+
/** When the player was created */
|
|
22
46
|
createdTimeStamp?: number;
|
|
47
|
+
/** All current used fitlers Data */
|
|
23
48
|
filters: FilterData;
|
|
49
|
+
/** The player's ping object */
|
|
24
50
|
ping: {
|
|
51
|
+
/** Ping to the voice websocket server */
|
|
25
52
|
ws: number;
|
|
53
|
+
/** Avg. calc. Ping to the lavalink server */
|
|
26
54
|
lavalink: number;
|
|
27
55
|
};
|
|
56
|
+
/** Equalizer Bands used in lavalink */
|
|
28
57
|
equalizer: EQBand[];
|
|
58
|
+
/** The Id of the last used node */
|
|
29
59
|
nodeId?: string;
|
|
30
60
|
}
|
|
31
61
|
export type RepeatMode = "queue" | "track" | "off";
|
|
@@ -88,10 +118,15 @@ export interface PlayOptions extends LavalinkPlayOptions {
|
|
|
88
118
|
clientTrack?: Track | UnresolvedTrack;
|
|
89
119
|
}
|
|
90
120
|
export interface Player {
|
|
121
|
+
/** Filter Manager per player */
|
|
91
122
|
filterManager: FilterManager;
|
|
123
|
+
/** circular reference to the lavalink Manager from the Player for easier use */
|
|
92
124
|
LavalinkManager: LavalinkManager;
|
|
125
|
+
/** Player options currently used, mutation doesn't affect player's state */
|
|
93
126
|
options: PlayerOptions;
|
|
127
|
+
/** The lavalink node assigned the the player, don't change it manually */
|
|
94
128
|
node: LavalinkNode;
|
|
129
|
+
/** The queue from the player */
|
|
95
130
|
queue: Queue;
|
|
96
131
|
}
|
|
97
132
|
export declare class Player {
|
|
@@ -117,7 +152,9 @@ export declare class Player {
|
|
|
117
152
|
/** The Volume Lavalink actually is outputting */
|
|
118
153
|
lavalinkVolume: number;
|
|
119
154
|
/** The current Positin of the player (Calculated) */
|
|
120
|
-
position: number;
|
|
155
|
+
get position(): number;
|
|
156
|
+
/** The timestamp when the last position change update happened */
|
|
157
|
+
lastPositionChange: number;
|
|
121
158
|
/** The current Positin of the player (from Lavalink) */
|
|
122
159
|
lastPosition: number;
|
|
123
160
|
/** When the player was created [Timestamp in Ms] (from lavalink) */
|
|
@@ -163,7 +200,7 @@ export declare class Player {
|
|
|
163
200
|
* @param ignoreVolumeDecrementer If it should ignore the volumedecrementer option
|
|
164
201
|
*/
|
|
165
202
|
setVolume(volume: number, ignoreVolumeDecrementer?: boolean): Promise<this>;
|
|
166
|
-
lavaSearch(query: LavaSearchQuery, requestUser: unknown): Promise<import("./Utils").SearchResult | import("./Utils").LavaSearchResponse>;
|
|
203
|
+
lavaSearch(query: LavaSearchQuery, requestUser: unknown, throwOnEmpty?: boolean): Promise<import("./Utils").SearchResult | import("./Utils").LavaSearchResponse>;
|
|
167
204
|
setSponsorBlock(segments?: SponsorBlockSegment[]): Promise<void>;
|
|
168
205
|
getSponsorBlock(): Promise<SponsorBlockSegment[]>;
|
|
169
206
|
deleteSponsorBlock(): Promise<void>;
|
|
@@ -172,7 +209,7 @@ export declare class Player {
|
|
|
172
209
|
* @param query Query for your data
|
|
173
210
|
* @param requestUser
|
|
174
211
|
*/
|
|
175
|
-
search(query: SearchQuery, requestUser: unknown): Promise<import("./Utils").SearchResult | import("./Utils").UnresolvedSearchResult>;
|
|
212
|
+
search(query: SearchQuery, requestUser: unknown, throwOnEmpty?: boolean): Promise<import("./Utils").SearchResult | import("./Utils").UnresolvedSearchResult>;
|
|
176
213
|
/**
|
|
177
214
|
* Pause the player
|
|
178
215
|
*/
|
|
@@ -220,7 +257,7 @@ export declare class Player {
|
|
|
220
257
|
/**
|
|
221
258
|
* Destroy the player and disconnect from the voice channel
|
|
222
259
|
*/
|
|
223
|
-
destroy(reason?: string, disconnect?: boolean): Promise<this>;
|
|
260
|
+
destroy(reason?: DestroyReasons | string, disconnect?: boolean): Promise<this>;
|
|
224
261
|
/**
|
|
225
262
|
* Move the player on a different Audio-Node
|
|
226
263
|
* @param newNode New Node / New Node Id
|
|
@@ -229,4 +266,3 @@ export declare class Player {
|
|
|
229
266
|
/** Converts the Player including Queue to a Json state */
|
|
230
267
|
toJSON(): PlayerJson;
|
|
231
268
|
}
|
|
232
|
-
export {};
|
|
@@ -2,18 +2,20 @@ import { bandCampSearch } from "./CustomSearches/BandCampSearch";
|
|
|
2
2
|
import { FilterManager } from "./Filters";
|
|
3
3
|
import { Queue, QueueSaver } from "./Queue";
|
|
4
4
|
import { queueTrackEnd } from "./Utils";
|
|
5
|
-
export
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
5
|
+
export var DestroyReasons;
|
|
6
|
+
(function (DestroyReasons) {
|
|
7
|
+
DestroyReasons["QueueEmpty"] = "QueueEmpty";
|
|
8
|
+
DestroyReasons["NodeDestroy"] = "NodeDestroy";
|
|
9
|
+
DestroyReasons["NodeDeleted"] = "NodeDeleted";
|
|
10
|
+
DestroyReasons["LavalinkNoVoice"] = "LavalinkNoVoice";
|
|
11
|
+
DestroyReasons["NodeReconnectFail"] = "NodeReconnectFail";
|
|
12
|
+
DestroyReasons["Disconnected"] = "Disconnected";
|
|
13
|
+
DestroyReasons["PlayerReconnectFail"] = "PlayerReconnectFail";
|
|
14
|
+
DestroyReasons["ChannelDeleted"] = "ChannelDeleted";
|
|
15
|
+
DestroyReasons["DisconnectAllNodes"] = "DisconnectAllNodes";
|
|
16
|
+
DestroyReasons["ReconnectAllNodes"] = "ReconnectAllNodes";
|
|
17
|
+
})(DestroyReasons || (DestroyReasons = {}));
|
|
18
|
+
;
|
|
17
19
|
export class Player {
|
|
18
20
|
/** The Guild Id of the Player */
|
|
19
21
|
guildId;
|
|
@@ -39,7 +41,11 @@ export class Player {
|
|
|
39
41
|
/** The Volume Lavalink actually is outputting */
|
|
40
42
|
lavalinkVolume = 100;
|
|
41
43
|
/** The current Positin of the player (Calculated) */
|
|
42
|
-
position
|
|
44
|
+
get position() {
|
|
45
|
+
return this.lastPosition + (this.lastPositionChange ? Date.now() - this.lastPositionChange : 0);
|
|
46
|
+
}
|
|
47
|
+
/** The timestamp when the last position change update happened */
|
|
48
|
+
lastPositionChange = null;
|
|
43
49
|
/** The current Positin of the player (from Lavalink) */
|
|
44
50
|
lastPosition = 0;
|
|
45
51
|
/** When the player was created [Timestamp in Ms] (from lavalink) */
|
|
@@ -242,8 +248,8 @@ export class Player {
|
|
|
242
248
|
this.ping.lavalink = Math.round((performance.now() - now) / 10) / 100;
|
|
243
249
|
return this;
|
|
244
250
|
}
|
|
245
|
-
async lavaSearch(query, requestUser) {
|
|
246
|
-
return this.node.lavaSearch(query, requestUser);
|
|
251
|
+
async lavaSearch(query, requestUser, throwOnEmpty = false) {
|
|
252
|
+
return this.node.lavaSearch(query, requestUser, throwOnEmpty);
|
|
247
253
|
}
|
|
248
254
|
async setSponsorBlock(segments = ["sponsor", "selfpromo"]) {
|
|
249
255
|
return this.node.setSponsorBlock(this, segments);
|
|
@@ -259,11 +265,11 @@ export class Player {
|
|
|
259
265
|
* @param query Query for your data
|
|
260
266
|
* @param requestUser
|
|
261
267
|
*/
|
|
262
|
-
async search(query, requestUser) {
|
|
268
|
+
async search(query, requestUser, throwOnEmpty = false) {
|
|
263
269
|
const Query = this.LavalinkManager.utils.transformQuery(query);
|
|
264
270
|
if (["bcsearch", "bandcamp"].includes(Query.source) && !this.node.info.sourceManagers.includes("bandcamp"))
|
|
265
271
|
return await bandCampSearch(this, Query.query, requestUser);
|
|
266
|
-
return this.node.search(Query, requestUser);
|
|
272
|
+
return this.node.search(Query, requestUser, throwOnEmpty);
|
|
267
273
|
}
|
|
268
274
|
/**
|
|
269
275
|
* Pause the player
|
|
@@ -272,6 +278,7 @@ export class Player {
|
|
|
272
278
|
if (this.paused && !this.playing)
|
|
273
279
|
throw new Error("Player is already paused - not able to pause.");
|
|
274
280
|
this.paused = true;
|
|
281
|
+
this.lastPositionChange = null; // needs to removed to not cause issues
|
|
275
282
|
const now = performance.now();
|
|
276
283
|
await this.node.updatePlayer({ guildId: this.guildId, playerOptions: { paused: true } });
|
|
277
284
|
this.ping.lavalink = Math.round((performance.now() - now) / 10) / 100;
|
|
@@ -303,7 +310,7 @@ export class Player {
|
|
|
303
310
|
throw new RangeError("Current Track is not seekable / a stream");
|
|
304
311
|
if (position < 0 || position > this.queue.current.info.duration)
|
|
305
312
|
position = Math.max(Math.min(position, this.queue.current.info.duration), 0);
|
|
306
|
-
this.
|
|
313
|
+
this.lastPositionChange = Date.now();
|
|
307
314
|
this.lastPosition = position;
|
|
308
315
|
const now = performance.now();
|
|
309
316
|
await this.node.updatePlayer({ guildId: this.guildId, playerOptions: { position } });
|
|
@@ -485,6 +492,7 @@ export class Player {
|
|
|
485
492
|
textChannelId: this.textChannelId,
|
|
486
493
|
position: this.position,
|
|
487
494
|
lastPosition: this.lastPosition,
|
|
495
|
+
lastPositionChange: this.lastPositionChange,
|
|
488
496
|
volume: this.volume,
|
|
489
497
|
lavalinkVolume: this.lavalinkVolume,
|
|
490
498
|
repeatMode: this.repeatMode,
|
|
@@ -495,6 +503,7 @@ export class Player {
|
|
|
495
503
|
equalizer: this.filterManager?.equalizerBands || [],
|
|
496
504
|
nodeId: this.node?.id,
|
|
497
505
|
ping: this.ping,
|
|
506
|
+
queue: this.queue.utils.toJSON(),
|
|
498
507
|
};
|
|
499
508
|
}
|
|
500
509
|
}
|
|
@@ -113,4 +113,51 @@ export declare class Queue {
|
|
|
113
113
|
* @returns {Track} Spliced Track
|
|
114
114
|
*/
|
|
115
115
|
splice(index: number, amount: number, TrackOrTracks?: Track | UnresolvedTrack | (Track | UnresolvedTrack)[]): any;
|
|
116
|
+
/**
|
|
117
|
+
* Remove stuff from the queue.tracks array
|
|
118
|
+
* - single Track | UnresolvedTrack
|
|
119
|
+
* - multiple Track | UnresovedTrack
|
|
120
|
+
* - at the index or multiple indexes
|
|
121
|
+
* @param removeQueryTrack
|
|
122
|
+
* @returns null (if nothing was removed) / { removed } where removed is an array with all removed elements
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* ```js
|
|
126
|
+
* // remove single track
|
|
127
|
+
*
|
|
128
|
+
* const track = player.queue.tracks[4];
|
|
129
|
+
* await player.queue.remove(track);
|
|
130
|
+
*
|
|
131
|
+
* // if you already have the index you can straight up pass it too
|
|
132
|
+
* await player.queue.remove(4);
|
|
133
|
+
*
|
|
134
|
+
*
|
|
135
|
+
* // if you want to remove multiple tracks, e.g. from position 4 to position 10 you can do smt like this
|
|
136
|
+
* await player.queue.remove(player.queue.tracks.slice(4, 10)) // get's the tracks from 4 - 10, which then get's found in the remove function to be removed
|
|
137
|
+
*
|
|
138
|
+
* // I still highly suggest to use .splice!
|
|
139
|
+
*
|
|
140
|
+
* await player.queue.splice(4, 10); // removes at index 4, 10 tracks
|
|
141
|
+
*
|
|
142
|
+
* await player.queue.splice(1, 1); // removes at index 1, 1 track
|
|
143
|
+
*
|
|
144
|
+
* await player.queue.splice(4, 0, ...tracks) // removes 0 tracks at position 4, and then inserts all tracks after position 4.
|
|
145
|
+
* ```
|
|
146
|
+
*/
|
|
147
|
+
remove<T extends Track | UnresolvedTrack | number | Track[] | UnresolvedTrack[] | number[] | (number | Track | UnresolvedTrack)[]>(removeQueryTrack: T): Promise<{
|
|
148
|
+
removed: (Track | UnresolvedTrack)[];
|
|
149
|
+
} | null>;
|
|
150
|
+
/**
|
|
151
|
+
* Shifts the previous array, to return the last previous track & thus remove it from the previous queue
|
|
152
|
+
* @returns
|
|
153
|
+
*
|
|
154
|
+
* @example
|
|
155
|
+
* ```js
|
|
156
|
+
* // example on how to play the previous track again
|
|
157
|
+
* const previous = await player.queue.shiftPrevious(); // get the previous track and remove it from the previous queue array!!
|
|
158
|
+
* if(!previous) return console.error("No previous track found");
|
|
159
|
+
* await player.play({ clientTrack: previous }); // play it again
|
|
160
|
+
* ```
|
|
161
|
+
*/
|
|
162
|
+
shiftPrevious(): Promise<Track>;
|
|
116
163
|
}
|
|
@@ -118,7 +118,7 @@ export class Queue {
|
|
|
118
118
|
if (this.tracks.length <= 1)
|
|
119
119
|
return this.tracks.length;
|
|
120
120
|
// swap #1 and #2 if only 2 tracks.
|
|
121
|
-
if (this.tracks.length
|
|
121
|
+
if (this.tracks.length === 2) {
|
|
122
122
|
[this.tracks[0], this.tracks[1]] = [this.tracks[1], this.tracks[0]];
|
|
123
123
|
}
|
|
124
124
|
else { // randomly swap places.
|
|
@@ -192,4 +192,107 @@ export class Queue {
|
|
|
192
192
|
// return the things
|
|
193
193
|
return spliced.length === 1 ? spliced[0] : spliced;
|
|
194
194
|
}
|
|
195
|
+
/**
|
|
196
|
+
* Remove stuff from the queue.tracks array
|
|
197
|
+
* - single Track | UnresolvedTrack
|
|
198
|
+
* - multiple Track | UnresovedTrack
|
|
199
|
+
* - at the index or multiple indexes
|
|
200
|
+
* @param removeQueryTrack
|
|
201
|
+
* @returns null (if nothing was removed) / { removed } where removed is an array with all removed elements
|
|
202
|
+
*
|
|
203
|
+
* @example
|
|
204
|
+
* ```js
|
|
205
|
+
* // remove single track
|
|
206
|
+
*
|
|
207
|
+
* const track = player.queue.tracks[4];
|
|
208
|
+
* await player.queue.remove(track);
|
|
209
|
+
*
|
|
210
|
+
* // if you already have the index you can straight up pass it too
|
|
211
|
+
* await player.queue.remove(4);
|
|
212
|
+
*
|
|
213
|
+
*
|
|
214
|
+
* // if you want to remove multiple tracks, e.g. from position 4 to position 10 you can do smt like this
|
|
215
|
+
* await player.queue.remove(player.queue.tracks.slice(4, 10)) // get's the tracks from 4 - 10, which then get's found in the remove function to be removed
|
|
216
|
+
*
|
|
217
|
+
* // I still highly suggest to use .splice!
|
|
218
|
+
*
|
|
219
|
+
* await player.queue.splice(4, 10); // removes at index 4, 10 tracks
|
|
220
|
+
*
|
|
221
|
+
* await player.queue.splice(1, 1); // removes at index 1, 1 track
|
|
222
|
+
*
|
|
223
|
+
* await player.queue.splice(4, 0, ...tracks) // removes 0 tracks at position 4, and then inserts all tracks after position 4.
|
|
224
|
+
* ```
|
|
225
|
+
*/
|
|
226
|
+
async remove(removeQueryTrack) {
|
|
227
|
+
if (typeof removeQueryTrack === "number") {
|
|
228
|
+
const toRemove = this.tracks[removeQueryTrack];
|
|
229
|
+
if (!toRemove)
|
|
230
|
+
return null;
|
|
231
|
+
const removed = this.tracks.splice(removeQueryTrack, 1);
|
|
232
|
+
await this.utils.save();
|
|
233
|
+
console.log("0st", removed, toRemove);
|
|
234
|
+
return { removed };
|
|
235
|
+
}
|
|
236
|
+
if (Array.isArray(removeQueryTrack)) {
|
|
237
|
+
if (removeQueryTrack.every(v => typeof v === "number")) {
|
|
238
|
+
const removed = [];
|
|
239
|
+
for (const i of removeQueryTrack) {
|
|
240
|
+
if (this.tracks[i])
|
|
241
|
+
removed.push(...this.tracks.splice(i, 1));
|
|
242
|
+
}
|
|
243
|
+
console.log("1st", removed, removeQueryTrack);
|
|
244
|
+
if (!removed.length)
|
|
245
|
+
return null;
|
|
246
|
+
await this.utils.save();
|
|
247
|
+
return { removed };
|
|
248
|
+
}
|
|
249
|
+
const tracksToRemove = this.tracks.map((v, i) => ({ v, i })).filter(({ v, i }) => removeQueryTrack.find(t => typeof t === "number" && (t === i) ||
|
|
250
|
+
typeof t === "object" && (t.encoded && t.encoded === v.encoded ||
|
|
251
|
+
t.info?.identifier && t.info.identifier === v.info?.identifier ||
|
|
252
|
+
t.info?.uri && t.info.uri === v.info?.uri ||
|
|
253
|
+
t.info?.title && t.info.title === v.info?.title ||
|
|
254
|
+
t.info?.isrc && t.info.isrc === v.info?.isrc ||
|
|
255
|
+
t.info?.artworkUrl && t.info.artworkUrl === v.info?.artworkUrl)));
|
|
256
|
+
if (!tracksToRemove.length)
|
|
257
|
+
return null;
|
|
258
|
+
const removed = [];
|
|
259
|
+
for (const { i } of tracksToRemove) {
|
|
260
|
+
if (this.tracks[i])
|
|
261
|
+
removed.push(...this.tracks.splice(i, 1));
|
|
262
|
+
}
|
|
263
|
+
await this.utils.save();
|
|
264
|
+
console.log("2nd", removed, tracksToRemove);
|
|
265
|
+
return { removed };
|
|
266
|
+
}
|
|
267
|
+
const toRemove = this.tracks.findIndex((v) => removeQueryTrack.encoded && removeQueryTrack.encoded === v.encoded ||
|
|
268
|
+
removeQueryTrack.info?.identifier && removeQueryTrack.info.identifier === v.info?.identifier ||
|
|
269
|
+
removeQueryTrack.info?.uri && removeQueryTrack.info.uri === v.info?.uri ||
|
|
270
|
+
removeQueryTrack.info?.title && removeQueryTrack.info.title === v.info?.title ||
|
|
271
|
+
removeQueryTrack.info?.isrc && removeQueryTrack.info.isrc === v.info?.isrc ||
|
|
272
|
+
removeQueryTrack.info?.artworkUrl && removeQueryTrack.info.artworkUrl === v.info?.artworkUrl);
|
|
273
|
+
if (toRemove < 0)
|
|
274
|
+
return null;
|
|
275
|
+
const removed = this.tracks.splice(toRemove, 1);
|
|
276
|
+
await this.utils.save();
|
|
277
|
+
console.log("3rd", removed, toRemove);
|
|
278
|
+
return { removed };
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Shifts the previous array, to return the last previous track & thus remove it from the previous queue
|
|
282
|
+
* @returns
|
|
283
|
+
*
|
|
284
|
+
* @example
|
|
285
|
+
* ```js
|
|
286
|
+
* // example on how to play the previous track again
|
|
287
|
+
* const previous = await player.queue.shiftPrevious(); // get the previous track and remove it from the previous queue array!!
|
|
288
|
+
* if(!previous) return console.error("No previous track found");
|
|
289
|
+
* await player.play({ clientTrack: previous }); // play it again
|
|
290
|
+
* ```
|
|
291
|
+
*/
|
|
292
|
+
async shiftPrevious() {
|
|
293
|
+
const removed = this.previous.shift();
|
|
294
|
+
if (removed)
|
|
295
|
+
await this.utils.save();
|
|
296
|
+
return removed ?? null;
|
|
297
|
+
}
|
|
195
298
|
}
|
|
@@ -105,6 +105,7 @@ export declare class ManagerUtils {
|
|
|
105
105
|
validateQueryString(node: LavalinkNode, queryString: string, sourceString?: LavalinkSearchPlatform): void;
|
|
106
106
|
transformQuery(query: SearchQuery): {
|
|
107
107
|
query: string;
|
|
108
|
+
extraQueryUrlParams: URLSearchParams;
|
|
108
109
|
source: any;
|
|
109
110
|
};
|
|
110
111
|
transformLavaSearchQuery(query: LavaSearchQuery): {
|
|
@@ -453,6 +454,8 @@ export interface LavaSearchResponse {
|
|
|
453
454
|
export type SearchQuery = {
|
|
454
455
|
/** lavalink search Query / identifier string */
|
|
455
456
|
query: string;
|
|
457
|
+
/** Extra url query params to use, e.g. for flowertts */
|
|
458
|
+
extraQueryUrlParams?: URLSearchParams;
|
|
456
459
|
/** Source to append to the search query string */
|
|
457
460
|
source?: SearchPlatform;
|
|
458
461
|
} | /** Our just the search query / identifier string */ string;
|
|
@@ -237,6 +237,7 @@ export class ManagerUtils {
|
|
|
237
237
|
const sourceOfQuery = typeof query === "string" ? undefined : (DefaultSources[(query.source?.trim?.()?.toLowerCase?.()) ?? this.LavalinkManager?.options?.playerOptions?.defaultSearchPlatform?.toLowerCase?.()] ?? (query.source?.trim?.()?.toLowerCase?.()));
|
|
238
238
|
const Query = {
|
|
239
239
|
query: typeof query === "string" ? query : query.query,
|
|
240
|
+
extraQueryUrlParams: typeof query !== "string" ? query.extraQueryUrlParams : undefined,
|
|
240
241
|
source: sourceOfQuery ?? this.LavalinkManager?.options?.playerOptions?.defaultSearchPlatform?.toLowerCase?.()
|
|
241
242
|
};
|
|
242
243
|
const foundSource = Object.keys(DefaultSources).find(source => Query.query?.toLowerCase?.()?.startsWith(`${source}:`.toLowerCase()))?.trim?.()?.toLowerCase?.();
|
|
@@ -338,10 +339,11 @@ export class MiniMap extends Map {
|
|
|
338
339
|
}
|
|
339
340
|
}
|
|
340
341
|
export async function queueTrackEnd(player) {
|
|
341
|
-
if (player.queue.current) { //
|
|
342
|
+
if (player.queue.current && !player.queue.current?.pluginInfo?.clientData?.previousTrack) { // If there was a current Track already and repeatmode === true, add it to the queue.
|
|
342
343
|
player.queue.previous.unshift(player.queue.current);
|
|
343
344
|
if (player.queue.previous.length > player.queue.options.maxPreviousTracks)
|
|
344
345
|
player.queue.previous.splice(player.queue.options.maxPreviousTracks, player.queue.previous.length);
|
|
346
|
+
await player.queue.utils.save();
|
|
345
347
|
}
|
|
346
348
|
// and if repeatMode == queue, add it back to the queue!
|
|
347
349
|
if (player.repeatMode === "queue" && player.queue.current)
|
|
@@ -370,11 +372,11 @@ async function applyUnresolvedData(resTrack, data, utils) {
|
|
|
370
372
|
resTrack.info.author = data.info.author;
|
|
371
373
|
}
|
|
372
374
|
else { // only overwrite if undefined / invalid
|
|
373
|
-
if ((resTrack.info.title
|
|
375
|
+
if ((resTrack.info.title === 'Unknown title' || resTrack.info.title === "Unspecified description") && resTrack.info.title != data.info.title)
|
|
374
376
|
resTrack.info.title = data.info.title;
|
|
375
|
-
if (resTrack.info.author
|
|
377
|
+
if (resTrack.info.author !== data.info.author)
|
|
376
378
|
resTrack.info.author = data.info.author;
|
|
377
|
-
if (resTrack.info.artworkUrl
|
|
379
|
+
if (resTrack.info.artworkUrl !== data.info.artworkUrl)
|
|
378
380
|
resTrack.info.artworkUrl = data.info.artworkUrl;
|
|
379
381
|
}
|
|
380
382
|
for (const key of Object.keys(data.info))
|
|
@@ -7,7 +7,7 @@ export declare class FilterManager {
|
|
|
7
7
|
/** The Equalizer bands currently applied to the Lavalink Server */
|
|
8
8
|
equalizerBands: EQBand[];
|
|
9
9
|
/** Private Util for the instaFix Filters option */
|
|
10
|
-
filterUpdatedState:
|
|
10
|
+
filterUpdatedState: boolean;
|
|
11
11
|
/** All "Active" / "disabled" Player Filters */
|
|
12
12
|
filters: PlayerFilters;
|
|
13
13
|
/** The Filter Data sent to Lavalink, only if the filter is enabled (ofc.) */
|
|
@@ -6,6 +6,7 @@ import { DestroyReasonsType, Player, PlayerJson, PlayerOptions } from "./Player"
|
|
|
6
6
|
import { ManagerQueueOptions } from "./Queue";
|
|
7
7
|
import { Track, UnresolvedTrack } from "./Track";
|
|
8
8
|
import { ChannelDeletePacket, GuildShardPayload, ManagerUtils, MiniMap, SearchPlatform, SponsorBlockChaptersLoaded, SponsorBlockChapterStarted, SponsorBlockSegmentSkipped, SponsorBlockSegmentsLoaded, TrackEndEvent, TrackExceptionEvent, TrackStartEvent, TrackStuckEvent, VoicePacket, VoiceServer, VoiceState, WebSocketClosedEvent } from "./Utils";
|
|
9
|
+
/** How the botclient is allowed to be structured */
|
|
9
10
|
export interface BotClientOptions {
|
|
10
11
|
/** Bot Client Id */
|
|
11
12
|
id: string;
|
|
@@ -14,6 +15,7 @@ export interface BotClientOptions {
|
|
|
14
15
|
/** So users can pass entire objects / classes */
|
|
15
16
|
[x: string | number | symbol]: unknown;
|
|
16
17
|
}
|
|
18
|
+
/** Sub Manager Options, for player specific things */
|
|
17
19
|
export interface ManagerPlayerOptions {
|
|
18
20
|
/** If the Lavalink Volume should be decremented by x number */
|
|
19
21
|
volumeDecrementer?: number;
|
|
@@ -39,6 +41,7 @@ export interface ManagerPlayerOptions {
|
|
|
39
41
|
};
|
|
40
42
|
useUnresolvedData?: boolean;
|
|
41
43
|
}
|
|
44
|
+
/** Manager Options used to create the manager */
|
|
42
45
|
export interface ManagerOptions {
|
|
43
46
|
/** The Node Options, for all Nodes! (on init) */
|
|
44
47
|
nodes: LavalinkNodeOptions[];
|
|
@@ -64,6 +67,8 @@ export interface ManagerOptions {
|
|
|
64
67
|
linksAllowed?: boolean;
|
|
65
68
|
/** Advanced Options for the Library, which may or may not be "library breaking" */
|
|
66
69
|
advancedOptions?: {
|
|
70
|
+
/** Max duration for that the filter fix duration works (in ms) - default is 8mins */
|
|
71
|
+
maxFilterFixDuration?: number;
|
|
67
72
|
/** optional */
|
|
68
73
|
debugOptions?: {
|
|
69
74
|
/** For logging custom searches */
|
|
@@ -90,7 +95,7 @@ export interface LavalinkManagerEvents {
|
|
|
90
95
|
* Emitted when a Track finished.
|
|
91
96
|
* @event Manager#trackEnd
|
|
92
97
|
*/
|
|
93
|
-
"trackEnd": (player: Player, track: Track, payload: TrackEndEvent) => void;
|
|
98
|
+
"trackEnd": (player: Player, track: Track | null, payload: TrackEndEvent) => void;
|
|
94
99
|
/**
|
|
95
100
|
* Emitted when a Track got stuck while playing.
|
|
96
101
|
* @event Manager#trackStuck
|
|
@@ -105,7 +110,7 @@ export interface LavalinkManagerEvents {
|
|
|
105
110
|
* Emitted when the Playing finished and no more tracks in the queue.
|
|
106
111
|
* @event Manager#queueEnd
|
|
107
112
|
*/
|
|
108
|
-
"queueEnd": (player: Player, track: Track, payload: TrackEndEvent | TrackStuckEvent | TrackExceptionEvent) => void;
|
|
113
|
+
"queueEnd": (player: Player, track: Track | UnresolvedTrack | null, payload: TrackEndEvent | TrackStuckEvent | TrackExceptionEvent) => void;
|
|
109
114
|
/**
|
|
110
115
|
* Emitted when a Player is created.
|
|
111
116
|
* @event Manager#playerCreate
|
|
@@ -142,28 +147,28 @@ export interface LavalinkManagerEvents {
|
|
|
142
147
|
* @link https://github.com/topi314/Sponsorblock-Plugin#segmentsloaded
|
|
143
148
|
* @event Manager#trackError
|
|
144
149
|
*/
|
|
145
|
-
"SegmentsLoaded": (player: Player, track: Track | UnresolvedTrack, payload: SponsorBlockSegmentsLoaded) => void;
|
|
150
|
+
"SegmentsLoaded": (player: Player, track: Track | UnresolvedTrack | null, payload: SponsorBlockSegmentsLoaded) => void;
|
|
146
151
|
/**
|
|
147
152
|
* SPONSORBLOCK-PLUGIN EVENT
|
|
148
153
|
* Emitted when a specific Segment was skipped
|
|
149
154
|
* @link https://github.com/topi314/Sponsorblock-Plugin#segmentskipped
|
|
150
155
|
* @event Manager#trackError
|
|
151
156
|
*/
|
|
152
|
-
"SegmentSkipped": (player: Player, track: Track | UnresolvedTrack, payload: SponsorBlockSegmentSkipped) => void;
|
|
157
|
+
"SegmentSkipped": (player: Player, track: Track | UnresolvedTrack | null, payload: SponsorBlockSegmentSkipped) => void;
|
|
153
158
|
/**
|
|
154
159
|
* SPONSORBLOCK-PLUGIN EVENT
|
|
155
160
|
* Emitted when a specific Chapter starts playing
|
|
156
161
|
* @link https://github.com/topi314/Sponsorblock-Plugin#chapterstarted
|
|
157
162
|
* @event Manager#trackError
|
|
158
163
|
*/
|
|
159
|
-
"ChapterStarted": (player: Player, track: Track | UnresolvedTrack, payload: SponsorBlockChapterStarted) => void;
|
|
164
|
+
"ChapterStarted": (player: Player, track: Track | UnresolvedTrack | null, payload: SponsorBlockChapterStarted) => void;
|
|
160
165
|
/**
|
|
161
166
|
* SPONSORBLOCK-PLUGIN EVENT
|
|
162
167
|
* Emitted when Chapters are loaded
|
|
163
168
|
* @link https://github.com/topi314/Sponsorblock-Plugin#chaptersloaded
|
|
164
169
|
* @event Manager#trackError
|
|
165
170
|
*/
|
|
166
|
-
"ChaptersLoaded": (player: Player, track: Track | UnresolvedTrack, payload: SponsorBlockChaptersLoaded) => void;
|
|
171
|
+
"ChaptersLoaded": (player: Player, track: Track | UnresolvedTrack | null, payload: SponsorBlockChaptersLoaded) => void;
|
|
167
172
|
}
|
|
168
173
|
export interface LavalinkManager {
|
|
169
174
|
/** @private */
|
|
@@ -239,6 +244,7 @@ export declare class LavalinkManager extends EventEmitter {
|
|
|
239
244
|
* linksBlacklist: [],
|
|
240
245
|
* linksWhitelist: [],
|
|
241
246
|
* advancedOptions: {
|
|
247
|
+
* maxFilterFixDuration: 600_000,
|
|
242
248
|
* debugOptions: {
|
|
243
249
|
* noAudio: false,
|
|
244
250
|
* playerDestroy: {
|
|
@@ -309,10 +315,22 @@ export declare class LavalinkManager extends EventEmitter {
|
|
|
309
315
|
* Delete's a player from the cache without destroying it on lavalink (only works when it's disconnected)
|
|
310
316
|
* @param guildId
|
|
311
317
|
* @returns
|
|
318
|
+
*
|
|
319
|
+
* @example
|
|
320
|
+
* ```ts
|
|
321
|
+
* client.lavalink.deletePlayer(interaction.guildId);
|
|
322
|
+
* // shouldn't be used except you know what you are doing.
|
|
323
|
+
* ```
|
|
312
324
|
*/
|
|
313
325
|
deletePlayer(guildId: string): boolean;
|
|
314
326
|
/**
|
|
315
327
|
* Checks wether the the lib is useable based on if any node is connected
|
|
328
|
+
*
|
|
329
|
+
* @example
|
|
330
|
+
* ```ts
|
|
331
|
+
* if(!client.lavalink.useable) return console.error("can'T search yet, because there is no useable lavalink node.")
|
|
332
|
+
* // continue with code e.g. createing a player and searching
|
|
333
|
+
* ```
|
|
316
334
|
*/
|
|
317
335
|
get useable(): boolean;
|
|
318
336
|
/**
|
|
@@ -320,7 +338,6 @@ export declare class LavalinkManager extends EventEmitter {
|
|
|
320
338
|
* @param clientData
|
|
321
339
|
*
|
|
322
340
|
* @example
|
|
323
|
-
*
|
|
324
341
|
* ```ts
|
|
325
342
|
* // on the bot ready event
|
|
326
343
|
* client.on("ready", () => {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { ClientCustomSearchPlatformUtils, LavalinkSearchPlatform, SearchPlatform, SourcesRegex } from "./Utils";
|
|
2
|
+
/** Default Sources Record, to allow source parsing with multiple inputs. */
|
|
2
3
|
export declare const DefaultSources: Record<SearchPlatform, LavalinkSearchPlatform | ClientCustomSearchPlatformUtils>;
|
|
4
|
+
/** Lavalink Plugins definiton */
|
|
3
5
|
export declare const LavalinkPlugins: {
|
|
4
6
|
DuncteBot_Plugin: string;
|
|
5
7
|
LavaSrc: string;
|
|
@@ -7,4 +9,5 @@ export declare const LavalinkPlugins: {
|
|
|
7
9
|
LavaSearch: string;
|
|
8
10
|
LavalinkFilterPlugin: string;
|
|
9
11
|
};
|
|
12
|
+
/** Lavalink Sources regexes for url validations */
|
|
10
13
|
export declare const SourceLinksRegexes: Record<SourcesRegex, RegExp>;
|