twitch-bot-streak/main.go

126 lines
3.2 KiB
Go

package main
import (
"bytes"
_ "embed"
"encoding/json"
"os"
"regexp"
"text/template"
"time"
"git.luzifer.io/luzifer/twitch-bot-streak/pkg/database"
_ "github.com/go-sql-driver/mysql"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/Luzifer/rconfig/v2"
)
type (
botResponse struct {
Type string `json:"type"`
Attributes map[string]any `json:"attributes"`
}
)
var (
cfg = struct {
Action string `flag:"action,a" description:"Which action to perform"`
TwitchID uint64 `flag:"twitch-id" description:"ID of the user to access the streak of"`
TwitchUsername string `flag:"twitch-username" description:"Username of the user to update in streaks table"`
StreamOfflineGrace time.Duration `flag:"stream-offline-grace" default:"30m" description:"How long to not start a new stream after previous went offline"`
StorageConnString string `flag:"storage-conn-string" default:"./storage.db" description:"Connection string for the database"`
StorageConnType string `flag:"storage-conn-type" default:"sqlite" description:"One of: mysql, postgres, sqlite"`
LogLevel string `flag:"log-level" default:"info" description:"Log level (debug, info, warn, error, fatal)"`
VersionAndExit bool `flag:"version" default:"false" description:"Prints current version and exits"`
}{}
version = "dev"
//go:embed message.tpl
messageTemplate string
)
func initApp() error {
rconfig.AutoEnv(true)
if err := rconfig.ParseAndValidate(&cfg); err != nil {
return errors.Wrap(err, "parsing cli options")
}
l, err := logrus.ParseLevel(cfg.LogLevel)
if err != nil {
return errors.Wrap(err, "parsing log-level")
}
logrus.SetLevel(l)
return nil
}
func main() {
var err error
if err = initApp(); err != nil {
logrus.WithError(err).Fatal("initializing app")
}
if cfg.VersionAndExit {
logrus.WithField("version", version).Info("twitch-bot-streak")
os.Exit(0)
}
tpl, err := template.New("tpl").Parse(messageTemplate)
if err != nil {
logrus.WithError(err).Fatal("parsing message template")
}
db, err := database.New(cfg.StorageConnType, cfg.StorageConnString)
if err != nil {
logrus.WithError(err).Fatal("connecting to database")
}
switch cfg.Action {
case "stream_start":
if err = db.StartStream(cfg.StreamOfflineGrace); err != nil {
logrus.WithError(err).Fatal("starting stream")
}
case "stream_offline":
if err = db.SetStreamOffline(); err != nil {
logrus.WithError(err).Fatal("stopping stream")
}
case "count_stream":
if err = db.StartStream(cfg.StreamOfflineGrace); err != nil {
logrus.WithError(err).Fatal("starting stream")
}
user, err := db.CountStreak(cfg.TwitchID, cfg.TwitchUsername)
if err != nil {
logrus.WithError(err).Fatal("counting streak")
}
buf := new(bytes.Buffer)
if err = tpl.Execute(buf, user); err != nil {
logrus.WithError(err).Fatal("rendering template")
}
msg := regexp.MustCompile(`\s+`).ReplaceAllString(buf.String(), " ")
if err = json.NewEncoder(os.Stdout).Encode([]botResponse{
{
Type: "respond",
Attributes: map[string]any{
"message": msg,
},
},
}); err != nil {
logrus.WithError(err).Fatal("encoding bot response")
}
default:
logrus.Fatalf("unknown action %q", cfg.Action)
}
}