lavalink-client 1.2.0 → 1.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 +14 -1
- package/dist/cjs/structures/Node.d.ts +5 -5
- package/dist/cjs/structures/Node.js +50 -40
- package/dist/cjs/structures/Player.d.ts +1 -1
- package/dist/cjs/structures/Player.js +8 -2
- package/dist/cjs/structures/Utils.d.ts +11 -0
- package/dist/cjs/structures/Utils.js +20 -2
- package/dist/esm/structures/Node.d.ts +5 -5
- package/dist/esm/structures/Node.js +50 -40
- package/dist/esm/structures/Player.d.ts +1 -1
- package/dist/esm/structures/Player.js +8 -2
- package/dist/esm/structures/Utils.d.ts +11 -0
- package/dist/esm/structures/Utils.js +18 -1
- package/dist/types/structures/Node.d.ts +5 -5
- package/dist/types/structures/Player.d.ts +1 -1
- package/dist/types/structures/Utils.d.ts +11 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -111,9 +111,22 @@ Check out the [Documentation](https://lc4.gitbook.io/lavalink-client) for **Exam
|
|
|
111
111
|
- `player.deleteSponsorBlock()` / `node.deleteSponsorBlock()`
|
|
112
112
|
- That Plugin adds following **Events** to the **Manager**: `"SegmentsLoaded"`, `"SegmentSkipped"`, `"ChapterStarted"`, `"ChaptersLoaded"`
|
|
113
113
|
- Example Bot show example in autoplayFunction how to "disable" / "enable" Autoplay with bot data variables.
|
|
114
|
-
- Added `ManagerOptions#
|
|
114
|
+
- Added `ManagerOptions#emitNewSongsOnly`. If set to true, it won't emit "trackStart" Event, when track.loop is active, or the new current track == the previous (current) track.
|
|
115
115
|
- Added `ManagerOptions#linksBlacklist` which allows user to specify an array of regExp / strings to match query strings (for links / words) and if a match happens it doesn't allow the request (blacklist)
|
|
116
116
|
- Added `ManagerOptions#linksWhitelist` which allows user to specify an array of regExp / strings to match query strings (for links only) and if a match does NOT HAPPEN it doesn't allow the request (whitelist)
|
|
117
117
|
- Added `ManagerOptions#linksAllowed` if set to false, it does not allow requests which are links
|
|
118
118
|
- Moved `ManaagerOptions#debugOptions` to `ManaagerOptions#advancedOptions.debugOptions`
|
|
119
119
|
|
|
120
|
+
### **Version 1.2.1**
|
|
121
|
+
- Adjusted `player.stopPlaying()`
|
|
122
|
+
- There are now following parameters. `stopPlaying(clearQueue:boolean = true, executeAutoplay:boolean = false)`.
|
|
123
|
+
- On Default it now clears the queue and stops playing. Also it does not execute Autoplay on default. IF you want the function to behave differently, you can use the 2 states for that.
|
|
124
|
+
- Fixed that it looped the current track if repeatmode === "track" / "queue". (it stops playing and loop stays)
|
|
125
|
+
- Implemented a `parseLavalinkConnUrl(connectionUrl:string)` Util Function.
|
|
126
|
+
- It allows you to parse Lavalink Connection Data of a Lavalink Connection Url.
|
|
127
|
+
Pattern: `lavalink://<nodeId>:<nodeAuthorization(Password)>@<NodeHost>:<NodePort>`
|
|
128
|
+
- Note that the nodeId and NodeAuthorization must be encoded via encodeURIComponents before you provide it into the function.
|
|
129
|
+
- The function will return the following: `{ id: string, authorization: string, host: string, port: number }`
|
|
130
|
+
- Example: `parseLavalinkConnUrl("lavalink://LavalinkNode_1:strong%23password1@localhost:2345")` will give you:
|
|
131
|
+
`{ id: "LavalinkNode_1", authorization: "strong#password1", host: "localhost", port: 2345 }`
|
|
132
|
+
- Note that the password "strong#password1" when encoded turns into "strong%23password1". For more information check the example bot
|
|
@@ -240,17 +240,17 @@ export declare class LavalinkNode {
|
|
|
240
240
|
private error;
|
|
241
241
|
private message;
|
|
242
242
|
private handleEvent;
|
|
243
|
+
private trackStart;
|
|
244
|
+
private trackEnd;
|
|
245
|
+
private trackStuck;
|
|
246
|
+
private trackError;
|
|
247
|
+
private socketClosed;
|
|
243
248
|
private SponsorBlockSegmentLoaded;
|
|
244
249
|
private SponsorBlockSegmentkipped;
|
|
245
250
|
private SponsorBlockChaptersLoaded;
|
|
246
251
|
private SponsorBlockChapterStarted;
|
|
247
|
-
private trackStart;
|
|
248
|
-
private trackEnd;
|
|
249
252
|
getSponsorBlock(player: Player): Promise<SponsorBlockSegment[]>;
|
|
250
253
|
setSponsorBlock(player: Player, segments?: SponsorBlockSegment[]): Promise<void>;
|
|
251
254
|
deleteSponsorBlock(player: Player): Promise<void>;
|
|
252
255
|
private queueEnd;
|
|
253
|
-
private trackStuck;
|
|
254
|
-
private trackError;
|
|
255
|
-
private socketClosed;
|
|
256
256
|
}
|
|
@@ -566,6 +566,7 @@ class LavalinkNode {
|
|
|
566
566
|
return;
|
|
567
567
|
}
|
|
568
568
|
}
|
|
569
|
+
// LAVALINK EVENT HANDLING UTIL FUNCTION
|
|
569
570
|
async handleEvent(payload) {
|
|
570
571
|
if (!payload.guildId)
|
|
571
572
|
return;
|
|
@@ -606,18 +607,7 @@ class LavalinkNode {
|
|
|
606
607
|
}
|
|
607
608
|
return;
|
|
608
609
|
}
|
|
609
|
-
|
|
610
|
-
return this.NodeManager.LavalinkManager.emit("SegmentsLoaded", player, track, payload);
|
|
611
|
-
}
|
|
612
|
-
SponsorBlockSegmentkipped(player, track, payload) {
|
|
613
|
-
return this.NodeManager.LavalinkManager.emit("SegmentSkipped", player, track, payload);
|
|
614
|
-
}
|
|
615
|
-
SponsorBlockChaptersLoaded(player, track, payload) {
|
|
616
|
-
return this.NodeManager.LavalinkManager.emit("ChaptersLoaded", player, track, payload);
|
|
617
|
-
}
|
|
618
|
-
SponsorBlockChapterStarted(player, track, payload) {
|
|
619
|
-
return this.NodeManager.LavalinkManager.emit("ChapterStarted", player, track, payload);
|
|
620
|
-
}
|
|
610
|
+
// LAVALINK EVENT HANDLING FUNCTIONS
|
|
621
611
|
trackStart(player, track, payload) {
|
|
622
612
|
player.playing = true;
|
|
623
613
|
player.paused = false;
|
|
@@ -628,7 +618,7 @@ class LavalinkNode {
|
|
|
628
618
|
}
|
|
629
619
|
async trackEnd(player, track, payload) {
|
|
630
620
|
// If there are no songs in the queue
|
|
631
|
-
if (!player.queue.tracks.length && player.repeatMode === "off")
|
|
621
|
+
if (!player.queue.tracks.length && (player.repeatMode === "off" || player.get("internal_stopPlaying")))
|
|
632
622
|
return this.queueEnd(player, track, payload);
|
|
633
623
|
// If a track was forcibly played
|
|
634
624
|
if (payload.reason === "replaced")
|
|
@@ -661,6 +651,49 @@ class LavalinkNode {
|
|
|
661
651
|
// play track if autoSkip is true
|
|
662
652
|
return this.NodeManager.LavalinkManager.options.autoSkip && player.play({ noReplace: true });
|
|
663
653
|
}
|
|
654
|
+
async trackStuck(player, track, payload) {
|
|
655
|
+
this.NodeManager.LavalinkManager.emit("trackStuck", player, track, payload);
|
|
656
|
+
// If there are no songs in the queue
|
|
657
|
+
if (!player.queue.tracks.length && (player.repeatMode === "off" || player.get("internal_stopPlaying")))
|
|
658
|
+
return this.queueEnd(player, track, payload);
|
|
659
|
+
// remove the current track, and enqueue the next one
|
|
660
|
+
await (0, Utils_1.queueTrackEnd)(player);
|
|
661
|
+
// if no track available, end queue
|
|
662
|
+
if (!player.queue.current)
|
|
663
|
+
return this.queueEnd(player, track, payload);
|
|
664
|
+
// play track if autoSkip is true
|
|
665
|
+
return (this.NodeManager.LavalinkManager.options.autoSkip && player.queue.current) && player.play({ noReplace: true });
|
|
666
|
+
}
|
|
667
|
+
async trackError(player, track, payload) {
|
|
668
|
+
this.NodeManager.LavalinkManager.emit("trackError", player, track, payload);
|
|
669
|
+
// If there are no songs in the queue
|
|
670
|
+
if (!player.queue.tracks.length && (player.repeatMode === "off" || player.get("internal_stopPlaying")))
|
|
671
|
+
return this.queueEnd(player, track, payload);
|
|
672
|
+
// remove the current track, and enqueue the next one
|
|
673
|
+
await (0, Utils_1.queueTrackEnd)(player);
|
|
674
|
+
// if no track available, end queue
|
|
675
|
+
if (!player.queue.current)
|
|
676
|
+
return this.queueEnd(player, track, payload);
|
|
677
|
+
// play track if autoSkip is true
|
|
678
|
+
return (this.NodeManager.LavalinkManager.options.autoSkip && player.queue.current) && player.play({ noReplace: true });
|
|
679
|
+
}
|
|
680
|
+
socketClosed(player, payload) {
|
|
681
|
+
return this.NodeManager.LavalinkManager.emit("playerSocketClosed", player, payload);
|
|
682
|
+
}
|
|
683
|
+
// SPONSOR BLOCK EVENT FUNCTIONS
|
|
684
|
+
SponsorBlockSegmentLoaded(player, track, payload) {
|
|
685
|
+
return this.NodeManager.LavalinkManager.emit("SegmentsLoaded", player, track, payload);
|
|
686
|
+
}
|
|
687
|
+
SponsorBlockSegmentkipped(player, track, payload) {
|
|
688
|
+
return this.NodeManager.LavalinkManager.emit("SegmentSkipped", player, track, payload);
|
|
689
|
+
}
|
|
690
|
+
SponsorBlockChaptersLoaded(player, track, payload) {
|
|
691
|
+
return this.NodeManager.LavalinkManager.emit("ChaptersLoaded", player, track, payload);
|
|
692
|
+
}
|
|
693
|
+
SponsorBlockChapterStarted(player, track, payload) {
|
|
694
|
+
return this.NodeManager.LavalinkManager.emit("ChapterStarted", player, track, payload);
|
|
695
|
+
}
|
|
696
|
+
// SPONSOR BLOCK EXECUTE FUNCTIONS
|
|
664
697
|
async getSponsorBlock(player) {
|
|
665
698
|
// no plugin enabled
|
|
666
699
|
if (!this.info.plugins.find(v => v.name === "sponsorblock-plugin"))
|
|
@@ -697,11 +730,13 @@ class LavalinkNode {
|
|
|
697
730
|
});
|
|
698
731
|
return;
|
|
699
732
|
}
|
|
733
|
+
// UTIL FOR QUEUE END
|
|
700
734
|
async queueEnd(player, track, payload) {
|
|
701
735
|
// add previous track to the queue!
|
|
702
736
|
player.queue.current = null;
|
|
703
737
|
player.playing = false;
|
|
704
|
-
|
|
738
|
+
player.set("internal_stopPlaying", undefined);
|
|
739
|
+
if (typeof this.NodeManager.LavalinkManager.options?.playerOptions?.onEmptyQueue?.autoPlayFunction === "function" && typeof player.get("internal_autoplayStopPlaying") === "undefined") {
|
|
705
740
|
await this.NodeManager.LavalinkManager.options?.playerOptions?.onEmptyQueue?.autoPlayFunction(player, track);
|
|
706
741
|
if (player.queue.tracks.length > 0)
|
|
707
742
|
await (0, Utils_1.queueTrackEnd)(player);
|
|
@@ -711,6 +746,7 @@ class LavalinkNode {
|
|
|
711
746
|
return player.play({ noReplace: true, paused: false });
|
|
712
747
|
}
|
|
713
748
|
}
|
|
749
|
+
player.set("internal_autoplayStopPlaying", undefined);
|
|
714
750
|
player.queue.previous.unshift(track);
|
|
715
751
|
if (payload?.reason !== "stopped") {
|
|
716
752
|
await player.queue.utils.save();
|
|
@@ -730,31 +766,5 @@ class LavalinkNode {
|
|
|
730
766
|
}
|
|
731
767
|
return this.NodeManager.LavalinkManager.emit("queueEnd", player, track, payload);
|
|
732
768
|
}
|
|
733
|
-
async trackStuck(player, track, payload) {
|
|
734
|
-
this.NodeManager.LavalinkManager.emit("trackStuck", player, track, payload);
|
|
735
|
-
// If there are no songs in the queue
|
|
736
|
-
if (!player.queue.tracks.length && player.repeatMode === "off")
|
|
737
|
-
return;
|
|
738
|
-
// remove the current track, and enqueue the next one
|
|
739
|
-
await (0, Utils_1.queueTrackEnd)(player);
|
|
740
|
-
// if no track available, end queue
|
|
741
|
-
if (!player.queue.current)
|
|
742
|
-
return this.queueEnd(player, track, payload);
|
|
743
|
-
// play track if autoSkip is true
|
|
744
|
-
return (this.NodeManager.LavalinkManager.options.autoSkip && player.queue.current) && player.play({ noReplace: true });
|
|
745
|
-
}
|
|
746
|
-
async trackError(player, track, payload) {
|
|
747
|
-
this.NodeManager.LavalinkManager.emit("trackError", player, track, payload);
|
|
748
|
-
// remove the current track, and enqueue the next one
|
|
749
|
-
await (0, Utils_1.queueTrackEnd)(player);
|
|
750
|
-
// if no track available, end queue
|
|
751
|
-
if (!player.queue.current)
|
|
752
|
-
return this.queueEnd(player, track, payload);
|
|
753
|
-
// play track if autoSkip is true
|
|
754
|
-
return (this.NodeManager.LavalinkManager.options.autoSkip && player.queue.current) && player.play({ noReplace: true });
|
|
755
|
-
}
|
|
756
|
-
socketClosed(player, payload) {
|
|
757
|
-
return this.NodeManager.LavalinkManager.emit("playerSocketClosed", player, payload);
|
|
758
|
-
}
|
|
759
769
|
}
|
|
760
770
|
exports.LavalinkNode = LavalinkNode;
|
|
@@ -185,7 +185,7 @@ export declare class Player {
|
|
|
185
185
|
* Clears the queue and stops playing. Does not destroy the Player and not leave the channel
|
|
186
186
|
* @returns
|
|
187
187
|
*/
|
|
188
|
-
stopPlaying(): Promise<this>;
|
|
188
|
+
stopPlaying(clearQueue?: boolean, executeAutoplay?: boolean): Promise<this>;
|
|
189
189
|
/**
|
|
190
190
|
* Connects the Player to the Voice Channel
|
|
191
191
|
* @returns
|
|
@@ -313,10 +313,16 @@ class Player {
|
|
|
313
313
|
* Clears the queue and stops playing. Does not destroy the Player and not leave the channel
|
|
314
314
|
* @returns
|
|
315
315
|
*/
|
|
316
|
-
async stopPlaying() {
|
|
316
|
+
async stopPlaying(clearQueue = true, executeAutoplay = false) {
|
|
317
|
+
// use internal_stopPlaying on true, so that it doesn't utilize current loop states. on trackEnd event
|
|
318
|
+
this.set("internal_stopPlaying", true);
|
|
317
319
|
// remove tracks from the queue
|
|
318
|
-
if (this.queue.tracks.length)
|
|
320
|
+
if (this.queue.tracks.length && clearQueue === true)
|
|
319
321
|
await this.queue.splice(0, this.queue.tracks.length);
|
|
322
|
+
if (executeAutoplay === false)
|
|
323
|
+
this.set("internal_autoplayStopPlaying", true);
|
|
324
|
+
else
|
|
325
|
+
this.set("internal_autoplayStopPlaying", undefined);
|
|
320
326
|
const now = performance.now();
|
|
321
327
|
// send to lavalink, that it should stop playing
|
|
322
328
|
await this.node.updatePlayer({ guildId: this.guildId, playerOptions: { encodedTrack: null } });
|
|
@@ -51,6 +51,17 @@ export interface UnresolvedSearchResult {
|
|
|
51
51
|
playlist: PlaylistInfo | null;
|
|
52
52
|
tracks: UnresolvedTrack[];
|
|
53
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* Parses Node Connection Url: "lavalink://<nodeId>:<nodeAuthorization(Password)>@<NodeHost>:<NodePort>"
|
|
56
|
+
* @param connectionUrl
|
|
57
|
+
* @returns
|
|
58
|
+
*/
|
|
59
|
+
export declare function parseLavalinkConnUrl(connectionUrl: string): {
|
|
60
|
+
authorization: string;
|
|
61
|
+
id: string;
|
|
62
|
+
host: string;
|
|
63
|
+
port: number;
|
|
64
|
+
};
|
|
54
65
|
export declare class ManagerUtils {
|
|
55
66
|
LavalinkManager: LavalinkManager | null;
|
|
56
67
|
constructor(LavalinkManager?: LavalinkManager);
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.queueTrackEnd = exports.MiniMap = exports.ManagerUtils = exports.NodeSymbol = exports.QueueSymbol = exports.UnresolvedTrackSymbol = exports.TrackSymbol = void 0;
|
|
4
|
-
const
|
|
3
|
+
exports.queueTrackEnd = exports.MiniMap = exports.ManagerUtils = exports.parseLavalinkConnUrl = exports.NodeSymbol = exports.QueueSymbol = exports.UnresolvedTrackSymbol = exports.TrackSymbol = void 0;
|
|
4
|
+
const node_url_1 = require("node:url");
|
|
5
|
+
const types_1 = require("node:util/types");
|
|
5
6
|
const LavalinkManagerStatics_1 = require("./LavalinkManagerStatics");
|
|
6
7
|
exports.TrackSymbol = Symbol("LC-Track");
|
|
7
8
|
exports.UnresolvedTrackSymbol = Symbol("LC-Track-Unresolved");
|
|
@@ -9,6 +10,23 @@ exports.QueueSymbol = Symbol("LC-Queue");
|
|
|
9
10
|
exports.NodeSymbol = Symbol("LC-Node");
|
|
10
11
|
/** @hidden */
|
|
11
12
|
const escapeRegExp = (str) => str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
13
|
+
/**
|
|
14
|
+
* Parses Node Connection Url: "lavalink://<nodeId>:<nodeAuthorization(Password)>@<NodeHost>:<NodePort>"
|
|
15
|
+
* @param connectionUrl
|
|
16
|
+
* @returns
|
|
17
|
+
*/
|
|
18
|
+
function parseLavalinkConnUrl(connectionUrl) {
|
|
19
|
+
if (!connectionUrl.startsWith("lavalink://"))
|
|
20
|
+
throw new Error(`ConnectionUrl (${connectionUrl}) must start with 'lavalink://'`);
|
|
21
|
+
const parsed = new node_url_1.URL(connectionUrl);
|
|
22
|
+
return {
|
|
23
|
+
authorization: parsed.password,
|
|
24
|
+
id: parsed.username,
|
|
25
|
+
host: parsed.hostname,
|
|
26
|
+
port: Number(parsed.port),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
exports.parseLavalinkConnUrl = parseLavalinkConnUrl;
|
|
12
30
|
class ManagerUtils {
|
|
13
31
|
LavalinkManager = null;
|
|
14
32
|
constructor(LavalinkManager) {
|
|
@@ -240,17 +240,17 @@ export declare class LavalinkNode {
|
|
|
240
240
|
private error;
|
|
241
241
|
private message;
|
|
242
242
|
private handleEvent;
|
|
243
|
+
private trackStart;
|
|
244
|
+
private trackEnd;
|
|
245
|
+
private trackStuck;
|
|
246
|
+
private trackError;
|
|
247
|
+
private socketClosed;
|
|
243
248
|
private SponsorBlockSegmentLoaded;
|
|
244
249
|
private SponsorBlockSegmentkipped;
|
|
245
250
|
private SponsorBlockChaptersLoaded;
|
|
246
251
|
private SponsorBlockChapterStarted;
|
|
247
|
-
private trackStart;
|
|
248
|
-
private trackEnd;
|
|
249
252
|
getSponsorBlock(player: Player): Promise<SponsorBlockSegment[]>;
|
|
250
253
|
setSponsorBlock(player: Player, segments?: SponsorBlockSegment[]): Promise<void>;
|
|
251
254
|
deleteSponsorBlock(player: Player): Promise<void>;
|
|
252
255
|
private queueEnd;
|
|
253
|
-
private trackStuck;
|
|
254
|
-
private trackError;
|
|
255
|
-
private socketClosed;
|
|
256
256
|
}
|
|
@@ -562,6 +562,7 @@ export class LavalinkNode {
|
|
|
562
562
|
return;
|
|
563
563
|
}
|
|
564
564
|
}
|
|
565
|
+
// LAVALINK EVENT HANDLING UTIL FUNCTION
|
|
565
566
|
async handleEvent(payload) {
|
|
566
567
|
if (!payload.guildId)
|
|
567
568
|
return;
|
|
@@ -602,18 +603,7 @@ export class LavalinkNode {
|
|
|
602
603
|
}
|
|
603
604
|
return;
|
|
604
605
|
}
|
|
605
|
-
|
|
606
|
-
return this.NodeManager.LavalinkManager.emit("SegmentsLoaded", player, track, payload);
|
|
607
|
-
}
|
|
608
|
-
SponsorBlockSegmentkipped(player, track, payload) {
|
|
609
|
-
return this.NodeManager.LavalinkManager.emit("SegmentSkipped", player, track, payload);
|
|
610
|
-
}
|
|
611
|
-
SponsorBlockChaptersLoaded(player, track, payload) {
|
|
612
|
-
return this.NodeManager.LavalinkManager.emit("ChaptersLoaded", player, track, payload);
|
|
613
|
-
}
|
|
614
|
-
SponsorBlockChapterStarted(player, track, payload) {
|
|
615
|
-
return this.NodeManager.LavalinkManager.emit("ChapterStarted", player, track, payload);
|
|
616
|
-
}
|
|
606
|
+
// LAVALINK EVENT HANDLING FUNCTIONS
|
|
617
607
|
trackStart(player, track, payload) {
|
|
618
608
|
player.playing = true;
|
|
619
609
|
player.paused = false;
|
|
@@ -624,7 +614,7 @@ export class LavalinkNode {
|
|
|
624
614
|
}
|
|
625
615
|
async trackEnd(player, track, payload) {
|
|
626
616
|
// If there are no songs in the queue
|
|
627
|
-
if (!player.queue.tracks.length && player.repeatMode === "off")
|
|
617
|
+
if (!player.queue.tracks.length && (player.repeatMode === "off" || player.get("internal_stopPlaying")))
|
|
628
618
|
return this.queueEnd(player, track, payload);
|
|
629
619
|
// If a track was forcibly played
|
|
630
620
|
if (payload.reason === "replaced")
|
|
@@ -657,6 +647,49 @@ export class LavalinkNode {
|
|
|
657
647
|
// play track if autoSkip is true
|
|
658
648
|
return this.NodeManager.LavalinkManager.options.autoSkip && player.play({ noReplace: true });
|
|
659
649
|
}
|
|
650
|
+
async trackStuck(player, track, payload) {
|
|
651
|
+
this.NodeManager.LavalinkManager.emit("trackStuck", player, track, payload);
|
|
652
|
+
// If there are no songs in the queue
|
|
653
|
+
if (!player.queue.tracks.length && (player.repeatMode === "off" || player.get("internal_stopPlaying")))
|
|
654
|
+
return this.queueEnd(player, track, payload);
|
|
655
|
+
// remove the current track, and enqueue the next one
|
|
656
|
+
await queueTrackEnd(player);
|
|
657
|
+
// if no track available, end queue
|
|
658
|
+
if (!player.queue.current)
|
|
659
|
+
return this.queueEnd(player, track, payload);
|
|
660
|
+
// play track if autoSkip is true
|
|
661
|
+
return (this.NodeManager.LavalinkManager.options.autoSkip && player.queue.current) && player.play({ noReplace: true });
|
|
662
|
+
}
|
|
663
|
+
async trackError(player, track, payload) {
|
|
664
|
+
this.NodeManager.LavalinkManager.emit("trackError", player, track, payload);
|
|
665
|
+
// If there are no songs in the queue
|
|
666
|
+
if (!player.queue.tracks.length && (player.repeatMode === "off" || player.get("internal_stopPlaying")))
|
|
667
|
+
return this.queueEnd(player, track, payload);
|
|
668
|
+
// remove the current track, and enqueue the next one
|
|
669
|
+
await queueTrackEnd(player);
|
|
670
|
+
// if no track available, end queue
|
|
671
|
+
if (!player.queue.current)
|
|
672
|
+
return this.queueEnd(player, track, payload);
|
|
673
|
+
// play track if autoSkip is true
|
|
674
|
+
return (this.NodeManager.LavalinkManager.options.autoSkip && player.queue.current) && player.play({ noReplace: true });
|
|
675
|
+
}
|
|
676
|
+
socketClosed(player, payload) {
|
|
677
|
+
return this.NodeManager.LavalinkManager.emit("playerSocketClosed", player, payload);
|
|
678
|
+
}
|
|
679
|
+
// SPONSOR BLOCK EVENT FUNCTIONS
|
|
680
|
+
SponsorBlockSegmentLoaded(player, track, payload) {
|
|
681
|
+
return this.NodeManager.LavalinkManager.emit("SegmentsLoaded", player, track, payload);
|
|
682
|
+
}
|
|
683
|
+
SponsorBlockSegmentkipped(player, track, payload) {
|
|
684
|
+
return this.NodeManager.LavalinkManager.emit("SegmentSkipped", player, track, payload);
|
|
685
|
+
}
|
|
686
|
+
SponsorBlockChaptersLoaded(player, track, payload) {
|
|
687
|
+
return this.NodeManager.LavalinkManager.emit("ChaptersLoaded", player, track, payload);
|
|
688
|
+
}
|
|
689
|
+
SponsorBlockChapterStarted(player, track, payload) {
|
|
690
|
+
return this.NodeManager.LavalinkManager.emit("ChapterStarted", player, track, payload);
|
|
691
|
+
}
|
|
692
|
+
// SPONSOR BLOCK EXECUTE FUNCTIONS
|
|
660
693
|
async getSponsorBlock(player) {
|
|
661
694
|
// no plugin enabled
|
|
662
695
|
if (!this.info.plugins.find(v => v.name === "sponsorblock-plugin"))
|
|
@@ -693,11 +726,13 @@ export class LavalinkNode {
|
|
|
693
726
|
});
|
|
694
727
|
return;
|
|
695
728
|
}
|
|
729
|
+
// UTIL FOR QUEUE END
|
|
696
730
|
async queueEnd(player, track, payload) {
|
|
697
731
|
// add previous track to the queue!
|
|
698
732
|
player.queue.current = null;
|
|
699
733
|
player.playing = false;
|
|
700
|
-
|
|
734
|
+
player.set("internal_stopPlaying", undefined);
|
|
735
|
+
if (typeof this.NodeManager.LavalinkManager.options?.playerOptions?.onEmptyQueue?.autoPlayFunction === "function" && typeof player.get("internal_autoplayStopPlaying") === "undefined") {
|
|
701
736
|
await this.NodeManager.LavalinkManager.options?.playerOptions?.onEmptyQueue?.autoPlayFunction(player, track);
|
|
702
737
|
if (player.queue.tracks.length > 0)
|
|
703
738
|
await queueTrackEnd(player);
|
|
@@ -707,6 +742,7 @@ export class LavalinkNode {
|
|
|
707
742
|
return player.play({ noReplace: true, paused: false });
|
|
708
743
|
}
|
|
709
744
|
}
|
|
745
|
+
player.set("internal_autoplayStopPlaying", undefined);
|
|
710
746
|
player.queue.previous.unshift(track);
|
|
711
747
|
if (payload?.reason !== "stopped") {
|
|
712
748
|
await player.queue.utils.save();
|
|
@@ -726,30 +762,4 @@ export class LavalinkNode {
|
|
|
726
762
|
}
|
|
727
763
|
return this.NodeManager.LavalinkManager.emit("queueEnd", player, track, payload);
|
|
728
764
|
}
|
|
729
|
-
async trackStuck(player, track, payload) {
|
|
730
|
-
this.NodeManager.LavalinkManager.emit("trackStuck", player, track, payload);
|
|
731
|
-
// If there are no songs in the queue
|
|
732
|
-
if (!player.queue.tracks.length && player.repeatMode === "off")
|
|
733
|
-
return;
|
|
734
|
-
// remove the current track, and enqueue the next one
|
|
735
|
-
await queueTrackEnd(player);
|
|
736
|
-
// if no track available, end queue
|
|
737
|
-
if (!player.queue.current)
|
|
738
|
-
return this.queueEnd(player, track, payload);
|
|
739
|
-
// play track if autoSkip is true
|
|
740
|
-
return (this.NodeManager.LavalinkManager.options.autoSkip && player.queue.current) && player.play({ noReplace: true });
|
|
741
|
-
}
|
|
742
|
-
async trackError(player, track, payload) {
|
|
743
|
-
this.NodeManager.LavalinkManager.emit("trackError", player, track, payload);
|
|
744
|
-
// remove the current track, and enqueue the next one
|
|
745
|
-
await queueTrackEnd(player);
|
|
746
|
-
// if no track available, end queue
|
|
747
|
-
if (!player.queue.current)
|
|
748
|
-
return this.queueEnd(player, track, payload);
|
|
749
|
-
// play track if autoSkip is true
|
|
750
|
-
return (this.NodeManager.LavalinkManager.options.autoSkip && player.queue.current) && player.play({ noReplace: true });
|
|
751
|
-
}
|
|
752
|
-
socketClosed(player, payload) {
|
|
753
|
-
return this.NodeManager.LavalinkManager.emit("playerSocketClosed", player, payload);
|
|
754
|
-
}
|
|
755
765
|
}
|
|
@@ -185,7 +185,7 @@ export declare class Player {
|
|
|
185
185
|
* Clears the queue and stops playing. Does not destroy the Player and not leave the channel
|
|
186
186
|
* @returns
|
|
187
187
|
*/
|
|
188
|
-
stopPlaying(): Promise<this>;
|
|
188
|
+
stopPlaying(clearQueue?: boolean, executeAutoplay?: boolean): Promise<this>;
|
|
189
189
|
/**
|
|
190
190
|
* Connects the Player to the Voice Channel
|
|
191
191
|
* @returns
|
|
@@ -310,10 +310,16 @@ export class Player {
|
|
|
310
310
|
* Clears the queue and stops playing. Does not destroy the Player and not leave the channel
|
|
311
311
|
* @returns
|
|
312
312
|
*/
|
|
313
|
-
async stopPlaying() {
|
|
313
|
+
async stopPlaying(clearQueue = true, executeAutoplay = false) {
|
|
314
|
+
// use internal_stopPlaying on true, so that it doesn't utilize current loop states. on trackEnd event
|
|
315
|
+
this.set("internal_stopPlaying", true);
|
|
314
316
|
// remove tracks from the queue
|
|
315
|
-
if (this.queue.tracks.length)
|
|
317
|
+
if (this.queue.tracks.length && clearQueue === true)
|
|
316
318
|
await this.queue.splice(0, this.queue.tracks.length);
|
|
319
|
+
if (executeAutoplay === false)
|
|
320
|
+
this.set("internal_autoplayStopPlaying", true);
|
|
321
|
+
else
|
|
322
|
+
this.set("internal_autoplayStopPlaying", undefined);
|
|
317
323
|
const now = performance.now();
|
|
318
324
|
// send to lavalink, that it should stop playing
|
|
319
325
|
await this.node.updatePlayer({ guildId: this.guildId, playerOptions: { encodedTrack: null } });
|
|
@@ -51,6 +51,17 @@ export interface UnresolvedSearchResult {
|
|
|
51
51
|
playlist: PlaylistInfo | null;
|
|
52
52
|
tracks: UnresolvedTrack[];
|
|
53
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* Parses Node Connection Url: "lavalink://<nodeId>:<nodeAuthorization(Password)>@<NodeHost>:<NodePort>"
|
|
56
|
+
* @param connectionUrl
|
|
57
|
+
* @returns
|
|
58
|
+
*/
|
|
59
|
+
export declare function parseLavalinkConnUrl(connectionUrl: string): {
|
|
60
|
+
authorization: string;
|
|
61
|
+
id: string;
|
|
62
|
+
host: string;
|
|
63
|
+
port: number;
|
|
64
|
+
};
|
|
54
65
|
export declare class ManagerUtils {
|
|
55
66
|
LavalinkManager: LavalinkManager | null;
|
|
56
67
|
constructor(LavalinkManager?: LavalinkManager);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { URL } from "node:url";
|
|
2
|
+
import { isRegExp } from "node:util/types";
|
|
2
3
|
import { DefaultSources, LavalinkPlugins, SourceLinksRegexes } from "./LavalinkManagerStatics";
|
|
3
4
|
export const TrackSymbol = Symbol("LC-Track");
|
|
4
5
|
export const UnresolvedTrackSymbol = Symbol("LC-Track-Unresolved");
|
|
@@ -6,6 +7,22 @@ export const QueueSymbol = Symbol("LC-Queue");
|
|
|
6
7
|
export const NodeSymbol = Symbol("LC-Node");
|
|
7
8
|
/** @hidden */
|
|
8
9
|
const escapeRegExp = (str) => str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
10
|
+
/**
|
|
11
|
+
* Parses Node Connection Url: "lavalink://<nodeId>:<nodeAuthorization(Password)>@<NodeHost>:<NodePort>"
|
|
12
|
+
* @param connectionUrl
|
|
13
|
+
* @returns
|
|
14
|
+
*/
|
|
15
|
+
export function parseLavalinkConnUrl(connectionUrl) {
|
|
16
|
+
if (!connectionUrl.startsWith("lavalink://"))
|
|
17
|
+
throw new Error(`ConnectionUrl (${connectionUrl}) must start with 'lavalink://'`);
|
|
18
|
+
const parsed = new URL(connectionUrl);
|
|
19
|
+
return {
|
|
20
|
+
authorization: parsed.password,
|
|
21
|
+
id: parsed.username,
|
|
22
|
+
host: parsed.hostname,
|
|
23
|
+
port: Number(parsed.port),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
9
26
|
export class ManagerUtils {
|
|
10
27
|
LavalinkManager = null;
|
|
11
28
|
constructor(LavalinkManager) {
|
|
@@ -240,17 +240,17 @@ export declare class LavalinkNode {
|
|
|
240
240
|
private error;
|
|
241
241
|
private message;
|
|
242
242
|
private handleEvent;
|
|
243
|
+
private trackStart;
|
|
244
|
+
private trackEnd;
|
|
245
|
+
private trackStuck;
|
|
246
|
+
private trackError;
|
|
247
|
+
private socketClosed;
|
|
243
248
|
private SponsorBlockSegmentLoaded;
|
|
244
249
|
private SponsorBlockSegmentkipped;
|
|
245
250
|
private SponsorBlockChaptersLoaded;
|
|
246
251
|
private SponsorBlockChapterStarted;
|
|
247
|
-
private trackStart;
|
|
248
|
-
private trackEnd;
|
|
249
252
|
getSponsorBlock(player: Player): Promise<SponsorBlockSegment[]>;
|
|
250
253
|
setSponsorBlock(player: Player, segments?: SponsorBlockSegment[]): Promise<void>;
|
|
251
254
|
deleteSponsorBlock(player: Player): Promise<void>;
|
|
252
255
|
private queueEnd;
|
|
253
|
-
private trackStuck;
|
|
254
|
-
private trackError;
|
|
255
|
-
private socketClosed;
|
|
256
256
|
}
|
|
@@ -185,7 +185,7 @@ export declare class Player {
|
|
|
185
185
|
* Clears the queue and stops playing. Does not destroy the Player and not leave the channel
|
|
186
186
|
* @returns
|
|
187
187
|
*/
|
|
188
|
-
stopPlaying(): Promise<this>;
|
|
188
|
+
stopPlaying(clearQueue?: boolean, executeAutoplay?: boolean): Promise<this>;
|
|
189
189
|
/**
|
|
190
190
|
* Connects the Player to the Voice Channel
|
|
191
191
|
* @returns
|
|
@@ -51,6 +51,17 @@ export interface UnresolvedSearchResult {
|
|
|
51
51
|
playlist: PlaylistInfo | null;
|
|
52
52
|
tracks: UnresolvedTrack[];
|
|
53
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* Parses Node Connection Url: "lavalink://<nodeId>:<nodeAuthorization(Password)>@<NodeHost>:<NodePort>"
|
|
56
|
+
* @param connectionUrl
|
|
57
|
+
* @returns
|
|
58
|
+
*/
|
|
59
|
+
export declare function parseLavalinkConnUrl(connectionUrl: string): {
|
|
60
|
+
authorization: string;
|
|
61
|
+
id: string;
|
|
62
|
+
host: string;
|
|
63
|
+
port: number;
|
|
64
|
+
};
|
|
54
65
|
export declare class ManagerUtils {
|
|
55
66
|
LavalinkManager: LavalinkManager | null;
|
|
56
67
|
constructor(LavalinkManager?: LavalinkManager);
|
package/package.json
CHANGED