[Fix] Discord posts account-link setup clutter in public channels#524
Conversation
Keep full setup copy out of public channels when an unlinked user pings Roomote: open a DM with the full link prompt and acknowledge briefly in the channel. Fall back to public instructions when DMs are blocked.
|
No new code issues found. See task
Reviewed 58ebe95 |
Rethrow retryable Discord DM failures so the Gateway keeps the event instead of leaking full setup instructions into the guild channel.
|
Addressed the review note on transient DM failures:
Covered with unit tests for blocked-DM fallback vs 503 on transient failure. |
Only Discord's cannot-send-messages code treats DMs as blocked. Bare 403s like Missing Access no longer dump full setup instructions in guild channels.
|
Tightened the blocked-DM check further: public fallback now requires Discord error code |
Review feedback: the mention-flow link prompt sent a fresh DM on every unlinked ping while the auto-start nudge next door already had a Redis dedupe. Both paths now share one claim/release slot (24h TTL per user) in account-link.ts, so repeated pings acknowledge the existing DM, a Gateway retry after a partial failure cannot double-send, and any entry path suppresses the others' duplicates. The mention flow fails open when Redis is unavailable (a possible duplicate DM beats silence); the best-effort nudge keeps failing closed. Also composes the fallback instruction into the full link message so the copy cannot drift, documents the intentional silence on permanent non-50007 DM failures, covers the unlinked guild slash-command path with a test, and adds the missing changeset.
|
Pushed f3b0a3f addressing review findings:
Note one behavior change from sharing the slot: a user who received the auto-start nudge within the last day gets "I sent you a DM" on a subsequent @mention rather than a second DM (and vice versa). The instructions in either DM are equivalent, so this reads as intended dedupe rather than lost information. |
Split the per-user DM slot into pending vs sent so concurrent mention acks never treat a claimed but undelivered DM as sent. Wait briefly for settlement, then retry or 503 instead of a false channel acknowledgement.
|
Addressed the claimed-but-undelivered race:
|
The pending slot carried the full 24h dedupe TTL, so a claimant that crashed between claim and mark/release would wedge the slot for a day: every later unlinked ping would wait out the in-flight window and bounce back to the Gateway with no user-visible reply. Pending claims now expire after 120 seconds; only a confirmed delivery holds the slot for the full window.
|
The in-flight race finding was addressed twice in parallel: I had a send-on-pending variant locally while e00c3c9 landed the wait-for-settlement approach on the branch. I kept the branch's version as the base since waiting avoids duplicate DMs entirely, and layered one fix on top in 58ebe95: pending claims now expire after 120 seconds instead of carrying the full 24h dedupe TTL. Without that, a claimant crashing between claim and mark/release (deploy restart mid-DM) would wedge the slot as |
What changed
When an unlinked Discord user mentions Roomote (or otherwise tries to start work) in a guild channel, Roomote no longer posts the full “Link your Discord account…” setup copy into the public channel.
Instead it:
I sent you a DM to link your Discord account.) as a reply to the triggering message5000750007403s and network/429/5xx) so they are not mistaken for “user blocked DMs”pendingwhile delivery is in flight and only treats it assentafter the DM posts, so concurrent mentions wait for settlement instead of acknowledging a claimed-but-undelivered DMThis matches the Slack/Teams account-link delivery pattern for private setup delivery.
Why this change was made
Public account-link replies clutter shared Discord channels when someone who has not linked their account pings the bot. Private delivery keeps the channel clean while still telling the invoker exactly how to link. Distinguishing in-flight vs delivered slots closes a race where a failed concurrent unravel could leave a user with neither a DM nor a proper fallback.
Impact
Unlinked pings in servers become quieter: setup instructions go to DM, and the channel only gets a brief acknowledgement after delivery is confirmed (or a full public fallback when DMs are confirmed blocked). Concurrent paths wait or retry instead of lying that a DM went out. Behavior in already-open DMs is unchanged.