From 13bf11abce85ae66a998690267a5149dc8e218e1 Mon Sep 17 00:00:00 2001 From: Atridad Lahiji Date: Tue, 22 Oct 2024 17:07:53 -0600 Subject: [PATCH] Better command abstraction --- command/hs.go | 41 ++++++++++++----------------------------- command/markov.go | 27 +++------------------------ command/ping.go | 23 ++--------------------- lib/command.go | 43 +++++++++++++++++++++++++++++++++++++++++++ main.go | 8 +++++--- 5 files changed, 65 insertions(+), 77 deletions(-) create mode 100644 lib/command.go diff --git a/command/hs.go b/command/hs.go index 0ebc92a..e7f71af 100644 --- a/command/hs.go +++ b/command/hs.go @@ -3,40 +3,23 @@ package command import ( "fmt" "himbot/lib" - "time" "github.com/bwmarrin/discordgo" ) -func HsCommand(s *discordgo.Session, i *discordgo.InteractionCreate) { - if !lib.CheckAndApplyCooldown(s, i, "hs", 10*time.Second) { - return - } +func HsCommand(s *discordgo.Session, i *discordgo.InteractionCreate) (string, error) { + options := i.ApplicationCommandData().Options + if len(options) == 0 || options[0].Type != discordgo.ApplicationCommandOptionString { + return "", fmt.Errorf("please provide a nickname") + } + nickname := options[0].StringValue() - options := i.ApplicationCommandData().Options - if len(options) == 0 || options[0].Type != discordgo.ApplicationCommandOptionString { - lib.RespondWithError(s, i, "Please provide a nickname.") - return - } - nickname := options[0].StringValue() + user, err := lib.GetUser(i) + if err != nil { + return "", fmt.Errorf("error processing command: %w", err) + } - user, err := lib.GetUser(i) - if err != nil { - lib.RespondWithError(s, i, "Error processing command: "+err.Error()) - return - } + response := fmt.Sprintf("%s was %s's nickname in high school!", nickname, user.Username) - response := fmt.Sprintf("%s was %s's nickname in high school!", nickname, user.Username) - - err = s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ - Type: discordgo.InteractionResponseChannelMessageWithSource, - Data: &discordgo.InteractionResponseData{ - Content: response, - }, - }) - - if err != nil { - fmt.Println("Error responding to interaction:", err) - lib.RespondWithError(s, i, "An error occurred while processing the command") - } + return response, nil } diff --git a/command/markov.go b/command/markov.go index 689e26c..abb00ab 100644 --- a/command/markov.go +++ b/command/markov.go @@ -1,24 +1,15 @@ package command import ( - "himbot/lib" - "log" "math/rand" "strings" - "time" "github.com/bwmarrin/discordgo" ) -func MarkovCommand(s *discordgo.Session, i *discordgo.InteractionCreate) { - if !lib.CheckAndApplyCooldown(s, i, "markov", 30*time.Second) { - return - } - - // Get the channel ID from the interaction +func MarkovCommand(s *discordgo.Session, i *discordgo.InteractionCreate) (string, error) { channelID := i.ChannelID - // Get the number of messages to fetch from the option numMessages := 100 // Default value if len(i.ApplicationCommandData().Options) > 0 { if i.ApplicationCommandData().Options[0].Name == "messages" { @@ -34,8 +25,7 @@ func MarkovCommand(s *discordgo.Session, i *discordgo.InteractionCreate) { // Fetch messages allMessages, err := fetchMessages(s, channelID, numMessages) if err != nil { - lib.RespondWithError(s, i, "Failed to fetch messages: "+err.Error()) - return + return "", err } // Build the Markov chain from the fetched messages @@ -49,18 +39,7 @@ func MarkovCommand(s *discordgo.Session, i *discordgo.InteractionCreate) { newMessage = "I couldn't generate a message. The channel might be empty or contain no usable text." } - // Respond to the interaction with the generated message - err = s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ - Type: discordgo.InteractionResponseChannelMessageWithSource, - Data: &discordgo.InteractionResponseData{ - Content: newMessage, - }, - }) - - if err != nil { - log.Printf("Error responding to interaction: %v", err) - lib.RespondWithError(s, i, "An error occurred while processing the command") - } + return newMessage, nil } func fetchMessages(s *discordgo.Session, channelID string, numMessages int) ([]*discordgo.Message, error) { diff --git a/command/ping.go b/command/ping.go index 34ab1c5..efc5c33 100644 --- a/command/ping.go +++ b/command/ping.go @@ -1,31 +1,12 @@ package command import ( - "fmt" - "himbot/lib" - "time" - "github.com/bwmarrin/discordgo" ) -func PingCommand(s *discordgo.Session, i *discordgo.InteractionCreate) { - if !lib.CheckAndApplyCooldown(s, i, "ping", 5*time.Second) { - return - } - +func PingCommand(s *discordgo.Session, i *discordgo.InteractionCreate) (string, error) { // Customize the response based on whether it's a guild or DM responseContent := "Pong!" - err := s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ - Type: discordgo.InteractionResponseChannelMessageWithSource, - Data: &discordgo.InteractionResponseData{ - Content: responseContent, - }, - }) - - if err != nil { - fmt.Println("Error responding to interaction:", err) - // Optionally, you could try to send an error message to the user - lib.RespondWithError(s, i, "An error occurred while processing the command") - } + return responseContent, nil } diff --git a/lib/command.go b/lib/command.go new file mode 100644 index 0000000..f5f2fdb --- /dev/null +++ b/lib/command.go @@ -0,0 +1,43 @@ +package lib + +import ( + "time" + + "github.com/bwmarrin/discordgo" +) + +type CommandFunc func(s *discordgo.Session, i *discordgo.InteractionCreate) (string, error) + +func HandleCommand(commandName string, cooldownDuration time.Duration, handler CommandFunc) func(s *discordgo.Session, i *discordgo.InteractionCreate) { + return func(s *discordgo.Session, i *discordgo.InteractionCreate) { + if !CheckAndApplyCooldown(s, i, commandName, cooldownDuration) { + return + } + + // Acknowledge the interaction immediately + err := s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ + Type: discordgo.InteractionResponseDeferredChannelMessageWithSource, + }) + if err != nil { + ThrowWithError(commandName, "Error deferring response: "+err.Error()) + return + } + + // Execute the command handler + response, err := handler(s, i) + + if err != nil { + RespondWithError(s, i, "Error processing command: "+err.Error()) + return + } + + // Send the follow-up message with the response + _, err = s.FollowupMessageCreate(i.Interaction, true, &discordgo.WebhookParams{ + Content: response, + }) + + if err != nil { + ThrowWithError(commandName, "Error sending follow-up message: "+err.Error()) + } + } +} diff --git a/main.go b/main.go index ddd3cb9..df3b983 100644 --- a/main.go +++ b/main.go @@ -2,10 +2,12 @@ package main import ( "himbot/command" + "himbot/lib" "log" "os" "os/signal" "syscall" + "time" "github.com/bwmarrin/discordgo" "github.com/joho/godotenv" @@ -44,9 +46,9 @@ var ( } commandHandlers = map[string]func(s *discordgo.Session, i *discordgo.InteractionCreate){ - "ping": command.PingCommand, - "hs": command.HsCommand, - "markov": command.MarkovCommand, + "ping": lib.HandleCommand("ping", 5*time.Second, command.PingCommand), + "hs": lib.HandleCommand("hs", 10*time.Second, command.HsCommand), + "markov": lib.HandleCommand("markov", 30*time.Second, command.MarkovCommand), } )