aiconductor-cli 1.2.2 → 1.2.3

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.
@@ -13,6 +13,7 @@ const {
13
13
  videoSearchCommand,
14
14
  linkToTextCommand,
15
15
  } = require("../src/commands/douyin");
16
+ const { notePublishCommand } = require("../src/commands/xhs");
16
17
 
17
18
  const program = new Command();
18
19
 
@@ -164,6 +165,25 @@ douyinCmd
164
165
  .option("-f, --format <format>", "输出格式:json 或 text", "json")
165
166
  .action((videoUrl, options) => { linkToTextCommand(videoUrl, options); });
166
167
 
168
+ // xhs 子命令组
169
+ const xhsCmd = program
170
+ .command("xhs")
171
+ .description("小红书数据工具箱");
172
+
173
+ xhsCmd
174
+ .command("note-publish")
175
+ .description("生成小红书扫码发布页与二维码(图文0.05元/次,含OSS转存0.1元/次)")
176
+ .argument("<type>", "笔记类型:normal(图文)或 video(视频)")
177
+ .option("-k, --api-key <key>", "AIConductor API Key")
178
+ .option("-t, --title <title>", "笔记标题(最多20字符)")
179
+ .option("--content <text>", "笔记正文(最多1000字符)")
180
+ .option("--images <urls>", "图片公网URL列表,逗号分隔(normal类型必填,最多18张)")
181
+ .option("--video <url>", "视频公网URL(video类型必填)")
182
+ .option("--cover <url>", "视频封面图公网URL(仅video类型有效)")
183
+ .option("--transfer-to-oss", "是否将素材转存到云端(更稳定,7天有效)")
184
+ .option("-f, --format <format>", "输出格式:json 或 text", "json")
185
+ .action((type, options) => { notePublishCommand(type, options); });
186
+
167
187
  // 未知命令处理
168
188
  program.on("command:*", () => {
169
189
  console.error(`未知命令: ${program.args.join(" ")}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aiconductor-cli",
3
- "version": "1.2.2",
3
+ "version": "1.2.3",
4
4
  "description": "AIConductor CLI 工具箱",
5
5
  "keywords": [
6
6
  "aiconductor",
package/src/api.js CHANGED
@@ -13,6 +13,7 @@ const DOUYIN_USER_DETAIL_PATH = "/api/douyin_user_detail";
13
13
  const DOUYIN_USER_SEARCH_PATH = "/api/douyin_user_search";
14
14
  const DOUYIN_VIDEO_SEARCH_PATH = "/api/douyin_video_search";
15
15
  const DOUYIN_LINK_TO_TEXT_PATH = "/api/douyin_link_to_text_v2";
16
+ const XHS_NOTE_PUBLISH_PATH = "/api/xhs_note_publish";
16
17
 
17
18
  /**
18
19
  * 解析 API Key,三级优先级:命令行参数 > 系统环境变量 > .env 文件
@@ -300,6 +301,27 @@ async function douyinLinkToText(apiKey, videoUrl) {
300
301
  return stripBilling(resp);
301
302
  }
302
303
 
304
+ /**
305
+ * 小红书笔记发布 — 生成扫码发布 H5 页面与二维码
306
+ * @param {string} apiKey
307
+ * @param {{ type: string, title?: string, content?: string, images?: string[], video?: string, cover?: string, transferToOss?: boolean }} params
308
+ * @returns {Promise<object>}
309
+ */
310
+ async function xhsNotePublish(apiKey, params) {
311
+ const body = { type: params.type };
312
+ if (params.title) body.title = params.title;
313
+ if (params.content) body.content = params.content;
314
+ if (params.images && params.images.length > 0) body.images = params.images;
315
+ if (params.video) body.video = params.video;
316
+ if (params.cover) body.cover = params.cover;
317
+ if (params.transferToOss !== undefined) body.transfer_to_oss = params.transferToOss;
318
+
319
+ const resp = await httpPost(API_HOST, XHS_NOTE_PUBLISH_PATH, body, {
320
+ Authorization: `Bearer ${apiKey}`,
321
+ });
322
+ return stripBilling(resp);
323
+ }
324
+
303
325
  module.exports = {
304
326
  resolveApiKey,
305
327
  publishHtml,
@@ -312,4 +334,5 @@ module.exports = {
312
334
  douyinUserSearch,
313
335
  douyinVideoSearch,
314
336
  douyinLinkToText,
337
+ xhsNotePublish,
315
338
  };
@@ -0,0 +1,55 @@
1
+ const { xhsNotePublish } = require("../api");
2
+ const { outputResult, resolveKeyOrExit, handleApiError } = require("../lib/cli-utils");
3
+
4
+ /**
5
+ * text 格式输出:用 ✓ 开头展示关键信息
6
+ */
7
+ function textFormatter(resp) {
8
+ const d = resp.data || {};
9
+ const lines = [];
10
+ lines.push("✓ 小红书笔记发布页已生成");
11
+ lines.push(` ID: ${d.id}`);
12
+ lines.push(` H5 地址: ${d.url}`);
13
+ if (resp.message) lines.push(` 消息: ${resp.message}`);
14
+ if (d.qrcode) lines.push(` 二维码: ${d.qrcode.substring(0, 50)}...`);
15
+ if (d.transfer_to_oss) lines.push(` OSS转存: 是`);
16
+ if (d.media) {
17
+ if (d.media.images) lines.push(` 图片: ${d.media.images.length} 张`);
18
+ if (d.media.video) lines.push(` 视频: ${d.media.video}`);
19
+ if (d.media.cover) lines.push(` 封面: ${d.media.cover}`);
20
+ }
21
+ return lines.join("\n");
22
+ }
23
+
24
+ async function notePublishCommand(type, options = {}) {
25
+ const format = options.format || "json";
26
+ const apiKey = resolveKeyOrExit(options.apiKey, format);
27
+
28
+ // 解析 --images(逗号分隔的 URL 列表)
29
+ let images;
30
+ if (options.images) {
31
+ images = options.images.split(",").map((s) => s.trim()).filter(Boolean);
32
+ }
33
+
34
+ // 解析 --transfer-to-oss(布尔标志)
35
+ const transferToOss = options.transferToOss !== undefined;
36
+
37
+ try {
38
+ const result = await xhsNotePublish(apiKey, {
39
+ type,
40
+ title: options.title,
41
+ content: options.content,
42
+ images,
43
+ video: options.video,
44
+ cover: options.cover,
45
+ transferToOss,
46
+ });
47
+ outputResult(result, format, textFormatter);
48
+ process.exit(0);
49
+ } catch (err) {
50
+ handleApiError(err, format);
51
+ process.exit(1);
52
+ }
53
+ }
54
+
55
+ module.exports = { notePublishCommand };