@iflyrpa/actions 4.0.5 → 4.0.6

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/bundle.js CHANGED
@@ -12474,6 +12474,8 @@ var __webpack_exports__ = {};
12474
12474
  bjhConfigDataSchema: ()=>bjhConfigDataSchema,
12475
12475
  Action: ()=>Action,
12476
12476
  ProxyAgent: ()=>ProxyAgent,
12477
+ douyinConfigDataSchema: ()=>douyinConfigDataSchema,
12478
+ shipinhaoConfigDataSchema: ()=>shipinhaoConfigDataSchema,
12477
12479
  version: ()=>package_namespaceObject_0.i8
12478
12480
  });
12479
12481
  var common_utils_namespaceObject = {};
@@ -12489,7 +12491,7 @@ var __webpack_exports__ = {};
12489
12491
  i8: "0.1.2"
12490
12492
  };
12491
12493
  var package_namespaceObject_0 = {
12492
- i8: "4.0.5"
12494
+ i8: "4.0.6"
12493
12495
  };
12494
12496
  const external_node_fs_namespaceObject = require("node:fs");
12495
12497
  var external_node_fs_default = /*#__PURE__*/ __webpack_require__.n(external_node_fs_namespaceObject);
@@ -27270,11 +27272,12 @@ var __webpack_exports__ = {};
27270
27272
  this.logger?.debug(`未处理的网络错误代码: ${error.code} ${error.message}`, {
27271
27273
  errorString: stringifyError(error)
27272
27274
  });
27273
- _message = `未知网络错误: ${error.message}`;
27275
+ _message = `网络错误: ${error.message}`;
27274
27276
  break;
27275
27277
  }
27276
27278
  }
27277
- errorResponse.message = errorResponse.message ? errorResponse.message : _message;
27279
+ if (error.code && !error.response?.data) errorResponse.message = _message || errorResponse.message;
27280
+ else errorResponse.message = errorResponse.message ? errorResponse.message : _message;
27278
27281
  if ("canceled" === errorResponse.message) {
27279
27282
  const message = errorResponse.extra?.isProxyRequest ? "代理连接建立超时,请更换区域或稍后重试!" : "网络请求超时,请稍后重试!";
27280
27283
  errorResponse.message = message;
@@ -38513,400 +38516,421 @@ var __webpack_exports__ = {};
38513
38516
  }
38514
38517
  return randomString;
38515
38518
  }
