Using it on Discord
How join roles and button panels behave for members.
When a new member joins, PaulCLI ignores bots, loads all JoinAutoRole rows for the guild, and attempts to add each role. It skips missing roles, roles the member already has, and roles at or above the bot's highest role. Failures are logged but not shown to the joining member.
Panel buttons use custom IDs in the form rr_toggle:<roleId>. Clicking a button creates an ephemeral response. If the member already has the role, the bot removes it and replies Removed. If they do not have it, the bot adds it and replies Added.
Button emoji can be Unicode or a custom emoji mention. For custom emoji, the publishing API converts <:name:id> or <a:name:id> into Discord's structured emoji payload; other emoji strings are sent as the button emoji name.
Editing live panels
Saving edits updates the existing Discord message first when channelId and messageId are present. Then the database deletes old buttons and creates the new button set in one transaction, keeping the dashboard copy aligned with the live panel.
