@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.
- package/README.md +6 -0
- package/dist/default/index.cjs +379 -301
- package/dist/default/index.d.cts +7565 -7788
- package/dist/default/index.d.ts +7565 -7788
- package/dist/default/index.js +377 -303
- package/package.json +1 -1
package/dist/default/index.js
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import
|
|
3
|
+
import url from "node:url";
|
|
4
4
|
import { Chalk } from "chalk";
|
|
5
5
|
import log4js from "log4js";
|
|
6
6
|
import axios, { AxiosError } from "axios";
|
|
7
7
|
import crypto from "node:crypto";
|
|
8
|
-
import
|
|
8
|
+
import zod from "zod";
|
|
9
9
|
import { Xhshow } from "@ikenxuan/xhshow-ts";
|
|
10
|
-
import express
|
|
10
|
+
import express from "express";
|
|
11
11
|
|
|
12
12
|
//#region src/model/logger.ts
|
|
13
13
|
/** 获取包的绝对路径 */
|
|
14
14
|
const getPackageLogsPath = () => {
|
|
15
15
|
const currentFileUrl = import.meta.url;
|
|
16
|
-
const currentFilePath = fileURLToPath(currentFileUrl);
|
|
16
|
+
const currentFilePath = url.fileURLToPath(currentFileUrl);
|
|
17
17
|
let packageRoot = path.dirname(currentFilePath);
|
|
18
18
|
while (packageRoot !== path.dirname(packageRoot)) {
|
|
19
19
|
if (fs.existsSync(path.join(packageRoot, "package.json"))) break;
|
|
@@ -128,7 +128,7 @@ const logMiddleware = (pathsToLog) => {
|
|
|
128
128
|
return (req, res, next) => {
|
|
129
129
|
if (!pathsToLog || pathsToLog.some((path$1) => req.url.startsWith(path$1))) {
|
|
130
130
|
const startTime = Date.now();
|
|
131
|
-
const url = req.url;
|
|
131
|
+
const url$1 = req.url;
|
|
132
132
|
const method = req.method;
|
|
133
133
|
const clientIP = req.headers["x-forwarded-for"] ?? req.socket.remoteAddress;
|
|
134
134
|
const referer = req.headers["referer"] ?? req.headers["referrer"] ?? "-";
|
|
@@ -142,7 +142,7 @@ const logMiddleware = (pathsToLog) => {
|
|
|
142
142
|
const responseSize = res.get("content-length") ?? "0";
|
|
143
143
|
const logData = {
|
|
144
144
|
method,
|
|
145
|
-
url,
|
|
145
|
+
url: url$1,
|
|
146
146
|
statusCode,
|
|
147
147
|
responseTime: `${responseTime}ms`,
|
|
148
148
|
clientIP,
|
|
@@ -861,9 +861,9 @@ const getWbiKeys = async (cookie) => {
|
|
|
861
861
|
*/
|
|
862
862
|
const wbi_sign = async (BASEURL, cookie) => {
|
|
863
863
|
const web_keys = await getWbiKeys(cookie);
|
|
864
|
-
const url = new URL(BASEURL);
|
|
864
|
+
const url$1 = new URL(BASEURL);
|
|
865
865
|
const params = {};
|
|
866
|
-
for (const [key, value] of url.searchParams.entries()) params[key] = value;
|
|
866
|
+
for (const [key, value] of url$1.searchParams.entries()) params[key] = value;
|
|
867
867
|
return encWbi(params, web_keys.img_key, web_keys.sub_key);
|
|
868
868
|
};
|
|
869
869
|
|
|
@@ -940,7 +940,7 @@ const handleError = (error, requestPath) => {
|
|
|
940
940
|
platform: error.platform,
|
|
941
941
|
requestPath
|
|
942
942
|
};
|
|
943
|
-
if (error instanceof
|
|
943
|
+
if (error instanceof zod.ZodError) return handleError(ValidationError.fromZodError(error, requestPath), requestPath);
|
|
944
944
|
return {
|
|
945
945
|
code: 500,
|
|
946
946
|
message: error instanceof Error ? error.message : "未知错误",
|
|
@@ -952,8 +952,8 @@ const handleError = (error, requestPath) => {
|
|
|
952
952
|
//#endregion
|
|
953
953
|
//#region src/validation/utils.ts
|
|
954
954
|
function smartNumber(errorMessage, minValue = 1, isInteger = false) {
|
|
955
|
-
if (isInteger) return
|
|
956
|
-
else return
|
|
955
|
+
if (isInteger) return zod.coerce.number({ error: errorMessage }).int({ error: `${errorMessage.replace("不能为空", "")}必须是整数,不能包含小数` }).min(minValue, { error: `${errorMessage.replace("不能为空", "")}必须大于等于${minValue}` });
|
|
956
|
+
else return zod.coerce.number({ error: errorMessage }).min(minValue, { error: `${errorMessage.replace("不能为空", "")}必须大于等于${minValue}` });
|
|
957
957
|
}
|
|
958
958
|
/**
|
|
959
959
|
* 智能正整数转换器 - 专门用于正整数类型的转换
|
|
@@ -982,18 +982,18 @@ const extractCreatorInfoFromHtml = (html) => {
|
|
|
982
982
|
|
|
983
983
|
//#endregion
|
|
984
984
|
//#region src/validation/bilibili.ts
|
|
985
|
-
const BilibiliVideoParamsSchema =
|
|
986
|
-
methodType:
|
|
987
|
-
bvid:
|
|
985
|
+
const BilibiliVideoParamsSchema = zod.object({
|
|
986
|
+
methodType: zod.literal("单个视频作品数据", { error: "方法类型必须是\"单个视频作品数据\"" }),
|
|
987
|
+
bvid: zod.string({ error: "BVID必须是字符串" }).min(1, { error: "BVID不能为空" })
|
|
988
988
|
});
|
|
989
|
-
const BilibiliVideoDownloadParamsSchema =
|
|
990
|
-
methodType:
|
|
989
|
+
const BilibiliVideoDownloadParamsSchema = zod.object({
|
|
990
|
+
methodType: zod.literal("单个视频下载信息数据", { error: "方法类型必须是\"单个视频下载信息数据\"" }),
|
|
991
991
|
avid: smartNumber("AVID不能为空", 1, true),
|
|
992
992
|
cid: smartNumber("CID不能为空", 1, true)
|
|
993
993
|
});
|
|
994
|
-
const BilibiliCommentParamsSchema =
|
|
995
|
-
methodType:
|
|
996
|
-
oid:
|
|
994
|
+
const BilibiliCommentParamsSchema = zod.object({
|
|
995
|
+
methodType: zod.literal("评论数据", { error: "方法类型必须是\"评论数据\"" }),
|
|
996
|
+
oid: zod.string({ error: "OID必须是字符串" }).min(1, { error: "OID不能为空" }),
|
|
997
997
|
type: smartNumber("评论类型不能为空", 1, true).refine((val) => [
|
|
998
998
|
1,
|
|
999
999
|
2,
|
|
@@ -1018,12 +1018,12 @@ const BilibiliCommentParamsSchema = z.object({
|
|
|
1018
1018
|
22,
|
|
1019
1019
|
33
|
|
1020
1020
|
].includes(val), { error: "无效的评论区类型" }),
|
|
1021
|
-
number:
|
|
1022
|
-
pn:
|
|
1021
|
+
number: zod.coerce.number({ error: "评论数量必须是数字" }).int({ error: "评论数量必须是整数" }).positive({ error: "评论数量必须是正数" }).default(20).optional(),
|
|
1022
|
+
pn: zod.coerce.number({ error: "页码必须是数字" }).int({ error: "页码必须是整数" }).positive({ error: "页码必须是正数" }).default(1).optional()
|
|
1023
1023
|
});
|
|
1024
|
-
const BilibiliCommentReplyParamsSchema =
|
|
1025
|
-
methodType:
|
|
1026
|
-
oid:
|
|
1024
|
+
const BilibiliCommentReplyParamsSchema = zod.object({
|
|
1025
|
+
methodType: zod.literal("指定评论的回复", { error: "方法类型必须是\"指定评论的回复\"" }),
|
|
1026
|
+
oid: zod.string({ error: "OID必须是字符串" }).min(1, { error: "OID不能为空" }),
|
|
1027
1027
|
type: smartNumber("评论类型不能为空", 1, true).refine((val) => [
|
|
1028
1028
|
1,
|
|
1029
1029
|
2,
|
|
@@ -1048,69 +1048,69 @@ const BilibiliCommentReplyParamsSchema = z.object({
|
|
|
1048
1048
|
22,
|
|
1049
1049
|
33
|
|
1050
1050
|
].includes(val), { error: "无效的评论区类型" }),
|
|
1051
|
-
root:
|
|
1052
|
-
number:
|
|
1053
|
-
pn:
|
|
1051
|
+
root: zod.string({ error: "根评论ID必须是字符串" }).min(1, { error: "根评论ID不能为空" }),
|
|
1052
|
+
number: zod.coerce.number({ error: "评论数量必须是数字" }).int({ error: "评论数量必须是整数" }).positive({ error: "评论数量必须是正数" }).default(20).optional(),
|
|
1053
|
+
pn: zod.coerce.number({ error: "页码必须是数字" }).int({ error: "页码必须是整数" }).positive({ error: "页码必须是正数" }).default(1).optional()
|
|
1054
1054
|
});
|
|
1055
|
-
const BilibiliUserParamsSchema =
|
|
1056
|
-
methodType:
|
|
1055
|
+
const BilibiliUserParamsSchema = zod.object({
|
|
1056
|
+
methodType: zod.enum([
|
|
1057
1057
|
"用户主页数据",
|
|
1058
1058
|
"用户主页动态列表数据",
|
|
1059
1059
|
"获取UP主总播放量"
|
|
1060
1060
|
], { error: "方法类型必须是指定的枚举值之一" }),
|
|
1061
1061
|
host_mid: smartNumber("UP主UID不能为空", 1, true)
|
|
1062
1062
|
});
|
|
1063
|
-
const BilibiliEmojiParamsSchema =
|
|
1064
|
-
const BilibiliBangumiInfoParamsSchema =
|
|
1065
|
-
methodType:
|
|
1066
|
-
ep_id:
|
|
1067
|
-
season_id:
|
|
1063
|
+
const BilibiliEmojiParamsSchema = zod.object({ methodType: zod.literal("Emoji数据", { error: "方法类型必须是\"Emoji数据\"" }) });
|
|
1064
|
+
const BilibiliBangumiInfoParamsSchema = zod.object({
|
|
1065
|
+
methodType: zod.literal("番剧基本信息数据", { error: "方法类型必须是\"番剧基本信息数据\"" }),
|
|
1066
|
+
ep_id: zod.string({ error: "番剧EP ID必须是字符串" }).min(1, { error: "番剧EP ID不能为空" }).optional(),
|
|
1067
|
+
season_id: zod.string({ error: "番剧季度ID必须是字符串" }).optional()
|
|
1068
1068
|
}).refine((data$1) => data$1.ep_id ?? data$1.season_id, {
|
|
1069
1069
|
error: "ep_id 和 season_id 至少需要提供一个",
|
|
1070
1070
|
path: ["ep_id"]
|
|
1071
1071
|
});
|
|
1072
|
-
const BilibiliBangumiStreamParamsSchema =
|
|
1073
|
-
methodType:
|
|
1072
|
+
const BilibiliBangumiStreamParamsSchema = zod.object({
|
|
1073
|
+
methodType: zod.literal("番剧下载信息数据", { error: "方法类型必须是\"番剧下载信息数据\"" }),
|
|
1074
1074
|
cid: smartNumber("CID不能为空", 1, true),
|
|
1075
|
-
ep_id:
|
|
1075
|
+
ep_id: zod.string({ error: "番剧EP ID必须是字符串" }).min(1, { error: "番剧EP ID不能为空" })
|
|
1076
1076
|
});
|
|
1077
|
-
const BilibiliDynamicParamsSchema =
|
|
1078
|
-
methodType:
|
|
1079
|
-
dynamic_id:
|
|
1077
|
+
const BilibiliDynamicParamsSchema = zod.object({
|
|
1078
|
+
methodType: zod.enum(["动态详情数据", "动态卡片数据"], { error: "方法类型必须是\"动态详情数据\"或\"动态卡片数据\"" }),
|
|
1079
|
+
dynamic_id: zod.string({ error: "动态ID必须是字符串" }).min(1, { error: "动态ID不能为空" })
|
|
1080
1080
|
});
|
|
1081
|
-
const BilibiliLiveParamsSchema =
|
|
1082
|
-
methodType:
|
|
1083
|
-
room_id:
|
|
1081
|
+
const BilibiliLiveParamsSchema = zod.object({
|
|
1082
|
+
methodType: zod.enum(["直播间信息", "直播间初始化信息"], { error: "方法类型必须是\"直播间信息\"或\"直播间初始化信息\"" }),
|
|
1083
|
+
room_id: zod.string({ error: "直播间ID必须是字符串" }).min(1, { error: "直播间ID不能为空" })
|
|
1084
1084
|
});
|
|
1085
|
-
const BilibiliLoginParamsSchema =
|
|
1086
|
-
const BilibiliQrcodeParamsSchema =
|
|
1087
|
-
const BilibiliQrcodeStatusParamsSchema =
|
|
1088
|
-
methodType:
|
|
1089
|
-
qrcode_key:
|
|
1085
|
+
const BilibiliLoginParamsSchema = zod.object({ methodType: zod.literal("登录基本信息", { error: "方法类型必须是\"登录基本信息\"" }) });
|
|
1086
|
+
const BilibiliQrcodeParamsSchema = zod.object({ methodType: zod.literal("申请二维码", { error: "方法类型必须是\"申请二维码\"" }) });
|
|
1087
|
+
const BilibiliQrcodeStatusParamsSchema = zod.object({
|
|
1088
|
+
methodType: zod.literal("二维码状态", { error: "方法类型必须是\"二维码状态\"" }),
|
|
1089
|
+
qrcode_key: zod.string({ error: "二维码key必须是字符串" }).min(1, { error: "二维码key不能为空" })
|
|
1090
1090
|
});
|
|
1091
|
-
const BilibiliAv2BvParamsSchema =
|
|
1092
|
-
methodType:
|
|
1093
|
-
avid:
|
|
1091
|
+
const BilibiliAv2BvParamsSchema = zod.object({
|
|
1092
|
+
methodType: zod.literal("AV转BV", { error: "方法类型必须是\"AV转BV\"" }),
|
|
1093
|
+
avid: zod.coerce.number({ error: "AVID必须是数字" }).int({ error: "AVID必须是整数" }).positive({ error: "AVID必须是正数" })
|
|
1094
1094
|
});
|
|
1095
|
-
const BilibiliBv2AvParamsSchema =
|
|
1096
|
-
methodType:
|
|
1097
|
-
bvid:
|
|
1095
|
+
const BilibiliBv2AvParamsSchema = zod.object({
|
|
1096
|
+
methodType: zod.literal("BV转AV", { error: "方法类型必须是\"BV转AV\"" }),
|
|
1097
|
+
bvid: zod.string({ error: "BVID必须是字符串" }).min(1, { error: "BVID不能为空" })
|
|
1098
1098
|
});
|
|
1099
|
-
const BilibiliArticleParamsSchema =
|
|
1100
|
-
methodType:
|
|
1101
|
-
id:
|
|
1099
|
+
const BilibiliArticleParamsSchema = zod.object({
|
|
1100
|
+
methodType: zod.literal("专栏正文内容", { error: "方法类型必须是\"专栏正文内容\"" }),
|
|
1101
|
+
id: zod.string({ error: "专栏ID必须是字符串" }).min(1, { error: "专栏ID不能为空" })
|
|
1102
1102
|
});
|
|
1103
|
-
const BilibiliArticleCardParamsSchema =
|
|
1104
|
-
methodType:
|
|
1105
|
-
ids:
|
|
1103
|
+
const BilibiliArticleCardParamsSchema = zod.object({
|
|
1104
|
+
methodType: zod.literal("专栏显示卡片信息", { error: "方法类型必须是\"专栏显示卡片信息\"" }),
|
|
1105
|
+
ids: zod.union([zod.array(zod.string({ error: "被查询的 id 列表必须是字符串数组" })).min(1, { error: "被查询的 id 列表不能为空" }), zod.string({ error: "被查询的 id 列表必须是字符串" }).min(1, { error: "被查询的 id 列表不能为空" })])
|
|
1106
1106
|
});
|
|
1107
|
-
const BilibiliArticleInfoParamsSchema =
|
|
1108
|
-
methodType:
|
|
1109
|
-
id:
|
|
1107
|
+
const BilibiliArticleInfoParamsSchema = zod.object({
|
|
1108
|
+
methodType: zod.literal("专栏文章基本信息", { error: "方法类型必须是\"专栏文章基本信息\"" }),
|
|
1109
|
+
id: zod.string({ error: "专栏ID必须是字符串" }).min(1, { error: "专栏ID不能为空" })
|
|
1110
1110
|
});
|
|
1111
|
-
const BilibiliColumnInfoParamsSchema =
|
|
1112
|
-
methodType:
|
|
1113
|
-
id:
|
|
1111
|
+
const BilibiliColumnInfoParamsSchema = zod.object({
|
|
1112
|
+
methodType: zod.literal("文集基本信息", { error: "方法类型必须是\"文集基本信息\"" }),
|
|
1113
|
+
id: zod.string({ error: "文集ID必须是字符串" }).min(1, { error: "文集ID不能为空" })
|
|
1114
1114
|
});
|
|
1115
1115
|
const BilibiliValidationSchemas = {
|
|
1116
1116
|
单个视频作品数据: BilibiliVideoParamsSchema,
|
|
@@ -1137,62 +1137,87 @@ const BilibiliValidationSchemas = {
|
|
|
1137
1137
|
专栏文章基本信息: BilibiliArticleInfoParamsSchema,
|
|
1138
1138
|
文集基本信息: BilibiliColumnInfoParamsSchema
|
|
1139
1139
|
};
|
|
1140
|
+
const BilibiliMethodRoutes = {
|
|
1141
|
+
单个视频作品数据: "/fetch_one_video",
|
|
1142
|
+
单个视频下载信息数据: "/fetch_video_playurl",
|
|
1143
|
+
评论数据: "/fetch_work_comments",
|
|
1144
|
+
指定评论的回复: "/fetch_comment_reply",
|
|
1145
|
+
用户主页数据: "/fetch_user_profile",
|
|
1146
|
+
用户主页动态列表数据: "/fetch_user_dynamic",
|
|
1147
|
+
Emoji数据: "/fetch_emoji_list",
|
|
1148
|
+
番剧基本信息数据: "/fetch_bangumi_video_info",
|
|
1149
|
+
番剧下载信息数据: "/fetch_bangumi_video_playurl",
|
|
1150
|
+
动态详情数据: "/fetch_dynamic_info",
|
|
1151
|
+
动态卡片数据: "/fetch_dynamic_card",
|
|
1152
|
+
直播间信息: "/fetch_live_room_detail",
|
|
1153
|
+
直播间初始化信息: "/fetch_liveroom_def",
|
|
1154
|
+
登录基本信息: "/login_basic_info",
|
|
1155
|
+
申请二维码: "/new_login_qrcode",
|
|
1156
|
+
二维码状态: "/check_qrcode",
|
|
1157
|
+
获取UP主总播放量: "/fetch_user_full_view",
|
|
1158
|
+
AV转BV: "/av_to_bv",
|
|
1159
|
+
BV转AV: "/bv_to_av",
|
|
1160
|
+
专栏正文内容: "/fetch_article_content",
|
|
1161
|
+
专栏显示卡片信息: "/fetch_article_card",
|
|
1162
|
+
专栏文章基本信息: "/fetch_article_info",
|
|
1163
|
+
文集基本信息: "/fetch_column_info"
|
|
1164
|
+
};
|
|
1140
1165
|
|
|
1141
1166
|
//#endregion
|
|
1142
1167
|
//#region src/validation/douyin.ts
|
|
1143
|
-
const DouyinWorkParamsSchema =
|
|
1144
|
-
methodType:
|
|
1145
|
-
"文字作品数据",
|
|
1168
|
+
const DouyinWorkParamsSchema = zod.object({
|
|
1169
|
+
methodType: zod.enum([
|
|
1146
1170
|
"视频作品数据",
|
|
1147
1171
|
"图集作品数据",
|
|
1148
1172
|
"合辑作品数据",
|
|
1149
1173
|
"聚合解析"
|
|
1150
1174
|
], { error: "方法类型必须是指定的枚举值之一" }),
|
|
1151
|
-
aweme_id:
|
|
1175
|
+
aweme_id: zod.string({ error: "视频ID必须是字符串" }).min(1, { error: "视频ID不能为空" })
|
|
1152
1176
|
});
|
|
1153
|
-
const DouyinCommentParamsSchema =
|
|
1154
|
-
methodType:
|
|
1155
|
-
aweme_id:
|
|
1177
|
+
const DouyinCommentParamsSchema = zod.object({
|
|
1178
|
+
methodType: zod.literal("评论数据", { error: "方法类型必须是\"评论数据\"" }),
|
|
1179
|
+
aweme_id: zod.string({ error: "视频ID必须是字符串" }).min(1, { error: "视频ID不能为空" }),
|
|
1156
1180
|
number: smartPositiveInteger("评论数量必须是正整数").optional().default(50),
|
|
1157
|
-
cursor:
|
|
1181
|
+
cursor: zod.coerce.number({ error: "游标必须是数字" }).int({ error: "游标必须是整数" }).min(0, { error: "游标不能小于0" }).default(0).optional()
|
|
1158
1182
|
});
|
|
1159
|
-
const DouyinSearchParamsSchema =
|
|
1160
|
-
methodType:
|
|
1161
|
-
query:
|
|
1183
|
+
const DouyinSearchParamsSchema = zod.object({
|
|
1184
|
+
methodType: zod.enum(["热点词数据", "搜索数据"], { error: "方法类型必须是\"热点词数据\"或\"搜索数据\"" }),
|
|
1185
|
+
query: zod.string({ error: "搜索词必须是字符串" }).min(1, { error: "搜索词不能为空" }),
|
|
1162
1186
|
number: smartPositiveInteger("搜索数量必须是正整数").optional().default(10),
|
|
1163
|
-
search_id:
|
|
1187
|
+
search_id: zod.string({ error: "搜索ID必须是字符串" }).optional()
|
|
1164
1188
|
});
|
|
1165
|
-
const DouyinCommentReplyParamsSchema =
|
|
1166
|
-
methodType:
|
|
1167
|
-
aweme_id:
|
|
1168
|
-
comment_id:
|
|
1189
|
+
const DouyinCommentReplyParamsSchema = zod.object({
|
|
1190
|
+
methodType: zod.literal("指定评论回复数据", { error: "方法类型必须是\"指定评论回复数据\"" }),
|
|
1191
|
+
aweme_id: zod.string({ error: "视频ID必须是字符串" }).min(1, { error: "视频ID不能为空" }),
|
|
1192
|
+
comment_id: zod.string({ error: "评论ID必须z串" }).min(1, { error: "评论ID不能为空" }),
|
|
1169
1193
|
number: smartPositiveInteger("评论数量必须是正整数").optional().default(5),
|
|
1170
|
-
cursor:
|
|
1194
|
+
cursor: zod.coerce.number({ error: "游标必须是数字" }).int({ error: "游标必须是整数" }).min(0, { error: "游标不能小于0" }).default(0).optional()
|
|
1171
1195
|
});
|
|
1172
|
-
const DouyinUserParamsSchema =
|
|
1173
|
-
methodType:
|
|
1174
|
-
|
|
1175
|
-
"用户主页视频列表数据",
|
|
1176
|
-
"直播间信息数据"
|
|
1177
|
-
], { error: "方法类型必须是指定的枚举值之一" }),
|
|
1178
|
-
sec_uid: z.string({ error: "用户ID必须是字符串" }).min(1, { error: "用户ID不能为空" })
|
|
1196
|
+
const DouyinUserParamsSchema = zod.object({
|
|
1197
|
+
methodType: zod.enum(["用户主页数据", "用户主页视频列表数据"], { error: "方法类型必须是指定的枚举值之一" }),
|
|
1198
|
+
sec_uid: zod.string({ error: "用户ID必须是字符串" }).min(1, { error: "用户ID不能为空" })
|
|
1179
1199
|
});
|
|
1180
|
-
const DouyinMusicParamsSchema =
|
|
1181
|
-
methodType:
|
|
1182
|
-
music_id:
|
|
1200
|
+
const DouyinMusicParamsSchema = zod.object({
|
|
1201
|
+
methodType: zod.literal("音乐数据", { error: "方法类型必须是\"音乐数据\"" }),
|
|
1202
|
+
music_id: zod.string({ error: "音乐ID必须是字符串" }).min(1, { error: "音乐ID不能为空" })
|
|
1183
1203
|
});
|
|
1184
|
-
const
|
|
1185
|
-
methodType:
|
|
1186
|
-
|
|
1204
|
+
const DouyinLiveRoomParamsSchema = zod.object({
|
|
1205
|
+
methodType: zod.literal("直播间信息数据", { error: "方法类型必须是\"直播间信息数据\"" }),
|
|
1206
|
+
web_rid: zod.string({ error: "直播间ID必须是字符串" }).min(1, { error: "直播间ID不能为空" }),
|
|
1207
|
+
room_id: zod.string({ error: "直播间ID必须是字符串" }).min(1, { error: "直播间ID不能为空" })
|
|
1187
1208
|
});
|
|
1188
|
-
const
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1209
|
+
const DouyinQrcodeParamsSchema = zod.object({
|
|
1210
|
+
methodType: zod.literal("申请二维码数据", { error: "方法类型必须是\"申请二维码数据\"" }),
|
|
1211
|
+
verify_fp: zod.string({ error: "fp指纹必须是字符串" }).min(1, { error: "fp指纹不能为空" })
|
|
1212
|
+
});
|
|
1213
|
+
const DouyinEmojiListParamsSchema = zod.object({ methodType: zod.literal("Emoji数据", { error: "方法类型必须是\"Emoji数据\"" }) });
|
|
1214
|
+
const DouyinEmojiProParamsSchema = zod.object({ methodType: zod.literal("动态表情数据", { error: "方法类型必须是\"动态表情数据\"" }) });
|
|
1215
|
+
const DouyinDanmakuParamsSchema = zod.object({
|
|
1216
|
+
methodType: zod.literal("弹幕数据", { error: "方法类型必须是\"弹幕数据\"" }),
|
|
1217
|
+
aweme_id: zod.string({ error: "视频ID必须是字符串" }).min(1, { error: "视频ID不能为空" }),
|
|
1218
|
+
start_time: zod.coerce.number({ error: "开始时间必须是数字" }).int({ error: "开始时间必须是整数" }).min(0, { error: "开始时间不能小于0" }).optional(),
|
|
1219
|
+
end_time: zod.coerce.number({ error: "结束时间必须是数字" }).int({ error: "结束时间必须是整数" }).min(0, { error: "结束时间不能小于0" }).optional(),
|
|
1220
|
+
duration: zod.coerce.number({ error: "视频时长必须是数字" }).int({ error: "视频时长必须是整数" }).min(0, { error: "视频时长不能小于0" })
|
|
1196
1221
|
}).refine((data$1) => {
|
|
1197
1222
|
if (data$1.end_time !== void 0) return data$1.end_time <= data$1.duration;
|
|
1198
1223
|
return true;
|
|
@@ -1218,30 +1243,53 @@ const DouyinValidationSchemas = {
|
|
|
1218
1243
|
热点词数据: DouyinSearchParamsSchema,
|
|
1219
1244
|
搜索数据: DouyinSearchParamsSchema,
|
|
1220
1245
|
音乐数据: DouyinMusicParamsSchema,
|
|
1221
|
-
直播间信息数据:
|
|
1246
|
+
直播间信息数据: DouyinLiveRoomParamsSchema,
|
|
1222
1247
|
申请二维码数据: DouyinQrcodeParamsSchema,
|
|
1223
1248
|
Emoji数据: DouyinEmojiListParamsSchema,
|
|
1224
1249
|
动态表情数据: DouyinEmojiProParamsSchema,
|
|
1225
1250
|
指定评论回复数据: DouyinCommentReplyParamsSchema,
|
|
1226
1251
|
弹幕数据: DouyinDanmakuParamsSchema
|
|
1227
1252
|
};
|
|
1253
|
+
const DouyinMethodRoutes = {
|
|
1254
|
+
聚合解析: "/fetch_one_work",
|
|
1255
|
+
文字作品数据: "/fetch_one_work",
|
|
1256
|
+
视频作品数据: "/fetch_one_work",
|
|
1257
|
+
图集作品数据: "/fetch_one_work",
|
|
1258
|
+
合辑作品数据: "/fetch_one_work",
|
|
1259
|
+
评论数据: "/fetch_work_comments",
|
|
1260
|
+
用户主页数据: "/fetch_user_info",
|
|
1261
|
+
用户主页视频列表数据: "/fetch_user_post_videos",
|
|
1262
|
+
搜索数据: "/fetch_search_info",
|
|
1263
|
+
热点词数据: "/fetch_suggest_words",
|
|
1264
|
+
音乐数据: "/fetch_music_work",
|
|
1265
|
+
Emoji数据: "/fetch_emoji_list",
|
|
1266
|
+
动态表情数据: "/fetch_emoji_pro_list",
|
|
1267
|
+
直播间信息数据: "/fetch_user_live_videos",
|
|
1268
|
+
指定评论回复数据: "/fetch_video_comment_replies",
|
|
1269
|
+
弹幕数据: "/fetch_work_danmaku"
|
|
1270
|
+
};
|
|
1228
1271
|
|
|
1229
1272
|
//#endregion
|
|
1230
1273
|
//#region src/validation/kuaishou.ts
|
|
1231
|
-
const KuaishouVideoParamsSchema =
|
|
1232
|
-
methodType:
|
|
1233
|
-
photoId:
|
|
1274
|
+
const KuaishouVideoParamsSchema = zod.object({
|
|
1275
|
+
methodType: zod.literal("单个视频作品数据", { error: "方法类型必须是\"单个视频作品数据\"" }),
|
|
1276
|
+
photoId: zod.string({ error: "视频ID必须是字符串" }).min(1, { error: "视频ID不能为空" })
|
|
1234
1277
|
});
|
|
1235
|
-
const KuaishouCommentParamsSchema =
|
|
1236
|
-
methodType:
|
|
1237
|
-
photoId:
|
|
1278
|
+
const KuaishouCommentParamsSchema = zod.object({
|
|
1279
|
+
methodType: zod.literal("评论数据", { error: "方法类型必须是\"评论数据\"" }),
|
|
1280
|
+
photoId: zod.string({ error: "视频ID必须是字符串" }).min(1, { error: "视频ID不能为空" })
|
|
1238
1281
|
});
|
|
1239
|
-
const KuaishouEmojiParamsSchema =
|
|
1282
|
+
const KuaishouEmojiParamsSchema = zod.object({ methodType: zod.literal("Emoji数据", { error: "方法类型必须是\"Emoji数据\"" }) });
|
|
1240
1283
|
const KuaishouValidationSchemas = {
|
|
1241
1284
|
单个视频作品数据: KuaishouVideoParamsSchema,
|
|
1242
1285
|
评论数据: KuaishouCommentParamsSchema,
|
|
1243
1286
|
Emoji数据: KuaishouEmojiParamsSchema
|
|
1244
1287
|
};
|
|
1288
|
+
const KuaishouMethodRoutes = {
|
|
1289
|
+
单个视频作品数据: "/fetch_one_work",
|
|
1290
|
+
评论数据: "/fetch_work_comments",
|
|
1291
|
+
Emoji数据: "/fetch_emoji_list"
|
|
1292
|
+
};
|
|
1245
1293
|
|
|
1246
1294
|
//#endregion
|
|
1247
1295
|
//#region src/platform/xiaohongshu/sign/index.ts
|
|
@@ -1281,9 +1329,9 @@ var xiaohongshuSign = class {
|
|
|
1281
1329
|
* @param a1Cookie - a1 cookie值
|
|
1282
1330
|
* @returns X-S签名
|
|
1283
1331
|
*/
|
|
1284
|
-
static generateXS(url, body, userAgent, method = "POST", a1Cookie = "") {
|
|
1332
|
+
static generateXS(url$1, body, userAgent, method = "POST", a1Cookie = "") {
|
|
1285
1333
|
try {
|
|
1286
|
-
const urlObj = new URL(url);
|
|
1334
|
+
const urlObj = new URL(url$1);
|
|
1287
1335
|
const path$1 = urlObj.pathname + urlObj.search;
|
|
1288
1336
|
if (method.toUpperCase() === "GET") {
|
|
1289
1337
|
const params = typeof body === "object" ? body : {};
|
|
@@ -1499,59 +1547,59 @@ const SearchNoteTypeValues = Object.values(SearchNoteType).filter((v) => typeof
|
|
|
1499
1547
|
/**
|
|
1500
1548
|
* 小红书首页推荐数据参数验证模式
|
|
1501
1549
|
*/
|
|
1502
|
-
const HomeFeedParamsSchema =
|
|
1503
|
-
methodType:
|
|
1504
|
-
cursor_score:
|
|
1505
|
-
num:
|
|
1506
|
-
refresh_type:
|
|
1507
|
-
note_index:
|
|
1508
|
-
category:
|
|
1509
|
-
search_key:
|
|
1550
|
+
const HomeFeedParamsSchema = zod.object({
|
|
1551
|
+
methodType: zod.literal("首页推荐数据", { error: "方法类型必须是\"首页推荐数据\"" }),
|
|
1552
|
+
cursor_score: zod.string({ error: "cursor_score必须是字符串" }).optional(),
|
|
1553
|
+
num: zod.coerce.number({ error: "数量必须是数字" }).int({ error: "数量必须是整数" }).min(1, { error: "数量不能小于1" }).max(100, { error: "数量不能大于100" }).optional(),
|
|
1554
|
+
refresh_type: zod.coerce.number({ error: "refresh_type必须是数字" }).int({ error: "refresh_type必须是整数" }).optional(),
|
|
1555
|
+
note_index: zod.coerce.number({ error: "note_index必须是数字" }).int({ error: "note_index必须是整数" }).optional(),
|
|
1556
|
+
category: zod.string({ error: "category必须是字符串" }).optional(),
|
|
1557
|
+
search_key: zod.string({ error: "search_key必须是字符串" }).optional()
|
|
1510
1558
|
});
|
|
1511
1559
|
/**
|
|
1512
1560
|
* 小红书单个笔记数据参数验证模式
|
|
1513
1561
|
*/
|
|
1514
|
-
const NoteParamsSchema =
|
|
1515
|
-
methodType:
|
|
1516
|
-
note_id:
|
|
1517
|
-
xsec_token:
|
|
1562
|
+
const NoteParamsSchema = zod.object({
|
|
1563
|
+
methodType: zod.literal("单个笔记数据", { error: "方法类型必须是\"单个笔记数据\"" }),
|
|
1564
|
+
note_id: zod.string({ error: "note_id必须是字符串" }),
|
|
1565
|
+
xsec_token: zod.string({ error: "xsec_token必须是字符串" })
|
|
1518
1566
|
});
|
|
1519
1567
|
/**
|
|
1520
1568
|
* 小红书评论数据参数验证模式
|
|
1521
1569
|
*/
|
|
1522
|
-
const CommentParamsSchema =
|
|
1523
|
-
methodType:
|
|
1524
|
-
note_id:
|
|
1525
|
-
cursor:
|
|
1526
|
-
xsec_token:
|
|
1570
|
+
const CommentParamsSchema = zod.object({
|
|
1571
|
+
methodType: zod.literal("评论数据", { error: "方法类型必须是\"评论数据\"" }),
|
|
1572
|
+
note_id: zod.string({ error: "note_id必须是字符串" }),
|
|
1573
|
+
cursor: zod.string({ error: "cursor必须是字符串" }).optional(),
|
|
1574
|
+
xsec_token: zod.string({ error: "xsec_token必须是字符串" })
|
|
1527
1575
|
});
|
|
1528
1576
|
/**
|
|
1529
1577
|
* 小红书用户数据参数验证模式
|
|
1530
1578
|
*/
|
|
1531
|
-
const UserParamsSchema =
|
|
1532
|
-
methodType:
|
|
1533
|
-
user_id:
|
|
1579
|
+
const UserParamsSchema = zod.object({
|
|
1580
|
+
methodType: zod.literal("用户数据", { error: "方法类型必须是\"用户数据\"" }),
|
|
1581
|
+
user_id: zod.string({ error: "user_id必须是字符串" })
|
|
1534
1582
|
});
|
|
1535
1583
|
/**
|
|
1536
1584
|
* 小红书用户笔记数据参数验证模式
|
|
1537
1585
|
*/
|
|
1538
|
-
const UserNoteParamsSchema =
|
|
1539
|
-
methodType:
|
|
1540
|
-
user_id:
|
|
1541
|
-
cursor:
|
|
1542
|
-
num:
|
|
1586
|
+
const UserNoteParamsSchema = zod.object({
|
|
1587
|
+
methodType: zod.literal("用户笔记数据", { error: "方法类型必须是\"用户笔记数据\"" }),
|
|
1588
|
+
user_id: zod.string({ error: "user_id必须是字符串" }),
|
|
1589
|
+
cursor: zod.string({ error: "cursor必须是字符串" }).optional(),
|
|
1590
|
+
num: zod.coerce.number({ error: "数量必须是数字" }).int({ error: "数量必须是整数" }).min(1, { error: "数量不能小于1" }).max(100, { error: "数量不能大于100" }).optional()
|
|
1543
1591
|
});
|
|
1544
|
-
const EmojiListParamsSchema =
|
|
1592
|
+
const EmojiListParamsSchema = zod.object({ methodType: zod.literal("表情列表", { error: "方法类型必须是\"表情列表\"" }) });
|
|
1545
1593
|
/**
|
|
1546
1594
|
* 小红书搜索笔记参数验证模式
|
|
1547
1595
|
*/
|
|
1548
|
-
const SearchNoteParamsSchema =
|
|
1549
|
-
methodType:
|
|
1550
|
-
keyword:
|
|
1551
|
-
page:
|
|
1552
|
-
page_size:
|
|
1553
|
-
sort:
|
|
1554
|
-
note_type:
|
|
1596
|
+
const SearchNoteParamsSchema = zod.object({
|
|
1597
|
+
methodType: zod.literal("搜索笔记", { error: "方法类型必须是\"搜索笔记\"" }),
|
|
1598
|
+
keyword: zod.string({ error: "keyword必须是字符串" }),
|
|
1599
|
+
page: zod.coerce.number({ error: "page必须是数字" }).int({ error: "page必须是整数" }).min(1, { error: "page不能小于1" }).optional(),
|
|
1600
|
+
page_size: zod.coerce.number({ error: "page_size必须是数字" }).int({ error: "page_size必须是整数" }).min(1, { error: "page_size不能小于1" }).max(100, { error: "page_size不能大于100" }).optional(),
|
|
1601
|
+
sort: zod.enum(SearchSortTypeValues, { error: "排序类型不合法" }).optional(),
|
|
1602
|
+
note_type: zod.coerce.number({ error: "笔记类型必须是数字" }).int({ error: "笔记类型必须是整数" }).refine((val) => SearchNoteTypeValues.includes(val), { message: "笔记类型不合法" }).optional()
|
|
1555
1603
|
});
|
|
1556
1604
|
/**
|
|
1557
1605
|
* 小红书验证模式映射
|
|
@@ -1566,19 +1614,16 @@ const XiaohongshuValidationSchemas = {
|
|
|
1566
1614
|
搜索笔记: SearchNoteParamsSchema
|
|
1567
1615
|
};
|
|
1568
1616
|
/**
|
|
1569
|
-
*
|
|
1570
|
-
* @param methodType - 小红书方法类型
|
|
1571
|
-
* @param params - 待验证的参数
|
|
1572
|
-
* @returns 验证后的参数
|
|
1617
|
+
* 小红书方法类型
|
|
1573
1618
|
*/
|
|
1574
|
-
const
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1619
|
+
const XiaohongshuMethodRoutes = {
|
|
1620
|
+
首页推荐数据: "/fetch_home_feed",
|
|
1621
|
+
单个笔记数据: "/fetch_one_note",
|
|
1622
|
+
评论数据: "/fetch_note_comments",
|
|
1623
|
+
用户数据: "/fetch_user_profile",
|
|
1624
|
+
用户笔记数据: "/fetch_user_notes",
|
|
1625
|
+
表情列表: "/fetch_emoji_list",
|
|
1626
|
+
搜索笔记: "/fetch_search_notes"
|
|
1582
1627
|
};
|
|
1583
1628
|
|
|
1584
1629
|
//#endregion
|
|
@@ -1629,6 +1674,21 @@ const validateKuaishouParams = (methodType, params) => {
|
|
|
1629
1674
|
});
|
|
1630
1675
|
};
|
|
1631
1676
|
/**
|
|
1677
|
+
* 验证小红书参数
|
|
1678
|
+
* @param methodType - 小红书方法类型
|
|
1679
|
+
* @param params - 待验证的参数
|
|
1680
|
+
* @returns 验证后的参数
|
|
1681
|
+
*/
|
|
1682
|
+
const validateXiaohongshuParams = (methodType, params) => {
|
|
1683
|
+
return XiaohongshuValidationSchemas[methodType].parse(typeof params === "object" && params !== null ? {
|
|
1684
|
+
methodType,
|
|
1685
|
+
...params
|
|
1686
|
+
} : {
|
|
1687
|
+
methodType,
|
|
1688
|
+
params
|
|
1689
|
+
});
|
|
1690
|
+
};
|
|
1691
|
+
/**
|
|
1632
1692
|
* 创建成功响应格式
|
|
1633
1693
|
* @param data - 响应数据
|
|
1634
1694
|
* @param message - 响应消息(可选)
|
|
@@ -1741,30 +1801,8 @@ const createBilibiliRouteHandler = (dataFetcher, methodType, cookie, requestConf
|
|
|
1741
1801
|
* @returns Express路由器
|
|
1742
1802
|
*/
|
|
1743
1803
|
const createBilibiliRoutes = (cookie, requestConfig = getBilibiliDefaultConfig(cookie)) => {
|
|
1744
|
-
const router = Router();
|
|
1745
|
-
router.get(
|
|
1746
|
-
router.get("/fetch_video_playurl", createBilibiliValidationMiddleware("单个视频下载信息数据"), createBilibiliRouteHandler(getBilibiliData, "单个视频下载信息数据", cookie, requestConfig));
|
|
1747
|
-
router.get("/fetch_work_comments", createBilibiliValidationMiddleware("评论数据"), createBilibiliRouteHandler(getBilibiliData, "评论数据", cookie, requestConfig));
|
|
1748
|
-
router.get("/fetch_comment_reply", createBilibiliValidationMiddleware("指定评论的回复"), createBilibiliRouteHandler(getBilibiliData, "指定评论的回复", cookie, requestConfig));
|
|
1749
|
-
router.get("/fetch_user_profile", createBilibiliValidationMiddleware("用户主页数据"), createBilibiliRouteHandler(getBilibiliData, "用户主页数据", cookie, requestConfig));
|
|
1750
|
-
router.get("/fetch_user_dynamic", createBilibiliValidationMiddleware("用户主页动态列表数据"), createBilibiliRouteHandler(getBilibiliData, "用户主页动态列表数据", cookie, requestConfig));
|
|
1751
|
-
router.get("/fetch_emoji_list", createBilibiliValidationMiddleware("Emoji数据"), createBilibiliRouteHandler(getBilibiliData, "Emoji数据", cookie, requestConfig));
|
|
1752
|
-
router.get("/fetch_bangumi_video_info", createBilibiliValidationMiddleware("番剧基本信息数据"), createBilibiliRouteHandler(getBilibiliData, "番剧基本信息数据", cookie, requestConfig));
|
|
1753
|
-
router.get("/fetch_bangumi_video_playurl", createBilibiliValidationMiddleware("番剧下载信息数据"), createBilibiliRouteHandler(getBilibiliData, "番剧下载信息数据", cookie, requestConfig));
|
|
1754
|
-
router.get("/fetch_dynamic_info", createBilibiliValidationMiddleware("动态详情数据"), createBilibiliRouteHandler(getBilibiliData, "动态详情数据", cookie, requestConfig));
|
|
1755
|
-
router.get("/fetch_dynamic_card", createBilibiliValidationMiddleware("动态卡片数据"), createBilibiliRouteHandler(getBilibiliData, "动态卡片数据", cookie, requestConfig));
|
|
1756
|
-
router.get("/fetch_live_room_detail", createBilibiliValidationMiddleware("直播间信息"), createBilibiliRouteHandler(getBilibiliData, "直播间信息", cookie, requestConfig));
|
|
1757
|
-
router.get("/fetch_liveroom_def", createBilibiliValidationMiddleware("直播间初始化信息"), createBilibiliRouteHandler(getBilibiliData, "直播间初始化信息", cookie, requestConfig));
|
|
1758
|
-
router.get("/login_basic_info", createBilibiliValidationMiddleware("登录基本信息"), createBilibiliRouteHandler(getBilibiliData, "登录基本信息", cookie, requestConfig));
|
|
1759
|
-
router.get("/new_login_qrcode", createBilibiliValidationMiddleware("申请二维码"), createBilibiliRouteHandler(getBilibiliData, "申请二维码", cookie, requestConfig));
|
|
1760
|
-
router.get("/check_qrcode", createBilibiliValidationMiddleware("二维码状态"), createBilibiliRouteHandler(getBilibiliData, "二维码状态", cookie, requestConfig));
|
|
1761
|
-
router.get("/fetch_user_full_view", createBilibiliValidationMiddleware("获取UP主总播放量"), createBilibiliRouteHandler(getBilibiliData, "获取UP主总播放量", cookie, requestConfig));
|
|
1762
|
-
router.get("/av_to_bv", createBilibiliValidationMiddleware("AV转BV"), createBilibiliRouteHandler(getBilibiliData, "AV转BV", cookie, requestConfig));
|
|
1763
|
-
router.get("/bv_to_av", createBilibiliValidationMiddleware("BV转AV"), createBilibiliRouteHandler(getBilibiliData, "BV转AV", cookie, requestConfig));
|
|
1764
|
-
router.get("/fetch_article_content", createBilibiliValidationMiddleware("专栏正文内容"), createBilibiliRouteHandler(getBilibiliData, "专栏正文内容", cookie, requestConfig));
|
|
1765
|
-
router.get("/fetch_article_card", createBilibiliValidationMiddleware("专栏显示卡片信息"), createBilibiliRouteHandler(getBilibiliData, "专栏显示卡片信息", cookie, requestConfig));
|
|
1766
|
-
router.get("/fetch_article_info", createBilibiliValidationMiddleware("专栏文章基本信息"), createBilibiliRouteHandler(getBilibiliData, "专栏文章基本信息", cookie, requestConfig));
|
|
1767
|
-
router.get("/fetch_column_info", createBilibiliValidationMiddleware("文集基本信息"), createBilibiliRouteHandler(getBilibiliData, "文集基本信息", cookie, requestConfig));
|
|
1804
|
+
const router = express.Router();
|
|
1805
|
+
for (const [method, path$1] of Object.entries(BilibiliMethodRoutes)) router.get(path$1, createBilibiliValidationMiddleware(method), createBilibiliRouteHandler(getBilibiliData, method, cookie, requestConfig));
|
|
1768
1806
|
return router;
|
|
1769
1807
|
};
|
|
1770
1808
|
|
|
@@ -1830,6 +1868,12 @@ const qtparam = async (BASEURL, cookie) => {
|
|
|
1830
1868
|
//#endregion
|
|
1831
1869
|
//#region src/platform/bilibili/getdata.ts
|
|
1832
1870
|
/**
|
|
1871
|
+
* B站数据获取模块
|
|
1872
|
+
*
|
|
1873
|
+
* 注意:为避免循环依赖,此文件直接从具体模块导入,而不是从平台 index 文件导入
|
|
1874
|
+
* 循环依赖链:DataFetchers → getdata → platform/bilibili → DataFetchers
|
|
1875
|
+
*/
|
|
1876
|
+
/**
|
|
1833
1877
|
* B站数据获取函数
|
|
1834
1878
|
* @param data - 请求数据参数
|
|
1835
1879
|
* @param cookie - 用户Cookie
|
|
@@ -2622,9 +2666,9 @@ const cleanUserAgentForSigning = (userAgent) => {
|
|
|
2622
2666
|
* @param user_agent - 用户代理字符串
|
|
2623
2667
|
* @returns 生成的a_bogus签名
|
|
2624
2668
|
*/
|
|
2625
|
-
var a_bogus_default = (url, user_agent) => {
|
|
2669
|
+
var a_bogus_default = (url$1, user_agent) => {
|
|
2626
2670
|
const cleanedUserAgent = cleanUserAgentForSigning(user_agent);
|
|
2627
|
-
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") + "=";
|
|
2671
|
+
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") + "=";
|
|
2628
2672
|
};
|
|
2629
2673
|
|
|
2630
2674
|
//#endregion
|
|
@@ -2726,8 +2770,8 @@ var XBogus = class {
|
|
|
2726
2770
|
* @param ua 可选的User-Agent,不提供则使用默认值
|
|
2727
2771
|
* @returns 包含完整URL、X-Bogus值和使用的User-Agent的元组
|
|
2728
2772
|
*/
|
|
2729
|
-
getXBogus(url, ua) {
|
|
2730
|
-
const parsedUrl = new
|
|
2773
|
+
getXBogus(url$1, ua) {
|
|
2774
|
+
const parsedUrl = new url.URL(url$1);
|
|
2731
2775
|
const urlPath = parsedUrl.pathname + parsedUrl.search;
|
|
2732
2776
|
const currentUa = ua ?? this.defaultUa;
|
|
2733
2777
|
const rc4EncryptedUa = this.rc4Encrypt(this.uaKey, currentUa);
|
|
@@ -2784,7 +2828,7 @@ var XBogus = class {
|
|
|
2784
2828
|
idx += 3;
|
|
2785
2829
|
}
|
|
2786
2830
|
return {
|
|
2787
|
-
fullUrl: url.includes("?") ? `${url}&X-Bogus=${xb}` : `${url}?X-Bogus=${xb}`,
|
|
2831
|
+
fullUrl: url$1.includes("?") ? `${url$1}&X-Bogus=${xb}` : `${url$1}?X-Bogus=${xb}`,
|
|
2788
2832
|
xbogus: xb,
|
|
2789
2833
|
userAgent: currentUa
|
|
2790
2834
|
};
|
|
@@ -2810,16 +2854,16 @@ var douyinSign = class {
|
|
|
2810
2854
|
* @param url 需要签名的地址
|
|
2811
2855
|
* @returns 对此地址签名后的URL查询参数
|
|
2812
2856
|
*/
|
|
2813
|
-
static AB(url, userAgent) {
|
|
2814
|
-
return a_bogus_default(url, userAgent ?? defaultUserAgent);
|
|
2857
|
+
static AB(url$1, userAgent) {
|
|
2858
|
+
return a_bogus_default(url$1, userAgent ?? defaultUserAgent);
|
|
2815
2859
|
}
|
|
2816
2860
|
/**
|
|
2817
2861
|
* X-Bogus 签名算法
|
|
2818
2862
|
* @param url 需要签名的地址
|
|
2819
2863
|
* @returns 对此地址签名后的URL查询参数
|
|
2820
2864
|
*/
|
|
2821
|
-
static XB(url, userAgent) {
|
|
2822
|
-
return new XBogus().getXBogus(url, userAgent ?? defaultUserAgent).xbogus;
|
|
2865
|
+
static XB(url$1, userAgent) {
|
|
2866
|
+
return new XBogus().getXBogus(url$1, userAgent ?? defaultUserAgent).xbogus;
|
|
2823
2867
|
}
|
|
2824
2868
|
/** 生成一个唯一的验证字符串 */
|
|
2825
2869
|
static VerifyFpManager() {
|
|
@@ -3285,17 +3329,23 @@ const douyinApiUrls = new DouyinAPI();
|
|
|
3285
3329
|
//#endregion
|
|
3286
3330
|
//#region src/platform/douyin/getdata.ts
|
|
3287
3331
|
/**
|
|
3332
|
+
* 抖音数据获取模块
|
|
3333
|
+
*
|
|
3334
|
+
* 注意:为避免循环依赖,此文件直接从具体模块导入,而不是从平台 index 文件导入
|
|
3335
|
+
* 循环依赖链:DataFetchers → getdata → platform/douyin → DataFetchers
|
|
3336
|
+
*/
|
|
3337
|
+
/**
|
|
3288
3338
|
* 获取签名参数
|
|
3289
3339
|
* @param url - 需要签名的URL
|
|
3290
3340
|
* @param signType - 签名算法类型
|
|
3291
3341
|
* @param userAgent - 用户代理
|
|
3292
3342
|
* @returns 签名后的参数字符串
|
|
3293
3343
|
*/
|
|
3294
|
-
const getSignature = (url, signType = "a_bogus", userAgent) => {
|
|
3344
|
+
const getSignature = (url$1, signType = "a_bogus", userAgent) => {
|
|
3295
3345
|
switch (signType) {
|
|
3296
|
-
case "x_bogus": return douyinSign.XB(url, userAgent);
|
|
3346
|
+
case "x_bogus": return douyinSign.XB(url$1, userAgent);
|
|
3297
3347
|
case "a_bogus":
|
|
3298
|
-
default: return douyinSign.AB(url, userAgent);
|
|
3348
|
+
default: return douyinSign.AB(url$1, userAgent);
|
|
3299
3349
|
}
|
|
3300
3350
|
};
|
|
3301
3351
|
/**
|
|
@@ -3317,9 +3367,9 @@ const getSignParamName = (signType = "a_bogus") => {
|
|
|
3317
3367
|
* @param userAgent - 用户代理
|
|
3318
3368
|
* @returns 带签名的完整URL
|
|
3319
3369
|
*/
|
|
3320
|
-
const buildSignedUrl = (url, signType = "a_bogus", userAgent) => {
|
|
3321
|
-
const signature = getSignature(url, signType, userAgent);
|
|
3322
|
-
return `${url}&${getSignParamName(signType)}=${signature}`;
|
|
3370
|
+
const buildSignedUrl = (url$1, signType = "a_bogus", userAgent) => {
|
|
3371
|
+
const signature = getSignature(url$1, signType, userAgent);
|
|
3372
|
+
return `${url$1}&${getSignParamName(signType)}=${signature}`;
|
|
3323
3373
|
};
|
|
3324
3374
|
/**
|
|
3325
3375
|
* 抖音数据获取函数
|
|
@@ -3348,10 +3398,10 @@ const DouyinData = async (data$1, cookie, requestConfig) => {
|
|
|
3348
3398
|
case "视频作品数据":
|
|
3349
3399
|
case "图集作品数据":
|
|
3350
3400
|
case "合辑作品数据": {
|
|
3351
|
-
const url = douyinApiUrls$1.视频或图集({ aweme_id: data$1.aweme_id });
|
|
3401
|
+
const url$1 = douyinApiUrls$1.视频或图集({ aweme_id: data$1.aweme_id });
|
|
3352
3402
|
return await GlobalGetData$2(data$1.methodType, {
|
|
3353
3403
|
...baseRequestConfig,
|
|
3354
|
-
url: buildSignedUrl(url, signType, userAgent)
|
|
3404
|
+
url: buildSignedUrl(url$1, signType, userAgent)
|
|
3355
3405
|
});
|
|
3356
3406
|
}
|
|
3357
3407
|
case "评论数据": {
|
|
@@ -3363,7 +3413,7 @@ const DouyinData = async (data$1, cookie, requestConfig) => {
|
|
|
3363
3413
|
return await fetchPaginatedData(data$1.methodType, urlGenerator, data$1, 3, baseRequestConfig, "x_bogus");
|
|
3364
3414
|
}
|
|
3365
3415
|
case "用户主页数据": {
|
|
3366
|
-
const url = douyinApiUrls$1.用户主页信息({ sec_uid: data$1.sec_uid });
|
|
3416
|
+
const url$1 = douyinApiUrls$1.用户主页信息({ sec_uid: data$1.sec_uid });
|
|
3367
3417
|
const customConfig = {
|
|
3368
3418
|
...baseRequestConfig,
|
|
3369
3419
|
headers: {
|
|
@@ -3373,18 +3423,18 @@ const DouyinData = async (data$1, cookie, requestConfig) => {
|
|
|
3373
3423
|
};
|
|
3374
3424
|
return await GlobalGetData$2(data$1.methodType, {
|
|
3375
3425
|
...customConfig,
|
|
3376
|
-
url: buildSignedUrl(url, signType, userAgent)
|
|
3426
|
+
url: buildSignedUrl(url$1, signType, userAgent)
|
|
3377
3427
|
});
|
|
3378
3428
|
}
|
|
3379
3429
|
case "Emoji数据": {
|
|
3380
|
-
const url = douyinApiUrls$1.表情();
|
|
3430
|
+
const url$1 = douyinApiUrls$1.表情();
|
|
3381
3431
|
return await GlobalGetData$2(data$1.methodType, {
|
|
3382
3432
|
...baseRequestConfig,
|
|
3383
|
-
url
|
|
3433
|
+
url: url$1
|
|
3384
3434
|
});
|
|
3385
3435
|
}
|
|
3386
3436
|
case "用户主页视频列表数据": {
|
|
3387
|
-
const url = douyinApiUrls$1.用户主页视频({ sec_uid: data$1.sec_uid });
|
|
3437
|
+
const url$1 = douyinApiUrls$1.用户主页视频({ sec_uid: data$1.sec_uid });
|
|
3388
3438
|
const customConfig = {
|
|
3389
3439
|
...baseRequestConfig,
|
|
3390
3440
|
headers: {
|
|
@@ -3394,11 +3444,11 @@ const DouyinData = async (data$1, cookie, requestConfig) => {
|
|
|
3394
3444
|
};
|
|
3395
3445
|
return await GlobalGetData$2(data$1.methodType, {
|
|
3396
3446
|
...customConfig,
|
|
3397
|
-
url: buildSignedUrl(url, signType, userAgent)
|
|
3447
|
+
url: buildSignedUrl(url$1, signType, userAgent)
|
|
3398
3448
|
});
|
|
3399
3449
|
}
|
|
3400
3450
|
case "热点词数据": {
|
|
3401
|
-
const url = douyinApiUrls$1.热点词({
|
|
3451
|
+
const url$1 = douyinApiUrls$1.热点词({
|
|
3402
3452
|
query: data$1.query,
|
|
3403
3453
|
number: data$1.number ?? 10
|
|
3404
3454
|
});
|
|
@@ -3411,7 +3461,7 @@ const DouyinData = async (data$1, cookie, requestConfig) => {
|
|
|
3411
3461
|
};
|
|
3412
3462
|
return await GlobalGetData$2(data$1.methodType, {
|
|
3413
3463
|
...customConfig,
|
|
3414
|
-
url: buildSignedUrl(url, signType, userAgent)
|
|
3464
|
+
url: buildSignedUrl(url$1, signType, userAgent)
|
|
3415
3465
|
});
|
|
3416
3466
|
}
|
|
3417
3467
|
case "搜索数据": {
|
|
@@ -3428,19 +3478,22 @@ const DouyinData = async (data$1, cookie, requestConfig) => {
|
|
|
3428
3478
|
};
|
|
3429
3479
|
while (fetchedSearchList.length < Number(data$1.number ?? 10)) {
|
|
3430
3480
|
const requestCount = Math.min(Number(data$1.number ?? 50) - fetchedSearchList.length, maxPageSize);
|
|
3431
|
-
const url = douyinApiUrls$1.搜索({
|
|
3481
|
+
const url$1 = douyinApiUrls$1.搜索({
|
|
3432
3482
|
query: data$1.query,
|
|
3433
3483
|
number: requestCount,
|
|
3434
3484
|
search_id: search_id === "" ? void 0 : search_id
|
|
3435
3485
|
});
|
|
3436
3486
|
const raw = await GlobalGetData$2(data$1.methodType, {
|
|
3437
3487
|
...customConfig,
|
|
3438
|
-
url: buildSignedUrl(url, "x_bogus", userAgent)
|
|
3488
|
+
url: buildSignedUrl(url$1, "x_bogus", userAgent)
|
|
3439
3489
|
});
|
|
3440
3490
|
const responses = filterSearchResponses(typeof raw === "string" ? parseDouyinMultiJson(raw) : [raw]);
|
|
3441
3491
|
if (responses.length === 0) {
|
|
3442
3492
|
logger.warn("抖音搜索返回无有效数据,疑似触发反爬\n你的抖音ck可能已经失效!\n请求类型:" + data$1.methodType);
|
|
3443
|
-
return
|
|
3493
|
+
return {
|
|
3494
|
+
success: false,
|
|
3495
|
+
amagiError: "抖音搜索返回无有效数据,疑似触发反爬\n你的抖音ck可能已经失效!\n请求类型:" + data$1.methodType
|
|
3496
|
+
};
|
|
3444
3497
|
}
|
|
3445
3498
|
for (const resp of responses) {
|
|
3446
3499
|
if (Array.isArray(resp.data) && resp.data.length > 0) fetchedSearchList.push(...resp.data);
|
|
@@ -3448,8 +3501,11 @@ const DouyinData = async (data$1, cookie, requestConfig) => {
|
|
|
3448
3501
|
search_id = resp.log_pb?.impr_id ?? search_id;
|
|
3449
3502
|
}
|
|
3450
3503
|
if (fetchedSearchList.length === 0) {
|
|
3451
|
-
logger.warn("
|
|
3452
|
-
return
|
|
3504
|
+
logger.warn("抖音搜索API请求成功,但返回数据长度为0,\n此问题暂时无法处理,也可能被风控!\n请求类型:" + data$1.methodType);
|
|
3505
|
+
return {
|
|
3506
|
+
success: false,
|
|
3507
|
+
amagiError: "抖音搜索API请求成功,但返回数据长度为0,\n此问题暂时无法处理,也可能被风控!\n请求类型:" + data$1.methodType
|
|
3508
|
+
};
|
|
3453
3509
|
}
|
|
3454
3510
|
if (tmpresp && typeof tmpresp.has_more === "number" && tmpresp.has_more === 0) break;
|
|
3455
3511
|
}
|
|
@@ -3459,77 +3515,42 @@ const DouyinData = async (data$1, cookie, requestConfig) => {
|
|
|
3459
3515
|
};
|
|
3460
3516
|
}
|
|
3461
3517
|
case "动态表情数据": {
|
|
3462
|
-
const url = douyinApiUrls$1.互动表情();
|
|
3518
|
+
const url$1 = douyinApiUrls$1.互动表情();
|
|
3463
3519
|
return await GlobalGetData$2(data$1.methodType, {
|
|
3464
3520
|
...baseRequestConfig,
|
|
3465
|
-
url: buildSignedUrl(url, signType, userAgent)
|
|
3521
|
+
url: buildSignedUrl(url$1, signType, userAgent)
|
|
3466
3522
|
});
|
|
3467
3523
|
}
|
|
3468
3524
|
case "音乐数据": {
|
|
3469
|
-
const url = douyinApiUrls$1.背景音乐({ music_id: data$1.music_id });
|
|
3525
|
+
const url$1 = douyinApiUrls$1.背景音乐({ music_id: data$1.music_id });
|
|
3470
3526
|
return await GlobalGetData$2(data$1.methodType, {
|
|
3471
3527
|
...baseRequestConfig,
|
|
3472
|
-
url: buildSignedUrl(url, signType, userAgent)
|
|
3528
|
+
url: buildSignedUrl(url$1, signType, userAgent)
|
|
3473
3529
|
});
|
|
3474
3530
|
}
|
|
3475
3531
|
case "直播间信息数据": {
|
|
3476
|
-
let url = douyinApiUrls$1
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
...baseRequestConfig,
|
|
3480
|
-
headers: {
|
|
3481
|
-
...baseRequestConfig.headers,
|
|
3482
|
-
...(!requestConfig?.headers || !("Referer" in requestConfig.headers)) && { Referer: `https://www.douyin.com/user/${data$1.sec_uid}` }
|
|
3483
|
-
}
|
|
3484
|
-
};
|
|
3485
|
-
const UserInfoData = await GlobalGetData$2(data$1.methodType, {
|
|
3486
|
-
...customConfig,
|
|
3487
|
-
url: fetchUrl
|
|
3488
|
-
});
|
|
3489
|
-
if (!UserInfoData?.user?.live_status || UserInfoData.user.live_status !== 1) {
|
|
3490
|
-
logger.error((UserInfoData?.user?.nickname ?? "用户") + "当前未在直播");
|
|
3491
|
-
const Err = {
|
|
3492
|
-
errorDescription: "检查失败!该用户当前未在直播! TypeError: Cannot read properties of undefined (reading 'live_status')",
|
|
3493
|
-
requestType: data$1.methodType ?? "未知请求类型",
|
|
3494
|
-
requestUrl: fetchUrl
|
|
3495
|
-
};
|
|
3496
|
-
return {
|
|
3497
|
-
code: douoyinAPIErrorCode.NOT_LIVE,
|
|
3498
|
-
data: UserInfoData,
|
|
3499
|
-
amagiError: Err,
|
|
3500
|
-
amagiMessage: Err.errorDescription
|
|
3501
|
-
};
|
|
3502
|
-
}
|
|
3503
|
-
if (!UserInfoData.user.room_data) {
|
|
3504
|
-
logger.error("未获取到直播间信息!");
|
|
3505
|
-
return {
|
|
3506
|
-
code: 500,
|
|
3507
|
-
message: "未获取到直播间信息!",
|
|
3508
|
-
data: null
|
|
3509
|
-
};
|
|
3510
|
-
}
|
|
3511
|
-
const room_data = JSON.parse(UserInfoData.user.room_data);
|
|
3512
|
-
url = douyinApiUrls$1.直播间信息({
|
|
3513
|
-
room_id: UserInfoData.user.room_id_str,
|
|
3514
|
-
web_rid: room_data.owner.web_rid
|
|
3532
|
+
let url$1 = douyinApiUrls$1.直播间信息({
|
|
3533
|
+
room_id: data$1.room_id,
|
|
3534
|
+
web_rid: data$1.web_rid
|
|
3515
3535
|
});
|
|
3516
3536
|
const liveCustomConfig = {
|
|
3517
3537
|
...baseRequestConfig,
|
|
3538
|
+
url: buildSignedUrl(url$1, signType, userAgent),
|
|
3518
3539
|
headers: {
|
|
3519
3540
|
...baseRequestConfig.headers,
|
|
3520
|
-
...(!requestConfig?.headers || !("Referer" in requestConfig.headers)) && { Referer: `https://live.douyin.com/${
|
|
3541
|
+
...(!requestConfig?.headers || !("Referer" in requestConfig.headers)) && { Referer: `https://live.douyin.com/${data$1.web_rid}` }
|
|
3521
3542
|
}
|
|
3522
3543
|
};
|
|
3523
3544
|
return await GlobalGetData$2(data$1.methodType, {
|
|
3524
3545
|
...liveCustomConfig,
|
|
3525
|
-
url: buildSignedUrl(url, signType, userAgent)
|
|
3546
|
+
url: buildSignedUrl(url$1, signType, userAgent)
|
|
3526
3547
|
});
|
|
3527
3548
|
}
|
|
3528
3549
|
case "申请二维码数据": {
|
|
3529
|
-
const url = douyinApiUrls$1.申请二维码({ verify_fp: data$1.verify_fp });
|
|
3550
|
+
const url$1 = douyinApiUrls$1.申请二维码({ verify_fp: data$1.verify_fp });
|
|
3530
3551
|
return await GlobalGetData$2(data$1.methodType, {
|
|
3531
3552
|
...baseRequestConfig,
|
|
3532
|
-
url: buildSignedUrl(url, signType, userAgent)
|
|
3553
|
+
url: buildSignedUrl(url$1, signType, userAgent)
|
|
3533
3554
|
});
|
|
3534
3555
|
}
|
|
3535
3556
|
case "弹幕数据": {
|
|
@@ -3538,7 +3559,7 @@ const DouyinData = async (data$1, cookie, requestConfig) => {
|
|
|
3538
3559
|
const endTime = data$1.end_time ?? data$1.duration;
|
|
3539
3560
|
const totalDuration = endTime - startTime;
|
|
3540
3561
|
if (totalDuration <= MAX_SEGMENT_DURATION) {
|
|
3541
|
-
const url = douyinApiUrls$1.弹幕({
|
|
3562
|
+
const url$1 = douyinApiUrls$1.弹幕({
|
|
3542
3563
|
aweme_id: data$1.aweme_id,
|
|
3543
3564
|
start_time: startTime,
|
|
3544
3565
|
end_time: endTime,
|
|
@@ -3546,7 +3567,7 @@ const DouyinData = async (data$1, cookie, requestConfig) => {
|
|
|
3546
3567
|
});
|
|
3547
3568
|
return await GlobalGetData$2(data$1.methodType, {
|
|
3548
3569
|
...baseRequestConfig,
|
|
3549
|
-
url: buildSignedUrl(url, signType, userAgent)
|
|
3570
|
+
url: buildSignedUrl(url$1, signType, userAgent)
|
|
3550
3571
|
});
|
|
3551
3572
|
}
|
|
3552
3573
|
const segments = [];
|
|
@@ -3561,7 +3582,7 @@ const DouyinData = async (data$1, cookie, requestConfig) => {
|
|
|
3561
3582
|
}
|
|
3562
3583
|
logger.debug(`弹幕数据需要分${segments.length}段获取,总时长:${totalDuration}ms`);
|
|
3563
3584
|
const segmentPromises = segments.map(async (segment, index) => {
|
|
3564
|
-
const url = douyinApiUrls$1.弹幕({
|
|
3585
|
+
const url$1 = douyinApiUrls$1.弹幕({
|
|
3565
3586
|
aweme_id: data$1.aweme_id,
|
|
3566
3587
|
start_time: segment.start,
|
|
3567
3588
|
end_time: segment.end,
|
|
@@ -3570,7 +3591,7 @@ const DouyinData = async (data$1, cookie, requestConfig) => {
|
|
|
3570
3591
|
try {
|
|
3571
3592
|
const segmentData = await GlobalGetData$2(`${data$1.methodType}-段${index + 1}`, {
|
|
3572
3593
|
...baseRequestConfig,
|
|
3573
|
-
url: buildSignedUrl(url, signType, userAgent)
|
|
3594
|
+
url: buildSignedUrl(url$1, signType, userAgent)
|
|
3574
3595
|
});
|
|
3575
3596
|
logger.debug(`弹幕第${index + 1}段获取成功 (${segment.start}ms-${segment.end}ms)`);
|
|
3576
3597
|
return segmentData;
|
|
@@ -3611,9 +3632,18 @@ const DouyinData = async (data$1, cookie, requestConfig) => {
|
|
|
3611
3632
|
logger.debug(`弹幕数据合并完成,共获取${mergedDanmakuList.length}条弹幕`);
|
|
3612
3633
|
return finalDanmakuData;
|
|
3613
3634
|
}
|
|
3614
|
-
default:
|
|
3635
|
+
default: {
|
|
3636
|
+
const customUrl = data$1.custom_url;
|
|
3637
|
+
if (typeof customUrl === "string" && customUrl.length > 0) {
|
|
3638
|
+
const url$1 = buildSignedUrl(customUrl, signType, userAgent);
|
|
3639
|
+
return await GlobalGetData$2(data$1.methodType ?? "自定义请求", {
|
|
3640
|
+
...baseRequestConfig,
|
|
3641
|
+
url: url$1
|
|
3642
|
+
});
|
|
3643
|
+
}
|
|
3615
3644
|
logger.warn(`未知的抖音数据接口:「${logger.red(data$1.methodType)}」`);
|
|
3616
3645
|
return null;
|
|
3646
|
+
}
|
|
3617
3647
|
}
|
|
3618
3648
|
};
|
|
3619
3649
|
/**
|
|
@@ -3633,14 +3663,14 @@ const fetchPaginatedData = async (type, apiUrlGenerator, params, maxPageSize, re
|
|
|
3633
3663
|
const userAgent = requestConfig.headers?.["User-Agent"];
|
|
3634
3664
|
while (fetchedData.length < Number(params.number ?? maxPageSize)) {
|
|
3635
3665
|
const requestCount = Math.min(Number(params.number ?? maxPageSize) - fetchedData.length, maxPageSize);
|
|
3636
|
-
const url = apiUrlGenerator({
|
|
3666
|
+
const url$1 = apiUrlGenerator({
|
|
3637
3667
|
...params,
|
|
3638
3668
|
number: requestCount,
|
|
3639
3669
|
cursor
|
|
3640
3670
|
});
|
|
3641
3671
|
const response = await GlobalGetData$2(type, {
|
|
3642
3672
|
...requestConfig,
|
|
3643
|
-
url: buildSignedUrl(url, signType, userAgent)
|
|
3673
|
+
url: buildSignedUrl(url$1, signType, userAgent)
|
|
3644
3674
|
});
|
|
3645
3675
|
fetchedData.push(...response.comments ?? response.data ?? []);
|
|
3646
3676
|
tmpresp = response;
|
|
@@ -3805,6 +3835,12 @@ const kuaishouApiUrls = new API();
|
|
|
3805
3835
|
//#endregion
|
|
3806
3836
|
//#region src/platform/kuaishou/getdata.ts
|
|
3807
3837
|
/**
|
|
3838
|
+
* 快手数据获取模块
|
|
3839
|
+
*
|
|
3840
|
+
* 注意:为避免循环依赖,此文件直接从具体模块导入,而不是从平台 index 文件导入
|
|
3841
|
+
* 循环依赖链:DataFetchers → getdata → platform/kuaishou → DataFetchers
|
|
3842
|
+
*/
|
|
3843
|
+
/**
|
|
3808
3844
|
* 快手数据获取函数
|
|
3809
3845
|
* @param data - 请求数据参数
|
|
3810
3846
|
* @param cookie - 用户Cookie
|
|
@@ -4082,7 +4118,7 @@ async function getDouyinData(methodType, optionsOrCookie, cookieOrOptions, reque
|
|
|
4082
4118
|
cookie = cookieOrOptions;
|
|
4083
4119
|
config = requestConfig;
|
|
4084
4120
|
}
|
|
4085
|
-
const { typeMode: _
|
|
4121
|
+
const { typeMode: _, ...validationOptions } = options ?? {};
|
|
4086
4122
|
const rawData = await DouyinData({ ...validateDouyinParams(methodType, validationOptions) }, cookie, config);
|
|
4087
4123
|
if (rawData.data === "" || rawData.status_code !== 0) return createErrorResponse(rawData.amagiError, rawData.status_msg ?? "抖音数据获取失败");
|
|
4088
4124
|
return createSuccessResponse(rawData, "获取成功", 200);
|
|
@@ -4105,7 +4141,7 @@ async function getBilibiliData(methodType, optionsOrCookie, cookieOrOptions, req
|
|
|
4105
4141
|
options = optionsOrCookie;
|
|
4106
4142
|
cookie = cookieOrOptions;
|
|
4107
4143
|
}
|
|
4108
|
-
const { typeMode: _
|
|
4144
|
+
const { typeMode: _, ...validationOptions } = options ?? {};
|
|
4109
4145
|
const rawData = await fetchBilibili({ ...validateBilibiliParams(methodType, validationOptions) }, cookie);
|
|
4110
4146
|
if (rawData.code !== 0) return createErrorResponse(rawData.amagiError, "B站数据获取失败");
|
|
4111
4147
|
return createSuccessResponse(rawData, "获取成功", 200);
|
|
@@ -4128,7 +4164,7 @@ async function getKuaishouData(methodType, optionsOrCookie, cookieOrOptions, req
|
|
|
4128
4164
|
options = optionsOrCookie;
|
|
4129
4165
|
cookie = cookieOrOptions;
|
|
4130
4166
|
}
|
|
4131
|
-
const { typeMode: _
|
|
4167
|
+
const { typeMode: _, ...validationOptions } = options ?? {};
|
|
4132
4168
|
const rawData = await KuaishouData({ ...validateKuaishouParams(methodType, validationOptions) }, cookie);
|
|
4133
4169
|
if (rawData.code && Object.values(kuaishouAPIErrorCode).includes(rawData.code)) return createErrorResponse(rawData.amagiError, "快手数据获取失败");
|
|
4134
4170
|
return createSuccessResponse(rawData, "获取成功", 200);
|
|
@@ -4151,7 +4187,7 @@ async function getXiaohongshuData(methodType, optionsOrCookie, cookieOrOptions,
|
|
|
4151
4187
|
options = optionsOrCookie;
|
|
4152
4188
|
cookie = cookieOrOptions;
|
|
4153
4189
|
}
|
|
4154
|
-
const { typeMode: _
|
|
4190
|
+
const { typeMode: _, ...validationOptions } = options ?? {};
|
|
4155
4191
|
const rawData = await XiaohongshuData({ ...validateXiaohongshuParams(methodType, validationOptions) }, cookie);
|
|
4156
4192
|
if (rawData.code && Object.values(xiaohongshuAPIErrorCode).includes(rawData.code)) return createErrorResponse(rawData.amagiError, "小红书数据获取失败");
|
|
4157
4193
|
return createSuccessResponse(rawData, "获取成功", 200);
|
|
@@ -4209,7 +4245,10 @@ const douyin = {
|
|
|
4209
4245
|
getSuggestWords: createDouyinApiMethod("热点词数据"),
|
|
4210
4246
|
search: createDouyinApiMethod("搜索数据"),
|
|
4211
4247
|
getLiveRoomInfo: createDouyinApiMethod("直播间信息数据"),
|
|
4212
|
-
getDanmaku: createDouyinApiMethod("弹幕数据")
|
|
4248
|
+
getDanmaku: createDouyinApiMethod("弹幕数据"),
|
|
4249
|
+
invoke: async (methodType, options, cookie, requestConfig) => {
|
|
4250
|
+
return await getDouyinData(methodType, options, cookie, requestConfig);
|
|
4251
|
+
}
|
|
4213
4252
|
};
|
|
4214
4253
|
/**
|
|
4215
4254
|
* 创建绑定了cookie的抖音API对象
|
|
@@ -4231,9 +4270,12 @@ const createBoundDouyinApi = (cookie, requestConfig) => {
|
|
|
4231
4270
|
getUserVideos: createBoundDouyinApiMethod("用户主页视频列表数据", cookie, requestConfig),
|
|
4232
4271
|
getMusicInfo: createBoundDouyinApiMethod("音乐数据", cookie, requestConfig),
|
|
4233
4272
|
getSuggestWords: createBoundDouyinApiMethod("热点词数据", cookie, requestConfig),
|
|
4234
|
-
|
|
4273
|
+
getSearchData: createBoundDouyinApiMethod("搜索数据", cookie, requestConfig),
|
|
4235
4274
|
getLiveRoomInfo: createBoundDouyinApiMethod("直播间信息数据", cookie, requestConfig),
|
|
4236
|
-
getDanmaku: createBoundDouyinApiMethod("弹幕数据", cookie, requestConfig)
|
|
4275
|
+
getDanmaku: createBoundDouyinApiMethod("弹幕数据", cookie, requestConfig),
|
|
4276
|
+
invoke: async (methodType, options) => {
|
|
4277
|
+
return await getDouyinData(methodType, options, cookie, requestConfig);
|
|
4278
|
+
}
|
|
4237
4279
|
};
|
|
4238
4280
|
};
|
|
4239
4281
|
|
|
@@ -4271,22 +4313,8 @@ const createDouyinRouteHandler = (dataFetcher, methodType, cookie, requestConfig
|
|
|
4271
4313
|
* @returns Express路由器
|
|
4272
4314
|
*/
|
|
4273
4315
|
const createDouyinRoutes = (cookie, requestConfig = getDouyinDefaultConfig(cookie)) => {
|
|
4274
|
-
const router = Router();
|
|
4275
|
-
router.get(
|
|
4276
|
-
router.get("/fetch_one_work", createDouyinValidationMiddleware("视频作品数据"), createDouyinRouteHandler(getDouyinData, "视频作品数据", cookie, requestConfig));
|
|
4277
|
-
router.get("/fetch_one_work", createDouyinValidationMiddleware("图集作品数据"), createDouyinRouteHandler(getDouyinData, "图集作品数据", cookie, requestConfig));
|
|
4278
|
-
router.get("/fetch_one_work", createDouyinValidationMiddleware("合辑作品数据"), createDouyinRouteHandler(getDouyinData, "合辑作品数据", cookie, requestConfig));
|
|
4279
|
-
router.get("/fetch_work_comments", createDouyinValidationMiddleware("评论数据"), createDouyinRouteHandler(getDouyinData, "评论数据", cookie, requestConfig));
|
|
4280
|
-
router.get("/fetch_user_info", createDouyinValidationMiddleware("用户主页数据"), createDouyinRouteHandler(getDouyinData, "用户主页数据", cookie, requestConfig));
|
|
4281
|
-
router.get("/fetch_user_post_videos", createDouyinValidationMiddleware("用户主页视频列表数据"), createDouyinRouteHandler(getDouyinData, "用户主页视频列表数据", cookie, requestConfig));
|
|
4282
|
-
router.get("/fetch_search_info", createDouyinValidationMiddleware("搜索数据"), createDouyinRouteHandler(getDouyinData, "搜索数据", cookie, requestConfig));
|
|
4283
|
-
router.get("/fetch_suggest_words", createDouyinValidationMiddleware("热点词数据"), createDouyinRouteHandler(getDouyinData, "热点词数据", cookie, requestConfig));
|
|
4284
|
-
router.get("/fetch_music_work", createDouyinValidationMiddleware("音乐数据"), createDouyinRouteHandler(getDouyinData, "音乐数据", cookie, requestConfig));
|
|
4285
|
-
router.get("/fetch_emoji_list", createDouyinValidationMiddleware("Emoji数据"), createDouyinRouteHandler(getDouyinData, "Emoji数据", cookie, requestConfig));
|
|
4286
|
-
router.get("/fetch_emoji_pro_list", createDouyinValidationMiddleware("动态表情数据"), createDouyinRouteHandler(getDouyinData, "动态表情数据", cookie, requestConfig));
|
|
4287
|
-
router.get("/fetch_user_live_videos", createDouyinValidationMiddleware("直播间信息数据"), createDouyinRouteHandler(getDouyinData, "直播间信息数据", cookie, requestConfig));
|
|
4288
|
-
router.get("/fetch_video_comment_replies", createDouyinValidationMiddleware("指定评论回复数据"), createDouyinRouteHandler(getDouyinData, "指定评论回复数据", cookie, requestConfig));
|
|
4289
|
-
router.get("/fetch_work_danmaku", createDouyinValidationMiddleware("弹幕数据"), createDouyinRouteHandler(getDouyinData, "弹幕数据", cookie, requestConfig));
|
|
4316
|
+
const router = express.Router();
|
|
4317
|
+
for (const [method, path$1] of Object.entries(DouyinMethodRoutes)) router.get(path$1, createDouyinValidationMiddleware(method), createDouyinRouteHandler(getDouyinData, method, cookie, requestConfig));
|
|
4290
4318
|
return router;
|
|
4291
4319
|
};
|
|
4292
4320
|
|
|
@@ -4378,10 +4406,8 @@ const createKuaishouRouteHandler = (dataFetcher, methodType, cookie, requestConf
|
|
|
4378
4406
|
* @returns Express路由器
|
|
4379
4407
|
*/
|
|
4380
4408
|
const createKuaishouRoutes = (cookie, requestConfig = getKuaishouDefaultConfig(cookie)) => {
|
|
4381
|
-
const router = Router();
|
|
4382
|
-
router.get(
|
|
4383
|
-
router.get("/fetch_work_comments", createKuaishouValidationMiddleware("评论数据"), createKuaishouRouteHandler(getKuaishouData, "评论数据", cookie, requestConfig));
|
|
4384
|
-
router.get("/fetch_emoji_list", createKuaishouValidationMiddleware("Emoji数据"), createKuaishouRouteHandler(getKuaishouData, "Emoji数据", cookie, requestConfig));
|
|
4409
|
+
const router = express.Router();
|
|
4410
|
+
for (const [method, path$1] of Object.entries(KuaishouMethodRoutes)) router.get(path$1, createKuaishouValidationMiddleware(method), createKuaishouRouteHandler(getKuaishouData, method, cookie, requestConfig));
|
|
4385
4411
|
return router;
|
|
4386
4412
|
};
|
|
4387
4413
|
|
|
@@ -4485,14 +4511,8 @@ const createXiaohongshuRouteHandler = (dataFetcher, methodType, cookie, requestC
|
|
|
4485
4511
|
* @returns Express路由器
|
|
4486
4512
|
*/
|
|
4487
4513
|
const createXiaohongshuRoutes = (cookie, requestConfig = getXiaohongshuDefaultConfig(cookie)) => {
|
|
4488
|
-
const router = Router();
|
|
4489
|
-
router.get(
|
|
4490
|
-
router.get("/fetch_one_note", createXiaohongshuValidationMiddleware("单个笔记数据"), createXiaohongshuRouteHandler(getXiaohongshuData, "单个笔记数据", cookie, requestConfig));
|
|
4491
|
-
router.get("/fetch_note_comments", createXiaohongshuValidationMiddleware("评论数据"), createXiaohongshuRouteHandler(getXiaohongshuData, "评论数据", cookie, requestConfig));
|
|
4492
|
-
router.get("/fetch_user_profile", createXiaohongshuValidationMiddleware("用户数据"), createXiaohongshuRouteHandler(getXiaohongshuData, "用户数据", cookie, requestConfig));
|
|
4493
|
-
router.get("/fetch_user_notes", createXiaohongshuValidationMiddleware("用户笔记数据"), createXiaohongshuRouteHandler(getXiaohongshuData, "用户笔记数据", cookie, requestConfig));
|
|
4494
|
-
router.get("/fetch_emoji_list", createXiaohongshuValidationMiddleware("表情列表"), createXiaohongshuRouteHandler(getXiaohongshuData, "表情列表", cookie, requestConfig));
|
|
4495
|
-
router.get("/fetch_search_notes", createXiaohongshuValidationMiddleware("搜索笔记"), createXiaohongshuRouteHandler(getXiaohongshuData, "搜索笔记", cookie, requestConfig));
|
|
4514
|
+
const router = express.Router();
|
|
4515
|
+
for (const [method, path$1] of Object.entries(XiaohongshuMethodRoutes)) router.get(path$1, createXiaohongshuValidationMiddleware(method), createXiaohongshuRouteHandler(getXiaohongshuData, method, cookie, requestConfig));
|
|
4496
4516
|
return router;
|
|
4497
4517
|
};
|
|
4498
4518
|
|
|
@@ -4603,6 +4623,60 @@ const createAmagiClient = (options) => {
|
|
|
4603
4623
|
};
|
|
4604
4624
|
};
|
|
4605
4625
|
|
|
4626
|
+
//#endregion
|
|
4627
|
+
//#region src/types/BilibiliAPIParams.ts
|
|
4628
|
+
/**
|
|
4629
|
+
* 评论区类型枚举
|
|
4630
|
+
* 对应 CommentParams.type 与 CommentReplyParams.type
|
|
4631
|
+
*/
|
|
4632
|
+
let CommentType = /* @__PURE__ */ function(CommentType$1) {
|
|
4633
|
+
/** 视频稿件:oid 为稿件 avid */
|
|
4634
|
+
CommentType$1[CommentType$1["Video"] = 1] = "Video";
|
|
4635
|
+
/** 话题:oid 为话题 id */
|
|
4636
|
+
CommentType$1[CommentType$1["Topic"] = 2] = "Topic";
|
|
4637
|
+
/** 活动:oid 为活动 id */
|
|
4638
|
+
CommentType$1[CommentType$1["Activity"] = 4] = "Activity";
|
|
4639
|
+
/** 小视频:oid 为小视频 id */
|
|
4640
|
+
CommentType$1[CommentType$1["SmallVideo"] = 5] = "SmallVideo";
|
|
4641
|
+
/** 小黑屋封禁信息:oid 为封禁公示 id */
|
|
4642
|
+
CommentType$1[CommentType$1["BlockInfo"] = 6] = "BlockInfo";
|
|
4643
|
+
/** 公告信息:oid 为公告 id */
|
|
4644
|
+
CommentType$1[CommentType$1["Announcement"] = 7] = "Announcement";
|
|
4645
|
+
/** 直播活动:oid 为直播间 id */
|
|
4646
|
+
CommentType$1[CommentType$1["LiveActivity"] = 8] = "LiveActivity";
|
|
4647
|
+
/** 活动稿件:oid 含义未知 */
|
|
4648
|
+
CommentType$1[CommentType$1["ActivityVideo"] = 9] = "ActivityVideo";
|
|
4649
|
+
/** 直播公告:oid 含义未知 */
|
|
4650
|
+
CommentType$1[CommentType$1["LiveAnnouncement"] = 10] = "LiveAnnouncement";
|
|
4651
|
+
/** 相簿(图片动态):oid 为相簿 id */
|
|
4652
|
+
CommentType$1[CommentType$1["Album"] = 11] = "Album";
|
|
4653
|
+
/** 专栏:oid 为专栏 cvid */
|
|
4654
|
+
CommentType$1[CommentType$1["Article"] = 12] = "Article";
|
|
4655
|
+
/** 票务:oid 含义未知 */
|
|
4656
|
+
CommentType$1[CommentType$1["Ticket"] = 13] = "Ticket";
|
|
4657
|
+
/** 音频:oid 为音频 auid */
|
|
4658
|
+
CommentType$1[CommentType$1["Audio"] = 14] = "Audio";
|
|
4659
|
+
/** 风纪委员会:oid 为众裁项目 id */
|
|
4660
|
+
CommentType$1[CommentType$1["Jury"] = 15] = "Jury";
|
|
4661
|
+
/** 点评:oid 含义未知 */
|
|
4662
|
+
CommentType$1[CommentType$1["Review"] = 16] = "Review";
|
|
4663
|
+
/** 动态(纯文字动态&分享):oid 为动态 id */
|
|
4664
|
+
CommentType$1[CommentType$1["Dynamic"] = 17] = "Dynamic";
|
|
4665
|
+
/** 播单:oid 含义未知 */
|
|
4666
|
+
CommentType$1[CommentType$1["Playlist"] = 18] = "Playlist";
|
|
4667
|
+
/** 音乐播单:oid 含义未知 */
|
|
4668
|
+
CommentType$1[CommentType$1["MusicPlaylist"] = 19] = "MusicPlaylist";
|
|
4669
|
+
/** 漫画:oid 含义未知 */
|
|
4670
|
+
CommentType$1[CommentType$1["Comic1"] = 20] = "Comic1";
|
|
4671
|
+
/** 漫画:oid 含义未知 */
|
|
4672
|
+
CommentType$1[CommentType$1["Comic2"] = 21] = "Comic2";
|
|
4673
|
+
/** 漫画:oid 为漫画 mcid */
|
|
4674
|
+
CommentType$1[CommentType$1["Comic"] = 22] = "Comic";
|
|
4675
|
+
/** 课程:oid 为课程 epid */
|
|
4676
|
+
CommentType$1[CommentType$1["Course"] = 33] = "Course";
|
|
4677
|
+
return CommentType$1;
|
|
4678
|
+
}({});
|
|
4679
|
+
|
|
4606
4680
|
//#endregion
|
|
4607
4681
|
//#region src/types/ReturnDataType/Bilibili/Dynamic/index.ts
|
|
4608
4682
|
/**
|
|
@@ -4716,4 +4790,4 @@ const Client = CreateApp;
|
|
|
4716
4790
|
const amagi = Client;
|
|
4717
4791
|
|
|
4718
4792
|
//#endregion
|
|
4719
|
-
export { AdditionalType, ApiError, BilibiliArticleCardParamsSchema, BilibiliArticleInfoParamsSchema, BilibiliArticleParamsSchema, BilibiliAv2BvParamsSchema, BilibiliBangumiInfoParamsSchema, BilibiliBangumiStreamParamsSchema, BilibiliBv2AvParamsSchema, BilibiliColumnInfoParamsSchema, BilibiliCommentParamsSchema, BilibiliCommentReplyParamsSchema, BilibiliDynamicParamsSchema, BilibiliEmojiParamsSchema, BilibiliLiveParamsSchema, BilibiliLoginParamsSchema, BilibiliQrcodeParamsSchema, BilibiliQrcodeStatusParamsSchema, BilibiliUserParamsSchema, BilibiliValidationSchemas, BilibiliVideoDownloadParamsSchema, BilibiliVideoParamsSchema, CreateApp, DouyinCommentParamsSchema, DouyinCommentReplyParamsSchema, DouyinDanmakuParamsSchema, DouyinEmojiListParamsSchema, DouyinEmojiProParamsSchema, DouyinMusicParamsSchema, DouyinQrcodeParamsSchema, DouyinSearchParamsSchema, DouyinUserParamsSchema, DouyinValidationSchemas, DouyinWorkParamsSchema, DynamicType, KuaishouCommentParamsSchema, KuaishouEmojiParamsSchema, KuaishouValidationSchemas, KuaishouVideoParamsSchema, MajorType, ValidationError, XiaohongshuValidationSchemas, amagi, amagiClient, av2bv, bilibili, bilibiliApiUrls, bilibiliErrorCodeMap, bilibiliUtils, bv2av, createAmagiClient, createBilibiliRoutes, createBilibiliRoutes as registerBilibiliRoutes, createBoundBilibiliApi, createBoundDouyinApi, createBoundKuaishouApi, createBoundXiaohongshuApi, createDouyinRoutes, createDouyinRoutes as registerDouyinRoutes, createErrorResponse, createKuaishouRoutes, createKuaishouRoutes as registerKuaishouRoutes, createSuccessResponse, createXiaohongshuRoutes, createXiaohongshuRoutes as registerXiaohongshuRoutes, Client as default, douyin, douyinApiUrls, douyinSign, douyinUtils, fetchData, fetchResponse, getBilibiliData, getDouyinData, getHeadersAndData, getKuaishouData, handleError, httpLogger, kuaishou, kuaishouApiUrls, kuaishouUtils, logMiddleware, logger, qtparam, validateBilibiliParams, validateDouyinParams, validateKuaishouParams, validateXiaohongshuParams, wbi_sign, xiaohongshu, xiaohongshuApiUrls, xiaohongshuSign, xiaohongshuUtils };
|
|
4793
|
+
export { AdditionalType, ApiError, BilibiliArticleCardParamsSchema, BilibiliArticleInfoParamsSchema, BilibiliArticleParamsSchema, BilibiliAv2BvParamsSchema, BilibiliBangumiInfoParamsSchema, BilibiliBangumiStreamParamsSchema, BilibiliBv2AvParamsSchema, BilibiliColumnInfoParamsSchema, BilibiliCommentParamsSchema, BilibiliCommentReplyParamsSchema, BilibiliDynamicParamsSchema, BilibiliEmojiParamsSchema, BilibiliLiveParamsSchema, BilibiliLoginParamsSchema, BilibiliMethodRoutes, BilibiliQrcodeParamsSchema, BilibiliQrcodeStatusParamsSchema, BilibiliUserParamsSchema, BilibiliValidationSchemas, BilibiliVideoDownloadParamsSchema, BilibiliVideoParamsSchema, CommentType, CreateApp, DouyinCommentParamsSchema, DouyinCommentReplyParamsSchema, DouyinDanmakuParamsSchema, DouyinEmojiListParamsSchema, DouyinEmojiProParamsSchema, DouyinLiveRoomParamsSchema, DouyinMethodRoutes, DouyinMusicParamsSchema, DouyinQrcodeParamsSchema, DouyinSearchParamsSchema, DouyinUserParamsSchema, DouyinValidationSchemas, DouyinWorkParamsSchema, DynamicType, KuaishouCommentParamsSchema, KuaishouEmojiParamsSchema, KuaishouMethodRoutes, KuaishouValidationSchemas, KuaishouVideoParamsSchema, MajorType, ValidationError, XiaohongshuMethodRoutes, XiaohongshuValidationSchemas, amagi, amagiClient, av2bv, bilibili, bilibiliApiUrls, bilibiliErrorCodeMap, bilibiliUtils, bv2av, createAmagiClient, createBilibiliRoutes, createBilibiliRoutes as registerBilibiliRoutes, createBoundBilibiliApi, createBoundDouyinApi, createBoundKuaishouApi, createBoundXiaohongshuApi, createDouyinRoutes, createDouyinRoutes as registerDouyinRoutes, createErrorResponse, createKuaishouRoutes, createKuaishouRoutes as registerKuaishouRoutes, createSuccessResponse, createXiaohongshuRoutes, createXiaohongshuRoutes as registerXiaohongshuRoutes, Client as default, douyin, douyinApiUrls, douyinSign, douyinUtils, fetchData, fetchResponse, getBilibiliData, getDouyinData, getHeadersAndData, getKuaishouData, handleError, httpLogger, kuaishou, kuaishouApiUrls, kuaishouUtils, logMiddleware, logger, qtparam, validateBilibiliParams, validateDouyinParams, validateKuaishouParams, validateXiaohongshuParams, wbi_sign, xiaohongshu, xiaohongshuApiUrls, xiaohongshuSign, xiaohongshuUtils };
|