Right-click menus and the message box
With ui, a plugin can add items to Fluxer’s right-click menus for messages, people and channels. With messages, it can type text into the message box after the user acts. Neither sends anything.
Add a menu item
Section titled “Add a menu item”cleanup.push( await api.ui.registerContextMenuItem( { id: "copy-id", label: "Copy ID", targets: ["message", "user", "channel"], }, async (target) => { const id = target.kind === "message" ? target.messageId : target.kind === "user" ? target.userId : target.channelId; await api.ui.notify("ID: " + id); }, ),);targets says which menus the item appears in. The item shows at the end of the menu with a tooltip naming your plugin. Group items under submenu: { id, label } the same way as attachment actions. A plugin may add up to 16 items.
Set only: “self” to show the item only on the user’s own messages and on their own name, or only: “others” for everyone else’s. Channels have no owner, so an item with only can’t target them. Fluxer’s user area at the bottom left has no right-click menu; users reach their own menu from their name on a message or in the member list.
The handler gets what was right-clicked, only when the user picks your item:
| kind | Fields |
|---|---|
| message | messageId, channelId, guildId, authorId, flags, and text with message_content |
| user | userId, guildId, channelId, self, bot |
| channel | channelId, guildId |
flags holds bot, webhook, self, reply, system, edited, pinned, mentioned and pending, which is true while Fluxer hasn’t confirmed the message: it is still sending, or failed. Names are never included. A right-click on a person’s name inside a message counts as a person, not the message. Links and text fields keep Fluxer’s own menus.
If the page changed before the user picked the item, for example the message was deleted or the user navigated away, the handler isn’t called.
Type into the message box
Section titled “Type into the message box”cleanup.push( await api.ui.registerContextMenuItem( { id: "quote", label: "Quote", targets: ["message"] }, async (target) => { if (target.kind !== "message" || !target.text) return; const quoted = target.text .split("\n") .map((line) => "> " + line) .join("\n"); await api.messages.insertText(quoted + "\n"); }, ),);messages.insertText(text) types up to 4000 characters at the cursor in the message box, as if the user typed or pasted them. Line breaks become soft breaks, so nothing is sent. It needs a user action in your plugin’s UI within the last 1.5 seconds: picking a menu item, a decoration button, a dialog submit or a shortcut. The action is used up.
This example also needs message_content to read the message’s text.
| Error | Meaning |
|---|---|
| user_gesture_required | No recent user action, or it was already used |
| composer_unavailable | No message box is open, or it can’t take text right now |
| composer_insert_failed | The message box didn’t accept the text |
| context_menu_unavailable | The runtime can’t add menu items on this page; skip the feature |
