2021-05-02 12:29:43 +00:00
package main
import (
2021-11-19 18:37:42 +00:00
"context"
2021-05-02 12:29:43 +00:00
"embed"
2021-11-19 18:37:42 +00:00
"errors"
2021-05-02 12:29:43 +00:00
"flag"
"fmt"
"io/fs"
2021-09-18 20:06:22 +00:00
"math/rand"
2021-05-02 19:33:37 +00:00
"runtime"
2021-05-02 12:29:43 +00:00
"time"
"github.com/strimertul/strimertul/modules"
2021-11-23 10:34:02 +00:00
"github.com/strimertul/strimertul/modules/database"
"github.com/strimertul/strimertul/modules/http"
2021-05-02 12:29:43 +00:00
"github.com/strimertul/strimertul/modules/loyalty"
2021-05-14 14:37:54 +00:00
"github.com/strimertul/strimertul/modules/stulbe"
2021-05-14 11:15:38 +00:00
"github.com/strimertul/strimertul/modules/twitch"
2021-05-02 12:29:43 +00:00
"github.com/dgraph-io/badger/v3"
2021-05-02 19:33:37 +00:00
"github.com/mattn/go-colorable"
2021-11-23 10:34:02 +00:00
"github.com/pkg/browser"
2021-05-02 19:33:37 +00:00
"github.com/sirupsen/logrus"
2021-06-05 23:18:31 +00:00
_ "net/http/pprof"
2021-05-02 12:29:43 +00:00
)
const AppTitle = "strimertül"
const AppHeader = `
_ _ _ O O _
__ | | _ _ _ ( _ ) _ __ ___ _ _ | | _ _ _ | |
( _ - < _ | ' _ | | ' \ / - _ ) ' _ | _ | || | |
/ __ / \ __ | _ | | _ | _ | _ | _ \ ___ | _ | \ __ | \ _ , _ | _ | `
const DefaultBind = "localhost:4337"
//go:embed frontend/dist/*
var frontend embed . FS
2021-05-02 19:33:37 +00:00
var log = logrus . New ( )
func parseLogLevel ( level string ) logrus . Level {
switch level {
case "error" :
return logrus . ErrorLevel
case "warn" , "warning" :
return logrus . WarnLevel
case "info" , "notice" :
return logrus . InfoLevel
case "debug" :
return logrus . DebugLevel
case "trace" :
return logrus . TraceLevel
default :
return logrus . InfoLevel
2021-05-02 12:29:43 +00:00
}
}
func main ( ) {
2021-05-02 19:33:37 +00:00
// Get cmd line parameters
2021-11-23 10:34:02 +00:00
noheader := flag . Bool ( "noheader" , false , "Do not print the app header" )
dbdir := flag . String ( "dbdir" , "data" , "Path to strimertül database dir" )
2021-05-02 19:33:37 +00:00
loglevel := flag . String ( "loglevel" , "info" , "Logging level (debug, info, warn, error)" )
2021-05-02 12:29:43 +00:00
flag . Parse ( )
2021-09-18 20:06:22 +00:00
rand . Seed ( time . Now ( ) . UnixNano ( ) )
2021-05-02 19:33:37 +00:00
log . SetLevel ( parseLogLevel ( * loglevel ) )
// Ok this is dumb but listen, I like colors.
if runtime . GOOS == "windows" {
log . SetFormatter ( & logrus . TextFormatter { ForceColors : true } )
log . SetOutput ( colorable . NewColorableStdout ( ) )
}
2021-11-23 10:34:02 +00:00
if ! * noheader {
// Print the app header :D
fmt . Println ( AppHeader )
}
// Create module manager
manager := modules . NewManager ( log )
2021-05-02 12:29:43 +00:00
// Loading routine
2021-11-23 10:34:02 +00:00
db , err := database . Open ( badger . DefaultOptions ( * dbdir ) , manager )
2021-05-02 12:29:43 +00:00
failOnError ( err , "Could not open DB" )
2021-11-23 10:34:02 +00:00
defer db . Close ( )
2021-05-02 12:29:43 +00:00
// Check if onboarding was completed
var moduleConfig modules . ModuleConfig
2021-05-10 21:09:15 +00:00
err = db . GetJSON ( modules . ModuleConfigKey , & moduleConfig )
2021-05-02 12:29:43 +00:00
if err != nil {
2021-11-19 18:37:42 +00:00
if errors . Is ( err , badger . ErrKeyNotFound ) {
2021-05-02 12:29:43 +00:00
moduleConfig = modules . ModuleConfig { CompletedOnboarding : false }
} else {
fatalError ( err , "Could not read from DB" )
}
}
2021-11-23 10:34:02 +00:00
// Bootstrap if needed
2021-05-02 12:29:43 +00:00
if ! moduleConfig . CompletedOnboarding {
// Initialize DB as empty and default endpoint
2021-11-19 18:37:42 +00:00
failOnError ( db . PutJSON ( http . ServerConfigKey , http . ServerConfig {
2021-05-10 21:09:15 +00:00
Bind : DefaultBind ,
} ) , "could not save http config" )
failOnError ( db . PutJSON ( modules . ModuleConfigKey , modules . ModuleConfig {
2021-05-14 11:15:38 +00:00
EnableTwitch : false ,
2021-05-10 21:09:15 +00:00
EnableStulbe : false ,
CompletedOnboarding : true ,
} ) , "could not save onboarding config" )
2021-05-02 12:29:43 +00:00
fmt . Printf ( "It appears this is your first time running %s! Please go to http://%s and make sure to configure anything you want!\n\n" , AppTitle , DefaultBind )
}
// Get Stulbe config, if enabled
if moduleConfig . EnableStulbe {
2021-11-23 10:34:02 +00:00
stulbeManager , err := stulbe . Initialize ( manager )
2021-05-07 16:36:23 +00:00
if err != nil {
2021-11-23 10:34:02 +00:00
log . WithError ( err ) . Error ( "Stulbe initialization failed!" )
2021-05-18 13:53:17 +00:00
} else {
defer stulbeManager . Close ( )
2021-05-07 16:36:23 +00:00
}
2021-05-02 12:29:43 +00:00
}
if moduleConfig . EnableLoyalty {
2021-11-23 10:34:02 +00:00
loyaltyManager , err := loyalty . NewManager ( manager )
2021-05-02 12:29:43 +00:00
if err != nil {
2021-11-23 10:34:02 +00:00
log . WithError ( err ) . Error ( "Loyalty initialization failed!" )
} else {
defer loyaltyManager . Close ( )
2021-05-14 14:37:54 +00:00
}
2021-05-02 12:29:43 +00:00
}
2021-05-14 11:15:38 +00:00
if moduleConfig . EnableTwitch {
// Create Twitch client
2021-11-23 10:34:02 +00:00
twitchModule , err := twitch . NewClient ( manager )
2021-11-19 18:37:42 +00:00
if err != nil {
2021-11-23 10:34:02 +00:00
log . WithError ( err ) . Error ( "Twitch initialization failed!" )
2021-11-19 18:37:42 +00:00
} else {
2021-11-23 10:34:02 +00:00
defer twitchModule . Close ( )
2021-05-02 12:29:43 +00:00
}
}
// Create logger and endpoints
2021-11-23 10:34:02 +00:00
httpServer , err := http . NewServer ( manager )
2021-11-19 18:37:42 +00:00
failOnError ( err , "Could not initialize http server" )
2021-11-23 10:34:02 +00:00
defer httpServer . Close ( )
2021-05-02 12:29:43 +00:00
fedir , _ := fs . Sub ( frontend , "frontend/dist" )
2021-11-19 18:37:42 +00:00
httpServer . SetFrontend ( fedir )
2021-05-02 12:29:43 +00:00
go func ( ) {
time . Sleep ( time . Second ) // THIS IS STUPID
2021-11-19 18:37:42 +00:00
dashboardURL := fmt . Sprintf ( "http://%s/ui" , httpServer . Config . Bind )
2021-10-28 09:01:52 +00:00
err := browser . OpenURL ( dashboardURL )
if err != nil {
log . WithError ( err ) . Warnf ( "could not open browser, dashboard URL available at: %s" , dashboardURL )
}
2021-05-02 12:29:43 +00:00
} ( )
2021-11-19 18:37:42 +00:00
go func ( ) {
err := db . Subscribe ( context . Background ( ) , func ( changed [ ] database . ModifiedKV ) error {
for _ , pair := range changed {
if pair . Key == modules . ModuleConfigKey {
//TODO Enable/disable modules
}
}
return nil
} , modules . ModuleConfigKey )
log . WithError ( err ) . Error ( "Error while listening to module config changes" )
} ( )
2021-05-02 12:29:43 +00:00
// Start HTTP server
2021-11-19 18:37:42 +00:00
failOnError ( httpServer . Listen ( ) , "HTTP server stopped" )
2021-05-02 12:29:43 +00:00
}
func failOnError ( err error , text string ) {
if err != nil {
fatalError ( err , text )
}
}
func fatalError ( err error , text string ) {
log . Fatalf ( "FATAL ERROR OCCURRED: %s\n\n%s" , text , err . Error ( ) )
}