lavalink-client 1.0.5 → 1.0.7
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 +23 -1
- package/dist/cjs/structures/Filters.d.ts +5 -3
- package/dist/cjs/structures/LavalinkManager.d.ts +18 -10
- package/dist/cjs/structures/LavalinkManager.js +1 -1
- package/dist/cjs/structures/Node.d.ts +3 -3
- package/dist/cjs/structures/Node.js +13 -8
- package/dist/cjs/structures/Player.d.ts +23 -18
- package/dist/cjs/structures/Player.js +1 -0
- package/dist/cjs/structures/Queue.d.ts +23 -18
- package/dist/cjs/structures/Queue.js +6 -21
- package/dist/cjs/structures/Utils.d.ts +2 -2
- package/dist/cjs/structures/Utils.js +58 -6
- package/dist/esm/structures/Filters.d.ts +5 -3
- package/dist/esm/structures/LavalinkManager.d.ts +18 -10
- package/dist/esm/structures/LavalinkManager.js +1 -1
- package/dist/esm/structures/Node.d.ts +3 -3
- package/dist/esm/structures/Node.js +13 -8
- package/dist/esm/structures/Player.d.ts +23 -18
- package/dist/esm/structures/Player.js +1 -0
- package/dist/esm/structures/Queue.d.ts +23 -18
- package/dist/esm/structures/Queue.js +6 -20
- package/dist/esm/structures/Utils.d.ts +2 -2
- package/dist/esm/structures/Utils.js +58 -6
- package/dist/structures/LavalinkManager.d.ts +5 -5
- package/dist/structures/Queue.d.ts +7 -7
- package/dist/structures/QueueManager.d.ts +6 -6
- package/dist/types/structures/Filters.d.ts +5 -3
- package/dist/types/structures/LavalinkManager.d.ts +18 -10
- package/dist/types/structures/Node.d.ts +3 -3
- package/dist/types/structures/Player.d.ts +23 -18
- package/dist/types/structures/Queue.d.ts +23 -18
- package/dist/types/structures/Utils.d.ts +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# Lavalink Client
|
|
2
|
-
Easy and
|
|
2
|
+
Easy, flexible and feature-rich lavalink@v4 Client. Both for Beginners and Proficients.
|
|
3
|
+
|
|
4
|
+
<div align="center">
|
|
5
|
+
<p>
|
|
6
|
+
<img src="https://madewithlove.now.sh/at?heart=true&template=for-the-badge" alt="Made with love in Austria">
|
|
7
|
+
<img alt="Made with TypeScript" src="https://img.shields.io/badge/typescript-%23007ACC.svg?style=for-the-badge&logo=typescript&logoColor=white">
|
|
8
|
+
</p>
|
|
9
|
+
<p>
|
|
10
|
+
<a href="https://www.npmjs.com/package/lavalink-client">
|
|
11
|
+
<img src="https://img.shields.io/npm/v/lavalink-client.svg?maxAge=3600&style=for-the-badge&logo=npm&logoColor=red" alt="NPM version" />
|
|
12
|
+
</a>
|
|
13
|
+
<a href="https://www.npmjs.com/package/lavalink-client">
|
|
14
|
+
<img src="https://img.shields.io/npm/dt/lavalink-client.svg?maxAge=3600&style=for-the-badge&logo=npm&logoColor=red" alt="NPM downloads" />
|
|
15
|
+
</a>
|
|
16
|
+
<a href="https://lc4.gitbook.io/lavalink-client/">
|
|
17
|
+
<img src="https://img.shields.io/badge/Documation-%230288D1.svg?style=for-the-badge&logo=gitbook&logoColor=white" alt="Get Started Now">
|
|
18
|
+
</a>
|
|
19
|
+
</p>
|
|
20
|
+
<p>
|
|
21
|
+
<a href="https://www.npmjs.com/package/lavalink-client"><img src="https://nodei.co/npm/lavalink-client.png?downloads=true&stars=true" alt="npm install lavalink-client" /></a>
|
|
22
|
+
</p>
|
|
23
|
+
</div>
|
|
3
24
|
|
|
4
25
|
# Install
|
|
5
26
|
|
|
@@ -11,6 +32,7 @@ Latest stable Version: (currently, unreleased)
|
|
|
11
32
|
npm install --save lavalink-client
|
|
12
33
|
```
|
|
13
34
|
|
|
35
|
+
|
|
14
36
|
Dev Version: (Current)
|
|
15
37
|
|
|
16
38
|
```bash
|
|
@@ -7,7 +7,7 @@ export declare class FilterManager {
|
|
|
7
7
|
equalizerBands: EQBand[];
|
|
8
8
|
filterUpdatedState: number;
|
|
9
9
|
filters: PlayerFilters;
|
|
10
|
-
data:
|
|
10
|
+
data: FilterData;
|
|
11
11
|
constructor(player: Player);
|
|
12
12
|
applyPlayerFilters(): Promise<void>;
|
|
13
13
|
/**
|
|
@@ -215,9 +215,8 @@ export interface ReverbFilter {
|
|
|
215
215
|
delay: number;
|
|
216
216
|
decay: number;
|
|
217
217
|
}
|
|
218
|
-
export interface
|
|
218
|
+
export interface FilterData {
|
|
219
219
|
volume?: number;
|
|
220
|
-
equalizer?: EQBand[];
|
|
221
220
|
karaoke?: KaraokeFilter;
|
|
222
221
|
timescale?: TimescaleFilter;
|
|
223
222
|
tremolo?: FreqFilter;
|
|
@@ -229,3 +228,6 @@ export interface LavalinkFilterData {
|
|
|
229
228
|
echo: EchoFilter;
|
|
230
229
|
reverb: ReverbFilter;
|
|
231
230
|
}
|
|
231
|
+
export interface LavalinkFilterData extends FilterData {
|
|
232
|
+
equalizer?: EQBand[];
|
|
233
|
+
}
|
|
@@ -1,22 +1,24 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import { EventEmitter } from "events";
|
|
3
3
|
import { NodeManager } from "./NodeManager";
|
|
4
|
-
import {
|
|
5
|
-
import { GuildShardPayload,
|
|
4
|
+
import { ManagerQueueOptions } from "./Queue";
|
|
5
|
+
import { GuildShardPayload, ManagerUitls, MiniMap, SearchPlatform, TrackEndEvent, TrackExceptionEvent, TrackStartEvent, TrackStuckEvent, VoicePacket, VoiceServer, VoiceState, WebSocketClosedEvent } from "./Utils";
|
|
6
6
|
import { LavalinkNodeOptions } from "./Node";
|
|
7
|
-
import { DestroyReasonsType, Player, PlayerOptions } from "./Player";
|
|
7
|
+
import { DestroyReasonsType, Player, PlayerJson, PlayerOptions } from "./Player";
|
|
8
8
|
import { Track, UnresolvedTrack } from "./Track";
|
|
9
9
|
export interface LavalinkManager {
|
|
10
10
|
nodeManager: NodeManager;
|
|
11
11
|
utils: ManagerUitls;
|
|
12
12
|
}
|
|
13
13
|
export interface BotClientOptions {
|
|
14
|
+
/** Bot Client Id */
|
|
14
15
|
id: string;
|
|
16
|
+
/** Bot Client Username */
|
|
15
17
|
username?: string;
|
|
16
18
|
/** So users can pass entire objects / classes */
|
|
17
19
|
[x: string | number | symbol | undefined]: any;
|
|
18
20
|
}
|
|
19
|
-
export interface
|
|
21
|
+
export interface ManagerPlayerOptions {
|
|
20
22
|
/** If the Lavalink Volume should be decremented by x number */
|
|
21
23
|
volumeDecrementer?: number;
|
|
22
24
|
/** How often it should update the the player Position */
|
|
@@ -39,15 +41,21 @@ export interface LavalinkPlayerOptions {
|
|
|
39
41
|
autoPlayFunction?: (player: Player, lastPlayedTrack: Track) => Promise<void>;
|
|
40
42
|
destroyAfterMs?: number;
|
|
41
43
|
};
|
|
44
|
+
useUnresolvedData?: boolean;
|
|
42
45
|
}
|
|
43
46
|
export interface ManagerOptions {
|
|
47
|
+
/** The Node Options, for all Nodes! (on init) */
|
|
44
48
|
nodes: LavalinkNodeOptions[];
|
|
45
|
-
|
|
49
|
+
/** @async The Function to send the voice connection changes from Lavalink to Discord */
|
|
50
|
+
sendToShard: (guildId: string, payload: GuildShardPayload) => void;
|
|
51
|
+
/** The Bot Client's Data for Authorization */
|
|
46
52
|
client?: BotClientOptions;
|
|
47
|
-
|
|
53
|
+
/** QueueOptions for all Queues */
|
|
54
|
+
queueOptions?: ManagerQueueOptions;
|
|
55
|
+
/** PlayerOptions for all Players */
|
|
56
|
+
playerOptions?: ManagerPlayerOptions;
|
|
57
|
+
/** If it should skip to the next Track on TrackEnd / TrackError etc. events */
|
|
48
58
|
autoSkip?: boolean;
|
|
49
|
-
/** @async */
|
|
50
|
-
sendToShard: (guildId: string, payload: GuildShardPayload) => void;
|
|
51
59
|
}
|
|
52
60
|
interface LavalinkManagerEvents {
|
|
53
61
|
/**
|
|
@@ -104,7 +112,7 @@ interface LavalinkManagerEvents {
|
|
|
104
112
|
* Always emits when the player (on lavalink side) got updated
|
|
105
113
|
* @event Manager#playerUpdate
|
|
106
114
|
*/
|
|
107
|
-
"playerUpdate": (
|
|
115
|
+
"playerUpdate": (oldPlayerJson: PlayerJson, newPlayer: Player) => void;
|
|
108
116
|
}
|
|
109
117
|
export interface LavalinkManager {
|
|
110
118
|
options: ManagerOptions;
|
|
@@ -112,7 +120,7 @@ export interface LavalinkManager {
|
|
|
112
120
|
emit<U extends keyof LavalinkManagerEvents>(event: U, ...args: Parameters<LavalinkManagerEvents[U]>): boolean;
|
|
113
121
|
}
|
|
114
122
|
export declare class LavalinkManager extends EventEmitter {
|
|
115
|
-
static DefaultSources: Record<SearchPlatform, LavalinkSearchPlatform>;
|
|
123
|
+
static DefaultSources: Record<SearchPlatform, import("./Utils").LavalinkSearchPlatform>;
|
|
116
124
|
static SourceLinksRegexes: Record<import("./Utils").SourcesRegex, RegExp>;
|
|
117
125
|
initiated: boolean;
|
|
118
126
|
readonly players: MiniMap<string, Player>;
|
|
@@ -81,7 +81,7 @@ class LavalinkManager extends events_1.EventEmitter {
|
|
|
81
81
|
const keys = Object.getOwnPropertyNames(Object.getPrototypeOf(options.queueOptions?.queueChangesWatcher));
|
|
82
82
|
const requiredKeys = ["tracksAdd", "tracksRemoved", "shuffled"];
|
|
83
83
|
if (!requiredKeys.every(v => keys.includes(v)) || !requiredKeys.every(v => typeof options.queueOptions?.queueChangesWatcher[v] === "function"))
|
|
84
|
-
throw new SyntaxError(`The provided ManagerOption.
|
|
84
|
+
throw new SyntaxError(`The provided ManagerOption.DefaultQueueChangesWatcher, does not have all required functions: ${requiredKeys.join(", ")}`);
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
87
|
constructor(options) {
|
|
@@ -4,7 +4,7 @@ import { NodeManager } from "./NodeManager";
|
|
|
4
4
|
import internal from "stream";
|
|
5
5
|
import { InvalidLavalinkRestRequest, LavalinkPlayer, PlayerUpdateInfo, RoutePlanner, Session, Base64 } from "./Utils";
|
|
6
6
|
import { DestroyReasonsType } from "./Player";
|
|
7
|
-
import {
|
|
7
|
+
import { Track } from "./Track";
|
|
8
8
|
/** Modifies any outgoing REST requests. */
|
|
9
9
|
export type ModifyRequest = (options: Dispatcher.RequestOptions) => void;
|
|
10
10
|
export interface LavalinkNodeOptions {
|
|
@@ -185,13 +185,13 @@ export declare class LavalinkNode {
|
|
|
185
185
|
* @param encoded
|
|
186
186
|
* @returns
|
|
187
187
|
*/
|
|
188
|
-
singleTrack: (encoded: Base64) => Promise<
|
|
188
|
+
singleTrack: (encoded: Base64, requester: unknown) => Promise<Track>;
|
|
189
189
|
/**
|
|
190
190
|
*
|
|
191
191
|
* @param encodeds Decodes multiple tracks into their info
|
|
192
192
|
* @returns
|
|
193
193
|
*/
|
|
194
|
-
multipleTracks: (encodeds: Base64[]) => Promise<
|
|
194
|
+
multipleTracks: (encodeds: Base64[], requester: unknown) => Promise<Track[]>;
|
|
195
195
|
};
|
|
196
196
|
/**
|
|
197
197
|
* Request Lavalink statistics.
|
|
@@ -227,25 +227,27 @@ class LavalinkNode {
|
|
|
227
227
|
* @param encoded
|
|
228
228
|
* @returns
|
|
229
229
|
*/
|
|
230
|
-
singleTrack: async (encoded) => {
|
|
230
|
+
singleTrack: async (encoded, requester) => {
|
|
231
231
|
if (!encoded)
|
|
232
232
|
throw new SyntaxError("No encoded (Base64 string) was provided");
|
|
233
|
-
return
|
|
233
|
+
// return the decoded + builded track
|
|
234
|
+
return this.NodeManager.LavalinkManager.utils.buildTrack(await this.request(`/decodetrack?encodedTrack=${encoded}`), requester);
|
|
234
235
|
},
|
|
235
236
|
/**
|
|
236
237
|
*
|
|
237
238
|
* @param encodeds Decodes multiple tracks into their info
|
|
238
239
|
* @returns
|
|
239
240
|
*/
|
|
240
|
-
multipleTracks: async (encodeds) => {
|
|
241
|
+
multipleTracks: async (encodeds, requester) => {
|
|
241
242
|
if (!Array.isArray(encodeds) || !encodeds.every(v => typeof v === "string" && v.length > 1))
|
|
242
243
|
throw new SyntaxError("You need to provide encodeds, which is an array of base64 strings");
|
|
244
|
+
// return the decoded + builded tracks
|
|
243
245
|
return await this.request(`/decodetracks`, r => {
|
|
244
246
|
r.method = "POST";
|
|
245
247
|
r.body = JSON.stringify(encodeds);
|
|
246
248
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
247
249
|
r.headers["Content-Type"] = "application/json";
|
|
248
|
-
});
|
|
250
|
+
}).then((r) => r.map(track => this.NodeManager.LavalinkManager.utils.buildTrack(track, requester)));
|
|
249
251
|
}
|
|
250
252
|
};
|
|
251
253
|
/**
|
|
@@ -356,7 +358,7 @@ class LavalinkNode {
|
|
|
356
358
|
if (data.playerOptions.filters.volume)
|
|
357
359
|
player.filterManager.data.volume = data.playerOptions.filters.volume;
|
|
358
360
|
if (data.playerOptions.filters.equalizer)
|
|
359
|
-
player.filterManager.
|
|
361
|
+
player.filterManager.equalizerBands = data.playerOptions.filters.equalizer;
|
|
360
362
|
if (data.playerOptions.filters.karaoke)
|
|
361
363
|
player.filterManager.data.karaoke = data.playerOptions.filters.karaoke;
|
|
362
364
|
if (data.playerOptions.filters.lowPass)
|
|
@@ -439,6 +441,7 @@ class LavalinkNode {
|
|
|
439
441
|
const player = this.NodeManager.LavalinkManager.getPlayer(payload.guildId);
|
|
440
442
|
if (!player)
|
|
441
443
|
return;
|
|
444
|
+
const oldPlayer = player?.toJSON();
|
|
442
445
|
if (player.get("internal_updateInterval"))
|
|
443
446
|
clearInterval(player.get("internal_updateInterval"));
|
|
444
447
|
// override the position
|
|
@@ -476,7 +479,7 @@ class LavalinkNode {
|
|
|
476
479
|
player.filterManager.filterUpdatedState = 0;
|
|
477
480
|
}
|
|
478
481
|
}
|
|
479
|
-
this.NodeManager.LavalinkManager.emit("playerUpdate", player);
|
|
482
|
+
this.NodeManager.LavalinkManager.emit("playerUpdate", oldPlayer, player);
|
|
480
483
|
break;
|
|
481
484
|
case "event":
|
|
482
485
|
this.handleEvent(payload);
|
|
@@ -523,7 +526,6 @@ class LavalinkNode {
|
|
|
523
526
|
return this.NodeManager.LavalinkManager.emit("trackStart", player, track, payload);
|
|
524
527
|
}
|
|
525
528
|
async trackEnd(player, track, payload) {
|
|
526
|
-
console.log(payload.reason);
|
|
527
529
|
// If there are no songs in the queue
|
|
528
530
|
if (!player.queue.tracks.length && player.repeatMode === "off")
|
|
529
531
|
return this.queueEnd(player, track, payload);
|
|
@@ -560,8 +562,11 @@ class LavalinkNode {
|
|
|
560
562
|
await this.NodeManager.LavalinkManager.options?.playerOptions?.onEmptyQueue?.autoPlayFunction(player, track);
|
|
561
563
|
if (player.queue.tracks.length > 0)
|
|
562
564
|
await (0, Utils_1.queueTrackEnd)(player);
|
|
563
|
-
if (player.queue.current)
|
|
565
|
+
if (player.queue.current) {
|
|
566
|
+
if (payload.type === "TrackEndEvent")
|
|
567
|
+
this.NodeManager.LavalinkManager.emit("trackEnd", player, track, payload);
|
|
564
568
|
return player.play({ noReplace: true, paused: false });
|
|
569
|
+
}
|
|
565
570
|
}
|
|
566
571
|
player.queue.previous.unshift(track);
|
|
567
572
|
if (payload?.reason !== "stopped") {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FilterManager, LavalinkFilterData } from "./Filters";
|
|
1
|
+
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";
|
|
@@ -7,6 +7,27 @@ import { LavalinkPlayerVoiceOptions, SearchPlatform, SearchResult } from "./Util
|
|
|
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>;
|
|
10
|
+
export interface PlayerJson {
|
|
11
|
+
guildId: string;
|
|
12
|
+
options: PlayerOptions;
|
|
13
|
+
voiceChannelId: string;
|
|
14
|
+
textChannelId?: string;
|
|
15
|
+
position: number;
|
|
16
|
+
lastPosition: number;
|
|
17
|
+
volume: number;
|
|
18
|
+
lavalinkVolume: number;
|
|
19
|
+
repeatMode: RepeatMode;
|
|
20
|
+
paused: boolean;
|
|
21
|
+
playing: boolean;
|
|
22
|
+
createdTimeStamp?: number;
|
|
23
|
+
filters: FilterData;
|
|
24
|
+
ping: {
|
|
25
|
+
ws: number;
|
|
26
|
+
lavalink: number;
|
|
27
|
+
};
|
|
28
|
+
equalizer: EQBand[];
|
|
29
|
+
nodeId?: string;
|
|
30
|
+
}
|
|
10
31
|
export type RepeatMode = "queue" | "track" | "off";
|
|
11
32
|
export interface PlayerOptions {
|
|
12
33
|
guildId: string;
|
|
@@ -170,22 +191,6 @@ export declare class Player {
|
|
|
170
191
|
*/
|
|
171
192
|
changeNode(newNode: LavalinkNode | string): Promise<string>;
|
|
172
193
|
/** Converts the Player including Queue to a Json state */
|
|
173
|
-
toJSON():
|
|
174
|
-
guildId: string;
|
|
175
|
-
options: PlayerOptions;
|
|
176
|
-
voiceChannelId: string;
|
|
177
|
-
textChannelId: string;
|
|
178
|
-
position: number;
|
|
179
|
-
lastPosition: number;
|
|
180
|
-
volume: number;
|
|
181
|
-
lavalinkVolume: number;
|
|
182
|
-
repeatMode: RepeatMode;
|
|
183
|
-
paused: boolean;
|
|
184
|
-
playing: boolean;
|
|
185
|
-
createdTimeStamp: number;
|
|
186
|
-
filters: {};
|
|
187
|
-
equalizer: import("./Filters").EQBand[];
|
|
188
|
-
nodeId: string;
|
|
189
|
-
};
|
|
194
|
+
toJSON(): PlayerJson;
|
|
190
195
|
}
|
|
191
196
|
export {};
|
|
@@ -1,53 +1,58 @@
|
|
|
1
1
|
import { Track, UnresolvedTrack } from "./Track";
|
|
2
|
+
import { MiniMap } from "./Utils";
|
|
2
3
|
export interface StoredQueue {
|
|
3
4
|
current: Track | null;
|
|
4
5
|
previous: Track[];
|
|
5
6
|
tracks: Track[];
|
|
6
7
|
}
|
|
7
|
-
export interface
|
|
8
|
+
export interface QueueStoreManager extends Record<string, any> {
|
|
8
9
|
/** @async get a Value (MUST RETURN UNPARSED!) */
|
|
9
10
|
get: (guildId: unknown) => Promise<any>;
|
|
10
11
|
/** @async Set a value inside a guildId (MUST BE UNPARSED) */
|
|
11
12
|
set: (guildId: unknown, value: unknown) => Promise<any>;
|
|
12
13
|
/** @async Delete a Database Value based of it's guildId */
|
|
13
14
|
delete: (guildId: unknown) => Promise<any>;
|
|
14
|
-
/** @async Transform the value(s) inside of the
|
|
15
|
+
/** @async Transform the value(s) inside of the QueueStoreManager (IF YOU DON'T NEED PARSING/STRINGIFY, then just return the value) */
|
|
15
16
|
stringify: (value: unknown) => Promise<any>;
|
|
16
17
|
/** @async Parse the saved value back to the Queue (IF YOU DON'T NEED PARSING/STRINGIFY, then just return the value) */
|
|
17
18
|
parse: (value: unknown) => Promise<Partial<StoredQueue>>;
|
|
18
19
|
}
|
|
19
|
-
export interface
|
|
20
|
-
maxPreviousTracks
|
|
21
|
-
queueStore?:
|
|
20
|
+
export interface ManagerQueueOptions {
|
|
21
|
+
maxPreviousTracks?: number;
|
|
22
|
+
queueStore?: QueueStoreManager;
|
|
22
23
|
queueChangesWatcher?: QueueChangesWatcher;
|
|
23
24
|
}
|
|
24
25
|
export interface QueueSaver {
|
|
25
26
|
/** @private */
|
|
26
|
-
_:
|
|
27
|
+
_: QueueStoreManager;
|
|
27
28
|
/** @private */
|
|
28
|
-
options:
|
|
29
|
+
options: {
|
|
30
|
+
maxPreviousTracks: number;
|
|
31
|
+
};
|
|
29
32
|
}
|
|
30
33
|
export declare class QueueSaver {
|
|
31
|
-
constructor(options:
|
|
34
|
+
constructor(options: ManagerQueueOptions);
|
|
32
35
|
get(guildId: string): Promise<Partial<StoredQueue>>;
|
|
33
36
|
delete(guildId: string): Promise<any>;
|
|
34
37
|
set(guildId: string, value: any): Promise<any>;
|
|
35
38
|
sync(guildId: string): Promise<Partial<StoredQueue>>;
|
|
36
39
|
}
|
|
37
|
-
export declare class DefaultQueueStore {
|
|
40
|
+
export declare class DefaultQueueStore implements QueueStoreManager {
|
|
38
41
|
private data;
|
|
39
42
|
constructor();
|
|
40
|
-
get(guildId: any): Promise<
|
|
41
|
-
set(guildId: any, stringifiedValue: any): Promise<
|
|
43
|
+
get(guildId: any): Promise<unknown>;
|
|
44
|
+
set(guildId: any, stringifiedValue: any): Promise<MiniMap<unknown, unknown>>;
|
|
42
45
|
delete(guildId: any): Promise<boolean>;
|
|
43
46
|
stringify(value: any): Promise<any>;
|
|
44
47
|
parse(value: any): Promise<Partial<StoredQueue>>;
|
|
45
48
|
}
|
|
46
|
-
export
|
|
47
|
-
|
|
48
|
-
tracksAdd(guildId: string, tracks: (Track | UnresolvedTrack)[], position: number, oldStoredQueue: StoredQueue, newStoredQueue: StoredQueue)
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
export interface QueueChangesWatcher {
|
|
50
|
+
/** get a Value (MUST RETURN UNPARSED!) */
|
|
51
|
+
tracksAdd: (guildId: string, tracks: (Track | UnresolvedTrack)[], position: number, oldStoredQueue: StoredQueue, newStoredQueue: StoredQueue) => any;
|
|
52
|
+
/** Set a value inside a guildId (MUST BE UNPARSED) */
|
|
53
|
+
tracksRemoved: (guildId: string, tracks: (Track | UnresolvedTrack)[], position: number, oldStoredQueue: StoredQueue, newStoredQueue: StoredQueue) => any;
|
|
54
|
+
/** Set a value inside a guildId (MUST BE UNPARSED) */
|
|
55
|
+
shuffled: (guildId: string, oldStoredQueue: StoredQueue, newStoredQueue: StoredQueue) => any;
|
|
51
56
|
}
|
|
52
57
|
export declare class Queue {
|
|
53
58
|
readonly tracks: (Track | UnresolvedTrack)[];
|
|
@@ -60,7 +65,7 @@ export declare class Queue {
|
|
|
60
65
|
private readonly QueueSaver;
|
|
61
66
|
private managerUtils;
|
|
62
67
|
private queueChanges;
|
|
63
|
-
constructor(guildId: string, data?: Partial<StoredQueue>, QueueSaver?: QueueSaver, queueOptions?:
|
|
68
|
+
constructor(guildId: string, data?: Partial<StoredQueue>, QueueSaver?: QueueSaver, queueOptions?: ManagerQueueOptions);
|
|
64
69
|
private applyData;
|
|
65
70
|
/**
|
|
66
71
|
* Utils for a Queue
|
|
@@ -77,7 +82,7 @@ export declare class Queue {
|
|
|
77
82
|
sync: (override?: boolean, dontSyncCurrent?: boolean) => Promise<void>;
|
|
78
83
|
destroy: () => Promise<any>;
|
|
79
84
|
/**
|
|
80
|
-
* @returns {{current:Track|null, previous:Track[], tracks:Track[]}}The Queue, but in a raw State, which allows easier handling for the
|
|
85
|
+
* @returns {{current:Track|null, previous:Track[], tracks:Track[]}}The Queue, but in a raw State, which allows easier handling for the QueueStoreManager
|
|
81
86
|
*/
|
|
82
87
|
toJSON: () => StoredQueue;
|
|
83
88
|
/**
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Queue = exports.
|
|
3
|
+
exports.Queue = exports.DefaultQueueStore = exports.QueueSaver = void 0;
|
|
4
4
|
const Utils_1 = require("./Utils");
|
|
5
5
|
class QueueSaver {
|
|
6
6
|
constructor(options) {
|
|
7
|
-
this._ = options
|
|
7
|
+
this._ = options?.queueStore || new DefaultQueueStore();
|
|
8
8
|
this.options = {
|
|
9
|
-
maxPreviousTracks: options
|
|
9
|
+
maxPreviousTracks: options?.maxPreviousTracks || 25,
|
|
10
10
|
};
|
|
11
11
|
}
|
|
12
12
|
async get(guildId) {
|
|
@@ -24,9 +24,8 @@ class QueueSaver {
|
|
|
24
24
|
}
|
|
25
25
|
exports.QueueSaver = QueueSaver;
|
|
26
26
|
class DefaultQueueStore {
|
|
27
|
-
data = new
|
|
28
|
-
constructor() {
|
|
29
|
-
}
|
|
27
|
+
data = new Utils_1.MiniMap();
|
|
28
|
+
constructor() { }
|
|
30
29
|
async get(guildId) {
|
|
31
30
|
return await this.data.get(guildId);
|
|
32
31
|
}
|
|
@@ -44,20 +43,6 @@ class DefaultQueueStore {
|
|
|
44
43
|
}
|
|
45
44
|
}
|
|
46
45
|
exports.DefaultQueueStore = DefaultQueueStore;
|
|
47
|
-
class QueueChangesWatcher {
|
|
48
|
-
constructor() {
|
|
49
|
-
}
|
|
50
|
-
tracksAdd(guildId, tracks, position, oldStoredQueue, newStoredQueue) {
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
tracksRemoved(guildId, tracks, position, oldStoredQueue, newStoredQueue) {
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
shuffled(guildId, oldStoredQueue, newStoredQueue) {
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
exports.QueueChangesWatcher = QueueChangesWatcher;
|
|
61
46
|
class Queue {
|
|
62
47
|
tracks = [];
|
|
63
48
|
previous = [];
|
|
@@ -111,7 +96,7 @@ class Queue {
|
|
|
111
96
|
return await this.QueueSaver.delete(this.guildId);
|
|
112
97
|
},
|
|
113
98
|
/**
|
|
114
|
-
* @returns {{current:Track|null, previous:Track[], tracks:Track[]}}The Queue, but in a raw State, which allows easier handling for the
|
|
99
|
+
* @returns {{current:Track|null, previous:Track[], tracks:Track[]}}The Queue, but in a raw State, which allows easier handling for the QueueStoreManager
|
|
115
100
|
*/
|
|
116
101
|
toJSON: () => {
|
|
117
102
|
if (this.previous.length > this.options.maxPreviousTracks)
|
|
@@ -7,8 +7,8 @@ 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 LavalinkSearchPlatform = "ytsearch" | "ytmsearch" | "scsearch" | "spsearch" | "sprec" | "amsearch" | "dzsearch" | "dzisrc" | "
|
|
11
|
-
export type ClientSearchPlatform = "youtube" | "yt" | "
|
|
10
|
+
export type LavalinkSearchPlatform = "ytsearch" | "ytmsearch" | "scsearch" | "spsearch" | "sprec" | "amsearch" | "dzsearch" | "dzisrc" | "ymsearch" | "speak" | "tts" | "ftts";
|
|
11
|
+
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
12
|
export type SearchPlatform = LavalinkSearchPlatform | ClientSearchPlatform;
|
|
13
13
|
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
14
|
export interface PlaylistInfo {
|
|
@@ -6,6 +6,8 @@ exports.TrackSymbol = Symbol("LC-Track");
|
|
|
6
6
|
exports.UnresolvedTrackSymbol = Symbol("LC-Track-Unresolved");
|
|
7
7
|
exports.QueueSymbol = Symbol("LC-Queue");
|
|
8
8
|
exports.NodeSymbol = Symbol("LC-Node");
|
|
9
|
+
/** @hidden */
|
|
10
|
+
const escapeRegExp = (str) => str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
9
11
|
class ManagerUitls {
|
|
10
12
|
constructor(LavalinkManager) {
|
|
11
13
|
this.manager = LavalinkManager;
|
|
@@ -23,7 +25,7 @@ class ManagerUitls {
|
|
|
23
25
|
identifier: data.info?.identifier,
|
|
24
26
|
title: data.info?.title,
|
|
25
27
|
author: data.info?.author,
|
|
26
|
-
duration: data.info?.length,
|
|
28
|
+
duration: data.info?.length || data.info?.duration,
|
|
27
29
|
artworkUrl: data.info?.artworkUrl || data.pluginInfo?.artworkUrl || data.plugin?.artworkUrl,
|
|
28
30
|
uri: data.info?.uri,
|
|
29
31
|
sourceName: data.info?.sourceName,
|
|
@@ -95,13 +97,21 @@ class ManagerUitls {
|
|
|
95
97
|
* @returns
|
|
96
98
|
*/
|
|
97
99
|
isTrack(data) {
|
|
98
|
-
|
|
100
|
+
if (!data)
|
|
101
|
+
return false;
|
|
102
|
+
if (data[exports.TrackSymbol] === true)
|
|
103
|
+
return true;
|
|
104
|
+
return typeof data?.encoded === "string" && typeof data?.info === "object" && !("resolve" in data);
|
|
99
105
|
}
|
|
100
106
|
/**
|
|
101
107
|
* Checks if the provided argument is a valid UnresolvedTrack.
|
|
102
108
|
* @param track
|
|
103
109
|
*/
|
|
104
110
|
isUnresolvedTrack(data) {
|
|
111
|
+
if (!data)
|
|
112
|
+
return false;
|
|
113
|
+
if (data[exports.UnresolvedTrackSymbol] === true)
|
|
114
|
+
return true;
|
|
105
115
|
return typeof data === "object" && "info" in data && typeof data.info.title === "string" && typeof data.resolve === "function";
|
|
106
116
|
}
|
|
107
117
|
/**
|
|
@@ -277,6 +287,32 @@ async function queueTrackEnd(player) {
|
|
|
277
287
|
return player.queue.current;
|
|
278
288
|
}
|
|
279
289
|
exports.queueTrackEnd = queueTrackEnd;
|
|
290
|
+
async function applyUnresolvedData(resTrack, data, utils) {
|
|
291
|
+
if (!resTrack?.info || !data?.info)
|
|
292
|
+
return;
|
|
293
|
+
if (utils.manager.options.playerOptions?.useUnresolvedData === true) { // overwrite values
|
|
294
|
+
if (data.info.uri)
|
|
295
|
+
resTrack.info.uri = data.info.uri;
|
|
296
|
+
if (data.info.artworkUrl?.length)
|
|
297
|
+
resTrack.info.artworkUrl = data.info.artworkUrl;
|
|
298
|
+
if (data.info.title?.length)
|
|
299
|
+
resTrack.info.title = data.info.title;
|
|
300
|
+
if (data.info.author?.length)
|
|
301
|
+
resTrack.info.author = data.info.author;
|
|
302
|
+
}
|
|
303
|
+
else { // only overwrite if undefined / invalid
|
|
304
|
+
if ((resTrack.info.title == 'Unknown title' || resTrack.info.title == "Unspecified description") && resTrack.info.title != data.info.title)
|
|
305
|
+
resTrack.info.title = data.info.title;
|
|
306
|
+
if (resTrack.info.author != data.info.author)
|
|
307
|
+
resTrack.info.author = data.info.author;
|
|
308
|
+
if (resTrack.info.artworkUrl != data.info.artworkUrl)
|
|
309
|
+
resTrack.info.artworkUrl = data.info.artworkUrl;
|
|
310
|
+
}
|
|
311
|
+
for (const key of Object.keys(data.info))
|
|
312
|
+
if (typeof resTrack.info[key] === "undefined" && key !== "resolve" && data.info[key])
|
|
313
|
+
resTrack.info[key] = data.info[key]; // add non-existing values
|
|
314
|
+
return resTrack;
|
|
315
|
+
}
|
|
280
316
|
async function getClosestTrack(data, player, utils) {
|
|
281
317
|
if (!player || !player.node)
|
|
282
318
|
throw new RangeError("No player with a lavalink node was provided");
|
|
@@ -288,19 +324,35 @@ async function getClosestTrack(data, player, utils) {
|
|
|
288
324
|
throw new SyntaxError("the track title is required for unresolved tracks");
|
|
289
325
|
if (!data.requester)
|
|
290
326
|
throw new SyntaxError("The requester is required");
|
|
327
|
+
// try to decode the track, if possible
|
|
291
328
|
if (typeof data.encoded === "string") {
|
|
292
|
-
const r = await player.node.decode.singleTrack(data.encoded);
|
|
329
|
+
const r = await player.node.decode.singleTrack(data.encoded, data.requester);
|
|
293
330
|
if (r)
|
|
294
|
-
return
|
|
331
|
+
return applyUnresolvedData(r, data, utils);
|
|
295
332
|
}
|
|
333
|
+
// try to fetch the track via a uri if possible
|
|
296
334
|
if (typeof data.info.uri === "string") {
|
|
297
335
|
const r = await player.search({ query: data?.info?.uri }, data.requester).then(v => v.tracks[0]);
|
|
298
336
|
if (r)
|
|
299
|
-
return r;
|
|
337
|
+
return applyUnresolvedData(r, data, utils);
|
|
300
338
|
}
|
|
339
|
+
// search the track as closely as possible
|
|
301
340
|
const query = [data.info?.title, data.info?.author].filter(str => !!str).join(" by ");
|
|
302
341
|
const sourceName = data.info?.sourceName;
|
|
303
342
|
return await player.search({
|
|
304
343
|
query, source: sourceName !== "bandcamp" && sourceName !== "twitch" && sourceName !== "flowery-tts" ? sourceName : player.LavalinkManager.options?.playerOptions?.defaultSearchPlatform,
|
|
305
|
-
}, data.requester).then(
|
|
344
|
+
}, data.requester).then(res => {
|
|
345
|
+
let trackToUse = null;
|
|
346
|
+
// try to find via author name
|
|
347
|
+
if (data.info.author && !trackToUse)
|
|
348
|
+
trackToUse = res.tracks.find(track => [data.info.author, `${data.info.author} - Topic`].some(name => new RegExp(`^${escapeRegExp(name)}$`, "i").test(track.info.author)) || new RegExp(`^${escapeRegExp(data.info.title)}$`, "i").test(track.info.title));
|
|
349
|
+
// try to find via duration
|
|
350
|
+
if (data.info.duration && !trackToUse)
|
|
351
|
+
trackToUse = res.tracks.find(track => (track.info.duration >= (data.info.duration - 1500)) && (track.info.duration <= (data.info.duration + 1500)));
|
|
352
|
+
// try to find via isrc
|
|
353
|
+
if (data.info.isrc && !trackToUse)
|
|
354
|
+
trackToUse = res.tracks.find(track => track.info.isrc === data.info.isrc);
|
|
355
|
+
// apply unresolved data and return the track
|
|
356
|
+
return applyUnresolvedData(trackToUse || res.tracks[0], data, utils);
|
|
357
|
+
});
|
|
306
358
|
}
|
|
@@ -7,7 +7,7 @@ export declare class FilterManager {
|
|
|
7
7
|
equalizerBands: EQBand[];
|
|
8
8
|
filterUpdatedState: number;
|
|
9
9
|
filters: PlayerFilters;
|
|
10
|
-
data:
|
|
10
|
+
data: FilterData;
|
|
11
11
|
constructor(player: Player);
|
|
12
12
|
applyPlayerFilters(): Promise<void>;
|
|
13
13
|
/**
|
|
@@ -215,9 +215,8 @@ export interface ReverbFilter {
|
|
|
215
215
|
delay: number;
|
|
216
216
|
decay: number;
|
|
217
217
|
}
|
|
218
|
-
export interface
|
|
218
|
+
export interface FilterData {
|
|
219
219
|
volume?: number;
|
|
220
|
-
equalizer?: EQBand[];
|
|
221
220
|
karaoke?: KaraokeFilter;
|
|
222
221
|
timescale?: TimescaleFilter;
|
|
223
222
|
tremolo?: FreqFilter;
|
|
@@ -229,3 +228,6 @@ export interface LavalinkFilterData {
|
|
|
229
228
|
echo: EchoFilter;
|
|
230
229
|
reverb: ReverbFilter;
|
|
231
230
|
}
|
|
231
|
+
export interface LavalinkFilterData extends FilterData {
|
|
232
|
+
equalizer?: EQBand[];
|
|
233
|
+
}
|