package service import ( "encoding/json" "fmt" "log" "os" "path/filepath" "time" ) // UpdateConfig 更新配置 type UpdateConfig struct { CurrentVersion string `json:"current_version"` LastCheckTime time.Time `json:"last_check_time"` AutoCheckEnabled bool `json:"auto_check_enabled"` CheckIntervalMinutes int `json:"check_interval_minutes"` // 检查间隔(分钟) CheckURL string `json:"check_url,omitempty"` // 版本检查接口 URL } // GetUpdateConfigPath 获取更新配置文件路径 func GetUpdateConfigPath() (string, error) { homeDir, err := os.UserHomeDir() if err != nil { return "", fmt.Errorf("获取用户目录失败: %v", err) } configDir := filepath.Join(homeDir, ".ssq-desk") if err := os.MkdirAll(configDir, 0755); err != nil { return "", fmt.Errorf("创建配置目录失败: %v", err) } return filepath.Join(configDir, "update_config.json"), nil } // LoadUpdateConfig 加载更新配置 func LoadUpdateConfig() (*UpdateConfig, error) { configPath, err := GetUpdateConfigPath() if err != nil { return nil, err } // 如果文件不存在,返回默认配置 if _, err := os.Stat(configPath); os.IsNotExist(err) { return &UpdateConfig{ CurrentVersion: GetCurrentVersion(), LastCheckTime: time.Time{}, AutoCheckEnabled: true, CheckIntervalMinutes: 1, // 默认1分钟检查一次 CheckURL: "https://img.1216.top/ssq/last-version.json", // 默认版本检查地址 }, nil } data, err := os.ReadFile(configPath) if err != nil { return nil, fmt.Errorf("读取配置文件失败: %v", err) } // 先解析为 map 以支持兼容旧配置 var configMap map[string]interface{} if err := json.Unmarshal(data, &configMap); err != nil { return nil, fmt.Errorf("解析配置文件失败: %v", err) } var config UpdateConfig if err := json.Unmarshal(data, &config); err != nil { return nil, fmt.Errorf("解析配置文件失败: %v", err) } // 兼容旧配置:如果存在 check_interval_days,转换为分钟 if config.CheckIntervalMinutes == 0 { if days, ok := configMap["check_interval_days"].(float64); ok && days > 0 { config.CheckIntervalMinutes = int(days * 24 * 60) // 转换为分钟 } else { config.CheckIntervalMinutes = 1 // 默认1分钟 } } // 获取最新版本号 latestVersion := GetCurrentVersion() // 如果当前版本为空或与最新版本不一致,更新为最新版本 if config.CurrentVersion == "" || config.CurrentVersion != latestVersion { if config.CurrentVersion != "" { log.Printf("[配置] 配置中的版本号 (%s) 与最新版本号 (%s) 不一致,更新配置", config.CurrentVersion, latestVersion) } config.CurrentVersion = latestVersion // 注意:这里不自动保存,避免频繁写入文件,由调用方决定是否保存 } // 如果检查地址为空,使用默认地址 if config.CheckURL == "" { config.CheckURL = "https://img.1216.top/ssq/last-version.json" } return &config, nil } // SaveUpdateConfig 保存更新配置 func SaveUpdateConfig(config *UpdateConfig) error { configPath, err := GetUpdateConfigPath() if err != nil { return err } data, err := json.MarshalIndent(config, "", " ") if err != nil { return fmt.Errorf("序列化配置失败: %v", err) } if err := os.WriteFile(configPath, data, 0644); err != nil { return fmt.Errorf("写入配置文件失败: %v", err) } return nil } // ShouldCheckUpdate 判断是否应该检查更新 func (c *UpdateConfig) ShouldCheckUpdate() bool { if !c.AutoCheckEnabled { return false } // 如果从未检查过,应该检查 if c.LastCheckTime.IsZero() { return true } // 检查是否超过间隔分钟数 minutesSinceLastCheck := time.Since(c.LastCheckTime).Minutes() return minutesSinceLastCheck >= float64(c.CheckIntervalMinutes) } // UpdateLastCheckTime 更新最后检查时间 func (c *UpdateConfig) UpdateLastCheckTime() error { c.LastCheckTime = time.Now() return SaveUpdateConfig(c) }