@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.
- package/LICENSE +17 -0
- package/README.md +478 -0
- package/dist/bin/nmsocial.js +14 -0
- package/dist/cli/args.js +103 -0
- package/dist/cli/config.js +69 -0
- package/dist/cli/help.js +21 -0
- package/dist/cli/output.js +386 -0
- package/dist/cli/router.js +82 -0
- package/dist/commands/accounts.js +19 -0
- package/dist/commands/auth.js +4 -0
- package/dist/commands/auto-replies.js +88 -0
- package/dist/commands/comments.js +49 -0
- package/dist/commands/materials.js +19 -0
- package/dist/commands/posts.js +40 -0
- package/dist/commands/publish.js +69 -0
- package/dist/commands/session.js +40 -0
- package/dist/commands/stats.js +65 -0
- package/dist/commands/tasks.js +17 -0
- package/dist/commands/types.js +1 -0
- package/dist/commands/update.js +138 -0
- package/dist/commands/webhook.js +16 -0
- package/dist/commands/youtube.js +16 -0
- package/dist/social/client.js +95 -0
- package/dist/social/types.js +47 -0
- package/dist/utils/query.js +30 -0
- package/dist/utils/stdin.js +17 -0
- package/dist/utils/validation.js +76 -0
- package/package.json +50 -0
- package/skills/nmsocial-cli/SKILL.md +155 -0
|
@@ -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`.
|