38519
+ function safeSerialize(obj) {
38520
+ if (!obj || "object" != typeof obj) return obj;
38521
+ try {
38522
+ return JSON.parse(JSON.stringify(obj));
38523
+ } catch (error) {
38524
+ return {};
38525
+ }
38526
+ }
38516
38527
  const mock_mockAction = async (task, params)=>{
38517
38528
  const updateTaskState = task.taskStageStore?.update?.bind(task.taskStageStore, task.taskId || "");
38518
38529
  if (!params.extraParam || !params.extraParam["security-sdk/s_sdk_pri_key"] || !params.extraParam["security-sdk/s_sdk_pub_key"] || !params.extraParam["security-sdk/s_sdk_sign_data_key/web_protect"] || !params.extraParam["security-sdk/s_sdk_server_cert_key"] || !params.extraParam["security-sdk/s_sdk_crypt_sdk"]) return utils_response(414, "extraParam 参数缺失或不完整", "");
38519
- const userAgent = params.userAgent || "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.38";
38520
- const sessionidCookie = params.cookies.find((it)=>"msToken" === it.name)?.value;
38521
- if (!sessionidCookie) return {
38522
- code: 414,
38523
- message: "账号数据异常,请重新绑定账号后重试。",
38524
- data: ""
38525
- };
38526
- const headers = {
38527
- cookie: params.cookies.map((it)=>`${it.name}=${it.value}`).join(";"),
38528
- origin: "https://creator.douyin.com",
38529
- referer: "https://creator.douyin.com/creator-micro/content/post/image?default-tab=3&enter_from=publish_page&media_type=image&type=new",
38530
- Accept: "application/json, text/plain, */*",
38531
- "Accept-Encoding": "gzip, deflate, br, zstd",
38532
- "Content-Type": "application/json",
38533
- pragma: "no-cache",
38534
- "cache-control": "no-cache",
38535
- "sec-ch-ua-platform": params.extraParam?.browserInfo?.["sec-ch-ua-platform"] || "",
38536
- "sec-ch-ua": params.extraParam?.browserInfo?.["sec-ch-ua"] || "",
38537
- "bd-ticket-guard-web-version": "2",
38538
- "sec-ch-ua-mobile": "?0",
38539
- "user-agent": userAgent,
38540
- "sec-fetch-site": "same-origin",
38541
- "sec-fetch-mode": "cors",
38542
- "sec-fetch-dest": "empty",
38543
- "accept-language": "zh-CN,zh;q=0.9",
38544
- priority: "u=1, i"
38545
- };
38546
- const publishParams = {
38547
- read_aid: "2906",
38548
- aid: "1128",
38549
- cookie_enabled: "true",
38550
- screen_width: params.extraParam?.browserInfo.screen_width || "1920",
38551
- screen_height: params.extraParam?.browserInfo.screen_height || "1080",
38552
- browser_language: params.extraParam?.browserInfo.browser_language || "zh-CN",
38553
- browser_platform: params.extraParam?.browserInfo.browser_platform || "Win32",
38554
- browser_name: params.extraParam?.browserInfo.browser_name || "Mozilla",
38555
- browser_version: userAgent,
38556
- browser_online: "true",
38557
- timezone_name: "Asia/Shanghai",
38558
- support_h265: "1",
38559
- msToken: params.cookies.find((e)=>"msToken" === e.name)?.value || "",
38560
- a_bogus: ""
38561
- };
38562
- task.logger.info(`[douyinPublish] publishParams ${JSON.stringify(publishParams)}`);
38563
- const publishData = {
38564
- item: {
38565
- common: {
38566
- text: params.content,
38567
- text_extra: params.textExtra,
38568
- activity: "[]",
38569
- challenges: params.challengeIds || "[]",
38570
- hashtag_source: "",
38571
- mentions: "[]",
38572
- music_id: params.musicId || "",
38573
- music_end_time: 1000 * (params.musicDuration || 0),
38574
- hot_sentence: params.hotSentence || "",
38575
- visibility_type: Number(params.visibleRange) || 0,
38576
- download: params.allowSave ? 1 : 0,
38577
- timing: params.isImmediatelyPublish ? -1 : params.scheduledPublish,
38578
- media_type: Number(params.publishType) || 2,
38579
- images: [],
38580
- creation_id: ""
38581
- },
38582
- cover: {
38583
- poster: ""
38584
- },
38585
- mix: params.mix ? {
38586
- mix_id: params.mix.mix_id,
38587
- mix_order: params.mix.mix_order || 0
38588
- } : {},
38589
- anchor: {},
38590
- declare: {
38591
- user_declare_info: "{}"
38530
+ let currentStep = "初始化";
38531
+ try {
38532
+ currentStep = "验证账号信息";
38533
+ const userAgent = params.userAgent || "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.38";
38534
+ const sessionidCookie = params.cookies.find((it)=>"msToken" === it.name)?.value;
38535
+ if (!sessionidCookie) return {
38536
+ code: 414,
38537
+ message: "账号数据异常,请重新绑定账号后重试。",
38538
+ data: ""
38539
+ };
38540
+ currentStep = "准备请求参数";
38541
+ const headers = {
38542
+ cookie: params.cookies.map((it)=>`${it.name}=${it.value}`).join(";"),
38543
+ origin: "https://creator.douyin.com",
38544
+ referer: "https://creator.douyin.com/creator-micro/content/post/image?default-tab=3&enter_from=publish_page&media_type=image&type=new",
38545
+ Accept: "application/json, text/plain, */*",
38546
+ "Accept-Encoding": "gzip, deflate, br, zstd",
38547
+ "Content-Type": "application/json",
38548
+ pragma: "no-cache",
38549
+ "cache-control": "no-cache",
38550
+ "sec-ch-ua-platform": params.extraParam?.browserInfo?.["sec-ch-ua-platform"] || "",
38551
+ "sec-ch-ua": params.extraParam?.browserInfo?.["sec-ch-ua"] || "",
38552
+ "bd-ticket-guard-web-version": "2",
38553
+ "sec-ch-ua-mobile": "?0",
38554
+ "user-agent": userAgent,
38555
+ "sec-fetch-site": "same-origin",
38556
+ "sec-fetch-mode": "cors",
38557
+ "sec-fetch-dest": "empty",
38558
+ "accept-language": "zh-CN,zh;q=0.9",
38559
+ priority: "u=1, i"
38560
+ };
38561
+ const publishParams = {
38562
+ read_aid: "2906",
38563
+ aid: "1128",
38564
+ cookie_enabled: "true",
38565
+ screen_width: params.extraParam?.browserInfo.screen_width || "1920",
38566
+ screen_height: params.extraParam?.browserInfo.screen_height || "1080",
38567
+ browser_language: params.extraParam?.browserInfo.browser_language || "zh-CN",
38568
+ browser_platform: params.extraParam?.browserInfo.browser_platform || "Win32",
38569
+ browser_name: params.extraParam?.browserInfo.browser_name || "Mozilla",
38570
+ browser_version: userAgent,
38571
+ browser_online: "true",
38572
+ timezone_name: "Asia/Shanghai",
38573
+ support_h265: "1",
38574
+ msToken: params.cookies.find((e)=>"msToken" === e.name)?.value || "",
38575
+ a_bogus: ""
38576
+ };
38577
+ task.logger.info(`[douyinPublish] publishParams ${JSON.stringify(publishParams)}`);
38578
+ const publishData = {
38579
+ item: {
38580
+ common: {
38581
+ text: params.content,
38582
+ text_extra: params.textExtra,
38583
+ activity: "[]",
38584
+ challenges: params.challengeIds || "[]",
38585
+ hashtag_source: "",
38586
+ mentions: "[]",
38587
+ music_id: params.musicId || "",
38588
+ music_end_time: 1000 * (params.musicDuration || 0),
38589
+ hot_sentence: params.hotSentence || "",
38590
+ visibility_type: Number(params.visibleRange) || 0,
38591
+ download: params.allowSave ? 1 : 0,
38592
+ timing: params.isImmediatelyPublish ? -1 : params.scheduledPublish,
38593
+ media_type: Number(params.publishType) || 2,
38594
+ images: [],
38595
+ creation_id: ""
38596
+ },
38597
+ cover: {
38598
+ poster: ""
38599
+ },
38600
+ mix: params.mix ? {
38601
+ mix_id: params.mix.mix_id,
38602
+ mix_order: params.mix.mix_order || 0
38603
+ } : {},
38604
+ anchor: {},
38605
+ declare: {
38606
+ user_declare_info: "{}"
38607
+ }
38592
38608
  }
38593
- }
38594
- };
38595
- const args = [
38596
- {
38609
+ };
38610
+ const args = [
38611
+ {
38612
+ headers
38613
+ },
38614
+ task.logger,
38615
+ "",
38616
+ "",
38617
+ params.accountId,
38618
+ "douyin"
38619
+ ];
38620
+ const http = new Http({
38597
38621
  headers
38598
- },
38599
- task.logger,
38600
- "",
38601
- "",
38602
- params.accountId,
38603
- "douyin"
38604
- ];
38605
- const http = new Http({
38606
- headers
38607
- });
38608
- const proxyHttp = new Http(...args);
38609
- const uploadedImgList = params.uploadedImgList ? JSON.parse(params.uploadedImgList) : [];
38610
- if (uploadedImgList.length > 0) publishData.item.common.images = uploadedImgList;
38611
- else {
38612
- const tmpCachePath = task.getTmpPath();
38613
- const uploader = new DouyinImageUploader(proxyHttp, headers, publishParams, tmpCachePath);
38614
- if (params.coverImage) {
38615
- const cover = await uploader.uploadCover(params.coverImage);
38616
- if (cover) {
38617
- publishData.item.common.images.push({
38618
- uri: cover.uri,
38619
- width: cover.width,
38620
- height: cover.height
38621
- });
38622
- publishData.item.cover = {
38623
- poster: cover.uri
38622
+ });
38623
+ const proxyHttp = new Http(...args);
38624
+ const uploadedImgList = params.uploadedImgList ? JSON.parse(params.uploadedImgList) : [];
38625
+ if (uploadedImgList.length > 0) publishData.item.common.images = uploadedImgList;
38626
+ else {
38627
+ const tmpCachePath = task.getTmpPath();
38628
+ const uploader = new DouyinImageUploader(proxyHttp, headers, publishParams, tmpCachePath);
38629
+ if (params.coverImage) {
38630
+ const cover = await uploader.uploadCover(params.coverImage);
38631
+ if (cover) {
38632
+ publishData.item.common.images.push({
38633
+ uri: cover.uri,
38634
+ width: cover.width,
38635
+ height: cover.height
38636
+ });
38637
+ publishData.item.cover = {
38638
+ poster: cover.uri
38639
+ };
38640
+ }
38641
+ }
38642
+ if (params.banners && params.banners.length > 0) {
38643
+ const banners = params.banners.filter((i)=>i !== params.coverImage);
38644
+ const uploadResults = await uploader.uploadImages(banners);
38645
+ publishData.item.common.images = publishData.item.common.images.concat(uploadResults.map((result)=>({
38646
+ uri: result.uri,
38647
+ width: result.width,
38648
+ height: result.height
38649
+ })));
38650
+ }
38651
+ }
38652
+ publishData.item.common.creation_id = generateRandomString(8) + Date.now();
38653
+ let decision = null;
38654
+ proxyHttp.addResponseInterceptor((response)=>{
38655
+ task.logger.info(`[douyinPublish] 拦截器收到响应response.headers: ${JSON.stringify(response.headers)} `);
38656
+ task.logger.info(`[douyinPublish] 拦截器收到响应response.data: ${JSON.stringify(response.data)} `);
38657
+ decision = parseVerifyPassportDecision(response.headers["x-tt-verify-passport-decision"]);
38658
+ if (needsVerification(decision)) {
38659
+ task.logger.info(`[douyinPublish] 检测到需要验证: ${JSON.stringify(decision)}`);
38660
+ return;
38661
+ }
38662
+ if (!response || !response.data) return;
38663
+ const responseData = response.data;
38664
+ if (response && responseData?.status_code && 0 !== responseData.status_code) {
38665
+ const errorCode = 4 === responseData.status_code ? 500 : responseData.status_code;
38666
+ if (4 === responseData.status_code) task.logger.warn(`[douyinPublish] 抖音服务器错误 status_code: 4,映射为 500 触发重试。原始响应: ${JSON.stringify(responseData)}`);
38667
+ return {
38668
+ code: errorCode,
38669
+ message: responseData.status_msg || "文章发布异常,请稍后重试。",
38670
+ data: responseData
38624
38671
  };
38625
38672
  }
38673
+ });
38674
+ task._timerRecord.PrePublish = Date.now();
38675
+ if (MockPublish) {
38676
+ const data = "123456789";
38677
+ const message = `图文模拟发布成功 ${http.proxyInfo}`;
38678
+ await updateTaskState?.({
38679
+ state: types_TaskState.SUCCESS,
38680
+ result: {
38681
+ response: data
38682
+ }
38683
+ });
38684
+ return utils_response(0, message, data);
38626
38685
  }
38627
- if (params.banners && params.banners.length > 0) {
38628
- const banners = params.banners.filter((i)=>i !== params.coverImage);
38629
- const uploadResults = await uploader.uploadImages(banners);
38630
- publishData.item.common.images = publishData.item.common.images.concat(uploadResults.map((result)=>({
38631
- uri: result.uri,
38632
- width: result.width,
38633
- height: result.height
38634
- })));
38635
- }
38636
- }
38637
- publishData.item.common.creation_id = generateRandomString(8) + Date.now();
38638
- let decision = null;
38639
- proxyHttp.addResponseInterceptor((response)=>{
38640
- task.logger.info(`[douyinPublish] 拦截器收到响应response.headers: ${JSON.stringify(response.headers)} `);
38641
- task.logger.info(`[douyinPublish] 拦截器收到响应response.data: ${JSON.stringify(response.data)} `);
38642
- decision = parseVerifyPassportDecision(response.headers["x-tt-verify-passport-decision"]);
38643
- if (needsVerification(decision)) {
38644
- task.logger.info(`[douyinPublish] 检测到需要验证: ${JSON.stringify(decision)}`);
38645
- return;
38686
+ let webProtectData;
38687
+ try {
38688
+ webProtectData = JSON.parse(JSON.parse(params.extraParam["security-sdk/s_sdk_sign_data_key/web_protect"] || "{}").data || "{}");
38689
+ if (!webProtectData.ticket || !webProtectData.ts_sign || !webProtectData.client_cert) {
38690
+ task.logger.error(`webProtectData 关键字段缺失: ${JSON.stringify(webProtectData)}`);
38691
+ return utils_response(414, "安全参数 webProtectData 不完整,请重新获取后重试", "");
38692
+ }
38693
+ } catch (error) {
38694
+ task.logger.error(`解析 webProtectData 失败: ${error}`);
38695
+ return utils_response(414, "安全参数 webProtectData 解析失败,请重新获取后重试", "");
38696
+ }
38697
+ let ticket = webProtectData.ticket;
38698
+ let ts_sign = webProtectData.ts_sign;
38699
+ const serverDataCookie = params.cookies.find((it)=>"bd_ticket_guard_server_data" === it.name)?.value;
38700
+ if (serverDataCookie) try {
38701
+ const decoded = JSON.parse(Buffer.from(decodeURIComponent(serverDataCookie), "base64").toString("utf8"));
38702
+ if (decoded.ticket && decoded.ts_sign) {
38703
+ if (decoded.ticket !== ticket) task.logger.info("[douyinPublish] 使用 cookie 中的最新 ticket(web_protect 已过期)");
38704
+ ticket = decoded.ticket;
38705
+ ts_sign = decoded.ts_sign;
38706
+ }
38707
+ } catch (error) {
38708
+ task.logger.info(`[douyinPublish] 解析 bd_ticket_guard_server_data 失败,回退到 web_protect: ${error}`);
38646
38709
  }
38647
- if (!response || !response.data) return;
38648
- const responseData = response.data;
38649
- if (response && responseData?.status_code && 0 !== responseData.status_code) {
38650
- const errorCode = 4 === responseData.status_code ? 500 : responseData.status_code;
38651
- if (4 === responseData.status_code) task.logger.warn(`[douyinPublish] 抖音服务器错误 status_code: 4,映射为 500 触发重试。原始响应: ${JSON.stringify(responseData)}`);
38652
- return {
38653
- code: errorCode,
38654
- message: responseData.status_msg || "文章发布异常,请稍后重试。",
38655
- data: responseData
38656
- };
38710
+ let ec_privateKey;
38711
+ try {
38712
+ ec_privateKey = JSON.parse(JSON.parse(params.extraParam["security-sdk/s_sdk_crypt_sdk"] || "{}").data || "{}").ec_privateKey;
38713
+ if (!ec_privateKey) {
38714
+ task.logger.error("[douyinPublish] ec_privateKey 为空");
38715
+ return utils_response(414, "安全参数 ec_privateKey 缺失,请重新获取后重试", "");
38716
+ }
38717
+ } catch (error) {
38718
+ task.logger.error(`[douyinPublish] 解析 ec_privateKey 失败: ${error}`);
38719
+ return utils_response(414, "安全参数 ec_privateKey 解析失败,请重新获取后重试", "");
38657
38720
  }
38658
- });
38659
- task._timerRecord.PrePublish = Date.now();
38660
- if (MockPublish) {
38661
- const data = "123456789";
38662
- const message = `图文模拟发布成功 ${http.proxyInfo}`;
38663
- await updateTaskState?.({
38664
- state: types_TaskState.SUCCESS,
38665
- result: {
38666
- response: data
38721
+ let certificate;
38722
+ try {
38723
+ certificate = JSON.parse(params.extraParam["security-sdk/s_sdk_server_cert_key"] || "{}").cert;
38724
+ if (!certificate) {
38725
+ task.logger.error("[douyinPublish] certificate 为空");
38726
+ return utils_response(414, "安全参数 certificate 缺失,请重新获取后重试", "");
38667
38727
  }
38668
- });
38669
- return utils_response(0, message, data);
38670
- }
38671
- let webProtectData;
38672
- try {
38673
- webProtectData = JSON.parse(JSON.parse(params.extraParam["security-sdk/s_sdk_sign_data_key/web_protect"] || "{}").data || "{}");
38674
- if (!webProtectData.ticket || !webProtectData.ts_sign || !webProtectData.client_cert) {
38675
- task.logger.error(`webProtectData 关键字段缺失: ${JSON.stringify(webProtectData)}`);
38676
- return utils_response(414, "安全参数 webProtectData 不完整,请重新获取后重试", "");
38728
+ } catch (error) {
38729
+ task.logger.error(`[douyinPublish] 解析 certificate 失败: ${error}`);
38730
+ return utils_response(414, "安全参数 certificate 解析失败,请重新获取后重试", "");
38677
38731
  }
38678
- } catch (error) {
38679
- task.logger.error(`解析 webProtectData 失败: ${error}`);
38680
- return utils_response(414, "安全参数 webProtectData 解析失败,请重新获取后重试", "");
38681
- }
38682
- let ticket = webProtectData.ticket;
38683
- let ts_sign = webProtectData.ts_sign;
38684
- const serverDataCookie = params.cookies.find((it)=>"bd_ticket_guard_server_data" === it.name)?.value;
38685
- if (serverDataCookie) try {
38686
- const decoded = JSON.parse(Buffer.from(decodeURIComponent(serverDataCookie), "base64").toString("utf8"));
38687
- if (decoded.ticket && decoded.ts_sign) {
38688
- if (decoded.ticket !== ticket) task.logger.info("[douyinPublish] 使用 cookie 中的最新 ticket(web_protect 已过期)");
38689
- ticket = decoded.ticket;
38690
- ts_sign = decoded.ts_sign;
38732
+ const ree_public_key = webProtectData.client_cert.replace("pub.", "");
38733
+ let bdTicketGuardClientData;
38734
+ try {
38735
+ bdTicketGuardClientData = getBdV2({
38736
+ ticket,
38737
+ ts_sign: ts_sign,
38738
+ ec_privateKey: ec_privateKey,
38739
+ certificate: certificate,
38740
+ bd_ticket_guard_ree_public_key: ree_public_key
38741
+ });
38742
+ if (!bdTicketGuardClientData || !bdTicketGuardClientData["headers_bd_ticket_guard_client_data"]) {
38743
+ task.logger.error(`[douyinPublish] bdTicketGuardClientData 生成失败或不完整: ${JSON.stringify(bdTicketGuardClientData)}`);
38744
+ return utils_response(414, "安全参数 bdTicketGuardClientData 生成失败,请重新获取后重试", "");
38745
+ }
38746
+ } catch (error) {
38747
+ task.logger.error(`[douyinPublish] 生成 bdTicketGuardClientData 失败: ${error}`);
38748
+ return utils_response(414, "安全参数 bdTicketGuardClientData 生成异常,请重新获取后重试", "");
38691
38749
  }
38692
- } catch (error) {
38693
- task.logger.info(`[douyinPublish] 解析 bd_ticket_guard_server_data 失败,回退到 web_protect: ${error}`);
38694
- }
38695
- let ec_privateKey;
38696
- try {
38697
- ec_privateKey = JSON.parse(JSON.parse(params.extraParam["security-sdk/s_sdk_crypt_sdk"] || "{}").data || "{}").ec_privateKey;
38698
- if (!ec_privateKey) {
38699
- task.logger.error("[douyinPublish] ec_privateKey 为空");
38700
- return utils_response(414, "安全参数 ec_privateKey 缺失,请重新获取后重试", "");
38750
+ task.logger.info("[douyinPublish] bdTicketGuardClientData 生成成功");
38751
+ const publishQuery = {
38752
+ ...publishParams,
38753
+ a_bogus: ""
38754
+ };
38755
+ const queryString = new URLSearchParams(publishQuery).toString();
38756
+ let aBogus;
38757
+ try {
38758
+ aBogus = mock_getABogus(`https://creator.douyin.com/web/api/media/aweme/create_v2/?${queryString}`, publishData, userAgent);
38759
+ if (!aBogus || aBogus.length < 10) {
38760
+ task.logger.error(`[douyinPublish] a_bogus 生成异常,长度过短: ${aBogus}`);
38761
+ return utils_response(414, "安全参数 a_bogus 生成失败,请重试", "");
38762
+ }
38763
+ } catch (error) {
38764
+ task.logger.error(`[douyinPublish] 生成 a_bogus 失败: ${error}`);
38765
+ return utils_response(414, "安全参数 a_bogus 生成异常,请重试", "");
38701
38766
  }
38702
- } catch (error) {
38703
- task.logger.error(`[douyinPublish] 解析 ec_privateKey 失败: ${error}`);
38704
- return utils_response(414, "安全参数 ec_privateKey 解析失败,请重新获取后重试", "");
38705
- }
38706
- let certificate;
38707
- try {
38708
- certificate = JSON.parse(params.extraParam["security-sdk/s_sdk_server_cert_key"] || "{}").cert;
38709
- if (!certificate) {
38710
- task.logger.error("[douyinPublish] certificate 为空");
38711
- return utils_response(414, "安全参数 certificate 缺失,请重新获取后重试", "");
38767
+ publishQuery.a_bogus = aBogus;
38768
+ const publishQueryParams = new URLSearchParams(publishQuery).toString();
38769
+ let csrfToken;
38770
+ try {
38771
+ csrfToken = mock_generateCsrfTokenAdvanced({
38772
+ cookies: params.cookies,
38773
+ url: "https://creator.douyin.com/web/api/media/aweme/create_v2/",
38774
+ method: "POST",
38775
+ userAgent
38776
+ });
38777
+ if (!csrfToken || csrfToken.length < 10) {
38778
+ task.logger.error(`[douyinPublish] csrfToken 生成异常,长度过短: ${csrfToken}`);
38779
+ return utils_response(414, "安全参数 csrfToken 生成失败,请重试", "");
38780
+ }
38781
+ task.logger.info(`[douyinPublish] csrfToken 生成成功: ${csrfToken.substring(0, 20)}...`);
38782
+ } catch (error) {
38783
+ task.logger.error(`[douyinPublish] 生成 csrfToken 失败: ${error}`);
38784
+ return utils_response(414, "安全参数 csrfToken 生成异常,请重试", "");
38712
38785
  }
38713
- } catch (error) {
38714
- task.logger.error(`[douyinPublish] 解析 certificate 失败: ${error}`);
38715
- return utils_response(414, "安全参数 certificate 解析失败,请重新获取后重试", "");
38716
- }
38717
- const ree_public_key = webProtectData.client_cert.replace("pub.", "");
38718
- let bdTicketGuardClientData;
38719
- try {
38720
- bdTicketGuardClientData = getBdV2({
38721
- ticket,
38722
- ts_sign: ts_sign,
38723
- ec_privateKey: ec_privateKey,
38724
- certificate: certificate,
38725
- bd_ticket_guard_ree_public_key: ree_public_key
38726
- });
38727
- if (!bdTicketGuardClientData || !bdTicketGuardClientData["headers_bd_ticket_guard_client_data"]) {
38728
- task.logger.error(`[douyinPublish] bdTicketGuardClientData 生成失败或不完整: ${JSON.stringify(bdTicketGuardClientData)}`);
38729
- return utils_response(414, "安全参数 bdTicketGuardClientData 生成失败,请重新获取后重试", "");
38786
+ let sessionDtrait;
38787
+ try {
38788
+ sessionDtrait = mock_generateDtrait("/web/api/media/aweme/create_v2/");
38789
+ task.logger.info(`[douyinPublish] sessionDtrait 生成成功: ${sessionDtrait || "(空)"}`);
38790
+ } catch (error) {
38791
+ task.logger.error(`[douyinPublish] 生成 sessionDtrait 失败: ${error}`);
38792
+ return utils_response(414, "安全参数 sessionDtrait 生成异常,请重试", "");
38730
38793
  }
38731
- } catch (error) {
38732
- task.logger.error(`[douyinPublish] 生成 bdTicketGuardClientData 失败: ${error}`);
38733
- return utils_response(414, "安全参数 bdTicketGuardClientData 生成异常,请重新获取后重试", "");
38734
- }
38735
- task.logger.info("[douyinPublish] bdTicketGuardClientData 生成成功");
38736
- const publishQuery = {
38737
- ...publishParams,
38738
- a_bogus: ""
38739
- };
38740
- const queryString = new URLSearchParams(publishQuery).toString();
38741
- let aBogus;
38742
- try {
38743
- aBogus = mock_getABogus(`https://creator.douyin.com/web/api/media/aweme/create_v2/?${queryString}`, publishData, userAgent);
38744
- if (!aBogus || aBogus.length < 10) {
38745
- task.logger.error(`[douyinPublish] a_bogus 生成异常,长度过短: ${aBogus}`);
38746
- return utils_response(414, "安全参数 a_bogus 生成失败,请重试", "");
38794
+ task.logger.info(`[douyinPublish] headers: ${JSON.stringify({
38795
+ ...headers,
38796
+ Referer: "https://creator.douyin.com/creator-micro/content/post/image?default-tab=3&enter_from=publish_page&media_type=image&type=new",
38797
+ "Content-Type": "application/json",
38798
+ Accept: "application/json, text/plain, */*",
38799
+ "bd-ticket-guard-client-data": bdTicketGuardClientData["headers_bd_ticket_guard_client_data"],
38800
+ "bd-ticket-guard-ree-public-key": bdTicketGuardClientData["headers_bd_ticket_guard_ree_public_key"],
38801
+ "bd-ticket-guard-version": "2",
38802
+ "bd-ticket-guard-web-sign-type": "1",
38803
+ "bd-ticket-guard-web-version": "2",
38804
+ "x-secsdk-csrf-token": csrfToken,
38805
+ "x-tt-session-dtrait": sessionDtrait || ""
38806
+ })}`);
38807
+ task.logger.info(`[douyinPublish] url: https://creator.douyin.com/web/api/media/aweme/create_v2/?${publishQueryParams}`);
38808
+ let publishResult;
38809
+ try {
38810
+ publishResult = await proxyHttp.api({
38811
+ method: "post",
38812
+ url: `https://creator.douyin.com/web/api/media/aweme/create_v2/?${publishQueryParams}`,
38813
+ data: publishData,
38814
+ defaultErrorMsg: "发布异常,请稍后重试。",
38815
+ headers: {
38816
+ ...headers,
38817
+ Referer: "https://creator.douyin.com/creator-micro/content/post/image?default-tab=3&enter_from=publish_page&media_type=image&type=new",
38818
+ "Content-Type": "application/json",
38819
+ Accept: "application/json, text/plain, */*",
38820
+ "bd-ticket-guard-client-data": bdTicketGuardClientData["headers_bd_ticket_guard_client_data"],
38821
+ "bd-ticket-guard-ree-public-key": bdTicketGuardClientData["headers_bd_ticket_guard_ree_public_key"],
38822
+ "bd-ticket-guard-version": "2",
38823
+ "bd-ticket-guard-web-sign-type": "1",
38824
+ "bd-ticket-guard-web-version": "2",
38825
+ "x-secsdk-csrf-token": csrfToken,
38826
+ "x-tt-session-dtrait": sessionDtrait || ""
38827
+ }
38828
+ }, {
38829
+ timeout: 60000,
38830
+ retries: 3,
38831
+ retryDelay: 2000
38832
+ });
38833
+ } catch (error) {
38834
+ const handledError = Http.handleApiError(error);
38835
+ const isProxyOrNetworkError = [
38836
+ 599,
38837
+ 500,
38838
+ 502,
38839
+ 503,
38840
+ 504
38841
+ ].includes(handledError.code);
38842
+ if (isProxyOrNetworkError) {
38843
+ const isProxyRequest = handledError.extra?.isProxyRequest === true;
38844
+ const errorType = 599 === handledError.code || isProxyRequest ? "代理错误" : "网络错误";
38845
+ const message = `图文发布失败,${errorType}:${handledError.message}${task.debug ? ` ${http.proxyInfo}` : ""}`;
38846
+ task.logger.error(`[douyinPublish] ${errorType},直接返回: ${message}`, stringifyError(handledError));
38847
+ await updateTaskState?.({
38848
+ state: types_TaskState.FAILED,
38849
+ error: message
38850
+ });
38851
+ return {
38852
+ code: 414,
38853
+ data: "",
38854
+ message
38855
+ };
38856
+ }
38857
+ throw error;
38747
38858
  }
38748
- } catch (error) {
38749
- task.logger.error(`[douyinPublish] 生成 a_bogus 失败: ${error}`);
38750
- return utils_response(414, "安全参数 a_bogus 生成异常,请重试", "");
38751
- }
38752
- publishQuery.a_bogus = aBogus;
38753
- const publishQueryParams = new URLSearchParams(publishQuery).toString();
38754
- let csrfToken;
38755
- try {
38756
- csrfToken = mock_generateCsrfTokenAdvanced({
38757
- cookies: params.cookies,
38758
- url: "https://creator.douyin.com/web/api/media/aweme/create_v2/",
38759
- method: "POST",
38760
- userAgent
38761
- });
38762
- if (!csrfToken || csrfToken.length < 10) {
38763
- task.logger.error(`[douyinPublish] csrfToken 生成异常,长度过短: ${csrfToken}`);
38764
- return utils_response(414, "安全参数 csrfToken 生成失败,请重试", "");
38859
+ task.logger.info(`[douyinPublish] decision值: ${JSON.stringify(decision)}, needsVerification(decision): ${needsVerification(decision)}`);
38860
+ if (needsVerification(decision)) {
38861
+ const details = [
38862
+ publishResult.status_msg,
38863
+ decision?.verify_title,
38864
+ decision?.verify_desc
38865
+ ].filter(Boolean).join(" ");
38866
+ const message = `图文发布失败,原因:${details}${task.debug ? ` ${http.proxyInfo}` : ""}`;
38867
+ const safeDecision = safeSerialize(decision) ?? {};
38868
+ const mockData = {
38869
+ state: types_TaskState.FAILED,
38870
+ error: message,
38871
+ result: {
38872
+ ...safeDecision,
38873
+ data: decision,
38874
+ uploadedImgList: JSON.stringify(publishData.item.common.images)
38875
+ }
38876
+ };
38877
+ await updateTaskState?.(mockData);
38878
+ return {
38879
+ code: 0,
38880
+ data: mockData,
38881
+ message: "操作成功"
38882
+ };
38765
38883
  }
38766
- task.logger.info(`[douyinPublish] csrfToken 生成成功: ${csrfToken.substring(0, 20)}...`);
38767
- } catch (error) {
38768
- task.logger.error(`[douyinPublish] 生成 csrfToken 失败: ${error}`);
38769
- return utils_response(414, "安全参数 csrfToken 生成异常,请重试", "");
38770
- }
38771
- let sessionDtrait;
38772
- try {
38773
- sessionDtrait = mock_generateDtrait("/web/api/media/aweme/create_v2/");
38774
- task.logger.info(`[douyinPublish] sessionDtrait 生成成功: ${sessionDtrait || "(空)"}`);
38775
- } catch (error) {
38776
- task.logger.error(`[douyinPublish] 生成 sessionDtrait 失败: ${error}`);
38777
- return utils_response(414, "安全参数 sessionDtrait 生成异常,请重试", "");
38778
- }
38779
- task.logger.info(`[douyinPublish] headers: ${JSON.stringify({
38780
- ...headers,
38781
- Referer: "https://creator.douyin.com/creator-micro/content/post/image?default-tab=3&enter_from=publish_page&media_type=image&type=new",
38782
- "Content-Type": "application/json",
38783
- Accept: "application/json, text/plain, */*",
38784
- "bd-ticket-guard-client-data": bdTicketGuardClientData["headers_bd_ticket_guard_client_data"],
38785
- "bd-ticket-guard-ree-public-key": bdTicketGuardClientData["headers_bd_ticket_guard_ree_public_key"],
38786
- "bd-ticket-guard-version": "2",
38787
- "bd-ticket-guard-web-sign-type": "1",
38788
- "bd-ticket-guard-web-version": "2",
38789
- "x-secsdk-csrf-token": csrfToken,
38790
- "x-tt-session-dtrait": sessionDtrait || ""
38791
- })}`);
38792
- task.logger.info(`[douyinPublish] url: https://creator.douyin.com/web/api/media/aweme/create_v2/?${publishQueryParams}`);
38793
- let publishResult;
38794
- try {
38795
- publishResult = await proxyHttp.api({
38796
- method: "post",
38797
- url: `https://creator.douyin.com/web/api/media/aweme/create_v2/?${publishQueryParams}`,
38798
- data: publishData,
38799
- defaultErrorMsg: "发布异常,请稍后重试。",
38800
- headers: {
38801
- ...headers,
38802
- Referer: "https://creator.douyin.com/creator-micro/content/post/image?default-tab=3&enter_from=publish_page&media_type=image&type=new",
38803
- "Content-Type": "application/json",
38804
- Accept: "application/json, text/plain, */*",
38805
- "bd-ticket-guard-client-data": bdTicketGuardClientData["headers_bd_ticket_guard_client_data"],
38806
- "bd-ticket-guard-ree-public-key": bdTicketGuardClientData["headers_bd_ticket_guard_ree_public_key"],
38807
- "bd-ticket-guard-version": "2",
38808
- "bd-ticket-guard-web-sign-type": "1",
38809
- "bd-ticket-guard-web-version": "2",
38810
- "x-secsdk-csrf-token": csrfToken,
38811
- "x-tt-session-dtrait": sessionDtrait || ""
38812
- }
38813
- }, {
38814
- timeout: 60000,
38815
- retries: 3,
38816
- retryDelay: 2000
38817
- });
38818
- } catch (error) {
38819
- const handledError = Http.handleApiError(error);
38820
- const isProxyOrNetworkError = [
38821
- 599,
38822
- 500,
38823
- 502,
38824
- 503,
38825
- 504
38826
- ].includes(handledError.code);
38827
- if (isProxyOrNetworkError) {
38828
- const isProxyRequest = handledError.extra?.isProxyRequest === true;
38829
- const errorType = 599 === handledError.code || isProxyRequest ? "代理错误" : "网络错误";
38830
- const message = `图文发布失败,${errorType}:${handledError.message}${task.debug ? ` ${http.proxyInfo}` : ""}`;
38831
- task.logger.error(`[douyinPublish] ${errorType},直接返回: ${message}`, stringifyError(handledError));
38884
+ reportLogger({
38885
+ token: params.huiwenToken || "",
38886
+ enverionment: task.enverionment || "development",
38887
+ postId: params.articleId,
38888
+ eip: proxyHttp.proxyInfo,
38889
+ proxyIp: params.localIP,
38890
+ accountId: params.accountId,
38891
+ uid: params.uid,
38892
+ platform: "douyin",
38893
+ publishParams: publishData
38894
+ });
38895
+ task.logger.info(`[douyinPublish] 发布结果 ${JSON.stringify(publishResult)}`);
38896
+ const isSuccess = 0 === publishResult.status_code;
38897
+ const message = `图文发布${isSuccess ? "成功" : `失败,原因:${publishResult.status_msg} ${decision?.verify_title} ${decision?.verify_desc}`}${task.debug ? ` ${http.proxyInfo}` : ""}`;
38898
+ const data = isSuccess ? publishResult.item_id || "" : "";
38899
+ if (!isSuccess) {
38900
+ const safeDecision = safeSerialize(decision) ?? {};
38832
38901
  await updateTaskState?.({
38833
38902
  state: types_TaskState.FAILED,
38834
- error: message
38903
+ error: message,
38904
+ result: {
38905
+ ...safeDecision,
38906
+ data: safeDecision,
38907
+ uploadedImgList: JSON.stringify(publishData.item.common.images)
38908
+ }
38835
38909
  });
38836
38910
  return {
38837
38911
  code: 414,
38838
- data: "",
38912
+ data: safeDecision,
38839
38913
  message
38840
38914
  };
38841
38915
  }
38842
- throw error;
38843
- }
38844
- task.logger.info(`[douyinPublish] decision值: ${JSON.stringify(decision)}, needsVerification(decision): ${needsVerification(decision)}`);
38845
- if (needsVerification(decision)) {
38846
- const details = [
38847
- publishResult.status_msg,
38848
- decision?.verify_title,
38849
- decision?.verify_desc
38850
- ].filter(Boolean).join(" ");
38851
- const message = `图文发布失败,原因:${details}${task.debug ? ` ${http.proxyInfo}` : ""}`;
38852
- let decisionObj = {};
38853
- if (decision) decisionObj = decision;
38854
- const mockData = {
38855
- state: types_TaskState.FAILED,
38856
- error: message,
38916
+ await updateTaskState?.({
38917
+ state: types_TaskState.SUCCESS,
38857
38918
  result: {
38858
- ...decisionObj,
38859
- data: decision,
38860
- uploadedImgList: JSON.stringify(publishData.item.common.images)
38919
+ response: data
38861
38920
  }
38862
- };
38863
- await updateTaskState?.(mockData);
38864
- return {
38865
- code: 0,
38866
- data: mockData,
38867
- message: "操作成功"
38868
- };
38869
- }
38870
- reportLogger({
38871
- token: params.huiwenToken || "",
38872
- enverionment: task.enverionment || "development",
38873
- postId: params.articleId,
38874
- eip: proxyHttp.proxyInfo,
38875
- proxyIp: params.localIP,
38876
- accountId: params.accountId,
38877
- uid: params.uid,
38878
- platform: "douyin",
38879
- publishParams: publishData
38880
- });
38881
- task.logger.info(`[douyinPublish] 发布结果 ${JSON.stringify(publishResult)}`);
38882
- const isSuccess = 0 === publishResult.status_code;
38883
- const message = `图文发布${isSuccess ? "成功" : `失败,原因:${publishResult.status_msg} ${decision?.verify_title} ${decision?.verify_desc}`}${task.debug ? ` ${http.proxyInfo}` : ""}`;
38884
- const data = isSuccess ? publishResult.item_id || "" : "";
38885
- if (!isSuccess) {
38886
- let decisionObj = {};
38887
- if (decision) decisionObj = decision;
38921
+ });
38922
+ return utils_response(isSuccess ? 0 : 414, message, data);
38923
+ } catch (error) {
38924
+ const handledError = Http.handleApiError(error);
38925
+ const errorMsg = handledError.message || "发布失败";
38926
+ const errorCode = handledError.code || 500;
38927
+ task.logger.error(`[douyinPublish] 发布流程异常 (步骤: ${currentStep}): ${errorMsg}`, stringifyError(error), handledError.extra);
38888
38928
  await updateTaskState?.({
38889
38929
  state: types_TaskState.FAILED,
38890
- error: message,
38891
- result: {
38892
- ...decisionObj,
38893
- data: decision,
38894
- uploadedImgList: JSON.stringify(publishData.item.common.images)
38895
- }
38930
+ error: `${currentStep}失败: ${errorMsg}`
38896
38931
  });
38897
- return {
38898
- code: 414,
38899
- data,
38900
- message
38901
- };
38932
+ return utils_response(errorCode, errorMsg, "");
38902
38933
  }
38903
- await updateTaskState?.({
38904
- state: types_TaskState.SUCCESS,
38905
- result: {
38906
- response: data
38907
- }
38908
- });
38909
- return utils_response(isSuccess ? 0 : 414, message, data);
38910
38934
  };
38911
38935
  const douyinPublish_rpa_rpaAction = async (task, params)=>{
38912
38936
  const commonCookies = {
@@ -40432,6 +40456,241 @@ var __webpack_exports__ = {};
40432
40456
  };
40433
40457
  return success(bjhData, "百家号平台数据获取成功!");
40434
40458
  }
40459
+ async function getDouyinData(_task, params) {
40460
+ try {
40461
+ const sessionidCookie = params.cookies.find((it)=>"sessionid" === it.name)?.value;
40462
+ if (!sessionidCookie) return types_errorResponse("抖音账号数据异常,请重新绑定账号后重试。", 414);
40463
+ const csrfToken = params.cookies.find((it)=>"passport_csrf_token" === it.name)?.value || "";
40464
+ const headers = {
40465
+ cookie: params.cookies.map((it)=>`${it.name}=${it.value}`).join(";"),
40466
+ referer: "https://creator.douyin.com/creator-micro/home",
40467
+ origin: "https://creator.douyin.com",
40468
+ "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36",
40469
+ ...csrfToken ? {
40470
+ "x-secsdk-csrf-token": csrfToken
40471
+ } : {}
40472
+ };
40473
+ const args = [
40474
+ {
40475
+ headers
40476
+ },
40477
+ _task.logger,
40478
+ params.proxyLoc,
40479
+ params.localIP,
40480
+ params.accountId
40481
+ ];
40482
+ const http = new Http(...args);
40483
+ const toNum = (val)=>{
40484
+ if (null == val) return 0;
40485
+ const n = Number.parseInt(String(val).replace(/[+,]/g, ""), 10);
40486
+ return Number.isNaN(n) ? 0 : n;
40487
+ };
40488
+ const userProfileP = http.api({
40489
+ method: "get",
40490
+ url: "https://www.douyin.com/aweme/v1/web/user/profile/self/",
40491
+ params: {
40492
+ device_platform: "webapp",
40493
+ aid: "6383",
40494
+ channel: "channel_pc_web",
40495
+ pc_client_type: "1",
40496
+ version_code: "170400",
40497
+ version_name: "17.4.0",
40498
+ cookie_enabled: "true",
40499
+ platform: "PC"
40500
+ }
40501
+ }, {
40502
+ retries: 3,
40503
+ retryDelay: 100,
40504
+ timeout: 10000
40505
+ }).catch((e)=>{
40506
+ _task.logger.warn(`抖音用户信息获取失败: ${e instanceof Error ? e.message : String(e)}`);
40507
+ return null;
40508
+ });
40509
+ const overviewP = http.api({
40510
+ method: "get",
40511
+ url: "https://creator.douyin.com/aweme/janus/creator/data/overview/all/",
40512
+ params: {
40513
+ last_days_type: 1,
40514
+ aid: 2906,
40515
+ app_name: "aweme_creator_platform",
40516
+ device_platform: "web"
40517
+ }
40518
+ }, {
40519
+ retries: 3,
40520
+ retryDelay: 100,
40521
+ timeout: 5000
40522
+ }).catch((e)=>{
40523
+ _task.logger.warn(`抖音近7日数据获取失败(可能未开通数据中心或被风控): ${e instanceof Error ? e.message : String(e)}`);
40524
+ return null;
40525
+ });
40526
+ const [userProfile, overview] = await Promise.all([
40527
+ userProfileP,
40528
+ overviewP
40529
+ ]);
40530
+ let fansNum = 0;
40531
+ let favedNum = 0;
40532
+ let followingNum = 0;
40533
+ if (userProfile?.status_code === 0 && userProfile.user) {
40534
+ const user = userProfile.user;
40535
+ fansNum = toNum(user.follower_count);
40536
+ followingNum = toNum(user.following_count);
40537
+ favedNum = toNum(user.total_favorited);
40538
+ } else _task.logger.warn(`用户信息接口返回异常: status_code=${userProfile?.status_code}, msg=${userProfile?.status_msg}`);
40539
+ const ov = overview?.data;
40540
+ const douyinData = {
40541
+ fansNum,
40542
+ favedNum,
40543
+ fansNumLastWeek: toNum(ov?.new_fans?.last_period_incr),
40544
+ watchNumLastWeek: toNum(ov?.play?.last_period_incr),
40545
+ likeNumLastWeek: toNum(ov?.digg?.last_period_incr),
40546
+ commentNumLastWeek: toNum(ov?.comment?.last_period_incr),
40547
+ shareNumLastWeek: toNum(ov?.share?.last_period_incr),
40548
+ visitNumLastWeek: toNum(ov?.profile?.last_period_incr)
40549
+ };
40550
+ return success(douyinData, "抖音平台数据获取成功!");
40551
+ } catch (error) {
40552
+ if (error && "object" == typeof error && "code" in error && "message" in error) {
40553
+ const err = error;
40554
+ _task.logger.error(`抖音账号数据获取失败: ${err.message} (${err.code})`);
40555
+ return types_errorResponse(err.message, err.code);
40556
+ }
40557
+ const errMsg = error instanceof Error ? error.message : String(error);
40558
+ _task.logger.error(`抖音账号数据获取失败: ${errMsg}`);
40559
+ return types_errorResponse(errMsg || "抖音账号数据获取失败");
40560
+ }
40561
+ }
40562
+ async function getShipinhaoData(_task, params) {
40563
+ try {
40564
+ const sessionidCookie = params.cookies.find((it)=>"sessionid" === it.name)?.value;
40565
+ if (!sessionidCookie) return types_errorResponse("视频号账号数据异常,请重新绑定账号后重试。", 414);
40566
+ const uinCookie = params.cookies.find((it)=>"uin" === it.name || "wxuin" === it.name)?.value || "0000000000";
40567
+ const deviceIdCookie = params.cookies.find((it)=>"device_id" === it.name || "finger_print_device_id" === it.name)?.value;
40568
+ const aid = params.cookies.find((it)=>"_aid" === it.name)?.value || "9d3e0e9f-b842-498d-a273-4285d58df264";
40569
+ const finderId = params.cookies.find((it)=>"_log_finder_id" === it.name || "finder_id" === it.name)?.value || "";
40570
+ const headers = {
40571
+ cookie: params.cookies.map((it)=>`${it.name}=${it.value}`).join(";"),
40572
+ referer: "https://channels.weixin.qq.com/platform",
40573
+ origin: "https://channels.weixin.qq.com",
40574
+ "content-type": "application/json",
40575
+ "X-WECHAT-UIN": uinCookie,
40576
+ ...deviceIdCookie ? {
40577
+ "finger-print-device-id": deviceIdCookie
40578
+ } : {}
40579
+ };
40580
+ const args = [
40581
+ {
40582
+ headers
40583
+ },
40584
+ _task.logger,
40585
+ params.proxyLoc,
40586
+ params.localIP,
40587
+ params.accountId
40588
+ ];
40589
+ const http = new Http(...args);
40590
+ const authData = await http.api({
40591
+ method: "post",
40592
+ url: "https://channels.weixin.qq.com/cgi-bin/mmfinderassistant-bin/auth/auth_data",
40593
+ params: {
40594
+ _aid: aid,
40595
+ _rid: `${Date.now().toString(16)}-${Math.random().toString(36).substring(2, 9)}`,
40596
+ _pageUrl: encodeURIComponent("https://channels.weixin.qq.com/platform")
40597
+ },
40598
+ data: {
40599
+ timestamp: Date.now().toString(),
40600
+ _log_finder_uin: "",
40601
+ _log_finder_id: finderId,
40602
+ rawKeyBuff: "",
40603
+ pluginSessionId: null,
40604
+ scene: 7,
40605
+ reqScene: 7
40606
+ }
40607
+ }, {
40608
+ retries: 3,
40609
+ retryDelay: 100,
40610
+ timeout: 5000
40611
+ });
40612
+ const AUTH_ERROR_CODES = [
40613
+ 300333,
40614
+ 300334,
40615
+ 300330,
40616
+ 300331,
40617
+ 300332
40618
+ ];
40619
+ if (authData.errCode && AUTH_ERROR_CODES.includes(authData.errCode)) {
40620
+ _task.logger.warn(`视频号登录已失效:${authData.errMsg} (${authData.errCode})`);
40621
+ return types_errorResponse("视频号账号信息获取失败,请检查账号状态", 414);
40622
+ }
40623
+ if (authData.errCode) {
40624
+ _task.logger.warn(`视频号账号API错误:${authData.errMsg} (${authData.errCode})`);
40625
+ return types_errorResponse(`视频号账号信息获取失败:${authData.errMsg || "未知错误"}`, 414);
40626
+ }
40627
+ const finderUser = authData.data?.finderUser;
40628
+ const now = new Date();
40629
+ const yesterday = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 2);
40630
+ const startTs = Math.floor(yesterday.getTime() / 1000);
40631
+ const endTs = startTs + 86400;
40632
+ _task.logger.info(`视频号昨日数据范围 start: ${startTs} ~ end: ${endTs}`);
40633
+ let fansNumYesterday = 0;
40634
+ let playNumYesterday = 0;
40635
+ let likeNumYesterday = 0;
40636
+ let commentNumYesterday = 0;
40637
+ try {
40638
+ const statsData = await http.api({
40639
+ method: "post",
40640
+ url: "https://channels.weixin.qq.com/cgi-bin/mmfinderassistant-bin/statistic/new_post_total_data",
40641
+ params: {
40642
+ _aid: aid,
40643
+ _rid: `${Date.now().toString(16)}-${Math.random().toString(36).substring(2, 9)}`,
40644
+ _pageUrl: encodeURIComponent("https://channels.weixin.qq.com/platform")
40645
+ },
40646
+ data: {
40647
+ startTs: startTs.toString(),
40648
+ endTs: endTs.toString(),
40649
+ interval: 3,
40650
+ timestamp: Date.now().toString(),
40651
+ _log_finder_uin: "",
40652
+ _log_finder_id: finderId,
40653
+ rawKeyBuff: "",
40654
+ pluginSessionId: null,
40655
+ scene: 7,
40656
+ reqScene: 7
40657
+ }
40658
+ }, {
40659
+ retries: 3,
40660
+ retryDelay: 100,
40661
+ timeout: 5000
40662
+ });
40663
+ if (!statsData.errCode && statsData.data?.totalData) {
40664
+ const data = statsData.data.totalData;
40665
+ fansNumYesterday = Number.parseInt(data.follow?.[1] || "0", 10) || 0;
40666
+ playNumYesterday = Number.parseInt(data.browse?.[1] || "0", 10) || 0;
40667
+ likeNumYesterday = Number.parseInt(data.like?.[1] || "0", 10) || 0;
40668
+ commentNumYesterday = Number.parseInt(data.comment?.[1] || "0", 10) || 0;
40669
+ }
40670
+ } catch (error) {
40671
+ const errMsg = error instanceof Error ? error.message : String(error);
40672
+ _task.logger.warn(`视频号昨日数据获取失败(降级为null): ${errMsg}`);
40673
+ }
40674
+ const shipinhaoData = {
40675
+ fansNum: finderUser?.fansCount || 0,
40676
+ feedsCount: finderUser?.feedsCount || 0,
40677
+ fansNumYesterday,
40678
+ playNumYesterday,
40679
+ likeNumYesterday,
40680
+ commentNumYesterday
40681
+ };
40682
+ return success(shipinhaoData, "视频号平台数据获取成功!");
40683
+ } catch (error) {
40684
+ if (error && "object" == typeof error && "code" in error && "message" in error) {
40685
+ const err = error;
40686
+ _task.logger.error(`视频号账号数据获取失败: ${err.message} (${err.code})`);
40687
+ return types_errorResponse(err.message, err.code);
40688
+ }
40689
+ const errMsg = error instanceof Error ? error.message : String(error);
40690
+ _task.logger.error(`视频号账号数据获取失败: ${errMsg}`);
40691
+ return types_errorResponse(errMsg || "视频号账号数据获取失败");
40692
+ }
40693
+ }
40435
40694
  async function getToutiaoData(_task, params) {
40436
40695
  const http = new Http({
40437
40696
  headers: {
@@ -40530,7 +40789,7 @@ var __webpack_exports__ = {};
40530
40789
  userInfoHtmlPromise,
40531
40790
  userSummaryHtmlPromise
40532
40791
  ]);
40533
- if (userInfoHtml.includes("请重新<a id='jumpUrl' href='/'>登录</a>")) return types_errorResponse("Token已失效,请重新获取", 414);
40792
+ if (userInfoHtml.includes("请重新<a id='jumpUrl' href='/'>登录</a>")) return types_errorResponse("微信公众号数据获取失败,请检查账号状态", 414);
40534
40793
  const userInfoJson = exportWxCgiData(userInfoHtml);
40535
40794
  const userSummaryJson = exportWxCgiData(userSummaryHtml);
40536
40795
  const wxData = {
@@ -40607,7 +40866,9 @@ var __webpack_exports__ = {};
40607
40866
  "toutiao",
40608
40867
  "xiaohongshu",
40609
40868
  "weixin",
40610
- "baijiahao"
40869
+ "baijiahao",
40870
+ "douyin",
40871
+ "shipinhao"
40611
40872
  ])
40612
40873
  });
40613
40874
  const SearchAccountInfo = async (_task, params)=>{
@@ -40621,6 +40882,10 @@ var __webpack_exports__ = {};
40621
40882
  return getWeixinData(_task, params);
40622
40883
  case "baijiahao":
40623
40884
  return getBaijiahaoData(_task, params);
40885
+ case "douyin":
40886
+ return getDouyinData(_task, params);
40887
+ case "shipinhao":
40888
+ return getShipinhaoData(_task, params);
40624
40889
  default:
40625
40890
  return success(null, "暂不支持该平台");
40626
40891
  }
@@ -40715,18 +40980,45 @@ var __webpack_exports__ = {};
40715
40980
  collectNum: classic_schemas_number(),
40716
40981
  shareNum: classic_schemas_number()
40717
40982
  });
40983
+ const DouyinArticleSchema = BaseArticleSchema.extend({
40984
+ playNum: classic_schemas_number(),
40985
+ likeNum: classic_schemas_number(),
40986
+ commentNum: classic_schemas_number(),
40987
+ shareNum: classic_schemas_number(),
40988
+ collectNum: classic_schemas_number(),
40989
+ awemeId: classic_schemas_string(),
40990
+ awemeType: classic_schemas_number(),
40991
+ duration: classic_schemas_number().optional(),
40992
+ status: classic_schemas_string(),
40993
+ publicUrl: classic_schemas_string()
40994
+ });
40995
+ const ShipinhaoArticleSchema = BaseArticleSchema.extend({
40996
+ readNum: classic_schemas_number(),
40997
+ likeNum: classic_schemas_number(),
40998
+ commentNum: classic_schemas_number(),
40999
+ forwardNum: classic_schemas_number(),
41000
+ favNum: classic_schemas_number(),
41001
+ objectId: classic_schemas_string(),
41002
+ postType: classic_schemas_string(),
41003
+ postStatus: classic_schemas_number(),
41004
+ effectiveTime: classic_schemas_number().optional()
41005
+ });
40718
41006
  const FetchArticlesDataSchema = classic_schemas_object({
40719
41007
  articleCell: classic_schemas_array(schemas_union([
40720
41008
  ToutiaoArticleSchema,
40721
41009
  WeixinArticleSchema,
40722
41010
  BaijiahaoArticleSchema,
40723
- XiaohongshuArticleSchema
41011
+ XiaohongshuArticleSchema,
41012
+ DouyinArticleSchema,
41013
+ ShipinhaoArticleSchema
40724
41014
  ])).optional(),
40725
41015
  timerPublish: classic_schemas_array(schemas_union([
40726
41016
  ToutiaoArticleSchema,
40727
41017
  WeixinArticleSchema,
40728
41018
  BaijiahaoArticleSchema,
40729
- XiaohongshuArticleSchema
41019
+ XiaohongshuArticleSchema,
41020
+ DouyinArticleSchema,
41021
+ ShipinhaoArticleSchema
40730
41022
  ])).optional(),
40731
41023
  pagination: classic_schemas_object({
40732
41024
  total: classic_schemas_number().optional(),
@@ -40841,6 +41133,269 @@ var __webpack_exports__ = {};
40841
41133
  return searchPublishInfo_types_errorResponse(error instanceof Error ? error.message : "百家号文章数据获取失败");
40842
41134
  }
40843
41135
  }
41136
+ async function handleDouyinData(_task, params) {
41137
+ try {
41138
+ const { cookies, pageSize = 12, status = 0, showOriginalData = false, onlySuccess = false } = params;
41139
+ const pageNum = params.pageNum || 1;
41140
+ const headers = {
41141
+ cookie: cookies.map((it)=>`${it.name}=${it.value}`).join(";"),
41142
+ referer: "https://creator.douyin.com"
41143
+ };
41144
+ const args = [
41145
+ {
41146
+ headers
41147
+ },
41148
+ _task.logger,
41149
+ params.proxyLoc,
41150
+ params.localIP,
41151
+ params.accountId
41152
+ ];
41153
+ const http = new Http(...args);
41154
+ async function fetchWorks(cursor) {
41155
+ return await http.api({
41156
+ method: "get",
41157
+ url: "https://creator.douyin.com/janus/douyin/creator/pc/work_list",
41158
+ params: {
41159
+ scene: "star_atlas",
41160
+ device_platform: "android",
41161
+ aid: 1128,
41162
+ status,
41163
+ count: pageSize,
41164
+ max_cursor: cursor
41165
+ }
41166
+ }, {
41167
+ retries: 3,
41168
+ retryDelay: 100,
41169
+ timeout: 5000
41170
+ });
41171
+ }
41172
+ const isHasMore = (v)=>true === v || 1 === v;
41173
+ const skipCount = (pageNum - 1) * pageSize;
41174
+ const needCount = skipCount + pageSize;
41175
+ const workListResponse = await fetchWorks(0);
41176
+ if (!workListResponse || !Array.isArray(workListResponse.aweme_list)) return searchPublishInfo_types_errorResponse("抖音数据获取失败,请检查账号状态", 414);
41177
+ const allWorks = [
41178
+ ...workListResponse.aweme_list
41179
+ ];
41180
+ let hasMore = isHasMore(workListResponse.has_more);
41181
+ let currentCursor = workListResponse.cursor ?? workListResponse.max_cursor ?? 0;
41182
+ let guard = 0;
41183
+ while(allWorks.length < needCount && hasMore && guard < 20){
41184
+ const nextPageResponse = await fetchWorks(currentCursor);
41185
+ if (!Array.isArray(nextPageResponse.aweme_list) || 0 === nextPageResponse.aweme_list.length) break;
41186
+ allWorks.push(...nextPageResponse.aweme_list);
41187
+ hasMore = isHasMore(nextPageResponse.has_more);
41188
+ currentCursor = nextPageResponse.cursor ?? nextPageResponse.max_cursor ?? currentCursor;
41189
+ guard++;
41190
+ }
41191
+ const finalWorks = allWorks.slice(skipCount, needCount);
41192
+ const articleCell = finalWorks.map((item)=>{
41193
+ const workDetailUrl = `https://creator.douyin.com/creator-micro/work-management/work-detail/${item.aweme_id}`;
41194
+ const workPublicUrl = item.share_url || `https://www.douyin.com/video/${item.aweme_id}`;
41195
+ let statusText;
41196
+ statusText = item.status?.is_delete ? "deleted" : item.status?.is_private ? "private" : item.status?.in_reviewing ? "reviewing" : "public";
41197
+ return {
41198
+ title: item.desc || "无作品描述",
41199
+ imageUrl: item.Cover?.url_list?.[0] || "",
41200
+ createTime: item.create_time,
41201
+ redirectUrl: workDetailUrl,
41202
+ playNum: item.statistics?.play_count || 0,
41203
+ likeNum: item.statistics?.digg_count || 0,
41204
+ commentNum: item.statistics?.comment_count || 0,
41205
+ shareNum: item.statistics?.share_count || 0,
41206
+ collectNum: item.statistics?.collect_count || 0,
41207
+ awemeId: item.aweme_id,
41208
+ awemeType: item.aweme_type ?? 0,
41209
+ duration: item.duration,
41210
+ status: statusText,
41211
+ publicUrl: workPublicUrl,
41212
+ ...showOriginalData ? {
41213
+ originalData: item
41214
+ } : {}
41215
+ };
41216
+ });
41217
+ return success({
41218
+ articleCell,
41219
+ ...onlySuccess ? {
41220
+ pagination: {
41221
+ total: workListResponse.total || allWorks.length,
41222
+ nextPage: hasMore,
41223
+ pageNum,
41224
+ pageSize
41225
+ }
41226
+ } : null
41227
+ }, "抖音数据获取成功");
41228
+ } catch (error) {
41229
+ return searchPublishInfo_types_errorResponse(error instanceof Error ? error.message : "抖音数据获取失败");
41230
+ }
41231
+ }
41232
+ async function handleShipinhaoData(_task, params) {
41233
+ try {
41234
+ const { cookies, postType = "all", pageSize = 10, showOriginalData = false } = params;
41235
+ const pageNum = params.pageNum || 1;
41236
+ const aidCookie = cookies.find((it)=>"_aid" === it.name)?.value;
41237
+ const aid = aidCookie || "9d3e0e9f-b842-498d-a273-4285d58df264";
41238
+ const uinCookie = cookies.find((it)=>"uin" === it.name || "wxuin" === it.name)?.value || "0000000000";
41239
+ const deviceIdCookie = cookies.find((it)=>"device_id" === it.name || "finger_print_device_id" === it.name)?.value;
41240
+ const headers = {
41241
+ cookie: cookies.map((it)=>`${it.name}=${it.value}`).join(";"),
41242
+ referer: "https://channels.weixin.qq.com",
41243
+ origin: "https://channels.weixin.qq.com",
41244
+ "content-type": "application/json",
41245
+ "X-WECHAT-UIN": uinCookie,
41246
+ ...deviceIdCookie ? {
41247
+ "finger-print-device-id": deviceIdCookie
41248
+ } : {}
41249
+ };
41250
+ const args = [
41251
+ {
41252
+ headers
41253
+ },
41254
+ _task.logger,
41255
+ params.proxyLoc,
41256
+ params.localIP,
41257
+ params.accountId
41258
+ ];
41259
+ const http = new Http(...args);
41260
+ const finderIdCookie = cookies.find((it)=>"_log_finder_id" === it.name || "finder_id" === it.name)?.value || "";
41261
+ async function fetchPosts(currentPage, userpageType, pageUrl, rawKeyBuff = "") {
41262
+ return await http.api({
41263
+ method: "post",
41264
+ url: "https://channels.weixin.qq.com/micro/content/cgi-bin/mmfinderassistant-bin/post/post_list",
41265
+ params: {
41266
+ _aid: aid,
41267
+ _rid: `${Date.now().toString(16)}-${Math.random().toString(36).substring(2, 9)}`,
41268
+ _pageUrl: encodeURIComponent(pageUrl)
41269
+ },
41270
+ data: {
41271
+ pageSize,
41272
+ currentPage,
41273
+ userpageType,
41274
+ stickyOrder: true,
41275
+ timestamp: Date.now().toString(),
41276
+ _log_finder_uin: "",
41277
+ _log_finder_id: finderIdCookie,
41278
+ rawKeyBuff,
41279
+ pluginSessionId: null,
41280
+ scene: 7,
41281
+ reqScene: 7
41282
+ }
41283
+ }, {
41284
+ retries: 3,
41285
+ retryDelay: 100,
41286
+ timeout: 5000
41287
+ });
41288
+ }
41289
+ async function fetchAllPosts(userpageType, pageUrl) {
41290
+ const allPosts = [];
41291
+ let currentPage = 1;
41292
+ let rawKeyBuff = "";
41293
+ let continueFlag = true;
41294
+ let totalCount = 0;
41295
+ while(continueFlag){
41296
+ const response = await fetchPosts(currentPage, userpageType, pageUrl, rawKeyBuff);
41297
+ if (response.errCode && AUTH_ERROR_CODES.includes(response.errCode)) throw new Error(`AUTH_ERROR:${response.errMsg || "登录已失效"}`);
41298
+ if (response.errCode) {
41299
+ _task.logger.warn(`视频号API错误:${response.errMsg} (${response.errCode})`);
41300
+ throw new Error(`视频号API错误:${response.errMsg} (${response.errCode})`);
41301
+ }
41302
+ if (1 === currentPage) totalCount = response.data?.totalCount ?? 0;
41303
+ const posts = response.data?.list || response.posts || response.post_list || [];
41304
+ allPosts.push(...posts);
41305
+ continueFlag = response.data?.continueFlag ?? false;
41306
+ rawKeyBuff = response.data?.lastBuff || "";
41307
+ currentPage++;
41308
+ if (currentPage > 100) {
41309
+ _task.logger.warn("分页超过100页,停止请求");
41310
+ break;
41311
+ }
41312
+ }
41313
+ if (totalCount > 0 && allPosts.length !== totalCount) _task.logger.warn(`视频号分页可能不完整:期望${totalCount}条,实际${allPosts.length}条`);
41314
+ return {
41315
+ posts: allPosts,
41316
+ totalCount
41317
+ };
41318
+ }
41319
+ const mapPost = (item, forcePostType)=>{
41320
+ let imageUrl = "";
41321
+ if (item.desc?.media?.[0]?.thumbUrl) imageUrl = item.desc.media[0].thumbUrl;
41322
+ else if (item.desc?.media?.[0]?.coverUrl) imageUrl = item.desc.media[0].coverUrl;
41323
+ else if (item.cover?.url) imageUrl = item.cover.url;
41324
+ else if (item.media_url) imageUrl = item.media_url;
41325
+ const title = item.desc?.description || item.object_desc || "无标题";
41326
+ return {
41327
+ title,
41328
+ imageUrl,
41329
+ createTime: item.createTime || item.create_time,
41330
+ redirectUrl: "https://channels.weixin.qq.com/platform",
41331
+ readNum: item.readCount || item.read_count || 0,
41332
+ likeNum: item.likeCount || item.like_count || 0,
41333
+ commentNum: item.commentCount || item.comment_count || 0,
41334
+ forwardNum: item.forwardCount || item.forward_count || 0,
41335
+ favNum: item.favCount || item.fav_count || 0,
41336
+ objectId: item.exportId || item.objectId || "",
41337
+ postType: forcePostType,
41338
+ postStatus: item.status || item.post_status || 0,
41339
+ ...item.effectiveTime ? {
41340
+ effectiveTime: item.effectiveTime
41341
+ } : {},
41342
+ ...showOriginalData ? {
41343
+ originalData: item
41344
+ } : {}
41345
+ };
41346
+ };
41347
+ const allArticles = [];
41348
+ const needVideo = "all" === postType || "video" === postType;
41349
+ const needArticle = "all" === postType || "article" === postType;
41350
+ const AUTH_ERROR_CODES = [
41351
+ 300333,
41352
+ 300334,
41353
+ 300330,
41354
+ 300331,
41355
+ 300332
41356
+ ];
41357
+ let combinedTotal = 0;
41358
+ if (needVideo) try {
41359
+ const videoPageUrl = "https://channels.weixin.qq.com/micro/content/post/list";
41360
+ const { posts, totalCount } = await fetchAllPosts(11, videoPageUrl);
41361
+ const videoArticles = posts.filter((item)=>item.createTime || item.create_time).map((item)=>mapPost(item, "video"));
41362
+ allArticles.push(...videoArticles);
41363
+ combinedTotal += totalCount || videoArticles.length;
41364
+ } catch (error) {
41365
+ const errMsg = error instanceof Error ? error.message : String(error);
41366
+ if (errMsg.startsWith("AUTH_ERROR:")) throw error;
41367
+ _task.logger.warn(`获取视频号视频失败:${errMsg}`);
41368
+ }
41369
+ if (needArticle) try {
41370
+ const articlePageUrl = "https://channels.weixin.qq.com/micro/content/post/finderNewLifePostList";
41371
+ const { posts, totalCount } = await fetchAllPosts(10, articlePageUrl);
41372
+ const articleArticles = posts.filter((item)=>item.createTime || item.create_time).map((item)=>mapPost(item, "article"));
41373
+ allArticles.push(...articleArticles);
41374
+ combinedTotal += totalCount || articleArticles.length;
41375
+ } catch (error) {
41376
+ const errMsg = error instanceof Error ? error.message : String(error);
41377
+ if (errMsg.startsWith("AUTH_ERROR:")) throw error;
41378
+ _task.logger.warn(`获取视频号图文失败:${errMsg}`);
41379
+ }
41380
+ allArticles.sort((a, b)=>b.createTime - a.createTime);
41381
+ const total = allArticles.length;
41382
+ const start = (pageNum - 1) * pageSize;
41383
+ const pageItems = allArticles.slice(start, start + pageSize);
41384
+ return success({
41385
+ articleCell: pageItems,
41386
+ pagination: {
41387
+ total,
41388
+ nextPage: start + pageSize < total,
41389
+ pageNum,
41390
+ pageSize
41391
+ }
41392
+ }, "视频号数据获取成功");
41393
+ } catch (error) {
41394
+ const errMsg = error instanceof Error ? error.message : String(error);
41395
+ if (errMsg.startsWith("AUTH_ERROR:")) return searchPublishInfo_types_errorResponse("视频号数据获取失败,请检查账号状态", 414);
41396
+ return searchPublishInfo_types_errorResponse(errMsg || "视频号数据获取失败");
41397
+ }
41398
+ }
40844
41399
  async function handleToutiaoData(_task, params) {
40845
41400
  try {
40846
41401
  const { cookies, pageNum = 1, pageSize = 10, showOriginalData = false, onlySuccess = false, containsArticle = false } = params;
@@ -40873,7 +41428,7 @@ var __webpack_exports__ = {};
40873
41428
  app_id: 1231
40874
41429
  }
40875
41430
  });
40876
- if (0 !== visitedUid.code) return searchPublishInfo_types_errorResponse("头条号账号信息获取失败,请检查账号状态", 414);
41431
+ if (0 !== visitedUid.code) return searchPublishInfo_types_errorResponse("头条号数据获取失败,请检查账号状态", 414);
40877
41432
  const articleInfo = await http.api({
40878
41433
  method: "get",
40879
41434
  url: "https://mp.toutiao.com/api/feed/mp_provider/v1/",
@@ -40982,7 +41537,7 @@ var __webpack_exports__ = {};
40982
41537
  const size = onlySuccess ? 10 : pageSize > 20 ? 20 : pageSize;
40983
41538
  let begin = (lastPage ?? pageNum) - 1;
40984
41539
  const rawArticlesInfo = await fetchArticles(begin * size, size, token);
40985
- if (rawArticlesInfo.includes("请重新<a id='jumpUrl' href='/'>登录</a>")) return searchPublishInfo_types_errorResponse("登陆已失效,请重新登陆!", 414);
41540
+ if (rawArticlesInfo.includes("请重新<a id='jumpUrl' href='/'>登录</a>")) return searchPublishInfo_types_errorResponse("微信公众号数据获取失败,请检查账号状态", 414);
40986
41541
  const articlesInfo = ParsePublishPage(rawArticlesInfo);
40987
41542
  let articleCell = [];
40988
41543
  if (!onlySuccess && pageSize > 20) {
@@ -41144,7 +41699,7 @@ var __webpack_exports__ = {};
41144
41699
  const a1Cookie = cookies.find((it)=>"a1" === it.name)?.value;
41145
41700
  if (!a1Cookie) return {
41146
41701
  code: 414,
41147
- message: "账号数据异常",
41702
+ message: "小红书数据获取失败,请检查账号状态",
41148
41703
  data: {}
41149
41704
  };
41150
41705
  if (onlySuccess && 10 !== pageSize) return {
@@ -41263,7 +41818,7 @@ var __webpack_exports__ = {};
41263
41818
  }, "小红书文章数据获取成功");
41264
41819
  }
41265
41820
  const FetchArticlesParamsSchema = ActionCommonParamsSchema.extend({
41266
- platform: classic_schemas_string().describe("社交平台:weixin, toutiao, baijiahao, xiaohongshu"),
41821
+ platform: classic_schemas_string().describe("社交平台:weixin, toutiao, baijiahao, xiaohongshu, douyin, shipinhao"),
41267
41822
  token: schemas_union([
41268
41823
  classic_schemas_string(),
41269
41824
  classic_schemas_number()
@@ -41275,7 +41830,14 @@ var __webpack_exports__ = {};
41275
41830
  showOriginalData: classic_schemas_boolean().optional().describe("是否展示原始数据,默认false"),
41276
41831
  cursor: classic_schemas_number().optional().describe("仅用于微信分页游标,默认为空"),
41277
41832
  lastPage: classic_schemas_number().optional(),
41278
- containsArticle: classic_schemas_boolean().optional().describe("是否包含文章内容,默认false")
41833
+ containsArticle: classic_schemas_boolean().optional().describe("是否包含文章内容,默认false"),
41834
+ status: classic_schemas_number().optional().describe("抖音作品状态:0=全部"),
41835
+ includeAccount: classic_schemas_boolean().optional().describe("是否包含账号数据,默认true"),
41836
+ postType: classic_schemas_enum([
41837
+ "video",
41838
+ "article",
41839
+ "all"
41840
+ ]).optional().describe("视频号作品类型:video=视频, article=图文, all=全部")
41279
41841
  });
41280
41842
  const FetchArticles = async (_task, params)=>{
41281
41843
  const { platform } = params;
@@ -41288,6 +41850,10 @@ var __webpack_exports__ = {};
41288
41850
  return handleBaijiahaoData(_task, params);
41289
41851
  case "xiaohongshu":
41290
41852
  return handleXiaohongshuData(_task, params);
41853
+ case "douyin":
41854
+ return handleDouyinData(_task, params);
41855
+ case "shipinhao":
41856
+ return handleShipinhaoData(_task, params);
41291
41857
  default:
41292
41858
  return success({}, "暂不支持该平台");
41293
41859
  }
@@ -42691,6 +43257,11 @@ var __webpack_exports__ = {};
42691
43257
  this.concurrentLimit = config.concurrentLimit || 4;
42692
43258
  this.singleFileSize = config.singleFileSize || 10485760;
42693
43259
  this.http = config.http || new Http();
43260
+ this.reqOptions = {
43261
+ timeout: config.timeout ?? 60000,
43262
+ retries: config.retries ?? 3,
43263
+ retryDelay: config.retryDelay ?? 2000
43264
+ };
42694
43265
  }
42695
43266
  calculateMd5(buffer) {
42696
43267
  const MAX_SIZE = 5242880;
@@ -42747,7 +43318,7 @@ var __webpack_exports__ = {};
42747
43318
  url: filePath,
42748
43319
  method: "get",
42749
43320
  responseType: "arraybuffer"
42750
- });
43321
+ }, this.reqOptions);
42751
43322
  return Buffer.from(resp);
42752
43323
  }
42753
43324
  return external_node_fs_default().promises.readFile(filePath);
@@ -42777,7 +43348,7 @@ var __webpack_exports__ = {};
42777
43348
  headers,
42778
43349
  data: requestBody,
42779
43350
  defaultErrorMsg: "获取UploadID失败"
42780
- });
43351
+ }, this.reqOptions);
42781
43352
  if (!resp?.UploadID) throw new Error(`获取 UploadID 失败: ${resp?.errMsg || "未知错误"}`);
42782
43353
  return resp.UploadID;
42783
43354
  }
@@ -42798,7 +43369,7 @@ var __webpack_exports__ = {};
42798
43369
  headers,
42799
43370
  data: chunk,
42800
43371
  defaultErrorMsg: `分片 ${partNumber} 上传失败`
42801
- });
43372
+ }, this.reqOptions);
42802
43373
  if (resp?.errCode !== void 0 && 0 !== resp.errCode) throw new Error(`分片 ${partNumber} 上传失败: ${resp.errMsg}`);
42803
43374
  if (onProgress) onProgress(chunk.length);
42804
43375
  return resp.ETag || "";
@@ -42822,7 +43393,7 @@ var __webpack_exports__ = {};
42822
43393
  headers,
42823
43394
  data: requestBody,
42824
43395
  defaultErrorMsg: "确认分片上传失败"
42825
- });
43396
+ }, this.reqOptions);
42826
43397
  if (resp?.ListPartsResult?.Part) return resp.ListPartsResult.Part.map((p)=>({
42827
43398
  PartNumber: parseInt(p.PartNumber),
42828
43399
  ETag: p.ETag
@@ -42848,7 +43419,7 @@ var __webpack_exports__ = {};
42848
43419
  headers,
42849
43420
  data: requestBody,
42850
43421
  defaultErrorMsg: "完成上传失败"
42851
- });
43422
+ }, this.reqOptions);
42852
43423
  if (!resp?.DownloadURL) throw new Error(`完成上传失败: ${resp?.errMsg || "未知错误"}`);
