diff --git a/internal/data/setting.go b/internal/data/setting.go index d63fe52f..516fe233 100644 --- a/internal/data/setting.go +++ b/internal/data/setting.go @@ -242,6 +242,10 @@ func (r *settingRepo) UpdatePanel(version, url, checksum string) error { if !io.Exists(filepath.Join(app.Root, "panel", "web")) { return errors.New("更新失败,可能是下载过程中出现了问题") } + if err = io.Mv(filepath.Join(app.Root, "panel", "cli"), "/usr/local/sbin/panel-cli"); err != nil { + color.Redln("移动面板命令行工具失败") + return err + } color.Greenln("更新完成") color.Greenln("恢复面板数据...") @@ -273,6 +277,7 @@ func (r *settingRepo) UpdatePanel(version, url, checksum string) error { } color.Greenln("设置面板文件权限...") + _ = io.Chmod("/usr/local/sbin/panel-cli", 0700) _ = io.Chmod("/etc/systemd/system/panel.servic", 0700) _ = io.Chmod(filepath.Join(app.Root, "panel"), 0700) color.Greenln("设置完成") diff --git a/internal/job/cert_renew.go b/internal/job/cert_renew.go index c3e7ec3b..0d2c3c30 100644 --- a/internal/job/cert_renew.go +++ b/internal/job/cert_renew.go @@ -14,12 +14,12 @@ import ( // CertRenew 证书续签 type CertRenew struct { - cert biz.CertRepo + certRepo biz.CertRepo } func NewCertRenew() *CertRenew { return &CertRenew{ - cert: data.NewCertRepo(), + certRepo: data.NewCertRepo(), } } @@ -50,7 +50,7 @@ func (receiver *CertRenew) Run() { continue } - _, err = receiver.cert.Renew(cert.ID) + _, err = receiver.certRepo.Renew(cert.ID) if err != nil { app.Logger.Error("续签证书失败", zap.Error(err)) } diff --git a/internal/job/monitoring.go b/internal/job/monitoring.go index 7ce8a33c..b178f15c 100644 --- a/internal/job/monitoring.go +++ b/internal/job/monitoring.go @@ -15,12 +15,12 @@ import ( // Monitoring 系统监控 type Monitoring struct { - setting biz.SettingRepo + settingRepo biz.SettingRepo } func NewMonitoring() *Monitoring { return &Monitoring{ - setting: data.NewSettingRepo(), + settingRepo: data.NewSettingRepo(), } } @@ -33,7 +33,7 @@ func (receiver *Monitoring) Run() { //task := data.NewTaskRepo() //_ = task.DispatchWaiting() - monitor, err := receiver.setting.Get(biz.SettingKeyMonitor) + monitor, err := receiver.settingRepo.Get(biz.SettingKeyMonitor) if err != nil || !cast.ToBool(monitor) { return } @@ -54,7 +54,7 @@ func (receiver *Monitoring) Run() { } // 删除过期数据 - dayStr, err := receiver.setting.Get(biz.SettingKeyMonitorDays) + dayStr, err := receiver.settingRepo.Get(biz.SettingKeyMonitorDays) if err != nil { return } diff --git a/internal/job/panel_task.go b/internal/job/panel_task.go index 8b162a3a..13b77375 100644 --- a/internal/job/panel_task.go +++ b/internal/job/panel_task.go @@ -9,6 +9,8 @@ import ( "go.uber.org/zap" "github.com/TheTNB/panel/internal/app" + "github.com/TheTNB/panel/internal/biz" + "github.com/TheTNB/panel/internal/data" "github.com/TheTNB/panel/pkg/io" "github.com/TheTNB/panel/pkg/shell" "github.com/TheTNB/panel/pkg/types" @@ -16,10 +18,13 @@ import ( // PanelTask 面板每日任务 type PanelTask struct { + appRepo biz.AppRepo } func NewPanelTask() *PanelTask { - return &PanelTask{} + return &PanelTask{ + appRepo: data.NewAppRepo(), + } } func (receiver *PanelTask) Run() { @@ -43,6 +48,11 @@ func (receiver *PanelTask) Run() { app.Logger.Error("清理面板备份失败", zap.Error(err)) } + // 更新商店缓存 + if err := receiver.appRepo.UpdateCache(); err != nil { + app.Logger.Error("更新商店缓存失败", zap.Error(err)) + } + // 回收内存 runtime.GC() debug.FreeOSMemory() diff --git a/internal/service/app.go b/internal/service/app.go index 493f48bd..07f265bf 100644 --- a/internal/service/app.go +++ b/internal/service/app.go @@ -25,7 +25,7 @@ func (s *AppService) List(w http.ResponseWriter, r *http.Request) { all := s.appRepo.All() installedApps, err := s.appRepo.Installed() if err != nil { - Error(w, http.StatusInternalServerError, err.Error()) + Error(w, http.StatusInternalServerError, "%v", err) return } installedAppMap := make(map[string]*biz.App) @@ -79,12 +79,12 @@ func (s *AppService) List(w http.ResponseWriter, r *http.Request) { func (s *AppService) Install(w http.ResponseWriter, r *http.Request) { req, err := Bind[request.App](r) if err != nil { - Error(w, http.StatusUnprocessableEntity, err.Error()) + Error(w, http.StatusUnprocessableEntity, "%v", err) return } if err = s.appRepo.Install(req.Channel, req.Slug); err != nil { - Error(w, http.StatusInternalServerError, err.Error()) + Error(w, http.StatusInternalServerError, "%v", err) return } diff --git a/internal/service/cli.go b/internal/service/cli.go index de939590..15cf32c6 100644 --- a/internal/service/cli.go +++ b/internal/service/cli.go @@ -6,15 +6,18 @@ import ( "fmt" "path/filepath" + "github.com/go-rat/utils/env" "github.com/go-rat/utils/hash" "github.com/goccy/go-yaml" "github.com/gookit/color" + "github.com/spf13/cast" "github.com/urfave/cli/v3" "gorm.io/gorm" "github.com/TheTNB/panel/internal/app" "github.com/TheTNB/panel/internal/biz" "github.com/TheTNB/panel/internal/data" + "github.com/TheTNB/panel/pkg/api" "github.com/TheTNB/panel/pkg/io" "github.com/TheTNB/panel/pkg/str" "github.com/TheTNB/panel/pkg/systemctl" @@ -23,16 +26,20 @@ import ( ) type CliService struct { - app biz.AppRepo - user biz.UserRepo - hash hash.Hasher + api *api.API + app biz.AppRepo + user biz.UserRepo + setting biz.SettingRepo + hash hash.Hasher } func NewCliService() *CliService { return &CliService{ - app: data.NewAppRepo(), - user: data.NewUserRepo(), - hash: hash.NewArgon2id(), + api: api.NewAPI(app.Version), + app: data.NewAppRepo(), + user: data.NewUserRepo(), + setting: data.NewSettingRepo(), + hash: hash.NewArgon2id(), } } @@ -49,8 +56,37 @@ func (s *CliService) Start(ctx context.Context, cmd *cli.Command) error { } func (s *CliService) Update(ctx context.Context, cmd *cli.Command) error { - println("Hello, World!") - return nil + panel, err := s.api.LatestVersion() + if err != nil { + return fmt.Errorf("获取最新版本失败:%v", err) + } + + // TODO 需要修改接口直接把arch传过去 + var ver, url, checksum string + if env.IsX86() { + for _, v := range panel.Downloads { + if v.Arch == "amd64" { + ver = panel.Version + url = v.URL + checksum = v.Checksum + break + } + } + } else if env.IsArm() { + for _, v := range panel.Downloads { + if v.Arch == "arm64" { + ver = panel.Version + url = v.URL + checksum = v.Checksum + break + } + + } + } else { + return errors.New("不支持的架构") + } + + return s.setting.UpdatePanel(ver, url, checksum) } func (s *CliService) Info(ctx context.Context, cmd *cli.Command) error { @@ -172,28 +208,133 @@ func (s *CliService) UserPassword(ctx context.Context, cmd *cli.Command) error { } func (s *CliService) HTTPSOn(ctx context.Context, cmd *cli.Command) error { - println("Hello, World!") - return nil + config := new(types.PanelConfig) + cm := yaml.CommentMap{} + raw, err := io.Read(filepath.Join(app.Root, "panel/config/config.yml")) + if err != nil { + return err + } + if err = yaml.UnmarshalWithOptions([]byte(raw), config, yaml.CommentToMap(cm)); err != nil { + return err + } + + config.HTTP.TLS = true + + encoded, err := yaml.MarshalWithOptions(config, yaml.WithComment(cm)) + if err != nil { + return err + } + + if err = io.Write(filepath.Join(app.Root, "panel/config/config.yml"), string(encoded), 0700); err != nil { + return err + } + + return s.Restart(ctx, cmd) } func (s *CliService) HTTPSOff(ctx context.Context, cmd *cli.Command) error { - println("Hello, World!") - return nil + config := new(types.PanelConfig) + cm := yaml.CommentMap{} + raw, err := io.Read(filepath.Join(app.Root, "panel/config/config.yml")) + if err != nil { + return err + } + if err = yaml.UnmarshalWithOptions([]byte(raw), config, yaml.CommentToMap(cm)); err != nil { + return err + } + + config.HTTP.TLS = false + + encoded, err := yaml.MarshalWithOptions(config, yaml.WithComment(cm)) + if err != nil { + return err + } + + if err = io.Write(filepath.Join(app.Root, "panel/config/config.yml"), string(encoded), 0700); err != nil { + return err + } + + return s.Restart(ctx, cmd) } func (s *CliService) EntranceOn(ctx context.Context, cmd *cli.Command) error { - println("Hello, World!") - return nil + config := new(types.PanelConfig) + cm := yaml.CommentMap{} + raw, err := io.Read(filepath.Join(app.Root, "panel/config/config.yml")) + if err != nil { + return err + } + if err = yaml.UnmarshalWithOptions([]byte(raw), config, yaml.CommentToMap(cm)); err != nil { + return err + } + + config.HTTP.Entrance = "/" + str.RandomString(6) + + encoded, err := yaml.MarshalWithOptions(config, yaml.WithComment(cm)) + if err != nil { + return err + } + + if err = io.Write(filepath.Join(app.Root, "panel/config/config.yml"), string(encoded), 0700); err != nil { + return err + } + + return s.Restart(ctx, cmd) } func (s *CliService) EntranceOff(ctx context.Context, cmd *cli.Command) error { - println("Hello, World!") - return nil + config := new(types.PanelConfig) + cm := yaml.CommentMap{} + raw, err := io.Read(filepath.Join(app.Root, "panel/config/config.yml")) + if err != nil { + return err + } + if err = yaml.UnmarshalWithOptions([]byte(raw), config, yaml.CommentToMap(cm)); err != nil { + return err + } + + config.HTTP.Entrance = "/" + + encoded, err := yaml.MarshalWithOptions(config, yaml.WithComment(cm)) + if err != nil { + return err + } + + if err = io.Write(filepath.Join(app.Root, "panel/config/config.yml"), string(encoded), 0700); err != nil { + return err + } + + return s.Restart(ctx, cmd) } func (s *CliService) Port(ctx context.Context, cmd *cli.Command) error { - println("Hello, World!") - return nil + port := cast.ToInt(cmd.Args().First()) + if port < 1 || port > 65535 { + return fmt.Errorf("端口范围错误") + } + + config := new(types.PanelConfig) + cm := yaml.CommentMap{} + raw, err := io.Read(filepath.Join(app.Root, "panel/config/config.yml")) + if err != nil { + return err + } + if err = yaml.UnmarshalWithOptions([]byte(raw), config, yaml.CommentToMap(cm)); err != nil { + return err + } + + config.HTTP.Port = port + + encoded, err := yaml.MarshalWithOptions(config, yaml.WithComment(cm)) + if err != nil { + return err + } + + if err = io.Write(filepath.Join(app.Root, "panel/config/config.yml"), string(encoded), 0700); err != nil { + return err + } + + return s.Restart(ctx, cmd) } func (s *CliService) WebsiteCreate(ctx context.Context, cmd *cli.Command) error { @@ -389,7 +530,7 @@ func (s *CliService) Init(ctx context.Context, cmd *cli.Command) error { if err != nil { return err } - if err = io.Write(filepath.Join(app.Root, "panel/config/config.yml"), string(encoded), 0644); err != nil { + if err = io.Write(filepath.Join(app.Root, "panel/config/config.yml"), string(encoded), 0700); err != nil { return err } diff --git a/pkg/tools/tools.go b/pkg/tools/tools.go index 48f9199c..7575bb19 100644 --- a/pkg/tools/tools.go +++ b/pkg/tools/tools.go @@ -62,12 +62,7 @@ func GetMonitoringInfo() MonitoringInfo { func RestartPanel() { color.Greenln("重启面板...") - err := shell.ExecfAsync("sleep 2 && systemctl restart panel") - if err != nil { - color.Redln("重启失败") - return - } - + _ = shell.ExecfAsync("sleep 1 && systemctl restart panel") color.Greenln("重启完成") }