@adbjs/sdk 2.0.2 → 2.1.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 +7 -5
- package/dist/index.cjs +315 -763
- package/dist/index.d.cts +1266 -1275
- package/dist/index.d.ts +1266 -1275
- package/dist/index.js +318 -748
- package/package.json +10 -8
- package/dist/index.cjs.map +0 -1
- package/dist/index.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1,15 +1,252 @@
|
|
|
1
|
-
|
|
1
|
+
// node_modules/wretch/dist/utils.js
|
|
2
|
+
function extractContentType(headers = {}) {
|
|
3
|
+
const normalizedHeaders = headers instanceof Array ? Object.fromEntries(headers) : headers;
|
|
4
|
+
for (const k in normalizedHeaders) {
|
|
5
|
+
if (k.toLowerCase() === "content-type")
|
|
6
|
+
return normalizedHeaders[k];
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
function isLikelyJsonMime(value) {
|
|
10
|
+
return /^application\/.*json/.test(value);
|
|
11
|
+
}
|
|
12
|
+
var mix = (one, two, mergeArrays = false) => {
|
|
13
|
+
const acc = { ...one };
|
|
14
|
+
for (const key in two) {
|
|
15
|
+
if (!Object.prototype.hasOwnProperty.call(two, key))
|
|
16
|
+
continue;
|
|
17
|
+
const value = one[key];
|
|
18
|
+
const newValue = two[key];
|
|
19
|
+
acc[key] = Array.isArray(value) && Array.isArray(newValue) ? mergeArrays ? [...value, ...newValue] : newValue : typeof value === "object" && typeof newValue === "object" ? mix(value, newValue, mergeArrays) : newValue;
|
|
20
|
+
}
|
|
21
|
+
return acc;
|
|
22
|
+
};
|
|
2
23
|
|
|
3
|
-
|
|
24
|
+
// node_modules/wretch/dist/constants.js
|
|
25
|
+
var JSON_MIME = "application/json";
|
|
26
|
+
var FETCH_ERROR = Symbol();
|
|
27
|
+
var CATCHER_FALLBACK = Symbol();
|
|
4
28
|
|
|
5
|
-
|
|
29
|
+
// node_modules/wretch/dist/middleware.js
|
|
30
|
+
var middlewareHelper = (middlewares) => (fetchFunction) => middlewares.reduceRight((acc, curr) => curr(acc), fetchFunction);
|
|
6
31
|
|
|
7
|
-
|
|
32
|
+
// node_modules/wretch/dist/resolver.js
|
|
33
|
+
class WretchError extends Error {
|
|
34
|
+
}
|
|
35
|
+
var resolver = (wretch) => {
|
|
36
|
+
const sharedState = Object.create(null);
|
|
37
|
+
wretch = wretch._addons.reduce((w, addon) => addon.beforeRequest && addon.beforeRequest(w, wretch._options, sharedState) || w, wretch);
|
|
38
|
+
const { _url: url, _options: opts, _fetch: customFetch, _errorTransformer: errorTransformer, _catchers, _resolvers: resolvers, _middlewares: middlewares, _addons: addons } = wretch;
|
|
39
|
+
const catchers = new Map(_catchers);
|
|
40
|
+
const finalOptions = opts;
|
|
41
|
+
let finalUrl = url;
|
|
42
|
+
const _fetchReq = middlewareHelper(middlewares)((url2, options) => {
|
|
43
|
+
finalUrl = url2;
|
|
44
|
+
const fetchImpl = customFetch || fetch;
|
|
45
|
+
return fetchImpl(url2, options);
|
|
46
|
+
})(url, finalOptions);
|
|
47
|
+
const referenceError = new Error;
|
|
48
|
+
const throwingPromise = _fetchReq.then(async (response) => {
|
|
49
|
+
if (!response.ok) {
|
|
50
|
+
const err = new WretchError;
|
|
51
|
+
err["cause"] = referenceError;
|
|
52
|
+
err.stack += `
|
|
53
|
+
CAUSE: ` + referenceError.stack;
|
|
54
|
+
err.response = response;
|
|
55
|
+
err.status = response.status;
|
|
56
|
+
err.url = finalUrl;
|
|
57
|
+
if (response.type === "opaque" || errorTransformer) {
|
|
58
|
+
err.message = response.statusText;
|
|
59
|
+
} else {
|
|
60
|
+
try {
|
|
61
|
+
err.message = await response.clone().text();
|
|
62
|
+
} catch (_a) {
|
|
63
|
+
err.message = response.statusText;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
throw err;
|
|
67
|
+
}
|
|
68
|
+
return response;
|
|
69
|
+
});
|
|
70
|
+
const catchersWrapper = (promise) => promise.catch(async (error) => {
|
|
71
|
+
const catcher = catchers.get(error === null || error === undefined ? undefined : error.status) || catchers.get(error === null || error === undefined ? undefined : error.name) || !(error instanceof WretchError) && catchers.get(FETCH_ERROR) || catchers.get(CATCHER_FALLBACK);
|
|
72
|
+
if (error.response && errorTransformer) {
|
|
73
|
+
error = await errorTransformer(error, error.response, wretch);
|
|
74
|
+
}
|
|
75
|
+
if (catcher)
|
|
76
|
+
return catcher(error, wretch);
|
|
77
|
+
throw error;
|
|
78
|
+
});
|
|
79
|
+
const bodyParser = (funName) => (cb) => {
|
|
80
|
+
const promise = funName ? throwingPromise.then((_) => _ === null || _ === undefined ? undefined : _[funName]()) : throwingPromise;
|
|
81
|
+
return catchersWrapper(cb ? promise.then(cb) : promise);
|
|
82
|
+
};
|
|
83
|
+
const responseChain = {
|
|
84
|
+
_wretchReq: wretch,
|
|
85
|
+
_fetchReq,
|
|
86
|
+
_sharedState: sharedState,
|
|
87
|
+
res: bodyParser(null),
|
|
88
|
+
json: bodyParser("json"),
|
|
89
|
+
blob: bodyParser("blob"),
|
|
90
|
+
formData: bodyParser("formData"),
|
|
91
|
+
arrayBuffer: bodyParser("arrayBuffer"),
|
|
92
|
+
text: bodyParser("text"),
|
|
93
|
+
error(errorId, cb) {
|
|
94
|
+
catchers.set(errorId, cb);
|
|
95
|
+
return this;
|
|
96
|
+
},
|
|
97
|
+
badRequest(cb) {
|
|
98
|
+
return this.error(400, cb);
|
|
99
|
+
},
|
|
100
|
+
unauthorized(cb) {
|
|
101
|
+
return this.error(401, cb);
|
|
102
|
+
},
|
|
103
|
+
forbidden(cb) {
|
|
104
|
+
return this.error(403, cb);
|
|
105
|
+
},
|
|
106
|
+
notFound(cb) {
|
|
107
|
+
return this.error(404, cb);
|
|
108
|
+
},
|
|
109
|
+
timeout(cb) {
|
|
110
|
+
return this.error(408, cb);
|
|
111
|
+
},
|
|
112
|
+
internalError(cb) {
|
|
113
|
+
return this.error(500, cb);
|
|
114
|
+
},
|
|
115
|
+
fetchError(cb) {
|
|
116
|
+
return this.error(FETCH_ERROR, cb);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
const enhancedResponseChain = addons.reduce((chain, addon) => ({
|
|
120
|
+
...chain,
|
|
121
|
+
...typeof addon.resolver === "function" ? addon.resolver(chain) : addon.resolver
|
|
122
|
+
}), responseChain);
|
|
123
|
+
return resolvers.reduce((chain, r) => r(chain, wretch), enhancedResponseChain);
|
|
124
|
+
};
|
|
8
125
|
|
|
9
|
-
//
|
|
126
|
+
// node_modules/wretch/dist/core.js
|
|
127
|
+
var core = {
|
|
128
|
+
_url: "",
|
|
129
|
+
_options: {},
|
|
130
|
+
_catchers: new Map,
|
|
131
|
+
_resolvers: [],
|
|
132
|
+
_deferred: [],
|
|
133
|
+
_middlewares: [],
|
|
134
|
+
_addons: [],
|
|
135
|
+
addon(addon) {
|
|
136
|
+
const addons = Array.isArray(addon) ? addon : [addon];
|
|
137
|
+
const wretchProps = addons.reduce((acc, a) => ({ ...acc, ...a.wretch }), {});
|
|
138
|
+
return { ...this, _addons: [...this._addons, ...addons], ...wretchProps };
|
|
139
|
+
},
|
|
140
|
+
fetchPolyfill(fetchImpl) {
|
|
141
|
+
return { ...this, _fetch: fetchImpl };
|
|
142
|
+
},
|
|
143
|
+
url(_url, replace = false) {
|
|
144
|
+
if (replace)
|
|
145
|
+
return { ...this, _url };
|
|
146
|
+
const idx = this._url.indexOf("?");
|
|
147
|
+
return {
|
|
148
|
+
...this,
|
|
149
|
+
_url: idx > -1 ? this._url.slice(0, idx) + _url + this._url.slice(idx) : this._url + _url
|
|
150
|
+
};
|
|
151
|
+
},
|
|
152
|
+
options(options, replace = false) {
|
|
153
|
+
return { ...this, _options: replace ? options : mix(this._options, options) };
|
|
154
|
+
},
|
|
155
|
+
headers(headerValues) {
|
|
156
|
+
const headers = !headerValues ? {} : Array.isArray(headerValues) ? Object.fromEntries(headerValues) : ("entries" in headerValues) ? Object.fromEntries(headerValues.entries()) : headerValues;
|
|
157
|
+
return { ...this, _options: mix(this._options, { headers }) };
|
|
158
|
+
},
|
|
159
|
+
accept(headerValue) {
|
|
160
|
+
return this.headers({ Accept: headerValue });
|
|
161
|
+
},
|
|
162
|
+
content(headerValue) {
|
|
163
|
+
return this.headers({ "Content-Type": headerValue });
|
|
164
|
+
},
|
|
165
|
+
auth(headerValue) {
|
|
166
|
+
return this.headers({ Authorization: headerValue });
|
|
167
|
+
},
|
|
168
|
+
catcher(errorId, catcher) {
|
|
169
|
+
const newMap = new Map(this._catchers);
|
|
170
|
+
newMap.set(errorId, catcher);
|
|
171
|
+
return { ...this, _catchers: newMap };
|
|
172
|
+
},
|
|
173
|
+
catcherFallback(catcher) {
|
|
174
|
+
return this.catcher(CATCHER_FALLBACK, catcher);
|
|
175
|
+
},
|
|
176
|
+
customError(transformer) {
|
|
177
|
+
return { ...this, _errorTransformer: transformer };
|
|
178
|
+
},
|
|
179
|
+
resolve(resolver2, clear = false) {
|
|
180
|
+
return { ...this, _resolvers: clear ? [resolver2] : [...this._resolvers, resolver2] };
|
|
181
|
+
},
|
|
182
|
+
defer(callback, clear = false) {
|
|
183
|
+
return {
|
|
184
|
+
...this,
|
|
185
|
+
_deferred: clear ? [callback] : [...this._deferred, callback]
|
|
186
|
+
};
|
|
187
|
+
},
|
|
188
|
+
middlewares(middlewares, clear = false) {
|
|
189
|
+
return {
|
|
190
|
+
...this,
|
|
191
|
+
_middlewares: clear ? middlewares : [...this._middlewares, ...middlewares]
|
|
192
|
+
};
|
|
193
|
+
},
|
|
194
|
+
fetch(method = this._options.method, url = "", body = null) {
|
|
195
|
+
let base = this.url(url).options({ method });
|
|
196
|
+
const contentType = extractContentType(base._options.headers);
|
|
197
|
+
const jsonify = typeof body === "object" && !(body instanceof FormData) && (!base._options.headers || !contentType || isLikelyJsonMime(contentType));
|
|
198
|
+
base = !body ? base : jsonify ? base.json(body, contentType) : base.body(body);
|
|
199
|
+
return resolver(base._deferred.reduce((acc, curr) => curr(acc, acc._url, acc._options), base));
|
|
200
|
+
},
|
|
201
|
+
get(url = "") {
|
|
202
|
+
return this.fetch("GET", url);
|
|
203
|
+
},
|
|
204
|
+
delete(url = "") {
|
|
205
|
+
return this.fetch("DELETE", url);
|
|
206
|
+
},
|
|
207
|
+
put(body, url = "") {
|
|
208
|
+
return this.fetch("PUT", url, body);
|
|
209
|
+
},
|
|
210
|
+
post(body, url = "") {
|
|
211
|
+
return this.fetch("POST", url, body);
|
|
212
|
+
},
|
|
213
|
+
patch(body, url = "") {
|
|
214
|
+
return this.fetch("PATCH", url, body);
|
|
215
|
+
},
|
|
216
|
+
head(url = "") {
|
|
217
|
+
return this.fetch("HEAD", url);
|
|
218
|
+
},
|
|
219
|
+
opts(url = "") {
|
|
220
|
+
return this.fetch("OPTIONS", url);
|
|
221
|
+
},
|
|
222
|
+
body(contents) {
|
|
223
|
+
return { ...this, _options: { ...this._options, body: contents } };
|
|
224
|
+
},
|
|
225
|
+
json(jsObject, contentType) {
|
|
226
|
+
const currentContentType = extractContentType(this._options.headers);
|
|
227
|
+
return this.content(contentType || isLikelyJsonMime(currentContentType) && currentContentType || JSON_MIME).body(JSON.stringify(jsObject));
|
|
228
|
+
},
|
|
229
|
+
toFetch() {
|
|
230
|
+
return (fetchUrl, fetchOptions = {}) => {
|
|
231
|
+
return this.url(fetchUrl).options(fetchOptions).catcherFallback((error) => {
|
|
232
|
+
if (error instanceof WretchError) {
|
|
233
|
+
return error.response;
|
|
234
|
+
} else {
|
|
235
|
+
throw error;
|
|
236
|
+
}
|
|
237
|
+
}).fetch().res();
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
// node_modules/wretch/dist/index.js
|
|
243
|
+
var factory = (_url = "", _options = {}) => ({ ...core, _url, _options });
|
|
244
|
+
factory["default"] = factory;
|
|
245
|
+
factory.WretchError = WretchError;
|
|
246
|
+
var dist_default = factory;
|
|
10
247
|
|
|
11
248
|
// src/errors.ts
|
|
12
|
-
|
|
249
|
+
class AllDebridError extends Error {
|
|
13
250
|
code;
|
|
14
251
|
isAllDebridError = true;
|
|
15
252
|
constructor(code, message) {
|
|
@@ -17,41 +254,43 @@ var AllDebridError = class _AllDebridError extends Error {
|
|
|
17
254
|
this.name = "AllDebridError";
|
|
18
255
|
this.code = code;
|
|
19
256
|
if ("captureStackTrace" in Error && typeof Error.captureStackTrace === "function") {
|
|
20
|
-
Error.captureStackTrace(this,
|
|
257
|
+
Error.captureStackTrace(this, AllDebridError);
|
|
21
258
|
}
|
|
22
259
|
}
|
|
23
|
-
/**
|
|
24
|
-
* Create an AllDebridError from an API error response
|
|
25
|
-
*/
|
|
26
260
|
static fromApiError(error) {
|
|
27
|
-
return new
|
|
261
|
+
return new AllDebridError(error.code, error.message);
|
|
28
262
|
}
|
|
29
|
-
}
|
|
30
|
-
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
class AuthenticationError extends AllDebridError {
|
|
31
266
|
constructor(code, message) {
|
|
32
267
|
super(code, message);
|
|
33
268
|
this.name = "AuthenticationError";
|
|
34
269
|
}
|
|
35
|
-
}
|
|
36
|
-
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
class LinkError extends AllDebridError {
|
|
37
273
|
constructor(code, message) {
|
|
38
274
|
super(code, message);
|
|
39
275
|
this.name = "LinkError";
|
|
40
276
|
}
|
|
41
|
-
}
|
|
42
|
-
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
class MagnetError extends AllDebridError {
|
|
43
280
|
constructor(code, message) {
|
|
44
281
|
super(code, message);
|
|
45
282
|
this.name = "MagnetError";
|
|
46
283
|
}
|
|
47
|
-
}
|
|
48
|
-
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
class NetworkError extends AllDebridError {
|
|
287
|
+
statusCode;
|
|
49
288
|
constructor(message, statusCode) {
|
|
50
289
|
super("NETWORK_ERROR", message);
|
|
51
290
|
this.statusCode = statusCode;
|
|
52
291
|
this.name = "NetworkError";
|
|
53
292
|
}
|
|
54
|
-
}
|
|
293
|
+
}
|
|
55
294
|
function createTypedError(code, message) {
|
|
56
295
|
if (code.startsWith("AUTH_")) {
|
|
57
296
|
return new AuthenticationError(code, message);
|
|
@@ -66,263 +305,82 @@ function createTypedError(code, message) {
|
|
|
66
305
|
}
|
|
67
306
|
|
|
68
307
|
// src/base-resource.ts
|
|
69
|
-
|
|
308
|
+
class BaseResource {
|
|
309
|
+
client;
|
|
70
310
|
constructor(client) {
|
|
71
311
|
this.client = client;
|
|
72
312
|
}
|
|
73
|
-
/**
|
|
74
|
-
* Make a GET request
|
|
75
|
-
* @template T - The generated response type (e.g., GetLinkUnlockResponse)
|
|
76
|
-
* @param path - API endpoint path
|
|
77
|
-
* @param params - Optional query parameters
|
|
78
|
-
* @returns The extracted data from the response (without the { status, data } wrapper)
|
|
79
|
-
*/
|
|
80
313
|
async get(path, params) {
|
|
81
314
|
return this.client.get(path, params);
|
|
82
315
|
}
|
|
83
|
-
/**
|
|
84
|
-
* Make a POST request
|
|
85
|
-
* @template T - The generated response type
|
|
86
|
-
* @param path - API endpoint path
|
|
87
|
-
* @param body - Request body
|
|
88
|
-
* @param params - Optional query parameters
|
|
89
|
-
* @returns The extracted data from the response (without the { status, data } wrapper)
|
|
90
|
-
*/
|
|
91
316
|
async post(path, body, params) {
|
|
92
317
|
return this.client.post(path, body, params);
|
|
93
318
|
}
|
|
94
|
-
/**
|
|
95
|
-
* Make a POST request with FormData (multipart/form-data)
|
|
96
|
-
* @template T - The generated response type
|
|
97
|
-
* @param path - API endpoint path
|
|
98
|
-
* @param formData - Form data to send
|
|
99
|
-
* @param params - Optional query parameters
|
|
100
|
-
* @returns The extracted data from the response (without the { status, data } wrapper)
|
|
101
|
-
*/
|
|
102
319
|
async postFormData(path, formData, params) {
|
|
103
320
|
return this.client.postFormData(path, formData, params);
|
|
104
321
|
}
|
|
105
|
-
}
|
|
322
|
+
}
|
|
106
323
|
|
|
107
324
|
// src/resources/host.ts
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Get list of all supported hosts with their information
|
|
111
|
-
*
|
|
112
|
-
* @param hostOnly - If true, only return hosts (exclude streams and redirectors)
|
|
113
|
-
*
|
|
114
|
-
* @example
|
|
115
|
-
* ```ts
|
|
116
|
-
* const hosts = await client.host.list()
|
|
117
|
-
* console.log(hosts.hosts) // All supported file hosts
|
|
118
|
-
* console.log(hosts.streams) // Streaming hosts
|
|
119
|
-
* console.log(hosts.redirectors) // Link redirectors
|
|
120
|
-
* ```
|
|
121
|
-
*/
|
|
325
|
+
class HostResource extends BaseResource {
|
|
122
326
|
async list(hostOnly) {
|
|
123
|
-
const params = hostOnly ? { hostOnly: "1" } :
|
|
327
|
+
const params = hostOnly ? { hostOnly: "1" } : undefined;
|
|
124
328
|
return this.get("/hosts", params);
|
|
125
329
|
}
|
|
126
|
-
/**
|
|
127
|
-
* Get array of all supported domain names
|
|
128
|
-
*
|
|
129
|
-
* @example
|
|
130
|
-
* ```ts
|
|
131
|
-
* const domains = await client.host.domains()
|
|
132
|
-
* console.log(domains) // ['rapidgator.net', 'uploaded.net', ...]
|
|
133
|
-
* ```
|
|
134
|
-
*/
|
|
135
330
|
async domains() {
|
|
136
331
|
return this.get("/hosts/domains");
|
|
137
332
|
}
|
|
138
|
-
/**
|
|
139
|
-
* Get hosts ordered by restriction level (priority list)
|
|
140
|
-
*
|
|
141
|
-
* @example
|
|
142
|
-
* ```ts
|
|
143
|
-
* const priority = await client.host.priority()
|
|
144
|
-
* console.log(priority.hosts) // Ordered list with restriction levels
|
|
145
|
-
* ```
|
|
146
|
-
*/
|
|
147
333
|
async priority() {
|
|
148
334
|
return this.get("/hosts/priority");
|
|
149
335
|
}
|
|
150
|
-
}
|
|
336
|
+
}
|
|
151
337
|
|
|
152
338
|
// src/resources/link.ts
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Get information about one or more links
|
|
156
|
-
*
|
|
157
|
-
* @param links - Single link or array of links to get info for
|
|
158
|
-
* @param password - Optional password for password-protected links
|
|
159
|
-
*
|
|
160
|
-
* @example
|
|
161
|
-
* ```ts
|
|
162
|
-
* const data = await client.link.infos('https://example.com/file.zip')
|
|
163
|
-
* console.log(data.infos)
|
|
164
|
-
*
|
|
165
|
-
* // With password
|
|
166
|
-
* const protectedData = await client.link.infos(
|
|
167
|
-
* 'https://example.com/protected.zip',
|
|
168
|
-
* 'mypassword'
|
|
169
|
-
* )
|
|
170
|
-
* ```
|
|
171
|
-
*/
|
|
339
|
+
class LinkResource extends BaseResource {
|
|
172
340
|
async infos(links, password) {
|
|
173
341
|
const linksArray = Array.isArray(links) ? links : [links];
|
|
174
|
-
const params = password ? { password } :
|
|
342
|
+
const params = password ? { password } : undefined;
|
|
175
343
|
return this.post("/link/infos", { "link[]": linksArray }, params);
|
|
176
344
|
}
|
|
177
|
-
/**
|
|
178
|
-
* Extract links from redirectors/link protectors
|
|
179
|
-
*
|
|
180
|
-
* @param link - The redirector link to extract from
|
|
181
|
-
*
|
|
182
|
-
* @example
|
|
183
|
-
* ```ts
|
|
184
|
-
* const data = await client.link.redirector('https://linkprotector.com/abc123')
|
|
185
|
-
* console.log(data.links)
|
|
186
|
-
* ```
|
|
187
|
-
*/
|
|
188
345
|
async redirector(link) {
|
|
189
346
|
return this.post("/link/redirector", {
|
|
190
347
|
link
|
|
191
348
|
});
|
|
192
349
|
}
|
|
193
|
-
/**
|
|
194
|
-
* Unlock a download link
|
|
195
|
-
*
|
|
196
|
-
* @param link - The link to unlock
|
|
197
|
-
* @param password - Optional password for password-protected links
|
|
198
|
-
*
|
|
199
|
-
* @example
|
|
200
|
-
* ```ts
|
|
201
|
-
* const result = await client.link.unlock('https://example.com/file.zip')
|
|
202
|
-
* if (result.link) {
|
|
203
|
-
* console.log('Direct link:', result.link)
|
|
204
|
-
* } else if (result.delayed) {
|
|
205
|
-
* // Handle delayed generation
|
|
206
|
-
* const delayedResult = await client.link.delayed(result.delayed)
|
|
207
|
-
* }
|
|
208
|
-
*
|
|
209
|
-
* // With password
|
|
210
|
-
* const protectedResult = await client.link.unlock(
|
|
211
|
-
* 'https://example.com/protected.zip',
|
|
212
|
-
* 'mypassword'
|
|
213
|
-
* )
|
|
214
|
-
* ```
|
|
215
|
-
*/
|
|
216
350
|
async unlock(link, password) {
|
|
217
|
-
const params = password ? { password } :
|
|
351
|
+
const params = password ? { password } : undefined;
|
|
218
352
|
return this.post("/link/unlock", { link }, params);
|
|
219
353
|
}
|
|
220
|
-
/**
|
|
221
|
-
* Unlock a link and automatically poll if delayed
|
|
222
|
-
* Note: The API response format doesn't include a delayed field in the current OpenAPI spec.
|
|
223
|
-
* This method will be updated once the delayed mechanism is documented.
|
|
224
|
-
*
|
|
225
|
-
* @param link - The link to unlock
|
|
226
|
-
* @param _options - Polling options (currently unused)
|
|
227
|
-
*
|
|
228
|
-
* @example
|
|
229
|
-
* ```ts
|
|
230
|
-
* const result = await client.link.unlockWithPolling('https://example.com/file.zip')
|
|
231
|
-
* console.log('Direct link:', result.link)
|
|
232
|
-
* ```
|
|
233
|
-
*/
|
|
234
354
|
async unlockWithPolling(link, _options = {}) {
|
|
235
355
|
return this.unlock(link);
|
|
236
356
|
}
|
|
237
|
-
/**
|
|
238
|
-
* Get streaming options for a generated link
|
|
239
|
-
*
|
|
240
|
-
* @param id - The generated link ID or streaming ID
|
|
241
|
-
*
|
|
242
|
-
* @example
|
|
243
|
-
* ```ts
|
|
244
|
-
* const streams = await client.link.streaming('abc123')
|
|
245
|
-
* ```
|
|
246
|
-
*/
|
|
247
357
|
async streaming(id, stream) {
|
|
248
358
|
return this.post("/link/streaming", {
|
|
249
359
|
id,
|
|
250
360
|
stream
|
|
251
361
|
});
|
|
252
362
|
}
|
|
253
|
-
/**
|
|
254
|
-
* Get the status/result of a delayed link generation
|
|
255
|
-
*
|
|
256
|
-
* @param id - The delayed generation ID
|
|
257
|
-
*
|
|
258
|
-
* @example
|
|
259
|
-
* ```ts
|
|
260
|
-
* const result = await client.link.delayed('delayed_id_123')
|
|
261
|
-
* ```
|
|
262
|
-
*/
|
|
263
363
|
async delayed(id) {
|
|
264
364
|
return this.post("/link/delayed", {
|
|
265
365
|
id
|
|
266
366
|
});
|
|
267
367
|
}
|
|
268
|
-
}
|
|
368
|
+
}
|
|
269
369
|
|
|
270
370
|
// src/resources/magnet.ts
|
|
271
|
-
|
|
272
|
-
/**
|
|
273
|
-
* Upload magnets by URI or hash
|
|
274
|
-
*
|
|
275
|
-
* @param magnets - Single magnet URI/hash or array of magnets
|
|
276
|
-
*
|
|
277
|
-
* @example
|
|
278
|
-
* ```ts
|
|
279
|
-
* const result = await client.magnet.upload('magnet:?xt=urn:btih:...')
|
|
280
|
-
* console.log('Magnet ID:', result.magnets[0].id)
|
|
281
|
-
* ```
|
|
282
|
-
*/
|
|
371
|
+
class MagnetResource extends BaseResource {
|
|
283
372
|
async upload(magnets) {
|
|
284
373
|
const magnetsArray = Array.isArray(magnets) ? magnets : [magnets];
|
|
285
374
|
return this.post("/magnet/upload", {
|
|
286
375
|
magnets: magnetsArray
|
|
287
376
|
});
|
|
288
377
|
}
|
|
289
|
-
/**
|
|
290
|
-
* Upload a torrent file
|
|
291
|
-
*
|
|
292
|
-
* @param file - The torrent file (Blob or File)
|
|
293
|
-
* @param filename - Optional filename (defaults to 'torrent.torrent' for Blob, or file.name for File)
|
|
294
|
-
*
|
|
295
|
-
* @example
|
|
296
|
-
* ```ts
|
|
297
|
-
* const file = new File([buffer], 'torrent.torrent')
|
|
298
|
-
* const result = await client.magnet.uploadFile(file)
|
|
299
|
-
*
|
|
300
|
-
* // Or with a Blob and custom filename
|
|
301
|
-
* const blob = new Blob([buffer])
|
|
302
|
-
* const result = await client.magnet.uploadFile(blob, 'my-torrent.torrent')
|
|
303
|
-
* ```
|
|
304
|
-
*/
|
|
305
378
|
async uploadFile(file, filename) {
|
|
306
|
-
const formData = new FormData
|
|
379
|
+
const formData = new FormData;
|
|
307
380
|
const actualFilename = filename || (file instanceof File ? file.name : "torrent.torrent");
|
|
308
381
|
formData.append("files[]", file, actualFilename);
|
|
309
382
|
return this.postFormData("/magnet/upload/file", formData);
|
|
310
383
|
}
|
|
311
|
-
/**
|
|
312
|
-
* Get the status of a specific magnet by ID
|
|
313
|
-
*
|
|
314
|
-
* @param id - Magnet ID to get status for
|
|
315
|
-
*
|
|
316
|
-
* @example
|
|
317
|
-
* ```ts
|
|
318
|
-
* const status = await client.magnet.status(123)
|
|
319
|
-
* console.log(status.magnets[0]?.status) // 'Downloading', 'Ready', etc.
|
|
320
|
-
* ```
|
|
321
|
-
*
|
|
322
|
-
* @remarks
|
|
323
|
-
* This endpoint uses AllDebrid API v4.1 (POST method)
|
|
324
|
-
* Migrated from v4 GET endpoint which was deprecated on 2024-10-16
|
|
325
|
-
*/
|
|
326
384
|
async status(id) {
|
|
327
385
|
const data = await this.post("/magnet/status", { id });
|
|
328
386
|
if (data?.magnets && !Array.isArray(data.magnets)) {
|
|
@@ -333,123 +391,10 @@ var MagnetResource = class extends BaseResource {
|
|
|
333
391
|
}
|
|
334
392
|
return data;
|
|
335
393
|
}
|
|
336
|
-
/**
|
|
337
|
-
* Get list of magnets with optional status filter
|
|
338
|
-
*
|
|
339
|
-
* @param statusFilter - Optional filter by status: 'active', 'ready', 'expired', or 'error'
|
|
340
|
-
*
|
|
341
|
-
* @example
|
|
342
|
-
* ```ts
|
|
343
|
-
* // Get all magnets
|
|
344
|
-
* const allMagnets = await client.magnet.statusList()
|
|
345
|
-
*
|
|
346
|
-
* // Get only active magnets
|
|
347
|
-
* const activeMagnets = await client.magnet.statusList('active')
|
|
348
|
-
*
|
|
349
|
-
* // Get only ready magnets
|
|
350
|
-
* const readyMagnets = await client.magnet.statusList('ready')
|
|
351
|
-
* ```
|
|
352
|
-
*
|
|
353
|
-
* @remarks
|
|
354
|
-
* This endpoint uses AllDebrid API v4.1 (POST method)
|
|
355
|
-
*/
|
|
356
394
|
async statusList(statusFilter) {
|
|
357
|
-
const body = statusFilter ? { status: statusFilter } :
|
|
395
|
+
const body = statusFilter ? { status: statusFilter } : undefined;
|
|
358
396
|
return this.post("/magnet/status", body);
|
|
359
397
|
}
|
|
360
|
-
/**
|
|
361
|
-
* Get magnet status using live mode for bandwidth-optimized delta synchronization
|
|
362
|
-
*
|
|
363
|
-
* Live mode is designed for monitoring multiple magnets efficiently by only transmitting
|
|
364
|
-
* changes between polling intervals, drastically reducing bandwidth usage for dashboards
|
|
365
|
-
* and real-time monitoring applications.
|
|
366
|
-
*
|
|
367
|
-
* ## How it works
|
|
368
|
-
*
|
|
369
|
-
* 1. **Session initialization**: Generate a random session ID and start with counter = 0
|
|
370
|
-
* 2. **First call (fullsync)**: Returns ALL magnets with `fullsync: true`
|
|
371
|
-
* 3. **Update counter**: Use the `counter` value returned by the API for the next call
|
|
372
|
-
* 4. **Subsequent calls (delta)**: Returns ONLY magnets that changed since last call
|
|
373
|
-
* 5. **Repeat**: Keep calling with updated counter to receive only deltas
|
|
374
|
-
*
|
|
375
|
-
* ## When to use
|
|
376
|
-
*
|
|
377
|
-
* - ✅ Monitoring multiple active magnets simultaneously
|
|
378
|
-
* - ✅ Building real-time dashboards
|
|
379
|
-
* - ✅ High-frequency polling scenarios (every few seconds)
|
|
380
|
-
* - ❌ Watching a single specific magnet (use `watch()` instead)
|
|
381
|
-
*
|
|
382
|
-
* ## Important notes
|
|
383
|
-
*
|
|
384
|
-
* - **Don't use the `id` parameter**: Passing an ID defeats the purpose of live mode
|
|
385
|
-
* as it disables delta sync and behaves like a regular `status()` call
|
|
386
|
-
* - **Session persistence**: Keep the same session ID for the entire monitoring session
|
|
387
|
-
* - **Counter tracking**: Always update the counter with the value returned by the API
|
|
388
|
-
* - **Empty deltas**: When no magnets changed, `magnets` will be an empty array
|
|
389
|
-
*
|
|
390
|
-
* @param options - Live mode session options
|
|
391
|
-
* @param options.session - Unique session ID (generate once: `Math.floor(Math.random() * 1000000)`)
|
|
392
|
-
* @param options.counter - Sync counter (start at 0, then use value from previous API response)
|
|
393
|
-
*
|
|
394
|
-
* @example
|
|
395
|
-
* ```ts
|
|
396
|
-
* // Initialize session
|
|
397
|
-
* const session = Math.floor(Math.random() * 1000000)
|
|
398
|
-
* let counter = 0
|
|
399
|
-
*
|
|
400
|
-
* // First call - returns all magnets (fullsync: true)
|
|
401
|
-
* const firstCall = await client.magnet.statusLive({ session, counter })
|
|
402
|
-
* console.log('Full sync:', firstCall.fullsync) // true
|
|
403
|
-
* console.log('All magnets:', firstCall.magnets) // Array of all magnets
|
|
404
|
-
* counter = firstCall.counter // Update counter for next call
|
|
405
|
-
*
|
|
406
|
-
* // Second call - returns only magnets that changed
|
|
407
|
-
* await new Promise(resolve => setTimeout(resolve, 3000)) // Wait 3 seconds
|
|
408
|
-
* const secondCall = await client.magnet.statusLive({ session, counter })
|
|
409
|
-
* console.log('Delta sync:', secondCall.magnets) // Only changed magnets
|
|
410
|
-
* counter = secondCall.counter
|
|
411
|
-
*
|
|
412
|
-
* // Example: Monitor all magnets until none are active
|
|
413
|
-
* const activeMagnets = new Map()
|
|
414
|
-
*
|
|
415
|
-
* while (true) {
|
|
416
|
-
* const response = await client.magnet.statusLive({ session, counter })
|
|
417
|
-
* counter = response.counter ?? counter
|
|
418
|
-
*
|
|
419
|
-
* // Update our local state with changes
|
|
420
|
-
* if (response.fullsync) {
|
|
421
|
-
* activeMagnets.clear()
|
|
422
|
-
* response.magnets?.forEach(m => activeMagnets.set(m.id, m))
|
|
423
|
-
* } else {
|
|
424
|
-
* response.magnets?.forEach(m => {
|
|
425
|
-
* if (m.status === 'Ready' || m.status === 'Error' || m.status === 'Expired') {
|
|
426
|
-
* activeMagnets.delete(m.id)
|
|
427
|
-
* } else {
|
|
428
|
-
* activeMagnets.set(m.id, m)
|
|
429
|
-
* }
|
|
430
|
-
* })
|
|
431
|
-
* }
|
|
432
|
-
*
|
|
433
|
-
* // Display current state
|
|
434
|
-
* console.log(`Active downloads: ${activeMagnets.size}`)
|
|
435
|
-
* activeMagnets.forEach(m => {
|
|
436
|
-
* console.log(` ${m.filename}: ${m.status} - ${m.downloaded}/${m.size} bytes`)
|
|
437
|
-
* })
|
|
438
|
-
*
|
|
439
|
-
* // Stop when no more active magnets
|
|
440
|
-
* if (activeMagnets.size === 0) {
|
|
441
|
-
* console.log('All downloads completed!')
|
|
442
|
-
* break
|
|
443
|
-
* }
|
|
444
|
-
*
|
|
445
|
-
* await new Promise(resolve => setTimeout(resolve, 3000))
|
|
446
|
-
* }
|
|
447
|
-
* ```
|
|
448
|
-
*
|
|
449
|
-
* @remarks
|
|
450
|
-
* This method is ideal for scenarios where you're monitoring multiple magnets and want
|
|
451
|
-
* to minimize bandwidth. For simple single-magnet monitoring, use `watch()` instead.
|
|
452
|
-
*/
|
|
453
398
|
async statusLive(options) {
|
|
454
399
|
const body = {
|
|
455
400
|
session: options.session,
|
|
@@ -457,94 +402,27 @@ var MagnetResource = class extends BaseResource {
|
|
|
457
402
|
};
|
|
458
403
|
return this.post("/magnet/status", body);
|
|
459
404
|
}
|
|
460
|
-
/**
|
|
461
|
-
* Delete a magnet
|
|
462
|
-
*
|
|
463
|
-
* @param id - The magnet ID to delete
|
|
464
|
-
*
|
|
465
|
-
* @example
|
|
466
|
-
* ```ts
|
|
467
|
-
* await client.magnet.delete(123)
|
|
468
|
-
* ```
|
|
469
|
-
*/
|
|
470
405
|
async delete(id) {
|
|
471
406
|
return this.post("/magnet/delete", {
|
|
472
407
|
id
|
|
473
408
|
});
|
|
474
409
|
}
|
|
475
|
-
/**
|
|
476
|
-
* Restart one or more failed magnets
|
|
477
|
-
*
|
|
478
|
-
* @param ids - Single magnet ID or array of magnet IDs to restart (numbers)
|
|
479
|
-
*
|
|
480
|
-
* @example
|
|
481
|
-
* ```ts
|
|
482
|
-
* // Restart single magnet
|
|
483
|
-
* await client.magnet.restart(123)
|
|
484
|
-
*
|
|
485
|
-
* // Restart multiple magnets
|
|
486
|
-
* await client.magnet.restart([123, 456])
|
|
487
|
-
* ```
|
|
488
|
-
*/
|
|
489
410
|
async restart(ids) {
|
|
490
411
|
const idsArray = Array.isArray(ids) ? ids : [ids];
|
|
491
412
|
return this.post("/magnet/restart", {
|
|
492
413
|
ids: idsArray
|
|
493
414
|
});
|
|
494
415
|
}
|
|
495
|
-
/**
|
|
496
|
-
* Get files for a completed magnet
|
|
497
|
-
*
|
|
498
|
-
* @param ids - The magnet ID or IDs to get files for
|
|
499
|
-
*
|
|
500
|
-
* @example
|
|
501
|
-
* ```ts
|
|
502
|
-
* const data = await client.magnet.files(123)
|
|
503
|
-
* data?.magnets?.forEach(magnet => {
|
|
504
|
-
* console.log(magnet.filename, magnet.files)
|
|
505
|
-
* })
|
|
506
|
-
* ```
|
|
507
|
-
*
|
|
508
|
-
* @remarks
|
|
509
|
-
* Files are now retrieved separately from magnet status (since v4.1)
|
|
510
|
-
* Only available for magnets with status 'Ready'
|
|
511
|
-
*/
|
|
512
416
|
async files(ids) {
|
|
513
|
-
const formData = new FormData
|
|
417
|
+
const formData = new FormData;
|
|
514
418
|
const idsArray = Array.isArray(ids) ? ids : [ids];
|
|
515
419
|
for (const id of idsArray) {
|
|
516
420
|
formData.append("id[]", String(id));
|
|
517
421
|
}
|
|
518
422
|
return this.postFormData("/magnet/files", formData);
|
|
519
423
|
}
|
|
520
|
-
/**
|
|
521
|
-
* Watch a magnet's status with automatic polling
|
|
522
|
-
*
|
|
523
|
-
* This is a simple helper that polls the status of a specific magnet until it reaches
|
|
524
|
-
* a target status (default: 'Ready'). For advanced use cases with multiple magnets
|
|
525
|
-
* or bandwidth optimization, use `statusLive()` directly instead.
|
|
526
|
-
*
|
|
527
|
-
* @param id - The magnet ID to watch
|
|
528
|
-
* @param options - Watch options
|
|
529
|
-
* @param options.interval - Polling interval in milliseconds (default: 3000)
|
|
530
|
-
* @param options.maxAttempts - Maximum polling attempts, 0 for infinite (default: 0)
|
|
531
|
-
* @param options.onUpdate - Callback called on each status update
|
|
532
|
-
* @param options.stopOnStatus - Stop when magnet reaches this status (default: 'Ready')
|
|
533
|
-
*
|
|
534
|
-
* @example
|
|
535
|
-
* ```ts
|
|
536
|
-
* await client.magnet.watch(123, {
|
|
537
|
-
* onUpdate: (status) => console.log('Status:', status.magnets[0]?.status),
|
|
538
|
-
* stopOnStatus: 'Ready'
|
|
539
|
-
* })
|
|
540
|
-
* ```
|
|
541
|
-
*
|
|
542
|
-
* @remarks
|
|
543
|
-
* For monitoring multiple magnets efficiently, use `statusLive()` directly.
|
|
544
|
-
* See the `statusLive()` documentation for details on delta synchronization.
|
|
545
|
-
*/
|
|
546
424
|
async watch(id, options = {}) {
|
|
547
|
-
const { interval =
|
|
425
|
+
const { interval = 3000, maxAttempts = 0, onUpdate, stopOnStatus = "Ready" } = options;
|
|
548
426
|
let attempt = 0;
|
|
549
427
|
while (maxAttempts === 0 || attempt < maxAttempts) {
|
|
550
428
|
attempt++;
|
|
@@ -556,105 +434,21 @@ var MagnetResource = class extends BaseResource {
|
|
|
556
434
|
}
|
|
557
435
|
await new Promise((resolve) => setTimeout(resolve, interval));
|
|
558
436
|
}
|
|
559
|
-
throw new Error(
|
|
560
|
-
`Watch timeout: magnet did not reach '${stopOnStatus}' status after ${maxAttempts} attempts`
|
|
561
|
-
);
|
|
437
|
+
throw new Error(`Watch timeout: magnet did not reach '${stopOnStatus}' status after ${maxAttempts} attempts`);
|
|
562
438
|
}
|
|
563
|
-
}
|
|
439
|
+
}
|
|
564
440
|
|
|
565
441
|
// src/resources/pin.ts
|
|
566
|
-
|
|
567
|
-
/**
|
|
568
|
-
* Generate a new PIN code for authentication
|
|
569
|
-
*
|
|
570
|
-
* This initiates the PIN authentication flow. The user should visit the
|
|
571
|
-
* returned URL to authorize the application.
|
|
572
|
-
*
|
|
573
|
-
* @example
|
|
574
|
-
* ```ts
|
|
575
|
-
* const pinData = await client.pin.generate()
|
|
576
|
-
* console.log('Visit:', pinData.user_url)
|
|
577
|
-
* console.log('PIN:', pinData.pin)
|
|
578
|
-
*
|
|
579
|
-
* // Poll the check endpoint until user authorizes
|
|
580
|
-
* const auth = await client.pin.check(pinData.check, pinData.pin)
|
|
581
|
-
* if (auth.activated) {
|
|
582
|
-
* console.log('API Key:', auth.apikey)
|
|
583
|
-
* }
|
|
584
|
-
* ```
|
|
585
|
-
*
|
|
586
|
-
* @returns PIN code and authorization URL
|
|
587
|
-
*/
|
|
442
|
+
class PinResource extends BaseResource {
|
|
588
443
|
async generate() {
|
|
589
444
|
return super.get("/pin/get");
|
|
590
445
|
}
|
|
591
|
-
/**
|
|
592
|
-
* Check the status of a PIN authentication
|
|
593
|
-
*
|
|
594
|
-
* Poll this endpoint to check if the user has authorized the application.
|
|
595
|
-
* Once authorized, the response will include the API key.
|
|
596
|
-
*
|
|
597
|
-
* @param check - Check ID from /pin/get
|
|
598
|
-
* @param pin - PIN code from /pin/get
|
|
599
|
-
*
|
|
600
|
-
* @example
|
|
601
|
-
* ```ts
|
|
602
|
-
* const pinData = await client.pin.generate()
|
|
603
|
-
*
|
|
604
|
-
* // Poll every few seconds until activated
|
|
605
|
-
* const checkStatus = async () => {
|
|
606
|
-
* const result = await client.pin.check(pinData.check, pinData.pin)
|
|
607
|
-
* if (result?.activated && result?.apikey) {
|
|
608
|
-
* console.log('Authorized! API Key:', result.apikey)
|
|
609
|
-
* return result.apikey
|
|
610
|
-
* }
|
|
611
|
-
* // Wait and try again
|
|
612
|
-
* await new Promise(resolve => setTimeout(resolve, 3000))
|
|
613
|
-
* return checkStatus()
|
|
614
|
-
* }
|
|
615
|
-
*
|
|
616
|
-
* const apikey = await checkStatus()
|
|
617
|
-
* ```
|
|
618
|
-
*
|
|
619
|
-
* @returns Authorization status and API key (if activated)
|
|
620
|
-
*/
|
|
621
446
|
async check(check, pin) {
|
|
622
447
|
return super.get("/pin/check", { check, pin });
|
|
623
448
|
}
|
|
624
|
-
/**
|
|
625
|
-
* Helper method to wait for PIN authorization with automatic polling
|
|
626
|
-
*
|
|
627
|
-
* This method handles the polling logic for you, making it easier to
|
|
628
|
-
* implement the PIN authentication flow.
|
|
629
|
-
*
|
|
630
|
-
* @param check - Check ID from /pin/get
|
|
631
|
-
* @param pin - PIN code from /pin/get
|
|
632
|
-
* @param options - Polling options
|
|
633
|
-
* @param options.timeout - Maximum time to wait in milliseconds (default: 600000 = 10 minutes)
|
|
634
|
-
* @param options.interval - Polling interval in milliseconds (default: 3000 = 3 seconds)
|
|
635
|
-
*
|
|
636
|
-
* @example
|
|
637
|
-
* ```ts
|
|
638
|
-
* const pinData = await client.pin.generate()
|
|
639
|
-
* console.log('Visit:', pinData.user_url)
|
|
640
|
-
*
|
|
641
|
-
* try {
|
|
642
|
-
* const apikey = await client.pin.waitForAuth(pinData.check, pinData.pin, {
|
|
643
|
-
* timeout: 600000, // 10 minutes
|
|
644
|
-
* interval: 3000, // Check every 3 seconds
|
|
645
|
-
* })
|
|
646
|
-
* console.log('Authorized! API Key:', apikey)
|
|
647
|
-
* } catch (error) {
|
|
648
|
-
* console.error('Authorization timed out or failed')
|
|
649
|
-
* }
|
|
650
|
-
* ```
|
|
651
|
-
*
|
|
652
|
-
* @returns The API key once authorized
|
|
653
|
-
* @throws Error if timeout is reached or authorization fails
|
|
654
|
-
*/
|
|
655
449
|
async waitForAuth(check, pin, options = {}) {
|
|
656
|
-
const timeout = options.timeout ??
|
|
657
|
-
const interval = options.interval ??
|
|
450
|
+
const timeout = options.timeout ?? 600000;
|
|
451
|
+
const interval = options.interval ?? 3000;
|
|
658
452
|
const startTime = Date.now();
|
|
659
453
|
while (Date.now() - startTime < timeout) {
|
|
660
454
|
const result = await this.check(check, pin);
|
|
@@ -665,281 +459,83 @@ var PinResource = class extends BaseResource {
|
|
|
665
459
|
}
|
|
666
460
|
throw new Error("PIN authorization timeout - user did not authorize within the time limit");
|
|
667
461
|
}
|
|
668
|
-
}
|
|
462
|
+
}
|
|
669
463
|
|
|
670
464
|
// src/resources/user.ts
|
|
671
|
-
|
|
672
|
-
/**
|
|
673
|
-
* Get user profile information including premium status and quotas
|
|
674
|
-
*
|
|
675
|
-
* @example
|
|
676
|
-
* ```ts
|
|
677
|
-
* const data = await client.user.getInfo()
|
|
678
|
-
* console.log(data.user.username, data.user.isPremium)
|
|
679
|
-
* ```
|
|
680
|
-
*/
|
|
465
|
+
class UserResource extends BaseResource {
|
|
681
466
|
async getInfo() {
|
|
682
467
|
return this.get("/user");
|
|
683
468
|
}
|
|
684
|
-
/**
|
|
685
|
-
* Get available hosts for the current user based on their subscription
|
|
686
|
-
*
|
|
687
|
-
* @param hostOnly - If true, only return hosts data (exclude streams and redirectors)
|
|
688
|
-
*
|
|
689
|
-
* @example
|
|
690
|
-
* ```ts
|
|
691
|
-
* const hosts = await client.user.getHosts()
|
|
692
|
-
* console.log(Object.keys(hosts.hosts))
|
|
693
|
-
* ```
|
|
694
|
-
*/
|
|
695
469
|
async getHosts(hostOnly) {
|
|
696
|
-
const params = hostOnly ? { hostOnly: "1" } :
|
|
470
|
+
const params = hostOnly ? { hostOnly: "1" } : undefined;
|
|
697
471
|
return this.get("/user/hosts", params);
|
|
698
472
|
}
|
|
699
|
-
/**
|
|
700
|
-
* Clear a specific notification by code
|
|
701
|
-
*
|
|
702
|
-
* @param code - The notification code to clear
|
|
703
|
-
*
|
|
704
|
-
* @example
|
|
705
|
-
* ```ts
|
|
706
|
-
* await client.user.clearNotification('SOME_NOTIF_CODE')
|
|
707
|
-
* ```
|
|
708
|
-
*/
|
|
709
473
|
async clearNotification(code) {
|
|
710
474
|
await this.post("/user/notification/clear", { code });
|
|
711
475
|
}
|
|
712
|
-
// ============================================
|
|
713
|
-
// Saved Links Management
|
|
714
|
-
// ============================================
|
|
715
|
-
/**
|
|
716
|
-
* Get all saved links
|
|
717
|
-
*
|
|
718
|
-
* @example
|
|
719
|
-
* ```ts
|
|
720
|
-
* const savedLinks = await client.user.getLinks()
|
|
721
|
-
* console.log(savedLinks.links)
|
|
722
|
-
* ```
|
|
723
|
-
*/
|
|
724
476
|
async getLinks() {
|
|
725
477
|
return this.get("/user/links");
|
|
726
478
|
}
|
|
727
|
-
/**
|
|
728
|
-
* Save one or multiple links for later use
|
|
729
|
-
*
|
|
730
|
-
* Supports batch operations - you can save multiple links in a single request.
|
|
731
|
-
*
|
|
732
|
-
* @param links - Single link or array of links to save
|
|
733
|
-
*
|
|
734
|
-
* @example
|
|
735
|
-
* ```ts
|
|
736
|
-
* // Save single link
|
|
737
|
-
* await client.user.saveLink('https://example.com/file.zip')
|
|
738
|
-
*
|
|
739
|
-
* // Save multiple links at once
|
|
740
|
-
* await client.user.saveLink([
|
|
741
|
-
* 'https://example.com/file1.zip',
|
|
742
|
-
* 'https://example.com/file2.zip',
|
|
743
|
-
* 'https://example.com/file3.zip'
|
|
744
|
-
* ])
|
|
745
|
-
* ```
|
|
746
|
-
*/
|
|
747
479
|
async saveLink(links) {
|
|
748
480
|
const linksArray = Array.isArray(links) ? links : [links];
|
|
749
|
-
const formData = new FormData
|
|
481
|
+
const formData = new FormData;
|
|
750
482
|
for (const link of linksArray) {
|
|
751
483
|
formData.append("links[]", link);
|
|
752
484
|
}
|
|
753
485
|
return this.postFormData("/user/links/save", formData);
|
|
754
486
|
}
|
|
755
|
-
/**
|
|
756
|
-
* Delete one or multiple saved links
|
|
757
|
-
*
|
|
758
|
-
* Supports batch operations - you can delete multiple links in a single request.
|
|
759
|
-
*
|
|
760
|
-
* @param links - Single link or array of links to delete (can be saved link IDs or URLs)
|
|
761
|
-
*
|
|
762
|
-
* @example
|
|
763
|
-
* ```ts
|
|
764
|
-
* // Delete single link
|
|
765
|
-
* await client.user.deleteLink('saved-link-id')
|
|
766
|
-
*
|
|
767
|
-
* // Delete multiple links at once
|
|
768
|
-
* await client.user.deleteLink([
|
|
769
|
-
* 'saved-link-id-1',
|
|
770
|
-
* 'saved-link-id-2',
|
|
771
|
-
* 'saved-link-id-3'
|
|
772
|
-
* ])
|
|
773
|
-
* ```
|
|
774
|
-
*/
|
|
775
487
|
async deleteLink(links) {
|
|
776
488
|
const linksArray = Array.isArray(links) ? links : [links];
|
|
777
|
-
const formData = new FormData
|
|
489
|
+
const formData = new FormData;
|
|
778
490
|
for (const link of linksArray) {
|
|
779
491
|
formData.append("links[]", link);
|
|
780
492
|
}
|
|
781
493
|
return this.postFormData("/user/links/delete", formData);
|
|
782
494
|
}
|
|
783
|
-
// ============================================
|
|
784
|
-
// History Management
|
|
785
|
-
// ============================================
|
|
786
|
-
/**
|
|
787
|
-
* Get user history (if enabled in account settings)
|
|
788
|
-
*
|
|
789
|
-
* @example
|
|
790
|
-
* ```ts
|
|
791
|
-
* const history = await client.user.getHistory()
|
|
792
|
-
* console.log(history.links)
|
|
793
|
-
* ```
|
|
794
|
-
*/
|
|
795
495
|
async getHistory() {
|
|
796
496
|
return this.get("/user/history");
|
|
797
497
|
}
|
|
798
|
-
/**
|
|
799
|
-
* Clear user history
|
|
800
|
-
*
|
|
801
|
-
* @example
|
|
802
|
-
* ```ts
|
|
803
|
-
* await client.user.clearHistory()
|
|
804
|
-
* ```
|
|
805
|
-
*/
|
|
806
498
|
async clearHistory() {
|
|
807
499
|
return this.post("/user/history/delete");
|
|
808
500
|
}
|
|
809
|
-
// ============================================
|
|
810
|
-
// Email Verification
|
|
811
|
-
// ============================================
|
|
812
|
-
/**
|
|
813
|
-
* Check email verification status
|
|
814
|
-
*
|
|
815
|
-
* @param token - Verification token
|
|
816
|
-
*
|
|
817
|
-
* @example
|
|
818
|
-
* ```ts
|
|
819
|
-
* const status = await client.user.getVerificationStatus('verification-token')
|
|
820
|
-
* console.log(status.verif) // 'waiting', 'allowed', or 'denied'
|
|
821
|
-
* ```
|
|
822
|
-
*/
|
|
823
501
|
async getVerificationStatus(token) {
|
|
824
|
-
return this.post("/user/verif",
|
|
502
|
+
return this.post("/user/verif", undefined, { token });
|
|
825
503
|
}
|
|
826
|
-
/**
|
|
827
|
-
* Resend verification email
|
|
828
|
-
*
|
|
829
|
-
* @param token - Verification token
|
|
830
|
-
*
|
|
831
|
-
* @example
|
|
832
|
-
* ```ts
|
|
833
|
-
* await client.user.resendVerification('verification-token')
|
|
834
|
-
* ```
|
|
835
|
-
*/
|
|
836
504
|
async resendVerification(token) {
|
|
837
|
-
return this.post("/user/verif/resend",
|
|
505
|
+
return this.post("/user/verif/resend", undefined, { token });
|
|
838
506
|
}
|
|
839
|
-
}
|
|
507
|
+
}
|
|
840
508
|
|
|
841
509
|
// src/resources/voucher.ts
|
|
842
|
-
|
|
843
|
-
/**
|
|
844
|
-
* Get voucher balance for reseller accounts
|
|
845
|
-
*
|
|
846
|
-
* This endpoint allows resellers to check their remaining voucher balance.
|
|
847
|
-
* Only available for accounts with reseller privileges.
|
|
848
|
-
*
|
|
849
|
-
* @example
|
|
850
|
-
* ```ts
|
|
851
|
-
* const balance = await client.voucher.getBalance()
|
|
852
|
-
* console.log('Remaining balance:', balance.balance, '€')
|
|
853
|
-
* ```
|
|
854
|
-
*
|
|
855
|
-
* @returns Voucher balance information
|
|
856
|
-
*/
|
|
510
|
+
class VoucherResource extends BaseResource {
|
|
857
511
|
async getBalance() {
|
|
858
512
|
return this.get("/voucher/balance");
|
|
859
513
|
}
|
|
860
|
-
/**
|
|
861
|
-
* Retrieve existing vouchers from reseller inventory
|
|
862
|
-
*
|
|
863
|
-
* This endpoint retrieves vouchers that were previously generated
|
|
864
|
-
* and are available in your inventory.
|
|
865
|
-
*
|
|
866
|
-
* @param quantity - Optional number of vouchers to retrieve
|
|
867
|
-
*
|
|
868
|
-
* @example
|
|
869
|
-
* ```ts
|
|
870
|
-
* // Get all available vouchers
|
|
871
|
-
* const allVouchers = await client.voucher.getVouchers()
|
|
872
|
-
* console.log('Vouchers:', allVouchers?.codes)
|
|
873
|
-
*
|
|
874
|
-
* // Get specific quantity
|
|
875
|
-
* const fiveVouchers = await client.voucher.getVouchers(5)
|
|
876
|
-
* ```
|
|
877
|
-
*
|
|
878
|
-
* @returns List of voucher codes
|
|
879
|
-
*/
|
|
880
514
|
async getVouchers(quantity) {
|
|
881
|
-
const params = quantity ? { quantity } :
|
|
515
|
+
const params = quantity ? { quantity } : undefined;
|
|
882
516
|
return this.get("/voucher/get", params);
|
|
883
517
|
}
|
|
884
|
-
/**
|
|
885
|
-
* Generate new vouchers (deducts from reseller balance)
|
|
886
|
-
*
|
|
887
|
-
* This endpoint creates new vouchers and deducts the cost from your
|
|
888
|
-
* reseller account balance.
|
|
889
|
-
*
|
|
890
|
-
* @param quantity - Number of vouchers to generate
|
|
891
|
-
* @param duration - Voucher duration in days
|
|
892
|
-
*
|
|
893
|
-
* @example
|
|
894
|
-
* ```ts
|
|
895
|
-
* // Generate 10 vouchers valid for 30 days
|
|
896
|
-
* const vouchers = await client.voucher.generateVouchers(10, 30)
|
|
897
|
-
* console.log('Generated vouchers:', vouchers?.codes)
|
|
898
|
-
*
|
|
899
|
-
* // Generate 5 vouchers valid for 7 days
|
|
900
|
-
* const weekVouchers = await client.voucher.generateVouchers(5, 7)
|
|
901
|
-
* ```
|
|
902
|
-
*
|
|
903
|
-
* @returns List of newly generated voucher codes
|
|
904
|
-
*/
|
|
905
518
|
async generateVouchers(quantity, duration) {
|
|
906
519
|
return this.post("/voucher/generate", {
|
|
907
520
|
quantity,
|
|
908
521
|
duration
|
|
909
522
|
});
|
|
910
523
|
}
|
|
911
|
-
}
|
|
524
|
+
}
|
|
912
525
|
|
|
913
526
|
// src/client.ts
|
|
914
527
|
var DEFAULT_BASE_URL = "https://api.alldebrid.com/v4.1";
|
|
915
528
|
var DEFAULT_AGENT = "@adbjs/sdk";
|
|
916
|
-
var DEFAULT_TIMEOUT =
|
|
529
|
+
var DEFAULT_TIMEOUT = 30000;
|
|
917
530
|
var DEFAULT_MAX_RETRIES = 3;
|
|
918
|
-
|
|
531
|
+
|
|
532
|
+
class AllDebridClient {
|
|
919
533
|
config;
|
|
920
|
-
/**
|
|
921
|
-
* User resource for managing user account
|
|
922
|
-
*/
|
|
923
534
|
user;
|
|
924
|
-
/**
|
|
925
|
-
* Link resource for unlocking and managing download links
|
|
926
|
-
*/
|
|
927
535
|
link;
|
|
928
|
-
/**
|
|
929
|
-
* Magnet resource for managing torrents
|
|
930
|
-
*/
|
|
931
536
|
magnet;
|
|
932
|
-
/**
|
|
933
|
-
* Host resource for getting information about supported hosts
|
|
934
|
-
*/
|
|
935
537
|
host;
|
|
936
|
-
/**
|
|
937
|
-
* Pin resource for PIN-based authentication
|
|
938
|
-
*/
|
|
939
538
|
pin;
|
|
940
|
-
/**
|
|
941
|
-
* Voucher resource for reseller voucher management
|
|
942
|
-
*/
|
|
943
539
|
voucher;
|
|
944
540
|
constructor(config) {
|
|
945
541
|
this.config = {
|
|
@@ -957,17 +553,14 @@ var AllDebridClient = class {
|
|
|
957
553
|
this.pin = new PinResource(this);
|
|
958
554
|
this.voucher = new VoucherResource(this);
|
|
959
555
|
}
|
|
960
|
-
/**
|
|
961
|
-
* Build query string from params
|
|
962
|
-
*/
|
|
963
556
|
buildUrl(path, params) {
|
|
964
557
|
const allParams = {
|
|
965
558
|
agent: this.config.agent,
|
|
966
559
|
...params
|
|
967
560
|
};
|
|
968
|
-
const query = new URLSearchParams
|
|
561
|
+
const query = new URLSearchParams;
|
|
969
562
|
for (const [key, value] of Object.entries(allParams)) {
|
|
970
|
-
if (value !==
|
|
563
|
+
if (value !== undefined && value !== null) {
|
|
971
564
|
if (Array.isArray(value)) {
|
|
972
565
|
value.forEach((v) => query.append(`${key}[]`, String(v)));
|
|
973
566
|
} else {
|
|
@@ -978,18 +571,10 @@ var AllDebridClient = class {
|
|
|
978
571
|
const queryString = query.toString();
|
|
979
572
|
return queryString ? `${path}?${queryString}` : path;
|
|
980
573
|
}
|
|
981
|
-
/**
|
|
982
|
-
* Make a GET request
|
|
983
|
-
* @template T - The generated response type (e.g., GetLinkUnlockResponse)
|
|
984
|
-
* @param path - API endpoint path
|
|
985
|
-
* @param params - Optional query parameters
|
|
986
|
-
* @returns The extracted data from the response (without the { status, data } wrapper)
|
|
987
|
-
* @internal
|
|
988
|
-
*/
|
|
989
574
|
async get(path, params) {
|
|
990
575
|
try {
|
|
991
576
|
const url = this.buildUrl(path, params);
|
|
992
|
-
const json = await
|
|
577
|
+
const json = await dist_default(this.config.baseUrl).auth(`Bearer ${this.config.apiKey}`).url(url).get().json();
|
|
993
578
|
if (json.status === "error" && json.error) {
|
|
994
579
|
throw createTypedError(json.error.code, json.error.message);
|
|
995
580
|
}
|
|
@@ -1010,22 +595,13 @@ var AllDebridClient = class {
|
|
|
1010
595
|
throw new NetworkError(error.message || "Network error occurred", error.status);
|
|
1011
596
|
}
|
|
1012
597
|
}
|
|
1013
|
-
/**
|
|
1014
|
-
* Make a POST request with application/x-www-form-urlencoded
|
|
1015
|
-
* @template T - The generated response type
|
|
1016
|
-
* @param path - API endpoint path
|
|
1017
|
-
* @param body - Request body (will be converted to URLSearchParams)
|
|
1018
|
-
* @param params - Optional query parameters
|
|
1019
|
-
* @returns The extracted data from the response (without the { status, data } wrapper)
|
|
1020
|
-
* @internal
|
|
1021
|
-
*/
|
|
1022
598
|
async post(path, body, params) {
|
|
1023
599
|
try {
|
|
1024
600
|
const url = this.buildUrl(path, params);
|
|
1025
|
-
const formData = new URLSearchParams
|
|
601
|
+
const formData = new URLSearchParams;
|
|
1026
602
|
if (body && typeof body === "object") {
|
|
1027
603
|
for (const [key, value] of Object.entries(body)) {
|
|
1028
|
-
if (value !==
|
|
604
|
+
if (value !== undefined && value !== null) {
|
|
1029
605
|
if (Array.isArray(value)) {
|
|
1030
606
|
value.forEach((v) => formData.append(key, String(v)));
|
|
1031
607
|
} else {
|
|
@@ -1034,7 +610,7 @@ var AllDebridClient = class {
|
|
|
1034
610
|
}
|
|
1035
611
|
}
|
|
1036
612
|
}
|
|
1037
|
-
const json = await
|
|
613
|
+
const json = await dist_default(this.config.baseUrl).auth(`Bearer ${this.config.apiKey}`).url(url).body(formData).post().json();
|
|
1038
614
|
if (json.status === "error" && json.error) {
|
|
1039
615
|
throw createTypedError(json.error.code, json.error.message);
|
|
1040
616
|
}
|
|
@@ -1055,19 +631,10 @@ var AllDebridClient = class {
|
|
|
1055
631
|
throw new NetworkError(error.message || "Network error occurred", error.status);
|
|
1056
632
|
}
|
|
1057
633
|
}
|
|
1058
|
-
/**
|
|
1059
|
-
* Make a POST request with FormData (multipart/form-data)
|
|
1060
|
-
* @template T - The generated response type
|
|
1061
|
-
* @param path - API endpoint path
|
|
1062
|
-
* @param formData - Form data to send
|
|
1063
|
-
* @param params - Optional query parameters
|
|
1064
|
-
* @returns The extracted data from the response (without the { status, data } wrapper)
|
|
1065
|
-
* @internal
|
|
1066
|
-
*/
|
|
1067
634
|
async postFormData(path, formData, params) {
|
|
1068
635
|
try {
|
|
1069
636
|
const url = this.buildUrl(path, params);
|
|
1070
|
-
const json = await
|
|
637
|
+
const json = await dist_default(this.config.baseUrl).auth(`Bearer ${this.config.apiKey}`).url(url).body(formData).post().json();
|
|
1071
638
|
if (json.status === "error" && json.error) {
|
|
1072
639
|
throw createTypedError(json.error.code, json.error.message);
|
|
1073
640
|
}
|
|
@@ -1088,37 +655,22 @@ var AllDebridClient = class {
|
|
|
1088
655
|
throw new NetworkError(error.message || "Network error occurred", error.status);
|
|
1089
656
|
}
|
|
1090
657
|
}
|
|
1091
|
-
/**
|
|
1092
|
-
* Test the API connection
|
|
1093
|
-
*
|
|
1094
|
-
* This endpoint doesn't require authentication and can be used to verify
|
|
1095
|
-
* that the AllDebrid API is reachable.
|
|
1096
|
-
*
|
|
1097
|
-
* @example
|
|
1098
|
-
* ```ts
|
|
1099
|
-
* const result = await client.ping()
|
|
1100
|
-
* console.log(result.ping) // 'pong'
|
|
1101
|
-
* ```
|
|
1102
|
-
*
|
|
1103
|
-
* @returns Ping response with 'pong' message
|
|
1104
|
-
*/
|
|
1105
658
|
async ping() {
|
|
1106
659
|
return this.get("/ping");
|
|
1107
660
|
}
|
|
661
|
+
}
|
|
662
|
+
export {
|
|
663
|
+
createTypedError,
|
|
664
|
+
VoucherResource,
|
|
665
|
+
UserResource,
|
|
666
|
+
PinResource,
|
|
667
|
+
NetworkError,
|
|
668
|
+
MagnetResource,
|
|
669
|
+
MagnetError,
|
|
670
|
+
LinkResource,
|
|
671
|
+
LinkError,
|
|
672
|
+
HostResource,
|
|
673
|
+
AuthenticationError,
|
|
674
|
+
AllDebridError,
|
|
675
|
+
AllDebridClient
|
|
1108
676
|
};
|
|
1109
|
-
|
|
1110
|
-
exports.AllDebridClient = AllDebridClient;
|
|
1111
|
-
exports.AllDebridError = AllDebridError;
|
|
1112
|
-
exports.AuthenticationError = AuthenticationError;
|
|
1113
|
-
exports.HostResource = HostResource;
|
|
1114
|
-
exports.LinkError = LinkError;
|
|
1115
|
-
exports.LinkResource = LinkResource;
|
|
1116
|
-
exports.MagnetError = MagnetError;
|
|
1117
|
-
exports.MagnetResource = MagnetResource;
|
|
1118
|
-
exports.NetworkError = NetworkError;
|
|
1119
|
-
exports.PinResource = PinResource;
|
|
1120
|
-
exports.UserResource = UserResource;
|
|
1121
|
-
exports.VoucherResource = VoucherResource;
|
|
1122
|
-
exports.createTypedError = createTypedError;
|
|
1123
|
-
//# sourceMappingURL=index.cjs.map
|
|
1124
|
-
//# sourceMappingURL=index.cjs.map
|