karin-plugin-kkk 2.32.2 → 2.32.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  import { i as __toESM } from "./rolldown-runtime.js";
2
- import { $ as SiGooglephotos, $t as Moon, A as RiHashtag, An as CircleEllipsis, At as Square, B as RiThumbUpFill, Bn as Bookmark, Bt as ScanLine, C as AiFillHeart, Cn as CornerDownLeft, Ct as UserPlus, D as Markdown, Dn as Clapperboard, Dt as Terminal, E as AiOutlineVideoCamera, En as Clock, Et as Trash2, F as RiMessage3Fill, Fn as ChartColumn, Ft as Shield, G as RiVideoLine, Gn as clsx, Gt as Quote, H as RiTrophyFill, Hn as ArrowDownToLine, Ht as RotateCcw, I as RiPieChart2Fill, In as Camera, It as ShieldCheck, J as SiSamsung, Jn as require_react, Jt as Plus, K as SiXiaomi, Kn as require_jsx_runtime, Kt as QrCode, L as RiShareForwardFill, Ln as Calendar, Lt as Share2, M as RiHeart3Line, Mn as CircleCheckBig, Mt as Sparkles, N as RiHeartLine, Nn as CircleAlert, Nt as Smartphone, O as RiArrowRightFill, On as CircleQuestionMark, Ot as Sun, P as RiLiveLine, Pn as Check, Pt as ShoppingBag, Q as SiHonor, Qn as zod_default, Qt as Music, R as RiStarFill, Rn as Box, Rt as Settings2, S as BiImage, Sn as Cpu, St as User, T as AiFillStar, Tn as Code, Tt as TriangleAlert, U as RiUserFollowLine, Un as Chip, Ut as RefreshCw, V as RiTiktokFill, Vn as BellRing, Vt as Save, W as RiVerifiedBadgeFill, Wn as Button, Wt as Radio, X as SiOneplus, Xn as Chalk, Xt as Pencil, Y as SiOppo, Yn as require_protobufjs, Yt as Play, Z as SiHuawei, Zn as Xhshow, Zt as Palette, _ as MdSchedule, _n as Eye, _t as X, a as VictoryScatter, an as LoaderCircle, at as m, b as FaTiktok, bn as Download, bt as Users, c as VictoryChart, cn as Info, ct as c, d as VictoryTheme, dn as Hash, dt as fromUnixTime, en as Monitor, et as SiGithub, f as rehypeHighlight, fn as GitBranch, ft as formatDistanceToNow, g as MdLocationOn, gn as FilePlay, gt as Zap, h as MdLightbulbOutline, hn as FileText, ht as twMerge, i as require_heic_decode, in as MapPin, it as o, j as RiHeart3Fill, jn as CircleCheck, jt as SquarePen, k as RiGroupLine, kn as CircleFadingArrowUp, kt as Star, l as VictoryAxis, ln as Image$1, lt as zhCN, m as MdInfoOutline, mn as Gamepad2, mt as differenceInSeconds, n as require_lib, nn as Menu, nt as SiApple, o as VictoryPie, on as Link, ot as a, p as MdFitScreen, pn as Gift, pt as format, q as SiVivo, qn as require_server_node, qt as Puzzle, r as require_jpeg_js, rn as Maximize, rt as SiAnthropic, s as VictoryLine, sn as LayoutTemplate, st as n, t as createProxyMiddleware, tn as MessageCircle, tt as SiBilibili, u as VictoryLabel, un as Heart, ut as parse, v as FaCommentDots, vn as EyeOff, vt as WandSparkles, w as AiFillPushpin, wn as Copy, wt as Upload, x as FaUserGroup, xn as Crown, xt as UsersRound, y as FaMusic, yn as ExternalLink, yt as Video, z as RiStarLine, zn as Bot, zt as Search } from "./vendor.js";
2
+ import { $ as SiGooglephotos, $n as ArrowDownToLine, $t as RefreshCw, A as RiHashtag, An as Download, At as Users, B as RiThumbUpFill, Bn as CircleFadingArrowUp, Bt as Square, C as AiFillHeart, Cn as Gift, Ct as format, D as Markdown, Dn as Eye, Dt as X, E as AiOutlineVideoCamera, En as FilePlay, Et as Zap, F as RiMessage3Fill, Fn as Code, Ft as TriangleAlert, G as RiVideoLine, Gn as Check, Gt as Shield, H as RiTrophyFill, Hn as CircleCheck, Ht as Sparkles, I as RiPieChart2Fill, In as Clock, It as Trash2, J as SiSamsung, Jn as Calendar, Jt as Settings2, K as SiXiaomi, Kn as ChartColumn, Kt as ShieldCheck, L as RiShareForwardFill, Ln as Clock3, Lt as Terminal, M as RiHeart3Line, Mn as Cpu, Mt as UsersRound, N as RiHeartLine, Nn as CornerDownLeft, Nt as UserPlus, O as RiArrowRightFill, On as EyeOff, Ot as WandSparkles, P as RiLiveLine, Pn as Copy, Pt as Upload, Q as SiHonor, Qn as BellRing, Qt as RotateCcw, R as RiStarFill, Rn as Clapperboard, Rt as Sun, S as BiImage, Sn as GitBranch, St as formatDistanceToNow, T as AiFillStar, Tn as FileText, Tt as twMerge, U as RiUserFollowLine, Un as CircleCheckBig, Ut as Smartphone, V as RiTiktokFill, Vn as CircleEllipsis, Vt as SquarePen, W as RiVerifiedBadgeFill, Wn as CircleAlert, Wt as ShoppingBag, X as SiOneplus, Xn as Bot, Xt as ScanLine, Y as SiOppo, Yn as Box, Yt as Search, Z as SiHuawei, Zn as Bookmark, Zt as Save, _ as MdSchedule, _n as LayoutTemplate, _t as t, a as VictoryScatter, an as Play, ar as require_react, at as r$1, b as FaTiktok, bn as Heart, bt as parse, c as VictoryChart, cn as Music, cr as Xhshow, ct as e$1, d as VictoryTheme, dn as MessageCircle, dt as n, en as Radio, er as Chip, et as SiGithub, f as rehypeHighlight, fn as Menu, ft as e, g as MdLocationOn, gn as Link, gt as c, h as MdLightbulbOutline, hn as LoaderCircle, ht as o$3, i as require_heic_decode, in as Plus, ir as require_server_node, it as o$2, j as RiHeart3Fill, jn as Crown, jt as User, k as RiGroupLine, kn as ExternalLink, kt as Video, l as VictoryAxis, ln as Moon, lr as zod_default, lt as m, m as MdInfoOutline, mn as MapPin, mt as o$1, n as require_lib, nn as QrCode, nr as clsx, nt as SiApple, o as VictoryPie, on as Pencil, or as require_protobufjs, ot as o, p as MdFitScreen, pn as Maximize, pt as a$1, q as SiVivo, qn as Camera, qt as Share2, r as require_jpeg_js, rn as Puzzle, rr as require_jsx_runtime, rt as SiAnthropic, s as VictoryLine, sn as Palette, sr as Chalk, st as o$4, t as createProxyMiddleware, tn as Quote, tr as Button, tt as SiBilibili, u as VictoryLabel, un as Monitor, ut as a, v as FaCommentDots, vn as Info, vt as r, w as AiFillPushpin, wn as Gamepad2, wt as differenceInSeconds, x as FaUserGroup, xn as Hash, xt as fromUnixTime, y as FaMusic, yn as Image$1, yt as zhCN, z as RiStarLine, zn as CircleQuestionMark, zt as Star } from "./vendor.js";
3
3
  import "node:module";
4
4
  import fs from "node:fs";
5
5
  import path, { resolve } from "node:path";
@@ -12791,7 +12791,7 @@ async function processImageUrl(imageUrl, title, index) {
12791
12791
  //#region ../template/src/dev/preview/utils/time.ts
12792
12792
  var import_react = /* @__PURE__ */ __toESM(require_react(), 1);
12793
12793
  var import_server_node = require_server_node();
12794
- var formatDuration$4 = (ms) => {
12794
+ var formatDuration$5 = (ms) => {
12795
12795
  const totalSeconds = Math.max(Math.floor(ms / 1e3), 0);
12796
12796
  const hours = Math.floor(totalSeconds / 3600);
12797
12797
  const minutes = Math.floor(totalSeconds % 3600 / 60);
@@ -12815,7 +12815,7 @@ var buildStatus = (state) => {
12815
12815
  statusText: `文件 ${filePath} 将在未知时间后删除`,
12816
12816
  countdownText: "--:--"
12817
12817
  };
12818
- const countdownText = formatDuration$4(state.remainingMs);
12818
+ const countdownText = formatDuration$5(state.remainingMs);
12819
12819
  return {
12820
12820
  statusText: `文件 ${filePath} 将在 ${countdownText} 后删除`,
12821
12821
  countdownText
@@ -12995,7 +12995,7 @@ var PreviewLayout = ({ state }) => {
12995
12995
  };
12996
12996
  //#endregion
12997
12997
  //#region ../template/src/utils/cn.ts
12998
- function cn(...inputs) {
12998
+ function cn$1(...inputs) {
12999
12999
  return twMerge(clsx(inputs));
13000
13000
  }
13001
13001
  //#endregion
@@ -14026,7 +14026,7 @@ var ViteLogo = ({ className = "w-auto h-12" }) => /* @__PURE__ */ (0, import_jsx
14026
14026
  var DefaultLayout = ({ children, version, data, scale = 3, className = "", style = {}, watermarkTextBitSize }) => {
14027
14027
  const { useDarkTheme } = data;
14028
14028
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
14029
- className: cn("w-360 shrink-0 bg-background text-foreground font-[HarmonyOSHans-Regular]", useDarkTheme ? "dark" : "light", className),
14029
+ className: cn$1("w-360 shrink-0 bg-background text-foreground font-[HarmonyOSHans-Regular]", useDarkTheme ? "dark" : "light", className),
14030
14030
  "data-theme": useDarkTheme ? "dark" : "light",
14031
14031
  id: "container",
14032
14032
  style: {
@@ -14102,12 +14102,12 @@ var DefaultLayout = ({ children, version, data, scale = 3, className = "", style
14102
14102
  className: "w-4 h-4"
14103
14103
  }),
14104
14104
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
14105
- className: cn(version.hasUpdate && "text-success", !version.hasUpdate && version.releaseType === "Preview" && "text-warning"),
14105
+ className: cn$1(version.hasUpdate && "text-success", !version.hasUpdate && version.releaseType === "Preview" && "text-warning"),
14106
14106
  children: version.hasUpdate ? "有可用更新" : version.releaseType
14107
14107
  })
14108
14108
  ]
14109
14109
  }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
14110
- className: cn("text-5xl font-bold tracking-wide", version.hasUpdate && "text-success", !version.hasUpdate && version.releaseType === "Preview" && "text-warning"),
14110
+ className: cn$1("text-5xl font-bold tracking-wide", version.hasUpdate && "text-success", !version.hasUpdate && version.releaseType === "Preview" && "text-warning"),
14111
14111
  children: ["v", version.pluginVersion]
14112
14112
  })]
14113
14113
  }),
@@ -14184,7 +14184,7 @@ var DefaultLayout = ({ children, version, data, scale = 3, className = "", style
14184
14184
  var UsernameDisplay = ({ metadata, className, style }) => {
14185
14185
  const vipColor = metadata.vipStatus === 1 ? metadata.nicknameColor ?? "#FB7299" : null;
14186
14186
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
14187
- className: cn(!vipColor && "text-foreground", "font-bold", className),
14187
+ className: cn$1(!vipColor && "text-foreground", "font-bold", className),
14188
14188
  style: {
14189
14189
  ...style,
14190
14190
  ...vipColor ? { color: vipColor } : {}
@@ -14616,14 +14616,14 @@ var BangumiBilibiliEpisodes = (props) => {
14616
14616
  className: "flex justify-center items-center text-7xl font-bold select-text text-foreground",
14617
14617
  children: day
14618
14618
  }),
14619
- !isLastOfAll && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: cn("mt-8 w-1 bg-divider", episodesInSameDate > 1 ? "h-110" : "h-95") })
14619
+ !isLastOfAll && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: cn$1("mt-8 w-1 bg-divider", episodesInSameDate > 1 ? "h-110" : "h-95") })
14620
14620
  ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
14621
14621
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "w-1 h-10 bg-divider" }),
14622
14622
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "my-2 w-4 h-4 rounded-full bg-divider" }),
14623
- (!isLastOfAll || episodesInSameDate > 1) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: cn("w-1 bg-divider", isLastOfDate ? "h-110" : "h-130") })
14623
+ (!isLastOfAll || episodesInSameDate > 1) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: cn$1("w-1 bg-divider", isLastOfDate ? "h-110" : "h-130") })
14624
14624
  ] })
14625
14625
  }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
14626
- className: cn("flex-1 min-w-0", !isLastOfAll && isLastOfDate && "mb-20"),
14626
+ className: cn$1("flex-1 min-w-0", !isLastOfAll && isLastOfDate && "mb-20"),
14627
14627
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
14628
14628
  className: "flex justify-between items-center mb-10",
14629
14629
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
@@ -14850,6 +14850,15 @@ var createLinkCardNode = (title, url, options = {}) => ({
14850
14850
  meta: options.meta
14851
14851
  });
14852
14852
  /**
14853
+ * 创建 hashtag 节点。
14854
+ *
14855
+ * 纯文本高亮,不带任何图标。适用于抖音等平台的 #话题# 展示。
14856
+ */
14857
+ var createHashtagNode = (text) => ({
14858
+ type: "hashtag",
14859
+ text
14860
+ });
14861
+ /**
14853
14862
  * 合并相邻文本节点并丢弃空文本节点。
14854
14863
  *
14855
14864
  * 这样 core 可以按匹配过程简单 push 节点,最后统一整理,避免前端拿到碎片过多的数据。
@@ -14887,6 +14896,7 @@ var extractRichTextPlainText = (document) => {
14887
14896
  case "webLink":
14888
14897
  case "vote":
14889
14898
  case "viewPicture":
14899
+ case "hashtag":
14890
14900
  case "emoji": return "text" in node ? node.text ?? "" : node.name ?? "";
14891
14901
  case "heading":
14892
14902
  case "paragraph":
@@ -14914,6 +14924,11 @@ var createRichTextDocument = (nodes, options = {}) => ({
14914
14924
  nodes: normalizeRichTextNodes(nodes)
14915
14925
  });
14916
14926
  //#endregion
14927
+ //#region ../richtext/src/react/cn.ts
14928
+ function cn(...inputs) {
14929
+ return twMerge(clsx(inputs));
14930
+ }
14931
+ //#endregion
14917
14932
  //#region ../richtext/src/react/index.tsx
14918
14933
  /**
14919
14934
  * 限制图片来源协议。
@@ -14972,7 +14987,7 @@ var SearchKeywordIcon = ({ className }) => {
14972
14987
  };
14973
14988
  /** 话题图标 */
14974
14989
  var TopicIcon = ({ className }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", {
14975
- className: clsx(className, "inline-block w-16 mb-4 mr-4 align-middle"),
14990
+ className: cn(className, "inline-block w-16 mb-4 mr-4 align-middle"),
14976
14991
  xmlns: "http://www.w3.org/2000/svg",
14977
14992
  viewBox: "0 0 16 16",
14978
14993
  children: [
@@ -14996,7 +15011,7 @@ var TopicIcon = ({ className }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
14996
15011
  });
14997
15012
  /** 抽奖图标 */
14998
15013
  var LotteryIcon = ({ className }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", {
14999
- className: clsx(className, "inline-block w-16 h-auto mb-4 mr-2 align-middle"),
15014
+ className: cn(className, "inline-block w-16 h-auto mb-4 mr-2 align-middle"),
15000
15015
  xmlns: "http://www.w3.org/2000/svg",
15001
15016
  viewBox: "0 0 18 18",
15002
15017
  children: [
@@ -15024,7 +15039,7 @@ var LotteryIcon = ({ className }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs
15024
15039
  });
15025
15040
  /** 网页链接图标 */
15026
15041
  var WebLinkIcon = ({ className }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", {
15027
- className: clsx(className, "inline-block w-14 mb-3 mr-2 align-middle"),
15042
+ className: cn(className, "inline-block w-14 mb-3 mr-2 align-middle"),
15028
15043
  xmlns: "http://www.w3.org/2000/svg",
15029
15044
  viewBox: "0 0 18 18",
15030
15045
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", {
@@ -15037,7 +15052,7 @@ var WebLinkIcon = ({ className }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs
15037
15052
  });
15038
15053
  /** 投票图标 */
15039
15054
  var VoteIcon = ({ className }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", {
15040
- className: clsx(className, "inline-block w-20 mb-2 align-middle"),
15055
+ className: cn(className, "inline-block w-20 mb-2 align-middle"),
15041
15056
  xmlns: "http://www.w3.org/2000/svg",
15042
15057
  viewBox: "0 0 18 18",
15043
15058
  children: [
@@ -15057,7 +15072,7 @@ var VoteIcon = ({ className }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("
15057
15072
  });
15058
15073
  /** 查看图片图标 */
15059
15074
  var ViewPictureIcon = ({ className }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", {
15060
- className: clsx(className, "inline-block w-20 align-middle"),
15075
+ className: cn(className, "inline-block w-20 align-middle"),
15061
15076
  xmlns: "http://www.w3.org/2000/svg",
15062
15077
  viewBox: "0 0 22 22",
15063
15078
  width: "22",
@@ -15172,6 +15187,11 @@ var renderNodeToReact = (node, index, options) => {
15172
15187
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TopicIcon, {})
15173
15188
  }), node.text]
15174
15189
  }, `topic-${index}`);
15190
+ case "hashtag": return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
15191
+ className: options.hashtag?.className,
15192
+ "data-richtext-node": "hashtag",
15193
+ children: node.text
15194
+ }, `hashtag-${index}`);
15175
15195
  case "at": return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
15176
15196
  className: options.at?.className,
15177
15197
  "data-richtext-node": "at",
@@ -15191,7 +15211,7 @@ var renderNodeToReact = (node, index, options) => {
15191
15211
  }), node.text]
15192
15212
  }, `lottery-${index}`);
15193
15213
  case "webLink": return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("a", {
15194
- className: clsx(options.webLink?.className, "break-all"),
15214
+ className: cn(options.webLink?.className, "break-all"),
15195
15215
  href: node.jumpUrl,
15196
15216
  target: "_blank",
15197
15217
  rel: "noopener noreferrer",
@@ -15277,7 +15297,7 @@ var renderNodeToReact = (node, index, options) => {
15277
15297
  const lines = node.content.split("\n");
15278
15298
  const showLang = node.language && node.language !== "plaintext";
15279
15299
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
15280
- className: clsx("bg-surface rounded-4xl my-8 border border-border", options.codeBlock?.className),
15300
+ className: cn("bg-surface rounded-4xl my-8 border border-border", options.codeBlock?.className),
15281
15301
  "data-richtext-node": "codeBlock",
15282
15302
  "data-language": node.language,
15283
15303
  children: [showLang && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
@@ -15571,7 +15591,7 @@ var FansMedal = ({ detail }) => {
15571
15591
  const nameColor = intToRgba(detail.medal_color_name);
15572
15592
  const levelColor = intToRgba(detail.medal_color_level);
15573
15593
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
15574
- className: cn("inline-flex items-center shrink-0", "h-14 rounded-full border"),
15594
+ className: cn$1("inline-flex items-center shrink-0", "h-14 rounded-full border"),
15575
15595
  style: {
15576
15596
  borderColor,
15577
15597
  backgroundImage: `linear-gradient(90deg, ${bgStart}, ${bgEnd})`
@@ -15583,7 +15603,7 @@ var FansMedal = ({ detail }) => {
15583
15603
  referrerPolicy: "no-referrer",
15584
15604
  crossOrigin: "anonymous"
15585
15605
  }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
15586
- className: cn("flex items-center", detail.first_icon ? "pr-4" : "px-4"),
15606
+ className: cn$1("flex items-center", detail.first_icon ? "pr-4" : "px-4"),
15587
15607
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
15588
15608
  className: "font-medium whitespace-nowrap text-3xl",
15589
15609
  style: { color: nameColor },
@@ -15601,7 +15621,7 @@ var FansMedal = ({ detail }) => {
15601
15621
  */
15602
15622
  var TopBadge = () => {
15603
15623
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
15604
- className: cn("inline-flex justify-center items-center", "px-4 py-2 mr-4 mb-1 rounded-xl", "text-[45px] font-light leading-none", "align-baseline", "bg-[#ffedf5] text-[#ff799e]", "dark:bg-[#321b26] dark:text-[#cb5775]"),
15624
+ className: cn$1("inline-flex justify-center items-center", "px-4 py-2 mr-4 mb-1 rounded-xl", "text-[45px] font-light leading-none", "align-baseline", "bg-[#ffedf5] text-[#ff799e]", "dark:bg-[#321b26] dark:text-[#cb5775]"),
15605
15625
  children: "置顶"
15606
15626
  });
15607
15627
  };
@@ -15785,7 +15805,7 @@ var VideoInfoHeader$1 = (props) => {
15785
15805
  */
15786
15806
  var CommentItemComponent$2 = ({ isLast = false, ...props }) => {
15787
15807
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
15788
- className: cn("flex relative px-10 py-10 max-w-full", { "pb-0": isLast }),
15808
+ className: cn$1("flex relative px-10 py-10 max-w-full", { "pb-0": isLast }),
15789
15809
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
15790
15810
  className: "relative mr-[33.75px] shrink-0 w-50 h-50 flex items-center justify-center",
15791
15811
  children: [
@@ -16884,7 +16904,7 @@ var BilibiliVideoDynamic = import_react.memo((props) => {
16884
16904
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BilibiliVideoContent, { ...props }),
16885
16905
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-15" }),
16886
16906
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BilibiliDynamicStatus, { ...props.data }),
16887
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: cn(props.data.staff && props.data.staff.length > 0 && "h-23", !props.data.staff && "h-40") }),
16907
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: cn$1(props.data.staff && props.data.staff.length > 0 && "h-23", !props.data.staff && "h-40") }),
16888
16908
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BilibiliVideoStaff, { ...props }),
16889
16909
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BilibiliDynamicFooter, { ...props.data })
16890
16910
  ]
@@ -17077,7 +17097,7 @@ var BilibiliUgcCard = ({ ugc }) => {
17077
17097
  var BilibiliAdditionalCard = ({ additional, gap = true, className }) => {
17078
17098
  if (!additional) return null;
17079
17099
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
17080
- className: cn(gap && "px-20 pb-20", className),
17100
+ className: cn$1(gap && "px-20 pb-20", className),
17081
17101
  children: [
17082
17102
  additional.type === "ADDITIONAL_TYPE_RESERVE" && additional.reserve && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BilibiliReserveCard, { reserve: additional.reserve }),
17083
17103
  additional.type === "ADDITIONAL_TYPE_VOTE" && additional.vote && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BilibiliVoteCard, { vote: additional.vote }),
@@ -18997,7 +19017,7 @@ BilibiliVideoInfo.displayName = "BilibiliVideoInfo";
18997
19017
  /**
18998
19018
  * 抖音Logo头部组件
18999
19019
  */
19000
- var DouyinHeader$4 = ({ useDarkTheme }) => {
19020
+ var DouyinHeader$2 = ({ useDarkTheme }) => {
19001
19021
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
19002
19022
  className: "flex items-center px-12 py-15",
19003
19023
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
@@ -19126,7 +19146,7 @@ var ContentSection = ({ markdown, images }) => {
19126
19146
  /**
19127
19147
  * 作品信息组件
19128
19148
  */
19129
- var InfoSection$4 = (props) => {
19149
+ var InfoSection$2 = (props) => {
19130
19150
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
19131
19151
  className: "flex flex-col px-16 py-5",
19132
19152
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
@@ -19161,7 +19181,7 @@ var InfoSection$4 = (props) => {
19161
19181
  /**
19162
19182
  * 用户信息组件
19163
19183
  */
19164
- var UserInfoSection$3 = (props) => {
19184
+ var UserInfoSection$1 = (props) => {
19165
19185
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
19166
19186
  className: "flex flex-col gap-12",
19167
19187
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
@@ -19255,7 +19275,7 @@ var DouyinArticleWork = (props) => {
19255
19275
  ...props,
19256
19276
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
19257
19277
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-15" }),
19258
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DouyinHeader$4, { useDarkTheme: props.data.useDarkTheme }),
19278
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DouyinHeader$2, { useDarkTheme: props.data.useDarkTheme }),
19259
19279
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-15" }),
19260
19280
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TitleSection, {
19261
19281
  title: props.data.title,
@@ -19268,13 +19288,13 @@ var DouyinArticleWork = (props) => {
19268
19288
  images: props.data.images
19269
19289
  }),
19270
19290
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-15" }),
19271
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InfoSection$4, { ...props }),
19291
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InfoSection$2, { ...props }),
19272
19292
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-25" }),
19273
19293
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
19274
19294
  className: "flex flex-col gap-10 px-0 pt-25",
19275
19295
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
19276
19296
  className: "flex justify-between items-start px-20 pb-20",
19277
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(UserInfoSection$3, { ...props }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
19297
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(UserInfoSection$1, { ...props }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
19278
19298
  className: "flex flex-col items-center gap-4",
19279
19299
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
19280
19300
  src: generateQRCode(props.data.share_url, props.data.useDarkTheme),
@@ -19595,26 +19615,26 @@ var ReplyItemComponent = ({ reply, depth = 0, isLast, maxDepth = 6 }) => {
19595
19615
  })
19596
19616
  }), reply.children.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "w-0.5 bg-border-secondary h-full grow mt-3 rounded-t-full" })]
19597
19617
  }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
19598
- className: cn("flex flex-col pl-6 min-w-0 gap-2", isLast && reply.children.length === 0 ? "pb-16" : "pb-6"),
19618
+ className: cn$1("flex flex-col pl-6 min-w-0 gap-2", isLast && reply.children.length === 0 ? "pb-16" : "pb-6"),
19599
19619
  children: [
19600
19620
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
19601
19621
  className: "flex flex-nowrap items-center content-center w-full overflow-hidden",
19602
19622
  children: [
19603
19623
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
19604
- className: cn("mr-2 text-4xl font-normal text-muted", isNicknameLonger ? "min-w-0 truncate shrink" : "shrink-0"),
19624
+ className: cn$1("mr-2 text-4xl font-normal text-muted", isNicknameLonger ? "min-w-0 truncate shrink" : "shrink-0"),
19605
19625
  children: reply.nickname
19606
19626
  }),
19607
19627
  reply.label_text !== "" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
19608
- className: cn("px-4 py-1 text-3xl rounded-xl mr-2", reply.label_text === "作者" ? "bg-[#fe2c55] text-white" : "bg-surface text-muted"),
19628
+ className: cn$1("px-4 py-1 text-3xl rounded-xl mr-2", reply.label_text === "作者" ? "bg-[#fe2c55] text-white" : "bg-surface text-muted"),
19609
19629
  children: reply.label_text
19610
19630
  }),
