@adbjs/sdk 1.0.0 → 2.0.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/dist/index.cjs +99 -69
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +97 -48
- package/dist/index.d.ts +97 -48
- package/dist/index.js +99 -69
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -153,11 +153,11 @@ var LinkResource = class extends BaseResource {
|
|
|
153
153
|
*
|
|
154
154
|
* @example
|
|
155
155
|
* ```ts
|
|
156
|
-
* const
|
|
157
|
-
* console.log(
|
|
156
|
+
* const data = await client.link.infos('https://example.com/file.zip')
|
|
157
|
+
* console.log(data.infos)
|
|
158
158
|
*
|
|
159
159
|
* // With password
|
|
160
|
-
* const
|
|
160
|
+
* const protectedData = await client.link.infos(
|
|
161
161
|
* 'https://example.com/protected.zip',
|
|
162
162
|
* 'mypassword'
|
|
163
163
|
* )
|
|
@@ -166,12 +166,7 @@ var LinkResource = class extends BaseResource {
|
|
|
166
166
|
async infos(links, password) {
|
|
167
167
|
const linksArray = Array.isArray(links) ? links : [links];
|
|
168
168
|
const params = password ? { password } : void 0;
|
|
169
|
-
|
|
170
|
-
"/link/infos",
|
|
171
|
-
{ "link[]": linksArray },
|
|
172
|
-
params
|
|
173
|
-
);
|
|
174
|
-
return data?.infos;
|
|
169
|
+
return this.post("/link/infos", { "link[]": linksArray }, params);
|
|
175
170
|
}
|
|
176
171
|
/**
|
|
177
172
|
* Extract links from redirectors/link protectors
|
|
@@ -180,14 +175,14 @@ var LinkResource = class extends BaseResource {
|
|
|
180
175
|
*
|
|
181
176
|
* @example
|
|
182
177
|
* ```ts
|
|
183
|
-
* const
|
|
178
|
+
* const data = await client.link.redirector('https://linkprotector.com/abc123')
|
|
179
|
+
* console.log(data.links)
|
|
184
180
|
* ```
|
|
185
181
|
*/
|
|
186
182
|
async redirector(link) {
|
|
187
|
-
|
|
183
|
+
return this.post("/link/redirector", {
|
|
188
184
|
link
|
|
189
185
|
});
|
|
190
|
-
return data?.links;
|
|
191
186
|
}
|
|
192
187
|
/**
|
|
193
188
|
* Unlock a download link
|
|
@@ -357,16 +352,38 @@ var MagnetResource = class extends BaseResource {
|
|
|
357
352
|
return this.post("/magnet/status", body);
|
|
358
353
|
}
|
|
359
354
|
/**
|
|
360
|
-
* Get magnet status using live mode for
|
|
355
|
+
* Get magnet status using live mode for bandwidth-optimized delta synchronization
|
|
356
|
+
*
|
|
357
|
+
* Live mode is designed for monitoring multiple magnets efficiently by only transmitting
|
|
358
|
+
* changes between polling intervals, drastically reducing bandwidth usage for dashboards
|
|
359
|
+
* and real-time monitoring applications.
|
|
360
|
+
*
|
|
361
|
+
* ## How it works
|
|
362
|
+
*
|
|
363
|
+
* 1. **Session initialization**: Generate a random session ID and start with counter = 0
|
|
364
|
+
* 2. **First call (fullsync)**: Returns ALL magnets with `fullsync: true`
|
|
365
|
+
* 3. **Update counter**: Use the `counter` value returned by the API for the next call
|
|
366
|
+
* 4. **Subsequent calls (delta)**: Returns ONLY magnets that changed since last call
|
|
367
|
+
* 5. **Repeat**: Keep calling with updated counter to receive only deltas
|
|
368
|
+
*
|
|
369
|
+
* ## When to use
|
|
370
|
+
*
|
|
371
|
+
* - ✅ Monitoring multiple active magnets simultaneously
|
|
372
|
+
* - ✅ Building real-time dashboards
|
|
373
|
+
* - ✅ High-frequency polling scenarios (every few seconds)
|
|
374
|
+
* - ❌ Watching a single specific magnet (use `watch()` instead)
|
|
361
375
|
*
|
|
362
|
-
*
|
|
363
|
-
* On the first call (counter=0), all data is returned with `fullsync: true`.
|
|
364
|
-
* Subsequent calls return only modifications.
|
|
376
|
+
* ## Important notes
|
|
365
377
|
*
|
|
366
|
-
*
|
|
367
|
-
*
|
|
368
|
-
*
|
|
369
|
-
*
|
|
378
|
+
* - **Don't use the `id` parameter**: Passing an ID defeats the purpose of live mode
|
|
379
|
+
* as it disables delta sync and behaves like a regular `status()` call
|
|
380
|
+
* - **Session persistence**: Keep the same session ID for the entire monitoring session
|
|
381
|
+
* - **Counter tracking**: Always update the counter with the value returned by the API
|
|
382
|
+
* - **Empty deltas**: When no magnets changed, `magnets` will be an empty array
|
|
383
|
+
*
|
|
384
|
+
* @param options - Live mode session options
|
|
385
|
+
* @param options.session - Unique session ID (generate once: `Math.floor(Math.random() * 1000000)`)
|
|
386
|
+
* @param options.counter - Sync counter (start at 0, then use value from previous API response)
|
|
370
387
|
*
|
|
371
388
|
* @example
|
|
372
389
|
* ```ts
|
|
@@ -374,34 +391,64 @@ var MagnetResource = class extends BaseResource {
|
|
|
374
391
|
* const session = Math.floor(Math.random() * 1000000)
|
|
375
392
|
* let counter = 0
|
|
376
393
|
*
|
|
377
|
-
* // First call -
|
|
394
|
+
* // First call - returns all magnets (fullsync: true)
|
|
378
395
|
* const firstCall = await client.magnet.statusLive({ session, counter })
|
|
379
396
|
* console.log('Full sync:', firstCall.fullsync) // true
|
|
380
|
-
* console.log('All magnets:', firstCall.magnets)
|
|
381
|
-
*
|
|
382
|
-
* // Update counter with value returned by API
|
|
383
|
-
* counter = firstCall.counter
|
|
397
|
+
* console.log('All magnets:', firstCall.magnets) // Array of all magnets
|
|
398
|
+
* counter = firstCall.counter // Update counter for next call
|
|
384
399
|
*
|
|
385
|
-
* // Second call - only
|
|
400
|
+
* // Second call - returns only magnets that changed
|
|
401
|
+
* await new Promise(resolve => setTimeout(resolve, 3000)) // Wait 3 seconds
|
|
386
402
|
* const secondCall = await client.magnet.statusLive({ session, counter })
|
|
387
|
-
* console.log('Delta sync:', secondCall.magnets) // Only
|
|
403
|
+
* console.log('Delta sync:', secondCall.magnets) // Only changed magnets
|
|
404
|
+
* counter = secondCall.counter
|
|
405
|
+
*
|
|
406
|
+
* // Example: Monitor all magnets until none are active
|
|
407
|
+
* const activeMagnets = new Map()
|
|
408
|
+
*
|
|
409
|
+
* while (true) {
|
|
410
|
+
* const response = await client.magnet.statusLive({ session, counter })
|
|
411
|
+
* counter = response.counter ?? counter
|
|
412
|
+
*
|
|
413
|
+
* // Update our local state with changes
|
|
414
|
+
* if (response.fullsync) {
|
|
415
|
+
* activeMagnets.clear()
|
|
416
|
+
* response.magnets?.forEach(m => activeMagnets.set(m.id, m))
|
|
417
|
+
* } else {
|
|
418
|
+
* response.magnets?.forEach(m => {
|
|
419
|
+
* if (m.status === 'Ready' || m.status === 'Error' || m.status === 'Expired') {
|
|
420
|
+
* activeMagnets.delete(m.id)
|
|
421
|
+
* } else {
|
|
422
|
+
* activeMagnets.set(m.id, m)
|
|
423
|
+
* }
|
|
424
|
+
* })
|
|
425
|
+
* }
|
|
426
|
+
*
|
|
427
|
+
* // Display current state
|
|
428
|
+
* console.log(`Active downloads: ${activeMagnets.size}`)
|
|
429
|
+
* activeMagnets.forEach(m => {
|
|
430
|
+
* console.log(` ${m.filename}: ${m.status} - ${m.downloaded}/${m.size} bytes`)
|
|
431
|
+
* })
|
|
432
|
+
*
|
|
433
|
+
* // Stop when no more active magnets
|
|
434
|
+
* if (activeMagnets.size === 0) {
|
|
435
|
+
* console.log('All downloads completed!')
|
|
436
|
+
* break
|
|
437
|
+
* }
|
|
388
438
|
*
|
|
389
|
-
*
|
|
390
|
-
*
|
|
439
|
+
* await new Promise(resolve => setTimeout(resolve, 3000))
|
|
440
|
+
* }
|
|
391
441
|
* ```
|
|
392
442
|
*
|
|
393
443
|
* @remarks
|
|
394
|
-
* This is ideal for
|
|
395
|
-
*
|
|
444
|
+
* This method is ideal for scenarios where you're monitoring multiple magnets and want
|
|
445
|
+
* to minimize bandwidth. For simple single-magnet monitoring, use `watch()` instead.
|
|
396
446
|
*/
|
|
397
|
-
async statusLive(options
|
|
447
|
+
async statusLive(options) {
|
|
398
448
|
const body = {
|
|
399
449
|
session: options.session,
|
|
400
450
|
counter: options.counter
|
|
401
451
|
};
|
|
402
|
-
if (id !== void 0) {
|
|
403
|
-
body.id = id;
|
|
404
|
-
}
|
|
405
452
|
return this.post("/magnet/status", body);
|
|
406
453
|
}
|
|
407
454
|
/**
|
|
@@ -446,9 +493,9 @@ var MagnetResource = class extends BaseResource {
|
|
|
446
493
|
*
|
|
447
494
|
* @example
|
|
448
495
|
* ```ts
|
|
449
|
-
* const
|
|
450
|
-
*
|
|
451
|
-
* console.log(
|
|
496
|
+
* const data = await client.magnet.files(123)
|
|
497
|
+
* data?.magnets?.forEach(magnet => {
|
|
498
|
+
* console.log(magnet.filename, magnet.files)
|
|
452
499
|
* })
|
|
453
500
|
* ```
|
|
454
501
|
*
|
|
@@ -462,56 +509,40 @@ var MagnetResource = class extends BaseResource {
|
|
|
462
509
|
for (const id of idsArray) {
|
|
463
510
|
formData.append("id[]", String(id));
|
|
464
511
|
}
|
|
465
|
-
|
|
466
|
-
return data?.magnets;
|
|
512
|
+
return this.postFormData("/magnet/files", formData);
|
|
467
513
|
}
|
|
468
514
|
/**
|
|
469
515
|
* Watch a magnet's status with automatic polling
|
|
470
516
|
*
|
|
517
|
+
* This is a simple helper that polls the status of a specific magnet until it reaches
|
|
518
|
+
* a target status (default: 'Ready'). For advanced use cases with multiple magnets
|
|
519
|
+
* or bandwidth optimization, use `statusLive()` directly instead.
|
|
520
|
+
*
|
|
471
521
|
* @param id - The magnet ID to watch
|
|
472
522
|
* @param options - Watch options
|
|
473
523
|
* @param options.interval - Polling interval in milliseconds (default: 3000)
|
|
474
524
|
* @param options.maxAttempts - Maximum polling attempts, 0 for infinite (default: 0)
|
|
475
525
|
* @param options.onUpdate - Callback called on each status update
|
|
476
526
|
* @param options.stopOnStatus - Stop when magnet reaches this status (default: 'Ready')
|
|
477
|
-
* @param options.useLiveMode - Use live mode for reduced bandwidth (default: false)
|
|
478
527
|
*
|
|
479
528
|
* @example
|
|
480
529
|
* ```ts
|
|
481
|
-
* // Standard mode
|
|
482
530
|
* await client.magnet.watch(123, {
|
|
483
531
|
* onUpdate: (status) => console.log('Status:', status.magnets[0]?.status),
|
|
484
532
|
* stopOnStatus: 'Ready'
|
|
485
533
|
* })
|
|
486
|
-
*
|
|
487
|
-
* // Live mode for reduced bandwidth
|
|
488
|
-
* await client.magnet.watch(123, {
|
|
489
|
-
* useLiveMode: true,
|
|
490
|
-
* interval: 2000,
|
|
491
|
-
* onUpdate: (status) => console.log('Update:', status)
|
|
492
|
-
* })
|
|
493
534
|
* ```
|
|
535
|
+
*
|
|
536
|
+
* @remarks
|
|
537
|
+
* For monitoring multiple magnets efficiently, use `statusLive()` directly.
|
|
538
|
+
* See the `statusLive()` documentation for details on delta synchronization.
|
|
494
539
|
*/
|
|
495
540
|
async watch(id, options = {}) {
|
|
496
|
-
const {
|
|
497
|
-
interval = 3e3,
|
|
498
|
-
maxAttempts = 0,
|
|
499
|
-
onUpdate,
|
|
500
|
-
stopOnStatus = "Ready",
|
|
501
|
-
useLiveMode = false
|
|
502
|
-
} = options;
|
|
541
|
+
const { interval = 3e3, maxAttempts = 0, onUpdate, stopOnStatus = "Ready" } = options;
|
|
503
542
|
let attempt = 0;
|
|
504
|
-
let session;
|
|
505
|
-
let counter = 0;
|
|
506
|
-
if (useLiveMode) {
|
|
507
|
-
session = Math.floor(Math.random() * 1e6);
|
|
508
|
-
}
|
|
509
543
|
while (maxAttempts === 0 || attempt < maxAttempts) {
|
|
510
544
|
attempt++;
|
|
511
|
-
const status =
|
|
512
|
-
if (useLiveMode && status?.counter !== void 0) {
|
|
513
|
-
counter = status.counter;
|
|
514
|
-
}
|
|
545
|
+
const status = await this.status(id);
|
|
515
546
|
onUpdate?.(status);
|
|
516
547
|
const magnet = status?.magnets?.[0];
|
|
517
548
|
if (magnet?.status === stopOnStatus) {
|
|
@@ -637,13 +668,12 @@ var UserResource = class extends BaseResource {
|
|
|
637
668
|
*
|
|
638
669
|
* @example
|
|
639
670
|
* ```ts
|
|
640
|
-
* const
|
|
641
|
-
* console.log(user.username, user.isPremium)
|
|
671
|
+
* const data = await client.user.getInfo()
|
|
672
|
+
* console.log(data.user.username, data.user.isPremium)
|
|
642
673
|
* ```
|
|
643
674
|
*/
|
|
644
675
|
async getInfo() {
|
|
645
|
-
|
|
646
|
-
return data?.user;
|
|
676
|
+
return this.get("/user");
|
|
647
677
|
}
|
|
648
678
|
/**
|
|
649
679
|
* Get available hosts for the current user based on their subscription
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/base-resource.ts","../src/resources/host.ts","../src/resources/link.ts","../src/resources/magnet.ts","../src/resources/pin.ts","../src/resources/user.ts","../src/resources/voucher.ts","../src/client.ts"],"names":[],"mappings":";;;;;AAKO,IAAM,cAAA,GAAN,MAAM,eAAA,SAAuB,KAAA,CAAM;AAAA,EACxB,IAAA;AAAA,EACA,gBAAA,GAAmB,IAAA;AAAA,EAEnC,WAAA,CAAY,MAAc,OAAA,EAAiB;AACzC,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,gBAAA;AACZ,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AAGZ,IAAA,IAAI,mBAAA,IAAuB,KAAA,IAAS,OAAQ,KAAA,CAAc,sBAAsB,UAAA,EAAY;AACzF,MAAC,KAAA,CAAc,iBAAA,CAAkB,IAAA,EAAM,eAAc,CAAA;AAAA,IACxD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,aAAa,KAAA,EAAiC;AACnD,IAAA,OAAO,IAAI,eAAA,CAAe,KAAA,CAAM,IAAA,EAAM,MAAM,OAAO,CAAA;AAAA,EACrD;AACF;AAKO,IAAM,mBAAA,GAAN,cAAkC,cAAA,CAAe;AAAA,EACtD,WAAA,CAAY,MAAc,OAAA,EAAiB;AACzC,IAAA,KAAA,CAAM,MAAM,OAAO,CAAA;AACnB,IAAA,IAAA,CAAK,IAAA,GAAO,qBAAA;AAAA,EACd;AACF;AAKO,IAAM,SAAA,GAAN,cAAwB,cAAA,CAAe;AAAA,EAC5C,WAAA,CAAY,MAAc,OAAA,EAAiB;AACzC,IAAA,KAAA,CAAM,MAAM,OAAO,CAAA;AACnB,IAAA,IAAA,CAAK,IAAA,GAAO,WAAA;AAAA,EACd;AACF;AAKO,IAAM,WAAA,GAAN,cAA0B,cAAA,CAAe;AAAA,EAC9C,WAAA,CAAY,MAAc,OAAA,EAAiB;AACzC,IAAA,KAAA,CAAM,MAAM,OAAO,CAAA;AACnB,IAAA,IAAA,CAAK,IAAA,GAAO,aAAA;AAAA,EACd;AACF;AAKO,IAAM,YAAA,GAAN,cAA2B,cAAA,CAAe;AAAA,EAC/C,WAAA,CACE,SACgB,UAAA,EAChB;AACA,IAAA,KAAA,CAAM,iBAAiB,OAAO,CAAA;AAFd,IAAA,IAAA,CAAA,UAAA,GAAA,UAAA;AAGhB,IAAA,IAAA,CAAK,IAAA,GAAO,cAAA;AAAA,EACd;AACF;AAKO,SAAS,gBAAA,CAAiB,MAAc,OAAA,EAAiC;AAC9E,EAAA,IAAI,IAAA,CAAK,UAAA,CAAW,OAAO,CAAA,EAAG;AAC5B,IAAA,OAAO,IAAI,mBAAA,CAAoB,IAAA,EAAM,OAAO,CAAA;AAAA,EAC9C;AACA,EAAA,IACE,IAAA,CAAK,UAAA,CAAW,OAAO,CAAA,IACvB,KAAK,UAAA,CAAW,aAAa,CAAA,IAC7B,IAAA,CAAK,WAAW,SAAS,CAAA,IACzB,IAAA,CAAK,UAAA,CAAW,UAAU,CAAA,EAC1B;AACA,IAAA,OAAO,IAAI,SAAA,CAAU,IAAA,EAAM,OAAO,CAAA;AAAA,EACpC;AACA,EAAA,IAAI,IAAA,CAAK,UAAA,CAAW,SAAS,CAAA,EAAG;AAC9B,IAAA,OAAO,IAAI,WAAA,CAAY,IAAA,EAAM,OAAO,CAAA;AAAA,EACtC;AACA,EAAA,OAAO,IAAI,cAAA,CAAe,IAAA,EAAM,OAAO,CAAA;AACzC;;;AClFO,IAAe,eAAf,MAA4B;AAAA,EACjC,YAA+B,MAAA,EAAyB;AAAzB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAAA,EAA0B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASzD,MAAgB,GAAA,CAAO,IAAA,EAAc,MAAA,EAA2D;AAC9F,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,GAAA,CAAO,IAAA,EAAM,MAAM,CAAA;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAgB,IAAA,CACd,IAAA,EACA,IAAA,EACA,MAAA,EACyB;AACzB,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,IAAA,CAAQ,IAAA,EAAM,MAAM,MAAM,CAAA;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAgB,YAAA,CACd,IAAA,EACA,QAAA,EACA,MAAA,EACyB;AACzB,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,YAAA,CAAgB,IAAA,EAAM,UAAU,MAAM,CAAA;AAAA,EAC3D;AACF,CAAA;;;AC3CO,IAAM,YAAA,GAAN,cAA2B,YAAA,CAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAc7C,MAAM,KAAK,QAAA,EAAoB;AAC7B,IAAA,MAAM,MAAA,GAAS,QAAA,GAAW,EAAE,QAAA,EAAU,KAAI,GAAI,MAAA;AAC9C,IAAA,OAAO,IAAA,CAAK,GAAA,CAAsB,QAAA,EAAU,MAAM,CAAA;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,OAAA,GAAU;AACd,IAAA,OAAO,IAAA,CAAK,IAA4B,gBAAgB,CAAA;AAAA,EAC1D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,QAAA,GAAW;AACf,IAAA,OAAO,IAAA,CAAK,IAA6B,iBAAiB,CAAA;AAAA,EAC5D;AACF;;;ACpBO,IAAM,YAAA,GAAN,cAA2B,YAAA,CAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmB7C,MAAM,KAAA,CAAM,KAAA,EAA0B,QAAA,EAAmB;AACvD,IAAA,MAAM,aAAa,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,GAAI,KAAA,GAAQ,CAAC,KAAK,CAAA;AACxD,IAAA,MAAM,MAAA,GAAS,QAAA,GAAW,EAAE,QAAA,EAAS,GAAI,MAAA;AACzC,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA;AAAA,MACtB,aAAA;AAAA,MACA,EAAE,UAAU,UAAA,EAAW;AAAA,MACvB;AAAA,KACF;AACA,IAAA,OAAO,IAAA,EAAM,KAAA;AAAA,EACf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,WAAW,IAAA,EAAc;AAC7B,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,CAAiC,kBAAA,EAAoB;AAAA,MAC3E;AAAA,KACD,CAAA;AACD,IAAA,OAAO,IAAA,EAAM,KAAA;AAAA,EACf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAyBA,MAAM,MAAA,CAAO,IAAA,EAAc,QAAA,EAAmB;AAC5C,IAAA,MAAM,MAAA,GAAS,QAAA,GAAW,EAAE,QAAA,EAAS,GAAI,MAAA;AACzC,IAAA,OAAO,KAAK,IAAA,CAAyB,cAAA,EAAgB,EAAE,IAAA,IAAQ,MAAM,CAAA;AAAA,EACvE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,MAAM,iBAAA,CAAkB,IAAA,EAAc,QAAA,GAAwB,EAAC,EAAG;AAGhE,IAAA,OAAO,IAAA,CAAK,OAAO,IAAI,CAAA;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,SAAA,CAAU,EAAA,EAAY,MAAA,EAAgB;AAC1C,IAAA,OAAO,IAAA,CAAK,KAA+B,iBAAA,EAAmB;AAAA,MAC5D,EAAA;AAAA,MACA;AAAA,KACD,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,QAAQ,EAAA,EAAY;AACxB,IAAA,OAAO,IAAA,CAAK,KAA+B,eAAA,EAAiB;AAAA,MAC1D;AAAA,KACD,CAAA;AAAA,EACH;AACF;;;AChGO,IAAM,cAAA,GAAN,cAA6B,YAAA,CAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAY/C,MAAM,OAAO,OAAA,EAA4B;AACvC,IAAA,MAAM,eAAe,KAAA,CAAM,OAAA,CAAQ,OAAO,CAAA,GAAI,OAAA,GAAU,CAAC,OAAO,CAAA;AAChE,IAAA,OAAO,IAAA,CAAK,KAA4B,gBAAA,EAAkB;AAAA,MACxD,OAAA,EAAS;AAAA,KACV,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA,MAAM,UAAA,CAAW,IAAA,EAAmB,QAAA,EAAmB;AACrD,IAAA,MAAM,QAAA,GAAW,IAAI,QAAA,EAAS;AAG9B,IAAA,MAAM,cAAA,GAAiB,QAAA,KAAa,IAAA,YAAgB,IAAA,GAAO,KAAK,IAAA,GAAO,iBAAA,CAAA;AAGvE,IAAA,QAAA,CAAS,MAAA,CAAO,SAAA,EAAW,IAAA,EAAM,cAAc,CAAA;AAE/C,IAAA,OAAO,IAAA,CAAK,YAAA,CAAwC,qBAAA,EAAuB,QAAQ,CAAA;AAAA,EACrF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,MAAM,OAAO,EAAA,EAAY;AACvB,IAAA,MAAM,OAAO,MAAM,IAAA,CAAK,KAA8B,gBAAA,EAAkB,EAAE,IAAI,CAAA;AAI9E,IAAA,IAAI,MAAM,OAAA,IAAW,CAAC,MAAM,OAAA,CAAQ,IAAA,CAAK,OAAO,CAAA,EAAG;AACjD,MAAA,OAAO;AAAA,QACL,GAAG,IAAA;AAAA,QACH,OAAA,EAAS,CAAC,IAAA,CAAK,OAAO;AAAA,OACxB;AAAA,IACF;AAEA,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsBA,MAAM,WAAW,YAAA,EAAyD;AACxE,IAAA,MAAM,IAAA,GAAO,YAAA,GAAe,EAAE,MAAA,EAAQ,cAAa,GAAI,MAAA;AACvD,IAAA,OAAO,IAAA,CAAK,IAAA,CAA8B,gBAAA,EAAkB,IAAI,CAAA;AAAA,EAClE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAwCA,MAAM,UAAA,CAAW,OAAA,EAA4B,EAAA,EAAa;AACxD,IAAA,MAAM,IAAA,GAAY;AAAA,MAChB,SAAS,OAAA,CAAQ,OAAA;AAAA,MACjB,SAAS,OAAA,CAAQ;AAAA,KACnB;AAEA,IAAA,IAAI,OAAO,MAAA,EAAW;AACpB,MAAA,IAAA,CAAK,EAAA,GAAK,EAAA;AAAA,IACZ;AAEA,IAAA,OAAO,IAAA,CAAK,IAAA,CAA8B,gBAAA,EAAkB,IAAI,CAAA;AAAA,EAClE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,OAAO,EAAA,EAAY;AACvB,IAAA,OAAO,IAAA,CAAK,KAA2B,gBAAA,EAAkB;AAAA,MACvD;AAAA,KACD,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,MAAM,QAAQ,GAAA,EAAwB;AACpC,IAAA,MAAM,WAAW,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAA,GAAI,GAAA,GAAM,CAAC,GAAG,CAAA;AAChD,IAAA,OAAO,IAAA,CAAK,KAA4B,iBAAA,EAAmB;AAAA,MACzD,GAAA,EAAK;AAAA,KACN,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBA,MAAM,MAAM,GAAA,EAAwB;AAClC,IAAA,MAAM,QAAA,GAAW,IAAI,QAAA,EAAS;AAC9B,IAAA,MAAM,WAAW,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAA,GAAI,GAAA,GAAM,CAAC,GAAG,CAAA;AAChD,IAAA,KAAA,MAAW,MAAM,QAAA,EAAU;AACzB,MAAA,QAAA,CAAS,MAAA,CAAO,MAAA,EAAQ,MAAA,CAAO,EAAE,CAAC,CAAA;AAAA,IACpC;AACA,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,YAAA,CAAqC,iBAAiB,QAAQ,CAAA;AACtF,IAAA,OAAO,IAAA,EAAM,OAAA;AAAA,EACf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA6BA,MAAM,KAAA,CAAM,EAAA,EAAY,OAAA,GAAwB,EAAC,EAAG;AAClD,IAAA,MAAM;AAAA,MACJ,QAAA,GAAW,GAAA;AAAA,MACX,WAAA,GAAc,CAAA;AAAA,MACd,QAAA;AAAA,MACA,YAAA,GAAe,OAAA;AAAA,MACf,WAAA,GAAc;AAAA,KAChB,GAAI,OAAA;AAEJ,IAAA,IAAI,OAAA,GAAU,CAAA;AAGd,IAAA,IAAI,OAAA;AACJ,IAAA,IAAI,OAAA,GAAU,CAAA;AAEd,IAAA,IAAI,WAAA,EAAa;AACf,MAAA,OAAA,GAAU,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,MAAA,KAAW,GAAO,CAAA;AAAA,IAC9C;AAEA,IAAA,OAAO,WAAA,KAAgB,CAAA,IAAK,OAAA,GAAU,WAAA,EAAa;AACjD,MAAA,OAAA,EAAA;AAGA,MAAA,MAAM,SACJ,WAAA,IAAe,OAAA,KAAY,MAAA,GACvB,MAAM,KAAK,UAAA,CAAW,EAAE,OAAA,EAAS,OAAA,IAAW,EAAE,CAAA,GAC9C,MAAM,IAAA,CAAK,OAAO,EAAE,CAAA;AAG1B,MAAA,IAAI,WAAA,IAAe,MAAA,EAAQ,OAAA,KAAY,MAAA,EAAW;AAChD,QAAA,OAAA,GAAU,MAAA,CAAO,OAAA;AAAA,MACnB;AAEA,MAAA,QAAA,GAAW,MAAM,CAAA;AAGjB,MAAA,MAAM,MAAA,GAAS,MAAA,EAAQ,OAAA,GAAU,CAAC,CAAA;AAClC,MAAA,IAAI,MAAA,EAAQ,WAAW,YAAA,EAAc;AACnC,QAAA,OAAO,MAAA;AAAA,MACT;AAGA,MAAA,MAAM,IAAI,OAAA,CAAQ,CAAC,YAAY,UAAA,CAAW,OAAA,EAAS,QAAQ,CAAC,CAAA;AAAA,IAC9D;AAEA,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,qCAAA,EAAwC,YAAY,CAAA,eAAA,EAAkB,WAAW,CAAA,SAAA;AAAA,KACnF;AAAA,EACF;AACF;;;AC5VO,IAAM,WAAA,GAAN,cAA0B,YAAA,CAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsB5C,MAAM,QAAA,GAAW;AACf,IAAA,OAAO,KAAA,CAAM,IAAoB,UAAU,CAAA;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgCA,MAAM,KAAA,CAAM,KAAA,EAAe,GAAA,EAAa;AACtC,IAAA,OAAO,MAAM,GAAA,CAAsB,YAAA,EAAc,EAAE,KAAA,EAAO,KAAK,CAAA;AAAA,EACjE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiCA,MAAM,WAAA,CACJ,KAAA,EACA,GAAA,EACA,OAAA,GAKI,EAAC,EACY;AACjB,IAAA,MAAM,OAAA,GAAU,QAAQ,OAAA,IAAW,GAAA;AACnC,IAAA,MAAM,QAAA,GAAW,QAAQ,QAAA,IAAY,GAAA;AACrC,IAAA,MAAM,SAAA,GAAY,KAAK,GAAA,EAAI;AAE3B,IAAA,OAAO,IAAA,CAAK,GAAA,EAAI,GAAI,SAAA,GAAY,OAAA,EAAS;AACvC,MAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,KAAA,CAAM,OAAO,GAAG,CAAA;AAE1C,MAAA,IAAI,MAAA,EAAQ,SAAA,IAAa,MAAA,EAAQ,MAAA,EAAQ;AACvC,QAAA,OAAO,MAAA,CAAO,MAAA;AAAA,MAChB;AAGA,MAAA,MAAM,IAAI,OAAA,CAAQ,CAAC,YAAY,UAAA,CAAW,OAAA,EAAS,QAAQ,CAAC,CAAA;AAAA,IAC9D;AAEA,IAAA,MAAM,IAAI,MAAM,0EAA0E,CAAA;AAAA,EAC5F;AACF;;;AC/GO,IAAM,YAAA,GAAN,cAA2B,YAAA,CAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAU7C,MAAM,OAAA,GAAU;AACd,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,GAAA,CAAqB,OAAO,CAAA;AACpD,IAAA,OAAO,IAAA,EAAM,IAAA;AAAA,EACf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,SAAS,QAAA,EAAoB;AACjC,IAAA,MAAM,MAAA,GAAS,QAAA,GAAW,EAAE,QAAA,EAAU,KAAI,GAAI,MAAA;AAC9C,IAAA,OAAO,IAAA,CAAK,GAAA,CAA0B,aAAA,EAAe,MAAM,CAAA;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,kBAAkB,IAAA,EAAc;AACpC,IAAA,MAAM,IAAA,CAAK,IAAA,CAAgC,0BAAA,EAA4B,EAAE,MAAM,CAAA;AAAA,EACjF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,MAAM,QAAA,GAAW;AACf,IAAA,OAAO,IAAA,CAAK,IAA2B,aAAa,CAAA;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsBA,MAAM,SAAS,KAAA,EAA0B;AACvC,IAAA,MAAM,aAAa,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,GAAI,KAAA,GAAQ,CAAC,KAAK,CAAA;AACxD,IAAA,MAAM,QAAA,GAAW,IAAI,QAAA,EAAS;AAG9B,IAAA,KAAA,MAAW,QAAQ,UAAA,EAAY;AAC7B,MAAA,QAAA,CAAS,MAAA,CAAO,WAAW,IAAI,CAAA;AAAA,IACjC;AAEA,IAAA,OAAO,IAAA,CAAK,YAAA,CAAgC,kBAAA,EAAoB,QAAQ,CAAA;AAAA,EAC1E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsBA,MAAM,WAAW,KAAA,EAA0B;AACzC,IAAA,MAAM,aAAa,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,GAAI,KAAA,GAAQ,CAAC,KAAK,CAAA;AACxD,IAAA,MAAM,QAAA,GAAW,IAAI,QAAA,EAAS;AAG9B,IAAA,KAAA,MAAW,QAAQ,UAAA,EAAY;AAC7B,MAAA,QAAA,CAAS,MAAA,CAAO,WAAW,IAAI,CAAA;AAAA,IACjC;AAEA,IAAA,OAAO,IAAA,CAAK,YAAA,CAAuC,oBAAA,EAAsB,QAAQ,CAAA;AAAA,EACnF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,MAAM,UAAA,GAAa;AACjB,IAAA,OAAO,IAAA,CAAK,IAAwB,eAAe,CAAA;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,YAAA,GAAe;AACnB,IAAA,OAAO,IAAA,CAAK,KAA4B,sBAAsB,CAAA;AAAA,EAChE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,MAAM,sBAAsB,KAAA,EAAe;AACzC,IAAA,OAAO,KAAK,IAAA,CAA6B,aAAA,EAAe,MAAA,EAAW,EAAE,OAAO,CAAA;AAAA,EAC9E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,mBAAmB,KAAA,EAAe;AACtC,IAAA,OAAO,KAAK,IAAA,CAA0B,oBAAA,EAAsB,MAAA,EAAW,EAAE,OAAO,CAAA;AAAA,EAClF;AACF;;;AChMO,IAAM,eAAA,GAAN,cAA8B,YAAA,CAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAehD,MAAM,UAAA,GAAa;AACjB,IAAA,OAAO,IAAA,CAAK,IAA+B,kBAAkB,CAAA;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsBA,MAAM,YAAY,QAAA,EAAmB;AACnC,IAAA,MAAM,MAAA,GAAS,QAAA,GAAW,EAAE,QAAA,EAAS,GAAI,MAAA;AACzC,IAAA,OAAO,IAAA,CAAK,GAAA,CAAkC,cAAA,EAAgB,MAAM,CAAA;AAAA,EACtE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAuBA,MAAM,gBAAA,CAAiB,QAAA,EAAkB,QAAA,EAAkB;AACzD,IAAA,OAAO,IAAA,CAAK,KAA+B,mBAAA,EAAqB;AAAA,MAC9D,QAAA;AAAA,MACA;AAAA,KACD,CAAA;AAAA,EACH;AACF;;;ACxEA,IAAM,gBAAA,GAAmB,gCAAA;AACzB,IAAM,aAAA,GAAgB,gBAAA;AACtB,IAAM,eAAA,GAAkB,GAAA;AACxB,IAAM,mBAAA,GAAsB,CAAA;AAKrB,IAAM,kBAAN,MAAsB;AAAA,EACV,MAAA;AAAA;AAAA;AAAA;AAAA,EAKD,IAAA;AAAA;AAAA;AAAA;AAAA,EAKA,IAAA;AAAA;AAAA;AAAA;AAAA,EAKA,MAAA;AAAA;AAAA;AAAA;AAAA,EAKA,IAAA;AAAA;AAAA;AAAA;AAAA,EAKA,GAAA;AAAA;AAAA;AAAA;AAAA,EAKA,OAAA;AAAA,EAEhB,YAAY,MAAA,EAAyB;AAEnC,IAAA,IAAA,CAAK,MAAA,GAAS;AAAA,MACZ,QAAQ,MAAA,CAAO,MAAA;AAAA,MACf,KAAA,EAAO,OAAO,KAAA,IAAS,aAAA;AAAA,MACvB,OAAA,EAAS,OAAO,OAAA,IAAW,gBAAA;AAAA,MAC3B,OAAA,EAAS,OAAO,OAAA,IAAW,eAAA;AAAA,MAC3B,KAAA,EAAO,OAAO,KAAA,IAAS,IAAA;AAAA,MACvB,UAAA,EAAY,OAAO,UAAA,IAAc;AAAA,KACnC;AAGA,IAAA,IAAA,CAAK,IAAA,GAAO,IAAI,YAAA,CAAa,IAAI,CAAA;AACjC,IAAA,IAAA,CAAK,IAAA,GAAO,IAAI,YAAA,CAAa,IAAI,CAAA;AACjC,IAAA,IAAA,CAAK,MAAA,GAAS,IAAI,cAAA,CAAe,IAAI,CAAA;AACrC,IAAA,IAAA,CAAK,IAAA,GAAO,IAAI,YAAA,CAAa,IAAI,CAAA;AACjC,IAAA,IAAA,CAAK,GAAA,GAAM,IAAI,WAAA,CAAY,IAAI,CAAA;AAC/B,IAAA,IAAA,CAAK,OAAA,GAAU,IAAI,eAAA,CAAgB,IAAI,CAAA;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA,EAKQ,QAAA,CAAS,MAAc,MAAA,EAA0C;AACvE,IAAA,MAAM,SAAA,GAAY;AAAA,MAChB,KAAA,EAAO,KAAK,MAAA,CAAO,KAAA;AAAA,MACnB,GAAG;AAAA,KACL;AAEA,IAAA,MAAM,KAAA,GAAQ,IAAI,eAAA,EAAgB;AAClC,IAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,SAAS,CAAA,EAAG;AACpD,MAAA,IAAI,KAAA,KAAU,MAAA,IAAa,KAAA,KAAU,IAAA,EAAM;AACzC,QAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AACxB,UAAA,KAAA,CAAM,OAAA,CAAQ,CAAC,CAAA,KAAM,KAAA,CAAM,MAAA,CAAO,CAAA,EAAG,GAAG,CAAA,EAAA,CAAA,EAAM,MAAA,CAAO,CAAC,CAAC,CAAC,CAAA;AAAA,QAC1D,CAAA,MAAO;AACL,UAAA,KAAA,CAAM,MAAA,CAAO,GAAA,EAAK,MAAA,CAAO,KAAK,CAAC,CAAA;AAAA,QACjC;AAAA,MACF;AAAA,IACF;AAEA,IAAA,MAAM,WAAA,GAAc,MAAM,QAAA,EAAS;AACnC,IAAA,OAAO,WAAA,GAAc,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,WAAW,CAAA,CAAA,GAAK,IAAA;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,GAAA,CAAO,IAAA,EAAc,MAAA,EAA2D;AACpF,IAAA,IAAI;AACF,MAAA,MAAM,GAAA,GAAM,IAAA,CAAK,QAAA,CAAS,IAAA,EAAM,MAAM,CAAA;AACtC,MAAA,MAAM,OAAO,MAAM,MAAA,CAAO,KAAK,MAAA,CAAO,OAAO,EAC1C,IAAA,CAAK,CAAA,OAAA,EAAU,KAAK,MAAA,CAAO,MAAM,EAAE,CAAA,CACnC,GAAA,CAAI,GAAG,CAAA,CACP,GAAA,GACA,IAAA,EAA2B;AAG9B,MAAA,IAAI,IAAA,CAAK,MAAA,KAAW,OAAA,IAAW,IAAA,CAAK,KAAA,EAAO;AACzC,QAAA,MAAM,iBAAiB,IAAA,CAAK,KAAA,CAAM,IAAA,EAAM,IAAA,CAAK,MAAM,OAAO,CAAA;AAAA,MAC5D;AAEA,MAAA,OAAO,IAAA,CAAK,IAAA;AAAA,IACd,SAAS,KAAA,EAAY;AAEnB,MAAA,IAAI,KAAA,CAAM,WAAW,GAAA,EAAK;AACxB,QAAA,MAAM,gBAAA,CAAiB,mBAAmB,wCAAwC,CAAA;AAAA,MACpF;AACA,MAAA,IAAI,KAAA,CAAM,WAAW,GAAA,EAAK;AACxB,QAAA,MAAM,gBAAA,CAAiB,gBAAgB,kBAAkB,CAAA;AAAA,MAC3D;AACA,MAAA,IAAI,KAAA,CAAM,WAAW,GAAA,EAAK;AACxB,QAAA,MAAM,gBAAA,CAAiB,gBAAgB,mBAAmB,CAAA;AAAA,MAC5D;AAGA,MAAA,IAAI,MAAM,gBAAA,EAAkB;AAC1B,QAAA,MAAM,KAAA;AAAA,MACR;AAGA,MAAA,MAAM,IAAI,YAAA,CAAa,KAAA,CAAM,OAAA,IAAW,wBAAA,EAA0B,MAAM,MAAM,CAAA;AAAA,IAChF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,IAAA,CACJ,IAAA,EACA,IAAA,EACA,MAAA,EACyB;AACzB,IAAA,IAAI;AACF,MAAA,MAAM,GAAA,GAAM,IAAA,CAAK,QAAA,CAAS,IAAA,EAAM,MAAM,CAAA;AAGtC,MAAA,MAAM,QAAA,GAAW,IAAI,eAAA,EAAgB;AACrC,MAAA,IAAI,IAAA,IAAQ,OAAO,IAAA,KAAS,QAAA,EAAU;AACpC,QAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,IAAI,CAAA,EAAG;AAC/C,UAAA,IAAI,KAAA,KAAU,KAAA,CAAA,IAAa,KAAA,KAAU,IAAA,EAAM;AACzC,YAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AAExB,cAAA,KAAA,CAAM,OAAA,CAAQ,CAAC,CAAA,KAAM,QAAA,CAAS,OAAO,GAAA,EAAK,MAAA,CAAO,CAAC,CAAC,CAAC,CAAA;AAAA,YACtD,CAAA,MAAO;AACL,cAAA,QAAA,CAAS,MAAA,CAAO,GAAA,EAAK,MAAA,CAAO,KAAK,CAAC,CAAA;AAAA,YACpC;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,MAAA,MAAM,IAAA,GAAO,MAAM,MAAA,CAAO,IAAA,CAAK,OAAO,OAAO,CAAA,CAC1C,IAAA,CAAK,CAAA,OAAA,EAAU,IAAA,CAAK,MAAA,CAAO,MAAM,CAAA,CAAE,CAAA,CACnC,IAAI,GAAG,CAAA,CACP,KAAK,QAAQ,CAAA,CACb,IAAA,EAAK,CACL,IAAA,EAA2B;AAG9B,MAAA,IAAI,IAAA,CAAK,MAAA,KAAW,OAAA,IAAW,IAAA,CAAK,KAAA,EAAO;AACzC,QAAA,MAAM,iBAAiB,IAAA,CAAK,KAAA,CAAM,IAAA,EAAM,IAAA,CAAK,MAAM,OAAO,CAAA;AAAA,MAC5D;AAEA,MAAA,OAAO,IAAA,CAAK,IAAA;AAAA,IACd,SAAS,KAAA,EAAY;AAEnB,MAAA,IAAI,KAAA,CAAM,WAAW,GAAA,EAAK;AACxB,QAAA,MAAM,gBAAA,CAAiB,mBAAmB,wCAAwC,CAAA;AAAA,MACpF;AACA,MAAA,IAAI,KAAA,CAAM,WAAW,GAAA,EAAK;AACxB,QAAA,MAAM,gBAAA,CAAiB,gBAAgB,kBAAkB,CAAA;AAAA,MAC3D;AACA,MAAA,IAAI,KAAA,CAAM,WAAW,GAAA,EAAK;AACxB,QAAA,MAAM,gBAAA,CAAiB,gBAAgB,mBAAmB,CAAA;AAAA,MAC5D;AAGA,MAAA,IAAI,MAAM,gBAAA,EAAkB;AAC1B,QAAA,MAAM,KAAA;AAAA,MACR;AAGA,MAAA,MAAM,IAAI,YAAA,CAAa,KAAA,CAAM,OAAA,IAAW,wBAAA,EAA0B,MAAM,MAAM,CAAA;AAAA,IAChF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,YAAA,CACJ,IAAA,EACA,QAAA,EACA,MAAA,EACyB;AACzB,IAAA,IAAI;AACF,MAAA,MAAM,GAAA,GAAM,IAAA,CAAK,QAAA,CAAS,IAAA,EAAM,MAAM,CAAA;AACtC,MAAA,MAAM,IAAA,GAAO,MAAM,MAAA,CAAO,IAAA,CAAK,OAAO,OAAO,CAAA,CAC1C,IAAA,CAAK,CAAA,OAAA,EAAU,IAAA,CAAK,MAAA,CAAO,MAAM,CAAA,CAAE,CAAA,CACnC,IAAI,GAAG,CAAA,CACP,KAAK,QAAQ,CAAA,CACb,IAAA,EAAK,CACL,IAAA,EAA2B;AAG9B,MAAA,IAAI,IAAA,CAAK,MAAA,KAAW,OAAA,IAAW,IAAA,CAAK,KAAA,EAAO;AACzC,QAAA,MAAM,iBAAiB,IAAA,CAAK,KAAA,CAAM,IAAA,EAAM,IAAA,CAAK,MAAM,OAAO,CAAA;AAAA,MAC5D;AAEA,MAAA,OAAO,IAAA,CAAK,IAAA;AAAA,IACd,SAAS,KAAA,EAAY;AAEnB,MAAA,IAAI,KAAA,CAAM,WAAW,GAAA,EAAK;AACxB,QAAA,MAAM,gBAAA,CAAiB,mBAAmB,wCAAwC,CAAA;AAAA,MACpF;AACA,MAAA,IAAI,KAAA,CAAM,WAAW,GAAA,EAAK;AACxB,QAAA,MAAM,gBAAA,CAAiB,gBAAgB,kBAAkB,CAAA;AAAA,MAC3D;AACA,MAAA,IAAI,KAAA,CAAM,WAAW,GAAA,EAAK;AACxB,QAAA,MAAM,gBAAA,CAAiB,gBAAgB,mBAAmB,CAAA;AAAA,MAC5D;AAGA,MAAA,IAAI,MAAM,gBAAA,EAAkB;AAC1B,QAAA,MAAM,KAAA;AAAA,MACR;AAGA,MAAA,MAAM,IAAI,YAAA,CAAa,KAAA,CAAM,OAAA,IAAW,wBAAA,EAA0B,MAAM,MAAM,CAAA;AAAA,IAChF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,MAAM,IAAA,GAAO;AACX,IAAA,OAAO,IAAA,CAAK,IAAkB,OAAO,CAAA;AAAA,EACvC;AACF","file":"index.js","sourcesContent":["import type { ApiError } from './types.js'\n\n/**\n * Base error class for AllDebrid SDK errors\n */\nexport class AllDebridError extends Error {\n public readonly code: string\n public readonly isAllDebridError = true\n\n constructor(code: string, message: string) {\n super(message)\n this.name = 'AllDebridError'\n this.code = code\n\n // Maintains proper stack trace for where our error was thrown (only available on V8)\n if ('captureStackTrace' in Error && typeof (Error as any).captureStackTrace === 'function') {\n ;(Error as any).captureStackTrace(this, AllDebridError)\n }\n }\n\n /**\n * Create an AllDebridError from an API error response\n */\n static fromApiError(error: ApiError): AllDebridError {\n return new AllDebridError(error.code, error.message)\n }\n}\n\n/**\n * Authentication related errors\n */\nexport class AuthenticationError extends AllDebridError {\n constructor(code: string, message: string) {\n super(code, message)\n this.name = 'AuthenticationError'\n }\n}\n\n/**\n * Link processing errors\n */\nexport class LinkError extends AllDebridError {\n constructor(code: string, message: string) {\n super(code, message)\n this.name = 'LinkError'\n }\n}\n\n/**\n * Magnet/Torrent related errors\n */\nexport class MagnetError extends AllDebridError {\n constructor(code: string, message: string) {\n super(code, message)\n this.name = 'MagnetError'\n }\n}\n\n/**\n * Network/HTTP errors\n */\nexport class NetworkError extends AllDebridError {\n constructor(\n message: string,\n public readonly statusCode?: number,\n ) {\n super('NETWORK_ERROR', message)\n this.name = 'NetworkError'\n }\n}\n\n/**\n * Helper to determine error type from error code\n */\nexport function createTypedError(code: string, message: string): AllDebridError {\n if (code.startsWith('AUTH_')) {\n return new AuthenticationError(code, message)\n }\n if (\n code.startsWith('LINK_') ||\n code.startsWith('REDIRECTOR_') ||\n code.startsWith('STREAM_') ||\n code.startsWith('DELAYED_')\n ) {\n return new LinkError(code, message)\n }\n if (code.startsWith('MAGNET_')) {\n return new MagnetError(code, message)\n }\n return new AllDebridError(code, message)\n}\n","import type { AllDebridClient } from './client.js'\nimport type { ExtractData } from './types.js'\n\n/**\n * Base class for all resources\n * Provides access to HTTP methods\n * @internal\n */\nexport abstract class BaseResource {\n constructor(protected readonly client: AllDebridClient) {}\n\n /**\n * Make a GET request\n * @template T - The generated response type (e.g., GetLinkUnlockResponse)\n * @param path - API endpoint path\n * @param params - Optional query parameters\n * @returns The extracted data from the response (without the { status, data } wrapper)\n */\n protected async get<T>(path: string, params?: Record<string, unknown>): Promise<ExtractData<T>> {\n return this.client.get<T>(path, params)\n }\n\n /**\n * Make a POST request\n * @template T - The generated response type\n * @param path - API endpoint path\n * @param body - Request body\n * @param params - Optional query parameters\n * @returns The extracted data from the response (without the { status, data } wrapper)\n */\n protected async post<T>(\n path: string,\n body?: unknown,\n params?: Record<string, unknown>,\n ): Promise<ExtractData<T>> {\n return this.client.post<T>(path, body, params)\n }\n\n /**\n * Make a POST request with FormData (multipart/form-data)\n * @template T - The generated response type\n * @param path - API endpoint path\n * @param formData - Form data to send\n * @param params - Optional query parameters\n * @returns The extracted data from the response (without the { status, data } wrapper)\n */\n protected async postFormData<T>(\n path: string,\n formData: FormData,\n params?: Record<string, unknown>,\n ): Promise<ExtractData<T>> {\n return this.client.postFormData<T>(path, formData, params)\n }\n}\n","import type {\n GetHostDomainsResponse,\n GetHostPriorityResponse,\n GetHostsResponse,\n} from '../generated/types.gen.js'\nimport { BaseResource } from '../base-resource.js'\n\n/**\n * Host resource for getting information about supported hosts\n */\nexport class HostResource extends BaseResource {\n /**\n * Get list of all supported hosts with their information\n *\n * @param hostOnly - If true, only return hosts (exclude streams and redirectors)\n *\n * @example\n * ```ts\n * const hosts = await client.host.list()\n * console.log(hosts.hosts) // All supported file hosts\n * console.log(hosts.streams) // Streaming hosts\n * console.log(hosts.redirectors) // Link redirectors\n * ```\n */\n async list(hostOnly?: boolean) {\n const params = hostOnly ? { hostOnly: '1' } : undefined\n return this.get<GetHostsResponse>('/hosts', params)\n }\n\n /**\n * Get array of all supported domain names\n *\n * @example\n * ```ts\n * const domains = await client.host.domains()\n * console.log(domains) // ['rapidgator.net', 'uploaded.net', ...]\n * ```\n */\n async domains() {\n return this.get<GetHostDomainsResponse>('/hosts/domains')\n }\n\n /**\n * Get hosts ordered by restriction level (priority list)\n *\n * @example\n * ```ts\n * const priority = await client.host.priority()\n * console.log(priority.hosts) // Ordered list with restriction levels\n * ```\n */\n async priority() {\n return this.get<GetHostPriorityResponse>('/hosts/priority')\n }\n}\n","import type {\n GetDelayedStatusResponse,\n GetLinkInfosResponse,\n GetRedirectorLinksResponse,\n GetStreamingLinkResponse,\n UnlockLinkResponse,\n} from '../generated/types.gen.js'\nimport { BaseResource } from '../base-resource.js'\n\n/**\n * Options for polling delayed link generation\n */\nexport interface PollOptions {\n /**\n * Polling interval in milliseconds\n * @default 2000\n */\n interval?: number\n\n /**\n * Maximum number of polling attempts\n * @default 30\n */\n maxAttempts?: number\n\n /**\n * Callback called on each polling attempt\n */\n onPoll?: (attempt: number) => void\n}\n\n/**\n * Link resource for unlocking and managing download links\n */\nexport class LinkResource extends BaseResource {\n /**\n * Get information about one or more links\n *\n * @param links - Single link or array of links to get info for\n * @param password - Optional password for password-protected links\n *\n * @example\n * ```ts\n * const info = await client.link.infos('https://example.com/file.zip')\n * console.log(info)\n *\n * // With password\n * const protectedInfo = await client.link.infos(\n * 'https://example.com/protected.zip',\n * 'mypassword'\n * )\n * ```\n */\n async infos(links: string | string[], password?: string) {\n const linksArray = Array.isArray(links) ? links : [links]\n const params = password ? { password } : undefined\n const data = await this.post<GetLinkInfosResponse>(\n '/link/infos',\n { 'link[]': linksArray },\n params,\n )\n return data?.infos\n }\n\n /**\n * Extract links from redirectors/link protectors\n *\n * @param link - The redirector link to extract from\n *\n * @example\n * ```ts\n * const links = await client.link.redirector('https://linkprotector.com/abc123')\n * ```\n */\n async redirector(link: string) {\n const data = await this.post<GetRedirectorLinksResponse>('/link/redirector', {\n link,\n })\n return data?.links\n }\n\n /**\n * Unlock a download link\n *\n * @param link - The link to unlock\n * @param password - Optional password for password-protected links\n *\n * @example\n * ```ts\n * const result = await client.link.unlock('https://example.com/file.zip')\n * if (result.link) {\n * console.log('Direct link:', result.link)\n * } else if (result.delayed) {\n * // Handle delayed generation\n * const delayedResult = await client.link.delayed(result.delayed)\n * }\n *\n * // With password\n * const protectedResult = await client.link.unlock(\n * 'https://example.com/protected.zip',\n * 'mypassword'\n * )\n * ```\n */\n async unlock(link: string, password?: string) {\n const params = password ? { password } : undefined\n return this.post<UnlockLinkResponse>('/link/unlock', { link }, params)\n }\n\n /**\n * Unlock a link and automatically poll if delayed\n * Note: The API response format doesn't include a delayed field in the current OpenAPI spec.\n * This method will be updated once the delayed mechanism is documented.\n *\n * @param link - The link to unlock\n * @param _options - Polling options (currently unused)\n *\n * @example\n * ```ts\n * const result = await client.link.unlockWithPolling('https://example.com/file.zip')\n * console.log('Direct link:', result.link)\n * ```\n */\n async unlockWithPolling(link: string, _options: PollOptions = {}) {\n // For now, just unlock without polling\n // TODO: Implement polling once delayed field is added to API response\n return this.unlock(link)\n }\n\n /**\n * Get streaming options for a generated link\n *\n * @param id - The generated link ID or streaming ID\n *\n * @example\n * ```ts\n * const streams = await client.link.streaming('abc123')\n * ```\n */\n async streaming(id: string, stream: string) {\n return this.post<GetStreamingLinkResponse>('/link/streaming', {\n id,\n stream,\n })\n }\n\n /**\n * Get the status/result of a delayed link generation\n *\n * @param id - The delayed generation ID\n *\n * @example\n * ```ts\n * const result = await client.link.delayed('delayed_id_123')\n * ```\n */\n async delayed(id: number) {\n return this.post<GetDelayedStatusResponse>('/link/delayed', {\n id,\n })\n }\n}\n","import type {\n DeleteMagnetResponse,\n GetMagnetFilesResponse,\n GetMagnetStatusResponse,\n RestartMagnetResponse,\n UploadMagnetsResponse,\n UploadTorrentFileResponse,\n} from '../generated/types.gen.js'\nimport { BaseResource } from '../base-resource.js'\n\n/**\n * Options for live mode status polling\n */\nexport interface LiveStatusOptions {\n /**\n * Session ID - Generate a random number and keep it consistent for the entire session\n * @example Math.floor(Math.random() * 1000000)\n */\n session: number\n\n /**\n * Counter for synchronization - Start at 0 and increment with each call\n * The API will return the next counter value to use\n */\n counter: number\n}\n\n/**\n * Options for watching magnet status\n */\nexport interface WatchOptions {\n /**\n * Polling interval in milliseconds\n * @default 3000\n */\n interval?: number\n\n /**\n * Maximum number of polling attempts (0 = infinite)\n * @default 0\n */\n maxAttempts?: number\n\n /**\n * Callback called on each status update\n */\n onUpdate?: (status: any) => void\n\n /**\n * Stop watching when magnet reaches this status\n * @default 'Ready'\n */\n stopOnStatus?: string\n\n /**\n * Use live mode for reduced bandwidth (delta sync)\n * When enabled, only changes are transmitted instead of full status\n * @default false\n */\n useLiveMode?: boolean\n}\n\n/**\n * Magnet/Torrent resource for managing torrent downloads\n */\nexport class MagnetResource extends BaseResource {\n /**\n * Upload magnets by URI or hash\n *\n * @param magnets - Single magnet URI/hash or array of magnets\n *\n * @example\n * ```ts\n * const result = await client.magnet.upload('magnet:?xt=urn:btih:...')\n * console.log('Magnet ID:', result.magnets[0].id)\n * ```\n */\n async upload(magnets: string | string[]) {\n const magnetsArray = Array.isArray(magnets) ? magnets : [magnets]\n return this.post<UploadMagnetsResponse>('/magnet/upload', {\n magnets: magnetsArray,\n })\n }\n\n /**\n * Upload a torrent file\n *\n * @param file - The torrent file (Blob or File)\n * @param filename - Optional filename (defaults to 'torrent.torrent' for Blob, or file.name for File)\n *\n * @example\n * ```ts\n * const file = new File([buffer], 'torrent.torrent')\n * const result = await client.magnet.uploadFile(file)\n *\n * // Or with a Blob and custom filename\n * const blob = new Blob([buffer])\n * const result = await client.magnet.uploadFile(blob, 'my-torrent.torrent')\n * ```\n */\n async uploadFile(file: Blob | File, filename?: string) {\n const formData = new FormData()\n\n // Determine the filename to use\n const actualFilename = filename || (file instanceof File ? file.name : 'torrent.torrent')\n\n // Append with explicit filename\n formData.append('files[]', file, actualFilename)\n\n return this.postFormData<UploadTorrentFileResponse>('/magnet/upload/file', formData)\n }\n\n /**\n * Get the status of a specific magnet by ID\n *\n * @param id - Magnet ID to get status for\n *\n * @example\n * ```ts\n * const status = await client.magnet.status(123)\n * console.log(status.magnets[0]?.status) // 'Downloading', 'Ready', etc.\n * ```\n *\n * @remarks\n * This endpoint uses AllDebrid API v4.1 (POST method)\n * Migrated from v4 GET endpoint which was deprecated on 2024-10-16\n */\n async status(id: number) {\n const data = await this.post<GetMagnetStatusResponse>('/magnet/status', { id })\n\n // Fix: AllDebrid API returns an object instead of array when filtering by ID\n // This is an API inconsistency, so we normalize it to always return an array\n if (data?.magnets && !Array.isArray(data.magnets)) {\n return {\n ...data,\n magnets: [data.magnets],\n }\n }\n\n return data\n }\n\n /**\n * Get list of magnets with optional status filter\n *\n * @param statusFilter - Optional filter by status: 'active', 'ready', 'expired', or 'error'\n *\n * @example\n * ```ts\n * // Get all magnets\n * const allMagnets = await client.magnet.statusList()\n *\n * // Get only active magnets\n * const activeMagnets = await client.magnet.statusList('active')\n *\n * // Get only ready magnets\n * const readyMagnets = await client.magnet.statusList('ready')\n * ```\n *\n * @remarks\n * This endpoint uses AllDebrid API v4.1 (POST method)\n */\n async statusList(statusFilter?: 'active' | 'ready' | 'expired' | 'error') {\n const body = statusFilter ? { status: statusFilter } : undefined\n return this.post<GetMagnetStatusResponse>('/magnet/status', body)\n }\n\n /**\n * Get magnet status using live mode for reduced bandwidth consumption\n *\n * Live mode uses delta synchronization - only changes since the last call are transmitted.\n * On the first call (counter=0), all data is returned with `fullsync: true`.\n * Subsequent calls return only modifications.\n *\n * @param options - Live mode options\n * @param options.session - Session ID (generate once per session and reuse)\n * @param options.counter - Synchronization counter (start at 0, use returned counter for next call)\n * @param id - Optional magnet ID to filter a specific magnet\n *\n * @example\n * ```ts\n * // Initialize session\n * const session = Math.floor(Math.random() * 1000000)\n * let counter = 0\n *\n * // First call - full sync\n * const firstCall = await client.magnet.statusLive({ session, counter })\n * console.log('Full sync:', firstCall.fullsync) // true\n * console.log('All magnets:', firstCall.magnets)\n *\n * // Update counter with value returned by API\n * counter = firstCall.counter\n *\n * // Second call - only changes\n * const secondCall = await client.magnet.statusLive({ session, counter })\n * console.log('Delta sync:', secondCall.magnets) // Only modified magnets\n *\n * // Filter specific magnet in live mode\n * const magnetLive = await client.magnet.statusLive({ session, counter }, 123)\n * ```\n *\n * @remarks\n * This is ideal for real-time dashboards or frequent polling scenarios\n * as it significantly reduces bandwidth usage by transmitting only changes.\n */\n async statusLive(options: LiveStatusOptions, id?: number) {\n const body: any = {\n session: options.session,\n counter: options.counter,\n }\n\n if (id !== undefined) {\n body.id = id\n }\n\n return this.post<GetMagnetStatusResponse>('/magnet/status', body)\n }\n\n /**\n * Delete a magnet\n *\n * @param id - The magnet ID to delete\n *\n * @example\n * ```ts\n * await client.magnet.delete(123)\n * ```\n */\n async delete(id: number) {\n return this.post<DeleteMagnetResponse>('/magnet/delete', {\n id,\n })\n }\n\n /**\n * Restart one or more failed magnets\n *\n * @param ids - Single magnet ID or array of magnet IDs to restart (numbers)\n *\n * @example\n * ```ts\n * // Restart single magnet\n * await client.magnet.restart(123)\n *\n * // Restart multiple magnets\n * await client.magnet.restart([123, 456])\n * ```\n */\n async restart(ids: number | number[]) {\n const idsArray = Array.isArray(ids) ? ids : [ids]\n return this.post<RestartMagnetResponse>('/magnet/restart', {\n ids: idsArray,\n })\n }\n\n /**\n * Get files for a completed magnet\n *\n * @param ids - The magnet ID or IDs to get files for\n *\n * @example\n * ```ts\n * const files = await client.magnet.files(123)\n * files?.forEach(file => {\n * console.log(file.filename, file.link)\n * })\n * ```\n *\n * @remarks\n * Files are now retrieved separately from magnet status (since v4.1)\n * Only available for magnets with status 'Ready'\n */\n async files(ids: number | number[]) {\n const formData = new FormData()\n const idsArray = Array.isArray(ids) ? ids : [ids]\n for (const id of idsArray) {\n formData.append('id[]', String(id))\n }\n const data = await this.postFormData<GetMagnetFilesResponse>('/magnet/files', formData)\n return data?.magnets\n }\n\n /**\n * Watch a magnet's status with automatic polling\n *\n * @param id - The magnet ID to watch\n * @param options - Watch options\n * @param options.interval - Polling interval in milliseconds (default: 3000)\n * @param options.maxAttempts - Maximum polling attempts, 0 for infinite (default: 0)\n * @param options.onUpdate - Callback called on each status update\n * @param options.stopOnStatus - Stop when magnet reaches this status (default: 'Ready')\n * @param options.useLiveMode - Use live mode for reduced bandwidth (default: false)\n *\n * @example\n * ```ts\n * // Standard mode\n * await client.magnet.watch(123, {\n * onUpdate: (status) => console.log('Status:', status.magnets[0]?.status),\n * stopOnStatus: 'Ready'\n * })\n *\n * // Live mode for reduced bandwidth\n * await client.magnet.watch(123, {\n * useLiveMode: true,\n * interval: 2000,\n * onUpdate: (status) => console.log('Update:', status)\n * })\n * ```\n */\n async watch(id: number, options: WatchOptions = {}) {\n const {\n interval = 3000,\n maxAttempts = 0,\n onUpdate,\n stopOnStatus = 'Ready',\n useLiveMode = false,\n } = options\n\n let attempt = 0\n\n // Live mode session state\n let session: number | undefined\n let counter = 0\n\n if (useLiveMode) {\n session = Math.floor(Math.random() * 1000000)\n }\n\n while (maxAttempts === 0 || attempt < maxAttempts) {\n attempt++\n\n // Use appropriate status method based on mode\n const status =\n useLiveMode && session !== undefined\n ? await this.statusLive({ session, counter }, id)\n : await this.status(id)\n\n // Update counter for next live mode call\n if (useLiveMode && status?.counter !== undefined) {\n counter = status.counter\n }\n\n onUpdate?.(status)\n\n // Check if we should stop (magnets is an array)\n const magnet = status?.magnets?.[0]\n if (magnet?.status === stopOnStatus) {\n return status\n }\n\n // Wait before next attempt\n await new Promise((resolve) => setTimeout(resolve, interval))\n }\n\n throw new Error(\n `Watch timeout: magnet did not reach '${stopOnStatus}' status after ${maxAttempts} attempts`,\n )\n }\n}\n","import type { CheckPinResponse, GetPinResponse } from '../generated/types.gen.js'\nimport { BaseResource } from '../base-resource.js'\n\n/**\n * Pin resource for PIN-based authentication flow\n *\n * The PIN flow allows users to authenticate without directly providing their API key.\n * This is useful for applications where you want users to authorize access through\n * the AllDebrid website.\n */\nexport class PinResource extends BaseResource {\n /**\n * Generate a new PIN code for authentication\n *\n * This initiates the PIN authentication flow. The user should visit the\n * returned URL to authorize the application.\n *\n * @example\n * ```ts\n * const pinData = await client.pin.generate()\n * console.log('Visit:', pinData.user_url)\n * console.log('PIN:', pinData.pin)\n *\n * // Poll the check endpoint until user authorizes\n * const auth = await client.pin.check(pinData.check, pinData.pin)\n * if (auth.activated) {\n * console.log('API Key:', auth.apikey)\n * }\n * ```\n *\n * @returns PIN code and authorization URL\n */\n async generate() {\n return super.get<GetPinResponse>('/pin/get')\n }\n\n /**\n * Check the status of a PIN authentication\n *\n * Poll this endpoint to check if the user has authorized the application.\n * Once authorized, the response will include the API key.\n *\n * @param check - Check ID from /pin/get\n * @param pin - PIN code from /pin/get\n *\n * @example\n * ```ts\n * const pinData = await client.pin.generate()\n *\n * // Poll every few seconds until activated\n * const checkStatus = async () => {\n * const result = await client.pin.check(pinData.check, pinData.pin)\n * if (result?.activated && result?.apikey) {\n * console.log('Authorized! API Key:', result.apikey)\n * return result.apikey\n * }\n * // Wait and try again\n * await new Promise(resolve => setTimeout(resolve, 3000))\n * return checkStatus()\n * }\n *\n * const apikey = await checkStatus()\n * ```\n *\n * @returns Authorization status and API key (if activated)\n */\n async check(check: string, pin: string) {\n return super.get<CheckPinResponse>('/pin/check', { check, pin })\n }\n\n /**\n * Helper method to wait for PIN authorization with automatic polling\n *\n * This method handles the polling logic for you, making it easier to\n * implement the PIN authentication flow.\n *\n * @param check - Check ID from /pin/get\n * @param pin - PIN code from /pin/get\n * @param options - Polling options\n * @param options.timeout - Maximum time to wait in milliseconds (default: 600000 = 10 minutes)\n * @param options.interval - Polling interval in milliseconds (default: 3000 = 3 seconds)\n *\n * @example\n * ```ts\n * const pinData = await client.pin.generate()\n * console.log('Visit:', pinData.user_url)\n *\n * try {\n * const apikey = await client.pin.waitForAuth(pinData.check, pinData.pin, {\n * timeout: 600000, // 10 minutes\n * interval: 3000, // Check every 3 seconds\n * })\n * console.log('Authorized! API Key:', apikey)\n * } catch (error) {\n * console.error('Authorization timed out or failed')\n * }\n * ```\n *\n * @returns The API key once authorized\n * @throws Error if timeout is reached or authorization fails\n */\n async waitForAuth(\n check: string,\n pin: string,\n options: {\n /** Maximum time to wait in milliseconds (default: 600000 = 10 minutes) */\n timeout?: number\n /** Polling interval in milliseconds (default: 3000 = 3 seconds) */\n interval?: number\n } = {},\n ): Promise<string> {\n const timeout = options.timeout ?? 600000 // 10 minutes default\n const interval = options.interval ?? 3000 // 3 seconds default\n const startTime = Date.now()\n\n while (Date.now() - startTime < timeout) {\n const result = await this.check(check, pin)\n\n if (result?.activated && result?.apikey) {\n return result.apikey\n }\n\n // Wait before next poll\n await new Promise((resolve) => setTimeout(resolve, interval))\n }\n\n throw new Error('PIN authorization timeout - user did not authorize within the time limit')\n }\n}\n","import type {\n ClearNotificationResponse,\n DeleteHistoryResponse,\n DeleteSavedLinksResponse,\n GetHistoryResponse,\n GetSavedLinksResponse,\n GetUserHostsResponse,\n GetUserResponse,\n GetVerifStatusResponse,\n ResendVerifResponse,\n SaveLinksResponse,\n} from '../generated/types.gen.js'\nimport { BaseResource } from '../base-resource.js'\n\n/**\n * User resource for managing user account information\n */\nexport class UserResource extends BaseResource {\n /**\n * Get user profile information including premium status and quotas\n *\n * @example\n * ```ts\n * const user = await client.user.getInfo()\n * console.log(user.username, user.isPremium)\n * ```\n */\n async getInfo() {\n const data = await this.get<GetUserResponse>('/user')\n return data?.user\n }\n\n /**\n * Get available hosts for the current user based on their subscription\n *\n * @param hostOnly - If true, only return hosts data (exclude streams and redirectors)\n *\n * @example\n * ```ts\n * const hosts = await client.user.getHosts()\n * console.log(Object.keys(hosts.hosts))\n * ```\n */\n async getHosts(hostOnly?: boolean) {\n const params = hostOnly ? { hostOnly: '1' } : undefined\n return this.get<GetUserHostsResponse>('/user/hosts', params)\n }\n\n /**\n * Clear a specific notification by code\n *\n * @param code - The notification code to clear\n *\n * @example\n * ```ts\n * await client.user.clearNotification('SOME_NOTIF_CODE')\n * ```\n */\n async clearNotification(code: string) {\n await this.post<ClearNotificationResponse>('/user/notification/clear', { code })\n }\n\n // ============================================\n // Saved Links Management\n // ============================================\n\n /**\n * Get all saved links\n *\n * @example\n * ```ts\n * const savedLinks = await client.user.getLinks()\n * console.log(savedLinks.links)\n * ```\n */\n async getLinks() {\n return this.get<GetSavedLinksResponse>('/user/links')\n }\n\n /**\n * Save one or multiple links for later use\n *\n * Supports batch operations - you can save multiple links in a single request.\n *\n * @param links - Single link or array of links to save\n *\n * @example\n * ```ts\n * // Save single link\n * await client.user.saveLink('https://example.com/file.zip')\n *\n * // Save multiple links at once\n * await client.user.saveLink([\n * 'https://example.com/file1.zip',\n * 'https://example.com/file2.zip',\n * 'https://example.com/file3.zip'\n * ])\n * ```\n */\n async saveLink(links: string | string[]) {\n const linksArray = Array.isArray(links) ? links : [links]\n const formData = new FormData()\n\n // API expects links[] array format\n for (const link of linksArray) {\n formData.append('links[]', link)\n }\n\n return this.postFormData<SaveLinksResponse>('/user/links/save', formData)\n }\n\n /**\n * Delete one or multiple saved links\n *\n * Supports batch operations - you can delete multiple links in a single request.\n *\n * @param links - Single link or array of links to delete (can be saved link IDs or URLs)\n *\n * @example\n * ```ts\n * // Delete single link\n * await client.user.deleteLink('saved-link-id')\n *\n * // Delete multiple links at once\n * await client.user.deleteLink([\n * 'saved-link-id-1',\n * 'saved-link-id-2',\n * 'saved-link-id-3'\n * ])\n * ```\n */\n async deleteLink(links: string | string[]) {\n const linksArray = Array.isArray(links) ? links : [links]\n const formData = new FormData()\n\n // API expects links[] array format\n for (const link of linksArray) {\n formData.append('links[]', link)\n }\n\n return this.postFormData<DeleteSavedLinksResponse>('/user/links/delete', formData)\n }\n\n // ============================================\n // History Management\n // ============================================\n\n /**\n * Get user history (if enabled in account settings)\n *\n * @example\n * ```ts\n * const history = await client.user.getHistory()\n * console.log(history.links)\n * ```\n */\n async getHistory() {\n return this.get<GetHistoryResponse>('/user/history')\n }\n\n /**\n * Clear user history\n *\n * @example\n * ```ts\n * await client.user.clearHistory()\n * ```\n */\n async clearHistory() {\n return this.post<DeleteHistoryResponse>('/user/history/delete')\n }\n\n // ============================================\n // Email Verification\n // ============================================\n\n /**\n * Check email verification status\n *\n * @param token - Verification token\n *\n * @example\n * ```ts\n * const status = await client.user.getVerificationStatus('verification-token')\n * console.log(status.verif) // 'waiting', 'allowed', or 'denied'\n * ```\n */\n async getVerificationStatus(token: string) {\n return this.post<GetVerifStatusResponse>('/user/verif', undefined, { token })\n }\n\n /**\n * Resend verification email\n *\n * @param token - Verification token\n *\n * @example\n * ```ts\n * await client.user.resendVerification('verification-token')\n * ```\n */\n async resendVerification(token: string) {\n return this.post<ResendVerifResponse>('/user/verif/resend', undefined, { token })\n }\n}\n","import type {\n GenerateVouchersResponse,\n GetAvailableVouchersResponse,\n GetVoucherBalanceResponse,\n} from '../generated/types.gen.js'\nimport { BaseResource } from '../base-resource.js'\n\n/**\n * Voucher resource for reseller voucher management\n *\n * Note: These endpoints are only available for reseller accounts.\n */\nexport class VoucherResource extends BaseResource {\n /**\n * Get voucher balance for reseller accounts\n *\n * This endpoint allows resellers to check their remaining voucher balance.\n * Only available for accounts with reseller privileges.\n *\n * @example\n * ```ts\n * const balance = await client.voucher.getBalance()\n * console.log('Remaining balance:', balance.balance, '€')\n * ```\n *\n * @returns Voucher balance information\n */\n async getBalance() {\n return this.get<GetVoucherBalanceResponse>('/voucher/balance')\n }\n\n /**\n * Retrieve existing vouchers from reseller inventory\n *\n * This endpoint retrieves vouchers that were previously generated\n * and are available in your inventory.\n *\n * @param quantity - Optional number of vouchers to retrieve\n *\n * @example\n * ```ts\n * // Get all available vouchers\n * const allVouchers = await client.voucher.getVouchers()\n * console.log('Vouchers:', allVouchers?.codes)\n *\n * // Get specific quantity\n * const fiveVouchers = await client.voucher.getVouchers(5)\n * ```\n *\n * @returns List of voucher codes\n */\n async getVouchers(quantity?: number) {\n const params = quantity ? { quantity } : undefined\n return this.get<GetAvailableVouchersResponse>('/voucher/get', params)\n }\n\n /**\n * Generate new vouchers (deducts from reseller balance)\n *\n * This endpoint creates new vouchers and deducts the cost from your\n * reseller account balance.\n *\n * @param quantity - Number of vouchers to generate\n * @param duration - Voucher duration in days\n *\n * @example\n * ```ts\n * // Generate 10 vouchers valid for 30 days\n * const vouchers = await client.voucher.generateVouchers(10, 30)\n * console.log('Generated vouchers:', vouchers?.codes)\n *\n * // Generate 5 vouchers valid for 7 days\n * const weekVouchers = await client.voucher.generateVouchers(5, 7)\n * ```\n *\n * @returns List of newly generated voucher codes\n */\n async generateVouchers(quantity: number, duration: number) {\n return this.post<GenerateVouchersResponse>('/voucher/generate', {\n quantity,\n duration,\n })\n }\n}\n","import type { PingResponse } from './generated/types.gen.js'\nimport type { AllDebridConfig, ApiResponse, ExtractData } from './types.js'\nimport wretch from 'wretch'\nimport { createTypedError, NetworkError } from './errors.js'\nimport { HostResource } from './resources/host.js'\nimport { LinkResource } from './resources/link.js'\nimport { MagnetResource } from './resources/magnet.js'\nimport { PinResource } from './resources/pin.js'\nimport { UserResource } from './resources/user.js'\nimport { VoucherResource } from './resources/voucher.js'\n\nconst DEFAULT_BASE_URL = 'https://api.alldebrid.com/v4.1'\nconst DEFAULT_AGENT = '@alldebrid/sdk'\nconst DEFAULT_TIMEOUT = 30000\nconst DEFAULT_MAX_RETRIES = 3\n\n/**\n * Main AllDebrid client class\n */\nexport class AllDebridClient {\n private readonly config: Required<AllDebridConfig>\n\n /**\n * User resource for managing user account\n */\n public readonly user: UserResource\n\n /**\n * Link resource for unlocking and managing download links\n */\n public readonly link: LinkResource\n\n /**\n * Magnet resource for managing torrents\n */\n public readonly magnet: MagnetResource\n\n /**\n * Host resource for getting information about supported hosts\n */\n public readonly host: HostResource\n\n /**\n * Pin resource for PIN-based authentication\n */\n public readonly pin: PinResource\n\n /**\n * Voucher resource for reseller voucher management\n */\n public readonly voucher: VoucherResource\n\n constructor(config: AllDebridConfig) {\n // Merge config with defaults\n this.config = {\n apiKey: config.apiKey,\n agent: config.agent ?? DEFAULT_AGENT,\n baseUrl: config.baseUrl ?? DEFAULT_BASE_URL,\n timeout: config.timeout ?? DEFAULT_TIMEOUT,\n retry: config.retry ?? true,\n maxRetries: config.maxRetries ?? DEFAULT_MAX_RETRIES,\n }\n\n // Initialize resources\n this.user = new UserResource(this)\n this.link = new LinkResource(this)\n this.magnet = new MagnetResource(this)\n this.host = new HostResource(this)\n this.pin = new PinResource(this)\n this.voucher = new VoucherResource(this)\n }\n\n /**\n * Build query string from params\n */\n private buildUrl(path: string, params?: Record<string, unknown>): string {\n const allParams = {\n agent: this.config.agent,\n ...params,\n }\n\n const query = new URLSearchParams()\n for (const [key, value] of Object.entries(allParams)) {\n if (value !== undefined && value !== null) {\n if (Array.isArray(value)) {\n value.forEach((v) => query.append(`${key}[]`, String(v)))\n } else {\n query.append(key, String(value))\n }\n }\n }\n\n const queryString = query.toString()\n return queryString ? `${path}?${queryString}` : path\n }\n\n /**\n * Make a GET request\n * @template T - The generated response type (e.g., GetLinkUnlockResponse)\n * @param path - API endpoint path\n * @param params - Optional query parameters\n * @returns The extracted data from the response (without the { status, data } wrapper)\n * @internal\n */\n async get<T>(path: string, params?: Record<string, unknown>): Promise<ExtractData<T>> {\n try {\n const url = this.buildUrl(path, params)\n const json = await wretch(this.config.baseUrl)\n .auth(`Bearer ${this.config.apiKey}`)\n .url(url)\n .get()\n .json<ApiResponse<unknown>>()\n\n // Handle error responses\n if (json.status === 'error' && json.error) {\n throw createTypedError(json.error.code, json.error.message)\n }\n\n return json.data as ExtractData<T>\n } catch (error: any) {\n // Handle HTTP errors\n if (error.status === 401) {\n throw createTypedError('AUTH_BAD_APIKEY', 'Invalid API key or unauthorized access')\n }\n if (error.status === 403) {\n throw createTypedError('AUTH_BLOCKED', 'Access forbidden')\n }\n if (error.status === 429) {\n throw createTypedError('RATE_LIMITED', 'Too many requests')\n }\n\n // Re-throw if already our error type\n if (error.isAllDebridError) {\n throw error\n }\n\n // Wrap in NetworkError\n throw new NetworkError(error.message || 'Network error occurred', error.status)\n }\n }\n\n /**\n * Make a POST request with application/x-www-form-urlencoded\n * @template T - The generated response type\n * @param path - API endpoint path\n * @param body - Request body (will be converted to URLSearchParams)\n * @param params - Optional query parameters\n * @returns The extracted data from the response (without the { status, data } wrapper)\n * @internal\n */\n async post<T>(\n path: string,\n body?: unknown,\n params?: Record<string, unknown>,\n ): Promise<ExtractData<T>> {\n try {\n const url = this.buildUrl(path, params)\n\n // Convert body to URLSearchParams for application/x-www-form-urlencoded\n const formData = new URLSearchParams()\n if (body && typeof body === 'object') {\n for (const [key, value] of Object.entries(body)) {\n if (value !== undefined && value !== null) {\n if (Array.isArray(value)) {\n // Handle arrays (e.g., link[] for multiple links)\n value.forEach((v) => formData.append(key, String(v)))\n } else {\n formData.append(key, String(value))\n }\n }\n }\n }\n\n const json = await wretch(this.config.baseUrl)\n .auth(`Bearer ${this.config.apiKey}`)\n .url(url)\n .body(formData)\n .post()\n .json<ApiResponse<unknown>>()\n\n // Handle error responses\n if (json.status === 'error' && json.error) {\n throw createTypedError(json.error.code, json.error.message)\n }\n\n return json.data as ExtractData<T>\n } catch (error: any) {\n // Handle HTTP errors\n if (error.status === 401) {\n throw createTypedError('AUTH_BAD_APIKEY', 'Invalid API key or unauthorized access')\n }\n if (error.status === 403) {\n throw createTypedError('AUTH_BLOCKED', 'Access forbidden')\n }\n if (error.status === 429) {\n throw createTypedError('RATE_LIMITED', 'Too many requests')\n }\n\n // Re-throw if already our error type\n if (error.isAllDebridError) {\n throw error\n }\n\n // Wrap in NetworkError\n throw new NetworkError(error.message || 'Network error occurred', error.status)\n }\n }\n\n /**\n * Make a POST request with FormData (multipart/form-data)\n * @template T - The generated response type\n * @param path - API endpoint path\n * @param formData - Form data to send\n * @param params - Optional query parameters\n * @returns The extracted data from the response (without the { status, data } wrapper)\n * @internal\n */\n async postFormData<T>(\n path: string,\n formData: FormData,\n params?: Record<string, unknown>,\n ): Promise<ExtractData<T>> {\n try {\n const url = this.buildUrl(path, params)\n const json = await wretch(this.config.baseUrl)\n .auth(`Bearer ${this.config.apiKey}`)\n .url(url)\n .body(formData)\n .post()\n .json<ApiResponse<unknown>>()\n\n // Handle error responses\n if (json.status === 'error' && json.error) {\n throw createTypedError(json.error.code, json.error.message)\n }\n\n return json.data as ExtractData<T>\n } catch (error: any) {\n // Handle HTTP errors\n if (error.status === 401) {\n throw createTypedError('AUTH_BAD_APIKEY', 'Invalid API key or unauthorized access')\n }\n if (error.status === 403) {\n throw createTypedError('AUTH_BLOCKED', 'Access forbidden')\n }\n if (error.status === 429) {\n throw createTypedError('RATE_LIMITED', 'Too many requests')\n }\n\n // Re-throw if already our error type\n if (error.isAllDebridError) {\n throw error\n }\n\n // Wrap in NetworkError\n throw new NetworkError(error.message || 'Network error occurred', error.status)\n }\n }\n\n /**\n * Test the API connection\n *\n * This endpoint doesn't require authentication and can be used to verify\n * that the AllDebrid API is reachable.\n *\n * @example\n * ```ts\n * const result = await client.ping()\n * console.log(result.ping) // 'pong'\n * ```\n *\n * @returns Ping response with 'pong' message\n */\n async ping() {\n return this.get<PingResponse>('/ping')\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/base-resource.ts","../src/resources/host.ts","../src/resources/link.ts","../src/resources/magnet.ts","../src/resources/pin.ts","../src/resources/user.ts","../src/resources/voucher.ts","../src/client.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { ApiError } from './types.js'\n\n/**\n * Base error class for AllDebrid SDK errors\n */\nexport class AllDebridError extends Error {\n public readonly code: string\n public readonly isAllDebridError = true\n\n constructor(code: string, message: string) {\n super(message)\n this.name = 'AllDebridError'\n this.code = code\n\n // Maintains proper stack trace for where our error was thrown (only available on V8)\n if ('captureStackTrace' in Error && typeof (Error as any).captureStackTrace === 'function') {\n ;(Error as any).captureStackTrace(this, AllDebridError)\n }\n }\n\n /**\n * Create an AllDebridError from an API error response\n */\n static fromApiError(error: ApiError): AllDebridError {\n return new AllDebridError(error.code, error.message)\n }\n}\n\n/**\n * Authentication related errors\n */\nexport class AuthenticationError extends AllDebridError {\n constructor(code: string, message: string) {\n super(code, message)\n this.name = 'AuthenticationError'\n }\n}\n\n/**\n * Link processing errors\n */\nexport class LinkError extends AllDebridError {\n constructor(code: string, message: string) {\n super(code, message)\n this.name = 'LinkError'\n }\n}\n\n/**\n * Magnet/Torrent related errors\n */\nexport class MagnetError extends AllDebridError {\n constructor(code: string, message: string) {\n super(code, message)\n this.name = 'MagnetError'\n }\n}\n\n/**\n * Network/HTTP errors\n */\nexport class NetworkError extends AllDebridError {\n constructor(\n message: string,\n public readonly statusCode?: number,\n ) {\n super('NETWORK_ERROR', message)\n this.name = 'NetworkError'\n }\n}\n\n/**\n * Helper to determine error type from error code\n */\nexport function createTypedError(code: string, message: string): AllDebridError {\n if (code.startsWith('AUTH_')) {\n return new AuthenticationError(code, message)\n }\n if (\n code.startsWith('LINK_') ||\n code.startsWith('REDIRECTOR_') ||\n code.startsWith('STREAM_') ||\n code.startsWith('DELAYED_')\n ) {\n return new LinkError(code, message)\n }\n if (code.startsWith('MAGNET_')) {\n return new MagnetError(code, message)\n }\n return new AllDebridError(code, message)\n}\n","import type { AllDebridClient } from './client.js'\nimport type { ExtractData } from './types.js'\n\n/**\n * Base class for all resources\n * Provides access to HTTP methods\n * @internal\n */\nexport abstract class BaseResource {\n constructor(protected readonly client: AllDebridClient) {}\n\n /**\n * Make a GET request\n * @template T - The generated response type (e.g., GetLinkUnlockResponse)\n * @param path - API endpoint path\n * @param params - Optional query parameters\n * @returns The extracted data from the response (without the { status, data } wrapper)\n */\n protected async get<T>(path: string, params?: Record<string, unknown>): Promise<ExtractData<T>> {\n return this.client.get<T>(path, params)\n }\n\n /**\n * Make a POST request\n * @template T - The generated response type\n * @param path - API endpoint path\n * @param body - Request body\n * @param params - Optional query parameters\n * @returns The extracted data from the response (without the { status, data } wrapper)\n */\n protected async post<T>(\n path: string,\n body?: unknown,\n params?: Record<string, unknown>,\n ): Promise<ExtractData<T>> {\n return this.client.post<T>(path, body, params)\n }\n\n /**\n * Make a POST request with FormData (multipart/form-data)\n * @template T - The generated response type\n * @param path - API endpoint path\n * @param formData - Form data to send\n * @param params - Optional query parameters\n * @returns The extracted data from the response (without the { status, data } wrapper)\n */\n protected async postFormData<T>(\n path: string,\n formData: FormData,\n params?: Record<string, unknown>,\n ): Promise<ExtractData<T>> {\n return this.client.postFormData<T>(path, formData, params)\n }\n}\n","import type {\n GetHostDomainsResponse,\n GetHostPriorityResponse,\n GetHostsResponse,\n} from '../generated/types.gen.js'\nimport { BaseResource } from '../base-resource.js'\n\n/**\n * Host resource for getting information about supported hosts\n */\nexport class HostResource extends BaseResource {\n /**\n * Get list of all supported hosts with their information\n *\n * @param hostOnly - If true, only return hosts (exclude streams and redirectors)\n *\n * @example\n * ```ts\n * const hosts = await client.host.list()\n * console.log(hosts.hosts) // All supported file hosts\n * console.log(hosts.streams) // Streaming hosts\n * console.log(hosts.redirectors) // Link redirectors\n * ```\n */\n async list(hostOnly?: boolean) {\n const params = hostOnly ? { hostOnly: '1' } : undefined\n return this.get<GetHostsResponse>('/hosts', params)\n }\n\n /**\n * Get array of all supported domain names\n *\n * @example\n * ```ts\n * const domains = await client.host.domains()\n * console.log(domains) // ['rapidgator.net', 'uploaded.net', ...]\n * ```\n */\n async domains() {\n return this.get<GetHostDomainsResponse>('/hosts/domains')\n }\n\n /**\n * Get hosts ordered by restriction level (priority list)\n *\n * @example\n * ```ts\n * const priority = await client.host.priority()\n * console.log(priority.hosts) // Ordered list with restriction levels\n * ```\n */\n async priority() {\n return this.get<GetHostPriorityResponse>('/hosts/priority')\n }\n}\n","import type {\n GetDelayedStatusResponse,\n GetLinkInfosResponse,\n GetRedirectorLinksResponse,\n GetStreamingLinkResponse,\n UnlockLinkResponse,\n} from '../generated/types.gen.js'\nimport { BaseResource } from '../base-resource.js'\n\n/**\n * Options for polling delayed link generation\n */\nexport interface PollOptions {\n /**\n * Polling interval in milliseconds\n * @default 2000\n */\n interval?: number\n\n /**\n * Maximum number of polling attempts\n * @default 30\n */\n maxAttempts?: number\n\n /**\n * Callback called on each polling attempt\n */\n onPoll?: (attempt: number) => void\n}\n\n/**\n * Link resource for unlocking and managing download links\n */\nexport class LinkResource extends BaseResource {\n /**\n * Get information about one or more links\n *\n * @param links - Single link or array of links to get info for\n * @param password - Optional password for password-protected links\n *\n * @example\n * ```ts\n * const data = await client.link.infos('https://example.com/file.zip')\n * console.log(data.infos)\n *\n * // With password\n * const protectedData = await client.link.infos(\n * 'https://example.com/protected.zip',\n * 'mypassword'\n * )\n * ```\n */\n async infos(links: string | string[], password?: string) {\n const linksArray = Array.isArray(links) ? links : [links]\n const params = password ? { password } : undefined\n return this.post<GetLinkInfosResponse>('/link/infos', { 'link[]': linksArray }, params)\n }\n\n /**\n * Extract links from redirectors/link protectors\n *\n * @param link - The redirector link to extract from\n *\n * @example\n * ```ts\n * const data = await client.link.redirector('https://linkprotector.com/abc123')\n * console.log(data.links)\n * ```\n */\n async redirector(link: string) {\n return this.post<GetRedirectorLinksResponse>('/link/redirector', {\n link,\n })\n }\n\n /**\n * Unlock a download link\n *\n * @param link - The link to unlock\n * @param password - Optional password for password-protected links\n *\n * @example\n * ```ts\n * const result = await client.link.unlock('https://example.com/file.zip')\n * if (result.link) {\n * console.log('Direct link:', result.link)\n * } else if (result.delayed) {\n * // Handle delayed generation\n * const delayedResult = await client.link.delayed(result.delayed)\n * }\n *\n * // With password\n * const protectedResult = await client.link.unlock(\n * 'https://example.com/protected.zip',\n * 'mypassword'\n * )\n * ```\n */\n async unlock(link: string, password?: string) {\n const params = password ? { password } : undefined\n return this.post<UnlockLinkResponse>('/link/unlock', { link }, params)\n }\n\n /**\n * Unlock a link and automatically poll if delayed\n * Note: The API response format doesn't include a delayed field in the current OpenAPI spec.\n * This method will be updated once the delayed mechanism is documented.\n *\n * @param link - The link to unlock\n * @param _options - Polling options (currently unused)\n *\n * @example\n * ```ts\n * const result = await client.link.unlockWithPolling('https://example.com/file.zip')\n * console.log('Direct link:', result.link)\n * ```\n */\n async unlockWithPolling(link: string, _options: PollOptions = {}) {\n // For now, just unlock without polling\n // TODO: Implement polling once delayed field is added to API response\n return this.unlock(link)\n }\n\n /**\n * Get streaming options for a generated link\n *\n * @param id - The generated link ID or streaming ID\n *\n * @example\n * ```ts\n * const streams = await client.link.streaming('abc123')\n * ```\n */\n async streaming(id: string, stream: string) {\n return this.post<GetStreamingLinkResponse>('/link/streaming', {\n id,\n stream,\n })\n }\n\n /**\n * Get the status/result of a delayed link generation\n *\n * @param id - The delayed generation ID\n *\n * @example\n * ```ts\n * const result = await client.link.delayed('delayed_id_123')\n * ```\n */\n async delayed(id: number) {\n return this.post<GetDelayedStatusResponse>('/link/delayed', {\n id,\n })\n }\n}\n","import type {\n DeleteMagnetResponse,\n GetMagnetFilesResponse,\n GetMagnetStatusResponse,\n RestartMagnetResponse,\n UploadMagnetsResponse,\n UploadTorrentFileResponse,\n} from '../generated/types.gen.js'\nimport { BaseResource } from '../base-resource.js'\n\n/**\n * Options for live mode status polling\n */\nexport interface LiveStatusOptions {\n /**\n * Session ID - Generate a random number and keep it consistent for the entire session\n * @example Math.floor(Math.random() * 1000000)\n */\n session: number\n\n /**\n * Counter for synchronization - Start at 0 and increment with each call\n * The API will return the next counter value to use\n */\n counter: number\n}\n\n/**\n * Options for watching magnet status\n */\nexport interface WatchOptions {\n /**\n * Polling interval in milliseconds\n * @default 3000\n */\n interval?: number\n\n /**\n * Maximum number of polling attempts (0 = infinite)\n * @default 0\n */\n maxAttempts?: number\n\n /**\n * Callback called on each status update\n */\n onUpdate?: (status: any) => void\n\n /**\n * Stop watching when magnet reaches this status\n * @default 'Ready'\n */\n stopOnStatus?: string\n}\n\n/**\n * Magnet/Torrent resource for managing torrent downloads\n */\nexport class MagnetResource extends BaseResource {\n /**\n * Upload magnets by URI or hash\n *\n * @param magnets - Single magnet URI/hash or array of magnets\n *\n * @example\n * ```ts\n * const result = await client.magnet.upload('magnet:?xt=urn:btih:...')\n * console.log('Magnet ID:', result.magnets[0].id)\n * ```\n */\n async upload(magnets: string | string[]) {\n const magnetsArray = Array.isArray(magnets) ? magnets : [magnets]\n return this.post<UploadMagnetsResponse>('/magnet/upload', {\n magnets: magnetsArray,\n })\n }\n\n /**\n * Upload a torrent file\n *\n * @param file - The torrent file (Blob or File)\n * @param filename - Optional filename (defaults to 'torrent.torrent' for Blob, or file.name for File)\n *\n * @example\n * ```ts\n * const file = new File([buffer], 'torrent.torrent')\n * const result = await client.magnet.uploadFile(file)\n *\n * // Or with a Blob and custom filename\n * const blob = new Blob([buffer])\n * const result = await client.magnet.uploadFile(blob, 'my-torrent.torrent')\n * ```\n */\n async uploadFile(file: Blob | File, filename?: string) {\n const formData = new FormData()\n\n // Determine the filename to use\n const actualFilename = filename || (file instanceof File ? file.name : 'torrent.torrent')\n\n // Append with explicit filename\n formData.append('files[]', file, actualFilename)\n\n return this.postFormData<UploadTorrentFileResponse>('/magnet/upload/file', formData)\n }\n\n /**\n * Get the status of a specific magnet by ID\n *\n * @param id - Magnet ID to get status for\n *\n * @example\n * ```ts\n * const status = await client.magnet.status(123)\n * console.log(status.magnets[0]?.status) // 'Downloading', 'Ready', etc.\n * ```\n *\n * @remarks\n * This endpoint uses AllDebrid API v4.1 (POST method)\n * Migrated from v4 GET endpoint which was deprecated on 2024-10-16\n */\n async status(id: number) {\n const data = await this.post<GetMagnetStatusResponse>('/magnet/status', { id })\n\n // Fix: AllDebrid API returns an object instead of array when filtering by ID\n // This is an API inconsistency, so we normalize it to always return an array\n if (data?.magnets && !Array.isArray(data.magnets)) {\n return {\n ...data,\n magnets: [data.magnets],\n }\n }\n\n return data\n }\n\n /**\n * Get list of magnets with optional status filter\n *\n * @param statusFilter - Optional filter by status: 'active', 'ready', 'expired', or 'error'\n *\n * @example\n * ```ts\n * // Get all magnets\n * const allMagnets = await client.magnet.statusList()\n *\n * // Get only active magnets\n * const activeMagnets = await client.magnet.statusList('active')\n *\n * // Get only ready magnets\n * const readyMagnets = await client.magnet.statusList('ready')\n * ```\n *\n * @remarks\n * This endpoint uses AllDebrid API v4.1 (POST method)\n */\n async statusList(statusFilter?: 'active' | 'ready' | 'expired' | 'error') {\n const body = statusFilter ? { status: statusFilter } : undefined\n return this.post<GetMagnetStatusResponse>('/magnet/status', body)\n }\n\n /**\n * Get magnet status using live mode for bandwidth-optimized delta synchronization\n *\n * Live mode is designed for monitoring multiple magnets efficiently by only transmitting\n * changes between polling intervals, drastically reducing bandwidth usage for dashboards\n * and real-time monitoring applications.\n *\n * ## How it works\n *\n * 1. **Session initialization**: Generate a random session ID and start with counter = 0\n * 2. **First call (fullsync)**: Returns ALL magnets with `fullsync: true`\n * 3. **Update counter**: Use the `counter` value returned by the API for the next call\n * 4. **Subsequent calls (delta)**: Returns ONLY magnets that changed since last call\n * 5. **Repeat**: Keep calling with updated counter to receive only deltas\n *\n * ## When to use\n *\n * - ✅ Monitoring multiple active magnets simultaneously\n * - ✅ Building real-time dashboards\n * - ✅ High-frequency polling scenarios (every few seconds)\n * - ❌ Watching a single specific magnet (use `watch()` instead)\n *\n * ## Important notes\n *\n * - **Don't use the `id` parameter**: Passing an ID defeats the purpose of live mode\n * as it disables delta sync and behaves like a regular `status()` call\n * - **Session persistence**: Keep the same session ID for the entire monitoring session\n * - **Counter tracking**: Always update the counter with the value returned by the API\n * - **Empty deltas**: When no magnets changed, `magnets` will be an empty array\n *\n * @param options - Live mode session options\n * @param options.session - Unique session ID (generate once: `Math.floor(Math.random() * 1000000)`)\n * @param options.counter - Sync counter (start at 0, then use value from previous API response)\n *\n * @example\n * ```ts\n * // Initialize session\n * const session = Math.floor(Math.random() * 1000000)\n * let counter = 0\n *\n * // First call - returns all magnets (fullsync: true)\n * const firstCall = await client.magnet.statusLive({ session, counter })\n * console.log('Full sync:', firstCall.fullsync) // true\n * console.log('All magnets:', firstCall.magnets) // Array of all magnets\n * counter = firstCall.counter // Update counter for next call\n *\n * // Second call - returns only magnets that changed\n * await new Promise(resolve => setTimeout(resolve, 3000)) // Wait 3 seconds\n * const secondCall = await client.magnet.statusLive({ session, counter })\n * console.log('Delta sync:', secondCall.magnets) // Only changed magnets\n * counter = secondCall.counter\n *\n * // Example: Monitor all magnets until none are active\n * const activeMagnets = new Map()\n *\n * while (true) {\n * const response = await client.magnet.statusLive({ session, counter })\n * counter = response.counter ?? counter\n *\n * // Update our local state with changes\n * if (response.fullsync) {\n * activeMagnets.clear()\n * response.magnets?.forEach(m => activeMagnets.set(m.id, m))\n * } else {\n * response.magnets?.forEach(m => {\n * if (m.status === 'Ready' || m.status === 'Error' || m.status === 'Expired') {\n * activeMagnets.delete(m.id)\n * } else {\n * activeMagnets.set(m.id, m)\n * }\n * })\n * }\n *\n * // Display current state\n * console.log(`Active downloads: ${activeMagnets.size}`)\n * activeMagnets.forEach(m => {\n * console.log(` ${m.filename}: ${m.status} - ${m.downloaded}/${m.size} bytes`)\n * })\n *\n * // Stop when no more active magnets\n * if (activeMagnets.size === 0) {\n * console.log('All downloads completed!')\n * break\n * }\n *\n * await new Promise(resolve => setTimeout(resolve, 3000))\n * }\n * ```\n *\n * @remarks\n * This method is ideal for scenarios where you're monitoring multiple magnets and want\n * to minimize bandwidth. For simple single-magnet monitoring, use `watch()` instead.\n */\n async statusLive(options: LiveStatusOptions) {\n const body: any = {\n session: options.session,\n counter: options.counter,\n }\n\n return this.post<GetMagnetStatusResponse>('/magnet/status', body)\n }\n\n /**\n * Delete a magnet\n *\n * @param id - The magnet ID to delete\n *\n * @example\n * ```ts\n * await client.magnet.delete(123)\n * ```\n */\n async delete(id: number) {\n return this.post<DeleteMagnetResponse>('/magnet/delete', {\n id,\n })\n }\n\n /**\n * Restart one or more failed magnets\n *\n * @param ids - Single magnet ID or array of magnet IDs to restart (numbers)\n *\n * @example\n * ```ts\n * // Restart single magnet\n * await client.magnet.restart(123)\n *\n * // Restart multiple magnets\n * await client.magnet.restart([123, 456])\n * ```\n */\n async restart(ids: number | number[]) {\n const idsArray = Array.isArray(ids) ? ids : [ids]\n return this.post<RestartMagnetResponse>('/magnet/restart', {\n ids: idsArray,\n })\n }\n\n /**\n * Get files for a completed magnet\n *\n * @param ids - The magnet ID or IDs to get files for\n *\n * @example\n * ```ts\n * const data = await client.magnet.files(123)\n * data?.magnets?.forEach(magnet => {\n * console.log(magnet.filename, magnet.files)\n * })\n * ```\n *\n * @remarks\n * Files are now retrieved separately from magnet status (since v4.1)\n * Only available for magnets with status 'Ready'\n */\n async files(ids: number | number[]) {\n const formData = new FormData()\n const idsArray = Array.isArray(ids) ? ids : [ids]\n for (const id of idsArray) {\n formData.append('id[]', String(id))\n }\n return this.postFormData<GetMagnetFilesResponse>('/magnet/files', formData)\n }\n\n /**\n * Watch a magnet's status with automatic polling\n *\n * This is a simple helper that polls the status of a specific magnet until it reaches\n * a target status (default: 'Ready'). For advanced use cases with multiple magnets\n * or bandwidth optimization, use `statusLive()` directly instead.\n *\n * @param id - The magnet ID to watch\n * @param options - Watch options\n * @param options.interval - Polling interval in milliseconds (default: 3000)\n * @param options.maxAttempts - Maximum polling attempts, 0 for infinite (default: 0)\n * @param options.onUpdate - Callback called on each status update\n * @param options.stopOnStatus - Stop when magnet reaches this status (default: 'Ready')\n *\n * @example\n * ```ts\n * await client.magnet.watch(123, {\n * onUpdate: (status) => console.log('Status:', status.magnets[0]?.status),\n * stopOnStatus: 'Ready'\n * })\n * ```\n *\n * @remarks\n * For monitoring multiple magnets efficiently, use `statusLive()` directly.\n * See the `statusLive()` documentation for details on delta synchronization.\n */\n async watch(id: number, options: WatchOptions = {}) {\n const { interval = 3000, maxAttempts = 0, onUpdate, stopOnStatus = 'Ready' } = options\n\n let attempt = 0\n\n while (maxAttempts === 0 || attempt < maxAttempts) {\n attempt++\n\n const status = await this.status(id)\n\n onUpdate?.(status)\n\n // Check if we should stop (magnets is normalized to an array with one element)\n const magnet = status?.magnets?.[0]\n if (magnet?.status === stopOnStatus) {\n return status\n }\n\n // Wait before next attempt\n await new Promise((resolve) => setTimeout(resolve, interval))\n }\n\n throw new Error(\n `Watch timeout: magnet did not reach '${stopOnStatus}' status after ${maxAttempts} attempts`,\n )\n }\n}\n","import type { CheckPinResponse, GetPinResponse } from '../generated/types.gen.js'\nimport { BaseResource } from '../base-resource.js'\n\n/**\n * Pin resource for PIN-based authentication flow\n *\n * The PIN flow allows users to authenticate without directly providing their API key.\n * This is useful for applications where you want users to authorize access through\n * the AllDebrid website.\n */\nexport class PinResource extends BaseResource {\n /**\n * Generate a new PIN code for authentication\n *\n * This initiates the PIN authentication flow. The user should visit the\n * returned URL to authorize the application.\n *\n * @example\n * ```ts\n * const pinData = await client.pin.generate()\n * console.log('Visit:', pinData.user_url)\n * console.log('PIN:', pinData.pin)\n *\n * // Poll the check endpoint until user authorizes\n * const auth = await client.pin.check(pinData.check, pinData.pin)\n * if (auth.activated) {\n * console.log('API Key:', auth.apikey)\n * }\n * ```\n *\n * @returns PIN code and authorization URL\n */\n async generate() {\n return super.get<GetPinResponse>('/pin/get')\n }\n\n /**\n * Check the status of a PIN authentication\n *\n * Poll this endpoint to check if the user has authorized the application.\n * Once authorized, the response will include the API key.\n *\n * @param check - Check ID from /pin/get\n * @param pin - PIN code from /pin/get\n *\n * @example\n * ```ts\n * const pinData = await client.pin.generate()\n *\n * // Poll every few seconds until activated\n * const checkStatus = async () => {\n * const result = await client.pin.check(pinData.check, pinData.pin)\n * if (result?.activated && result?.apikey) {\n * console.log('Authorized! API Key:', result.apikey)\n * return result.apikey\n * }\n * // Wait and try again\n * await new Promise(resolve => setTimeout(resolve, 3000))\n * return checkStatus()\n * }\n *\n * const apikey = await checkStatus()\n * ```\n *\n * @returns Authorization status and API key (if activated)\n */\n async check(check: string, pin: string) {\n return super.get<CheckPinResponse>('/pin/check', { check, pin })\n }\n\n /**\n * Helper method to wait for PIN authorization with automatic polling\n *\n * This method handles the polling logic for you, making it easier to\n * implement the PIN authentication flow.\n *\n * @param check - Check ID from /pin/get\n * @param pin - PIN code from /pin/get\n * @param options - Polling options\n * @param options.timeout - Maximum time to wait in milliseconds (default: 600000 = 10 minutes)\n * @param options.interval - Polling interval in milliseconds (default: 3000 = 3 seconds)\n *\n * @example\n * ```ts\n * const pinData = await client.pin.generate()\n * console.log('Visit:', pinData.user_url)\n *\n * try {\n * const apikey = await client.pin.waitForAuth(pinData.check, pinData.pin, {\n * timeout: 600000, // 10 minutes\n * interval: 3000, // Check every 3 seconds\n * })\n * console.log('Authorized! API Key:', apikey)\n * } catch (error) {\n * console.error('Authorization timed out or failed')\n * }\n * ```\n *\n * @returns The API key once authorized\n * @throws Error if timeout is reached or authorization fails\n */\n async waitForAuth(\n check: string,\n pin: string,\n options: {\n /** Maximum time to wait in milliseconds (default: 600000 = 10 minutes) */\n timeout?: number\n /** Polling interval in milliseconds (default: 3000 = 3 seconds) */\n interval?: number\n } = {},\n ): Promise<string> {\n const timeout = options.timeout ?? 600000 // 10 minutes default\n const interval = options.interval ?? 3000 // 3 seconds default\n const startTime = Date.now()\n\n while (Date.now() - startTime < timeout) {\n const result = await this.check(check, pin)\n\n if (result?.activated && result?.apikey) {\n return result.apikey\n }\n\n // Wait before next poll\n await new Promise((resolve) => setTimeout(resolve, interval))\n }\n\n throw new Error('PIN authorization timeout - user did not authorize within the time limit')\n }\n}\n","import type {\n ClearNotificationResponse,\n DeleteHistoryResponse,\n DeleteSavedLinksResponse,\n GetHistoryResponse,\n GetSavedLinksResponse,\n GetUserHostsResponse,\n GetUserResponse,\n GetVerifStatusResponse,\n ResendVerifResponse,\n SaveLinksResponse,\n} from '../generated/types.gen.js'\nimport { BaseResource } from '../base-resource.js'\n\n/**\n * User resource for managing user account information\n */\nexport class UserResource extends BaseResource {\n /**\n * Get user profile information including premium status and quotas\n *\n * @example\n * ```ts\n * const data = await client.user.getInfo()\n * console.log(data.user.username, data.user.isPremium)\n * ```\n */\n async getInfo() {\n return this.get<GetUserResponse>('/user')\n }\n\n /**\n * Get available hosts for the current user based on their subscription\n *\n * @param hostOnly - If true, only return hosts data (exclude streams and redirectors)\n *\n * @example\n * ```ts\n * const hosts = await client.user.getHosts()\n * console.log(Object.keys(hosts.hosts))\n * ```\n */\n async getHosts(hostOnly?: boolean) {\n const params = hostOnly ? { hostOnly: '1' } : undefined\n return this.get<GetUserHostsResponse>('/user/hosts', params)\n }\n\n /**\n * Clear a specific notification by code\n *\n * @param code - The notification code to clear\n *\n * @example\n * ```ts\n * await client.user.clearNotification('SOME_NOTIF_CODE')\n * ```\n */\n async clearNotification(code: string) {\n await this.post<ClearNotificationResponse>('/user/notification/clear', { code })\n }\n\n // ============================================\n // Saved Links Management\n // ============================================\n\n /**\n * Get all saved links\n *\n * @example\n * ```ts\n * const savedLinks = await client.user.getLinks()\n * console.log(savedLinks.links)\n * ```\n */\n async getLinks() {\n return this.get<GetSavedLinksResponse>('/user/links')\n }\n\n /**\n * Save one or multiple links for later use\n *\n * Supports batch operations - you can save multiple links in a single request.\n *\n * @param links - Single link or array of links to save\n *\n * @example\n * ```ts\n * // Save single link\n * await client.user.saveLink('https://example.com/file.zip')\n *\n * // Save multiple links at once\n * await client.user.saveLink([\n * 'https://example.com/file1.zip',\n * 'https://example.com/file2.zip',\n * 'https://example.com/file3.zip'\n * ])\n * ```\n */\n async saveLink(links: string | string[]) {\n const linksArray = Array.isArray(links) ? links : [links]\n const formData = new FormData()\n\n // API expects links[] array format\n for (const link of linksArray) {\n formData.append('links[]', link)\n }\n\n return this.postFormData<SaveLinksResponse>('/user/links/save', formData)\n }\n\n /**\n * Delete one or multiple saved links\n *\n * Supports batch operations - you can delete multiple links in a single request.\n *\n * @param links - Single link or array of links to delete (can be saved link IDs or URLs)\n *\n * @example\n * ```ts\n * // Delete single link\n * await client.user.deleteLink('saved-link-id')\n *\n * // Delete multiple links at once\n * await client.user.deleteLink([\n * 'saved-link-id-1',\n * 'saved-link-id-2',\n * 'saved-link-id-3'\n * ])\n * ```\n */\n async deleteLink(links: string | string[]) {\n const linksArray = Array.isArray(links) ? links : [links]\n const formData = new FormData()\n\n // API expects links[] array format\n for (const link of linksArray) {\n formData.append('links[]', link)\n }\n\n return this.postFormData<DeleteSavedLinksResponse>('/user/links/delete', formData)\n }\n\n // ============================================\n // History Management\n // ============================================\n\n /**\n * Get user history (if enabled in account settings)\n *\n * @example\n * ```ts\n * const history = await client.user.getHistory()\n * console.log(history.links)\n * ```\n */\n async getHistory() {\n return this.get<GetHistoryResponse>('/user/history')\n }\n\n /**\n * Clear user history\n *\n * @example\n * ```ts\n * await client.user.clearHistory()\n * ```\n */\n async clearHistory() {\n return this.post<DeleteHistoryResponse>('/user/history/delete')\n }\n\n // ============================================\n // Email Verification\n // ============================================\n\n /**\n * Check email verification status\n *\n * @param token - Verification token\n *\n * @example\n * ```ts\n * const status = await client.user.getVerificationStatus('verification-token')\n * console.log(status.verif) // 'waiting', 'allowed', or 'denied'\n * ```\n */\n async getVerificationStatus(token: string) {\n return this.post<GetVerifStatusResponse>('/user/verif', undefined, { token })\n }\n\n /**\n * Resend verification email\n *\n * @param token - Verification token\n *\n * @example\n * ```ts\n * await client.user.resendVerification('verification-token')\n * ```\n */\n async resendVerification(token: string) {\n return this.post<ResendVerifResponse>('/user/verif/resend', undefined, { token })\n }\n}\n","import type {\n GenerateVouchersResponse,\n GetAvailableVouchersResponse,\n GetVoucherBalanceResponse,\n} from '../generated/types.gen.js'\nimport { BaseResource } from '../base-resource.js'\n\n/**\n * Voucher resource for reseller voucher management\n *\n * Note: These endpoints are only available for reseller accounts.\n */\nexport class VoucherResource extends BaseResource {\n /**\n * Get voucher balance for reseller accounts\n *\n * This endpoint allows resellers to check their remaining voucher balance.\n * Only available for accounts with reseller privileges.\n *\n * @example\n * ```ts\n * const balance = await client.voucher.getBalance()\n * console.log('Remaining balance:', balance.balance, '€')\n * ```\n *\n * @returns Voucher balance information\n */\n async getBalance() {\n return this.get<GetVoucherBalanceResponse>('/voucher/balance')\n }\n\n /**\n * Retrieve existing vouchers from reseller inventory\n *\n * This endpoint retrieves vouchers that were previously generated\n * and are available in your inventory.\n *\n * @param quantity - Optional number of vouchers to retrieve\n *\n * @example\n * ```ts\n * // Get all available vouchers\n * const allVouchers = await client.voucher.getVouchers()\n * console.log('Vouchers:', allVouchers?.codes)\n *\n * // Get specific quantity\n * const fiveVouchers = await client.voucher.getVouchers(5)\n * ```\n *\n * @returns List of voucher codes\n */\n async getVouchers(quantity?: number) {\n const params = quantity ? { quantity } : undefined\n return this.get<GetAvailableVouchersResponse>('/voucher/get', params)\n }\n\n /**\n * Generate new vouchers (deducts from reseller balance)\n *\n * This endpoint creates new vouchers and deducts the cost from your\n * reseller account balance.\n *\n * @param quantity - Number of vouchers to generate\n * @param duration - Voucher duration in days\n *\n * @example\n * ```ts\n * // Generate 10 vouchers valid for 30 days\n * const vouchers = await client.voucher.generateVouchers(10, 30)\n * console.log('Generated vouchers:', vouchers?.codes)\n *\n * // Generate 5 vouchers valid for 7 days\n * const weekVouchers = await client.voucher.generateVouchers(5, 7)\n * ```\n *\n * @returns List of newly generated voucher codes\n */\n async generateVouchers(quantity: number, duration: number) {\n return this.post<GenerateVouchersResponse>('/voucher/generate', {\n quantity,\n duration,\n })\n }\n}\n","import type { PingResponse } from './generated/types.gen.js'\nimport type { AllDebridConfig, ApiResponse, ExtractData } from './types.js'\nimport wretch from 'wretch'\nimport { createTypedError, NetworkError } from './errors.js'\nimport { HostResource } from './resources/host.js'\nimport { LinkResource } from './resources/link.js'\nimport { MagnetResource } from './resources/magnet.js'\nimport { PinResource } from './resources/pin.js'\nimport { UserResource } from './resources/user.js'\nimport { VoucherResource } from './resources/voucher.js'\n\nconst DEFAULT_BASE_URL = 'https://api.alldebrid.com/v4.1'\nconst DEFAULT_AGENT = '@alldebrid/sdk'\nconst DEFAULT_TIMEOUT = 30000\nconst DEFAULT_MAX_RETRIES = 3\n\n/**\n * Main AllDebrid client class\n */\nexport class AllDebridClient {\n private readonly config: Required<AllDebridConfig>\n\n /**\n * User resource for managing user account\n */\n public readonly user: UserResource\n\n /**\n * Link resource for unlocking and managing download links\n */\n public readonly link: LinkResource\n\n /**\n * Magnet resource for managing torrents\n */\n public readonly magnet: MagnetResource\n\n /**\n * Host resource for getting information about supported hosts\n */\n public readonly host: HostResource\n\n /**\n * Pin resource for PIN-based authentication\n */\n public readonly pin: PinResource\n\n /**\n * Voucher resource for reseller voucher management\n */\n public readonly voucher: VoucherResource\n\n constructor(config: AllDebridConfig) {\n // Merge config with defaults\n this.config = {\n apiKey: config.apiKey,\n agent: config.agent ?? DEFAULT_AGENT,\n baseUrl: config.baseUrl ?? DEFAULT_BASE_URL,\n timeout: config.timeout ?? DEFAULT_TIMEOUT,\n retry: config.retry ?? true,\n maxRetries: config.maxRetries ?? DEFAULT_MAX_RETRIES,\n }\n\n // Initialize resources\n this.user = new UserResource(this)\n this.link = new LinkResource(this)\n this.magnet = new MagnetResource(this)\n this.host = new HostResource(this)\n this.pin = new PinResource(this)\n this.voucher = new VoucherResource(this)\n }\n\n /**\n * Build query string from params\n */\n private buildUrl(path: string, params?: Record<string, unknown>): string {\n const allParams = {\n agent: this.config.agent,\n ...params,\n }\n\n const query = new URLSearchParams()\n for (const [key, value] of Object.entries(allParams)) {\n if (value !== undefined && value !== null) {\n if (Array.isArray(value)) {\n value.forEach((v) => query.append(`${key}[]`, String(v)))\n } else {\n query.append(key, String(value))\n }\n }\n }\n\n const queryString = query.toString()\n return queryString ? `${path}?${queryString}` : path\n }\n\n /**\n * Make a GET request\n * @template T - The generated response type (e.g., GetLinkUnlockResponse)\n * @param path - API endpoint path\n * @param params - Optional query parameters\n * @returns The extracted data from the response (without the { status, data } wrapper)\n * @internal\n */\n async get<T>(path: string, params?: Record<string, unknown>): Promise<ExtractData<T>> {\n try {\n const url = this.buildUrl(path, params)\n const json = await wretch(this.config.baseUrl)\n .auth(`Bearer ${this.config.apiKey}`)\n .url(url)\n .get()\n .json<ApiResponse<unknown>>()\n\n // Handle error responses\n if (json.status === 'error' && json.error) {\n throw createTypedError(json.error.code, json.error.message)\n }\n\n return json.data as ExtractData<T>\n } catch (error: any) {\n // Handle HTTP errors\n if (error.status === 401) {\n throw createTypedError('AUTH_BAD_APIKEY', 'Invalid API key or unauthorized access')\n }\n if (error.status === 403) {\n throw createTypedError('AUTH_BLOCKED', 'Access forbidden')\n }\n if (error.status === 429) {\n throw createTypedError('RATE_LIMITED', 'Too many requests')\n }\n\n // Re-throw if already our error type\n if (error.isAllDebridError) {\n throw error\n }\n\n // Wrap in NetworkError\n throw new NetworkError(error.message || 'Network error occurred', error.status)\n }\n }\n\n /**\n * Make a POST request with application/x-www-form-urlencoded\n * @template T - The generated response type\n * @param path - API endpoint path\n * @param body - Request body (will be converted to URLSearchParams)\n * @param params - Optional query parameters\n * @returns The extracted data from the response (without the { status, data } wrapper)\n * @internal\n */\n async post<T>(\n path: string,\n body?: unknown,\n params?: Record<string, unknown>,\n ): Promise<ExtractData<T>> {\n try {\n const url = this.buildUrl(path, params)\n\n // Convert body to URLSearchParams for application/x-www-form-urlencoded\n const formData = new URLSearchParams()\n if (body && typeof body === 'object') {\n for (const [key, value] of Object.entries(body)) {\n if (value !== undefined && value !== null) {\n if (Array.isArray(value)) {\n // Handle arrays (e.g., link[] for multiple links)\n value.forEach((v) => formData.append(key, String(v)))\n } else {\n formData.append(key, String(value))\n }\n }\n }\n }\n\n const json = await wretch(this.config.baseUrl)\n .auth(`Bearer ${this.config.apiKey}`)\n .url(url)\n .body(formData)\n .post()\n .json<ApiResponse<unknown>>()\n\n // Handle error responses\n if (json.status === 'error' && json.error) {\n throw createTypedError(json.error.code, json.error.message)\n }\n\n return json.data as ExtractData<T>\n } catch (error: any) {\n // Handle HTTP errors\n if (error.status === 401) {\n throw createTypedError('AUTH_BAD_APIKEY', 'Invalid API key or unauthorized access')\n }\n if (error.status === 403) {\n throw createTypedError('AUTH_BLOCKED', 'Access forbidden')\n }\n if (error.status === 429) {\n throw createTypedError('RATE_LIMITED', 'Too many requests')\n }\n\n // Re-throw if already our error type\n if (error.isAllDebridError) {\n throw error\n }\n\n // Wrap in NetworkError\n throw new NetworkError(error.message || 'Network error occurred', error.status)\n }\n }\n\n /**\n * Make a POST request with FormData (multipart/form-data)\n * @template T - The generated response type\n * @param path - API endpoint path\n * @param formData - Form data to send\n * @param params - Optional query parameters\n * @returns The extracted data from the response (without the { status, data } wrapper)\n * @internal\n */\n async postFormData<T>(\n path: string,\n formData: FormData,\n params?: Record<string, unknown>,\n ): Promise<ExtractData<T>> {\n try {\n const url = this.buildUrl(path, params)\n const json = await wretch(this.config.baseUrl)\n .auth(`Bearer ${this.config.apiKey}`)\n .url(url)\n .body(formData)\n .post()\n .json<ApiResponse<unknown>>()\n\n // Handle error responses\n if (json.status === 'error' && json.error) {\n throw createTypedError(json.error.code, json.error.message)\n }\n\n return json.data as ExtractData<T>\n } catch (error: any) {\n // Handle HTTP errors\n if (error.status === 401) {\n throw createTypedError('AUTH_BAD_APIKEY', 'Invalid API key or unauthorized access')\n }\n if (error.status === 403) {\n throw createTypedError('AUTH_BLOCKED', 'Access forbidden')\n }\n if (error.status === 429) {\n throw createTypedError('RATE_LIMITED', 'Too many requests')\n }\n\n // Re-throw if already our error type\n if (error.isAllDebridError) {\n throw error\n }\n\n // Wrap in NetworkError\n throw new NetworkError(error.message || 'Network error occurred', error.status)\n }\n }\n\n /**\n * Test the API connection\n *\n * This endpoint doesn't require authentication and can be used to verify\n * that the AllDebrid API is reachable.\n *\n * @example\n * ```ts\n * const result = await client.ping()\n * console.log(result.ping) // 'pong'\n * ```\n *\n * @returns Ping response with 'pong' message\n */\n async ping() {\n return this.get<PingResponse>('/ping')\n }\n}\n"]}
|