aqualink 1.0.5 → 1.1.0
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 +21 -0
- package/build/structures/Aqua.js +21 -11
- package/build/structures/Connection.js +14 -11
- package/build/structures/Node.js +19 -43
- package/build/structures/Player.js +20 -9
- package/build/structures/Queue.js +1 -0
- package/build/structures/Rest.js +23 -27
- package/build/structures/Track.js +7 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -20,6 +20,27 @@ This code is based in riffy, but its an 100% Rewrite made from scratch...
|
|
|
20
20
|
# Docs (Wiki)
|
|
21
21
|
- https://github.com/ToddyTheNoobDud/AquaLink/wiki
|
|
22
22
|
|
|
23
|
+
# Yay, Version 1.1.0 is released ! aqualink so cool
|
|
24
|
+
|
|
25
|
+
+ Fixed stop
|
|
26
|
+
+ Fixed Destroy
|
|
27
|
+
+ Fixed disconnect
|
|
28
|
+
+ Improved events
|
|
29
|
+
+ Optimize more
|
|
30
|
+
+ Improved queue system
|
|
31
|
+
+ Improved speed
|
|
32
|
+
+ Remove useless code
|
|
33
|
+
+ Add more features...
|
|
34
|
+
+ Fixed some resolve() methods
|
|
35
|
+
+ Improved debug / logging
|
|
36
|
+
+ Add new option: shouldDeleteMessage (true, false, if true will delete the nowPlayingMessage, false will not delete)
|
|
37
|
+
+ Add nowPlayingMessage
|
|
38
|
+
+ Rewrited REST Manager (1,5x faster, less memory usage, less cpu usage, less latency)
|
|
39
|
+
+ Rewrited NODE Manager (A bit faster, less memory usage, less cpu, Less temp objects, better error handling)
|
|
40
|
+
+ Rewrite Connection Manager (Faster, less bugs, less useless checking, fixed an random memory leak)
|
|
41
|
+
+ Updated Aqua.js (added shouldDeleteMessage, some misc update for playlist)
|
|
42
|
+
+ Added playlist support for Track (testing)
|
|
43
|
+
|
|
23
44
|
# How to install
|
|
24
45
|
|
|
25
46
|
`npm install aqualink`
|
package/build/structures/Aqua.js
CHANGED
|
@@ -13,6 +13,7 @@ class Aqua extends EventEmitter {
|
|
|
13
13
|
* @param {string} [options.defaultSearchPlatform="ytsearch"] - Default search platform.
|
|
14
14
|
* @param {string} [options.restVersion="v4"] - Version of the REST API.
|
|
15
15
|
* @param {Array<Object>} [options.plugins=[]] - Plugins to load.
|
|
16
|
+
* @param {string} [options.shouldDeleteMessage='none'] - Should delete your message? (true, false)
|
|
16
17
|
*/
|
|
17
18
|
constructor(client, nodes, options) {
|
|
18
19
|
super();
|
|
@@ -27,6 +28,7 @@ class Aqua extends EventEmitter {
|
|
|
27
28
|
this.clientId = null;
|
|
28
29
|
this.initiated = false;
|
|
29
30
|
this.sessionId = null;
|
|
31
|
+
this.shouldDeleteMessage = options.shouldDeleteMessage || "false";
|
|
30
32
|
this.defaultSearchPlatform = options.defaultSearchPlatform || "ytmsearch";
|
|
31
33
|
this.restVersion = options.restVersion || "v3";
|
|
32
34
|
this.plugins = options.plugins || [];
|
|
@@ -225,21 +227,28 @@ class Aqua extends EventEmitter {
|
|
|
225
227
|
* @param {Node} requestNode - The node that handled the request.
|
|
226
228
|
*/
|
|
227
229
|
loadTracks(response, requester, requestNode) {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
230
|
+
|
|
231
|
+
switch (response.loadType) {
|
|
232
|
+
case "track":
|
|
233
|
+
if (response.data) {
|
|
234
|
+
this.tracks.push(new Track(response.data, requester, requestNode));
|
|
235
|
+
}
|
|
236
|
+
break;
|
|
237
|
+
case "playlist":
|
|
238
|
+
this.tracks = response.data?.tracks?.map(track => new Track(track, requester, requestNode)) || [];
|
|
239
|
+
this.playlistInfo = {
|
|
240
|
+
name: response.data?.info?.name || response.data?.info?.title,
|
|
241
|
+
...response.data?.info,
|
|
242
|
+
} || null;
|
|
243
|
+
break;
|
|
244
|
+
case "search":
|
|
245
|
+
this.tracks = response.data?.map(track => new Track(track, requester, requestNode));
|
|
246
|
+
break;
|
|
238
247
|
}
|
|
248
|
+
|
|
239
249
|
this.loadType = response.loadType;
|
|
240
250
|
this.pluginInfo = response.pluginInfo || {};
|
|
241
251
|
}
|
|
242
|
-
|
|
243
252
|
/**
|
|
244
253
|
* Constructs the response object for the resolved tracks.
|
|
245
254
|
* @returns {Object} The constructed response.
|
|
@@ -254,6 +263,7 @@ class Aqua extends EventEmitter {
|
|
|
254
263
|
};
|
|
255
264
|
}
|
|
256
265
|
|
|
266
|
+
|
|
257
267
|
/**
|
|
258
268
|
* Gets the player associated with the specified guild ID.
|
|
259
269
|
* @param {string} guildId - The ID of the guild.
|
|
@@ -10,6 +10,8 @@ class Connection {
|
|
|
10
10
|
this.selfDeaf = false;
|
|
11
11
|
this.selfMute = false;
|
|
12
12
|
this.voiceChannel = player.voiceChannel;
|
|
13
|
+
this.lastUpdateTime = 0; // Track the last update time to throttle updates
|
|
14
|
+
this.updateThrottle = 1000; // Throttle updates to every 1000 ms (1 second)
|
|
13
15
|
}
|
|
14
16
|
|
|
15
17
|
/**
|
|
@@ -27,6 +29,7 @@ class Connection {
|
|
|
27
29
|
this.voice.endpoint = endpoint;
|
|
28
30
|
this.voice.token = token;
|
|
29
31
|
this.region = endpoint.split(".")[0].replace(/[0-9]/g, "");
|
|
32
|
+
|
|
30
33
|
this.player.aqua.emit("debug", `[Player ${this.player.guildId} - CONNECTION] ${previousVoiceRegion ? `Changed Voice Region from ${previousVoiceRegion} to ${this.region}` : `Voice Server: ${this.region}`}`);
|
|
31
34
|
|
|
32
35
|
if (this.player.paused) {
|
|
@@ -70,15 +73,15 @@ class Connection {
|
|
|
70
73
|
/**
|
|
71
74
|
* Updates the player voice data.
|
|
72
75
|
*/
|
|
73
|
-
updatePlayerVoiceData() {
|
|
74
|
-
this.player.nodes.rest.updatePlayer({
|
|
75
|
-
guildId: this.player.guildId,
|
|
76
|
-
data: {
|
|
77
|
-
voice: this.voice,
|
|
78
|
-
volume: this.player.volume
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
}
|
|
76
|
+
updatePlayerVoiceData() {
|
|
77
|
+
this.player.nodes.rest.updatePlayer({
|
|
78
|
+
guildId: this.player.guildId,
|
|
79
|
+
data: {
|
|
80
|
+
voice: this.voice,
|
|
81
|
+
volume: this.player.volume
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
83
86
|
|
|
84
|
-
module.exports = { Connection };
|
|
87
|
+
module.exports = { Connection };
|
package/build/structures/Node.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
const WebSocket = require("ws");
|
|
3
2
|
const { Rest } = require("./Rest");
|
|
4
3
|
|
|
@@ -19,22 +18,18 @@ class Node {
|
|
|
19
18
|
this.secure = nodes.secure || false;
|
|
20
19
|
this.sessionId = nodes.sessionId || null;
|
|
21
20
|
this.rest = new Rest(aqua, this);
|
|
22
|
-
|
|
23
21
|
this.wsUrl = `ws${this.secure ? 's' : ''}://${this.host}:${this.port}/v4/websocket`;
|
|
24
|
-
this.restUrl = `http${this.secure ? 's' : ''}://${this.host}:${this.port}`;
|
|
25
|
-
|
|
26
22
|
this.ws = null;
|
|
27
23
|
this.regions = nodes.regions || [];
|
|
28
24
|
this.info = null;
|
|
29
25
|
this.connected = false;
|
|
30
|
-
|
|
31
26
|
this.resumeKey = options.resumeKey || null;
|
|
32
27
|
this.resumeTimeout = options.resumeTimeout || 60;
|
|
33
28
|
this.autoResume = options.autoResume || false;
|
|
34
|
-
|
|
35
29
|
this.reconnectTimeout = options.reconnectTimeout || 5000;
|
|
36
30
|
this.reconnectTries = options.reconnectTries || 3;
|
|
37
31
|
this.reconnectAttempted = 0;
|
|
32
|
+
this.lastStatsRequest = 0; // Track the last time stats were requested
|
|
38
33
|
}
|
|
39
34
|
|
|
40
35
|
initializeStats() {
|
|
@@ -61,16 +56,9 @@ class Node {
|
|
|
61
56
|
};
|
|
62
57
|
}
|
|
63
58
|
|
|
64
|
-
/**
|
|
65
|
-
* Fetches the lavalink node's information.
|
|
66
|
-
* @param {Object} [options] Options to pass to the rest request.
|
|
67
|
-
* @param {boolean} [options.includeHeaders=false] Include headers in the response.
|
|
68
|
-
* @returns {Promise<Object>} The lavalink node's information.
|
|
69
|
-
*/
|
|
70
59
|
async fetchInfo(options = {}) {
|
|
71
60
|
return await this.rest.makeRequest("GET", `/v4/info`, null, options.includeHeaders);
|
|
72
61
|
}
|
|
73
|
-
|
|
74
62
|
|
|
75
63
|
async connect() {
|
|
76
64
|
if (this.ws) this.ws.close();
|
|
@@ -100,12 +88,12 @@ class Node {
|
|
|
100
88
|
async onOpen() {
|
|
101
89
|
this.connected = true;
|
|
102
90
|
this.aqua.emit('debug', this.name, `Connected to Lavalink at ${this.wsUrl}`);
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
91
|
+
try {
|
|
92
|
+
this.info = await this.fetchInfo();
|
|
93
|
+
} catch (err) {
|
|
94
|
+
this.aqua.emit('debug', `Failed to fetch info: ${err.message}`);
|
|
95
|
+
this.info = null;
|
|
96
|
+
}
|
|
109
97
|
|
|
110
98
|
if (!this.info && !this.aqua.bypassChecks.nodeFetchInfo) {
|
|
111
99
|
throw new Error(`Failed to fetch node info.`);
|
|
@@ -114,30 +102,26 @@ class Node {
|
|
|
114
102
|
if (this.autoResume) {
|
|
115
103
|
this.resumePlayers();
|
|
116
104
|
}
|
|
117
|
-
|
|
118
105
|
this.lastStats = 0;
|
|
119
106
|
}
|
|
120
107
|
|
|
121
108
|
async getStats() {
|
|
122
|
-
|
|
123
|
-
|
|
109
|
+
const now = Date.now();
|
|
110
|
+
if (now - this.lastStatsRequest < 5000) {
|
|
111
|
+
return this.stats; // Return cached stats if requested too soon
|
|
124
112
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
.catch(err => {
|
|
129
|
-
this.aqua.emit('debug', `Error fetching stats: ${err.message}`);
|
|
130
|
-
return null;
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
if (stats) {
|
|
113
|
+
|
|
114
|
+
try {
|
|
115
|
+
const stats = await this.rest.makeRequest("GET", `/v4/stats`);
|
|
134
116
|
this.stats = { ...this.stats, ...stats };
|
|
135
|
-
this.
|
|
117
|
+
this.lastStatsRequest = now; // Update last request time
|
|
118
|
+
return stats;
|
|
119
|
+
} catch (err) {
|
|
120
|
+
this.aqua.emit('debug', `Error fetching stats: ${err.message}`);
|
|
121
|
+
return this.stats; // Return last known stats on error
|
|
136
122
|
}
|
|
137
|
-
return stats;
|
|
138
123
|
}
|
|
139
124
|
|
|
140
|
-
|
|
141
125
|
resumePlayers() {
|
|
142
126
|
for (const player of this.aqua.players.values()) {
|
|
143
127
|
if (player.node === this) {
|
|
@@ -153,13 +137,10 @@ class Node {
|
|
|
153
137
|
onMessage(msg) {
|
|
154
138
|
if (Array.isArray(msg)) msg = Buffer.concat(msg);
|
|
155
139
|
if (msg instanceof ArrayBuffer) msg = Buffer.from(msg);
|
|
156
|
-
|
|
157
140
|
const payload = JSON.parse(msg.toString());
|
|
158
141
|
if (!payload.op) return;
|
|
159
|
-
|
|
160
142
|
this.aqua.emit("raw", "Node", payload);
|
|
161
143
|
this.aqua.emit("debug", this.name, `Received update: ${JSON.stringify(payload)}`);
|
|
162
|
-
|
|
163
144
|
this.handlePayload(payload);
|
|
164
145
|
}
|
|
165
146
|
|
|
@@ -201,7 +182,6 @@ class Node {
|
|
|
201
182
|
this.aqua.emit("nodeError", this, new Error(`Unable to connect after ${this.reconnectTries} attempts.`));
|
|
202
183
|
return this.destroy();
|
|
203
184
|
}
|
|
204
|
-
|
|
205
185
|
setTimeout(() => {
|
|
206
186
|
this.aqua.emit("nodeReconnect", this);
|
|
207
187
|
this.connect();
|
|
@@ -216,17 +196,13 @@ class Node {
|
|
|
216
196
|
this.aqua.nodes.delete(this.name);
|
|
217
197
|
return;
|
|
218
198
|
}
|
|
219
|
-
|
|
220
199
|
if (!this.connected) return;
|
|
221
|
-
|
|
222
200
|
this.aqua.players.forEach((player) => {
|
|
223
201
|
if (player.node === this) player.destroy();
|
|
224
202
|
});
|
|
225
|
-
|
|
226
203
|
if (this.ws) this.ws.close(1000, "destroy");
|
|
227
204
|
this.ws?.removeAllListeners();
|
|
228
205
|
this.ws = null;
|
|
229
|
-
|
|
230
206
|
this.aqua.emit("nodeDestroy", this);
|
|
231
207
|
this.aqua.nodeMap.delete(this.name);
|
|
232
208
|
this.connected = false;
|
|
@@ -255,4 +231,4 @@ class Node {
|
|
|
255
231
|
}
|
|
256
232
|
}
|
|
257
233
|
|
|
258
|
-
module.exports = { Node };
|
|
234
|
+
module.exports = { Node };
|
|
@@ -16,7 +16,7 @@ class Player extends EventEmitter {
|
|
|
16
16
|
* @param {number} [options.defaultVolume=100] - The default volume level (0-200).
|
|
17
17
|
* @param {string} [options.loop='none'] - The loop mode ('none', 'track', 'queue').
|
|
18
18
|
*/
|
|
19
|
-
constructor(aqua, nodes, options) {
|
|
19
|
+
constructor(aqua, nodes, options = {}) {
|
|
20
20
|
super();
|
|
21
21
|
this.aqua = aqua;
|
|
22
22
|
this.nodes = nodes;
|
|
@@ -40,6 +40,9 @@ class Player extends EventEmitter {
|
|
|
40
40
|
this.timestamp = 0;
|
|
41
41
|
this.ping = 0;
|
|
42
42
|
this.isAutoplay = false;
|
|
43
|
+
this.nowPlayingMessage = null;
|
|
44
|
+
|
|
45
|
+
this.shouldDeleteMessage = options.shouldDeleteMessage ?? true;
|
|
43
46
|
|
|
44
47
|
this.setupEventListeners();
|
|
45
48
|
}
|
|
@@ -62,7 +65,6 @@ class Player extends EventEmitter {
|
|
|
62
65
|
this.position = state.position;
|
|
63
66
|
this.ping = state.ping;
|
|
64
67
|
this.timestamp = state.time;
|
|
65
|
-
|
|
66
68
|
}
|
|
67
69
|
|
|
68
70
|
/**
|
|
@@ -83,18 +85,24 @@ class Player extends EventEmitter {
|
|
|
83
85
|
|
|
84
86
|
/**
|
|
85
87
|
* Plays the next track in the queue.
|
|
88
|
+
* @param {Object} options - Options for playing the next track.
|
|
89
|
+
* @param {string} options.query - The query to search for the next track.
|
|
90
|
+
* @param {boolean} options.force - Whether to force play the next track even if the queue is empty.
|
|
86
91
|
* @returns {Promise<Player>} The player instance.
|
|
87
92
|
* @throws {Error} If the player is not connected.
|
|
93
|
+
* @throws {Error} If the queue is empty and force is not set to true.
|
|
94
|
+
* @description This method plays the next track in the queue.
|
|
95
|
+
* @event play
|
|
88
96
|
*/
|
|
89
97
|
async play() {
|
|
90
|
-
if (!this.connected) throw new Error("
|
|
98
|
+
if (!this.connected) throw new Error("Bro go on and use the connection first");
|
|
99
|
+
if (!this.queue.length) return;
|
|
100
|
+
|
|
91
101
|
this.current = this.queue.shift();
|
|
92
|
-
if (!this.current) return this;
|
|
93
102
|
|
|
94
103
|
if (!this.current.track) {
|
|
95
104
|
this.current = await this.current.resolve(this.aqua);
|
|
96
105
|
}
|
|
97
|
-
|
|
98
106
|
this.playing = true;
|
|
99
107
|
this.position = 0;
|
|
100
108
|
|
|
@@ -102,6 +110,7 @@ class Player extends EventEmitter {
|
|
|
102
110
|
await this.updatePlayer({ track: { encoded: this.current.track } });
|
|
103
111
|
return this;
|
|
104
112
|
}
|
|
113
|
+
|
|
105
114
|
/**
|
|
106
115
|
* Connects the player to the voice channel.
|
|
107
116
|
* @param {Object} [options=this] - Connection options.
|
|
@@ -307,10 +316,12 @@ class Player extends EventEmitter {
|
|
|
307
316
|
* @param {Object} payload - The event payload.
|
|
308
317
|
*/
|
|
309
318
|
trackEnd(player, track, payload) {
|
|
310
|
-
this.
|
|
319
|
+
if (this.shouldDeleteMessage && this.nowPlayingMessage) {
|
|
320
|
+
this.nowPlayingMessage.delete();
|
|
321
|
+
this.nowPlayingMessage = null;
|
|
322
|
+
}
|
|
311
323
|
if (["loadfailed", "cleanup"].includes(payload.reason.replace("_", "").toLowerCase())) {
|
|
312
324
|
if (player.queue.length === 0) {
|
|
313
|
-
this.playing = false;
|
|
314
325
|
return this.aqua.emit("queueEnd", player);
|
|
315
326
|
}
|
|
316
327
|
this.aqua.emit("trackEnd", player, payload);
|
|
@@ -326,7 +337,6 @@ class Player extends EventEmitter {
|
|
|
326
337
|
return player.play();
|
|
327
338
|
}
|
|
328
339
|
if (player.queue.length === 0) {
|
|
329
|
-
this.playing = false;
|
|
330
340
|
return this.aqua.emit("queueEnd", player);
|
|
331
341
|
} else {
|
|
332
342
|
this.aqua.emit("trackEnd", player, payload);
|
|
@@ -439,4 +449,5 @@ class Player extends EventEmitter {
|
|
|
439
449
|
}
|
|
440
450
|
}
|
|
441
451
|
|
|
442
|
-
module.exports = { Player };
|
|
452
|
+
module.exports = { Player };
|
|
453
|
+
|
package/build/structures/Rest.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
const { fetch: undiciFetch } = require("undici");
|
|
2
|
-
const nodeUtil = require("node:util");
|
|
3
2
|
|
|
4
3
|
class Rest {
|
|
5
4
|
constructor(aqua, options) {
|
|
@@ -9,10 +8,10 @@ class Rest {
|
|
|
9
8
|
this.password = options.password;
|
|
10
9
|
this.version = options.restVersion;
|
|
11
10
|
this.calls = 0;
|
|
12
|
-
this.queue = [];
|
|
13
|
-
this.maxQueueSize = options.maxQueueSize || 100;
|
|
14
|
-
this.maxConcurrentRequests = options.maxConcurrentRequests || 5;
|
|
15
|
-
this.activeRequests = 0;
|
|
11
|
+
this.queue = [];
|
|
12
|
+
this.maxQueueSize = options.maxQueueSize || 100;
|
|
13
|
+
this.maxConcurrentRequests = options.maxConcurrentRequests || 5;
|
|
14
|
+
this.activeRequests = 0;
|
|
16
15
|
}
|
|
17
16
|
|
|
18
17
|
setSessionId(sessionId) {
|
|
@@ -24,22 +23,23 @@ class Rest {
|
|
|
24
23
|
"Content-Type": "application/json",
|
|
25
24
|
Authorization: this.password,
|
|
26
25
|
};
|
|
27
|
-
|
|
28
|
-
method,
|
|
29
|
-
headers,
|
|
30
|
-
body: body ? JSON.stringify(body) : null,
|
|
31
|
-
};
|
|
26
|
+
|
|
32
27
|
try {
|
|
33
|
-
const response = await undiciFetch(`${this.url}${endpoint}`,
|
|
28
|
+
const response = await undiciFetch(`${this.url}${endpoint}`, {
|
|
29
|
+
method,
|
|
30
|
+
headers,
|
|
31
|
+
body: body && JSON.stringify(body),
|
|
32
|
+
});
|
|
34
33
|
this.calls++;
|
|
35
34
|
const data = await this.parseResponse(response);
|
|
36
35
|
this.aqua.emit("apiResponse", endpoint, response);
|
|
37
36
|
this.aqua.emit(
|
|
38
37
|
"debug",
|
|
39
|
-
`[Rest] ${method} ${endpoint} ${body ? `body: ${JSON.stringify(body)}` : ""} -> Status Code: ${response.status} Response: ${
|
|
38
|
+
`[Rest] ${method} ${endpoint} ${body ? `body: ${JSON.stringify(body)}` : ""} -> Status Code: ${response.status} Response(body): ${JSON.stringify(data)}`
|
|
40
39
|
);
|
|
41
40
|
return includeHeaders ? { data, headers: response.headers } : data;
|
|
42
41
|
} catch (error) {
|
|
42
|
+
this.aqua.emit("debug", `Network error during request: ${method} ${this.url}${endpoint}`, { cause: error });
|
|
43
43
|
throw new Error(`Network error during request: ${method} ${this.url}${endpoint}`, { cause: error });
|
|
44
44
|
}
|
|
45
45
|
}
|
|
@@ -50,15 +50,18 @@ class Rest {
|
|
|
50
50
|
|
|
51
51
|
async updatePlayer(options) {
|
|
52
52
|
const requestBody = { ...options.data };
|
|
53
|
+
|
|
53
54
|
if ((requestBody.track && requestBody.track.encoded && requestBody.track.identifier) ||
|
|
54
55
|
(requestBody.encodedTrack && requestBody.identifier)) {
|
|
55
56
|
throw new Error(`Cannot provide both 'encoded' and 'identifier' for track in Update Player Endpoint`);
|
|
56
57
|
}
|
|
58
|
+
|
|
57
59
|
if (this.version === "v3" && options.data?.track) {
|
|
58
60
|
const { track } = requestBody;
|
|
59
61
|
delete requestBody.track;
|
|
60
62
|
Object.assign(requestBody, track.encoded ? { encodedTrack: track.encoded } : { identifier: track.identifier });
|
|
61
63
|
}
|
|
64
|
+
|
|
62
65
|
return this.makeRequest("PATCH", `/${this.version}/sessions/${this.sessionId}/players/${options.guildId}?noReplace=false`, requestBody);
|
|
63
66
|
}
|
|
64
67
|
|
|
@@ -70,7 +73,7 @@ class Rest {
|
|
|
70
73
|
return this.makeRequest("GET", `/${this.version}/loadtracks?identifier=${encodeURIComponent(identifier)}`);
|
|
71
74
|
}
|
|
72
75
|
|
|
73
|
-
async decodeTrack(track
|
|
76
|
+
async decodeTrack(track) {
|
|
74
77
|
return this.makeRequest("GET", `/${this.version}/decodetrack?encodedTrack=${encodeURIComponent(track)}`);
|
|
75
78
|
}
|
|
76
79
|
|
|
@@ -79,10 +82,7 @@ class Rest {
|
|
|
79
82
|
}
|
|
80
83
|
|
|
81
84
|
async getStats() {
|
|
82
|
-
|
|
83
|
-
return this.makeRequest("GET", `/${this.version}/stats`);
|
|
84
|
-
}
|
|
85
|
-
return this.makeRequest("GET", `/${this.version}/stats/all`);
|
|
85
|
+
return this.makeRequest("GET", this.version === "v3" ? `/${this.version}/stats` : `/${this.version}/stats/all`);
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
async getInfo() {
|
|
@@ -98,23 +98,19 @@ class Rest {
|
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
async parseResponse(response) {
|
|
101
|
-
if (response.status === 204)
|
|
102
|
-
return null;
|
|
103
|
-
}
|
|
101
|
+
if (response.status === 204) return null;
|
|
104
102
|
try {
|
|
105
|
-
|
|
106
|
-
return await response[contentType.includes("text/plain") ? "text" : "json"]();
|
|
103
|
+
return response.headers.get("Content-Type").includes("text/plain") ? await response.text() : await response.json();
|
|
107
104
|
} catch (error) {
|
|
108
105
|
this.aqua.emit("debug", `[Rest - Error] Failed to process response from ${response.url}: ${error}`);
|
|
109
106
|
return null;
|
|
110
107
|
}
|
|
111
108
|
}
|
|
112
|
-
|
|
113
|
-
* Cleans up resources related to the queue.
|
|
114
|
-
*/
|
|
109
|
+
|
|
115
110
|
cleanupQueue() {
|
|
116
|
-
this.queue = [];
|
|
111
|
+
this.queue = [];
|
|
117
112
|
}
|
|
118
113
|
}
|
|
119
114
|
|
|
120
|
-
module.exports = { Rest };
|
|
115
|
+
module.exports = { Rest };
|
|
116
|
+
|
|
@@ -7,7 +7,7 @@ const { getImageUrl } = require("../handlers/fetchImage");
|
|
|
7
7
|
*/
|
|
8
8
|
class Track {
|
|
9
9
|
/**
|
|
10
|
-
* @param {{ encoded: string, info: { identifier: string, isSeekable: boolean, author: string, length: number, isStream: boolean, position: number, title: string, uri: string, sourceName: string,
|
|
10
|
+
* @param {{ encoded: string, info: { identifier: string, isSeekable: boolean, author: string, length: number, isStream: boolean, position: number, title: string, uri: string, sourceName: string, artworkUrl: string, track: string, tracks: Array<Track>, playlist: { name: string, selectedTrack: number } } }} data
|
|
11
11
|
* @param {Player} requester
|
|
12
12
|
* @param {Node} nodes
|
|
13
13
|
*/
|
|
@@ -17,6 +17,7 @@ class Track {
|
|
|
17
17
|
this.requester = requester;
|
|
18
18
|
this.nodes = nodes;
|
|
19
19
|
this.track = data.encoded || Buffer.from(data.track, "base64").toString("utf8");
|
|
20
|
+
this.playlist = data.playlist || null;
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
/**
|
|
@@ -62,14 +63,18 @@ class Track {
|
|
|
62
63
|
updateTrackInfo(track) {
|
|
63
64
|
this.info.identifier = track.info.identifier;
|
|
64
65
|
this.track = track.track;
|
|
66
|
+
if (track.playlist) {
|
|
67
|
+
this.playlist = track.playlist;
|
|
68
|
+
}
|
|
65
69
|
}
|
|
66
70
|
|
|
67
71
|
/**
|
|
68
72
|
* @private
|
|
69
73
|
*/
|
|
70
74
|
cleanup() {
|
|
71
|
-
this.rawData = this.track = this.info = null;
|
|
75
|
+
this.rawData = this.track = this.info = this.playlist = null;
|
|
72
76
|
}
|
|
73
77
|
}
|
|
74
78
|
|
|
75
79
|
module.exports = { Track };
|
|
80
|
+
|