lavalink-client 1.0.4 → 1.0.5
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 +32 -98
- package/dist/cjs/structures/LavalinkManager.d.ts +16 -14
- package/dist/cjs/structures/LavalinkManager.js +3 -14
- package/dist/cjs/structures/Node.js +10 -7
- package/dist/cjs/structures/NodeManager.d.ts +1 -12
- package/dist/cjs/structures/NodeManager.js +53 -60
- package/dist/cjs/structures/Player.d.ts +4 -4
- package/dist/cjs/structures/Player.js +20 -7
- package/dist/cjs/structures/Queue.d.ts +9 -9
- package/dist/cjs/structures/Queue.js +24 -23
- package/dist/cjs/structures/Track.d.ts +14 -3
- package/dist/cjs/structures/Utils.d.ts +20 -5
- package/dist/cjs/structures/Utils.js +81 -13
- package/dist/esm/structures/LavalinkManager.d.ts +16 -14
- package/dist/esm/structures/LavalinkManager.js +3 -14
- package/dist/esm/structures/Node.js +10 -7
- package/dist/esm/structures/NodeManager.d.ts +1 -12
- package/dist/esm/structures/NodeManager.js +53 -60
- package/dist/esm/structures/Player.d.ts +4 -4
- package/dist/esm/structures/Player.js +20 -7
- package/dist/esm/structures/Queue.d.ts +9 -9
- package/dist/esm/structures/Queue.js +25 -24
- package/dist/esm/structures/Track.d.ts +14 -3
- package/dist/esm/structures/Utils.d.ts +20 -5
- package/dist/esm/structures/Utils.js +81 -13
- package/dist/types/structures/LavalinkManager.d.ts +16 -14
- package/dist/types/structures/NodeManager.d.ts +1 -12
- package/dist/types/structures/Player.d.ts +4 -4
- package/dist/types/structures/Queue.d.ts +9 -9
- package/dist/types/structures/Track.d.ts +14 -3
- package/dist/types/structures/Utils.d.ts +20 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,17 +1,42 @@
|
|
|
1
|
-
#
|
|
2
|
-
Easy and advanced lavalink client. Use it with lavalink plugins as well as latest lavalink versions
|
|
1
|
+
# Lavalink Client
|
|
2
|
+
Easy and advanced lavalink client. Use it with lavalink plugins as well as latest lavalink versions.
|
|
3
3
|
|
|
4
4
|
# Install
|
|
5
5
|
|
|
6
6
|
Latest stable Version: (currently, unreleased)
|
|
7
|
-
|
|
7
|
+
|
|
8
|
+
<details><summary>👉 via NPM</summary>
|
|
9
|
+
|
|
10
|
+
```bash
|
|
8
11
|
npm install --save lavalink-client
|
|
9
12
|
```
|
|
13
|
+
|
|
10
14
|
Dev Version: (Current)
|
|
11
|
-
|
|
15
|
+
|
|
16
|
+
```bash
|
|
12
17
|
npm install tomato6966/lavalink-client
|
|
13
18
|
```
|
|
14
19
|
|
|
20
|
+
</details>
|
|
21
|
+
|
|
22
|
+
<details><summary>👉 via YARN</summary>
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
yarn add lavalink-client
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Dev Version: (Current)
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
yarn add tomato6966/lavalink-client
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
</details>
|
|
35
|
+
|
|
36
|
+
# Documentation
|
|
37
|
+
|
|
38
|
+
Check out the [Documentation](https://lc4.gitbook.io/lavalink-client) for **Examples**, and **__detailled__ Docs**, and to figure out **how to get started**. *note: it's not fully done yet (see the docs)*
|
|
39
|
+
|
|
15
40
|
# Features
|
|
16
41
|
|
|
17
42
|
- 💯 Lavalink v4 Supported only (with Lavalink Plugins)
|
|
@@ -21,6 +46,8 @@ npm install tomato6966/lavalink-client
|
|
|
21
46
|
|
|
22
47
|
- ✨ Choose able queue stores (maps, collections, redis, databases, ...)
|
|
23
48
|
- You can create your own queueStore, thus make it easy to sync queues accross multiple connections (e.g. dashboard-bot)
|
|
49
|
+
- Automated Queue Sync methods
|
|
50
|
+
- Automated unresolveable Tracks (save the queries as Partial Track Objects -> Fetch the tracks only once they are gonna play)
|
|
24
51
|
|
|
25
52
|
- 😍 Included Filter & Equalizer Management
|
|
26
53
|
|
|
@@ -41,98 +68,5 @@ npm install tomato6966/lavalink-client
|
|
|
41
68
|
- Destroys the player on channeldelete
|
|
42
69
|
- Pauses / resumes the player if it get's muted / unmuted (server-wide) [soon]
|
|
43
70
|
- ...
|
|
44
|
-
- 😁 Much much more!
|
|
45
|
-
|
|
46
|
-
# Documentation
|
|
47
|
-
|
|
48
|
-
*soon*
|
|
49
|
-
|
|
50
|
-
# How to Use
|
|
51
|
-
|
|
52
|
-
1. Import the Manager
|
|
53
|
-
|
|
54
|
-
```ts
|
|
55
|
-
import { LavalinkManager } from "lavalink-client"; // Modular JS / Typescript
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
```js
|
|
59
|
-
const { LavalinkManager } = require("lavalink-client"); // Common Js
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
2. create the Manager
|
|
63
|
-
|
|
64
|
-
```ts
|
|
65
|
-
// Suggest it to extend it to the bot Client
|
|
66
|
-
client.lavalink = new LavalinkManager({
|
|
67
|
-
nodes: [
|
|
68
|
-
{
|
|
69
|
-
authorization: "youshallnotpass",
|
|
70
|
-
host: "localhost",
|
|
71
|
-
port: 2333,
|
|
72
|
-
id: "testnode",
|
|
73
|
-
requestTimeout: 10000,
|
|
74
|
-
}
|
|
75
|
-
],
|
|
76
|
-
sendToShard: (guildId, payload) => client.guilds.cache.get(guildId)?.shard?.send(payload),
|
|
77
|
-
autoSkip: true,
|
|
78
|
-
client: {
|
|
79
|
-
id: envConfig.clientId,
|
|
80
|
-
username: "TESTBOT",
|
|
81
|
-
shards: "auto"
|
|
82
|
-
},
|
|
83
|
-
playerOptions: {
|
|
84
|
-
applyVolumeAsFilter: false,
|
|
85
|
-
clientBasedUpdateInterval: 50,
|
|
86
|
-
defaultSearchPlatform: "dzsearch",
|
|
87
|
-
volumeDecrementer: 0.7
|
|
88
|
-
},
|
|
89
|
-
queueOptions: {
|
|
90
|
-
maxPreviousTracks: 5
|
|
91
|
-
},
|
|
92
|
-
// queueStore: new myCustomStore(client.redis), // OPTIONAL! 'class myCustomStore extends DefaultQueueStore' --> for custom queue stores, e.g. redis, etc. | default is lavalink-client#MiniMap
|
|
93
|
-
// queueChangesWatcher: new myCustomWatcher(), // OPTIONAL! 'class myCustomWatcher extends QueueChangesWatcher' --> for queue action logs!
|
|
94
|
-
});
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
3. **VERY IMPORTANT!** - Register Voice State updates + initialize the Manager
|
|
98
|
-
|
|
99
|
-
```ts
|
|
100
|
-
client.on("raw", d => client.lavalink.sendRawData(d)); // for voice state updates!
|
|
101
|
-
client.on("ready", async () => {
|
|
102
|
-
console.log("Discord Bot is ready to be Used!");
|
|
103
|
-
// user.id is required, user.shards (not), user.username (not, but recommended for lavalink stats!)
|
|
104
|
-
await client.lavalink.init({ ...client.user!, shards: "auto" });
|
|
105
|
-
});
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
4. **Use it!**
|
|
109
|
-
|
|
110
|
-
```ts
|
|
111
|
-
// create player
|
|
112
|
-
const player = await client.lavalink.createPlayer({
|
|
113
|
-
guildId: guild.id, voiceChannelId: voice.id, textChannelId: text.id, // in what guild + channel(s)
|
|
114
|
-
selfDeaf: true, selfMute: false, volume: 100 // configuration(s)
|
|
115
|
-
});
|
|
116
|
-
// connect the player to it's vc
|
|
117
|
-
await player.connect();
|
|
118
|
-
|
|
119
|
-
const res = await player.search({
|
|
120
|
-
query: `Elton John`, // source: `soundcloud`,
|
|
121
|
-
}, client.user); // search a query (query-search, url search, identifier search, etc.)
|
|
122
|
-
|
|
123
|
-
await player.queue.add(res.tracks); // add 1 track, or an array of tracks
|
|
124
|
-
await player.play(); // you can provide specific track, or let the manager choose the track from the queue!
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
## Example (typescript)
|
|
128
|
-
|
|
129
|
-
Can be found in the [`/testBot`](https://github.com/Tomato6966/lavalink-client/blob/main/testBot/README.md) Directory
|
|
130
|
-
|
|
131
|
-
It contains the following features:
|
|
132
71
|
|
|
133
|
-
-
|
|
134
|
-
- Example Use for `Queue Changes Watcher Logger`
|
|
135
|
-
- Example Use for `Filters`, `Audio Output`, `equalizers`
|
|
136
|
-
- How to make an easy, yet advanced `Slash Commands Only Bot`
|
|
137
|
-
- `Slim Memory Usage`
|
|
138
|
-
- `All lavalink-client events` displayments
|
|
72
|
+
- 😁 Much much more!
|
|
@@ -5,13 +5,12 @@ import { QueueSaverOptions } from "./Queue";
|
|
|
5
5
|
import { GuildShardPayload, LavalinkSearchPlatform, ManagerUitls, MiniMap, SearchPlatform, TrackEndEvent, TrackExceptionEvent, TrackStartEvent, TrackStuckEvent, VoicePacket, VoiceServer, VoiceState, WebSocketClosedEvent } from "./Utils";
|
|
6
6
|
import { LavalinkNodeOptions } from "./Node";
|
|
7
7
|
import { DestroyReasonsType, Player, PlayerOptions } from "./Player";
|
|
8
|
-
import { Track } from "./Track";
|
|
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
|
-
shards?: number | number[] | "auto";
|
|
15
14
|
id: string;
|
|
16
15
|
username?: string;
|
|
17
16
|
/** So users can pass entire objects / classes */
|
|
@@ -47,40 +46,38 @@ export interface ManagerOptions {
|
|
|
47
46
|
client?: BotClientOptions;
|
|
48
47
|
playerOptions?: LavalinkPlayerOptions;
|
|
49
48
|
autoSkip?: boolean;
|
|
50
|
-
defaultLeastUsedNodeSortType?: "memory" | "calls" | "players";
|
|
51
|
-
defaultLeastLoadNodeSortType?: "cpu" | "memory";
|
|
52
49
|
/** @async */
|
|
53
50
|
sendToShard: (guildId: string, payload: GuildShardPayload) => void;
|
|
54
51
|
}
|
|
55
52
|
interface LavalinkManagerEvents {
|
|
56
53
|
/**
|
|
57
54
|
* Emitted when a Track started playing.
|
|
58
|
-
* @event Manager
|
|
55
|
+
* @event Manager#trackStart
|
|
59
56
|
*/
|
|
60
57
|
"trackStart": (player: Player, track: Track, payload: TrackStartEvent) => void;
|
|
61
58
|
/**
|
|
62
59
|
* Emitted when a Track finished.
|
|
63
|
-
* @event Manager
|
|
60
|
+
* @event Manager#trackEnd
|
|
64
61
|
*/
|
|
65
62
|
"trackEnd": (player: Player, track: Track, payload: TrackEndEvent) => void;
|
|
66
63
|
/**
|
|
67
64
|
* Emitted when a Track got stuck while playing.
|
|
68
|
-
* @event Manager
|
|
65
|
+
* @event Manager#trackStuck
|
|
69
66
|
*/
|
|
70
67
|
"trackStuck": (player: Player, track: Track, payload: TrackStuckEvent) => void;
|
|
71
68
|
/**
|
|
72
69
|
* Emitted when a Track errored.
|
|
73
|
-
* @event Manager
|
|
70
|
+
* @event Manager#trackError
|
|
74
71
|
*/
|
|
75
|
-
"trackError": (player: Player, track: Track, payload: TrackExceptionEvent) => void;
|
|
72
|
+
"trackError": (player: Player, track: Track | UnresolvedTrack, payload: TrackExceptionEvent) => void;
|
|
76
73
|
/**
|
|
77
74
|
* Emitted when the Playing finished and no more tracks in the queue.
|
|
78
|
-
* @event Manager
|
|
75
|
+
* @event Manager#queueEnd
|
|
79
76
|
*/
|
|
80
77
|
"queueEnd": (player: Player, track: Track, payload: TrackEndEvent | TrackStuckEvent | TrackExceptionEvent) => void;
|
|
81
78
|
/**
|
|
82
79
|
* Emitted when a Player is created.
|
|
83
|
-
* @event Manager
|
|
80
|
+
* @event Manager#playerCreate
|
|
84
81
|
*/
|
|
85
82
|
"playerCreate": (player: Player) => void;
|
|
86
83
|
/**
|
|
@@ -90,19 +87,24 @@ interface LavalinkManagerEvents {
|
|
|
90
87
|
"playerMove": (player: Player, oldVoiceChannelId: string, newVoiceChannelId: string) => void;
|
|
91
88
|
/**
|
|
92
89
|
* Emitted when a Player is disconnected from a channel.
|
|
93
|
-
* @event Manager
|
|
90
|
+
* @event Manager#playerDisconnect
|
|
94
91
|
*/
|
|
95
92
|
"playerDisconnect": (player: Player, voiceChannelId: string) => void;
|
|
96
93
|
/**
|
|
97
94
|
* Emitted when a Node-Socket got closed for a specific Player.
|
|
98
|
-
* @event Manager
|
|
95
|
+
* @event Manager#playerSocketClosed
|
|
99
96
|
*/
|
|
100
97
|
"playerSocketClosed": (player: Player, payload: WebSocketClosedEvent) => void;
|
|
101
98
|
/**
|
|
102
99
|
* Emitted when a Player get's destroyed
|
|
103
|
-
* @event Manager
|
|
100
|
+
* @event Manager#playerDestroy
|
|
104
101
|
*/
|
|
105
102
|
"playerDestroy": (player: Player, destroyReason?: DestroyReasonsType) => void;
|
|
103
|
+
/**
|
|
104
|
+
* Always emits when the player (on lavalink side) got updated
|
|
105
|
+
* @event Manager#playerUpdate
|
|
106
|
+
*/
|
|
107
|
+
"playerUpdate": (player: Player) => void;
|
|
106
108
|
}
|
|
107
109
|
export interface LavalinkManager {
|
|
108
110
|
options: ManagerOptions;
|
|
@@ -45,10 +45,6 @@ class LavalinkManager extends events_1.EventEmitter {
|
|
|
45
45
|
};
|
|
46
46
|
if (!this.options.autoSkip)
|
|
47
47
|
this.options.autoSkip = true;
|
|
48
|
-
if (!this.options.defaultLeastLoadNodeSortType)
|
|
49
|
-
this.options.defaultLeastLoadNodeSortType = "memory";
|
|
50
|
-
if (!this.options.defaultLeastUsedNodeSortType)
|
|
51
|
-
this.options.defaultLeastUsedNodeSortType = "players";
|
|
52
48
|
if (!this.options.playerOptions.defaultSearchPlatform)
|
|
53
49
|
this.options.playerOptions.defaultSearchPlatform = "ytsearch";
|
|
54
50
|
// default queue options
|
|
@@ -66,13 +62,9 @@ class LavalinkManager extends events_1.EventEmitter {
|
|
|
66
62
|
if (typeof options.sendToShard !== "function")
|
|
67
63
|
throw new SyntaxError("ManagerOption.sendToShard was not provided, which is required!");
|
|
68
64
|
// only check in .init()
|
|
69
|
-
// if(typeof options.client !== "object" || typeof options.client.id !== "string") throw new SyntaxError("ManagerOption.client = { id: string, username?:string
|
|
65
|
+
// if(typeof options.client !== "object" || typeof options.client.id !== "string") throw new SyntaxError("ManagerOption.client = { id: string, username?:string } was not provided, which is required");
|
|
70
66
|
if (options.autoSkip && typeof options.autoSkip !== "boolean")
|
|
71
67
|
throw new SyntaxError("ManagerOption.autoSkip must be either false | true aka boolean");
|
|
72
|
-
if (options.defaultLeastLoadNodeSortType && !["memory", "cpu"].includes(options.defaultLeastLoadNodeSortType))
|
|
73
|
-
throw new SyntaxError("ManagerOption.defaultLeastLoadNodeSortType must be 'memory' | 'cpu'");
|
|
74
|
-
if (options.defaultLeastUsedNodeSortType && !["memory", "players", "calls"].includes(options.defaultLeastUsedNodeSortType))
|
|
75
|
-
throw new SyntaxError("ManagerOption.defaultLeastLoadNodeSortType must be 'memory' | 'calls' | 'players'");
|
|
76
68
|
if (!options.nodes || !Array.isArray(options.nodes) || !options.nodes.every(node => this.utils.isNodeOptions(node)))
|
|
77
69
|
throw new SyntaxError("ManagerOption.nodes must be an Array of NodeOptions and is required of at least 1 Node");
|
|
78
70
|
/* QUEUE STORE */
|
|
@@ -157,9 +149,7 @@ class LavalinkManager extends events_1.EventEmitter {
|
|
|
157
149
|
* @param data
|
|
158
150
|
*/
|
|
159
151
|
async sendRawData(data) {
|
|
160
|
-
if (!this.initiated)
|
|
161
|
-
return;
|
|
162
|
-
if (!("t" in data))
|
|
152
|
+
if (!this.initiated || !("t" in data))
|
|
163
153
|
return;
|
|
164
154
|
// for channel Delete
|
|
165
155
|
if ("CHANNEL_DELETE" === data.t) {
|
|
@@ -167,9 +157,8 @@ class LavalinkManager extends events_1.EventEmitter {
|
|
|
167
157
|
if (!update.guild_id)
|
|
168
158
|
return;
|
|
169
159
|
const player = this.getPlayer(update.guild_id);
|
|
170
|
-
if (player.voiceChannelId === update.id)
|
|
160
|
+
if (player && player.voiceChannelId === update.id)
|
|
171
161
|
return player.destroy(Player_1.DestroyReasons.ChannelDeleted);
|
|
172
|
-
}
|
|
173
162
|
}
|
|
174
163
|
// for voice updates
|
|
175
164
|
if (["VOICE_STATE_UPDATE", "VOICE_SERVER_UPDATE"].includes(data.t)) {
|
|
@@ -137,9 +137,8 @@ class LavalinkNode {
|
|
|
137
137
|
return;
|
|
138
138
|
const headers = {
|
|
139
139
|
Authorization: this.options.authorization,
|
|
140
|
-
"Num-Shards": String(this.NodeManager.LavalinkManager.options.client.shards || "auto"),
|
|
141
140
|
"User-Id": this.NodeManager.LavalinkManager.options.client.id,
|
|
142
|
-
"
|
|
141
|
+
"Client-Name": this.NodeManager.LavalinkManager.options.client.username || "Lavalink-Client",
|
|
143
142
|
};
|
|
144
143
|
if (typeof this.options.sessionId === "string" || typeof sessionId === "string") {
|
|
145
144
|
headers["Session-Id"] = this.options.sessionId || sessionId;
|
|
@@ -477,6 +476,7 @@ class LavalinkNode {
|
|
|
477
476
|
player.filterManager.filterUpdatedState = 0;
|
|
478
477
|
}
|
|
479
478
|
}
|
|
479
|
+
this.NodeManager.LavalinkManager.emit("playerUpdate", player);
|
|
480
480
|
break;
|
|
481
481
|
case "event":
|
|
482
482
|
this.handleEvent(payload);
|
|
@@ -523,6 +523,7 @@ class LavalinkNode {
|
|
|
523
523
|
return this.NodeManager.LavalinkManager.emit("trackStart", player, track, payload);
|
|
524
524
|
}
|
|
525
525
|
async trackEnd(player, track, payload) {
|
|
526
|
+
console.log(payload.reason);
|
|
526
527
|
// If there are no songs in the queue
|
|
527
528
|
if (!player.queue.tracks.length && player.repeatMode === "off")
|
|
528
529
|
return this.queueEnd(player, track, payload);
|
|
@@ -531,7 +532,7 @@ class LavalinkNode {
|
|
|
531
532
|
return this.NodeManager.LavalinkManager.emit("trackEnd", player, track, payload);
|
|
532
533
|
// If a track had an error while starting
|
|
533
534
|
if (["loadFailed", "cleanup"].includes(payload.reason)) {
|
|
534
|
-
await (0, Utils_1.queueTrackEnd)(player
|
|
535
|
+
await (0, Utils_1.queueTrackEnd)(player);
|
|
535
536
|
// if no track available, end queue
|
|
536
537
|
if (!player.queue.current)
|
|
537
538
|
return this.queueEnd(player, track, payload);
|
|
@@ -542,7 +543,7 @@ class LavalinkNode {
|
|
|
542
543
|
}
|
|
543
544
|
// remove tracks from the queue
|
|
544
545
|
if (player.repeatMode !== "track")
|
|
545
|
-
await (0, Utils_1.queueTrackEnd)(player
|
|
546
|
+
await (0, Utils_1.queueTrackEnd)(player);
|
|
546
547
|
// if no track available, end queue
|
|
547
548
|
if (!player.queue.current)
|
|
548
549
|
return this.queueEnd(player, track, payload);
|
|
@@ -552,15 +553,17 @@ class LavalinkNode {
|
|
|
552
553
|
return this.NodeManager.LavalinkManager.options.autoSkip && player.play({ noReplace: true });
|
|
553
554
|
}
|
|
554
555
|
async queueEnd(player, track, payload) {
|
|
556
|
+
// add previous track to the queue!
|
|
555
557
|
player.queue.current = null;
|
|
556
558
|
player.playing = false;
|
|
557
559
|
if (typeof this.NodeManager.LavalinkManager.options?.playerOptions?.onEmptyQueue?.autoPlayFunction === "function") {
|
|
558
560
|
await this.NodeManager.LavalinkManager.options?.playerOptions?.onEmptyQueue?.autoPlayFunction(player, track);
|
|
559
561
|
if (player.queue.tracks.length > 0)
|
|
560
|
-
await (0, Utils_1.queueTrackEnd)(player
|
|
562
|
+
await (0, Utils_1.queueTrackEnd)(player);
|
|
561
563
|
if (player.queue.current)
|
|
562
564
|
return player.play({ noReplace: true, paused: false });
|
|
563
565
|
}
|
|
566
|
+
player.queue.previous.unshift(track);
|
|
564
567
|
if (payload?.reason !== "stopped") {
|
|
565
568
|
await player.queue.utils.save();
|
|
566
569
|
}
|
|
@@ -585,7 +588,7 @@ class LavalinkNode {
|
|
|
585
588
|
if (!player.queue.tracks.length && player.repeatMode === "off")
|
|
586
589
|
return;
|
|
587
590
|
// remove the current track, and enqueue the next one
|
|
588
|
-
await (0, Utils_1.queueTrackEnd)(player
|
|
591
|
+
await (0, Utils_1.queueTrackEnd)(player);
|
|
589
592
|
// if no track available, end queue
|
|
590
593
|
if (!player.queue.current)
|
|
591
594
|
return this.queueEnd(player, track, payload);
|
|
@@ -595,7 +598,7 @@ class LavalinkNode {
|
|
|
595
598
|
async trackError(player, track, payload) {
|
|
596
599
|
this.NodeManager.LavalinkManager.emit("trackError", player, track, payload);
|
|
597
600
|
// remove the current track, and enqueue the next one
|
|
598
|
-
await (0, Utils_1.queueTrackEnd)(player
|
|
601
|
+
await (0, Utils_1.queueTrackEnd)(player);
|
|
599
602
|
// if no track available, end queue
|
|
600
603
|
if (!player.queue.current)
|
|
601
604
|
return this.queueEnd(player, track, payload);
|
|
@@ -55,18 +55,7 @@ export declare class NodeManager extends EventEmitter {
|
|
|
55
55
|
nodes: MiniMap<string, LavalinkNode>;
|
|
56
56
|
constructor(LavalinkManager: LavalinkManager);
|
|
57
57
|
createNode(options: LavalinkNodeOptions): LavalinkNode;
|
|
58
|
-
|
|
59
|
-
/** Returns the least used Nodes sorted by amount of calls. */
|
|
60
|
-
private get leastUsedNodesCalls();
|
|
61
|
-
/** Returns the least used Nodes sorted by amount of players. */
|
|
62
|
-
private get leastUsedNodesPlayers();
|
|
63
|
-
/** Returns the least used Nodes sorted by amount of memory usage. */
|
|
64
|
-
private get leastUsedNodesMemory();
|
|
65
|
-
/** Returns the least system load Nodes. */
|
|
66
|
-
get leastLoadNodes(): LavalinkNode[];
|
|
67
|
-
get leastLoadNodesMemory(): LavalinkNode[];
|
|
68
|
-
/** Returns the least system load Nodes. */
|
|
69
|
-
get leastLoadNodesCpu(): LavalinkNode[];
|
|
58
|
+
leastUsedNodes(sortType?: "memory" | "cpuLavalink" | "cpuSystem" | "calls" | "playingPlayers" | "players"): LavalinkNode[];
|
|
70
59
|
deleteNode(node: LavalinkNodeIdentifier | LavalinkNode): void;
|
|
71
60
|
}
|
|
72
61
|
export {};
|
|
@@ -20,68 +20,61 @@ class NodeManager extends stream_1.EventEmitter {
|
|
|
20
20
|
this.nodes.set(newNode.id, newNode);
|
|
21
21
|
return newNode;
|
|
22
22
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
? (a.stats.cpu.systemLoad / a.stats.cpu.cores) * 100
|
|
76
|
-
: 0;
|
|
77
|
-
const bload = b.stats.cpu
|
|
78
|
-
? (b.stats.cpu.systemLoad / b.stats.cpu.cores) * 100
|
|
79
|
-
: 0;
|
|
80
|
-
return aload - bload;
|
|
81
|
-
});
|
|
23
|
+
leastUsedNodes(sortType = "players") {
|
|
24
|
+
switch (sortType) {
|
|
25
|
+
case "memory":
|
|
26
|
+
{
|
|
27
|
+
return [...this.nodes.values()]
|
|
28
|
+
.filter((node) => node.connected)
|
|
29
|
+
.sort((a, b) => (a.stats?.memory?.used || 0) - (b.stats?.memory?.used || 0)); // sort after memor
|
|
30
|
+
}
|
|
31
|
+
break;
|
|
32
|
+
case "cpuLavalink":
|
|
33
|
+
{
|
|
34
|
+
return [...this.nodes.values()]
|
|
35
|
+
.filter((node) => node.connected)
|
|
36
|
+
.sort((a, b) => (a.stats?.cpu?.lavalinkLoad || 0) - (b.stats?.cpu?.lavalinkLoad || 0)); // sort after memor
|
|
37
|
+
}
|
|
38
|
+
break;
|
|
39
|
+
case "cpuSystem":
|
|
40
|
+
{
|
|
41
|
+
return [...this.nodes.values()]
|
|
42
|
+
.filter((node) => node.connected)
|
|
43
|
+
.sort((a, b) => (a.stats?.cpu?.systemLoad || 0) - (b.stats?.cpu?.systemLoad || 0)); // sort after memor
|
|
44
|
+
}
|
|
45
|
+
break;
|
|
46
|
+
case "calls":
|
|
47
|
+
{
|
|
48
|
+
return [...this.nodes.values()]
|
|
49
|
+
.filter((node) => node.connected)
|
|
50
|
+
.sort((a, b) => a.calls - b.calls); // client sided sorting
|
|
51
|
+
}
|
|
52
|
+
break;
|
|
53
|
+
case "playingPlayers":
|
|
54
|
+
{
|
|
55
|
+
return [...this.nodes.values()]
|
|
56
|
+
.filter((node) => node.connected)
|
|
57
|
+
.sort((a, b) => (a.stats?.playingPlayers || 0) - (b.stats?.playingPlayers || 0));
|
|
58
|
+
}
|
|
59
|
+
break;
|
|
60
|
+
case "players":
|
|
61
|
+
{
|
|
62
|
+
return [...this.nodes.values()]
|
|
63
|
+
.filter((node) => node.connected)
|
|
64
|
+
.sort((a, b) => (a.stats?.players || 0) - (b.stats?.players || 0));
|
|
65
|
+
}
|
|
66
|
+
break;
|
|
67
|
+
default:
|
|
68
|
+
{
|
|
69
|
+
return [...this.nodes.values()]
|
|
70
|
+
.filter((node) => node.connected)
|
|
71
|
+
.sort((a, b) => (a.stats?.players || 0) - (b.stats?.players || 0));
|
|
72
|
+
}
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
82
75
|
}
|
|
83
76
|
deleteNode(node) {
|
|
84
|
-
const decodeNode = typeof node === "string" ? this.nodes.get(node) : node || this.leastUsedNodes[0];
|
|
77
|
+
const decodeNode = typeof node === "string" ? this.nodes.get(node) : node || this.leastUsedNodes()[0];
|
|
85
78
|
if (!decodeNode)
|
|
86
79
|
throw new Error("Node was not found");
|
|
87
80
|
decodeNode.destroy(Player_1.DestroyReasons.NodeDeleted);
|
|
@@ -110,7 +110,7 @@ export declare class Player {
|
|
|
110
110
|
* Play the next track from the queue / a specific track, with playoptions for Lavalink
|
|
111
111
|
* @param options
|
|
112
112
|
*/
|
|
113
|
-
play(options?: Partial<PlayOptions>):
|
|
113
|
+
play(options?: Partial<PlayOptions>): any;
|
|
114
114
|
/**
|
|
115
115
|
* Set the Volume for the Player
|
|
116
116
|
* @param volume The Volume in percent
|
|
@@ -143,12 +143,12 @@ export declare class Player {
|
|
|
143
143
|
* Set the Repeatmode of the Player
|
|
144
144
|
* @param repeatMode
|
|
145
145
|
*/
|
|
146
|
-
setRepeatMode(repeatMode: RepeatMode): Promise<
|
|
146
|
+
setRepeatMode(repeatMode: RepeatMode): Promise<RepeatMode>;
|
|
147
147
|
/**
|
|
148
148
|
* Skip the current song, or a specific amount of songs
|
|
149
149
|
* @param amount provide the index of the next track to skip to
|
|
150
150
|
*/
|
|
151
|
-
skip(skipTo?: number): Promise<
|
|
151
|
+
skip(skipTo?: number): Promise<any>;
|
|
152
152
|
/**
|
|
153
153
|
* Connects the Player to the Voice Channel
|
|
154
154
|
* @returns
|
|
@@ -172,6 +172,7 @@ export declare class Player {
|
|
|
172
172
|
/** Converts the Player including Queue to a Json state */
|
|
173
173
|
toJSON(): {
|
|
174
174
|
guildId: string;
|
|
175
|
+
options: PlayerOptions;
|
|
175
176
|
voiceChannelId: string;
|
|
176
177
|
textChannelId: string;
|
|
177
178
|
position: number;
|
|
@@ -184,7 +185,6 @@ export declare class Player {
|
|
|
184
185
|
createdTimeStamp: number;
|
|
185
186
|
filters: {};
|
|
186
187
|
equalizer: import("./Filters").EQBand[];
|
|
187
|
-
queue: import("./Queue").StoredQueue;
|
|
188
188
|
nodeId: string;
|
|
189
189
|
};
|
|
190
190
|
}
|
|
@@ -67,8 +67,10 @@ class Player {
|
|
|
67
67
|
this.voiceChannelId = this.options.voiceChannelId;
|
|
68
68
|
this.textChannelId = this.options.textChannelId || null;
|
|
69
69
|
this.node = typeof this.options.node === "string" ? this.LavalinkManager.nodeManager.nodes.get(this.options.node) : this.options.node;
|
|
70
|
-
if (!this.node || typeof this.node
|
|
71
|
-
|
|
70
|
+
if (!this.node || typeof this.node.request !== "function") {
|
|
71
|
+
const least = this.LavalinkManager.nodeManager.leastUsedNodes();
|
|
72
|
+
this.node = least.filter(v => options.vcRegion ? v.options?.regions?.includes(options.vcRegion) : true)[0] || least[0] || null;
|
|
73
|
+
}
|
|
72
74
|
if (!this.node)
|
|
73
75
|
throw new Error("No available Node was found, please add a LavalinkNode to the Manager via Manager.NodeManager#createNode");
|
|
74
76
|
if (this.LavalinkManager.options.playerOptions.volumeDecrementer)
|
|
@@ -123,10 +125,22 @@ class Player {
|
|
|
123
125
|
}
|
|
124
126
|
if (options?.track && this.LavalinkManager.utils.isTrack(options?.track)) {
|
|
125
127
|
await this.queue.add(options?.track, 0);
|
|
126
|
-
await (0, Utils_1.queueTrackEnd)(this
|
|
128
|
+
await (0, Utils_1.queueTrackEnd)(this);
|
|
127
129
|
}
|
|
128
130
|
if (!this.queue.current && this.queue.tracks.length)
|
|
129
|
-
await (0, Utils_1.queueTrackEnd)(this
|
|
131
|
+
await (0, Utils_1.queueTrackEnd)(this);
|
|
132
|
+
// @ts-ignore
|
|
133
|
+
if (this.queue.current && this.LavalinkManager.utils.isUnresolvedTrack(this.queue.current)) {
|
|
134
|
+
try {
|
|
135
|
+
this.queue.current = await this.LavalinkManager.utils.getClosestTrack({ ...(this.queue.current || {}) }, this);
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
this.LavalinkManager.emit("trackError", this, this.queue.current, error);
|
|
139
|
+
if (this.queue.tracks[0])
|
|
140
|
+
return this.play();
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
130
144
|
const track = this.queue.current;
|
|
131
145
|
if (!track)
|
|
132
146
|
throw new Error(`There is no Track in the Queue, nor provided in the PlayOptions`);
|
|
@@ -277,8 +291,7 @@ class Player {
|
|
|
277
291
|
async setRepeatMode(repeatMode) {
|
|
278
292
|
if (!["off", "track", "queue"].includes(repeatMode))
|
|
279
293
|
throw new RangeError("Repeatmode must be either 'off', 'track', or 'queue'");
|
|
280
|
-
this.repeatMode = repeatMode;
|
|
281
|
-
return;
|
|
294
|
+
return this.repeatMode = repeatMode;
|
|
282
295
|
}
|
|
283
296
|
/**
|
|
284
297
|
* Skip the current song, or a specific amount of songs
|
|
@@ -378,6 +391,7 @@ class Player {
|
|
|
378
391
|
toJSON() {
|
|
379
392
|
return {
|
|
380
393
|
guildId: this.guildId,
|
|
394
|
+
options: this.options,
|
|
381
395
|
voiceChannelId: this.voiceChannelId,
|
|
382
396
|
textChannelId: this.textChannelId,
|
|
383
397
|
position: this.position,
|
|
@@ -390,7 +404,6 @@ class Player {
|
|
|
390
404
|
createdTimeStamp: this.createdTimeStamp,
|
|
391
405
|
filters: this.filterManager?.data || {},
|
|
392
406
|
equalizer: this.filterManager?.equalizerBands || [],
|
|
393
|
-
queue: this.queue?.utils?.getStored?.() || { current: null, tracks: [], previous: [] },
|
|
394
407
|
nodeId: this.node?.id,
|
|
395
408
|
};
|
|
396
409
|
}
|