Files
GoTunnel/pkg/version/version.go
Flik f46741a84b
Some checks failed
Build Multi-Platform Binaries / build-frontend (push) Successful in 30s
Build Multi-Platform Binaries / build-binaries (amd64, darwin, server, false) (push) Successful in 1m4s
Build Multi-Platform Binaries / build-binaries (amd64, linux, client, true) (push) Successful in 45s
Build Multi-Platform Binaries / build-binaries (amd64, linux, server, true) (push) Successful in 1m29s
Build Multi-Platform Binaries / build-binaries (amd64, windows, client, true) (push) Successful in 45s
Build Multi-Platform Binaries / build-binaries (amd64, windows, server, true) (push) Successful in 1m27s
Build Multi-Platform Binaries / build-binaries (arm, 7, linux, client, true) (push) Successful in 50s
Build Multi-Platform Binaries / build-binaries (arm, 7, linux, server, true) (push) Successful in 1m42s
Build Multi-Platform Binaries / build-binaries (arm64, darwin, server, false) (push) Has been cancelled
Build Multi-Platform Binaries / build-binaries (arm64, linux, client, true) (push) Has been cancelled
Build Multi-Platform Binaries / build-binaries (arm64, linux, server, true) (push) Has been cancelled
Build Multi-Platform Binaries / build-binaries (arm64, windows, server, false) (push) Has been cancelled
updete
2026-01-02 01:59:44 +08:00

208 lines
4.6 KiB
Go

package version
import (
"encoding/json"
"fmt"
"io"
"net/http"
"runtime"
"strconv"
"strings"
"time"
)
// 版本信息
const Version = "1.0.0"
// 仓库信息
const (
RepoURL = "https://git.92coco.cn:8443/flik/GoTunnel"
APIBaseURL = "https://git.92coco.cn:8443/api/v1"
RepoOwner = "flik"
RepoName = "GoTunnel"
)
// Info 版本详细信息
type Info struct {
Version string `json:"version"`
GitCommit string `json:"git_commit"`
BuildTime string `json:"build_time"`
GoVersion string `json:"go_version"`
OS string `json:"os"`
Arch string `json:"arch"`
}
// GetInfo 获取版本信息
func GetInfo() Info {
return Info{
Version: Version,
GitCommit: "",
BuildTime: "",
GoVersion: runtime.Version(),
OS: runtime.GOOS,
Arch: runtime.GOARCH,
}
}
// ReleaseInfo Release 信息
type ReleaseInfo struct {
TagName string `json:"tag_name"`
Name string `json:"name"`
Body string `json:"body"`
PublishedAt string `json:"published_at"`
Assets []ReleaseAsset `json:"assets"`
}
// ReleaseAsset Release 资产
type ReleaseAsset struct {
Name string `json:"name"`
Size int64 `json:"size"`
BrowserDownloadURL string `json:"browser_download_url"`
}
// UpdateInfo 更新信息
type UpdateInfo struct {
Latest string `json:"latest"`
ReleaseNote string `json:"release_note"`
DownloadURL string `json:"download_url"`
AssetName string `json:"asset_name"`
AssetSize int64 `json:"asset_size"`
}
// GetLatestRelease 获取最新 Release
func GetLatestRelease() (*ReleaseInfo, error) {
url := fmt.Sprintf("%s/repos/%s/%s/releases/latest", APIBaseURL, RepoOwner, RepoName)
client := &http.Client{Timeout: 30 * time.Second}
resp, err := client.Get(url)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
body, _ := io.ReadAll(resp.Body)
return nil, fmt.Errorf("API error: %s - %s", resp.Status, string(body))
}
var release ReleaseInfo
if err := json.NewDecoder(resp.Body).Decode(&release); err != nil {
return nil, err
}
return &release, nil
}
// CheckUpdate 检查更新(返回最新版本信息)
func CheckUpdate(component string) (*UpdateInfo, error) {
release, err := GetLatestRelease()
if err != nil {
return nil, fmt.Errorf("get latest release: %w", err)
}
// 查找对应平台的资产
assetName := getAssetName(component)
var downloadURL string
var assetSize int64
for _, asset := range release.Assets {
if asset.Name == assetName {
downloadURL = asset.BrowserDownloadURL
assetSize = asset.Size
break
}
}
return &UpdateInfo{
Latest: release.TagName,
ReleaseNote: release.Body,
DownloadURL: downloadURL,
AssetName: assetName,
AssetSize: assetSize,
}, nil
}
// CheckUpdateForPlatform 检查指定平台的更新
func CheckUpdateForPlatform(component, osName, arch string) (*UpdateInfo, error) {
release, err := GetLatestRelease()
if err != nil {
return nil, fmt.Errorf("get latest release: %w", err)
}
// 查找对应平台的资产
assetName := getAssetNameForPlatform(component, osName, arch)
var downloadURL string
var assetSize int64
for _, asset := range release.Assets {
if asset.Name == assetName {
downloadURL = asset.BrowserDownloadURL
assetSize = asset.Size
break
}
}
return &UpdateInfo{
Latest: release.TagName,
ReleaseNote: release.Body,
DownloadURL: downloadURL,
AssetName: assetName,
AssetSize: assetSize,
}, nil
}
// getAssetName 获取当前平台的资产文件名
func getAssetName(component string) string {
return getAssetNameForPlatform(component, runtime.GOOS, runtime.GOARCH)
}
// getAssetNameForPlatform 获取指定平台的资产文件名
func getAssetNameForPlatform(component, osName, arch string) string {
ext := ""
if osName == "windows" {
ext = ".exe"
}
return fmt.Sprintf("%s_%s_%s%s", component, osName, arch, ext)
}
// CompareVersions 比较版本号
// 返回: -1 (v1 < v2), 0 (v1 == v2), 1 (v1 > v2)
func CompareVersions(v1, v2 string) int {
parts1 := parseVersionParts(v1)
parts2 := parseVersionParts(v2)
maxLen := len(parts1)
if len(parts2) > maxLen {
maxLen = len(parts2)
}
for i := 0; i < maxLen; i++ {
var p1, p2 int
if i < len(parts1) {
p1 = parts1[i]
}
if i < len(parts2) {
p2 = parts2[i]
}
if p1 < p2 {
return -1
}
if p1 > p2 {
return 1
}
}
return 0
}
func parseVersionParts(v string) []int {
v = strings.TrimPrefix(v, "v")
parts := strings.Split(v, ".")
result := make([]int, len(parts))
for i, p := range parts {
n, _ := strconv.Atoi(p)
result[i] = n
}
return result
}