karin-plugin-kkk 2.45.0-rc.3 → 2.45.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  globalThis.__KTR_BUNDLED__ = true;
2
2
  import { o as __toESM } from "./rolldown-runtime.js";
3
3
  import { a as createBilibiliRoutes, c as createXiaohongshuRoutes, i as bilibiliApiUrls, l as wbi_sign, n as DynamicType, o as createDouyinRoutes, r as MajorType, s as createKuaishouRoutes, t as Client } from "./default.js";
4
- import { $ as RiPieChart2Fill, $n as Gamepad2, $t as Users, A as MdFitScreen, An as Puzzle, Ar as Bookmark, At as p$1, B as AiFillHeart, Bn as Maximize, Br as resolveTemplateStyle, Bt as n$1, C as webassembly, Cn as Route, Cr as Check, Ct as o, D as tailwind_css, Dn as Radio, Dr as Braces, Dt as m, E as tsdown, En as RefreshCw, Er as Calendar, Et as n$2, F as FaCommentDots, Fn as Music, Fr as Button, Ft as m$2, G as RiArrowRightFill, Gn as LayoutTemplate, Gt as fromUnixTime, H as AiFillStar, Hn as LoaderCircle, Hr as require_react, Ht as m$3, I as FaMusic, In as Moon, Ir as require_jsx_runtime, It as c$1, J as RiHeart3Fill, Jn as Heart, Jt as differenceInSeconds, K as RiGroupLine, Kn as Info, Kt as formatDistanceToNow, L as FaTiktok, Ln as Monitor, Lr as twMerge, Lt as o$2, M as MdLightbulbOutline, Mn as Play, Mr as BellRing, Mt as c$2, N as MdLocationOn, Nn as Pencil, Nr as ArrowRight, Nt as a$1, O as sqlite, On as Quote, Or as Box, Ot as a, P as MdSchedule, Pn as Palette, Pr as Chip, Pt as m$1, Q as RiMessage3Fill, Qn as Gauge, Qt as Video, R as FaUserGroup, Rn as MessageCircle, Rr as clsx, Rt as c, S as rehypeHighlight, Sn as Save, Sr as CircleAlert, St as r, T as typescript, Tn as Repeat, Tr as Camera, Tt as s, U as AiOutlineVideoCamera, Un as ListChecks, Ur as HtmlWrapper, Ut as zhCN, V as AiFillPushpin, Vn as MapPin, Vr as require_server_node, Vt as s$1, W as Markdown, Wn as Link, Wr as defineTemplate, Wt as parse, X as RiHeartLine, Xn as GitBranch, Xt as X, Y as RiHeart3Line, Yn as Hash, Yt as Zap, Z as RiLiveLine, Zn as Gift, Zt as WandSparkles, _ as use, _n as ShieldAlert, _r as CircleFadingArrowUp, _t as SiGithub, a as drawDither, an as Trash, ar as EyeOff, at as RiTrophyFill, b as install$2, bn as Search, br as CircleCheck, bt as SiAnthropic, c as install$11, cn as Sun, cr as Crown, ct as RiVideoLine, d as install$8, dn as SquarePen, dr as Copy, dt as SiSamsung, en as UsersRound, er as FingerprintPattern, et as RiShareForwardFill, f as install$7, fn as Sparkles, fr as Code, ft as SiOppo, g as install$5, gn as ShieldCheck, gr as CircleQuestionMark, gt as SiGooglephotos, h as install$6, hn as Shield, hr as Clapperboard, ht as SiHonor, in as TriangleAlert, ir as Eye, it as RiTiktokFill, j as MdInfoOutline, jn as Plus, jr as BookOpenText, jt as e, k as react, kn as QrCode, kr as Bot, kt as n, l as install$10, ln as Star, lr as Cpu, lt as SiXiaomi, m as install$4, mn as ShoppingBag, mr as Clock3, mt as SiHuawei, nn as UserPlus, nr as FilePlay, nt as RiStarLine, o as require_jpeg_js, on as Timer, or as ExternalLink, ot as RiUserFollowLine, p as install$3, pn as Smartphone, pr as Clock, pt as SiOneplus, q as RiHashtag, qn as Image$1, qt as format, rn as Upload, rr as FileExclamationPoint, rt as RiThumbUpFill, s as require_heic_decode, sn as Terminal, sr as Download, st as RiVerifiedBadgeFill, tn as User, tr as FileText, tt as RiStarFill, u as install$9, un as Square, ur as CornerDownLeft, ut as SiVivo, v as init, vn as Share2, vr as CircleEllipsis, vt as SiBilibili, w as vite, wn as RotateCcw, wr as ChartColumn, wt as o$1, x as install$1, xn as ScanLine, xr as CircleCheckBig, xt as o$3, y as install, yn as Settings2, yr as CircleDashed, yt as SiApple, z as BiImage, zn as Menu, zr as createTemplateRenderer, zt as p } from "./vendor.js";
4
+ import { $ as RiPieChart2Fill, $n as FingerprintPattern, $t as UsersRound, A as MdFitScreen, An as Plus, Ar as BookOpenText, At as e, B as AiFillHeart, Bn as MapPin, Br as require_server_node, Bt as s$1, C as webassembly_default, Cn as RotateCcw, Cr as ChartColumn, Ct as o, D as tailwind_css_default, Dn as Quote, Dr as Box, Dt as a, E as tsdown_default, En as Radio, Er as Braces, Et as m, F as FaCommentDots, Fn as Moon, Fr as require_jsx_runtime, Ft as c$1, G as RiArrowRightFill, Gn as Info, Gt as formatDistanceToNow, H as AiFillStar, Hn as ListChecks, Hr as HtmlWrapper, Ht as zhCN, I as FaMusic, In as Monitor, Ir as twMerge, It as o$2, J as RiHeart3Fill, Jn as Hash, Jt as Zap, K as RiGroupLine, Kn as Image$1, Kt as format, L as FaTiktok, Ln as MessageCircle, Lr as clsx, Lt as c, M as MdLightbulbOutline, Mn as Pencil, Mr as ArrowRight, Mt as a$1, N as MdLocationOn, Nn as Palette, Nr as Chip, Nt as m$1, O as sqlite_default, On as QrCode, Or as Bot, Ot as n, P as MdSchedule, Pn as Music, Pr as Button, Pt as m$2, Q as RiMessage3Fill, Qn as Gamepad2, Qt as Users, R as FaUserGroup, Rn as Menu, Rr as createTemplateRenderer, Rt as p, S as rehypeHighlight, Sn as Route, Sr as Check, St as r, T as typescript_default, Tn as RefreshCw, Tr as Calendar, Tt as s, U as AiOutlineVideoCamera, Un as Link, Ur as defineTemplate, Ut as parse, V as AiFillPushpin, Vn as LoaderCircle, Vr as require_react, Vt as m$3, W as Markdown, Wn as LayoutTemplate, Wt as fromUnixTime, X as RiHeartLine, Xn as Gift, Xt as WandSparkles, Y as RiHeart3Line, Yn as GitBranch, Yt as X, Z as RiLiveLine, Zn as Gauge, Zt as Video, _ as use, _n as Share2, _r as CircleEllipsis, _t as SiGithub, a as drawDither, an as Timer, ar as ExternalLink, at as RiTrophyFill, b as install$2, bn as ScanLine, br as CircleCheckBig, bt as SiAnthropic, c as install$11, cn as Star, cr as Cpu, ct as RiVideoLine, d as install$8, dn as Sparkles, dr as Code, dt as SiSamsung, en as User, er as FileText, et as RiShareForwardFill, f as install$7, fn as Smartphone, fr as Clock, ft as SiOppo, g as install$5, gn as ShieldAlert, gr as CircleFadingArrowUp, gt as SiGooglephotos, h as install$6, hn as ShieldCheck, hr as CircleQuestionMark, ht as SiHonor, in as Trash, ir as EyeOff, it as RiTiktokFill, j as MdInfoOutline, jn as Play, jr as BellRing, jt as c$2, k as react_default, kn as Puzzle, kr as Bookmark, kt as p$1, l as install$10, ln as Square, lr as CornerDownLeft, lt as SiXiaomi, m as install$4, mn as Shield, mr as Clapperboard, mt as SiHuawei, nn as Upload, nr as FileExclamationPoint, nt as RiStarLine, o as require_jpeg_js, on as Terminal, or as Download, ot as RiUserFollowLine, p as install$3, pn as ShoppingBag, pr as Clock3, pt as SiOneplus, q as RiHashtag, qn as Heart, qt as differenceInSeconds, rn as TriangleAlert, rr as Eye, rt as RiThumbUpFill, s as require_heic_decode, sn as Sun, sr as Crown, st as RiVerifiedBadgeFill, tn as UserPlus, tr as FilePlay, tt as RiStarFill, u as install$9, un as SquarePen, ur as Copy, ut as SiVivo, v as init, vn as Settings2, vr as CircleDashed, vt as SiBilibili, w as vite_default, wn as Repeat, wr as Camera, wt as o$1, x as install$1, xn as Save, xr as CircleAlert, xt as o$3, y as install, yn as Search, yr as CircleCheck, yt as SiApple, z as BiImage, zn as Maximize, zr as resolveTemplateStyle, zt as n$1 } from "./vendor.js";
5
5
  import { createRequire } from "node:module";
6
6
  import fs from "node:fs";
7
7
  import path, { resolve } from "node:path";
@@ -742,15 +742,16 @@ var uploadFile = async (event, file, videoUrl, options) => {
742
742
  logger$1.mark(`已开启视频文件 base64转换 正在进行${logger$1.yellow("base64转换中")}...`);
743
743
  } else File = options?.useGroupFile ? file.filepath : `file://${file.filepath}`;
744
744
  try {
745
- if (options?.active) if (options.useGroupFile) {
746
- const bot = karin.getBot(String(options.activeOption?.uin));
747
- logger$1.mark(`${logger$1.blue("主动消息:")} 视频大小: ${newFileSize.toFixed(1)}MB 正在通过${logger$1.yellow("bot.uploadFile")}回复...`);
748
- await bot.uploadFile(contact, File, file.originTitle ? `${file.originTitle}.mp4` : `${File.split("/").pop()}`);
749
- } else {
750
- logger$1.mark(`${logger$1.blue("主动消息:")} 视频大小: ${newFileSize.toFixed(1)}MB 正在通过${logger$1.yellow("karin.sendMsg")}回复...`);
751
- sendStatus = (await karin.sendMsg(selfId, contact, [segment.video(File)], { retryCount: 0 })).messageId ? true : false;
752
- }
753
- else if (options?.useGroupFile) {
745
+ if (options?.active) {
746
+ if (options.useGroupFile) {
747
+ const bot = karin.getBot(String(options.activeOption?.uin));
748
+ logger$1.mark(`${logger$1.blue("主动消息:")} 视频大小: ${newFileSize.toFixed(1)}MB 正在通过${logger$1.yellow("bot.uploadFile")}回复...`);
749
+ await bot.uploadFile(contact, File, file.originTitle ? `${file.originTitle}.mp4` : `${File.split("/").pop()}`);
750
+ } else {
751
+ logger$1.mark(`${logger$1.blue("主动消息:")} 视频大小: ${newFileSize.toFixed(1)}MB 正在通过${logger$1.yellow("karin.sendMsg")}回复...`);
752
+ sendStatus = (await karin.sendMsg(selfId, contact, [segment.video(File)], { retryCount: 0 })).messageId ? true : false;
753
+ }
754
+ } else if (options?.useGroupFile) {
754
755
  logger$1.mark(`${logger$1.blue("被动消息:")} 视频大小: ${newFileSize.toFixed(1)}MB 正在通过${logger$1.yellow("e.bot.uploadFile")}回复...`);
755
756
  await event.bot.uploadFile(event.contact, File, file.originTitle ? `${file.originTitle}.mp4` : `${File.split("/").pop()}`);
756
757
  } else {
@@ -764,12 +765,12 @@ var uploadFile = async (event, file, videoUrl, options) => {
764
765
  throw error;
765
766
  } finally {
766
767
  const filePath = file.filepath;
767
- const previewInfo = Common.registerVideoPreview(filePath, Config.app.removeCache, 1800 * 1e3);
768
+ const previewInfo = Common.registerVideoPreview(filePath, Config.app.removeCache, 18e5);
768
769
  logger$1.mark(`临时预览地址:http://localhost:${process.env.HTTP_PORT}/kkk/ssr/video/${previewInfo.token}`);
769
770
  if (Config.app.removeCache) logger$1.info(`文件 ${filePath} 将在 30 分钟后删除`);
770
771
  setTimeout(async () => {
771
772
  if (await Common.removeFile(filePath)) Common.markVideoPreviewRemoved(filePath);
772
- }, 1800 * 1e3);
773
+ }, 18e5);
773
774
  }
774
775
  };
775
776
  /**
@@ -784,7 +785,7 @@ var downloadVideo = async (event, downloadOpt, uploadOpt) => {
784
785
  url: downloadOpt.video_url,
785
786
  headers: downloadOpt.headers ?? BASE_HEADERS
786
787
  }).getHeaders());
787
- const fileSizeInMB = (fileSizeContent / (1024 * 1024)).toFixed(2);
788
+ const fileSizeInMB = (fileSizeContent / 1048576).toFixed(2);
788
789
  const fileSize = parseInt(parseFloat(fileSizeInMB).toFixed(2));
789
790
  if (fileSizeContent > 0 && Config.app.usefilelimit && fileSize > Config.app.filelimit) {
790
791
  const message = segment.text(`视频:「${downloadOpt.title.originTitle ?? "Error: 文件名获取失败"}」大小 (${fileSizeInMB} MB) 超出最大限制(设定值:${Config.app.filelimit} MB),已取消上传`);
@@ -801,7 +802,7 @@ var downloadVideo = async (event, downloadOpt, uploadOpt) => {
801
802
  ...res,
802
803
  ...downloadOpt.title
803
804
  };
804
- res.totalBytes = Number((res.totalBytes / (1024 * 1024)).toFixed(2));
805
+ res.totalBytes = Number((res.totalBytes / 1048576).toFixed(2));
805
806
  /** 上传视频 */
806
807
  return await uploadFile(event, res, downloadOpt.video_url, uploadOpt);
807
808
  };
@@ -944,8 +945,8 @@ var isSafePublicHttpUrl = (url) => {
944
945
  };
945
946
  /** 常用工具合集 */
