From 88077fef46e6f21d2e4cdef9a5d40c9893829d7a Mon Sep 17 00:00:00 2001 From: yzqzss Date: Fri, 13 Dec 2024 20:40:30 +0800 Subject: [PATCH] feat: check new version --- README.md | 2 +- main.go | 75 +++++++++++++++++++++++++++++------- pkg/api/api_test.go | 5 +-- pkg/downloader/downloader.go | 2 +- pkg/utils/veriosn_test.go | 17 ++++++++ pkg/utils/version.go | 61 ++++++++++++++++++++++++++++- 6 files changed, 141 insertions(+), 21 deletions(-) create mode 100644 pkg/utils/veriosn_test.go diff --git a/README.md b/README.md index 2e9d2c2..1e62f79 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ - [ ] Uploader - [ ] mapping IA S3 protocol - [ ] modify metadata -- [ ] Version check +- [x] Version check - [ ] CLI - [X] `aixifan_config.json` Config - [x] "downloads_home_dir" diff --git a/main.go b/main.go index 1dafa3a..67e7dc0 100644 --- a/main.go +++ b/main.go @@ -11,31 +11,76 @@ import ( "github.com/saveweb/aixifan/pkg/utils" ) -func help() { +func rootHelp() { fmt.Println("aixifan - " + utils.GetVersion().Version + " (" + utils.GetVersion().GoVersion + ")") + fmt.Println("") fmt.Println( - `Usage: aixifan action [dougaId] + `Usage: aixifan COMMAND [ARGS]... -Action: +Commands: down Download up Upload to IA - version Show version -dougaId: - int-string, NOT contain 'ac' or '_' - -Examples: -e.g. aixifan down 32749`) + version Show version`) } func main() { - flag.Usage = help + flag.Usage = rootHelp flag.Parse() - action := flag.Arg(0) + downCmd := flag.NewFlagSet("down", flag.ExitOnError) + downNoVersionCheck := downCmd.Bool("no-version-check", false, "Do not check aixifan's version") + downDougaId := downCmd.String("i", "", "Douga ID (int-string, NOT contain 'ac' or '_')") + + upCmd := flag.NewFlagSet("up", flag.ExitOnError) + + versionCmd := flag.NewFlagSet("version", flag.ExitOnError) + + if len(os.Args) < 2 { + rootHelp() + os.Exit(2) + } - switch action { + switch os.Args[1] { case "down": - dougaId := flag.Arg(1) + downCmd.Parse(os.Args[2:]) + + // check new version + newVersionChan := make(chan bool, 1) + defer func(ch chan bool) { + select { + case newVersion := <-ch: + if newVersion { + slog.Warn("") + slog.Warn("New version available, please update :) ") + } + default: + } + }(newVersionChan) + defer close(newVersionChan) + if !*downNoVersionCheck { + go func(ch chan bool) { + slog.Info("Checking new version...") + newVersion, err := utils.NewVersionAvailable() + if err != nil { + slog.Warn("Failed to check new version", "err", err) + } + if newVersion { + slog.Warn("New version available, please update :) ") + ch <- true + } else { + slog.Info("You are using the latest version :)") + ch <- false + } + }(newVersionChan) + } + + // download + dougaId := *downDougaId + if dougaId == "" { + downCmd.Usage() + os.Exit(2) + } + config, err := config.LoadOrNewConfig() if err != nil { panic(err) @@ -48,12 +93,14 @@ func main() { panic(err) } case "up": + upCmd.Parse(os.Args[2:]) panic("not implemented") case "version": + versionCmd.Parse(os.Args[2:]) fmt.Println(utils.GetVersion().Version) default: slog.Error("Invalid action") - help() + rootHelp() os.Exit(2) } } diff --git a/pkg/api/api_test.go b/pkg/api/api_test.go index 0066034..d9c34c7 100644 --- a/pkg/api/api_test.go +++ b/pkg/api/api_test.go @@ -12,8 +12,9 @@ import ( "github.com/tidwall/gjson" ) +var client = &http.Client{Timeout: 10 * time.Second} + func Test_requestDouga(t *testing.T) { - client := &http.Client{Timeout: 10 * time.Second} body, err := requestDouga(client, "41") if err != nil { t.Fatal(err) @@ -33,7 +34,6 @@ func Test_requestDouga(t *testing.T) { } func Test_getDougaMultiP(t *testing.T) { - client := &http.Client{Timeout: 10 * time.Second} json, err := GetDouga(client, "32749_1") if err != nil { t.Fatal(err) @@ -61,7 +61,6 @@ func Test_getDougaMultiP(t *testing.T) { } func Test_GetDougaAll(t *testing.T) { - client := &http.Client{Timeout: 10 * time.Second} parts, err := GetDougaAll(client, "32749") if err != nil { t.Fatal(err) diff --git a/pkg/downloader/downloader.go b/pkg/downloader/downloader.go index 2f2872a..e42cfc2 100644 --- a/pkg/downloader/downloader.go +++ b/pkg/downloader/downloader.go @@ -100,7 +100,7 @@ func DownloadVideo(dougaDir, acid, part string) error { slog.Info("Found m3u8s", "count", len(m3u8s), "QualityLabels", qualityLabels) m3u8 := m3u8s[0] // assume the first one is the best slog.Info("Selected", "QualityLabel", m3u8.QualityLabel) - hlsDL := hlsdl.New(m3u8.Url, headers, dougaDir, "ac"+acid+".ts", 3, true) + hlsDL := hlsdl.New(m3u8.Url, headers, dougaDir, "ac"+acid+".ts", 4, true) tsFilepath, err := hlsDL.Download() if err != nil { diff --git a/pkg/utils/veriosn_test.go b/pkg/utils/veriosn_test.go new file mode 100644 index 0000000..ce25338 --- /dev/null +++ b/pkg/utils/veriosn_test.go @@ -0,0 +1,17 @@ +package utils + +import ( + "testing" +) + +func Test_GetLatestTags(t *testing.T) { + tags, err := GetLatestTags() + if err != nil { + t.Fatal(err) + return + } + if len(tags) == 0 { + t.Fatal("tags is empty") + } + t.Logf("tags: %v", tags) +} diff --git a/pkg/utils/version.go b/pkg/utils/version.go index baf1c25..173f65e 100644 --- a/pkg/utils/version.go +++ b/pkg/utils/version.go @@ -1,9 +1,15 @@ package utils -import "runtime/debug" +import ( + "encoding/json" + "log/slog" + "net/http" + "runtime/debug" + "time" +) type Version struct { - Version string + Version string // "unknown_version" or "" or " (modified)" GoVersion string } @@ -26,3 +32,54 @@ func GetVersion() (version Version) { } return } + +type GitTag struct { + Name string `json:"name"` + Commit struct { + Sha string `json:"sha"` + } `json:"commit"` +} + +func GetLatestTags() (tags []GitTag, err error) { + client := &http.Client{Timeout: 3 * time.Second} + for _, url := range []string{ + "https://git.saveweb.org/api/v1/repos/saveweb/aixifan/tags", + "https://api.github.com/repos/saveweb/aixifan/tags", // in case git.saveweb.org is down + } { + var resp *http.Response + req, _ := http.NewRequest("GET", url, nil) + req.Header.Set("User-Agent", "aixifan/"+GetVersion().Version) + resp, err = client.Do(req) + if err != nil { + slog.Error(err.Error(), "url", url) + continue + } + defer resp.Body.Close() + if resp.StatusCode != 200 { + slog.Error("Failed to get tags", "status", resp.Status, "url", url) + continue + } + err = json.NewDecoder(resp.Body).Decode(&tags) + if err != nil { + slog.Error(err.Error(), "url", url) + continue + } + return + } + return + +} + +func NewVersionAvailable() (bool, error) { + tags, err := GetLatestTags() + if err != nil { + return false, err + } + latestTagName := tags[0].Name + latestTagCommit := tags[0].Commit.Sha + if latestTagCommit != GetVersion().Version { + slog.Info("New version available", "latest_tag", latestTagName, "latest_commit", latestTagCommit) + return true, nil + } + return false, nil +}