package main import ( "flag" "log" "os" "os/signal" "github.com/bwmarrin/discordgo" ) // Bot parameters var ( GuildID = flag.String("guild", "", "Test guild ID") BotToken = flag.String("token", "", "Bot access token") AppID = flag.String("app", "", "Application ID") ) var s *discordgo.Session func init() { flag.Parse() } func init() { var err error s, err = discordgo.New("Bot " + *BotToken) if err != nil { log.Fatalf("Invalid bot parameters: %v", err) } } func main() { s.AddHandler(func(s *discordgo.Session, r *discordgo.Ready) { log.Println("Bot is up!") }) // Buttons are part of interactions, so we register InteractionCreate handler s.AddHandler(func(s *discordgo.Session, i *discordgo.InteractionCreate) { if i.Type == discordgo.InteractionApplicationCommand { if i.ApplicationCommandData().Name == "feedback" { err := s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ Type: discordgo.InteractionResponseChannelMessageWithSource, Data: &discordgo.InteractionResponseData{ Content: "Are you satisfied with Buttons?", // Buttons and other components are specified in Components field. Components: []discordgo.MessageComponent{ // ActionRow is a container of all buttons within the same row. discordgo.ActionsRow{ Components: []discordgo.MessageComponent{ discordgo.Button{ Label: "Yes", Style: discordgo.SuccessButton, Disabled: false, CustomID: "yes_btn", }, discordgo.Button{ Label: "No", Style: discordgo.DangerButton, Disabled: false, CustomID: "no_btn", }, discordgo.Button{ Label: "I don't know", Style: discordgo.LinkButton, Disabled: false, // Link buttons don't require CustomID and do not trigger the gateway/HTTP event URL: "https://www.youtube.com/watch?v=dQw4w9WgXcQ", Emoji: discordgo.ButtonEmoji{ Name: "🤷", }, }, }, }, // The message may have multiple actions rows. discordgo.ActionsRow{ Components: []discordgo.MessageComponent{ discordgo.Button{ Label: "Discord Developers server", Style: discordgo.LinkButton, Disabled: false, URL: "https://discord.gg/discord-developers", }, }, }, }, }, }) if err != nil { panic(err) } } return } // Type for button press will be always InteractionButton (3) if i.Type != discordgo.InteractionMessageComponent { return } content := "Thanks for your feedback " // CustomID field contains the same id as when was sent. It's used to identify the which button was clicked. switch i.MessageComponentData().CustomID { case "yes_btn": content += "(yes)" case "no_btn": content += "(no)" } s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ // Buttons also may update the message which to which they are attached. // Or may just acknowledge (InteractionResponseDeferredMessageUpdate) that the event was received and not update the message. // To update it later you need to use interaction response edit endpoint. Type: discordgo.InteractionResponseUpdateMessage, Data: &discordgo.InteractionResponseData{ Content: content, Components: []discordgo.MessageComponent{ discordgo.ActionsRow{ Components: []discordgo.MessageComponent{ discordgo.Button{ Label: "Our sponsor", Style: discordgo.LinkButton, Disabled: false, URL: "https://www.youtube.com/watch?v=dQw4w9WgXcQ", Emoji: discordgo.ButtonEmoji{ Name: "💠", }, }, }, }, }, }, }) }) _, err := s.ApplicationCommandCreate(*AppID, *GuildID, &discordgo.ApplicationCommand{ Name: "feedback", Description: "Give your feedback", }) if err != nil { log.Fatalf("Cannot create slash command: %v", err) } err = s.Open() if err != nil { log.Fatalf("Cannot open the session: %v", err) } defer s.Close() stop := make(chan os.Signal, 1) signal.Notify(stop, os.Interrupt) <-stop log.Println("Graceful shutdown") }