@ikenxuan/amagi 5.5.1 → 5.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.
@@ -5,7 +5,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  var chalk = require('chalk');
6
6
  var log4js = require('log4js');
7
7
  var path = require('path');
8
- var url = require('url');
8
+ var URL2 = require('url');
9
9
  var fs = require('fs');
10
10
  var axios = require('axios');
11
11
  var crypto = require('crypto');
@@ -17,6 +17,7 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
17
17
 
18
18
  var log4js__default = /*#__PURE__*/_interopDefault(log4js);
19
19
  var path__default = /*#__PURE__*/_interopDefault(path);
20
+ var URL2__default = /*#__PURE__*/_interopDefault(URL2);
20
21
  var fs__default = /*#__PURE__*/_interopDefault(fs);
21
22
  var axios__default = /*#__PURE__*/_interopDefault(axios);
22
23
  var crypto__default = /*#__PURE__*/_interopDefault(crypto);
@@ -33,7 +34,7 @@ var getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${_
33
34
  var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
34
35
  var getPackageLogsPath = () => {
35
36
  const currentFileUrl = importMetaUrl;
36
- const currentFilePath = url.fileURLToPath(currentFileUrl);
37
+ const currentFilePath = URL2.fileURLToPath(currentFileUrl);
37
38
  const currentDir = path__default.default.dirname(currentFilePath);
38
39
  let packageRoot = currentDir;
39
40
  while (packageRoot !== path__default.default.dirname(packageRoot)) {
@@ -1332,6 +1333,184 @@ var a_bogus_default = (url, user_agent) => {
1332
1333
  let result_str = generate_random_str() + generate_rc4_bb_str(new URLSearchParams(new URL(url).search).toString(), cleanedUserAgent, "1536|747|1536|834|0|30|0|0|1536|834|1536|864|1525|747|24|24|Win32");
1333
1334
  return result_encrypt(result_str, "s4") + "=";
1334
1335
  };
1336
+ var XBogus = class {
1337
+ charMap;
1338
+ base64Charset;
1339
+ uaKey;
1340
+ defaultUa;
1341
+ params;
1342
+ xb;
1343
+ constructor() {
1344
+ this.charMap = new Array(128).fill(null);
1345
+ for (let i = 48; i <= 57; i++) {
1346
+ this.charMap[i] = i - 48;
1347
+ }
1348
+ for (let i = 65; i <= 70; i++) {
1349
+ this.charMap[i] = i - 55;
1350
+ }
1351
+ for (let i = 97; i <= 102; i++) {
1352
+ this.charMap[i] = i - 87;
1353
+ }
1354
+ this.base64Charset = "Dkdpgh4ZKsQB80/Mfvw36XI1R25-WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe=";
1355
+ this.uaKey = Buffer.from([0, 1, 12]);
1356
+ this.defaultUa = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0";
1357
+ }
1358
+ md5StrToArray(md5Str) {
1359
+ const result = [];
1360
+ if (md5Str.length > 32) {
1361
+ for (const char of md5Str) {
1362
+ result.push(char.charCodeAt(0));
1363
+ }
1364
+ return result;
1365
+ }
1366
+ let idx = 0;
1367
+ while (idx < md5Str.length) {
1368
+ const leftCharCode = md5Str.charCodeAt(idx);
1369
+ const rightCharCode = md5Str.charCodeAt(idx + 1);
1370
+ const left = this.charMap[leftCharCode];
1371
+ const right = this.charMap[rightCharCode];
1372
+ if (left === null || right === null) {
1373
+ throw new Error(`Invalid MD5 character: ${md5Str[idx]}${md5Str[idx + 1]}`);
1374
+ }
1375
+ result.push(left << 4 | right);
1376
+ idx += 2;
1377
+ }
1378
+ return result;
1379
+ }
1380
+ md5(input) {
1381
+ const dataArray = typeof input === "string" ? this.md5StrToArray(input) : input;
1382
+ const dataBuffer = Buffer.from(dataArray);
1383
+ return crypto__default.default.createHash("md5").update(dataBuffer).digest("hex");
1384
+ }
1385
+ md5Encrypt(urlPath) {
1386
+ const firstMd5 = this.md5(urlPath);
1387
+ const firstArray = this.md5StrToArray(firstMd5);
1388
+ const secondMd5 = this.md5(firstArray);
1389
+ return this.md5StrToArray(secondMd5);
1390
+ }
1391
+ encodingConversion(...params) {
1392
+ const byteList = [];
1393
+ for (const param of params) {
1394
+ if (typeof param === "number") {
1395
+ byteList.push(Math.floor(param));
1396
+ } else if (typeof param === "string") {
1397
+ for (const char of param) {
1398
+ byteList.push(char.charCodeAt(0));
1399
+ }
1400
+ }
1401
+ }
1402
+ return Buffer.from(byteList).toString("latin1");
1403
+ }
1404
+ encodingConversion2(a, b, c) {
1405
+ return String.fromCharCode(a) + String.fromCharCode(b) + c;
1406
+ }
1407
+ rc4Encrypt(key, data2) {
1408
+ const keyBuffer = typeof key === "string" ? Buffer.from(key, "latin1") : key;
1409
+ const dataBuffer = Buffer.from(data2, "latin1");
1410
+ const S = Array.from({ length: 256 }, (_, i2) => i2);
1411
+ let j = 0;
1412
+ for (let i2 = 0; i2 < 256; i2++) {
1413
+ j = (j + S[i2] + keyBuffer[i2 % keyBuffer.length]) % 256;
1414
+ [S[i2], S[j]] = [S[j], S[i2]];
1415
+ }
1416
+ const encryptedBuffer = Buffer.alloc(dataBuffer.length);
1417
+ let i = 0;
1418
+ j = 0;
1419
+ for (let k = 0; k < dataBuffer.length; k++) {
1420
+ i = (i + 1) % 256;
1421
+ j = (j + S[i]) % 256;
1422
+ [S[i], S[j]] = [S[j], S[i]];
1423
+ const t = (S[i] + S[j]) % 256;
1424
+ encryptedBuffer[k] = dataBuffer[k] ^ S[t];
1425
+ }
1426
+ return encryptedBuffer.toString("latin1");
1427
+ }
1428
+ calculation(a1, a2, a3) {
1429
+ const x1 = (a1 & 255) << 16;
1430
+ const x2 = (a2 & 255) << 8;
1431
+ const x3 = x1 | x2 | a3 & 255;
1432
+ const c1 = this.base64Charset[(x3 & 16760832) >> 18];
1433
+ const c2 = this.base64Charset[(x3 & 258048) >> 12];
1434
+ const c3 = this.base64Charset[(x3 & 4032) >> 6];
1435
+ const c4 = this.base64Charset[x3 & 63];
1436
+ return c1 + c2 + c3 + c4;
1437
+ }
1438
+ /**
1439
+ * 生成X-Bogus签名
1440
+ * @param url 完整的URL地址
1441
+ * @param ua 可选的User-Agent,不提供则使用默认值
1442
+ * @returns 包含完整URL、X-Bogus值和使用的User-Agent的元组
1443
+ */
1444
+ getXBogus(url, ua) {
1445
+ const parsedUrl = new URL2__default.default.URL(url);
1446
+ const urlPath = parsedUrl.pathname + parsedUrl.search;
1447
+ const currentUa = ua || this.defaultUa;
1448
+ const rc4EncryptedUa = this.rc4Encrypt(this.uaKey, currentUa);
1449
+ const base64Ua = Buffer.from(rc4EncryptedUa, "latin1").toString("base64");
1450
+ const md5Ua = this.md5(base64Ua);
1451
+ const array1 = this.md5StrToArray(md5Ua);
1452
+ const emptyStrMd5 = "d41d8cd98f00b204e9800998ecf8427e";
1453
+ const array2 = this.md5StrToArray(this.md5(this.md5StrToArray(emptyStrMd5)));
1454
+ const urlEncryptedArray = this.md5Encrypt(urlPath);
1455
+ const timestamp = Math.floor(Date.now() / 1e3);
1456
+ const ct = 536919696;
1457
+ const newArray = [
1458
+ 64,
1459
+ 1,
1460
+ 1,
1461
+ 12,
1462
+ urlEncryptedArray[14],
1463
+ urlEncryptedArray[15],
1464
+ array2[14],
1465
+ array2[15],
1466
+ array1[14],
1467
+ array1[15],
1468
+ timestamp >> 24 & 255,
1469
+ timestamp >> 16 & 255,
1470
+ timestamp >> 8 & 255,
1471
+ timestamp & 255,
1472
+ ct >> 24 & 255,
1473
+ ct >> 16 & 255,
1474
+ ct >> 8 & 255,
1475
+ ct & 255
1476
+ ];
1477
+ let xorResult = newArray[0];
1478
+ for (let i = 1; i < newArray.length; i++) {
1479
+ xorResult ^= newArray[i];
1480
+ }
1481
+ newArray.push(xorResult);
1482
+ const array3 = [];
1483
+ const array4 = [];
1484
+ let idx = 0;
1485
+ while (idx < newArray.length) {
1486
+ array3.push(newArray[idx]);
1487
+ if (idx + 1 < newArray.length) {
1488
+ array4.push(newArray[idx + 1]);
1489
+ }
1490
+ idx += 2;
1491
+ }
1492
+ const mergedArray = [...array3, ...array4];
1493
+ const firstConversion = this.encodingConversion(...mergedArray);
1494
+ const rc4Garbled = this.rc4Encrypt("\xFF", firstConversion);
1495
+ const garbledCode = this.encodingConversion2(2, 255, rc4Garbled);
1496
+ let xb = "";
1497
+ idx = 0;
1498
+ while (idx < garbledCode.length) {
1499
+ if (idx + 2 >= garbledCode.length) break;
1500
+ const a1 = garbledCode.charCodeAt(idx);
1501
+ const a2 = garbledCode.charCodeAt(idx + 1);
1502
+ const a3 = garbledCode.charCodeAt(idx + 2);
1503
+ xb += this.calculation(a1, a2, a3);
1504
+ idx += 3;
1505
+ }
1506
+ const fullUrl = url.includes("?") ? `${url}&X-Bogus=${xb}` : `${url}?X-Bogus=${xb}`;
1507
+ return {
1508
+ fullUrl,
1509
+ xbogus: xb,
1510
+ userAgent: currentUa
1511
+ };
1512
+ }
1513
+ };
1335
1514
 
1336
1515
  // src/platform/douyin/sign/index.ts
1337
1516
  var defaultUserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36";
@@ -1354,6 +1533,15 @@ var douyinSign = class {
1354
1533
  static AB(url, userAgent) {
1355
1534
  return a_bogus_default(url, userAgent || defaultUserAgent);
1356
1535
  }
1536
+ /**
1537
+ * X-Bogus 签名算法
1538
+ * @param url 需要签名的地址
1539
+ * @returns 对此地址签名后的URL查询参数
1540
+ */
1541
+ static XB(url, userAgent) {
1542
+ const xbogusResult = new XBogus().getXBogus(url, userAgent || defaultUserAgent);
1543
+ return xbogusResult.xbogus;
1544
+ }
1357
1545
  /** 生成一个唯一的验证字符串 */
1358
1546
  static VerifyFpManager() {
1359
1547
  const e = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split("");
@@ -1482,7 +1670,7 @@ var DouyinAPI = class {
1482
1670
  * @returns 完整的接口URL
1483
1671
  */
1484
1672
  \u4E8C\u7EA7\u8BC4\u8BBA(data2) {
1485
- const baseUrl = "https://www.douyin.com/aweme/v1/web/comment/list/reply/";
1673
+ const baseUrl = "https://www-hj.douyin.com/aweme/v1/web/comment/list/reply/";
1486
1674
  const params = {
1487
1675
  device_platform: "webapp",
1488
1676
  aid: "6383",
@@ -1506,10 +1694,10 @@ var DouyinAPI = class {
1506
1694
  browser_language: "zh-CN",
1507
1695
  browser_platform: "Win32",
1508
1696
  browser_name: "Edge",
1509
- browser_version: "132.0.0.0",
1697
+ browser_version: this.browserVersion,
1510
1698
  browser_online: "true",
1511
1699
  engine_name: "Blink",
1512
- engine_version: "132.0.0.0",
1700
+ engine_version: this.browserVersion,
1513
1701
  os_name: "Windows",
1514
1702
  os_version: "10",
1515
1703
  cpu_core_num: "16",
@@ -1518,7 +1706,7 @@ var DouyinAPI = class {
1518
1706
  downlink: "10",
1519
1707
  effective_type: "4g",
1520
1708
  round_trip_time: "50",
1521
- webid: "7386217876267796006",
1709
+ webid: "7487210762873685515",
1522
1710
  verifyFp: fp,
1523
1711
  fp
1524
1712
  };
@@ -1822,6 +2010,29 @@ var createDouyinApiUrls = (userAgent) => {
1822
2010
  var douyinApiUrls = new DouyinAPI();
1823
2011
 
1824
2012
  // src/platform/douyin/getdata.ts
2013
+ var getSignature = (url, signType = "a_bogus", userAgent) => {
2014
+ switch (signType) {
2015
+ case "x_bogus":
2016
+ return douyinSign.XB(url, userAgent);
2017
+ case "a_bogus":
2018
+ default:
2019
+ return douyinSign.AB(url, userAgent);
2020
+ }
2021
+ };
2022
+ var getSignParamName = (signType = "a_bogus") => {
2023
+ switch (signType) {
2024
+ case "x_bogus":
2025
+ return "X-Bogus";
2026
+ case "a_bogus":
2027
+ default:
2028
+ return "a_bogus";
2029
+ }
2030
+ };
2031
+ var buildSignedUrl = (url, signType = "a_bogus", userAgent) => {
2032
+ const signature = getSignature(url, signType, userAgent);
2033
+ const paramName = getSignParamName(signType);
2034
+ return `${url}&${paramName}=${signature}`;
2035
+ };
1825
2036
  var DouyinData = async (data2, cookie, requestConfig) => {
1826
2037
  var _a, _b, _c, _d, _e;
1827
2038
  const defHeaders = getDouyinDefaultConfig(cookie)["headers"];
@@ -1835,54 +2046,47 @@ var DouyinData = async (data2, cookie, requestConfig) => {
1835
2046
  }
1836
2047
  };
1837
2048
  const userAgent = (_a = baseRequestConfig.headers) == null ? void 0 : _a["User-Agent"];
1838
- const douyinApiUrls3 = createDouyinApiUrls(userAgent);
2049
+ const douyinApiUrls2 = createDouyinApiUrls(userAgent);
2050
+ const signType = data2.signType || "a_bogus";
1839
2051
  switch (data2.methodType) {
1840
2052
  case "\u6587\u5B57\u4F5C\u54C1\u6570\u636E":
1841
2053
  case "\u805A\u5408\u89E3\u6790":
1842
2054
  case "\u89C6\u9891\u4F5C\u54C1\u6570\u636E":
1843
2055
  case "\u56FE\u96C6\u4F5C\u54C1\u6570\u636E":
1844
2056
  case "\u5408\u8F91\u4F5C\u54C1\u6570\u636E": {
1845
- const url = douyinApiUrls3.\u89C6\u9891\u6216\u56FE\u96C6({ aweme_id: data2.aweme_id });
2057
+ const url = douyinApiUrls2.\u89C6\u9891\u6216\u56FE\u96C6({ aweme_id: data2.aweme_id });
1846
2058
  const VideoData = await GlobalGetData2(data2.methodType, {
1847
2059
  ...baseRequestConfig,
1848
- url: `${url}&a_bogus=${douyinSign.AB(url, userAgent)}`
2060
+ url: buildSignedUrl(url, signType, userAgent)
1849
2061
  });
1850
2062
  return VideoData;
1851
2063
  }
1852
2064
  case "\u8BC4\u8BBA\u6570\u636E": {
1853
- const urlGenerator = (params) => douyinApiUrls3.\u8BC4\u8BBA(params);
2065
+ const urlGenerator = (params) => douyinApiUrls2.\u8BC4\u8BBA(params);
1854
2066
  const response = await fetchPaginatedData(
1855
2067
  data2.methodType,
1856
2068
  urlGenerator,
1857
2069
  data2,
1858
2070
  50,
1859
- baseRequestConfig
2071
+ baseRequestConfig,
2072
+ signType
1860
2073
  );
1861
2074
  return response;
1862
2075
  }
1863
2076
  case "\u6307\u5B9A\u8BC4\u8BBA\u56DE\u590D\u6570\u636E": {
1864
- const urlGenerator = (params) => douyinApiUrls3.\u4E8C\u7EA7\u8BC4\u8BBA(params);
1865
- const customConfig = {
1866
- ...baseRequestConfig,
1867
- headers: {
1868
- ...baseRequestConfig.headers,
1869
- // 只有在外部配置没有referer时才设置内部的referer
1870
- ...(!(requestConfig == null ? void 0 : requestConfig.headers) || !("referer" in requestConfig.headers)) && {
1871
- referer: `https://www.douyin.com/note/${data2.aweme_id}`
1872
- }
1873
- }
1874
- };
2077
+ const urlGenerator = (params) => douyinApiUrls2.\u4E8C\u7EA7\u8BC4\u8BBA(params);
1875
2078
  const response = await fetchPaginatedData(
1876
2079
  data2.methodType,
1877
2080
  urlGenerator,
1878
2081
  data2,
1879
2082
  3,
1880
- customConfig
2083
+ baseRequestConfig,
2084
+ "x_bogus"
1881
2085
  );
1882
2086
  return response;
1883
2087
  }
1884
2088
  case "\u7528\u6237\u4E3B\u9875\u6570\u636E": {
1885
- const url = douyinApiUrls3.\u7528\u6237\u4E3B\u9875\u4FE1\u606F({ sec_uid: data2.sec_uid });
2089
+ const url = douyinApiUrls2.\u7528\u6237\u4E3B\u9875\u4FE1\u606F({ sec_uid: data2.sec_uid });
1886
2090
  const customConfig = {
1887
2091
  ...baseRequestConfig,
1888
2092
  headers: {
@@ -1895,12 +2099,12 @@ var DouyinData = async (data2, cookie, requestConfig) => {
1895
2099
  };
1896
2100
  const UserInfoData = await GlobalGetData2(data2.methodType, {
1897
2101
  ...customConfig,
1898
- url: `${url}&a_bogus=${douyinSign.AB(url, userAgent)}`
2102
+ url: buildSignedUrl(url, signType, userAgent)
1899
2103
  });
1900
2104
  return UserInfoData;
1901
2105
  }
1902
2106
  case "Emoji\u6570\u636E": {
1903
- const url = douyinApiUrls3.\u8868\u60C5();
2107
+ const url = douyinApiUrls2.\u8868\u60C5();
1904
2108
  const EmojiData = await GlobalGetData2(data2.methodType, {
1905
2109
  ...baseRequestConfig,
1906
2110
  url
@@ -1908,7 +2112,7 @@ var DouyinData = async (data2, cookie, requestConfig) => {
1908
2112
  return EmojiData;
1909
2113
  }
1910
2114
  case "\u7528\u6237\u4E3B\u9875\u89C6\u9891\u5217\u8868\u6570\u636E": {
1911
- const url = douyinApiUrls3.\u7528\u6237\u4E3B\u9875\u89C6\u9891({ sec_uid: data2.sec_uid });
2115
+ const url = douyinApiUrls2.\u7528\u6237\u4E3B\u9875\u89C6\u9891({ sec_uid: data2.sec_uid });
1912
2116
  const customConfig = {
1913
2117
  ...baseRequestConfig,
1914
2118
  headers: {
@@ -1920,12 +2124,12 @@ var DouyinData = async (data2, cookie, requestConfig) => {
1920
2124
  };
1921
2125
  const UserVideoListData = await GlobalGetData2(data2.methodType, {
1922
2126
  ...customConfig,
1923
- url: `${url}&a_bogus=${douyinSign.AB(url, userAgent)}`
2127
+ url: buildSignedUrl(url, signType, userAgent)
1924
2128
  });
1925
2129
  return UserVideoListData;
1926
2130
  }
1927
2131
  case "\u70ED\u70B9\u8BCD\u6570\u636E": {
1928
- const url = douyinApiUrls3.\u70ED\u70B9\u8BCD({ query: data2.query, number: data2.number ?? 10 });
2132
+ const url = douyinApiUrls2.\u70ED\u70B9\u8BCD({ query: data2.query, number: data2.number ?? 10 });
1929
2133
  const customConfig = {
1930
2134
  ...baseRequestConfig,
1931
2135
  headers: {
@@ -1937,7 +2141,7 @@ var DouyinData = async (data2, cookie, requestConfig) => {
1937
2141
  };
1938
2142
  const SuggestWordsData = await GlobalGetData2(data2.methodType, {
1939
2143
  ...customConfig,
1940
- url: `${url}&a_bogus=${douyinSign.AB(url, userAgent)}`
2144
+ url: buildSignedUrl(url, signType, userAgent)
1941
2145
  });
1942
2146
  return SuggestWordsData;
1943
2147
  }
@@ -1957,14 +2161,14 @@ var DouyinData = async (data2, cookie, requestConfig) => {
1957
2161
  };
1958
2162
  while (fetchedSearchList.length < Number(data2.number ?? 10)) {
1959
2163
  const requestCount = Math.min(Number(data2.number ?? 50) - fetchedSearchList.length, maxPageSize);
1960
- const url = douyinApiUrls3.\u641C\u7D22({
2164
+ const url = douyinApiUrls2.\u641C\u7D22({
1961
2165
  query: data2.query,
1962
2166
  number: requestCount,
1963
2167
  search_id: search_id === "" ? void 0 : search_id
1964
2168
  });
1965
2169
  const response = await GlobalGetData2(data2.methodType, {
1966
2170
  ...customConfig,
1967
- url: `${url}&a_bogus=${douyinSign.AB(url, userAgent)}`
2171
+ url: buildSignedUrl(url, signType, userAgent)
1968
2172
  });
1969
2173
  if (((_b = response.data) == null ? void 0 : _b.length) === 0) {
1970
2174
  logger.warn("\u83B7\u53D6\u641C\u7D22\u6570\u636E\u5931\u8D25\uFF01\u8BF7\u6C42\u6210\u529F\u4F46\u63A5\u53E3\u8FD4\u56DE\u5185\u5BB9\u4E3A\u7A7A\n\u4F60\u7684\u6296\u97F3ck\u53EF\u80FD\u5DF2\u7ECF\u5931\u6548\uFF01\n\u8BF7\u6C42\u7C7B\u578B\uFF1A" + data2.methodType);
@@ -1984,24 +2188,24 @@ var DouyinData = async (data2, cookie, requestConfig) => {
1984
2188
  return finalResponse;
1985
2189
  }
1986
2190
  case "\u52A8\u6001\u8868\u60C5\u6570\u636E": {
1987
- const url = douyinApiUrls3.\u4E92\u52A8\u8868\u60C5();
2191
+ const url = douyinApiUrls2.\u4E92\u52A8\u8868\u60C5();
1988
2192
  const ExpressionPlusData = await GlobalGetData2(data2.methodType, {
1989
2193
  ...baseRequestConfig,
1990
- url: `${url}&a_bogus=${douyinSign.AB(url, userAgent)}`
2194
+ url: buildSignedUrl(url, signType, userAgent)
1991
2195
  });
1992
2196
  return ExpressionPlusData;
1993
2197
  }
1994
2198
  case "\u97F3\u4E50\u6570\u636E": {
1995
- const url = douyinApiUrls3.\u80CC\u666F\u97F3\u4E50({ music_id: data2.music_id });
2199
+ const url = douyinApiUrls2.\u80CC\u666F\u97F3\u4E50({ music_id: data2.music_id });
1996
2200
  const MusicData = await GlobalGetData2(data2.methodType, {
1997
2201
  ...baseRequestConfig,
1998
- url: `${url}&a_bogus=${douyinSign.AB(url, userAgent)}`
2202
+ url: buildSignedUrl(url, signType, userAgent)
1999
2203
  });
2000
2204
  return MusicData;
2001
2205
  }
2002
2206
  case "\u76F4\u64AD\u95F4\u4FE1\u606F\u6570\u636E": {
2003
- let url = douyinApiUrls3.\u7528\u6237\u4E3B\u9875\u4FE1\u606F({ sec_uid: data2.sec_uid });
2004
- const fetchUrl = `${url}&a_bogus=${douyinSign.AB(url, userAgent)}`;
2207
+ let url = douyinApiUrls2.\u7528\u6237\u4E3B\u9875\u4FE1\u606F({ sec_uid: data2.sec_uid });
2208
+ const fetchUrl = buildSignedUrl(url, signType, userAgent);
2005
2209
  const customConfig = {
2006
2210
  ...baseRequestConfig,
2007
2211
  headers: {
@@ -2038,7 +2242,7 @@ var DouyinData = async (data2, cookie, requestConfig) => {
2038
2242
  };
2039
2243
  }
2040
2244
  const room_data = JSON.parse(UserInfoData.user.room_data);
2041
- url = douyinApiUrls3.\u76F4\u64AD\u95F4\u4FE1\u606F({ room_id: UserInfoData.user.room_id_str, web_rid: room_data.owner.web_rid });
2245
+ url = douyinApiUrls2.\u76F4\u64AD\u95F4\u4FE1\u606F({ room_id: UserInfoData.user.room_id_str, web_rid: room_data.owner.web_rid });
2042
2246
  const liveCustomConfig = {
2043
2247
  ...baseRequestConfig,
2044
2248
  headers: {
@@ -2050,15 +2254,15 @@ var DouyinData = async (data2, cookie, requestConfig) => {
2050
2254
  };
2051
2255
  const LiveRoomData = await GlobalGetData2(data2.methodType, {
2052
2256
  ...liveCustomConfig,
2053
- url: `${url}&a_bogus=${douyinSign.AB(url, userAgent)}`
2257
+ url: buildSignedUrl(url, signType, userAgent)
2054
2258
  });
2055
2259
  return LiveRoomData;
2056
2260
  }
2057
2261
  case "\u7533\u8BF7\u4E8C\u7EF4\u7801\u6570\u636E": {
2058
- const url = douyinApiUrls3.\u7533\u8BF7\u4E8C\u7EF4\u7801({ verify_fp: data2.verify_fp });
2262
+ const url = douyinApiUrls2.\u7533\u8BF7\u4E8C\u7EF4\u7801({ verify_fp: data2.verify_fp });
2059
2263
  const LoginQrcodeStatusData = await GlobalGetData2(data2.methodType, {
2060
2264
  ...baseRequestConfig,
2061
- url: `${url}&a_bogus=${douyinSign.AB(url, userAgent)}`
2265
+ url: buildSignedUrl(url, signType, userAgent)
2062
2266
  });
2063
2267
  return LoginQrcodeStatusData;
2064
2268
  }
@@ -2068,7 +2272,7 @@ var DouyinData = async (data2, cookie, requestConfig) => {
2068
2272
  const endTime = data2.end_time ?? data2.duration;
2069
2273
  const totalDuration = endTime - startTime;
2070
2274
  if (totalDuration <= MAX_SEGMENT_DURATION) {
2071
- const url = douyinApiUrls3.\u5F39\u5E55({
2275
+ const url = douyinApiUrls2.\u5F39\u5E55({
2072
2276
  aweme_id: data2.aweme_id,
2073
2277
  start_time: startTime,
2074
2278
  end_time: endTime,
@@ -2076,7 +2280,7 @@ var DouyinData = async (data2, cookie, requestConfig) => {
2076
2280
  });
2077
2281
  const DanmakuData = await GlobalGetData2(data2.methodType, {
2078
2282
  ...baseRequestConfig,
2079
- url: `${url}&a_bogus=${douyinSign.AB(url, userAgent)}`
2283
+ url: buildSignedUrl(url, signType, userAgent)
2080
2284
  });
2081
2285
  return DanmakuData;
2082
2286
  }
@@ -2089,7 +2293,7 @@ var DouyinData = async (data2, cookie, requestConfig) => {
2089
2293
  }
2090
2294
  logger.debug(`\u5F39\u5E55\u6570\u636E\u9700\u8981\u5206${segments.length}\u6BB5\u83B7\u53D6\uFF0C\u603B\u65F6\u957F\uFF1A${totalDuration}ms`);
2091
2295
  const segmentPromises = segments.map(async (segment, index) => {
2092
- const url = douyinApiUrls3.\u5F39\u5E55({
2296
+ const url = douyinApiUrls2.\u5F39\u5E55({
2093
2297
  aweme_id: data2.aweme_id,
2094
2298
  start_time: segment.start,
2095
2299
  end_time: segment.end,
@@ -2098,7 +2302,7 @@ var DouyinData = async (data2, cookie, requestConfig) => {
2098
2302
  try {
2099
2303
  const segmentData = await GlobalGetData2(`${data2.methodType}-\u6BB5${index + 1}`, {
2100
2304
  ...baseRequestConfig,
2101
- url: `${url}&a_bogus=${douyinSign.AB(url, userAgent)}`
2305
+ url: buildSignedUrl(url, signType, userAgent)
2102
2306
  });
2103
2307
  logger.debug(`\u5F39\u5E55\u7B2C${index + 1}\u6BB5\u83B7\u53D6\u6210\u529F (${segment.start}ms-${segment.end}ms)`);
2104
2308
  return segmentData;
@@ -2146,7 +2350,7 @@ var DouyinData = async (data2, cookie, requestConfig) => {
2146
2350
  }
2147
2351
  }
2148
2352
  };
2149
- var fetchPaginatedData = async (type, apiUrlGenerator, params, maxPageSize, requestConfig) => {
2353
+ var fetchPaginatedData = async (type, apiUrlGenerator, params, maxPageSize, requestConfig, signType = "a_bogus") => {
2150
2354
  var _a;
2151
2355
  let cursor = params.cursor ?? 0;
2152
2356
  let fetchedData = [];
@@ -2161,7 +2365,7 @@ var fetchPaginatedData = async (type, apiUrlGenerator, params, maxPageSize, requ
2161
2365
  });
2162
2366
  const response = await GlobalGetData2(type, {
2163
2367
  ...requestConfig,
2164
- url: `${url}&a_bogus=${douyinSign.AB(url, userAgent)}`
2368
+ url: buildSignedUrl(url, signType, userAgent)
2165
2369
  });
2166
2370
  fetchedData.push(...response.comments || response.data || []);
2167
2371
  tmpresp = response;
@@ -2452,7 +2656,7 @@ var DouyinDanmakuParamsSchema = zod.z.object({
2452
2656
  aweme_id: zod.z.string({ error: "\u89C6\u9891ID\u5FC5\u987B\u662F\u5B57\u7B26\u4E32" }).min(1, { error: "\u89C6\u9891ID\u4E0D\u80FD\u4E3A\u7A7A" }),
2453
2657
  start_time: zod.z.coerce.number({ error: "\u5F00\u59CB\u65F6\u95F4\u5FC5\u987B\u662F\u6570\u5B57" }).int({ error: "\u5F00\u59CB\u65F6\u95F4\u5FC5\u987B\u662F\u6574\u6570" }).min(0, { error: "\u5F00\u59CB\u65F6\u95F4\u4E0D\u80FD\u5C0F\u4E8E0" }).optional(),
2454
2658
  end_time: zod.z.coerce.number({ error: "\u7ED3\u675F\u65F6\u95F4\u5FC5\u987B\u662F\u6570\u5B57" }).int({ error: "\u7ED3\u675F\u65F6\u95F4\u5FC5\u987B\u662F\u6574\u6570" }).min(0, { error: "\u7ED3\u675F\u65F6\u95F4\u4E0D\u80FD\u5C0F\u4E8E0" }).optional(),
2455
- duration: zod.z.number({ error: "\u89C6\u9891\u65F6\u957F\u5FC5\u987B\u662F\u6570\u5B57" }).int({ error: "\u89C6\u9891\u65F6\u957F\u5FC5\u987B\u662F\u6574\u6570" }).min(0, { error: "\u89C6\u9891\u65F6\u957F\u4E0D\u80FD\u5C0F\u4E8E0" })
2659
+ duration: zod.z.coerce.number({ error: "\u89C6\u9891\u65F6\u957F\u5FC5\u987B\u662F\u6570\u5B57" }).int({ error: "\u89C6\u9891\u65F6\u957F\u5FC5\u987B\u662F\u6574\u6570" }).min(0, { error: "\u89C6\u9891\u65F6\u957F\u4E0D\u80FD\u5C0F\u4E8E0" })
2456
2660
  }).refine(
2457
2661
  (data2) => {
2458
2662
  if (data2.end_time !== void 0) {
@@ -1,7 +1,7 @@
1
1
  import { Chalk } from 'chalk';
2
2
  import log4js from 'log4js';
3
3
  import path from 'path';
4
- import { fileURLToPath } from 'url';
4
+ import URL2, { fileURLToPath } from 'url';
5
5
  import fs from 'fs';
6
6
  import axios, { AxiosError } from 'axios';
7
7
  import crypto from 'crypto';
@@ -1316,6 +1316,184 @@ var a_bogus_default = (url, user_agent) => {
1316
1316
  let result_str = generate_random_str() + generate_rc4_bb_str(new URLSearchParams(new URL(url).search).toString(), cleanedUserAgent, "1536|747|1536|834|0|30|0|0|1536|834|1536|864|1525|747|24|24|Win32");
1317
1317
  return result_encrypt(result_str, "s4") + "=";
1318
1318
  };
1319
+ var XBogus = class {
1320
+ charMap;
1321
+ base64Charset;
1322
+ uaKey;
1323
+ defaultUa;
1324
+ params;
1325
+ xb;
1326
+ constructor() {
1327
+ this.charMap = new Array(128).fill(null);
1328
+ for (let i = 48; i <= 57; i++) {
1329
+ this.charMap[i] = i - 48;
1330
+ }
1331
+ for (let i = 65; i <= 70; i++) {
1332
+ this.charMap[i] = i - 55;
1333
+ }
1334
+ for (let i = 97; i <= 102; i++) {
1335
+ this.charMap[i] = i - 87;
1336
+ }
1337
+ this.base64Charset = "Dkdpgh4ZKsQB80/Mfvw36XI1R25-WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe=";
1338
+ this.uaKey = Buffer.from([0, 1, 12]);
1339
+ this.defaultUa = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0";
1340
+ }
1341
+ md5StrToArray(md5Str) {
1342
+ const result = [];
1343
+ if (md5Str.length > 32) {
1344
+ for (const char of md5Str) {
1345
+ result.push(char.charCodeAt(0));
1346
+ }
1347
+ return result;
1348
+ }
1349
+ let idx = 0;
1350
+ while (idx < md5Str.length) {
1351
+ const leftCharCode = md5Str.charCodeAt(idx);
1352
+ const rightCharCode = md5Str.charCodeAt(idx + 1);
1353
+ const left = this.charMap[leftCharCode];
1354
+ const right = this.charMap[rightCharCode];
1355
+ if (left === null || right === null) {
1356
+ throw new Error(`Invalid MD5 character: ${md5Str[idx]}${md5Str[idx + 1]}`);
1357
+ }
1358
+ result.push(left << 4 | right);
1359
+ idx += 2;
1360
+ }
1361
+ return result;
1362
+ }
1363
+ md5(input) {
1364
+ const dataArray = typeof input === "string" ? this.md5StrToArray(input) : input;
1365
+ const dataBuffer = Buffer.from(dataArray);
1366
+ return crypto.createHash("md5").update(dataBuffer).digest("hex");
1367
+ }
1368
+ md5Encrypt(urlPath) {
1369
+ const firstMd5 = this.md5(urlPath);
1370
+ const firstArray = this.md5StrToArray(firstMd5);
1371
+ const secondMd5 = this.md5(firstArray);
1372
+ return this.md5StrToArray(secondMd5);
1373
+ }
1374
+ encodingConversion(...params) {
1375
+ const byteList = [];
1376
+ for (const param of params) {
1377
+ if (typeof param === "number") {
1378
+ byteList.push(Math.floor(param));
1379
+ } else if (typeof param === "string") {
1380
+ for (const char of param) {
1381
+ byteList.push(char.charCodeAt(0));
1382
+ }
1383
+ }
1384
+ }
1385
+ return Buffer.from(byteList).toString("latin1");
1386
+ }
1387
+ encodingConversion2(a, b, c) {
1388
+ return String.fromCharCode(a) + String.fromCharCode(b) + c;
1389
+ }
1390
+ rc4Encrypt(key, data2) {
1391
+ const keyBuffer = typeof key === "string" ? Buffer.from(key, "latin1") : key;
1392
+ const dataBuffer = Buffer.from(data2, "latin1");
1393
+ const S = Array.from({ length: 256 }, (_, i2) => i2);
1394
+ let j = 0;
1395
+ for (let i2 = 0; i2 < 256; i2++) {
1396
+ j = (j + S[i2] + keyBuffer[i2 % keyBuffer.length]) % 256;
1397
+ [S[i2], S[j]] = [S[j], S[i2]];
1398
+ }
1399
+ const encryptedBuffer = Buffer.alloc(dataBuffer.length);
1400
+ let i = 0;
1401
+ j = 0;
1402
+ for (let k = 0; k < dataBuffer.length; k++) {
1403
+ i = (i + 1) % 256;
1404
+ j = (j + S[i]) % 256;
1405
+ [S[i], S[j]] = [S[j], S[i]];
1406
+ const t = (S[i] + S[j]) % 256;
1407
+ encryptedBuffer[k] = dataBuffer[k] ^ S[t];
1408
+ }
1409
+ return encryptedBuffer.toString("latin1");
1410
+ }
1411
+ calculation(a1, a2, a3) {
1412
+ const x1 = (a1 & 255) << 16;
1413
+ const x2 = (a2 & 255) << 8;
1414
+ const x3 = x1 | x2 | a3 & 255;
1415
+ const c1 = this.base64Charset[(x3 & 16760832) >> 18];
1416
+ const c2 = this.base64Charset[(x3 & 258048) >> 12];
1417
+ const c3 = this.base64Charset[(x3 & 4032) >> 6];
1418
+ const c4 = this.base64Charset[x3 & 63];
1419
+ return c1 + c2 + c3 + c4;
1420
+ }
1421
+ /**
1422
+ * 生成X-Bogus签名
1423
+ * @param url 完整的URL地址
1424
+ * @param ua 可选的User-Agent,不提供则使用默认值
1425
+ * @returns 包含完整URL、X-Bogus值和使用的User-Agent的元组
1426
+ */
1427
+ getXBogus(url, ua) {
1428
+ const parsedUrl = new URL2.URL(url);
1429
+ const urlPath = parsedUrl.pathname + parsedUrl.search;
1430
+ const currentUa = ua || this.defaultUa;
1431
+ const rc4EncryptedUa = this.rc4Encrypt(this.uaKey, currentUa);
1432
+ const base64Ua = Buffer.from(rc4EncryptedUa, "latin1").toString("base64");
1433
+ const md5Ua = this.md5(base64Ua);
1434
+ const array1 = this.md5StrToArray(md5Ua);
1435
+ const emptyStrMd5 = "d41d8cd98f00b204e9800998ecf8427e";
1436
+ const array2 = this.md5StrToArray(this.md5(this.md5StrToArray(emptyStrMd5)));
1437
+ const urlEncryptedArray = this.md5Encrypt(urlPath);
1438
+ const timestamp = Math.floor(Date.now() / 1e3);
1439
+ const ct = 536919696;
1440
+ const newArray = [
1441
+ 64,
1442
+ 1,
1443
+ 1,
1444
+ 12,
1445
+ urlEncryptedArray[14],
1446
+ urlEncryptedArray[15],
1447
+ array2[14],
1448
+ array2[15],
1449
+ array1[14],
1450
+ array1[15],
1451
+ timestamp >> 24 & 255,
1452
+ timestamp >> 16 & 255,
1453
+ timestamp >> 8 & 255,
1454
+ timestamp & 255,
1455
+ ct >> 24 & 255,
1456
+ ct >> 16 & 255,
1457
+ ct >> 8 & 255,
1458
+ ct & 255
1459
+ ];
1460
+ let xorResult = newArray[0];
1461
+ for (let i = 1; i < newArray.length; i++) {
1462
+ xorResult ^= newArray[i];
1463
+ }
1464
+ newArray.push(xorResult);
1465
+ const array3 = [];
1466
+ const array4 = [];
1467
+ let idx = 0;
1468
+ while (idx < newArray.length) {
1469
+ array3.push(newArray[idx]);
1470
+ if (idx + 1 < newArray.length) {
1471
+ array4.push(newArray[idx + 1]);
1472
+ }
1473
+ idx += 2;
1474
+ }
1475
+ const mergedArray = [...array3, ...array4];
1476
+ const firstConversion = this.encodingConversion(...mergedArray);
1477
+ const rc4Garbled = this.rc4Encrypt("\xFF", firstConversion);
1478
+ const garbledCode = this.encodingConversion2(2, 255, rc4Garbled);
1479
+ let xb = "";
1480
+ idx = 0;
1481
+ while (idx < garbledCode.length) {
1482
+ if (idx + 2 >= garbledCode.length) break;
1483
+ const a1 = garbledCode.charCodeAt(idx);
1484
+ const a2 = garbledCode.charCodeAt(idx + 1);
1485
+ const a3 = garbledCode.charCodeAt(idx + 2);
1486
+ xb += this.calculation(a1, a2, a3);
1487
+ idx += 3;
1488
+ }
1489
+ const fullUrl = url.includes("?") ? `${url}&X-Bogus=${xb}` : `${url}?X-Bogus=${xb}`;
1490
+ return {
1491
+ fullUrl,
1492
+ xbogus: xb,
1493
+ userAgent: currentUa
1494
+ };
1495
+ }
1496
+ };
1319
1497
 
1320
1498
  // src/platform/douyin/sign/index.ts
1321
1499
  var defaultUserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36";
@@ -1338,6 +1516,15 @@ var douyinSign = class {
1338
1516
  static AB(url, userAgent) {
1339
1517
  return a_bogus_default(url, userAgent || defaultUserAgent);
1340
1518
  }
1519
+ /**
1520
+ * X-Bogus 签名算法
1521
+ * @param url 需要签名的地址
1522
+ * @returns 对此地址签名后的URL查询参数
1523
+ */
1524
+ static XB(url, userAgent) {
1525
+ const xbogusResult = new XBogus().getXBogus(url, userAgent || defaultUserAgent);
1526
+ return xbogusResult.xbogus;
1527
+ }
1341
1528
  /** 生成一个唯一的验证字符串 */
1342
1529
  static VerifyFpManager() {
1343
1530
  const e = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split("");
@@ -1466,7 +1653,7 @@ var DouyinAPI = class {
1466
1653
  * @returns 完整的接口URL
1467
1654
  */
1468
1655
  \u4E8C\u7EA7\u8BC4\u8BBA(data2) {
1469
- const baseUrl = "https://www.douyin.com/aweme/v1/web/comment/list/reply/";
1656
+ const baseUrl = "https://www-hj.douyin.com/aweme/v1/web/comment/list/reply/";
1470
1657
  const params = {
1471
1658
  device_platform: "webapp",
1472
1659
  aid: "6383",
@@ -1490,10 +1677,10 @@ var DouyinAPI = class {
1490
1677
  browser_language: "zh-CN",
1491
1678
  browser_platform: "Win32",
1492
1679
  browser_name: "Edge",
1493
- browser_version: "132.0.0.0",
1680
+ browser_version: this.browserVersion,
1494
1681
  browser_online: "true",
1495
1682
  engine_name: "Blink",
1496
- engine_version: "132.0.0.0",
1683
+ engine_version: this.browserVersion,
1497
1684
  os_name: "Windows",
1498
1685
  os_version: "10",
1499
1686
  cpu_core_num: "16",
@@ -1502,7 +1689,7 @@ var DouyinAPI = class {
1502
1689
  downlink: "10",
1503
1690
  effective_type: "4g",
1504
1691
  round_trip_time: "50",
1505
- webid: "7386217876267796006",
1692
+ webid: "7487210762873685515",
1506
1693
  verifyFp: fp,
1507
1694
  fp
1508
1695
  };
@@ -1806,6 +1993,29 @@ var createDouyinApiUrls = (userAgent) => {
1806
1993
  var douyinApiUrls = new DouyinAPI();
1807
1994
 
1808
1995
  // src/platform/douyin/getdata.ts
1996
+ var getSignature = (url, signType = "a_bogus", userAgent) => {
1997
+ switch (signType) {
1998
+ case "x_bogus":
1999
+ return douyinSign.XB(url, userAgent);
2000
+ case "a_bogus":
2001
+ default:
2002
+ return douyinSign.AB(url, userAgent);
2003
+ }
2004
+ };
2005
+ var getSignParamName = (signType = "a_bogus") => {
2006
+ switch (signType) {
2007
+ case "x_bogus":
2008
+ return "X-Bogus";
2009
+ case "a_bogus":
2010
+ default:
2011
+ return "a_bogus";
2012
+ }
2013
+ };
2014
+ var buildSignedUrl = (url, signType = "a_bogus", userAgent) => {
2015
+ const signature = getSignature(url, signType, userAgent);
2016
+ const paramName = getSignParamName(signType);
2017
+ return `${url}&${paramName}=${signature}`;
2018
+ };
1809
2019
  var DouyinData = async (data2, cookie, requestConfig) => {
1810
2020
  var _a, _b, _c, _d, _e;
1811
2021
  const defHeaders = getDouyinDefaultConfig(cookie)["headers"];
@@ -1819,54 +2029,47 @@ var DouyinData = async (data2, cookie, requestConfig) => {
1819
2029
  }
1820
2030
  };
1821
2031
  const userAgent = (_a = baseRequestConfig.headers) == null ? void 0 : _a["User-Agent"];
1822
- const douyinApiUrls3 = createDouyinApiUrls(userAgent);
2032
+ const douyinApiUrls2 = createDouyinApiUrls(userAgent);
2033
+ const signType = data2.signType || "a_bogus";
1823
2034
  switch (data2.methodType) {
1824
2035
  case "\u6587\u5B57\u4F5C\u54C1\u6570\u636E":
1825
2036
  case "\u805A\u5408\u89E3\u6790":
1826
2037
  case "\u89C6\u9891\u4F5C\u54C1\u6570\u636E":
1827
2038
  case "\u56FE\u96C6\u4F5C\u54C1\u6570\u636E":
1828
2039
  case "\u5408\u8F91\u4F5C\u54C1\u6570\u636E": {
1829
- const url = douyinApiUrls3.\u89C6\u9891\u6216\u56FE\u96C6({ aweme_id: data2.aweme_id });
2040
+ const url = douyinApiUrls2.\u89C6\u9891\u6216\u56FE\u96C6({ aweme_id: data2.aweme_id });
1830
2041
  const VideoData = await GlobalGetData2(data2.methodType, {
1831
2042
  ...baseRequestConfig,
1832
- url: `${url}&a_bogus=${douyinSign.AB(url, userAgent)}`
2043
+ url: buildSignedUrl(url, signType, userAgent)
1833
2044
  });
1834
2045
  return VideoData;
1835
2046
  }
1836
2047
  case "\u8BC4\u8BBA\u6570\u636E": {
1837
- const urlGenerator = (params) => douyinApiUrls3.\u8BC4\u8BBA(params);
2048
+ const urlGenerator = (params) => douyinApiUrls2.\u8BC4\u8BBA(params);
1838
2049
  const response = await fetchPaginatedData(
1839
2050
  data2.methodType,
1840
2051
  urlGenerator,
1841
2052
  data2,
1842
2053
  50,
1843
- baseRequestConfig
2054
+ baseRequestConfig,
2055
+ signType
1844
2056
  );
1845
2057
  return response;
1846
2058
  }
1847
2059
  case "\u6307\u5B9A\u8BC4\u8BBA\u56DE\u590D\u6570\u636E": {
1848
- const urlGenerator = (params) => douyinApiUrls3.\u4E8C\u7EA7\u8BC4\u8BBA(params);
1849
- const customConfig = {
1850
- ...baseRequestConfig,
1851
- headers: {
1852
- ...baseRequestConfig.headers,
1853
- // 只有在外部配置没有referer时才设置内部的referer
1854
- ...(!(requestConfig == null ? void 0 : requestConfig.headers) || !("referer" in requestConfig.headers)) && {
1855
- referer: `https://www.douyin.com/note/${data2.aweme_id}`
1856
- }
1857
- }
1858
- };
2060
+ const urlGenerator = (params) => douyinApiUrls2.\u4E8C\u7EA7\u8BC4\u8BBA(params);
1859
2061
  const response = await fetchPaginatedData(
1860
2062
  data2.methodType,
1861
2063
  urlGenerator,
1862
2064
  data2,
1863
2065
  3,
1864
- customConfig
2066
+ baseRequestConfig,
2067
+ "x_bogus"
1865
2068
  );
1866
2069
  return response;
1867
2070
  }
1868
2071
  case "\u7528\u6237\u4E3B\u9875\u6570\u636E": {
1869
- const url = douyinApiUrls3.\u7528\u6237\u4E3B\u9875\u4FE1\u606F({ sec_uid: data2.sec_uid });
2072
+ const url = douyinApiUrls2.\u7528\u6237\u4E3B\u9875\u4FE1\u606F({ sec_uid: data2.sec_uid });
1870
2073
  const customConfig = {
1871
2074
  ...baseRequestConfig,
1872
2075
  headers: {
@@ -1879,12 +2082,12 @@ var DouyinData = async (data2, cookie, requestConfig) => {
1879
2082
  };
1880
2083
  const UserInfoData = await GlobalGetData2(data2.methodType, {
1881
2084
  ...customConfig,
1882
- url: `${url}&a_bogus=${douyinSign.AB(url, userAgent)}`
2085
+ url: buildSignedUrl(url, signType, userAgent)
1883
2086
  });
1884
2087
  return UserInfoData;
1885
2088
  }
1886
2089
  case "Emoji\u6570\u636E": {
1887
- const url = douyinApiUrls3.\u8868\u60C5();
2090
+ const url = douyinApiUrls2.\u8868\u60C5();
1888
2091
  const EmojiData = await GlobalGetData2(data2.methodType, {
1889
2092
  ...baseRequestConfig,
1890
2093
  url
@@ -1892,7 +2095,7 @@ var DouyinData = async (data2, cookie, requestConfig) => {
1892
2095
  return EmojiData;
1893
2096
  }
1894
2097
  case "\u7528\u6237\u4E3B\u9875\u89C6\u9891\u5217\u8868\u6570\u636E": {
1895
- const url = douyinApiUrls3.\u7528\u6237\u4E3B\u9875\u89C6\u9891({ sec_uid: data2.sec_uid });
2098
+ const url = douyinApiUrls2.\u7528\u6237\u4E3B\u9875\u89C6\u9891({ sec_uid: data2.sec_uid });
1896
2099
  const customConfig = {
1897
2100
  ...baseRequestConfig,
1898
2101
  headers: {
@@ -1904,12 +2107,12 @@ var DouyinData = async (data2, cookie, requestConfig) => {
1904
2107
  };
1905
2108
  const UserVideoListData = await GlobalGetData2(data2.methodType, {
1906
2109
  ...customConfig,
1907
- url: `${url}&a_bogus=${douyinSign.AB(url, userAgent)}`
2110
+ url: buildSignedUrl(url, signType, userAgent)
1908
2111
  });
1909
2112
  return UserVideoListData;
1910
2113
  }
1911
2114
  case "\u70ED\u70B9\u8BCD\u6570\u636E": {
1912
- const url = douyinApiUrls3.\u70ED\u70B9\u8BCD({ query: data2.query, number: data2.number ?? 10 });
2115
+ const url = douyinApiUrls2.\u70ED\u70B9\u8BCD({ query: data2.query, number: data2.number ?? 10 });
1913
2116
  const customConfig = {
1914
2117
  ...baseRequestConfig,
1915
2118
  headers: {
@@ -1921,7 +2124,7 @@ var DouyinData = async (data2, cookie, requestConfig) => {
1921
2124
  };
1922
2125
  const SuggestWordsData = await GlobalGetData2(data2.methodType, {
1923
2126
  ...customConfig,
1924
- url: `${url}&a_bogus=${douyinSign.AB(url, userAgent)}`
2127
+ url: buildSignedUrl(url, signType, userAgent)
1925
2128
  });
1926
2129
  return SuggestWordsData;
1927
2130
  }
@@ -1941,14 +2144,14 @@ var DouyinData = async (data2, cookie, requestConfig) => {
1941
2144
  };
1942
2145
  while (fetchedSearchList.length < Number(data2.number ?? 10)) {
1943
2146
  const requestCount = Math.min(Number(data2.number ?? 50) - fetchedSearchList.length, maxPageSize);
1944
- const url = douyinApiUrls3.\u641C\u7D22({
2147
+ const url = douyinApiUrls2.\u641C\u7D22({
1945
2148
  query: data2.query,
1946
2149
  number: requestCount,
1947
2150
  search_id: search_id === "" ? void 0 : search_id
1948
2151
  });
1949
2152
  const response = await GlobalGetData2(data2.methodType, {
1950
2153
  ...customConfig,
1951
- url: `${url}&a_bogus=${douyinSign.AB(url, userAgent)}`
2154
+ url: buildSignedUrl(url, signType, userAgent)
1952
2155
  });
1953
2156
  if (((_b = response.data) == null ? void 0 : _b.length) === 0) {
1954
2157
  logger.warn("\u83B7\u53D6\u641C\u7D22\u6570\u636E\u5931\u8D25\uFF01\u8BF7\u6C42\u6210\u529F\u4F46\u63A5\u53E3\u8FD4\u56DE\u5185\u5BB9\u4E3A\u7A7A\n\u4F60\u7684\u6296\u97F3ck\u53EF\u80FD\u5DF2\u7ECF\u5931\u6548\uFF01\n\u8BF7\u6C42\u7C7B\u578B\uFF1A" + data2.methodType);
@@ -1968,24 +2171,24 @@ var DouyinData = async (data2, cookie, requestConfig) => {
1968
2171
  return finalResponse;
1969
2172
  }
1970
2173
  case "\u52A8\u6001\u8868\u60C5\u6570\u636E": {
1971
- const url = douyinApiUrls3.\u4E92\u52A8\u8868\u60C5();
2174
+ const url = douyinApiUrls2.\u4E92\u52A8\u8868\u60C5();
1972
2175
  const ExpressionPlusData = await GlobalGetData2(data2.methodType, {
1973
2176
  ...baseRequestConfig,
1974
- url: `${url}&a_bogus=${douyinSign.AB(url, userAgent)}`
2177
+ url: buildSignedUrl(url, signType, userAgent)
1975
2178
  });
1976
2179
  return ExpressionPlusData;
1977
2180
  }
1978
2181
  case "\u97F3\u4E50\u6570\u636E": {
1979
- const url = douyinApiUrls3.\u80CC\u666F\u97F3\u4E50({ music_id: data2.music_id });
2182
+ const url = douyinApiUrls2.\u80CC\u666F\u97F3\u4E50({ music_id: data2.music_id });
1980
2183
  const MusicData = await GlobalGetData2(data2.methodType, {
1981
2184
  ...baseRequestConfig,
1982
- url: `${url}&a_bogus=${douyinSign.AB(url, userAgent)}`
2185
+ url: buildSignedUrl(url, signType, userAgent)
1983
2186
  });
1984
2187
  return MusicData;
1985
2188
  }
1986
2189
  case "\u76F4\u64AD\u95F4\u4FE1\u606F\u6570\u636E": {
1987
- let url = douyinApiUrls3.\u7528\u6237\u4E3B\u9875\u4FE1\u606F({ sec_uid: data2.sec_uid });
1988
- const fetchUrl = `${url}&a_bogus=${douyinSign.AB(url, userAgent)}`;
2190
+ let url = douyinApiUrls2.\u7528\u6237\u4E3B\u9875\u4FE1\u606F({ sec_uid: data2.sec_uid });
2191
+ const fetchUrl = buildSignedUrl(url, signType, userAgent);
1989
2192
  const customConfig = {
1990
2193
  ...baseRequestConfig,
1991
2194
  headers: {
@@ -2022,7 +2225,7 @@ var DouyinData = async (data2, cookie, requestConfig) => {
2022
2225
  };
2023
2226
  }
2024
2227
  const room_data = JSON.parse(UserInfoData.user.room_data);
2025
- url = douyinApiUrls3.\u76F4\u64AD\u95F4\u4FE1\u606F({ room_id: UserInfoData.user.room_id_str, web_rid: room_data.owner.web_rid });
2228
+ url = douyinApiUrls2.\u76F4\u64AD\u95F4\u4FE1\u606F({ room_id: UserInfoData.user.room_id_str, web_rid: room_data.owner.web_rid });
2026
2229
  const liveCustomConfig = {
2027
2230
  ...baseRequestConfig,
2028
2231
  headers: {
@@ -2034,15 +2237,15 @@ var DouyinData = async (data2, cookie, requestConfig) => {
2034
2237
  };
2035
2238
  const LiveRoomData = await GlobalGetData2(data2.methodType, {
2036
2239
  ...liveCustomConfig,
2037
- url: `${url}&a_bogus=${douyinSign.AB(url, userAgent)}`
2240
+ url: buildSignedUrl(url, signType, userAgent)
2038
2241
  });
2039
2242
  return LiveRoomData;
2040
2243
  }
2041
2244
  case "\u7533\u8BF7\u4E8C\u7EF4\u7801\u6570\u636E": {
2042
- const url = douyinApiUrls3.\u7533\u8BF7\u4E8C\u7EF4\u7801({ verify_fp: data2.verify_fp });
2245
+ const url = douyinApiUrls2.\u7533\u8BF7\u4E8C\u7EF4\u7801({ verify_fp: data2.verify_fp });
2043
2246
  const LoginQrcodeStatusData = await GlobalGetData2(data2.methodType, {
2044
2247
  ...baseRequestConfig,
2045
- url: `${url}&a_bogus=${douyinSign.AB(url, userAgent)}`
2248
+ url: buildSignedUrl(url, signType, userAgent)
2046
2249
  });
2047
2250
  return LoginQrcodeStatusData;
2048
2251
  }
@@ -2052,7 +2255,7 @@ var DouyinData = async (data2, cookie, requestConfig) => {
2052
2255
  const endTime = data2.end_time ?? data2.duration;
2053
2256
  const totalDuration = endTime - startTime;
2054
2257
  if (totalDuration <= MAX_SEGMENT_DURATION) {
2055
- const url = douyinApiUrls3.\u5F39\u5E55({
2258
+ const url = douyinApiUrls2.\u5F39\u5E55({
2056
2259
  aweme_id: data2.aweme_id,
2057
2260
  start_time: startTime,
2058
2261
  end_time: endTime,
@@ -2060,7 +2263,7 @@ var DouyinData = async (data2, cookie, requestConfig) => {
2060
2263
  });
2061
2264
  const DanmakuData = await GlobalGetData2(data2.methodType, {
2062
2265
  ...baseRequestConfig,
2063
- url: `${url}&a_bogus=${douyinSign.AB(url, userAgent)}`
2266
+ url: buildSignedUrl(url, signType, userAgent)
2064
2267
  });
2065
2268
  return DanmakuData;
2066
2269
  }
@@ -2073,7 +2276,7 @@ var DouyinData = async (data2, cookie, requestConfig) => {
2073
2276
  }
2074
2277
  logger.debug(`\u5F39\u5E55\u6570\u636E\u9700\u8981\u5206${segments.length}\u6BB5\u83B7\u53D6\uFF0C\u603B\u65F6\u957F\uFF1A${totalDuration}ms`);
2075
2278
  const segmentPromises = segments.map(async (segment, index) => {
2076
- const url = douyinApiUrls3.\u5F39\u5E55({
2279
+ const url = douyinApiUrls2.\u5F39\u5E55({
2077
2280
  aweme_id: data2.aweme_id,
2078
2281
  start_time: segment.start,
2079
2282
  end_time: segment.end,
@@ -2082,7 +2285,7 @@ var DouyinData = async (data2, cookie, requestConfig) => {
2082
2285
  try {
2083
2286
  const segmentData = await GlobalGetData2(`${data2.methodType}-\u6BB5${index + 1}`, {
2084
2287
  ...baseRequestConfig,
2085
- url: `${url}&a_bogus=${douyinSign.AB(url, userAgent)}`
2288
+ url: buildSignedUrl(url, signType, userAgent)
2086
2289
  });
2087
2290
  logger.debug(`\u5F39\u5E55\u7B2C${index + 1}\u6BB5\u83B7\u53D6\u6210\u529F (${segment.start}ms-${segment.end}ms)`);
2088
2291
  return segmentData;
@@ -2130,7 +2333,7 @@ var DouyinData = async (data2, cookie, requestConfig) => {
2130
2333
  }
2131
2334
  }
2132
2335
  };
2133
- var fetchPaginatedData = async (type, apiUrlGenerator, params, maxPageSize, requestConfig) => {
2336
+ var fetchPaginatedData = async (type, apiUrlGenerator, params, maxPageSize, requestConfig, signType = "a_bogus") => {
2134
2337
  var _a;
2135
2338
  let cursor = params.cursor ?? 0;
2136
2339
  let fetchedData = [];
@@ -2145,7 +2348,7 @@ var fetchPaginatedData = async (type, apiUrlGenerator, params, maxPageSize, requ
2145
2348
  });
2146
2349
  const response = await GlobalGetData2(type, {
2147
2350
  ...requestConfig,
2148
- url: `${url}&a_bogus=${douyinSign.AB(url, userAgent)}`
2351
+ url: buildSignedUrl(url, signType, userAgent)
2149
2352
  });
2150
2353
  fetchedData.push(...response.comments || response.data || []);
2151
2354
  tmpresp = response;
@@ -2436,7 +2639,7 @@ var DouyinDanmakuParamsSchema = z.object({
2436
2639
  aweme_id: z.string({ error: "\u89C6\u9891ID\u5FC5\u987B\u662F\u5B57\u7B26\u4E32" }).min(1, { error: "\u89C6\u9891ID\u4E0D\u80FD\u4E3A\u7A7A" }),
2437
2640
  start_time: z.coerce.number({ error: "\u5F00\u59CB\u65F6\u95F4\u5FC5\u987B\u662F\u6570\u5B57" }).int({ error: "\u5F00\u59CB\u65F6\u95F4\u5FC5\u987B\u662F\u6574\u6570" }).min(0, { error: "\u5F00\u59CB\u65F6\u95F4\u4E0D\u80FD\u5C0F\u4E8E0" }).optional(),
2438
2641
  end_time: z.coerce.number({ error: "\u7ED3\u675F\u65F6\u95F4\u5FC5\u987B\u662F\u6570\u5B57" }).int({ error: "\u7ED3\u675F\u65F6\u95F4\u5FC5\u987B\u662F\u6574\u6570" }).min(0, { error: "\u7ED3\u675F\u65F6\u95F4\u4E0D\u80FD\u5C0F\u4E8E0" }).optional(),
2439
- duration: z.number({ error: "\u89C6\u9891\u65F6\u957F\u5FC5\u987B\u662F\u6570\u5B57" }).int({ error: "\u89C6\u9891\u65F6\u957F\u5FC5\u987B\u662F\u6574\u6570" }).min(0, { error: "\u89C6\u9891\u65F6\u957F\u4E0D\u80FD\u5C0F\u4E8E0" })
2642
+ duration: z.coerce.number({ error: "\u89C6\u9891\u65F6\u957F\u5FC5\u987B\u662F\u6570\u5B57" }).int({ error: "\u89C6\u9891\u65F6\u957F\u5FC5\u987B\u662F\u6574\u6570" }).min(0, { error: "\u89C6\u9891\u65F6\u957F\u4E0D\u80FD\u5C0F\u4E8E0" })
2440
2643
  }).refine(
2441
2644
  (data2) => {
2442
2645
  if (data2.end_time !== void 0) {
@@ -19850,6 +19850,12 @@ declare class douyinSign {
19850
19850
  * @returns 对此地址签名后的URL查询参数
19851
19851
  */
19852
19852
  static AB(url: string, userAgent?: string): string;
19853
+ /**
19854
+ * X-Bogus 签名算法
19855
+ * @param url 需要签名的地址
19856
+ * @returns 对此地址签名后的URL查询参数
19857
+ */
19858
+ static XB(url: string, userAgent?: string): string;
19853
19859
  /** 生成一个唯一的验证字符串 */
19854
19860
  static VerifyFpManager(): string;
19855
19861
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ikenxuan/amagi",
3
- "version": "5.5.1",
3
+ "version": "5.6.0",
4
4
  "description": "抖音、B站的 web 端相关数据接口基于 Node.js 的实现",
5
5
  "keywords": [
6
6
  "douyin",