@iflyrpa/actions 3.0.1 → 3.0.2-beta.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
@@ -5489,9 +5489,7 @@ var __webpack_exports__ = {};
5489
5489
  });
5490
5490
  const package_json_namespaceObject = require("@iflyrpa/share/package.json");
5491
5491
  var package_json_default = /*#__PURE__*/ __webpack_require__.n(package_json_namespaceObject);
5492
- var package_namespaceObject = {
5493
- i8: "3.0.0"
5494
- };
5492
+ var package_namespaceObject = JSON.parse('{"i8":"3.0.2-beta.0"}');
5495
5493
  const share_namespaceObject = require("@iflyrpa/share");
5496
5494
  const external_node_fs_namespaceObject = require("node:fs");
5497
5495
  var external_node_fs_default = /*#__PURE__*/ __webpack_require__.n(external_node_fs_namespaceObject);
@@ -5628,6 +5626,9 @@ var __webpack_exports__ = {};
5628
5626
  case "ERR_BAD_REQUEST":
5629
5627
  _message = "请求出现错误,请检查请求参数!";
5630
5628
  break;
5629
+ case "ERR_BAD_RESPONSE":
5630
+ _message = `服务器响应异常 (${error.response?.status ?? "unknown"}),请稍后重试!`;
5631
+ break;
5631
5632
  case "ERR_CANCELED":
5632
5633
  errorResponse.code = 414;
5633
5634
  _message = "请求连接超时,请稍候重试!";
@@ -5678,6 +5679,9 @@ var __webpack_exports__ = {};
5678
5679
  const isRetry = [
5679
5680
  0,
5680
5681
  500,
5682
+ 502,
5683
+ 503,
5684
+ 504,
5681
5685
  599
5682
5686
  ].includes(handledError.code);
5683
5687
  if (Rtimes < retries && isRetry) {
@@ -9690,7 +9694,7 @@ var __webpack_exports__ = {};
9690
9694
  data: null
9691
9695
  });
9692
9696
  const MockPublish = false;
9693
- const DisabledReq = true;
9697
+ const DisabledReq = false;
9694
9698
  const scanRetryMaxCount = 60;
9695
9699
  const waitQrcodeResultMaxTime = 2000 * scanRetryMaxCount;
9696
9700
  const rpaServer = async (task, params)=>{
@@ -14006,7 +14010,7 @@ var __webpack_exports__ = {};
14006
14010
  this.authCache = null;
14007
14011
  this.authExpireTime = 0;
14008
14012
  this.AUTH_REFRESH_BUFFER = 300000;
14009
- this.CONCURRENT_LIMIT = 5;
14013
+ this.CONCURRENT_LIMIT = 10;
14010
14014
  this.UPLOAD_DELAY = 1000;
14011
14015
  this.UPLOAD_TIMEOUT = 300000;
14012
14016
  this.TOS_UPLOAD_TIMEOUT = 600000;
@@ -14035,16 +14039,17 @@ var __webpack_exports__ = {};
14035
14039
  const aBogus = imageUploader_getABogus(`https://creator.douyin.com/web/api/media/upload/auth/v5/?${queryString}`, {}, this.headers["user-agent"]);
14036
14040
  this.queryParams.a_bogus = aBogus;
14037
14041
  const newQueryString = new URLSearchParams(this.queryParams).toString();
14038
- const uploadAuth = await this.proxyHttp.api({
14039
- method: "get",
14040
- url: `https://creator.douyin.com/web/api/media/upload/auth/v5/?${newQueryString}`,
14041
- headers: {
14042
- ...this.headers,
14043
- "Content-Type": "application/json"
14044
- }
14045
- }, {
14046
- timeout: 300000
14047
- });
14042
+ const uploadAuth = await this.withRetry(()=>this.proxyHttp.api({
14043
+ method: "get",
14044
+ url: `https://creator.douyin.com/web/api/media/upload/auth/v5/?${newQueryString}`,
14045
+ headers: {
14046
+ ...this.headers,
14047
+ "Content-Type": "application/json"
14048
+ }
14049
+ }, {
14050
+ timeout: 300000,
14051
+ retries: 0
14052
+ }), 3, 1000, "获取上传凭证");
14048
14053
  if (!uploadAuth.auth) throw new Error(uploadAuth.status_msg || "获取上传权限失败");
14049
14054
  try {
14050
14055
  const authData = JSON.parse(uploadAuth.auth);
@@ -14084,19 +14089,19 @@ var __webpack_exports__ = {};
14084
14089
  };
14085
14090
  const result = generateAuthorization(addrParamsConfig).authorization;
14086
14091
  const addrParamsQueryString = canonicalQueryString(addrParamsConfig.params);
14087
- const response = await this.proxyHttp.api({
14088
- method: "get",
14089
- url: `https://imagex.bytedanceapi.com/?${addrParamsQueryString}`,
14090
- headers: {
14091
- ...this.headers,
14092
- Authorization: result,
14093
- "Content-Type": "application/json",
14094
- "X-amz-date": amzDate,
14095
- "X-amz-security-token": authData.SessionToken
14096
- }
14097
- }, {
14098
- timeout: this.UPLOAD_TIMEOUT
14099
- });
14092
+ const response = await this.withRetry(()=>this.proxyHttp.api({
14093
+ method: "get",
14094
+ url: `https://imagex.bytedanceapi.com/?${addrParamsQueryString}`,
14095
+ headers: {
14096
+ ...this.headers,
14097
+ Authorization: result,
14098
+ "Content-Type": "application/json",
14099
+ "X-amz-date": amzDate,
14100
+ "X-amz-security-token": authData.SessionToken
14101
+ }
14102
+ }, {
14103
+ timeout: this.UPLOAD_TIMEOUT
14104
+ }), 3, 1000, "获取上传地址");
14100
14105
  if (!response) throw new Error("获取上传地址失败: 响应为空");
14101
14106
  if (response.ResponseMetadata?.Error) throw new Error(`ImageX错误: ${response.ResponseMetadata.Error.Code} - ${response.ResponseMetadata.Error.Message}`);
14102
14107
  if (!response.Result) {
@@ -14127,23 +14132,24 @@ var __webpack_exports__ = {};
14127
14132
  console.log(`上传至: ${uploadUrl.substring(0, 80)}...`);
14128
14133
  console.log(`文件大小: ${imageInfo.size} bytes, CRC32: ${imageInfo.md5}`);
14129
14134
  try {
14130
- const uploadImgResp = await this.proxyHttp.api({
14131
- method: "post",
14132
- url: uploadUrl,
14133
- headers: {
14134
- ...this.headers,
14135
- Authorization: uploadAddr.auth,
14136
- "Content-crc32": imageInfo.md5,
14137
- "Content-Type": "application/octet-stream",
14138
- "Content-Length": imageInfo.size.toString()
14139
- },
14140
- data: fileBuffer,
14141
- httpAgent: this.uploadAgent,
14142
- httpsAgent: this.uploadAgent,
14143
- timeout: this.TOS_UPLOAD_TIMEOUT,
14144
- maxBodyLength: 1 / 0,
14145
- maxContentLength: 1 / 0
14146
- });
14135
+ const uploadImgResp = await this.withRetry(()=>this.proxyHttp.api({
14136
+ method: "post",
14137
+ url: uploadUrl,
14138
+ headers: {
14139
+ ...this.headers,
14140
+ Authorization: uploadAddr.auth,
14141
+ "Content-crc32": imageInfo.md5,
14142
+ "Content-Type": "application/octet-stream",
14143
+ "Content-Length": imageInfo.size.toString()
14144
+ },
14145
+ data: fileBuffer,
14146
+ httpAgent: this.uploadAgent,
14147
+ httpsAgent: this.uploadAgent,
14148
+ maxBodyLength: 1 / 0,
14149
+ maxContentLength: 1 / 0
14150
+ }, {
14151
+ timeout: this.TOS_UPLOAD_TIMEOUT
14152
+ }), 5, 3000, "TOS上传");
14147
14153
  console.log("TOS 上传响应:", uploadImgResp);
14148
14154
  const isSuccess = uploadImgResp && (2000 === uploadImgResp.code || 200 === uploadImgResp.status || 200 === uploadImgResp.statusCode || uploadImgResp.data && uploadImgResp.data.crc32 || "Success" === uploadImgResp.message);
14149
14155
  if (!isSuccess) throw new Error(`上传失败: ${JSON.stringify(uploadImgResp)}`);
@@ -14164,20 +14170,22 @@ var __webpack_exports__ = {};
14164
14170
  async processSingleImage(imageUrl, index, total) {
14165
14171
  console.log(`\n[${index + 1}/${total}] 处理图片: ${imageUrl.substring(0, 50)}...`);
14166
14172
  const fileName = (0, share_namespaceObject.getFilenameFromUrl)(imageUrl);
14167
- const localPath = external_node_path_default().join(this.tmpCachePath, fileName);
14173
+ const localPath = external_node_path_default().resolve(this.tmpCachePath, fileName);
14168
14174
  try {
14169
14175
  await (0, share_namespaceObject.downloadImage)(imageUrl, localPath);
14170
14176
  console.log(`图片下载完成: ${localPath}`);
14177
+ const imageInfo = await this.getImageInfo(localPath);
14178
+ console.log(`图片信息: ${imageInfo.width}x${imageInfo.height}, ${imageInfo.size} bytes`);
14179
+ const auth = await this.getValidAuth();
14180
+ const uploadAddr = await this.getUploadAddress(auth);
14181
+ const result = await this.uploadToTOS(imageInfo, uploadAddr);
14182
+ this.safeDeleteFile(localPath);
14183
+ return result;
14171
14184
  } catch (error) {
14172
- throw new Error(`下载图片失败: ${imageUrl}`);
14173
- }
14174
- const imageInfo = await this.getImageInfo(localPath);
14175
- console.log(`图片信息: ${imageInfo.width}x${imageInfo.height}, ${imageInfo.size} bytes`);
14176
- const auth = await this.getValidAuth();
14177
- const uploadAddr = await this.getUploadAddress(auth);
14178
- const result = await this.uploadToTOS(imageInfo, uploadAddr);
14179
- this.safeDeleteFile(localPath);
14180
- return result;
14185
+ console.error(`[${index + 1}/${total}] 图片上传失败,已跳过: ${imageUrl}`, error?.message ?? error);
14186
+ this.safeDeleteFile(localPath);
14187
+ return null;
14188
+ }
14181
14189
  }
14182
14190
  async getImageInfo(localPath) {
14183
14191
  const stats = external_node_fs_default().statSync(localPath);
@@ -14210,13 +14218,11 @@ var __webpack_exports__ = {};
14210
14218
  const globalIndex = i + idx;
14211
14219
  return this.processSingleImage(url, globalIndex, total);
14212
14220
  });
14213
- try {
14214
- const batchResults = await Promise.all(batchPromises);
14215
- results.push(...batchResults);
14216
- } catch (error) {
14217
- console.error(`批次 ${batchIndex} 上传失败:`, error);
14218
- throw error;
14219
- }
14221
+ const batchResults = await Promise.all(batchPromises);
14222
+ const successResults = batchResults.filter((r)=>null !== r);
14223
+ results.push(...successResults);
14224
+ const failedCount = batchResults.length - successResults.length;
14225
+ if (failedCount > 0) console.warn(`批次 ${batchIndex} 中有 ${failedCount} 张图片上传失败`);
14220
14226
  if (i + this.CONCURRENT_LIMIT < total) {
14221
14227
  console.log(`等待 ${this.UPLOAD_DELAY}ms...`);
14222
14228
  await this.delay(this.UPLOAD_DELAY);
@@ -14228,6 +14234,7 @@ var __webpack_exports__ = {};
14228
14234
  async uploadCover(coverUrl) {
14229
14235
  console.log("\n========== 上传封面 ==========\n");
14230
14236
  const result = await this.processSingleImage(coverUrl, 0, 1);
14237
+ if (!result) console.error(`封面图上传失败,已跳过: ${coverUrl}`);
14231
14238
  return result;
14232
14239
  }
14233
14240
  safeDeleteFile(filePath) {
@@ -14241,6 +14248,17 @@ var __webpack_exports__ = {};
14241
14248
  delay(ms) {
14242
14249
  return new Promise((resolve)=>setTimeout(resolve, ms));
14243
14250
  }
14251
+ async withRetry(fn, retries = 3, delayMs = 1000, label = "") {
14252
+ for(let attempt = 1; attempt <= retries; attempt++)try {
14253
+ return await fn();
14254
+ } catch (err) {
14255
+ if (attempt === retries) throw err;
14256
+ const waitTime = delayMs * attempt;
14257
+ console.warn(`${label} 第 ${attempt} 次失败,${waitTime}ms 后重试:`, err?.message ?? err);
14258
+ await this.delay(waitTime);
14259
+ }
14260
+ throw new Error("unreachable");
14261
+ }
14244
14262
  destroy() {
14245
14263
  this.uploadAgent.destroy();
14246
14264
  }
@@ -14437,14 +14455,16 @@ var __webpack_exports__ = {};
14437
14455
  const uploader = new DouyinImageUploader(proxyHttp, headers, publishParams, tmpCachePath);
14438
14456
  if (params.coverImage) {
14439
14457
  const cover = await uploader.uploadCover(params.coverImage);
14440
- publishData.item.common.images.push({
14441
- uri: cover.uri,
14442
- width: cover.width,
14443
- height: cover.height
14444
- });
14445
- publishData.item.cover = {
14446
- poster: cover.uri
14447
- };
14458
+ if (cover) {
14459
+ publishData.item.common.images.push({
14460
+ uri: cover.uri,
14461
+ width: cover.width,
14462
+ height: cover.height
14463
+ });
14464
+ publishData.item.cover = {
14465
+ poster: cover.uri
14466
+ };
14467
+ }
14448
14468
  }
14449
14469
  if (params.banners && params.banners.length > 0) {
14450
14470
  const banners = params.banners.filter((i)=>i !== params.coverImage);
@@ -14470,11 +14490,15 @@ var __webpack_exports__ = {};
14470
14490
  }
14471
14491
  if (!response || !response.data) return;
14472
14492
  const responseData = response.data;
14473
- if (response && responseData?.status_code && 0 !== responseData.status_code) return {
14474
- code: responseData?.status_code,
14475
- message: responseData.status_msg || "文章发布异常,请稍后重试。",
14476
- data: responseData
14477
- };
14493
+ if (response && responseData?.status_code && 0 !== responseData.status_code) {
14494
+ const errorCode = 4 === responseData.status_code ? 500 : responseData.status_code;
14495
+ if (4 === responseData.status_code) task.logger.warn(`抖音服务器错误 status_code: 4,映射为 500 触发重试。原始响应: ${JSON.stringify(responseData)}`);
14496
+ return {
14497
+ code: errorCode,
14498
+ message: responseData.status_msg || "文章发布异常,请稍后重试。",
14499
+ data: responseData
14500
+ };
14501
+ }
14478
14502
  });
14479
14503
  task._timerRecord.PrePublish = Date.now();
14480
14504
  if (MockPublish) {
@@ -14557,7 +14581,9 @@ var __webpack_exports__ = {};
14557
14581
  "x-tt-session-dtrait": sessionDtrait || ""
14558
14582
  }
14559
14583
  }, {
14560
- timeout: 60000
14584
+ timeout: 60000,
14585
+ retries: 3,
14586
+ retryDelay: 2000
14561
14587
  });
14562
14588
  reportLogger({
14563
14589
  token: params.huiwenToken || "",
@@ -14570,9 +14596,8 @@ var __webpack_exports__ = {};
14570
14596
  platform: "douyin",
14571
14597
  publishParams: publishData
14572
14598
  });
14573
- console.log("publishResult", JSON.stringify(publishResult));
14574
- task.logger.warn("发布数据");
14575
- task.logger.warn(JSON.stringify(publishData));
14599
+ task.logger.warn("发布结果");
14600
+ task.logger.warn(JSON.stringify(publishResult));
14576
14601
  const isSuccess = 0 === publishResult.status_code;
14577
14602
  const message = `图文发布${isSuccess ? "成功" : `失败,原因:${publishResult.status_msg} ${decision?.verify_title} ${decision?.verify_desc}`}${task.debug ? ` ${http.proxyInfo}` : ""}`;
14578
14603
  const data = isSuccess ? publishResult.item_id || "" : "";
@@ -23264,423 +23289,1516 @@ var __webpack_exports__ = {};
23264
23289
  if ("server" === params.actionType) return xiaohongshuLogin_rpa_server_rpaServer(task, params);
23265
23290
  return executeAction(xiaohongshuLogin_rpa_rpaAction)(task, params);
23266
23291
  };
