From c14400f74af4d9962405ce24f7428dafa2d8a424 Mon Sep 17 00:00:00 2001 From: vaporvee Date: Sat, 16 Mar 2024 23:53:34 +0100 Subject: [PATCH] some fixes and added logging --- cmd_ask.go | 10 ++++- cmd_autojoinroles.go | 15 +++++-- cmd_autopublish.go | 20 +++++++-- cmd_cat.go | 8 +++- cmd_dadjoke.go | 6 ++- cmd_form.go | 41 ++++++++++++++----- cmd_ping.go | 8 +++- cmd_sticky.go | 35 ++++++++++++---- cmd_tag.go | 42 ++++++++++++------- gather_apis.go | 33 --------------- go.mod | 3 +- go.sum | 11 +++++ handlers.go | 33 ++++++++------- logs/bot.1710629569.log | 5 +++ main.go | 46 ++++++++++++++++----- manage_data.go | 73 +++++++++++++++++---------------- tool.go | 91 +++++++++++++++++++++++++++++++---------- 17 files changed, 318 insertions(+), 162 deletions(-) delete mode 100644 gather_apis.go create mode 100644 logs/bot.1710629569.log diff --git a/cmd_ask.go b/cmd_ask.go index b2d8c19..a94c384 100644 --- a/cmd_ask.go +++ b/cmd_ask.go @@ -1,6 +1,9 @@ package main -import "github.com/bwmarrin/discordgo" +import ( + "github.com/bwmarrin/discordgo" + "github.com/sirupsen/logrus" +) var cmd_ask Command = Command{ Definition: discordgo.ApplicationCommand{ @@ -16,11 +19,14 @@ var cmd_ask Command = Command{ }, }, Interact: func(s *discordgo.Session, i *discordgo.InteractionCreate) { - respondEmbed(i.Interaction, discordgo.MessageEmbed{ + err := respondEmbed(i.Interaction, discordgo.MessageEmbed{ Type: discordgo.EmbedTypeImage, Color: hexToDecimal(color["primary"]), Image: &discordgo.MessageEmbedImage{ URL: simpleGetFromAPI("image", "https://yesno.wtf/api").(string), }}, false) + if err != nil { + logrus.Error("Failed to respond with embed: ", err) + } }, } diff --git a/cmd_autojoinroles.go b/cmd_autojoinroles.go index ceee1d7..9b47539 100644 --- a/cmd_autojoinroles.go +++ b/cmd_autojoinroles.go @@ -1,6 +1,9 @@ package main -import "github.com/bwmarrin/discordgo" +import ( + "github.com/bwmarrin/discordgo" + "github.com/sirupsen/logrus" +) var cmd_autojoinroles Command = Command{ Definition: discordgo.ApplicationCommand{ @@ -40,7 +43,10 @@ var cmd_autojoinroles Command = Command{ if len(i.ApplicationCommandData().Options[0].Options) == 1 { var givenRole *discordgo.Role = i.ApplicationCommandData().Options[0].Options[0].RoleValue(s, i.GuildID) role = givenRole.ID - botrole, _ := getHighestRole(i.GuildID) + botrole, err := getHighestRole(i.GuildID) + if err != nil { + logrus.Error(err) + } if givenRole.Position >= botrole.Position { content = "<@&" + role + "> is not below the Bot's current highest role(<@&" + botrole.ID + ">). That makes it unable to manage it." } else { @@ -53,7 +59,10 @@ var cmd_autojoinroles Command = Command{ } else if setAutoJoinRole(i.GuildID, option, role) { content = "Deleted auto join role for " + option + "s" } - respond(i.Interaction, content, true) + err := respond(i.Interaction, content, true) + if err != nil { + logrus.Error(err) + } purgeUnusedAutoJoinRoles(i.GuildID) }, } diff --git a/cmd_autopublish.go b/cmd_autopublish.go index b62a52f..bd643ea 100644 --- a/cmd_autopublish.go +++ b/cmd_autopublish.go @@ -1,6 +1,9 @@ package main -import "github.com/bwmarrin/discordgo" +import ( + "github.com/bwmarrin/discordgo" + "github.com/sirupsen/logrus" +) var cmd_autopublish Command = Command{ Definition: discordgo.ApplicationCommand{ @@ -11,12 +14,21 @@ var cmd_autopublish Command = Command{ channel, _ := s.State.Channel(i.ChannelID) if channel.Type == discordgo.ChannelTypeGuildNews { if toggleAutoPublish(i.GuildID, i.ChannelID) { - respond(i.Interaction, "Autopublishing is now disabled on <#"+i.ChannelID+">", true) + err := respond(i.Interaction, "Autopublishing is now disabled on <#"+i.ChannelID+">", true) + if err != nil { + logrus.Error(err) + } } else { - respond(i.Interaction, "Autopublishing is now enabled on <#"+i.ChannelID+">", true) + err := respond(i.Interaction, "Autopublishing is now enabled on <#"+i.ChannelID+">", true) + if err != nil { + logrus.Error(err) + } } } else { - respond(i.Interaction, "This is not an announcement channel!", true) + err := respond(i.Interaction, "This is not an announcement channel!", true) + if err != nil { + logrus.Error(err) + } } }, } diff --git a/cmd_cat.go b/cmd_cat.go index 047b3c7..2782506 100644 --- a/cmd_cat.go +++ b/cmd_cat.go @@ -6,6 +6,7 @@ import ( "net/http" "github.com/bwmarrin/discordgo" + "github.com/sirupsen/logrus" ) var cmd_cat Command = Command{ @@ -16,12 +17,17 @@ var cmd_cat Command = Command{ Interact: func(s *discordgo.Session, i *discordgo.InteractionCreate) { cat, err := GetCatImageURL() if err == nil { - respondEmbed(i.Interaction, discordgo.MessageEmbed{ + err := respondEmbed(i.Interaction, discordgo.MessageEmbed{ Type: discordgo.EmbedTypeImage, Color: hexToDecimal(color["primary"]), Image: &discordgo.MessageEmbedImage{ URL: cat, }}, false) + if err != nil { + logrus.Error(err) + } + } else { + logrus.Error(err) } }, } diff --git a/cmd_dadjoke.go b/cmd_dadjoke.go index 68577a2..d9d7f6d 100644 --- a/cmd_dadjoke.go +++ b/cmd_dadjoke.go @@ -2,6 +2,7 @@ package main import ( "github.com/bwmarrin/discordgo" + "github.com/sirupsen/logrus" ) var cmd_dadjoke Command = Command{ @@ -10,6 +11,9 @@ var cmd_dadjoke Command = Command{ Description: "Gives you a random joke that is as bad as your dad would tell them", }, Interact: func(s *discordgo.Session, i *discordgo.InteractionCreate) { - respond(i.Interaction, simpleGetFromAPI("joke", "https://icanhazdadjoke.com/").(string), false) + err := respond(i.Interaction, simpleGetFromAPI("joke", "https://icanhazdadjoke.com/").(string), false) + if err != nil { + logrus.Error(err) + } }, } diff --git a/cmd_form.go b/cmd_form.go index bcf748e..7c26776 100644 --- a/cmd_form.go +++ b/cmd_form.go @@ -2,12 +2,12 @@ package main import ( "bytes" - "log" "os" "strings" "github.com/bwmarrin/discordgo" "github.com/google/uuid" + "github.com/sirupsen/logrus" ) var fileData []byte @@ -79,7 +79,7 @@ var cmd_form Command = Command{ case "help": fileData, _ = os.ReadFile("./form_templates/form_demo.json") fileReader := bytes.NewReader(fileData) - s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ + err := s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ Type: discordgo.InteractionResponseChannelMessageWithSource, Data: &discordgo.InteractionResponseData{ Content: "NOT SUPPORTED YET!(use `/form add` instead)\n\nGet the example file edit it (make sure to have a unique \"form_type\") and submit it via `/form create`.\nOr use the demo button to get an idea of how the example would look like.", @@ -107,13 +107,18 @@ var cmd_form Command = Command{ }, }, }) + if err != nil { + logrus.Error(err) + } case "custom": - respond(i.Interaction, "Feature not available yet use `/form add` instead", true) + err := respond(i.Interaction, "Feature not available yet use `/form add` instead", true) + if err != nil { + logrus.Error(err) + } case "add": var title, formID, overwriteTitle, acceptChannelID string var modsCanComment bool options := i.ApplicationCommandData().Options[0] - for _, opt := range options.Options { switch opt.Name { case "type": @@ -140,7 +145,6 @@ var cmd_form Command = Command{ title = val } } - var exists bool = true var formManageID uuid.UUID = uuid.New() for exists { @@ -148,7 +152,7 @@ var cmd_form Command = Command{ exists = getFormManageIdExists(formManageID) } - message, _ := s.ChannelMessageSendComplex(i.ChannelID, &discordgo.MessageSend{ + message, err := s.ChannelMessageSendComplex(i.ChannelID, &discordgo.MessageSend{ Embed: &discordgo.MessageEmbed{ Color: hexToDecimal(color["primary"]), Title: title, @@ -171,8 +175,14 @@ var cmd_form Command = Command{ }, }, }) + if err != nil { + logrus.Error(err) + } addFormButton(i.GuildID, i.ChannelID, message.ID, formManageID.String(), formID, options.Options[0].ChannelValue(s).ID, overwriteTitle, acceptChannelID, modsCanComment) - respond(i.Interaction, "Successfully added form button!", true) + err = respond(i.Interaction, "Successfully added form button!", true) + if err != nil { + logrus.Error(err) + } } }, ComponentInteract: func(s *discordgo.Session, i *discordgo.InteractionCreate) { @@ -219,12 +229,18 @@ var cmd_form Command = Command{ }, }) if err != nil { - log.Println(err) + logrus.Error(err) } else { - respond(i.Interaction, "Submited!", true) + err = respond(i.Interaction, "Submited!", true) + if err != nil { + logrus.Error(err) + } } } else { - respond(i.Interaction, "The form data would be send to a specified channel. 🤲", true) + err := respond(i.Interaction, "The form data would be send to a specified channel. 🤲", true) + if err != nil { + logrus.Error(err) + } } } }, @@ -243,12 +259,15 @@ var cmd_form Command = Command{ Value: "template_general", }, } - s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ + err := s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ Type: discordgo.InteractionApplicationCommandAutocompleteResult, Data: &discordgo.InteractionResponseData{ Choices: choices, }, }) + if err != nil { + logrus.Error(err) + } }, } diff --git a/cmd_ping.go b/cmd_ping.go index 8a13a8e..791e512 100644 --- a/cmd_ping.go +++ b/cmd_ping.go @@ -6,6 +6,7 @@ import ( "time" "github.com/bwmarrin/discordgo" + "github.com/sirupsen/logrus" ) var cmd_ping Command = Command{ @@ -22,7 +23,7 @@ var cmd_ping Command = Command{ resp, err := client.Get("https://discord.com/api/v9/gateway/bot") if err != nil { - fmt.Println("Error:", err) + logrus.Error(err) return } defer resp.Body.Close() @@ -36,10 +37,13 @@ var cmd_ping Command = Command{ } else { ping_color = "red" } - respondEmbed(i.Interaction, discordgo.MessageEmbed{ + err = respondEmbed(i.Interaction, discordgo.MessageEmbed{ Title: s.State.User.Username + " ping", Description: fmt.Sprintf("# %.2fms", ping.Seconds()*1000), Type: discordgo.EmbedTypeArticle, Color: hexToDecimal(color[ping_color])}, true) + if err != nil { + logrus.Error(err) + } }, } diff --git a/cmd_sticky.go b/cmd_sticky.go index a3b32bd..93065ba 100644 --- a/cmd_sticky.go +++ b/cmd_sticky.go @@ -1,9 +1,8 @@ package main import ( - "log" - "github.com/bwmarrin/discordgo" + "github.com/sirupsen/logrus" ) var cmd_sticky Command = Command{ @@ -27,7 +26,7 @@ var cmd_sticky Command = Command{ Interact: func(s *discordgo.Session, i *discordgo.InteractionCreate) { switch i.ApplicationCommandData().Options[0].Name { case "add": - s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ + err := s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ Type: discordgo.InteractionResponseModal, Data: &discordgo.InteractionResponseData{ CustomID: "sticky_modal", @@ -49,13 +48,25 @@ var cmd_sticky Command = Command{ }, }, }) + if err != nil { + logrus.Error(err) + } case "remove": if hasSticky(i.GuildID, i.ChannelID) { - s.ChannelMessageDelete(i.ChannelID, getStickyMessageID(i.GuildID, i.ChannelID)) + err := s.ChannelMessageDelete(i.ChannelID, getStickyMessageID(i.GuildID, i.ChannelID)) + if err != nil { + logrus.Error(err) + } removeSticky(i.GuildID, i.ChannelID) - respond(i.Interaction, "The sticky message was removed from this channel!", true) + err = respond(i.Interaction, "The sticky message was removed from this channel!", true) + if err != nil { + logrus.Error(err) + } } else { - respond(i.Interaction, "This channel has no sticky message!", true) + err := respond(i.Interaction, "This channel has no sticky message!", true) + if err != nil { + logrus.Error(err) + } } } }, @@ -71,12 +82,18 @@ var cmd_sticky Command = Command{ Description: text, }) if err != nil { - log.Println(err) + logrus.Error(err) } if addSticky(i.GuildID, i.ChannelID, text, message.ID) { - respond(i.Interaction, "Sticky message in this channel was updated!", true) + err := respond(i.Interaction, "Sticky message in this channel was updated!", true) + if err != nil { + logrus.Error(err) + } } else { - respond(i.Interaction, "Message sticked to the channel!", true) + err := respond(i.Interaction, "Message sticked to the channel!", true) + if err != nil { + logrus.Error(err) + } } }, } diff --git a/cmd_tag.go b/cmd_tag.go index 73947e4..576d3ca 100644 --- a/cmd_tag.go +++ b/cmd_tag.go @@ -1,9 +1,8 @@ package main import ( - "log" - "github.com/bwmarrin/discordgo" + "github.com/sirupsen/logrus" ) var cmd_tag Command = Command{ @@ -50,9 +49,9 @@ var cmd_tag Command = Command{ Interact: func(s *discordgo.Session, i *discordgo.InteractionCreate) { switch i.ApplicationCommandData().Options[0].Name { case "get": - GetTagCommand(s, i, i.ApplicationCommandData().Options[0].Options[0]) + GetTagCommand(i, i.ApplicationCommandData().Options[0].Options[0]) case "add": - s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ + err := s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ Type: discordgo.InteractionResponseModal, Data: &discordgo.InteractionResponseData{ CustomID: "tag_add_modal" + i.Interaction.Member.User.ID, @@ -86,9 +85,15 @@ var cmd_tag Command = Command{ }, }, }) + if err != nil { + logrus.Error(err) + } case "remove": removeTag(i.GuildID, i.ApplicationCommandData().Options[0].Options[0].StringValue()) - respond(i.Interaction, "Tag removed!", true) + err := respond(i.Interaction, "Tag removed!", true) + if err != nil { + logrus.Error(err) + } } }, ModalIDs: []string{"tag_add_modal"}, @@ -96,10 +101,13 @@ var cmd_tag Command = Command{ tagName := i.ModalSubmitData().Components[0].(*discordgo.ActionsRow).Components[0].(*discordgo.TextInput).Value tagContent := i.ModalSubmitData().Components[1].(*discordgo.ActionsRow).Components[0].(*discordgo.TextInput).Value addTag(i.GuildID, tagName, tagContent) - respond(i.Interaction, "Tag \""+tagName+"\" added!", true) + err := respond(i.Interaction, "Tag \""+tagName+"\" added!", true) + if err != nil { + logrus.Error(err) + } }, Autocomplete: func(s *discordgo.Session, i *discordgo.InteractionCreate) { - AutocompleteTag(s, i) + AutocompleteTag(i) }, } @@ -118,31 +126,37 @@ var cmd_tag_short Command = Command{ }, }, Interact: func(s *discordgo.Session, i *discordgo.InteractionCreate) { - GetTagCommand(s, i, i.ApplicationCommandData().Options[0]) + GetTagCommand(i, i.ApplicationCommandData().Options[0]) }, Autocomplete: func(s *discordgo.Session, i *discordgo.InteractionCreate) { - AutocompleteTag(s, i) + AutocompleteTag(i) }, } -func GetTagCommand(s *discordgo.Session, i *discordgo.InteractionCreate, option *discordgo.ApplicationCommandInteractionDataOption) { - respond(i.Interaction, getTagContent(i.GuildID, option.Value.(string)), false) +func GetTagCommand(i *discordgo.InteractionCreate, option *discordgo.ApplicationCommandInteractionDataOption) { + err := respond(i.Interaction, getTagContent(i.GuildID, option.Value.(string)), false) + if err != nil { + logrus.Error(err) + } } -func AutocompleteTag(s *discordgo.Session, i *discordgo.InteractionCreate) { - s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ +func AutocompleteTag(i *discordgo.InteractionCreate) { + err := bot.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ Type: discordgo.InteractionApplicationCommandAutocompleteResult, Data: &discordgo.InteractionResponseData{ Choices: generateTagChoices(i.GuildID), }, }) + if err != nil { + logrus.Error(err) + } } func generateTagChoices(guildID string) []*discordgo.ApplicationCommandOptionChoice { choices := []*discordgo.ApplicationCommandOptionChoice{} IDs, err := getTagIDs(guildID) if err != nil { - log.Println("Error getting tag keys:", err) + logrus.Error(err) return choices } for _, id := range IDs { diff --git a/gather_apis.go b/gather_apis.go deleted file mode 100644 index 66f861b..0000000 --- a/gather_apis.go +++ /dev/null @@ -1,33 +0,0 @@ -package main - -import ( - "encoding/json" - "io" - "log" - "net/http" -) - -func simpleGetFromAPI(key string, url string) interface{} { - client := &http.Client{} - req, err := http.NewRequest("GET", url, nil) - if err != nil { - log.Println("Error creating request:", err) - } - req.Header.Set("Accept", "application/json") - resp, err := client.Do(req) - if err != nil { - log.Println("Error making request:", err) - } - defer resp.Body.Close() - body, err := io.ReadAll(resp.Body) - if err != nil { - log.Println("Error reading response body:", err) - } - - var result map[string]interface{} - err = json.Unmarshal(body, &result) - if err != nil { - log.Println("Error decoding JSON:", err) - } - return result[key] -} diff --git a/go.mod b/go.mod index 8be6a50..a6e18fd 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( require ( github.com/gorilla/websocket v1.4.2 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b // indirect - golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 // indirect + golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect ) diff --git a/go.sum b/go.sum index cf13ea7..8d6aa43 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,7 @@ github.com/bwmarrin/discordgo v0.27.1 h1:ib9AIc/dom1E/fSIulrBwnez0CToJE113ZGt4HoliGY= github.com/bwmarrin/discordgo v0.27.1/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0kIVMCHkZtRY= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= @@ -8,11 +10,20 @@ github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b h1:7mWr3k41Qtv8XlltBkDkl8LoP3mpSgBW8BUoxtEdbXg= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/handlers.go b/handlers.go index 3953806..32ede3c 100644 --- a/handlers.go +++ b/handlers.go @@ -1,13 +1,12 @@ package main import ( - "fmt" - "log" "os" "slices" "strings" "github.com/bwmarrin/discordgo" + "github.com/sirupsen/logrus" ) type Command struct { @@ -25,7 +24,7 @@ type Command struct { var commands []Command = []Command{cmd_form, cmd_tag, cmd_tag_short, cmd_dadjoke, cmd_ping, cmd_ask, cmd_sticky, cmd_cat, cmd_autojoinroles, cmd_autopublish} func ready(s *discordgo.Session, event *discordgo.Ready) { - fmt.Print("\nStarting up...") + logrus.Info("\nStarting up...") findAndDeleteUnusedMessages() removeOldCommandFromAllGuilds(s) var existingCommandNames []string @@ -35,28 +34,28 @@ func ready(s *discordgo.Session, event *discordgo.Ready) { existingCommandNames = append(existingCommandNames, existingCommand.Name) } if err != nil { - fmt.Printf("error fetching existing commands for guild %s: %v\n", guild.Name, err) + logrus.Errorf("error fetching existing commands for guild %s: %v\n", guild.Name, err) continue } for _, command := range commands { 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) + logrus.Infof("\nAdded command \"%s\"", cmd.Name) if err != nil { - fmt.Println("error creating command,", err) + logrus.Error("error creating command,", err) continue } } } } - fmt.Print("\nSuccessfully started the Bot!") + logrus.Info("\nSuccessfully started the Bot!") } func guildCreate(s *discordgo.Session, event *discordgo.GuildCreate) { for _, command := range commands { _, err := s.ApplicationCommandCreate(s.State.User.ID, event.Guild.ID, &command.Definition) if err != nil { - log.Printf("error creating command for guild %s: %v\n", event.Guild.Name, err) + logrus.Errorf("error creating command for guild %s: %v\n", event.Guild.Name, err) } } } @@ -107,7 +106,7 @@ func removeOldCommandFromAllGuilds(s *discordgo.Session) { for _, guild := range s.State.Guilds { existingCommands, err := s.ApplicationCommands(s.State.User.ID, guild.ID) if err != nil { - fmt.Printf("error fetching existing commands for guild %s: %v\n", guild.Name, err) + logrus.Errorf("error fetching existing commands for guild %s: %v\n", guild.Name, err) continue } var commandIDs []string @@ -116,10 +115,10 @@ func removeOldCommandFromAllGuilds(s *discordgo.Session) { } for _, existingCommand := range existingCommands { if !slices.Contains(commandIDs, existingCommand.Name) { - fmt.Printf("\nDeleting command \"%s\"", existingCommand.Name) + logrus.Infof("\nDeleting command \"%s\"", existingCommand.Name) err := s.ApplicationCommandDelete(s.State.User.ID, guild.ID, existingCommand.ID) if err != nil { - fmt.Printf("error deleting command %s for guild %s: %v\n", existingCommand.Name, guild.Name, err) + logrus.Errorf("error deleting command %s for guild %s: %v\n", existingCommand.Name, guild.Name, err) } } } @@ -129,7 +128,7 @@ func removeOldCommandFromAllGuilds(s *discordgo.Session) { func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) { if len(m.Embeds) == 0 || m.Embeds[0].Footer == nil || m.Embeds[0].Footer.Text != "📌 Sticky message" { if hasSticky(m.GuildID, m.ChannelID) { - s.ChannelMessageDelete(m.ChannelID, getStickyMessageID(m.GuildID, m.ChannelID)) + err := s.ChannelMessageDelete(m.ChannelID, getStickyMessageID(m.GuildID, m.ChannelID)) stickyMessage, _ := s.ChannelMessageSendEmbed(m.ChannelID, &discordgo.MessageEmbed{ Type: discordgo.EmbedTypeArticle, Footer: &discordgo.MessageEmbedFooter{ @@ -138,13 +137,19 @@ func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) { Color: hexToDecimal(color["primary"]), Description: getStickyMessageContent(m.GuildID, m.ChannelID), }) + if err != nil { + logrus.Error(err) + } updateStickyMessageID(m.GuildID, m.ChannelID, stickyMessage.ID) } } channel, _ := s.Channel(m.ChannelID) if channel.Type == discordgo.ChannelTypeGuildNews { if isAutopublishEnabled(m.GuildID, m.ChannelID) { - s.ChannelMessageCrosspost(m.ChannelID, m.ID) + _, err := s.ChannelMessageCrosspost(m.ChannelID, m.ID) + if err != nil { + logrus.Error(err) + } } } } @@ -156,6 +161,6 @@ func messageDelete(s *discordgo.Session, m *discordgo.MessageDelete) { //TODO: a func guildMemberJoin(s *discordgo.Session, m *discordgo.GuildMemberAdd) { err := s.GuildMemberRoleAdd(m.GuildID, m.User.ID, getAutoJoinRole(m.GuildID, m.User.Bot)) if err != nil { - log.Println(err) + logrus.Error(err) } } diff --git a/logs/bot.1710629569.log b/logs/bot.1710629569.log new file mode 100644 index 0000000..45186cf --- /dev/null +++ b/logs/bot.1710629569.log @@ -0,0 +1,5 @@ +{"file":"/home/vaporvee/acecore/main.go:40","func":"main.main","level":"info","msg":"Discord session created","time":"2024-03-16T23:52:49+01:00"} +{"file":"/home/vaporvee/acecore/main.go:54","func":"main.main","level":"info","msg":"\nBot is now running as \"acecore [DEV]\"!","time":"2024-03-16T23:52:49+01:00"} +{"file":"/home/vaporvee/acecore/handlers.go:27","func":"main.ready","level":"info","msg":"\nStarting up...","time":"2024-03-16T23:52:49+01:00"} +{"file":"/home/vaporvee/acecore/handlers.go:51","func":"main.ready","level":"info","msg":"\nSuccessfully started the Bot!","time":"2024-03-16T23:52:50+01:00"} +{"file":"/home/vaporvee/acecore/main.go:58","func":"main.main","level":"info","msg":"\nShutting down...","time":"2024-03-16T23:53:10+01:00"} diff --git a/main.go b/main.go index 52ac566..dfb2bd0 100644 --- a/main.go +++ b/main.go @@ -1,11 +1,12 @@ package main import ( - "fmt" - "log" + "io" "os" "os/signal" + "strconv" "syscall" + "time" "database/sql" "net/url" @@ -13,6 +14,7 @@ import ( "github.com/bwmarrin/discordgo" "github.com/joho/godotenv" _ "github.com/lib/pq" + "github.com/sirupsen/logrus" ) //TODO: add more error handlings @@ -21,21 +23,21 @@ var db *sql.DB var bot *discordgo.Session func main() { - godotenv.Load() - + logrusInitFile() var err error + godotenv.Load() connStr := "postgresql://" + os.Getenv("DB_USER") + ":" + url.QueryEscape(os.Getenv("DB_PASSWORD")) + "@" + os.Getenv("DB_SERVER") + ":" + string(os.Getenv("DB_PORT")) + "/" + os.Getenv("DB_NAME") + "?sslmode=disable&application_name=Discord Bot" db, err = sql.Open("postgres", connStr) if err != nil { - log.Fatal(err) + logrus.Fatal(err) } initTables() bot, err = discordgo.New("Bot " + os.Getenv("BOT_TOKEN")) if err != nil { - fmt.Println("error creating Discord session,", err) + logrus.Fatal("error creating Discord session,", err) return } else { - fmt.Println("Discord session created") + logrus.Info("Discord session created") } bot.Identify.Intents = discordgo.IntentsGuildMessages | discordgo.IntentsGuilds | discordgo.IntentMessageContent | discordgo.IntentGuildMembers bot.AddHandler(ready) @@ -46,13 +48,37 @@ func main() { bot.AddHandler(guildMemberJoin) err = bot.Open() if err != nil { - fmt.Println("error opening connection,", err) + logrus.Error("error opening connection,", err) return } - fmt.Printf("\nBot is now running as \"%s\"!", bot.State.User.Username) + logrus.Infof("\nBot is now running as \"%s\"!", bot.State.User.Username) sc := make(chan os.Signal, 1) signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt) <-sc - fmt.Println("\nShutting down...") + logrus.Info("\nShutting down...") bot.Close() } + +func logrusInitFile() { + logrus.SetLevel(logrus.DebugLevel) + logrus.SetFormatter(&logrus.JSONFormatter{}) + logrus.SetReportCaller(true) + timestamp := time.Now().Unix() + + var file_name string = "logs/bot." + strconv.FormatInt(timestamp, 10) + ".log" + if _, err := os.Stat("logs"); os.IsNotExist(err) { + err := os.Mkdir("logs", 0755) + if err != nil { + logrus.Error(err) + return + } + } + log, err := os.OpenFile(file_name, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) + if err != nil { + logrus.Error(err) + return + } + + mw := io.MultiWriter(os.Stdout, log) + logrus.SetOutput(mw) +} diff --git a/manage_data.go b/manage_data.go index e4942ce..a6f5198 100644 --- a/manage_data.go +++ b/manage_data.go @@ -4,6 +4,7 @@ import ( "log" "github.com/google/uuid" + "github.com/sirupsen/logrus" ) func initTables() { @@ -74,12 +75,12 @@ func addTag(guildID, tagName, tagContent string) bool { id = uuid.New() err := db.QueryRow("SELECT EXISTS (SELECT 1 FROM tags WHERE guild_id = $1 AND tag_id = $2)", guildID, id).Scan(&exists) if err != nil { - log.Println(err) + logrus.Error(err) } } _, err := db.Exec("INSERT INTO tags (guild_id, tag_name, tag_content, tag_id) VALUES ($1, $2, $3, $4)", guildID, tagName, tagContent, id) if err != nil { - log.Println(err) + logrus.Error(err) } return exists @@ -88,12 +89,12 @@ func removeTag(guildID string, tagID string) { var exists bool err := db.QueryRow("SELECT EXISTS (SELECT 1 FROM tags WHERE guild_id = $1 AND tag_id = $2)", guildID, tagID).Scan(&exists) if err != nil { - log.Println(err) + logrus.Error(err) } if exists { _, err = db.Exec("DELETE FROM tags WHERE guild_id = $1 AND tag_id = $2", guildID, tagID) if err != nil { - log.Println(err) + logrus.Error(err) } } } @@ -135,12 +136,12 @@ func addSticky(guildID string, channelID string, messageContent string, messageI if exists { _, err := db.Exec("UPDATE sticky SET message_content = $1 WHERE guild_id = $2 AND channel_id = $3", messageContent, guildID, channelID) if err != nil { - log.Println(err) + logrus.Error(err) } } else { _, err := db.Exec("INSERT INTO sticky (guild_id, channel_id, message_id, message_content) VALUES ($1, $2, $3, $4)", guildID, channelID, messageID, messageContent) if err != nil { - log.Println(err) + logrus.Error(err) } } return exists @@ -150,7 +151,7 @@ func hasSticky(guildID string, channelID string) bool { var exists bool err := db.QueryRow("SELECT EXISTS (SELECT 1 FROM sticky WHERE guild_id = $1 AND channel_id = $2)", guildID, channelID).Scan(&exists) if err != nil { - log.Println(err) + logrus.Error(err) } return exists } @@ -161,7 +162,7 @@ func getStickyMessageID(guildID string, channelID string) string { if exists { err := db.QueryRow("SELECT message_id FROM sticky WHERE guild_id = $1 AND channel_id = $2", guildID, channelID).Scan(&messageID) if err != nil { - log.Println(err) + logrus.Error(err) } } return messageID @@ -172,7 +173,7 @@ func getStickyMessageContent(guildID string, channelID string) string { if exists { err := db.QueryRow("SELECT message_content FROM sticky WHERE guild_id = $1 AND channel_id = $2", guildID, channelID).Scan(&messageID) if err != nil { - log.Println(err) + logrus.Error(err) } } return messageID @@ -183,7 +184,7 @@ func updateStickyMessageID(guildID string, channelID string, messageID string) { if exists { _, err := db.Exec("UPDATE sticky SET message_id = $1 WHERE guild_id = $2 AND channel_id = $3", messageID, guildID, channelID) if err != nil { - log.Println(err) + logrus.Error(err) } } } @@ -191,7 +192,7 @@ func updateStickyMessageID(guildID string, channelID string, messageID string) { func removeSticky(guildID string, channelID string) { _, err := db.Exec("DELETE FROM sticky WHERE guild_id = $1 AND channel_id = $2", guildID, channelID) if err != nil { - log.Println(err) + logrus.Error(err) } } @@ -199,7 +200,7 @@ func getFormManageIdExists(id uuid.UUID) bool { var exists bool err := db.QueryRow("SELECT EXISTS (SELECT 1 FROM form_manage WHERE form_manage_id = $1)", id).Scan(&exists) if err != nil { - log.Println(err) + logrus.Error(err) } return exists } @@ -207,7 +208,7 @@ func getFormManageIdExists(id uuid.UUID) bool { func addFormButton(guildID string, channelID string, messageID string, formManageID string, formType string, resultChannelID string, overwriteTitle string, acceptChannelID string, modsCanComment bool) { _, err := db.Exec("INSERT INTO form_manage (guild_id, form_manage_id, channel_id, message_id, form_type, result_channel_id, overwrite_title, accept_channel_id, mods_can_comment) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)", guildID, formManageID, channelID, messageID, formType, resultChannelID, overwriteTitle, acceptChannelID, modsCanComment) if err != nil { - log.Println(err) + logrus.Error(err) } } @@ -218,7 +219,7 @@ func getFormManageIDs() []string { var IDs []string rows, err := db.Query("SELECT form_manage_id FROM form_manage") if err != nil { - log.Println(err) + logrus.Error(err) return nil } defer rows.Close() @@ -226,14 +227,14 @@ func getFormManageIDs() []string { for rows.Next() { var id string if err := rows.Scan(&id); err != nil { - log.Println(err) + logrus.Error(err) return nil } IDs = append(IDs, id) } if err := rows.Err(); err != nil { - log.Println(err) + logrus.Error(err) return nil } return IDs @@ -243,7 +244,7 @@ func getFormType(formManageID string) string { var formType string err := db.QueryRow("SELECT form_type FROM form_manage WHERE form_manage_id = $1", formManageID).Scan(&formType) if err != nil { - log.Println(err) + logrus.Error(err) } return formType } @@ -252,19 +253,19 @@ func getFormResultValues(formManageID string) FormResult { var result FormResult err := db.QueryRow("SELECT overwrite_title FROM form_manage WHERE form_manage_id = $1", formManageID).Scan(&result.OverwriteTitle) if err != nil { - log.Println(err) + logrus.Error(err) } err = db.QueryRow("SELECT result_channel_id FROM form_manage WHERE form_manage_id = $1", formManageID).Scan(&result.ResultChannelID) if err != nil { - log.Println(err) + logrus.Error(err) } err = db.QueryRow("SELECT accept_channel_id FROM form_manage WHERE form_manage_id = $1", formManageID).Scan(&result.AcceptChannelID) if err != nil { - log.Println(err) + logrus.Error(err) } err = db.QueryRow("SELECT mods_can_comment FROM form_manage WHERE form_manage_id = $1", formManageID).Scan(&result.ModsCanComment) if err != nil { - log.Println(err) + logrus.Error(err) } return result } @@ -273,7 +274,7 @@ func getFormOverwriteTitle(formManageID string) string { var overwriteTitle string err := db.QueryRow("SELECT overwrite_title FROM form_manage WHERE form_manage_id = $1", formManageID).Scan(&overwriteTitle) if err != nil { - log.Println(err) + logrus.Error(err) } return overwriteTitle } @@ -283,21 +284,21 @@ func setAutoJoinRole(guildID string, option string, roleID string) bool { var autojoinroles_exists bool err := db.QueryRow("SELECT EXISTS (SELECT 1 FROM autojoinroles WHERE guild_id = $1)", guildID).Scan(&autojoinroles_exists) if err != nil { - log.Println(err) + logrus.Error(err) } err = db.QueryRow("SELECT EXISTS (SELECT 1 FROM autojoinroles WHERE guild_id = $1 AND "+option+"_role IS NOT NULL AND "+option+"_role != '')", guildID).Scan(&role_exists) if err != nil { - log.Println(err) + logrus.Error(err) } if autojoinroles_exists { _, err = db.Exec("UPDATE autojoinroles SET "+option+"_role = $1 WHERE guild_id = $2", roleID, guildID) if err != nil { - log.Println(err) + logrus.Error(err) } } else { _, err = db.Exec("INSERT INTO autojoinroles (guild_id, "+option+"_role) VALUES ($1, $2)", guildID, roleID) if err != nil { - log.Println(err) + logrus.Error(err) } } return role_exists @@ -306,7 +307,7 @@ func setAutoJoinRole(guildID string, option string, roleID string) bool { func purgeUnusedAutoJoinRoles(guildID string) { _, err := db.Exec("DELETE FROM autojoinroles WHERE guild_id = $1 AND user_role = '' OR user_role IS NULL AND bot_role = '' OR bot_role IS NULL", guildID) if err != nil { - log.Println(err) + logrus.Error(err) } } @@ -320,7 +321,7 @@ func getAutoJoinRole(guildID string, isBot bool) string { } err := db.QueryRow("SELECT "+isBotString+"_role FROM autojoinroles WHERE guild_id = $1", guildID).Scan(&role) if err != nil { - log.Println(err, guildID) + logrus.Error(err, guildID) } return role } @@ -329,17 +330,17 @@ func toggleAutoPublish(guildID string, newsChannelID string) bool { var exists bool err := db.QueryRow("SELECT EXISTS (SELECT 1 FROM autopublish WHERE guild_id = $1 AND news_channel_id = $2)", guildID, newsChannelID).Scan(&exists) if err != nil { - log.Print(err) + logrus.Error(err) } if exists { _, err := db.Exec("DELETE FROM autopublish WHERE guild_id = $1 AND news_channel_id = $2", guildID, newsChannelID) if err != nil { - log.Print(err) + logrus.Error(err) } } else { _, err := db.Exec("INSERT INTO autopublish (guild_id, news_channel_id) VALUES ($1, $2)", guildID, newsChannelID) if err != nil { - log.Print(err) + logrus.Error(err) } } return exists @@ -349,7 +350,7 @@ func isAutopublishEnabled(guildID string, newsChannelID string) bool { var enabled bool err := db.QueryRow("SELECT EXISTS (SELECT 1 FROM autopublish WHERE guild_id = $1 AND news_channel_id = $2)", guildID, newsChannelID).Scan(&enabled) if err != nil { - log.Print(err) + logrus.Error(err) } return enabled } @@ -357,7 +358,7 @@ func isAutopublishEnabled(guildID string, newsChannelID string) bool { func tryDeleteUnusedMessage(messageID string) { _, err := db.Exec("DELETE FROM form_manage WHERE message_id = $1", messageID) if err != nil { - log.Println(err) + logrus.Error(err) } } @@ -365,20 +366,20 @@ func getAllSavedMessages() []MessageIDs { var savedMessages []MessageIDs rows, err := db.Query("SELECT message_id, channel_id FROM form_manage") if err != nil { - log.Print(err) + logrus.Error(err) return nil } defer rows.Close() for rows.Next() { var messageID, channelID string if err := rows.Scan(&messageID, &channelID); err != nil { - log.Print(err) + logrus.Error(err) continue } savedMessages = append(savedMessages, MessageIDs{ID: messageID, ChannelID: channelID}) } if err := rows.Err(); err != nil { - log.Print(err) + logrus.Error(err) } return savedMessages } diff --git a/tool.go b/tool.go index d328ec0..9cb3b12 100644 --- a/tool.go +++ b/tool.go @@ -1,14 +1,16 @@ package main import ( + "embed" "encoding/json" "fmt" - "log" - "os" + "io" + "net/http" "strconv" "strings" "github.com/bwmarrin/discordgo" + "github.com/sirupsen/logrus" ) type ModalJsonField struct { @@ -58,33 +60,47 @@ func jsonStringShowModal(interaction *discordgo.Interaction, manageID string, fo if overwrite[0] != "" { modal.Title = overwrite[0] } - err := bot.InteractionRespond(interaction, &discordgo.InteractionResponse{ - Type: discordgo.InteractionResponseModal, - Data: &discordgo.InteractionResponseData{ - CustomID: manageID + ":" + interaction.Member.User.ID, - Title: modal.Title, - Components: components, - }, - }) + var err error + if components != nil { + err = bot.InteractionRespond(interaction, &discordgo.InteractionResponse{ + Type: discordgo.InteractionResponseModal, + Data: &discordgo.InteractionResponseData{ + CustomID: manageID + ":" + interaction.Member.User.ID, + Title: modal.Title, + Components: components, + }, + }) + } if err != nil { - log.Print(err) + logrus.Error(err) } } +// Why does the golang compiler care about commands?? +// +//go:embed form_templates/*.json +var formTemplates embed.FS + func getModalByFormID(formID string) ModalJson { var modal ModalJson - //TODO: add custom forms - entries, err := os.ReadDir("./form_templates") + entries, err := formTemplates.ReadDir("form_templates") if err != nil { - log.Print(err) + logrus.Error(err) + return modal } for _, entry := range entries { if strings.HasPrefix(entry.Name(), formID) { - json_file, err := os.ReadFile("./form_templates/" + entry.Name()) + jsonFile, err := formTemplates.ReadFile("form_templates/" + entry.Name()) if err != nil { - log.Print(err) + logrus.Error(err) + continue } - json.Unmarshal(json_file, &modal) + err = json.Unmarshal(jsonFile, &modal) + if err != nil { + logrus.Error(err) + continue + } + break } } return modal @@ -128,26 +144,55 @@ func hexToDecimal(hexColor string) int { return int(decimal) } -func respond(interaction *discordgo.Interaction, content string, ephemeral bool) { +func simpleGetFromAPI(key string, url string) interface{} { + client := &http.Client{} + req, err := http.NewRequest("GET", url, nil) + if err != nil { + logrus.Error("Error creating request:", err) + } + req.Header.Set("Accept", "application/json") + resp, err := client.Do(req) + if err != nil { + logrus.Error("Error making request:", err) + } + defer resp.Body.Close() + body, err := io.ReadAll(resp.Body) + if err != nil { + logrus.Error("Error reading response body:", err) + } + + var result map[string]interface{} + err = json.Unmarshal(body, &result) + if err != nil { + logrus.Error("Error decoding JSON:", err) + } + return result[key] +} + +func respond(interaction *discordgo.Interaction, content string, ephemeral bool) error { var flag discordgo.MessageFlags if ephemeral { flag = discordgo.MessageFlagsEphemeral } - bot.InteractionRespond(interaction, &discordgo.InteractionResponse{ + err := bot.InteractionRespond(interaction, &discordgo.InteractionResponse{ Type: discordgo.InteractionResponseChannelMessageWithSource, Data: &discordgo.InteractionResponseData{ Content: content, Flags: flag, }, }) + if err != nil { + return err + } + return nil } -func respondEmbed(interaction *discordgo.Interaction, embed discordgo.MessageEmbed, ephemeral bool) { +func respondEmbed(interaction *discordgo.Interaction, embed discordgo.MessageEmbed, ephemeral bool) error { var flag discordgo.MessageFlags if ephemeral { flag = discordgo.MessageFlagsEphemeral } - bot.InteractionRespond(interaction, &discordgo.InteractionResponse{ + err := bot.InteractionRespond(interaction, &discordgo.InteractionResponse{ Type: discordgo.InteractionResponseChannelMessageWithSource, Data: &discordgo.InteractionResponseData{ Flags: flag, @@ -156,6 +201,10 @@ func respondEmbed(interaction *discordgo.Interaction, embed discordgo.MessageEmb }, }, }) + if err != nil { + return err + } + return nil } func findAndDeleteUnusedMessages() {