42853
43424
  return resp.DownloadURL;
42854
43425
  }
@@ -43199,7 +43770,9 @@ var __webpack_exports__ = {};
43199
43770
  task.logger.info("[shipinhaoPublish] 开始执行视频号发布 - Mock API 方式");
43200
43771
  const updateTaskState = task.taskStageStore?.update?.bind(task.taskStageStore, task.taskId || "");
43201
43772
  if (!params.extraParam.fingerPrintDeviceId || !params.extraParam.aId) return utils_response(400, "fingerPrintDeviceId和aId 不能为空", "");
43773
+ let currentStep = "初始化";
43202
43774
  try {
43775
+ currentStep = "解析认证信息";
43203
43776
  const cookieString = params.cookies.map((c)=>`${c.name}=${c.value}`).join("; ");
43204
43777
  const fingerPrintDeviceId = params.extraParam.fingerPrintDeviceId;
43205
43778
  const aId = params.extraParam.aId;
@@ -43220,8 +43793,10 @@ var __webpack_exports__ = {};
43220
43793
  headers
43221
43794
  });
43222
43795
  const proxyHttp = new Http(...args);
43796
+ currentStep = "验证发布参数";
43223
43797
  if (!params.banners || 0 === params.banners.length) return utils_response(400, "至少需要一张图片", "");
