Add MineGeo gameplay systems and interface
This commit is contained in:
135
docs/discord-integration.md
Normal file
135
docs/discord-integration.md
Normal file
@@ -0,0 +1,135 @@
|
||||
# Discord announcements
|
||||
|
||||
MineGeo uses your Discord bot to send messages through Discord's REST API.
|
||||
It runs on Vercel and does not need a continuously running bot process, Gateway,
|
||||
Message Content intent, slash commands, an interactions URL, or a Discord webhook.
|
||||
The bot can appear offline while announcements work.
|
||||
|
||||
New maps are announced when a Moderator or Admin approves their first public
|
||||
version. Drafts, imported ZIP copies, player contributions, subsequent map updates,
|
||||
and re-publication do not create new-map announcements. Existing maps from before
|
||||
this integration are not backfilled.
|
||||
|
||||
In an open multiplayer lobby, the host can select **Publish party to Discord**.
|
||||
All published parties go to the single server-wide `DISCORD_PARTIES_CHANNEL_ID`.
|
||||
Players cannot choose a destination. Discord readers can open the invite and join
|
||||
without a MineGeo account while the lobby is open and has space. Messages show
|
||||
the map, host, difficulty, player count, and link. Publishing is optional: ordinary
|
||||
private invite links still work. Parties on private or imported maps cannot be
|
||||
announced publicly. A room gets one announcement, including repeated clicks or
|
||||
a transfer of lobby ownership. The counts are a snapshot when posted.
|
||||
|
||||
## Create and invite your bot
|
||||
|
||||
1. Open the [Discord Developer Portal](https://discord.com/developers/applications)
|
||||
and select **New Application**. Name it **MineGeo**, or your preferred bot name.
|
||||
2. Open **Bot**. Create the bot if prompted, then use **Reset Token** to obtain
|
||||
its bot token. Keep it private; save it directly into Vercel as described below.
|
||||
3. Under **Installation**, enable **Guild Install**. For the guild's install
|
||||
settings, choose the **bot** scope and these permissions: **View Channels**,
|
||||
**Send Messages**, **Embed Links**. You do not need Administrator permission.
|
||||
Use the installation link to add the bot to your Discord server. Alternatively,
|
||||
**OAuth2 → URL Generator** with the `bot` scope generates an invite link.
|
||||
4. Create or choose a text channel for map announcements and another for parties.
|
||||
You can use the same channel for both. Ensure the bot has the three permissions
|
||||
above in each channel, including any category or channel permission overrides.
|
||||
Ensure community members can view the party channel.
|
||||
5. In Discord's **User Settings → Advanced**, enable **Developer Mode**. Right-click
|
||||
each channel and choose **Copy Channel ID**. On mobile, long-press the channel
|
||||
or open its channel menu, then choose **Copy Channel ID**. Copy the numeric
|
||||
channel IDs; an invite link or server ID is not a channel ID.
|
||||
|
||||
Discord setup references: [application setup](https://docs.discord.com/developers/quick-start/getting-started),
|
||||
[bot permissions](https://docs.discord.com/developers/topics/permissions).
|
||||
|
||||
## Add the Vercel environment variables
|
||||
|
||||
Open [MineGeo's environment settings](https://vercel.com/pavel-melnikovs-projects-74f979c2/minegeo/settings/environment-variables).
|
||||
Add these for **Production**:
|
||||
|
||||
| Name | Value | Sensitive? |
|
||||
| --- | --- | --- |
|
||||
| `DISCORD_BOT_TOKEN` | Bot token from the Developer Portal, without `Bot ` in front | Yes |
|
||||
| `DISCORD_MAPS_CHANNEL_ID` | Numeric channel ID for new approved maps | No |
|
||||
| `DISCORD_PARTIES_CHANNEL_ID` | Numeric channel ID where **all published parties** appear | No |
|
||||
| `MINEGEO_URL` | `https://minegeo.vercel.app` (already configured) | No |
|
||||
|
||||
Use **Sensitive** for the token, and never prefix these names with `NEXT_PUBLIC_`.
|
||||
Leave a channel variable blank to disable that announcement type. A Discord
|
||||
invite such as `MINEGEO_DISCORD_URL` controls the footer button only; it cannot
|
||||
send announcements.
|
||||
|
||||
After saving, open **Deployments**, choose the newest Production deployment,
|
||||
select **Redeploy**, and use the current environment variables. Vercel applies
|
||||
environment changes to new deployments. See [Vercel's environment-variable guide](https://vercel.com/docs/environment-variables).
|
||||
|
||||
For local use, put the same variables in ignored `.env.local` (ordinary `.env`
|
||||
also works) and restart the server. Use a publicly reachable HTTPS `MINEGEO_URL`
|
||||
for links that Discord members can open. Do not paste bot tokens into chat,
|
||||
source control, Linear issues, or public map metadata.
|
||||
|
||||
## Check it
|
||||
|
||||
Sign in as **PerfectPython500**, open **Moderation → Discord integration**, and
|
||||
select **Check Discord setup**. This reads the bot and channels without sending
|
||||
a test message. It confirms the bot token, channel visibility, and channel type;
|
||||
the bot must also have **Send Messages** and **Embed Links**.
|
||||
|
||||
Approve a genuinely new map to test a map announcement. Create a multiplayer room
|
||||
on a published map, choose **Publish party to Discord**, and open the resulting
|
||||
link from Discord. The lobby shows queued, sent, expired, or failed delivery.
|
||||
|
||||
## Saved delivery and retries
|
||||
|
||||
Announcements are stored in a private Supabase queue. Delivery runs after map
|
||||
approval or party publication, leaving gameplay and approval independent of
|
||||
Discord availability. Active workers hold leases, repeated clicks share one event,
|
||||
and Discord receives a stable nonce with `enforce_nonce`. Rate limits and temporary
|
||||
errors retry with a delay, up to eight attempts. Invalid tokens and missing channel
|
||||
permissions require fixing the settings and selecting **Retry saved announcements**
|
||||
as an Admin. Delivery resumes while the host polls their lobby or an Admin opens
|
||||
the integration panel; other announcements also wake pending jobs.
|
||||
|
||||
Started, closed, full, removed, private, or stale parties are skipped. Pending
|
||||
party announcements expire one hour after sharing; lobbies themselves last up to
|
||||
24 hours. A map removed before delivery is skipped. Messages already posted are
|
||||
kept when the match starts; the linked lobby shows its live state. When a party
|
||||
closes (including its last player leaving), its posted announcement turns red,
|
||||
says **Party closed**, and removes the join prompt. Five minutes after Discord
|
||||
acknowledges that notice, the bot deletes the message. Vercel Workflow stores the
|
||||
timer and resumes deletion even if every player closes the page. Retries preserve
|
||||
the original deadline and tolerate messages already removed by a moderator.
|
||||
Previously posted announcements for closed or deleted rooms receive the same
|
||||
cleanup when the queue next runs. The original message's channel is used even
|
||||
if `DISCORD_PARTIES_CHANNEL_ID` has since changed. Cleanup failures appear in the
|
||||
Admin integration panel and can be retried after fixing bot access.
|
||||
Discord only deduplicates nonces for a few minutes. A long outage after an
|
||||
unconfirmed send can therefore result in a duplicate; inspect the channel before
|
||||
manually retrying uncertain deliveries.
|
||||
|
||||
For optional scheduled retries, configure a private `CRON_SECRET` and call
|
||||
`GET /api/integrations/discord/dispatch` with `Authorization: Bearer <CRON_SECRET>`.
|
||||
This endpoint claims at most five due announcements. A Vercel Cron entry can use
|
||||
that path; scheduling limits depend on your plan. No schedule is installed by
|
||||
default, and the secret must never be placed in a URL.
|
||||
|
||||
## Database and verification
|
||||
|
||||
Apply `20261009133431_discord_announcements.sql` and
|
||||
`20261009153708_discord_party_cleanup.sql` after existing migrations.
|
||||
The queue and functions are service-role-only, use RLS and invoker permissions,
|
||||
and verify the host from the room's server-verified access hash. No Discord
|
||||
credentials are stored in Supabase or sent to a browser.
|
||||
|
||||
Vercel Workflow uses the project's managed backend automatically. Keep **Settings
|
||||
→ Environment Variables → Enable access to System Environment Variables** enabled
|
||||
and redeploy after changing it. No additional secret or scheduled cron is needed
|
||||
for the five-minute timer. The bot edits and deletes its own announcements, so
|
||||
**Manage Messages** is not required.
|
||||
|
||||
Run `npm test`, `npm run typecheck -- --incremental false`, `npm run build`, and
|
||||
`node scripts/test-discord-sql.mjs`. `node scripts/test-discord-http.mjs` verifies
|
||||
the live role gates, destination restrictions, optional configuration, and
|
||||
host-only room action with temporary accounts and a room, which it removes.
|
||||
Discord transport tests use a mocked API; real delivery requires your bot token
|
||||
and channel permissions.
|
||||
Reference in New Issue
Block a user