chirpie 1.0.40 → 1.0.42
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/README.md +2 -0
- package/dist/index.js +83 -3
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -34,9 +34,11 @@ export CHIRPIE_API_KEY=chirpie_sk_...
|
|
|
34
34
|
| `chirpie thread <post> <post> ...` | Create a 2 to 25 post thread. `-f` takes a JSON payload file |
|
|
35
35
|
| `chirpie posts` | List posts. `--status`, `--account`, `--limit` |
|
|
36
36
|
| `chirpie posts get <id>` | Fetch one post |
|
|
37
|
+
| `chirpie posts update <id>` | Edit a post that has not published yet. `--text`, `--media`, `--clear-media`, `--schedule-at`. Leaving `--schedule-at` out keeps the time it already has |
|
|
37
38
|
| `chirpie posts delete <id>` | Delete a post. Deleting any post of a scheduled thread cancels the thread |
|
|
38
39
|
| `chirpie accounts` | List connected accounts, active and inactive |
|
|
39
40
|
| `chirpie accounts activate <id>` / `deactivate <id>` | Choose which accounts publish. Deactivating cancels that account's scheduled posts |
|
|
41
|
+
| `chirpie accounts disconnect <id>` | End a connection. Cancels that account's scheduled posts, frees a plan slot, and removes the stored credential, so reconnecting means authorizing again. Asks first; `-y` skips the prompt |
|
|
40
42
|
| `chirpie accounts connect-x` | Start the X OAuth flow and print the URL |
|
|
41
43
|
| `chirpie accounts connect-bluesky` | Connect Bluesky with an app password |
|
|
42
44
|
| `chirpie accounts connect-linkedin` / `connect-mastodon` | Start that platform's OAuth flow |
|
package/dist/index.js
CHANGED
|
@@ -287,7 +287,7 @@ function wantsJson(opts, cmd) {
|
|
|
287
287
|
}
|
|
288
288
|
|
|
289
289
|
// src/commands/posts.ts
|
|
290
|
-
var postsCommand = new Command5("posts").description("List, get, or delete posts").option("--status <status>", "Filter by status").option("--account <id>", "Filter by account").option("--limit <n>", "Limit results", "20").option("--json", "Output raw JSON").action(async (opts, cmd) => {
|
|
290
|
+
var postsCommand = new Command5("posts").description("List, get, update, or delete posts").option("--status <status>", "Filter by status").option("--account <id>", "Filter by account").option("--limit <n>", "Limit results", "20").option("--json", "Output raw JSON").action(async (opts, cmd) => {
|
|
291
291
|
const client = getClient();
|
|
292
292
|
try {
|
|
293
293
|
const posts = await client.listPosts({
|
|
@@ -332,6 +332,47 @@ postsCommand.command("get <id>").description("Get a post by ID").option("--json"
|
|
|
332
332
|
process.exit(1);
|
|
333
333
|
}
|
|
334
334
|
});
|
|
335
|
+
postsCommand.command("update <id>").description(
|
|
336
|
+
"Edit a post that has not published yet. Leaving --schedule-at out keeps the time it already has"
|
|
337
|
+
).option("-t, --text <text>", "Replacement post text").option(
|
|
338
|
+
"-m, --media <urls...>",
|
|
339
|
+
"Replacement image or video URLs, following the same per-platform rules as creating a post. Pass --clear-media to remove the media instead."
|
|
340
|
+
).option("--clear-media", "Remove the media from the post").option(
|
|
341
|
+
"-s, --schedule-at <datetime>",
|
|
342
|
+
"New publish time. Any ISO 8601 timestamp with a timezone (2027-04-01T14:00:00Z or 2027-04-01T16:00:00+02:00). Omit it to keep the time the post already has. Rescheduling one part of a thread moves the whole thread."
|
|
343
|
+
).option("--json", "Output raw JSON").action(async (id, opts, cmd) => {
|
|
344
|
+
if (opts.media && opts.clearMedia) {
|
|
345
|
+
error("Pass either --media or --clear-media, not both");
|
|
346
|
+
process.exit(1);
|
|
347
|
+
}
|
|
348
|
+
if (!opts.text && !opts.media && !opts.clearMedia && !opts.scheduleAt) {
|
|
349
|
+
error("Nothing to change. Pass --text, --media, --clear-media or --schedule-at");
|
|
350
|
+
process.exit(1);
|
|
351
|
+
}
|
|
352
|
+
const client = getClient();
|
|
353
|
+
try {
|
|
354
|
+
const post = await client.updatePost(id, {
|
|
355
|
+
...opts.text !== void 0 ? { text: opts.text } : {},
|
|
356
|
+
...opts.clearMedia ? { media_urls: [] } : {},
|
|
357
|
+
...opts.media ? { media_urls: opts.media } : {},
|
|
358
|
+
...opts.scheduleAt ? { schedule_at: opts.scheduleAt } : {}
|
|
359
|
+
});
|
|
360
|
+
if (wantsJson(opts, cmd)) {
|
|
361
|
+
json(post);
|
|
362
|
+
} else {
|
|
363
|
+
const moved = post.rescheduled_post_ids ?? [];
|
|
364
|
+
success(`Post ${post.id} updated`);
|
|
365
|
+
if (opts.scheduleAt) {
|
|
366
|
+
success(
|
|
367
|
+
moved.length > 1 ? `Thread rescheduled for ${post.scheduled_at} (${moved.length} posts)` : `Scheduled for ${post.scheduled_at}`
|
|
368
|
+
);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
} catch (err) {
|
|
372
|
+
apiError(err, "Failed to update post");
|
|
373
|
+
process.exit(1);
|
|
374
|
+
}
|
|
375
|
+
});
|
|
335
376
|
postsCommand.command("delete <id>").description(
|
|
336
377
|
"Delete a post (deleting any post of a scheduled thread cancels the thread)"
|
|
337
378
|
).option("--json", "Output raw JSON").action(async (id, opts, cmd) => {
|
|
@@ -475,6 +516,45 @@ accountsCommand.command("deactivate").argument("<id>", "Account ID (from `chirpi
|
|
|
475
516
|
process.exit(1);
|
|
476
517
|
}
|
|
477
518
|
});
|
|
519
|
+
accountsCommand.command("disconnect").argument("<id>", "Account ID (from `chirpie accounts`)").description(
|
|
520
|
+
"Disconnect a connected account (stops publishing, frees a plan slot, cancels its scheduled posts)"
|
|
521
|
+
).option("-y, --yes", "Skip the confirmation prompt").option("--json", "Output raw JSON").action(async (id, opts, cmd) => {
|
|
522
|
+
if (!opts.yes && !await confirm(`Disconnect account ${id}?`)) {
|
|
523
|
+
error("Cancelled");
|
|
524
|
+
process.exit(1);
|
|
525
|
+
}
|
|
526
|
+
const client = getClient();
|
|
527
|
+
try {
|
|
528
|
+
const result = await client.disconnectAccount(id);
|
|
529
|
+
if (wantsJson(opts, cmd)) {
|
|
530
|
+
json(result);
|
|
531
|
+
} else {
|
|
532
|
+
success(`Disconnected account ${id}`);
|
|
533
|
+
if (result.canceled_posts > 0) {
|
|
534
|
+
success(
|
|
535
|
+
`Cancelled ${result.canceled_posts} scheduled post${result.canceled_posts === 1 ? "" : "s"} and returned them to your monthly quota. They are not restored if you connect the account again.`
|
|
536
|
+
);
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
} catch (err) {
|
|
540
|
+
error(err instanceof Error ? err.message : "Failed to disconnect account");
|
|
541
|
+
process.exit(1);
|
|
542
|
+
}
|
|
543
|
+
});
|
|
544
|
+
async function confirm(question) {
|
|
545
|
+
if (!process.stdin.isTTY) return false;
|
|
546
|
+
const readline = await import("readline");
|
|
547
|
+
const rl = readline.createInterface({
|
|
548
|
+
input: process.stdin,
|
|
549
|
+
output: process.stderr
|
|
550
|
+
});
|
|
551
|
+
return new Promise((resolve) => {
|
|
552
|
+
rl.question(`${question} [y/N] `, (answer) => {
|
|
553
|
+
rl.close();
|
|
554
|
+
resolve(answer.trim().toLowerCase() === "y");
|
|
555
|
+
});
|
|
556
|
+
});
|
|
557
|
+
}
|
|
478
558
|
accountsCommand.command("connect-x").description("Connect a new X/Twitter account via OAuth").option("--json", "Output raw JSON").action(async (opts, cmd) => {
|
|
479
559
|
const client = getClient();
|
|
480
560
|
try {
|
|
@@ -832,7 +912,7 @@ commentsCommand.command("hide").description("Hide a comment, or show it again wi
|
|
|
832
912
|
}
|
|
833
913
|
});
|
|
834
914
|
commentsCommand.command("delete").description("Delete a comment from the platform").argument("<post_id>", "Post ID").argument("<comment_id>", "Comment ID from `chirpie comments list`").option("-y, --yes", "Skip the confirmation prompt").option("--json", "Output raw JSON").action(async (postId, commentId, opts, cmd) => {
|
|
835
|
-
if (!opts.yes && !await
|
|
915
|
+
if (!opts.yes && !await confirm2(`Delete comment ${commentId}?`)) {
|
|
836
916
|
error("Cancelled");
|
|
837
917
|
process.exit(1);
|
|
838
918
|
}
|
|
@@ -849,7 +929,7 @@ commentsCommand.command("delete").description("Delete a comment from the platfor
|
|
|
849
929
|
process.exit(1);
|
|
850
930
|
}
|
|
851
931
|
});
|
|
852
|
-
async function
|
|
932
|
+
async function confirm2(question) {
|
|
853
933
|
if (!process.stdin.isTTY) return false;
|
|
854
934
|
const readline = await import("readline");
|
|
855
935
|
const rl = readline.createInterface({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chirpie",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.42",
|
|
4
4
|
"description": "Chirpie CLI: post to social media from the command line",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
],
|
|
45
45
|
"license": "MIT",
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@chirpie/sdk": "^1.0.
|
|
47
|
+
"@chirpie/sdk": "^1.0.39",
|
|
48
48
|
"commander": "^13"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|