karin-plugin-kkk 2.36.0 → 2.36.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.
@@ -1,12 +1,12 @@
1
1
  import { i as __toESM } from "./rolldown-runtime.js";
2
- import { $ as SiGooglephotos, $n as require_jsx_runtime, $t as Puzzle, A as RiHashtag, An as Copy, At as Upload, B as RiThumbUpFill, Bn as CircleAlert, Bt as ShoppingBag, C as AiFillHeart, Cn as Eye, Ct as X, D as Markdown, Dn as Crown, Dt as UsersRound, E as AiOutlineVideoCamera, En as Download, Et as Users, F as RiMessage3Fill, Fn as CircleQuestionMark, Ft as Star, G as RiVideoLine, Gn as Box, Gt as Search, H as RiTrophyFill, Hn as ChartColumn, Ht as ShieldCheck, I as RiPieChart2Fill, In as CircleFadingArrowUp, It as Square, J as SiSamsung, Jn as BellRing, Jt as RotateCcw, K as SiXiaomi, Kn as Bot, Kt as ScanLine, L as RiShareForwardFill, Ln as CircleEllipsis, Lt as SquarePen, M as RiHeart3Line, Mn as Clock, Mt as Trash2, N as RiHeartLine, Nn as Clock3, Nt as Terminal, O as RiArrowRightFill, On as Cpu, Ot as User, P as RiLiveLine, Pn as Clapperboard, Pt as Sun, Q as SiHonor, Qn as clsx, Qt as QrCode, R as RiStarFill, Rn as CircleCheck, Rt as Sparkles, S as BiImage, Sn as FilePlay, St as Zap, T as AiFillStar, Tn as ExternalLink, Tt as Video, U as RiUserFollowLine, Un as Camera, Ut as Share2, V as RiTiktokFill, Vn as Check, Vt as Shield, W as RiVerifiedBadgeFill, Wn as Calendar, Wt as Settings2, X as SiOneplus, Xn as Chip, Xt as Radio, Y as SiOppo, Yn as ArrowDownToLine, Yt as RefreshCw, Z as SiHuawei, Zn as Button, Zt as Quote, _ as MdSchedule, _n as Hash, _t as fromUnixTime, a as VictoryScatter, an as Moon, ar as zod_default, at as r, b as FaTiktok, bn as Gamepad2, bt as differenceInSeconds, c as VictoryChart, cn as Menu, ct as m, d as VictoryTheme, dn as LoaderCircle, dt as e, en as Plus, er as require_server_node, et as SiGithub, f as rehypeHighlight, fn as Link, ft as a$1, g as MdLocationOn, gn as Heart, gt as parse, h as MdLightbulbOutline, hn as Image$1, ht as zhCN, i as require_heic_decode, in as Music, ir as Xhshow, it as o$2, j as RiHeart3Fill, jn as Code, jt as TriangleAlert, k as RiGroupLine, kn as CornerDownLeft, kt as UserPlus, l as VictoryAxis, ln as Maximize, lt as a, m as MdInfoOutline, mn as Info, mt as c, n as require_lib, nn as Pencil, nr as require_protobufjs, nt as SiApple, o as VictoryPie, on as Monitor, ot as o, p as MdFitScreen, pn as LayoutTemplate, pt as o$1, q as SiVivo, qn as Bookmark, qt as Save, r as require_jpeg_js, rn as Palette, rr as Chalk, rt as SiAnthropic, s as VictoryLine, sn as MessageCircle, st as o$3, t as createProxyMiddleware, tn as Play, tr as require_react, tt as SiBilibili, u as VictoryLabel, un as MapPin, ut as n, v as FaCommentDots, vn as GitBranch, vt as formatDistanceToNow, w as AiFillPushpin, wn as EyeOff, wt as WandSparkles, x as FaUserGroup, xn as FileText, xt as twMerge, y as FaMusic, yn as Gift, yt as format, z as RiStarLine, zn as CircleCheckBig, zt as Smartphone } from "./vendor.js";
2
+ import { $ as SiGooglephotos, $n as require_jsx_runtime, $t as Puzzle, A as RiHashtag, An as Copy, At as Upload, B as RiThumbUpFill, Bn as CircleAlert, Bt as ShoppingBag, C as AiFillHeart, Cn as Eye, Ct as X, D as Markdown, Dn as Crown, Dt as UsersRound, E as AiOutlineVideoCamera, En as Download, Et as Users, F as RiMessage3Fill, Fn as CircleQuestionMark, Ft as Star, G as RiVideoLine, Gn as Box, Gt as Search, H as RiTrophyFill, Hn as ChartColumn, Ht as ShieldCheck, I as RiPieChart2Fill, In as CircleFadingArrowUp, It as Square, J as SiSamsung, Jn as BellRing, Jt as RotateCcw, K as SiXiaomi, Kn as Bot, Kt as ScanLine, L as RiShareForwardFill, Ln as CircleEllipsis, Lt as SquarePen, M as RiHeart3Line, Mn as Clock, Mt as Trash2, N as RiHeartLine, Nn as Clock3, Nt as Terminal, O as RiArrowRightFill, On as Cpu, Ot as User, P as RiLiveLine, Pn as Clapperboard, Pt as Sun, Q as SiHonor, Qn as clsx, Qt as QrCode, R as RiStarFill, Rn as CircleCheck, Rt as Sparkles, S as BiImage, Sn as FilePlay, St as Zap, T as AiFillStar, Tn as ExternalLink, Tt as Video, U as RiUserFollowLine, Un as Camera, Ut as Share2, V as RiTiktokFill, Vn as Check, Vt as Shield, W as RiVerifiedBadgeFill, Wn as Calendar, Wt as Settings2, X as SiOneplus, Xn as Chip, Xt as Radio, Y as SiOppo, Yn as ArrowDownToLine, Yt as RefreshCw, Z as SiHuawei, Zn as Button, Zt as Quote, _ as MdSchedule, _n as Hash, _t as fromUnixTime, a as VictoryScatter, an as Moon, ar as FingerprintGenerator, at as r, b as FaTiktok, bn as Gamepad2, bt as differenceInSeconds, c as VictoryChart, cn as Menu, ct as m, d as VictoryTheme, dn as LoaderCircle, dt as e, en as Plus, er as require_server_node, et as SiGithub, f as rehypeHighlight, fn as Link, ft as a$1, g as MdLocationOn, gn as Heart, gt as parse, h as MdLightbulbOutline, hn as Image$1, ht as zhCN, i as require_heic_decode, in as Music, ir as CryptoConfig, it as o$2, j as RiHeart3Fill, jn as Code, jt as TriangleAlert, k as RiGroupLine, kn as CornerDownLeft, kt as UserPlus, l as VictoryAxis, ln as Maximize, lt as a, m as MdInfoOutline, mn as Info, mt as c, n as require_lib, nn as Pencil, nr as require_protobufjs, nt as SiApple, o as VictoryPie, on as Monitor, or as Xhshow, ot as o, p as MdFitScreen, pn as LayoutTemplate, pt as o$1, q as SiVivo, qn as Bookmark, qt as Save, r as require_jpeg_js, rn as Palette, rr as Chalk, rt as SiAnthropic, s as VictoryLine, sn as MessageCircle, sr as zod_default, st as o$3, t as createProxyMiddleware, tn as Play, tr as require_react, tt as SiBilibili, u as VictoryLabel, un as MapPin, ut as n, v as FaCommentDots, vn as GitBranch, vt as formatDistanceToNow, w as AiFillPushpin, wn as EyeOff, wt as WandSparkles, x as FaUserGroup, xn as FileText, xt as twMerge, y as FaMusic, yn as Gift, yt as format, z as RiStarLine, zn as CircleCheckBig, zt as Smartphone } from "./vendor.js";
3
3
  import "node:module";
