@discord
@discord
Section titled “@discord”@discord[/<switch>] [<argument>[=<value>]]
The Discord plugin links channels on a Discord server to the game, through a bot the game runs itself. Each linked channel is a feed, discord/<channel id>: every line sent on that feed is posted in the channel under the speaker’s name, and a linked member’s message in the channel comes back as a line on the feed, spoken by the character they chose.
@discord alone shows the bot’s connection and the linked channels. Everything but @discord/speak needs the discord.admin permission. Nobody holds it until it is given, wizards included: @role/assign <player>=discord-admin gives the discord package’s Discord Admin role, which allows it.
Discord ids are numbers. To copy one, turn on Developer Mode in Discord’s User Settings, under Advanced, then right-click a channel, role or server and choose Copy ID.
- @discord setup: the bot’s token and connection
- @discord channels: linking, unlinking and resuming channels
- @discord restrict: who may post in a linked channel
- @discord members: linking Discord accounts to game accounts
- @discord speak: choosing who speaks for you in a channel
- @discord roles: Discord roles that follow game roles
- @discord bans: banning on Discord when banned in the game
- @discord events: the game’s events in Discord’s Events tab
- @discord event fields: what an event’s JSON holds
The portal’s Discord page, under Build & manage, does the same as these commands.
Setting up the bot
Section titled “Setting up the bot”Illustrated setup guide (screens, permissions and channel checks): https://github.com/SharpMUSH/SharpMUSH/blob/main/docs/guides/discord-setup.md.
@discord@discord/connect
Each game makes its own Discord application in Discord’s developer portal. On its Bot page, copy the token, untick Public Bot, and turn on Server Members Intent and Message Content Intent. Then store the token and connect:
> @secret discord.token=<the token>> @discord/connect@discord says where the connection stands and what to do next when something is wrong. @discord/connect logs the bot in again with the token stored now; run it after changing the token or the intents.
Once Discord accepts the token, @discord ends with a line starting Add the bot to a server: and a link. Open it, pick the server and keep every permission it asks for.
Linked channels
Section titled “Linked channels”@discord/link <channel id>@discord/unlink <channel id>@discord/resume <channel id>
Install the discord package from the portal’s Packages page first; it adds the discord feed kind. @discord/link then makes a webhook in the channel, which the bot posts through, and lets only members holding the Linked role send messages there. These commands, and those in @discord restrict, return the channel id at once and say how it went when Discord answers.
> @discord/link 1234567890123456789Output: Linked #ooc in My Game. Lines sent on the feed discord/1234567890123456789 are posted there. Only linked members may post there.
/unlinkstops posting, deletes the webhook, and puts back who may post in the channel as it was before. The feed and its lines stay in the game. If Discord refuses that permission change, the link stays listed with the error: give the bot the permission it needs and unlink again./resumeposts again after a link stopped.@discordshows why a link stopped in its State column: a webhook deleted twice within ten minutes, a permission the bot lost, or five posts refused within a minute.
Anything that sends a line on the feed posts it in Discord, such as @feed/send discord/1234567890123456789=Server restart in ten minutes. A line sent with @feed/send/to is not posted, and neither is one still waiting after a minute. See @feed.
Restricted channels
Section titled “Restricted channels”-
@discord/gate <channel id> -
@discord/restrict <channel id> -
@discord/unrestricted <channel id> -
/gateor/restrictmakes the channel need a linked game account again./gatealso retries a permission change that failed while linking. -
/unrestrictedlets Discord members without a game account speak too, under their Discord name. Use it for a help channel for newcomers. The portal’s Discord page does the same, channel by channel, and shows which channels are unrestricted.
To restrict a channel, the bot notes the channel’s Send Messages and Send Messages in Threads settings for @everyone and the Linked role, then denies both to @everyone and allows both to Linked. Unlinking or unrestricting puts the noted settings back, but only where a setting still holds what the bot wrote: one someone has changed since is left alone, and so is every other permission. A channel linked before the bot noted settings has nothing to put back, so the bot clears its own values and those settings fall back to the category’s or the server’s.
An unrestricted channel still follows the Discord server’s own permissions. In the game, a member without a game account speaks under their Discord name behind [D], such as [D] Mercutio, and in Discord their message is replaced by the game’s line under that name. feedmsg(<id>,external_id) gives their Discord id. A send lock on the feed, or on its kind, refuses those guests, since there is no game object to test it against; clear the lock only where anyone on Discord should be able to speak. A member whose game account is disabled or banned cannot speak there either.
Linking members
Section titled “Linking members”A member links their Discord account to their game account once. In the game’s Discord server they type /link, and the bot answers, to them alone, with a link to open while signed in to the game’s website. It works once, for ten minutes, and needs mud_url to be set. /unlink in Discord, or Unlink on the portal’s account page, drops the link.
- A game account links to one Discord account, and a Discord account to one game account.
- Only an active account can link.
- A Discord account unlinked from one game account waits a week before it can link a different one.
- While a game account’s ban stands, the Discord account that was linked to it cannot link another.
The bot gives every member linked to an active account a role named Linked, and takes it from everyone else. Only that role may post in restricted linked channels. Unrestricted channels do not require that role.
Speaking from Discord
Section titled “Speaking from Discord”@discord/speak <channel id>@discord/speak/off <channel id>- In Discord:
/speakas <character>in the channel you want to speak in.
Anyone may run these, as the character they want to speak as. In Discord, /speakas names a character you own, and the bot answers you alone. Either way, your Discord account must be linked to the character’s game account, which must be active, and the choice is for that channel only. From then on, each message you post in that channel comes into the game as a line on its feed, spoken by that character, which must pass the feed’s send lock each time. One character speaks per channel; choosing another replaces it. /off stops it.
This is not private: anyone who reads both the game and the channel can tell which Discord member plays the character.
In a restricted channel, a member with no character chosen gets a direct message saying how to choose one, and their messages do not reach the game. In an unrestricted channel, a member without a chosen character speaks under their Discord identity instead; choosing an owned character with /speakas or @discord/speak uses that character. Nothing that arrives from Discord is ever evaluated.
@discord/map@discord/map[/confirm] <game role>=<Discord role>@discord/unmap <Discord role>@discord/map/enforce <Discord role>and@discord/map/report <Discord role>@discord/drift@discord/drift/apply [<Discord role>]
@discord/map builder=@Builders gives the Discord role Builders to every linked member whose account, or one of its characters, holds the game role builder, and takes it from those who don’t. A Discord role is named with or without its @, or by its id. @discord/map alone lists the mappings and whether the bot can manage each one. @discord/unmap stops mapping a role; members keep it as it is.
A role you may map is below your own highest role and does not allow administrator. everyone, player and god cannot be mapped. wizard and royalty need /confirm, because the Discord role shows everyone who holds them. See @role.
The bot needs Manage Roles, and its own role must be above each mapped role in the server’s role list.
A mapped role given or taken by hand on Discord is listed by @discord/drift. @discord/drift/apply puts back the game’s answer for every role, or for one. /enforce makes the bot put such a change back at once, and /report goes back to only listing it.
Game bans
Section titled “Game bans”@discord/bans@discord/bans onand@discord/bans off
A game ban always takes the Linked role and every mapped role. With @discord/bans on, it also bans the account’s Discord member in every server the bot is in, and turning it on bans the members of accounts banned already. When the game ban ends, the bot lifts the Discord bans it made; a Discord ban staff made themselves is left alone. /bans off stops new bans. @discord/bans says whether bans are mirrored and lists the members the bot banned. The bot needs Ban Members.
Scheduled events
Section titled “Scheduled events”@discord/event@discord/event <key>=<json>@discord/event/start <key>@discord/event/end <key>
@discord/event publishes a game event to the server’s Events tab, under a key the game chooses, such as a scene’s id. The value is a JSON object; build it with json(), since typed braces would be taken as grouping. @discord event fields lists what it holds.
> @discord/event 12=[json(object,name,json(string,Harbour Night),start,add(secs(),86400),location,json(string,https://game.example/scenes/12))]Publishing the same key again updates the event while it is still to come. Once it has started or ended, publishing ends it and makes a new one: a paused scene moved to another day is a new event. /start shows the event as happening now. /end ends an event that started and cancels one that has not. @discord/event alone lists what is published. Each command returns the key at once and says how it went when Discord answers.
Event fields
Section titled “Event fields”The JSON object given to @discord/event <key>=<json> holds:
name: up to 100 characters (required)start: seconds since 1970 UTC, as secs() gives it, still to come (required)end: seconds since 1970 UTC, after the start; three hours after the start if left outlocation: up to 100 characters (required)description: up to 1000 charactersserver: the server’s id, needed only when the bot is in more than one. A key’s event stays in its server:/endit there before publishing the key in another
::: seealso