@ikenxuan/amagi 5.7.2 → 5.8.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.
@@ -7,7 +7,6 @@ node_path = require_chunk.__toESM(node_path);
7
7
  let node_url = require("node:url");
8
8
  node_url = require_chunk.__toESM(node_url);
9
9
  let chalk = require("chalk");
10
- chalk = require_chunk.__toESM(chalk);
11
10
  let log4js = require("log4js");
12
11
  log4js = require_chunk.__toESM(log4js);
13
12
  let axios = require("axios");
@@ -17,7 +16,6 @@ node_crypto = require_chunk.__toESM(node_crypto);
17
16
  let zod = require("zod");
18
17
  zod = require_chunk.__toESM(zod);
19
18
  let __ikenxuan_xhshow_ts = require("@ikenxuan/xhshow-ts");
20
- __ikenxuan_xhshow_ts = require_chunk.__toESM(__ikenxuan_xhshow_ts);
21
19
  let express = require("express");
22
20
  express = require_chunk.__toESM(express);
23
21
 
@@ -25,7 +23,7 @@ express = require_chunk.__toESM(express);
25
23
  /** 获取包的绝对路径 */
26
24
  const getPackageLogsPath = () => {
27
25
  const currentFileUrl = require("url").pathToFileURL(__filename).href;
28
- const currentFilePath = (0, node_url.fileURLToPath)(currentFileUrl);
26
+ const currentFilePath = node_url.default.fileURLToPath(currentFileUrl);
29
27
  let packageRoot = node_path.default.dirname(currentFilePath);
30
28
  while (packageRoot !== node_path.default.dirname(packageRoot)) {
31
29
  if (node_fs.default.existsSync(node_path.default.join(packageRoot, "package.json"))) break;
@@ -140,7 +138,7 @@ const logMiddleware = (pathsToLog) => {
140
138
  return (req, res, next) => {
141
139
  if (!pathsToLog || pathsToLog.some((path$1) => req.url.startsWith(path$1))) {
142
140
  const startTime = Date.now();
143
- const url = req.url;
141
+ const url$1 = req.url;
144
142
  const method = req.method;
145
143
  const clientIP = req.headers["x-forwarded-for"] ?? req.socket.remoteAddress;
146
144
  const referer = req.headers["referer"] ?? req.headers["referrer"] ?? "-";
@@ -154,7 +152,7 @@ const logMiddleware = (pathsToLog) => {
154
152
  const responseSize = res.get("content-length") ?? "0";
155
153
  const logData = {
156
154
  method,
157
- url,
155
+ url: url$1,
158
156
  statusCode,
159
157
  responseTime: `${responseTime}ms`,
160
158
  clientIP,
@@ -554,6 +552,10 @@ var BiLiBiLiAPI = class {
554
552
  评论区状态(data$1) {
555
553
  return `https://api.bilibili.com/x/v2/reply/subject/description?type=${data$1.type}&oid=${data$1.oid}`;
556
554
  }
555
+ /** 指定评论的回复 */
556
+ 指定评论的回复(data$1) {
557
+ return `https://api.bilibili.com/x/v2/reply/reply?type=${data$1.type}&oid=${data$1.oid}&root=${data$1.root}&ps=${data$1.number}`;
558
+ }
557
559
  表情列表() {
558
560
  return "https://api.bilibili.com/x/emote/user/panel/web?business=reply&web_location=0.0";
559
561
  }
@@ -646,6 +648,7 @@ const bilibili = {
646
648
  getVideoInfo: createBilibiliApiMethod("单个视频作品数据"),
647
649
  getVideoStream: createBilibiliApiMethod("单个视频下载信息数据"),
648
650
  getComments: createBilibiliApiMethod("评论数据"),
651
+ getCommentReply: createBilibiliApiMethod("指定评论的回复"),
649
652
  getUserProfile: createBilibiliApiMethod("用户主页数据"),
650
653
  getUserDynamic: createBilibiliApiMethod("用户主页动态列表数据"),
651
654
  getEmojiList: createBilibiliApiMethod("Emoji数据"),
@@ -676,6 +679,7 @@ const createBoundBilibiliApi = (cookie, requestConfig) => {
676
679
  getVideoInfo: createBoundBilibiliApiMethod("单个视频作品数据", cookie),
677
680
  getVideoStream: createBoundBilibiliApiMethod("单个视频下载信息数据", cookie),
678
681
  getComments: createBoundBilibiliApiMethod("评论数据", cookie),
682
+ getCommentReply: createBoundBilibiliApiMethod("指定评论的回复", cookie),
679
683
  getUserProfile: createBoundBilibiliApiMethod("用户主页数据", cookie),
680
684
  getUserDynamic: createBoundBilibiliApiMethod("用户主页动态列表数据", cookie),
681
685
  getEmojiList: createBoundBilibiliApiMethod("Emoji数据", cookie),
@@ -867,9 +871,9 @@ const getWbiKeys = async (cookie) => {
867
871
  */
868
872
  const wbi_sign = async (BASEURL, cookie) => {
869
873
  const web_keys = await getWbiKeys(cookie);
870
- const url = new URL(BASEURL);
874
+ const url$1 = new URL(BASEURL);
871
875
  const params = {};
872
- for (const [key, value] of url.searchParams.entries()) params[key] = value;
876
+ for (const [key, value] of url$1.searchParams.entries()) params[key] = value;
873
877
  return encWbi(params, web_keys.img_key, web_keys.sub_key);
874
878
  };
875
879
 
@@ -946,7 +950,7 @@ const handleError = (error, requestPath) => {
946
950
  platform: error.platform,
947
951
  requestPath
948
952
  };
949
- if (error instanceof zod.z.ZodError) return handleError(ValidationError.fromZodError(error, requestPath), requestPath);
953
+ if (error instanceof zod.default.ZodError) return handleError(ValidationError.fromZodError(error, requestPath), requestPath);
950
954
  return {
951
955
  code: 500,
952
956
  message: error instanceof Error ? error.message : "未知错误",
@@ -958,8 +962,8 @@ const handleError = (error, requestPath) => {
958
962
  //#endregion
959
963
  //#region src/validation/utils.ts
960
964
  function smartNumber(errorMessage, minValue = 1, isInteger = false) {
961
- if (isInteger) return zod.z.coerce.number({ error: errorMessage }).int({ error: `${errorMessage.replace("不能为空", "")}必须是整数,不能包含小数` }).min(minValue, { error: `${errorMessage.replace("不能为空", "")}必须大于等于${minValue}` });
962
- else return zod.z.coerce.number({ error: errorMessage }).min(minValue, { error: `${errorMessage.replace("不能为空", "")}必须大于等于${minValue}` });
965
+ if (isInteger) return zod.default.coerce.number({ error: errorMessage }).int({ error: `${errorMessage.replace("不能为空", "")}必须是整数,不能包含小数` }).min(minValue, { error: `${errorMessage.replace("不能为空", "")}必须大于等于${minValue}` });
966
+ else return zod.default.coerce.number({ error: errorMessage }).min(minValue, { error: `${errorMessage.replace("不能为空", "")}必须大于等于${minValue}` });
963
967
  }
964
968
  /**
965
969
  * 智能正整数转换器 - 专门用于正整数类型的转换
@@ -988,18 +992,48 @@ const extractCreatorInfoFromHtml = (html) => {
988
992
 
989
993
  //#endregion
990
994
  //#region src/validation/bilibili.ts
991
- const BilibiliVideoParamsSchema = zod.z.object({
992
- methodType: zod.z.literal("单个视频作品数据", { error: "方法类型必须是\"单个视频作品数据\"" }),
993
- bvid: zod.z.string({ error: "BVID必须是字符串" }).min(1, { error: "BVID不能为空" })
995
+ const BilibiliVideoParamsSchema = zod.default.object({
996
+ methodType: zod.default.literal("单个视频作品数据", { error: "方法类型必须是\"单个视频作品数据\"" }),
997
+ bvid: zod.default.string({ error: "BVID必须是字符串" }).min(1, { error: "BVID不能为空" })
994
998
  });
995
- const BilibiliVideoDownloadParamsSchema = zod.z.object({
996
- methodType: zod.z.literal("单个视频下载信息数据", { error: "方法类型必须是\"单个视频下载信息数据\"" }),
999
+ const BilibiliVideoDownloadParamsSchema = zod.default.object({
1000
+ methodType: zod.default.literal("单个视频下载信息数据", { error: "方法类型必须是\"单个视频下载信息数据\"" }),
997
1001
  avid: smartNumber("AVID不能为空", 1, true),
998
1002
  cid: smartNumber("CID不能为空", 1, true)
999
1003
  });
1000
- const BilibiliCommentParamsSchema = zod.z.object({
1001
- methodType: zod.z.literal("评论数据", { error: "方法类型必须是\"评论数据\"" }),
1002
- oid: zod.z.string({ error: "OID必须是字符串" }).min(1, { error: "OID不能为空" }),
1004
+ const BilibiliCommentParamsSchema = zod.default.object({
1005
+ methodType: zod.default.literal("评论数据", { error: "方法类型必须是\"评论数据\"" }),
1006
+ oid: zod.default.string({ error: "OID必须是字符串" }).min(1, { error: "OID不能为空" }),
1007
+ type: smartNumber("评论类型不能为空", 1, true).refine((val) => [
1008
+ 1,
1009
+ 2,
1010
+ 4,
1011
+ 5,
1012
+ 6,
1013
+ 7,
1014
+ 8,
1015
+ 9,
1016
+ 10,
1017
+ 11,
1018
+ 12,
1019
+ 13,
1020
+ 14,
1021
+ 15,
1022
+ 16,
1023
+ 17,
1024
+ 18,
1025
+ 19,
1026
+ 20,
1027
+ 21,
1028
+ 22,
1029
+ 33
1030
+ ].includes(val), { error: "无效的评论区类型" }),
1031
+ number: zod.default.coerce.number({ error: "评论数量必须是数字" }).int({ error: "评论数量必须是整数" }).positive({ error: "评论数量必须是正数" }).default(20).optional(),
1032
+ pn: zod.default.coerce.number({ error: "页码必须是数字" }).int({ error: "页码必须是整数" }).positive({ error: "页码必须是正数" }).default(1).optional()
1033
+ });
1034
+ const BilibiliCommentReplyParamsSchema = zod.default.object({
1035
+ methodType: zod.default.literal("指定评论的回复", { error: "方法类型必须是\"指定评论的回复\"" }),
1036
+ oid: zod.default.string({ error: "OID必须是字符串" }).min(1, { error: "OID不能为空" }),
1003
1037
  type: smartNumber("评论类型不能为空", 1, true).refine((val) => [
1004
1038
  1,
1005
1039
  2,
@@ -1024,73 +1058,75 @@ const BilibiliCommentParamsSchema = zod.z.object({
1024
1058
  22,
1025
1059
  33
1026
1060
  ].includes(val), { error: "无效的评论区类型" }),
1027
- number: zod.z.coerce.number({ error: "评论数量必须是数字" }).int({ error: "评论数量必须是整数" }).positive({ error: "评论数量必须是正数" }).default(20).optional(),
1028
- pn: zod.z.coerce.number({ error: "页码必须是数字" }).int({ error: "页码必须是整数" }).positive({ error: "页码必须是正数" }).default(1).optional()
1061
+ root: zod.default.string({ error: "根评论ID必须是字符串" }).min(1, { error: "根评论ID不能为空" }),
1062
+ number: zod.default.coerce.number({ error: "评论数量必须是数字" }).int({ error: "评论数量必须是整数" }).positive({ error: "评论数量必须是正数" }).default(20).optional(),
1063
+ pn: zod.default.coerce.number({ error: "页码必须是数字" }).int({ error: "页码必须是整数" }).positive({ error: "页码必须是正数" }).default(1).optional()
1029
1064
  });
1030
- const BilibiliUserParamsSchema = zod.z.object({
1031
- methodType: zod.z.enum([
1065
+ const BilibiliUserParamsSchema = zod.default.object({
1066
+ methodType: zod.default.enum([
1032
1067
  "用户主页数据",
1033
1068
  "用户主页动态列表数据",
1034
1069
  "获取UP主总播放量"
1035
1070
  ], { error: "方法类型必须是指定的枚举值之一" }),
1036
1071
  host_mid: smartNumber("UP主UID不能为空", 1, true)
1037
1072
  });
1038
- const BilibiliEmojiParamsSchema = zod.z.object({ methodType: zod.z.literal("Emoji数据", { error: "方法类型必须是\"Emoji数据\"" }) });
1039
- const BilibiliBangumiInfoParamsSchema = zod.z.object({
1040
- methodType: zod.z.literal("番剧基本信息数据", { error: "方法类型必须是\"番剧基本信息数据\"" }),
1041
- ep_id: zod.z.string({ error: "番剧EP ID必须是字符串" }).min(1, { error: "番剧EP ID不能为空" }).optional(),
1042
- season_id: zod.z.string({ error: "番剧季度ID必须是字符串" }).optional()
1073
+ const BilibiliEmojiParamsSchema = zod.default.object({ methodType: zod.default.literal("Emoji数据", { error: "方法类型必须是\"Emoji数据\"" }) });
1074
+ const BilibiliBangumiInfoParamsSchema = zod.default.object({
1075
+ methodType: zod.default.literal("番剧基本信息数据", { error: "方法类型必须是\"番剧基本信息数据\"" }),
1076
+ ep_id: zod.default.string({ error: "番剧EP ID必须是字符串" }).min(1, { error: "番剧EP ID不能为空" }).optional(),
1077
+ season_id: zod.default.string({ error: "番剧季度ID必须是字符串" }).optional()
1043
1078
  }).refine((data$1) => data$1.ep_id ?? data$1.season_id, {
1044
1079
  error: "ep_id 和 season_id 至少需要提供一个",
1045
1080
  path: ["ep_id"]
1046
1081
  });
1047
- const BilibiliBangumiStreamParamsSchema = zod.z.object({
1048
- methodType: zod.z.literal("番剧下载信息数据", { error: "方法类型必须是\"番剧下载信息数据\"" }),
1082
+ const BilibiliBangumiStreamParamsSchema = zod.default.object({
1083
+ methodType: zod.default.literal("番剧下载信息数据", { error: "方法类型必须是\"番剧下载信息数据\"" }),
1049
1084
  cid: smartNumber("CID不能为空", 1, true),
1050
- ep_id: zod.z.string({ error: "番剧EP ID必须是字符串" }).min(1, { error: "番剧EP ID不能为空" })
1085
+ ep_id: zod.default.string({ error: "番剧EP ID必须是字符串" }).min(1, { error: "番剧EP ID不能为空" })
1051
1086
  });
1052
- const BilibiliDynamicParamsSchema = zod.z.object({
1053
- methodType: zod.z.enum(["动态详情数据", "动态卡片数据"], { error: "方法类型必须是\"动态详情数据\"或\"动态卡片数据\"" }),
1054
- dynamic_id: zod.z.string({ error: "动态ID必须是字符串" }).min(1, { error: "动态ID不能为空" })
1087
+ const BilibiliDynamicParamsSchema = zod.default.object({
1088
+ methodType: zod.default.enum(["动态详情数据", "动态卡片数据"], { error: "方法类型必须是\"动态详情数据\"或\"动态卡片数据\"" }),
1089
+ dynamic_id: zod.default.string({ error: "动态ID必须是字符串" }).min(1, { error: "动态ID不能为空" })
1055
1090
  });
1056
- const BilibiliLiveParamsSchema = zod.z.object({
1057
- methodType: zod.z.enum(["直播间信息", "直播间初始化信息"], { error: "方法类型必须是\"直播间信息\"或\"直播间初始化信息\"" }),
1058
- room_id: zod.z.string({ error: "直播间ID必须是字符串" }).min(1, { error: "直播间ID不能为空" })
1091
+ const BilibiliLiveParamsSchema = zod.default.object({
1092
+ methodType: zod.default.enum(["直播间信息", "直播间初始化信息"], { error: "方法类型必须是\"直播间信息\"或\"直播间初始化信息\"" }),
1093
+ room_id: zod.default.string({ error: "直播间ID必须是字符串" }).min(1, { error: "直播间ID不能为空" })
1059
1094
  });
1060
- const BilibiliLoginParamsSchema = zod.z.object({ methodType: zod.z.literal("登录基本信息", { error: "方法类型必须是\"登录基本信息\"" }) });
1061
- const BilibiliQrcodeParamsSchema = zod.z.object({ methodType: zod.z.literal("申请二维码", { error: "方法类型必须是\"申请二维码\"" }) });
1062
- const BilibiliQrcodeStatusParamsSchema = zod.z.object({
1063
- methodType: zod.z.literal("二维码状态", { error: "方法类型必须是\"二维码状态\"" }),
1064
- qrcode_key: zod.z.string({ error: "二维码key必须是字符串" }).min(1, { error: "二维码key不能为空" })
1095
+ const BilibiliLoginParamsSchema = zod.default.object({ methodType: zod.default.literal("登录基本信息", { error: "方法类型必须是\"登录基本信息\"" }) });
1096
+ const BilibiliQrcodeParamsSchema = zod.default.object({ methodType: zod.default.literal("申请二维码", { error: "方法类型必须是\"申请二维码\"" }) });
1097
+ const BilibiliQrcodeStatusParamsSchema = zod.default.object({
1098
+ methodType: zod.default.literal("二维码状态", { error: "方法类型必须是\"二维码状态\"" }),
1099
+ qrcode_key: zod.default.string({ error: "二维码key必须是字符串" }).min(1, { error: "二维码key不能为空" })
1065
1100
  });
1066
- const BilibiliAv2BvParamsSchema = zod.z.object({
1067
- methodType: zod.z.literal("AV转BV", { error: "方法类型必须是\"AV转BV\"" }),
1068
- avid: zod.z.coerce.number({ error: "AVID必须是数字" }).int({ error: "AVID必须是整数" }).positive({ error: "AVID必须是正数" })
1101
+ const BilibiliAv2BvParamsSchema = zod.default.object({
1102
+ methodType: zod.default.literal("AV转BV", { error: "方法类型必须是\"AV转BV\"" }),
1103
+ avid: zod.default.coerce.number({ error: "AVID必须是数字" }).int({ error: "AVID必须是整数" }).positive({ error: "AVID必须是正数" })
1069
1104
  });
1070
- const BilibiliBv2AvParamsSchema = zod.z.object({
1071
- methodType: zod.z.literal("BV转AV", { error: "方法类型必须是\"BV转AV\"" }),
1072
- bvid: zod.z.string({ error: "BVID必须是字符串" }).min(1, { error: "BVID不能为空" })
1105
+ const BilibiliBv2AvParamsSchema = zod.default.object({
1106
+ methodType: zod.default.literal("BV转AV", { error: "方法类型必须是\"BV转AV\"" }),
1107
+ bvid: zod.default.string({ error: "BVID必须是字符串" }).min(1, { error: "BVID不能为空" })
1073
1108
  });
1074
- const BilibiliArticleParamsSchema = zod.z.object({
1075
- methodType: zod.z.literal("专栏正文内容", { error: "方法类型必须是\"专栏正文内容\"" }),
1076
- id: zod.z.string({ error: "专栏ID必须是字符串" }).min(1, { error: "专栏ID不能为空" })
1109
+ const BilibiliArticleParamsSchema = zod.default.object({
1110
+ methodType: zod.default.literal("专栏正文内容", { error: "方法类型必须是\"专栏正文内容\"" }),
1111
+ id: zod.default.string({ error: "专栏ID必须是字符串" }).min(1, { error: "专栏ID不能为空" })
1077
1112
  });
1078
- const BilibiliArticleCardParamsSchema = zod.z.object({
1079
- methodType: zod.z.literal("专栏显示卡片信息", { error: "方法类型必须是\"专栏显示卡片信息\"" }),
1080
- ids: zod.z.union([zod.z.array(zod.z.string({ error: "被查询的 id 列表必须是字符串数组" })).min(1, { error: "被查询的 id 列表不能为空" }), zod.z.string({ error: "被查询的 id 列表必须是字符串" }).min(1, { error: "被查询的 id 列表不能为空" })])
1113
+ const BilibiliArticleCardParamsSchema = zod.default.object({
1114
+ methodType: zod.default.literal("专栏显示卡片信息", { error: "方法类型必须是\"专栏显示卡片信息\"" }),
1115
+ ids: zod.default.union([zod.default.array(zod.default.string({ error: "被查询的 id 列表必须是字符串数组" })).min(1, { error: "被查询的 id 列表不能为空" }), zod.default.string({ error: "被查询的 id 列表必须是字符串" }).min(1, { error: "被查询的 id 列表不能为空" })])
1081
1116
  });
1082
- const BilibiliArticleInfoParamsSchema = zod.z.object({
1083
- methodType: zod.z.literal("专栏文章基本信息", { error: "方法类型必须是\"专栏文章基本信息\"" }),
1084
- id: zod.z.string({ error: "专栏ID必须是字符串" }).min(1, { error: "专栏ID不能为空" })
1117
+ const BilibiliArticleInfoParamsSchema = zod.default.object({
1118
+ methodType: zod.default.literal("专栏文章基本信息", { error: "方法类型必须是\"专栏文章基本信息\"" }),
1119
+ id: zod.default.string({ error: "专栏ID必须是字符串" }).min(1, { error: "专栏ID不能为空" })
1085
1120
  });
1086
- const BilibiliColumnInfoParamsSchema = zod.z.object({
1087
- methodType: zod.z.literal("文集基本信息", { error: "方法类型必须是\"文集基本信息\"" }),
1088
- id: zod.z.string({ error: "文集ID必须是字符串" }).min(1, { error: "文集ID不能为空" })
1121
+ const BilibiliColumnInfoParamsSchema = zod.default.object({
1122
+ methodType: zod.default.literal("文集基本信息", { error: "方法类型必须是\"文集基本信息\"" }),
1123
+ id: zod.default.string({ error: "文集ID必须是字符串" }).min(1, { error: "文集ID不能为空" })
1089
1124
  });
1090
1125
  const BilibiliValidationSchemas = {
1091
1126
  单个视频作品数据: BilibiliVideoParamsSchema,
1092
1127
  单个视频下载信息数据: BilibiliVideoDownloadParamsSchema,
1093
1128
  评论数据: BilibiliCommentParamsSchema,
1129
+ 指定评论的回复: BilibiliCommentReplyParamsSchema,
1094
1130
  用户主页数据: BilibiliUserParamsSchema,
1095
1131
  用户主页动态列表数据: BilibiliUserParamsSchema,
1096
1132
  Emoji数据: BilibiliEmojiParamsSchema,
@@ -1111,62 +1147,87 @@ const BilibiliValidationSchemas = {
1111
1147
  专栏文章基本信息: BilibiliArticleInfoParamsSchema,
1112
1148
  文集基本信息: BilibiliColumnInfoParamsSchema
1113
1149
  };
1150
+ const BilibiliMethodRoutes = {
1151
+ 单个视频作品数据: "/fetch_one_video",
1152
+ 单个视频下载信息数据: "/fetch_video_playurl",
1153
+ 评论数据: "/fetch_work_comments",
1154
+ 指定评论的回复: "/fetch_comment_reply",
1155
+ 用户主页数据: "/fetch_user_profile",
1156
+ 用户主页动态列表数据: "/fetch_user_dynamic",
1157
+ Emoji数据: "/fetch_emoji_list",
1158
+ 番剧基本信息数据: "/fetch_bangumi_video_info",
1159
+ 番剧下载信息数据: "/fetch_bangumi_video_playurl",
1160
+ 动态详情数据: "/fetch_dynamic_info",
1161
+ 动态卡片数据: "/fetch_dynamic_card",
1162
+ 直播间信息: "/fetch_live_room_detail",
1163
+ 直播间初始化信息: "/fetch_liveroom_def",
1164
+ 登录基本信息: "/login_basic_info",
1165
+ 申请二维码: "/new_login_qrcode",
1166
+ 二维码状态: "/check_qrcode",
1167
+ 获取UP主总播放量: "/fetch_user_full_view",
1168
+ AV转BV: "/av_to_bv",
1169
+ BV转AV: "/bv_to_av",
1170
+ 专栏正文内容: "/fetch_article_content",
1171
+ 专栏显示卡片信息: "/fetch_article_card",
1172
+ 专栏文章基本信息: "/fetch_article_info",
1173
+ 文集基本信息: "/fetch_column_info"
1174
+ };
1114
1175
 
1115
1176
  //#endregion
1116
1177
  //#region src/validation/douyin.ts
1117
- const DouyinWorkParamsSchema = zod.z.object({
1118
- methodType: zod.z.enum([
1119
- "文字作品数据",
1178
+ const DouyinWorkParamsSchema = zod.default.object({
1179
+ methodType: zod.default.enum([
1120
1180
  "视频作品数据",
1121
1181
  "图集作品数据",
1122
1182
  "合辑作品数据",
1123
1183
  "聚合解析"
1124
1184
  ], { error: "方法类型必须是指定的枚举值之一" }),
1125
- aweme_id: zod.z.string({ error: "视频ID必须是字符串" }).min(1, { error: "视频ID不能为空" })
1185
+ aweme_id: zod.default.string({ error: "视频ID必须是字符串" }).min(1, { error: "视频ID不能为空" })
1126
1186
  });
1127
- const DouyinCommentParamsSchema = zod.z.object({
1128
- methodType: zod.z.literal("评论数据", { error: "方法类型必须是\"评论数据\"" }),
1129
- aweme_id: zod.z.string({ error: "视频ID必须是字符串" }).min(1, { error: "视频ID不能为空" }),
1187
+ const DouyinCommentParamsSchema = zod.default.object({
1188
+ methodType: zod.default.literal("评论数据", { error: "方法类型必须是\"评论数据\"" }),
1189
+ aweme_id: zod.default.string({ error: "视频ID必须是字符串" }).min(1, { error: "视频ID不能为空" }),
1130
1190
  number: smartPositiveInteger("评论数量必须是正整数").optional().default(50),
1131
- cursor: zod.z.coerce.number({ error: "游标必须是数字" }).int({ error: "游标必须是整数" }).min(0, { error: "游标不能小于0" }).default(0).optional()
1191
+ cursor: zod.default.coerce.number({ error: "游标必须是数字" }).int({ error: "游标必须是整数" }).min(0, { error: "游标不能小于0" }).default(0).optional()
1132
1192
  });
1133
- const DouyinSearchParamsSchema = zod.z.object({
1134
- methodType: zod.z.enum(["热点词数据", "搜索数据"], { error: "方法类型必须是\"热点词数据\"或\"搜索数据\"" }),
1135
- query: zod.z.string({ error: "搜索词必须是字符串" }).min(1, { error: "搜索词不能为空" }),
1193
+ const DouyinSearchParamsSchema = zod.default.object({
1194
+ methodType: zod.default.enum(["热点词数据", "搜索数据"], { error: "方法类型必须是\"热点词数据\"或\"搜索数据\"" }),
1195
+ query: zod.default.string({ error: "搜索词必须是字符串" }).min(1, { error: "搜索词不能为空" }),
1136
1196
  number: smartPositiveInteger("搜索数量必须是正整数").optional().default(10),
1137
- search_id: zod.z.string({ error: "搜索ID必须是字符串" }).optional()
1197
+ search_id: zod.default.string({ error: "搜索ID必须是字符串" }).optional()
1138
1198
  });
1139
- const DouyinCommentReplyParamsSchema = zod.z.object({
1140
- methodType: zod.z.literal("指定评论回复数据", { error: "方法类型必须是\"指定评论回复数据\"" }),
1141
- aweme_id: zod.z.string({ error: "视频ID必须是字符串" }).min(1, { error: "视频ID不能为空" }),
1142
- comment_id: zod.z.string({ error: "评论ID必须是字符串" }).min(1, { error: "评论ID不能为空" }),
1199
+ const DouyinCommentReplyParamsSchema = zod.default.object({
1200
+ methodType: zod.default.literal("指定评论回复数据", { error: "方法类型必须是\"指定评论回复数据\"" }),
1201
+ aweme_id: zod.default.string({ error: "视频ID必须是字符串" }).min(1, { error: "视频ID不能为空" }),
1202
+ comment_id: zod.default.string({ error: "评论ID必须z串" }).min(1, { error: "评论ID不能为空" }),
1143
1203
  number: smartPositiveInteger("评论数量必须是正整数").optional().default(5),
1144
- cursor: zod.z.coerce.number({ error: "游标必须是数字" }).int({ error: "游标必须是整数" }).min(0, { error: "游标不能小于0" }).default(0).optional()
1204
+ cursor: zod.default.coerce.number({ error: "游标必须是数字" }).int({ error: "游标必须是整数" }).min(0, { error: "游标不能小于0" }).default(0).optional()
1145
1205
  });
1146
- const DouyinUserParamsSchema = zod.z.object({
1147
- methodType: zod.z.enum([
1148
- "用户主页数据",
1149
- "用户主页视频列表数据",
1150
- "直播间信息数据"
1151
- ], { error: "方法类型必须是指定的枚举值之一" }),
1152
- sec_uid: zod.z.string({ error: "用户ID必须是字符串" }).min(1, { error: "用户ID不能为空" })
1206
+ const DouyinUserParamsSchema = zod.default.object({
1207
+ methodType: zod.default.enum(["用户主页数据", "用户主页视频列表数据"], { error: "方法类型必须是指定的枚举值之一" }),
1208
+ sec_uid: zod.default.string({ error: "用户ID必须是字符串" }).min(1, { error: "用户ID不能为空" })
1209
+ });
1210
+ const DouyinMusicParamsSchema = zod.default.object({
1211
+ methodType: zod.default.literal("音乐数据", { error: "方法类型必须是\"音乐数据\"" }),
1212
+ music_id: zod.default.string({ error: "音乐ID必须是字符串" }).min(1, { error: "音乐ID不能为空" })
1153
1213
  });
1154
- const DouyinMusicParamsSchema = zod.z.object({
1155
- methodType: zod.z.literal("音乐数据", { error: "方法类型必须是\"音乐数据\"" }),
1156
- music_id: zod.z.string({ error: "音乐ID必须是字符串" }).min(1, { error: "音乐ID不能为空" })
1214
+ const DouyinLiveRoomParamsSchema = zod.default.object({
1215
+ methodType: zod.default.literal("直播间信息数据", { error: "方法类型必须是\"直播间信息数据\"" }),
1216
+ web_rid: zod.default.string({ error: "直播间ID必须是字符串" }).min(1, { error: "直播间ID不能为空" }),
1217
+ room_id: zod.default.string({ error: "直播间ID必须是字符串" }).min(1, { error: "直播间ID不能为空" })
1157
1218
  });
1158
- const DouyinQrcodeParamsSchema = zod.z.object({
1159
- methodType: zod.z.literal("申请二维码数据", { error: "方法类型必须是\"申请二维码数据\"" }),
1160
- verify_fp: zod.z.string({ error: "fp指纹必须是字符串" }).min(1, { error: "fp指纹不能为空" })
1219
+ const DouyinQrcodeParamsSchema = zod.default.object({
1220
+ methodType: zod.default.literal("申请二维码数据", { error: "方法类型必须是\"申请二维码数据\"" }),
1221
+ verify_fp: zod.default.string({ error: "fp指纹必须是字符串" }).min(1, { error: "fp指纹不能为空" })
1161
1222
  });
1162
- const DouyinEmojiListParamsSchema = zod.z.object({ methodType: zod.z.literal("Emoji数据", { error: "方法类型必须是\"Emoji数据\"" }) });
1163
- const DouyinEmojiProParamsSchema = zod.z.object({ methodType: zod.z.literal("动态表情数据", { error: "方法类型必须是\"动态表情数据\"" }) });
1164
- const DouyinDanmakuParamsSchema = zod.z.object({
1165
- methodType: zod.z.literal("弹幕数据", { error: "方法类型必须是\"弹幕数据\"" }),
1166
- aweme_id: zod.z.string({ error: "视频ID必须是字符串" }).min(1, { error: "视频ID不能为空" }),
1167
- start_time: zod.z.coerce.number({ error: "开始时间必须是数字" }).int({ error: "开始时间必须是整数" }).min(0, { error: "开始时间不能小于0" }).optional(),
1168
- end_time: zod.z.coerce.number({ error: "结束时间必须是数字" }).int({ error: "结束时间必须是整数" }).min(0, { error: "结束时间不能小于0" }).optional(),
1169
- duration: zod.z.coerce.number({ error: "视频时长必须是数字" }).int({ error: "视频时长必须是整数" }).min(0, { error: "视频时长不能小于0" })
1223
+ const DouyinEmojiListParamsSchema = zod.default.object({ methodType: zod.default.literal("Emoji数据", { error: "方法类型必须是\"Emoji数据\"" }) });
1224
+ const DouyinEmojiProParamsSchema = zod.default.object({ methodType: zod.default.literal("动态表情数据", { error: "方法类型必须是\"动态表情数据\"" }) });
1225
+ const DouyinDanmakuParamsSchema = zod.default.object({
1226
+ methodType: zod.default.literal("弹幕数据", { error: "方法类型必须是\"弹幕数据\"" }),
1227
+ aweme_id: zod.default.string({ error: "视频ID必须是字符串" }).min(1, { error: "视频ID不能为空" }),
1228
+ start_time: zod.default.coerce.number({ error: "开始时间必须是数字" }).int({ error: "开始时间必须是整数" }).min(0, { error: "开始时间不能小于0" }).optional(),
1229
+ end_time: zod.default.coerce.number({ error: "结束时间必须是数字" }).int({ error: "结束时间必须是整数" }).min(0, { error: "结束时间不能小于0" }).optional(),
1230
+ duration: zod.default.coerce.number({ error: "视频时长必须是数字" }).int({ error: "视频时长必须是整数" }).min(0, { error: "视频时长不能小于0" })
1170
1231
  }).refine((data$1) => {
1171
1232
  if (data$1.end_time !== void 0) return data$1.end_time <= data$1.duration;
1172
1233
  return true;
@@ -1192,30 +1253,53 @@ const DouyinValidationSchemas = {
1192
1253
  热点词数据: DouyinSearchParamsSchema,
1193
1254
  搜索数据: DouyinSearchParamsSchema,
1194
1255
  音乐数据: DouyinMusicParamsSchema,
1195
- 直播间信息数据: DouyinUserParamsSchema,
1256
+ 直播间信息数据: DouyinLiveRoomParamsSchema,
1196
1257
  申请二维码数据: DouyinQrcodeParamsSchema,
1197
1258
  Emoji数据: DouyinEmojiListParamsSchema,
1198
1259
  动态表情数据: DouyinEmojiProParamsSchema,
1199
1260
  指定评论回复数据: DouyinCommentReplyParamsSchema,
1200
1261
  弹幕数据: DouyinDanmakuParamsSchema
1201
1262
  };
1263
+ const DouyinMethodRoutes = {
1264
+ 聚合解析: "/fetch_one_work",
1265
+ 文字作品数据: "/fetch_one_work",
1266
+ 视频作品数据: "/fetch_one_work",
1267
+ 图集作品数据: "/fetch_one_work",
1268
+ 合辑作品数据: "/fetch_one_work",
1269
+ 评论数据: "/fetch_work_comments",
1270
+ 用户主页数据: "/fetch_user_info",
1271
+ 用户主页视频列表数据: "/fetch_user_post_videos",
1272
+ 搜索数据: "/fetch_search_info",
1273
+ 热点词数据: "/fetch_suggest_words",
1274
+ 音乐数据: "/fetch_music_work",
1275
+ Emoji数据: "/fetch_emoji_list",
1276
+ 动态表情数据: "/fetch_emoji_pro_list",
1277
+ 直播间信息数据: "/fetch_user_live_videos",
1278
+ 指定评论回复数据: "/fetch_video_comment_replies",
1279
+ 弹幕数据: "/fetch_work_danmaku"
1280
+ };
1202
1281
 
1203
1282
  //#endregion
1204
1283
  //#region src/validation/kuaishou.ts
1205
- const KuaishouVideoParamsSchema = zod.z.object({
1206
- methodType: zod.z.literal("单个视频作品数据", { error: "方法类型必须是\"单个视频作品数据\"" }),
1207
- photoId: zod.z.string({ error: "视频ID必须是字符串" }).min(1, { error: "视频ID不能为空" })
1284
+ const KuaishouVideoParamsSchema = zod.default.object({
1285
+ methodType: zod.default.literal("单个视频作品数据", { error: "方法类型必须是\"单个视频作品数据\"" }),
1286
+ photoId: zod.default.string({ error: "视频ID必须是字符串" }).min(1, { error: "视频ID不能为空" })
1208
1287
  });
1209
- const KuaishouCommentParamsSchema = zod.z.object({
1210
- methodType: zod.z.literal("评论数据", { error: "方法类型必须是\"评论数据\"" }),
1211
- photoId: zod.z.string({ error: "视频ID必须是字符串" }).min(1, { error: "视频ID不能为空" })
1288
+ const KuaishouCommentParamsSchema = zod.default.object({
1289
+ methodType: zod.default.literal("评论数据", { error: "方法类型必须是\"评论数据\"" }),
1290
+ photoId: zod.default.string({ error: "视频ID必须是字符串" }).min(1, { error: "视频ID不能为空" })
1212
1291
  });
1213
- const KuaishouEmojiParamsSchema = zod.z.object({ methodType: zod.z.literal("Emoji数据", { error: "方法类型必须是\"Emoji数据\"" }) });
1292
+ const KuaishouEmojiParamsSchema = zod.default.object({ methodType: zod.default.literal("Emoji数据", { error: "方法类型必须是\"Emoji数据\"" }) });
1214
1293
  const KuaishouValidationSchemas = {
1215
1294
  单个视频作品数据: KuaishouVideoParamsSchema,
1216
1295
  评论数据: KuaishouCommentParamsSchema,
1217
1296
  Emoji数据: KuaishouEmojiParamsSchema
1218
1297
  };
1298
+ const KuaishouMethodRoutes = {
1299
+ 单个视频作品数据: "/fetch_one_work",
1300
+ 评论数据: "/fetch_work_comments",
1301
+ Emoji数据: "/fetch_emoji_list"
1302
+ };
1219
1303
 
1220
1304
  //#endregion
1221
1305
  //#region src/platform/xiaohongshu/sign/index.ts
@@ -1255,9 +1339,9 @@ var xiaohongshuSign = class {
1255
1339
  * @param a1Cookie - a1 cookie值
1256
1340
  * @returns X-S签名
1257
1341
  */
1258
- static generateXS(url, body, userAgent, method = "POST", a1Cookie = "") {
1342
+ static generateXS(url$1, body, userAgent, method = "POST", a1Cookie = "") {
1259
1343
  try {
1260
- const urlObj = new URL(url);
1344
+ const urlObj = new URL(url$1);
1261
1345
  const path$1 = urlObj.pathname + urlObj.search;
1262
1346
  if (method.toUpperCase() === "GET") {
1263
1347
  const params = typeof body === "object" ? body : {};
@@ -1473,59 +1557,59 @@ const SearchNoteTypeValues = Object.values(SearchNoteType).filter((v) => typeof
1473
1557
  /**
1474
1558
  * 小红书首页推荐数据参数验证模式
1475
1559
  */
1476
- const HomeFeedParamsSchema = zod.z.object({
1477
- methodType: zod.z.literal("首页推荐数据", { error: "方法类型必须是\"首页推荐数据\"" }),
1478
- cursor_score: zod.z.string({ error: "cursor_score必须是字符串" }).optional(),
1479
- num: zod.z.coerce.number({ error: "数量必须是数字" }).int({ error: "数量必须是整数" }).min(1, { error: "数量不能小于1" }).max(100, { error: "数量不能大于100" }).optional(),
1480
- refresh_type: zod.z.coerce.number({ error: "refresh_type必须是数字" }).int({ error: "refresh_type必须是整数" }).optional(),
1481
- note_index: zod.z.coerce.number({ error: "note_index必须是数字" }).int({ error: "note_index必须是整数" }).optional(),
1482
- category: zod.z.string({ error: "category必须是字符串" }).optional(),
1483
- search_key: zod.z.string({ error: "search_key必须是字符串" }).optional()
1560
+ const HomeFeedParamsSchema = zod.default.object({
1561
+ methodType: zod.default.literal("首页推荐数据", { error: "方法类型必须是\"首页推荐数据\"" }),
1562
+ cursor_score: zod.default.string({ error: "cursor_score必须是字符串" }).optional(),
1563
+ num: zod.default.coerce.number({ error: "数量必须是数字" }).int({ error: "数量必须是整数" }).min(1, { error: "数量不能小于1" }).max(100, { error: "数量不能大于100" }).optional(),
1564
+ refresh_type: zod.default.coerce.number({ error: "refresh_type必须是数字" }).int({ error: "refresh_type必须是整数" }).optional(),
1565
+ note_index: zod.default.coerce.number({ error: "note_index必须是数字" }).int({ error: "note_index必须是整数" }).optional(),
1566
+ category: zod.default.string({ error: "category必须是字符串" }).optional(),
1567
+ search_key: zod.default.string({ error: "search_key必须是字符串" }).optional()
1484
1568
  });
1485
1569
  /**
1486
1570
  * 小红书单个笔记数据参数验证模式
1487
1571
  */
1488
- const NoteParamsSchema = zod.z.object({
1489
- methodType: zod.z.literal("单个笔记数据", { error: "方法类型必须是\"单个笔记数据\"" }),
1490
- note_id: zod.z.string({ error: "note_id必须是字符串" }),
1491
- xsec_token: zod.z.string({ error: "xsec_token必须是字符串" })
1572
+ const NoteParamsSchema = zod.default.object({
1573
+ methodType: zod.default.literal("单个笔记数据", { error: "方法类型必须是\"单个笔记数据\"" }),
1574
+ note_id: zod.default.string({ error: "note_id必须是字符串" }),
1575
+ xsec_token: zod.default.string({ error: "xsec_token必须是字符串" })
1492
1576
  });
1493
1577
  /**
1494
1578
  * 小红书评论数据参数验证模式
1495
1579
  */
1496
- const CommentParamsSchema = zod.z.object({
1497
- methodType: zod.z.literal("评论数据", { error: "方法类型必须是\"评论数据\"" }),
1498
- note_id: zod.z.string({ error: "note_id必须是字符串" }),
1499
- cursor: zod.z.string({ error: "cursor必须是字符串" }).optional(),
1500
- xsec_token: zod.z.string({ error: "xsec_token必须是字符串" })
1580
+ const CommentParamsSchema = zod.default.object({
1581
+ methodType: zod.default.literal("评论数据", { error: "方法类型必须是\"评论数据\"" }),
1582
+ note_id: zod.default.string({ error: "note_id必须是字符串" }),
1583
+ cursor: zod.default.string({ error: "cursor必须是字符串" }).optional(),
1584
+ xsec_token: zod.default.string({ error: "xsec_token必须是字符串" })
1501
1585
  });
1502
1586
  /**
1503
1587
  * 小红书用户数据参数验证模式
1504
1588
  */
1505
- const UserParamsSchema = zod.z.object({
1506
- methodType: zod.z.literal("用户数据", { error: "方法类型必须是\"用户数据\"" }),
1507
- user_id: zod.z.string({ error: "user_id必须是字符串" })
1589
+ const UserParamsSchema = zod.default.object({
1590
+ methodType: zod.default.literal("用户数据", { error: "方法类型必须是\"用户数据\"" }),
1591
+ user_id: zod.default.string({ error: "user_id必须是字符串" })
1508
1592
  });
1509
1593
  /**
1510
1594
  * 小红书用户笔记数据参数验证模式
1511
1595
  */
1512
- const UserNoteParamsSchema = zod.z.object({
1513
- methodType: zod.z.literal("用户笔记数据", { error: "方法类型必须是\"用户笔记数据\"" }),
1514
- user_id: zod.z.string({ error: "user_id必须是字符串" }),
1515
- cursor: zod.z.string({ error: "cursor必须是字符串" }).optional(),
1516
- num: zod.z.coerce.number({ error: "数量必须是数字" }).int({ error: "数量必须是整数" }).min(1, { error: "数量不能小于1" }).max(100, { error: "数量不能大于100" }).optional()
1596
+ const UserNoteParamsSchema = zod.default.object({
1597
+ methodType: zod.default.literal("用户笔记数据", { error: "方法类型必须是\"用户笔记数据\"" }),
1598
+ user_id: zod.default.string({ error: "user_id必须是字符串" }),
1599
+ cursor: zod.default.string({ error: "cursor必须是字符串" }).optional(),
1600
+ num: zod.default.coerce.number({ error: "数量必须是数字" }).int({ error: "数量必须是整数" }).min(1, { error: "数量不能小于1" }).max(100, { error: "数量不能大于100" }).optional()
1517
1601
  });
1518
- const EmojiListParamsSchema = zod.z.object({ methodType: zod.z.literal("表情列表", { error: "方法类型必须是\"表情列表\"" }) });
1602
+ const EmojiListParamsSchema = zod.default.object({ methodType: zod.default.literal("表情列表", { error: "方法类型必须是\"表情列表\"" }) });
1519
1603
  /**
1520
1604
  * 小红书搜索笔记参数验证模式
1521
1605
  */
1522
- const SearchNoteParamsSchema = zod.z.object({
1523
- methodType: zod.z.literal("搜索笔记", { error: "方法类型必须是\"搜索笔记\"" }),
1524
- keyword: zod.z.string({ error: "keyword必须是字符串" }),
1525
- page: zod.z.coerce.number({ error: "page必须是数字" }).int({ error: "page必须是整数" }).min(1, { error: "page不能小于1" }).optional(),
1526
- page_size: zod.z.coerce.number({ error: "page_size必须是数字" }).int({ error: "page_size必须是整数" }).min(1, { error: "page_size不能小于1" }).max(100, { error: "page_size不能大于100" }).optional(),
1527
- sort: zod.z.enum(SearchSortTypeValues, { error: "排序类型不合法" }).optional(),
1528
- note_type: zod.z.coerce.number({ error: "笔记类型必须是数字" }).int({ error: "笔记类型必须是整数" }).refine((val) => SearchNoteTypeValues.includes(val), { message: "笔记类型不合法" }).optional()
1606
+ const SearchNoteParamsSchema = zod.default.object({
1607
+ methodType: zod.default.literal("搜索笔记", { error: "方法类型必须是\"搜索笔记\"" }),
1608
+ keyword: zod.default.string({ error: "keyword必须是字符串" }),
1609
+ page: zod.default.coerce.number({ error: "page必须是数字" }).int({ error: "page必须是整数" }).min(1, { error: "page不能小于1" }).optional(),
1610
+ page_size: zod.default.coerce.number({ error: "page_size必须是数字" }).int({ error: "page_size必须是整数" }).min(1, { error: "page_size不能小于1" }).max(100, { error: "page_size不能大于100" }).optional(),
1611
+ sort: zod.default.enum(SearchSortTypeValues, { error: "排序类型不合法" }).optional(),
1612
+ note_type: zod.default.coerce.number({ error: "笔记类型必须是数字" }).int({ error: "笔记类型必须是整数" }).refine((val) => SearchNoteTypeValues.includes(val), { message: "笔记类型不合法" }).optional()
1529
1613
  });
1530
1614
  /**
1531
1615
  * 小红书验证模式映射
@@ -1540,19 +1624,16 @@ const XiaohongshuValidationSchemas = {
1540
1624
  搜索笔记: SearchNoteParamsSchema
1541
1625
  };
1542
1626
  /**
1543
- * 验证小红书参数
1544
- * @param methodType - 小红书方法类型
1545
- * @param params - 待验证的参数
1546
- * @returns 验证后的参数
1627
+ * 小红书方法类型
1547
1628
  */
1548
- const validateXiaohongshuParams = (methodType, params) => {
1549
- return XiaohongshuValidationSchemas[methodType].parse(typeof params === "object" && params !== null ? {
1550
- methodType,
1551
- ...params
1552
- } : {
1553
- methodType,
1554
- params
1555
- });
1629
+ const XiaohongshuMethodRoutes = {
1630
+ 首页推荐数据: "/fetch_home_feed",
1631
+ 单个笔记数据: "/fetch_one_note",
1632
+ 评论数据: "/fetch_note_comments",
1633
+ 用户数据: "/fetch_user_profile",
1634
+ 用户笔记数据: "/fetch_user_notes",
1635
+ 表情列表: "/fetch_emoji_list",
1636
+ 搜索笔记: "/fetch_search_notes"
1556
1637
  };
1557
1638
 
1558
1639
  //#endregion
@@ -1603,6 +1684,21 @@ const validateKuaishouParams = (methodType, params) => {
1603
1684
  });
1604
1685
  };
1605
1686
  /**
1687
+ * 验证小红书参数
1688
+ * @param methodType - 小红书方法类型
1689
+ * @param params - 待验证的参数
1690
+ * @returns 验证后的参数
1691
+ */
1692
+ const validateXiaohongshuParams = (methodType, params) => {
1693
+ return XiaohongshuValidationSchemas[methodType].parse(typeof params === "object" && params !== null ? {
1694
+ methodType,
1695
+ ...params
1696
+ } : {
1697
+ methodType,
1698
+ params
1699
+ });
1700
+ };
1701
+ /**
1606
1702
  * 创建成功响应格式
1607
1703
  * @param data - 响应数据
1608
1704
  * @param message - 响应消息(可选)
@@ -1715,29 +1811,8 @@ const createBilibiliRouteHandler = (dataFetcher, methodType, cookie, requestConf
1715
1811
  * @returns Express路由器
1716
1812
  */
1717
1813
  const createBilibiliRoutes = (cookie, requestConfig = getBilibiliDefaultConfig(cookie)) => {
1718
- const router = (0, express.Router)();
1719
- router.get("/fetch_one_video", createBilibiliValidationMiddleware("单个视频作品数据"), createBilibiliRouteHandler(getBilibiliData, "单个视频作品数据", cookie, requestConfig));
1720
- router.get("/fetch_video_playurl", createBilibiliValidationMiddleware("单个视频下载信息数据"), createBilibiliRouteHandler(getBilibiliData, "单个视频下载信息数据", cookie, requestConfig));
1721
- router.get("/fetch_work_comments", createBilibiliValidationMiddleware("评论数据"), createBilibiliRouteHandler(getBilibiliData, "评论数据", cookie, requestConfig));
1722
- router.get("/fetch_user_profile", createBilibiliValidationMiddleware("用户主页数据"), createBilibiliRouteHandler(getBilibiliData, "用户主页数据", cookie, requestConfig));
1723
- router.get("/fetch_user_dynamic", createBilibiliValidationMiddleware("用户主页动态列表数据"), createBilibiliRouteHandler(getBilibiliData, "用户主页动态列表数据", cookie, requestConfig));
1724
- router.get("/fetch_emoji_list", createBilibiliValidationMiddleware("Emoji数据"), createBilibiliRouteHandler(getBilibiliData, "Emoji数据", cookie, requestConfig));
1725
- router.get("/fetch_bangumi_video_info", createBilibiliValidationMiddleware("番剧基本信息数据"), createBilibiliRouteHandler(getBilibiliData, "番剧基本信息数据", cookie, requestConfig));
1726
- router.get("/fetch_bangumi_video_playurl", createBilibiliValidationMiddleware("番剧下载信息数据"), createBilibiliRouteHandler(getBilibiliData, "番剧下载信息数据", cookie, requestConfig));
1727
- router.get("/fetch_dynamic_info", createBilibiliValidationMiddleware("动态详情数据"), createBilibiliRouteHandler(getBilibiliData, "动态详情数据", cookie, requestConfig));
1728
- router.get("/fetch_dynamic_card", createBilibiliValidationMiddleware("动态卡片数据"), createBilibiliRouteHandler(getBilibiliData, "动态卡片数据", cookie, requestConfig));
1729
- router.get("/fetch_live_room_detail", createBilibiliValidationMiddleware("直播间信息"), createBilibiliRouteHandler(getBilibiliData, "直播间信息", cookie, requestConfig));
1730
- router.get("/fetch_liveroom_def", createBilibiliValidationMiddleware("直播间初始化信息"), createBilibiliRouteHandler(getBilibiliData, "直播间初始化信息", cookie, requestConfig));
1731
- router.get("/login_basic_info", createBilibiliValidationMiddleware("登录基本信息"), createBilibiliRouteHandler(getBilibiliData, "登录基本信息", cookie, requestConfig));
1732
- router.get("/new_login_qrcode", createBilibiliValidationMiddleware("申请二维码"), createBilibiliRouteHandler(getBilibiliData, "申请二维码", cookie, requestConfig));
1733
- router.get("/check_qrcode", createBilibiliValidationMiddleware("二维码状态"), createBilibiliRouteHandler(getBilibiliData, "二维码状态", cookie, requestConfig));
1734
- router.get("/fetch_user_full_view", createBilibiliValidationMiddleware("获取UP主总播放量"), createBilibiliRouteHandler(getBilibiliData, "获取UP主总播放量", cookie, requestConfig));
1735
- router.get("/av_to_bv", createBilibiliValidationMiddleware("AV转BV"), createBilibiliRouteHandler(getBilibiliData, "AV转BV", cookie, requestConfig));
1736
- router.get("/bv_to_av", createBilibiliValidationMiddleware("BV转AV"), createBilibiliRouteHandler(getBilibiliData, "BV转AV", cookie, requestConfig));
1737
- router.get("/fetch_article_content", createBilibiliValidationMiddleware("专栏正文内容"), createBilibiliRouteHandler(getBilibiliData, "专栏正文内容", cookie, requestConfig));
1738
- router.get("/fetch_article_card", createBilibiliValidationMiddleware("专栏显示卡片信息"), createBilibiliRouteHandler(getBilibiliData, "专栏显示卡片信息", cookie, requestConfig));
1739
- router.get("/fetch_article_info", createBilibiliValidationMiddleware("专栏文章基本信息"), createBilibiliRouteHandler(getBilibiliData, "专栏文章基本信息", cookie, requestConfig));
1740
- router.get("/fetch_column_info", createBilibiliValidationMiddleware("文集基本信息"), createBilibiliRouteHandler(getBilibiliData, "文集基本信息", cookie, requestConfig));
1814
+ const router = express.default.Router();
1815
+ for (const [method, path$1] of Object.entries(BilibiliMethodRoutes)) router.get(path$1, createBilibiliValidationMiddleware(method), createBilibiliRouteHandler(getBilibiliData, method, cookie, requestConfig));
1741
1816
  return router;
1742
1817
  };
1743
1818
 
@@ -1803,6 +1878,12 @@ const qtparam = async (BASEURL, cookie) => {
1803
1878
  //#endregion
1804
1879
  //#region src/platform/bilibili/getdata.ts
1805
1880
  /**
1881
+ * B站数据获取模块
1882
+ *
1883
+ * 注意:为避免循环依赖,此文件直接从具体模块导入,而不是从平台 index 文件导入
1884
+ * 循环依赖链:DataFetchers → getdata → platform/bilibili → DataFetchers
1885
+ */
1886
+ /**
1806
1887
  * B站数据获取函数
1807
1888
  * @param data - 请求数据参数
1808
1889
  * @param cookie - 用户Cookie
@@ -1898,6 +1979,10 @@ const fetchBilibili = async (data$1, cookie, requestConfig) => {
1898
1979
  }
1899
1980
  };
1900
1981
  }
1982
+ case "指定评论的回复": return await GlobalGetData$3(data$1.methodType, {
1983
+ ...baseRequestConfig,
1984
+ url: bilibiliApiUrls.指定评论的回复(data$1)
1985
+ });
1901
1986
  case "Emoji数据": return await GlobalGetData$3(data$1.methodType, {
1902
1987
  ...baseRequestConfig,
1903
1988
  url: bilibiliApiUrls.表情列表()
@@ -2591,9 +2676,9 @@ const cleanUserAgentForSigning = (userAgent) => {
2591
2676
  * @param user_agent - 用户代理字符串
2592
2677
  * @returns 生成的a_bogus签名
2593
2678
  */
2594
- var a_bogus_default = (url, user_agent) => {
2679
+ var a_bogus_default = (url$1, user_agent) => {
2595
2680
  const cleanedUserAgent = cleanUserAgentForSigning(user_agent);
2596
- return result_encrypt(generate_random_str() + generate_rc4_bb_str(new URLSearchParams(new URL(url).search).toString(), cleanedUserAgent, "1536|747|1536|834|0|30|0|0|1536|834|1536|864|1525|747|24|24|Win32"), "s4") + "=";
2681
+ return result_encrypt(generate_random_str() + generate_rc4_bb_str(new URLSearchParams(new URL(url$1).search).toString(), cleanedUserAgent, "1536|747|1536|834|0|30|0|0|1536|834|1536|864|1525|747|24|24|Win32"), "s4") + "=";
2597
2682
  };
2598
2683
 
2599
2684
  //#endregion
@@ -2695,8 +2780,8 @@ var XBogus = class {
2695
2780
  * @param ua 可选的User-Agent,不提供则使用默认值
2696
2781
  * @returns 包含完整URL、X-Bogus值和使用的User-Agent的元组
2697
2782
  */
2698
- getXBogus(url, ua) {
2699
- const parsedUrl = new node_url.default.URL(url);
2783
+ getXBogus(url$1, ua) {
2784
+ const parsedUrl = new node_url.default.URL(url$1);
2700
2785
  const urlPath = parsedUrl.pathname + parsedUrl.search;
2701
2786
  const currentUa = ua ?? this.defaultUa;
2702
2787
  const rc4EncryptedUa = this.rc4Encrypt(this.uaKey, currentUa);
@@ -2753,7 +2838,7 @@ var XBogus = class {
2753
2838
  idx += 3;
2754
2839
  }
2755
2840
  return {
2756
- fullUrl: url.includes("?") ? `${url}&X-Bogus=${xb}` : `${url}?X-Bogus=${xb}`,
2841
+ fullUrl: url$1.includes("?") ? `${url$1}&X-Bogus=${xb}` : `${url$1}?X-Bogus=${xb}`,
2757
2842
  xbogus: xb,
2758
2843
  userAgent: currentUa
2759
2844
  };
@@ -2779,16 +2864,16 @@ var douyinSign = class {
2779
2864
  * @param url 需要签名的地址
2780
2865
  * @returns 对此地址签名后的URL查询参数
2781
2866
  */
2782
- static AB(url, userAgent) {
2783
- return a_bogus_default(url, userAgent ?? defaultUserAgent);
2867
+ static AB(url$1, userAgent) {
2868
+ return a_bogus_default(url$1, userAgent ?? defaultUserAgent);
2784
2869
  }
2785
2870
  /**
2786
2871
  * X-Bogus 签名算法
2787
2872
  * @param url 需要签名的地址
2788
2873
  * @returns 对此地址签名后的URL查询参数
2789
2874
  */
2790
- static XB(url, userAgent) {
2791
- return new XBogus().getXBogus(url, userAgent ?? defaultUserAgent).xbogus;
2875
+ static XB(url$1, userAgent) {
2876
+ return new XBogus().getXBogus(url$1, userAgent ?? defaultUserAgent).xbogus;
2792
2877
  }
2793
2878
  /** 生成一个唯一的验证字符串 */
2794
2879
  static VerifyFpManager() {
@@ -3254,17 +3339,23 @@ const douyinApiUrls = new DouyinAPI();
3254
3339
  //#endregion
3255
3340
  //#region src/platform/douyin/getdata.ts
3256
3341
  /**
3342
+ * 抖音数据获取模块
3343
+ *
3344
+ * 注意:为避免循环依赖,此文件直接从具体模块导入,而不是从平台 index 文件导入
3345
+ * 循环依赖链:DataFetchers → getdata → platform/douyin → DataFetchers
3346
+ */
3347
+ /**
3257
3348
  * 获取签名参数
3258
3349
  * @param url - 需要签名的URL
3259
3350
  * @param signType - 签名算法类型
3260
3351
  * @param userAgent - 用户代理
3261
3352
  * @returns 签名后的参数字符串
3262
3353
  */
3263
- const getSignature = (url, signType = "a_bogus", userAgent) => {
3354
+ const getSignature = (url$1, signType = "a_bogus", userAgent) => {
3264
3355
  switch (signType) {
3265
- case "x_bogus": return douyinSign.XB(url, userAgent);
3356
+ case "x_bogus": return douyinSign.XB(url$1, userAgent);
3266
3357
  case "a_bogus":
3267
- default: return douyinSign.AB(url, userAgent);
3358
+ default: return douyinSign.AB(url$1, userAgent);
3268
3359
  }
3269
3360
  };
3270
3361
  /**
@@ -3286,9 +3377,9 @@ const getSignParamName = (signType = "a_bogus") => {
3286
3377
  * @param userAgent - 用户代理
3287
3378
  * @returns 带签名的完整URL
3288
3379
  */
3289
- const buildSignedUrl = (url, signType = "a_bogus", userAgent) => {
3290
- const signature = getSignature(url, signType, userAgent);
3291
- return `${url}&${getSignParamName(signType)}=${signature}`;
3380
+ const buildSignedUrl = (url$1, signType = "a_bogus", userAgent) => {
3381
+ const signature = getSignature(url$1, signType, userAgent);
3382
+ return `${url$1}&${getSignParamName(signType)}=${signature}`;
3292
3383
  };
3293
3384
  /**
3294
3385
  * 抖音数据获取函数
@@ -3317,10 +3408,10 @@ const DouyinData = async (data$1, cookie, requestConfig) => {
3317
3408
  case "视频作品数据":
3318
3409
  case "图集作品数据":
3319
3410
  case "合辑作品数据": {
3320
- const url = douyinApiUrls$1.视频或图集({ aweme_id: data$1.aweme_id });
3411
+ const url$1 = douyinApiUrls$1.视频或图集({ aweme_id: data$1.aweme_id });
3321
3412
  return await GlobalGetData$2(data$1.methodType, {
3322
3413
  ...baseRequestConfig,
3323
- url: buildSignedUrl(url, signType, userAgent)
3414
+ url: buildSignedUrl(url$1, signType, userAgent)
3324
3415
  });
3325
3416
  }
3326
3417
  case "评论数据": {
@@ -3332,7 +3423,7 @@ const DouyinData = async (data$1, cookie, requestConfig) => {
3332
3423
  return await fetchPaginatedData(data$1.methodType, urlGenerator, data$1, 3, baseRequestConfig, "x_bogus");
3333
3424
  }
3334
3425
  case "用户主页数据": {
3335
- const url = douyinApiUrls$1.用户主页信息({ sec_uid: data$1.sec_uid });
3426
+ const url$1 = douyinApiUrls$1.用户主页信息({ sec_uid: data$1.sec_uid });
3336
3427
  const customConfig = {
3337
3428
  ...baseRequestConfig,
3338
3429
  headers: {
@@ -3342,18 +3433,18 @@ const DouyinData = async (data$1, cookie, requestConfig) => {
3342
3433
  };
3343
3434
  return await GlobalGetData$2(data$1.methodType, {
3344
3435
  ...customConfig,
3345
- url: buildSignedUrl(url, signType, userAgent)
3436
+ url: buildSignedUrl(url$1, signType, userAgent)
3346
3437
  });
3347
3438
  }
3348
3439
  case "Emoji数据": {
3349
- const url = douyinApiUrls$1.表情();
3440
+ const url$1 = douyinApiUrls$1.表情();
3350
3441
  return await GlobalGetData$2(data$1.methodType, {
3351
3442
  ...baseRequestConfig,
3352
- url
3443
+ url: url$1
3353
3444
  });
3354
3445
  }
3355
3446
  case "用户主页视频列表数据": {
3356
- const url = douyinApiUrls$1.用户主页视频({ sec_uid: data$1.sec_uid });
3447
+ const url$1 = douyinApiUrls$1.用户主页视频({ sec_uid: data$1.sec_uid });
3357
3448
  const customConfig = {
3358
3449
  ...baseRequestConfig,
3359
3450
  headers: {
@@ -3363,11 +3454,11 @@ const DouyinData = async (data$1, cookie, requestConfig) => {
3363
3454
  };
3364
3455
  return await GlobalGetData$2(data$1.methodType, {
3365
3456
  ...customConfig,
3366
- url: buildSignedUrl(url, signType, userAgent)
3457
+ url: buildSignedUrl(url$1, signType, userAgent)
3367
3458
  });
3368
3459
  }
3369
3460
  case "热点词数据": {
3370
- const url = douyinApiUrls$1.热点词({
3461
+ const url$1 = douyinApiUrls$1.热点词({
3371
3462
  query: data$1.query,
3372
3463
  number: data$1.number ?? 10
3373
3464
  });
@@ -3380,7 +3471,7 @@ const DouyinData = async (data$1, cookie, requestConfig) => {
3380
3471
  };
3381
3472
  return await GlobalGetData$2(data$1.methodType, {
3382
3473
  ...customConfig,
3383
- url: buildSignedUrl(url, signType, userAgent)
3474
+ url: buildSignedUrl(url$1, signType, userAgent)
3384
3475
  });
3385
3476
  }
3386
3477
  case "搜索数据": {
@@ -3397,19 +3488,22 @@ const DouyinData = async (data$1, cookie, requestConfig) => {
3397
3488
  };
3398
3489
  while (fetchedSearchList.length < Number(data$1.number ?? 10)) {
3399
3490
  const requestCount = Math.min(Number(data$1.number ?? 50) - fetchedSearchList.length, maxPageSize);
3400
- const url = douyinApiUrls$1.搜索({
3491
+ const url$1 = douyinApiUrls$1.搜索({
3401
3492
  query: data$1.query,
3402
3493
  number: requestCount,
3403
3494
  search_id: search_id === "" ? void 0 : search_id
3404
3495
  });
3405
3496
  const raw = await GlobalGetData$2(data$1.methodType, {
3406
3497
  ...customConfig,
3407
- url: buildSignedUrl(url, "x_bogus", userAgent)
3498
+ url: buildSignedUrl(url$1, "x_bogus", userAgent)
3408
3499
  });
3409
3500
  const responses = filterSearchResponses(typeof raw === "string" ? parseDouyinMultiJson(raw) : [raw]);
3410
3501
  if (responses.length === 0) {
3411
3502
  logger.warn("抖音搜索返回无有效数据,疑似触发反爬\n你的抖音ck可能已经失效!\n请求类型:" + data$1.methodType);
3412
- return false;
3503
+ return {
3504
+ success: false,
3505
+ amagiError: "抖音搜索返回无有效数据,疑似触发反爬\n你的抖音ck可能已经失效!\n请求类型:" + data$1.methodType
3506
+ };
3413
3507
  }
3414
3508
  for (const resp of responses) {
3415
3509
  if (Array.isArray(resp.data) && resp.data.length > 0) fetchedSearchList.push(...resp.data);
@@ -3417,8 +3511,11 @@ const DouyinData = async (data$1, cookie, requestConfig) => {
3417
3511
  search_id = resp.log_pb?.impr_id ?? search_id;
3418
3512
  }
3419
3513
  if (fetchedSearchList.length === 0) {
3420
- logger.warn("抖音搜索返回数据长度为空,\n你的抖音ck疑似触发验证码!\n请求类型:" + data$1.methodType);
3421
- return false;
3514
+ logger.warn("抖音搜索API请求成功,但返回数据长度为0,\n此问题暂时无法处理,也可能被风控!\n请求类型:" + data$1.methodType);
3515
+ return {
3516
+ success: false,
3517
+ amagiError: "抖音搜索API请求成功,但返回数据长度为0,\n此问题暂时无法处理,也可能被风控!\n请求类型:" + data$1.methodType
3518
+ };
3422
3519
  }
3423
3520
  if (tmpresp && typeof tmpresp.has_more === "number" && tmpresp.has_more === 0) break;
3424
3521
  }
@@ -3428,77 +3525,42 @@ const DouyinData = async (data$1, cookie, requestConfig) => {
3428
3525
  };
3429
3526
  }
3430
3527
  case "动态表情数据": {
3431
- const url = douyinApiUrls$1.互动表情();
3528
+ const url$1 = douyinApiUrls$1.互动表情();
3432
3529
  return await GlobalGetData$2(data$1.methodType, {
3433
3530
  ...baseRequestConfig,
3434
- url: buildSignedUrl(url, signType, userAgent)
3531
+ url: buildSignedUrl(url$1, signType, userAgent)
3435
3532
  });
3436
3533
  }
3437
3534
  case "音乐数据": {
3438
- const url = douyinApiUrls$1.背景音乐({ music_id: data$1.music_id });
3535
+ const url$1 = douyinApiUrls$1.背景音乐({ music_id: data$1.music_id });
3439
3536
  return await GlobalGetData$2(data$1.methodType, {
3440
3537
  ...baseRequestConfig,
3441
- url: buildSignedUrl(url, signType, userAgent)
3538
+ url: buildSignedUrl(url$1, signType, userAgent)
3442
3539
  });
3443
3540
  }
3444
3541
  case "直播间信息数据": {
3445
- let url = douyinApiUrls$1.用户主页信息({ sec_uid: data$1.sec_uid });
3446
- const fetchUrl = buildSignedUrl(url, signType, userAgent);
3447
- const customConfig = {
3448
- ...baseRequestConfig,
3449
- headers: {
3450
- ...baseRequestConfig.headers,
3451
- ...(!requestConfig?.headers || !("Referer" in requestConfig.headers)) && { Referer: `https://www.douyin.com/user/${data$1.sec_uid}` }
3452
- }
3453
- };
3454
- const UserInfoData = await GlobalGetData$2(data$1.methodType, {
3455
- ...customConfig,
3456
- url: fetchUrl
3457
- });
3458
- if (!UserInfoData?.user?.live_status || UserInfoData.user.live_status !== 1) {
3459
- logger.error((UserInfoData?.user?.nickname ?? "用户") + "当前未在直播");
3460
- const Err = {
3461
- errorDescription: "检查失败!该用户当前未在直播! TypeError: Cannot read properties of undefined (reading 'live_status')",
3462
- requestType: data$1.methodType ?? "未知请求类型",
3463
- requestUrl: fetchUrl
3464
- };
3465
- return {
3466
- code: douoyinAPIErrorCode.NOT_LIVE,
3467
- data: UserInfoData,
3468
- amagiError: Err,
3469
- amagiMessage: Err.errorDescription
3470
- };
3471
- }
3472
- if (!UserInfoData.user.room_data) {
3473
- logger.error("未获取到直播间信息!");
3474
- return {
3475
- code: 500,
3476
- message: "未获取到直播间信息!",
3477
- data: null
3478
- };
3479
- }
3480
- const room_data = JSON.parse(UserInfoData.user.room_data);
3481
- url = douyinApiUrls$1.直播间信息({
3482
- room_id: UserInfoData.user.room_id_str,
3483
- web_rid: room_data.owner.web_rid
3542
+ let url$1 = douyinApiUrls$1.直播间信息({
3543
+ room_id: data$1.room_id,
3544
+ web_rid: data$1.web_rid
3484
3545
  });
3485
3546
  const liveCustomConfig = {
3486
3547
  ...baseRequestConfig,
3548
+ url: buildSignedUrl(url$1, signType, userAgent),
3487
3549
  headers: {
3488
3550
  ...baseRequestConfig.headers,
3489
- ...(!requestConfig?.headers || !("Referer" in requestConfig.headers)) && { Referer: `https://live.douyin.com/${room_data.owner.web_rid}` }
3551
+ ...(!requestConfig?.headers || !("Referer" in requestConfig.headers)) && { Referer: `https://live.douyin.com/${data$1.web_rid}` }
3490
3552
  }
3491
3553
  };
3492
3554
  return await GlobalGetData$2(data$1.methodType, {
3493
3555
  ...liveCustomConfig,
3494
- url: buildSignedUrl(url, signType, userAgent)
3556
+ url: buildSignedUrl(url$1, signType, userAgent)
3495
3557
  });
3496
3558
  }
3497
3559
  case "申请二维码数据": {
3498
- const url = douyinApiUrls$1.申请二维码({ verify_fp: data$1.verify_fp });
3560
+ const url$1 = douyinApiUrls$1.申请二维码({ verify_fp: data$1.verify_fp });
3499
3561
  return await GlobalGetData$2(data$1.methodType, {
3500
3562
  ...baseRequestConfig,
3501
- url: buildSignedUrl(url, signType, userAgent)
3563
+ url: buildSignedUrl(url$1, signType, userAgent)
3502
3564
  });
3503
3565
  }
3504
3566
  case "弹幕数据": {
@@ -3507,7 +3569,7 @@ const DouyinData = async (data$1, cookie, requestConfig) => {
3507
3569
  const endTime = data$1.end_time ?? data$1.duration;
3508
3570
  const totalDuration = endTime - startTime;
3509
3571
  if (totalDuration <= MAX_SEGMENT_DURATION) {
3510
- const url = douyinApiUrls$1.弹幕({
3572
+ const url$1 = douyinApiUrls$1.弹幕({
3511
3573
  aweme_id: data$1.aweme_id,
3512
3574
  start_time: startTime,
3513
3575
  end_time: endTime,
@@ -3515,7 +3577,7 @@ const DouyinData = async (data$1, cookie, requestConfig) => {
3515
3577
  });
3516
3578
  return await GlobalGetData$2(data$1.methodType, {
3517
3579
  ...baseRequestConfig,
3518
- url: buildSignedUrl(url, signType, userAgent)
3580
+ url: buildSignedUrl(url$1, signType, userAgent)
3519
3581
  });
3520
3582
  }
3521
3583
  const segments = [];
@@ -3530,7 +3592,7 @@ const DouyinData = async (data$1, cookie, requestConfig) => {
3530
3592
  }
3531
3593
  logger.debug(`弹幕数据需要分${segments.length}段获取,总时长:${totalDuration}ms`);
3532
3594
  const segmentPromises = segments.map(async (segment, index) => {
3533
- const url = douyinApiUrls$1.弹幕({
3595
+ const url$1 = douyinApiUrls$1.弹幕({
3534
3596
  aweme_id: data$1.aweme_id,
3535
3597
  start_time: segment.start,
3536
3598
  end_time: segment.end,
@@ -3539,7 +3601,7 @@ const DouyinData = async (data$1, cookie, requestConfig) => {
3539
3601
  try {
3540
3602
  const segmentData = await GlobalGetData$2(`${data$1.methodType}-段${index + 1}`, {
3541
3603
  ...baseRequestConfig,
3542
- url: buildSignedUrl(url, signType, userAgent)
3604
+ url: buildSignedUrl(url$1, signType, userAgent)
3543
3605
  });
3544
3606
  logger.debug(`弹幕第${index + 1}段获取成功 (${segment.start}ms-${segment.end}ms)`);
3545
3607
  return segmentData;
@@ -3580,9 +3642,18 @@ const DouyinData = async (data$1, cookie, requestConfig) => {
3580
3642
  logger.debug(`弹幕数据合并完成,共获取${mergedDanmakuList.length}条弹幕`);
3581
3643
  return finalDanmakuData;
3582
3644
  }
3583
- default:
3645
+ default: {
3646
+ const customUrl = data$1.custom_url;
3647
+ if (typeof customUrl === "string" && customUrl.length > 0) {
3648
+ const url$1 = buildSignedUrl(customUrl, signType, userAgent);
3649
+ return await GlobalGetData$2(data$1.methodType ?? "自定义请求", {
3650
+ ...baseRequestConfig,
3651
+ url: url$1
3652
+ });
3653
+ }
3584
3654
  logger.warn(`未知的抖音数据接口:「${logger.red(data$1.methodType)}」`);
3585
3655
  return null;
3656
+ }
3586
3657
  }
3587
3658
  };
3588
3659
  /**
@@ -3602,14 +3673,14 @@ const fetchPaginatedData = async (type, apiUrlGenerator, params, maxPageSize, re
3602
3673
  const userAgent = requestConfig.headers?.["User-Agent"];
3603
3674
  while (fetchedData.length < Number(params.number ?? maxPageSize)) {
3604
3675
  const requestCount = Math.min(Number(params.number ?? maxPageSize) - fetchedData.length, maxPageSize);
3605
- const url = apiUrlGenerator({
3676
+ const url$1 = apiUrlGenerator({
3606
3677
  ...params,
3607
3678
  number: requestCount,
3608
3679
  cursor
3609
3680
  });
3610
3681
  const response = await GlobalGetData$2(type, {
3611
3682
  ...requestConfig,
3612
- url: buildSignedUrl(url, signType, userAgent)
3683
+ url: buildSignedUrl(url$1, signType, userAgent)
3613
3684
  });
3614
3685
  fetchedData.push(...response.comments ?? response.data ?? []);
3615
3686
  tmpresp = response;
@@ -3774,6 +3845,12 @@ const kuaishouApiUrls = new API();
3774
3845
  //#endregion
3775
3846
  //#region src/platform/kuaishou/getdata.ts
3776
3847
  /**
3848
+ * 快手数据获取模块
3849
+ *
3850
+ * 注意:为避免循环依赖,此文件直接从具体模块导入,而不是从平台 index 文件导入
3851
+ * 循环依赖链:DataFetchers → getdata → platform/kuaishou → DataFetchers
3852
+ */
3853
+ /**
3777
3854
  * 快手数据获取函数
3778
3855
  * @param data - 请求数据参数
3779
3856
  * @param cookie - 用户Cookie
@@ -4051,7 +4128,7 @@ async function getDouyinData(methodType, optionsOrCookie, cookieOrOptions, reque
4051
4128
  cookie = cookieOrOptions;
4052
4129
  config = requestConfig;
4053
4130
  }
4054
- const { typeMode: _,...validationOptions } = options ?? {};
4131
+ const { typeMode: _, ...validationOptions } = options ?? {};
4055
4132
  const rawData = await DouyinData({ ...validateDouyinParams(methodType, validationOptions) }, cookie, config);
4056
4133
  if (rawData.data === "" || rawData.status_code !== 0) return createErrorResponse(rawData.amagiError, rawData.status_msg ?? "抖音数据获取失败");
4057
4134
  return createSuccessResponse(rawData, "获取成功", 200);
@@ -4074,7 +4151,7 @@ async function getBilibiliData(methodType, optionsOrCookie, cookieOrOptions, req
4074
4151
  options = optionsOrCookie;
4075
4152
  cookie = cookieOrOptions;
4076
4153
  }
4077
- const { typeMode: _,...validationOptions } = options ?? {};
4154
+ const { typeMode: _, ...validationOptions } = options ?? {};
4078
4155
  const rawData = await fetchBilibili({ ...validateBilibiliParams(methodType, validationOptions) }, cookie);
4079
4156
  if (rawData.code !== 0) return createErrorResponse(rawData.amagiError, "B站数据获取失败");
4080
4157
  return createSuccessResponse(rawData, "获取成功", 200);
@@ -4097,7 +4174,7 @@ async function getKuaishouData(methodType, optionsOrCookie, cookieOrOptions, req
4097
4174
  options = optionsOrCookie;
4098
4175
  cookie = cookieOrOptions;
4099
4176
  }
4100
- const { typeMode: _,...validationOptions } = options ?? {};
4177
+ const { typeMode: _, ...validationOptions } = options ?? {};
4101
4178
  const rawData = await KuaishouData({ ...validateKuaishouParams(methodType, validationOptions) }, cookie);
4102
4179
  if (rawData.code && Object.values(kuaishouAPIErrorCode).includes(rawData.code)) return createErrorResponse(rawData.amagiError, "快手数据获取失败");
4103
4180
  return createSuccessResponse(rawData, "获取成功", 200);
@@ -4120,7 +4197,7 @@ async function getXiaohongshuData(methodType, optionsOrCookie, cookieOrOptions,
4120
4197
  options = optionsOrCookie;
4121
4198
  cookie = cookieOrOptions;
4122
4199
  }
4123
- const { typeMode: _,...validationOptions } = options ?? {};
4200
+ const { typeMode: _, ...validationOptions } = options ?? {};
4124
4201
  const rawData = await XiaohongshuData({ ...validateXiaohongshuParams(methodType, validationOptions) }, cookie);
4125
4202
  if (rawData.code && Object.values(xiaohongshuAPIErrorCode).includes(rawData.code)) return createErrorResponse(rawData.amagiError, "小红书数据获取失败");
4126
4203
  return createSuccessResponse(rawData, "获取成功", 200);
@@ -4178,7 +4255,10 @@ const douyin = {
4178
4255
  getSuggestWords: createDouyinApiMethod("热点词数据"),
4179
4256
  search: createDouyinApiMethod("搜索数据"),
4180
4257
  getLiveRoomInfo: createDouyinApiMethod("直播间信息数据"),
4181
- getDanmaku: createDouyinApiMethod("弹幕数据")
4258
+ getDanmaku: createDouyinApiMethod("弹幕数据"),
4259
+ invoke: async (methodType, options, cookie, requestConfig) => {
4260
+ return await getDouyinData(methodType, options, cookie, requestConfig);
4261
+ }
4182
4262
  };
4183
4263
  /**
4184
4264
  * 创建绑定了cookie的抖音API对象
@@ -4200,9 +4280,12 @@ const createBoundDouyinApi = (cookie, requestConfig) => {
4200
4280
  getUserVideos: createBoundDouyinApiMethod("用户主页视频列表数据", cookie, requestConfig),
4201
4281
  getMusicInfo: createBoundDouyinApiMethod("音乐数据", cookie, requestConfig),
4202
4282
  getSuggestWords: createBoundDouyinApiMethod("热点词数据", cookie, requestConfig),
4203
- search: createBoundDouyinApiMethod("搜索数据", cookie, requestConfig),
4283
+ getSearchData: createBoundDouyinApiMethod("搜索数据", cookie, requestConfig),
4204
4284
  getLiveRoomInfo: createBoundDouyinApiMethod("直播间信息数据", cookie, requestConfig),
4205
- getDanmaku: createBoundDouyinApiMethod("弹幕数据", cookie, requestConfig)
4285
+ getDanmaku: createBoundDouyinApiMethod("弹幕数据", cookie, requestConfig),
4286
+ invoke: async (methodType, options) => {
4287
+ return await getDouyinData(methodType, options, cookie, requestConfig);
4288
+ }
4206
4289
  };
4207
4290
  };
4208
4291
 
@@ -4240,22 +4323,8 @@ const createDouyinRouteHandler = (dataFetcher, methodType, cookie, requestConfig
4240
4323
  * @returns Express路由器
4241
4324
  */
4242
4325
  const createDouyinRoutes = (cookie, requestConfig = getDouyinDefaultConfig(cookie)) => {
4243
- const router = (0, express.Router)();
4244
- router.get("/fetch_one_work", createDouyinValidationMiddleware("聚合解析"), createDouyinRouteHandler(getDouyinData, "聚合解析", cookie, requestConfig));
4245
- router.get("/fetch_one_work", createDouyinValidationMiddleware("视频作品数据"), createDouyinRouteHandler(getDouyinData, "视频作品数据", cookie, requestConfig));
4246
- router.get("/fetch_one_work", createDouyinValidationMiddleware("图集作品数据"), createDouyinRouteHandler(getDouyinData, "图集作品数据", cookie, requestConfig));
4247
- router.get("/fetch_one_work", createDouyinValidationMiddleware("合辑作品数据"), createDouyinRouteHandler(getDouyinData, "合辑作品数据", cookie, requestConfig));
4248
- router.get("/fetch_work_comments", createDouyinValidationMiddleware("评论数据"), createDouyinRouteHandler(getDouyinData, "评论数据", cookie, requestConfig));
4249
- router.get("/fetch_user_info", createDouyinValidationMiddleware("用户主页数据"), createDouyinRouteHandler(getDouyinData, "用户主页数据", cookie, requestConfig));
4250
- router.get("/fetch_user_post_videos", createDouyinValidationMiddleware("用户主页视频列表数据"), createDouyinRouteHandler(getDouyinData, "用户主页视频列表数据", cookie, requestConfig));
4251
- router.get("/fetch_search_info", createDouyinValidationMiddleware("搜索数据"), createDouyinRouteHandler(getDouyinData, "搜索数据", cookie, requestConfig));
4252
- router.get("/fetch_suggest_words", createDouyinValidationMiddleware("热点词数据"), createDouyinRouteHandler(getDouyinData, "热点词数据", cookie, requestConfig));
4253
- router.get("/fetch_music_work", createDouyinValidationMiddleware("音乐数据"), createDouyinRouteHandler(getDouyinData, "音乐数据", cookie, requestConfig));
4254
- router.get("/fetch_emoji_list", createDouyinValidationMiddleware("Emoji数据"), createDouyinRouteHandler(getDouyinData, "Emoji数据", cookie, requestConfig));
4255
- router.get("/fetch_emoji_pro_list", createDouyinValidationMiddleware("动态表情数据"), createDouyinRouteHandler(getDouyinData, "动态表情数据", cookie, requestConfig));
4256
- router.get("/fetch_user_live_videos", createDouyinValidationMiddleware("直播间信息数据"), createDouyinRouteHandler(getDouyinData, "直播间信息数据", cookie, requestConfig));
4257
- router.get("/fetch_video_comment_replies", createDouyinValidationMiddleware("指定评论回复数据"), createDouyinRouteHandler(getDouyinData, "指定评论回复数据", cookie, requestConfig));
4258
- router.get("/fetch_work_danmaku", createDouyinValidationMiddleware("弹幕数据"), createDouyinRouteHandler(getDouyinData, "弹幕数据", cookie, requestConfig));
4326
+ const router = express.default.Router();
4327
+ for (const [method, path$1] of Object.entries(DouyinMethodRoutes)) router.get(path$1, createDouyinValidationMiddleware(method), createDouyinRouteHandler(getDouyinData, method, cookie, requestConfig));
4259
4328
  return router;
4260
4329
  };
4261
4330
 
@@ -4347,10 +4416,8 @@ const createKuaishouRouteHandler = (dataFetcher, methodType, cookie, requestConf
4347
4416
  * @returns Express路由器
4348
4417
  */
4349
4418
  const createKuaishouRoutes = (cookie, requestConfig = getKuaishouDefaultConfig(cookie)) => {
4350
- const router = (0, express.Router)();
4351
- router.get("/fetch_one_work", createKuaishouValidationMiddleware("单个视频作品数据"), createKuaishouRouteHandler(getKuaishouData, "单个视频作品数据", cookie, requestConfig));
4352
- router.get("/fetch_work_comments", createKuaishouValidationMiddleware("评论数据"), createKuaishouRouteHandler(getKuaishouData, "评论数据", cookie, requestConfig));
4353
- router.get("/fetch_emoji_list", createKuaishouValidationMiddleware("Emoji数据"), createKuaishouRouteHandler(getKuaishouData, "Emoji数据", cookie, requestConfig));
4419
+ const router = express.default.Router();
4420
+ for (const [method, path$1] of Object.entries(KuaishouMethodRoutes)) router.get(path$1, createKuaishouValidationMiddleware(method), createKuaishouRouteHandler(getKuaishouData, method, cookie, requestConfig));
4354
4421
  return router;
4355
4422
  };
4356
4423
 
@@ -4454,14 +4521,8 @@ const createXiaohongshuRouteHandler = (dataFetcher, methodType, cookie, requestC
4454
4521
  * @returns Express路由器
4455
4522
  */
4456
4523
  const createXiaohongshuRoutes = (cookie, requestConfig = getXiaohongshuDefaultConfig(cookie)) => {
4457
- const router = (0, express.Router)();
4458
- router.get("/fetch_home_feed", createXiaohongshuValidationMiddleware("首页推荐数据"), createXiaohongshuRouteHandler(getXiaohongshuData, "首页推荐数据", cookie, requestConfig));
4459
- router.get("/fetch_one_note", createXiaohongshuValidationMiddleware("单个笔记数据"), createXiaohongshuRouteHandler(getXiaohongshuData, "单个笔记数据", cookie, requestConfig));
4460
- router.get("/fetch_note_comments", createXiaohongshuValidationMiddleware("评论数据"), createXiaohongshuRouteHandler(getXiaohongshuData, "评论数据", cookie, requestConfig));
4461
- router.get("/fetch_user_profile", createXiaohongshuValidationMiddleware("用户数据"), createXiaohongshuRouteHandler(getXiaohongshuData, "用户数据", cookie, requestConfig));
4462
- router.get("/fetch_user_notes", createXiaohongshuValidationMiddleware("用户笔记数据"), createXiaohongshuRouteHandler(getXiaohongshuData, "用户笔记数据", cookie, requestConfig));
4463
- router.get("/fetch_emoji_list", createXiaohongshuValidationMiddleware("表情列表"), createXiaohongshuRouteHandler(getXiaohongshuData, "表情列表", cookie, requestConfig));
4464
- router.get("/fetch_search_notes", createXiaohongshuValidationMiddleware("搜索笔记"), createXiaohongshuRouteHandler(getXiaohongshuData, "搜索笔记", cookie, requestConfig));
4524
+ const router = express.default.Router();
4525
+ for (const [method, path$1] of Object.entries(XiaohongshuMethodRoutes)) router.get(path$1, createXiaohongshuValidationMiddleware(method), createXiaohongshuRouteHandler(getXiaohongshuData, method, cookie, requestConfig));
4465
4526
  return router;
4466
4527
  };
4467
4528
 
@@ -4572,6 +4633,60 @@ const createAmagiClient = (options) => {
4572
4633
  };
4573
4634
  };
4574
4635
 
4636
+ //#endregion
4637
+ //#region src/types/BilibiliAPIParams.ts
4638
+ /**
4639
+ * 评论区类型枚举
4640
+ * 对应 CommentParams.type 与 CommentReplyParams.type
4641
+ */
4642
+ let CommentType = /* @__PURE__ */ function(CommentType$1) {
4643
+ /** 视频稿件:oid 为稿件 avid */
4644
+ CommentType$1[CommentType$1["Video"] = 1] = "Video";
4645
+ /** 话题:oid 为话题 id */
4646
+ CommentType$1[CommentType$1["Topic"] = 2] = "Topic";
4647
+ /** 活动:oid 为活动 id */
4648
+ CommentType$1[CommentType$1["Activity"] = 4] = "Activity";
4649
+ /** 小视频:oid 为小视频 id */
4650
+ CommentType$1[CommentType$1["SmallVideo"] = 5] = "SmallVideo";
4651
+ /** 小黑屋封禁信息:oid 为封禁公示 id */
4652
+ CommentType$1[CommentType$1["BlockInfo"] = 6] = "BlockInfo";
4653
+ /** 公告信息:oid 为公告 id */
4654
+ CommentType$1[CommentType$1["Announcement"] = 7] = "Announcement";
4655
+ /** 直播活动:oid 为直播间 id */
4656
+ CommentType$1[CommentType$1["LiveActivity"] = 8] = "LiveActivity";
4657
+ /** 活动稿件:oid 含义未知 */
4658
+ CommentType$1[CommentType$1["ActivityVideo"] = 9] = "ActivityVideo";
4659
+ /** 直播公告:oid 含义未知 */
4660
+ CommentType$1[CommentType$1["LiveAnnouncement"] = 10] = "LiveAnnouncement";
4661
+ /** 相簿(图片动态):oid 为相簿 id */
4662
+ CommentType$1[CommentType$1["Album"] = 11] = "Album";
4663
+ /** 专栏:oid 为专栏 cvid */
4664
+ CommentType$1[CommentType$1["Article"] = 12] = "Article";
4665
+ /** 票务:oid 含义未知 */
4666
+ CommentType$1[CommentType$1["Ticket"] = 13] = "Ticket";
4667
+ /** 音频:oid 为音频 auid */
4668
+ CommentType$1[CommentType$1["Audio"] = 14] = "Audio";
4669
+ /** 风纪委员会:oid 为众裁项目 id */
4670
+ CommentType$1[CommentType$1["Jury"] = 15] = "Jury";
4671
+ /** 点评:oid 含义未知 */
4672
+ CommentType$1[CommentType$1["Review"] = 16] = "Review";
4673
+ /** 动态(纯文字动态&分享):oid 为动态 id */
4674
+ CommentType$1[CommentType$1["Dynamic"] = 17] = "Dynamic";
4675
+ /** 播单:oid 含义未知 */
4676
+ CommentType$1[CommentType$1["Playlist"] = 18] = "Playlist";
4677
+ /** 音乐播单:oid 含义未知 */
4678
+ CommentType$1[CommentType$1["MusicPlaylist"] = 19] = "MusicPlaylist";
4679
+ /** 漫画:oid 含义未知 */
4680
+ CommentType$1[CommentType$1["Comic1"] = 20] = "Comic1";
4681
+ /** 漫画:oid 含义未知 */
4682
+ CommentType$1[CommentType$1["Comic2"] = 21] = "Comic2";
4683
+ /** 漫画:oid 为漫画 mcid */
4684
+ CommentType$1[CommentType$1["Comic"] = 22] = "Comic";
4685
+ /** 课程:oid 为课程 epid */
4686
+ CommentType$1[CommentType$1["Course"] = 33] = "Course";
4687
+ return CommentType$1;
4688
+ }({});
4689
+
4575
4690
  //#endregion
4576
4691
  //#region src/types/ReturnDataType/Bilibili/Dynamic/index.ts
4577
4692
  /**
@@ -4696,22 +4811,27 @@ exports.BilibiliBangumiStreamParamsSchema = BilibiliBangumiStreamParamsSchema;
4696
4811
  exports.BilibiliBv2AvParamsSchema = BilibiliBv2AvParamsSchema;
4697
4812
  exports.BilibiliColumnInfoParamsSchema = BilibiliColumnInfoParamsSchema;
4698
4813
  exports.BilibiliCommentParamsSchema = BilibiliCommentParamsSchema;
4814
+ exports.BilibiliCommentReplyParamsSchema = BilibiliCommentReplyParamsSchema;
4699
4815
  exports.BilibiliDynamicParamsSchema = BilibiliDynamicParamsSchema;
4700
4816
  exports.BilibiliEmojiParamsSchema = BilibiliEmojiParamsSchema;
4701
4817
  exports.BilibiliLiveParamsSchema = BilibiliLiveParamsSchema;
4702
4818
  exports.BilibiliLoginParamsSchema = BilibiliLoginParamsSchema;
4819
+ exports.BilibiliMethodRoutes = BilibiliMethodRoutes;
4703
4820
  exports.BilibiliQrcodeParamsSchema = BilibiliQrcodeParamsSchema;
4704
4821
  exports.BilibiliQrcodeStatusParamsSchema = BilibiliQrcodeStatusParamsSchema;
4705
4822
  exports.BilibiliUserParamsSchema = BilibiliUserParamsSchema;
4706
4823
  exports.BilibiliValidationSchemas = BilibiliValidationSchemas;
4707
4824
  exports.BilibiliVideoDownloadParamsSchema = BilibiliVideoDownloadParamsSchema;
4708
4825
  exports.BilibiliVideoParamsSchema = BilibiliVideoParamsSchema;
4826
+ exports.CommentType = CommentType;
4709
4827
  exports.CreateApp = CreateApp;
4710
4828
  exports.DouyinCommentParamsSchema = DouyinCommentParamsSchema;
4711
4829
  exports.DouyinCommentReplyParamsSchema = DouyinCommentReplyParamsSchema;
4712
4830
  exports.DouyinDanmakuParamsSchema = DouyinDanmakuParamsSchema;
4713
4831
  exports.DouyinEmojiListParamsSchema = DouyinEmojiListParamsSchema;
4714
4832
  exports.DouyinEmojiProParamsSchema = DouyinEmojiProParamsSchema;
4833
+ exports.DouyinLiveRoomParamsSchema = DouyinLiveRoomParamsSchema;
4834
+ exports.DouyinMethodRoutes = DouyinMethodRoutes;
4715
4835
  exports.DouyinMusicParamsSchema = DouyinMusicParamsSchema;
4716
4836
  exports.DouyinQrcodeParamsSchema = DouyinQrcodeParamsSchema;
4717
4837
  exports.DouyinSearchParamsSchema = DouyinSearchParamsSchema;
@@ -4721,10 +4841,12 @@ exports.DouyinWorkParamsSchema = DouyinWorkParamsSchema;
4721
4841
  exports.DynamicType = DynamicType;
4722
4842
  exports.KuaishouCommentParamsSchema = KuaishouCommentParamsSchema;
4723
4843
  exports.KuaishouEmojiParamsSchema = KuaishouEmojiParamsSchema;
4844
+ exports.KuaishouMethodRoutes = KuaishouMethodRoutes;
4724
4845
  exports.KuaishouValidationSchemas = KuaishouValidationSchemas;
4725
4846
  exports.KuaishouVideoParamsSchema = KuaishouVideoParamsSchema;
4726
4847
  exports.MajorType = MajorType;
4727
4848
  exports.ValidationError = ValidationError;
4849
+ exports.XiaohongshuMethodRoutes = XiaohongshuMethodRoutes;
4728
4850
  exports.XiaohongshuValidationSchemas = XiaohongshuValidationSchemas;
4729
4851
  exports.amagi = amagi;
4730
4852
  exports.amagiClient = amagiClient;