43224
43798
  const images = params.banners.slice(0, 18).filter((img)=>"string" == typeof img);
43799
+ currentStep = "获取用户信息";
43225
43800
  task.logger.info("[shipinhaoPublish] 获取用户信息...");
43226
43801
  console.log("cookieString", cookieString);
43227
43802
  const userInfo = await mock_getUserInfo(cookieString, http);
@@ -43232,6 +43807,7 @@ var __webpack_exports__ = {};
43232
43807
  }
43233
43808
  const finderUsername = userInfo.data.finderUser.finderUsername;
43234
43809
  console.log(finderUsername);
43810
+ currentStep = "获取上传认证密钥";
43235
43811
  task.logger.info("[shipinhaoPublish] 获取上传认证密钥...");
43236
43812
  const authKeyResponse = await getUploadAuthKey(cookieString, finderUsername, http);
43237
43813
  if (0 !== authKeyResponse.errCode || !authKeyResponse.data?.authKey) return utils_response(authKeyResponse.errCode || 500, `获取上传认证参数失败: ${authKeyResponse.errMsg}`, "");
@@ -43239,10 +43815,12 @@ var __webpack_exports__ = {};
43239
43815
  const uin = authKeyResponse.data.uin;
43240
43816
  if (!uin) return utils_response(500, "获取用户 uin 失败", "");
