@tiktool/live 2.3.4 → 2.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -215,6 +215,58 @@ const tikTokData = await fetchSignedUrl(apiResponse);
215
215
 
216
216
  ---
217
217
 
218
+ ## 🧩 CAPTCHA Solver (Ultra)
219
+
220
+ Solve TikTok CAPTCHAs programmatically. Requires an **Ultra** tier API key.
221
+
222
+ ### `solvePuzzle(apiKey, puzzleB64, pieceB64, serverUrl?)` — Puzzle Slider
223
+
224
+ ```typescript
225
+ import { solvePuzzle } from '@tiktool/live';
226
+
227
+ const result = await solvePuzzle('YOUR_API_KEY', backgroundBase64, pieceBase64);
228
+ console.log(`Slide to X=${result.slideX}px (confidence: ${result.confidence})`);
229
+ ```
230
+
231
+ | Field | Type | Description |
232
+ |-------|------|-------------|
233
+ | `slideX` | `number` | Pixel X position for the slider |
234
+ | `confidence` | `number` | Confidence score (0.0–1.0) |
235
+ | `solveTimeMs` | `number` | Time taken to solve in ms |
236
+
237
+ ### `solveRotate(apiKey, outerB64, innerB64, serverUrl?)` — Rotate Whirl
238
+
239
+ ```typescript
240
+ import { solveRotate } from '@tiktool/live';
241
+
242
+ const result = await solveRotate('YOUR_API_KEY', outerBase64, innerBase64);
243
+ console.log(`Rotate ${result.angle}° (confidence: ${result.confidence})`);
244
+ ```
245
+
246
+ | Field | Type | Description |
247
+ |-------|------|-------------|
248
+ | `angle` | `number` | Rotation angle in degrees (0–360) |
249
+ | `confidence` | `number` | Confidence score (0.0–1.0) |
250
+ | `solveTimeMs` | `number` | Time taken to solve in ms |
251
+
252
+ ### `solveShapes(apiKey, imageB64, serverUrl?)` — 3D Shape Matching
253
+
254
+ ```typescript
255
+ import { solveShapes } from '@tiktool/live';
256
+
257
+ const result = await solveShapes('YOUR_API_KEY', imageBase64);
258
+ console.log(`Match: (${result.point1.x},${result.point1.y}) ↔ (${result.point2.x},${result.point2.y})`);
259
+ ```
260
+
261
+ | Field | Type | Description |
262
+ |-------|------|-------------|
263
+ | `point1` | `{x, y}` | First matching shape center |
264
+ | `point2` | `{x, y}` | Second matching shape center |
265
+ | `confidence` | `number` | Confidence score (0.0–1.0) |
266
+ | `solveTimeMs` | `number` | Time taken to solve in ms |
267
+
268
+ ---
269
+
218
270
  ## 🌐 REST API Endpoints
219
271
 
220
272
  The sign server at `api.tik.tools` exposes a full REST API alongside WebSocket signing. Endpoints use a **sign-and-return** pattern — when called with a `unique_id`, they return instructions for resolving the room ID; when called with a `room_id`, they return a signed URL to fetch data directly from TikTok. Use `callApi()` to handle this automatically.
@@ -241,6 +293,9 @@ The sign server at `api.tik.tools` exposes a full REST API alongside WebSocket s
241
293
  | `GET /webcast/live_analytics/*` | Video list, video detail, user interactions |
242
294
  | `GET /webcast/moderation/*` | Mute and ban management |
243
295
  | `POST /authentication/jwt` | Generate scoped JWT for frontend WebSocket access |
296
+ | `POST /captcha/solve/puzzle` | Solve puzzle slider CAPTCHA (**Ultra**) |
297
+ | `POST /captcha/solve/rotate` | Solve rotate whirl CAPTCHA (**Ultra**) |
298
+ | `POST /captcha/solve/shapes` | Solve 3D shape matching CAPTCHA (**Ultra**) |
244
299
 
