@ikenxuan/amagi 5.8.0 → 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,
@@ -873,9 +871,9 @@ const getWbiKeys = async (cookie) => {
873
871
  */
874
872
  const wbi_sign = async (BASEURL, cookie) => {
875
873
  const web_keys = await getWbiKeys(cookie);
876
- const url = new URL(BASEURL);
874
+ const url$1 = new URL(BASEURL);
877
875
  const params = {};
878
- for (const [key, value] of url.searchParams.entries()) params[key] = value;
876
+ for (const [key, value] of url$1.searchParams.entries()) params[key] = value;
879
877
  return encWbi(params, web_keys.img_key, web_keys.sub_key);
880
878
  };
881
879
 
@@ -952,7 +950,7 @@ const handleError = (error, requestPath) => {
952
950
  platform: error.platform,
953
951
  requestPath
954
952
  };
955
- 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);
956
954
  return {
957
955
  code: 500,
958
956
  message: error instanceof Error ? error.message : "未知错误",
@@ -964,8 +962,8 @@ const handleError = (error, requestPath) => {
964
962
  //#endregion
965
963
  //#region src/validation/utils.ts
966
964
  function smartNumber(errorMessage, minValue = 1, isInteger = false) {
967
- if (isInteger) return zod.z.coerce.number({ error: errorMessage }).int({ error: `${errorMessage.replace("不能为空", "")}必须是整数,不能包含小数` }).min(minValue, { error: `${errorMessage.replace("不能为空", "")}必须大于等于${minValue}` });
968
- 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}` });
969
967
  }
970
968
  /**
971
969
  * 智能正整数转换器 - 专门用于正整数类型的转换
@@ -994,18 +992,18 @@ const extractCreatorInfoFromHtml = (html) => {
994
992
 
995
993
  //#endregion
996
994
  //#region src/validation/bilibili.ts
997
- const BilibiliVideoParamsSchema = zod.z.object({
998
- methodType: zod.z.literal("单个视频作品数据", { error: "方法类型必须是\"单个视频作品数据\"" }),
999
- 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不能为空" })
1000
998
  });
1001
- const BilibiliVideoDownloadParamsSchema = zod.z.object({
1002
- methodType: zod.z.literal("单个视频下载信息数据", { error: "方法类型必须是\"单个视频下载信息数据\"" }),
999
+ const BilibiliVideoDownloadParamsSchema = zod.default.object({
1000
+ methodType: zod.default.literal("单个视频下载信息数据", { error: "方法类型必须是\"单个视频下载信息数据\"" }),
1003
1001
  avid: smartNumber("AVID不能为空", 1, true),
1004
1002
  cid: smartNumber("CID不能为空", 1, true)
1005
1003
  });
1006
- const BilibiliCommentParamsSchema = zod.z.object({
1007
- methodType: zod.z.literal("评论数据", { error: "方法类型必须是\"评论数据\"" }),
1008
- 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不能为空" }),
1009
1007
  type: smartNumber("评论类型不能为空", 1, true).refine((val) => [
1010
1008
  1,
1011
1009
  2,
@@ -1030,12 +1028,12 @@ const BilibiliCommentParamsSchema = zod.z.object({
1030
1028
  22,
1031
1029
  33
1032
1030
  ].includes(val), { error: "无效的评论区类型" }),
1033
- number: zod.z.coerce.number({ error: "评论数量必须是数字" }).int({ error: "评论数量必须是整数" }).positive({ error: "评论数量必须是正数" }).default(20).optional(),
1034
- pn: zod.z.coerce.number({ error: "页码必须是数字" }).int({ error: "页码必须是整数" }).positive({ error: "页码必须是正数" }).default(1).optional()
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()
1035
1033
  });
1036
- const BilibiliCommentReplyParamsSchema = zod.z.object({
1037
- methodType: zod.z.literal("指定评论的回复", { error: "方法类型必须是\"指定评论的回复\"" }),
1038
- oid: zod.z.string({ error: "OID必须是字符串" }).min(1, { error: "OID不能为空" }),
1034
+ const BilibiliCommentReplyParamsSchema = zod.default.object({
1035
+ methodType: zod.default.literal("指定评论的回复", { error: "方法类型必须是\"指定评论的回复\"" }),
1036
+ oid: zod.default.string({ error: "OID必须是字符串" }).min(1, { error: "OID不能为空" }),
1039
1037
  type: smartNumber("评论类型不能为空", 1, true).refine((val) => [
1040
1038
  1,
1041
1039
  2,
@@ -1060,69 +1058,69 @@ const BilibiliCommentReplyParamsSchema = zod.z.object({
1060
1058
  22,
1061
1059
  33
1062
1060
  ].includes(val), { error: "无效的评论区类型" }),
1063
- root: zod.z.string({ error: "根评论ID必须是字符串" }).min(1, { error: "根评论ID不能为空" }),
1064
- number: zod.z.coerce.number({ error: "评论数量必须是数字" }).int({ error: "评论数量必须是整数" }).positive({ error: "评论数量必须是正数" }).default(20).optional(),
1065
- 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()
1066
1064
  });
1067
- const BilibiliUserParamsSchema = zod.z.object({
1068
- methodType: zod.z.enum([
1065
+ const BilibiliUserParamsSchema = zod.default.object({
1066
+ methodType: zod.default.enum([
1069
1067
  "用户主页数据",
1070
1068
  "用户主页动态列表数据",
1071
1069
  "获取UP主总播放量"
1072
1070
  ], { error: "方法类型必须是指定的枚举值之一" }),
1073
1071
  host_mid: smartNumber("UP主UID不能为空", 1, true)
1074
1072
  });
1075
- const BilibiliEmojiParamsSchema = zod.z.object({ methodType: zod.z.literal("Emoji数据", { error: "方法类型必须是\"Emoji数据\"" }) });
1076
- const BilibiliBangumiInfoParamsSchema = zod.z.object({
1077
- methodType: zod.z.literal("番剧基本信息数据", { error: "方法类型必须是\"番剧基本信息数据\"" }),
1078
- ep_id: zod.z.string({ error: "番剧EP ID必须是字符串" }).min(1, { error: "番剧EP ID不能为空" }).optional(),
1079
- 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()
1080
1078
  }).refine((data$1) => data$1.ep_id ?? data$1.season_id, {
1081
1079
  error: "ep_id 和 season_id 至少需要提供一个",
1082
1080
  path: ["ep_id"]
1083
1081
  });
1084
- const BilibiliBangumiStreamParamsSchema = zod.z.object({
1085
- methodType: zod.z.literal("番剧下载信息数据", { error: "方法类型必须是\"番剧下载信息数据\"" }),
1082
+ const BilibiliBangumiStreamParamsSchema = zod.default.object({
1083
+ methodType: zod.default.literal("番剧下载信息数据", { error: "方法类型必须是\"番剧下载信息数据\"" }),
1086
1084
  cid: smartNumber("CID不能为空", 1, true),
1087
- 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不能为空" })
1088
1086
  });
1089
- const BilibiliDynamicParamsSchema = zod.z.object({
1090
- methodType: zod.z.enum(["动态详情数据", "动态卡片数据"], { error: "方法类型必须是\"动态详情数据\"或\"动态卡片数据\"" }),
1091
- 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不能为空" })
1092
1090
  });
1093
- const BilibiliLiveParamsSchema = zod.z.object({
1094
- methodType: zod.z.enum(["直播间信息", "直播间初始化信息"], { error: "方法类型必须是\"直播间信息\"或\"直播间初始化信息\"" }),
1095
- 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不能为空" })
1096
1094
  });
1097
- const BilibiliLoginParamsSchema = zod.z.object({ methodType: zod.z.literal("登录基本信息", { error: "方法类型必须是\"登录基本信息\"" }) });
1098
- const BilibiliQrcodeParamsSchema = zod.z.object({ methodType: zod.z.literal("申请二维码", { error: "方法类型必须是\"申请二维码\"" }) });
1099
- const BilibiliQrcodeStatusParamsSchema = zod.z.object({
1100
- methodType: zod.z.literal("二维码状态", { error: "方法类型必须是\"二维码状态\"" }),
1101
- 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不能为空" })
1102
1100
  });
1103
- const BilibiliAv2BvParamsSchema = zod.z.object({
1104
- methodType: zod.z.literal("AV转BV", { error: "方法类型必须是\"AV转BV\"" }),
1105
- 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必须是正数" })
1106
1104
  });
1107
- const BilibiliBv2AvParamsSchema = zod.z.object({
1108
- methodType: zod.z.literal("BV转AV", { error: "方法类型必须是\"BV转AV\"" }),
1109
- 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不能为空" })
1110
1108
  });
1111
- const BilibiliArticleParamsSchema = zod.z.object({
1112
- methodType: zod.z.literal("专栏正文内容", { error: "方法类型必须是\"专栏正文内容\"" }),
1113
- 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不能为空" })
1114
1112
  });
1115
- const BilibiliArticleCardParamsSchema = zod.z.object({
1116
- methodType: zod.z.literal("专栏显示卡片信息", { error: "方法类型必须是\"专栏显示卡片信息\"" }),
1117
- 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 列表不能为空" })])
1118
1116
  });
1119
- const BilibiliArticleInfoParamsSchema = zod.z.object({
1120
- methodType: zod.z.literal("专栏文章基本信息", { error: "方法类型必须是\"专栏文章基本信息\"" }),
1121
- 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不能为空" })
1122
1120
  });
1123
- const BilibiliColumnInfoParamsSchema = zod.z.object({
1124
- methodType: zod.z.literal("文集基本信息", { error: "方法类型必须是\"文集基本信息\"" }),
1125
- 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不能为空" })
1126
1124
  });
1127
1125
  const BilibiliValidationSchemas = {
1128
1126
  单个视频作品数据: BilibiliVideoParamsSchema,
@@ -1149,62 +1147,87 @@ const BilibiliValidationSchemas = {
1149
1147
  专栏文章基本信息: BilibiliArticleInfoParamsSchema,
1150
1148
  文集基本信息: BilibiliColumnInfoParamsSchema
1151
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
+ };
1152
1175
 
1153
1176
  //#endregion
1154
1177
  //#region src/validation/douyin.ts
1155
- const DouyinWorkParamsSchema = zod.z.object({
1156
- methodType: zod.z.enum([
1157
- "文字作品数据",
1178
+ const DouyinWorkParamsSchema = zod.default.object({
1179
+ methodType: zod.default.enum([
1158
1180
  "视频作品数据",
1159
1181
  "图集作品数据",
1160
1182
  "合辑作品数据",
1161
1183
  "聚合解析"
1162
1184
  ], { error: "方法类型必须是指定的枚举值之一" }),
1163
- aweme_id: zod.z.string({ error: "视频ID必须是字符串" }).min(1, { error: "视频ID不能为空" })
1185
+ aweme_id: zod.default.string({ error: "视频ID必须是字符串" }).min(1, { error: "视频ID不能为空" })
1164
1186
  });
1165
- const DouyinCommentParamsSchema = zod.z.object({
1166
- methodType: zod.z.literal("评论数据", { error: "方法类型必须是\"评论数据\"" }),
1167
- 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不能为空" }),
1168
1190
  number: smartPositiveInteger("评论数量必须是正整数").optional().default(50),
1169
- 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()
1170
1192
  });
1171
- const DouyinSearchParamsSchema = zod.z.object({
1172
- methodType: zod.z.enum(["热点词数据", "搜索数据"], { error: "方法类型必须是\"热点词数据\"或\"搜索数据\"" }),
1173
- 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: "搜索词不能为空" }),
1174
1196
  number: smartPositiveInteger("搜索数量必须是正整数").optional().default(10),
1175
- search_id: zod.z.string({ error: "搜索ID必须是字符串" }).optional()
1197
+ search_id: zod.default.string({ error: "搜索ID必须是字符串" }).optional()
1176
1198
  });
1177
- const DouyinCommentReplyParamsSchema = zod.z.object({
1178
- methodType: zod.z.literal("指定评论回复数据", { error: "方法类型必须是\"指定评论回复数据\"" }),
1179
- aweme_id: zod.z.string({ error: "视频ID必须是字符串" }).min(1, { error: "视频ID不能为空" }),
1180
- 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不能为空" }),
1181
1203
  number: smartPositiveInteger("评论数量必须是正整数").optional().default(5),
1182
- 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()
1183
1205
  });
1184
- const DouyinUserParamsSchema = zod.z.object({
1185
- methodType: zod.z.enum([
1186
- "用户主页数据",
1187
- "用户主页视频列表数据",
1188
- "直播间信息数据"
1189
- ], { error: "方法类型必须是指定的枚举值之一" }),
1190
- 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不能为空" })
1191
1209
  });
1192
- const DouyinMusicParamsSchema = zod.z.object({
1193
- methodType: zod.z.literal("音乐数据", { error: "方法类型必须是\"音乐数据\"" }),
1194
- music_id: zod.z.string({ error: "音乐ID必须是字符串" }).min(1, { error: "音乐ID不能为空" })
1210
+ const DouyinMusicParamsSchema = zod.default.object({
1211
+ methodType: zod.default.literal("音乐数据", { error: "方法类型必须是\"音乐数据\"" }),
1212
+ music_id: zod.default.string({ error: "音乐ID必须是字符串" }).min(1, { error: "音乐ID不能为空" })
1195
1213
  });
1196
- const DouyinQrcodeParamsSchema = zod.z.object({
1197
- methodType: zod.z.literal("申请二维码数据", { error: "方法类型必须是\"申请二维码数据\"" }),
1198
- verify_fp: zod.z.string({ error: "fp指纹必须是字符串" }).min(1, { error: "fp指纹不能为空" })
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不能为空" })
1199
1218
  });
1200
- const DouyinEmojiListParamsSchema = zod.z.object({ methodType: zod.z.literal("Emoji数据", { error: "方法类型必须是\"Emoji数据\"" }) });
1201
- const DouyinEmojiProParamsSchema = zod.z.object({ methodType: zod.z.literal("动态表情数据", { error: "方法类型必须是\"动态表情数据\"" }) });
1202
- const DouyinDanmakuParamsSchema = zod.z.object({
1203
- methodType: zod.z.literal("弹幕数据", { error: "方法类型必须是\"弹幕数据\"" }),
1204
- aweme_id: zod.z.string({ error: "视频ID必须是字符串" }).min(1, { error: "视频ID不能为空" }),
1205
- start_time: zod.z.coerce.number({ error: "开始时间必须是数字" }).int({ error: "开始时间必须是整数" }).min(0, { error: "开始时间不能小于0" }).optional(),
1206
- end_time: zod.z.coerce.number({ error: "结束时间必须是数字" }).int({ error: "结束时间必须是整数" }).min(0, { error: "结束时间不能小于0" }).optional(),
1207
- duration: zod.z.coerce.number({ error: "视频时长必须是数字" }).int({ error: "视频时长必须是整数" }).min(0, { error: "视频时长不能小于0" })
1219
+ const DouyinQrcodeParamsSchema = zod.default.object({
1220
+ methodType: zod.default.literal("申请二维码数据", { error: "方法类型必须是\"申请二维码数据\"" }),
1221
+ verify_fp: zod.default.string({ error: "fp指纹必须是字符串" }).min(1, { error: "fp指纹不能为空" })
1222
+ });
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" })
1208
1231
  }).refine((data$1) => {
1209
1232
  if (data$1.end_time !== void 0) return data$1.end_time <= data$1.duration;
1210
1233
  return true;
@@ -1230,30 +1253,53 @@ const DouyinValidationSchemas = {
1230
1253
  热点词数据: DouyinSearchParamsSchema,
1231
1254
  搜索数据: DouyinSearchParamsSchema,
1232
1255
  音乐数据: DouyinMusicParamsSchema,
1233
- 直播间信息数据: DouyinUserParamsSchema,
1256
+ 直播间信息数据: DouyinLiveRoomParamsSchema,
1234
1257
  申请二维码数据: DouyinQrcodeParamsSchema,
1235
1258
  Emoji数据: DouyinEmojiListParamsSchema,
1236
1259
  动态表情数据: DouyinEmojiProParamsSchema,
1237
1260
  指定评论回复数据: DouyinCommentReplyParamsSchema,
1238
1261
  弹幕数据: DouyinDanmakuParamsSchema
1239
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
+ };
1240
1281
 
1241
1282
  //#endregion
1242
1283
  //#region src/validation/kuaishou.ts
1243
- const KuaishouVideoParamsSchema = zod.z.object({
1244
- methodType: zod.z.literal("单个视频作品数据", { error: "方法类型必须是\"单个视频作品数据\"" }),
1245
- 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不能为空" })
1246
1287
  });
1247
- const KuaishouCommentParamsSchema = zod.z.object({
1248
- methodType: zod.z.literal("评论数据", { error: "方法类型必须是\"评论数据\"" }),
1249
- 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不能为空" })
1250
1291
  });
1251
- 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数据\"" }) });
1252
1293
  const KuaishouValidationSchemas = {
1253
1294
  单个视频作品数据: KuaishouVideoParamsSchema,
1254
1295
  评论数据: KuaishouCommentParamsSchema,
1255
1296
  Emoji数据: KuaishouEmojiParamsSchema
1256
1297
  };
1298
+ const KuaishouMethodRoutes = {
1299
+ 单个视频作品数据: "/fetch_one_work",
1300
+ 评论数据: "/fetch_work_comments",
1301
+ Emoji数据: "/fetch_emoji_list"
1302
+ };
1257
1303
 
1258
1304
  //#endregion
1259
1305
  //#region src/platform/xiaohongshu/sign/index.ts
@@ -1293,9 +1339,9 @@ var xiaohongshuSign = class {
1293
1339
  * @param a1Cookie - a1 cookie值
1294
1340
  * @returns X-S签名
1295
1341
  */
1296
- static generateXS(url, body, userAgent, method = "POST", a1Cookie = "") {
1342
+ static generateXS(url$1, body, userAgent, method = "POST", a1Cookie = "") {
1297
1343
  try {
1298
- const urlObj = new URL(url);
1344
+ const urlObj = new URL(url$1);
1299
1345
  const path$1 = urlObj.pathname + urlObj.search;
1300
1346
  if (method.toUpperCase() === "GET") {
1301
1347
  const params = typeof body === "object" ? body : {};
@@ -1511,59 +1557,59 @@ const SearchNoteTypeValues = Object.values(SearchNoteType).filter((v) => typeof
1511
1557
  /**
1512
1558
  * 小红书首页推荐数据参数验证模式
1513
1559
  */
1514
- const HomeFeedParamsSchema = zod.z.object({
1515
- methodType: zod.z.literal("首页推荐数据", { error: "方法类型必须是\"首页推荐数据\"" }),
1516
- cursor_score: zod.z.string({ error: "cursor_score必须是字符串" }).optional(),
1517
- num: zod.z.coerce.number({ error: "数量必须是数字" }).int({ error: "数量必须是整数" }).min(1, { error: "数量不能小于1" }).max(100, { error: "数量不能大于100" }).optional(),
1518
- refresh_type: zod.z.coerce.number({ error: "refresh_type必须是数字" }).int({ error: "refresh_type必须是整数" }).optional(),
1519
- note_index: zod.z.coerce.number({ error: "note_index必须是数字" }).int({ error: "note_index必须是整数" }).optional(),
1520
- category: zod.z.string({ error: "category必须是字符串" }).optional(),
1521
- 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()
1522
1568
  });
1523
1569
  /**
1524
1570
  * 小红书单个笔记数据参数验证模式
1525
1571
  */
1526
- const NoteParamsSchema = zod.z.object({
1527
- methodType: zod.z.literal("单个笔记数据", { error: "方法类型必须是\"单个笔记数据\"" }),
1528
- note_id: zod.z.string({ error: "note_id必须是字符串" }),
1529
- 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必须是字符串" })
1530
1576
  });
1531
1577
  /**
1532
1578
  * 小红书评论数据参数验证模式
1533
1579
  */
1534
- const CommentParamsSchema = zod.z.object({
1535
- methodType: zod.z.literal("评论数据", { error: "方法类型必须是\"评论数据\"" }),
1536
- note_id: zod.z.string({ error: "note_id必须是字符串" }),
1537
- cursor: zod.z.string({ error: "cursor必须是字符串" }).optional(),
1538
- 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必须是字符串" })
1539
1585
  });
1540
1586
  /**
1541
1587
  * 小红书用户数据参数验证模式
1542
1588
  */
1543
- const UserParamsSchema = zod.z.object({
1544
- methodType: zod.z.literal("用户数据", { error: "方法类型必须是\"用户数据\"" }),
1545
- 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必须是字符串" })
1546
1592
  });
1547
1593
  /**
1548
1594
  * 小红书用户笔记数据参数验证模式
1549
1595
  */
1550
- const UserNoteParamsSchema = zod.z.object({
1551
- methodType: zod.z.literal("用户笔记数据", { error: "方法类型必须是\"用户笔记数据\"" }),
1552
- user_id: zod.z.string({ error: "user_id必须是字符串" }),
1553
- cursor: zod.z.string({ error: "cursor必须是字符串" }).optional(),
1554
- 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()
1555
1601
  });
1556
- const EmojiListParamsSchema = zod.z.object({ methodType: zod.z.literal("表情列表", { error: "方法类型必须是\"表情列表\"" }) });
1602
+ const EmojiListParamsSchema = zod.default.object({ methodType: zod.default.literal("表情列表", { error: "方法类型必须是\"表情列表\"" }) });
1557
1603
  /**
1558
1604
  * 小红书搜索笔记参数验证模式
1559
1605
  */
1560
- const SearchNoteParamsSchema = zod.z.object({
1561
- methodType: zod.z.literal("搜索笔记", { error: "方法类型必须是\"搜索笔记\"" }),
1562
- keyword: zod.z.string({ error: "keyword必须是字符串" }),
1563
- page: zod.z.coerce.number({ error: "page必须是数字" }).int({ error: "page必须是整数" }).min(1, { error: "page不能小于1" }).optional(),
1564
- 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(),
1565
- sort: zod.z.enum(SearchSortTypeValues, { error: "排序类型不合法" }).optional(),
1566
- 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()
1567
1613
  });
1568
1614
  /**
1569
1615
  * 小红书验证模式映射
@@ -1578,19 +1624,16 @@ const XiaohongshuValidationSchemas = {
1578
1624
  搜索笔记: SearchNoteParamsSchema
1579
1625
  };
1580
1626
  /**
1581
- * 验证小红书参数
1582
- * @param methodType - 小红书方法类型
1583
- * @param params - 待验证的参数
1584
- * @returns 验证后的参数
1627
+ * 小红书方法类型
1585
1628
  */
1586
- const validateXiaohongshuParams = (methodType, params) => {
1587
- return XiaohongshuValidationSchemas[methodType].parse(typeof params === "object" && params !== null ? {
1588
- methodType,
1589
- ...params
1590
- } : {
1591
- methodType,
1592
- params
1593
- });
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"
1594
1637
  };
1595
1638
 
1596
1639
  //#endregion
@@ -1641,6 +1684,21 @@ const validateKuaishouParams = (methodType, params) => {
1641
1684
  });
1642
1685
  };
1643
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
+ /**
1644
1702
  * 创建成功响应格式
1645
1703
  * @param data - 响应数据
1646
1704
  * @param message - 响应消息(可选)
@@ -1753,30 +1811,8 @@ const createBilibiliRouteHandler = (dataFetcher, methodType, cookie, requestConf
1753
1811
  * @returns Express路由器
1754
1812
  */
1755
1813
  const createBilibiliRoutes = (cookie, requestConfig = getBilibiliDefaultConfig(cookie)) => {
1756
- const router = (0, express.Router)();
1757
- router.get("/fetch_one_video", createBilibiliValidationMiddleware("单个视频作品数据"), createBilibiliRouteHandler(getBilibiliData, "单个视频作品数据", cookie, requestConfig));
1758
- router.get("/fetch_video_playurl", createBilibiliValidationMiddleware("单个视频下载信息数据"), createBilibiliRouteHandler(getBilibiliData, "单个视频下载信息数据", cookie, requestConfig));
1759
- router.get("/fetch_work_comments", createBilibiliValidationMiddleware("评论数据"), createBilibiliRouteHandler(getBilibiliData, "评论数据", cookie, requestConfig));
1760
- router.get("/fetch_comment_reply", createBilibiliValidationMiddleware("指定评论的回复"), createBilibiliRouteHandler(getBilibiliData, "指定评论的回复", cookie, requestConfig));
1761
- router.get("/fetch_user_profile", createBilibiliValidationMiddleware("用户主页数据"), createBilibiliRouteHandler(getBilibiliData, "用户主页数据", cookie, requestConfig));
1762
- router.get("/fetch_user_dynamic", createBilibiliValidationMiddleware("用户主页动态列表数据"), createBilibiliRouteHandler(getBilibiliData, "用户主页动态列表数据", cookie, requestConfig));
1763
- router.get("/fetch_emoji_list", createBilibiliValidationMiddleware("Emoji数据"), createBilibiliRouteHandler(getBilibiliData, "Emoji数据", cookie, requestConfig));
1764
- router.get("/fetch_bangumi_video_info", createBilibiliValidationMiddleware("番剧基本信息数据"), createBilibiliRouteHandler(getBilibiliData, "番剧基本信息数据", cookie, requestConfig));
1765
- router.get("/fetch_bangumi_video_playurl", createBilibiliValidationMiddleware("番剧下载信息数据"), createBilibiliRouteHandler(getBilibiliData, "番剧下载信息数据", cookie, requestConfig));
1766
- router.get("/fetch_dynamic_info", createBilibiliValidationMiddleware("动态详情数据"), createBilibiliRouteHandler(getBilibiliData, "动态详情数据", cookie, requestConfig));
1767
- router.get("/fetch_dynamic_card", createBilibiliValidationMiddleware("动态卡片数据"), createBilibiliRouteHandler(getBilibiliData, "动态卡片数据", cookie, requestConfig));
1768
- router.get("/fetch_live_room_detail", createBilibiliValidationMiddleware("直播间信息"), createBilibiliRouteHandler(getBilibiliData, "直播间信息", cookie, requestConfig));
1769
- router.get("/fetch_liveroom_def", createBilibiliValidationMiddleware("直播间初始化信息"), createBilibiliRouteHandler(getBilibiliData, "直播间初始化信息", cookie, requestConfig));
1770
- router.get("/login_basic_info", createBilibiliValidationMiddleware("登录基本信息"), createBilibiliRouteHandler(getBilibiliData, "登录基本信息", cookie, requestConfig));
1771
- router.get("/new_login_qrcode", createBilibiliValidationMiddleware("申请二维码"), createBilibiliRouteHandler(getBilibiliData, "申请二维码", cookie, requestConfig));
1772
- router.get("/check_qrcode", createBilibiliValidationMiddleware("二维码状态"), createBilibiliRouteHandler(getBilibiliData, "二维码状态", cookie, requestConfig));
1773
- router.get("/fetch_user_full_view", createBilibiliValidationMiddleware("获取UP主总播放量"), createBilibiliRouteHandler(getBilibiliData, "获取UP主总播放量", cookie, requestConfig));
1774
- router.get("/av_to_bv", createBilibiliValidationMiddleware("AV转BV"), createBilibiliRouteHandler(getBilibiliData, "AV转BV", cookie, requestConfig));
1775
- router.get("/bv_to_av", createBilibiliValidationMiddleware("BV转AV"), createBilibiliRouteHandler(getBilibiliData, "BV转AV", cookie, requestConfig));
1776
- router.get("/fetch_article_content", createBilibiliValidationMiddleware("专栏正文内容"), createBilibiliRouteHandler(getBilibiliData, "专栏正文内容", cookie, requestConfig));
1777
- router.get("/fetch_article_card", createBilibiliValidationMiddleware("专栏显示卡片信息"), createBilibiliRouteHandler(getBilibiliData, "专栏显示卡片信息", cookie, requestConfig));
1778
- router.get("/fetch_article_info", createBilibiliValidationMiddleware("专栏文章基本信息"), createBilibiliRouteHandler(getBilibiliData, "专栏文章基本信息", cookie, requestConfig));
1779
- 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));
1780
1816
  return router;
1781
1817
  };
1782
1818
 
@@ -1842,6 +1878,12 @@ const qtparam = async (BASEURL, cookie) => {
1842
1878
  //#endregion
1843
1879
  //#region src/platform/bilibili/getdata.ts
1844
1880
  /**
1881
+ * B站数据获取模块
1882
+ *
1883
+ * 注意:为避免循环依赖,此文件直接从具体模块导入,而不是从平台 index 文件导入
1884
+ * 循环依赖链:DataFetchers → getdata → platform/bilibili → DataFetchers
1885
+ */
1886
+ /**
1845
1887
  * B站数据获取函数
1846
1888
  * @param data - 请求数据参数
1847
1889
  * @param cookie - 用户Cookie
@@ -2634,9 +2676,9 @@ const cleanUserAgentForSigning = (userAgent) => {
2634
2676
  * @param user_agent - 用户代理字符串
2635
2677
  * @returns 生成的a_bogus签名
2636
2678
  */
2637
- var a_bogus_default = (url, user_agent) => {
2679
+ var a_bogus_default = (url$1, user_agent) => {
2638
2680
  const cleanedUserAgent = cleanUserAgentForSigning(user_agent);
2639
- 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") + "=";
2640
2682
  };
2641
2683
 
2642
2684
  //#endregion
@@ -2738,8 +2780,8 @@ var XBogus = class {
2738
2780
  * @param ua 可选的User-Agent,不提供则使用默认值
2739
2781
  * @returns 包含完整URL、X-Bogus值和使用的User-Agent的元组
2740
2782
  */
2741
- getXBogus(url, ua) {
2742
- const parsedUrl = new node_url.default.URL(url);
2783
+ getXBogus(url$1, ua) {
2784
+ const parsedUrl = new node_url.default.URL(url$1);
2743
2785
  const urlPath = parsedUrl.pathname + parsedUrl.search;
2744
2786
  const currentUa = ua ?? this.defaultUa;
2745
2787
  const rc4EncryptedUa = this.rc4Encrypt(this.uaKey, currentUa);
@@ -2796,7 +2838,7 @@ var XBogus = class {
2796
2838
  idx += 3;
2797
2839
  }
2798
2840
  return {
2799
- 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}`,
2800
2842
  xbogus: xb,
2801
2843
  userAgent: currentUa
2802
2844
  };
@@ -2822,16 +2864,16 @@ var douyinSign = class {
2822
2864
  * @param url 需要签名的地址
2823
2865
  * @returns 对此地址签名后的URL查询参数
2824
2866
  */
2825
- static AB(url, userAgent) {
2826
- return a_bogus_default(url, userAgent ?? defaultUserAgent);
2867
+ static AB(url$1, userAgent) {
2868
+ return a_bogus_default(url$1, userAgent ?? defaultUserAgent);
2827
2869
  }
2828
2870
  /**
2829
2871
  * X-Bogus 签名算法
2830
2872
  * @param url 需要签名的地址
2831
2873
  * @returns 对此地址签名后的URL查询参数
2832
2874
  */
2833
- static XB(url, userAgent) {
2834
- return new XBogus().getXBogus(url, userAgent ?? defaultUserAgent).xbogus;
2875
+ static XB(url$1, userAgent) {
2876
+ return new XBogus().getXBogus(url$1, userAgent ?? defaultUserAgent).xbogus;
2835
2877
  }
2836
2878
  /** 生成一个唯一的验证字符串 */
2837
2879
  static VerifyFpManager() {
@@ -3297,17 +3339,23 @@ const douyinApiUrls = new DouyinAPI();
3297
3339
  //#endregion
3298
3340
  //#region src/platform/douyin/getdata.ts
3299
3341
  /**
3342
+ * 抖音数据获取模块
3343
+ *
3344
+ * 注意:为避免循环依赖,此文件直接从具体模块导入,而不是从平台 index 文件导入
3345
+ * 循环依赖链:DataFetchers → getdata → platform/douyin → DataFetchers
3346
+ */
3347
+ /**
3300
3348
  * 获取签名参数
3301
3349
  * @param url - 需要签名的URL
3302
3350
  * @param signType - 签名算法类型
3303
3351
  * @param userAgent - 用户代理
3304
3352
  * @returns 签名后的参数字符串
3305
3353
  */
3306
- const getSignature = (url, signType = "a_bogus", userAgent) => {
3354
+ const getSignature = (url$1, signType = "a_bogus", userAgent) => {
3307
3355
  switch (signType) {
3308
- case "x_bogus": return douyinSign.XB(url, userAgent);
3356
+ case "x_bogus": return douyinSign.XB(url$1, userAgent);
3309
3357
  case "a_bogus":
3310
- default: return douyinSign.AB(url, userAgent);
3358
+ default: return douyinSign.AB(url$1, userAgent);
3311
3359
  }
3312
3360
  };
3313
3361
  /**
@@ -3329,9 +3377,9 @@ const getSignParamName = (signType = "a_bogus") => {
3329
3377
  * @param userAgent - 用户代理
3330
3378
  * @returns 带签名的完整URL
3331
3379
  */
3332
- const buildSignedUrl = (url, signType = "a_bogus", userAgent) => {
3333
- const signature = getSignature(url, signType, userAgent);
3334
- 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}`;
3335
3383
  };
3336
3384
  /**
3337
3385
  * 抖音数据获取函数
@@ -3360,10 +3408,10 @@ const DouyinData = async (data$1, cookie, requestConfig) => {
3360
3408
  case "视频作品数据":
3361
3409
  case "图集作品数据":
3362
3410
  case "合辑作品数据": {
3363
- const url = douyinApiUrls$1.视频或图集({ aweme_id: data$1.aweme_id });
3411
+ const url$1 = douyinApiUrls$1.视频或图集({ aweme_id: data$1.aweme_id });
3364
3412
  return await GlobalGetData$2(data$1.methodType, {
3365
3413
  ...baseRequestConfig,
3366
- url: buildSignedUrl(url, signType, userAgent)
3414
+ url: buildSignedUrl(url$1, signType, userAgent)
3367
3415
  });
3368
3416
  }
3369
3417
  case "评论数据": {
@@ -3375,7 +3423,7 @@ const DouyinData = async (data$1, cookie, requestConfig) => {
3375
3423
  return await fetchPaginatedData(data$1.methodType, urlGenerator, data$1, 3, baseRequestConfig, "x_bogus");
3376
3424
  }
3377
3425
  case "用户主页数据": {
3378
- const url = douyinApiUrls$1.用户主页信息({ sec_uid: data$1.sec_uid });
3426
+ const url$1 = douyinApiUrls$1.用户主页信息({ sec_uid: data$1.sec_uid });
3379
3427
  const customConfig = {
3380
3428
  ...baseRequestConfig,
3381
3429
  headers: {
@@ -3385,18 +3433,18 @@ const DouyinData = async (data$1, cookie, requestConfig) => {
3385
3433
  };
3386
3434
  return await GlobalGetData$2(data$1.methodType, {
3387
3435
  ...customConfig,
3388
- url: buildSignedUrl(url, signType, userAgent)
3436
+ url: buildSignedUrl(url$1, signType, userAgent)
3389
3437
  });
3390
3438
  }
3391
3439
  case "Emoji数据": {
3392
- const url = douyinApiUrls$1.表情();
3440
+ const url$1 = douyinApiUrls$1.表情();
3393
3441
  return await GlobalGetData$2(data$1.methodType, {
3394
3442
  ...baseRequestConfig,
3395
- url
3443
+ url: url$1
3396
3444
  });
3397
3445
  }
3398
3446
  case "用户主页视频列表数据": {
3399
- const url = douyinApiUrls$1.用户主页视频({ sec_uid: data$1.sec_uid });
3447
+ const url$1 = douyinApiUrls$1.用户主页视频({ sec_uid: data$1.sec_uid });
3400
3448
  const customConfig = {
3401
3449
  ...baseRequestConfig,
3402
3450
  headers: {
@@ -3406,11 +3454,11 @@ const DouyinData = async (data$1, cookie, requestConfig) => {
3406
3454
  };
3407
3455
  return await GlobalGetData$2(data$1.methodType, {
3408
3456
  ...customConfig,
3409
- url: buildSignedUrl(url, signType, userAgent)
3457
+ url: buildSignedUrl(url$1, signType, userAgent)
3410
3458
  });
3411
3459
  }
3412
3460
  case "热点词数据": {
3413
- const url = douyinApiUrls$1.热点词({
3461
+ const url$1 = douyinApiUrls$1.热点词({
3414
3462
  query: data$1.query,
3415
3463
  number: data$1.number ?? 10
3416
3464
  });
@@ -3423,7 +3471,7 @@ const DouyinData = async (data$1, cookie, requestConfig) => {
3423
3471
  };
3424
3472
  return await GlobalGetData$2(data$1.methodType, {
3425
3473
  ...customConfig,
3426
- url: buildSignedUrl(url, signType, userAgent)
3474
+ url: buildSignedUrl(url$1, signType, userAgent)
3427
3475
  });
3428
3476
  }
3429
3477
  case "搜索数据": {
@@ -3440,19 +3488,22 @@ const DouyinData = async (data$1, cookie, requestConfig) => {
3440
3488
  };
3441
3489
  while (fetchedSearchList.length < Number(data$1.number ?? 10)) {
3442
3490
  const requestCount = Math.min(Number(data$1.number ?? 50) - fetchedSearchList.length, maxPageSize);
3443
- const url = douyinApiUrls$1.搜索({
3491
+ const url$1 = douyinApiUrls$1.搜索({
3444
3492
  query: data$1.query,
3445
3493
  number: requestCount,
3446
3494
  search_id: search_id === "" ? void 0 : search_id
3447
3495
  });
3448
3496
  const raw = await GlobalGetData$2(data$1.methodType, {
3449
3497
  ...customConfig,
3450
- url: buildSignedUrl(url, "x_bogus", userAgent)
3498
+ url: buildSignedUrl(url$1, "x_bogus", userAgent)
3451
3499
  });
3452
3500
  const responses = filterSearchResponses(typeof raw === "string" ? parseDouyinMultiJson(raw) : [raw]);
3453
3501
  if (responses.length === 0) {
3454
3502
  logger.warn("抖音搜索返回无有效数据,疑似触发反爬\n你的抖音ck可能已经失效!\n请求类型:" + data$1.methodType);
3455
- return false;
3503
+ return {
3504
+ success: false,
3505
+ amagiError: "抖音搜索返回无有效数据,疑似触发反爬\n你的抖音ck可能已经失效!\n请求类型:" + data$1.methodType
3506
+ };
3456
3507
  }
3457
3508
  for (const resp of responses) {
3458
3509
  if (Array.isArray(resp.data) && resp.data.length > 0) fetchedSearchList.push(...resp.data);
@@ -3460,8 +3511,11 @@ const DouyinData = async (data$1, cookie, requestConfig) => {
3460
3511
  search_id = resp.log_pb?.impr_id ?? search_id;
3461
3512
  }
3462
3513
  if (fetchedSearchList.length === 0) {
3463
- logger.warn("抖音搜索返回数据长度为空,\n你的抖音ck疑似触发验证码!\n请求类型:" + data$1.methodType);
3464
- 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
+ };
3465
3519
  }
3466
3520
  if (tmpresp && typeof tmpresp.has_more === "number" && tmpresp.has_more === 0) break;
3467
3521
  }
@@ -3471,77 +3525,42 @@ const DouyinData = async (data$1, cookie, requestConfig) => {
3471
3525
  };
3472
3526
  }
3473
3527
  case "动态表情数据": {
3474
- const url = douyinApiUrls$1.互动表情();
3528
+ const url$1 = douyinApiUrls$1.互动表情();
3475
3529
  return await GlobalGetData$2(data$1.methodType, {
3476
3530
  ...baseRequestConfig,
3477
- url: buildSignedUrl(url, signType, userAgent)
3531
+ url: buildSignedUrl(url$1, signType, userAgent)
3478
3532
  });
3479
3533
  }
3480
3534
  case "音乐数据": {
3481
- const url = douyinApiUrls$1.背景音乐({ music_id: data$1.music_id });
3535
+ const url$1 = douyinApiUrls$1.背景音乐({ music_id: data$1.music_id });
3482
3536
  return await GlobalGetData$2(data$1.methodType, {
3483
3537
  ...baseRequestConfig,
3484
- url: buildSignedUrl(url, signType, userAgent)
3538
+ url: buildSignedUrl(url$1, signType, userAgent)
3485
3539
  });
3486
3540
  }
3487
3541
  case "直播间信息数据": {
3488
- let url = douyinApiUrls$1.用户主页信息({ sec_uid: data$1.sec_uid });
3489
- const fetchUrl = buildSignedUrl(url, signType, userAgent);
3490
- const customConfig = {
3491
- ...baseRequestConfig,
3492
- headers: {
3493
- ...baseRequestConfig.headers,
3494
- ...(!requestConfig?.headers || !("Referer" in requestConfig.headers)) && { Referer: `https://www.douyin.com/user/${data$1.sec_uid}` }
3495
- }
3496
- };
3497
- const UserInfoData = await GlobalGetData$2(data$1.methodType, {
3498
- ...customConfig,
3499
- url: fetchUrl
3500
- });
3501
- if (!UserInfoData?.user?.live_status || UserInfoData.user.live_status !== 1) {
3502
- logger.error((UserInfoData?.user?.nickname ?? "用户") + "当前未在直播");
3503
- const Err = {
3504
- errorDescription: "检查失败!该用户当前未在直播! TypeError: Cannot read properties of undefined (reading 'live_status')",
3505
- requestType: data$1.methodType ?? "未知请求类型",
3506
- requestUrl: fetchUrl
3507
- };
3508
- return {
3509
- code: douoyinAPIErrorCode.NOT_LIVE,
3510
- data: UserInfoData,
3511
- amagiError: Err,
3512
- amagiMessage: Err.errorDescription
3513
- };
3514
- }
3515
- if (!UserInfoData.user.room_data) {
3516
- logger.error("未获取到直播间信息!");
3517
- return {
3518
- code: 500,
3519
- message: "未获取到直播间信息!",
3520
- data: null
3521
- };
3522
- }
3523
- const room_data = JSON.parse(UserInfoData.user.room_data);
3524
- url = douyinApiUrls$1.直播间信息({
3525
- room_id: UserInfoData.user.room_id_str,
3526
- 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
3527
3545
  });
3528
3546
  const liveCustomConfig = {
3529
3547
  ...baseRequestConfig,
3548
+ url: buildSignedUrl(url$1, signType, userAgent),
3530
3549
  headers: {
3531
3550
  ...baseRequestConfig.headers,
3532
- ...(!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}` }
3533
3552
  }
3534
3553
  };
3535
3554
  return await GlobalGetData$2(data$1.methodType, {
3536
3555
  ...liveCustomConfig,
3537
- url: buildSignedUrl(url, signType, userAgent)
3556
+ url: buildSignedUrl(url$1, signType, userAgent)
3538
3557
  });
3539
3558
  }
3540
3559
  case "申请二维码数据": {
3541
- const url = douyinApiUrls$1.申请二维码({ verify_fp: data$1.verify_fp });
3560
+ const url$1 = douyinApiUrls$1.申请二维码({ verify_fp: data$1.verify_fp });
3542
3561
  return await GlobalGetData$2(data$1.methodType, {
3543
3562
  ...baseRequestConfig,
3544
- url: buildSignedUrl(url, signType, userAgent)
3563
+ url: buildSignedUrl(url$1, signType, userAgent)
3545
3564
  });
3546
3565
  }
3547
3566
  case "弹幕数据": {
@@ -3550,7 +3569,7 @@ const DouyinData = async (data$1, cookie, requestConfig) => {
3550
3569
  const endTime = data$1.end_time ?? data$1.duration;
3551
3570
  const totalDuration = endTime - startTime;
3552
3571
  if (totalDuration <= MAX_SEGMENT_DURATION) {
3553
- const url = douyinApiUrls$1.弹幕({
3572
+ const url$1 = douyinApiUrls$1.弹幕({
3554
3573
  aweme_id: data$1.aweme_id,
3555
3574
  start_time: startTime,
3556
3575
  end_time: endTime,
@@ -3558,7 +3577,7 @@ const DouyinData = async (data$1, cookie, requestConfig) => {
3558
3577
  });
3559
3578
  return await GlobalGetData$2(data$1.methodType, {
3560
3579
  ...baseRequestConfig,
3561
- url: buildSignedUrl(url, signType, userAgent)
3580
+ url: buildSignedUrl(url$1, signType, userAgent)
3562
3581
  });
3563
3582
  }
3564
3583
  const segments = [];
@@ -3573,7 +3592,7 @@ const DouyinData = async (data$1, cookie, requestConfig) => {
3573
3592
  }
3574
3593
  logger.debug(`弹幕数据需要分${segments.length}段获取,总时长:${totalDuration}ms`);
3575
3594
  const segmentPromises = segments.map(async (segment, index) => {
3576
- const url = douyinApiUrls$1.弹幕({
3595
+ const url$1 = douyinApiUrls$1.弹幕({
3577
3596
  aweme_id: data$1.aweme_id,
3578
3597
  start_time: segment.start,
3579
3598
  end_time: segment.end,
@@ -3582,7 +3601,7 @@ const DouyinData = async (data$1, cookie, requestConfig) => {
3582
3601
  try {
3583
3602
  const segmentData = await GlobalGetData$2(`${data$1.methodType}-段${index + 1}`, {
3584
3603
  ...baseRequestConfig,
3585
- url: buildSignedUrl(url, signType, userAgent)
3604
+ url: buildSignedUrl(url$1, signType, userAgent)
3586
3605
  });
3587
3606
  logger.debug(`弹幕第${index + 1}段获取成功 (${segment.start}ms-${segment.end}ms)`);
3588
3607
  return segmentData;
@@ -3623,9 +3642,18 @@ const DouyinData = async (data$1, cookie, requestConfig) => {
3623
3642
  logger.debug(`弹幕数据合并完成,共获取${mergedDanmakuList.length}条弹幕`);
3624
3643
  return finalDanmakuData;
3625
3644
  }
3626
- 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
+ }
3627
3654
  logger.warn(`未知的抖音数据接口:「${logger.red(data$1.methodType)}」`);
3628
3655
  return null;
3656
+ }
3629
3657
  }
3630
3658
  };
3631
3659
  /**
@@ -3645,14 +3673,14 @@ const fetchPaginatedData = async (type, apiUrlGenerator, params, maxPageSize, re
3645
3673
  const userAgent = requestConfig.headers?.["User-Agent"];
3646
3674
  while (fetchedData.length < Number(params.number ?? maxPageSize)) {
3647
3675
  const requestCount = Math.min(Number(params.number ?? maxPageSize) - fetchedData.length, maxPageSize);
3648
- const url = apiUrlGenerator({
3676
+ const url$1 = apiUrlGenerator({
3649
3677
  ...params,
3650
3678
  number: requestCount,
3651
3679
  cursor
3652
3680
  });
3653
3681
  const response = await GlobalGetData$2(type, {
3654
3682
  ...requestConfig,
3655
- url: buildSignedUrl(url, signType, userAgent)
3683
+ url: buildSignedUrl(url$1, signType, userAgent)
3656
3684
  });
3657
3685
  fetchedData.push(...response.comments ?? response.data ?? []);
3658
3686
  tmpresp = response;
@@ -3817,6 +3845,12 @@ const kuaishouApiUrls = new API();
3817
3845
  //#endregion
3818
3846
  //#region src/platform/kuaishou/getdata.ts
3819
3847
  /**
3848
+ * 快手数据获取模块
3849
+ *
3850
+ * 注意:为避免循环依赖,此文件直接从具体模块导入,而不是从平台 index 文件导入
3851
+ * 循环依赖链:DataFetchers → getdata → platform/kuaishou → DataFetchers
3852
+ */
3853
+ /**
3820
3854
  * 快手数据获取函数
3821
3855
  * @param data - 请求数据参数
3822
3856
  * @param cookie - 用户Cookie
@@ -4094,7 +4128,7 @@ async function getDouyinData(methodType, optionsOrCookie, cookieOrOptions, reque
4094
4128
  cookie = cookieOrOptions;
4095
4129
  config = requestConfig;
4096
4130
  }
4097
- const { typeMode: _,...validationOptions } = options ?? {};
4131
+ const { typeMode: _, ...validationOptions } = options ?? {};
4098
4132
  const rawData = await DouyinData({ ...validateDouyinParams(methodType, validationOptions) }, cookie, config);
4099
4133
  if (rawData.data === "" || rawData.status_code !== 0) return createErrorResponse(rawData.amagiError, rawData.status_msg ?? "抖音数据获取失败");
4100
4134
  return createSuccessResponse(rawData, "获取成功", 200);
@@ -4117,7 +4151,7 @@ async function getBilibiliData(methodType, optionsOrCookie, cookieOrOptions, req
4117
4151
  options = optionsOrCookie;
4118
4152
  cookie = cookieOrOptions;
4119
4153
  }
4120
- const { typeMode: _,...validationOptions } = options ?? {};
4154
+ const { typeMode: _, ...validationOptions } = options ?? {};
4121
4155
  const rawData = await fetchBilibili({ ...validateBilibiliParams(methodType, validationOptions) }, cookie);
4122
4156
  if (rawData.code !== 0) return createErrorResponse(rawData.amagiError, "B站数据获取失败");
4123
4157
  return createSuccessResponse(rawData, "获取成功", 200);
@@ -4140,7 +4174,7 @@ async function getKuaishouData(methodType, optionsOrCookie, cookieOrOptions, req
4140
4174
  options = optionsOrCookie;
4141
4175
  cookie = cookieOrOptions;
4142
4176
  }
4143
- const { typeMode: _,...validationOptions } = options ?? {};
4177
+ const { typeMode: _, ...validationOptions } = options ?? {};
4144
4178
  const rawData = await KuaishouData({ ...validateKuaishouParams(methodType, validationOptions) }, cookie);
4145
4179
  if (rawData.code && Object.values(kuaishouAPIErrorCode).includes(rawData.code)) return createErrorResponse(rawData.amagiError, "快手数据获取失败");
4146
4180
  return createSuccessResponse(rawData, "获取成功", 200);
@@ -4163,7 +4197,7 @@ async function getXiaohongshuData(methodType, optionsOrCookie, cookieOrOptions,
4163
4197
  options = optionsOrCookie;
4164
4198
  cookie = cookieOrOptions;
4165
4199
  }
4166
- const { typeMode: _,...validationOptions } = options ?? {};
4200
+ const { typeMode: _, ...validationOptions } = options ?? {};
4167
4201
  const rawData = await XiaohongshuData({ ...validateXiaohongshuParams(methodType, validationOptions) }, cookie);
4168
4202
  if (rawData.code && Object.values(xiaohongshuAPIErrorCode).includes(rawData.code)) return createErrorResponse(rawData.amagiError, "小红书数据获取失败");
4169
4203
  return createSuccessResponse(rawData, "获取成功", 200);
@@ -4221,7 +4255,10 @@ const douyin = {
4221
4255
  getSuggestWords: createDouyinApiMethod("热点词数据"),
4222
4256
  search: createDouyinApiMethod("搜索数据"),
4223
4257
  getLiveRoomInfo: createDouyinApiMethod("直播间信息数据"),
4224
- getDanmaku: createDouyinApiMethod("弹幕数据")
4258
+ getDanmaku: createDouyinApiMethod("弹幕数据"),
4259
+ invoke: async (methodType, options, cookie, requestConfig) => {
4260
+ return await getDouyinData(methodType, options, cookie, requestConfig);
4261
+ }
4225
4262
  };
4226
4263
  /**
4227
4264
  * 创建绑定了cookie的抖音API对象
@@ -4243,9 +4280,12 @@ const createBoundDouyinApi = (cookie, requestConfig) => {
4243
4280
  getUserVideos: createBoundDouyinApiMethod("用户主页视频列表数据", cookie, requestConfig),
4244
4281
  getMusicInfo: createBoundDouyinApiMethod("音乐数据", cookie, requestConfig),
4245
4282
  getSuggestWords: createBoundDouyinApiMethod("热点词数据", cookie, requestConfig),
4246
- search: createBoundDouyinApiMethod("搜索数据", cookie, requestConfig),
4283
+ getSearchData: createBoundDouyinApiMethod("搜索数据", cookie, requestConfig),
4247
4284
  getLiveRoomInfo: createBoundDouyinApiMethod("直播间信息数据", cookie, requestConfig),
4248
- getDanmaku: createBoundDouyinApiMethod("弹幕数据", cookie, requestConfig)
4285
+ getDanmaku: createBoundDouyinApiMethod("弹幕数据", cookie, requestConfig),
4286
+ invoke: async (methodType, options) => {
4287
+ return await getDouyinData(methodType, options, cookie, requestConfig);
4288
+ }
4249
4289
  };
4250
4290
  };
4251
4291
 
@@ -4283,22 +4323,8 @@ const createDouyinRouteHandler = (dataFetcher, methodType, cookie, requestConfig
4283
4323
  * @returns Express路由器
4284
4324
  */
4285
4325
  const createDouyinRoutes = (cookie, requestConfig = getDouyinDefaultConfig(cookie)) => {
4286
- const router = (0, express.Router)();
4287
- router.get("/fetch_one_work", createDouyinValidationMiddleware("聚合解析"), createDouyinRouteHandler(getDouyinData, "聚合解析", cookie, requestConfig));
4288
- router.get("/fetch_one_work", createDouyinValidationMiddleware("视频作品数据"), createDouyinRouteHandler(getDouyinData, "视频作品数据", cookie, requestConfig));
4289
- router.get("/fetch_one_work", createDouyinValidationMiddleware("图集作品数据"), createDouyinRouteHandler(getDouyinData, "图集作品数据", cookie, requestConfig));
4290
- router.get("/fetch_one_work", createDouyinValidationMiddleware("合辑作品数据"), createDouyinRouteHandler(getDouyinData, "合辑作品数据", cookie, requestConfig));
4291
- router.get("/fetch_work_comments", createDouyinValidationMiddleware("评论数据"), createDouyinRouteHandler(getDouyinData, "评论数据", cookie, requestConfig));
4292
- router.get("/fetch_user_info", createDouyinValidationMiddleware("用户主页数据"), createDouyinRouteHandler(getDouyinData, "用户主页数据", cookie, requestConfig));
4293
- router.get("/fetch_user_post_videos", createDouyinValidationMiddleware("用户主页视频列表数据"), createDouyinRouteHandler(getDouyinData, "用户主页视频列表数据", cookie, requestConfig));
4294
- router.get("/fetch_search_info", createDouyinValidationMiddleware("搜索数据"), createDouyinRouteHandler(getDouyinData, "搜索数据", cookie, requestConfig));
4295
- router.get("/fetch_suggest_words", createDouyinValidationMiddleware("热点词数据"), createDouyinRouteHandler(getDouyinData, "热点词数据", cookie, requestConfig));
4296
- router.get("/fetch_music_work", createDouyinValidationMiddleware("音乐数据"), createDouyinRouteHandler(getDouyinData, "音乐数据", cookie, requestConfig));
4297
- router.get("/fetch_emoji_list", createDouyinValidationMiddleware("Emoji数据"), createDouyinRouteHandler(getDouyinData, "Emoji数据", cookie, requestConfig));
4298
- router.get("/fetch_emoji_pro_list", createDouyinValidationMiddleware("动态表情数据"), createDouyinRouteHandler(getDouyinData, "动态表情数据", cookie, requestConfig));
4299
- router.get("/fetch_user_live_videos", createDouyinValidationMiddleware("直播间信息数据"), createDouyinRouteHandler(getDouyinData, "直播间信息数据", cookie, requestConfig));
4300
- router.get("/fetch_video_comment_replies", createDouyinValidationMiddleware("指定评论回复数据"), createDouyinRouteHandler(getDouyinData, "指定评论回复数据", cookie, requestConfig));
4301
- 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));
4302
4328
  return router;
4303
4329
  };
4304
4330
 
@@ -4390,10 +4416,8 @@ const createKuaishouRouteHandler = (dataFetcher, methodType, cookie, requestConf
4390
4416
  * @returns Express路由器
4391
4417
  */
4392
4418
  const createKuaishouRoutes = (cookie, requestConfig = getKuaishouDefaultConfig(cookie)) => {
4393
- const router = (0, express.Router)();
4394
- router.get("/fetch_one_work", createKuaishouValidationMiddleware("单个视频作品数据"), createKuaishouRouteHandler(getKuaishouData, "单个视频作品数据", cookie, requestConfig));
4395
- router.get("/fetch_work_comments", createKuaishouValidationMiddleware("评论数据"), createKuaishouRouteHandler(getKuaishouData, "评论数据", cookie, requestConfig));
4396
- 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));
4397
4421
  return router;
4398
4422
  };
4399
4423
 
@@ -4497,14 +4521,8 @@ const createXiaohongshuRouteHandler = (dataFetcher, methodType, cookie, requestC
4497
4521
  * @returns Express路由器
4498
4522
  */
4499
4523
  const createXiaohongshuRoutes = (cookie, requestConfig = getXiaohongshuDefaultConfig(cookie)) => {
4500
- const router = (0, express.Router)();
4501
- router.get("/fetch_home_feed", createXiaohongshuValidationMiddleware("首页推荐数据"), createXiaohongshuRouteHandler(getXiaohongshuData, "首页推荐数据", cookie, requestConfig));
4502
- router.get("/fetch_one_note", createXiaohongshuValidationMiddleware("单个笔记数据"), createXiaohongshuRouteHandler(getXiaohongshuData, "单个笔记数据", cookie, requestConfig));
4503
- router.get("/fetch_note_comments", createXiaohongshuValidationMiddleware("评论数据"), createXiaohongshuRouteHandler(getXiaohongshuData, "评论数据", cookie, requestConfig));
4504
- router.get("/fetch_user_profile", createXiaohongshuValidationMiddleware("用户数据"), createXiaohongshuRouteHandler(getXiaohongshuData, "用户数据", cookie, requestConfig));
4505
- router.get("/fetch_user_notes", createXiaohongshuValidationMiddleware("用户笔记数据"), createXiaohongshuRouteHandler(getXiaohongshuData, "用户笔记数据", cookie, requestConfig));
4506
- router.get("/fetch_emoji_list", createXiaohongshuValidationMiddleware("表情列表"), createXiaohongshuRouteHandler(getXiaohongshuData, "表情列表", cookie, requestConfig));
4507
- 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));
4508
4526
  return router;
4509
4527
  };
4510
4528
 
@@ -4615,6 +4633,60 @@ const createAmagiClient = (options) => {
4615
4633
  };
4616
4634
  };
4617
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
+
4618
4690
  //#endregion
4619
4691
  //#region src/types/ReturnDataType/Bilibili/Dynamic/index.ts
4620
4692
  /**
@@ -4744,18 +4816,22 @@ exports.BilibiliDynamicParamsSchema = BilibiliDynamicParamsSchema;
4744
4816
  exports.BilibiliEmojiParamsSchema = BilibiliEmojiParamsSchema;
4745
4817
  exports.BilibiliLiveParamsSchema = BilibiliLiveParamsSchema;
4746
4818
  exports.BilibiliLoginParamsSchema = BilibiliLoginParamsSchema;
4819
+ exports.BilibiliMethodRoutes = BilibiliMethodRoutes;
4747
4820
  exports.BilibiliQrcodeParamsSchema = BilibiliQrcodeParamsSchema;
4748
4821
  exports.BilibiliQrcodeStatusParamsSchema = BilibiliQrcodeStatusParamsSchema;
4749
4822
  exports.BilibiliUserParamsSchema = BilibiliUserParamsSchema;
4750
4823
  exports.BilibiliValidationSchemas = BilibiliValidationSchemas;
4751
4824
  exports.BilibiliVideoDownloadParamsSchema = BilibiliVideoDownloadParamsSchema;
4752
4825
  exports.BilibiliVideoParamsSchema = BilibiliVideoParamsSchema;
4826
+ exports.CommentType = CommentType;
4753
4827
  exports.CreateApp = CreateApp;
4754
4828
  exports.DouyinCommentParamsSchema = DouyinCommentParamsSchema;
4755
4829
  exports.DouyinCommentReplyParamsSchema = DouyinCommentReplyParamsSchema;
4756
4830
  exports.DouyinDanmakuParamsSchema = DouyinDanmakuParamsSchema;
4757
4831
  exports.DouyinEmojiListParamsSchema = DouyinEmojiListParamsSchema;
4758
4832
  exports.DouyinEmojiProParamsSchema = DouyinEmojiProParamsSchema;
4833
+ exports.DouyinLiveRoomParamsSchema = DouyinLiveRoomParamsSchema;
4834
+ exports.DouyinMethodRoutes = DouyinMethodRoutes;
4759
4835
  exports.DouyinMusicParamsSchema = DouyinMusicParamsSchema;
4760
4836
  exports.DouyinQrcodeParamsSchema = DouyinQrcodeParamsSchema;
4761
4837
  exports.DouyinSearchParamsSchema = DouyinSearchParamsSchema;
@@ -4765,10 +4841,12 @@ exports.DouyinWorkParamsSchema = DouyinWorkParamsSchema;
4765
4841
  exports.DynamicType = DynamicType;
4766
4842
  exports.KuaishouCommentParamsSchema = KuaishouCommentParamsSchema;
4767
4843
  exports.KuaishouEmojiParamsSchema = KuaishouEmojiParamsSchema;
4844
+ exports.KuaishouMethodRoutes = KuaishouMethodRoutes;
4768
4845
  exports.KuaishouValidationSchemas = KuaishouValidationSchemas;
4769
4846
  exports.KuaishouVideoParamsSchema = KuaishouVideoParamsSchema;
4770
4847
  exports.MajorType = MajorType;
4771
4848
  exports.ValidationError = ValidationError;
4849
+ exports.XiaohongshuMethodRoutes = XiaohongshuMethodRoutes;
4772
4850
  exports.XiaohongshuValidationSchemas = XiaohongshuValidationSchemas;
4773
4851
  exports.amagi = amagi;
4774
4852
  exports.amagiClient = amagiClient;