@tiktool/live 2.5.2 → 2.6.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/dist/index.js CHANGED
@@ -284,10 +284,24 @@ function parseUser(data) {
284
284
  }
285
285
  }
286
286
  const badges = [];
287
- const badgeBuf = getBytes(f, 64);
288
- if (badgeBuf) {
287
+ let payGrade;
288
+ const badgeBufs = getAllBytes(f, 64);
289
+ for (const badgeBuf of badgeBufs) {
289
290
  try {
290
291
  const badgeFields = decodeProto(badgeBuf);
292
+ const badgeCategory = getInt(badgeFields, 2);
293
+ const badgeSubCat = getInt(badgeFields, 3);
294
+ if (badgeCategory === 20 && badgeSubCat === 8 && !payGrade) {
295
+ const privBuf = getBytes(badgeFields, 12);
296
+ if (privBuf) {
297
+ const privFields = decodeProto(privBuf);
298
+ const levelStr = getStr(privFields, 5);
299
+ if (levelStr) {
300
+ const level = parseInt(levelStr, 10);
301
+ if (level > 0) payGrade = level;
302
+ }
303
+ }
304
+ }
291
305
  const badgeItems = getAllBytes(badgeFields, 21);
292
306
  for (const bi of badgeItems) {
293
307
  const bf = decodeProto(bi);
@@ -302,7 +316,8 @@ function parseUser(data) {
302
316
  nickname,
303
317
  uniqueId: uniqueId || nickname || id,
304
318
  profilePictureUrl: profilePicture,
305
- badges: badges.length > 0 ? badges : void 0
319
+ badges: badges.length > 0 ? badges : void 0,
320
+ payGrade
306
321
  };
307
322
  }
308
323
  function parseBattleTeamFromArmies(itemBuf) {
@@ -552,9 +567,27 @@ function parseWebcastMessage(method, payload) {
552
567
  return { ...base, type: "battle", battleId, status, battleDuration, teams, battleSettings };
553
568
  }
554
569
  case "WebcastLinkMicArmies": {
555
- const battleId = getIntStr(f, 1) || "";
570
+ const battleId = getIntStr(f, 2) || getIntStr(f, 1) || "";
556
571
  const battleStatus = getInt(f, 7);
557
572
  const teams = [];
573
+ let battleSettings;
574
+ const settingsBuf18 = getBytes(f, 18);
575
+ if (settingsBuf18) {
576
+ try {
577
+ const sf = decodeProto(settingsBuf18);
578
+ const startTimeMs = getInt(sf, 2);
579
+ const duration = getInt(sf, 3);
580
+ const endTimeMs = getInt(sf, 10);
581
+ battleSettings = {
582
+ startTimeMs: startTimeMs || void 0,
583
+ duration: duration || void 0,
584
+ endTimeMs: endTimeMs || void 0
585
+ };
586
+ } catch {
587
+ }
588
+ }
589
+ const scoreUpdateTime = getInt(f, 5);
590
+ const giftSentTime = getInt(f, 6);
558
591
  const itemBufs = getAllBytes(f, 3);
559
592
  for (const ib of itemBufs) {
560
593
  try {
@@ -567,7 +600,10 @@ function parseWebcastMessage(method, payload) {
567
600
  type: "battleArmies",
568
601
  battleId,
569
602
  teams,
570
- status: battleStatus
603
+ status: battleStatus,
604
+ battleSettings,
605
+ scoreUpdateTime,
606
+ giftSentTime
571
607
  };
572
608
  }
573
609
  case "WebcastSubNotifyMessage": {
@@ -866,6 +902,8 @@ var TikTokLive = class extends import_events.EventEmitter {
866
902
  _sessionId;
867
903
  _ttTargetIdc;
868
904
  proxyAgent;
905
+ _presetRoomId;
906
+ _presetTtwid;
869
907
  constructor(options) {
870
908
  super();
871
909
  this.uniqueId = options.uniqueId.replace(/^@/, "");
@@ -881,45 +919,51 @@ var TikTokLive = class extends import_events.EventEmitter {
881
919
  if (options.agent) {
882
920
  this.proxyAgent = options.agent;
883
921
  }
922
+ this._presetRoomId = options.roomId;
923
+ this._presetTtwid = options.ttwid;
884
924
  }
885
925
  async connect() {
886
926
  this.intentionalClose = false;
887
- const resp = await httpGet(`https://www.tiktok.com/@${this.uniqueId}/live`, {
888
- "User-Agent": DEFAULT_UA,
889
- "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
890
- "Accept-Encoding": "gzip, deflate, br",
891
- "Accept-Language": "en-US,en;q=0.9"
892
- }, this.proxyAgent);
893
- let ttwid = "";
894
- for (const sc of [resp.headers["set-cookie"] || []].flat()) {
895
- if (typeof sc === "string" && sc.startsWith("ttwid=")) {
896
- ttwid = sc.split(";")[0].split("=").slice(1).join("=");
897
- break;
898
- }
899
- }
900
- if (!ttwid) throw new Error("Failed to obtain session cookie");
901
- const html = resp.body.toString();
902
- let roomId = "";
927
+ let ttwid = this._presetTtwid || "";
928
+ let roomId = this._presetRoomId || "";
903
929
  let ownerUserId = "";
904
- const sigiMatch = html.match(/id="SIGI_STATE"[^>]*>([^<]+)/);
905
- if (sigiMatch) {
906
- try {
907
- const json = JSON.parse(sigiMatch[1]);
908
- const jsonStr = JSON.stringify(json);
909
- const m = jsonStr.match(/"roomId"\s*:\s*"(\d+)"/);
910
- if (m) roomId = m[1];
911
- const ownerUser = json?.LiveRoom?.liveRoomUserInfo?.user;
912
- if (ownerUser?.id) {
913
- ownerUserId = String(ownerUser.id);
930
+ let clusterRegion = "";
931
+ if (!roomId || !ttwid) {
932
+ const targetUrl = `https://www.tiktok.com/@${this.uniqueId}/live`;
933
+ const resp = await httpGet(targetUrl, {
934
+ "User-Agent": DEFAULT_UA,
935
+ "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
936
+ "Accept-Encoding": "gzip, deflate, br",
937
+ "Accept-Language": "en-US,en;q=0.9"
938
+ }, this.proxyAgent);
939
+ for (const sc of [resp.headers["set-cookie"] || []].flat()) {
940
+ if (typeof sc === "string" && sc.startsWith("ttwid=")) {
941
+ ttwid = sc.split(";")[0].split("=").slice(1).join("=");
942
+ break;
943
+ }
944
+ }
945
+ if (!ttwid) throw new Error("Failed to obtain session cookie");
946
+ const html = resp.body.toString();
947
+ const sigiMatch = html.match(/id="SIGI_STATE"[^>]*>([^<]+)/);
948
+ if (sigiMatch) {
949
+ try {
950
+ const json = JSON.parse(sigiMatch[1]);
951
+ const jsonStr = JSON.stringify(json);
952
+ const m = jsonStr.match(/"roomId"\s*:\s*"(\d+)"/);
953
+ if (m) roomId = m[1];
954
+ const ownerUser = json?.LiveRoom?.liveRoomUserInfo?.user;
955
+ if (ownerUser?.id) {
956
+ ownerUserId = String(ownerUser.id);
957
+ }
958
+ } catch {
914
959
  }
915
- } catch {
916
960
  }
961
+ if (!roomId) throw new Error(`User @${this.uniqueId} is not currently live`);
962
+ const crMatch = html.match(/"clusterRegion"\s*:\s*"([^"]+)"/);
963
+ clusterRegion = crMatch ? crMatch[1] : "";
917
964
  }
918
- if (!roomId) throw new Error(`User @${this.uniqueId} is not currently live`);
919
965
  this._roomId = roomId;
920
966
  this._ownerUserId = ownerUserId;
921
- const crMatch = html.match(/"clusterRegion"\s*:\s*"([^"]+)"/);
922
- const clusterRegion = crMatch ? crMatch[1] : "";
923
967
  const wsHost = getWsHost(clusterRegion);
924
968
  const wsParams = new URLSearchParams({
925
969
  version_code: "270000",
@@ -973,9 +1017,10 @@ var TikTokLive = class extends import_events.EventEmitter {
973
1017
  wsUrl = rawWsUrl.replace(/^https:\/\//, "wss://");
974
1018
  }
975
1019
  return new Promise((resolve, reject) => {
976
- let cookieHeader = `ttwid=${ttwid}`;
1020
+ let cookieHeader = ttwid ? `ttwid=${ttwid}` : "";
977
1021
  if (this._sessionId) {
978
- cookieHeader += `; sessionid=${this._sessionId}; sessionid_ss=${this._sessionId}; sid_tt=${this._sessionId}`;
1022
+ const sessionCookies = `sessionid=${this._sessionId}; sessionid_ss=${this._sessionId}; sid_tt=${this._sessionId}`;
1023
+ cookieHeader = cookieHeader ? `${cookieHeader}; ${sessionCookies}` : sessionCookies;
979
1024
  if (this._ttTargetIdc) {
980
1025
  cookieHeader += `; tt-target-idc=${this._ttTargetIdc}`;
981
1026
  }