@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.
@@ -28,6 +28,11 @@ var getPackageLogsPath = () => {
28
28
  return path.join(packageRoot, "logs");
29
29
  };
30
30
  var logsPath = getPackageLogsPath();
31
+ var getLogLevel = () => {
32
+ const logLevel = process.env.LOG_LEVEL || "info";
33
+ return logLevel;
34
+ };
35
+ var currentLogLevel = getLogLevel();
31
36
  log4js.configure({
32
37
  appenders: {
33
38
  console: {
@@ -68,7 +73,7 @@ log4js.configure({
68
73
  }
69
74
  },
70
75
  categories: {
71
- default: { appenders: ["console", "command"], level: "info" },
76
+ default: { appenders: ["console", "command"], level: currentLogLevel },
72
77
  http: { appenders: ["httpConsole", "httpRequest"], level: "debug" }
73
78
  },
74
79
  pm2: true
@@ -1725,6 +1730,43 @@ var DouyinAPI = class {
1725
1730
  };
1726
1731
  return `${baseUrl}?${buildQueryString(params)}`;
1727
1732
  }
1733
+ /**
1734
+ * 获取弹幕数据的接口地址
1735
+ * @param data - 请求参数,包含group_id、item_id等
1736
+ * @returns 完整的接口URL
1737
+ */
1738
+ \u5F39\u5E55(data2) {
1739
+ const baseUrl = "https://www-hj.douyin.com/aweme/v1/web/danmaku/get_v2/";
1740
+ const params = {
1741
+ ...this.getBaseParams(),
1742
+ app_name: "aweme",
1743
+ format: "json",
1744
+ group_id: data2.aweme_id,
1745
+ item_id: data2.aweme_id,
1746
+ start_time: data2.start_time ?? "0",
1747
+ end_time: data2.end_time ?? "32000",
1748
+ duration: data2.duration,
1749
+ update_version_code: "170400",
1750
+ pc_libra_divert: "Windows",
1751
+ support_h265: "1",
1752
+ support_dash: "1",
1753
+ version_code: "170400",
1754
+ version_name: "17.4.0",
1755
+ screen_width: "2328",
1756
+ screen_height: "1310",
1757
+ browser_name: "Edge",
1758
+ browser_version: "140.0.0.0",
1759
+ engine_name: "Blink",
1760
+ engine_version: "140.0.0.0",
1761
+ downlink: "1.55",
1762
+ round_trip_time: "200",
1763
+ webid: "7487210762873685515",
1764
+ msToken: douyinSign.Mstoken(116),
1765
+ verifyFp: fp,
1766
+ fp
1767
+ };
1768
+ return `${baseUrl}?${buildQueryString(params)}`;
1769
+ }
1728
1770
  };
1729
1771
  var createDouyinApiUrls = (userAgent) => {
1730
1772
  return new DouyinAPI(userAgent);
@@ -1747,6 +1789,7 @@ var DouyinData = async (data2, cookie, requestConfig) => {
1747
1789
  const userAgent = (_a = baseRequestConfig.headers) == null ? void 0 : _a["User-Agent"];
1748
1790
  const douyinApiUrls3 = createDouyinApiUrls(userAgent);
1749
1791
  switch (data2.methodType) {
1792
+ case "\u6587\u5B57\u4F5C\u54C1\u6570\u636E":
1750
1793
  case "\u805A\u5408\u89E3\u6790":
1751
1794
  case "\u89C6\u9891\u4F5C\u54C1\u6570\u636E":
1752
1795
  case "\u56FE\u96C6\u4F5C\u54C1\u6570\u636E":
@@ -1971,6 +2014,84 @@ var DouyinData = async (data2, cookie, requestConfig) => {
1971
2014
  });
1972
2015
  return LoginQrcodeStatusData;
1973
2016
  }
2017
+ case "\u5F39\u5E55\u6570\u636E": {
2018
+ const MAX_SEGMENT_DURATION = 32e3;
2019
+ const startTime = data2.start_time ?? 0;
2020
+ const endTime = data2.end_time ?? data2.duration;
2021
+ const totalDuration = endTime - startTime;
2022
+ if (totalDuration <= MAX_SEGMENT_DURATION) {
2023
+ const url = douyinApiUrls3.\u5F39\u5E55({
2024
+ aweme_id: data2.aweme_id,
2025
+ start_time: startTime,
2026
+ end_time: endTime,
2027
+ duration: data2.duration
2028
+ });
2029
+ const DanmakuData = await GlobalGetData2(data2.methodType, {
2030
+ ...baseRequestConfig,
2031
+ url: `${url}&a_bogus=${douyinSign.AB(url, userAgent)}`
2032
+ });
2033
+ return DanmakuData;
2034
+ }
2035
+ const segments = [];
2036
+ let currentStart = startTime;
2037
+ while (currentStart < endTime) {
2038
+ const currentEnd = Math.min(currentStart + MAX_SEGMENT_DURATION, endTime);
2039
+ segments.push({ start: currentStart, end: currentEnd });
2040
+ currentStart = currentEnd;
2041
+ }
2042
+ logger.debug(`\u5F39\u5E55\u6570\u636E\u9700\u8981\u5206${segments.length}\u6BB5\u83B7\u53D6\uFF0C\u603B\u65F6\u957F\uFF1A${totalDuration}ms`);
2043
+ const segmentPromises = segments.map(async (segment, index) => {
2044
+ const url = douyinApiUrls3.\u5F39\u5E55({
2045
+ aweme_id: data2.aweme_id,
2046
+ start_time: segment.start,
2047
+ end_time: segment.end,
2048
+ duration: data2.duration
2049
+ });
2050
+ try {
2051
+ const segmentData = await GlobalGetData2(`${data2.methodType}-\u6BB5${index + 1}`, {
2052
+ ...baseRequestConfig,
2053
+ url: `${url}&a_bogus=${douyinSign.AB(url, userAgent)}`
2054
+ });
2055
+ logger.debug(`\u5F39\u5E55\u7B2C${index + 1}\u6BB5\u83B7\u53D6\u6210\u529F (${segment.start}ms-${segment.end}ms)`);
2056
+ return segmentData;
2057
+ } catch (error) {
2058
+ logger.debug(`\u5F39\u5E55\u7B2C${index + 1}\u6BB5\u83B7\u53D6\u5931\u8D25 (${segment.start}ms-${segment.end}ms):`, error);
2059
+ return null;
2060
+ }
2061
+ });
2062
+ const segmentResults = await Promise.all(segmentPromises);
2063
+ const mergedDanmakuList = [];
2064
+ let totalCount = 0;
2065
+ let finalStartTime = startTime;
2066
+ let finalEndTime = endTime;
2067
+ let finalExtra = null;
2068
+ let finalLogPb = null;
2069
+ let finalStatusCode = 0;
2070
+ segmentResults.forEach((segmentData, index) => {
2071
+ if (segmentData && segmentData.danmaku_list) {
2072
+ mergedDanmakuList.push(...segmentData.danmaku_list);
2073
+ totalCount += segmentData.total || 0;
2074
+ if (index === 0) {
2075
+ finalExtra = segmentData.extra;
2076
+ finalLogPb = segmentData.log_pb;
2077
+ finalStatusCode = segmentData.status_code;
2078
+ }
2079
+ }
2080
+ });
2081
+ mergedDanmakuList.sort((a, b) => (a.offset_time || 0) - (b.offset_time || 0));
2082
+ const finalDanmakuData = {
2083
+ danmaku_list: mergedDanmakuList,
2084
+ start_time: finalStartTime,
2085
+ end_time: finalEndTime,
2086
+ total: mergedDanmakuList.length,
2087
+ // 使用实际合并后的数量
2088
+ status_code: finalStatusCode,
2089
+ extra: finalExtra,
2090
+ log_pb: finalLogPb
2091
+ };
2092
+ logger.debug(`\u5F39\u5E55\u6570\u636E\u5408\u5E76\u5B8C\u6210\uFF0C\u5171\u83B7\u53D6${mergedDanmakuList.length}\u6761\u5F39\u5E55`);
2093
+ return finalDanmakuData;
2094
+ }
1974
2095
  default: {
1975
2096
  logger.warn(`\u672A\u77E5\u7684\u6296\u97F3\u6570\u636E\u63A5\u53E3\uFF1A\u300C${logger.red(data2.methodType)}\u300D`);
1976
2097
  return null;
@@ -2217,7 +2338,7 @@ var smartPositiveInteger = (errorMessage) => {
2217
2338
 
2218
2339
  // src/validation/douyin.ts
2219
2340
  var DouyinWorkParamsSchema = z.object({
2220
- methodType: z.enum(["\u89C6\u9891\u4F5C\u54C1\u6570\u636E", "\u56FE\u96C6\u4F5C\u54C1\u6570\u636E", "\u5408\u8F91\u4F5C\u54C1\u6570\u636E", "\u805A\u5408\u89E3\u6790"]),
2341
+ methodType: 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"]),
2221
2342
  aweme_id: z.string({ required_error: "\u89C6\u9891ID\u4E0D\u80FD\u4E3A\u7A7A" }).min(1, "\u89C6\u9891ID\u4E0D\u80FD\u4E3A\u7A7A")
2222
2343
  });
2223
2344
  var DouyinCommentParamsSchema = z.object({
@@ -2257,7 +2378,37 @@ var DouyinEmojiListParamsSchema = z.object({
2257
2378
  var DouyinEmojiProParamsSchema = z.object({
2258
2379
  methodType: z.literal("\u52A8\u6001\u8868\u60C5\u6570\u636E")
2259
2380
  });
2381
+ var DouyinDanmakuParamsSchema = z.object({
2382
+ methodType: z.literal("\u5F39\u5E55\u6570\u636E"),
2383
+ aweme_id: z.string({ required_error: "\u89C6\u9891ID\u4E0D\u80FD\u4E3A\u7A7A" }).min(1, "\u89C6\u9891ID\u4E0D\u80FD\u4E3A\u7A7A"),
2384
+ start_time: z.coerce.number().int().min(0).optional(),
2385
+ end_time: z.coerce.number().int().min(0).optional(),
2386
+ duration: z.coerce.number().int().min(0)
2387
+ }).refine(
2388
+ (data2) => {
2389
+ if (data2.end_time !== void 0) {
2390
+ return data2.end_time <= data2.duration;
2391
+ }
2392
+ return true;
2393
+ },
2394
+ {
2395
+ message: "\u83B7\u53D6\u5F39\u5E55\u533A\u95F4\u7684\u7ED3\u675F\u65F6\u95F4\u4E0D\u80FD\u8D85\u8FC7\u89C6\u9891\u603B\u65F6\u957F",
2396
+ path: ["end_time"]
2397
+ }
2398
+ ).refine(
2399
+ (data2) => {
2400
+ if (data2.start_time !== void 0 && data2.end_time !== void 0) {
2401
+ return data2.start_time < data2.end_time;
2402
+ }
2403
+ return true;
2404
+ },
2405
+ {
2406
+ message: "\u83B7\u53D6\u5F39\u5E55\u533A\u95F4\u7684\u5F00\u59CB\u65F6\u95F4\u5FC5\u987B\u5C0F\u4E8E\u7ED3\u675F\u65F6\u95F4",
2407
+ path: ["start_time"]
2408
+ }
2409
+ );
2260
2410
  var DouyinValidationSchemas2 = {
2411
+ "\u6587\u5B57\u4F5C\u54C1\u6570\u636E": DouyinWorkParamsSchema,
2261
2412
  "\u805A\u5408\u89E3\u6790": DouyinWorkParamsSchema,
2262
2413
  "\u89C6\u9891\u4F5C\u54C1\u6570\u636E": DouyinWorkParamsSchema,
2263
2414
  "\u56FE\u96C6\u4F5C\u54C1\u6570\u636E": DouyinWorkParamsSchema,
@@ -2272,7 +2423,8 @@ var DouyinValidationSchemas2 = {
2272
2423
  "\u7533\u8BF7\u4E8C\u7EF4\u7801\u6570\u636E": DouyinQrcodeParamsSchema,
2273
2424
  "Emoji\u6570\u636E": DouyinEmojiListParamsSchema,
2274
2425
  "\u52A8\u6001\u8868\u60C5\u6570\u636E": DouyinEmojiProParamsSchema,
2275
- "\u6307\u5B9A\u8BC4\u8BBA\u56DE\u590D\u6570\u636E": DouyinCommentReplyParamsSchema
2426
+ "\u6307\u5B9A\u8BC4\u8BBA\u56DE\u590D\u6570\u636E": DouyinCommentReplyParamsSchema,
2427
+ "\u5F39\u5E55\u6570\u636E": DouyinDanmakuParamsSchema
2276
2428
  };
2277
2429
  var BilibiliVideoParamsSchema = z.object({
2278
2430
  methodType: z.literal("\u5355\u4E2A\u89C6\u9891\u4F5C\u54C1\u6570\u636E"),
@@ -2441,8 +2593,8 @@ async function getDouyinData(methodType, optionsOrCookie, cookieOrOptions, reque
2441
2593
  ...validatedParams
2442
2594
  };
2443
2595
  const rawData = await DouyinData(apiParams, cookie, config);
2444
- if (rawData.data === "") {
2445
- return createErrorResponse(rawData.amagiError, "\u6296\u97F3\u6570\u636E\u83B7\u53D6\u5931\u8D25");
2596
+ if (rawData.data === "" || rawData.status_code !== 0) {
2597
+ return createErrorResponse(rawData.amagiError, rawData.status_msg || "\u6296\u97F3\u6570\u636E\u83B7\u53D6\u5931\u8D25");
2446
2598
  }
2447
2599
  return createSuccessResponse(rawData, "\u83B7\u53D6\u6210\u529F", 200);
2448
2600
  } catch (error) {
@@ -2983,6 +3135,13 @@ var createBoundDouyinApiMethod = (methodType, cookie, requestConfig) => {
2983
3135
  };
2984
3136
  };
2985
3137
  var douyin = {
3138
+ /**
3139
+ * 获取文字作品数据
3140
+ * @param options 请求参数,包含 aweme_id 和可选的 typeMode
3141
+ * @param cookie 有效的用户 Cookie
3142
+ * @returns 统一格式的API响应,包含文字作品详细信息
3143
+ */
3144
+ getTextWorkInfo: createDouyinApiMethod("\u6587\u5B57\u4F5C\u54C1\u6570\u636E"),
2986
3145
  /**
2987
3146
  * 聚合解析 (视频/图集/合辑)
2988
3147
  * @param options 请求参数,包含 aweme_id 和可选的 typeMode
@@ -3080,10 +3239,22 @@ var douyin = {
3080
3239
  * @param cookie 有效的用户 Cookie
3081
3240
  * @returns 统一格式的API响应,包含直播间详细信息
3082
3241
  */
3083
- getLiveRoomInfo: createDouyinApiMethod("\u76F4\u64AD\u95F4\u4FE1\u606F\u6570\u636E")
3242
+ getLiveRoomInfo: createDouyinApiMethod("\u76F4\u64AD\u95F4\u4FE1\u606F\u6570\u636E"),
3243
+ /**
3244
+ * 获取弹幕数据
3245
+ * @param options 请求参数,包含 aweme_id, 可选的 start_time, end_time, duration 和 typeMode
3246
+ * @returns 统一格式的API响应,包含弹幕数据
3247
+ */
3248
+ getDanmaku: createDouyinApiMethod("\u5F39\u5E55\u6570\u636E")
3084
3249
  };
3085
3250
  var createBoundDouyinApi = (cookie, requestConfig) => {
3086
3251
  return {
3252
+ /**
3253
+ * 获取文字作品数据
3254
+ * @param options 请求参数,包含 aweme_id 和可选的 typeMode
3255
+ * @returns 统一格式的API响应,包含文字作品详细信息
3256
+ */
3257
+ getTextWorkInfo: createBoundDouyinApiMethod("\u6587\u5B57\u4F5C\u54C1\u6570\u636E", cookie, requestConfig),
3087
3258
  /**
3088
3259
  * 聚合解析 (视频/图集/合辑)
3089
3260
  * @param options 请求参数,包含 aweme_id 和可选的 typeMode
@@ -3167,7 +3338,13 @@ var createBoundDouyinApi = (cookie, requestConfig) => {
3167
3338
  * @param options 请求参数,包含 sec_uid 和可选的 typeMode
3168
3339
  * @returns 统一格式的API响应,包含直播间详细信息
3169
3340
  */
3170
- getLiveRoomInfo: createBoundDouyinApiMethod("\u76F4\u64AD\u95F4\u4FE1\u606F\u6570\u636E", cookie, requestConfig)
3341
+ getLiveRoomInfo: createBoundDouyinApiMethod("\u76F4\u64AD\u95F4\u4FE1\u606F\u6570\u636E", cookie, requestConfig),
3342
+ /**
3343
+ * 获取弹幕数据
3344
+ * @param options 请求参数,包含 aweme_id, 可选的 start_time, end_time, duration 和 typeMode
3345
+ * @returns 统一格式的API响应,包含弹幕数据
3346
+ */
3347
+ getDanmaku: createBoundDouyinApiMethod("\u5F39\u5E55\u6570\u636E", cookie, requestConfig)
3171
3348
  };
3172
3349
  };
3173
3350
  var createDouyinRouteHandler = (dataFetcher, methodType, cookie, requestConfig = getDouyinDefaultConfig(cookie)) => {
@@ -3259,6 +3436,11 @@ var createDouyinRoutes = (cookie, requestConfig = getDouyinDefaultConfig(cookie)
3259
3436
  createDouyinValidationMiddleware("\u6307\u5B9A\u8BC4\u8BBA\u56DE\u590D\u6570\u636E"),
3260
3437
  createDouyinRouteHandler(getDouyinData, "\u6307\u5B9A\u8BC4\u8BBA\u56DE\u590D\u6570\u636E", cookie, requestConfig)
3261
3438
  );
3439
+ router.get(
3440
+ "/fetch_work_danmaku",
3441
+ createDouyinValidationMiddleware("\u5F39\u5E55\u6570\u636E"),
3442
+ createDouyinRouteHandler(getDouyinData, "\u5F39\u5E55\u6570\u636E", cookie, requestConfig)
3443
+ );
3262
3444
  return router;
3263
3445
  };
3264
3446
 
@@ -3492,4 +3674,4 @@ var amagi = Client;
3492
3674
  * GPL-3.0 Licensed
3493
3675
  */
3494
3676
 
3495
- export { AdditionalType, ApiError, BilibiliAv2BvParamsSchema, BilibiliBangumiInfoParamsSchema, BilibiliBangumiStreamParamsSchema, BilibiliBv2AvParamsSchema, BilibiliCommentParamsSchema, BilibiliDynamicParamsSchema, BilibiliEmojiParamsSchema, BilibiliLiveParamsSchema, BilibiliLoginParamsSchema, BilibiliQrcodeParamsSchema, BilibiliQrcodeStatusParamsSchema, BilibiliUserParamsSchema, BilibiliValidationSchemas2 as BilibiliValidationSchemas, BilibiliVideoDownloadParamsSchema, BilibiliVideoParamsSchema, CreateApp, DouyinCommentParamsSchema, DouyinCommentReplyParamsSchema, DouyinEmojiListParamsSchema, DouyinEmojiProParamsSchema, DouyinMusicParamsSchema, DouyinQrcodeParamsSchema, DouyinSearchParamsSchema, DouyinUserParamsSchema, DouyinValidationSchemas2 as DouyinValidationSchemas, DouyinWorkParamsSchema, DynamicType, KuaishouCommentParamsSchema, KuaishouEmojiParamsSchema, KuaishouValidationSchemas2 as KuaishouValidationSchemas, KuaishouVideoParamsSchema, MajorType, ValidationError, amagi, amagiClient, av2bv, bilibili, bilibiliApiUrls, bilibiliErrorCodeMap, bilibiliUtils, bv2av, createAmagiClient, createBilibiliRoutes, createBoundBilibiliApi, createBoundDouyinApi, createBoundKuaishouApi, createDouyinRoutes, createErrorResponse, createKuaishouRoutes, createSuccessResponse, Client as default, douyin, douyinApiUrls, douyinSign, douyinUtils, fetchData, fetchResponse, getBilibiliData, getDouyinData, getHeadersAndData, getKuaishouData, handleError, httpLogger, kuaishou, kuaishouApiUrls, kuaishouUtils, logMiddleware, logger, qtparam, createBilibiliRoutes as registerBilibiliRoutes, createDouyinRoutes as registerDouyinRoutes, createKuaishouRoutes as registerKuaishouRoutes, validateBilibiliParams, validateDouyinParams, validateKuaishouParams, wbi_sign };
3677
+ export { AdditionalType, ApiError, BilibiliAv2BvParamsSchema, BilibiliBangumiInfoParamsSchema, BilibiliBangumiStreamParamsSchema, BilibiliBv2AvParamsSchema, BilibiliCommentParamsSchema, BilibiliDynamicParamsSchema, BilibiliEmojiParamsSchema, BilibiliLiveParamsSchema, BilibiliLoginParamsSchema, BilibiliQrcodeParamsSchema, BilibiliQrcodeStatusParamsSchema, BilibiliUserParamsSchema, BilibiliValidationSchemas2 as BilibiliValidationSchemas, BilibiliVideoDownloadParamsSchema, BilibiliVideoParamsSchema, CreateApp, DouyinCommentParamsSchema, DouyinCommentReplyParamsSchema, DouyinDanmakuParamsSchema, DouyinEmojiListParamsSchema, DouyinEmojiProParamsSchema, DouyinMusicParamsSchema, DouyinQrcodeParamsSchema, DouyinSearchParamsSchema, DouyinUserParamsSchema, DouyinValidationSchemas2 as DouyinValidationSchemas, DouyinWorkParamsSchema, DynamicType, KuaishouCommentParamsSchema, KuaishouEmojiParamsSchema, KuaishouValidationSchemas2 as KuaishouValidationSchemas, KuaishouVideoParamsSchema, MajorType, ValidationError, amagi, amagiClient, av2bv, bilibili, bilibiliApiUrls, bilibiliErrorCodeMap, bilibiliUtils, bv2av, createAmagiClient, createBilibiliRoutes, createBoundBilibiliApi, createBoundDouyinApi, createBoundKuaishouApi, createDouyinRoutes, createErrorResponse, createKuaishouRoutes, createSuccessResponse, Client as default, douyin, douyinApiUrls, douyinSign, douyinUtils, fetchData, fetchResponse, getBilibiliData, getDouyinData, getHeadersAndData, getKuaishouData, handleError, httpLogger, kuaishou, kuaishouApiUrls, kuaishouUtils, logMiddleware, logger, qtparam, createBilibiliRoutes as registerBilibiliRoutes, createDouyinRoutes as registerDouyinRoutes, createKuaishouRoutes as registerKuaishouRoutes, validateBilibiliParams, validateDouyinParams, validateKuaishouParams, wbi_sign };