245
300
  Full API documentation: **[tik.tools/docs](https://tik.tools/docs)**
246
301
 
@@ -258,6 +313,7 @@ All plans include signatures and full WebSocket support. Higher tiers unlock all
258
313
  | **Daily Requests** | 2,500 | 50,000 | 250,000 |
259
314
  | **WebSocket Connections** | 1 | 50 | 500 |
260
315
  | **Endpoints** | Basic | All | All |
316
+ | **CAPTCHA Solver** | — | — | ✓ |
261
317
  | **Priority Routing** | — | ✓ | ✓ |
262
318
  | **Overage** | — | $0.001/req | $0.0005/req |
263
319
  | **Support** | Community | Email | Dedicated |
package/dist/index.d.mts CHANGED
@@ -175,6 +175,37 @@ interface TikTokLiveOptions {
175
175
  debug?: boolean;
176
176
  webSocketImpl?: any;
177
177
  }
178
+ /** Result from solving a puzzle (slider) CAPTCHA */
179
+ interface PuzzleSolveResult {
180
+ /** X position as proportion (0.0–1.0) of background width */
181
+ slide_x_proportion: number;
182
+ /** Absolute pixel X offset */
183
+ slide_x_px: number;
184
+ /** Confidence score (0.0–1.0) */
185
+ confidence: number;
186
+ }
187
+ /** Result from solving a rotate (whirl) CAPTCHA */
188
+ interface RotateSolveResult {
189
+ /** Rotation angle in degrees (0–360) */
190
+ angle: number;
191
+ /** Confidence score (0.0–1.0) */
192
+ confidence: number;
193
+ }
194
+ /** Result from solving a shapes (3D matching) CAPTCHA */
195
+ interface ShapesSolveResult {
196
+ /** First matching shape center */
197
+ point1: {
198
+ x: number;
199
+ y: number;
200
+ };
201
+ /** Second matching shape center */
202
+ point2: {
203
+ x: number;
204
+ y: number;
205
+ };
206
+ /** Confidence score (0.0–1.0) */
207
+ confidence: number;
208
+ }
178
209
 
179
210
  type Listener = (...args: any[]) => void;
180
211
  declare class TypedEmitter {
@@ -286,4 +317,34 @@ interface CallApiOptions {
286
317
  */
287
318
  declare function callApi(opts: CallApiOptions): Promise<any>;
288
319
 
289
- export { type BaseEvent, type BattleArmiesEvent, type BattleEvent, type BattleTeam, type BattleTeamUser, type CallApiOptions, type ChatEvent, type ControlEvent, type EmoteChatEvent, type EnvelopeEvent, type GiftEvent, type LikeEvent, type LinkMicEvent, type LiveEvent, type LiveIntroEvent, type LivePageInfo, type MemberEvent, type QuestionEvent, type RankUpdateEvent, type RoomEvent, type RoomInfo, type RoomUserSeqEvent, type SignedUrlResponse, type SocialEvent, type SubscribeEvent, TikTokLive, type TikTokLiveEvents, type TikTokLiveOptions, type TikTokUser, type UnknownEvent, callApi, fetchSignedUrl, resolveLivePage, resolveRoomId };
320
+ /**
321
+ * Solve a puzzle (slider) CAPTCHA using the TikTool solver.
322
+ *
323
+ * @param apiKey - API key for authentication
324
+ * @param puzzleB64 - Base64-encoded background image (PNG/JPEG)
325
+ * @param pieceB64 - Base64-encoded puzzle piece image (PNG/JPEG)
326
+ * @param serverUrl - Custom server URL (default: https://api.tik.tools)
327
+ * @returns Solve result with slide position and confidence
328
+ */
329
+ declare function solvePuzzle(apiKey: string, puzzleB64: string, pieceB64: string, serverUrl?: string): Promise<PuzzleSolveResult>;
330
+ /**
331
+ * Solve a rotate (whirl) CAPTCHA using the TikTool solver.
332
+ *
333
+ * @param apiKey - API key for authentication
334
+ * @param outerB64 - Base64-encoded outer ring image (PNG/JPEG)
335
+ * @param innerB64 - Base64-encoded inner rotated image (PNG/JPEG)
336
+ * @param serverUrl - Custom server URL (default: https://api.tik.tools)
337
+ * @returns Solve result with rotation angle and confidence
338
+ */
339
+ declare function solveRotate(apiKey: string, outerB64: string, innerB64: string, serverUrl?: string): Promise<RotateSolveResult>;
340
+ /**
341
+ * Solve a shapes (3D matching) CAPTCHA using the TikTool solver.
342
+ *
343
+ * @param apiKey - API key for authentication
344
+ * @param imageB64 - Base64-encoded CAPTCHA image with shape grid (PNG/JPEG)
345
+ * @param serverUrl - Custom server URL (default: https://api.tik.tools)
346
+ * @returns Solve result with two matching shape coordinates and confidence
347
+ */
348
+ declare function solveShapes(apiKey: string, imageB64: string, serverUrl?: string): Promise<ShapesSolveResult>;
349
+
350
+ export { type BaseEvent, type BattleArmiesEvent, type BattleEvent, type BattleTeam, type BattleTeamUser, type CallApiOptions, type ChatEvent, type ControlEvent, type EmoteChatEvent, type EnvelopeEvent, type GiftEvent, type LikeEvent, type LinkMicEvent, type LiveEvent, type LiveIntroEvent, type LivePageInfo, type MemberEvent, type PuzzleSolveResult, type QuestionEvent, type RankUpdateEvent, type RoomEvent, type RoomInfo, type RoomUserSeqEvent, type RotateSolveResult, type ShapesSolveResult, type SignedUrlResponse, type SocialEvent, type SubscribeEvent, TikTokLive, type TikTokLiveEvents, type TikTokLiveOptions, type TikTokUser, type UnknownEvent, callApi, fetchSignedUrl, resolveLivePage, resolveRoomId, solvePuzzle, solveRotate, solveShapes };
package/dist/index.d.ts CHANGED
@@ -175,6 +175,37 @@ interface TikTokLiveOptions {
175
175
  debug?: boolean;
176
176
  webSocketImpl?: any;
177
177
  }
178
+ /** Result from solving a puzzle (slider) CAPTCHA */
179
+ interface PuzzleSolveResult {
180
+ /** X position as proportion (0.0–1.0) of background width */
181
+ slide_x_proportion: number;
182
+ /** Absolute pixel X offset */
183
+ slide_x_px: number;
184
+ /** Confidence score (0.0–1.0) */
185
+ confidence: number;
186
+ }
187
+ /** Result from solving a rotate (whirl) CAPTCHA */
188
+ interface RotateSolveResult {
189
+ /** Rotation angle in degrees (0–360) */
190
+ angle: number;
191
+ /** Confidence score (0.0–1.0) */
192
+ confidence: number;
193
+ }
194
+ /** Result from solving a shapes (3D matching) CAPTCHA */
195
+ interface ShapesSolveResult {
196
+ /** First matching shape center */
197
+ point1: {
198
+ x: number;
199
+ y: number;
200
+ };
201
+ /** Second matching shape center */
202
+ point2: {
203
+ x: number;
204
+ y: number;
205
+ };
206
+ /** Confidence score (0.0–1.0) */
207
+ confidence: number;
208
+ }
178
209
 
179
210
  type Listener = (...args: any[]) => void;
180
211
  declare class TypedEmitter {
@@ -286,4 +317,34 @@ interface CallApiOptions {
286
317
  */
287
318
  declare function callApi(opts: CallApiOptions): Promise<any>;
288
319
 
289
- export { type BaseEvent, type BattleArmiesEvent, type BattleEvent, type BattleTeam, type BattleTeamUser, type CallApiOptions, type ChatEvent, type ControlEvent, type EmoteChatEvent, type EnvelopeEvent, type GiftEvent, type LikeEvent, type LinkMicEvent, type LiveEvent, type LiveIntroEvent, type LivePageInfo, type MemberEvent, type QuestionEvent, type RankUpdateEvent, type RoomEvent, type RoomInfo, type RoomUserSeqEvent, type SignedUrlResponse, type SocialEvent, type SubscribeEvent, TikTokLive, type TikTokLiveEvents, type TikTokLiveOptions, type TikTokUser, type UnknownEvent, callApi, fetchSignedUrl, resolveLivePage, resolveRoomId };
320
+ /**
321
+ * Solve a puzzle (slider) CAPTCHA using the TikTool solver.
322
+ *
323
+ * @param apiKey - API key for authentication
324
+ * @param puzzleB64 - Base64-encoded background image (PNG/JPEG)
325
+ * @param pieceB64 - Base64-encoded puzzle piece image (PNG/JPEG)
326
+ * @param serverUrl - Custom server URL (default: https://api.tik.tools)
327
+ * @returns Solve result with slide position and confidence
328
+ */
329
+ declare function solvePuzzle(apiKey: string, puzzleB64: string, pieceB64: string, serverUrl?: string): Promise<PuzzleSolveResult>;
330
+ /**
331
+ * Solve a rotate (whirl) CAPTCHA using the TikTool solver.
332
+ *
333
+ * @param apiKey - API key for authentication
334
+ * @param outerB64 - Base64-encoded outer ring image (PNG/JPEG)
335
+ * @param innerB64 - Base64-encoded inner rotated image (PNG/JPEG)
336
+ * @param serverUrl - Custom server URL (default: https://api.tik.tools)
337
+ * @returns Solve result with rotation angle and confidence
338
+ */
339
+ declare function solveRotate(apiKey: string, outerB64: string, innerB64: string, serverUrl?: string): Promise<RotateSolveResult>;
340
+ /**
341
+ * Solve a shapes (3D matching) CAPTCHA using the TikTool solver.
342
+ *
343
+ * @param apiKey - API key for authentication
344
+ * @param imageB64 - Base64-encoded CAPTCHA image with shape grid (PNG/JPEG)
345
+ * @param serverUrl - Custom server URL (default: https://api.tik.tools)
346
+ * @returns Solve result with two matching shape coordinates and confidence
347
+ */
348
+ declare function solveShapes(apiKey: string, imageB64: string, serverUrl?: string): Promise<ShapesSolveResult>;
349
+
350
+ export { type BaseEvent, type BattleArmiesEvent, type BattleEvent, type BattleTeam, type BattleTeamUser, type CallApiOptions, type ChatEvent, type ControlEvent, type EmoteChatEvent, type EnvelopeEvent, type GiftEvent, type LikeEvent, type LinkMicEvent, type LiveEvent, type LiveIntroEvent, type LivePageInfo, type MemberEvent, type PuzzleSolveResult, type QuestionEvent, type RankUpdateEvent, type RoomEvent, type RoomInfo, type RoomUserSeqEvent, type RotateSolveResult, type ShapesSolveResult, type SignedUrlResponse, type SocialEvent, type SubscribeEvent, TikTokLive, type TikTokLiveEvents, type TikTokLiveOptions, type TikTokUser, type UnknownEvent, callApi, fetchSignedUrl, resolveLivePage, resolveRoomId, solvePuzzle, solveRotate, solveShapes };
package/dist/index.js CHANGED
@@ -34,7 +34,10 @@ __export(index_exports, {
34
34
  callApi: () => callApi,
35
35
  fetchSignedUrl: () => fetchSignedUrl,
36
36
  resolveLivePage: () => resolveLivePage,
37
- resolveRoomId: () => resolveRoomId
37
+ resolveRoomId: () => resolveRoomId,
38
+ solvePuzzle: () => solvePuzzle,
39
+ solveRotate: () => solveRotate,
40
+ solveShapes: () => solveShapes
38
41
  });
39
42
  module.exports = __toCommonJS(index_exports);
40
43
 
@@ -174,18 +177,37 @@ function buildAck(id) {
174
177
  encodeField(7, 2, "ack")
175
178
  );
176
179
  }
180
+ function looksLikeUsername(s) {
181
+ return s.length > 0 && s.length <= 50 && !s.includes("://") && !s.includes("\0");
182
+ }
177
183
  function parseUser(data) {
178
184
  const f = decodeProto(data);
179
185
  const id = String(getInt(f, 1) || getStr(f, 1));
180
186
  const nickname = getStr(f, 3) || getStr(f, 2);
181
- const uniqueId = getStr(f, 38) || getStr(f, 4) || getStr(f, 2) || "";
187
+ let uniqueId = "";
188
+ const uid4 = getStr(f, 4);
189
+ const uid38 = getStr(f, 38);
190
+ if (uid4 && looksLikeUsername(uid4)) {
191
+ uniqueId = uid4;
192
+ } else if (uid38 && looksLikeUsername(uid38)) {
193
+ uniqueId = uid38;
194
+ } else {
195
+ const uid2 = getStr(f, 2);
196
+ if (uid2 && looksLikeUsername(uid2)) uniqueId = uid2;
197
+ }
182
198
  let profilePicture;
183
199
  const avatarBuf = getBytes(f, 9) || getBytes(f, 3);
184
200
  if (avatarBuf) {
185
201
  try {
186
202
  const avatarFields = decodeProto(avatarBuf);
187
203
  const urlBufs = getAllBytes(avatarFields, 1);
188
- if (urlBufs.length > 0) profilePicture = decoder.decode(urlBufs[0]);
204
+ for (const urlBuf of urlBufs) {
205
+ const url = decoder.decode(urlBuf);
206
+ if (url.includes("://")) {
207
+ profilePicture = url;
208
+ break;
209
+ }
210
+ }
189
211
  } catch {
190
212
  }
191
213
  }
@@ -630,6 +652,45 @@ async function callApi(opts) {
630
652
  }
631
653
  return data1;
632
654
  }
655
+ async function solvePuzzle(apiKey, puzzleB64, pieceB64, serverUrl) {
656
+ const base = (serverUrl || DEFAULT_SIGN_SERVER).replace(/\/$/, "");
657
+ const resp = await fetch(`${base}/captcha/solve/puzzle?apiKey=${encodeURIComponent(apiKey)}`, {
658
+ method: "POST",
659
+ headers: { "Content-Type": "application/json" },
660
+ body: JSON.stringify({ puzzle: puzzleB64, piece: pieceB64 })
661
+ });
662
+ const data = await resp.json();
663
+ if (data.status_code !== 0) {
664
+ throw new Error(data.error || `Solver failed (status ${data.status_code})`);
665
+ }
666
+ return data.data;
667
+ }
668
+ async function solveRotate(apiKey, outerB64, innerB64, serverUrl) {
669
+ const base = (serverUrl || DEFAULT_SIGN_SERVER).replace(/\/$/, "");
670
+ const resp = await fetch(`${base}/captcha/solve/rotate?apiKey=${encodeURIComponent(apiKey)}`, {
671
+ method: "POST",
672
+ headers: { "Content-Type": "application/json" },
673
+ body: JSON.stringify({ outer: outerB64, inner: innerB64 })
674
+ });
675
+ const data = await resp.json();
676
+ if (data.status_code !== 0) {
677
+ throw new Error(data.error || `Solver failed (status ${data.status_code})`);
678
+ }
679
+ return data.data;
680
+ }
681
+ async function solveShapes(apiKey, imageB64, serverUrl) {
682
+ const base = (serverUrl || DEFAULT_SIGN_SERVER).replace(/\/$/, "");
683
+ const resp = await fetch(`${base}/captcha/solve/shapes?apiKey=${encodeURIComponent(apiKey)}`, {
684
+ method: "POST",
685
+ headers: { "Content-Type": "application/json" },
686
+ body: JSON.stringify({ image: imageB64 })
687
+ });
688
+ const data = await resp.json();
689
+ if (data.status_code !== 0) {
690
+ throw new Error(data.error || `Solver failed (status ${data.status_code})`);
691
+ }
692
+ return data.data;
693
+ }
633
694
 
634
695
  // src/client.ts
635
696
  var DEFAULT_UA2 = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36";
@@ -1019,6 +1080,9 @@ var TikTokLive = class extends TypedEmitter {
1019
1080
  callApi,
1020
1081
  fetchSignedUrl,
1021
1082
  resolveLivePage,
1022
- resolveRoomId
1083
+ resolveRoomId,
1084
+ solvePuzzle,
1085
+ solveRotate,
1086
+ solveShapes
1023
1087
  });
1024
1088
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/proto.ts","../src/api.ts","../src/client.ts"],"sourcesContent":["export { TikTokLive } from './client.js';\r\nexport { resolveLivePage, resolveRoomId, fetchSignedUrl, callApi } from './api.js';\r\nexport type { LivePageInfo, SignedUrlResponse, CallApiOptions } from './api.js';\r\n\r\nexport type {\r\n TikTokLiveOptions,\r\n TikTokLiveEvents,\r\n RoomInfo,\r\n LiveEvent,\r\n BaseEvent,\r\n ChatEvent,\r\n MemberEvent,\r\n LikeEvent,\r\n GiftEvent,\r\n SocialEvent,\r\n RoomUserSeqEvent,\r\n BattleEvent,\r\n BattleArmiesEvent,\r\n BattleTeam,\r\n BattleTeamUser,\r\n SubscribeEvent,\r\n EmoteChatEvent,\r\n EnvelopeEvent,\r\n QuestionEvent,\r\n ControlEvent,\r\n RoomEvent,\r\n LiveIntroEvent,\r\n RankUpdateEvent,\r\n LinkMicEvent,\r\n UnknownEvent,\r\n TikTokUser,\r\n} from './types.js';\r\n","import type { LiveEvent, TikTokUser, BattleTeam, BattleTeamUser } from './types.js';\r\n\r\nconst encoder = new TextEncoder();\r\nconst decoder = new TextDecoder();\r\n\r\nexport function concatBytes(...arrays: Uint8Array[]): Uint8Array {\r\n let totalLength = 0;\r\n for (const arr of arrays) totalLength += arr.length;\r\n const result = new Uint8Array(totalLength);\r\n let offset = 0;\r\n for (const arr of arrays) {\r\n result.set(arr, offset);\r\n offset += arr.length;\r\n }\r\n return result;\r\n}\r\n\r\nfunction readInt32LE(buf: Uint8Array, offset: number): number {\r\n return buf[offset] |\r\n (buf[offset + 1] << 8) |\r\n (buf[offset + 2] << 16) |\r\n (buf[offset + 3] << 24);\r\n}\r\n\r\nfunction readBigInt64LE(buf: Uint8Array, offset: number): bigint {\r\n const lo = BigInt(buf[offset] |\r\n (buf[offset + 1] << 8) |\r\n (buf[offset + 2] << 16) |\r\n ((buf[offset + 3] << 24) >>> 0));\r\n const hi = BigInt(buf[offset + 4] |\r\n (buf[offset + 5] << 8) |\r\n (buf[offset + 6] << 16) |\r\n ((buf[offset + 7] << 24) >>> 0));\r\n return (hi << 32n) | (lo & 0xFFFFFFFFn);\r\n}\r\n\r\nexport function decodeVarint(buf: Uint8Array, offset: number): { value: number; offset: number } {\r\n let result = 0, shift = 0;\r\n while (offset < buf.length) {\r\n const byte = buf[offset++];\r\n result |= (byte & 0x7F) << shift;\r\n if ((byte & 0x80) === 0) break;\r\n shift += 7;\r\n }\r\n return { value: result >>> 0, offset };\r\n}\r\n\r\nexport function decodeVarint64(buf: Uint8Array, offset: number): { value: bigint; offset: number } {\r\n let result = 0n, shift = 0n;\r\n while (offset < buf.length) {\r\n const byte = BigInt(buf[offset++]);\r\n result |= (byte & 0x7Fn) << shift;\r\n if ((byte & 0x80n) === 0n) break;\r\n shift += 7n;\r\n }\r\n return { value: result, offset };\r\n}\r\n\r\nexport function encodeVarint(v: number | bigint): Uint8Array {\r\n const bytes: number[] = [];\r\n let n = typeof v === 'bigint' ? v : BigInt(v);\r\n do {\r\n let b = Number(n & 0x7Fn);\r\n n >>= 7n;\r\n if (n > 0n) b |= 0x80;\r\n bytes.push(b);\r\n } while (n > 0n);\r\n return new Uint8Array(bytes);\r\n}\r\n\r\nexport interface ProtoField {\r\n fn: number;\r\n wt: number;\r\n value: Uint8Array | number | bigint;\r\n}\r\n\r\nexport function encodeField(fn: number, wt: number, value: Uint8Array | bigint | number | string): Uint8Array {\r\n const tag = encodeVarint((fn << 3) | wt);\r\n if (wt === 0) {\r\n return concatBytes(tag, encodeVarint(typeof value === 'number' ? BigInt(value) : value as bigint));\r\n }\r\n const data = typeof value === 'string' ? encoder.encode(value) : value as Uint8Array;\r\n return concatBytes(tag, encodeVarint(data.length), data);\r\n}\r\n\r\nexport function decodeProto(buf: Uint8Array): ProtoField[] {\r\n const fields: ProtoField[] = [];\r\n let offset = 0;\r\n while (offset < buf.length) {\r\n const tagResult = decodeVarint(buf, offset);\r\n offset = tagResult.offset;\r\n const fn = tagResult.value >> 3;\r\n const wt = tagResult.value & 7;\r\n if (wt === 0) {\r\n const r = decodeVarint64(buf, offset);\r\n offset = r.offset;\r\n fields.push({ fn, wt, value: r.value });\r\n } else if (wt === 2) {\r\n const lenR = decodeVarint(buf, offset);\r\n offset = lenR.offset;\r\n const data = buf.subarray(offset, offset + lenR.value);\r\n offset += lenR.value;\r\n fields.push({ fn, wt, value: data });\r\n } else if (wt === 1) {\r\n fields.push({ fn, wt, value: readBigInt64LE(buf, offset) });\r\n offset += 8;\r\n } else if (wt === 5) {\r\n fields.push({ fn, wt, value: BigInt(readInt32LE(buf, offset)) });\r\n offset += 4;\r\n } else {\r\n break;\r\n }\r\n }\r\n return fields;\r\n}\r\n\r\nexport function getStr(fields: ProtoField[], fn: number): string {\r\n const f = fields.find(x => x.fn === fn && x.wt === 2);\r\n return f ? decoder.decode(f.value as Uint8Array) : '';\r\n}\r\n\r\nexport function getBytes(fields: ProtoField[], fn: number): Uint8Array | null {\r\n const f = fields.find(x => x.fn === fn && x.wt === 2);\r\n return f ? f.value as Uint8Array : null;\r\n}\r\n\r\nexport function getInt(fields: ProtoField[], fn: number): number {\r\n const f = fields.find(x => x.fn === fn && x.wt === 0);\r\n return f ? Number(f.value) : 0;\r\n}\r\n\r\nexport function getAllBytes(fields: ProtoField[], fn: number): Uint8Array[] {\r\n return fields.filter(x => x.fn === fn && x.wt === 2).map(x => x.value as Uint8Array);\r\n}\r\n\r\nexport function buildHeartbeat(roomId: string): Uint8Array {\r\n const payload = encodeField(1, 0, BigInt(roomId));\r\n return concatBytes(\r\n encodeField(6, 2, 'pb'),\r\n encodeField(7, 2, 'hb'),\r\n encodeField(8, 2, payload),\r\n );\r\n}\r\n\r\nexport function buildImEnterRoom(roomId: string): Uint8Array {\r\n const inner = concatBytes(\r\n encodeField(1, 0, BigInt(roomId)),\r\n encodeField(4, 0, 12n),\r\n encodeField(5, 2, 'audience'),\r\n encodeField(6, 2, ''),\r\n encodeField(9, 2, ''),\r\n encodeField(10, 2, ''),\r\n );\r\n return concatBytes(\r\n encodeField(6, 2, 'pb'),\r\n encodeField(7, 2, 'im_enter_room'),\r\n encodeField(8, 2, inner),\r\n );\r\n}\r\n\r\nexport function buildAck(id: bigint): Uint8Array {\r\n return concatBytes(\r\n encodeField(2, 0, id),\r\n encodeField(6, 2, 'pb'),\r\n encodeField(7, 2, 'ack'),\r\n );\r\n}\r\n\r\nfunction parseUser(data: Uint8Array): TikTokUser {\r\n const f = decodeProto(data);\r\n const id = String(getInt(f, 1) || getStr(f, 1));\r\n const nickname = getStr(f, 3) || getStr(f, 2);\r\n const uniqueId = getStr(f, 38) || getStr(f, 4) || getStr(f, 2) || '';\r\n\r\n let profilePicture: string | undefined;\r\n const avatarBuf = getBytes(f, 9) || getBytes(f, 3);\r\n if (avatarBuf) {\r\n try {\r\n const avatarFields = decodeProto(avatarBuf);\r\n const urlBufs = getAllBytes(avatarFields, 1);\r\n if (urlBufs.length > 0) profilePicture = decoder.decode(urlBufs[0]);\r\n } catch { }\r\n }\r\n\r\n const badges: string[] = [];\r\n const badgeBuf = getBytes(f, 64);\r\n if (badgeBuf) {\r\n try {\r\n const badgeFields = decodeProto(badgeBuf);\r\n const badgeItems = getAllBytes(badgeFields, 21);\r\n for (const bi of badgeItems) {\r\n const bf = decodeProto(bi);\r\n const name = getStr(bf, 3) || getStr(bf, 2);\r\n if (name) badges.push(name);\r\n }\r\n } catch { }\r\n }\r\n\r\n return {\r\n id,\r\n nickname,\r\n uniqueId: uniqueId || nickname || id,\r\n profilePictureUrl: profilePicture,\r\n badges: badges.length > 0 ? badges : undefined,\r\n };\r\n}\r\n\r\nfunction parseBattleTeamFromArmies(itemBuf: Uint8Array): BattleTeam {\r\n const f = decodeProto(itemBuf);\r\n const hostUserId = String(getInt(f, 1));\r\n let teamScore = 0;\r\n const users: BattleTeamUser[] = [];\r\n\r\n const groups = getAllBytes(f, 2);\r\n for (const gb of groups) {\r\n try {\r\n const gf = decodeProto(gb);\r\n const points = getInt(gf, 2);\r\n teamScore += points;\r\n\r\n const userBufs = getAllBytes(gf, 1);\r\n for (const ub of userBufs) {\r\n try {\r\n const user = parseUser(ub);\r\n users.push({ user, score: points });\r\n } catch { }\r\n }\r\n } catch { }\r\n }\r\n\r\n return { hostUserId, score: teamScore, users };\r\n}\r\n\r\nexport function parseWebcastMessage(method: string, payload: Uint8Array): LiveEvent {\r\n const f = decodeProto(payload);\r\n const base = { timestamp: Date.now(), msgId: '' };\r\n\r\n const typeBuf = getBytes(f, 1);\r\n if (typeBuf) {\r\n try {\r\n const tf = decodeProto(typeBuf);\r\n const ts = getInt(tf, 4);\r\n if (ts) base.timestamp = ts;\r\n } catch { }\r\n }\r\n\r\n switch (method) {\r\n case 'WebcastChatMessage': {\r\n const userBuf = getBytes(f, 2);\r\n const user = userBuf ? parseUser(userBuf) : { id: '0', nickname: '', uniqueId: '' };\r\n return { ...base, type: 'chat' as const, user, comment: getStr(f, 3) };\r\n }\r\n\r\n case 'WebcastMemberMessage': {\r\n const userBuf = getBytes(f, 2);\r\n const user = userBuf ? parseUser(userBuf) : { id: '0', nickname: '', uniqueId: '' };\r\n let action = 1;\r\n const eventBuf = getBytes(f, 1);\r\n if (eventBuf) {\r\n const ef = decodeProto(eventBuf);\r\n const detailBuf = getBytes(ef, 8);\r\n if (detailBuf) {\r\n const df = decodeProto(detailBuf);\r\n const label = getStr(df, 2);\r\n if (label.includes('followed')) action = 2;\r\n else if (label.includes('share')) action = 3;\r\n }\r\n }\r\n return { ...base, type: 'member' as const, user, action };\r\n }\r\n\r\n case 'WebcastLikeMessage': {\r\n const userBuf = getBytes(f, 5);\r\n const user = userBuf ? parseUser(userBuf) : { id: '0', nickname: '', uniqueId: '' };\r\n return {\r\n ...base, type: 'like' as const, user,\r\n likeCount: getInt(f, 2),\r\n totalLikes: getInt(f, 3),\r\n };\r\n }\r\n\r\n case 'WebcastGiftMessage': {\r\n const userBuf = getBytes(f, 7);\r\n const user = userBuf ? parseUser(userBuf) : { id: '0', nickname: '', uniqueId: '' };\r\n const giftId = getInt(f, 2);\r\n const repeatCount = getInt(f, 5);\r\n const repeatEnd = getInt(f, 9) === 1;\r\n\r\n let giftName = '', diamondCount = 0, giftType = 0;\r\n let giftImageUrl = '';\r\n const detailsBuf = getBytes(f, 15);\r\n if (detailsBuf) {\r\n const df = decodeProto(detailsBuf);\r\n giftName = getStr(df, 16) || getStr(df, 2);\r\n diamondCount = getInt(df, 12);\r\n giftType = getInt(df, 11);\r\n\r\n const imgBuf = getBytes(df, 1);\r\n if (imgBuf) {\r\n const imgf = decodeProto(imgBuf);\r\n giftImageUrl = getStr(imgf, 1);\r\n }\r\n }\r\n\r\n let toUserId = '';\r\n const extraBuf = getBytes(f, 23);\r\n if (extraBuf) {\r\n const ef = decodeProto(extraBuf);\r\n toUserId = String(getInt(ef, 8));\r\n }\r\n\r\n const groupId = toUserId || getStr(f, 11);\r\n\r\n return {\r\n ...base, type: 'gift' as const, user, giftId, giftName, diamondCount,\r\n repeatCount, repeatEnd, combo: repeatCount > 1 && !repeatEnd,\r\n giftType, groupId, giftPictureUrl: giftImageUrl,\r\n };\r\n }\r\n\r\n case 'WebcastSocialMessage': {\r\n const userBuf = getBytes(f, 2);\r\n const user = userBuf ? parseUser(userBuf) : { id: '0', nickname: '', uniqueId: '' };\r\n let action = 'follow';\r\n const eventBuf = getBytes(f, 1);\r\n if (eventBuf) {\r\n const ef = decodeProto(eventBuf);\r\n const detailBuf = getBytes(ef, 8);\r\n if (detailBuf) {\r\n const df = decodeProto(detailBuf);\r\n const label = getStr(df, 2);\r\n if (label.includes('share')) action = 'share';\r\n else if (label.includes('follow')) action = 'follow';\r\n const displayType = getStr(df, 1);\r\n if (displayType === 'pm_mt_msg_viewer_share') action = 'share';\r\n }\r\n }\r\n return { ...base, type: 'social' as const, user, action };\r\n }\r\n\r\n case 'WebcastRoomUserSeqMessage': {\r\n const viewerCount = getInt(f, 3) || getInt(f, 2);\r\n const totalViewers = getInt(f, 1) || viewerCount;\r\n return { ...base, type: 'roomUserSeq' as const, totalViewers, viewerCount };\r\n }\r\n\r\n case 'WebcastLinkMicBattle': {\r\n const battleId = String(getInt(f, 1) || '');\r\n const status = getInt(f, 2) || 1;\r\n const battleDuration = getInt(f, 3);\r\n const teams: BattleTeam[] = [];\r\n\r\n const battleUserBufs = getAllBytes(f, 10);\r\n for (const bub of battleUserBufs) {\r\n try {\r\n const bf = decodeProto(bub);\r\n const groupBuf = getBytes(bf, 2);\r\n if (groupBuf) {\r\n const gf = decodeProto(groupBuf);\r\n const linkUserBuf = getBytes(gf, 1);\r\n if (linkUserBuf) {\r\n const user = parseUser(linkUserBuf);\r\n teams.push({\r\n hostUserId: user.id,\r\n score: 0,\r\n users: [{ user, score: 0 }],\r\n });\r\n }\r\n }\r\n } catch { }\r\n }\r\n\r\n if (teams.length === 0) {\r\n const teamBufs7 = getAllBytes(f, 7);\r\n for (const tb of teamBufs7) {\r\n try {\r\n teams.push(parseBattleTeamFromArmies(tb));\r\n } catch { }\r\n }\r\n }\r\n\r\n return { ...base, type: 'battle' as const, battleId, status, battleDuration, teams };\r\n }\r\n\r\n case 'WebcastLinkMicArmies': {\r\n const battleId = String(getInt(f, 1) || '');\r\n const battleStatus = getInt(f, 7);\r\n const teams: BattleTeam[] = [];\r\n\r\n const itemBufs = getAllBytes(f, 3);\r\n for (const ib of itemBufs) {\r\n try {\r\n teams.push(parseBattleTeamFromArmies(ib));\r\n } catch { }\r\n }\r\n\r\n return {\r\n ...base, type: 'battleArmies' as const, battleId, teams,\r\n status: battleStatus,\r\n };\r\n }\r\n\r\n case 'WebcastSubNotifyMessage': {\r\n const userBuf = getBytes(f, 2);\r\n const user = userBuf ? parseUser(userBuf) : { id: '0', nickname: '', uniqueId: '' };\r\n return { ...base, type: 'subscribe' as const, user, subMonth: getInt(f, 3) };\r\n }\r\n\r\n case 'WebcastEmoteChatMessage': {\r\n const userBuf = getBytes(f, 2);\r\n const user = userBuf ? parseUser(userBuf) : { id: '0', nickname: '', uniqueId: '' };\r\n let emoteId = '', emoteUrl = '';\r\n const emoteBuf = getBytes(f, 3);\r\n if (emoteBuf) {\r\n const ef = decodeProto(emoteBuf);\r\n emoteId = getStr(ef, 1);\r\n const imageBuf = getBytes(ef, 2);\r\n if (imageBuf) {\r\n const imgFields = decodeProto(imageBuf);\r\n emoteUrl = getStr(imgFields, 1);\r\n }\r\n }\r\n return { ...base, type: 'emoteChat' as const, user, emoteId, emoteUrl };\r\n }\r\n\r\n case 'WebcastEnvelopeMessage': {\r\n const envelopeId = String(getInt(f, 1) || getStr(f, 1));\r\n return { ...base, type: 'envelope' as const, envelopeId, diamondCount: getInt(f, 3) };\r\n }\r\n\r\n case 'WebcastQuestionNewMessage': {\r\n let questionText = '', user: TikTokUser = { id: '0', nickname: '', uniqueId: '' };\r\n const detailBuf = getBytes(f, 2);\r\n if (detailBuf) {\r\n const df = decodeProto(detailBuf);\r\n questionText = getStr(df, 2);\r\n const userBuf = getBytes(df, 5);\r\n if (userBuf) user = parseUser(userBuf);\r\n }\r\n return { ...base, type: 'question' as const, user, questionText };\r\n }\r\n\r\n case 'WebcastRankUpdateMessage':\r\n case 'WebcastHourlyRankMessage': {\r\n const rankType = getStr(f, 1) || `rank_${getInt(f, 1)}`;\r\n const rankList: Array<{ user: TikTokUser; rank: number; score: number }> = [];\r\n const listBufs = getAllBytes(f, 2);\r\n for (const lb of listBufs) {\r\n try {\r\n const rf = decodeProto(lb);\r\n const userBuf = getBytes(rf, 1);\r\n const rank = getInt(rf, 2);\r\n const score = getInt(rf, 3);\r\n const user = userBuf ? parseUser(userBuf) : { id: '0', nickname: '', uniqueId: '' };\r\n rankList.push({ user, rank, score });\r\n } catch { }\r\n }\r\n return { ...base, type: 'rankUpdate' as const, rankType, rankList };\r\n }\r\n\r\n case 'WebcastControlMessage':\r\n return { ...base, type: 'control' as const, action: getInt(f, 2) || getInt(f, 1) };\r\n\r\n case 'WebcastRoomMessage':\r\n case 'RoomMessage':\r\n return { ...base, type: 'room' as const, status: getInt(f, 2) };\r\n\r\n case 'WebcastLiveIntroMessage': {\r\n const roomId = String(getInt(f, 2));\r\n const title = getStr(f, 4) || getStr(f, 2);\r\n return { ...base, type: 'liveIntro' as const, roomId, title };\r\n }\r\n\r\n case 'WebcastLinkMicMethod':\r\n case 'WebcastLinkmicBattleTaskMessage': {\r\n const action = getStr(f, 1) || `action_${getInt(f, 1)}`;\r\n const users: TikTokUser[] = [];\r\n const userBufs = getAllBytes(f, 2);\r\n for (const ub of userBufs) {\r\n try { users.push(parseUser(ub)); } catch { }\r\n }\r\n return { ...base, type: 'linkMic' as const, action, users };\r\n }\r\n\r\n default:\r\n return { ...base, type: 'unknown' as const, method };\r\n }\r\n}\r\n\r\nexport function parseWebcastResponse(payload: Uint8Array): LiveEvent[] {\r\n const events: LiveEvent[] = [];\r\n const respFields = decodeProto(payload);\r\n\r\n for (const mf of respFields.filter(f => f.fn === 1 && f.wt === 2)) {\r\n const msgBuf = mf.value as Uint8Array;\r\n const msgFields = decodeProto(msgBuf);\r\n const method = getStr(msgFields, 1);\r\n const innerPayload = getBytes(msgFields, 2);\r\n if (!method || !innerPayload) continue;\r\n\r\n try {\r\n events.push(parseWebcastMessage(method, innerPayload));\r\n } catch { }\r\n }\r\n\r\n return events;\r\n}\r\n","/**\r\n * TikTool API utilities for the sign-and-return API flow.\r\n *\r\n * The API server returns signed URLs instead of fetching TikTok data directly.\r\n * These utilities handle the two-step flow:\r\n * 1. resolve_required — scrape TikTok HTML to get room_id\r\n * 2. fetch_signed_url — use the signed URL to get actual TikTok data\r\n *\r\n * @module\r\n */\r\n\r\nconst DEFAULT_UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36';\r\nconst DEFAULT_SIGN_SERVER = 'https://api.tik.tools';\r\n\r\nconst pageCache = new Map<string, { info: LivePageInfo; ts: number }>();\r\nconst PAGE_CACHE_TTL = 5 * 60 * 1000;\r\n\r\n/**\r\n * Resolved live page metadata from a TikTok live page.\r\n */\r\nexport interface LivePageInfo {\r\n /** Active room ID for the livestream */\r\n roomId: string;\r\n /** Session cookie required for WebSocket authentication */\r\n ttwid: string;\r\n /** Server cluster region (e.g. 'us', 'eu') */\r\n clusterRegion: string;\r\n}\r\n\r\n/**\r\n * Scrape a TikTok live page to extract room metadata.\r\n * Returns the room ID, session cookie, and cluster region.\r\n * Results are cached for 5 minutes. Returns `null` if the user is not live.\r\n */\r\nexport async function resolveLivePage(uniqueId: string): Promise<LivePageInfo | null> {\r\n const clean = uniqueId.replace(/^@/, '');\r\n const cached = pageCache.get(clean);\r\n if (cached && Date.now() - cached.ts < PAGE_CACHE_TTL) {\r\n return cached.info;\r\n }\r\n\r\n try {\r\n const resp = await fetch(`https://www.tiktok.com/@${clean}/live`, {\r\n headers: {\r\n 'User-Agent': DEFAULT_UA,\r\n 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',\r\n 'Accept-Language': 'en-US,en;q=0.9',\r\n },\r\n redirect: 'follow',\r\n });\r\n\r\n if (!resp.ok) return null;\r\n\r\n // Extract ttwid session cookie\r\n let ttwid = '';\r\n const setCookies = resp.headers.get('set-cookie') || '';\r\n for (const part of setCookies.split(',')) {\r\n const trimmed = part.trim();\r\n if (trimmed.startsWith('ttwid=')) {\r\n ttwid = trimmed.split(';')[0].split('=').slice(1).join('=');\r\n break;\r\n }\r\n }\r\n if (!ttwid && typeof (resp.headers as any).getSetCookie === 'function') {\r\n for (const sc of (resp.headers as any).getSetCookie()) {\r\n if (typeof sc === 'string' && sc.startsWith('ttwid=')) {\r\n ttwid = sc.split(';')[0].split('=').slice(1).join('=');\r\n break;\r\n }\r\n }\r\n }\r\n\r\n const html = await resp.text();\r\n\r\n // Extract roomId from SIGI_STATE JSON block\r\n let roomId = '';\r\n const sigiMatch = html.match(/id=\"SIGI_STATE\"[^>]*>([^<]+)/);\r\n if (sigiMatch) {\r\n try {\r\n const json = JSON.parse(sigiMatch[1]);\r\n const jsonStr = JSON.stringify(json);\r\n const m = jsonStr.match(/\"roomId\"\\s*:\\s*\"(\\d+)\"/);\r\n if (m) roomId = m[1];\r\n } catch { }\r\n }\r\n\r\n // Fallback patterns\r\n if (!roomId) {\r\n const patterns = [\r\n /\"roomId\"\\s*:\\s*\"(\\d+)\"/,\r\n /room_id[=/](\\d{10,})/,\r\n /\"idStr\"\\s*:\\s*\"(\\d{10,})\"/,\r\n ];\r\n for (const p of patterns) {\r\n const m = html.match(p);\r\n if (m) { roomId = m[1]; break; }\r\n }\r\n }\r\n\r\n if (!roomId) return null;\r\n\r\n // Extract cluster region\r\n const crMatch = html.match(/\"clusterRegion\"\\s*:\\s*\"([^\"]+)\"/);\r\n const clusterRegion = crMatch ? crMatch[1] : '';\r\n\r\n const info: LivePageInfo = { roomId, ttwid, clusterRegion };\r\n pageCache.set(clean, { info, ts: Date.now() });\r\n return info;\r\n } catch { }\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * Resolve a TikTok username to a room ID.\r\n * Returns `null` if the user is not currently live.\r\n * Results are cached for 5 minutes.\r\n */\r\nexport async function resolveRoomId(uniqueId: string): Promise<string | null> {\r\n const info = await resolveLivePage(uniqueId);\r\n return info?.roomId ?? null;\r\n}\r\n\r\nexport interface SignedUrlResponse {\r\n status_code: number;\r\n action?: string;\r\n signed_url: string;\r\n headers: Record<string, string>;\r\n cookies: string;\r\n}\r\n\r\n/**\r\n * Execute a signed-URL API response: fetch the signed URL and return the\r\n * parsed JSON data from TikTok.\r\n */\r\nexport async function fetchSignedUrl(response: SignedUrlResponse): Promise<any> {\r\n if (!response.signed_url) {\r\n return null;\r\n }\r\n\r\n const headers: Record<string, string> = { ...(response.headers || {}) };\r\n if (response.cookies) {\r\n headers['Cookie'] = response.cookies;\r\n }\r\n\r\n const resp = await fetch(response.signed_url, { headers, redirect: 'follow' });\r\n const text = await resp.text();\r\n try {\r\n return JSON.parse(text);\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\nexport interface CallApiOptions {\r\n /** API server URL (default: https://api.tik.tools) */\r\n serverUrl?: string;\r\n /** API key for authentication */\r\n apiKey: string;\r\n /** API endpoint path (e.g. '/webcast/room_video') */\r\n endpoint: string;\r\n /** TikTok unique_id to resolve */\r\n uniqueId: string;\r\n /** HTTP method (default: POST) */\r\n method?: 'GET' | 'POST';\r\n /** Additional body fields for POST requests */\r\n extraBody?: Record<string, any>;\r\n}\r\n\r\n/**\r\n * Call a TikTool API endpoint, handling the full\r\n * resolve_required → room_id → signed_url → fetch flow automatically.\r\n *\r\n * Returns the actual TikTok data, or `null` if the user is not live.\r\n */\r\nexport async function callApi(opts: CallApiOptions): Promise<any> {\r\n const serverUrl = (opts.serverUrl || DEFAULT_SIGN_SERVER).replace(/\\/$/, '');\r\n const isGet = opts.method === 'GET';\r\n const ak = encodeURIComponent(opts.apiKey);\r\n\r\n const url1 = isGet\r\n ? `${serverUrl}${opts.endpoint}?apiKey=${ak}&unique_id=${encodeURIComponent(opts.uniqueId)}`\r\n : `${serverUrl}${opts.endpoint}?apiKey=${ak}`;\r\n\r\n const fetchOpts1: RequestInit = isGet\r\n ? {}\r\n : {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ unique_id: opts.uniqueId, ...opts.extraBody }),\r\n };\r\n\r\n const resp1 = await fetch(url1, fetchOpts1);\r\n const data1 = await resp1.json() as any;\r\n\r\n // If the response contains a signed URL to fetch (with or without explicit action),\r\n // follow through and fetch the actual TikTok data\r\n if (data1.signed_url || data1.action === 'fetch_signed_url') {\r\n return fetchSignedUrl(data1);\r\n }\r\n\r\n if (data1.status_code === 0 && data1.action !== 'resolve_required') {\r\n return data1;\r\n }\r\n\r\n if (data1.action === 'resolve_required') {\r\n const roomId = await resolveRoomId(opts.uniqueId);\r\n if (!roomId) return null;\r\n\r\n const url2 = isGet\r\n ? `${serverUrl}${opts.endpoint}?apiKey=${ak}&room_id=${encodeURIComponent(roomId)}`\r\n : `${serverUrl}${opts.endpoint}?apiKey=${ak}`;\r\n\r\n const fetchOpts2: RequestInit = isGet\r\n ? {}\r\n : {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ room_id: roomId, ...opts.extraBody }),\r\n };\r\n\r\n const resp2 = await fetch(url2, fetchOpts2);\r\n const data2 = await resp2.json() as any;\r\n\r\n if (data2.signed_url || data2.action === 'fetch_signed_url') {\r\n return fetchSignedUrl(data2);\r\n }\r\n\r\n return data2;\r\n }\r\n\r\n return data1;\r\n}\r\n","import type { TikTokLiveOptions, TikTokLiveEvents, RoomInfo, LiveEvent } from './types.js';\r\nimport {\r\n concatBytes,\r\n decodeProto,\r\n getStr,\r\n getBytes,\r\n buildHeartbeat,\r\n buildImEnterRoom,\r\n buildAck,\r\n parseWebcastResponse,\r\n} from './proto.js';\r\nimport { resolveLivePage } from './api.js';\r\n\r\nconst DEFAULT_UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36';\r\nconst DEFAULT_SIGN_SERVER = 'https://api.tik.tools';\r\n\r\ntype Listener = (...args: any[]) => void;\r\n\r\nclass TypedEmitter {\r\n private _listeners = new Map<string, Listener[]>();\r\n\r\n on(event: string, fn: Listener): this {\r\n const arr = this._listeners.get(event) || [];\r\n arr.push(fn);\r\n this._listeners.set(event, arr);\r\n return this;\r\n }\r\n\r\n once(event: string, fn: Listener): this {\r\n const wrapper: Listener = (...args) => {\r\n this.off(event, wrapper);\r\n fn(...args);\r\n };\r\n return this.on(event, wrapper);\r\n }\r\n\r\n off(event: string, fn: Listener): this {\r\n const arr = this._listeners.get(event);\r\n if (arr) {\r\n this._listeners.set(event, arr.filter(l => l !== fn));\r\n }\r\n return this;\r\n }\r\n\r\n emit(event: string, ...args: any[]): boolean {\r\n const arr = this._listeners.get(event);\r\n if (!arr || arr.length === 0) return false;\r\n for (const fn of [...arr]) fn(...args);\r\n return true;\r\n }\r\n\r\n removeAllListeners(event?: string): this {\r\n if (event) this._listeners.delete(event);\r\n else this._listeners.clear();\r\n return this;\r\n }\r\n}\r\n\r\nasync function gunzip(data: Uint8Array): Promise<Uint8Array> {\r\n if (typeof DecompressionStream !== 'undefined') {\r\n const ds = new DecompressionStream('gzip');\r\n const writer = ds.writable.getWriter();\r\n const reader = ds.readable.getReader();\r\n writer.write(data as any);\r\n writer.close();\r\n const chunks: Uint8Array[] = [];\r\n while (true) {\r\n const { done, value } = await reader.read();\r\n if (done) break;\r\n chunks.push(value);\r\n }\r\n return concatBytes(...chunks);\r\n }\r\n try {\r\n const zlib = await import('zlib');\r\n return new Promise((resolve, reject) => {\r\n zlib.gunzip(data, (err: Error | null, result: Buffer) => {\r\n if (err) reject(err);\r\n else resolve(new Uint8Array(result));\r\n });\r\n });\r\n } catch {\r\n return data;\r\n }\r\n}\r\n\r\n// Pre-cache zlib for sync decompression (require fails in ESM)\r\nlet _zlib: any = null;\r\nlet _zlibLoadAttempted = false;\r\n\r\nasync function ensureZlib(): Promise<any> {\r\n if (_zlib) return _zlib;\r\n if (_zlibLoadAttempted) return null;\r\n _zlibLoadAttempted = true;\r\n try {\r\n _zlib = await import('zlib');\r\n } catch { }\r\n return _zlib;\r\n}\r\n\r\n// Attempt to load zlib eagerly at module init\r\nensureZlib();\r\n\r\nfunction gunzipSync(data: Uint8Array): Uint8Array | null {\r\n if (!_zlib) return null; // Signal that sync decompress is unavailable\r\n try {\r\n return new Uint8Array(_zlib.gunzipSync(data));\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\ntype WebSocketLike = {\r\n readonly readyState: number;\r\n send(data: ArrayBufferLike | string): void;\r\n close(code?: number, reason?: string): void;\r\n onopen: ((ev: any) => void) | null;\r\n onmessage: ((ev: any) => void) | null;\r\n onerror: ((ev: any) => void) | null;\r\n onclose: ((ev: any) => void) | null;\r\n};\r\n\r\ninterface WebSocketConstructor {\r\n new(url: string, protocols?: string | string[]): WebSocketLike;\r\n readonly OPEN: number;\r\n readonly CLOSED: number;\r\n}\r\n\r\nfunction getWsHost(clusterRegion: string): string {\r\n if (!clusterRegion) return 'webcast-ws.tiktok.com';\r\n const r = clusterRegion.toLowerCase();\r\n if (r.startsWith('eu') || r.includes('eu')) return 'webcast-ws.eu.tiktok.com';\r\n if (r.startsWith('us') || r.includes('us')) return 'webcast-ws.us.tiktok.com';\r\n return 'webcast-ws.tiktok.com';\r\n}\r\n\r\nasync function resolveWebSocket(userImpl?: any): Promise<WebSocketConstructor> {\r\n if (userImpl) return userImpl;\r\n\r\n if (typeof globalThis.WebSocket !== 'undefined') {\r\n return globalThis.WebSocket as unknown as WebSocketConstructor;\r\n }\r\n\r\n try {\r\n const ws = await import('ws');\r\n return (ws.default || ws) as unknown as WebSocketConstructor;\r\n } catch {\r\n throw new Error(\r\n 'No WebSocket implementation found. ' +\r\n 'Either use Node.js 22+ (native WebSocket), Cloudflare Workers, or install the \"ws\" package: npm i ws'\r\n );\r\n }\r\n}\r\n\r\nexport class TikTokLive extends TypedEmitter {\r\n private ws: WebSocketLike | null = null;\r\n private heartbeatTimer: ReturnType<typeof setInterval> | null = null;\r\n private reconnectAttempts = 0;\r\n private intentionalClose = false;\r\n private _connected = false;\r\n private _eventCount = 0;\r\n private _roomId = '';\r\n private _battleHosts = new Map<string, { id: string; nickname: string; uniqueId: string; profilePicture?: string }>();\r\n\r\n private readonly uniqueId: string;\r\n private readonly signServerUrl: string;\r\n private readonly apiKey: string;\r\n private readonly autoReconnect: boolean;\r\n private readonly maxReconnectAttempts: number;\r\n private readonly heartbeatInterval: number;\r\n private readonly debug: boolean;\r\n private readonly webSocketImpl?: any;\r\n private WS!: WebSocketConstructor;\r\n\r\n constructor(options: TikTokLiveOptions) {\r\n super();\r\n this.uniqueId = options.uniqueId.replace(/^@/, '');\r\n this.signServerUrl = (options.signServerUrl || DEFAULT_SIGN_SERVER).replace(/\\/$/, '');\r\n if (!options.apiKey) throw new Error('apiKey is required. Get a free key at https://tik.tools');\r\n this.apiKey = options.apiKey;\r\n this.autoReconnect = options.autoReconnect ?? true;\r\n this.maxReconnectAttempts = options.maxReconnectAttempts ?? 5;\r\n this.heartbeatInterval = options.heartbeatInterval ?? 10_000;\r\n this.debug = options.debug ?? false;\r\n this.webSocketImpl = options.webSocketImpl;\r\n }\r\n\r\n async connect(): Promise<void> {\r\n this.intentionalClose = false;\r\n\r\n if (!this.WS) {\r\n this.WS = await resolveWebSocket(this.webSocketImpl);\r\n }\r\n\r\n const pageInfo = await resolveLivePage(this.uniqueId);\r\n if (!pageInfo) throw new Error(`User @${this.uniqueId} is not currently live`);\r\n if (!pageInfo.ttwid) throw new Error('Failed to obtain session cookie');\r\n\r\n const { roomId, ttwid, clusterRegion } = pageInfo;\r\n this._roomId = roomId;\r\n const wsHost = getWsHost(clusterRegion);\r\n\r\n const wsParams = new URLSearchParams({\r\n version_code: '270000', device_platform: 'web', cookie_enabled: 'true',\r\n screen_width: '1920', screen_height: '1080', browser_language: 'en-US',\r\n browser_platform: 'Win32', browser_name: 'Mozilla',\r\n browser_version: DEFAULT_UA.split('Mozilla/')[1] || '5.0',\r\n browser_online: 'true', tz_name: 'Etc/UTC',\r\n app_name: 'tiktok_web', sup_ws_ds_opt: '1', update_version_code: '2.0.0',\r\n compress: 'gzip', webcast_language: 'en', ws_direct: '1', aid: '1988',\r\n live_id: '12', app_language: 'en', client_enter: '1', room_id: roomId,\r\n identity: 'audience', history_comment_count: '6', last_rtt: '0',\r\n heartbeat_duration: '10000', resp_content_type: 'protobuf', did_rule: '3',\r\n });\r\n\r\n const rawWsUrl = `https://${wsHost}/webcast/im/ws_proxy/ws_reuse_supplement/?${wsParams}`;\r\n const signUrl = `${this.signServerUrl}/webcast/sign_url`;\r\n\r\n let wsUrl: string;\r\n try {\r\n const signResp = await fetch(signUrl, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'x-api-key': this.apiKey,\r\n },\r\n body: JSON.stringify({ url: rawWsUrl }),\r\n });\r\n const signData = await signResp.json() as Record<string, any>;\r\n\r\n if (signData.status_code === 0 && signData.data?.signed_url) {\r\n wsUrl = (signData.data.signed_url as string).replace(/^https:\\/\\//, 'wss://');\r\n } else {\r\n wsUrl = rawWsUrl.replace(/^https:\\/\\//, 'wss://');\r\n }\r\n } catch {\r\n wsUrl = rawWsUrl.replace(/^https:\\/\\//, 'wss://');\r\n }\r\n\r\n return new Promise<void>((resolve, reject) => {\r\n const connUrl = wsUrl + (wsUrl.includes('?') ? '&' : '?') + `ttwid=${ttwid}`;\r\n\r\n try {\r\n this.ws = new (this.WS as any)(connUrl, {\r\n headers: {\r\n 'User-Agent': DEFAULT_UA,\r\n 'Cookie': `ttwid=${ttwid}`,\r\n 'Origin': 'https://www.tiktok.com',\r\n },\r\n }) as WebSocketLike;\r\n } catch {\r\n this.ws = new this.WS(connUrl) as WebSocketLike;\r\n }\r\n\r\n const ws = this.ws;\r\n let settled = false;\r\n\r\n ws.onopen = () => {\r\n this._connected = true;\r\n this.reconnectAttempts = 0;\r\n\r\n const hb = buildHeartbeat(roomId);\r\n const enter = buildImEnterRoom(roomId);\r\n ws.send(hb.buffer.byteLength === hb.length ? hb.buffer : hb.buffer.slice(hb.byteOffset, hb.byteOffset + hb.byteLength));\r\n ws.send(enter.buffer.byteLength === enter.length ? enter.buffer : enter.buffer.slice(enter.byteOffset, enter.byteOffset + enter.byteLength));\r\n this.startHeartbeat(roomId);\r\n\r\n const roomInfo: RoomInfo = {\r\n roomId,\r\n wsHost,\r\n clusterRegion,\r\n connectedAt: new Date().toISOString(),\r\n };\r\n\r\n (this as TypedEmitter).emit('connected');\r\n (this as TypedEmitter).emit('roomInfo', roomInfo);\r\n if (!settled) { settled = true; resolve(); }\r\n };\r\n\r\n ws.onmessage = (event: any) => {\r\n const raw = event.data !== undefined ? event.data : event;\r\n this.handleMessage(raw);\r\n };\r\n\r\n ws.onclose = (event: any) => {\r\n this._connected = false;\r\n this.stopHeartbeat();\r\n\r\n const code = event?.code ?? 1006;\r\n const reason = event?.reason ?? '';\r\n (this as TypedEmitter).emit('disconnected', code, reason?.toString?.() || '');\r\n\r\n if (!this.intentionalClose && this.autoReconnect && this.reconnectAttempts < this.maxReconnectAttempts) {\r\n this.reconnectAttempts++;\r\n const delay = Math.min(1000 * Math.pow(2, this.reconnectAttempts - 1), 30_000);\r\n setTimeout(() => this.connect().catch(e => (this as TypedEmitter).emit('error', e)), delay);\r\n }\r\n };\r\n\r\n ws.onerror = (err: any) => {\r\n (this as TypedEmitter).emit('error', err instanceof Error ? err : new Error(String(err?.message || err)));\r\n if (!settled) { settled = true; reject(err); }\r\n };\r\n\r\n setTimeout(() => {\r\n if (!settled) {\r\n settled = true;\r\n ws.close();\r\n reject(new Error('Connection timeout'));\r\n }\r\n }, 15_000);\r\n });\r\n }\r\n\r\n disconnect(): void {\r\n this.intentionalClose = true;\r\n this.stopHeartbeat();\r\n if (this.ws) {\r\n this.ws.close(1000);\r\n this.ws = null;\r\n }\r\n this._connected = false;\r\n }\r\n\r\n get connected(): boolean {\r\n return this._connected;\r\n }\r\n\r\n get eventCount(): number {\r\n return this._eventCount;\r\n }\r\n\r\n get roomId(): string {\r\n return this._roomId;\r\n }\r\n\r\n override on<K extends keyof TikTokLiveEvents>(event: K, listener: TikTokLiveEvents[K]): this {\r\n return super.on(event as string, listener as Listener);\r\n }\r\n\r\n override once<K extends keyof TikTokLiveEvents>(event: K, listener: TikTokLiveEvents[K]): this {\r\n return super.once(event as string, listener as Listener);\r\n }\r\n\r\n override off<K extends keyof TikTokLiveEvents>(event: K, listener: TikTokLiveEvents[K]): this {\r\n return super.off(event as string, listener as Listener);\r\n }\r\n\r\n override emit<K extends keyof TikTokLiveEvents>(event: K, ...args: Parameters<TikTokLiveEvents[K]>): boolean {\r\n return super.emit(event as string, ...args);\r\n }\r\n\r\n private async handleMessage(raw: any): Promise<void> {\r\n try {\r\n let bytes: Uint8Array;\r\n\r\n if (raw instanceof ArrayBuffer) {\r\n bytes = new Uint8Array(raw);\r\n } else if (raw instanceof Uint8Array) {\r\n bytes = raw;\r\n } else if (typeof Blob !== 'undefined' && raw instanceof Blob) {\r\n bytes = new Uint8Array(await raw.arrayBuffer());\r\n } else if (raw?.buffer instanceof ArrayBuffer) {\r\n bytes = new Uint8Array(raw.buffer, raw.byteOffset, raw.byteLength);\r\n } else {\r\n return;\r\n }\r\n\r\n this.handleFrame(bytes);\r\n } catch { }\r\n }\r\n\r\n private async handleFrame(buf: Uint8Array): Promise<void> {\r\n try {\r\n const fields = decodeProto(buf);\r\n const idField = fields.find(f => f.fn === 2 && f.wt === 0);\r\n const id = idField ? idField.value as bigint : 0n;\r\n const type = getStr(fields, 7);\r\n const binary = getBytes(fields, 8);\r\n\r\n if (id > 0n && this.ws && (this.ws.readyState === 1)) {\r\n const ack = buildAck(id);\r\n this.ws.send(ack.buffer.byteLength === ack.length ? ack.buffer : ack.buffer.slice(ack.byteOffset, ack.byteOffset + ack.byteLength));\r\n }\r\n\r\n if (type === 'msg' && binary && binary.length > 0) {\r\n let inner = binary;\r\n if (inner.length > 2 && inner[0] === 0x1f && inner[1] === 0x8b) {\r\n // Try sync first (fastest, works when zlib is loaded)\r\n const syncResult = gunzipSync(inner);\r\n if (syncResult) {\r\n inner = syncResult;\r\n } else {\r\n // Fallback to async gunzip (uses DecompressionStream or async import)\r\n inner = await gunzip(inner);\r\n }\r\n }\r\n\r\n const events = parseWebcastResponse(inner);\r\n for (const evt of events) {\r\n this._eventCount++;\r\n\r\n if (evt.type === 'battle') {\r\n for (const team of evt.teams) {\r\n const host = team.users.find(u => u.user.id === team.hostUserId);\r\n if (host) {\r\n this._battleHosts.set(team.hostUserId, host.user);\r\n team.hostUser = host.user;\r\n }\r\n }\r\n }\r\n\r\n if (evt.type === 'battleArmies') {\r\n for (const team of evt.teams) {\r\n const host = team.users.find(u => u.user.id === team.hostUserId);\r\n if (host) {\r\n team.hostUser = host.user;\r\n this._battleHosts.set(team.hostUserId, host.user);\r\n } else {\r\n const cached = this._battleHosts.get(team.hostUserId);\r\n if (cached) team.hostUser = cached;\r\n }\r\n }\r\n }\r\n\r\n (this as TypedEmitter).emit('event', evt);\r\n (this as TypedEmitter).emit(evt.type, evt as any);\r\n }\r\n }\r\n } catch { }\r\n }\r\n\r\n private startHeartbeat(roomId: string): void {\r\n this.stopHeartbeat();\r\n this.heartbeatTimer = setInterval(() => {\r\n if (this.ws && this.ws.readyState === 1) {\r\n const hb = buildHeartbeat(roomId);\r\n this.ws.send(hb.buffer.byteLength === hb.length ? hb.buffer : hb.buffer.slice(hb.byteOffset, hb.byteOffset + hb.byteLength));\r\n }\r\n }, this.heartbeatInterval);\r\n }\r\n\r\n private stopHeartbeat(): void {\r\n if (this.heartbeatTimer) {\r\n clearInterval(this.heartbeatTimer);\r\n this.heartbeatTimer = null;\r\n }\r\n }\r\n}\r\n"],"mappings":"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","names":["DEFAULT_UA","DEFAULT_SIGN_SERVER"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/proto.ts","../src/api.ts","../src/client.ts"],"sourcesContent":["export { TikTokLive } from './client.js';\r\nexport { resolveLivePage, resolveRoomId, fetchSignedUrl, callApi, solvePuzzle, solveRotate, solveShapes } from './api.js';\r\nexport type { LivePageInfo, SignedUrlResponse, CallApiOptions } from './api.js';\r\n\r\nexport type {\r\n TikTokLiveOptions,\r\n TikTokLiveEvents,\r\n RoomInfo,\r\n LiveEvent,\r\n BaseEvent,\r\n ChatEvent,\r\n MemberEvent,\r\n LikeEvent,\r\n GiftEvent,\r\n SocialEvent,\r\n RoomUserSeqEvent,\r\n BattleEvent,\r\n BattleArmiesEvent,\r\n BattleTeam,\r\n BattleTeamUser,\r\n SubscribeEvent,\r\n EmoteChatEvent,\r\n EnvelopeEvent,\r\n QuestionEvent,\r\n ControlEvent,\r\n RoomEvent,\r\n LiveIntroEvent,\r\n RankUpdateEvent,\r\n LinkMicEvent,\r\n UnknownEvent,\r\n TikTokUser,\r\n PuzzleSolveResult,\r\n RotateSolveResult,\r\n ShapesSolveResult,\r\n} from './types.js';\r\n","import type { LiveEvent, TikTokUser, BattleTeam, BattleTeamUser } from './types.js';\r\n\r\nconst encoder = new TextEncoder();\r\nconst decoder = new TextDecoder();\r\n\r\nexport function concatBytes(...arrays: Uint8Array[]): Uint8Array {\r\n let totalLength = 0;\r\n for (const arr of arrays) totalLength += arr.length;\r\n const result = new Uint8Array(totalLength);\r\n let offset = 0;\r\n for (const arr of arrays) {\r\n result.set(arr, offset);\r\n offset += arr.length;\r\n }\r\n return result;\r\n}\r\n\r\nfunction readInt32LE(buf: Uint8Array, offset: number): number {\r\n return buf[offset] |\r\n (buf[offset + 1] << 8) |\r\n (buf[offset + 2] << 16) |\r\n (buf[offset + 3] << 24);\r\n}\r\n\r\nfunction readBigInt64LE(buf: Uint8Array, offset: number): bigint {\r\n const lo = BigInt(buf[offset] |\r\n (buf[offset + 1] << 8) |\r\n (buf[offset + 2] << 16) |\r\n ((buf[offset + 3] << 24) >>> 0));\r\n const hi = BigInt(buf[offset + 4] |\r\n (buf[offset + 5] << 8) |\r\n (buf[offset + 6] << 16) |\r\n ((buf[offset + 7] << 24) >>> 0));\r\n return (hi << 32n) | (lo & 0xFFFFFFFFn);\r\n}\r\n\r\nexport function decodeVarint(buf: Uint8Array, offset: number): { value: number; offset: number } {\r\n let result = 0, shift = 0;\r\n while (offset < buf.length) {\r\n const byte = buf[offset++];\r\n result |= (byte & 0x7F) << shift;\r\n if ((byte & 0x80) === 0) break;\r\n shift += 7;\r\n }\r\n return { value: result >>> 0, offset };\r\n}\r\n\r\nexport function decodeVarint64(buf: Uint8Array, offset: number): { value: bigint; offset: number } {\r\n let result = 0n, shift = 0n;\r\n while (offset < buf.length) {\r\n const byte = BigInt(buf[offset++]);\r\n result |= (byte & 0x7Fn) << shift;\r\n if ((byte & 0x80n) === 0n) break;\r\n shift += 7n;\r\n }\r\n return { value: result, offset };\r\n}\r\n\r\nexport function encodeVarint(v: number | bigint): Uint8Array {\r\n const bytes: number[] = [];\r\n let n = typeof v === 'bigint' ? v : BigInt(v);\r\n do {\r\n let b = Number(n & 0x7Fn);\r\n n >>= 7n;\r\n if (n > 0n) b |= 0x80;\r\n bytes.push(b);\r\n } while (n > 0n);\r\n return new Uint8Array(bytes);\r\n}\r\n\r\nexport interface ProtoField {\r\n fn: number;\r\n wt: number;\r\n value: Uint8Array | number | bigint;\r\n}\r\n\r\nexport function encodeField(fn: number, wt: number, value: Uint8Array | bigint | number | string): Uint8Array {\r\n const tag = encodeVarint((fn << 3) | wt);\r\n if (wt === 0) {\r\n return concatBytes(tag, encodeVarint(typeof value === 'number' ? BigInt(value) : value as bigint));\r\n }\r\n const data = typeof value === 'string' ? encoder.encode(value) : value as Uint8Array;\r\n return concatBytes(tag, encodeVarint(data.length), data);\r\n}\r\n\r\nexport function decodeProto(buf: Uint8Array): ProtoField[] {\r\n const fields: ProtoField[] = [];\r\n let offset = 0;\r\n while (offset < buf.length) {\r\n const tagResult = decodeVarint(buf, offset);\r\n offset = tagResult.offset;\r\n const fn = tagResult.value >> 3;\r\n const wt = tagResult.value & 7;\r\n if (wt === 0) {\r\n const r = decodeVarint64(buf, offset);\r\n offset = r.offset;\r\n fields.push({ fn, wt, value: r.value });\r\n } else if (wt === 2) {\r\n const lenR = decodeVarint(buf, offset);\r\n offset = lenR.offset;\r\n const data = buf.subarray(offset, offset + lenR.value);\r\n offset += lenR.value;\r\n fields.push({ fn, wt, value: data });\r\n } else if (wt === 1) {\r\n fields.push({ fn, wt, value: readBigInt64LE(buf, offset) });\r\n offset += 8;\r\n } else if (wt === 5) {\r\n fields.push({ fn, wt, value: BigInt(readInt32LE(buf, offset)) });\r\n offset += 4;\r\n } else {\r\n break;\r\n }\r\n }\r\n return fields;\r\n}\r\n\r\nexport function getStr(fields: ProtoField[], fn: number): string {\r\n const f = fields.find(x => x.fn === fn && x.wt === 2);\r\n return f ? decoder.decode(f.value as Uint8Array) : '';\r\n}\r\n\r\nexport function getBytes(fields: ProtoField[], fn: number): Uint8Array | null {\r\n const f = fields.find(x => x.fn === fn && x.wt === 2);\r\n return f ? f.value as Uint8Array : null;\r\n}\r\n\r\nexport function getInt(fields: ProtoField[], fn: number): number {\r\n const f = fields.find(x => x.fn === fn && x.wt === 0);\r\n return f ? Number(f.value) : 0;\r\n}\r\n\r\nexport function getAllBytes(fields: ProtoField[], fn: number): Uint8Array[] {\r\n return fields.filter(x => x.fn === fn && x.wt === 2).map(x => x.value as Uint8Array);\r\n}\r\n\r\nexport function buildHeartbeat(roomId: string): Uint8Array {\r\n const payload = encodeField(1, 0, BigInt(roomId));\r\n return concatBytes(\r\n encodeField(6, 2, 'pb'),\r\n encodeField(7, 2, 'hb'),\r\n encodeField(8, 2, payload),\r\n );\r\n}\r\n\r\nexport function buildImEnterRoom(roomId: string): Uint8Array {\r\n const inner = concatBytes(\r\n encodeField(1, 0, BigInt(roomId)),\r\n encodeField(4, 0, 12n),\r\n encodeField(5, 2, 'audience'),\r\n encodeField(6, 2, ''),\r\n encodeField(9, 2, ''),\r\n encodeField(10, 2, ''),\r\n );\r\n return concatBytes(\r\n encodeField(6, 2, 'pb'),\r\n encodeField(7, 2, 'im_enter_room'),\r\n encodeField(8, 2, inner),\r\n );\r\n}\r\n\r\nexport function buildAck(id: bigint): Uint8Array {\r\n return concatBytes(\r\n encodeField(2, 0, id),\r\n encodeField(6, 2, 'pb'),\r\n encodeField(7, 2, 'ack'),\r\n );\r\n}\r\n\r\n// NOTE: Army users in WebcastLinkMicArmies use a DIFFERENT layout where\r\n// field 38 contains avatar/image data, NOT uniqueId.\r\n// We detect this by checking if the string looks like a username (short, no URLs).\r\nfunction looksLikeUsername(s: string): boolean {\r\n return s.length > 0 && s.length <= 50 && !s.includes('://') && !s.includes('\\x00');\r\n}\r\n\r\nfunction parseUser(data: Uint8Array): TikTokUser {\r\n const f = decodeProto(data);\r\n const id = String(getInt(f, 1) || getStr(f, 1));\r\n const nickname = getStr(f, 3) || getStr(f, 2);\r\n\r\n // uniqueId: Try field 4 (LinkUser format) first, then field 38 (User format)\r\n // Validate that the result looks like a username, not binary/URL data\r\n let uniqueId = '';\r\n const uid4 = getStr(f, 4);\r\n const uid38 = getStr(f, 38);\r\n if (uid4 && looksLikeUsername(uid4)) {\r\n uniqueId = uid4;\r\n } else if (uid38 && looksLikeUsername(uid38)) {\r\n uniqueId = uid38;\r\n } else {\r\n const uid2 = getStr(f, 2);\r\n if (uid2 && looksLikeUsername(uid2)) uniqueId = uid2;\r\n }\r\n\r\n // profilePicture: Try field 9 (User), field 3 (LinkUser)\r\n // Each should contain a ProfilePicture submessage with repeated urls at field 1\r\n let profilePicture: string | undefined;\r\n const avatarBuf = getBytes(f, 9) || getBytes(f, 3);\r\n if (avatarBuf) {\r\n try {\r\n const avatarFields = decodeProto(avatarBuf);\r\n const urlBufs = getAllBytes(avatarFields, 1);\r\n for (const urlBuf of urlBufs) {\r\n const url = decoder.decode(urlBuf);\r\n if (url.includes('://')) {\r\n profilePicture = url;\r\n break;\r\n }\r\n }\r\n } catch { }\r\n }\r\n\r\n const badges: string[] = [];\r\n const badgeBuf = getBytes(f, 64);\r\n if (badgeBuf) {\r\n try {\r\n const badgeFields = decodeProto(badgeBuf);\r\n const badgeItems = getAllBytes(badgeFields, 21);\r\n for (const bi of badgeItems) {\r\n const bf = decodeProto(bi);\r\n const name = getStr(bf, 3) || getStr(bf, 2);\r\n if (name) badges.push(name);\r\n }\r\n } catch { }\r\n }\r\n\r\n return {\r\n id,\r\n nickname,\r\n uniqueId: uniqueId || nickname || id,\r\n profilePictureUrl: profilePicture,\r\n badges: badges.length > 0 ? badges : undefined,\r\n };\r\n}\r\n\r\nfunction parseBattleTeamFromArmies(itemBuf: Uint8Array): BattleTeam {\r\n const f = decodeProto(itemBuf);\r\n const hostUserId = String(getInt(f, 1));\r\n let teamScore = 0;\r\n const users: BattleTeamUser[] = [];\r\n\r\n const groups = getAllBytes(f, 2);\r\n for (const gb of groups) {\r\n try {\r\n const gf = decodeProto(gb);\r\n const points = getInt(gf, 2);\r\n teamScore += points;\r\n\r\n const userBufs = getAllBytes(gf, 1);\r\n for (const ub of userBufs) {\r\n try {\r\n const user = parseUser(ub);\r\n users.push({ user, score: points });\r\n } catch { }\r\n }\r\n } catch { }\r\n }\r\n\r\n return { hostUserId, score: teamScore, users };\r\n}\r\n\r\nexport function parseWebcastMessage(method: string, payload: Uint8Array): LiveEvent {\r\n const f = decodeProto(payload);\r\n const base = { timestamp: Date.now(), msgId: '' };\r\n\r\n const typeBuf = getBytes(f, 1);\r\n if (typeBuf) {\r\n try {\r\n const tf = decodeProto(typeBuf);\r\n const ts = getInt(tf, 4);\r\n if (ts) base.timestamp = ts;\r\n } catch { }\r\n }\r\n\r\n switch (method) {\r\n case 'WebcastChatMessage': {\r\n const userBuf = getBytes(f, 2);\r\n const user = userBuf ? parseUser(userBuf) : { id: '0', nickname: '', uniqueId: '' };\r\n return { ...base, type: 'chat' as const, user, comment: getStr(f, 3) };\r\n }\r\n\r\n case 'WebcastMemberMessage': {\r\n const userBuf = getBytes(f, 2);\r\n const user = userBuf ? parseUser(userBuf) : { id: '0', nickname: '', uniqueId: '' };\r\n let action = 1;\r\n const eventBuf = getBytes(f, 1);\r\n if (eventBuf) {\r\n const ef = decodeProto(eventBuf);\r\n const detailBuf = getBytes(ef, 8);\r\n if (detailBuf) {\r\n const df = decodeProto(detailBuf);\r\n const label = getStr(df, 2);\r\n if (label.includes('followed')) action = 2;\r\n else if (label.includes('share')) action = 3;\r\n }\r\n }\r\n return { ...base, type: 'member' as const, user, action };\r\n }\r\n\r\n case 'WebcastLikeMessage': {\r\n const userBuf = getBytes(f, 5);\r\n const user = userBuf ? parseUser(userBuf) : { id: '0', nickname: '', uniqueId: '' };\r\n return {\r\n ...base, type: 'like' as const, user,\r\n likeCount: getInt(f, 2),\r\n totalLikes: getInt(f, 3),\r\n };\r\n }\r\n\r\n case 'WebcastGiftMessage': {\r\n const userBuf = getBytes(f, 7);\r\n const user = userBuf ? parseUser(userBuf) : { id: '0', nickname: '', uniqueId: '' };\r\n const giftId = getInt(f, 2);\r\n const repeatCount = getInt(f, 5);\r\n const repeatEnd = getInt(f, 9) === 1;\r\n\r\n let giftName = '', diamondCount = 0, giftType = 0;\r\n let giftImageUrl = '';\r\n const detailsBuf = getBytes(f, 15);\r\n if (detailsBuf) {\r\n const df = decodeProto(detailsBuf);\r\n giftName = getStr(df, 16) || getStr(df, 2);\r\n diamondCount = getInt(df, 12);\r\n giftType = getInt(df, 11);\r\n\r\n const imgBuf = getBytes(df, 1);\r\n if (imgBuf) {\r\n const imgf = decodeProto(imgBuf);\r\n giftImageUrl = getStr(imgf, 1);\r\n }\r\n }\r\n\r\n let toUserId = '';\r\n const extraBuf = getBytes(f, 23);\r\n if (extraBuf) {\r\n const ef = decodeProto(extraBuf);\r\n toUserId = String(getInt(ef, 8));\r\n }\r\n\r\n const groupId = toUserId || getStr(f, 11);\r\n\r\n return {\r\n ...base, type: 'gift' as const, user, giftId, giftName, diamondCount,\r\n repeatCount, repeatEnd, combo: repeatCount > 1 && !repeatEnd,\r\n giftType, groupId, giftPictureUrl: giftImageUrl,\r\n };\r\n }\r\n\r\n case 'WebcastSocialMessage': {\r\n const userBuf = getBytes(f, 2);\r\n const user = userBuf ? parseUser(userBuf) : { id: '0', nickname: '', uniqueId: '' };\r\n let action = 'follow';\r\n const eventBuf = getBytes(f, 1);\r\n if (eventBuf) {\r\n const ef = decodeProto(eventBuf);\r\n const detailBuf = getBytes(ef, 8);\r\n if (detailBuf) {\r\n const df = decodeProto(detailBuf);\r\n const label = getStr(df, 2);\r\n if (label.includes('share')) action = 'share';\r\n else if (label.includes('follow')) action = 'follow';\r\n const displayType = getStr(df, 1);\r\n if (displayType === 'pm_mt_msg_viewer_share') action = 'share';\r\n }\r\n }\r\n return { ...base, type: 'social' as const, user, action };\r\n }\r\n\r\n case 'WebcastRoomUserSeqMessage': {\r\n const viewerCount = getInt(f, 3) || getInt(f, 2);\r\n const totalViewers = getInt(f, 1) || viewerCount;\r\n return { ...base, type: 'roomUserSeq' as const, totalViewers, viewerCount };\r\n }\r\n\r\n case 'WebcastLinkMicBattle': {\r\n const battleId = String(getInt(f, 1) || '');\r\n const status = getInt(f, 2) || 1;\r\n const battleDuration = getInt(f, 3);\r\n const teams: BattleTeam[] = [];\r\n\r\n const battleUserBufs = getAllBytes(f, 10);\r\n for (const bub of battleUserBufs) {\r\n try {\r\n const bf = decodeProto(bub);\r\n const groupBuf = getBytes(bf, 2);\r\n if (groupBuf) {\r\n const gf = decodeProto(groupBuf);\r\n const linkUserBuf = getBytes(gf, 1);\r\n if (linkUserBuf) {\r\n const user = parseUser(linkUserBuf);\r\n teams.push({\r\n hostUserId: user.id,\r\n score: 0,\r\n users: [{ user, score: 0 }],\r\n });\r\n }\r\n }\r\n } catch { }\r\n }\r\n\r\n if (teams.length === 0) {\r\n const teamBufs7 = getAllBytes(f, 7);\r\n for (const tb of teamBufs7) {\r\n try {\r\n teams.push(parseBattleTeamFromArmies(tb));\r\n } catch { }\r\n }\r\n }\r\n\r\n return { ...base, type: 'battle' as const, battleId, status, battleDuration, teams };\r\n }\r\n\r\n case 'WebcastLinkMicArmies': {\r\n const battleId = String(getInt(f, 1) || '');\r\n const battleStatus = getInt(f, 7);\r\n const teams: BattleTeam[] = [];\r\n\r\n const itemBufs = getAllBytes(f, 3);\r\n for (const ib of itemBufs) {\r\n try {\r\n teams.push(parseBattleTeamFromArmies(ib));\r\n } catch { }\r\n }\r\n\r\n return {\r\n ...base, type: 'battleArmies' as const, battleId, teams,\r\n status: battleStatus,\r\n };\r\n }\r\n\r\n case 'WebcastSubNotifyMessage': {\r\n const userBuf = getBytes(f, 2);\r\n const user = userBuf ? parseUser(userBuf) : { id: '0', nickname: '', uniqueId: '' };\r\n return { ...base, type: 'subscribe' as const, user, subMonth: getInt(f, 3) };\r\n }\r\n\r\n case 'WebcastEmoteChatMessage': {\r\n const userBuf = getBytes(f, 2);\r\n const user = userBuf ? parseUser(userBuf) : { id: '0', nickname: '', uniqueId: '' };\r\n let emoteId = '', emoteUrl = '';\r\n const emoteBuf = getBytes(f, 3);\r\n if (emoteBuf) {\r\n const ef = decodeProto(emoteBuf);\r\n emoteId = getStr(ef, 1);\r\n const imageBuf = getBytes(ef, 2);\r\n if (imageBuf) {\r\n const imgFields = decodeProto(imageBuf);\r\n emoteUrl = getStr(imgFields, 1);\r\n }\r\n }\r\n return { ...base, type: 'emoteChat' as const, user, emoteId, emoteUrl };\r\n }\r\n\r\n case 'WebcastEnvelopeMessage': {\r\n const envelopeId = String(getInt(f, 1) || getStr(f, 1));\r\n return { ...base, type: 'envelope' as const, envelopeId, diamondCount: getInt(f, 3) };\r\n }\r\n\r\n case 'WebcastQuestionNewMessage': {\r\n let questionText = '', user: TikTokUser = { id: '0', nickname: '', uniqueId: '' };\r\n const detailBuf = getBytes(f, 2);\r\n if (detailBuf) {\r\n const df = decodeProto(detailBuf);\r\n questionText = getStr(df, 2);\r\n const userBuf = getBytes(df, 5);\r\n if (userBuf) user = parseUser(userBuf);\r\n }\r\n return { ...base, type: 'question' as const, user, questionText };\r\n }\r\n\r\n case 'WebcastRankUpdateMessage':\r\n case 'WebcastHourlyRankMessage': {\r\n const rankType = getStr(f, 1) || `rank_${getInt(f, 1)}`;\r\n const rankList: Array<{ user: TikTokUser; rank: number; score: number }> = [];\r\n const listBufs = getAllBytes(f, 2);\r\n for (const lb of listBufs) {\r\n try {\r\n const rf = decodeProto(lb);\r\n const userBuf = getBytes(rf, 1);\r\n const rank = getInt(rf, 2);\r\n const score = getInt(rf, 3);\r\n const user = userBuf ? parseUser(userBuf) : { id: '0', nickname: '', uniqueId: '' };\r\n rankList.push({ user, rank, score });\r\n } catch { }\r\n }\r\n return { ...base, type: 'rankUpdate' as const, rankType, rankList };\r\n }\r\n\r\n case 'WebcastControlMessage':\r\n return { ...base, type: 'control' as const, action: getInt(f, 2) || getInt(f, 1) };\r\n\r\n case 'WebcastRoomMessage':\r\n case 'RoomMessage':\r\n return { ...base, type: 'room' as const, status: getInt(f, 2) };\r\n\r\n case 'WebcastLiveIntroMessage': {\r\n const roomId = String(getInt(f, 2));\r\n const title = getStr(f, 4) || getStr(f, 2);\r\n return { ...base, type: 'liveIntro' as const, roomId, title };\r\n }\r\n\r\n case 'WebcastLinkMicMethod':\r\n case 'WebcastLinkmicBattleTaskMessage': {\r\n const action = getStr(f, 1) || `action_${getInt(f, 1)}`;\r\n const users: TikTokUser[] = [];\r\n const userBufs = getAllBytes(f, 2);\r\n for (const ub of userBufs) {\r\n try { users.push(parseUser(ub)); } catch { }\r\n }\r\n return { ...base, type: 'linkMic' as const, action, users };\r\n }\r\n\r\n default:\r\n return { ...base, type: 'unknown' as const, method };\r\n }\r\n}\r\n\r\nexport function parseWebcastResponse(payload: Uint8Array): LiveEvent[] {\r\n const events: LiveEvent[] = [];\r\n const respFields = decodeProto(payload);\r\n\r\n for (const mf of respFields.filter(f => f.fn === 1 && f.wt === 2)) {\r\n const msgBuf = mf.value as Uint8Array;\r\n const msgFields = decodeProto(msgBuf);\r\n const method = getStr(msgFields, 1);\r\n const innerPayload = getBytes(msgFields, 2);\r\n if (!method || !innerPayload) continue;\r\n\r\n try {\r\n events.push(parseWebcastMessage(method, innerPayload));\r\n } catch { }\r\n }\r\n\r\n return events;\r\n}\r\n","/**\r\n * TikTool API utilities for the sign-and-return API flow.\r\n *\r\n * The API server returns signed URLs instead of fetching TikTok data directly.\r\n * These utilities handle the two-step flow:\r\n * 1. resolve_required — scrape TikTok HTML to get room_id\r\n * 2. fetch_signed_url — use the signed URL to get actual TikTok data\r\n *\r\n * @module\r\n */\r\n\r\nconst DEFAULT_UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36';\r\nconst DEFAULT_SIGN_SERVER = 'https://api.tik.tools';\r\n\r\nconst pageCache = new Map<string, { info: LivePageInfo; ts: number }>();\r\nconst PAGE_CACHE_TTL = 5 * 60 * 1000;\r\n\r\n/**\r\n * Resolved live page metadata from a TikTok live page.\r\n */\r\nexport interface LivePageInfo {\r\n /** Active room ID for the livestream */\r\n roomId: string;\r\n /** Session cookie required for WebSocket authentication */\r\n ttwid: string;\r\n /** Server cluster region (e.g. 'us', 'eu') */\r\n clusterRegion: string;\r\n}\r\n\r\n/**\r\n * Scrape a TikTok live page to extract room metadata.\r\n * Returns the room ID, session cookie, and cluster region.\r\n * Results are cached for 5 minutes. Returns `null` if the user is not live.\r\n */\r\nexport async function resolveLivePage(uniqueId: string): Promise<LivePageInfo | null> {\r\n const clean = uniqueId.replace(/^@/, '');\r\n const cached = pageCache.get(clean);\r\n if (cached && Date.now() - cached.ts < PAGE_CACHE_TTL) {\r\n return cached.info;\r\n }\r\n\r\n try {\r\n const resp = await fetch(`https://www.tiktok.com/@${clean}/live`, {\r\n headers: {\r\n 'User-Agent': DEFAULT_UA,\r\n 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',\r\n 'Accept-Language': 'en-US,en;q=0.9',\r\n },\r\n redirect: 'follow',\r\n });\r\n\r\n if (!resp.ok) return null;\r\n\r\n // Extract ttwid session cookie\r\n let ttwid = '';\r\n const setCookies = resp.headers.get('set-cookie') || '';\r\n for (const part of setCookies.split(',')) {\r\n const trimmed = part.trim();\r\n if (trimmed.startsWith('ttwid=')) {\r\n ttwid = trimmed.split(';')[0].split('=').slice(1).join('=');\r\n break;\r\n }\r\n }\r\n if (!ttwid && typeof (resp.headers as any).getSetCookie === 'function') {\r\n for (const sc of (resp.headers as any).getSetCookie()) {\r\n if (typeof sc === 'string' && sc.startsWith('ttwid=')) {\r\n ttwid = sc.split(';')[0].split('=').slice(1).join('=');\r\n break;\r\n }\r\n }\r\n }\r\n\r\n const html = await resp.text();\r\n\r\n // Extract roomId from SIGI_STATE JSON block\r\n let roomId = '';\r\n const sigiMatch = html.match(/id=\"SIGI_STATE\"[^>]*>([^<]+)/);\r\n if (sigiMatch) {\r\n try {\r\n const json = JSON.parse(sigiMatch[1]);\r\n const jsonStr = JSON.stringify(json);\r\n const m = jsonStr.match(/\"roomId\"\\s*:\\s*\"(\\d+)\"/);\r\n if (m) roomId = m[1];\r\n } catch { }\r\n }\r\n\r\n // Fallback patterns\r\n if (!roomId) {\r\n const patterns = [\r\n /\"roomId\"\\s*:\\s*\"(\\d+)\"/,\r\n /room_id[=/](\\d{10,})/,\r\n /\"idStr\"\\s*:\\s*\"(\\d{10,})\"/,\r\n ];\r\n for (const p of patterns) {\r\n const m = html.match(p);\r\n if (m) { roomId = m[1]; break; }\r\n }\r\n }\r\n\r\n if (!roomId) return null;\r\n\r\n // Extract cluster region\r\n const crMatch = html.match(/\"clusterRegion\"\\s*:\\s*\"([^\"]+)\"/);\r\n const clusterRegion = crMatch ? crMatch[1] : '';\r\n\r\n const info: LivePageInfo = { roomId, ttwid, clusterRegion };\r\n pageCache.set(clean, { info, ts: Date.now() });\r\n return info;\r\n } catch { }\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * Resolve a TikTok username to a room ID.\r\n * Returns `null` if the user is not currently live.\r\n * Results are cached for 5 minutes.\r\n */\r\nexport async function resolveRoomId(uniqueId: string): Promise<string | null> {\r\n const info = await resolveLivePage(uniqueId);\r\n return info?.roomId ?? null;\r\n}\r\n\r\nexport interface SignedUrlResponse {\r\n status_code: number;\r\n action?: string;\r\n signed_url: string;\r\n headers: Record<string, string>;\r\n cookies: string;\r\n}\r\n\r\n/**\r\n * Execute a signed-URL API response: fetch the signed URL and return the\r\n * parsed JSON data from TikTok.\r\n */\r\nexport async function fetchSignedUrl(response: SignedUrlResponse): Promise<any> {\r\n if (!response.signed_url) {\r\n return null;\r\n }\r\n\r\n const headers: Record<string, string> = { ...(response.headers || {}) };\r\n if (response.cookies) {\r\n headers['Cookie'] = response.cookies;\r\n }\r\n\r\n const resp = await fetch(response.signed_url, { headers, redirect: 'follow' });\r\n const text = await resp.text();\r\n try {\r\n return JSON.parse(text);\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\nexport interface CallApiOptions {\r\n /** API server URL (default: https://api.tik.tools) */\r\n serverUrl?: string;\r\n /** API key for authentication */\r\n apiKey: string;\r\n /** API endpoint path (e.g. '/webcast/room_video') */\r\n endpoint: string;\r\n /** TikTok unique_id to resolve */\r\n uniqueId: string;\r\n /** HTTP method (default: POST) */\r\n method?: 'GET' | 'POST';\r\n /** Additional body fields for POST requests */\r\n extraBody?: Record<string, any>;\r\n}\r\n\r\n/**\r\n * Call a TikTool API endpoint, handling the full\r\n * resolve_required → room_id → signed_url → fetch flow automatically.\r\n *\r\n * Returns the actual TikTok data, or `null` if the user is not live.\r\n */\r\nexport async function callApi(opts: CallApiOptions): Promise<any> {\r\n const serverUrl = (opts.serverUrl || DEFAULT_SIGN_SERVER).replace(/\\/$/, '');\r\n const isGet = opts.method === 'GET';\r\n const ak = encodeURIComponent(opts.apiKey);\r\n\r\n const url1 = isGet\r\n ? `${serverUrl}${opts.endpoint}?apiKey=${ak}&unique_id=${encodeURIComponent(opts.uniqueId)}`\r\n : `${serverUrl}${opts.endpoint}?apiKey=${ak}`;\r\n\r\n const fetchOpts1: RequestInit = isGet\r\n ? {}\r\n : {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ unique_id: opts.uniqueId, ...opts.extraBody }),\r\n };\r\n\r\n const resp1 = await fetch(url1, fetchOpts1);\r\n const data1 = await resp1.json() as any;\r\n\r\n // If the response contains a signed URL to fetch (with or without explicit action),\r\n // follow through and fetch the actual TikTok data\r\n if (data1.signed_url || data1.action === 'fetch_signed_url') {\r\n return fetchSignedUrl(data1);\r\n }\r\n\r\n if (data1.status_code === 0 && data1.action !== 'resolve_required') {\r\n return data1;\r\n }\r\n\r\n if (data1.action === 'resolve_required') {\r\n const roomId = await resolveRoomId(opts.uniqueId);\r\n if (!roomId) return null;\r\n\r\n const url2 = isGet\r\n ? `${serverUrl}${opts.endpoint}?apiKey=${ak}&room_id=${encodeURIComponent(roomId)}`\r\n : `${serverUrl}${opts.endpoint}?apiKey=${ak}`;\r\n\r\n const fetchOpts2: RequestInit = isGet\r\n ? {}\r\n : {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ room_id: roomId, ...opts.extraBody }),\r\n };\r\n\r\n const resp2 = await fetch(url2, fetchOpts2);\r\n const data2 = await resp2.json() as any;\r\n\r\n if (data2.signed_url || data2.action === 'fetch_signed_url') {\r\n return fetchSignedUrl(data2);\r\n }\r\n\r\n return data2;\r\n }\r\n\r\n return data1;\r\n}\r\n\r\n// ── CAPTCHA Solver API ──────────────────────────────────────────────\r\n\r\nimport type { PuzzleSolveResult, RotateSolveResult, ShapesSolveResult } from './types.js';\r\n\r\n/**\r\n * Solve a puzzle (slider) CAPTCHA using the TikTool solver.\r\n *\r\n * @param apiKey - API key for authentication\r\n * @param puzzleB64 - Base64-encoded background image (PNG/JPEG)\r\n * @param pieceB64 - Base64-encoded puzzle piece image (PNG/JPEG)\r\n * @param serverUrl - Custom server URL (default: https://api.tik.tools)\r\n * @returns Solve result with slide position and confidence\r\n */\r\nexport async function solvePuzzle(\r\n apiKey: string,\r\n puzzleB64: string,\r\n pieceB64: string,\r\n serverUrl?: string,\r\n): Promise<PuzzleSolveResult> {\r\n const base = (serverUrl || DEFAULT_SIGN_SERVER).replace(/\\/$/, '');\r\n const resp = await fetch(`${base}/captcha/solve/puzzle?apiKey=${encodeURIComponent(apiKey)}`, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ puzzle: puzzleB64, piece: pieceB64 }),\r\n });\r\n const data = await resp.json() as any;\r\n if (data.status_code !== 0) {\r\n throw new Error(data.error || `Solver failed (status ${data.status_code})`);\r\n }\r\n return data.data as PuzzleSolveResult;\r\n}\r\n\r\n/**\r\n * Solve a rotate (whirl) CAPTCHA using the TikTool solver.\r\n *\r\n * @param apiKey - API key for authentication\r\n * @param outerB64 - Base64-encoded outer ring image (PNG/JPEG)\r\n * @param innerB64 - Base64-encoded inner rotated image (PNG/JPEG)\r\n * @param serverUrl - Custom server URL (default: https://api.tik.tools)\r\n * @returns Solve result with rotation angle and confidence\r\n */\r\nexport async function solveRotate(\r\n apiKey: string,\r\n outerB64: string,\r\n innerB64: string,\r\n serverUrl?: string,\r\n): Promise<RotateSolveResult> {\r\n const base = (serverUrl || DEFAULT_SIGN_SERVER).replace(/\\/$/, '');\r\n const resp = await fetch(`${base}/captcha/solve/rotate?apiKey=${encodeURIComponent(apiKey)}`, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ outer: outerB64, inner: innerB64 }),\r\n });\r\n const data = await resp.json() as any;\r\n if (data.status_code !== 0) {\r\n throw new Error(data.error || `Solver failed (status ${data.status_code})`);\r\n }\r\n return data.data as RotateSolveResult;\r\n}\r\n\r\n/**\r\n * Solve a shapes (3D matching) CAPTCHA using the TikTool solver.\r\n *\r\n * @param apiKey - API key for authentication\r\n * @param imageB64 - Base64-encoded CAPTCHA image with shape grid (PNG/JPEG)\r\n * @param serverUrl - Custom server URL (default: https://api.tik.tools)\r\n * @returns Solve result with two matching shape coordinates and confidence\r\n */\r\nexport async function solveShapes(\r\n apiKey: string,\r\n imageB64: string,\r\n serverUrl?: string,\r\n): Promise<ShapesSolveResult> {\r\n const base = (serverUrl || DEFAULT_SIGN_SERVER).replace(/\\/$/, '');\r\n const resp = await fetch(`${base}/captcha/solve/shapes?apiKey=${encodeURIComponent(apiKey)}`, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ image: imageB64 }),\r\n });\r\n const data = await resp.json() as any;\r\n if (data.status_code !== 0) {\r\n throw new Error(data.error || `Solver failed (status ${data.status_code})`);\r\n }\r\n return data.data as ShapesSolveResult;\r\n}\r\n","import type { TikTokLiveOptions, TikTokLiveEvents, RoomInfo, LiveEvent } from './types.js';\r\nimport {\r\n concatBytes,\r\n decodeProto,\r\n getStr,\r\n getBytes,\r\n buildHeartbeat,\r\n buildImEnterRoom,\r\n buildAck,\r\n parseWebcastResponse,\r\n} from './proto.js';\r\nimport { resolveLivePage } from './api.js';\r\n\r\nconst DEFAULT_UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36';\r\nconst DEFAULT_SIGN_SERVER = 'https://api.tik.tools';\r\n\r\ntype Listener = (...args: any[]) => void;\r\n\r\nclass TypedEmitter {\r\n private _listeners = new Map<string, Listener[]>();\r\n\r\n on(event: string, fn: Listener): this {\r\n const arr = this._listeners.get(event) || [];\r\n arr.push(fn);\r\n this._listeners.set(event, arr);\r\n return this;\r\n }\r\n\r\n once(event: string, fn: Listener): this {\r\n const wrapper: Listener = (...args) => {\r\n this.off(event, wrapper);\r\n fn(...args);\r\n };\r\n return this.on(event, wrapper);\r\n }\r\n\r\n off(event: string, fn: Listener): this {\r\n const arr = this._listeners.get(event);\r\n if (arr) {\r\n this._listeners.set(event, arr.filter(l => l !== fn));\r\n }\r\n return this;\r\n }\r\n\r\n emit(event: string, ...args: any[]): boolean {\r\n const arr = this._listeners.get(event);\r\n if (!arr || arr.length === 0) return false;\r\n for (const fn of [...arr]) fn(...args);\r\n return true;\r\n }\r\n\r\n removeAllListeners(event?: string): this {\r\n if (event) this._listeners.delete(event);\r\n else this._listeners.clear();\r\n return this;\r\n }\r\n}\r\n\r\nasync function gunzip(data: Uint8Array): Promise<Uint8Array> {\r\n if (typeof DecompressionStream !== 'undefined') {\r\n const ds = new DecompressionStream('gzip');\r\n const writer = ds.writable.getWriter();\r\n const reader = ds.readable.getReader();\r\n writer.write(data as any);\r\n writer.close();\r\n const chunks: Uint8Array[] = [];\r\n while (true) {\r\n const { done, value } = await reader.read();\r\n if (done) break;\r\n chunks.push(value);\r\n }\r\n return concatBytes(...chunks);\r\n }\r\n try {\r\n const zlib = await import('zlib');\r\n return new Promise((resolve, reject) => {\r\n zlib.gunzip(data, (err: Error | null, result: Buffer) => {\r\n if (err) reject(err);\r\n else resolve(new Uint8Array(result));\r\n });\r\n });\r\n } catch {\r\n return data;\r\n }\r\n}\r\n\r\n// Pre-cache zlib for sync decompression (require fails in ESM)\r\nlet _zlib: any = null;\r\nlet _zlibLoadAttempted = false;\r\n\r\nasync function ensureZlib(): Promise<any> {\r\n if (_zlib) return _zlib;\r\n if (_zlibLoadAttempted) return null;\r\n _zlibLoadAttempted = true;\r\n try {\r\n _zlib = await import('zlib');\r\n } catch { }\r\n return _zlib;\r\n}\r\n\r\n// Attempt to load zlib eagerly at module init\r\nensureZlib();\r\n\r\nfunction gunzipSync(data: Uint8Array): Uint8Array | null {\r\n if (!_zlib) return null; // Signal that sync decompress is unavailable\r\n try {\r\n return new Uint8Array(_zlib.gunzipSync(data));\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\ntype WebSocketLike = {\r\n readonly readyState: number;\r\n send(data: ArrayBufferLike | string): void;\r\n close(code?: number, reason?: string): void;\r\n onopen: ((ev: any) => void) | null;\r\n onmessage: ((ev: any) => void) | null;\r\n onerror: ((ev: any) => void) | null;\r\n onclose: ((ev: any) => void) | null;\r\n};\r\n\r\ninterface WebSocketConstructor {\r\n new(url: string, protocols?: string | string[]): WebSocketLike;\r\n readonly OPEN: number;\r\n readonly CLOSED: number;\r\n}\r\n\r\nfunction getWsHost(clusterRegion: string): string {\r\n if (!clusterRegion) return 'webcast-ws.tiktok.com';\r\n const r = clusterRegion.toLowerCase();\r\n if (r.startsWith('eu') || r.includes('eu')) return 'webcast-ws.eu.tiktok.com';\r\n if (r.startsWith('us') || r.includes('us')) return 'webcast-ws.us.tiktok.com';\r\n return 'webcast-ws.tiktok.com';\r\n}\r\n\r\nasync function resolveWebSocket(userImpl?: any): Promise<WebSocketConstructor> {\r\n if (userImpl) return userImpl;\r\n\r\n if (typeof globalThis.WebSocket !== 'undefined') {\r\n return globalThis.WebSocket as unknown as WebSocketConstructor;\r\n }\r\n\r\n try {\r\n const ws = await import('ws');\r\n return (ws.default || ws) as unknown as WebSocketConstructor;\r\n } catch {\r\n throw new Error(\r\n 'No WebSocket implementation found. ' +\r\n 'Either use Node.js 22+ (native WebSocket), Cloudflare Workers, or install the \"ws\" package: npm i ws'\r\n );\r\n }\r\n}\r\n\r\nexport class TikTokLive extends TypedEmitter {\r\n private ws: WebSocketLike | null = null;\r\n private heartbeatTimer: ReturnType<typeof setInterval> | null = null;\r\n private reconnectAttempts = 0;\r\n private intentionalClose = false;\r\n private _connected = false;\r\n private _eventCount = 0;\r\n private _roomId = '';\r\n private _battleHosts = new Map<string, { id: string; nickname: string; uniqueId: string; profilePicture?: string }>();\r\n\r\n private readonly uniqueId: string;\r\n private readonly signServerUrl: string;\r\n private readonly apiKey: string;\r\n private readonly autoReconnect: boolean;\r\n private readonly maxReconnectAttempts: number;\r\n private readonly heartbeatInterval: number;\r\n private readonly debug: boolean;\r\n private readonly webSocketImpl?: any;\r\n private WS!: WebSocketConstructor;\r\n\r\n constructor(options: TikTokLiveOptions) {\r\n super();\r\n this.uniqueId = options.uniqueId.replace(/^@/, '');\r\n this.signServerUrl = (options.signServerUrl || DEFAULT_SIGN_SERVER).replace(/\\/$/, '');\r\n if (!options.apiKey) throw new Error('apiKey is required. Get a free key at https://tik.tools');\r\n this.apiKey = options.apiKey;\r\n this.autoReconnect = options.autoReconnect ?? true;\r\n this.maxReconnectAttempts = options.maxReconnectAttempts ?? 5;\r\n this.heartbeatInterval = options.heartbeatInterval ?? 10_000;\r\n this.debug = options.debug ?? false;\r\n this.webSocketImpl = options.webSocketImpl;\r\n }\r\n\r\n async connect(): Promise<void> {\r\n this.intentionalClose = false;\r\n\r\n if (!this.WS) {\r\n this.WS = await resolveWebSocket(this.webSocketImpl);\r\n }\r\n\r\n const pageInfo = await resolveLivePage(this.uniqueId);\r\n if (!pageInfo) throw new Error(`User @${this.uniqueId} is not currently live`);\r\n if (!pageInfo.ttwid) throw new Error('Failed to obtain session cookie');\r\n\r\n const { roomId, ttwid, clusterRegion } = pageInfo;\r\n this._roomId = roomId;\r\n const wsHost = getWsHost(clusterRegion);\r\n\r\n const wsParams = new URLSearchParams({\r\n version_code: '270000', device_platform: 'web', cookie_enabled: 'true',\r\n screen_width: '1920', screen_height: '1080', browser_language: 'en-US',\r\n browser_platform: 'Win32', browser_name: 'Mozilla',\r\n browser_version: DEFAULT_UA.split('Mozilla/')[1] || '5.0',\r\n browser_online: 'true', tz_name: 'Etc/UTC',\r\n app_name: 'tiktok_web', sup_ws_ds_opt: '1', update_version_code: '2.0.0',\r\n compress: 'gzip', webcast_language: 'en', ws_direct: '1', aid: '1988',\r\n live_id: '12', app_language: 'en', client_enter: '1', room_id: roomId,\r\n identity: 'audience', history_comment_count: '6', last_rtt: '0',\r\n heartbeat_duration: '10000', resp_content_type: 'protobuf', did_rule: '3',\r\n });\r\n\r\n const rawWsUrl = `https://${wsHost}/webcast/im/ws_proxy/ws_reuse_supplement/?${wsParams}`;\r\n const signUrl = `${this.signServerUrl}/webcast/sign_url`;\r\n\r\n let wsUrl: string;\r\n try {\r\n const signResp = await fetch(signUrl, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'x-api-key': this.apiKey,\r\n },\r\n body: JSON.stringify({ url: rawWsUrl }),\r\n });\r\n const signData = await signResp.json() as Record<string, any>;\r\n\r\n if (signData.status_code === 0 && signData.data?.signed_url) {\r\n wsUrl = (signData.data.signed_url as string).replace(/^https:\\/\\//, 'wss://');\r\n } else {\r\n wsUrl = rawWsUrl.replace(/^https:\\/\\//, 'wss://');\r\n }\r\n } catch {\r\n wsUrl = rawWsUrl.replace(/^https:\\/\\//, 'wss://');\r\n }\r\n\r\n return new Promise<void>((resolve, reject) => {\r\n const connUrl = wsUrl + (wsUrl.includes('?') ? '&' : '?') + `ttwid=${ttwid}`;\r\n\r\n try {\r\n this.ws = new (this.WS as any)(connUrl, {\r\n headers: {\r\n 'User-Agent': DEFAULT_UA,\r\n 'Cookie': `ttwid=${ttwid}`,\r\n 'Origin': 'https://www.tiktok.com',\r\n },\r\n }) as WebSocketLike;\r\n } catch {\r\n this.ws = new this.WS(connUrl) as WebSocketLike;\r\n }\r\n\r\n const ws = this.ws;\r\n let settled = false;\r\n\r\n ws.onopen = () => {\r\n this._connected = true;\r\n this.reconnectAttempts = 0;\r\n\r\n const hb = buildHeartbeat(roomId);\r\n const enter = buildImEnterRoom(roomId);\r\n ws.send(hb.buffer.byteLength === hb.length ? hb.buffer : hb.buffer.slice(hb.byteOffset, hb.byteOffset + hb.byteLength));\r\n ws.send(enter.buffer.byteLength === enter.length ? enter.buffer : enter.buffer.slice(enter.byteOffset, enter.byteOffset + enter.byteLength));\r\n this.startHeartbeat(roomId);\r\n\r\n const roomInfo: RoomInfo = {\r\n roomId,\r\n wsHost,\r\n clusterRegion,\r\n connectedAt: new Date().toISOString(),\r\n };\r\n\r\n (this as TypedEmitter).emit('connected');\r\n (this as TypedEmitter).emit('roomInfo', roomInfo);\r\n if (!settled) { settled = true; resolve(); }\r\n };\r\n\r\n ws.onmessage = (event: any) => {\r\n const raw = event.data !== undefined ? event.data : event;\r\n this.handleMessage(raw);\r\n };\r\n\r\n ws.onclose = (event: any) => {\r\n this._connected = false;\r\n this.stopHeartbeat();\r\n\r\n const code = event?.code ?? 1006;\r\n const reason = event?.reason ?? '';\r\n (this as TypedEmitter).emit('disconnected', code, reason?.toString?.() || '');\r\n\r\n if (!this.intentionalClose && this.autoReconnect && this.reconnectAttempts < this.maxReconnectAttempts) {\r\n this.reconnectAttempts++;\r\n const delay = Math.min(1000 * Math.pow(2, this.reconnectAttempts - 1), 30_000);\r\n setTimeout(() => this.connect().catch(e => (this as TypedEmitter).emit('error', e)), delay);\r\n }\r\n };\r\n\r\n ws.onerror = (err: any) => {\r\n (this as TypedEmitter).emit('error', err instanceof Error ? err : new Error(String(err?.message || err)));\r\n if (!settled) { settled = true; reject(err); }\r\n };\r\n\r\n setTimeout(() => {\r\n if (!settled) {\r\n settled = true;\r\n ws.close();\r\n reject(new Error('Connection timeout'));\r\n }\r\n }, 15_000);\r\n });\r\n }\r\n\r\n disconnect(): void {\r\n this.intentionalClose = true;\r\n this.stopHeartbeat();\r\n if (this.ws) {\r\n this.ws.close(1000);\r\n this.ws = null;\r\n }\r\n this._connected = false;\r\n }\r\n\r\n get connected(): boolean {\r\n return this._connected;\r\n }\r\n\r\n get eventCount(): number {\r\n return this._eventCount;\r\n }\r\n\r\n get roomId(): string {\r\n return this._roomId;\r\n }\r\n\r\n override on<K extends keyof TikTokLiveEvents>(event: K, listener: TikTokLiveEvents[K]): this {\r\n return super.on(event as string, listener as Listener);\r\n }\r\n\r\n override once<K extends keyof TikTokLiveEvents>(event: K, listener: TikTokLiveEvents[K]): this {\r\n return super.once(event as string, listener as Listener);\r\n }\r\n\r\n override off<K extends keyof TikTokLiveEvents>(event: K, listener: TikTokLiveEvents[K]): this {\r\n return super.off(event as string, listener as Listener);\r\n }\r\n\r\n override emit<K extends keyof TikTokLiveEvents>(event: K, ...args: Parameters<TikTokLiveEvents[K]>): boolean {\r\n return super.emit(event as string, ...args);\r\n }\r\n\r\n private async handleMessage(raw: any): Promise<void> {\r\n try {\r\n let bytes: Uint8Array;\r\n\r\n if (raw instanceof ArrayBuffer) {\r\n bytes = new Uint8Array(raw);\r\n } else if (raw instanceof Uint8Array) {\r\n bytes = raw;\r\n } else if (typeof Blob !== 'undefined' && raw instanceof Blob) {\r\n bytes = new Uint8Array(await raw.arrayBuffer());\r\n } else if (raw?.buffer instanceof ArrayBuffer) {\r\n bytes = new Uint8Array(raw.buffer, raw.byteOffset, raw.byteLength);\r\n } else {\r\n return;\r\n }\r\n\r\n this.handleFrame(bytes);\r\n } catch { }\r\n }\r\n\r\n private async handleFrame(buf: Uint8Array): Promise<void> {\r\n try {\r\n const fields = decodeProto(buf);\r\n const idField = fields.find(f => f.fn === 2 && f.wt === 0);\r\n const id = idField ? idField.value as bigint : 0n;\r\n const type = getStr(fields, 7);\r\n const binary = getBytes(fields, 8);\r\n\r\n if (id > 0n && this.ws && (this.ws.readyState === 1)) {\r\n const ack = buildAck(id);\r\n this.ws.send(ack.buffer.byteLength === ack.length ? ack.buffer : ack.buffer.slice(ack.byteOffset, ack.byteOffset + ack.byteLength));\r\n }\r\n\r\n if (type === 'msg' && binary && binary.length > 0) {\r\n let inner = binary;\r\n if (inner.length > 2 && inner[0] === 0x1f && inner[1] === 0x8b) {\r\n // Try sync first (fastest, works when zlib is loaded)\r\n const syncResult = gunzipSync(inner);\r\n if (syncResult) {\r\n inner = syncResult;\r\n } else {\r\n // Fallback to async gunzip (uses DecompressionStream or async import)\r\n inner = await gunzip(inner);\r\n }\r\n }\r\n\r\n const events = parseWebcastResponse(inner);\r\n for (const evt of events) {\r\n this._eventCount++;\r\n\r\n if (evt.type === 'battle') {\r\n for (const team of evt.teams) {\r\n const host = team.users.find(u => u.user.id === team.hostUserId);\r\n if (host) {\r\n this._battleHosts.set(team.hostUserId, host.user);\r\n team.hostUser = host.user;\r\n }\r\n }\r\n }\r\n\r\n if (evt.type === 'battleArmies') {\r\n for (const team of evt.teams) {\r\n const host = team.users.find(u => u.user.id === team.hostUserId);\r\n if (host) {\r\n team.hostUser = host.user;\r\n this._battleHosts.set(team.hostUserId, host.user);\r\n } else {\r\n const cached = this._battleHosts.get(team.hostUserId);\r\n if (cached) team.hostUser = cached;\r\n }\r\n }\r\n }\r\n\r\n (this as TypedEmitter).emit('event', evt);\r\n (this as TypedEmitter).emit(evt.type, evt as any);\r\n }\r\n }\r\n } catch { }\r\n }\r\n\r\n private startHeartbeat(roomId: string): void {\r\n this.stopHeartbeat();\r\n this.heartbeatTimer = setInterval(() => {\r\n if (this.ws && this.ws.readyState === 1) {\r\n const hb = buildHeartbeat(roomId);\r\n this.ws.send(hb.buffer.byteLength === hb.length ? hb.buffer : hb.buffer.slice(hb.byteOffset, hb.byteOffset + hb.byteLength));\r\n }\r\n }, this.heartbeatInterval);\r\n }\r\n\r\n private stopHeartbeat(): void {\r\n if (this.heartbeatTimer) {\r\n clearInterval(this.heartbeatTimer);\r\n this.heartbeatTimer = null;\r\n }\r\n }\r\n}\r\n"],"mappings":"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","names":["DEFAULT_UA","DEFAULT_SIGN_SERVER"]}
package/dist/index.mjs CHANGED
@@ -134,18 +134,37 @@ function buildAck(id) {
134
134
  encodeField(7, 2, "ack")
135
135
  );
136
136
  }
137
+ function looksLikeUsername(s) {
138
+ return s.length > 0 && s.length <= 50 && !s.includes("://") && !s.includes("\0");
139
+ }
137
140
  function parseUser(data) {
138
141
  const f = decodeProto(data);
139
142
  const id = String(getInt(f, 1) || getStr(f, 1));
140
143
  const nickname = getStr(f, 3) || getStr(f, 2);
141
- const uniqueId = getStr(f, 38) || getStr(f, 4) || getStr(f, 2) || "";
144
+ let uniqueId = "";
145
+ const uid4 = getStr(f, 4);
146
+ const uid38 = getStr(f, 38);
147
+ if (uid4 && looksLikeUsername(uid4)) {
148
+ uniqueId = uid4;
149
+ } else if (uid38 && looksLikeUsername(uid38)) {
150
+ uniqueId = uid38;
151
+ } else {
152
+ const uid2 = getStr(f, 2);
153
+ if (uid2 && looksLikeUsername(uid2)) uniqueId = uid2;
154
+ }
142
155
  let profilePicture;
143
156
  const avatarBuf = getBytes(f, 9) || getBytes(f, 3);
144
157
  if (avatarBuf) {
145
158
  try {
146
159
  const avatarFields = decodeProto(avatarBuf);
147
160
  const urlBufs = getAllBytes(avatarFields, 1);
148
- if (urlBufs.length > 0) profilePicture = decoder.decode(urlBufs[0]);
161
+ for (const urlBuf of urlBufs) {
162
+ const url = decoder.decode(urlBuf);
163
+ if (url.includes("://")) {
164
+ profilePicture = url;
165
+ break;
166
+ }
167
+ }
149
168
  } catch {
150
169
  }
151
170
  }
@@ -590,6 +609,45 @@ async function callApi(opts) {
590
609
  }
591
610
  return data1;
592
611
  }
612
+ async function solvePuzzle(apiKey, puzzleB64, pieceB64, serverUrl) {
613
+ const base = (serverUrl || DEFAULT_SIGN_SERVER).replace(/\/$/, "");
614
+ const resp = await fetch(`${base}/captcha/solve/puzzle?apiKey=${encodeURIComponent(apiKey)}`, {
615
+ method: "POST",
616
+ headers: { "Content-Type": "application/json" },
617
+ body: JSON.stringify({ puzzle: puzzleB64, piece: pieceB64 })
618
+ });
619
+ const data = await resp.json();
620
+ if (data.status_code !== 0) {
621
+ throw new Error(data.error || `Solver failed (status ${data.status_code})`);
622
+ }
623
+ return data.data;
624
+ }
625
+ async function solveRotate(apiKey, outerB64, innerB64, serverUrl) {
626
+ const base = (serverUrl || DEFAULT_SIGN_SERVER).replace(/\/$/, "");
627
+ const resp = await fetch(`${base}/captcha/solve/rotate?apiKey=${encodeURIComponent(apiKey)}`, {
628
+ method: "POST",
629
+ headers: { "Content-Type": "application/json" },
630
+ body: JSON.stringify({ outer: outerB64, inner: innerB64 })
631
+ });
632
+ const data = await resp.json();
633
+ if (data.status_code !== 0) {
634
+ throw new Error(data.error || `Solver failed (status ${data.status_code})`);
635
+ }
636
+ return data.data;
637
+ }
638
+ async function solveShapes(apiKey, imageB64, serverUrl) {
639
+ const base = (serverUrl || DEFAULT_SIGN_SERVER).replace(/\/$/, "");
640
+ const resp = await fetch(`${base}/captcha/solve/shapes?apiKey=${encodeURIComponent(apiKey)}`, {
641
+ method: "POST",
642
+ headers: { "Content-Type": "application/json" },
643
+ body: JSON.stringify({ image: imageB64 })
644
+ });
645
+ const data = await resp.json();
646
+ if (data.status_code !== 0) {
647
+ throw new Error(data.error || `Solver failed (status ${data.status_code})`);
648
+ }
649
+ return data.data;
650
+ }
593
651
 
594
652
  // src/client.ts
595
653
  var DEFAULT_UA2 = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36";
@@ -978,6 +1036,9 @@ export {
978
1036
  callApi,
979
1037
  fetchSignedUrl,
980
1038
  resolveLivePage,
981
- resolveRoomId
1039
+ resolveRoomId,
1040
+ solvePuzzle,
1041
+ solveRotate,
1042
+ solveShapes
982
1043
  };
983
1044
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/proto.ts","../src/api.ts","../src/client.ts"],"sourcesContent":["import type { LiveEvent, TikTokUser, BattleTeam, BattleTeamUser } from './types.js';\r\n\r\nconst encoder = new TextEncoder();\r\nconst decoder = new TextDecoder();\r\n\r\nexport function concatBytes(...arrays: Uint8Array[]): Uint8Array {\r\n let totalLength = 0;\r\n for (const arr of arrays) totalLength += arr.length;\r\n const result = new Uint8Array(totalLength);\r\n let offset = 0;\r\n for (const arr of arrays) {\r\n result.set(arr, offset);\r\n offset += arr.length;\r\n }\r\n return result;\r\n}\r\n\r\nfunction readInt32LE(buf: Uint8Array, offset: number): number {\r\n return buf[offset] |\r\n (buf[offset + 1] << 8) |\r\n (buf[offset + 2] << 16) |\r\n (buf[offset + 3] << 24);\r\n}\r\n\r\nfunction readBigInt64LE(buf: Uint8Array, offset: number): bigint {\r\n const lo = BigInt(buf[offset] |\r\n (buf[offset + 1] << 8) |\r\n (buf[offset + 2] << 16) |\r\n ((buf[offset + 3] << 24) >>> 0));\r\n const hi = BigInt(buf[offset + 4] |\r\n (buf[offset + 5] << 8) |\r\n (buf[offset + 6] << 16) |\r\n ((buf[offset + 7] << 24) >>> 0));\r\n return (hi << 32n) | (lo & 0xFFFFFFFFn);\r\n}\r\n\r\nexport function decodeVarint(buf: Uint8Array, offset: number): { value: number; offset: number } {\r\n let result = 0, shift = 0;\r\n while (offset < buf.length) {\r\n const byte = buf[offset++];\r\n result |= (byte & 0x7F) << shift;\r\n if ((byte & 0x80) === 0) break;\r\n shift += 7;\r\n }\r\n return { value: result >>> 0, offset };\r\n}\r\n\r\nexport function decodeVarint64(buf: Uint8Array, offset: number): { value: bigint; offset: number } {\r\n let result = 0n, shift = 0n;\r\n while (offset < buf.length) {\r\n const byte = BigInt(buf[offset++]);\r\n result |= (byte & 0x7Fn) << shift;\r\n if ((byte & 0x80n) === 0n) break;\r\n shift += 7n;\r\n }\r\n return { value: result, offset };\r\n}\r\n\r\nexport function encodeVarint(v: number | bigint): Uint8Array {\r\n const bytes: number[] = [];\r\n let n = typeof v === 'bigint' ? v : BigInt(v);\r\n do {\r\n let b = Number(n & 0x7Fn);\r\n n >>= 7n;\r\n if (n > 0n) b |= 0x80;\r\n bytes.push(b);\r\n } while (n > 0n);\r\n return new Uint8Array(bytes);\r\n}\r\n\r\nexport interface ProtoField {\r\n fn: number;\r\n wt: number;\r\n value: Uint8Array | number | bigint;\r\n}\r\n\r\nexport function encodeField(fn: number, wt: number, value: Uint8Array | bigint | number | string): Uint8Array {\r\n const tag = encodeVarint((fn << 3) | wt);\r\n if (wt === 0) {\r\n return concatBytes(tag, encodeVarint(typeof value === 'number' ? BigInt(value) : value as bigint));\r\n }\r\n const data = typeof value === 'string' ? encoder.encode(value) : value as Uint8Array;\r\n return concatBytes(tag, encodeVarint(data.length), data);\r\n}\r\n\r\nexport function decodeProto(buf: Uint8Array): ProtoField[] {\r\n const fields: ProtoField[] = [];\r\n let offset = 0;\r\n while (offset < buf.length) {\r\n const tagResult = decodeVarint(buf, offset);\r\n offset = tagResult.offset;\r\n const fn = tagResult.value >> 3;\r\n const wt = tagResult.value & 7;\r\n if (wt === 0) {\r\n const r = decodeVarint64(buf, offset);\r\n offset = r.offset;\r\n fields.push({ fn, wt, value: r.value });\r\n } else if (wt === 2) {\r\n const lenR = decodeVarint(buf, offset);\r\n offset = lenR.offset;\r\n const data = buf.subarray(offset, offset + lenR.value);\r\n offset += lenR.value;\r\n fields.push({ fn, wt, value: data });\r\n } else if (wt === 1) {\r\n fields.push({ fn, wt, value: readBigInt64LE(buf, offset) });\r\n offset += 8;\r\n } else if (wt === 5) {\r\n fields.push({ fn, wt, value: BigInt(readInt32LE(buf, offset)) });\r\n offset += 4;\r\n } else {\r\n break;\r\n }\r\n }\r\n return fields;\r\n}\r\n\r\nexport function getStr(fields: ProtoField[], fn: number): string {\r\n const f = fields.find(x => x.fn === fn && x.wt === 2);\r\n return f ? decoder.decode(f.value as Uint8Array) : '';\r\n}\r\n\r\nexport function getBytes(fields: ProtoField[], fn: number): Uint8Array | null {\r\n const f = fields.find(x => x.fn === fn && x.wt === 2);\r\n return f ? f.value as Uint8Array : null;\r\n}\r\n\r\nexport function getInt(fields: ProtoField[], fn: number): number {\r\n const f = fields.find(x => x.fn === fn && x.wt === 0);\r\n return f ? Number(f.value) : 0;\r\n}\r\n\r\nexport function getAllBytes(fields: ProtoField[], fn: number): Uint8Array[] {\r\n return fields.filter(x => x.fn === fn && x.wt === 2).map(x => x.value as Uint8Array);\r\n}\r\n\r\nexport function buildHeartbeat(roomId: string): Uint8Array {\r\n const payload = encodeField(1, 0, BigInt(roomId));\r\n return concatBytes(\r\n encodeField(6, 2, 'pb'),\r\n encodeField(7, 2, 'hb'),\r\n encodeField(8, 2, payload),\r\n );\r\n}\r\n\r\nexport function buildImEnterRoom(roomId: string): Uint8Array {\r\n const inner = concatBytes(\r\n encodeField(1, 0, BigInt(roomId)),\r\n encodeField(4, 0, 12n),\r\n encodeField(5, 2, 'audience'),\r\n encodeField(6, 2, ''),\r\n encodeField(9, 2, ''),\r\n encodeField(10, 2, ''),\r\n );\r\n return concatBytes(\r\n encodeField(6, 2, 'pb'),\r\n encodeField(7, 2, 'im_enter_room'),\r\n encodeField(8, 2, inner),\r\n );\r\n}\r\n\r\nexport function buildAck(id: bigint): Uint8Array {\r\n return concatBytes(\r\n encodeField(2, 0, id),\r\n encodeField(6, 2, 'pb'),\r\n encodeField(7, 2, 'ack'),\r\n );\r\n}\r\n\r\nfunction parseUser(data: Uint8Array): TikTokUser {\r\n const f = decodeProto(data);\r\n const id = String(getInt(f, 1) || getStr(f, 1));\r\n const nickname = getStr(f, 3) || getStr(f, 2);\r\n const uniqueId = getStr(f, 38) || getStr(f, 4) || getStr(f, 2) || '';\r\n\r\n let profilePicture: string | undefined;\r\n const avatarBuf = getBytes(f, 9) || getBytes(f, 3);\r\n if (avatarBuf) {\r\n try {\r\n const avatarFields = decodeProto(avatarBuf);\r\n const urlBufs = getAllBytes(avatarFields, 1);\r\n if (urlBufs.length > 0) profilePicture = decoder.decode(urlBufs[0]);\r\n } catch { }\r\n }\r\n\r\n const badges: string[] = [];\r\n const badgeBuf = getBytes(f, 64);\r\n if (badgeBuf) {\r\n try {\r\n const badgeFields = decodeProto(badgeBuf);\r\n const badgeItems = getAllBytes(badgeFields, 21);\r\n for (const bi of badgeItems) {\r\n const bf = decodeProto(bi);\r\n const name = getStr(bf, 3) || getStr(bf, 2);\r\n if (name) badges.push(name);\r\n }\r\n } catch { }\r\n }\r\n\r\n return {\r\n id,\r\n nickname,\r\n uniqueId: uniqueId || nickname || id,\r\n profilePictureUrl: profilePicture,\r\n badges: badges.length > 0 ? badges : undefined,\r\n };\r\n}\r\n\r\nfunction parseBattleTeamFromArmies(itemBuf: Uint8Array): BattleTeam {\r\n const f = decodeProto(itemBuf);\r\n const hostUserId = String(getInt(f, 1));\r\n let teamScore = 0;\r\n const users: BattleTeamUser[] = [];\r\n\r\n const groups = getAllBytes(f, 2);\r\n for (const gb of groups) {\r\n try {\r\n const gf = decodeProto(gb);\r\n const points = getInt(gf, 2);\r\n teamScore += points;\r\n\r\n const userBufs = getAllBytes(gf, 1);\r\n for (const ub of userBufs) {\r\n try {\r\n const user = parseUser(ub);\r\n users.push({ user, score: points });\r\n } catch { }\r\n }\r\n } catch { }\r\n }\r\n\r\n return { hostUserId, score: teamScore, users };\r\n}\r\n\r\nexport function parseWebcastMessage(method: string, payload: Uint8Array): LiveEvent {\r\n const f = decodeProto(payload);\r\n const base = { timestamp: Date.now(), msgId: '' };\r\n\r\n const typeBuf = getBytes(f, 1);\r\n if (typeBuf) {\r\n try {\r\n const tf = decodeProto(typeBuf);\r\n const ts = getInt(tf, 4);\r\n if (ts) base.timestamp = ts;\r\n } catch { }\r\n }\r\n\r\n switch (method) {\r\n case 'WebcastChatMessage': {\r\n const userBuf = getBytes(f, 2);\r\n const user = userBuf ? parseUser(userBuf) : { id: '0', nickname: '', uniqueId: '' };\r\n return { ...base, type: 'chat' as const, user, comment: getStr(f, 3) };\r\n }\r\n\r\n case 'WebcastMemberMessage': {\r\n const userBuf = getBytes(f, 2);\r\n const user = userBuf ? parseUser(userBuf) : { id: '0', nickname: '', uniqueId: '' };\r\n let action = 1;\r\n const eventBuf = getBytes(f, 1);\r\n if (eventBuf) {\r\n const ef = decodeProto(eventBuf);\r\n const detailBuf = getBytes(ef, 8);\r\n if (detailBuf) {\r\n const df = decodeProto(detailBuf);\r\n const label = getStr(df, 2);\r\n if (label.includes('followed')) action = 2;\r\n else if (label.includes('share')) action = 3;\r\n }\r\n }\r\n return { ...base, type: 'member' as const, user, action };\r\n }\r\n\r\n case 'WebcastLikeMessage': {\r\n const userBuf = getBytes(f, 5);\r\n const user = userBuf ? parseUser(userBuf) : { id: '0', nickname: '', uniqueId: '' };\r\n return {\r\n ...base, type: 'like' as const, user,\r\n likeCount: getInt(f, 2),\r\n totalLikes: getInt(f, 3),\r\n };\r\n }\r\n\r\n case 'WebcastGiftMessage': {\r\n const userBuf = getBytes(f, 7);\r\n const user = userBuf ? parseUser(userBuf) : { id: '0', nickname: '', uniqueId: '' };\r\n const giftId = getInt(f, 2);\r\n const repeatCount = getInt(f, 5);\r\n const repeatEnd = getInt(f, 9) === 1;\r\n\r\n let giftName = '', diamondCount = 0, giftType = 0;\r\n let giftImageUrl = '';\r\n const detailsBuf = getBytes(f, 15);\r\n if (detailsBuf) {\r\n const df = decodeProto(detailsBuf);\r\n giftName = getStr(df, 16) || getStr(df, 2);\r\n diamondCount = getInt(df, 12);\r\n giftType = getInt(df, 11);\r\n\r\n const imgBuf = getBytes(df, 1);\r\n if (imgBuf) {\r\n const imgf = decodeProto(imgBuf);\r\n giftImageUrl = getStr(imgf, 1);\r\n }\r\n }\r\n\r\n let toUserId = '';\r\n const extraBuf = getBytes(f, 23);\r\n if (extraBuf) {\r\n const ef = decodeProto(extraBuf);\r\n toUserId = String(getInt(ef, 8));\r\n }\r\n\r\n const groupId = toUserId || getStr(f, 11);\r\n\r\n return {\r\n ...base, type: 'gift' as const, user, giftId, giftName, diamondCount,\r\n repeatCount, repeatEnd, combo: repeatCount > 1 && !repeatEnd,\r\n giftType, groupId, giftPictureUrl: giftImageUrl,\r\n };\r\n }\r\n\r\n case 'WebcastSocialMessage': {\r\n const userBuf = getBytes(f, 2);\r\n const user = userBuf ? parseUser(userBuf) : { id: '0', nickname: '', uniqueId: '' };\r\n let action = 'follow';\r\n const eventBuf = getBytes(f, 1);\r\n if (eventBuf) {\r\n const ef = decodeProto(eventBuf);\r\n const detailBuf = getBytes(ef, 8);\r\n if (detailBuf) {\r\n const df = decodeProto(detailBuf);\r\n const label = getStr(df, 2);\r\n if (label.includes('share')) action = 'share';\r\n else if (label.includes('follow')) action = 'follow';\r\n const displayType = getStr(df, 1);\r\n if (displayType === 'pm_mt_msg_viewer_share') action = 'share';\r\n }\r\n }\r\n return { ...base, type: 'social' as const, user, action };\r\n }\r\n\r\n case 'WebcastRoomUserSeqMessage': {\r\n const viewerCount = getInt(f, 3) || getInt(f, 2);\r\n const totalViewers = getInt(f, 1) || viewerCount;\r\n return { ...base, type: 'roomUserSeq' as const, totalViewers, viewerCount };\r\n }\r\n\r\n case 'WebcastLinkMicBattle': {\r\n const battleId = String(getInt(f, 1) || '');\r\n const status = getInt(f, 2) || 1;\r\n const battleDuration = getInt(f, 3);\r\n const teams: BattleTeam[] = [];\r\n\r\n const battleUserBufs = getAllBytes(f, 10);\r\n for (const bub of battleUserBufs) {\r\n try {\r\n const bf = decodeProto(bub);\r\n const groupBuf = getBytes(bf, 2);\r\n if (groupBuf) {\r\n const gf = decodeProto(groupBuf);\r\n const linkUserBuf = getBytes(gf, 1);\r\n if (linkUserBuf) {\r\n const user = parseUser(linkUserBuf);\r\n teams.push({\r\n hostUserId: user.id,\r\n score: 0,\r\n users: [{ user, score: 0 }],\r\n });\r\n }\r\n }\r\n } catch { }\r\n }\r\n\r\n if (teams.length === 0) {\r\n const teamBufs7 = getAllBytes(f, 7);\r\n for (const tb of teamBufs7) {\r\n try {\r\n teams.push(parseBattleTeamFromArmies(tb));\r\n } catch { }\r\n }\r\n }\r\n\r\n return { ...base, type: 'battle' as const, battleId, status, battleDuration, teams };\r\n }\r\n\r\n case 'WebcastLinkMicArmies': {\r\n const battleId = String(getInt(f, 1) || '');\r\n const battleStatus = getInt(f, 7);\r\n const teams: BattleTeam[] = [];\r\n\r\n const itemBufs = getAllBytes(f, 3);\r\n for (const ib of itemBufs) {\r\n try {\r\n teams.push(parseBattleTeamFromArmies(ib));\r\n } catch { }\r\n }\r\n\r\n return {\r\n ...base, type: 'battleArmies' as const, battleId, teams,\r\n status: battleStatus,\r\n };\r\n }\r\n\r\n case 'WebcastSubNotifyMessage': {\r\n const userBuf = getBytes(f, 2);\r\n const user = userBuf ? parseUser(userBuf) : { id: '0', nickname: '', uniqueId: '' };\r\n return { ...base, type: 'subscribe' as const, user, subMonth: getInt(f, 3) };\r\n }\r\n\r\n case 'WebcastEmoteChatMessage': {\r\n const userBuf = getBytes(f, 2);\r\n const user = userBuf ? parseUser(userBuf) : { id: '0', nickname: '', uniqueId: '' };\r\n let emoteId = '', emoteUrl = '';\r\n const emoteBuf = getBytes(f, 3);\r\n if (emoteBuf) {\r\n const ef = decodeProto(emoteBuf);\r\n emoteId = getStr(ef, 1);\r\n const imageBuf = getBytes(ef, 2);\r\n if (imageBuf) {\r\n const imgFields = decodeProto(imageBuf);\r\n emoteUrl = getStr(imgFields, 1);\r\n }\r\n }\r\n return { ...base, type: 'emoteChat' as const, user, emoteId, emoteUrl };\r\n }\r\n\r\n case 'WebcastEnvelopeMessage': {\r\n const envelopeId = String(getInt(f, 1) || getStr(f, 1));\r\n return { ...base, type: 'envelope' as const, envelopeId, diamondCount: getInt(f, 3) };\r\n }\r\n\r\n case 'WebcastQuestionNewMessage': {\r\n let questionText = '', user: TikTokUser = { id: '0', nickname: '', uniqueId: '' };\r\n const detailBuf = getBytes(f, 2);\r\n if (detailBuf) {\r\n const df = decodeProto(detailBuf);\r\n questionText = getStr(df, 2);\r\n const userBuf = getBytes(df, 5);\r\n if (userBuf) user = parseUser(userBuf);\r\n }\r\n return { ...base, type: 'question' as const, user, questionText };\r\n }\r\n\r\n case 'WebcastRankUpdateMessage':\r\n case 'WebcastHourlyRankMessage': {\r\n const rankType = getStr(f, 1) || `rank_${getInt(f, 1)}`;\r\n const rankList: Array<{ user: TikTokUser; rank: number; score: number }> = [];\r\n const listBufs = getAllBytes(f, 2);\r\n for (const lb of listBufs) {\r\n try {\r\n const rf = decodeProto(lb);\r\n const userBuf = getBytes(rf, 1);\r\n const rank = getInt(rf, 2);\r\n const score = getInt(rf, 3);\r\n const user = userBuf ? parseUser(userBuf) : { id: '0', nickname: '', uniqueId: '' };\r\n rankList.push({ user, rank, score });\r\n } catch { }\r\n }\r\n return { ...base, type: 'rankUpdate' as const, rankType, rankList };\r\n }\r\n\r\n case 'WebcastControlMessage':\r\n return { ...base, type: 'control' as const, action: getInt(f, 2) || getInt(f, 1) };\r\n\r\n case 'WebcastRoomMessage':\r\n case 'RoomMessage':\r\n return { ...base, type: 'room' as const, status: getInt(f, 2) };\r\n\r\n case 'WebcastLiveIntroMessage': {\r\n const roomId = String(getInt(f, 2));\r\n const title = getStr(f, 4) || getStr(f, 2);\r\n return { ...base, type: 'liveIntro' as const, roomId, title };\r\n }\r\n\r\n case 'WebcastLinkMicMethod':\r\n case 'WebcastLinkmicBattleTaskMessage': {\r\n const action = getStr(f, 1) || `action_${getInt(f, 1)}`;\r\n const users: TikTokUser[] = [];\r\n const userBufs = getAllBytes(f, 2);\r\n for (const ub of userBufs) {\r\n try { users.push(parseUser(ub)); } catch { }\r\n }\r\n return { ...base, type: 'linkMic' as const, action, users };\r\n }\r\n\r\n default:\r\n return { ...base, type: 'unknown' as const, method };\r\n }\r\n}\r\n\r\nexport function parseWebcastResponse(payload: Uint8Array): LiveEvent[] {\r\n const events: LiveEvent[] = [];\r\n const respFields = decodeProto(payload);\r\n\r\n for (const mf of respFields.filter(f => f.fn === 1 && f.wt === 2)) {\r\n const msgBuf = mf.value as Uint8Array;\r\n const msgFields = decodeProto(msgBuf);\r\n const method = getStr(msgFields, 1);\r\n const innerPayload = getBytes(msgFields, 2);\r\n if (!method || !innerPayload) continue;\r\n\r\n try {\r\n events.push(parseWebcastMessage(method, innerPayload));\r\n } catch { }\r\n }\r\n\r\n return events;\r\n}\r\n","/**\r\n * TikTool API utilities for the sign-and-return API flow.\r\n *\r\n * The API server returns signed URLs instead of fetching TikTok data directly.\r\n * These utilities handle the two-step flow:\r\n * 1. resolve_required — scrape TikTok HTML to get room_id\r\n * 2. fetch_signed_url — use the signed URL to get actual TikTok data\r\n *\r\n * @module\r\n */\r\n\r\nconst DEFAULT_UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36';\r\nconst DEFAULT_SIGN_SERVER = 'https://api.tik.tools';\r\n\r\nconst pageCache = new Map<string, { info: LivePageInfo; ts: number }>();\r\nconst PAGE_CACHE_TTL = 5 * 60 * 1000;\r\n\r\n/**\r\n * Resolved live page metadata from a TikTok live page.\r\n */\r\nexport interface LivePageInfo {\r\n /** Active room ID for the livestream */\r\n roomId: string;\r\n /** Session cookie required for WebSocket authentication */\r\n ttwid: string;\r\n /** Server cluster region (e.g. 'us', 'eu') */\r\n clusterRegion: string;\r\n}\r\n\r\n/**\r\n * Scrape a TikTok live page to extract room metadata.\r\n * Returns the room ID, session cookie, and cluster region.\r\n * Results are cached for 5 minutes. Returns `null` if the user is not live.\r\n */\r\nexport async function resolveLivePage(uniqueId: string): Promise<LivePageInfo | null> {\r\n const clean = uniqueId.replace(/^@/, '');\r\n const cached = pageCache.get(clean);\r\n if (cached && Date.now() - cached.ts < PAGE_CACHE_TTL) {\r\n return cached.info;\r\n }\r\n\r\n try {\r\n const resp = await fetch(`https://www.tiktok.com/@${clean}/live`, {\r\n headers: {\r\n 'User-Agent': DEFAULT_UA,\r\n 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',\r\n 'Accept-Language': 'en-US,en;q=0.9',\r\n },\r\n redirect: 'follow',\r\n });\r\n\r\n if (!resp.ok) return null;\r\n\r\n // Extract ttwid session cookie\r\n let ttwid = '';\r\n const setCookies = resp.headers.get('set-cookie') || '';\r\n for (const part of setCookies.split(',')) {\r\n const trimmed = part.trim();\r\n if (trimmed.startsWith('ttwid=')) {\r\n ttwid = trimmed.split(';')[0].split('=').slice(1).join('=');\r\n break;\r\n }\r\n }\r\n if (!ttwid && typeof (resp.headers as any).getSetCookie === 'function') {\r\n for (const sc of (resp.headers as any).getSetCookie()) {\r\n if (typeof sc === 'string' && sc.startsWith('ttwid=')) {\r\n ttwid = sc.split(';')[0].split('=').slice(1).join('=');\r\n break;\r\n }\r\n }\r\n }\r\n\r\n const html = await resp.text();\r\n\r\n // Extract roomId from SIGI_STATE JSON block\r\n let roomId = '';\r\n const sigiMatch = html.match(/id=\"SIGI_STATE\"[^>]*>([^<]+)/);\r\n if (sigiMatch) {\r\n try {\r\n const json = JSON.parse(sigiMatch[1]);\r\n const jsonStr = JSON.stringify(json);\r\n const m = jsonStr.match(/\"roomId\"\\s*:\\s*\"(\\d+)\"/);\r\n if (m) roomId = m[1];\r\n } catch { }\r\n }\r\n\r\n // Fallback patterns\r\n if (!roomId) {\r\n const patterns = [\r\n /\"roomId\"\\s*:\\s*\"(\\d+)\"/,\r\n /room_id[=/](\\d{10,})/,\r\n /\"idStr\"\\s*:\\s*\"(\\d{10,})\"/,\r\n ];\r\n for (const p of patterns) {\r\n const m = html.match(p);\r\n if (m) { roomId = m[1]; break; }\r\n }\r\n }\r\n\r\n if (!roomId) return null;\r\n\r\n // Extract cluster region\r\n const crMatch = html.match(/\"clusterRegion\"\\s*:\\s*\"([^\"]+)\"/);\r\n const clusterRegion = crMatch ? crMatch[1] : '';\r\n\r\n const info: LivePageInfo = { roomId, ttwid, clusterRegion };\r\n pageCache.set(clean, { info, ts: Date.now() });\r\n return info;\r\n } catch { }\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * Resolve a TikTok username to a room ID.\r\n * Returns `null` if the user is not currently live.\r\n * Results are cached for 5 minutes.\r\n */\r\nexport async function resolveRoomId(uniqueId: string): Promise<string | null> {\r\n const info = await resolveLivePage(uniqueId);\r\n return info?.roomId ?? null;\r\n}\r\n\r\nexport interface SignedUrlResponse {\r\n status_code: number;\r\n action?: string;\r\n signed_url: string;\r\n headers: Record<string, string>;\r\n cookies: string;\r\n}\r\n\r\n/**\r\n * Execute a signed-URL API response: fetch the signed URL and return the\r\n * parsed JSON data from TikTok.\r\n */\r\nexport async function fetchSignedUrl(response: SignedUrlResponse): Promise<any> {\r\n if (!response.signed_url) {\r\n return null;\r\n }\r\n\r\n const headers: Record<string, string> = { ...(response.headers || {}) };\r\n if (response.cookies) {\r\n headers['Cookie'] = response.cookies;\r\n }\r\n\r\n const resp = await fetch(response.signed_url, { headers, redirect: 'follow' });\r\n const text = await resp.text();\r\n try {\r\n return JSON.parse(text);\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\nexport interface CallApiOptions {\r\n /** API server URL (default: https://api.tik.tools) */\r\n serverUrl?: string;\r\n /** API key for authentication */\r\n apiKey: string;\r\n /** API endpoint path (e.g. '/webcast/room_video') */\r\n endpoint: string;\r\n /** TikTok unique_id to resolve */\r\n uniqueId: string;\r\n /** HTTP method (default: POST) */\r\n method?: 'GET' | 'POST';\r\n /** Additional body fields for POST requests */\r\n extraBody?: Record<string, any>;\r\n}\r\n\r\n/**\r\n * Call a TikTool API endpoint, handling the full\r\n * resolve_required → room_id → signed_url → fetch flow automatically.\r\n *\r\n * Returns the actual TikTok data, or `null` if the user is not live.\r\n */\r\nexport async function callApi(opts: CallApiOptions): Promise<any> {\r\n const serverUrl = (opts.serverUrl || DEFAULT_SIGN_SERVER).replace(/\\/$/, '');\r\n const isGet = opts.method === 'GET';\r\n const ak = encodeURIComponent(opts.apiKey);\r\n\r\n const url1 = isGet\r\n ? `${serverUrl}${opts.endpoint}?apiKey=${ak}&unique_id=${encodeURIComponent(opts.uniqueId)}`\r\n : `${serverUrl}${opts.endpoint}?apiKey=${ak}`;\r\n\r\n const fetchOpts1: RequestInit = isGet\r\n ? {}\r\n : {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ unique_id: opts.uniqueId, ...opts.extraBody }),\r\n };\r\n\r\n const resp1 = await fetch(url1, fetchOpts1);\r\n const data1 = await resp1.json() as any;\r\n\r\n // If the response contains a signed URL to fetch (with or without explicit action),\r\n // follow through and fetch the actual TikTok data\r\n if (data1.signed_url || data1.action === 'fetch_signed_url') {\r\n return fetchSignedUrl(data1);\r\n }\r\n\r\n if (data1.status_code === 0 && data1.action !== 'resolve_required') {\r\n return data1;\r\n }\r\n\r\n if (data1.action === 'resolve_required') {\r\n const roomId = await resolveRoomId(opts.uniqueId);\r\n if (!roomId) return null;\r\n\r\n const url2 = isGet\r\n ? `${serverUrl}${opts.endpoint}?apiKey=${ak}&room_id=${encodeURIComponent(roomId)}`\r\n : `${serverUrl}${opts.endpoint}?apiKey=${ak}`;\r\n\r\n const fetchOpts2: RequestInit = isGet\r\n ? {}\r\n : {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ room_id: roomId, ...opts.extraBody }),\r\n };\r\n\r\n const resp2 = await fetch(url2, fetchOpts2);\r\n const data2 = await resp2.json() as any;\r\n\r\n if (data2.signed_url || data2.action === 'fetch_signed_url') {\r\n return fetchSignedUrl(data2);\r\n }\r\n\r\n return data2;\r\n }\r\n\r\n return data1;\r\n}\r\n","import type { TikTokLiveOptions, TikTokLiveEvents, RoomInfo, LiveEvent } from './types.js';\r\nimport {\r\n concatBytes,\r\n decodeProto,\r\n getStr,\r\n getBytes,\r\n buildHeartbeat,\r\n buildImEnterRoom,\r\n buildAck,\r\n parseWebcastResponse,\r\n} from './proto.js';\r\nimport { resolveLivePage } from './api.js';\r\n\r\nconst DEFAULT_UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36';\r\nconst DEFAULT_SIGN_SERVER = 'https://api.tik.tools';\r\n\r\ntype Listener = (...args: any[]) => void;\r\n\r\nclass TypedEmitter {\r\n private _listeners = new Map<string, Listener[]>();\r\n\r\n on(event: string, fn: Listener): this {\r\n const arr = this._listeners.get(event) || [];\r\n arr.push(fn);\r\n this._listeners.set(event, arr);\r\n return this;\r\n }\r\n\r\n once(event: string, fn: Listener): this {\r\n const wrapper: Listener = (...args) => {\r\n this.off(event, wrapper);\r\n fn(...args);\r\n };\r\n return this.on(event, wrapper);\r\n }\r\n\r\n off(event: string, fn: Listener): this {\r\n const arr = this._listeners.get(event);\r\n if (arr) {\r\n this._listeners.set(event, arr.filter(l => l !== fn));\r\n }\r\n return this;\r\n }\r\n\r\n emit(event: string, ...args: any[]): boolean {\r\n const arr = this._listeners.get(event);\r\n if (!arr || arr.length === 0) return false;\r\n for (const fn of [...arr]) fn(...args);\r\n return true;\r\n }\r\n\r\n removeAllListeners(event?: string): this {\r\n if (event) this._listeners.delete(event);\r\n else this._listeners.clear();\r\n return this;\r\n }\r\n}\r\n\r\nasync function gunzip(data: Uint8Array): Promise<Uint8Array> {\r\n if (typeof DecompressionStream !== 'undefined') {\r\n const ds = new DecompressionStream('gzip');\r\n const writer = ds.writable.getWriter();\r\n const reader = ds.readable.getReader();\r\n writer.write(data as any);\r\n writer.close();\r\n const chunks: Uint8Array[] = [];\r\n while (true) {\r\n const { done, value } = await reader.read();\r\n if (done) break;\r\n chunks.push(value);\r\n }\r\n return concatBytes(...chunks);\r\n }\r\n try {\r\n const zlib = await import('zlib');\r\n return new Promise((resolve, reject) => {\r\n zlib.gunzip(data, (err: Error | null, result: Buffer) => {\r\n if (err) reject(err);\r\n else resolve(new Uint8Array(result));\r\n });\r\n });\r\n } catch {\r\n return data;\r\n }\r\n}\r\n\r\n// Pre-cache zlib for sync decompression (require fails in ESM)\r\nlet _zlib: any = null;\r\nlet _zlibLoadAttempted = false;\r\n\r\nasync function ensureZlib(): Promise<any> {\r\n if (_zlib) return _zlib;\r\n if (_zlibLoadAttempted) return null;\r\n _zlibLoadAttempted = true;\r\n try {\r\n _zlib = await import('zlib');\r\n } catch { }\r\n return _zlib;\r\n}\r\n\r\n// Attempt to load zlib eagerly at module init\r\nensureZlib();\r\n\r\nfunction gunzipSync(data: Uint8Array): Uint8Array | null {\r\n if (!_zlib) return null; // Signal that sync decompress is unavailable\r\n try {\r\n return new Uint8Array(_zlib.gunzipSync(data));\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\ntype WebSocketLike = {\r\n readonly readyState: number;\r\n send(data: ArrayBufferLike | string): void;\r\n close(code?: number, reason?: string): void;\r\n onopen: ((ev: any) => void) | null;\r\n onmessage: ((ev: any) => void) | null;\r\n onerror: ((ev: any) => void) | null;\r\n onclose: ((ev: any) => void) | null;\r\n};\r\n\r\ninterface WebSocketConstructor {\r\n new(url: string, protocols?: string | string[]): WebSocketLike;\r\n readonly OPEN: number;\r\n readonly CLOSED: number;\r\n}\r\n\r\nfunction getWsHost(clusterRegion: string): string {\r\n if (!clusterRegion) return 'webcast-ws.tiktok.com';\r\n const r = clusterRegion.toLowerCase();\r\n if (r.startsWith('eu') || r.includes('eu')) return 'webcast-ws.eu.tiktok.com';\r\n if (r.startsWith('us') || r.includes('us')) return 'webcast-ws.us.tiktok.com';\r\n return 'webcast-ws.tiktok.com';\r\n}\r\n\r\nasync function resolveWebSocket(userImpl?: any): Promise<WebSocketConstructor> {\r\n if (userImpl) return userImpl;\r\n\r\n if (typeof globalThis.WebSocket !== 'undefined') {\r\n return globalThis.WebSocket as unknown as WebSocketConstructor;\r\n }\r\n\r\n try {\r\n const ws = await import('ws');\r\n return (ws.default || ws) as unknown as WebSocketConstructor;\r\n } catch {\r\n throw new Error(\r\n 'No WebSocket implementation found. ' +\r\n 'Either use Node.js 22+ (native WebSocket), Cloudflare Workers, or install the \"ws\" package: npm i ws'\r\n );\r\n }\r\n}\r\n\r\nexport class TikTokLive extends TypedEmitter {\r\n private ws: WebSocketLike | null = null;\r\n private heartbeatTimer: ReturnType<typeof setInterval> | null = null;\r\n private reconnectAttempts = 0;\r\n private intentionalClose = false;\r\n private _connected = false;\r\n private _eventCount = 0;\r\n private _roomId = '';\r\n private _battleHosts = new Map<string, { id: string; nickname: string; uniqueId: string; profilePicture?: string }>();\r\n\r\n private readonly uniqueId: string;\r\n private readonly signServerUrl: string;\r\n private readonly apiKey: string;\r\n private readonly autoReconnect: boolean;\r\n private readonly maxReconnectAttempts: number;\r\n private readonly heartbeatInterval: number;\r\n private readonly debug: boolean;\r\n private readonly webSocketImpl?: any;\r\n private WS!: WebSocketConstructor;\r\n\r\n constructor(options: TikTokLiveOptions) {\r\n super();\r\n this.uniqueId = options.uniqueId.replace(/^@/, '');\r\n this.signServerUrl = (options.signServerUrl || DEFAULT_SIGN_SERVER).replace(/\\/$/, '');\r\n if (!options.apiKey) throw new Error('apiKey is required. Get a free key at https://tik.tools');\r\n this.apiKey = options.apiKey;\r\n this.autoReconnect = options.autoReconnect ?? true;\r\n this.maxReconnectAttempts = options.maxReconnectAttempts ?? 5;\r\n this.heartbeatInterval = options.heartbeatInterval ?? 10_000;\r\n this.debug = options.debug ?? false;\r\n this.webSocketImpl = options.webSocketImpl;\r\n }\r\n\r\n async connect(): Promise<void> {\r\n this.intentionalClose = false;\r\n\r\n if (!this.WS) {\r\n this.WS = await resolveWebSocket(this.webSocketImpl);\r\n }\r\n\r\n const pageInfo = await resolveLivePage(this.uniqueId);\r\n if (!pageInfo) throw new Error(`User @${this.uniqueId} is not currently live`);\r\n if (!pageInfo.ttwid) throw new Error('Failed to obtain session cookie');\r\n\r\n const { roomId, ttwid, clusterRegion } = pageInfo;\r\n this._roomId = roomId;\r\n const wsHost = getWsHost(clusterRegion);\r\n\r\n const wsParams = new URLSearchParams({\r\n version_code: '270000', device_platform: 'web', cookie_enabled: 'true',\r\n screen_width: '1920', screen_height: '1080', browser_language: 'en-US',\r\n browser_platform: 'Win32', browser_name: 'Mozilla',\r\n browser_version: DEFAULT_UA.split('Mozilla/')[1] || '5.0',\r\n browser_online: 'true', tz_name: 'Etc/UTC',\r\n app_name: 'tiktok_web', sup_ws_ds_opt: '1', update_version_code: '2.0.0',\r\n compress: 'gzip', webcast_language: 'en', ws_direct: '1', aid: '1988',\r\n live_id: '12', app_language: 'en', client_enter: '1', room_id: roomId,\r\n identity: 'audience', history_comment_count: '6', last_rtt: '0',\r\n heartbeat_duration: '10000', resp_content_type: 'protobuf', did_rule: '3',\r\n });\r\n\r\n const rawWsUrl = `https://${wsHost}/webcast/im/ws_proxy/ws_reuse_supplement/?${wsParams}`;\r\n const signUrl = `${this.signServerUrl}/webcast/sign_url`;\r\n\r\n let wsUrl: string;\r\n try {\r\n const signResp = await fetch(signUrl, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'x-api-key': this.apiKey,\r\n },\r\n body: JSON.stringify({ url: rawWsUrl }),\r\n });\r\n const signData = await signResp.json() as Record<string, any>;\r\n\r\n if (signData.status_code === 0 && signData.data?.signed_url) {\r\n wsUrl = (signData.data.signed_url as string).replace(/^https:\\/\\//, 'wss://');\r\n } else {\r\n wsUrl = rawWsUrl.replace(/^https:\\/\\//, 'wss://');\r\n }\r\n } catch {\r\n wsUrl = rawWsUrl.replace(/^https:\\/\\//, 'wss://');\r\n }\r\n\r\n return new Promise<void>((resolve, reject) => {\r\n const connUrl = wsUrl + (wsUrl.includes('?') ? '&' : '?') + `ttwid=${ttwid}`;\r\n\r\n try {\r\n this.ws = new (this.WS as any)(connUrl, {\r\n headers: {\r\n 'User-Agent': DEFAULT_UA,\r\n 'Cookie': `ttwid=${ttwid}`,\r\n 'Origin': 'https://www.tiktok.com',\r\n },\r\n }) as WebSocketLike;\r\n } catch {\r\n this.ws = new this.WS(connUrl) as WebSocketLike;\r\n }\r\n\r\n const ws = this.ws;\r\n let settled = false;\r\n\r\n ws.onopen = () => {\r\n this._connected = true;\r\n this.reconnectAttempts = 0;\r\n\r\n const hb = buildHeartbeat(roomId);\r\n const enter = buildImEnterRoom(roomId);\r\n ws.send(hb.buffer.byteLength === hb.length ? hb.buffer : hb.buffer.slice(hb.byteOffset, hb.byteOffset + hb.byteLength));\r\n ws.send(enter.buffer.byteLength === enter.length ? enter.buffer : enter.buffer.slice(enter.byteOffset, enter.byteOffset + enter.byteLength));\r\n this.startHeartbeat(roomId);\r\n\r\n const roomInfo: RoomInfo = {\r\n roomId,\r\n wsHost,\r\n clusterRegion,\r\n connectedAt: new Date().toISOString(),\r\n };\r\n\r\n (this as TypedEmitter).emit('connected');\r\n (this as TypedEmitter).emit('roomInfo', roomInfo);\r\n if (!settled) { settled = true; resolve(); }\r\n };\r\n\r\n ws.onmessage = (event: any) => {\r\n const raw = event.data !== undefined ? event.data : event;\r\n this.handleMessage(raw);\r\n };\r\n\r\n ws.onclose = (event: any) => {\r\n this._connected = false;\r\n this.stopHeartbeat();\r\n\r\n const code = event?.code ?? 1006;\r\n const reason = event?.reason ?? '';\r\n (this as TypedEmitter).emit('disconnected', code, reason?.toString?.() || '');\r\n\r\n if (!this.intentionalClose && this.autoReconnect && this.reconnectAttempts < this.maxReconnectAttempts) {\r\n this.reconnectAttempts++;\r\n const delay = Math.min(1000 * Math.pow(2, this.reconnectAttempts - 1), 30_000);\r\n setTimeout(() => this.connect().catch(e => (this as TypedEmitter).emit('error', e)), delay);\r\n }\r\n };\r\n\r\n ws.onerror = (err: any) => {\r\n (this as TypedEmitter).emit('error', err instanceof Error ? err : new Error(String(err?.message || err)));\r\n if (!settled) { settled = true; reject(err); }\r\n };\r\n\r\n setTimeout(() => {\r\n if (!settled) {\r\n settled = true;\r\n ws.close();\r\n reject(new Error('Connection timeout'));\r\n }\r\n }, 15_000);\r\n });\r\n }\r\n\r\n disconnect(): void {\r\n this.intentionalClose = true;\r\n this.stopHeartbeat();\r\n if (this.ws) {\r\n this.ws.close(1000);\r\n this.ws = null;\r\n }\r\n this._connected = false;\r\n }\r\n\r\n get connected(): boolean {\r\n return this._connected;\r\n }\r\n\r\n get eventCount(): number {\r\n return this._eventCount;\r\n }\r\n\r\n get roomId(): string {\r\n return this._roomId;\r\n }\r\n\r\n override on<K extends keyof TikTokLiveEvents>(event: K, listener: TikTokLiveEvents[K]): this {\r\n return super.on(event as string, listener as Listener);\r\n }\r\n\r\n override once<K extends keyof TikTokLiveEvents>(event: K, listener: TikTokLiveEvents[K]): this {\r\n return super.once(event as string, listener as Listener);\r\n }\r\n\r\n override off<K extends keyof TikTokLiveEvents>(event: K, listener: TikTokLiveEvents[K]): this {\r\n return super.off(event as string, listener as Listener);\r\n }\r\n\r\n override emit<K extends keyof TikTokLiveEvents>(event: K, ...args: Parameters<TikTokLiveEvents[K]>): boolean {\r\n return super.emit(event as string, ...args);\r\n }\r\n\r\n private async handleMessage(raw: any): Promise<void> {\r\n try {\r\n let bytes: Uint8Array;\r\n\r\n if (raw instanceof ArrayBuffer) {\r\n bytes = new Uint8Array(raw);\r\n } else if (raw instanceof Uint8Array) {\r\n bytes = raw;\r\n } else if (typeof Blob !== 'undefined' && raw instanceof Blob) {\r\n bytes = new Uint8Array(await raw.arrayBuffer());\r\n } else if (raw?.buffer instanceof ArrayBuffer) {\r\n bytes = new Uint8Array(raw.buffer, raw.byteOffset, raw.byteLength);\r\n } else {\r\n return;\r\n }\r\n\r\n this.handleFrame(bytes);\r\n } catch { }\r\n }\r\n\r\n private async handleFrame(buf: Uint8Array): Promise<void> {\r\n try {\r\n const fields = decodeProto(buf);\r\n const idField = fields.find(f => f.fn === 2 && f.wt === 0);\r\n const id = idField ? idField.value as bigint : 0n;\r\n const type = getStr(fields, 7);\r\n const binary = getBytes(fields, 8);\r\n\r\n if (id > 0n && this.ws && (this.ws.readyState === 1)) {\r\n const ack = buildAck(id);\r\n this.ws.send(ack.buffer.byteLength === ack.length ? ack.buffer : ack.buffer.slice(ack.byteOffset, ack.byteOffset + ack.byteLength));\r\n }\r\n\r\n if (type === 'msg' && binary && binary.length > 0) {\r\n let inner = binary;\r\n if (inner.length > 2 && inner[0] === 0x1f && inner[1] === 0x8b) {\r\n // Try sync first (fastest, works when zlib is loaded)\r\n const syncResult = gunzipSync(inner);\r\n if (syncResult) {\r\n inner = syncResult;\r\n } else {\r\n // Fallback to async gunzip (uses DecompressionStream or async import)\r\n inner = await gunzip(inner);\r\n }\r\n }\r\n\r\n const events = parseWebcastResponse(inner);\r\n for (const evt of events) {\r\n this._eventCount++;\r\n\r\n if (evt.type === 'battle') {\r\n for (const team of evt.teams) {\r\n const host = team.users.find(u => u.user.id === team.hostUserId);\r\n if (host) {\r\n this._battleHosts.set(team.hostUserId, host.user);\r\n team.hostUser = host.user;\r\n }\r\n }\r\n }\r\n\r\n if (evt.type === 'battleArmies') {\r\n for (const team of evt.teams) {\r\n const host = team.users.find(u => u.user.id === team.hostUserId);\r\n if (host) {\r\n team.hostUser = host.user;\r\n this._battleHosts.set(team.hostUserId, host.user);\r\n } else {\r\n const cached = this._battleHosts.get(team.hostUserId);\r\n if (cached) team.hostUser = cached;\r\n }\r\n }\r\n }\r\n\r\n (this as TypedEmitter).emit('event', evt);\r\n (this as TypedEmitter).emit(evt.type, evt as any);\r\n }\r\n }\r\n } catch { }\r\n }\r\n\r\n private startHeartbeat(roomId: string): void {\r\n this.stopHeartbeat();\r\n this.heartbeatTimer = setInterval(() => {\r\n if (this.ws && this.ws.readyState === 1) {\r\n const hb = buildHeartbeat(roomId);\r\n this.ws.send(hb.buffer.byteLength === hb.length ? hb.buffer : hb.buffer.slice(hb.byteOffset, hb.byteOffset + hb.byteLength));\r\n }\r\n }, this.heartbeatInterval);\r\n }\r\n\r\n private stopHeartbeat(): void {\r\n if (this.heartbeatTimer) {\r\n clearInterval(this.heartbeatTimer);\r\n this.heartbeatTimer = null;\r\n }\r\n }\r\n}\r\n"],"mappings":"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","names":["DEFAULT_UA","DEFAULT_SIGN_SERVER"]}
1
+ {"version":3,"sources":["../src/proto.ts","../src/api.ts","../src/client.ts"],"sourcesContent":["import type { LiveEvent, TikTokUser, BattleTeam, BattleTeamUser } from './types.js';\r\n\r\nconst encoder = new TextEncoder();\r\nconst decoder = new TextDecoder();\r\n\r\nexport function concatBytes(...arrays: Uint8Array[]): Uint8Array {\r\n let totalLength = 0;\r\n for (const arr of arrays) totalLength += arr.length;\r\n const result = new Uint8Array(totalLength);\r\n let offset = 0;\r\n for (const arr of arrays) {\r\n result.set(arr, offset);\r\n offset += arr.length;\r\n }\r\n return result;\r\n}\r\n\r\nfunction readInt32LE(buf: Uint8Array, offset: number): number {\r\n return buf[offset] |\r\n (buf[offset + 1] << 8) |\r\n (buf[offset + 2] << 16) |\r\n (buf[offset + 3] << 24);\r\n}\r\n\r\nfunction readBigInt64LE(buf: Uint8Array, offset: number): bigint {\r\n const lo = BigInt(buf[offset] |\r\n (buf[offset + 1] << 8) |\r\n (buf[offset + 2] << 16) |\r\n ((buf[offset + 3] << 24) >>> 0));\r\n const hi = BigInt(buf[offset + 4] |\r\n (buf[offset + 5] << 8) |\r\n (buf[offset + 6] << 16) |\r\n ((buf[offset + 7] << 24) >>> 0));\r\n return (hi << 32n) | (lo & 0xFFFFFFFFn);\r\n}\r\n\r\nexport function decodeVarint(buf: Uint8Array, offset: number): { value: number; offset: number } {\r\n let result = 0, shift = 0;\r\n while (offset < buf.length) {\r\n const byte = buf[offset++];\r\n result |= (byte & 0x7F) << shift;\r\n if ((byte & 0x80) === 0) break;\r\n shift += 7;\r\n }\r\n return { value: result >>> 0, offset };\r\n}\r\n\r\nexport function decodeVarint64(buf: Uint8Array, offset: number): { value: bigint; offset: number } {\r\n let result = 0n, shift = 0n;\r\n while (offset < buf.length) {\r\n const byte = BigInt(buf[offset++]);\r\n result |= (byte & 0x7Fn) << shift;\r\n if ((byte & 0x80n) === 0n) break;\r\n shift += 7n;\r\n }\r\n return { value: result, offset };\r\n}\r\n\r\nexport function encodeVarint(v: number | bigint): Uint8Array {\r\n const bytes: number[] = [];\r\n let n = typeof v === 'bigint' ? v : BigInt(v);\r\n do {\r\n let b = Number(n & 0x7Fn);\r\n n >>= 7n;\r\n if (n > 0n) b |= 0x80;\r\n bytes.push(b);\r\n } while (n > 0n);\r\n return new Uint8Array(bytes);\r\n}\r\n\r\nexport interface ProtoField {\r\n fn: number;\r\n wt: number;\r\n value: Uint8Array | number | bigint;\r\n}\r\n\r\nexport function encodeField(fn: number, wt: number, value: Uint8Array | bigint | number | string): Uint8Array {\r\n const tag = encodeVarint((fn << 3) | wt);\r\n if (wt === 0) {\r\n return concatBytes(tag, encodeVarint(typeof value === 'number' ? BigInt(value) : value as bigint));\r\n }\r\n const data = typeof value === 'string' ? encoder.encode(value) : value as Uint8Array;\r\n return concatBytes(tag, encodeVarint(data.length), data);\r\n}\r\n\r\nexport function decodeProto(buf: Uint8Array): ProtoField[] {\r\n const fields: ProtoField[] = [];\r\n let offset = 0;\r\n while (offset < buf.length) {\r\n const tagResult = decodeVarint(buf, offset);\r\n offset = tagResult.offset;\r\n const fn = tagResult.value >> 3;\r\n const wt = tagResult.value & 7;\r\n if (wt === 0) {\r\n const r = decodeVarint64(buf, offset);\r\n offset = r.offset;\r\n fields.push({ fn, wt, value: r.value });\r\n } else if (wt === 2) {\r\n const lenR = decodeVarint(buf, offset);\r\n offset = lenR.offset;\r\n const data = buf.subarray(offset, offset + lenR.value);\r\n offset += lenR.value;\r\n fields.push({ fn, wt, value: data });\r\n } else if (wt === 1) {\r\n fields.push({ fn, wt, value: readBigInt64LE(buf, offset) });\r\n offset += 8;\r\n } else if (wt === 5) {\r\n fields.push({ fn, wt, value: BigInt(readInt32LE(buf, offset)) });\r\n offset += 4;\r\n } else {\r\n break;\r\n }\r\n }\r\n return fields;\r\n}\r\n\r\nexport function getStr(fields: ProtoField[], fn: number): string {\r\n const f = fields.find(x => x.fn === fn && x.wt === 2);\r\n return f ? decoder.decode(f.value as Uint8Array) : '';\r\n}\r\n\r\nexport function getBytes(fields: ProtoField[], fn: number): Uint8Array | null {\r\n const f = fields.find(x => x.fn === fn && x.wt === 2);\r\n return f ? f.value as Uint8Array : null;\r\n}\r\n\r\nexport function getInt(fields: ProtoField[], fn: number): number {\r\n const f = fields.find(x => x.fn === fn && x.wt === 0);\r\n return f ? Number(f.value) : 0;\r\n}\r\n\r\nexport function getAllBytes(fields: ProtoField[], fn: number): Uint8Array[] {\r\n return fields.filter(x => x.fn === fn && x.wt === 2).map(x => x.value as Uint8Array);\r\n}\r\n\r\nexport function buildHeartbeat(roomId: string): Uint8Array {\r\n const payload = encodeField(1, 0, BigInt(roomId));\r\n return concatBytes(\r\n encodeField(6, 2, 'pb'),\r\n encodeField(7, 2, 'hb'),\r\n encodeField(8, 2, payload),\r\n );\r\n}\r\n\r\nexport function buildImEnterRoom(roomId: string): Uint8Array {\r\n const inner = concatBytes(\r\n encodeField(1, 0, BigInt(roomId)),\r\n encodeField(4, 0, 12n),\r\n encodeField(5, 2, 'audience'),\r\n encodeField(6, 2, ''),\r\n encodeField(9, 2, ''),\r\n encodeField(10, 2, ''),\r\n );\r\n return concatBytes(\r\n encodeField(6, 2, 'pb'),\r\n encodeField(7, 2, 'im_enter_room'),\r\n encodeField(8, 2, inner),\r\n );\r\n}\r\n\r\nexport function buildAck(id: bigint): Uint8Array {\r\n return concatBytes(\r\n encodeField(2, 0, id),\r\n encodeField(6, 2, 'pb'),\r\n encodeField(7, 2, 'ack'),\r\n );\r\n}\r\n\r\n// NOTE: Army users in WebcastLinkMicArmies use a DIFFERENT layout where\r\n// field 38 contains avatar/image data, NOT uniqueId.\r\n// We detect this by checking if the string looks like a username (short, no URLs).\r\nfunction looksLikeUsername(s: string): boolean {\r\n return s.length > 0 && s.length <= 50 && !s.includes('://') && !s.includes('\\x00');\r\n}\r\n\r\nfunction parseUser(data: Uint8Array): TikTokUser {\r\n const f = decodeProto(data);\r\n const id = String(getInt(f, 1) || getStr(f, 1));\r\n const nickname = getStr(f, 3) || getStr(f, 2);\r\n\r\n // uniqueId: Try field 4 (LinkUser format) first, then field 38 (User format)\r\n // Validate that the result looks like a username, not binary/URL data\r\n let uniqueId = '';\r\n const uid4 = getStr(f, 4);\r\n const uid38 = getStr(f, 38);\r\n if (uid4 && looksLikeUsername(uid4)) {\r\n uniqueId = uid4;\r\n } else if (uid38 && looksLikeUsername(uid38)) {\r\n uniqueId = uid38;\r\n } else {\r\n const uid2 = getStr(f, 2);\r\n if (uid2 && looksLikeUsername(uid2)) uniqueId = uid2;\r\n }\r\n\r\n // profilePicture: Try field 9 (User), field 3 (LinkUser)\r\n // Each should contain a ProfilePicture submessage with repeated urls at field 1\r\n let profilePicture: string | undefined;\r\n const avatarBuf = getBytes(f, 9) || getBytes(f, 3);\r\n if (avatarBuf) {\r\n try {\r\n const avatarFields = decodeProto(avatarBuf);\r\n const urlBufs = getAllBytes(avatarFields, 1);\r\n for (const urlBuf of urlBufs) {\r\n const url = decoder.decode(urlBuf);\r\n if (url.includes('://')) {\r\n profilePicture = url;\r\n break;\r\n }\r\n }\r\n } catch { }\r\n }\r\n\r\n const badges: string[] = [];\r\n const badgeBuf = getBytes(f, 64);\r\n if (badgeBuf) {\r\n try {\r\n const badgeFields = decodeProto(badgeBuf);\r\n const badgeItems = getAllBytes(badgeFields, 21);\r\n for (const bi of badgeItems) {\r\n const bf = decodeProto(bi);\r\n const name = getStr(bf, 3) || getStr(bf, 2);\r\n if (name) badges.push(name);\r\n }\r\n } catch { }\r\n }\r\n\r\n return {\r\n id,\r\n nickname,\r\n uniqueId: uniqueId || nickname || id,\r\n profilePictureUrl: profilePicture,\r\n badges: badges.length > 0 ? badges : undefined,\r\n };\r\n}\r\n\r\nfunction parseBattleTeamFromArmies(itemBuf: Uint8Array): BattleTeam {\r\n const f = decodeProto(itemBuf);\r\n const hostUserId = String(getInt(f, 1));\r\n let teamScore = 0;\r\n const users: BattleTeamUser[] = [];\r\n\r\n const groups = getAllBytes(f, 2);\r\n for (const gb of groups) {\r\n try {\r\n const gf = decodeProto(gb);\r\n const points = getInt(gf, 2);\r\n teamScore += points;\r\n\r\n const userBufs = getAllBytes(gf, 1);\r\n for (const ub of userBufs) {\r\n try {\r\n const user = parseUser(ub);\r\n users.push({ user, score: points });\r\n } catch { }\r\n }\r\n } catch { }\r\n }\r\n\r\n return { hostUserId, score: teamScore, users };\r\n}\r\n\r\nexport function parseWebcastMessage(method: string, payload: Uint8Array): LiveEvent {\r\n const f = decodeProto(payload);\r\n const base = { timestamp: Date.now(), msgId: '' };\r\n\r\n const typeBuf = getBytes(f, 1);\r\n if (typeBuf) {\r\n try {\r\n const tf = decodeProto(typeBuf);\r\n const ts = getInt(tf, 4);\r\n if (ts) base.timestamp = ts;\r\n } catch { }\r\n }\r\n\r\n switch (method) {\r\n case 'WebcastChatMessage': {\r\n const userBuf = getBytes(f, 2);\r\n const user = userBuf ? parseUser(userBuf) : { id: '0', nickname: '', uniqueId: '' };\r\n return { ...base, type: 'chat' as const, user, comment: getStr(f, 3) };\r\n }\r\n\r\n case 'WebcastMemberMessage': {\r\n const userBuf = getBytes(f, 2);\r\n const user = userBuf ? parseUser(userBuf) : { id: '0', nickname: '', uniqueId: '' };\r\n let action = 1;\r\n const eventBuf = getBytes(f, 1);\r\n if (eventBuf) {\r\n const ef = decodeProto(eventBuf);\r\n const detailBuf = getBytes(ef, 8);\r\n if (detailBuf) {\r\n const df = decodeProto(detailBuf);\r\n const label = getStr(df, 2);\r\n if (label.includes('followed')) action = 2;\r\n else if (label.includes('share')) action = 3;\r\n }\r\n }\r\n return { ...base, type: 'member' as const, user, action };\r\n }\r\n\r\n case 'WebcastLikeMessage': {\r\n const userBuf = getBytes(f, 5);\r\n const user = userBuf ? parseUser(userBuf) : { id: '0', nickname: '', uniqueId: '' };\r\n return {\r\n ...base, type: 'like' as const, user,\r\n likeCount: getInt(f, 2),\r\n totalLikes: getInt(f, 3),\r\n };\r\n }\r\n\r\n case 'WebcastGiftMessage': {\r\n const userBuf = getBytes(f, 7);\r\n const user = userBuf ? parseUser(userBuf) : { id: '0', nickname: '', uniqueId: '' };\r\n const giftId = getInt(f, 2);\r\n const repeatCount = getInt(f, 5);\r\n const repeatEnd = getInt(f, 9) === 1;\r\n\r\n let giftName = '', diamondCount = 0, giftType = 0;\r\n let giftImageUrl = '';\r\n const detailsBuf = getBytes(f, 15);\r\n if (detailsBuf) {\r\n const df = decodeProto(detailsBuf);\r\n giftName = getStr(df, 16) || getStr(df, 2);\r\n diamondCount = getInt(df, 12);\r\n giftType = getInt(df, 11);\r\n\r\n const imgBuf = getBytes(df, 1);\r\n if (imgBuf) {\r\n const imgf = decodeProto(imgBuf);\r\n giftImageUrl = getStr(imgf, 1);\r\n }\r\n }\r\n\r\n let toUserId = '';\r\n const extraBuf = getBytes(f, 23);\r\n if (extraBuf) {\r\n const ef = decodeProto(extraBuf);\r\n toUserId = String(getInt(ef, 8));\r\n }\r\n\r\n const groupId = toUserId || getStr(f, 11);\r\n\r\n return {\r\n ...base, type: 'gift' as const, user, giftId, giftName, diamondCount,\r\n repeatCount, repeatEnd, combo: repeatCount > 1 && !repeatEnd,\r\n giftType, groupId, giftPictureUrl: giftImageUrl,\r\n };\r\n }\r\n\r\n case 'WebcastSocialMessage': {\r\n const userBuf = getBytes(f, 2);\r\n const user = userBuf ? parseUser(userBuf) : { id: '0', nickname: '', uniqueId: '' };\r\n let action = 'follow';\r\n const eventBuf = getBytes(f, 1);\r\n if (eventBuf) {\r\n const ef = decodeProto(eventBuf);\r\n const detailBuf = getBytes(ef, 8);\r\n if (detailBuf) {\r\n const df = decodeProto(detailBuf);\r\n const label = getStr(df, 2);\r\n if (label.includes('share')) action = 'share';\r\n else if (label.includes('follow')) action = 'follow';\r\n const displayType = getStr(df, 1);\r\n if (displayType === 'pm_mt_msg_viewer_share') action = 'share';\r\n }\r\n }\r\n return { ...base, type: 'social' as const, user, action };\r\n }\r\n\r\n case 'WebcastRoomUserSeqMessage': {\r\n const viewerCount = getInt(f, 3) || getInt(f, 2);\r\n const totalViewers = getInt(f, 1) || viewerCount;\r\n return { ...base, type: 'roomUserSeq' as const, totalViewers, viewerCount };\r\n }\r\n\r\n case 'WebcastLinkMicBattle': {\r\n const battleId = String(getInt(f, 1) || '');\r\n const status = getInt(f, 2) || 1;\r\n const battleDuration = getInt(f, 3);\r\n const teams: BattleTeam[] = [];\r\n\r\n const battleUserBufs = getAllBytes(f, 10);\r\n for (const bub of battleUserBufs) {\r\n try {\r\n const bf = decodeProto(bub);\r\n const groupBuf = getBytes(bf, 2);\r\n if (groupBuf) {\r\n const gf = decodeProto(groupBuf);\r\n const linkUserBuf = getBytes(gf, 1);\r\n if (linkUserBuf) {\r\n const user = parseUser(linkUserBuf);\r\n teams.push({\r\n hostUserId: user.id,\r\n score: 0,\r\n users: [{ user, score: 0 }],\r\n });\r\n }\r\n }\r\n } catch { }\r\n }\r\n\r\n if (teams.length === 0) {\r\n const teamBufs7 = getAllBytes(f, 7);\r\n for (const tb of teamBufs7) {\r\n try {\r\n teams.push(parseBattleTeamFromArmies(tb));\r\n } catch { }\r\n }\r\n }\r\n\r\n return { ...base, type: 'battle' as const, battleId, status, battleDuration, teams };\r\n }\r\n\r\n case 'WebcastLinkMicArmies': {\r\n const battleId = String(getInt(f, 1) || '');\r\n const battleStatus = getInt(f, 7);\r\n const teams: BattleTeam[] = [];\r\n\r\n const itemBufs = getAllBytes(f, 3);\r\n for (const ib of itemBufs) {\r\n try {\r\n teams.push(parseBattleTeamFromArmies(ib));\r\n } catch { }\r\n }\r\n\r\n return {\r\n ...base, type: 'battleArmies' as const, battleId, teams,\r\n status: battleStatus,\r\n };\r\n }\r\n\r\n case 'WebcastSubNotifyMessage': {\r\n const userBuf = getBytes(f, 2);\r\n const user = userBuf ? parseUser(userBuf) : { id: '0', nickname: '', uniqueId: '' };\r\n return { ...base, type: 'subscribe' as const, user, subMonth: getInt(f, 3) };\r\n }\r\n\r\n case 'WebcastEmoteChatMessage': {\r\n const userBuf = getBytes(f, 2);\r\n const user = userBuf ? parseUser(userBuf) : { id: '0', nickname: '', uniqueId: '' };\r\n let emoteId = '', emoteUrl = '';\r\n const emoteBuf = getBytes(f, 3);\r\n if (emoteBuf) {\r\n const ef = decodeProto(emoteBuf);\r\n emoteId = getStr(ef, 1);\r\n const imageBuf = getBytes(ef, 2);\r\n if (imageBuf) {\r\n const imgFields = decodeProto(imageBuf);\r\n emoteUrl = getStr(imgFields, 1);\r\n }\r\n }\r\n return { ...base, type: 'emoteChat' as const, user, emoteId, emoteUrl };\r\n }\r\n\r\n case 'WebcastEnvelopeMessage': {\r\n const envelopeId = String(getInt(f, 1) || getStr(f, 1));\r\n return { ...base, type: 'envelope' as const, envelopeId, diamondCount: getInt(f, 3) };\r\n }\r\n\r\n case 'WebcastQuestionNewMessage': {\r\n let questionText = '', user: TikTokUser = { id: '0', nickname: '', uniqueId: '' };\r\n const detailBuf = getBytes(f, 2);\r\n if (detailBuf) {\r\n const df = decodeProto(detailBuf);\r\n questionText = getStr(df, 2);\r\n const userBuf = getBytes(df, 5);\r\n if (userBuf) user = parseUser(userBuf);\r\n }\r\n return { ...base, type: 'question' as const, user, questionText };\r\n }\r\n\r\n case 'WebcastRankUpdateMessage':\r\n case 'WebcastHourlyRankMessage': {\r\n const rankType = getStr(f, 1) || `rank_${getInt(f, 1)}`;\r\n const rankList: Array<{ user: TikTokUser; rank: number; score: number }> = [];\r\n const listBufs = getAllBytes(f, 2);\r\n for (const lb of listBufs) {\r\n try {\r\n const rf = decodeProto(lb);\r\n const userBuf = getBytes(rf, 1);\r\n const rank = getInt(rf, 2);\r\n const score = getInt(rf, 3);\r\n const user = userBuf ? parseUser(userBuf) : { id: '0', nickname: '', uniqueId: '' };\r\n rankList.push({ user, rank, score });\r\n } catch { }\r\n }\r\n return { ...base, type: 'rankUpdate' as const, rankType, rankList };\r\n }\r\n\r\n case 'WebcastControlMessage':\r\n return { ...base, type: 'control' as const, action: getInt(f, 2) || getInt(f, 1) };\r\n\r\n case 'WebcastRoomMessage':\r\n case 'RoomMessage':\r\n return { ...base, type: 'room' as const, status: getInt(f, 2) };\r\n\r\n case 'WebcastLiveIntroMessage': {\r\n const roomId = String(getInt(f, 2));\r\n const title = getStr(f, 4) || getStr(f, 2);\r\n return { ...base, type: 'liveIntro' as const, roomId, title };\r\n }\r\n\r\n case 'WebcastLinkMicMethod':\r\n case 'WebcastLinkmicBattleTaskMessage': {\r\n const action = getStr(f, 1) || `action_${getInt(f, 1)}`;\r\n const users: TikTokUser[] = [];\r\n const userBufs = getAllBytes(f, 2);\r\n for (const ub of userBufs) {\r\n try { users.push(parseUser(ub)); } catch { }\r\n }\r\n return { ...base, type: 'linkMic' as const, action, users };\r\n }\r\n\r\n default:\r\n return { ...base, type: 'unknown' as const, method };\r\n }\r\n}\r\n\r\nexport function parseWebcastResponse(payload: Uint8Array): LiveEvent[] {\r\n const events: LiveEvent[] = [];\r\n const respFields = decodeProto(payload);\r\n\r\n for (const mf of respFields.filter(f => f.fn === 1 && f.wt === 2)) {\r\n const msgBuf = mf.value as Uint8Array;\r\n const msgFields = decodeProto(msgBuf);\r\n const method = getStr(msgFields, 1);\r\n const innerPayload = getBytes(msgFields, 2);\r\n if (!method || !innerPayload) continue;\r\n\r\n try {\r\n events.push(parseWebcastMessage(method, innerPayload));\r\n } catch { }\r\n }\r\n\r\n return events;\r\n}\r\n","/**\r\n * TikTool API utilities for the sign-and-return API flow.\r\n *\r\n * The API server returns signed URLs instead of fetching TikTok data directly.\r\n * These utilities handle the two-step flow:\r\n * 1. resolve_required — scrape TikTok HTML to get room_id\r\n * 2. fetch_signed_url — use the signed URL to get actual TikTok data\r\n *\r\n * @module\r\n */\r\n\r\nconst DEFAULT_UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36';\r\nconst DEFAULT_SIGN_SERVER = 'https://api.tik.tools';\r\n\r\nconst pageCache = new Map<string, { info: LivePageInfo; ts: number }>();\r\nconst PAGE_CACHE_TTL = 5 * 60 * 1000;\r\n\r\n/**\r\n * Resolved live page metadata from a TikTok live page.\r\n */\r\nexport interface LivePageInfo {\r\n /** Active room ID for the livestream */\r\n roomId: string;\r\n /** Session cookie required for WebSocket authentication */\r\n ttwid: string;\r\n /** Server cluster region (e.g. 'us', 'eu') */\r\n clusterRegion: string;\r\n}\r\n\r\n/**\r\n * Scrape a TikTok live page to extract room metadata.\r\n * Returns the room ID, session cookie, and cluster region.\r\n * Results are cached for 5 minutes. Returns `null` if the user is not live.\r\n */\r\nexport async function resolveLivePage(uniqueId: string): Promise<LivePageInfo | null> {\r\n const clean = uniqueId.replace(/^@/, '');\r\n const cached = pageCache.get(clean);\r\n if (cached && Date.now() - cached.ts < PAGE_CACHE_TTL) {\r\n return cached.info;\r\n }\r\n\r\n try {\r\n const resp = await fetch(`https://www.tiktok.com/@${clean}/live`, {\r\n headers: {\r\n 'User-Agent': DEFAULT_UA,\r\n 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',\r\n 'Accept-Language': 'en-US,en;q=0.9',\r\n },\r\n redirect: 'follow',\r\n });\r\n\r\n if (!resp.ok) return null;\r\n\r\n // Extract ttwid session cookie\r\n let ttwid = '';\r\n const setCookies = resp.headers.get('set-cookie') || '';\r\n for (const part of setCookies.split(',')) {\r\n const trimmed = part.trim();\r\n if (trimmed.startsWith('ttwid=')) {\r\n ttwid = trimmed.split(';')[0].split('=').slice(1).join('=');\r\n break;\r\n }\r\n }\r\n if (!ttwid && typeof (resp.headers as any).getSetCookie === 'function') {\r\n for (const sc of (resp.headers as any).getSetCookie()) {\r\n if (typeof sc === 'string' && sc.startsWith('ttwid=')) {\r\n ttwid = sc.split(';')[0].split('=').slice(1).join('=');\r\n break;\r\n }\r\n }\r\n }\r\n\r\n const html = await resp.text();\r\n\r\n // Extract roomId from SIGI_STATE JSON block\r\n let roomId = '';\r\n const sigiMatch = html.match(/id=\"SIGI_STATE\"[^>]*>([^<]+)/);\r\n if (sigiMatch) {\r\n try {\r\n const json = JSON.parse(sigiMatch[1]);\r\n const jsonStr = JSON.stringify(json);\r\n const m = jsonStr.match(/\"roomId\"\\s*:\\s*\"(\\d+)\"/);\r\n if (m) roomId = m[1];\r\n } catch { }\r\n }\r\n\r\n // Fallback patterns\r\n if (!roomId) {\r\n const patterns = [\r\n /\"roomId\"\\s*:\\s*\"(\\d+)\"/,\r\n /room_id[=/](\\d{10,})/,\r\n /\"idStr\"\\s*:\\s*\"(\\d{10,})\"/,\r\n ];\r\n for (const p of patterns) {\r\n const m = html.match(p);\r\n if (m) { roomId = m[1]; break; }\r\n }\r\n }\r\n\r\n if (!roomId) return null;\r\n\r\n // Extract cluster region\r\n const crMatch = html.match(/\"clusterRegion\"\\s*:\\s*\"([^\"]+)\"/);\r\n const clusterRegion = crMatch ? crMatch[1] : '';\r\n\r\n const info: LivePageInfo = { roomId, ttwid, clusterRegion };\r\n pageCache.set(clean, { info, ts: Date.now() });\r\n return info;\r\n } catch { }\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * Resolve a TikTok username to a room ID.\r\n * Returns `null` if the user is not currently live.\r\n * Results are cached for 5 minutes.\r\n */\r\nexport async function resolveRoomId(uniqueId: string): Promise<string | null> {\r\n const info = await resolveLivePage(uniqueId);\r\n return info?.roomId ?? null;\r\n}\r\n\r\nexport interface SignedUrlResponse {\r\n status_code: number;\r\n action?: string;\r\n signed_url: string;\r\n headers: Record<string, string>;\r\n cookies: string;\r\n}\r\n\r\n/**\r\n * Execute a signed-URL API response: fetch the signed URL and return the\r\n * parsed JSON data from TikTok.\r\n */\r\nexport async function fetchSignedUrl(response: SignedUrlResponse): Promise<any> {\r\n if (!response.signed_url) {\r\n return null;\r\n }\r\n\r\n const headers: Record<string, string> = { ...(response.headers || {}) };\r\n if (response.cookies) {\r\n headers['Cookie'] = response.cookies;\r\n }\r\n\r\n const resp = await fetch(response.signed_url, { headers, redirect: 'follow' });\r\n const text = await resp.text();\r\n try {\r\n return JSON.parse(text);\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\nexport interface CallApiOptions {\r\n /** API server URL (default: https://api.tik.tools) */\r\n serverUrl?: string;\r\n /** API key for authentication */\r\n apiKey: string;\r\n /** API endpoint path (e.g. '/webcast/room_video') */\r\n endpoint: string;\r\n /** TikTok unique_id to resolve */\r\n uniqueId: string;\r\n /** HTTP method (default: POST) */\r\n method?: 'GET' | 'POST';\r\n /** Additional body fields for POST requests */\r\n extraBody?: Record<string, any>;\r\n}\r\n\r\n/**\r\n * Call a TikTool API endpoint, handling the full\r\n * resolve_required → room_id → signed_url → fetch flow automatically.\r\n *\r\n * Returns the actual TikTok data, or `null` if the user is not live.\r\n */\r\nexport async function callApi(opts: CallApiOptions): Promise<any> {\r\n const serverUrl = (opts.serverUrl || DEFAULT_SIGN_SERVER).replace(/\\/$/, '');\r\n const isGet = opts.method === 'GET';\r\n const ak = encodeURIComponent(opts.apiKey);\r\n\r\n const url1 = isGet\r\n ? `${serverUrl}${opts.endpoint}?apiKey=${ak}&unique_id=${encodeURIComponent(opts.uniqueId)}`\r\n : `${serverUrl}${opts.endpoint}?apiKey=${ak}`;\r\n\r\n const fetchOpts1: RequestInit = isGet\r\n ? {}\r\n : {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ unique_id: opts.uniqueId, ...opts.extraBody }),\r\n };\r\n\r\n const resp1 = await fetch(url1, fetchOpts1);\r\n const data1 = await resp1.json() as any;\r\n\r\n // If the response contains a signed URL to fetch (with or without explicit action),\r\n // follow through and fetch the actual TikTok data\r\n if (data1.signed_url || data1.action === 'fetch_signed_url') {\r\n return fetchSignedUrl(data1);\r\n }\r\n\r\n if (data1.status_code === 0 && data1.action !== 'resolve_required') {\r\n return data1;\r\n }\r\n\r\n if (data1.action === 'resolve_required') {\r\n const roomId = await resolveRoomId(opts.uniqueId);\r\n if (!roomId) return null;\r\n\r\n const url2 = isGet\r\n ? `${serverUrl}${opts.endpoint}?apiKey=${ak}&room_id=${encodeURIComponent(roomId)}`\r\n : `${serverUrl}${opts.endpoint}?apiKey=${ak}`;\r\n\r\n const fetchOpts2: RequestInit = isGet\r\n ? {}\r\n : {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ room_id: roomId, ...opts.extraBody }),\r\n };\r\n\r\n const resp2 = await fetch(url2, fetchOpts2);\r\n const data2 = await resp2.json() as any;\r\n\r\n if (data2.signed_url || data2.action === 'fetch_signed_url') {\r\n return fetchSignedUrl(data2);\r\n }\r\n\r\n return data2;\r\n }\r\n\r\n return data1;\r\n}\r\n\r\n// ── CAPTCHA Solver API ──────────────────────────────────────────────\r\n\r\nimport type { PuzzleSolveResult, RotateSolveResult, ShapesSolveResult } from './types.js';\r\n\r\n/**\r\n * Solve a puzzle (slider) CAPTCHA using the TikTool solver.\r\n *\r\n * @param apiKey - API key for authentication\r\n * @param puzzleB64 - Base64-encoded background image (PNG/JPEG)\r\n * @param pieceB64 - Base64-encoded puzzle piece image (PNG/JPEG)\r\n * @param serverUrl - Custom server URL (default: https://api.tik.tools)\r\n * @returns Solve result with slide position and confidence\r\n */\r\nexport async function solvePuzzle(\r\n apiKey: string,\r\n puzzleB64: string,\r\n pieceB64: string,\r\n serverUrl?: string,\r\n): Promise<PuzzleSolveResult> {\r\n const base = (serverUrl || DEFAULT_SIGN_SERVER).replace(/\\/$/, '');\r\n const resp = await fetch(`${base}/captcha/solve/puzzle?apiKey=${encodeURIComponent(apiKey)}`, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ puzzle: puzzleB64, piece: pieceB64 }),\r\n });\r\n const data = await resp.json() as any;\r\n if (data.status_code !== 0) {\r\n throw new Error(data.error || `Solver failed (status ${data.status_code})`);\r\n }\r\n return data.data as PuzzleSolveResult;\r\n}\r\n\r\n/**\r\n * Solve a rotate (whirl) CAPTCHA using the TikTool solver.\r\n *\r\n * @param apiKey - API key for authentication\r\n * @param outerB64 - Base64-encoded outer ring image (PNG/JPEG)\r\n * @param innerB64 - Base64-encoded inner rotated image (PNG/JPEG)\r\n * @param serverUrl - Custom server URL (default: https://api.tik.tools)\r\n * @returns Solve result with rotation angle and confidence\r\n */\r\nexport async function solveRotate(\r\n apiKey: string,\r\n outerB64: string,\r\n innerB64: string,\r\n serverUrl?: string,\r\n): Promise<RotateSolveResult> {\r\n const base = (serverUrl || DEFAULT_SIGN_SERVER).replace(/\\/$/, '');\r\n const resp = await fetch(`${base}/captcha/solve/rotate?apiKey=${encodeURIComponent(apiKey)}`, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ outer: outerB64, inner: innerB64 }),\r\n });\r\n const data = await resp.json() as any;\r\n if (data.status_code !== 0) {\r\n throw new Error(data.error || `Solver failed (status ${data.status_code})`);\r\n }\r\n return data.data as RotateSolveResult;\r\n}\r\n\r\n/**\r\n * Solve a shapes (3D matching) CAPTCHA using the TikTool solver.\r\n *\r\n * @param apiKey - API key for authentication\r\n * @param imageB64 - Base64-encoded CAPTCHA image with shape grid (PNG/JPEG)\r\n * @param serverUrl - Custom server URL (default: https://api.tik.tools)\r\n * @returns Solve result with two matching shape coordinates and confidence\r\n */\r\nexport async function solveShapes(\r\n apiKey: string,\r\n imageB64: string,\r\n serverUrl?: string,\r\n): Promise<ShapesSolveResult> {\r\n const base = (serverUrl || DEFAULT_SIGN_SERVER).replace(/\\/$/, '');\r\n const resp = await fetch(`${base}/captcha/solve/shapes?apiKey=${encodeURIComponent(apiKey)}`, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ image: imageB64 }),\r\n });\r\n const data = await resp.json() as any;\r\n if (data.status_code !== 0) {\r\n throw new Error(data.error || `Solver failed (status ${data.status_code})`);\r\n }\r\n return data.data as ShapesSolveResult;\r\n}\r\n","import type { TikTokLiveOptions, TikTokLiveEvents, RoomInfo, LiveEvent } from './types.js';\r\nimport {\r\n concatBytes,\r\n decodeProto,\r\n getStr,\r\n getBytes,\r\n buildHeartbeat,\r\n buildImEnterRoom,\r\n buildAck,\r\n parseWebcastResponse,\r\n} from './proto.js';\r\nimport { resolveLivePage } from './api.js';\r\n\r\nconst DEFAULT_UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36';\r\nconst DEFAULT_SIGN_SERVER = 'https://api.tik.tools';\r\n\r\ntype Listener = (...args: any[]) => void;\r\n\r\nclass TypedEmitter {\r\n private _listeners = new Map<string, Listener[]>();\r\n\r\n on(event: string, fn: Listener): this {\r\n const arr = this._listeners.get(event) || [];\r\n arr.push(fn);\r\n this._listeners.set(event, arr);\r\n return this;\r\n }\r\n\r\n once(event: string, fn: Listener): this {\r\n const wrapper: Listener = (...args) => {\r\n this.off(event, wrapper);\r\n fn(...args);\r\n };\r\n return this.on(event, wrapper);\r\n }\r\n\r\n off(event: string, fn: Listener): this {\r\n const arr = this._listeners.get(event);\r\n if (arr) {\r\n this._listeners.set(event, arr.filter(l => l !== fn));\r\n }\r\n return this;\r\n }\r\n\r\n emit(event: string, ...args: any[]): boolean {\r\n const arr = this._listeners.get(event);\r\n if (!arr || arr.length === 0) return false;\r\n for (const fn of [...arr]) fn(...args);\r\n return true;\r\n }\r\n\r\n removeAllListeners(event?: string): this {\r\n if (event) this._listeners.delete(event);\r\n else this._listeners.clear();\r\n return this;\r\n }\r\n}\r\n\r\nasync function gunzip(data: Uint8Array): Promise<Uint8Array> {\r\n if (typeof DecompressionStream !== 'undefined') {\r\n const ds = new DecompressionStream('gzip');\r\n const writer = ds.writable.getWriter();\r\n const reader = ds.readable.getReader();\r\n writer.write(data as any);\r\n writer.close();\r\n const chunks: Uint8Array[] = [];\r\n while (true) {\r\n const { done, value } = await reader.read();\r\n if (done) break;\r\n chunks.push(value);\r\n }\r\n return concatBytes(...chunks);\r\n }\r\n try {\r\n const zlib = await import('zlib');\r\n return new Promise((resolve, reject) => {\r\n zlib.gunzip(data, (err: Error | null, result: Buffer) => {\r\n if (err) reject(err);\r\n else resolve(new Uint8Array(result));\r\n });\r\n });\r\n } catch {\r\n return data;\r\n }\r\n}\r\n\r\n// Pre-cache zlib for sync decompression (require fails in ESM)\r\nlet _zlib: any = null;\r\nlet _zlibLoadAttempted = false;\r\n\r\nasync function ensureZlib(): Promise<any> {\r\n if (_zlib) return _zlib;\r\n if (_zlibLoadAttempted) return null;\r\n _zlibLoadAttempted = true;\r\n try {\r\n _zlib = await import('zlib');\r\n } catch { }\r\n return _zlib;\r\n}\r\n\r\n// Attempt to load zlib eagerly at module init\r\nensureZlib();\r\n\r\nfunction gunzipSync(data: Uint8Array): Uint8Array | null {\r\n if (!_zlib) return null; // Signal that sync decompress is unavailable\r\n try {\r\n return new Uint8Array(_zlib.gunzipSync(data));\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\ntype WebSocketLike = {\r\n readonly readyState: number;\r\n send(data: ArrayBufferLike | string): void;\r\n close(code?: number, reason?: string): void;\r\n onopen: ((ev: any) => void) | null;\r\n onmessage: ((ev: any) => void) | null;\r\n onerror: ((ev: any) => void) | null;\r\n onclose: ((ev: any) => void) | null;\r\n};\r\n\r\ninterface WebSocketConstructor {\r\n new(url: string, protocols?: string | string[]): WebSocketLike;\r\n readonly OPEN: number;\r\n readonly CLOSED: number;\r\n}\r\n\r\nfunction getWsHost(clusterRegion: string): string {\r\n if (!clusterRegion) return 'webcast-ws.tiktok.com';\r\n const r = clusterRegion.toLowerCase();\r\n if (r.startsWith('eu') || r.includes('eu')) return 'webcast-ws.eu.tiktok.com';\r\n if (r.startsWith('us') || r.includes('us')) return 'webcast-ws.us.tiktok.com';\r\n return 'webcast-ws.tiktok.com';\r\n}\r\n\r\nasync function resolveWebSocket(userImpl?: any): Promise<WebSocketConstructor> {\r\n if (userImpl) return userImpl;\r\n\r\n if (typeof globalThis.WebSocket !== 'undefined') {\r\n return globalThis.WebSocket as unknown as WebSocketConstructor;\r\n }\r\n\r\n try {\r\n const ws = await import('ws');\r\n return (ws.default || ws) as unknown as WebSocketConstructor;\r\n } catch {\r\n throw new Error(\r\n 'No WebSocket implementation found. ' +\r\n 'Either use Node.js 22+ (native WebSocket), Cloudflare Workers, or install the \"ws\" package: npm i ws'\r\n );\r\n }\r\n}\r\n\r\nexport class TikTokLive extends TypedEmitter {\r\n private ws: WebSocketLike | null = null;\r\n private heartbeatTimer: ReturnType<typeof setInterval> | null = null;\r\n private reconnectAttempts = 0;\r\n private intentionalClose = false;\r\n private _connected = false;\r\n private _eventCount = 0;\r\n private _roomId = '';\r\n private _battleHosts = new Map<string, { id: string; nickname: string; uniqueId: string; profilePicture?: string }>();\r\n\r\n private readonly uniqueId: string;\r\n private readonly signServerUrl: string;\r\n private readonly apiKey: string;\r\n private readonly autoReconnect: boolean;\r\n private readonly maxReconnectAttempts: number;\r\n private readonly heartbeatInterval: number;\r\n private readonly debug: boolean;\r\n private readonly webSocketImpl?: any;\r\n private WS!: WebSocketConstructor;\r\n\r\n constructor(options: TikTokLiveOptions) {\r\n super();\r\n this.uniqueId = options.uniqueId.replace(/^@/, '');\r\n this.signServerUrl = (options.signServerUrl || DEFAULT_SIGN_SERVER).replace(/\\/$/, '');\r\n if (!options.apiKey) throw new Error('apiKey is required. Get a free key at https://tik.tools');\r\n this.apiKey = options.apiKey;\r\n this.autoReconnect = options.autoReconnect ?? true;\r\n this.maxReconnectAttempts = options.maxReconnectAttempts ?? 5;\r\n this.heartbeatInterval = options.heartbeatInterval ?? 10_000;\r\n this.debug = options.debug ?? false;\r\n this.webSocketImpl = options.webSocketImpl;\r\n }\r\n\r\n async connect(): Promise<void> {\r\n this.intentionalClose = false;\r\n\r\n if (!this.WS) {\r\n this.WS = await resolveWebSocket(this.webSocketImpl);\r\n }\r\n\r\n const pageInfo = await resolveLivePage(this.uniqueId);\r\n if (!pageInfo) throw new Error(`User @${this.uniqueId} is not currently live`);\r\n if (!pageInfo.ttwid) throw new Error('Failed to obtain session cookie');\r\n\r\n const { roomId, ttwid, clusterRegion } = pageInfo;\r\n this._roomId = roomId;\r\n const wsHost = getWsHost(clusterRegion);\r\n\r\n const wsParams = new URLSearchParams({\r\n version_code: '270000', device_platform: 'web', cookie_enabled: 'true',\r\n screen_width: '1920', screen_height: '1080', browser_language: 'en-US',\r\n browser_platform: 'Win32', browser_name: 'Mozilla',\r\n browser_version: DEFAULT_UA.split('Mozilla/')[1] || '5.0',\r\n browser_online: 'true', tz_name: 'Etc/UTC',\r\n app_name: 'tiktok_web', sup_ws_ds_opt: '1', update_version_code: '2.0.0',\r\n compress: 'gzip', webcast_language: 'en', ws_direct: '1', aid: '1988',\r\n live_id: '12', app_language: 'en', client_enter: '1', room_id: roomId,\r\n identity: 'audience', history_comment_count: '6', last_rtt: '0',\r\n heartbeat_duration: '10000', resp_content_type: 'protobuf', did_rule: '3',\r\n });\r\n\r\n const rawWsUrl = `https://${wsHost}/webcast/im/ws_proxy/ws_reuse_supplement/?${wsParams}`;\r\n const signUrl = `${this.signServerUrl}/webcast/sign_url`;\r\n\r\n let wsUrl: string;\r\n try {\r\n const signResp = await fetch(signUrl, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'x-api-key': this.apiKey,\r\n },\r\n body: JSON.stringify({ url: rawWsUrl }),\r\n });\r\n const signData = await signResp.json() as Record<string, any>;\r\n\r\n if (signData.status_code === 0 && signData.data?.signed_url) {\r\n wsUrl = (signData.data.signed_url as string).replace(/^https:\\/\\//, 'wss://');\r\n } else {\r\n wsUrl = rawWsUrl.replace(/^https:\\/\\//, 'wss://');\r\n }\r\n } catch {\r\n wsUrl = rawWsUrl.replace(/^https:\\/\\//, 'wss://');\r\n }\r\n\r\n return new Promise<void>((resolve, reject) => {\r\n const connUrl = wsUrl + (wsUrl.includes('?') ? '&' : '?') + `ttwid=${ttwid}`;\r\n\r\n try {\r\n this.ws = new (this.WS as any)(connUrl, {\r\n headers: {\r\n 'User-Agent': DEFAULT_UA,\r\n 'Cookie': `ttwid=${ttwid}`,\r\n 'Origin': 'https://www.tiktok.com',\r\n },\r\n }) as WebSocketLike;\r\n } catch {\r\n this.ws = new this.WS(connUrl) as WebSocketLike;\r\n }\r\n\r\n const ws = this.ws;\r\n let settled = false;\r\n\r\n ws.onopen = () => {\r\n this._connected = true;\r\n this.reconnectAttempts = 0;\r\n\r\n const hb = buildHeartbeat(roomId);\r\n const enter = buildImEnterRoom(roomId);\r\n ws.send(hb.buffer.byteLength === hb.length ? hb.buffer : hb.buffer.slice(hb.byteOffset, hb.byteOffset + hb.byteLength));\r\n ws.send(enter.buffer.byteLength === enter.length ? enter.buffer : enter.buffer.slice(enter.byteOffset, enter.byteOffset + enter.byteLength));\r\n this.startHeartbeat(roomId);\r\n\r\n const roomInfo: RoomInfo = {\r\n roomId,\r\n wsHost,\r\n clusterRegion,\r\n connectedAt: new Date().toISOString(),\r\n };\r\n\r\n (this as TypedEmitter).emit('connected');\r\n (this as TypedEmitter).emit('roomInfo', roomInfo);\r\n if (!settled) { settled = true; resolve(); }\r\n };\r\n\r\n ws.onmessage = (event: any) => {\r\n const raw = event.data !== undefined ? event.data : event;\r\n this.handleMessage(raw);\r\n };\r\n\r\n ws.onclose = (event: any) => {\r\n this._connected = false;\r\n this.stopHeartbeat();\r\n\r\n const code = event?.code ?? 1006;\r\n const reason = event?.reason ?? '';\r\n (this as TypedEmitter).emit('disconnected', code, reason?.toString?.() || '');\r\n\r\n if (!this.intentionalClose && this.autoReconnect && this.reconnectAttempts < this.maxReconnectAttempts) {\r\n this.reconnectAttempts++;\r\n const delay = Math.min(1000 * Math.pow(2, this.reconnectAttempts - 1), 30_000);\r\n setTimeout(() => this.connect().catch(e => (this as TypedEmitter).emit('error', e)), delay);\r\n }\r\n };\r\n\r\n ws.onerror = (err: any) => {\r\n (this as TypedEmitter).emit('error', err instanceof Error ? err : new Error(String(err?.message || err)));\r\n if (!settled) { settled = true; reject(err); }\r\n };\r\n\r\n setTimeout(() => {\r\n if (!settled) {\r\n settled = true;\r\n ws.close();\r\n reject(new Error('Connection timeout'));\r\n }\r\n }, 15_000);\r\n });\r\n }\r\n\r\n disconnect(): void {\r\n this.intentionalClose = true;\r\n this.stopHeartbeat();\r\n if (this.ws) {\r\n this.ws.close(1000);\r\n this.ws = null;\r\n }\r\n this._connected = false;\r\n }\r\n\r\n get connected(): boolean {\r\n return this._connected;\r\n }\r\n\r\n get eventCount(): number {\r\n return this._eventCount;\r\n }\r\n\r\n get roomId(): string {\r\n return this._roomId;\r\n }\r\n\r\n override on<K extends keyof TikTokLiveEvents>(event: K, listener: TikTokLiveEvents[K]): this {\r\n return super.on(event as string, listener as Listener);\r\n }\r\n\r\n override once<K extends keyof TikTokLiveEvents>(event: K, listener: TikTokLiveEvents[K]): this {\r\n return super.once(event as string, listener as Listener);\r\n }\r\n\r\n override off<K extends keyof TikTokLiveEvents>(event: K, listener: TikTokLiveEvents[K]): this {\r\n return super.off(event as string, listener as Listener);\r\n }\r\n\r\n override emit<K extends keyof TikTokLiveEvents>(event: K, ...args: Parameters<TikTokLiveEvents[K]>): boolean {\r\n return super.emit(event as string, ...args);\r\n }\r\n\r\n private async handleMessage(raw: any): Promise<void> {\r\n try {\r\n let bytes: Uint8Array;\r\n\r\n if (raw instanceof ArrayBuffer) {\r\n bytes = new Uint8Array(raw);\r\n } else if (raw instanceof Uint8Array) {\r\n bytes = raw;\r\n } else if (typeof Blob !== 'undefined' && raw instanceof Blob) {\r\n bytes = new Uint8Array(await raw.arrayBuffer());\r\n } else if (raw?.buffer instanceof ArrayBuffer) {\r\n bytes = new Uint8Array(raw.buffer, raw.byteOffset, raw.byteLength);\r\n } else {\r\n return;\r\n }\r\n\r\n this.handleFrame(bytes);\r\n } catch { }\r\n }\r\n\r\n private async handleFrame(buf: Uint8Array): Promise<void> {\r\n try {\r\n const fields = decodeProto(buf);\r\n const idField = fields.find(f => f.fn === 2 && f.wt === 0);\r\n const id = idField ? idField.value as bigint : 0n;\r\n const type = getStr(fields, 7);\r\n const binary = getBytes(fields, 8);\r\n\r\n if (id > 0n && this.ws && (this.ws.readyState === 1)) {\r\n const ack = buildAck(id);\r\n this.ws.send(ack.buffer.byteLength === ack.length ? ack.buffer : ack.buffer.slice(ack.byteOffset, ack.byteOffset + ack.byteLength));\r\n }\r\n\r\n if (type === 'msg' && binary && binary.length > 0) {\r\n let inner = binary;\r\n if (inner.length > 2 && inner[0] === 0x1f && inner[1] === 0x8b) {\r\n // Try sync first (fastest, works when zlib is loaded)\r\n const syncResult = gunzipSync(inner);\r\n if (syncResult) {\r\n inner = syncResult;\r\n } else {\r\n // Fallback to async gunzip (uses DecompressionStream or async import)\r\n inner = await gunzip(inner);\r\n }\r\n }\r\n\r\n const events = parseWebcastResponse(inner);\r\n for (const evt of events) {\r\n this._eventCount++;\r\n\r\n if (evt.type === 'battle') {\r\n for (const team of evt.teams) {\r\n const host = team.users.find(u => u.user.id === team.hostUserId);\r\n if (host) {\r\n this._battleHosts.set(team.hostUserId, host.user);\r\n team.hostUser = host.user;\r\n }\r\n }\r\n }\r\n\r\n if (evt.type === 'battleArmies') {\r\n for (const team of evt.teams) {\r\n const host = team.users.find(u => u.user.id === team.hostUserId);\r\n if (host) {\r\n team.hostUser = host.user;\r\n this._battleHosts.set(team.hostUserId, host.user);\r\n } else {\r\n const cached = this._battleHosts.get(team.hostUserId);\r\n if (cached) team.hostUser = cached;\r\n }\r\n }\r\n }\r\n\r\n (this as TypedEmitter).emit('event', evt);\r\n (this as TypedEmitter).emit(evt.type, evt as any);\r\n }\r\n }\r\n } catch { }\r\n }\r\n\r\n private startHeartbeat(roomId: string): void {\r\n this.stopHeartbeat();\r\n this.heartbeatTimer = setInterval(() => {\r\n if (this.ws && this.ws.readyState === 1) {\r\n const hb = buildHeartbeat(roomId);\r\n this.ws.send(hb.buffer.byteLength === hb.length ? hb.buffer : hb.buffer.slice(hb.byteOffset, hb.byteOffset + hb.byteLength));\r\n }\r\n }, this.heartbeatInterval);\r\n }\r\n\r\n private stopHeartbeat(): void {\r\n if (this.heartbeatTimer) {\r\n clearInterval(this.heartbeatTimer);\r\n this.heartbeatTimer = null;\r\n }\r\n }\r\n}\r\n"],"mappings":"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","names":["DEFAULT_UA","DEFAULT_SIGN_SERVER"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tiktool/live",
3
- "version": "2.3.4",
3
+ "version": "2.4.1",
4
4
  "description": "TikTok LIVE API SDK — Real-time chat, gifts, battles, follows, likes & 18+ event types from any TikTok livestream via WebSocket. Zero dependencies. Works in Node.js, Bun, Deno, Cloudflare Workers & Durable Objects.",
5
5
  "author": "TikTool <hello@tik.tools>",
6
6
  "license": "MIT",