169 lines
5.3 KiB
Go
169 lines
5.3 KiB
Go
package service
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"net/http"
|
|
"time"
|
|
)
|
|
|
|
// UpdateService 更新服务
|
|
type UpdateService struct {
|
|
checkURL string // 版本检查接口 URL
|
|
}
|
|
|
|
// NewUpdateService 创建更新服务
|
|
func NewUpdateService(checkURL string) *UpdateService {
|
|
return &UpdateService{
|
|
checkURL: checkURL,
|
|
}
|
|
}
|
|
|
|
// RemoteVersionInfo 远程版本信息
|
|
type RemoteVersionInfo struct {
|
|
Version string `json:"version"`
|
|
DownloadURL string `json:"download_url"`
|
|
Changelog string `json:"changelog"`
|
|
ForceUpdate bool `json:"force_update"`
|
|
ReleaseDate string `json:"release_date"`
|
|
}
|
|
|
|
// CheckUpdate 检查更新
|
|
func (s *UpdateService) CheckUpdate() (*UpdateCheckResult, error) {
|
|
log.Printf("[更新检查] 开始检查更新,检查地址: %s", s.checkURL)
|
|
|
|
// 加载配置
|
|
config, err := LoadUpdateConfig()
|
|
if err != nil {
|
|
log.Printf("[更新检查] 加载配置失败: %v", err)
|
|
return nil, fmt.Errorf("加载配置失败: %v", err)
|
|
}
|
|
|
|
// 获取当前版本(优先使用服务获取的最新版本号,而不是配置中可能过期的版本号)
|
|
currentVersionStr := GetCurrentVersion()
|
|
if currentVersionStr == "" {
|
|
// 如果服务获取失败,回退到配置中的版本号
|
|
currentVersionStr = config.CurrentVersion
|
|
log.Printf("[更新检查] 使用配置中的版本号: %s", currentVersionStr)
|
|
} else {
|
|
log.Printf("[更新检查] 使用服务获取的版本号: %s", currentVersionStr)
|
|
// 如果配置中的版本号不一致,更新配置
|
|
if config.CurrentVersion != currentVersionStr {
|
|
log.Printf("[更新检查] 配置中的版本号 (%s) 与当前版本号 (%s) 不一致,更新配置", config.CurrentVersion, currentVersionStr)
|
|
config.CurrentVersion = currentVersionStr
|
|
if err := SaveUpdateConfig(config); err != nil {
|
|
log.Printf("[更新检查] 更新配置失败: %v", err)
|
|
}
|
|
}
|
|
}
|
|
|
|
currentVersion, err := ParseVersion(currentVersionStr)
|
|
if err != nil {
|
|
log.Printf("[更新检查] 解析当前版本失败: %v", err)
|
|
return nil, fmt.Errorf("解析当前版本失败: %v", err)
|
|
}
|
|
|
|
// 请求远程版本信息
|
|
remoteInfo, err := s.fetchRemoteVersionInfo()
|
|
if err != nil {
|
|
log.Printf("[更新检查] 获取远程版本信息失败: %v", err)
|
|
return nil, fmt.Errorf("获取远程版本信息失败: %v", err)
|
|
}
|
|
|
|
log.Printf("[更新检查] 远程版本信息: 版本=%s, 下载地址=%s, 强制更新=%v",
|
|
remoteInfo.Version, remoteInfo.DownloadURL, remoteInfo.ForceUpdate)
|
|
|
|
// 解析远程版本号
|
|
remoteVersion, err := ParseVersion(remoteInfo.Version)
|
|
if err != nil {
|
|
log.Printf("[更新检查] 解析远程版本号失败: %v", err)
|
|
return nil, fmt.Errorf("解析远程版本号失败: %v", err)
|
|
}
|
|
|
|
// 比较版本
|
|
hasUpdate := remoteVersion.IsNewerThan(currentVersion)
|
|
log.Printf("[更新检查] 版本比较: 当前=%s, 远程=%s, 有更新=%v",
|
|
currentVersion.String(), remoteVersion.String(), hasUpdate)
|
|
|
|
// 更新最后检查时间
|
|
config.UpdateLastCheckTime()
|
|
|
|
result := &UpdateCheckResult{
|
|
HasUpdate: hasUpdate,
|
|
CurrentVersion: currentVersionStr,
|
|
LatestVersion: remoteInfo.Version,
|
|
DownloadURL: remoteInfo.DownloadURL,
|
|
Changelog: remoteInfo.Changelog,
|
|
ForceUpdate: remoteInfo.ForceUpdate,
|
|
ReleaseDate: remoteInfo.ReleaseDate,
|
|
}
|
|
|
|
log.Printf("[更新检查] 检查完成: 有更新=%v", hasUpdate)
|
|
return result, nil
|
|
}
|
|
|
|
// fetchRemoteVersionInfo 获取远程版本信息
|
|
func (s *UpdateService) fetchRemoteVersionInfo() (*RemoteVersionInfo, error) {
|
|
if s.checkURL == "" {
|
|
log.Printf("[远程版本] 版本检查 URL 未配置")
|
|
return nil, fmt.Errorf("版本检查 URL 未配置,请先设置检查地址")
|
|
}
|
|
|
|
log.Printf("[远程版本] 请求远程版本信息: %s", s.checkURL)
|
|
|
|
// 创建 HTTP 客户端,设置超时
|
|
client := &http.Client{
|
|
Timeout: 10 * time.Second,
|
|
}
|
|
|
|
// 发送请求
|
|
resp, err := client.Get(s.checkURL)
|
|
if err != nil {
|
|
log.Printf("[远程版本] 网络请求失败: %v", err)
|
|
return nil, fmt.Errorf("网络请求失败: %v", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
log.Printf("[远程版本] HTTP 响应状态码: %d", resp.StatusCode)
|
|
if resp.StatusCode != http.StatusOK {
|
|
return nil, fmt.Errorf("服务器返回错误状态码: %d", resp.StatusCode)
|
|
}
|
|
|
|
// 读取响应
|
|
body, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
log.Printf("[远程版本] 读取响应失败: %v", err)
|
|
return nil, fmt.Errorf("读取响应失败: %v", err)
|
|
}
|
|
|
|
log.Printf("[远程版本] 响应内容长度: %d 字节", len(body))
|
|
|
|
// 解析 JSON
|
|
var remoteInfo RemoteVersionInfo
|
|
if err := json.Unmarshal(body, &remoteInfo); err != nil {
|
|
log.Printf("[远程版本] 解析 JSON 失败: %v, 响应内容: %s", err, string(body))
|
|
return nil, fmt.Errorf("解析响应失败: %v", err)
|
|
}
|
|
|
|
if remoteInfo.Version == "" {
|
|
log.Printf("[远程版本] 远程版本信息不完整,响应内容: %s", string(body))
|
|
return nil, fmt.Errorf("远程版本信息不完整")
|
|
}
|
|
|
|
log.Printf("[远程版本] 成功获取远程版本信息: %+v", remoteInfo)
|
|
return &remoteInfo, nil
|
|
}
|
|
|
|
// UpdateCheckResult 更新检查结果
|
|
type UpdateCheckResult struct {
|
|
HasUpdate bool `json:"has_update"`
|
|
CurrentVersion string `json:"current_version"`
|
|
LatestVersion string `json:"latest_version"`
|
|
DownloadURL string `json:"download_url"`
|
|
Changelog string `json:"changelog"`
|
|
ForceUpdate bool `json:"force_update"`
|
|
ReleaseDate string `json:"release_date"`
|
|
}
|