lavalink-client 2.1.7 → 2.2.1
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 +87 -1
- package/dist/cjs/structures/CustomSearches/BandCampSearch.js +3 -2
- package/dist/cjs/structures/Filters.d.ts +1 -1
- package/dist/cjs/structures/Filters.js +5 -5
- package/dist/cjs/structures/LavalinkManager.d.ts +23 -5
- package/dist/cjs/structures/LavalinkManager.js +15 -1
- package/dist/cjs/structures/LavalinkManagerStatics.d.ts +3 -0
- package/dist/cjs/structures/LavalinkManagerStatics.js +8 -1
- package/dist/cjs/structures/Node.d.ts +317 -35
- package/dist/cjs/structures/Node.js +330 -85
- package/dist/cjs/structures/NodeManager.d.ts +1 -1
- package/dist/cjs/structures/Player.d.ts +44 -8
- package/dist/cjs/structures/Player.js +35 -27
- package/dist/cjs/structures/Queue.js +1 -1
- package/dist/cjs/structures/Utils.d.ts +5 -2
- package/dist/cjs/structures/Utils.js +7 -4
- package/dist/esm/structures/CustomSearches/BandCampSearch.js +2 -1
- package/dist/esm/structures/Filters.d.ts +1 -1
- package/dist/esm/structures/Filters.js +5 -5
- package/dist/esm/structures/LavalinkManager.d.ts +23 -5
- package/dist/esm/structures/LavalinkManager.js +15 -1
- package/dist/esm/structures/LavalinkManagerStatics.d.ts +3 -0
- package/dist/esm/structures/LavalinkManagerStatics.js +8 -1
- package/dist/esm/structures/Node.d.ts +317 -35
- package/dist/esm/structures/Node.js +330 -85
- package/dist/esm/structures/NodeManager.d.ts +1 -1
- package/dist/esm/structures/Player.d.ts +44 -8
- package/dist/esm/structures/Player.js +35 -27
- package/dist/esm/structures/Queue.js +1 -1
- package/dist/esm/structures/Utils.d.ts +5 -2
- package/dist/esm/structures/Utils.js +7 -4
- package/dist/types/structures/Filters.d.ts +1 -1
- package/dist/types/structures/LavalinkManager.d.ts +23 -5
- package/dist/types/structures/LavalinkManagerStatics.d.ts +3 -0
- package/dist/types/structures/Node.d.ts +317 -35
- package/dist/types/structures/NodeManager.d.ts +1 -1
- package/dist/types/structures/Player.d.ts +44 -8
- package/dist/types/structures/Utils.d.ts +5 -2
- package/package.json +5 -4
|
@@ -5,7 +5,7 @@ import { LavalinkNode, LavalinkNodeOptions } from "./Node";
|
|
|
5
5
|
import { DestroyReasonsType } from "./Player";
|
|
6
6
|
import { LavalinkPlayer, MiniMap } from "./Utils";
|
|
7
7
|
type LavalinkNodeIdentifier = string;
|
|
8
|
-
interface NodeManagerEvents {
|
|
8
|
+
export interface NodeManagerEvents {
|
|
9
9
|
/**
|
|
10
10
|
* Emitted when a Node is created.
|
|
11
11
|
* @event Manager.nodeManager#create
|
|
@@ -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 {};
|
|
@@ -5,18 +5,20 @@ const BandCampSearch_1 = require("./CustomSearches/BandCampSearch");
|
|
|
5
5
|
const Filters_1 = require("./Filters");
|
|
6
6
|
const Queue_1 = require("./Queue");
|
|
7
7
|
const Utils_1 = require("./Utils");
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
8
|
+
var DestroyReasons;
|
|
9
|
+
(function (DestroyReasons) {
|
|
10
|
+
DestroyReasons["QueueEmpty"] = "QueueEmpty";
|
|
11
|
+
DestroyReasons["NodeDestroy"] = "NodeDestroy";
|
|
12
|
+
DestroyReasons["NodeDeleted"] = "NodeDeleted";
|
|
13
|
+
DestroyReasons["LavalinkNoVoice"] = "LavalinkNoVoice";
|
|
14
|
+
DestroyReasons["NodeReconnectFail"] = "NodeReconnectFail";
|
|
15
|
+
DestroyReasons["Disconnected"] = "Disconnected";
|
|
16
|
+
DestroyReasons["PlayerReconnectFail"] = "PlayerReconnectFail";
|
|
17
|
+
DestroyReasons["ChannelDeleted"] = "ChannelDeleted";
|
|
18
|
+
DestroyReasons["DisconnectAllNodes"] = "DisconnectAllNodes";
|
|
19
|
+
DestroyReasons["ReconnectAllNodes"] = "ReconnectAllNodes";
|
|
20
|
+
})(DestroyReasons || (exports.DestroyReasons = DestroyReasons = {}));
|
|
21
|
+
;
|
|
20
22
|
class Player {
|
|
21
23
|
/** The Guild Id of the Player */
|
|
22
24
|
guildId;
|
|
@@ -42,7 +44,11 @@ class Player {
|
|
|
42
44
|
/** The Volume Lavalink actually is outputting */
|
|
43
45
|
lavalinkVolume = 100;
|
|
44
46
|
/** The current Positin of the player (Calculated) */
|
|
45
|
-
position
|
|
47
|
+
get position() {
|
|
48
|
+
return this.lastPosition + (this.lastPositionChange ? Date.now() - this.lastPositionChange : 0);
|
|
49
|
+
}
|
|
50
|
+
/** The timestamp when the last position change update happened */
|
|
51
|
+
lastPositionChange = null;
|
|
46
52
|
/** The current Positin of the player (from Lavalink) */
|
|
47
53
|
lastPosition = 0;
|
|
48
54
|
/** When the player was created [Timestamp in Ms] (from lavalink) */
|
|
@@ -132,17 +138,17 @@ class Player {
|
|
|
132
138
|
if (options?.clientTrack && (this.LavalinkManager.utils.isTrack(options?.clientTrack) || this.LavalinkManager.utils.isUnresolvedTrack(options.clientTrack))) {
|
|
133
139
|
if (this.LavalinkManager.utils.isUnresolvedTrack(options.clientTrack))
|
|
134
140
|
await options.clientTrack.resolve(this);
|
|
135
|
-
if (typeof options.track.userData === "object")
|
|
136
|
-
options.clientTrack.userData = { ...(options?.clientTrack.userData || {}), ...(options.track
|
|
141
|
+
if ((typeof options.track?.userData === "object" || typeof options.clientTrack?.userData === "object") && options.clientTrack)
|
|
142
|
+
options.clientTrack.userData = { ...(options?.clientTrack.userData || {}), ...(options.track?.userData || {}) };
|
|
137
143
|
await this.queue.add(options?.clientTrack, 0);
|
|
138
144
|
return await this.skip();
|
|
139
145
|
}
|
|
140
146
|
else if (options?.track?.encoded) {
|
|
141
147
|
// handle play encoded options manually // TODO let it resolve by lavalink!
|
|
142
148
|
const track = await this.node.decode.singleTrack(options.track?.encoded, options.track?.requester || this.queue?.current?.requester || this.queue.previous?.[0]?.requester || this.queue.tracks?.[0]?.requester || this.LavalinkManager.options.client);
|
|
143
|
-
if (typeof options.track.userData === "object")
|
|
144
|
-
track.userData = { ...(track.userData || {}), ...(options.track.userData || {}) };
|
|
145
149
|
if (track) {
|
|
150
|
+
if (typeof options.track?.userData === "object")
|
|
151
|
+
track.userData = { ...(track.userData || {}), ...(options.track.userData || {}) };
|
|
146
152
|
replaced = true;
|
|
147
153
|
this.queue.add(track, 0);
|
|
148
154
|
await (0, Utils_1.queueTrackEnd)(this);
|
|
@@ -153,9 +159,9 @@ class Player {
|
|
|
153
159
|
const res = await this.search({
|
|
154
160
|
query: options?.track?.identifier
|
|
155
161
|
}, options?.track?.requester || this.queue?.current?.requester || this.queue.previous?.[0]?.requester || this.queue.tracks?.[0]?.requester || this.LavalinkManager.options.client);
|
|
156
|
-
if (typeof options.track.userData === "object")
|
|
157
|
-
res.tracks[0].userData = { ...(res.tracks[0].userData || {}), ...(options.track.userData || {}) };
|
|
158
162
|
if (res.tracks[0]) {
|
|
163
|
+
if (typeof options.track?.userData === "object")
|
|
164
|
+
res.tracks[0].userData = { ...(res.tracks[0].userData || {}), ...(options.track.userData || {}) };
|
|
159
165
|
replaced = true;
|
|
160
166
|
this.queue.add(res.tracks[0], 0);
|
|
161
167
|
await (0, Utils_1.queueTrackEnd)(this);
|
|
@@ -167,8 +173,8 @@ class Player {
|
|
|
167
173
|
try {
|
|
168
174
|
// resolve the unresolved track
|
|
169
175
|
await this.queue.current.resolve(this);
|
|
170
|
-
if (typeof options.track
|
|
171
|
-
this.queue.current.userData = { ...(this.queue.current
|
|
176
|
+
if (typeof options.track?.userData === "object" && this.queue.current)
|
|
177
|
+
this.queue.current.userData = { ...(this.queue.current?.userData || {}), ...(options.track?.userData || {}) };
|
|
172
178
|
}
|
|
173
179
|
catch (error) {
|
|
174
180
|
this.LavalinkManager.emit("trackError", this, this.queue.current, error);
|
|
@@ -245,8 +251,8 @@ class Player {
|
|
|
245
251
|
this.ping.lavalink = Math.round((performance.now() - now) / 10) / 100;
|
|
246
252
|
return this;
|
|
247
253
|
}
|
|
248
|
-
async lavaSearch(query, requestUser) {
|
|
249
|
-
return this.node.lavaSearch(query, requestUser);
|
|
254
|
+
async lavaSearch(query, requestUser, throwOnEmpty = false) {
|
|
255
|
+
return this.node.lavaSearch(query, requestUser, throwOnEmpty);
|
|
250
256
|
}
|
|
251
257
|
async setSponsorBlock(segments = ["sponsor", "selfpromo"]) {
|
|
252
258
|
return this.node.setSponsorBlock(this, segments);
|
|
@@ -262,11 +268,11 @@ class Player {
|
|
|
262
268
|
* @param query Query for your data
|
|
263
269
|
* @param requestUser
|
|
264
270
|
*/
|
|
265
|
-
async search(query, requestUser) {
|
|
271
|
+
async search(query, requestUser, throwOnEmpty = false) {
|
|
266
272
|
const Query = this.LavalinkManager.utils.transformQuery(query);
|
|
267
|
-
if (["bcsearch", "bandcamp"].includes(Query.source))
|
|
273
|
+
if (["bcsearch", "bandcamp"].includes(Query.source) && !this.node.info.sourceManagers.includes("bandcamp"))
|
|
268
274
|
return await (0, BandCampSearch_1.bandCampSearch)(this, Query.query, requestUser);
|
|
269
|
-
return this.node.search(Query, requestUser);
|
|
275
|
+
return this.node.search(Query, requestUser, throwOnEmpty);
|
|
270
276
|
}
|
|
271
277
|
/**
|
|
272
278
|
* Pause the player
|
|
@@ -306,7 +312,7 @@ class Player {
|
|
|
306
312
|
throw new RangeError("Current Track is not seekable / a stream");
|
|
307
313
|
if (position < 0 || position > this.queue.current.info.duration)
|
|
308
314
|
position = Math.max(Math.min(position, this.queue.current.info.duration), 0);
|
|
309
|
-
this.
|
|
315
|
+
this.lastPositionChange = Date.now();
|
|
310
316
|
this.lastPosition = position;
|
|
311
317
|
const now = performance.now();
|
|
312
318
|
await this.node.updatePlayer({ guildId: this.guildId, playerOptions: { position } });
|
|
@@ -488,6 +494,7 @@ class Player {
|
|
|
488
494
|
textChannelId: this.textChannelId,
|
|
489
495
|
position: this.position,
|
|
490
496
|
lastPosition: this.lastPosition,
|
|
497
|
+
lastPositionChange: this.lastPositionChange,
|
|
491
498
|
volume: this.volume,
|
|
492
499
|
lavalinkVolume: this.lavalinkVolume,
|
|
493
500
|
repeatMode: this.repeatMode,
|
|
@@ -498,6 +505,7 @@ class Player {
|
|
|
498
505
|
equalizer: this.filterManager?.equalizerBands || [],
|
|
499
506
|
nodeId: this.node?.id,
|
|
500
507
|
ping: this.ping,
|
|
508
|
+
queue: this.queue.utils.toJSON(),
|
|
501
509
|
};
|
|
502
510
|
}
|
|
503
511
|
}
|
|
@@ -81,7 +81,7 @@ class Queue {
|
|
|
81
81
|
sync: async (override = true, dontSyncCurrent = true) => {
|
|
82
82
|
const data = await this.QueueSaver.get(this.guildId);
|
|
83
83
|
if (!data)
|
|
84
|
-
|
|
84
|
+
throw new Error(`No data found to sync for guildId: ${this.guildId}`);
|
|
85
85
|
if (!dontSyncCurrent && !this.current && (this.managerUtils.isTrack(data.current)))
|
|
86
86
|
this.current = data.current;
|
|
87
87
|
if (Array.isArray(data.tracks) && data?.tracks.length && data.tracks.some(track => this.managerUtils.isTrack(track) || this.managerUtils.isUnresolvedTrack(track)))
|
|
@@ -14,10 +14,10 @@ export type IntegerNumber = Opaque<number, 'Int'>;
|
|
|
14
14
|
export type FloatNumber = Opaque<number, 'Float'>;
|
|
15
15
|
export type LavaSrcSearchPlatformBase = "spsearch" | "sprec" | "amsearch" | "dzsearch" | "dzisrc" | "ymsearch";
|
|
16
16
|
export type LavaSrcSearchPlatform = LavaSrcSearchPlatformBase | "ftts";
|
|
17
|
-
export type DuncteSearchPlatform = "speak" | "tts";
|
|
17
|
+
export type DuncteSearchPlatform = "speak" | "phsearch" | "pornhub" | "porn" | "tts";
|
|
18
18
|
export type LavalinkClientSearchPlatform = "bcsearch";
|
|
19
19
|
export type LavalinkClientSearchPlatformResolve = "bandcamp" | "bc";
|
|
20
|
-
export type LavalinkSearchPlatform = "ytsearch" | "ytmsearch" | "scsearch" | LavaSrcSearchPlatform | DuncteSearchPlatform | LavalinkClientSearchPlatform;
|
|
20
|
+
export type LavalinkSearchPlatform = "ytsearch" | "ytmsearch" | "scsearch" | "bcsearch" | LavaSrcSearchPlatform | DuncteSearchPlatform | LavalinkClientSearchPlatform;
|
|
21
21
|
export type ClientCustomSearchPlatformUtils = "local" | "http" | "https" | "link" | "uri";
|
|
22
22
|
export type ClientSearchPlatform = ClientCustomSearchPlatformUtils | // for file/link requests
|
|
23
23
|
"youtube" | "yt" | "youtube music" | "youtubemusic" | "ytm" | "musicyoutube" | "music youtube" | "soundcloud" | "sc" | "am" | "apple music" | "applemusic" | "apple" | "musicapple" | "music apple" | "sp" | "spsuggestion" | "spotify" | "spotify.com" | "spotifycom" | "dz" | "deezer" | "yandex" | "yandex music" | "yandexmusic" | "flowerytts" | "flowery" | "flowery.tts" | LavalinkClientSearchPlatformResolve | LavalinkClientSearchPlatform;
|
|
@@ -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;
|
|
@@ -50,7 +50,7 @@ class ManagerUtils {
|
|
|
50
50
|
identifier: data.info.identifier,
|
|
51
51
|
title: data.info.title,
|
|
52
52
|
author: data.info.author,
|
|
53
|
-
duration: data.info.
|
|
53
|
+
duration: data.info.duration || data.info.length,
|
|
54
54
|
artworkUrl: data.info.artworkUrl || data.pluginInfo?.artworkUrl || data.plugin?.artworkUrl,
|
|
55
55
|
uri: data.info.uri,
|
|
56
56
|
sourceName: data.info.sourceName,
|
|
@@ -206,7 +206,7 @@ class ManagerUtils {
|
|
|
206
206
|
throw new Error("Lavalink Node has not 'soundcloud' enabled");
|
|
207
207
|
}
|
|
208
208
|
if (LavalinkManagerStatics_1.SourceLinksRegexes.bandcamp.test(queryString) && !node.info?.sourceManagers?.includes("bandcamp")) {
|
|
209
|
-
throw new Error("Lavalink Node has not 'bandcamp' enabled");
|
|
209
|
+
throw new Error("Lavalink Node has not 'bandcamp' enabled (introduced with lavaplayer 2.2.0 or lavalink 4.0.6)");
|
|
210
210
|
}
|
|
211
211
|
if (LavalinkManagerStatics_1.SourceLinksRegexes.TwitchTv.test(queryString) && !node.info?.sourceManagers?.includes("twitch")) {
|
|
212
212
|
throw new Error("Lavalink Node has not 'twitch' enabled");
|
|
@@ -238,9 +238,11 @@ class ManagerUtils {
|
|
|
238
238
|
return;
|
|
239
239
|
}
|
|
240
240
|
transformQuery(query) {
|
|
241
|
+
const sourceOfQuery = typeof query === "string" ? undefined : (LavalinkManagerStatics_1.DefaultSources[(query.source?.trim?.()?.toLowerCase?.()) ?? this.LavalinkManager?.options?.playerOptions?.defaultSearchPlatform?.toLowerCase?.()] ?? (query.source?.trim?.()?.toLowerCase?.()));
|
|
241
242
|
const Query = {
|
|
242
243
|
query: typeof query === "string" ? query : query.query,
|
|
243
|
-
|
|
244
|
+
extraQueryUrlParams: typeof query !== "string" ? query.extraQueryUrlParams : undefined,
|
|
245
|
+
source: sourceOfQuery ?? this.LavalinkManager?.options?.playerOptions?.defaultSearchPlatform?.toLowerCase?.()
|
|
244
246
|
};
|
|
245
247
|
const foundSource = Object.keys(LavalinkManagerStatics_1.DefaultSources).find(source => Query.query?.toLowerCase?.()?.startsWith(`${source}:`.toLowerCase()))?.trim?.()?.toLowerCase?.();
|
|
246
248
|
// ignore links...
|
|
@@ -252,10 +254,11 @@ class ManagerUtils {
|
|
|
252
254
|
}
|
|
253
255
|
transformLavaSearchQuery(query) {
|
|
254
256
|
// transform the query object
|
|
257
|
+
const sourceOfQuery = typeof query === "string" ? undefined : (LavalinkManagerStatics_1.DefaultSources[(query.source?.trim?.()?.toLowerCase?.()) ?? this.LavalinkManager?.options?.playerOptions?.defaultSearchPlatform?.toLowerCase?.()] ?? (query.source?.trim?.()?.toLowerCase?.()));
|
|
255
258
|
const Query = {
|
|
256
259
|
query: typeof query === "string" ? query : query.query,
|
|
257
260
|
types: query.types ? ["track", "playlist", "artist", "album", "text"].filter(v => query.types?.find(x => x.toLowerCase().startsWith(v))) : ["track", "playlist", "artist", "album", /*"text"*/],
|
|
258
|
-
source:
|
|
261
|
+
source: sourceOfQuery ?? this.LavalinkManager?.options?.playerOptions?.defaultSearchPlatform?.toLowerCase?.()
|
|
259
262
|
};
|
|
260
263
|
const foundSource = Object.keys(LavalinkManagerStatics_1.DefaultSources).find(source => Query.query.toLowerCase().startsWith(`${source}:`.toLowerCase()))?.trim?.()?.toLowerCase?.();
|
|
261
264
|
if (foundSource && LavalinkManagerStatics_1.DefaultSources[foundSource]) {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { fetch } from "undici";
|
|
2
1
|
export const bandCampSearch = async (player, query, requestUser) => {
|
|
3
2
|
let error = null;
|
|
4
3
|
let tracks = [];
|
|
4
|
+
if (player.LavalinkManager.options.advancedOptions.debugOptions.logCustomSearches)
|
|
5
|
+
console.log(`Lavalink-Client-Debug | SEARCHING | - ${query} on lavalink-client`);
|
|
5
6
|
player.LavalinkManager.utils.validateQueryString(player.node, query);
|
|
6
7
|
try {
|
|
7
8
|
const data = await fetch(`https://bandcamp.com/api/nusearch/2/autocomplete?q=${encodeURIComponent(query)}`, {
|
|
@@ -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.) */
|
|
@@ -5,7 +5,7 @@ export class FilterManager {
|
|
|
5
5
|
/** The Equalizer bands currently applied to the Lavalink Server */
|
|
6
6
|
equalizerBands = [];
|
|
7
7
|
/** Private Util for the instaFix Filters option */
|
|
8
|
-
filterUpdatedState =
|
|
8
|
+
filterUpdatedState = false;
|
|
9
9
|
/** All "Active" / "disabled" Player Filters */
|
|
10
10
|
filters = {
|
|
11
11
|
volume: false,
|
|
@@ -157,6 +157,8 @@ export class FilterManager {
|
|
|
157
157
|
delete sendData[key];
|
|
158
158
|
}
|
|
159
159
|
const now = performance.now();
|
|
160
|
+
if (this.player.options.instaUpdateFiltersFix === true)
|
|
161
|
+
this.filterUpdatedState = true;
|
|
160
162
|
await this.player.node.updatePlayer({
|
|
161
163
|
guildId: this.player.guildId,
|
|
162
164
|
playerOptions: {
|
|
@@ -164,8 +166,6 @@ export class FilterManager {
|
|
|
164
166
|
}
|
|
165
167
|
});
|
|
166
168
|
this.player.ping.lavalink = Math.round((performance.now() - now) / 10) / 100;
|
|
167
|
-
if (this.player.options.instaUpdateFiltersFix === true)
|
|
168
|
-
this.filterUpdatedState = 1;
|
|
169
169
|
return;
|
|
170
170
|
}
|
|
171
171
|
/**
|
|
@@ -651,6 +651,8 @@ export class FilterManager {
|
|
|
651
651
|
if (!this.player.node.sessionId)
|
|
652
652
|
throw new Error("The Lavalink-Node is either not ready or not up to date");
|
|
653
653
|
const now = performance.now();
|
|
654
|
+
if (this.player.options.instaUpdateFiltersFix === true)
|
|
655
|
+
this.filterUpdatedState = true;
|
|
654
656
|
await this.player.node.updatePlayer({
|
|
655
657
|
guildId: this.player.guildId,
|
|
656
658
|
playerOptions: {
|
|
@@ -658,8 +660,6 @@ export class FilterManager {
|
|
|
658
660
|
}
|
|
659
661
|
});
|
|
660
662
|
this.player.ping.lavalink = Math.round((performance.now() - now) / 10) / 100;
|
|
661
|
-
if (this.player.options.instaUpdateFiltersFix === true)
|
|
662
|
-
this.filterUpdatedState = 1;
|
|
663
663
|
return this;
|
|
664
664
|
}
|
|
665
665
|
/** Clears the equalizer bands. */
|
|
@@ -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,8 +67,12 @@ 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?: {
|
|
74
|
+
/** For logging custom searches */
|
|
75
|
+
logCustomSearches?: boolean;
|
|
69
76
|
/** logs for debugging the "no-Audio" playing error */
|
|
70
77
|
noAudio?: boolean;
|
|
71
78
|
/** For Logging the Destroy function */
|
|
@@ -78,7 +85,7 @@ export interface ManagerOptions {
|
|
|
78
85
|
};
|
|
79
86
|
};
|
|
80
87
|
}
|
|
81
|
-
interface LavalinkManagerEvents {
|
|
88
|
+
export interface LavalinkManagerEvents {
|
|
82
89
|
/**
|
|
83
90
|
* Emitted when a Track started playing.
|
|
84
91
|
* @event Manager#trackStart
|
|
@@ -93,12 +100,12 @@ interface LavalinkManagerEvents {
|
|
|
93
100
|
* Emitted when a Track got stuck while playing.
|
|
94
101
|
* @event Manager#trackStuck
|
|
95
102
|
*/
|
|
96
|
-
"trackStuck": (player: Player, track: Track, payload: TrackStuckEvent) => void;
|
|
103
|
+
"trackStuck": (player: Player, track: Track | null, payload: TrackStuckEvent) => void;
|
|
97
104
|
/**
|
|
98
105
|
* Emitted when a Track errored.
|
|
99
106
|
* @event Manager#trackError
|
|
100
107
|
*/
|
|
101
|
-
"trackError": (player: Player, track: Track | UnresolvedTrack, payload: TrackExceptionEvent) => void;
|
|
108
|
+
"trackError": (player: Player, track: Track | UnresolvedTrack | null, payload: TrackExceptionEvent) => void;
|
|
102
109
|
/**
|
|
103
110
|
* Emitted when the Playing finished and no more tracks in the queue.
|
|
104
111
|
* @event Manager#queueEnd
|
|
@@ -237,6 +244,7 @@ export declare class LavalinkManager extends EventEmitter {
|
|
|
237
244
|
* linksBlacklist: [],
|
|
238
245
|
* linksWhitelist: [],
|
|
239
246
|
* advancedOptions: {
|
|
247
|
+
* maxFilterFixDuration: 600_000,
|
|
240
248
|
* debugOptions: {
|
|
241
249
|
* noAudio: false,
|
|
242
250
|
* playerDestroy: {
|
|
@@ -307,10 +315,22 @@ export declare class LavalinkManager extends EventEmitter {
|
|
|
307
315
|
* Delete's a player from the cache without destroying it on lavalink (only works when it's disconnected)
|
|
308
316
|
* @param guildId
|
|
309
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
|
+
* ```
|
|
310
324
|
*/
|
|
311
325
|
deletePlayer(guildId: string): boolean;
|
|
312
326
|
/**
|
|
313
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
|
+
* ```
|
|
314
334
|
*/
|
|
315
335
|
get useable(): boolean;
|
|
316
336
|
/**
|
|
@@ -318,7 +338,6 @@ export declare class LavalinkManager extends EventEmitter {
|
|
|
318
338
|
* @param clientData
|
|
319
339
|
*
|
|
320
340
|
* @example
|
|
321
|
-
*
|
|
322
341
|
* ```ts
|
|
323
342
|
* // on the bot ready event
|
|
324
343
|
* client.on("ready", () => {
|
|
@@ -347,4 +366,3 @@ export declare class LavalinkManager extends EventEmitter {
|
|
|
347
366
|
*/
|
|
348
367
|
sendRawData(data: VoicePacket | VoiceServer | VoiceState | ChannelDeletePacket): Promise<void>;
|
|
349
368
|
}
|
|
350
|
-
export {};
|
|
@@ -55,7 +55,9 @@ export class LavalinkManager extends EventEmitter {
|
|
|
55
55
|
queueStore: options?.queueOptions?.queueStore ?? new DefaultQueueStore(),
|
|
56
56
|
},
|
|
57
57
|
advancedOptions: {
|
|
58
|
+
maxFilterFixDuration: options?.advancedOptions?.maxFilterFixDuration ?? 600000,
|
|
58
59
|
debugOptions: {
|
|
60
|
+
logCustomSearches: options?.advancedOptions?.debugOptions?.logCustomSearches ?? false,
|
|
59
61
|
noAudio: options?.advancedOptions?.debugOptions?.noAudio ?? false,
|
|
60
62
|
playerDestroy: {
|
|
61
63
|
dontThrowError: options?.advancedOptions?.debugOptions?.playerDestroy?.dontThrowError ?? false,
|
|
@@ -146,6 +148,7 @@ export class LavalinkManager extends EventEmitter {
|
|
|
146
148
|
* linksBlacklist: [],
|
|
147
149
|
* linksWhitelist: [],
|
|
148
150
|
* advancedOptions: {
|
|
151
|
+
* maxFilterFixDuration: 600_000,
|
|
149
152
|
* debugOptions: {
|
|
150
153
|
* noAudio: false,
|
|
151
154
|
* playerDestroy: {
|
|
@@ -240,6 +243,12 @@ export class LavalinkManager extends EventEmitter {
|
|
|
240
243
|
* Delete's a player from the cache without destroying it on lavalink (only works when it's disconnected)
|
|
241
244
|
* @param guildId
|
|
242
245
|
* @returns
|
|
246
|
+
*
|
|
247
|
+
* @example
|
|
248
|
+
* ```ts
|
|
249
|
+
* client.lavalink.deletePlayer(interaction.guildId);
|
|
250
|
+
* // shouldn't be used except you know what you are doing.
|
|
251
|
+
* ```
|
|
243
252
|
*/
|
|
244
253
|
deletePlayer(guildId) {
|
|
245
254
|
const oldPlayer = this.getPlayer(guildId);
|
|
@@ -256,6 +265,12 @@ export class LavalinkManager extends EventEmitter {
|
|
|
256
265
|
}
|
|
257
266
|
/**
|
|
258
267
|
* Checks wether the the lib is useable based on if any node is connected
|
|
268
|
+
*
|
|
269
|
+
* @example
|
|
270
|
+
* ```ts
|
|
271
|
+
* if(!client.lavalink.useable) return console.error("can'T search yet, because there is no useable lavalink node.")
|
|
272
|
+
* // continue with code e.g. createing a player and searching
|
|
273
|
+
* ```
|
|
259
274
|
*/
|
|
260
275
|
get useable() {
|
|
261
276
|
return this.nodeManager.nodes.filter(v => v.connected).size > 0;
|
|
@@ -265,7 +280,6 @@ export class LavalinkManager extends EventEmitter {
|
|
|
265
280
|
* @param clientData
|
|
266
281
|
*
|
|
267
282
|
* @example
|
|
268
|
-
*
|
|
269
283
|
* ```ts
|
|
270
284
|
* // on the bot ready event
|
|
271
285
|
* 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>;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/** Default Sources Record, to allow source parsing with multiple inputs. */
|
|
1
2
|
export const DefaultSources = {
|
|
2
3
|
// youtubemusic
|
|
3
4
|
"youtube music": "ytmsearch",
|
|
@@ -47,10 +48,14 @@ export const DefaultSources = {
|
|
|
47
48
|
"flowery": "ftts",
|
|
48
49
|
"flowery.tts": "ftts",
|
|
49
50
|
"flowerytts": "ftts",
|
|
50
|
-
// Client sided search platforms
|
|
51
|
+
// Client sided search platforms (after lavalinkv4.0.6 it will search via bcsearch on the node itself)
|
|
51
52
|
"bandcamp": "bcsearch",
|
|
52
53
|
"bc": "bcsearch",
|
|
53
54
|
"bcsearch": "bcsearch",
|
|
55
|
+
// other searches:
|
|
56
|
+
"phsearch": "phsearch",
|
|
57
|
+
"pornhub": "phsearch",
|
|
58
|
+
"porn": "phsearch",
|
|
54
59
|
// local files
|
|
55
60
|
"local": "local",
|
|
56
61
|
// http requests
|
|
@@ -59,6 +64,7 @@ export const DefaultSources = {
|
|
|
59
64
|
"link": "link",
|
|
60
65
|
"uri": "uri"
|
|
61
66
|
};
|
|
67
|
+
/** Lavalink Plugins definiton */
|
|
62
68
|
export const LavalinkPlugins = {
|
|
63
69
|
DuncteBot_Plugin: "DuncteBot-plugin",
|
|
64
70
|
LavaSrc: "lavasrc-plugin",
|
|
@@ -66,6 +72,7 @@ export const LavalinkPlugins = {
|
|
|
66
72
|
LavaSearch: "lavasearch-plugin",
|
|
67
73
|
LavalinkFilterPlugin: "lavalink-filter-plugin"
|
|
68
74
|
};
|
|
75
|
+
/** Lavalink Sources regexes for url validations */
|
|
69
76
|
export const SourceLinksRegexes = {
|
|
70
77
|
/** DEFAULT SUPPORTED BY LAVALINK */
|
|
71
78
|
YoutubeRegex: /https?:\/\/?(?:www\.)?(?:(m|www)\.)?(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|shorts|playlist\?|watch\?v=|watch\?.+(?:&|&);v=))([a-zA-Z0-9\-_]{11})?(?:(?:\?|&|&)index=((?:\d){1,3}))?(?:(?:\?|&|&)?list=([a-zA-Z\-_0-9]{34}))?(?:\S+)?/,
|