@iflyrpa/actions 2.0.0-beta.8 → 2.0.1

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
  });
@@ -5004,7 +5004,9 @@ var __webpack_exports__ = {};
5004
5004
  });
5005
5005
  const package_json_namespaceObject = require("@iflyrpa/share/package.json");
5006
5006
  var package_json_default = /*#__PURE__*/ __webpack_require__.n(package_json_namespaceObject);
5007
- var package_namespaceObject = JSON.parse('{"i8":"2.0.0-beta.7"}');
5007
+ var package_namespaceObject = {
5008
+ i8: "2.0.0"
5009
+ };
5008
5010
  const share_namespaceObject = require("@iflyrpa/share");
5009
5011
  const external_node_fs_namespaceObject = require("node:fs");
5010
5012
  var external_node_fs_default = /*#__PURE__*/ __webpack_require__.n(external_node_fs_namespaceObject);
@@ -9134,7 +9136,7 @@ var __webpack_exports__ = {};
9134
9136
  message,
9135
9137
  data: null
9136
9138
  });
9137
- const MockPublish = true;
9139
+ const MockPublish = false;
9138
9140
  const rpa_server_scanRetryMaxCount = 60;
9139
9141
  const rpa_server_waitQrcodeResultMaxTime = 2000 * rpa_server_scanRetryMaxCount;
