@iflyrpa/actions 1.1.8 → 1.1.9

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.cjs CHANGED
@@ -14,6 +14,8 @@ const require$$4$1 = require('assert');
14
14
  const require$$0$1 = require('tty');
15
15
  const zlib = require('zlib');
16
16
  const events$1 = require('events');
17
+ const node_buffer = require('node:buffer');
18
+ const crypto = require('node:crypto');
17
19
 
18
20
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
19
21
 
@@ -44,6 +46,7 @@ const require$$6__default = /*#__PURE__*/_interopDefaultCompat(require$$6);
44
46
  const require$$4__default$1 = /*#__PURE__*/_interopDefaultCompat(require$$4$1);
45
47
  const require$$0__default$1 = /*#__PURE__*/_interopDefaultCompat(require$$0$1);
46
48
  const zlib__default = /*#__PURE__*/_interopDefaultCompat(zlib);
49
+ const crypto__default = /*#__PURE__*/_interopDefaultCompat(crypto);
47
50
 
48
51
  function ensureFile(filePath) {
49
52
  return new Promise((resolve, reject)=>{
@@ -967,8 +970,6 @@ AxiosError.from = (error, code, config, request, response, customProps) => {
967
970
  return axiosError;
968
971
  };
969
972
 
970
- var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
971
-
972
973
  function getDefaultExportFromCjs (x) {
973
974
  return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
974
975
  }
@@ -21627,7 +21628,7 @@ const replaceImgSrc = (html, callback) => {
21627
21628
  return lastedHtml;
21628
21629
  };
21629
21630
 
21630
- const errnoMap$2 = {
21631
+ const errnoMap$3 = {
21631
21632
  20040706: "\u6B63\u6587\u56FE\u7247\u548C\u5C01\u9762\u56FE\u7247\u63A8\u8350jpg\u3001png\u683C\u5F0F\u3002",
21632
21633
  20040084: "\u6B63\u6587\u56FE\u7247\u548C\u5C01\u9762\u56FE\u7247\u63A8\u8350jpg\u3001png\u683C\u5F0F\u3002",
21633
21634
  20050004: "\u4ECA\u65E5\u767E\u5BB6\u53F7\u53D1\u5E03\u6B21\u6570\u5DF2\u8FBE\u4E0A\u9650\uFF0C\u8BF7\u660E\u5929\u518D\u8BD5\u3002",
@@ -21639,7 +21640,7 @@ const errnoMap$2 = {
21639
21640
  2004005714: "\u7F51\u7EDC\u73AF\u5883\u5F02\u5E38\uFF0C\u8BF7\u68C0\u67E5\u7F51\u7EDC\u540E\u91CD\u8BD5\u53D1\u5E03\u3002",
21640
21641
  401100032: "\u5F02\u5E38\uFF0C\u8BF7\u68C0\u67E5\u56FE\u7247\uFF08\u5982\uFF1A\u683C\u5F0F\u3001\u7248\u6743\u3001\u5408\u89C4\u6027\u7B49\uFF09\u3002"
21641
21642
  };
21642
- const mockAction$4 = async (task, params) => {
21643
+ const mockAction$5 = async (task, params) => {
21643
21644
  const { baijiahaoSingleCover, baijiahaoMultCover, baijiahaoCoverType } = params.settingInfo;
21644
21645
  const tmpCachePath = task.getTmpPath();
21645
21646
  const api = axios$1.create({
@@ -21651,7 +21652,7 @@ const mockAction$4 = async (task, params) => {
21651
21652
  api.interceptors.response.use(
21652
21653
  (response) => {
21653
21654
  if (response.data.errno !== 0) {
21654
- const errmsg = response.data.errno === 2005e4 ? (params.saveType === "draft" ? "\u540C\u6B65" : "\u53D1\u5E03") + errnoMap$2[response.data.errno] : response.data.errno === 401100032 ? "\u56FE\u7247" + (params.saveType === "draft" ? "\u540C\u6B65" : "\u53D1\u5E03") + errnoMap$2[response.data.errno] : errnoMap$2[response.data.errno] || response.config.defaultErrorMsg || (params.saveType === "draft" ? "\u6587\u7AE0\u540C\u6B65\u5F02\u5E38\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002" : "\u6587\u7AE0\u53D1\u5E03\u5F02\u5E38\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002");
21655
+ const errmsg = response.data.errno === 2005e4 ? (params.saveType === "draft" ? "\u540C\u6B65" : "\u53D1\u5E03") + errnoMap$3[response.data.errno] : response.data.errno === 401100032 ? "\u56FE\u7247" + (params.saveType === "draft" ? "\u540C\u6B65" : "\u53D1\u5E03") + errnoMap$3[response.data.errno] : errnoMap$3[response.data.errno] || response.config.defaultErrorMsg || (params.saveType === "draft" ? "\u6587\u7AE0\u540C\u6B65\u5F02\u5E38\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002" : "\u6587\u7AE0\u53D1\u5E03\u5F02\u5E38\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002");
21655
21656
  task.logger.error(errmsg);
21656
21657
  return Promise.reject(new Error(errmsg));
21657
21658
  }
@@ -21770,7 +21771,7 @@ const mockAction$4 = async (task, params) => {
21770
21771
 
21771
21772
  const baijiahaoPublish = async (task, params) => {
21772
21773
  task.logger.info("\u5F00\u59CB\u767E\u5BB6\u53F7\u53D1\u5E03");
21773
- return mockAction$4(task, params);
21774
+ return mockAction$5(task, params);
21774
21775
  };
21775
21776
 
21776
21777
  const getBaijiahaoActivity = async (task, params) => {
@@ -21900,7 +21901,7 @@ const COVER_TYPE = {
21900
21901
  single: 2,
21901
21902
  multiple: 3
21902
21903
  };
21903
- const errnoMap$1 = {
21904
+ const errnoMap$2 = {
21904
21905
  20004020: "\u56FE\u7247\u4E0A\u4F20\u5F02\u5E38\uFF0C\u8BF7\u91CD\u65B0\u7ED1\u5B9A\u8D26\u53F7\u540E\u540C\u6B65\u3002",
21905
21906
  7115: "\u6B63\u6587\u56FE\u7247\u548C\u5C01\u9762\u56FE\u7247\u63A8\u8350jpg\u3001png\u683C\u5F0F\u3002",
21906
21907
  100006: "\u6587\u7AE0\u540C\u6B65\u5F02\u5E38\uFF0C\u8BF7\u91CD\u65B0\u7ED1\u5B9A\u8D26\u53F7\u540E\u91CD\u8BD5\u3002",
@@ -21924,7 +21925,7 @@ const get3101DetailError = (errorList, message, saveType) => {
21924
21925
  }
21925
21926
  return error || (saveType === "draft" ? "\u6587\u7AE0\u540C\u6B65\u5F02\u5E38\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002" : "\u6587\u7AE0\u53D1\u5E03\u5F02\u5E38\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002");
21926
21927
  };
21927
- const mockAction$3 = async (task, params) => {
21928
+ const mockAction$4 = async (task, params) => {
21928
21929
  const { toutiaoSingleCover, toutiaoMultCover, toutiaoCoverType, toutiaoOriginal } = params.settingInfo;
21929
21930
  const tmpCachePath = task.getTmpPath();
21930
21931
  const api = axios$1.create({
@@ -21938,10 +21939,10 @@ const mockAction$3 = async (task, params) => {
21938
21939
  (response) => {
21939
21940
  if (response.data.code !== 0) {
21940
21941
  let errmsg = "";
21941
- if (Array.isArray(errnoMap$1[response.data.code])) {
21942
- errmsg = get3101DetailError(errnoMap$1[response.data.code], response.data.message, params.saveType);
21942
+ if (Array.isArray(errnoMap$2[response.data.code])) {
21943
+ errmsg = get3101DetailError(errnoMap$2[response.data.code], response.data.message, params.saveType);
21943
21944
  } else {
21944
- errmsg = errnoMap$1[response.data.code] || response.config.defaultErrorMsg || (params.saveType === "draft" ? "\u6587\u7AE0\u540C\u6B65\u5F02\u5E38\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002" : "\u6587\u7AE0\u53D1\u5E03\u5F02\u5E38\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002");
21945
+ errmsg = errnoMap$2[response.data.code] || response.config.defaultErrorMsg || (params.saveType === "draft" ? "\u6587\u7AE0\u540C\u6B65\u5F02\u5E38\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002" : "\u6587\u7AE0\u53D1\u5E03\u5F02\u5E38\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002");
21945
21946
  }
21946
21947
  task.logger.error(errmsg);
21947
21948
  return Promise.reject(new Error(errmsg));
@@ -22089,10 +22090,10 @@ const mockAction$3 = async (task, params) => {
22089
22090
 
22090
22091
  const toutiaoPublish = async (task, params) => {
22091
22092
  task.logger.info("\u5F00\u59CB\u5934\u6761\u53D1\u5E03");
22092
- return mockAction$3(task, params);
22093
+ return mockAction$4(task, params);
22093
22094
  };
22094
22095
 
22095
- const mockAction$2 = async (task, params) => {
22096
+ const mockAction$3 = async (task, params) => {
22096
22097
  const tmpCachePath = task.getTmpPath();
22097
22098
  const api = axios$1.create({
22098
22099
  headers: {
@@ -22223,9 +22224,9 @@ const rpaAction$2 = async (task, params) => {
22223
22224
  await page.locator(".footer-wrap button.publish-content").click();
22224
22225
  };
22225
22226
 
22226
- const executeAction$1 = (task, params) => {
22227
+ const executeAction$2 = (task, params) => {
22227
22228
  return new Promise((resolve, reject) => {
22228
- mockAction$2(task, params).then(resolve).catch(() => {
22229
+ mockAction$3(task, params).then(resolve).catch(() => {
22229
22230
  rpaAction$2(task, params).then(resolve).catch(reject);
22230
22231
  });
22231
22232
  });
@@ -22236,13 +22237,13 @@ const weitoutiaoPublish = async (task, params) => {
22236
22237
  return rpaAction$2(task, params);
22237
22238
  }
22238
22239
  if (params.actionType === "mockApi") {
22239
- return mockAction$2(task, params);
22240
+ return mockAction$3(task, params);
22240
22241
  }
22241
- return executeAction$1(task, params);
22242
+ return executeAction$2(task, params);
22242
22243
  };
22243
22244
 
22244
22245
  const scanRetryMaxCount = 30;
22245
- const errnoMap = {
22246
+ const errnoMap$1 = {
22246
22247
  200003: "\u767B\u5F55\u5931\u6548"
22247
22248
  };
22248
22249
  const saveDraft$1 = (api, params, data) => {
@@ -22340,7 +22341,7 @@ const massSend = async (api, params, data) => {
22340
22341
  });
22341
22342
  return res;
22342
22343
  };
22343
- const mockAction$1 = async (task, params) => {
22344
+ const mockAction$2 = async (task, params) => {
22344
22345
  const tmpCachePath = task.getTmpPath();
22345
22346
  const api = axios$1.create({
22346
22347
  headers: {
@@ -22352,7 +22353,7 @@ const mockAction$1 = async (task, params) => {
22352
22353
  (response) => {
22353
22354
  const responseData = response.data;
22354
22355
  if (responseData?.base_resp && responseData.base_resp.ret !== 0) {
22355
- const errmsg = errnoMap[responseData.base_resp.ret] || response.config.defaultErrorMsg || responseData.base_resp.err_msg || "Unknown error";
22356
+ const errmsg = errnoMap$1[responseData.base_resp.ret] || response.config.defaultErrorMsg || responseData.base_resp.err_msg || "Unknown error";
22356
22357
  task.logger.error(errmsg, responseData);
22357
22358
  return Promise.reject(new Error(errmsg));
22358
22359
  }
@@ -22561,7 +22562,7 @@ const mockAction$1 = async (task, params) => {
22561
22562
 
22562
22563
  const weixinPublish = async (task, params) => {
22563
22564
  task.logger.info("\u5F00\u59CB\u5FAE\u4FE1\u516C\u4F17\u53F7\u53D1\u5E03");
22564
- return mockAction$1(task, params);
22565
+ return mockAction$2(task, params);
22565
22566
  };
22566
22567
 
22567
22568
  const saveDraft = (api, params, data) => {
@@ -22582,7 +22583,7 @@ const saveDraft = (api, params, data) => {
22582
22583
  data: formData
22583
22584
  });
22584
22585
  };
22585
- const mockAction = async (task, params) => {
22586
+ const mockAction$1 = async (task, params) => {
22586
22587
  const tmpCachePath = task.getTmpPath();
22587
22588
  const api = axios$1.create({
22588
22589
  headers: {
@@ -22763,9 +22764,9 @@ const rpaAction$1 = async (task, params) => {
22763
22764
  }
22764
22765
  };
22765
22766
 
22766
- const executeAction = (task, params) => {
22767
+ const executeAction$1 = (task, params) => {
22767
22768
  return new Promise((resolve, reject) => {
22768
- mockAction(task, params).then(resolve).catch(() => {
22769
+ mockAction$1(task, params).then(resolve).catch(() => {
22769
22770
  rpaAction$1(task, params).then(resolve).catch(reject);
22770
22771
  });
22771
22772
  });
@@ -22776,16 +22777,252 @@ const weixinmpPublish = async (task, params) => {
22776
22777
  return rpaAction$1(task, params);
22777
22778
  }
22778
22779
  if (params.actionType === "mockApi") {
22779
- return mockAction(task, params);
22780
+ return mockAction$1(task, params);
22780
22781
  }
22781
- return executeAction(task, params);
22782
+ return executeAction$1(task, params);
22782
22783
  };
22783
22784
 
22784
- var dayjs_min = {exports: {}};
22785
+ var __defProp = Object.defineProperty;
22786
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
22787
+ var __publicField = (obj, key, value) => {
22788
+ __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
22789
+ return value;
22790
+ };
22791
+ class XsEncrypt {
22792
+ constructor() {
22793
+ __publicField(this, "words", [929260340, 1633971297, 895580464, 925905270]);
22794
+ __publicField(this, "keyBytes", node_buffer.Buffer.concat(
22795
+ this.words.map(
22796
+ (word) => new Uint8Array(node_buffer.Buffer.from([word >> 24 & 255, word >> 16 & 255, word >> 8 & 255, word & 255]))
22797
+ )
22798
+ ));
22799
+ __publicField(this, "iv", node_buffer.Buffer.from("4uzjr7mbsibcaldp", "utf8"));
22800
+ }
22801
+ /**
22802
+ * 根据传入的url生成MD5摘要
22803
+ *
22804
+ * @param {string} url - API的url
22805
+ * @returns {string} MD5摘要
22806
+ */
22807
+ async encryptMD5(url) {
22808
+ return crypto__default.createHash("md5").update(url, "utf8").digest("hex");
22809
+ }
22810
+ /**
22811
+ * 根据传入的text生成AES加密后的内容,并将其转为base64编码
22812
+ *
22813
+ * @param {string} text - 需要加密的字符串
22814
+ * @returns {string} 加密后的base64编码字符串
22815
+ */
22816
+ async encryptText(text) {
22817
+ const textEncoded = node_buffer.Buffer.from(text).toString("base64");
22818
+ const cipher = crypto__default.createCipheriv("aes-128-cbc", new Uint8Array(this.keyBytes), new Uint8Array(this.iv));
22819
+ const ciphertext = cipher.update(textEncoded, "utf8", "base64");
22820
+ return ciphertext + cipher.final("base64");
22821
+ }
22822
+ /**
22823
+ * 把加密后的payload转为16进制
22824
+ *
22825
+ * @param {string} encodedData - 加密后的payload(Base64编码)
22826
+ * @returns {string} 十六进制字符串
22827
+ */
22828
+ async base64ToHex(encodedData) {
22829
+ const decodedData = node_buffer.Buffer.from(encodedData, "base64");
22830
+ return decodedData.toString("hex");
22831
+ }
22832
+ /**
22833
+ * 把小红书加密参数payload转16进制 再使用base64编码
22834
+ *
22835
+ * @param {string} payload - 要加密处理的payload内容
22836
+ * @param {string} platform - 登录平台
22837
+ * @returns {string} 加密后并进行base64编码的字符串
22838
+ */
22839
+ async encryptPayload(payload, platform) {
22840
+ const hexPayload = await this.base64ToHex(payload);
22841
+ const obj = {
22842
+ signSvn: "56",
22843
+ signType: "x2",
22844
+ appID: platform,
22845
+ signVersion: "1",
22846
+ payload: hexPayload
22847
+ };
22848
+ const jsonString = JSON.stringify(obj, null, 0);
22849
+ return node_buffer.Buffer.from(jsonString).toString("base64");
22850
+ }
22851
+ /**
22852
+ * 将传入的参数加密为小红书的xs
22853
+ * Args: url: API请求的URL
22854
+ * a1: 签名参数a1
22855
+ * ts: 时间戳
22856
+ * platform: 登录平台 默认为xhs-pc-web
22857
+ * Returns:
22858
+ * 最终的加密签名字符串,前缀为“XYW_”
22859
+ */
22860
+ async encryptXs(url, a1, ts, platform = "xhs-pc-web") {
22861
+ const text = `x1=${await this.encryptMD5(`url=${url}`)};x2=0|0|0|1|0|0|1|0|0|0|1|0|0|0|0|1|0|0|0;x3=${a1};x4=${ts};`;
22862
+ return `XYW_${await this.encryptPayload(await this.encryptText(text), platform)}`;
22863
+ }
22864
+ dumps(...rest) {
22865
+ const [data, replacer = null, space = 0] = rest;
22866
+ return JSON.stringify(data, replacer, space).replace(/\n/g, "").replace(/":\s+"/g, '":"');
22867
+ }
22868
+ }
22785
22869
 
22786
- (function (module, exports) {
22787
- !function(t,e){module.exports=e();}(commonjsGlobal,(function(){var t=1e3,e=6e4,n=36e5,r="millisecond",i="second",s="minute",u="hour",a="day",o="week",c="month",f="quarter",h="year",d="date",l="Invalid Date",$=/^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[Tt\s]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?[.:]?(\d+)?$/,y=/\[([^\]]+)]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g,M={name:"en",weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),ordinal:function(t){var e=["th","st","nd","rd"],n=t%100;return "["+t+(e[(n-20)%10]||e[n]||e[0])+"]"}},m=function(t,e,n){var r=String(t);return !r||r.length>=e?t:""+Array(e+1-r.length).join(n)+t},v={s:m,z:function(t){var e=-t.utcOffset(),n=Math.abs(e),r=Math.floor(n/60),i=n%60;return (e<=0?"+":"-")+m(r,2,"0")+":"+m(i,2,"0")},m:function t(e,n){if(e.date()<n.date())return -t(n,e);var r=12*(n.year()-e.year())+(n.month()-e.month()),i=e.clone().add(r,c),s=n-i<0,u=e.clone().add(r+(s?-1:1),c);return +(-(r+(n-i)/(s?i-u:u-i))||0)},a:function(t){return t<0?Math.ceil(t)||0:Math.floor(t)},p:function(t){return {M:c,y:h,w:o,d:a,D:d,h:u,m:s,s:i,ms:r,Q:f}[t]||String(t||"").toLowerCase().replace(/s$/,"")},u:function(t){return void 0===t}},g="en",D={};D[g]=M;var p="$isDayjsObject",S=function(t){return t instanceof _||!(!t||!t[p])},w=function t(e,n,r){var i;if(!e)return g;if("string"==typeof e){var s=e.toLowerCase();D[s]&&(i=s),n&&(D[s]=n,i=s);var u=e.split("-");if(!i&&u.length>1)return t(u[0])}else {var a=e.name;D[a]=e,i=a;}return !r&&i&&(g=i),i||!r&&g},O=function(t,e){if(S(t))return t.clone();var n="object"==typeof e?e:{};return n.date=t,n.args=arguments,new _(n)},b=v;b.l=w,b.i=S,b.w=function(t,e){return O(t,{locale:e.$L,utc:e.$u,x:e.$x,$offset:e.$offset})};var _=function(){function M(t){this.$L=w(t.locale,null,!0),this.parse(t),this.$x=this.$x||t.x||{},this[p]=!0;}var m=M.prototype;return m.parse=function(t){this.$d=function(t){var e=t.date,n=t.utc;if(null===e)return new Date(NaN);if(b.u(e))return new Date;if(e instanceof Date)return new Date(e);if("string"==typeof e&&!/Z$/i.test(e)){var r=e.match($);if(r){var i=r[2]-1||0,s=(r[7]||"0").substring(0,3);return n?new Date(Date.UTC(r[1],i,r[3]||1,r[4]||0,r[5]||0,r[6]||0,s)):new Date(r[1],i,r[3]||1,r[4]||0,r[5]||0,r[6]||0,s)}}return new Date(e)}(t),this.init();},m.init=function(){var t=this.$d;this.$y=t.getFullYear(),this.$M=t.getMonth(),this.$D=t.getDate(),this.$W=t.getDay(),this.$H=t.getHours(),this.$m=t.getMinutes(),this.$s=t.getSeconds(),this.$ms=t.getMilliseconds();},m.$utils=function(){return b},m.isValid=function(){return !(this.$d.toString()===l)},m.isSame=function(t,e){var n=O(t);return this.startOf(e)<=n&&n<=this.endOf(e)},m.isAfter=function(t,e){return O(t)<this.startOf(e)},m.isBefore=function(t,e){return this.endOf(e)<O(t)},m.$g=function(t,e,n){return b.u(t)?this[e]:this.set(n,t)},m.unix=function(){return Math.floor(this.valueOf()/1e3)},m.valueOf=function(){return this.$d.getTime()},m.startOf=function(t,e){var n=this,r=!!b.u(e)||e,f=b.p(t),l=function(t,e){var i=b.w(n.$u?Date.UTC(n.$y,e,t):new Date(n.$y,e,t),n);return r?i:i.endOf(a)},$=function(t,e){return b.w(n.toDate()[t].apply(n.toDate("s"),(r?[0,0,0,0]:[23,59,59,999]).slice(e)),n)},y=this.$W,M=this.$M,m=this.$D,v="set"+(this.$u?"UTC":"");switch(f){case h:return r?l(1,0):l(31,11);case c:return r?l(1,M):l(0,M+1);case o:var g=this.$locale().weekStart||0,D=(y<g?y+7:y)-g;return l(r?m-D:m+(6-D),M);case a:case d:return $(v+"Hours",0);case u:return $(v+"Minutes",1);case s:return $(v+"Seconds",2);case i:return $(v+"Milliseconds",3);default:return this.clone()}},m.endOf=function(t){return this.startOf(t,!1)},m.$set=function(t,e){var n,o=b.p(t),f="set"+(this.$u?"UTC":""),l=(n={},n[a]=f+"Date",n[d]=f+"Date",n[c]=f+"Month",n[h]=f+"FullYear",n[u]=f+"Hours",n[s]=f+"Minutes",n[i]=f+"Seconds",n[r]=f+"Milliseconds",n)[o],$=o===a?this.$D+(e-this.$W):e;if(o===c||o===h){var y=this.clone().set(d,1);y.$d[l]($),y.init(),this.$d=y.set(d,Math.min(this.$D,y.daysInMonth())).$d;}else l&&this.$d[l]($);return this.init(),this},m.set=function(t,e){return this.clone().$set(t,e)},m.get=function(t){return this[b.p(t)]()},m.add=function(r,f){var d,l=this;r=Number(r);var $=b.p(f),y=function(t){var e=O(l);return b.w(e.date(e.date()+Math.round(t*r)),l)};if($===c)return this.set(c,this.$M+r);if($===h)return this.set(h,this.$y+r);if($===a)return y(1);if($===o)return y(7);var M=(d={},d[s]=e,d[u]=n,d[i]=t,d)[$]||1,m=this.$d.getTime()+r*M;return b.w(m,this)},m.subtract=function(t,e){return this.add(-1*t,e)},m.format=function(t){var e=this,n=this.$locale();if(!this.isValid())return n.invalidDate||l;var r=t||"YYYY-MM-DDTHH:mm:ssZ",i=b.z(this),s=this.$H,u=this.$m,a=this.$M,o=n.weekdays,c=n.months,f=n.meridiem,h=function(t,n,i,s){return t&&(t[n]||t(e,r))||i[n].slice(0,s)},d=function(t){return b.s(s%12||12,t,"0")},$=f||function(t,e,n){var r=t<12?"AM":"PM";return n?r.toLowerCase():r};return r.replace(y,(function(t,r){return r||function(t){switch(t){case"YY":return String(e.$y).slice(-2);case"YYYY":return b.s(e.$y,4,"0");case"M":return a+1;case"MM":return b.s(a+1,2,"0");case"MMM":return h(n.monthsShort,a,c,3);case"MMMM":return h(c,a);case"D":return e.$D;case"DD":return b.s(e.$D,2,"0");case"d":return String(e.$W);case"dd":return h(n.weekdaysMin,e.$W,o,2);case"ddd":return h(n.weekdaysShort,e.$W,o,3);case"dddd":return o[e.$W];case"H":return String(s);case"HH":return b.s(s,2,"0");case"h":return d(1);case"hh":return d(2);case"a":return $(s,u,!0);case"A":return $(s,u,!1);case"m":return String(u);case"mm":return b.s(u,2,"0");case"s":return String(e.$s);case"ss":return b.s(e.$s,2,"0");case"SSS":return b.s(e.$ms,3,"0");case"Z":return i}return null}(t)||i.replace(":","")}))},m.utcOffset=function(){return 15*-Math.round(this.$d.getTimezoneOffset()/15)},m.diff=function(r,d,l){var $,y=this,M=b.p(d),m=O(r),v=(m.utcOffset()-this.utcOffset())*e,g=this-m,D=function(){return b.m(y,m)};switch(M){case h:$=D()/12;break;case c:$=D();break;case f:$=D()/3;break;case o:$=(g-v)/6048e5;break;case a:$=(g-v)/864e5;break;case u:$=g/n;break;case s:$=g/e;break;case i:$=g/t;break;default:$=g;}return l?$:b.a($)},m.daysInMonth=function(){return this.endOf(c).$D},m.$locale=function(){return D[this.$L]},m.locale=function(t,e){if(!t)return this.$L;var n=this.clone(),r=w(t,e,!0);return r&&(n.$L=r),n},m.clone=function(){return b.w(this.$d,this)},m.toDate=function(){return new Date(this.valueOf())},m.toJSON=function(){return this.isValid()?this.toISOString():null},m.toISOString=function(){return this.$d.toISOString()},m.toString=function(){return this.$d.toUTCString()},M}(),k=_.prototype;return O.prototype=k,[["$ms",r],["$s",i],["$m",s],["$H",u],["$W",a],["$M",c],["$y",h],["$D",d]].forEach((function(t){k[t[1]]=function(e){return this.$g(e,t[0],t[1])};})),O.extend=function(t,e){return t.$i||(t(e,_,O),t.$i=!0),O},O.locale=w,O.isDayjs=S,O.unix=function(t){return O(1e3*t)},O.en=D[g],O.Ls=D,O.p={},O}));
22788
- } (dayjs_min));
22870
+ const errnoMap = {};
22871
+ const xsEncrypt = new XsEncrypt();
22872
+ const mockAction = async (task, params) => {
22873
+ const tmpCachePath = task.getTmpPath();
22874
+ const a1Cookie = params.cookies.find((it) => it.name === "a1")?.value;
22875
+ if (!a1Cookie) {
22876
+ throw new Error("\u672A\u83B7\u53D6\u5230 a1 cookie");
22877
+ }
22878
+ const api = axios$1.create({
22879
+ headers: {
22880
+ cookie: params.cookies.map((it) => `${it.name}=${it.value}`).join(";"),
22881
+ origin: "https://creator.xiaohongshu.com",
22882
+ referer: "https://creator.xiaohongshu.com/",
22883
+ "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"
22884
+ }
22885
+ });
22886
+ api.interceptors.response.use(
22887
+ (response) => {
22888
+ const responseData = response.data;
22889
+ if (responseData?.code && responseData.code !== 0) {
22890
+ const errmsg = errnoMap[responseData.code] || response.config.defaultErrorMsg || "Unknown error";
22891
+ task.logger.error(errmsg, responseData);
22892
+ return Promise.reject(new Error(errmsg));
22893
+ }
22894
+ return response;
22895
+ },
22896
+ (error) => {
22897
+ task.logger.error("\u5C0F\u7EA2\u4E66\u63A5\u53E3\u8BF7\u6C42\u5931\u8D25", error);
22898
+ return Promise.reject(error);
22899
+ }
22900
+ );
22901
+ const fetchCoverUrl = `/api/media/v1/upload/creator/permit?biz_name=spectrum&scene=image&file_count=${params.banners.length}&version=1&source=web`;
22902
+ const xt = Date.now().toString();
22903
+ const xs = await xsEncrypt.encryptXs(fetchCoverUrl, a1Cookie, xt);
22904
+ const coverIdInfo = await api({
22905
+ method: "get",
22906
+ baseURL: "https://creator.xiaohongshu.com",
22907
+ url: fetchCoverUrl,
22908
+ defaultErrorMsg: "\u83B7\u53D6\u4E0A\u4F20\u9644\u4EF6 token \u5931\u8D25",
22909
+ headers: { "x-s": xs, "x-t": xt }
22910
+ });
22911
+ const coverIds = coverIdInfo.data.data.uploadTempPermits[0].fileIds;
22912
+ const ossToken = coverIdInfo.data.data.uploadTempPermits[0].token;
22913
+ const uploadFile = async (url, index) => {
22914
+ const fileName = getFilenameFromUrl(url);
22915
+ const localUrl = await downloadImage(url, path__default.join(tmpCachePath, fileName));
22916
+ const ossFileId = coverIds[index];
22917
+ const fileBuffer = __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c____default.readFileSync(localUrl);
22918
+ await api.put(`https://ros-upload.xiaohongshu.com/${ossFileId}`, fileBuffer, {
22919
+ headers: {
22920
+ "x-cos-security-token": ossToken
22921
+ },
22922
+ defaultErrorMsg: "\u56FE\u7247\u4E0A\u4F20\u51FA\u73B0\u95EE\u9898\uFF0C\u8BF7\u8054\u7CFB\u5BA2\u670D"
22923
+ });
22924
+ return { ossFileId, ossToken };
22925
+ };
22926
+ const coverInfos = await Promise.all(params.banners.map((it, idx) => uploadFile(it, idx)));
22927
+ const publishData = {
22928
+ common: {
22929
+ ats: [],
22930
+ biz_relations: [],
22931
+ desc: params?.content,
22932
+ goods_info: {},
22933
+ hash_tag: [],
22934
+ note_id: "",
22935
+ source: JSON.stringify({
22936
+ type: "web",
22937
+ ids: "",
22938
+ extraInfo: '{"systemId":"web"}'
22939
+ }),
22940
+ title: params?.title,
22941
+ type: "normal",
22942
+ privacy_info: {
22943
+ op_type: 1,
22944
+ type: params.visibleRange === "public" ? 0 : 1
22945
+ },
22946
+ post_loc: params.address ? {
22947
+ name: params.address?.name,
22948
+ poi_id: params.address?.poi_id,
22949
+ poi_type: params.address?.poi_type,
22950
+ subname: params.address?.full_address
22951
+ } : null,
22952
+ business_binds: ""
22953
+ },
22954
+ image_info: {
22955
+ images: coverInfos.map((it) => ({
22956
+ extra_info_json: '{"mimeType":"image/png"}',
22957
+ file_id: it.ossFileId,
22958
+ metadata: { source: -1 },
22959
+ stickers: { floating: [], version: 2 }
22960
+ }))
22961
+ },
22962
+ video_info: null
22963
+ };
22964
+ const userDeclarationBind = {
22965
+ origin: 2,
22966
+ photoInfo: {},
22967
+ repostInfo: {}
22968
+ };
22969
+ if (params.selfDeclaration?.type === "fictional-rendition") {
22970
+ userDeclarationBind.origin = 1;
22971
+ } else if (params.selfDeclaration?.type === "ai-generated") {
22972
+ userDeclarationBind.origin = 2;
22973
+ } else if (params.selfDeclaration?.type === "source-statement") {
22974
+ if (params.selfDeclaration.childType === "self-labeling") {
22975
+ userDeclarationBind.origin = 3;
22976
+ } else if (params.selfDeclaration.childType === "self-shooting") {
22977
+ userDeclarationBind.origin = 4;
22978
+ const photoInfo = {};
22979
+ if (params.selfDeclaration.shootingLocation) {
22980
+ photoInfo.photoPlace = {
22981
+ name: params.selfDeclaration.shootingLocation.name,
22982
+ poiId: params.selfDeclaration.shootingLocation.poi_id,
22983
+ poiType: params.selfDeclaration.shootingLocation.poi_type,
22984
+ subname: params.selfDeclaration.shootingLocation.full_address
22985
+ };
22986
+ }
22987
+ if (params.selfDeclaration.shootingDate) {
22988
+ photoInfo.photoTime = params.selfDeclaration.shootingDate;
22989
+ }
22990
+ userDeclarationBind.photoInfo = photoInfo;
22991
+ } else if (params.selfDeclaration.childType === "transshipment") {
22992
+ userDeclarationBind.origin = 5;
22993
+ if (params.selfDeclaration.sourceMedia) {
22994
+ userDeclarationBind.repostInfo = {
22995
+ source: params.selfDeclaration.sourceMedia
22996
+ };
22997
+ }
22998
+ }
22999
+ }
23000
+ const business_binds = {
23001
+ version: 1,
23002
+ bizType: "",
23003
+ noteId: "",
23004
+ noteOrderBind: {},
23005
+ // 发布时间 - 立即发布/定时发布
23006
+ notePostTiming: params.isImmediatelyPublish ? {} : { postTime: params.scheduledPublish },
23007
+ noteCollectionBind: { id: "" },
23008
+ ...params.selfDeclaration ? { userDeclarationBind } : {}
23009
+ };
23010
+ publishData.common.business_binds = JSON.stringify(business_binds);
23011
+ const publishDataStr = xsEncrypt.dumps(publishData);
23012
+ const publishXt = Date.now().toString();
23013
+ const publishXs = await xsEncrypt.encryptXs(`/web_api/sns/v2/note${publishDataStr}`, a1Cookie, publishXt);
23014
+ const publishResult = await api({
23015
+ method: "post",
23016
+ url: "https://edith.xiaohongshu.com/web_api/sns/v2/note",
23017
+ data: publishData,
23018
+ headers: {
23019
+ "x-s": publishXs,
23020
+ "x-t": publishXt
23021
+ },
23022
+ defaultErrorMsg: "\u6587\u7AE0\u53D1\u5E03\u51FA\u73B0\u95EE\u9898\uFF0C\u8BF7\u8054\u7CFB\u5BA2\u670D"
23023
+ });
23024
+ return publishResult.data.data.id;
23025
+ };
22789
23026
 
22790
23027
  const rpaAction = async (task, params) => {
22791
23028
  const commonCookies = {
@@ -22934,9 +23171,22 @@ const rpaAction = async (task, params) => {
22934
23171
  return response;
22935
23172
  };
22936
23173
 
23174
+ const executeAction = (task, params) => {
23175
+ return new Promise((resolve, reject) => {
23176
+ mockAction(task, params).then(resolve).catch(() => {
23177
+ rpaAction(task, params).then(resolve).catch(reject);
23178
+ });
23179
+ });
23180
+ };
22937
23181
  const xiaohongshuPublish = async (task, params) => {
22938
23182
  task.logger.info("\u5F00\u59CB\u5C0F\u7EA2\u4E66\u53D1\u5E03");
22939
- return rpaAction(task, params);
23183
+ if (params.actionType === "rpa") {
23184
+ return rpaAction(task, params);
23185
+ }
23186
+ if (params.actionType === "mockApi") {
23187
+ return mockAction(task, params);
23188
+ }
23189
+ return executeAction(task, params);
22940
23190
  };
22941
23191
 
22942
23192
  class Action {
package/dist/index.mjs CHANGED
@@ -14,6 +14,8 @@ import require$$4$1 from 'assert';
14
14
  import require$$0$1 from 'tty';
15
15
  import zlib from 'zlib';
16
16
  import { EventEmitter } from 'events';
17
+ import { Buffer as Buffer$1 } from 'node:buffer';
18
+ import crypto from 'node:crypto';
17
19
 
18
20
  function ensureFile(filePath) {
19
21
  return new Promise((resolve, reject)=>{
@@ -937,8 +939,6 @@ AxiosError.from = (error, code, config, request, response, customProps) => {
937
939
  return axiosError;
938
940
  };
939
941
 
940
- var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
941
-
942
942
  function getDefaultExportFromCjs (x) {
943
943
  return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
944
944
  }
@@ -21597,7 +21597,7 @@ const replaceImgSrc = (html, callback) => {
21597
21597
  return lastedHtml;
21598
21598
  };
21599
21599
 
21600
- const errnoMap$2 = {
21600
+ const errnoMap$3 = {
21601
21601
  20040706: "\u6B63\u6587\u56FE\u7247\u548C\u5C01\u9762\u56FE\u7247\u63A8\u8350jpg\u3001png\u683C\u5F0F\u3002",
21602
21602
  20040084: "\u6B63\u6587\u56FE\u7247\u548C\u5C01\u9762\u56FE\u7247\u63A8\u8350jpg\u3001png\u683C\u5F0F\u3002",
21603
21603
  20050004: "\u4ECA\u65E5\u767E\u5BB6\u53F7\u53D1\u5E03\u6B21\u6570\u5DF2\u8FBE\u4E0A\u9650\uFF0C\u8BF7\u660E\u5929\u518D\u8BD5\u3002",
@@ -21609,7 +21609,7 @@ const errnoMap$2 = {
21609
21609
  2004005714: "\u7F51\u7EDC\u73AF\u5883\u5F02\u5E38\uFF0C\u8BF7\u68C0\u67E5\u7F51\u7EDC\u540E\u91CD\u8BD5\u53D1\u5E03\u3002",
21610
21610
  401100032: "\u5F02\u5E38\uFF0C\u8BF7\u68C0\u67E5\u56FE\u7247\uFF08\u5982\uFF1A\u683C\u5F0F\u3001\u7248\u6743\u3001\u5408\u89C4\u6027\u7B49\uFF09\u3002"
21611
21611
  };
21612
- const mockAction$4 = async (task, params) => {
21612
+ const mockAction$5 = async (task, params) => {
21613
21613
  const { baijiahaoSingleCover, baijiahaoMultCover, baijiahaoCoverType } = params.settingInfo;
21614
21614
  const tmpCachePath = task.getTmpPath();
21615
21615
  const api = axios$1.create({
@@ -21621,7 +21621,7 @@ const mockAction$4 = async (task, params) => {
21621
21621
  api.interceptors.response.use(
21622
21622
  (response) => {
21623
21623
  if (response.data.errno !== 0) {
21624
- const errmsg = response.data.errno === 2005e4 ? (params.saveType === "draft" ? "\u540C\u6B65" : "\u53D1\u5E03") + errnoMap$2[response.data.errno] : response.data.errno === 401100032 ? "\u56FE\u7247" + (params.saveType === "draft" ? "\u540C\u6B65" : "\u53D1\u5E03") + errnoMap$2[response.data.errno] : errnoMap$2[response.data.errno] || response.config.defaultErrorMsg || (params.saveType === "draft" ? "\u6587\u7AE0\u540C\u6B65\u5F02\u5E38\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002" : "\u6587\u7AE0\u53D1\u5E03\u5F02\u5E38\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002");
21624
+ const errmsg = response.data.errno === 2005e4 ? (params.saveType === "draft" ? "\u540C\u6B65" : "\u53D1\u5E03") + errnoMap$3[response.data.errno] : response.data.errno === 401100032 ? "\u56FE\u7247" + (params.saveType === "draft" ? "\u540C\u6B65" : "\u53D1\u5E03") + errnoMap$3[response.data.errno] : errnoMap$3[response.data.errno] || response.config.defaultErrorMsg || (params.saveType === "draft" ? "\u6587\u7AE0\u540C\u6B65\u5F02\u5E38\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002" : "\u6587\u7AE0\u53D1\u5E03\u5F02\u5E38\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002");
21625
21625
  task.logger.error(errmsg);
21626
21626
  return Promise.reject(new Error(errmsg));
21627
21627
  }
@@ -21740,7 +21740,7 @@ const mockAction$4 = async (task, params) => {
21740
21740
 
21741
21741
  const baijiahaoPublish = async (task, params) => {
21742
21742
  task.logger.info("\u5F00\u59CB\u767E\u5BB6\u53F7\u53D1\u5E03");
21743
- return mockAction$4(task, params);
21743
+ return mockAction$5(task, params);
21744
21744
  };
21745
21745
 
21746
21746
  const getBaijiahaoActivity = async (task, params) => {
@@ -21870,7 +21870,7 @@ const COVER_TYPE = {
21870
21870
  single: 2,
21871
21871
  multiple: 3
21872
21872
  };
21873
- const errnoMap$1 = {
21873
+ const errnoMap$2 = {
21874
21874
  20004020: "\u56FE\u7247\u4E0A\u4F20\u5F02\u5E38\uFF0C\u8BF7\u91CD\u65B0\u7ED1\u5B9A\u8D26\u53F7\u540E\u540C\u6B65\u3002",
21875
21875
  7115: "\u6B63\u6587\u56FE\u7247\u548C\u5C01\u9762\u56FE\u7247\u63A8\u8350jpg\u3001png\u683C\u5F0F\u3002",
21876
21876
  100006: "\u6587\u7AE0\u540C\u6B65\u5F02\u5E38\uFF0C\u8BF7\u91CD\u65B0\u7ED1\u5B9A\u8D26\u53F7\u540E\u91CD\u8BD5\u3002",
@@ -21894,7 +21894,7 @@ const get3101DetailError = (errorList, message, saveType) => {
21894
21894
  }
21895
21895
  return error || (saveType === "draft" ? "\u6587\u7AE0\u540C\u6B65\u5F02\u5E38\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002" : "\u6587\u7AE0\u53D1\u5E03\u5F02\u5E38\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002");
21896
21896
  };
21897
- const mockAction$3 = async (task, params) => {
21897
+ const mockAction$4 = async (task, params) => {
21898
21898
  const { toutiaoSingleCover, toutiaoMultCover, toutiaoCoverType, toutiaoOriginal } = params.settingInfo;
21899
21899
  const tmpCachePath = task.getTmpPath();
21900
21900
  const api = axios$1.create({
@@ -21908,10 +21908,10 @@ const mockAction$3 = async (task, params) => {
21908
21908
  (response) => {
21909
21909
  if (response.data.code !== 0) {
21910
21910
  let errmsg = "";
21911
- if (Array.isArray(errnoMap$1[response.data.code])) {
21912
- errmsg = get3101DetailError(errnoMap$1[response.data.code], response.data.message, params.saveType);
21911
+ if (Array.isArray(errnoMap$2[response.data.code])) {
21912
+ errmsg = get3101DetailError(errnoMap$2[response.data.code], response.data.message, params.saveType);
21913
21913
  } else {
21914
- errmsg = errnoMap$1[response.data.code] || response.config.defaultErrorMsg || (params.saveType === "draft" ? "\u6587\u7AE0\u540C\u6B65\u5F02\u5E38\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002" : "\u6587\u7AE0\u53D1\u5E03\u5F02\u5E38\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002");
21914
+ errmsg = errnoMap$2[response.data.code] || response.config.defaultErrorMsg || (params.saveType === "draft" ? "\u6587\u7AE0\u540C\u6B65\u5F02\u5E38\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002" : "\u6587\u7AE0\u53D1\u5E03\u5F02\u5E38\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002");
21915
21915
  }
21916
21916
  task.logger.error(errmsg);
21917
21917
  return Promise.reject(new Error(errmsg));
@@ -22059,10 +22059,10 @@ const mockAction$3 = async (task, params) => {
22059
22059
 
22060
22060
  const toutiaoPublish = async (task, params) => {
22061
22061
  task.logger.info("\u5F00\u59CB\u5934\u6761\u53D1\u5E03");
22062
- return mockAction$3(task, params);
22062
+ return mockAction$4(task, params);
22063
22063
  };
22064
22064
 
22065
- const mockAction$2 = async (task, params) => {
22065
+ const mockAction$3 = async (task, params) => {
22066
22066
  const tmpCachePath = task.getTmpPath();
22067
22067
  const api = axios$1.create({
22068
22068
  headers: {
@@ -22193,9 +22193,9 @@ const rpaAction$2 = async (task, params) => {
22193
22193
  await page.locator(".footer-wrap button.publish-content").click();
22194
22194
  };
22195
22195
 
22196
- const executeAction$1 = (task, params) => {
22196
+ const executeAction$2 = (task, params) => {
22197
22197
  return new Promise((resolve, reject) => {
22198
- mockAction$2(task, params).then(resolve).catch(() => {
22198
+ mockAction$3(task, params).then(resolve).catch(() => {
22199
22199
  rpaAction$2(task, params).then(resolve).catch(reject);
22200
22200
  });
22201
22201
  });
@@ -22206,13 +22206,13 @@ const weitoutiaoPublish = async (task, params) => {
22206
22206
  return rpaAction$2(task, params);
22207
22207
  }
22208
22208
  if (params.actionType === "mockApi") {
22209
- return mockAction$2(task, params);
22209
+ return mockAction$3(task, params);
22210
22210
  }
22211
- return executeAction$1(task, params);
22211
+ return executeAction$2(task, params);
22212
22212
  };
22213
22213
 
22214
22214
  const scanRetryMaxCount = 30;
22215
- const errnoMap = {
22215
+ const errnoMap$1 = {
22216
22216
  200003: "\u767B\u5F55\u5931\u6548"
22217
22217
  };
22218
22218
  const saveDraft$1 = (api, params, data) => {
@@ -22310,7 +22310,7 @@ const massSend = async (api, params, data) => {
22310
22310
  });
22311
22311
  return res;
22312
22312
  };
22313
- const mockAction$1 = async (task, params) => {
22313
+ const mockAction$2 = async (task, params) => {
22314
22314
  const tmpCachePath = task.getTmpPath();
22315
22315
  const api = axios$1.create({
22316
22316
  headers: {
@@ -22322,7 +22322,7 @@ const mockAction$1 = async (task, params) => {
22322
22322
  (response) => {
22323
22323
  const responseData = response.data;
22324
22324
  if (responseData?.base_resp && responseData.base_resp.ret !== 0) {
22325
- const errmsg = errnoMap[responseData.base_resp.ret] || response.config.defaultErrorMsg || responseData.base_resp.err_msg || "Unknown error";
22325
+ const errmsg = errnoMap$1[responseData.base_resp.ret] || response.config.defaultErrorMsg || responseData.base_resp.err_msg || "Unknown error";
22326
22326
  task.logger.error(errmsg, responseData);
22327
22327
  return Promise.reject(new Error(errmsg));
22328
22328
  }
@@ -22531,7 +22531,7 @@ const mockAction$1 = async (task, params) => {
22531
22531
 
22532
22532
  const weixinPublish = async (task, params) => {
22533
22533
  task.logger.info("\u5F00\u59CB\u5FAE\u4FE1\u516C\u4F17\u53F7\u53D1\u5E03");
22534
- return mockAction$1(task, params);
22534
+ return mockAction$2(task, params);
22535
22535
  };
22536
22536
 
22537
22537
  const saveDraft = (api, params, data) => {
@@ -22552,7 +22552,7 @@ const saveDraft = (api, params, data) => {
22552
22552
  data: formData
22553
22553
  });
22554
22554
  };
22555
- const mockAction = async (task, params) => {
22555
+ const mockAction$1 = async (task, params) => {
22556
22556
  const tmpCachePath = task.getTmpPath();
22557
22557
  const api = axios$1.create({
22558
22558
  headers: {
@@ -22733,9 +22733,9 @@ const rpaAction$1 = async (task, params) => {
22733
22733
  }
22734
22734
  };
22735
22735
 
22736
- const executeAction = (task, params) => {
22736
+ const executeAction$1 = (task, params) => {
22737
22737
  return new Promise((resolve, reject) => {
22738
- mockAction(task, params).then(resolve).catch(() => {
22738
+ mockAction$1(task, params).then(resolve).catch(() => {
22739
22739
  rpaAction$1(task, params).then(resolve).catch(reject);
22740
22740
  });
22741
22741
  });
@@ -22746,16 +22746,252 @@ const weixinmpPublish = async (task, params) => {
22746
22746
  return rpaAction$1(task, params);
22747
22747
  }
22748
22748
  if (params.actionType === "mockApi") {
22749
- return mockAction(task, params);
22749
+ return mockAction$1(task, params);
22750
22750
  }
22751
- return executeAction(task, params);
22751
+ return executeAction$1(task, params);
22752
22752
  };
22753
22753
 
22754
- var dayjs_min = {exports: {}};
22754
+ var __defProp = Object.defineProperty;
22755
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
22756
+ var __publicField = (obj, key, value) => {
22757
+ __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
22758
+ return value;
22759
+ };
22760
+ class XsEncrypt {
22761
+ constructor() {
22762
+ __publicField(this, "words", [929260340, 1633971297, 895580464, 925905270]);
22763
+ __publicField(this, "keyBytes", Buffer$1.concat(
22764
+ this.words.map(
22765
+ (word) => new Uint8Array(Buffer$1.from([word >> 24 & 255, word >> 16 & 255, word >> 8 & 255, word & 255]))
22766
+ )
22767
+ ));
22768
+ __publicField(this, "iv", Buffer$1.from("4uzjr7mbsibcaldp", "utf8"));
22769
+ }
22770
+ /**
22771
+ * 根据传入的url生成MD5摘要
22772
+ *
22773
+ * @param {string} url - API的url
22774
+ * @returns {string} MD5摘要
22775
+ */
22776
+ async encryptMD5(url) {
22777
+ return crypto.createHash("md5").update(url, "utf8").digest("hex");
22778
+ }
22779
+ /**
22780
+ * 根据传入的text生成AES加密后的内容,并将其转为base64编码
22781
+ *
22782
+ * @param {string} text - 需要加密的字符串
22783
+ * @returns {string} 加密后的base64编码字符串
22784
+ */
22785
+ async encryptText(text) {
22786
+ const textEncoded = Buffer$1.from(text).toString("base64");
22787
+ const cipher = crypto.createCipheriv("aes-128-cbc", new Uint8Array(this.keyBytes), new Uint8Array(this.iv));
22788
+ const ciphertext = cipher.update(textEncoded, "utf8", "base64");
22789
+ return ciphertext + cipher.final("base64");
22790
+ }
22791
+ /**
22792
+ * 把加密后的payload转为16进制
22793
+ *
22794
+ * @param {string} encodedData - 加密后的payload(Base64编码)
22795
+ * @returns {string} 十六进制字符串
22796
+ */
22797
+ async base64ToHex(encodedData) {
22798
+ const decodedData = Buffer$1.from(encodedData, "base64");
22799
+ return decodedData.toString("hex");
22800
+ }
22801
+ /**
22802
+ * 把小红书加密参数payload转16进制 再使用base64编码
22803
+ *
22804
+ * @param {string} payload - 要加密处理的payload内容
22805
+ * @param {string} platform - 登录平台
22806
+ * @returns {string} 加密后并进行base64编码的字符串
22807
+ */
22808
+ async encryptPayload(payload, platform) {
22809
+ const hexPayload = await this.base64ToHex(payload);
22810
+ const obj = {
22811
+ signSvn: "56",
22812
+ signType: "x2",
22813
+ appID: platform,
22814
+ signVersion: "1",
22815
+ payload: hexPayload
22816
+ };
22817
+ const jsonString = JSON.stringify(obj, null, 0);
22818
+ return Buffer$1.from(jsonString).toString("base64");
22819
+ }
22820
+ /**
22821
+ * 将传入的参数加密为小红书的xs
22822
+ * Args: url: API请求的URL
22823
+ * a1: 签名参数a1
22824
+ * ts: 时间戳
22825
+ * platform: 登录平台 默认为xhs-pc-web
22826
+ * Returns:
22827
+ * 最终的加密签名字符串,前缀为“XYW_”
22828
+ */
22829
+ async encryptXs(url, a1, ts, platform = "xhs-pc-web") {
22830
+ const text = `x1=${await this.encryptMD5(`url=${url}`)};x2=0|0|0|1|0|0|1|0|0|0|1|0|0|0|0|1|0|0|0;x3=${a1};x4=${ts};`;
22831
+ return `XYW_${await this.encryptPayload(await this.encryptText(text), platform)}`;
22832
+ }
22833
+ dumps(...rest) {
22834
+ const [data, replacer = null, space = 0] = rest;
22835
+ return JSON.stringify(data, replacer, space).replace(/\n/g, "").replace(/":\s+"/g, '":"');
22836
+ }
22837
+ }
22755
22838
 
22756
- (function (module, exports) {
22757
- !function(t,e){module.exports=e();}(commonjsGlobal,(function(){var t=1e3,e=6e4,n=36e5,r="millisecond",i="second",s="minute",u="hour",a="day",o="week",c="month",f="quarter",h="year",d="date",l="Invalid Date",$=/^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[Tt\s]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?[.:]?(\d+)?$/,y=/\[([^\]]+)]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g,M={name:"en",weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),ordinal:function(t){var e=["th","st","nd","rd"],n=t%100;return "["+t+(e[(n-20)%10]||e[n]||e[0])+"]"}},m=function(t,e,n){var r=String(t);return !r||r.length>=e?t:""+Array(e+1-r.length).join(n)+t},v={s:m,z:function(t){var e=-t.utcOffset(),n=Math.abs(e),r=Math.floor(n/60),i=n%60;return (e<=0?"+":"-")+m(r,2,"0")+":"+m(i,2,"0")},m:function t(e,n){if(e.date()<n.date())return -t(n,e);var r=12*(n.year()-e.year())+(n.month()-e.month()),i=e.clone().add(r,c),s=n-i<0,u=e.clone().add(r+(s?-1:1),c);return +(-(r+(n-i)/(s?i-u:u-i))||0)},a:function(t){return t<0?Math.ceil(t)||0:Math.floor(t)},p:function(t){return {M:c,y:h,w:o,d:a,D:d,h:u,m:s,s:i,ms:r,Q:f}[t]||String(t||"").toLowerCase().replace(/s$/,"")},u:function(t){return void 0===t}},g="en",D={};D[g]=M;var p="$isDayjsObject",S=function(t){return t instanceof _||!(!t||!t[p])},w=function t(e,n,r){var i;if(!e)return g;if("string"==typeof e){var s=e.toLowerCase();D[s]&&(i=s),n&&(D[s]=n,i=s);var u=e.split("-");if(!i&&u.length>1)return t(u[0])}else {var a=e.name;D[a]=e,i=a;}return !r&&i&&(g=i),i||!r&&g},O=function(t,e){if(S(t))return t.clone();var n="object"==typeof e?e:{};return n.date=t,n.args=arguments,new _(n)},b=v;b.l=w,b.i=S,b.w=function(t,e){return O(t,{locale:e.$L,utc:e.$u,x:e.$x,$offset:e.$offset})};var _=function(){function M(t){this.$L=w(t.locale,null,!0),this.parse(t),this.$x=this.$x||t.x||{},this[p]=!0;}var m=M.prototype;return m.parse=function(t){this.$d=function(t){var e=t.date,n=t.utc;if(null===e)return new Date(NaN);if(b.u(e))return new Date;if(e instanceof Date)return new Date(e);if("string"==typeof e&&!/Z$/i.test(e)){var r=e.match($);if(r){var i=r[2]-1||0,s=(r[7]||"0").substring(0,3);return n?new Date(Date.UTC(r[1],i,r[3]||1,r[4]||0,r[5]||0,r[6]||0,s)):new Date(r[1],i,r[3]||1,r[4]||0,r[5]||0,r[6]||0,s)}}return new Date(e)}(t),this.init();},m.init=function(){var t=this.$d;this.$y=t.getFullYear(),this.$M=t.getMonth(),this.$D=t.getDate(),this.$W=t.getDay(),this.$H=t.getHours(),this.$m=t.getMinutes(),this.$s=t.getSeconds(),this.$ms=t.getMilliseconds();},m.$utils=function(){return b},m.isValid=function(){return !(this.$d.toString()===l)},m.isSame=function(t,e){var n=O(t);return this.startOf(e)<=n&&n<=this.endOf(e)},m.isAfter=function(t,e){return O(t)<this.startOf(e)},m.isBefore=function(t,e){return this.endOf(e)<O(t)},m.$g=function(t,e,n){return b.u(t)?this[e]:this.set(n,t)},m.unix=function(){return Math.floor(this.valueOf()/1e3)},m.valueOf=function(){return this.$d.getTime()},m.startOf=function(t,e){var n=this,r=!!b.u(e)||e,f=b.p(t),l=function(t,e){var i=b.w(n.$u?Date.UTC(n.$y,e,t):new Date(n.$y,e,t),n);return r?i:i.endOf(a)},$=function(t,e){return b.w(n.toDate()[t].apply(n.toDate("s"),(r?[0,0,0,0]:[23,59,59,999]).slice(e)),n)},y=this.$W,M=this.$M,m=this.$D,v="set"+(this.$u?"UTC":"");switch(f){case h:return r?l(1,0):l(31,11);case c:return r?l(1,M):l(0,M+1);case o:var g=this.$locale().weekStart||0,D=(y<g?y+7:y)-g;return l(r?m-D:m+(6-D),M);case a:case d:return $(v+"Hours",0);case u:return $(v+"Minutes",1);case s:return $(v+"Seconds",2);case i:return $(v+"Milliseconds",3);default:return this.clone()}},m.endOf=function(t){return this.startOf(t,!1)},m.$set=function(t,e){var n,o=b.p(t),f="set"+(this.$u?"UTC":""),l=(n={},n[a]=f+"Date",n[d]=f+"Date",n[c]=f+"Month",n[h]=f+"FullYear",n[u]=f+"Hours",n[s]=f+"Minutes",n[i]=f+"Seconds",n[r]=f+"Milliseconds",n)[o],$=o===a?this.$D+(e-this.$W):e;if(o===c||o===h){var y=this.clone().set(d,1);y.$d[l]($),y.init(),this.$d=y.set(d,Math.min(this.$D,y.daysInMonth())).$d;}else l&&this.$d[l]($);return this.init(),this},m.set=function(t,e){return this.clone().$set(t,e)},m.get=function(t){return this[b.p(t)]()},m.add=function(r,f){var d,l=this;r=Number(r);var $=b.p(f),y=function(t){var e=O(l);return b.w(e.date(e.date()+Math.round(t*r)),l)};if($===c)return this.set(c,this.$M+r);if($===h)return this.set(h,this.$y+r);if($===a)return y(1);if($===o)return y(7);var M=(d={},d[s]=e,d[u]=n,d[i]=t,d)[$]||1,m=this.$d.getTime()+r*M;return b.w(m,this)},m.subtract=function(t,e){return this.add(-1*t,e)},m.format=function(t){var e=this,n=this.$locale();if(!this.isValid())return n.invalidDate||l;var r=t||"YYYY-MM-DDTHH:mm:ssZ",i=b.z(this),s=this.$H,u=this.$m,a=this.$M,o=n.weekdays,c=n.months,f=n.meridiem,h=function(t,n,i,s){return t&&(t[n]||t(e,r))||i[n].slice(0,s)},d=function(t){return b.s(s%12||12,t,"0")},$=f||function(t,e,n){var r=t<12?"AM":"PM";return n?r.toLowerCase():r};return r.replace(y,(function(t,r){return r||function(t){switch(t){case"YY":return String(e.$y).slice(-2);case"YYYY":return b.s(e.$y,4,"0");case"M":return a+1;case"MM":return b.s(a+1,2,"0");case"MMM":return h(n.monthsShort,a,c,3);case"MMMM":return h(c,a);case"D":return e.$D;case"DD":return b.s(e.$D,2,"0");case"d":return String(e.$W);case"dd":return h(n.weekdaysMin,e.$W,o,2);case"ddd":return h(n.weekdaysShort,e.$W,o,3);case"dddd":return o[e.$W];case"H":return String(s);case"HH":return b.s(s,2,"0");case"h":return d(1);case"hh":return d(2);case"a":return $(s,u,!0);case"A":return $(s,u,!1);case"m":return String(u);case"mm":return b.s(u,2,"0");case"s":return String(e.$s);case"ss":return b.s(e.$s,2,"0");case"SSS":return b.s(e.$ms,3,"0");case"Z":return i}return null}(t)||i.replace(":","")}))},m.utcOffset=function(){return 15*-Math.round(this.$d.getTimezoneOffset()/15)},m.diff=function(r,d,l){var $,y=this,M=b.p(d),m=O(r),v=(m.utcOffset()-this.utcOffset())*e,g=this-m,D=function(){return b.m(y,m)};switch(M){case h:$=D()/12;break;case c:$=D();break;case f:$=D()/3;break;case o:$=(g-v)/6048e5;break;case a:$=(g-v)/864e5;break;case u:$=g/n;break;case s:$=g/e;break;case i:$=g/t;break;default:$=g;}return l?$:b.a($)},m.daysInMonth=function(){return this.endOf(c).$D},m.$locale=function(){return D[this.$L]},m.locale=function(t,e){if(!t)return this.$L;var n=this.clone(),r=w(t,e,!0);return r&&(n.$L=r),n},m.clone=function(){return b.w(this.$d,this)},m.toDate=function(){return new Date(this.valueOf())},m.toJSON=function(){return this.isValid()?this.toISOString():null},m.toISOString=function(){return this.$d.toISOString()},m.toString=function(){return this.$d.toUTCString()},M}(),k=_.prototype;return O.prototype=k,[["$ms",r],["$s",i],["$m",s],["$H",u],["$W",a],["$M",c],["$y",h],["$D",d]].forEach((function(t){k[t[1]]=function(e){return this.$g(e,t[0],t[1])};})),O.extend=function(t,e){return t.$i||(t(e,_,O),t.$i=!0),O},O.locale=w,O.isDayjs=S,O.unix=function(t){return O(1e3*t)},O.en=D[g],O.Ls=D,O.p={},O}));
22758
- } (dayjs_min));
22839
+ const errnoMap = {};
22840
+ const xsEncrypt = new XsEncrypt();
22841
+ const mockAction = async (task, params) => {
22842
+ const tmpCachePath = task.getTmpPath();
22843
+ const a1Cookie = params.cookies.find((it) => it.name === "a1")?.value;
22844
+ if (!a1Cookie) {
22845
+ throw new Error("\u672A\u83B7\u53D6\u5230 a1 cookie");
22846
+ }
22847
+ const api = axios$1.create({
22848
+ headers: {
22849
+ cookie: params.cookies.map((it) => `${it.name}=${it.value}`).join(";"),
22850
+ origin: "https://creator.xiaohongshu.com",
22851
+ referer: "https://creator.xiaohongshu.com/",
22852
+ "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"
22853
+ }
22854
+ });
22855
+ api.interceptors.response.use(
22856
+ (response) => {
22857
+ const responseData = response.data;
22858
+ if (responseData?.code && responseData.code !== 0) {
22859
+ const errmsg = errnoMap[responseData.code] || response.config.defaultErrorMsg || "Unknown error";
22860
+ task.logger.error(errmsg, responseData);
22861
+ return Promise.reject(new Error(errmsg));
22862
+ }
22863
+ return response;
22864
+ },
22865
+ (error) => {
22866
+ task.logger.error("\u5C0F\u7EA2\u4E66\u63A5\u53E3\u8BF7\u6C42\u5931\u8D25", error);
22867
+ return Promise.reject(error);
22868
+ }
22869
+ );
22870
+ const fetchCoverUrl = `/api/media/v1/upload/creator/permit?biz_name=spectrum&scene=image&file_count=${params.banners.length}&version=1&source=web`;
22871
+ const xt = Date.now().toString();
22872
+ const xs = await xsEncrypt.encryptXs(fetchCoverUrl, a1Cookie, xt);
22873
+ const coverIdInfo = await api({
22874
+ method: "get",
22875
+ baseURL: "https://creator.xiaohongshu.com",
22876
+ url: fetchCoverUrl,
22877
+ defaultErrorMsg: "\u83B7\u53D6\u4E0A\u4F20\u9644\u4EF6 token \u5931\u8D25",
22878
+ headers: { "x-s": xs, "x-t": xt }
22879
+ });
22880
+ const coverIds = coverIdInfo.data.data.uploadTempPermits[0].fileIds;
22881
+ const ossToken = coverIdInfo.data.data.uploadTempPermits[0].token;
22882
+ const uploadFile = async (url, index) => {
22883
+ const fileName = getFilenameFromUrl(url);
22884
+ const localUrl = await downloadImage(url, path__default.join(tmpCachePath, fileName));
22885
+ const ossFileId = coverIds[index];
22886
+ const fileBuffer = __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c____default.readFileSync(localUrl);
22887
+ await api.put(`https://ros-upload.xiaohongshu.com/${ossFileId}`, fileBuffer, {
22888
+ headers: {
22889
+ "x-cos-security-token": ossToken
22890
+ },
22891
+ defaultErrorMsg: "\u56FE\u7247\u4E0A\u4F20\u51FA\u73B0\u95EE\u9898\uFF0C\u8BF7\u8054\u7CFB\u5BA2\u670D"
22892
+ });
22893
+ return { ossFileId, ossToken };
22894
+ };
22895
+ const coverInfos = await Promise.all(params.banners.map((it, idx) => uploadFile(it, idx)));
22896
+ const publishData = {
22897
+ common: {
22898
+ ats: [],
22899
+ biz_relations: [],
22900
+ desc: params?.content,
22901
+ goods_info: {},
22902
+ hash_tag: [],
22903
+ note_id: "",
22904
+ source: JSON.stringify({
22905
+ type: "web",
22906
+ ids: "",
22907
+ extraInfo: '{"systemId":"web"}'
22908
+ }),
22909
+ title: params?.title,
22910
+ type: "normal",
22911
+ privacy_info: {
22912
+ op_type: 1,
22913
+ type: params.visibleRange === "public" ? 0 : 1
22914
+ },
22915
+ post_loc: params.address ? {
22916
+ name: params.address?.name,
22917
+ poi_id: params.address?.poi_id,
22918
+ poi_type: params.address?.poi_type,
22919
+ subname: params.address?.full_address
22920
+ } : null,
22921
+ business_binds: ""
22922
+ },
22923
+ image_info: {
22924
+ images: coverInfos.map((it) => ({
22925
+ extra_info_json: '{"mimeType":"image/png"}',
22926
+ file_id: it.ossFileId,
22927
+ metadata: { source: -1 },
22928
+ stickers: { floating: [], version: 2 }
22929
+ }))
22930
+ },
22931
+ video_info: null
22932
+ };
22933
+ const userDeclarationBind = {
22934
+ origin: 2,
22935
+ photoInfo: {},
22936
+ repostInfo: {}
22937
+ };
22938
+ if (params.selfDeclaration?.type === "fictional-rendition") {
22939
+ userDeclarationBind.origin = 1;
22940
+ } else if (params.selfDeclaration?.type === "ai-generated") {
22941
+ userDeclarationBind.origin = 2;
22942
+ } else if (params.selfDeclaration?.type === "source-statement") {
22943
+ if (params.selfDeclaration.childType === "self-labeling") {
22944
+ userDeclarationBind.origin = 3;
22945
+ } else if (params.selfDeclaration.childType === "self-shooting") {
22946
+ userDeclarationBind.origin = 4;
22947
+ const photoInfo = {};
22948
+ if (params.selfDeclaration.shootingLocation) {
22949
+ photoInfo.photoPlace = {
22950
+ name: params.selfDeclaration.shootingLocation.name,
22951
+ poiId: params.selfDeclaration.shootingLocation.poi_id,
22952
+ poiType: params.selfDeclaration.shootingLocation.poi_type,
22953
+ subname: params.selfDeclaration.shootingLocation.full_address
22954
+ };
22955
+ }
22956
+ if (params.selfDeclaration.shootingDate) {
22957
+ photoInfo.photoTime = params.selfDeclaration.shootingDate;
22958
+ }
22959
+ userDeclarationBind.photoInfo = photoInfo;
22960
+ } else if (params.selfDeclaration.childType === "transshipment") {
22961
+ userDeclarationBind.origin = 5;
22962
+ if (params.selfDeclaration.sourceMedia) {
22963
+ userDeclarationBind.repostInfo = {
22964
+ source: params.selfDeclaration.sourceMedia
22965
+ };
22966
+ }
22967
+ }
22968
+ }
22969
+ const business_binds = {
22970
+ version: 1,
22971
+ bizType: "",
22972
+ noteId: "",
22973
+ noteOrderBind: {},
22974
+ // 发布时间 - 立即发布/定时发布
22975
+ notePostTiming: params.isImmediatelyPublish ? {} : { postTime: params.scheduledPublish },
22976
+ noteCollectionBind: { id: "" },
22977
+ ...params.selfDeclaration ? { userDeclarationBind } : {}
22978
+ };
22979
+ publishData.common.business_binds = JSON.stringify(business_binds);
22980
+ const publishDataStr = xsEncrypt.dumps(publishData);
22981
+ const publishXt = Date.now().toString();
22982
+ const publishXs = await xsEncrypt.encryptXs(`/web_api/sns/v2/note${publishDataStr}`, a1Cookie, publishXt);
22983
+ const publishResult = await api({
22984
+ method: "post",
22985
+ url: "https://edith.xiaohongshu.com/web_api/sns/v2/note",
22986
+ data: publishData,
22987
+ headers: {
22988
+ "x-s": publishXs,
22989
+ "x-t": publishXt
22990
+ },
22991
+ defaultErrorMsg: "\u6587\u7AE0\u53D1\u5E03\u51FA\u73B0\u95EE\u9898\uFF0C\u8BF7\u8054\u7CFB\u5BA2\u670D"
22992
+ });
22993
+ return publishResult.data.data.id;
22994
+ };
22759
22995
 
22760
22996
  const rpaAction = async (task, params) => {
22761
22997
  const commonCookies = {
@@ -22904,9 +23140,22 @@ const rpaAction = async (task, params) => {
22904
23140
  return response;
22905
23141
  };
22906
23142
 
23143
+ const executeAction = (task, params) => {
23144
+ return new Promise((resolve, reject) => {
23145
+ mockAction(task, params).then(resolve).catch(() => {
23146
+ rpaAction(task, params).then(resolve).catch(reject);
23147
+ });
23148
+ });
23149
+ };
22907
23150
  const xiaohongshuPublish = async (task, params) => {
22908
23151
  task.logger.info("\u5F00\u59CB\u5C0F\u7EA2\u4E66\u53D1\u5E03");
22909
- return rpaAction(task, params);
23152
+ if (params.actionType === "rpa") {
23153
+ return rpaAction(task, params);
23154
+ }
23155
+ if (params.actionType === "mockApi") {
23156
+ return mockAction(task, params);
23157
+ }
23158
+ return executeAction(task, params);
22910
23159
  };
22911
23160
 
22912
23161
  class Action {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iflyrpa/actions",
3
- "version": "1.1.8",
3
+ "version": "1.1.9",
4
4
  "description": "",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.mjs",
@@ -14,7 +14,6 @@
14
14
  "devDependencies": {
15
15
  "@types/mime-types": "^2.1.4",
16
16
  "axios": "^1.7.8",
17
- "dayjs": "^1.11.13",
18
17
  "dom-serializer": "^2.0.0",
19
18
  "domhandler": "^5.0.3",
20
19
  "form-data": "^4.0.1",
@@ -49,15 +49,13 @@ const executeAction: PublishAction = (task, params) => {
49
49
  export const xiaohongshuPublish: PublishAction = async (task, params) => {
50
50
  task.logger.info("开始小红书发布");
51
51
 
52
- return rpaAction(task, params);
52
+ if (params.actionType === "rpa") {
53
+ return rpaAction(task, params);
54
+ }
53
55
 
54
- // if (params.actionType === "rpa") {
55
- // return rpaAction(task, params);
56
- // }
56
+ if (params.actionType === "mockApi") {
57
+ return mockAction(task, params);
58
+ }
57
59
 
58
- // if (params.actionType === "mockApi") {
59
- // return mockAction(task, params);
60
- // }
61
-
62
- // return executeAction(task, params);
60
+ return executeAction(task, params);
63
61
  };
@@ -1,10 +1,9 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
- // import type { CookieMap } from "@iflyrpa/share";
4
- import { downloadImage, getFilenameFromUrl, sleep } from "@iflyrpa/share";
3
+ import { downloadImage, getFilenameFromUrl } from "@iflyrpa/share";
5
4
  import axios, { type AxiosResponse } from "axios";
6
- import dayjs from "dayjs";
7
5
  import type { PublishAction } from ".";
6
+ import { XsEncrypt } from "../../utils/xhsXsEncrypt";
8
7
 
9
8
  interface CommonResponse<T = unknown> {
10
9
  data: T;
@@ -20,35 +19,24 @@ interface UploadTempPermit {
20
19
 
21
20
  const errnoMap: Record<number, string> = {};
22
21
 
23
- // const commonCookies: CookieMap[number] = {
24
- // path: "/",
25
- // sameSite: "lax",
26
- // secure: false,
27
- // domain: "xiaohongshu.com",
28
- // url: "https://creator.xiaohongshu.com",
29
- // httpOnly: true,
30
- // };
22
+ // 小红书参数加密器
23
+ const xsEncrypt = new XsEncrypt();
31
24
 
32
25
  export const mockAction: PublishAction = async (task, params) => {
33
- // const page = await task.createPage({
34
- // show: task.debug,
35
- // url: params.url || "https://creator.xiaohongshu.com/publish/publish",
36
- // cookies: params.cookies?.map((it) => ({ ...commonCookies, ...it })) || [],
37
- // });
38
26
  const tmpCachePath = task.getTmpPath();
39
27
 
40
- await sleep(5000);
41
-
42
- const fetchCoverArg = `/api/media/v1/upload/creator/permit?biz_name=spectrum&scene=image&file_count=${params.banners.length}&version=1&source=web`;
43
-
44
- // const xsValue = await page.evaluate(([arg]) => window._webmsxyw(), [fetchCoverArg]);
28
+ const a1Cookie = params.cookies.find((it) => it.name === "a1")?.value;
29
+ if (!a1Cookie) {
30
+ throw new Error("未获取到 a1 cookie");
31
+ }
45
32
 
46
33
  const api = axios.create({
47
34
  headers: {
48
35
  cookie: params.cookies.map((it) => `${it.name}=${it.value}`).join(";"),
49
- referer: "https://creator.xiaohongshu.com/publish/publish?source=official&from=tab_switch",
50
- // "x-s": xsValue["X-s"],
51
- // "x-t": xsValue["X-t"],
36
+ origin: "https://creator.xiaohongshu.com",
37
+ referer: "https://creator.xiaohongshu.com/",
38
+ "user-agent":
39
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36",
52
40
  },
53
41
  });
54
42
 
@@ -69,17 +57,22 @@ export const mockAction: PublishAction = async (task, params) => {
69
57
  return response;
70
58
  },
71
59
  (error) => {
72
- task.logger.error("小红书接口请求失败:", error);
60
+ task.logger.error("小红书接口请求失败", error);
73
61
  // 处理响应错误
74
62
  return Promise.reject(error);
75
63
  },
76
64
  );
77
65
 
78
66
  // 0. 获取上传 token
67
+ const fetchCoverUrl = `/api/media/v1/upload/creator/permit?biz_name=spectrum&scene=image&file_count=${params.banners.length}&version=1&source=web`;
68
+ const xt = Date.now().toString();
69
+ const xs = await xsEncrypt.encryptXs(fetchCoverUrl, a1Cookie, xt);
79
70
  const coverIdInfo = await api<{ data: { uploadTempPermits: UploadTempPermit[] } }>({
80
71
  method: "get",
81
- url: `https://creator.xiaohongshu.com${fetchCoverArg}`,
72
+ baseURL: "https://creator.xiaohongshu.com",
73
+ url: fetchCoverUrl,
82
74
  defaultErrorMsg: "获取上传附件 token 失败",
75
+ headers: { "x-s": xs, "x-t": xt },
83
76
  });
84
77
 
85
78
  const coverIds = coverIdInfo.data.data.uploadTempPermits[0].fileIds;
@@ -98,7 +91,7 @@ export const mockAction: PublishAction = async (task, params) => {
98
91
  headers: {
99
92
  "x-cos-security-token": ossToken,
100
93
  },
101
- defaultErrorMsg: "获取上传附件 token 失败",
94
+ defaultErrorMsg: "图片上传出现问题,请联系客服",
102
95
  });
103
96
 
104
97
  return { ossFileId, ossToken };
@@ -139,13 +132,8 @@ export const mockAction: PublishAction = async (task, params) => {
139
132
  images: coverInfos.map((it) => ({
140
133
  extra_info_json: '{"mimeType":"image/png"}',
141
134
  file_id: it.ossFileId,
142
- metadata: {
143
- source: -1,
144
- },
145
- stickers: {
146
- floating: [],
147
- version: 2,
148
- },
135
+ metadata: { source: -1 },
136
+ stickers: { floating: [], version: 2 },
149
137
  })),
150
138
  },
151
139
  video_info: null,
@@ -208,15 +196,29 @@ export const mockAction: PublishAction = async (task, params) => {
208
196
  bizType: "",
209
197
  noteId: "",
210
198
  noteOrderBind: {},
211
- // 发布时间 - 立即发布
212
- notePostTiming: params.isImmediatelyPublish ? { postTime: dayjs().format("YYYY-MM-DD HH:mm") } : {},
199
+ // 发布时间 - 立即发布/定时发布
200
+ notePostTiming: params.isImmediatelyPublish ? {} : { postTime: params.scheduledPublish },
213
201
  noteCollectionBind: { id: "" },
214
202
  ...(params.selfDeclaration ? { userDeclarationBind } : {}),
215
203
  };
216
204
 
217
205
  publishData.common.business_binds = JSON.stringify(business_binds);
218
206
 
219
- console.log(publishData);
207
+ const publishDataStr = xsEncrypt.dumps(publishData);
208
+ const publishXt = Date.now().toString();
209
+ const publishXs = await xsEncrypt.encryptXs(`/web_api/sns/v2/note${publishDataStr}`, a1Cookie, publishXt);
210
+
211
+ // 发布
212
+ const publishResult = await api<CommonResponse<{ id: string }>>({
213
+ method: "post",
214
+ url: "https://edith.xiaohongshu.com/web_api/sns/v2/note",
215
+ data: publishData,
216
+ headers: {
217
+ "x-s": publishXs,
218
+ "x-t": publishXt,
219
+ },
220
+ defaultErrorMsg: "文章发布出现问题,请联系客服",
221
+ });
220
222
 
221
- return Promise.reject();
223
+ return publishResult.data.data.id;
222
224
  };
@@ -0,0 +1,103 @@
1
+ import { Buffer } from "node:buffer";
2
+ import crypto from "node:crypto";
3
+
4
+ /**
5
+ * 小红书加密参数逆向,代码来自:https://github.com/Cloxl/xhshow
6
+ */
7
+ export class XsEncrypt {
8
+ private words = [929260340, 1633971297, 895580464, 925905270];
9
+ private keyBytes = Buffer.concat(
10
+ this.words.map(
11
+ (word) =>
12
+ new Uint8Array(Buffer.from([(word >> 24) & 0xff, (word >> 16) & 0xff, (word >> 8) & 0xff, word & 0xff])),
13
+ ),
14
+ );
15
+ private iv = Buffer.from("4uzjr7mbsibcaldp", "utf8");
16
+
17
+ /**
18
+ * 根据传入的url生成MD5摘要
19
+ *
20
+ * @param {string} url - API的url
21
+ * @returns {string} MD5摘要
22
+ */
23
+ async encryptMD5(url: string): Promise<string> {
24
+ return crypto.createHash("md5").update(url, "utf8").digest("hex");
25
+ }
26
+
27
+ /**
28
+ * 根据传入的text生成AES加密后的内容,并将其转为base64编码
29
+ *
30
+ * @param {string} text - 需要加密的字符串
31
+ * @returns {string} 加密后的base64编码字符串
32
+ */
33
+ async encryptText(text: string): Promise<string> {
34
+ // 将文本编码为 Base64
35
+ const textEncoded = Buffer.from(text).toString("base64");
36
+ // 创建 AES 加密器
37
+ const cipher = crypto.createCipheriv("aes-128-cbc", new Uint8Array(this.keyBytes), new Uint8Array(this.iv));
38
+ // 对数据进行填充
39
+ const ciphertext = cipher.update(textEncoded, "utf8", "base64");
40
+ return ciphertext + cipher.final("base64");
41
+ }
42
+
43
+ /**
44
+ * 把加密后的payload转为16进制
45
+ *
46
+ * @param {string} encodedData - 加密后的payload(Base64编码)
47
+ * @returns {string} 十六进制字符串
48
+ */
49
+ async base64ToHex(encodedData: string): Promise<string> {
50
+ // 将 Base64 字符串解码为二进制数据
51
+ const decodedData = Buffer.from(encodedData, "base64");
52
+ // 将二进制数据转换为十六进制字符串
53
+ return decodedData.toString("hex");
54
+ }
55
+
56
+ /**
57
+ * 把小红书加密参数payload转16进制 再使用base64编码
58
+ *
59
+ * @param {string} payload - 要加密处理的payload内容
60
+ * @param {string} platform - 登录平台
61
+ * @returns {string} 加密后并进行base64编码的字符串
62
+ */
63
+ async encryptPayload(payload: string, platform: string): Promise<string> {
64
+ // 将 payload 转换为十六进制
65
+ const hexPayload = await this.base64ToHex(payload);
66
+
67
+ // 构造对象
68
+ const obj = {
69
+ signSvn: "56",
70
+ signType: "x2",
71
+ appID: platform,
72
+ signVersion: "1",
73
+ payload: hexPayload,
74
+ };
75
+
76
+ // 将对象转换为 JSON 字符串(紧凑格式)
77
+ const jsonString = JSON.stringify(obj, null, 0);
78
+
79
+ // 对 JSON 字符串进行 Base64 编码
80
+ return Buffer.from(jsonString).toString("base64");
81
+ }
82
+
83
+ /**
84
+ * 将传入的参数加密为小红书的xs
85
+ * Args: url: API请求的URL
86
+ * a1: 签名参数a1
87
+ * ts: 时间戳
88
+ * platform: 登录平台 默认为xhs-pc-web
89
+ * Returns:
90
+ * 最终的加密签名字符串,前缀为“XYW_”
91
+ */
92
+ async encryptXs(url: string, a1: string, ts: string, platform = "xhs-pc-web"): Promise<string> {
93
+ const text = `x1=${await this.encryptMD5(`url=${url}`)};x2=0|0|0|1|0|0|1|0|0|0|1|0|0|0|0|1|0|0|0;x3=${a1};x4=${ts};`;
94
+ return `XYW_${await this.encryptPayload(await this.encryptText(text), platform)}`;
95
+ }
96
+
97
+ dumps(...rest: Parameters<typeof JSON.stringify>): string {
98
+ const [data, replacer = null, space = 0] = rest;
99
+ return JSON.stringify(data, replacer, space)
100
+ .replace(/\n/g, "")
101
+ .replace(/":\s+"/g, '":"');
102
+ }
103
+ }