tiktok-live-api 1.4.5 → 1.4.7

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.d.mts CHANGED
@@ -326,6 +326,110 @@ declare class TikTokLive {
326
326
  private _maybeReconnect;
327
327
  }
328
328
 
329
+ /**
330
+ * TikTool REST client - typed methods for every customer-facing tik.tools
331
+ * REST endpoint. Pairs with the {@link TikTokLive} WebSocket client.
332
+ *
333
+ * @example
334
+ * ```typescript
335
+ * import { TikTool } from 'tiktok-live-api';
336
+ *
337
+ * const api = new TikTool({ apiKey: 'YOUR_KEY' });
338
+ *
339
+ * const live = await api.isLive('username');
340
+ * const board = await api.leaderboard({ region: 'US+' });
341
+ * const recruits = await api.eligibleCreators({ region: 'US+', limit: 50 });
342
+ * ```
343
+ *
344
+ * Uses the global `fetch` (Node 18+ or any browser).
345
+ */
346
+ interface TikToolOptions {
347
+ apiKey: string;
348
+ /** Override the API base URL. Defaults to https://api.tik.tools */
349
+ baseUrl?: string;
350
+ }
351
+ /** Thrown when an endpoint returns a non-2xx status. `body` holds the parsed error payload. */
352
+ declare class TikToolError extends Error {
353
+ readonly status: number;
354
+ readonly body: unknown;
355
+ constructor(status: number, body: unknown);
356
+ }
357
+ type Query = Record<string, string | number | boolean | undefined | null>;
358
+ interface RequestOpts {
359
+ method?: 'GET' | 'POST';
360
+ query?: Query;
361
+ body?: unknown;
362
+ }
363
+ declare class TikTool {
364
+ private readonly apiKey;
365
+ private readonly baseUrl;
366
+ constructor(options: TikToolOptions);
367
+ /** Low-level request. Use the named methods below; this is exposed for endpoints not yet wrapped. */
368
+ request<T = any>(path: string, opts?: RequestOpts): Promise<T>;
369
+ /**
370
+ * Creator-identifier query params. The API is inconsistent about whether an
371
+ * endpoint reads `unique_id`, `username`, or `uniqueId`, so we send all three;
372
+ * unused ones are ignored server-side.
373
+ */
374
+ private uid;
375
+ signUrl(url: string): Promise<any>;
376
+ signWebsocket(body: Record<string, unknown>): Promise<any>;
377
+ wsCredentials(uniqueId: string): Promise<any>;
378
+ connectionMode(uniqueId: string): Promise<any>;
379
+ checkAlive(uniqueId: string): Promise<any>;
380
+ rateLimits(): Promise<any>;
381
+ wsSessions(): Promise<any>;
382
+ jwt(body?: Record<string, unknown>): Promise<any>;
383
+ isLive(uniqueId: string): Promise<any>;
384
+ liveStatus(uniqueId: string): Promise<any>;
385
+ bulkLiveCheck(usernames: string[]): Promise<any>;
386
+ liveCounts(region?: string): Promise<any>;
387
+ roomId(uniqueId: string): Promise<any>;
388
+ roomInfo(uniqueId: string): Promise<any>;
389
+ roomCover(uniqueId: string): Promise<any>;
390
+ roomVideo(uniqueId: string): Promise<any>;
391
+ rankings(query?: Query): Promise<any>;
392
+ ranklist(query?: Query): Promise<any>;
393
+ ranklistRegional(region: string): Promise<any>;
394
+ ranklistGaming(region: string): Promise<any>;
395
+ gamingMovers(region: string): Promise<any>;
396
+ regionMovers(region: string): Promise<any>;
397
+ leaderboard(query: {
398
+ region: string;
399
+ } & Query): Promise<any>;
400
+ eligibleCreators(query: {
401
+ region?: string;
402
+ page?: number;
403
+ limit?: number;
404
+ min_score?: number;
405
+ } & Query): Promise<any>;
406
+ giftInfo(query?: Query): Promise<any>;
407
+ giftGallery(query?: Query): Promise<any>;
408
+ giftsByCountry(country: string): Promise<any>;
409
+ lookupUsername(uniqueId: string): Promise<any>;
410
+ profileInfo(uniqueId: string): Promise<any>;
411
+ resolveUserIds(usernames: string[]): Promise<any>;
412
+ userProfile(uniqueId: string): Promise<any>;
413
+ userVideos(uniqueId: string, query?: Query): Promise<any>;
414
+ userFollowers(uniqueId: string, query?: Query): Promise<any>;
415
+ userFollowing(uniqueId: string, query?: Query): Promise<any>;
416
+ userLikes(uniqueId: string, query?: Query): Promise<any>;
417
+ userEarnings(uniqueId: string): Promise<any>;
418
+ hashtagList(query?: Query): Promise<any>;
419
+ fetch(body: Record<string, unknown>): Promise<any>;
420
+ feed(query?: Query): Promise<any>;
421
+ chat(uniqueId: string, query?: Query): Promise<any>;
422
+ analyticsVideoList(query?: Query): Promise<any>;
423
+ analyticsVideoDetail(query?: Query): Promise<any>;
424
+ analyticsUserInteractions(query?: Query): Promise<any>;
425
+ moderationMutes(uniqueId: string): Promise<any>;
426
+ moderationBans(uniqueId: string): Promise<any>;
427
+ solvePuzzle(body: Record<string, unknown>): Promise<any>;
428
+ solveRotate(body: Record<string, unknown>): Promise<any>;
429
+ solveShapes(body: Record<string, unknown>): Promise<any>;
430
+ captionsCredits(): Promise<any>;
431
+ }
432
+
329
433
  /**
330
434
  * TikTokCaptions - Real-time AI speech-to-text for TikTok LIVE streams.
331
435
  *
@@ -431,4 +535,4 @@ declare class TikTokCaptions {
431
535
  disconnect(): void;
432
536
  }
433
537
 
434
- export { type BattleEvent, type CaptionEvent, type ChatEvent, type ConnectedEvent, type CreditsEvent, type DisconnectedEvent, type ErrorEvent, type GiftEvent, type LikeEvent, type MemberEvent, type RoomUserSeqEvent, type SocialEvent, TikTokCaptions, type TikTokCaptionsEventMap, type TikTokCaptionsOptions, TikTokLive, type TikTokLiveEventMap, type TikTokLiveOptions, type TikTokUser, type TranslationEvent };
538
+ export { type BattleEvent, type CaptionEvent, type ChatEvent, type ConnectedEvent, type CreditsEvent, type DisconnectedEvent, type ErrorEvent, type GiftEvent, type LikeEvent, type MemberEvent, type RoomUserSeqEvent, type SocialEvent, TikTokCaptions, type TikTokCaptionsEventMap, type TikTokCaptionsOptions, TikTokLive, type TikTokLiveEventMap, type TikTokLiveOptions, type TikTokUser, TikTool, TikToolError, type TikToolOptions, type TranslationEvent };
package/dist/index.d.ts CHANGED
@@ -326,6 +326,110 @@ declare class TikTokLive {
326
326
  private _maybeReconnect;
327
327
  }
328
328
 
329
+ /**
330
+ * TikTool REST client - typed methods for every customer-facing tik.tools
331
+ * REST endpoint. Pairs with the {@link TikTokLive} WebSocket client.
332
+ *
333
+ * @example
334
+ * ```typescript
335
+ * import { TikTool } from 'tiktok-live-api';
336
+ *
337
+ * const api = new TikTool({ apiKey: 'YOUR_KEY' });
338
+ *
339
+ * const live = await api.isLive('username');
340
+ * const board = await api.leaderboard({ region: 'US+' });
341
+ * const recruits = await api.eligibleCreators({ region: 'US+', limit: 50 });
342
+ * ```
343
+ *
344
+ * Uses the global `fetch` (Node 18+ or any browser).
345
+ */
346
+ interface TikToolOptions {
347
+ apiKey: string;
348
+ /** Override the API base URL. Defaults to https://api.tik.tools */
349
+ baseUrl?: string;
350
+ }
351
+ /** Thrown when an endpoint returns a non-2xx status. `body` holds the parsed error payload. */
352
+ declare class TikToolError extends Error {
353
+ readonly status: number;
354
+ readonly body: unknown;
355
+ constructor(status: number, body: unknown);
356
+ }
357
+ type Query = Record<string, string | number | boolean | undefined | null>;
358
+ interface RequestOpts {
359
+ method?: 'GET' | 'POST';
360
+ query?: Query;
361
+ body?: unknown;
362
+ }
363
+ declare class TikTool {
364
+ private readonly apiKey;
365
+ private readonly baseUrl;
366
+ constructor(options: TikToolOptions);
367
+ /** Low-level request. Use the named methods below; this is exposed for endpoints not yet wrapped. */
368
+ request<T = any>(path: string, opts?: RequestOpts): Promise<T>;
369
+ /**
370
+ * Creator-identifier query params. The API is inconsistent about whether an
371
+ * endpoint reads `unique_id`, `username`, or `uniqueId`, so we send all three;
372
+ * unused ones are ignored server-side.
373
+ */
374
+ private uid;
375
+ signUrl(url: string): Promise<any>;
376
+ signWebsocket(body: Record<string, unknown>): Promise<any>;
377
+ wsCredentials(uniqueId: string): Promise<any>;
378
+ connectionMode(uniqueId: string): Promise<any>;
379
+ checkAlive(uniqueId: string): Promise<any>;
380
+ rateLimits(): Promise<any>;
381
+ wsSessions(): Promise<any>;
382
+ jwt(body?: Record<string, unknown>): Promise<any>;
383
+ isLive(uniqueId: string): Promise<any>;
384
+ liveStatus(uniqueId: string): Promise<any>;
385
+ bulkLiveCheck(usernames: string[]): Promise<any>;
386
+ liveCounts(region?: string): Promise<any>;
387
+ roomId(uniqueId: string): Promise<any>;
388
+ roomInfo(uniqueId: string): Promise<any>;
389
+ roomCover(uniqueId: string): Promise<any>;
390
+ roomVideo(uniqueId: string): Promise<any>;
391
+ rankings(query?: Query): Promise<any>;
392
+ ranklist(query?: Query): Promise<any>;
393
+ ranklistRegional(region: string): Promise<any>;
394
+ ranklistGaming(region: string): Promise<any>;
395
+ gamingMovers(region: string): Promise<any>;
396
+ regionMovers(region: string): Promise<any>;
397
+ leaderboard(query: {
398
+ region: string;
399
+ } & Query): Promise<any>;
400
+ eligibleCreators(query: {
401
+ region?: string;
402
+ page?: number;
403
+ limit?: number;
404
+ min_score?: number;
405
+ } & Query): Promise<any>;
406
+ giftInfo(query?: Query): Promise<any>;
407
+ giftGallery(query?: Query): Promise<any>;
408
+ giftsByCountry(country: string): Promise<any>;
409
+ lookupUsername(uniqueId: string): Promise<any>;
410
+ profileInfo(uniqueId: string): Promise<any>;
411
+ resolveUserIds(usernames: string[]): Promise<any>;
412
+ userProfile(uniqueId: string): Promise<any>;
413
+ userVideos(uniqueId: string, query?: Query): Promise<any>;
414
+ userFollowers(uniqueId: string, query?: Query): Promise<any>;
415
+ userFollowing(uniqueId: string, query?: Query): Promise<any>;
416
+ userLikes(uniqueId: string, query?: Query): Promise<any>;
417
+ userEarnings(uniqueId: string): Promise<any>;
418
+ hashtagList(query?: Query): Promise<any>;
419
+ fetch(body: Record<string, unknown>): Promise<any>;
420
+ feed(query?: Query): Promise<any>;
421
+ chat(uniqueId: string, query?: Query): Promise<any>;
422
+ analyticsVideoList(query?: Query): Promise<any>;
423
+ analyticsVideoDetail(query?: Query): Promise<any>;
424
+ analyticsUserInteractions(query?: Query): Promise<any>;
425
+ moderationMutes(uniqueId: string): Promise<any>;
426
+ moderationBans(uniqueId: string): Promise<any>;
427
+ solvePuzzle(body: Record<string, unknown>): Promise<any>;
428
+ solveRotate(body: Record<string, unknown>): Promise<any>;
429
+ solveShapes(body: Record<string, unknown>): Promise<any>;
430
+ captionsCredits(): Promise<any>;
431
+ }
432
+
329
433
  /**
330
434
  * TikTokCaptions - Real-time AI speech-to-text for TikTok LIVE streams.
331
435
  *
@@ -431,4 +535,4 @@ declare class TikTokCaptions {
431
535
  disconnect(): void;
432
536
  }
433
537
 
434
- export { type BattleEvent, type CaptionEvent, type ChatEvent, type ConnectedEvent, type CreditsEvent, type DisconnectedEvent, type ErrorEvent, type GiftEvent, type LikeEvent, type MemberEvent, type RoomUserSeqEvent, type SocialEvent, TikTokCaptions, type TikTokCaptionsEventMap, type TikTokCaptionsOptions, TikTokLive, type TikTokLiveEventMap, type TikTokLiveOptions, type TikTokUser, type TranslationEvent };
538
+ export { type BattleEvent, type CaptionEvent, type ChatEvent, type ConnectedEvent, type CreditsEvent, type DisconnectedEvent, type ErrorEvent, type GiftEvent, type LikeEvent, type MemberEvent, type RoomUserSeqEvent, type SocialEvent, TikTokCaptions, type TikTokCaptionsEventMap, type TikTokCaptionsOptions, TikTokLive, type TikTokLiveEventMap, type TikTokLiveOptions, type TikTokUser, TikTool, TikToolError, type TikToolOptions, type TranslationEvent };
package/dist/index.js CHANGED
@@ -31,7 +31,9 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
33
  TikTokCaptions: () => TikTokCaptions,
34
- TikTokLive: () => TikTokLive
34
+ TikTokLive: () => TikTokLive,
35
+ TikTool: () => TikTool,
36
+ TikToolError: () => TikToolError
35
37
  });
36
38
  module.exports = __toCommonJS(index_exports);
37
39
 
@@ -177,6 +179,216 @@ var TikTokLive = class {
177
179
  }
178
180
  };
179
181
 
182
+ // src/rest.ts
183
+ var REST_BASE = "https://api.tik.tools";
184
+ var TikToolError = class extends Error {
185
+ constructor(status, body) {
186
+ const msg = body && typeof body === "object" && "error" in body ? String(body.error) : `Request failed with status ${status}`;
187
+ super(msg);
188
+ this.name = "TikToolError";
189
+ this.status = status;
190
+ this.body = body;
191
+ }
192
+ };
193
+ var TikTool = class {
194
+ constructor(options) {
195
+ if (!options?.apiKey) throw new Error("TikTool requires an apiKey");
196
+ this.apiKey = options.apiKey;
197
+ this.baseUrl = (options.baseUrl ?? REST_BASE).replace(/\/$/, "");
198
+ }
199
+ /** Low-level request. Use the named methods below; this is exposed for endpoints not yet wrapped. */
200
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- API boundary
201
+ async request(path, opts = {}) {
202
+ const url = new URL(this.baseUrl + path);
203
+ if (opts.query) {
204
+ for (const [k, v] of Object.entries(opts.query)) {
205
+ if (v !== void 0 && v !== null) url.searchParams.set(k, String(v));
206
+ }
207
+ }
208
+ const headers = { "x-api-key": this.apiKey };
209
+ if (opts.body !== void 0) headers["content-type"] = "application/json";
210
+ const res = await fetch(url.toString(), {
211
+ method: opts.method ?? "GET",
212
+ headers,
213
+ body: opts.body !== void 0 ? JSON.stringify(opts.body) : void 0
214
+ });
215
+ const text = await res.text();
216
+ let data;
217
+ try {
218
+ data = text ? JSON.parse(text) : null;
219
+ } catch {
220
+ data = text;
221
+ }
222
+ if (!res.ok) throw new TikToolError(res.status, data);
223
+ return data;
224
+ }
225
+ /**
226
+ * Creator-identifier query params. The API is inconsistent about whether an
227
+ * endpoint reads `unique_id`, `username`, or `uniqueId`, so we send all three;
228
+ * unused ones are ignored server-side.
229
+ */
230
+ uid(uniqueId) {
231
+ return { unique_id: uniqueId, username: uniqueId, uniqueId };
232
+ }
233
+ // --- Signing / connection ---
234
+ signUrl(url) {
235
+ return this.request("/webcast/sign_url", { method: "POST", body: { url } });
236
+ }
237
+ signWebsocket(body) {
238
+ return this.request("/webcast/sign_websocket", { method: "POST", body });
239
+ }
240
+ wsCredentials(uniqueId) {
241
+ return this.request("/webcast/ws_credentials", { query: this.uid(uniqueId) });
242
+ }
243
+ connectionMode(uniqueId) {
244
+ return this.request("/webcast/connection_mode", { query: this.uid(uniqueId) });
245
+ }
246
+ checkAlive(uniqueId) {
247
+ return this.request("/webcast/check_alive", { query: this.uid(uniqueId) });
248
+ }
249
+ rateLimits() {
250
+ return this.request("/webcast/rate_limits");
251
+ }
252
+ wsSessions() {
253
+ return this.request("/webcast/ws_sessions");
254
+ }
255
+ jwt(body) {
256
+ return this.request("/authentication/jwt", { method: "POST", body: body ?? {} });
257
+ }
258
+ // --- Live status ---
259
+ isLive(uniqueId) {
260
+ return this.request("/webcast/is_live", { query: this.uid(uniqueId) });
261
+ }
262
+ liveStatus(uniqueId) {
263
+ return this.request("/webcast/live_status", { query: this.uid(uniqueId) });
264
+ }
265
+ bulkLiveCheck(usernames) {
266
+ return this.request("/webcast/bulk_live_check", { method: "POST", body: { usernames } });
267
+ }
268
+ liveCounts(region) {
269
+ return this.request("/webcast/live_counts", { query: { region } });
270
+ }
271
+ roomId(uniqueId) {
272
+ return this.request("/webcast/room_id", { query: this.uid(uniqueId) });
273
+ }
274
+ roomInfo(uniqueId) {
275
+ return this.request("/webcast/room_info", { query: this.uid(uniqueId) });
276
+ }
277
+ roomCover(uniqueId) {
278
+ return this.request("/webcast/room_cover", { query: this.uid(uniqueId) });
279
+ }
280
+ roomVideo(uniqueId) {
281
+ return this.request("/webcast/room_video", { query: this.uid(uniqueId) });
282
+ }
283
+ // --- Rankings / leaderboards ---
284
+ rankings(query) {
285
+ return this.request("/webcast/rankings", { query });
286
+ }
287
+ ranklist(query) {
288
+ return this.request("/webcast/ranklist", { query });
289
+ }
290
+ ranklistRegional(region) {
291
+ return this.request("/webcast/ranklist/regional", { query: { region } });
292
+ }
293
+ ranklistGaming(region) {
294
+ return this.request("/webcast/ranklist/gaming", { query: { region } });
295
+ }
296
+ gamingMovers(region) {
297
+ return this.request("/webcast/ranklist/gaming_movers", { query: { region } });
298
+ }
299
+ regionMovers(region) {
300
+ return this.request("/webcast/ranklist/region_movers", { query: { region } });
301
+ }
302
+ leaderboard(query) {
303
+ return this.request("/webcast/leaderboard", { query });
304
+ }
305
+ eligibleCreators(query) {
306
+ return this.request("/webcast/eligible_creators", { query });
307
+ }
308
+ // --- Gifts ---
309
+ giftInfo(query) {
310
+ return this.request("/webcast/gift_info", { query });
311
+ }
312
+ giftGallery(query) {
313
+ return this.request("/webcast/gift_gallery", { query });
314
+ }
315
+ giftsByCountry(country) {
316
+ return this.request("/webcast/gifts_by_country", { query: { country } });
317
+ }
318
+ // --- User / profile ---
319
+ lookupUsername(uniqueId) {
320
+ return this.request("/webcast/lookup_username", { query: this.uid(uniqueId) });
321
+ }
322
+ profileInfo(uniqueId) {
323
+ return this.request("/webcast/profile_info", { query: this.uid(uniqueId) });
324
+ }
325
+ resolveUserIds(usernames) {
326
+ return this.request("/webcast/resolve_user_ids", { method: "POST", body: { usernames } });
327
+ }
328
+ userProfile(uniqueId) {
329
+ return this.request("/webcast/user_profile", { query: this.uid(uniqueId) });
330
+ }
331
+ userVideos(uniqueId, query) {
332
+ return this.request("/webcast/user_videos", { query: { ...this.uid(uniqueId), ...query } });
333
+ }
334
+ userFollowers(uniqueId, query) {
335
+ return this.request("/webcast/user_followers", { query: { ...this.uid(uniqueId), ...query } });
336
+ }
337
+ userFollowing(uniqueId, query) {
338
+ return this.request("/webcast/user_following", { query: { ...this.uid(uniqueId), ...query } });
339
+ }
340
+ userLikes(uniqueId, query) {
341
+ return this.request("/webcast/user_likes", { query: { ...this.uid(uniqueId), ...query } });
342
+ }
343
+ userEarnings(uniqueId) {
344
+ return this.request("/webcast/user_earnings", { query: this.uid(uniqueId) });
345
+ }
346
+ // --- Content / feed ---
347
+ hashtagList(query) {
348
+ return this.request("/webcast/hashtag_list", { query });
349
+ }
350
+ fetch(body) {
351
+ return this.request("/webcast/fetch", { method: "POST", body });
352
+ }
353
+ feed(query) {
354
+ return this.request("/webcast/feed", { query });
355
+ }
356
+ chat(uniqueId, query) {
357
+ return this.request("/webcast/chat", { query: { ...this.uid(uniqueId), ...query } });
358
+ }
359
+ // --- Live analytics ---
360
+ analyticsVideoList(query) {
361
+ return this.request("/webcast/live_analytics/video_list", { query });
362
+ }
363
+ analyticsVideoDetail(query) {
364
+ return this.request("/webcast/live_analytics/video_detail", { query });
365
+ }
366
+ analyticsUserInteractions(query) {
367
+ return this.request("/webcast/live_analytics/user_interactions", { query });
368
+ }
369
+ // --- Moderation ---
370
+ moderationMutes(uniqueId) {
371
+ return this.request("/webcast/moderation/mutes", { query: this.uid(uniqueId) });
372
+ }
373
+ moderationBans(uniqueId) {
374
+ return this.request("/webcast/moderation/bans", { query: this.uid(uniqueId) });
375
+ }
376
+ // --- CAPTCHA solver (Pro+) ---
377
+ solvePuzzle(body) {
378
+ return this.request("/captcha/solve/puzzle", { method: "POST", body });
379
+ }
380
+ solveRotate(body) {
381
+ return this.request("/captcha/solve/rotate", { method: "POST", body });
382
+ }
383
+ solveShapes(body) {
384
+ return this.request("/captcha/solve/shapes", { method: "POST", body });
385
+ }
386
+ // --- Captions ---
387
+ captionsCredits() {
388
+ return this.request("/captions/credits");
389
+ }
390
+ };
391
+
180
392
  // src/captions.ts
