@dotta/xc 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/README.md +348 -0
- package/dist/__tests__/bookmarks.test.d.ts +4 -0
- package/dist/__tests__/bookmarks.test.js +104 -0
- package/dist/__tests__/bookmarks.test.js.map +1 -0
- package/dist/__tests__/budget.test.d.ts +6 -0
- package/dist/__tests__/budget.test.js +105 -0
- package/dist/__tests__/budget.test.js.map +1 -0
- package/dist/__tests__/dm.test.d.ts +4 -0
- package/dist/__tests__/dm.test.js +115 -0
- package/dist/__tests__/dm.test.js.map +1 -0
- package/dist/__tests__/followers.test.d.ts +4 -0
- package/dist/__tests__/followers.test.js +129 -0
- package/dist/__tests__/followers.test.js.map +1 -0
- package/dist/__tests__/lib/api.test.d.ts +5 -0
- package/dist/__tests__/lib/api.test.js +202 -0
- package/dist/__tests__/lib/api.test.js.map +1 -0
- package/dist/__tests__/lib/budget.test.d.ts +5 -0
- package/dist/__tests__/lib/budget.test.js +194 -0
- package/dist/__tests__/lib/budget.test.js.map +1 -0
- package/dist/__tests__/lib/config.test.d.ts +6 -0
- package/dist/__tests__/lib/config.test.js +228 -0
- package/dist/__tests__/lib/config.test.js.map +1 -0
- package/dist/__tests__/lib/cost.test.d.ts +6 -0
- package/dist/__tests__/lib/cost.test.js +177 -0
- package/dist/__tests__/lib/cost.test.js.map +1 -0
- package/dist/__tests__/lib/format.test.d.ts +4 -0
- package/dist/__tests__/lib/format.test.js +139 -0
- package/dist/__tests__/lib/format.test.js.map +1 -0
- package/dist/__tests__/lib/oauth.test.d.ts +5 -0
- package/dist/__tests__/lib/oauth.test.js +123 -0
- package/dist/__tests__/lib/oauth.test.js.map +1 -0
- package/dist/__tests__/lib/resolve.test.d.ts +4 -0
- package/dist/__tests__/lib/resolve.test.js +154 -0
- package/dist/__tests__/lib/resolve.test.js.map +1 -0
- package/dist/__tests__/lists.test.d.ts +4 -0
- package/dist/__tests__/lists.test.js +96 -0
- package/dist/__tests__/lists.test.js.map +1 -0
- package/dist/__tests__/media.test.d.ts +4 -0
- package/dist/__tests__/media.test.js +132 -0
- package/dist/__tests__/media.test.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +93 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/auth.d.ts +2 -0
- package/dist/commands/auth.js +191 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/block.d.ts +15 -0
- package/dist/commands/block.js +117 -0
- package/dist/commands/block.js.map +1 -0
- package/dist/commands/bookmarks.d.ts +12 -0
- package/dist/commands/bookmarks.js +100 -0
- package/dist/commands/bookmarks.js.map +1 -0
- package/dist/commands/budget.d.ts +9 -0
- package/dist/commands/budget.js +124 -0
- package/dist/commands/budget.js.map +1 -0
- package/dist/commands/cost.d.ts +5 -0
- package/dist/commands/cost.js +75 -0
- package/dist/commands/cost.js.map +1 -0
- package/dist/commands/delete.d.ts +8 -0
- package/dist/commands/delete.js +31 -0
- package/dist/commands/delete.js.map +1 -0
- package/dist/commands/dm.d.ts +10 -0
- package/dist/commands/dm.js +179 -0
- package/dist/commands/dm.js.map +1 -0
- package/dist/commands/engagement.d.ts +14 -0
- package/dist/commands/engagement.js +167 -0
- package/dist/commands/engagement.js.map +1 -0
- package/dist/commands/followers.d.ts +14 -0
- package/dist/commands/followers.js +138 -0
- package/dist/commands/followers.js.map +1 -0
- package/dist/commands/get.d.ts +2 -0
- package/dist/commands/get.js +63 -0
- package/dist/commands/get.js.map +1 -0
- package/dist/commands/hide.d.ts +10 -0
- package/dist/commands/hide.js +58 -0
- package/dist/commands/hide.js.map +1 -0
- package/dist/commands/like.d.ts +3 -0
- package/dist/commands/like.js +52 -0
- package/dist/commands/like.js.map +1 -0
- package/dist/commands/lists.d.ts +20 -0
- package/dist/commands/lists.js +384 -0
- package/dist/commands/lists.js.map +1 -0
- package/dist/commands/media.d.ts +19 -0
- package/dist/commands/media.js +205 -0
- package/dist/commands/media.js.map +1 -0
- package/dist/commands/mentions.d.ts +8 -0
- package/dist/commands/mentions.js +59 -0
- package/dist/commands/mentions.js.map +1 -0
- package/dist/commands/mute.d.ts +12 -0
- package/dist/commands/mute.js +99 -0
- package/dist/commands/mute.js.map +1 -0
- package/dist/commands/post.d.ts +11 -0
- package/dist/commands/post.js +87 -0
- package/dist/commands/post.js.map +1 -0
- package/dist/commands/repost.d.ts +10 -0
- package/dist/commands/repost.js +59 -0
- package/dist/commands/repost.js.map +1 -0
- package/dist/commands/search.d.ts +2 -0
- package/dist/commands/search.js +49 -0
- package/dist/commands/search.js.map +1 -0
- package/dist/commands/stream.d.ts +13 -0
- package/dist/commands/stream.js +251 -0
- package/dist/commands/stream.js.map +1 -0
- package/dist/commands/timeline.d.ts +2 -0
- package/dist/commands/timeline.js +61 -0
- package/dist/commands/timeline.js.map +1 -0
- package/dist/commands/trends.d.ts +10 -0
- package/dist/commands/trends.js +59 -0
- package/dist/commands/trends.js.map +1 -0
- package/dist/commands/usage.d.ts +2 -0
- package/dist/commands/usage.js +52 -0
- package/dist/commands/usage.js.map +1 -0
- package/dist/commands/user.d.ts +2 -0
- package/dist/commands/user.js +43 -0
- package/dist/commands/user.js.map +1 -0
- package/dist/commands/usersearch.d.ts +8 -0
- package/dist/commands/usersearch.js +48 -0
- package/dist/commands/usersearch.js.map +1 -0
- package/dist/commands/whoami.d.ts +2 -0
- package/dist/commands/whoami.js +54 -0
- package/dist/commands/whoami.js.map +1 -0
- package/dist/lib/api.d.ts +12 -0
- package/dist/lib/api.js +91 -0
- package/dist/lib/api.js.map +1 -0
- package/dist/lib/budget.d.ts +44 -0
- package/dist/lib/budget.js +119 -0
- package/dist/lib/budget.js.map +1 -0
- package/dist/lib/config.d.ts +39 -0
- package/dist/lib/config.js +63 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/cost.d.ts +43 -0
- package/dist/lib/cost.js +224 -0
- package/dist/lib/cost.js.map +1 -0
- package/dist/lib/format.d.ts +24 -0
- package/dist/lib/format.js +72 -0
- package/dist/lib/format.js.map +1 -0
- package/dist/lib/oauth.d.ts +32 -0
- package/dist/lib/oauth.js +132 -0
- package/dist/lib/oauth.js.map +1 -0
- package/dist/lib/resolve.d.ts +12 -0
- package/dist/lib/resolve.js +48 -0
- package/dist/lib/resolve.js.map +1 -0
- package/package.json +46 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mentions timeline command.
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* xc mentions [username] — view mentions (defaults to authenticated user)
|
|
6
|
+
*/
|
|
7
|
+
import { getClient } from "../lib/api.js";
|
|
8
|
+
import { outputJson } from "../lib/cost.js";
|
|
9
|
+
import { buildUserMap, formatTweetList } from "../lib/format.js";
|
|
10
|
+
import { resolveAuthenticatedUserId, resolveUserId, } from "../lib/resolve.js";
|
|
11
|
+
const TWEET_FIELDS = ["created_at", "public_metrics", "author_id"];
|
|
12
|
+
const EXPANSIONS = ["author_id"];
|
|
13
|
+
const USER_FIELDS = ["name", "username"];
|
|
14
|
+
export function registerMentionsCommand(program) {
|
|
15
|
+
program
|
|
16
|
+
.command("mentions [username]")
|
|
17
|
+
.description("View mentions timeline (defaults to authenticated user)")
|
|
18
|
+
.option("-n, --limit <n>", "Max results (1-100)", "20")
|
|
19
|
+
.option("--json", "Output raw JSON")
|
|
20
|
+
.option("--account <name>", "Account to use")
|
|
21
|
+
.action(async (username, opts) => {
|
|
22
|
+
try {
|
|
23
|
+
const client = await getClient(opts.account);
|
|
24
|
+
let userId;
|
|
25
|
+
if (username) {
|
|
26
|
+
userId = await resolveUserId(username, opts.account);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
userId = await resolveAuthenticatedUserId(opts.account);
|
|
30
|
+
}
|
|
31
|
+
const result = await client.users.getMentions(userId, {
|
|
32
|
+
tweetFields: TWEET_FIELDS,
|
|
33
|
+
expansions: EXPANSIONS,
|
|
34
|
+
userFields: USER_FIELDS,
|
|
35
|
+
maxResults: parseInt(opts.limit, 10),
|
|
36
|
+
});
|
|
37
|
+
if (opts.json) {
|
|
38
|
+
outputJson(result);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const tweets = result.data ?? [];
|
|
42
|
+
if (tweets.length === 0) {
|
|
43
|
+
console.log("No mentions found.");
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const usersById = buildUserMap(result.includes?.users);
|
|
47
|
+
const label = username
|
|
48
|
+
? `@${username.replace(/^@/, "")}`
|
|
49
|
+
: "your";
|
|
50
|
+
console.log(`Mentions for ${label}:\n`);
|
|
51
|
+
console.log(formatTweetList(tweets, usersById));
|
|
52
|
+
}
|
|
53
|
+
catch (err) {
|
|
54
|
+
console.error(`Error: ${err instanceof Error ? err.message : err}`);
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=mentions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mentions.js","sourceRoot":"","sources":["../../src/commands/mentions.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EACL,0BAA0B,EAC1B,aAAa,GACd,MAAM,mBAAmB,CAAC;AAE3B,MAAM,YAAY,GAAG,CAAC,YAAY,EAAE,gBAAgB,EAAE,WAAW,CAAC,CAAC;AACnE,MAAM,UAAU,GAAG,CAAC,WAAW,CAAC,CAAC;AACjC,MAAM,WAAW,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AAEzC,MAAM,UAAU,uBAAuB,CAAC,OAAgB;IACtD,OAAO;SACJ,OAAO,CAAC,qBAAqB,CAAC;SAC9B,WAAW,CAAC,yDAAyD,CAAC;SACtE,MAAM,CAAC,iBAAiB,EAAE,qBAAqB,EAAE,IAAI,CAAC;SACtD,MAAM,CAAC,QAAQ,EAAE,iBAAiB,CAAC;SACnC,MAAM,CAAC,kBAAkB,EAAE,gBAAgB,CAAC;SAC5C,MAAM,CAAC,KAAK,EAAE,QAA4B,EAAE,IAAI,EAAE,EAAE;QACnD,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAE7C,IAAI,MAAc,CAAC;YACnB,IAAI,QAAQ,EAAE,CAAC;gBACb,MAAM,GAAG,MAAM,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;YACvD,CAAC;iBAAM,CAAC;gBACN,MAAM,GAAG,MAAM,0BAA0B,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC1D,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,EAAE;gBACpD,WAAW,EAAE,YAAY;gBACzB,UAAU,EAAE,UAAU;gBACtB,UAAU,EAAE,WAAW;gBACvB,UAAU,EAAE,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC;aACrC,CAAC,CAAC;YAEH,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;gBACd,UAAU,CAAC,MAAM,CAAC,CAAC;gBACnB,OAAO;YACT,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;YACjC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACxB,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;gBAClC,OAAO;YACT,CAAC;YAED,MAAM,SAAS,GAAG,YAAY,CAAC,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;YACvD,MAAM,KAAK,GAAG,QAAQ;gBACpB,CAAC,CAAC,IAAI,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE;gBAClC,CAAC,CAAC,MAAM,CAAC;YACX,OAAO,CAAC,GAAG,CAAC,gBAAgB,KAAK,KAAK,CAAC,CAAC;YACxC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;QAClD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;YACpE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mute/unmute/muted commands.
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* xc mute <username> — mute a user
|
|
6
|
+
* xc unmute <username> — unmute a user
|
|
7
|
+
* xc muted — list muted users
|
|
8
|
+
*/
|
|
9
|
+
import { Command } from "commander";
|
|
10
|
+
export declare function registerMuteCommand(program: Command): void;
|
|
11
|
+
export declare function registerUnmuteCommand(program: Command): void;
|
|
12
|
+
export declare function registerMutedCommand(program: Command): void;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mute/unmute/muted commands.
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* xc mute <username> — mute a user
|
|
6
|
+
* xc unmute <username> — unmute a user
|
|
7
|
+
* xc muted — list muted users
|
|
8
|
+
*/
|
|
9
|
+
import { getClient } from "../lib/api.js";
|
|
10
|
+
import { outputJson } from "../lib/cost.js";
|
|
11
|
+
import { resolveAuthenticatedUserId, resolveUserId, } from "../lib/resolve.js";
|
|
12
|
+
import { formatUserLine } from "../lib/format.js";
|
|
13
|
+
export function registerMuteCommand(program) {
|
|
14
|
+
program
|
|
15
|
+
.command("mute <username>")
|
|
16
|
+
.description("Mute a user")
|
|
17
|
+
.option("--json", "Output raw JSON")
|
|
18
|
+
.option("--account <name>", "Account to use")
|
|
19
|
+
.action(async (username, opts) => {
|
|
20
|
+
try {
|
|
21
|
+
const myId = await resolveAuthenticatedUserId(opts.account);
|
|
22
|
+
const targetId = await resolveUserId(username, opts.account);
|
|
23
|
+
const client = await getClient(opts.account);
|
|
24
|
+
const result = await client.users.muteUser(myId, {
|
|
25
|
+
body: { targetUserId: targetId },
|
|
26
|
+
});
|
|
27
|
+
if (opts.json) {
|
|
28
|
+
outputJson(result);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
console.log(`Muted @${username.replace(/^@/, "")}`);
|
|
32
|
+
}
|
|
33
|
+
catch (err) {
|
|
34
|
+
console.error(`Error: ${err instanceof Error ? err.message : err}`);
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
export function registerUnmuteCommand(program) {
|
|
40
|
+
program
|
|
41
|
+
.command("unmute <username>")
|
|
42
|
+
.description("Unmute a user")
|
|
43
|
+
.option("--json", "Output raw JSON")
|
|
44
|
+
.option("--account <name>", "Account to use")
|
|
45
|
+
.action(async (username, opts) => {
|
|
46
|
+
try {
|
|
47
|
+
const myId = await resolveAuthenticatedUserId(opts.account);
|
|
48
|
+
const targetId = await resolveUserId(username, opts.account);
|
|
49
|
+
const client = await getClient(opts.account);
|
|
50
|
+
const result = await client.users.unmuteUser(myId, targetId);
|
|
51
|
+
if (opts.json) {
|
|
52
|
+
outputJson(result);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
console.log(`Unmuted @${username.replace(/^@/, "")}`);
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
console.error(`Error: ${err instanceof Error ? err.message : err}`);
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
export function registerMutedCommand(program) {
|
|
64
|
+
program
|
|
65
|
+
.command("muted")
|
|
66
|
+
.description("List muted users")
|
|
67
|
+
.option("-n, --limit <n>", "Max results (1-1000)", "100")
|
|
68
|
+
.option("--json", "Output raw JSON")
|
|
69
|
+
.option("--account <name>", "Account to use")
|
|
70
|
+
.action(async (opts) => {
|
|
71
|
+
try {
|
|
72
|
+
const userId = await resolveAuthenticatedUserId(opts.account);
|
|
73
|
+
const client = await getClient(opts.account);
|
|
74
|
+
const result = await client.users.getMuting(userId, {
|
|
75
|
+
userFields: ["username", "name", "public_metrics", "description"],
|
|
76
|
+
maxResults: parseInt(opts.limit, 10),
|
|
77
|
+
});
|
|
78
|
+
if (opts.json) {
|
|
79
|
+
outputJson(result);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
const users = (result.data ?? []);
|
|
83
|
+
if (users.length === 0) {
|
|
84
|
+
console.log("No muted users.");
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
console.log("Muted users:\n");
|
|
88
|
+
for (const user of users) {
|
|
89
|
+
console.log(formatUserLine(user));
|
|
90
|
+
}
|
|
91
|
+
console.log(`\n— ${users.length} shown`);
|
|
92
|
+
}
|
|
93
|
+
catch (err) {
|
|
94
|
+
console.error(`Error: ${err instanceof Error ? err.message : err}`);
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=mute.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mute.js","sourceRoot":"","sources":["../../src/commands/mute.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Post command: create a single post or a thread of posts.
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* xc post "hello"
|
|
6
|
+
* xc post "first" --thread "second" --thread "third"
|
|
7
|
+
* xc post "reply text" --reply <id>
|
|
8
|
+
* xc post "with image" --media photo.jpg
|
|
9
|
+
*/
|
|
10
|
+
import { Command } from "commander";
|
|
11
|
+
export declare function registerPostCommand(program: Command): void;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Post command: create a single post or a thread of posts.
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* xc post "hello"
|
|
6
|
+
* xc post "first" --thread "second" --thread "third"
|
|
7
|
+
* xc post "reply text" --reply <id>
|
|
8
|
+
* xc post "with image" --media photo.jpg
|
|
9
|
+
*/
|
|
10
|
+
import { getClient } from "../lib/api.js";
|
|
11
|
+
import { outputJson } from "../lib/cost.js";
|
|
12
|
+
import { uploadMedia } from "./media.js";
|
|
13
|
+
export function registerPostCommand(program) {
|
|
14
|
+
program
|
|
15
|
+
.command("post <text>")
|
|
16
|
+
.description("Create a post (use --thread to post a thread)")
|
|
17
|
+
.option("--reply <id>", "Reply to a post by ID")
|
|
18
|
+
.option("--quote <id>", "Quote a post by ID")
|
|
19
|
+
.option("--thread <texts...>", "Additional posts to chain as a thread")
|
|
20
|
+
.option("--media <file>", "Attach media file (image, GIF, or video)")
|
|
21
|
+
.option("--json", "Output raw JSON")
|
|
22
|
+
.option("--account <name>", "Account to use")
|
|
23
|
+
.action(async (text, opts) => {
|
|
24
|
+
try {
|
|
25
|
+
const client = await getClient(opts.account);
|
|
26
|
+
const threadTexts = opts.thread ?? [];
|
|
27
|
+
// All texts in order: first post + thread continuations
|
|
28
|
+
const allTexts = [text, ...threadTexts];
|
|
29
|
+
// Upload media if provided (attaches to the first post only)
|
|
30
|
+
let mediaId;
|
|
31
|
+
if (opts.media) {
|
|
32
|
+
console.error("Uploading media...");
|
|
33
|
+
mediaId = await uploadMedia(opts.media, opts.account);
|
|
34
|
+
}
|
|
35
|
+
// Post each tweet in sequence, chaining replies
|
|
36
|
+
const posted = [];
|
|
37
|
+
let replyToId = opts.reply;
|
|
38
|
+
for (let i = 0; i < allTexts.length; i++) {
|
|
39
|
+
const body = { text: allTexts[i] };
|
|
40
|
+
// First post may reply to an external ID; subsequent ones chain to the previous
|
|
41
|
+
if (replyToId) {
|
|
42
|
+
body.reply = { inReplyToTweetId: replyToId };
|
|
43
|
+
}
|
|
44
|
+
// Only the first post supports quoting and media
|
|
45
|
+
if (i === 0 && opts.quote) {
|
|
46
|
+
body.quoteTweetId = opts.quote;
|
|
47
|
+
}
|
|
48
|
+
if (i === 0 && mediaId) {
|
|
49
|
+
body.media = { mediaIds: [mediaId] };
|
|
50
|
+
}
|
|
51
|
+
const result = (await client.posts.create(body));
|
|
52
|
+
const data = result.data;
|
|
53
|
+
const postId = data?.id;
|
|
54
|
+
if (!postId) {
|
|
55
|
+
console.error(`Error: failed to create post ${i + 1} (no ID returned)`);
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
posted.push({ id: postId, text: data?.text ?? allTexts[i] });
|
|
59
|
+
// Chain the next post as a reply to this one
|
|
60
|
+
replyToId = postId;
|
|
61
|
+
}
|
|
62
|
+
// Output results
|
|
63
|
+
if (opts.json) {
|
|
64
|
+
outputJson(posted);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
if (posted.length === 1) {
|
|
68
|
+
// Single post
|
|
69
|
+
console.log(`Posted (id: ${posted[0].id})`);
|
|
70
|
+
console.log(` ${posted[0].text}`);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
// Thread
|
|
74
|
+
console.log(`Thread posted (${posted.length} posts):`);
|
|
75
|
+
for (let i = 0; i < posted.length; i++) {
|
|
76
|
+
console.log(` ${i + 1}. id:${posted[i].id}`);
|
|
77
|
+
console.log(` ${posted[i].text}`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
catch (err) {
|
|
82
|
+
console.error(`Error: ${err instanceof Error ? err.message : err}`);
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=post.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"post.js","sourceRoot":"","sources":["../../src/commands/post.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Repost/unrepost commands.
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* xc repost <post-id> — repost a post
|
|
6
|
+
* xc unrepost <post-id> — undo a repost
|
|
7
|
+
*/
|
|
8
|
+
import { Command } from "commander";
|
|
9
|
+
export declare function registerRepostCommand(program: Command): void;
|
|
10
|
+
export declare function registerUnrepostCommand(program: Command): void;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Repost/unrepost commands.
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* xc repost <post-id> — repost a post
|
|
6
|
+
* xc unrepost <post-id> — undo a repost
|
|
7
|
+
*/
|
|
8
|
+
import { getClient } from "../lib/api.js";
|
|
9
|
+
import { outputJson } from "../lib/cost.js";
|
|
10
|
+
import { resolveAuthenticatedUserId } from "../lib/resolve.js";
|
|
11
|
+
export function registerRepostCommand(program) {
|
|
12
|
+
program
|
|
13
|
+
.command("repost <post-id>")
|
|
14
|
+
.description("Repost a post")
|
|
15
|
+
.option("--json", "Output raw JSON")
|
|
16
|
+
.option("--account <name>", "Account to use")
|
|
17
|
+
.action(async (postId, opts) => {
|
|
18
|
+
try {
|
|
19
|
+
const userId = await resolveAuthenticatedUserId(opts.account);
|
|
20
|
+
const client = await getClient(opts.account);
|
|
21
|
+
const result = await client.users.repostPost(userId, {
|
|
22
|
+
body: { tweetId: postId },
|
|
23
|
+
});
|
|
24
|
+
if (opts.json) {
|
|
25
|
+
outputJson(result);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
console.log(`Reposted post ${postId}`);
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
console.error(`Error: ${err instanceof Error ? err.message : err}`);
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
export function registerUnrepostCommand(program) {
|
|
37
|
+
program
|
|
38
|
+
.command("unrepost <post-id>")
|
|
39
|
+
.description("Undo a repost")
|
|
40
|
+
.option("--json", "Output raw JSON")
|
|
41
|
+
.option("--account <name>", "Account to use")
|
|
42
|
+
.action(async (postId, opts) => {
|
|
43
|
+
try {
|
|
44
|
+
const userId = await resolveAuthenticatedUserId(opts.account);
|
|
45
|
+
const client = await getClient(opts.account);
|
|
46
|
+
const result = await client.users.unrepostPost(userId, postId);
|
|
47
|
+
if (opts.json) {
|
|
48
|
+
outputJson(result);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
console.log(`Unreposted post ${postId}`);
|
|
52
|
+
}
|
|
53
|
+
catch (err) {
|
|
54
|
+
console.error(`Error: ${err instanceof Error ? err.message : err}`);
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=repost.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repost.js","sourceRoot":"","sources":["../../src/commands/repost.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,0BAA0B,EAAE,MAAM,mBAAmB,CAAC;AAE/D,MAAM,UAAU,qBAAqB,CAAC,OAAgB;IACpD,OAAO;SACJ,OAAO,CAAC,kBAAkB,CAAC;SAC3B,WAAW,CAAC,eAAe,CAAC;SAC5B,MAAM,CAAC,QAAQ,EAAE,iBAAiB,CAAC;SACnC,MAAM,CAAC,kBAAkB,EAAE,gBAAgB,CAAC;SAC5C,MAAM,CAAC,KAAK,EAAE,MAAc,EAAE,IAAI,EAAE,EAAE;QACrC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,0BAA0B,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC9D,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAE7C,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,EAAE;gBACnD,IAAI,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE;aAC1B,CAAC,CAAC;YAEH,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;gBACd,UAAU,CAAC,MAAM,CAAC,CAAC;gBACnB,OAAO;YACT,CAAC;YAED,OAAO,CAAC,GAAG,CAAC,iBAAiB,MAAM,EAAE,CAAC,CAAC;QACzC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;YACpE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,OAAgB;IACtD,OAAO;SACJ,OAAO,CAAC,oBAAoB,CAAC;SAC7B,WAAW,CAAC,eAAe,CAAC;SAC5B,MAAM,CAAC,QAAQ,EAAE,iBAAiB,CAAC;SACnC,MAAM,CAAC,kBAAkB,EAAE,gBAAgB,CAAC;SAC5C,MAAM,CAAC,KAAK,EAAE,MAAc,EAAE,IAAI,EAAE,EAAE;QACrC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,0BAA0B,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC9D,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAE7C,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YAE/D,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;gBACd,UAAU,CAAC,MAAM,CAAC,CAAC;gBACnB,OAAO;YACT,CAAC;YAED,OAAO,CAAC,GAAG,CAAC,mBAAmB,MAAM,EAAE,CAAC,CAAC;QAC3C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;YACpE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { getClient } from "../lib/api.js";
|
|
2
|
+
import { outputJson } from "../lib/cost.js";
|
|
3
|
+
import { buildUserMap, formatTweetList } from "../lib/format.js";
|
|
4
|
+
const TWEET_FIELDS = ["created_at", "public_metrics", "author_id"];
|
|
5
|
+
const EXPANSIONS = ["author_id"];
|
|
6
|
+
const USER_FIELDS = ["name", "username"];
|
|
7
|
+
export function registerSearchCommand(program) {
|
|
8
|
+
program
|
|
9
|
+
.command("search <query>")
|
|
10
|
+
.description("Search posts (recent 7 days, or full archive with --archive)")
|
|
11
|
+
.option("--archive", "Search full archive instead of recent")
|
|
12
|
+
.option("-n, --limit <n>", "Max results (10-100, or 10-500 for archive)", "10")
|
|
13
|
+
.option("--json", "Output raw JSON")
|
|
14
|
+
.option("--account <name>", "Account to use")
|
|
15
|
+
.action(async (query, opts) => {
|
|
16
|
+
try {
|
|
17
|
+
const client = await getClient(opts.account);
|
|
18
|
+
const searchOpts = {
|
|
19
|
+
tweetFields: TWEET_FIELDS,
|
|
20
|
+
expansions: EXPANSIONS,
|
|
21
|
+
userFields: USER_FIELDS,
|
|
22
|
+
maxResults: Math.max(10, parseInt(opts.limit, 10)),
|
|
23
|
+
};
|
|
24
|
+
const result = opts.archive
|
|
25
|
+
? await client.posts.searchAll(query, searchOpts)
|
|
26
|
+
: await client.posts.searchRecent(query, searchOpts);
|
|
27
|
+
if (opts.json) {
|
|
28
|
+
outputJson(result);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const tweets = result.data ?? [];
|
|
32
|
+
if (tweets.length === 0) {
|
|
33
|
+
console.log("No results found.");
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const usersById = buildUserMap(result.includes?.users);
|
|
37
|
+
console.log(formatTweetList(tweets, usersById));
|
|
38
|
+
// Show result count summary
|
|
39
|
+
const meta = result.meta;
|
|
40
|
+
const count = meta?.resultCount ?? tweets.length;
|
|
41
|
+
console.log(`\n— ${count} result${count !== 1 ? "s" : ""}`);
|
|
42
|
+
}
|
|
43
|
+
catch (err) {
|
|
44
|
+
console.error(`Error: ${err instanceof Error ? err.message : err}`);
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/commands/search.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEjE,MAAM,YAAY,GAAG,CAAC,YAAY,EAAE,gBAAgB,EAAE,WAAW,CAAC,CAAC;AACnE,MAAM,UAAU,GAAG,CAAC,WAAW,CAAC,CAAC;AACjC,MAAM,WAAW,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AAEzC,MAAM,UAAU,qBAAqB,CAAC,OAAgB;IACpD,OAAO;SACJ,OAAO,CAAC,gBAAgB,CAAC;SACzB,WAAW,CAAC,8DAA8D,CAAC;SAC3E,MAAM,CAAC,WAAW,EAAE,uCAAuC,CAAC;SAC5D,MAAM,CAAC,iBAAiB,EAAE,6CAA6C,EAAE,IAAI,CAAC;SAC9E,MAAM,CAAC,QAAQ,EAAE,iBAAiB,CAAC;SACnC,MAAM,CAAC,kBAAkB,EAAE,gBAAgB,CAAC;SAC5C,MAAM,CAAC,KAAK,EAAE,KAAa,EAAE,IAAI,EAAE,EAAE;QACpC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC7C,MAAM,UAAU,GAAG;gBACjB,WAAW,EAAE,YAAY;gBACzB,UAAU,EAAE,UAAU;gBACtB,UAAU,EAAE,WAAW;gBACvB,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;aACnD,CAAC;YAEF,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO;gBACzB,CAAC,CAAC,MAAM,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,EAAE,UAAU,CAAC;gBACjD,CAAC,CAAC,MAAM,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;YAEvD,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;gBACd,UAAU,CAAC,MAAM,CAAC,CAAC;gBACnB,OAAO;YACT,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;YACjC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACxB,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;gBACjC,OAAO;YACT,CAAC;YAED,MAAM,SAAS,GAAG,YAAY,CAAC,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;YACvD,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;YAEhD,4BAA4B;YAC5B,MAAM,IAAI,GAAG,MAAM,CAAC,IAA2C,CAAC;YAChE,MAAM,KAAK,GAAI,IAAI,EAAE,WAAsB,IAAI,MAAM,CAAC,MAAM,CAAC;YAC7D,OAAO,CAAC,GAAG,CAAC,OAAO,KAAK,UAAU,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC9D,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;YACpE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stream commands: manage filtered stream rules and connect to the stream.
|
|
3
|
+
*
|
|
4
|
+
* Subcommands:
|
|
5
|
+
* xc stream add <query> [--tag <name>] — add a filtered stream rule
|
|
6
|
+
* xc stream rules — list current rules
|
|
7
|
+
* xc stream remove <rule-id> — remove a rule by ID
|
|
8
|
+
* xc stream clear — remove all rules
|
|
9
|
+
* xc stream connect [--json] [--quiet] — connect and output matching posts
|
|
10
|
+
*/
|
|
11
|
+
import { Command } from "commander";
|
|
12
|
+
/** Register the `stream` command group with its subcommands. */
|
|
13
|
+
export declare function registerStreamCommand(program: Command): void;
|