karin-plugin-kkk 2.18.3 → 2.19.1

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,6 +1,6 @@
1
1
  import { n as __esmMin, o as __toESM, r as __export } from "./rolldown-runtime-BMXAG3ag.js";
2
- import { $t as require_express, G as zhCN, J as init_date_fns, Q as differenceInSeconds, W as init_locale, X as formatDistanceToNow, Y as fromUnixTime, Z as format, a as require_lib, an as axios_default, c as Window, cn as init_zod, en as require_protobufjs, i as require_dist, in as init_axios, ln as zod_default, n as require_jsQR, nn as init_source, o as require_qr_code_styling, on as Xhshow, r as require_heic_convert, rn as AxiosError$1, s as init_lib, sn as init_esm, t as require_png, tn as Chalk } from "./vendor-B-twx8Ds.js";
3
- import { n as init_client, r as reactServerRender } from "./template-BBVRQ9ag.js";
2
+ import { D as init_locale, O as zhCN, _n as init_zod, a as require_lib, at as format, c as Window, cn as require_express, dn as init_source, fn as AxiosError$1, gn as init_esm, hn as Xhshow, i as require_dist, it as formatDistanceToNow, ln as require_protobufjs, mn as axios_default, n as require_jsQR, nt as init_date_fns, o as require_qr_code_styling, ot as differenceInSeconds, pn as init_axios, r as require_heic_convert, rt as fromUnixTime, s as init_lib, t as require_png, un as Chalk, vn as zod_default } from "./vendor-BsdYKPEs.js";
3
+ import { n as init_client, r as reactServerRender } from "./template-BjkVe9U9.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";
@@ -746,7 +746,7 @@ var init_bilibili$3 = __esmMin(() => {
746
746
  videoDanmaku: "/fetch_danmaku"
747
747
  };
748
748
  });