181
393
  var import_ws2 = __toESM(require("ws"));
182
394
  var CAPTIONS_BASE = "wss://api.tik.tools/captions";
@@ -287,5 +499,7 @@ var TikTokCaptions = class {
287
499
  // Annotate the CommonJS export names for ESM import in node:
288
500
  0 && (module.exports = {
289
501
  TikTokCaptions,
290
- TikTokLive
502
+ TikTokLive,
503
+ TikTool,
504
+ TikToolError
291
505
  });
package/dist/index.mjs CHANGED
@@ -140,6 +140,216 @@ var TikTokLive = class {
140
140
  }
141
141
  };
142
142
 
143
+ // src/rest.ts
144
+ var REST_BASE = "https://api.tik.tools";
145
+ var TikToolError = class extends Error {
146
+ constructor(status, body) {
147
+ const msg = body && typeof body === "object" && "error" in body ? String(body.error) : `Request failed with status ${status}`;
148
+ super(msg);
149
+ this.name = "TikToolError";
150
+ this.status = status;
151
+ this.body = body;
152
+ }
153
+ };
154
+ var TikTool = class {
155
+ constructor(options) {
156
+ if (!options?.apiKey) throw new Error("TikTool requires an apiKey");
157
+ this.apiKey = options.apiKey;
158
+ this.baseUrl = (options.baseUrl ?? REST_BASE).replace(/\/$/, "");
159
+ }
160
+ /** Low-level request. Use the named methods below; this is exposed for endpoints not yet wrapped. */
161
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- API boundary
162
+ async request(path, opts = {}) {
163
+ const url = new URL(this.baseUrl + path);
164
+ if (opts.query) {
165
+ for (const [k, v] of Object.entries(opts.query)) {
166
+ if (v !== void 0 && v !== null) url.searchParams.set(k, String(v));
167
+ }
168
+ }
169
+ const headers = { "x-api-key": this.apiKey };
170
+ if (opts.body !== void 0) headers["content-type"] = "application/json";
171
+ const res = await fetch(url.toString(), {
172
+ method: opts.method ?? "GET",
173
+ headers,
174
+ body: opts.body !== void 0 ? JSON.stringify(opts.body) : void 0
175
+ });
176
+ const text = await res.text();
177
+ let data;
178
+ try {
179
+ data = text ? JSON.parse(text) : null;
180
+ } catch {
181
+ data = text;
182
+ }
183
+ if (!res.ok) throw new TikToolError(res.status, data);
184
+ return data;
185
+ }
186
+ /**
187
+ * Creator-identifier query params. The API is inconsistent about whether an
188
+ * endpoint reads `unique_id`, `username`, or `uniqueId`, so we send all three;
189
+ * unused ones are ignored server-side.
190
+ */
191
+ uid(uniqueId) {
192
+ return { unique_id: uniqueId, username: uniqueId, uniqueId };
193
+ }
194
+ // --- Signing / connection ---
195
+ signUrl(url) {
196
+ return this.request("/webcast/sign_url", { method: "POST", body: { url } });
197
+ }
198
+ signWebsocket(body) {
199
+ return this.request("/webcast/sign_websocket", { method: "POST", body });
200
+ }
201
+ wsCredentials(uniqueId) {
202
+ return this.request("/webcast/ws_credentials", { query: this.uid(uniqueId) });
203
+ }
204
+ connectionMode(uniqueId) {
205
+ return this.request("/webcast/connection_mode", { query: this.uid(uniqueId) });
206
+ }
207
+ checkAlive(uniqueId) {
208
+ return this.request("/webcast/check_alive", { query: this.uid(uniqueId) });
209
+ }
210
+ rateLimits() {
211
+ return this.request("/webcast/rate_limits");
212
+ }
213
+ wsSessions() {
214
+ return this.request("/webcast/ws_sessions");
215
+ }
216
+ jwt(body) {
217
+ return this.request("/authentication/jwt", { method: "POST", body: body ?? {} });
218
+ }
219
+ // --- Live status ---
220
+ isLive(uniqueId) {
221
+ return this.request("/webcast/is_live", { query: this.uid(uniqueId) });
222
+ }
223
+ liveStatus(uniqueId) {
224
+ return this.request("/webcast/live_status", { query: this.uid(uniqueId) });
225
+ }
226
+ bulkLiveCheck(usernames) {
227
+ return this.request("/webcast/bulk_live_check", { method: "POST", body: { usernames } });
228
+ }
229
+ liveCounts(region) {
230
+ return this.request("/webcast/live_counts", { query: { region } });
231
+ }
232
+ roomId(uniqueId) {
233
+ return this.request("/webcast/room_id", { query: this.uid(uniqueId) });
234
+ }
235
+ roomInfo(uniqueId) {
236
+ return this.request("/webcast/room_info", { query: this.uid(uniqueId) });
237
+ }
238
+ roomCover(uniqueId) {
239
+ return this.request("/webcast/room_cover", { query: this.uid(uniqueId) });
240
+ }
241
+ roomVideo(uniqueId) {
242
+ return this.request("/webcast/room_video", { query: this.uid(uniqueId) });
243
+ }
244
+ // --- Rankings / leaderboards ---
245
+ rankings(query) {
246
+ return this.request("/webcast/rankings", { query });
247
+ }
248
+ ranklist(query) {
249
+ return this.request("/webcast/ranklist", { query });
250
+ }
251
+ ranklistRegional(region) {
252
+ return this.request("/webcast/ranklist/regional", { query: { region } });
253
+ }
254
+ ranklistGaming(region) {
255
+ return this.request("/webcast/ranklist/gaming", { query: { region } });
256
+ }
257
+ gamingMovers(region) {
258
+ return this.request("/webcast/ranklist/gaming_movers", { query: { region } });
259
+ }
260
+ regionMovers(region) {
261
+ return this.request("/webcast/ranklist/region_movers", { query: { region } });
262
+ }
263
+ leaderboard(query) {
264
+ return this.request("/webcast/leaderboard", { query });
265
+ }
266
+ eligibleCreators(query) {
267
+ return this.request("/webcast/eligible_creators", { query });
268
+ }
269
+ // --- Gifts ---
270
+ giftInfo(query) {
271
+ return this.request("/webcast/gift_info", { query });
272
+ }
273
+ giftGallery(query) {
274
+ return this.request("/webcast/gift_gallery", { query });
275
+ }
276
+ giftsByCountry(country) {
277
+ return this.request("/webcast/gifts_by_country", { query: { country } });
278
+ }
279
+ // --- User / profile ---
280
+ lookupUsername(uniqueId) {
281
+ return this.request("/webcast/lookup_username", { query: this.uid(uniqueId) });
282
+ }
283
+ profileInfo(uniqueId) {
284
+ return this.request("/webcast/profile_info", { query: this.uid(uniqueId) });
285
+ }
286
+ resolveUserIds(usernames) {
287
+ return this.request("/webcast/resolve_user_ids", { method: "POST", body: { usernames } });
288
+ }
289
+ userProfile(uniqueId) {
290
+ return this.request("/webcast/user_profile", { query: this.uid(uniqueId) });
291
+ }
292
+ userVideos(uniqueId, query) {
293
+ return this.request("/webcast/user_videos", { query: { ...this.uid(uniqueId), ...query } });
294
+ }
295
+ userFollowers(uniqueId, query) {
296
+ return this.request("/webcast/user_followers", { query: { ...this.uid(uniqueId), ...query } });
297
+ }
298
+ userFollowing(uniqueId, query) {
299
+ return this.request("/webcast/user_following", { query: { ...this.uid(uniqueId), ...query } });
300
+ }
301
+ userLikes(uniqueId, query) {
302
+ return this.request("/webcast/user_likes", { query: { ...this.uid(uniqueId), ...query } });
303
+ }
304
+ userEarnings(uniqueId) {
305
+ return this.request("/webcast/user_earnings", { query: this.uid(uniqueId) });
306
+ }
307
+ // --- Content / feed ---
308
+ hashtagList(query) {
309
+ return this.request("/webcast/hashtag_list", { query });
310
+ }
311
+ fetch(body) {
312
+ return this.request("/webcast/fetch", { method: "POST", body });
313
+ }
314
+ feed(query) {
315
+ return this.request("/webcast/feed", { query });
316
+ }
317
+ chat(uniqueId, query) {
318
+ return this.request("/webcast/chat", { query: { ...this.uid(uniqueId), ...query } });
319
+ }
320
+ // --- Live analytics ---
321
+ analyticsVideoList(query) {
322
+ return this.request("/webcast/live_analytics/video_list", { query });
323
+ }
324
+ analyticsVideoDetail(query) {
325
+ return this.request("/webcast/live_analytics/video_detail", { query });
326
+ }
327
+ analyticsUserInteractions(query) {
328
+ return this.request("/webcast/live_analytics/user_interactions", { query });
329
+ }
330
+ // --- Moderation ---
331
+ moderationMutes(uniqueId) {
332
+ return this.request("/webcast/moderation/mutes", { query: this.uid(uniqueId) });
333
+ }
334
+ moderationBans(uniqueId) {
335
+ return this.request("/webcast/moderation/bans", { query: this.uid(uniqueId) });
336
+ }
337
+ // --- CAPTCHA solver (Pro+) ---
338
+ solvePuzzle(body) {
339
+ return this.request("/captcha/solve/puzzle", { method: "POST", body });
340
+ }
341
+ solveRotate(body) {
342
+ return this.request("/captcha/solve/rotate", { method: "POST", body });
343
+ }
344
+ solveShapes(body) {
345
+ return this.request("/captcha/solve/shapes", { method: "POST", body });
346
+ }
347
+ // --- Captions ---
348
+ captionsCredits() {
349
+ return this.request("/captions/credits");
350
+ }
351
+ };
352
+
143
353
  // src/captions.ts
144
354
  import WebSocket2 from "ws";
145
355
  var CAPTIONS_BASE = "wss://api.tik.tools/captions";
@@ -249,5 +459,7 @@ var TikTokCaptions = class {
249
459
  };
250
460
  export {
251
461
  TikTokCaptions,
252
- TikTokLive
462
+ TikTokLive,
463
+ TikTool,
464
+ TikToolError
253
465
  };