4
4
  import fs from "node:fs";
5
5
  import path, { resolve } from "node:path";
6
6
  import URL$1, { fileURLToPath } from "node:url";
7
7
  import karin$1, { BOT_CONNECT, app, authMiddleware, checkPkgUpdate, checkPort, common, config, createBadRequestResponse, createNotFoundResponse, createServerErrorResponse, createSuccessResponse, db, defineConfig, ffmpeg, ffprobe, hooks, karin, karinPathHtml, karinPathTemp, logger, logger as logger$1, logs, mkdirSync, parseChangelog, range, render, restart, segment, updatePkg, watch } from "node-karin";
8
8
  import { EventEmitter } from "node:events";
9
- import crypto from "node:crypto";
9
+ import crypto, { createCipheriv, createHash, randomBytes, randomUUID } from "node:crypto";
10
10
  import axios, { AxiosError } from "node-karin/axios";
11
11
  import os, { platform } from "node:os";
12
12
  import express from "node-karin/express";
@@ -1379,12 +1379,194 @@ var KuaishouMethodRoutes = {
1379
1379
  emojiList: "/fetch_emoji_list"
1380
1380
  };
1381
1381
  //#endregion
1382
+ //#region ../amagi/packages/core/src/platform/xiaohongshu/sign/config.ts
1383
+ /** 初始化签名配置。 */
1384
+ var createXiaohongshuCryptoConfig = () => new CryptoConfig().withOverrides({
1385
+ DATA_WEB_BUILD: "6.12.3",
1386
+ SIGNATURE_DATA_TEMPLATE: {
1387
+ x0: "4.3.5",
1388
+ x1: "xhs-pc-web",
1389
+ x2: "Windows",
1390
+ x3: "",
1391
+ x4: ""
1392
+ },
1393
+ SIGNATURE_XSCOMMON_TEMPLATE: {
1394
+ s0: 5,
1395
+ s1: "",
1396
+ x0: "1",
1397
+ x1: "4.3.5",
1398
+ x2: "Windows",
1399
+ x3: "xhs-pc-web",
1400
+ x4: "6.12.3",
1401
+ x5: "",
1402
+ x6: "",
1403
+ x7: "",
1404
+ x8: "",
1405
+ x9: -596800761,
1406
+ x10: 0,
1407
+ x11: "normal"
1408
+ }
1409
+ });
1410
+ //#endregion
1411
+ //#region ../amagi/packages/core/src/platform/xiaohongshu/sign/guestCookie.ts
1412
+ /** @see https://github.com/Cialle/RedCrack */
1413
+ /** 小红书 Web 端游客会话初始化使用的浏览器请求头。 */
1414
+ var GUEST_HEADERS = {
1415
+ accept: "application/json, text/plain, */*",
1416
+ "accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
1417
+ "content-type": "application/json;charset=UTF-8",
1418
+ origin: "https://www.xiaohongshu.com",
1419
+ priority: "u=1, i",
1420
+ referer: "https://www.xiaohongshu.com/",
1421
+ "sec-ch-ua": "\"Microsoft Edge\";v=\"141\", \"Not?A_Brand\";v=\"8\", \"Chromium\";v=\"141\"",
1422
+ "sec-ch-ua-mobile": "?0",
1423
+ "sec-ch-ua-platform": "\"Windows\"",
1424
+ "sec-fetch-dest": "empty",
1425
+ "sec-fetch-mode": "cors",
1426
+ "sec-fetch-site": "same-site",
1427
+ "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36 Edg/141.0.0.0"
1428
+ };
1429
+ /** 生成 a1 随机段时使用的 Web 端字符集。 */
1430
+ var COOKIE_RANDOM_CHARS = "abcdefghijklmnopqrstuvwxyz1234567890";
1431
+ /** 将 Cookie Jar 序列化为可直接写入 HTTP Cookie 请求头的字符串。 */
1432
+ var toCookieString = (cookies) => Object.entries(cookies).map(([key, value]) => `${key}=${value}`).join("; ");
1433
+ /** 将响应头中的 Set-Cookie 字段合并到当前游客会话的 Cookie Jar。 */
1434
+ var updateCookiesFromResponse = (cookies, setCookie) => {
1435
+ const headers = Array.isArray(setCookie) ? setCookie : setCookie ? [setCookie] : [];
1436
+ for (const header of headers) {
1437
+ const [nameValue] = header.split(";", 1);
1438
+ const separatorIndex = nameValue.indexOf("=");
1439
+ if (separatorIndex > 0) cookies[nameValue.slice(0, separatorIndex).trim()] = nameValue.slice(separatorIndex + 1).trim();
1440
+ }
1441
+ };
1442
+ /** 按小红书 Web 端规则生成 a1,以及由 a1 派生的 webId。 */
1443
+ var generateA1AndWebId = () => {
1444
+ const source = `${Date.now().toString(16)}${Array.from(randomBytes(30), (byte) => COOKIE_RANDOM_CHARS[byte % 36]).join("")}5000`;
1445
+ const a1 = `${source}${crc32(source)}`.slice(0, 52);
1446
+ return {
1447
+ a1,
1448
+ webId: createHash("md5").update(a1).digest("hex")
1449
+ };
1450
+ };
1451
+ /** 计算与浏览器端实现兼容的无符号 CRC32 校验值。 */
1452
+ var crc32 = (input) => {
1453
+ let value = 4294967295;
1454
+ for (const byte of Buffer.from(input)) {
1455
+ value ^= byte;
1456
+ for (let bit = 0; bit < 8; bit += 1) value = value & 1 ? value >>> 1 ^ 3988292384 : value >>> 1;
1457
+ }
1458
+ return (value ^ 4294967295) >>> 0;
1459
+ };
1460
+ /** 从 scripting 接口返回的 VMP 数据中解码 websectiga Cookie。 */
1461
+ var generateWebsectiga = (payload) => {
1462
+ const bMatch = payload.match(/"b":"(.*?)",/);
1463
+ const dMatch = payload.match(/"d":(.*?)\}\)/);
1464
+ if (!bMatch || !dMatch) throw new Error("小红书 scripting 响应格式异常,无法生成 websectiga");
1465
+ const decoderData = JSON.parse(dMatch[1]);
1466
+ const encoded = Buffer.from(bMatch[1], "base64").toString("utf8");
1467
+ const logicList = [];
1468
+ for (let index = 0; index < encoded.length; index += 5) logicList.push(Array.from(encoded.slice(index, index + 5), (char) => char.charCodeAt(0) - 1));
1469
+ const start = decoderData[92];
1470
+ const end = decoderData[93];
1471
+ const target = logicList.slice(start, end + 1);
1472
+ const key = Array.from({ length: 64 }, (_, index) => {
1473
+ const item = target[675 + index * 2];
1474
+ if (!item) throw new Error("小红书 scripting 响应缺少 websectiga 解码数据");
1475
+ return decoderData[item[2]];
1476
+ });
1477
+ return Array.from({ length: 8 }, (_, group) => {
1478
+ const offset = 56 - group * 8;
1479
+ return String.fromCharCode(...key.slice(offset, offset + 8));
1480
+ }).join("");
1481
+ };
1482
+ /** 将浏览器指纹编码为 webprofile 接口要求的 DES-ECB profileData。 */
1483
+ var encryptProfileData = (fingerprint, desKey) => {
1484
+ const encoded = Buffer.from(JSON.stringify(fingerprint)).toString("base64");
1485
+ const blockSize = 8;
1486
+ const padding = blockSize - encoded.length % blockSize;
1487
+ const plaintext = Buffer.concat([Buffer.from(encoded), Buffer.alloc(padding)]);
1488
+ const cipher = createCipheriv("des-ede3", Buffer.from(desKey.repeat(3)), null);
1489
+ cipher.setAutoPadding(false);
1490
+ return Buffer.concat([cipher.update(plaintext), cipher.final()]).toString("hex");
1491
+ };
1492
+ /** 将 scripting 的 JSON 或 JSONP 响应统一还原为结构化数据。 */
1493
+ var unwrapScriptingResponse = (data) => {
1494
+ if (typeof data === "string") {
1495
+ const json = data.match(/^[^(]+\((.*)\)$/s)?.[1];
1496
+ return JSON.parse(json ?? data);
1497
+ }
1498
+ return data;
1499
+ };
1500
+ /**
1501
+ * 创建小红书 Web 端游客会话 Cookie。
1502
+ *
1503
+ * 该流程对应 Web 端首次访问时的 Cookie 初始化:生成 a1/webId,完成
1504
+ * scripting、webprofile 与 activate 三个会话请求,并返回最终 Cookie 字符串。
1505
+ */
1506
+ var createXiaohongshuGuestCookie = async (requestConfig) => {
1507
+ const cryptoConfig = createXiaohongshuCryptoConfig();
1508
+ const signer = new Xhshow(cryptoConfig);
1509
+ const cookies = {
1510
+ ...generateA1AndWebId(),
1511
+ webBuild: cryptoConfig.DATA_WEB_BUILD,
1512
+ xsecappid: "xhs-pc-web",
1513
+ loadts: String(Date.now()),
1514
+ abRequestId: randomUUID()
1515
+ };
1516
+ const { headers: requestHeaders, params: _params, ...transportConfig } = requestConfig ?? {};
1517
+ /** 发送会话初始化请求,并将响应中的 Set-Cookie 合并回当前 Cookie Jar。 */
1518
+ const request = async (url, data, signed = false) => {
1519
+ const signatureHeaders = signed ? signer.signHeadersPost(new URL(url).pathname, cookies, "xhs-pc-web", data) : {};
1520
+ const response = await axios({
1521
+ ...transportConfig,
1522
+ method: "POST",
1523
+ url,
1524
+ data,
1525
+ validateStatus: () => true,
1526
+ headers: {
1527
+ ...GUEST_HEADERS,
1528
+ ...requestHeaders,
1529
+ ...signatureHeaders,
1530
+ Cookie: toCookieString(cookies)
1531
+ }
1532
+ });
1533
+ updateCookiesFromResponse(cookies, response.headers["set-cookie"]);
1534
+ if (response.status < 200 || response.status >= 300) throw new Error(`小红书游客会话初始化失败:${url} 返回 HTTP ${response.status}`);
1535
+ return response.data;
1536
+ };
1537
+ const scriptingData = unwrapScriptingResponse(await request("https://as.xiaohongshu.com/api/sec/v1/scripting", {
1538
+ callFrom: "web",
1539
+ callback: "seccallback"
1540
+ })).data;
1541
+ if (!scriptingData?.data || !scriptingData.secPoisonId) throw new Error("小红书 scripting 响应缺少游客会话数据");
1542
+ cookies.websectiga = generateWebsectiga(scriptingData.data);
1543
+ cookies.sec_poison_id = scriptingData.secPoisonId;
1544
+ const fingerprint = new FingerprintGenerator(cryptoConfig).generate(cookies, GUEST_HEADERS["user-agent"]);
1545
+ await request(cryptoConfig.GID_URL, {
1546
+ platform: cryptoConfig.DATA_PLATFORM,
1547
+ profileData: encryptProfileData(fingerprint, cryptoConfig.DES_KEY),
1548
+ sdkVersion: cryptoConfig.DATA_SDK_VERSION,
1549
+ svn: cryptoConfig.DATA_SVN
1550
+ }, true);
1551
+ await request("https://edith.xiaohongshu.com/api/sns/web/v1/login/activate", {}, true);
1552
+ if (!cookies.web_session) throw new Error("小红书游客会话初始化失败:未获取到 web_session");
1553
+ return toCookieString(cookies);
1554
+ };
1555
+ //#endregion
1382
1556
  //#region ../amagi/packages/core/src/platform/xiaohongshu/sign/index.ts
1383
1557
  /**
1384
1558
  * 小红书签名算法类
1385
1559
  */
1386
1560
  var xiaohongshuSign = class {
1387
- static client = new Xhshow();
1561
+ static client = new Xhshow(createXiaohongshuCryptoConfig());
1562
+ /**
1563
+ * 创建包含 web_session 的小红书 Web 端游客 Cookie。
1564
+ *
1565
+ * `requestConfig` 会透传到游客会话初始化请求,可用于配置代理、超时等传输参数。
1566
+ */
1567
+ static createGuestCookie(requestConfig) {
1568
+ return createXiaohongshuGuestCookie(requestConfig);
1569
+ }
1388
1570
  /**
1389
1571
  * 生成GET请求的X-S签名
1390
1572
  * @param path - API路径
@@ -4236,7 +4418,7 @@ var DouyinData = async (data, cookie, requestConfig) => {
4236
4418
  if (isInvalidResponse) {
4237
4419
  const desc = `抖音${typeStr}搜索返回无有效数据,疑似触发反爬机制,你的抖音Cookie可能已经失效!`;
4238
4420
  const warningMessage = `
4239
- 获取响应数据失败!原因:${logger$2.yellow(`${typeStr}搜索返回无有效数据,疑似触发反爬机制`)}
4421
+ 获取响应数据失败!原因:${typeStr}搜索返回无有效数据,疑似触发反爬机制
4240
4422
  请求类型:「${data.methodType}」
4241
4423
  搜索关键词:「${data.query}」
4242
4424
  请求URL:${url}
@@ -4255,12 +4437,12 @@ var DouyinData = async (data, cookie, requestConfig) => {
4255
4437
  if (!list || list.length === 0) {
4256
4438
  const desc = `抖音${typeStr}搜索接口第一次请求就返回空数组,可能该关键词无搜索结果或触发风控限制,你的抖音Cookie可能已经失效!`;
4257
4439
  const warningMessage = `
4258
- 获取响应数据失败!原因:${logger$2.yellow(`${typeStr}搜索接口第一次请求就返回空数组,你的抖音Cookie可能已经失效!`)}
4440
+ 获取响应数据失败!原因:${typeStr}搜索接口第一次请求就返回空数组,你的抖音Cookie可能已经失效!
4259
4441
  请求类型:「${data.methodType}」
4260
4442
  搜索关键词:「${data.query}」
4261
4443
  请求URL:${url}
4262
4444
  `;
4263
- logger$2.warn(warningMessage);
4445
+ emitLogWarn(warningMessage);
4264
4446
  return {
4265
4447
  data: raw,
4266
4448
  amagiError: {
@@ -4351,7 +4533,7 @@ var DouyinData = async (data, cookie, requestConfig) => {
4351
4533
  });
4352
4534
  currentStart = currentEnd;
4353
4535
  }
4354
- logger$2.debug(`弹幕数据需要分${segments.length}段获取,总时长:${totalDuration}ms`);
4536
+ emitLogDebug(`弹幕数据需要分${segments.length}段获取,总时长:${totalDuration}ms`);
4355
4537
  const segmentPromises = segments.map(async (segment, index) => {
4356
4538
  const url = douyinApiUrls.getDanmakuList({
4357
4539
  aweme_id: data.aweme_id,
@@ -4364,10 +4546,10 @@ var DouyinData = async (data, cookie, requestConfig) => {
4364
4546
  ...baseRequestConfig,
4365
4547
  url: buildSignedUrl(url, signType, userAgent)
4366
4548
  });
4367
- logger$2.debug(`弹幕第${index + 1}段获取成功 (${segment.start}ms-${segment.end}ms)`);
4549
+ emitLogDebug(`弹幕第${index + 1}段获取成功 (${segment.start}ms-${segment.end}ms)`);
4368
4550
  return segmentData;
4369
4551
  } catch (error) {
4370
- logger$2.debug(`弹幕第${index + 1}段获取失败 (${segment.start}ms-${segment.end}ms):`, error);
4552
+ emitLogDebug(`弹幕第${index + 1}段获取失败 (${segment.start}ms-${segment.end}ms):`, error);
4371
4553
  return null;
4372
4554
  }
4373
4555
  });
@@ -4396,7 +4578,7 @@ var DouyinData = async (data, cookie, requestConfig) => {
4396
4578
  extra: finalExtra,
4397
4579
  log_pb: finalLogPb
4398
4580
  };
4399
- logger$2.debug(`弹幕数据合并完成,共获取${mergedDanmakuList.length}条弹幕`);
4581
+ emitLogDebug(`弹幕数据合并完成,共获取${mergedDanmakuList.length}条弹幕`);
4400
4582
  return finalDanmakuData;
4401
4583
  }
4402
4584
  default: {
@@ -4408,7 +4590,7 @@ var DouyinData = async (data, cookie, requestConfig) => {
4408
4590
  url
4409
4591
  });
4410
4592
  }
4411
- logger$2.warn(`未知的抖音数据接口:「${logger$2.red(data.methodType)}」`);
4593
+ emitLogWarn(`未知的抖音数据接口:「${data.methodType}」`);
4412
4594
  return null;
4413
4595
  }
4414
4596
  }
@@ -4476,11 +4658,11 @@ var GlobalGetData$3 = async (type, config) => {
4476
4658
  requestUrl: config.url
4477
4659
  };
4478
4660
  warningMessage = `
4479
- 获取响应数据失败!原因:${logger$2.yellow("接口返回内容为空,你的抖音ck可能已经失效!")}
4661
+ 获取响应数据失败!原因:接口返回内容为空,你的抖音ck可能已经失效!
4480
4662
  请求类型:「${type}」
4481
4663
  请求URL:${config.url}
4482
4664
  `;
4483
- logger$2.warn(warningMessage);
4665
+ emitLogWarn(warningMessage);
4484
4666
  const cookieError = new Error(Err.errorDescription);
4485
4667
  Object.assign(cookieError, {
4486
4668
  code: douoyinAPIErrorCode.COOKIE,
@@ -4497,11 +4679,11 @@ var GlobalGetData$3 = async (type, config) => {
4497
4679
  requestUrl: config.url
4498
4680
  };
4499
4681
  warningMessage = `
4500
- 获取响应数据失败!原因:${logger$2.yellow(filterReason)}
4682
+ 获取响应数据失败!原因:${filterReason}
4501
4683
  请求类型:「${type}」
4502
4684
  请求URL:${config.url}
4503
4685
  `;
4504
- logger$2.warn(warningMessage);
4686
+ emitLogWarn(warningMessage);
4505
4687
  const filterError = new Error(Err.errorDescription);
4506
4688
  Object.assign(filterError, {
4507
4689
  code: douoyinAPIErrorCode.FILTER,
@@ -7166,7 +7348,7 @@ var KuaishouData = async (data, cookie, requestConfig) => {
7166
7348
  }
7167
7349
  case "emojiList": return fetchKuaishouGraphqlPayload(data.methodType, kuaishouApiUrls.emojiList());
7168
7350
  default:
7169
- logger$2.warn(`Unknown Kuaishou API method: "${logger$2.red(data.methodType)}"`);
7351
+ emitLogWarn(`Unknown Kuaishou API method: "${data.methodType}"`);
7170
7352
  return null;
7171
7353
  }
7172
7354
  };
@@ -7205,12 +7387,12 @@ var GlobalGetData$2 = async (type, options, config) => {
7205
7387
  requestBody: JSON.stringify(options.data)
7206
7388
  };
7207
7389
  warningMessage = `
7208
- 获取响应数据失败!原因:${logger$2.yellow("接口返回内容为空,你的快手ck可能已经失效!")}
7390
+ 获取响应数据失败!原因:接口返回内容为空,你的快手ck可能已经失效!
7209
7391
  请求类型:「${type}」
7210
7392
  请求URL:${options.url}
7211
7393
  请求参数:${JSON.stringify(options.data, null, 2)}
7212
7394
  `;
7213
- logger$2.warn(warningMessage);
7395
+ emitLogWarn(warningMessage);
7214
7396
  const cookieError = new Error(Err.errorDescription);
7215
7397
  Object.assign(cookieError, {
7216
7398
  code: kuaishouAPIErrorCode.COOKIE,
@@ -7437,6 +7619,13 @@ function createBoundKuaishouFetcher(cookie, requestConfig) {
7437
7619
  }
7438
7620
  //#endregion
7439
7621
  //#region ../amagi/packages/core/src/platform/xiaohongshu/getdata.ts
7622
+ /** 小红书返回 code=-100,表示当前登录 Cookie 已失效。 */
7623
+ var XiaohongshuLoginExpiredError = class extends Error {
7624
+ constructor() {
7625
+ super("小红书登录 Cookie 已过期");
7626
+ this.name = "XiaohongshuLoginExpiredError";
7627
+ }
7628
+ };
7440
7629
  /**
7441
7630
  * 小红书数据获取函数
7442
7631
  * @param data - 请求数据参数
@@ -7445,131 +7634,143 @@ function createBoundKuaishouFetcher(cookie, requestConfig) {
7445
7634
  * @returns 返回小红书数据
7446
7635
  */
7447
7636
  var XiaohongshuData = async (data, cookie, requestConfig) => {
7448
- const defHeaders = getXiaohongshuDefaultConfig(cookie)["headers"];
7449
- const baseRequestConfig = {
7450
- method: "POST",
7451
- timeout: 1e4,
7452
- ...requestConfig,
7453
- headers: {
7454
- ...defHeaders,
7455
- ...requestConfig?.headers ?? {}
7456
- }
7457
- };
7458
- const xiaohongshuApiUrls = createXiaohongshuApiUrls();
7459
- switch (data.methodType) {
7460
- case "homeFeed": return await GlobalGetData$1(data.methodType, {
7461
- ...baseRequestConfig,
7462
- url: xiaohongshuApiUrls.homeFeed(data).Url,
7463
- data: JSON.stringify(xiaohongshuApiUrls.homeFeed(data).Body),
7464
- headers: {
7465
- ...baseRequestConfig.headers,
7466
- "x-s": xiaohongshuSign.generateXSPost(xiaohongshuApiUrls.homeFeed(data).apiPath, xiaohongshuSign.extractA1FromCookie(cookie ?? ""), "xhs-pc-web", xiaohongshuApiUrls.homeFeed(data).Body),
7467
- "x-s-common": xiaohongshuSign.generateXSCommon(cookie ?? ""),
7468
- "x-t": xiaohongshuSign.generateXT()
7469
- }
7470
- });
7471
- case "noteDetail": return await GlobalGetData$1(data.methodType, {
7472
- ...baseRequestConfig,
7473
- url: xiaohongshuApiUrls.noteDetail(data).Url,
7474
- data: xiaohongshuApiUrls.noteDetail(data).Body,
7637
+ /** 使用指定 Cookie 构建一次完整的小红书 API 请求。 */
7638
+ const requestWithCookie = async (requestCookie) => {
7639
+ const defHeaders = getXiaohongshuDefaultConfig(requestCookie)["headers"];
7640
+ const baseRequestConfig = {
7641
+ method: "POST",
7642
+ timeout: 1e4,
7643
+ ...requestConfig,
7475
7644
  headers: {
7476
- ...baseRequestConfig.headers,
7477
- "x-s": xiaohongshuSign.generateXSPost(xiaohongshuApiUrls.noteDetail(data).apiPath, xiaohongshuSign.extractA1FromCookie(cookie ?? ""), "xhs-pc-web", xiaohongshuApiUrls.noteDetail(data).Body),
7478
- "x-s-common": xiaohongshuSign.generateXSCommon(cookie ?? ""),
7479
- "x-t": xiaohongshuSign.generateXT()
7645
+ ...defHeaders,
7646
+ ...requestConfig?.headers ?? {}
7480
7647
  }
7481
- });
7482
- case "noteComments": {
7483
- const baseRequestConfig = {
7484
- method: "GET",
7485
- timeout: 1e4,
7486
- ...requestConfig,
7487
- headers: {
7488
- ...defHeaders,
7489
- ...requestConfig?.headers ?? {}
7490
- }
7491
- };
7492
- return await GlobalGetData$1(data.methodType, {
7648
+ };
7649
+ const xiaohongshuApiUrls = createXiaohongshuApiUrls();
7650
+ switch (data.methodType) {
7651
+ case "homeFeed": return await GlobalGetData$1(data.methodType, {
7493
7652
  ...baseRequestConfig,
7494
- url: xiaohongshuApiUrls.noteComments(data).Url,
7653
+ url: xiaohongshuApiUrls.homeFeed(data).Url,
7654
+ data: JSON.stringify(xiaohongshuApiUrls.homeFeed(data).Body),
7495
7655
  headers: {
7496
7656
  ...baseRequestConfig.headers,
7497
- "x-s": xiaohongshuSign.generateXSGet(xiaohongshuApiUrls.noteComments(data).apiPath, xiaohongshuSign.extractA1FromCookie(cookie ?? ""), "xhs-pc-web"),
7498
- "x-s-common": xiaohongshuSign.generateXSCommon(cookie ?? ""),
7657
+ "x-s": xiaohongshuSign.generateXSPost(xiaohongshuApiUrls.homeFeed(data).apiPath, xiaohongshuSign.extractA1FromCookie(requestCookie), "xhs-pc-web", xiaohongshuApiUrls.homeFeed(data).Body),
7658
+ "x-s-common": xiaohongshuSign.generateXSCommon(requestCookie),
7499
7659
  "x-t": xiaohongshuSign.generateXT()
7500
7660
  }
7501
7661
  });
7502
- }
7503
- case "userProfile": {
7504
- const baseRequestConfig = {
7505
- method: "GET",
7506
- timeout: 1e4,
7507
- ...requestConfig,
7662
+ case "noteDetail": return await GlobalGetData$1(data.methodType, {
7663
+ ...baseRequestConfig,
7664
+ url: xiaohongshuApiUrls.noteDetail(data).Url,
7665
+ data: xiaohongshuApiUrls.noteDetail(data).Body,
7508
7666
  headers: {
7509
- ...defHeaders,
7510
- ...requestConfig?.headers ?? {}
7667
+ ...baseRequestConfig.headers,
7668
+ "x-s": xiaohongshuSign.generateXSPost(xiaohongshuApiUrls.noteDetail(data).apiPath, xiaohongshuSign.extractA1FromCookie(requestCookie), "xhs-pc-web", xiaohongshuApiUrls.noteDetail(data).Body),
7669
+ "x-s-common": xiaohongshuSign.generateXSCommon(requestCookie),
7670
+ "x-t": xiaohongshuSign.generateXT()
7511
7671
  }
7512
- };
7513
- return {
7514
- code: 0,
7515
- data: extractCreatorInfoFromHtml(await GlobalGetData$1(data.methodType, {
7672
+ });
7673
+ case "noteComments": {
7674
+ const baseRequestConfig = {
7675
+ method: "GET",
7676
+ timeout: 1e4,
7677
+ ...requestConfig,
7678
+ headers: {
7679
+ ...defHeaders,
7680
+ ...requestConfig?.headers ?? {}
7681
+ }
7682
+ };
7683
+ return await GlobalGetData$1(data.methodType, {
7516
7684
  ...baseRequestConfig,
7517
- url: xiaohongshuApiUrls.userProfile(data).Url,
7685
+ url: xiaohongshuApiUrls.noteComments(data).Url,
7518
7686
  headers: {
7519
7687
  ...baseRequestConfig.headers,
7520
- "x-s": xiaohongshuSign.generateXSGet(xiaohongshuApiUrls.userProfile(data).apiPath, xiaohongshuSign.extractA1FromCookie(cookie ?? ""), "xhs-pc-web"),
7521
- "x-s-common": xiaohongshuSign.generateXSCommon(cookie ?? ""),
7688
+ "x-s": xiaohongshuSign.generateXSGet(xiaohongshuApiUrls.noteComments(data).apiPath, xiaohongshuSign.extractA1FromCookie(requestCookie), "xhs-pc-web"),
7689
+ "x-s-common": xiaohongshuSign.generateXSCommon(requestCookie),
7522
7690
  "x-t": xiaohongshuSign.generateXT()
7523
7691
  }
7524
- })),
7525
- msg: "success"
7526
- };
7527
- }
7528
- case "userNoteList": return await GlobalGetData$1(data.methodType, {
7529
- ...baseRequestConfig,
7530
- method: "GET",
7531
- url: xiaohongshuApiUrls.userNoteList(data).Url,
7532
- headers: {
7533
- ...baseRequestConfig.headers,
7534
- "x-b3-traceid": xiaohongshuSign.generateXB3Traceid(),
7535
- "x-s": xiaohongshuSign.generateXSGet(xiaohongshuApiUrls.userNoteList(data).apiPath, xiaohongshuSign.extractA1FromCookie(cookie ?? ""), "xhs-pc-web"),
7536
- "x-s-common": xiaohongshuSign.generateXSCommon(cookie ?? ""),
7537
- "x-t": xiaohongshuSign.generateXT()
7692
+ });
7538
7693
  }
7539
- });
7540
- case "emojiList": {
7541
- const baseRequestConfig = {
7694
+ case "userProfile": {
7695
+ const baseRequestConfig = {
7696
+ method: "GET",
7697
+ timeout: 1e4,
7698
+ ...requestConfig,
7699
+ headers: {
7700
+ ...defHeaders,
7701
+ ...requestConfig?.headers ?? {}
7702
+ }
7703
+ };
7704
+ return {
7705
+ code: 0,
7706
+ data: extractCreatorInfoFromHtml(await GlobalGetData$1(data.methodType, {
7707
+ ...baseRequestConfig,
7708
+ url: xiaohongshuApiUrls.userProfile(data).Url,
7709
+ headers: {
7710
+ ...baseRequestConfig.headers,
7711
+ "x-s": xiaohongshuSign.generateXSGet(xiaohongshuApiUrls.userProfile(data).apiPath, xiaohongshuSign.extractA1FromCookie(requestCookie), "xhs-pc-web"),
7712
+ "x-s-common": xiaohongshuSign.generateXSCommon(requestCookie),
7713
+ "x-t": xiaohongshuSign.generateXT()
7714
+ }
7715
+ })),
7716
+ msg: "success"
7717
+ };
7718
+ }
7719
+ case "userNoteList": return await GlobalGetData$1(data.methodType, {
7720
+ ...baseRequestConfig,
7542
7721
  method: "GET",
7543
- timeout: 1e4,
7544
- ...requestConfig,
7722
+ url: xiaohongshuApiUrls.userNoteList(data).Url,
7545
7723
  headers: {
7546
- ...defHeaders,
7547
- ...requestConfig?.headers ?? {}
7724
+ ...baseRequestConfig.headers,
7725
+ "x-b3-traceid": xiaohongshuSign.generateXB3Traceid(),
7726
+ "x-s": xiaohongshuSign.generateXSGet(xiaohongshuApiUrls.userNoteList(data).apiPath, xiaohongshuSign.extractA1FromCookie(requestCookie), "xhs-pc-web"),
7727
+ "x-s-common": xiaohongshuSign.generateXSCommon(requestCookie),
7728
+ "x-t": xiaohongshuSign.generateXT()
7548
7729
  }
7549
- };
7550
- return await GlobalGetData$1(data.methodType, {
7730
+ });
7731
+ case "emojiList": {
7732
+ const baseRequestConfig = {
7733
+ method: "GET",
7734
+ timeout: 1e4,
7735
+ ...requestConfig,
7736
+ headers: {
7737
+ ...defHeaders,
7738
+ ...requestConfig?.headers ?? {}
7739
+ }
7740
+ };
7741
+ return await GlobalGetData$1(data.methodType, {
7742
+ ...baseRequestConfig,
7743
+ url: xiaohongshuApiUrls.emojiList(data).Url,
7744
+ headers: {
7745
+ ...baseRequestConfig.headers,
7746
+ "x-s": xiaohongshuSign.generateXSGet(xiaohongshuApiUrls.emojiList(data).apiPath, xiaohongshuSign.extractA1FromCookie(requestCookie), "xhs-pc-web"),
7747
+ "x-s-common": xiaohongshuSign.generateXSCommon(requestCookie),
7748
+ "x-t": xiaohongshuSign.generateXT()
7749
+ }
7750
+ });
7751
+ }
7752
+ case "searchNotes": return await GlobalGetData$1(data.methodType, {
7551
7753
  ...baseRequestConfig,
7552
- url: xiaohongshuApiUrls.emojiList(data).Url,
7754
+ url: xiaohongshuApiUrls.searchNotes(data).Url,
7755
+ data: xiaohongshuApiUrls.searchNotes(data).Body,
7553
7756
  headers: {
7554
7757
  ...baseRequestConfig.headers,
7555
- "x-s": xiaohongshuSign.generateXSGet(xiaohongshuApiUrls.emojiList(data).apiPath, xiaohongshuSign.extractA1FromCookie(cookie ?? ""), "xhs-pc-web"),
7556
- "x-s-common": xiaohongshuSign.generateXSCommon(cookie ?? ""),
7758
+ "x-s": xiaohongshuSign.generateXSPost(xiaohongshuApiUrls.searchNotes(data).apiPath, xiaohongshuSign.extractA1FromCookie(requestCookie), "xhs-pc-web"),
7759
+ "x-s-common": xiaohongshuSign.generateXSCommon(requestCookie),
7557
7760
  "x-t": xiaohongshuSign.generateXT()
7558
7761
  }
7559
7762
  });
7763
+ default: throw new Error(`Unknown Xiaohongshu API method: "${data.methodType}"`);
7560
7764
  }
7561
- case "searchNotes": return await GlobalGetData$1(data.methodType, {
7562
- ...baseRequestConfig,
7563
- url: xiaohongshuApiUrls.searchNotes(data).Url,
7564
- data: xiaohongshuApiUrls.searchNotes(data).Body,
7565
- headers: {
7566
- ...baseRequestConfig.headers,
7567
- "x-s": xiaohongshuSign.generateXSPost(xiaohongshuApiUrls.searchNotes(data).apiPath, xiaohongshuSign.extractA1FromCookie(cookie ?? ""), "xhs-pc-web"),
7568
- "x-s-common": xiaohongshuSign.generateXSCommon(cookie ?? ""),
7569
- "x-t": xiaohongshuSign.generateXT()
7570
- }
7571
- });
7572
- default: throw new Error(`Unknown Xiaohongshu API method: "${logger$2.red(data.methodType)}"`);
7765
+ };
7766
+ const userCookie = cookie?.trim();
7767
+ if (!userCookie) return requestWithCookie(await xiaohongshuSign.createGuestCookie(requestConfig));
7768
+ try {
7769
+ return await requestWithCookie(userCookie);
7770
+ } catch (error) {
7771
+ if (!(error instanceof XiaohongshuLoginExpiredError)) throw error;
7772
+ emitLogWarn("小红书用户 Cookie 已过期,切换游客 Cookie 后重试请求");
7773
+ return requestWithCookie(await xiaohongshuSign.createGuestCookie(requestConfig));
7573
7774
  }
7574
7775
  };
7575
7776
  /**
@@ -7591,10 +7792,12 @@ var GlobalGetData$1 = async (methodType, config) => {
7591
7792
  throw networkError;
7592
7793
  }
7593
7794
  if (typeof response === "string" && response.includes("<html>")) return response;
7795
+ if (response.code === -100) throw new XiaohongshuLoginExpiredError();
7594
7796
  if (response.code !== 0) throw new Error(`API request failed: ${response.data?.msg ?? response.msg ?? "Unknown error"}, code: ${response.code}`);
7595
7797
  return response;
7596
7798
  } catch (error) {
7597
- logger$2.error(`Xiaohongshu API request failed [${methodType}]:`, error.message);
7799
+ if (error instanceof XiaohongshuLoginExpiredError) throw error;
7800
+ emitLogError(`Xiaohongshu API request failed [${methodType}]:`, error.message);
7598
7801
  return {
7599
7802
  code: 500,
7600
7803
  message: "error",
@@ -8523,7 +8726,7 @@ var fetchBilibili = async (data, cookie, requestConfig) => {
8523
8726
  ...baseRequestConfig,
8524
8727
  url: checkStatusUrl
8525
8728
  })).data === null) {
8526
- logger$2.error("评论区未开放");
8729
+ emitLogError("评论区未开放");
8527
8730
  return {
8528
8731
  code: 404,
8529
8732
  message: "评论区未开放",
@@ -8554,7 +8757,7 @@ var fetchBilibili = async (data, cookie, requestConfig) => {
8554
8757
  } else isEnd = true;
8555
8758
  requestCount++;
8556
8759
  if (isEnd || currentComments.length === 0 || !nextPaginationStr) {
8557
- logger$2.info("已到达评论末尾或无更多评论");
8760
+ emitLogInfo("已到达评论末尾或无更多评论");
8558
8761
  break;
8559
8762
  }
8560
8763
  }
@@ -8794,7 +8997,7 @@ var fetchBilibili = async (data, cookie, requestConfig) => {
8794
8997
  }
8795
8998
  }
8796
8999
  default:
8797
- logger$2.warn(`未知的B站数据接口:「${logger$2.red(data.methodType)}」`);
9000
+ emitLogWarn(`未知的B站数据接口:「${data.methodType}」`);
8798
9001
  return null;
8799
9002
  }
8800
9003
  };
@@ -8830,11 +9033,11 @@ var GlobalGetData = async (type, options, retryCount = 0) => {
8830
9033
  requestUrl: options.url
8831
9034
  };
8832
9035
  warningMessage = `
8833
- 获取响应数据失败!原因:${logger$2.yellow("接口返回内容为空,你的B站ck可能已经失效!")}
9036
+ 获取响应数据失败!原因:接口返回内容为空,你的B站ck可能已经失效!
8834
9037
  请求类型:「${type}」
8835
9038
  请求URL:${options.url}
8836
9039
  `;
8837
- logger$2.warn(warningMessage);
9040
+ emitLogWarn(warningMessage);
8838
9041
  const riskError = new Error(Err.errorDescription);
8839
9042
  Object.assign(riskError, {
8840
9043
  code: bilibiliAPIErrorCode.RISK_CONTROL_FAILED,
@@ -8856,12 +9059,12 @@ var GlobalGetData = async (type, options, retryCount = 0) => {
8856
9059
  responseCode: result.code
8857
9060
  };
8858
9061
  warningMessage = `
8859
- 获取响应数据失败!原因:${logger$2.yellow(errorMessage)}
9062
+ 获取响应数据失败!原因:${errorMessage}
8860
9063
  错误代码:${result.code}
8861
9064
  请求类型:「${type}」
8862
9065
  请求URL:${options.url}
8863
9066
  `;
8864
- logger$2.warn(warningMessage);
9067
+ emitLogWarn(warningMessage);
8865
9068
  const apiError = new Error(Err.errorDescription);
8866
9069
  Object.assign(apiError, {
8867
9070
  code: result.code,
@@ -16943,8 +17146,9 @@ var BilibiliReserveCard = ({ reserve }) => {
16943
17146
  }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
16944
17147
  className: "shrink-0",
16945
17148
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Button, {
16946
- className: `text-5xl font-normal px-8 py-5 h-auto min-w-0 ${reserve.buttonText === "已结束" ? "bg-surface-secondary/70 text-muted" : "bg-[#fb7299] text-white"}`,
16947
- children: [reserve.buttonText !== "已结束" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BellRing, { className: "scale-180 mr-4" }), reserve.buttonText]
17149
+ size: "lg",
17150
+ className: `font-normal scale-200 mr-15 rounded-xl ${reserve.buttonText === "已结束" ? "bg-surface-secondary/70 text-muted" : "bg-[#fb7299] text-white"}`,
17151
+ children: [reserve.buttonText !== "已结束" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BellRing, { size: 330 }), reserve.buttonText]
16948
17152
  })
16949
17153
  })]
16950
17154
  })