All checks were successful
Deploy MineGeo to Dokploy / deploy (push) Successful in 5m57s
140 lines
8.3 KiB
Markdown
140 lines
8.3 KiB
Markdown
# 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**.
|
|
Hosting requires a signed-in account and always uses its stored Display Name.
|
|
Signed-in players join with account names; guests can join with nicknames.
|
|
If the host leaves, another signed-in player takes over; the party closes if
|
|
only guests remain.
|
|
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.site` (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.
|