@ikenxuan/amagi 5.2.0 → 5.4.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/README.md +4 -196
- package/dist/default/cjs/index.cjs +191 -8
- package/dist/default/esm/index.mjs +190 -8
- package/dist/default/index.d.ts +1598 -665
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -20,19 +20,8 @@ amagi 将作为一个独立的上游模块,提供给下游 [karin-plugin-kkk](
|
|
|
20
20
|
pnpm add @ikenxuan/amagi@latest
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
## 版本说明 📋
|
|
24
23
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
v4 版本保持向后兼容,是默认导入版本,适合现有项目的平滑迁移。
|
|
28
|
-
|
|
29
|
-
### v5 版本 (测试中 慎用) 🆕
|
|
30
|
-
|
|
31
|
-
v5 版本是当前的主要开发版本,提供了更好的错误处理、统一的响应格式和更强的类型安全性。
|
|
32
|
-
|
|
33
|
-
## 快速开始 (v4 版本) 🚀
|
|
34
|
-
|
|
35
|
-
### 基本用法 ✨
|
|
24
|
+
## 基本用法 ✨
|
|
36
25
|
主要就两个方法,`getDouyinData` 和 `getBilibiliData`。
|
|
37
26
|
|
|
38
27
|
> 它接收三个参数,
|
|
@@ -73,22 +62,6 @@ async function example() {
|
|
|
73
62
|
example()
|
|
74
63
|
```
|
|
75
64
|
|
|
76
|
-
## v5 版本完整指南 🆕
|
|
77
|
-
|
|
78
|
-
### v5 版本使用方式
|
|
79
|
-
|
|
80
|
-
```javascript
|
|
81
|
-
// v5 版本导入方式
|
|
82
|
-
import { createAmagiClient } from '@ikenxuan/amagi/v5'
|
|
83
|
-
// 或者
|
|
84
|
-
import amagi from '@ikenxuan/amagi/v5'
|
|
85
|
-
|
|
86
|
-
const client = createAmagiClient({ douyin: 'your_cookie' })
|
|
87
|
-
const result = await client.getDouyinData('搜索数据', { keyword: '测试' })
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
### v5 版本主要变化
|
|
91
|
-
|
|
92
65
|
#### 1. 统一的响应格式 📦
|
|
93
66
|
|
|
94
67
|
v5 版本所有 API 返回统一的响应格式:
|
|
@@ -116,6 +89,8 @@ if (result.success) {
|
|
|
116
89
|
|
|
117
90
|
#### 3. 类型模式控制 🎯
|
|
118
91
|
|
|
92
|
+
> 接口返回数据的类型类型为自动生成,仅供参考,不保证 100% 准确。
|
|
93
|
+
|
|
119
94
|
支持 `strict` 和 `loose` 两种类型模式:
|
|
120
95
|
|
|
121
96
|
```javascript
|
|
@@ -132,94 +107,6 @@ const looseResult = await client.getDouyinData(
|
|
|
132
107
|
)
|
|
133
108
|
```
|
|
134
109
|
|
|
135
|
-
#### 4. 强化的参数验证 🔍
|
|
136
|
-
v5 版本引入了 Zod 进行运行时参数验证,确保数据类型安全和参数完整性。
|
|
137
|
-
PS: 当前更改已在 v4.5.0 往后的版本实装
|
|
138
|
-
|
|
139
|
-
```javascript
|
|
140
|
-
// 自动参数验证
|
|
141
|
-
const result = await client.getDouyinData('搜索数据', {
|
|
142
|
-
keyword: '测试', // ✅ 必需参数
|
|
143
|
-
offset: 0, // ✅ 可选参数,类型正确
|
|
144
|
-
count: 20 // ✅ 可选参数,类型正确
|
|
145
|
-
})
|
|
146
|
-
|
|
147
|
-
// 参数验证失败示例
|
|
148
|
-
const invalidResult = await client.getDouyinData('搜索数据', {
|
|
149
|
-
// ❌ 缺少必需参数 keyword
|
|
150
|
-
offset: 'invalid' // ❌ 类型错误,应为 number
|
|
151
|
-
})
|
|
152
|
-
// 返回: { success: false, message: '参数验证失败: ...', code: 400 }
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
验证特性:
|
|
156
|
-
|
|
157
|
-
- 🔒 类型安全 :确保参数类型正确
|
|
158
|
-
- ✅ 必需参数检查 :自动验证必需参数是否存在
|
|
159
|
-
- 🎯 值范围验证 :验证数值范围、字符串长度等
|
|
160
|
-
- 🛡️ 注入防护 :防止恶意参数注入
|
|
161
|
-
- 📝 详细错误信息 :提供具体的验证失败原因
|
|
162
|
-
|
|
163
|
-
```javascript
|
|
164
|
-
// 验证错误响应示例
|
|
165
|
-
{
|
|
166
|
-
code: 400,
|
|
167
|
-
message: "参数验证失败",
|
|
168
|
-
data: null,
|
|
169
|
-
errors: [
|
|
170
|
-
{
|
|
171
|
-
path: ["keyword"],
|
|
172
|
-
message: "必需参数",
|
|
173
|
-
code: "invalid_type"
|
|
174
|
-
},
|
|
175
|
-
{
|
|
176
|
-
path: ["offset"],
|
|
177
|
-
message: "期望 number 类型,收到 string",
|
|
178
|
-
code: "invalid_type"
|
|
179
|
-
}
|
|
180
|
-
]
|
|
181
|
-
}
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
### v5 版本兼容性更改 🔄
|
|
185
|
-
|
|
186
|
-
#### 向后兼容性 ✅
|
|
187
|
-
|
|
188
|
-
- **v4 API 完全兼容**:现有的 v4 代码无需修改即可继续使用
|
|
189
|
-
- **默认导入保持 v4**:`import Client from '@ikenxuan/amagi'` 仍然使用 v4 版本
|
|
190
|
-
- **渐进式迁移**:可以逐步迁移到 v5 版本,无需一次性重写
|
|
191
|
-
|
|
192
|
-
#### 迁移指南 📖
|
|
193
|
-
|
|
194
|
-
##### 从 v4 迁移到 v5
|
|
195
|
-
|
|
196
|
-
1. **更新导入语句**:
|
|
197
|
-
```javascript
|
|
198
|
-
// v4
|
|
199
|
-
import Client from '@ikenxuan/amagi'
|
|
200
|
-
|
|
201
|
-
// v5
|
|
202
|
-
import Client from '@ikenxuan/amagi/v5'
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
2. **处理响应格式**:
|
|
206
|
-
```javascript
|
|
207
|
-
// v4 - 直接返回数据
|
|
208
|
-
const data = await amagi.getDouyinData('搜索数据', { keyword: '测试' })
|
|
209
|
-
|
|
210
|
-
// v5 - 包装的响应格式
|
|
211
|
-
const response = await client.getDouyinData('搜索数据', { keyword: '测试' })
|
|
212
|
-
const data = response.data
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
#### 破坏性变更 ⚠️
|
|
216
|
-
|
|
217
|
-
v5 版本的破坏性变更:
|
|
218
|
-
|
|
219
|
-
1. **响应格式变更**:所有 API 返回包装的响应对象而非直接数据
|
|
220
|
-
2. **服务器方法重命名**:`startClient()` 重命名为 `startServer()`
|
|
221
|
-
3. **错误处理方式**:错误不再抛出异常,而是在响应对象中返回
|
|
222
|
-
|
|
223
110
|
## 高级用法 🔧
|
|
224
111
|
|
|
225
112
|
### 启动本地 HTTP 服务 🌐
|
|
@@ -240,86 +127,7 @@ const app = amagi.startClient()
|
|
|
240
127
|
- 抖音 API: `http://localhost:4567/api/douyin/...` 📱
|
|
241
128
|
- bilibili API: `http://localhost:4567/api/bilibili/...` 📺
|
|
242
129
|
|
|
243
|
-
API 文档: https://amagi.apifox.cn 📝
|
|
244
|
-
|
|
245
|
-
## 平台功能模块 🧩
|
|
246
|
-
|
|
247
|
-
PS: 以下功能模块的使用方法与上述基本用法类似,我也不知道为什么要写这个。。。
|
|
248
|
-
|
|
249
|
-
### 抖音功能模块 📱
|
|
250
|
-
|
|
251
|
-
抖音相关功能模块提供了一系列工具和 API 接口,用于获取抖音平台的数据。
|
|
252
|
-
|
|
253
|
-
```javascript
|
|
254
|
-
import { douyinUtils } from '@ikenxuan/amagi'
|
|
255
|
-
|
|
256
|
-
// 使用签名算法
|
|
257
|
-
const mstoken = douyinUtils.sign.Mstoken(107)
|
|
258
|
-
const verifyFp = douyinUtils.sign.VerifyFpManager()
|
|
259
|
-
const abSign = douyinUtils.sign.AB('需要签名的地址')
|
|
260
|
-
|
|
261
|
-
// 使用 API 接口
|
|
262
|
-
const videoData = await douyinUtils.api.getWorkInfo(
|
|
263
|
-
{ ...opt },
|
|
264
|
-
'cookies'
|
|
265
|
-
)
|
|
266
|
-
|
|
267
|
-
const userInfo = await douyinUtils.api.getUserProfile(
|
|
268
|
-
{ ...opt },
|
|
269
|
-
'cookies'
|
|
270
|
-
)
|
|
271
|
-
|
|
272
|
-
// 直接获取数据
|
|
273
|
-
const searchResult = await douyinUtils.getDouyinData(
|
|
274
|
-
'搜索数据',
|
|
275
|
-
{ ...opt }
|
|
276
|
-
)
|
|
277
|
-
```
|
|
278
|
-
|
|
279
|
-
主要功能:
|
|
280
|
-
|
|
281
|
-
- 📹 视频/图集作品数据获取
|
|
282
|
-
- 👤 用户信息获取
|
|
283
|
-
- 💬 评论数据获取
|
|
284
|
-
- 🔍 搜索功能
|
|
285
|
-
- 🎬 直播间信息
|
|
286
|
-
- 🎵 音乐数据
|
|
287
|
-
- 😄 表情数据
|
|
288
|
-
|
|
289
|
-
### bilibili 功能模块 📺
|
|
290
|
-
|
|
291
|
-
bilibili 相关功能模块提供了获取 bilibili 平台数据的工具和 API。
|
|
292
|
-
|
|
293
|
-
```javascript
|
|
294
|
-
import { bilibiliUtils } from '@ikenxuan/amagi'
|
|
295
|
-
|
|
296
|
-
// 获取视频信息
|
|
297
|
-
const videoInfo = await bilibiliUtils.api.getVideoInfo({ ...opt })
|
|
298
|
-
|
|
299
|
-
// 获取评论数据
|
|
300
|
-
const comments = await bilibiliUtils.api.getComments({ ...opt })
|
|
301
|
-
|
|
302
|
-
// 直接获取数据
|
|
303
|
-
const userInfo = await bilibiliUtils.getBilibiliData(
|
|
304
|
-
'用户主页数据',
|
|
305
|
-
{ ...opt }
|
|
306
|
-
)
|
|
307
|
-
```
|
|
308
|
-
|
|
309
|
-
主要功能:
|
|
310
|
-
|
|
311
|
-
- 📹 视频信息获取
|
|
312
|
-
- 💬 评论数据获取
|
|
313
|
-
- 👤 用户信息获取
|
|
314
|
-
- 🎬 番剧信息获取
|
|
315
|
-
- 📡 直播间信息
|
|
316
|
-
- 📊 动态数据获取
|
|
317
|
-
- 🔄 AV/BV 号转换
|
|
318
|
-
|
|
319
|
-
## 类型支持 🧰
|
|
320
|
-
|
|
321
|
-
该库提供完整的 TypeScript 类型支持,可以获得良好的代码提示和类型检查。✅
|
|
322
|
-
虽有类型但写得和迷宫一样
|
|
130
|
+
API 文档: https://amagi.apifox.cn 或 https://ikenxuan.github.io/amagi📝
|
|
323
131
|
|
|
324
132
|
## 许可证 📜
|
|
325
133
|
|
|
@@ -27,7 +27,7 @@ var express__default = /*#__PURE__*/_interopDefault(express);
|
|
|
27
27
|
* GPL-3.0 Licensed
|
|
28
28
|
*/
|
|
29
29
|
|
|
30
|
-
// node_modules/.pnpm/tsup@8.5.0_@swc+core@1.13.
|
|
30
|
+
// node_modules/.pnpm/tsup@8.5.0_@swc+core@1.13.5_tsx@4.20.5_typescript@5.9.2_yaml@2.8.1/node_modules/tsup/assets/cjs_shims.js
|
|
31
31
|
var getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.src || new URL("main.js", document.baseURI).href;
|
|
32
32
|
var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
|
|
33
33
|
var getPackageLogsPath = () => {
|
|
@@ -44,6 +44,11 @@ var getPackageLogsPath = () => {
|
|
|
44
44
|
return path__default.default.join(packageRoot, "logs");
|
|
45
45
|
};
|
|
46
46
|
var logsPath = getPackageLogsPath();
|
|
47
|
+
var getLogLevel = () => {
|
|
48
|
+
const logLevel = process.env.LOG_LEVEL || "info";
|
|
49
|
+
return logLevel;
|
|
50
|
+
};
|
|
51
|
+
var currentLogLevel = getLogLevel();
|
|
47
52
|
log4js__default.default.configure({
|
|
48
53
|
appenders: {
|
|
49
54
|
console: {
|
|
@@ -84,7 +89,7 @@ log4js__default.default.configure({
|
|
|
84
89
|
}
|
|
85
90
|
},
|
|
86
91
|
categories: {
|
|
87
|
-
default: { appenders: ["console", "command"], level:
|
|
92
|
+
default: { appenders: ["console", "command"], level: currentLogLevel },
|
|
88
93
|
http: { appenders: ["httpConsole", "httpRequest"], level: "debug" }
|
|
89
94
|
},
|
|
90
95
|
pm2: true
|
|
@@ -1741,6 +1746,43 @@ var DouyinAPI = class {
|
|
|
1741
1746
|
};
|
|
1742
1747
|
return `${baseUrl}?${buildQueryString(params)}`;
|
|
1743
1748
|
}
|
|
1749
|
+
/**
|
|
1750
|
+
* 获取弹幕数据的接口地址
|
|
1751
|
+
* @param data - 请求参数,包含group_id、item_id等
|
|
1752
|
+
* @returns 完整的接口URL
|
|
1753
|
+
*/
|
|
1754
|
+
\u5F39\u5E55(data2) {
|
|
1755
|
+
const baseUrl = "https://www-hj.douyin.com/aweme/v1/web/danmaku/get_v2/";
|
|
1756
|
+
const params = {
|
|
1757
|
+
...this.getBaseParams(),
|
|
1758
|
+
app_name: "aweme",
|
|
1759
|
+
format: "json",
|
|
1760
|
+
group_id: data2.aweme_id,
|
|
1761
|
+
item_id: data2.aweme_id,
|
|
1762
|
+
start_time: data2.start_time ?? "0",
|
|
1763
|
+
end_time: data2.end_time ?? "32000",
|
|
1764
|
+
duration: data2.duration,
|
|
1765
|
+
update_version_code: "170400",
|
|
1766
|
+
pc_libra_divert: "Windows",
|
|
1767
|
+
support_h265: "1",
|
|
1768
|
+
support_dash: "1",
|
|
1769
|
+
version_code: "170400",
|
|
1770
|
+
version_name: "17.4.0",
|
|
1771
|
+
screen_width: "2328",
|
|
1772
|
+
screen_height: "1310",
|
|
1773
|
+
browser_name: "Edge",
|
|
1774
|
+
browser_version: "140.0.0.0",
|
|
1775
|
+
engine_name: "Blink",
|
|
1776
|
+
engine_version: "140.0.0.0",
|
|
1777
|
+
downlink: "1.55",
|
|
1778
|
+
round_trip_time: "200",
|
|
1779
|
+
webid: "7487210762873685515",
|
|
1780
|
+
msToken: douyinSign.Mstoken(116),
|
|
1781
|
+
verifyFp: fp,
|
|
1782
|
+
fp
|
|
1783
|
+
};
|
|
1784
|
+
return `${baseUrl}?${buildQueryString(params)}`;
|
|
1785
|
+
}
|
|
1744
1786
|
};
|
|
1745
1787
|
var createDouyinApiUrls = (userAgent) => {
|
|
1746
1788
|
return new DouyinAPI(userAgent);
|
|
@@ -1763,6 +1805,7 @@ var DouyinData = async (data2, cookie, requestConfig) => {
|
|
|
1763
1805
|
const userAgent = (_a = baseRequestConfig.headers) == null ? void 0 : _a["User-Agent"];
|
|
1764
1806
|
const douyinApiUrls3 = createDouyinApiUrls(userAgent);
|
|
1765
1807
|
switch (data2.methodType) {
|
|
1808
|
+
case "\u6587\u5B57\u4F5C\u54C1\u6570\u636E":
|
|
1766
1809
|
case "\u805A\u5408\u89E3\u6790":
|
|
1767
1810
|
case "\u89C6\u9891\u4F5C\u54C1\u6570\u636E":
|
|
1768
1811
|
case "\u56FE\u96C6\u4F5C\u54C1\u6570\u636E":
|
|
@@ -1987,6 +2030,84 @@ var DouyinData = async (data2, cookie, requestConfig) => {
|
|
|
1987
2030
|
});
|
|
1988
2031
|
return LoginQrcodeStatusData;
|
|
1989
2032
|
}
|
|
2033
|
+
case "\u5F39\u5E55\u6570\u636E": {
|
|
2034
|
+
const MAX_SEGMENT_DURATION = 32e3;
|
|
2035
|
+
const startTime = data2.start_time ?? 0;
|
|
2036
|
+
const endTime = data2.end_time ?? data2.duration;
|
|
2037
|
+
const totalDuration = endTime - startTime;
|
|
2038
|
+
if (totalDuration <= MAX_SEGMENT_DURATION) {
|
|
2039
|
+
const url = douyinApiUrls3.\u5F39\u5E55({
|
|
2040
|
+
aweme_id: data2.aweme_id,
|
|
2041
|
+
start_time: startTime,
|
|
2042
|
+
end_time: endTime,
|
|
2043
|
+
duration: data2.duration
|
|
2044
|
+
});
|
|
2045
|
+
const DanmakuData = await GlobalGetData2(data2.methodType, {
|
|
2046
|
+
...baseRequestConfig,
|
|
2047
|
+
url: `${url}&a_bogus=${douyinSign.AB(url, userAgent)}`
|
|
2048
|
+
});
|
|
2049
|
+
return DanmakuData;
|
|
2050
|
+
}
|
|
2051
|
+
const segments = [];
|
|
2052
|
+
let currentStart = startTime;
|
|
2053
|
+
while (currentStart < endTime) {
|
|
2054
|
+
const currentEnd = Math.min(currentStart + MAX_SEGMENT_DURATION, endTime);
|
|
2055
|
+
segments.push({ start: currentStart, end: currentEnd });
|
|
2056
|
+
currentStart = currentEnd;
|
|
2057
|
+
}
|
|
2058
|
+
logger.debug(`\u5F39\u5E55\u6570\u636E\u9700\u8981\u5206${segments.length}\u6BB5\u83B7\u53D6\uFF0C\u603B\u65F6\u957F\uFF1A${totalDuration}ms`);
|
|
2059
|
+
const segmentPromises = segments.map(async (segment, index) => {
|
|
2060
|
+
const url = douyinApiUrls3.\u5F39\u5E55({
|
|
2061
|
+
aweme_id: data2.aweme_id,
|
|
2062
|
+
start_time: segment.start,
|
|
2063
|
+
end_time: segment.end,
|
|
2064
|
+
duration: data2.duration
|
|
2065
|
+
});
|
|
2066
|
+
try {
|
|
2067
|
+
const segmentData = await GlobalGetData2(`${data2.methodType}-\u6BB5${index + 1}`, {
|
|
2068
|
+
...baseRequestConfig,
|
|
2069
|
+
url: `${url}&a_bogus=${douyinSign.AB(url, userAgent)}`
|
|
2070
|
+
});
|
|
2071
|
+
logger.debug(`\u5F39\u5E55\u7B2C${index + 1}\u6BB5\u83B7\u53D6\u6210\u529F (${segment.start}ms-${segment.end}ms)`);
|
|
2072
|
+
return segmentData;
|
|
2073
|
+
} catch (error) {
|
|
2074
|
+
logger.debug(`\u5F39\u5E55\u7B2C${index + 1}\u6BB5\u83B7\u53D6\u5931\u8D25 (${segment.start}ms-${segment.end}ms):`, error);
|
|
2075
|
+
return null;
|
|
2076
|
+
}
|
|
2077
|
+
});
|
|
2078
|
+
const segmentResults = await Promise.all(segmentPromises);
|
|
2079
|
+
const mergedDanmakuList = [];
|
|
2080
|
+
let totalCount = 0;
|
|
2081
|
+
let finalStartTime = startTime;
|
|
2082
|
+
let finalEndTime = endTime;
|
|
2083
|
+
let finalExtra = null;
|
|
2084
|
+
let finalLogPb = null;
|
|
2085
|
+
let finalStatusCode = 0;
|
|
2086
|
+
segmentResults.forEach((segmentData, index) => {
|
|
2087
|
+
if (segmentData && segmentData.danmaku_list) {
|
|
2088
|
+
mergedDanmakuList.push(...segmentData.danmaku_list);
|
|
2089
|
+
totalCount += segmentData.total || 0;
|
|
2090
|
+
if (index === 0) {
|
|
2091
|
+
finalExtra = segmentData.extra;
|
|
2092
|
+
finalLogPb = segmentData.log_pb;
|
|
2093
|
+
finalStatusCode = segmentData.status_code;
|
|
2094
|
+
}
|
|
2095
|
+
}
|
|
2096
|
+
});
|
|
2097
|
+
mergedDanmakuList.sort((a, b) => (a.offset_time || 0) - (b.offset_time || 0));
|
|
2098
|
+
const finalDanmakuData = {
|
|
2099
|
+
danmaku_list: mergedDanmakuList,
|
|
2100
|
+
start_time: finalStartTime,
|
|
2101
|
+
end_time: finalEndTime,
|
|
2102
|
+
total: mergedDanmakuList.length,
|
|
2103
|
+
// 使用实际合并后的数量
|
|
2104
|
+
status_code: finalStatusCode,
|
|
2105
|
+
extra: finalExtra,
|
|
2106
|
+
log_pb: finalLogPb
|
|
2107
|
+
};
|
|
2108
|
+
logger.debug(`\u5F39\u5E55\u6570\u636E\u5408\u5E76\u5B8C\u6210\uFF0C\u5171\u83B7\u53D6${mergedDanmakuList.length}\u6761\u5F39\u5E55`);
|
|
2109
|
+
return finalDanmakuData;
|
|
2110
|
+
}
|
|
1990
2111
|
default: {
|
|
1991
2112
|
logger.warn(`\u672A\u77E5\u7684\u6296\u97F3\u6570\u636E\u63A5\u53E3\uFF1A\u300C${logger.red(data2.methodType)}\u300D`);
|
|
1992
2113
|
return null;
|
|
@@ -2233,7 +2354,7 @@ var smartPositiveInteger = (errorMessage) => {
|
|
|
2233
2354
|
|
|
2234
2355
|
// src/validation/douyin.ts
|
|
2235
2356
|
var DouyinWorkParamsSchema = zod.z.object({
|
|
2236
|
-
methodType: zod.z.enum(["\u89C6\u9891\u4F5C\u54C1\u6570\u636E", "\u56FE\u96C6\u4F5C\u54C1\u6570\u636E", "\u5408\u8F91\u4F5C\u54C1\u6570\u636E", "\u805A\u5408\u89E3\u6790"]),
|
|
2357
|
+
methodType: zod.z.enum(["\u6587\u5B57\u4F5C\u54C1\u6570\u636E", "\u89C6\u9891\u4F5C\u54C1\u6570\u636E", "\u56FE\u96C6\u4F5C\u54C1\u6570\u636E", "\u5408\u8F91\u4F5C\u54C1\u6570\u636E", "\u805A\u5408\u89E3\u6790"]),
|
|
2237
2358
|
aweme_id: zod.z.string({ required_error: "\u89C6\u9891ID\u4E0D\u80FD\u4E3A\u7A7A" }).min(1, "\u89C6\u9891ID\u4E0D\u80FD\u4E3A\u7A7A")
|
|
2238
2359
|
});
|
|
2239
2360
|
var DouyinCommentParamsSchema = zod.z.object({
|
|
@@ -2273,7 +2394,37 @@ var DouyinEmojiListParamsSchema = zod.z.object({
|
|
|
2273
2394
|
var DouyinEmojiProParamsSchema = zod.z.object({
|
|
2274
2395
|
methodType: zod.z.literal("\u52A8\u6001\u8868\u60C5\u6570\u636E")
|
|
2275
2396
|
});
|
|
2397
|
+
var DouyinDanmakuParamsSchema = zod.z.object({
|
|
2398
|
+
methodType: zod.z.literal("\u5F39\u5E55\u6570\u636E"),
|
|
2399
|
+
aweme_id: zod.z.string({ required_error: "\u89C6\u9891ID\u4E0D\u80FD\u4E3A\u7A7A" }).min(1, "\u89C6\u9891ID\u4E0D\u80FD\u4E3A\u7A7A"),
|
|
2400
|
+
start_time: zod.z.coerce.number().int().min(0).optional(),
|
|
2401
|
+
end_time: zod.z.coerce.number().int().min(0).optional(),
|
|
2402
|
+
duration: zod.z.coerce.number().int().min(0)
|
|
2403
|
+
}).refine(
|
|
2404
|
+
(data2) => {
|
|
2405
|
+
if (data2.end_time !== void 0) {
|
|
2406
|
+
return data2.end_time <= data2.duration;
|
|
2407
|
+
}
|
|
2408
|
+
return true;
|
|
2409
|
+
},
|
|
2410
|
+
{
|
|
2411
|
+
message: "\u83B7\u53D6\u5F39\u5E55\u533A\u95F4\u7684\u7ED3\u675F\u65F6\u95F4\u4E0D\u80FD\u8D85\u8FC7\u89C6\u9891\u603B\u65F6\u957F",
|
|
2412
|
+
path: ["end_time"]
|
|
2413
|
+
}
|
|
2414
|
+
).refine(
|
|
2415
|
+
(data2) => {
|
|
2416
|
+
if (data2.start_time !== void 0 && data2.end_time !== void 0) {
|
|
2417
|
+
return data2.start_time < data2.end_time;
|
|
2418
|
+
}
|
|
2419
|
+
return true;
|
|
2420
|
+
},
|
|
2421
|
+
{
|
|
2422
|
+
message: "\u83B7\u53D6\u5F39\u5E55\u533A\u95F4\u7684\u5F00\u59CB\u65F6\u95F4\u5FC5\u987B\u5C0F\u4E8E\u7ED3\u675F\u65F6\u95F4",
|
|
2423
|
+
path: ["start_time"]
|
|
2424
|
+
}
|
|
2425
|
+
);
|
|
2276
2426
|
var DouyinValidationSchemas2 = {
|
|
2427
|
+
"\u6587\u5B57\u4F5C\u54C1\u6570\u636E": DouyinWorkParamsSchema,
|
|
2277
2428
|
"\u805A\u5408\u89E3\u6790": DouyinWorkParamsSchema,
|
|
2278
2429
|
"\u89C6\u9891\u4F5C\u54C1\u6570\u636E": DouyinWorkParamsSchema,
|
|
2279
2430
|
"\u56FE\u96C6\u4F5C\u54C1\u6570\u636E": DouyinWorkParamsSchema,
|
|
@@ -2288,7 +2439,8 @@ var DouyinValidationSchemas2 = {
|
|
|
2288
2439
|
"\u7533\u8BF7\u4E8C\u7EF4\u7801\u6570\u636E": DouyinQrcodeParamsSchema,
|
|
2289
2440
|
"Emoji\u6570\u636E": DouyinEmojiListParamsSchema,
|
|
2290
2441
|
"\u52A8\u6001\u8868\u60C5\u6570\u636E": DouyinEmojiProParamsSchema,
|
|
2291
|
-
"\u6307\u5B9A\u8BC4\u8BBA\u56DE\u590D\u6570\u636E": DouyinCommentReplyParamsSchema
|
|
2442
|
+
"\u6307\u5B9A\u8BC4\u8BBA\u56DE\u590D\u6570\u636E": DouyinCommentReplyParamsSchema,
|
|
2443
|
+
"\u5F39\u5E55\u6570\u636E": DouyinDanmakuParamsSchema
|
|
2292
2444
|
};
|
|
2293
2445
|
var BilibiliVideoParamsSchema = zod.z.object({
|
|
2294
2446
|
methodType: zod.z.literal("\u5355\u4E2A\u89C6\u9891\u4F5C\u54C1\u6570\u636E"),
|
|
@@ -2457,8 +2609,8 @@ async function getDouyinData(methodType, optionsOrCookie, cookieOrOptions, reque
|
|
|
2457
2609
|
...validatedParams
|
|
2458
2610
|
};
|
|
2459
2611
|
const rawData = await DouyinData(apiParams, cookie, config);
|
|
2460
|
-
if (rawData.data === "") {
|
|
2461
|
-
return createErrorResponse(rawData.amagiError, "\u6296\u97F3\u6570\u636E\u83B7\u53D6\u5931\u8D25");
|
|
2612
|
+
if (rawData.data === "" || rawData.status_code !== 0) {
|
|
2613
|
+
return createErrorResponse(rawData.amagiError, rawData.status_msg || "\u6296\u97F3\u6570\u636E\u83B7\u53D6\u5931\u8D25");
|
|
2462
2614
|
}
|
|
2463
2615
|
return createSuccessResponse(rawData, "\u83B7\u53D6\u6210\u529F", 200);
|
|
2464
2616
|
} catch (error) {
|
|
@@ -2999,6 +3151,13 @@ var createBoundDouyinApiMethod = (methodType, cookie, requestConfig) => {
|
|
|
2999
3151
|
};
|
|
3000
3152
|
};
|
|
3001
3153
|
var douyin = {
|
|
3154
|
+
/**
|
|
3155
|
+
* 获取文字作品数据
|
|
3156
|
+
* @param options 请求参数,包含 aweme_id 和可选的 typeMode
|
|
3157
|
+
* @param cookie 有效的用户 Cookie
|
|
3158
|
+
* @returns 统一格式的API响应,包含文字作品详细信息
|
|
3159
|
+
*/
|
|
3160
|
+
getTextWorkInfo: createDouyinApiMethod("\u6587\u5B57\u4F5C\u54C1\u6570\u636E"),
|
|
3002
3161
|
/**
|
|
3003
3162
|
* 聚合解析 (视频/图集/合辑)
|
|
3004
3163
|
* @param options 请求参数,包含 aweme_id 和可选的 typeMode
|
|
@@ -3096,10 +3255,22 @@ var douyin = {
|
|
|
3096
3255
|
* @param cookie 有效的用户 Cookie
|
|
3097
3256
|
* @returns 统一格式的API响应,包含直播间详细信息
|
|
3098
3257
|
*/
|
|
3099
|
-
getLiveRoomInfo: createDouyinApiMethod("\u76F4\u64AD\u95F4\u4FE1\u606F\u6570\u636E")
|
|
3258
|
+
getLiveRoomInfo: createDouyinApiMethod("\u76F4\u64AD\u95F4\u4FE1\u606F\u6570\u636E"),
|
|
3259
|
+
/**
|
|
3260
|
+
* 获取弹幕数据
|
|
3261
|
+
* @param options 请求参数,包含 aweme_id, 可选的 start_time, end_time, duration 和 typeMode
|
|
3262
|
+
* @returns 统一格式的API响应,包含弹幕数据
|
|
3263
|
+
*/
|
|
3264
|
+
getDanmaku: createDouyinApiMethod("\u5F39\u5E55\u6570\u636E")
|
|
3100
3265
|
};
|
|
3101
3266
|
var createBoundDouyinApi = (cookie, requestConfig) => {
|
|
3102
3267
|
return {
|
|
3268
|
+
/**
|
|
3269
|
+
* 获取文字作品数据
|
|
3270
|
+
* @param options 请求参数,包含 aweme_id 和可选的 typeMode
|
|
3271
|
+
* @returns 统一格式的API响应,包含文字作品详细信息
|
|
3272
|
+
*/
|
|
3273
|
+
getTextWorkInfo: createBoundDouyinApiMethod("\u6587\u5B57\u4F5C\u54C1\u6570\u636E", cookie, requestConfig),
|
|
3103
3274
|
/**
|
|
3104
3275
|
* 聚合解析 (视频/图集/合辑)
|
|
3105
3276
|
* @param options 请求参数,包含 aweme_id 和可选的 typeMode
|
|
@@ -3183,7 +3354,13 @@ var createBoundDouyinApi = (cookie, requestConfig) => {
|
|
|
3183
3354
|
* @param options 请求参数,包含 sec_uid 和可选的 typeMode
|
|
3184
3355
|
* @returns 统一格式的API响应,包含直播间详细信息
|
|
3185
3356
|
*/
|
|
3186
|
-
getLiveRoomInfo: createBoundDouyinApiMethod("\u76F4\u64AD\u95F4\u4FE1\u606F\u6570\u636E", cookie, requestConfig)
|
|
3357
|
+
getLiveRoomInfo: createBoundDouyinApiMethod("\u76F4\u64AD\u95F4\u4FE1\u606F\u6570\u636E", cookie, requestConfig),
|
|
3358
|
+
/**
|
|
3359
|
+
* 获取弹幕数据
|
|
3360
|
+
* @param options 请求参数,包含 aweme_id, 可选的 start_time, end_time, duration 和 typeMode
|
|
3361
|
+
* @returns 统一格式的API响应,包含弹幕数据
|
|
3362
|
+
*/
|
|
3363
|
+
getDanmaku: createBoundDouyinApiMethod("\u5F39\u5E55\u6570\u636E", cookie, requestConfig)
|
|
3187
3364
|
};
|
|
3188
3365
|
};
|
|
3189
3366
|
var createDouyinRouteHandler = (dataFetcher, methodType, cookie, requestConfig = getDouyinDefaultConfig(cookie)) => {
|
|
@@ -3275,6 +3452,11 @@ var createDouyinRoutes = (cookie, requestConfig = getDouyinDefaultConfig(cookie)
|
|
|
3275
3452
|
createDouyinValidationMiddleware("\u6307\u5B9A\u8BC4\u8BBA\u56DE\u590D\u6570\u636E"),
|
|
3276
3453
|
createDouyinRouteHandler(getDouyinData, "\u6307\u5B9A\u8BC4\u8BBA\u56DE\u590D\u6570\u636E", cookie, requestConfig)
|
|
3277
3454
|
);
|
|
3455
|
+
router.get(
|
|
3456
|
+
"/fetch_work_danmaku",
|
|
3457
|
+
createDouyinValidationMiddleware("\u5F39\u5E55\u6570\u636E"),
|
|
3458
|
+
createDouyinRouteHandler(getDouyinData, "\u5F39\u5E55\u6570\u636E", cookie, requestConfig)
|
|
3459
|
+
);
|
|
3278
3460
|
return router;
|
|
3279
3461
|
};
|
|
3280
3462
|
|
|
@@ -3528,6 +3710,7 @@ exports.BilibiliVideoParamsSchema = BilibiliVideoParamsSchema;
|
|
|
3528
3710
|
exports.CreateApp = CreateApp;
|
|
3529
3711
|
exports.DouyinCommentParamsSchema = DouyinCommentParamsSchema;
|
|
3530
3712
|
exports.DouyinCommentReplyParamsSchema = DouyinCommentReplyParamsSchema;
|
|
3713
|
+
exports.DouyinDanmakuParamsSchema = DouyinDanmakuParamsSchema;
|
|
3531
3714
|
exports.DouyinEmojiListParamsSchema = DouyinEmojiListParamsSchema;
|
|
3532
3715
|
exports.DouyinEmojiProParamsSchema = DouyinEmojiProParamsSchema;
|
|
3533
3716
|
exports.DouyinMusicParamsSchema = DouyinMusicParamsSchema;
|