@ikenxuan/amagi 5.12.1 → 5.13.0
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/dist/default/index.cjs +447 -280
- package/dist/default/index.d.cts +145 -31
- package/dist/default/index.d.cts.map +1 -0
- package/dist/default/index.d.ts +145 -31
- package/dist/default/index.d.ts.map +1 -0
- package/dist/default/index.js +443 -278
- package/dist/default/index.js.map +1 -0
- package/package.json +17 -16
package/dist/default/index.js
CHANGED
|
@@ -1,15 +1,29 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
1
|
import path from "node:path";
|
|
3
2
|
import url from "node:url";
|
|
3
|
+
import fs from "node:fs";
|
|
4
4
|
import { Chalk } from "chalk";
|
|
5
|
-
import log4js from "log4js";
|
|
6
5
|
import axios, { AxiosError } from "axios";
|
|
7
6
|
import zod from "zod";
|
|
8
|
-
import crypto from "node:crypto";
|
|
9
7
|
import { Xhshow } from "@ikenxuan/xhshow-ts";
|
|
8
|
+
import protobuf from "protobufjs";
|
|
9
|
+
import crypto from "node:crypto";
|
|
10
10
|
import express from "express";
|
|
11
11
|
|
|
12
12
|
//#region src/model/logger.ts
|
|
13
|
+
/**
|
|
14
|
+
* 动态获取 log4js 库
|
|
15
|
+
* 优先使用 node-karin/log4js (Karin 环境)
|
|
16
|
+
* 失败则回退到 log4js (独立环境,通过别名映射到 @karinjs/log4js)
|
|
17
|
+
*/
|
|
18
|
+
const getLog4js = async () => {
|
|
19
|
+
try {
|
|
20
|
+
return (await import("node-karin/log4js")).default;
|
|
21
|
+
} catch {
|
|
22
|
+
const lib = await import("log4js");
|
|
23
|
+
return lib.default || lib;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
const log4jsPromise = getLog4js();
|
|
13
27
|
/** 获取包的绝对路径 */
|
|
14
28
|
const getPackageLogsPath = () => {
|
|
15
29
|
const currentFileUrl = import.meta.url;
|
|
@@ -19,7 +33,11 @@ const getPackageLogsPath = () => {
|
|
|
19
33
|
if (fs.existsSync(path.join(packageRoot, "package.json"))) break;
|
|
20
34
|
packageRoot = path.dirname(packageRoot);
|
|
21
35
|
}
|
|
22
|
-
|
|
36
|
+
const logsDir = path.join(packageRoot, "logs");
|
|
37
|
+
try {
|
|
38
|
+
if (!fs.existsSync(logsDir)) fs.mkdirSync(logsDir, { recursive: true });
|
|
39
|
+
} catch (error) {}
|
|
40
|
+
return logsDir;
|
|
23
41
|
};
|
|
24
42
|
const logsPath = getPackageLogsPath();
|
|
25
43
|
/** 获取日志级别,优先使用环境变量,默认为 info */
|
|
@@ -27,59 +45,65 @@ const getLogLevel = () => {
|
|
|
27
45
|
return process.env.LOG_LEVEL ?? "info";
|
|
28
46
|
};
|
|
29
47
|
const currentLogLevel = getLogLevel();
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}
|
|
48
|
+
/** 初始化 logger 配置 */
|
|
49
|
+
const initLogger = () => {
|
|
50
|
+
log4jsPromise.then((log4js) => {
|
|
51
|
+
log4js.configure({
|
|
52
|
+
appenders: {
|
|
53
|
+
console: {
|
|
54
|
+
type: "stdout",
|
|
55
|
+
layout: {
|
|
56
|
+
type: "pattern",
|
|
57
|
+
pattern: "%[[amagi][%d{hh:mm:ss.SSS}][%4.4p]%] %m"
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
command: {
|
|
61
|
+
type: "dateFile",
|
|
62
|
+
filename: path.join(logsPath, "application", "command"),
|
|
63
|
+
pattern: "yyyy-MM-dd.log",
|
|
64
|
+
numBackups: 15,
|
|
65
|
+
alwaysIncludePattern: true,
|
|
66
|
+
layout: {
|
|
67
|
+
type: "pattern",
|
|
68
|
+
pattern: "[%d{hh:mm:ss.SSS}][%4.4p] %m"
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
httpConsole: {
|
|
72
|
+
type: "stdout",
|
|
73
|
+
layout: {
|
|
74
|
+
type: "pattern",
|
|
75
|
+
pattern: "%[[amagi][%d{hh:mm:ss.SSS}][HTTP]%] %m"
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
httpRequest: {
|
|
79
|
+
type: "dateFile",
|
|
80
|
+
filename: path.join(logsPath, "http", "requests"),
|
|
81
|
+
pattern: "yyyy-MM-dd.log",
|
|
82
|
+
numBackups: 30,
|
|
83
|
+
alwaysIncludePattern: true,
|
|
84
|
+
layout: {
|
|
85
|
+
type: "pattern",
|
|
86
|
+
pattern: "[%d{hh:mm:ss.SSS}][%4.4p] %m"
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
categories: {
|
|
91
|
+
default: {
|
|
92
|
+
appenders: ["console", "command"],
|
|
93
|
+
level: currentLogLevel
|
|
94
|
+
},
|
|
95
|
+
http: {
|
|
96
|
+
appenders: ["httpConsole", "httpRequest"],
|
|
97
|
+
level: "debug"
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
pm2: true
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
};
|
|
81
104
|
var CustomLogger = class {
|
|
82
105
|
logger;
|
|
106
|
+
queue = [];
|
|
83
107
|
chalk;
|
|
84
108
|
red;
|
|
85
109
|
green;
|
|
@@ -90,7 +114,10 @@ var CustomLogger = class {
|
|
|
90
114
|
white;
|
|
91
115
|
gray;
|
|
92
116
|
constructor(name) {
|
|
93
|
-
|
|
117
|
+
log4jsPromise.then((log4js) => {
|
|
118
|
+
this.logger = log4js.getLogger(name);
|
|
119
|
+
this.flush();
|
|
120
|
+
});
|
|
94
121
|
this.chalk = new Chalk();
|
|
95
122
|
this.red = this.chalk.red;
|
|
96
123
|
this.green = this.chalk.green;
|
|
@@ -101,20 +128,31 @@ var CustomLogger = class {
|
|
|
101
128
|
this.white = this.chalk.white;
|
|
102
129
|
this.gray = this.chalk.gray;
|
|
103
130
|
}
|
|
131
|
+
flush() {
|
|
132
|
+
if (!this.logger) return;
|
|
133
|
+
while (this.queue.length) {
|
|
134
|
+
const [method, args] = this.queue.shift();
|
|
135
|
+
this.logger[method](...args);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
proxy(method, args) {
|
|
139
|
+
if (this.logger) this.logger[method](...args);
|
|
140
|
+
else this.queue.push([method, args]);
|
|
141
|
+
}
|
|
104
142
|
info(message, ...args) {
|
|
105
|
-
this.
|
|
143
|
+
this.proxy("info", [message, ...args]);
|
|
106
144
|
}
|
|
107
145
|
warn(message, ...args) {
|
|
108
|
-
this.
|
|
146
|
+
this.proxy("warn", [message, ...args]);
|
|
109
147
|
}
|
|
110
148
|
error(message, ...args) {
|
|
111
|
-
this.
|
|
149
|
+
this.proxy("error", [message, ...args]);
|
|
112
150
|
}
|
|
113
151
|
mark(message, ...args) {
|
|
114
|
-
this.
|
|
152
|
+
this.proxy("mark", [message, ...args]);
|
|
115
153
|
}
|
|
116
154
|
debug(message, ...args) {
|
|
117
|
-
this.
|
|
155
|
+
this.proxy("debug", [message, ...args]);
|
|
118
156
|
}
|
|
119
157
|
};
|
|
120
158
|
const logger = new CustomLogger("default");
|
|
@@ -489,6 +527,11 @@ const BilibiliValidateCaptchaParamsSchema = zod.object({
|
|
|
489
527
|
validate: zod.string({ error: "验证码validate必须是字符串" }).min(1, { error: "验证码validate不能为空" }),
|
|
490
528
|
seccode: zod.string({ error: "验证码seccode必须是字符串" }).min(1, { error: "验证码seccode不能为空" })
|
|
491
529
|
});
|
|
530
|
+
const BilibiliDanmakuParamsSchema = zod.object({
|
|
531
|
+
methodType: zod.literal("实时弹幕", { error: "方法类型必须是\"实时弹幕\"" }),
|
|
532
|
+
cid: smartNumber("CID不能为空", 1, true),
|
|
533
|
+
segment_index: zod.coerce.number({ error: "分段序号必须是数字" }).int({ error: "分段序号必须是整数" }).positive({ error: "分段序号必须是正数" }).default(1).optional()
|
|
534
|
+
});
|
|
492
535
|
const BilibiliValidationSchemas = {
|
|
493
536
|
单个视频作品数据: BilibiliVideoParamsSchema,
|
|
494
537
|
单个视频下载信息数据: BilibiliVideoDownloadParamsSchema,
|
|
@@ -515,7 +558,8 @@ const BilibiliValidationSchemas = {
|
|
|
515
558
|
专栏文章基本信息: BilibiliArticleInfoParamsSchema,
|
|
516
559
|
文集基本信息: BilibiliColumnInfoParamsSchema,
|
|
517
560
|
从_v_voucher_申请_captcha: BilibiliApplyCaptchaParamsSchema,
|
|
518
|
-
验证验证码结果: BilibiliValidateCaptchaParamsSchema
|
|
561
|
+
验证验证码结果: BilibiliValidateCaptchaParamsSchema,
|
|
562
|
+
实时弹幕: BilibiliDanmakuParamsSchema
|
|
519
563
|
};
|
|
520
564
|
const BilibiliMethodRoutes = {
|
|
521
565
|
单个视频作品数据: "/fetch_one_video",
|
|
@@ -543,7 +587,8 @@ const BilibiliMethodRoutes = {
|
|
|
543
587
|
专栏文章基本信息: "/fetch_article_info",
|
|
544
588
|
文集基本信息: "/fetch_column_info",
|
|
545
589
|
从_v_voucher_申请_captcha: "/apply_captcha",
|
|
546
|
-
验证验证码结果: "/validate_captcha"
|
|
590
|
+
验证验证码结果: "/validate_captcha",
|
|
591
|
+
实时弹幕: "/fetch_danmaku"
|
|
547
592
|
};
|
|
548
593
|
|
|
549
594
|
//#endregion
|
|
@@ -713,51 +758,26 @@ var xiaohongshuSign = class {
|
|
|
713
758
|
return this.client.signXsPost(path$1, a1Cookie, clientType, body);
|
|
714
759
|
}
|
|
715
760
|
/**
|
|
716
|
-
* 生成X-S签名(兼容旧接口)
|
|
717
|
-
* @param url - 请求URL
|
|
718
|
-
* @param body - 请求体
|
|
719
|
-
* @param userAgent - User-Agent(暂未使用)
|
|
720
|
-
* @param method - 请求方法,默认为 'POST'
|
|
721
|
-
* @param a1Cookie - a1 cookie值
|
|
722
|
-
* @returns X-S签名
|
|
723
|
-
*/
|
|
724
|
-
static generateXS(url$1, body, userAgent, method = "POST", a1Cookie = "") {
|
|
725
|
-
try {
|
|
726
|
-
const urlObj = new URL(url$1);
|
|
727
|
-
const path$1 = urlObj.pathname + urlObj.search;
|
|
728
|
-
if (method.toUpperCase() === "GET") {
|
|
729
|
-
const params = typeof body === "object" ? body : {};
|
|
730
|
-
return this.generateXSGet(path$1, a1Cookie, "xhs-pc-web", params);
|
|
731
|
-
} else {
|
|
732
|
-
const requestBody = typeof body === "object" ? body : {};
|
|
733
|
-
return this.generateXSPost(path$1, a1Cookie, "xhs-pc-web", requestBody);
|
|
734
|
-
}
|
|
735
|
-
} catch (error) {
|
|
736
|
-
console.error("生成X-S签名失败:", error);
|
|
737
|
-
throw new Error(`签名生成失败: ${error}`);
|
|
738
|
-
}
|
|
739
|
-
}
|
|
740
|
-
/**
|
|
741
761
|
* 生成X-S-Common参数
|
|
742
|
-
* @param
|
|
762
|
+
* @param cookies - cookie字符串
|
|
743
763
|
* @returns Base64编码的随机字符串
|
|
744
764
|
*/
|
|
745
|
-
static generateXSCommon(
|
|
746
|
-
return
|
|
765
|
+
static generateXSCommon(cookies) {
|
|
766
|
+
return this.client.signXsCommon(cookies);
|
|
747
767
|
}
|
|
748
768
|
/**
|
|
749
769
|
* 生成X-T时间戳
|
|
750
770
|
* @returns 当前时间戳字符串
|
|
751
771
|
*/
|
|
752
772
|
static generateXT() {
|
|
753
|
-
return
|
|
773
|
+
return this.client.getXT();
|
|
754
774
|
}
|
|
755
775
|
/**
|
|
756
776
|
* 生成X-B3-Traceid
|
|
757
777
|
* @returns 16位随机字符串
|
|
758
778
|
*/
|
|
759
779
|
static generateXB3Traceid() {
|
|
760
|
-
return
|
|
780
|
+
return this.client.getB3TraceId();
|
|
761
781
|
}
|
|
762
782
|
/**
|
|
763
783
|
* 从cookie字符串中提取a1值
|
|
@@ -1243,7 +1263,8 @@ const fetchResponse = async (config, maxRetries = DEFAULT_MAX_RETRIES) => {
|
|
|
1243
1263
|
* 判断结果是否为网络错误响应
|
|
1244
1264
|
* @param result - 请求结果
|
|
1245
1265
|
* @returns 是否为ErrorResult
|
|
1246
|
-
*
|
|
1266
|
+
*
|
|
1267
|
+
* 通过检查 error 字段中的 amagiError 来区分网络错误和业务错误
|
|
1247
1268
|
*/
|
|
1248
1269
|
const isNetworkErrorResult = (result) => {
|
|
1249
1270
|
if (result === null || typeof result !== "object") return false;
|
|
@@ -1512,6 +1533,17 @@ var BiLiBiLiAPI = class {
|
|
|
1512
1533
|
}
|
|
1513
1534
|
};
|
|
1514
1535
|
}
|
|
1536
|
+
/**
|
|
1537
|
+
* 获取实时弹幕(web端 protobuf 接口)
|
|
1538
|
+
* @see https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/danmaku/danmaku_proto.md
|
|
1539
|
+
*/
|
|
1540
|
+
实时弹幕(data$1) {
|
|
1541
|
+
return `https://api.bilibili.com/x/v2/dm/web/seg.so?${new URLSearchParams({
|
|
1542
|
+
type: "1",
|
|
1543
|
+
oid: data$1.cid.toString(),
|
|
1544
|
+
segment_index: (data$1.segment_index ?? 1).toString()
|
|
1545
|
+
}).toString()}`;
|
|
1546
|
+
}
|
|
1515
1547
|
};
|
|
1516
1548
|
/** 该类下的所有方法只会返回拼接好参数后的 Url 地址,需要手动请求该地址以获取数据 */
|
|
1517
1549
|
const bilibiliApiUrls = new BiLiBiLiAPI();
|
|
@@ -1576,7 +1608,8 @@ const bilibili = {
|
|
|
1576
1608
|
getColumnInfo: createBilibiliApiMethod("文集基本信息"),
|
|
1577
1609
|
getUserProfileDetail: createBilibiliApiMethod("用户空间详细信息"),
|
|
1578
1610
|
applyVoucherCaptcha: createBilibiliApiMethod("从_v_voucher_申请_captcha"),
|
|
1579
|
-
validateCaptcha: createBilibiliApiMethod("验证验证码结果")
|
|
1611
|
+
validateCaptcha: createBilibiliApiMethod("验证验证码结果"),
|
|
1612
|
+
getDanmaku: createBilibiliApiMethod("实时弹幕")
|
|
1580
1613
|
};
|
|
1581
1614
|
/**
|
|
1582
1615
|
* 创建绑定了cookie的B站API对象
|
|
@@ -1610,7 +1643,8 @@ const createBoundBilibiliApi = (cookie, requestConfig) => {
|
|
|
1610
1643
|
getColumnInfo: createBoundBilibiliApiMethod("文集基本信息", cookie),
|
|
1611
1644
|
getUserProfileDetail: createBoundBilibiliApiMethod("用户空间详细信息", cookie),
|
|
1612
1645
|
applyVoucherCaptcha: createBoundBilibiliApiMethod("从_v_voucher_申请_captcha", cookie),
|
|
1613
|
-
validateCaptcha: createBoundBilibiliApiMethod("验证验证码结果", cookie)
|
|
1646
|
+
validateCaptcha: createBoundBilibiliApiMethod("验证验证码结果", cookie),
|
|
1647
|
+
getDanmaku: createBoundBilibiliApiMethod("实时弹幕", cookie)
|
|
1614
1648
|
};
|
|
1615
1649
|
};
|
|
1616
1650
|
|
|
@@ -1666,6 +1700,101 @@ const bv2av = (bvid) => {
|
|
|
1666
1700
|
return Number(tmp & MASK_CODE ^ XOR_CODE);
|
|
1667
1701
|
};
|
|
1668
1702
|
|
|
1703
|
+
//#endregion
|
|
1704
|
+
//#region src/platform/bilibili/sign/danmaku_proto.ts
|
|
1705
|
+
/**
|
|
1706
|
+
* B站弹幕 Protobuf 定义(内联)
|
|
1707
|
+
* @see https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/danmaku/danmaku_proto.md
|
|
1708
|
+
*/
|
|
1709
|
+
const DANMAKU_PROTO_JSON = { nested: { bilibili: { nested: { community: { nested: { service: { nested: { dm: { nested: { v1: { nested: {
|
|
1710
|
+
DmSegMobileReply: { fields: { elems: {
|
|
1711
|
+
rule: "repeated",
|
|
1712
|
+
type: "DanmakuElem",
|
|
1713
|
+
id: 1
|
|
1714
|
+
} } },
|
|
1715
|
+
DanmakuElem: { fields: {
|
|
1716
|
+
id: {
|
|
1717
|
+
type: "int64",
|
|
1718
|
+
id: 1
|
|
1719
|
+
},
|
|
1720
|
+
progress: {
|
|
1721
|
+
type: "int32",
|
|
1722
|
+
id: 2
|
|
1723
|
+
},
|
|
1724
|
+
mode: {
|
|
1725
|
+
type: "int32",
|
|
1726
|
+
id: 3
|
|
1727
|
+
},
|
|
1728
|
+
fontsize: {
|
|
1729
|
+
type: "int32",
|
|
1730
|
+
id: 4
|
|
1731
|
+
},
|
|
1732
|
+
color: {
|
|
1733
|
+
type: "uint32",
|
|
1734
|
+
id: 5
|
|
1735
|
+
},
|
|
1736
|
+
midHash: {
|
|
1737
|
+
type: "string",
|
|
1738
|
+
id: 6
|
|
1739
|
+
},
|
|
1740
|
+
content: {
|
|
1741
|
+
type: "string",
|
|
1742
|
+
id: 7
|
|
1743
|
+
},
|
|
1744
|
+
ctime: {
|
|
1745
|
+
type: "int64",
|
|
1746
|
+
id: 8
|
|
1747
|
+
},
|
|
1748
|
+
weight: {
|
|
1749
|
+
type: "int32",
|
|
1750
|
+
id: 9
|
|
1751
|
+
},
|
|
1752
|
+
action: {
|
|
1753
|
+
type: "string",
|
|
1754
|
+
id: 10
|
|
1755
|
+
},
|
|
1756
|
+
pool: {
|
|
1757
|
+
type: "int32",
|
|
1758
|
+
id: 11
|
|
1759
|
+
},
|
|
1760
|
+
idStr: {
|
|
1761
|
+
type: "string",
|
|
1762
|
+
id: 12
|
|
1763
|
+
},
|
|
1764
|
+
attr: {
|
|
1765
|
+
type: "int32",
|
|
1766
|
+
id: 13
|
|
1767
|
+
},
|
|
1768
|
+
animation: {
|
|
1769
|
+
type: "string",
|
|
1770
|
+
id: 22
|
|
1771
|
+
}
|
|
1772
|
+
} }
|
|
1773
|
+
} } } } } } } } } } } };
|
|
1774
|
+
let DmSegMobileReplyType = null;
|
|
1775
|
+
/**
|
|
1776
|
+
* 获取 protobuf 类型定义
|
|
1777
|
+
*/
|
|
1778
|
+
function getProtoType() {
|
|
1779
|
+
if (DmSegMobileReplyType) return DmSegMobileReplyType;
|
|
1780
|
+
DmSegMobileReplyType = protobuf.Root.fromJSON(DANMAKU_PROTO_JSON).lookupType("bilibili.community.service.dm.v1.DmSegMobileReply");
|
|
1781
|
+
return DmSegMobileReplyType;
|
|
1782
|
+
}
|
|
1783
|
+
/**
|
|
1784
|
+
* 解析弹幕分段响应
|
|
1785
|
+
* @param data - 二进制 protobuf 数据
|
|
1786
|
+
* @returns 解析后的弹幕数据
|
|
1787
|
+
*/
|
|
1788
|
+
function parseDmSegMobileReply(data$1) {
|
|
1789
|
+
const messageType = getProtoType();
|
|
1790
|
+
const buffer = data$1 instanceof Uint8Array ? data$1 : new Uint8Array(data$1);
|
|
1791
|
+
const message = messageType.decode(buffer);
|
|
1792
|
+
return messageType.toObject(message, {
|
|
1793
|
+
longs: String,
|
|
1794
|
+
defaults: true
|
|
1795
|
+
});
|
|
1796
|
+
}
|
|
1797
|
+
|
|
1669
1798
|
//#endregion
|
|
1670
1799
|
//#region src/platform/bilibili/sign/wbi.ts
|
|
1671
1800
|
/**
|
|
@@ -1965,6 +2094,7 @@ const bilibiliUtils = {
|
|
|
1965
2094
|
av2bv,
|
|
1966
2095
|
bv2av
|
|
1967
2096
|
},
|
|
2097
|
+
danmaku: { parseDmSegMobileReply },
|
|
1968
2098
|
bilibiliApiUrls,
|
|
1969
2099
|
api: bilibili
|
|
1970
2100
|
};
|
|
@@ -2304,6 +2434,48 @@ const fetchBilibili = async (data$1, cookie, requestConfig) => {
|
|
|
2304
2434
|
url: bilibiliApiUrls.验证验证码结果(data$1).Url,
|
|
2305
2435
|
data: bilibiliApiUrls.验证验证码结果(data$1).Body
|
|
2306
2436
|
});
|
|
2437
|
+
case "实时弹幕": {
|
|
2438
|
+
const url$1 = bilibiliApiUrls.实时弹幕({
|
|
2439
|
+
cid: data$1.cid,
|
|
2440
|
+
segment_index: data$1.segment_index
|
|
2441
|
+
});
|
|
2442
|
+
try {
|
|
2443
|
+
const response = await fetchData({
|
|
2444
|
+
...baseRequestConfig,
|
|
2445
|
+
url: url$1,
|
|
2446
|
+
responseType: "arraybuffer"
|
|
2447
|
+
});
|
|
2448
|
+
if (isNetworkErrorResult(response)) {
|
|
2449
|
+
const networkError = new Error(response.error.amagiError.errorDescription);
|
|
2450
|
+
Object.assign(networkError, {
|
|
2451
|
+
code: response.error.code,
|
|
2452
|
+
data: null,
|
|
2453
|
+
amagiError: {
|
|
2454
|
+
...response.error.amagiError,
|
|
2455
|
+
requestType: data$1.methodType
|
|
2456
|
+
}
|
|
2457
|
+
});
|
|
2458
|
+
throw networkError;
|
|
2459
|
+
}
|
|
2460
|
+
return {
|
|
2461
|
+
code: 0,
|
|
2462
|
+
message: "success",
|
|
2463
|
+
data: { elems: parseDmSegMobileReply(response).elems }
|
|
2464
|
+
};
|
|
2465
|
+
} catch (error) {
|
|
2466
|
+
if (error && typeof error === "object" && "code" in error) return error;
|
|
2467
|
+
const Err = {
|
|
2468
|
+
errorDescription: `获取弹幕数据失败:${error instanceof Error ? error.message : "未知错误"}`,
|
|
2469
|
+
requestType: data$1.methodType,
|
|
2470
|
+
requestUrl: url$1
|
|
2471
|
+
};
|
|
2472
|
+
return {
|
|
2473
|
+
code: amagiAPIErrorCode.UNKNOWN,
|
|
2474
|
+
data: null,
|
|
2475
|
+
amagiError: Err
|
|
2476
|
+
};
|
|
2477
|
+
}
|
|
2478
|
+
}
|
|
2307
2479
|
default:
|
|
2308
2480
|
logger.warn(`未知的B站数据接口:「${logger.red(data$1.methodType)}」`);
|
|
2309
2481
|
return null;
|
|
@@ -3649,11 +3821,53 @@ const DouyinData = async (data$1, cookie, requestConfig) => {
|
|
|
3649
3821
|
}
|
|
3650
3822
|
case "评论数据": {
|
|
3651
3823
|
const urlGenerator = (params) => douyinApiUrls$1.评论(params);
|
|
3652
|
-
return await fetchPaginatedData(
|
|
3824
|
+
return await fetchPaginatedData({
|
|
3825
|
+
type: data$1.methodType,
|
|
3826
|
+
apiUrlGenerator: urlGenerator,
|
|
3827
|
+
params: {
|
|
3828
|
+
...data$1,
|
|
3829
|
+
cursor: data$1.cursor ?? 0
|
|
3830
|
+
},
|
|
3831
|
+
maxPageSize: 50,
|
|
3832
|
+
requestConfig: baseRequestConfig,
|
|
3833
|
+
signType,
|
|
3834
|
+
extractList: (resp) => resp.comments ?? [],
|
|
3835
|
+
updateParams: (params, resp) => ({
|
|
3836
|
+
...params,
|
|
3837
|
+
cursor: resp.cursor
|
|
3838
|
+
}),
|
|
3839
|
+
hasMore: (resp) => resp.has_more === 1,
|
|
3840
|
+
formatFinalResponse: (resp, list) => ({
|
|
3841
|
+
...resp,
|
|
3842
|
+
comments: list,
|
|
3843
|
+
cursor: resp.cursor ?? list.length
|
|
3844
|
+
})
|
|
3845
|
+
});
|
|
3653
3846
|
}
|
|
3654
3847
|
case "指定评论回复数据": {
|
|
3655
3848
|
const urlGenerator = (params) => douyinApiUrls$1.二级评论(params);
|
|
3656
|
-
return await fetchPaginatedData(
|
|
3849
|
+
return await fetchPaginatedData({
|
|
3850
|
+
type: data$1.methodType,
|
|
3851
|
+
apiUrlGenerator: urlGenerator,
|
|
3852
|
+
params: {
|
|
3853
|
+
...data$1,
|
|
3854
|
+
cursor: data$1.cursor ?? 0
|
|
3855
|
+
},
|
|
3856
|
+
maxPageSize: 3,
|
|
3857
|
+
requestConfig: baseRequestConfig,
|
|
3858
|
+
signType: "x_bogus",
|
|
3859
|
+
extractList: (resp) => resp.comments ?? [],
|
|
3860
|
+
updateParams: (params, resp) => ({
|
|
3861
|
+
...params,
|
|
3862
|
+
cursor: resp.cursor
|
|
3863
|
+
}),
|
|
3864
|
+
hasMore: (resp) => resp.has_more === 1,
|
|
3865
|
+
formatFinalResponse: (resp, list) => ({
|
|
3866
|
+
...resp,
|
|
3867
|
+
comments: list,
|
|
3868
|
+
cursor: resp.cursor ?? list.length
|
|
3869
|
+
})
|
|
3870
|
+
});
|
|
3657
3871
|
}
|
|
3658
3872
|
case "用户主页数据": {
|
|
3659
3873
|
const url$1 = douyinApiUrls$1.用户主页信息({ sec_uid: data$1.sec_uid });
|
|
@@ -3705,10 +3919,6 @@ const DouyinData = async (data$1, cookie, requestConfig) => {
|
|
|
3705
3919
|
});
|
|
3706
3920
|
}
|
|
3707
3921
|
case "搜索数据": {
|
|
3708
|
-
let search_id = "";
|
|
3709
|
-
const maxPageSize = 15;
|
|
3710
|
-
let fetchedSearchList = [];
|
|
3711
|
-
let tmpresp = null;
|
|
3712
3922
|
const searchType = data$1.type ?? "综合";
|
|
3713
3923
|
const refererUrl = searchType === "用户" ? `https://www.douyin.com/search/${encodeURIComponent(String(data$1.query))}?type=user` : searchType === "视频" ? `https://www.douyin.com/search/${encodeURIComponent(String(data$1.query))}?type=video` : `https://www.douyin.com/root/search/${encodeURIComponent(String(data$1.query))}`;
|
|
3714
3924
|
const customConfig = {
|
|
@@ -3720,146 +3930,82 @@ const DouyinData = async (data$1, cookie, requestConfig) => {
|
|
|
3720
3930
|
};
|
|
3721
3931
|
const isUserSearch = searchType === "用户";
|
|
3722
3932
|
const isVideoSearch = searchType === "视频";
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
|
|
3933
|
+
return await fetchPaginatedData({
|
|
3934
|
+
type: data$1.methodType,
|
|
3935
|
+
apiUrlGenerator: (params) => douyinApiUrls$1.搜索(params),
|
|
3936
|
+
params: {
|
|
3727
3937
|
query: data$1.query,
|
|
3728
3938
|
type: data$1.type,
|
|
3729
|
-
number:
|
|
3730
|
-
search_id:
|
|
3731
|
-
}
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
请求类型:「${data$1.methodType}」
|
|
3746
|
-
搜索关键词:「${data$1.query}」
|
|
3747
|
-
请求URL:${url$1}
|
|
3748
|
-
`;
|
|
3749
|
-
!isFirstRequest && logger.warn(warningMessage);
|
|
3750
|
-
return {
|
|
3751
|
-
code: douoyinAPIErrorCode.COOKIE,
|
|
3752
|
-
data: raw,
|
|
3753
|
-
amagiError: Err,
|
|
3754
|
-
amagiMessage: warningMessage
|
|
3755
|
-
};
|
|
3756
|
-
}
|
|
3757
|
-
const userList = raw.user_list;
|
|
3758
|
-
if (isFirstRequest && (!userList || userList.length === 0)) {
|
|
3759
|
-
const Err = {
|
|
3760
|
-
errorDescription: "抖音用户搜索接口第一次请求就返回空数组,可能该关键词无搜索结果或触发风控限制,你的抖音Cookie可能已经失效!",
|
|
3761
|
-
requestType: data$1.methodType ?? "未知请求类型",
|
|
3762
|
-
requestUrl: url$1
|
|
3763
|
-
};
|
|
3764
|
-
const warningMessage = `
|
|
3765
|
-
获取响应数据失败!原因:${logger.yellow("用户搜索接口第一次请求就返回空数组,你的抖音Cookie可能已经失效!")}
|
|
3766
|
-
请求类型:「${data$1.methodType}」
|
|
3767
|
-
搜索关键词:「${data$1.query}」
|
|
3768
|
-
请求URL:${url$1}
|
|
3769
|
-
`;
|
|
3770
|
-
logger.warn(warningMessage);
|
|
3771
|
-
return {
|
|
3772
|
-
data: raw,
|
|
3773
|
-
amagiError: Err,
|
|
3774
|
-
amagiMessage: warningMessage
|
|
3775
|
-
};
|
|
3776
|
-
}
|
|
3777
|
-
if (Array.isArray(userList) && userList.length > 0) fetchedSearchList.push(...userList);
|
|
3778
|
-
tmpresp = raw;
|
|
3779
|
-
search_id = raw.rid ?? search_id;
|
|
3780
|
-
if (typeof raw.has_more === "number" && raw.has_more === 0) break;
|
|
3781
|
-
if (!userList || userList.length === 0) break;
|
|
3782
|
-
} else if (isVideoSearch) {
|
|
3783
|
-
if (!raw || typeof raw !== "object") {
|
|
3784
|
-
const Err = {
|
|
3785
|
-
errorDescription: "抖音视频搜索接口返回无有效数据,疑似触发反爬机制,你的抖音Cookie可能已经失效,你的抖音Cookie可能已经失效!",
|
|
3786
|
-
requestType: data$1.methodType ?? "未知请求类型",
|
|
3787
|
-
requestUrl: url$1
|
|
3788
|
-
};
|
|
3789
|
-
const warningMessage = `
|
|
3790
|
-
获取响应数据失败!原因:${logger.yellow("视频搜索接口返回无有效数据,疑似触发反爬机制,你的抖音Cookie可能已经失效!")}
|
|
3791
|
-
请求类型:「${data$1.methodType}」
|
|
3792
|
-
搜索关键词:「${data$1.query}」
|
|
3793
|
-
请求URL:${url$1}
|
|
3794
|
-
`;
|
|
3795
|
-
!isFirstRequest && logger.warn(warningMessage);
|
|
3796
|
-
return {
|
|
3797
|
-
code: douoyinAPIErrorCode.COOKIE,
|
|
3798
|
-
data: raw,
|
|
3799
|
-
amagiError: Err,
|
|
3800
|
-
amagiMessage: warningMessage
|
|
3801
|
-
};
|
|
3802
|
-
}
|
|
3803
|
-
const videoList = raw.data;
|
|
3804
|
-
if (isFirstRequest && (!videoList || videoList.length === 0)) {
|
|
3805
|
-
const Err = {
|
|
3806
|
-
errorDescription: "抖音视频搜索接口第一次请求就返回空数组,可能该关键词无搜索结果或触发风控限制,你的抖音Cookie可能已经失效!",
|
|
3807
|
-
requestType: data$1.methodType ?? "未知请求类型",
|
|
3808
|
-
requestUrl: url$1
|
|
3809
|
-
};
|
|
3810
|
-
const warningMessage = `
|
|
3811
|
-
获取响应数据失败!原因:${logger.yellow("视频搜索接口第一次请求就返回空数组,你的抖音Cookie可能已经失效!")}
|
|
3812
|
-
请求类型:「${data$1.methodType}」
|
|
3813
|
-
搜索关键词:「${data$1.query}」
|
|
3814
|
-
请求URL:${url$1}
|
|
3815
|
-
`;
|
|
3816
|
-
logger.warn(warningMessage);
|
|
3939
|
+
number: data$1.number ?? 10,
|
|
3940
|
+
search_id: ""
|
|
3941
|
+
},
|
|
3942
|
+
maxPageSize: 15,
|
|
3943
|
+
requestConfig: customConfig,
|
|
3944
|
+
signType: null,
|
|
3945
|
+
processRawResponse: (raw) => {
|
|
3946
|
+
if (!isUserSearch && !isVideoSearch) {
|
|
3947
|
+
const responses = filterSearchResponses(typeof raw === "string" ? parseDouyinMultiJson(raw) : [raw]);
|
|
3948
|
+
if (responses.length === 0) return raw;
|
|
3949
|
+
const mergedData = [];
|
|
3950
|
+
let lastValid = {};
|
|
3951
|
+
for (const resp of responses) {
|
|
3952
|
+
if (Array.isArray(resp.data) && resp.data.length > 0) mergedData.push(...resp.data);
|
|
3953
|
+
lastValid = resp;
|
|
3954
|
+
}
|
|
3817
3955
|
return {
|
|
3818
|
-
|
|
3819
|
-
|
|
3820
|
-
amagiMessage: warningMessage
|
|
3956
|
+
...lastValid,
|
|
3957
|
+
data: mergedData
|
|
3821
3958
|
};
|
|
3822
3959
|
}
|
|
3823
|
-
|
|
3824
|
-
|
|
3825
|
-
|
|
3826
|
-
if (
|
|
3827
|
-
|
|
3828
|
-
}
|
|
3829
|
-
|
|
3830
|
-
|
|
3831
|
-
|
|
3832
|
-
|
|
3833
|
-
|
|
3834
|
-
|
|
3835
|
-
|
|
3960
|
+
return raw;
|
|
3961
|
+
},
|
|
3962
|
+
extractList: (resp) => {
|
|
3963
|
+
if (isUserSearch) return resp.user_list ?? [];
|
|
3964
|
+
return resp.data ?? [];
|
|
3965
|
+
},
|
|
3966
|
+
updateParams: (params, resp) => {
|
|
3967
|
+
let nextSearchId = params.search_id;
|
|
3968
|
+
if (isUserSearch) nextSearchId = resp.rid ?? nextSearchId;
|
|
3969
|
+
else nextSearchId = resp.log_pb?.impr_id ?? nextSearchId;
|
|
3970
|
+
return {
|
|
3971
|
+
...params,
|
|
3972
|
+
search_id: nextSearchId
|
|
3973
|
+
};
|
|
3974
|
+
},
|
|
3975
|
+
hasMore: (resp) => {
|
|
3976
|
+
return resp.has_more !== 0;
|
|
3977
|
+
},
|
|
3978
|
+
validateFirstPage: (list, raw, url$1) => {
|
|
3979
|
+
const typeStr = isUserSearch ? "用户" : isVideoSearch ? "视频" : "综合";
|
|
3980
|
+
let isInvalidResponse = false;
|
|
3981
|
+
const rawAny = raw;
|
|
3982
|
+
if (!rawAny || typeof rawAny !== "object") isInvalidResponse = true;
|
|
3983
|
+
else if (isUserSearch && !rawAny.user_list) isInvalidResponse = true;
|
|
3984
|
+
else if (isVideoSearch && !rawAny.data) isInvalidResponse = true;
|
|
3985
|
+
else if (!isUserSearch && !isVideoSearch && !rawAny.data) isInvalidResponse = true;
|
|
3986
|
+
if (isInvalidResponse) {
|
|
3987
|
+
const desc = `抖音${typeStr}搜索返回无有效数据,疑似触发反爬机制,你的抖音Cookie可能已经失效!`;
|
|
3836
3988
|
const warningMessage = `
|
|
3837
|
-
获取响应数据失败!原因:${logger.yellow(
|
|
3989
|
+
获取响应数据失败!原因:${logger.yellow(`${typeStr}搜索返回无有效数据,疑似触发反爬机制`)}
|
|
3838
3990
|
请求类型:「${data$1.methodType}」
|
|
3839
3991
|
搜索关键词:「${data$1.query}」
|
|
3840
3992
|
请求URL:${url$1}
|
|
3841
3993
|
`;
|
|
3842
|
-
!isFirstRequest && logger.warn(warningMessage);
|
|
3843
3994
|
return {
|
|
3844
3995
|
code: douoyinAPIErrorCode.COOKIE,
|
|
3845
3996
|
data: raw,
|
|
3846
|
-
amagiError:
|
|
3997
|
+
amagiError: {
|
|
3998
|
+
errorDescription: desc,
|
|
3999
|
+
requestType: data$1.methodType ?? "未知请求类型",
|
|
4000
|
+
requestUrl: url$1
|
|
4001
|
+
},
|
|
3847
4002
|
amagiMessage: warningMessage
|
|
3848
4003
|
};
|
|
3849
4004
|
}
|
|
3850
|
-
|
|
3851
|
-
|
|
3852
|
-
tmpresp = resp;
|
|
3853
|
-
search_id = resp.log_pb?.impr_id ?? search_id;
|
|
3854
|
-
}
|
|
3855
|
-
if (isFirstRequest && fetchedSearchList.length === 0) {
|
|
3856
|
-
const Err = {
|
|
3857
|
-
errorDescription: "抖音综合搜索接口第一次请求就返回空数组,可能该关键词无搜索结果或触发风控限制,你的抖音Cookie可能已经失效!",
|
|
3858
|
-
requestType: data$1.methodType ?? "未知请求类型",
|
|
3859
|
-
requestUrl: url$1
|
|
3860
|
-
};
|
|
4005
|
+
if (!list || list.length === 0) {
|
|
4006
|
+
const desc = `抖音${typeStr}搜索接口第一次请求就返回空数组,可能该关键词无搜索结果或触发风控限制,你的抖音Cookie可能已经失效!`;
|
|
3861
4007
|
const warningMessage = `
|
|
3862
|
-
获取响应数据失败!原因:${logger.yellow(
|
|
4008
|
+
获取响应数据失败!原因:${logger.yellow(`${typeStr}搜索接口第一次请求就返回空数组,你的抖音Cookie可能已经失效!`)}
|
|
3863
4009
|
请求类型:「${data$1.methodType}」
|
|
3864
4010
|
搜索关键词:「${data$1.query}」
|
|
3865
4011
|
请求URL:${url$1}
|
|
@@ -3867,25 +4013,27 @@ const DouyinData = async (data$1, cookie, requestConfig) => {
|
|
|
3867
4013
|
logger.warn(warningMessage);
|
|
3868
4014
|
return {
|
|
3869
4015
|
data: raw,
|
|
3870
|
-
amagiError:
|
|
4016
|
+
amagiError: {
|
|
4017
|
+
errorDescription: desc,
|
|
4018
|
+
requestType: data$1.methodType ?? "未知请求类型",
|
|
4019
|
+
requestUrl: url$1
|
|
4020
|
+
},
|
|
3871
4021
|
amagiMessage: warningMessage
|
|
3872
4022
|
};
|
|
3873
4023
|
}
|
|
3874
|
-
|
|
4024
|
+
return null;
|
|
4025
|
+
},
|
|
4026
|
+
formatFinalResponse: (resp, list) => {
|
|
4027
|
+
if (isUserSearch) return {
|
|
4028
|
+
...resp,
|
|
4029
|
+
user_list: list
|
|
4030
|
+
};
|
|
4031
|
+
return {
|
|
4032
|
+
...resp,
|
|
4033
|
+
data: list
|
|
4034
|
+
};
|
|
3875
4035
|
}
|
|
3876
|
-
|
|
3877
|
-
}
|
|
3878
|
-
const slicedList = Number(data$1.number ?? 10) === 0 ? [] : fetchedSearchList.slice(0, Number(data$1.number ?? 10));
|
|
3879
|
-
return isUserSearch ? {
|
|
3880
|
-
...tmpresp ?? {},
|
|
3881
|
-
user_list: slicedList
|
|
3882
|
-
} : isVideoSearch ? {
|
|
3883
|
-
...tmpresp ?? {},
|
|
3884
|
-
data: slicedList
|
|
3885
|
-
} : {
|
|
3886
|
-
...tmpresp ?? {},
|
|
3887
|
-
data: slicedList
|
|
3888
|
-
};
|
|
4036
|
+
});
|
|
3889
4037
|
}
|
|
3890
4038
|
case "动态表情数据": {
|
|
3891
4039
|
const url$1 = douyinApiUrls$1.互动表情();
|
|
@@ -4021,40 +4169,48 @@ const DouyinData = async (data$1, cookie, requestConfig) => {
|
|
|
4021
4169
|
};
|
|
4022
4170
|
/**
|
|
4023
4171
|
* 通用的分页请求函数
|
|
4024
|
-
*
|
|
4025
|
-
*
|
|
4026
|
-
* @
|
|
4027
|
-
* @
|
|
4028
|
-
* @
|
|
4029
|
-
* @
|
|
4030
|
-
* @
|
|
4172
|
+
* 封装了循环分页请求、数据合并、错误处理和反爬检测逻辑
|
|
4173
|
+
*
|
|
4174
|
+
* @template T - 列表项类型
|
|
4175
|
+
* @template P - 参数类型
|
|
4176
|
+
* @template R - 返回值类型
|
|
4177
|
+
* @template RawResp - 原始响应类型
|
|
4178
|
+
* @param config - 分页请求配置对象
|
|
4179
|
+
* @returns Promise<R> 返回最终构造的数据对象
|
|
4031
4180
|
*/
|
|
4032
|
-
const fetchPaginatedData = async (
|
|
4033
|
-
|
|
4034
|
-
let
|
|
4035
|
-
|
|
4181
|
+
const fetchPaginatedData = async (config) => {
|
|
4182
|
+
const { type, apiUrlGenerator, params, maxPageSize, requestConfig, signType = "a_bogus", extractList, updateParams, hasMore, formatFinalResponse, processRawResponse, validateFirstPage } = config;
|
|
4183
|
+
let currentParams = { ...params };
|
|
4184
|
+
const fetchedData = [];
|
|
4185
|
+
let lastResponse = {};
|
|
4186
|
+
let isFirstRequest = true;
|
|
4036
4187
|
const userAgent = requestConfig.headers?.["User-Agent"];
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
const
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
const response = await GlobalGetData$2(type, {
|
|
4188
|
+
const targetNumber = Number(params.number ?? maxPageSize);
|
|
4189
|
+
while (fetchedData.length < targetNumber) {
|
|
4190
|
+
const remaining = targetNumber - fetchedData.length;
|
|
4191
|
+
currentParams.number = Math.min(remaining, maxPageSize);
|
|
4192
|
+
const url$1 = apiUrlGenerator(currentParams);
|
|
4193
|
+
const finalUrl = signType ? buildSignedUrl(url$1, signType, userAgent) : url$1;
|
|
4194
|
+
const raw = await GlobalGetData$2(type, {
|
|
4045
4195
|
...requestConfig,
|
|
4046
|
-
url:
|
|
4196
|
+
url: finalUrl
|
|
4047
4197
|
});
|
|
4048
|
-
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
|
|
4198
|
+
const response = processRawResponse ? processRawResponse(raw) : raw;
|
|
4199
|
+
if (response && response.amagiError) return response;
|
|
4200
|
+
const list = extractList(response);
|
|
4201
|
+
if (isFirstRequest && validateFirstPage) {
|
|
4202
|
+
const error = validateFirstPage(list, response, finalUrl);
|
|
4203
|
+
if (error) return error;
|
|
4204
|
+
}
|
|
4205
|
+
if (Array.isArray(list) && list.length > 0) fetchedData.push(...list);
|
|
4206
|
+
lastResponse = response;
|
|
4207
|
+
if (!hasMore(response)) break;
|
|
4208
|
+
if (!list || list.length === 0) break;
|
|
4209
|
+
currentParams = updateParams(currentParams, response);
|
|
4210
|
+
isFirstRequest = false;
|
|
4052
4211
|
}
|
|
4053
|
-
|
|
4054
|
-
|
|
4055
|
-
comments: params.number === 0 ? [] : fetchedData.slice(0, Number(params.number ?? maxPageSize)),
|
|
4056
|
-
cursor: params.number === 0 ? 0 : fetchedData.length
|
|
4057
|
-
};
|
|
4212
|
+
const slicedData = targetNumber === 0 ? [] : fetchedData.slice(0, targetNumber);
|
|
4213
|
+
return formatFinalResponse(lastResponse, slicedData);
|
|
4058
4214
|
};
|
|
4059
4215
|
/**
|
|
4060
4216
|
* 全局数据获取函数
|
|
@@ -4363,7 +4519,7 @@ const XiaohongshuData = async (data$1, cookie, requestConfig) => {
|
|
|
4363
4519
|
headers: {
|
|
4364
4520
|
...baseRequestConfig.headers,
|
|
4365
4521
|
"x-s": xiaohongshuSign.generateXSPost(xiaohongshuApiUrls$1.首页推荐数据(data$1).apiPath, xiaohongshuSign.extractA1FromCookie(cookie ?? ""), "xhs-pc-web", xiaohongshuApiUrls$1.首页推荐数据(data$1).Body),
|
|
4366
|
-
"x-s-common": xiaohongshuSign.generateXSCommon(),
|
|
4522
|
+
"x-s-common": xiaohongshuSign.generateXSCommon(cookie ?? ""),
|
|
4367
4523
|
"x-t": xiaohongshuSign.generateXT()
|
|
4368
4524
|
}
|
|
4369
4525
|
});
|
|
@@ -4374,7 +4530,7 @@ const XiaohongshuData = async (data$1, cookie, requestConfig) => {
|
|
|
4374
4530
|
headers: {
|
|
4375
4531
|
...baseRequestConfig.headers,
|
|
4376
4532
|
"x-s": xiaohongshuSign.generateXSPost(xiaohongshuApiUrls$1.单个笔记数据(data$1).apiPath, xiaohongshuSign.extractA1FromCookie(cookie ?? ""), "xhs-pc-web", xiaohongshuApiUrls$1.单个笔记数据(data$1).Body),
|
|
4377
|
-
"x-s-common": xiaohongshuSign.generateXSCommon(),
|
|
4533
|
+
"x-s-common": xiaohongshuSign.generateXSCommon(cookie ?? ""),
|
|
4378
4534
|
"x-t": xiaohongshuSign.generateXT()
|
|
4379
4535
|
}
|
|
4380
4536
|
});
|
|
@@ -4394,7 +4550,7 @@ const XiaohongshuData = async (data$1, cookie, requestConfig) => {
|
|
|
4394
4550
|
headers: {
|
|
4395
4551
|
...baseRequestConfig$1.headers,
|
|
4396
4552
|
"x-s": xiaohongshuSign.generateXSGet(xiaohongshuApiUrls$1.评论数据(data$1).apiPath, xiaohongshuSign.extractA1FromCookie(cookie ?? ""), "xhs-pc-web"),
|
|
4397
|
-
"x-s-common": xiaohongshuSign.generateXSCommon(),
|
|
4553
|
+
"x-s-common": xiaohongshuSign.generateXSCommon(cookie ?? ""),
|
|
4398
4554
|
"x-t": xiaohongshuSign.generateXT()
|
|
4399
4555
|
}
|
|
4400
4556
|
});
|
|
@@ -4417,7 +4573,7 @@ const XiaohongshuData = async (data$1, cookie, requestConfig) => {
|
|
|
4417
4573
|
headers: {
|
|
4418
4574
|
...baseRequestConfig$1.headers,
|
|
4419
4575
|
"x-s": xiaohongshuSign.generateXSGet(xiaohongshuApiUrls$1.用户数据(data$1).apiPath, xiaohongshuSign.extractA1FromCookie(cookie ?? ""), "xhs-pc-web"),
|
|
4420
|
-
"x-s-common": xiaohongshuSign.generateXSCommon(),
|
|
4576
|
+
"x-s-common": xiaohongshuSign.generateXSCommon(cookie ?? ""),
|
|
4421
4577
|
"x-t": xiaohongshuSign.generateXT()
|
|
4422
4578
|
}
|
|
4423
4579
|
})),
|
|
@@ -4432,7 +4588,7 @@ const XiaohongshuData = async (data$1, cookie, requestConfig) => {
|
|
|
4432
4588
|
...baseRequestConfig.headers,
|
|
4433
4589
|
"x-b3-traceid": xiaohongshuSign.generateXB3Traceid(),
|
|
4434
4590
|
"x-s": xiaohongshuSign.generateXSGet(xiaohongshuApiUrls$1.用户笔记数据(data$1).apiPath, xiaohongshuSign.extractA1FromCookie(cookie ?? ""), "xhs-pc-web"),
|
|
4435
|
-
"x-s-common": xiaohongshuSign.generateXSCommon(),
|
|
4591
|
+
"x-s-common": xiaohongshuSign.generateXSCommon(cookie ?? ""),
|
|
4436
4592
|
"x-t": xiaohongshuSign.generateXT()
|
|
4437
4593
|
}
|
|
4438
4594
|
});
|
|
@@ -4452,7 +4608,7 @@ const XiaohongshuData = async (data$1, cookie, requestConfig) => {
|
|
|
4452
4608
|
headers: {
|
|
4453
4609
|
...baseRequestConfig$1.headers,
|
|
4454
4610
|
"x-s": xiaohongshuSign.generateXSGet(xiaohongshuApiUrls$1.表情列表(data$1).apiPath, xiaohongshuSign.extractA1FromCookie(cookie ?? ""), "xhs-pc-web"),
|
|
4455
|
-
"x-s-common": xiaohongshuSign.generateXSCommon(),
|
|
4611
|
+
"x-s-common": xiaohongshuSign.generateXSCommon(cookie ?? ""),
|
|
4456
4612
|
"x-t": xiaohongshuSign.generateXT()
|
|
4457
4613
|
}
|
|
4458
4614
|
});
|
|
@@ -4464,7 +4620,7 @@ const XiaohongshuData = async (data$1, cookie, requestConfig) => {
|
|
|
4464
4620
|
headers: {
|
|
4465
4621
|
...baseRequestConfig.headers,
|
|
4466
4622
|
"x-s": xiaohongshuSign.generateXSPost(xiaohongshuApiUrls$1.搜索笔记(data$1).apiPath, xiaohongshuSign.extractA1FromCookie(cookie ?? ""), "xhs-pc-web"),
|
|
4467
|
-
"x-s-common": xiaohongshuSign.generateXSCommon(),
|
|
4623
|
+
"x-s-common": xiaohongshuSign.generateXSCommon(cookie ?? ""),
|
|
4468
4624
|
"x-t": xiaohongshuSign.generateXT()
|
|
4469
4625
|
}
|
|
4470
4626
|
});
|
|
@@ -4956,6 +5112,7 @@ const createAmagiClient = (options) => {
|
|
|
4956
5112
|
* @returns Express应用实例
|
|
4957
5113
|
*/
|
|
4958
5114
|
const startServer = (port = 4567) => {
|
|
5115
|
+
initLogger();
|
|
4959
5116
|
const app = express();
|
|
4960
5117
|
app.use(express.json());
|
|
4961
5118
|
app.use(express.urlencoded({ extended: true }));
|
|
@@ -5173,7 +5330,14 @@ let DynamicType = /* @__PURE__ */ function(DynamicType$1) {
|
|
|
5173
5330
|
|
|
5174
5331
|
//#endregion
|
|
5175
5332
|
//#region src/index.ts
|
|
5176
|
-
|
|
5333
|
+
/**
|
|
5334
|
+
* 获取版本号
|
|
5335
|
+
* 构建后使用 __VERSION__,开发环境从 package.json 读取
|
|
5336
|
+
*/
|
|
5337
|
+
const getVersion = () => {
|
|
5338
|
+
return "5.13.0";
|
|
5339
|
+
};
|
|
5340
|
+
const VERSION = getVersion();
|
|
5177
5341
|
/**
|
|
5178
5342
|
* @deprecated 请使用 createAmagiClient 替代
|
|
5179
5343
|
*/
|
|
@@ -5209,4 +5373,5 @@ const Client = CreateApp;
|
|
|
5209
5373
|
const amagi = Client;
|
|
5210
5374
|
|
|
5211
5375
|
//#endregion
|
|
5212
|
-
export { AdditionalType, ApiError, BilibiliApplyCaptchaParamsSchema, BilibiliArticleCardParamsSchema, BilibiliArticleInfoParamsSchema, BilibiliArticleParamsSchema, BilibiliAv2BvParamsSchema, BilibiliBangumiInfoParamsSchema, BilibiliBangumiStreamParamsSchema, BilibiliBv2AvParamsSchema, BilibiliColumnInfoParamsSchema, BilibiliCommentParamsSchema, BilibiliCommentReplyParamsSchema, BilibiliDynamicParamsSchema, BilibiliEmojiParamsSchema, BilibiliLiveParamsSchema, BilibiliLoginParamsSchema, BilibiliMethodRoutes, BilibiliQrcodeParamsSchema, BilibiliQrcodeStatusParamsSchema, BilibiliUserParamsSchema, BilibiliValidateCaptchaParamsSchema, BilibiliValidationSchemas, BilibiliVideoDownloadParamsSchema, BilibiliVideoParamsSchema, CommentType, CreateApp, DouyinCommentParamsSchema, DouyinCommentReplyParamsSchema, DouyinDanmakuParamsSchema, DouyinEmojiListParamsSchema, DouyinEmojiProParamsSchema, DouyinHotWordsParamsSchema, 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, isNetworkErrorResult, kuaishou, kuaishouApiUrls, kuaishouUtils, logMiddleware, logger, qtparam, validateBilibiliParams, validateDouyinParams, validateKuaishouParams, validateXiaohongshuParams, wbi_sign, xiaohongshu, xiaohongshuApiUrls, xiaohongshuSign, xiaohongshuUtils };
|
|
5376
|
+
export { AdditionalType, ApiError, BilibiliApplyCaptchaParamsSchema, BilibiliArticleCardParamsSchema, BilibiliArticleInfoParamsSchema, BilibiliArticleParamsSchema, BilibiliAv2BvParamsSchema, BilibiliBangumiInfoParamsSchema, BilibiliBangumiStreamParamsSchema, BilibiliBv2AvParamsSchema, BilibiliColumnInfoParamsSchema, BilibiliCommentParamsSchema, BilibiliCommentReplyParamsSchema, BilibiliDanmakuParamsSchema, BilibiliDynamicParamsSchema, BilibiliEmojiParamsSchema, BilibiliLiveParamsSchema, BilibiliLoginParamsSchema, BilibiliMethodRoutes, BilibiliQrcodeParamsSchema, BilibiliQrcodeStatusParamsSchema, BilibiliUserParamsSchema, BilibiliValidateCaptchaParamsSchema, BilibiliValidationSchemas, BilibiliVideoDownloadParamsSchema, BilibiliVideoParamsSchema, CommentType, CreateApp, DouyinCommentParamsSchema, DouyinCommentReplyParamsSchema, DouyinDanmakuParamsSchema, DouyinEmojiListParamsSchema, DouyinEmojiProParamsSchema, DouyinHotWordsParamsSchema, 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, initLogger, isNetworkErrorResult, kuaishou, kuaishouApiUrls, kuaishouUtils, logMiddleware, logger, parseDmSegMobileReply, qtparam, validateBilibiliParams, validateDouyinParams, validateKuaishouParams, validateXiaohongshuParams, wbi_sign, xiaohongshu, xiaohongshuApiUrls, xiaohongshuSign, xiaohongshuUtils };
|
|
5377
|
+
//# sourceMappingURL=index.js.map
|