19611
19631
  reply.reply_to_username && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
19612
- className: cn("flex items-center", !isNicknameLonger ? "overflow-hidden min-w-0 shrink" : "shrink-0"),
19632
+ className: cn$1("flex items-center", !isNicknameLonger ? "overflow-hidden min-w-0 shrink" : "shrink-0"),
19613
19633
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(a, {
19614
19634
  weight: "fill",
19615
19635
  className: "w-7 h-auto mr-3.5 mx-1 text-muted shrink-0"
19616
19636
  }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
19617
- className: cn("text-4xl font-normal text-muted", !isNicknameLonger && "truncate"),
19637
+ className: cn$1("text-4xl font-normal text-muted", !isNicknameLonger && "truncate"),
19618
19638
  children: reply.reply_to_username
19619
19639
  })]
19620
19640
  })
@@ -19684,7 +19704,7 @@ var ReplyItemComponent = ({ reply, depth = 0, isLast, maxDepth = 6 }) => {
19684
19704
  */
19685
19705
  var CommentItemComponent$1 = (props) => {
19686
19706
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
19687
- className: cn("flex flex-col px-6 pt-8", {
19707
+ className: cn$1("flex flex-col px-6 pt-8", {
19688
19708
  "pb-0": props.isLast,
19689
19709
  "pb-10": !props.isLast
19690
19710
  }),
@@ -19846,7 +19866,7 @@ var DouyinComment = import_react.memo((props) => {
19846
19866
  * @param props 组件属性
19847
19867
  * @returns JSX元素
19848
19868
  */
19849
- var DouyinHeader$3 = ({ useDarkTheme }) => {
19869
+ var DouyinHeader$1 = ({ useDarkTheme }) => {
19850
19870
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
19851
19871
  className: "flex items-center px-12 py-15",
19852
19872
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
@@ -19867,7 +19887,7 @@ var DouyinHeader$3 = ({ useDarkTheme }) => {
19867
19887
  * @param props 组件属性
19868
19888
  * @returns JSX元素
19869
19889
  */
19870
- var CoverSection$3 = ({ imageUrl }) => {
19890
+ var CoverSection$1 = ({ imageUrl }) => {
19871
19891
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
19872
19892
  className: "flex flex-col items-center my-5",
19873
19893
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
@@ -19885,7 +19905,7 @@ var CoverSection$3 = ({ imageUrl }) => {
19885
19905
  * @param props 组件属性
19886
19906
  * @returns JSX元素
19887
19907
  */
19888
- var InfoSection$3 = (props) => {
19908
+ var InfoSection$1 = (props) => {
19889
19909
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
19890
19910
  className: "flex flex-col px-16 py-5",
19891
19911
  children: [
@@ -19937,7 +19957,7 @@ var InfoSection$3 = (props) => {
19937
19957
  * @param props 组件属性
19938
19958
  * @returns JSX元素
19939
19959
  */
19940
- var UserInfoSection$2 = (props) => {
19960
+ var UserInfoSection = (props) => {
19941
19961
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
19942
19962
  className: "flex flex-col gap-12",
19943
19963
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
@@ -20036,7 +20056,7 @@ var UserInfoSection$2 = (props) => {
20036
20056
  });
20037
20057
  };
20038
20058
  /** 共创者信息 */
20039
- var CoCreatorsInfo$2 = ({ info }) => {
20059
+ var CoCreatorsInfo = ({ info }) => {
20040
20060
  const creators = info?.co_creators ?? [];
20041
20061
  if (creators.length === 0) return null;
20042
20062
  const items = creators.slice(0, 50);
@@ -20121,11 +20141,11 @@ var DouyinDynamic = (props) => {
20121
20141
  ...props,
20122
20142
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
20123
20143
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-15" }),
20124
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DouyinHeader$3, { useDarkTheme: props.data.useDarkTheme }),
20144
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DouyinHeader$1, { useDarkTheme: props.data.useDarkTheme }),
20125
20145
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-15" }),
20126
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CoverSection$3, { imageUrl: props.data.image_url }),
20146
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CoverSection$1, { imageUrl: props.data.image_url }),
20127
20147
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-5" }),
20128
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InfoSection$3, { ...props }),
20148
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InfoSection$1, { ...props }),
20129
20149
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-25" }),
20130
20150
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20131
20151
  className: "flex flex-col gap-10 px-0 pt-25",
@@ -20140,10 +20160,10 @@ var DouyinDynamic = (props) => {
20140
20160
  children: [coCreatorCount, "人共创"]
20141
20161
  })]
20142
20162
  })
20143
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CoCreatorsInfo$2, { info: props.data.cooperation_info })]
20163
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CoCreatorsInfo, { info: props.data.cooperation_info })]
20144
20164
  }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20145
20165
  className: "flex justify-between items-start px-20 pb-20",
20146
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(UserInfoSection$2, { ...props }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
20166
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(UserInfoSection, { ...props }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
20147
20167
  className: "flex flex-col items-center gap-4",
20148
20168
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
20149
20169
  src: generateQRCode(props.data.share_url, props.data.useDarkTheme),
@@ -20427,197 +20447,344 @@ var StatItem$3 = ({ icon: IconComponent, value, iconClassName }) => /* @__PURE__
20427
20447
  });
20428
20448
  //#endregion
20429
20449
  //#region ../template/src/components/platforms/douyin/ImageWork.tsx
20430
- /**
20431
- * 抖音Logo头部组件
20432
- */
20433
- var DouyinHeader$2 = ({ useDarkTheme }) => {
20434
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20435
- className: "flex items-center px-12 py-15",
20436
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
20437
- className: "w-[39%] h-50 bg-cover bg-center bg-fixed",
20438
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
20439
- src: useDarkTheme ? "/image/douyin/dylogo-light.svg" : "/image/douyin/dylogo-dark.svg",
20440
- alt: "抖音Logo",
20441
- className: "object-contain w-full h-full"
20442
- })
20443
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
20444
- className: "text-[65px] ml-4 text-foreground/70",
20445
- children: "记录美好生活"
20446
- })]
20447
- });
20448
- };
20449
- /**
20450
- * 图文封面组件
20451
- */
20452
- var CoverSection$2 = ({ imageUrl }) => {
20453
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
20454
- className: "flex flex-col items-center my-5",
20455
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
20456
- className: "flex flex-col items-center overflow-hidden shadow-large rounded-[25px] w-[90%] relative",
20457
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
20458
- className: "rounded-[25px] object-contain w-full h-full",
20459
- src: imageUrl,
20460
- alt: "图文封面"
20461
- })
20450
+ /** 抖音实况图标,来源于根目录 noun-live-photo-710576.svg 的 React 化精简版。 */
20451
+ var LivePhotoIcon = ({ size = 28, className }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", {
20452
+ width: size,
20453
+ height: size,
20454
+ viewBox: "0 0 100 100",
20455
+ fill: "none",
20456
+ xmlns: "http://www.w3.org/2000/svg",
20457
+ className,
20458
+ "aria-hidden": "true",
20459
+ children: [
20460
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", {
20461
+ cx: "50",
20462
+ cy: "50",
20463
+ r: "37",
20464
+ stroke: "currentColor",
20465
+ strokeWidth: "6",
20466
+ strokeDasharray: "2 9",
20467
+ strokeLinecap: "round"
20468
+ }),
20469
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", {
20470
+ cx: "50",
20471
+ cy: "50",
20472
+ r: "25",
20473
+ stroke: "currentColor",
20474
+ strokeWidth: "6"
20475
+ }),
20476
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", {
20477
+ cx: "50",
20478
+ cy: "50",
20479
+ r: "10",
20480
+ fill: "currentColor"
20462
20481
  })
20463
- });
20482
+ ]
20483
+ });
20484
+ /** 首图媒体类型徽标配置。 */
20485
+ var imageMediaTypeMeta = {
20486
+ static: {
20487
+ label: "静态",
20488
+ icon: o$1
20489
+ },
20490
+ live: {
20491
+ label: "动图",
20492
+ icon: LivePhotoIcon
20493
+ },
20494
+ clip: {
20495
+ label: "短片",
20496
+ icon: o$2
20497
+ }
20464
20498
  };
20465
- /**
20466
- * 作品信息组件
20467
- */
20468
- var InfoSection$2 = (props) => {
20469
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20470
- className: "flex flex-col px-16 py-5",
20471
- children: [
20472
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
20473
- className: "text-[70px] font-bold leading-relaxed mb-9 text-foreground select-text",
20474
- style: {
20475
- letterSpacing: "1.5px",
20476
- wordWrap: "break-word"
20477
- },
20478
- dangerouslySetInnerHTML: { __html: props.data.desc }
20479
- }),
20480
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20481
- className: "flex items-center gap-6 text-[45px] text-muted font-light mb-2.5 select-text",
20482
- children: [
20483
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20484
- className: "flex gap-2 items-center",
20485
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heart, { className: "w-11 h-11 text-like" }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [props.data.dianzan, "点赞"] })]
20486
- }),
20487
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "·" }),
20488
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20489
- className: "flex gap-2 items-center",
20490
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(MessageCircle, { className: "w-11 h-11 text-comment" }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [props.data.pinglun, "评论"] })]
20491
- }),
20492
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "·" }),
20493
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20494
- className: "flex gap-2 items-center",
20495
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Bookmark, { className: "w-11 h-11" }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [props.data.shouchang, "收藏"] })]
20496
- }),
20497
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "·" }),
20498
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20499
- className: "flex gap-2 items-center",
20500
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Share2, { className: "w-11 h-11 text-success" }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [props.data.share, "分享"] })]
20501
- })
20502
- ]
20503
- }),
20504
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20505
- className: "flex items-center gap-2 text-[45px] text-muted font-light select-text",
20506
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Clock, { className: "w-11 h-11 text-time" }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: ["发布于: ", props.data.create_time] })]
20507
- }),
20508
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20509
- className: "flex items-center gap-2 text-[45px] text-muted font-light select-text",
20510
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Maximize, { className: "w-11 h-11 text-time text-time" }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: ["图片生成于: ", format(/* @__PURE__ */ new Date(), "yyyy-MM-dd HH:mm:ss")] })]
20511
- })
20512
- ]
20499
+ var DouyinAvatarUserInfo$1 = (props) => {
20500
+ const { avater_url, username, create_time, useDarkTheme, dynamicTYPE } = props.data;
20501
+ const publishTime = formatDistanceToNow(fromUnixTime(create_time), {
20502
+ addSuffix: true,
20503
+ locale: zhCN
20513
20504
  });
20514
- };
20515
- /**
20516
- * 用户信息组件
20517
- */
20518
- var UserInfoSection$1 = (props) => {
20519
20505
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20520
- className: "flex flex-col gap-12",
20506
+ className: "flex gap-10 items-center justify-between px-0 pb-0 pl-24 pr-10",
20521
20507
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20522
- className: "flex gap-12 items-start",
20508
+ className: "flex gap-10 items-center",
20523
20509
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
20524
- className: "relative shrink-0",
20525
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
20526
- className: "flex justify-center items-center bg-white rounded-full w-35 h-35",
20527
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
20528
- src: props.data.avater_url,
20529
- alt: "头像",
20530
- className: "rounded-full w-33 h-33 shadow-large"
20531
- })
20510
+ className: "flex justify-center items-center bg-white rounded-full w-35 h-35",
20511
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
20512
+ src: avater_url,
20513
+ alt: "头像",
20514
+ className: "rounded-full w-33 h-33 shadow-large",
20515
+ referrerPolicy: "no-referrer",
20516
+ crossOrigin: "anonymous"
20532
20517
  })
20533
20518
  }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20534
- className: "flex flex-col gap-5",
20535
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20536
- className: "text-7xl font-bold select-text text-foreground",
20537
- children: ["@", props.data.username]
20519
+ className: "flex flex-col gap-8 text-7xl",
20520
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
20521
+ className: "text-6xl font-bold select-text text-foreground",
20522
+ children: username
20538
20523
  }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20539
- className: "flex gap-2 items-center text-4xl text-muted",
20540
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Hash, {
20541
- size: 32,
20542
- className: "text-muted"
20543
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
20524
+ className: "flex gap-2 items-center text-4xl font-normal whitespace-nowrap text-muted",
20525
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Clock3, { size: 40 }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
20544
20526
  className: "select-text",
20545
- children: ["抖音号: ", props.data.抖音号]
20527
+ children: publishTime
20546
20528
  })]
20547
20529
  })]
20548
20530
  })]
20549
20531
  }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20550
- className: "text-3xl flex gap-6 items-center text-foreground/70",
20532
+ className: "shrink-0 flex flex-col items-end gap-2",
20533
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
20534
+ src: useDarkTheme ? "/image/douyin/dylogo-light.svg" : "/image/douyin/dylogo-dark.svg",
20535
+ alt: "抖音",
20536
+ className: "h-20 w-auto object-contain"
20537
+ }), dynamicTYPE && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
20538
+ className: "px-6 py-2 rounded-full bg-surface-secondary text-2xl font-medium text-muted select-text tracking-widest",
20539
+ children: dynamicTYPE
20540
+ })]
20541
+ })]
20542
+ });
20543
+ };
20544
+ var DouyinCoverImage = (props) => {
20545
+ const { image_list, music } = props.data;
20546
+ const imageItems = image_list.images;
20547
+ const cover = imageItems[0];
20548
+ const previews = imageItems.slice(1);
20549
+ const totalCount = image_list.total_count;
20550
+ const previewItems = previews.slice(0, 2);
20551
+ if (!cover?.url) return null;
20552
+ const firstMediaMeta = imageMediaTypeMeta[cover?.media_type ?? "static"];
20553
+ const FirstMediaIcon = firstMediaMeta.icon;
20554
+ const firstMediaBadge = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20555
+ className: "absolute top-7 right-7 z-20 flex items-center gap-2 px-4 py-2 rounded-2xl bg-black/50 backdrop-blur-sm text-white shadow-large",
20556
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(FirstMediaIcon, {
20557
+ size: 34,
20558
+ className: "text-white",
20559
+ weight: "fill"
20560
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
20561
+ className: "text-3xl font-medium select-text",
20562
+ children: firstMediaMeta.label
20563
+ })]
20564
+ });
20565
+ const musicBadge = music && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20566
+ className: "absolute left-7 bottom-7 z-20 flex items-center gap-4 max-w-[72%] p-3 rounded-3xl bg-black/45 backdrop-blur-2xl border border-white/20 shadow-large overflow-hidden",
20567
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
20568
+ className: "relative shrink-0 w-18 h-18",
20569
+ children: music.cover ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
20570
+ src: music.cover,
20571
+ alt: "",
20572
+ className: "absolute inset-0 w-full h-full rounded-2xl object-cover blur-md scale-110 opacity-70",
20573
+ referrerPolicy: "no-referrer",
20574
+ crossOrigin: "anonymous"
20575
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
20576
+ src: music.cover,
20577
+ alt: "BGM封面",
20578
+ className: "relative z-10 w-full h-full rounded-2xl object-cover",
20579
+ referrerPolicy: "no-referrer",
20580
+ crossOrigin: "anonymous"
20581
+ })] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
20582
+ className: "flex items-center justify-center w-full h-full rounded-2xl bg-white/15 text-white",
20583
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(e, {
20584
+ size: 36,
20585
+ weight: "fill"
20586
+ })
20587
+ })
20588
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20589
+ className: "flex flex-col gap-1 min-w-0 pr-2 text-white",
20590
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
20591
+ className: "text-3xl font-semibold truncate select-text",
20592
+ children: music.title
20593
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
20594
+ className: "text-2xl text-white/85 truncate select-text",
20595
+ children: music.author
20596
+ })]
20597
+ })]
20598
+ });
20599
+ if (previewItems.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
20600
+ className: "px-20",
20601
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20602
+ className: "relative overflow-hidden rounded-5xl shadow-large",
20551
20603
  children: [
20552
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20553
- className: "flex flex-col gap-1 items-start px-6 py-3 rounded-2xl bg-surface",
20554
- children: [
20555
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20556
- className: "flex gap-1 items-center",
20557
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heart, {
20558
- size: 28,
20559
- className: "text-like"
20560
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
20561
- className: "text-muted",
20562
- children: "获赞"
20563
- })]
20564
- }),
20565
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "w-full h-px bg-border" }),
20566
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
20567
- className: "select-text font-medium text-4xl",
20568
- children: props.data.获赞
20569
- })
20570
- ]
20604
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
20605
+ src: cover.url,
20606
+ alt: "图文封面",
20607
+ className: "object-contain w-full h-auto",
20608
+ referrerPolicy: "no-referrer",
20609
+ crossOrigin: "anonymous"
20571
20610
  }),
20572
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20573
- className: "flex flex-col gap-1 items-start px-6 py-3 rounded-2xl bg-surface",
20611
+ firstMediaBadge,
20612
+ musicBadge
20613
+ ]
20614
+ })
20615
+ });
20616
+ const stack = [{
20617
+ url: cover.url,
20618
+ filter: "none",
20619
+ shift: 0
20620
+ }, ...previewItems.map((item, idx) => ({
20621
+ url: item.url,
20622
+ filter: idx === 0 ? "brightness(0.88) saturate(0.86) contrast(0.96) blur(1px) opacity(0.8)" : "brightness(0.78) saturate(0.68) contrast(0.9) blur(3px) opacity(0.6)",
20623
+ shift: (idx + 1) * 16
20624
+ }))].filter((item) => item.url);
20625
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
20626
+ className: "px-20",
20627
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
20628
+ className: "relative overflow-visible rounded-5xl",
20629
+ children: stack.map((item, idx) => {
20630
+ return idx === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20631
+ className: "relative overflow-hidden rounded-5xl shadow-large",
20632
+ style: { zIndex: stack.length },
20574
20633
  children: [
20575
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20576
- className: "flex gap-1 items-center",
20577
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Eye, {
20578
- size: 28,
20579
- className: "text-view"
20580
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
20581
- className: "text-muted",
20582
- children: "关注"
20583
- })]
20634
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
20635
+ src: item.url,
20636
+ alt: "图文封面",
20637
+ className: "w-full h-auto block",
20638
+ referrerPolicy: "no-referrer",
20639
+ crossOrigin: "anonymous"
20584
20640
  }),
20585
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "w-full h-px bg-border" }),
20586
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
20587
- className: "select-text font-medium text-4xl",
20588
- children: props.data.关注
20589
- })
20590
- ]
20591
- }),
20592
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20593
- className: "flex flex-col gap-1 items-start px-6 py-3 rounded-2xl bg-surface",
20594
- children: [
20595
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20596
- className: "flex gap-1 items-center",
20597
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Users, {
20598
- size: 28,
20599
- className: "text-accent"
20600
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
20601
- className: "text-muted",
20602
- children: "粉丝"
20603
- })]
20641
+ totalCount > 1 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
20642
+ className: "absolute top-7 left-7 px-5 py-2 rounded-2xl bg-black/50 backdrop-blur-sm",
20643
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
20644
+ className: "text-3xl font-medium text-white select-text",
20645
+ children: [
20646
+ "共 ",
20647
+ totalCount,
20648
+ " "
20649
+ ]
20650
+ })
20604
20651
  }),
20605
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "w-full h-px bg-border" }),
20606
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
20607
- className: "select-text font-medium text-4xl",
20608
- children: props.data.粉丝
20609
- })
20652
+ firstMediaBadge,
20653
+ musicBadge
20610
20654
  ]
20611
- })
20612
- ]
20655
+ }, idx) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
20656
+ className: "absolute inset-0 overflow-hidden rounded-5xl shadow-large",
20657
+ style: {
20658
+ transform: `translate(${item.shift}px, ${item.shift * 2}px)`,
20659
+ zIndex: stack.length - idx
20660
+ },
20661
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
20662
+ src: item.url,
20663
+ alt: `预览图 ${idx + 1}`,
20664
+ className: "w-full h-full object-cover object-center",
20665
+ style: { filter: item.filter },
20666
+ referrerPolicy: "no-referrer",
20667
+ crossOrigin: "anonymous"
20668
+ })
20669
+ }, idx);
20670
+ })
20671
+ })
20672
+ });
20673
+ };
20674
+ var DouyinDynamicContent$1 = (props) => {
20675
+ const { title, desc } = props.data;
20676
+ const richTextOptions = {
20677
+ hashtag: { className: "text-[#04498d] dark:text-[#face15] font-medium" },
20678
+ mention: { className: "text-[#04498d] dark:text-[#face15] font-medium" }
20679
+ };
20680
+ const hasTitle = Boolean(title?.nodes.length);
20681
+ const hasDesc = desc.nodes.length > 0;
20682
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20683
+ className: "flex flex-col px-20 w-full leading-relaxed",
20684
+ children: [hasTitle && title && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
20685
+ className: "text-[72px] leading-tight mb-8 text-foreground select-text",
20686
+ style: {
20687
+ wordBreak: "break-word",
20688
+ overflowWrap: "break-word"
20689
+ },
20690
+ children: renderRichTextToReact(title, richTextOptions)
20691
+ }), hasDesc && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
20692
+ className: "text-[56px] tracking-[0.5px] leading-[1.7] whitespace-pre-wrap text-foreground select-text",
20693
+ style: {
20694
+ wordBreak: "break-word",
20695
+ overflowWrap: "break-word"
20696
+ },
20697
+ children: renderRichTextToReact(desc, richTextOptions)
20613
20698
  })]
