@adbjs/sdk 0.1.1 → 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/README.md +336 -223
- package/dist/index.cjs +518 -81
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +885 -1025
- package/dist/index.d.ts +885 -1025
- package/dist/index.js +517 -82
- package/dist/index.js.map +1 -1
- package/package.json +66 -66
package/dist/index.js
CHANGED
|
@@ -66,30 +66,35 @@ var BaseResource = class {
|
|
|
66
66
|
}
|
|
67
67
|
/**
|
|
68
68
|
* Make a GET request
|
|
69
|
-
* @
|
|
69
|
+
* @template T - The generated response type (e.g., GetLinkUnlockResponse)
|
|
70
|
+
* @param path - API endpoint path
|
|
71
|
+
* @param params - Optional query parameters
|
|
70
72
|
* @returns The extracted data from the response (without the { status, data } wrapper)
|
|
71
73
|
*/
|
|
72
74
|
async get(path, params) {
|
|
73
|
-
|
|
74
|
-
return clientAny.get(path, params);
|
|
75
|
+
return this.client.get(path, params);
|
|
75
76
|
}
|
|
76
77
|
/**
|
|
77
78
|
* Make a POST request
|
|
78
|
-
* @
|
|
79
|
+
* @template T - The generated response type
|
|
80
|
+
* @param path - API endpoint path
|
|
81
|
+
* @param body - Request body
|
|
82
|
+
* @param params - Optional query parameters
|
|
79
83
|
* @returns The extracted data from the response (without the { status, data } wrapper)
|
|
80
84
|
*/
|
|
81
85
|
async post(path, body, params) {
|
|
82
|
-
|
|
83
|
-
return clientAny.post(path, body, params);
|
|
86
|
+
return this.client.post(path, body, params);
|
|
84
87
|
}
|
|
85
88
|
/**
|
|
86
89
|
* Make a POST request with FormData (multipart/form-data)
|
|
87
|
-
* @
|
|
90
|
+
* @template T - The generated response type
|
|
91
|
+
* @param path - API endpoint path
|
|
92
|
+
* @param formData - Form data to send
|
|
93
|
+
* @param params - Optional query parameters
|
|
88
94
|
* @returns The extracted data from the response (without the { status, data } wrapper)
|
|
89
95
|
*/
|
|
90
96
|
async postFormData(path, formData, params) {
|
|
91
|
-
|
|
92
|
-
return clientAny.postFormData(path, formData, params);
|
|
97
|
+
return this.client.postFormData(path, formData, params);
|
|
93
98
|
}
|
|
94
99
|
};
|
|
95
100
|
|
|
@@ -144,19 +149,24 @@ var LinkResource = class extends BaseResource {
|
|
|
144
149
|
* Get information about one or more links
|
|
145
150
|
*
|
|
146
151
|
* @param links - Single link or array of links to get info for
|
|
152
|
+
* @param password - Optional password for password-protected links
|
|
147
153
|
*
|
|
148
154
|
* @example
|
|
149
155
|
* ```ts
|
|
150
|
-
* const
|
|
151
|
-
* console.log(
|
|
156
|
+
* const data = await client.link.infos('https://example.com/file.zip')
|
|
157
|
+
* console.log(data.infos)
|
|
158
|
+
*
|
|
159
|
+
* // With password
|
|
160
|
+
* const protectedData = await client.link.infos(
|
|
161
|
+
* 'https://example.com/protected.zip',
|
|
162
|
+
* 'mypassword'
|
|
163
|
+
* )
|
|
152
164
|
* ```
|
|
153
165
|
*/
|
|
154
|
-
async infos(links) {
|
|
166
|
+
async infos(links, password) {
|
|
155
167
|
const linksArray = Array.isArray(links) ? links : [links];
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
});
|
|
159
|
-
return data?.infos;
|
|
168
|
+
const params = password ? { password } : void 0;
|
|
169
|
+
return this.post("/link/infos", { "link[]": linksArray }, params);
|
|
160
170
|
}
|
|
161
171
|
/**
|
|
162
172
|
* Extract links from redirectors/link protectors
|
|
@@ -165,19 +175,20 @@ var LinkResource = class extends BaseResource {
|
|
|
165
175
|
*
|
|
166
176
|
* @example
|
|
167
177
|
* ```ts
|
|
168
|
-
* const
|
|
178
|
+
* const data = await client.link.redirector('https://linkprotector.com/abc123')
|
|
179
|
+
* console.log(data.links)
|
|
169
180
|
* ```
|
|
170
181
|
*/
|
|
171
182
|
async redirector(link) {
|
|
172
|
-
|
|
183
|
+
return this.post("/link/redirector", {
|
|
173
184
|
link
|
|
174
185
|
});
|
|
175
|
-
return data?.links;
|
|
176
186
|
}
|
|
177
187
|
/**
|
|
178
188
|
* Unlock a download link
|
|
179
189
|
*
|
|
180
190
|
* @param link - The link to unlock
|
|
191
|
+
* @param password - Optional password for password-protected links
|
|
181
192
|
*
|
|
182
193
|
* @example
|
|
183
194
|
* ```ts
|
|
@@ -188,12 +199,17 @@ var LinkResource = class extends BaseResource {
|
|
|
188
199
|
* // Handle delayed generation
|
|
189
200
|
* const delayedResult = await client.link.delayed(result.delayed)
|
|
190
201
|
* }
|
|
202
|
+
*
|
|
203
|
+
* // With password
|
|
204
|
+
* const protectedResult = await client.link.unlock(
|
|
205
|
+
* 'https://example.com/protected.zip',
|
|
206
|
+
* 'mypassword'
|
|
207
|
+
* )
|
|
191
208
|
* ```
|
|
192
209
|
*/
|
|
193
|
-
async unlock(link) {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
});
|
|
210
|
+
async unlock(link, password) {
|
|
211
|
+
const params = password ? { password } : void 0;
|
|
212
|
+
return this.post("/link/unlock", { link }, params);
|
|
197
213
|
}
|
|
198
214
|
/**
|
|
199
215
|
* Unlock a link and automatically poll if delayed
|
|
@@ -222,9 +238,10 @@ var LinkResource = class extends BaseResource {
|
|
|
222
238
|
* const streams = await client.link.streaming('abc123')
|
|
223
239
|
* ```
|
|
224
240
|
*/
|
|
225
|
-
async streaming(id) {
|
|
226
|
-
return this.
|
|
227
|
-
id
|
|
241
|
+
async streaming(id, stream) {
|
|
242
|
+
return this.post("/link/streaming", {
|
|
243
|
+
id,
|
|
244
|
+
stream
|
|
228
245
|
});
|
|
229
246
|
}
|
|
230
247
|
/**
|
|
@@ -238,7 +255,7 @@ var LinkResource = class extends BaseResource {
|
|
|
238
255
|
* ```
|
|
239
256
|
*/
|
|
240
257
|
async delayed(id) {
|
|
241
|
-
return this.
|
|
258
|
+
return this.post("/link/delayed", {
|
|
242
259
|
id
|
|
243
260
|
});
|
|
244
261
|
}
|
|
@@ -259,7 +276,7 @@ var MagnetResource = class extends BaseResource {
|
|
|
259
276
|
*/
|
|
260
277
|
async upload(magnets) {
|
|
261
278
|
const magnetsArray = Array.isArray(magnets) ? magnets : [magnets];
|
|
262
|
-
return this.
|
|
279
|
+
return this.post("/magnet/upload", {
|
|
263
280
|
magnets: magnetsArray
|
|
264
281
|
});
|
|
265
282
|
}
|
|
@@ -286,23 +303,22 @@ var MagnetResource = class extends BaseResource {
|
|
|
286
303
|
return this.postFormData("/magnet/upload/file", formData);
|
|
287
304
|
}
|
|
288
305
|
/**
|
|
289
|
-
* Get the status of
|
|
306
|
+
* Get the status of a specific magnet by ID
|
|
290
307
|
*
|
|
291
|
-
* @param id -
|
|
308
|
+
* @param id - Magnet ID to get status for
|
|
292
309
|
*
|
|
293
310
|
* @example
|
|
294
311
|
* ```ts
|
|
295
|
-
*
|
|
296
|
-
* const allStatus = await client.magnet.status()
|
|
297
|
-
*
|
|
298
|
-
* // Get specific magnet status
|
|
299
|
-
* const status = await client.magnet.status('123')
|
|
312
|
+
* const status = await client.magnet.status(123)
|
|
300
313
|
* console.log(status.magnets[0]?.status) // 'Downloading', 'Ready', etc.
|
|
301
314
|
* ```
|
|
315
|
+
*
|
|
316
|
+
* @remarks
|
|
317
|
+
* This endpoint uses AllDebrid API v4.1 (POST method)
|
|
318
|
+
* Migrated from v4 GET endpoint which was deprecated on 2024-10-16
|
|
302
319
|
*/
|
|
303
320
|
async status(id) {
|
|
304
|
-
const
|
|
305
|
-
const data = await this.get("/magnet/status", params);
|
|
321
|
+
const data = await this.post("/magnet/status", { id });
|
|
306
322
|
if (data?.magnets && !Array.isArray(data.magnets)) {
|
|
307
323
|
return {
|
|
308
324
|
...data,
|
|
@@ -311,71 +327,215 @@ var MagnetResource = class extends BaseResource {
|
|
|
311
327
|
}
|
|
312
328
|
return data;
|
|
313
329
|
}
|
|
330
|
+
/**
|
|
331
|
+
* Get list of magnets with optional status filter
|
|
332
|
+
*
|
|
333
|
+
* @param statusFilter - Optional filter by status: 'active', 'ready', 'expired', or 'error'
|
|
334
|
+
*
|
|
335
|
+
* @example
|
|
336
|
+
* ```ts
|
|
337
|
+
* // Get all magnets
|
|
338
|
+
* const allMagnets = await client.magnet.statusList()
|
|
339
|
+
*
|
|
340
|
+
* // Get only active magnets
|
|
341
|
+
* const activeMagnets = await client.magnet.statusList('active')
|
|
342
|
+
*
|
|
343
|
+
* // Get only ready magnets
|
|
344
|
+
* const readyMagnets = await client.magnet.statusList('ready')
|
|
345
|
+
* ```
|
|
346
|
+
*
|
|
347
|
+
* @remarks
|
|
348
|
+
* This endpoint uses AllDebrid API v4.1 (POST method)
|
|
349
|
+
*/
|
|
350
|
+
async statusList(statusFilter) {
|
|
351
|
+
const body = statusFilter ? { status: statusFilter } : void 0;
|
|
352
|
+
return this.post("/magnet/status", body);
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
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)
|
|
375
|
+
*
|
|
376
|
+
* ## Important notes
|
|
377
|
+
*
|
|
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)
|
|
387
|
+
*
|
|
388
|
+
* @example
|
|
389
|
+
* ```ts
|
|
390
|
+
* // Initialize session
|
|
391
|
+
* const session = Math.floor(Math.random() * 1000000)
|
|
392
|
+
* let counter = 0
|
|
393
|
+
*
|
|
394
|
+
* // First call - returns all magnets (fullsync: true)
|
|
395
|
+
* const firstCall = await client.magnet.statusLive({ session, counter })
|
|
396
|
+
* console.log('Full sync:', firstCall.fullsync) // true
|
|
397
|
+
* console.log('All magnets:', firstCall.magnets) // Array of all magnets
|
|
398
|
+
* counter = firstCall.counter // Update counter for next call
|
|
399
|
+
*
|
|
400
|
+
* // Second call - returns only magnets that changed
|
|
401
|
+
* await new Promise(resolve => setTimeout(resolve, 3000)) // Wait 3 seconds
|
|
402
|
+
* const secondCall = await client.magnet.statusLive({ session, counter })
|
|
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
|
+
* }
|
|
438
|
+
*
|
|
439
|
+
* await new Promise(resolve => setTimeout(resolve, 3000))
|
|
440
|
+
* }
|
|
441
|
+
* ```
|
|
442
|
+
*
|
|
443
|
+
* @remarks
|
|
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.
|
|
446
|
+
*/
|
|
447
|
+
async statusLive(options) {
|
|
448
|
+
const body = {
|
|
449
|
+
session: options.session,
|
|
450
|
+
counter: options.counter
|
|
451
|
+
};
|
|
452
|
+
return this.post("/magnet/status", body);
|
|
453
|
+
}
|
|
314
454
|
/**
|
|
315
455
|
* Delete a magnet
|
|
316
456
|
*
|
|
317
|
-
* @param id - The magnet ID to delete
|
|
457
|
+
* @param id - The magnet ID to delete
|
|
318
458
|
*
|
|
319
459
|
* @example
|
|
320
460
|
* ```ts
|
|
321
|
-
* await client.magnet.delete(
|
|
461
|
+
* await client.magnet.delete(123)
|
|
322
462
|
* ```
|
|
323
463
|
*/
|
|
324
464
|
async delete(id) {
|
|
325
|
-
return this.
|
|
465
|
+
return this.post("/magnet/delete", {
|
|
326
466
|
id
|
|
327
467
|
});
|
|
328
468
|
}
|
|
329
469
|
/**
|
|
330
470
|
* Restart one or more failed magnets
|
|
331
471
|
*
|
|
332
|
-
* @param ids - Single magnet ID or array of magnet IDs to restart (
|
|
472
|
+
* @param ids - Single magnet ID or array of magnet IDs to restart (numbers)
|
|
333
473
|
*
|
|
334
474
|
* @example
|
|
335
475
|
* ```ts
|
|
336
476
|
* // Restart single magnet
|
|
337
|
-
* await client.magnet.restart(
|
|
477
|
+
* await client.magnet.restart(123)
|
|
338
478
|
*
|
|
339
479
|
* // Restart multiple magnets
|
|
340
|
-
* await client.magnet.restart([
|
|
480
|
+
* await client.magnet.restart([123, 456])
|
|
341
481
|
* ```
|
|
342
482
|
*/
|
|
343
483
|
async restart(ids) {
|
|
344
484
|
const idsArray = Array.isArray(ids) ? ids : [ids];
|
|
345
|
-
return this.
|
|
485
|
+
return this.post("/magnet/restart", {
|
|
346
486
|
ids: idsArray
|
|
347
487
|
});
|
|
348
488
|
}
|
|
349
489
|
/**
|
|
350
|
-
*
|
|
490
|
+
* Get files for a completed magnet
|
|
351
491
|
*
|
|
352
|
-
* @param
|
|
492
|
+
* @param ids - The magnet ID or IDs to get files for
|
|
353
493
|
*
|
|
354
494
|
* @example
|
|
355
495
|
* ```ts
|
|
356
|
-
* const
|
|
357
|
-
*
|
|
496
|
+
* const data = await client.magnet.files(123)
|
|
497
|
+
* data?.magnets?.forEach(magnet => {
|
|
498
|
+
* console.log(magnet.filename, magnet.files)
|
|
499
|
+
* })
|
|
358
500
|
* ```
|
|
501
|
+
*
|
|
502
|
+
* @remarks
|
|
503
|
+
* Files are now retrieved separately from magnet status (since v4.1)
|
|
504
|
+
* Only available for magnets with status 'Ready'
|
|
359
505
|
*/
|
|
360
|
-
async
|
|
361
|
-
const
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
506
|
+
async files(ids) {
|
|
507
|
+
const formData = new FormData();
|
|
508
|
+
const idsArray = Array.isArray(ids) ? ids : [ids];
|
|
509
|
+
for (const id of idsArray) {
|
|
510
|
+
formData.append("id[]", String(id));
|
|
511
|
+
}
|
|
512
|
+
return this.postFormData("/magnet/files", formData);
|
|
365
513
|
}
|
|
366
514
|
/**
|
|
367
515
|
* Watch a magnet's status with automatic polling
|
|
368
516
|
*
|
|
369
|
-
*
|
|
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
|
+
*
|
|
521
|
+
* @param id - The magnet ID to watch
|
|
370
522
|
* @param options - Watch options
|
|
523
|
+
* @param options.interval - Polling interval in milliseconds (default: 3000)
|
|
524
|
+
* @param options.maxAttempts - Maximum polling attempts, 0 for infinite (default: 0)
|
|
525
|
+
* @param options.onUpdate - Callback called on each status update
|
|
526
|
+
* @param options.stopOnStatus - Stop when magnet reaches this status (default: 'Ready')
|
|
371
527
|
*
|
|
372
528
|
* @example
|
|
373
529
|
* ```ts
|
|
374
|
-
* await client.magnet.watch(
|
|
530
|
+
* await client.magnet.watch(123, {
|
|
375
531
|
* onUpdate: (status) => console.log('Status:', status.magnets[0]?.status),
|
|
376
532
|
* stopOnStatus: 'Ready'
|
|
377
533
|
* })
|
|
378
534
|
* ```
|
|
535
|
+
*
|
|
536
|
+
* @remarks
|
|
537
|
+
* For monitoring multiple magnets efficiently, use `statusLive()` directly.
|
|
538
|
+
* See the `statusLive()` documentation for details on delta synchronization.
|
|
379
539
|
*/
|
|
380
540
|
async watch(id, options = {}) {
|
|
381
541
|
const { interval = 3e3, maxAttempts = 0, onUpdate, stopOnStatus = "Ready" } = options;
|
|
@@ -396,6 +556,111 @@ var MagnetResource = class extends BaseResource {
|
|
|
396
556
|
}
|
|
397
557
|
};
|
|
398
558
|
|
|
559
|
+
// src/resources/pin.ts
|
|
560
|
+
var PinResource = class extends BaseResource {
|
|
561
|
+
/**
|
|
562
|
+
* Generate a new PIN code for authentication
|
|
563
|
+
*
|
|
564
|
+
* This initiates the PIN authentication flow. The user should visit the
|
|
565
|
+
* returned URL to authorize the application.
|
|
566
|
+
*
|
|
567
|
+
* @example
|
|
568
|
+
* ```ts
|
|
569
|
+
* const pinData = await client.pin.generate()
|
|
570
|
+
* console.log('Visit:', pinData.user_url)
|
|
571
|
+
* console.log('PIN:', pinData.pin)
|
|
572
|
+
*
|
|
573
|
+
* // Poll the check endpoint until user authorizes
|
|
574
|
+
* const auth = await client.pin.check(pinData.check, pinData.pin)
|
|
575
|
+
* if (auth.activated) {
|
|
576
|
+
* console.log('API Key:', auth.apikey)
|
|
577
|
+
* }
|
|
578
|
+
* ```
|
|
579
|
+
*
|
|
580
|
+
* @returns PIN code and authorization URL
|
|
581
|
+
*/
|
|
582
|
+
async generate() {
|
|
583
|
+
return super.get("/pin/get");
|
|
584
|
+
}
|
|
585
|
+
/**
|
|
586
|
+
* Check the status of a PIN authentication
|
|
587
|
+
*
|
|
588
|
+
* Poll this endpoint to check if the user has authorized the application.
|
|
589
|
+
* Once authorized, the response will include the API key.
|
|
590
|
+
*
|
|
591
|
+
* @param check - Check ID from /pin/get
|
|
592
|
+
* @param pin - PIN code from /pin/get
|
|
593
|
+
*
|
|
594
|
+
* @example
|
|
595
|
+
* ```ts
|
|
596
|
+
* const pinData = await client.pin.generate()
|
|
597
|
+
*
|
|
598
|
+
* // Poll every few seconds until activated
|
|
599
|
+
* const checkStatus = async () => {
|
|
600
|
+
* const result = await client.pin.check(pinData.check, pinData.pin)
|
|
601
|
+
* if (result?.activated && result?.apikey) {
|
|
602
|
+
* console.log('Authorized! API Key:', result.apikey)
|
|
603
|
+
* return result.apikey
|
|
604
|
+
* }
|
|
605
|
+
* // Wait and try again
|
|
606
|
+
* await new Promise(resolve => setTimeout(resolve, 3000))
|
|
607
|
+
* return checkStatus()
|
|
608
|
+
* }
|
|
609
|
+
*
|
|
610
|
+
* const apikey = await checkStatus()
|
|
611
|
+
* ```
|
|
612
|
+
*
|
|
613
|
+
* @returns Authorization status and API key (if activated)
|
|
614
|
+
*/
|
|
615
|
+
async check(check, pin) {
|
|
616
|
+
return super.get("/pin/check", { check, pin });
|
|
617
|
+
}
|
|
618
|
+
/**
|
|
619
|
+
* Helper method to wait for PIN authorization with automatic polling
|
|
620
|
+
*
|
|
621
|
+
* This method handles the polling logic for you, making it easier to
|
|
622
|
+
* implement the PIN authentication flow.
|
|
623
|
+
*
|
|
624
|
+
* @param check - Check ID from /pin/get
|
|
625
|
+
* @param pin - PIN code from /pin/get
|
|
626
|
+
* @param options - Polling options
|
|
627
|
+
* @param options.timeout - Maximum time to wait in milliseconds (default: 600000 = 10 minutes)
|
|
628
|
+
* @param options.interval - Polling interval in milliseconds (default: 3000 = 3 seconds)
|
|
629
|
+
*
|
|
630
|
+
* @example
|
|
631
|
+
* ```ts
|
|
632
|
+
* const pinData = await client.pin.generate()
|
|
633
|
+
* console.log('Visit:', pinData.user_url)
|
|
634
|
+
*
|
|
635
|
+
* try {
|
|
636
|
+
* const apikey = await client.pin.waitForAuth(pinData.check, pinData.pin, {
|
|
637
|
+
* timeout: 600000, // 10 minutes
|
|
638
|
+
* interval: 3000, // Check every 3 seconds
|
|
639
|
+
* })
|
|
640
|
+
* console.log('Authorized! API Key:', apikey)
|
|
641
|
+
* } catch (error) {
|
|
642
|
+
* console.error('Authorization timed out or failed')
|
|
643
|
+
* }
|
|
644
|
+
* ```
|
|
645
|
+
*
|
|
646
|
+
* @returns The API key once authorized
|
|
647
|
+
* @throws Error if timeout is reached or authorization fails
|
|
648
|
+
*/
|
|
649
|
+
async waitForAuth(check, pin, options = {}) {
|
|
650
|
+
const timeout = options.timeout ?? 6e5;
|
|
651
|
+
const interval = options.interval ?? 3e3;
|
|
652
|
+
const startTime = Date.now();
|
|
653
|
+
while (Date.now() - startTime < timeout) {
|
|
654
|
+
const result = await this.check(check, pin);
|
|
655
|
+
if (result?.activated && result?.apikey) {
|
|
656
|
+
return result.apikey;
|
|
657
|
+
}
|
|
658
|
+
await new Promise((resolve) => setTimeout(resolve, interval));
|
|
659
|
+
}
|
|
660
|
+
throw new Error("PIN authorization timeout - user did not authorize within the time limit");
|
|
661
|
+
}
|
|
662
|
+
};
|
|
663
|
+
|
|
399
664
|
// src/resources/user.ts
|
|
400
665
|
var UserResource = class extends BaseResource {
|
|
401
666
|
/**
|
|
@@ -403,13 +668,12 @@ var UserResource = class extends BaseResource {
|
|
|
403
668
|
*
|
|
404
669
|
* @example
|
|
405
670
|
* ```ts
|
|
406
|
-
* const
|
|
407
|
-
* console.log(user.username, user.isPremium)
|
|
671
|
+
* const data = await client.user.getInfo()
|
|
672
|
+
* console.log(data.user.username, data.user.isPremium)
|
|
408
673
|
* ```
|
|
409
674
|
*/
|
|
410
675
|
async getInfo() {
|
|
411
|
-
|
|
412
|
-
return data?.user;
|
|
676
|
+
return this.get("/user");
|
|
413
677
|
}
|
|
414
678
|
/**
|
|
415
679
|
* Get available hosts for the current user based on their subscription
|
|
@@ -437,7 +701,7 @@ var UserResource = class extends BaseResource {
|
|
|
437
701
|
* ```
|
|
438
702
|
*/
|
|
439
703
|
async clearNotification(code) {
|
|
440
|
-
await this.
|
|
704
|
+
await this.post("/user/notification/clear", { code });
|
|
441
705
|
}
|
|
442
706
|
// ============================================
|
|
443
707
|
// Saved Links Management
|
|
@@ -455,30 +719,60 @@ var UserResource = class extends BaseResource {
|
|
|
455
719
|
return this.get("/user/links");
|
|
456
720
|
}
|
|
457
721
|
/**
|
|
458
|
-
* Save
|
|
722
|
+
* Save one or multiple links for later use
|
|
459
723
|
*
|
|
460
|
-
*
|
|
724
|
+
* Supports batch operations - you can save multiple links in a single request.
|
|
725
|
+
*
|
|
726
|
+
* @param links - Single link or array of links to save
|
|
461
727
|
*
|
|
462
728
|
* @example
|
|
463
729
|
* ```ts
|
|
730
|
+
* // Save single link
|
|
464
731
|
* await client.user.saveLink('https://example.com/file.zip')
|
|
732
|
+
*
|
|
733
|
+
* // Save multiple links at once
|
|
734
|
+
* await client.user.saveLink([
|
|
735
|
+
* 'https://example.com/file1.zip',
|
|
736
|
+
* 'https://example.com/file2.zip',
|
|
737
|
+
* 'https://example.com/file3.zip'
|
|
738
|
+
* ])
|
|
465
739
|
* ```
|
|
466
740
|
*/
|
|
467
|
-
async saveLink(
|
|
468
|
-
|
|
741
|
+
async saveLink(links) {
|
|
742
|
+
const linksArray = Array.isArray(links) ? links : [links];
|
|
743
|
+
const formData = new FormData();
|
|
744
|
+
for (const link of linksArray) {
|
|
745
|
+
formData.append("links[]", link);
|
|
746
|
+
}
|
|
747
|
+
return this.postFormData("/user/links/save", formData);
|
|
469
748
|
}
|
|
470
749
|
/**
|
|
471
|
-
* Delete
|
|
750
|
+
* Delete one or multiple saved links
|
|
472
751
|
*
|
|
473
|
-
*
|
|
752
|
+
* Supports batch operations - you can delete multiple links in a single request.
|
|
753
|
+
*
|
|
754
|
+
* @param links - Single link or array of links to delete (can be saved link IDs or URLs)
|
|
474
755
|
*
|
|
475
756
|
* @example
|
|
476
757
|
* ```ts
|
|
758
|
+
* // Delete single link
|
|
477
759
|
* await client.user.deleteLink('saved-link-id')
|
|
760
|
+
*
|
|
761
|
+
* // Delete multiple links at once
|
|
762
|
+
* await client.user.deleteLink([
|
|
763
|
+
* 'saved-link-id-1',
|
|
764
|
+
* 'saved-link-id-2',
|
|
765
|
+
* 'saved-link-id-3'
|
|
766
|
+
* ])
|
|
478
767
|
* ```
|
|
479
768
|
*/
|
|
480
|
-
async deleteLink(
|
|
481
|
-
|
|
769
|
+
async deleteLink(links) {
|
|
770
|
+
const linksArray = Array.isArray(links) ? links : [links];
|
|
771
|
+
const formData = new FormData();
|
|
772
|
+
for (const link of linksArray) {
|
|
773
|
+
formData.append("links[]", link);
|
|
774
|
+
}
|
|
775
|
+
return this.postFormData("/user/links/delete", formData);
|
|
482
776
|
}
|
|
483
777
|
// ============================================
|
|
484
778
|
// History Management
|
|
@@ -504,12 +798,114 @@ var UserResource = class extends BaseResource {
|
|
|
504
798
|
* ```
|
|
505
799
|
*/
|
|
506
800
|
async clearHistory() {
|
|
507
|
-
return this.
|
|
801
|
+
return this.post("/user/history/delete");
|
|
802
|
+
}
|
|
803
|
+
// ============================================
|
|
804
|
+
// Email Verification
|
|
805
|
+
// ============================================
|
|
806
|
+
/**
|
|
807
|
+
* Check email verification status
|
|
808
|
+
*
|
|
809
|
+
* @param token - Verification token
|
|
810
|
+
*
|
|
811
|
+
* @example
|
|
812
|
+
* ```ts
|
|
813
|
+
* const status = await client.user.getVerificationStatus('verification-token')
|
|
814
|
+
* console.log(status.verif) // 'waiting', 'allowed', or 'denied'
|
|
815
|
+
* ```
|
|
816
|
+
*/
|
|
817
|
+
async getVerificationStatus(token) {
|
|
818
|
+
return this.post("/user/verif", void 0, { token });
|
|
819
|
+
}
|
|
820
|
+
/**
|
|
821
|
+
* Resend verification email
|
|
822
|
+
*
|
|
823
|
+
* @param token - Verification token
|
|
824
|
+
*
|
|
825
|
+
* @example
|
|
826
|
+
* ```ts
|
|
827
|
+
* await client.user.resendVerification('verification-token')
|
|
828
|
+
* ```
|
|
829
|
+
*/
|
|
830
|
+
async resendVerification(token) {
|
|
831
|
+
return this.post("/user/verif/resend", void 0, { token });
|
|
832
|
+
}
|
|
833
|
+
};
|
|
834
|
+
|
|
835
|
+
// src/resources/voucher.ts
|
|
836
|
+
var VoucherResource = class extends BaseResource {
|
|
837
|
+
/**
|
|
838
|
+
* Get voucher balance for reseller accounts
|
|
839
|
+
*
|
|
840
|
+
* This endpoint allows resellers to check their remaining voucher balance.
|
|
841
|
+
* Only available for accounts with reseller privileges.
|
|
842
|
+
*
|
|
843
|
+
* @example
|
|
844
|
+
* ```ts
|
|
845
|
+
* const balance = await client.voucher.getBalance()
|
|
846
|
+
* console.log('Remaining balance:', balance.balance, '€')
|
|
847
|
+
* ```
|
|
848
|
+
*
|
|
849
|
+
* @returns Voucher balance information
|
|
850
|
+
*/
|
|
851
|
+
async getBalance() {
|
|
852
|
+
return this.get("/voucher/balance");
|
|
853
|
+
}
|
|
854
|
+
/**
|
|
855
|
+
* Retrieve existing vouchers from reseller inventory
|
|
856
|
+
*
|
|
857
|
+
* This endpoint retrieves vouchers that were previously generated
|
|
858
|
+
* and are available in your inventory.
|
|
859
|
+
*
|
|
860
|
+
* @param quantity - Optional number of vouchers to retrieve
|
|
861
|
+
*
|
|
862
|
+
* @example
|
|
863
|
+
* ```ts
|
|
864
|
+
* // Get all available vouchers
|
|
865
|
+
* const allVouchers = await client.voucher.getVouchers()
|
|
866
|
+
* console.log('Vouchers:', allVouchers?.codes)
|
|
867
|
+
*
|
|
868
|
+
* // Get specific quantity
|
|
869
|
+
* const fiveVouchers = await client.voucher.getVouchers(5)
|
|
870
|
+
* ```
|
|
871
|
+
*
|
|
872
|
+
* @returns List of voucher codes
|
|
873
|
+
*/
|
|
874
|
+
async getVouchers(quantity) {
|
|
875
|
+
const params = quantity ? { quantity } : void 0;
|
|
876
|
+
return this.get("/voucher/get", params);
|
|
877
|
+
}
|
|
878
|
+
/**
|
|
879
|
+
* Generate new vouchers (deducts from reseller balance)
|
|
880
|
+
*
|
|
881
|
+
* This endpoint creates new vouchers and deducts the cost from your
|
|
882
|
+
* reseller account balance.
|
|
883
|
+
*
|
|
884
|
+
* @param quantity - Number of vouchers to generate
|
|
885
|
+
* @param duration - Voucher duration in days
|
|
886
|
+
*
|
|
887
|
+
* @example
|
|
888
|
+
* ```ts
|
|
889
|
+
* // Generate 10 vouchers valid for 30 days
|
|
890
|
+
* const vouchers = await client.voucher.generateVouchers(10, 30)
|
|
891
|
+
* console.log('Generated vouchers:', vouchers?.codes)
|
|
892
|
+
*
|
|
893
|
+
* // Generate 5 vouchers valid for 7 days
|
|
894
|
+
* const weekVouchers = await client.voucher.generateVouchers(5, 7)
|
|
895
|
+
* ```
|
|
896
|
+
*
|
|
897
|
+
* @returns List of newly generated voucher codes
|
|
898
|
+
*/
|
|
899
|
+
async generateVouchers(quantity, duration) {
|
|
900
|
+
return this.post("/voucher/generate", {
|
|
901
|
+
quantity,
|
|
902
|
+
duration
|
|
903
|
+
});
|
|
508
904
|
}
|
|
509
905
|
};
|
|
510
906
|
|
|
511
907
|
// src/client.ts
|
|
512
|
-
var DEFAULT_BASE_URL = "https://api.alldebrid.com/v4";
|
|
908
|
+
var DEFAULT_BASE_URL = "https://api.alldebrid.com/v4.1";
|
|
513
909
|
var DEFAULT_AGENT = "@alldebrid/sdk";
|
|
514
910
|
var DEFAULT_TIMEOUT = 3e4;
|
|
515
911
|
var DEFAULT_MAX_RETRIES = 3;
|
|
@@ -531,6 +927,14 @@ var AllDebridClient = class {
|
|
|
531
927
|
* Host resource for getting information about supported hosts
|
|
532
928
|
*/
|
|
533
929
|
host;
|
|
930
|
+
/**
|
|
931
|
+
* Pin resource for PIN-based authentication
|
|
932
|
+
*/
|
|
933
|
+
pin;
|
|
934
|
+
/**
|
|
935
|
+
* Voucher resource for reseller voucher management
|
|
936
|
+
*/
|
|
937
|
+
voucher;
|
|
534
938
|
constructor(config) {
|
|
535
939
|
this.config = {
|
|
536
940
|
apiKey: config.apiKey,
|
|
@@ -544,6 +948,8 @@ var AllDebridClient = class {
|
|
|
544
948
|
this.link = new LinkResource(this);
|
|
545
949
|
this.magnet = new MagnetResource(this);
|
|
546
950
|
this.host = new HostResource(this);
|
|
951
|
+
this.pin = new PinResource(this);
|
|
952
|
+
this.voucher = new VoucherResource(this);
|
|
547
953
|
}
|
|
548
954
|
/**
|
|
549
955
|
* Build query string from params
|
|
@@ -568,8 +974,11 @@ var AllDebridClient = class {
|
|
|
568
974
|
}
|
|
569
975
|
/**
|
|
570
976
|
* Make a GET request
|
|
571
|
-
* @
|
|
977
|
+
* @template T - The generated response type (e.g., GetLinkUnlockResponse)
|
|
978
|
+
* @param path - API endpoint path
|
|
979
|
+
* @param params - Optional query parameters
|
|
572
980
|
* @returns The extracted data from the response (without the { status, data } wrapper)
|
|
981
|
+
* @internal
|
|
573
982
|
*/
|
|
574
983
|
async get(path, params) {
|
|
575
984
|
try {
|
|
@@ -596,14 +1005,30 @@ var AllDebridClient = class {
|
|
|
596
1005
|
}
|
|
597
1006
|
}
|
|
598
1007
|
/**
|
|
599
|
-
* Make a POST request
|
|
600
|
-
* @
|
|
1008
|
+
* Make a POST request with application/x-www-form-urlencoded
|
|
1009
|
+
* @template T - The generated response type
|
|
1010
|
+
* @param path - API endpoint path
|
|
1011
|
+
* @param body - Request body (will be converted to URLSearchParams)
|
|
1012
|
+
* @param params - Optional query parameters
|
|
601
1013
|
* @returns The extracted data from the response (without the { status, data } wrapper)
|
|
1014
|
+
* @internal
|
|
602
1015
|
*/
|
|
603
1016
|
async post(path, body, params) {
|
|
604
1017
|
try {
|
|
605
1018
|
const url = this.buildUrl(path, params);
|
|
606
|
-
const
|
|
1019
|
+
const formData = new URLSearchParams();
|
|
1020
|
+
if (body && typeof body === "object") {
|
|
1021
|
+
for (const [key, value] of Object.entries(body)) {
|
|
1022
|
+
if (value !== void 0 && value !== null) {
|
|
1023
|
+
if (Array.isArray(value)) {
|
|
1024
|
+
value.forEach((v) => formData.append(key, String(v)));
|
|
1025
|
+
} else {
|
|
1026
|
+
formData.append(key, String(value));
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
const json = await wretch(this.config.baseUrl).auth(`Bearer ${this.config.apiKey}`).url(url).body(formData).post().json();
|
|
607
1032
|
if (json.status === "error" && json.error) {
|
|
608
1033
|
throw createTypedError(json.error.code, json.error.message);
|
|
609
1034
|
}
|
|
@@ -626,8 +1051,12 @@ var AllDebridClient = class {
|
|
|
626
1051
|
}
|
|
627
1052
|
/**
|
|
628
1053
|
* Make a POST request with FormData (multipart/form-data)
|
|
629
|
-
* @
|
|
1054
|
+
* @template T - The generated response type
|
|
1055
|
+
* @param path - API endpoint path
|
|
1056
|
+
* @param formData - Form data to send
|
|
1057
|
+
* @param params - Optional query parameters
|
|
630
1058
|
* @returns The extracted data from the response (without the { status, data } wrapper)
|
|
1059
|
+
* @internal
|
|
631
1060
|
*/
|
|
632
1061
|
async postFormData(path, formData, params) {
|
|
633
1062
|
try {
|
|
@@ -655,17 +1084,23 @@ var AllDebridClient = class {
|
|
|
655
1084
|
}
|
|
656
1085
|
/**
|
|
657
1086
|
* Test the API connection
|
|
1087
|
+
*
|
|
1088
|
+
* This endpoint doesn't require authentication and can be used to verify
|
|
1089
|
+
* that the AllDebrid API is reachable.
|
|
1090
|
+
*
|
|
1091
|
+
* @example
|
|
1092
|
+
* ```ts
|
|
1093
|
+
* const result = await client.ping()
|
|
1094
|
+
* console.log(result.ping) // 'pong'
|
|
1095
|
+
* ```
|
|
1096
|
+
*
|
|
1097
|
+
* @returns Ping response with 'pong' message
|
|
658
1098
|
*/
|
|
659
1099
|
async ping() {
|
|
660
|
-
|
|
661
|
-
await this.get("/user");
|
|
662
|
-
return true;
|
|
663
|
-
} catch {
|
|
664
|
-
return false;
|
|
665
|
-
}
|
|
1100
|
+
return this.get("/ping");
|
|
666
1101
|
}
|
|
667
1102
|
};
|
|
668
1103
|
|
|
669
|
-
export { AllDebridClient, AllDebridError, AuthenticationError, HostResource, LinkError, LinkResource, MagnetError, MagnetResource, NetworkError, UserResource, createTypedError };
|
|
1104
|
+
export { AllDebridClient, AllDebridError, AuthenticationError, HostResource, LinkError, LinkResource, MagnetError, MagnetResource, NetworkError, PinResource, UserResource, VoucherResource, createTypedError };
|
|
670
1105
|
//# sourceMappingURL=index.js.map
|
|
671
1106
|
//# sourceMappingURL=index.js.map
|