From bda58c73118ac20dc013be18d36f557ad5406c16 Mon Sep 17 00:00:00 2001 From: fy Date: Thu, 31 Oct 2024 22:13:27 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0github=E4=B8=8B?= =?UTF-8?q?=E8=BD=BD=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/auto-build.yml | 10 +++ main.go | 10 +++ update.go | 121 +++++++++++++++++++++++++++++++ 3 files changed, 141 insertions(+) diff --git a/.github/workflows/auto-build.yml b/.github/workflows/auto-build.yml index 69ca7e6..a989985 100644 --- a/.github/workflows/auto-build.yml +++ b/.github/workflows/auto-build.yml @@ -123,10 +123,20 @@ jobs: echo "::set-output name=SHORT_SHA::$(echo ${{ github.sha }} | cut -c1-7)" echo "::set-output name=DATE::$(date +%Y%m%d)" + - name: Generate Release Notes + id: release_notes + run: | + echo "NOTES<> $GITHUB_ENV + git log --format='- %s' $(git describe --tags --abbrev=0 2>/dev/null || git rev-list --max-parents=0 HEAD)..HEAD >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + - name: Upload Release uses: softprops/action-gh-release@v1 with: tag_name: ${{ steps.slug.outputs.DATE }}-${{ steps.slug.outputs.SHORT_SHA }} + body: | + ## 更新说明 + ${{ env.NOTES }} files: | release/sealchat_*_*_${{ matrix.name }}.* env: diff --git a/main.go b/main.go index 5774587..6e94f99 100644 --- a/main.go +++ b/main.go @@ -2,6 +2,7 @@ package main import ( "embed" + "fmt" "os" "os/signal" "time" @@ -24,6 +25,7 @@ func main() { var opts struct { Install bool `short:"i" long:"install" description:"安装为系统服务"` Uninstall bool `long:"uninstall" description:"删除系统服务"` + Download bool `short:"d" long:"download" description:"从github下载最新的压缩包"` } _, err := flags.ParseArgs(&opts, os.Args) if err != nil { @@ -40,6 +42,14 @@ func main() { return } + if opts.Download { + err = downloadLatestRelease() + if err != nil { + fmt.Println(err.Error()) + } + return + } + lo.Must0(os.MkdirAll("./data", 0755)) config := utils.ReadConfig() diff --git a/update.go b/update.go index 06ab7d0..cad8eb3 100644 --- a/update.go +++ b/update.go @@ -1 +1,122 @@ package main + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + "os" + "runtime" + "strings" + "time" +) + +// writeCounter 用于跟踪写入进度的结构体 +type writeCounter struct { + total int64 + onWrite func(int64) +} + +// Write 实现io.Writer接口 +func (wc *writeCounter) Write(p []byte) (int, error) { + n := len(p) + if wc.onWrite != nil { + wc.onWrite(int64(n)) + } + return n, nil +} + +func downloadLatestRelease() error { + // 获取最新release信息 + resp, err := http.Get("https://api.github.com/repos/sealdice/sealchat/releases/latest") + if err != nil { + return fmt.Errorf("获取release信息失败: %v", err) + } + defer resp.Body.Close() + + var release struct { + Assets []struct { + Name string `json:"name"` + BrowserDownloadURL string `json:"browser_download_url"` + } `json:"assets"` + } + + if err := json.NewDecoder(resp.Body).Decode(&release); err != nil { + return fmt.Errorf("解析release信息失败: %v", err) + } + + // 获取当前系统和架构信息 + osType := runtime.GOOS + arch := runtime.GOARCH + + // 查找匹配的资源文件 + var targetAsset struct { + Name string + URL string + } + + for _, asset := range release.Assets { + // 只检查系统和架构后缀 + suffix := fmt.Sprintf("_%s_%s", osType, arch) + if strings.Contains(asset.Name, suffix) { + targetAsset.Name = asset.Name + targetAsset.URL = asset.BrowserDownloadURL + break + } + } + + if targetAsset.URL == "" { + return fmt.Errorf("未找到适合当前系统(%s_%s)的安装包", osType, arch) + } + + fmt.Printf("正在下载最新版本的压缩包: %s\n", targetAsset.Name) + fmt.Println("请注意,即使当前版本就是最新版本,也会一样下载") + fmt.Println("根据网络情况,下载可能需要较长时间,请耐心等待") + + // 获取文件大小 + resp, err = http.Head(targetAsset.URL) + if err != nil { + return fmt.Errorf("获取文件大小失败: %v", err) + } + fileSize := resp.ContentLength + fmt.Printf("文件大小: %.2f MB\n", float64(fileSize)/(1024*1024)) + + resp, err = http.Get(targetAsset.URL) + if err != nil { + return fmt.Errorf("下载文件失败: %v", err) + } + defer resp.Body.Close() + + out, err := os.Create(targetAsset.Name) + if err != nil { + return fmt.Errorf("创建文件失败: %v", err) + } + defer out.Close() + + // 创建一个计数器来跟踪已下载的字节数 + var downloaded int64 = 0 + lastPrintTime := time.Now() + + // 创建一个代理reader来统计下载进度 + reader := io.TeeReader(resp.Body, &writeCounter{ + total: fileSize, + onWrite: func(n int64) { + downloaded += n + if time.Since(lastPrintTime) >= 10*time.Second { + progress := float64(downloaded) / float64(fileSize) * 100 + fmt.Printf("已下载: %.1f%% (%.1f MB)\n", + progress, + float64(downloaded)/(1024*1024)) + lastPrintTime = time.Now() + } + }, + }) + + _, err = io.Copy(out, reader) + if err != nil { + return fmt.Errorf("保存文件失败: %v", err) + } + fmt.Printf("文件 %s 下载完成\n", targetAsset.Name) + + return nil +}