Skip to content

feat(discord): set up the Discord server with /openmu setup (M3) - #1157

Open
sven-n wants to merge 4 commits into
claude/sweet-cray-w8crms-m2from
claude/sweet-cray-w8crms-m3
Open

sven-n wants to merge 4 commits into
claude/sweet-cray-w8crms-m2from
claude/sweet-cray-w8crms-m3

Conversation

@sven-n

@sven-n sven-n commented Oct 8, 2026

Copy link
Copy Markdown
Member

Milestone M3 of the Discord integration (#1101). Stacked on #1156 (M2), so review/merge that first.

What

  • Layout file (src/Discord/Provisioning/DefaultLayout.json, embedded): roles GM and Linked Player; categories Info (#announcements, #events, #server-status), Community (#world-news, #world-chat, #general) and Staff (#staff-alerts, #gm-commands, only visible to GM). Each item has a stable key. Channels can be read-only, announcement channels, receive notification categories or show the status. A custom layout can be configured with Discord__Bot__LayoutFile; it's validated on load (unique keys, known roles).
  • /openmu setup: a slash command with Administrator as its default member permission, usable in guilds only. The handler re-checks that the user is an admin. Behaviour:
    • Idempotent: existing roles, categories and channels are adopted by name (case-insensitive); only the missing ones are created.
    • Permissions: the permissions the layout defines are merged into the existing overwrites for @everyone, the roles and the bot; other overwrites stay as they are.
    • Nothing destructive: nothing is deleted or renamed.
    • Report: an ephemeral reply (en/de) lists what was created, what was adopted and what failed, plus a hint about the needed permissions.
  • Key-based routing: the bot finds the layout's channels by name in the configured guild (or in the only guild it's in), refreshed every status tick and right after setup. Notifications and the status message go there. Explicitly configured Bot__Channels__* / Bot__StatusChannelId take precedence. Until the bot is connected, categories without an explicit channel fall back to their webhook.
  • Storage decision: no DB entity or migration. The key→id mapping is resolved by name at runtime, just as the status message is found again after a restart. Renamed channels can be pinned by configuring their id.
  • Testability: provisioning runs against a small IDiscordServer abstraction; SocketGuildServer adapts Discord.Net's guild to it.
  • Docs: setup section, layout format, server template workflow (M3.4), extra bot permissions (Manage Channels, Manage Roles) and new settings.

Tests

New: provisioning of an empty server, idempotency, adoption by name across categories, failure reporting with continuation, permission overwrites, finding channels, layout validation, routing precedence, setup report, and webhook fallback in the notifier. Full suite: 1690 passed.

Not tested against a real Discord server/bot token.

🤖 Generated with Claude Code

https://claude.ai/code/session_01USFZ9xErMB1EwkpfdUHzoZ


Generated by Claude Code

claude added 2 commits October 8, 2026 21:26
A layout file defines the roles, categories and channels of the Discord
server of a game server. Administrators run /openmu setup to create what's
missing; existing items are adopted by name, so it can run repeatedly.
The bot posts notifications and the status into the channels of the layout,
found by name, unless channel ids are configured.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01USFZ9xErMB1EwkpfdUHzoZ
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01USFZ9xErMB1EwkpfdUHzoZ
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Oct 8, 2026 •

Copy link
Copy Markdown

Deploying openmudocs with  Cloudflare Pages  Cloudflare Pages

Latest commit: 1979383
Status: ✅  Deploy successful!
Preview URL: https://3aecb009.openmudocs.pages.dev
Branch Preview URL: https://claude-sweet-cray-w8crms-m3.openmudocs.pages.dev

View logs

@sven-n sven-n left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Part of a review pass over the whole Discord stack.

The idempotency story here is the part I was most sceptical of going in, and it holds up: adopt by name, create only what's missing, never delete or rename, and the IDiscordServer seam with FakeDiscordServer means the provisioner is actually testable without a live server. /openmu setup is gated twice — WithDefaultMemberPermissions(Administrator) on the command plus an explicit GuildPermissions.Administrator check at execution, because the default can be overridden in the Discord server's settings. That's the right instinct and the comment says so.

Three comments inline. The permission-overwrite one is the only one with a user-visible failure mode.


Generated by Claude Code

Comment thread src/Discord/Provisioning/DiscordServerProvisioner.cs
Comment thread src/Discord/Provisioning/DiscordServerLayout.cs Outdated
Comment thread src/Discord/DiscordBot.cs
…failed commands

A private category whose roles couldn't be created stays visible to
everyone, and the setup report says so, instead of being visible to
nobody but the bot. The names in a layout have to be unique, because the
items are adopted by their name. A command which fails after it was
deferred gets an answer, instead of leaving the user waiting.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01USFZ9xErMB1EwkpfdUHzoZ

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants