@northmoon-labs/social-cli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,76 @@
1
+ import { access } from 'node:fs/promises';
2
+ import { extname } from 'node:path';
3
+ import { constants } from 'node:fs';
4
+ import { value } from '../cli/args.js';
5
+ import { CliError } from '../cli/output.js';
6
+ import { MATERIAL_EXTENSIONS, PLATFORM_MAP } from '../social/types.js';
7
+ export function platformOption(options, required = false) {
8
+ const raw = value(options, 'platform');
9
+ if (raw === undefined) {
10
+ if (required)
11
+ throw new CliError('VALIDATION_REQUIRED_OPTION', 'missing required option --platform');
12
+ return undefined;
13
+ }
14
+ const normalized = String(raw).toLowerCase();
15
+ if (PLATFORM_MAP[normalized])
16
+ return PLATFORM_MAP[normalized];
17
+ const numeric = Number(raw);
18
+ if ([1, 2, 3, 4].includes(numeric))
19
+ return numeric;
20
+ throw new CliError('VALIDATION_INVALID_OPTION', '--platform must be tiktok, youtube, instagram, facebook, or 1-4');
21
+ }
22
+ export function timeOption(options, key) {
23
+ const raw = value(options, key);
24
+ if (raw === undefined)
25
+ return undefined;
26
+ if (/^\d+$/.test(String(raw)))
27
+ return Number(raw);
28
+ return parseDateTime(raw, `--${key}`);
29
+ }
30
+ export function parseDateTime(raw, label) {
31
+ if (!/[zZ]|[+-]\d\d:\d\d$/.test(String(raw))) {
32
+ throw new CliError('VALIDATION_INVALID_OPTION', `${label} must include a timezone`);
33
+ }
34
+ const parsed = Date.parse(raw);
35
+ if (Number.isNaN(parsed))
36
+ throw new CliError('VALIDATION_INVALID_OPTION', `${label} must be a valid date time`);
37
+ return parsed;
38
+ }
39
+ export function dateOption(options, key) {
40
+ const raw = value(options, key);
41
+ if (raw === undefined)
42
+ return undefined;
43
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(String(raw)))
44
+ throw new CliError('VALIDATION_INVALID_OPTION', `--${key} must use yyyy-MM-dd`);
45
+ return raw;
46
+ }
47
+ export function validateHttpUrl(raw, label) {
48
+ try {
49
+ const url = new URL(raw);
50
+ if (!['http:', 'https:'].includes(url.protocol))
51
+ throw new Error('invalid protocol');
52
+ }
53
+ catch {
54
+ throw new CliError('VALIDATION_INVALID_OPTION', `${label} must be an http(s) URL`);
55
+ }
56
+ }
57
+ export function validateMetric(metric, allowed) {
58
+ if (!allowed.includes(metric))
59
+ throw new CliError('VALIDATION_INVALID_OPTION', `unsupported metric: ${metric}`);
60
+ }
61
+ export async function validateUploadFile(file) {
62
+ try {
63
+ await access(file, constants.R_OK);
64
+ }
65
+ catch (error) {
66
+ if (isNodeError(error) && error.code === 'ENOENT')
67
+ throw new CliError('FILE_NOT_FOUND', `file not found: ${file}`);
68
+ throw new CliError('FILE_UNREADABLE', `file is not readable: ${file}`);
69
+ }
70
+ const ext = extname(file).slice(1).toLowerCase();
71
+ if (!MATERIAL_EXTENSIONS.has(ext))
72
+ throw new CliError('FILE_UNSUPPORTED_TYPE', `unsupported file type: ${ext || '(none)'}`);
73
+ }
74
+ function isNodeError(error) {
75
+ return error instanceof Error && 'code' in error;
76
+ }
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@northmoon-labs/social-cli",
3
+ "version": "0.1.0",
4
+ "description": "Agent-ready CLI for Northmoon Social account authorization, publishing, comments, analytics, webhooks, and auto replies.",
5
+ "keywords": [
6
+ "northmoon",
7
+ "social",
8
+ "cli",
9
+ "social-api",
10
+ "publishing",
11
+ "tiktok",
12
+ "youtube",
13
+ "instagram",
14
+ "facebook",
15
+ "webhook",
16
+ "analytics"
17
+ ],
18
+ "type": "module",
19
+ "packageManager": "pnpm@10.33.2",
20
+ "bin": {
21
+ "nmsocial": "./dist/bin/nmsocial.js"
22
+ },
23
+ "engines": {
24
+ "node": ">=18"
25
+ },
26
+ "files": [
27
+ "dist",
28
+ "README.md",
29
+ "LICENSE",
30
+ "skills"
31
+ ],
32
+ "scripts": {
33
+ "clean": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"",
34
+ "build": "pnpm run clean && tsc -p tsconfig.json",
35
+ "test": "pnpm run build && node --test --test-concurrency=1 tests/*.test.mjs",
36
+ "typecheck": "tsc -p tsconfig.json --noEmit"
37
+ },
38
+ "devDependencies": {
39
+ "@types/node": "^24.0.0",
40
+ "typescript": "^5.8.0"
41
+ },
42
+ "license": "Apache-2.0",
43
+ "publishConfig": {
44
+ "access": "public"
45
+ },
46
+ "dependencies": {
47
+ "cli-table3": "^0.6.5",
48
+ "picocolors": "^1.1.1"
49
+ }
50
+ }
@@ -0,0 +1,155 @@
1
+ ---
2
+ name: nmsocial-cli
3
+ description: Instructions for AI agents that need to use the `nmsocial` command line tool to operate Northmoon Social workflows, including login, account authorization, material upload, publishing, tasks, posts, comments, webhooks, statistics, auto-replies, dry-run previews, and JSON output.
4
+ ---
5
+
6
+ # NMSocial CLI
7
+
8
+ Use this skill when an agent needs to call the `nmsocial` CLI on a user's machine.
9
+
10
+ ## Core Rules
11
+
12
+ - Use the installed `nmsocial` command.
13
+ - Treat the API URL as built into the CLI; do not ask the user to configure it unless they explicitly mention a custom endpoint.
14
+ - Authenticate agents with `nmsocial login --api-key YOUR_KEY` when non-interactive execution is required.
15
+ - Prefer `nmsocial login --api-key-stdin` for interactive human usage.
16
+ - Do not put API keys directly in commands, logs, or responses.
17
+ - Default output is compact text or tables for quick reading; do not parse it as a stable contract.
18
+ - Use `--json` when another program or agent needs to parse the result.
19
+ - Use `--dry-run --json` before mutation commands when confirming a request body is useful.
20
+ - Prefer platform names: `tiktok`, `youtube`, `instagram`, `facebook`.
21
+ - Use `nmsocial update check` to inspect CLI updates. Only run `nmsocial update` when the user explicitly asks to update the installed CLI.
22
+
23
+ ## Login
24
+
25
+ ```bash
26
+ nmsocial login --api-key YOUR_KEY
27
+ nmsocial login --api-key-stdin
28
+ nmsocial status
29
+ nmsocial logout
30
+ ```
31
+
32
+ ## CLI Updates
33
+
34
+ ```bash
35
+ nmsocial update check
36
+ nmsocial update --dry-run
37
+ nmsocial update
38
+ nmsocial update --manager npm
39
+ nmsocial update --manager pnpm
40
+ nmsocial update --manager bun
41
+ ```
42
+
43
+ ## Accounts
44
+
45
+ ```bash
46
+ nmsocial auth-url --platform tiktok
47
+ nmsocial accounts list --platform tiktok --status 1 --page 1 --page-size 20
48
+ ```
49
+
50
+ ## YouTube Series
51
+
52
+ ```bash
53
+ nmsocial youtube series list --open-id CHANNEL_ID
54
+ nmsocial youtube series create --open-id CHANNEL_ID --title "Demo Series" --description "Demo description"
55
+ ```
56
+
57
+ ## Materials
58
+
59
+ ```bash
60
+ nmsocial materials list --type 1 --page 1 --page-size 20
61
+ nmsocial materials upload ./demo.mp4
62
+ ```
63
+
64
+ ## Publishing
65
+
66
+ Create video task:
67
+
68
+ ```bash
69
+ nmsocial publish video --account OPEN_ID --content https://example.com/video.mp4 --caption "hello"
70
+ ```
71
+
72
+ Create image task:
73
+
74
+ ```bash
75
+ nmsocial publish image --account OPEN_ID --content https://example.com/a.png --content https://example.com/b.png --title "title"
76
+ ```
77
+
78
+ Schedule task:
79
+
80
+ ```bash
81
+ nmsocial publish video --account OPEN_ID --content https://example.com/video.mp4 --at 2026-07-18T10:00:00+08:00
82
+ ```
83
+
84
+ Preview task:
85
+
86
+ ```bash
87
+ nmsocial publish video --account OPEN_ID --content https://example.com/video.mp4 --dry-run --json
88
+ ```
89
+
90
+ ## Tasks And Posts
91
+
92
+ ```bash
93
+ nmsocial tasks list --platform tiktok --page 1 --page-size 20
94
+ nmsocial posts list --platform tiktok --open-id OPEN_ID
95
+ nmsocial posts stats --platform tiktok --main-task-id TASK_ID
96
+ ```
97
+
98
+ ## Comments
99
+
100
+ ```bash
101
+ nmsocial comments list --platform tiktok --open-id OPEN_ID
102
+ nmsocial comments reply --platform tiktok --open-id OPEN_ID --video-id VIDEO_ID --comment-id COMMENT_ID --text "Thanks"
103
+ ```
104
+
105
+ Preview reply:
106
+
107
+ ```bash
108
+ nmsocial comments reply --platform tiktok --open-id OPEN_ID --video-id VIDEO_ID --comment-id COMMENT_ID --text "Thanks" --dry-run --json
109
+ ```
110
+
111
+ ## Webhook
112
+
113
+ ```bash
114
+ nmsocial webhook set --url https://partner.example.com/spost/webhook
115
+ nmsocial webhook disable
116
+ ```
117
+
118
+ ## Statistics
119
+
120
+ ```bash
121
+ nmsocial stats overview --platform tiktok --start-date 2026-07-11 --end-date 2026-07-17
122
+ nmsocial stats account trend --platform tiktok --metric followers
123
+ nmsocial stats account rank --metric followerIncrease --order desc --page 1 --page-size 20
124
+ nmsocial stats post trend --platform tiktok --metric viewCount
125
+ nmsocial stats post rank --metric viewIncrease --order desc --page 1 --page-size 20
126
+ nmsocial stats post detail-trend --post-id POST_ID --metric viewCount --metric likeCount
127
+ nmsocial stats platform summary --start-date 2026-07-11 --end-date 2026-07-17
128
+ ```
129
+
130
+ ## Auto Replies
131
+
132
+ ```bash
133
+ nmsocial auto-replies list --platform tiktok --page 1 --page-size 20
134
+ nmsocial auto-replies detail --id STRATEGY_ID
135
+ nmsocial auto-replies create --from-file ./auto-reply.json --dry-run --json
136
+ nmsocial auto-replies update --id STRATEGY_ID --from-file ./auto-reply.json
137
+ nmsocial auto-replies enable --id STRATEGY_ID
138
+ nmsocial auto-replies disable --id STRATEGY_ID
139
+ nmsocial auto-replies delete --id STRATEGY_ID
140
+ ```
141
+
142
+ ## Output
143
+
144
+ Use `--json` for stable output:
145
+
146
+ ```json
147
+ {
148
+ "ok": true,
149
+ "data": {},
150
+ "error": null,
151
+ "meta": {}
152
+ }
153
+ ```
154
+
155
+ On failure, inspect `error.code` and `error.message`.