946
947
  var Common = new class Tools {
947
- static VIDEO_PREVIEW_REMOVED_RETENTION_MS = 300 * 1e3;
948
- static VIDEO_PREVIEW_SWEEP_INTERVAL_MS = 600 * 1e3;
948
+ static VIDEO_PREVIEW_REMOVED_RETENTION_MS = 3e5;
949
+ static VIDEO_PREVIEW_SWEEP_INTERVAL_MS = 6e5;
949
950
  /**
950
951
  * 插件缓存目录
951
952
  */
@@ -987,7 +988,8 @@ var Common = new class Tools {
987
988
  try {
988
989
  logger$1.debug(`检测到${source}为图片,尝试识别二维码...`);
989
990
  const response = await axios.get(imageUrl, { responseType: "arraybuffer" });
990
- const qrContent = scanSync(Buffer.from(response.data));
991
+ const buffer = Buffer.from(response.data);
992
+ const qrContent = scanSync(buffer);
991
993
  if (qrContent && [
992
994
  /(https?:\/\/)?(www|v|jx|m|jingxuan)\.(douyin|iesdouyin)\.com/i,
993
995
  /https:\/\/aweme\.snssdk\.com\/aweme\/v1\/play/i,
@@ -1102,7 +1104,7 @@ var Common = new class Tools {
1102
1104
  */
1103
1105
  async getVideoFileSize(filePath) {
1104
1106
  try {
1105
- return (await fs.promises.stat(filePath)).size / (1024 * 1024);
1107
+ return (await fs.promises.stat(filePath)).size / 1048576;
1106
1108
  } catch (error) {
1107
1109
  logger$1.error("获取文件大小时发生错误:", error);
1108
1110
  throw error;
@@ -1238,8 +1240,8 @@ var Common = new class Tools {
1238
1240
  formatFileSize(sizeInMB) {
1239
1241
  const size = typeof sizeInMB === "string" ? parseFloat(sizeInMB) : sizeInMB;
1240
1242
  if (size < 1024) return `${size.toFixed(2)}MB`;
1241
- else if (size < 1024 * 1024) return `${(size / 1024).toFixed(2)}GB`;
1242
- else return `${(size / (1024 * 1024)).toFixed(2)}TB`;
1243
+ else if (size < 1048576) return `${(size / 1024).toFixed(2)}GB`;
1244
+ else return `${(size / 1048576).toFixed(2)}TB`;
1243
1245
  }
1244
1246
  }();
1245
1247
  //#endregion
@@ -1973,9 +1975,9 @@ var calculateBackoffDelay = (retryCount, baseDelay = 1e3, maxDelay = 8e3) => {
1973
1975
  */
1974
1976
  var formatBytes = (bytes) => {
1975
1977
  if (bytes < 1024) return `${bytes} B`;
1976
- if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
1977
- if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
1978
- return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)} GB`;
1978
+ if (bytes < 1048576) return `${(bytes / 1024).toFixed(1)} KB`;
1979
+ if (bytes < 1073741824) return `${(bytes / 1048576).toFixed(2)} MB`;
1980
+ return `${(bytes / 1073741824).toFixed(2)} GB`;
1979
1981
  };
1980
1982
  /**
1981
1983
  * 从响应头中提取文件总字节数
@@ -2068,9 +2070,9 @@ var ThrottleStream = class extends Transform {
2068
2070
  */
2069
2071
  var DEFAULT_THROTTLE_CONFIG = {
2070
2072
  enabled: true,
2071
- maxSpeed: 10 * 1024 * 1024,
2073
+ maxSpeed: 10485760,
2072
2074
  autoReduceRatio: .7,
2073
- minSpeed: 1 * 1024 * 1024
2075
+ minSpeed: 1048576
2074
2076
  };
2075
2077
  //#endregion
2076
2078
  //#region src/module/utils/Network/Downloader.ts
@@ -2122,7 +2124,7 @@ var Downloader = class {
2122
2124
  let startByte = 0;
2123
2125
  if (fs.existsSync(this.filepath)) {
2124
2126
  const stats = fs.statSync(this.filepath);
2125
- startByte = Math.max(0, stats.size - 256 * 1024);
2127
+ startByte = Math.max(0, stats.size - 262144);
2126
2128
  if (startByte > 0 && startByte < stats.size) {
2127
2129
  fs.truncateSync(this.filepath, startByte);
2128
2130
  logger$1.debug(`检测到部分下载文件,截断到 ${formatBytes(startByte)} 后重新下载(回退 256KB 安全裕量)`);
@@ -2219,7 +2221,7 @@ var Downloader = class {
2219
2221
  }
2220
2222
  } else progressCallback(downloadedBytes, totalBytes);
2221
2223
  };
2222
- intervalId = setInterval(printProgress, totalBytes > 0 && totalBytes < 10 * 1024 * 1024 ? 1e3 : 500);
2224
+ intervalId = setInterval(printProgress, totalBytes > 0 && totalBytes < 10485760 ? 1e3 : 500);
2223
2225
  const counterStream = new Transform({ transform(chunk, encoding, callback) {
2224
2226
  downloadedBytes += chunk.length;
2225
2227
  callback(null, chunk);
@@ -2247,7 +2249,7 @@ var Downloader = class {
2247
2249
  if (actualSize < expectedSize) {
2248
2250
  logger$1.warn(`文件大小不匹配: 实际 ${formatBytes(actualSize)}, 预期 ${formatBytes(expectedSize)}`);
2249
2251
  logger$1.warn(`差异: ${formatBytes(expectedSize - actualSize)} (${((expectedSize - actualSize) / expectedSize * 100).toFixed(2)}%)`);
2250
- if (expectedSize - actualSize > 10 * 1024) throw new Error(`文件下载不完整: 实际 ${formatBytes(actualSize)}, 预期 ${formatBytes(expectedSize)}`);
2252
+ if (expectedSize - actualSize > 10240) throw new Error(`文件下载不完整: 实际 ${formatBytes(actualSize)}, 预期 ${formatBytes(expectedSize)}`);
2251
2253
  } else logger$1.debug(`文件大小验证通过: ${formatBytes(actualSize)}`);
2252
2254
  }
2253
2255
  this.consecutiveResets = 0;
@@ -2484,7 +2486,7 @@ var ImageDownloader = class {
2484
2486
  const actualPath = filePath.replace(/^file:\/\//, "");
2485
2487
  setTimeout(() => {
2486
2488
  this.deleteFile(actualPath);
2487
- }, 600 * 1e3);
2489
+ }, 6e5);
2488
2490
  }
2489
2491
  /**
2490
2492
  * 删除文件
@@ -7298,12 +7300,16 @@ var renderNodeToReact = (node, index, options) => {
7298
7300
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ViewPictureIcon, {})
7299
7301
  }), node.text]
7300
7302
  }, `viewpicture-${index}`);
7301
- case "heading": return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(`h${node.level}`, {
7302
- className: `${node.level === 1 ? "text-[64px]" : node.level === 2 ? "text-[58px]" : node.level === 3 ? "text-[52px]" : node.level === 4 ? "text-[48px]" : node.level === 5 ? "text-[44px]" : "text-[40px]"} font-bold my-10`,
7303
- "data-richtext-node": "heading",
7304
- "data-heading-level": node.level,
7305
- children: node.nodes.map((child, childIndex) => renderNodeToReact(child, childIndex, options))
7306
- }, `heading-${index}`);
7303
+ case "heading": {
7304
+ const HeadingTag = `h${node.level}`;
7305
+ const sizeClass = node.level === 1 ? "text-[64px]" : node.level === 2 ? "text-[58px]" : node.level === 3 ? "text-[52px]" : node.level === 4 ? "text-[48px]" : node.level === 5 ? "text-[44px]" : "text-[40px]";
7306
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(HeadingTag, {
7307
+ className: `${sizeClass} font-bold my-10`,
7308
+ "data-richtext-node": "heading",
7309
+ "data-heading-level": node.level,
7310
+ children: node.nodes.map((child, childIndex) => renderNodeToReact(child, childIndex, options))
7311
+ }, `heading-${index}`);
7312
+ }
7307
7313
  case "paragraph": return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
7308
7314
  "data-richtext-node": "paragraph",
7309
7315
  children: node.nodes.map((child, childIndex) => renderNodeToReact(child, childIndex, options))
@@ -7333,11 +7339,14 @@ var renderNodeToReact = (node, index, options) => {
7333
7339
  "data-richtext-node": "blockquote",
7334
7340
  children: node.nodes.map((child, childIndex) => renderNodeToReact(child, childIndex, options))
7335
7341
  }, `blockquote-${index}`);
7336
- case "list": return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(node.ordered ? "ol" : "ul", {
7337
- "data-richtext-node": "list",
7338
- "data-list-ordered": node.ordered,
7339
- children: node.items.map((item, itemIndex) => renderNodeToReact(item, itemIndex, options))
7340
- }, `list-${index}`);
7342
+ case "list": {
7343
+ const ListTag = node.ordered ? "ol" : "ul";
7344
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ListTag, {
7345
+ "data-richtext-node": "list",
7346
+ "data-list-ordered": node.ordered,
7347
+ children: node.items.map((item, itemIndex) => renderNodeToReact(item, itemIndex, options))
7348
+ }, `list-${index}`);
7349
+ }
7341
7350
  case "listItem": return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", {
7342
7351
  "data-richtext-node": "listItem",
7343
7352
  children: node.nodes.map((child, childIndex) => renderNodeToReact(child, childIndex, options))
@@ -7645,9 +7654,7 @@ var rgbToHsl = ({ r, g, b }) => {
7645
7654
  case ng:
7646
7655
  h = (nb - nr) / d + 2;
7647
7656
  break;
7648
- default:
7649
- h = (nr - ng) / d + 4;
7650
- break;
7657
+ default: h = (nr - ng) / d + 4;
7651
7658
  }
7652
7659
  return {
7653
7660
  h: h / 6,
@@ -7901,7 +7908,7 @@ var Render = async (event, path, data) => {
7901
7908
  imageStats.push({
7902
7909
  index: ret.length,
7903
7910
  type: "png",
7904
- sizeMb: (imageBuffer.length / (1024 * 1024)).toFixed(3),
7911
+ sizeMb: (imageBuffer.length / 1048576).toFixed(3),
7905
7912
  dimensions
7906
7913
  });
7907
7914
  ret.push(segment.image("base64://" + image));
@@ -8505,14 +8512,16 @@ var BilibiliDBBase = class {
8505
8512
  if (moduleDynamic.desc && moduleDynamic.desc.rich_text_nodes) {
8506
8513
  for (const node of moduleDynamic.desc.rich_text_nodes) if (node.type !== "RICH_TEXT_NODE_TYPE_TEXT") tags.push(node.orig_text);
8507
8514
  }
8508
- if (dynamicData.type === DynamicType.FORWARD && "orig" in dynamicData) if (dynamicData.orig.type === DynamicType.AV) text += dynamicData.orig.modules.module_dynamic.major.archive.title + "";
8509
- else {
8510
- logger$1.debug(`提取子动态文本和tag:https://t.bilibili.com/${dynamicData.id_str}`);
8511
- try {
8512
- text += dynamicData.orig.modules.module_dynamic.major.opus.summary.text + " ";
8513
- for (const node of dynamicData.orig.modules.module_dynamic.major.opus.summary.rich_text_nodes) tags.push(node.orig_text);
8514
- } catch (error) {
8515
- logger$1.error(`提取子动态文本和tag失败:${error}`);
8515
+ if (dynamicData.type === DynamicType.FORWARD && "orig" in dynamicData) {
8516
+ if (dynamicData.orig.type === DynamicType.AV) text += dynamicData.orig.modules.module_dynamic.major.archive.title + "";
8517
+ else {
8518
+ logger$1.debug(`提取子动态文本和tag:https://t.bilibili.com/${dynamicData.id_str}`);
8519
+ try {
8520
+ text += dynamicData.orig.modules.module_dynamic.major.opus.summary.text + " ";
8521
+ for (const node of dynamicData.orig.modules.module_dynamic.major.opus.summary.rich_text_nodes) tags.push(node.orig_text);
8522
+ } catch (error) {
8523
+ logger$1.error(`提取子动态文本和tag失败:${error}`);
8524
+ }
8516
8525
  }
8517
8526
  }
8518
8527
  return {
@@ -11666,10 +11675,11 @@ var processCommentHTML = (htmlContent) => {
11666
11675
  * @returns JSX元素
11667
11676
  */
11668
11677
  var CommentText = ({ content, className, style }) => {
11678
+ const processedContent = processCommentHTML(content);
11669
11679
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
11670
11680
  className,
11671
11681
  style,
11672
- dangerouslySetInnerHTML: { __html: processCommentHTML(content) }
11682
+ dangerouslySetInnerHTML: { __html: processedContent }
11673
11683
  });
11674
11684
  };
11675
11685
  /**
@@ -12284,7 +12294,7 @@ var isProxyableAvatarUrl = (url) => {
12284
12294
  var toProxiedAvatarUrl = (url) => `${AVATAR_PROXY_PATH}?url=${encodeURIComponent(url)}`;
12285
12295
  //#endregion
12286
12296
  //#region ktr/utils/QRCodeAvatar.ts
12287
- var MAX_QRCODE_AVATAR_BYTES = 2 * 1024 * 1024;
12297
+ var MAX_QRCODE_AVATAR_BYTES = 2097152;
12288
12298
  var QRCODE_AVATAR_TIMEOUT_MS = 5e3;
12289
12299
  var QRCODE_AVATAR_CACHE_SIZE = 128;
12290
12300
  var SUPPORTED_QRCODE_AVATAR_TYPES = /* @__PURE__ */ new Set([
@@ -13136,42 +13146,43 @@ var CommentItemComponent$2 = ({ isLast = false, ...props }) => {
13136
13146
  })]
13137
13147
  });
13138
13148
  };
13149
+ var BilibiliComment = import_react.memo((props) => {
13150
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DefaultLayout, {
13151
+ ...props,
13152
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
13153
+ className: "p-5",
13154
+ children: [
13155
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-20" }),
13156
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(VideoInfoHeader$1, {
13157
+ ...props.data,
13158
+ useDarkTheme: isDark(props.ctx)
13159
+ }),
13160
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
13161
+ className: "overflow-hidden mt-8",
13162
+ children: props.data.CommentsData.length > 0 ? props.data.CommentsData.map((comment, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CommentItemComponent$2, {
13163
+ isLast: index === props.data.CommentsData.length - 1,
13164
+ ...comment
13165
+ }, index)) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
13166
+ className: "flex justify-center items-center py-20 text-muted",
13167
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
13168
+ className: "text-center",
13169
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
13170
+ className: "text-xl",
13171
+ children: "暂无评论数据"
13172
+ })
13173
+ })
13174
+ })
13175
+ })
13176
+ ]
13177
+ })
13178
+ });
13179
+ });
13139
13180
  //#endregion
13140
13181
  //#region ktr/template/bilibili/comment/index.tsx
13141
13182
  var comment_default$3 = defineTemplate({
13142
13183
  name: "评论列表",
13143
13184
  description: "B站视频稿件评论列表展示模板",
13144
- component: import_react.memo((props) => {
13145
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DefaultLayout, {
13146
- ...props,
13147
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
13148
- className: "p-5",
13149
- children: [
13150
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-20" }),
13151
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(VideoInfoHeader$1, {
13152
- ...props.data,
13153
- useDarkTheme: isDark(props.ctx)
13154
- }),
13155
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
13156
- className: "overflow-hidden mt-8",
13157
- children: props.data.CommentsData.length > 0 ? props.data.CommentsData.map((comment, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CommentItemComponent$2, {
13158
- isLast: index === props.data.CommentsData.length - 1,
13159
- ...comment
13160
- }, index)) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
13161
- className: "flex justify-center items-center py-20 text-muted",
13162
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
13163
- className: "text-center",
13164
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
13165
- className: "text-xl",
13166
- children: "暂无评论数据"
13167
- })
13168
- })
13169
- })
13170
- })
13171
- ]
13172
- })
13173
- });
13174
- }),
13185
+ component: BilibiliComment,
13175
13186
  validate: (data) => typeof data === "object" && data !== null && typeof data.share_url === "string"
13176
13187
  });
13177
13188
  //#endregion
@@ -14193,17 +14204,18 @@ var BilibiliDynamicContent = (props) => {
14193
14204
  const lastRow = Math.floor((total - 1) / cols);
14194
14205
  const firstRowLastCol = Math.min(cols, total) - 1;
14195
14206
  const lastRowLastCol = (total - 1) % cols;
14207
+ const cornerClasses = [
14208
+ "overflow-hidden",
14209
+ "aspect-square",
14210
+ "shadow-medium",
14211
+ "rounded-2xl",
14212
+ row === 0 && col === 0 ? "rounded-tl-4xl" : "",
14213
+ row === 0 && col === firstRowLastCol ? "rounded-tr-4xl" : "",
14214
+ row === lastRow && col === 0 ? "rounded-bl-4xl" : "",
14215
+ row === lastRow && col === lastRowLastCol ? "rounded-br-4xl" : ""
14216
+ ].filter(Boolean).join(" ");
14196
14217
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
14197
- className: [
14198
- "overflow-hidden",
14199
- "aspect-square",
14200
- "shadow-medium",
14201
- "rounded-2xl",
14202
- row === 0 && col === 0 ? "rounded-tl-4xl" : "",
14203
- row === 0 && col === firstRowLastCol ? "rounded-tr-4xl" : "",
14204
- row === lastRow && col === 0 ? "rounded-bl-4xl" : "",
14205
- row === lastRow && col === lastRowLastCol ? "rounded-br-4xl" : ""
14206
- ].filter(Boolean).join(" "),
14218
+ className: cornerClasses,
14207
14219
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EnhancedImage, {
14208
14220
  src: img.image_src,
14209
14221
  alt: `图片${index + 1}`,
@@ -14456,18 +14468,19 @@ var OriginalDrawContent = ({ content }) => {
14456
14468
  const lastRow = Math.floor((total - 1) / cols);
14457
14469
  const firstRowLastCol = Math.min(cols, total) - 1;
14458
14470
  const lastRowLastCol = (total - 1) % cols;
14471
+ const cornerClasses = [
14472
+ "overflow-hidden",
14473
+ "relative",
14474
+ "shadow-medium",
14475
+ "aspect-square",
14476
+ "rounded-2xl",
14477
+ row === 0 && col === 0 ? "rounded-tl-4xl" : "",
14478
+ row === 0 && col === firstRowLastCol ? "rounded-tr-4xl" : "",
14479
+ row === lastRow && col === 0 ? "rounded-bl-4xl" : "",
14480
+ row === lastRow && col === lastRowLastCol ? "rounded-br-4xl" : ""
14481
+ ].filter(Boolean).join(" ");
14459
14482
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
14460
- className: [
14461
- "overflow-hidden",
14462
- "relative",
14463
- "shadow-medium",
14464
- "aspect-square",
14465
- "rounded-2xl",
14466
- row === 0 && col === 0 ? "rounded-tl-4xl" : "",
14467
- row === 0 && col === firstRowLastCol ? "rounded-tr-4xl" : "",
14468
- row === lastRow && col === 0 ? "rounded-bl-4xl" : "",
14469
- row === lastRow && col === lastRowLastCol ? "rounded-br-4xl" : ""
14470
- ].filter(Boolean).join(" "),
14483
+ className: cornerClasses,
14471
14484
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EnhancedImage, {
14472
14485
  src: img.image_src,
14473
14486
  alt: `图片${index + 1}`,
@@ -16980,66 +16993,72 @@ var CommentItemComponent$1 = (props) => {
16980
16993
  })
16981
16994
  });
16982
16995
  };
16996
+ /**
16997
+ * 抖音评论组件
16998
+ * @param props 组件属性
16999
+ * @returns JSX元素
17000
+ */
17001
+ var DouyinComment = import_react.memo((props) => {
17002
+ const randomSuggestWord = () => {
17003
+ if (props.data.suggestWrod && props.data.suggestWrod.length > 0) {
17004
+ const randomIndex = Math.floor(Math.random() * props.data.suggestWrod.length);
17005
+ return props.data.suggestWrod[randomIndex];
17006
+ }
17007
+ return null;
17008
+ };
17009
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DefaultLayout, {
17010
+ ...props,
17011
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
17012
+ className: "p-5 px-15",
17013
+ children: [
17014
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-20" }),
17015
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(VideoInfoHeader, {
17016
+ ...props.data,
17017
+ useDarkTheme: isDark(props.ctx)
17018
+ }),
17019
+ randomSuggestWord() && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
17020
+ className: "mx-auto my-20 mb-5 ml-10",
17021
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
17022
+ className: "flex gap-3 items-center px-6 py-4 rounded-2xl",
17023
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
17024
+ className: "text-5xl text-muted",
17025
+ children: "大家都在搜:"
17026
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
17027
+ className: "relative text-5xl text-[#04498d] dark:text-[#face15]",
17028
+ children: [randomSuggestWord(), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Search, {
17029
+ size: 32,
17030
+ className: "absolute -top-2 -right-8"
17031
+ })]
17032
+ })]
17033
+ })
17034
+ }),
17035
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
17036
+ className: "overflow-hidden mt-8",
17037
+ children: props.data.CommentsData.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: props.data.CommentsData.map((comment, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CommentItemComponent$1, {
17038
+ ...comment,
17039
+ isLast: index === props.data.CommentsData.length - 1,
17040
+ maxDepth: props.data.maxDepth
17041
+ }, comment.cid || index)) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
17042
+ className: "flex justify-center items-center py-20 text-muted",
17043
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
17044
+ className: "text-center",
17045
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
17046
+ className: "text-xl",
17047
+ children: "暂无评论数据"
17048
+ })
17049
+ })
17050
+ })
17051
+ })
17052
+ ]
17053
+ })
17054
+ });
17055
+ });
16983
17056
  //#endregion
16984
17057
  //#region ktr/template/douyin/comment/index.tsx
16985
17058
  var comment_default$2 = defineTemplate({
16986
17059
  name: "评论列表",
16987
17060
  description: "抖音评论列表展示模板",
16988
- component: import_react.memo((props) => {
16989
- const randomSuggestWord = () => {
16990
- if (props.data.suggestWrod && props.data.suggestWrod.length > 0) {
16991
- const randomIndex = Math.floor(Math.random() * props.data.suggestWrod.length);
16992
- return props.data.suggestWrod[randomIndex];
16993
- }
16994
- return null;
16995
- };
16996
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DefaultLayout, {
16997
- ...props,
16998
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
16999
- className: "p-5 px-15",
17000
- children: [
17001
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-20" }),
17002
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(VideoInfoHeader, {
17003
- ...props.data,
17004
- useDarkTheme: isDark(props.ctx)
17005
- }),
17006
- randomSuggestWord() && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
17007
- className: "mx-auto my-20 mb-5 ml-10",
17008
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
17009
- className: "flex gap-3 items-center px-6 py-4 rounded-2xl",
17010
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
17011
- className: "text-5xl text-muted",
17012
- children: "大家都在搜:"
17013
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
17014
- className: "relative text-5xl text-[#04498d] dark:text-[#face15]",
17015
- children: [randomSuggestWord(), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Search, {
17016
- size: 32,
17017
- className: "absolute -top-2 -right-8"
17018
- })]
17019
- })]
17020
- })
17021
- }),
17022
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
17023
- className: "overflow-hidden mt-8",
17024
- children: props.data.CommentsData.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: props.data.CommentsData.map((comment, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CommentItemComponent$1, {
17025
- ...comment,
17026
- isLast: index === props.data.CommentsData.length - 1,
17027
- maxDepth: props.data.maxDepth
17028
- }, comment.cid || index)) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
17029
- className: "flex justify-center items-center py-20 text-muted",
17030
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
17031
- className: "text-center",
17032
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
17033
- className: "text-xl",
17034
- children: "暂无评论数据"
17035
- })
17036
- })
17037
- })
17038
- })
17039
- ]
17040
- })
17041
- });
17042
- }),
17061
+ component: DouyinComment,
17043
17062
  validate: (data) => typeof data === "object" && data !== null && typeof data.share_url === "string"
17044
17063
  });
17045
17064
  //#endregion
@@ -20519,45 +20538,51 @@ var KuaishouCommentItemComponent = ({ ...props }, isLast = false) => {
20519
20538
  })]
20520
20539
  });
20521
20540
  };
20541
+ /**
20542
+ * 快手评论组件
20543
+ * @param props 组件属性
20544
+ * @returns JSX元素
20545
+ */
20546
+ var KuaishouComment = import_react.memo((props) => {
20547
+ const commentsArray = Array.isArray(props.data?.CommentsData) ? props.data.CommentsData : [];
20548
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DefaultLayout, {
20549
+ ...props,
20550
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20551
+ className: "p-5",
20552
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20553
+ className: "flex justify-between items-center max-w-300 mx-auto p-5",
20554
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(KuaishouVideoInfoHeader, { ...props.data }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(KuaishouQRCodeSection, {
20555
+ ...props.data,
20556
+ useDarkTheme: isDark(props.ctx)
20557
+ })]
20558
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
20559
+ className: "overflow-auto mx-auto max-w-full",
20560
+ children: commentsArray.length > 0 ? commentsArray.map((comment, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(KuaishouCommentItemComponent, {
20561
+ ...comment,
20562
+ isLast: index === commentsArray.length - 1
20563
+ }, comment.cid || index)) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
20564
+ className: "flex justify-center items-center py-20 text-muted",
20565
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20566
+ className: "text-center",
20567
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(MessageCircle, {
20568
+ size: 64,
20569
+ className: "mx-auto mb-4 text-muted/70"
20570
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
20571
+ className: "text-xl",
20572
+ children: "暂无评论数据"
20573
+ })]
20574
+ })
20575
+ })
20576
+ })]
20577
+ })
20578
+ });
20579
+ });
20522
20580
  //#endregion
20523
20581
  //#region ktr/template/kuaishou/comment/index.tsx
20524
20582
  var comment_default$1 = defineTemplate({
20525
20583
  name: "评论列表",
20526
20584
  description: "快手视频评论列表展示模板",
20527
- component: import_react.memo((props) => {
20528
- const commentsArray = Array.isArray(props.data?.CommentsData) ? props.data.CommentsData : [];
20529
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DefaultLayout, {
20530
- ...props,
20531
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20532
- className: "p-5",
20533
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20534
- className: "flex justify-between items-center max-w-300 mx-auto p-5",
20535
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(KuaishouVideoInfoHeader, { ...props.data }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(KuaishouQRCodeSection, {
20536
- ...props.data,
20537
- useDarkTheme: isDark(props.ctx)
20538
- })]
20539
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
20540
- className: "overflow-auto mx-auto max-w-full",
20541
- children: commentsArray.length > 0 ? commentsArray.map((comment, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(KuaishouCommentItemComponent, {
20542
- ...comment,
20543
- isLast: index === commentsArray.length - 1
20544
- }, comment.cid || index)) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
20545
- className: "flex justify-center items-center py-20 text-muted",
20546
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20547
- className: "text-center",
20548
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(MessageCircle, {
20549
- size: 64,
20550
- className: "mx-auto mb-4 text-muted/70"
20551
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
20552
- className: "text-xl",
20553
- children: "暂无评论数据"
20554
- })]
20555
- })
20556
- })
20557
- })]
20558
- })
20559
- });
20560
- }),
20585
+ component: KuaishouComment,
20561
20586
  validate: (data) => typeof data === "object" && data !== null && typeof data.share_url === "string"
20562
20587
  });
20563
20588
  //#endregion