23267
- const FictionalRendition = schemas_object({
23268
- type: literal("fictional-rendition")
23269
- });
23270
- const AIGenerated = schemas_object({
23271
- type: literal("ai-generated")
23272
- });
23273
- const SourceStatement = schemas_object({
23274
- type: literal("source-statement"),
23275
- childType: schemas_enum([
23276
- "self-labeling",
23277
- "self-shooting",
23278
- "transshipment"
23279
- ]),
23280
- shootingLocation: custom().optional(),
23281
- shootingDate: schemas_string().optional(),
23282
- sourceMedia: schemas_string().optional()
23283
- });
23284
- union([
23285
- FictionalRendition,
23286
- AIGenerated,
23287
- SourceStatement
23288
- ]);
23289
- const XiaohongshuPublishParamsSchema = ActionCommonParamsSchema.extend({
23290
- banners: schemas_array(schemas_string()),
23291
- title: schemas_string(),
23292
- content: schemas_string(),
23293
- address: custom().optional(),
23294
- selfDeclaration: custom().optional(),
23295
- topic: schemas_array(custom()).optional(),
23296
- proxyLoc: schemas_string().optional(),
23297
- localIP: schemas_string().optional(),
23298
- huiwenToken: schemas_string().optional(),
23299
- visibleRange: schemas_enum([
23300
- "public",
23301
- "private",
23302
- "friends"
23303
- ]),
23304
- isImmediatelyPublish: schemas_boolean().optional(),
23305
- scheduledPublish: schemas_string().optional(),
23306
- collectionId: schemas_string().optional(),
23307
- collectionBind: custom().optional(),
23308
- groupBind: custom().optional(),
23309
- noteCopyBind: schemas_boolean().optional(),
23310
- coProduceBind: schemas_boolean().optional(),
23311
- originalBind: schemas_boolean().optional()
23312
- });
23313
- const xiaohongshuPublish = async (_task, _params)=>({
23292
+ let _windowCache = null;
23293
+ const getWindow = ()=>{
23294
+ if (_windowCache) return _windowCache;
23295
+ _windowCache = "undefined" != typeof window ? window : globalThis;
23296
+ return _windowCache;
23297
+ };
23298
+ if ("undefined" != typeof process) {
23299
+ process.on("uncaughtException", ()=>{});
23300
+ process.on("unhandledRejection", ()=>{});
23301
+ }
23302
+ const mnsv2_enc = (arg1, arg2, cookieString)=>{
23303
+ const win = getWindow();
23304
+ win.ck = cookieString;
23305
+ __webpack_require__("./src/utils/xhs_ob_feed/ob.env.js");
23306
+ try {
23307
+ __webpack_require__("./src/utils/xhs_ob_feed/ob.enc.js");
23308
+ } catch {}
23309
+ let result = "";
23310
+ try {
23311
+ result = win.mnsv2(arg1, arg2);
23312
+ } catch {}
23313
+ return result;
23314
+ };
23315
+ const mnsvc2 = mnsv2_enc;
23316
+ const xhs_ob_feed_encode_mnsv2 = __webpack_require__("./src/utils/xhs_ob_feed/x_s.encoder.js");
23317
+ class xhs_ob_feed_Xhshow {
23318
+ stringifyCookies(cookies) {
23319
+ return Object.entries(cookies).map(([key, value])=>`${key}=${value}`).join("; ");
23320
+ }
23321
+ signHeadersGet(uri, cookieString, xsecAppid = "ugc", params) {
23322
+ let para1 = "";
23323
+ if (params && 0 !== Object.keys(params).length) {
23324
+ const _queryPara = Object.entries(params).map(([key, value])=>{
23325
+ let valueStr = "";
23326
+ if (Array.isArray(value)) valueStr = value.map((v)=>String(v)).join(",");
23327
+ else if (null != value) valueStr = String(value);
23328
+ return `${key}=${valueStr}`;
23329
+ });
23330
+ para1 = `${uri}?${_queryPara.join("&")}`;
23331
+ } else para1 = uri;
23332
+ const md5Para1 = external_node_crypto_default().createHash("md5").update(para1).digest("hex");
23333
+ const mnsvc2_data = mnsvc2(para1, md5Para1, this.stringifyCookies(cookieString));
23334
+ return {
23335
+ "X-S": xhs_ob_feed_encode_mnsv2(mnsvc2_data, xsecAppid, "Windows", "object")
23336
+ };
23337
+ }
23338
+ signHeadersPost(uri, cookieString, xsecAppid = "ugc", payload) {
23339
+ const para1 = uri + JSON.stringify(payload || {});
23340
+ const md5Para1 = external_node_crypto_default().createHash("md5").update(para1).digest("hex");
23341
+ const mnsvc2_data = mnsvc2(para1, md5Para1, this.stringifyCookies(cookieString));
23342
+ return {
23343
+ "X-S": xhs_ob_feed_encode_mnsv2(mnsvc2_data, xsecAppid, "Windows", "object")
23344
+ };
23345
+ }
23346
+ }
23347
+ const xiaohongshuPublish_mock_errnoMap = {
23348
+ "-1": "未知拦截器错误,请稍后重试。",
23349
+ 915: "所属C端账号手机号被修改,请重新登录",
23350
+ 914: "所属C端账号密码被修改,请重新登录",
23351
+ 903: "账户已登出,需重新登陆重试!",
23352
+ 902: "登录已过期,请重新登录!",
23353
+ 906: "账号存在风险,请重新登录!",
23354
+ "-9136": "因违反社区规范禁止发笔记,请检查账号状态!"
23355
+ };
23356
+ const mock_xsEncrypt = new xhs_ob_feed_Xhshow();
23357
+ const xiaohongshuPublish_mock_mockAction = async (task, params)=>{
23358
+ const tmpCachePath = task.getTmpPath();
23359
+ if (params?.selfDeclaration?.type === "source-statement" && "transshipment" === params.selfDeclaration.childType && params.originalBind) return {
23314
23360
  code: 414,
23315
- data: "",
23316
- message: "临时维护:小红书发布政策调整,本平台小红书发布功能临时暂停服务并进行维护调整,暂时无法正常发布,敬请理解知悉。"
23317
- });
23318
- const xiaohongshuWebCommentAction_xsEncrypt = new Xhshow();
23319
- const xiaohongshuWebCommentAction = async (_task, params)=>{
23320
- if (DisabledReq) return (0, share_namespaceObject.response)(414, "点赞相关操作失败", {});
23361
+ message: "原创声明与转载声明互斥,请重新选择后发布!",
23362
+ data: ""
23363
+ };
23364
+ const a1Cookie = params.cookies.find((it)=>"a1" === it.name)?.value;
23365
+ if (!a1Cookie) return {
23366
+ code: 414,
23367
+ message: "账号数据异常,请重新绑定账号后重试。",
23368
+ data: ""
23369
+ };
23321
23370
  const headers = {
23322
23371
  cookie: params.cookies.map((it)=>`${it.name}=${it.value}`).join(";"),
23323
- referer: "https://www.xiaohongshu.com/",
23324
- origin: "https://www.xiaohongshu.com/"
23372
+ origin: "https://creator.xiaohongshu.com",
23373
+ referer: "https://creator.xiaohongshu.com/",
23374
+ "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"
23325
23375
  };
23376
+ const recordCookie = params.cookies.reduce((acc, cookie)=>{
23377
+ if (cookie.name && cookie.value) acc[cookie.name] = cookie.value;
23378
+ return acc;
23379
+ }, {});
23326
23380
  const args = [
23327
23381
  {
23328
23382
  headers
23329
23383
  },
23330
- _task.logger,
23384
+ task.logger,
23331
23385
  params.proxyLoc,
23332
23386
  params.localIP,
23333
23387
  params.accountId
23334
23388
  ];
23335
- const http = new Http(...args);
23336
- const a1Cookie = params.cookies.find((it)=>"a1" === it.name)?.value;
23337
- if (!a1Cookie) return {
23338
- code: 414,
23339
- message: "账号数据异常,请重新绑定账号后重试。",
23340
- data: []
23341
- };
23342
- if (!params.note_id && !params.comment_id && !params.action) return {
23343
- code: 414,
23344
- message: "参数缺失,请检查后重试!",
23345
- data: {}
23346
- };
23347
- const actionParams = {
23348
- note_id: params.note_id,
23349
- comment_id: params.comment_id
23350
- };
23351
- let likeActionRes = {
23352
- code: 500,
23353
- success: false,
23354
- msg: ""
23389
+ const http = new Http({
23390
+ headers
23391
+ });
23392
+ const proxyHttp = new Http(...args);
23393
+ proxyHttp.addResponseInterceptor((response)=>{
23394
+ const responseData = response.data;
23395
+ if (response && responseData?.code && 0 !== responseData.code || responseData?.code && !responseData.success) {
23396
+ const errmsg = xiaohongshuPublish_mock_errnoMap[responseData.code] || response.config.defaultErrorMsg || "文章发布异常,请稍后重试。";
23397
+ return {
23398
+ code: xiaohongshuPublish_mock_errnoMap[responseData.code] ? 414 : 500,
23399
+ message: errmsg,
23400
+ data: responseData
23401
+ };
23402
+ }
23403
+ });
23404
+ const fetchCoverUrl = "/api/media/v1/upload/creator/permit";
23405
+ const fetchCoverParams = {
23406
+ biz_name: "spectrum",
23407
+ scene: "image",
23408
+ file_count: params.banners.length,
23409
+ version: 1,
23410
+ source: "web"
23355
23411
  };
23356
- const recordCookie = params.cookies.reduce((acc, cookie)=>{
23357
- if (cookie.name && cookie.value) acc[cookie.name] = cookie.value;
23358
- return acc;
23359
- }, {});
23360
- switch(params.action){
23361
- case "like":
23362
- {
23363
- const likeAction = "/api/sns/web/v1/comment/like";
23364
- const likeActionXsHeader = xiaohongshuWebCommentAction_xsEncrypt.signHeadersPost(likeAction, recordCookie, "xhs-pc-web", actionParams);
23365
- likeActionRes = await http.api({
23366
- method: "post",
23367
- url: "https://edith.xiaohongshu.com/api/sns/web/v1/comment/like",
23368
- data: actionParams,
23369
- headers: likeActionXsHeader
23370
- }, {
23371
- retries: 3,
23372
- retryDelay: 20,
23373
- timeout: 3000
23374
- });
23375
- break;
23376
- }
23377
- case "dislike":
23378
- {
23379
- const dislikeMentions = "/api/sns/web/v1/comment/dislike";
23380
- const dislikeXsHeader = xiaohongshuWebCommentAction_xsEncrypt.signHeadersPost(dislikeMentions, recordCookie, "xhs-pc-web", actionParams);
23381
- likeActionRes = await http.api({
23382
- method: "post",
23383
- url: "https://edith.xiaohongshu.com/api/sns/web/v1/comment/dislike",
23384
- data: actionParams,
23385
- headers: dislikeXsHeader
23386
- }, {
23387
- retries: 3,
23388
- retryDelay: 20,
23389
- timeout: 3000
23412
+ const fetchCoverXsHeader = mock_xsEncrypt.signHeadersGet(fetchCoverUrl, recordCookie, "ugc", fetchCoverParams);
23413
+ const uploadInfos = [];
23414
+ if (params.banners.length > 18) {
23415
+ const num = Math.ceil(params.banners.length / 14);
23416
+ for(let i = 0; i < num; i++){
23417
+ const start = 14 * i;
23418
+ params.banners.length;
23419
+ ({
23420
+ ...fetchCoverParams
23421
+ });
23422
+ const batchCoverIdInfo = await proxyHttp.api({
23423
+ method: "get",
23424
+ baseURL: "https://creator.xiaohongshu.com",
23425
+ url: fetchCoverUrl,
23426
+ defaultErrorMsg: "获取小红书用户信息失败,请稍后重试发布。",
23427
+ headers: fetchCoverXsHeader,
23428
+ params: fetchCoverParams
23429
+ }, {
23430
+ retries: 3,
23431
+ retryDelay: 20,
23432
+ timeout: 3000
23433
+ });
23434
+ for (const item of batchCoverIdInfo.data.uploadTempPermits)for (const fileId of item.fileIds)uploadInfos.push({
23435
+ bucket: item.bucket || "",
23436
+ uploadAddr: item.uploadAddr || "",
23437
+ fileIds: fileId,
23438
+ token: item.token || ""
23439
+ });
23440
+ }
23441
+ } else {
23442
+ const coverIdInfo = await proxyHttp.api({
23443
+ method: "get",
23444
+ baseURL: "https://creator.xiaohongshu.com",
23445
+ url: fetchCoverUrl,
23446
+ defaultErrorMsg: "获取小红书用户信息失败,请稍后重试发布。",
23447
+ headers: fetchCoverXsHeader,
23448
+ params: fetchCoverParams
23449
+ }, {
23450
+ retries: 3,
23451
+ retryDelay: 20,
23452
+ timeout: 3000
23453
+ });
23454
+ for (const item of coverIdInfo.data.uploadTempPermits)for (const fileId of item.fileIds)uploadInfos.push({
23455
+ bucket: item.bucket || "",
23456
+ uploadAddr: item.uploadAddr || "",
23457
+ fileIds: fileId,
23458
+ token: item.token || ""
23459
+ });
23460
+ }
23461
+ if (uploadInfos.length < params.banners.length) return {
23462
+ code: 414,
23463
+ message: "可用 OSS bucket 数量不足,无法上传所有图片!",
23464
+ data: ""
23465
+ };
23466
+ if (0 === uploadInfos.length) return {
23467
+ code: 414,
23468
+ message: "图片上传失败,请稍后重试!",
23469
+ data: ""
23470
+ };
23471
+ const availableBuckets = Array.from({
23472
+ length: uploadInfos.length
23473
+ }, (_, i)=>i);
23474
+ const uploadFile = async (url, index)=>{
23475
+ const fileName = (0, share_namespaceObject.getFilenameFromUrl)(url);
23476
+ const localUrl = await (0, share_namespaceObject.downloadImage)(url, external_node_path_default().join(tmpCachePath, fileName));
23477
+ const fileBuffer = external_node_fs_default().readFileSync(localUrl);
23478
+ const MAX_RETRIES = uploadInfos.length;
23479
+ let attempt = 0;
23480
+ while(attempt < MAX_RETRIES){
23481
+ const ossBucketIndex = availableBuckets.shift();
23482
+ if (void 0 === ossBucketIndex) break;
23483
+ const currentInfo = uploadInfos[ossBucketIndex];
23484
+ const ossFileId = currentInfo.fileIds;
23485
+ const ossToken = currentInfo.token;
23486
+ const ossDomain = currentInfo.uploadAddr;
23487
+ try {
23488
+ await http.api({
23489
+ method: "put",
23490
+ url: `https://${ossDomain}/${ossFileId}`,
23491
+ data: fileBuffer,
23492
+ headers: {
23493
+ "x-cos-security-token": ossToken
23494
+ },
23495
+ defaultErrorMsg: "图片上传异常,请稍后重试发布。"
23390
23496
  });
23391
- break;
23497
+ return {
23498
+ ossFileId,
23499
+ ossToken
23500
+ };
23501
+ } catch (error) {
23502
+ attempt++;
23392
23503
  }
23393
- default:
23394
- return {
23395
- code: 414,
23396
- message: "参数action错误,请重试!",
23397
- data: {}
23504
+ }
23505
+ return {
23506
+ ossFileId: "",
23507
+ ossToken: ""
23508
+ };
23509
+ };
23510
+ const coverInfos = await Promise.all(params.banners.map((it, idx)=>uploadFile(it, idx)));
23511
+ const invalidUpload = coverInfos.find((it)=>"" === it.ossToken || "" === it.ossFileId);
23512
+ if (invalidUpload) return {
23513
+ code: 414,
23514
+ message: "图片上传异常,请稍后重试发布。",
23515
+ data: ""
23516
+ };
23517
+ if (params.topic && params.topic.length > 0) await Promise.all(params.topic.map(async (topic)=>{
23518
+ if (!topic.id) {
23519
+ const topicData = {
23520
+ topic_names: topic.name
23398
23521
  };
23399
- }
23400
- const isSuccess = 0 === likeActionRes.code;
23401
- const message = `点赞相关操作${isSuccess ? "成功" : `失败,原因:${likeActionRes.msg}`}${_task.debug ? ` ${http.proxyInfo}` : ""}`;
23402
- const data = isSuccess ? likeActionRes.success : {};
23403
- return (0, share_namespaceObject.response)(isSuccess ? 0 : 414, message, data);
23404
- };
23405
- const xiaohongshuWebIntimacySearch = async (_task, params)=>{
23406
- if (DisabledReq) return (0, share_namespaceObject.response)(0, "搜索@列表数据成功", []);
23407
- const headers = {
23408
- cookie: params.cookies.map((it)=>`${it.name}=${it.value}`).join(";"),
23409
- referer: "https://www.xiaohongshu.com/",
23410
- origin: "https://www.xiaohongshu.com"
23522
+ const topicXsHeader = mock_xsEncrypt.signHeadersPost("/web_api/sns/capa/postgw/topic/batch_customized", recordCookie, "ugc", topicData);
23523
+ const createTopic = await proxyHttp.api({
23524
+ method: "POST",
23525
+ url: "https://edith.xiaohongshu.com/web_api/sns/capa/postgw/topic/batch_customized",
23526
+ headers: topicXsHeader,
23527
+ data: topicData,
23528
+ defaultErrorMsg: "话题创建异常,请稍后重试。"
23529
+ }, {
23530
+ retries: 3,
23531
+ retryDelay: 20,
23532
+ timeout: 3000
23533
+ });
23534
+ if (!createTopic?.data) throw types_errorResponse("话题创建失败,请检查话题字段!", 414);
23535
+ Object.assign(topic, createTopic?.data?.topic_infos[0]);
23536
+ }
23537
+ }));
23538
+ const visibleRangeMap = {
23539
+ public: 0,
23540
+ private: 1,
23541
+ friends: 4
23411
23542
  };
23412
- const args = [
23413
- {
23414
- headers
23543
+ const publishData = {
23544
+ common: {
23545
+ ats: [],
23546
+ biz_relations: [],
23547
+ desc: params?.content,
23548
+ goods_info: {},
23549
+ hash_tag: params.topic || [],
23550
+ note_id: "",
23551
+ source: JSON.stringify({
23552
+ type: "web",
23553
+ ids: "",
23554
+ extraInfo: '{"systemId":"web"}'
23555
+ }),
23556
+ title: params?.title,
23557
+ type: "normal",
23558
+ privacy_info: {
23559
+ op_type: 1,
23560
+ type: visibleRangeMap[params.visibleRange]
23561
+ },
23562
+ post_loc: params.address ? {
23563
+ name: params.address?.name,
23564
+ poi_id: params.address?.poi_id,
23565
+ poi_type: params.address?.poi_type,
23566
+ subname: params.address?.full_address
23567
+ } : null,
23568
+ business_binds: ""
23415
23569
  },
23416
- _task.logger,
23417
- params.proxyLoc,
23418
- params.localIP,
23419
- params.accountId
23420
- ];
23421
- const http = new Http(...args);
23422
- let intimacyDetail = [];
23423
- const res = await http.api({
23570
+ image_info: {
23571
+ images: coverInfos.map((it)=>({
23572
+ extra_info_json: '{"mimeType":"image/png"}',
23573
+ file_id: it.ossFileId,
23574
+ metadata: {
23575
+ source: -1
23576
+ },
23577
+ stickers: {
23578
+ floating: [],
23579
+ version: 2
23580
+ }
23581
+ }))
23582
+ },
23583
+ video_info: null
23584
+ };
23585
+ const userDeclarationBind = {
23586
+ origin: 2,
23587
+ photoInfo: {},
23588
+ repostInfo: {}
23589
+ };
23590
+ if (params.selfDeclaration?.type === "fictional-rendition") userDeclarationBind.origin = 1;
23591
+ else if (params.selfDeclaration?.type === "ai-generated") userDeclarationBind.origin = 2;
23592
+ else if (params.selfDeclaration?.type === "source-statement") {
23593
+ if ("self-labeling" === params.selfDeclaration.childType) userDeclarationBind.origin = 3;
23594
+ else if ("self-shooting" === params.selfDeclaration.childType) {
23595
+ userDeclarationBind.origin = 4;
23596
+ const photoInfo = {};
23597
+ if (params.selfDeclaration.shootingLocation) photoInfo.photoPlace = {
23598
+ name: params.selfDeclaration.shootingLocation.name,
23599
+ poiId: params.selfDeclaration.shootingLocation.poi_id,
23600
+ poiType: params.selfDeclaration.shootingLocation.poi_type,
23601
+ subname: params.selfDeclaration.shootingLocation.full_address
23602
+ };
23603
+ if (params.selfDeclaration.shootingDate) photoInfo.photoTime = params.selfDeclaration.shootingDate;
23604
+ userDeclarationBind.photoInfo = photoInfo;
23605
+ } else if ("transshipment" === params.selfDeclaration.childType) {
23606
+ userDeclarationBind.origin = 5;
23607
+ if (params.selfDeclaration.sourceMedia) userDeclarationBind.repostInfo = {
23608
+ source: params.selfDeclaration.sourceMedia
23609
+ };
23610
+ }
23611
+ }
23612
+ const bizId = params?.originalBind && (params.cookies.find((it)=>"x-user-id-creator.xiaohongshu.com" === it.name)?.value || await proxyHttp.api({
23424
23613
  method: "get",
23425
- url: `https://edith.xiaohongshu.com/api/sns/web/v1/intimacy/intimacy_list${params.searchValue ? "/search" : ""}`,
23426
- ...params.searchValue ? {
23427
- params: {
23428
- keyword: params.searchValue,
23429
- page: 1,
23430
- rows: 30
23431
- }
23432
- } : {}
23614
+ url: "https://creator.xiaohongshu.com/api/galaxy/user/my-info"
23433
23615
  }, {
23434
23616
  retries: 3,
23435
23617
  retryDelay: 20,
23436
23618
  timeout: 3000
23437
- });
23438
- const isSuccess = 0 === res.code;
23439
- if (isSuccess) intimacyDetail = res.data.items;
23440
- const message = `搜索@列表数据${isSuccess ? "成功" : `失败,原因:${res.msg}`}${_task.debug ? ` ${http.proxyInfo}` : ""}`;
23441
- return (0, share_namespaceObject.response)(isSuccess ? 0 : 414, message, intimacyDetail);
23442
- };
23443
- const xiaohongshuWebMsgRead_xsEncrypt = new Xhshow();
23444
- const xiaohongshuWebMsgRead = async (_task, params)=>{
23445
- if (DisabledReq) return (0, share_namespaceObject.response)(414, "Read指定Tab失败", {});
23446
- const headers = {
23447
- cookie: params.cookies.map((it)=>`${it.name}=${it.value}`).join(";"),
23448
- referer: "https://www.xiaohongshu.com/",
23449
- origin: "https://www.xiaohongshu.com/"
23450
- };
23451
- const args = [
23452
- {
23453
- headers
23619
+ }).then((userData)=>userData.data?.userDetail?.id));
23620
+ const business_binds = {
23621
+ version: 1,
23622
+ bizType: "",
23623
+ noteId: "",
23624
+ noteOrderBind: {},
23625
+ notePostTiming: params.isImmediatelyPublish ? {} : {
23626
+ postTime: params.scheduledPublish
23454
23627
  },
23455
- _task.logger,
23456
- params.proxyLoc,
23457
- params.localIP,
23458
- params.accountId
23459
- ];
23460
- const http = new Http(...args);
23461
- const a1Cookie = params.cookies.find((it)=>"a1" === it.name)?.value;
23462
- if (!a1Cookie) return {
23463
- code: 414,
23464
- message: "账号数据异常,请重新绑定账号后重试。",
23465
- data: []
23466
- };
23467
- if (!params.type) return {
23468
- code: 414,
23469
- message: "参数缺失,请检查后重试!",
23470
- data: {}
23471
- };
23472
- const replyParams = {
23473
- type: params.type
23628
+ coProduceBind: {
23629
+ enable: !!params?.coProduceBind
23630
+ },
23631
+ noteCopyBind: {
23632
+ copyable: !!params?.noteCopyBind
23633
+ },
23634
+ optionRelationList: params.originalBind ? [
23635
+ {
23636
+ type: "ORIGINAL_STATEMENT",
23637
+ relationList: [
23638
+ {
23639
+ bizId,
23640
+ bizType: "ORIGINAL_STATEMENT",
23641
+ extraInfo: "{}"
23642
+ }
23643
+ ]
23644
+ }
23645
+ ] : [],
23646
+ ...params?.groupBind ? {
23647
+ groupBind: {
23648
+ groupId: params?.groupBind?.group_id,
23649
+ groupName: params.groupBind?.group_name,
23650
+ desc: params.groupBind?.desc,
23651
+ avatar: params.groupBind?.avatar
23652
+ }
23653
+ } : {
23654
+ groupBind: {}
23655
+ },
23656
+ ...params.selfDeclaration ? {
23657
+ userDeclarationBind
23658
+ } : {},
23659
+ ...params?.collectionBind?.id ? {
23660
+ noteCollectionBind: {
23661
+ id: params.collectionBind.id
23662
+ }
23663
+ } : {}
23474
23664
  };
23475
- const fatchMentions = "/api/sns/web/v1/message/read";
23476
- const recordCookie = params.cookies.reduce((acc, cookie)=>{
23477
- if (cookie.name && cookie.value) acc[cookie.name] = cookie.value;
23478
- return acc;
23479
- }, {});
23480
- const fatchMentionsXsHeader = xiaohongshuWebMsgRead_xsEncrypt.signHeadersPost(fatchMentions, recordCookie, "xhs-pc-web", replyParams);
23481
- const res = await http.api({
23665
+ publishData.common.business_binds = JSON.stringify(business_binds);
23666
+ const publishXsHeader = mock_xsEncrypt.signHeadersPost("/web_api/sns/v2/note", recordCookie, "ugc", publishData);
23667
+ task._timerRecord.PrePublish = Date.now();
23668
+ const updateTaskState = task.taskStageStore?.update?.bind(task.taskStageStore, task.taskId || "");
23669
+ if (MockPublish) {
23670
+ const message = `文章模拟发布成功 ${http.proxyInfo}`;
23671
+ const data = "123456789";
23672
+ await updateTaskState?.({
23673
+ state: share_namespaceObject.TaskState.SUCCESS,
23674
+ result: {
23675
+ response: data
23676
+ }
23677
+ });
23678
+ return (0, share_namespaceObject.success)(data, message);
23679
+ }
23680
+ const publishResult = await proxyHttp.api({
23482
23681
  method: "post",
23483
- url: "https://edith.xiaohongshu.com/api/sns/web/v1/message/read",
23484
- data: replyParams,
23485
- headers: fatchMentionsXsHeader
23682
+ url: "https://edith.xiaohongshu.com/web_api/sns/v2/note",
23683
+ data: publishData,
23684
+ headers: publishXsHeader,
23685
+ defaultErrorMsg: "文章发布异常,请稍后重试。"
23486
23686
  }, {
23487
- retries: 3,
23488
- retryDelay: 20,
23489
- timeout: 3000
23687
+ retries: 2,
23688
+ retryDelay: 500,
23689
+ timeout: 12000
23690
+ });
23691
+ reportLogger({
23692
+ token: params.huiwenToken || "",
23693
+ enverionment: task.enverionment || "development",
23694
+ postId: params.articleId,
23695
+ eip: proxyHttp.proxyInfo,
23696
+ proxyIp: params.localIP,
23697
+ accountId: params.accountId,
23698
+ uid: params.uid,
23699
+ platform: "xiaohongshu",
23700
+ publishParams: publishData
23701
+ });
23702
+ const isSuccess = publishResult.success;
23703
+ const message = `文章发布${isSuccess ? "成功" : `失败,原因:${publishResult.msg}`}${task.debug ? ` ${http.proxyInfo}` : ""}`;
23704
+ const data = isSuccess ? publishResult.data?.id || "" : "";
23705
+ if (!isSuccess) {
23706
+ await updateTaskState?.({
23707
+ state: share_namespaceObject.TaskState.FAILED,
23708
+ error: message
23709
+ });
23710
+ return {
23711
+ code: 414,
23712
+ data,
23713
+ message
23714
+ };
23715
+ }
23716
+ await updateTaskState?.({
23717
+ state: share_namespaceObject.TaskState.SUCCESS,
23718
+ result: {
23719
+ response: data
23720
+ }
23490
23721
  });
23491
- const isSuccess = 0 === res.code;
23492
- const message = `Read指定Tab${isSuccess ? "成功" : `失败,原因:${res.msg}`}${_task.debug ? ` ${http.proxyInfo}` : ""}`;
23493
- const data = isSuccess ? res.success : {};
23494
23722
  return (0, share_namespaceObject.response)(isSuccess ? 0 : 414, message, data);
23495
23723
  };
23496
- const xiaohongshuWebMsgReply_xsEncrypt = new Xhshow();
23497
- const xiaohongshuWebMsgReply = async (_task, params)=>{
23498
- if (DisabledReq) return (0, share_namespaceObject.response)(414, "评论回复失败", {});
23499
- const headers = {
23500
- cookie: params.cookies.map((it)=>`${it.name}=${it.value}`).join(";"),
23501
- referer: "https://www.xiaohongshu.com/",
23502
- origin: "https://www.xiaohongshu.com/"
23724
+ const xiaohongshuPublish_rpa_rpaAction = async (task, params)=>{
23725
+ const updateTaskState = task.taskStageStore?.update?.bind(task.taskStageStore, task.taskId || "");
23726
+ const commonCookies = {
23727
+ path: "/",
23728
+ sameSite: "lax",
23729
+ secure: false,
23730
+ domain: ".xiaohongshu.com",
23731
+ url: "https://creator.xiaohongshu.com",
23732
+ httpOnly: true
23503
23733
  };
23504
- const args = [
23505
- {
23506
- headers
23507
- },
23508
- _task.logger,
23509
- params.proxyLoc,
23510
- params.localIP,
23511
- params.accountId
23512
- ];
23513
- const http = new Http(...args);
23514
- const a1Cookie = params.cookies.find((it)=>"a1" === it.name)?.value;
23515
- if (!a1Cookie) return {
23516
- code: 414,
23517
- message: "账号数据异常,请重新绑定账号后重试。",
23518
- data: []
23734
+ const page = await task.createPage({
23735
+ show: task.debug,
23736
+ url: params.url || "https://creator.xiaohongshu.com/publish/publish",
23737
+ cookies: params.cookies?.map((it)=>({
23738
+ ...it,
23739
+ ...commonCookies
23740
+ }))
23741
+ });
23742
+ await updateTaskState?.({
23743
+ state: share_namespaceObject.TaskState.ACTION,
23744
+ connectAddress: task.steelConnector?.getProxyUrl(task.sessionId || "", "v1/sessions/debug"),
23745
+ sessionId: task.sessionId
23746
+ });
23747
+ const tmpCachePath = task.getTmpPath();
23748
+ const selectAddress = async (selector, address)=>{
23749
+ const instance = "string" == typeof selector ? page.locator(selector) : selector;
23750
+ await instance.click();
23751
+ await instance.locator("input").fill(address);
23752
+ const poperInstance = page.locator('.d-popover:not([style*="display: none"]) .d-options .d-grid-item');
23753
+ await poperInstance.first().waitFor();
23754
+ await poperInstance.first().click();
23519
23755
  };
23520
- if (!params.note_id || !params.target_comment_id || !params.content) return {
23521
- code: 414,
23522
- message: "参数缺失,请检查后重试!",
23523
- data: {}
23756
+ const selectDate = async (selector, date)=>{
23757
+ const instance = "string" == typeof selector ? page.locator(selector) : selector;
23758
+ await instance.click();
23759
+ await instance.fill(date);
23760
+ await instance.blur();
23524
23761
  };
23525
- const replyParams = {
23526
- at_users: params.at_users ?? [],
23527
- content: params.content,
23528
- note_id: params.note_id,
23529
- target_comment_id: params.target_comment_id
23762
+ const getPoperInstance = async ()=>{
23763
+ await page.waitForTimeout(500);
23764
+ const elements = page.locator(".d-popover");
23765
+ const count = await elements.count();
23766
+ const visibleElements = [];
23767
+ for(let i = 0; i < count; i++){
23768
+ const element = elements.nth(i);
23769
+ const style = await element.getAttribute("style");
23770
+ if (style && !style.includes("display: none")) visibleElements.push(element);
23771
+ }
23772
+ if (visibleElements.length > 0) return visibleElements[visibleElements.length - 1];
23773
+ throw new Error("未找到 popover 弹窗");
23774
+ };
23775
+ const getDialogInstance = async ()=>{
23776
+ await page.waitForTimeout(1000);
23777
+ const elements = page.locator(".el-dialog");
23778
+ return elements.last();
23530
23779
  };
23531
- const replyPath = "/api/sns/web/v1/comment/post";
23532
- const recordCookie = params.cookies.reduce((acc, cookie)=>{
23533
- if (cookie.name && cookie.value) acc[cookie.name] = cookie.value;
23534
- return acc;
23535
- }, {});
23536
- const replyXsHeader = xiaohongshuWebMsgReply_xsEncrypt.signHeadersPost(replyPath, recordCookie, "xhs-pc-web", replyParams);
23537
- const res = await http.api({
23538
- method: "post",
23539
- url: "https://edith.xiaohongshu.com/api/sns/web/v1/comment/post",
23540
- data: replyParams,
23541
- headers: replyXsHeader
23542
- }, {
23543
- retries: 3,
23544
- retryDelay: 20,
23545
- timeout: 3000
23546
- });
23547
- const isSuccess = 0 === res.code;
23548
- const message = `评论回复${isSuccess ? "成功" : `失败,原因:${res.msg}`}${_task.debug ? ` ${http.proxyInfo}` : ""}`;
23549
- const data = isSuccess ? res.data : {};
23550
- return (0, share_namespaceObject.response)(isSuccess ? 0 : 414, message, data);
23551
- };
23552
- let _windowCache = null;
23553
- const getWindow = ()=>{
23554
- if (_windowCache) return _windowCache;
23555
- _windowCache = "undefined" != typeof window ? window : globalThis;
23556
- return _windowCache;
23557
- };
23558
- if ("undefined" != typeof process) {
23559
- process.on("uncaughtException", ()=>{});
23560
- process.on("unhandledRejection", ()=>{});
23561
- }
23562
- const mnsv2_enc = (arg1, arg2, cookieString)=>{
23563
- const win = getWindow();
23564
- win.ck = cookieString;
23565
- __webpack_require__("./src/utils/xhs_ob_feed/ob.env.js");
23566
- try {
23567
- __webpack_require__("./src/utils/xhs_ob_feed/ob.enc.js");
23568
- } catch {}
23569
- let result = "";
23570
23780
  try {
23571
- result = win.mnsv2(arg1, arg2);
23572
- } catch {}
23573
- return result;
23574
- };
23575
- const mnsvc2 = mnsv2_enc;
23576
- const xhs_ob_feed_encode_mnsv2 = __webpack_require__("./src/utils/xhs_ob_feed/x_s.encoder.js");
23577
- class xhs_ob_feed_Xhshow {
23578
- stringifyCookies(cookies) {
23579
- return Object.entries(cookies).map(([key, value])=>`${key}=${value}`).join("; ");
23580
- }
23581
- signHeadersGet(uri, cookieString, xsecAppid = "ugc", params) {
23582
- let para1 = "";
23583
- if (params && 0 !== Object.keys(params).length) {
23584
- const _queryPara = Object.entries(params).map(([key, value])=>{
23585
- let valueStr = "";
23586
- if (Array.isArray(value)) valueStr = value.map((v)=>String(v)).join(",");
23587
- else if (null != value) valueStr = String(value);
23588
- return `${key}=${valueStr}`;
23589
- });
23590
- para1 = `${uri}?${_queryPara.join("&")}`;
23591
- } else para1 = uri;
23592
- const md5Para1 = external_node_crypto_default().createHash("md5").update(para1).digest("hex");
23593
- const mnsvc2_data = mnsvc2(para1, md5Para1, this.stringifyCookies(cookieString));
23781
+ await page.waitForSelector("#CreatorPlatform", {
23782
+ state: "visible"
23783
+ });
23784
+ } catch (error) {
23594
23785
  return {
23595
- "X-S": xhs_ob_feed_encode_mnsv2(mnsvc2_data, xsecAppid, "Windows", "object")
23786
+ code: 414,
23787
+ message: "登录失效",
23788
+ data: page.url()
23596
23789
  };
23597
23790
  }
23598
- signHeadersPost(uri, cookieString, xsecAppid = "ugc", payload) {
23599
- const para1 = uri + JSON.stringify(payload || {});
23600
- const md5Para1 = external_node_crypto_default().createHash("md5").update(para1).digest("hex");
23601
- const mnsvc2_data = mnsvc2(para1, md5Para1, this.stringifyCookies(cookieString));
23791
+ await page.locator("#content-area .menu-container .publish-video .btn-wrapper .btn-inner").click();
23792
+ await page.locator('.header-tabs .creator-tab:not([style*="-9999px"])').filter({
23793
+ hasText: /^上传图文$/
23794
+ }).click();
23795
+ const images = await Promise.all(params.banners.map((url)=>{
23796
+ const fileName = (0, share_namespaceObject.getFilenameFromUrl)(url);
23797
+ return (0, share_namespaceObject.downloadImage)(url, external_node_path_default().join(tmpCachePath, fileName));
23798
+ }));
23799
+ const fileChooser = await page.$("input.upload-input");
23800
+ if (fileChooser) await fileChooser.setInputFiles(images);
23801
+ const titleInstance = page.locator(".input input");
23802
+ await titleInstance.waitFor({
23803
+ state: "visible",
23804
+ timeout: 50000
23805
+ });
23806
+ await titleInstance.click();
23807
+ await titleInstance.fill(params.title);
23808
+ const descInstance = page.locator(".editor-container .tiptap.ProseMirror");
23809
+ await descInstance.click();
23810
+ await descInstance.pressSequentially(params.content.replace(/#.*?\[.*?]#/g, ""));
23811
+ if (params.topic && params.topic.length > 0) for (const it of params.topic){
23812
+ await descInstance.pressSequentially(`#${it.name}`);
23813
+ await page.locator("#creator-editor-topic-container").waitFor({
23814
+ state: "visible"
23815
+ });
23816
+ await page.waitForTimeout(500);
23817
+ await page.locator("#creator-editor-topic-container .item").first().click();
23818
+ }
23819
+ if (params.address) await selectAddress(page.locator(".address-card-wrapper .d-select-wrapper"), params.address.name);
23820
+ if (params.selfDeclaration) {
23821
+ await page.locator(".declaration-wrapper .d-select-wrapper").click();
23822
+ const poperInstance = await getPoperInstance();
23823
+ const selfDeclarationInstance = poperInstance.locator(".d-options .d-option");
23824
+ if ("fictional-rendition" === params.selfDeclaration.type) await selfDeclarationInstance.filter({
23825
+ hasText: "虚构演绎,仅供娱乐"
23826
+ }).click();
23827
+ else if ("ai-generated" === params.selfDeclaration.type) await selfDeclarationInstance.filter({
23828
+ hasText: "笔记含AI合成内容"
23829
+ }).click();
23830
+ else if ("source-statement" === params.selfDeclaration.type) {
23831
+ await selfDeclarationInstance.filter({
23832
+ hasText: /内容来源声明/
23833
+ }).click();
23834
+ const selfDeclarationSecondaryMenuInstance = (await getPoperInstance()).locator(".d-options .d-option");
23835
+ await selfDeclarationSecondaryMenuInstance.first().waitFor();
23836
+ if ("self-labeling" === params.selfDeclaration.childType) await selfDeclarationSecondaryMenuInstance.filter({
23837
+ hasText: "已在正文中自主标注"
23838
+ }).click();
23839
+ else if ("self-shooting" === params.selfDeclaration.childType) {
23840
+ const { shootingDate, shootingLocation } = params.selfDeclaration;
23841
+ await selfDeclarationSecondaryMenuInstance.filter({
23842
+ hasText: "自主拍摄"
23843
+ }).click();
23844
+ const selfShootingPopup = await getDialogInstance();
23845
+ const hasCustomContent = shootingDate || shootingLocation;
23846
+ if (shootingLocation) await selectAddress(selfShootingPopup.locator(".address-input"), shootingLocation.name);
23847
+ if (shootingDate) await selectDate(selfShootingPopup.locator(".date-picker input"), shootingDate);
23848
+ await selfShootingPopup.locator("footer button").filter({
23849
+ hasText: hasCustomContent ? "确认" : "取消"
23850
+ }).click();
23851
+ } else if ("transshipment" === params.selfDeclaration.childType) {
23852
+ await selfDeclarationSecondaryMenuInstance.filter({
23853
+ hasText: "来源转载"
23854
+ }).click();
23855
+ const selfShootingPopup = await getDialogInstance();
23856
+ const sourceMedia = params.selfDeclaration.sourceMedia;
23857
+ if (sourceMedia) await selfShootingPopup.locator(".el-input input").fill(sourceMedia);
23858
+ await selfShootingPopup.locator("footer button").filter({
23859
+ hasText: sourceMedia ? "确认" : "取消"
23860
+ }).click();
23861
+ }
23862
+ }
23863
+ }
23864
+ if ("private" === params.visibleRange) {
23865
+ await page.locator(".publish-page-content-setting-content .d-select-wrapper").last().click();
23866
+ const poperInstance = await getPoperInstance();
23867
+ await poperInstance.locator(".d-options .d-option").filter({
23868
+ hasText: "仅自己可见"
23869
+ }).click();
23870
+ }
23871
+ task._timerRecord.PrePublish = Date.now();
23872
+ const releaseTimeInstance = page.locator("label").filter({
23873
+ hasText: params.isImmediatelyPublish ? "立即发布" : "定时发布"
23874
+ });
23875
+ await releaseTimeInstance.click();
23876
+ if (params.scheduledPublish) await selectDate(".date-picker input", params.scheduledPublish);
23877
+ await page.waitForFunction(()=>{
23878
+ const publishBtn = Array.from(document.querySelectorAll("button")).find((b)=>b.textContent?.trim() === "发布");
23879
+ const uploading = document.querySelector(".progress-container");
23880
+ return !!publishBtn && !uploading;
23881
+ }, {
23882
+ timeout: 180000,
23883
+ polling: 2000
23884
+ });
23885
+ const response = await new Promise((resolve, reject)=>{
23886
+ const handleResponse = async (response)=>{
23887
+ if (response.url().includes("/web_api/sns/v2/note")) {
23888
+ const jsonResponse = await response.json();
23889
+ page.off("response", handleResponse);
23890
+ if (jsonResponse?.success) resolve(jsonResponse?.data?.id);
23891
+ else reject(new Error(jsonResponse?.msg || "发布失败"));
23892
+ }
23893
+ };
23894
+ page.on("response", handleResponse);
23895
+ page.locator(".publish-page-publish-btn button").filter({
23896
+ hasText: "发布"
23897
+ }).click();
23898
+ });
23899
+ await updateTaskState?.({
23900
+ state: share_namespaceObject.TaskState.SUCCESS,
23901
+ result: {
23902
+ response
23903
+ }
23904
+ });
23905
+ await page.close();
23906
+ return (0, share_namespaceObject.success)(response);
23907
+ };
23908
+ const xiaohongshuPublish_rpa_server_rpaAction_Server = async (task, params)=>{
23909
+ if (params.originalBind && params?.selfDeclaration?.type === "source-statement") return {
23910
+ code: 414,
23911
+ message: "已声明原创不可选择“来源转载”",
23912
+ data: ""
23913
+ };
23914
+ const defaultPage = task.steelBrowserContext?.pages()[0];
23915
+ if (defaultPage) {
23916
+ if (!defaultPage._routeRegistered) {
23917
+ defaultPage._routeRegistered = true;
23918
+ const blockedPatterns = [
23919
+ "**/ffmpeg-core.wasm*",
23920
+ "**/apm-fe.xiaohongshu.com*",
23921
+ "**/t2.xiaohongshu.com*",
23922
+ "**/fe-video-qc.xhscdn.com*"
23923
+ ].map((pattern)=>new RegExp(pattern.replace(/\*\*/g, ".*").replace(/\*/g, "[^/]*")));
23924
+ await defaultPage.route("**/*", async (route)=>{
23925
+ const req = route.request();
23926
+ const url = req.url();
23927
+ const blocked = blockedPatterns.some((regex)=>regex.test(url));
23928
+ if (!blocked) return route.continue();
23929
+ if ("OPTIONS" === req.method()) {
23930
+ console.log("处理 OPTIONS 预检:", url);
23931
+ await route.fulfill({
23932
+ status: 204,
23933
+ headers: {
23934
+ "access-control-allow-origin": "*",
23935
+ "access-control-allow-methods": "GET,POST,OPTIONS,PUT,DELETE",
23936
+ "access-control-allow-headers": "*"
23937
+ },
23938
+ body: ""
23939
+ });
23940
+ return;
23941
+ }
23942
+ await route.fulfill({
23943
+ status: 204,
23944
+ body: ""
23945
+ });
23946
+ });
23947
+ }
23948
+ }
23949
+ const tmpCachePath = task.getTmpPath();
23950
+ task.logger?.info("==>进入RPA操作:任务开始,下载图片开始...");
23951
+ const updateTaskState = task.taskStageStore?.update?.bind(task.taskStageStore, task.taskId || "");
23952
+ const imagePromise = Promise.all(params.banners.map((url)=>{
23953
+ const fileName = (0, share_namespaceObject.getFilenameFromUrl)(url);
23954
+ return (0, share_namespaceObject.downloadImage)(url, external_node_path_default().join(tmpCachePath, fileName));
23955
+ }));
23956
+ let proxyUrl;
23957
+ if (params.localIP) {
23958
+ const args = [
23959
+ params.localIP,
23960
+ params.proxyLoc,
23961
+ params.accountId
23962
+ ];
23963
+ task.logger?.info(`==> 开始获取代理信息:${args}`);
23964
+ const ProxyAgentResult = await ProxyAgent({
23965
+ logger: task.logger
23966
+ }, ...args);
23967
+ task.logger?.info("==> 代理信息获取成功!");
23968
+ proxyUrl = ProxyAgentResult ? `http://${ProxyAgentResult.ip}:${ProxyAgentResult.port}` : void 0;
23969
+ }
23970
+ task.logger?.info("==>开始打开小红书页面...");
23971
+ const page = await task.createPage({
23972
+ show: task.debug,
23973
+ cookies: params.cookies,
23974
+ proxyUrl,
23975
+ url: params.url || "https://creator.xiaohongshu.com/publish/publish?source=official&from=menu&target=image",
23976
+ ...params.viewport ? {
23977
+ viewport: params.viewport
23978
+ } : {}
23979
+ });
23980
+ task.logger?.info("==>小红书页面打开成功");
23981
+ await updateTaskState?.({
23982
+ state: share_namespaceObject.TaskState.ACTION,
23983
+ connectAddress: task.steelConnector?.getProxyUrl(task.sessionId || "", "v1/sessions/debug"),
23984
+ sessionId: task.sessionId
23985
+ });
23986
+ const clickTimeout = 10000;
23987
+ const selectAddress = async (selector, address)=>{
23988
+ const instance = "string" == typeof selector ? page.locator(selector) : selector;
23989
+ await instance.click({
23990
+ timeout: clickTimeout
23991
+ });
23992
+ await instance.locator("input").fill(address);
23993
+ const poperInstance = page.locator('.d-popover:not([style*="display: none"]) .d-options .d-grid-item');
23994
+ await poperInstance.first().waitFor();
23995
+ await poperInstance.first().click({
23996
+ timeout: clickTimeout
23997
+ });
23998
+ };
23999
+ const selectDate = async (selector, date)=>{
24000
+ const instance = "string" == typeof selector ? page.locator(selector) : selector;
24001
+ await instance.click({
24002
+ timeout: clickTimeout
24003
+ });
24004
+ await instance.fill(date);
24005
+ await instance.blur();
24006
+ };
24007
+ const getPoperInstance = async ()=>{
24008
+ await page.waitForTimeout(500);
24009
+ const elements = page.locator(".d-popover");
24010
+ const count = await elements.count();
24011
+ const visibleElements = [];
24012
+ for(let i = 0; i < count; i++){
24013
+ const element = elements.nth(i);
24014
+ const style = await element.getAttribute("style");
24015
+ if (style && !style.includes("display: none")) visibleElements.push(element);
24016
+ }
24017
+ if (visibleElements.length > 0) return visibleElements[visibleElements.length - 1];
24018
+ throw new Error("未找到 popover 弹窗");
24019
+ };
24020
+ const getDialogInstance = async ()=>{
24021
+ await page.waitForTimeout(1000);
24022
+ const elements = page.locator(".el-dialog");
24023
+ return elements.last();
24024
+ };
24025
+ try {
24026
+ await page.waitForSelector("#CreatorPlatform", {
24027
+ state: "attached"
24028
+ });
24029
+ } catch (error) {
23602
24030
  return {
23603
- "X-S": xhs_ob_feed_encode_mnsv2(mnsvc2_data, xsecAppid, "Windows", "object")
24031
+ code: 414,
24032
+ message: "登录失效",
24033
+ data: page.url()
23604
24034
  };
23605
24035
  }
24036
+ const images = await imagePromise;
24037
+ task.logger?.info(`==>图片下载完成,共 ${images.length} 张,开始上传图片...`);
24038
+ const fileChooser = await page.waitForSelector("input.upload-input", {
24039
+ timeout: 10000
24040
+ });
24041
+ if (fileChooser) await fileChooser.setInputFiles(images, {
24042
+ timeout: 60000
24043
+ }).catch((err)=>{
24044
+ task.logger?.error(`设置上传文件失败:${err.message}`);
24045
+ });
24046
+ else task.logger?.error("文件上传输入框未找到");
24047
+ task.logger?.info("==>图片上传完成,开始渲染预览图...");
24048
+ const titleInstance = page.locator(".input input");
24049
+ await titleInstance.waitFor({
24050
+ state: "attached",
24051
+ timeout: 60000
24052
+ });
24053
+ await titleInstance.click({
24054
+ timeout: 24 * clickTimeout
24055
+ });
24056
+ task.logger?.info("==> 预览图渲染成功,开始RPA操作!");
24057
+ await titleInstance.fill(params.title);
24058
+ const descInstance = page.locator(".editor-container .tiptap.ProseMirror");
24059
+ await descInstance.click({
24060
+ timeout: clickTimeout
24061
+ });
24062
+ await descInstance.fill(`${params.content.replace(/#.*?\[.*?]#/g, "")}\n`);
24063
+ await page.keyboard.press("Control+End");
24064
+ if (params.topic && params.topic.length > 0) for (const it of params.topic){
24065
+ await page.keyboard.insertText(`#${it.name}`);
24066
+ await page.locator(".ql-mention-loading").waitFor({
24067
+ state: "detached"
24068
+ });
24069
+ await page.waitForTimeout(1000);
24070
+ await page.locator("#creator-editor-topic-container .item.is-selected").click({
24071
+ timeout: clickTimeout
24072
+ });
24073
+ await page.keyboard.press("Control+End");
24074
+ }
24075
+ const container = page.locator(".plugin.editor-container");
24076
+ await container.focus();
24077
+ await page.mouse.wheel(0, 500);
24078
+ if (params.address) await selectAddress(page.locator(".media-extension .address-input").filter({
24079
+ hasText: "添加地点"
24080
+ }), params.address.name);
24081
+ if (params.collectionBind) {
24082
+ await page.locator(".media-extension .collection-container").filter({
24083
+ hasText: "添加合集"
24084
+ }).click({
24085
+ timeout: clickTimeout
24086
+ });
24087
+ const collectionName = params.collectionBind.name;
24088
+ const collectionBindInstance = await getPoperInstance();
24089
+ const collectionItemInstance = collectionBindInstance.locator(".d-grid-item .item-label", {
24090
+ hasText: collectionName
24091
+ });
24092
+ await collectionBindInstance.locator(".loading").waitFor({
24093
+ state: "detached"
24094
+ });
24095
+ await collectionItemInstance.click({
24096
+ timeout: clickTimeout
24097
+ });
24098
+ }
24099
+ if (params.groupBind) {
24100
+ await page.locator(".media-extension .address-input").filter({
24101
+ hasText: "选择群聊"
24102
+ }).click({
24103
+ timeout: clickTimeout
24104
+ });
24105
+ const groupBindName = params.groupBind.group_name;
24106
+ const groupBindInstance = await getPoperInstance();
24107
+ const groupItemInstance = groupBindInstance.locator(".d-grid-item .name", {
24108
+ hasText: groupBindName
24109
+ });
24110
+ await groupBindInstance.locator(".loading").waitFor({
24111
+ state: "detached"
24112
+ });
24113
+ await groupItemInstance.click({
24114
+ timeout: clickTimeout
24115
+ });
24116
+ }
24117
+ const OriginalBindBtn = page.locator(".btn-text.red", {
24118
+ hasText: "去声明"
24119
+ });
24120
+ const isOriginalBindBtnVisible = await OriginalBindBtn.isVisible();
24121
+ if (isOriginalBindBtnVisible && params.originalBind) {
24122
+ await OriginalBindBtn.click({
24123
+ timeout: clickTimeout
24124
+ });
24125
+ const poperInstance = await getPoperInstance();
24126
+ await poperInstance.locator(".d-checkbox-simulator").click({
24127
+ timeout: clickTimeout
24128
+ });
24129
+ await poperInstance.locator(".footer .custom-button.bg-red").click({
24130
+ timeout: clickTimeout
24131
+ });
24132
+ }
24133
+ if (params.selfDeclaration) {
24134
+ await page.locator(".media-settings .flexbox").filter({
24135
+ hasText: "内容类型声明"
24136
+ }).locator(".d-select-placeholder").click({
24137
+ timeout: clickTimeout
24138
+ });
24139
+ const poperInstance = await getPoperInstance();
24140
+ const selfDeclarationInstance = poperInstance.locator(".d-options .d-option");
24141
+ if ("fictional-rendition" === params.selfDeclaration.type) await selfDeclarationInstance.filter({
24142
+ hasText: "虚构演绎,仅供娱乐"
24143
+ }).click({
24144
+ timeout: clickTimeout
24145
+ });
24146
+ else if ("ai-generated" === params.selfDeclaration.type) await selfDeclarationInstance.filter({
24147
+ hasText: "笔记含AI合成内容"
24148
+ }).click({
24149
+ timeout: clickTimeout
24150
+ });
24151
+ else if ("source-statement" === params.selfDeclaration.type) {
24152
+ await selfDeclarationInstance.filter({
24153
+ hasText: /内容来源声明/
24154
+ }).click({
24155
+ timeout: clickTimeout
24156
+ });
24157
+ const selfDeclarationSecondaryMenuInstance = (await getPoperInstance()).locator(".d-options .d-option");
24158
+ await selfDeclarationSecondaryMenuInstance.first().waitFor();
24159
+ if ("self-labeling" === params.selfDeclaration.childType) await selfDeclarationSecondaryMenuInstance.filter({
24160
+ hasText: "已在正文中自主标注"
24161
+ }).click({
24162
+ timeout: clickTimeout
24163
+ });
24164
+ else if ("self-shooting" === params.selfDeclaration.childType) {
24165
+ const { shootingDate, shootingLocation } = params.selfDeclaration;
24166
+ await selfDeclarationSecondaryMenuInstance.filter({
24167
+ hasText: "自主拍摄"
24168
+ }).click({
24169
+ timeout: clickTimeout
24170
+ });
24171
+ const selfShootingPopup = await getDialogInstance();
24172
+ const hasCustomContent = shootingDate || shootingLocation;
24173
+ if (shootingLocation) await selectAddress(selfShootingPopup.locator(".address-input"), shootingLocation.name);
24174
+ if (shootingDate) await selectDate(selfShootingPopup.locator(".date-picker input"), shootingDate);
24175
+ await selfShootingPopup.locator("footer button").filter({
24176
+ hasText: hasCustomContent ? "确认" : "取消"
24177
+ }).click({
24178
+ timeout: clickTimeout
24179
+ });
24180
+ } else if ("transshipment" === params.selfDeclaration.childType) {
24181
+ await selfDeclarationSecondaryMenuInstance.filter({
24182
+ hasText: "来源转载"
24183
+ }).click({
24184
+ timeout: clickTimeout
24185
+ });
24186
+ const selfShootingPopup = await getDialogInstance();
24187
+ const sourceMedia = params.selfDeclaration.sourceMedia;
24188
+ if (sourceMedia) await selfShootingPopup.locator(".el-input input").fill(sourceMedia);
24189
+ await selfShootingPopup.locator("footer button").filter({
24190
+ hasText: sourceMedia ? "确认" : "取消"
24191
+ }).click({
24192
+ timeout: clickTimeout
24193
+ });
24194
+ }
24195
+ }
24196
+ }
24197
+ if ("public" !== params.visibleRange) {
24198
+ await page.locator(".media-settings .flexbox").filter({
24199
+ hasText: "可见范围"
24200
+ }).locator(".d-select-wrapper").click({
24201
+ timeout: clickTimeout
24202
+ });
24203
+ const poperInstance = await getPoperInstance();
24204
+ const visibleText = "friends" === params.visibleRange ? "好友可见" : "仅自己可见";
24205
+ await poperInstance.locator(".d-options .custom-option").filter({
24206
+ hasText: visibleText
24207
+ }).click({
24208
+ timeout: clickTimeout
24209
+ });
24210
+ }
24211
+ async function setSwitch(page, label, target) {
24212
+ const item = page.locator(".d-new-form-item", {
24213
+ has: page.locator(".d-form-item__label", {
24214
+ hasText: label
24215
+ })
24216
+ });
24217
+ const switchUI = item.locator(".d-switch-simulator");
24218
+ const cls = await switchUI.getAttribute("class");
24219
+ const isChecked = cls?.includes("checked") || true;
24220
+ if (isChecked !== target) await switchUI.click({
24221
+ timeout: clickTimeout
24222
+ });
24223
+ }
24224
+ if (!params.coProduceBind) await setSwitch(page, "允许合拍", false);
24225
+ if (!params.noteCopyBind) await setSwitch(page, "允许正文复制", false);
24226
+ const releaseTimeInstance = page.locator("label").filter({
24227
+ hasText: params.isImmediatelyPublish ? "立即发布" : "定时发布"
24228
+ });
24229
+ await releaseTimeInstance.click({
24230
+ timeout: clickTimeout
24231
+ });
24232
+ if (params.scheduledPublish) await selectDate(".date-picker input", params.scheduledPublish);
24233
+ const imgPreviewArea = page.locator(".img-preview-area");
24234
+ try {
24235
+ await imgPreviewArea.locator(".mask.uploading").waitFor({
24236
+ state: "hidden",
24237
+ timeout: 50000
24238
+ });
24239
+ } catch (error) {
24240
+ throw new Error("上传图片超时,请重试!");
24241
+ }
24242
+ if (MockPublish) {
24243
+ const message = "文章模拟发布成功";
24244
+ const data = "123456789";
24245
+ await updateTaskState?.({
24246
+ state: share_namespaceObject.TaskState.SUCCESS,
24247
+ result: {
24248
+ response: data
24249
+ }
24250
+ });
24251
+ return (0, share_namespaceObject.success)(data, message);
24252
+ }
24253
+ const response = await new Promise((resolve)=>{
24254
+ const handleResponse = async (response)=>{
24255
+ if (response.url().includes("/web_api/sns/v2/note")) {
24256
+ const jsonResponse = await response.json();
24257
+ page.off("response", handleResponse);
24258
+ resolve(jsonResponse);
24259
+ }
24260
+ };
24261
+ page.on("response", handleResponse);
24262
+ page.locator(".submit .publishBtn").click({
24263
+ timeout: clickTimeout
24264
+ });
24265
+ page.waitForSelector(".d-toast-icon-danger", {
24266
+ state: "visible",
24267
+ timeout: 2000
24268
+ }).then(async ()=>{
24269
+ await page.waitForTimeout(300);
24270
+ const toastDesc = await page.locator(".d-toast-description").textContent();
24271
+ const desc = toastDesc?.trim();
24272
+ page.off("response", handleResponse);
24273
+ resolve({
24274
+ success: false,
24275
+ msg: desc || "未知错误"
24276
+ });
24277
+ }).catch(()=>{});
24278
+ setTimeout(()=>{
24279
+ page.off("response", handleResponse);
24280
+ resolve({
24281
+ success: false,
24282
+ msg: "发布超时"
24283
+ });
24284
+ }, 7000);
24285
+ });
24286
+ if (!response?.success) {
24287
+ const msg = `发布失败:${response?.msg || "未知错误"}`;
24288
+ await updateTaskState?.({
24289
+ state: share_namespaceObject.TaskState.FAILED,
24290
+ error: msg
24291
+ });
24292
+ await page.close();
24293
+ return {
24294
+ code: 414,
24295
+ message: msg,
24296
+ data: ""
24297
+ };
24298
+ }
24299
+ await updateTaskState?.({
24300
+ state: share_namespaceObject.TaskState.SUCCESS,
24301
+ result: {
24302
+ response: response?.data?.id || ""
24303
+ }
24304
+ });
24305
+ await page.close();
24306
+ return (0, share_namespaceObject.success)(response?.data?.id || "");
24307
+ };
24308
+ const rpa_server_mock_encode_mnsv2 = __webpack_require__("./src/utils/xhs_ob/x_s.encoder.js");
24309
+ function Md5(input) {
24310
+ return external_node_crypto_default().createHash("md5").update(input).digest("hex");
23606
24311
  }
23607
- const xiaohongshuWebNoteFeed_xsEncrypt = new xhs_ob_feed_Xhshow();
23608
- const GenXSCommon = __webpack_require__("./src/utils/XhsXsCommonEnc.js");
23609
- const xiaohongshuWebNoteFeed = async (_task, params)=>{
23610
- if (DisabledReq) return (0, share_namespaceObject.response)(414, "获取指定文章详情失败", {});
24312
+ const rpa_server_mock_errnoMap = {
24313
+ "-1": "未知拦截器错误,请稍后重试。",
24314
+ 915: "所属C端账号手机号被修改,请重新登录",
24315
+ 914: "所属C端账号密码被修改,请重新登录",
24316
+ 903: "账户已登出,需重新登陆重试!",
24317
+ 902: "登录已过期,请重新登录!",
24318
+ 906: "账号存在风险,请重新登录!",
24319
+ "-9136": "因违反社区规范禁止发笔记,请检查账号状态!"
24320
+ };
24321
+ const rpa_server_mock_xsEncrypt = new Xhshow();
24322
+ const rpaAction_Server_Mock = async (task, params)=>{
24323
+ const updateTaskState = task.taskStageStore?.update?.bind(task.taskStageStore, task.taskId || "");
24324
+ const tmpCachePath = task.getTmpPath();
24325
+ if (params?.selfDeclaration?.type === "source-statement" && "transshipment" === params.selfDeclaration.childType && params.originalBind) return {
24326
+ code: 414,
24327
+ message: "原创声明与转载声明互斥,请重新选择后发布!",
24328
+ data: ""
24329
+ };
24330
+ const a1Cookie = params.cookies.find((it)=>"a1" === it.name)?.value;
24331
+ if (!a1Cookie) return {
24332
+ code: 414,
24333
+ message: "账号数据异常,请重新绑定账号后重试。",
24334
+ data: ""
24335
+ };
24336
+ const defaultPage = task.steelBrowserContext?.pages()[0];
24337
+ if (defaultPage) {
24338
+ if (!defaultPage._routeRegistered) {
24339
+ defaultPage._routeRegistered = true;
24340
+ const blockedPatterns = [
24341
+ "**/ffmpeg-core.wasm*",
24342
+ "**/apm-fe.xiaohongshu.com*",
24343
+ "**/t2.xiaohongshu.com*",
24344
+ "**/fe-video-qc.xhscdn.com*"
24345
+ ].map((pattern)=>new RegExp(pattern.replace(/\*\*/g, ".*").replace(/\*/g, "[^/]*")));
24346
+ await defaultPage.route("**/*", async (route)=>{
24347
+ const req = route.request();
24348
+ const url = req.url();
24349
+ const blocked = blockedPatterns.some((regex)=>regex.test(url));
24350
+ if (!blocked) return route.continue();
24351
+ if ("OPTIONS" === req.method()) {
24352
+ console.log("处理 OPTIONS 预检:", url);
24353
+ await route.fulfill({
24354
+ status: 204,
24355
+ headers: {
24356
+ "access-control-allow-origin": "*",
24357
+ "access-control-allow-methods": "GET,POST,OPTIONS,PUT,DELETE",
24358
+ "access-control-allow-headers": "*"
24359
+ },
24360
+ body: ""
24361
+ });
24362
+ return;
24363
+ }
24364
+ await route.fulfill({
24365
+ status: 204,
24366
+ body: ""
24367
+ });
24368
+ });
24369
+ }
24370
+ }
24371
+ const pagePromise = task.createPage({
24372
+ show: task.debug,
24373
+ cookies: params.cookies,
24374
+ url: params.url || "https://creator.xiaohongshu.com/statistics/account/v2?source=official"
24375
+ });
24376
+ await updateTaskState?.({
24377
+ state: share_namespaceObject.TaskState.ACTION
24378
+ });
23611
24379
  const headers = {
23612
24380
  cookie: params.cookies.map((it)=>`${it.name}=${it.value}`).join(";"),
23613
- referer: "https://www.xiaohongshu.com/",
23614
- origin: "https://www.xiaohongshu.com/"
24381
+ origin: "https://creator.xiaohongshu.com",
24382
+ referer: "https://creator.xiaohongshu.com/",
24383
+ "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"
23615
24384
  };
24385
+ const recordCookie = params.cookies.reduce((acc, cookie)=>{
24386
+ if (cookie.name && cookie.value) acc[cookie.name] = cookie.value;
24387
+ return acc;
24388
+ }, {});
23616
24389
  const args = [
23617
24390
  {
23618
24391
  headers
23619
24392
  },
23620
- _task.logger,
24393
+ task.logger,
23621
24394
  params.proxyLoc,
23622
24395
  params.localIP,
23623
24396
  params.accountId
23624
24397
  ];
23625
- const http = new Http(...args);
23626
- const a1Cookie = params.cookies.find((it)=>"a1" === it.name)?.value;
23627
- if (!a1Cookie) return {
24398
+ const http = new Http({
24399
+ headers
24400
+ });
24401
+ const proxyHttp = new Http(...args);
24402
+ proxyHttp.addResponseInterceptor((response)=>{
24403
+ const responseData = response.data;
24404
+ if (response && responseData?.code && 0 !== responseData.code || responseData?.code && !responseData.success) {
24405
+ const errmsg = rpa_server_mock_errnoMap[responseData.code] || response.config.defaultErrorMsg || "文章发布异常,请稍后重试。";
24406
+ return {
24407
+ code: rpa_server_mock_errnoMap[responseData.code] ? 414 : 500,
24408
+ message: errmsg,
24409
+ data: responseData
24410
+ };
24411
+ }
24412
+ });
24413
+ const fetchCoverUrl = "/api/media/v1/upload/creator/permit";
24414
+ const fetchCoverParams = {
24415
+ biz_name: "spectrum",
24416
+ scene: "image",
24417
+ file_count: params.banners.length,
24418
+ version: 1,
24419
+ source: "web"
24420
+ };
24421
+ const fetchCoverXsHeader = rpa_server_mock_xsEncrypt.signHeadersGet(fetchCoverUrl, recordCookie, "ugc", fetchCoverParams);
24422
+ const uploadInfos = [];
24423
+ if (params.banners.length > 18) {
24424
+ let num = Math.ceil(params.banners.length / 14);
24425
+ for(let i = 0; i < num; i++){
24426
+ const start = 14 * i;
24427
+ params.banners.length;
24428
+ ({
24429
+ ...fetchCoverParams
24430
+ });
24431
+ const batchCoverIdInfo = await proxyHttp.api({
24432
+ method: "get",
24433
+ baseURL: "https://creator.xiaohongshu.com",
24434
+ url: fetchCoverUrl,
24435
+ defaultErrorMsg: "获取小红书用户信息失败,请稍后重试发布。",
24436
+ headers: fetchCoverXsHeader,
24437
+ params: fetchCoverParams
24438
+ }, {
24439
+ retries: 3,
24440
+ retryDelay: 20,
24441
+ timeout: 3000
24442
+ });
24443
+ for (const item of batchCoverIdInfo.data.uploadTempPermits)for (const fileId of item.fileIds)uploadInfos.push({
24444
+ bucket: item.bucket || "",
24445
+ uploadAddr: item.uploadAddr || "",
24446
+ fileIds: fileId,
24447
+ token: item.token || ""
24448
+ });
24449
+ }
24450
+ } else {
24451
+ const coverIdInfo = await proxyHttp.api({
24452
+ method: "get",
24453
+ baseURL: "https://creator.xiaohongshu.com",
24454
+ url: fetchCoverUrl,
24455
+ defaultErrorMsg: "获取小红书用户信息失败,请稍后重试发布。",
24456
+ headers: fetchCoverXsHeader,
24457
+ params: fetchCoverParams
24458
+ }, {
24459
+ retries: 3,
24460
+ retryDelay: 20,
24461
+ timeout: 3000
24462
+ });
24463
+ for (const item of coverIdInfo.data.uploadTempPermits)for (const fileId of item.fileIds)uploadInfos.push({
24464
+ bucket: item.bucket || "",
24465
+ uploadAddr: item.uploadAddr || "",
24466
+ fileIds: fileId,
24467
+ token: item.token || ""
24468
+ });
24469
+ }
24470
+ if (uploadInfos.length < params.banners.length) return {
23628
24471
  code: 414,
23629
- message: "账号数据异常,请重新绑定账号后重试。",
23630
- data: {}
24472
+ message: "可用 OSS bucket 数量不足,无法上传所有图片!",
24473
+ data: ""
23631
24474
  };
23632
- if (!params.source_note_id && !params.xsec_token) return {
24475
+ if (0 === uploadInfos.length) return {
23633
24476
  code: 414,
23634
- message: "参数缺失,请检查后重试!",
23635
- data: {}
24477
+ message: "图片上传失败,请稍后重试!",
24478
+ data: ""
24479
+ };
24480
+ const availableBuckets = Array.from({
24481
+ length: uploadInfos.length
24482
+ }, (_, i)=>i);
24483
+ const uploadFile = async (url, index)=>{
24484
+ const fileName = (0, share_namespaceObject.getFilenameFromUrl)(url);
24485
+ const localUrl = await (0, share_namespaceObject.downloadImage)(url, external_node_path_default().join(tmpCachePath, fileName));
24486
+ const fileBuffer = external_node_fs_default().readFileSync(localUrl);
24487
+ const MAX_RETRIES = uploadInfos.length;
24488
+ task.logger.debug(`上传图片 ${index + 1}:尝试使用最多 ${MAX_RETRIES} 个 bucket`);
24489
+ let attempt = 0;
24490
+ while(attempt < MAX_RETRIES){
24491
+ const ossBucketIndex = availableBuckets.shift();
24492
+ if (void 0 === ossBucketIndex) break;
24493
+ const currentInfo = uploadInfos[ossBucketIndex];
24494
+ const ossFileId = currentInfo.fileIds;
24495
+ const ossToken = currentInfo.token;
24496
+ const ossDomain = currentInfo.uploadAddr;
24497
+ try {
24498
+ await http.api({
24499
+ method: "put",
24500
+ url: `https://${ossDomain}/${ossFileId}`,
24501
+ data: fileBuffer,
24502
+ headers: {
24503
+ "x-cos-security-token": ossToken
24504
+ },
24505
+ defaultErrorMsg: "图片上传异常,请稍后重试发布。"
24506
+ });
24507
+ return {
24508
+ ossFileId,
24509
+ ossToken
24510
+ };
24511
+ } catch (error) {
24512
+ task.logger.warn(`上传图片 ${index + 1}:使用 bucket ${ossDomain} 失败,尝试下一个可用 bucket。错误信息:${error.message}`);
24513
+ attempt++;
24514
+ }
24515
+ }
24516
+ return {
24517
+ ossFileId: "",
24518
+ ossToken: ""
24519
+ };
24520
+ };
24521
+ const coverInfos = await Promise.all(params.banners.map((it, idx)=>uploadFile(it, idx)));
24522
+ const invalidUpload = coverInfos.find((it)=>"" === it.ossToken || "" === it.ossFileId);
24523
+ if (invalidUpload) return {
24524
+ code: 414,
24525
+ message: "图片上传异常,请稍后重试发布。",
24526
+ data: ""
24527
+ };
24528
+ if (params.topic && params.topic.length > 0) await Promise.all(params.topic.map(async (topic)=>{
24529
+ if (!topic.id) {
24530
+ const topicData = {
24531
+ topic_names: topic.name
24532
+ };
24533
+ const topicXsHeader = rpa_server_mock_xsEncrypt.signHeadersPost("/web_api/sns/capa/postgw/topic/batch_customized", recordCookie, "ugc", topicData);
24534
+ const createTopic = await proxyHttp.api({
24535
+ method: "POST",
24536
+ url: "https://edith.xiaohongshu.com/web_api/sns/capa/postgw/topic/batch_customized",
24537
+ headers: topicXsHeader,
24538
+ data: topicData,
24539
+ defaultErrorMsg: "话题创建异常,请稍后重试。"
24540
+ }, {
24541
+ retries: 3,
24542
+ retryDelay: 20,
24543
+ timeout: 3000
24544
+ });
24545
+ Object.assign(topic, createTopic.data.topic_infos[0]);
24546
+ }
24547
+ }));
24548
+ const visibleRangeMap = {
24549
+ public: 0,
24550
+ private: 1,
24551
+ friends: 4
23636
24552
  };
23637
- const feedParams = {
23638
- source_note_id: params.source_note_id,
23639
- image_formats: [
23640
- "jpg",
23641
- "webp",
23642
- "avif"
23643
- ],
23644
- extra: {
23645
- need_body_topic: "1"
24553
+ const publishData = {
24554
+ common: {
24555
+ ats: [],
24556
+ biz_relations: [],
24557
+ desc: params?.content,
24558
+ goods_info: {},
24559
+ hash_tag: params.topic || [],
24560
+ note_id: "",
24561
+ source: JSON.stringify({
24562
+ type: "web",
24563
+ ids: "",
24564
+ extraInfo: '{"systemId":"web"}'
24565
+ }),
24566
+ title: params?.title,
24567
+ type: "normal",
24568
+ privacy_info: {
24569
+ op_type: 1,
24570
+ type: visibleRangeMap[params.visibleRange]
24571
+ },
24572
+ post_loc: params.address ? {
24573
+ name: params.address?.name,
24574
+ poi_id: params.address?.poi_id,
24575
+ poi_type: params.address?.poi_type,
24576
+ subname: params.address?.full_address
24577
+ } : null,
24578
+ business_binds: ""
23646
24579
  },
23647
- xsec_source: "pc_feed",
23648
- xsec_token: params.xsec_token
24580
+ image_info: {
24581
+ images: coverInfos.map((it)=>({
24582
+ extra_info_json: '{"mimeType":"image/png"}',
24583
+ file_id: it.ossFileId,
24584
+ metadata: {
24585
+ source: -1
24586
+ },
24587
+ stickers: {
24588
+ floating: [],
24589
+ version: 2
24590
+ }
24591
+ }))
24592
+ },
24593
+ video_info: null
23649
24594
  };
23650
- const fatchFeed = "/api/sns/web/v1/feed";
23651
- const recordCookie = params.cookies.reduce((acc, cookie)=>{
23652
- if (cookie.name && cookie.value) acc[cookie.name] = cookie.value;
23653
- return acc;
23654
- }, {});
23655
- const xsHeader = xiaohongshuWebNoteFeed_xsEncrypt.signHeadersPost(fatchFeed, recordCookie, "xhs-pc-web", feedParams);
23656
- const xT = Date.now().toString();
23657
- const xsCommon = GenXSCommon(a1Cookie, xT, xsHeader["X-S"]);
23658
- _task.logger.info(`请求参数: ${JSON.stringify(feedParams)}`);
23659
- _task.logger.info(`X-S: ${xsHeader["X-S"]}`);
23660
- _task.logger.info(`x-s-common: ${xsCommon}`);
23661
- const res = await http.api({
23662
- method: "post",
23663
- url: "https://edith.xiaohongshu.com/api/sns/web/v1/feed",
23664
- data: feedParams,
23665
- headers: {
23666
- "X-S": xsHeader["X-S"],
23667
- "X-S-Common": xsCommon,
23668
- "X-T": xT
24595
+ const userDeclarationBind = {
24596
+ origin: 2,
24597
+ photoInfo: {},
24598
+ repostInfo: {}
24599
+ };
24600
+ if (params.selfDeclaration?.type === "fictional-rendition") userDeclarationBind.origin = 1;
24601
+ else if (params.selfDeclaration?.type === "ai-generated") userDeclarationBind.origin = 2;
24602
+ else if (params.selfDeclaration?.type === "source-statement") {
24603
+ if ("self-labeling" === params.selfDeclaration.childType) userDeclarationBind.origin = 3;
24604
+ else if ("self-shooting" === params.selfDeclaration.childType) {
24605
+ userDeclarationBind.origin = 4;
24606
+ const photoInfo = {};
24607
+ if (params.selfDeclaration.shootingLocation) photoInfo.photoPlace = {
24608
+ name: params.selfDeclaration.shootingLocation.name,
24609
+ poiId: params.selfDeclaration.shootingLocation.poi_id,
24610
+ poiType: params.selfDeclaration.shootingLocation.poi_type,
24611
+ subname: params.selfDeclaration.shootingLocation.full_address
24612
+ };
24613
+ if (params.selfDeclaration.shootingDate) photoInfo.photoTime = params.selfDeclaration.shootingDate;
24614
+ userDeclarationBind.photoInfo = photoInfo;
24615
+ } else if ("transshipment" === params.selfDeclaration.childType) {
24616
+ userDeclarationBind.origin = 5;
24617
+ if (params.selfDeclaration.sourceMedia) userDeclarationBind.repostInfo = {
24618
+ source: params.selfDeclaration.sourceMedia
24619
+ };
23669
24620
  }
24621
+ }
24622
+ const bizId = params?.originalBind && (params.cookies.find((it)=>"x-user-id-creator.xiaohongshu.com" === it.name)?.value || await proxyHttp.api({
24623
+ method: "get",
24624
+ url: "https://creator.xiaohongshu.com/api/galaxy/user/my-info"
23670
24625
  }, {
23671
24626
  retries: 3,
23672
24627
  retryDelay: 20,
23673
24628
  timeout: 3000
24629
+ }).then((userData)=>userData.data?.userDetail?.id));
24630
+ const business_binds = {
24631
+ version: 1,
24632
+ bizType: "",
24633
+ noteId: "",
24634
+ noteOrderBind: {},
24635
+ notePostTiming: params.isImmediatelyPublish ? {} : {
24636
+ postTime: params.scheduledPublish
24637
+ },
24638
+ coProduceBind: {
24639
+ enable: !!params?.coProduceBind
24640
+ },
24641
+ noteCopyBind: {
24642
+ copyable: !!params?.noteCopyBind
24643
+ },
24644
+ optionRelationList: params.originalBind ? [
24645
+ {
24646
+ type: "ORIGINAL_STATEMENT",
24647
+ relationList: [
24648
+ {
24649
+ bizId,
24650
+ bizType: "ORIGINAL_STATEMENT",
24651
+ extraInfo: "{}"
24652
+ }
24653
+ ]
24654
+ }
24655
+ ] : [],
24656
+ ...params?.groupBind ? {
24657
+ groupBind: {
24658
+ groupId: params?.groupBind?.group_id,
24659
+ groupName: params.groupBind?.group_name,
24660
+ desc: params.groupBind?.desc,
24661
+ avatar: params.groupBind?.avatar
24662
+ }
24663
+ } : {
24664
+ groupBind: {}
24665
+ },
24666
+ ...params.selfDeclaration ? {
24667
+ userDeclarationBind
24668
+ } : {},
24669
+ ...params?.collectionBind?.id ? {
24670
+ noteCollectionBind: {
24671
+ id: params.collectionBind.id
24672
+ }
24673
+ } : {}
24674
+ };
24675
+ publishData.common.business_binds = JSON.stringify(business_binds);
24676
+ task._timerRecord.PrePublish = Date.now();
24677
+ const page = await pagePromise;
24678
+ await updateTaskState?.({
24679
+ sessionId: task.sessionId
23674
24680
  });
23675
- _task.logger.info(`API 响应: ${JSON.stringify(res)}`);
23676
- const isSuccess = 0 === res.code && res.data && res.data.items && res.data.items.length > 0;
23677
- const message = `获取指定文章详情${isSuccess ? "成功" : `失败,原因:${res.msg || "返回数据为空,可能笔记不存在或参数错误"}`}${_task.debug ? ` ${http.proxyInfo}` : ""}`;
23678
- const data = isSuccess ? res.data?.items[0].note_card || {} : {};
23679
- return (0, share_namespaceObject.response)(isSuccess ? 0 : 414, message, data);
24681
+ const publishXsHeader = {
24682
+ "x-s": "",
24683
+ "x-t": Date.now().toString()
24684
+ };
24685
+ await page.waitForFunction(()=>"function" == typeof window.mnsv2, {
24686
+ timeout: 10000
24687
+ });
24688
+ const encodeData = `/web_api/sns/v2/note${JSON.stringify(publishData)}`;
24689
+ const ticket_mnsv2 = await page.evaluate(({ c, d })=>{
24690
+ if ("function" == typeof window.mnsv2) return window.mnsv2(c, d);
24691
+ return "mnsv2 未定义";
24692
+ }, {
24693
+ c: encodeData,
24694
+ d: Md5(encodeData)
24695
+ });
24696
+ publishXsHeader["x-s"] = rpa_server_mock_encode_mnsv2(ticket_mnsv2, "Windows", "object");
24697
+ publishXsHeader["x-t"] = Date.now().toString();
24698
+ if (MockPublish) {
24699
+ const message = `文章模拟发布成功 ${http.proxyInfo}`;
24700
+ const data = "123456789";
24701
+ await updateTaskState?.({
24702
+ state: share_namespaceObject.TaskState.SUCCESS,
24703
+ result: {
24704
+ response: data
24705
+ }
24706
+ });
24707
+ return (0, share_namespaceObject.success)(data, message);
24708
+ }
24709
+ const publishResult = await proxyHttp.api({
24710
+ method: "post",
24711
+ url: "https://edith.xiaohongshu.com/web_api/sns/v2/note",
24712
+ data: publishData,
24713
+ headers: publishXsHeader,
24714
+ defaultErrorMsg: "文章发布异常,请稍后重试。"
24715
+ }, {
24716
+ retries: 2,
24717
+ retryDelay: 500,
24718
+ timeout: 12000
24719
+ });
24720
+ const isSuccess = publishResult.success;
24721
+ const message = `文章发布${isSuccess ? "成功" : `失败,原因:${publishResult.msg}`}${task.debug ? ` ${http.proxyInfo}` : ""}`;
24722
+ const data = isSuccess ? publishResult.data?.id || "" : "";
24723
+ if (!isSuccess) {
24724
+ await updateTaskState?.({
24725
+ state: share_namespaceObject.TaskState.FAILED,
24726
+ error: message
24727
+ });
24728
+ return {
24729
+ code: 414,
24730
+ data,
24731
+ message
24732
+ };
24733
+ }
24734
+ await updateTaskState?.({
24735
+ state: share_namespaceObject.TaskState.SUCCESS,
24736
+ result: {
24737
+ response: data
24738
+ }
24739
+ });
24740
+ return (0, share_namespaceObject.success)(data, message);
24741
+ };
24742
+ const FictionalRendition = schemas_object({
24743
+ type: literal("fictional-rendition")
24744
+ });
24745
+ const AIGenerated = schemas_object({
24746
+ type: literal("ai-generated")
24747
+ });
24748
+ const SourceStatement = schemas_object({
24749
+ type: literal("source-statement"),
24750
+ childType: schemas_enum([
24751
+ "self-labeling",
24752
+ "self-shooting",
24753
+ "transshipment"
24754
+ ]),
24755
+ shootingLocation: custom().optional(),
24756
+ shootingDate: schemas_string().optional(),
24757
+ sourceMedia: schemas_string().optional()
24758
+ });
24759
+ union([
24760
+ FictionalRendition,
24761
+ AIGenerated,
24762
+ SourceStatement
24763
+ ]);
24764
+ const XiaohongshuPublishParamsSchema = ActionCommonParamsSchema.extend({
24765
+ banners: schemas_array(schemas_string()),
24766
+ title: schemas_string(),
24767
+ content: schemas_string(),
24768
+ address: custom().optional(),
24769
+ selfDeclaration: custom().optional(),
24770
+ topic: schemas_array(custom()).optional(),
24771
+ proxyLoc: schemas_string().optional(),
24772
+ localIP: schemas_string().optional(),
24773
+ huiwenToken: schemas_string().optional(),
24774
+ visibleRange: schemas_enum([
24775
+ "public",
24776
+ "private",
24777
+ "friends"
24778
+ ]),
24779
+ isImmediatelyPublish: schemas_boolean().optional(),
24780
+ scheduledPublish: schemas_string().optional(),
24781
+ collectionId: schemas_string().optional(),
24782
+ collectionBind: custom().optional(),
24783
+ groupBind: custom().optional(),
24784
+ noteCopyBind: schemas_boolean().optional(),
24785
+ coProduceBind: schemas_boolean().optional(),
24786
+ originalBind: schemas_boolean().optional()
24787
+ });
24788
+ const xiaohongshuPublish = async (task, params)=>{
24789
+ if (DisabledReq) return {
24790
+ code: 414,
24791
+ data: "",
24792
+ message: "临时维护:小红书发布政策调整,本平台小红书发布功能临时暂停服务并进行维护调整,暂时无法正常发布,敬请理解知悉。"
24793
+ };
24794
+ if ("rpa" === params.actionType) return xiaohongshuPublish_rpa_rpaAction(task, params);
24795
+ if ("mockApi" === params.actionType) return xiaohongshuPublish_mock_mockAction(task, params);
24796
+ if ("server" === params.actionType) return xiaohongshuPublish_rpa_server_rpaAction_Server(task, params);
24797
+ return executeAction(xiaohongshuPublish_mock_mockAction, rpaAction_Server_Mock, xiaohongshuPublish_rpa_server_rpaAction_Server)(task, params);
23680
24798
  };
23681
- const xiaohongshuWebRelationAction_xsEncrypt = new Xhshow();
23682
- const xiaohongshuWebRelationAction = async (_task, params)=>{
23683
- if (DisabledReq) return (0, share_namespaceObject.response)(414, "用户关系操作失败", {});
24799
+ const xiaohongshuWebCommentAction_xsEncrypt = new Xhshow();
24800
+ const xiaohongshuWebCommentAction = async (_task, params)=>{
24801
+ if (DisabledReq) return (0, share_namespaceObject.response)(414, "点赞相关操作失败", {});
23684
24802
  const headers = {
23685
24803
  cookie: params.cookies.map((it)=>`${it.name}=${it.value}`).join(";"),
23686
24804
  referer: "https://www.xiaohongshu.com/",
@@ -23700,47 +24818,52 @@ var __webpack_exports__ = {};
23700
24818
  if (!a1Cookie) return {
23701
24819
  code: 414,
23702
24820
  message: "账号数据异常,请重新绑定账号后重试。",
23703
- data: {}
24821
+ data: []
23704
24822
  };
23705
- if (!params.action || !params.target_user_id) return {
24823
+ if (!params.note_id && !params.comment_id && !params.action) return {
23706
24824
  code: 414,
23707
24825
  message: "参数缺失,请检查后重试!",
23708
24826
  data: {}
23709
24827
  };
23710
- const relationParams = {
23711
- target_user_id: params.target_user_id
24828
+ const actionParams = {
24829
+ note_id: params.note_id,
24830
+ comment_id: params.comment_id
24831
+ };
24832
+ let likeActionRes = {
24833
+ code: 500,
24834
+ success: false,
24835
+ msg: ""
23712
24836
  };
23713
- let relationActionRes;
23714
24837
  const recordCookie = params.cookies.reduce((acc, cookie)=>{
23715
24838
  if (cookie.name && cookie.value) acc[cookie.name] = cookie.value;
23716
24839
  return acc;
23717
24840
  }, {});
23718
24841
  switch(params.action){
23719
- case "follow":
24842
+ case "like":
23720
24843
  {
23721
- const followMentions = "/api/sns/web/v1/user/follow";
23722
- const followXsHeader = xiaohongshuWebRelationAction_xsEncrypt.signHeadersPost(followMentions, recordCookie, "xhs-pc-web", relationParams);
23723
- relationActionRes = await http.api({
24844
+ const likeAction = "/api/sns/web/v1/comment/like";
24845
+ const likeActionXsHeader = xiaohongshuWebCommentAction_xsEncrypt.signHeadersPost(likeAction, recordCookie, "xhs-pc-web", actionParams);
24846
+ likeActionRes = await http.api({
23724
24847
  method: "post",
23725
- url: "https://edith.xiaohongshu.com/api/sns/web/v1/user/follow",
23726
- data: relationParams,
23727
- headers: followXsHeader
24848
+ url: "https://edith.xiaohongshu.com/api/sns/web/v1/comment/like",
24849
+ data: actionParams,
24850
+ headers: likeActionXsHeader
23728
24851
  }, {
23729
24852
  retries: 3,
23730
- retryDelay: 500,
24853
+ retryDelay: 20,
23731
24854
  timeout: 3000
23732
24855
  });
23733
24856
  break;
23734
24857
  }
23735
- case "unfollow":
24858
+ case "dislike":
23736
24859
  {
23737
- const unfllowMentions = "/api/sns/web/v1/user/unfollow";
23738
- const unfllowXsHeader = xiaohongshuWebRelationAction_xsEncrypt.signHeadersPost(unfllowMentions, recordCookie, "xhs-pc-web", relationParams);
23739
- relationActionRes = await http.api({
24860
+ const dislikeMentions = "/api/sns/web/v1/comment/dislike";
24861
+ const dislikeXsHeader = xiaohongshuWebCommentAction_xsEncrypt.signHeadersPost(dislikeMentions, recordCookie, "xhs-pc-web", actionParams);
24862
+ likeActionRes = await http.api({
23740
24863
  method: "post",
23741
- url: "https://edith.xiaohongshu.com/api/sns/web/v1/user/unfollow",
23742
- data: relationParams,
23743
- headers: unfllowXsHeader
24864
+ url: "https://edith.xiaohongshu.com/api/sns/web/v1/comment/dislike",
24865
+ data: actionParams,
24866
+ headers: dislikeXsHeader
23744
24867
  }, {
23745
24868
  retries: 3,
23746
24869
  retryDelay: 20,
@@ -23755,40 +24878,17 @@ var __webpack_exports__ = {};
23755
24878
  data: {}
23756
24879
  };
23757
24880
  }
23758
- const isSuccess = 0 === relationActionRes.code;
23759
- const message = `用户关系操作${isSuccess ? "成功" : `失败,原因:${relationActionRes.msg}`}${_task.debug ? ` ${http.proxyInfo}` : ""}`;
23760
- const data = isSuccess ? relationActionRes.data : {
23761
- fstatus: null
23762
- };
24881
+ const isSuccess = 0 === likeActionRes.code;
24882
+ const message = `点赞相关操作${isSuccess ? "成功" : `失败,原因:${likeActionRes.msg}`}${_task.debug ? ` ${http.proxyInfo}` : ""}`;
24883
+ const data = isSuccess ? likeActionRes.success : {};
23763
24884
  return (0, share_namespaceObject.response)(isSuccess ? 0 : 414, message, data);
23764
24885
  };
23765
- const xiaohongshuWebSearch_xsEncrypt = new Xhshow();
23766
- const XhsWebSearchParamsSchema = ActionCommonParamsSchema.extend({
23767
- keyword: schemas_string(),
23768
- page: schemas_number(),
23769
- page_size: schemas_number(),
23770
- sort_type: schemas_enum([
23771
- "general",
23772
- "time_descending",
23773
- "popular_descending"
23774
- ]),
23775
- time_filter: schemas_enum([
23776
- "不限",
23777
- "一周内"
23778
- ])
23779
- });
23780
- const createSearchId = ()=>{
23781
- let r = BigInt(Date.now());
23782
- const o = BigInt(Math.ceil(0x7ffffffe * Math.random()));
23783
- r <<= BigInt(64);
23784
- r += o;
23785
- return r.toString(36);
23786
- };
23787
- const xiaohongshuWebSearch = async (_task, params)=>{
24886
+ const xiaohongshuWebIntimacySearch = async (_task, params)=>{
24887
+ if (DisabledReq) return (0, share_namespaceObject.response)(0, "搜索@列表数据成功", []);
23788
24888
  const headers = {
23789
24889
  cookie: params.cookies.map((it)=>`${it.name}=${it.value}`).join(";"),
23790
24890
  referer: "https://www.xiaohongshu.com/",
23791
- origin: "https://www.xiaohongshu.com/"
24891
+ origin: "https://www.xiaohongshu.com"
23792
24892
  };
23793
24893
  const args = [
23794
24894
  {
@@ -23800,569 +24900,461 @@ var __webpack_exports__ = {};
23800
24900
  params.accountId
23801
24901
  ];
23802
24902
  const http = new Http(...args);
23803
- const a1Cookie = params.cookies.find((it)=>"a1" === it.name)?.value;
23804
- if (!a1Cookie) return {
23805
- code: 414,
23806
- message: "账号数据异常,请重新绑定账号后重试。",
23807
- data: {}
23808
- };
23809
- if (!params.keyword || !params.page || !params.page_size || !params.sort_type || !params.time_filter) {
23810
- if ("general" !== params.sort_type && "time_descending" !== params.sort_type && "popular_descending" !== params.sort_type) return {
23811
- code: 414,
23812
- message: "排序类型参数错误,请检查后重试!",
23813
- data: {}
23814
- };
23815
- if ("不限" !== params.time_filter && "一周内" !== params.time_filter) return {
23816
- code: 414,
23817
- message: "时间过滤参数错误,请检查后重试!",
23818
- data: {}
23819
- };
23820
- return {
23821
- code: 414,
23822
- message: "参数缺失,请检查后重试!",
23823
- data: {}
23824
- };
23825
- }
23826
- const filterPath = "/api/sns/web/v1/search/notes";
23827
- const filterParams = {
23828
- ext_flags: [],
23829
- geo: "",
23830
- image_formats: [
23831
- "jpg",
23832
- "webp",
23833
- "avif"
23834
- ],
23835
- filters: [
23836
- {
23837
- tags: [
23838
- params.sort_type
23839
- ],
23840
- type: "sort_type"
23841
- },
23842
- {
23843
- tags: [
23844
- "不限"
23845
- ],
23846
- type: "filter_note_type"
23847
- },
23848
- {
23849
- tags: [
23850
- params.time_filter
23851
- ],
23852
- type: "filter_note_time"
23853
- },
23854
- {
23855
- tags: [
23856
- "不限"
23857
- ],
23858
- type: "filter_note_range"
23859
- },
23860
- {
23861
- tags: [
23862
- "不限"
23863
- ],
23864
- type: "filter_pos_distance"
23865
- }
23866
- ],
23867
- keyword: params.keyword,
23868
- note_type: 0,
23869
- page: params.page,
23870
- page_size: params.page_size,
23871
- search_id: createSearchId() + (params.sort_type || params.time_filter ? `@${createSearchId()}` : ""),
23872
- sort: "general"
23873
- };
23874
- const recordCookie = params.cookies.reduce((acc, cookie)=>{
23875
- if (cookie.name && cookie.value) acc[cookie.name] = cookie.value;
23876
- return acc;
23877
- }, {});
23878
- const searchXsHeader = xiaohongshuWebSearch_xsEncrypt.signHeadersPost(filterPath, recordCookie, "xhs-pc-web", filterParams);
24903
+ let intimacyDetail = [];
23879
24904
  const res = await http.api({
23880
- method: "post",
23881
- url: "https://edith.xiaohongshu.com/api/sns/web/v1/search/notes",
23882
- data: filterParams,
23883
- headers: searchXsHeader
24905
+ method: "get",
24906
+ url: `https://edith.xiaohongshu.com/api/sns/web/v1/intimacy/intimacy_list${params.searchValue ? "/search" : ""}`,
24907
+ ...params.searchValue ? {
24908
+ params: {
24909
+ keyword: params.searchValue,
24910
+ page: 1,
24911
+ rows: 30
24912
+ }
24913
+ } : {}
23884
24914
  }, {
23885
24915
  retries: 3,
23886
24916
  retryDelay: 20,
23887
24917
  timeout: 3000
23888
24918
  });
23889
24919
  const isSuccess = 0 === res.code;
23890
- const message = `Web笔记搜索${isSuccess ? "成功" : `失败,原因:${res.msg}`}${_task.debug ? ` ${http.proxyInfo}` : ""}`;
23891
- const data = isSuccess ? res.data : {};
23892
- return (0, share_namespaceObject.response)(isSuccess ? 0 : 414, message, data);
23893
- };
23894
- const ttConfigDataSchema = schemas_object({
23895
- fansNum: schemas_number(),
23896
- fansNumYesterday: schemas_number().nullable(),
23897
- readNum: schemas_number(),
23898
- incomeNum: schemas_number(),
23899
- incomeNumYesterday: schemas_number().nullable(),
23900
- showNumYesterday: schemas_number().nullable(),
23901
- readNumYesterday: schemas_number().nullable(),
23902
- likeNumYesterday: schemas_number().nullable(),
23903
- commentNumYesterday: schemas_number().nullable()
23904
- });
23905
- const xhsConfigDataSchema = schemas_object({
23906
- fansNum: schemas_number(),
23907
- favedNum: schemas_number(),
23908
- watchNumLastWeek: schemas_number(),
23909
- likeNumLastWeek: schemas_number(),
23910
- collectNumLastWeek: schemas_number(),
23911
- commentNumLastWeek: schemas_number(),
23912
- fansNumLastWeek: schemas_number(),
23913
- fansNumYesterday: schemas_number()
23914
- });
23915
- const wxConfigDataSchema = schemas_object({
23916
- fansNum: schemas_number(),
23917
- fansNumYesterday: schemas_number(),
23918
- readNumYesterday: schemas_number(),
23919
- shareNumYesterday: schemas_number()
23920
- });
23921
- const bjhConfigDataSchema = schemas_object({
23922
- fansNum: schemas_number(),
23923
- fansNumYesterday: schemas_number().nullable(),
23924
- readNum: schemas_number(),
23925
- incomeNum: schemas_number(),
23926
- incomeNumYesterday: schemas_number().nullable(),
23927
- recommendNumYesterday: schemas_number().nullable(),
23928
- readNumYesterday: schemas_number().nullable(),
23929
- likeNumYesterday: schemas_number().nullable(),
23930
- commentNumYesterday: schemas_number().nullable()
23931
- });
23932
- const rpa_server_mock_encode_mnsv2 = __webpack_require__("./src/utils/xhs_ob/x_s.encoder.js");
23933
- function Md5(input) {
23934
- return external_node_crypto_default().createHash("md5").update(input).digest("hex");
23935
- }
23936
- const rpa_server_mock_errnoMap = {
23937
- "-1": "未知拦截器错误,请稍后重试。",
23938
- 915: "所属C端账号手机号被修改,请重新登录",
23939
- 914: "所属C端账号密码被修改,请重新登录",
23940
- 903: "账户已登出,需重新登陆重试!",
23941
- 902: "登录已过期,请重新登录!",
23942
- 906: "账号存在风险,请重新登录!",
23943
- "-9136": "因违反社区规范禁止发笔记,请检查账号状态!"
24920
+ if (isSuccess) intimacyDetail = res.data.items;
24921
+ const message = `搜索@列表数据${isSuccess ? "成功" : `失败,原因:${res.msg}`}${_task.debug ? ` ${http.proxyInfo}` : ""}`;
24922
+ return (0, share_namespaceObject.response)(isSuccess ? 0 : 414, message, intimacyDetail);
23944
24923
  };
23945
- const rpa_server_mock_xsEncrypt = new Xhshow();
23946
- const rpaAction_Server_Mock = async (task, params)=>{
23947
- const updateTaskState = task.taskStageStore?.update?.bind(task.taskStageStore, task.taskId || "");
23948
- const tmpCachePath = task.getTmpPath();
23949
- if (params?.selfDeclaration?.type === "source-statement" && "transshipment" === params.selfDeclaration.childType && params.originalBind) return {
23950
- code: 414,
23951
- message: "原创声明与转载声明互斥,请重新选择后发布!",
23952
- data: ""
24924
+ const xiaohongshuWebMsgRead_xsEncrypt = new Xhshow();
24925
+ const xiaohongshuWebMsgRead = async (_task, params)=>{
24926
+ if (DisabledReq) return (0, share_namespaceObject.response)(414, "Read指定Tab失败", {});
24927
+ const headers = {
24928
+ cookie: params.cookies.map((it)=>`${it.name}=${it.value}`).join(";"),
24929
+ referer: "https://www.xiaohongshu.com/",
24930
+ origin: "https://www.xiaohongshu.com/"
23953
24931
  };
24932
+ const args = [
24933
+ {
24934
+ headers
24935
+ },
24936
+ _task.logger,
24937
+ params.proxyLoc,
24938
+ params.localIP,
24939
+ params.accountId
24940
+ ];
24941
+ const http = new Http(...args);
23954
24942
  const a1Cookie = params.cookies.find((it)=>"a1" === it.name)?.value;
23955
24943
  if (!a1Cookie) return {
23956
24944
  code: 414,
23957
24945
  message: "账号数据异常,请重新绑定账号后重试。",
23958
- data: ""
24946
+ data: []
23959
24947
  };
23960
- const defaultPage = task.steelBrowserContext?.pages()[0];
23961
- if (defaultPage) {
23962
- if (!defaultPage._routeRegistered) {
23963
- defaultPage._routeRegistered = true;
23964
- const blockedPatterns = [
23965
- "**/ffmpeg-core.wasm*",
23966
- "**/apm-fe.xiaohongshu.com*",
23967
- "**/t2.xiaohongshu.com*",
23968
- "**/fe-video-qc.xhscdn.com*"
23969
- ].map((pattern)=>new RegExp(pattern.replace(/\*\*/g, ".*").replace(/\*/g, "[^/]*")));
23970
- await defaultPage.route("**/*", async (route)=>{
23971
- const req = route.request();
23972
- const url = req.url();
23973
- const blocked = blockedPatterns.some((regex)=>regex.test(url));
23974
- if (!blocked) return route.continue();
23975
- if ("OPTIONS" === req.method()) {
23976
- console.log("处理 OPTIONS 预检:", url);
23977
- await route.fulfill({
23978
- status: 204,
23979
- headers: {
23980
- "access-control-allow-origin": "*",
23981
- "access-control-allow-methods": "GET,POST,OPTIONS,PUT,DELETE",
23982
- "access-control-allow-headers": "*"
23983
- },
23984
- body: ""
23985
- });
23986
- return;
23987
- }
23988
- await route.fulfill({
23989
- status: 204,
23990
- body: ""
23991
- });
23992
- });
23993
- }
23994
- }
23995
- const pagePromise = task.createPage({
23996
- show: task.debug,
23997
- cookies: params.cookies,
23998
- url: params.url || "https://creator.xiaohongshu.com/statistics/account/v2?source=official"
23999
- });
24000
- await updateTaskState?.({
24001
- state: share_namespaceObject.TaskState.ACTION
24002
- });
24003
- const headers = {
24004
- cookie: params.cookies.map((it)=>`${it.name}=${it.value}`).join(";"),
24005
- origin: "https://creator.xiaohongshu.com",
24006
- referer: "https://creator.xiaohongshu.com/",
24007
- "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"
24948
+ if (!params.type) return {
24949
+ code: 414,
24950
+ message: "参数缺失,请检查后重试!",
24951
+ data: {}
24952
+ };
24953
+ const replyParams = {
24954
+ type: params.type
24008
24955
  };
24956
+ const fatchMentions = "/api/sns/web/v1/message/read";
24009
24957
  const recordCookie = params.cookies.reduce((acc, cookie)=>{
24010
24958
  if (cookie.name && cookie.value) acc[cookie.name] = cookie.value;
24011
24959
  return acc;
24012
24960
  }, {});
24961
+ const fatchMentionsXsHeader = xiaohongshuWebMsgRead_xsEncrypt.signHeadersPost(fatchMentions, recordCookie, "xhs-pc-web", replyParams);
24962
+ const res = await http.api({
24963
+ method: "post",
24964
+ url: "https://edith.xiaohongshu.com/api/sns/web/v1/message/read",
24965
+ data: replyParams,
24966
+ headers: fatchMentionsXsHeader
24967
+ }, {
24968
+ retries: 3,
24969
+ retryDelay: 20,
24970
+ timeout: 3000
24971
+ });
24972
+ const isSuccess = 0 === res.code;
24973
+ const message = `Read指定Tab${isSuccess ? "成功" : `失败,原因:${res.msg}`}${_task.debug ? ` ${http.proxyInfo}` : ""}`;
24974
+ const data = isSuccess ? res.success : {};
24975
+ return (0, share_namespaceObject.response)(isSuccess ? 0 : 414, message, data);
24976
+ };
24977
+ const xiaohongshuWebMsgReply_xsEncrypt = new Xhshow();
24978
+ const xiaohongshuWebMsgReply = async (_task, params)=>{
24979
+ if (DisabledReq) return (0, share_namespaceObject.response)(414, "评论回复失败", {});
24980
+ const headers = {
24981
+ cookie: params.cookies.map((it)=>`${it.name}=${it.value}`).join(";"),
24982
+ referer: "https://www.xiaohongshu.com/",
24983
+ origin: "https://www.xiaohongshu.com/"
24984
+ };
24013
24985
  const args = [
24014
24986
  {
24015
24987
  headers
24016
24988
  },
24017
- task.logger,
24989
+ _task.logger,
24018
24990
  params.proxyLoc,
24019
24991
  params.localIP,
24020
24992
  params.accountId
24021
24993
  ];
24022
- const http = new Http({
24023
- headers
24024
- });
24025
- const proxyHttp = new Http(...args);
24026
- proxyHttp.addResponseInterceptor((response)=>{
24027
- const responseData = response.data;
24028
- if (response && responseData?.code && 0 !== responseData.code || responseData?.code && !responseData.success) {
24029
- const errmsg = rpa_server_mock_errnoMap[responseData.code] || response.config.defaultErrorMsg || "文章发布异常,请稍后重试。";
24030
- return {
24031
- code: rpa_server_mock_errnoMap[responseData.code] ? 414 : 500,
24032
- message: errmsg,
24033
- data: responseData
24034
- };
24035
- }
24036
- });
24037
- const fetchCoverUrl = "/api/media/v1/upload/creator/permit";
24038
- const fetchCoverParams = {
24039
- biz_name: "spectrum",
24040
- scene: "image",
24041
- file_count: params.banners.length,
24042
- version: 1,
24043
- source: "web"
24044
- };
24045
- const fetchCoverXsHeader = rpa_server_mock_xsEncrypt.signHeadersGet(fetchCoverUrl, recordCookie, "ugc", fetchCoverParams);
24046
- const uploadInfos = [];
24047
- if (params.banners.length > 18) {
24048
- let num = Math.ceil(params.banners.length / 14);
24049
- for(let i = 0; i < num; i++){
24050
- const start = 14 * i;
24051
- params.banners.length;
24052
- ({
24053
- ...fetchCoverParams
24054
- });
24055
- const batchCoverIdInfo = await proxyHttp.api({
24056
- method: "get",
24057
- baseURL: "https://creator.xiaohongshu.com",
24058
- url: fetchCoverUrl,
24059
- defaultErrorMsg: "获取小红书用户信息失败,请稍后重试发布。",
24060
- headers: fetchCoverXsHeader,
24061
- params: fetchCoverParams
24062
- }, {
24063
- retries: 3,
24064
- retryDelay: 20,
24065
- timeout: 3000
24066
- });
24067
- for (const item of batchCoverIdInfo.data.uploadTempPermits)for (const fileId of item.fileIds)uploadInfos.push({
24068
- bucket: item.bucket || "",
24069
- uploadAddr: item.uploadAddr || "",
24070
- fileIds: fileId,
24071
- token: item.token || ""
24072
- });
24073
- }
24074
- } else {
24075
- const coverIdInfo = await proxyHttp.api({
24076
- method: "get",
24077
- baseURL: "https://creator.xiaohongshu.com",
24078
- url: fetchCoverUrl,
24079
- defaultErrorMsg: "获取小红书用户信息失败,请稍后重试发布。",
24080
- headers: fetchCoverXsHeader,
24081
- params: fetchCoverParams
24082
- }, {
24083
- retries: 3,
24084
- retryDelay: 20,
24085
- timeout: 3000
24086
- });
24087
- for (const item of coverIdInfo.data.uploadTempPermits)for (const fileId of item.fileIds)uploadInfos.push({
24088
- bucket: item.bucket || "",
24089
- uploadAddr: item.uploadAddr || "",
24090
- fileIds: fileId,
24091
- token: item.token || ""
24092
- });
24093
- }
24094
- if (uploadInfos.length < params.banners.length) return {
24994
+ const http = new Http(...args);
24995
+ const a1Cookie = params.cookies.find((it)=>"a1" === it.name)?.value;
24996
+ if (!a1Cookie) return {
24095
24997
  code: 414,
24096
- message: "可用 OSS bucket 数量不足,无法上传所有图片!",
24097
- data: ""
24998
+ message: "账号数据异常,请重新绑定账号后重试。",
24999
+ data: []
24098
25000
  };
24099
- if (0 === uploadInfos.length) return {
25001
+ if (!params.note_id || !params.target_comment_id || !params.content) return {
24100
25002
  code: 414,
24101
- message: "图片上传失败,请稍后重试!",
24102
- data: ""
25003
+ message: "参数缺失,请检查后重试!",
25004
+ data: {}
24103
25005
  };
24104
- const availableBuckets = Array.from({
24105
- length: uploadInfos.length
24106
- }, (_, i)=>i);
24107
- const uploadFile = async (url, index)=>{
24108
- const fileName = (0, share_namespaceObject.getFilenameFromUrl)(url);
24109
- const localUrl = await (0, share_namespaceObject.downloadImage)(url, external_node_path_default().join(tmpCachePath, fileName));
24110
- const fileBuffer = external_node_fs_default().readFileSync(localUrl);
24111
- const MAX_RETRIES = uploadInfos.length;
24112
- task.logger.debug(`上传图片 ${index + 1}:尝试使用最多 ${MAX_RETRIES} 个 bucket`);
24113
- let attempt = 0;
24114
- while(attempt < MAX_RETRIES){
24115
- const ossBucketIndex = availableBuckets.shift();
24116
- if (void 0 === ossBucketIndex) break;
24117
- const currentInfo = uploadInfos[ossBucketIndex];
24118
- const ossFileId = currentInfo.fileIds;
24119
- const ossToken = currentInfo.token;
24120
- const ossDomain = currentInfo.uploadAddr;
24121
- try {
24122
- await http.api({
24123
- method: "put",
24124
- url: `https://${ossDomain}/${ossFileId}`,
24125
- data: fileBuffer,
24126
- headers: {
24127
- "x-cos-security-token": ossToken
24128
- },
24129
- defaultErrorMsg: "图片上传异常,请稍后重试发布。"
24130
- });
24131
- return {
24132
- ossFileId,
24133
- ossToken
24134
- };
24135
- } catch (error) {
24136
- task.logger.warn(`上传图片 ${index + 1}:使用 bucket ${ossDomain} 失败,尝试下一个可用 bucket。错误信息:${error.message}`);
24137
- attempt++;
24138
- }
24139
- }
24140
- return {
24141
- ossFileId: "",
24142
- ossToken: ""
24143
- };
25006
+ const replyParams = {
25007
+ at_users: params.at_users ?? [],
25008
+ content: params.content,
25009
+ note_id: params.note_id,
25010
+ target_comment_id: params.target_comment_id
25011
+ };
25012
+ const replyPath = "/api/sns/web/v1/comment/post";
25013
+ const recordCookie = params.cookies.reduce((acc, cookie)=>{
25014
+ if (cookie.name && cookie.value) acc[cookie.name] = cookie.value;
25015
+ return acc;
25016
+ }, {});
25017
+ const replyXsHeader = xiaohongshuWebMsgReply_xsEncrypt.signHeadersPost(replyPath, recordCookie, "xhs-pc-web", replyParams);
25018
+ const res = await http.api({
25019
+ method: "post",
25020
+ url: "https://edith.xiaohongshu.com/api/sns/web/v1/comment/post",
25021
+ data: replyParams,
25022
+ headers: replyXsHeader
25023
+ }, {
25024
+ retries: 3,
25025
+ retryDelay: 20,
25026
+ timeout: 3000
25027
+ });
25028
+ const isSuccess = 0 === res.code;
25029
+ const message = `评论回复${isSuccess ? "成功" : `失败,原因:${res.msg}`}${_task.debug ? ` ${http.proxyInfo}` : ""}`;
25030
+ const data = isSuccess ? res.data : {};
25031
+ return (0, share_namespaceObject.response)(isSuccess ? 0 : 414, message, data);
25032
+ };
25033
+ const xiaohongshuWebNoteFeed_xsEncrypt = new xhs_ob_feed_Xhshow();
25034
+ const GenXSCommon = __webpack_require__("./src/utils/XhsXsCommonEnc.js");
25035
+ const xiaohongshuWebNoteFeed = async (_task, params)=>{
25036
+ if (DisabledReq) return (0, share_namespaceObject.response)(414, "获取指定文章详情失败", {});
25037
+ const headers = {
25038
+ cookie: params.cookies.map((it)=>`${it.name}=${it.value}`).join(";"),
25039
+ referer: "https://www.xiaohongshu.com/",
25040
+ origin: "https://www.xiaohongshu.com/"
24144
25041
  };
24145
- const coverInfos = await Promise.all(params.banners.map((it, idx)=>uploadFile(it, idx)));
24146
- const invalidUpload = coverInfos.find((it)=>"" === it.ossToken || "" === it.ossFileId);
24147
- if (invalidUpload) return {
25042
+ const args = [
25043
+ {
25044
+ headers
25045
+ },
25046
+ _task.logger,
25047
+ params.proxyLoc,
25048
+ params.localIP,
25049
+ params.accountId
25050
+ ];
25051
+ const http = new Http(...args);
25052
+ const a1Cookie = params.cookies.find((it)=>"a1" === it.name)?.value;
25053
+ if (!a1Cookie) return {
24148
25054
  code: 414,
24149
- message: "图片上传异常,请稍后重试发布。",
24150
- data: ""
25055
+ message: "账号数据异常,请重新绑定账号后重试。",
25056
+ data: {}
24151
25057
  };
24152
- if (params.topic && params.topic.length > 0) await Promise.all(params.topic.map(async (topic)=>{
24153
- if (!topic.id) {
24154
- const topicData = {
24155
- topic_names: topic.name
24156
- };
24157
- const topicXsHeader = rpa_server_mock_xsEncrypt.signHeadersPost("/web_api/sns/capa/postgw/topic/batch_customized", recordCookie, "ugc", topicData);
24158
- const createTopic = await proxyHttp.api({
24159
- method: "POST",
24160
- url: "https://edith.xiaohongshu.com/web_api/sns/capa/postgw/topic/batch_customized",
24161
- headers: topicXsHeader,
24162
- data: topicData,
24163
- defaultErrorMsg: "话题创建异常,请稍后重试。"
24164
- }, {
24165
- retries: 3,
24166
- retryDelay: 20,
24167
- timeout: 3000
24168
- });
24169
- Object.assign(topic, createTopic.data.topic_infos[0]);
24170
- }
24171
- }));
24172
- const visibleRangeMap = {
24173
- public: 0,
24174
- private: 1,
24175
- friends: 4
25058
+ if (!params.source_note_id && !params.xsec_token) return {
25059
+ code: 414,
25060
+ message: "参数缺失,请检查后重试!",
25061
+ data: {}
24176
25062
  };
24177
- const publishData = {
24178
- common: {
24179
- ats: [],
24180
- biz_relations: [],
24181
- desc: params?.content,
24182
- goods_info: {},
24183
- hash_tag: params.topic || [],
24184
- note_id: "",
24185
- source: JSON.stringify({
24186
- type: "web",
24187
- ids: "",
24188
- extraInfo: '{"systemId":"web"}'
24189
- }),
24190
- title: params?.title,
24191
- type: "normal",
24192
- privacy_info: {
24193
- op_type: 1,
24194
- type: visibleRangeMap[params.visibleRange]
24195
- },
24196
- post_loc: params.address ? {
24197
- name: params.address?.name,
24198
- poi_id: params.address?.poi_id,
24199
- poi_type: params.address?.poi_type,
24200
- subname: params.address?.full_address
24201
- } : null,
24202
- business_binds: ""
24203
- },
24204
- image_info: {
24205
- images: coverInfos.map((it)=>({
24206
- extra_info_json: '{"mimeType":"image/png"}',
24207
- file_id: it.ossFileId,
24208
- metadata: {
24209
- source: -1
24210
- },
24211
- stickers: {
24212
- floating: [],
24213
- version: 2
24214
- }
24215
- }))
25063
+ const feedParams = {
25064
+ source_note_id: params.source_note_id,
25065
+ image_formats: [
25066
+ "jpg",
25067
+ "webp",
25068
+ "avif"
25069
+ ],
25070
+ extra: {
25071
+ need_body_topic: "1"
24216
25072
  },
24217
- video_info: null
24218
- };
24219
- const userDeclarationBind = {
24220
- origin: 2,
24221
- photoInfo: {},
24222
- repostInfo: {}
25073
+ xsec_source: "pc_feed",
25074
+ xsec_token: params.xsec_token
24223
25075
  };
24224
- if (params.selfDeclaration?.type === "fictional-rendition") userDeclarationBind.origin = 1;
24225
- else if (params.selfDeclaration?.type === "ai-generated") userDeclarationBind.origin = 2;
24226
- else if (params.selfDeclaration?.type === "source-statement") {
24227
- if ("self-labeling" === params.selfDeclaration.childType) userDeclarationBind.origin = 3;
24228
- else if ("self-shooting" === params.selfDeclaration.childType) {
24229
- userDeclarationBind.origin = 4;
24230
- const photoInfo = {};
24231
- if (params.selfDeclaration.shootingLocation) photoInfo.photoPlace = {
24232
- name: params.selfDeclaration.shootingLocation.name,
24233
- poiId: params.selfDeclaration.shootingLocation.poi_id,
24234
- poiType: params.selfDeclaration.shootingLocation.poi_type,
24235
- subname: params.selfDeclaration.shootingLocation.full_address
24236
- };
24237
- if (params.selfDeclaration.shootingDate) photoInfo.photoTime = params.selfDeclaration.shootingDate;
24238
- userDeclarationBind.photoInfo = photoInfo;
24239
- } else if ("transshipment" === params.selfDeclaration.childType) {
24240
- userDeclarationBind.origin = 5;
24241
- if (params.selfDeclaration.sourceMedia) userDeclarationBind.repostInfo = {
24242
- source: params.selfDeclaration.sourceMedia
24243
- };
25076
+ const fatchFeed = "/api/sns/web/v1/feed";
25077
+ const recordCookie = params.cookies.reduce((acc, cookie)=>{
25078
+ if (cookie.name && cookie.value) acc[cookie.name] = cookie.value;
25079
+ return acc;
25080
+ }, {});
25081
+ const xsHeader = xiaohongshuWebNoteFeed_xsEncrypt.signHeadersPost(fatchFeed, recordCookie, "xhs-pc-web", feedParams);
25082
+ const xT = Date.now().toString();
25083
+ const xsCommon = GenXSCommon(a1Cookie, xT, xsHeader["X-S"]);
25084
+ _task.logger.info(`请求参数: ${JSON.stringify(feedParams)}`);
25085
+ _task.logger.info(`X-S: ${xsHeader["X-S"]}`);
25086
+ _task.logger.info(`x-s-common: ${xsCommon}`);
25087
+ const res = await http.api({
25088
+ method: "post",
25089
+ url: "https://edith.xiaohongshu.com/api/sns/web/v1/feed",
25090
+ data: feedParams,
25091
+ headers: {
25092
+ "X-S": xsHeader["X-S"],
25093
+ "X-S-Common": xsCommon,
25094
+ "X-T": xT
24244
25095
  }
24245
- }
24246
- const bizId = params?.originalBind && (params.cookies.find((it)=>"x-user-id-creator.xiaohongshu.com" === it.name)?.value || await proxyHttp.api({
24247
- method: "get",
24248
- url: "https://creator.xiaohongshu.com/api/galaxy/user/my-info"
24249
25096
  }, {
24250
25097
  retries: 3,
24251
25098
  retryDelay: 20,
24252
25099
  timeout: 3000
24253
- }).then((userData)=>userData.data?.userDetail?.id));
24254
- const business_binds = {
24255
- version: 1,
24256
- bizType: "",
24257
- noteId: "",
24258
- noteOrderBind: {},
24259
- notePostTiming: params.isImmediatelyPublish ? {} : {
24260
- postTime: params.scheduledPublish
24261
- },
24262
- coProduceBind: {
24263
- enable: !!params?.coProduceBind
24264
- },
24265
- noteCopyBind: {
24266
- copyable: !!params?.noteCopyBind
25100
+ });
25101
+ _task.logger.info(`API 响应: ${JSON.stringify(res)}`);
25102
+ const isSuccess = 0 === res.code && res.data && res.data.items && res.data.items.length > 0;
25103
+ const message = `获取指定文章详情${isSuccess ? "成功" : `失败,原因:${res.msg || "返回数据为空,可能笔记不存在或参数错误"}`}${_task.debug ? ` ${http.proxyInfo}` : ""}`;
25104
+ const data = isSuccess ? res.data?.items[0].note_card || {} : {};
25105
+ return (0, share_namespaceObject.response)(isSuccess ? 0 : 414, message, data);
25106
+ };
25107
+ const xiaohongshuWebRelationAction_xsEncrypt = new Xhshow();
25108
+ const xiaohongshuWebRelationAction = async (_task, params)=>{
25109
+ if (DisabledReq) return (0, share_namespaceObject.response)(414, "用户关系操作失败", {});
25110
+ const headers = {
25111
+ cookie: params.cookies.map((it)=>`${it.name}=${it.value}`).join(";"),
25112
+ referer: "https://www.xiaohongshu.com/",
25113
+ origin: "https://www.xiaohongshu.com/"
25114
+ };
25115
+ const args = [
25116
+ {
25117
+ headers
24267
25118
  },
24268
- optionRelationList: params.originalBind ? [
25119
+ _task.logger,
25120
+ params.proxyLoc,
25121
+ params.localIP,
25122
+ params.accountId
25123
+ ];
25124
+ const http = new Http(...args);
25125
+ const a1Cookie = params.cookies.find((it)=>"a1" === it.name)?.value;
25126
+ if (!a1Cookie) return {
25127
+ code: 414,
25128
+ message: "账号数据异常,请重新绑定账号后重试。",
25129
+ data: {}
25130
+ };
25131
+ if (!params.action || !params.target_user_id) return {
25132
+ code: 414,
25133
+ message: "参数缺失,请检查后重试!",
25134
+ data: {}
25135
+ };
25136
+ const relationParams = {
25137
+ target_user_id: params.target_user_id
25138
+ };
25139
+ let relationActionRes;
25140
+ const recordCookie = params.cookies.reduce((acc, cookie)=>{
25141
+ if (cookie.name && cookie.value) acc[cookie.name] = cookie.value;
25142
+ return acc;
25143
+ }, {});
25144
+ switch(params.action){
25145
+ case "follow":
24269
25146
  {
24270
- type: "ORIGINAL_STATEMENT",
24271
- relationList: [
24272
- {
24273
- bizId,
24274
- bizType: "ORIGINAL_STATEMENT",
24275
- extraInfo: "{}"
24276
- }
24277
- ]
24278
- }
24279
- ] : [],
24280
- ...params?.groupBind ? {
24281
- groupBind: {
24282
- groupId: params?.groupBind?.group_id,
24283
- groupName: params.groupBind?.group_name,
24284
- desc: params.groupBind?.desc,
24285
- avatar: params.groupBind?.avatar
24286
- }
24287
- } : {
24288
- groupBind: {}
24289
- },
24290
- ...params.selfDeclaration ? {
24291
- userDeclarationBind
24292
- } : {},
24293
- ...params?.collectionBind?.id ? {
24294
- noteCollectionBind: {
24295
- id: params.collectionBind.id
25147
+ const followMentions = "/api/sns/web/v1/user/follow";
25148
+ const followXsHeader = xiaohongshuWebRelationAction_xsEncrypt.signHeadersPost(followMentions, recordCookie, "xhs-pc-web", relationParams);
25149
+ relationActionRes = await http.api({
25150
+ method: "post",
25151
+ url: "https://edith.xiaohongshu.com/api/sns/web/v1/user/follow",
25152
+ data: relationParams,
25153
+ headers: followXsHeader
25154
+ }, {
25155
+ retries: 3,
25156
+ retryDelay: 500,
25157
+ timeout: 3000
25158
+ });
25159
+ break;
24296
25160
  }
24297
- } : {}
24298
- };
24299
- publishData.common.business_binds = JSON.stringify(business_binds);
24300
- task._timerRecord.PrePublish = Date.now();
24301
- const page = await pagePromise;
24302
- await updateTaskState?.({
24303
- sessionId: task.sessionId
24304
- });
24305
- const publishXsHeader = {
24306
- "x-s": "",
24307
- "x-t": Date.now().toString()
24308
- };
24309
- await page.waitForFunction(()=>"function" == typeof window.mnsv2, {
24310
- timeout: 10000
24311
- });
24312
- const encodeData = `/web_api/sns/v2/note${JSON.stringify(publishData)}`;
24313
- const ticket_mnsv2 = await page.evaluate(({ c, d })=>{
24314
- if ("function" == typeof window.mnsv2) return window.mnsv2(c, d);
24315
- return "mnsv2 未定义";
24316
- }, {
24317
- c: encodeData,
24318
- d: Md5(encodeData)
24319
- });
24320
- publishXsHeader["x-s"] = rpa_server_mock_encode_mnsv2(ticket_mnsv2, "Windows", "object");
24321
- publishXsHeader["x-t"] = Date.now().toString();
24322
- if (MockPublish) {
24323
- const message = `文章模拟发布成功 ${http.proxyInfo}`;
24324
- const data = "123456789";
24325
- await updateTaskState?.({
24326
- state: share_namespaceObject.TaskState.SUCCESS,
24327
- result: {
24328
- response: data
25161
+ case "unfollow":
25162
+ {
25163
+ const unfllowMentions = "/api/sns/web/v1/user/unfollow";
25164
+ const unfllowXsHeader = xiaohongshuWebRelationAction_xsEncrypt.signHeadersPost(unfllowMentions, recordCookie, "xhs-pc-web", relationParams);
25165
+ relationActionRes = await http.api({
25166
+ method: "post",
25167
+ url: "https://edith.xiaohongshu.com/api/sns/web/v1/user/unfollow",
25168
+ data: relationParams,
25169
+ headers: unfllowXsHeader
25170
+ }, {
25171
+ retries: 3,
25172
+ retryDelay: 20,
25173
+ timeout: 3000
25174
+ });
25175
+ break;
24329
25176
  }
24330
- });
24331
- return (0, share_namespaceObject.success)(data, message);
25177
+ default:
25178
+ return {
25179
+ code: 414,
25180
+ message: "参数action错误,请重试!",
25181
+ data: {}
25182
+ };
24332
25183
  }
24333
- const publishResult = await proxyHttp.api({
24334
- method: "post",
24335
- url: "https://edith.xiaohongshu.com/web_api/sns/v2/note",
24336
- data: publishData,
24337
- headers: publishXsHeader,
24338
- defaultErrorMsg: "文章发布异常,请稍后重试。"
24339
- }, {
24340
- retries: 2,
24341
- retryDelay: 500,
24342
- timeout: 12000
24343
- });
24344
- const isSuccess = publishResult.success;
24345
- const message = `文章发布${isSuccess ? "成功" : `失败,原因:${publishResult.msg}`}${task.debug ? ` ${http.proxyInfo}` : ""}`;
24346
- const data = isSuccess ? publishResult.data?.id || "" : "";
24347
- if (!isSuccess) {
24348
- await updateTaskState?.({
24349
- state: share_namespaceObject.TaskState.FAILED,
24350
- error: message
24351
- });
25184
+ const isSuccess = 0 === relationActionRes.code;
25185
+ const message = `用户关系操作${isSuccess ? "成功" : `失败,原因:${relationActionRes.msg}`}${_task.debug ? ` ${http.proxyInfo}` : ""}`;
25186
+ const data = isSuccess ? relationActionRes.data : {
25187
+ fstatus: null
25188
+ };
25189
+ return (0, share_namespaceObject.response)(isSuccess ? 0 : 414, message, data);
25190
+ };
25191
+ const xiaohongshuWebSearch_xsEncrypt = new Xhshow();
25192
+ const XhsWebSearchParamsSchema = ActionCommonParamsSchema.extend({
25193
+ keyword: schemas_string(),
25194
+ page: schemas_number(),
25195
+ page_size: schemas_number(),
25196
+ sort_type: schemas_enum([
25197
+ "general",
25198
+ "time_descending",
25199
+ "popular_descending"
25200
+ ]),
25201
+ time_filter: schemas_enum([
25202
+ "不限",
25203
+ "一周内"
25204
+ ])
25205
+ });
25206
+ const createSearchId = ()=>{
25207
+ let r = BigInt(Date.now());
25208
+ const o = BigInt(Math.ceil(0x7ffffffe * Math.random()));
25209
+ r <<= BigInt(64);
25210
+ r += o;
25211
+ return r.toString(36);
25212
+ };
25213
+ const xiaohongshuWebSearch = async (_task, params)=>{
25214
+ const headers = {
25215
+ cookie: params.cookies.map((it)=>`${it.name}=${it.value}`).join(";"),
25216
+ referer: "https://www.xiaohongshu.com/",
25217
+ origin: "https://www.xiaohongshu.com/"
25218
+ };
25219
+ const args = [
25220
+ {
25221
+ headers
25222
+ },
25223
+ _task.logger,
25224
+ params.proxyLoc,
25225
+ params.localIP,
25226
+ params.accountId
25227
+ ];
25228
+ const http = new Http(...args);
25229
+ const a1Cookie = params.cookies.find((it)=>"a1" === it.name)?.value;
25230
+ if (!a1Cookie) return {
25231
+ code: 414,
25232
+ message: "账号数据异常,请重新绑定账号后重试。",
25233
+ data: {}
25234
+ };
25235
+ if (!params.keyword || !params.page || !params.page_size || !params.sort_type || !params.time_filter) {
25236
+ if ("general" !== params.sort_type && "time_descending" !== params.sort_type && "popular_descending" !== params.sort_type) return {
25237
+ code: 414,
25238
+ message: "排序类型参数错误,请检查后重试!",
25239
+ data: {}
25240
+ };
25241
+ if ("不限" !== params.time_filter && "一周内" !== params.time_filter) return {
25242
+ code: 414,
25243
+ message: "时间过滤参数错误,请检查后重试!",
25244
+ data: {}
25245
+ };
24352
25246
  return {
24353
25247
  code: 414,
24354
- data,
24355
- message
25248
+ message: "参数缺失,请检查后重试!",
25249
+ data: {}
24356
25250
  };
24357
25251
  }
24358
- await updateTaskState?.({
24359
- state: share_namespaceObject.TaskState.SUCCESS,
24360
- result: {
24361
- response: data
24362
- }
25252
+ const filterPath = "/api/sns/web/v1/search/notes";
25253
+ const filterParams = {
25254
+ ext_flags: [],
25255
+ geo: "",
25256
+ image_formats: [
25257
+ "jpg",
25258
+ "webp",
25259
+ "avif"
25260
+ ],
25261
+ filters: [
25262
+ {
25263
+ tags: [
25264
+ params.sort_type
25265
+ ],
25266
+ type: "sort_type"
25267
+ },
25268
+ {
25269
+ tags: [
25270
+ "不限"
25271
+ ],
25272
+ type: "filter_note_type"
25273
+ },
25274
+ {
25275
+ tags: [
25276
+ params.time_filter
25277
+ ],
25278
+ type: "filter_note_time"
25279
+ },
25280
+ {
25281
+ tags: [
25282
+ "不限"
25283
+ ],
25284
+ type: "filter_note_range"
25285
+ },
25286
+ {
25287
+ tags: [
25288
+ "不限"
25289
+ ],
25290
+ type: "filter_pos_distance"
25291
+ }
25292
+ ],
25293
+ keyword: params.keyword,
25294
+ note_type: 0,
25295
+ page: params.page,
25296
+ page_size: params.page_size,
25297
+ search_id: createSearchId() + (params.sort_type || params.time_filter ? `@${createSearchId()}` : ""),
25298
+ sort: "general"
25299
+ };
25300
+ const recordCookie = params.cookies.reduce((acc, cookie)=>{
25301
+ if (cookie.name && cookie.value) acc[cookie.name] = cookie.value;
25302
+ return acc;
25303
+ }, {});
25304
+ const searchXsHeader = xiaohongshuWebSearch_xsEncrypt.signHeadersPost(filterPath, recordCookie, "xhs-pc-web", filterParams);
25305
+ const res = await http.api({
25306
+ method: "post",
25307
+ url: "https://edith.xiaohongshu.com/api/sns/web/v1/search/notes",
25308
+ data: filterParams,
25309
+ headers: searchXsHeader
25310
+ }, {
25311
+ retries: 3,
25312
+ retryDelay: 20,
25313
+ timeout: 3000
24363
25314
  });
24364
- return (0, share_namespaceObject.success)(data, message);
25315
+ const isSuccess = 0 === res.code;
25316
+ const message = `Web笔记搜索${isSuccess ? "成功" : `失败,原因:${res.msg}`}${_task.debug ? ` ${http.proxyInfo}` : ""}`;
25317
+ const data = isSuccess ? res.data : {};
25318
+ return (0, share_namespaceObject.response)(isSuccess ? 0 : 414, message, data);
24365
25319
  };
25320
+ const ttConfigDataSchema = schemas_object({
25321
+ fansNum: schemas_number(),
25322
+ fansNumYesterday: schemas_number().nullable(),
25323
+ readNum: schemas_number(),
25324
+ incomeNum: schemas_number(),
25325
+ incomeNumYesterday: schemas_number().nullable(),
25326
+ showNumYesterday: schemas_number().nullable(),
25327
+ readNumYesterday: schemas_number().nullable(),
25328
+ likeNumYesterday: schemas_number().nullable(),
25329
+ commentNumYesterday: schemas_number().nullable()
25330
+ });
25331
+ const xhsConfigDataSchema = schemas_object({
25332
+ fansNum: schemas_number(),
25333
+ favedNum: schemas_number(),
25334
+ watchNumLastWeek: schemas_number(),
25335
+ likeNumLastWeek: schemas_number(),
25336
+ collectNumLastWeek: schemas_number(),
25337
+ commentNumLastWeek: schemas_number(),
25338
+ fansNumLastWeek: schemas_number(),
25339
+ fansNumYesterday: schemas_number()
25340
+ });
25341
+ const wxConfigDataSchema = schemas_object({
25342
+ fansNum: schemas_number(),
25343
+ fansNumYesterday: schemas_number(),
25344
+ readNumYesterday: schemas_number(),
25345
+ shareNumYesterday: schemas_number()
25346
+ });
25347
+ const bjhConfigDataSchema = schemas_object({
25348
+ fansNum: schemas_number(),
25349
+ fansNumYesterday: schemas_number().nullable(),
25350
+ readNum: schemas_number(),
25351
+ incomeNum: schemas_number(),
25352
+ incomeNumYesterday: schemas_number().nullable(),
25353
+ recommendNumYesterday: schemas_number().nullable(),
25354
+ readNumYesterday: schemas_number().nullable(),
25355
+ likeNumYesterday: schemas_number().nullable(),
25356
+ commentNumYesterday: schemas_number().nullable()
25357
+ });
24366
25358
  const BetaFlag = "HuiwenCanary";
24367
25359
  class Action {
24368
25360
  constructor(task){