diff --git a/README-CN.md b/README-CN.md index b0eacb8..baef53d 100644 --- a/README-CN.md +++ b/README-CN.md @@ -90,15 +90,6 @@ docker run -d --name synctv -p 8080:8080 synctvorg/synctv 如果你想使用自定义配置文件,你可以使用 `-f` 标志,否则它将使用 `${HOME}/.config/synctv/config.yaml` -## Init -`synctv init` 来初始化配置文件 - -```bash -synctv init -# or -synctv init -f ./config.yaml -``` - ## Server `synctv server` 启动服务器 diff --git a/README.md b/README.md index 95595ea..1ca5898 100644 --- a/README.md +++ b/README.md @@ -91,15 +91,6 @@ More information about docker image, please see [here](https://hub.docker.com/r/ if you want to use a custom config file, you can use `-f` flag, else it will use `${HOME}/.config/synctv/config.yaml` -## Init -`synctv init` to init config file - -```bash -synctv init -# or -synctv init -f ./config.yaml -``` - ## Server `synctv server` to start the server diff --git a/cmd/conf.go b/cmd/conf.go index 1514636..e7191ac 100644 --- a/cmd/conf.go +++ b/cmd/conf.go @@ -16,7 +16,10 @@ var ConfCmd = &cobra.Command{ } func Conf(cmd *cobra.Command, args []string) error { - bootstrap.InitConfig() + err := bootstrap.InitConfig(cmd.Context()) + if err != nil { + return err + } fmt.Println(conf.Conf.String()) return nil } diff --git a/cmd/init.go b/cmd/init.go deleted file mode 100644 index 7427f20..0000000 --- a/cmd/init.go +++ /dev/null @@ -1,24 +0,0 @@ -package cmd - -import ( - "github.com/spf13/cobra" - "github.com/synctv-org/synctv/internal/bootstrap" -) - -func Init(cmd *cobra.Command, args []string) error { - bootstrap.InitSysNotify() - bootstrap.InitConfig() - bootstrap.InitLog() - return nil -} - -var InitCmd = &cobra.Command{ - Use: "init", - Short: "init and check config", - Long: `auto create config file or check config, and auto add new key and delete old key`, - RunE: Init, -} - -func init() { - RootCmd.AddCommand(InitCmd) -} diff --git a/cmd/self-update.go b/cmd/self-update.go index 732ab63..f73e058 100644 --- a/cmd/self-update.go +++ b/cmd/self-update.go @@ -3,21 +3,28 @@ package cmd import ( log "github.com/sirupsen/logrus" "github.com/spf13/cobra" + "github.com/synctv-org/synctv/internal/bootstrap" "github.com/synctv-org/synctv/internal/conf" "github.com/synctv-org/synctv/internal/version" ) const SelfUpdateLong = `self-update command will update synctv-server binary to latest version. -Version check url: https://github.com/synctv-org/synctv/releases/latest + +Version check in: https://github.com/synctv-org/synctv/releases/latest If use '--dev' flag, will update to latest dev version always.` var SelfUpdateCmd = &cobra.Command{ - Use: "self-update", - Short: "self-update", - Long: SelfUpdateLong, - PersistentPreRunE: Init, - RunE: SelfUpdate, + Use: "self-update", + Short: "self-update", + Long: SelfUpdateLong, + PersistentPreRunE: func(cmd *cobra.Command, args []string) error { + return bootstrap.New(bootstrap.WithContext(cmd.Context())).Add( + bootstrap.InitConfig, + bootstrap.InitLog, + ).Run() + }, + RunE: SelfUpdate, } func SelfUpdate(cmd *cobra.Command, args []string) error { diff --git a/cmd/server.go b/cmd/server.go index dedef2b..0b9353c 100644 --- a/cmd/server.go +++ b/cmd/server.go @@ -15,12 +15,19 @@ import ( ) var ServerCmd = &cobra.Command{ - Use: "server", - Short: "Start synctv-server", - Long: `Start synctv-server`, - PersistentPreRunE: Init, - PreRunE: func(cmd *cobra.Command, args []string) error { return InitGinMode() }, - Run: Server, + Use: "server", + Short: "Start synctv-server", + Long: `Start synctv-server`, + PersistentPreRunE: func(cmd *cobra.Command, args []string) error { + return bootstrap.New(bootstrap.WithContext(cmd.Context())).Add( + bootstrap.InitSysNotify, + bootstrap.InitConfig, + bootstrap.InitLog, + bootstrap.InitCheckUpdate, + ).Run() + }, + PreRunE: func(cmd *cobra.Command, args []string) error { return InitGinMode() }, + Run: Server, } func Server(cmd *cobra.Command, args []string) { diff --git a/internal/bootstrap/config.go b/internal/bootstrap/config.go index 51d3408..a68ab8f 100644 --- a/internal/bootstrap/config.go +++ b/internal/bootstrap/config.go @@ -1,6 +1,7 @@ package bootstrap import ( + "context" "errors" "path/filepath" @@ -13,10 +14,10 @@ import ( "github.com/synctv-org/synctv/utils" ) -func InitConfig() { +func InitConfig(ctx context.Context) error { if flags.SkipConfig && flags.SkipEnv { log.Fatal("skip config and skip env at the same time") - return + return errors.New("skip config and skip env at the same time") } conf.Conf = conf.DefaultConfig() if !flags.SkipConfig { @@ -58,6 +59,7 @@ func InitConfig() { } log.Info("load config success from env") } + return nil } func confFromConfig(filePath string, conf *conf.Config) error { diff --git a/internal/bootstrap/init.go b/internal/bootstrap/init.go new file mode 100644 index 0000000..098f901 --- /dev/null +++ b/internal/bootstrap/init.go @@ -0,0 +1,46 @@ +package bootstrap + +import "context" + +type BootstrapConf func(*Bootstrap) + +func WithContext(ctx context.Context) BootstrapConf { + return func(b *Bootstrap) { + b.ctx = ctx + } +} + +func WithTask(f ...BootstrapFunc) BootstrapConf { + return func(b *Bootstrap) { + b.task = append(b.task, f...) + } +} + +type Bootstrap struct { + task []BootstrapFunc + ctx context.Context +} + +func New(conf ...BootstrapConf) *Bootstrap { + b := &Bootstrap{} + for _, c := range conf { + c(b) + } + return b +} + +type BootstrapFunc func(context.Context) error + +func (b *Bootstrap) Add(f ...BootstrapFunc) *Bootstrap { + b.task = append(b.task, f...) + return b +} + +func (b *Bootstrap) Run() error { + for _, f := range b.task { + if err := f(b.ctx); err != nil { + return err + } + } + return nil +} diff --git a/internal/bootstrap/log.go b/internal/bootstrap/log.go index 1b1d1f1..9a3102f 100644 --- a/internal/bootstrap/log.go +++ b/internal/bootstrap/log.go @@ -1,6 +1,7 @@ package bootstrap import ( + "context" "io" "log" "os" @@ -22,7 +23,7 @@ func setLog(l *logrus.Logger) { } } -func InitLog() { +func InitLog(ctx context.Context) error { setLog(logrus.StandardLogger()) if conf.Conf.Log.Enable { var l = &lumberjack.Logger{ @@ -60,4 +61,5 @@ func InitLog() { } } log.SetOutput(logrus.StandardLogger().Out) + return nil } diff --git a/internal/bootstrap/sysNotify.go b/internal/bootstrap/sysNotify.go index d3aa87e..aead23f 100644 --- a/internal/bootstrap/sysNotify.go +++ b/internal/bootstrap/sysNotify.go @@ -1,11 +1,16 @@ package bootstrap -import sysnotify "github.com/synctv-org/synctv/utils/sysNotify" +import ( + "context" + + sysnotify "github.com/synctv-org/synctv/utils/sysNotify" +) var ( - SysNotify *sysnotify.SysNotify + SysNotify sysnotify.SysNotify ) -func InitSysNotify() { - SysNotify = sysnotify.New() +func InitSysNotify(ctx context.Context) error { + SysNotify.Init() + return nil } diff --git a/internal/bootstrap/update.go b/internal/bootstrap/update.go new file mode 100644 index 0000000..a37c0e3 --- /dev/null +++ b/internal/bootstrap/update.go @@ -0,0 +1,69 @@ +package bootstrap + +import ( + "context" + "sync" + "time" + + log "github.com/sirupsen/logrus" + "github.com/synctv-org/synctv/internal/version" + sysnotify "github.com/synctv-org/synctv/utils/sysNotify" +) + +func InitCheckUpdate(ctx context.Context) error { + v, err := version.NewVersionInfo() + if err != nil { + log.Fatalf("get version info error: %v", err) + } + go func() { + t := time.NewTicker(time.Second) + defer t.Stop() + var ( + need bool + latest string + url string + once sync.Once + ) + SysNotify.RegisterSysNotifyTask(0, sysnotify.NewSysNotifyTask( + "check-update", + sysnotify.NotifyTypeEXIT, + func() error { + if need { + log.Infof("new version (%s) available: %s", latest, url) + log.Infof("run 'synctv self-update' to auto update") + } + return nil + }, + )) + for range t.C { + l, err := v.CheckLatest(ctx) + if err != nil { + log.Errorf("check update error: %v", err) + continue + } + latest = l + b, err := v.NeedUpdate(ctx) + if err != nil { + log.Errorf("check update error: %v", err) + continue + } + need = b + if b { + u, err := v.LatestBinaryURL(ctx) + if err != nil { + log.Errorf("check update error: %v", err) + continue + } + url = u + } + once.Do(func() { + if b { + log.Infof("new version (%s) available: %s", latest, url) + log.Infof("run 'synctv self-update' to auto update") + } + t.Reset(time.Hour * 6) + }) + } + }() + return nil +} diff --git a/utils/sysNotify/signal.go b/utils/sysNotify/signal.go index 53e4856..768f061 100644 --- a/utils/sysNotify/signal.go +++ b/utils/sysNotify/signal.go @@ -9,12 +9,9 @@ import ( "syscall" ) -func New() *SysNotify { - s := &SysNotify{ - c: make(chan os.Signal, 1), - } +func (s *SysNotify) Init() { + s.c = make(chan os.Signal, 1) signal.Notify(s.c, syscall.SIGHUP /*1*/, syscall.SIGINT /*2*/, syscall.SIGQUIT /*3*/, syscall.SIGTERM /*15*/, syscall.SIGUSR1 /*10*/, syscall.SIGUSR2 /*12*/) - return s } func parseSysNotifyType(s os.Signal) NotifyType { diff --git a/utils/sysNotify/signal_windows.go b/utils/sysNotify/signal_windows.go index 52325f8..948ca0f 100644 --- a/utils/sysNotify/signal_windows.go +++ b/utils/sysNotify/signal_windows.go @@ -6,12 +6,9 @@ import ( "syscall" ) -func New() *SysNotify { - s := &SysNotify{ - c: make(chan os.Signal, 1), - } +func (s *SysNotify) Init() { + s.c = make(chan os.Signal, 1) signal.Notify(s.c, syscall.SIGHUP /*1*/, syscall.SIGINT /*2*/, syscall.SIGQUIT /*3*/, syscall.SIGTERM /*15*/) - return s } func parseSysNotifyType(s os.Signal) NotifyType {