9140
9142
  const rpaServer = async (task, params)=>{
@@ -11198,8 +11200,7 @@ var __webpack_exports__ = {};
11198
11200
  const http = new Http({
11199
11201
  headers: {
11200
11202
  cookie: params.cookies.map((it)=>`${it.name}=${it.value}`).join(";"),
11201
- referer: "https://creator.douyin.com/",
11202
- "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
11203
+ referer: "https://creator.douyin.com/"
11203
11204
  }
11204
11205
  });
11205
11206
  const res = await http.api({
@@ -11256,40 +11257,9 @@ var __webpack_exports__ = {};
11256
11257
  const rid = ()=>`${Math.floor(Date.now() / 1e3).toString(16)}-${[
11257
11258
  ...Array(8)
11258
11259
  ].map(()=>Math.floor(16 * Math.random()).toString(16)).join("")}`;
11259
- let randomValuesFunc = null;
11260
- const byteBuffer = new Uint8Array(16);
11261
- 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;
11260
+ new Uint8Array(16);
11262
11261
  const hexTable = [];
11263
11262
  for(let i = 0; i < 256; i++)hexTable.push((i + 256).toString(16).substr(1));
11264
- function initRandomGenerator() {
11265
- if (randomValuesFunc) return randomValuesFunc;
11266
- const globalCrypto = "undefined" != typeof crypto ? crypto : void 0;
11267
- const globalMsCrypto = "undefined" != typeof msCrypto ? msCrypto : void 0;
11268
- const cryptoAPI = globalCrypto?.getRandomValues?.bind(globalCrypto) || globalMsCrypto?.getRandomValues?.bind(globalMsCrypto);
11269
- if (!cryptoAPI) throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");
11270
- randomValuesFunc = cryptoAPI;
11271
- return randomValuesFunc;
11272
- }
11273
- function generateRandomBytes() {
11274
- const rng = initRandomGenerator();
11275
- return rng(byteBuffer);
11276
- }
11277
- function bytesToUuid(bytes, offset = 0) {
11278
- 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();
11279
- if (!UUID_REGEX.test(uuidString)) throw new TypeError("Stringified UUID is invalid");
11280
- return uuidString;
11281
- }
11282
- function utils_uuidv4(options = {}, buffer = null, bufferOffset = 0) {
11283
- const rng = options.random || options.rng || generateRandomBytes;
11284
- const bytes = rng();
11285
- bytes[6] = 0x0f & bytes[6] | 0x40;
11286
- bytes[8] = 0x3f & bytes[8] | 0x80;
11287
- if (buffer) {
11288
- for(let i = 0; i < 16; i++)buffer[bufferOffset + i] = bytes[i];
11289
- return buffer;
11290
- }
11291
- return bytesToUuid(bytes);
11292
- }
11293
11263
  const createShipinhaoComment = async (_task, params)=>{
11294
11264
  if (!params.content || "" === params.content.trim()) return (0, share_namespaceObject.response)(400, "评论内容不能为空", void 0);
11295
11265
  if (!params.exportId) return (0, share_namespaceObject.response)(400, "exportId 不能为空", void 0);
@@ -12813,7 +12783,7 @@ var __webpack_exports__ = {};
12813
12783
  const batch = imageUrls.slice(i, i + this.CONCURRENT_LIMIT);
12814
12784
  const batchIndex = Math.floor(i / this.CONCURRENT_LIMIT) + 1;
12815
12785
  const totalBatches = Math.ceil(total / this.CONCURRENT_LIMIT);
12816
- console.log(`\n--- 批次 ${batchIndex}/${totalBatches} (${batch.length} 张) ---`);
12786
+ console.log(`\n--- 批次 ${batchIndex}/${totalBatches} (${batch?.length} 张) ---`);
12817
12787
  const batchPromises = batch.map((url, idx)=>{
12818
12788
  const globalIndex = i + idx;
12819
12789
  return this.processSingleImage(url, globalIndex, total);
@@ -12858,11 +12828,15 @@ var __webpack_exports__ = {};
12858
12828
  const { generateCsrfTokenAdvanced: mock_generateCsrfTokenAdvanced } = __webpack_require__("./src/utils/douyin/csrfToken.js");
12859
12829
  const mock_mockAction = async (task, params)=>{
12860
12830
  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 参数缺失或不完整", "");
12831
+ const userAgent = params.userAgent || "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36";
12861
12832
  const tmpCachePath = task.getTmpPath();
12862
12833
  let bdTicketGuardClientDataV2 = params.cookies.find((e)=>"bd_ticket_guard_client_data" === e.name)?.value || "";
12863
12834
  if (!bdTicketGuardClientDataV2) return (0, share_namespaceObject.response)(400, "bdTicketGuardClientDataV2 不能为空", "");
12864
12835
  bdTicketGuardClientDataV2 = decodeURIComponent(bdTicketGuardClientDataV2);
12865
12836
  console.log("原始 bdTicketGuardClientDataV2:", bdTicketGuardClientDataV2);
12837
+ task.logger.warn("原始 bdTicketGuardClientDataV2", {
12838
+ bdTicketGuardClientDataV2
12839
+ });
12866
12840
  try {
12867
12841
  bdTicketGuardClientDataV2 = atob(bdTicketGuardClientDataV2);
12868
12842
  console.log("解码后 bdTicketGuardClientDataV2:", bdTicketGuardClientDataV2);
@@ -12870,6 +12844,9 @@ var __webpack_exports__ = {};
12870
12844
  console.error("bdTicketGuardClientDataV2 解码失败:", error);
12871
12845
  return (0, share_namespaceObject.response)(500, "bdTicketGuardClientDataV2 解码失败", "");
12872
12846
  }
12847
+ task.logger.warn("解码后 bdTicketGuardClientDataV2:", {
12848
+ bdTicketGuardClientDataV2
12849
+ });
12873
12850
  let ree_public_key = "";
12874
12851
  let ts_sign = "";
12875
12852
  try {
@@ -12881,16 +12858,23 @@ var __webpack_exports__ = {};
12881
12858
  const publicKey = JSON.parse(params.extraParam["security-sdk/s_sdk_pub_key"] || "{}").data;
12882
12859
  const signData = JSON.parse(JSON.parse(params.extraParam["security-sdk/s_sdk_sign_data_key/web_protect"] || "{}").data || "{}");
12883
12860
  console.log("privateKey:", privateKey);
12861
+ task.logger.warn("privateKey", {
12862
+ privateKey
12863
+ });
12884
12864
  console.log("publicKey:", publicKey);
12885
- console.log("signData:", signData);
12865
+ task.logger.warn("signData", {
12866
+ signData
12867
+ });
12886
12868
  let bdTicketGuardClientData = {
12887
12869
  ts_sign,
12888
12870
  req_content: "ticket,path,timestamp",
12889
12871
  timestamp: Math.floor(Date.now() / 1000),
12890
12872
  req_sign: generateReqSignFromTicket(signData.ticket, privateKey)
12891
12873
  };
12892
- console.log("bdTicketGuardClientData:", bdTicketGuardClientData);
12893
12874
  bdTicketGuardClientData = btoa(JSON.stringify(bdTicketGuardClientData));
12875
+ task.logger.warn("bdTicketGuardClientData", {
12876
+ bdTicketGuardClientData
12877
+ });
12894
12878
  const sessionidCookie = params.cookies.find((it)=>"msToken" === it.name)?.value;
12895
12879
  if (!sessionidCookie) return {
12896
12880
  code: 414,
@@ -12901,7 +12885,7 @@ var __webpack_exports__ = {};
12901
12885
  cookie: params.cookies.map((it)=>`${it.name}=${it.value}`).join(";"),
12902
12886
  origin: "https://creator.douyin.com",
12903
12887
  referer: "https://creator.douyin.com/",
12904
- "user-agent": params.userAgent || ""
12888
+ "user-agent": userAgent
12905
12889
  };
12906
12890
  const publishParams = {
12907
12891
  read_aid: "2906",
@@ -12912,13 +12896,16 @@ var __webpack_exports__ = {};
12912
12896
  browser_language: "zh-CN",
12913
12897
  browser_platform: "Win32",
12914
12898
  browser_name: "Mozilla",
12915
- browser_version: params.userAgent || "",
12899
+ browser_version: userAgent,
12916
12900
  browser_online: "true",
12917
12901
  timezone_name: "Asia/Shanghai",
12918
12902
  support_h265: "1",
12919
12903
  msToken: params.cookies.find((e)=>"msToken" === e.name)?.value || "",
12920
12904
  a_bogus: ""
12921
12905
  };
12906
+ task.logger.warn("publishParams", {
12907
+ publishParams
12908
+ });
12922
12909
  const publishData = {
12923
12910
  item: {
12924
12911
  common: {
@@ -12948,7 +12935,10 @@ var __webpack_exports__ = {};
12948
12935
  }
12949
12936
  }
12950
12937
  };
12951
- const aBogus = mock_sign_reply(publishParams, params.userAgent);
12938
+ const aBogus = mock_sign_reply(publishParams, userAgent);
12939
+ task.logger.warn("aBogusaBogusaBogus", {
12940
+ aBogus
12941
+ });
12952
12942
  publishParams.a_bogus = aBogus;
12953
12943
  const queryString = new URLSearchParams(publishParams).toString();
12954
12944
  const args = [
@@ -12964,6 +12954,9 @@ var __webpack_exports__ = {};
12964
12954
  headers
12965
12955
  });
12966
12956
  const proxyHttp = new Http(...args);
12957
+ task.logger.warn("queryString", {
12958
+ queryString
12959
+ });
12967
12960
  const uploader = new DouyinImageUploader(proxyHttp, headers, queryString, tmpCachePath);
12968
12961
  if (params.coverImage) {
12969
12962
  const coverUri = await uploader.uploadCover(params.coverImage);
@@ -12981,6 +12974,9 @@ var __webpack_exports__ = {};
12981
12974
  }
12982
12975
  proxyHttp.addResponseInterceptor((response)=>{
12983
12976
  console.log("拦截器收到响应:", JSON.stringify(response.data));
12977
+ task.logger.warn("拦截器收到响应", {
12978
+ data: JSON.stringify(response.data)
12979
+ });
12984
12980
  if (!response || !response.data) return;
12985
12981
  const responseData = response.data;
12986
12982
  if (response && responseData?.status_code && 0 !== responseData.status_code) return {
@@ -12994,7 +12990,7 @@ var __webpack_exports__ = {};
12994
12990
  const publishQuery = {
12995
12991
  ...publishParams
12996
12992
  };
12997
- publishQuery.a_bogus = mock_sign_reply(publishQuery, params.userAgent);
12993
+ publishQuery.a_bogus = mock_sign_reply(publishQuery, userAgent);
12998
12994
  const publishQueryParams = new URLSearchParams(publishQuery).toString();
12999
12995
  function generateRandomString(length) {
13000
12996
  const characters = "abcdefghijklmnopqrstuvwxyz0123456789";
@@ -13010,9 +13006,12 @@ var __webpack_exports__ = {};
13010
13006
  cookies: params.cookies,
13011
13007
  url: "https://creator.douyin.com/web/api/media/aweme/create_v2/",
13012
13008
  method: "POST",
13013
- userAgent: headers["user-agent"]
13009
+ userAgent
13014
13010
  });
13015
13011
  console.log("发布数据", JSON.stringify(publishData));
13012
+ task.logger.warn("发布数据", {
13013
+ data: JSON.stringify(publishData)
13014
+ });
13016
13015
  const publishResult = await proxyHttp.api({
13017
13016
  method: "post",
13018
13017
  url: `https://creator.douyin.com/web/api/media/aweme/create_v2/?${publishQueryParams}`,
@@ -13028,15 +13027,16 @@ var __webpack_exports__ = {};
13028
13027
  "Bd-ticket-guard-version": "2",
13029
13028
  "Bd-ticket-guard-web-sign-type": "1",
13030
13029
  "Bd-ticket-guard-web-version": "2",
13031
- "X-secsdk-csrf-token": csrfToken,
13032
- "X-tt-session-dtrait": params.cookies.find((e)=>"x-tt-session-dtrait" === e.name)?.value || ""
13030
+ "X-secsdk-csrf-token": csrfToken
13033
13031
  }
13034
13032
  }, {
13035
13033
  retries: 2,
13036
13034
  retryDelay: 500,
13037
13035
  timeout: 12000
13038
13036
  });
13039
- console.log("publishResult", publishResult);
13037
+ console.log("publishResult", JSON.stringify(publishResult));
13038
+ task.logger.warn("发布数据");
13039
+ task.logger.warn(JSON.stringify(publishData));
13040
13040
  const isSuccess = 0 === publishResult.status_code;
13041
13041
  const message = `图文发布${isSuccess ? "成功" : `失败,原因:${publishResult.status_msg}`}${task.debug ? ` ${http.proxyInfo}` : ""}`;
13042
13042
  const data = isSuccess ? publishResult.item_id || "" : "";
@@ -13135,7 +13135,7 @@ var __webpack_exports__ = {};
13135
13135
  timeout: 20000
13136
13136
  });
13137
13137
  task.logger.info("✓ 登录状态正常");
13138
- } catch (error) {
13138
+ } catch (_error) {
13139
13139
  task.logger.error("✗ 登录失效或页面加载异常");
13140
13140
  return {
13141
13141
  code: 414,
@@ -13207,11 +13207,11 @@ var __webpack_exports__ = {};
13207
13207
  task.logger.warn(`添加话题标签失败: ${error}`);
13208
13208
  }
13209
13209
  }
13210
- if (params.mix && params.mix.mix_name) {
13210
+ if (params.mix?.mix_name) {
13211
13211
  task.logger.info(`选择合集: ${params.mix.mix_name}`);
13212
13212
  const instanceCollection = page.locator("[class^='mix-sel-wrap'] .semi-select").nth(1);
13213
13213
  await instanceCollection.click();
13214
- await page.waitForTimeout(1000);
13214
+ await page.waitForTimeout(2000);
13215
13215
  page.locator(".semi-select-option-list .semi-select-option").filter({
13216
13216
  hasText: params.mix.mix_name
13217
13217
  }).first().click({
@@ -13254,7 +13254,7 @@ var __webpack_exports__ = {};
13254
13254
  task.logger.info("找到匹配的音乐,准备选择");
13255
13255
  await matchedCard.hover();
13256
13256
  task.logger.info("已 hover 到音乐卡片");
13257
- await page.waitForTimeout(1000);
13257
+ await page.waitForTimeout(2000);
13258
13258
  const selectButton = matchedCard.locator(".semi-button").first();
13259
13259
  const buttonClicked = await safeClick(selectButton);
13260
13260
  if (!buttonClicked) throw new Error("点击音乐选择按钮失败");
@@ -13343,8 +13343,10 @@ var __webpack_exports__ = {};
13343
13343
  console.log("监听响应事件");
13344
13344
  page.on("response", handleResponse);
13345
13345
  console.log("点击发布按钮");
13346
- page.locator("#DCPF button:has-text('发布')").first().click();
13347
- console.log("发布按钮已点击");
13346
+ setTimeout(()=>{
13347
+ page.locator("#DCPF button:has-text('发布')").first().click();
13348
+ console.log("发布按钮已点击");
13349
+ }, 1000);
13348
13350
  });
13349
13351
  console.log("发布成功了");
13350
13352
  await page.close();
@@ -16148,33 +16150,257 @@ var __webpack_exports__ = {};
16148
16150
  if ("server" === params.actionType) return shipinhaoLogin_rpa_server_rpaServer(task, params);
16149
16151
  return executeAction(shipinhaoLogin_rpa_server_rpaServer)(task, params);
16150
16152
  };
16151
- function calculateBufferMd5(buffer) {
16152
- const hash = external_node_crypto_default().createHash("md5");
16153
- hash.update(buffer);
16154
- return hash.digest("hex");
16155
- }
16156
- function calculatePartialMd5(buffer) {
16157
- const MAX_SIZE = 5242880;
16158
- const slice = buffer.length > MAX_SIZE ? buffer.slice(0, MAX_SIZE) : buffer;
16159
- const hash = external_node_crypto_default().createHash("md5");
16160
- hash.update(slice);
16161
- return hash.digest("hex");
16162
- }
16163
- async function readImageFile(imagePath) {
16164
- try {
16165
- if (imagePath.startsWith("http://") || imagePath.startsWith("https://")) {
16166
- const response = await external_axios_default().get(imagePath, {
16153
+ class VideoChannelUploader {
16154
+ constructor(config = {}){
16155
+ this.uploadTaskId = "";
16156
+ this.partInfo = [];
16157
+ this.md5 = "";
16158
+ this.chunkCount = 0;
16159
+ this.uploadedChunks = 0;
16160
+ this.startTime = 0;
16161
+ this.uploadSpeed = 0;
16162
+ this.speedRecords = [];
16163
+ this.chunkSize = config.chunkSize || 8388608;
16164
+ this.concurrentLimit = config.concurrentLimit || 4;
16165
+ this.singleFileSize = config.singleFileSize || 10485760;
16166
+ }
16167
+ calculateMd5(buffer) {
16168
+ const MAX_SIZE = 5242880;
16169
+ const slice = buffer.length > MAX_SIZE ? buffer.slice(0, MAX_SIZE) : buffer;
16170
+ return external_node_crypto_default().createHash("md5").update(slice).digest("hex");
16171
+ }
16172
+ calculateChunkMd5(buffer) {
16173
+ return external_node_crypto_default().createHash("md5").update(buffer).digest("hex");
16174
+ }
16175
+ generateUUID() {
16176
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c)=>{
16177
+ const r = 16 * Math.random() | 0;
16178
+ const v = "x" === c ? r : 0x3 & r | 0x8;
16179
+ return v.toString(16);
16180
+ });
16181
+ }
16182
+ getImageSize(buffer) {
16183
+ try {
16184
+ if (0x89 === buffer[0] && 0x50 === buffer[1]) return {
16185
+ width: buffer.readUInt32BE(16),
16186
+ height: buffer.readUInt32BE(20)
16187
+ };
16188
+ if (0xff === buffer[0] && 0xd8 === buffer[1]) {
16189
+ let offset = 2;
16190
+ while(offset < buffer.length){
16191
+ if (0xff !== buffer[offset]) break;
16192
+ const marker = buffer[offset + 1];
16193
+ const size = buffer.readUInt16BE(offset + 2);
16194
+ if (0xc0 === marker || 0xc1 === marker || 0xc2 === marker) return {
16195
+ height: buffer.readUInt16BE(offset + 5),
16196
+ width: buffer.readUInt16BE(offset + 7)
16197
+ };
16198
+ offset += size + 2;
16199
+ }
16200
+ }
16201
+ if (0x47 === buffer[0] && 0x49 === buffer[1]) return {
16202
+ width: buffer.readUInt16LE(6),
16203
+ height: buffer.readUInt16LE(8)
16204
+ };
16205
+ return {
16206
+ width: 0,
16207
+ height: 0
16208
+ };
16209
+ } catch {
16210
+ return {
16211
+ width: 0,
16212
+ height: 0
16213
+ };
16214
+ }
16215
+ }
16216
+ async readFile(filePath) {
16217
+ if (filePath.startsWith("http://") || filePath.startsWith("https://")) {
16218
+ const resp = await external_axios_default().get(filePath, {
16167
16219
  responseType: "arraybuffer"
16168
16220
  });
16169
- return Buffer.from(response.data);
16221
+ return Buffer.from(resp.data);
16170
16222
  }
16171
- if (external_node_fs_default().existsSync(imagePath)) return external_node_fs_default().readFileSync(imagePath);
16172
- return null;
16173
- } catch (error) {
16174
- console.error("读取图片失败:", error);
16175
- return null;
16223
+ return external_node_fs_default().promises.readFile(filePath);
16224
+ }
16225
+ async getUploadId(fileSize, fileName, uin, authKey, taskId) {
16226
+ const blockSum = Math.ceil(fileSize / this.chunkSize);
16227
+ const blockPartLength = [];
16228
+ for(let i = 1; i <= blockSum; i++){
16229
+ const end = Math.min(i * this.chunkSize, fileSize);
16230
+ blockPartLength.push(end);
16231
+ }
16232
+ const requestBody = {
16233
+ BlockSum: blockSum,
16234
+ BlockPartLength: blockPartLength
16235
+ };
16236
+ const headers = {
16237
+ "X-Arguments": `apptype=251&filetype=20304&weixinnum=${uin}&filekey=${encodeURIComponent(fileName)}&filesize=${fileSize}&taskid=${taskId}&scene=2`,
16238
+ Authorization: authKey,
16239
+ Accept: "application/json, text/plain, */*",
16240
+ "Content-MD5": "null",
16241
+ Referer: "https://channels.weixin.qq.com/",
16242
+ Origin: "https://channels.weixin.qq.com/"
16243
+ };
16244
+ const resp = await external_axios_default().put("https://finderassistancea.video.qq.com/applyuploaddfs", requestBody, {
16245
+ headers
16246
+ });
16247
+ if (!resp.data?.UploadID) throw new Error(`获取 UploadID 失败: ${resp.data?.errMsg || "未知错误"}`);
16248
+ return resp.data.UploadID;
16249
+ }
16250
+ async uploadChunk(chunk, fileName, fileSize, uin, authKey, uploadId, partNumber, taskId, onProgress) {
16251
+ const md5Hash = this.calculateChunkMd5(chunk);
16252
+ const headers = {
16253
+ "Content-MD5": md5Hash,
16254
+ "X-Arguments": `apptype=251&filetype=20304&weixinnum=${uin}&filekey=${encodeURIComponent(fileName)}&filesize=${fileSize}&taskid=${taskId}&scene=0`,
16255
+ Authorization: authKey,
16256
+ "Content-Type": "application/octet-stream",
16257
+ Referer: "https://channels.weixin.qq.com/platform/post/create",
16258
+ Origin: "https://channels.weixin.qq.com"
16259
+ };
16260
+ const url = `https://finderassistancea.video.qq.com/uploadpartdfs?PartNumber=${partNumber}&UploadID=${encodeURIComponent(uploadId)}`;
16261
+ const resp = await external_axios_default().put(url, chunk, {
16262
+ headers,
16263
+ maxBodyLength: 1 / 0,
16264
+ maxContentLength: 1 / 0,
16265
+ onUploadProgress: (progressEvent)=>{
16266
+ if (onProgress && progressEvent.bytes) onProgress(progressEvent.bytes);
16267
+ }
16268
+ });
16269
+ if (resp.data?.errCode !== void 0 && 0 !== resp.data.errCode) throw new Error(`分片 ${partNumber} 上传失败: ${resp.data.errMsg}`);
16270
+ return resp.data.ETag;
16271
+ }
16272
+ async confirmChunks(uploadId, fileName, uin, authKey, transFlag, taskId) {
16273
+ const headers = {
16274
+ "Content-MD5": "null",
16275
+ "X-Arguments": `apptype=251&filetype=20304&weixinnum=${uin}&filekey=${encodeURIComponent(fileName)}&filesize=0&taskid=${taskId}&scene=0`,
16276
+ Authorization: authKey,
16277
+ Referer: "https://channels.weixin.qq.com/platform/post/create",
16278
+ Origin: "https://channels.weixin.qq.com"
16279
+ };
16280
+ const requestBody = {
16281
+ TransFlag: transFlag || "0_0",
16282
+ PartNumberMarker: "1"
16283
+ };
16284
+ const url = `https://finderassistancea.video.qq.com/listparts?UploadID=${encodeURIComponent(uploadId)}`;
16285
+ const resp = await external_axios_default().post(url, requestBody, {
16286
+ headers
16287
+ });
16288
+ if (resp.data?.ListPartsResult?.Part) return resp.data.ListPartsResult.Part.map((p)=>({
16289
+ PartNumber: parseInt(p.PartNumber),
16290
+ ETag: p.ETag
16291
+ }));
16292
+ return [];
16293
+ }
16294
+ async completeUpload(uploadId, fileName, fileSize, uin, authKey, transFlag, partInfo, taskId) {
16295
+ const headers = {
16296
+ "Content-MD5": "null",
16297
+ "X-Arguments": `apptype=251&filetype=20304&weixinnum=${uin}&filekey=${encodeURIComponent(fileName)}&filesize=${fileSize}&taskid=${taskId}&scene=0`,
16298
+ Authorization: authKey,
16299
+ Referer: "https://channels.weixin.qq.com/platform/post/create",
16300
+ Origin: "https://channels.weixin.qq.com"
16301
+ };
16302
+ const requestBody = {
16303
+ TransFlag: transFlag || "0_0",
16304
+ PartInfo: partInfo
16305
+ };
16306
+ const url = `https://finderassistancea.video.qq.com/completepartuploaddfs?UploadID=${encodeURIComponent(uploadId)}`;
16307
+ const resp = await external_axios_default().post(url, requestBody, {
16308
+ headers
16309
+ });
16310
+ if (!resp.data?.DownloadURL) throw new Error(`完成上传失败: ${resp.data?.errMsg || "未知错误"}`);
16311
+ return resp.data.DownloadURL;
16312
+ }
16313
+ async asyncPool(concurrency, items, fn) {
16314
+ const executing = [];
16315
+ for (const item of items){
16316
+ const p = Promise.resolve().then(()=>fn(item));
16317
+ executing.push(p);
16318
+ if (executing.length >= concurrency) await Promise.race(executing);
16319
+ }
16320
+ await Promise.all(executing);
16321
+ }
16322
+ async upload(imagePath, uin, authKey, options = {}) {
16323
+ const { onProgress, transFlag } = options;
16324
+ const fileBuffer = await this.readFile(imagePath);
16325
+ const fileSize = fileBuffer.length;
16326
+ const fileName = external_node_path_default().basename(imagePath);
16327
+ if (fileSize > 20971520) throw new Error("图片大小超过 20MB 限制");
16328
+ this.md5 = this.calculateMd5(fileBuffer);
16329
+ const { width, height } = this.getImageSize(fileBuffer);
16330
+ this.startTime = Date.now();
16331
+ this.chunkCount = Math.ceil(fileSize / this.chunkSize);
16332
+ this.uploadedChunks = 0;
16333
+ this.partInfo = new Array(this.chunkCount).fill(null);
16334
+ const taskId = this.generateUUID();
16335
+ this.generateUUID();
16336
+ console.log(`[上传开始] 文件: ${fileName}, 大小: ${fileSize}, 分片: ${this.chunkCount}`);
16337
+ this.uploadTaskId = await this.getUploadId(fileSize, fileName, uin, authKey, taskId);
16338
+ console.log(`[获取 UploadID] ${this.uploadTaskId}`);
16339
+ this.startSpeedWatch();
16340
+ if (fileSize <= this.chunkSize) {
16341
+ console.log("[直接上传] 单文件模式");
16342
+ const etag = await this.uploadChunk(fileBuffer, fileName, fileSize, uin, authKey, this.uploadTaskId, 1, taskId, (delta)=>this.updateProgress(delta, onProgress));
16343
+ this.partInfo[0] = {
16344
+ PartNumber: 1,
16345
+ ETag: etag
16346
+ };
16347
+ this.uploadedChunks = 1;
16348
+ } else {
16349
+ console.log(`[分片上传] 并发数: ${this.concurrentLimit}`);
16350
+ const chunks = Array.from({
16351
+ length: this.chunkCount
16352
+ }, (_, i)=>i);
16353
+ await this.asyncPool(this.concurrentLimit, chunks, async (index)=>{
16354
+ const start = index * this.chunkSize;
16355
+ const end = Math.min((index + 1) * this.chunkSize, fileSize);
16356
+ const chunk = fileBuffer.slice(start, end);
16357
+ console.log(`[上传分片 ${index + 1}/${this.chunkCount}] 大小: ${chunk.length}`);
16358
+ const etag = await this.uploadChunk(chunk, fileName, fileSize, uin, authKey, this.uploadTaskId, index + 1, taskId, (delta)=>this.updateProgress(delta, onProgress));
16359
+ this.partInfo[index] = {
16360
+ PartNumber: index + 1,
16361
+ ETag: etag
16362
+ };
16363
+ this.uploadedChunks++;
16364
+ onProgress?.({
16365
+ uploadedChunks: this.uploadedChunks,
16366
+ totalChunks: this.chunkCount,
16367
+ percent: Math.floor(this.uploadedChunks / this.chunkCount * 100),
16368
+ speed: this.uploadSpeed
16369
+ });
16370
+ });
16371
+ }
16372
+ console.log("[完成上传] 合并分片...");
16373
+ const downloadUrl = await this.completeUpload(this.uploadTaskId, fileName, fileSize, uin, authKey, transFlag || "0_0", this.partInfo.filter(Boolean), taskId);
16374
+ this.stopSpeedWatch();
16375
+ return {
16376
+ downloadUrl,
16377
+ width,
16378
+ height,
16379
+ fileSize,
16380
+ md5: external_node_crypto_default().createHash("md5").update(fileBuffer).digest("hex")
16381
+ };
16382
+ }
16383
+ updateProgress(delta, onProgress) {}
16384
+ startSpeedWatch() {
16385
+ let lastUploaded = 0;
16386
+ this.speedInterval = setInterval(()=>{
16387
+ const current = this.uploadedChunks * this.chunkSize;
16388
+ this.uploadSpeed = Math.floor((current - lastUploaded) / 1024);
16389
+ this.speedRecords.push(this.uploadSpeed);
16390
+ lastUploaded = current;
16391
+ }, 1000);
16392
+ }
16393
+ stopSpeedWatch() {
16394
+ if (this.speedInterval) clearInterval(this.speedInterval);
16176
16395
  }
16177
16396
  }
16397
+ function generateUUID() {
16398
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c)=>{
16399
+ const r = 16 * Math.random() | 0;
16400
+ const v = "x" === c ? r : 0x3 & r | 0x8;
16401
+ return v.toString(16);
16402
+ });
16403
+ }
16178
16404
  function mock_getTimeStamp(length) {
16179
16405
  return Date.now().toString().substring(0, length);
16180
16406
  }
@@ -16223,119 +16449,21 @@ var __webpack_exports__ = {};
16223
16449
  });
16224
16450
  return response.data;
16225
16451
  }
16226
- async function getUploadId(fileSize, fileName, _finderUsername, taskId, uin, authKey, mediaType) {
16227
- const blockSize = 8388608;
16228
- const blockSum = Math.ceil(fileSize / blockSize);
16229
- const blockPartLength = [];
16230
- if (fileSize < blockSize) blockPartLength.push(fileSize);
16231
- else for(let i = 1; i <= blockSum; i++)if (i * blockSize <= fileSize) blockPartLength.push(i * blockSize);
16232
- else {
16233
- blockPartLength.push(fileSize);
16234
- break;
16235
- }
16236
- const requestBody = {
16237
- BlockSum: blockSum,
16238
- BlockPartLength: blockPartLength
16239
- };
16240
- console.log("taskId:", taskId);
16241
- const headers = {
16242
- "X-Arguments": `apptype=251&filetype=${mediaType}&weixinnum=${uin}&filekey=${encodeURIComponent(fileName)}&filesize=${fileSize}&taskid=${taskId}&scene=2`,
16243
- Authorization: authKey,
16244
- Accept: "application/json, text/plain, */*",
16245
- "Content-MD5": "null",
16246
- Referer: "https://channels.weixin.qq.com/",
16247
- Origin: "https://channels.weixin.qq.com/"
16248
- };
16249
- try {
16250
- const response = await external_axios_default().put("https://finderassistancea.video.qq.com/applyuploaddfs", requestBody, {
16251
- headers
16252
- });
16253
- return response.data;
16254
- } catch (e) {
16255
- console.log("getUploadId error:", e);
16256
- return {
16257
- errCode: -1,
16258
- errMsg: e instanceof Error ? e.message : "未知错误"
16259
- };
16260
- }
16261
- }
16262
- async function uploadImagePart(imageBuffer, fileName, mediaType, _finderUsername, taskId, fileSize, uin, authKey, uploadId, partNumber = 1) {
16263
- const md5Hash = calculatePartialMd5(imageBuffer);
16264
- const headers = {
16265
- "Content-MD5": md5Hash,
16266
- "X-Arguments": `apptype=251&filetype=${mediaType}&weixinnum=${uin}&filekey=${encodeURIComponent(fileName)}&filesize=${fileSize}&taskid=${taskId}&scene=0`,
16267
- Authorization: authKey,
16268
- "Content-Type": "application/octet-stream",
16269
- Referer: "https://channels.weixin.qq.com/platform/post/create",
16270
- Origin: "https://channels.weixin.qq.com",
16271
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
16272
- };
16273
- const url = `https://finderassistancea.video.qq.com/uploadpartdfs?PartNumber=${partNumber}&UploadID=${encodeURIComponent(uploadId)}`;
16274
- const response = await external_axios_default().put(url, imageBuffer, {
16275
- headers
16452
+ async function uploadImageComplete(imagePath, taskId, finderUsername, uin, authKey) {
16453
+ const uploader = new VideoChannelUploader({
16454
+ chunkSize: 8388608,
16455
+ concurrentLimit: 4
16276
16456
  });
16277
- console.log("上传图片响应:", JSON.stringify(response.data));
16278
- return response.data;
16279
- }
16280
- async function getUploadedImageInfo(partInfo, _finderUsername, fileName, uploadId, fileSize, taskId, uin, authKey, mediaType) {
16281
- const headers = {
16282
- "Content-MD5": "null",
16283
- "X-Arguments": `apptype=251&filetype=${mediaType}&weixinnum=${uin}&filekey=${encodeURIComponent(fileName)}&filesize=${fileSize}&taskid=${taskId}&scene=0`,
16284
- Authorization: authKey,
16285
- Referer: "https://channels.weixin.qq.com/platform/post/create",
16286
- Origin: "https://channels.weixin.qq.com",
16287
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
16288
- };
16289
- const requestBody = {
16290
- TransFlag: "0_0",
16291
- PartInfo: partInfo
16292
- };
16293
- const url = `https://finderassistancea.video.qq.com/completepartuploaddfs?UploadID=${encodeURIComponent(uploadId)}`;
16294
- const response = await external_axios_default().post(url, requestBody, {
16295
- headers
16457
+ const result = await uploader.upload(imagePath, uin, authKey, {
16458
+ onProgress: (p)=>console.log(`上传进度: ${p.percent}%`)
16296
16459
  });
16297
- return response.data;
16298
- }
16299
- async function uploadImageComplete(imagePath, taskId, finderUsername, uin, authKey, _retryCount = 3) {
16300
- try {
16301
- const imageBuffer = await readImageFile(imagePath);
16302
- if (!imageBuffer || 0 === imageBuffer.length) return {
16303
- errMsg: `读取图片失败: ${imagePath}`
16304
- };
16305
- if (imageBuffer.length > 5242880) return {
16306
- errMsg: `图片大小超限制5MB: ${imagePath}`
16307
- };
16308
- const fileName = external_node_path_default().basename(imagePath);
16309
- const fileSize = imageBuffer.length;
16310
- const uploadIdResponse = await getUploadId(fileSize, fileName, finderUsername, taskId, uin, authKey, 20304);
16311
- console.log("申请上传ID响应SSS:", JSON.stringify(uploadIdResponse));
16312
- if (!uploadIdResponse.UploadID) return {
16313
- errMsg: `获取上传id失败: ${uploadIdResponse.errMsg}`
16314
- };
16315
- const uploadResponse = await uploadImagePart(imageBuffer, fileName, 20304, finderUsername, taskId, fileSize, uin, authKey, uploadIdResponse.UploadID);
16316
- if (!uploadResponse.ETag) return {
16317
- errMsg: `上传图片失败: ${uploadResponse.errMsg}`
16318
- };
16319
- const partInfo = [
16320
- {
16321
- PartNumber: 1,
16322
- ETag: uploadResponse.ETag
16323
- }
16324
- ];
16325
- const imageInfo = await getUploadedImageInfo(partInfo, finderUsername, fileName, uploadIdResponse.UploadID, fileSize, taskId, uin, authKey, 20304);
16326
- if (!imageInfo.DownloadURL) return {
16327
- errMsg: `获取图片信息失败: ${imageInfo.errMsg}`
16328
- };
16329
- const md5 = calculateBufferMd5(imageBuffer);
16330
- return {
16331
- DownloadURL: imageInfo.DownloadURL,
16332
- md5
16333
- };
16334
- } catch (error) {
16335
- return {
16336
- errMsg: error instanceof Error ? error.message : "上传图片失败"
16337
- };
16338
- }
16460
+ return {
16461
+ DownloadURL: result.downloadUrl,
16462
+ md5: result.md5,
16463
+ fileSize: result.fileSize,
16464
+ width: result.width,
16465
+ height: result.height
16466
+ };
16339
16467
  }
16340
16468
  function buildLocation(address) {
16341
16469
  if (!address || !address.city) return {
@@ -16407,7 +16535,7 @@ var __webpack_exports__ = {};
16407
16535
  const topicList = params.topic || [];
16408
16536
  const location1 = params.address ? buildLocation(params.address) : {};
16409
16537
  const publishData = {
16410
- clientid: utils_uuidv4(),
16538
+ clientid: generateUUID(),
16411
16539
  timestamp: mock_getTimeStamp(13),
16412
16540
  _log_finder_id: params.finderUsername,
16413
16541
  _log_finder_uin: "",
@@ -16449,7 +16577,7 @@ var __webpack_exports__ = {};
16449
16577
  }
16450
16578
  }
16451
16579
  };
16452
- if (params.scheduledPublish) publishData.effectiveTime = Math.floor(params.scheduledPublish / 1000);
16580
+ if (params.scheduledPublish) publishData.effectiveTime = params.scheduledPublish;
16453
16581
  const objectDesc = publishData.objectDesc;
16454
16582
  if (topicList.length) objectDesc.topic = {
16455
16583
  finderTopicInfo: buildTopicXml(params.content, topicList)
@@ -16489,6 +16617,7 @@ var __webpack_exports__ = {};
16489
16617
  _pageUrl: "https://channels.weixin.qq.com/micro/content/post/finderNewLifeCreate"
16490
16618
  };
16491
16619
  const queryString = new URLSearchParams(queryData).toString();
16620
+ console.log("1111111111111111", JSON.stringify(requestBody));
16492
16621
  const apiResponse = await external_axios_default().post(`${publishUrl}?${queryString}`, requestBody, {
16493
16622
  headers: {
16494
16623
  cookie: cookies,
@@ -16525,7 +16654,8 @@ var __webpack_exports__ = {};
16525
16654
  if (0 !== authKeyResponse.errCode || !authKeyResponse.data?.authKey) return (0, share_namespaceObject.response)(authKeyResponse.errCode || 500, `获取上传认证参数失败: ${authKeyResponse.errMsg}`, "");
16526
16655
  const authKey = authKeyResponse.data.authKey;
16527
16656
  const uin = authKeyResponse.data.uin;
16528
- const taskId = utils_uuidv4();
16657
+ if (!uin) return (0, share_namespaceObject.response)(500, "获取用户 uin 失败", "");
16658
+ const taskId = String(generateUUID());
16529
16659
  task.logger.info(`开始上传 ${images.length} 张图片...`);
16530
16660
  const uploadedImages = [];
16531
16661
  for(let i = 0; i < images.length; i++){
@@ -16536,11 +16666,11 @@ var __webpack_exports__ = {};
16536
16666
  uploadedImages.push({
16537
16667
  url: `https://finder.video.qq.com${uploadResult.DownloadURL.split("qq.com")[1] || ""}`,
16538
16668
  md5sum: uploadResult.md5 || "",
16539
- fileSize: 0,
16669
+ fileSize: uploadResult.fileSize || 0,
16540
16670
  thumbUrl: uploadResult.DownloadURL,
16541
16671
  fullThumbUrl: uploadResult.DownloadURL,
16542
- width: 0,
16543
- height: 0,
16672
+ width: uploadResult.width || 0,
16673
+ height: uploadResult.height || 0,
16544
16674
  mediaType: 2,
16545
16675
  videoPlayLen: 0,
16546
16676
  urlCdnTaskId: ""
@@ -16565,6 +16695,7 @@ var __webpack_exports__ = {};
16565
16695
  topic: topicNames,
16566
16696
  link: params.link,
16567
16697
  address: addressInfo,
16698
+ collection: params.collection,
16568
16699
  scheduledPublish: params.scheduledPublish,
16569
16700
  music: params.music
16570
16701
  });
@@ -16741,12 +16872,12 @@ var __webpack_exports__ = {};
16741
16872
  task.logger.info("内容填写完成");
16742
16873
  });
16743
16874
  }
16744
- if (params.address) {
16875
+ if (params.address?.poi_id) {
16745
16876
  task.logger.info(`选择地点: ${params.address.name}`);
16746
16877
  const instance = page.locator(".position-display-wrap");
16747
16878
  await instance.click();
16748
16879
  await page.waitForTimeout(1000);
16749
- await page.locator(".location-filter-wrap input").fill(params.address.name);
16880
+ await page.locator(".location-filter-wrap input").fill(params.address?.name || params.address?.address || params.address?.city_name);
16750
16881
  await page.waitForTimeout(2000);
16751
16882
  const poperInstance = page.locator(".location-filter-wrap .common-option-list-wrap .option-item");
16752
16883
  await poperInstance.nth(1).waitFor();
@@ -16769,7 +16900,7 @@ var __webpack_exports__ = {};
16769
16900
  await instanceLink.first().click();
16770
16901
  task.logger.info(`添加链接: ${params.link.link}`);
16771
16902
  await page.waitForTimeout(500);
16772
- const linkTypeName = "1" === params.link.urlType ? "公众号文章" : "红包封面";
16903
+ const linkTypeName = 1 === params.link.urlType ? "公众号文章" : "红包封面";
16773
16904
  page.locator(".post-link-wrap .link-list-options .link-option-item").filter({
16774
16905
  hasText: linkTypeName
16775
16906
  }).first().click({
@@ -16864,6 +16995,384 @@ var __webpack_exports__ = {};
16864
16995
  return (0, share_namespaceObject.response)(500, `微信视频号发布失败: ${errorMsg}`, "");
16865
16996
  }
16866
16997
  };
16998
+ const rpaAction_Server = async (task, params)=>{
16999
+ task.logger.info("开始微信视频号发布(Server 模式)");
17000
+ const defaultPage = task.steelBrowserContext?.pages()[0];
17001
+ if (defaultPage) {
17002
+ if (!defaultPage._routeRegistered) {
17003
+ defaultPage._routeRegistered = true;
17004
+ const blockedPatterns = [
17005
+ "**/apm-fe.weixin.com*",
17006
+ "**/t2.weixin.com*"
17007
+ ].map((pattern)=>new RegExp(pattern.replace(/\*\*/g, ".*").replace(/\*/g, "[^/]*")));
17008
+ await defaultPage.route("**/*", async (route)=>{
17009
+ const req = route.request();
17010
+ const url = req.url();
17011
+ const blocked = blockedPatterns.some((regex)=>regex.test(url));
17012
+ if (!blocked) return route.continue();
17013
+ if ("OPTIONS" === req.method()) {
17014
+ console.log("处理 OPTIONS 预检:", url);
17015
+ await route.fulfill({
17016
+ status: 204,
17017
+ headers: {
17018
+ "access-control-allow-origin": "*",
17019
+ "access-control-allow-methods": "GET,POST,OPTIONS,PUT,DELETE",
17020
+ "access-control-allow-headers": "*"
17021
+ },
17022
+ body: ""
17023
+ });
17024
+ return;
17025
+ }
17026
+ await route.fulfill({
17027
+ status: 204,
17028
+ body: ""
17029
+ });
17030
+ });
17031
+ }
17032
+ }
17033
+ const tmpCachePath = task.getTmpPath();
17034
+ task.logger?.info("==>进入RPA操作:任务开始,下载图片开始...");
17035
+ const updateTaskState = task.taskStageStore?.update?.bind(task.taskStageStore, task.taskId || "");
17036
+ const imagePromise = Promise.all(params.banners.map((url)=>{
17037
+ const fileName = (0, share_namespaceObject.getFilenameFromUrl)(url);
17038
+ return (0, share_namespaceObject.downloadImage)(url, external_node_path_default().join(tmpCachePath, fileName));
17039
+ }));
17040
+ let proxyUrl;
17041
+ if (params.localIP) {
17042
+ const args = [
17043
+ params.localIP,
17044
+ params.proxyLoc,
17045
+ params.accountId
17046
+ ];
17047
+ task.logger?.info(`==> 开始获取代理信息:${args}`);
17048
+ const ProxyAgentResult = await ProxyAgent({
17049
+ logger: task.logger
17050
+ }, ...args);
17051
+ task.logger?.info("==> 代理信息获取成功!");
17052
+ proxyUrl = ProxyAgentResult ? `http://${ProxyAgentResult.ip}:${ProxyAgentResult.port}` : void 0;
17053
+ }
17054
+ task.logger?.info("==>开始打开视频号页面...");
17055
+ const page = await task.createPage({
17056
+ show: task.debug,
17057
+ cookies: params.cookies,
17058
+ proxyUrl,
17059
+ url: params.url || "https://channels.weixin.qq.com/platform/post/finderNewLifeCreate",
17060
+ ...params.viewport ? {
17061
+ viewport: params.viewport
17062
+ } : {}
17063
+ });
17064
+ task.logger?.info("==>视频号页面打开成功");
17065
+ console.log(task.steelConnector?.getLive(task.sessionId || ""));
17066
+ await updateTaskState?.({
17067
+ state: share_namespaceObject.TaskState.ACTION,
17068
+ connectAddress: task.steelConnector?.getProxyUrl(task.sessionId || "", "v1/sessions/debug"),
17069
+ sessionId: task.sessionId
17070
+ });
17071
+ const clickTimeout = 10000;
17072
+ try {
17073
+ await page.waitForSelector(".post-edit-wrap", {
17074
+ state: "visible",
17075
+ timeout: 10000
17076
+ });
17077
+ task.logger?.info("✓ 登录状态正常,找到编辑器容器");
17078
+ } catch (error) {
17079
+ task.logger?.error("✗ 未找到编辑器,可能登录失效");
17080
+ return {
17081
+ code: 414,
17082
+ message: "登录失效或页面加载异常",
17083
+ data: page.url()
17084
+ };
17085
+ }
17086
+ const images = await imagePromise;
17087
+ task.logger?.info(`==>图片下载完成,共 ${images.length} 张,开始上传图片...`);
17088
+ const uploadSelectors = [
17089
+ '.ant-upload-btn input[type="file"]',
17090
+ '.upload input[type="file"][accept*="image"]',
17091
+ '.upload-wrap input[type="file"]',
17092
+ 'input[type="file"][accept*="image"]'
17093
+ ];
17094
+ let uploadInput = null;
17095
+ for (const selector of uploadSelectors){
17096
+ const input = page.locator(selector);
17097
+ const count = await input.count();
17098
+ if (count > 0) {
17099
+ uploadInput = input.first();
17100
+ task.logger?.info(`找到上传输入框: ${selector}`);
17101
+ break;
17102
+ }
17103
+ }
17104
+ if (!uploadInput) {
17105
+ task.logger?.warn("未找到上传输入框,等待 3 秒后重试...");
17106
+ await page.waitForTimeout(3000);
17107
+ const anyFileInput = page.locator('input[type="file"]');
17108
+ const inputCount = await anyFileInput.count();
17109
+ if (inputCount > 0) {
17110
+ uploadInput = anyFileInput.first();
17111
+ task.logger?.info(`找到文件输入框(共 ${inputCount} 个)`);
17112
+ } else {
17113
+ if (task.debug) {
17114
+ const screenshotPath = external_node_path_default().join(tmpCachePath, `upload-error-${Date.now()}.png`);
17115
+ await page.screenshot({
17116
+ path: screenshotPath,
17117
+ fullPage: true
17118
+ });
17119
+ task.logger?.error(`未找到上传输入框,已截图保存至: ${screenshotPath}`);
17120
+ }
17121
+ throw new Error("未找到图片上传输入框");
17122
+ }
17123
+ }
17124
+ await uploadInput.setInputFiles(images, {
17125
+ timeout: 60000
17126
+ });
17127
+ task.logger?.info(`==>图片上传完成: ${images.length} 张`);
17128
+ await page.waitForTimeout(3000);
17129
+ if (params.title) {
17130
+ task.logger?.info(`填写标题: ${params.title}`);
17131
+ const titleInput = page.locator('input[placeholder*="填写标题"]');
17132
+ await titleInput.waitFor({
17133
+ state: "visible",
17134
+ timeout: clickTimeout
17135
+ });
17136
+ await titleInput.click({
17137
+ timeout: clickTimeout
17138
+ });
17139
+ await titleInput.clear({
17140
+ timeout: 3000
17141
+ });
17142
+ await titleInput.fill(params.title, {
17143
+ timeout: 5000
17144
+ });
17145
+ task.logger?.info("==>标题填写完成");
17146
+ }
17147
+ if (params.content) {
17148
+ task.logger?.info("填写描述和话题");
17149
+ const descEditor = page.locator(".input-editor");
17150
+ await descEditor.waitFor({
17151
+ state: "visible",
17152
+ timeout: clickTimeout
17153
+ });
17154
+ await descEditor.click({
17155
+ timeout: clickTimeout
17156
+ });
17157
+ await page.waitForTimeout(500);
17158
+ await descEditor.evaluate((el)=>{
17159
+ el.textContent = "";
17160
+ });
17161
+ await page.waitForTimeout(300);
17162
+ task.logger?.info("已清空编辑器内容");
17163
+ await descEditor.pressSequentially(params.content, {
17164
+ delay: 10
17165
+ });
17166
+ await page.waitForTimeout(500);
17167
+ task.logger?.info("==>内容填写完成");
17168
+ }
17169
+ if (params.address?.poi_id) {
17170
+ task.logger?.info(`选择地点: ${params.address.name}`);
17171
+ const positionDisplayWrap = page.locator(".position-display-wrap");
17172
+ await positionDisplayWrap.click({
17173
+ timeout: clickTimeout
17174
+ });
17175
+ await page.waitForTimeout(1000);
17176
+ await page.locator(".location-filter-wrap input").fill(params.address?.name || params.address?.address || params.address?.city_name);
17177
+ await page.waitForTimeout(2000);
17178
+ const poperInstance = page.locator(".location-filter-wrap .common-option-list-wrap .option-item");
17179
+ await poperInstance.nth(1).waitFor();
17180
+ await poperInstance.nth(1).click({
17181
+ timeout: clickTimeout
17182
+ });
17183
+ task.logger?.info("==>地点选择完成");
17184
+ }
17185
+ if (params.collection) {
17186
+ task.logger?.info(`选择合集: ${params.collection.collectionName}`);
17187
+ const instanceCollection = page.locator(".post-album-display-wrap");
17188
+ await instanceCollection.click({
17189
+ timeout: clickTimeout
17190
+ });
17191
+ await page.waitForTimeout(1000);
17192
+ await page.locator(".post-album-wrap .option-item").filter({
17193
+ hasText: params.collection.collectionName
17194
+ }).first().click({
17195
+ force: true
17196
+ });
17197
+ task.logger?.info("==>合集选择完成");
17198
+ }
17199
+ if (params.link) {
17200
+ task.logger?.info(`添加链接: ${params.link.link}`);
17201
+ const instanceLink = page.locator(".link-display-wrap");
17202
+ await instanceLink.first().click({
17203
+ timeout: clickTimeout
17204
+ });
17205
+ await page.waitForTimeout(500);
17206
+ const linkTypeName = 1 === params.link.urlType ? "公众号文章" : "红包封面";
17207
+ await page.locator(".post-link-wrap .link-list-options .link-option-item").filter({
17208
+ hasText: linkTypeName
17209
+ }).first().click({
17210
+ force: true
17211
+ });
17212
+ await page.waitForSelector(".link-input-wrap", {
17213
+ state: "visible",
17214
+ timeout: 3000
17215
+ });
17216
+ const linkInput = page.locator('.link-input-wrap input[type="text"]');
17217
+ await linkInput.first().fill(params.link.link);
17218
+ task.logger?.info("==>链接添加完成");
17219
+ }
17220
+ if (params.music) {
17221
+ task.logger?.info(`添加背景音乐: ${params.music.name}`);
17222
+ const musicFormItem = page.locator(".post-with-link").filter({
17223
+ hasText: "音乐"
17224
+ });
17225
+ const musicDisplayWrap = musicFormItem.locator(".link-display-wrap").first();
17226
+ await musicDisplayWrap.click({
17227
+ timeout: clickTimeout
17228
+ });
17229
+ const searchInput = musicFormItem.locator('.weui-desktop-search input[type="text"]').first();
17230
+ const searchTxt = `${params.music.name} - ${params.music.authorName}`;
17231
+ await searchInput.fill(searchTxt);
17232
+ await page.waitForTimeout(300);
17233
+ await searchInput.press("Enter");
17234
+ await page.waitForTimeout(2000);
17235
+ const bgmItemWrap = musicFormItem.locator(".bgm-item-wrap").filter({
17236
+ hasText: searchTxt
17237
+ }).first();
17238
+ await bgmItemWrap.hover();
17239
+ await page.waitForTimeout(500);
17240
+ await bgmItemWrap.locator(".selected-icon").first().click({
17241
+ force: true
17242
+ });
17243
+ task.logger?.info("==>背景音乐添加完成");
17244
+ }
17245
+ if (!params.isImmediatelyPublish && params.scheduledPublish) {
17246
+ task.logger?.info("设置定时发布");
17247
+ const timingRadio = page.locator(".weui-desktop-form__check-content").filter({
17248
+ hasNotText: "不定时"
17249
+ }).first();
17250
+ await timingRadio.click({
17251
+ timeout: clickTimeout
17252
+ });
17253
+ await page.waitForTimeout(500);
17254
+ const dateInput = page.locator('.weui-desktop-picker__date input[placeholder*="请选择发表时间"]');
17255
+ await dateInput.click({
17256
+ timeout: clickTimeout
17257
+ });
17258
+ const dateD = utils_TimeFormatter.format(params.scheduledPublish, "d");
17259
+ const nowMonth = utils_TimeFormatter.format(Date.now(), "MM月");
17260
+ const nowMonthText = utils_TimeFormatter.format(Date.now(), "M月");
17261
+ const month = utils_TimeFormatter.format(params.scheduledPublish, "MM月");
17262
+ const monthLocator = page.locator("weui-desktop-picker__panel__label").filter({
17263
+ hasText: month
17264
+ }).first();
17265
+ const monthCount = await monthLocator.count();
17266
+ if (0 === monthCount) {
17267
+ await page.locator(".weui-desktop-picker__panel__label").filter({
17268
+ hasText: nowMonth
17269
+ }).first().click({
17270
+ timeout: clickTimeout
17271
+ });
17272
+ await page.waitForTimeout(500);
17273
+ await page.locator(".weui-desktop-picker__table-row td a").filter({
17274
+ hasText: nowMonthText
17275
+ }).first().click({
17276
+ timeout: clickTimeout
17277
+ });
17278
+ }
17279
+ await page.waitForTimeout(500);
17280
+ await page.locator(".weui-desktop-picker__table-row td a").filter({
17281
+ hasText: dateD
17282
+ }).first().click({
17283
+ timeout: clickTimeout
17284
+ });
17285
+ await page.locator(".weui-desktop-form__input-wrp input[placeholder*='请选择时间']").fill(utils_TimeFormatter.format(params.scheduledPublish, "hh:mm"));
17286
+ await page.locator("i.weui-desktop-icon__time").click({
17287
+ timeout: clickTimeout
17288
+ });
17289
+ await page.locator(".post-time-wrap .form-item .label").filter({
17290
+ hasText: "发表时间"
17291
+ }).click({
17292
+ timeout: clickTimeout
17293
+ });
17294
+ task.logger?.info("==>定时发布设置完成");
17295
+ }
17296
+ task.logger?.info("准备发布...");
17297
+ await page.waitForTimeout(300);
17298
+ if (MockPublish) {
17299
+ const message = "视频号模拟发布成功";
17300
+ const data = "123456789";
17301
+ await updateTaskState?.({
17302
+ state: share_namespaceObject.TaskState.SUCCESS,
17303
+ result: {
17304
+ response: data
17305
+ }
17306
+ });
17307
+ return (0, share_namespaceObject.success)(data, message);
17308
+ }
17309
+ const publishResponse = await new Promise((resolve)=>{
17310
+ const handleResponse = async (response)=>{
17311
+ const url = response.url();
17312
+ if (url.includes("/post/post_create") || url.includes("/post/post_draft")) {
17313
+ const jsonResponse = await response.json();
17314
+ page.off("response", handleResponse);
17315
+ const articleId = jsonResponse.object?.id || jsonResponse.data?.objectId || "";
17316
+ const message = jsonResponse?.errMsg || "";
17317
+ const errCode = jsonResponse.data?.baseResp?.errcode ?? jsonResponse.errCode;
17318
+ if (0 === errCode) resolve({
17319
+ success: true,
17320
+ msg: message || "发布成功",
17321
+ data: {
17322
+ id: articleId,
17323
+ objectId: articleId
17324
+ }
17325
+ });
17326
+ else {
17327
+ let errorMessage = message;
17328
+ if (-11224 === errCode) errorMessage = "视频号管理员完成实名且绑定手机号后才可以发表";
17329
+ else if (300333 === errCode || 300334 === errCode) errorMessage = "登录失效";
17330
+ else if (300330 === errCode) errorMessage = "未登录";
17331
+ else if (300002 === errCode) errorMessage = "官方平台在校验音乐/位置/定时信息时失败了,请重新编辑后发布";
17332
+ resolve({
17333
+ success: false,
17334
+ msg: errorMessage
17335
+ });
17336
+ }
17337
+ }
17338
+ };
17339
+ page.on("response", handleResponse);
17340
+ const publishText = "1" === params.publishType ? "发表" : "保存草稿";
17341
+ page.locator(".form-btns .weui-desktop-btn").filter({
17342
+ hasText: publishText
17343
+ }).first().click({
17344
+ timeout: clickTimeout
17345
+ });
17346
+ setTimeout(()=>{
17347
+ page.off("response", handleResponse);
17348
+ resolve({
17349
+ success: false,
17350
+ msg: "发布超时"
17351
+ });
17352
+ }, 10000);
17353
+ });
17354
+ if (!publishResponse?.success) {
17355
+ const msg = `发布失败:${publishResponse?.msg || "未知错误"}`;
17356
+ await updateTaskState?.({
17357
+ state: share_namespaceObject.TaskState.FAILED,
17358
+ error: msg
17359
+ });
17360
+ await page.close();
17361
+ return {
17362
+ code: 414,
17363
+ message: msg,
17364
+ data: ""
17365
+ };
17366
+ }
17367
+ await updateTaskState?.({
17368
+ state: share_namespaceObject.TaskState.SUCCESS,
17369
+ result: {
17370
+ response: publishResponse?.data?.id || ""
17371
+ }
17372
+ });
17373
+ await page.close();
17374
+ return (0, share_namespaceObject.success)(publishResponse?.data?.id || "", publishResponse?.msg || "发布成功");
17375
+ };
16867
17376
  const ShipinhaoPublishParamsSchema = ActionCommonParamsSchema.extend({
16868
17377
  title: schemas_string(),
16869
17378
  content: schemas_string(),
@@ -16871,19 +17380,14 @@ var __webpack_exports__ = {};
16871
17380
  topic: schemas_array(schemas_string()).optional(),
16872
17381
  address: schemas_object({
16873
17382
  poi_id: schemas_string(),
16874
- name: schemas_string(),
16875
- address: schemas_string(),
17383
+ name: schemas_string().optional(),
17384
+ address: schemas_string().optional(),
16876
17385
  latitude: schemas_number(),
16877
17386
  longitude: schemas_number(),
16878
- city_name: schemas_string(),
16879
- poi_type: schemas_number(),
16880
- type: schemas_string()
17387
+ city_name: schemas_string()
16881
17388
  }).optional(),
16882
17389
  link: schemas_object({
16883
- urlType: schemas_enum([
16884
- "1",
16885
- "2"
16886
- ]),
17390
+ urlType: schemas_number(),
16887
17391
  link: schemas_string(),
16888
17392
  title: schemas_string()
16889
17393
  }).optional(),
@@ -16918,7 +17422,8 @@ var __webpack_exports__ = {};
16918
17422
  console.log("shipinhaoPublish params:", params);
16919
17423
  if ("rpa" === params.actionType) return shipinhaoPublish_rpa_rpaAction(task, params);
16920
17424
  if ("mockApi" === params.actionType) return shipinhaoPublish_mock_mockAction(task, params);
16921
- return executeAction(shipinhaoPublish_mock_mockAction, shipinhaoPublish_rpa_rpaAction)(task, params);
17425
+ if ("server" === params.actionType) return rpaAction_Server(task, params);
17426
+ return executeAction(shipinhaoPublish_mock_mockAction, rpaAction_Server)(task, params);
16922
17427
  };
16923
17428
  const toutiaoLogin_rpa_scanRetryMaxCount = 60;
16924
17429
  const toutiaoLogin_rpa_waitQrcodeResultMaxTime = 2000 * toutiaoLogin_rpa_scanRetryMaxCount;
@@ -20845,7 +21350,7 @@ var __webpack_exports__ = {};
20845
21350
  await page.close();
20846
21351
  return (0, share_namespaceObject.success)(response);
20847
21352
  };
20848
- const rpaAction_Server = async (task, params)=>{
21353
+ const rpa_server_rpaAction_Server = async (task, params)=>{
20849
21354
  if (params.originalBind && params?.selfDeclaration?.type === "source-statement") return {
20850
21355
  code: 414,
20851
21356
  message: "已声明原创不可选择“来源转载”",
@@ -21728,8 +22233,8 @@ var __webpack_exports__ = {};
21728
22233
  const xiaohongshuPublish = async (task, params)=>{
21729
22234
  if ("rpa" === params.actionType) return xiaohongshuPublish_rpa_rpaAction(task, params);
21730
22235
  if ("mockApi" === params.actionType) return xiaohongshuPublish_mock_mockAction(task, params);
21731
- if ("server" === params.actionType) return rpaAction_Server(task, params);
21732
- return executeAction(xiaohongshuPublish_mock_mockAction, rpaAction_Server_Mock, rpaAction_Server)(task, params);
22236
+ if ("server" === params.actionType) return rpa_server_rpaAction_Server(task, params);
22237
+ return executeAction(xiaohongshuPublish_mock_mockAction, rpaAction_Server_Mock, rpa_server_rpaAction_Server)(task, params);
21733
22238
  };
21734
22239
  const xiaohongshuWebCommentAction_xsEncrypt = new Xhshow();
21735
22240
  const xiaohongshuWebCommentAction = async (_task, params)=>{