43241
43817
  const taskId = String(generateUUID());
43818
+ currentStep = "上传图片";
43242
43819
  task.logger.info(`[shipinhaoPublish] 开始上传 ${images.length} 张图片...`);
43243
43820
  const uploadedImages = [];
43244
43821
  for(let i = 0; i < images.length; i++){
43245
- task.logger.info(`[shipinhaoPublish] 上传图片 ${i + 1}/${images.length}...`);
43822
+ currentStep = `上传图片 ${i + 1}/${images.length}`;
43823
+ task.logger.info(`[shipinhaoPublish] ${currentStep}...`);
43246
43824
  const uploadResult = await uploadImageComplete(images[i], taskId, finderUsername, uin, authKey, http);
43247
43825
  console.log(JSON.stringify(uploadResult));
43248
43826
  if (!uploadResult.DownloadURL) return utils_response(500, `图片上传失败: ${uploadResult.errMsg}`, "");
@@ -43259,6 +43837,7 @@ var __webpack_exports__ = {};
43259
43837
  urlCdnTaskId: ""
43260
43838
  });
43261
43839
  }
43840
+ currentStep = "发布图文内容";
43262
43841
  task.logger.info("[shipinhaoPublish] 正在发布...");
43263
43842
  const topicNames = params.topic || void 0;
