aqualink 2.0.1 → 2.0.2

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 CHANGED
@@ -23,12 +23,19 @@ This code is based in riffy, but its an 100% Rewrite made from scratch...
23
23
  - https://github.com/DRSchlaubi/lyrics.kt (?)
24
24
  - https://github.com/DuncteBot/java-timed-lyrics (RECOMMENDED)
25
25
 
26
- # Tralalero Tralala 2.0.1 Released
26
+ # Tralalero Tralala 2.0.2 Released
27
27
  ---
28
-
29
- ### Now aqualink is 100% depedency free!
30
- - Use ws for websocket (much more stable, better performance)
31
- - Added http2 support on rest
28
+ - Updated the `PLAYER` module
29
+ - Now uses Set() and WeakMap()
30
+ - More simple logic
31
+ - Improved error handling, and also a bit of memory management
32
+ - Rewrite the shuffle() method to use Fisher-Yates shuffle
33
+ - Fix updatePlayer sending an extra pause request
34
+ - Improved the clean up system (correctly uses clearData now)
35
+
36
+ - Updated the `NODE` module
37
+ - Optimized stats creating / reusing
38
+ - Some stuff i made on the reconnecting system
32
39
 
33
40
  # Docs (Wiki)
34
41
  - https://github.com/ToddyTheNoobDud/AquaLink/wiki