20614
20699
  });
20615
20700
  };
20616
- /**
20617
- * 共创者信息组件
20618
- */
20619
- var CoCreatorsInfo$1 = ({ info }) => {
20620
- const creators = info?.co_creators ?? [];
20701
+ var DouyinDynamicStatus$1 = (props) => {
20702
+ const { dianzan, pinglun, shouchang, share, ip_location, suggest_word } = props.data;
20703
+ const renderTime = format(/* @__PURE__ */ new Date(), "yyyy-MM-dd HH:mm:ss");
20704
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20705
+ className: "flex flex-col gap-10 px-18 w-full leading-relaxed",
20706
+ children: [
20707
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
20708
+ className: "flex gap-6 items-center text-5xl tracking-normal select-text text-foreground/70",
20709
+ children: [
20710
+ {
20711
+ icon: o$3,
20712
+ value: dianzan,
20713
+ label: "点赞"
20714
+ },
20715
+ {
20716
+ icon: t,
20717
+ value: pinglun,
20718
+ label: "评论"
20719
+ },
20720
+ {
20721
+ icon: r,
20722
+ value: shouchang,
20723
+ label: "收藏"
20724
+ },
20725
+ {
20726
+ icon: e$1,
20727
+ value: share,
20728
+ label: "分享"
20729
+ }
20730
+ ].map((stat, idx) => {
20731
+ const Icon = stat.icon;
20732
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react.Fragment, { children: [idx > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "·" }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20733
+ className: "flex gap-2 items-end",
20734
+ children: [
20735
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Icon, {
20736
+ size: 50,
20737
+ weight: "fill",
20738
+ className: "mt-2"
20739
+ }),
20740
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
20741
+ className: "font-medium",
20742
+ children: stat.value
20743
+ }),
20744
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
20745
+ className: "text-3xl font-light",
20746
+ children: stat.label
20747
+ })
20748
+ ]
20749
+ })] }, stat.label);
20750
+ })
20751
+ }),
20752
+ ip_location && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20753
+ className: "flex gap-12 items-center font-light select-text text-foreground/70",
20754
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20755
+ className: "flex gap-2 items-center",
20756
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(a$1, {
20757
+ size: 50,
20758
+ weight: "fill",
20759
+ className: "mt-1"
20760
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
20761
+ className: "text-5xl font-medium",
20762
+ children: ip_location
20763
+ })]
20764
+ }), suggest_word && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20765
+ className: "flex gap-2 items-center py-3.5 px-6 bg-foreground/5 dark:bg-foreground/10 rounded-full text-4xl font-light select-text text-foreground/70",
20766
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
20767
+ className: "text-muted",
20768
+ children: suggest_word.hint_text
20769
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
20770
+ className: "text-[#04498d] dark:text-[#face15] font-medium",
20771
+ children: suggest_word.word
20772
+ })]
20773
+ })]
20774
+ }),
20775
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20776
+ className: "flex gap-3 items-center text-4xl font-light tracking-normal select-text text-foreground/70",
20777
+ children: [
20778
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Maximize, { size: 44 }),
20779
+ "图片生成于: ",
20780
+ renderTime
20781
+ ]
20782
+ })
20783
+ ]
20784
+ });
20785
+ };
20786
+ var DouyinCoCreatorList$1 = (props) => {
20787
+ const creators = props.data.cooperation_info?.co_creators ?? [];
20621
20788
  if (creators.length === 0) return null;
20622
20789
  const items = creators.slice(0, 50);
20623
20790
  const listRef = import_react.useRef(null);
@@ -20635,46 +20802,44 @@ var CoCreatorsInfo$1 = ({ info }) => {
20635
20802
  return () => window.removeEventListener("resize", calc);
20636
20803
  }, [items.length]);
20637
20804
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
20638
- className: "flex flex-col pl-16 w-full",
20805
+ className: "flex flex-col px-20 w-full",
20639
20806
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20640
20807
  ref: listRef,
20641
20808
  className: "flex overflow-hidden gap-8 py-1 pr-2 w-full",
20642
- style: { scrollbarWidth: "thin" },
20643
- children: [items.slice(0, visibleCount).map((c, idx) => {
20644
- const avatar = c.avatar_url;
20645
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20646
- className: "flex flex-col items-center min-w-38 w-38 shrink-0",
20647
- children: [
20648
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
20649
- className: "flex justify-center items-center bg-white rounded-full w-30 h-30",
20650
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
20651
- src: avatar,
20652
- alt: "共创者头像",
20653
- className: "object-cover w-28 h-auto rounded-full"
20654
- })
20655
- }),
20656
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
20657
- className: "overflow-hidden mt-6 w-full text-3xl font-medium leading-tight text-center truncate whitespace-nowrap select-text text-foreground/80",
20658
- children: c.nickname || "未提供"
20659
- }),
20660
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
20661
- className: "overflow-hidden mt-2 w-full text-3xl leading-tight text-center truncate whitespace-nowrap select-text text-foreground/70",
20662
- children: c.role_title || "未提供"
20809
+ children: [items.slice(0, visibleCount).map((c, idx) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20810
+ className: "flex flex-col items-center min-w-38 w-38 shrink-0",
20811
+ children: [
20812
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
20813
+ className: "flex justify-center items-center bg-white rounded-full w-30 h-30",
20814
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
20815
+ src: c.avatar_url,
20816
+ alt: "共创者头像",
20817
+ className: "object-cover w-28 h-28 rounded-full",
20818
+ referrerPolicy: "no-referrer",
20819
+ crossOrigin: "anonymous"
20663
20820
  })
20664
- ]
20665
- }, `${c.nickname || "creator"}-${idx}`);
20666
- }), items.length > visibleCount && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20821
+ }),
20822
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
20823
+ className: "overflow-hidden mt-6 w-full text-3xl font-medium leading-tight text-center truncate whitespace-nowrap select-text text-foreground",
20824
+ children: c.nickname || "未提供"
20825
+ }),
20826
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
20827
+ className: "overflow-hidden mt-2 w-full text-3xl leading-tight text-center truncate whitespace-nowrap select-text text-muted",
20828
+ children: c.role_title || "未提供"
20829
+ })
20830
+ ]
20831
+ }, `${c.nickname || "creator"}-${idx}`)), items.length > visibleCount && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20667
20832
  className: "flex flex-col items-center min-w-38 w-38 shrink-0",
20668
20833
  children: [
20669
20834
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
20670
- className: "flex justify-center items-center rounded-full bg-surface-secondary w-38 h-38",
20835
+ className: "flex justify-center items-center rounded-full bg-surface-secondary w-30 h-30",
20671
20836
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
20672
20837
  className: "text-[42px] leading-none text-muted",
20673
20838
  children: "···"
20674
20839
  })
20675
20840
  }),
20676
20841
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20677
- className: "overflow-hidden mt-6 w-full text-3xl font-medium leading-tight text-center truncate whitespace-nowrap select-text text-foreground/80",
20842
+ className: "overflow-hidden mt-6 w-full text-3xl font-medium leading-tight text-center truncate whitespace-nowrap select-text text-foreground",
20678
20843
  children: [
20679
20844
  "还有",
20680
20845
  items.length - visibleCount,
@@ -20682,7 +20847,7 @@ var CoCreatorsInfo$1 = ({ info }) => {
20682
20847
  ]
20683
20848
  }),
20684
20849
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
20685
- className: "overflow-hidden mt-2 w-full text-3xl leading-tight text-center truncate whitespace-nowrap select-text text-foreground/70",
20850
+ className: "overflow-hidden mt-2 w-full text-3xl leading-tight text-center truncate whitespace-nowrap select-text text-muted",
20686
20851
  children: "共创"
20687
20852
  })
20688
20853
  ]
@@ -20690,50 +20855,134 @@ var CoCreatorsInfo$1 = ({ info }) => {
20690
20855
  })
20691
20856
  });
20692
20857
  };
20693
- /**
20694
- * 抖音图文作品组件
20695
- */
20696
- var DouyinImageWork = (props) => {
20858
+ var DouyinDynamicFooter$1 = (props) => {
20859
+ const { avater_url, username, 抖音号, 获赞, 关注, 粉丝, share_url, useDarkTheme } = props.data;
20860
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20861
+ className: "flex justify-between items-start px-20 pb-20",
20862
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20863
+ className: "flex flex-col gap-12",
20864
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20865
+ className: "flex gap-12 items-start",
20866
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
20867
+ className: "relative shrink-0",
20868
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
20869
+ className: "flex justify-center items-center bg-white rounded-full w-35 h-35",
20870
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
20871
+ src: avater_url,
20872
+ alt: "头像",
20873
+ className: "rounded-full w-33 h-33 shadow-large",
20874
+ referrerPolicy: "no-referrer",
20875
+ crossOrigin: "anonymous"
20876
+ })
20877
+ })
20878
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20879
+ className: "flex flex-col gap-5",
20880
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
20881
+ className: "text-7xl font-bold select-text text-foreground",
20882
+ children: username
20883
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20884
+ className: "flex gap-2 items-center text-4xl text-muted",
20885
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Hash, { size: 32 }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
20886
+ className: "select-text",
20887
+ children: ["抖音号: ", 抖音号]
20888
+ })]
20889
+ })]
20890
+ })]
20891
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
20892
+ className: "text-3xl flex gap-6 items-center text-foreground/70",
20893
+ children: [
20894
+ {
20895
+ icon: o$3,
20896
+ iconSize: 36,
20897
+ label: "获赞",
20898
+ value: 获赞
20899
+ },
20900
+ {
20901
+ icon: o$4,
20902
+ iconSize: 36,
20903
+ label: "关注",
20904
+ value: 关注
20905
+ },
20906
+ {
20907
+ icon: r$1,
20908
+ iconSize: 36,
20909
+ label: "粉丝",
20910
+ value: 粉丝
20911
+ }
20912
+ ].map((stat) => {
20913
+ const Icon = stat.icon;
20914
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20915
+ className: "flex flex-col gap-1 items-start px-6 py-3 rounded-2xl bg-surface",
20916
+ children: [
20917
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20918
+ className: "flex gap-1 items-center",
20919
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Icon, {
20920
+ size: stat.iconSize,
20921
+ weight: "fill"
20922
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
20923
+ className: "text-muted",
20924
+ children: stat.label
20925
+ })]
20926
+ }),
20927
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "w-full h-px bg-border" }),
20928
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
20929
+ className: "select-text font-medium text-4xl",
20930
+ children: stat.value
20931
+ })
20932
+ ]
20933
+ }, stat.label);
20934
+ })
20935
+ })]
20936
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
20937
+ className: "flex flex-col items-center gap-4",
20938
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
20939
+ src: generateQRCode(share_url, useDarkTheme),
20940
+ alt: "二维码",
20941
+ className: "h-auto w-75 rounded-2xl"
20942
+ })
20943
+ })]
20944
+ });
20945
+ };
20946
+ var DouyinImageWork = import_react.memo((props) => {
20697
20947
  const coCreatorCount = props.data.cooperation_info?.co_creator_nums ?? props.data.cooperation_info?.co_creators?.length ?? void 0;
20948
+ const hasCoCreators = !!coCreatorCount && coCreatorCount > 0;
20698
20949
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DefaultLayout, {
20699
20950
  ...props,
20700
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
20701
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-15" }),
20702
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DouyinHeader$2, { useDarkTheme: props.data.useDarkTheme }),
20703
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-15" }),
20704
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CoverSection$2, { imageUrl: props.data.image_url }),
20705
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-5" }),
20706
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InfoSection$2, { ...props }),
20707
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-25" }),
20708
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20709
- className: "flex flex-col gap-10 px-0 pt-25",
20710
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20711
- className: "w-full",
20712
- children: [coCreatorCount && coCreatorCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
20713
- className: "px-16 pb-8",
20951
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20952
+ className: "p-4",
20953
+ children: [
20954
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-25" }),
20955
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DouyinAvatarUserInfo$1, { ...props }),
20956
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-15" }),
20957
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DouyinDynamicContent$1, { ...props }),
20958
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-15" }),
20959
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DouyinCoverImage, { ...props }),
20960
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: cn$1(props.data.image_list.images.length > 2 ? "h-25" : "h-20") }),
20961
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DouyinDynamicStatus$1, { ...props }),
20962
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: cn$1(hasCoCreators && "h-23", !hasCoCreators && "h-40") }),
20963
+ hasCoCreators && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
20964
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
20965
+ className: "px-20 pb-8",
20714
20966
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20715
20967
  className: "gap-2 inline-flex items-center rounded-2xl bg-surface text-foreground/80 px-6 py-3",
20716
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Users, { className: "w-7 h-7" }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
20717
- className: "text-3xl font-medium leading-none select-text text-foreground/80",
20968
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(o, {
20969
+ size: 26,
20970
+ weight: "fill"
20971
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
20972
+ className: "text-3xl font-medium leading-none select-text",
20718
20973
  children: [coCreatorCount, "人共创"]
20719
20974
  })]
20720
20975
  })
20721
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CoCreatorsInfo$1, { info: props.data.cooperation_info })]
20722
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20723
- className: "flex justify-between items-start px-20 pb-20",
20724
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(UserInfoSection$1, { ...props }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
20725
- className: "flex flex-col items-center gap-4",
20726
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
20727
- src: generateQRCode(props.data.share_url, props.data.useDarkTheme),
20728
- alt: "二维码",
20729
- className: "h-auto w-75 rounded-xl"
20730
- })
20731
- })]
20732
- })]
20733
- })
20734
- ] })
20976
+ }),
20977
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DouyinCoCreatorList$1, { ...props }),
20978
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-15" })
20979
+ ] }),
20980
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DouyinDynamicFooter$1, { ...props })
20981
+ ]
20982
+ })
20735
20983
  });
20736
- };
20984
+ });
20985
+ DouyinImageWork.displayName = "DouyinImageWork";
20737
20986
  //#endregion
20738
20987
  //#region ../template/src/components/platforms/douyin/Live.tsx
20739
20988
  var coverMaskStyle = {
@@ -20847,7 +21096,7 @@ AmbientBackground.displayName = "AmbientBackground";
20847
21096
  /**
20848
21097
  * 封面组件 - 全宽铺满 + 双向渐变溶解 + LIVE大字
20849
21098
  */
20850
- var CoverSection$1 = ({ imageUrl }) => {
21099
+ var CoverSection = ({ imageUrl }) => {
20851
21100
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20852
21101
  className: "relative",
20853
21102
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
@@ -20869,7 +21118,7 @@ var CoverSection$1 = ({ imageUrl }) => {
20869
21118
  /**
20870
21119
  * 直播信息组件
20871
21120
  */
20872
- var InfoSection$1 = ({ data }) => {
21121
+ var InfoSection = ({ data }) => {
20873
21122
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20874
21123
  className: "flex flex-col gap-8 px-16 pt-12",
20875
21124
  children: [
@@ -21082,8 +21331,8 @@ var DouyinLive = (props) => {
21082
21331
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(AmbientBackground, { pic: d.image_url }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
21083
21332
  className: "relative z-10",
21084
21333
  children: [
21085
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CoverSection$1, { imageUrl: d.image_url }),
21086
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InfoSection$1, { data: d }),
21334
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CoverSection, { imageUrl: d.image_url }),
21335
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InfoSection, { data: d }),
21087
21336
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BottomSection, { data: d })
21088
21337
  ]
21089
21338
  })]
@@ -21096,7 +21345,7 @@ var DouyinLive = (props) => {
21096
21345
  * @param props 组件属性
21097
21346
  * @returns JSX元素
21098
21347
  */
21099
- var DouyinHeader$1 = ({ useDarkTheme }) => {
21348
+ var DouyinHeader = ({ useDarkTheme }) => {
21100
21349
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
21101
21350
  className: "flex items-center px-12 py-15",
21102
21351
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
@@ -21240,7 +21489,7 @@ var DouyinMusicInfo = (props) => {
21240
21489
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DefaultLayout, {
21241
21490
  ...props,
21242
21491
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
21243
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DouyinHeader$1, { useDarkTheme: data.useDarkTheme }),
21492
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DouyinHeader, { useDarkTheme: data.useDarkTheme }),
21244
21493
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MusicCoverSection, {
21245
21494
  imageUrl: data.image_url,
21246
21495
  description: data.desc,
@@ -22118,7 +22367,7 @@ var formatCount$2 = (count) => {
22118
22367
  * 格式化视频时长显示 (如: 6:20)
22119
22368
  * @param milliseconds 毫秒数
22120
22369
  */
22121
- var formatDuration$3 = (milliseconds) => {
22370
+ var formatDuration$4 = (milliseconds) => {
22122
22371
  const seconds = Math.floor(milliseconds / 1e3);
22123
22372
  return `${Math.floor(seconds / 60)}:${(seconds % 60).toString().padStart(2, "0")}`;
22124
22373
  };
@@ -22154,7 +22403,7 @@ var VideoCard = ({ video }) => {
22154
22403
  }),
22155
22404
  video.is_video && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
22156
22405
  className: "absolute bottom-4 right-4 px-8 py-3 rounded-2xl text-4xl bg-white/50 text-black backdrop-blur-xs shadow-lg",
22157
- children: formatDuration$3(video.duration)
22406
+ children: formatDuration$4(video.duration)
22158
22407
  }),
22159
22408
  video.music && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
22160
22409
  className: "absolute bottom-4 left-4 flex items-center gap-2 px-6 py-3 rounded-2xl text-xl bg-white/50 text-black backdrop-blur-xs shadow-lg",
@@ -22368,12 +22617,12 @@ var formatNumber$1 = (num) => {
22368
22617
  if (num >= 1e4) return `${(num / 1e4).toFixed(1)}万`;
22369
22618
  return num.toLocaleString();
22370
22619
  };
22371
- var formatDuration$2 = (ms) => {
22620
+ var formatDuration$3 = (ms) => {
22372
22621
  const seconds = Math.floor(ms / 1e3);
22373
22622
  return `${Math.floor(seconds / 60)}:${(seconds % 60).toString().padStart(2, "0")}`;
22374
22623
  };
22375
22624
  var DouyinVideoInfo = import_react.memo((props) => {
22376
- const duration = (0, import_react.useMemo)(() => props.data.video ? formatDuration$2(props.data.video.duration) : null, [props.data.video]);
22625
+ const duration = (0, import_react.useMemo)(() => props.data.video ? formatDuration$3(props.data.video.duration) : null, [props.data.video]);
22377
22626
  const coverMaskStyle = (0, import_react.useMemo)(() => ({
22378
22627
  maskImage: `linear-gradient(to bottom,
22379
22628
  transparent 0%,
@@ -22604,201 +22853,271 @@ var StatItem$1 = ({ icon, value }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx
22604
22853
  DouyinVideoInfo.displayName = "DouyinVideoInfo";
22605
22854
  //#endregion
22606
22855
  //#region ../template/src/components/platforms/douyin/VideoWork.tsx
22607
- /**
22608
- * 抖音Logo头部组件
22609
- */
22610
- var DouyinHeader = ({ useDarkTheme }) => {
22611
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
22612
- className: "flex items-center px-12 py-15",
22613
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
22614
- className: "w-[39%] h-50 bg-cover bg-center bg-fixed",
22615
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
22616
- src: useDarkTheme ? "/image/douyin/dylogo-light.svg" : "/image/douyin/dylogo-dark.svg",
22617
- alt: "抖音Logo",
22618
- className: "object-contain w-full h-full"
22619
- })
22620
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
22621
- className: "text-[65px] ml-4 text-foreground/70",
22622
- children: "记录美好生活"
22623
- })]
22624
- });
22625
- };
22626
- /**
22627
- * 视频封面组件
22628
- */
22629
- var CoverSection = ({ imageUrl }) => {
22630
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
22631
- className: "flex flex-col items-center my-5",
22632
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
22633
- className: "flex flex-col items-center overflow-hidden shadow-large rounded-[25px] w-[90%] relative",
22634
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
22635
- className: "rounded-[25px] object-contain w-full h-full",
22636
- src: imageUrl,
22637
- alt: "视频封面"
22638
- })
22639
- })
22640
- });
22641
- };
22642
- /**
22643
- * 作品信息组件
22644
- */
22645
- var InfoSection = (props) => {
22646
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
22647
- className: "flex flex-col px-16 py-5",
22648
- children: [
22649
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
22650
- className: "text-[70px] font-bold leading-relaxed mb-9 text-foreground select-text",
22651
- style: {
22652
- letterSpacing: "1.5px",
22653
- wordWrap: "break-word"
22654
- },
22655
- dangerouslySetInnerHTML: { __html: props.data.desc }
22656
- }),
22657
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
22658
- className: "flex items-center gap-6 text-[45px] text-muted font-light mb-2.5 select-text",
22659
- children: [
22660
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
22661
- className: "flex gap-2 items-center",
22662
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heart, { className: "w-11 h-11 text-like" }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [props.data.dianzan, "点赞"] })]
22663
- }),
22664
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "·" }),
22665
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
22666
- className: "flex gap-2 items-center",
22667
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(MessageCircle, { className: "w-11 h-11 text-comment" }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [props.data.pinglun, "评论"] })]
22668
- }),
22669
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "·" }),
22670
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
22671
- className: "flex gap-2 items-center",
22672
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Bookmark, { className: "w-11 h-11" }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [props.data.shouchang, "收藏"] })]
22673
- }),
22674
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "·" }),
22675
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
22676
- className: "flex gap-2 items-center",
22677
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Share2, { className: "w-11 h-11 text-success" }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [props.data.share, "分享"] })]
22678
- })
22679
- ]
22680
- }),
22681
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
22682
- className: "flex items-center gap-2 text-[45px] text-muted font-light select-text",
22683
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Clock, { className: "w-11 h-11 text-time" }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: ["发布于: ", props.data.create_time] })]
22684
- }),
22685
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
22686
- className: "flex items-center gap-2 text-[45px] text-muted font-light select-text",
22687
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Maximize, { className: "w-11 h-11 text-time text-time" }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: ["图片生成于: ", format(/* @__PURE__ */ new Date(), "yyyy-MM-dd HH:mm:ss")] })]
22688
- })
22689
- ]
22856
+ function formatDuration$2(duration) {
22857
+ if (typeof duration !== "number" || !Number.isFinite(duration) || duration < 0) return void 0;
22858
+ const totalSeconds = Math.floor(duration / 1e3);
22859
+ const hours = Math.floor(totalSeconds / 3600);
22860
+ const minutes = Math.floor(totalSeconds % 3600 / 60);
22861
+ const seconds = totalSeconds % 60;
22862
+ const pad = (value) => value.toString().padStart(2, "0");
22863
+ if (hours > 0) return `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;
22864
+ return `${pad(minutes)}:${pad(seconds)}`;
22865
+ }
22866
+ var DouyinAvatarUserInfo = (props) => {
22867
+ const { avater_url, username, create_time, useDarkTheme, dynamicTYPE } = props.data;
22868
+ const subscriberRole = props.data.cooperation_info?.subscriber_role;
22869
+ const publishTime = formatDistanceToNow(fromUnixTime(create_time), {
22870
+ addSuffix: true,
22871
+ locale: zhCN
22690
22872
  });
22691
- };
22692
- /**
22693
- * 用户信息组件
22694
- */
22695
- var UserInfoSection = (props) => {
22696
22873
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
22697
- className: "flex flex-col gap-12",
22874
+ className: "flex gap-10 items-center justify-between px-0 pb-0 pl-24 pr-10",
22698
22875
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
22699
- className: "flex gap-12 items-start",
22876
+ className: "flex gap-10 items-center",
22700
22877
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
22701
- className: "relative shrink-0",
22702
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
22703
- className: "flex justify-center items-center bg-white rounded-full w-35 h-35",
22704
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
22705
- src: props.data.avater_url,
22706
- alt: "头像",
22707
- className: "rounded-full w-33 h-33 shadow-large"
22708
- })
22878
+ className: "flex justify-center items-center bg-white rounded-full w-35 h-35",
22879
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
22880
+ src: avater_url,
22881
+ alt: "头像",
22882
+ className: "rounded-full w-33 h-33 shadow-large",
22883
+ referrerPolicy: "no-referrer",
22884
+ crossOrigin: "anonymous"
22709
22885
  })
22710
22886
  }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
22711
- className: "flex flex-col gap-5",
22712
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
22713
- className: "text-7xl font-bold select-text text-foreground",
22714
- children: ["@", props.data.username]
22887
+ className: "flex flex-col gap-8 text-7xl",
22888
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
22889
+ className: "text-6xl font-bold select-text text-foreground",
22890
+ children: username
22715
22891
  }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
22716
- className: "flex gap-2 items-center text-4xl text-muted",
22892
+ className: "flex gap-2 items-center text-4xl font-normal whitespace-nowrap text-muted",
22717
22893
  children: [
22718
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Hash, { size: 32 }),
22719
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
22894
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Clock3, { size: 40 }),
22895
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
22720
22896
  className: "select-text",
22721
- children: ["抖音号: ", props.data.抖音号]
22897
+ children: publishTime
22722
22898
  }),
22723
- props.data.cooperation_info?.subscriber_role && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
22724
- className: "ml-5 px-3 py-1 rounded-xl bg-surface-secondary text-3xl",
22725
- children: props.data.cooperation_info.subscriber_role
22899
+ subscriberRole && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
22900
+ className: "ml-5 px-3 py-1 rounded-xl bg-surface-secondary text-3xl text-foreground",
22901
+ children: subscriberRole
22726
22902
  })
