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) } }