@@ -37,16 +37,7 @@ class Node {
37
37
  this.infiniteReconnects = options.infiniteReconnects || false;
38
38
  this.connected = false;
39
39
  this.info = null;
40
- this.defaultStats = this.#createDefaultStats();
41
- this.stats = { ...this.defaultStats };
42
- this._onOpen = this.#onOpen.bind(this);
43
- this._onError = this.#onError.bind(this);
44
- this._onMessage = this.#onMessage.bind(this);
45
- this._onClose = this.#onClose.bind(this);
46
- }
47
-
48
- #createDefaultStats() {
49
- return {
40
+ this.stats = {
50
41
  players: 0,
51
42
  playingPlayers: 0,
52
43
  uptime: 0,
@@ -55,8 +46,13 @@ class Node {
55
46
  frameStats: { sent: 0, nulled: 0, deficit: 0 },
56
47
  ping: 0
57
48
  };
49
+ this._onOpen = this.#onOpen.bind(this);
50
+ this._onError = this.#onError.bind(this);
51
+ this._onMessage = this.#onMessage.bind(this);
52
+ this._onClose = this.#onClose.bind(this);
58
53
  }
59
54
 
55
+
60
56
  async connect() {
61
57
  this.#ws = new WebSocket(this.wsUrl.href, {
62
58
  headers: this.#constructHeaders(),
@@ -97,10 +93,8 @@ class Node {
97
93
  }
98
94
 
99
95
  async getStats() {
100
- const stats = await this.rest.getStats();
101
- if (JSON.stringify(this.stats) !== JSON.stringify({ ...this.defaultStats, ...stats })) {
102
- this.stats = { ...this.defaultStats, ...stats };
103
- }
96
+ const newStats = await this.rest.getStats();
97
+ Object.assign(this.stats, newStats);
104
98
  return this.stats;
105
99
  }
106
100
 
@@ -141,48 +135,41 @@ class Node {
141
135
 
142
136
  #updateStats(payload) {
143
137
  if (!payload) return;
144
- const newStats = {
145
- ...this.stats,
146
- ...payload,
147
- memory: this.#updateMemoryStats(payload.memory),
148
- cpu: this.#updateCpuStats(payload.cpu),
149
- frameStats: this.#updateFrameStats(payload.frameStats)
150
- };
151
- if (JSON.stringify(this.stats) !== JSON.stringify(newStats)) {
152
- this.stats = newStats;
153
- }
154
- }
155
138
 
156
- #updateMemoryStats(memory = {}) {
157
- const allocated = memory.allocated || 0;
158
- const free = memory.free || 0;
159
- const used = memory.used || 0;
160
- return {
139
+ this.stats.players = payload.players || this.stats.players;
140
+ this.stats.playingPlayers = payload.playingPlayers || this.stats.playingPlayers;
141
+ this.stats.uptime = payload.uptime || this.stats.uptime;
142
+ this.stats.ping = payload.ping || this.stats.ping;
143
+
144
+ const memory = payload.memory || {};
145
+ const allocated = memory.allocated || this.stats.memory.allocated;
146
+ const free = memory.free || this.stats.memory.free;
147
+ const used = memory.used || this.stats.memory.used;
148
+
149
+ this.stats.memory = {
161
150
  free,
162
151
  used,
163
152
  allocated,
164
- reservable: memory.reservable || 0,
165
- freePercentage: allocated ? (free / allocated) * 100 : 0,
166
- usedPercentage: allocated ? (used / allocated) * 100 : 0
153
+ reservable: memory.reservable || this.stats.memory.reservable,
154
+ freePercentage: allocated ? (free / allocated) * 100 : this.stats.memory.freePercentage,
155
+ usedPercentage: allocated ? (used / allocated) * 100 : this.stats.memory.usedPercentage
167
156
  };
168
- }
169
157
 
170
- #updateCpuStats(cpu = {}) {
171
- const cores = cpu.cores || 0;
172
- return {
158
+ const cpu = payload.cpu || {};
159
+ const cores = cpu.cores || this.stats.cpu.cores;
160
+
161
+ this.stats.cpu = {
173
162
  cores,
174
- systemLoad: cpu.systemLoad || 0,
175
- lavalinkLoad: cpu.lavalinkLoad || 0,
176
- lavalinkLoadPercentage: cores ? (cpu.lavalinkLoad / cores) * 100 : 0
163
+ systemLoad: cpu.systemLoad || this.stats.cpu.systemLoad,
164
+ lavalinkLoad: cpu.lavalinkLoad || this.stats.cpu.lavalinkLoad,
165
+ lavalinkLoadPercentage: cores ? (cpu.lavalinkLoad / cores) * 100 : this.stats.cpu.lavalinkLoadPercentage
177
166
  };
178
- }
179
167
 
180
- #updateFrameStats(frameStats = {}) {
181
- if (!frameStats) return { sent: 0, nulled: 0, deficit: 0 };
182
- return {
183
- sent: frameStats.sent || 0,
184
- nulled: frameStats.nulled || 0,
185
- deficit: frameStats.deficit || 0
168
+ const frameStats = payload.frameStats || {};
169
+ this.stats.frameStats = {
170
+ sent: frameStats.sent || this.stats.frameStats.sent,
171
+ nulled: frameStats.nulled || this.stats.frameStats.nulled,
172
+ deficit: frameStats.deficit || this.stats.frameStats.deficit
186
173
  };
187
174
  }
188
175
 
@@ -11,6 +11,7 @@ class Player extends EventEmitter {
11
11
  TRACK: "track",
12
12
  QUEUE: "queue"
13
13
  });
14
+
14
15
  static EVENT_HANDLERS = Object.freeze({
15
16
  TrackStartEvent: "trackStart",
16
17
  TrackEndEvent: "trackEnd",
@@ -19,7 +20,8 @@ class Player extends EventEmitter {
19
20
  TrackChangeEvent: "trackChange",
20
21
  WebSocketClosedEvent: "socketClosed"
21
22
  });
22
- static validModes = ["none", "track", "queue"]
23
+
24
+ static validModes = new Set(Object.values(Player.LOOP_MODES));
23
25
 
24
26
  constructor(aqua, nodes, options = {}) {
25
27
  super();
@@ -31,7 +33,7 @@ class Player extends EventEmitter {
31
33
  this.connection = new Connection(this);
32
34
  this.filters = new Filters(this);
33
35
  this.volume = Math.min(Math.max(options.defaultVolume ?? 100, 0), 200);
34
- this.loop = Player.LOOP_MODES[options.loop?.toUpperCase()] || Player.LOOP_MODES.NONE;
36
+ this.loop = Player.validModes.has(options.loop) ? options.loop : Player.LOOP_MODES.NONE;
35
37
  this.queue = new Queue();
36
38
  this.previousTracks = [];
37
39
  this.shouldDeleteMessage = options.shouldDeleteMessage ?? false;
@@ -45,23 +47,19 @@ class Player extends EventEmitter {
45
47
  this.ping = 0;
46
48
  this.nowPlayingMessage = null;
47
49
 
48
- this.onPlayerUpdate = ({ state }) => state && Object.assign(this, state) && this.aqua.emit("playerUpdate", this, { state });
49
- this.handleEvent = async (payload) => {
50
- const player = this.aqua.players.get(payload.guildId);
51
- if (!player) return;
50
+ this.on("playerUpdate", ({ state }) => {
51
+ if (state) Object.assign(this, state);
52
+ this.aqua.emit("playerUpdate", this, { state });
53
+ });
54
+
55
+ this.on("event", async (payload) => {
52
56
  const handler = Player.EVENT_HANDLERS[payload.type];
53
57
  if (handler && typeof this[handler] === "function") {
54
- await this[handler](player, this.current, payload);
58
+ await this[handler](this, this.current, payload);
55
59
  } else {
56
60
  this.handleUnknownEvent(payload);
57
61
  }
58
- };
59
- if (!this.listenerCount("playerUpdate")) {
60
- this.on("playerUpdate", this.onPlayerUpdate);
61
- }
62
- if (!this.listenerCount("event")) {
63
- this.on("event", this.handleEvent);
64
- }
62
+ });
65
63
  }
66
64
 
67
65
  get previous() {
@@ -107,11 +105,13 @@ class Player extends EventEmitter {
107
105
  this.nowPlayingMessage?.delete().catch(() => { });
108
106
  this.aqua.destroyPlayer(this.guildId);
109
107
  this.nodes.rest.destroyPlayer(this.guildId);
108
+ this.clearData();
110
109
  this.removeAllListeners();
111
110
  return this;
112
111
  }
113
112
 
114
113
  pause(paused) {
114
+ if (this.paused === paused) return this;
115
115
  this.paused = paused;
116
116
  this.updatePlayer({ paused });
117
117
  return this;
@@ -184,7 +184,10 @@ class Player extends EventEmitter {
184
184
  return this;
185
185
  }
186
186
  shuffle() {
187
- this.queue = this.queue.sort(() => Math.random() - 0.5);
187
+ for (let i = this.queue.length - 1; i > 0; i--) {
188
+ const j = Math.floor(Math.random() * (i + 1));
189
+ [this.queue[i], this.queue[j]] = [this.queue[j], this.queue[i]];
190
+ }
188
191
  return this;
189
192
  }
190
193
 
@@ -213,14 +216,16 @@ class Player extends EventEmitter {
213
216
 
214
217
  async trackEnd(player, track, payload) {
215
218
  if (this.shouldDeleteMessage && this.nowPlayingMessage) {
216
- await this.nowPlayingMessage.delete().catch(() => { });
217
- this.nowPlayingMessage = null;
219
+ try {
220
+ await this.nowPlayingMessage.delete();
221
+ this.nowPlayingMessage = null;
222
+ } catch {}
218
223
  }
219
224
 
220
225
  const reason = payload.reason?.replace("_", "").toLowerCase();
221
-
222
- if (reason === "loadfailed" || reason === "cleanup") {
223
- if (player.queue.isEmpty()) {
226
+ if (["loadfailed", "cleanup"].includes(reason)) {
227
+ if (!player.queue.length) {
228
+ this.clearData();
224
229
  this.aqua.emit("queueEnd", player);
225
230
  } else {
226
231
  await player.play();
@@ -228,20 +233,16 @@ class Player extends EventEmitter {
228
233
  return;
229
234
  }
230
235
 
231
- switch (this.loop) {
232
- case Player.LOOP_MODES.TRACK:
233
- this.aqua.emit("trackRepeat", player, track);
234
- player.queue.unshift(track);
235
- break;
236
- case Player.LOOP_MODES.QUEUE:
237
- this.aqua.emit("queueRepeat", player, track);
238
- player.queue.push(track);
239
- break;
236
+ if (this.loop === Player.LOOP_MODES.TRACK) {
237
+ player.queue.unshift(track);
238
+ } else if (this.loop === Player.LOOP_MODES.QUEUE) {
239
+ player.queue.push(track);
240
240
  }
241
241
 
242
242
  if (player.queue.isEmpty()) {
243
243
  this.playing = false;
244
244
  if (this.leaveOnEnd) {
245
+ this.clearData();
245
246
  this.cleanup();
246
247
  }
247
248
  this.aqua.emit("queueEnd", player);
@@ -290,11 +291,11 @@ class Player extends EventEmitter {
290
291
  }
291
292
 
292
293
  clearData() {
294
+ if (this.previousTracks) this.previousTracks.length = 0;
293
295
  this.#dataStore = new WeakMap();
294
296
  return this;
295
297
  }
296
298
 
297
-
298
299
  updatePlayer(data) {
299
300
  return this.nodes.rest.updatePlayer({ guildId: this.guildId, data });
300
301
  }
@@ -313,7 +314,6 @@ class Player extends EventEmitter {
313
314
  updateTrackState(playing, paused) {
314
315
  this.playing = playing;
315
316
  this.paused = paused;
316
- this.updatePlayer({ paused });
317
317
  }
318
318
  }
319
319
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aqualink",
3
- "version": "2.0.1",
3
+ "version": "2.0.2",
4
4
  "description": "An Lavalink client, focused in pure performance and features",
5
5
  "main": "build/index.js",
6
6
  "types": "index.d.ts",