@@ -20574,31 +20599,31 @@ var toSvgDataUri = (svg) => `data:image/svg+xml;charset=utf-8,${encodeURICompone
20574
20599
  var techStackItems = [
20575
20600
  {
20576
20601
  label: "TypeScript",
20577
- iconSrc: toSvgDataUri(typescript.svg)
20602
+ iconSrc: toSvgDataUri(typescript_default.svg)
20578
20603
  },
20579
20604
  {
20580
20605
  label: "SQLite",
20581
- iconSrc: toSvgDataUri(sqlite.svg)
20606
+ iconSrc: toSvgDataUri(sqlite_default.svg)
20582
20607
  },
20583
20608
  {
20584
20609
  label: "React",
20585
- iconSrc: toSvgDataUri(react.svg)
20610
+ iconSrc: toSvgDataUri(react_default.svg)
20586
20611
  },
20587
20612
  {
20588
20613
  label: "Tailwind CSS",
20589
- iconSrc: toSvgDataUri(tailwind_css.svg)
20614
+ iconSrc: toSvgDataUri(tailwind_css_default.svg)
20590
20615
  },
20591
20616
  {
20592
20617
  label: "WebAssembly",
20593
- iconSrc: toSvgDataUri(webassembly.svg)
20618
+ iconSrc: toSvgDataUri(webassembly_default.svg)
20594
20619
  },
20595
20620
  {
20596
20621
  label: "Vite",
20597
- iconSrc: toSvgDataUri(vite.svg)
20622
+ iconSrc: toSvgDataUri(vite_default.svg)
20598
20623
  },
20599
20624
  {
20600
20625
  label: "tsdown",
20601
- iconSrc: toSvgDataUri(tsdown.svg)
20626
+ iconSrc: toSvgDataUri(tsdown_default.svg)
20602
20627
  }
20603
20628
  ];
20604
20629
  /**
@@ -22862,7 +22887,6 @@ var iconRegistry = {
22862
22887
  "ph:paper-plane-right-fill": p$1,
22863
22888
  "ph:arrows-clockwise-fill": m$3,
22864
22889
  "ph:bell-fill": s$1,
22865
- "ph:robot-fill": n$2,
22866
22890
  "ph:monitor-fill": c$2,
22867
22891
  "logos:tiktok-icon": FaTiktok,
22868
22892
  "streamline-ultimate:bilibili-logo-bold": SiBilibili,
@@ -22890,13 +22914,15 @@ var getIconForItem = (icon) => {
22890
22914
  * 展示单个功能的图标、标题和描述
22891
22915
  */
22892
22916
  var MenuItemComponent = ({ item, themeColor }) => {
22917
+ const IconComponent = getIconForItem(item.icon);
22918
+ const iconColor = typeof item.icon === "object" && item.icon?.color ? item.icon.color : themeColor;
22893
22919
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
22894
22920
  className: "flex flex-row gap-8 py-2 relative",
22895
22921
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
22896
22922
  className: "pt-2 shrink-0 relative",
22897
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(getIconForItem(item.icon), {
22923
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IconComponent, {
22898
22924
  className: "w-16 h-16 relative z-10 text-foreground",
22899
- style: { color: typeof item.icon === "object" && item.icon?.color ? item.icon.color : themeColor }
22925
+ style: { color: iconColor }
22900
22926
  })
22901
22927
  }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
22902
22928
  className: "flex-1 min-w-0",
@@ -24483,214 +24509,230 @@ var heroVersionSize = (version) => {
24483
24509
  if (len <= 6) return 150;
24484
24510
  return Math.max(72, Math.min(150, Math.floor(1180 / (len * .6))));
24485
24511
  };
24486
- //#endregion
24487
- //#region ktr/template/other/updateHelp/index.tsx
24488
- var updateHelp_default = defineTemplate({
24489
- name: "更新渠道面板",
24490
- description: "#kkk更新 用法与各渠道可用版本一览",
24491
- component: import_react.memo((props) => {
24492
- const { data } = props;
24493
- const palette = isDark(props.ctx) ? {
24494
- background: "#081416",
24495
- glowPrimary: "rgba(45, 212, 191, 0.28)",
24496
- glowSecondary: "rgba(56, 130, 246, 0.14)",
24497
- glowWarm: "rgba(250, 204, 21, 0.12)",
24498
- bgWord: "#99f6e4",
24499
- ink: "#effefd",
24500
- muted: "rgba(239, 254, 253, 0.62)",
24501
- faint: "rgba(239, 254, 253, 0.36)",
24502
- pillBg: "rgba(45, 212, 191, 0.12)",
24503
- pillBorder: "rgba(94, 234, 212, 0.32)",
24504
- pillText: "#5eead4",
24505
- accentText: "#5eead4",
24506
- success: "#4ade80",
24507
- warning: "#fbbf24",
24508
- noiseOpacity: .16
24509
- } : {
24510
- background: "#effaf8",
24511
- glowPrimary: "rgba(20, 184, 166, 0.26)",
24512
- glowSecondary: "rgba(125, 211, 252, 0.40)",
24513
- glowWarm: "rgba(250, 204, 21, 0.26)",
24514
- bgWord: "#0c3b38",
24515
- ink: "#0c3b38",
24516
- muted: "rgba(12, 59, 56, 0.68)",
24517
- faint: "rgba(12, 59, 56, 0.42)",
24518
- pillBg: "rgba(20, 184, 166, 0.10)",
24519
- pillBorder: "rgba(20, 184, 166, 0.30)",
24520
- pillText: "#0f766e",
24521
- accentText: "#0d9488",
24522
- success: "#15803d",
24523
- warning: "#8a5a06",
24524
- noiseOpacity: .12
24512
+ var UpdateHelp = import_react.memo((props) => {
24513
+ const { data } = props;
24514
+ const palette = isDark(props.ctx) ? {
24515
+ background: "#081416",
24516
+ glowPrimary: "rgba(45, 212, 191, 0.28)",
24517
+ glowSecondary: "rgba(56, 130, 246, 0.14)",
24518
+ glowWarm: "rgba(250, 204, 21, 0.12)",
24519
+ bgWord: "#99f6e4",
24520
+ ink: "#effefd",
24521
+ muted: "rgba(239, 254, 253, 0.62)",
24522
+ faint: "rgba(239, 254, 253, 0.36)",
24523
+ pillBg: "rgba(45, 212, 191, 0.12)",
24524
+ pillBorder: "rgba(94, 234, 212, 0.32)",
24525
+ pillText: "#5eead4",
24526
+ accentText: "#5eead4",
24527
+ success: "#4ade80",
24528
+ warning: "#fbbf24",
24529
+ noiseOpacity: .16
24530
+ } : {
24531
+ background: "#effaf8",
24532
+ glowPrimary: "rgba(20, 184, 166, 0.26)",
24533
+ glowSecondary: "rgba(125, 211, 252, 0.40)",
24534
+ glowWarm: "rgba(250, 204, 21, 0.26)",
24535
+ bgWord: "#0c3b38",
24536
+ ink: "#0c3b38",
24537
+ muted: "rgba(12, 59, 56, 0.68)",
24538
+ faint: "rgba(12, 59, 56, 0.42)",
24539
+ pillBg: "rgba(20, 184, 166, 0.10)",
24540
+ pillBorder: "rgba(20, 184, 166, 0.30)",
24541
+ pillText: "#0f766e",
24542
+ accentText: "#0d9488",
24543
+ success: "#15803d",
24544
+ warning: "#8a5a06",
24545
+ noiseOpacity: .12
24546
+ };
24547
+ /**
24548
+ * 渠道状态:文案按具体状态区分(有更新 / 已是最新 / 低于当前版本 / 暂未发布 / 获取失败),
24549
+ * 颜色只分两档 —— 可升级(success)与置灰(faint):非可升级状态一律不引导行动。
24550
+ * active 供行内所有元素同步置灰。
24551
+ */
24552
+ const statusView = (channel) => {
24553
+ if (channel.status === "missing") return {
24554
+ dot: palette.faint,
24555
+ text: "该渠道暂未发布",
24556
+ active: false
24525
24557
  };
24526
- /**
24527
- * 渠道状态:文案按具体状态区分(有更新 / 已是最新 / 低于当前版本 / 暂未发布 / 获取失败),
24528
- * 颜色只分两档 —— 可升级(success)与置灰(faint):非可升级状态一律不引导行动。
24529
- * active 供行内所有元素同步置灰。
24530
- */
24531
- const statusView = (channel) => {
24532
- if (channel.status === "missing") return {
24533
- dot: palette.faint,
24534
- text: "该渠道暂未发布",
24535
- active: false
24536
- };
24537
- if (channel.status === "error") return {
24538
- dot: palette.faint,
24539
- text: "获取失败",
24540
- active: false
24541
- };
24542
- if (channel.status === "canary") {
24543
- if (channel.hasUpdate) return {
24544
- dot: palette.success,
24545
- text: "有新构建可升级",
24546
- active: true
24547
- };
24548
- return channel.hasUpdate === false ? {
24549
- dot: palette.faint,
24550
- text: "与当前构建一致",
24551
- active: false
24552
- } : {
24553
- dot: palette.faint,
24554
- text: "main 分支构建",
24555
- active: false
24556
- };
24557
- }
24558
- const order = semverCompare(channel.version ?? "0.0.0", data.currentVersion);
24559
- if (channel.hasUpdate !== void 0) return channel.hasUpdate ? {
24560
- dot: palette.success,
24561
- text: "有更新可升级",
24562
- active: true
24563
- } : {
24564
- dot: palette.faint,
24565
- text: order < 0 ? "低于当前版本" : "已是最新",
24566
- active: false
24567
- };
24568
- if (order > 0) return {
24558
+ if (channel.status === "error") return {
24559
+ dot: palette.faint,
24560
+ text: "获取失败",
24561
+ active: false
24562
+ };
24563
+ if (channel.status === "canary") {
24564
+ if (channel.hasUpdate) return {
24569
24565
  dot: palette.success,
24570
- text: "有更新可升级",
24566
+ text: "有新构建可升级",
24571
24567
  active: true
24572
24568
  };
24573
- if (order === 0) return {
24569
+ return channel.hasUpdate === false ? {
24574
24570
  dot: palette.faint,
24575
- text: "已是最新",
24571
+ text: "与当前构建一致",
24576
24572
  active: false
24577
- };
24578
- return {
24573
+ } : {
24579
24574
  dot: palette.faint,
24580
- text: "低于当前版本",
24575
+ text: "main 分支构建",
24581
24576
  active: false
24582
24577
  };
24578
+ }
24579
+ const order = semverCompare(channel.version ?? "0.0.0", data.currentVersion);
24580
+ if (channel.hasUpdate !== void 0) return channel.hasUpdate ? {
24581
+ dot: palette.success,
24582
+ text: "有更新可升级",
24583
+ active: true
24584
+ } : {
24585
+ dot: palette.faint,
24586
+ text: order < 0 ? "低于当前版本" : "已是最新",
24587
+ active: false
24583
24588
  };
24584
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DefaultLayout, {
24585
- ...props,
24586
- className: "relative min-h-440 overflow-hidden",
24587
- style: { backgroundColor: palette.background },
24588
- children: [
24589
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
24590
- className: "pointer-events-none absolute inset-0 z-0 overflow-hidden",
24591
- children: [
24592
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
24593
- className: "absolute -left-130 -top-120 h-337.5 w-375 rounded-full blur-[230px]",
24594
- style: { background: `radial-gradient(ellipse at center, ${palette.glowPrimary} 0%, transparent 70%)` }
24595
- }),
24596
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
24597
- className: "absolute -right-130 top-[36%] h-312.5 w-300 rounded-full blur-[240px]",
24598
- style: { background: `radial-gradient(ellipse at center, ${palette.glowSecondary} 0%, transparent 72%)` }
24599
- }),
24600
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
24601
- className: "absolute -bottom-120 -left-80 h-287.5 w-337.5 rounded-full blur-[260px]",
24602
- style: { background: `radial-gradient(ellipse at center, ${palette.glowWarm} 0%, transparent 72%)` }
24603
- }),
24604
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
24605
- className: "pointer-events-none absolute right-14 top-8 select-none font-bold leading-none tracking-[-0.02em]",
24606
- style: {
24607
- fontSize: "220px",
24608
- opacity: .04,
24609
- color: palette.bgWord
24610
- },
24611
- children: "UPDATE"
24612
- })
24613
- ]
24614
- }),
24615
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
24616
- className: "pointer-events-none absolute inset-0 z-0",
24617
- style: { opacity: palette.noiseOpacity },
24618
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", {
24619
- className: "h-full w-full",
24620
- xmlns: "http://www.w3.org/2000/svg",
24621
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("filter", {
24622
- id: "updateHelpNoise",
24623
- x: "0%",
24624
- y: "0%",
24625
- width: "100%",
24626
- height: "100%",
24627
- children: [
24628
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("feTurbulence", {
24629
- type: "fractalNoise",
24630
- baseFrequency: "0.8",
24631
- numOctaves: "1",
24632
- stitchTiles: "stitch",
24633
- result: "noise"
24589
+ if (order > 0) return {
24590
+ dot: palette.success,
24591
+ text: "有更新可升级",
24592
+ active: true
24593
+ };
24594
+ if (order === 0) return {
24595
+ dot: palette.faint,
24596
+ text: "已是最新",
24597
+ active: false
24598
+ };
24599
+ return {
24600
+ dot: palette.faint,
24601
+ text: "低于当前版本",
24602
+ active: false
24603
+ };
24604
+ };
24605
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DefaultLayout, {
24606
+ ...props,
24607
+ className: "relative min-h-440 overflow-hidden",
24608
+ style: { backgroundColor: palette.background },
24609
+ children: [
24610
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
24611
+ className: "pointer-events-none absolute inset-0 z-0 overflow-hidden",
24612
+ children: [
24613
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
24614
+ className: "absolute -left-130 -top-120 h-337.5 w-375 rounded-full blur-[230px]",
24615
+ style: { background: `radial-gradient(ellipse at center, ${palette.glowPrimary} 0%, transparent 70%)` }
24616
+ }),
24617
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
24618
+ className: "absolute -right-130 top-[36%] h-312.5 w-300 rounded-full blur-[240px]",
24619
+ style: { background: `radial-gradient(ellipse at center, ${palette.glowSecondary} 0%, transparent 72%)` }
24620
+ }),
24621
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
24622
+ className: "absolute -bottom-120 -left-80 h-287.5 w-337.5 rounded-full blur-[260px]",
24623
+ style: { background: `radial-gradient(ellipse at center, ${palette.glowWarm} 0%, transparent 72%)` }
24624
+ }),
24625
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
24626
+ className: "pointer-events-none absolute right-14 top-8 select-none font-bold leading-none tracking-[-0.02em]",
24627
+ style: {
24628
+ fontSize: "220px",
24629
+ opacity: .04,
24630
+ color: palette.bgWord
24631
+ },
24632
+ children: "UPDATE"
24633
+ })
24634
+ ]
24635
+ }),
24636
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
24637
+ className: "pointer-events-none absolute inset-0 z-0",
24638
+ style: { opacity: palette.noiseOpacity },
24639
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", {
24640
+ className: "h-full w-full",
24641
+ xmlns: "http://www.w3.org/2000/svg",
24642
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("filter", {
24643
+ id: "updateHelpNoise",
24644
+ x: "0%",
24645
+ y: "0%",
24646
+ width: "100%",
24647
+ height: "100%",
24648
+ children: [
24649
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("feTurbulence", {
24650
+ type: "fractalNoise",
24651
+ baseFrequency: "0.8",
24652
+ numOctaves: "1",
24653
+ stitchTiles: "stitch",
24654
+ result: "noise"
24655
+ }),
24656
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("feColorMatrix", {
24657
+ type: "saturate",
24658
+ values: "0",
24659
+ result: "gray"
24660
+ }),
24661
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("feComponentTransfer", { children: [
24662
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("feFuncR", {
24663
+ type: "discrete",
24664
+ tableValues: "0 1"
24634
24665
  }),
24635
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("feColorMatrix", {
24636
- type: "saturate",
24637
- values: "0",
24638
- result: "gray"
24666
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("feFuncG", {
24667
+ type: "discrete",
24668
+ tableValues: "0 1"
24639
24669
  }),
24640
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("feComponentTransfer", { children: [
24641
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("feFuncR", {
24642
- type: "discrete",
24643
- tableValues: "0 1"
24644
- }),
24645
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("feFuncG", {
24646
- type: "discrete",
24647
- tableValues: "0 1"
24648
- }),
24649
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("feFuncB", {
24650
- type: "discrete",
24651
- tableValues: "0 1"
24652
- })
24653
- ] })
24654
- ]
24655
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", {
24656
- width: "100%",
24657
- height: "100%",
24658
- filter: "url(#updateHelpNoise)"
24659
- })]
24660
- })
24661
- }),
24662
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("main", {
24663
- className: "relative z-10 px-22 pb-16 pt-20",
24664
- children: [
24665
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("header", {
24666
- className: "relative flex items-center justify-between gap-12",
24667
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
24668
- className: "flex items-center gap-4",
24669
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
24670
- className: "h-3 w-3 rounded-full",
24671
- style: { background: palette.accentText }
24672
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
24673
- className: "whitespace-nowrap text-[24px] font-bold tracking-[0.28em] text-foreground/44",
24674
- children: "更新面板 · UPDATE PANEL"
24675
- })]
24670
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("feFuncB", {
24671
+ type: "discrete",
24672
+ tableValues: "0 1"
24673
+ })
24674
+ ] })
24675
+ ]
24676
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", {
24677
+ width: "100%",
24678
+ height: "100%",
24679
+ filter: "url(#updateHelpNoise)"
24680
+ })]
24681
+ })
24682
+ }),
24683
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("main", {
24684
+ className: "relative z-10 px-22 pb-16 pt-20",
24685
+ children: [
24686
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("header", {
24687
+ className: "relative flex items-center justify-between gap-12",
24688
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
24689
+ className: "flex items-center gap-4",
24690
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
24691
+ className: "h-3 w-3 rounded-full",
24692
+ style: { background: palette.accentText }
24676
24693
  }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
24677
- className: "whitespace-nowrap rounded-full border px-6 py-2 text-[22px] font-bold tracking-[0.14em]",
24678
- style: {
24679
- borderColor: palette.pillBorder,
24680
- background: palette.pillBg,
24681
- color: palette.pillText
24682
- },
24683
- children: data.currentChannel
24694
+ className: "whitespace-nowrap text-[24px] font-bold tracking-[0.28em] text-foreground/44",
24695
+ children: "更新面板 · UPDATE PANEL"
24684
24696
  })]
24685
- }),
24686
- heroStacked(data.currentVersion) ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", {
24697
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
24698
+ className: "whitespace-nowrap rounded-full border px-6 py-2 text-[22px] font-bold tracking-[0.14em]",
24699
+ style: {
24700
+ borderColor: palette.pillBorder,
24701
+ background: palette.pillBg,
24702
+ color: palette.pillText
24703
+ },
24704
+ children: data.currentChannel
24705
+ })]
24706
+ }),
24707
+ heroStacked(data.currentVersion) ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", {
24708
+ className: "whitespace-nowrap text-[96px] font-bold leading-[1.04] tracking-[-0.02em] text-foreground",
24709
+ children: "更新渠道"
24710
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
24711
+ className: "mt-6 whitespace-nowrap text-[30px] font-semibold text-foreground/48",
24712
+ children: data.currentChannel === "金丝雀" ? "金丝雀构建跟随 main 分支实时发布,可随时切换回正式渠道" : "各渠道可用版本与 #kkk更新 用法一览"
24713
+ })] }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
24714
+ className: "relative mt-14",
24715
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
24716
+ className: "text-[22px] font-bold uppercase tracking-[0.22em] text-foreground/36",
24717
+ children: "当前安装 · INSTALLED"
24718
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
24719
+ className: "mt-4 whitespace-nowrap font-mono font-bold leading-none tracking-[-0.05em] tabular-nums text-foreground",
24720
+ style: { fontSize: `${heroVersionSize(data.currentVersion)}px` },
24721
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
24722
+ className: "mr-3 align-top text-[0.42em] font-bold text-foreground/40",
24723
+ children: "v"
24724
+ }), data.currentVersion]
24725
+ })]
24726
+ })] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
24727
+ className: "relative mt-14 flex items-end justify-between gap-12",
24728
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", {
24687
24729
  className: "whitespace-nowrap text-[96px] font-bold leading-[1.04] tracking-[-0.02em] text-foreground",
24688
24730
  children: "更新渠道"
24689
24731
  }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
24690
24732
  className: "mt-6 whitespace-nowrap text-[30px] font-semibold text-foreground/48",
24691
24733
  children: data.currentChannel === "金丝雀" ? "金丝雀构建跟随 main 分支实时发布,可随时切换回正式渠道" : "各渠道可用版本与 #kkk更新 用法一览"
24692
24734
  })] }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
24693
- className: "relative mt-14",
24735
+ className: "flex shrink-0 flex-col items-end",
24694
24736
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
24695
24737
  className: "text-[22px] font-bold uppercase tracking-[0.22em] text-foreground/36",
24696
24738
  children: "当前安装 · INSTALLED"
@@ -24702,110 +24744,37 @@ var updateHelp_default = defineTemplate({
24702
24744
  children: "v"
24703
24745
  }), data.currentVersion]
24704
24746
  })]
24705
- })] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
24706
- className: "relative mt-14 flex items-end justify-between gap-12",
24707
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", {
24708
- className: "whitespace-nowrap text-[96px] font-bold leading-[1.04] tracking-[-0.02em] text-foreground",
24709
- children: "更新渠道"
24710
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
24711
- className: "mt-6 whitespace-nowrap text-[30px] font-semibold text-foreground/48",
24712
- children: data.currentChannel === "金丝雀" ? "金丝雀构建跟随 main 分支实时发布,可随时切换回正式渠道" : "各渠道可用版本与 #kkk更新 用法一览"
24713
- })] }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
24714
- className: "flex shrink-0 flex-col items-end",
24715
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
24716
- className: "text-[22px] font-bold uppercase tracking-[0.22em] text-foreground/36",
24717
- children: "当前安装 · INSTALLED"
24718
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
24719
- className: "mt-4 whitespace-nowrap font-mono font-bold leading-none tracking-[-0.05em] tabular-nums text-foreground",
24720
- style: { fontSize: `${heroVersionSize(data.currentVersion)}px` },
24721
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
24722
- className: "mr-3 align-top text-[0.42em] font-bold text-foreground/40",
24723
- children: "v"
24724
- }), data.currentVersion]
24725
- })]
24747
+ })]
24748
+ }),
24749
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", {
24750
+ className: "relative mt-24",
24751
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
24752
+ className: "flex items-center gap-4",
24753
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
24754
+ className: "h-3 w-3 rounded-full",
24755
+ style: { background: palette.accentText }
24756
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
24757
+ className: "text-[24px] font-bold tracking-[0.28em] text-foreground/44",
24758
+ children: "可用版本 · AVAILABLE"
24726
24759
  })]
24727
- }),
24728
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", {
24729
- className: "relative mt-24",
24730
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
24731
- className: "flex items-center gap-4",
24732
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
24733
- className: "h-3 w-3 rounded-full",
24734
- style: { background: palette.accentText }
24735
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
24736
- className: "text-[24px] font-bold tracking-[0.28em] text-foreground/44",
24737
- children: "可用版本 · AVAILABLE"
24738
- })]
24739
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
24740
- className: "mt-12 flex flex-col gap-14",
24741
- children: data.channels.map((channel) => {
24742
- const status = statusView(channel);
24743
- const publishedDate = channel.publishedAt ? new Date(channel.publishedAt) : void 0;
24744
- if (channel.status === "canary") return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
24745
- className: "flex flex-col gap-4",
24746
- children: [
24747
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
24748
- className: "flex items-center justify-between gap-10",
24749
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
24750
- className: "flex items-center gap-4",
24751
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
24752
- className: "whitespace-nowrap text-[30px] font-semibold",
24753
- style: { color: status.active ? palette.muted : palette.faint },
24754
- children: channel.label
24755
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
24756
- className: "whitespace-nowrap rounded-full border px-4 py-0.5 font-mono text-[20px] font-semibold",
24757
- style: {
24758
- borderColor: palette.pillBorder,
24759
- background: palette.pillBg,
24760
- color: status.active ? palette.pillText : palette.faint
24761
- },
24762
- children: channel.tag
24763
- })]
24764
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
24765
- className: "flex items-center gap-6",
24766
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
24767
- className: "whitespace-nowrap font-mono text-[46px] font-bold leading-none",
24768
- style: { color: status.active ? palette.ink : palette.faint },
24769
- children: ["SHA: ", channel.version]
24770
- })
24771
- })]
24772
- }),
24773
- channel.installCommand && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
24774
- className: "whitespace-nowrap rounded-3xl px-7 py-4 font-mono text-[27px] font-semibold",
24775
- style: {
24776
- background: status.active ? palette.pillBg : "transparent",
24777
- color: status.active ? palette.pillText : palette.faint
24778
- },
24779
- children: channel.installCommand
24780
- }),
24781
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
24782
- className: "flex items-center justify-between gap-10 whitespace-nowrap",
24783
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
24784
- className: "text-[24px] text-foreground/42",
24785
- children: ["发布于 ", publishedDate && format(publishedDate, "yyyy/MM/dd HH:mm")]
24786
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
24787
- className: "font-mono text-[24px] font-semibold",
24788
- style: { color: palette.faint },
24789
- title: channel.publishedAt,
24790
- children: publishedDate && formatDistanceToNow(publishedDate, {
24791
- addSuffix: true,
24792
- locale: zhCN
24793
- })
24794
- })]
24795
- })
24796
- ]
24797
- }, channel.tag);
24798
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
24799
- className: "grid grid-cols-[11rem_1fr_auto] items-center gap-8",
24800
- children: [
24801
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
24802
- className: "flex flex-col gap-2",
24760
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
24761
+ className: "mt-12 flex flex-col gap-14",
24762
+ children: data.channels.map((channel) => {
24763
+ const status = statusView(channel);
24764
+ const publishedDate = channel.publishedAt ? new Date(channel.publishedAt) : void 0;
24765
+ if (channel.status === "canary") return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
24766
+ className: "flex flex-col gap-4",
24767
+ children: [
24768
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
24769
+ className: "flex items-center justify-between gap-10",
24770
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
24771
+ className: "flex items-center gap-4",
24803
24772
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
24804
24773
  className: "whitespace-nowrap text-[30px] font-semibold",
24805
24774
  style: { color: status.active ? palette.muted : palette.faint },
24806
24775
  children: channel.label
24807
24776
  }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
24808
- className: "w-fit whitespace-nowrap rounded-full border px-4 py-0.5 font-mono text-[20px] font-semibold",
24777
+ className: "whitespace-nowrap rounded-full border px-4 py-0.5 font-mono text-[20px] font-semibold",
24809
24778
  style: {
24810
24779
  borderColor: palette.pillBorder,
24811
24780
  background: palette.pillBg,
@@ -24813,86 +24782,144 @@ var updateHelp_default = defineTemplate({
24813
24782
  },
24814
24783
  children: channel.tag
24815
24784
  })]
24816
- }),
24817
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
24818
- className: "whitespace-nowrap font-mono text-[24px] font-semibold",
24785
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
24786
+ className: "flex items-center gap-6",
24787
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
24788
+ className: "whitespace-nowrap font-mono text-[46px] font-bold leading-none",
24789
+ style: { color: status.active ? palette.ink : palette.faint },
24790
+ children: ["SHA: ", channel.version]
24791
+ })
24792
+ })]
24793
+ }),
24794
+ channel.installCommand && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
24795
+ className: "whitespace-nowrap rounded-3xl px-7 py-4 font-mono text-[27px] font-semibold",
24796
+ style: {
24797
+ background: status.active ? palette.pillBg : "transparent",
24798
+ color: status.active ? palette.pillText : palette.faint
24799
+ },
24800
+ children: channel.installCommand
24801
+ }),
24802
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
24803
+ className: "flex items-center justify-between gap-10 whitespace-nowrap",
24804
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
24805
+ className: "text-[24px] text-foreground/42",
24806
+ children: ["发布于 ", publishedDate && format(publishedDate, "yyyy/MM/dd HH:mm")]
24807
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
24808
+ className: "font-mono text-[24px] font-semibold",
24809
+ style: { color: palette.faint },
24810
+ title: channel.publishedAt,
24811
+ children: publishedDate && formatDistanceToNow(publishedDate, {
24812
+ addSuffix: true,
24813
+ locale: zhCN
24814
+ })
24815
+ })]
24816
+ })
24817
+ ]
24818
+ }, channel.tag);
24819
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
24820
+ className: "grid grid-cols-[11rem_1fr_auto] items-center gap-8",
24821
+ children: [
24822
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
24823
+ className: "flex flex-col gap-2",
24824
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
24825
+ className: "whitespace-nowrap text-[30px] font-semibold",
24819
24826
  style: { color: status.active ? palette.muted : palette.faint },
24820
- children: channel.command
24821
- }),
24822
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
24823
- className: "flex flex-col items-end gap-2.5 whitespace-nowrap",
24827
+ children: channel.label
24828
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
24829
+ className: "w-fit whitespace-nowrap rounded-full border px-4 py-0.5 font-mono text-[20px] font-semibold",
24830
+ style: {
24831
+ borderColor: palette.pillBorder,
24832
+ background: palette.pillBg,
24833
+ color: status.active ? palette.pillText : palette.faint
24834
+ },
24835
+ children: channel.tag
24836
+ })]
24837
+ }),
24838
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
24839
+ className: "whitespace-nowrap font-mono text-[24px] font-semibold",
24840
+ style: { color: status.active ? palette.muted : palette.faint },
24841
+ children: channel.command
24842
+ }),
24843
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
24844
+ className: "flex flex-col items-end gap-2.5 whitespace-nowrap",
24845
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
24846
+ className: "font-mono text-[56px] font-bold leading-none tracking-[-0.02em] tabular-nums",
24847
+ style: { color: status.active ? palette.ink : palette.faint },
24848
+ children: channel.status === "ok" ? `v${channel.version}` : "—"
24849
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
24850
+ className: "flex items-center gap-3 text-[24px] font-semibold",
24851
+ style: { color: status.dot },
24824
24852
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
24825
- className: "font-mono text-[56px] font-bold leading-none tracking-[-0.02em] tabular-nums",
24826
- style: { color: status.active ? palette.ink : palette.faint },
24827
- children: channel.status === "ok" ? `v${channel.version}` : "—"
24828
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
24829
- className: "flex items-center gap-3 text-[24px] font-semibold",
24830
- style: { color: status.dot },
24831
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
24832
- className: "h-2.5 w-2.5 rounded-full",
24833
- style: { background: status.dot }
24834
- }), status.text]
24835
- })]
24836
- })
24837
- ]
24838
- }, channel.tag);
24839
- })
24840
- })]
24841
- }),
24842
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", {
24843
- className: "relative mt-28",
24844
- children: [
24845
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
24846
- className: "flex items-center gap-4",
24853
+ className: "h-2.5 w-2.5 rounded-full",
24854
+ style: { background: status.dot }
24855
+ }), status.text]
24856
+ })]
24857
+ })
24858
+ ]
24859
+ }, channel.tag);
24860
+ })
24861
+ })]
24862
+ }),
24863
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", {
24864
+ className: "relative mt-28",
24865
+ children: [
24866
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
24867
+ className: "flex items-center gap-4",
24868
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
24869
+ className: "h-3 w-3 rounded-full",
24870
+ style: { background: palette.accentText }
24871
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
24872
+ className: "text-[24px] font-bold tracking-[0.28em] text-foreground/44",
24873
+ children: "用法 · COMMANDS"
24874
+ })]
24875
+ }),
24876
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
24877
+ className: "mt-12 flex flex-col gap-10",
24878
+ children: [
24879
+ {
24880
+ command: "#kkk更新",
24881
+ desc: "更新到最新正式版"
24882
+ },
24883
+ {
24884
+ command: "#kkk更新rc",
24885
+ desc: "更新到预览渠道最新版"
24886
+ },
24887
+ {
24888
+ command: "#kkk更新beta",
24889
+ desc: "更新到测试渠道最新版"
24890
+ },
24891
+ {
24892
+ command: "#kkk更新<版本号>",
24893
+ desc: "更新到指定 stable 版本,例如 #kkk更新2.45.0"
24894
+ }
24895
+ ].map((item) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
24896
+ className: "grid grid-cols-[24rem_1fr] items-baseline gap-8",
24847
24897
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
24848
- className: "h-3 w-3 rounded-full",
24849
- style: { background: palette.accentText }
24898
+ className: "whitespace-nowrap font-mono text-[34px] font-bold text-foreground",
24899
+ children: item.command
24850
24900
  }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
24851
- className: "text-[24px] font-bold tracking-[0.28em] text-foreground/44",
24852
- children: "用法 · COMMANDS"
24901
+ className: "whitespace-nowrap text-[26px] font-semibold text-foreground/48",
24902
+ children: item.desc
24853
24903
  })]
24854
- }),
24855
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
24856
- className: "mt-12 flex flex-col gap-10",
24857
- children: [
24858
- {
24859
- command: "#kkk更新",
24860
- desc: "更新到最新正式版"
24861
- },
24862
- {
24863
- command: "#kkk更新rc",
24864
- desc: "更新到预览渠道最新版"
24865
- },
24866
- {
24867
- command: "#kkk更新beta",
24868
- desc: "更新到测试渠道最新版"
24869
- },
24870
- {
24871
- command: "#kkk更新<版本号>",
24872
- desc: "更新到指定 stable 版本,例如 #kkk更新2.45.0"
24873
- }
24874
- ].map((item) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
24875
- className: "grid grid-cols-[24rem_1fr] items-baseline gap-8",
24876
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
24877
- className: "whitespace-nowrap font-mono text-[34px] font-bold text-foreground",
24878
- children: item.command
24879
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
24880
- className: "whitespace-nowrap text-[26px] font-semibold text-foreground/48",
24881
- children: item.desc
24882
- })]
24883
- }, item.command))
24884
- }),
24885
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
24886
- className: "mt-16 flex flex-col gap-2 whitespace-nowrap font-mono text-[22px] font-semibold text-foreground/28",
24887
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "金丝雀版本经 pkg.pr.new 分发,不提供渠道订阅与更新推送" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "指定低于当前安装版本的版本号属于降级,需回复「确认」才会执行" })]
24888
- })
24889
- ]
24890
- })
24891
- ]
24892
- })
24893
- ]
24894
- });
24895
- })
24904
+ }, item.command))
24905
+ }),
24906
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
24907
+ className: "mt-16 flex flex-col gap-2 whitespace-nowrap font-mono text-[22px] font-semibold text-foreground/28",
24908
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "金丝雀版本经 pkg.pr.new 分发,不提供渠道订阅与更新推送" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "指定低于当前安装版本的版本号属于降级,需回复「确认」才会执行" })]
24909
+ })
24910
+ ]
24911
+ })
24912
+ ]
24913
+ })
24914
+ ]
24915
+ });
24916
+ });
24917
+ //#endregion
24918
+ //#region ktr/template/other/updateHelp/index.tsx
24919
+ var updateHelp_default = defineTemplate({
24920
+ name: "更新渠道面板",
24921
+ description: "#kkk更新 用法与各渠道可用版本一览",
24922
+ component: UpdateHelp
24896
24923
  });
24897
24924
  //#endregion
24898
24925
  //#region ktr/template/other/version_warning/components/VersionWarning.tsx
@@ -26896,20 +26923,8 @@ var buildDurationCurveOption = (data, dark) => {
26896
26923
  };
26897
26924
  //#endregion
26898
26925
  //#region ktr/template/statistics/global/components/GlobalStatistics.tsx
26899
- /**
26900
- * 全局解析统计海报。
26901
- *
26902
- * 与群海报同一套密排卡片版式:每张图独占一张卡、卡内自带紧凑标题行,
26903
- * 两列网格铺满 1440 宽的画面,尽量压低总高度以适配手机竖屏浏览。
26904
- * 图表由 ECharts 在 render 期同步出 SVG 字符串再注入,不用 hooks、不碰 DOM。
26905
- */
26906
- /** 海报内容区宽度:1440 - 左右各 72(p-18) */
26907
- var CONTENT_WIDTH$1 = 1296;
26908
- var HALF_CARD_WIDTH$1 = (CONTENT_WIDTH$1 - 56) / 2;
26909
- /** 卡片内边距 p-6 = 24px,算画布宽度时必须减掉,否则 SVG 会溢出卡片边框 */
26910
- var CARD_PADDING$1 = 24;
26911
- var FULL_CHART_WIDTH$1 = CONTENT_WIDTH$1 - CARD_PADDING$1 * 2;
26912
- var HALF_CHART_WIDTH$1 = HALF_CARD_WIDTH$1 - CARD_PADDING$1 * 2;
26926
+ var FULL_CHART_WIDTH$1 = 1248;
26927
+ var HALF_CHART_WIDTH$1 = 572;
26913
26928
  var HALF_CHART_HEIGHT$1 = 340;
26914
26929
  /**
26915
26930
  * 热力图的画布高度。
@@ -27617,23 +27632,8 @@ var global_default = defineTemplate({
27617
27632
  });
27618
27633
  //#endregion
27619
27634
  //#region ktr/template/statistics/group/components/GroupStatistics.tsx
27620
- /**
27621
- * 群组解析统计海报。
27622
- *
27623
- * 版式按「手机竖屏一屏尽量装下」设计:1440 宽的画面里全部走卡片网格,
27624
- * 每张图独占一张卡,卡内自带紧凑标题行 —— 旧版那种「大标题 + 160px 下边距」的分区头
27625
- * 每张图要吃掉 360px,是海报被撑到 6900px 的主因。
27626
- *
27627
- * 图表由 ECharts 在 render 期同步渲染成 SVG 字符串后注入,
27628
- * 组件不持有状态、不碰 DOM、不用 hooks。配色约束见 `chartTheme.ts` 文件头。
27629
- */
27630
- /** 海报内容区宽度:1440 - 左右各 72(p-18) */
27631
- var CONTENT_WIDTH = 1296;
27632
- var HALF_CARD_WIDTH = (CONTENT_WIDTH - 56) / 2;
27633
- /** 卡片内边距 p-6 = 24px,算图表画布宽度时必须减掉,否则 SVG 会溢出卡片边框 */
27634
- var CARD_PADDING = 24;
27635
- var FULL_CHART_WIDTH = CONTENT_WIDTH - CARD_PADDING * 2;
27636
- var HALF_CHART_WIDTH = HALF_CARD_WIDTH - CARD_PADDING * 2;
27635
+ var FULL_CHART_WIDTH = 1248;
27636
+ var HALF_CHART_WIDTH = 572;
27637
27637
  /** 半宽卡片的图表高度 */
27638
27638
  var HALF_CHART_HEIGHT = 340;
27639
27639
  /**
@@ -28403,39 +28403,45 @@ var CommentItemComponent = ({ ...props }, isLast = false) => {
28403
28403
  })]
28404
28404
  });
28405
28405
  };
28406
+ /**
28407
+ * 小红书评论组件
28408
+ * @param props 组件属性
28409
+ * @returns JSX元素
28410
+ */
28411
+ var XiaohongshuComment = import_react.memo((props) => {
28412
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DefaultLayout, {
28413
+ ...props,
28414
+ children: [
28415
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-30" }),
28416
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(NoteInfoHeader, {
28417
+ ...props.data,
28418
+ useDarkTheme: isDark(props.ctx)
28419
+ }),
28420
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
28421
+ className: "overflow-auto mx-20 max-w-full",
28422
+ children: props.data.CommentsData.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
28423
+ className: "divide-y divide-divider",
28424
+ children: props.data.CommentsData.map((comment, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CommentItemComponent, {
28425
+ ...comment,
28426
+ isLast: index === props.data.CommentsData.length - 1
28427
+ }, comment.id))
28428
+ }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
28429
+ className: "flex justify-center items-center py-20",
28430
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
28431
+ className: "text-[60px] text-muted",
28432
+ children: "暂无评论"
28433
+ })
28434
+ })
28435
+ })
28436
+ ]
28437
+ });
28438
+ });
28406
28439
  //#endregion
28407
28440
  //#region ktr/template/xiaohongshu/comment/index.tsx
28408
28441
  var comment_default = defineTemplate({
28409
28442
  name: "评论列表",
28410
28443
  description: "小红书评论列表展示模板",
28411
- component: import_react.memo((props) => {
28412
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DefaultLayout, {
28413
- ...props,
28414
- children: [
28415
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-30" }),
28416
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(NoteInfoHeader, {
28417
- ...props.data,
28418
- useDarkTheme: isDark(props.ctx)
28419
- }),
28420
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
28421
- className: "overflow-auto mx-20 max-w-full",
28422
- children: props.data.CommentsData.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
28423
- className: "divide-y divide-divider",
28424
- children: props.data.CommentsData.map((comment, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CommentItemComponent, {
28425
- ...comment,
28426
- isLast: index === props.data.CommentsData.length - 1
28427
- }, comment.id))
28428
- }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
28429
- className: "flex justify-center items-center py-20",
28430
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
28431
- className: "text-[60px] text-muted",
28432
- children: "暂无评论"
28433
- })
28434
- })
28435
- })
28436
- ]
28437
- });
28438
- })
28444
+ component: XiaohongshuComment
28439
28445
  });
28440
28446
  //#endregion
28441
28447
  //#region ktr/template/xiaohongshu/noteInfo/components/noteInfo.tsx
@@ -28671,34 +28677,35 @@ var NoteContent = ({ data }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("se
28671
28677
  * 互动数据行:大数字做视觉锚点,只有点赞用心红,其余中性色
28672
28678
  */
28673
28679
  var NoteStatsRow = ({ data }) => {
28680
+ const stats = [
28681
+ {
28682
+ icon: Heart,
28683
+ value: data.statistics.liked_count,
28684
+ label: "点赞",
28685
+ accent: true
28686
+ },
28687
+ {
28688
+ icon: MessageCircle,
28689
+ value: data.statistics.comment_count,
28690
+ label: "评论",
28691
+ accent: false
28692
+ },
28693
+ {
28694
+ icon: Star,
28695
+ value: data.statistics.collected_count,
28696
+ label: "收藏",
28697
+ accent: false
28698
+ },
28699
+ {
28700
+ icon: Share2,
28701
+ value: data.statistics.share_count,
28702
+ label: "分享",
28703
+ accent: false
28704
+ }
28705
+ ];
28674
28706
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("section", {
28675
28707
  className: "mt-14 flex flex-wrap items-end gap-x-20 gap-y-8",
28676
- children: [
28677
- {
28678
- icon: Heart,
28679
- value: data.statistics.liked_count,
28680
- label: "点赞",
28681
- accent: true
28682
- },
28683
- {
28684
- icon: MessageCircle,
28685
- value: data.statistics.comment_count,
28686
- label: "评论",
28687
- accent: false
28688
- },
28689
- {
28690
- icon: Star,
28691
- value: data.statistics.collected_count,
28692
- label: "收藏",
28693
- accent: false
28694
- },
28695
- {
28696
- icon: Share2,
28697
- value: data.statistics.share_count,
28698
- label: "分享",
28699
- accent: false
28700
- }
28701
- ].map((stat) => {
28708
+ children: stats.map((stat) => {
28702
28709
  const Icon = stat.icon;
28703
28710
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
28704
28711
  className: "min-w-40",
@@ -29821,7 +29828,9 @@ async function burnBiliDanmaku(videoPath, danmakuList, outputPath, options = {})
29821
29828
  const assPath = videoPath.replace(/\.[^.]+$/, "_danmaku.ass");
29822
29829
  fs.writeFileSync(assPath, assContent, "utf-8");
29823
29830
  logger$1.debug(`[BiliDanmaku] 弹幕字幕已生成: ${assPath}`);
29824
- const result = await ffmpeg(`-y -i "${videoPath}" -vf "${buildFilter$1(canvas, assPath)}" -r ${frameRate} ${getEncoderParams$1(await detectEncoder$1(videoCodec), sourceBitrate)} -c:a copy "${outputPath}"`);
29831
+ const filter = buildFilter$1(canvas, assPath);
29832
+ const encoderParams = getEncoderParams$1(await detectEncoder$1(videoCodec), sourceBitrate);
29833
+ const result = await ffmpeg(`-y -i "${videoPath}" -vf "${filter}" -r ${frameRate} ${encoderParams} -c:a copy "${outputPath}"`);
29825
29834
  Common.removeFile(assPath, true);
29826
29835
  if (result.status) {
29827
29836
  logger$1.mark(`[BiliDanmaku] 弹幕烧录成功: ${outputPath}`);
@@ -29852,7 +29861,9 @@ async function mergeAndBurnBili(videoPath, audioPath, danmakuList, outputPath, o
29852
29861
  const assPath = videoPath.replace(/\.[^.]+$/, "_danmaku.ass");
29853
29862
  fs.writeFileSync(assPath, assContent, "utf-8");
29854
29863
  logger$1.debug(`[BiliDanmaku] 弹幕字幕已生成: ${assPath},共 ${danmakuList.length} 条`);
29855
- const result = await ffmpeg(`-y -i "${videoPath}" -i "${audioPath}" -f mp4 -vf "${buildFilter$1(canvas, assPath)}" -r ${frameRate} ${getEncoderParams$1(await detectEncoder$1(videoCodec), sourceBitrate)} -c:a aac -b:a 192k "${outputPath}"`);
29864
+ const filter = buildFilter$1(canvas, assPath);
29865
+ const encoderParams = getEncoderParams$1(await detectEncoder$1(videoCodec), sourceBitrate);
29866
+ const result = await ffmpeg(`-y -i "${videoPath}" -i "${audioPath}" -f mp4 -vf "${filter}" -r ${frameRate} ${encoderParams} -c:a aac -b:a 192k "${outputPath}"`);
29856
29867
  Common.removeFile(assPath, true);
29857
29868
  if (result.status) {
29858
29869
  logger$1.mark(`[BiliDanmaku] 视频合成+弹幕烧录成功: ${outputPath}`);
@@ -30015,9 +30026,7 @@ var buildBilibiliVideoDescRichText = (descV2) => {
30015
30026
  case 2:
30016
30027
  nodes.push(createAtNode(`@${rawText}`, item.biz_id?.toString()));
30017
30028
  break;
30018
- default:
30019
- nodes.push(createTextNode(rawText));
30020
- break;
30029
+ default: nodes.push(createTextNode(rawText));
30021
30030
  }
30022
30031
  }
30023
30032
  return createRichTextDocument(nodes, { platform: "bilibili" });
@@ -30260,26 +30269,27 @@ var parseHtmlContentToRichText = (content) => {
30260
30269
  const tag = match[2].toLowerCase();
30261
30270
  const level = match[3] ? parseInt(match[3], 10) : void 0;
30262
30271
  const attrs = match[4] || "";
30263
- if (!isClose) if (tag === "img") {
30264
- const srcMatch = /src="([^"]*)"/.exec(attrs);
30265
- if (srcMatch) {
30266
- const src = fixImageUrl(srcMatch[1]);
30267
- const altMatch = /alt="([^"]*)"/.exec(attrs);
30268
- pushBlock(createImageNode(src, altMatch ? altMatch[1] : "专栏图片"));
30269
- }
30270
- } else if (tag === "br") currentInline.push(createLineBreakNode());
30271
- else if (tag === "li") {
30272
- currentInline = [];
30273
- stack.push({
30274
- tag: "li",
30272
+ if (!isClose) {
30273
+ if (tag === "img") {
30274
+ const srcMatch = /src="([^"]*)"/.exec(attrs);
30275
+ if (srcMatch) {
30276
+ const src = fixImageUrl(srcMatch[1]);
30277
+ const altMatch = /alt="([^"]*)"/.exec(attrs);
30278
+ pushBlock(createImageNode(src, altMatch ? altMatch[1] : "专栏图片"));
30279
+ }
30280
+ } else if (tag === "br") currentInline.push(createLineBreakNode());
30281
+ else if (tag === "li") {
30282
+ currentInline = [];
30283
+ stack.push({
30284
+ tag: "li",
30285
+ nodes: []
30286
+ });
30287
+ } else stack.push({
30288
+ tag,
30289
+ level,
30275
30290
  nodes: []
30276
30291
  });
30277
- } else stack.push({
30278
- tag,
30279
- level,
30280
- nodes: []
30281
- });
30282
- else if (tag === "li") {
30292
+ } else if (tag === "li") {
30283
30293
  const inlineNodes = flushInline();
30284
30294
  pushBlock(createListItemNode([...stack.pop()?.nodes || [], ...inlineNodes]));
30285
30295
  } else if (tag === "p" || tag === "h1" || tag === "h2" || tag === "h3" || tag === "h4" || tag === "h5" || tag === "h6") {
@@ -30301,8 +30311,10 @@ var parseHtmlContentToRichText = (content) => {
30301
30311
  const tail = content.slice(lastIndex);
30302
30312
  if (tail) {
30303
30313
  const inlineNodes = parseInlineHtml(tail);
30304
- if (inlineNodes.length > 0) if (stack.length === 0) nodes.push(createParagraphNode(inlineNodes));
30305
- else currentInline.push(...inlineNodes);
30314
+ if (inlineNodes.length > 0) {
30315
+ if (stack.length === 0) nodes.push(createParagraphNode(inlineNodes));
30316
+ else currentInline.push(...inlineNodes);
30317
+ }
30306
30318
  }
30307
30319
  while (stack.length > 0) {
30308
30320
  const frame = stack.pop();
@@ -30444,8 +30456,6 @@ var buildBilibiliRichTextForwardMessage = async (document, options = {}) => {
30444
30456
  ensureBlockBreak();
30445
30457
  appendText("---");
30446
30458
  ensureBlockBreak();
30447
- break;
30448
- default: break;
30449
30459
  }
30450
30460
  };
30451
30461
  const headerLines = [];
@@ -30525,51 +30535,53 @@ var Bilibili = class extends Base {
30525
30535
  }) + "&platform=html5",
30526
30536
  headers: this.headers
30527
30537
  }).getData();
30528
- if (Config.bilibili.sendContent.some((content) => content === "info")) if (Config.bilibili.videoInfoMode === "text") {
30529
- const replyContent = [];
30530
- const { coin, like, share, view, favorite, danmaku } = infoData.data.data.stat;
30531
- const coverUrl = await processImageUrl(infoData.data.data.pic, infoData.data.data.title);
30532
- const contentMap = {
30533
- cover: segment.image(coverUrl),
30534
- title: segment.text(`\n📺 标题: ${infoData.data.data.title}\n`),
30535
- author: segment.text(`\n👤 作者: ${infoData.data.data.owner.name}\n`),
30536
- stats: segment.text(formatVideoStats$1(view, danmaku, like, coin, share, favorite)),
30537
- desc: segment.text(`\n\n📝 简介: ${infoData.data.data.desc}`)
30538
- };
30539
- [
30540
- "cover",
30541
- "title",
30542
- "author",
30543
- "stats",
30544
- "desc"
30545
- ].forEach((item) => {
30546
- if (Config.bilibili.displayContent.includes(item) && contentMap[item]) replyContent.push(contentMap[item]);
30547
- });
30548
- if (replyContent.length > 0) this.e.reply(replyContent);
30549
- } else {
30550
- const userProfileData = await this.amagi.bilibili.fetcher.fetchUserCard({ host_mid: infoData.data.data.owner.mid });
30551
- let hotDanmaku;
30552
- if (Config.bilibili.showDanmakuInVideoInfo) {
30553
- const danmakuCid = iddata.p ? infoData.data.data.pages[iddata.p - 1]?.cid ?? infoData.data.data.cid : infoData.data.data.cid;
30554
- const danmakuDuration = iddata.p ? infoData.data.data.pages[iddata.p - 1]?.duration ?? infoData.data.data.duration : infoData.data.data.duration;
30555
- hotDanmaku = getHotDanmaku(await this.fetchVideoDanmakuList(danmakuCid, danmakuDuration), 20);
30556
- }
30557
- const img = await Render(this.e, "bilibili/videoInfo", {
30558
- share_url: "https://b23.tv/" + infoData.data.data.bvid,
30559
- title: infoData.data.data.title,
30560
- desc: infoData.data.data.desc_v2?.length ? buildBilibiliVideoDescRichText(infoData.data.data.desc_v2) : buildBilibiliDynamicRichText(infoData.data.data.desc || "", []),
30561
- stat: infoData.data.data.stat,
30562
- bvid: infoData.data.data.bvid,
30563
- ctime: infoData.data.data.ctime,
30564
- pic: infoData.data.data.pic,
30565
- hotDanmaku,
30566
- owner: {
30567
- ...infoData.data.data.owner,
30568
- usernameMeta: getUsernameMetadata(userProfileData.data.data.card),
30569
- frame: userProfileData.data.data.card.pendant?.image || ""
30538
+ if (Config.bilibili.sendContent.some((content) => content === "info")) {
30539
+ if (Config.bilibili.videoInfoMode === "text") {
30540
+ const replyContent = [];
30541
+ const { coin, like, share, view, favorite, danmaku } = infoData.data.data.stat;
30542
+ const coverUrl = await processImageUrl(infoData.data.data.pic, infoData.data.data.title);
30543
+ const contentMap = {
30544
+ cover: segment.image(coverUrl),
30545
+ title: segment.text(`\n📺 标题: ${infoData.data.data.title}\n`),
30546
+ author: segment.text(`\n👤 作者: ${infoData.data.data.owner.name}\n`),
30547
+ stats: segment.text(formatVideoStats$1(view, danmaku, like, coin, share, favorite)),
30548
+ desc: segment.text(`\n\n📝 简介: ${infoData.data.data.desc}`)
30549
+ };
30550
+ [
30551
+ "cover",
30552
+ "title",
30553
+ "author",
30554
+ "stats",
30555
+ "desc"
30556
+ ].forEach((item) => {
30557
+ if (Config.bilibili.displayContent.includes(item) && contentMap[item]) replyContent.push(contentMap[item]);
30558
+ });
30559
+ if (replyContent.length > 0) this.e.reply(replyContent);
30560
+ } else {
30561
+ const userProfileData = await this.amagi.bilibili.fetcher.fetchUserCard({ host_mid: infoData.data.data.owner.mid });
30562
+ let hotDanmaku;
30563
+ if (Config.bilibili.showDanmakuInVideoInfo) {
30564
+ const danmakuCid = iddata.p ? infoData.data.data.pages[iddata.p - 1]?.cid ?? infoData.data.data.cid : infoData.data.data.cid;
30565
+ const danmakuDuration = iddata.p ? infoData.data.data.pages[iddata.p - 1]?.duration ?? infoData.data.data.duration : infoData.data.data.duration;
30566
+ hotDanmaku = getHotDanmaku(await this.fetchVideoDanmakuList(danmakuCid, danmakuDuration), 20);
30570
30567
  }
30571
- });
30572
- this.e.reply(img);
30568
+ const img = await Render(this.e, "bilibili/videoInfo", {
30569
+ share_url: "https://b23.tv/" + infoData.data.data.bvid,
30570
+ title: infoData.data.data.title,
30571
+ desc: infoData.data.data.desc_v2?.length ? buildBilibiliVideoDescRichText(infoData.data.data.desc_v2) : buildBilibiliDynamicRichText(infoData.data.data.desc || "", []),
30572
+ stat: infoData.data.data.stat,
30573
+ bvid: infoData.data.data.bvid,
30574
+ ctime: infoData.data.data.ctime,
30575
+ pic: infoData.data.data.pic,
30576
+ hotDanmaku,
30577
+ owner: {
30578
+ ...infoData.data.data.owner,
30579
+ usernameMeta: getUsernameMetadata(userProfileData.data.data.card),
30580
+ frame: userProfileData.data.data.card.pendant?.image || ""
30581
+ }
30582
+ });
30583
+ this.e.reply(img);
30584
+ }
30573
30585
  }
30574
30586
  let videoSize = "";
30575
30587
  let correctList;
@@ -30594,7 +30606,7 @@ var Bilibili = class extends Base {
30594
30606
  playUrlData.data.data.accept_description = correctList.accept_description;
30595
30607
  /** 获取第一个视频流的大小 */
30596
30608
  videoSize = await getvideosize(correctList.videoList[0].base_url, audioUrl, infoData.data.data.bvid);
30597
- } else videoSize = (nockData.data.durl[0].size / (1024 * 1024)).toFixed(2);
30609
+ } else videoSize = (nockData.data.durl[0].size / 1048576).toFixed(2);
30598
30610
  if (Config.bilibili.sendContent.some((content) => content === "comment")) {
30599
30611
  const commentsData = await softFetch(() => this.amagi.bilibili.fetcher.fetchComments({
30600
30612
  number: Config.bilibili.numcomment,
@@ -30626,7 +30638,7 @@ var Bilibili = class extends Base {
30626
30638
  CommentLength: Config.bilibili.realCommentCount ? Count(infoData.data.data.stat.reply) : String(commentsdata.length),
30627
30639
  share_url: "https://b23.tv/" + infoData.data.data.bvid,
30628
30640
  Clarity: Config.bilibili.videoQuality !== 0 && Config.bilibili.videoQuality < 64 ? nockData.data.accept_description[nockData.data.accept_description.length - 1] : playUrlData.data.data.accept_description[0],
30629
- VideoSize: Config.bilibili.videoQuality !== 0 && Config.bilibili.videoQuality < 64 ? Common.formatFileSize((nockData.data.durl[0].size / (1024 * 1024)).toFixed(2)) : Common.formatFileSize(videoSize),
30641
+ VideoSize: Config.bilibili.videoQuality !== 0 && Config.bilibili.videoQuality < 64 ? Common.formatFileSize((nockData.data.durl[0].size / 1048576).toFixed(2)) : Common.formatFileSize(videoSize),
30630
30642
  ImageLength: 0,
30631
30643
  shareurl: "https://b23.tv/" + infoData.data.data.bvid,
30632
30644
  Resolution: Config.bilibili.videoQuality !== 0 && Config.bilibili.videoQuality < 64 ? null : `${playUrlData.data.data.dash.video[0].width} x ${playUrlData.data.data.dash.video[0].height}`,
@@ -30636,23 +30648,25 @@ var Bilibili = class extends Base {
30636
30648
  }
30637
30649
  }
30638
30650
  }
30639
- if (Config.bilibili.sendContent.some((content) => content === "video")) if (Config.app.usefilelimit && Number(videoSize) > Number(Config.app.filelimit) && !Config.app.compress) this.e.reply(`设定的最大上传大小为 ${Config.app.filelimit}MB\n当前解析到的视频大小为 ${Number(videoSize)}MB\n视频太大了,还是去B站看吧~`, { reply: true });
30640
- else {
30641
- if (Config.bilibili.videoQuality !== 0 && Config.bilibili.videoQuality < 64) this.islogin = false;
30642
- let danmakuList = [];
30643
- if (this.forceBurnDanmaku || Config.bilibili.burnDanmaku) {
30644
- const cid = iddata.p ? infoData.data.data.pages[iddata.p - 1]?.cid ?? infoData.data.data.cid : infoData.data.data.cid;
30645
- const duration = iddata.p ? infoData.data.data.pages[iddata.p - 1]?.duration ?? infoData.data.data.duration : infoData.data.data.duration;
30646
- danmakuList = await this.fetchVideoDanmakuList(cid, duration);
30651
+ if (Config.bilibili.sendContent.some((content) => content === "video")) {
30652
+ if (Config.app.usefilelimit && Number(videoSize) > Number(Config.app.filelimit) && !Config.app.compress) this.e.reply(`设定的最大上传大小为 ${Config.app.filelimit}MB\n当前解析到的视频大小为 ${Number(videoSize)}MB\n视频太大了,还是去B站看吧~`, { reply: true });
30653
+ else {
30654
+ if (Config.bilibili.videoQuality !== 0 && Config.bilibili.videoQuality < 64) this.islogin = false;
30655
+ let danmakuList = [];
30656
+ if (this.forceBurnDanmaku || Config.bilibili.burnDanmaku) {
30657
+ const cid = iddata.p ? infoData.data.data.pages[iddata.p - 1]?.cid ?? infoData.data.data.cid : infoData.data.data.cid;
30658
+ const duration = iddata.p ? infoData.data.data.pages[iddata.p - 1]?.duration ?? infoData.data.data.duration : infoData.data.data.duration;
30659
+ danmakuList = await this.fetchVideoDanmakuList(cid, duration);
30660
+ }
30661
+ await this.getvideo(Config.bilibili.videoQuality !== 0 && Config.bilibili.videoQuality < 64 ? {
30662
+ playUrlData: nockData.data,
30663
+ danmakuList
30664
+ } : {
30665
+ infoData: infoData.data,
30666
+ playUrlData: playUrlData.data,
30667
+ danmakuList
30668
+ });
30647
30669
  }
30648
- await this.getvideo(Config.bilibili.videoQuality !== 0 && Config.bilibili.videoQuality < 64 ? {
30649
- playUrlData: nockData.data,
30650
- danmakuList
30651
- } : {
30652
- infoData: infoData.data,
30653
- playUrlData: playUrlData.data,
30654
- danmakuList
30655
- });
30656
30670
  }
30657
30671
  break;
30658
30672
  }
@@ -30761,78 +30775,80 @@ var Bilibili = class extends Base {
30761
30775
  const temp = [];
30762
30776
  let hasGeneratedLivePhoto = false;
30763
30777
  const title = dynamicInfo.data.data.item.modules.module_dynamic.major.opus.title || "bilibili_dynamic";
30764
- for (const [index, img] of dynamicInfo.data.data.item.modules.module_dynamic.major.opus.pics.entries()) if (img.url) if (img.live_url) {
30765
- const livePhoto = await downloadFile(img.live_url, {
30766
- title: `Bilibili_tmp_V_${Date.now()}_${index}.mp4`,
30767
- headers: BASE_HEADERS
30768
- });
30769
- if (livePhoto.filepath) {
30770
- const outputPath = Common.tempDri.video + `Bilibili_Live_${Date.now()}_${index}.mp4`;
30771
- const staticImg = await downloadFile(img.url, {
30772
- title: `Bilibili_static_${Date.now()}_${index}.jpg`,
30773
- headers: BASE_HEADERS,
30774
- filepath: Common.tempDri.images + `Bilibili_static_${Date.now()}_${index}.jpg`
30778
+ for (const [index, img] of dynamicInfo.data.data.item.modules.module_dynamic.major.opus.pics.entries()) if (img.url) {
30779
+ if (img.live_url) {
30780
+ const livePhoto = await downloadFile(img.live_url, {
30781
+ title: `Bilibili_tmp_V_${Date.now()}_${index}.mp4`,
30782
+ headers: BASE_HEADERS
30775
30783
  });
30776
- if (staticImg.filepath) temp.push({
30777
- filepath: staticImg.filepath,
30778
- totalBytes: 0
30779
- });
30780
- const livePhotoMode = Config.app.livePhotoMode ?? "video_and_livephoto";
30781
- const shouldGenerateVideo = livePhotoMode === "video_and_livephoto" || livePhotoMode === "video_only";
30782
- const shouldGenerateLivePhoto = livePhotoMode === "video_and_livephoto" || livePhotoMode === "livephoto_only";
30783
- const loopCount = 3;
30784
- if (!staticImg.filepath) {
30785
- await Common.removeFile(livePhoto.filepath, true);
30786
- continue;
30787
- }
30788
- if (shouldGenerateVideo) {
30789
- if ((await loopVideoWithTransition({
30790
- inputPath: livePhoto.filepath,
30791
- outputPath,
30792
- loopCount,
30793
- staticImagePath: staticImg.filepath,
30794
- transitionEnabled: true
30795
- })).success) {
30796
- const filePath = Common.tempDri.video + `tmp_${Date.now()}.mp4`;
30797
- fs.renameSync(outputPath, filePath);
30798
- logger$1.mark(`视频文件重命名完成: ${outputPath.split("/").pop()} -> ${filePath.split("/").pop()}`);
30799
- temp.push({
30800
- filepath: filePath,
30801
- totalBytes: 0
30802
- });
30803
- const videoPath = Config.app.videoSendMode === "base64" ? `base64://${fs.readFileSync(filePath).toString("base64")}` : `file://${filePath}`;
30804
- imgArray.push(segment.video(videoPath));
30784
+ if (livePhoto.filepath) {
30785
+ const outputPath = Common.tempDri.video + `Bilibili_Live_${Date.now()}_${index}.mp4`;
30786
+ const staticImg = await downloadFile(img.url, {
30787
+ title: `Bilibili_static_${Date.now()}_${index}.jpg`,
30788
+ headers: BASE_HEADERS,
30789
+ filepath: Common.tempDri.images + `Bilibili_static_${Date.now()}_${index}.jpg`
30790
+ });
30791
+ if (staticImg.filepath) temp.push({
30792
+ filepath: staticImg.filepath,
30793
+ totalBytes: 0
30794
+ });
30795
+ const livePhotoMode = Config.app.livePhotoMode ?? "video_and_livephoto";
30796
+ const shouldGenerateVideo = livePhotoMode === "video_and_livephoto" || livePhotoMode === "video_only";
30797
+ const shouldGenerateLivePhoto = livePhotoMode === "video_and_livephoto" || livePhotoMode === "livephoto_only";
30798
+ const loopCount = 3;
30799
+ if (!staticImg.filepath) {
30800
+ await Common.removeFile(livePhoto.filepath, true);
30801
+ continue;
30805
30802
  }
30806
- }
30807
- if (shouldGenerateLivePhoto) {
30808
- let hasPushedMotionPhotoCover = false;
30809
- if (staticImg.filepath) {
30810
- const motionPhotoCoverPath = Common.tempDri.images + `MVIMG_${format(/* @__PURE__ */ new Date(), "yyyyMMdd_HHmmss_SSS")}_${index}.jpg`;
30811
- if (await buildGoogleMotionPhoto({
30812
- imagePath: staticImg.filepath,
30813
- videoPath: livePhoto.filepath,
30814
- outputPath: motionPhotoCoverPath
30815
- })) {
30803
+ if (shouldGenerateVideo) {
30804
+ if ((await loopVideoWithTransition({
30805
+ inputPath: livePhoto.filepath,
30806
+ outputPath,
30807
+ loopCount,
30808
+ staticImagePath: staticImg.filepath,
30809
+ transitionEnabled: true
30810
+ })).success) {
30811
+ const filePath = Common.tempDri.video + `tmp_${Date.now()}.mp4`;
30812
+ fs.renameSync(outputPath, filePath);
30813
+ logger$1.mark(`视频文件重命名完成: ${outputPath.split("/").pop()} -> ${filePath.split("/").pop()}`);
30816
30814
  temp.push({
30817
- filepath: motionPhotoCoverPath,
30815
+ filepath: filePath,
30818
30816
  totalBytes: 0
30819
30817
  });
30820
- const motionPhotoCover = processLocalImageFile(motionPhotoCoverPath);
30821
- imgArray.push(segment.image(motionPhotoCover));
30822
- hasPushedMotionPhotoCover = true;
30818
+ const videoPath = Config.app.videoSendMode === "base64" ? `base64://${fs.readFileSync(filePath).toString("base64")}` : `file://${filePath}`;
30819
+ imgArray.push(segment.video(videoPath));
30823
30820
  }
30824
30821
  }
30825
- if (!hasPushedMotionPhotoCover) {
30826
- const imageUrl = await processImageUrl(img.url, title, index);
30827
- imgArray.push(segment.image(imageUrl));
30828
- } else hasGeneratedLivePhoto = true;
30822
+ if (shouldGenerateLivePhoto) {
30823
+ let hasPushedMotionPhotoCover = false;
30824
+ if (staticImg.filepath) {
30825
+ const motionPhotoCoverPath = Common.tempDri.images + `MVIMG_${format(/* @__PURE__ */ new Date(), "yyyyMMdd_HHmmss_SSS")}_${index}.jpg`;
30826
+ if (await buildGoogleMotionPhoto({
30827
+ imagePath: staticImg.filepath,
30828
+ videoPath: livePhoto.filepath,
30829
+ outputPath: motionPhotoCoverPath
30830
+ })) {
30831
+ temp.push({
30832
+ filepath: motionPhotoCoverPath,
30833
+ totalBytes: 0
30834
+ });
30835
+ const motionPhotoCover = processLocalImageFile(motionPhotoCoverPath);
30836
+ imgArray.push(segment.image(motionPhotoCover));
30837
+ hasPushedMotionPhotoCover = true;
30838
+ }
30839
+ }
30840
+ if (!hasPushedMotionPhotoCover) {
30841
+ const imageUrl = await processImageUrl(img.url, title, index);
30842
+ imgArray.push(segment.image(imageUrl));
30843
+ } else hasGeneratedLivePhoto = true;
30844
+ }
30845
+ logger$1.mark("正在尝试删除缓存文件");
30846
+ await Common.removeFile(livePhoto.filepath, true);
30829
30847
  }
30830
- logger$1.mark("正在尝试删除缓存文件");
30831
- await Common.removeFile(livePhoto.filepath, true);
30848
+ } else {
30849
+ const imageUrl = await processImageUrl(img.url, title, index);
30850
+ imgArray.push(segment.image(imageUrl));
30832
30851
  }
30833
- } else {
30834
- const imageUrl = await processImageUrl(img.url, title, index);
30835
- imgArray.push(segment.image(imageUrl));
30836
30852
  }
