@iflyrpa/actions 2.0.0-beta.7 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1721,7 +1721,7 @@ var __webpack_modules__ = {
1721
1721
  module.exports = GenXSCommon;
1722
1722
  },
1723
1723
  "./src/utils/douyin/csrfToken.js": function(module, __unused_webpack_exports, __webpack_require__) {
1724
- const crypto1 = __webpack_require__("crypto");
1724
+ const crypto = __webpack_require__("crypto");
1725
1725
  function generateCsrfToken(options = {}) {
1726
1726
  const { cookies = [], url = '', method = 'POST' } = options;
1727
1727
  const sessionid = getCookieValue(cookies, 'sessionid') || '';
@@ -1733,7 +1733,7 @@ var __webpack_modules__ = {
1733
1733
  const timestampHex = timestamp.toString(16).padStart(8, '0');
1734
1734
  const random = generateRandomHex(8);
1735
1735
  const signData = `${method}${url}${sessionid}${uid_tt}${msToken}${ttwid}${timestamp}`;
1736
- const hash = crypto1.createHash('md5').update(signData).digest('hex');
1736
+ const hash = crypto.createHash('md5').update(signData).digest('hex');
1737
1737
  const csrfToken = `0001${version}${timestampHex}${random}${hash}`;
1738
1738
  return csrfToken;
1739
1739
  }
@@ -1742,7 +1742,7 @@ var __webpack_modules__ = {
1742
1742
  return cookie ? cookie.value : '';
1743
1743
  }
1744
1744
  function generateRandomHex(length) {
1745
- const bytes = crypto1.randomBytes(Math.ceil(length / 2));
1745
+ const bytes = crypto.randomBytes(Math.ceil(length / 2));
1746
1746
  return bytes.toString('hex').slice(0, length);
1747
1747
  }
1748
1748
  function generateCsrfTokenAdvanced(options = {}) {
@@ -1775,8 +1775,8 @@ var __webpack_modules__ = {
1775
1775
  userAgent
1776
1776
  ].filter(Boolean);
1777
1777
  const signData = signParts.join('|');
1778
- const firstHash = crypto1.createHash('md5').update(signData).digest('hex');
1779
- const secondHash = crypto1.createHash('md5').update(firstHash + timestamp).digest('hex');
1778
+ const firstHash = crypto.createHash('md5').update(signData).digest('hex');
1779
+ const secondHash = crypto.createHash('md5').update(firstHash + timestamp).digest('hex');
1780
1780
  const timestampHex = timestampSec.toString(16).padStart(8, '0');
1781
1781
  const random = generateRandomHex(16);
1782
1782
  return `0001000${timestampHex.slice(0, 2)}${random}${secondHash}`;
@@ -1785,7 +1785,7 @@ var __webpack_modules__ = {
1785
1785
  const sessionid = getCookieValue(cookies, 'sessionid') || 'default_session';
1786
1786
  const timestamp = Math.floor(Date.now() / 1000);
1787
1787
  const random = generateRandomHex(32);
1788
- const hash = crypto1.createHash('md5').update(`${sessionid}${timestamp}${random}`).digest('hex');
1788
+ const hash = crypto.createHash('md5').update(`${sessionid}${timestamp}${random}`).digest('hex');
1789
1789
  const timestampHex = timestamp.toString(16).padStart(8, '0');
1790
1790
  return `0001000${timestampHex}${random}${hash}`.slice(0, 90);
1791
1791
  }
@@ -2184,7 +2184,7 @@ var __webpack_modules__ = {
2184
2184
  generateAuthorization: ()=>generateAuthorization,
2185
2185
  randomS: ()=>randomS
2186
2186
  });
2187
- const crypto1 = __webpack_require__("crypto");
2187
+ const crypto = __webpack_require__("crypto");
2188
2188
  const UNSIGNABLE_HEADERS = [
2189
2189
  'authorization',
2190
2190
  'content-type',
@@ -2195,10 +2195,10 @@ var __webpack_modules__ = {
2195
2195
  'x-amzn-trace-id'
2196
2196
  ];
2197
2197
  function sha256(data) {
2198
- return crypto1.createHash('sha256').update(data, 'utf8').digest('hex');
2198
+ return crypto.createHash('sha256').update(data, 'utf8').digest('hex');
2199
2199
  }
2200
2200
  function hmac(key, data) {
2201
- return crypto1.createHmac('sha256', key).update(data, 'utf8').digest();
2201
+ return crypto.createHmac('sha256', key).update(data, 'utf8').digest();
2202
2202
  }
2203
2203
  function getSigningKey(secretAccessKey, dateStamp, region, service) {
2204
2204
  const kDate = hmac('AWS4' + secretAccessKey, dateStamp);
@@ -2287,7 +2287,7 @@ var __webpack_modules__ = {
2287
2287
  canonicalRequestHash
2288
2288
  ].join('\n');
2289
2289
  const signingKey = getSigningKey(secretAccessKey, dateStamp, region, service);
2290
- const signature = crypto1.createHmac('sha256', signingKey).update(stringToSign, 'utf8').digest('hex');
2290
+ const signature = crypto.createHmac('sha256', signingKey).update(stringToSign, 'utf8').digest('hex');
2291
2291
  const authorization = `${algorithm} Credential=${accessKeyId}/${credentialScope}, SignedHeaders=${signedHeadersStr}, Signature=${signature}`;
2292
2292
  return {
2293
2293
  authorization,
@@ -2320,19 +2320,19 @@ var __webpack_modules__ = {
2320
2320
  }
2321
2321
  },
2322
2322
  "./src/utils/douyin/reqSign.js.js": function(module, __unused_webpack_exports, __webpack_require__) {
2323
- const crypto1 = __webpack_require__("crypto");
2323
+ const crypto = __webpack_require__("crypto");
2324
2324
  function bufferToHex(buffer) {
2325
2325
  return buffer.toString('hex');
2326
2326
  }
2327
2327
  function generateReqSign(privateKeyPem, data) {
2328
2328
  try {
2329
- const privateKey = crypto1.createPrivateKey({
2329
+ const privateKey = crypto.createPrivateKey({
2330
2330
  key: privateKeyPem,
2331
2331
  format: 'pem',
2332
2332
  type: 'pkcs8'
2333
2333
  });
2334
2334
  const dataBuffer = Buffer.from(data, 'utf8');
2335
- const signature = crypto1.sign('sha256', dataBuffer, {
2335
+ const signature = crypto.sign('sha256', dataBuffer, {
2336
2336
  key: privateKey,
2337
2337
  dsaEncoding: 'der'
2338
2338
  });
@@ -4967,10 +4967,12 @@ var __webpack_exports__ = {};
4967
4967
  XhsWebSearchParamsSchema: ()=>XhsWebSearchParamsSchema,
4968
4968
  ttConfigDataSchema: ()=>ttConfigDataSchema,
4969
4969
  getFileState: ()=>getFileState,
4970
- DouyinPublishParamsSchema: ()=>DouyinPublishParamsSchema,
4971
4970
  DouyinGetMusicCategoryParamsSchema: ()=>DouyinGetMusicCategoryParamsSchema,
4971
+ DouyinPublishParamsSchema: ()=>DouyinPublishParamsSchema,
4972
4972
  xhsConfigDataSchema: ()=>xhsConfigDataSchema,
4973
4973
  SessionCheckResultSchema: ()=>SessionCheckResultSchema,
4974
+ DouyinGetCommentReplyListParamsSchema: ()=>DouyinGetCommentReplyListParamsSchema,
4975
+ DouyinCreateCommentReplyParamsSchema: ()=>DouyinCreateCommentReplyParamsSchema,
4974
4976
  DouyinGetHotParamsSchema: ()=>DouyinGetHotParamsSchema,
4975
4977
  DouyinGetMusicParamsSchema: ()=>DouyinGetMusicParamsSchema,
4976
4978
  FetchArticlesDataSchema: ()=>FetchArticlesDataSchema,
@@ -4984,6 +4986,7 @@ var __webpack_exports__ = {};
4984
4986
  DouyinGetCollectionParamsSchema: ()=>DouyinGetCollectionParamsSchema,
4985
4987
  ShipinhaoGetLocationParamsSchema: ()=>ShipinhaoGetLocationParamsSchema,
4986
4988
  DouyinGetTopicsParamsSchema: ()=>DouyinGetTopicsParamsSchema,
4989
+ DouyinGetCommentListParamsSchema: ()=>DouyinGetCommentListParamsSchema,
4987
4990
  UnreadCountSchema: ()=>UnreadCountSchema,
4988
4991
  ShipinhaoCheckLinkValidateParamsSchema: ()=>ShipinhaoCheckLinkValidateParamsSchema,
4989
4992
  ActionCommonParamsSchema: ()=>ActionCommonParamsSchema,
@@ -4994,13 +4997,14 @@ var __webpack_exports__ = {};
4994
4997
  BetaFlag: ()=>BetaFlag,
4995
4998
  bjhConfigDataSchema: ()=>bjhConfigDataSchema,
4996
4999
  BaijiahaoPublishParamsSchema: ()=>BaijiahaoPublishParamsSchema,
5000
+ DouyinGetWorkListParamsSchema: ()=>DouyinGetWorkListParamsSchema,
4997
5001
  version: ()=>package_namespaceObject.i8,
4998
5002
  Action: ()=>Action,
4999
5003
  ProxyAgent: ()=>ProxyAgent
5000
5004
  });
5001
5005
  const package_json_namespaceObject = require("@iflyrpa/share/package.json");
5002
5006
  var package_json_default = /*#__PURE__*/ __webpack_require__.n(package_json_namespaceObject);
5003
- var package_namespaceObject = JSON.parse('{"i8":"2.0.0-beta.6"}');
5007
+ var package_namespaceObject = JSON.parse('{"i8":"2.0.0-beta.8"}');
5004
5008
  const share_namespaceObject = require("@iflyrpa/share");
5005
5009
  const external_node_fs_namespaceObject = require("node:fs");
5006
5010
  var external_node_fs_default = /*#__PURE__*/ __webpack_require__.n(external_node_fs_namespaceObject);
@@ -5442,7 +5446,7 @@ var __webpack_exports__ = {};
5442
5446
  });
5443
5447
  } catch (e) {
5444
5448
  return {
5445
- code: 500,
5449
+ code: 414,
5446
5450
  message: `浏览器启动失败: ${e}`,
5447
5451
  data: {}
5448
5452
  };
@@ -11249,11 +11253,122 @@ var __webpack_exports__ = {};
11249
11253
  };
11250
11254
  return (0, share_namespaceObject.success)(data, message);
11251
11255
  };
11256
+ const rid = ()=>`${Math.floor(Date.now() / 1e3).toString(16)}-${[
11257
+ ...Array(8)
11258
+ ].map(()=>Math.floor(16 * Math.random()).toString(16)).join("")}`;
11259
+ new Uint8Array(16);
11260
+ const hexTable = [];
11261
+ for(let i = 0; i < 256; i++)hexTable.push((i + 256).toString(16).substr(1));
11262
+ const createShipinhaoComment = async (_task, params)=>{
11263
+ if (!params.content || "" === params.content.trim()) return (0, share_namespaceObject.response)(400, "评论内容不能为空", void 0);
11264
+ if (!params.exportId) return (0, share_namespaceObject.response)(400, "exportId 不能为空", void 0);
11265
+ if (!params.extraParam) return (0, share_namespaceObject.response)(400, "缺少 extraParam 参数", void 0);
11266
+ if (!params.extraParam.fingerPrintDeviceId || !params.extraParam.aId || !params.extraParam.uin) return (0, share_namespaceObject.response)(400, "fingerPrintDeviceId、aId和uin不能为空", void 0);
11267
+ const headers = {
11268
+ cookie: params.cookies.map((it)=>`${it.name}=${it.value}`).join(";"),
11269
+ referer: "https://channels.weixin.qq.com/micro/interaction/comment",
11270
+ origin: "https://channels.weixin.qq.com",
11271
+ "content-type": "application/json",
11272
+ "finger-print-device-id": params.extraParam.fingerPrintDeviceId,
11273
+ "x-wechat-uin": params.extraParam.uin
11274
+ };
11275
+ const http = new Http({
11276
+ headers
11277
+ });
11278
+ const urlParams = new URLSearchParams({
11279
+ _aid: params.extraParam.aId,
11280
+ _rid: rid(),
11281
+ _pageUrl: "https://channels.weixin.qq.com/micro/interaction/comment"
11282
+ }).toString();
11283
+ const requestData = {
11284
+ replyCommentId: params.replyCommentId || "",
11285
+ content: params.content,
11286
+ clientId: `${Date.now()}-${Math.random().toString(36).substring(2, 15)}`,
11287
+ rootCommentId: params.rootCommentId || "",
11288
+ comment: {},
11289
+ exportId: params.exportId,
11290
+ timestamp: Date.now().toString(),
11291
+ _log_finder_uin: "",
11292
+ _log_finder_id: params.extraParam.finderUserName || "",
11293
+ rawKeyBuff: null,
11294
+ pluginSessionId: null,
11295
+ scene: 7,
11296
+ reqScene: 7
11297
+ };
11298
+ if (params.rootCommentId) requestData.rootCommentId = params.rootCommentId;
11299
+ if (params.replyCommentId) requestData.replyCommentId = params.replyCommentId;
11300
+ const res = await http.api({
11301
+ method: "post",
11302
+ url: `https://channels.weixin.qq.com/micro/interaction/cgi-bin/mmfinderassistant-bin/comment/create_comment?${urlParams}`,
11303
+ data: requestData
11304
+ });
11305
+ console.log(res, "----create comment res");
11306
+ const isSuccess = res?.errCode === 0;
11307
+ return (0, share_namespaceObject.response)(isSuccess ? 0 : 414, res?.errMsg || "添加评论失败", res.data);
11308
+ };
11309
+ const DouyinCreateCommentReplyParamsSchema = ActionCommonParamsSchema.extend({
11310
+ itemId: schemas_string(),
11311
+ commentId: schemas_string(),
11312
+ text: schemas_string()
11313
+ });
11314
+ const { sign_reply } = __webpack_require__("./src/utils/douyin/douyin.js");
11315
+ const { generateCsrfTokenAdvanced } = __webpack_require__("./src/utils/douyin/csrfToken.js");
11316
+ const douyinCreateCommentReply = async (_task, params)=>{
11317
+ const headers = {
11318
+ cookie: params.cookies.map((it)=>`${it.name}=${it.value}`).join(";"),
11319
+ referer: "https://creator.douyin.com/",
11320
+ origin: "https://creator.douyin.com/"
11321
+ };
11322
+ const args = [
11323
+ {
11324
+ headers
11325
+ },
11326
+ _task.logger,
11327
+ params.proxyLoc,
11328
+ params.localIP,
11329
+ params.accountId
11330
+ ];
11331
+ const http = new Http(...args);
11332
+ const csrfToken = generateCsrfTokenAdvanced(params.cookies);
11333
+ console.log("生成的 csrfToken:", csrfToken);
11334
+ const queryParams = {
11335
+ aid: "2906",
11336
+ msToken: params.cookies.find((e)=>"msToken" === e.name)?.value || "",
11337
+ a_bogus: ""
11338
+ };
11339
+ const aBogus = sign_reply(queryParams, "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36");
11340
+ queryParams.a_bogus = aBogus;
11341
+ const queryString = new URLSearchParams(queryParams).toString();
11342
+ const body = {
11343
+ comment_Id: params.commentId,
11344
+ text: params.text,
11345
+ item_id: params.itemId
11346
+ };
11347
+ console.log("抖音添加评论回复参数:", body);
11348
+ const res = await http.api({
11349
+ method: "post",
11350
+ url: `https://creator.douyin.com/aweme/v1/creator/comment/reply/?${queryString}`,
11351
+ data: body,
11352
+ headers: {
11353
+ ...headers,
11354
+ "Content-Type": "application/json",
11355
+ "X-secsdk-csrf-token": csrfToken
11356
+ }
11357
+ }, {
11358
+ retries: 3,
11359
+ retryDelay: 20,
11360
+ timeout: 3000
11361
+ });
11362
+ console.log("抖音添加评论回复响应:", res);
11363
+ const isSuccess = 0 === res.status_code;
11364
+ const message = `抖音添加评论回复${isSuccess ? "成功" : `失败,原因:${res.status_msg}`}${_task.debug ? ` ${http.proxyInfo}` : ""}`;
11365
+ return (0, share_namespaceObject.response)(isSuccess ? 0 : 414, message, res);
11366
+ };
11252
11367
  const DouyinGetCollectionParamsSchema = ActionCommonParamsSchema.extend({
11253
11368
  keyword: schemas_string().optional(),
11254
11369
  count: schemas_number().optional()
11255
11370
  });
11256
- const { sign_datail, sign_reply } = __webpack_require__("./src/utils/douyin/douyin.js");
11371
+ const { sign_datail, sign_reply: douyinGetCollection_sign_reply } = __webpack_require__("./src/utils/douyin/douyin.js");
11257
11372
  const douyinGetCollection = async (_task, params)=>{
11258
11373
  const headers = {
11259
11374
  cookie: params.cookies.map((it)=>`${it.name}=${it.value}`).join(";"),
@@ -11289,7 +11404,7 @@ var __webpack_exports__ = {};
11289
11404
  msToken: params.cookies.find((e)=>"msToken" === e.name)?.value || "rWRQTO837CH1bajTIbvPAL9o1lpyzocwIToJZFtN61sBoeN_OJM2ykkGFhQxgq6OXOzn2XDML8Lvo829NxjGfQy00RLGJ2q9DMaPEhrgSVv9YklzRT1sT7R03XZ3I6_3y7D_m0wnjGszj8IBQq8EpTNk8B0S3YIbUGfnl_Za9VnS25CU7PygDEY=",
11290
11405
  a_bogus: ""
11291
11406
  };
11292
- const aBogus = sign_reply(collectionParams, "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36");
11407
+ const aBogus = douyinGetCollection_sign_reply(collectionParams, "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36");
11293
11408
  collectionParams.a_bogus = aBogus;
11294
11409
  const queryString = new URLSearchParams(collectionParams).toString();
11295
11410
  const res = await http.api({
@@ -11315,6 +11430,117 @@ var __webpack_exports__ = {};
11315
11430
  };
11316
11431
  return (0, share_namespaceObject.response)(isSuccess ? 0 : 414, message, data);
11317
11432
  };
11433
+ const DouyinGetCommentListParamsSchema = ActionCommonParamsSchema.extend({
11434
+ cursor: schemas_number().optional(),
11435
+ count: schemas_number().optional(),
11436
+ itemId: schemas_string()
11437
+ });
11438
+ const { sign_datail: douyinGetCommentList_sign_datail, sign_reply: douyinGetCommentList_sign_reply } = __webpack_require__("./src/utils/douyin/douyin.js");
11439
+ const { generateCsrfTokenAdvanced: douyinGetCommentList_generateCsrfTokenAdvanced } = __webpack_require__("./src/utils/douyin/csrfToken.js");
11440
+ const douyinGetCommentList = async (_task, params)=>{
11441
+ const headers = {
11442
+ cookie: params.cookies.map((it)=>`${it.name}=${it.value}`).join(";"),
11443
+ referer: "https://creator.douyin.com/",
11444
+ origin: "https://creator.douyin.com/"
11445
+ };
11446
+ const args = [
11447
+ {
11448
+ headers
11449
+ },
11450
+ _task.logger,
11451
+ params.proxyLoc,
11452
+ params.localIP,
11453
+ params.accountId
11454
+ ];
11455
+ const http = new Http(...args);
11456
+ const csrfToken = douyinGetCommentList_generateCsrfTokenAdvanced(params.cookies);
11457
+ console.log("生成的 csrfToken:", csrfToken);
11458
+ const commentListParams = {
11459
+ count: params.count?.toString() || "10",
11460
+ cursor: params.cursor?.toString() || "0",
11461
+ aid: "2906",
11462
+ sort: "TIME",
11463
+ item_id: params.itemId || "",
11464
+ msToken: params.cookies.find((e)=>"msToken" === e.name)?.value || "",
11465
+ a_bogus: ""
11466
+ };
11467
+ const aBogus = douyinGetCommentList_sign_reply(commentListParams, "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36");
11468
+ commentListParams.a_bogus = aBogus;
11469
+ const queryString = new URLSearchParams(commentListParams).toString();
11470
+ console.log("抖音获取评论列表参数:", queryString);
11471
+ const res = await http.api({
11472
+ method: "get",
11473
+ url: `https://creator.douyin.com/aweme/v1/creator/comment/list/?${queryString}`,
11474
+ headers: {
11475
+ ...headers,
11476
+ "Content-Type": "application/json",
11477
+ "X-secsdk-csrf-token": csrfToken
11478
+ }
11479
+ }, {
11480
+ retries: 3,
11481
+ retryDelay: 20,
11482
+ timeout: 3000
11483
+ });
11484
+ console.log("抖音获取评论列表响应:", res);
11485
+ const isSuccess = 0 === res.status_code;
11486
+ const message = `抖音获取评论列表${isSuccess ? "成功" : `失败,原因:${res.status_msg}`}${_task.debug ? ` ${http.proxyInfo}` : ""}`;
11487
+ return (0, share_namespaceObject.response)(isSuccess ? 0 : 414, message, res);
11488
+ };
11489
+ const DouyinGetCommentReplyListParamsSchema = ActionCommonParamsSchema.extend({
11490
+ commentId: schemas_string(),
11491
+ cursor: schemas_number().optional(),
11492
+ count: schemas_number().optional()
11493
+ });
11494
+ const { sign_datail: douyinGetCommentReplyList_sign_datail, sign_reply: douyinGetCommentReplyList_sign_reply } = __webpack_require__("./src/utils/douyin/douyin.js");
11495
+ const { generateCsrfTokenAdvanced: douyinGetCommentReplyList_generateCsrfTokenAdvanced } = __webpack_require__("./src/utils/douyin/csrfToken.js");
11496
+ const douyinGetCommentReplyList = async (_task, params)=>{
11497
+ const headers = {
11498
+ cookie: params.cookies.map((it)=>`${it.name}=${it.value}`).join(";"),
11499
+ referer: "https://creator.douyin.com/",
11500
+ origin: "https://creator.douyin.com/"
11501
+ };
11502
+ const args = [
11503
+ {
11504
+ headers
11505
+ },
11506
+ _task.logger,
11507
+ params.proxyLoc,
11508
+ params.localIP,
11509
+ params.accountId
11510
+ ];
11511
+ const http = new Http(...args);
11512
+ const csrfToken = douyinGetCommentReplyList_generateCsrfTokenAdvanced(params.cookies);
11513
+ console.log("生成的 csrfToken:", csrfToken);
11514
+ const replyListParams = {
11515
+ count: params.count?.toString() || "10",
11516
+ cursor: params.cursor?.toString() || "0",
11517
+ aid: "2906",
11518
+ comment_id: params.commentId,
11519
+ msToken: params.cookies.find((e)=>"msToken" === e.name)?.value || "",
11520
+ a_bogus: ""
11521
+ };
11522
+ const aBogus = douyinGetCommentReplyList_sign_reply(replyListParams, "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36");
11523
+ replyListParams.a_bogus = aBogus;
11524
+ const queryString = new URLSearchParams(replyListParams).toString();
11525
+ console.log("抖音获取评论回复列表参数:", queryString);
11526
+ const res = await http.api({
11527
+ method: "get",
11528
+ url: `https://creator.douyin.com/aweme/v1/creator/comment/reply/list/?${queryString}`,
11529
+ headers: {
11530
+ ...headers,
11531
+ "Content-Type": "application/json",
11532
+ "X-secsdk-csrf-token": csrfToken
11533
+ }
11534
+ }, {
11535
+ retries: 3,
11536
+ retryDelay: 20,
11537
+ timeout: 3000
11538
+ });
11539
+ console.log("抖音获取评论回复列表响应:", res);
11540
+ const isSuccess = 0 === res.status_code;
11541
+ const message = `抖音获取评论回复列表${isSuccess ? "成功" : `失败,原因:${res.status_msg}`}${_task.debug ? ` ${http.proxyInfo}` : ""}`;
11542
+ return (0, share_namespaceObject.response)(isSuccess ? 0 : 414, message, res);
11543
+ };
11318
11544
  const DouyinGetHotParamsSchema = ActionCommonParamsSchema.extend({
11319
11545
  query: schemas_string().optional(),
11320
11546
  count: schemas_number().optional()
@@ -11758,6 +11984,70 @@ var __webpack_exports__ = {};
11758
11984
  };
11759
11985
  return (0, share_namespaceObject.response)(isSuccess ? 0 : 414, message, data);
11760
11986
  };
11987
+ const DouyinGetWorkListParamsSchema = ActionCommonParamsSchema.extend({
11988
+ cursor: schemas_number().optional(),
11989
+ count: schemas_number().optional()
11990
+ });
11991
+ const { sign_datail: douyinGetWorkList_sign_datail, sign_reply: douyinGetWorkList_sign_reply } = __webpack_require__("./src/utils/douyin/douyin.js");
11992
+ const { generateCsrfTokenAdvanced: douyinGetWorkList_generateCsrfTokenAdvanced } = __webpack_require__("./src/utils/douyin/csrfToken.js");
11993
+ const douyinGetWorkList = async (_task, params)=>{
11994
+ const headers = {
11995
+ cookie: params.cookies.map((it)=>`${it.name}=${it.value}`).join(";"),
11996
+ referer: "https://creator.douyin.com/",
11997
+ origin: "https://creator.douyin.com/"
11998
+ };
11999
+ const args = [
12000
+ {
12001
+ headers
12002
+ },
12003
+ _task.logger,
12004
+ params.proxyLoc,
12005
+ params.localIP,
12006
+ params.accountId
12007
+ ];
12008
+ const http = new Http(...args);
12009
+ const csrfToken = douyinGetWorkList_generateCsrfTokenAdvanced(params.cookies);
12010
+ console.log("生成的 csrfToken:", csrfToken);
12011
+ const workListParams = {
12012
+ count: params.count?.toString() || "10",
12013
+ cursor: params.cursor?.toString() || "",
12014
+ aid: "2906",
12015
+ msToken: params.cookies.find((e)=>"msToken" === e.name)?.value || "",
12016
+ a_bogus: ""
12017
+ };
12018
+ const aBogus = douyinGetWorkList_sign_reply(workListParams, "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36");
12019
+ workListParams.a_bogus = aBogus;
12020
+ const queryString = new URLSearchParams(workListParams).toString();
12021
+ console.log("抖音获取作品列表参数:", queryString);
12022
+ const res = await http.api({
12023
+ method: "get",
12024
+ url: `https://creator.douyin.com/aweme/v1/creator/item/list/?${queryString}`,
12025
+ headers: {
12026
+ ...headers,
12027
+ "Content-Type": "application/json",
12028
+ "X-secsdk-csrf-token": csrfToken
12029
+ }
12030
+ }, {
12031
+ retries: 3,
12032
+ retryDelay: 20,
12033
+ timeout: 3000
12034
+ });
12035
+ console.log("抖音获取作品列表响应:", res);
12036
+ const isSuccess = 0 === res.status_code;
12037
+ const message = `抖音获取作品列表${isSuccess ? "成功" : `失败,原因:${res.status_msg}`}${_task.debug ? ` ${http.proxyInfo}` : ""}`;
12038
+ const data = isSuccess ? {
12039
+ works: res?.aweme_list || [],
12040
+ has_more: res?.has_more || false,
12041
+ cursor: res?.cursor || 0,
12042
+ total: res?.aweme_list?.length || 0
12043
+ } : {
12044
+ works: [],
12045
+ has_more: false,
12046
+ cursor: 0,
12047
+ total: 0
12048
+ };
12049
+ return (0, share_namespaceObject.response)(isSuccess ? 0 : 414, message, data);
12050
+ };
11761
12051
  const rpa_scanRetryMaxCount = 60;
11762
12052
  const rpa_waitQrcodeResultMaxTime = 2000 * rpa_scanRetryMaxCount;
11763
12053
  const douyinLogin_rpa_rpaAction = async (task, params)=>{
@@ -11777,7 +12067,7 @@ var __webpack_exports__ = {};
11777
12067
  } catch (e) {
11778
12068
  task.logger.error("浏览器启动失败", e);
11779
12069
  return {
11780
- code: 500,
12070
+ code: 414,
11781
12071
  message: `浏览器启动失败: ${e}`,
11782
12072
  data: {}
11783
12073
  };
@@ -12534,7 +12824,7 @@ var __webpack_exports__ = {};
12534
12824
  }
12535
12825
  const { sign_reply: mock_sign_reply } = __webpack_require__("./src/utils/douyin/douyin.js");
12536
12826
  const { generateReqSignFromTicket } = __webpack_require__("./src/utils/douyin/reqSign.js.js");
12537
- const { generateCsrfTokenAdvanced } = __webpack_require__("./src/utils/douyin/csrfToken.js");
12827
+ const { generateCsrfTokenAdvanced: mock_generateCsrfTokenAdvanced } = __webpack_require__("./src/utils/douyin/csrfToken.js");
12538
12828
  const mock_mockAction = async (task, params)=>{
12539
12829
  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"]) return (0, share_namespaceObject.response)(400, "extraParam 参数缺失或不完整", "");
12540
12830
  const tmpCachePath = task.getTmpPath();
@@ -12580,7 +12870,7 @@ var __webpack_exports__ = {};
12580
12870
  cookie: params.cookies.map((it)=>`${it.name}=${it.value}`).join(";"),
12581
12871
  origin: "https://creator.douyin.com",
12582
12872
  referer: "https://creator.douyin.com/",
12583
- "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36"
12873
+ "user-agent": params.userAgent || ""
12584
12874
  };
12585
12875
  const publishParams = {
12586
12876
  read_aid: "2906",
@@ -12591,7 +12881,7 @@ var __webpack_exports__ = {};
12591
12881
  browser_language: "zh-CN",
12592
12882
  browser_platform: "Win32",
12593
12883
  browser_name: "Mozilla",
12594
- browser_version: "5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36",
12884
+ browser_version: params.userAgent || "",
12595
12885
  browser_online: "true",
12596
12886
  timezone_name: "Asia/Shanghai",
12597
12887
  support_h265: "1",
@@ -12627,7 +12917,7 @@ var __webpack_exports__ = {};
12627
12917
  }
12628
12918
  }
12629
12919
  };
12630
- const aBogus = mock_sign_reply(publishParams, "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36");
12920
+ const aBogus = mock_sign_reply(publishParams, params.userAgent);
12631
12921
  publishParams.a_bogus = aBogus;
12632
12922
  const queryString = new URLSearchParams(publishParams).toString();
12633
12923
  const args = [
@@ -12673,7 +12963,7 @@ var __webpack_exports__ = {};
12673
12963
  const publishQuery = {
12674
12964
  ...publishParams
12675
12965
  };
12676
- publishQuery.a_bogus = mock_sign_reply(publishQuery, "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36");
12966
+ publishQuery.a_bogus = mock_sign_reply(publishQuery, params.userAgent);
12677
12967
  const publishQueryParams = new URLSearchParams(publishQuery).toString();
12678
12968
  function generateRandomString(length) {
12679
12969
  const characters = "abcdefghijklmnopqrstuvwxyz0123456789";
@@ -12685,7 +12975,7 @@ var __webpack_exports__ = {};
12685
12975
  return randomString;
12686
12976
  }
12687
12977
  publishData.item.common.creation_id = generateRandomString(8) + Date.now();
12688
- const csrfToken = generateCsrfTokenAdvanced({
12978
+ const csrfToken = mock_generateCsrfTokenAdvanced({
12689
12979
  cookies: params.cookies,
12690
12980
  url: "https://creator.douyin.com/web/api/media/aweme/create_v2/",
12691
12981
  method: "POST",
@@ -12701,6 +12991,7 @@ var __webpack_exports__ = {};
12701
12991
  ...headers,
12702
12992
  Referer: "https://creator.douyin.com/creator-micro/content/post/image?default-tab=3&enter_from=publish_page&media_type=image&type=new",
12703
12993
  "Content-Type": "application/json",
12994
+ Accept: "application/json, text/plain, */*",
12704
12995
  "Bd-ticket-guard-client-data": bdTicketGuardClientData,
12705
12996
  "Bd-ticket-guard-ree-public-key": ree_public_key,
12706
12997
  "Bd-ticket-guard-version": "2",
@@ -12738,7 +13029,6 @@ var __webpack_exports__ = {};
12738
13029
  return (0, share_namespaceObject.response)(isSuccess ? 0 : 414, message, data);
12739
13030
  };
12740
13031
  const douyinPublish_rpa_rpaAction = async (task, params)=>{
12741
- const updateTaskState = task.taskStageStore?.update?.bind(task.taskStageStore, task.taskId || "");
12742
13032
  const commonCookies = {
12743
13033
  path: "/",
12744
13034
  secure: true,
@@ -12754,77 +13044,280 @@ var __webpack_exports__ = {};
12754
13044
  ...commonCookies
12755
13045
  }))
12756
13046
  });
12757
- await updateTaskState?.({
12758
- state: share_namespaceObject.TaskState.ACTION,
12759
- connectAddress: task.steelConnector?.getProxyUrl(task.sessionId || "", "v1/sessions/debug"),
12760
- sessionId: task.sessionId
12761
- });
12762
13047
  const tmpCachePath = task.getTmpPath();
13048
+ const waitForElement = async (selector, timeout = 10000)=>{
13049
+ try {
13050
+ const element = page.locator(selector);
13051
+ task.logger.warn(`element: ${element}`);
13052
+ await element.waitFor({
13053
+ state: "visible",
13054
+ timeout
13055
+ });
13056
+ return element;
13057
+ } catch {
13058
+ task.logger.warn(`元素未找到: ${selector}`);
13059
+ return null;
13060
+ }
13061
+ };
13062
+ const retryAction = async (action, maxRetries = 3, delay = 1000)=>{
13063
+ let lastError;
13064
+ for(let i = 0; i < maxRetries; i++)try {
13065
+ return await action();
13066
+ } catch (error) {
13067
+ lastError = error;
13068
+ task.logger.warn(`重试 ${i + 1}/${maxRetries}: ${lastError.message}`);
13069
+ if (i < maxRetries - 1) await page.waitForTimeout(delay);
13070
+ }
13071
+ throw lastError;
13072
+ };
13073
+ const safeClick = async (locator)=>{
13074
+ if (!locator) return false;
13075
+ try {
13076
+ await locator.click({
13077
+ timeout: 5000
13078
+ });
13079
+ return true;
13080
+ } catch (error) {
13081
+ task.logger.warn(`点击失败: ${error}`);
13082
+ return false;
13083
+ }
13084
+ };
13085
+ const safeFill = async (locator, text)=>{
13086
+ if (!locator || !text) return false;
13087
+ try {
13088
+ await locator.clear({
13089
+ timeout: 3000
13090
+ });
13091
+ await locator.fill(text, {
13092
+ timeout: 5000
13093
+ });
13094
+ return true;
13095
+ } catch (error) {
13096
+ task.logger.warn(`填充文本失败: ${error}`);
13097
+ return false;
13098
+ }
13099
+ };
12763
13100
  try {
13101
+ task.logger.info("检查登录状态...");
12764
13102
  await page.waitForSelector("#micro", {
12765
13103
  state: "visible",
12766
13104
  timeout: 20000
12767
13105
  });
12768
- } catch (error) {
13106
+ task.logger.info("✓ 登录状态正常");
13107
+ } catch (_error) {
13108
+ task.logger.error("✗ 登录失效或页面加载异常");
12769
13109
  return {
12770
13110
  code: 414,
12771
13111
  message: "登录失效",
12772
13112
  data: page.url()
12773
13113
  };
12774
13114
  }
12775
- const images = await Promise.all([
12776
- "https://svip-8.rcouyi.com/file/draw/volc/2026/01/15/2011725723554811904.png"
12777
- ].map((url)=>{
12778
- const fileName = (0, share_namespaceObject.getFilenameFromUrl)(url);
12779
- return (0, share_namespaceObject.downloadImage)(url, external_node_path_default().join(tmpCachePath, fileName));
12780
- }));
12781
- const fileChooser = await page.waitForSelector('input[type="file"]', {
12782
- timeout: 20000
12783
- });
12784
- if (fileChooser) await fileChooser.setInputFiles(images);
12785
- const titleInstance = page.locator(".semi-input-wrapper input[placeholder='添加作品标题']");
12786
- await titleInstance.waitFor({
12787
- state: "visible",
12788
- timeout: 50000
12789
- });
12790
- await titleInstance.click();
12791
- await titleInstance.fill(params.title || "1111");
12792
- await page.waitForTimeout(1000);
12793
- const descInstance = page.locator("div[data-placeholder='添加作品描述...']");
12794
- await descInstance.click();
12795
- await descInstance.pressSequentially(params.content.replace(/#.*?\[.*?]#/g, "") || "22222");
12796
- if ("1" === params.visibleRange) await page.locator("label:has-text('好友可见')").first().click();
12797
- else if ("2" === params.visibleRange) await page.locator("label:has-text('仅自己可见')").first().click();
12798
- if (!params.isImmediatelyPublish) {
12799
- await await page.locator('label:has-text("定时发布")').first().click();
12800
- await page.waitForTimeout(500);
12801
- const releaseTimeInstance = page.locator(".semi-datepicker-input input[placeholder='日期和时间']");
12802
- await releaseTimeInstance.click();
13115
+ if (params.banners && params.banners.length > 0 && params.coverImage && params.coverImage.length > 0) {
13116
+ const imgs = [
13117
+ params.coverImage
13118
+ ].concat(params.banners);
13119
+ task.logger.info(`开始上传 ${imgs.length} 张图片`);
13120
+ await retryAction(async ()=>{
13121
+ const images = await Promise.all(imgs.map((url)=>{
13122
+ const fileName = (0, share_namespaceObject.getFilenameFromUrl)(url);
13123
+ return (0, share_namespaceObject.downloadImage)(url, external_node_path_default().join(tmpCachePath, fileName));
13124
+ }));
13125
+ const fileChooser = await page.waitForSelector('input[type="file"]', {
13126
+ timeout: 20000
13127
+ });
13128
+ if (!fileChooser) throw new Error("未找到图片上传输入框");
13129
+ await fileChooser.setInputFiles(images);
13130
+ task.logger.info(`图片上传成功: ${images.length} 张`);
13131
+ await page.waitForTimeout(2000);
13132
+ });
13133
+ }
13134
+ if (params.title) {
13135
+ task.logger.info(`填写标题: ${params.title}`);
13136
+ await retryAction(async ()=>{
13137
+ const titleInstance = await waitForElement(".semi-input-wrapper input[placeholder='添加作品标题']", 50000);
13138
+ if (!titleInstance) throw new Error("未找到标题输入框");
13139
+ await titleInstance.click();
13140
+ await safeFill(titleInstance, params.title);
13141
+ task.logger.info("标题填写完成");
13142
+ });
13143
+ }
13144
+ if (params.content) {
13145
+ task.logger.info("填写描述");
12803
13146
  await page.waitForTimeout(1000);
12804
- await releaseTimeInstance.blur();
13147
+ await retryAction(async ()=>{
13148
+ const descInstance = await waitForElement("div[data-placeholder='添加作品描述...']", 10000);
13149
+ if (!descInstance) throw new Error("未找到描述编辑器");
13150
+ await descInstance.click();
13151
+ await page.waitForTimeout(500);
13152
+ const cleanContent = params.content.replace(/#.*?\[.*?]#/g, "");
13153
+ await descInstance.pressSequentially(cleanContent, {
13154
+ delay: 10
13155
+ });
13156
+ task.logger.info("描述填写完成");
13157
+ });
12805
13158
  }
12806
- const response = await new Promise((resolve)=>{
12807
- const handleResponse = async (response)=>{
12808
- if (response.url().includes("/web/api/media/aweme/create_v2")) {
12809
- console.log("匹配到发布接口响应");
12810
- const jsonResponse = await response.json();
12811
- console.log("发布接口响应数据:", jsonResponse);
12812
- page.off("response", handleResponse);
12813
- resolve(jsonResponse?.data?.item_id);
12814
- }
12815
- };
12816
- console.log("监听响应事件");
13159
+ if (params.topic && params.topic.length > 0) {
13160
+ task.logger.info(`添加话题标签: ${params.topic.length} 个`);
13161
+ try {
13162
+ const topics = params.topic;
13163
+ await retryAction(async ()=>{
13164
+ const descInstance = page.locator(".editor-kit-container.editor.editor-comp-publish");
13165
+ for (const topic of topics)if (topic.cha_name) {
13166
+ const topicTag = `#${topic.cha_name} `;
13167
+ await descInstance.pressSequentially(topicTag, {
13168
+ delay: 10
13169
+ });
13170
+ task.logger.info(`已添加话题: ${topicTag.trim()}`);
13171
+ await page.waitForTimeout(300);
13172
+ }
13173
+ task.logger.info("✓ 话题标签添加完成");
13174
+ });
13175
+ } catch (error) {
13176
+ task.logger.warn(`添加话题标签失败: ${error}`);
13177
+ }
13178
+ }
13179
+ if (params.mix?.mix_name) {
13180
+ task.logger.info(`选择合集: ${params.mix.mix_name}`);
13181
+ const instanceCollection = page.locator("[class^='mix-sel-wrap'] .semi-select").nth(1);
13182
+ await instanceCollection.click();
13183
+ await page.waitForTimeout(2000);
13184
+ page.locator(".semi-select-option-list .semi-select-option").filter({
13185
+ hasText: params.mix.mix_name
13186
+ }).first().click({
13187
+ force: true
13188
+ });
13189
+ }
13190
+ if (params.musicId && params.musicName) {
13191
+ task.logger.info(`选择音乐: ${params.musicName} - ${params.musicAuthor || ""}`);
13192
+ try {
13193
+ await retryAction(async ()=>{
13194
+ const musicTrigger = await waitForElement("[class^='container-right-']", 10000);
13195
+ if (!musicTrigger) throw new Error("未找到音乐选择触发器");
13196
+ await musicTrigger.click();
13197
+ task.logger.info("已打开音乐选择面板");
13198
+ await page.waitForTimeout(1000);
13199
+ const searchBox = await waitForElement("[class^='music-search']", 10000);
13200
+ if (!searchBox) throw new Error("未找到音乐搜索框");
13201
+ await searchBox.click();
13202
+ await page.waitForTimeout(500);
13203
+ const searchInput = page.locator("[class^='music-search'] input");
13204
+ const searchText = params.musicAuthor ? `${params.musicName} - ${params.musicAuthor}` : params.musicName;
13205
+ await searchInput.fill(searchText || "");
13206
+ task.logger.info(`已输入搜索内容: ${searchText}`);
13207
+ await page.waitForTimeout(300);
13208
+ await searchInput.press("Enter");
13209
+ task.logger.info("已触发搜索");
13210
+ await page.waitForTimeout(4000);
13211
+ const resultContainer = page.locator("[class^='card-container-']");
13212
+ task.logger.info(`resultContainer: ${resultContainer}`);
13213
+ if (!resultContainer) throw new Error("未找到音乐搜索结果");
13214
+ const musicCards = page.locator("[class^='card-container-']");
13215
+ const matchedCard = musicCards.filter({
13216
+ hasText: params.musicName
13217
+ }).first();
13218
+ const cardCount = await matchedCard.count();
13219
+ if (0 === cardCount) {
13220
+ task.logger.warn(`未找到匹配的音乐: ${params.musicName}`);
13221
+ throw new Error(`未找到匹配的音乐: ${params.musicName}`);
13222
+ }
13223
+ task.logger.info("找到匹配的音乐,准备选择");
13224
+ await matchedCard.hover();
13225
+ task.logger.info("已 hover 到音乐卡片");
13226
+ await page.waitForTimeout(2000);
13227
+ const selectButton = matchedCard.locator(".semi-button").first();
13228
+ const buttonClicked = await safeClick(selectButton);
13229
+ if (!buttonClicked) throw new Error("点击音乐选择按钮失败");
13230
+ task.logger.info("✓ 音乐选择完成");
13231
+ await page.waitForTimeout(500);
13232
+ });
13233
+ } catch (error) {
13234
+ task.logger.warn(`选择音乐失败: ${error}`);
13235
+ }
13236
+ }
13237
+ if (params.hotSentence) {
13238
+ task.logger.info(`选择热点: ${params.hotSentence}`);
13239
+ const instance = page.locator(".semi-select-filterable").nth(1);
13240
+ await instance.click();
13241
+ await page.waitForTimeout(1000);
13242
+ await page.locator(".semi-input-wrapper input").nth(1).fill(params.hotSentence);
13243
+ await page.waitForTimeout(2000);
13244
+ page.locator(".semi-popover-content .semi-select-option").filter({
13245
+ hasText: params.hotSentence
13246
+ }).first().click({
13247
+ force: true
13248
+ });
13249
+ }
13250
+ if (params.visibleRange) {
13251
+ task.logger.info(`设置可见范围: ${params.visibleRange}`);
13252
+ if ("2" === params.visibleRange) {
13253
+ await page.locator("label:has-text('好友可见')").first().click();
13254
+ task.logger.info("已设置为好友可见");
13255
+ } else if ("1" === params.visibleRange) {
13256
+ await page.locator("label:has-text('仅自己可见')").first().click();
13257
+ task.logger.info("已设置为仅自己可见");
13258
+ }
13259
+ }
13260
+ if (!params.allowSave) {
13261
+ task.logger.info(`设置保存权限: ${params.allowSave ? "允许" : "不允许"}`);
13262
+ try {
13263
+ await page.locator("label:has-text('不允许')").first().click();
13264
+ task.logger.info("已设置为保存权限不允许");
13265
+ await page.waitForTimeout(300);
13266
+ } catch (error) {
13267
+ task.logger.warn(`设置保存权限失败: ${error}`);
13268
+ }
13269
+ }
13270
+ if (!params.isImmediatelyPublish && params.scheduledPublish) {
13271
+ task.logger.info("设置定时发布");
13272
+ try {
13273
+ await page.locator('label:has-text("定时发布")').first().click();
13274
+ task.logger.info("已选择定时发布");
13275
+ await page.waitForTimeout(500);
13276
+ const timestamp = params.scheduledPublish > 10000000000 ? params.scheduledPublish / 1000 : params.scheduledPublish;
13277
+ const publishDate = new Date(1000 * timestamp);
13278
+ const year = publishDate.getFullYear();
13279
+ const month = String(publishDate.getMonth() + 1).padStart(2, "0");
13280
+ const day = String(publishDate.getDate()).padStart(2, "0");
13281
+ const hour = String(publishDate.getHours()).padStart(2, "0");
13282
+ const minute = String(publishDate.getMinutes()).padStart(2, "0");
13283
+ const formattedTime = `${year}-${month}-${day} ${hour}:${minute}`;
13284
+ task.logger.info(`目标发布时间: ${formattedTime}`);
13285
+ const releaseTimeInstance = await waitForElement(".semi-datepicker-input input[placeholder='日期和时间']", 10000);
13286
+ if (!releaseTimeInstance) throw new Error("未找到时间输入框");
13287
+ await releaseTimeInstance.click();
13288
+ await page.waitForTimeout(500);
13289
+ await releaseTimeInstance.fill(formattedTime);
13290
+ await page.waitForTimeout(500);
13291
+ const inputValue = await releaseTimeInstance.inputValue();
13292
+ if (inputValue !== formattedTime) task.logger.warn(`时间输入验证失败,期望: ${formattedTime}, 实际: ${inputValue}`);
13293
+ else task.logger.info("定时发布设置完成");
13294
+ await releaseTimeInstance.blur();
13295
+ await page.waitForTimeout(500);
13296
+ } catch (error) {
13297
+ task.logger.warn(`定时发布设置失败: ${error}`);
13298
+ }
13299
+ }
13300
+ task.logger.info("准备发布...");
13301
+ await page.waitForTimeout(1000);
13302
+ const response = await new Promise((resolve)=>{
13303
+ const handleResponse = async (response)=>{
13304
+ if (response.url().includes("/web/api/media/aweme/create_v2")) {
13305
+ console.log("匹配到发布接口响应");
13306
+ const jsonResponse = await response.json();
13307
+ console.log("发布接口响应数据:", jsonResponse);
13308
+ page.off("response", handleResponse);
13309
+ resolve(jsonResponse?.data?.item_id);
13310
+ }
13311
+ };
13312
+ console.log("监听响应事件");
12817
13313
  page.on("response", handleResponse);
12818
13314
  console.log("点击发布按钮");
12819
- page.locator("#DCPF button:has-text('发布')").first().click();
12820
- console.log("发布按钮已点击");
12821
- });
12822
- await updateTaskState?.({
12823
- state: share_namespaceObject.TaskState.SUCCESS,
12824
- result: {
12825
- response
12826
- }
13315
+ setTimeout(()=>{
13316
+ page.locator("#DCPF button:has-text('发布')").first().click();
13317
+ console.log("发布按钮已点击");
13318
+ }, 1000);
12827
13319
  });
13320
+ console.log("发布成功了");
12828
13321
  await page.close();
12829
13322
  return (0, share_namespaceObject.success)(response);
12830
13323
  };
@@ -12844,9 +13337,12 @@ var __webpack_exports__ = {};
12844
13337
  banners: schemas_array(schemas_string()),
12845
13338
  mix: schemas_object({
12846
13339
  mix_id: schemas_string(),
12847
- mix_order: schemas_number()
13340
+ mix_order: schemas_number(),
13341
+ mix_name: schemas_string().optional()
12848
13342
  }).optional(),
12849
13343
  musicId: schemas_string().optional(),
13344
+ musicName: schemas_string().optional(),
13345
+ musicAuthor: schemas_string().optional(),
12850
13346
  musicDuration: schemas_number().optional(),
12851
13347
  challengeIds: schemas_string().optional(),
12852
13348
  hotSentence: schemas_string().optional(),
@@ -12937,43 +13433,6 @@ var __webpack_exports__ = {};
12937
13433
  });
12938
13434
  return (0, share_namespaceObject.success)(data, "获取百家号配置项成功!");
12939
13435
  };
12940
- const rid = ()=>`${Math.floor(Date.now() / 1e3).toString(16)}-${[
12941
- ...Array(8)
12942
- ].map(()=>Math.floor(16 * Math.random()).toString(16)).join("")}`;
12943
- let randomValuesFunc = null;
12944
- const byteBuffer = new Uint8Array(16);
12945
- const UUID_REGEX = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;
12946
- const hexTable = [];
12947
- for(let i = 0; i < 256; i++)hexTable.push((i + 256).toString(16).substr(1));
12948
- function initRandomGenerator() {
12949
- if (randomValuesFunc) return randomValuesFunc;
12950
- const globalCrypto = "undefined" != typeof crypto ? crypto : void 0;
12951
- const globalMsCrypto = "undefined" != typeof msCrypto ? msCrypto : void 0;
12952
- const cryptoAPI = globalCrypto?.getRandomValues?.bind(globalCrypto) || globalMsCrypto?.getRandomValues?.bind(globalMsCrypto);
12953
- if (!cryptoAPI) throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");
12954
- randomValuesFunc = cryptoAPI;
12955
- return randomValuesFunc;
12956
- }
12957
- function generateRandomBytes() {
12958
- const rng = initRandomGenerator();
12959
- return rng(byteBuffer);
12960
- }
12961
- function bytesToUuid(bytes, offset = 0) {
12962
- const uuidString = (hexTable[bytes[offset + 0]] + hexTable[bytes[offset + 1]] + hexTable[bytes[offset + 2]] + hexTable[bytes[offset + 3]] + "-" + hexTable[bytes[offset + 4]] + hexTable[bytes[offset + 5]] + "-" + hexTable[bytes[offset + 6]] + hexTable[bytes[offset + 7]] + "-" + hexTable[bytes[offset + 8]] + hexTable[bytes[offset + 9]] + "-" + hexTable[bytes[offset + 10]] + hexTable[bytes[offset + 11]] + hexTable[bytes[offset + 12]] + hexTable[bytes[offset + 13]] + hexTable[bytes[offset + 14]] + hexTable[bytes[offset + 15]]).toLowerCase();
12963
- if (!UUID_REGEX.test(uuidString)) throw new TypeError("Stringified UUID is invalid");
12964
- return uuidString;
12965
- }
12966
- function utils_uuidv4(options = {}, buffer = null, bufferOffset = 0) {
12967
- const rng = options.random || options.rng || generateRandomBytes;
12968
- const bytes = rng();
12969
- bytes[6] = 0x0f & bytes[6] | 0x40;
12970
- bytes[8] = 0x3f & bytes[8] | 0x80;
12971
- if (buffer) {
12972
- for(let i = 0; i < 16; i++)buffer[bufferOffset + i] = bytes[i];
12973
- return buffer;
12974
- }
12975
- return bytesToUuid(bytes);
12976
- }
12977
13436
  const getShipinhaoBgm = async (_task, params)=>{
12978
13437
  if (!params.extraParam) return (0, share_namespaceObject.response)(400, "缺少 extraParam 参数", {
12979
13438
  items: [],
@@ -13010,7 +13469,7 @@ var __webpack_exports__ = {};
13010
13469
  query: params.query || "",
13011
13470
  timestamp: Date.now().toString(),
13012
13471
  _log_finder_uin: "",
13013
- _log_finder_id: "v2_060000231003b20faec8c4e48d1ac4d0cf04ea30b0770cdb1c9d90e6403c4964e53c4a1e53f9@finder",
13472
+ _log_finder_id: params.extraParam.finderUserName || "",
13014
13473
  rawKeyBuff: null,
13015
13474
  pluginSessionId: null,
13016
13475
  scene: 7,
@@ -13046,7 +13505,7 @@ var __webpack_exports__ = {};
13046
13505
  const requestData = {
13047
13506
  timestamp: Date.now().toString(),
13048
13507
  _log_finder_uin: "",
13049
- _log_finder_id: "v2_060000231003b20faec8c4e48d1ac4d0cf04ea30b0770cdb1c9d90e6403c4964e53c4a1e53f9@finder",
13508
+ _log_finder_id: params.extraParam.finderUserName || "",
13050
13509
  rawKeyBuff: null,
13051
13510
  pluginSessionId: null,
13052
13511
  scene: 7,
@@ -13098,7 +13557,7 @@ var __webpack_exports__ = {};
13098
13557
  pageSize: params.pageSize ?? 20,
13099
13558
  timestamp: Date.now().toString(),
13100
13559
  _log_finder_uin: "",
13101
- _log_finder_id: "v2_060000231003b20faec8c4e48d1ac4d0cf04ea30b0770cdb1c9d90e6403c4964e53c4a1e53f9@finder",
13560
+ _log_finder_id: params.extraParam.finderUserName || "",
13102
13561
  rawKeyBuff: null,
13103
13562
  pluginSessionId: null,
13104
13563
  scene: 7,
@@ -13136,7 +13595,7 @@ var __webpack_exports__ = {};
13136
13595
  forMcn: false,
13137
13596
  timestamp: Date.now().toString(),
13138
13597
  _log_finder_uin: "",
13139
- _log_finder_id: "v2_060000231003b20faec8c4e48d1ac4d0cf04ea30b0770cdb1c9d90e6403c4964e53c4a1e53f9@finder",
13598
+ _log_finder_id: params.extraParam?.finderUserName || "",
13140
13599
  rawKeyBuff: null,
13141
13600
  pluginSessionId: null,
13142
13601
  scene: 7,
@@ -13144,7 +13603,7 @@ var __webpack_exports__ = {};
13144
13603
  };
13145
13604
  const res = await http.api({
13146
13605
  method: "post",
13147
- url: `https://channels.weixin.qq.com/micro/interaction/cgi-bin/mmfinderassistant-bin/post/post_list?${urlParams}`,
13606
+ url: `https://channels.weixin.qq.com/micro/interaction/cgi-bin/mmfinderassistant-bin/comment/comment_list?${urlParams}`,
13148
13607
  data: requestData
13149
13608
  });
13150
13609
  console.log(res, "----res");
@@ -13205,7 +13664,7 @@ var __webpack_exports__ = {};
13205
13664
  lastBuff: params.lastBuff || "",
13206
13665
  timestamp: Date.now().toString(),
13207
13666
  _log_finder_uin: "",
13208
- _log_finder_id: "v2_060000231003b20faec8c4e48d1ac4d0cf04ea30b0770cdb1c9d90e6403c4964e53c4a1e53f9@finder",
13667
+ _log_finder_id: params.extraParam?.finderUserName || "",
13209
13668
  rawKeyBuff: null,
13210
13669
  pluginSessionId: null,
13211
13670
  scene: 7,
@@ -14993,11 +15452,12 @@ var __webpack_exports__ = {};
14993
15452
  ...res
14994
15453
  });
14995
15454
  const isSuccess = 0 === res.errCode;
14996
- const message = `视频号验证链接${isSuccess ? "成功" : `失败,原因:${res.errMsg || "无法添加此链接"}`}${_task.debug ? ` ${http.proxyInfo}` : ""}`;
15455
+ const baseResp = res.data?.baseResp;
15456
+ const message = `视频号验证链接${res.data?.title ? "成功" : `失败,原因:${baseResp?.errmsg || "无法添加此链接"}`}${_task.debug ? ` ${http.proxyInfo}` : ""}`;
14997
15457
  const data = {
14998
15458
  title: res?.data?.title || "",
14999
- errMsg: res?.errMsg || "",
15000
- errCode: res?.errCode
15459
+ errMsg: baseResp?.errmsg || "",
15460
+ errCode: baseResp?.errcode
15001
15461
  };
15002
15462
  return (0, share_namespaceObject.response)(isSuccess ? 0 : 414, message, data);
15003
15463
  };
@@ -15086,19 +15546,20 @@ var __webpack_exports__ = {};
15086
15546
  const isSuccess = 0 === res.errCode;
15087
15547
  const message = `视频号获取位置${isSuccess ? "成功" : `失败,原因:${res.errMsg || res.errCode || "未知错误"}`}${_task.debug ? ` ${http.proxyInfo}` : ""}`;
15088
15548
  let locations = [];
15089
- if (isSuccess && res?.data?.list) locations = res.data.list;
15549
+ let address;
15550
+ if (isSuccess && res?.data?.list) {
15551
+ locations = res.data.list;
15552
+ address = res.data?.address;
15553
+ }
15090
15554
  const data = {
15091
15555
  locations,
15092
- total: res?.data?.total || locations.length
15556
+ total: res?.data?.total || locations.length,
15557
+ address
15093
15558
  };
15094
15559
  return (0, share_namespaceObject.response)(isSuccess ? 0 : 414, message, data);
15095
15560
  };
15096
15561
  const shipinhaoLogin_rpa_scanRetryMaxCount = 60;
15097
15562
  const shipinhaoLogin_rpa_waitQrcodeResultMaxTime = 2000 * shipinhaoLogin_rpa_scanRetryMaxCount;
15098
- const DEFAULT_VIEWPORT = {
15099
- width: 1280,
15100
- height: 720
15101
- };
15102
15563
  const shipinhaoLogin_rpa_rpaAction = async (task, params)=>{
15103
15564
  const reporter = task.reportService?.reportLoginStatus ?? (()=>Promise.resolve());
15104
15565
  let page;
@@ -15106,8 +15567,7 @@ var __webpack_exports__ = {};
15106
15567
  let isSelfClosing = false;
15107
15568
  try {
15108
15569
  page = await task.createPage({
15109
- url: "https://channels.weixin.qq.com/login.html",
15110
- viewport: params.viewport || DEFAULT_VIEWPORT
15570
+ url: "https://channels.weixin.qq.com/login.html"
15111
15571
  });
15112
15572
  if (!task._session?.id) throw new Error("Session ID 不存在");
15113
15573
  task._steelBrowser?.on("disconnected", ()=>{
@@ -15117,7 +15577,7 @@ var __webpack_exports__ = {};
15117
15577
  } catch (e) {
15118
15578
  task.logger.error("浏览器启动失败", e);
15119
15579
  return {
15120
- code: 500,
15580
+ code: 414,
15121
15581
  message: `浏览器启动失败: ${e}`,
15122
15582
  data: {}
15123
15583
  };
@@ -15659,33 +16119,257 @@ var __webpack_exports__ = {};
15659
16119
  if ("server" === params.actionType) return shipinhaoLogin_rpa_server_rpaServer(task, params);
15660
16120
  return executeAction(shipinhaoLogin_rpa_server_rpaServer)(task, params);
15661
16121
  };
15662
- function calculateBufferMd5(buffer) {
15663
- const hash = external_node_crypto_default().createHash("md5");
15664
- hash.update(buffer);
15665
- return hash.digest("hex");
15666
- }
15667
- function calculatePartialMd5(buffer) {
15668
- const MAX_SIZE = 5242880;
15669
- const slice = buffer.length > MAX_SIZE ? buffer.slice(0, MAX_SIZE) : buffer;
15670
- const hash = external_node_crypto_default().createHash("md5");
15671
- hash.update(slice);
15672
- return hash.digest("hex");
15673
- }
15674
- async function readImageFile(imagePath) {
15675
- try {
15676
- if (imagePath.startsWith("http://") || imagePath.startsWith("https://")) {
15677
- const response = await external_axios_default().get(imagePath, {
16122
+ class VideoChannelUploader {
16123
+ constructor(config = {}){
16124
+ this.uploadTaskId = "";
16125
+ this.partInfo = [];
16126
+ this.md5 = "";
16127
+ this.chunkCount = 0;
16128
+ this.uploadedChunks = 0;
16129
+ this.startTime = 0;
16130
+ this.uploadSpeed = 0;
16131
+ this.speedRecords = [];
16132
+ this.chunkSize = config.chunkSize || 8388608;
16133
+ this.concurrentLimit = config.concurrentLimit || 4;
16134
+ this.singleFileSize = config.singleFileSize || 10485760;
16135
+ }
16136
+ calculateMd5(buffer) {
16137
+ const MAX_SIZE = 5242880;
16138
+ const slice = buffer.length > MAX_SIZE ? buffer.slice(0, MAX_SIZE) : buffer;
16139
+ return external_node_crypto_default().createHash("md5").update(slice).digest("hex");
16140
+ }
16141
+ calculateChunkMd5(buffer) {
16142
+ return external_node_crypto_default().createHash("md5").update(buffer).digest("hex");
16143
+ }
16144
+ generateUUID() {
16145
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c)=>{
16146
+ const r = 16 * Math.random() | 0;
16147
+ const v = "x" === c ? r : 0x3 & r | 0x8;
16148
+ return v.toString(16);
16149
+ });
16150
+ }
16151
+ getImageSize(buffer) {
16152
+ try {
16153
+ if (0x89 === buffer[0] && 0x50 === buffer[1]) return {
16154
+ width: buffer.readUInt32BE(16),
16155
+ height: buffer.readUInt32BE(20)
16156
+ };
16157
+ if (0xff === buffer[0] && 0xd8 === buffer[1]) {
16158
+ let offset = 2;
16159
+ while(offset < buffer.length){
16160
+ if (0xff !== buffer[offset]) break;
16161
+ const marker = buffer[offset + 1];
16162
+ const size = buffer.readUInt16BE(offset + 2);
16163
+ if (0xc0 === marker || 0xc1 === marker || 0xc2 === marker) return {
16164
+ height: buffer.readUInt16BE(offset + 5),
16165
+ width: buffer.readUInt16BE(offset + 7)
16166
+ };
16167
+ offset += size + 2;
16168
+ }
16169
+ }
16170
+ if (0x47 === buffer[0] && 0x49 === buffer[1]) return {
16171
+ width: buffer.readUInt16LE(6),
16172
+ height: buffer.readUInt16LE(8)
16173
+ };
16174
+ return {
16175
+ width: 0,
16176
+ height: 0
16177
+ };
16178
+ } catch {
16179
+ return {
16180
+ width: 0,
16181
+ height: 0
16182
+ };
16183
+ }
16184
+ }
16185
+ async readFile(filePath) {
16186
+ if (filePath.startsWith("http://") || filePath.startsWith("https://")) {
16187
+ const resp = await external_axios_default().get(filePath, {
15678
16188
  responseType: "arraybuffer"
15679
16189
  });
15680
- return Buffer.from(response.data);
16190
+ return Buffer.from(resp.data);
15681
16191
  }
15682
- if (external_node_fs_default().existsSync(imagePath)) return external_node_fs_default().readFileSync(imagePath);
15683
- return null;
15684
- } catch (error) {
15685
- console.error("读取图片失败:", error);
15686
- return null;
16192
+ return external_node_fs_default().promises.readFile(filePath);
16193
+ }
16194
+ async getUploadId(fileSize, fileName, uin, authKey, taskId) {
16195
+ const blockSum = Math.ceil(fileSize / this.chunkSize);
16196
+ const blockPartLength = [];
16197
+ for(let i = 1; i <= blockSum; i++){
16198
+ const end = Math.min(i * this.chunkSize, fileSize);
16199
+ blockPartLength.push(end);
16200
+ }
16201
+ const requestBody = {
16202
+ BlockSum: blockSum,
16203
+ BlockPartLength: blockPartLength
16204
+ };
16205
+ const headers = {
16206
+ "X-Arguments": `apptype=251&filetype=20304&weixinnum=${uin}&filekey=${encodeURIComponent(fileName)}&filesize=${fileSize}&taskid=${taskId}&scene=2`,
16207
+ Authorization: authKey,
16208
+ Accept: "application/json, text/plain, */*",
16209
+ "Content-MD5": "null",
16210
+ Referer: "https://channels.weixin.qq.com/",
16211
+ Origin: "https://channels.weixin.qq.com/"
16212
+ };
16213
+ const resp = await external_axios_default().put("https://finderassistancea.video.qq.com/applyuploaddfs", requestBody, {
16214
+ headers
16215
+ });
16216
+ if (!resp.data?.UploadID) throw new Error(`获取 UploadID 失败: ${resp.data?.errMsg || "未知错误"}`);
16217
+ return resp.data.UploadID;
16218
+ }
16219
+ async uploadChunk(chunk, fileName, fileSize, uin, authKey, uploadId, partNumber, taskId, onProgress) {
16220
+ const md5Hash = this.calculateChunkMd5(chunk);
16221
+ const headers = {
16222
+ "Content-MD5": md5Hash,
16223
+ "X-Arguments": `apptype=251&filetype=20304&weixinnum=${uin}&filekey=${encodeURIComponent(fileName)}&filesize=${fileSize}&taskid=${taskId}&scene=0`,
16224
+ Authorization: authKey,
16225
+ "Content-Type": "application/octet-stream",
16226
+ Referer: "https://channels.weixin.qq.com/platform/post/create",
16227
+ Origin: "https://channels.weixin.qq.com"
16228
+ };
16229
+ const url = `https://finderassistancea.video.qq.com/uploadpartdfs?PartNumber=${partNumber}&UploadID=${encodeURIComponent(uploadId)}`;
16230
+ const resp = await external_axios_default().put(url, chunk, {
16231
+ headers,
16232
+ maxBodyLength: 1 / 0,
16233
+ maxContentLength: 1 / 0,
16234
+ onUploadProgress: (progressEvent)=>{
16235
+ if (onProgress && progressEvent.bytes) onProgress(progressEvent.bytes);
16236
+ }
16237
+ });
16238
+ if (resp.data?.errCode !== void 0 && 0 !== resp.data.errCode) throw new Error(`分片 ${partNumber} 上传失败: ${resp.data.errMsg}`);
16239
+ return resp.data.ETag;
16240
+ }
16241
+ async confirmChunks(uploadId, fileName, uin, authKey, transFlag, taskId) {
16242
+ const headers = {
16243
+ "Content-MD5": "null",
16244
+ "X-Arguments": `apptype=251&filetype=20304&weixinnum=${uin}&filekey=${encodeURIComponent(fileName)}&filesize=0&taskid=${taskId}&scene=0`,
16245
+ Authorization: authKey,
16246
+ Referer: "https://channels.weixin.qq.com/platform/post/create",
16247
+ Origin: "https://channels.weixin.qq.com"
16248
+ };
16249
+ const requestBody = {
16250
+ TransFlag: transFlag || "0_0",
16251
+ PartNumberMarker: "1"
16252
+ };
16253
+ const url = `https://finderassistancea.video.qq.com/listparts?UploadID=${encodeURIComponent(uploadId)}`;
16254
+ const resp = await external_axios_default().post(url, requestBody, {
16255
+ headers
16256
+ });
16257
+ if (resp.data?.ListPartsResult?.Part) return resp.data.ListPartsResult.Part.map((p)=>({
16258
+ PartNumber: parseInt(p.PartNumber),
16259
+ ETag: p.ETag
16260
+ }));
16261
+ return [];
16262
+ }
16263
+ async completeUpload(uploadId, fileName, fileSize, uin, authKey, transFlag, partInfo, taskId) {
16264
+ const headers = {
16265
+ "Content-MD5": "null",
16266
+ "X-Arguments": `apptype=251&filetype=20304&weixinnum=${uin}&filekey=${encodeURIComponent(fileName)}&filesize=${fileSize}&taskid=${taskId}&scene=0`,
16267
+ Authorization: authKey,
16268
+ Referer: "https://channels.weixin.qq.com/platform/post/create",
16269
+ Origin: "https://channels.weixin.qq.com"
16270
+ };
16271
+ const requestBody = {
16272
+ TransFlag: transFlag || "0_0",
16273
+ PartInfo: partInfo
16274
+ };
16275
+ const url = `https://finderassistancea.video.qq.com/completepartuploaddfs?UploadID=${encodeURIComponent(uploadId)}`;
16276
+ const resp = await external_axios_default().post(url, requestBody, {
16277
+ headers
16278
+ });
16279
+ if (!resp.data?.DownloadURL) throw new Error(`完成上传失败: ${resp.data?.errMsg || "未知错误"}`);
16280
+ return resp.data.DownloadURL;
16281
+ }
16282
+ async asyncPool(concurrency, items, fn) {
16283
+ const executing = [];
16284
+ for (const item of items){
16285
+ const p = Promise.resolve().then(()=>fn(item));
16286
+ executing.push(p);
16287
+ if (executing.length >= concurrency) await Promise.race(executing);
16288
+ }
16289
+ await Promise.all(executing);
16290
+ }
16291
+ async upload(imagePath, uin, authKey, options = {}) {
16292
+ const { onProgress, transFlag } = options;
16293
+ const fileBuffer = await this.readFile(imagePath);
16294
+ const fileSize = fileBuffer.length;
16295
+ const fileName = external_node_path_default().basename(imagePath);
16296
+ if (fileSize > 20971520) throw new Error("图片大小超过 20MB 限制");
16297
+ this.md5 = this.calculateMd5(fileBuffer);
16298
+ const { width, height } = this.getImageSize(fileBuffer);
16299
+ this.startTime = Date.now();
16300
+ this.chunkCount = Math.ceil(fileSize / this.chunkSize);
16301
+ this.uploadedChunks = 0;
16302
+ this.partInfo = new Array(this.chunkCount).fill(null);
16303
+ const taskId = this.generateUUID();
16304
+ this.generateUUID();
16305
+ console.log(`[上传开始] 文件: ${fileName}, 大小: ${fileSize}, 分片: ${this.chunkCount}`);
16306
+ this.uploadTaskId = await this.getUploadId(fileSize, fileName, uin, authKey, taskId);
16307
+ console.log(`[获取 UploadID] ${this.uploadTaskId}`);
16308
+ this.startSpeedWatch();
16309
+ if (fileSize <= this.chunkSize) {
16310
+ console.log("[直接上传] 单文件模式");
16311
+ const etag = await this.uploadChunk(fileBuffer, fileName, fileSize, uin, authKey, this.uploadTaskId, 1, taskId, (delta)=>this.updateProgress(delta, onProgress));
16312
+ this.partInfo[0] = {
16313
+ PartNumber: 1,
16314
+ ETag: etag
16315
+ };
16316
+ this.uploadedChunks = 1;
16317
+ } else {
16318
+ console.log(`[分片上传] 并发数: ${this.concurrentLimit}`);
16319
+ const chunks = Array.from({
16320
+ length: this.chunkCount
16321
+ }, (_, i)=>i);
16322
+ await this.asyncPool(this.concurrentLimit, chunks, async (index)=>{
16323
+ const start = index * this.chunkSize;
16324
+ const end = Math.min((index + 1) * this.chunkSize, fileSize);
16325
+ const chunk = fileBuffer.slice(start, end);
16326
+ console.log(`[上传分片 ${index + 1}/${this.chunkCount}] 大小: ${chunk.length}`);
16327
+ const etag = await this.uploadChunk(chunk, fileName, fileSize, uin, authKey, this.uploadTaskId, index + 1, taskId, (delta)=>this.updateProgress(delta, onProgress));
16328
+ this.partInfo[index] = {
16329
+ PartNumber: index + 1,
16330
+ ETag: etag
16331
+ };
16332
+ this.uploadedChunks++;
16333
+ onProgress?.({
16334
+ uploadedChunks: this.uploadedChunks,
16335
+ totalChunks: this.chunkCount,
16336
+ percent: Math.floor(this.uploadedChunks / this.chunkCount * 100),
16337
+ speed: this.uploadSpeed
16338
+ });
16339
+ });
16340
+ }
16341
+ console.log("[完成上传] 合并分片...");
16342
+ const downloadUrl = await this.completeUpload(this.uploadTaskId, fileName, fileSize, uin, authKey, transFlag || "0_0", this.partInfo.filter(Boolean), taskId);
16343
+ this.stopSpeedWatch();
16344
+ return {
16345
+ downloadUrl,
16346
+ width,
16347
+ height,
16348
+ fileSize,
16349
+ md5: external_node_crypto_default().createHash("md5").update(fileBuffer).digest("hex")
16350
+ };
16351
+ }
16352
+ updateProgress(delta, onProgress) {}
16353
+ startSpeedWatch() {
16354
+ let lastUploaded = 0;
16355
+ this.speedInterval = setInterval(()=>{
16356
+ const current = this.uploadedChunks * this.chunkSize;
16357
+ this.uploadSpeed = Math.floor((current - lastUploaded) / 1024);
16358
+ this.speedRecords.push(this.uploadSpeed);
16359
+ lastUploaded = current;
16360
+ }, 1000);
16361
+ }
16362
+ stopSpeedWatch() {
16363
+ if (this.speedInterval) clearInterval(this.speedInterval);
15687
16364
  }
15688
16365
  }
16366
+ function generateUUID() {
16367
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c)=>{
16368
+ const r = 16 * Math.random() | 0;
16369
+ const v = "x" === c ? r : 0x3 & r | 0x8;
16370
+ return v.toString(16);
16371
+ });
16372
+ }
15689
16373
  function mock_getTimeStamp(length) {
15690
16374
  return Date.now().toString().substring(0, length);
15691
16375
  }
@@ -15734,119 +16418,21 @@ var __webpack_exports__ = {};
15734
16418
  });
15735
16419
  return response.data;
15736
16420
  }
15737
- async function getUploadId(fileSize, fileName, _finderUsername, taskId, uin, authKey, mediaType) {
15738
- const blockSize = 8388608;
15739
- const blockSum = Math.ceil(fileSize / blockSize);
15740
- const blockPartLength = [];
15741
- if (fileSize < blockSize) blockPartLength.push(fileSize);
15742
- else for(let i = 1; i <= blockSum; i++)if (i * blockSize <= fileSize) blockPartLength.push(i * blockSize);
15743
- else {
15744
- blockPartLength.push(fileSize);
15745
- break;
15746
- }
15747
- const requestBody = {
15748
- BlockSum: blockSum,
15749
- BlockPartLength: blockPartLength
15750
- };
15751
- console.log("taskId:", taskId);
15752
- const headers = {
15753
- "X-Arguments": `apptype=251&filetype=${mediaType}&weixinnum=${uin}&filekey=${encodeURIComponent(fileName)}&filesize=${fileSize}&taskid=${taskId}&scene=2`,
15754
- Authorization: authKey,
15755
- Accept: "application/json, text/plain, */*",
15756
- "Content-MD5": "null",
15757
- Referer: "https://channels.weixin.qq.com/",
15758
- Origin: "https://channels.weixin.qq.com/"
15759
- };
15760
- try {
15761
- const response = await external_axios_default().put("https://finderassistancea.video.qq.com/applyuploaddfs", requestBody, {
15762
- headers
15763
- });
15764
- return response.data;
15765
- } catch (e) {
15766
- console.log("getUploadId error:", e);
15767
- return {
15768
- errCode: -1,
15769
- errMsg: e instanceof Error ? e.message : "未知错误"
15770
- };
15771
- }
15772
- }
15773
- async function uploadImagePart(imageBuffer, fileName, mediaType, _finderUsername, taskId, fileSize, uin, authKey, uploadId, partNumber = 1) {
15774
- const md5Hash = calculatePartialMd5(imageBuffer);
15775
- const headers = {
15776
- "Content-MD5": md5Hash,
15777
- "X-Arguments": `apptype=251&filetype=${mediaType}&weixinnum=${uin}&filekey=${encodeURIComponent(fileName)}&filesize=${fileSize}&taskid=${taskId}&scene=0`,
15778
- Authorization: authKey,
15779
- "Content-Type": "application/octet-stream",
15780
- Referer: "https://channels.weixin.qq.com/platform/post/create",
15781
- Origin: "https://channels.weixin.qq.com",
15782
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
15783
- };
15784
- const url = `https://finderassistancea.video.qq.com/uploadpartdfs?PartNumber=${partNumber}&UploadID=${encodeURIComponent(uploadId)}`;
15785
- const response = await external_axios_default().put(url, imageBuffer, {
15786
- headers
16421
+ async function uploadImageComplete(imagePath, taskId, finderUsername, uin, authKey) {
16422
+ const uploader = new VideoChannelUploader({
16423
+ chunkSize: 8388608,
16424
+ concurrentLimit: 4
15787
16425
  });
15788
- console.log("上传图片响应:", JSON.stringify(response.data));
15789
- return response.data;
15790
- }
15791
- async function getUploadedImageInfo(partInfo, _finderUsername, fileName, uploadId, fileSize, taskId, uin, authKey, mediaType) {
15792
- const headers = {
15793
- "Content-MD5": "null",
15794
- "X-Arguments": `apptype=251&filetype=${mediaType}&weixinnum=${uin}&filekey=${encodeURIComponent(fileName)}&filesize=${fileSize}&taskid=${taskId}&scene=0`,
15795
- Authorization: authKey,
15796
- Referer: "https://channels.weixin.qq.com/platform/post/create",
15797
- Origin: "https://channels.weixin.qq.com",
15798
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
15799
- };
15800
- const requestBody = {
15801
- TransFlag: "0_0",
15802
- PartInfo: partInfo
15803
- };
15804
- const url = `https://finderassistancea.video.qq.com/completepartuploaddfs?UploadID=${encodeURIComponent(uploadId)}`;
15805
- const response = await external_axios_default().post(url, requestBody, {
15806
- headers
16426
+ const result = await uploader.upload(imagePath, uin, authKey, {
16427
+ onProgress: (p)=>console.log(`上传进度: ${p.percent}%`)
15807
16428
  });
15808
- return response.data;
15809
- }
15810
- async function uploadImageComplete(imagePath, taskId, finderUsername, uin, authKey, _retryCount = 3) {
15811
- try {
15812
- const imageBuffer = await readImageFile(imagePath);
15813
- if (!imageBuffer || 0 === imageBuffer.length) return {
15814
- errMsg: `读取图片失败: ${imagePath}`
15815
- };
15816
- if (imageBuffer.length > 5242880) return {
15817
- errMsg: `图片大小超限制5MB: ${imagePath}`
15818
- };
15819
- const fileName = external_node_path_default().basename(imagePath);
15820
- const fileSize = imageBuffer.length;
15821
- const uploadIdResponse = await getUploadId(fileSize, fileName, finderUsername, taskId, uin, authKey, 20304);
15822
- console.log("申请上传ID响应SSS:", JSON.stringify(uploadIdResponse));
15823
- if (!uploadIdResponse.UploadID) return {
15824
- errMsg: `获取上传id失败: ${uploadIdResponse.errMsg}`
15825
- };
15826
- const uploadResponse = await uploadImagePart(imageBuffer, fileName, 20304, finderUsername, taskId, fileSize, uin, authKey, uploadIdResponse.UploadID);
15827
- if (!uploadResponse.ETag) return {
15828
- errMsg: `上传图片失败: ${uploadResponse.errMsg}`
15829
- };
15830
- const partInfo = [
15831
- {
15832
- PartNumber: 1,
15833
- ETag: uploadResponse.ETag
15834
- }
15835
- ];
15836
- const imageInfo = await getUploadedImageInfo(partInfo, finderUsername, fileName, uploadIdResponse.UploadID, fileSize, taskId, uin, authKey, 20304);
15837
- if (!imageInfo.DownloadURL) return {
15838
- errMsg: `获取图片信息失败: ${imageInfo.errMsg}`
15839
- };
15840
- const md5 = calculateBufferMd5(imageBuffer);
15841
- return {
15842
- DownloadURL: imageInfo.DownloadURL,
15843
- md5
15844
- };
15845
- } catch (error) {
15846
- return {
15847
- errMsg: error instanceof Error ? error.message : "上传图片失败"
15848
- };
15849
- }
16429
+ return {
16430
+ DownloadURL: result.downloadUrl,
16431
+ md5: result.md5,
16432
+ fileSize: result.fileSize,
16433
+ width: result.width,
16434
+ height: result.height
16435
+ };
15850
16436
  }
15851
16437
  function buildLocation(address) {
15852
16438
  if (!address || !address.city) return {
@@ -15918,7 +16504,7 @@ var __webpack_exports__ = {};
15918
16504
  const topicList = params.topic || [];
15919
16505
  const location1 = params.address ? buildLocation(params.address) : {};
15920
16506
  const publishData = {
15921
- clientid: utils_uuidv4(),
16507
+ clientid: generateUUID(),
15922
16508
  timestamp: mock_getTimeStamp(13),
15923
16509
  _log_finder_id: params.finderUsername,
15924
16510
  _log_finder_uin: "",
@@ -15960,7 +16546,7 @@ var __webpack_exports__ = {};
15960
16546
  }
15961
16547
  }
15962
16548
  };
15963
- if (params.scheduledPublish) publishData.effectiveTime = Math.floor(params.scheduledPublish / 1000);
16549
+ if (params.scheduledPublish) publishData.effectiveTime = params.scheduledPublish;
15964
16550
  const objectDesc = publishData.objectDesc;
15965
16551
  if (topicList.length) objectDesc.topic = {
15966
16552
  finderTopicInfo: buildTopicXml(params.content, topicList)
@@ -16000,6 +16586,7 @@ var __webpack_exports__ = {};
16000
16586
  _pageUrl: "https://channels.weixin.qq.com/micro/content/post/finderNewLifeCreate"
16001
16587
  };
16002
16588
  const queryString = new URLSearchParams(queryData).toString();
16589
+ console.log("1111111111111111", JSON.stringify(requestBody));
16003
16590
  const apiResponse = await external_axios_default().post(`${publishUrl}?${queryString}`, requestBody, {
16004
16591
  headers: {
16005
16592
  cookie: cookies,
@@ -16013,6 +16600,7 @@ var __webpack_exports__ = {};
16013
16600
  }
16014
16601
  const shipinhaoPublish_mock_mockAction = async (task, params)=>{
16015
16602
  task.logger.info("开始执行视频号发布 - Mock API 方式");
16603
+ const updateTaskState = task.taskStageStore?.update?.bind(task.taskStageStore, task.taskId || "");
16016
16604
  if (!params.extraParam.fingerPrintDeviceId || !params.extraParam.aId) return (0, share_namespaceObject.response)(400, "fingerPrintDeviceId和aId 不能为空", "");
16017
16605
  try {
16018
16606
  const cookieString = params.cookies.map((c)=>`${c.name}=${c.value}`).join("; ");
@@ -16035,7 +16623,8 @@ var __webpack_exports__ = {};
16035
16623
  if (0 !== authKeyResponse.errCode || !authKeyResponse.data?.authKey) return (0, share_namespaceObject.response)(authKeyResponse.errCode || 500, `获取上传认证参数失败: ${authKeyResponse.errMsg}`, "");
16036
16624
  const authKey = authKeyResponse.data.authKey;
16037
16625
  const uin = authKeyResponse.data.uin;
16038
- const taskId = utils_uuidv4();
16626
+ if (!uin) return (0, share_namespaceObject.response)(500, "获取用户 uin 失败", "");
16627
+ const taskId = String(generateUUID());
16039
16628
  task.logger.info(`开始上传 ${images.length} 张图片...`);
16040
16629
  const uploadedImages = [];
16041
16630
  for(let i = 0; i < images.length; i++){
@@ -16046,11 +16635,11 @@ var __webpack_exports__ = {};
16046
16635
  uploadedImages.push({
16047
16636
  url: `https://finder.video.qq.com${uploadResult.DownloadURL.split("qq.com")[1] || ""}`,
16048
16637
  md5sum: uploadResult.md5 || "",
16049
- fileSize: 0,
16638
+ fileSize: uploadResult.fileSize || 0,
16050
16639
  thumbUrl: uploadResult.DownloadURL,
16051
16640
  fullThumbUrl: uploadResult.DownloadURL,
16052
- width: 0,
16053
- height: 0,
16641
+ width: uploadResult.width || 0,
16642
+ height: uploadResult.height || 0,
16054
16643
  mediaType: 2,
16055
16644
  videoPlayLen: 0,
16056
16645
  urlCdnTaskId: ""
@@ -16075,6 +16664,7 @@ var __webpack_exports__ = {};
16075
16664
  topic: topicNames,
16076
16665
  link: params.link,
16077
16666
  address: addressInfo,
16667
+ collection: params.collection,
16078
16668
  scheduledPublish: params.scheduledPublish,
16079
16669
  music: params.music
16080
16670
  });
@@ -16083,6 +16673,12 @@ var __webpack_exports__ = {};
16083
16673
  if (0 === resultCode) {
16084
16674
  task.logger.info("发布成功");
16085
16675
  const publishId = uploadedImages[0]?.thumbUrl?.split("encfilekey=")[1]?.split("&")[0] || "";
16676
+ await updateTaskState?.({
16677
+ state: share_namespaceObject.TaskState.SUCCESS,
16678
+ result: {
16679
+ response: resultMsg
16680
+ }
16681
+ });
16086
16682
  return (0, share_namespaceObject.response)(0, "发布成功", publishId);
16087
16683
  }
16088
16684
  let errorMessage = resultMsg;
@@ -16091,6 +16687,10 @@ var __webpack_exports__ = {};
16091
16687
  else if (300330 === resultCode) errorMessage = "未登录";
16092
16688
  else if (300002 === resultCode) errorMessage = "官方平台在校验音乐/位置/定时信息时失败了,请重新编辑后发布";
16093
16689
  task.logger.error(`发布失败: ${errorMessage}`);
16690
+ await updateTaskState?.({
16691
+ state: share_namespaceObject.TaskState.FAILED,
16692
+ error: errorMessage
16693
+ });
16094
16694
  return (0, share_namespaceObject.response)(resultCode || 500, errorMessage, "");
16095
16695
  } catch (error) {
16096
16696
  const errorMsg = error instanceof Error ? error.message : "发布失败";
@@ -16132,33 +16732,6 @@ var __webpack_exports__ = {};
16132
16732
  }
16133
16733
  throw lastError;
16134
16734
  };
16135
- const safeClick = async (locator)=>{
16136
- if (!locator) return false;
16137
- try {
16138
- await locator.click({
16139
- timeout: 5000
16140
- });
16141
- return true;
16142
- } catch (error) {
16143
- task.logger.warn(`点击失败: ${error}`);
16144
- return false;
16145
- }
16146
- };
16147
- const safeFill = async (locator, text)=>{
16148
- if (!locator || !text) return false;
16149
- try {
16150
- await locator.clear({
16151
- timeout: 3000
16152
- });
16153
- await locator.fill(text, {
16154
- timeout: 5000
16155
- });
16156
- return true;
16157
- } catch (error) {
16158
- task.logger.warn(`填充文本失败: ${error}`);
16159
- return false;
16160
- }
16161
- };
16162
16735
  task.logger.info("等待页面加载...");
16163
16736
  task.logger.info("检查登录状态...");
16164
16737
  if (task.debug) {
@@ -16172,16 +16745,8 @@ var __webpack_exports__ = {};
16172
16745
  timeout: 10000
16173
16746
  });
16174
16747
  task.logger.info("✓ 登录状态正常,找到编辑器容器");
16175
- } catch (error) {
16748
+ } catch {
16176
16749
  task.logger.error("✗ 未找到编辑器,可能登录失效");
16177
- if (task.debug) {
16178
- const screenshotPath = external_node_path_default().join(tmpCachePath, `login-error-${Date.now()}.png`);
16179
- await page.screenshot({
16180
- path: screenshotPath,
16181
- fullPage: true
16182
- });
16183
- task.logger.error(`登录检查失败截图: ${screenshotPath}`);
16184
- }
16185
16750
  return {
16186
16751
  code: 414,
16187
16752
  message: "登录失效或页面加载异常",
@@ -16248,7 +16813,12 @@ var __webpack_exports__ = {};
16248
16813
  const titleInput = await waitForElement('input[placeholder*="填写标题"]', 10000);
16249
16814
  if (!titleInput) throw new Error("未找到标题输入框");
16250
16815
  await titleInput.click();
16251
- await safeFill(titleInput, params.title);
16816
+ await titleInput.clear({
16817
+ timeout: 3000
16818
+ });
16819
+ await titleInput.fill(params.title, {
16820
+ timeout: 5000
16821
+ });
16252
16822
  task.logger.info("标题填写完成");
16253
16823
  });
16254
16824
  }
@@ -16259,137 +16829,518 @@ var __webpack_exports__ = {};
16259
16829
  if (!descEditor) throw new Error("未找到描述编辑器");
16260
16830
  await descEditor.click();
16261
16831
  await page.waitForTimeout(500);
16262
- if (params.topic && params.topic.length > 0) {
16263
- const topicButton = page.locator(".quick-btns > .finder-tag-wrap.btn");
16264
- const contentWithoutTopics = params.content.replace(/#[^#]+#/g, "").trim();
16265
- if (contentWithoutTopics) {
16266
- await descEditor.pressSequentially(contentWithoutTopics, {
16267
- delay: 50
16268
- });
16269
- await page.waitForTimeout(500);
16270
- }
16271
- for(let i = 0; i < params.topic.length; i++){
16272
- const topic = params.topic[i];
16273
- task.logger.info(`添加话题: ${topic}`);
16274
- await page.waitForTimeout(300);
16275
- if (await topicButton.count() > 0) {
16276
- await topicButton.click();
16277
- await page.waitForTimeout(500);
16278
- }
16279
- await descEditor.pressSequentially(topic, {
16280
- delay: 50
16281
- });
16282
- await page.waitForTimeout(500);
16283
- }
16284
- } else await descEditor.pressSequentially(params.content, {
16285
- delay: 50
16832
+ await descEditor.evaluate((el)=>{
16833
+ el.textContent = "";
16834
+ });
16835
+ await page.waitForTimeout(300);
16836
+ task.logger.info("已清空编辑器内容");
16837
+ await descEditor.pressSequentially(params.content, {
16838
+ delay: 10
16286
16839
  });
16840
+ await page.waitForTimeout(500);
16287
16841
  task.logger.info("内容填写完成");
16288
16842
  });
16289
16843
  }
16290
- if (params.address) {
16844
+ if (params.address?.poi_id) {
16291
16845
  task.logger.info(`选择地点: ${params.address.name}`);
16292
- try {
16293
- const locationSelector = await waitForElement(".location-selector, .address-input", 5000);
16294
- if (locationSelector) {
16295
- await safeClick(locationSelector);
16296
- await page.waitForTimeout(500);
16297
- const locationInput = page.locator(".location-search input, .address-input input");
16298
- if (await locationInput.count() > 0) {
16299
- await locationInput.first().fill(params.address.name);
16300
- await page.waitForTimeout(1000);
16301
- const firstLocation = page.locator(".location-list .location-item, .d-options .d-grid-item").first();
16302
- if (await firstLocation.count() > 0) {
16303
- await firstLocation.click();
16304
- task.logger.info("地点选择完成");
16305
- }
16306
- }
16307
- }
16308
- } catch (error) {
16309
- task.logger.warn(`地点选择失败: ${error}`);
16310
- }
16846
+ const instance = page.locator(".position-display-wrap");
16847
+ await instance.click();
16848
+ await page.waitForTimeout(1000);
16849
+ await page.locator(".location-filter-wrap input").fill(params.address?.name || params.address?.address || params.address?.city_name);
16850
+ await page.waitForTimeout(2000);
16851
+ const poperInstance = page.locator(".location-filter-wrap .common-option-list-wrap .option-item");
16852
+ await poperInstance.nth(1).waitFor();
16853
+ await poperInstance.nth(1).click();
16854
+ task.logger.info("地点选择完成");
16855
+ }
16856
+ if (params.collection) {
16857
+ task.logger.info(`选择合集: ${params.collection.collectionName}`);
16858
+ const instanceCollection = page.locator(".post-album-display-wrap");
16859
+ await instanceCollection.click();
16860
+ await page.waitForTimeout(1000);
16861
+ page.locator(".post-album-wrap .option-item").filter({
16862
+ hasText: params.collection.collectionName
16863
+ }).first().click({
16864
+ force: true
16865
+ });
16866
+ }
16867
+ if (params.link) {
16868
+ const instanceLink = page.locator(".link-display-wrap");
16869
+ await instanceLink.first().click();
16870
+ task.logger.info(`添加链接: ${params.link.link}`);
16871
+ await page.waitForTimeout(500);
16872
+ const linkTypeName = 1 === params.link.urlType ? "公众号文章" : "红包封面";
16873
+ page.locator(".post-link-wrap .link-list-options .link-option-item").filter({
16874
+ hasText: linkTypeName
16875
+ }).first().click({
16876
+ force: true
16877
+ });
16878
+ await waitForElement(".link-input-wrap", 3000);
16879
+ const linkInput = page.locator('.link-input-wrap input[type="text"]');
16880
+ await linkInput.first().fill(params.link.link);
16881
+ }
16882
+ if (params.music) {
16883
+ task.logger.info(`添加背景音乐: ${params.music.name}`);
16884
+ const musicFormItem = page.locator(".post-with-link").filter({
16885
+ hasText: "音乐"
16886
+ });
16887
+ const musicDisplayWrap = musicFormItem.locator(".link-display-wrap").first();
16888
+ await musicDisplayWrap.click();
16889
+ const searchInput = musicFormItem.locator('.weui-desktop-search input[type="text"]').first();
16890
+ const searchTxt = `${params.music.name} - ${params.music.authorName}`;
16891
+ await searchInput.fill(searchTxt);
16892
+ await page.waitForTimeout(300);
16893
+ await searchInput.press("Enter");
16894
+ await page.waitForTimeout(2000);
16895
+ const bgmItemWrap = musicFormItem.locator(".bgm-item-wrap").filter({
16896
+ hasText: searchTxt
16897
+ }).first();
16898
+ await bgmItemWrap.hover();
16899
+ await page.waitForTimeout(500);
16900
+ await bgmItemWrap.locator(".selected-icon").first().click({
16901
+ force: true
16902
+ });
16311
16903
  }
16312
16904
  if (!params.isImmediatelyPublish && params.scheduledPublish) {
16313
16905
  task.logger.info("设置定时发布");
16314
- try {
16315
- const scheduledRadio = page.locator('text="定时发布"').first();
16316
- if (await scheduledRadio.count() > 0) {
16317
- await scheduledRadio.click();
16318
- await page.waitForTimeout(500);
16319
- const dateInput = page.locator(".date-picker input").first();
16320
- if (await dateInput.count() > 0) {
16321
- const publishDate = new Date(1000 * params.scheduledPublish);
16322
- const dateStr = publishDate.toISOString().slice(0, 16).replace("T", " ");
16323
- await dateInput.fill(dateStr);
16324
- task.logger.info(`定时发布时间设置为: ${dateStr}`);
16325
- }
16326
- }
16327
- } catch (error) {
16328
- task.logger.warn(`定时发布设置失败: ${error}`);
16906
+ const timingRadio = page.locator(".weui-desktop-form__check-content").filter({
16907
+ hasNotText: "不定时"
16908
+ }).first();
16909
+ await timingRadio.click();
16910
+ await page.waitForTimeout(500);
16911
+ const instance = page.locator('.weui-desktop-picker__date input[placeholder*="请选择发表时间"]');
16912
+ await instance.click();
16913
+ const dateD = utils_TimeFormatter.format(params.scheduledPublish, "d");
16914
+ const nowMonth = utils_TimeFormatter.format(Date.now(), "MM月");
16915
+ const nowMonthText = utils_TimeFormatter.format(Date.now(), "M月");
16916
+ const month = utils_TimeFormatter.format(params.scheduledPublish, "MM月");
16917
+ const monthLocator = await page.locator("weui-desktop-picker__panel__label").filter({
16918
+ hasText: month
16919
+ }).first();
16920
+ if (!monthLocator) {
16921
+ await page.locator(".weui-desktop-picker__panel__label").filter({
16922
+ hasText: nowMonth
16923
+ }).first().click();
16924
+ await page.waitForTimeout(500);
16925
+ await page.locator(".weui-desktop-picker__table-row td a").filter({
16926
+ hasText: nowMonthText
16927
+ }).first().click();
16329
16928
  }
16929
+ await page.waitForTimeout(500);
16930
+ await page.locator(".weui-desktop-picker__table-row td a").filter({
16931
+ hasText: dateD
16932
+ }).first().click();
16933
+ await page.locator(".weui-desktop-form__input-wrp input[placeholder*='请选择时间']").fill(utils_TimeFormatter.format(params.scheduledPublish, "hh:mm"));
16934
+ await page.locator("i.weui-desktop-icon__time").click();
16935
+ await page.locator(".post-time-wrap .form-item .label").filter({
16936
+ hasText: "发表时间"
16937
+ }).click();
16330
16938
  }
16331
16939
  task.logger.info("准备发布...");
16332
- await page.waitForTimeout(1000);
16333
- const publishPromise = page.waitForResponse((response)=>{
16940
+ await page.waitForTimeout(300);
16941
+ let articleId = "";
16942
+ let message = "";
16943
+ const handleResponse = async (response)=>{
16334
16944
  const url = response.url();
16335
- return url.includes("/post/post_create") || url.includes("/post/post_draft");
16336
- }, {
16337
- timeout: 60000
16945
+ if (url.includes("/post/post_create") || url.includes("/post/post_draft")) {
16946
+ const jsonResponse = await response.json();
16947
+ page.off("response", handleResponse);
16948
+ articleId = jsonResponse.object?.id || jsonResponse.data?.objectId || "";
16949
+ message = jsonResponse?.errMsg || "";
16950
+ }
16951
+ };
16952
+ page.on("response", handleResponse);
16953
+ task._timerRecord.PrePublish = Date.now();
16954
+ const publishText = "1" === params.publishType ? "发表" : "保存草稿";
16955
+ await page.locator(".form-btns .weui-desktop-btn").filter({
16956
+ hasText: publishText
16957
+ }).first().click();
16958
+ task.logger.info("已点击发布按钮,等待响应...");
16959
+ await page.close();
16960
+ return (0, share_namespaceObject.success)(articleId, message || "发布成功");
16961
+ } catch (error) {
16962
+ const errorMsg = error instanceof Error ? error.message : String(error);
16963
+ task.logger.error(`微信视频号发布失败: ${errorMsg}`);
16964
+ return (0, share_namespaceObject.response)(500, `微信视频号发布失败: ${errorMsg}`, "");
16965
+ }
16966
+ };
16967
+ const rpaAction_Server = async (task, params)=>{
16968
+ task.logger.info("开始微信视频号发布(Server 模式)");
16969
+ const defaultPage = task.steelBrowserContext?.pages()[0];
16970
+ if (defaultPage) {
16971
+ if (!defaultPage._routeRegistered) {
16972
+ defaultPage._routeRegistered = true;
16973
+ const blockedPatterns = [
16974
+ "**/apm-fe.weixin.com*",
16975
+ "**/t2.weixin.com*"
16976
+ ].map((pattern)=>new RegExp(pattern.replace(/\*\*/g, ".*").replace(/\*/g, "[^/]*")));
16977
+ await defaultPage.route("**/*", async (route)=>{
16978
+ const req = route.request();
16979
+ const url = req.url();
16980
+ const blocked = blockedPatterns.some((regex)=>regex.test(url));
16981
+ if (!blocked) return route.continue();
16982
+ if ("OPTIONS" === req.method()) {
16983
+ console.log("处理 OPTIONS 预检:", url);
16984
+ await route.fulfill({
16985
+ status: 204,
16986
+ headers: {
16987
+ "access-control-allow-origin": "*",
16988
+ "access-control-allow-methods": "GET,POST,OPTIONS,PUT,DELETE",
16989
+ "access-control-allow-headers": "*"
16990
+ },
16991
+ body: ""
16992
+ });
16993
+ return;
16994
+ }
16995
+ await route.fulfill({
16996
+ status: 204,
16997
+ body: ""
16998
+ });
16999
+ });
17000
+ }
17001
+ }
17002
+ const tmpCachePath = task.getTmpPath();
17003
+ task.logger?.info("==>进入RPA操作:任务开始,下载图片开始...");
17004
+ const updateTaskState = task.taskStageStore?.update?.bind(task.taskStageStore, task.taskId || "");
17005
+ const imagePromise = Promise.all(params.banners.map((url)=>{
17006
+ const fileName = (0, share_namespaceObject.getFilenameFromUrl)(url);
17007
+ return (0, share_namespaceObject.downloadImage)(url, external_node_path_default().join(tmpCachePath, fileName));
17008
+ }));
17009
+ let proxyUrl;
17010
+ if (params.localIP) {
17011
+ const args = [
17012
+ params.localIP,
17013
+ params.proxyLoc,
17014
+ params.accountId
17015
+ ];
17016
+ task.logger?.info(`==> 开始获取代理信息:${args}`);
17017
+ const ProxyAgentResult = await ProxyAgent({
17018
+ logger: task.logger
17019
+ }, ...args);
17020
+ task.logger?.info("==> 代理信息获取成功!");
17021
+ proxyUrl = ProxyAgentResult ? `http://${ProxyAgentResult.ip}:${ProxyAgentResult.port}` : void 0;
17022
+ }
17023
+ task.logger?.info("==>开始打开视频号页面...");
17024
+ const page = await task.createPage({
17025
+ show: task.debug,
17026
+ cookies: params.cookies,
17027
+ proxyUrl,
17028
+ url: params.url || "https://channels.weixin.qq.com/platform/post/finderNewLifeCreate",
17029
+ ...params.viewport ? {
17030
+ viewport: params.viewport
17031
+ } : {}
17032
+ });
17033
+ task.logger?.info("==>视频号页面打开成功");
17034
+ console.log(task.steelConnector?.getLive(task.sessionId || ""));
17035
+ await updateTaskState?.({
17036
+ state: share_namespaceObject.TaskState.ACTION,
17037
+ connectAddress: task.steelConnector?.getProxyUrl(task.sessionId || "", "v1/sessions/debug"),
17038
+ sessionId: task.sessionId
17039
+ });
17040
+ const clickTimeout = 10000;
17041
+ try {
17042
+ await page.waitForSelector(".post-edit-wrap", {
17043
+ state: "visible",
17044
+ timeout: 10000
16338
17045
  });
16339
- const publishButton = await waitForElement(".form-btns .weui-desktop-btn_wrp .weui-desktop-btn.weui-desktop-btn_primary", 10000);
16340
- if (publishButton) {
16341
- await publishButton.click();
16342
- task.logger.info("已点击发布按钮,等待响应...");
17046
+ task.logger?.info(" 登录状态正常,找到编辑器容器");
17047
+ } catch (error) {
17048
+ task.logger?.error("✗ 未找到编辑器,可能登录失效");
17049
+ return {
17050
+ code: 414,
17051
+ message: "登录失效或页面加载异常",
17052
+ data: page.url()
17053
+ };
17054
+ }
17055
+ const images = await imagePromise;
17056
+ task.logger?.info(`==>图片下载完成,共 ${images.length} 张,开始上传图片...`);
17057
+ const uploadSelectors = [
17058
+ '.ant-upload-btn input[type="file"]',
17059
+ '.upload input[type="file"][accept*="image"]',
17060
+ '.upload-wrap input[type="file"]',
17061
+ 'input[type="file"][accept*="image"]'
17062
+ ];
17063
+ let uploadInput = null;
17064
+ for (const selector of uploadSelectors){
17065
+ const input = page.locator(selector);
17066
+ const count = await input.count();
17067
+ if (count > 0) {
17068
+ uploadInput = input.first();
17069
+ task.logger?.info(`找到上传输入框: ${selector}`);
17070
+ break;
17071
+ }
17072
+ }
17073
+ if (!uploadInput) {
17074
+ task.logger?.warn("未找到上传输入框,等待 3 秒后重试...");
17075
+ await page.waitForTimeout(3000);
17076
+ const anyFileInput = page.locator('input[type="file"]');
17077
+ const inputCount = await anyFileInput.count();
17078
+ if (inputCount > 0) {
17079
+ uploadInput = anyFileInput.first();
17080
+ task.logger?.info(`找到文件输入框(共 ${inputCount} 个)`);
16343
17081
  } else {
16344
- task.logger.warn("未找到主发布按钮,尝试备用方案...");
16345
- const backupSelectors = [
16346
- 'button:has-text("发布")',
16347
- 'button:has-text("发表")',
16348
- 'div:has-text("发布")',
16349
- 'span:has-text("发 布")',
16350
- 'span:has-text("发布")'
16351
- ];
16352
- let clicked = false;
16353
- for (const selector of backupSelectors){
16354
- const btn = page.locator(selector).first();
16355
- if (await btn.count() > 0) {
16356
- await btn.click();
16357
- clicked = true;
16358
- task.logger.info(`使用备用按钮发布: ${selector}`);
16359
- break;
16360
- }
17082
+ if (task.debug) {
17083
+ const screenshotPath = external_node_path_default().join(tmpCachePath, `upload-error-${Date.now()}.png`);
17084
+ await page.screenshot({
17085
+ path: screenshotPath,
17086
+ fullPage: true
17087
+ });
17088
+ task.logger?.error(`未找到上传输入框,已截图保存至: ${screenshotPath}`);
16361
17089
  }
16362
- if (!clicked) return (0, share_namespaceObject.response)(500, "未找到发布按钮", "");
17090
+ throw new Error("未找到图片上传输入框");
16363
17091
  }
16364
- try {
16365
- const publishResponse = await publishPromise;
16366
- const result = await publishResponse.json();
16367
- task.logger.info("发布响应:", result);
16368
- if (0 === result.errCode || result.base_resp?.errcode === 0) {
16369
- const objectId = result.object?.id || result.data?.objectId || "";
16370
- task.logger.info(`✅ 发布成功,ID: ${objectId}`);
16371
- await page.waitForTimeout(2000);
16372
- return (0, share_namespaceObject.success)(objectId);
17092
+ }
17093
+ await uploadInput.setInputFiles(images, {
17094
+ timeout: 60000
17095
+ });
17096
+ task.logger?.info(`==>图片上传完成: ${images.length} 张`);
17097
+ await page.waitForTimeout(3000);
17098
+ if (params.title) {
17099
+ task.logger?.info(`填写标题: ${params.title}`);
17100
+ const titleInput = page.locator('input[placeholder*="填写标题"]');
17101
+ await titleInput.waitFor({
17102
+ state: "visible",
17103
+ timeout: clickTimeout
17104
+ });
17105
+ await titleInput.click({
17106
+ timeout: clickTimeout
17107
+ });
17108
+ await titleInput.clear({
17109
+ timeout: 3000
17110
+ });
17111
+ await titleInput.fill(params.title, {
17112
+ timeout: 5000
17113
+ });
17114
+ task.logger?.info("==>标题填写完成");
17115
+ }
17116
+ if (params.content) {
17117
+ task.logger?.info("填写描述和话题");
17118
+ const descEditor = page.locator(".input-editor");
17119
+ await descEditor.waitFor({
17120
+ state: "visible",
17121
+ timeout: clickTimeout
17122
+ });
17123
+ await descEditor.click({
17124
+ timeout: clickTimeout
17125
+ });
17126
+ await page.waitForTimeout(500);
17127
+ await descEditor.evaluate((el)=>{
17128
+ el.textContent = "";
17129
+ });
17130
+ await page.waitForTimeout(300);
17131
+ task.logger?.info("已清空编辑器内容");
17132
+ await descEditor.pressSequentially(params.content, {
17133
+ delay: 10
17134
+ });
17135
+ await page.waitForTimeout(500);
17136
+ task.logger?.info("==>内容填写完成");
17137
+ }
17138
+ if (params.address?.poi_id) {
17139
+ task.logger?.info(`选择地点: ${params.address.name}`);
17140
+ const positionDisplayWrap = page.locator(".position-display-wrap");
17141
+ await positionDisplayWrap.click({
17142
+ timeout: clickTimeout
17143
+ });
17144
+ await page.waitForTimeout(1000);
17145
+ await page.locator(".location-filter-wrap input").fill(params.address?.name || params.address?.address || params.address?.city_name);
17146
+ await page.waitForTimeout(2000);
17147
+ const poperInstance = page.locator(".location-filter-wrap .common-option-list-wrap .option-item");
17148
+ await poperInstance.nth(1).waitFor();
17149
+ await poperInstance.nth(1).click({
17150
+ timeout: clickTimeout
17151
+ });
17152
+ task.logger?.info("==>地点选择完成");
17153
+ }
17154
+ if (params.collection) {
17155
+ task.logger?.info(`选择合集: ${params.collection.collectionName}`);
17156
+ const instanceCollection = page.locator(".post-album-display-wrap");
17157
+ await instanceCollection.click({
17158
+ timeout: clickTimeout
17159
+ });
17160
+ await page.waitForTimeout(1000);
17161
+ await page.locator(".post-album-wrap .option-item").filter({
17162
+ hasText: params.collection.collectionName
17163
+ }).first().click({
17164
+ force: true
17165
+ });
17166
+ task.logger?.info("==>合集选择完成");
17167
+ }
17168
+ if (params.link) {
17169
+ task.logger?.info(`添加链接: ${params.link.link}`);
17170
+ const instanceLink = page.locator(".link-display-wrap");
17171
+ await instanceLink.first().click({
17172
+ timeout: clickTimeout
17173
+ });
17174
+ await page.waitForTimeout(500);
17175
+ const linkTypeName = 1 === params.link.urlType ? "公众号文章" : "红包封面";
17176
+ await page.locator(".post-link-wrap .link-list-options .link-option-item").filter({
17177
+ hasText: linkTypeName
17178
+ }).first().click({
17179
+ force: true
17180
+ });
17181
+ await page.waitForSelector(".link-input-wrap", {
17182
+ state: "visible",
17183
+ timeout: 3000
17184
+ });
17185
+ const linkInput = page.locator('.link-input-wrap input[type="text"]');
17186
+ await linkInput.first().fill(params.link.link);
17187
+ task.logger?.info("==>链接添加完成");
17188
+ }
17189
+ if (params.music) {
17190
+ task.logger?.info(`添加背景音乐: ${params.music.name}`);
17191
+ const musicFormItem = page.locator(".post-with-link").filter({
17192
+ hasText: "音乐"
17193
+ });
17194
+ const musicDisplayWrap = musicFormItem.locator(".link-display-wrap").first();
17195
+ await musicDisplayWrap.click({
17196
+ timeout: clickTimeout
17197
+ });
17198
+ const searchInput = musicFormItem.locator('.weui-desktop-search input[type="text"]').first();
17199
+ const searchTxt = `${params.music.name} - ${params.music.authorName}`;
17200
+ await searchInput.fill(searchTxt);
17201
+ await page.waitForTimeout(300);
17202
+ await searchInput.press("Enter");
17203
+ await page.waitForTimeout(2000);
17204
+ const bgmItemWrap = musicFormItem.locator(".bgm-item-wrap").filter({
17205
+ hasText: searchTxt
17206
+ }).first();
17207
+ await bgmItemWrap.hover();
17208
+ await page.waitForTimeout(500);
17209
+ await bgmItemWrap.locator(".selected-icon").first().click({
17210
+ force: true
17211
+ });
17212
+ task.logger?.info("==>背景音乐添加完成");
17213
+ }
17214
+ if (!params.isImmediatelyPublish && params.scheduledPublish) {
17215
+ task.logger?.info("设置定时发布");
17216
+ const timingRadio = page.locator(".weui-desktop-form__check-content").filter({
17217
+ hasNotText: "不定时"
17218
+ }).first();
17219
+ await timingRadio.click({
17220
+ timeout: clickTimeout
17221
+ });
17222
+ await page.waitForTimeout(500);
17223
+ const dateInput = page.locator('.weui-desktop-picker__date input[placeholder*="请选择发表时间"]');
17224
+ await dateInput.click({
17225
+ timeout: clickTimeout
17226
+ });
17227
+ const dateD = utils_TimeFormatter.format(params.scheduledPublish, "d");
17228
+ const nowMonth = utils_TimeFormatter.format(Date.now(), "MM月");
17229
+ const nowMonthText = utils_TimeFormatter.format(Date.now(), "M月");
17230
+ const month = utils_TimeFormatter.format(params.scheduledPublish, "MM月");
17231
+ const monthLocator = page.locator("weui-desktop-picker__panel__label").filter({
17232
+ hasText: month
17233
+ }).first();
17234
+ const monthCount = await monthLocator.count();
17235
+ if (0 === monthCount) {
17236
+ await page.locator(".weui-desktop-picker__panel__label").filter({
17237
+ hasText: nowMonth
17238
+ }).first().click({
17239
+ timeout: clickTimeout
17240
+ });
17241
+ await page.waitForTimeout(500);
17242
+ await page.locator(".weui-desktop-picker__table-row td a").filter({
17243
+ hasText: nowMonthText
17244
+ }).first().click({
17245
+ timeout: clickTimeout
17246
+ });
17247
+ }
17248
+ await page.waitForTimeout(500);
17249
+ await page.locator(".weui-desktop-picker__table-row td a").filter({
17250
+ hasText: dateD
17251
+ }).first().click({
17252
+ timeout: clickTimeout
17253
+ });
17254
+ await page.locator(".weui-desktop-form__input-wrp input[placeholder*='请选择时间']").fill(utils_TimeFormatter.format(params.scheduledPublish, "hh:mm"));
17255
+ await page.locator("i.weui-desktop-icon__time").click({
17256
+ timeout: clickTimeout
17257
+ });
17258
+ await page.locator(".post-time-wrap .form-item .label").filter({
17259
+ hasText: "发表时间"
17260
+ }).click({
17261
+ timeout: clickTimeout
17262
+ });
17263
+ task.logger?.info("==>定时发布设置完成");
17264
+ }
17265
+ task.logger?.info("准备发布...");
17266
+ await page.waitForTimeout(300);
17267
+ if (MockPublish) {
17268
+ const message = "视频号模拟发布成功";
17269
+ const data = "123456789";
17270
+ await updateTaskState?.({
17271
+ state: share_namespaceObject.TaskState.SUCCESS,
17272
+ result: {
17273
+ response: data
16373
17274
  }
16374
- {
16375
- const errorMsg = result.errMsg || result.base_resp?.errmsg || "发布失败";
16376
- const errorCode = result.errCode || result.base_resp?.errcode || 500;
16377
- task.logger.error(`❌ 发布失败 [${errorCode}]: ${errorMsg}`);
16378
- return (0, share_namespaceObject.response)(errorCode, errorMsg, "");
17275
+ });
17276
+ return (0, share_namespaceObject.success)(data, message);
17277
+ }
17278
+ const publishResponse = await new Promise((resolve)=>{
17279
+ const handleResponse = async (response)=>{
17280
+ const url = response.url();
17281
+ if (url.includes("/post/post_create") || url.includes("/post/post_draft")) {
17282
+ const jsonResponse = await response.json();
17283
+ page.off("response", handleResponse);
17284
+ const articleId = jsonResponse.object?.id || jsonResponse.data?.objectId || "";
17285
+ const message = jsonResponse?.errMsg || "";
17286
+ const errCode = jsonResponse.data?.baseResp?.errcode ?? jsonResponse.errCode;
17287
+ if (0 === errCode) resolve({
17288
+ success: true,
17289
+ msg: message || "发布成功",
17290
+ data: {
17291
+ id: articleId,
17292
+ objectId: articleId
17293
+ }
17294
+ });
17295
+ else {
17296
+ let errorMessage = message;
17297
+ if (-11224 === errCode) errorMessage = "视频号管理员完成实名且绑定手机号后才可以发表";
17298
+ else if (300333 === errCode || 300334 === errCode) errorMessage = "登录失效";
17299
+ else if (300330 === errCode) errorMessage = "未登录";
17300
+ else if (300002 === errCode) errorMessage = "官方平台在校验音乐/位置/定时信息时失败了,请重新编辑后发布";
17301
+ resolve({
17302
+ success: false,
17303
+ msg: errorMessage
17304
+ });
17305
+ }
16379
17306
  }
16380
- } catch (error) {
16381
- task.logger.error(`等待发布响应超时: ${error.message}`);
16382
- return (0, share_namespaceObject.response)(500, "发布超时,请检查网络或稍后重试", "");
16383
- }
16384
- } catch (error) {
16385
- const errorMsg = error instanceof Error ? error.message : String(error);
16386
- const errorStack = error instanceof Error ? error.stack : "";
16387
- task.logger.error(`微信视频号发布失败: ${errorMsg}`);
16388
- task.logger.error(errorStack || "");
16389
- return (0, share_namespaceObject.response)(500, `微信视频号发布失败: ${errorMsg}`, "");
16390
- } finally{
16391
- if (!task.debug) await page.close();
17307
+ };
17308
+ page.on("response", handleResponse);
17309
+ const publishText = "1" === params.publishType ? "发表" : "保存草稿";
17310
+ page.locator(".form-btns .weui-desktop-btn").filter({
17311
+ hasText: publishText
17312
+ }).first().click({
17313
+ timeout: clickTimeout
17314
+ });
17315
+ setTimeout(()=>{
17316
+ page.off("response", handleResponse);
17317
+ resolve({
17318
+ success: false,
17319
+ msg: "发布超时"
17320
+ });
17321
+ }, 10000);
17322
+ });
17323
+ if (!publishResponse?.success) {
17324
+ const msg = `发布失败:${publishResponse?.msg || "未知错误"}`;
17325
+ await updateTaskState?.({
17326
+ state: share_namespaceObject.TaskState.FAILED,
17327
+ error: msg
17328
+ });
17329
+ await page.close();
17330
+ return {
17331
+ code: 414,
17332
+ message: msg,
17333
+ data: ""
17334
+ };
16392
17335
  }
17336
+ await updateTaskState?.({
17337
+ state: share_namespaceObject.TaskState.SUCCESS,
17338
+ result: {
17339
+ response: publishResponse?.data?.id || ""
17340
+ }
17341
+ });
17342
+ await page.close();
17343
+ return (0, share_namespaceObject.success)(publishResponse?.data?.id || "", publishResponse?.msg || "发布成功");
16393
17344
  };
16394
17345
  const ShipinhaoPublishParamsSchema = ActionCommonParamsSchema.extend({
16395
17346
  title: schemas_string(),
@@ -16398,19 +17349,14 @@ var __webpack_exports__ = {};
16398
17349
  topic: schemas_array(schemas_string()).optional(),
16399
17350
  address: schemas_object({
16400
17351
  poi_id: schemas_string(),
16401
- name: schemas_string(),
16402
- address: schemas_string(),
17352
+ name: schemas_string().optional(),
17353
+ address: schemas_string().optional(),
16403
17354
  latitude: schemas_number(),
16404
17355
  longitude: schemas_number(),
16405
- city_name: schemas_string(),
16406
- poi_type: schemas_number(),
16407
- type: schemas_string()
17356
+ city_name: schemas_string()
16408
17357
  }).optional(),
16409
17358
  link: schemas_object({
16410
- urlType: schemas_enum([
16411
- "1",
16412
- "2"
16413
- ]),
17359
+ urlType: schemas_number(),
16414
17360
  link: schemas_string(),
16415
17361
  title: schemas_string()
16416
17362
  }).optional(),
@@ -16445,7 +17391,8 @@ var __webpack_exports__ = {};
16445
17391
  console.log("shipinhaoPublish params:", params);
16446
17392
  if ("rpa" === params.actionType) return shipinhaoPublish_rpa_rpaAction(task, params);
16447
17393
  if ("mockApi" === params.actionType) return shipinhaoPublish_mock_mockAction(task, params);
16448
- return executeAction(shipinhaoPublish_mock_mockAction, shipinhaoPublish_rpa_rpaAction)(task, params);
17394
+ if ("server" === params.actionType) return rpaAction_Server(task, params);
17395
+ return executeAction(shipinhaoPublish_mock_mockAction, rpaAction_Server)(task, params);
16449
17396
  };
16450
17397
  const toutiaoLogin_rpa_scanRetryMaxCount = 60;
16451
17398
  const toutiaoLogin_rpa_waitQrcodeResultMaxTime = 2000 * toutiaoLogin_rpa_scanRetryMaxCount;
@@ -16465,7 +17412,7 @@ var __webpack_exports__ = {};
16465
17412
  });
16466
17413
  } catch (e) {
16467
17414
  return {
16468
- code: 500,
17415
+ code: 414,
16469
17416
  message: `浏览器启动失败: ${e}`,
16470
17417
  data: {}
16471
17418
  };
@@ -17501,7 +18448,7 @@ var __webpack_exports__ = {};
17501
18448
  });
17502
18449
  } catch (e) {
17503
18450
  return {
17504
- code: 500,
18451
+ code: 414,
17505
18452
  message: `浏览器启动失败: ${e}`,
17506
18453
  data: {}
17507
18454
  };
@@ -19391,7 +20338,7 @@ var __webpack_exports__ = {};
19391
20338
  } catch (e) {
19392
20339
  task.logger.error("浏览器启动失败", e);
19393
20340
  return {
19394
- code: 500,
20341
+ code: 414,
19395
20342
  message: `浏览器启动失败: ${e}`,
19396
20343
  data: {}
19397
20344
  };
@@ -20372,7 +21319,7 @@ var __webpack_exports__ = {};
20372
21319
  await page.close();
20373
21320
  return (0, share_namespaceObject.success)(response);
20374
21321
  };
20375
- const rpaAction_Server = async (task, params)=>{
21322
+ const rpa_server_rpaAction_Server = async (task, params)=>{
20376
21323
  if (params.originalBind && params?.selfDeclaration?.type === "source-statement") return {
20377
21324
  code: 414,
20378
21325
  message: "已声明原创不可选择“来源转载”",
@@ -21255,8 +22202,8 @@ var __webpack_exports__ = {};
21255
22202
  const xiaohongshuPublish = async (task, params)=>{
21256
22203
  if ("rpa" === params.actionType) return xiaohongshuPublish_rpa_rpaAction(task, params);
21257
22204
  if ("mockApi" === params.actionType) return xiaohongshuPublish_mock_mockAction(task, params);
21258
- if ("server" === params.actionType) return rpaAction_Server(task, params);
21259
- return executeAction(xiaohongshuPublish_mock_mockAction, rpaAction_Server_Mock, rpaAction_Server)(task, params);
22205
+ if ("server" === params.actionType) return rpa_server_rpaAction_Server(task, params);
22206
+ return executeAction(xiaohongshuPublish_mock_mockAction, rpaAction_Server_Mock, rpa_server_rpaAction_Server)(task, params);
21260
22207
  };
21261
22208
  const xiaohongshuWebCommentAction_xsEncrypt = new Xhshow();
21262
22209
  const xiaohongshuWebCommentAction = async (_task, params)=>{
@@ -21976,6 +22923,9 @@ var __webpack_exports__ = {};
21976
22923
  getShipinhaoCommentList(params) {
21977
22924
  return this.bindTask(getShipinhaoCommentList, params);
21978
22925
  }
22926
+ createShipinhaoComment(params) {
22927
+ return this.bindTask(createShipinhaoComment, params);
22928
+ }
21979
22929
  getXhsCollection(params) {
21980
22930
  return this.bindTask(getXhsCollection, params);
21981
22931
  }
@@ -22042,6 +22992,18 @@ var __webpack_exports__ = {};
22042
22992
  douyinGetCollection(params) {
22043
22993
  return this.bindTask(douyinGetCollection, params);
22044
22994
  }
22995
+ douyinGetCommentList(params) {
22996
+ return this.bindTask(douyinGetCommentList, params);
22997
+ }
22998
+ douyinGetCommentReplyList(params) {
22999
+ return this.bindTask(douyinGetCommentReplyList, params);
23000
+ }
23001
+ douyinCreateCommentReply(params) {
23002
+ return this.bindTask(douyinCreateCommentReply, params);
23003
+ }
23004
+ douyinGetWorkList(params) {
23005
+ return this.bindTask(douyinGetWorkList, params);
23006
+ }
22045
23007
  douyinLogin(params) {
22046
23008
  return this.bindTask(douyinLogin, params);
22047
23009
  }