@tiktool/live 2.5.2 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/dist/index.d.mts +581 -3
- package/dist/index.d.ts +581 -3
- package/dist/index.js +82 -37
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +82 -37
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -2
package/dist/index.mjs
CHANGED
|
@@ -246,10 +246,24 @@ function parseUser(data) {
|
|
|
246
246
|
}
|
|
247
247
|
}
|
|
248
248
|
const badges = [];
|
|
249
|
-
|
|
250
|
-
|
|
249
|
+
let payGrade;
|
|
250
|
+
const badgeBufs = getAllBytes(f, 64);
|
|
251
|
+
for (const badgeBuf of badgeBufs) {
|
|
251
252
|
try {
|
|
252
253
|
const badgeFields = decodeProto(badgeBuf);
|
|
254
|
+
const badgeCategory = getInt(badgeFields, 2);
|
|
255
|
+
const badgeSubCat = getInt(badgeFields, 3);
|
|
256
|
+
if (badgeCategory === 20 && badgeSubCat === 8 && !payGrade) {
|
|
257
|
+
const privBuf = getBytes(badgeFields, 12);
|
|
258
|
+
if (privBuf) {
|
|
259
|
+
const privFields = decodeProto(privBuf);
|
|
260
|
+
const levelStr = getStr(privFields, 5);
|
|
261
|
+
if (levelStr) {
|
|
262
|
+
const level = parseInt(levelStr, 10);
|
|
263
|
+
if (level > 0) payGrade = level;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
253
267
|
const badgeItems = getAllBytes(badgeFields, 21);
|
|
254
268
|
for (const bi of badgeItems) {
|
|
255
269
|
const bf = decodeProto(bi);
|
|
@@ -264,7 +278,8 @@ function parseUser(data) {
|
|
|
264
278
|
nickname,
|
|
265
279
|
uniqueId: uniqueId || nickname || id,
|
|
266
280
|
profilePictureUrl: profilePicture,
|
|
267
|
-
badges: badges.length > 0 ? badges : void 0
|
|
281
|
+
badges: badges.length > 0 ? badges : void 0,
|
|
282
|
+
payGrade
|
|
268
283
|
};
|
|
269
284
|
}
|
|
270
285
|
function parseBattleTeamFromArmies(itemBuf) {
|
|
@@ -514,9 +529,27 @@ function parseWebcastMessage(method, payload) {
|
|
|
514
529
|
return { ...base, type: "battle", battleId, status, battleDuration, teams, battleSettings };
|
|
515
530
|
}
|
|
516
531
|
case "WebcastLinkMicArmies": {
|
|
517
|
-
const battleId = getIntStr(f, 1) || "";
|
|
532
|
+
const battleId = getIntStr(f, 2) || getIntStr(f, 1) || "";
|
|
518
533
|
const battleStatus = getInt(f, 7);
|
|
519
534
|
const teams = [];
|
|
535
|
+
let battleSettings;
|
|
536
|
+
const settingsBuf18 = getBytes(f, 18);
|
|
537
|
+
if (settingsBuf18) {
|
|
538
|
+
try {
|
|
539
|
+
const sf = decodeProto(settingsBuf18);
|
|
540
|
+
const startTimeMs = getInt(sf, 2);
|
|
541
|
+
const duration = getInt(sf, 3);
|
|
542
|
+
const endTimeMs = getInt(sf, 10);
|
|
543
|
+
battleSettings = {
|
|
544
|
+
startTimeMs: startTimeMs || void 0,
|
|
545
|
+
duration: duration || void 0,
|
|
546
|
+
endTimeMs: endTimeMs || void 0
|
|
547
|
+
};
|
|
548
|
+
} catch {
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
const scoreUpdateTime = getInt(f, 5);
|
|
552
|
+
const giftSentTime = getInt(f, 6);
|
|
520
553
|
const itemBufs = getAllBytes(f, 3);
|
|
521
554
|
for (const ib of itemBufs) {
|
|
522
555
|
try {
|
|
@@ -529,7 +562,10 @@ function parseWebcastMessage(method, payload) {
|
|
|
529
562
|
type: "battleArmies",
|
|
530
563
|
battleId,
|
|
531
564
|
teams,
|
|
532
|
-
status: battleStatus
|
|
565
|
+
status: battleStatus,
|
|
566
|
+
battleSettings,
|
|
567
|
+
scoreUpdateTime,
|
|
568
|
+
giftSentTime
|
|
533
569
|
};
|
|
534
570
|
}
|
|
535
571
|
case "WebcastSubNotifyMessage": {
|
|
@@ -828,6 +864,8 @@ var TikTokLive = class extends EventEmitter {
|
|
|
828
864
|
_sessionId;
|
|
829
865
|
_ttTargetIdc;
|
|
830
866
|
proxyAgent;
|
|
867
|
+
_presetRoomId;
|
|
868
|
+
_presetTtwid;
|
|
831
869
|
constructor(options) {
|
|
832
870
|
super();
|
|
833
871
|
this.uniqueId = options.uniqueId.replace(/^@/, "");
|
|
@@ -843,45 +881,51 @@ var TikTokLive = class extends EventEmitter {
|
|
|
843
881
|
if (options.agent) {
|
|
844
882
|
this.proxyAgent = options.agent;
|
|
845
883
|
}
|
|
884
|
+
this._presetRoomId = options.roomId;
|
|
885
|
+
this._presetTtwid = options.ttwid;
|
|
846
886
|
}
|
|
847
887
|
async connect() {
|
|
848
888
|
this.intentionalClose = false;
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
|
|
852
|
-
"Accept-Encoding": "gzip, deflate, br",
|
|
853
|
-
"Accept-Language": "en-US,en;q=0.9"
|
|
854
|
-
}, this.proxyAgent);
|
|
855
|
-
let ttwid = "";
|
|
856
|
-
for (const sc of [resp.headers["set-cookie"] || []].flat()) {
|
|
857
|
-
if (typeof sc === "string" && sc.startsWith("ttwid=")) {
|
|
858
|
-
ttwid = sc.split(";")[0].split("=").slice(1).join("=");
|
|
859
|
-
break;
|
|
860
|
-
}
|
|
861
|
-
}
|
|
862
|
-
if (!ttwid) throw new Error("Failed to obtain session cookie");
|
|
863
|
-
const html = resp.body.toString();
|
|
864
|
-
let roomId = "";
|
|
889
|
+
let ttwid = this._presetTtwid || "";
|
|
890
|
+
let roomId = this._presetRoomId || "";
|
|
865
891
|
let ownerUserId = "";
|
|
866
|
-
|
|
867
|
-
if (
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
892
|
+
let clusterRegion = "";
|
|
893
|
+
if (!roomId || !ttwid) {
|
|
894
|
+
const targetUrl = `https://www.tiktok.com/@${this.uniqueId}/live`;
|
|
895
|
+
const resp = await httpGet(targetUrl, {
|
|
896
|
+
"User-Agent": DEFAULT_UA,
|
|
897
|
+
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
|
|
898
|
+
"Accept-Encoding": "gzip, deflate, br",
|
|
899
|
+
"Accept-Language": "en-US,en;q=0.9"
|
|
900
|
+
}, this.proxyAgent);
|
|
901
|
+
for (const sc of [resp.headers["set-cookie"] || []].flat()) {
|
|
902
|
+
if (typeof sc === "string" && sc.startsWith("ttwid=")) {
|
|
903
|
+
ttwid = sc.split(";")[0].split("=").slice(1).join("=");
|
|
904
|
+
break;
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
if (!ttwid) throw new Error("Failed to obtain session cookie");
|
|
908
|
+
const html = resp.body.toString();
|
|
909
|
+
const sigiMatch = html.match(/id="SIGI_STATE"[^>]*>([^<]+)/);
|
|
910
|
+
if (sigiMatch) {
|
|
911
|
+
try {
|
|
912
|
+
const json = JSON.parse(sigiMatch[1]);
|
|
913
|
+
const jsonStr = JSON.stringify(json);
|
|
914
|
+
const m = jsonStr.match(/"roomId"\s*:\s*"(\d+)"/);
|
|
915
|
+
if (m) roomId = m[1];
|
|
916
|
+
const ownerUser = json?.LiveRoom?.liveRoomUserInfo?.user;
|
|
917
|
+
if (ownerUser?.id) {
|
|
918
|
+
ownerUserId = String(ownerUser.id);
|
|
919
|
+
}
|
|
920
|
+
} catch {
|
|
876
921
|
}
|
|
877
|
-
} catch {
|
|
878
922
|
}
|
|
923
|
+
if (!roomId) throw new Error(`User @${this.uniqueId} is not currently live`);
|
|
924
|
+
const crMatch = html.match(/"clusterRegion"\s*:\s*"([^"]+)"/);
|
|
925
|
+
clusterRegion = crMatch ? crMatch[1] : "";
|
|
879
926
|
}
|
|
880
|
-
if (!roomId) throw new Error(`User @${this.uniqueId} is not currently live`);
|
|
881
927
|
this._roomId = roomId;
|
|
882
928
|
this._ownerUserId = ownerUserId;
|
|
883
|
-
const crMatch = html.match(/"clusterRegion"\s*:\s*"([^"]+)"/);
|
|
884
|
-
const clusterRegion = crMatch ? crMatch[1] : "";
|
|
885
929
|
const wsHost = getWsHost(clusterRegion);
|
|
886
930
|
const wsParams = new URLSearchParams({
|
|
887
931
|
version_code: "270000",
|
|
@@ -935,9 +979,10 @@ var TikTokLive = class extends EventEmitter {
|
|
|
935
979
|
wsUrl = rawWsUrl.replace(/^https:\/\//, "wss://");
|
|
936
980
|
}
|
|
937
981
|
return new Promise((resolve, reject) => {
|
|
938
|
-
let cookieHeader = `ttwid=${ttwid}
|
|
982
|
+
let cookieHeader = ttwid ? `ttwid=${ttwid}` : "";
|
|
939
983
|
if (this._sessionId) {
|
|
940
|
-
|
|
984
|
+
const sessionCookies = `sessionid=${this._sessionId}; sessionid_ss=${this._sessionId}; sid_tt=${this._sessionId}`;
|
|
985
|
+
cookieHeader = cookieHeader ? `${cookieHeader}; ${sessionCookies}` : sessionCookies;
|
|
941
986
|
if (this._ttTargetIdc) {
|
|
942
987
|
cookieHeader += `; tt-target-idc=${this._ttTargetIdc}`;
|
|
943
988
|
}
|