slack-term 1.15.0 → 1.16.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.
Files changed (3) hide show
  1. package/dist/cli.js +58 -58
  2. package/package.json +1 -1
  3. package/ts/cli.ts +43 -16
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "slack-term",
3
- "version": "1.15.0",
3
+ "version": "1.16.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/snomiao/slack-term.git"
package/ts/cli.ts CHANGED
@@ -188,31 +188,52 @@ async function formatMsgLine(
188
188
  return `${stamp} ${who}: ${body}${tail}`;
189
189
  }
190
190
 
191
+ // Slim a raw message down to the fields a script actually needs. Keeps the
192
+ // author's user ID (incl. external / Slack-Connect guests that never appear in
193
+ // users.list) so callers can resolve mentions without scraping history by hand.
194
+ function slimMsg(m: Record<string, Json>): Record<string, Json> {
195
+ return {
196
+ ts: m.ts ?? null,
197
+ user: m.user ?? null,
198
+ username: m.username ?? null,
199
+ bot_id: m.bot_id ?? null,
200
+ thread_ts: m.thread_ts ?? null,
201
+ text: typeof m.text === "string" ? m.text : "",
202
+ };
203
+ }
204
+
191
205
  // --- msgs <target> — channel/DM history with timestamps ---
192
- async function cmdMsgsTarget(token: string, target: string, limit: number): Promise<void> {
206
+ async function cmdMsgsTarget(token: string, target: string, limit: number, format: "text" | "jsonl" = "text"): Promise<void> {
193
207
  const parsed = parseSlackPermalink(target);
194
208
  const channelId = await resolveChannel(token, target);
195
209
  const cache = new Map<string, string>();
196
- if (parsed?.threadTs) {
197
- const resp = (await replies(token, channelId, parsed.threadTs, limit)) as Record<string, Json>;
198
- const msgs = asArray(resp.messages).map(asRecord);
199
- for (const m of msgs) {
200
- console.log(await formatMsgLine(token, m, cache));
210
+ const fetchMsgs = async (): Promise<Record<string, Json>[]> => {
211
+ if (parsed?.threadTs) {
212
+ const resp = (await replies(token, channelId, parsed.threadTs, limit)) as Record<string, Json>;
213
+ return asArray(resp.messages).map(asRecord);
201
214
  }
202
- } else {
203
215
  const hist = (await history(token, channelId, limit)) as Record<string, Json>;
204
- const msgs = asArray(hist.messages).map(asRecord);
205
- for (const m of msgs.reverse()) {
206
- console.log(await formatMsgLine(token, m, cache));
207
- }
216
+ return asArray(hist.messages).map(asRecord).reverse();
217
+ };
218
+ const msgs = await fetchMsgs();
219
+ if (format === "jsonl") {
220
+ for (const m of msgs) console.log(JSON.stringify(slimMsg(m)));
221
+ return;
222
+ }
223
+ for (const m of msgs) {
224
+ console.log(await formatMsgLine(token, m, cache));
208
225
  }
209
226
  }
210
227
 
211
228
  // --- thread ---
212
- async function cmdThread(token: string, target: string, ts: string, limit: number): Promise<void> {
229
+ async function cmdThread(token: string, target: string, ts: string, limit: number, format: "text" | "jsonl" = "text"): Promise<void> {
213
230
  const channelId = await resolveChannel(token, target);
214
231
  const resp = (await replies(token, channelId, parseInputTs(ts), limit)) as Record<string, Json>;
215
232
  const msgs = asArray(resp.messages).map(asRecord);
233
+ if (format === "jsonl") {
234
+ for (const m of msgs) console.log(JSON.stringify(slimMsg(m)));
235
+ return;
236
+ }
216
237
  const cache = new Map<string, string>();
217
238
  for (const m of msgs) {
218
239
  console.log(await formatMsgLine(token, m, cache));
@@ -1025,10 +1046,13 @@ async function main(): Promise<void> {
1025
1046
  "Browse messages",
1026
1047
  (y) => y
1027
1048
  .positional("target", { type: "string", describe: "#channel, @user, or URL" })
1028
- .option("limit", { alias: "n", type: "number", default: 20, describe: "Number of messages" }),
1049
+ .option("limit", { alias: "n", type: "number", default: 20, describe: "Number of messages" })
1050
+ .option("format", { type: "string", choices: ["text", "jsonl"] as const, default: "text", describe: "jsonl exposes raw ts/user/text (incl. external-guest user IDs)" })
1051
+ .option("json", { type: "boolean", default: false, describe: "Alias for --format=jsonl" }),
1029
1052
  async (argv) => {
1030
1053
  const token = tok(argv as W);
1031
- if (argv.target) await cmdMsgsTarget(token, argv.target, argv.limit);
1054
+ const format = argv.json ? "jsonl" : (argv.format as "text" | "jsonl");
1055
+ if (argv.target) await cmdMsgsTarget(token, argv.target, argv.limit, format);
1032
1056
  else await cmdMsgs(token);
1033
1057
  },
1034
1058
  )
@@ -1038,9 +1062,12 @@ async function main(): Promise<void> {
1038
1062
  (y) => y
1039
1063
  .positional("target", { type: "string", demandOption: true })
1040
1064
  .positional("ts", { type: "string", demandOption: true })
1041
- .option("limit", { alias: "n", type: "number", default: 100 }),
1065
+ .option("limit", { alias: "n", type: "number", default: 100 })
1066
+ .option("format", { type: "string", choices: ["text", "jsonl"] as const, default: "text", describe: "jsonl exposes raw ts/user/text (incl. external-guest user IDs)" })
1067
+ .option("json", { type: "boolean", default: false, describe: "Alias for --format=jsonl" }),
1042
1068
  async (argv) => {
1043
- await cmdThread(tok(argv as W), argv.target!, argv.ts!, argv.limit);
1069
+ const format = argv.json ? "jsonl" : (argv.format as "text" | "jsonl");
1070
+ await cmdThread(tok(argv as W), argv.target!, argv.ts!, argv.limit, format);
1044
1071
  },
1045
1072
  )
1046
1073
  .command(