aqualink 3.1.0 → 3.2.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.
@@ -11,10 +11,7 @@ const {
11
11
  zstdDecompressSync
12
12
  } = require('node:zlib')
13
13
 
14
- let autoplayModule = null
15
- try {
16
- autoplayModule = require('../handlers/autoplay')
17
- } catch {}
14
+ const { emitOperationalError } = require('./Reporting')
18
15
 
19
16
  const unrefTimer = (t) => {
20
17
  try {
@@ -90,7 +87,6 @@ const _functions = {
90
87
  parseBody(data, contentType, forceJson) {
91
88
  const isJson = forceJson || this.isJsonContent(contentType)
92
89
  if (isJson) {
93
- if (typeof data === 'string') return JSON.parse(data)
94
90
  return JSON.parse(data)
95
91
  }
96
92
  return typeof data === 'string' ? data : data.toString(UTF8)
@@ -209,21 +205,18 @@ class Rest {
209
205
  this.agent = new (node.ssl ? HttpsAgent : HttpAgent)(opts)
210
206
  this.request = node.ssl ? httpsRequest : httpRequest
211
207
 
212
- if (autoplayModule?.setSharedAgent) {
213
- if (node.ssl) {
214
- this._autoplayAgent = this.agent
215
- } else {
216
- this._autoplayAgent = new HttpsAgent({
217
- keepAlive: true,
218
- maxSockets: node.maxSockets || 128,
219
- maxFreeSockets: node.maxFreeSockets || 64,
220
- freeSocketTimeout: node.freeSocketTimeout || 15000,
221
- keepAliveMsecs: node.keepAliveMsecs || 500,
222
- scheduling: 'lifo',
223
- timeout: this.timeout
224
- })
225
- }
226
- autoplayModule.setSharedAgent(this._autoplayAgent)
208
+ if (node.ssl) {
209
+ this._autoplayAgent = this.agent
210
+ } else {
211
+ this._autoplayAgent = new HttpsAgent({
212
+ keepAlive: true,
213
+ maxSockets: node.maxSockets || 128,
214
+ maxFreeSockets: node.maxFreeSockets || 64,
215
+ freeSocketTimeout: node.freeSocketTimeout || 15000,
216
+ keepAliveMsecs: node.keepAliveMsecs || 500,
217
+ scheduling: 'lifo',
218
+ timeout: this.timeout
219
+ })
227
220
  }
228
221
 
229
222
  const origCreate = this.agent.createConnection.bind(this.agent)
@@ -280,7 +273,7 @@ class Rest {
280
273
  }
281
274
  }
282
275
 
283
- _collectBody(stream, preallocSize = 0) {
276
+ _collectBody(stream, preallocSize = 0, source = stream) {
284
277
  return new Promise((resolve, reject) => {
285
278
  let done = false
286
279
  let size = 0
@@ -313,7 +306,11 @@ class Rest {
313
306
  size += chunk.length
314
307
  chunks.push(chunk)
315
308
  }
316
- if (size > MAX_RESPONSE_SIZE) finish(false, ERRORS.RESPONSE_TOO_LARGE)
309
+ if (size > MAX_RESPONSE_SIZE) {
310
+ stream.destroy?.(ERRORS.RESPONSE_TOO_LARGE)
311
+ if (source !== stream) source.destroy?.(ERRORS.RESPONSE_TOO_LARGE)
312
+ finish(false, ERRORS.RESPONSE_TOO_LARGE)
313
+ }
317
314
  })
318
315
 
319
316
  stream.once('error', (e) => finish(false, e))
@@ -423,7 +420,7 @@ class Rest {
423
420
 
424
421
  const clInt = cl ? parseInt(cl, 10) : 0
425
422
  if (clInt > MAX_RESPONSE_SIZE) {
426
- res.resume()
423
+ res.destroy(ERRORS.RESPONSE_TOO_LARGE)
427
424
  return finish(false, ERRORS.RESPONSE_TOO_LARGE)
428
425
  }
429
426
 
@@ -481,7 +478,7 @@ class Rest {
481
478
  preallocSize = clInt
482
479
  }
483
480
 
484
- this._collectBody(stream, preallocSize)
481
+ this._collectBody(stream, preallocSize, res)
485
482
  .then((buffer) => {
486
483
  if (!buffer) return finish(true, null)
487
484
  finalize(buffer)
@@ -491,6 +488,10 @@ class Rest {
491
488
  )
492
489
 
493
490
  req.once('error', (e) => finish(false, e))
491
+ req.setTimeout(this.timeout, () => {
492
+ req.destroy()
493
+ finish(false, new Error(`Socket timeout: ${this.timeout}ms`))
494
+ })
494
495
  timer = setTimeout(
495
496
  () => finish(false, new Error(`Request timeout: ${this.timeout}ms`)),
496
497
  this.timeout
@@ -503,13 +504,14 @@ class Rest {
503
504
  _getH2Session() {
504
505
  if (!this._h2 || this._h2.closed || this._h2.destroyed) {
505
506
  this._clearH2()
506
- this._h2 = http2.connect(this.baseUrl, this._tlsOptions || undefined)
507
+ const session = http2.connect(this.baseUrl, this._tlsOptions || undefined)
508
+ this._h2 = session
507
509
  this._resetH2Timer()
508
510
 
509
- const onEnd = () => this._clearH2()
510
- this._h2.once('error', onEnd)
511
- this._h2.once('close', onEnd)
512
- this._h2.socket?.unref?.()
511
+ const onEnd = () => this._clearH2(session)
512
+ session.once('error', onEnd)
513
+ session.once('close', onEnd)
514
+ session.socket?.unref?.()
513
515
  }
514
516
  return this._h2
515
517
  }
@@ -520,12 +522,14 @@ class Rest {
520
522
  this._h2Timer = null
521
523
  }
522
524
  if (this._h2 && !this._h2.closed && !this._h2.destroyed) {
523
- this._h2Timer = setTimeout(() => this._closeH2(), H2_TIMEOUT)
525
+ const session = this._h2
526
+ this._h2Timer = setTimeout(() => this._closeH2(session), H2_TIMEOUT)
524
527
  unrefTimer(this._h2Timer)
525
528
  }
526
529
  }
527
530
 
528
- _clearH2() {
531
+ _clearH2(session = this._h2) {
532
+ if (session !== this._h2) return
529
533
  if (this._h2Timer) {
530
534
  clearTimeout(this._h2Timer)
531
535
  this._h2Timer = null
@@ -533,7 +537,8 @@ class Rest {
533
537
  this._h2 = null
534
538
  }
535
539
 
536
- _closeH2() {
540
+ _closeH2(session = this._h2) {
541
+ if (session !== this._h2) return
537
542
  if (this._h2Timer) {
538
543
  clearTimeout(this._h2Timer)
539
544
  this._h2Timer = null
@@ -597,7 +602,7 @@ class Rest {
597
602
 
598
603
  const clInt = cl ? parseInt(cl, 10) : 0
599
604
  if (clInt > MAX_RESPONSE_SIZE) {
600
- req.resume()
605
+ req.close(http2.constants.NGHTTP2_CANCEL)
601
606
  return finish(false, ERRORS.RESPONSE_TOO_LARGE)
602
607
  }
603
608
 
@@ -630,7 +635,7 @@ class Rest {
630
635
 
631
636
  if (decomp) decomp.once('error', (e) => finish(false, e))
632
637
  req.once('error', (e) => finish(false, e))
633
- this._collectBody(stream, preallocSize)
638
+ this._collectBody(stream, preallocSize, req)
634
639
  .then((buffer) => {
635
640
  if (!buffer) return finish(true, null)
636
641
  finalize(buffer)
@@ -739,7 +744,7 @@ class Rest {
739
744
  const title = track?.info?.title
740
745
 
741
746
  if (!track || (!guildId && !hasEncoded && !title)) {
742
- this.aqua?.emit?.('error', '[Aqua/Lyrics] Invalid track object')
747
+ emitOperationalError(this.aqua, this.node, 'Invalid lyrics track object')
743
748
  return null
744
749
  }
745
750
 
@@ -833,9 +838,10 @@ class Rest {
833
838
  volume: options.volume !== undefined ? options.volume : 0.8
834
839
  }
835
840
 
841
+ const gen = this._sessionGeneration
836
842
  return this.makeRequest(
837
843
  'POST',
838
- `/v4/sessions/${this.sessionId}/players/${guildId}/mix`,
844
+ `${this._getSessionPath(gen)}/players/${guildId}/mix`,
839
845
  payload
840
846
  )
841
847
  }
@@ -843,9 +849,10 @@ class Rest {
843
849
  async getActiveMixer(guildId) {
844
850
  if (!this.node.isNodelink)
845
851
  throw new Error('Mixer endpoints are only available on Nodelink nodes')
852
+ const gen = this._sessionGeneration
846
853
  const response = await this.makeRequest(
847
854
  'GET',
848
- `/v4/sessions/${this.sessionId}/players/${guildId}/mix`
855
+ `${this._getSessionPath(gen)}/players/${guildId}/mix`
849
856
  )
850
857
  return response?.mixes || []
851
858
  }
@@ -856,9 +863,10 @@ class Rest {
856
863
  if (!guildId || !mix || typeof volume !== 'number')
857
864
  throw new Error('You forget to set the guild_id, mix or volume options')
858
865
 
866
+ const gen = this._sessionGeneration
859
867
  return this.makeRequest(
860
868
  'PATCH',
861
- `/v4/sessions/${this.sessionId}/players/${guildId}/mix/${mix}`,
869
+ `${this._getSessionPath(gen)}/players/${guildId}/mix/${mix}`,
862
870
  { volume }
863
871
  )
864
872
  }
@@ -869,9 +877,10 @@ class Rest {
869
877
  if (!guildId || !mix)
870
878
  throw new Error('You forget to set the guild_id and/or mix options')
871
879
 
880
+ const gen = this._sessionGeneration
872
881
  return this.makeRequest(
873
882
  'DELETE',
874
- `/v4/sessions/${this.sessionId}/players/${guildId}/mix/${mix}`
883
+ `${this._getSessionPath(gen)}/players/${guildId}/mix/${mix}`
875
884
  )
876
885
  }
877
886
 
@@ -885,9 +894,6 @@ class Rest {
885
894
  if (autoplayAgent && autoplayAgent !== primaryAgent) {
886
895
  autoplayAgent.destroy?.()
887
896
  }
888
- if (autoplayModule?.setSharedAgent && autoplayAgent) {
889
- autoplayModule.setSharedAgent(null)
890
- }
891
897
  this._closeH2()
892
898
  if (this._headerPool) {
893
899
  this._headerPool.length = 0
@@ -9,6 +9,7 @@ const _h = {
9
9
  class Track {
10
10
  constructor(data = {}, requester = null, node = null) {
11
11
  const info = data.info || {}
12
+ const pluginInfo = info.pluginInfo || data.pluginInfo || {}
12
13
 
13
14
  this.track = data.track || data.encoded || null
14
15
  this.identifier = _h.str(info.identifier)
@@ -21,14 +22,15 @@ class Track {
21
22
  this.uri = _h.str(info.uri)
22
23
  this.sourceName = _h.str(info.sourceName)
23
24
  this.artworkUrl = _h.str(info.artworkUrl)
24
- this.pluginInfo = info.pluginInfo || data.pluginInfo || {}
25
+ this.pluginInfo = pluginInfo
26
+ this.isrc = _h.str(info.isrc || pluginInfo.isrc) // ISRC support
25
27
 
26
28
  this.playlist = data.playlist || null
27
29
  this.node = node || data.node || null
28
30
  this.nodes = data.nodes || null
29
31
  this.requester = requester || null
30
32
  this._infoCache = null
31
- this._artworkCache = undefined // undefined = not computed, null = computed but no artwork
33
+ this._artworkCache = undefined
32
34
  }
33
35
 
34
36
  get info() {
@@ -43,7 +45,8 @@ class Track {
43
45
  title: this.title,
44
46
  uri: this.uri,
45
47
  sourceName: this.sourceName,
46
- artworkUrl: this.artworkUrl || this._computeArtwork()
48
+ artworkUrl: this.artworkUrl || this._computeArtwork(),
49
+ isrc: this.isrc || null // exposed here
47
50
  })
48
51
  return this._infoCache
49
52
  }
@@ -113,6 +116,9 @@ class Track {
113
116
  this.position = _h.num(fi.position, this.position)
114
117
  this.duration = _h.num(fi.length, this.duration)
115
118
  this.playlist = found.playlist ?? this.playlist
119
+ this.isrc = _h.str(
120
+ fi.isrc ?? fi.pluginInfo?.isrc ?? found.pluginInfo?.isrc ?? this.isrc
121
+ ) // keep ISRC
116
122
  this._infoCache = null
117
123
 
118
124
  return this
@@ -139,6 +145,7 @@ class Track {
139
145
  this.uri =
140
146
  this.sourceName =
141
147
  this.artworkUrl =
148
+ this.isrc =
142
149
  ''
143
150
  }
144
151
 
package/package.json CHANGED
@@ -1,70 +1,70 @@
1
- {
2
- "name": "aqualink",
3
- "version": "3.1.0",
4
- "description": "An Lavalink/Nodelink client, focused in pure performance and features",
5
- "main": "./build/index.js",
6
- "types": "./build/index.d.ts",
7
- "scripts": {
8
- "start": "node ./build/index.js"
9
- },
10
- "exports": {
11
- ".": {
12
- "require": "./build/index.js",
13
- "import": "./build/index.js",
14
- "types": "./build/index.d.ts"
15
- }
16
- },
17
- "keywords": [
18
- "lavalink",
19
- "lavalink-client",
20
- "client-wrapper",
21
- "discord.js",
22
- "node.js",
23
- "audio-streaming",
24
- "music-bot",
25
- "discord-integration",
26
- "high-performance",
27
- "scalable",
28
- "nodelink",
29
- "api",
30
- "discord",
31
- "lavalink.js",
32
- "discord.js",
33
- "lavalink-api",
34
- "cross-platform",
35
- "seamless-integration",
36
- "community-support",
37
- "open-source",
38
- "opus"
39
- ],
40
- "author": "mushroom0162 (https://github.com/ToddyTheNoobDud)",
41
- "license": "ISC",
42
- "repository": {
43
- "type": "git",
44
- "url": "git+https://github.com/ToddyTheNoobDud/AquaLink.git"
45
- },
46
- "homepage": "https://aqualink-6006388d.mintlify.app/",
47
- "dependencies": {
48
- "ws": "^8.19.0"
49
- },
50
- "contributors": [
51
- {
52
- "name": "mushroom0162",
53
- "url": "https://github.com/ToddyTheNoobDud"
54
- },
55
- {
56
- "name": "SoulDevs",
57
- "url": "https://github.com/SoulDevs"
58
- },
59
- {
60
- "name": "southctrl",
61
- "url": "https://github.com/southctrl"
62
- }
63
- ],
64
- "maintainers": [
65
- {
66
- "name": "mushroom0162",
67
- "url": "https://github.com/ToddyTheNoobDud"
68
- }
69
- ]
70
- }
1
+ {
2
+ "name": "aqualink",
3
+ "version": "3.2.0",
4
+ "description": "An Lavalink/Nodelink client, focused in pure performance and features",
5
+ "main": "./build/index.js",
6
+ "types": "./build/index.d.ts",
7
+ "scripts": {
8
+ "start": "node ./build/index.js"
9
+ },
10
+ "exports": {
11
+ ".": {
12
+ "require": "./build/index.js",
13
+ "import": "./build/index.js",
14
+ "types": "./build/index.d.ts"
15
+ }
16
+ },
17
+ "keywords": [
18
+ "lavalink",
19
+ "lavalink-client",
20
+ "client-wrapper",
21
+ "discord.js",
22
+ "node.js",
23
+ "audio-streaming",
24
+ "music-bot",
25
+ "discord-integration",
26
+ "high-performance",
27
+ "scalable",
28
+ "nodelink",
29
+ "api",
30
+ "discord",
31
+ "lavalink.js",
32
+ "discord.js",
33
+ "lavalink-api",
34
+ "cross-platform",
35
+ "seamless-integration",
36
+ "community-support",
37
+ "open-source",
38
+ "opus"
39
+ ],
40
+ "author": "mushroom0162 (https://github.com/ToddyTheNoobDud)",
41
+ "license": "ISC",
42
+ "repository": {
43
+ "type": "git",
44
+ "url": "git+https://github.com/ToddyTheNoobDud/AquaLink.git"
45
+ },
46
+ "homepage": "https://aqualink-6006388d.mintlify.app/",
47
+ "dependencies": {
48
+ "ws": "^8.21.1"
49
+ },
50
+ "contributors": [
51
+ {
52
+ "name": "mushroom0162",
53
+ "url": "https://github.com/ToddyTheNoobDud"
54
+ },
55
+ {
56
+ "name": "SoulDevs",
57
+ "url": "https://github.com/SoulDevs"
58
+ },
59
+ {
60
+ "name": "southctrl",
61
+ "url": "https://github.com/southctrl"
62
+ }
63
+ ],
64
+ "maintainers": [
65
+ {
66
+ "name": "mushroom0162",
67
+ "url": "https://github.com/ToddyTheNoobDud"
68
+ }
69
+ ]
70
+ }