1
0
Fork 0
polaris-task-force/docs/bot/context.md

5.9 KiB

Discord Bot — Product Context

Status: implemented and shipping. The bot runs inside the production Docker image and activates per-environment when DISCORD_TOKEN is set (prod only) — see ../../DEPLOYMENT.md §5. 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.