karin-plugin-kkk 2.36.0 → 2.36.2
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/CHANGELOG.md +52 -24
- package/lib/build-metadata.json +5 -5
- package/lib/core_chunk/amagi.d.mts +6 -0
- package/lib/core_chunk/main.js +785 -290
- package/lib/core_chunk/rolldown-runtime.js +1 -1
- package/lib/core_chunk/vendor.js +8112 -7769
- package/lib/karin-plugin-kkk.css +617 -125
- package/lib/web/assets/CronEditor-BrSMQ7Wt.js +1 -0
- package/lib/web/assets/DesktopLayout-D42mvBB3.js +1 -0
- package/lib/web/assets/MobileLayout-CsGZCHOX.js +1 -0
- package/lib/web/assets/ThemeSwitch-CehenZXq.js +1 -0
- package/lib/web/assets/{index-3mh4kVq1.css → index-hQel6cUs.css} +2 -2
- package/lib/web/assets/index-xT9tCQxI.js +47 -0
- package/lib/web/assets/separator-0i510i92.js +1 -0
- package/lib/web/index.html +2 -2
- package/package.json +2 -2
- package/lib/web/assets/CronEditor-KiEwYMrF.js +0 -1
- package/lib/web/assets/DesktopLayout-Cdla4l6u.js +0 -1
- package/lib/web/assets/MobileLayout-DfXVuyA-.js +0 -1
- package/lib/web/assets/ThemeSwitch-DcAlzu8R.js +0 -1
- package/lib/web/assets/index-zS6iiHmV.js +0 -47
package/lib/core_chunk/main.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { i as __toESM } from "./rolldown-runtime.js";
|
|
2
|
-
import { $ as
|
|
2
|
+
import { $ as SiXiaomi, $n as CircleCheckBig, $t as Quote, A as AiFillHeart, An as Copy, At as X, B as RiHeartLine, Bn as Box, Bt as Square, C as MdLocationOn, Cn as Eye, Ct as parse, D as FaTiktok, Dn as Crown, Dt as differenceInSeconds, E as FaMusic, En as Download, Et as format, F as RiArrowRightFill, Fn as CircleFadingArrowUp, Ft as Upload, G as RiStarFill, Gn as WandSparkles, Gt as Share2, H as RiMessage3Fill, Hn as Bookmark, Ht as ShoppingBag, I as RiGroupLine, In as CircleEllipsis, It as Trash2, J as RiTiktokFill, Jn as SquarePen, Jt as ScanLine, K as RiStarLine, Kn as UsersRound, Kt as Settings2, L as RiHashtag, Ln as Check, Lt as Terminal, M as AiFillStar, Mn as Clock, Mt as Users, N as AiOutlineVideoCamera, Nn as Clock3, Nt as User, O as FaUserGroup, On as Cpu, Ot as twMerge, P as Markdown, Pn as Clapperboard, Pt as UserPlus, Q as RiVideoLine, Qn as CircleQuestionMark, Qt as Radio, R as RiHeart3Fill, Rn as Camera, Rt as Sun, S as MdLightbulbOutline, Sn as FileText, St as zhCN, T as FaCommentDots, Tn as ExternalLink, Tt as formatDistanceToNow, U as RiPieChart2Fill, Un as BellRing, Ut as Shield, V as RiLiveLine, Vn as Bot, Vt as Smartphone, W as RiShareForwardFill, Wn as ArrowDownToLine, Wt as ShieldCheck, X as RiUserFollowLine, Xn as LoaderCircle, Xt as RotateCcw, Y as RiTrophyFill, Yn as Sparkles, Yt as Save, Z as RiVerifiedBadgeFill, Zn as FilePlay, Zt as RefreshCw, _ as tailwind_css, _n as Heart, _t as n, a as VictoryScatter, an as Palette, ar as clsx, at as SiHonor, b as MdFitScreen, bn as Gift, bt as o$1, c as VictoryChart, cn as Monitor, cr as require_react, ct as SiBilibili, d as VictoryTheme, dn as Maximize, dr as CryptoConfig, dt as o$2, en as QrCode, er as CircleCheck, et as SiVivo, f as rehypeHighlight, fn as MapPin, fr as FingerprintGenerator, ft as r, g as tsdown, gn as Image$1, gt as a, h as typescript, hn as Info, ht as m, i as require_heic_decode, in as Pencil, ir as Button, it as SiHuawei, j as AiFillPushpin, jn as Code, jt as Video, k as BiImage, kn as CornerDownLeft, kt as Zap, l as VictoryAxis, ln as MessageCircle, lr as require_protobufjs, lt as SiApple, m as vite, mn as LayoutTemplate, mr as zod_default, mt as o$3, n as require_lib, nn as Plus, nr as ChartColumn, nt as SiOppo, o as VictoryPie, on as Music, or as require_jsx_runtime, ot as SiGooglephotos, p as webassembly, pn as Link, pr as Xhshow, pt as o, q as RiThumbUpFill, qn as TriangleAlert, qt as Search, r as require_jpeg_js, rn as Play, rr as Chip, rt as SiOneplus, s as VictoryLine, sn as Moon, sr as require_server_node, st as SiGithub, t as createProxyMiddleware, tn as Puzzle, tr as CircleAlert, tt as SiSamsung, u as VictoryLabel, un as Menu, ur as Chalk, ut as SiAnthropic, v as sqlite, vn as Hash, vt as e, w as MdSchedule, wn as EyeOff, wt as fromUnixTime, x as MdInfoOutline, xn as Gamepad2, xt as c, y as react, yn as GitBranch, yt as a$1, z as RiHeart3Line, zn as Calendar, zt as Star } from "./vendor.js";
|
|
3
3
|
import "node:module";
|
|
4
4
|
import fs from "node:fs";
|
|
5
5
|
import path, { resolve } from "node:path";
|
|
6
|
-
import URL$
|
|
7
|
-
import karin
|
|
6
|
+
import URL$2, { fileURLToPath } from "node:url";
|
|
7
|
+
import karin, { BOT_CONNECT, app, authMiddleware, checkPkgUpdate, checkPort, common, config, createBadRequestResponse, createNotFoundResponse, createServerErrorResponse, createSuccessResponse, db, defineConfig, ffmpeg, ffprobe, hooks, karin as karin$1, 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路径
|
|
@@ -3288,7 +3470,7 @@ var XBogus = class {
|
|
|
3288
3470
|
* @returns 包含完整URL、X-Bogus值和使用的User-Agent的元组
|
|
3289
3471
|
*/
|
|
3290
3472
|
getXBogus(url, ua) {
|
|
3291
|
-
const parsedUrl = new URL$
|
|
3473
|
+
const parsedUrl = new URL$2.URL(url);
|
|
3292
3474
|
const urlPath = parsedUrl.pathname + parsedUrl.search;
|
|
3293
3475
|
const currentUa = ua ?? this.defaultUa;
|
|
3294
3476
|
const rc4EncryptedUa = this.rc4Encrypt(this.uaKey, currentUa);
|
|
@@ -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
|
-
获取响应数据失败!原因:${
|
|
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
|
-
获取响应数据失败!原因:${
|
|
4440
|
+
获取响应数据失败!原因:${typeStr}搜索接口第一次请求就返回空数组,你的抖音Cookie可能已经失效!
|
|
4259
4441
|
请求类型:「${data.methodType}」
|
|
4260
4442
|
搜索关键词:「${data.query}」
|
|
4261
4443
|
请求URL:${url}
|
|
4262
4444
|
`;
|
|
4263
|
-
|
|
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
|
-
|
|
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
|
-
|
|
4549
|
+
emitLogDebug(`弹幕第${index + 1}段获取成功 (${segment.start}ms-${segment.end}ms)`);
|
|
4368
4550
|
return segmentData;
|
|
4369
4551
|
} catch (error) {
|
|
4370
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
4661
|
+
获取响应数据失败!原因:接口返回内容为空,你的抖音ck可能已经失效!
|
|
4480
4662
|
请求类型:「${type}」
|
|
4481
4663
|
请求URL:${config.url}
|
|
4482
4664
|
`;
|
|
4483
|
-
|
|
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
|
-
获取响应数据失败!原因:${
|
|
4682
|
+
获取响应数据失败!原因:${filterReason}
|
|
4501
4683
|
请求类型:「${type}」
|
|
4502
4684
|
请求URL:${config.url}
|
|
4503
4685
|
`;
|
|
4504
|
-
|
|
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
|
-
|
|
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
|
-
|
|
7390
|
+
获取响应数据失败!原因:接口返回内容为空,你的快手ck可能已经失效!
|
|
7209
7391
|
请求类型:「${type}」
|
|
7210
7392
|
请求URL:${options.url}
|
|
7211
7393
|
请求参数:${JSON.stringify(options.data, null, 2)}
|
|
7212
7394
|
`;
|
|
7213
|
-
|
|
7395
|
+
emitLogWarn(warningMessage);
|
|
7214
7396
|
const cookieError = new Error(Err.errorDescription);
|
|
7215
7397
|
Object.assign(cookieError, {
|
|
7216
7398
|
code: kuaishouAPIErrorCode.COOKIE,
|
|
@@ -7445,132 +7627,136 @@ function createBoundKuaishouFetcher(cookie, requestConfig) {
|
|
|
7445
7627
|
* @returns 返回小红书数据
|
|
7446
7628
|
*/
|
|
7447
7629
|
var XiaohongshuData = async (data, cookie, requestConfig) => {
|
|
7448
|
-
|
|
7449
|
-
const
|
|
7450
|
-
|
|
7451
|
-
|
|
7452
|
-
|
|
7453
|
-
|
|
7454
|
-
...
|
|
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,
|
|
7630
|
+
/** 使用指定 Cookie 构建一次完整的小红书 API 请求。 */
|
|
7631
|
+
const requestWithCookie = async (requestCookie) => {
|
|
7632
|
+
const defHeaders = getXiaohongshuDefaultConfig(requestCookie)["headers"];
|
|
7633
|
+
const baseRequestConfig = {
|
|
7634
|
+
method: "POST",
|
|
7635
|
+
timeout: 1e4,
|
|
7636
|
+
...requestConfig,
|
|
7475
7637
|
headers: {
|
|
7476
|
-
...
|
|
7477
|
-
|
|
7478
|
-
"x-s-common": xiaohongshuSign.generateXSCommon(cookie ?? ""),
|
|
7479
|
-
"x-t": xiaohongshuSign.generateXT()
|
|
7638
|
+
...defHeaders,
|
|
7639
|
+
...requestConfig?.headers ?? {}
|
|
7480
7640
|
}
|
|
7481
|
-
}
|
|
7482
|
-
|
|
7483
|
-
|
|
7484
|
-
|
|
7485
|
-
timeout: 1e4,
|
|
7486
|
-
...requestConfig,
|
|
7487
|
-
headers: {
|
|
7488
|
-
...defHeaders,
|
|
7489
|
-
...requestConfig?.headers ?? {}
|
|
7490
|
-
}
|
|
7491
|
-
};
|
|
7492
|
-
return await GlobalGetData$1(data.methodType, {
|
|
7641
|
+
};
|
|
7642
|
+
const xiaohongshuApiUrls = createXiaohongshuApiUrls();
|
|
7643
|
+
switch (data.methodType) {
|
|
7644
|
+
case "homeFeed": return await GlobalGetData$1(data.methodType, {
|
|
7493
7645
|
...baseRequestConfig,
|
|
7494
|
-
url: xiaohongshuApiUrls.
|
|
7646
|
+
url: xiaohongshuApiUrls.homeFeed(data).Url,
|
|
7647
|
+
data: JSON.stringify(xiaohongshuApiUrls.homeFeed(data).Body),
|
|
7495
7648
|
headers: {
|
|
7496
7649
|
...baseRequestConfig.headers,
|
|
7497
|
-
"x-s": xiaohongshuSign.
|
|
7498
|
-
"x-s-common": xiaohongshuSign.generateXSCommon(
|
|
7650
|
+
"x-s": xiaohongshuSign.generateXSPost(xiaohongshuApiUrls.homeFeed(data).apiPath, xiaohongshuSign.extractA1FromCookie(requestCookie), "xhs-pc-web", xiaohongshuApiUrls.homeFeed(data).Body),
|
|
7651
|
+
"x-s-common": xiaohongshuSign.generateXSCommon(requestCookie),
|
|
7499
7652
|
"x-t": xiaohongshuSign.generateXT()
|
|
7500
7653
|
}
|
|
7501
7654
|
});
|
|
7502
|
-
|
|
7503
|
-
|
|
7504
|
-
|
|
7505
|
-
|
|
7506
|
-
timeout: 1e4,
|
|
7507
|
-
...requestConfig,
|
|
7655
|
+
case "noteDetail": return await GlobalGetData$1(data.methodType, {
|
|
7656
|
+
...baseRequestConfig,
|
|
7657
|
+
url: xiaohongshuApiUrls.noteDetail(data).Url,
|
|
7658
|
+
data: xiaohongshuApiUrls.noteDetail(data).Body,
|
|
7508
7659
|
headers: {
|
|
7509
|
-
...
|
|
7510
|
-
|
|
7660
|
+
...baseRequestConfig.headers,
|
|
7661
|
+
"x-s": xiaohongshuSign.generateXSPost(xiaohongshuApiUrls.noteDetail(data).apiPath, xiaohongshuSign.extractA1FromCookie(requestCookie), "xhs-pc-web", xiaohongshuApiUrls.noteDetail(data).Body),
|
|
7662
|
+
"x-s-common": xiaohongshuSign.generateXSCommon(requestCookie),
|
|
7663
|
+
"x-t": xiaohongshuSign.generateXT()
|
|
7511
7664
|
}
|
|
7512
|
-
};
|
|
7513
|
-
|
|
7514
|
-
|
|
7515
|
-
|
|
7665
|
+
});
|
|
7666
|
+
case "noteComments": {
|
|
7667
|
+
const baseRequestConfig = {
|
|
7668
|
+
method: "GET",
|
|
7669
|
+
timeout: 1e4,
|
|
7670
|
+
...requestConfig,
|
|
7671
|
+
headers: {
|
|
7672
|
+
...defHeaders,
|
|
7673
|
+
...requestConfig?.headers ?? {}
|
|
7674
|
+
}
|
|
7675
|
+
};
|
|
7676
|
+
return await GlobalGetData$1(data.methodType, {
|
|
7516
7677
|
...baseRequestConfig,
|
|
7517
|
-
url: xiaohongshuApiUrls.
|
|
7678
|
+
url: xiaohongshuApiUrls.noteComments(data).Url,
|
|
7518
7679
|
headers: {
|
|
7519
7680
|
...baseRequestConfig.headers,
|
|
7520
|
-
"x-s": xiaohongshuSign.generateXSGet(xiaohongshuApiUrls.
|
|
7521
|
-
"x-s-common": xiaohongshuSign.generateXSCommon(
|
|
7681
|
+
"x-s": xiaohongshuSign.generateXSGet(xiaohongshuApiUrls.noteComments(data).apiPath, xiaohongshuSign.extractA1FromCookie(requestCookie), "xhs-pc-web"),
|
|
7682
|
+
"x-s-common": xiaohongshuSign.generateXSCommon(requestCookie),
|
|
7522
7683
|
"x-t": xiaohongshuSign.generateXT()
|
|
7523
7684
|
}
|
|
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()
|
|
7685
|
+
});
|
|
7538
7686
|
}
|
|
7539
|
-
|
|
7540
|
-
|
|
7541
|
-
|
|
7687
|
+
case "userProfile": {
|
|
7688
|
+
const baseRequestConfig = {
|
|
7689
|
+
method: "GET",
|
|
7690
|
+
timeout: 1e4,
|
|
7691
|
+
...requestConfig,
|
|
7692
|
+
headers: {
|
|
7693
|
+
...defHeaders,
|
|
7694
|
+
...requestConfig?.headers ?? {}
|
|
7695
|
+
}
|
|
7696
|
+
};
|
|
7697
|
+
return {
|
|
7698
|
+
code: 0,
|
|
7699
|
+
data: extractCreatorInfoFromHtml(await GlobalGetData$1(data.methodType, {
|
|
7700
|
+
...baseRequestConfig,
|
|
7701
|
+
url: xiaohongshuApiUrls.userProfile(data).Url,
|
|
7702
|
+
headers: {
|
|
7703
|
+
...baseRequestConfig.headers,
|
|
7704
|
+
"x-s": xiaohongshuSign.generateXSGet(xiaohongshuApiUrls.userProfile(data).apiPath, xiaohongshuSign.extractA1FromCookie(requestCookie), "xhs-pc-web"),
|
|
7705
|
+
"x-s-common": xiaohongshuSign.generateXSCommon(requestCookie),
|
|
7706
|
+
"x-t": xiaohongshuSign.generateXT()
|
|
7707
|
+
}
|
|
7708
|
+
})),
|
|
7709
|
+
msg: "success"
|
|
7710
|
+
};
|
|
7711
|
+
}
|
|
7712
|
+
case "userNoteList": return await GlobalGetData$1(data.methodType, {
|
|
7713
|
+
...baseRequestConfig,
|
|
7542
7714
|
method: "GET",
|
|
7543
|
-
|
|
7544
|
-
...requestConfig,
|
|
7715
|
+
url: xiaohongshuApiUrls.userNoteList(data).Url,
|
|
7545
7716
|
headers: {
|
|
7546
|
-
...
|
|
7547
|
-
|
|
7717
|
+
...baseRequestConfig.headers,
|
|
7718
|
+
"x-b3-traceid": xiaohongshuSign.generateXB3Traceid(),
|
|
7719
|
+
"x-s": xiaohongshuSign.generateXSGet(xiaohongshuApiUrls.userNoteList(data).apiPath, xiaohongshuSign.extractA1FromCookie(requestCookie), "xhs-pc-web"),
|
|
7720
|
+
"x-s-common": xiaohongshuSign.generateXSCommon(requestCookie),
|
|
7721
|
+
"x-t": xiaohongshuSign.generateXT()
|
|
7548
7722
|
}
|
|
7549
|
-
};
|
|
7550
|
-
|
|
7723
|
+
});
|
|
7724
|
+
case "emojiList": {
|
|
7725
|
+
const baseRequestConfig = {
|
|
7726
|
+
method: "GET",
|
|
7727
|
+
timeout: 1e4,
|
|
7728
|
+
...requestConfig,
|
|
7729
|
+
headers: {
|
|
7730
|
+
...defHeaders,
|
|
7731
|
+
...requestConfig?.headers ?? {}
|
|
7732
|
+
}
|
|
7733
|
+
};
|
|
7734
|
+
return await GlobalGetData$1(data.methodType, {
|
|
7735
|
+
...baseRequestConfig,
|
|
7736
|
+
url: xiaohongshuApiUrls.emojiList(data).Url,
|
|
7737
|
+
headers: {
|
|
7738
|
+
...baseRequestConfig.headers,
|
|
7739
|
+
"x-s": xiaohongshuSign.generateXSGet(xiaohongshuApiUrls.emojiList(data).apiPath, xiaohongshuSign.extractA1FromCookie(requestCookie), "xhs-pc-web"),
|
|
7740
|
+
"x-s-common": xiaohongshuSign.generateXSCommon(requestCookie),
|
|
7741
|
+
"x-t": xiaohongshuSign.generateXT()
|
|
7742
|
+
}
|
|
7743
|
+
});
|
|
7744
|
+
}
|
|
7745
|
+
case "searchNotes": return await GlobalGetData$1(data.methodType, {
|
|
7551
7746
|
...baseRequestConfig,
|
|
7552
|
-
url: xiaohongshuApiUrls.
|
|
7747
|
+
url: xiaohongshuApiUrls.searchNotes(data).Url,
|
|
7748
|
+
data: xiaohongshuApiUrls.searchNotes(data).Body,
|
|
7553
7749
|
headers: {
|
|
7554
7750
|
...baseRequestConfig.headers,
|
|
7555
|
-
"x-s": xiaohongshuSign.
|
|
7556
|
-
"x-s-common": xiaohongshuSign.generateXSCommon(
|
|
7751
|
+
"x-s": xiaohongshuSign.generateXSPost(xiaohongshuApiUrls.searchNotes(data).apiPath, xiaohongshuSign.extractA1FromCookie(requestCookie), "xhs-pc-web"),
|
|
7752
|
+
"x-s-common": xiaohongshuSign.generateXSCommon(requestCookie),
|
|
7557
7753
|
"x-t": xiaohongshuSign.generateXT()
|
|
7558
7754
|
}
|
|
7559
7755
|
});
|
|
7756
|
+
default: throw new Error(`Unknown Xiaohongshu API method: "${data.methodType}"`);
|
|
7560
7757
|
}
|
|
7561
|
-
|
|
7562
|
-
|
|
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)}"`);
|
|
7573
|
-
}
|
|
7758
|
+
};
|
|
7759
|
+
return requestWithCookie(cookie?.trim() ?? "");
|
|
7574
7760
|
};
|
|
7575
7761
|
/**
|
|
7576
7762
|
* 全局数据获取函数
|
|
@@ -7594,7 +7780,7 @@ var GlobalGetData$1 = async (methodType, config) => {
|
|
|
7594
7780
|
if (response.code !== 0) throw new Error(`API request failed: ${response.data?.msg ?? response.msg ?? "Unknown error"}, code: ${response.code}`);
|
|
7595
7781
|
return response;
|
|
7596
7782
|
} catch (error) {
|
|
7597
|
-
|
|
7783
|
+
emitLogError(`Xiaohongshu API request failed [${methodType}]:`, error.message);
|
|
7598
7784
|
return {
|
|
7599
7785
|
code: 500,
|
|
7600
7786
|
message: "error",
|
|
@@ -8523,7 +8709,7 @@ var fetchBilibili = async (data, cookie, requestConfig) => {
|
|
|
8523
8709
|
...baseRequestConfig,
|
|
8524
8710
|
url: checkStatusUrl
|
|
8525
8711
|
})).data === null) {
|
|
8526
|
-
|
|
8712
|
+
emitLogError("评论区未开放");
|
|
8527
8713
|
return {
|
|
8528
8714
|
code: 404,
|
|
8529
8715
|
message: "评论区未开放",
|
|
@@ -8554,7 +8740,7 @@ var fetchBilibili = async (data, cookie, requestConfig) => {
|
|
|
8554
8740
|
} else isEnd = true;
|
|
8555
8741
|
requestCount++;
|
|
8556
8742
|
if (isEnd || currentComments.length === 0 || !nextPaginationStr) {
|
|
8557
|
-
|
|
8743
|
+
emitLogInfo("已到达评论末尾或无更多评论");
|
|
8558
8744
|
break;
|
|
8559
8745
|
}
|
|
8560
8746
|
}
|
|
@@ -8794,7 +8980,7 @@ var fetchBilibili = async (data, cookie, requestConfig) => {
|
|
|
8794
8980
|
}
|
|
8795
8981
|
}
|
|
8796
8982
|
default:
|
|
8797
|
-
|
|
8983
|
+
emitLogWarn(`未知的B站数据接口:「${data.methodType}」`);
|
|
8798
8984
|
return null;
|
|
8799
8985
|
}
|
|
8800
8986
|
};
|
|
@@ -8830,11 +9016,11 @@ var GlobalGetData = async (type, options, retryCount = 0) => {
|
|
|
8830
9016
|
requestUrl: options.url
|
|
8831
9017
|
};
|
|
8832
9018
|
warningMessage = `
|
|
8833
|
-
|
|
9019
|
+
获取响应数据失败!原因:接口返回内容为空,你的B站ck可能已经失效!
|
|
8834
9020
|
请求类型:「${type}」
|
|
8835
9021
|
请求URL:${options.url}
|
|
8836
9022
|
`;
|
|
8837
|
-
|
|
9023
|
+
emitLogWarn(warningMessage);
|
|
8838
9024
|
const riskError = new Error(Err.errorDescription);
|
|
8839
9025
|
Object.assign(riskError, {
|
|
8840
9026
|
code: bilibiliAPIErrorCode.RISK_CONTROL_FAILED,
|
|
@@ -8856,12 +9042,12 @@ var GlobalGetData = async (type, options, retryCount = 0) => {
|
|
|
8856
9042
|
responseCode: result.code
|
|
8857
9043
|
};
|
|
8858
9044
|
warningMessage = `
|
|
8859
|
-
获取响应数据失败!原因:${
|
|
9045
|
+
获取响应数据失败!原因:${errorMessage}
|
|
8860
9046
|
错误代码:${result.code}
|
|
8861
9047
|
请求类型:「${type}」
|
|
8862
9048
|
请求URL:${options.url}
|
|
8863
9049
|
`;
|
|
8864
|
-
|
|
9050
|
+
emitLogWarn(warningMessage);
|
|
8865
9051
|
const apiError = new Error(Err.errorDescription);
|
|
8866
9052
|
Object.assign(apiError, {
|
|
8867
9053
|
code: result.code,
|
|
@@ -10147,7 +10333,7 @@ function getApiRoute(platform, methodType) {
|
|
|
10147
10333
|
* 构建后使用 __VERSION__,开发环境从 package.json 读取
|
|
10148
10334
|
*/
|
|
10149
10335
|
var getVersion = () => {
|
|
10150
|
-
return "6.
|
|
10336
|
+
return "6.2.0";
|
|
10151
10337
|
};
|
|
10152
10338
|
var VERSION = getVersion();
|
|
10153
10339
|
/**
|
|
@@ -10703,7 +10889,7 @@ var uploadFile = async (event, file, videoUrl, options) => {
|
|
|
10703
10889
|
let contact;
|
|
10704
10890
|
if (options?.active) {
|
|
10705
10891
|
selfId = options?.activeOption?.uin;
|
|
10706
|
-
contact = karin
|
|
10892
|
+
contact = karin.contactGroup(options?.activeOption?.group_id);
|
|
10707
10893
|
} else {
|
|
10708
10894
|
selfId = event.selfId;
|
|
10709
10895
|
contact = event.contact;
|
|
@@ -10712,7 +10898,7 @@ var uploadFile = async (event, file, videoUrl, options) => {
|
|
|
10712
10898
|
const Duration = await getMediaDuration(file.filepath);
|
|
10713
10899
|
logger.warn(logger.yellow(`视频大小 (${file.totalBytes} MB) 触发压缩条件(设定值:${Config.app.compresstrigger} MB),正在进行压缩至${Config.app.compressvalue} MB...`));
|
|
10714
10900
|
const message = [segment.text(`视频大小 (${file.totalBytes} MB) 触发压缩条件(设定值:${Config.app.compresstrigger} MB),正在进行压缩至${Config.app.compressvalue} MB...`), options?.message_id ? segment.reply(options.message_id) : segment.text("")];
|
|
10715
|
-
const msg1 = await karin
|
|
10901
|
+
const msg1 = await karin.sendMsg(selfId, contact, message);
|
|
10716
10902
|
const targetBitrate = Common.calculateBitrate(Config.app.compresstrigger, Duration) * .75;
|
|
10717
10903
|
const startTime = Date.now();
|
|
10718
10904
|
const outputPath = `${Common.tempDri.video}tmp_${Date.now()}.mp4`;
|
|
@@ -10726,7 +10912,7 @@ var uploadFile = async (event, file, videoUrl, options) => {
|
|
|
10726
10912
|
newFileSize = await Common.getVideoFileSize(file.filepath);
|
|
10727
10913
|
logger.debug(`原始视频大小为: ${file.totalBytes.toFixed(1)} MB, ${logger.green(`经 FFmpeg 压缩后最终视频大小为: ${newFileSize.toFixed(1)} MB,原视频文件已删除`)}`);
|
|
10728
10914
|
const message2 = [segment.text(`压缩后最终视频大小为: ${newFileSize.toFixed(1)} MB,压缩耗时:${((endTime - startTime) / 1e3).toFixed(1)} 秒`), segment.reply(msg1.messageId)];
|
|
10729
|
-
await karin
|
|
10915
|
+
await karin.sendMsg(selfId, contact, message2);
|
|
10730
10916
|
}
|
|
10731
10917
|
if (options) options.useGroupFile = Config.app.usegroupfile && newFileSize > Config.app.groupfilevalue;
|
|
10732
10918
|
if (Config.app.videoSendMode === "base64" && !options?.useGroupFile) {
|
|
@@ -10735,12 +10921,12 @@ var uploadFile = async (event, file, videoUrl, options) => {
|
|
|
10735
10921
|
} else File = options?.useGroupFile ? file.filepath : `file://${file.filepath}`;
|
|
10736
10922
|
try {
|
|
10737
10923
|
if (options?.active) if (options.useGroupFile) {
|
|
10738
|
-
const bot = karin
|
|
10924
|
+
const bot = karin.getBot(String(options.activeOption?.uin));
|
|
10739
10925
|
logger.mark(`${logger.blue("主动消息:")} 视频大小: ${newFileSize.toFixed(1)}MB 正在通过${logger.yellow("bot.uploadFile")}回复...`);
|
|
10740
10926
|
await bot.uploadFile(contact, File, file.originTitle ? `${file.originTitle}.mp4` : `${File.split("/").pop()}`);
|
|
10741
10927
|
} else {
|
|
10742
10928
|
logger.mark(`${logger.blue("主动消息:")} 视频大小: ${newFileSize.toFixed(1)}MB 正在通过${logger.yellow("karin.sendMsg")}回复...`);
|
|
10743
|
-
sendStatus = (await karin
|
|
10929
|
+
sendStatus = (await karin.sendMsg(selfId, contact, [segment.video(File)])).messageId ? true : false;
|
|
10744
10930
|
}
|
|
10745
10931
|
else if (options?.useGroupFile) {
|
|
10746
10932
|
logger.mark(`${logger.blue("被动消息:")} 视频大小: ${newFileSize.toFixed(1)}MB 正在通过${logger.yellow("e.bot.uploadFile")}回复...`);
|
|
@@ -10781,8 +10967,8 @@ var downloadVideo = async (event, downloadOpt, uploadOpt) => {
|
|
|
10781
10967
|
if (fileSizeContent > 0 && Config.app.usefilelimit && fileSize > Config.app.filelimit) {
|
|
10782
10968
|
const message = segment.text(`视频:「${downloadOpt.title.originTitle ?? "Error: 文件名获取失败"}」大小 (${fileSizeInMB} MB) 超出最大限制(设定值:${Config.app.filelimit} MB),已取消上传`);
|
|
10783
10969
|
const selfId = event.selfId || uploadOpt?.activeOption?.uin;
|
|
10784
|
-
const contact = event.contact || karin
|
|
10785
|
-
await karin
|
|
10970
|
+
const contact = event.contact || karin.contactGroup(uploadOpt?.activeOption?.group_id) || karin.contactFriend(selfId);
|
|
10971
|
+
await karin.sendMsg(selfId, contact, message);
|
|
10786
10972
|
return false;
|
|
10787
10973
|
}
|
|
10788
10974
|
let res = await downloadFile(downloadOpt.video_url, {
|
|
@@ -12330,6 +12516,7 @@ var ImageDownloader = class {
|
|
|
12330
12516
|
* @returns 处理后的图片路径(HTTP URL / file:// 协议 / base64://)
|
|
12331
12517
|
*/
|
|
12332
12518
|
async processImage(imageUrl, title, index) {
|
|
12519
|
+
if (!/^https?:\/\//i.test(imageUrl)) return imageUrl;
|
|
12333
12520
|
switch (Config.app.imageSendMode) {
|
|
12334
12521
|
case "base64": try {
|
|
12335
12522
|
return await this.downloadAndConvertToBase64(imageUrl);
|
|
@@ -12776,6 +12963,20 @@ function getImageDownloader() {
|
|
|
12776
12963
|
async function processImageUrl(imageUrl, title, index) {
|
|
12777
12964
|
return await getImageDownloader().processImage(imageUrl, title, index);
|
|
12778
12965
|
}
|
|
12966
|
+
/**
|
|
12967
|
+
* 处理本地生成的图片文件。
|
|
12968
|
+
*
|
|
12969
|
+
* imageSendMode 的 url 只适用于已有 HTTP 图片;本地合成图没有可直接发送的公网 URL,
|
|
12970
|
+
* 因此在 url 模式下回退到 base64,避免依赖 file 协议。
|
|
12971
|
+
*/
|
|
12972
|
+
function processLocalImageFile(filePath) {
|
|
12973
|
+
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
12974
|
+
if (Config.app.imageSendMode !== "file") {
|
|
12975
|
+
if (Config.app.imageSendMode === "url") logger.debug(`本地生成图片不支持 imageSendMode=url,已回退到 base64 发送: ${normalizedPath}`);
|
|
12976
|
+
return `base64://${fs.readFileSync(normalizedPath).toString("base64")}`;
|
|
12977
|
+
}
|
|
12978
|
+
return `file://${normalizedPath}`;
|
|
12979
|
+
}
|
|
12779
12980
|
//#endregion
|
|
12780
12981
|
//#region ../template/src/dev/preview/utils/time.ts
|
|
12781
12982
|
var import_react = /* @__PURE__ */ __toESM(require_react(), 1);
|
|
@@ -16943,8 +17144,9 @@ var BilibiliReserveCard = ({ reserve }) => {
|
|
|
16943
17144
|
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
16944
17145
|
className: "shrink-0",
|
|
16945
17146
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Button, {
|
|
16946
|
-
|
|
16947
|
-
|
|
17147
|
+
size: "lg",
|
|
17148
|
+
className: `font-normal scale-200 mr-15 rounded-xl ${reserve.buttonText === "已结束" ? "bg-surface-secondary/70 text-muted" : "bg-[#fb7299] text-white"}`,
|
|
17149
|
+
children: [reserve.buttonText !== "已结束" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BellRing, { size: 330 }), reserve.buttonText]
|
|
16948
17150
|
})
|
|
16949
17151
|
})]
|
|
16950
17152
|
})
|
|
@@ -23614,6 +23816,37 @@ var InlineCalloutCode = ({ children, className }) => /* @__PURE__ */ (0, import_
|
|
|
23614
23816
|
},
|
|
23615
23817
|
children
|
|
23616
23818
|
});
|
|
23819
|
+
var toSvgDataUri = (svg) => `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`;
|
|
23820
|
+
var techStackItems = [
|
|
23821
|
+
{
|
|
23822
|
+
label: "TypeScript",
|
|
23823
|
+
iconSrc: toSvgDataUri(typescript.svg)
|
|
23824
|
+
},
|
|
23825
|
+
{
|
|
23826
|
+
label: "SQLite",
|
|
23827
|
+
iconSrc: toSvgDataUri(sqlite.svg)
|
|
23828
|
+
},
|
|
23829
|
+
{
|
|
23830
|
+
label: "React",
|
|
23831
|
+
iconSrc: toSvgDataUri(react.svg)
|
|
23832
|
+
},
|
|
23833
|
+
{
|
|
23834
|
+
label: "Tailwind CSS",
|
|
23835
|
+
iconSrc: toSvgDataUri(tailwind_css.svg)
|
|
23836
|
+
},
|
|
23837
|
+
{
|
|
23838
|
+
label: "WebAssembly",
|
|
23839
|
+
iconSrc: toSvgDataUri(webassembly.svg)
|
|
23840
|
+
},
|
|
23841
|
+
{
|
|
23842
|
+
label: "Vite",
|
|
23843
|
+
iconSrc: toSvgDataUri(vite.svg)
|
|
23844
|
+
},
|
|
23845
|
+
{
|
|
23846
|
+
label: "tsdown",
|
|
23847
|
+
iconSrc: toSvgDataUri(tsdown.svg)
|
|
23848
|
+
}
|
|
23849
|
+
];
|
|
23617
23850
|
/**
|
|
23618
23851
|
* 更新日志组件
|
|
23619
23852
|
* @param props 组件属性
|
|
@@ -23621,6 +23854,7 @@ var InlineCalloutCode = ({ children, className }) => /* @__PURE__ */ (0, import_
|
|
|
23621
23854
|
*/
|
|
23622
23855
|
var Changelog = import_react.memo((props) => {
|
|
23623
23856
|
const isDark = props.data.useDarkTheme ?? false;
|
|
23857
|
+
const isUpdateTip = props.data.Tip === true;
|
|
23624
23858
|
const share_url = props.data?.share_url || "";
|
|
23625
23859
|
const backgroundColors = isDark ? {
|
|
23626
23860
|
base: "#0a0a0a",
|
|
@@ -23739,7 +23973,7 @@ var Changelog = import_react.memo((props) => {
|
|
|
23739
23973
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
23740
23974
|
className: "relative px-16 pt-5 pb-0 w-full max-w-none prose prose-lg prose-invert from-surface to-surface",
|
|
23741
23975
|
children: [
|
|
23742
|
-
|
|
23976
|
+
isUpdateTip ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
23743
23977
|
className: "pt-32",
|
|
23744
23978
|
children: [
|
|
23745
23979
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
@@ -23904,7 +24138,7 @@ var Changelog = import_react.memo((props) => {
|
|
|
23904
24138
|
a: ({ children, href, ...props }) => {
|
|
23905
24139
|
const isVersionLink = href?.includes("/compare/");
|
|
23906
24140
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", {
|
|
23907
|
-
className: `inline-flex gap-3 items-baseline cursor-pointer font-medium hover:underline ${isVersionLink ? "text-
|
|
24141
|
+
className: `inline-flex gap-3 items-baseline cursor-pointer font-medium hover:underline ${isVersionLink ? "text-foreground" : "text-foreground/50"}`,
|
|
23908
24142
|
onClick: (e) => e.preventDefault(),
|
|
23909
24143
|
...props,
|
|
23910
24144
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children })
|
|
@@ -23933,8 +24167,81 @@ var Changelog = import_react.memo((props) => {
|
|
|
23933
24167
|
children: props.data?.markdown ?? ""
|
|
23934
24168
|
})
|
|
23935
24169
|
}),
|
|
23936
|
-
share_url && /* @__PURE__ */ (0, import_jsx_runtime.
|
|
23937
|
-
className: "
|
|
24170
|
+
share_url && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: isUpdateTip ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
24171
|
+
className: "py-10",
|
|
24172
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
24173
|
+
className: "relative flex flex-col gap-8 overflow-hidden border-y border-muted/70 py-10",
|
|
24174
|
+
children: [
|
|
24175
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "absolute inset-x-0 top-0 h-px bg-linear-to-r from-transparent via-foreground/20 to-transparent" }),
|
|
24176
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "absolute inset-x-0 bottom-0 h-px bg-linear-to-r from-transparent via-foreground/20 to-transparent" }),
|
|
24177
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
24178
|
+
className: "relative flex items-stretch gap-12",
|
|
24179
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
24180
|
+
className: "relative w-[36%] shrink-0",
|
|
24181
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
24182
|
+
className: "inline-flex items-center gap-4 rounded-full border border-border/60 bg-surface/40 px-5 py-2 text-[1.75em] font-semibold text-foreground/60",
|
|
24183
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "h-3 w-3 rounded-full bg-foreground/50" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "DIFF SCAN" })]
|
|
24184
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
24185
|
+
className: "mt-4 w-100 rounded-3xl p-1",
|
|
24186
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
|
|
24187
|
+
src: generateQRCode(share_url, isDark),
|
|
24188
|
+
alt: "二维码",
|
|
24189
|
+
className: "w-full h-full rounded-2xl object-contain"
|
|
24190
|
+
})
|
|
24191
|
+
})]
|
|
24192
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
24193
|
+
className: "relative flex-1 py-2",
|
|
24194
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
24195
|
+
className: "flex items-end justify-between gap-8",
|
|
24196
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
24197
|
+
className: "text-[1.65em] font-semibold tracking-[0.22em] text-foreground/45",
|
|
24198
|
+
children: "PROJECT STACK"
|
|
24199
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
24200
|
+
className: "mt-2 text-[3.3em] font-black leading-none text-foreground/85",
|
|
24201
|
+
children: "技术栈"
|
|
24202
|
+
})] }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-16 w-px bg-border/80" })]
|
|
24203
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
24204
|
+
className: "mt-8 grid grid-cols-4 gap-4",
|
|
24205
|
+
children: techStackItems.map(({ iconSrc, label }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
24206
|
+
className: "flex min-h-40 flex-col items-center justify-center gap-3 rounded-2xl border border-border/60 bg-surface/45 px-4 py-5 backdrop-blur-xs",
|
|
24207
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(GlowImage, {
|
|
24208
|
+
glowStrength: isDark ? 1 : 0,
|
|
24209
|
+
blurRadius: 20,
|
|
24210
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
|
|
24211
|
+
"aria-hidden": true,
|
|
24212
|
+
src: iconSrc,
|
|
24213
|
+
alt: "",
|
|
24214
|
+
draggable: false,
|
|
24215
|
+
className: "h-16 w-16 object-contain drop-shadow-lg"
|
|
24216
|
+
})
|
|
24217
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
24218
|
+
className: "text-center text-[1.35em] font-bold leading-tight text-foreground/75",
|
|
24219
|
+
children: label
|
|
24220
|
+
})]
|
|
24221
|
+
}, label))
|
|
24222
|
+
})]
|
|
24223
|
+
})]
|
|
24224
|
+
}),
|
|
24225
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
24226
|
+
className: "text-4xl leading-relaxed text-foreground/60",
|
|
24227
|
+
children: [
|
|
24228
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "扫码查看实际运行代码从" }),
|
|
24229
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
24230
|
+
className: "font-bold text-foreground/80",
|
|
24231
|
+
children: [" v", props.data.localVersion]
|
|
24232
|
+
}),
|
|
24233
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: " 到 " }),
|
|
24234
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
24235
|
+
className: "font-bold text-foreground/80",
|
|
24236
|
+
children: [" v", props.data.remoteVersion]
|
|
24237
|
+
}),
|
|
24238
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: " 的差异" })
|
|
24239
|
+
]
|
|
24240
|
+
})
|
|
24241
|
+
]
|
|
24242
|
+
})
|
|
24243
|
+
}) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
24244
|
+
className: "flex flex-col gap-12 py-8",
|
|
23938
24245
|
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
23939
24246
|
className: "w-120 h-auto",
|
|
23940
24247
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
|
|
@@ -23958,8 +24265,8 @@ var Changelog = import_react.memo((props) => {
|
|
|
23958
24265
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: " 的差异" })
|
|
23959
24266
|
]
|
|
23960
24267
|
})]
|
|
23961
|
-
}),
|
|
23962
|
-
|
|
24268
|
+
}) }),
|
|
24269
|
+
isUpdateTip && props.data.buildTime && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
23963
24270
|
className: "flex gap-8 justify-center text-foreground/60",
|
|
23964
24271
|
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
23965
24272
|
className: "text-4xl",
|
|
@@ -32743,7 +33050,7 @@ var renderErrorImage = async (ctx, opts = {}) => {
|
|
|
32743
33050
|
* @returns
|
|
32744
33051
|
*/
|
|
32745
33052
|
var getCandidateBots = () => {
|
|
32746
|
-
return karin
|
|
33053
|
+
return karin.getAllBotList().map((item) => item.bot).filter((bot) => bot.account.name !== "console");
|
|
32747
33054
|
};
|
|
32748
33055
|
/**
|
|
32749
33056
|
* 获取非console主机器人ID列表
|
|
@@ -32791,7 +33098,7 @@ var getReachableMasterBots = async (masters = config.master()) => {
|
|
|
32791
33098
|
*/
|
|
32792
33099
|
var resolveUsableBot = async (selfId) => {
|
|
32793
33100
|
if (selfId) {
|
|
32794
|
-
const matchedBot = karin
|
|
33101
|
+
const matchedBot = karin.getBot(selfId);
|
|
32795
33102
|
if (matchedBot) return matchedBot;
|
|
32796
33103
|
}
|
|
32797
33104
|
const reachable = await getReachableMasterBots();
|
|
@@ -32799,12 +33106,12 @@ var resolveUsableBot = async (selfId) => {
|
|
|
32799
33106
|
const { douyin, bilibili } = statBotId$1(Config.pushlist);
|
|
32800
33107
|
const preferredBotId = douyin.botId || bilibili.botId;
|
|
32801
33108
|
if (preferredBotId) {
|
|
32802
|
-
const matchedBot = karin
|
|
33109
|
+
const matchedBot = karin.getBot(preferredBotId);
|
|
32803
33110
|
if (matchedBot) return matchedBot;
|
|
32804
33111
|
}
|
|
32805
|
-
const fallbackBotId = karin
|
|
33112
|
+
const fallbackBotId = karin.getAllBotID()[0];
|
|
32806
33113
|
if (!fallbackBotId) return void 0;
|
|
32807
|
-
return karin
|
|
33114
|
+
return karin.getBot(fallbackBotId);
|
|
32808
33115
|
};
|
|
32809
33116
|
//#endregion
|
|
32810
33117
|
//#region src/module/utils/ErrorHandler/utils.ts
|
|
@@ -32889,7 +33196,7 @@ var injectBotToEventForPushTask = async (event, businessName) => {
|
|
|
32889
33196
|
if (!isPushTask(event, businessName)) return event;
|
|
32890
33197
|
if (event?.bot) return event;
|
|
32891
33198
|
const preferredBotId = typeof event?.selfId === "string" ? event.selfId : getPushTaskBotId();
|
|
32892
|
-
const bot = (preferredBotId ? karin
|
|
33199
|
+
const bot = (preferredBotId ? karin.getBot(preferredBotId) : void 0) ?? await resolveUsableBot(preferredBotId);
|
|
32893
33200
|
if (!bot) throw new Error(`[ErrorHandler] push 任务缺少可用 bot 实例: ${businessName}`);
|
|
32894
33201
|
const normalizedEvent = event ?? {};
|
|
32895
33202
|
normalizedEvent.bot = bot;
|
|
@@ -32943,7 +33250,7 @@ var sendErrorToMaster = async (ctx, img, customPrefix) => {
|
|
|
32943
33250
|
if (!target) return;
|
|
32944
33251
|
try {
|
|
32945
33252
|
const prefix = customPrefix || await buildErrorPrefix(ctx, isPush, target.botId);
|
|
32946
|
-
await karin
|
|
33253
|
+
await karin.sendMaster(target.botId, target.master, [segment.text(prefix), ...img]);
|
|
32947
33254
|
} catch (err) {
|
|
32948
33255
|
logger.error(`[ErrorHandler] 发送错误消息给主人失败: ${err}`);
|
|
32949
33256
|
}
|
|
@@ -32978,7 +33285,7 @@ var sendErrorToAllMasters = async (ctx, img, customPrefix) => {
|
|
|
32978
33285
|
const key = `${target.botId}:${target.master}`;
|
|
32979
33286
|
if (notifiedSet.has(key)) continue;
|
|
32980
33287
|
try {
|
|
32981
|
-
await karin
|
|
33288
|
+
await karin.sendMaster(target.botId, target.master, [segment.text(prefix), ...img]);
|
|
32982
33289
|
notifiedSet.add(key);
|
|
32983
33290
|
logger.debug(`[ErrorHandler] 已发送错误消息给主人: ${target.master} (via ${target.botId})`);
|
|
32984
33291
|
} catch (err) {
|
|
@@ -33029,7 +33336,7 @@ var buildErrorPrefix = async (ctx, isPush, botId) => {
|
|
|
33029
33336
|
const { options, event } = ctx;
|
|
33030
33337
|
if (isPush) return `${options.businessName} 任务执行出错\n请尽快解决以消除警告`;
|
|
33031
33338
|
const groupId = event && "groupId" in event ? event.groupId : "";
|
|
33032
|
-
return `群:${(await karin
|
|
33339
|
+
return `群:${(await karin.getBot(botId)?.getGroupInfo(groupId))?.groupName || "未知"}(${groupId})\n${options.businessName} 任务执行出错\n请尽快解决以消除警告`;
|
|
33033
33340
|
};
|
|
33034
33341
|
//#endregion
|
|
33035
33342
|
//#region src/module/utils/ErrorHandler/handler.ts
|
|
@@ -33995,6 +34302,139 @@ var buildBilibiliArticleRichText = (opus, content, useDarkTheme) => {
|
|
|
33995
34302
|
if (content) return parseHtmlContentToRichText(content);
|
|
33996
34303
|
return createRichTextDocument([], { platform: "bilibili" });
|
|
33997
34304
|
};
|
|
34305
|
+
var MAX_FORWARD_TEXT_LENGTH = 1800;
|
|
34306
|
+
var normalizeForwardText = (text) => {
|
|
34307
|
+
return text.replace(/\r\n/g, "\n").replace(/[ \t]+\n/g, "\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
34308
|
+
};
|
|
34309
|
+
var splitForwardText = (text) => {
|
|
34310
|
+
const chunks = [];
|
|
34311
|
+
let rest = text;
|
|
34312
|
+
while (rest.length > MAX_FORWARD_TEXT_LENGTH) {
|
|
34313
|
+
let splitAt = rest.lastIndexOf("\n\n", MAX_FORWARD_TEXT_LENGTH);
|
|
34314
|
+
if (splitAt < MAX_FORWARD_TEXT_LENGTH / 2) splitAt = rest.lastIndexOf("\n", MAX_FORWARD_TEXT_LENGTH);
|
|
34315
|
+
if (splitAt < MAX_FORWARD_TEXT_LENGTH / 2) splitAt = MAX_FORWARD_TEXT_LENGTH;
|
|
34316
|
+
const chunk = rest.slice(0, splitAt).trim();
|
|
34317
|
+
if (chunk) chunks.push(chunk);
|
|
34318
|
+
rest = rest.slice(splitAt).trim();
|
|
34319
|
+
}
|
|
34320
|
+
if (rest) chunks.push(rest);
|
|
34321
|
+
return chunks;
|
|
34322
|
+
};
|
|
34323
|
+
var formatRichTextLink = (text, url) => {
|
|
34324
|
+
if (!url || url === text) return text;
|
|
34325
|
+
return `${text} (${url})`;
|
|
34326
|
+
};
|
|
34327
|
+
var inlineRichTextNodeToText = (node) => {
|
|
34328
|
+
switch (node.type) {
|
|
34329
|
+
case "text":
|
|
34330
|
+
case "mention":
|
|
34331
|
+
case "searchKeyword":
|
|
34332
|
+
case "topic":
|
|
34333
|
+
case "at":
|
|
34334
|
+
case "lottery":
|
|
34335
|
+
case "vote":
|
|
34336
|
+
case "viewPicture":
|
|
34337
|
+
case "hashtag": return node.text;
|
|
34338
|
+
case "emoji": return node.name;
|
|
34339
|
+
case "webLink": return formatRichTextLink(node.text, node.jumpUrl);
|
|
34340
|
+
case "lineBreak": return "\n";
|
|
34341
|
+
default: return "";
|
|
34342
|
+
}
|
|
34343
|
+
};
|
|
34344
|
+
/**
|
|
34345
|
+
* 将共享富文本文档转换为 Karin 消息段。
|
|
34346
|
+
*
|
|
34347
|
+
* 这里用于专栏正文的合并转发:文本节点保留为 text,图片节点保留为 image,
|
|
34348
|
+
* 让用户在客户端里能按原文顺序查看图文内容,而不是只能看渲染长图。
|
|
34349
|
+
*/
|
|
34350
|
+
var buildBilibiliRichTextForwardMessage = async (document, options = {}) => {
|
|
34351
|
+
const elements = [];
|
|
34352
|
+
let textBuffer = "";
|
|
34353
|
+
let imageIndex = 0;
|
|
34354
|
+
const appendText = (text) => {
|
|
34355
|
+
if (!text) return;
|
|
34356
|
+
textBuffer += text;
|
|
34357
|
+
};
|
|
34358
|
+
const ensureBlockBreak = () => {
|
|
34359
|
+
if (!textBuffer) return;
|
|
34360
|
+
if (textBuffer.endsWith("\n\n")) return;
|
|
34361
|
+
textBuffer += textBuffer.endsWith("\n") ? "\n" : "\n\n";
|
|
34362
|
+
};
|
|
34363
|
+
const flushText = () => {
|
|
34364
|
+
const text = normalizeForwardText(textBuffer);
|
|
34365
|
+
textBuffer = "";
|
|
34366
|
+
for (const chunk of splitForwardText(text)) elements.push(segment.text(chunk));
|
|
34367
|
+
};
|
|
34368
|
+
const appendChildren = async (nodes) => {
|
|
34369
|
+
for (const node of nodes) await appendNode(node);
|
|
34370
|
+
};
|
|
34371
|
+
const appendImage = async (src, caption) => {
|
|
34372
|
+
flushText();
|
|
34373
|
+
const imageUrl = options.imageResolver ? await options.imageResolver(src, imageIndex) : src;
|
|
34374
|
+
imageIndex += 1;
|
|
34375
|
+
elements.push(segment.image(imageUrl));
|
|
34376
|
+
if (caption) {
|
|
34377
|
+
appendText(caption);
|
|
34378
|
+
ensureBlockBreak();
|
|
34379
|
+
}
|
|
34380
|
+
};
|
|
34381
|
+
const appendNode = async (node) => {
|
|
34382
|
+
const inlineText = inlineRichTextNodeToText(node);
|
|
34383
|
+
if (inlineText) {
|
|
34384
|
+
appendText(inlineText);
|
|
34385
|
+
return;
|
|
34386
|
+
}
|
|
34387
|
+
switch (node.type) {
|
|
34388
|
+
case "heading":
|
|
34389
|
+
case "paragraph":
|
|
34390
|
+
case "blockquote":
|
|
34391
|
+
case "listItem":
|
|
34392
|
+
ensureBlockBreak();
|
|
34393
|
+
await appendChildren(node.nodes);
|
|
34394
|
+
ensureBlockBreak();
|
|
34395
|
+
break;
|
|
34396
|
+
case "image":
|
|
34397
|
+
if (node.src) await appendImage(node.src, node.caption);
|
|
34398
|
+
break;
|
|
34399
|
+
case "list":
|
|
34400
|
+
ensureBlockBreak();
|
|
34401
|
+
for (const [index, item] of node.items.entries()) {
|
|
34402
|
+
appendText(node.ordered ? `${index + 1}. ` : "- ");
|
|
34403
|
+
await appendChildren(item.nodes);
|
|
34404
|
+
appendText("\n");
|
|
34405
|
+
}
|
|
34406
|
+
ensureBlockBreak();
|
|
34407
|
+
break;
|
|
34408
|
+
case "codeBlock":
|
|
34409
|
+
ensureBlockBreak();
|
|
34410
|
+
appendText(node.content);
|
|
34411
|
+
ensureBlockBreak();
|
|
34412
|
+
break;
|
|
34413
|
+
case "linkCard":
|
|
34414
|
+
ensureBlockBreak();
|
|
34415
|
+
appendText(formatRichTextLink(node.title, node.url));
|
|
34416
|
+
ensureBlockBreak();
|
|
34417
|
+
break;
|
|
34418
|
+
case "horizontalRule":
|
|
34419
|
+
ensureBlockBreak();
|
|
34420
|
+
appendText("---");
|
|
34421
|
+
ensureBlockBreak();
|
|
34422
|
+
break;
|
|
34423
|
+
default: break;
|
|
34424
|
+
}
|
|
34425
|
+
};
|
|
34426
|
+
const headerLines = [];
|
|
34427
|
+
if (options.title) headerLines.push(`标题:${options.title}`);
|
|
34428
|
+
if (options.summary) headerLines.push(`简介:${options.summary}`);
|
|
34429
|
+
if (options.shareUrl) headerLines.push(`链接:${options.shareUrl}`);
|
|
34430
|
+
if (headerLines.length > 0) {
|
|
34431
|
+
appendText(headerLines.join("\n"));
|
|
34432
|
+
ensureBlockBreak();
|
|
34433
|
+
}
|
|
34434
|
+
await appendChildren(document.nodes);
|
|
34435
|
+
flushText();
|
|
34436
|
+
return elements;
|
|
34437
|
+
};
|
|
33998
34438
|
//#endregion
|
|
33999
34439
|
//#region src/platform/bilibili/bilibili.ts
|
|
34000
34440
|
var img$1;
|
|
@@ -34210,7 +34650,7 @@ var Bilibili = class extends Base {
|
|
|
34210
34650
|
length: videoInfo.data.result.episodes.length
|
|
34211
34651
|
});
|
|
34212
34652
|
this.e.reply([...img$1, segment.text("请在120秒内输入 第?集 选择集数")]);
|
|
34213
|
-
const context = await karin
|
|
34653
|
+
const context = await karin.ctx(this.e, {
|
|
34214
34654
|
reply: true,
|
|
34215
34655
|
throwOnTimeout: false
|
|
34216
34656
|
});
|
|
@@ -34337,7 +34777,7 @@ var Bilibili = class extends Base {
|
|
|
34337
34777
|
filepath: motionPhotoCoverPath,
|
|
34338
34778
|
totalBytes: 0
|
|
34339
34779
|
});
|
|
34340
|
-
const motionPhotoCover =
|
|
34780
|
+
const motionPhotoCover = processLocalImageFile(motionPhotoCoverPath);
|
|
34341
34781
|
imgArray.push(segment.image(motionPhotoCover));
|
|
34342
34782
|
hasPushedMotionPhotoCover = true;
|
|
34343
34783
|
}
|
|
@@ -34697,28 +35137,19 @@ var Bilibili = class extends Base {
|
|
|
34697
35137
|
const articleData = articleInfoBase.data.data;
|
|
34698
35138
|
const articleContent = articleInfo.data.data;
|
|
34699
35139
|
const body = buildBilibiliArticleRichText(articleContent.opus, articleContent.content, Common.useDarkTheme());
|
|
34700
|
-
const extractImagesFromBody = (nodes) => {
|
|
34701
|
-
const images = [];
|
|
34702
|
-
for (const node of nodes) {
|
|
34703
|
-
if (node.type === "image" && node.src) images.push(node.src);
|
|
34704
|
-
if (node.nodes) images.push(...extractImagesFromBody(node.nodes));
|
|
34705
|
-
if (node.items) images.push(...extractImagesFromBody(node.items));
|
|
34706
|
-
}
|
|
34707
|
-
return images;
|
|
34708
|
-
};
|
|
34709
|
-
const messageElements = [];
|
|
34710
|
-
const articleImages = extractImagesFromBody(body.nodes);
|
|
34711
35140
|
const title = articleData.title || "bilibili_article";
|
|
34712
|
-
|
|
34713
|
-
|
|
34714
|
-
|
|
34715
|
-
|
|
34716
|
-
|
|
34717
|
-
|
|
35141
|
+
const shareUrl = articleContent.dyn_id_str ? `https://www.bilibili.com/opus/${articleContent.dyn_id_str}` : `https://www.bilibili.com/read/cv${articleContent.id}`;
|
|
35142
|
+
const messageElements = await buildBilibiliRichTextForwardMessage(body, {
|
|
35143
|
+
title: articleData.title,
|
|
35144
|
+
summary: articleData.summary,
|
|
35145
|
+
shareUrl,
|
|
35146
|
+
imageResolver: (src, index) => processImageUrl(src, title, index)
|
|
35147
|
+
});
|
|
35148
|
+
if (messageElements.length > 0) {
|
|
34718
35149
|
const forwardMsg = common.makeForward(messageElements, Config.app.fakeForward ? this.e.sender.userId : this.e.bot.account.selfId, Config.app.fakeForward ? this.e.sender.nick : this.e.bot.account.name);
|
|
34719
35150
|
await this.e.bot.sendForwardMsg(this.e.contact, forwardMsg, {
|
|
34720
|
-
source: "
|
|
34721
|
-
summary: `查看${messageElements.length}
|
|
35151
|
+
source: "专栏内容",
|
|
35152
|
+
summary: `查看${messageElements.length}条专栏内容`,
|
|
34722
35153
|
prompt: "B站专栏动态解析结果",
|
|
34723
35154
|
news: [{ text: "点击查看解析结果" }]
|
|
34724
35155
|
});
|
|
@@ -34736,7 +35167,7 @@ var Bilibili = class extends Base {
|
|
|
34736
35167
|
body,
|
|
34737
35168
|
stats: articleData.stats,
|
|
34738
35169
|
render_time: TimeFormatter.now(),
|
|
34739
|
-
share_url:
|
|
35170
|
+
share_url: shareUrl,
|
|
34740
35171
|
dynamicTYPE: "专栏动态解析",
|
|
34741
35172
|
user_shortid: userProfileData.data.data.card.mid,
|
|
34742
35173
|
total_favorited: Count(userProfileData.data.data.like_num),
|
|
@@ -34937,9 +35368,9 @@ var Bilibili = class extends Base {
|
|
|
34937
35368
|
}
|
|
34938
35369
|
case false:
|
|
34939
35370
|
/** 没登录(没配置ck)情况下直接发直链,传直链在DownLoadVideo()处理 */
|
|
34940
|
-
logger.debug("视频 URL:", playUrlData.durl[0].url);
|
|
35371
|
+
logger.debug("视频 URL:", playUrlData.data.durl[0].url);
|
|
34941
35372
|
if ((this.forceBurnDanmaku || Config.bilibili.burnDanmaku) && danmakuList.length > 0) {
|
|
34942
|
-
const videoFile = await downloadFile(playUrlData.durl[0].url, {
|
|
35373
|
+
const videoFile = await downloadFile(playUrlData.data.durl[0].url, {
|
|
34943
35374
|
title: `Bil_V_tmp_${Date.now()}.mp4`,
|
|
34944
35375
|
headers: this.headers
|
|
34945
35376
|
});
|
|
@@ -34971,7 +35402,7 @@ var Bilibili = class extends Base {
|
|
|
34971
35402
|
} else await Common.removeFile(videoFile.filepath, true);
|
|
34972
35403
|
}
|
|
34973
35404
|
} else await downloadVideo(this.e, {
|
|
34974
|
-
video_url: playUrlData.durl[0].url,
|
|
35405
|
+
video_url: playUrlData.data.durl[0].url,
|
|
34975
35406
|
title: {
|
|
34976
35407
|
timestampTitle: `tmp_${Date.now()}.mp4`,
|
|
34977
35408
|
originTitle: `${this.downloadfilename}.mp4`
|
|
@@ -35303,32 +35734,6 @@ var getStringDisplayWidth$1 = (str) => {
|
|
|
35303
35734
|
}
|
|
35304
35735
|
return width;
|
|
35305
35736
|
};
|
|
35306
|
-
/**
|
|
35307
|
-
* 提取专栏中的所有图片URL
|
|
35308
|
-
* @param content
|
|
35309
|
-
* @returns
|
|
35310
|
-
*/
|
|
35311
|
-
var extractArticleImages = (content) => {
|
|
35312
|
-
const images = [];
|
|
35313
|
-
if (content.opus?.content?.paragraphs) {
|
|
35314
|
-
for (const paragraph of content.opus.content.paragraphs) if (paragraph.para_type === 2 && paragraph.pic?.pics) {
|
|
35315
|
-
for (const pic of paragraph.pic.pics) if (pic.url) {
|
|
35316
|
-
const url = pic.url.startsWith("//") ? `https:${pic.url}` : pic.url;
|
|
35317
|
-
images.push(url);
|
|
35318
|
-
}
|
|
35319
|
-
}
|
|
35320
|
-
}
|
|
35321
|
-
if (content.content && typeof content.content === "string") {
|
|
35322
|
-
const imgRegex = /<img[^>]+src="([^"]+)"/gi;
|
|
35323
|
-
let match;
|
|
35324
|
-
while ((match = imgRegex.exec(content.content)) !== null) {
|
|
35325
|
-
let url = match[1];
|
|
35326
|
-
if (url.startsWith("//")) url = `https:${url}`;
|
|
35327
|
-
images.push(url);
|
|
35328
|
-
}
|
|
35329
|
-
}
|
|
35330
|
-
return images;
|
|
35331
|
-
};
|
|
35332
35737
|
//#endregion
|
|
35333
35738
|
//#region src/platform/bilibili/comments.ts
|
|
35334
35739
|
/**
|
|
@@ -35853,7 +36258,7 @@ var Bilibilipush = class extends Base {
|
|
|
35853
36258
|
injectBotToEventForRender(targets) {
|
|
35854
36259
|
const targetBotId = targets.find((item) => item.botId)?.botId;
|
|
35855
36260
|
if (!targetBotId) return;
|
|
35856
|
-
const bot = karin
|
|
36261
|
+
const bot = karin.getBot(targetBotId);
|
|
35857
36262
|
if (!bot) return;
|
|
35858
36263
|
const eventWithBot = this.e;
|
|
35859
36264
|
eventWithBot.bot = bot;
|
|
@@ -35890,7 +36295,7 @@ var Bilibilipush = class extends Base {
|
|
|
35890
36295
|
this.ensureConfigFields(Config.pushlist.bilibili);
|
|
35891
36296
|
const deletedCount = await cleanOldDynamicCache("bilibili");
|
|
35892
36297
|
if (deletedCount > 0) logger.info(`已清理 ${deletedCount} 条过期的B站动态缓存记录`);
|
|
35893
|
-
const registeredBotIds = karin
|
|
36298
|
+
const registeredBotIds = karin.getAllBotID();
|
|
35894
36299
|
const filteredPushList = this.filterPushListByRegisteredBots(Config.pushlist.bilibili, registeredBotIds);
|
|
35895
36300
|
if (filteredPushList.length === 0) {
|
|
35896
36301
|
logger.warn("没有已注册的 bot 可用于B站推送");
|
|
@@ -35949,6 +36354,7 @@ var Bilibilipush = class extends Base {
|
|
|
35949
36354
|
if (skip) logger.warn(`动态 https://t.bilibili.com/${dynamicId} 已被处理,跳过`);
|
|
35950
36355
|
let send_video = true;
|
|
35951
36356
|
let img = [];
|
|
36357
|
+
let articleForwardPayload = null;
|
|
35952
36358
|
this.injectBotToEventForRender(data[dynamicId].targets);
|
|
35953
36359
|
if (!skip) {
|
|
35954
36360
|
const userINFO = await this.amagi.bilibili.fetcher.fetchUserCard({
|
|
@@ -36277,6 +36683,14 @@ var Bilibilipush = class extends Base {
|
|
|
36277
36683
|
});
|
|
36278
36684
|
const articleData = articleInfoBase.data.data;
|
|
36279
36685
|
const articleContent = articleInfo.data.data;
|
|
36686
|
+
const body = buildBilibiliArticleRichText(articleContent.opus, articleContent.content, Common.useDarkTheme());
|
|
36687
|
+
const shareUrl = articleContent.dyn_id_str ? `https://www.bilibili.com/opus/${articleContent.dyn_id_str}` : `https://www.bilibili.com/read/cv${articleContent.id}`;
|
|
36688
|
+
articleForwardPayload = {
|
|
36689
|
+
body,
|
|
36690
|
+
title: articleData.title,
|
|
36691
|
+
summary: articleData.summary,
|
|
36692
|
+
shareUrl
|
|
36693
|
+
};
|
|
36280
36694
|
img = await Render(this.e, "bilibili/dynamic/DYNAMIC_TYPE_ARTICLE", {
|
|
36281
36695
|
usernameMeta: getUsernameMetadata(data[dynamicId].Dynamic_Data.modules.module_author),
|
|
36282
36696
|
avatar_url: data[dynamicId].Dynamic_Data.modules.module_author.face,
|
|
@@ -36291,10 +36705,10 @@ var Bilibilipush = class extends Base {
|
|
|
36291
36705
|
banner_url: articleData.banner_url || articleData.image_urls && articleData.image_urls[0] || "",
|
|
36292
36706
|
categories: articleData.categories || [],
|
|
36293
36707
|
words: articleData.words || 0,
|
|
36294
|
-
body
|
|
36708
|
+
body,
|
|
36295
36709
|
stats: articleData.stats,
|
|
36296
36710
|
render_time: TimeFormatter.now(),
|
|
36297
|
-
share_url:
|
|
36711
|
+
share_url: shareUrl,
|
|
36298
36712
|
dynamicTYPE: "专栏动态推送"
|
|
36299
36713
|
}, { skipWatermark: true });
|
|
36300
36714
|
break;
|
|
@@ -36312,13 +36726,23 @@ var Bilibilipush = class extends Base {
|
|
|
36312
36726
|
let status = null;
|
|
36313
36727
|
if (!skip) {
|
|
36314
36728
|
const { groupId, botId } = target;
|
|
36315
|
-
const bot = karin
|
|
36316
|
-
const Contact = karin
|
|
36729
|
+
const bot = karin.getBot(botId);
|
|
36730
|
+
const Contact = karin.contactGroup(groupId);
|
|
36317
36731
|
const eventWithBot = this.e;
|
|
36318
36732
|
eventWithBot.bot = bot;
|
|
36319
36733
|
eventWithBot.selfId = botId;
|
|
36320
36734
|
const watermarkedImg = img ? applyWatermarkToImages(img, this.e) : [];
|
|
36321
|
-
|
|
36735
|
+
const parseUrl = buildParseUrl(data[dynamicId]);
|
|
36736
|
+
const parseButton = bot?.adapter?.name === "QQ Official Bot" && parseUrl ? [segment.button([{
|
|
36737
|
+
text: "解析",
|
|
36738
|
+
callback: true,
|
|
36739
|
+
data: `#解析${parseUrl}`
|
|
36740
|
+
}, {
|
|
36741
|
+
text: "帮助",
|
|
36742
|
+
callback: true,
|
|
36743
|
+
data: `#kkk帮助`
|
|
36744
|
+
}])] : [];
|
|
36745
|
+
status = await karin.sendMsg(botId, Contact, [...watermarkedImg, ...parseButton]);
|
|
36322
36746
|
if (Config.bilibili.push.parsedynamic && status.messageId) switch (data[dynamicId].dynamic_type) {
|
|
36323
36747
|
case "DYNAMIC_TYPE_AV":
|
|
36324
36748
|
if (send_video) {
|
|
@@ -36353,7 +36777,7 @@ var Bilibilipush = class extends Base {
|
|
|
36353
36777
|
/** 获取第一个视频流的大小 */
|
|
36354
36778
|
videoSize = await getvideosize(correctList.videoList[0].base_url, playUrlData.data.data.dash.audio[0].base_url, data[dynamicId].Dynamic_Data.modules.module_dynamic.major.archive.bvid);
|
|
36355
36779
|
if (Config.app.usefilelimit && Number(videoSize) > Number(Config.app.filelimit) && !Config.app.compress) {
|
|
36356
|
-
await karin
|
|
36780
|
+
await karin.sendMsg(botId, Contact, [segment.text(`设定的最大上传大小为 ${Config.app.filelimit}MB\n当前解析到的视频大小为 ${Number(videoSize)}MB\n视频太大了,还是去B站看吧~`), segment.reply(status.messageId)]);
|
|
36357
36781
|
break;
|
|
36358
36782
|
}
|
|
36359
36783
|
logger.mark(`当前处于自动推送状态,解析到的视频大小为 ${logger.yellow(Number(videoSize))} MB`);
|
|
@@ -36476,7 +36900,7 @@ var Bilibilipush = class extends Base {
|
|
|
36476
36900
|
filepath: motionPhotoCoverPath,
|
|
36477
36901
|
totalBytes: 0
|
|
36478
36902
|
});
|
|
36479
|
-
const motionPhotoCover =
|
|
36903
|
+
const motionPhotoCover = processLocalImageFile(motionPhotoCoverPath);
|
|
36480
36904
|
imgArray.push(segment.image(motionPhotoCover));
|
|
36481
36905
|
hasPushedMotionPhotoCover = true;
|
|
36482
36906
|
}
|
|
@@ -36517,23 +36941,35 @@ var Bilibilipush = class extends Base {
|
|
|
36517
36941
|
break;
|
|
36518
36942
|
}
|
|
36519
36943
|
case "DYNAMIC_TYPE_ARTICLE": {
|
|
36520
|
-
|
|
36521
|
-
|
|
36522
|
-
|
|
36523
|
-
|
|
36524
|
-
|
|
36525
|
-
|
|
36526
|
-
|
|
36527
|
-
|
|
36528
|
-
|
|
36529
|
-
|
|
36944
|
+
let payload = articleForwardPayload;
|
|
36945
|
+
if (!payload) {
|
|
36946
|
+
const articleInfoBase = await this.amagi.bilibili.fetcher.fetchArticleInfo({
|
|
36947
|
+
id: data[dynamicId].Dynamic_Data.basic.rid_str,
|
|
36948
|
+
typeMode: "strict"
|
|
36949
|
+
});
|
|
36950
|
+
const articleContent = (await this.amagi.bilibili.fetcher.fetchArticleContent({
|
|
36951
|
+
id: data[dynamicId].Dynamic_Data.basic.rid_str,
|
|
36952
|
+
typeMode: "strict"
|
|
36953
|
+
})).data.data;
|
|
36954
|
+
payload = {
|
|
36955
|
+
body: buildBilibiliArticleRichText(articleContent.opus, articleContent.content, Common.useDarkTheme()),
|
|
36956
|
+
title: articleInfoBase.data.data.title,
|
|
36957
|
+
summary: articleInfoBase.data.data.summary,
|
|
36958
|
+
shareUrl: articleContent.dyn_id_str ? `https://www.bilibili.com/opus/${articleContent.dyn_id_str}` : `https://www.bilibili.com/read/cv${articleContent.id}`
|
|
36959
|
+
};
|
|
36530
36960
|
}
|
|
36531
|
-
|
|
36532
|
-
|
|
36961
|
+
const title = payload.title || "bilibili_article";
|
|
36962
|
+
const messageElements = await buildBilibiliRichTextForwardMessage(payload.body, {
|
|
36963
|
+
title: payload.title,
|
|
36964
|
+
summary: payload.summary,
|
|
36965
|
+
shareUrl: payload.shareUrl,
|
|
36966
|
+
imageResolver: (src, index) => processImageUrl(src, title, index)
|
|
36967
|
+
});
|
|
36968
|
+
if (messageElements.length > 0) {
|
|
36533
36969
|
const forwardMsg = common.makeForward(messageElements, botId, bot.account.name);
|
|
36534
36970
|
await bot.sendForwardMsg(Contact, forwardMsg, {
|
|
36535
|
-
source: "
|
|
36536
|
-
summary: `查看${messageElements.length}
|
|
36971
|
+
source: "专栏内容",
|
|
36972
|
+
summary: `查看${messageElements.length}条专栏内容`,
|
|
36537
36973
|
prompt: "B站专栏动态解析结果",
|
|
36538
36974
|
news: [{ text: "点击查看解析结果" }]
|
|
36539
36975
|
});
|
|
@@ -36664,6 +37100,7 @@ var Bilibilipush = class extends Base {
|
|
|
36664
37100
|
} else {
|
|
36665
37101
|
await bilibiliDBInstance.subscribeBilibiliUser(groupId, botId, host_mid, data.data.card.name);
|
|
36666
37102
|
existingItem.group_id.push(`${groupId}:${botId}`);
|
|
37103
|
+
if (!existingItem.pushTypes || existingItem.pushTypes.length === 0) existingItem.pushTypes = [...allBilibiliPushTypes];
|
|
36667
37104
|
Config.Modify("pushlist", "bilibili", config.bilibili);
|
|
36668
37105
|
await this.e.reply(`群:${groupInfo.groupName}(${groupId})\n添加成功!${data.data.card.name}\nUID:${host_mid}`);
|
|
36669
37106
|
if (Config.bilibili.push.switch === false) await this.e.reply("请发送「#设置B站推送开启」以进行推送");
|
|
@@ -36675,7 +37112,8 @@ var Bilibilipush = class extends Base {
|
|
|
36675
37112
|
switch: true,
|
|
36676
37113
|
host_mid,
|
|
36677
37114
|
group_id: [`${groupId}:${botId}`],
|
|
36678
|
-
remark: data.data.card.name
|
|
37115
|
+
remark: data.data.card.name,
|
|
37116
|
+
pushTypes: [...allBilibiliPushTypes]
|
|
36679
37117
|
});
|
|
36680
37118
|
Config.Modify("pushlist", "bilibili", config.bilibili);
|
|
36681
37119
|
await this.e.reply(`群:${groupInfo.groupName}(${groupId})\n添加成功!${data.data.card.name}\nUID:${host_mid}`);
|
|
@@ -36785,6 +37223,22 @@ var br = (data) => {
|
|
|
36785
37223
|
return data = data.replace(/\n/g, "<br>");
|
|
36786
37224
|
};
|
|
36787
37225
|
/**
|
|
37226
|
+
* 根据动态类型构造用于「解析」按钮的地址。
|
|
37227
|
+
* 视频动态使用 BV 视频地址,其余动态使用动态地址;直播动态返回空字符串(不追加按钮)。
|
|
37228
|
+
* @param PushItem 推送项
|
|
37229
|
+
* @returns 解析地址,无法解析时返回空字符串
|
|
37230
|
+
*/
|
|
37231
|
+
var buildParseUrl = (PushItem) => {
|
|
37232
|
+
switch (PushItem.dynamic_type) {
|
|
37233
|
+
case DynamicType.AV: {
|
|
37234
|
+
const bvid = PushItem.Dynamic_Data.modules.module_dynamic.major?.archive?.bvid;
|
|
37235
|
+
return bvid ? `https://www.bilibili.com/video/${bvid}` : "";
|
|
37236
|
+
}
|
|
37237
|
+
case DynamicType.LIVE_RCMD: return "";
|
|
37238
|
+
default: return `https://t.bilibili.com/${PushItem.Dynamic_Data.id_str}`;
|
|
37239
|
+
}
|
|
37240
|
+
};
|
|
37241
|
+
/**
|
|
36788
37242
|
* 判断标题是否有屏蔽词或屏蔽标签
|
|
36789
37243
|
* @param PushItem 推送项
|
|
36790
37244
|
* @returns 是否应该跳过推送
|
|
@@ -36841,7 +37295,7 @@ registerErrorStrategy({
|
|
|
36841
37295
|
await event.reply([segment.text("检测到B站风控,请在「120 秒内」扫描二维码完成验证后发送验证结果\n"), ...img]);
|
|
36842
37296
|
await sendErrorToMaster(ctx, img);
|
|
36843
37297
|
await sendErrorToAllMasters(ctx, img);
|
|
36844
|
-
const resultCtx = await karin
|
|
37298
|
+
const resultCtx = await karin.ctx(event);
|
|
36845
37299
|
if (!resultCtx) return "continue";
|
|
36846
37300
|
const params = new URLSearchParams(resultCtx.msg);
|
|
36847
37301
|
const validate = params.get("validate");
|
|
@@ -37664,7 +38118,7 @@ var DouYin = class DouYin extends Base {
|
|
|
37664
38118
|
filepath: motionPhotoCoverPath,
|
|
37665
38119
|
totalBytes: 0
|
|
37666
38120
|
});
|
|
37667
|
-
const motionPhotoCover =
|
|
38121
|
+
const motionPhotoCover = processLocalImageFile(motionPhotoCoverPath);
|
|
37668
38122
|
processedImages.push(segment.image(motionPhotoCover));
|
|
37669
38123
|
hasPushedMotionPhotoCover = true;
|
|
37670
38124
|
}
|
|
@@ -37819,7 +38273,7 @@ var DouYin = class DouYin extends Base {
|
|
|
37819
38273
|
filepath: motionPhotoCoverPath,
|
|
37820
38274
|
totalBytes: 0
|
|
37821
38275
|
});
|
|
37822
|
-
const motionPhotoCover =
|
|
38276
|
+
const motionPhotoCover = processLocalImageFile(motionPhotoCoverPath);
|
|
37823
38277
|
images.push(segment.image(motionPhotoCover));
|
|
37824
38278
|
hasPushedMotionPhotoCover = true;
|
|
37825
38279
|
}
|
|
@@ -38135,7 +38589,7 @@ var DouYin = class DouYin extends Base {
|
|
|
38135
38589
|
});
|
|
38136
38590
|
await this.e.reply(img);
|
|
38137
38591
|
logger.debug(`等待用户选择视频,开始计时,${timeoutSeconds}秒后终止等待...`);
|
|
38138
|
-
const context = await karin
|
|
38592
|
+
const context = await karin.ctx(this.e, {
|
|
38139
38593
|
throwOnTimeout: false,
|
|
38140
38594
|
time: timeoutSeconds
|
|
38141
38595
|
});
|
|
@@ -39319,7 +39773,7 @@ var DouYinpush = class extends Base {
|
|
|
39319
39773
|
injectBotToEventForRender(targets) {
|
|
39320
39774
|
const targetBotId = targets.find((item) => item.botId)?.botId;
|
|
39321
39775
|
if (!targetBotId) return;
|
|
39322
|
-
const bot = karin
|
|
39776
|
+
const bot = karin.getBot(targetBotId);
|
|
39323
39777
|
if (!bot) return;
|
|
39324
39778
|
const eventWithBot = this.e;
|
|
39325
39779
|
eventWithBot.bot = bot;
|
|
@@ -39334,7 +39788,7 @@ var DouYinpush = class extends Base {
|
|
|
39334
39788
|
if (deletedCount > 0) logger.info(`已清理 ${deletedCount} 条过期的抖音作品缓存记录`);
|
|
39335
39789
|
if (await this.checkremark()) return true;
|
|
39336
39790
|
await this.ensureConfigFields(Config.pushlist.douyin);
|
|
39337
|
-
const registeredBotIds = karin
|
|
39791
|
+
const registeredBotIds = karin.getAllBotID();
|
|
39338
39792
|
const filteredPushList = this.filterPushListByRegisteredBots(Config.pushlist.douyin, registeredBotIds);
|
|
39339
39793
|
if (filteredPushList.length === 0) {
|
|
39340
39794
|
logger.warn("没有已注册的 bot 可用于抖音推送");
|
|
@@ -39522,13 +39976,22 @@ var DouYinpush = class extends Base {
|
|
|
39522
39976
|
let status = { message_id: "" };
|
|
39523
39977
|
const { groupId, botId } = target;
|
|
39524
39978
|
if (!skip) {
|
|
39525
|
-
const Contact = karin
|
|
39526
|
-
const bot = karin
|
|
39979
|
+
const Contact = karin.contactGroup(groupId);
|
|
39980
|
+
const bot = karin.getBot(botId);
|
|
39527
39981
|
const eventWithBot = this.e;
|
|
39528
39982
|
eventWithBot.bot = bot;
|
|
39529
39983
|
eventWithBot.selfId = botId;
|
|
39530
39984
|
const watermarkedImg = img ? applyWatermarkToImages(img, this.e) : [];
|
|
39531
|
-
|
|
39985
|
+
const parseButton = bot?.adapter?.name === "QQ Official Bot" && pushItem.pushType !== "live" && Detail_Data.share_url ? [segment.button([{
|
|
39986
|
+
text: "解析",
|
|
39987
|
+
callback: true,
|
|
39988
|
+
data: `#解析${Detail_Data.share_url}`
|
|
39989
|
+
}, {
|
|
39990
|
+
text: "帮助",
|
|
39991
|
+
callback: true,
|
|
39992
|
+
data: `#kkk帮助`
|
|
39993
|
+
}])] : [];
|
|
39994
|
+
status = await karin.sendMsg(botId, Contact, [...watermarkedImg, ...parseButton]);
|
|
39532
39995
|
if (pushItem.pushType === "live" && "room_data" in pushItem.Detail_Data && status.message_id) await douyinDBInstance.updateLiveStatus(pushItem.sec_uid, true);
|
|
39533
39996
|
if (Config.douyin.push.parsedynamic && status.message_id) {
|
|
39534
39997
|
const workTypeInfo = getWorkTypeInfo(Detail_Data);
|
|
@@ -39654,7 +40117,7 @@ var DouYinpush = class extends Base {
|
|
|
39654
40117
|
filepath: motionPhotoCoverPath,
|
|
39655
40118
|
totalBytes: 0
|
|
39656
40119
|
});
|
|
39657
|
-
const motionPhotoCover =
|
|
40120
|
+
const motionPhotoCover = processLocalImageFile(motionPhotoCoverPath);
|
|
39658
40121
|
images.push(segment.image(motionPhotoCover));
|
|
39659
40122
|
hasPushedMotionPhotoCover = true;
|
|
39660
40123
|
}
|
|
@@ -39675,7 +40138,7 @@ var DouYinpush = class extends Base {
|
|
|
39675
40138
|
});
|
|
39676
40139
|
images.push(...tipImg);
|
|
39677
40140
|
}
|
|
39678
|
-
const bot = karin
|
|
40141
|
+
const bot = karin.getBot(botId);
|
|
39679
40142
|
const Element = common.makeForward(images, botId, bot.account.name);
|
|
39680
40143
|
try {
|
|
39681
40144
|
await bot.sendForwardMsg(Contact, Element, {
|
|
@@ -39777,7 +40240,7 @@ var DouYinpush = class extends Base {
|
|
|
39777
40240
|
filepath: motionPhotoCoverPath,
|
|
39778
40241
|
totalBytes: 0
|
|
39779
40242
|
});
|
|
39780
|
-
const motionPhotoCover =
|
|
40243
|
+
const motionPhotoCover = processLocalImageFile(motionPhotoCoverPath);
|
|
39781
40244
|
processedImages.push(segment.image(motionPhotoCover));
|
|
39782
40245
|
hasPushedMotionPhotoCover = true;
|
|
39783
40246
|
}
|
|
@@ -39798,7 +40261,7 @@ var DouYinpush = class extends Base {
|
|
|
39798
40261
|
});
|
|
39799
40262
|
processedImages.push(...tipImg);
|
|
39800
40263
|
}
|
|
39801
|
-
const bot = karin
|
|
40264
|
+
const bot = karin.getBot(botId);
|
|
39802
40265
|
const Element = common.makeForward(processedImages, botId, bot.account.name);
|
|
39803
40266
|
try {
|
|
39804
40267
|
await bot.sendForwardMsg(Contact, Element, {
|
|
@@ -39820,7 +40283,7 @@ var DouYinpush = class extends Base {
|
|
|
39820
40283
|
const imageUrl = await processImageUrl(image_url, Detail_Data.desc, index);
|
|
39821
40284
|
imageres.push(segment.image(imageUrl));
|
|
39822
40285
|
}
|
|
39823
|
-
const bot = karin
|
|
40286
|
+
const bot = karin.getBot(botId);
|
|
39824
40287
|
if (imageres.length === 1) {
|
|
39825
40288
|
const imageUrl = await processImageUrl(image_url, Detail_Data.desc);
|
|
39826
40289
|
await bot.sendMsg(Contact, [segment.image(imageUrl)]);
|
|
@@ -40550,6 +41013,42 @@ var Xiaohongshu = class extends Base {
|
|
|
40550
41013
|
this.e = e;
|
|
40551
41014
|
this.type = iddata?.type;
|
|
40552
41015
|
}
|
|
41016
|
+
async fetchConfiguredNoteComments(data) {
|
|
41017
|
+
const targetCount = Math.max(1, Config.xiaohongshu.numcomment);
|
|
41018
|
+
const firstPage = await this.amagi.xiaohongshu.fetcher.fetchNoteComments({
|
|
41019
|
+
typeMode: "strict",
|
|
41020
|
+
note_id: data.note_id,
|
|
41021
|
+
xsec_token: data.xsec_token
|
|
41022
|
+
});
|
|
41023
|
+
const comments = [...firstPage.data.data.comments ?? []];
|
|
41024
|
+
let cursor = firstPage.data.data.cursor;
|
|
41025
|
+
let hasMore = firstPage.data.data.has_more;
|
|
41026
|
+
const seenCursors = /* @__PURE__ */ new Set();
|
|
41027
|
+
while (comments.length < targetCount && hasMore && cursor && !seenCursors.has(cursor)) {
|
|
41028
|
+
seenCursors.add(cursor);
|
|
41029
|
+
const nextPage = await this.amagi.xiaohongshu.fetcher.fetchNoteComments({
|
|
41030
|
+
typeMode: "strict",
|
|
41031
|
+
note_id: data.note_id,
|
|
41032
|
+
cursor,
|
|
41033
|
+
xsec_token: data.xsec_token
|
|
41034
|
+
});
|
|
41035
|
+
comments.push(...nextPage.data.data.comments ?? []);
|
|
41036
|
+
cursor = nextPage.data.data.cursor;
|
|
41037
|
+
hasMore = nextPage.data.data.has_more;
|
|
41038
|
+
}
|
|
41039
|
+
return {
|
|
41040
|
+
...firstPage,
|
|
41041
|
+
data: {
|
|
41042
|
+
...firstPage.data,
|
|
41043
|
+
data: {
|
|
41044
|
+
...firstPage.data.data,
|
|
41045
|
+
comments,
|
|
41046
|
+
cursor,
|
|
41047
|
+
has_more: hasMore
|
|
41048
|
+
}
|
|
41049
|
+
}
|
|
41050
|
+
};
|
|
41051
|
+
}
|
|
40553
41052
|
async XiaohongshuHandler(data) {
|
|
40554
41053
|
if (Config.amagi.cookies.xiaohongshu === "") throw new Error("我还没有小红书的 Cookies,暂时无法解析呢 ~");
|
|
40555
41054
|
if (Config.app.parseTip) await this.e.reply("检测到小红书链接,开始解析");
|
|
@@ -40573,11 +41072,7 @@ var Xiaohongshu = class extends Base {
|
|
|
40573
41072
|
this.e.reply(noteInfoImg);
|
|
40574
41073
|
}
|
|
40575
41074
|
if (Config.xiaohongshu.sendContent.some((item) => item === "comment")) {
|
|
40576
|
-
const CommentData = await this.
|
|
40577
|
-
typeMode: "strict",
|
|
40578
|
-
note_id: data.note_id,
|
|
40579
|
-
xsec_token: data.xsec_token
|
|
40580
|
-
});
|
|
41075
|
+
const CommentData = await this.fetchConfiguredNoteComments(data);
|
|
40581
41076
|
if (!CommentData.data.data.comments || CommentData.data.data.comments.length === 0) await this.e.reply("这个笔记没有评论 ~");
|
|
40582
41077
|
else {
|
|
40583
41078
|
const processedComments = await xiaohongshuComments(CommentData.data, formattedEmojis);
|
|
@@ -40669,7 +41164,7 @@ var Xiaohongshu = class extends Base {
|
|
|
40669
41164
|
filepath: motionPhotoCoverPath,
|
|
40670
41165
|
totalBytes: 0
|
|
40671
41166
|
});
|
|
40672
|
-
const motionPhotoCover =
|
|
41167
|
+
const motionPhotoCover = processLocalImageFile(motionPhotoCoverPath);
|
|
40673
41168
|
processedImages.push(segment.image(motionPhotoCover));
|
|
40674
41169
|
hasPushedMotionPhotoCover = true;
|
|
40675
41170
|
hasGeneratedLivePhoto = true;
|
|
@@ -41095,7 +41590,7 @@ var douyinLogin = async (e) => {
|
|
|
41095
41590
|
while (verifyAttempts < maxAttempts && !verifySuccess) {
|
|
41096
41591
|
verifyAttempts++;
|
|
41097
41592
|
logger.debug(`验证码输入尝试 ${verifyAttempts}/${maxAttempts}`);
|
|
41098
|
-
const ctx = await Promise.race([karin.ctx(e, { reply: true }), new Promise((_, reject) => setTimeout(() => reject(/* @__PURE__ */ new Error("2FA_TIMEOUT")), 6e4))]).catch(async (error) => {
|
|
41593
|
+
const ctx = await Promise.race([karin$1.ctx(e, { reply: true }), new Promise((_, reject) => setTimeout(() => reject(/* @__PURE__ */ new Error("2FA_TIMEOUT")), 6e4))]).catch(async (error) => {
|
|
41099
41594
|
if (error.message === "2FA_TIMEOUT") {
|
|
41100
41595
|
logger.warn("2FA验证码输入超时");
|
|
41101
41596
|
clearTimeout(timer);
|
|
@@ -41252,12 +41747,12 @@ var handleCacheCleanup = wrapWithErrorHandler(async () => {
|
|
|
41252
41747
|
const twoHoursAgo = Date.now() - 7200 * 1e3;
|
|
41253
41748
|
const videoDeleted = removeOldFiles(Common.tempDri.video, twoHoursAgo);
|
|
41254
41749
|
logger.debug(`${Common.tempDri.video} 目录下已删除 ${videoDeleted} 个文件`);
|
|
41255
|
-
if (Config.app.imageSendMode
|
|
41750
|
+
if (Config.app.imageSendMode !== "url") {
|
|
41256
41751
|
const imageDeleted = removeOldFiles(Common.tempDri.images, twoHoursAgo);
|
|
41257
41752
|
logger.debug(`${Common.tempDri.images} 目录下已删除 ${imageDeleted} 个文件`);
|
|
41258
41753
|
}
|
|
41259
41754
|
}, { businessName: "缓存自动删除" });
|
|
41260
|
-
var task = Config.app.removeCache && karin
|
|
41755
|
+
var task = Config.app.removeCache && karin.task("[kkk-缓存自动删除]", "*/30 * * * *", handleCacheCleanup, { log: false });
|
|
41261
41756
|
var handleBilibiliLogin = wrapWithErrorHandler(async (e) => {
|
|
41262
41757
|
await bilibiliLogin(e);
|
|
41263
41758
|
return true;
|
|
@@ -41276,15 +41771,15 @@ var handlTestWrapWithErrorHandler = wrapWithErrorHandler(async (_e) => {
|
|
|
41276
41771
|
logger.fatal("测试致命日志");
|
|
41277
41772
|
throw Error("测试异常");
|
|
41278
41773
|
}, { businessName: "测试命令-错误捕获" });
|
|
41279
|
-
var biLogin = karin
|
|
41774
|
+
var biLogin = karin.command(/^#?(kkk)?\s*B站\s*(扫码)?\s*登录$/i, handleBilibiliLogin, {
|
|
41280
41775
|
perm: Config.bilibili.loginPerm,
|
|
41281
41776
|
name: "kkk-ck管理"
|
|
41282
41777
|
});
|
|
41283
|
-
var dylogin = karin
|
|
41778
|
+
var dylogin = karin.command(/^#?(kkk)?抖音(扫码)?登录$/, handleDouyinLogin, {
|
|
41284
41779
|
perm: Config.douyin.loginPerm,
|
|
41285
41780
|
name: "kkk-ck管理"
|
|
41286
41781
|
});
|
|
41287
|
-
var testWrapWithErrorHandler = process.env.NODE_ENV === "development" ? karin
|
|
41782
|
+
var testWrapWithErrorHandler = process.env.NODE_ENV === "development" ? karin.command(/^#?(kkk)?\s*测试\s*错误捕获$/i, handlTestWrapWithErrorHandler, {
|
|
41288
41783
|
perm: Config.bilibili.loginPerm,
|
|
41289
41784
|
name: "kkk-测试命令-错误捕获"
|
|
41290
41785
|
}) : null;
|
|
@@ -41473,8 +41968,8 @@ var handleVersion = wrapWithErrorHandler(async (e) => {
|
|
|
41473
41968
|
e.reply(img);
|
|
41474
41969
|
return true;
|
|
41475
41970
|
}, { businessName: "KKK版本" });
|
|
41476
|
-
var help = karin
|
|
41477
|
-
var version = karin
|
|
41971
|
+
var help = karin.command(/^#?kkk帮助$/, handleHelp, { name: "kkk-帮助" });
|
|
41972
|
+
var version = karin.command(/^#?kkk(版本|更新日志)$/, handleVersion, { name: "kkk-版本" });
|
|
41478
41973
|
//#endregion
|
|
41479
41974
|
//#region src/apps/push.ts
|
|
41480
41975
|
var handleDouyinPush = wrapWithErrorHandler(async () => {
|
|
@@ -41640,42 +42135,42 @@ var handleGlobalIgnore = wrapWithErrorHandler(async (e) => {
|
|
|
41640
42135
|
}
|
|
41641
42136
|
return true;
|
|
41642
42137
|
}, { businessName: "推送全局忽略" });
|
|
41643
|
-
var douyinPush = Config.douyin.push.switch && karin
|
|
42138
|
+
var douyinPush = Config.douyin.push.switch && karin.task("抖音推送", Config.douyin.push.cron, handleDouyinPush, {
|
|
41644
42139
|
log: true,
|
|
41645
42140
|
type: "skip"
|
|
41646
42141
|
});
|
|
41647
|
-
var bilibiliPush = Config.bilibili.push.switch && karin
|
|
42142
|
+
var bilibiliPush = Config.bilibili.push.switch && karin.task("B站推送", Config.bilibili.push.cron, handleBilibiliPush, {
|
|
41648
42143
|
log: true,
|
|
41649
42144
|
type: "skip"
|
|
41650
42145
|
});
|
|
41651
|
-
var forcePush = karin
|
|
42146
|
+
var forcePush = karin.command(/#(抖音|B站)(全部)?强制推送/, handleForcePush, {
|
|
41652
42147
|
name: "𝑪𝒊𝒂𝒍𝒍𝒐~(∠・ω< )⌒★",
|
|
41653
42148
|
perm: "master",
|
|
41654
42149
|
event: "message.group"
|
|
41655
42150
|
});
|
|
41656
|
-
var setdyPush = karin
|
|
42151
|
+
var setdyPush = karin.command(/^#设置抖音推送/, handleSetDouyinPush, {
|
|
41657
42152
|
name: "kkk-推送功能-设置",
|
|
41658
42153
|
event: "message.group",
|
|
41659
42154
|
perm: Config.douyin.push.permission
|
|
41660
42155
|
});
|
|
41661
|
-
var setbiliPush = karin
|
|
42156
|
+
var setbiliPush = karin.command(/^#设置[bB]站推送/, handleSetBilibiliPush, {
|
|
41662
42157
|
name: "kkk-推送功能-设置",
|
|
41663
42158
|
event: "message.group",
|
|
41664
42159
|
perm: Config.bilibili.push.permission
|
|
41665
42160
|
});
|
|
41666
|
-
var bilibiliPushList = karin
|
|
42161
|
+
var bilibiliPushList = karin.command(/^#?[bB]站推送列表$/, handleBilibiliPushList, {
|
|
41667
42162
|
name: "kkk-推送功能-列表",
|
|
41668
42163
|
event: "message.group"
|
|
41669
42164
|
});
|
|
41670
|
-
var douyinPushList = karin
|
|
42165
|
+
var douyinPushList = karin.command(/^#?抖音推送列表$/, handleDouyinPushList, {
|
|
41671
42166
|
name: "kkk-推送功能-列表",
|
|
41672
42167
|
event: "message.group"
|
|
41673
42168
|
});
|
|
41674
|
-
var changeBotID = karin
|
|
42169
|
+
var changeBotID = karin.command(/^#kkk设置推送机器人/, handleChangeBotID, {
|
|
41675
42170
|
name: "kkk-推送功能-设置",
|
|
41676
42171
|
perm: "master"
|
|
41677
42172
|
});
|
|
41678
|
-
var globalIgnore = karin
|
|
42173
|
+
var globalIgnore = karin.command(/^#kkk推送全局忽略/, handleGlobalIgnore, {
|
|
41679
42174
|
name: "kkk-推送功能-全局忽略",
|
|
41680
42175
|
perm: "master",
|
|
41681
42176
|
event: "message.group",
|
|
@@ -41750,7 +42245,7 @@ async function getHostByConfig() {
|
|
|
41750
42245
|
* 生成登录二维码(仅私发给主人)
|
|
41751
42246
|
*/
|
|
41752
42247
|
var handleQrLogin = wrapWithErrorHandler(async (e) => {
|
|
41753
|
-
const bot = karin
|
|
42248
|
+
const bot = karin.getBot(e.selfId);
|
|
41754
42249
|
const userId = e.userId;
|
|
41755
42250
|
if (e.isGroup) {
|
|
41756
42251
|
if (!(await bot?.getFriendList())?.some((f) => f.userId === userId)) {
|
|
@@ -41775,11 +42270,11 @@ var handleQrLogin = wrapWithErrorHandler(async (e) => {
|
|
|
41775
42270
|
}),
|
|
41776
42271
|
serverUrl: `${protocol}://${host}:${port}`
|
|
41777
42272
|
});
|
|
41778
|
-
await karin
|
|
42273
|
+
await karin.sendMaster(e.selfId, userId, images);
|
|
41779
42274
|
if (e.isGroup) await e.reply("登录二维码已私聊发送,请查收~");
|
|
41780
42275
|
return true;
|
|
41781
42276
|
}, { businessName: "APP扫码登录" });
|
|
41782
|
-
var qrLogin = karin
|
|
42277
|
+
var qrLogin = karin.command(/^#?(kkk)?登录$/i, handleQrLogin, {
|
|
41783
42278
|
perm: "master",
|
|
41784
42279
|
name: "kkk-APP扫码登录"
|
|
41785
42280
|
});
|
|
@@ -41831,7 +42326,7 @@ var handleGroupStatistics = wrapWithErrorHandler(async (e) => {
|
|
|
41831
42326
|
await e.reply(img);
|
|
41832
42327
|
return true;
|
|
41833
42328
|
}, { businessName: "群组解析统计" });
|
|
41834
|
-
var groupStatistics = karin
|
|
42329
|
+
var groupStatistics = karin.command(/^#?kkk解析统计$/, handleGroupStatistics, { name: "kkk-解析统计" });
|
|
41835
42330
|
/**
|
|
41836
42331
|
* #kkk全局解析统计 命令
|
|
41837
42332
|
* 获取整个插件的全局解析统计数据
|
|
@@ -41859,7 +42354,7 @@ var handleGlobalStatistics = wrapWithErrorHandler(async (e) => {
|
|
|
41859
42354
|
await e.reply(img);
|
|
41860
42355
|
return true;
|
|
41861
42356
|
}, { businessName: "全局解析统计" });
|
|
41862
|
-
var globalStatistics = karin
|
|
42357
|
+
var globalStatistics = karin.command(/^#?kkk全局解析统计$/, handleGlobalStatistics, {
|
|
41863
42358
|
name: "kkk-全局解析统计",
|
|
41864
42359
|
perm: "master"
|
|
41865
42360
|
});
|
|
@@ -42069,7 +42564,7 @@ var handleTestPush = wrapWithErrorHandler(async (e) => {
|
|
|
42069
42564
|
return true;
|
|
42070
42565
|
}, { businessName: "测试抖音推送" });
|
|
42071
42566
|
/** 注册测试推送命令 */
|
|
42072
|
-
var testPush = Config.douyin.switch && karin
|
|
42567
|
+
var testPush = Config.douyin.switch && karin.command(/^#测试抖音(作品|喜欢列表|推荐列表|直播状态)推送/, handleTestPush, {
|
|
42073
42568
|
name: "kkk-测试抖音推送",
|
|
42074
42569
|
perm: "master"
|
|
42075
42570
|
});
|
|
@@ -42156,7 +42651,7 @@ var handleXiaohongshu = wrapWithErrorHandler(async (e, next) => {
|
|
|
42156
42651
|
}, { businessName: "小红书视频解析" });
|
|
42157
42652
|
var handlePrefix = wrapWithErrorHandler(async (e, next) => {
|
|
42158
42653
|
const originalMsg = e.msg;
|
|
42159
|
-
e.msg = await Common.getReplyMessage(e);
|
|
42654
|
+
e.msg = await Common.getReplyMessage(e) || originalMsg.replace(/^#?(解析|kkk解析|弹幕解析)\s*/, "");
|
|
42160
42655
|
if (/^#?弹幕解析/.test(originalMsg)) e.msg = "#弹幕解析 " + e.msg;
|
|
42161
42656
|
if (reg.douyinCDN.test(e.msg)) {
|
|
42162
42657
|
logger.debug("检测到抖音 CDN 下载链接,直接下载视频");
|
|
@@ -42175,23 +42670,23 @@ var handlePrefix = wrapWithErrorHandler(async (e, next) => {
|
|
|
42175
42670
|
else if (reg.kuaishou.test(e.msg)) return await handleKuaishou(e, next);
|
|
42176
42671
|
else if (reg.xiaohongshu.test(e.msg)) return await handleXiaohongshu(e, next);
|
|
42177
42672
|
}, { businessName: "引用解析" });
|
|
42178
|
-
var douyin = karin
|
|
42673
|
+
var douyin = karin.command(reg.douyin, handleDouyin, {
|
|
42179
42674
|
name: "kkk-视频功能-抖音",
|
|
42180
42675
|
priority: Config.app.videoTool ? -Infinity : 800
|
|
42181
42676
|
});
|
|
42182
|
-
var bilibili = karin
|
|
42677
|
+
var bilibili = karin.command(reg.bilibili, handleBilibili, {
|
|
42183
42678
|
name: "kkk-视频功能-B站",
|
|
42184
42679
|
priority: Config.app.videoTool ? -Infinity : 800
|
|
42185
42680
|
});
|
|
42186
|
-
var kuaishou = karin
|
|
42681
|
+
var kuaishou = karin.command(reg.kuaishou, handleKuaishou, {
|
|
42187
42682
|
name: "kkk-视频功能-快手",
|
|
42188
42683
|
priority: Config.app.videoTool ? -Infinity : 800
|
|
42189
42684
|
});
|
|
42190
|
-
var xiaohongshu = karin
|
|
42685
|
+
var xiaohongshu = karin.command(reg.xiaohongshu, handleXiaohongshu, {
|
|
42191
42686
|
name: "kkk-视频功能-小红书",
|
|
42192
42687
|
priority: Config.app.videoTool ? -Infinity : 800
|
|
42193
42688
|
});
|
|
42194
|
-
var prefix = karin
|
|
42689
|
+
var prefix = karin.command(/^#?(解析|kkk解析|弹幕解析)/, handlePrefix, { name: "kkk-视频功能-引用解析" });
|
|
42195
42690
|
var douyinAPP = Config.douyin.switch && douyin;
|
|
42196
42691
|
var bilibiliAPP = Config.bilibili.switch && bilibili;
|
|
42197
42692
|
var kuaishouAPP = Config.kuaishou.switch && kuaishou;
|
|
@@ -42358,7 +42853,7 @@ var Handler = async () => {
|
|
|
42358
42853
|
} catch {}
|
|
42359
42854
|
const masters = config.master().filter((id) => id !== "console");
|
|
42360
42855
|
if (masters.length === 0) return true;
|
|
42361
|
-
const botItems = karin
|
|
42856
|
+
const botItems = karin.getAllBotList().filter((b) => b.bot.account.name !== "console");
|
|
42362
42857
|
if (botItems.length === 0) return true;
|
|
42363
42858
|
const friendsMap = /* @__PURE__ */ new Map();
|
|
42364
42859
|
await Promise.all(botItems.map(async (item) => {
|
|
@@ -42390,7 +42885,7 @@ var Handler = async () => {
|
|
|
42390
42885
|
if (!bot) continue;
|
|
42391
42886
|
const elements = botToImage.get(bot.account.selfId);
|
|
42392
42887
|
if (!elements) continue;
|
|
42393
|
-
const msg = await karin
|
|
42888
|
+
const msg = await karin.sendMaster(bot.account.selfId, owner, elements);
|
|
42394
42889
|
if (!storedMsgId && msg?.messageId) storedMsgId = msg.messageId;
|
|
42395
42890
|
}
|
|
42396
42891
|
if (storedMsgId) try {
|
|
@@ -42453,14 +42948,14 @@ var handleKkkUpdate = wrapWithErrorHandler(async (e) => {
|
|
|
42453
42948
|
await restart(e.selfId, e.contact, msgResult.messageId);
|
|
42454
42949
|
} else e.reply(`${Root.pluginName} 更新失败: ${result.data ?? "更新执行失败"}`);
|
|
42455
42950
|
}, { businessName: "KKK更新" });
|
|
42456
|
-
var kkkUpdateCommand = karin
|
|
42457
|
-
var kkkUpdateTest = process.env.NODE_ENV === "development" && karin
|
|
42951
|
+
var kkkUpdateCommand = karin.command(/^#?kkk更新$/, handleKkkUpdate, { name: "kkk-更新" });
|
|
42952
|
+
var kkkUpdateTest = process.env.NODE_ENV === "development" && karin.command("test", async (_e, next) => {
|
|
42458
42953
|
await db.del(UPDATE_MSGID_KEY);
|
|
42459
42954
|
await db.del(UPDATE_LOCK_KEY);
|
|
42460
42955
|
await Handler();
|
|
42461
42956
|
next();
|
|
42462
42957
|
}, { name: "kkk-更新检测-测试" });
|
|
42463
|
-
var update = karin
|
|
42958
|
+
var update = karin.task("kkk-更新检测", "*/3 * * * *", Handler, {
|
|
42464
42959
|
name: "kkk-更新检测",
|
|
42465
42960
|
log: false
|
|
42466
42961
|
});
|
|
@@ -42503,7 +42998,7 @@ var ROUTES = {
|
|
|
42503
42998
|
* Bot 管理 API
|
|
42504
42999
|
*/
|
|
42505
43000
|
var getOnlineBotById = (botId) => {
|
|
42506
|
-
return karin.getAllBotList().find((item) => item.bot.account.selfId === botId)?.bot;
|
|
43001
|
+
return karin$1.getAllBotList().find((item) => item.bot.account.selfId === botId)?.bot;
|
|
42507
43002
|
};
|
|
42508
43003
|
var getBotAvatar = async (bot, botId) => {
|
|
42509
43004
|
if (!bot) return "";
|
|
@@ -42520,7 +43015,7 @@ var getBotAvatar = async (bot, botId) => {
|
|
|
42520
43015
|
*/
|
|
42521
43016
|
var getBots = async (_req, res) => {
|
|
42522
43017
|
try {
|
|
42523
|
-
const botList = karin.getAllBotList();
|
|
43018
|
+
const botList = karin$1.getAllBotList();
|
|
42524
43019
|
const bots = [];
|
|
42525
43020
|
for (const item of botList) {
|
|
42526
43021
|
const bot = item.bot;
|
|
@@ -42573,7 +43068,7 @@ var getBotGroups = async (req, res) => {
|
|
|
42573
43068
|
try {
|
|
42574
43069
|
const botId = Array.isArray(req.params.botId) ? req.params.botId[0] : req.params.botId;
|
|
42575
43070
|
if (!botId) return createServerErrorResponse(res, "缺少 botId 参数");
|
|
42576
|
-
const botItem = karin.getAllBotList().find((item) => item.bot.account.selfId === botId);
|
|
43071
|
+
const botItem = karin$1.getAllBotList().find((item) => item.bot.account.selfId === botId);
|
|
42577
43072
|
if (!botItem) return createServerErrorResponse(res, "Bot 不存在或不在线");
|
|
42578
43073
|
const bot = botItem.bot;
|
|
42579
43074
|
const groupList = await bot.getGroupList();
|
|
@@ -42642,7 +43137,7 @@ var getGroupsBatch = async (req, res) => {
|
|
|
42642
43137
|
const { groups } = req.body;
|
|
42643
43138
|
if (!groups || !Array.isArray(groups)) return createServerErrorResponse(res, "缺少 groups 参数");
|
|
42644
43139
|
const result = [];
|
|
42645
|
-
const botList = karin.getAllBotList();
|
|
43140
|
+
const botList = karin$1.getAllBotList();
|
|
42646
43141
|
for (const item of groups) {
|
|
42647
43142
|
const botItem = botList.find((b) => b.bot.account.selfId === item.botId);
|
|
42648
43143
|
if (!botItem) {
|
|
@@ -43119,7 +43614,7 @@ if (process.env.NODE_ENV !== "development" && isSemverGreater(requireVersion, Ro
|
|
|
43119
43614
|
logger.warn(msg);
|
|
43120
43615
|
/** 已发送通知的 Bot ID 和主人 ID 组合,格式:`${botId}:${master}` */
|
|
43121
43616
|
const notifiedSet = /* @__PURE__ */ new Set();
|
|
43122
|
-
karin
|
|
43617
|
+
karin.on(BOT_CONNECT, async (bot) => {
|
|
43123
43618
|
const botId = bot.selfId;
|
|
43124
43619
|
if (botId === "console") return;
|
|
43125
43620
|
await new Promise((resolve) => setTimeout(resolve, 2e3));
|
|
@@ -43129,7 +43624,7 @@ if (process.env.NODE_ENV !== "development" && isSemverGreater(requireVersion, Ro
|
|
|
43129
43624
|
for (const master of masters) {
|
|
43130
43625
|
if (master === "console") continue;
|
|
43131
43626
|
try {
|
|
43132
|
-
warningImage = await Render({ bot: karin
|
|
43627
|
+
warningImage = await Render({ bot: karin.getBot(botId) }, "other/version_warning", {
|
|
43133
43628
|
requireVersion,
|
|
43134
43629
|
currentVersion: Root.karinVersion
|
|
43135
43630
|
});
|
|
@@ -43141,7 +43636,7 @@ if (process.env.NODE_ENV !== "development" && isSemverGreater(requireVersion, Ro
|
|
|
43141
43636
|
try {
|
|
43142
43637
|
const elements = [];
|
|
43143
43638
|
if (warningImage) elements.push(...warningImage);
|
|
43144
|
-
await karin
|
|
43639
|
+
await karin.sendMaster(botId, master, elements);
|
|
43145
43640
|
notifiedSet.add(key);
|
|
43146
43641
|
logger.info(`[karin-plugin-kkk] 已发送版本警告给主人: ${master} (via ${botId})`);
|
|
43147
43642
|
} catch (error) {
|