~xenrox/twitch-bot

f2dc645d03cf3625220cf5b15edbb6c5e7230802 — Thorben Günther 8 months ago 8d66c04
Use "log/slog" for logging
6 files changed, 46 insertions(+), 23 deletions(-)

M bot.go
M config.go
M go.mod
M go.sum
M main.go
M static_commands.go
M bot.go => bot.go +7 -4
@@ 2,9 2,9 @@ package main

import (
	"errors"
	"log/slog"
	"os"

	"git.xenrox.net/~xenrox/go-log"
	"git.xenrox.net/~xenrox/twitch-bot/database"
	"github.com/gempir/go-twitch-irc/v3"
)


@@ 15,7 15,7 @@ type bot struct {
	client *twitch.Client
	cfg    *config
	db     *database.DB
	logger *log.Logger
	logger *slog.Logger
}

func (b *bot) isAuthorized(user *twitch.User, channel string) bool {


@@ 33,10 33,13 @@ func (b *bot) say(msg *twitch.PrivateMessage, text string) {
}

func (b *bot) shutdown(sig os.Signal) {
	b.logger.Info("Shutting down")
	if err := b.client.Disconnect(); err != nil {
		b.logger.Errorf("shutdown: %v", err)
		b.logger.Error("Failed to disconnect",
			slog.String("error", err.Error()))
	}
	if err := b.db.Close(); err != nil {
		b.logger.Errorf("shutdown: %v", err)
		b.logger.Error("Failed to close database connection",
			slog.String("error", err.Error()))
	}
}

M config.go => config.go +1 -4
@@ 4,7 4,6 @@ import (
	"fmt"

	"git.sr.ht/~emersion/go-scfg"
	"git.xenrox.net/~xenrox/go-log"
)

type config struct {


@@ 21,7 20,7 @@ type channel struct {
	ModsAreAdmins bool
}

func readConfig(path string, logger *log.Logger) (*config, error) {
func readConfig(path string) (*config, error) {
	cfg, err := scfg.Load(path)
	if err != nil {
		return nil, err


@@ 58,8 57,6 @@ func readConfig(path string, logger *log.Logger) (*config, error) {
		if err := d.ParseParams(&config.FaceitAPIKey); err != nil {
			return nil, err
		}
	} else {
		logger.Warningf("Faceit: No API key found. Faceit support disabled.")
	}

	config.LogLevel = "info"

M go.mod => go.mod +1 -1
@@ 4,7 4,7 @@ go 1.21.0

require (
	git.sr.ht/~emersion/go-scfg v0.0.0-20211215104734-c2c7a15d6c99
	git.xenrox.net/~xenrox/go-log v0.0.0-20221009010407-dfed95a0aeee
	git.xenrox.net/~xenrox/go-utils v0.0.0-20230813142628-a8bdc9211a98
	github.com/gempir/go-twitch-irc/v3 v3.2.0
	github.com/lib/pq v1.10.7
)

M go.sum => go.sum +2 -2
@@ 1,7 1,7 @@
git.sr.ht/~emersion/go-scfg v0.0.0-20211215104734-c2c7a15d6c99 h1:1s8n5uisqkR+BzPgaum6xxIjKmzGrTykJdh+Y3f5Xao=
git.sr.ht/~emersion/go-scfg v0.0.0-20211215104734-c2c7a15d6c99/go.mod h1:t+Ww6SR24yYnXzEWiNlOY0AFo5E9B73X++10lrSpp4U=
git.xenrox.net/~xenrox/go-log v0.0.0-20221009010407-dfed95a0aeee h1:LE8pzV95yjK3VIOBZSFcWeKe4xxUVEHbxPA5uH2dvBk=
git.xenrox.net/~xenrox/go-log v0.0.0-20221009010407-dfed95a0aeee/go.mod h1:d98WFDHGpxaEThKue5CfGtr9OrWgbaApprt3GH+OM4s=
git.xenrox.net/~xenrox/go-utils v0.0.0-20230813142628-a8bdc9211a98 h1:c6B8yMLiPWj8Fqp3AeLBB86gKhdz2hfgAupaNpmMRMo=
git.xenrox.net/~xenrox/go-utils v0.0.0-20230813142628-a8bdc9211a98/go.mod h1:BM4sMPD0fqFB6eG1T/7rGgEUiqZsMpHvq4PGE861Sfk=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gempir/go-twitch-irc/v3 v3.2.0 h1:ENhsa7RgBE1GMmDqe0iMkvcSYfgw6ZsXilt+sAg32/U=

M main.go => main.go +23 -9
@@ 3,12 3,13 @@ package main
import (
	"errors"
	"flag"
	"log/slog"
	"os"
	"os/signal"
	"strings"
	"syscall"

	"git.xenrox.net/~xenrox/go-log"
	"git.xenrox.net/~xenrox/go-utils/logging"
	"git.xenrox.net/~xenrox/twitch-bot/database"
	"github.com/gempir/go-twitch-irc/v3"
)


@@ 21,20 22,29 @@ func main() {
	sigs := make(chan os.Signal, 1)
	signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)

	logger := log.NewDefaultLogger()
	cfg, err := readConfig(configPath)
	if err != nil {
		slog.Error("Failed to read config",
			slog.String("error", err.Error()))
		os.Exit(1)
	}

	cfg, err := readConfig(configPath, logger)
	logger, err := logging.New(cfg.LogLevel, "text", os.Stderr)
	if err != nil {
		logger.Fatalf("config: %v", err)
		slog.Error("Failed to create logger",
			slog.String("error", err.Error()))
		os.Exit(1)
	}

	if err := logger.ParseLevel(cfg.LogLevel); err != nil {
		logger.Errorf("config: %v", err)
	if cfg.FaceitAPIKey == "" {
		logger.Warn("No Faceit API key found, disabling Faceit support.")
	}

	db, err := database.Open(cfg.DBConnectionString)
	if err != nil {
		logger.Fatalf("database: %v", err)
		logger.Error("Failed to open database connection",
			slog.String("error", err.Error()))
		os.Exit(1)
	}

	client := twitch.NewClient(cfg.UserName, cfg.Token)


@@ 63,7 73,10 @@ func main() {
			} else if errors.Is(err, errTooShort) {
				bot.say(&message, "The command you entered is too short.")
			} else if err != nil {
				logger.Errorf("Channel %q: Command %v failed: %v", message.Channel, parsed, err)
				logger.Error("Failed to execute command",
					slog.String("channel", message.Channel),
					slog.String("command", message.Message),
					slog.String("error", err.Error()))
			}
		}
	})


@@ 75,7 88,8 @@ func main() {
	go func() {
		err = client.Connect()
		if err != nil {
			logger.Fatalf("connecting: %v", err)
			logger.Error("Failed to connect",
				slog.String("error", err.Error()))
		}
	}()


M static_commands.go => static_commands.go +12 -3
@@ 4,6 4,7 @@ import (
	"database/sql"
	"errors"
	"fmt"
	"log/slog"
	"slices"
	"strings"



@@ 82,7 83,10 @@ func (b *bot) handleCommands(parsed []string, msg *twitch.PrivateMessage) error 
			}

			b.say(msg, "Success.")
			b.logger.Infof("Channel %q: %q updated command %q", msg.Channel, msg.User.DisplayName, name)
			b.logger.Info("Successfully updated command",
				slog.String("channel", msg.Channel),
				slog.String("command", name),
				slog.String("user", msg.User.DisplayName))
			return nil
		}
	}


@@ 112,7 116,10 @@ func (b *bot) handleCommands(parsed []string, msg *twitch.PrivateMessage) error 
		}

		b.say(msg, "Success.")
		b.logger.Infof("Channel %q: %q deleted command %q", msg.Channel, msg.User.DisplayName, name)
		b.logger.Info("Successfully deleted command",
			slog.String("channel", msg.Channel),
			slog.String("command", name),
			slog.String("user", msg.User.DisplayName))
		return nil
	}



@@ 130,7 137,9 @@ func (b *bot) lookupCommand(name string, msg *twitch.PrivateMessage) error {

	err := b.db.DB.QueryRow(query, msg.Channel, name).Scan(&response)
	if errors.Is(err, sql.ErrNoRows) {
		b.logger.Infof("Channel %q: Command %q not found", msg.Channel, name)
		b.logger.Info("Command not found",
			slog.String("channel", msg.Channel),
			slog.String("command", name))
		return nil
	} else if err != nil {
		return err