749
- var DouyinWorkParamsSchema, DouyinCommentParamsSchema, DouyinHotWordsParamsSchema, DouyinSearchParamsSchema, DouyinCommentReplyParamsSchema, DouyinUserParamsSchema, DouyinMusicParamsSchema, DouyinLiveRoomParamsSchema, DouyinQrcodeParamsSchema, DouyinEmojiListParamsSchema, DouyinEmojiProParamsSchema, DouyinDanmakuParamsSchema, DouyinValidationSchemas, DouyinMethodRoutes;
749
+ var DouyinWorkParamsSchema, DouyinCommentParamsSchema, DouyinHotWordsParamsSchema, DouyinSearchParamsSchema, DouyinCommentReplyParamsSchema, DouyinUserParamsSchema, DouyinUserListParamsSchema, DouyinMusicParamsSchema, DouyinLiveRoomParamsSchema, DouyinQrcodeParamsSchema, DouyinEmojiListParamsSchema, DouyinEmojiProParamsSchema, DouyinDanmakuParamsSchema, DouyinValidationSchemas, DouyinMethodRoutes;
750
750
  var init_douyin$3 = __esmMin(() => {
751
751
  init_zod();
752
752
  init_utils$3();
@@ -789,9 +789,19 @@ var init_douyin$3 = __esmMin(() => {
789
789
  cursor: zod_default.coerce.number({ error: "游标必须是数字" }).int({ error: "游标必须是整数" }).min(0, { error: "游标不能小于0" }).default(0).optional()
790
790
  });
791
791
  DouyinUserParamsSchema = zod_default.object({
792
- methodType: zod_default.enum(["userProfile", "userVideoList"], { error: "方法类型必须是指定的枚举值之一" }),
792
+ methodType: zod_default.literal("userProfile", { error: "方法类型必须是\"userProfile\"" }),
793
793
  sec_uid: zod_default.string({ error: "用户ID必须是字符串" }).min(1, { error: "用户ID不能为空" })
794
794
  });
795
+ DouyinUserListParamsSchema = zod_default.object({
796
+ methodType: zod_default.enum([
797
+ "userVideoList",
798
+ "userFavoriteList",
799
+ "userRecommendList"
800
+ ], { error: "方法类型必须是指定的枚举值之一" }),
801
+ sec_uid: zod_default.string({ error: "用户ID必须是字符串" }).min(1, { error: "用户ID不能为空" }),
802
+ number: smartPositiveInteger("获取数量必须是正整数").optional().default(18),
803
+ max_cursor: zod_default.string({ error: "游标必须是字符串" }).optional()
804
+ });
795
805
  DouyinMusicParamsSchema = zod_default.object({
796
806
  methodType: zod_default.literal("musicInfo", { error: "方法类型必须是\"musicInfo\"" }),
797
807
  music_id: zod_default.string({ error: "音乐ID必须是字符串" }).min(1, { error: "音乐ID不能为空" })
@@ -834,7 +844,9 @@ var init_douyin$3 = __esmMin(() => {
834
844
  slidesWork: DouyinWorkParamsSchema,
835
845
  comments: DouyinCommentParamsSchema,
836
846
  userProfile: DouyinUserParamsSchema,
837
- userVideoList: DouyinUserParamsSchema,
847
+ userVideoList: DouyinUserListParamsSchema,
848
+ userFavoriteList: DouyinUserListParamsSchema,
849
+ userRecommendList: DouyinUserListParamsSchema,
838
850
  suggestWords: DouyinHotWordsParamsSchema,
839
851
  search: DouyinSearchParamsSchema,
840
852
  musicInfo: DouyinMusicParamsSchema,
@@ -855,6 +867,8 @@ var init_douyin$3 = __esmMin(() => {
855
867
  commentReplies: "/fetch_video_comment_replies",
856
868
  userProfile: "/fetch_user_info",
857
869
  userVideoList: "/fetch_user_post_videos",
870
+ userFavoriteList: "/fetch_user_favorite_list",
871
+ userRecommendList: "/fetch_user_recommend_list",
858
872
  search: "/fetch_search_info",
859
873
  suggestWords: "/fetch_suggest_words",
860
874
  musicInfo: "/fetch_music_work",
@@ -2354,14 +2368,14 @@ var init_API$1 = __esmMin(() => {
2354
2368
  return `https://www.douyin.com/aweme/v1/web/aweme/post/?${buildQueryString({
2355
2369
  ...this.getBaseParams(),
2356
2370
  sec_user_id: data$1.sec_uid,
2357
- max_cursor: "0",
2371
+ max_cursor: data$1.max_cursor ?? "0",
2358
2372
  locate_query: "false",
2359
2373
  show_live_replay_strategy: "1",
2360
2374
  need_time_list: "1",
2361
2375
  time_list_query: "0",
2362
2376
  whale_cut_token: "",
2363
2377
  cut_version: "1",
2364
- count: "18",
2378
+ count: data$1.number ?? 18,
2365
2379
  publish_video_strategy_type: "2",
2366
2380
  version_code: "170400",
2367
2381
  version_name: "17.4.0",
@@ -2371,6 +2385,70 @@ var init_API$1 = __esmMin(() => {
2371
2385
  webid: "7338423850134226495"
2372
2386
  })}`;
2373
2387
  }
2388
+ getUserFavoriteList(data$1) {
2389
+ return `https://www-hj.douyin.com/aweme/v1/web/aweme/favorite/?${buildQueryString({
2390
+ ...this.getBaseParams(),
2391
+ sec_user_id: data$1.sec_uid,
2392
+ max_cursor: data$1.max_cursor ?? "0",
2393
+ min_cursor: "0",
2394
+ whale_cut_token: "",
2395
+ cut_version: "1",
2396
+ count: data$1.number ?? 18,
2397
+ publish_video_strategy_type: "2",
2398
+ update_version_code: "170400",
2399
+ pc_libra_divert: "Windows",
2400
+ support_h265: "1",
2401
+ support_dash: "1",
2402
+ version_code: "170400",
2403
+ version_name: "17.4.0",
2404
+ screen_width: "2328",
2405
+ screen_height: "1310",
2406
+ round_trip_time: "0",
2407
+ webid: "7487210762873685515"
2408
+ })}`;
2409
+ }
2410
+ getUserRecommendList(data$1) {
2411
+ return `https://www.douyin.com/aweme/v1/web/familiar/recommend/feed/?${buildQueryString({
2412
+ device_platform: "",
2413
+ aid: "6383",
2414
+ channel: "channel_pc_web",
2415
+ sec_user_id: data$1.sec_uid,
2416
+ max_cursor: data$1.max_cursor ?? "0",
2417
+ min_cursor: "0",
2418
+ whale_cut_token: "",
2419
+ count: data$1.number ?? 18,
2420
+ from: "1",
2421
+ update_version_code: "170400",
2422
+ pc_client_type: "1",
2423
+ pc_libra_divert: "Windows",
2424
+ support_h265: "1",
2425
+ support_dash: "1",
2426
+ cpu_core_num: "16",
2427
+ version_code: "170400",
2428
+ version_name: "17.4.0",
2429
+ cookie_enabled: "true",
2430
+ screen_width: "2328",
2431
+ screen_height: "1310",
2432
+ browser_language: "zh-CN",
2433
+ browser_platform: "Win32",
2434
+ browser_name: "Edge",
2435
+ browser_version: this.browserVersion,
2436
+ browser_online: "true",
2437
+ engine_name: "Blink",
2438
+ engine_version: this.browserVersion,
2439
+ os_name: "Windows",
2440
+ os_version: "10",
2441
+ device_memory: "8",
2442
+ platform: "PC",
2443
+ downlink: "10",
2444
+ effective_type: "4g",
2445
+ round_trip_time: "50",
2446
+ webid: "7487210762873685515",
2447
+ msToken: douyinSign.Mstoken(184),
2448
+ verifyFp: fp,
2449
+ fp
2450
+ })}`;
2451
+ }
2374
2452
  getUserProfile(data$1) {
2375
2453
  return `https://www.douyin.com/aweme/v1/web/user/profile/other/?${buildQueryString({
2376
2454
  ...this.getBaseParams(),
@@ -2737,17 +2815,93 @@ var init_getdata$3 = __esmMin(() => {
2737
2815
  });
2738
2816
  }
2739
2817
  case "userVideoList": {
2740
- const url = douyinApiUrls$1.getUserVideoList({ sec_uid: data$1.sec_uid });
2741
- const customConfig = {
2742
- ...baseRequestConfig,
2743
- headers: {
2744
- ...baseRequestConfig.headers,
2745
- ...(!requestConfig?.headers || !("Referer" in requestConfig.headers)) && { Referer: `https://www.douyin.com/user/${data$1.sec_uid}` }
2746
- }
2747
- };
2748
- return await GlobalGetData$3(data$1.methodType, {
2749
- ...customConfig,
2750
- url: buildSignedUrl(url, signType, userAgent)
2818
+ const urlGenerator = (params) => douyinApiUrls$1.getUserVideoList(params);
2819
+ return await fetchPaginatedData({
2820
+ type: data$1.methodType,
2821
+ apiUrlGenerator: urlGenerator,
2822
+ params: {
2823
+ ...data$1,
2824
+ max_cursor: data$1.max_cursor
2825
+ },
2826
+ maxPageSize: 18,
2827
+ requestConfig: {
2828
+ ...baseRequestConfig,
2829
+ headers: {
2830
+ ...baseRequestConfig.headers,
2831
+ ...(!requestConfig?.headers || !("Referer" in requestConfig.headers)) && { Referer: `https://www.douyin.com/user/${data$1.sec_uid}` }
2832
+ }
2833
+ },
2834
+ signType,
2835
+ extractList: (resp) => resp.aweme_list ?? [],
2836
+ updateParams: (params, resp) => ({
2837
+ ...params,
2838
+ max_cursor: resp.max_cursor?.toString() ?? "0"
2839
+ }),
2840
+ hasMore: (resp) => resp.has_more === 1,
2841
+ formatFinalResponse: (resp, list) => ({
2842
+ ...resp,
2843
+ aweme_list: list
2844
+ })
2845
+ });
2846
+ }
2847
+ case "userFavoriteList": {
2848
+ const urlGenerator = (params) => douyinApiUrls$1.getUserFavoriteList(params);
2849
+ return await fetchPaginatedData({
2850
+ type: data$1.methodType,
2851
+ apiUrlGenerator: urlGenerator,
2852
+ params: {
2853
+ ...data$1,
2854
+ max_cursor: data$1.max_cursor
2855
+ },
2856
+ maxPageSize: 18,
2857
+ requestConfig: {
2858
+ ...baseRequestConfig,
2859
+ headers: {
2860
+ ...baseRequestConfig.headers,
2861
+ ...(!requestConfig?.headers || !("Referer" in requestConfig.headers)) && { Referer: `https://www.douyin.com/user/${data$1.sec_uid}` }
2862
+ }
2863
+ },
2864
+ signType,
2865
+ extractList: (resp) => resp.aweme_list ?? [],
2866
+ updateParams: (params, resp) => ({
2867
+ ...params,
2868
+ max_cursor: resp.max_cursor?.toString() ?? "0"
2869
+ }),
2870
+ hasMore: (resp) => resp.has_more === 1,
2871
+ formatFinalResponse: (resp, list) => ({
2872
+ ...resp,
2873
+ aweme_list: list
2874
+ })
2875
+ });
2876
+ }
2877
+ case "userRecommendList": {
2878
+ const urlGenerator = (params) => douyinApiUrls$1.getUserRecommendList(params);
2879
+ return await fetchPaginatedData({
2880
+ type: data$1.methodType,
2881
+ apiUrlGenerator: urlGenerator,
2882
+ params: {
2883
+ ...data$1,
2884
+ max_cursor: data$1.max_cursor
2885
+ },
2886
+ maxPageSize: 18,
2887
+ requestConfig: {
2888
+ ...baseRequestConfig,
2889
+ headers: {
2890
+ ...baseRequestConfig.headers,
2891
+ ...(!requestConfig?.headers || !("Referer" in requestConfig.headers)) && { Referer: `https://www.douyin.com/user/${data$1.sec_uid}` }
2892
+ }
2893
+ },
2894
+ signType,
2895
+ extractList: (resp) => resp.aweme_list ?? [],
2896
+ updateParams: (params, resp) => ({
2897
+ ...params,
2898
+ max_cursor: resp.max_cursor?.toString() ?? "0"
2899
+ }),
2900
+ hasMore: (resp) => resp.has_more === true,
2901
+ formatFinalResponse: (resp, list) => ({
2902
+ ...resp,
2903
+ aweme_list: list
2904
+ })
2751
2905
  });
2752
2906
  }
2753
2907
  case "suggestWords": {
@@ -3240,6 +3394,18 @@ async function fetchUserVideoList(options, cookie, requestConfig) {
3240
3394
  requestConfig
3241
3395
  });
3242
3396
  }
3397
+ async function fetchUserFavoriteList(options, cookie, requestConfig) {
3398
+ return fetchDouyinInternal("userFavoriteList", options, {
3399
+ cookie,
3400
+ requestConfig
3401
+ });
3402
+ }
3403
+ async function fetchUserRecommendList(options, cookie, requestConfig) {
3404
+ return fetchDouyinInternal("userRecommendList", options, {
3405
+ cookie,
3406
+ requestConfig
3407
+ });
3408
+ }
3243
3409
  var init_user$1 = __esmMin(() => {
3244
3410
  init_internal$2();
3245
3411
  });
@@ -3294,6 +3460,8 @@ function createBoundDouyinFetcher(cookie, requestConfig) {
3294
3460
  fetchCommentReplies: (options, reqConfig) => fetchCommentReplies(options, cookie, reqConfig ?? requestConfig),
3295
3461
  fetchUserProfile: (options, reqConfig) => fetchUserProfile$1(options, cookie, reqConfig ?? requestConfig),
3296
3462
  fetchUserVideoList: (options, reqConfig) => fetchUserVideoList(options, cookie, reqConfig ?? requestConfig),
3463
+ fetchUserFavoriteList: (options, reqConfig) => fetchUserFavoriteList(options, cookie, reqConfig ?? requestConfig),
3464
+ fetchUserRecommendList: (options, reqConfig) => fetchUserRecommendList(options, cookie, reqConfig ?? requestConfig),
3297
3465
  searchContent: (options, reqConfig) => searchContent(options, cookie, reqConfig ?? requestConfig),
3298
3466
  fetchSuggestWords: (options, reqConfig) => fetchSuggestWords(options, cookie, reqConfig ?? requestConfig),
3299
3467
  fetchMusicInfo: (options, reqConfig) => fetchMusicInfo(options, cookie, reqConfig ?? requestConfig),
@@ -3334,6 +3502,8 @@ var init_douyin$2 = __esmMin(() => {
3334
3502
  fetchCommentReplies,
3335
3503
  fetchUserProfile: fetchUserProfile$1,
3336
3504
  fetchUserVideoList,
3505
+ fetchUserFavoriteList,
3506
+ fetchUserRecommendList,
3337
3507
  searchContent,
3338
3508
  fetchSuggestWords,
3339
3509
  fetchMusicInfo,
@@ -5597,7 +5767,7 @@ var init_src = __esmMin(() => {
5597
5767
  init_server();
5598
5768
  init_types$1();
5599
5769
  init_api_spec();
5600
- getVersion = () => "6.0.0-beta.0";
5770
+ getVersion = () => "6.0.0-beta.2";
5601
5771
  VERSION = getVersion();
5602
5772
  Object.defineProperty(CreateAmagiApp, "version", {
5603
5773
  value: VERSION,
@@ -5649,6 +5819,121 @@ var init_root = __esmMin(() => {
5649
5819
  karinVersion: process.env.KARIN_VERSION
5650
5820
  };
5651
5821
  });
5822
+ var amagiClient_exports = __export({
5823
+ AmagiBase: () => AmagiBase,
5824
+ AmagiError: () => AmagiError,
5825
+ bilibiliFetcher: () => bilibiliFetcher,
5826
+ douyinFetcher: () => douyinFetcher,
5827
+ kuaishouFetcher: () => kuaishouFetcher,
5828
+ reloadAmagiConfig: () => reloadAmagiConfig,
5829
+ xiaohongshuFetcher: () => xiaohongshuFetcher
5830
+ }, 1);
5831
+ var AmagiError, AmagiBase, amagiClientInstance, amagiClient, reloadAmagiConfig, bilibiliFetcher, douyinFetcher, kuaishouFetcher, xiaohongshuFetcher;
5832
+ var init_amagiClient = __esmMin(() => {
5833
+ init_src();
5834
+ init_Config();
5835
+ AmagiError = class extends Error {
5836
+ code;
5837
+ data;
5838
+ rawError;
5839
+ constructor(code, message, data$1, rawError) {
5840
+ super(message);
5841
+ this.name = "AmagiError";
5842
+ this.code = code;
5843
+ this.data = data$1;
5844
+ this.rawError = rawError;
5845
+ }
5846
+ };
5847
+ AmagiBase = class {
5848
+ amagi;
5849
+ constructor() {
5850
+ const client = this.createAmagiClient();
5851
+ this.amagi = this.wrapAmagiClient(client);
5852
+ }
5853
+ createAmagiClient = () => Client({
5854
+ cookies: {
5855
+ douyin: Config.cookies.douyin,
5856
+ bilibili: Config.cookies.bilibili,
5857
+ kuaishou: Config.cookies.kuaishou,
5858
+ xiaohongshu: Config.cookies.xiaohongshu
5859
+ },
5860
+ request: {
5861
+ timeout: Config.request.timeout,
5862
+ headers: { "User-Agent": Config.request["User-Agent"] },
5863
+ proxy: Config.request.proxy?.switch ? Config.request.proxy : false
5864
+ }
5865
+ });
5866
+ reloadConfig() {
5867
+ logger.debug("[AmagiClient] 检测到配置变化,正在重载...");
5868
+ const oldCookies = {
5869
+ douyin: Config.cookies.douyin?.substring(0, 20) + "...",
5870
+ bilibili: Config.cookies.bilibili?.substring(0, 20) + "...",
5871
+ kuaishou: Config.cookies.kuaishou?.substring(0, 20) + "...",
5872
+ xiaohongshu: Config.cookies.xiaohongshu?.substring(0, 20) + "..."
5873
+ };
5874
+ const client = this.createAmagiClient();
5875
+ this.amagi = this.wrapAmagiClient(client);
5876
+ const newCookies = {
5877
+ douyin: Config.cookies.douyin?.substring(0, 20) + "...",
5878
+ bilibili: Config.cookies.bilibili?.substring(0, 20) + "...",
5879
+ kuaishou: Config.cookies.kuaishou?.substring(0, 20) + "...",
5880
+ xiaohongshu: Config.cookies.xiaohongshu?.substring(0, 20) + "..."
5881
+ };
5882
+ logger.debug("[AmagiClient] 配置重载完成");
5883
+ logger.debug(`[AmagiClient] Cookie 变化对比:\n${util.inspect({
5884
+ "旧配置": oldCookies,
5885
+ "新配置": newCookies
5886
+ }, {
5887
+ colors: true,
5888
+ depth: 2
5889
+ })}`);
5890
+ }
5891
+ wrapAmagiClient = (client) => {
5892
+ const createProxy = (target) => new Proxy(target, { get(obj, prop) {
5893
+ const value = obj[prop];
5894
+ if (value && typeof value === "object" && !Array.isArray(value)) return createProxy(value);
5895
+ if (typeof value === "function") return async (...args) => {
5896
+ const result = await value.apply(obj, args);
5897
+ const isResultType = (val) => {
5898
+ if (!val || typeof val !== "object") return false;
5899
+ if (!("success" in val) || typeof val.success !== "boolean") return false;
5900
+ if (!("code" in val) || !("message" in val)) return false;
5901
+ return true;
5902
+ };
5903
+ if (isResultType(result)) {
5904
+ if (result.success === true) return result;
5905
+ const errMessage = result.message || result.error?.amagiMessage || "请求失败";
5906
+ const errorDetails = util.inspect({
5907
+ code: result.code,
5908
+ data: result.data,
5909
+ message: errMessage,
5910
+ error: result.error
5911
+ }, {
5912
+ depth: 10,
5913
+ colors: true,
5914
+ compact: false,
5915
+ breakLength: 120,
5916
+ showHidden: true
5917
+ });
5918
+ throw new AmagiError(result.code, errorDetails, result.data, result.error);
5919
+ }
5920
+ return result;
5921
+ };
5922
+ return value;
5923
+ } });
5924
+ return createProxy(client);
5925
+ };
5926
+ };
5927
+ amagiClientInstance = new AmagiBase();
5928
+ amagiClient = amagiClientInstance.amagi;
5929
+ reloadAmagiConfig = () => {
5930
+ amagiClientInstance.reloadConfig();
5931
+ };
5932
+ bilibiliFetcher = amagiClient.bilibili.fetcher;
5933
+ douyinFetcher = amagiClient.douyin.fetcher;
5934
+ kuaishouFetcher = amagiClient.kuaishou.fetcher;
5935
+ xiaohongshuFetcher = amagiClient.xiaohongshu.fetcher;
5936
+ });
5652
5937
  var Cfg, configInstance, getConfigInstance, Config;
5653
5938
  var init_Config = __esmMin(() => {
5654
5939
  init_root();
@@ -5669,7 +5954,17 @@ var init_Config = __esmMin(() => {
5669
5954
  if (differences) fs.writeFileSync(`${this.dirCfgPath}/${file}`, result.toString({ lineWidth: -1 }));
5670
5955
  }
5671
5956
  setTimeout(() => {
5672
- filesByExt(this.dirCfgPath, ".yaml", "abs").forEach((file) => watch(file, (_old, _now) => {}));
5957
+ filesByExt(this.dirCfgPath, ".yaml", "abs").forEach((file) => watch(file, (_old, _now) => {
5958
+ const fileName = path.basename(file, ".yaml");
5959
+ if (fileName === "cookies" || fileName === "request") {
5960
+ logger.debug(`[Config] 检测到 ${fileName} 配置变化,正在重载 Amagi Client...`);
5961
+ Promise.resolve().then(() => (init_amagiClient(), amagiClient_exports)).then(({ reloadAmagiConfig: reloadAmagiConfig$1 }) => {
5962
+ reloadAmagiConfig$1();
5963
+ }).catch((error) => {
5964
+ logger.error(`[Config] 重载 Amagi Client 失败: ${error}`);
5965
+ });
5966
+ }
5967
+ }));
5673
5968
  }, 2e3);
5674
5969
  return this;
5675
5970
  }
@@ -5852,82 +6147,6 @@ var init_Config = __esmMin(() => {
5852
6147
  Config = new Proxy({}, { get(target, prop) {
5853
6148
  return getConfigInstance()[prop];
5854
6149
  } });
5855
- }), AmagiError, AmagiBase, amagiClient, bilibiliFetcher, douyinFetcher, kuaishouFetcher;
5856
- var init_amagiClient = __esmMin(() => {
5857
- init_src();
5858
- init_Config();
5859
- AmagiError = class extends Error {
5860
- code;
5861
- data;
5862
- rawError;
5863
- constructor(code, message, data$1, rawError) {
5864
- super(message);
5865
- this.name = "AmagiError";
5866
- this.code = code;
5867
- this.data = data$1;
5868
- this.rawError = rawError;
5869
- }
5870
- };
5871
- AmagiBase = class {
5872
- amagi;
5873
- constructor() {
5874
- const client = this.createAmagiClient();
5875
- this.amagi = this.wrapAmagiClient(client);
5876
- }
5877
- createAmagiClient = () => Client({
5878
- cookies: {
5879
- douyin: Config.cookies.douyin,
5880
- bilibili: Config.cookies.bilibili,
5881
- kuaishou: Config.cookies.kuaishou,
5882
- xiaohongshu: Config.cookies.xiaohongshu
5883
- },
5884
- request: {
5885
- timeout: Config.request.timeout,
5886
- headers: { "User-Agent": Config.request["User-Agent"] },
5887
- proxy: Config.request.proxy?.switch ? Config.request.proxy : false
5888
- }
5889
- });
5890
- wrapAmagiClient = (client) => {
5891
- const createProxy = (target) => new Proxy(target, { get(obj, prop) {
5892
- const value = obj[prop];
5893
- if (value && typeof value === "object" && !Array.isArray(value)) return createProxy(value);
5894
- if (typeof value === "function") return async (...args) => {
5895
- const result = await value.apply(obj, args);
5896
- const isResultType = (val) => {
5897
- if (!val || typeof val !== "object") return false;
5898
- if (!("success" in val) || typeof val.success !== "boolean") return false;
5899
- if (!("code" in val) || !("message" in val)) return false;
5900
- return true;
5901
- };
5902
- if (isResultType(result)) {
5903
- if (result.success === true) return result;
5904
- const errMessage = result.message || result.error?.amagiMessage || "请求失败";
5905
- const errorDetails = util.inspect({
5906
- code: result.code,
5907
- data: result.data,
5908
- message: errMessage,
5909
- error: result.error
5910
- }, {
5911
- depth: 10,
5912
- colors: true,
5913
- compact: false,
5914
- breakLength: 120,
5915
- showHidden: true
5916
- });
5917
- throw new AmagiError(result.code, errorDetails, result.data, result.error);
5918
- }
5919
- return result;
5920
- };
5921
- return value;
5922
- } });
5923
- return createProxy(client);
5924
- };
5925
- };
5926
- amagiClient = new AmagiBase().amagi;
5927
- bilibiliFetcher = amagiClient.bilibili.fetcher;
5928
- douyinFetcher = amagiClient.douyin.fetcher;
5929
- kuaishouFetcher = amagiClient.kuaishou.fetcher;
5930
- amagiClient.xiaohongshu.fetcher;
5931
6150
  });
5932
6151
  var Base, statBotId$1, Count, uploadFile, downloadVideo, downloadFile, processFilename;
5933
6152
  var init_Base = __esmMin(() => {
@@ -7913,7 +8132,7 @@ var init_bilibili = __esmMin(async () => {
7913
8132
  async createTables() {
7914
8133
  for (const query of [
7915
8134
  `CREATE TABLE IF NOT EXISTS Bots (\n id TEXT PRIMARY KEY,\n createdAt TEXT DEFAULT CURRENT_TIMESTAMP,\n updatedAt TEXT DEFAULT CURRENT_TIMESTAMP\n )`,
7916
- `CREATE TABLE IF NOT EXISTS Groups (\n id TEXT PRIMARY KEY,\n botId TEXT NOT NULL,\n createdAt TEXT DEFAULT CURRENT_TIMESTAMP,\n updatedAt TEXT DEFAULT CURRENT_TIMESTAMP,\n FOREIGN KEY (botId) REFERENCES Bots(id)\n )`,
8135
+ `CREATE TABLE IF NOT EXISTS Groups (\n id TEXT NOT NULL,\n botId TEXT NOT NULL,\n createdAt TEXT DEFAULT CURRENT_TIMESTAMP,\n updatedAt TEXT DEFAULT CURRENT_TIMESTAMP,\n PRIMARY KEY (id, botId),\n FOREIGN KEY (botId) REFERENCES Bots(id)\n )`,
7917
8136
  `CREATE TABLE IF NOT EXISTS BilibiliUsers (\n host_mid INTEGER PRIMARY KEY,\n remark TEXT,\n filterMode TEXT DEFAULT 'blacklist',\n createdAt TEXT DEFAULT CURRENT_TIMESTAMP,\n updatedAt TEXT DEFAULT CURRENT_TIMESTAMP\n )`,
7918
8137
  `CREATE TABLE IF NOT EXISTS GroupUserSubscriptions (\n groupId TEXT,\n host_mid INTEGER,\n createdAt TEXT DEFAULT CURRENT_TIMESTAMP,\n updatedAt TEXT DEFAULT CURRENT_TIMESTAMP,\n PRIMARY KEY (groupId, host_mid),\n FOREIGN KEY (groupId) REFERENCES Groups(id),\n FOREIGN KEY (host_mid) REFERENCES BilibiliUsers(host_mid)\n )`,
7919
8138
  `CREATE TABLE IF NOT EXISTS DynamicCaches (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n dynamic_id TEXT NOT NULL,\n host_mid INTEGER NOT NULL,\n groupId TEXT NOT NULL,\n dynamic_type TEXT,\n createdAt TEXT DEFAULT CURRENT_TIMESTAMP,\n updatedAt TEXT DEFAULT CURRENT_TIMESTAMP,\n FOREIGN KEY (host_mid) REFERENCES BilibiliUsers(host_mid),\n FOREIGN KEY (groupId) REFERENCES Groups(id),\n UNIQUE(dynamic_id, host_mid, groupId)\n )`,
@@ -8399,6 +8618,7 @@ var init_douyin = __esmMin(async () => {
8399
8618
  await fs.promises.mkdir(path.dirname(this.dbPath), { recursive: true });
8400
8619
  this.db = new sqlite3.Database(this.dbPath);
8401
8620
  await this.createTables();
8621
+ await this.migrate();
8402
8622
  logger.debug("[DouyinDB] 数据库模型同步成功");
8403
8623
  logger.debug("[DouyinDB] 正在同步配置订阅...");
8404
8624
  logger.debug("[DouyinDB] 配置项数量:", Config.pushlist.douyin?.length || 0);
@@ -8411,15 +8631,33 @@ var init_douyin = __esmMin(async () => {
8411
8631
  }
8412
8632
  return this;
8413
8633
  }
8634
+ async migrate() {
8635
+ try {
8636
+ try {
8637
+ await this.runQuery("SELECT pushType FROM AwemeCaches LIMIT 1");
8638
+ } catch {
8639
+ logger.info("[DouyinDB] 检测到 AwemeCaches 表缺少 pushType 字段,开始执行迁移...");
8640
+ await this.runQuery("ALTER TABLE AwemeCaches ADD COLUMN pushType TEXT DEFAULT 'post'");
8641
+ await this.runQuery("ALTER TABLE AwemeCaches RENAME TO AwemeCaches_old");
8642
+ await this.runQuery(`\n CREATE TABLE IF NOT EXISTS AwemeCaches (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n aweme_id TEXT NOT NULL,\n sec_uid TEXT NOT NULL,\n groupId TEXT NOT NULL,\n pushType TEXT DEFAULT 'post',\n createdAt TEXT DEFAULT CURRENT_TIMESTAMP,\n updatedAt TEXT DEFAULT CURRENT_TIMESTAMP,\n FOREIGN KEY (sec_uid) REFERENCES DouyinUsers(sec_uid),\n FOREIGN KEY (groupId) REFERENCES Groups(id),\n UNIQUE(aweme_id, sec_uid, groupId, pushType)\n )\n `);
8643
+ await this.runQuery(`\n INSERT INTO AwemeCaches (id, aweme_id, sec_uid, groupId, pushType, createdAt, updatedAt)\n SELECT id, aweme_id, sec_uid, groupId, pushType, createdAt, updatedAt\n FROM AwemeCaches_old\n `);
8644
+ await this.runQuery("DROP TABLE AwemeCaches_old");
8645
+ logger.info("[DouyinDB] AwemeCaches 表迁移完成");
8646
+ }
8647
+ } catch (error) {
8648
+ logger.error("[DouyinDB] 数据库迁移失败:", error);
8649
+ }
8650
+ }
8414
8651
  async createTables() {
8415
8652
  for (const query of [
8416
8653
  `CREATE TABLE IF NOT EXISTS Bots (\n id TEXT PRIMARY KEY,\n createdAt TEXT DEFAULT CURRENT_TIMESTAMP,\n updatedAt TEXT DEFAULT CURRENT_TIMESTAMP\n )`,
8417
- `CREATE TABLE IF NOT EXISTS Groups (\n id TEXT PRIMARY KEY,\n botId TEXT NOT NULL,\n createdAt TEXT DEFAULT CURRENT_TIMESTAMP,\n updatedAt TEXT DEFAULT CURRENT_TIMESTAMP,\n FOREIGN KEY (botId) REFERENCES Bots(id)\n )`,
8654
+ `CREATE TABLE IF NOT EXISTS Groups (\n id TEXT NOT NULL,\n botId TEXT NOT NULL,\n createdAt TEXT DEFAULT CURRENT_TIMESTAMP,\n updatedAt TEXT DEFAULT CURRENT_TIMESTAMP,\n PRIMARY KEY (id, botId),\n FOREIGN KEY (botId) REFERENCES Bots(id)\n )`,
8418
8655
  `CREATE TABLE IF NOT EXISTS DouyinUsers (\n sec_uid TEXT PRIMARY KEY,\n short_id TEXT,\n remark TEXT,\n living INTEGER DEFAULT 0,\n filterMode TEXT DEFAULT 'blacklist',\n createdAt TEXT DEFAULT CURRENT_TIMESTAMP,\n updatedAt TEXT DEFAULT CURRENT_TIMESTAMP\n )`,
8419
8656
  `CREATE TABLE IF NOT EXISTS GroupUserSubscriptions (\n groupId TEXT,\n sec_uid TEXT,\n createdAt TEXT DEFAULT CURRENT_TIMESTAMP,\n updatedAt TEXT DEFAULT CURRENT_TIMESTAMP,\n PRIMARY KEY (groupId, sec_uid),\n FOREIGN KEY (groupId) REFERENCES Groups(id),\n FOREIGN KEY (sec_uid) REFERENCES DouyinUsers(sec_uid)\n )`,
8420
- `CREATE TABLE IF NOT EXISTS AwemeCaches (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n aweme_id TEXT NOT NULL,\n sec_uid TEXT NOT NULL,\n groupId TEXT NOT NULL,\n createdAt TEXT DEFAULT CURRENT_TIMESTAMP,\n updatedAt TEXT DEFAULT CURRENT_TIMESTAMP,\n FOREIGN KEY (sec_uid) REFERENCES DouyinUsers(sec_uid),\n FOREIGN KEY (groupId) REFERENCES Groups(id),\n UNIQUE(aweme_id, sec_uid, groupId)\n )`,
8657
+ `CREATE TABLE IF NOT EXISTS AwemeCaches (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n aweme_id TEXT NOT NULL,\n sec_uid TEXT NOT NULL,\n groupId TEXT NOT NULL,\n pushType TEXT DEFAULT 'post',\n createdAt TEXT DEFAULT CURRENT_TIMESTAMP,\n updatedAt TEXT DEFAULT CURRENT_TIMESTAMP,\n FOREIGN KEY (sec_uid) REFERENCES DouyinUsers(sec_uid),\n FOREIGN KEY (groupId) REFERENCES Groups(id),\n UNIQUE(aweme_id, sec_uid, groupId, pushType)\n )`,
8421
8658
  `CREATE TABLE IF NOT EXISTS FilterWords (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n sec_uid TEXT NOT NULL,\n word TEXT NOT NULL,\n createdAt TEXT DEFAULT CURRENT_TIMESTAMP,\n updatedAt TEXT DEFAULT CURRENT_TIMESTAMP,\n FOREIGN KEY (sec_uid) REFERENCES DouyinUsers(sec_uid),\n UNIQUE(sec_uid, word)\n )`,
8422
- `CREATE TABLE IF NOT EXISTS FilterTags (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n sec_uid TEXT NOT NULL,\n tag TEXT NOT NULL,\n createdAt TEXT DEFAULT CURRENT_TIMESTAMP,\n updatedAt TEXT DEFAULT CURRENT_TIMESTAMP,\n FOREIGN KEY (sec_uid) REFERENCES DouyinUsers(sec_uid),\n UNIQUE(sec_uid, tag)\n )`
8659
+ `CREATE TABLE IF NOT EXISTS FilterTags (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n sec_uid TEXT NOT NULL,\n tag TEXT NOT NULL,\n createdAt TEXT DEFAULT CURRENT_TIMESTAMP,\n updatedAt TEXT DEFAULT CURRENT_TIMESTAMP,\n FOREIGN KEY (sec_uid) REFERENCES DouyinUsers(sec_uid),\n UNIQUE(sec_uid, tag)\n )`,
8660
+ `CREATE TABLE IF NOT EXISTS ListSnapshots (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n sec_uid TEXT NOT NULL,\n pushType TEXT NOT NULL,\n aweme_id TEXT NOT NULL,\n createdAt TEXT DEFAULT CURRENT_TIMESTAMP,\n updatedAt TEXT DEFAULT CURRENT_TIMESTAMP,\n FOREIGN KEY (sec_uid) REFERENCES DouyinUsers(sec_uid),\n UNIQUE(sec_uid, pushType, aweme_id)\n )`
8423
8661
  ]) await this.runQuery(query);
8424
8662
  }
8425
8663
  runQuery(sql, params = []) {
@@ -8561,36 +8799,47 @@ var init_douyin = __esmMin(async () => {
8561
8799
  await this.runQuery("DELETE FROM AwemeCaches WHERE groupId = ? AND sec_uid = ?", [groupId, sec_uid]);
8562
8800
  return result.changes > 0;
8563
8801
  }
8564
- async addAwemeCache(aweme_id, sec_uid, groupId) {
8565
- let cache = await this.getQuery("SELECT * FROM AwemeCaches WHERE aweme_id = ? AND sec_uid = ? AND groupId = ?", [
8802
+ async addAwemeCache(aweme_id, sec_uid, groupId, pushType = "post") {
8803
+ let cache = await this.getQuery("SELECT * FROM AwemeCaches WHERE aweme_id = ? AND sec_uid = ? AND groupId = ? AND pushType = ?", [
8566
8804
  aweme_id,
8567
8805
  sec_uid,
8568
- groupId
8806
+ groupId,
8807
+ pushType
8569
8808
  ]);
8570
8809
  if (!cache) {
8571
8810
  const now = (/* @__PURE__ */ new Date()).toISOString();
8572
8811
  cache = {
8573
- id: (await this.runQuery("INSERT INTO AwemeCaches (aweme_id, sec_uid, groupId, createdAt, updatedAt) VALUES (?, ?, ?, ?, ?)", [
8812
+ id: (await this.runQuery("INSERT INTO AwemeCaches (aweme_id, sec_uid, groupId, pushType, createdAt, updatedAt) VALUES (?, ?, ?, ?, ?, ?)", [
8574
8813
  aweme_id,
8575
8814
  sec_uid,
8576
8815
  groupId,
8816
+ pushType,
8577
8817
  now,
8578
8818
  now
8579
8819
  ])).lastID,
8580
8820
  aweme_id,
8581
8821
  sec_uid,
8582
8822
  groupId,
8823
+ pushType,
8583
8824
  createdAt: now,
8584
8825
  updatedAt: now
8585
8826
  };
8586
8827
  }
8587
8828
  return cache;
8588
8829
  }
8589
- async isAwemePushed(aweme_id, sec_uid, groupId) {
8590
- return ((await this.getQuery("SELECT COUNT(*) as count FROM AwemeCaches WHERE aweme_id = ? AND sec_uid = ? AND groupId = ?", [
8830
+ async isAwemePushed(aweme_id, sec_uid, groupId, pushType = "post") {
8831
+ return ((await this.getQuery("SELECT COUNT(*) as count FROM AwemeCaches WHERE aweme_id = ? AND sec_uid = ? AND groupId = ? AND pushType = ?", [
8591
8832
  aweme_id,
8592
8833
  sec_uid,
8593
- groupId
8834
+ groupId,
8835
+ pushType
8836
+ ]))?.count || 0) > 0;
8837
+ }
8838
+ async hasHistory(sec_uid, groupId, pushType) {
8839
+ return ((await this.getQuery("SELECT COUNT(*) as count FROM AwemeCaches WHERE sec_uid = ? AND groupId = ? AND pushType = ? LIMIT 1", [
8840
+ sec_uid,
8841
+ groupId,
8842
+ pushType
8594
8843
  ]))?.count || 0) > 0;
8595
8844
  }
8596
8845
  async getBotGroups(botId) {
@@ -8871,6 +9120,24 @@ var init_douyin = __esmMin(async () => {
8871
9120
  }
8872
9121
  };
8873
9122
  }
9123
+ async isAwemeInList(aweme_id, sec_uid, pushType) {
9124
+ return ((await this.getQuery("SELECT COUNT(*) as count FROM ListSnapshots WHERE aweme_id = ? AND sec_uid = ? AND pushType = ?", [
9125
+ aweme_id,
9126
+ sec_uid,
9127
+ pushType
9128
+ ]))?.count || 0) > 0;
9129
+ }
9130
+ async updateListSnapshot(sec_uid, pushType, aweme_ids) {
9131
+ const now = (/* @__PURE__ */ new Date()).toISOString();
9132
+ await this.runQuery("DELETE FROM ListSnapshots WHERE sec_uid = ? AND pushType = ?", [sec_uid, pushType]);
9133
+ for (const aweme_id of aweme_ids) await this.runQuery("INSERT OR IGNORE INTO ListSnapshots (sec_uid, pushType, aweme_id, createdAt, updatedAt) VALUES (?, ?, ?, ?, ?)", [
9134
+ sec_uid,
9135
+ pushType,
9136
+ aweme_id,
9137
+ now,
9138
+ now
9139
+ ]);
9140
+ }
8874
9141
  };
8875
9142
  });
8876
9143
  var db_exports = __export({
@@ -13564,7 +13831,7 @@ const webConfig = defineConfig({
13564
13831
  children: [components.accordion.createItem("cfg:cookies", {
13565
13832
  title: "Cookies 相关",
13566
13833
  className: "ml-4 mr-4",
13567
- subtitle: "建议配置,否则大部分功能无法使用,此部分修改后需重启方可生效!",
13834
+ subtitle: "建议配置,否则大部分功能无法使用",
13568
13835
  children: [
13569
13836
  components.input.string("douyin", {
13570
13837
  label: "抖音",
@@ -13578,7 +13845,7 @@ const webConfig = defineConfig({
13578
13845
  components.input.string("bilibili", {
13579
13846
  label: "B站",
13580
13847
  type: "text",
13581
- description: "请输入你的B站Cookies,不输入则无法使用B站相关功能噢",
13848
+ description: "请输入你的B站Cookies,不输入部分功能将受限噢",
13582
13849
  defaultValue: all.cookies.bilibili,
13583
13850
  placeholder: "",
13584
13851
  rules: void 0,
@@ -14058,6 +14325,38 @@ const webConfig = defineConfig({
14058
14325
  isRequired: false,
14059
14326
  description: "博主的抖音名称"
14060
14327
  }),
14328
+ components.divider.create("push:douyin:divider-pushTypes", {
14329
+ description: "推送类型配置",
14330
+ descPosition: 20
14331
+ }),
14332
+ components.checkbox.group("pushTypes", {
14333
+ label: "推送类型",
14334
+ description: "选择要推送的内容类型,可多选",
14335
+ orientation: "horizontal",
14336
+ color: "warning",
14337
+ checkbox: [
14338
+ components.checkbox.create("pushTypes:checkbox:post", {
14339
+ label: "作品列表",
14340
+ description: "推送博主发布的作品",
14341
+ value: "post"
14342
+ }),
14343
+ components.checkbox.create("pushTypes:checkbox:favorite", {
14344
+ label: "喜欢列表",
14345
+ description: "推送博主喜欢的作品",
14346
+ value: "favorite"
14347
+ }),
14348
+ components.checkbox.create("pushTypes:checkbox:recommend", {
14349
+ label: "推荐列表",
14350
+ description: "推送博主的推荐作品",
14351
+ value: "recommend"
14352
+ }),
14353
+ components.checkbox.create("pushTypes:checkbox:live", {
14354
+ label: "直播",
14355
+ description: "推送博主开播通知",
14356
+ value: "live"
14357
+ })
14358
+ ]
14359
+ }),
14061
14360
  components.divider.create("push:douyin:divider-1", {
14062
14361
  description: "过滤系统",
14063
14362
  descPosition: 20
@@ -14197,16 +14496,26 @@ const webConfig = defineConfig({
14197
14496
  cleanFlattenedFields(mergeCfg);
14198
14497
  let success = false;
14199
14498
  let isChange = false;
14499
+ let needReloadAmagi = false;
14200
14500
  for (const key of Object.keys(mergeCfg)) {
14201
14501
  const configValue = mergeCfg[key];
14202
14502
  if (configValue && typeof configValue === "object" && Object.keys(configValue).length > 0) {
14203
14503
  isChange = deepEqual(configValue, oldAllCfg[key]);
14204
14504
  if (isChange) {
14205
- if (await Config.ModifyPro(key, configValue)) success = true;
14505
+ if (await Config.ModifyPro(key, configValue)) {
14506
+ success = true;
14507
+ if (key === "cookies" || key === "request") needReloadAmagi = true;
14508
+ }
14206
14509
  }
14207
14510
  }
14208
14511
  }
14209
14512
  await Config.syncConfigToDatabase();
14513
+ if (needReloadAmagi) try {
14514
+ const { reloadAmagiConfig: reloadAmagiConfig$1 } = await Promise.resolve().then(() => (init_amagiClient(), amagiClient_exports));
14515
+ reloadAmagiConfig$1();
14516
+ } catch (error) {
14517
+ logger.error(`[WebConfig] 重载 Amagi Client 失败: ${error}`);
14518
+ }
14210
14519
  return {
14211
14520
  mergeCfg,
14212
14521
  formatCfg,
@@ -16538,7 +16847,7 @@ const douyinComments = async (data$1, emojidata) => {
16538
16847
  const replyCommentsList = [];
16539
16848
  if (replyComment.data.comments && replyComment.data.comments.length > 0) for (const reply of replyComment.data.comments) {
16540
16849
  const replyItem = reply;
16541
- const replyUserintextlongid = replyItem.text_extra && replyItem.text_extra[0] && replyItem.text_extra[0].sec_uid ? replyItem.text_extra.map((extra) => extra.sec_uid) : null;
16850
+ const replyUserintextlongid = replyItem.text_extra && replyItem.text_extra[0] && replyItem.text_extra[0].sec_uid ? replyItem.text_extra.filter((extra) => extra.sec_uid).map((extra) => extra.sec_uid) : null;
16542
16851
  const processedReplyText = await processAtUsers$1(replyItem.text, replyUserintextlongid);
16543
16852
  const replyImageUrl = replyItem.image_list?.[0]?.origin_url?.url_list?.[0];
16544
16853
  const replyStickerUrl = replyItem.sticker?.animate_url?.url_list?.[0];
@@ -16624,6 +16933,7 @@ var DouYin = class extends Base {
16624
16933
  is_mp4;
16625
16934
  is_slides;
16626
16935
  forceBurnDanmaku;
16936
+ hasProcessedLiveImage;
16627
16937
  get botadapter() {
16628
16938
  return this.e.bot?.adapter?.name;
16629
16939
  }
@@ -16634,6 +16944,7 @@ var DouYin = class extends Base {
16634
16944
  this.is_mp4 = iddata?.is_mp4;
16635
16945
  this.is_slides = false;
16636
16946
  this.forceBurnDanmaku = options?.forceBurnDanmaku ?? false;
16947
+ this.hasProcessedLiveImage = false;
16637
16948
  }
16638
16949
  async DouyinHandler(data$1) {
16639
16950
  if (Config.app.EmojiReply && !this.e.isPrivate) try {
@@ -16664,36 +16975,121 @@ var DouYin = class extends Base {
16664
16975
  const imageres = [];
16665
16976
  let image_url = "";
16666
16977
  const images = VideoData.data.aweme_detail.images ?? [];
16667
- for (const [index, imageItem] of images.entries()) {
16668
- image_url = imageItem.url_list[2] || imageItem.url_list[1];
16978
+ if (images.some((item) => item.clip_type !== 2)) {
16979
+ const processedImages = [];
16980
+ const temp = [];
16669
16981
  g_title = VideoData.data.aweme_detail.preview_title.substring(0, 50).replace(/[\\/:*?"<>|\r\n]/g, " ");
16670
- imageres.push(segment.image(image_url));
16671
- imagenum++;
16672
- if (Config.app.removeCache === false) {
16673
- mkdirSync(`${Common.tempDri.images}${g_title}`);
16674
- const path$1 = `${Common.tempDri.images}${g_title}/${index + 1}.png`;
16675
- await new Network({
16676
- url: image_url,
16677
- type: "arraybuffer"
16678
- }).getData().then((data$2) => fs.promises.writeFile(path$1, Buffer.from(data$2)));
16982
+ let mp3Path = "";
16983
+ if (VideoData.data.aweme_detail.music.play_url.uri === "") mp3Path = JSON.parse(VideoData.data.aweme_detail.music.extra).original_song_url;
16984
+ else mp3Path = VideoData.data.aweme_detail.music.play_url.uri;
16985
+ const liveimgbgm = await downloadFile(mp3Path, {
16986
+ title: `Douyin_tmp_A_${Date.now()}.mp3`,
16987
+ headers: this.headers
16988
+ });
16989
+ temp.push(liveimgbgm);
16990
+ const mergeMode = Config.douyin.liveImageMergeMode ?? "independent";
16991
+ let bgmContext = null;
16992
+ if (mergeMode === "continuous") bgmContext = await createLiveImageContext(liveimgbgm.filepath);
16993
+ for (const [index, imageItem] of images.entries()) {
16994
+ imagenum++;
16995
+ if (imageItem.clip_type === 2) {
16996
+ image_url = imageItem.url_list[2] || imageItem.url_list[1];
16997
+ processedImages.push(segment.image(image_url));
16998
+ if (Config.app.removeCache === false) {
16999
+ mkdirSync(`${Common.tempDri.images}${g_title}`);
17000
+ const path$1 = `${Common.tempDri.images}${g_title}/${index + 1}.png`;
17001
+ await new Network({
17002
+ url: image_url,
17003
+ type: "arraybuffer"
17004
+ }).getData().then((data$2) => fs.promises.writeFile(path$1, Buffer.from(data$2)));
17005
+ }
17006
+ continue;
17007
+ }
17008
+ const liveimg = await downloadFile(`https://aweme.snssdk.com/aweme/v1/play/?video_id=${imageItem.video.play_addr_h264.uri}&ratio=1080p&line=0`, {
17009
+ title: `Douyin_tmp_V_${Date.now()}.mp4`,
17010
+ headers: this.headers
17011
+ });
17012
+ if (liveimg.filepath) {
17013
+ const outputPath = Common.tempDri.video + `Douyin_Result_${Date.now()}.mp4`;
17014
+ let success;
17015
+ const loopCount = imageItem.clip_type === 4 ? 1 : 3;
17016
+ if (mergeMode === "continuous" && bgmContext) {
17017
+ const result = await mergeLiveImageContinuous({
17018
+ videoPath: liveimg.filepath,
17019
+ outputPath,
17020
+ loopCount
17021
+ }, bgmContext);
17022
+ success = result.success;
17023
+ bgmContext = result.context;
17024
+ } else success = await mergeLiveImageIndependent({
17025
+ videoPath: liveimg.filepath,
17026
+ outputPath,
17027
+ loopCount
17028
+ }, liveimgbgm.filepath);
17029
+ if (success) {
17030
+ const filePath = Common.tempDri.video + `tmp_${Date.now()}.mp4`;
17031
+ fs.renameSync(outputPath, filePath);
17032
+ logger.mark(`视频文件重命名完成: ${outputPath.split("/").pop()} -> ${filePath.split("/").pop()}`);
17033
+ logger.mark("正在尝试删除缓存文件");
17034
+ await Common.removeFile(liveimg.filepath, true);
17035
+ temp.push({
17036
+ filepath: filePath,
17037
+ totalBytes: 0
17038
+ });
17039
+ processedImages.push(segment.video("file://" + filePath));
17040
+ if (imageItem.clip_type === 5 && imageItem.url_list?.[0]) processedImages.push(segment.image(imageItem.url_list[0]));
17041
+ } else await Common.removeFile(liveimg.filepath, true);
17042
+ }
16679
17043
  }
17044
+ const Element = common.makeForward(processedImages, this.e.sender.userId, this.e.sender.nick);
17045
+ try {
17046
+ await this.e.bot.sendForwardMsg(this.e.contact, Element, {
17047
+ source: "图集内容",
17048
+ summary: `查看${Element.length}张图片/视频消息`,
17049
+ prompt: "抖音图集解析结果",
17050
+ news: [{ text: "点击查看解析结果" }]
17051
+ });
17052
+ } catch (error) {
17053
+ await this.e.reply(JSON.stringify(error, null, 2));
17054
+ } finally {
17055
+ for (const item of temp) await Common.removeFile(item.filepath, true);
17056
+ }
17057
+ this.hasProcessedLiveImage = true;
17058
+ } else {
17059
+ for (const [index, imageItem] of images.entries()) {
17060
+ image_url = imageItem.url_list[2] || imageItem.url_list[1];
17061
+ g_title = VideoData.data.aweme_detail.preview_title.substring(0, 50).replace(/[\\/:*?"<>|\r\n]/g, " ");
17062
+ imageres.push(segment.image(image_url));
17063
+ imagenum++;
17064
+ if (Config.app.removeCache === false) {
17065
+ mkdirSync(`${Common.tempDri.images}${g_title}`);
17066
+ const path$1 = `${Common.tempDri.images}${g_title}/${index + 1}.png`;
17067
+ await new Network({
17068
+ url: image_url,
17069
+ type: "arraybuffer"
17070
+ }).getData().then((data$2) => fs.promises.writeFile(path$1, Buffer.from(data$2)));
17071
+ }
17072
+ }
17073
+ const res = common.makeForward(imageres, this.e.sender.userId, this.e.sender.nick);
17074
+ image_data.push(res);
17075
+ image_res.push(image_data);
17076
+ if (imageres.length === 1) await this.e.reply(segment.image(image_url));
17077
+ else await this.e.bot.sendForwardMsg(this.e.contact, res, {
17078
+ source: "图片合集",
17079
+ summary: `查看${res.length}张图片消息`,
17080
+ prompt: "抖音图集解析结果",
17081
+ news: [{ text: "点击查看解析结果" }]
17082
+ });
16680
17083
  }
16681
- const res = common.makeForward(imageres, this.e.sender.userId, this.e.sender.nick);
16682
- image_data.push(res);
16683
- image_res.push(image_data);
16684
- if (imageres.length === 1) await this.e.reply(segment.image(image_url));
16685
- else await this.e.bot.sendForwardMsg(this.e.contact, res, {
16686
- source: "图片合集",
16687
- summary: `查看${res.length}张图片消息`,
16688
- prompt: "抖音图集解析结果",
16689
- news: [{ text: "点击查看解析结果" }]
16690
- });
16691
17084
  break;
16692
17085
  }
16693
17086
  case VideoData.data.aweme_detail.is_slides === true && VideoData.data.aweme_detail.images !== null: {
16694
17087
  const images = [];
16695
17088
  const temp = [];
16696
- const liveimgbgm = await downloadFile(VideoData.data.aweme_detail.music.play_url.uri, {
17089
+ let mp3Path = "";
17090
+ if (VideoData.data.aweme_detail.music.play_url.uri === "") mp3Path = JSON.parse(VideoData.data.aweme_detail.music.extra).original_song_url;
17091
+ else mp3Path = VideoData.data.aweme_detail.music.play_url.uri;
17092
+ const liveimgbgm = await downloadFile(mp3Path, {
16697
17093
  title: `Douyin_tmp_A_${Date.now()}.mp3`,
16698
17094
  headers: this.headers
16699
17095
  });
@@ -16716,18 +17112,19 @@ var DouYin = class extends Base {
16716
17112
  if (liveimg.filepath) {
16717
17113
  const outputPath = Common.tempDri.video + `Douyin_Result_${Date.now()}.mp4`;
16718
17114
  let success;
17115
+ const loopCount = item.clip_type === 4 ? 1 : 3;
16719
17116
  if (mergeMode === "continuous" && bgmContext) {
16720
17117
  const result = await mergeLiveImageContinuous({
16721
17118
  videoPath: liveimg.filepath,
16722
17119
  outputPath,
16723
- loopCount: 3
17120
+ loopCount
16724
17121
  }, bgmContext);
16725
17122
  success = result.success;
16726
17123
  bgmContext = result.context;
16727
17124
  } else success = await mergeLiveImageIndependent({
16728
17125
  videoPath: liveimg.filepath,
16729
17126
  outputPath,
16730
- loopCount: 3
17127
+ loopCount
16731
17128
  }, liveimgbgm.filepath);
16732
17129
  if (success) {
16733
17130
  const filePath = Common.tempDri.video + `tmp_${Date.now()}.mp4`;
@@ -16740,6 +17137,7 @@ var DouYin = class extends Base {
16740
17137
  totalBytes: 0
16741
17138
  });
16742
17139
  images.push(segment.video("file://" + filePath));
17140
+ if (item.clip_type === 5 && item.url_list?.[0]) images.push(segment.image(item.url_list[0]));
16743
17141
  } else await Common.removeFile(liveimg.filepath, true);
16744
17142
  }
16745
17143
  }
@@ -16760,7 +17158,10 @@ var DouYin = class extends Base {
16760
17158
  }
16761
17159
  }
16762
17160
  if (VideoData.data.aweme_detail.music) {
16763
- const music_url = VideoData.data.aweme_detail.music.play_url.uri;
17161
+ const music = VideoData.data.aweme_detail.music;
17162
+ let music_url = "";
17163
+ if (music.play_url.uri === "") music_url = JSON.parse(music.extra).original_song_url;
17164
+ else music_url = music.play_url.uri;
16764
17165
  if (this.is_mp4 === false && Config.app.removeCache === false && music_url !== void 0) try {
16765
17166
  const path$1 = Common.tempDri.images + `${g_title}/BGM.mp3`;
16766
17167
  await new Network({
@@ -16770,7 +17171,7 @@ var DouYin = class extends Base {
16770
17171
  } catch (error) {
16771
17172
  console.log(error);
16772
17173
  }
16773
- music_url && this.is_mp4 === false && music_url !== void 0 && await this.e.reply(segment.record(music_url, false));
17174
+ music_url && this.is_mp4 === false && music_url !== void 0 && !this.hasProcessedLiveImage && await this.e.reply(segment.record(music_url, false));
16774
17175
  }
16775
17176
  let FPS;
16776
17177
  let video = null;
@@ -17265,6 +17666,197 @@ const getDouyinID = async (event, url, log = true) => {
17265
17666
  log && console.log(result);
17266
17667
  return result;
17267
17668
  };
17669
+ await init_module();
17670
+ await init_amagiClient();
17671
+ async function processFavoriteList(contentList, sec_uid, userinfo, item, targets, force = false) {
17672
+ const pushType = "favorite";
17673
+ const listName = "喜欢列表";
17674
+ const result = [];
17675
+ const groupHistoryStatus = /* @__PURE__ */ new Map();
17676
+ for (const target of targets) {
17677
+ const hasHistory = await douyinDBInstance.hasHistory(sec_uid, target.groupId, pushType);
17678
+ groupHistoryStatus.set(target.groupId, hasHistory);
17679
+ }
17680
+ for (const [index, aweme] of contentList.entries()) {
17681
+ const validTargets = [];
17682
+ for (const target of targets) if (!await douyinDBInstance.isAwemePushed(aweme.aweme_id, sec_uid, target.groupId, pushType)) {
17683
+ const hasHistory = groupHistoryStatus.get(target.groupId);
17684
+ if (force || hasHistory || index === 0) validTargets.push(target);
17685
+ else {
17686
+ await douyinDBInstance.addAwemeCache(aweme.aweme_id, sec_uid, target.groupId, pushType);
17687
+ logger.debug(`新订阅群组 ${target.groupId} 跳过旧作品 ${aweme.aweme_id} 并已标记为已读`);
17688
+ }
17689
+ }
17690
+ if (validTargets.length === 0) continue;
17691
+ let authorUserInfo;
17692
+ try {
17693
+ if (aweme.author?.sec_uid) {
17694
+ authorUserInfo = await douyinFetcher.fetchUserProfile({
17695
+ sec_uid: aweme.author.sec_uid,
17696
+ typeMode: "strict"
17697
+ });
17698
+ logger.debug(`获取作品作者 ${aweme.author.nickname} 的用户信息成功`);
17699
+ }
17700
+ } catch (error) {
17701
+ logger.warn(`获取作品作者用户信息失败: ${error}`);
17702
+ }
17703
+ result.push({
17704
+ remark: item.remark,
17705
+ sec_uid,
17706
+ create_time: aweme.create_time,
17707
+ targets: validTargets,
17708
+ pushType,
17709
+ Detail_Data: {
17710
+ ...aweme,
17711
+ user_info: userinfo,
17712
+ author_user_info: authorUserInfo
17713
+ },
17714
+ avatar_img: "https://p3-pc.douyinpic.com/aweme/1080x1080/" + userinfo.data.user.avatar_larger.uri,
17715
+ living: false
17716
+ });
17717
+ logger.debug(`发现新${listName}作品:${aweme.aweme_id}`);
17718
+ }
17719
+ await douyinDBInstance.updateListSnapshot(sec_uid, pushType, contentList.map((a) => a.aweme_id));
17720
+ return result;
17721
+ }
17722
+ await init_module();
17723
+ async function processLiveStream(sec_uid, userinfo, item, targets, amagi) {
17724
+ const pushType = "live";
17725
+ const liveStatus = await douyinDBInstance.getLiveStatus(sec_uid);
17726
+ if (userinfo.data.user.live_status === 1) {
17727
+ const UserInfoData = await amagi.douyin.fetcher.fetchUserProfile({
17728
+ sec_uid: userinfo.data.user.sec_uid,
17729
+ typeMode: "strict"
17730
+ });
17731
+ if (!UserInfoData.data.user?.live_status || UserInfoData.data.user.live_status !== 1) {
17732
+ logger.error((UserInfoData?.data?.user?.nickname ?? "用户") + "当前未在直播");
17733
+ return null;
17734
+ }
17735
+ if (!UserInfoData.data.user.room_data) {
17736
+ logger.error("未获取到直播间信息!");
17737
+ return null;
17738
+ }
17739
+ const room_data = JSON.parse(UserInfoData.data.user.room_data);
17740
+ const liveInfo = await amagi.douyin.fetcher.fetchLiveRoomInfo({
17741
+ room_id: UserInfoData.data.user.room_id_str,
17742
+ web_rid: room_data.owner.web_rid,
17743
+ typeMode: "strict"
17744
+ });
17745
+ if (!liveStatus.living) {
17746
+ await douyinDBInstance.updateLiveStatus(sec_uid, true);
17747
+ logger.info(`用户 ${item.remark ?? sec_uid} 开播了`);
17748
+ return {
17749
+ remark: item.remark,
17750
+ sec_uid,
17751
+ create_time: Date.now(),
17752
+ targets,
17753
+ pushType,
17754
+ Detail_Data: {
17755
+ user_info: userinfo,
17756
+ room_data: JSON.parse(userinfo.data.user.room_data),
17757
+ live_data: liveInfo,
17758
+ liveStatus: {
17759
+ liveStatus: "open",
17760
+ isChanged: true,
17761
+ isliving: true
17762
+ }
17763
+ },
17764
+ avatar_img: "https://p3-pc.douyinpic.com/aweme/1080x1080/" + userinfo.data.user.avatar_larger.uri,
17765
+ living: true
17766
+ };
17767
+ }
17768
+ } else if (liveStatus.living) {
17769
+ await douyinDBInstance.updateLiveStatus(sec_uid, false);
17770
+ logger.info(`用户 ${item.remark ?? sec_uid} 已关播,更新直播状态`);
17771
+ }
17772
+ return null;
17773
+ }
17774
+ await init_date_fns();
17775
+ await init_module();
17776
+ async function processPostList(contentList, sec_uid, userinfo, item, targets) {
17777
+ const pushType = "post";
17778
+ const listName = "作品列表";
17779
+ const result = [];
17780
+ for (const aweme of contentList) {
17781
+ const nowSeconds = Math.floor(Date.now() / 1e3);
17782
+ const createTime = aweme.create_time;
17783
+ const timeDifference = nowSeconds - createTime;
17784
+ const is_top = aweme.is_top === 1;
17785
+ const timeDiffHours = Math.round(timeDifference / 3600 * 100) / 100;
17786
+ logger.trace(`\n 前期获取该作品基本信息:\n 推送类型:${pushType}(${listName})\n 作者:${aweme.author.nickname}\n 作品ID:${aweme.aweme_id}\n 发布时间:${format(fromUnixTime(aweme.create_time), "yyyy-MM-dd HH:mm")}\n 发布时间戳(s):${createTime}\n 当前时间戳(s):${nowSeconds}\n 时间差(s):${timeDifference}s (${timeDiffHours}h)\n 是否置顶:${is_top}\n 是否在一天内:${timeDifference < 86400 ? logger.green("true") : logger.red("false")}\n `);
17787
+ if (is_top && timeDifference < 86400 || timeDifference < 86400 && !is_top) {
17788
+ const validTargets = [];
17789
+ for (const target of targets) if (!await douyinDBInstance.isAwemePushed(aweme.aweme_id, sec_uid, target.groupId, pushType)) validTargets.push(target);
17790
+ if (validTargets.length > 0) result.push({
17791
+ remark: item.remark,
17792
+ sec_uid,
17793
+ create_time: aweme.create_time,
17794
+ targets: validTargets,
17795
+ pushType,
17796
+ Detail_Data: {
17797
+ ...aweme,
17798
+ user_info: userinfo
17799
+ },
17800
+ avatar_img: "https://p3-pc.douyinpic.com/aweme/1080x1080/" + userinfo.data.user.avatar_larger.uri,
17801
+ living: false
17802
+ });
17803
+ }
17804
+ }
17805
+ return result;
17806
+ }
17807
+ await init_module();
17808
+ await init_amagiClient();
17809
+ async function processRecommendList(contentList, sec_uid, userinfo, item, targets, force = false) {
17810
+ const pushType = "recommend";
17811
+ const listName = "推荐列表";
17812
+ const result = [];
17813
+ const groupHistoryStatus = /* @__PURE__ */ new Map();
17814
+ for (const target of targets) {
17815
+ const hasHistory = await douyinDBInstance.hasHistory(sec_uid, target.groupId, pushType);
17816
+ groupHistoryStatus.set(target.groupId, hasHistory);
17817
+ }
17818
+ for (const [index, aweme] of contentList.entries()) {
17819
+ const validTargets = [];
17820
+ for (const target of targets) if (!await douyinDBInstance.isAwemePushed(aweme.aweme_id, sec_uid, target.groupId, pushType)) {
17821
+ const hasHistory = groupHistoryStatus.get(target.groupId);
17822
+ if (force || hasHistory || index === 0) validTargets.push(target);
17823
+ else {
17824
+ await douyinDBInstance.addAwemeCache(aweme.aweme_id, sec_uid, target.groupId, pushType);
17825
+ logger.debug(`新订阅群组 ${target.groupId} 跳过旧作品 ${aweme.aweme_id} 并已标记为已读`);
17826
+ }
17827
+ }
17828
+ if (validTargets.length === 0) continue;
17829
+ let authorUserInfo;
17830
+ try {
17831
+ if (aweme.author?.sec_uid) {
17832
+ authorUserInfo = await douyinFetcher.fetchUserProfile({
17833
+ sec_uid: aweme.author.sec_uid,
17834
+ typeMode: "strict"
17835
+ });
17836
+ logger.debug(`获取作品作者 ${aweme.author.nickname} 的用户信息成功`);
17837
+ }
17838
+ } catch (error) {
17839
+ logger.warn(`获取作品作者用户信息失败: ${error}`);
17840
+ }
17841
+ result.push({
17842
+ remark: item.remark,
17843
+ sec_uid,
17844
+ create_time: aweme.create_time,
17845
+ targets: validTargets,
17846
+ pushType,
17847
+ Detail_Data: {
17848
+ ...aweme,
17849
+ user_info: userinfo,
17850
+ author_user_info: authorUserInfo
17851
+ },
17852
+ avatar_img: "https://p3-pc.douyinpic.com/aweme/1080x1080/" + userinfo.data.user.avatar_larger.uri,
17853
+ living: false
17854
+ });
17855
+ logger.debug(`发现新${listName}作品:${aweme.aweme_id}`);
17856
+ }
17857
+ await douyinDBInstance.updateListSnapshot(sec_uid, pushType, contentList.map((a) => a.aweme_id));
17858
+ return result;
17859
+ }
17268
17860
  await init_date_fns();
17269
17861
  await init_module();
17270
17862
  await init_Config();
@@ -17290,6 +17882,7 @@ var DouYinpush = class extends Base {
17290
17882
  const deletedCount = await cleanOldDynamicCache("douyin");
17291
17883
  if (deletedCount > 0) logger.info(`已清理 ${deletedCount} 条过期的抖音作品缓存记录`);
17292
17884
  if (await this.checkremark()) return true;
17885
+ this.ensureConfigFields(Config.pushlist.douyin);
17293
17886
  const registeredBotIds = karin$1.getAllBotID();
17294
17887
  const filteredPushList = this.filterPushListByRegisteredBots(Config.pushlist.douyin, registeredBotIds);
17295
17888
  if (filteredPushList.length === 0) {
@@ -17301,6 +17894,30 @@ var DouYinpush = class extends Base {
17301
17894
  if (this.force) return await this.forcepush(data$1);
17302
17895
  else return await this.getdata(data$1);
17303
17896
  }
17897
+ ensureConfigFields(pushList) {
17898
+ if (!pushList || pushList.length === 0) return;
17899
+ let hasChanges = false;
17900
+ for (const item of pushList) {
17901
+ if (!item.pushTypes || item.pushTypes.length === 0) {
17902
+ item.pushTypes = [
17903
+ "post",
17904
+ "live",
17905
+ "favorite",
17906
+ "recommend"
17907
+ ];
17908
+ hasChanges = true;
17909
+ logger.info(`为用户 ${item.remark ?? item.sec_uid} 自动补全推送类型:作品列表、直播、收藏、推荐`);
17910
+ }
17911
+ if (item.switch === void 0) {
17912
+ item.switch = true;
17913
+ hasChanges = true;
17914
+ }
17915
+ }
17916
+ if (hasChanges) {
17917
+ Config.Modify("pushlist", "douyin", pushList);
17918
+ logger.info("已自动补全配置文件中缺失的字段并保存");
17919
+ }
17920
+ }
17304
17921
  filterPushListByRegisteredBots(pushList, registeredBotIds) {
17305
17922
  if (!pushList || pushList.length === 0) return [];
17306
17923
  const registeredSet = new Set(registeredBotIds);
@@ -17327,18 +17944,20 @@ var DouYinpush = class extends Base {
17327
17944
  async getdata(data$1) {
17328
17945
  if (Object.keys(data$1).length === 0) return true;
17329
17946
  for (const awemeId in data$1) {
17330
- logger.mark(`\n ${logger.blue("开始处理并渲染抖音动态图片")}\n ${logger.blue("博主")}: ${logger.green(data$1[awemeId].remark)} \n ${logger.cyan("作品id")}:${logger.yellow(awemeId)}\n ${logger.cyan("访问地址")}:${logger.green("https://www.douyin.com/video/" + awemeId)}`);
17331
17947
  const pushItem = data$1[awemeId];
17948
+ const actualAwemeId = awemeId.replace(/^(post|favorite|recommend|live)_/, "");
17949
+ const pushTypeLabel = pushItem.pushType === "post" ? "作品列表" : pushItem.pushType === "favorite" ? "喜欢列表" : pushItem.pushType === "recommend" ? "推荐列表" : "直播";
17950
+ logger.mark(`\n ${logger.blue("开始处理并渲染抖音动态图片")}\n ${logger.blue("博主")}: ${logger.green(pushItem.remark)} \n ${logger.blue("推送类型")}: ${logger.magenta(pushTypeLabel)}\n ${logger.cyan("作品id")}:${logger.yellow(actualAwemeId)}\n ${logger.cyan("访问地址")}:${logger.green("https://www.douyin.com/video/" + actualAwemeId)}`);
17332
17951
  const Detail_Data = pushItem.Detail_Data;
17333
17952
  const skip = await skipDynamic(pushItem);
17334
- skip && logger.warn(`作品 https://www.douyin.com/video/${awemeId} 已被处理,跳过`);
17953
+ skip && logger.warn(`作品 https://www.douyin.com/video/${actualAwemeId} 已被处理,跳过`);
17335
17954
  let img$2 = [];
17336
17955
  let iddata = {
17337
17956
  is_mp4: true,
17338
17957
  type: "one_work"
17339
17958
  };
17340
17959
  if (!skip) iddata = await getDouyinID(this.e, Detail_Data.share_url ?? "https://live.douyin.com/" + Detail_Data.room_data?.owner.web_rid, false);
17341
- if (!skip) if (pushItem.living && "room_data" in pushItem.Detail_Data && Detail_Data.live_data) img$2 = await Render("douyin/live", {
17960
+ if (!skip) if (pushItem.pushType === "live" && "room_data" in pushItem.Detail_Data && Detail_Data.live_data) img$2 = await Render("douyin/live", {
17342
17961
  image_url: Detail_Data.live_data.data.data.data[0]?.cover?.url_list[0] ?? Detail_Data.live_data.data.data.qrcode_url,
17343
17962
  text: Detail_Data.live_data.data.data.data[0]?.title ?? "",
17344
17963
  liveinf: `${Detail_Data.live_data.data.data.partition_road_map?.partition?.title ?? Detail_Data.live_data.data.data.data[0]?.title ?? "获取失败"} | 房间号: ${Detail_Data.room_data.owner.web_rid}`,
@@ -17360,7 +17979,45 @@ var DouYinpush = class extends Base {
17360
17979
  Connection: "keep-alive"
17361
17980
  }
17362
17981
  }).getLocation();
17363
- img$2 = await Render("douyin/dynamic", {
17982
+ if (pushItem.pushType === "favorite") {
17983
+ const authorUserInfo = "author_user_info" in Detail_Data ? Detail_Data.author_user_info : void 0;
17984
+ img$2 = await Render("douyin/favorite-list", {
17985
+ image_url: iddata.is_mp4 ? Detail_Data.video.animated_cover?.url_list[0] ?? Detail_Data.video.cover.url_list[0] : Detail_Data.images[0].url_list[0],
17986
+ desc: this.desc(Detail_Data, Detail_Data.desc),
17987
+ dianzan: this.count(Detail_Data.statistics.digg_count),
17988
+ pinglun: this.count(Detail_Data.statistics.comment_count),
17989
+ share: this.count(Detail_Data.statistics.share_count),
17990
+ shouchang: this.count(Detail_Data.statistics.collect_count),
17991
+ tuijian: this.count(Detail_Data.statistics.recommend_count),
17992
+ create_time: format(fromUnixTime(pushItem.create_time), "yyyy-MM-dd HH:mm"),
17993
+ liker_username: pushItem.remark,
17994
+ liker_avatar: "https://p3-pc.douyinpic.com/aweme/1080x1080/" + Detail_Data.user_info.data.user.avatar_larger.uri,
17995
+ 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,
17996
+ author_username: Detail_Data.author.nickname,
17997
+ author_avatar: "https://p3-pc.douyinpic.com/aweme/1080x1080/" + authorUserInfo.data.user.avatar_larger.uri,
17998
+ author_douyin_id: authorUserInfo.data.user.unique_id === "" ? authorUserInfo.data.user.short_id : authorUserInfo.data.user.unique_id,
17999
+ 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`
18000
+ });
18001
+ } else if (pushItem.pushType === "recommend") {
18002
+ const authorUserInfo = "author_user_info" in Detail_Data ? Detail_Data.author_user_info : void 0;
18003
+ img$2 = await Render("douyin/recommend-list", {
18004
+ image_url: iddata.is_mp4 ? Detail_Data.video.animated_cover?.url_list[0] ?? Detail_Data.video.cover.url_list[0] : Detail_Data.images[0].url_list[0],
18005
+ desc: this.desc(Detail_Data, Detail_Data.desc),
18006
+ dianzan: this.count(Detail_Data.statistics.digg_count),
18007
+ pinglun: this.count(Detail_Data.statistics.comment_count),
18008
+ share: this.count(Detail_Data.statistics.share_count),
18009
+ shouchang: this.count(Detail_Data.statistics.collect_count),
18010
+ tuijian: this.count(Detail_Data.statistics.recommend_count),
18011
+ create_time: format(fromUnixTime(pushItem.create_time), "yyyy-MM-dd HH:mm"),
18012
+ recommender_username: pushItem.remark,
18013
+ recommender_avatar: "https://p3-pc.douyinpic.com/aweme/1080x1080/" + Detail_Data.user_info.data.user.avatar_larger.uri,
18014
+ 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,
18015
+ author_username: Detail_Data.author.nickname,
18016
+ author_avatar: "https://p3-pc.douyinpic.com/aweme/1080x1080/" + authorUserInfo.data.user.avatar_larger.uri,
18017
+ author_douyin_id: authorUserInfo.data.user.unique_id === "" ? authorUserInfo.data.user.short_id : authorUserInfo.data.user.unique_id,
18018
+ 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`
18019
+ });
18020
+ } else img$2 = await Render("douyin/dynamic", {
17364
18021
  image_url: iddata.is_mp4 ? Detail_Data.video.animated_cover?.url_list[0] ?? Detail_Data.video.cover.url_list[0] : Detail_Data.images[0].url_list[0],
17365
18022
  desc: this.desc(Detail_Data, Detail_Data.desc),
17366
18023
  dianzan: this.count(Detail_Data.statistics.digg_count),
@@ -17375,6 +18032,7 @@ var DouYinpush = class extends Base {
17375
18032
  "粉丝": this.count(Detail_Data.user_info.data.user.follower_count),
17376
18033
  "获赞": this.count(Detail_Data.user_info.data.user.total_favorited),
17377
18034
  "关注": this.count(Detail_Data.user_info.data.user.following_count),
18035
+ dynamicTYPE: "作品动态推送",
17378
18036
  cooperation_info: (() => {
17379
18037
  const raw = Detail_Data.cooperation_info;
17380
18038
  if (!raw) return void 0;
@@ -17405,7 +18063,7 @@ var DouYinpush = class extends Base {
17405
18063
  if (!skip) {
17406
18064
  const Contact = karin$1.contactGroup(groupId);
17407
18065
  status = await karin$1.sendMsg(botId, Contact, img$2 ? [...img$2] : []);
17408
- if (pushItem.living && "room_data" in pushItem.Detail_Data && status.message_id) await douyinDBInstance.updateLiveStatus(pushItem.sec_uid, true);
18066
+ if (pushItem.pushType === "live" && "room_data" in pushItem.Detail_Data && status.message_id) await douyinDBInstance.updateLiveStatus(pushItem.sec_uid, true);
17409
18067
  if (Config.douyin.push.parsedynamic && status.message_id) {
17410
18068
  logger.debug(`开始解析作品,类型为:${iddata.is_mp4 ? "视频" : "图集"}`);
17411
18069
  if (iddata.is_mp4) try {
@@ -17434,19 +18092,186 @@ var DouYinpush = class extends Base {
17434
18092
  throw new Error(`下载视频失败: ${error}`);
17435
18093
  }
17436
18094
  else if (!iddata.is_mp4 && iddata.type === "one_work") {
17437
- const imageres = [];
17438
- let image_url;
17439
- for (const item of Detail_Data.images) {
17440
- image_url = item.url_list[2] ?? item.url_list[1];
17441
- imageres.push(segment.image(image_url));
18095
+ if (Detail_Data.is_slides === true && Detail_Data.images) {
18096
+ const images = [];
18097
+ const temp = [];
18098
+ let mp3Path = "";
18099
+ if (Detail_Data.music.play_url.uri === "") mp3Path = JSON.parse(Detail_Data.music.extra).original_song_url;
18100
+ else mp3Path = Detail_Data.music.play_url.uri;
18101
+ const liveimgbgm = await downloadFile(mp3Path, {
18102
+ title: `Douyin_tmp_A_${Date.now()}.mp3`,
18103
+ headers: douyinBaseHeaders
18104
+ });
18105
+ temp.push(liveimgbgm);
18106
+ const images1 = Detail_Data.images ?? [];
18107
+ if (!images1.length) logger.debug("未获取到合辑的图片数据");
18108
+ const mergeMode = Config.douyin.liveImageMergeMode ?? "independent";
18109
+ let bgmContext = null;
18110
+ if (mergeMode === "continuous") {
18111
+ const { createLiveImageContext: createLiveImageContext$1 } = await init_utils$1().then(() => utils_exports);
18112
+ bgmContext = await createLiveImageContext$1(liveimgbgm.filepath);
18113
+ }
18114
+ for (const item of images1) {
18115
+ if (item.clip_type === 2) {
18116
+ images.push(segment.image(item.url_list[0]));
18117
+ continue;
18118
+ }
18119
+ const liveimg = await downloadFile(`https://aweme.snssdk.com/aweme/v1/play/?video_id=${item.video.play_addr_h264.uri}&ratio=1080p&line=0`, {
18120
+ title: `Douyin_tmp_V_${Date.now()}.mp4`,
18121
+ headers: douyinBaseHeaders
18122
+ });
18123
+ if (liveimg.filepath) {
18124
+ const { Common: Common$1, mergeLiveImageContinuous: mergeLiveImageContinuous$1, mergeLiveImageIndependent: mergeLiveImageIndependent$1 } = await init_utils$1().then(() => utils_exports);
18125
+ const outputPath = Common$1.tempDri.video + `Douyin_Result_${Date.now()}.mp4`;
18126
+ let success;
18127
+ const loopCount = item.clip_type === 4 ? 1 : 3;
18128
+ if (mergeMode === "continuous" && bgmContext) {
18129
+ const result = await mergeLiveImageContinuous$1({
18130
+ videoPath: liveimg.filepath,
18131
+ outputPath,
18132
+ loopCount
18133
+ }, bgmContext);
18134
+ success = result.success;
18135
+ bgmContext = result.context;
18136
+ } else success = await mergeLiveImageIndependent$1({
18137
+ videoPath: liveimg.filepath,
18138
+ outputPath,
18139
+ loopCount
18140
+ }, liveimgbgm.filepath);
18141
+ if (success) {
18142
+ const fs$1 = await import("node:fs");
18143
+ const filePath = Common$1.tempDri.video + `tmp_${Date.now()}.mp4`;
18144
+ fs$1.default.renameSync(outputPath, filePath);
18145
+ logger.mark(`视频文件重命名完成: ${outputPath.split("/").pop()} -> ${filePath.split("/").pop()}`);
18146
+ logger.mark("正在尝试删除缓存文件");
18147
+ await Common$1.removeFile(liveimg.filepath, true);
18148
+ temp.push({
18149
+ filepath: filePath,
18150
+ totalBytes: 0
18151
+ });
18152
+ images.push(segment.video("file://" + filePath));
18153
+ if (item.clip_type === 5 && item.url_list?.[0]) images.push(segment.image(item.url_list[0]));
18154
+ } else await Common$1.removeFile(liveimg.filepath, true);
18155
+ }
18156
+ }
18157
+ const bot = karin$1.getBot(botId);
18158
+ const Element = common.makeForward(images, botId, bot.account.name);
18159
+ try {
18160
+ await bot.sendForwardMsg(Contact, Element, {
18161
+ source: "合辑内容",
18162
+ summary: `查看${Element.length}张图片/视频消息`,
18163
+ prompt: "抖音合辑解析结果",
18164
+ news: [{ text: "点击查看解析结果" }]
18165
+ });
18166
+ } catch (error) {
18167
+ logger.error(`发送合辑失败: ${error}`);
18168
+ } finally {
18169
+ for (const item of temp) {
18170
+ const { Common: Common$1 } = await init_utils$1().then(() => utils_exports);
18171
+ await Common$1.removeFile(item.filepath, true);
18172
+ }
18173
+ }
18174
+ } else if (Detail_Data.images) if (Detail_Data.images.some((item) => item.clip_type !== 2)) {
18175
+ const processedImages = [];
18176
+ const temp = [];
18177
+ let mp3Path = "";
18178
+ if (Detail_Data.music.play_url.uri === "") mp3Path = JSON.parse(Detail_Data.music.extra).original_song_url;
18179
+ else mp3Path = Detail_Data.music.play_url.uri;
18180
+ const liveimgbgm = await downloadFile(mp3Path, {
18181
+ title: `Douyin_tmp_A_${Date.now()}.mp3`,
18182
+ headers: douyinBaseHeaders
18183
+ });
18184
+ temp.push(liveimgbgm);
18185
+ const mergeMode = Config.douyin.liveImageMergeMode ?? "independent";
18186
+ let bgmContext = null;
18187
+ if (mergeMode === "continuous") {
18188
+ const { createLiveImageContext: createLiveImageContext$1 } = await init_utils$1().then(() => utils_exports);
18189
+ bgmContext = await createLiveImageContext$1(liveimgbgm.filepath);
18190
+ }
18191
+ for (const item of Detail_Data.images) {
18192
+ if (item.clip_type === 2) {
18193
+ const image_url = item.url_list[2] ?? item.url_list[1];
18194
+ processedImages.push(segment.image(image_url));
18195
+ continue;
18196
+ }
18197
+ const liveimg = await downloadFile(`https://aweme.snssdk.com/aweme/v1/play/?video_id=${item.video.play_addr_h264.uri}&ratio=1080p&line=0`, {
18198
+ title: `Douyin_tmp_V_${Date.now()}.mp4`,
18199
+ headers: douyinBaseHeaders
18200
+ });
18201
+ if (liveimg.filepath) {
18202
+ const { Common: Common$1, mergeLiveImageContinuous: mergeLiveImageContinuous$1, mergeLiveImageIndependent: mergeLiveImageIndependent$1 } = await init_utils$1().then(() => utils_exports);
18203
+ const outputPath = Common$1.tempDri.video + `Douyin_Result_${Date.now()}.mp4`;
18204
+ let success;
18205
+ const loopCount = item.clip_type === 4 ? 1 : 3;
18206
+ if (mergeMode === "continuous" && bgmContext) {
18207
+ const result = await mergeLiveImageContinuous$1({
18208
+ videoPath: liveimg.filepath,
18209
+ outputPath,
18210
+ loopCount
18211
+ }, bgmContext);
18212
+ success = result.success;
18213
+ bgmContext = result.context;
18214
+ } else success = await mergeLiveImageIndependent$1({
18215
+ videoPath: liveimg.filepath,
18216
+ outputPath,
18217
+ loopCount
18218
+ }, liveimgbgm.filepath);
18219
+ if (success) {
18220
+ const fs$1 = await import("node:fs");
18221
+ const filePath = Common$1.tempDri.video + `tmp_${Date.now()}.mp4`;
18222
+ fs$1.default.renameSync(outputPath, filePath);
18223
+ logger.mark(`视频文件重命名完成: ${outputPath.split("/").pop()} -> ${filePath.split("/").pop()}`);
18224
+ logger.mark("正在尝试删除缓存文件");
18225
+ await Common$1.removeFile(liveimg.filepath, true);
18226
+ temp.push({
18227
+ filepath: filePath,
18228
+ totalBytes: 0
18229
+ });
18230
+ processedImages.push(segment.video("file://" + filePath));
18231
+ if (item.clip_type === 5 && item.url_list?.[0]) processedImages.push(segment.image(item.url_list[0]));
18232
+ } else await Common$1.removeFile(liveimg.filepath, true);
18233
+ }
18234
+ }
18235
+ const bot = karin$1.getBot(botId);
18236
+ const Element = common.makeForward(processedImages, botId, bot.account.name);
18237
+ try {
18238
+ await bot.sendForwardMsg(Contact, Element, {
18239
+ source: "图集内容",
18240
+ summary: `查看${Element.length}张图片/视频消息`,
18241
+ prompt: "抖音图集解析结果",
18242
+ news: [{ text: "点击查看解析结果" }]
18243
+ });
18244
+ } catch (error) {
18245
+ logger.error(`发送图集失败: ${error}`);
18246
+ } finally {
18247
+ for (const item of temp) {
18248
+ const { Common: Common$1 } = await init_utils$1().then(() => utils_exports);
18249
+ await Common$1.removeFile(item.filepath, true);
18250
+ }
18251
+ }
18252
+ } else {
18253
+ const imageres = [];
18254
+ let image_url;
18255
+ for (const item of Detail_Data.images) {
18256
+ image_url = item.url_list[2] ?? item.url_list[1];
18257
+ imageres.push(segment.image(image_url));
18258
+ }
18259
+ const bot = karin$1.getBot(botId);
18260
+ if (imageres.length === 1) await bot.sendMsg(Contact, [segment.image(image_url)]);
18261
+ else {
18262
+ const forwardMsg = common.makeForward(imageres, botId, bot.account.name);
18263
+ await bot.sendForwardMsg(Contact, forwardMsg, {
18264
+ source: "图片合集",
18265
+ summary: `查看${forwardMsg.length}张图片消息`,
18266
+ prompt: "抖音图集解析结果",
18267
+ news: [{ text: "点击查看解析结果" }]
18268
+ });
18269
+ }
17442
18270
  }
17443
- const bot = karin$1.getBot(botId);
17444
- const forwardMsg = common.makeForward(imageres, botId, bot.account.name);
17445
- await bot.sendForwardMsg(Contact, forwardMsg);
17446
18271
  }
17447
18272
  }
17448
18273
  }
17449
- if (skip || !pushItem.living && status.message_id) await douyinDBInstance.addAwemeCache(awemeId, pushItem.sec_uid, groupId);
18274
+ if (skip || pushItem.pushType !== "live" && status.message_id) await douyinDBInstance.addAwemeCache(actualAwemeId, pushItem.sec_uid, groupId, pushItem.pushType);
17450
18275
  } catch (error) {
17451
18276
  throw new Error(`${error}`);
17452
18277
  }
@@ -17460,11 +18285,8 @@ var DouYinpush = class extends Base {
17460
18285
  for (const item of filteredUserList) {
17461
18286
  await common.sleep(2e3);
17462
18287
  const sec_uid = item.sec_uid;
17463
- logger.debug(`开始获取用户:${item.remark}(${sec_uid})的主页作品列表`);
17464
- const videolist = await this.amagi.douyin.fetcher.fetchUserVideoList({
17465
- sec_uid,
17466
- typeMode: "strict"
17467
- });
18288
+ const pushTypes = item.pushTypes || ["post"];
18289
+ logger.debug(`开始获取用户:${item.remark}(${sec_uid})的内容,推送类型:${pushTypes.join(", ")}`);
17468
18290
  const userinfo = await this.amagi.douyin.fetcher.fetchUserProfile({
17469
18291
  sec_uid,
17470
18292
  typeMode: "strict"
@@ -17481,74 +18303,73 @@ var DouYinpush = class extends Base {
17481
18303
  logger.warn(`${item.remark}(${sec_uid})${userinfo.data.user.special_state_info.title}`);
17482
18304
  continue;
17483
18305
  }
17484
- if (videolist.data.aweme_list.length > 0) for (const aweme of videolist.data.aweme_list) {
17485
- const nowSeconds = Math.floor(Date.now() / 1e3);
17486
- const createTime = aweme.create_time;
17487
- const timeDifference = nowSeconds - createTime;
17488
- const is_top = aweme.is_top === 1;
17489
- let shouldPush = false;
17490
- const timeDiffHours = Math.round(timeDifference / 3600 * 100) / 100;
17491
- logger.trace(`\n 前期获取该作品基本信息:\n 作者:${aweme.author.nickname}\n 作品ID:${aweme.aweme_id}\n 发布时间:${format(fromUnixTime(aweme.create_time), "yyyy-MM-dd HH:mm")}\n 发布时间戳(s):${createTime}\n 当前时间戳(s):${nowSeconds}\n 时间差(s):${timeDifference}s (${timeDiffHours}h)\n 是否置顶:${is_top}\n 是否处于开播:${userinfo.data.user?.live_status === 1 ? logger.green("true") : logger.red("false")}\n 是否在一天内:${timeDifference < 86400 ? logger.green("true") : logger.red("false")}\n `);
17492
- if (is_top && timeDifference < 86400 || timeDifference < 86400 && !is_top) {
17493
- if (!await this.checkIfAlreadyPushed(aweme.aweme_id, sec_uid, targets.map((t) => t.groupId))) shouldPush = true;
18306
+ for (const pushType of pushTypes) {
18307
+ await common.sleep(1e3);
18308
+ if (pushType === "live") {
18309
+ const liveItem = await processLiveStream(sec_uid, userinfo, item, targets, this.amagi);
18310
+ if (liveItem) willbepushlist[`live_${sec_uid}`] = liveItem;
18311
+ continue;
18312
+ }
18313
+ let contentList = [];
18314
+ let listName = "";
18315
+ switch (pushType) {
18316
+ case "post":
18317
+ listName = "作品列表";
18318
+ contentList = (await this.amagi.douyin.fetcher.fetchUserVideoList({
18319
+ sec_uid,
18320
+ number: 5,
18321
+ typeMode: "strict"
18322
+ })).data.aweme_list || [];
18323
+ break;
18324
+ case "favorite":
18325
+ listName = "喜欢列表";
18326
+ const favoritelist = await this.amagi.douyin.fetcher.fetchUserFavoriteList({
18327
+ sec_uid,
18328
+ number: 5,
18329
+ typeMode: "strict"
18330
+ });
18331
+ if (favoritelist.data.aweme_list.length === 0) logger.warn(`${item.remark}(${item.short_id}) 获取到的喜欢列表数量为零!此博主可能未公开他/她的喜欢列表`);
18332
+ contentList = favoritelist.data.aweme_list || [];
18333
+ break;
18334
+ case "recommend":
18335
+ listName = "推荐列表";
18336
+ const recommendlist = await this.amagi.douyin.fetcher.fetchUserRecommendList({
18337
+ sec_uid,
18338
+ number: 5,
18339
+ typeMode: "strict"
18340
+ });
18341
+ if (recommendlist.data.aweme_list.length === 0) logger.warn(`${item.remark}(${item.short_id}) 获取到的推荐列表数量为零!此博主可能未公开他/她的推荐列表`);
18342
+ contentList = recommendlist.data.aweme_list || [];
18343
+ break;
18344
+ }
18345
+ logger.debug(`获取到 ${item.remark} 的${listName},共 ${contentList.length} 条`);
18346
+ if (contentList.length > 0) {
18347
+ let pushItems = [];
18348
+ switch (pushType) {
18349
+ case "post":
18350
+ pushItems = await processPostList(contentList, sec_uid, userinfo, item, targets);
18351
+ break;
18352
+ case "favorite":
18353
+ pushItems = await processFavoriteList(contentList, sec_uid, userinfo, item, targets, this.force);
18354
+ break;
18355
+ case "recommend":
18356
+ pushItems = await processRecommendList(contentList, sec_uid, userinfo, item, targets, this.force);
18357
+ break;
18358
+ }
18359
+ for (const pushItem of pushItems) {
18360
+ const key = `${pushType}_${pushItem.Detail_Data.aweme_id}`;
18361
+ willbepushlist[key] = pushItem;
18362
+ }
17494
18363
  }
17495
- if (shouldPush) willbepushlist[aweme.aweme_id] = {
17496
- remark: item.remark,
17497
- sec_uid,
17498
- create_time: aweme.create_time,
17499
- targets,
17500
- Detail_Data: {
17501
- ...aweme,
17502
- user_info: userinfo
17503
- },
17504
- avatar_img: "https://p3-pc.douyinpic.com/aweme/1080x1080/" + userinfo.data.user.avatar_larger.uri,
17505
- living: false
17506
- };
17507
- }
17508
- const liveStatus = await douyinDBInstance.getLiveStatus(sec_uid);
17509
- if (userinfo.data.user.live_status === 1) {
17510
- const UserInfoData = await this.amagi.douyin.fetcher.fetchUserProfile({
17511
- sec_uid: userinfo.data.user.sec_uid,
17512
- typeMode: "strict"
17513
- });
17514
- if (!UserInfoData.data.user?.live_status || UserInfoData.data.user.live_status !== 1) logger.error((UserInfoData?.data?.user?.nickname ?? "用户") + "当前未在直播");
17515
- if (!UserInfoData.data.user.room_data) logger.error("未获取到直播间信息!");
17516
- const room_data = JSON.parse(UserInfoData.data.user.room_data);
17517
- const liveInfo = await this.amagi.douyin.fetcher.fetchLiveRoomInfo({
17518
- room_id: UserInfoData.data.user.room_id_str,
17519
- web_rid: room_data.owner.web_rid,
17520
- typeMode: "strict"
17521
- });
17522
- if (!liveStatus.living) willbepushlist[`live_${sec_uid}`] = {
17523
- remark: item.remark,
17524
- sec_uid,
17525
- create_time: Date.now(),
17526
- targets,
17527
- Detail_Data: {
17528
- user_info: userinfo,
17529
- room_data: JSON.parse(userinfo.data.user.room_data),
17530
- live_data: liveInfo,
17531
- liveStatus: {
17532
- liveStatus: "open",
17533
- isChanged: true,
17534
- isliving: true
17535
- }
17536
- },
17537
- avatar_img: "https://p3-pc.douyinpic.com/aweme/1080x1080/" + userinfo.data.user.avatar_larger.uri,
17538
- living: true
17539
- };
17540
- } else if (liveStatus.living) {
17541
- await douyinDBInstance.updateLiveStatus(sec_uid, false);
17542
- logger.info(`用户 ${item.remark ?? sec_uid} 已关播,更新直播状态`);
17543
18364
  }
17544
18365
  }
17545
18366
  } catch (error) {
17546
- throw new Error(`获取抖音用户主页作品列表失败: ${error}`);
18367
+ throw new Error(`获取抖音用户内容列表失败: ${error}`);
17547
18368
  }
17548
18369
  return willbepushlist;
17549
18370
  }
17550
- async checkIfAlreadyPushed(aweme_id, sec_uid, groupIds) {
17551
- for (const groupId of groupIds) if (!await douyinDBInstance.isAwemePushed(aweme_id, sec_uid, groupId)) return false;
18371
+ async checkIfAlreadyPushed(aweme_id, sec_uid, groupIds, pushType = "post") {
18372
+ for (const groupId of groupIds) if (!await douyinDBInstance.isAwemePushed(aweme_id, sec_uid, groupId, pushType)) return false;
17552
18373
  return true;
17553
18374
  }
17554
18375
  async setting(data$1) {
@@ -17593,6 +18414,7 @@ var DouYinpush = class extends Base {
17593
18414
  }
17594
18415
  } else {
17595
18416
  existingItem.group_id.push(`${groupId}:${botId}`);
18417
+ if (!existingItem.pushTypes || existingItem.pushTypes.length === 0) existingItem.pushTypes = ["post", "live"];
17596
18418
  if (!isSubscribed) await douyinDBInstance.subscribeDouyinUser(groupId, botId, sec_uid, user_shortid, UserInfoData.data.user.nickname);
17597
18419
  await this.e.reply(`群:${groupInfo.groupName}(${groupId})\n添加成功!${UserInfoData.data.user.nickname}\n抖音号:${user_shortid}`);
17598
18420
  if (Config.douyin.push.switch === false) await this.e.reply("请发送「#设置抖音推送开启」以进行推送");
@@ -17604,7 +18426,8 @@ var DouYinpush = class extends Base {
17604
18426
  sec_uid,
17605
18427
  group_id: [`${groupId}:${botId}`],
17606
18428
  remark: UserInfoData.data.user.nickname,
17607
- short_id: user_shortid
18429
+ short_id: user_shortid,
18430
+ pushTypes: ["post", "live"]
17608
18431
  });
17609
18432
  if (!isSubscribed) await douyinDBInstance.subscribeDouyinUser(groupId, botId, sec_uid, user_shortid, UserInfoData.data.user.nickname);
17610
18433
  await this.e.reply(`群:${groupInfo.groupName}(${groupId})\n添加成功!${UserInfoData.data.user.nickname}\n抖音号:${user_shortid}`);
@@ -17632,7 +18455,9 @@ var DouYinpush = class extends Base {
17632
18455
  sec_uid,
17633
18456
  typeMode: "strict"
17634
18457
  });
17635
- const switchStatus = (Config.pushlist.douyin?.find((item) => item.sec_uid === sec_uid))?.switch !== false;
18458
+ const configItem = Config.pushlist.douyin?.find((item) => item.sec_uid === sec_uid);
18459
+ const switchStatus = configItem?.switch !== false;
18460
+ const pushTypes = configItem?.pushTypes || ["post"];
17636
18461
  renderOpt.push({
17637
18462
  avatar_img: userInfo.data.user.avatar_larger.url_list[0],
17638
18463
  username: userInfo.data.user.nickname,
@@ -17640,7 +18465,8 @@ var DouYinpush = class extends Base {
17640
18465
  fans: this.count(userInfo.data.user.follower_count),
17641
18466
  total_favorited: this.count(userInfo.data.user.total_favorited),
17642
18467
  following_count: this.count(userInfo.data.user.following_count),
17643
- switch: switchStatus
18468
+ switch: switchStatus,
18469
+ pushTypes
17644
18470
  });
17645
18471
  }
17646
18472
  const img$2 = await Render("douyin/userlist", {