Skip to content

Commit

Permalink
Add option to recover from panics
Browse files Browse the repository at this point in the history
  • Loading branch information
xoltia committed Nov 7, 2023
1 parent 95b1dfb commit 5680c25
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 9 deletions.
23 changes: 17 additions & 6 deletions cmd/botsu/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"log/slog"
"net/url"
"os"
"slices"
"strings"

"github.com/pelletier/go-toml/v2"
Expand All @@ -19,6 +18,7 @@ type Config struct {
Token string `toml:"token"`
UseMembersIntent bool `toml:"use_members_intent"`
LogLevel slog.Level `toml:"log_level"`
NoPanic bool `toml:"no_panic"`
}

type DatabaseConfig struct {
Expand Down Expand Up @@ -109,11 +109,7 @@ func (c *Config) LoadEnv() error {
useMembersIntent, ok := os.LookupEnv("BOTSU_USE_MEMBERS_INTENT")

if ok {
c.UseMembersIntent = slices.Contains([]string{
"t",
"true",
"1",
}, strings.ToLower(useMembersIntent))
c.UseMembersIntent = stringToTruthy(useMembersIntent)
}

logLevel, ok := os.LookupEnv("BOTSU_LOG_LEVEL")
Expand All @@ -124,6 +120,12 @@ func (c *Config) LoadEnv() error {
}
}

noPanic, ok := os.LookupEnv("BOTSU_NO_PANIC")

if ok {
c.NoPanic = stringToTruthy(noPanic)
}

return nil
}

Expand All @@ -142,3 +144,12 @@ func (c *Config) Load(path string) error {

return nil
}

func stringToTruthy(s string) bool {
switch strings.ToLower(s) {
case "true", "t", "1", "yes", "y":
return true
default:
return false
}
}
1 change: 1 addition & 0 deletions cmd/botsu/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,7 @@ func main() {
guildRepo := guilds.NewGuildRepository(pool)

bot := bot.NewBot(logger.WithGroup("bot"), guildRepo)
bot.SetNoPanic(config.NoPanic)

bot.AddCommand(commands.LogCommandData, commands.NewLogCommand(activityRepo, userRepo, guildRepo, searcher, vnSearcher))
bot.AddCommand(commands.ConfigCommandData, commands.NewConfigCommand(userRepo, activityRepo))
Expand Down
3 changes: 1 addition & 2 deletions cmd/botsu/usage.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,9 @@ func init() {
fmt.Fprintln(flag.CommandLine.Output(), " BOTSU_ANIDB_DUMP_PATH: Path to anidb dump")
fmt.Fprintln(flag.CommandLine.Output(), " BOTSU_VNDB_DUMP_PATH: Path to vndb dump")
fmt.Fprintln(flag.CommandLine.Output(), " BOTSU_USE_MEMBERS_INTENT: Whether to use the members intent")
fmt.Fprintln(flag.CommandLine.Output(), " BOTSU_NO_PANIC: Whether to recover from panics caused by command handlers")

fmt.Fprintln(flag.CommandLine.Output(), "\nConfig file:")
fmt.Fprintln(flag.CommandLine.Output(), "The config file is a TOML file with the following structure:")
fmt.Fprintln(flag.CommandLine.Output())
printTOMLStructure(
&prefixedWriter{w: flag.CommandLine.Output(), prefix: []byte(" ")},
NewConfig(),
Expand Down
22 changes: 21 additions & 1 deletion internal/bot/bot.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package bot
import (
"context"
"log/slog"
"runtime/debug"

"github.com/UTD-JLA/botsu/internal/guilds"
"github.com/bwmarrin/discordgo"
Expand All @@ -19,6 +20,7 @@ type Bot struct {
createdCommands []*discordgo.ApplicationCommand
destroyOnClose bool
guildRepo *guilds.GuildRepository
noPanic bool
}

func NewBot(logger *slog.Logger, guildRepo *guilds.GuildRepository) *Bot {
Expand Down Expand Up @@ -58,11 +60,24 @@ func (b *Bot) onInteractionCreate(s *discordgo.Session, i *discordgo.Interaction

defer ctx.Cancel()

if b.noPanic {
defer func() {
if r := recover(); r != nil {
stack := debug.Stack()
ctx.Logger.Error("Panic occurred", slog.Any("panic", r), slog.Any("stack", string(stack)))
_, err := ctx.RespondOrFollowup(unexpectedErrorMessage, false)

if err != nil {
ctx.Logger.Error("Failed to send error message", slog.String("err", err.Error()))
}
}
}()
}

err := b.commands.Handle(ctx)
if err != nil {
ctx.Logger.Error("Failed to handle interaction", slog.String("err", err.Error()))

// if this is a command, and we haven't responded yet, respond with an error
if ctx.IsCommand() {
_, err = ctx.RespondOrFollowup(unexpectedErrorMessage, false)

Expand All @@ -81,6 +96,11 @@ func (b *Bot) onMemberRemove(s *discordgo.Session, m *discordgo.GuildMemberRemov
}
}

func (b *Bot) SetNoPanic(noPanic bool) {
b.logger.Debug("Setting no panic", slog.Bool("no_panic", noPanic))
b.noPanic = noPanic
}

func (b *Bot) SetDestroyCommandsOnClose(destroy bool) {
b.logger.Debug("Setting destroy commands on close", slog.Bool("destroy", destroy))
b.destroyOnClose = destroy
Expand Down

0 comments on commit 5680c25

Please sign in to comment.