karin-plugin-kkk 2.23.1 → 2.23.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,18 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ## [2.23.2](https://github.com/ikenxuan/karin-plugin-kkk/compare/v2.23.1...v2.23.2) (2026-03-10)
6
+
7
+
8
+ ### 🐛 错误修复
9
+
10
+ * **douyin:** 优化共创者信息显示并添加订阅者角色标识 ([bb16787](https://github.com/ikenxuan/karin-plugin-kkk/commit/bb167878719a5351ef0a30d97fa4331f88d39ff9))
11
+
12
+
13
+ ### ♻️ 代码重构
14
+
15
+ * **douyin:** 重构作品类型判断逻辑 ([72b09c6](https://github.com/ikenxuan/karin-plugin-kkk/commit/72b09c6c98c90fec7b33bdacf3aa36d1bca0e707))
16
+
5
17
  ## [2.23.1](https://github.com/ikenxuan/karin-plugin-kkk/compare/v2.23.0...v2.23.1) (2026-03-09)
6
18
 
7
19
 
package/lib/apps/admin.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import "../core_chunk/rolldown-runtime-BMXAG3ag.js";
2
- import { C as biLogin, E as task, T as removeOldFiles, w as dylogin } from "../core_chunk/main-BdZy8WYB.js";
3
- import "../core_chunk/vendor-DxfKHvj-.js";
4
- import "../core_chunk/template-CnW8M_F0.js";
2
+ import { C as biLogin, E as task, T as removeOldFiles, w as dylogin } from "../core_chunk/main-BQn-mQch.js";
3
+ import "../core_chunk/vendor-9pKTNH6x.js";
4
+ import "../core_chunk/template-2ApQpQ8R.js";
5
5
  export { biLogin, dylogin, removeOldFiles, task };
package/lib/apps/help.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import "../core_chunk/rolldown-runtime-BMXAG3ag.js";
2
- import { S as version, x as help } from "../core_chunk/main-BdZy8WYB.js";
3
- import "../core_chunk/vendor-DxfKHvj-.js";
4
- import "../core_chunk/template-CnW8M_F0.js";
2
+ import { S as version, x as help } from "../core_chunk/main-BQn-mQch.js";
3
+ import "../core_chunk/vendor-9pKTNH6x.js";
4
+ import "../core_chunk/template-2ApQpQ8R.js";
5
5
  export { help, version };
package/lib/apps/push.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import "../core_chunk/rolldown-runtime-BMXAG3ag.js";
2
- import { _ as forcePush, b as testDouyinPush, f as bilibiliPush, g as douyinPushList, h as douyinPush, m as changeBotID, p as bilibiliPushList, v as setbiliPush, y as setdyPush } from "../core_chunk/main-BdZy8WYB.js";
3
- import "../core_chunk/vendor-DxfKHvj-.js";
4
- import "../core_chunk/template-CnW8M_F0.js";
2
+ import { _ as forcePush, b as testDouyinPush, f as bilibiliPush, g as douyinPushList, h as douyinPush, m as changeBotID, p as bilibiliPushList, v as setbiliPush, y as setdyPush } from "../core_chunk/main-BQn-mQch.js";
3
+ import "../core_chunk/vendor-9pKTNH6x.js";
4
+ import "../core_chunk/template-2ApQpQ8R.js";
5
5
  export { bilibiliPush, bilibiliPushList, changeBotID, douyinPush, douyinPushList, forcePush, setbiliPush, setdyPush, testDouyinPush };
@@ -1,5 +1,5 @@
1
1
  import "../core_chunk/rolldown-runtime-BMXAG3ag.js";
2
- import { d as qrLogin } from "../core_chunk/main-BdZy8WYB.js";
3
- import "../core_chunk/vendor-DxfKHvj-.js";
4
- import "../core_chunk/template-CnW8M_F0.js";
2
+ import { d as qrLogin } from "../core_chunk/main-BQn-mQch.js";
3
+ import "../core_chunk/vendor-9pKTNH6x.js";
4
+ import "../core_chunk/template-2ApQpQ8R.js";
5
5
  export { qrLogin };
@@ -1,5 +1,5 @@
1
1
  import "../core_chunk/rolldown-runtime-BMXAG3ag.js";
2
- import { l as globalStatistics, u as groupStatistics } from "../core_chunk/main-BdZy8WYB.js";
3
- import "../core_chunk/vendor-DxfKHvj-.js";
4
- import "../core_chunk/template-CnW8M_F0.js";
2
+ import { l as globalStatistics, u as groupStatistics } from "../core_chunk/main-BQn-mQch.js";
3
+ import "../core_chunk/vendor-9pKTNH6x.js";
4
+ import "../core_chunk/template-2ApQpQ8R.js";
5
5
  export { globalStatistics, groupStatistics };
package/lib/apps/tools.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import "../core_chunk/rolldown-runtime-BMXAG3ag.js";
2
- import { a as douyinAPP, c as xiaohongshuAPP, i as bilibiliAPP, o as kuaishouAPP, s as prefix } from "../core_chunk/main-BdZy8WYB.js";
3
- import "../core_chunk/vendor-DxfKHvj-.js";
4
- import "../core_chunk/template-CnW8M_F0.js";
2
+ import { a as douyinAPP, c as xiaohongshuAPP, i as bilibiliAPP, o as kuaishouAPP, s as prefix } from "../core_chunk/main-BQn-mQch.js";
3
+ import "../core_chunk/vendor-9pKTNH6x.js";
4
+ import "../core_chunk/template-2ApQpQ8R.js";
5
5
  export { bilibiliAPP, douyinAPP, kuaishouAPP, prefix, xiaohongshuAPP };
@@ -1,5 +1,5 @@
1
1
  import "../core_chunk/rolldown-runtime-BMXAG3ag.js";
2
- import { n as kkkUpdateCommand, r as update, t as kkkUpdate } from "../core_chunk/main-BdZy8WYB.js";
3
- import "../core_chunk/vendor-DxfKHvj-.js";
4
- import "../core_chunk/template-CnW8M_F0.js";
2
+ import { n as kkkUpdateCommand, r as update, t as kkkUpdate } from "../core_chunk/main-BQn-mQch.js";
3
+ import "../core_chunk/vendor-9pKTNH6x.js";
4
+ import "../core_chunk/template-2ApQpQ8R.js";
5
5
  export { kkkUpdate, kkkUpdateCommand, update };
@@ -1,10 +1,10 @@
1
1
  {
2
- "version": "2.23.1",
3
- "buildTime": "2026-03-09T16:21:53.700Z",
4
- "buildTimestamp": 1773073313701,
2
+ "version": "2.23.2",
3
+ "buildTime": "2026-03-10T12:18:40.775Z",
4
+ "buildTimestamp": 1773145120775,
5
5
  "name": "karin-plugin-kkk",
6
6
  "description": "Karin 的「抖音」「B 站」视频解析/动态推送插件",
7
7
  "homepage": "https://github.com/ikenxuan/karin-plugin-kkk",
8
- "commitHash": "3c5a21ee25d05d410878aebfb0f52b71ba7dc7f2",
9
- "shortCommitHash": "3c5a21ee"
8
+ "commitHash": "b3481ecef05b4f18a257336b152d1171adf9a029",
9
+ "shortCommitHash": "b3481ece"
10
10
  }
@@ -1,6 +1,6 @@
1
1
  import { n as __esmMin, o as __toESM, r as __export } from "./rolldown-runtime-BMXAG3ag.js";
2
- import { A as init_locale, An as init_zod, Cn as Chalk, Dn as axios_default, En as init_axios, On as Xhshow, Sn as require_protobufjs, Tn as AxiosError$1, _n as require_png, a as Window, bn as require_heic_decode, dt as init_date_fns, ft as fromUnixTime, ht as differenceInSeconds, i as init_lib, j as zhCN, jn as zod_default, kn as init_dist, mt as format, n as require_lib, pt as formatDistanceToNow, r as require_qr_code_styling, t as require_dist, vn as require_jsQR, wn as init_source, xn as require_express, yn as require_jpeg_js } from "./vendor-DxfKHvj-.js";
3
- import { n as init_client, r as reactServerRender } from "./template-CnW8M_F0.js";
2
+ import { A as init_locale, An as init_zod, Cn as Chalk, Dn as axios_default, En as init_axios, On as Xhshow, Sn as require_protobufjs, Tn as AxiosError$1, _n as require_png, a as Window, bn as require_heic_decode, dt as init_date_fns, ft as fromUnixTime, ht as differenceInSeconds, i as init_lib, j as zhCN, jn as zod_default, kn as init_dist, mt as format, n as require_lib, pt as formatDistanceToNow, r as require_qr_code_styling, t as require_dist, vn as require_jsQR, wn as init_source, xn as require_express, yn as require_jpeg_js } from "./vendor-9pKTNH6x.js";
3
+ import { n as init_client, r as reactServerRender } from "./template-2ApQpQ8R.js";
4
4
  import { createRequire } from "node:module";
5
5
  import karin$1, { BOT_CONNECT, app, authMiddleware, checkPkgUpdate, checkPort, common, components, config, copyConfigSync, createBadRequestResponse, createNotFoundResponse, createServerErrorResponse, createSuccessResponse, db, defineConfig, ffmpeg, ffprobe, filesByExt, getBot, hooks, karin, karinPathHtml, karinPathTemp, logger, logs, mkdirSync, range, render, requireFileSync, restart, segment, updatePkg, watch } from "node-karin";
6
6
  import fs from "node:fs";
@@ -18228,7 +18228,6 @@ var img;
18228
18228
  var DouYin = class extends Base {
18229
18229
  e;
18230
18230
  type;
18231
- is_mp4;
18232
18231
  is_slides;
18233
18232
  forceBurnDanmaku;
18234
18233
  hasProcessedLiveImage;
@@ -18239,7 +18238,6 @@ var DouYin = class extends Base {
18239
18238
  super(e);
18240
18239
  this.e = e;
18241
18240
  this.type = iddata?.type;
18242
- this.is_mp4 = iddata?.is_mp4;
18243
18241
  this.is_slides = false;
18244
18242
  this.forceBurnDanmaku = options?.forceBurnDanmaku ?? false;
18245
18243
  this.hasProcessedLiveImage = false;
@@ -18283,7 +18281,6 @@ var DouYin = class extends Base {
18283
18281
  const aweme_type = VideoData.data.aweme_detail.aweme_type;
18284
18282
  const isArticle = aweme_type === 163;
18285
18283
  const isVideo = aweme_type === 0;
18286
- if (this.is_mp4 === void 0) this.is_mp4 = isVideo;
18287
18284
  const CommentsData = await this.amagi.douyin.fetcher.fetchWorkComments({
18288
18285
  aweme_id: data$1.aweme_id,
18289
18286
  number: Config.douyin.numcomment,
@@ -18294,7 +18291,7 @@ var DouYin = class extends Base {
18294
18291
  let g_title;
18295
18292
  let imagenum = 0;
18296
18293
  const image_res = [];
18297
- if (this.is_mp4 === false && !isArticle) switch (true) {
18294
+ if (!isVideo && !isArticle) switch (true) {
18298
18295
  case this.is_slides === false && VideoData.data.aweme_detail.images !== null: {
18299
18296
  const image_data = [];
18300
18297
  const imageres = [];
@@ -18514,7 +18511,7 @@ var DouYin = class extends Base {
18514
18511
  let music_url = "";
18515
18512
  if (music.play_url.uri === "") music_url = JSON.parse(music.extra).original_song_url;
18516
18513
  else music_url = music.play_url.uri;
18517
- if (this.is_mp4 === false && Config.app.removeCache === false && music_url !== void 0) try {
18514
+ if (!isVideo && Config.app.removeCache === false && music_url !== void 0) try {
18518
18515
  const path$1 = Common.tempDri.images + `${g_title}/BGM.mp3`;
18519
18516
  await new Network({
18520
18517
  url: music_url,
@@ -18523,11 +18520,11 @@ var DouYin = class extends Base {
18523
18520
  } catch (error) {
18524
18521
  console.log(error);
18525
18522
  }
18526
- music_url && (this.is_mp4 === false || isArticle) && music_url !== void 0 && !this.hasProcessedLiveImage && await this.e.reply(segment.record(music_url, false));
18523
+ music_url && !isVideo && music_url !== void 0 && !this.hasProcessedLiveImage && await this.e.reply(segment.record(music_url, false));
18527
18524
  }
18528
18525
  let FPS;
18529
18526
  let video = null;
18530
- if (this.is_mp4) {
18527
+ if (isVideo) {
18531
18528
  video = VideoData.data.aweme_detail.video;
18532
18529
  FPS = video.bit_rate[0]?.FPS ?? "获取失败";
18533
18530
  logger.debug(`开始排除不符合条件的视频分辨率;\n\n 共拥有${logger.yellow(video.bit_rate.length)}个视频源\n\n 视频ID:${logger.green(VideoData.data.aweme_detail.aweme_id)}\n\n 分享链接:${logger.green(VideoData.data.aweme_detail.share_url)}\n `);
@@ -18545,7 +18542,7 @@ var DouYin = class extends Base {
18545
18542
  if (Config.douyin.sendContent.includes("info")) if (Config.douyin.videoInfoMode === "text") {
18546
18543
  const replyContent = [];
18547
18544
  const { digg_count, share_count, collect_count, comment_count, recommend_count } = VideoData.data.aweme_detail.statistics;
18548
- const coverUrl = await processImageUrl(isArticle ? VideoData.data.aweme_detail.video.origin_cover.url_list[0] : this.is_mp4 ? VideoData.data.aweme_detail.video.animated_cover?.url_list[0] ?? VideoData.data.aweme_detail.video.cover.url_list[0] : VideoData.data.aweme_detail.images[0].url_list[0], VideoData.data.aweme_detail.desc);
18545
+ const coverUrl = await processImageUrl(isArticle ? VideoData.data.aweme_detail.video.origin_cover.url_list[0] : isVideo ? VideoData.data.aweme_detail.video.animated_cover?.url_list[0] ?? VideoData.data.aweme_detail.video.cover.url_list[0] : VideoData.data.aweme_detail.images[0].url_list[0], VideoData.data.aweme_detail.desc);
18549
18546
  const contentMap = {
18550
18547
  cover: segment.image(coverUrl),
18551
18548
  title: segment.text(`\n📺 标题: ${VideoData.data.aweme_detail.desc}\n`),
@@ -18583,11 +18580,11 @@ var DouYin = class extends Base {
18583
18580
  gender: userProfile.data.user.gender ?? 0,
18584
18581
  user_age: userProfile.data.user.user_age ?? 0
18585
18582
  } : void 0,
18586
- image_url: isArticle ? VideoData.data.aweme_detail.video.origin_cover.url_list[0] : this.is_mp4 ? VideoData.data.aweme_detail.video.animated_cover?.url_list[0] ?? VideoData.data.aweme_detail.video.dynamic_cover?.url_list[0] ?? VideoData.data.aweme_detail.video.cover_original_scale?.url_list[0] ?? VideoData.data.aweme_detail.video.cover.url_list[0] : VideoData.data.aweme_detail.images[0].url_list[0],
18583
+ image_url: isArticle ? VideoData.data.aweme_detail.video.origin_cover.url_list[0] : isVideo ? VideoData.data.aweme_detail.video.animated_cover?.url_list[0] ?? VideoData.data.aweme_detail.video.dynamic_cover?.url_list[0] ?? VideoData.data.aweme_detail.video.cover_original_scale?.url_list[0] ?? VideoData.data.aweme_detail.video.cover.url_list[0] : VideoData.data.aweme_detail.images[0].url_list[0],
18587
18584
  cover_size: isArticle ? VideoData.data.aweme_detail.video.origin_cover ? {
18588
18585
  width: VideoData.data.aweme_detail.video.origin_cover.width,
18589
18586
  height: VideoData.data.aweme_detail.video.origin_cover.height
18590
- } : void 0 : this.is_mp4 ? VideoData.data.aweme_detail.video.cover ? {
18587
+ } : void 0 : isVideo ? VideoData.data.aweme_detail.video.cover ? {
18591
18588
  width: VideoData.data.aweme_detail.video.cover_original_scale.width,
18592
18589
  height: VideoData.data.aweme_detail.video.cover_original_scale.height
18593
18590
  } : void 0 : VideoData.data.aweme_detail.images?.[0] ? {
@@ -18600,7 +18597,7 @@ var DouYin = class extends Base {
18600
18597
  title: VideoData.data.aweme_detail.music.title,
18601
18598
  cover: VideoData.data.aweme_detail.music.cover_hd?.url_list[0] ?? VideoData.data.aweme_detail.music.cover_large?.url_list[0]
18602
18599
  } : void 0,
18603
- video: this.is_mp4 ? {
18600
+ video: isVideo ? {
18604
18601
  duration: VideoData.data.aweme_detail.video.duration,
18605
18602
  width: VideoData.data.aweme_detail.video.width,
18606
18603
  height: VideoData.data.aweme_detail.video.height,
@@ -18619,16 +18616,16 @@ var DouYin = class extends Base {
18619
18616
  for (const item of VideoData.data.aweme_detail.suggest_words.suggest_words) if (item.words && item.scene === "comment_top_rec") for (const v of item.words) v.word && suggest.push(v.word);
18620
18617
  }
18621
18618
  const img$2 = await Render("douyin/comment", {
18622
- Type: isArticle ? "文章" : this.is_mp4 ? "视频" : this.is_slides ? "合辑" : "图集",
18619
+ Type: isArticle ? "文章" : isVideo ? "视频" : this.is_slides ? "合辑" : "图集",
18623
18620
  CommentsData: douyinCommentsRes.CommentsData,
18624
18621
  CommentLength: Config.douyin.realCommentCount ? VideoData.data.aweme_detail.statistics.comment_count : douyinCommentsRes.CommentsData.length ?? 0,
18625
- share_url: this.is_mp4 ? `https://aweme.snssdk.com/aweme/v1/play/?video_id=${VideoData.data.aweme_detail.video.play_addr.uri}&ratio=1080p&line=0` : VideoData.data.aweme_detail.share_url,
18622
+ share_url: isVideo ? `https://aweme.snssdk.com/aweme/v1/play/?video_id=${VideoData.data.aweme_detail.video.play_addr.uri}&ratio=1080p&line=0` : VideoData.data.aweme_detail.share_url,
18626
18623
  VideoSize: mp4size,
18627
18624
  VideoFPS: FPS,
18628
18625
  ImageLength: imagenum,
18629
18626
  Region: VideoData.data.aweme_detail.region,
18630
18627
  suggestWrod: suggest,
18631
- Resolution: this.is_mp4 && video ? `${video.bit_rate[0].play_addr.width} x ${video.bit_rate[0].play_addr.height}` : null,
18628
+ Resolution: isVideo && video ? `${video.bit_rate[0].play_addr.width} x ${video.bit_rate[0].play_addr.height}` : null,
18632
18629
  maxDepth: Config.douyin.subCommentDepth
18633
18630
  });
18634
18631
  const messageElements = [];
@@ -18648,7 +18645,7 @@ var DouYin = class extends Base {
18648
18645
  this.e.reply(img$2);
18649
18646
  }
18650
18647
  }
18651
- if (this.is_mp4 && !isArticle && Config.douyin.sendContent.includes("video")) {
18648
+ if (isVideo && !isArticle && Config.douyin.sendContent.includes("video")) {
18652
18649
  let danmakuList = [];
18653
18650
  if ((this.forceBurnDanmaku || Config.douyin.burnDanmaku) && video) try {
18654
18651
  const duration = video.duration;
@@ -19015,6 +19012,13 @@ function getWorkCoverUrl(workTypeInfo, data$1) {
19015
19012
  }
19016
19013
  return "";
19017
19014
  }
19015
+ function getWorkTypeDisplayName(workTypeInfo) {
19016
+ if (workTypeInfo.isVideo) return "视频";
19017
+ if (workTypeInfo.isGallery) return "图集";
19018
+ if (workTypeInfo.isCollection) return "合辑";
19019
+ if (workTypeInfo.isArticle) return "文章";
19020
+ return "未知";
19021
+ }
19018
19022
  const getDouyinID = async (event, url, log = true) => {
19019
19023
  const resp = await axios.get(url, {
19020
19024
  headers: { "User-Agent": "Apifox/1.0.0 (https://apifox.com)" },
@@ -19365,10 +19369,7 @@ var DouYinpush = class extends Base {
19365
19369
  const skip = await skipDynamic(pushItem);
19366
19370
  skip && logger.warn(`作品 https://www.douyin.com/video/${actualAwemeId} 已被处理,跳过`);
19367
19371
  let img$2 = [];
19368
- let iddata = {
19369
- is_mp4: true,
19370
- type: "one_work"
19371
- };
19372
+ let iddata = { type: "one_work" };
19372
19373
  if (!skip) iddata = await getDouyinID(this.e, Detail_Data.share_url ?? "https://live.douyin.com/" + Detail_Data.room_data?.owner.web_rid, false);
19373
19374
  if (!skip) if (pushItem.pushType === "live" && "room_data" in pushItem.Detail_Data && Detail_Data.live_data) img$2 = await Render("douyin/live", {
19374
19375
  image_url: Detail_Data.live_data.data.data.data[0]?.cover?.url_list[0] ?? Detail_Data.live_data.data.data.qrcode_url,
@@ -19466,7 +19467,7 @@ var DouYinpush = class extends Base {
19466
19467
  create_time: format(fromUnixTime(pushItem.create_time), "yyyy-MM-dd HH:mm"),
19467
19468
  avater_url: "https://p3-pc.douyinpic.com/aweme/1080x1080/" + Detail_Data.user_info.data.user.avatar_larger.uri,
19468
19469
  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`,
19469
- username: Detail_Data.author.nickname,
19470
+ username: Detail_Data.user_info.data.user.nickname,
19470
19471
  "抖音号": Detail_Data.user_info.data.user.unique_id === "" ? Detail_Data.user_info.data.user.short_id : Detail_Data.user_info.data.user.unique_id,
19471
19472
  "粉丝": this.count(Detail_Data.user_info.data.user.follower_count),
19472
19473
  "获赞": this.count(Detail_Data.user_info.data.user.total_favorited),
@@ -19476,22 +19477,23 @@ var DouYinpush = class extends Base {
19476
19477
  const raw = Detail_Data.cooperation_info;
19477
19478
  if (!raw) return void 0;
19478
19479
  const rawCreators = Array.isArray(raw.co_creators) ? raw.co_creators : [];
19479
- const author = Detail_Data.author;
19480
- const authorUid = author?.uid;
19481
- const authorSecUid = author?.sec_uid;
19482
- const authorNickname = author?.nickname;
19483
- const authorInCreators = rawCreators.some((c) => authorUid && c.uid && c.uid === authorUid || authorSecUid && c.sec_uid && c.sec_uid === authorSecUid || authorNickname && c.nickname && c.nickname === authorNickname);
19484
- const co_creators = rawCreators.map((c) => {
19485
- const firstUrl = c.avatar_thumb?.url_list?.[0] ?? (c.avatar_thumb?.uri ? `https://p3.douyinpic.com/${c.avatar_thumb.uri}` : void 0);
19486
- return {
19487
- avatar_thumb: firstUrl ? { url_list: [firstUrl] } : void 0,
19488
- nickname: c.nickname,
19489
- role_title: c.role_title
19490
- };
19480
+ const subscriberUid = Detail_Data.user_info.data.user.uid;
19481
+ const subscriberSecUid = Detail_Data.user_info.data.user.sec_uid;
19482
+ const subscriberInCreators = rawCreators.find((c) => subscriberUid && c.uid && c.uid === subscriberUid || subscriberSecUid && c.sec_uid && c.sec_uid === subscriberSecUid);
19483
+ const co_creators = rawCreators.map((c) => ({
19484
+ avatar_url: c.avatar_thumb?.url_list?.[0] ?? (c.avatar_thumb?.uri ? `https://p3.douyinpic.com/${c.avatar_thumb.uri}` : void 0),
19485
+ nickname: c.nickname,
19486
+ role_title: c.role_title
19487
+ }));
19488
+ 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({
19489
+ 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),
19490
+ nickname: Detail_Data.author.nickname,
19491
+ role_title: "作者"
19491
19492
  });
19492
19493
  return {
19493
- co_creator_nums: Math.max(Number(raw.co_creator_nums || 0), co_creators.length) + (authorInCreators ? 0 : 1),
19494
- co_creators
19494
+ co_creator_nums: Math.max(Number(raw.co_creator_nums || 0), co_creators.length),
19495
+ co_creators,
19496
+ 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)
19495
19497
  };
19496
19498
  })()
19497
19499
  });
@@ -19505,8 +19507,9 @@ var DouYinpush = class extends Base {
19505
19507
  status = await karin$1.sendMsg(botId, Contact, img$2 ? [...img$2] : []);
19506
19508
  if (pushItem.pushType === "live" && "room_data" in pushItem.Detail_Data && status.message_id) await douyinDBInstance.updateLiveStatus(pushItem.sec_uid, true);
19507
19509
  if (Config.douyin.push.parsedynamic && status.message_id) {
19508
- logger.debug(`开始解析作品,类型为:${iddata.is_mp4 ? "视频" : "图集"}`);
19509
- if (iddata.is_mp4) try {
19510
+ const workTypeInfo = getWorkTypeInfo(Detail_Data);
19511
+ logger.debug(`开始解析作品,类型为:${getWorkTypeDisplayName(workTypeInfo)}`);
19512
+ if (workTypeInfo.isVideo) try {
19510
19513
  let downloadUrl = `https://aweme.snssdk.com/aweme/v1/play/?video_id=${Detail_Data.video.play_addr.uri}&ratio=1080p&line=0`;
19511
19514
  logger.debug(`开始排除不符合条件的视频分辨率;\n\n 共拥有${logger.yellow(Detail_Data.video.bit_rate.length)}个视频源\n\n 视频ID:${logger.green(Detail_Data.aweme_id)}\n\n 分享链接:${logger.green(Detail_Data.share_url)}\n `);
19512
19515
  const videoObj = douyinProcessVideos(Detail_Data.video.bit_rate, Config.douyin.videoQuality);
@@ -19531,7 +19534,7 @@ var DouYinpush = class extends Base {
19531
19534
  } catch (error) {
19532
19535
  throw new Error(`下载视频失败: ${error}`);
19533
19536
  }
19534
- else if (!iddata.is_mp4 && iddata.type === "one_work") {
19537
+ else if (workTypeInfo.isImage && iddata.type === "one_work") {
19535
19538
  if (Detail_Data.is_slides === true && Detail_Data.images) {
19536
19539
  const images = [];
19537
19540
  const temp = [];
@@ -20867,14 +20870,11 @@ var handleTestDouyinPush = wrapWithErrorHandler(async (e) => {
20867
20870
  const authorSecUid = author?.sec_uid;
20868
20871
  const authorNickname = author?.nickname;
20869
20872
  const authorInCreators = rawCreators.some((c) => authorUid && c.uid && c.uid === authorUid || authorSecUid && c.sec_uid && c.sec_uid === authorSecUid || authorNickname && c.nickname && c.nickname === authorNickname);
20870
- const co_creators = rawCreators.map((c) => {
20871
- const firstUrl = c.avatar_thumb?.url_list?.[0] ?? (c.avatar_thumb?.uri ? `https://p3.douyinpic.com/${c.avatar_thumb.uri}` : void 0);
20872
- return {
20873
- avatar_thumb: firstUrl ? { url_list: [firstUrl] } : void 0,
20874
- nickname: c.nickname,
20875
- role_title: c.role_title
20876
- };
20877
- });
20873
+ const co_creators = rawCreators.map((c) => ({
20874
+ avatar_url: c.avatar_thumb?.url_list?.[0] ?? (c.avatar_thumb?.uri ? `https://p3.douyinpic.com/${c.avatar_thumb.uri}` : void 0),
20875
+ nickname: c.nickname,
20876
+ role_title: c.role_title
20877
+ }));
20878
20878
  return {
20879
20879
  co_creator_nums: Math.max(Number(raw.co_creator_nums || 0), co_creators.length) + (authorInCreators ? 0 : 1),
20880
20880
  co_creators
@@ -1,5 +1,5 @@
1
1
  import { n as __esmMin, o as __toESM, r as __export } from "./rolldown-runtime-BMXAG3ag.js";
2
- import { $ as RiStarFill, $t as ExternalLink, A as init_locale, At as ThumbsUp, B as RiLineChartFill, Bt as QrCode, C as init_hi, Ct as init_io5, D as AiFillHeart, Dt as User, E as init_fa6, Et as Users, F as RiGroupLine, Ft as ShieldCheck, G as RiMessage3Fill, Gt as MapPin, H as RiListCheck2, Ht as Play, I as RiHashtag, It as Share2, J as RiRefreshLine, Jt as Hash, K as RiPieChart2Fill, Kt as Info, L as RiHeart2Line, Lt as ScanLine, M as RiArrowRightFill, Mt as Star, N as RiBarChartFill, Nt as Smartphone, O as AiFillStar, Ot as UserPlus, P as RiBellFill, Pt as Shield, Q as RiSparkling2Fill, Qt as Eye, R as RiHeart3Fill, Rt as Radio, S as HiOutlineMenuAlt2, St as IoSearch, T as FaCommentDots, Tt as Zap, U as RiLiveLine, Ut as Music, V as RiLinkM, Vt as Plug2, W as RiLoginCircleFill, Wt as MessageCircle, X as RiSendPlaneFill, Xt as Gamepad2, Y as RiRobot2Fill, Yt as Gift, Z as RiShareForwardFill, Zt as FileText, _ as init_md, _t as code_default, an as CircleEllipsis, at as RiVideoLine, b as TbScan, bt as HeroUIProvider, c as VictoryPie, cn as ChartColumn, ct as Markdown, d as VictoryAxis, dn as BookOpen, dt as init_date_fns, en as Crown, et as RiStarLine, f as VictoryLabel, fn as Bell, g as MdAccessTime, gn as require_react, gt as init_dist, h as rehypeHighlight, hn as require_server_node, in as CircleFadingArrowUp, it as RiUserFollowLine, j as zhCN, jt as Terminal, k as init_ai, kt as TriangleAlert, l as VictoryLine, ln as Calendar, lt as LuFullscreen, m as init_rehype_highlight, mn as init_clsx, mt as format, nn as Coins, nt as RiTiktokFill, o as init_es, on as CircleCheckBig, ot as init_ri, p as VictoryTheme, pn as clsx_default, pt as formatDistanceToNow, q as RiQuestionFill, qt as Heart, rn as Clock, rt as RiTrophyFill, s as VictoryScatter, sn as CircleAlert, st as init_react_markdown, tn as CornerDownLeft, tt as RiThumbUpFill, u as VictoryChart, un as Bookmark, ut as init_lu, v as SiBilibili, vt as chip_default, w as FaCodeBranch, wt as init_lucide_react, x as init_tb, xt as require_jsx_runtime, y as init_si, yt as button_default, z as RiHeart3Line, zt as Quote } from "./vendor-DxfKHvj-.js";
2
+ import { $ as RiStarFill, $t as ExternalLink, A as init_locale, At as ThumbsUp, B as RiLineChartFill, Bt as QrCode, C as init_hi, Ct as init_io5, D as AiFillHeart, Dt as User, E as init_fa6, Et as Users, F as RiGroupLine, Ft as ShieldCheck, G as RiMessage3Fill, Gt as MapPin, H as RiListCheck2, Ht as Play, I as RiHashtag, It as Share2, J as RiRefreshLine, Jt as Hash, K as RiPieChart2Fill, Kt as Info, L as RiHeart2Line, Lt as ScanLine, M as RiArrowRightFill, Mt as Star, N as RiBarChartFill, Nt as Smartphone, O as AiFillStar, Ot as UserPlus, P as RiBellFill, Pt as Shield, Q as RiSparkling2Fill, Qt as Eye, R as RiHeart3Fill, Rt as Radio, S as HiOutlineMenuAlt2, St as IoSearch, T as FaCommentDots, Tt as Zap, U as RiLiveLine, Ut as Music, V as RiLinkM, Vt as Plug2, W as RiLoginCircleFill, Wt as MessageCircle, X as RiSendPlaneFill, Xt as Gamepad2, Y as RiRobot2Fill, Yt as Gift, Z as RiShareForwardFill, Zt as FileText, _ as init_md, _t as code_default, an as CircleEllipsis, at as RiVideoLine, b as TbScan, bt as HeroUIProvider, c as VictoryPie, cn as ChartColumn, ct as Markdown, d as VictoryAxis, dn as BookOpen, dt as init_date_fns, en as Crown, et as RiStarLine, f as VictoryLabel, fn as Bell, g as MdAccessTime, gn as require_react, gt as init_dist, h as rehypeHighlight, hn as require_server_node, in as CircleFadingArrowUp, it as RiUserFollowLine, j as zhCN, jt as Terminal, k as init_ai, kt as TriangleAlert, l as VictoryLine, ln as Calendar, lt as LuFullscreen, m as init_rehype_highlight, mn as init_clsx, mt as format, nn as Coins, nt as RiTiktokFill, o as init_es, on as CircleCheckBig, ot as init_ri, p as VictoryTheme, pn as clsx_default, pt as formatDistanceToNow, q as RiQuestionFill, qt as Heart, rn as Clock, rt as RiTrophyFill, s as VictoryScatter, sn as CircleAlert, st as init_react_markdown, tn as CornerDownLeft, tt as RiThumbUpFill, u as VictoryChart, un as Bookmark, ut as init_lu, v as SiBilibili, vt as chip_default, w as FaCodeBranch, wt as init_lucide_react, x as init_tb, xt as require_jsx_runtime, y as init_si, yt as button_default, z as RiHeart3Line, zt as Quote } from "./vendor-9pKTNH6x.js";
3
3
  import { logger as logger$1 } from "node-karin";
4
4
  import fs from "node:fs";
5
5
  import path from "node:path";
@@ -2211,7 +2211,7 @@ var init_Dynamic = __esmMin(() => {
2211
2211
  className: "flex overflow-hidden gap-8 py-1 pr-2 w-full",
2212
2212
  style: { scrollbarWidth: "thin" },
2213
2213
  children: [items.slice(0, visibleCount).map((c, idx) => {
2214
- const avatar = c.avatar_thumb?.url_list[0];
2214
+ const avatar = c.avatar_url;
2215
2215
  return (0, import_jsx_runtime$34.jsxs)("div", {
2216
2216
  className: "flex flex-col items-center min-w-38 w-38 shrink-0",
2217
2217
  children: [
@@ -2412,13 +2412,17 @@ var init_VideoWork = __esmMin(() => {
2412
2412
  children: ["@", props.data.username]
2413
2413
  }), (0, import_jsx_runtime$33.jsxs)("div", {
2414
2414
  className: "flex gap-2 items-center text-4xl text-default-500",
2415
- children: [(0, import_jsx_runtime$33.jsx)(Hash, {
2416
- size: 32,
2417
- className: "text-default-400"
2418
- }), (0, import_jsx_runtime$33.jsxs)("span", {
2419
- className: "select-text",
2420
- children: ["抖音号: ", props.data.抖音号]
2421
- })]
2415
+ children: [
2416
+ (0, import_jsx_runtime$33.jsx)(Hash, { size: 32 }),
2417
+ (0, import_jsx_runtime$33.jsxs)("span", {
2418
+ className: "select-text",
2419
+ children: ["抖音号: ", props.data.抖音号]
2420
+ }),
2421
+ props.data.cooperation_info?.subscriber_role && (0, import_jsx_runtime$33.jsx)("span", {
2422
+ className: "ml-5 px-3 py-1 rounded-xl bg-default-200 text-3xl",
2423
+ children: props.data.cooperation_info.subscriber_role
2424
+ })
2425
+ ]
2422
2426
  })]
2423
2427
  })]
2424
2428
  }), (0, import_jsx_runtime$33.jsxs)("div", {
@@ -2487,8 +2491,8 @@ var init_VideoWork = __esmMin(() => {
2487
2491
  ]
2488
2492
  })]
2489
2493
  });
2490
- CoCreatorsInfo$1 = ({ info }) => {
2491
- const creators = info?.co_creators ?? [];
2494
+ CoCreatorsInfo$1 = ({ info, subscriberNickname }) => {
2495
+ const creators = (info?.co_creators ?? []).filter((c) => !subscriberNickname || c.nickname !== subscriberNickname);
2492
2496
  if (creators.length === 0) return null;
2493
2497
  const items = creators.slice(0, 50);
2494
2498
  const listRef = import_react$35.useRef(null);
@@ -2512,9 +2516,9 @@ var init_VideoWork = __esmMin(() => {
2512
2516
  className: "flex overflow-hidden gap-8 py-1 pr-2 w-full",
2513
2517
  style: { scrollbarWidth: "thin" },
2514
2518
  children: [items.slice(0, visibleCount).map((c, idx) => {
2515
- const avatar = c.avatar_thumb?.url_list[0];
2519
+ const avatar = c.avatar_url;
2516
2520
  return (0, import_jsx_runtime$33.jsxs)("div", {
2517
- className: "flex flex-col items-center min-w-38 w-38 shrink-0",
2521
+ className: "flex flex-col items-center min-w-42 w-42 shrink-0",
2518
2522
  children: [
2519
2523
  (0, import_jsx_runtime$33.jsx)("div", {
2520
2524
  className: "flex justify-center items-center bg-white rounded-full w-30 h-30",
@@ -2525,7 +2529,7 @@ var init_VideoWork = __esmMin(() => {
2525
2529
  })
2526
2530
  }),
2527
2531
  (0, import_jsx_runtime$33.jsx)("div", {
2528
- className: "overflow-hidden mt-6 w-full text-3xl font-medium leading-tight text-center truncate whitespace-nowrap select-text text-foreground-700",
2532
+ className: "overflow-hidden mt-6 w-full text-3xl font-medium leading-tight text-center truncate whitespace-nowrap select-text text-foreground",
2529
2533
  children: c.nickname || "未提供"
2530
2534
  }),
2531
2535
  (0, import_jsx_runtime$33.jsx)("div", {
@@ -2538,7 +2542,7 @@ var init_VideoWork = __esmMin(() => {
2538
2542
  className: "flex flex-col items-center min-w-38 w-38 shrink-0",
2539
2543
  children: [
2540
2544
  (0, import_jsx_runtime$33.jsx)("div", {
2541
- className: "flex justify-center items-center rounded-full bg-default-200 w-38 h-38",
2545
+ className: "flex justify-center items-center rounded-full bg-default-200 w-30 h-30",
2542
2546
  children: (0, import_jsx_runtime$33.jsx)("span", {
2543
2547
  className: "text-[42px] leading-none text-foreground-500",
2544
2548
  children: "···"
@@ -2586,7 +2590,10 @@ var init_VideoWork = __esmMin(() => {
2586
2590
  children: [coCreatorCount, "人共创"]
2587
2591
  })]
2588
2592
  })
2589
- }), (0, import_jsx_runtime$33.jsx)(CoCreatorsInfo$1, { info: props.data.cooperation_info })]
2593
+ }), (0, import_jsx_runtime$33.jsx)(CoCreatorsInfo$1, {
2594
+ info: props.data.cooperation_info,
2595
+ subscriberNickname: props.data.username
2596
+ })]
2590
2597
  }), (0, import_jsx_runtime$33.jsxs)("div", {
2591
2598
  className: "flex justify-between items-start px-20 pb-20",
2592
2599
  children: [(0, import_jsx_runtime$33.jsx)(UserInfoSection$3, { ...props }), (0, import_jsx_runtime$33.jsx)("div", {
@@ -2813,7 +2820,7 @@ var init_ImageWork = __esmMin(() => {
2813
2820
  className: "flex overflow-hidden gap-8 py-1 pr-2 w-full",
2814
2821
  style: { scrollbarWidth: "thin" },
2815
2822
  children: [items.slice(0, visibleCount).map((c, idx) => {
2816
- const avatar = c.avatar_thumb?.url_list[0];
2823
+ const avatar = c.avatar_url;
2817
2824
  return (0, import_jsx_runtime$32.jsxs)("div", {
2818
2825
  className: "flex flex-col items-center min-w-38 w-38 shrink-0",
2819
2826
  children: [
@@ -4295,80 +4302,87 @@ var init_UserList$1 = __esmMin(() => {
4295
4302
  })
4296
4303
  }),
4297
4304
  (0, import_jsx_runtime$25.jsxs)("div", {
4298
- className: "relative z-10 p-8 flex items-center gap-8",
4305
+ className: "relative z-10 p-6 flex flex-col gap-4",
4299
4306
  children: [(0, import_jsx_runtime$25.jsxs)("div", {
4300
- className: "relative shrink-0",
4301
- children: [(0, import_jsx_runtime$25.jsx)("div", {
4302
- className: "w-28 h-28 rounded-full p-1 bg-default-100/20 backdrop-blur-md border border-default-200/30 shadow-lg",
4303
- children: (0, import_jsx_runtime$25.jsx)("img", {
4304
- src: props.avatar_img,
4305
- alt: "Avatar",
4306
- className: "w-full h-full rounded-full object-cover"
4307
- })
4308
- }), (0, import_jsx_runtime$25.jsxs)("div", {
4309
- className: `absolute -bottom-1 -right-1 px-3 py-1 rounded-full border-2 border-background flex items-center gap-1.5 shadow-md ${props.switch ? "bg-success text-white" : "bg-danger-500 text-default-100"}`,
4310
- children: [(0, import_jsx_runtime$25.jsx)("div", { className: `w-1.5 h-1.5 rounded-full ${props.switch ? "bg-white" : "bg-default-300"}` }), (0, import_jsx_runtime$25.jsx)("span", {
4311
- className: "text-[10px] font-bold uppercase tracking-wider leading-none",
4312
- children: props.switch ? "ON" : "OFF"
4313
- })]
4314
- })]
4315
- }), (0, import_jsx_runtime$25.jsxs)("div", {
4316
- className: "flex-1 min-w-0",
4307
+ className: "flex items-center gap-4",
4317
4308
  children: [
4309
+ (0, import_jsx_runtime$25.jsx)("div", {
4310
+ className: "w-20 h-20 rounded-full p-1 bg-default-100/20 backdrop-blur-md border border-default-200/30 shadow-lg shrink-0",
4311
+ children: (0, import_jsx_runtime$25.jsx)("img", {
4312
+ src: props.avatar_img,
4313
+ alt: "Avatar",
4314
+ className: "w-full h-full rounded-full object-cover"
4315
+ })
4316
+ }),
4318
4317
  (0, import_jsx_runtime$25.jsxs)("div", {
4319
- className: "mb-3",
4318
+ className: "flex-1 min-w-0",
4320
4319
  children: [(0, import_jsx_runtime$25.jsx)("h3", {
4321
- className: "text-2xl font-black tracking-tight text-foreground truncate drop-shadow-sm",
4320
+ className: "text-3xl font-black tracking-tight text-foreground truncate drop-shadow-sm mb-1.5",
4322
4321
  children: props.username
4323
- }), (0, import_jsx_runtime$25.jsx)("div", {
4324
- className: "flex items-center gap-2 mt-1",
4325
- children: (0, import_jsx_runtime$25.jsxs)("span", {
4326
- className: "px-1.5 py-0.5 rounded-md bg-default-100/50 border border-default-200/50 text-[10px] font-mono font-bold text-default-500 flex items-center gap-1",
4327
- children: [(0, import_jsx_runtime$25.jsx)(RiHashtag, { className: "w-2.5 h-2.5 opacity-70" }), props.short_id]
4328
- })
4322
+ }), (0, import_jsx_runtime$25.jsxs)("span", {
4323
+ className: "inline-flex items-center gap-1 px-2 py-1 rounded-md bg-default-100/50 border border-default-200/50 text-xs font-mono font-bold text-default-500",
4324
+ children: [(0, import_jsx_runtime$25.jsx)(RiHashtag, { className: "w-3 h-3 opacity-70" }), props.short_id]
4329
4325
  })]
4330
4326
  }),
4331
- (0, import_jsx_runtime$25.jsx)("div", {
4332
- className: "flex flex-wrap gap-2 mb-4",
4333
- children: Object.entries(pushTypeConfig).map(([type, config$1]) => {
4334
- const isActive = props.pushTypes?.includes(type);
4335
- const Icon = config$1.icon;
4336
- return (0, import_jsx_runtime$25.jsxs)("div", {
4337
- className: `px-2 py-0.5 rounded-md border flex items-center gap-1.5 transition-colors duration-200 ${isActive ? config$1.color : "bg-default-100/50 text-default-400 border-transparent dark:bg-default-100/10"}`,
4338
- children: [(0, import_jsx_runtime$25.jsx)(Icon, { className: `w-3 h-3 ${isActive ? "" : "opacity-50"}` }), (0, import_jsx_runtime$25.jsx)("span", {
4339
- className: "text-[10px] font-bold",
4340
- children: config$1.label
4341
- })]
4342
- }, type);
4343
- })
4344
- }),
4345
4327
  (0, import_jsx_runtime$25.jsxs)("div", {
4346
- className: "flex items-center gap-2 w-full",
4347
- children: [
4348
- (0, import_jsx_runtime$25.jsxs)("div", {
4349
- className: "flex-1 flex flex-col items-center justify-center py-1.5 px-2 rounded-lg bg-content2/20 border border-default-200/20 backdrop-blur-sm",
4350
- children: [(0, import_jsx_runtime$25.jsx)(RiGroupLine, { className: "w-3.5 h-3.5 mb-0.5 text-default-400" }), (0, import_jsx_runtime$25.jsx)("span", {
4351
- className: "text-sm font-bold font-mono text-default-600 leading-none",
4352
- children: props.fans
4353
- })]
4354
- }),
4355
- (0, import_jsx_runtime$25.jsxs)("div", {
4356
- className: "flex-1 flex flex-col items-center justify-center py-1.5 px-2 rounded-lg bg-content2/20 border border-default-200/20 backdrop-blur-sm",
4357
- children: [(0, import_jsx_runtime$25.jsx)(RiHeart3Line, { className: "w-3.5 h-3.5 mb-0.5 text-default-400" }), (0, import_jsx_runtime$25.jsx)("span", {
4358
- className: "text-sm font-bold font-mono text-default-600 leading-none",
4359
- children: props.total_favorited
4360
- })]
4361
- }),
4362
- (0, import_jsx_runtime$25.jsxs)("div", {
4363
- className: "flex-1 flex flex-col items-center justify-center py-1.5 px-2 rounded-lg bg-content2/20 border border-default-200/20 backdrop-blur-sm",
4364
- children: [(0, import_jsx_runtime$25.jsx)(RiUserFollowLine, { className: "w-3.5 h-3.5 mb-0.5 text-default-400" }), (0, import_jsx_runtime$25.jsx)("span", {
4365
- className: "text-sm font-bold font-mono text-default-600 leading-none",
4366
- children: props.following_count
4367
- })]
4368
- })
4369
- ]
4328
+ className: `px-4 py-2 rounded-full border-2 border-background flex items-center gap-2 shadow-md shrink-0 ${props.switch ? "bg-success text-white" : "bg-danger-500 text-default-100"}`,
4329
+ children: [(0, import_jsx_runtime$25.jsx)("div", { className: `w-2 h-2 rounded-full ${props.switch ? "bg-white" : "bg-default-300"}` }), (0, import_jsx_runtime$25.jsx)("span", {
4330
+ className: "text-xs font-bold uppercase tracking-wider leading-none",
4331
+ children: props.switch ? "ON" : "OFF"
4332
+ })]
4370
4333
  })
4371
4334
  ]
4335
+ }), (0, import_jsx_runtime$25.jsxs)("div", {
4336
+ className: "flex gap-6",
4337
+ children: [(0, import_jsx_runtime$25.jsx)("div", {
4338
+ className: "flex gap-2.5",
4339
+ children: Object.entries(pushTypeConfig).map(([type, config$1]) => {
4340
+ const isActive = props.pushTypes?.includes(type);
4341
+ const Icon = config$1.icon;
4342
+ return (0, import_jsx_runtime$25.jsxs)("div", {
4343
+ className: `px-2.5 py-3 rounded-xl border flex flex-col items-center gap-2.5 transition-colors duration-200 ${isActive ? config$1.color : "bg-default-100/50 text-default-400 border-transparent dark:bg-default-100/10"}`,
4344
+ children: [(0, import_jsx_runtime$25.jsx)(Icon, { className: `w-5 h-5 ${isActive ? "" : "opacity-50"}` }), (0, import_jsx_runtime$25.jsx)("span", {
4345
+ className: "text-xs font-bold whitespace-nowrap tracking-wide",
4346
+ style: { writingMode: "vertical-rl" },
4347
+ children: config$1.label
4348
+ })]
4349
+ }, type);
4350
+ })
4351
+ }), (0, import_jsx_runtime$25.jsx)("div", {
4352
+ className: "flex-1 flex flex-col gap-2",
4353
+ children: [
4354
+ {
4355
+ icon: RiGroupLine,
4356
+ value: props.fans,
4357
+ label: "粉丝"
4358
+ },
4359
+ {
4360
+ icon: RiHeart3Line,
4361
+ value: props.total_favorited,
4362
+ label: "获赞"
4363
+ },
4364
+ {
4365
+ icon: RiUserFollowLine,
4366
+ value: props.following_count,
4367
+ label: "关注"
4368
+ }
4369
+ ].map((item, index) => {
4370
+ const Icon = item.icon;
4371
+ return (0, import_jsx_runtime$25.jsxs)("div", {
4372
+ className: "flex items-center gap-3 px-4 py-2 rounded-lg bg-content2/30 border border-default-200/30 backdrop-blur-sm",
4373
+ children: [(0, import_jsx_runtime$25.jsx)(Icon, { className: "w-5 h-5 text-default-400 shrink-0" }), (0, import_jsx_runtime$25.jsxs)("div", {
4374
+ className: "flex items-baseline gap-2 flex-1",
4375
+ children: [(0, import_jsx_runtime$25.jsx)("span", {
4376
+ className: "text-base font-bold font-mono text-foreground",
4377
+ children: item.value
4378
+ }), (0, import_jsx_runtime$25.jsx)("span", {
4379
+ className: "text-xs text-default-400 font-medium",
4380
+ children: item.label
4381
+ })]
4382
+ })]
4383
+ }, index);
4384
+ })
4385
+ })]
4372
4386
  })]
4373
4387
  })
4374
4388
  ]
@@ -4559,11 +4573,101 @@ var init_videoInfo$1 = __esmMin(() => {
4559
4573
  className: "relative",
4560
4574
  children: [(0, import_jsx_runtime$24.jsxs)("div", {
4561
4575
  className: "absolute inset-0 overflow-hidden -z-10",
4562
- children: [(0, import_jsx_runtime$24.jsx)("img", {
4563
- src: props.data.image_url,
4564
- alt: "",
4565
- className: "w-full h-full object-cover scale-150 blur-[120px] saturate-[1.8] opacity-50"
4566
- }), (0, import_jsx_runtime$24.jsx)("div", { className: "absolute inset-0 bg-linear-to-b from-default-50/70 via-default-50/50 to-default-50/70 dark:from-black/40 dark:via-black/30 dark:to-black/40" })]
4576
+ children: [
4577
+ (0, import_jsx_runtime$24.jsx)("img", {
4578
+ src: props.data.image_url,
4579
+ alt: "",
4580
+ className: "w-full h-full object-cover scale-150 blur-[120px] saturate-[1.8] opacity-50"
4581
+ }),
4582
+ (0, import_jsx_runtime$24.jsx)("div", { className: "absolute inset-0 bg-linear-to-b from-default-50/70 via-default-50/50 to-default-50/70 dark:from-black/40 dark:via-black/30 dark:to-black/40" }),
4583
+ (0, import_jsx_runtime$24.jsx)("div", {
4584
+ className: "absolute inset-0 pointer-events-none opacity-[0.35] mix-blend-overlay dark:mix-blend-soft-light",
4585
+ children: (0, import_jsx_runtime$24.jsxs)("svg", {
4586
+ className: "w-full h-full",
4587
+ xmlns: "http://www.w3.org/2000/svg",
4588
+ children: [(0, import_jsx_runtime$24.jsxs)("defs", { children: [(0, import_jsx_runtime$24.jsxs)("filter", {
4589
+ id: "douyinNoise",
4590
+ children: [
4591
+ (0, import_jsx_runtime$24.jsx)("feTurbulence", {
4592
+ type: "fractalNoise",
4593
+ baseFrequency: "1.2",
4594
+ numOctaves: "3",
4595
+ stitchTiles: "stitch"
4596
+ }),
4597
+ (0, import_jsx_runtime$24.jsx)("feColorMatrix", {
4598
+ type: "saturate",
4599
+ values: "0"
4600
+ }),
4601
+ (0, import_jsx_runtime$24.jsxs)("feComponentTransfer", { children: [
4602
+ (0, import_jsx_runtime$24.jsx)("feFuncR", {
4603
+ type: "discrete",
4604
+ tableValues: "0 1"
4605
+ }),
4606
+ (0, import_jsx_runtime$24.jsx)("feFuncG", {
4607
+ type: "discrete",
4608
+ tableValues: "0 1"
4609
+ }),
4610
+ (0, import_jsx_runtime$24.jsx)("feFuncB", {
4611
+ type: "discrete",
4612
+ tableValues: "0 1"
4613
+ })
4614
+ ] }),
4615
+ (0, import_jsx_runtime$24.jsx)("feComponentTransfer", { children: (0, import_jsx_runtime$24.jsx)("feFuncA", {
4616
+ type: "linear",
4617
+ slope: "2",
4618
+ intercept: "-0.5"
4619
+ }) })
4620
+ ]
4621
+ }), (0, import_jsx_runtime$24.jsxs)("mask", {
4622
+ id: "noiseMask",
4623
+ children: [(0, import_jsx_runtime$24.jsxs)("linearGradient", {
4624
+ id: "noiseGradient",
4625
+ x1: "0%",
4626
+ y1: "0%",
4627
+ x2: "0%",
4628
+ y2: "100%",
4629
+ children: [
4630
+ (0, import_jsx_runtime$24.jsx)("stop", {
4631
+ offset: "0%",
4632
+ stopColor: "white",
4633
+ stopOpacity: "1"
4634
+ }),
4635
+ (0, import_jsx_runtime$24.jsx)("stop", {
4636
+ offset: "15%",
4637
+ stopColor: "white",
4638
+ stopOpacity: "0.6"
4639
+ }),
4640
+ (0, import_jsx_runtime$24.jsx)("stop", {
4641
+ offset: "50%",
4642
+ stopColor: "white",
4643
+ stopOpacity: "0.15"
4644
+ }),
4645
+ (0, import_jsx_runtime$24.jsx)("stop", {
4646
+ offset: "85%",
4647
+ stopColor: "white",
4648
+ stopOpacity: "0.6"
4649
+ }),
4650
+ (0, import_jsx_runtime$24.jsx)("stop", {
4651
+ offset: "100%",
4652
+ stopColor: "white",
4653
+ stopOpacity: "1"
4654
+ })
4655
+ ]
4656
+ }), (0, import_jsx_runtime$24.jsx)("rect", {
4657
+ width: "100%",
4658
+ height: "100%",
4659
+ fill: "url(#noiseGradient)"
4660
+ })]
4661
+ })] }), (0, import_jsx_runtime$24.jsx)("rect", {
4662
+ width: "100%",
4663
+ height: "100%",
4664
+ filter: "url(#douyinNoise)",
4665
+ mask: "url(#noiseMask)",
4666
+ fill: "white"
4667
+ })]
4668
+ })
4669
+ })
4670
+ ]
4567
4671
  }), (0, import_jsx_runtime$24.jsx)("div", {
4568
4672
  className: "relative w-full overflow-hidden text-default-900",
4569
4673
  children: (0, import_jsx_runtime$24.jsxs)("div", {
@@ -13017,56 +13121,95 @@ var init_GlobalStatistics = __esmMin(() => {
13017
13121
  children: [(0, import_jsx_runtime.jsx)("div", { className: "w-5 h-24 rounded-full bg-violet-500" }), (0, import_jsx_runtime.jsxs)("div", {
13018
13122
  className: "flex flex-col",
13019
13123
  children: [(0, import_jsx_runtime.jsx)("h2", {
13020
- className: "text-[5rem] font-black tracking-tight leading-none text-slate-900 dark:text-white",
13124
+ className: "text-[5rem] font-black tracking-tight leading-none text-default-900/90",
13021
13125
  children: "平台详情"
13022
13126
  }), (0, import_jsx_runtime.jsx)("span", {
13023
- className: "text-2xl font-medium tracking-[0.15em] uppercase text-slate-400 dark:text-slate-500 mt-2",
13127
+ className: "text-2xl font-medium tracking-[0.15em] uppercase text-default-500/70 mt-2",
13024
13128
  children: "PLATFORMS"
13025
13129
  })]
13026
13130
  })]
13027
- }), (0, import_jsx_runtime.jsx)("div", {
13028
- className: "space-y-18",
13029
- children: Object.entries(platformStats).map(([platform, count]) => {
13030
- const maxCount = Math.max(...Object.values(platformStats));
13031
- const percentage = maxCount > 0 ? count / maxCount * 100 : 0;
13032
- const config$1 = platformConfig[platform];
13033
- return (0, import_jsx_runtime.jsxs)("div", {
13034
- className: "relative",
13035
- children: [(0, import_jsx_runtime.jsxs)("div", {
13036
- className: "flex items-center gap-8 mb-6",
13037
- children: [
13038
- (0, import_jsx_runtime.jsx)("img", {
13039
- src: config$1.logo,
13040
- alt: config$1.name,
13041
- className: "h-24 w-auto object-contain"
13042
- }),
13043
- (0, import_jsx_runtime.jsxs)("div", {
13044
- className: "flex-1",
13045
- children: [(0, import_jsx_runtime.jsx)("div", {
13131
+ }), (0, import_jsx_runtime.jsxs)("div", {
13132
+ className: "flex flex-col items-center gap-20",
13133
+ children: [(0, import_jsx_runtime.jsx)("div", {
13134
+ className: "relative w-full h-200 flex items-center justify-center",
13135
+ children: (0, import_jsx_runtime.jsx)("svg", {
13136
+ width: "1200",
13137
+ height: "1000",
13138
+ viewBox: "0 0 1200 1000",
13139
+ children: (0, import_jsx_runtime.jsx)(VictoryPie, {
13140
+ standalone: false,
13141
+ width: 1200,
13142
+ height: 1e3,
13143
+ data: Object.entries(platformStats).map(([platform, count]) => {
13144
+ const config$1 = platformConfig[platform];
13145
+ const total = Object.values(platformStats).reduce((sum, c) => sum + c, 0);
13146
+ const percentage = total > 0 ? (count / total * 100).toFixed(0) : "0";
13147
+ return {
13148
+ x: config$1.name,
13149
+ y: count,
13150
+ label: `${config$1.name} ${percentage}%\n${formatNumber$4(count)}次`,
13151
+ fill: config$1.color
13152
+ };
13153
+ }),
13154
+ innerRadius: 220,
13155
+ radius: 320,
13156
+ padAngle: 3,
13157
+ colorScale: Object.keys(platformStats).map((platform) => platformConfig[platform].color),
13158
+ style: { labels: {
13159
+ fontSize: 40,
13160
+ fontFamily: "HarmonyOSHans-Regular",
13161
+ fontWeight: "bold",
13162
+ fill: useDarkTheme ? "#fff" : "#000"
13163
+ } },
13164
+ labelRadius: 400
13165
+ })
13166
+ })
13167
+ }), (0, import_jsx_runtime.jsx)("div", {
13168
+ className: "w-full grid grid-cols-2 gap-x-16 gap-y-8",
13169
+ children: Object.entries(platformStats).map(([platform, count]) => {
13170
+ if (count === 0) return null;
13171
+ const config$1 = platformConfig[platform];
13172
+ const total = Object.values(platformStats).reduce((sum, c) => sum + c, 0);
13173
+ const percentage = total > 0 ? (count / total * 100).toFixed(1) : "0.0";
13174
+ return (0, import_jsx_runtime.jsxs)("div", {
13175
+ className: "flex items-center gap-8",
13176
+ children: [(0, import_jsx_runtime.jsx)("div", {
13177
+ className: "w-14 h-14 rounded-lg shrink-0",
13178
+ style: { backgroundColor: config$1.color }
13179
+ }), (0, import_jsx_runtime.jsxs)("div", {
13180
+ className: "flex-1",
13181
+ children: [
13182
+ (0, import_jsx_runtime.jsx)("div", {
13046
13183
  className: "text-4xl font-bold text-default-900/90 mb-2",
13047
13184
  children: config$1.name
13048
- }), (0, import_jsx_runtime.jsx)("div", {
13049
- className: "text-2xl text-default-600/80",
13185
+ }),
13186
+ (0, import_jsx_runtime.jsx)("div", {
13187
+ className: "text-2xl text-default-600/80 mb-2",
13050
13188
  children: config$1.nameEn
13051
- })]
13052
- }),
13053
- (0, import_jsx_runtime.jsx)("div", {
13054
- className: "text-[5rem] font-black text-default-900/90",
13055
- children: formatWithCommas(count)
13056
- })
13057
- ]
13058
- }), (0, import_jsx_runtime.jsx)("div", {
13059
- className: "relative h-18 bg-default-200/30 rounded-full overflow-hidden",
13060
- children: (0, import_jsx_runtime.jsx)("div", {
13061
- className: "absolute inset-y-0 left-0 rounded-full transition-all duration-500",
13062
- style: {
13063
- width: `${percentage}%`,
13064
- backgroundColor: config$1.color
13065
- }
13066
- })
13067
- })]
13068
- }, platform);
13069
- })
13189
+ }),
13190
+ (0, import_jsx_runtime.jsxs)("div", {
13191
+ className: "text-3xl text-default-600/80",
13192
+ children: [
13193
+ (0, import_jsx_runtime.jsx)("span", {
13194
+ className: "font-black text-default-900/90",
13195
+ children: formatWithCommas(count)
13196
+ }),
13197
+ " ",
13198
+ (0, import_jsx_runtime.jsxs)("span", {
13199
+ className: "text-2xl ml-2",
13200
+ children: [
13201
+ "(",
13202
+ percentage,
13203
+ "%)"
13204
+ ]
13205
+ })
13206
+ ]
13207
+ })
13208
+ ]
13209
+ })]
13210
+ }, platform);
13211
+ })
13212
+ })]
13070
13213
  })]
13071
13214
  }),
13072
13215
  (0, import_jsx_runtime.jsxs)("div", { children: [(0, import_jsx_runtime.jsxs)("div", {
@@ -142,9 +142,7 @@ interface DouyinDynamicProps extends BaseComponentProps {
142
142
  cooperation_info?: {
143
143
  co_creator_nums: number;
144
144
  co_creators: Array<{
145
- avatar_thumb: {
146
- url_list: string[];
147
- };
145
+ avatar_url?: string;
148
146
  nickname: string;
149
147
  role_title: string;
150
148
  }>;
@@ -209,9 +207,7 @@ interface DouyinImageWorkProps extends BaseComponentProps {
209
207
  cooperation_info?: {
210
208
  co_creator_nums: number;
211
209
  co_creators: Array<{
212
- avatar_thumb: {
213
- url_list: string[];
214
- };
210
+ avatar_url?: string;
215
211
  nickname: string;
216
212
  role_title: string;
217
213
  }>;
@@ -451,12 +447,11 @@ interface DouyinVideoWorkProps extends BaseComponentProps {
451
447
  cooperation_info?: {
452
448
  co_creator_nums: number;
453
449
  co_creators: Array<{
454
- avatar_thumb: {
455
- url_list: string[];
456
- };
450
+ avatar_url?: string;
457
451
  nickname: string;
458
452
  role_title: string;
459
453
  }>;
454
+ subscriber_role?: string;
460
455
  };
461
456
  };
462
457
  /** 预生成的二维码数据URL */
@@ -1,4 +1,4 @@
1
1
  import "./rolldown-runtime-BMXAG3ag.js";
2
- import "./vendor-DxfKHvj-.js";
3
- import { r as reactServerRender, t as template_default } from "./template-CnW8M_F0.js";
2
+ import "./vendor-9pKTNH6x.js";
3
+ import { r as reactServerRender, t as template_default } from "./template-2ApQpQ8R.js";
4
4
  export { template_default as default, reactServerRender };
@@ -144568,7 +144568,6 @@ var init_victory_brush_line = __esmMin(() => {
144568
144568
  __toESM(require_react());
144569
144569
  __toESM(require_defaults());
144570
144570
  __toESM(require_pick());
144571
- init_es$27();
144572
144571
  __toESM(require_react_fast_compare());
144573
144572
  1 / Number.MAX_SAFE_INTEGER;
144574
144573
  });
@@ -145161,7 +145160,6 @@ var init_use_canvas_context = __esmMin(() => {
145161
145160
  var import_react$32;
145162
145161
  var init_canvas_bar = __esmMin(() => {
145163
145162
  __toESM(require_react());
145164
- init_es$24();
145165
145163
  });
145166
145164
  var import_react$31, CanvasGroup;
145167
145165
  var init_canvas_group = __esmMin(() => {
@@ -145202,12 +145200,10 @@ var init_canvas_group = __esmMin(() => {
145202
145200
  var import_react$30;
145203
145201
  var init_canvas_curve = __esmMin(() => {
145204
145202
  __toESM(require_react());
145205
- init_es$27();
145206
145203
  });
145207
145204
  var import_react$29;
145208
145205
  var init_canvas_point = __esmMin(() => {
145209
145206
  __toESM(require_react());
145210
- init_es$27();
145211
145207
  });
145212
145208
  var init_es$19 = __esmMin(() => {
145213
145209
  init_canvas_bar();
package/lib/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import "./core_chunk/rolldown-runtime-BMXAG3ag.js";
2
- import "./core_chunk/main-BdZy8WYB.js";
3
- import "./core_chunk/vendor-DxfKHvj-.js";
4
- import "./core_chunk/template-CnW8M_F0.js";
2
+ import "./core_chunk/main-BQn-mQch.js";
3
+ import "./core_chunk/vendor-9pKTNH6x.js";
4
+ import "./core_chunk/template-2ApQpQ8R.js";
5
5
  export {};
@@ -1585,10 +1585,6 @@
1585
1585
  margin-bottom: calc(var(--spacing) * 0);
1586
1586
  }
1587
1587
 
1588
- .mb-0\.5 {
1589
- margin-bottom: calc(var(--spacing) * .5);
1590
- }
1591
-
1592
1588
  .mb-1 {
1593
1589
  margin-bottom: calc(var(--spacing) * 1);
1594
1590
  }
@@ -4176,17 +4172,7 @@
4176
4172
  border-color: hsl(var(--heroui-default-100) / 1);
4177
4173
  }
4178
4174
 
4179
- .border-default-200, .border-default-200\/20 {
4180
- border-color: hsl(var(--heroui-default-200) / 1);
4181
- }
4182
-
4183
- @supports (color: color-mix(in lab, red, red)) {
4184
- .border-default-200\/20 {
4185
- border-color: color-mix(in oklab, hsl(var(--heroui-default-200) / 1) 20%, transparent);
4186
- }
4187
- }
4188
-
4189
- .border-default-200\/30 {
4175
+ .border-default-200, .border-default-200\/30 {
4190
4176
  border-color: hsl(var(--heroui-default-200) / 1);
4191
4177
  }
4192
4178
 
@@ -4654,13 +4640,13 @@
4654
4640
  }
4655
4641
  }
4656
4642
 
4657
- .bg-content2, .bg-content2\/20 {
4643
+ .bg-content2, .bg-content2\/30 {
4658
4644
  background-color: hsl(var(--heroui-content2) / 1);
4659
4645
  }
4660
4646
 
4661
4647
  @supports (color: color-mix(in lab, red, red)) {
4662
- .bg-content2\/20 {
4663
- background-color: color-mix(in oklab, hsl(var(--heroui-content2) / 1) 20%, transparent);
4648
+ .bg-content2\/30 {
4649
+ background-color: color-mix(in oklab, hsl(var(--heroui-content2) / 1) 30%, transparent);
4664
4650
  }
4665
4651
  }
4666
4652
 
@@ -4848,16 +4834,6 @@
4848
4834
  }
4849
4835
  }
4850
4836
 
4851
- .bg-default-200\/30 {
4852
- background-color: hsl(var(--heroui-default-200) / 1);
4853
- }
4854
-
4855
- @supports (color: color-mix(in lab, red, red)) {
4856
- .bg-default-200\/30 {
4857
- background-color: color-mix(in oklab, hsl(var(--heroui-default-200) / 1) 30%, transparent);
4858
- }
4859
- }
4860
-
4861
4837
  .bg-default-200\/60 {
4862
4838
  background-color: hsl(var(--heroui-default-200) / 1);
4863
4839
  }
@@ -7058,10 +7034,6 @@
7058
7034
  }
7059
7035
  }
7060
7036
 
7061
- .text-slate-400 {
7062
- color: var(--color-slate-400);
7063
- }
7064
-
7065
7037
  .text-slate-500 {
7066
7038
  color: var(--color-slate-500);
7067
7039
  }
@@ -7523,6 +7495,10 @@
7523
7495
  opacity: .08;
7524
7496
  }
7525
7497
 
7498
+ .opacity-\[0\.35\] {
7499
+ opacity: .35;
7500
+ }
7501
+
7526
7502
  .opacity-\[value\] {
7527
7503
  opacity: value;
7528
7504
  }
@@ -13249,10 +13225,6 @@
13249
13225
  color: var(--color-slate-400);
13250
13226
  }
13251
13227
 
13252
- .dark\:text-slate-500:is(.dark *) {
13253
- color: var(--color-slate-500);
13254
- }
13255
-
13256
13228
  .dark\:text-success:is(.dark *) {
13257
13229
  color: hsl(var(--heroui-success) / 1);
13258
13230
  }
@@ -13281,6 +13253,10 @@
13281
13253
  opacity: .12;
13282
13254
  }
13283
13255
 
13256
+ .dark\:mix-blend-soft-light:is(.dark *) {
13257
+ mix-blend-mode: soft-light;
13258
+ }
13259
+
13284
13260
  .dark\:placeholder\:text-danger-500:is(.dark *)::placeholder {
13285
13261
  color: hsl(var(--heroui-danger-500) / 1);
13286
13262
  }
package/lib/root.js CHANGED
@@ -1,4 +1,4 @@
1
1
  import "./core_chunk/rolldown-runtime-BMXAG3ag.js";
2
- import { A as init_root, k as Root } from "./core_chunk/main-BdZy8WYB.js";
2
+ import { A as init_root, k as Root } from "./core_chunk/main-BQn-mQch.js";
3
3
  init_root();
4
4
  export { Root };
package/lib/web.config.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import "./core_chunk/rolldown-runtime-BMXAG3ag.js";
2
- import { D as webConfig, O as web_config_default } from "./core_chunk/main-BdZy8WYB.js";
3
- import "./core_chunk/vendor-DxfKHvj-.js";
4
- import "./core_chunk/template-CnW8M_F0.js";
2
+ import { D as webConfig, O as web_config_default } from "./core_chunk/main-BQn-mQch.js";
3
+ import "./core_chunk/vendor-9pKTNH6x.js";
4
+ import "./core_chunk/template-2ApQpQ8R.js";
5
5
  export { web_config_default as default, webConfig };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "karin-plugin-kkk",
3
- "version": "2.23.1",
3
+ "version": "2.23.2",
4
4
  "description": "Karin 的「抖音」「B 站」视频解析/动态推送插件",
5
5
  "keywords": [
6
6
  "karin-plugin",
@@ -76,7 +76,7 @@
76
76
  "web": "./lib/web.config.js",
77
77
  "ts-web": "./src/web.config.ts"
78
78
  },
79
- "timestamp": "2026-03-08T12:56:59.360Z",
79
+ "timestamp": "2026-03-10T11:28:43.385Z",
80
80
  "scripts": {
81
81
  "build": "cross-env NODE_ENV=production vite build && tsdown && vitest run",
82
82
  "build:check": "tsc --noEmit && pnpm build",