slkcli 0.1.1 → 0.1.2
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 +5 -0
- package/bin/slk.js +6 -0
- package/package.json +1 -1
- package/src/api.js +1 -0
- package/src/commands.js +66 -0
package/README.md
CHANGED
|
@@ -59,6 +59,9 @@ slk unread
|
|
|
59
59
|
# See starred items and VIP users
|
|
60
60
|
slk starred
|
|
61
61
|
|
|
62
|
+
# See saved for later items
|
|
63
|
+
slk saved
|
|
64
|
+
|
|
62
65
|
# See pinned messages in a channel
|
|
63
66
|
slk pins general
|
|
64
67
|
|
|
@@ -84,6 +87,7 @@ slk react general 1234567890.123456 thumbsup
|
|
|
84
87
|
| `slk activity` | `a` | Show all channel activity with unread/mention counts |
|
|
85
88
|
| `slk unread` | `ur` | Show only channels with unreads (excludes muted) |
|
|
86
89
|
| `slk starred` | `star` | Show VIP users and starred items |
|
|
90
|
+
| `slk saved [count]` | `sv` | Show saved for later items (active by default, `--all` includes completed) |
|
|
87
91
|
| `slk pins <channel>` | `pin` | Show pinned items in a channel |
|
|
88
92
|
|
|
89
93
|
### Flags
|
|
@@ -92,6 +96,7 @@ slk react general 1234567890.123456 thumbsup
|
|
|
92
96
|
|------|-------------|
|
|
93
97
|
| `--ts` | Show raw Slack timestamps (useful for getting ts to read threads) |
|
|
94
98
|
| `--no-emoji` | Disable emoji in output (or set `NO_EMOJI=1`) |
|
|
99
|
+
| `--all` | Include completed items in `slk saved` |
|
|
95
100
|
|
|
96
101
|
```bash
|
|
97
102
|
# Get timestamps to use with thread command
|
package/bin/slk.js
CHANGED
|
@@ -28,6 +28,7 @@ Commands:
|
|
|
28
28
|
slk activity (a) Channel activity with unread/mention counts
|
|
29
29
|
slk unread (ur) Channels with unreads (excludes muted)
|
|
30
30
|
slk starred (star) VIP users + starred items
|
|
31
|
+
slk saved [n] (sv) Saved for later items (--all includes completed)
|
|
31
32
|
slk pins <ch> (pin) Pinned items in a channel
|
|
32
33
|
|
|
33
34
|
Drafts (synced to Slack UI):
|
|
@@ -119,6 +120,11 @@ async function main() {
|
|
|
119
120
|
await cmd.starred();
|
|
120
121
|
break;
|
|
121
122
|
|
|
123
|
+
case "saved":
|
|
124
|
+
case "sv":
|
|
125
|
+
await cmd.saved(parseInt(args[1]) || 20, args.includes("--all"));
|
|
126
|
+
break;
|
|
127
|
+
|
|
122
128
|
case "pins":
|
|
123
129
|
case "pin":
|
|
124
130
|
if (!args[1]) { console.error("Usage: slk pins <channel>"); process.exit(1); }
|
package/package.json
CHANGED
package/src/api.js
CHANGED
package/src/commands.js
CHANGED
|
@@ -333,6 +333,72 @@ export async function pins(channelRef) {
|
|
|
333
333
|
}
|
|
334
334
|
}
|
|
335
335
|
|
|
336
|
+
export async function saved(count = 20, includeCompleted = false) {
|
|
337
|
+
const users = await getUsers();
|
|
338
|
+
|
|
339
|
+
// Build channel name map
|
|
340
|
+
const chData = await slackPaginate("conversations.list", {
|
|
341
|
+
types: "public_channel,private_channel,mpim,im",
|
|
342
|
+
exclude_archived: true,
|
|
343
|
+
});
|
|
344
|
+
const chMap = {};
|
|
345
|
+
if (chData.ok) {
|
|
346
|
+
for (const ch of chData.channels) {
|
|
347
|
+
chMap[ch.id] = ch.name || (ch.user ? `DM:${userName(users, ch.user)}` : ch.id);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
const data = await slackApi("saved.list", { count });
|
|
352
|
+
if (!data.ok) {
|
|
353
|
+
console.error(`Error: ${data.error}`);
|
|
354
|
+
process.exit(1);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
const items = data.saved_items || [];
|
|
358
|
+
const counts = data.counts || {};
|
|
359
|
+
console.log(`📑 Saved for Later — ${counts.uncompleted_count || 0} active, ${counts.completed_count || 0} completed\n`);
|
|
360
|
+
|
|
361
|
+
if (!items.length) {
|
|
362
|
+
console.log("No saved items.");
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
for (const item of items) {
|
|
367
|
+
if (!includeCompleted && item.state === "completed") continue;
|
|
368
|
+
|
|
369
|
+
const chName = chMap[item.item_id] || item.item_id;
|
|
370
|
+
const savedAt = formatTs(item.date_created);
|
|
371
|
+
const state = item.state === "completed" ? " ✅" : "";
|
|
372
|
+
|
|
373
|
+
// Fetch the actual message
|
|
374
|
+
try {
|
|
375
|
+
const msgData = await slackApi("conversations.history", {
|
|
376
|
+
channel: item.item_id,
|
|
377
|
+
latest: item.ts,
|
|
378
|
+
inclusive: true,
|
|
379
|
+
limit: 1,
|
|
380
|
+
});
|
|
381
|
+
if (msgData.ok && msgData.messages?.[0]) {
|
|
382
|
+
const msg = msgData.messages[0];
|
|
383
|
+
const who = userName(users, msg.user);
|
|
384
|
+
const msgTime = formatTs(msg.ts);
|
|
385
|
+
console.log(`[saved ${savedAt}]${state} #${chName} — ${who} (${msgTime}):`);
|
|
386
|
+
console.log(` ${(msg.text || "").substring(0, 300)}`);
|
|
387
|
+
if (msg.files?.length) {
|
|
388
|
+
for (const f of msg.files) {
|
|
389
|
+
console.log(` 📎 ${f.name} (${f.mimetype})`);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
} else {
|
|
393
|
+
console.log(`[saved ${savedAt}]${state} #${chName} (ts: ${item.ts}) — could not fetch message`);
|
|
394
|
+
}
|
|
395
|
+
} catch {
|
|
396
|
+
console.log(`[saved ${savedAt}]${state} #${chName} (ts: ${item.ts}) — access denied or channel not found`);
|
|
397
|
+
}
|
|
398
|
+
console.log();
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
336
402
|
export async function react(channelRef, ts, emoji) {
|
|
337
403
|
const channel = await resolveChannel(channelRef);
|
|
338
404
|
const data = await slackApi("reactions.add", {
|