aqualink 2.18.1 → 2.19.1
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 +148 -121
- package/build/handlers/fetchImage.js +152 -148
- package/build/index.d.ts +1401 -1080
- package/build/index.js +23 -12
- package/build/structures/Aqua.js +1085 -896
- package/build/structures/AqualinkEvents.js +43 -45
- package/build/structures/Connection.js +576 -483
- package/build/structures/Filters.js +351 -244
- package/build/structures/Node.js +666 -548
- package/build/structures/Player.js +1143 -904
- package/build/structures/Plugins.js +10 -11
- package/build/structures/Queue.js +129 -111
- package/build/structures/Rest.js +856 -645
- package/build/structures/Track.js +158 -129
- package/package.json +1 -1
package/build/structures/Rest.js
CHANGED
|
@@ -1,646 +1,857 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const {
|
|
4
|
-
const
|
|
5
|
-
const {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const
|
|
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
|
-
if (
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
if (
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
if (
|
|
93
|
-
if (
|
|
94
|
-
return
|
|
95
|
-
}
|
|
96
|
-
return
|
|
97
|
-
},
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
this.
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
'
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
this.
|
|
145
|
-
this.
|
|
146
|
-
|
|
147
|
-
this.
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
this.
|
|
175
|
-
this.
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
this.
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
this.
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
handleResponse(
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
}
|
|
617
|
-
|
|
618
|
-
async
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
1
|
+
const { Buffer } = require('node:buffer')
|
|
2
|
+
const { Agent: HttpsAgent, request: httpsRequest } = require('node:https')
|
|
3
|
+
const { Agent: HttpAgent, request: httpRequest } = require('node:http')
|
|
4
|
+
const http2 = require('node:http2')
|
|
5
|
+
const {
|
|
6
|
+
createBrotliDecompress,
|
|
7
|
+
createUnzip,
|
|
8
|
+
brotliDecompressSync,
|
|
9
|
+
unzipSync,
|
|
10
|
+
createZstdDecompress,
|
|
11
|
+
zstdDecompressSync
|
|
12
|
+
} = require('node:zlib')
|
|
13
|
+
|
|
14
|
+
let autoplayModule = null
|
|
15
|
+
try {
|
|
16
|
+
autoplayModule = require('../handlers/autoplay')
|
|
17
|
+
} catch {}
|
|
18
|
+
|
|
19
|
+
const unrefTimer = (t) => {
|
|
20
|
+
try {
|
|
21
|
+
t?.unref?.()
|
|
22
|
+
} catch {}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const HAS_ZSTD =
|
|
26
|
+
typeof createZstdDecompress === 'function' &&
|
|
27
|
+
typeof zstdDecompressSync === 'function'
|
|
28
|
+
|
|
29
|
+
const BASE64_LOOKUP = new Uint8Array(256)
|
|
30
|
+
for (let i = 65; i <= 90; i++) BASE64_LOOKUP[i] = 1
|
|
31
|
+
for (let i = 97; i <= 122; i++) BASE64_LOOKUP[i] = 1
|
|
32
|
+
for (let i = 48; i <= 57; i++) BASE64_LOOKUP[i] = 1
|
|
33
|
+
BASE64_LOOKUP[43] =
|
|
34
|
+
BASE64_LOOKUP[47] =
|
|
35
|
+
BASE64_LOOKUP[61] =
|
|
36
|
+
BASE64_LOOKUP[95] =
|
|
37
|
+
BASE64_LOOKUP[45] =
|
|
38
|
+
1
|
|
39
|
+
|
|
40
|
+
const ENCODING_NONE = 0,
|
|
41
|
+
ENCODING_BR = 1,
|
|
42
|
+
ENCODING_GZIP = 2,
|
|
43
|
+
ENCODING_DEFLATE = 3,
|
|
44
|
+
ENCODING_ZSTD = 4
|
|
45
|
+
const MAX_RESPONSE_SIZE = 10485760
|
|
46
|
+
const COMPRESSION_MIN_SIZE = 1024
|
|
47
|
+
const API_VERSION = 'v4'
|
|
48
|
+
const UTF8 = 'utf8'
|
|
49
|
+
const JSON_CT = 'application/json'
|
|
50
|
+
const HTTP2_THRESHOLD = 1024
|
|
51
|
+
const MAX_HEADER_POOL = 10
|
|
52
|
+
const H2_TIMEOUT = 60000
|
|
53
|
+
|
|
54
|
+
const ERRORS = Object.freeze({
|
|
55
|
+
NO_SESSION: new Error('Session ID required'),
|
|
56
|
+
INVALID_TRACK: new Error('Invalid encoded track format'),
|
|
57
|
+
INVALID_TRACKS: new Error('One or more tracks have invalid format'),
|
|
58
|
+
RESPONSE_TOO_LARGE: new Error('Response too large'),
|
|
59
|
+
RESPONSE_ABORTED: new Error('Response aborted')
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
const _functions = {
|
|
63
|
+
isValidBase64(str) {
|
|
64
|
+
if (typeof str !== 'string' || !str) return false
|
|
65
|
+
const len = str.length
|
|
66
|
+
if (len % 4 === 1) return false
|
|
67
|
+
for (let i = 0; i < len; i++) {
|
|
68
|
+
if (!BASE64_LOOKUP[str.charCodeAt(i)]) return false
|
|
69
|
+
}
|
|
70
|
+
return true
|
|
71
|
+
},
|
|
72
|
+
|
|
73
|
+
getEncodingType(header) {
|
|
74
|
+
if (!header) return ENCODING_NONE
|
|
75
|
+
const c = header.charCodeAt(0)
|
|
76
|
+
|
|
77
|
+
if (c === 122 && header.startsWith('zstd')) return ENCODING_ZSTD
|
|
78
|
+
if (c === 120 && header.startsWith('x-zstd')) return ENCODING_ZSTD
|
|
79
|
+
|
|
80
|
+
if (c === 98 && header.startsWith('br')) return ENCODING_BR
|
|
81
|
+
if (c === 103 && header.startsWith('gzip')) return ENCODING_GZIP
|
|
82
|
+
if (c === 100 && header.startsWith('deflate')) return ENCODING_DEFLATE
|
|
83
|
+
return ENCODING_NONE
|
|
84
|
+
},
|
|
85
|
+
|
|
86
|
+
isJsonContent(ct) {
|
|
87
|
+
return ct && ct.charCodeAt(0) === 97 && ct.includes(JSON_CT)
|
|
88
|
+
},
|
|
89
|
+
|
|
90
|
+
parseBody(data, contentType, forceJson) {
|
|
91
|
+
const isJson = forceJson || this.isJsonContent(contentType)
|
|
92
|
+
if (isJson) {
|
|
93
|
+
if (typeof data === 'string') return JSON.parse(data)
|
|
94
|
+
return JSON.parse(data)
|
|
95
|
+
}
|
|
96
|
+
return typeof data === 'string' ? data : data.toString(UTF8)
|
|
97
|
+
},
|
|
98
|
+
|
|
99
|
+
createHttpError(status, method, url, headers, body, statusMessage) {
|
|
100
|
+
const err = new Error(`HTTP ${status} ${method} ${url}`)
|
|
101
|
+
err.statusCode = status
|
|
102
|
+
err.headers = headers
|
|
103
|
+
err.body = body
|
|
104
|
+
err.url = url
|
|
105
|
+
if (statusMessage !== undefined) err.statusMessage = statusMessage
|
|
106
|
+
return err
|
|
107
|
+
},
|
|
108
|
+
|
|
109
|
+
createDecompressor(type) {
|
|
110
|
+
if (type === ENCODING_ZSTD) {
|
|
111
|
+
if (!HAS_ZSTD)
|
|
112
|
+
throw new Error(
|
|
113
|
+
'Unsupported content-encoding: zstd (zlib zstd APIs not available in this Node runtime)'
|
|
114
|
+
)
|
|
115
|
+
return createZstdDecompress()
|
|
116
|
+
}
|
|
117
|
+
return type === ENCODING_BR ? createBrotliDecompress() : createUnzip()
|
|
118
|
+
},
|
|
119
|
+
|
|
120
|
+
decompressSync(buf, type) {
|
|
121
|
+
if (type === ENCODING_ZSTD) {
|
|
122
|
+
if (!HAS_ZSTD)
|
|
123
|
+
throw new Error(
|
|
124
|
+
'Unsupported content-encoding: zstd (zlib zstd APIs not available in this Node runtime)'
|
|
125
|
+
)
|
|
126
|
+
return zstdDecompressSync(buf)
|
|
127
|
+
}
|
|
128
|
+
return type === ENCODING_BR ? brotliDecompressSync(buf) : unzipSync(buf)
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
class Rest {
|
|
133
|
+
constructor(aqua, node) {
|
|
134
|
+
this.aqua = aqua
|
|
135
|
+
this.node = node
|
|
136
|
+
this.sessionId = node.sessionId
|
|
137
|
+
this.timeout = node.timeout || 30000
|
|
138
|
+
|
|
139
|
+
const protocol = node.ssl ? 'https:' : 'http:'
|
|
140
|
+
const host =
|
|
141
|
+
node.host.includes(':') && !node.host.startsWith('[')
|
|
142
|
+
? `[${node.host}]`
|
|
143
|
+
: node.host
|
|
144
|
+
this.baseUrl = `${protocol}//${host}:${node.port}`
|
|
145
|
+
this._apiBase = `/${API_VERSION}`
|
|
146
|
+
|
|
147
|
+
this._endpoints = Object.freeze({
|
|
148
|
+
loadtracks: `${this._apiBase}/loadtracks?identifier=`,
|
|
149
|
+
decodetrack: `${this._apiBase}/decodetrack?encodedTrack=`,
|
|
150
|
+
decodetracks: `${this._apiBase}/decodetracks`,
|
|
151
|
+
stats: `${this._apiBase}/stats`,
|
|
152
|
+
info: `${this._apiBase}/info`,
|
|
153
|
+
version: `${this._apiBase}/version`,
|
|
154
|
+
routeplanner: Object.freeze({
|
|
155
|
+
status: `${this._apiBase}/routeplanner/status`,
|
|
156
|
+
freeAddress: `${this._apiBase}/routeplanner/free/address`,
|
|
157
|
+
freeAll: `${this._apiBase}/routeplanner/free/all`
|
|
158
|
+
}),
|
|
159
|
+
lyrics: `${this._apiBase}/lyrics`
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
const acceptEncoding = HAS_ZSTD
|
|
163
|
+
? 'zstd, br, gzip, deflate'
|
|
164
|
+
: 'br, gzip, deflate'
|
|
165
|
+
|
|
166
|
+
this.defaultHeaders = Object.freeze({
|
|
167
|
+
Authorization: String(node.auth || node.password || ''),
|
|
168
|
+
Accept: 'application/json, */*;q=0.5',
|
|
169
|
+
'Accept-Encoding': acceptEncoding,
|
|
170
|
+
'User-Agent': `Aqualink/${aqua?.version || '1.0'} (Node.js ${process.version})`
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
this._headerPool = []
|
|
174
|
+
this._tlsOptions = null
|
|
175
|
+
this._setupAgent(node)
|
|
176
|
+
this.useHttp2 = !!aqua?.options?.useHttp2
|
|
177
|
+
this._h2 = null
|
|
178
|
+
this._h2Timer = null
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
_setupAgent(node) {
|
|
182
|
+
const opts = {
|
|
183
|
+
keepAlive: true,
|
|
184
|
+
maxSockets: node.maxSockets || 128,
|
|
185
|
+
maxFreeSockets: node.maxFreeSockets || 64,
|
|
186
|
+
freeSocketTimeout: node.freeSocketTimeout || 15000,
|
|
187
|
+
keepAliveMsecs: node.keepAliveMsecs || 500,
|
|
188
|
+
scheduling: 'lifo',
|
|
189
|
+
timeout: this.timeout
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (node.ssl) {
|
|
193
|
+
opts.maxCachedSessions = node.maxCachedSessions || 200
|
|
194
|
+
this._tlsOptions = Object.create(null)
|
|
195
|
+
if (node.rejectUnauthorized !== undefined)
|
|
196
|
+
this._tlsOptions.rejectUnauthorized = opts.rejectUnauthorized =
|
|
197
|
+
node.rejectUnauthorized
|
|
198
|
+
if (node.ca) this._tlsOptions.ca = opts.ca = node.ca
|
|
199
|
+
if (node.cert) this._tlsOptions.cert = opts.cert = node.cert
|
|
200
|
+
if (node.key) this._tlsOptions.key = opts.key = node.key
|
|
201
|
+
if (node.passphrase)
|
|
202
|
+
this._tlsOptions.passphrase = opts.passphrase = node.passphrase
|
|
203
|
+
if (node.servername) this._tlsOptions.servername = node.servername
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
this.agent = new (node.ssl ? HttpsAgent : HttpAgent)(opts)
|
|
207
|
+
this.request = node.ssl ? httpsRequest : httpRequest
|
|
208
|
+
|
|
209
|
+
if (node.ssl && autoplayModule?.setSharedAgent) {
|
|
210
|
+
autoplayModule.setSharedAgent(this.agent)
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const origCreate = this.agent.createConnection.bind(this.agent)
|
|
214
|
+
this.agent.createConnection = (options, cb) => {
|
|
215
|
+
const socket = origCreate(options, cb)
|
|
216
|
+
socket.setNoDelay(true)
|
|
217
|
+
socket.setKeepAlive(true, 500)
|
|
218
|
+
return socket
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
setSessionId(sessionId) {
|
|
223
|
+
this.sessionId = sessionId
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
_getSessionPath() {
|
|
227
|
+
if (!this.sessionId) throw ERRORS.NO_SESSION
|
|
228
|
+
return `${this._apiBase}/sessions/${this.sessionId}`
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
_buildHeaders(hasPayload, payloadLength) {
|
|
232
|
+
if (!hasPayload) return this.defaultHeaders
|
|
233
|
+
const h = this._headerPool.pop() || Object.create(null)
|
|
234
|
+
h.Authorization = this.defaultHeaders.Authorization
|
|
235
|
+
h.Accept = this.defaultHeaders.Accept
|
|
236
|
+
h['Accept-Encoding'] = this.defaultHeaders['Accept-Encoding']
|
|
237
|
+
h['User-Agent'] = this.defaultHeaders['User-Agent']
|
|
238
|
+
h['Content-Type'] = JSON_CT
|
|
239
|
+
h['Content-Length'] = payloadLength
|
|
240
|
+
return h
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
_returnHeaders(h) {
|
|
244
|
+
if (
|
|
245
|
+
h !== this.defaultHeaders &&
|
|
246
|
+
this._headerPool.length < MAX_HEADER_POOL
|
|
247
|
+
) {
|
|
248
|
+
h.Authorization =
|
|
249
|
+
h.Accept =
|
|
250
|
+
h['Accept-Encoding'] =
|
|
251
|
+
h['User-Agent'] =
|
|
252
|
+
h['Content-Type'] =
|
|
253
|
+
h['Content-Length'] =
|
|
254
|
+
null
|
|
255
|
+
this._headerPool.push(h)
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
async makeRequest(method, endpoint, body) {
|
|
260
|
+
const url = `${this.baseUrl}${endpoint}`
|
|
261
|
+
const payload =
|
|
262
|
+
body === undefined
|
|
263
|
+
? undefined
|
|
264
|
+
: typeof body === 'string'
|
|
265
|
+
? body
|
|
266
|
+
: JSON.stringify(body)
|
|
267
|
+
const payloadLen = payload ? Buffer.byteLength(payload, UTF8) : 0
|
|
268
|
+
const headers = this._buildHeaders(!!payload, payloadLen)
|
|
269
|
+
|
|
270
|
+
try {
|
|
271
|
+
const resp =
|
|
272
|
+
this.useHttp2 && payloadLen >= HTTP2_THRESHOLD
|
|
273
|
+
? await this._h2Request(method, endpoint, headers, payload)
|
|
274
|
+
: await this._h1Request(method, url, headers, payload)
|
|
275
|
+
return resp
|
|
276
|
+
} finally {
|
|
277
|
+
this._returnHeaders(headers)
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
_h1Request(method, url, headers, payload) {
|
|
282
|
+
return new Promise((resolve, reject) => {
|
|
283
|
+
let req,
|
|
284
|
+
timer,
|
|
285
|
+
done = false
|
|
286
|
+
let chunks = null,
|
|
287
|
+
size = 0,
|
|
288
|
+
prealloc = null
|
|
289
|
+
|
|
290
|
+
const finish = (ok, val) => {
|
|
291
|
+
if (done) return
|
|
292
|
+
done = true
|
|
293
|
+
if (timer) {
|
|
294
|
+
clearTimeout(timer)
|
|
295
|
+
timer = null
|
|
296
|
+
}
|
|
297
|
+
chunks = prealloc = null
|
|
298
|
+
if (req && !ok) req.destroy()
|
|
299
|
+
ok ? resolve(val) : reject(val)
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
req = this.request(
|
|
303
|
+
url,
|
|
304
|
+
{ method, headers, agent: this.agent, timeout: this.timeout },
|
|
305
|
+
(res) => {
|
|
306
|
+
if (timer) {
|
|
307
|
+
clearTimeout(timer)
|
|
308
|
+
timer = null
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
const status = res.statusCode || 0
|
|
312
|
+
const cl = res.headers['content-length']
|
|
313
|
+
const contentType = res.headers['content-type'] || ''
|
|
314
|
+
|
|
315
|
+
if (status === 204 || cl === '0') {
|
|
316
|
+
res.resume()
|
|
317
|
+
return finish(true, null)
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
const clInt = cl ? parseInt(cl, 10) : 0
|
|
321
|
+
if (clInt > MAX_RESPONSE_SIZE) {
|
|
322
|
+
res.resume()
|
|
323
|
+
return finish(false, ERRORS.RESPONSE_TOO_LARGE)
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const encoding = _functions.getEncodingType(
|
|
327
|
+
res.headers['content-encoding']
|
|
328
|
+
)
|
|
329
|
+
|
|
330
|
+
const handleResponse = (buffer) => {
|
|
331
|
+
if (buffer.length > MAX_RESPONSE_SIZE)
|
|
332
|
+
return finish(false, ERRORS.RESPONSE_TOO_LARGE)
|
|
333
|
+
|
|
334
|
+
try {
|
|
335
|
+
const result = _functions.parseBody(buffer, contentType, false)
|
|
336
|
+
if (status >= 400) {
|
|
337
|
+
finish(
|
|
338
|
+
false,
|
|
339
|
+
_functions.createHttpError(
|
|
340
|
+
status,
|
|
341
|
+
method,
|
|
342
|
+
url,
|
|
343
|
+
res.headers,
|
|
344
|
+
result,
|
|
345
|
+
res.statusMessage
|
|
346
|
+
)
|
|
347
|
+
)
|
|
348
|
+
} else {
|
|
349
|
+
finish(true, result)
|
|
350
|
+
}
|
|
351
|
+
} catch (e) {
|
|
352
|
+
finish(false, new Error(`JSON parse error: ${e.message}`))
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
if (
|
|
357
|
+
encoding !== ENCODING_NONE &&
|
|
358
|
+
clInt > 0 &&
|
|
359
|
+
clInt < COMPRESSION_MIN_SIZE
|
|
360
|
+
) {
|
|
361
|
+
const compressed = []
|
|
362
|
+
let csize = 0
|
|
363
|
+
|
|
364
|
+
res.on('data', (c) => {
|
|
365
|
+
csize += c.length
|
|
366
|
+
if (csize > MAX_RESPONSE_SIZE)
|
|
367
|
+
return finish(false, ERRORS.RESPONSE_TOO_LARGE)
|
|
368
|
+
compressed.push(c)
|
|
369
|
+
})
|
|
370
|
+
res.once('end', () => {
|
|
371
|
+
try {
|
|
372
|
+
handleResponse(
|
|
373
|
+
_functions.decompressSync(Buffer.concat(compressed), encoding)
|
|
374
|
+
)
|
|
375
|
+
} catch (e) {
|
|
376
|
+
finish(false, e)
|
|
377
|
+
}
|
|
378
|
+
})
|
|
379
|
+
res.once('aborted', () => finish(false, ERRORS.RESPONSE_ABORTED))
|
|
380
|
+
res.once('error', (e) => finish(false, e))
|
|
381
|
+
return
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
if (
|
|
385
|
+
encoding === ENCODING_NONE &&
|
|
386
|
+
clInt > 0 &&
|
|
387
|
+
clInt <= MAX_RESPONSE_SIZE
|
|
388
|
+
) {
|
|
389
|
+
prealloc = Buffer.allocUnsafe(clInt)
|
|
390
|
+
} else {
|
|
391
|
+
chunks = []
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
let stream = res
|
|
395
|
+
if (encoding !== ENCODING_NONE) {
|
|
396
|
+
const decomp = _functions.createDecompressor(encoding)
|
|
397
|
+
decomp.once('error', (e) => finish(false, e))
|
|
398
|
+
res.pipe(decomp)
|
|
399
|
+
stream = decomp
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
res.once('aborted', () => finish(false, ERRORS.RESPONSE_ABORTED))
|
|
403
|
+
res.once('error', (e) => finish(false, e))
|
|
404
|
+
|
|
405
|
+
stream.on('data', (chunk) => {
|
|
406
|
+
if (prealloc) {
|
|
407
|
+
chunk.copy(prealloc, size)
|
|
408
|
+
size += chunk.length
|
|
409
|
+
} else {
|
|
410
|
+
size += chunk.length
|
|
411
|
+
if (size > MAX_RESPONSE_SIZE)
|
|
412
|
+
return finish(false, ERRORS.RESPONSE_TOO_LARGE)
|
|
413
|
+
chunks.push(chunk)
|
|
414
|
+
}
|
|
415
|
+
})
|
|
416
|
+
|
|
417
|
+
stream.once('end', () => {
|
|
418
|
+
if (size === 0) return finish(true, null)
|
|
419
|
+
handleResponse(
|
|
420
|
+
prealloc
|
|
421
|
+
? prealloc.slice(0, size)
|
|
422
|
+
: chunks.length === 1
|
|
423
|
+
? chunks[0]
|
|
424
|
+
: Buffer.concat(chunks, size)
|
|
425
|
+
)
|
|
426
|
+
})
|
|
427
|
+
}
|
|
428
|
+
)
|
|
429
|
+
|
|
430
|
+
req.once('error', (e) => finish(false, e))
|
|
431
|
+
timer = setTimeout(
|
|
432
|
+
() => finish(false, new Error(`Request timeout: ${this.timeout}ms`)),
|
|
433
|
+
this.timeout
|
|
434
|
+
)
|
|
435
|
+
unrefTimer(timer)
|
|
436
|
+
payload ? req.end(payload) : req.end()
|
|
437
|
+
})
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
_getH2Session() {
|
|
441
|
+
if (!this._h2 || this._h2.closed || this._h2.destroyed) {
|
|
442
|
+
this._clearH2()
|
|
443
|
+
this._h2 = http2.connect(this.baseUrl, this._tlsOptions || undefined)
|
|
444
|
+
this._resetH2Timer()
|
|
445
|
+
|
|
446
|
+
const onEnd = () => this._clearH2()
|
|
447
|
+
this._h2.once('error', onEnd)
|
|
448
|
+
this._h2.once('close', onEnd)
|
|
449
|
+
this._h2.socket?.unref?.()
|
|
450
|
+
}
|
|
451
|
+
return this._h2
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
_resetH2Timer() {
|
|
455
|
+
if (this._h2Timer) {
|
|
456
|
+
clearTimeout(this._h2Timer)
|
|
457
|
+
this._h2Timer = null
|
|
458
|
+
}
|
|
459
|
+
if (this._h2 && !this._h2.closed && !this._h2.destroyed) {
|
|
460
|
+
this._h2Timer = setTimeout(() => this._closeH2(), H2_TIMEOUT)
|
|
461
|
+
unrefTimer(this._h2Timer)
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
_clearH2() {
|
|
466
|
+
if (this._h2Timer) {
|
|
467
|
+
clearTimeout(this._h2Timer)
|
|
468
|
+
this._h2Timer = null
|
|
469
|
+
}
|
|
470
|
+
this._h2 = null
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
_closeH2() {
|
|
474
|
+
if (this._h2Timer) {
|
|
475
|
+
clearTimeout(this._h2Timer)
|
|
476
|
+
this._h2Timer = null
|
|
477
|
+
}
|
|
478
|
+
if (this._h2) {
|
|
479
|
+
try {
|
|
480
|
+
this._h2.close()
|
|
481
|
+
} catch {}
|
|
482
|
+
this._h2 = null
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
_h2Request(method, path, headers, payload) {
|
|
487
|
+
const session = this._getH2Session()
|
|
488
|
+
|
|
489
|
+
return new Promise((resolve, reject) => {
|
|
490
|
+
let req,
|
|
491
|
+
timer,
|
|
492
|
+
done = false
|
|
493
|
+
let chunks = null,
|
|
494
|
+
size = 0,
|
|
495
|
+
prealloc = null
|
|
496
|
+
|
|
497
|
+
const finish = (ok, val) => {
|
|
498
|
+
if (done) return
|
|
499
|
+
done = true
|
|
500
|
+
if (timer) {
|
|
501
|
+
clearTimeout(timer)
|
|
502
|
+
timer = null
|
|
503
|
+
}
|
|
504
|
+
chunks = prealloc = null
|
|
505
|
+
if (req && !ok) req.close(http2.constants.NGHTTP2_CANCEL)
|
|
506
|
+
ok ? resolve(val) : reject(val)
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
const h2h = {
|
|
510
|
+
':method': method,
|
|
511
|
+
':path': path,
|
|
512
|
+
Authorization: headers.Authorization,
|
|
513
|
+
Accept: headers.Accept,
|
|
514
|
+
'Accept-Encoding': headers['Accept-Encoding'],
|
|
515
|
+
'User-Agent': headers['User-Agent']
|
|
516
|
+
}
|
|
517
|
+
if (headers['Content-Type']) h2h['Content-Type'] = headers['Content-Type']
|
|
518
|
+
if (headers['Content-Length'])
|
|
519
|
+
h2h['Content-Length'] = headers['Content-Length']
|
|
520
|
+
|
|
521
|
+
req = session.request(h2h)
|
|
522
|
+
this._resetH2Timer()
|
|
523
|
+
|
|
524
|
+
req.once('response', (rh) => {
|
|
525
|
+
if (timer) {
|
|
526
|
+
clearTimeout(timer)
|
|
527
|
+
timer = null
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
const status = rh[':status'] || 0
|
|
531
|
+
const cl = rh['content-length']
|
|
532
|
+
const contentType = rh['content-type'] || ''
|
|
533
|
+
|
|
534
|
+
if (status === 204 || cl === '0') {
|
|
535
|
+
req.resume()
|
|
536
|
+
return finish(true, null)
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
const clInt = cl ? parseInt(cl, 10) : 0
|
|
540
|
+
if (clInt > MAX_RESPONSE_SIZE) {
|
|
541
|
+
req.resume()
|
|
542
|
+
return finish(false, ERRORS.RESPONSE_TOO_LARGE)
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
const encoding = _functions.getEncodingType(rh['content-encoding'])
|
|
546
|
+
|
|
547
|
+
if (
|
|
548
|
+
encoding === ENCODING_NONE &&
|
|
549
|
+
clInt > 0 &&
|
|
550
|
+
clInt <= MAX_RESPONSE_SIZE
|
|
551
|
+
) {
|
|
552
|
+
prealloc = Buffer.allocUnsafe(clInt)
|
|
553
|
+
} else {
|
|
554
|
+
chunks = []
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
const decomp =
|
|
558
|
+
encoding !== ENCODING_NONE
|
|
559
|
+
? _functions.createDecompressor(encoding)
|
|
560
|
+
: null
|
|
561
|
+
const stream = decomp ? req.pipe(decomp) : req
|
|
562
|
+
|
|
563
|
+
if (decomp) decomp.once('error', (e) => finish(false, e))
|
|
564
|
+
req.once('error', (e) => finish(false, e))
|
|
565
|
+
|
|
566
|
+
stream.on('data', (chunk) => {
|
|
567
|
+
if (prealloc) {
|
|
568
|
+
chunk.copy(prealloc, size)
|
|
569
|
+
size += chunk.length
|
|
570
|
+
} else {
|
|
571
|
+
size += chunk.length
|
|
572
|
+
if (size > MAX_RESPONSE_SIZE)
|
|
573
|
+
return finish(false, ERRORS.RESPONSE_TOO_LARGE)
|
|
574
|
+
chunks.push(chunk)
|
|
575
|
+
}
|
|
576
|
+
})
|
|
577
|
+
|
|
578
|
+
stream.once('end', () => {
|
|
579
|
+
if (size === 0) return finish(true, null)
|
|
580
|
+
|
|
581
|
+
const buffer = prealloc
|
|
582
|
+
? prealloc.slice(0, size)
|
|
583
|
+
: chunks.length === 1
|
|
584
|
+
? chunks[0]
|
|
585
|
+
: Buffer.concat(chunks, size)
|
|
586
|
+
|
|
587
|
+
try {
|
|
588
|
+
const result = _functions.parseBody(buffer, contentType, false)
|
|
589
|
+
if (status >= 400) {
|
|
590
|
+
finish(
|
|
591
|
+
false,
|
|
592
|
+
_functions.createHttpError(
|
|
593
|
+
status,
|
|
594
|
+
method,
|
|
595
|
+
this.baseUrl + path,
|
|
596
|
+
rh,
|
|
597
|
+
result
|
|
598
|
+
)
|
|
599
|
+
)
|
|
600
|
+
} else {
|
|
601
|
+
finish(true, result)
|
|
602
|
+
}
|
|
603
|
+
} catch (e) {
|
|
604
|
+
finish(false, new Error(`JSON parse error: ${e.message}`))
|
|
605
|
+
}
|
|
606
|
+
})
|
|
607
|
+
})
|
|
608
|
+
|
|
609
|
+
timer = setTimeout(
|
|
610
|
+
() => finish(false, new Error(`Request timeout: ${this.timeout}ms`)),
|
|
611
|
+
this.timeout
|
|
612
|
+
)
|
|
613
|
+
unrefTimer(timer)
|
|
614
|
+
payload ? req.end(payload) : req.end()
|
|
615
|
+
})
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
async updatePlayer({ guildId, data, noReplace = false }) {
|
|
619
|
+
return this.makeRequest(
|
|
620
|
+
'PATCH',
|
|
621
|
+
`${this._getSessionPath()}/players/${guildId}?noReplace=${noReplace}`,
|
|
622
|
+
data
|
|
623
|
+
)
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
async getPlayer(guildId) {
|
|
627
|
+
return this.makeRequest(
|
|
628
|
+
'GET',
|
|
629
|
+
`${this._getSessionPath()}/players/${guildId}`
|
|
630
|
+
)
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
async getPlayers() {
|
|
634
|
+
return this.makeRequest('GET', `${this._getSessionPath()}/players`)
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
async destroyPlayer(guildId) {
|
|
638
|
+
return this.makeRequest(
|
|
639
|
+
'DELETE',
|
|
640
|
+
`${this._getSessionPath()}/players/${guildId}`
|
|
641
|
+
)
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
async loadTracks(identifier) {
|
|
645
|
+
return this.makeRequest(
|
|
646
|
+
'GET',
|
|
647
|
+
`${this._endpoints.loadtracks}${encodeURIComponent(identifier)}`
|
|
648
|
+
)
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
async decodeTrack(encodedTrack) {
|
|
652
|
+
if (!_functions.isValidBase64(encodedTrack)) throw ERRORS.INVALID_TRACK
|
|
653
|
+
return this.makeRequest(
|
|
654
|
+
'GET',
|
|
655
|
+
`${this._endpoints.decodetrack}${encodeURIComponent(encodedTrack)}`
|
|
656
|
+
)
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
async decodeTracks(encodedTracks) {
|
|
660
|
+
if (!Array.isArray(encodedTracks) || !encodedTracks.length)
|
|
661
|
+
throw ERRORS.INVALID_TRACKS
|
|
662
|
+
for (let i = 0; i < encodedTracks.length; i++) {
|
|
663
|
+
if (!_functions.isValidBase64(encodedTracks[i]))
|
|
664
|
+
throw ERRORS.INVALID_TRACKS
|
|
665
|
+
}
|
|
666
|
+
return this.makeRequest('POST', this._endpoints.decodetracks, encodedTracks)
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
async getStats() {
|
|
670
|
+
return this.makeRequest('GET', this._endpoints.stats)
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
async getInfo() {
|
|
674
|
+
return this.makeRequest('GET', this._endpoints.info)
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
async getVersion() {
|
|
678
|
+
return this.makeRequest('GET', this._endpoints.version)
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
async getRoutePlannerStatus() {
|
|
682
|
+
return this.makeRequest('GET', this._endpoints.routeplanner.status)
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
async freeRoutePlannerAddress(address) {
|
|
686
|
+
return this.makeRequest('POST', this._endpoints.routeplanner.freeAddress, {
|
|
687
|
+
address
|
|
688
|
+
})
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
async freeAllRoutePlannerAddresses() {
|
|
692
|
+
return this.makeRequest('POST', this._endpoints.routeplanner.freeAll)
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
async getLyrics({ track, skipTrackSource = false }) {
|
|
696
|
+
const guildId = track?.guild_id ?? track?.guildId
|
|
697
|
+
const encoded = track?.encoded
|
|
698
|
+
const hasEncoded =
|
|
699
|
+
typeof encoded === 'string' &&
|
|
700
|
+
encoded.length > 0 &&
|
|
701
|
+
_functions.isValidBase64(encoded)
|
|
702
|
+
const title = track?.info?.title
|
|
703
|
+
|
|
704
|
+
if (!track || (!guildId && !hasEncoded && !title)) {
|
|
705
|
+
this.aqua?.emit?.('error', '[Aqua/Lyrics] Invalid track object')
|
|
706
|
+
return null
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
const skip = skipTrackSource ? 'true' : 'false'
|
|
710
|
+
|
|
711
|
+
if (guildId) {
|
|
712
|
+
try {
|
|
713
|
+
const lyrics = await this.makeRequest(
|
|
714
|
+
'GET',
|
|
715
|
+
`${this._getSessionPath()}/players/${guildId}/track/lyrics?skipTrackSource=${skip}`
|
|
716
|
+
)
|
|
717
|
+
if (this._validLyrics(lyrics)) return lyrics
|
|
718
|
+
} catch {}
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
if (hasEncoded) {
|
|
722
|
+
try {
|
|
723
|
+
const lyrics = await this.makeRequest(
|
|
724
|
+
'GET',
|
|
725
|
+
`${this._endpoints.lyrics}?track=${encodeURIComponent(encoded)}&skipTrackSource=${skip}`
|
|
726
|
+
)
|
|
727
|
+
if (this._validLyrics(lyrics)) return lyrics
|
|
728
|
+
} catch {}
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
if (title) {
|
|
732
|
+
const info = track.info || {}
|
|
733
|
+
const query = info.author ? `${title} ${info.author}` : title
|
|
734
|
+
try {
|
|
735
|
+
const lyrics = await this.makeRequest(
|
|
736
|
+
'GET',
|
|
737
|
+
`${this._endpoints.lyrics}/search?query=${encodeURIComponent(query)}`
|
|
738
|
+
)
|
|
739
|
+
if (this._validLyrics(lyrics)) return lyrics
|
|
740
|
+
} catch {}
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
return null
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
_validLyrics(r) {
|
|
747
|
+
if (!r) return false
|
|
748
|
+
if (typeof r === 'string') return r.length > 0
|
|
749
|
+
if (typeof r === 'object')
|
|
750
|
+
return Array.isArray(r) ? r.length > 0 : Object.keys(r).length > 0
|
|
751
|
+
return false
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
async subscribeLiveLyrics(guildId, skipTrackSource = false) {
|
|
755
|
+
try {
|
|
756
|
+
return (
|
|
757
|
+
(await this.makeRequest(
|
|
758
|
+
'POST',
|
|
759
|
+
`${this._getSessionPath()}/players/${guildId}/lyrics/subscribe?skipTrackSource=${skipTrackSource ? 'true' : 'false'}`
|
|
760
|
+
)) === null
|
|
761
|
+
)
|
|
762
|
+
} catch {
|
|
763
|
+
return false
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
async unsubscribeLiveLyrics(guildId) {
|
|
768
|
+
try {
|
|
769
|
+
return (
|
|
770
|
+
(await this.makeRequest(
|
|
771
|
+
'DELETE',
|
|
772
|
+
`${this._getSessionPath()}/players/${guildId}/lyrics/subscribe`
|
|
773
|
+
)) === null
|
|
774
|
+
)
|
|
775
|
+
} catch {
|
|
776
|
+
return false
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
async addMixer(guildId, options) {
|
|
781
|
+
if (!this.node.isNodelink)
|
|
782
|
+
throw new Error('Mixer endpoints are only available on Nodelink nodes')
|
|
783
|
+
if (!options?.encoded && !options?.identifier)
|
|
784
|
+
throw new Error('You must provide either encoded or identifier')
|
|
785
|
+
|
|
786
|
+
const track = {}
|
|
787
|
+
if (options.encoded) track.encoded = options.encoded
|
|
788
|
+
if (options.identifier) track.identifier = options.identifier
|
|
789
|
+
if (options.userData) track.userData = options.userData
|
|
790
|
+
|
|
791
|
+
const payload = {
|
|
792
|
+
track,
|
|
793
|
+
volume: options.volume !== undefined ? options.volume : 0.8
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
return this.makeRequest(
|
|
797
|
+
'POST',
|
|
798
|
+
`/v4/sessions/${this.sessionId}/players/${guildId}/mix`,
|
|
799
|
+
payload
|
|
800
|
+
)
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
async getActiveMixer(guildId) {
|
|
804
|
+
if (!this.node.isNodelink)
|
|
805
|
+
throw new Error('Mixer endpoints are only available on Nodelink nodes')
|
|
806
|
+
const response = await this.makeRequest(
|
|
807
|
+
'GET',
|
|
808
|
+
`/v4/sessions/${this.sessionId}/players/${guildId}/mix`
|
|
809
|
+
)
|
|
810
|
+
return response?.mixes || []
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
async updateMixerVolume(guildId, mix, volume) {
|
|
814
|
+
if (!this.node.isNodelink)
|
|
815
|
+
throw new Error('Mixer endpoints are only available on Nodelink nodes')
|
|
816
|
+
if (!guildId || !mix || typeof volume !== 'number')
|
|
817
|
+
throw new Error('You forget to set the guild_id, mix or volume options')
|
|
818
|
+
|
|
819
|
+
return this.makeRequest(
|
|
820
|
+
'PATCH',
|
|
821
|
+
`/v4/sessions/${this.sessionId}/players/${guildId}/mix/${mix}`,
|
|
822
|
+
{ volume }
|
|
823
|
+
)
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
async removeMixer(guildId, mix) {
|
|
827
|
+
if (!this.node.isNodelink)
|
|
828
|
+
throw new Error('Mixer endpoints are only available on Nodelink nodes')
|
|
829
|
+
if (!guildId || !mix)
|
|
830
|
+
throw new Error('You forget to set the guild_id and/or mix options')
|
|
831
|
+
|
|
832
|
+
return this.makeRequest(
|
|
833
|
+
'DELETE',
|
|
834
|
+
`/v4/sessions/${this.sessionId}/players/${guildId}/mix/${mix}`
|
|
835
|
+
)
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
destroy() {
|
|
839
|
+
if (this.agent) {
|
|
840
|
+
this.agent.destroy()
|
|
841
|
+
this.agent = null
|
|
842
|
+
}
|
|
843
|
+
this._closeH2()
|
|
844
|
+
if (this._headerPool) {
|
|
845
|
+
this._headerPool.length = 0
|
|
846
|
+
this._headerPool = null
|
|
847
|
+
}
|
|
848
|
+
this.aqua =
|
|
849
|
+
this.node =
|
|
850
|
+
this.request =
|
|
851
|
+
this.defaultHeaders =
|
|
852
|
+
this._endpoints =
|
|
853
|
+
null
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
|
|
646
857
|
module.exports = Rest
|