# Discord Bot — Product Context Status: **design phase, not started**. Requirements captured from Jason's explanation (2026-08-11). Keep this file updated as decisions are made — it is the canonical reference for what the bot must do. Planned location: `src/bot/` (same repo as the web app — the bot runs as a standalone long-running process importing `@payload-config`, following the existing `src/scripts/` / `src/tools/seed/` pattern). ## 1. Discord sign-up and account linking Allow people in the Discord server to sign up for the site and link their Discord account — **without OAuth / without logging into Discord**. - The bot checks the Discord username of the person trying to sign up. - If the username is acceptable, the bot uses it when creating the user (i.e., the new Payload `users` doc gets `discordUsername` = their Discord username). - This is the "linking" step: the Discord account and the site account are tied together by the matching username. ## 2. Recurring operations calendar + attendance (two-way sync) Post recurring calendar events for operations, with a **Yes / No / Tentative** sign-up system for tracking attendance. - When players mark their attendance in Discord, the corresponding mission attendance entry on the website is updated to show the same data. - When a user changes their attendance on the website, the Discord calendar embed updates to reflect the change — names move between / are removed from the Yes / No / Tentative lists. In short: Discord embed ↔ website attendance data stay in sync in both directions. ## 3. Announcements and app-event notifications Post announcements and selected app events to Discord. - Event examples: someone offers to buy a player's market listing; a shipment completes; a deposit to a bank account; etc. - Notification should be **optional, per user preference** — "The options for these could live in the user's preferences." ## Integration points (verified against the current codebase, 2026-08-11) - **Users collection** (`src/collections/users/Users.ts`): has `discordUsername` (text, required, unique) + `preferences` group (`notifications.mutedAll` / `mutedTypes`, `display.showCallsign`). No Discord snowflake/ID field yet. - **Existing standalone-process pattern**: `src/scripts/` (game-tick, market-tick bins) and `src/tools/seed/` (`backfillProfiles.ts`) all do `import config from "@payload-config"` → `getPayload({ config })`. The bot reuses this + the `@/` aliases and `src/payload-types.ts`. - **Notification types** (`src/lib/notifications/notificationTypes.ts`): `market:offer`, `market:counter`, `market:accept`, `market:reject`, `market:withdrawn`, `market:closed`, `market:sold`, `market:expired`, `account:discord-request`. `notifyUser()` (fire-and-forget in-app notifications) is the existing hook point the bot could bridge into. - **Missions collection** (`src/collections/intelligence/Missions.ts`): the operations model. Has `classification.startDateTime` (date+time picker, required, defaults to next Saturday 20:00) and `classification.estimatedDuration` (minutes, default 240). Also `operationType` (main/side/external), `ownershipAndStatus.status` (Concept/Planning/Ready/Scheduled/Active/Completed/Cancelled) + `visibility`, `missionRoles`, campaign link, briefing/objectives, server details. **No attendance and no recurrence fields exist.** - **Event log**: `emitGameEvent()` — the bot can log its own actions. - **Reusable libs** the bot can call directly: banking (`applyTransaction`, `ensurePersonalAccount`), market (`buyListing`, negotiations), notifications, storage rules. ## Locked decisions (2026-08-11) 1. **Sign-up includes `steamId`** — the player provides it as part of `/signup` (it is required on the Users collection). 2. **The operations model is the Missions collection** — no new operations collection. Any scheduling/attendance work builds on `missions`. 3. **Attendance is per-occurrence.** Each mission has one `startDateTime`, so an occurrence == a mission; attendance records are per (mission, user). 4. **App → Discord bridge: the bot polls `user-notifications`** with direct DB access and mirrors new notifications to Discord DMs for users who opted in. No webhook plumbing; existing `notifyUser()` call sites stay untouched. ## Gaps the bot work will need to fill - **No attendance model exists** (verified: zero matches for attendance/occurrence/recurring in `src/`). The website-side attendance model must be built as part of this feature. Lean: a new collection (e.g., `mission-attendances`: `mission` → missions, `user` → users, `response` yes/no/tentative), consistent with the app's LedgerEntries precedent. - **No Discord snowflake ID on users.** `discordUsername` is a username string ("Z8MB1E"), not a Discord user ID. DMs / role-gating / reliable linking need the snowflake (add a `discordId` field + `/link` command or guild-join mapping). - **No Discord notification preferences.** Current prefs mute *in-app* notifications only; Discord-notification toggles would extend the `preferences` group. ## Open design questions 1. Sign-up flow: what does the player type in Discord (username + password + display name + steam ID?), and how is the initial password handled? Lean: `/signup` in a DM; bot creates the user with a generated temp password, DMs it, player changes it on first login. 2. Recurrence type: same weekly slot? How far ahead are events posted? (Missions are one-shot docs — is a new mission created per operation night?) 3. Attendance model details: unique (mission, user) enforced in code; how web changes reach the bot (the chosen bridge is the `user-notifications` poll — attendance changes may need their own notification type so the bot reconciles the embed). 4. Announcements: which channels, who can trigger (Discord roles → app roles mapping), and how app → Discord pushes work.