2021-05-02 12:29:43 +00:00
package main
import (
2022-12-03 15:16:59 +00:00
"context"
2021-05-02 12:29:43 +00:00
"embed"
"fmt"
2024-03-16 00:20:15 +00:00
corelog "log"
2024-03-14 12:33:52 +00:00
"log/slog"
2023-02-17 18:18:44 +00:00
_ "net/http/pprof"
2022-01-02 10:45:09 +00:00
"os"
2024-03-14 12:33:52 +00:00
"runtime/debug"
2021-05-02 12:29:43 +00:00
2024-03-16 00:20:15 +00:00
"git.sr.ht/~ashkeel/strimertul/log"
2024-03-14 12:33:52 +00:00
"git.sr.ht/~ashkeel/strimertul/utils"
2022-11-25 19:56:48 +00:00
"github.com/apenwarr/fixconsole"
2022-11-16 11:23:54 +00:00
"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"
2023-01-26 12:18:38 +00:00
"github.com/wailsapp/wails/v2/pkg/runtime"
2021-05-02 12:29:43 +00:00
)
2024-03-14 12:33:52 +00:00
const devVersionMarker = "v0.0.0-UNKNOWN"
var appVersion = devVersionMarker
2021-12-06 13:47:38 +00:00
2023-04-14 18:04:21 +00:00
const (
crashReportURL = "https://crash.strimertul.stream/upload"
)
2022-11-25 18:07:11 +00:00
//go:embed frontend/dist
2021-05-02 12:29:43 +00:00
var frontend embed . FS
func main ( ) {
2024-03-14 12:33:52 +00:00
if err := fixconsole . FixConsoleIfNeeded ( ) ; err != nil {
2024-03-16 00:20:15 +00:00
corelog . Fatal ( err )
2022-11-25 19:56:48 +00:00
}
2023-03-09 11:41:50 +00:00
var panicLog * os . File
2022-11-16 11:23:54 +00:00
app := & cli . App {
Name : "strimertul" ,
Usage : "the small broadcasting suite for Twitch" ,
Version : appVersion ,
Action : cliMain ,
Flags : [ ] cli . Flag {
2022-11-24 12:15:59 +00:00
& cli . StringFlag { Name : "log-level" , Usage : "logging level (debug,info,warn,error)" , Value : "info" } ,
2022-11-16 11:23:54 +00:00
& 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
2024-03-14 12:33:52 +00:00
level := slog . LevelInfo
if err := level . UnmarshalText ( [ ] byte ( ctx . String ( "log-level" ) ) ) ; err != nil {
return cli . Exit ( fmt . Sprintf ( "Invalid log level: %s" , err ) , 1 )
2022-11-24 12:15:59 +00:00
}
2024-03-16 00:20:15 +00:00
log . Init ( level )
2023-03-09 11:41:50 +00:00
// Create file for panics
2024-03-14 12:33:52 +00:00
var err error
2024-03-16 00:20:15 +00:00
panicLog , err = os . OpenFile ( log . PanicFilename , os . O_APPEND | os . O_WRONLY | os . O_CREATE , 0 o666 )
2023-03-09 11:41:50 +00:00
if err != nil {
2024-03-16 00:20:15 +00:00
slog . Warn ( "Could not create panic log" , log . Error ( err ) )
2023-03-09 11:41:50 +00:00
} else {
utils . RedirectStderr ( panicLog )
}
2024-03-14 12:33:52 +00:00
// For development builds, force crash dumps
if isDev ( ) {
debug . SetTraceback ( "crash" )
}
2023-03-09 11:41:50 +00:00
2022-11-16 11:23:54 +00:00
return nil
} ,
2024-02-25 13:58:35 +00:00
After : func ( _ * cli . Context ) error {
2023-03-09 11:41:50 +00:00
if panicLog != nil {
2024-03-14 12:33:52 +00:00
utils . Close ( panicLog )
2023-03-09 11:41:50 +00:00
}
2022-11-16 11:23:54 +00:00
return nil
} ,
}
if err := app . Run ( os . Args ) ; err != nil {
2024-03-16 00:20:15 +00:00
corelog . Fatal ( err )
2022-11-16 11:23:54 +00:00
}
}
func cliMain ( ctx * cli . Context ) error {
// Create an instance of the app structure
2022-11-18 16:37:30 +00:00
app := NewApp ( ctx )
2022-11-16 11:23:54 +00:00
// Create application with options
2022-11-18 16:37:30 +00:00
err := wails . Run ( & options . App {
2023-11-13 17:44:02 +00:00
Title : "strimertul" ,
Width : 1024 ,
Height : 768 ,
MinWidth : 480 ,
MinHeight : 300 ,
2022-11-16 11:23:54 +00:00
AssetServer : & assetserver . Options {
Assets : frontend ,
} ,
2024-02-23 08:56:19 +00:00
SingleInstanceLock : & options . SingleInstanceLock {
UniqueId : "d1272ae3-765a-4768-97cb-3203b788e7c5" ,
OnSecondInstanceLaunch : app . onSecondInstanceLaunch ,
} ,
2023-11-05 11:51:25 +00:00
EnableDefaultContextMenu : true ,
BackgroundColour : & options . RGBA { R : 27 , G : 38 , B : 54 , A : 1 } ,
OnStartup : app . startup ,
OnShutdown : app . stop ,
2023-01-26 12:18:38 +00:00
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"
} ,
2023-04-23 00:59:30 +00:00
Bind : [ ] any {
2022-11-16 11:23:54 +00:00
app ,
} ,
} )
if err != nil {
2022-11-18 16:37:30 +00:00
return cli . Exit ( fmt . Errorf ( "%s: %w" , "App exited unexpectedly" , err ) , 1 )
2022-11-16 11:23:54 +00:00
}
return nil
}
2021-05-02 12:29:43 +00:00
2024-03-14 12:33:52 +00:00
func warnOnError ( err error , text string , fields ... any ) {
2021-05-02 12:29:43 +00:00
if err != nil {
2024-03-16 00:20:15 +00:00
fields = append ( fields , log . Error ( err ) )
2024-03-14 12:33:52 +00:00
slog . Warn ( text , fields ... )
2022-12-02 22:52:45 +00:00
}
}
2022-11-18 16:37:30 +00:00
func fatalError ( err error , text string ) error {
return cli . Exit ( fmt . Errorf ( "%s: %w" , text , err ) , 1 )
}
2024-03-14 12:33:52 +00:00
// isDev checks if the running code is a development version
func isDev ( ) bool {
return appVersion == devVersionMarker
}