karin-plugin-kkk 2.36.1 → 2.36.3
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 +60 -29
- package/lib/build-metadata.json +5 -5
- package/lib/core_chunk/main.js +488 -192
- package/lib/core_chunk/rolldown-runtime.js +1 -1
- package/lib/core_chunk/template.d.mts +1 -1
- package/lib/core_chunk/vendor.js +8176 -7833
- package/lib/karin-plugin-kkk.css +606 -125
- package/lib/web/assets/CronEditor-rHmpAxFj.js +1 -0
- package/lib/web/assets/DesktopLayout-Cr5ZibGs.js +1 -0
- package/lib/web/assets/MobileLayout-WN2r3MCa.js +1 -0
- package/lib/web/assets/ThemeSwitch-DMmlpRk7.js +1 -0
- package/lib/web/assets/index-DU0mjeqO.js +47 -0
- package/lib/web/assets/{index-2paV9T2e.css → index-hQel6cUs.css} +1 -1
- package/lib/web/assets/separator-DSAWGreF.js +1 -0
- package/lib/web/index.html +2 -2
- package/package.json +4 -4
- package/lib/web/assets/CronEditor-DLELr4UG.js +0 -1
- package/lib/web/assets/DesktopLayout-DMqLKe0d.js +0 -1
- package/lib/web/assets/MobileLayout-Dq6Ng8rW.js +0 -1
- package/lib/web/assets/ThemeSwitch-C9X8kWTm.js +0 -1
- package/lib/web/assets/index-DhbVGvm8.js +0 -47
- package/lib/web/assets/separator-D6lAHrvZ.js +0 -1
package/lib/core_chunk/main.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { i as __toESM } from "./rolldown-runtime.js";
|
|
2
|
-
import { $ as
|
|
2
|
+
import { $ as SiXiaomi, $n as CircleCheck, $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 EyeOff, 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 CircleCheckBig, 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 Eye, 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
9
|
import crypto, { createCipheriv, createHash, randomBytes, randomUUID } from "node:crypto";
|
|
10
10
|
import axios, { AxiosError } from "node-karin/axios";
|
|
@@ -14,7 +14,7 @@ import { karinPathBase, karinPathTemp as karinPathTemp$1 } from "node-karin/root
|
|
|
14
14
|
import sqlite3 from "node-karin/sqlite3";
|
|
15
15
|
import YAML from "node-karin/yaml";
|
|
16
16
|
import util from "node:util";
|
|
17
|
-
import {
|
|
17
|
+
import { generateSync, scanSync } from "@ikenxuan/qrcode";
|
|
18
18
|
import { Transform } from "node:stream";
|
|
19
19
|
import { pipeline } from "node:stream/promises";
|
|
20
20
|
import _ from "node-karin/lodash";
|
|
@@ -3470,7 +3470,7 @@ var XBogus = class {
|
|
|
3470
3470
|
* @returns 包含完整URL、X-Bogus值和使用的User-Agent的元组
|
|
3471
3471
|
*/
|
|
3472
3472
|
getXBogus(url, ua) {
|
|
3473
|
-
const parsedUrl = new URL$
|
|
3473
|
+
const parsedUrl = new URL$2.URL(url);
|
|
3474
3474
|
const urlPath = parsedUrl.pathname + parsedUrl.search;
|
|
3475
3475
|
const currentUa = ua ?? this.defaultUa;
|
|
3476
3476
|
const rc4EncryptedUa = this.rc4Encrypt(this.uaKey, currentUa);
|
|
@@ -7619,13 +7619,6 @@ function createBoundKuaishouFetcher(cookie, requestConfig) {
|
|
|
7619
7619
|
}
|
|
7620
7620
|
//#endregion
|
|
7621
7621
|
//#region ../amagi/packages/core/src/platform/xiaohongshu/getdata.ts
|
|
7622
|
-
/** 小红书返回 code=-100,表示当前登录 Cookie 已失效。 */
|
|
7623
|
-
var XiaohongshuLoginExpiredError = class extends Error {
|
|
7624
|
-
constructor() {
|
|
7625
|
-
super("小红书登录 Cookie 已过期");
|
|
7626
|
-
this.name = "XiaohongshuLoginExpiredError";
|
|
7627
|
-
}
|
|
7628
|
-
};
|
|
7629
7622
|
/**
|
|
7630
7623
|
* 小红书数据获取函数
|
|
7631
7624
|
* @param data - 请求数据参数
|
|
@@ -7763,15 +7756,7 @@ var XiaohongshuData = async (data, cookie, requestConfig) => {
|
|
|
7763
7756
|
default: throw new Error(`Unknown Xiaohongshu API method: "${data.methodType}"`);
|
|
7764
7757
|
}
|
|
7765
7758
|
};
|
|
7766
|
-
|
|
7767
|
-
if (!userCookie) return requestWithCookie(await xiaohongshuSign.createGuestCookie(requestConfig));
|
|
7768
|
-
try {
|
|
7769
|
-
return await requestWithCookie(userCookie);
|
|
7770
|
-
} catch (error) {
|
|
7771
|
-
if (!(error instanceof XiaohongshuLoginExpiredError)) throw error;
|
|
7772
|
-
emitLogWarn("小红书用户 Cookie 已过期,切换游客 Cookie 后重试请求");
|
|
7773
|
-
return requestWithCookie(await xiaohongshuSign.createGuestCookie(requestConfig));
|
|
7774
|
-
}
|
|
7759
|
+
return requestWithCookie(cookie?.trim() ?? "");
|
|
7775
7760
|
};
|
|
7776
7761
|
/**
|
|
7777
7762
|
* 全局数据获取函数
|
|
@@ -7792,11 +7777,9 @@ var GlobalGetData$1 = async (methodType, config) => {
|
|
|
7792
7777
|
throw networkError;
|
|
7793
7778
|
}
|
|
7794
7779
|
if (typeof response === "string" && response.includes("<html>")) return response;
|
|
7795
|
-
if (response.code === -100) throw new XiaohongshuLoginExpiredError();
|
|
7796
7780
|
if (response.code !== 0) throw new Error(`API request failed: ${response.data?.msg ?? response.msg ?? "Unknown error"}, code: ${response.code}`);
|
|
7797
7781
|
return response;
|
|
7798
7782
|
} catch (error) {
|
|
7799
|
-
if (error instanceof XiaohongshuLoginExpiredError) throw error;
|
|
7800
7783
|
emitLogError(`Xiaohongshu API request failed [${methodType}]:`, error.message);
|
|
7801
7784
|
return {
|
|
7802
7785
|
code: 500,
|
|
@@ -10350,7 +10333,7 @@ function getApiRoute(platform, methodType) {
|
|
|
10350
10333
|
* 构建后使用 __VERSION__,开发环境从 package.json 读取
|
|
10351
10334
|
*/
|
|
10352
10335
|
var getVersion = () => {
|
|
10353
|
-
return "6.
|
|
10336
|
+
return "6.2.0";
|
|
10354
10337
|
};
|
|
10355
10338
|
var VERSION = getVersion();
|
|
10356
10339
|
/**
|
|
@@ -10906,7 +10889,7 @@ var uploadFile = async (event, file, videoUrl, options) => {
|
|
|
10906
10889
|
let contact;
|
|
10907
10890
|
if (options?.active) {
|
|
10908
10891
|
selfId = options?.activeOption?.uin;
|
|
10909
|
-
contact = karin
|
|
10892
|
+
contact = karin.contactGroup(options?.activeOption?.group_id);
|
|
10910
10893
|
} else {
|
|
10911
10894
|
selfId = event.selfId;
|
|
10912
10895
|
contact = event.contact;
|
|
@@ -10915,7 +10898,7 @@ var uploadFile = async (event, file, videoUrl, options) => {
|
|
|
10915
10898
|
const Duration = await getMediaDuration(file.filepath);
|
|
10916
10899
|
logger.warn(logger.yellow(`视频大小 (${file.totalBytes} MB) 触发压缩条件(设定值:${Config.app.compresstrigger} MB),正在进行压缩至${Config.app.compressvalue} MB...`));
|
|
10917
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("")];
|
|
10918
|
-
const msg1 = await karin
|
|
10901
|
+
const msg1 = await karin.sendMsg(selfId, contact, message);
|
|
10919
10902
|
const targetBitrate = Common.calculateBitrate(Config.app.compresstrigger, Duration) * .75;
|
|
10920
10903
|
const startTime = Date.now();
|
|
10921
10904
|
const outputPath = `${Common.tempDri.video}tmp_${Date.now()}.mp4`;
|
|
@@ -10929,7 +10912,7 @@ var uploadFile = async (event, file, videoUrl, options) => {
|
|
|
10929
10912
|
newFileSize = await Common.getVideoFileSize(file.filepath);
|
|
10930
10913
|
logger.debug(`原始视频大小为: ${file.totalBytes.toFixed(1)} MB, ${logger.green(`经 FFmpeg 压缩后最终视频大小为: ${newFileSize.toFixed(1)} MB,原视频文件已删除`)}`);
|
|
10931
10914
|
const message2 = [segment.text(`压缩后最终视频大小为: ${newFileSize.toFixed(1)} MB,压缩耗时:${((endTime - startTime) / 1e3).toFixed(1)} 秒`), segment.reply(msg1.messageId)];
|
|
10932
|
-
await karin
|
|
10915
|
+
await karin.sendMsg(selfId, contact, message2);
|
|
10933
10916
|
}
|
|
10934
10917
|
if (options) options.useGroupFile = Config.app.usegroupfile && newFileSize > Config.app.groupfilevalue;
|
|
10935
10918
|
if (Config.app.videoSendMode === "base64" && !options?.useGroupFile) {
|
|
@@ -10938,12 +10921,12 @@ var uploadFile = async (event, file, videoUrl, options) => {
|
|
|
10938
10921
|
} else File = options?.useGroupFile ? file.filepath : `file://${file.filepath}`;
|
|
10939
10922
|
try {
|
|
10940
10923
|
if (options?.active) if (options.useGroupFile) {
|
|
10941
|
-
const bot = karin
|
|
10924
|
+
const bot = karin.getBot(String(options.activeOption?.uin));
|
|
10942
10925
|
logger.mark(`${logger.blue("主动消息:")} 视频大小: ${newFileSize.toFixed(1)}MB 正在通过${logger.yellow("bot.uploadFile")}回复...`);
|
|
10943
10926
|
await bot.uploadFile(contact, File, file.originTitle ? `${file.originTitle}.mp4` : `${File.split("/").pop()}`);
|
|
10944
10927
|
} else {
|
|
10945
10928
|
logger.mark(`${logger.blue("主动消息:")} 视频大小: ${newFileSize.toFixed(1)}MB 正在通过${logger.yellow("karin.sendMsg")}回复...`);
|
|
10946
|
-
sendStatus = (await karin
|
|
10929
|
+
sendStatus = (await karin.sendMsg(selfId, contact, [segment.video(File)], { retryCount: 0 })).messageId ? true : false;
|
|
10947
10930
|
}
|
|
10948
10931
|
else if (options?.useGroupFile) {
|
|
10949
10932
|
logger.mark(`${logger.blue("被动消息:")} 视频大小: ${newFileSize.toFixed(1)}MB 正在通过${logger.yellow("e.bot.uploadFile")}回复...`);
|
|
@@ -10984,8 +10967,8 @@ var downloadVideo = async (event, downloadOpt, uploadOpt) => {
|
|
|
10984
10967
|
if (fileSizeContent > 0 && Config.app.usefilelimit && fileSize > Config.app.filelimit) {
|
|
10985
10968
|
const message = segment.text(`视频:「${downloadOpt.title.originTitle ?? "Error: 文件名获取失败"}」大小 (${fileSizeInMB} MB) 超出最大限制(设定值:${Config.app.filelimit} MB),已取消上传`);
|
|
10986
10969
|
const selfId = event.selfId || uploadOpt?.activeOption?.uin;
|
|
10987
|
-
const contact = event.contact || karin
|
|
10988
|
-
await karin
|
|
10970
|
+
const contact = event.contact || karin.contactGroup(uploadOpt?.activeOption?.group_id) || karin.contactFriend(selfId);
|
|
10971
|
+
await karin.sendMsg(selfId, contact, message);
|
|
10989
10972
|
return false;
|
|
10990
10973
|
}
|
|
10991
10974
|
let res = await downloadFile(downloadOpt.video_url, {
|
|
@@ -11140,7 +11123,7 @@ var Common = new class Tools {
|
|
|
11140
11123
|
try {
|
|
11141
11124
|
logger.debug(`检测到${source}为图片,尝试识别二维码...`);
|
|
11142
11125
|
const response = await axios.get(imageUrl, { responseType: "arraybuffer" });
|
|
11143
|
-
const qrContent =
|
|
11126
|
+
const qrContent = scanSync(Buffer.from(response.data));
|
|
11144
11127
|
if (qrContent && [
|
|
11145
11128
|
/(https?:\/\/)?(www|v|jx|m|jingxuan)\.(douyin|iesdouyin)\.com/i,
|
|
11146
11129
|
/https:\/\/aweme\.snssdk\.com\/aweme\/v1\/play/i,
|
|
@@ -12533,6 +12516,7 @@ var ImageDownloader = class {
|
|
|
12533
12516
|
* @returns 处理后的图片路径(HTTP URL / file:// 协议 / base64://)
|
|
12534
12517
|
*/
|
|
12535
12518
|
async processImage(imageUrl, title, index) {
|
|
12519
|
+
if (!/^https?:\/\//i.test(imageUrl)) return imageUrl;
|
|
12536
12520
|
switch (Config.app.imageSendMode) {
|
|
12537
12521
|
case "base64": try {
|
|
12538
12522
|
return await this.downloadAndConvertToBase64(imageUrl);
|
|
@@ -12979,6 +12963,20 @@ function getImageDownloader() {
|
|
|
12979
12963
|
async function processImageUrl(imageUrl, title, index) {
|
|
12980
12964
|
return await getImageDownloader().processImage(imageUrl, title, index);
|
|
12981
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
|
+
}
|
|
12982
12980
|
//#endregion
|
|
12983
12981
|
//#region ../template/src/dev/preview/utils/time.ts
|
|
12984
12982
|
var import_react = /* @__PURE__ */ __toESM(require_react(), 1);
|
|
@@ -15548,7 +15546,7 @@ var renderRichTextToReact = (document, options = {}) => {
|
|
|
15548
15546
|
* @return {string} The base64-encoded QR code image.
|
|
15549
15547
|
*/
|
|
15550
15548
|
var generateQRCode = (text, useDarkTheme = false) => {
|
|
15551
|
-
return `data:image/webp;base64,${
|
|
15549
|
+
return `data:image/webp;base64,${generateSync({
|
|
15552
15550
|
data: text,
|
|
15553
15551
|
size: 1e3,
|
|
15554
15552
|
dotsOptions: {
|
|
@@ -23818,6 +23816,37 @@ var InlineCalloutCode = ({ children, className }) => /* @__PURE__ */ (0, import_
|
|
|
23818
23816
|
},
|
|
23819
23817
|
children
|
|
23820
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
|
+
];
|
|
23821
23850
|
/**
|
|
23822
23851
|
* 更新日志组件
|
|
23823
23852
|
* @param props 组件属性
|
|
@@ -23825,6 +23854,7 @@ var InlineCalloutCode = ({ children, className }) => /* @__PURE__ */ (0, import_
|
|
|
23825
23854
|
*/
|
|
23826
23855
|
var Changelog = import_react.memo((props) => {
|
|
23827
23856
|
const isDark = props.data.useDarkTheme ?? false;
|
|
23857
|
+
const isUpdateTip = props.data.Tip === true;
|
|
23828
23858
|
const share_url = props.data?.share_url || "";
|
|
23829
23859
|
const backgroundColors = isDark ? {
|
|
23830
23860
|
base: "#0a0a0a",
|
|
@@ -23943,7 +23973,7 @@ var Changelog = import_react.memo((props) => {
|
|
|
23943
23973
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
23944
23974
|
className: "relative px-16 pt-5 pb-0 w-full max-w-none prose prose-lg prose-invert from-surface to-surface",
|
|
23945
23975
|
children: [
|
|
23946
|
-
|
|
23976
|
+
isUpdateTip ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
23947
23977
|
className: "pt-32",
|
|
23948
23978
|
children: [
|
|
23949
23979
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
@@ -24108,7 +24138,7 @@ var Changelog = import_react.memo((props) => {
|
|
|
24108
24138
|
a: ({ children, href, ...props }) => {
|
|
24109
24139
|
const isVersionLink = href?.includes("/compare/");
|
|
24110
24140
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", {
|
|
24111
|
-
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"}`,
|
|
24112
24142
|
onClick: (e) => e.preventDefault(),
|
|
24113
24143
|
...props,
|
|
24114
24144
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children })
|
|
@@ -24137,8 +24167,81 @@ var Changelog = import_react.memo((props) => {
|
|
|
24137
24167
|
children: props.data?.markdown ?? ""
|
|
24138
24168
|
})
|
|
24139
24169
|
}),
|
|
24140
|
-
share_url && /* @__PURE__ */ (0, import_jsx_runtime.
|
|
24141
|
-
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",
|
|
24142
24245
|
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
24143
24246
|
className: "w-120 h-auto",
|
|
24144
24247
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
|
|
@@ -24162,8 +24265,8 @@ var Changelog = import_react.memo((props) => {
|
|
|
24162
24265
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: " 的差异" })
|
|
24163
24266
|
]
|
|
24164
24267
|
})]
|
|
24165
|
-
}),
|
|
24166
|
-
|
|
24268
|
+
}) }),
|
|
24269
|
+
isUpdateTip && props.data.buildTime && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
24167
24270
|
className: "flex gap-8 justify-center text-foreground/60",
|
|
24168
24271
|
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
24169
24272
|
className: "text-4xl",
|
|
@@ -32814,6 +32917,14 @@ var cleanOldDynamicCache = async (platform, days = 7) => {
|
|
|
32814
32917
|
};
|
|
32815
32918
|
//#endregion
|
|
32816
32919
|
//#region src/web.config.ts
|
|
32920
|
+
var resolveRealPath = (value) => {
|
|
32921
|
+
try {
|
|
32922
|
+
return fs.realpathSync.native(value);
|
|
32923
|
+
} catch {
|
|
32924
|
+
return path.resolve(value);
|
|
32925
|
+
}
|
|
32926
|
+
};
|
|
32927
|
+
var isLocalDevelopment = process.env.NODE_ENV === "development" && resolveRealPath(Root.pluginPath) === resolveRealPath(process.cwd());
|
|
32817
32928
|
var webConfig = defineConfig({
|
|
32818
32929
|
info: {
|
|
32819
32930
|
id: "karin-plugin-kkk",
|
|
@@ -32835,7 +32946,7 @@ var webConfig = defineConfig({
|
|
|
32835
32946
|
}]
|
|
32836
32947
|
},
|
|
32837
32948
|
page: {
|
|
32838
|
-
url:
|
|
32949
|
+
url: isLocalDevelopment ? "http://localhost:5176/kkk/assets/karin-config" : "/kkk/assets/karin-config",
|
|
32839
32950
|
title: "kkk插件配置管理",
|
|
32840
32951
|
description: "使用 kkk 插件自带的配置管理页面"
|
|
32841
32952
|
}
|
|
@@ -32947,7 +33058,7 @@ var renderErrorImage = async (ctx, opts = {}) => {
|
|
|
32947
33058
|
* @returns
|
|
32948
33059
|
*/
|
|
32949
33060
|
var getCandidateBots = () => {
|
|
32950
|
-
return karin
|
|
33061
|
+
return karin.getAllBotList().map((item) => item.bot).filter((bot) => bot.account.name !== "console");
|
|
32951
33062
|
};
|
|
32952
33063
|
/**
|
|
32953
33064
|
* 获取非console主机器人ID列表
|
|
@@ -32995,7 +33106,7 @@ var getReachableMasterBots = async (masters = config.master()) => {
|
|
|
32995
33106
|
*/
|
|
32996
33107
|
var resolveUsableBot = async (selfId) => {
|
|
32997
33108
|
if (selfId) {
|
|
32998
|
-
const matchedBot = karin
|
|
33109
|
+
const matchedBot = karin.getBot(selfId);
|
|
32999
33110
|
if (matchedBot) return matchedBot;
|
|
33000
33111
|
}
|
|
33001
33112
|
const reachable = await getReachableMasterBots();
|
|
@@ -33003,12 +33114,12 @@ var resolveUsableBot = async (selfId) => {
|
|
|
33003
33114
|
const { douyin, bilibili } = statBotId$1(Config.pushlist);
|
|
33004
33115
|
const preferredBotId = douyin.botId || bilibili.botId;
|
|
33005
33116
|
if (preferredBotId) {
|
|
33006
|
-
const matchedBot = karin
|
|
33117
|
+
const matchedBot = karin.getBot(preferredBotId);
|
|
33007
33118
|
if (matchedBot) return matchedBot;
|
|
33008
33119
|
}
|
|
33009
|
-
const fallbackBotId = karin
|
|
33120
|
+
const fallbackBotId = karin.getAllBotID()[0];
|
|
33010
33121
|
if (!fallbackBotId) return void 0;
|
|
33011
|
-
return karin
|
|
33122
|
+
return karin.getBot(fallbackBotId);
|
|
33012
33123
|
};
|
|
33013
33124
|
//#endregion
|
|
33014
33125
|
//#region src/module/utils/ErrorHandler/utils.ts
|
|
@@ -33093,7 +33204,7 @@ var injectBotToEventForPushTask = async (event, businessName) => {
|
|
|
33093
33204
|
if (!isPushTask(event, businessName)) return event;
|
|
33094
33205
|
if (event?.bot) return event;
|
|
33095
33206
|
const preferredBotId = typeof event?.selfId === "string" ? event.selfId : getPushTaskBotId();
|
|
33096
|
-
const bot = (preferredBotId ? karin
|
|
33207
|
+
const bot = (preferredBotId ? karin.getBot(preferredBotId) : void 0) ?? await resolveUsableBot(preferredBotId);
|
|
33097
33208
|
if (!bot) throw new Error(`[ErrorHandler] push 任务缺少可用 bot 实例: ${businessName}`);
|
|
33098
33209
|
const normalizedEvent = event ?? {};
|
|
33099
33210
|
normalizedEvent.bot = bot;
|
|
@@ -33147,7 +33258,7 @@ var sendErrorToMaster = async (ctx, img, customPrefix) => {
|
|
|
33147
33258
|
if (!target) return;
|
|
33148
33259
|
try {
|
|
33149
33260
|
const prefix = customPrefix || await buildErrorPrefix(ctx, isPush, target.botId);
|
|
33150
|
-
await karin
|
|
33261
|
+
await karin.sendMaster(target.botId, target.master, [segment.text(prefix), ...img]);
|
|
33151
33262
|
} catch (err) {
|
|
33152
33263
|
logger.error(`[ErrorHandler] 发送错误消息给主人失败: ${err}`);
|
|
33153
33264
|
}
|
|
@@ -33182,7 +33293,7 @@ var sendErrorToAllMasters = async (ctx, img, customPrefix) => {
|
|
|
33182
33293
|
const key = `${target.botId}:${target.master}`;
|
|
33183
33294
|
if (notifiedSet.has(key)) continue;
|
|
33184
33295
|
try {
|
|
33185
|
-
await karin
|
|
33296
|
+
await karin.sendMaster(target.botId, target.master, [segment.text(prefix), ...img]);
|
|
33186
33297
|
notifiedSet.add(key);
|
|
33187
33298
|
logger.debug(`[ErrorHandler] 已发送错误消息给主人: ${target.master} (via ${target.botId})`);
|
|
33188
33299
|
} catch (err) {
|
|
@@ -33233,7 +33344,7 @@ var buildErrorPrefix = async (ctx, isPush, botId) => {
|
|
|
33233
33344
|
const { options, event } = ctx;
|
|
33234
33345
|
if (isPush) return `${options.businessName} 任务执行出错\n请尽快解决以消除警告`;
|
|
33235
33346
|
const groupId = event && "groupId" in event ? event.groupId : "";
|
|
33236
|
-
return `群:${(await karin
|
|
33347
|
+
return `群:${(await karin.getBot(botId)?.getGroupInfo(groupId))?.groupName || "未知"}(${groupId})\n${options.businessName} 任务执行出错\n请尽快解决以消除警告`;
|
|
33237
33348
|
};
|
|
33238
33349
|
//#endregion
|
|
33239
33350
|
//#region src/module/utils/ErrorHandler/handler.ts
|
|
@@ -34199,6 +34310,139 @@ var buildBilibiliArticleRichText = (opus, content, useDarkTheme) => {
|
|
|
34199
34310
|
if (content) return parseHtmlContentToRichText(content);
|
|
34200
34311
|
return createRichTextDocument([], { platform: "bilibili" });
|
|
34201
34312
|
};
|
|
34313
|
+
var MAX_FORWARD_TEXT_LENGTH = 1800;
|
|
34314
|
+
var normalizeForwardText = (text) => {
|
|
34315
|
+
return text.replace(/\r\n/g, "\n").replace(/[ \t]+\n/g, "\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
34316
|
+
};
|
|
34317
|
+
var splitForwardText = (text) => {
|
|
34318
|
+
const chunks = [];
|
|
34319
|
+
let rest = text;
|
|
34320
|
+
while (rest.length > MAX_FORWARD_TEXT_LENGTH) {
|
|
34321
|
+
let splitAt = rest.lastIndexOf("\n\n", MAX_FORWARD_TEXT_LENGTH);
|
|
34322
|
+
if (splitAt < MAX_FORWARD_TEXT_LENGTH / 2) splitAt = rest.lastIndexOf("\n", MAX_FORWARD_TEXT_LENGTH);
|
|
34323
|
+
if (splitAt < MAX_FORWARD_TEXT_LENGTH / 2) splitAt = MAX_FORWARD_TEXT_LENGTH;
|
|
34324
|
+
const chunk = rest.slice(0, splitAt).trim();
|
|
34325
|
+
if (chunk) chunks.push(chunk);
|
|
34326
|
+
rest = rest.slice(splitAt).trim();
|
|
34327
|
+
}
|
|
34328
|
+
if (rest) chunks.push(rest);
|
|
34329
|
+
return chunks;
|
|
34330
|
+
};
|
|
34331
|
+
var formatRichTextLink = (text, url) => {
|
|
34332
|
+
if (!url || url === text) return text;
|
|
34333
|
+
return `${text} (${url})`;
|
|
34334
|
+
};
|
|
34335
|
+
var inlineRichTextNodeToText = (node) => {
|
|
34336
|
+
switch (node.type) {
|
|
34337
|
+
case "text":
|
|
34338
|
+
case "mention":
|
|
34339
|
+
case "searchKeyword":
|
|
34340
|
+
case "topic":
|
|
34341
|
+
case "at":
|
|
34342
|
+
case "lottery":
|
|
34343
|
+
case "vote":
|
|
34344
|
+
case "viewPicture":
|
|
34345
|
+
case "hashtag": return node.text;
|
|
34346
|
+
case "emoji": return node.name;
|
|
34347
|
+
case "webLink": return formatRichTextLink(node.text, node.jumpUrl);
|
|
34348
|
+
case "lineBreak": return "\n";
|
|
34349
|
+
default: return "";
|
|
34350
|
+
}
|
|
34351
|
+
};
|
|
34352
|
+
/**
|
|
34353
|
+
* 将共享富文本文档转换为 Karin 消息段。
|
|
34354
|
+
*
|
|
34355
|
+
* 这里用于专栏正文的合并转发:文本节点保留为 text,图片节点保留为 image,
|
|
34356
|
+
* 让用户在客户端里能按原文顺序查看图文内容,而不是只能看渲染长图。
|
|
34357
|
+
*/
|
|
34358
|
+
var buildBilibiliRichTextForwardMessage = async (document, options = {}) => {
|
|
34359
|
+
const elements = [];
|
|
34360
|
+
let textBuffer = "";
|
|
34361
|
+
let imageIndex = 0;
|
|
34362
|
+
const appendText = (text) => {
|
|
34363
|
+
if (!text) return;
|
|
34364
|
+
textBuffer += text;
|
|
34365
|
+
};
|
|
34366
|
+
const ensureBlockBreak = () => {
|
|
34367
|
+
if (!textBuffer) return;
|
|
34368
|
+
if (textBuffer.endsWith("\n\n")) return;
|
|
34369
|
+
textBuffer += textBuffer.endsWith("\n") ? "\n" : "\n\n";
|
|
34370
|
+
};
|
|
34371
|
+
const flushText = () => {
|
|
34372
|
+
const text = normalizeForwardText(textBuffer);
|
|
34373
|
+
textBuffer = "";
|
|
34374
|
+
for (const chunk of splitForwardText(text)) elements.push(segment.text(chunk));
|
|
34375
|
+
};
|
|
34376
|
+
const appendChildren = async (nodes) => {
|
|
34377
|
+
for (const node of nodes) await appendNode(node);
|
|
34378
|
+
};
|
|
34379
|
+
const appendImage = async (src, caption) => {
|
|
34380
|
+
flushText();
|
|
34381
|
+
const imageUrl = options.imageResolver ? await options.imageResolver(src, imageIndex) : src;
|
|
34382
|
+
imageIndex += 1;
|
|
34383
|
+
elements.push(segment.image(imageUrl));
|
|
34384
|
+
if (caption) {
|
|
34385
|
+
appendText(caption);
|
|
34386
|
+
ensureBlockBreak();
|
|
34387
|
+
}
|
|
34388
|
+
};
|
|
34389
|
+
const appendNode = async (node) => {
|
|
34390
|
+
const inlineText = inlineRichTextNodeToText(node);
|
|
34391
|
+
if (inlineText) {
|
|
34392
|
+
appendText(inlineText);
|
|
34393
|
+
return;
|
|
34394
|
+
}
|
|
34395
|
+
switch (node.type) {
|
|
34396
|
+
case "heading":
|
|
34397
|
+
case "paragraph":
|
|
34398
|
+
case "blockquote":
|
|
34399
|
+
case "listItem":
|
|
34400
|
+
ensureBlockBreak();
|
|
34401
|
+
await appendChildren(node.nodes);
|
|
34402
|
+
ensureBlockBreak();
|
|
34403
|
+
break;
|
|
34404
|
+
case "image":
|
|
34405
|
+
if (node.src) await appendImage(node.src, node.caption);
|
|
34406
|
+
break;
|
|
34407
|
+
case "list":
|
|
34408
|
+
ensureBlockBreak();
|
|
34409
|
+
for (const [index, item] of node.items.entries()) {
|
|
34410
|
+
appendText(node.ordered ? `${index + 1}. ` : "- ");
|
|
34411
|
+
await appendChildren(item.nodes);
|
|
34412
|
+
appendText("\n");
|
|
34413
|
+
}
|
|
34414
|
+
ensureBlockBreak();
|
|
34415
|
+
break;
|
|
34416
|
+
case "codeBlock":
|
|
34417
|
+
ensureBlockBreak();
|
|
34418
|
+
appendText(node.content);
|
|
34419
|
+
ensureBlockBreak();
|
|
34420
|
+
break;
|
|
34421
|
+
case "linkCard":
|
|
34422
|
+
ensureBlockBreak();
|
|
34423
|
+
appendText(formatRichTextLink(node.title, node.url));
|
|
34424
|
+
ensureBlockBreak();
|
|
34425
|
+
break;
|
|
34426
|
+
case "horizontalRule":
|
|
34427
|
+
ensureBlockBreak();
|
|
34428
|
+
appendText("---");
|
|
34429
|
+
ensureBlockBreak();
|
|
34430
|
+
break;
|
|
34431
|
+
default: break;
|
|
34432
|
+
}
|
|
34433
|
+
};
|
|
34434
|
+
const headerLines = [];
|
|
34435
|
+
if (options.title) headerLines.push(`标题:${options.title}`);
|
|
34436
|
+
if (options.summary) headerLines.push(`简介:${options.summary}`);
|
|
34437
|
+
if (options.shareUrl) headerLines.push(`链接:${options.shareUrl}`);
|
|
34438
|
+
if (headerLines.length > 0) {
|
|
34439
|
+
appendText(headerLines.join("\n"));
|
|
34440
|
+
ensureBlockBreak();
|
|
34441
|
+
}
|
|
34442
|
+
await appendChildren(document.nodes);
|
|
34443
|
+
flushText();
|
|
34444
|
+
return elements;
|
|
34445
|
+
};
|
|
34202
34446
|
//#endregion
|
|
34203
34447
|
//#region src/platform/bilibili/bilibili.ts
|
|
34204
34448
|
var img$1;
|
|
@@ -34414,7 +34658,7 @@ var Bilibili = class extends Base {
|
|
|
34414
34658
|
length: videoInfo.data.result.episodes.length
|
|
34415
34659
|
});
|
|
34416
34660
|
this.e.reply([...img$1, segment.text("请在120秒内输入 第?集 选择集数")]);
|
|
34417
|
-
const context = await karin
|
|
34661
|
+
const context = await karin.ctx(this.e, {
|
|
34418
34662
|
reply: true,
|
|
34419
34663
|
throwOnTimeout: false
|
|
34420
34664
|
});
|
|
@@ -34541,7 +34785,7 @@ var Bilibili = class extends Base {
|
|
|
34541
34785
|
filepath: motionPhotoCoverPath,
|
|
34542
34786
|
totalBytes: 0
|
|
34543
34787
|
});
|
|
34544
|
-
const motionPhotoCover =
|
|
34788
|
+
const motionPhotoCover = processLocalImageFile(motionPhotoCoverPath);
|
|
34545
34789
|
imgArray.push(segment.image(motionPhotoCover));
|
|
34546
34790
|
hasPushedMotionPhotoCover = true;
|
|
34547
34791
|
}
|
|
@@ -34901,28 +35145,19 @@ var Bilibili = class extends Base {
|
|
|
34901
35145
|
const articleData = articleInfoBase.data.data;
|
|
34902
35146
|
const articleContent = articleInfo.data.data;
|
|
34903
35147
|
const body = buildBilibiliArticleRichText(articleContent.opus, articleContent.content, Common.useDarkTheme());
|
|
34904
|
-
const extractImagesFromBody = (nodes) => {
|
|
34905
|
-
const images = [];
|
|
34906
|
-
for (const node of nodes) {
|
|
34907
|
-
if (node.type === "image" && node.src) images.push(node.src);
|
|
34908
|
-
if (node.nodes) images.push(...extractImagesFromBody(node.nodes));
|
|
34909
|
-
if (node.items) images.push(...extractImagesFromBody(node.items));
|
|
34910
|
-
}
|
|
34911
|
-
return images;
|
|
34912
|
-
};
|
|
34913
|
-
const messageElements = [];
|
|
34914
|
-
const articleImages = extractImagesFromBody(body.nodes);
|
|
34915
35148
|
const title = articleData.title || "bilibili_article";
|
|
34916
|
-
|
|
34917
|
-
|
|
34918
|
-
|
|
34919
|
-
|
|
34920
|
-
|
|
34921
|
-
|
|
35149
|
+
const shareUrl = articleContent.dyn_id_str ? `https://www.bilibili.com/opus/${articleContent.dyn_id_str}` : `https://www.bilibili.com/read/cv${articleContent.id}`;
|
|
35150
|
+
const messageElements = await buildBilibiliRichTextForwardMessage(body, {
|
|
35151
|
+
title: articleData.title,
|
|
35152
|
+
summary: articleData.summary,
|
|
35153
|
+
shareUrl,
|
|
35154
|
+
imageResolver: (src, index) => processImageUrl(src, title, index)
|
|
35155
|
+
});
|
|
35156
|
+
if (messageElements.length > 0) {
|
|
34922
35157
|
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);
|
|
34923
35158
|
await this.e.bot.sendForwardMsg(this.e.contact, forwardMsg, {
|
|
34924
|
-
source: "
|
|
34925
|
-
summary: `查看${messageElements.length}
|
|
35159
|
+
source: "专栏内容",
|
|
35160
|
+
summary: `查看${messageElements.length}条专栏内容`,
|
|
34926
35161
|
prompt: "B站专栏动态解析结果",
|
|
34927
35162
|
news: [{ text: "点击查看解析结果" }]
|
|
34928
35163
|
});
|
|
@@ -34940,7 +35175,7 @@ var Bilibili = class extends Base {
|
|
|
34940
35175
|
body,
|
|
34941
35176
|
stats: articleData.stats,
|
|
34942
35177
|
render_time: TimeFormatter.now(),
|
|
34943
|
-
share_url:
|
|
35178
|
+
share_url: shareUrl,
|
|
34944
35179
|
dynamicTYPE: "专栏动态解析",
|
|
34945
35180
|
user_shortid: userProfileData.data.data.card.mid,
|
|
34946
35181
|
total_favorited: Count(userProfileData.data.data.like_num),
|
|
@@ -35141,9 +35376,9 @@ var Bilibili = class extends Base {
|
|
|
35141
35376
|
}
|
|
35142
35377
|
case false:
|
|
35143
35378
|
/** 没登录(没配置ck)情况下直接发直链,传直链在DownLoadVideo()处理 */
|
|
35144
|
-
logger.debug("视频 URL:", playUrlData.durl[0].url);
|
|
35379
|
+
logger.debug("视频 URL:", playUrlData.data.durl[0].url);
|
|
35145
35380
|
if ((this.forceBurnDanmaku || Config.bilibili.burnDanmaku) && danmakuList.length > 0) {
|
|
35146
|
-
const videoFile = await downloadFile(playUrlData.durl[0].url, {
|
|
35381
|
+
const videoFile = await downloadFile(playUrlData.data.durl[0].url, {
|
|
35147
35382
|
title: `Bil_V_tmp_${Date.now()}.mp4`,
|
|
35148
35383
|
headers: this.headers
|
|
35149
35384
|
});
|
|
@@ -35175,7 +35410,7 @@ var Bilibili = class extends Base {
|
|
|
35175
35410
|
} else await Common.removeFile(videoFile.filepath, true);
|
|
35176
35411
|
}
|
|
35177
35412
|
} else await downloadVideo(this.e, {
|
|
35178
|
-
video_url: playUrlData.durl[0].url,
|
|
35413
|
+
video_url: playUrlData.data.durl[0].url,
|
|
35179
35414
|
title: {
|
|
35180
35415
|
timestampTitle: `tmp_${Date.now()}.mp4`,
|
|
35181
35416
|
originTitle: `${this.downloadfilename}.mp4`
|
|
@@ -35507,32 +35742,6 @@ var getStringDisplayWidth$1 = (str) => {
|
|
|
35507
35742
|
}
|
|
35508
35743
|
return width;
|
|
35509
35744
|
};
|
|
35510
|
-
/**
|
|
35511
|
-
* 提取专栏中的所有图片URL
|
|
35512
|
-
* @param content
|
|
35513
|
-
* @returns
|
|
35514
|
-
*/
|
|
35515
|
-
var extractArticleImages = (content) => {
|
|
35516
|
-
const images = [];
|
|
35517
|
-
if (content.opus?.content?.paragraphs) {
|
|
35518
|
-
for (const paragraph of content.opus.content.paragraphs) if (paragraph.para_type === 2 && paragraph.pic?.pics) {
|
|
35519
|
-
for (const pic of paragraph.pic.pics) if (pic.url) {
|
|
35520
|
-
const url = pic.url.startsWith("//") ? `https:${pic.url}` : pic.url;
|
|
35521
|
-
images.push(url);
|
|
35522
|
-
}
|
|
35523
|
-
}
|
|
35524
|
-
}
|
|
35525
|
-
if (content.content && typeof content.content === "string") {
|
|
35526
|
-
const imgRegex = /<img[^>]+src="([^"]+)"/gi;
|
|
35527
|
-
let match;
|
|
35528
|
-
while ((match = imgRegex.exec(content.content)) !== null) {
|
|
35529
|
-
let url = match[1];
|
|
35530
|
-
if (url.startsWith("//")) url = `https:${url}`;
|
|
35531
|
-
images.push(url);
|
|
35532
|
-
}
|
|
35533
|
-
}
|
|
35534
|
-
return images;
|
|
35535
|
-
};
|
|
35536
35745
|
//#endregion
|
|
35537
35746
|
//#region src/platform/bilibili/comments.ts
|
|
35538
35747
|
/**
|
|
@@ -36057,7 +36266,7 @@ var Bilibilipush = class extends Base {
|
|
|
36057
36266
|
injectBotToEventForRender(targets) {
|
|
36058
36267
|
const targetBotId = targets.find((item) => item.botId)?.botId;
|
|
36059
36268
|
if (!targetBotId) return;
|
|
36060
|
-
const bot = karin
|
|
36269
|
+
const bot = karin.getBot(targetBotId);
|
|
36061
36270
|
if (!bot) return;
|
|
36062
36271
|
const eventWithBot = this.e;
|
|
36063
36272
|
eventWithBot.bot = bot;
|
|
@@ -36094,7 +36303,7 @@ var Bilibilipush = class extends Base {
|
|
|
36094
36303
|
this.ensureConfigFields(Config.pushlist.bilibili);
|
|
36095
36304
|
const deletedCount = await cleanOldDynamicCache("bilibili");
|
|
36096
36305
|
if (deletedCount > 0) logger.info(`已清理 ${deletedCount} 条过期的B站动态缓存记录`);
|
|
36097
|
-
const registeredBotIds = karin
|
|
36306
|
+
const registeredBotIds = karin.getAllBotID();
|
|
36098
36307
|
const filteredPushList = this.filterPushListByRegisteredBots(Config.pushlist.bilibili, registeredBotIds);
|
|
36099
36308
|
if (filteredPushList.length === 0) {
|
|
36100
36309
|
logger.warn("没有已注册的 bot 可用于B站推送");
|
|
@@ -36153,6 +36362,7 @@ var Bilibilipush = class extends Base {
|
|
|
36153
36362
|
if (skip) logger.warn(`动态 https://t.bilibili.com/${dynamicId} 已被处理,跳过`);
|
|
36154
36363
|
let send_video = true;
|
|
36155
36364
|
let img = [];
|
|
36365
|
+
let articleForwardPayload = null;
|
|
36156
36366
|
this.injectBotToEventForRender(data[dynamicId].targets);
|
|
36157
36367
|
if (!skip) {
|
|
36158
36368
|
const userINFO = await this.amagi.bilibili.fetcher.fetchUserCard({
|
|
@@ -36481,6 +36691,14 @@ var Bilibilipush = class extends Base {
|
|
|
36481
36691
|
});
|
|
36482
36692
|
const articleData = articleInfoBase.data.data;
|
|
36483
36693
|
const articleContent = articleInfo.data.data;
|
|
36694
|
+
const body = buildBilibiliArticleRichText(articleContent.opus, articleContent.content, Common.useDarkTheme());
|
|
36695
|
+
const shareUrl = articleContent.dyn_id_str ? `https://www.bilibili.com/opus/${articleContent.dyn_id_str}` : `https://www.bilibili.com/read/cv${articleContent.id}`;
|
|
36696
|
+
articleForwardPayload = {
|
|
36697
|
+
body,
|
|
36698
|
+
title: articleData.title,
|
|
36699
|
+
summary: articleData.summary,
|
|
36700
|
+
shareUrl
|
|
36701
|
+
};
|
|
36484
36702
|
img = await Render(this.e, "bilibili/dynamic/DYNAMIC_TYPE_ARTICLE", {
|
|
36485
36703
|
usernameMeta: getUsernameMetadata(data[dynamicId].Dynamic_Data.modules.module_author),
|
|
36486
36704
|
avatar_url: data[dynamicId].Dynamic_Data.modules.module_author.face,
|
|
@@ -36495,10 +36713,10 @@ var Bilibilipush = class extends Base {
|
|
|
36495
36713
|
banner_url: articleData.banner_url || articleData.image_urls && articleData.image_urls[0] || "",
|
|
36496
36714
|
categories: articleData.categories || [],
|
|
36497
36715
|
words: articleData.words || 0,
|
|
36498
|
-
body
|
|
36716
|
+
body,
|
|
36499
36717
|
stats: articleData.stats,
|
|
36500
36718
|
render_time: TimeFormatter.now(),
|
|
36501
|
-
share_url:
|
|
36719
|
+
share_url: shareUrl,
|
|
36502
36720
|
dynamicTYPE: "专栏动态推送"
|
|
36503
36721
|
}, { skipWatermark: true });
|
|
36504
36722
|
break;
|
|
@@ -36516,13 +36734,23 @@ var Bilibilipush = class extends Base {
|
|
|
36516
36734
|
let status = null;
|
|
36517
36735
|
if (!skip) {
|
|
36518
36736
|
const { groupId, botId } = target;
|
|
36519
|
-
const bot = karin
|
|
36520
|
-
const Contact = karin
|
|
36737
|
+
const bot = karin.getBot(botId);
|
|
36738
|
+
const Contact = karin.contactGroup(groupId);
|
|
36521
36739
|
const eventWithBot = this.e;
|
|
36522
36740
|
eventWithBot.bot = bot;
|
|
36523
36741
|
eventWithBot.selfId = botId;
|
|
36524
36742
|
const watermarkedImg = img ? applyWatermarkToImages(img, this.e) : [];
|
|
36525
|
-
|
|
36743
|
+
const parseUrl = buildParseUrl(data[dynamicId]);
|
|
36744
|
+
const parseButton = bot?.adapter?.name === "QQ Official Bot" && parseUrl ? [segment.button([{
|
|
36745
|
+
text: "解析",
|
|
36746
|
+
callback: true,
|
|
36747
|
+
data: `#解析${parseUrl}`
|
|
36748
|
+
}, {
|
|
36749
|
+
text: "帮助",
|
|
36750
|
+
callback: true,
|
|
36751
|
+
data: `#kkk帮助`
|
|
36752
|
+
}])] : [];
|
|
36753
|
+
status = await karin.sendMsg(botId, Contact, [...watermarkedImg, ...parseButton]);
|
|
36526
36754
|
if (Config.bilibili.push.parsedynamic && status.messageId) switch (data[dynamicId].dynamic_type) {
|
|
36527
36755
|
case "DYNAMIC_TYPE_AV":
|
|
36528
36756
|
if (send_video) {
|
|
@@ -36557,7 +36785,7 @@ var Bilibilipush = class extends Base {
|
|
|
36557
36785
|
/** 获取第一个视频流的大小 */
|
|
36558
36786
|
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);
|
|
36559
36787
|
if (Config.app.usefilelimit && Number(videoSize) > Number(Config.app.filelimit) && !Config.app.compress) {
|
|
36560
|
-
await karin
|
|
36788
|
+
await karin.sendMsg(botId, Contact, [segment.text(`设定的最大上传大小为 ${Config.app.filelimit}MB\n当前解析到的视频大小为 ${Number(videoSize)}MB\n视频太大了,还是去B站看吧~`), segment.reply(status.messageId)]);
|
|
36561
36789
|
break;
|
|
36562
36790
|
}
|
|
36563
36791
|
logger.mark(`当前处于自动推送状态,解析到的视频大小为 ${logger.yellow(Number(videoSize))} MB`);
|
|
@@ -36680,7 +36908,7 @@ var Bilibilipush = class extends Base {
|
|
|
36680
36908
|
filepath: motionPhotoCoverPath,
|
|
36681
36909
|
totalBytes: 0
|
|
36682
36910
|
});
|
|
36683
|
-
const motionPhotoCover =
|
|
36911
|
+
const motionPhotoCover = processLocalImageFile(motionPhotoCoverPath);
|
|
36684
36912
|
imgArray.push(segment.image(motionPhotoCover));
|
|
36685
36913
|
hasPushedMotionPhotoCover = true;
|
|
36686
36914
|
}
|
|
@@ -36721,23 +36949,35 @@ var Bilibilipush = class extends Base {
|
|
|
36721
36949
|
break;
|
|
36722
36950
|
}
|
|
36723
36951
|
case "DYNAMIC_TYPE_ARTICLE": {
|
|
36724
|
-
|
|
36725
|
-
|
|
36726
|
-
|
|
36727
|
-
|
|
36728
|
-
|
|
36729
|
-
|
|
36730
|
-
|
|
36731
|
-
|
|
36732
|
-
|
|
36733
|
-
|
|
36952
|
+
let payload = articleForwardPayload;
|
|
36953
|
+
if (!payload) {
|
|
36954
|
+
const articleInfoBase = await this.amagi.bilibili.fetcher.fetchArticleInfo({
|
|
36955
|
+
id: data[dynamicId].Dynamic_Data.basic.rid_str,
|
|
36956
|
+
typeMode: "strict"
|
|
36957
|
+
});
|
|
36958
|
+
const articleContent = (await this.amagi.bilibili.fetcher.fetchArticleContent({
|
|
36959
|
+
id: data[dynamicId].Dynamic_Data.basic.rid_str,
|
|
36960
|
+
typeMode: "strict"
|
|
36961
|
+
})).data.data;
|
|
36962
|
+
payload = {
|
|
36963
|
+
body: buildBilibiliArticleRichText(articleContent.opus, articleContent.content, Common.useDarkTheme()),
|
|
36964
|
+
title: articleInfoBase.data.data.title,
|
|
36965
|
+
summary: articleInfoBase.data.data.summary,
|
|
36966
|
+
shareUrl: articleContent.dyn_id_str ? `https://www.bilibili.com/opus/${articleContent.dyn_id_str}` : `https://www.bilibili.com/read/cv${articleContent.id}`
|
|
36967
|
+
};
|
|
36734
36968
|
}
|
|
36735
|
-
|
|
36736
|
-
|
|
36969
|
+
const title = payload.title || "bilibili_article";
|
|
36970
|
+
const messageElements = await buildBilibiliRichTextForwardMessage(payload.body, {
|
|
36971
|
+
title: payload.title,
|
|
36972
|
+
summary: payload.summary,
|
|
36973
|
+
shareUrl: payload.shareUrl,
|
|
36974
|
+
imageResolver: (src, index) => processImageUrl(src, title, index)
|
|
36975
|
+
});
|
|
36976
|
+
if (messageElements.length > 0) {
|
|
36737
36977
|
const forwardMsg = common.makeForward(messageElements, botId, bot.account.name);
|
|
36738
36978
|
await bot.sendForwardMsg(Contact, forwardMsg, {
|
|
36739
|
-
source: "
|
|
36740
|
-
summary: `查看${messageElements.length}
|
|
36979
|
+
source: "专栏内容",
|
|
36980
|
+
summary: `查看${messageElements.length}条专栏内容`,
|
|
36741
36981
|
prompt: "B站专栏动态解析结果",
|
|
36742
36982
|
news: [{ text: "点击查看解析结果" }]
|
|
36743
36983
|
});
|
|
@@ -36868,6 +37108,7 @@ var Bilibilipush = class extends Base {
|
|
|
36868
37108
|
} else {
|
|
36869
37109
|
await bilibiliDBInstance.subscribeBilibiliUser(groupId, botId, host_mid, data.data.card.name);
|
|
36870
37110
|
existingItem.group_id.push(`${groupId}:${botId}`);
|
|
37111
|
+
if (!existingItem.pushTypes || existingItem.pushTypes.length === 0) existingItem.pushTypes = [...allBilibiliPushTypes];
|
|
36871
37112
|
Config.Modify("pushlist", "bilibili", config.bilibili);
|
|
36872
37113
|
await this.e.reply(`群:${groupInfo.groupName}(${groupId})\n添加成功!${data.data.card.name}\nUID:${host_mid}`);
|
|
36873
37114
|
if (Config.bilibili.push.switch === false) await this.e.reply("请发送「#设置B站推送开启」以进行推送");
|
|
@@ -36879,7 +37120,8 @@ var Bilibilipush = class extends Base {
|
|
|
36879
37120
|
switch: true,
|
|
36880
37121
|
host_mid,
|
|
36881
37122
|
group_id: [`${groupId}:${botId}`],
|
|
36882
|
-
remark: data.data.card.name
|
|
37123
|
+
remark: data.data.card.name,
|
|
37124
|
+
pushTypes: [...allBilibiliPushTypes]
|
|
36883
37125
|
});
|
|
36884
37126
|
Config.Modify("pushlist", "bilibili", config.bilibili);
|
|
36885
37127
|
await this.e.reply(`群:${groupInfo.groupName}(${groupId})\n添加成功!${data.data.card.name}\nUID:${host_mid}`);
|
|
@@ -36989,6 +37231,22 @@ var br = (data) => {
|
|
|
36989
37231
|
return data = data.replace(/\n/g, "<br>");
|
|
36990
37232
|
};
|
|
36991
37233
|
/**
|
|
37234
|
+
* 根据动态类型构造用于「解析」按钮的地址。
|
|
37235
|
+
* 视频动态使用 BV 视频地址,其余动态使用动态地址;直播动态返回空字符串(不追加按钮)。
|
|
37236
|
+
* @param PushItem 推送项
|
|
37237
|
+
* @returns 解析地址,无法解析时返回空字符串
|
|
37238
|
+
*/
|
|
37239
|
+
var buildParseUrl = (PushItem) => {
|
|
37240
|
+
switch (PushItem.dynamic_type) {
|
|
37241
|
+
case DynamicType.AV: {
|
|
37242
|
+
const bvid = PushItem.Dynamic_Data.modules.module_dynamic.major?.archive?.bvid;
|
|
37243
|
+
return bvid ? `https://www.bilibili.com/video/${bvid}` : "";
|
|
37244
|
+
}
|
|
37245
|
+
case DynamicType.LIVE_RCMD: return "";
|
|
37246
|
+
default: return `https://t.bilibili.com/${PushItem.Dynamic_Data.id_str}`;
|
|
37247
|
+
}
|
|
37248
|
+
};
|
|
37249
|
+
/**
|
|
36992
37250
|
* 判断标题是否有屏蔽词或屏蔽标签
|
|
36993
37251
|
* @param PushItem 推送项
|
|
36994
37252
|
* @returns 是否应该跳过推送
|
|
@@ -37045,7 +37303,7 @@ registerErrorStrategy({
|
|
|
37045
37303
|
await event.reply([segment.text("检测到B站风控,请在「120 秒内」扫描二维码完成验证后发送验证结果\n"), ...img]);
|
|
37046
37304
|
await sendErrorToMaster(ctx, img);
|
|
37047
37305
|
await sendErrorToAllMasters(ctx, img);
|
|
37048
|
-
const resultCtx = await karin
|
|
37306
|
+
const resultCtx = await karin.ctx(event);
|
|
37049
37307
|
if (!resultCtx) return "continue";
|
|
37050
37308
|
const params = new URLSearchParams(resultCtx.msg);
|
|
37051
37309
|
const validate = params.get("validate");
|
|
@@ -37868,7 +38126,7 @@ var DouYin = class DouYin extends Base {
|
|
|
37868
38126
|
filepath: motionPhotoCoverPath,
|
|
37869
38127
|
totalBytes: 0
|
|
37870
38128
|
});
|
|
37871
|
-
const motionPhotoCover =
|
|
38129
|
+
const motionPhotoCover = processLocalImageFile(motionPhotoCoverPath);
|
|
37872
38130
|
processedImages.push(segment.image(motionPhotoCover));
|
|
37873
38131
|
hasPushedMotionPhotoCover = true;
|
|
37874
38132
|
}
|
|
@@ -38023,7 +38281,7 @@ var DouYin = class DouYin extends Base {
|
|
|
38023
38281
|
filepath: motionPhotoCoverPath,
|
|
38024
38282
|
totalBytes: 0
|
|
38025
38283
|
});
|
|
38026
|
-
const motionPhotoCover =
|
|
38284
|
+
const motionPhotoCover = processLocalImageFile(motionPhotoCoverPath);
|
|
38027
38285
|
images.push(segment.image(motionPhotoCover));
|
|
38028
38286
|
hasPushedMotionPhotoCover = true;
|
|
38029
38287
|
}
|
|
@@ -38339,7 +38597,7 @@ var DouYin = class DouYin extends Base {
|
|
|
38339
38597
|
});
|
|
38340
38598
|
await this.e.reply(img);
|
|
38341
38599
|
logger.debug(`等待用户选择视频,开始计时,${timeoutSeconds}秒后终止等待...`);
|
|
38342
|
-
const context = await karin
|
|
38600
|
+
const context = await karin.ctx(this.e, {
|
|
38343
38601
|
throwOnTimeout: false,
|
|
38344
38602
|
time: timeoutSeconds
|
|
38345
38603
|
});
|
|
@@ -39523,7 +39781,7 @@ var DouYinpush = class extends Base {
|
|
|
39523
39781
|
injectBotToEventForRender(targets) {
|
|
39524
39782
|
const targetBotId = targets.find((item) => item.botId)?.botId;
|
|
39525
39783
|
if (!targetBotId) return;
|
|
39526
|
-
const bot = karin
|
|
39784
|
+
const bot = karin.getBot(targetBotId);
|
|
39527
39785
|
if (!bot) return;
|
|
39528
39786
|
const eventWithBot = this.e;
|
|
39529
39787
|
eventWithBot.bot = bot;
|
|
@@ -39538,7 +39796,7 @@ var DouYinpush = class extends Base {
|
|
|
39538
39796
|
if (deletedCount > 0) logger.info(`已清理 ${deletedCount} 条过期的抖音作品缓存记录`);
|
|
39539
39797
|
if (await this.checkremark()) return true;
|
|
39540
39798
|
await this.ensureConfigFields(Config.pushlist.douyin);
|
|
39541
|
-
const registeredBotIds = karin
|
|
39799
|
+
const registeredBotIds = karin.getAllBotID();
|
|
39542
39800
|
const filteredPushList = this.filterPushListByRegisteredBots(Config.pushlist.douyin, registeredBotIds);
|
|
39543
39801
|
if (filteredPushList.length === 0) {
|
|
39544
39802
|
logger.warn("没有已注册的 bot 可用于抖音推送");
|
|
@@ -39726,18 +39984,27 @@ var DouYinpush = class extends Base {
|
|
|
39726
39984
|
let status = { message_id: "" };
|
|
39727
39985
|
const { groupId, botId } = target;
|
|
39728
39986
|
if (!skip) {
|
|
39729
|
-
const Contact = karin
|
|
39730
|
-
const bot = karin
|
|
39987
|
+
const Contact = karin.contactGroup(groupId);
|
|
39988
|
+
const bot = karin.getBot(botId);
|
|
39731
39989
|
const eventWithBot = this.e;
|
|
39732
39990
|
eventWithBot.bot = bot;
|
|
39733
39991
|
eventWithBot.selfId = botId;
|
|
39734
39992
|
const watermarkedImg = img ? applyWatermarkToImages(img, this.e) : [];
|
|
39735
|
-
|
|
39993
|
+
const parseButton = bot?.adapter?.name === "QQ Official Bot" && pushItem.pushType !== "live" && Detail_Data.share_url ? [segment.button([{
|
|
39994
|
+
text: "解析",
|
|
39995
|
+
callback: true,
|
|
39996
|
+
data: `#解析${Detail_Data.share_url}`
|
|
39997
|
+
}, {
|
|
39998
|
+
text: "帮助",
|
|
39999
|
+
callback: true,
|
|
40000
|
+
data: `#kkk帮助`
|
|
40001
|
+
}])] : [];
|
|
40002
|
+
status = await karin.sendMsg(botId, Contact, [...watermarkedImg, ...parseButton]);
|
|
39736
40003
|
if (pushItem.pushType === "live" && "room_data" in pushItem.Detail_Data && status.message_id) await douyinDBInstance.updateLiveStatus(pushItem.sec_uid, true);
|
|
39737
40004
|
if (Config.douyin.push.parsedynamic && status.message_id) {
|
|
39738
40005
|
const workTypeInfo = getWorkTypeInfo(Detail_Data);
|
|
39739
40006
|
logger.debug(`开始解析作品,类型为:${getWorkTypeDisplayName(workTypeInfo)}`);
|
|
39740
|
-
if (workTypeInfo.isVideo)
|
|
40007
|
+
if (workTypeInfo.isVideo) {
|
|
39741
40008
|
/** 默认视频下载地址 */
|
|
39742
40009
|
let downloadUrl = `https://aweme.snssdk.com/aweme/v1/play/?video_id=${Detail_Data.video.play_addr.uri}&ratio=1080p&line=0`;
|
|
39743
40010
|
logger.debug(`开始排除不符合条件的视频分辨率;\n
|
|
@@ -39764,10 +40031,7 @@ var DouYinpush = class extends Base {
|
|
|
39764
40031
|
group_id: groupId
|
|
39765
40032
|
}
|
|
39766
40033
|
});
|
|
39767
|
-
}
|
|
39768
|
-
throw new Error(`下载视频失败: ${error}`);
|
|
39769
|
-
}
|
|
39770
|
-
else if (workTypeInfo.isImage && iddata.type === "one_work") {
|
|
40034
|
+
} else if (workTypeInfo.isImage && iddata.type === "one_work") {
|
|
39771
40035
|
if (Detail_Data.is_slides === true && Detail_Data.images) {
|
|
39772
40036
|
const images = [];
|
|
39773
40037
|
const temp = [];
|
|
@@ -39858,7 +40122,7 @@ var DouYinpush = class extends Base {
|
|
|
39858
40122
|
filepath: motionPhotoCoverPath,
|
|
39859
40123
|
totalBytes: 0
|
|
39860
40124
|
});
|
|
39861
|
-
const motionPhotoCover =
|
|
40125
|
+
const motionPhotoCover = processLocalImageFile(motionPhotoCoverPath);
|
|
39862
40126
|
images.push(segment.image(motionPhotoCover));
|
|
39863
40127
|
hasPushedMotionPhotoCover = true;
|
|
39864
40128
|
}
|
|
@@ -39879,7 +40143,7 @@ var DouYinpush = class extends Base {
|
|
|
39879
40143
|
});
|
|
39880
40144
|
images.push(...tipImg);
|
|
39881
40145
|
}
|
|
39882
|
-
const bot = karin
|
|
40146
|
+
const bot = karin.getBot(botId);
|
|
39883
40147
|
const Element = common.makeForward(images, botId, bot.account.name);
|
|
39884
40148
|
try {
|
|
39885
40149
|
await bot.sendForwardMsg(Contact, Element, {
|
|
@@ -39981,7 +40245,7 @@ var DouYinpush = class extends Base {
|
|
|
39981
40245
|
filepath: motionPhotoCoverPath,
|
|
39982
40246
|
totalBytes: 0
|
|
39983
40247
|
});
|
|
39984
|
-
const motionPhotoCover =
|
|
40248
|
+
const motionPhotoCover = processLocalImageFile(motionPhotoCoverPath);
|
|
39985
40249
|
processedImages.push(segment.image(motionPhotoCover));
|
|
39986
40250
|
hasPushedMotionPhotoCover = true;
|
|
39987
40251
|
}
|
|
@@ -40002,7 +40266,7 @@ var DouYinpush = class extends Base {
|
|
|
40002
40266
|
});
|
|
40003
40267
|
processedImages.push(...tipImg);
|
|
40004
40268
|
}
|
|
40005
|
-
const bot = karin
|
|
40269
|
+
const bot = karin.getBot(botId);
|
|
40006
40270
|
const Element = common.makeForward(processedImages, botId, bot.account.name);
|
|
40007
40271
|
try {
|
|
40008
40272
|
await bot.sendForwardMsg(Contact, Element, {
|
|
@@ -40024,7 +40288,7 @@ var DouYinpush = class extends Base {
|
|
|
40024
40288
|
const imageUrl = await processImageUrl(image_url, Detail_Data.desc, index);
|
|
40025
40289
|
imageres.push(segment.image(imageUrl));
|
|
40026
40290
|
}
|
|
40027
|
-
const bot = karin
|
|
40291
|
+
const bot = karin.getBot(botId);
|
|
40028
40292
|
if (imageres.length === 1) {
|
|
40029
40293
|
const imageUrl = await processImageUrl(image_url, Detail_Data.desc);
|
|
40030
40294
|
await bot.sendMsg(Contact, [segment.image(imageUrl)]);
|
|
@@ -40754,6 +41018,42 @@ var Xiaohongshu = class extends Base {
|
|
|
40754
41018
|
this.e = e;
|
|
40755
41019
|
this.type = iddata?.type;
|
|
40756
41020
|
}
|
|
41021
|
+
async fetchConfiguredNoteComments(data) {
|
|
41022
|
+
const targetCount = Math.max(1, Config.xiaohongshu.numcomment);
|
|
41023
|
+
const firstPage = await this.amagi.xiaohongshu.fetcher.fetchNoteComments({
|
|
41024
|
+
typeMode: "strict",
|
|
41025
|
+
note_id: data.note_id,
|
|
41026
|
+
xsec_token: data.xsec_token
|
|
41027
|
+
});
|
|
41028
|
+
const comments = [...firstPage.data.data.comments ?? []];
|
|
41029
|
+
let cursor = firstPage.data.data.cursor;
|
|
41030
|
+
let hasMore = firstPage.data.data.has_more;
|
|
41031
|
+
const seenCursors = /* @__PURE__ */ new Set();
|
|
41032
|
+
while (comments.length < targetCount && hasMore && cursor && !seenCursors.has(cursor)) {
|
|
41033
|
+
seenCursors.add(cursor);
|
|
41034
|
+
const nextPage = await this.amagi.xiaohongshu.fetcher.fetchNoteComments({
|
|
41035
|
+
typeMode: "strict",
|
|
41036
|
+
note_id: data.note_id,
|
|
41037
|
+
cursor,
|
|
41038
|
+
xsec_token: data.xsec_token
|
|
41039
|
+
});
|
|
41040
|
+
comments.push(...nextPage.data.data.comments ?? []);
|
|
41041
|
+
cursor = nextPage.data.data.cursor;
|
|
41042
|
+
hasMore = nextPage.data.data.has_more;
|
|
41043
|
+
}
|
|
41044
|
+
return {
|
|
41045
|
+
...firstPage,
|
|
41046
|
+
data: {
|
|
41047
|
+
...firstPage.data,
|
|
41048
|
+
data: {
|
|
41049
|
+
...firstPage.data.data,
|
|
41050
|
+
comments,
|
|
41051
|
+
cursor,
|
|
41052
|
+
has_more: hasMore
|
|
41053
|
+
}
|
|
41054
|
+
}
|
|
41055
|
+
};
|
|
41056
|
+
}
|
|
40757
41057
|
async XiaohongshuHandler(data) {
|
|
40758
41058
|
if (Config.amagi.cookies.xiaohongshu === "") throw new Error("我还没有小红书的 Cookies,暂时无法解析呢 ~");
|
|
40759
41059
|
if (Config.app.parseTip) await this.e.reply("检测到小红书链接,开始解析");
|
|
@@ -40777,11 +41077,7 @@ var Xiaohongshu = class extends Base {
|
|
|
40777
41077
|
this.e.reply(noteInfoImg);
|
|
40778
41078
|
}
|
|
40779
41079
|
if (Config.xiaohongshu.sendContent.some((item) => item === "comment")) {
|
|
40780
|
-
const CommentData = await this.
|
|
40781
|
-
typeMode: "strict",
|
|
40782
|
-
note_id: data.note_id,
|
|
40783
|
-
xsec_token: data.xsec_token
|
|
40784
|
-
});
|
|
41080
|
+
const CommentData = await this.fetchConfiguredNoteComments(data);
|
|
40785
41081
|
if (!CommentData.data.data.comments || CommentData.data.data.comments.length === 0) await this.e.reply("这个笔记没有评论 ~");
|
|
40786
41082
|
else {
|
|
40787
41083
|
const processedComments = await xiaohongshuComments(CommentData.data, formattedEmojis);
|
|
@@ -40873,7 +41169,7 @@ var Xiaohongshu = class extends Base {
|
|
|
40873
41169
|
filepath: motionPhotoCoverPath,
|
|
40874
41170
|
totalBytes: 0
|
|
40875
41171
|
});
|
|
40876
|
-
const motionPhotoCover =
|
|
41172
|
+
const motionPhotoCover = processLocalImageFile(motionPhotoCoverPath);
|
|
40877
41173
|
processedImages.push(segment.image(motionPhotoCover));
|
|
40878
41174
|
hasPushedMotionPhotoCover = true;
|
|
40879
41175
|
hasGeneratedLivePhoto = true;
|
|
@@ -41299,7 +41595,7 @@ var douyinLogin = async (e) => {
|
|
|
41299
41595
|
while (verifyAttempts < maxAttempts && !verifySuccess) {
|
|
41300
41596
|
verifyAttempts++;
|
|
41301
41597
|
logger.debug(`验证码输入尝试 ${verifyAttempts}/${maxAttempts}`);
|
|
41302
|
-
const ctx = await Promise.race([karin.ctx(e, { reply: true }), new Promise((_, reject) => setTimeout(() => reject(/* @__PURE__ */ new Error("2FA_TIMEOUT")), 6e4))]).catch(async (error) => {
|
|
41598
|
+
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) => {
|
|
41303
41599
|
if (error.message === "2FA_TIMEOUT") {
|
|
41304
41600
|
logger.warn("2FA验证码输入超时");
|
|
41305
41601
|
clearTimeout(timer);
|
|
@@ -41433,7 +41729,7 @@ var waitQrcode = async (page) => {
|
|
|
41433
41729
|
const response = await fetch(originalImage);
|
|
41434
41730
|
imageBuffer = Buffer.from(await response.arrayBuffer());
|
|
41435
41731
|
}
|
|
41436
|
-
const qrContent =
|
|
41732
|
+
const qrContent = scanSync(imageBuffer);
|
|
41437
41733
|
if (qrContent) {
|
|
41438
41734
|
logger.mark("二维码解码成功:", qrContent);
|
|
41439
41735
|
return {
|
|
@@ -41456,12 +41752,12 @@ var handleCacheCleanup = wrapWithErrorHandler(async () => {
|
|
|
41456
41752
|
const twoHoursAgo = Date.now() - 7200 * 1e3;
|
|
41457
41753
|
const videoDeleted = removeOldFiles(Common.tempDri.video, twoHoursAgo);
|
|
41458
41754
|
logger.debug(`${Common.tempDri.video} 目录下已删除 ${videoDeleted} 个文件`);
|
|
41459
|
-
if (Config.app.imageSendMode
|
|
41755
|
+
if (Config.app.imageSendMode !== "url") {
|
|
41460
41756
|
const imageDeleted = removeOldFiles(Common.tempDri.images, twoHoursAgo);
|
|
41461
41757
|
logger.debug(`${Common.tempDri.images} 目录下已删除 ${imageDeleted} 个文件`);
|
|
41462
41758
|
}
|
|
41463
41759
|
}, { businessName: "缓存自动删除" });
|
|
41464
|
-
var task = Config.app.removeCache && karin
|
|
41760
|
+
var task = Config.app.removeCache && karin.task("[kkk-缓存自动删除]", "*/30 * * * *", handleCacheCleanup, { log: false });
|
|
41465
41761
|
var handleBilibiliLogin = wrapWithErrorHandler(async (e) => {
|
|
41466
41762
|
await bilibiliLogin(e);
|
|
41467
41763
|
return true;
|
|
@@ -41480,15 +41776,15 @@ var handlTestWrapWithErrorHandler = wrapWithErrorHandler(async (_e) => {
|
|
|
41480
41776
|
logger.fatal("测试致命日志");
|
|
41481
41777
|
throw Error("测试异常");
|
|
41482
41778
|
}, { businessName: "测试命令-错误捕获" });
|
|
41483
|
-
var biLogin = karin
|
|
41779
|
+
var biLogin = karin.command(/^#?(kkk)?\s*B站\s*(扫码)?\s*登录$/i, handleBilibiliLogin, {
|
|
41484
41780
|
perm: Config.bilibili.loginPerm,
|
|
41485
41781
|
name: "kkk-ck管理"
|
|
41486
41782
|
});
|
|
41487
|
-
var dylogin = karin
|
|
41783
|
+
var dylogin = karin.command(/^#?(kkk)?抖音(扫码)?登录$/, handleDouyinLogin, {
|
|
41488
41784
|
perm: Config.douyin.loginPerm,
|
|
41489
41785
|
name: "kkk-ck管理"
|
|
41490
41786
|
});
|
|
41491
|
-
var testWrapWithErrorHandler = process.env.NODE_ENV === "development" ? karin
|
|
41787
|
+
var testWrapWithErrorHandler = process.env.NODE_ENV === "development" ? karin.command(/^#?(kkk)?\s*测试\s*错误捕获$/i, handlTestWrapWithErrorHandler, {
|
|
41492
41788
|
perm: Config.bilibili.loginPerm,
|
|
41493
41789
|
name: "kkk-测试命令-错误捕获"
|
|
41494
41790
|
}) : null;
|
|
@@ -41677,8 +41973,8 @@ var handleVersion = wrapWithErrorHandler(async (e) => {
|
|
|
41677
41973
|
e.reply(img);
|
|
41678
41974
|
return true;
|
|
41679
41975
|
}, { businessName: "KKK版本" });
|
|
41680
|
-
var help = karin
|
|
41681
|
-
var version = karin
|
|
41976
|
+
var help = karin.command(/^#?kkk帮助$/, handleHelp, { name: "kkk-帮助" });
|
|
41977
|
+
var version = karin.command(/^#?kkk(版本|更新日志)$/, handleVersion, { name: "kkk-版本" });
|
|
41682
41978
|
//#endregion
|
|
41683
41979
|
//#region src/apps/push.ts
|
|
41684
41980
|
var handleDouyinPush = wrapWithErrorHandler(async () => {
|
|
@@ -41844,42 +42140,42 @@ var handleGlobalIgnore = wrapWithErrorHandler(async (e) => {
|
|
|
41844
42140
|
}
|
|
41845
42141
|
return true;
|
|
41846
42142
|
}, { businessName: "推送全局忽略" });
|
|
41847
|
-
var douyinPush = Config.douyin.push.switch && karin
|
|
42143
|
+
var douyinPush = Config.douyin.push.switch && karin.task("抖音推送", Config.douyin.push.cron, handleDouyinPush, {
|
|
41848
42144
|
log: true,
|
|
41849
42145
|
type: "skip"
|
|
41850
42146
|
});
|
|
41851
|
-
var bilibiliPush = Config.bilibili.push.switch && karin
|
|
42147
|
+
var bilibiliPush = Config.bilibili.push.switch && karin.task("B站推送", Config.bilibili.push.cron, handleBilibiliPush, {
|
|
41852
42148
|
log: true,
|
|
41853
42149
|
type: "skip"
|
|
41854
42150
|
});
|
|
41855
|
-
var forcePush = karin
|
|
42151
|
+
var forcePush = karin.command(/#(抖音|B站)(全部)?强制推送/, handleForcePush, {
|
|
41856
42152
|
name: "𝑪𝒊𝒂𝒍𝒍𝒐~(∠・ω< )⌒★",
|
|
41857
42153
|
perm: "master",
|
|
41858
42154
|
event: "message.group"
|
|
41859
42155
|
});
|
|
41860
|
-
var setdyPush = karin
|
|
42156
|
+
var setdyPush = karin.command(/^#设置抖音推送/, handleSetDouyinPush, {
|
|
41861
42157
|
name: "kkk-推送功能-设置",
|
|
41862
42158
|
event: "message.group",
|
|
41863
42159
|
perm: Config.douyin.push.permission
|
|
41864
42160
|
});
|
|
41865
|
-
var setbiliPush = karin
|
|
42161
|
+
var setbiliPush = karin.command(/^#设置[bB]站推送/, handleSetBilibiliPush, {
|
|
41866
42162
|
name: "kkk-推送功能-设置",
|
|
41867
42163
|
event: "message.group",
|
|
41868
42164
|
perm: Config.bilibili.push.permission
|
|
41869
42165
|
});
|
|
41870
|
-
var bilibiliPushList = karin
|
|
42166
|
+
var bilibiliPushList = karin.command(/^#?[bB]站推送列表$/, handleBilibiliPushList, {
|
|
41871
42167
|
name: "kkk-推送功能-列表",
|
|
41872
42168
|
event: "message.group"
|
|
41873
42169
|
});
|
|
41874
|
-
var douyinPushList = karin
|
|
42170
|
+
var douyinPushList = karin.command(/^#?抖音推送列表$/, handleDouyinPushList, {
|
|
41875
42171
|
name: "kkk-推送功能-列表",
|
|
41876
42172
|
event: "message.group"
|
|
41877
42173
|
});
|
|
41878
|
-
var changeBotID = karin
|
|
42174
|
+
var changeBotID = karin.command(/^#kkk设置推送机器人/, handleChangeBotID, {
|
|
41879
42175
|
name: "kkk-推送功能-设置",
|
|
41880
42176
|
perm: "master"
|
|
41881
42177
|
});
|
|
41882
|
-
var globalIgnore = karin
|
|
42178
|
+
var globalIgnore = karin.command(/^#kkk推送全局忽略/, handleGlobalIgnore, {
|
|
41883
42179
|
name: "kkk-推送功能-全局忽略",
|
|
41884
42180
|
perm: "master",
|
|
41885
42181
|
event: "message.group",
|
|
@@ -41954,7 +42250,7 @@ async function getHostByConfig() {
|
|
|
41954
42250
|
* 生成登录二维码(仅私发给主人)
|
|
41955
42251
|
*/
|
|
41956
42252
|
var handleQrLogin = wrapWithErrorHandler(async (e) => {
|
|
41957
|
-
const bot = karin
|
|
42253
|
+
const bot = karin.getBot(e.selfId);
|
|
41958
42254
|
const userId = e.userId;
|
|
41959
42255
|
if (e.isGroup) {
|
|
41960
42256
|
if (!(await bot?.getFriendList())?.some((f) => f.userId === userId)) {
|
|
@@ -41979,11 +42275,11 @@ var handleQrLogin = wrapWithErrorHandler(async (e) => {
|
|
|
41979
42275
|
}),
|
|
41980
42276
|
serverUrl: `${protocol}://${host}:${port}`
|
|
41981
42277
|
});
|
|
41982
|
-
await karin
|
|
42278
|
+
await karin.sendMaster(e.selfId, userId, images);
|
|
41983
42279
|
if (e.isGroup) await e.reply("登录二维码已私聊发送,请查收~");
|
|
41984
42280
|
return true;
|
|
41985
42281
|
}, { businessName: "APP扫码登录" });
|
|
41986
|
-
var qrLogin = karin
|
|
42282
|
+
var qrLogin = karin.command(/^#?(kkk)?登录$/i, handleQrLogin, {
|
|
41987
42283
|
perm: "master",
|
|
41988
42284
|
name: "kkk-APP扫码登录"
|
|
41989
42285
|
});
|
|
@@ -42035,7 +42331,7 @@ var handleGroupStatistics = wrapWithErrorHandler(async (e) => {
|
|
|
42035
42331
|
await e.reply(img);
|
|
42036
42332
|
return true;
|
|
42037
42333
|
}, { businessName: "群组解析统计" });
|
|
42038
|
-
var groupStatistics = karin
|
|
42334
|
+
var groupStatistics = karin.command(/^#?kkk解析统计$/, handleGroupStatistics, { name: "kkk-解析统计" });
|
|
42039
42335
|
/**
|
|
42040
42336
|
* #kkk全局解析统计 命令
|
|
42041
42337
|
* 获取整个插件的全局解析统计数据
|
|
@@ -42063,7 +42359,7 @@ var handleGlobalStatistics = wrapWithErrorHandler(async (e) => {
|
|
|
42063
42359
|
await e.reply(img);
|
|
42064
42360
|
return true;
|
|
42065
42361
|
}, { businessName: "全局解析统计" });
|
|
42066
|
-
var globalStatistics = karin
|
|
42362
|
+
var globalStatistics = karin.command(/^#?kkk全局解析统计$/, handleGlobalStatistics, {
|
|
42067
42363
|
name: "kkk-全局解析统计",
|
|
42068
42364
|
perm: "master"
|
|
42069
42365
|
});
|
|
@@ -42273,7 +42569,7 @@ var handleTestPush = wrapWithErrorHandler(async (e) => {
|
|
|
42273
42569
|
return true;
|
|
42274
42570
|
}, { businessName: "测试抖音推送" });
|
|
42275
42571
|
/** 注册测试推送命令 */
|
|
42276
|
-
var testPush = Config.douyin.switch && karin
|
|
42572
|
+
var testPush = Config.douyin.switch && karin.command(/^#测试抖音(作品|喜欢列表|推荐列表|直播状态)推送/, handleTestPush, {
|
|
42277
42573
|
name: "kkk-测试抖音推送",
|
|
42278
42574
|
perm: "master"
|
|
42279
42575
|
});
|
|
@@ -42360,7 +42656,7 @@ var handleXiaohongshu = wrapWithErrorHandler(async (e, next) => {
|
|
|
42360
42656
|
}, { businessName: "小红书视频解析" });
|
|
42361
42657
|
var handlePrefix = wrapWithErrorHandler(async (e, next) => {
|
|
42362
42658
|
const originalMsg = e.msg;
|
|
42363
|
-
e.msg = await Common.getReplyMessage(e);
|
|
42659
|
+
e.msg = await Common.getReplyMessage(e) || originalMsg.replace(/^#?(解析|kkk解析|弹幕解析)\s*/, "");
|
|
42364
42660
|
if (/^#?弹幕解析/.test(originalMsg)) e.msg = "#弹幕解析 " + e.msg;
|
|
42365
42661
|
if (reg.douyinCDN.test(e.msg)) {
|
|
42366
42662
|
logger.debug("检测到抖音 CDN 下载链接,直接下载视频");
|
|
@@ -42379,23 +42675,23 @@ var handlePrefix = wrapWithErrorHandler(async (e, next) => {
|
|
|
42379
42675
|
else if (reg.kuaishou.test(e.msg)) return await handleKuaishou(e, next);
|
|
42380
42676
|
else if (reg.xiaohongshu.test(e.msg)) return await handleXiaohongshu(e, next);
|
|
42381
42677
|
}, { businessName: "引用解析" });
|
|
42382
|
-
var douyin = karin
|
|
42678
|
+
var douyin = karin.command(reg.douyin, handleDouyin, {
|
|
42383
42679
|
name: "kkk-视频功能-抖音",
|
|
42384
42680
|
priority: Config.app.videoTool ? -Infinity : 800
|
|
42385
42681
|
});
|
|
42386
|
-
var bilibili = karin
|
|
42682
|
+
var bilibili = karin.command(reg.bilibili, handleBilibili, {
|
|
42387
42683
|
name: "kkk-视频功能-B站",
|
|
42388
42684
|
priority: Config.app.videoTool ? -Infinity : 800
|
|
42389
42685
|
});
|
|
42390
|
-
var kuaishou = karin
|
|
42686
|
+
var kuaishou = karin.command(reg.kuaishou, handleKuaishou, {
|
|
42391
42687
|
name: "kkk-视频功能-快手",
|
|
42392
42688
|
priority: Config.app.videoTool ? -Infinity : 800
|
|
42393
42689
|
});
|
|
42394
|
-
var xiaohongshu = karin
|
|
42690
|
+
var xiaohongshu = karin.command(reg.xiaohongshu, handleXiaohongshu, {
|
|
42395
42691
|
name: "kkk-视频功能-小红书",
|
|
42396
42692
|
priority: Config.app.videoTool ? -Infinity : 800
|
|
42397
42693
|
});
|
|
42398
|
-
var prefix = karin
|
|
42694
|
+
var prefix = karin.command(/^#?(解析|kkk解析|弹幕解析)/, handlePrefix, { name: "kkk-视频功能-引用解析" });
|
|
42399
42695
|
var douyinAPP = Config.douyin.switch && douyin;
|
|
42400
42696
|
var bilibiliAPP = Config.bilibili.switch && bilibili;
|
|
42401
42697
|
var kuaishouAPP = Config.kuaishou.switch && kuaishou;
|
|
@@ -42562,7 +42858,7 @@ var Handler = async () => {
|
|
|
42562
42858
|
} catch {}
|
|
42563
42859
|
const masters = config.master().filter((id) => id !== "console");
|
|
42564
42860
|
if (masters.length === 0) return true;
|
|
42565
|
-
const botItems = karin
|
|
42861
|
+
const botItems = karin.getAllBotList().filter((b) => b.bot.account.name !== "console");
|
|
42566
42862
|
if (botItems.length === 0) return true;
|
|
42567
42863
|
const friendsMap = /* @__PURE__ */ new Map();
|
|
42568
42864
|
await Promise.all(botItems.map(async (item) => {
|
|
@@ -42594,7 +42890,7 @@ var Handler = async () => {
|
|
|
42594
42890
|
if (!bot) continue;
|
|
42595
42891
|
const elements = botToImage.get(bot.account.selfId);
|
|
42596
42892
|
if (!elements) continue;
|
|
42597
|
-
const msg = await karin
|
|
42893
|
+
const msg = await karin.sendMaster(bot.account.selfId, owner, elements);
|
|
42598
42894
|
if (!storedMsgId && msg?.messageId) storedMsgId = msg.messageId;
|
|
42599
42895
|
}
|
|
42600
42896
|
if (storedMsgId) try {
|
|
@@ -42657,14 +42953,14 @@ var handleKkkUpdate = wrapWithErrorHandler(async (e) => {
|
|
|
42657
42953
|
await restart(e.selfId, e.contact, msgResult.messageId);
|
|
42658
42954
|
} else e.reply(`${Root.pluginName} 更新失败: ${result.data ?? "更新执行失败"}`);
|
|
42659
42955
|
}, { businessName: "KKK更新" });
|
|
42660
|
-
var kkkUpdateCommand = karin
|
|
42661
|
-
var kkkUpdateTest = process.env.NODE_ENV === "development" && karin
|
|
42956
|
+
var kkkUpdateCommand = karin.command(/^#?kkk更新$/, handleKkkUpdate, { name: "kkk-更新" });
|
|
42957
|
+
var kkkUpdateTest = process.env.NODE_ENV === "development" && karin.command("test", async (_e, next) => {
|
|
42662
42958
|
await db.del(UPDATE_MSGID_KEY);
|
|
42663
42959
|
await db.del(UPDATE_LOCK_KEY);
|
|
42664
42960
|
await Handler();
|
|
42665
42961
|
next();
|
|
42666
42962
|
}, { name: "kkk-更新检测-测试" });
|
|
42667
|
-
var update = karin
|
|
42963
|
+
var update = karin.task("kkk-更新检测", "*/3 * * * *", Handler, {
|
|
42668
42964
|
name: "kkk-更新检测",
|
|
42669
42965
|
log: false
|
|
42670
42966
|
});
|
|
@@ -42707,7 +43003,7 @@ var ROUTES = {
|
|
|
42707
43003
|
* Bot 管理 API
|
|
42708
43004
|
*/
|
|
42709
43005
|
var getOnlineBotById = (botId) => {
|
|
42710
|
-
return karin.getAllBotList().find((item) => item.bot.account.selfId === botId)?.bot;
|
|
43006
|
+
return karin$1.getAllBotList().find((item) => item.bot.account.selfId === botId)?.bot;
|
|
42711
43007
|
};
|
|
42712
43008
|
var getBotAvatar = async (bot, botId) => {
|
|
42713
43009
|
if (!bot) return "";
|
|
@@ -42724,7 +43020,7 @@ var getBotAvatar = async (bot, botId) => {
|
|
|
42724
43020
|
*/
|
|
42725
43021
|
var getBots = async (_req, res) => {
|
|
42726
43022
|
try {
|
|
42727
|
-
const botList = karin.getAllBotList();
|
|
43023
|
+
const botList = karin$1.getAllBotList();
|
|
42728
43024
|
const bots = [];
|
|
42729
43025
|
for (const item of botList) {
|
|
42730
43026
|
const bot = item.bot;
|
|
@@ -42777,7 +43073,7 @@ var getBotGroups = async (req, res) => {
|
|
|
42777
43073
|
try {
|
|
42778
43074
|
const botId = Array.isArray(req.params.botId) ? req.params.botId[0] : req.params.botId;
|
|
42779
43075
|
if (!botId) return createServerErrorResponse(res, "缺少 botId 参数");
|
|
42780
|
-
const botItem = karin.getAllBotList().find((item) => item.bot.account.selfId === botId);
|
|
43076
|
+
const botItem = karin$1.getAllBotList().find((item) => item.bot.account.selfId === botId);
|
|
42781
43077
|
if (!botItem) return createServerErrorResponse(res, "Bot 不存在或不在线");
|
|
42782
43078
|
const bot = botItem.bot;
|
|
42783
43079
|
const groupList = await bot.getGroupList();
|
|
@@ -42846,7 +43142,7 @@ var getGroupsBatch = async (req, res) => {
|
|
|
42846
43142
|
const { groups } = req.body;
|
|
42847
43143
|
if (!groups || !Array.isArray(groups)) return createServerErrorResponse(res, "缺少 groups 参数");
|
|
42848
43144
|
const result = [];
|
|
42849
|
-
const botList = karin.getAllBotList();
|
|
43145
|
+
const botList = karin$1.getAllBotList();
|
|
42850
43146
|
for (const item of groups) {
|
|
42851
43147
|
const botItem = botList.find((b) => b.bot.account.selfId === item.botId);
|
|
42852
43148
|
if (!botItem) {
|
|
@@ -43317,13 +43613,13 @@ app$1.use(ASSETS_PREFIX, staticRouter);
|
|
|
43317
43613
|
app.use(KKK_PREFIX, app$1);
|
|
43318
43614
|
//#endregion
|
|
43319
43615
|
//#region src/setup.ts
|
|
43320
|
-
var requireVersion = "1.16.
|
|
43616
|
+
var requireVersion = "1.16.2";
|
|
43321
43617
|
if (process.env.NODE_ENV !== "development" && isSemverGreater(requireVersion, Root.karinVersion)) {
|
|
43322
43618
|
const msg = `[karin-plugin-kkk] 插件构建时的 karin 版本 (${requireVersion}) 高于当前运行版本 (${Root.karinVersion}),可能会出现兼容性问题!`;
|
|
43323
43619
|
logger.warn(msg);
|
|
43324
43620
|
/** 已发送通知的 Bot ID 和主人 ID 组合,格式:`${botId}:${master}` */
|
|
43325
43621
|
const notifiedSet = /* @__PURE__ */ new Set();
|
|
43326
|
-
karin
|
|
43622
|
+
karin.on(BOT_CONNECT, async (bot) => {
|
|
43327
43623
|
const botId = bot.selfId;
|
|
43328
43624
|
if (botId === "console") return;
|
|
43329
43625
|
await new Promise((resolve) => setTimeout(resolve, 2e3));
|
|
@@ -43333,7 +43629,7 @@ if (process.env.NODE_ENV !== "development" && isSemverGreater(requireVersion, Ro
|
|
|
43333
43629
|
for (const master of masters) {
|
|
43334
43630
|
if (master === "console") continue;
|
|
43335
43631
|
try {
|
|
43336
|
-
warningImage = await Render({ bot: karin
|
|
43632
|
+
warningImage = await Render({ bot: karin.getBot(botId) }, "other/version_warning", {
|
|
43337
43633
|
requireVersion,
|
|
43338
43634
|
currentVersion: Root.karinVersion
|
|
43339
43635
|
});
|
|
@@ -43345,7 +43641,7 @@ if (process.env.NODE_ENV !== "development" && isSemverGreater(requireVersion, Ro
|
|
|
43345
43641
|
try {
|
|
43346
43642
|
const elements = [];
|
|
43347
43643
|
if (warningImage) elements.push(...warningImage);
|
|
43348
|
-
await karin
|
|
43644
|
+
await karin.sendMaster(botId, master, elements);
|
|
43349
43645
|
notifiedSet.add(key);
|
|
43350
43646
|
logger.info(`[karin-plugin-kkk] 已发送版本警告给主人: ${master} (via ${botId})`);
|
|
43351
43647
|
} catch (error) {
|