diff --git a/attachments/example_modal.json b/attachments/example_modal.json new file mode 100644 index 0000000..6323164 --- /dev/null +++ b/attachments/example_modal.json @@ -0,0 +1,20 @@ +[ + { + "label": "This is a simple textline", + "is_paragraph": false, + "placeholder": "...and it is required!", + "value": "", + "required": true, + "min_length": 0, + "max_length": 20 + }, + { + "label": "This is a paragraph", + "is_paragraph": true, + "placeholder": "...and it is not required!", + "value": "We already have some input here", + "required": false, + "min_length": 0, + "max_length": 2000 + } +] diff --git a/cmd_form.go b/cmd_form.go new file mode 100644 index 0000000..3dc8202 --- /dev/null +++ b/cmd_form.go @@ -0,0 +1,142 @@ +package main + +import ( + "bytes" + "os" + + "github.com/bwmarrin/discordgo" +) + +var fileData []byte + +var form_command Command = Command{ + Definition: discordgo.ApplicationCommand{ + Name: "form", + Description: "Create custom forms right inside Discord", + Options: []*discordgo.ApplicationCommandOption{ + { + Type: discordgo.ApplicationCommandOptionSubCommand, + Name: "help", + Description: "Gives you a example file and demo for creating custom forms", + }, + { + Type: discordgo.ApplicationCommandOptionSubCommand, + Name: "create", + Description: "Create a new custom form right inside Discord", + Options: []*discordgo.ApplicationCommandOption{ + { + Type: discordgo.ApplicationCommandOptionString, + Name: "title", + Description: "The title inside the form window", + Required: true, + }, + { + Type: discordgo.ApplicationCommandOptionAttachment, + Name: "json", + Description: "Your edited form file", + Required: true, + }, + { + Type: discordgo.ApplicationCommandOptionChannel, + Name: "results_channel", + Description: "The channel where the form results should be posted", + Required: true, + }, + }, + }, + }, + }, + Interact: func(s *discordgo.Session, i *discordgo.InteractionCreate) { + switch i.ApplicationCommandData().Options[0].Name { + case "help": + fileData, _ = os.ReadFile("./attachments/example_modal.json") + fileReader := bytes.NewReader(fileData) + s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ + Type: discordgo.InteractionResponseChannelMessageWithSource, + Data: &discordgo.InteractionResponseData{ + Content: "Get the example file edit it and submit it via `/form create`.\nOr use the demo button to get an idea of how the example would look like.", + Flags: discordgo.MessageFlagsEphemeral, + Files: []*discordgo.File{ + { + Name: "example.json", + ContentType: "json", + Reader: fileReader, + }, + }, + Components: []discordgo.MessageComponent{ + discordgo.ActionsRow{ + Components: []discordgo.MessageComponent{ + discordgo.Button{ + Emoji: discordgo.ComponentEmoji{ + Name: "📑", + }, + CustomID: "form_demo", + Label: "Demo", + Style: discordgo.PrimaryButton, + }, + }, + }, + }, + }, + }) + case "create": + s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ + Type: discordgo.InteractionResponseChannelMessageWithSource, + Data: &discordgo.InteractionResponseData{ + Content: "Placeholder", + Flags: discordgo.MessageFlagsEphemeral, + }, + }) + } + }, + ComponentIDs: []string{"form_demo"}, + ComponentInteract: func(s *discordgo.Session, i *discordgo.InteractionCreate) { + s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ + Type: discordgo.InteractionResponseModal, + Data: &discordgo.InteractionResponseData{ + CustomID: "form_demo_modal" + i.Interaction.Member.User.ID, + Title: "Demo form", + Components: []discordgo.MessageComponent{ + discordgo.ActionsRow{ + Components: []discordgo.MessageComponent{ + discordgo.TextInput{ + CustomID: "demo_short", + Label: "This is a simple textline", + Style: discordgo.TextInputShort, + Placeholder: "...and it is required!", + Value: "", + Required: true, + MaxLength: 20, + MinLength: 0, + }, + }, + }, + discordgo.ActionsRow{ + Components: []discordgo.MessageComponent{ + discordgo.TextInput{ + CustomID: "demo_paragraph", + Label: "This is a paragraph", + Style: discordgo.TextInputParagraph, + Placeholder: "...and it is not required!", + Value: "We already have some input here", + Required: false, + MaxLength: 2000, + MinLength: 0, + }, + }, + }, + }, + }, + }) + }, + ModalID: "form_demo_modal", + ModalSubmit: func(s *discordgo.Session, i *discordgo.InteractionCreate) { + s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ + Type: discordgo.InteractionResponseChannelMessageWithSource, + Data: &discordgo.InteractionResponseData{ + Content: "The form data would be send to a specified channel. 🤲", + Flags: discordgo.MessageFlagsEphemeral, + }, + }) + }, +} diff --git a/register_commands.go b/register_commands.go index 5d62c9f..751ea7a 100644 --- a/register_commands.go +++ b/register_commands.go @@ -10,14 +10,16 @@ import ( ) type Command struct { - Definition discordgo.ApplicationCommand - Interact func(s *discordgo.Session, i *discordgo.InteractionCreate) - Autocomplete func(s *discordgo.Session, i *discordgo.InteractionCreate) - ModalSubmit func(s *discordgo.Session, i *discordgo.InteractionCreate) - ModalID string + Definition discordgo.ApplicationCommand + Interact func(s *discordgo.Session, i *discordgo.InteractionCreate) + ComponentInteract func(s *discordgo.Session, i *discordgo.InteractionCreate) + ComponentIDs []string + Autocomplete func(s *discordgo.Session, i *discordgo.InteractionCreate) + ModalSubmit func(s *discordgo.Session, i *discordgo.InteractionCreate) + ModalID string } -var commands []Command = []Command{tag_command, short_get_tag_command, dadjoke_command, ping_command, ask_command, sticky_command, cat_command} +var commands []Command = []Command{tag_command, short_get_tag_command, dadjoke_command, ping_command, ask_command, sticky_command, cat_command, form_command} func ready(s *discordgo.Session, event *discordgo.Ready) { fmt.Print("\nStarting up... (May take longer when Discord rate limits the bot)") @@ -33,7 +35,7 @@ func ready(s *discordgo.Session, event *discordgo.Ready) { continue } for _, command := range commands { - if !slices.Contains(existingCommandNames, command.Definition.Name) || slices.Contains(os.Args, "--update") { + if !slices.Contains(existingCommandNames, command.Definition.Name) || slices.Contains(os.Args, "--update="+command.Definition.Name) { cmd, err := s.ApplicationCommandCreate(s.State.User.ID, guild.ID, &command.Definition) fmt.Printf("\nAdded command \"%s\"", cmd.Name) if err != nil { @@ -61,6 +63,10 @@ func interactionCreate(s *discordgo.Session, i *discordgo.InteractionCreate) { if command.ModalSubmit != nil && strings.HasPrefix(i.ModalSubmitData().CustomID, command.ModalID) { command.ModalSubmit(s, i) } + case discordgo.InteractionMessageComponent: + if command.ComponentInteract != nil && slices.Contains(command.ComponentIDs, i.MessageComponentData().CustomID) { + command.ComponentInteract(s, i) + } } } }