package main import ( "context" "embed" "fmt" "log" _ "net/http/pprof" "os" "github.com/apenwarr/fixconsole" jsoniter "github.com/json-iterator/go" "github.com/urfave/cli/v2" "github.com/wailsapp/wails/v2" "github.com/wailsapp/wails/v2/pkg/options" "github.com/wailsapp/wails/v2/pkg/options/assetserver" "github.com/wailsapp/wails/v2/pkg/runtime" "go.uber.org/zap" "go.uber.org/zap/zapcore" "github.com/strimertul/strimertul/utils" ) var json = jsoniter.ConfigFastest var appVersion = "v0.0.0-UNKNOWN" //go:embed frontend/dist var frontend embed.FS func main() { err := fixconsole.FixConsoleIfNeeded() if err != nil { log.Fatal(err) } var panicLog *os.File app := &cli.App{ Name: "strimertul", Usage: "the small broadcasting suite for Twitch", Version: appVersion, Action: cliMain, Flags: []cli.Flag{ &cli.StringFlag{Name: "log-level", Usage: "logging level (debug,info,warn,error)", Value: "info"}, &cli.StringFlag{Name: "driver", Usage: "specify database driver", Value: "auto"}, &cli.StringFlag{Name: "database-dir", Aliases: []string{"db-dir"}, Usage: "specify database directory", Value: "data"}, &cli.StringFlag{Name: "backup-dir", Aliases: []string{"b-dir"}, Usage: "specify backup directory", Value: "backups"}, &cli.IntFlag{Name: "backup-interval", Aliases: []string{"b-i"}, Usage: "specify backup interval (in minutes, 0 to disable)", Value: 60}, &cli.IntFlag{Name: "max-backups", Aliases: []string{"b-max"}, Usage: "maximum number of backups to keep, older ones will be deleted, set to 0 to keep all", Value: 20}, }, Commands: []*cli.Command{ { Name: "import", Usage: "import database from JSON file", ArgsUsage: "[-f input.json]", Flags: []cli.Flag{ &cli.StringFlag{Name: "file", Aliases: []string{"f"}, Usage: "file to open", DefaultText: "STDIN"}, }, Action: cliImport, }, { Name: "export", Usage: "export database as JSON file", ArgsUsage: "[-f output.json]", Flags: []cli.Flag{ &cli.StringFlag{Name: "file", Aliases: []string{"f"}, Usage: "file to save to", DefaultText: "STDOUT"}, }, Action: cliExport, }, { Name: "restore", Usage: "restore database from backup", ArgsUsage: "[-f backup.db]", Flags: []cli.Flag{ &cli.StringFlag{Name: "file", Aliases: []string{"f"}, Usage: "backup to open", DefaultText: "STDOUT"}, }, Action: cliRestore, }, }, Before: func(ctx *cli.Context) error { // Initialize logger with global flags level, err := zapcore.ParseLevel(ctx.String("log-level")) if err != nil { level = zapcore.InfoLevel } initLogger(level) // Create file for panics panicLog, err = os.OpenFile("strimertul-panic.log", os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0o666) if err != nil { logger.Warn("could not create panic log", zap.Error(err)) } else { utils.RedirectStderr(panicLog) } zap.RedirectStdLog(logger)() ctx.Context = context.WithValue(ctx.Context, utils.ContextLogger, logger) return nil }, After: func(ctx *cli.Context) error { if panicLog != nil { utils.Close(panicLog, logger) } _ = logger.Sync() return nil }, } if err := app.Run(os.Args); err != nil { log.Fatal(err) } } func cliMain(ctx *cli.Context) error { // Create an instance of the app structure app := NewApp(ctx) // Create application with options err := wails.Run(&options.App{ Title: "strimertul", Width: 1024, Height: 768, AssetServer: &assetserver.Options{ Assets: frontend, }, BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, OnStartup: app.startup, OnShutdown: app.stop, OnBeforeClose: func(ctx context.Context) (prevent bool) { dialog, err := runtime.MessageDialog(ctx, runtime.MessageDialogOptions{ Type: runtime.QuestionDialog, Title: "Quit?", Message: "Are you sure you want to quit?", }) if err != nil { return false } return dialog != "Yes" }, Bind: []interface{}{ app, }, }) if err != nil { return cli.Exit(fmt.Errorf("%s: %w", "App exited unexpectedly", err), 1) } return nil } func warnOnError(err error, text string, fields ...zap.Field) { if err != nil { fields = append(fields, zap.Error(err)) logger.Warn(text, fields...) } } func failOnError(err error, text string, fields ...zap.Field) { if err != nil { fields = append(fields, zap.Error(err)) logger.Fatal(text, fields...) } } func fatalError(err error, text string) error { return cli.Exit(fmt.Errorf("%s: %w", text, err), 1) }