22727
22903
  ]
22728
22904
  })]
22729
22905
  })]
22730
22906
  }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
22731
- className: "text-3xl flex gap-6 items-center text-foreground/70",
22907
+ className: "shrink-0 flex flex-col items-end gap-2",
22908
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
22909
+ src: useDarkTheme ? "/image/douyin/dylogo-light.svg" : "/image/douyin/dylogo-dark.svg",
22910
+ alt: "抖音",
22911
+ className: "h-20 w-auto object-contain"
22912
+ }), dynamicTYPE && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
22913
+ className: "px-6 py-2 rounded-full bg-surface-secondary text-2xl font-medium text-muted select-text tracking-widest",
22914
+ children: dynamicTYPE
22915
+ })]
22916
+ })]
22917
+ });
22918
+ };
22919
+ var DouyinVideoCover = (props) => {
22920
+ const { image_url, music, duration } = props.data;
22921
+ const durationText = formatDuration$2(duration);
22922
+ const musicBadge = music && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
22923
+ className: "absolute left-7 bottom-7 z-20 flex items-center gap-4 max-w-[72%] p-3 rounded-3xl bg-black/45 backdrop-blur-2xl border border-white/20 shadow-large overflow-hidden",
22924
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
22925
+ className: "relative shrink-0 w-18 h-18",
22926
+ children: music.cover ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
22927
+ src: music.cover,
22928
+ alt: "",
22929
+ className: "absolute inset-0 w-full h-full rounded-2xl object-cover blur-md scale-110 opacity-70",
22930
+ referrerPolicy: "no-referrer",
22931
+ crossOrigin: "anonymous"
22932
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
22933
+ src: music.cover,
22934
+ alt: "BGM封面",
22935
+ className: "relative z-10 w-full h-full rounded-2xl object-cover",
22936
+ referrerPolicy: "no-referrer",
22937
+ crossOrigin: "anonymous"
22938
+ })] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
22939
+ className: "flex items-center justify-center w-full h-full rounded-2xl bg-white/15 text-white",
22940
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(e, {
22941
+ size: 36,
22942
+ weight: "fill"
22943
+ })
22944
+ })
22945
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
22946
+ className: "flex flex-col gap-1 min-w-0 pr-2 text-white",
22947
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
22948
+ className: "text-3xl font-semibold truncate select-text",
22949
+ children: music.title
22950
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
22951
+ className: "text-2xl text-white/85 truncate select-text",
22952
+ children: music.author
22953
+ })]
22954
+ })]
22955
+ });
22956
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
22957
+ className: "px-20",
22958
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
22959
+ className: "relative overflow-hidden rounded-5xl shadow-large",
22732
22960
  children: [
22733
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
22734
- className: "flex flex-col gap-1 items-start px-6 py-3 rounded-2xl bg-surface",
22735
- children: [
22736
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
22737
- className: "flex gap-1 items-center",
22738
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heart, {
22739
- size: 28,
22740
- className: "text-like"
22741
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
22742
- className: "text-muted",
22743
- children: "获赞"
22744
- })]
22745
- }),
22746
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "w-full h-px bg-border" }),
22747
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
22748
- className: "select-text font-medium text-4xl",
22749
- children: props.data.获赞
22750
- })
22751
- ]
22961
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
22962
+ src: image_url,
22963
+ alt: "视频封面",
22964
+ className: "object-contain w-full h-auto block",
22965
+ referrerPolicy: "no-referrer",
22966
+ crossOrigin: "anonymous"
22752
22967
  }),
22753
22968
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
22754
- className: "flex flex-col gap-1 items-start px-6 py-3 rounded-2xl bg-surface",
22755
- children: [
22756
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
22757
- className: "flex gap-1 items-center",
22758
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Eye, {
22759
- size: 28,
22760
- className: "text-view"
22761
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
22762
- className: "text-muted",
22763
- children: "关注"
22969
+ className: "absolute bottom-8 right-10 z-20 flex items-center justify-center text-white mix-blend-difference",
22970
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", {
22971
+ width: "0",
22972
+ height: "0",
22973
+ className: "absolute",
22974
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("filter", {
22975
+ id: "douyin-play-inner-blur",
22976
+ colorInterpolationFilters: "sRGB",
22977
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("feGaussianBlur", {
22978
+ in: "SourceGraphic",
22979
+ stdDeviation: "30",
22980
+ result: "blur"
22981
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("feComposite", {
22982
+ in: "blur",
22983
+ in2: "SourceAlpha",
22984
+ operator: "in"
22764
22985
  })]
22765
- }),
22766
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "w-full h-px bg-border" }),
22767
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
22768
- className: "select-text font-medium text-4xl",
22769
- children: props.data.关注
22770
22986
  })
22771
- ]
22987
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(a, {
22988
+ size: 150,
22989
+ weight: "fill",
22990
+ "aria-label": "播放",
22991
+ style: { filter: "url(#douyin-play-inner-blur)" }
22992
+ })]
22772
22993
  }),
22773
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
22774
- className: "flex flex-col gap-1 items-start px-6 py-3 rounded-2xl bg-surface",
22775
- children: [
22776
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
22777
- className: "flex gap-1 items-center",
22778
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Users, {
22779
- size: 28,
22780
- className: "text-accent"
22781
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
22782
- className: "text-muted",
22783
- children: "粉丝"
22784
- })]
22785
- }),
22786
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "w-full h-px bg-border" }),
22787
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
22788
- className: "select-text font-medium text-4xl",
22789
- children: props.data.粉丝
22790
- })
22791
- ]
22792
- })
22994
+ durationText && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
22995
+ className: "absolute top-7 left-7 z-20 px-5 py-2 rounded-2xl bg-black/50 backdrop-blur-sm",
22996
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
22997
+ className: "text-3xl font-medium text-white select-text",
22998
+ children: durationText
22999
+ })
23000
+ }),
23001
+ musicBadge
22793
23002
  ]
23003
+ })
23004
+ });
23005
+ };
23006
+ var DouyinDynamicContent = (props) => {
23007
+ const { title, desc } = props.data;
23008
+ const richTextOptions = {
23009
+ hashtag: { className: "text-[#04498d] dark:text-[#face15] font-medium" },
23010
+ mention: { className: "text-[#04498d] dark:text-[#face15] font-medium" }
23011
+ };
23012
+ const hasTitle = Boolean(title?.nodes.length);
23013
+ const hasDesc = desc.nodes.length > 0;
23014
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
23015
+ className: "flex flex-col px-20 w-full leading-relaxed",
23016
+ children: [hasTitle && title && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
23017
+ className: "text-[72px] leading-tight mb-8 text-foreground select-text",
23018
+ style: {
23019
+ wordBreak: "break-word",
23020
+ overflowWrap: "break-word"
23021
+ },
23022
+ children: renderRichTextToReact(title, richTextOptions)
23023
+ }), hasDesc && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
23024
+ className: "text-[56px] tracking-[0.5px] leading-[1.7] whitespace-pre-wrap text-foreground select-text",
23025
+ style: {
23026
+ wordBreak: "break-word",
23027
+ overflowWrap: "break-word"
23028
+ },
23029
+ children: renderRichTextToReact(desc, richTextOptions)
22794
23030
  })]
22795
23031
  });
22796
23032
  };
22797
- /**
22798
- * 共创者信息组件
22799
- */
22800
- var CoCreatorsInfo = ({ info, subscriberNickname }) => {
22801
- const creators = (info?.co_creators ?? []).filter((c) => !subscriberNickname || c.nickname !== subscriberNickname);
23033
+ var DouyinDynamicStatus = (props) => {
23034
+ const { dianzan, pinglun, shouchang, share, ip_location, suggest_word } = props.data;
23035
+ const renderTime = format(/* @__PURE__ */ new Date(), "yyyy-MM-dd HH:mm:ss");
23036
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
23037
+ className: "flex flex-col gap-10 px-18 w-full leading-relaxed",
23038
+ children: [
23039
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
23040
+ className: "flex gap-6 items-center text-5xl tracking-normal select-text text-foreground/70",
23041
+ children: [
23042
+ {
23043
+ icon: o$3,
23044
+ value: dianzan,
23045
+ label: "点赞"
23046
+ },
23047
+ {
23048
+ icon: t,
23049
+ value: pinglun,
23050
+ label: "评论"
23051
+ },
23052
+ {
23053
+ icon: r,
23054
+ value: shouchang,
23055
+ label: "收藏"
23056
+ },
23057
+ {
23058
+ icon: e$1,
23059
+ value: share,
23060
+ label: "分享"
23061
+ }
23062
+ ].map((stat, idx) => {
23063
+ const Icon = stat.icon;
23064
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react.Fragment, { children: [idx > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "·" }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
23065
+ className: "flex gap-2 items-end",
23066
+ children: [
23067
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Icon, {
23068
+ size: 50,
23069
+ weight: "fill",
23070
+ className: "mt-2"
23071
+ }),
23072
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
23073
+ className: "font-medium",
23074
+ children: stat.value
23075
+ }),
23076
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
23077
+ className: "text-3xl font-light",
23078
+ children: stat.label
23079
+ })
23080
+ ]
23081
+ })] }, stat.label);
23082
+ })
23083
+ }),
23084
+ ip_location && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
23085
+ className: "flex gap-12 items-center font-light select-text text-foreground/70",
23086
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
23087
+ className: "flex gap-2 items-center",
23088
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(a$1, {
23089
+ size: 50,
23090
+ weight: "fill",
23091
+ className: "mt-1"
23092
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
23093
+ className: "text-5xl font-medium",
23094
+ children: ip_location
23095
+ })]
23096
+ }), suggest_word && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
23097
+ className: "flex gap-2 items-center py-3.5 px-6 bg-foreground/5 dark:bg-foreground/10 rounded-full text-4xl font-light select-text text-foreground/70",
23098
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
23099
+ className: "text-muted",
23100
+ children: suggest_word.hint_text
23101
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
23102
+ className: "text-[#04498d] dark:text-[#face15] font-medium",
23103
+ children: suggest_word.word
23104
+ })]
23105
+ })]
23106
+ }),
23107
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
23108
+ className: "flex gap-3 items-center text-4xl font-light tracking-normal select-text text-foreground/70",
23109
+ children: [
23110
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Maximize, { size: 44 }),
23111
+ "图片生成于: ",
23112
+ renderTime
23113
+ ]
23114
+ })
23115
+ ]
23116
+ });
23117
+ };
23118
+ var DouyinCoCreatorList = (props) => {
23119
+ const subscriberNickname = props.data.username;
23120
+ const creators = (props.data.cooperation_info?.co_creators ?? []).filter((c) => c.nickname !== subscriberNickname);
22802
23121
  if (creators.length === 0) return null;
22803
23122
  const items = creators.slice(0, 50);
22804
23123
  const listRef = import_react.useRef(null);
@@ -22816,35 +23135,33 @@ var CoCreatorsInfo = ({ info, subscriberNickname }) => {
22816
23135
  return () => window.removeEventListener("resize", calc);
22817
23136
  }, [items.length]);
22818
23137
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
22819
- className: "flex flex-col pl-16 w-full",
23138
+ className: "flex flex-col px-20 w-full",
22820
23139
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
22821
23140
  ref: listRef,
22822
23141
  className: "flex overflow-hidden gap-8 py-1 pr-2 w-full",
22823
- style: { scrollbarWidth: "thin" },
22824
- children: [items.slice(0, visibleCount).map((c, idx) => {
22825
- const avatar = c.avatar_url;
22826
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
22827
- className: "flex flex-col items-center min-w-42 w-42 shrink-0",
22828
- children: [
22829
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
22830
- className: "flex justify-center items-center bg-white rounded-full w-30 h-30",
22831
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
22832
- src: avatar,
22833
- alt: "共创者头像",
22834
- className: "object-cover w-28 h-auto rounded-full"
22835
- })
22836
- }),
22837
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
22838
- className: "overflow-hidden mt-6 w-full text-3xl font-medium leading-tight text-center truncate whitespace-nowrap select-text text-foreground",
22839
- children: c.nickname || "未提供"
22840
- }),
22841
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
22842
- className: "overflow-hidden mt-2 w-full text-3xl leading-tight text-center truncate whitespace-nowrap select-text text-foreground/70",
22843
- children: c.role_title || "未提供"
23142
+ children: [items.slice(0, visibleCount).map((c, idx) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
23143
+ className: "flex flex-col items-center min-w-38 w-38 shrink-0",
23144
+ children: [
23145
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
23146
+ className: "flex justify-center items-center bg-white rounded-full w-30 h-30",
23147
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
23148
+ src: c.avatar_url,
23149
+ alt: "共创者头像",
23150
+ className: "object-cover w-28 h-28 rounded-full",
23151
+ referrerPolicy: "no-referrer",
23152
+ crossOrigin: "anonymous"
22844
23153
  })
22845
- ]
22846
- }, `${c.nickname || "creator"}-${idx}`);
22847
- }), items.length > visibleCount && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
23154
+ }),
23155
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
23156
+ className: "overflow-hidden mt-6 w-full text-3xl font-medium leading-tight text-center truncate whitespace-nowrap select-text text-foreground",
23157
+ children: c.nickname || "未提供"
23158
+ }),
23159
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
23160
+ className: "overflow-hidden mt-2 w-full text-3xl leading-tight text-center truncate whitespace-nowrap select-text text-muted",
23161
+ children: c.role_title || "未提供"
23162
+ })
23163
+ ]
23164
+ }, `${c.nickname || "creator"}-${idx}`)), items.length > visibleCount && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
22848
23165
  className: "flex flex-col items-center min-w-38 w-38 shrink-0",
22849
23166
  children: [
22850
23167
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
@@ -22855,7 +23172,7 @@ var CoCreatorsInfo = ({ info, subscriberNickname }) => {
22855
23172
  })
22856
23173
  }),
22857
23174
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
22858
- className: "overflow-hidden mt-6 w-full text-3xl font-medium leading-tight text-center truncate whitespace-nowrap select-text text-foreground/80",
23175
+ className: "overflow-hidden mt-6 w-full text-3xl font-medium leading-tight text-center truncate whitespace-nowrap select-text text-foreground",
22859
23176
  children: [
22860
23177
  "还有",
22861
23178
  items.length - visibleCount,
@@ -22863,7 +23180,7 @@ var CoCreatorsInfo = ({ info, subscriberNickname }) => {
22863
23180
  ]
22864
23181
  }),
22865
23182
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
22866
- className: "overflow-hidden mt-2 w-full text-3xl leading-tight text-center truncate whitespace-nowrap select-text text-foreground/70",
23183
+ className: "overflow-hidden mt-2 w-full text-3xl leading-tight text-center truncate whitespace-nowrap select-text text-muted",
22867
23184
  children: "共创"
22868
23185
  })
22869
23186
  ]
@@ -22871,53 +23188,134 @@ var CoCreatorsInfo = ({ info, subscriberNickname }) => {
22871
23188
  })
22872
23189
  });
22873
23190
  };
22874
- /**
22875
- * 抖音视频作品组件
22876
- */
22877
- var DouyinVideoWork = (props) => {
23191
+ var DouyinDynamicFooter = (props) => {
23192
+ const { avater_url, username, 抖音号, 获赞, 关注, 粉丝, share_url, useDarkTheme } = props.data;
23193
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
23194
+ className: "flex justify-between items-start px-20 pb-20",
23195
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
23196
+ className: "flex flex-col gap-12",
23197
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
23198
+ className: "flex gap-12 items-start",
23199
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
23200
+ className: "relative shrink-0",
23201
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
23202
+ className: "flex justify-center items-center bg-white rounded-full w-35 h-35",
23203
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
23204
+ src: avater_url,
23205
+ alt: "头像",
23206
+ className: "rounded-full w-33 h-33 shadow-large",
23207
+ referrerPolicy: "no-referrer",
23208
+ crossOrigin: "anonymous"
23209
+ })
23210
+ })
23211
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
23212
+ className: "flex flex-col gap-5",
23213
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
23214
+ className: "text-7xl font-bold select-text text-foreground",
23215
+ children: username
23216
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
23217
+ className: "flex gap-2 items-center text-4xl text-muted",
23218
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Hash, { size: 32 }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
23219
+ className: "select-text",
23220
+ children: ["抖音号: ", 抖音号]
23221
+ })]
23222
+ })]
23223
+ })]
23224
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
23225
+ className: "text-3xl flex gap-6 items-center text-foreground/70",
23226
+ children: [
23227
+ {
23228
+ icon: o$3,
23229
+ iconSize: 36,
23230
+ label: "获赞",
23231
+ value: 获赞
23232
+ },
23233
+ {
23234
+ icon: o$4,
23235
+ iconSize: 36,
23236
+ label: "关注",
23237
+ value: 关注
23238
+ },
23239
+ {
23240
+ icon: r$1,
23241
+ iconSize: 36,
23242
+ label: "粉丝",
23243
+ value: 粉丝
23244
+ }
23245
+ ].map((stat) => {
23246
+ const Icon = stat.icon;
23247
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
23248
+ className: "flex flex-col gap-1 items-start px-6 py-3 rounded-2xl bg-surface",
23249
+ children: [
23250
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
23251
+ className: "flex gap-1 items-center",
23252
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Icon, {
23253
+ size: stat.iconSize,
23254
+ weight: "fill"
23255
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
23256
+ className: "text-muted",
23257
+ children: stat.label
23258
+ })]
23259
+ }),
23260
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "w-full h-px bg-border" }),
23261
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
23262
+ className: "select-text font-medium text-4xl",
23263
+ children: stat.value
23264
+ })
23265
+ ]
23266
+ }, stat.label);
23267
+ })
23268
+ })]
23269
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
23270
+ className: "flex flex-col items-center gap-4",
23271
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
23272
+ src: generateQRCode(share_url, useDarkTheme),
23273
+ alt: "二维码",
23274
+ className: "h-auto w-75 rounded-2xl"
23275
+ })
23276
+ })]
23277
+ });
23278
+ };
23279
+ var DouyinVideoWork = import_react.memo((props) => {
22878
23280
  const coCreatorCount = props.data.cooperation_info?.co_creator_nums ?? props.data.cooperation_info?.co_creators?.length ?? void 0;
23281
+ const hasCoCreators = !!coCreatorCount && coCreatorCount > 0;
22879
23282
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DefaultLayout, {
22880
23283
  ...props,
22881
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
22882
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-15" }),
22883
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DouyinHeader, { useDarkTheme: props.data.useDarkTheme }),
22884
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-15" }),
22885
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CoverSection, { imageUrl: props.data.image_url }),
22886
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-5" }),
22887
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InfoSection, { ...props }),
22888
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-25" }),
22889
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
22890
- className: "flex flex-col gap-10 px-0 pt-25",
22891
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
22892
- className: "w-full",
22893
- children: [coCreatorCount && coCreatorCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
22894
- className: "px-16 pb-8",
23284
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
23285
+ className: "p-4",
23286
+ children: [
23287
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-25" }),
23288
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DouyinAvatarUserInfo, { ...props }),
23289
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-15" }),
23290
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DouyinDynamicContent, { ...props }),
23291
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-15" }),
23292
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DouyinVideoCover, { ...props }),
23293
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-20" }),
23294
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DouyinDynamicStatus, { ...props }),
23295
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: cn$1(hasCoCreators && "h-23", !hasCoCreators && "h-40") }),
23296
+ hasCoCreators && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
23297
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
23298
+ className: "px-20 pb-8",
22895
23299
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
22896
23300
  className: "gap-2 inline-flex items-center rounded-2xl bg-surface text-foreground/80 px-6 py-3",
22897
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Users, { className: "w-7 h-7" }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
22898
- className: "text-3xl font-medium leading-none select-text text-foreground/80",
23301
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(o, {
23302
+ size: 26,
23303
+ weight: "fill"
23304
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
23305
+ className: "text-3xl font-medium leading-none select-text",
22899
23306
  children: [coCreatorCount, "人共创"]
22900
23307
  })]
22901
23308
  })
22902
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CoCreatorsInfo, {
22903
- info: props.data.cooperation_info,
22904
- subscriberNickname: props.data.username
22905
- })]
22906
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
22907
- className: "flex justify-between items-start px-20 pb-20",
22908
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(UserInfoSection, { ...props }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
22909
- className: "flex flex-col items-center gap-4",
22910
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
22911
- src: generateQRCode(props.data.share_url, props.data.useDarkTheme),
22912
- alt: "二维码",
22913
- className: "h-auto w-75 rounded-xl"
22914
- })
22915
- })]
22916
- })]
22917
- })
22918
- ] })
23309
+ }),
23310
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DouyinCoCreatorList, { ...props }),
23311
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-15" })
23312
+ ] }),
23313
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DouyinDynamicFooter, { ...props })
23314
+ ]
23315
+ })
22919
23316
  });
22920
- };
23317
+ });
23318
+ DouyinVideoWork.displayName = "DouyinVideoWork";
22921
23319
  //#endregion
22922
23320
  //#region ../template/src/components/platforms/kuaishou/Comment.tsx
22923
23321
  var kuaishouMentionClassName = "text-[#03488d] dark:text-[#c7daef]";
@@ -27323,7 +27721,7 @@ var VersionWarning = (props) => {
27323
27721
  })
27324
27722
  }),
27325
27723
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Puzzle, {
27326
- className: cn("w-10 h-auto"),
27724
+ className: cn$1("w-10 h-auto"),
27327
27725
  style: { color: mutedColor }
27328
27726
  }),