30837
30853
  if (hasGeneratedLivePhoto) {
30838
30854
  const tipImg = await Render(this.e, "other/live-photo-tip", {
@@ -31044,9 +31060,7 @@ var Bilibili = class extends Base {
31044
31060
  } };
31045
31061
  break;
31046
31062
  }
31047
- default:
31048
- logger$1.warn(`UP主:${userProfileData.data.data.card.name}的${logger$1.green("转发动态")}转发的原动态类型为「${logger$1.yellow(dynamicInfo.data.item.orig.type)}」暂未支持解析`);
31049
- break;
31063
+ default: logger$1.warn(`UP主:${userProfileData.data.data.card.name}的${logger$1.green("转发动态")}转发的原动态类型为「${logger$1.yellow(dynamicInfo.data.item.orig.type)}」暂未支持解析`);
31050
31064
  }
31051
31065
  this.e.reply(await Render(this.e, "bilibili/dynamic/DYNAMIC_TYPE_FORWARD", {
31052
31066
  text,
@@ -31282,7 +31296,6 @@ var Bilibili = class extends Base {
31282
31296
  this.e.reply(img);
31283
31297
  break;
31284
31298
  }
31285
- default: break;
31286
31299
  }
31287
31300
  }
31288
31301
  /**
@@ -31357,18 +31370,19 @@ var Bilibili = class extends Base {
31357
31370
  let success;
31358
31371
  /** 最终要上传的文件:合成/烧录的产物,或没有音频流时直接用的视频流 */
31359
31372
  let sourcePath = bmp4.filepath;
31360
- if (!bmp3) if (hasDanmaku) {
31361
- logger$1.debug(`开始烧录 ${danmakuList.length} 条弹幕...`);
31362
- success = await burnBiliDanmaku(bmp4.filepath, danmakuList, resultPath, {
31363
- danmakuArea: Config.bilibili.danmakuArea,
31364
- verticalMode: Config.bilibili.verticalMode,
31365
- videoCodec: Config.bilibili.videoCodec,
31366
- danmakuFontSize: Config.bilibili.danmakuFontSize,
31367
- danmakuOpacity: Config.bilibili.danmakuOpacity
31368
- });
31369
- sourcePath = resultPath;
31370
- } else success = true;
31371
- else if (hasDanmaku) {
31373
+ if (!bmp3) {
31374
+ if (hasDanmaku) {
31375
+ logger$1.debug(`开始烧录 ${danmakuList.length} 条弹幕...`);
31376
+ success = await burnBiliDanmaku(bmp4.filepath, danmakuList, resultPath, {
31377
+ danmakuArea: Config.bilibili.danmakuArea,
31378
+ verticalMode: Config.bilibili.verticalMode,
31379
+ videoCodec: Config.bilibili.videoCodec,
31380
+ danmakuFontSize: Config.bilibili.danmakuFontSize,
31381
+ danmakuOpacity: Config.bilibili.danmakuOpacity
31382
+ });
31383
+ sourcePath = resultPath;
31384
+ } else success = true;
31385
+ } else if (hasDanmaku) {
31372
31386
  logger$1.debug(`开始合成视频并烧录 ${danmakuList.length} 条弹幕...`);
31373
31387
  success = await mergeAndBurnBili(bmp4.filepath, bmp3.filepath, danmakuList, resultPath, {
31374
31388
  danmakuArea: Config.bilibili.danmakuArea,
@@ -31390,7 +31404,7 @@ var Bilibili = class extends Base {
31390
31404
  if (fs.existsSync(bmp4.filepath)) await Common.removeFile(bmp4.filepath, true);
31391
31405
  if (bmp3 && fs.existsSync(bmp3.filepath)) await Common.removeFile(bmp3.filepath, true);
31392
31406
  const stats = fs.statSync(filePath);
31393
- const fileSizeInMB = Number((stats.size / (1024 * 1024)).toFixed(2));
31407
+ const fileSizeInMB = Number((stats.size / 1048576).toFixed(2));
31394
31408
  if (fileSizeInMB > Config.app.groupfilevalue) await uploadFile(this.e, {
31395
31409
  filepath: filePath,
31396
31410
  totalBytes: fileSizeInMB,
@@ -31432,7 +31446,7 @@ var Bilibili = class extends Base {
31432
31446
  fs.renameSync(resultPath, filePath);
31433
31447
  await Common.removeFile(videoFile.filepath, true);
31434
31448
  const stats = fs.statSync(filePath);
31435
- const fileSizeInMB = Number((stats.size / (1024 * 1024)).toFixed(2));
31449
+ const fileSizeInMB = Number((stats.size / 1048576).toFixed(2));
31436
31450
  if (fileSizeInMB > Config.app.groupfilevalue) await uploadFile(this.e, {
31437
31451
  filepath: filePath,
31438
31452
  totalBytes: fileSizeInMB,
@@ -31452,8 +31466,6 @@ var Bilibili = class extends Base {
31452
31466
  originTitle: `${this.downloadfilename}.mp4`
31453
31467
  }
31454
31468
  });
31455
- break;
31456
- default: break;
31457
31469
  }
31458
31470
  }
31459
31471
  };
@@ -31471,7 +31483,8 @@ var TimeFormatter = {
31471
31483
  */
31472
31484
  toRelative: (timestamp) => {
31473
31485
  try {
31474
- return formatDistanceToNow(fromUnixTime(timestamp), {
31486
+ const date = fromUnixTime(timestamp);
31487
+ return formatDistanceToNow(date, {
31475
31488
  addSuffix: true,
31476
31489
  locale: zhCN
31477
31490
  });
@@ -31728,8 +31741,8 @@ var getvideosize = async (videourl, audiourl, bvid) => {
31728
31741
  }).getHeaders() : void 0;
31729
31742
  const videoSize = extractTotalBytesFromHeaders(videoheaders);
31730
31743
  const audioSize = audioheaders ? extractTotalBytesFromHeaders(audioheaders) : 0;
31731
- const videoSizeInMB = (videoSize / (1024 * 1024)).toFixed(2);
31732
- const audioSizeInMB = (audioSize / (1024 * 1024)).toFixed(2);
31744
+ const videoSizeInMB = (videoSize / 1048576).toFixed(2);
31745
+ const audioSizeInMB = (audioSize / 1048576).toFixed(2);
31733
31746
  return (parseFloat(videoSizeInMB) + parseFloat(audioSizeInMB)).toFixed(2);
31734
31747
  } catch (error) {
31735
31748
  logger$1.warn(`获取视频大小失败: ${error instanceof Error ? error.message : String(error)}`);
@@ -32183,9 +32196,7 @@ var getBilibiliID = async (url) => {
32183
32196
  };
32184
32197
  break;
32185
32198
  }
32186
- default:
32187
- logger$1.warn("无法获取作品ID");
32188
- break;
32199
+ default: logger$1.warn("无法获取作品ID");
32189
32200
  }
32190
32201
  logger$1.debug(result);
32191
32202
  return result;
@@ -32971,7 +32982,7 @@ var Bilibilipush = class extends Base {
32971
32982
  if (fs.existsSync(mp4File.filepath)) await Common.removeFile(mp4File.filepath, true);
32972
32983
  if (mp3File) await Common.removeFile(mp3File.filepath, true);
32973
32984
  const stats = fs.statSync(filePath);
32974
- const fileSizeInMB = Number((stats.size / (1024 * 1024)).toFixed(2));
32985
+ const fileSizeInMB = Number((stats.size / 1048576).toFixed(2));
32975
32986
  if (fileSizeInMB > Config.app.groupfilevalue) await uploadFile(this.e, {
32976
32987
  filepath: filePath,
32977
32988
  totalBytes: fileSizeInMB,
@@ -33665,10 +33676,11 @@ var processCommentImage = async (imageUrl) => {
33665
33676
  type: "arraybuffer"
33666
33677
  }).getHeaders();
33667
33678
  if (headers["content-type"] && headers["content-type"] === "image/heic") {
33668
- const decoded = await (0, import_heic_decode.default)({ buffer: (await new Network({
33679
+ const response = await new Network({
33669
33680
  url: imageUrl,
33670
33681
  type: "arraybuffer"
33671
- }).returnResult()).data });
33682
+ }).returnResult();
33683
+ const decoded = await (0, import_heic_decode.default)({ buffer: response.data });
33672
33684
  const jpegImageData = {
33673
33685
  data: Buffer.from(decoded.data),
33674
33686
  width: decoded.width,
@@ -34803,7 +34815,7 @@ var douyinProcessVideos = (videos, videoQuality, maxAutoVideoSize) => {
34803
34815
  if (qualityVideos && qualityVideos.length > 0) {
34804
34816
  const suitableVideo = qualityVideos.find((video) => video.play_addr.data_size <= sizeLimitBytes);
34805
34817
  if (suitableVideo) {
34806
- logger$1.debug(`自动选择画质: ${quality}, 文件大小: ${(suitableVideo.play_addr.data_size / (1024 * 1024)).toFixed(2)}MB`);
34818
+ logger$1.debug(`自动选择画质: ${quality}, 文件大小: ${(suitableVideo.play_addr.data_size / 1048576).toFixed(2)}MB`);
34807
34819
  return [suitableVideo];
34808
34820
  }
34809
34821
  }
@@ -34812,13 +34824,13 @@ var douyinProcessVideos = (videos, videoQuality, maxAutoVideoSize) => {
34812
34824
  mp4Videos.forEach((video) => {
34813
34825
  if (video.play_addr.data_size < smallestVideo.play_addr.data_size) smallestVideo = video;
34814
34826
  });
34815
- logger$1.debug(`未找到符合大小限制的视频,选择最小视频: ${(smallestVideo.play_addr.data_size / (1024 * 1024)).toFixed(2)}MB`);
34827
+ logger$1.debug(`未找到符合大小限制的视频,选择最小视频: ${(smallestVideo.play_addr.data_size / 1048576).toFixed(2)}MB`);
34816
34828
  return [smallestVideo];
34817
34829
  }
34818
34830
  const targetQuality = videoQuality;
34819
34831
  const targetVideos = videosByQuality.get(targetQuality);
34820
34832
  if (targetVideos && targetVideos.length > 0) {
34821
- logger$1.debug(`选择固定画质: ${targetQuality}, 文件大小: ${(targetVideos[0].play_addr.data_size / (1024 * 1024)).toFixed(2)}MB`);
34833
+ logger$1.debug(`选择固定画质: ${targetQuality}, 文件大小: ${(targetVideos[0].play_addr.data_size / 1048576).toFixed(2)}MB`);
34822
34834
  return [targetVideos[0]];
34823
34835
  }
34824
34836
  const targetIndex = QUALITY_PRIORITY.indexOf(targetQuality);
@@ -35900,40 +35912,42 @@ var DouYin = class DouYin extends Base {
35900
35912
  if (!selectedVideo) throw new Error(`未找到可用的视频源,aweme_id=${VideoData.data.aweme_detail.aweme_id}`);
35901
35913
  g_video_url = selectedVideo.play_addr.url_list[0] ?? selectedVideo.play_addr.url_list[1] ?? selectedVideo.play_addr.url_list[2];
35902
35914
  g_title = VideoData.data.aweme_detail.preview_title.substring(0, 80).replace(/[\\/:*?"<>|\r\n]/g, " ");
35903
- mp4size = (selectedVideo.play_addr.data_size / (1024 * 1024)).toFixed(2);
35915
+ mp4size = (selectedVideo.play_addr.data_size / 1048576).toFixed(2);
35904
35916
  }
35905
- if (Config.douyin.sendContent.includes("info")) if (Config.douyin.videoInfoMode === "text") {
35906
- const replyContent = [];
35907
- const { digg_count, share_count, collect_count, comment_count, recommend_count } = VideoData.data.aweme_detail.statistics;
35908
- const coverUrl = await processImageUrl(isArticle ? VideoData.data.aweme_detail.video.origin_cover.url_list[0] : isVideo ? VideoData.data.aweme_detail.video.animated_cover?.url_list[0] ?? VideoData.data.aweme_detail.video.cover.url_list[0] : VideoData.data.aweme_detail.images[0].url_list[0], VideoData.data.aweme_detail.desc);
35909
- const contentMap = {
35910
- cover: segment.image(coverUrl),
35911
- title: segment.text(`\n📺 标题: ${VideoData.data.aweme_detail.desc}\n`),
35912
- author: segment.text(`\n👤 作者: ${VideoData.data.aweme_detail.author.nickname}\n`),
35913
- stats: segment.text(formatVideoStats(digg_count, share_count, collect_count, comment_count, recommend_count))
35914
- };
35915
- [
35916
- "cover",
35917
- "title",
35918
- "author",
35919
- "stats"
35920
- ].forEach((item) => {
35921
- if (Config.douyin.displayContent.includes(item) && contentMap[item]) replyContent.push(contentMap[item]);
35922
- });
35923
- if (replyContent.length > 0) this.e.reply(replyContent);
35924
- } else {
35925
- const aweme = VideoData.data.aweme_detail;
35926
- const userProfile = await this.amagi.douyin.fetcher.fetchUserProfile({ sec_uid: aweme.author.sec_uid });
35927
- const shareLink = isVideo && selectedVideo ? buildDouyinPlayUrl(selectedVideo.play_addr) : `https://www.douyin.com/${isArticle ? "article" : "note"}/${aweme.aweme_id}`;
35928
- const workInfoImg = await renderWorkImage({
35929
- e: this.e,
35930
- Detail_Data: buildDouyinWorkDetail(aweme, { user_info: userProfile.data }),
35931
- videoSource: selectedVideo,
35932
- create_time: aweme.create_time,
35933
- shareLink,
35934
- dynamicTypeLabel: isArticle ? "文章作品" : isVideo ? "视频作品" : this.is_slides ? "合辑作品" : "图文作品"
35935
- });
35936
- await this.e.reply(workInfoImg);
35917
+ if (Config.douyin.sendContent.includes("info")) {
35918
+ if (Config.douyin.videoInfoMode === "text") {
35919
+ const replyContent = [];
35920
+ const { digg_count, share_count, collect_count, comment_count, recommend_count } = VideoData.data.aweme_detail.statistics;
35921
+ const coverUrl = await processImageUrl(isArticle ? VideoData.data.aweme_detail.video.origin_cover.url_list[0] : isVideo ? VideoData.data.aweme_detail.video.animated_cover?.url_list[0] ?? VideoData.data.aweme_detail.video.cover.url_list[0] : VideoData.data.aweme_detail.images[0].url_list[0], VideoData.data.aweme_detail.desc);
35922
+ const contentMap = {
35923
+ cover: segment.image(coverUrl),
35924
+ title: segment.text(`\n📺 标题: ${VideoData.data.aweme_detail.desc}\n`),
35925
+ author: segment.text(`\n👤 作者: ${VideoData.data.aweme_detail.author.nickname}\n`),
35926
+ stats: segment.text(formatVideoStats(digg_count, share_count, collect_count, comment_count, recommend_count))
35927
+ };
35928
+ [
35929
+ "cover",
35930
+ "title",
35931
+ "author",
35932
+ "stats"
35933
+ ].forEach((item) => {
35934
+ if (Config.douyin.displayContent.includes(item) && contentMap[item]) replyContent.push(contentMap[item]);
35935
+ });
35936
+ if (replyContent.length > 0) this.e.reply(replyContent);
35937
+ } else {
35938
+ const aweme = VideoData.data.aweme_detail;
35939
+ const userProfile = await this.amagi.douyin.fetcher.fetchUserProfile({ sec_uid: aweme.author.sec_uid });
35940
+ const shareLink = isVideo && selectedVideo ? buildDouyinPlayUrl(selectedVideo.play_addr) : `https://www.douyin.com/${isArticle ? "article" : "note"}/${aweme.aweme_id}`;
35941
+ const workInfoImg = await renderWorkImage({
35942
+ e: this.e,
35943
+ Detail_Data: buildDouyinWorkDetail(aweme, { user_info: userProfile.data }),
35944
+ videoSource: selectedVideo,
35945
+ create_time: aweme.create_time,
35946
+ shareLink,
35947
+ dynamicTypeLabel: isArticle ? "文章作品" : isVideo ? "视频作品" : this.is_slides ? "合辑作品" : "图文作品"
35948
+ });
35949
+ await this.e.reply(workInfoImg);
35950
+ }
35937
35951
  }
35938
35952
  if (Config.douyin.sendContent.includes("comment")) {
35939
35953
  const list = Emoji((await this.amagi.douyin.fetcher.fetchEmojiList()).data);
@@ -36025,7 +36039,7 @@ var DouYin = class DouYin extends Base {
36025
36039
  fs.renameSync(resultPath, filePath);
36026
36040
  await Common.removeFile(videoFile.filepath, true);
36027
36041
  const stats = fs.statSync(filePath);
36028
- const fileSizeInMB = Number((stats.size / (1024 * 1024)).toFixed(2));
36042
+ const fileSizeInMB = Number((stats.size / 1048576).toFixed(2));
36029
36043
  if (fileSizeInMB > Config.app.groupfilevalue) await uploadFile(this.e, {
36030
36044
  filepath: filePath,
36031
36045
  totalBytes: fileSizeInMB,
@@ -36226,7 +36240,6 @@ var DouYin = class DouYin extends Base {
36226
36240
  } else this.e.reply(`「${UserInfoData.data.user.nickname}」\n未开播,正在休息中~`);
36227
36241
  return true;
36228
36242
  }
36229
- default: break;
36230
36243
  }
36231
36244
  }
36232
36245
  };
@@ -36368,9 +36381,7 @@ var getDouyinID = async (event, url, log = true) => {
36368
36381
  };
36369
36382
  break;
36370
36383
  }
36371
- default:
36372
- logger$1.warn("无法获取作品ID");
36373
- break;
36384
+ default: logger$1.warn("无法获取作品ID");
36374
36385
  }
36375
36386
  if (log) logger$1.debug(result);
36376
36387
  return result;
@@ -36733,9 +36744,7 @@ var DouYinpush = class extends Base {
36733
36744
  case "recommend":
36734
36745
  pushTypeLabel = "推荐列表";
36735
36746
  break;
36736
- default:
36737
- pushTypeLabel = "直播";
36738
- break;
36747
+ default: pushTypeLabel = "直播";
36739
36748
  }
36740
36749
  logger$1.mark(`
36741
36750
  ${logger$1.blue("开始处理并渲染抖音动态图片")}
@@ -36758,12 +36767,14 @@ var DouYinpush = class extends Base {
36758
36767
  if (!skip) {
36759
36768
  if (pushItem.pushType !== "live" && workTypeInfo.isVideo && pushItem.Detail_Data.video?.bit_rate?.length) selectedVideo = douyinProcessVideos(pushItem.Detail_Data.video.bit_rate, Config.douyin.videoQuality)[0];
36760
36769
  let workShareLink;
36761
- if (pushItem.pushType !== "live") if (workTypeInfo.isArticle) workShareLink = `https://www.douyin.com/article/${actualAwemeId}`;
36762
- else if (workTypeInfo.isImage) workShareLink = `https://www.douyin.com/note/${actualAwemeId}`;
36763
- else if (Config.douyin.push.shareType === "web") workShareLink = `https://www.douyin.com/video/${actualAwemeId}`;
36764
- else {
36765
- const playAddr = selectedVideo?.play_addr ?? pushItem.Detail_Data.video?.play_addr;
36766
- workShareLink = playAddr ? buildDouyinPlayUrl(playAddr) : `https://www.douyin.com/video/${actualAwemeId}`;
36770
+ if (pushItem.pushType !== "live") {
36771
+ if (workTypeInfo.isArticle) workShareLink = `https://www.douyin.com/article/${actualAwemeId}`;
36772
+ else if (workTypeInfo.isImage) workShareLink = `https://www.douyin.com/note/${actualAwemeId}`;
36773
+ else if (Config.douyin.push.shareType === "web") workShareLink = `https://www.douyin.com/video/${actualAwemeId}`;
36774
+ else {
36775
+ const playAddr = selectedVideo?.play_addr ?? pushItem.Detail_Data.video?.play_addr;
36776
+ workShareLink = playAddr ? buildDouyinPlayUrl(playAddr) : `https://www.douyin.com/video/${actualAwemeId}`;
36777
+ }
36767
36778
  }
36768
36779
  switch (pushItem.pushType) {
36769
36780
  case "live":
@@ -36792,15 +36803,13 @@ var DouYinpush = class extends Base {
36792
36803
  remark: pushItem.remark
36793
36804
  });
36794
36805
  break;
36795
- default:
36796
- img = await renderWorkImage({
36797
- e: this.e,
36798
- Detail_Data: pushItem.Detail_Data,
36799
- create_time: pushItem.create_time,
36800
- shareLink: workShareLink,
36801
- videoSource: selectedVideo
36802
- });
36803
- break;
36806
+ default: img = await renderWorkImage({
36807
+ e: this.e,
36808
+ Detail_Data: pushItem.Detail_Data,
36809
+ create_time: pushItem.create_time,
36810
+ shareLink: workShareLink,
36811
+ videoSource: selectedVideo
36812
+ });
36804
36813
  }
36805
36814
  }
36806
36815
  for (const target of pushItem.targets) {
@@ -36986,158 +36995,160 @@ var DouYinpush = class extends Base {
36986
36995
  } finally {
36987
36996
  for (const item of temp) await Common.removeFile(item.filepath, true);
36988
36997
  }
36989
- } else if (Detail_Data.images) if (Detail_Data.images.some((item) => item.clip_type !== 2 && item.clip_type !== void 0)) {
36990
- const processedImages = [];
36991
- const temp = [];
36992
- let hasGeneratedLivePhoto = false;
36993
- /** 下载 BGM(如果存在) */
36994
- let liveimgbgm = null;
36995
- let bgmContext = null;
36996
- const mergeMode = Config.douyin.liveImageMergeMode ?? "independent";
36997
- if (Detail_Data.music) {
36998
- let mp3Path = "";
36999
- if (Detail_Data.music.play_url.uri === "") mp3Path = JSON.parse(Detail_Data.music.extra).original_song_url;
37000
- else mp3Path = Detail_Data.music.play_url.uri;
37001
- liveimgbgm = await downloadFile(mp3Path, {
37002
- title: `Douyin_tmp_A_${Date.now()}.mp3`,
37003
- headers: douyinBaseHeaders
37004
- });
37005
- temp.push(liveimgbgm);
37006
- }
37007
- for (const [index, item] of Detail_Data.images.entries()) {
37008
- if (item.clip_type === 2 || item.clip_type === void 0) {
37009
- const image_url = item.url_list[2] ?? item.url_list[1];
37010
- if (!image_url) continue;
37011
- const imageUrl = await processImageUrl(image_url, Detail_Data.desc, index);
37012
- processedImages.push(segment.image(imageUrl));
37013
- continue;
37014
- }
37015
- /** live 图 */
37016
- const livePlayAddr = item.video?.play_addr_h264;
37017
- if (!livePlayAddr?.uri) {
37018
- logger$1.warn(`图集第 ${index + 1} 个动态媒体缺少视频源,跳过`);
37019
- continue;
36998
+ } else if (Detail_Data.images) {
36999
+ if (Detail_Data.images.some((item) => item.clip_type !== 2 && item.clip_type !== void 0)) {
37000
+ const processedImages = [];
37001
+ const temp = [];
37002
+ let hasGeneratedLivePhoto = false;
37003
+ /** 下载 BGM(如果存在) */
37004
+ let liveimgbgm = null;
37005
+ let bgmContext = null;
37006
+ const mergeMode = Config.douyin.liveImageMergeMode ?? "independent";
37007
+ if (Detail_Data.music) {
37008
+ let mp3Path = "";
37009
+ if (Detail_Data.music.play_url.uri === "") mp3Path = JSON.parse(Detail_Data.music.extra).original_song_url;
37010
+ else mp3Path = Detail_Data.music.play_url.uri;
37011
+ liveimgbgm = await downloadFile(mp3Path, {
37012
+ title: `Douyin_tmp_A_${Date.now()}.mp3`,
37013
+ headers: douyinBaseHeaders
37014
+ });
37015
+ temp.push(liveimgbgm);
37020
37016
  }
37021
- const liveimg = await downloadFile(buildDouyinPlayUrl(livePlayAddr), {
37022
- title: `Douyin_tmp_V_${Date.now()}.mp4`,
37023
- headers: douyinBaseHeaders
37024
- });
37025
- if (liveimg.filepath) {
37026
- const outputPath = Common.tempDri.video + `Douyin_Result_${Date.now()}.mp4`;
37027
- const loopCount = item.clip_type === 4 ? 1 : 3;
37028
- let staticImgPath = "";
37029
- if (item.url_list?.[0]) {
37030
- const staticImg = await downloadFile(item.url_list[0], {
37031
- title: `Douyin_static_${Date.now()}_${index}.jpg`,
37032
- headers: douyinBaseHeaders,
37033
- filepath: Common.tempDri.images + `Douyin_static_${Date.now()}_${index}.jpg`
37034
- });
37035
- if (staticImg.filepath) temp.push({
37036
- filepath: staticImg.filepath,
37037
- totalBytes: 0
37038
- });
37039
- staticImgPath = staticImg.filepath ?? "";
37017
+ for (const [index, item] of Detail_Data.images.entries()) {
37018
+ if (item.clip_type === 2 || item.clip_type === void 0) {
37019
+ const image_url = item.url_list[2] ?? item.url_list[1];
37020
+ if (!image_url) continue;
37021
+ const imageUrl = await processImageUrl(image_url, Detail_Data.desc, index);
37022
+ processedImages.push(segment.image(imageUrl));
37023
+ continue;
37040
37024
  }
37041
- const { shouldGenerateVideo, shouldGenerateLivePhoto } = getDouyinLiveImageSendPolicy(item.clip_type, Config.app.livePhotoMode ?? "video_and_livephoto");
37042
- if (shouldGenerateVideo) {
37043
- const transitionEnabled = loopCount > 1 && Boolean(staticImgPath);
37044
- const safeStaticPath = staticImgPath || liveimg.filepath;
37045
- const result = await loopVideoWithTransition({
37046
- inputPath: liveimg.filepath,
37047
- outputPath,
37048
- loopCount,
37049
- staticImagePath: safeStaticPath,
37050
- transitionEnabled,
37051
- bgmPath: liveimgbgm?.filepath,
37052
- mergeMode,
37053
- context: bgmContext ?? void 0
37054
- });
37055
- const success = result.success;
37056
- if (mergeMode === "continuous" && result.context) bgmContext = result.context;
37057
- if (success) {
37058
- const filePath = Common.tempDri.video + `tmp_${Date.now()}.mp4`;
37059
- fs.renameSync(outputPath, filePath);
37060
- logger$1.mark(`视频文件重命名完成: ${outputPath.split("/").pop()} -> ${filePath.split("/").pop()}`);
37061
- temp.push({
37062
- filepath: filePath,
37025
+ /** live 图 */
37026
+ const livePlayAddr = item.video?.play_addr_h264;
37027
+ if (!livePlayAddr?.uri) {
37028
+ logger$1.warn(`图集第 ${index + 1} 个动态媒体缺少视频源,跳过`);
37029
+ continue;
37030
+ }
37031
+ const liveimg = await downloadFile(buildDouyinPlayUrl(livePlayAddr), {
37032
+ title: `Douyin_tmp_V_${Date.now()}.mp4`,
37033
+ headers: douyinBaseHeaders
37034
+ });
37035
+ if (liveimg.filepath) {
37036
+ const outputPath = Common.tempDri.video + `Douyin_Result_${Date.now()}.mp4`;
37037
+ const loopCount = item.clip_type === 4 ? 1 : 3;
37038
+ let staticImgPath = "";
37039
+ if (item.url_list?.[0]) {
37040
+ const staticImg = await downloadFile(item.url_list[0], {
37041
+ title: `Douyin_static_${Date.now()}_${index}.jpg`,
37042
+ headers: douyinBaseHeaders,
37043
+ filepath: Common.tempDri.images + `Douyin_static_${Date.now()}_${index}.jpg`
37044
+ });
37045
+ if (staticImg.filepath) temp.push({
37046
+ filepath: staticImg.filepath,
37063
37047
  totalBytes: 0
37064
37048
  });
37065
- const videoPath = Config.app.videoSendMode === "base64" ? `base64://${fs.readFileSync(filePath).toString("base64")}` : `file://${filePath}`;
37066
- processedImages.push(segment.video(videoPath));
37049
+ staticImgPath = staticImg.filepath ?? "";
37067
37050
  }
37068
- }
37069
- if (shouldGenerateLivePhoto && item.clip_type === 5 && item.url_list?.[0]) {
37070
- let hasPushedMotionPhotoCover = false;
37071
- if (staticImgPath) {
37072
- const motionPhotoCoverPath = Common.tempDri.images + `MVIMG_${format(/* @__PURE__ */ new Date(), "yyyyMMdd_HHmmss_SSS")}_${index}.jpg`;
37073
- if (await buildGoogleMotionPhoto({
37074
- imagePath: staticImgPath,
37075
- videoPath: liveimg.filepath,
37076
- outputPath: motionPhotoCoverPath
37077
- })) {
37051
+ const { shouldGenerateVideo, shouldGenerateLivePhoto } = getDouyinLiveImageSendPolicy(item.clip_type, Config.app.livePhotoMode ?? "video_and_livephoto");
37052
+ if (shouldGenerateVideo) {
37053
+ const transitionEnabled = loopCount > 1 && Boolean(staticImgPath);
37054
+ const safeStaticPath = staticImgPath || liveimg.filepath;
37055
+ const result = await loopVideoWithTransition({
37056
+ inputPath: liveimg.filepath,
37057
+ outputPath,
37058
+ loopCount,
37059
+ staticImagePath: safeStaticPath,
37060
+ transitionEnabled,
37061
+ bgmPath: liveimgbgm?.filepath,
37062
+ mergeMode,
37063
+ context: bgmContext ?? void 0
37064
+ });
37065
+ const success = result.success;
37066
+ if (mergeMode === "continuous" && result.context) bgmContext = result.context;
37067
+ if (success) {
37068
+ const filePath = Common.tempDri.video + `tmp_${Date.now()}.mp4`;
37069
+ fs.renameSync(outputPath, filePath);
37070
+ logger$1.mark(`视频文件重命名完成: ${outputPath.split("/").pop()} -> ${filePath.split("/").pop()}`);
37078
37071
  temp.push({
37079
- filepath: motionPhotoCoverPath,
37072
+ filepath: filePath,
37080
37073
  totalBytes: 0
37081
37074
  });
37082
- const motionPhotoCover = processLocalImageFile(motionPhotoCoverPath);
37083
- processedImages.push(segment.image(motionPhotoCover));
37084
- hasPushedMotionPhotoCover = true;
37075
+ const videoPath = Config.app.videoSendMode === "base64" ? `base64://${fs.readFileSync(filePath).toString("base64")}` : `file://${filePath}`;
37076
+ processedImages.push(segment.video(videoPath));
37085
37077
  }
37086
37078
  }
37087
- if (!hasPushedMotionPhotoCover) {
37088
- const imageUrl = await processImageUrl(item.url_list[0], Detail_Data.desc, index);
37089
- processedImages.push(segment.image(imageUrl));
37090
- } else hasGeneratedLivePhoto = true;
37079
+ if (shouldGenerateLivePhoto && item.clip_type === 5 && item.url_list?.[0]) {
37080
+ let hasPushedMotionPhotoCover = false;
37081
+ if (staticImgPath) {
37082
+ const motionPhotoCoverPath = Common.tempDri.images + `MVIMG_${format(/* @__PURE__ */ new Date(), "yyyyMMdd_HHmmss_SSS")}_${index}.jpg`;
37083
+ if (await buildGoogleMotionPhoto({
37084
+ imagePath: staticImgPath,
37085
+ videoPath: liveimg.filepath,
37086
+ outputPath: motionPhotoCoverPath
37087
+ })) {
37088
+ temp.push({
37089
+ filepath: motionPhotoCoverPath,
37090
+ totalBytes: 0
37091
+ });
37092
+ const motionPhotoCover = processLocalImageFile(motionPhotoCoverPath);
37093
+ processedImages.push(segment.image(motionPhotoCover));
37094
+ hasPushedMotionPhotoCover = true;
37095
+ }
37096
+ }
37097
+ if (!hasPushedMotionPhotoCover) {
37098
+ const imageUrl = await processImageUrl(item.url_list[0], Detail_Data.desc, index);
37099
+ processedImages.push(segment.image(imageUrl));
37100
+ } else hasGeneratedLivePhoto = true;
37101
+ }
37102
+ logger$1.mark("正在尝试删除缓存文件");
37103
+ await Common.removeFile(liveimg.filepath, true);
37091
37104
  }
37092
- logger$1.mark("正在尝试删除缓存文件");
37093
- await Common.removeFile(liveimg.filepath, true);
37094
37105
  }
37095
- }
37096
- if (hasGeneratedLivePhoto) {
37097
- const tipImg = await Render(this.e, "other/live-photo-tip", {
37098
- title: "实况照片已生成",
37099
- description: "保存原图到相册即可识别为实况图"
37100
- });
37101
- processedImages.push(...tipImg);
37102
- }
37103
- const bot = karin.getBot(botId);
37104
- try {
37105
- if (processedImages.length === 0) logger$1.warn(`抖音图集推送解析未生成可发送内容,aweme_id=${Detail_Data.aweme_id}`);
37106
- else {
37107
- const Element = common.makeForward(processedImages, botId, bot.account.name);
37108
- await bot.sendForwardMsg(Contact, Element, {
37109
- source: "图集内容",
37110
- summary: `查看${Element.length}张图片/视频消息`,
37106
+ if (hasGeneratedLivePhoto) {
37107
+ const tipImg = await Render(this.e, "other/live-photo-tip", {
37108
+ title: "实况照片已生成",
37109
+ description: "保存原图到相册即可识别为实况图"
37110
+ });
37111
+ processedImages.push(...tipImg);
37112
+ }
37113
+ const bot = karin.getBot(botId);
37114
+ try {
37115
+ if (processedImages.length === 0) logger$1.warn(`抖音图集推送解析未生成可发送内容,aweme_id=${Detail_Data.aweme_id}`);
37116
+ else {
37117
+ const Element = common.makeForward(processedImages, botId, bot.account.name);
37118
+ await bot.sendForwardMsg(Contact, Element, {
37119
+ source: "图集内容",
37120
+ summary: `查看${Element.length}张图片/视频消息`,
37121
+ prompt: "抖音图集解析结果",
37122
+ news: [{ text: "点击查看解析结果" }]
37123
+ });
37124
+ }
37125
+ } catch (error) {
37126
+ logger$1.error(`发送图集失败: ${error}`);
37127
+ } finally {
37128
+ for (const item of temp) await Common.removeFile(item.filepath, true);
37129
+ }
37130
+ } else {
37131
+ const imageres = [];
37132
+ let image_url;
37133
+ for (const [index, item] of Detail_Data.images.entries()) {
37134
+ image_url = item.url_list[2] ?? item.url_list[1];
37135
+ if (!image_url) continue;
37136
+ const imageUrl = await processImageUrl(image_url, Detail_Data.desc, index);
37137
+ imageres.push(segment.image(imageUrl));
37138
+ }
37139
+ const bot = karin.getBot(botId);
37140
+ if (imageres.length === 1 && image_url) {
37141
+ const imageUrl = await processImageUrl(image_url, Detail_Data.desc);
37142
+ await bot.sendMsg(Contact, [segment.image(imageUrl)]);
37143
+ } else {
37144
+ const forwardMsg = common.makeForward(imageres, botId, bot.account.name);
37145
+ await bot.sendForwardMsg(Contact, forwardMsg, {
37146
+ source: "图片合集",
37147
+ summary: `查看${forwardMsg.length}张图片消息`,
37111
37148
  prompt: "抖音图集解析结果",
37112
37149
  news: [{ text: "点击查看解析结果" }]
37113
37150
  });
37114
37151
  }
37115
- } catch (error) {
37116
- logger$1.error(`发送图集失败: ${error}`);
37117
- } finally {
37118
- for (const item of temp) await Common.removeFile(item.filepath, true);
37119
- }
37120
- } else {
37121
- const imageres = [];
37122
- let image_url;
37123
- for (const [index, item] of Detail_Data.images.entries()) {
37124
- image_url = item.url_list[2] ?? item.url_list[1];
37125
- if (!image_url) continue;
37126
- const imageUrl = await processImageUrl(image_url, Detail_Data.desc, index);
37127
- imageres.push(segment.image(imageUrl));
37128
- }
37129
- const bot = karin.getBot(botId);
37130
- if (imageres.length === 1 && image_url) {
37131
- const imageUrl = await processImageUrl(image_url, Detail_Data.desc);
37132
- await bot.sendMsg(Contact, [segment.image(imageUrl)]);
37133
- } else {
37134
- const forwardMsg = common.makeForward(imageres, botId, bot.account.name);
37135
- await bot.sendForwardMsg(Contact, forwardMsg, {
37136
- source: "图片合集",
37137
- summary: `查看${forwardMsg.length}张图片消息`,
37138
- prompt: "抖音图集解析结果",
37139
- news: [{ text: "点击查看解析结果" }]
37140
- });
37141
37152
  }
37142
37153
  }
37143
37154
  }
@@ -37213,7 +37224,6 @@ var DouYinpush = class extends Base {
37213
37224
  });
37214
37225
  if (recommendlist.data.aweme_list.length === 0) logger$1.warn(`${item.remark}(${item.short_id}) 获取到的推荐列表数量为零!此博主可能未公开他/她的推荐列表`);
37215
37226
  contentList = recommendlist.data.aweme_list || [];
37216
- break;
37217
37227
  }
37218
37228
  logger$1.debug(`获取到 ${item.remark} 的${listName},共 ${contentList.length} 条`);
37219
37229
  if (contentList.length > 0) {
@@ -37225,9 +37235,7 @@ var DouYinpush = class extends Base {
37225
37235
  case "favorite":
37226
37236
  pushItems = await processFavoriteList(contentList, sec_uid, userinfo.data, item, targets, this.force);
37227
37237
  break;
37228
- case "recommend":
37229
- pushItems = await processRecommendList(contentList, sec_uid, userinfo.data, item, targets, this.force);
37230
- break;
37238
+ case "recommend": pushItems = await processRecommendList(contentList, sec_uid, userinfo.data, item, targets, this.force);
37231
37239
  }
37232
37240
  for (const pushItem of pushItems) {
37233
37241
  const key = `${pushType}_${pushItem.Detail_Data.aweme_id}`;
@@ -37540,7 +37548,6 @@ var fetchKuaishouData = async (type, opt) => {
37540
37548
  }
37541
37549
  case "work_comments": return (await kuaishouFetcher.fetchWorkComments({ photoId: opt.photoId })).data;
37542
37550
  case "emoji_list": return (await kuaishouFetcher.fetchEmojiList()).data;
37543
- default: break;
37544
37551
  }
37545
37552
  };
37546
37553
  //#endregion
@@ -37571,9 +37578,7 @@ var getKuaishouID = async (url, log = true) => {
37571
37578
  };
37572
37579
  break;
37573
37580
  }
37574
- default:
37575
- logger$1.warn("无法获取作品ID");
37576
- break;
37581
+ default: logger$1.warn("无法获取作品ID");
37577
37582
  }
37578
37583
  if (log) logger$1.debug(result);
37579
37584
  return result;
@@ -37630,7 +37635,7 @@ var Kuaishou = class extends Base {
37630
37635
  const fileSizeInMB = (extractTotalBytesFromHeaders(await new Network({
37631
37636
  url: video_url,
37632
37637
  headers: this.headers
37633
- }).getHeaders()) / (1024 * 1024)).toFixed(2);
37638
+ }).getHeaders()) / 1048576).toFixed(2);
37634
37639
  const img = await Render(this.e, "kuaishou/comment", {
37635
37640
  Type: "视频",
37636
37641
  viewCount: work.photo.viewCount,
@@ -37759,9 +37764,7 @@ var getXiaohongshuID = async (url, log = true) => {
37759
37764
  };
37760
37765
  break;
37761
37766
  }
37762
- default:
37763
- result = { type: "unknown" };
37764
- break;
37767
+ default: result = { type: "unknown" };
37765
37768
  }
37766
37769
  if (result.type === "unknown") throw new Error("无法从链接中提取小红书笔记ID");
37767
37770
  if (log) logger$1.debug(result);
@@ -38147,7 +38150,7 @@ var xiaohongshuGetLivePhotoVideo = (streamData) => {
38147
38150
  const videos = codecVideos(streamData, codec);
38148
38151
  if (videos.length > 0) {
38149
38152
  const video = videos[0];
38150
- logger.debug(`选择实况图视频流: 编码=${codec}, 大小=${(video.size || 0) / (1024 * 1024)}MB`);
38153
+ logger.debug(`选择实况图视频流: 编码=${codec}, 大小=${(video.size || 0) / 1048576}MB`);
38151
38154
  return video;
38152
38155
  }
38153
38156
  }
@@ -38181,10 +38184,10 @@ var xiaohongshuProcessVideos = (streamData, videoQuality, maxAutoVideoSize) => {
38181
38184
  logger.debug(`找到 ${allVideos.length} 个视频流`);
38182
38185
  const getQualityLevel = (width, height) => {
38183
38186
  const pixels = width * height;
38184
- if (pixels >= 3840 * 2160) return "4k";
38185
- if (pixels >= 2560 * 1440) return "2k";
38186
- if (pixels >= 1920 * 1080) return "1080p";
38187
- if (pixels >= 1280 * 720) return "720p";
38187
+ if (pixels >= 8294400) return "4k";
38188
+ if (pixels >= 3686400) return "2k";
38189
+ if (pixels >= 2073600) return "1080p";
38190
+ if (pixels >= 921600) return "720p";
38188
38191
  return "540p";
38189
38192
  };
38190
38193
  const videosByQuality = /* @__PURE__ */ new Map();
@@ -38209,7 +38212,7 @@ var xiaohongshuProcessVideos = (streamData, videoQuality, maxAutoVideoSize) => {
38209
38212
  if (qualityVideos && qualityVideos.length > 0) {
38210
38213
  const suitableVideo = qualityVideos.find((video) => video.size <= sizeLimitBytes);
38211
38214
  if (suitableVideo) {
38212
- logger.debug(`自动选择画质: ${quality}, 文件大小: ${(suitableVideo.size / (1024 * 1024)).toFixed(2)}MB, 编码: ${suitableVideo.video_codec}`);
38215
+ logger.debug(`自动选择画质: ${quality}, 文件大小: ${(suitableVideo.size / 1048576).toFixed(2)}MB, 编码: ${suitableVideo.video_codec}`);
38213
38216
  return suitableVideo;
38214
38217
  }
38215
38218
  }
@@ -38218,13 +38221,13 @@ var xiaohongshuProcessVideos = (streamData, videoQuality, maxAutoVideoSize) => {
38218
38221
  allVideos.forEach((video) => {
38219
38222
  if (video.size < smallestVideo.size) smallestVideo = video;
38220
38223
  });
38221
- logger.debug(`未找到符合大小限制的视频,选择最小视频: ${(smallestVideo.size / (1024 * 1024)).toFixed(2)}MB, 编码: ${smallestVideo.video_codec}`);
38224
+ logger.debug(`未找到符合大小限制的视频,选择最小视频: ${(smallestVideo.size / 1048576).toFixed(2)}MB, 编码: ${smallestVideo.video_codec}`);
38222
38225
  return smallestVideo;
38223
38226
  }
38224
38227
  const targetQuality = videoQuality;
38225
38228
  const targetVideos = videosByQuality.get(targetQuality);
38226
38229
  if (targetVideos && targetVideos.length > 0) {
38227
- logger.debug(`选择固定画质: ${targetQuality}, 文件大小: ${(targetVideos[0].size / (1024 * 1024)).toFixed(2)}MB, 编码: ${targetVideos[0].video_codec}`);
38230
+ logger.debug(`选择固定画质: ${targetQuality}, 文件大小: ${(targetVideos[0].size / 1048576).toFixed(2)}MB, 编码: ${targetVideos[0].video_codec}`);
38228
38231
  return targetVideos[0];
38229
38232
  }
38230
38233
  const qualityPriority = [
@@ -38472,7 +38475,7 @@ var douyinLogin = async (e) => {
38472
38475
  //#endregion
38473
38476
  //#region src/apps/admin.ts
38474
38477
  var handleCacheCleanup = wrapWithErrorHandler(async () => {
38475
- const twoHoursAgo = Date.now() - 7200 * 1e3;
38478
+ const twoHoursAgo = Date.now() - 72e5;
38476
38479
  const videoDeleted = removeOldFiles(Common.tempDri.video, twoHoursAgo);
38477
38480
  logger$1.debug(`${Common.tempDri.video} 目录下已删除 ${videoDeleted} 个文件`);
38478
38481
  if (Config.app.imageSendMode !== "url") {
@@ -38726,29 +38729,20 @@ var HELP_MENU_CONFIG = [
38726
38729
  },
38727
38730
  {
38728
38731
  title: "设置相关",
38729
- items: [
38730
- {
38731
- title: "#kkk设置推送机器人 + Bot ID",
38732
- description: "一键更换推送机器人",
38733
- icon: "ph:robot-fill",
38734
- roles: ["master"]
38735
- },
38736
- {
38737
- title: "#抖音登录",
38738
- description: "使用抖音APP扫码登录获取 Cookies",
38739
- icon: "logos:tiktok-icon",
38740
- roles: ["master"]
38732
+ items: [{
38733
+ title: "#抖音登录",
38734
+ description: "使用抖音APP扫码登录获取 Cookies",
38735
+ icon: "logos:tiktok-icon",
38736
+ roles: ["master"]
38737
+ }, {
38738
+ title: "#B站登录",
38739
+ description: "使用哔哩哔哩APP扫码登录获取 Cookies",
38740
+ icon: {
38741
+ name: "streamline-ultimate:bilibili-logo-bold",
38742
+ color: "#7fe1fa"
38741
38743
  },
38742
- {
38743
- title: "#B站登录",
38744
- description: "使用哔哩哔哩APP扫码登录获取 Cookies",
38745
- icon: {
38746
- name: "streamline-ultimate:bilibili-logo-bold",
38747
- color: "#7fe1fa"
38748
- },
38749
- roles: ["master"]
38750
- }
38751
- ]
38744
+ roles: ["master"]
38745
+ }]
38752
38746
  },
38753
38747
  {
38754
38748
  title: "其他",
@@ -38898,39 +38892,6 @@ var handleBilibiliPushList = wrapWithErrorHandler(async (e) => {
38898
38892
  var handleDouyinPushList = wrapWithErrorHandler(async (e) => {
38899
38893
  await new DouYinpush(e).renderPushList();
38900
38894
  }, { businessName: "抖音推送列表" });
38901
- var handleChangeBotID = wrapWithErrorHandler(async (e) => {
38902
- const newBotId = e.msg.replace(/^#kkk设置推送机器人/, "");
38903
- const newDouyinlist = Config.pushlist.douyin.map((item) => {
38904
- const modifiedGroupIds = item.group_id.map((groupId) => {
38905
- const [group_id, oldBotId] = groupId.split(":");
38906
- if (oldBotId && oldBotId !== newBotId) douyinDBInstance.updateGroupBotId(group_id, oldBotId, newBotId).catch((err) => {
38907
- logger$1.error(`Failed to update douyin group ${group_id}:`, err);
38908
- });
38909
- return `${group_id}:${newBotId}`;
38910
- });
38911
- return {
38912
- ...item,
38913
- group_id: modifiedGroupIds
38914
- };
38915
- });
38916
- const newBilibililist = Config.pushlist.bilibili.map((item) => {
38917
- const modifiedGroupIds = item.group_id.map((groupId) => {
38918
- const [group_id, oldBotId] = groupId.split(":");
38919
- if (oldBotId && oldBotId !== newBotId) bilibiliDBInstance.updateGroupBotId(group_id, oldBotId, newBotId).catch((err) => {
38920
- logger$1.error(`Failed to update bilibili group ${group_id}:`, err);
38921
- });
38922
- return `${group_id}:${newBotId}`;
38923
- });
38924
- return {
38925
- ...item,
38926
- group_id: modifiedGroupIds
38927
- };
38928
- });
38929
- Config.Modify("pushlist", "douyin", newDouyinlist);
38930
- Config.Modify("pushlist", "bilibili", newBilibililist);
38931
- await e.reply("推送机器人已修改为" + newBotId);
38932
- return true;
38933
- }, { businessName: "设置推送机器人" });
38934
38895
  var handleGlobalIgnore = wrapWithErrorHandler(async (e) => {
38935
38896
  const url = e.msg.replace(/^#kkk推送全局忽略/, "").trim();
38936
38897
  if (!url) {
@@ -39022,10 +38983,6 @@ var douyinPushList = karin.command(/^#?抖音推送列表$/, handleDouyinPushLis
39022
38983
  name: "kkk-推送功能-列表",
39023
38984
  event: "message.group"
39024
38985
  });
39025
- var changeBotID = karin.command(/^#kkk设置推送机器人/, handleChangeBotID, {
39026
- name: "kkk-推送功能-设置",
39027
- perm: "master"
39028
- });
39029
38986
  var globalIgnore = karin.command(/^#kkk推送全局忽略/, handleGlobalIgnore, {
39030
38987
  name: "kkk-推送功能-全局忽略",
39031
38988
  perm: "master",
@@ -40869,12 +40826,13 @@ var getBotInfo = async (req, res) => {
40869
40826
  if (!botId) return createServerErrorResponse(res, "缺少 botId 参数");
40870
40827
  const bot = getOnlineBotById(botId);
40871
40828
  if (!bot || bot.account.name === "console") return createServerErrorResponse(res, "Bot 不存在或不在线");
40872
- return createSuccessResponse(res, {
40829
+ const botInfo = {
40873
40830
  id: bot.account.selfId,
40874
40831
  name: bot.account.name || bot.account.selfId,
40875
40832
  avatar: await getBotAvatar(bot, bot.account.selfId),
40876
40833
  isOnline: true
40877
- });
40834
+ };
40835
+ return createSuccessResponse(res, botInfo);
40878
40836
  } catch (error) {
40879
40837
  logger$1.error("[BotsAPI] 获取 Bot 信息失败:", error);
40880
40838
  return createServerErrorResponse(res, "获取 Bot 信息失败");
@@ -40932,7 +40890,7 @@ var getBotGroupInfo = async (req, res) => {
40932
40890
  } catch (e) {
40933
40891
  logger$1.warn(`[BotsAPI] 获取群组信息失败 ${groupId}:`, e);
40934
40892
  }
40935
- return createSuccessResponse(res, {
40893
+ const groupDetail = {
40936
40894
  id: groupId,
40937
40895
  name: groupName,
40938
40896
  avatar: groupAvatar,
@@ -40941,7 +40899,8 @@ var getBotGroupInfo = async (req, res) => {
40941
40899
  botAvatar: await getBotAvatar(bot, bot.account.selfId),
40942
40900
  memberCount,
40943
40901
  isOnline: true
40944
- });
40902
+ };
40903
+ return createSuccessResponse(res, groupDetail);
40945
40904
  } catch (error) {
40946
40905
  logger$1.error("[BotsAPI] 获取 Bot 群信息失败:", error);
40947
40906
  return createServerErrorResponse(res, "获取群信息失败");
@@ -41013,7 +40972,8 @@ var getGroupsBatch = async (req, res) => {
41013
40972
  */
41014
40973
  var getAllConfig = async (_req, res) => {
41015
40974
  try {
41016
- return createSuccessResponse(res, await Config.All());
40975
+ const config = await Config.All();
40976
+ return createSuccessResponse(res, config);
41017
40977
  } catch (error) {
41018
40978
  return createServerErrorResponse(res, `获取配置失败: ${error.message}`);
41019
40979
  }
@@ -41056,8 +41016,9 @@ var updateAllConfig = async (req, res) => {
41056
41016
  if ("pushlist" in newConfig) await Config.syncConfigToDatabase();
41057
41017
  if (needReloadAmagi) reloadAmagiConfig();
41058
41018
  const allSuccess = results.every((r) => r.success);
41019
+ const updatedConfig = await Config.All();
41059
41020
  return createSuccessResponse(res, {
41060
- config: await Config.All(),
41021
+ config: updatedConfig,
41061
41022
  results
41062
41023
  }, allSuccess ? "所有配置更新成功" : "部分配置更新失败");
41063
41024
  } catch (error) {
@@ -41484,7 +41445,7 @@ var getVideoPage = (req, res) => {
41484
41445
  const videoDataUrl = `/kkk/v1/stream/${encodeURIComponent(token)}`;
41485
41446
  const removeCache = previewInfo.removeCache;
41486
41447
  const createdAt = previewInfo.createdAt;
41487
- const expireAt = previewInfo.expireAt ?? (removeCache ? createdAt + 600 * 1e3 : void 0);
41448
+ const expireAt = previewInfo.expireAt ?? (removeCache ? createdAt + 6e5 : void 0);
41488
41449
  const htmlContent = renderVideoPreviewPage({
41489
41450
  filename: previewInfo.filename,
41490
41451
  filePath: previewInfo.filePath,
@@ -41627,7 +41588,7 @@ var signatureVerificationMiddleware = (req, res, next) => {
41627
41588
  const nonce = req.headers["x-nonce"];
41628
41589
  const token = req.headers["authorization"]?.replace("Bearer ", "") || "";
41629
41590
  if (!encodedSignature || !timestamp || !nonce) return createBadRequestResponse(res, "缺少必要的签名参数");
41630
- if (Math.abs(Date.now() - parseInt(timestamp)) > 300 * 1e3) return createBadRequestResponse(res, "请求时间戳已过期");
41591
+ if (Math.abs(Date.now() - parseInt(timestamp)) > 3e5) return createBadRequestResponse(res, "请求时间戳已过期");
41631
41592
  let decodedSignature;
41632
41593
  try {
41633
41594
  decodedSignature = multiLayerDecode(encodedSignature);
@@ -41821,4 +41782,4 @@ mkdirSync(`${karinPathBase}/${Root.pluginName}/data`);
41821
41782
  mkdirSync(Common.tempDri.images);
41822
41783
  mkdirSync(Common.tempDri.video);
41823
41784
  //#endregion
41824
- export { registerAmagiReloadListener as $, testWrapWithErrorHandler as A, METRIC_BUCKETS as B, changelog as C, dylogin as D, biLogin as E, douyinDBInstance as F, AmagiBase as G, resolveMetricBucket as H, getBilibiliDB as I, bilibiliFetcher as J, AmagiError as K, getDouyinDB as L, webConfig as M, bilibiliDBInstance as N, removeOldFiles as O, cleanOldDynamicCache as P, kuaishouFetcher as Q, getStatisticsDB as R, setdyPush as S, version as T, DouyinDBBase as U, StatisticsDBBase as V, BilibiliDBBase as W, getAmagiClient as X, douyinFetcher as Y, isSoftFailure as Z, douyinPush as _, bilibiliAPP as a, globalIgnore as b, prefix as c, globalStatistics as d, reloadAmagiConfig as et, groupStatistics as f, changeBotID as g, bilibiliPushList as h, update as i, templates as j, task as k, xiaohongshuAPP as l, bilibiliPush as m, kkkUpdateCommand as n, xiaohongshuFetcher as nt, douyinAPP as o, qrLogin as p, SOFT_ERROR_CODES as q, kkkUpdateTest as r, Root as rt, kuaishouAPP as s, kkkUpdate as t, softFetch as tt, testPush as u, douyinPushList as v, help as w, setbiliPush as x, forcePush as y, initAllDatabases as z };
41785
+ export { reloadAmagiConfig as $, templates as A, StatisticsDBBase as B, help as C, removeOldFiles as D, dylogin as E, getBilibiliDB as F, AmagiError as G, DouyinDBBase as H, getDouyinDB as I, douyinFetcher as J, SOFT_ERROR_CODES as K, getStatisticsDB as L, bilibiliDBInstance as M, cleanOldDynamicCache as N, task as O, douyinDBInstance as P, registerAmagiReloadListener as Q, initAllDatabases as R, changelog as S, biLogin as T, BilibiliDBBase as U, resolveMetricBucket as V, AmagiBase as W, isSoftFailure as X, getAmagiClient as Y, kuaishouFetcher as Z, douyinPushList as _, bilibiliAPP as a, setbiliPush as b, prefix as c, globalStatistics as d, softFetch as et, groupStatistics as f, douyinPush as g, bilibiliPushList as h, update as i, webConfig as j, testWrapWithErrorHandler as k, xiaohongshuAPP as l, bilibiliPush as m, kkkUpdateCommand as n, Root as nt, douyinAPP as o, qrLogin as p, bilibiliFetcher as q, kkkUpdateTest as r, kuaishouAPP as s, kkkUpdate as t, xiaohongshuFetcher as tt, testPush as u, forcePush as v, version as w, setdyPush as x, globalIgnore as y, METRIC_BUCKETS as z };