This commit is contained in:
2025-04-08 11:55:56 -04:00
parent e003afab6d
commit 14e5187535
+63 -48
View File
@@ -3,7 +3,6 @@ package commands
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"log"
"os" "os"
"strings" "strings"
@@ -55,21 +54,43 @@ func manageRolesPerm() *int64 {
// Only members with the "Manage Roles" permission may use this command. // Only members with the "Manage Roles" permission may use this command.
var ReactionRoleCommand = &discordgo.ApplicationCommand{ var ReactionRoleCommand = &discordgo.ApplicationCommand{
Name: "reactionrole", Name: "reactionrole",
Description: "Setup a reaction role message using buttons. Provide a number (max 10) for role-button pairs", Description: "Setup a reaction role message using buttons. Provide up to 5 roles.",
DefaultMemberPermissions: manageRolesPerm(), DefaultMemberPermissions: manageRolesPerm(),
Options: []*discordgo.ApplicationCommandOption{ Options: []*discordgo.ApplicationCommandOption{
{ {
Type: discordgo.ApplicationCommandOptionInteger, Type: discordgo.ApplicationCommandOptionRole, // type 8
Name: "count", Name: "role1",
Description: "Number of role-button pairs to setup (max 10)", Description: "The first role",
Required: true, Required: true,
MinValue: func(v float64) *float64 { return &v }(1), },
MaxValue: func(v float64) float64 { return v }(10), {
Type: discordgo.ApplicationCommandOptionRole,
Name: "role2",
Description: "The second role",
Required: false,
},
{
Type: discordgo.ApplicationCommandOptionRole,
Name: "role3",
Description: "The third role",
Required: false,
},
{
Type: discordgo.ApplicationCommandOptionRole,
Name: "role4",
Description: "The fourth role",
Required: false,
},
{
Type: discordgo.ApplicationCommandOptionRole,
Name: "role5",
Description: "The fifth role",
Required: false,
}, },
{ {
Type: discordgo.ApplicationCommandOptionString, Type: discordgo.ApplicationCommandOptionString,
Name: "style", Name: "style",
Description: "Button style", Description: "Button style (primary, secondary, success, danger)",
Required: false, Required: false,
Choices: []*discordgo.ApplicationCommandOptionChoice{ Choices: []*discordgo.ApplicationCommandOptionChoice{
{ {
@@ -144,7 +165,7 @@ func memberHasManageRoles(s *discordgo.Session, guildID string, member *discordg
} }
func HandleReactionRole(s *discordgo.Session, i *discordgo.InteractionCreate) { func HandleReactionRole(s *discordgo.Session, i *discordgo.InteractionCreate) {
// Ensure the command is used in a guild and member data is present. // Standard guild and permission checks.
if i.GuildID == "" || i.Member == nil { if i.GuildID == "" || i.Member == nil {
helpers.HandleError(s, i, fmt.Errorf("command must be used in a guild")) helpers.HandleError(s, i, fmt.Errorf("command must be used in a guild"))
return return
@@ -154,7 +175,6 @@ func HandleReactionRole(s *discordgo.Session, i *discordgo.InteractionCreate) {
helpers.HandleError(s, i, fmt.Errorf("failed to check user permissions: %w", err)) helpers.HandleError(s, i, fmt.Errorf("failed to check user permissions: %w", err))
return return
} }
if !hasPerm { if !hasPerm {
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
Type: discordgo.InteractionResponseChannelMessageWithSource, Type: discordgo.InteractionResponseChannelMessageWithSource,
@@ -168,15 +188,20 @@ func HandleReactionRole(s *discordgo.Session, i *discordgo.InteractionCreate) {
options := i.ApplicationCommandData().Options options := i.ApplicationCommandData().Options
// Extract count (required - type Integer) // Collect role IDs from the role options.
countOpt := helpers.GetOption(options, "count") var roles []*discordgo.Role
if countOpt == nil { for _, optName := range []string{"role1", "role2", "role3", "role4", "role5"} {
helpers.HandleError(s, i, fmt.Errorf("missing count option")) if opt := helpers.GetOption(options, optName); opt != nil {
roles = append(roles, opt.RoleValue(s, i.GuildID))
}
}
if len(roles) == 0 {
helpers.HandleError(s, i, fmt.Errorf("at least one role must be provided"))
return return
} }
count := int(countOpt.IntValue())
// Determine style based on the "style" option; default to "primary" // Determine style; default to primary.
style := "primary" style := "primary"
if opt := helpers.GetOption(options, "style"); opt != nil { if opt := helpers.GetOption(options, "style"); opt != nil {
if val := opt.StringValue(); val != "" { if val := opt.StringValue(); val != "" {
@@ -184,7 +209,7 @@ func HandleReactionRole(s *discordgo.Session, i *discordgo.InteractionCreate) {
} }
} }
// Extract target message ID from the "message_id" option if available. // Extract target message ID, if provided.
targetMsgID := "" targetMsgID := ""
if opt := helpers.GetOption(options, "message_id"); opt != nil { if opt := helpers.GetOption(options, "message_id"); opt != nil {
if val := opt.StringValue(); val != "" { if val := opt.StringValue(); val != "" {
@@ -194,28 +219,17 @@ func HandleReactionRole(s *discordgo.Session, i *discordgo.InteractionCreate) {
} }
} }
// Build modal components: for each pair, add two text inputs (each in its own action row). // Build the modal components: one text input per role for its button label.
modalComponents := []discordgo.MessageComponent{} modalComponents := []discordgo.MessageComponent{}
for idx := 1; idx <= count; idx++ { for _, role := range roles {
// Input for Role ID.
roleInput := discordgo.TextInput{
CustomID: fmt.Sprintf("role_id_%d", idx),
Label: fmt.Sprintf("Role ID for pair %d", idx),
Style: discordgo.TextInputShort,
Placeholder: "Enter Role ID",
Required: true,
}
// Input for Button Label.
labelInput := discordgo.TextInput{ labelInput := discordgo.TextInput{
CustomID: fmt.Sprintf("role_label_%d", idx), CustomID: fmt.Sprintf("label_%s", role.ID),
Label: fmt.Sprintf("Button label for pair %d", idx), Label: fmt.Sprintf("Button label for role %s", role.Name),
Style: discordgo.TextInputShort, Style: discordgo.TextInputShort,
Placeholder: "Button Text", Placeholder: "Enter Button Label",
Required: true, Required: true,
} }
modalComponents = append(modalComponents, discordgo.ActionsRow{
Components: []discordgo.MessageComponent{&roleInput},
})
modalComponents = append(modalComponents, discordgo.ActionsRow{ modalComponents = append(modalComponents, discordgo.ActionsRow{
Components: []discordgo.MessageComponent{&labelInput}, Components: []discordgo.MessageComponent{&labelInput},
}) })
@@ -295,27 +309,28 @@ func HandleReactionRoleModalSubmit(s *discordgo.Session, i *discordgo.Interactio
} }
} }
// For each pair, extract the Role ID and label. // FLAT
for idx := 1; idx <= count; idx++ { var rolearr [][]string
var roleID, label string
for idx := range count {
for _, comp := range data.Components { for _, comp := range data.Components {
row, ok := comp.(*discordgo.ActionsRow) row, ok := comp.(*discordgo.ActionsRow)
if !ok { if !ok {
continue continue
} }
for _, innerComp := range row.Components {
textInput, ok := innerComp.(*discordgo.TextInput) inp := row.Components[idx].(*discordgo.TextInput)
if !ok { rolearr = append(rolearr, []string{inp.Value, strings.Split(inp.CustomID, "_")[1]})
continue
}
if textInput.CustomID == fmt.Sprintf("role_id_%d", idx) {
roleID = textInput.Value
} else if textInput.CustomID == fmt.Sprintf("role_label_%d", idx) {
label = textInput.Value
}
} }
} }
for idx := range len(rolearr) {
var roleID, label string
label = rolearr[idx][0]
roleID = rolearr[idx][1]
// Allow a cancellation action. // Allow a cancellation action.
if strings.ToLower(roleID) == "cancel" { if strings.ToLower(roleID) == "cancel" {
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
@@ -391,7 +406,7 @@ func HandleReactionRoleModalSubmit(s *discordgo.Session, i *discordgo.Interactio
ID: targetMsgID, ID: targetMsgID,
Content: &originalMsg.Content, // Preserve original content. Content: &originalMsg.Content, // Preserve original content.
Components: &components, Components: &components,
}); })
if err != nil { if err != nil {
helpers.HandleError(s, i, fmt.Errorf("failed to edit target message: %w", err)) helpers.HandleError(s, i, fmt.Errorf("failed to edit target message: %w", err))