slack-term 1.26.1 → 1.26.3

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 +63 -63
  2. package/package.json +1 -1
  3. package/ts/cli.ts +49 -16
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "slack-term",
3
- "version": "1.26.1",
3
+ "version": "1.26.3",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/snomiao/slack-term.git"
package/ts/cli.ts CHANGED
@@ -1224,14 +1224,27 @@ interface SendArgs {
1224
1224
  // Slack does not notify you about messages you sent to yourself, so an
1225
1225
  // escalation DM via `send @me` (or @your-own-handle) is delivered but never
1226
1226
  // surfaces. Returns true when ref names the token's own user.
1227
- async function isSelfDm(token: string, ref: string, cookie?: string): Promise<boolean> {
1228
- if (!ref.startsWith("@")) return false;
1229
- const name = ref.slice(1).toLowerCase().replace(/[^a-z0-9]/g, "");
1230
- if (name === "me" || name === "you") return true;
1227
+ /** Is `channelId` the token owner's DM with themselves?
1228
+ *
1229
+ * Decided on the RESOLVED channel rather than the target string. Matching the
1230
+ * target text only catches the spellings someone thought of (`@me`, the exact
1231
+ * handle) and misses every other way the same conversation gets addressed — a
1232
+ * display name, `--user-id`, `--channel-id`, a permalink. Slack's self-DM is an
1233
+ * IM whose counterparty is you, which is true regardless of how it was named.
1234
+ *
1235
+ * Fail-soft: an unreadable channel returns false, so the send is never blocked
1236
+ * by a lookup failure. Only asked for `D…` ids, so channel sends pay nothing. */
1237
+ async function isSelfDmChannel(
1238
+ token: string,
1239
+ channelId: string,
1240
+ selfUserId: string | undefined,
1241
+ cookie?: string,
1242
+ ): Promise<boolean> {
1243
+ if (!selfUserId || !channelId.startsWith("D")) return false;
1231
1244
  try {
1232
- const self = await authTest(token, cookie);
1233
- const selfName = (self.user ?? "").toLowerCase().replace(/[^a-z0-9]/g, "");
1234
- return selfName !== "" && selfName === name;
1245
+ const info = asRecord((await conversationInfo(token, channelId, cookie)) as Json);
1246
+ const ch = asRecord(info.channel);
1247
+ return ch.is_im === true && ch.user === selfUserId;
1235
1248
  } catch {
1236
1249
  return false;
1237
1250
  }
@@ -1245,20 +1258,24 @@ async function cmdSend(token: string, args: SendArgs): Promise<void> {
1245
1258
  // --as-bot, the user token otherwise.
1246
1259
  const getSelf = selfLookup(token, cookie);
1247
1260
 
1248
- // Guard the self-DM footgun before doing anything else, unless sending as the
1249
- // bot (which delivers a notifiable DM from a different identity).
1250
- if (!args.asBot && !args.channelId && !args.userId && await isSelfDm(token, ref, cookie)) {
1251
- console.error(
1252
- `Warning: "${ref}" is a DM to yourself — Slack will NOT notify you of your own message.\n` +
1253
- ` To reach yourself with a notification, send as the bot: slack send '${ref}' '...' --as-bot`,
1254
- );
1255
- }
1256
-
1257
1261
  let channelId: string;
1258
1262
  if (args.channelId) channelId = args.channelId;
1259
1263
  else if (args.userId) channelId = await openDm(token, args.userId, cookie);
1260
1264
  else channelId = await resolveChannel(token, ref, cookie);
1261
1265
 
1266
+ // Self-DM footgun: Slack never notifies you about a message you sent, so a DM
1267
+ // to yourself is delivered and then silently never surfaces — the worst shape
1268
+ // for an escalation ("I told you" / nobody saw it). Checked after resolution
1269
+ // so it fires however the DM was addressed: @me, a handle, a display name,
1270
+ // --user-id, --channel-id, or a permalink. --as-bot is exempt: that posts as
1271
+ // the app, a different identity, which does notify you.
1272
+ if (!args.asBot && await isSelfDmChannel(token, channelId, (await getSelf())?.userId, cookie)) {
1273
+ console.error(
1274
+ `Warning: "${args.target}" is a DM to yourself — Slack will NOT notify you of your own message.\n` +
1275
+ ` To reach yourself with a notification, send as the bot: slack send '${args.target}' '...' --as-bot`,
1276
+ );
1277
+ }
1278
+
1262
1279
  // Convert @handle / @名前 tokens to <@USERID> before hashing/sending so the
1263
1280
  // safety gate covers exactly what will be posted. Unresolved tokens stay as
1264
1281
  // text. The detailed report drives the confirm-gate mention preview below.
@@ -1560,6 +1577,16 @@ async function cmdScheduleSend(token: string, args: ScheduleSendArgs): Promise<v
1560
1577
  // than anywhere else: the message goes out later, unattended, under whichever
1561
1578
  // identity was current at schedule time.
1562
1579
  const self = await getSelf();
1580
+
1581
+ // Self-DM is worst here: the message fires later, unattended, and Slack never
1582
+ // notifies you about your own post — so a scheduled reminder to yourself is
1583
+ // delivered into silence at exactly the moment you were counting on it.
1584
+ if (await isSelfDmChannel(token, channelId, self?.userId, args.cookie)) {
1585
+ console.error(
1586
+ `Warning: "${args.target}" is a DM to yourself — Slack will NOT notify you when this fires.`,
1587
+ );
1588
+ }
1589
+
1563
1590
  const code = safetyCode(channelId, args.message, String(postAt), self?.userId ?? "");
1564
1591
 
1565
1592
  if (args.code !== code) {
@@ -1651,6 +1678,12 @@ async function cmdUpload(token: string, args: UploadArgs): Promise<void> {
1651
1678
  else if (args.userId) channelId = await openDm(token, args.userId, args.cookie);
1652
1679
  else channelId = await resolveChannel(token, ref, args.cookie);
1653
1680
 
1681
+ // Same silent-delivery footgun as `send`: a file uploaded to your own DM
1682
+ // notifies nobody, so it lands and is never seen.
1683
+ if (await isSelfDmChannel(token, channelId, (await getSelf())?.userId, args.cookie)) {
1684
+ console.error(`Warning: "${args.target}" is a DM to yourself — Slack will NOT notify you of your own upload.`);
1685
+ }
1686
+
1654
1687
  const isBatch = args.filePaths.length > 1;
1655
1688
  const files = args.filePaths.map((fp) => {
1656
1689
  const filename = basename(fp);