nginx-ui/internal/version/release.go
2025-05-02 10:31:00 +08:00

141 lines
3.3 KiB
Go

package version
import (
"encoding/json"
"io"
"net/http"
"time"
"github.com/pkg/errors"
)
const (
GithubLatestReleaseAPI = "https://api.github.com/repos/0xJacky/nginx-ui/releases/latest"
GithubReleasesListAPI = "https://api.github.com/repos/0xJacky/nginx-ui/releases"
)
type ReleaseType string
const (
ReleaseTypeStable ReleaseType = "stable"
ReleaseTypePrerelease ReleaseType = "prerelease"
ReleaseTypeDev ReleaseType = "dev"
)
type TReleaseAsset struct {
Name string `json:"name"`
BrowserDownloadUrl string `json:"browser_download_url"`
Size uint `json:"size"`
}
type TRelease struct {
TagName string `json:"tag_name"`
Name string `json:"name"`
PublishedAt time.Time `json:"published_at"`
Body string `json:"body"`
Prerelease bool `json:"prerelease"`
Type ReleaseType `json:"type"`
Assets []TReleaseAsset `json:"assets"`
}
func (t *TRelease) GetAssetsMap() (m map[string]TReleaseAsset) {
m = make(map[string]TReleaseAsset)
for _, v := range t.Assets {
m[v.Name] = v
}
return
}
func getLatestRelease() (data TRelease, err error) {
resp, err := http.Get(GithubLatestReleaseAPI)
if err != nil {
err = errors.Wrap(err, "service.getLatestRelease http.Get err")
return
}
body, err := io.ReadAll(resp.Body)
if err != nil {
err = errors.Wrap(err, "service.getLatestRelease io.ReadAll err")
return
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
err = errors.New(string(body))
return
}
err = json.Unmarshal(body, &data)
if err != nil {
err = errors.Wrap(err, "service.getLatestRelease json.Unmarshal err")
return
}
data.Type = ReleaseTypeStable
return
}
func getLatestPrerelease() (data TRelease, err error) {
resp, err := http.Get(GithubReleasesListAPI)
if err != nil {
err = errors.Wrap(err, "service.getLatestPrerelease http.Get err")
return
}
body, err := io.ReadAll(resp.Body)
if err != nil {
err = errors.Wrap(err, "service.getLatestPrerelease io.ReadAll err")
return
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
err = errors.New(string(body))
return
}
var releaseList []TRelease
err = json.Unmarshal(body, &releaseList)
if err != nil {
err = errors.Wrap(err, "service.getLatestPrerelease json.Unmarshal err")
return
}
latestDate := time.Time{}
for _, release := range releaseList {
if release.Prerelease && release.PublishedAt.After(latestDate) {
data = release
latestDate = release.PublishedAt
data.Type = ReleaseTypePrerelease
}
}
return
}
func GetRelease(channel string) (data TRelease, err error) {
stableRelease, err := getLatestRelease()
if err != nil {
return TRelease{}, err
}
switch ReleaseType(channel) {
default:
fallthrough
case ReleaseTypeStable:
return stableRelease, nil
case ReleaseTypePrerelease:
preRelease, err := getLatestPrerelease()
if err != nil {
return TRelease{}, err
}
// if preRelease is newer than stableRelease, return preRelease
// otherwise return stableRelease
if preRelease.PublishedAt.After(stableRelease.PublishedAt) {
return preRelease, nil
}
return stableRelease, nil
case ReleaseTypeDev:
devRelease, err := getDevBuild()
if err != nil {
return TRelease{}, err
}
return devRelease, nil
}
}