43264
43843
  const addressInfo = params.address ? {
@@ -43345,9 +43924,15 @@ var __webpack_exports__ = {};
43345
43924
  });
43346
43925
  return utils_response(resultCode || 500, errorMessage, "");
43347
43926
  } catch (error) {
43348
- const errorMsg = error instanceof Error ? error.message : "发布失败";
43349
- task.logger.error(`[shipinhaoPublish] 发布异常: ${errorMsg}`);
43350
- return utils_response(500, errorMsg, "");
43927
+ const handledError = Http.handleApiError(error);
43928
+ const errorMsg = handledError.message || "发布失败,请稍后重试";
43929
+ const errorCode = handledError.code || 500;
43930
+ task.logger.error(`[shipinhaoPublish] 发布流程异常: ${errorMsg}`, stringifyError(error), handledError.extra);
43931
+ await updateTaskState?.({
43932
+ state: types_TaskState.FAILED,
43933
+ error: errorMsg
43934
+ });
43935
+ return utils_response(errorCode, errorMsg, "");
43351
43936
  }
43352
43937
  };
43353
43938
  const shipinhaoPublish_rpa_rpaAction = async (task, params)=>{
@@ -49853,6 +50438,24 @@ var __webpack_exports__ = {};
49853
50438
  likeNumYesterday: classic_schemas_number().nullable(),
49854
50439
  commentNumYesterday: classic_schemas_number().nullable()
49855
50440
  });
50441
+ const douyinConfigDataSchema = classic_schemas_object({
50442
+ fansNum: classic_schemas_number(),
50443
+ favedNum: classic_schemas_number(),
50444
+ fansNumLastWeek: classic_schemas_number(),
50445
+ watchNumLastWeek: classic_schemas_number(),
50446
+ likeNumLastWeek: classic_schemas_number(),
50447
+ commentNumLastWeek: classic_schemas_number(),
50448
+ shareNumLastWeek: classic_schemas_number(),
50449
+ visitNumLastWeek: classic_schemas_number()
50450
+ });
50451
+ const shipinhaoConfigDataSchema = classic_schemas_object({
50452
+ fansNum: classic_schemas_number(),
50453
+ feedsCount: classic_schemas_number(),
50454
+ fansNumYesterday: classic_schemas_number().nullable(),
50455
+ playNumYesterday: classic_schemas_number().nullable(),
50456
+ likeNumYesterday: classic_schemas_number().nullable(),
50457
+ commentNumYesterday: classic_schemas_number().nullable()
50458
+ });
49856
50459
  const BetaFlag = "HuiwenCanary";
49857
50460
  class Action {
49858
50461
  constructor(task){