27329
27727
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
@@ -34679,6 +35077,7 @@ var wrapWithErrorHandler = (fn, options) => {
34679
35077
  return async (e, next) => {
34680
35078
  const rawEvent = e;
34681
35079
  const normalizedEvent = await injectBotToEventForPushTask(rawEvent, options.businessName);
35080
+ const normalizedNext = next ?? (() => void 0);
34682
35081
  const emojiManager = Boolean(rawEvent) && !isPushTask(rawEvent, options.businessName) ? new EmojiReactionManager(rawEvent) : void 0;
34683
35082
  let processingTimer = null;
34684
35083
  let successTimer = null;
@@ -34688,7 +35087,7 @@ var wrapWithErrorHandler = (fn, options) => {
34688
35087
  emojiManager.add("PROCESSING").catch(() => {});
34689
35088
  }, 1500);
34690
35089
  }
34691
- const ctx = logger.runContext(async () => fn(normalizedEvent, next));
35090
+ const ctx = logger.runContext(async () => fn(normalizedEvent, normalizedNext));
34692
35091
  try {
34693
35092
  const result = await ctx.run();
34694
35093
  if (emojiManager) successTimer = setTimeout(() => {
@@ -38493,7 +38892,7 @@ var extractSearchTokens = (textExtra, text) => {
38493
38892
  * 抖音评论正文里通常只保留 `@昵称` 文本,稳定用户 ID 在 `text_extra` 里。
38494
38893
  * 这里先把 ID 转成 `@昵称 + userId`,后续解析时才能把普通文本切成 mention 节点。
38495
38894
  */
38496
- var resolveMentionTokens = async (userIds) => {
38895
+ var resolveMentionTokens$1 = async (userIds) => {
38497
38896
  if (!userIds || userIds.length === 0) return [];
38498
38897
  const uniqueUserIds = [...new Set(userIds)];
38499
38898
  return (await Promise.all(uniqueUserIds.map(async (secUid) => {
@@ -38523,7 +38922,7 @@ var resolveMentionTokens = async (userIds) => {
38523
38922
  * - @ 用户转成 mention 节点,template 侧只负责套样式。
38524
38923
  */
38525
38924
  var buildDouyinRichText = async (text, emojiData, mentionUserIds, searchTokens = []) => {
38526
- const mentionTokens = await resolveMentionTokens(mentionUserIds);
38925
+ const mentionTokens = await resolveMentionTokens$1(mentionUserIds);
38527
38926
  const emojiTokens = emojiData.filter((item) => Boolean(item?.name) && Boolean(item?.url)).sort((a, b) => b.name.length - a.name.length);
38528
38927
  const nodes = [];
38529
38928
  let buffer = "";
@@ -40204,168 +40603,665 @@ async function processFavoriteList(contentList, sec_uid, userinfo, item, targets
40204
40603
  return result;
40205
40604
  }
40206
40605
  //#endregion
40207
- //#region src/platform/douyin/push/live.ts
40606
+ //#region src/platform/douyin/push/live.ts
40607
+ /**
40608
+ * 处理直播推送
40609
+ * 检测用户是否开播,如果开播则推送
40610
+ * @returns 返回需要推送的直播项(如果有)
40611
+ */
40612
+ async function processLiveStream(sec_uid, userinfo, item, targets, amagi) {
40613
+ const pushType = "live";
40614
+ const liveStatus = await douyinDBInstance.getLiveStatus(sec_uid);
40615
+ if (userinfo.data.user.live_status === 1) {
40616
+ const UserInfoData = await amagi.douyin.fetcher.fetchUserProfile({
40617
+ sec_uid: userinfo.data.user.sec_uid,
40618
+ typeMode: "strict"
40619
+ });
40620
+ if (!UserInfoData.data.user?.live_status || UserInfoData.data.user.live_status !== 1) {
40621
+ logger.error((UserInfoData?.data?.user?.nickname ?? "用户") + "当前未在直播");
40622
+ return null;
40623
+ }
40624
+ if (!UserInfoData.data.user.room_data) {
40625
+ logger.error("未获取到直播间信息!");
40626
+ return null;
40627
+ }
40628
+ const room_data = JSON.parse(UserInfoData.data.user.room_data);
40629
+ const liveInfo = await amagi.douyin.fetcher.fetchLiveRoomInfo({
40630
+ room_id: UserInfoData.data.user.room_id_str,
40631
+ web_rid: room_data.owner.web_rid,
40632
+ typeMode: "strict"
40633
+ });
40634
+ if (!liveStatus.living) {
40635
+ logger.info(`用户 ${item.remark ?? sec_uid} 开播了`);
40636
+ return {
40637
+ remark: item.remark,
40638
+ sec_uid,
40639
+ create_time: Date.now(),
40640
+ targets,
40641
+ pushType,
40642
+ Detail_Data: {
40643
+ user_info: userinfo,
40644
+ room_data: JSON.parse(userinfo.data.user.room_data),
40645
+ live_data: liveInfo,
40646
+ liveStatus: {
40647
+ liveStatus: "open",
40648
+ isChanged: true,
40649
+ isliving: true
40650
+ }
40651
+ },
40652
+ avatar_img: "https://p3-pc.douyinpic.com/aweme/1080x1080/" + userinfo.data.user.avatar_larger.uri,
40653
+ living: true
40654
+ };
40655
+ }
40656
+ } else if (liveStatus.living) {
40657
+ await douyinDBInstance.updateLiveStatus(sec_uid, false);
40658
+ logger.info(`用户 ${item.remark ?? sec_uid} 已关播,更新直播状态`);
40659
+ }
40660
+ return null;
40661
+ }
40662
+ //#endregion
40663
+ //#region src/platform/douyin/push/post.ts
40664
+ /**
40665
+ * 处理作品列表推送
40666
+ * 按照作品发布时间进行过滤,只推送24小时内的作品
40667
+ * @returns 返回需要推送的作品项数组
40668
+ */
40669
+ async function processPostList(contentList, sec_uid, userinfo, item, targets) {
40670
+ const pushType = "post";
40671
+ const listName = "作品列表";
40672
+ const result = [];
40673
+ for (const aweme of contentList) {
40674
+ const nowSeconds = Math.floor(Date.now() / 1e3);
40675
+ const createTime = aweme.create_time;
40676
+ const timeDifference = nowSeconds - createTime;
40677
+ const is_top = aweme.is_top === 1;
40678
+ const timeDiffHours = Math.round(timeDifference / 3600 * 100) / 100;
40679
+ logger.trace(`
40680
+ 前期获取该作品基本信息:
40681
+ 推送类型:${pushType}(${listName})
40682
+ 作者:${aweme.author.nickname}
40683
+ 作品ID:${aweme.aweme_id}
40684
+ 发布时间:${format(fromUnixTime(aweme.create_time), "yyyy-MM-dd HH:mm")}
40685
+ 发布时间戳(s):${createTime}
40686
+ 当前时间戳(s):${nowSeconds}
40687
+ 时间差(s):${timeDifference}s (${timeDiffHours}h)
40688
+ 是否置顶:${is_top}
40689
+ 是否在一天内:${timeDifference < 86400 ? logger.green("true") : logger.red("false")}
40690
+ `);
40691
+ if (is_top && timeDifference < 86400 || timeDifference < 86400 && !is_top) {
40692
+ const validTargets = [];
40693
+ for (const target of targets) if (!await douyinDBInstance.isAwemePushed(aweme.aweme_id, sec_uid, target.groupId, pushType)) validTargets.push(target);
40694
+ if (validTargets.length > 0) result.push({
40695
+ remark: item.remark,
40696
+ sec_uid,
40697
+ create_time: aweme.create_time,
40698
+ targets: validTargets,
40699
+ pushType,
40700
+ Detail_Data: {
40701
+ ...aweme,
40702
+ user_info: userinfo
40703
+ },
40704
+ avatar_img: "https://p3-pc.douyinpic.com/aweme/1080x1080/" + userinfo.data.user.avatar_larger.uri,
40705
+ living: false
40706
+ });
40707
+ }
40708
+ }
40709
+ return result;
40710
+ }
40711
+ //#endregion
40712
+ //#region src/platform/douyin/push/recommend.ts
40713
+ /**
40714
+ * 处理推荐列表推送
40715
+ * 通过对比aweme_id判断是否有新增的推荐作品
40716
+ * @returns 返回需要推送的作品项数组
40717
+ */
40718
+ async function processRecommendList(contentList, sec_uid, userinfo, item, targets, force = false) {
40719
+ const pushType = "recommend";
40720
+ const listName = "推荐列表";
40721
+ const result = [];
40722
+ const groupHistoryStatus = /* @__PURE__ */ new Map();
40723
+ for (const target of targets) {
40724
+ const hasHistory = await douyinDBInstance.hasHistory(sec_uid, target.groupId, pushType);
40725
+ groupHistoryStatus.set(target.groupId, hasHistory);
40726
+ }
40727
+ for (const [index, aweme] of contentList.entries()) {
40728
+ const validTargets = [];
40729
+ for (const target of targets) if (!await douyinDBInstance.isAwemePushed(aweme.aweme_id, sec_uid, target.groupId, pushType)) {
40730
+ const hasHistory = groupHistoryStatus.get(target.groupId);
40731
+ if (force || hasHistory || index === 0) validTargets.push(target);
40732
+ else {
40733
+ await douyinDBInstance.addAwemeCache(aweme.aweme_id, sec_uid, target.groupId, pushType);
40734
+ logger.debug(`新订阅群组 ${target.groupId} 跳过旧作品 ${aweme.aweme_id} 并已标记为已读`);
40735
+ }
40736
+ }
40737
+ if (validTargets.length === 0) continue;
40738
+ let authorUserInfo;
40739
+ try {
40740
+ if (aweme.author?.sec_uid) {
40741
+ authorUserInfo = await douyinFetcher.fetchUserProfile({
40742
+ sec_uid: aweme.author.sec_uid,
40743
+ typeMode: "strict"
40744
+ });
40745
+ logger.debug(`获取作品作者 ${aweme.author.nickname} 的用户信息成功`);
40746
+ }
40747
+ } catch (error) {
40748
+ logger.warn(`获取作品作者用户信息失败: ${error}`);
40749
+ }
40750
+ result.push({
40751
+ remark: item.remark,
40752
+ sec_uid,
40753
+ create_time: aweme.create_time,
40754
+ targets: validTargets,
40755
+ pushType,
40756
+ Detail_Data: {
40757
+ ...aweme,
40758
+ user_info: userinfo,
40759
+ author_user_info: authorUserInfo
40760
+ },
40761
+ avatar_img: "https://p3-pc.douyinpic.com/aweme/1080x1080/" + userinfo.data.user.avatar_larger.uri,
40762
+ living: false
40763
+ });
40764
+ logger.debug(`发现新${listName}作品:${aweme.aweme_id}`);
40765
+ }
40766
+ await douyinDBInstance.updateListSnapshot(sec_uid, pushType, contentList.map((a) => a.aweme_id));
40767
+ return result;
40768
+ }
40769
+ //#endregion
40770
+ //#region src/platform/douyin/push/render.ts
40208
40771
  /**
40209
- * 处理直播推送
40210
- * 检测用户是否开播,如果开播则推送
40211
- * @returns 返回需要推送的直播项(如果有)
40772
+ * 处理作品描述
40773
+ * @param Desc - 作品原始描述文本
40774
+ * @returns 如果描述为空则返回默认提示,否则返回原文
40212
40775
  */
40213
- async function processLiveStream(sec_uid, userinfo, item, targets, amagi) {
40214
- const pushType = "live";
40215
- const liveStatus = await douyinDBInstance.getLiveStatus(sec_uid);
40216
- if (userinfo.data.user.live_status === 1) {
40217
- const UserInfoData = await amagi.douyin.fetcher.fetchUserProfile({
40218
- sec_uid: userinfo.data.user.sec_uid,
40219
- typeMode: "strict"
40220
- });
40221
- if (!UserInfoData.data.user?.live_status || UserInfoData.data.user.live_status !== 1) {
40222
- logger.error((UserInfoData?.data?.user?.nickname ?? "用户") + "当前未在直播");
40223
- return null;
40224
- }
40225
- if (!UserInfoData.data.user.room_data) {
40226
- logger.error("未获取到直播间信息!");
40227
- return null;
40228
- }
40229
- const room_data = JSON.parse(UserInfoData.data.user.room_data);
40230
- const liveInfo = await amagi.douyin.fetcher.fetchLiveRoomInfo({
40231
- room_id: UserInfoData.data.user.room_id_str,
40232
- web_rid: room_data.owner.web_rid,
40233
- typeMode: "strict"
40234
- });
40235
- if (!liveStatus.living) {
40236
- logger.info(`用户 ${item.remark ?? sec_uid} 开播了`);
40237
- return {
40238
- remark: item.remark,
40239
- sec_uid,
40240
- create_time: Date.now(),
40241
- targets,
40242
- pushType,
40243
- Detail_Data: {
40244
- user_info: userinfo,
40245
- room_data: JSON.parse(userinfo.data.user.room_data),
40246
- live_data: liveInfo,
40247
- liveStatus: {
40248
- liveStatus: "open",
40249
- isChanged: true,
40250
- isliving: true
40251
- }
40252
- },
40253
- avatar_img: "https://p3-pc.douyinpic.com/aweme/1080x1080/" + userinfo.data.user.avatar_larger.uri,
40254
- living: true
40255
- };
40256
- }
40257
- } else if (liveStatus.living) {
40258
- await douyinDBInstance.updateLiveStatus(sec_uid, false);
40259
- logger.info(`用户 ${item.remark ?? sec_uid} 已关播,更新直播状态`);
40260
- }
40261
- return null;
40776
+ function desc(Desc) {
40777
+ return Desc === "" ? "该作品没有描述" : Desc;
40262
40778
  }
40263
- //#endregion
40264
- //#region src/platform/douyin/push/post.ts
40265
40779
  /**
40266
- * 处理作品列表推送
40267
- * 按照作品发布时间进行过滤,只推送24小时内的作品
40268
- * @returns 返回需要推送的作品项数组
40780
+ * 构建合作信息数据
40781
+ * 从作品详情中提取创作者合作信息,包括合作者列表和订阅者角色
40782
+ * @param Detail_Data - 作品详情数据,包含 cooperation_info、user_info、author 等字段
40783
+ * @returns 合作信息对象,如果不存在则返回 undefined
40784
+ */
40785
+ function buildCooperationInfo(Detail_Data) {
40786
+ const raw = Detail_Data.cooperation_info;
40787
+ if (!raw) return void 0;
40788
+ const rawCreators = Array.isArray(raw.co_creators) ? raw.co_creators : [];
40789
+ const subscriberUid = Detail_Data.user_info.data.user.uid;
40790
+ const subscriberSecUid = Detail_Data.user_info.data.user.sec_uid;
40791
+ const subscriberInCreators = rawCreators.find((c) => subscriberUid && c.uid && c.uid === subscriberUid || subscriberSecUid && c.sec_uid && c.sec_uid === subscriberSecUid);
40792
+ const co_creators = rawCreators.map((c) => {
40793
+ return {
40794
+ avatar_url: c.avatar_thumb?.url_list?.[0] ?? (c.avatar_thumb?.uri ? `https://p3.douyinpic.com/${c.avatar_thumb.uri}` : void 0),
40795
+ nickname: c.nickname,
40796
+ role_title: c.role_title
40797
+ };
40798
+ });
40799
+ if (Detail_Data.author && !rawCreators.some((c) => Detail_Data.author?.uid && c.uid && c.uid === Detail_Data.author.uid || Detail_Data.author?.sec_uid && c.sec_uid && c.sec_uid === Detail_Data.author.sec_uid || Detail_Data.author?.nickname && c.nickname && c.nickname === Detail_Data.author.nickname)) co_creators.unshift({
40800
+ avatar_url: Detail_Data.author.avatar_thumb?.url_list?.[0] ?? (Detail_Data.author.avatar_thumb?.uri ? `https://p3.douyinpic.com/${Detail_Data.author.avatar_thumb.uri}` : void 0),
40801
+ nickname: Detail_Data.author.nickname,
40802
+ role_title: "作者"
40803
+ });
40804
+ return {
40805
+ co_creator_nums: Math.max(Number(raw.co_creator_nums || 0), co_creators.length),
40806
+ co_creators,
40807
+ subscriber_role: subscriberInCreators?.role_title ?? (subscriberUid && Detail_Data.author?.uid && subscriberUid === Detail_Data.author.uid || subscriberSecUid && Detail_Data.author?.sec_uid && subscriberSecUid === Detail_Data.author.sec_uid || Detail_Data.user_info.data.user.nickname && Detail_Data.author?.nickname && Detail_Data.user_info.data.user.nickname === Detail_Data.author.nickname ? "作者" : void 0)
40808
+ };
40809
+ }
40810
+ /**
40811
+ * 构建 Douyin CDN 头像 URL
40812
+ * @param uri - 头像资源的 URI 标识
40813
+ * @returns 完整的 1080x1080 分辨率头像 CDN 地址
40269
40814
  */
40270
- async function processPostList(contentList, sec_uid, userinfo, item, targets) {
40271
- const pushType = "post";
40272
- const listName = "作品列表";
40273
- const result = [];
40274
- for (const aweme of contentList) {
40275
- const nowSeconds = Math.floor(Date.now() / 1e3);
40276
- const createTime = aweme.create_time;
40277
- const timeDifference = nowSeconds - createTime;
40278
- const is_top = aweme.is_top === 1;
40279
- const timeDiffHours = Math.round(timeDifference / 3600 * 100) / 100;
40280
- logger.trace(`
40281
- 前期获取该作品基本信息:
40282
- 推送类型:${pushType}(${listName})
40283
- 作者:${aweme.author.nickname}
40284
- 作品ID:${aweme.aweme_id}
40285
- 发布时间:${format(fromUnixTime(aweme.create_time), "yyyy-MM-dd HH:mm")}
40286
- 发布时间戳(s):${createTime}
40287
- 当前时间戳(s):${nowSeconds}
40288
- 时间差(s):${timeDifference}s (${timeDiffHours}h)
40289
- 是否置顶:${is_top}
40290
- 是否在一天内:${timeDifference < 86400 ? logger.green("true") : logger.red("false")}
40291
- `);
40292
- if (is_top && timeDifference < 86400 || timeDifference < 86400 && !is_top) {
40293
- const validTargets = [];
40294
- for (const target of targets) if (!await douyinDBInstance.isAwemePushed(aweme.aweme_id, sec_uid, target.groupId, pushType)) validTargets.push(target);
40295
- if (validTargets.length > 0) result.push({
40296
- remark: item.remark,
40297
- sec_uid,
40298
- create_time: aweme.create_time,
40299
- targets: validTargets,
40300
- pushType,
40301
- Detail_Data: {
40302
- ...aweme,
40303
- user_info: userinfo
40304
- },
40305
- avatar_img: "https://p3-pc.douyinpic.com/aweme/1080x1080/" + userinfo.data.user.avatar_larger.uri,
40306
- living: false
40307
- });
40308
- }
40815
+ function cdnAvatar(uri) {
40816
+ return "https://p3-pc.douyinpic.com/aweme/1080x1080/" + uri;
40817
+ }
40818
+ /**
40819
+ * 解析图文/合辑中单张图片的媒体类型。
40820
+ * clip_type 规则参考普通解析逻辑:2/空为静态图,5 为实况动图,4 为短片。
40821
+ * @param image - 抖音 images 数组中的单项
40822
+ * @returns 模板可识别的媒体类型
40823
+ */
40824
+ function getImageMediaType(image) {
40825
+ switch (image?.clip_type) {
40826
+ case 4: return "clip";
40827
+ case 5: return "live";
40828
+ case 2:
40829
+ case void 0:
40830
+ default: return "static";
40309
40831
  }
40310
- return result;
40311
40832
  }
40312
- //#endregion
40313
- //#region src/platform/douyin/push/recommend.ts
40314
40833
  /**
40315
- * 处理推荐列表推送
40316
- * 通过对比aweme_id判断是否有新增的推荐作品
40317
- * @returns 返回需要推送的作品项数组
40834
+ * 构建图文作品图片列表。
40835
+ * 第一项为封面,后续最多保留 2 张预览图,并在每项上携带媒体类型。
40836
+ * @param images - 作品原始图片数组,每项包含 url_list(多分辨率 URL)
40837
+ * @param fallbackCover - images 缺失时使用的兜底封面
40838
+ * @returns 图片列表数据
40839
+ */
40840
+ function buildImageList(images, fallbackCover) {
40841
+ if (!images || images.length === 0) return {
40842
+ images: fallbackCover ? [{
40843
+ url: fallbackCover,
40844
+ media_type: "static"
40845
+ }] : [],
40846
+ total_count: fallbackCover ? 1 : 0
40847
+ };
40848
+ const usedUrls = /* @__PURE__ */ new Set();
40849
+ return {
40850
+ images: images.map((img, index) => ({
40851
+ url: index === 0 ? img.url_list[2] ?? img.url_list[1] ?? img.url_list[0] ?? fallbackCover : img.url_list[1] ?? img.url_list[0] ?? img.url_list[2] ?? "",
40852
+ media_type: getImageMediaType(img)
40853
+ })).filter((item) => {
40854
+ if (!item.url) return false;
40855
+ const key = normalizeImageUrl(item.url);
40856
+ if (usedUrls.has(key)) return false;
40857
+ usedUrls.add(key);
40858
+ return true;
40859
+ }).slice(0, 3),
40860
+ total_count: images.length
40861
+ };
40862
+ }
40863
+ /**
40864
+ * 去掉签名参数,避免同一张图因 CDN 查询参数不同被重复放入预览列表。
40865
+ * @param url - 原始图片 URL
40866
+ * @returns 用于去重的稳定 URL key
40318
40867
  */
40319
- async function processRecommendList(contentList, sec_uid, userinfo, item, targets, force = false) {
40320
- const pushType = "recommend";
40321
- const listName = "推荐列表";
40322
- const result = [];
40323
- const groupHistoryStatus = /* @__PURE__ */ new Map();
40324
- for (const target of targets) {
40325
- const hasHistory = await douyinDBInstance.hasHistory(sec_uid, target.groupId, pushType);
40326
- groupHistoryStatus.set(target.groupId, hasHistory);
40868
+ function normalizeImageUrl(url) {
40869
+ try {
40870
+ const parsed = new URL(url);
40871
+ return `${parsed.host}${parsed.pathname}`;
40872
+ } catch {
40873
+ return url.split("?")[0];
40327
40874
  }
40328
- for (const [index, aweme] of contentList.entries()) {
40329
- const validTargets = [];
40330
- for (const target of targets) if (!await douyinDBInstance.isAwemePushed(aweme.aweme_id, sec_uid, target.groupId, pushType)) {
40331
- const hasHistory = groupHistoryStatus.get(target.groupId);
40332
- if (force || hasHistory || index === 0) validTargets.push(target);
40333
- else {
40334
- await douyinDBInstance.addAwemeCache(aweme.aweme_id, sec_uid, target.groupId, pushType);
40335
- logger.debug(`新订阅群组 ${target.groupId} 跳过旧作品 ${aweme.aweme_id} 并已标记为已读`);
40336
- }
40337
- }
40338
- if (validTargets.length === 0) continue;
40339
- let authorUserInfo;
40875
+ }
40876
+ /**
40877
+ * 将作品描述按首句句号/感叹号/问号拆分为标题和正文
40878
+ * @param desc - 原始描述文本
40879
+ * @returns `{ title, body }`,若无句点分隔符则 title 为空字符串
40880
+ */
40881
+ function splitTitleAndBody(desc) {
40882
+ const match = desc.match(/^[^。!?!?\n]*[。!?!?]/);
40883
+ if (!match) return {
40884
+ title: "",
40885
+ body: desc
40886
+ };
40887
+ return {
40888
+ title: match[0].replace(/[。!?!?]$/, ""),
40889
+ body: desc.slice(match[0].length)
40890
+ };
40891
+ }
40892
+ /**
40893
+ * 根据抖音作品描述和 text_extra 构建富文本文档
40894
+ * 普通正文走 text 节点,换行走 lineBreak 节点,hashtag 与有效 @ 用户走高亮节点。
40895
+ * @param body - 需要编排的文本片段
40896
+ * @param textExtra - 抖音作品 text_extra 数组
40897
+ * @param titleOffset - 当前片段在原始 desc 中的起始偏移字符数
40898
+ * @param mentionCache - 本次渲染内复用的 @ 校验结果,避免重复请求同一个用户主页
40899
+ * @returns 构建好的 RichTextDocument
40900
+ */
40901
+ async function buildDescRichText(text, textExtra, titleOffset = 0, mentionCache = /* @__PURE__ */ new Map()) {
40902
+ if (!text) return createRichTextDocument([], { platform: "douyin" });
40903
+ const tokens = [...extractHashtagTokens(text, textExtra, titleOffset), ...(await resolveMentionTokens(text, textExtra, titleOffset, mentionCache)).map((item) => ({
40904
+ start: item.start,
40905
+ end: item.end,
40906
+ kind: "mention",
40907
+ text: item.text,
40908
+ userId: item.userId
40909
+ }))].sort((a, b) => a.start - b.start || b.end - b.start - (a.end - a.start));
40910
+ const nodes = [];
40911
+ let cursor = 0;
40912
+ for (const token of tokens) {
40913
+ if (token.start < cursor) continue;
40914
+ appendTextSegments(text.slice(cursor, token.start), nodes);
40915
+ if (token.kind === "hashtag") nodes.push(createHashtagNode(token.text));
40916
+ else nodes.push(createMentionNode(token.text, token.userId));
40917
+ cursor = token.end;
40918
+ }
40919
+ appendTextSegments(text.slice(cursor), nodes);
40920
+ return createRichTextDocument(nodes, { platform: "douyin" });
40921
+ }
40922
+ function extractHashtagTokens(body, textExtra, titleOffset = 0) {
40923
+ return (textExtra ?? []).filter((item) => item.type === 1 && !!item.hashtag_name && typeof item.start === "number" && typeof item.end === "number").map((item) => ({
40924
+ start: item.start - titleOffset,
40925
+ end: item.end - titleOffset,
40926
+ kind: "hashtag",
40927
+ text: "#" + item.hashtag_name
40928
+ })).filter((item) => item.start >= 0 && item.end > item.start && item.end <= body.length).filter((item) => body.slice(item.start, item.end) === item.text);
40929
+ }
40930
+ /**
40931
+ * 根据 text_extra 中的 sec_uid 反查当前昵称,并只在原文片段完全等于 @昵称 时生成 mention。
40932
+ * 这样可以过滤掉失效、改名或 text_extra 范围异常的 @。
40933
+ */
40934
+ async function resolveMentionTokens(text, textExtra, titleOffset, mentionCache) {
40935
+ const candidates = (textExtra ?? []).filter((item) => item.type === 0 && typeof item.start === "number" && typeof item.end === "number" && typeof item.sec_uid === "string" && item.sec_uid.length > 0).map((item) => ({
40936
+ start: item.start - titleOffset,
40937
+ end: item.end - titleOffset,
40938
+ sec_uid: item.sec_uid
40939
+ })).filter((item) => item.start >= 0 && item.end > item.start && item.end <= text.length);
40940
+ if (candidates.length === 0) return [];
40941
+ const uniqueSecUids = [...new Set(candidates.map((item) => item.sec_uid))];
40942
+ await Promise.all(uniqueSecUids.map(async (secUid) => {
40943
+ if (mentionCache.has(secUid)) return;
40340
40944
  try {
40341
- if (aweme.author?.sec_uid) {
40342
- authorUserInfo = await douyinFetcher.fetchUserProfile({
40343
- sec_uid: aweme.author.sec_uid,
40344
- typeMode: "strict"
40345
- });
40346
- logger.debug(`获取作品作者 ${aweme.author.nickname} 的用户信息成功`);
40347
- }
40348
- } catch (error) {
40349
- logger.warn(`获取作品作者用户信息失败: ${error}`);
40945
+ const user = (await douyinFetcher.fetchUserProfile({
40946
+ sec_uid: secUid,
40947
+ typeMode: "strict"
40948
+ })).data.user;
40949
+ const nickname = user.nickname?.trim();
40950
+ mentionCache.set(secUid, user.sec_uid === secUid && nickname ? `@${nickname}` : null);
40951
+ } catch {
40952
+ mentionCache.set(secUid, null);
40350
40953
  }
40351
- result.push({
40352
- remark: item.remark,
40353
- sec_uid,
40354
- create_time: aweme.create_time,
40355
- targets: validTargets,
40356
- pushType,
40357
- Detail_Data: {
40358
- ...aweme,
40359
- user_info: userinfo,
40360
- author_user_info: authorUserInfo
40361
- },
40362
- avatar_img: "https://p3-pc.douyinpic.com/aweme/1080x1080/" + userinfo.data.user.avatar_larger.uri,
40363
- living: false
40364
- });
40365
- logger.debug(`发现新${listName}作品:${aweme.aweme_id}`);
40954
+ }));
40955
+ return candidates.flatMap((item) => {
40956
+ const mentionText = mentionCache.get(item.sec_uid);
40957
+ if (!mentionText) return [];
40958
+ if (text.slice(item.start, item.end) !== mentionText) return [];
40959
+ return [{
40960
+ start: item.start,
40961
+ end: item.end,
40962
+ text: mentionText,
40963
+ userId: item.sec_uid
40964
+ }];
40965
+ });
40966
+ }
40967
+ /**
40968
+ * 将文本按换行拆分为 text 节点和 lineBreak 节点并推入目标数组
40969
+ */
40970
+ function appendTextSegments(text, target) {
40971
+ if (!text) return;
40972
+ const parts = text.split(/(\r?\n)/);
40973
+ for (const part of parts) if (part === "\r\n" || part === "\n") target.push(createLineBreakNode());
40974
+ else if (part) target.push(createTextNode(part));
40975
+ }
40976
+ /**
40977
+ * 提取博主 IP 属地
40978
+ * @param Detail_Data - 作品详情数据
40979
+ * @returns IP 属地文本(如 "重庆"),不存在时返回 undefined
40980
+ */
40981
+ function extractIpLocation(Detail_Data) {
40982
+ let raw = Detail_Data.user_info?.data?.user?.ip_location;
40983
+ if (!raw) raw = Detail_Data.ip_location;
40984
+ if (!raw || typeof raw !== "string") return void 0;
40985
+ return raw.replace(/^IP属地[::]?\s*/, "").trim() || void 0;
40986
+ }
40987
+ /**
40988
+ * 从 suggest_words 中随机选择一条热点词
40989
+ * @param Detail_Data - 作品详情数据
40990
+ * @returns `{ hint_text, word }` 或 undefined
40991
+ */
40992
+ function extractSuggestWord(Detail_Data) {
40993
+ const groups = Detail_Data.suggest_words?.suggest_words;
40994
+ if (!Array.isArray(groups) || groups.length === 0) return void 0;
40995
+ const group = groups[0];
40996
+ const words = Array.isArray(group?.words) ? group.words : [];
40997
+ if (words.length === 0) return void 0;
40998
+ const pick = words[Math.floor(Math.random() * words.length)];
40999
+ if (!pick?.word) return void 0;
41000
+ return {
41001
+ hint_text: group.hint_text ?? "大家都在搜:",
41002
+ word: pick.word
41003
+ };
41004
+ }
41005
+ /**
41006
+ * 从抖音图片对象中提取第一个可用 URL。
41007
+ * @param images - 可能存在的多种封面对象
41008
+ * @returns 可直接渲染的图片 URL,不存在时返回 undefined
41009
+ */
41010
+ function pickImageUrl(...images) {
41011
+ for (const image of images) {
41012
+ const url = image?.url_list?.find((item) => typeof item === "string" && item.length > 0);
41013
+ if (url) return url;
40366
41014
  }
40367
- await douyinDBInstance.updateListSnapshot(sec_uid, pushType, contentList.map((a) => a.aweme_id));
40368
- return result;
41015
+ }
41016
+ /**
41017
+ * 安全解析 music.extra JSON。
41018
+ * @param extra - 抖音 music.extra 原始字符串
41019
+ * @returns 解析后的对象,解析失败时返回空对象
41020
+ */
41021
+ function parseMusicExtra(extra) {
41022
+ if (typeof extra !== "string" || extra.length === 0) return {};
41023
+ try {
41024
+ return JSON.parse(extra);
41025
+ } catch {
41026
+ return {};
41027
+ }
41028
+ }
41029
+ /**
41030
+ * 构建图文作品 BGM 展示信息。
41031
+ * 优先使用 matched_pgc_sound 的标准曲目信息,再回退到原声/作者字段和 extra 中的映射标题。
41032
+ * @param music - 抖音作品 music 字段
41033
+ * @returns 可传给模板的音乐信息;无有效音乐数据时返回 undefined
41034
+ */
41035
+ function buildMusicInfo(music) {
41036
+ if (!music || typeof music !== "object") return void 0;
41037
+ const extra = parseMusicExtra(music.extra);
41038
+ const matched = music.matched_pgc_sound;
41039
+ const title = matched?.title || matched?.mixed_title || extra.music_display_mapping_title || music.title;
41040
+ const author = matched?.author || matched?.mixed_author || music.author || music.owner_nickname;
41041
+ const cover = pickImageUrl(matched?.cover_medium, music.cover_hd, music.cover_large, music.cover_medium, music.cover_thumb, music.avatar_large, music.avatar_medium, music.avatar_thumb);
41042
+ if (!title && !author && !cover) return void 0;
41043
+ return {
41044
+ title: title || "未知音乐",
41045
+ author: author || "未知作者",
41046
+ cover
41047
+ };
41048
+ }
41049
+ /**
41050
+ * 获取用户抖音号
41051
+ * @param user - 用户对象,包含 unique_id 和 short_id
41052
+ * @returns 优先返回抖音号(unique_id),为空则返回短 ID
41053
+ */
41054
+ function douyinId(user) {
41055
+ return user.unique_id === "" ? user.short_id : user.unique_id;
41056
+ }
41057
+ /**
41058
+ * 根据作品类型计算默认推送标签
41059
+ * @param workTypeInfo - 作品类型信息
41060
+ * @returns 视频/图文/合辑/文章/直播 之一的推送标签
41061
+ */
41062
+ function getDefaultPushLabel(workTypeInfo) {
41063
+ if (workTypeInfo.isVideo) return "视频作品推送";
41064
+ if (workTypeInfo.isArticle) return "文章作品推送";
41065
+ if (workTypeInfo.isCollection) return "合辑作品推送";
41066
+ if (workTypeInfo.isImage) return "图文作品推送";
41067
+ if (workTypeInfo.isLive) return "直播动态推送";
41068
+ return "作品动态推送";
41069
+ }
41070
+ /**
41071
+ * 渲染作品推送图片
41072
+ * 根据作品类型(文章/视频/图文/合辑)自动选择对应模板进行渲染
41073
+ * 推送类型标签按优先级:调用方显式传入 → 根据作品主/子类型自动计算
41074
+ * @param options - 渲染参数
41075
+ * @returns 渲染后的图片元素数组
41076
+ */
41077
+ async function renderWorkImage(options) {
41078
+ const { e, Detail_Data, create_time, shareLink, skipWatermark = false } = options;
41079
+ const workTypeInfo = getWorkTypeInfo(Detail_Data);
41080
+ const dynamicTypeLabel = options.dynamicTypeLabel ?? getDefaultPushLabel(workTypeInfo);
41081
+ const coverUrl = getWorkCoverUrl(workTypeInfo, Detail_Data);
41082
+ const formatTime = format(fromUnixTime(create_time), "yyyy-MM-dd HH:mm");
41083
+ const user = Detail_Data.user_info.data.user;
41084
+ const userDouyinId = douyinId(user);
41085
+ const avatarUrl = cdnAvatar(user.avatar_larger.uri);
41086
+ const authorNickname = Detail_Data.author?.nickname ?? user.nickname;
41087
+ const cooperationInfo = buildCooperationInfo(Detail_Data);
41088
+ const mentionCache = /* @__PURE__ */ new Map();
41089
+ const renderOpts = skipWatermark ? { skipWatermark: true } : void 0;
41090
+ switch (workTypeInfo.mainType) {
41091
+ case DouyinWorkMainType.ARTICLE: {
41092
+ const content = JSON.parse(Detail_Data.article_info.article_content);
41093
+ const fe_data = JSON.parse(Detail_Data.article_info.fe_data);
41094
+ return await Render(e, "douyin/article-work", {
41095
+ title: Detail_Data.article_info.article_title,
41096
+ markdown: content.markdown,
41097
+ images: fe_data.image_list || [],
41098
+ read_time: fe_data.read_time || 0,
41099
+ dianzan: Count(Detail_Data.statistics.digg_count),
41100
+ pinglun: Count(Detail_Data.statistics.comment_count),
41101
+ shouchang: Count(Detail_Data.statistics.collect_count),
41102
+ share: Count(Detail_Data.statistics.share_count),
41103
+ create_time: formatTime,
41104
+ avater_url: avatarUrl,
41105
+ username: authorNickname,
41106
+ 抖音号: userDouyinId,
41107
+ 获赞: Count(user.total_favorited),
41108
+ 关注: Count(user.following_count),
41109
+ 粉丝: Count(user.follower_count),
41110
+ share_url: Detail_Data.share_url
41111
+ }, renderOpts);
41112
+ }
41113
+ case DouyinWorkMainType.VIDEO: return await Render(e, "douyin/video-work", {
41114
+ image_url: coverUrl,
41115
+ title: await buildDescRichText(desc(Detail_Data.desc ?? ""), Detail_Data.text_extra, 0, mentionCache),
41116
+ desc: createRichTextDocument([], { platform: "douyin" }),
41117
+ ip_location: extractIpLocation(Detail_Data),
41118
+ suggest_word: extractSuggestWord(Detail_Data),
41119
+ music: buildMusicInfo(Detail_Data.music),
41120
+ duration: Detail_Data.duration,
41121
+ dianzan: Count(Detail_Data.statistics.digg_count),
41122
+ pinglun: Count(Detail_Data.statistics.comment_count),
41123
+ share: Count(Detail_Data.statistics.share_count),
41124
+ shouchang: Count(Detail_Data.statistics.collect_count),
41125
+ create_time,
41126
+ avater_url: avatarUrl,
41127
+ share_url: shareLink,
41128
+ username: user.nickname,
41129
+ 抖音号: userDouyinId,
41130
+ 粉丝: Count(user.follower_count),
41131
+ 获赞: Count(user.total_favorited),
41132
+ 关注: Count(user.following_count),
41133
+ dynamicTYPE: dynamicTypeLabel,
41134
+ cooperation_info: cooperationInfo
41135
+ }, renderOpts);
41136
+ case DouyinWorkMainType.IMAGE: {
41137
+ const cover = Detail_Data.images?.[0]?.url_list[2] ?? Detail_Data.images?.[0]?.url_list[1] ?? coverUrl;
41138
+ const rawDesc = Detail_Data.desc ?? "";
41139
+ const splitDesc = splitTitleAndBody(rawDesc);
41140
+ const titleOffset = rawDesc.length - splitDesc.body.length;
41141
+ const title = splitDesc.title ? await buildDescRichText(splitDesc.title, Detail_Data.text_extra, 0, mentionCache) : void 0;
41142
+ const richDesc = await buildDescRichText(splitDesc.title && !splitDesc.body ? "" : desc(splitDesc.body), Detail_Data.text_extra, titleOffset, mentionCache);
41143
+ return await Render(e, "douyin/image-work", {
41144
+ image_list: buildImageList(Detail_Data.images, cover),
41145
+ title,
41146
+ desc: richDesc,
41147
+ ip_location: extractIpLocation(Detail_Data),
41148
+ suggest_word: extractSuggestWord(Detail_Data),
41149
+ music: buildMusicInfo(Detail_Data.music),
41150
+ dianzan: Count(Detail_Data.statistics.digg_count),
41151
+ pinglun: Count(Detail_Data.statistics.comment_count),
41152
+ share: Count(Detail_Data.statistics.share_count),
41153
+ shouchang: Count(Detail_Data.statistics.collect_count),
41154
+ create_time,
41155
+ avater_url: avatarUrl,
41156
+ share_url: shareLink,
41157
+ username: user.nickname,
41158
+ 抖音号: userDouyinId,
41159
+ 粉丝: Count(user.follower_count),
41160
+ 获赞: Count(user.total_favorited),
41161
+ 关注: Count(user.following_count),
41162
+ dynamicTYPE: dynamicTypeLabel,
41163
+ cooperation_info: cooperationInfo
41164
+ }, renderOpts);
41165
+ }
41166
+ default: return [];
41167
+ }
41168
+ }
41169
+ /**
41170
+ * 渲染喜欢列表推送图片
41171
+ * 展示用户喜欢的作品,同时显示点赞者和作品原作者的信息
41172
+ * @param options - 渲染参数
41173
+ * @returns 渲染后的图片元素数组
41174
+ */
41175
+ async function renderFavoriteImage(options) {
41176
+ const { e, Detail_Data, create_time, shareLink, remark, skipWatermark = false } = options;
41177
+ const coverUrl = getWorkCoverUrl(getWorkTypeInfo(Detail_Data), Detail_Data);
41178
+ const authorUserInfo = Detail_Data.author_user_info;
41179
+ const subscriberUser = Detail_Data.user_info.data.user;
41180
+ return await Render(e, "douyin/favorite-list", {
41181
+ image_url: coverUrl,
41182
+ desc: desc(Detail_Data.desc),
41183
+ dianzan: Count(Detail_Data.statistics.digg_count),
41184
+ pinglun: Count(Detail_Data.statistics.comment_count),
41185
+ share: Count(Detail_Data.statistics.share_count),
41186
+ shouchang: Count(Detail_Data.statistics.collect_count),
41187
+ tuijian: Count(Detail_Data.statistics.recommend_count),
41188
+ create_time: format(fromUnixTime(create_time), "yyyy-MM-dd HH:mm"),
41189
+ liker_username: remark,
41190
+ liker_avatar: cdnAvatar(subscriberUser.avatar_larger.uri),
41191
+ liker_douyin_id: douyinId(subscriberUser),
41192
+ author_username: Detail_Data.author.nickname,
41193
+ author_avatar: authorUserInfo ? cdnAvatar(authorUserInfo.data.user.avatar_larger.uri) : Detail_Data.author.avatar_thumb.url_list[0],
41194
+ author_douyin_id: authorUserInfo ? douyinId(authorUserInfo.data.user) : douyinId(Detail_Data.author),
41195
+ share_url: shareLink
41196
+ }, skipWatermark ? { skipWatermark: true } : void 0);
41197
+ }
41198
+ /**
41199
+ * 渲染推荐列表推送图片
41200
+ * 展示用户推荐的作品,同时显示推荐者和作品原作者的信息
41201
+ * @param options - 渲染参数
41202
+ * @returns 渲染后的图片元素数组
41203
+ */
41204
+ async function renderRecommendImage(options) {
41205
+ const { e, Detail_Data, create_time, shareLink, remark, skipWatermark = false } = options;
41206
+ const coverUrl = getWorkCoverUrl(getWorkTypeInfo(Detail_Data), Detail_Data);
41207
+ const authorUserInfo = Detail_Data.author_user_info;
41208
+ const recommenderUser = Detail_Data.user_info.data.user;
41209
+ return await Render(e, "douyin/recommend-list", {
41210
+ image_url: coverUrl,
41211
+ desc: desc(Detail_Data.desc),
41212
+ dianzan: Count(Detail_Data.statistics.digg_count),
41213
+ pinglun: Count(Detail_Data.statistics.comment_count),
41214
+ share: Count(Detail_Data.statistics.share_count),
41215
+ shouchang: Count(Detail_Data.statistics.collect_count),
41216
+ tuijian: Count(Detail_Data.statistics.recommend_count),
41217
+ create_time: format(fromUnixTime(create_time), "yyyy-MM-dd HH:mm"),
41218
+ recommender_username: remark,
41219
+ recommender_avatar: cdnAvatar(recommenderUser.avatar_larger.uri),
41220
+ recommender_douyin_id: douyinId(recommenderUser),
41221
+ author_username: Detail_Data.author.nickname,
41222
+ author_avatar: authorUserInfo ? cdnAvatar(authorUserInfo.data.user.avatar_larger.uri) : Detail_Data.author.avatar_thumb.url_list[0],
41223
+ author_douyin_id: authorUserInfo ? douyinId(authorUserInfo.data.user) : douyinId(Detail_Data.author),
41224
+ share_url: shareLink
41225
+ }, skipWatermark ? { skipWatermark: true } : void 0);
41226
+ }
41227
+ /**
41228
+ * 渲染直播状态推送图片
41229
+ * 展示直播间封面、主播信息、在线人数、分区等数据
41230
+ * 如果 room_data 或 live_data 缺失则返回空数组
41231
+ * @param options - 渲染参数
41232
+ * @returns 渲染后的图片元素数组
41233
+ */
41234
+ async function renderLiveImage(options) {
41235
+ const { e, Detail_Data, skipWatermark = false } = options;
41236
+ const dynamicTypeLabel = options.dynamicTypeLabel ?? "直播动态推送";
41237
+ const user = Detail_Data.user_info.data.user;
41238
+ if (!Detail_Data.room_data || !Detail_Data.live_data) return [];
41239
+ const liveItem = Detail_Data.live_data.data.data.data[0];
41240
+ const room_data = Detail_Data.room_data;
41241
+ const streamExtra = liveItem.stream_url?.extra;
41242
+ const resolution = streamExtra ? `${streamExtra.width}x${streamExtra.height}` : liveItem.stream_url?.default_resolution;
41243
+ return await Render(e, "douyin/live", {
41244
+ image_url: liveItem.cover?.url_list[0],
41245
+ text: liveItem.title,
41246
+ partition_title: Detail_Data.live_data.data.data.partition_road_map?.partition?.title || "未知分区",
41247
+ room_id: room_data.owner.web_rid,
41248
+ online_viewers: Count(Number(liveItem.room_view_stats?.display_value)),
41249
+ total_viewers: liveItem.stats?.total_user_str || "",
41250
+ username: user.nickname,
41251
+ avater_url: cdnAvatar(user.avatar_larger.uri),
41252
+ fans: Count(user.follower_count),
41253
+ share_url: "https://live.douyin.com/" + room_data.owner.web_rid,
41254
+ dynamicTYPE: dynamicTypeLabel,
41255
+ like_count: Count(Number(liveItem.like_count || 0)),
41256
+ user_count_str: liveItem.user_count_str || "",
41257
+ resolution,
41258
+ signature: user.signature || "",
41259
+ city: user.city || "",
41260
+ aweme_count: Count(user.aweme_count || 0),
41261
+ following_count: Count(user.following_count || 0),
41262
+ total_favorited: Count(user.total_favorited || 0),
41263
+ has_commerce_goods: liveItem.has_commerce_goods || false
41264
+ }, skipWatermark ? { skipWatermark: true } : void 0);
40369
41265
  }
40370
41266
  //#endregion
40371
41267
  //#region src/platform/douyin/push.ts
@@ -40483,13 +41379,30 @@ var DouYinpush = class extends Base {
40483
41379
  for (const awemeId in data) {
40484
41380
  const pushItem = data[awemeId];
40485
41381
  const actualAwemeId = awemeId.replace(/^(post|favorite|recommend|live)_/, "");
40486
- const pushTypeLabel = pushItem.pushType === "post" ? "作品列表" : pushItem.pushType === "favorite" ? "喜欢列表" : pushItem.pushType === "recommend" ? "推荐列表" : "直播";
41382
+ const shareUrl = pushItem.Detail_Data.share_url ?? `https://live.douyin.com/${pushItem.Detail_Data.room_data?.owner.web_rid}`;
41383
+ let pushTypeLabel;
41384
+ switch (pushItem.pushType) {
41385
+ case "post":
41386
+ pushTypeLabel = "作品列表";
41387
+ break;
41388
+ case "favorite":
41389
+ pushTypeLabel = "喜欢列表";
41390
+ break;
41391
+ case "recommend":
41392
+ pushTypeLabel = "推荐列表";
41393
+ break;
41394
+ default:
41395
+ pushTypeLabel = "直播";
41396
+ break;
41397
+ }
40487
41398
  logger.mark(`
40488
41399
  ${logger.blue("开始处理并渲染抖音动态图片")}
40489
41400
  ${logger.blue("博主")}: ${logger.green(pushItem.remark)}
40490
41401
  ${logger.blue("推送类型")}: ${logger.magenta(pushTypeLabel)}
40491
41402
  ${logger.cyan("作品id")}:${logger.yellow(actualAwemeId)}
40492
- ${logger.cyan("访问地址")}:${logger.green("https://www.douyin.com/video/" + actualAwemeId)}`);
41403
+ ${logger.cyan("访问地址")}:${logger.green("https://www.douyin.com/video/" + actualAwemeId)}
41404
+ ${logger.cyan("分享链接")}: ${logger.green(shareUrl)}
41405
+ `);
40493
41406
  const Detail_Data = pushItem.Detail_Data;
40494
41407
  const skip = await skipDynamic(pushItem);
40495
41408
  skip && logger.warn(`作品 https://www.douyin.com/video/${actualAwemeId} 已被处理,跳过`);
@@ -40497,34 +41410,8 @@ var DouYinpush = class extends Base {
40497
41410
  let iddata = { type: "one_work" };
40498
41411
  this.injectBotToEventForRender(pushItem.targets);
40499
41412
  if (!skip) iddata = await getDouyinID(this.e, Detail_Data.share_url ?? "https://live.douyin.com/" + Detail_Data.room_data?.owner.web_rid, false);
40500
- if (!skip) if (pushItem.pushType === "live" && "room_data" in pushItem.Detail_Data && Detail_Data.live_data) {
40501
- const liveItem = Detail_Data.live_data.data.data.data[0];
40502
- const streamExtra = liveItem.stream_url.extra;
40503
- const resolution = streamExtra ? `${streamExtra.width}x${streamExtra.height}` : liveItem.stream_url.default_resolution;
40504
- img = await Render(this.e, "douyin/live", {
40505
- image_url: liveItem.cover.url_list[0],
40506
- text: liveItem.title,
40507
- partition_title: Detail_Data.live_data.data.data.partition_road_map?.partition?.title || "未知分区",
40508
- room_id: Detail_Data.room_data.owner.web_rid,
40509
- online_viewers: this.count(liveItem.room_view_stats.display_value),
40510
- total_viewers: liveItem.stats.total_user_str,
40511
- username: Detail_Data.user_info.data.user.nickname,
40512
- avater_url: "https://p3-pc.douyinpic.com/aweme/1080x1080/" + Detail_Data.user_info.data.user.avatar_larger.uri,
40513
- fans: this.count(Detail_Data.user_info.data.user.follower_count),
40514
- share_url: "https://live.douyin.com/" + Detail_Data.room_data.owner.web_rid,
40515
- dynamicTYPE: "直播动态推送",
40516
- like_count: this.count(liveItem.like_count),
40517
- user_count_str: liveItem.user_count_str,
40518
- resolution,
40519
- signature: Detail_Data.user_info.data.user.signature,
40520
- city: Detail_Data.user_info.data.user.city,
40521
- aweme_count: this.count(Detail_Data.user_info.data.user.aweme_count),
40522
- following_count: this.count(Detail_Data.user_info.data.user.following_count),
40523
- total_favorited: this.count(Detail_Data.user_info.data.user.total_favorited),
40524
- has_commerce_goods: liveItem.has_commerce_goods
40525
- }, { skipWatermark: true });
40526
- } else {
40527
- const realUrl = Config.douyin.push.shareType === "web" && await new Network({
41413
+ if (!skip) {
41414
+ const realUrl = pushItem.pushType !== "live" && Config.douyin.push.shareType === "web" && await new Network({
40528
41415
  url: Detail_Data.share_url,
40529
41416
  headers: {
40530
41417
  "User-Agent": "Apifox/1.0.0 (https://apifox.com)",
@@ -40533,114 +41420,51 @@ var DouYinpush = class extends Base {
40533
41420
  Connection: "keep-alive"
40534
41421
  }
40535
41422
  }).getLocation();
40536
- if (pushItem.pushType === "favorite") {
40537
- const authorUserInfo = "author_user_info" in Detail_Data ? Detail_Data.author_user_info : void 0;
40538
- const coverUrl = getWorkCoverUrl(getWorkTypeInfo(Detail_Data), Detail_Data);
40539
- img = await Render(this.e, "douyin/favorite-list", {
40540
- image_url: coverUrl,
40541
- desc: this.desc(Detail_Data, Detail_Data.desc),
40542
- dianzan: this.count(Detail_Data.statistics.digg_count),
40543
- pinglun: this.count(Detail_Data.statistics.comment_count),
40544
- share: this.count(Detail_Data.statistics.share_count),
40545
- shouchang: this.count(Detail_Data.statistics.collect_count),
40546
- tuijian: this.count(Detail_Data.statistics.recommend_count),
40547
- create_time: format(fromUnixTime(pushItem.create_time), "yyyy-MM-dd HH:mm"),
40548
- liker_username: pushItem.remark,
40549
- liker_avatar: "https://p3-pc.douyinpic.com/aweme/1080x1080/" + Detail_Data.user_info.data.user.avatar_larger.uri,
40550
- liker_douyin_id: Detail_Data.user_info.data.user.unique_id === "" ? Detail_Data.user_info.data.user.short_id : Detail_Data.user_info.data.user.unique_id,
40551
- author_username: Detail_Data.author.nickname,
40552
- author_avatar: "https://p3-pc.douyinpic.com/aweme/1080x1080/" + authorUserInfo.data.user.avatar_larger.uri,
40553
- author_douyin_id: authorUserInfo.data.user.unique_id === "" ? authorUserInfo.data.user.short_id : authorUserInfo.data.user.unique_id,
40554
- share_url: Config.douyin.push.shareType === "web" ? realUrl : `https://aweme.snssdk.com/aweme/v1/play/?video_id=${Detail_Data.video.play_addr.uri}&ratio=1080p&line=0`
40555
- }, { skipWatermark: true });
40556
- } else if (pushItem.pushType === "recommend") {
40557
- const authorUserInfo = "author_user_info" in Detail_Data ? Detail_Data.author_user_info : void 0;
40558
- const coverUrl = getWorkCoverUrl(getWorkTypeInfo(Detail_Data), Detail_Data);
40559
- img = await Render(this.e, "douyin/recommend-list", {
40560
- image_url: coverUrl,
40561
- desc: this.desc(Detail_Data, Detail_Data.desc),
40562
- dianzan: this.count(Detail_Data.statistics.digg_count),
40563
- pinglun: this.count(Detail_Data.statistics.comment_count),
40564
- share: this.count(Detail_Data.statistics.share_count),
40565
- shouchang: this.count(Detail_Data.statistics.collect_count),
40566
- tuijian: this.count(Detail_Data.statistics.recommend_count),
40567
- create_time: format(fromUnixTime(pushItem.create_time), "yyyy-MM-dd HH:mm"),
40568
- recommender_username: pushItem.remark,
40569
- recommender_avatar: "https://p3-pc.douyinpic.com/aweme/1080x1080/" + Detail_Data.user_info.data.user.avatar_larger.uri,
40570
- recommender_douyin_id: Detail_Data.user_info.data.user.unique_id === "" ? Detail_Data.user_info.data.user.short_id : Detail_Data.user_info.data.user.unique_id,
40571
- author_username: Detail_Data.author.nickname,
40572
- author_avatar: "https://p3-pc.douyinpic.com/aweme/1080x1080/" + authorUserInfo.data.user.avatar_larger.uri,
40573
- author_douyin_id: authorUserInfo.data.user.unique_id === "" ? authorUserInfo.data.user.short_id : authorUserInfo.data.user.unique_id,
40574
- share_url: Config.douyin.push.shareType === "web" ? realUrl : `https://aweme.snssdk.com/aweme/v1/play/?video_id=${Detail_Data.video.play_addr.uri}&ratio=1080p&line=0`
40575
- }, { skipWatermark: true });
40576
- } else {
40577
- const dynamicTypeLabel = "作品动态推送";
40578
- const workTypeInfo = getWorkTypeInfo(Detail_Data);
40579
- const coverUrl = getWorkCoverUrl(workTypeInfo, Detail_Data);
40580
- if (workTypeInfo.isArticle) {
40581
- const content = JSON.parse(Detail_Data.article_info.article_content);
40582
- const fe_data = JSON.parse(Detail_Data.article_info.fe_data);
40583
- img = await Render(this.e, "douyin/article-work", {
40584
- title: Detail_Data.article_info.article_title,
40585
- markdown: content.markdown,
40586
- images: fe_data.image_list || [],
40587
- read_time: fe_data.read_time || 0,
40588
- dianzan: this.count(Detail_Data.statistics.digg_count),
40589
- pinglun: this.count(Detail_Data.statistics.comment_count),
40590
- shouchang: this.count(Detail_Data.statistics.collect_count),
40591
- share: this.count(Detail_Data.statistics.share_count),
40592
- create_time: format(fromUnixTime(pushItem.create_time), "yyyy-MM-dd HH:mm"),
40593
- avater_url: "https://p3-pc.douyinpic.com/aweme/1080x1080/" + Detail_Data.user_info.data.user.avatar_larger.uri,
40594
- username: Detail_Data.author.nickname,
40595
- 抖音号: Detail_Data.user_info.data.user.unique_id === "" ? Detail_Data.user_info.data.user.short_id : Detail_Data.user_info.data.user.unique_id,
40596
- 获赞: this.count(Detail_Data.user_info.data.user.total_favorited),
40597
- 关注: this.count(Detail_Data.user_info.data.user.following_count),
40598
- 粉丝: this.count(Detail_Data.user_info.data.user.follower_count),
40599
- share_url: Detail_Data.share_url,
40600
- useDarkTheme: false
40601
- }, { skipWatermark: true });
40602
- } else img = await Render(this.e, workTypeInfo.templatePath, {
40603
- image_url: coverUrl,
40604
- desc: this.desc(Detail_Data, Detail_Data.desc),
40605
- dianzan: this.count(Detail_Data.statistics.digg_count),
40606
- pinglun: this.count(Detail_Data.statistics.comment_count),
40607
- share: this.count(Detail_Data.statistics.share_count),
40608
- shouchang: this.count(Detail_Data.statistics.collect_count),
40609
- create_time: format(fromUnixTime(pushItem.create_time), "yyyy-MM-dd HH:mm"),
40610
- avater_url: "https://p3-pc.douyinpic.com/aweme/1080x1080/" + Detail_Data.user_info.data.user.avatar_larger.uri,
40611
- share_url: Config.douyin.push.shareType === "web" ? realUrl : `https://aweme.snssdk.com/aweme/v1/play/?video_id=${Detail_Data.video.play_addr.uri}&ratio=1080p&line=0`,
40612
- username: Detail_Data.user_info.data.user.nickname,
40613
- 抖音号: Detail_Data.user_info.data.user.unique_id === "" ? Detail_Data.user_info.data.user.short_id : Detail_Data.user_info.data.user.unique_id,
40614
- 粉丝: this.count(Detail_Data.user_info.data.user.follower_count),
40615
- 获赞: this.count(Detail_Data.user_info.data.user.total_favorited),
40616
- 关注: this.count(Detail_Data.user_info.data.user.following_count),
40617
- dynamicTYPE: dynamicTypeLabel,
40618
- cooperation_info: (() => {
40619
- const raw = Detail_Data.cooperation_info;
40620
- if (!raw) return void 0;
40621
- const rawCreators = Array.isArray(raw.co_creators) ? raw.co_creators : [];
40622
- const subscriberUid = Detail_Data.user_info.data.user.uid;
40623
- const subscriberSecUid = Detail_Data.user_info.data.user.sec_uid;
40624
- const subscriberInCreators = rawCreators.find((c) => subscriberUid && c.uid && c.uid === subscriberUid || subscriberSecUid && c.sec_uid && c.sec_uid === subscriberSecUid);
40625
- const co_creators = rawCreators.map((c) => {
40626
- return {
40627
- avatar_url: c.avatar_thumb?.url_list?.[0] ?? (c.avatar_thumb?.uri ? `https://p3.douyinpic.com/${c.avatar_thumb.uri}` : void 0),
40628
- nickname: c.nickname,
40629
- role_title: c.role_title
40630
- };
40631
- });
40632
- if (Detail_Data.author && !rawCreators.some((c) => Detail_Data.author?.uid && c.uid && c.uid === Detail_Data.author.uid || Detail_Data.author?.sec_uid && c.sec_uid && c.sec_uid === Detail_Data.author.sec_uid || Detail_Data.author?.nickname && c.nickname && c.nickname === Detail_Data.author.nickname)) co_creators.unshift({
40633
- avatar_url: Detail_Data.author.avatar_thumb?.url_list?.[0] ?? (Detail_Data.author.avatar_thumb?.uri ? `https://p3.douyinpic.com/${Detail_Data.author.avatar_thumb.uri}` : void 0),
40634
- nickname: Detail_Data.author.nickname,
40635
- role_title: "作者"
40636
- });
40637
- return {
40638
- co_creator_nums: Math.max(Number(raw.co_creator_nums || 0), co_creators.length),
40639
- co_creators,
40640
- subscriber_role: subscriberInCreators?.role_title ?? (subscriberUid && Detail_Data.author?.uid && subscriberUid === Detail_Data.author.uid || subscriberSecUid && Detail_Data.author?.sec_uid && subscriberSecUid === Detail_Data.author.sec_uid || Detail_Data.user_info.data.user.nickname && Detail_Data.author?.nickname && Detail_Data.user_info.data.user.nickname === Detail_Data.author.nickname ? "作者" : void 0)
40641
- };
40642
- })()
40643
- }, { skipWatermark: true });
41423
+ switch (pushItem.pushType) {
41424
+ case "live":
41425
+ if (!("room_data" in pushItem.Detail_Data && Detail_Data.live_data)) break;
41426
+ img = await renderLiveImage({
41427
+ e: this.e,
41428
+ Detail_Data,
41429
+ skipWatermark: true,
41430
+ dynamicTypeLabel: "直播动态推送"
41431
+ });
41432
+ break;
41433
+ case "favorite": {
41434
+ const shareLink = Config.douyin.push.shareType === "web" ? realUrl : `https://aweme.snssdk.com/aweme/v1/play/?video_id=${Detail_Data.video.play_addr.uri}&ratio=1080p&line=0`;
41435
+ img = await renderFavoriteImage({
41436
+ e: this.e,
41437
+ Detail_Data,
41438
+ create_time: pushItem.create_time,
41439
+ shareLink,
41440
+ remark: pushItem.remark,
41441
+ skipWatermark: true
41442
+ });
41443
+ break;
41444
+ }
41445
+ case "recommend": {
41446
+ const shareLink = Config.douyin.push.shareType === "web" ? realUrl : `https://aweme.snssdk.com/aweme/v1/play/?video_id=${Detail_Data.video.play_addr.uri}&ratio=1080p&line=0`;
41447
+ img = await renderRecommendImage({
41448
+ e: this.e,
41449
+ Detail_Data,
41450
+ create_time: pushItem.create_time,
41451
+ shareLink,
41452
+ remark: pushItem.remark,
41453
+ skipWatermark: true
41454
+ });
41455
+ break;
41456
+ }
41457
+ default: {
41458
+ const shareLink = Config.douyin.push.shareType === "web" ? realUrl : `https://aweme.snssdk.com/aweme/v1/play/?video_id=${Detail_Data.video.play_addr.uri}&ratio=1080p&line=0`;
41459
+ img = await renderWorkImage({
41460
+ e: this.e,
41461
+ Detail_Data,
41462
+ create_time: pushItem.create_time,
41463
+ shareLink,
41464
+ skipWatermark: true
41465
+ });
41466
+ break;
41467
+ }
40644
41468
  }
40645
41469
  }
40646
41470
  for (const target of pushItem.targets) {
@@ -41236,13 +42060,6 @@ var DouYinpush = class extends Base {
41236
42060
  return false;
41237
42061
  }
41238
42062
  /**
41239
- * 处理作品描述
41240
- */
41241
- desc(Detail_Data, desc) {
41242
- if (desc === "") return "该作品没有描述";
41243
- return desc;
41244
- }
41245
- /**
41246
42063
  * 格式化数字
41247
42064
  */
41248
42065
  count(num) {
@@ -42992,6 +43809,216 @@ var globalStatistics = karin$1.command(/^#?kkk全局解析统计$/, handleGlobal
42992
43809
  perm: "master"
42993
43810
  });
42994
43811
  //#endregion
43812
+ //#region src/apps/testPush.ts
43813
+ /**
43814
+ * 测试抖音推送命令处理器
43815
+ * 支持四种推送类型的预览渲染,无数据库交互,仅用于调试和验证推送卡片效果
43816
+ *
43817
+ * 命令格式:
43818
+ * - #测试抖音作品推送 <作品链接>
43819
+ * - #测试抖音喜欢列表推送 <用户主页链接>
43820
+ * - #测试抖音推荐列表推送 <用户主页链接>
43821
+ * - #测试抖音直播状态推送 <用户主页链接>
43822
+ */
43823
+ var handleTestPush = wrapWithErrorHandler(async (e) => {
43824
+ const match = e.msg.match(/^#测试抖音(作品|喜欢列表|推荐列表|直播状态)推送/);
43825
+ if (!match) {
43826
+ e.reply("支持的命令:\n#测试抖音作品推送 <作品链接>\n#测试抖音喜欢列表推送 <用户主页链接>\n#测试抖音推荐列表推送 <用户主页链接>\n#测试抖音直播状态推送 <用户主页链接>");
43827
+ return true;
43828
+ }
43829
+ /** 提取推送类型和链接 */
43830
+ const pushType = match[1];
43831
+ const urlMatch = e.msg.replace(match[0], "").trim().match(/(https?:\/\/[^\s]+)/i);
43832
+ if (!urlMatch) {
43833
+ e.reply(`请在命令后提供对应的${pushType === "作品" ? "作品" : "用户主页"}链接`);
43834
+ return true;
43835
+ }
43836
+ const url = urlMatch[1];
43837
+ const iddata = await getDouyinID(e, url, false);
43838
+ let images = [];
43839
+ switch (pushType) {
43840
+ /** 作品推送:作品链接 → parseWork → 渲染 */
43841
+ case "作品": {
43842
+ if (iddata.type !== "one_work" || !iddata.aweme_id) {
43843
+ e.reply("该链接不是作品链接,请提供视频/图集/文章链接");
43844
+ return true;
43845
+ }
43846
+ logger.mark(`[测试抖音推送] 开始解析作品: ${iddata.aweme_id}`);
43847
+ const workData = await douyinFetcher.parseWork({
43848
+ aweme_id: iddata.aweme_id,
43849
+ typeMode: "strict"
43850
+ });
43851
+ if (!workData.data.aweme_detail) {
43852
+ e.reply("获取作品详情失败,作品可能已被删除或设为私密");
43853
+ return true;
43854
+ }
43855
+ const aweme = workData.data.aweme_detail;
43856
+ const userinfo = await douyinFetcher.fetchUserProfile({
43857
+ sec_uid: aweme.author.sec_uid,
43858
+ typeMode: "strict"
43859
+ });
43860
+ const Detail_Data = {
43861
+ ...aweme,
43862
+ user_info: userinfo
43863
+ };
43864
+ const shareLink = Detail_Data.video?.play_addr?.uri ? `https://aweme.snssdk.com/aweme/v1/play/?video_id=${Detail_Data.video.play_addr.uri}&ratio=1080p&line=0` : Detail_Data.share_url || url;
43865
+ images = await renderWorkImage({
43866
+ e,
43867
+ Detail_Data,
43868
+ create_time: aweme.create_time,
43869
+ shareLink
43870
+ });
43871
+ if (images.length === 0) {
43872
+ e.reply("未能识别该作品类型,无法渲染推送图片");
43873
+ return true;
43874
+ }
43875
+ break;
43876
+ }
43877
+ /** 喜欢列表:用户主页 → fetchUserFavoriteList[0] → 渲染 */
43878
+ case "喜欢列表": {
43879
+ if (iddata.type !== "user_dynamic" || !iddata.sec_uid) {
43880
+ e.reply("需要用户主页链接以获取喜欢列表");
43881
+ return true;
43882
+ }
43883
+ logger.mark(`[测试抖音推送] 开始获取喜欢列表: sec_uid=${iddata.sec_uid}`);
43884
+ const userinfo = await douyinFetcher.fetchUserProfile({
43885
+ sec_uid: iddata.sec_uid,
43886
+ typeMode: "strict"
43887
+ });
43888
+ const favoriteData = await douyinFetcher.fetchUserFavoriteList({
43889
+ sec_uid: iddata.sec_uid,
43890
+ number: 1,
43891
+ typeMode: "strict"
43892
+ });
43893
+ if (!favoriteData.data.aweme_list?.length) {
43894
+ e.reply("该用户的喜欢列表为空或未公开");
43895
+ return true;
43896
+ }
43897
+ const aweme = favoriteData.data.aweme_list[0];
43898
+ let authorUserInfo;
43899
+ try {
43900
+ authorUserInfo = await douyinFetcher.fetchUserProfile({
43901
+ sec_uid: aweme.author.sec_uid,
43902
+ typeMode: "strict"
43903
+ });
43904
+ } catch {}
43905
+ const Detail_Data = {
43906
+ ...aweme,
43907
+ user_info: userinfo,
43908
+ author_user_info: authorUserInfo
43909
+ };
43910
+ const shareLink = Detail_Data.video?.play_addr?.uri ? `https://aweme.snssdk.com/aweme/v1/play/?video_id=${Detail_Data.video.play_addr.uri}&ratio=1080p&line=0` : aweme.share_url;
43911
+ images = await renderFavoriteImage({
43912
+ e,
43913
+ Detail_Data,
43914
+ create_time: aweme.create_time,
43915
+ shareLink,
43916
+ remark: userinfo.data.user.nickname
43917
+ });
43918
+ if (!images.length) {
43919
+ e.reply("渲染喜欢列表推送图片失败");
43920
+ return true;
43921
+ }
43922
+ break;
43923
+ }
43924
+ /** 推荐列表:用户主页 → fetchUserRecommendList[0] → 渲染 */
43925
+ case "推荐列表": {
43926
+ if (iddata.type !== "user_dynamic" || !iddata.sec_uid) {
43927
+ e.reply("需要用户主页链接以获取推荐列表");
43928
+ return true;
43929
+ }
43930
+ logger.mark(`[测试抖音推送] 开始获取推荐列表: sec_uid=${iddata.sec_uid}`);
43931
+ const userinfo = await douyinFetcher.fetchUserProfile({
43932
+ sec_uid: iddata.sec_uid,
43933
+ typeMode: "strict"
43934
+ });
43935
+ const recommendData = await douyinFetcher.fetchUserRecommendList({
43936
+ sec_uid: iddata.sec_uid,
43937
+ number: 1,
43938
+ typeMode: "strict"
43939
+ });
43940
+ if (!recommendData.data.aweme_list?.length) {
43941
+ e.reply("该用户的推荐列表为空或未公开");
43942
+ return true;
43943
+ }
43944
+ const aweme = recommendData.data.aweme_list[0];
43945
+ let authorUserInfo;
43946
+ try {
43947
+ authorUserInfo = await douyinFetcher.fetchUserProfile({
43948
+ sec_uid: aweme.author.sec_uid,
43949
+ typeMode: "strict"
43950
+ });
43951
+ } catch {}
43952
+ const Detail_Data = {
43953
+ ...aweme,
43954
+ user_info: userinfo,
43955
+ author_user_info: authorUserInfo
43956
+ };
43957
+ const shareLink = Detail_Data.video?.play_addr?.uri ? `https://aweme.snssdk.com/aweme/v1/play/?video_id=${Detail_Data.video.play_addr.uri}&ratio=1080p&line=0` : aweme.share_url;
43958
+ images = await renderRecommendImage({
43959
+ e,
43960
+ Detail_Data,
43961
+ create_time: aweme.create_time,
43962
+ shareLink,
43963
+ remark: userinfo.data.user.nickname
43964
+ });
43965
+ if (!images.length) {
43966
+ e.reply("渲染推荐列表推送图片失败");
43967
+ return true;
43968
+ }
43969
+ break;
43970
+ }
43971
+ /** 直播状态:用户主页 → 检查 live_status → fetchLiveRoomInfo → 渲染 */
43972
+ case "直播状态": {
43973
+ if (iddata.type !== "user_dynamic" || !iddata.sec_uid) {
43974
+ e.reply("需要用户主页链接以检查直播状态");
43975
+ return true;
43976
+ }
43977
+ const sec_uid = iddata.sec_uid;
43978
+ logger.mark(`[测试抖音推送] 开始检查直播状态: sec_uid=${sec_uid}`);
43979
+ const userinfo = await douyinFetcher.fetchUserProfile({
43980
+ sec_uid,
43981
+ typeMode: "strict"
43982
+ });
43983
+ const user = userinfo.data.user;
43984
+ if (user.live_status !== 1) {
43985
+ e.reply(`${user.nickname} 当前未在直播`);
43986
+ return true;
43987
+ }
43988
+ if (!user.room_data) {
43989
+ e.reply("未获取到直播间信息");
43990
+ return true;
43991
+ }
43992
+ const room_data = JSON.parse(user.room_data);
43993
+ images = await renderLiveImage({
43994
+ e,
43995
+ Detail_Data: {
43996
+ user_info: userinfo,
43997
+ room_data,
43998
+ live_data: await douyinFetcher.fetchLiveRoomInfo({
43999
+ room_id: user.room_id_str,
44000
+ web_rid: room_data.owner.web_rid,
44001
+ typeMode: "strict"
44002
+ })
44003
+ }
44004
+ });
44005
+ if (!images.length) {
44006
+ e.reply("渲染直播状态推送图片失败");
44007
+ return true;
44008
+ }
44009
+ break;
44010
+ }
44011
+ }
44012
+ e.reply([...images, segment.markdown("[跳转](mqqapi://forward/url?version=1&src_type=web&url_prefix=" + encodeURIComponent("https://www.douyin.com"))]);
44013
+ logger.mark(`[测试抖音推送] ${pushType}推送渲染完成`);
44014
+ return true;
44015
+ }, { businessName: "测试抖音推送" });
44016
+ /** 注册测试推送命令 */
44017
+ var testPush = Config.douyin.switch && karin$1.command(/^#测试抖音(作品|喜欢列表|推荐列表|直播状态)推送/, handleTestPush, {
44018
+ name: "kkk-测试抖音推送",
44019
+ perm: "master"
44020
+ });
44021
+ //#endregion
42995
44022
  //#region src/apps/tools.ts
42996
44023
  var reg = {
42997
44024
  douyin: /(https?:\/\/)?(www|v|jx|m|jingxuan)\.(douyin|iesdouyin)\.com/i,
@@ -43000,13 +44027,13 @@ var reg = {
43000
44027
  kuaishou: /(快手.*快手|v\.kuaishou\.com|kuaishou\.com)/,
43001
44028
  xiaohongshu: /(xiaohongshu\.com|xhslink\.com)/
43002
44029
  };
43003
- var handleDouyin = wrapWithErrorHandler(async (e) => {
43004
- if (e.msg.startsWith("#测试")) return false;
44030
+ var handleDouyin = wrapWithErrorHandler(async (e, next) => {
44031
+ if (e.msg.startsWith("#测试")) return next();
43005
44032
  const forceBurnDanmaku = /^#?弹幕解析/.test(e.msg);
43006
44033
  const urlMatch = e.msg.match(/(https?:\/\/[^\s]*\.(douyin|iesdouyin)\.com[^\s]*)/gi);
43007
44034
  if (!urlMatch) {
43008
44035
  logger.warn(`未能在消息中找到有效的抖音链接: ${e.msg}`);
43009
- return true;
44036
+ return next();
43010
44037
  }
43011
44038
  const iddata = await getDouyinID(e, String(urlMatch[0]));
43012
44039
  await new DouYin(e, iddata, { forceBurnDanmaku }).DouyinHandler(iddata);
@@ -43017,9 +44044,8 @@ var handleDouyin = wrapWithErrorHandler(async (e) => {
43017
44044
  } catch (error) {
43018
44045
  logger.debug("[统计] 记录抖音解析统计失败:", error);
43019
44046
  }
43020
- return true;
43021
44047
  }, { businessName: "抖音视频解析" });
43022
- var handleBilibili = wrapWithErrorHandler(async (e) => {
44048
+ var handleBilibili = wrapWithErrorHandler(async (e, next) => {
43023
44049
  e.msg = e.msg.replace(/\\/g, "");
43024
44050
  const forceBurnDanmaku = /^#?弹幕解析/.test(e.msg);
43025
44051
  const urlRegex = /(https?:\/\/(?:(?:www\.|m\.|t\.)?bilibili\.com|b23\.tv|bili2233\.cn)\/[a-zA-Z0-9_\-.~:\/?#[\]@!$&'()*+,;=]+)/;
@@ -43032,7 +44058,7 @@ var handleBilibili = wrapWithErrorHandler(async (e) => {
43032
44058
  else if (avRegex.test(e.msg)) url = `https://www.bilibili.com/video/${e.msg}`;
43033
44059
  if (!url) {
43034
44060
  logger.warn(`未能在消息中找到有效的B站分享链接、BV号或AV号: ${e.msg}`);
43035
- return true;
44061
+ return next();
43036
44062
  }
43037
44063
  const iddata = await getBilibiliID(url);
43038
44064
  await new Bilibili(e, iddata, { forceBurnDanmaku }).BilibiliHandler(iddata);
@@ -43043,7 +44069,6 @@ var handleBilibili = wrapWithErrorHandler(async (e) => {
43043
44069
  } catch (error) {
43044
44070
  logger.debug("[统计] 记录B站解析统计失败:", error);
43045
44071
  }
43046
- return true;
43047
44072
  }, { businessName: "B站视频解析" });
43048
44073
  var handleKuaishou = wrapWithErrorHandler(async (e) => {
43049
44074
  const kuaishouUrl = e.msg.replaceAll("\\", "").match(/(https:\/\/v\.kuaishou\.com\/\w+|https:\/\/www\.kuaishou\.com\/f\/[a-zA-Z0-9]+)/g);
@@ -43058,11 +44083,11 @@ var handleKuaishou = wrapWithErrorHandler(async (e) => {
43058
44083
  logger.debug("[统计] 记录快手解析统计失败:", error);
43059
44084
  }
43060
44085
  }, { businessName: "快手视频解析" });
43061
- var handleXiaohongshu = wrapWithErrorHandler(async (e) => {
44086
+ var handleXiaohongshu = wrapWithErrorHandler(async (e, next) => {
43062
44087
  const url = e.msg.replaceAll("\\", "").match(/https?:\/\/[^\s"'<>]+/)?.[0];
43063
44088
  if (!url) {
43064
44089
  logger.warn(`未能在消息中找到有效链接: ${e.msg}`);
43065
- return true;
44090
+ return next();
43066
44091
  }
43067
44092
  const iddata = await getXiaohongshuID(url);
43068
44093
  await new Xiaohongshu(e, iddata).XiaohongshuHandler(iddata);
@@ -43073,7 +44098,6 @@ var handleXiaohongshu = wrapWithErrorHandler(async (e) => {
43073
44098
  } catch (error) {
43074
44099
  logger.debug("[统计] 记录小红书解析统计失败:", error);
43075
44100
  }
43076
- return true;
43077
44101
  }, { businessName: "小红书视频解析" });
43078
44102
  var handlePrefix = wrapWithErrorHandler(async (e, next) => {
43079
44103
  const originalMsg = e.msg;
@@ -47020,4 +48044,4 @@ mkdirSync(`${karinPathBase}/${Root.pluginName}/data`);
47020
48044
  mkdirSync(Common.tempDri.images);
47021
48045
  mkdirSync(Common.tempDri.video);
47022
48046
  //#endregion
47023
- export { createListItemNode as $, KuaishouCommentParamsSchema as $n, emitLogError as $r, createAmagiClient as $t, webConfig as A, isNetworkErrorResult as An, BilibiliColumnInfoParamsSchema as Ar, KuaishouMethodMapping as At, BilibiliDBBase as B, douyinSign as Bn, BilibiliQrcodeStatusParamsSchema as Br, DouyinMethodToFetcher as Bt, version as C, httpLogger as Cn, BilibiliArticleCardParamsSchema as Cr, amagi as Ct, task as D, fetchData as Dn, BilibiliBangumiInfoParamsSchema as Dr, DouyinApiRoutes as Dt, removeOldFiles as E, logger$2 as En, BilibiliAv2BvParamsSchema as Er, BilibiliMethodMapping as Et, getDouyinDB as F, kuaishouSign as Fn, BilibiliEmojiParamsSchema as Fr, BilibiliFetcherMethods as Ft, createBlockquoteNode as G, validateBilibiliParams as Gn, BilibiliVideoParamsSchema as Gr, XiaohongshuFetcherMethods as Gt, renderVideoPreviewPage as H, createBoundBilibiliFetcher as Hn, BilibiliValidateCaptchaParamsSchema as Hr, KuaishouInternalMethods as Ht, getStatisticsDB as I, kuaishouApiUrls as In, BilibiliLiveParamsSchema as Ir, BilibiliInternalMethods as It, createHeadingNode as J, validateXiaohongshuParams as Jn, emitApiSuccess as Jr, toFetcherMethod as Jt, createCodeBlockNode as K, validateDouyinParams as Kn, amagiEvents as Kr, XiaohongshuInternalMethods as Kt, initAllDatabases as L, douyinFetcher$1 as Ln, BilibiliLoginParamsSchema as Lr, BilibiliMethodToFetcher as Lt, cleanOldDynamicCache as M, xiaohongshuFetcher$1 as Mn, BilibiliCommentReplyParamsSchema as Mr, XiaohongshuMethodMapping as Mt, douyinDBInstance as N, createBoundKuaishouFetcher as Nn, BilibiliDanmakuParamsSchema as Nr, getApiRoute as Nt, testWrapWithErrorHandler as O, fetchResponse as On, BilibiliBangumiStreamParamsSchema as Or, DouyinMethodMapping as Ot, getBilibiliDB as P, kuaishouFetcher$1 as Pn, BilibiliDynamicParamsSchema as Pr, getEnglishMethodName as Pt, createLinkCardNode as Q, xiaohongshuSign as Qn, emitLogDebug as Qr, CommentType as Qt, StatisticsDBBase as R, createBoundDouyinFetcher as Rn, BilibiliMethodRoutes as Rr, DouyinFetcherMethods as Rt, help as S, qtparam as Sn, BilibiliApplyCaptchaParamsSchema as Sr, CreateApp as St, dylogin as T, logMiddleware as Tn, BilibiliArticleParamsSchema as Tr, BilibiliApiRoutes as Tt, renderRichTextToReact as U, createErrorResponse as Un, BilibiliValidationSchemas as Ur, KuaishouMethodToFetcher as Ut, reactServerRender as V, bilibiliFetcher$1 as Vn, BilibiliUserParamsSchema as Vr, KuaishouFetcherMethods as Vt, createAtNode as W, createSuccessResponse$1 as Wn, BilibiliVideoDownloadParamsSchema as Wr, MethodMaps as Wt, createImageNode as X, XiaohongshuValidationSchemas as Xn, emitHttpResponse as Xr, AdditionalType as Xt, createHorizontalRuleNode as Y, XiaohongshuMethodRoutes as Yn, emitHttpRequest as Yr, DynamicType as Yt, createLineBreakNode as Z, xiaohongshuApiUrls as Zn, emitLog as Zr, MajorType as Zt, douyinPushList as _, bilibiliErrorCodeMap as _n, DouyinSearchParamsSchema as _r, bilibiliFetcher as _t, bilibiliAPP as a, bilibili$1 as ai, createKuaishouRoutes as an, KuaishouValidationSchemas as ar, createSearchKeywordNode as at, setbiliPush as b, av2bv as bn, DouyinValidationSchemas as br, reloadAmagiConfig as bt, prefix as c, getBilibiliData as ci, douyinUtils as cn, DouyinCommentReplyParamsSchema as cr, createViewPictureNode as ct, groupStatistics as d, Root as di, douyin$1 as dn, DouyinEmojiProParamsSchema as dr, extractRichTextPlainText as dt, emitLogInfo as ei, xiaohongshuUtils as en, KuaishouEmojiParamsSchema as er, createListNode as et, qrLogin as f, bilibiliUtils as fn, DouyinHotWordsParamsSchema as fr, normalizeRichTextNodes as ft, douyinPush as g, handleError as gn, DouyinQrcodeParamsSchema as gr, amagiClient as gt, changeBotID as h, ValidationError as hn, DouyinMusicParamsSchema as hr, SOFT_ERROR_CODES as ht, update as i, emitNetworkRetry as ii, kuaishouUtils as in, KuaishouUserWorkListParamsSchema as ir, createRichTextDocument as it, bilibiliDBInstance as j, createBoundXiaohongshuFetcher as jn, BilibiliCommentParamsSchema as jr, XiaohongshuApiRoutes as jt, template_default as k, getHeadersAndData as kn, BilibiliBv2AvParamsSchema as kr, KuaishouApiRoutes as kt, xiaohongshuAPP as l, getDouyinData as li, createDouyinRoutes as ln, DouyinDanmakuParamsSchema as lr, createVoteNode as lt, bilibiliPushList as m, ApiError as mn, DouyinMethodRoutes as mr, AmagiError as mt, kkkUpdateCommand as n, emitLogWarn as ni, createBoundXiaohongshuApi as nn, KuaishouMethodRoutes as nr, createMentionNode as nt, douyinAPP as o, createBoundBilibiliApi as oi, createBoundKuaishouApi as on, KuaishouVideoParamsSchema as or, createTextNode as ot, bilibiliPush as p, createBilibiliRoutes as pn, DouyinLiveRoomParamsSchema as pr, AmagiBase as pt, createEmojiNode as q, validateKuaishouParams as qn, emitApiError as qr, XiaohongshuMethodToFetcher as qt, kkkUpdateTest as r, emitNetworkError as ri, xiaohongshu$1 as rn, KuaishouUserProfileParamsSchema as rr, createParagraphNode as rt, kuaishouAPP as s, bilibiliApiUrls as si, kuaishou$1 as sn, DouyinCommentParamsSchema as sr, createTopicNode as st, kkkUpdate as t, emitLogMark as ti, createXiaohongshuRoutes as tn, KuaishouLiveRoomInfoParamsSchema as tr, createLotteryNode as tt, globalStatistics as u, getKuaishouData as ui, createBoundDouyinApi as un, DouyinEmojiListParamsSchema as ur, createWebLinkNode as ut, forcePush as v, wbi_sign as vn, DouyinUserListParamsSchema as vr, douyinFetcher as vt, biLogin as w, initLogger as wn, BilibiliArticleInfoParamsSchema as wr, amagiClient$1 as wt, setdyPush as x, bv2av as xn, DouyinWorkParamsSchema as xr, softFetch as xt, globalIgnore as y, parseDmSegMobileReply as yn, DouyinUserParamsSchema as yr, kuaishouFetcher as yt, DouyinDBBase as z, douyinApiUrls as zn, BilibiliQrcodeParamsSchema as zr, DouyinInternalMethods as zt };
48047
+ export { createLineBreakNode as $, xiaohongshuApiUrls as $n, emitLog as $r, MajorType as $t, template_default as A, fetchResponse as An, BilibiliBangumiStreamParamsSchema as Ar, DouyinMethodMapping as At, DouyinDBBase as B, createBoundDouyinFetcher as Bn, BilibiliMethodRoutes as Br, DouyinFetcherMethods as Bt, help as C, bv2av as Cn, DouyinWorkParamsSchema as Cr, softFetch as Ct, removeOldFiles as D, logMiddleware as Dn, BilibiliArticleParamsSchema as Dr, BilibiliApiRoutes as Dt, dylogin as E, initLogger as En, BilibiliArticleInfoParamsSchema as Er, amagiClient$1 as Et, getBilibiliDB as F, createBoundKuaishouFetcher as Fn, BilibiliDanmakuParamsSchema as Fr, getApiRoute as Ft, createAtNode as G, createErrorResponse as Gn, BilibiliValidationSchemas as Gr, KuaishouMethodToFetcher as Gt, reactServerRender as H, douyinSign as Hn, BilibiliQrcodeStatusParamsSchema as Hr, DouyinMethodToFetcher as Ht, getDouyinDB as I, kuaishouFetcher$1 as In, BilibiliDynamicParamsSchema as Ir, getEnglishMethodName as It, createEmojiNode as J, validateDouyinParams as Jn, amagiEvents as Jr, XiaohongshuInternalMethods as Jt, createBlockquoteNode as K, createSuccessResponse$1 as Kn, BilibiliVideoDownloadParamsSchema as Kr, MethodMaps as Kt, getStatisticsDB as L, kuaishouSign as Ln, BilibiliEmojiParamsSchema as Lr, BilibiliFetcherMethods as Lt, bilibiliDBInstance as M, isNetworkErrorResult as Mn, BilibiliColumnInfoParamsSchema as Mr, KuaishouMethodMapping as Mt, cleanOldDynamicCache as N, createBoundXiaohongshuFetcher as Nn, BilibiliCommentParamsSchema as Nr, XiaohongshuApiRoutes as Nt, task as O, logger$2 as On, BilibiliAv2BvParamsSchema as Or, BilibiliMethodMapping as Ot, douyinDBInstance as P, xiaohongshuFetcher$1 as Pn, BilibiliCommentReplyParamsSchema as Pr, XiaohongshuMethodMapping as Pt, createImageNode as Q, XiaohongshuValidationSchemas as Qn, emitHttpResponse as Qr, AdditionalType as Qt, initAllDatabases as R, kuaishouApiUrls as Rn, BilibiliLiveParamsSchema as Rr, BilibiliInternalMethods as Rt, setdyPush as S, av2bv as Sn, DouyinValidationSchemas as Sr, reloadAmagiConfig as St, biLogin as T, httpLogger as Tn, BilibiliArticleCardParamsSchema as Tr, amagi as Tt, renderVideoPreviewPage as U, bilibiliFetcher$1 as Un, BilibiliUserParamsSchema as Ur, KuaishouFetcherMethods as Ut, BilibiliDBBase as V, douyinApiUrls as Vn, BilibiliQrcodeParamsSchema as Vr, DouyinInternalMethods as Vt, renderRichTextToReact as W, createBoundBilibiliFetcher as Wn, BilibiliValidateCaptchaParamsSchema as Wr, KuaishouInternalMethods as Wt, createHeadingNode as X, validateXiaohongshuParams as Xn, emitApiSuccess as Xr, toFetcherMethod as Xt, createHashtagNode as Y, validateKuaishouParams as Yn, emitApiError as Yr, XiaohongshuMethodToFetcher as Yt, createHorizontalRuleNode as Z, XiaohongshuMethodRoutes as Zn, emitHttpRequest as Zr, DynamicType as Zt, douyinPush as _, ValidationError as _n, DouyinMusicParamsSchema as _r, SOFT_ERROR_CODES as _t, bilibiliAPP as a, emitNetworkError as ai, xiaohongshu$1 as an, KuaishouUserProfileParamsSchema as ar, createParagraphNode as at, globalIgnore as b, wbi_sign as bn, DouyinUserListParamsSchema as br, douyinFetcher as bt, prefix as c, createBoundBilibiliApi as ci, createBoundKuaishouApi as cn, KuaishouVideoParamsSchema as cr, createTextNode as ct, globalStatistics as d, getDouyinData as di, createDouyinRoutes as dn, DouyinDanmakuParamsSchema as dr, createVoteNode as dt, emitLogDebug as ei, CommentType as en, xiaohongshuSign as er, createLinkCardNode as et, groupStatistics as f, getKuaishouData as fi, createBoundDouyinApi as fn, DouyinEmojiListParamsSchema as fr, createWebLinkNode as ft, changeBotID as g, ApiError as gn, DouyinMethodRoutes as gr, AmagiError as gt, bilibiliPushList as h, createBilibiliRoutes as hn, DouyinLiveRoomParamsSchema as hr, AmagiBase as ht, update as i, emitLogWarn as ii, createBoundXiaohongshuApi as in, KuaishouMethodRoutes as ir, createMentionNode as it, webConfig as j, getHeadersAndData as jn, BilibiliBv2AvParamsSchema as jr, KuaishouApiRoutes as jt, testWrapWithErrorHandler as k, fetchData as kn, BilibiliBangumiInfoParamsSchema as kr, DouyinApiRoutes as kt, xiaohongshuAPP as l, bilibiliApiUrls as li, kuaishou$1 as ln, DouyinCommentParamsSchema as lr, createTopicNode as lt, bilibiliPush as m, bilibiliUtils as mn, DouyinHotWordsParamsSchema as mr, normalizeRichTextNodes as mt, kkkUpdateCommand as n, emitLogInfo as ni, xiaohongshuUtils as nn, KuaishouEmojiParamsSchema as nr, createListNode as nt, douyinAPP as o, emitNetworkRetry as oi, kuaishouUtils as on, KuaishouUserWorkListParamsSchema as or, createRichTextDocument as ot, qrLogin as p, Root as pi, douyin$1 as pn, DouyinEmojiProParamsSchema as pr, extractRichTextPlainText as pt, createCodeBlockNode as q, validateBilibiliParams as qn, BilibiliVideoParamsSchema as qr, XiaohongshuFetcherMethods as qt, kkkUpdateTest as r, emitLogMark as ri, createXiaohongshuRoutes as rn, KuaishouLiveRoomInfoParamsSchema as rr, createLotteryNode as rt, kuaishouAPP as s, bilibili$1 as si, createKuaishouRoutes as sn, KuaishouValidationSchemas as sr, createSearchKeywordNode as st, kkkUpdate as t, emitLogError as ti, createAmagiClient as tn, KuaishouCommentParamsSchema as tr, createListItemNode as tt, testPush as u, getBilibiliData as ui, douyinUtils as un, DouyinCommentReplyParamsSchema as ur, createViewPictureNode as ut, douyinPushList as v, handleError as vn, DouyinQrcodeParamsSchema as vr, amagiClient as vt, version as w, qtparam as wn, BilibiliApplyCaptchaParamsSchema as wr, CreateApp as wt, setbiliPush as x, parseDmSegMobileReply as xn, DouyinUserParamsSchema as xr, kuaishouFetcher as xt, forcePush as y, bilibiliErrorCodeMap as yn, DouyinSearchParamsSchema as yr, bilibiliFetcher as yt, StatisticsDBBase as z, douyinFetcher$1 as zn, BilibiliLoginParamsSchema as zr, BilibiliMethodToFetcher as zt };