diff --git a/internal/data/setting.go b/internal/data/setting.go index d457d42f..4b523643 100644 --- a/internal/data/setting.go +++ b/internal/data/setting.go @@ -309,6 +309,18 @@ func (r *settingRepo) UpdatePanel(ctx context.Context, req *request.SettingPanel return false, err } + // 订阅模式后台下载 IPDB + if req.IPDBType == "subscribe" && ipdbURL != "" { + go func() { + destPath := filepath.Join(app.Root, "panel/storage/geo.ipdb") + if err := io.DownloadFile(ipdbURL, destPath); err != nil { + r.log.Warn("failed to download ipdb", slog.String("url", ipdbURL), slog.Any("err", err)) + } else { + r.log.Info("ipdb downloaded", slog.String("url", ipdbURL)) + } + }() + } + // 下面是需要需要重启的设置 // 面板HTTPS restartFlag := false diff --git a/internal/job/helper.go b/internal/job/helper.go index 7bf5f883..fba1c73a 100644 --- a/internal/job/helper.go +++ b/internal/job/helper.go @@ -1,14 +1,11 @@ package job import ( - "fmt" "log/slog" "os" "path/filepath" "time" - "resty.dev/v3" - "github.com/acepanel/panel/internal/app" "github.com/acepanel/panel/internal/biz" "github.com/acepanel/panel/pkg/geoip" @@ -19,7 +16,7 @@ func resolveIPDBPath(setting biz.SettingRepo) string { ipdbType, _ := setting.Get(biz.SettingKeyIPDBType) switch ipdbType { case "subscribe": - return filepath.Join(app.Root, "panel/storage/geo/qqwry.ipdb") + return filepath.Join(app.Root, "panel/storage/geo.ipdb") case "custom": path, _ := setting.Get(biz.SettingKeyIPDBPath) return path @@ -71,32 +68,3 @@ func refreshGeoIP(setting biz.SettingRepo, current *geoip.GeoIP, curPath string, log.Info("ipdb loaded", slog.String("path", path)) return g, path, modTime } - -// downloadFile 下载文件到指定路径原子替换 -func downloadFile(url, destPath string) error { - if err := os.MkdirAll(filepath.Dir(destPath), 0755); err != nil { - return fmt.Errorf("failed to create directory: %w", err) - } - - tmpPath := destPath + ".tmp" - client := resty.New() - defer func() { _ = client.Close() }() - defer func() { _ = os.Remove(tmpPath) }() - - resp, err := client.R(). - SetSaveResponse(true). - SetOutputFileName(tmpPath). - Get(url) - if err != nil { - return fmt.Errorf("request failed: %w", err) - } - if resp.IsError() { - return fmt.Errorf("unexpected status code: %d", resp.StatusCode()) - } - - if err = os.Rename(tmpPath, destPath); err != nil { - return fmt.Errorf("failed to rename file: %w", err) - } - - return nil -} diff --git a/internal/job/panel_task.go b/internal/job/panel_task.go index a0a469cc..fe3128da 100644 --- a/internal/job/panel_task.go +++ b/internal/job/panel_task.go @@ -4,6 +4,7 @@ import ( "fmt" "log/slog" "math/rand/v2" + "os" "path/filepath" "runtime" "runtime/debug" @@ -17,6 +18,7 @@ import ( "github.com/acepanel/panel/internal/biz" "github.com/acepanel/panel/pkg/api" "github.com/acepanel/panel/pkg/config" + "github.com/acepanel/panel/pkg/io" ) // PanelTask 面板每日任务 @@ -170,10 +172,12 @@ func (r *PanelTask) updatePanel() { // updateIPDB 更新 IPDB 订阅文件 func (r *PanelTask) updateIPDB() { - // 每周五更新 - if time.Now().Weekday() != time.Friday { + // 文件已存在时每周五更新,不存在则立即下载 + destPath := filepath.Join(app.Root, "panel/storage/geo.ipdb") + if _, err := os.Stat(destPath); err == nil && time.Now().Weekday() != time.Friday { return } + ipdbType, _ := r.settingRepo.Get(biz.SettingKeyIPDBType) if ipdbType != "subscribe" { return @@ -183,8 +187,7 @@ func (r *PanelTask) updateIPDB() { return } - destPath := filepath.Join(app.Root, "panel/storage/geo/qqwry.ipdb") - if err := downloadFile(ipdbURL, destPath); err != nil { + if err := io.DownloadFile(ipdbURL, destPath); err != nil { r.log.Warn("failed to download ipdb", slog.String("url", ipdbURL), slog.Any("err", err)) return } diff --git a/pkg/io/file.go b/pkg/io/file.go index 8775dd03..efda735b 100644 --- a/pkg/io/file.go +++ b/pkg/io/file.go @@ -1,10 +1,13 @@ package io import ( + "fmt" "os" "path/filepath" "strings" + "resty.dev/v3" + "github.com/acepanel/panel/pkg/chattr" ) @@ -110,3 +113,32 @@ func GetSymlink(path string) string { } return linkPath } + +// DownloadFile 下载文件到指定路径,使用 .tmp 原子替换 +func DownloadFile(url, destPath string) error { + if err := os.MkdirAll(filepath.Dir(destPath), 0755); err != nil { + return fmt.Errorf("failed to create directory: %w", err) + } + + tmpPath := destPath + ".tmp" + client := resty.New() + defer func() { _ = client.Close() }() + defer func() { _ = os.Remove(tmpPath) }() + + resp, err := client.R(). + SetSaveResponse(true). + SetOutputFileName(tmpPath). + Get(url) + if err != nil { + return fmt.Errorf("request failed: %w", err) + } + if resp.IsError() { + return fmt.Errorf("unexpected status code: %d", resp.StatusCode()) + } + + if err = os.Rename(tmpPath, destPath); err != nil { + return fmt.Errorf("failed to rename file: %w", err) + } + + return nil +}