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.
- package/build/handlers/autoplay.js +67 -66
- package/build/index.d.ts +170 -133
- package/build/index.js +3 -3
- package/build/structures/Aqua.js +65 -41
- package/build/structures/AquaRecovery.js +41 -10
- package/build/structures/AqualinkEvents.js +2 -0
- package/build/structures/Connection.js +9 -1
- package/build/structures/ConnectionRecovery.js +3 -38
- package/build/structures/Node.js +158 -80
- package/build/structures/Player.js +54 -23
- package/build/structures/PlayerLifecycle.js +10 -1
- package/build/structures/Reporting.js +12 -0
- package/build/structures/Rest.js +48 -42
- package/build/structures/Track.js +10 -3
- package/package.json +70 -70
package/build/structures/Rest.js
CHANGED
|
@@ -11,10 +11,7 @@ const {
|
|
|
11
11
|
zstdDecompressSync
|
|
12
12
|
} = require('node:zlib')
|
|
13
13
|
|
|
14
|
-
|
|
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 (
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
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)
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
511
|
-
|
|
512
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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
|
|
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.
|
|
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.
|
|
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
|
+
}
|