diff --git a/backend/src/plugins/ReactionRoles/ReactionRolesPlugin.ts b/backend/src/plugins/ReactionRoles/ReactionRolesPlugin.ts index 90946d92..523ab7bd 100644 --- a/backend/src/plugins/ReactionRoles/ReactionRolesPlugin.ts +++ b/backend/src/plugins/ReactionRoles/ReactionRolesPlugin.ts @@ -36,6 +36,7 @@ export const ReactionRolesPlugin = zeppelinGuildPlugin( showInDocs: true, info: { prettyName: "Reaction roles", + legacy: "Consider using the [Role buttons](/docs/plugins/role_buttons) plugin instead.", }, dependencies: () => [LogsPlugin], diff --git a/backend/src/plugins/RoleButtons/RoleButtonsPlugin.ts b/backend/src/plugins/RoleButtons/RoleButtonsPlugin.ts index 35359f52..60f5a221 100644 --- a/backend/src/plugins/RoleButtons/RoleButtonsPlugin.ts +++ b/backend/src/plugins/RoleButtons/RoleButtonsPlugin.ts @@ -7,10 +7,13 @@ import { GuildRoleButtons } from "../../data/GuildRoleButtons"; import { RoleManagerPlugin } from "../RoleManager/RoleManagerPlugin"; import { StrictValidationError } from "../../validatorUtils"; import { onButtonInteraction } from "./events/buttonInteraction"; +import { pluginInfo } from "./info"; export const RoleButtonsPlugin = zeppelinGuildPlugin()({ name: "role_buttons", configSchema: ConfigSchema, + info: pluginInfo, + showInDocs: true, configPreprocessor(options) { // Auto-fill "name" property for buttons based on the object key diff --git a/backend/src/plugins/RoleButtons/events/buttonInteraction.ts b/backend/src/plugins/RoleButtons/events/buttonInteraction.ts index 0b0c4a65..9384d5a2 100644 --- a/backend/src/plugins/RoleButtons/events/buttonInteraction.ts +++ b/backend/src/plugins/RoleButtons/events/buttonInteraction.ts @@ -1,6 +1,8 @@ import { typedGuildEventListener } from "knub"; import { RoleButtonsPluginType, TRoleButtonOption } from "../types"; import { RoleManagerPlugin } from "../../RoleManager/RoleManagerPlugin"; +import { GuildMember } from "discord.js"; +import { getAllRolesInButtons } from "../functions/getAllRolesInButtons"; export const onButtonInteraction = typedGuildEventListener()({ event: "interactionCreate", @@ -12,8 +14,9 @@ export const onButtonInteraction = typedGuildEventListener(); + for (const option of buttons.options) { + roles.add(option.role_id); + } + return Array.from(roles); +} diff --git a/backend/src/plugins/RoleButtons/info.ts b/backend/src/plugins/RoleButtons/info.ts new file mode 100644 index 00000000..7b0976a5 --- /dev/null +++ b/backend/src/plugins/RoleButtons/info.ts @@ -0,0 +1,80 @@ +import { trimPluginDescription } from "../../utils"; +import { ZeppelinGuildPluginBlueprint } from "../ZeppelinPluginBlueprint"; + +export const pluginInfo: ZeppelinGuildPluginBlueprint["info"] = { + prettyName: "Role buttons", + description: trimPluginDescription(` + Allow users to pick roles by clicking on buttons + `), + configurationGuide: trimPluginDescription(` + Button roles are entirely config-based; this is in contrast to the old reaction roles. They can either be added to an existing message posted by Zeppelin or posted as a new message. + + ## Basic role buttons + ~~~yml + role_buttons: + config: + buttons: + my_roles: # You can use any name you want here, but make sure not to change it afterwards + messages: + channel_id: "967407495544983552" + content: "Click the reactions below to get roles! Click again to remove the role." + options: + - role_id: "878339100015489044" + label: "Role 1" + - role_id: "967410091571703808" + emoji: "😁" # Default emoji as a unicode emoji + label: "Role 2" + - role_id: "967410091571703234" + emoji: "967412591683047445" # Custom emoji ID + - role_id: "967410091571703567" + label: "Role 4" + style: DANGER # Button style (in all caps), see https://discord.com/developers/docs/interactions/message-components#button-object-button-styles + ~~~ + + ### Or with an embed: + ~~~yml + role_buttons: + config: + buttons: + my_roles: + messages: + channel_id: "967407495544983552" + content: + embeds: + - title: "Pick your role below!" + color: 0x0088FF + description: "You can pick any role you want by clicking the buttons below." + options: + ... # See above for examples for options + ~~~ + + ## Role buttons for an existing message + This message must be posted by Zeppelin. + ~~~yml + role_buttons: + config: + buttons: + my_roles: + messages: + channel_id: "967407495544983552" + message_id: "967407554412040193" + options: + ... # See above for examples for options + ~~~ + + ## Limiting to one role ("exclusive" roles) + When the \`exclusive\` option is enabled, only one role can be selected at a time. + ~~~yml + role_buttons: + config: + buttons: + my_roles: + messages: + channel_id: "967407495544983552" + message_id: "967407554412040193" + exclusive: true # With this option set, only one role can be selected at a time + options: + ... # See above for examples for options + ~~~ + `), +}; diff --git a/backend/src/plugins/RoleButtons/types.ts b/backend/src/plugins/RoleButtons/types.ts index b02db577..0dbbcd07 100644 --- a/backend/src/plugins/RoleButtons/types.ts +++ b/backend/src/plugins/RoleButtons/types.ts @@ -32,6 +32,7 @@ const RoleButtonsConfigItem = t.type({ }), ]), options: t.array(RoleButtonOption), + exclusive: tNullable(t.boolean), }); export type TRoleButtonsConfigItem = t.TypeOf; diff --git a/backend/src/plugins/ZeppelinPluginBlueprint.ts b/backend/src/plugins/ZeppelinPluginBlueprint.ts index 0bc7dbce..bb8cc70d 100644 --- a/backend/src/plugins/ZeppelinPluginBlueprint.ts +++ b/backend/src/plugins/ZeppelinPluginBlueprint.ts @@ -27,7 +27,7 @@ export interface ZeppelinGuildPluginBlueprint +
+
+
+ +
+
+ Note! This is a legacy plugin which is no longer actively maintained and may be removed in a future update. +
+ +
+
+
+
+ Usage @@ -172,12 +186,13 @@ import Tab from "../Tab.vue"; import Expandable from "../Expandable.vue"; import { DocsState } from "../../store/types"; + import Alert from 'vue-material-design-icons/Alert.vue'; const validTabs = ['usage', 'configuration']; const defaultTab = 'usage'; export default { - components: { CodeBlock, MarkdownBlock, Tabs, Tab, Expandable }, + components: { CodeBlock, MarkdownBlock, Tabs, Tab, Expandable, Alert }, async mounted() { this.loading = true;