Compare commits
37 Commits
Author | SHA1 | Date | |
---|---|---|---|
9b7aab1fc7 | |||
3c717097cb | |||
991de009be | |||
2fef329319 | |||
db7623968d | |||
7c80c88feb | |||
2c7153cd7a | |||
d730feecb4 | |||
8293b7fdae | |||
0ba415866e | |||
53b41ca166 | |||
8a75f78e63 | |||
d9692c6366 | |||
f4b0062dfc | |||
b9ffc82e53 | |||
78aaea6a45 | |||
3645fbf161 | |||
a1d0f22132 | |||
fa73b0f4bf | |||
3b76a8b839 | |||
667f42dcdc | |||
dfbe09860f | |||
9e20f9c26a | |||
f968d0cb82 | |||
2ad84f4379 | |||
c7aa16426f | |||
5987f8e3b5 | |||
3a8eb72de2 | |||
33abbdfd24 | |||
0703d6cbff | |||
10d2d14938 | |||
691cf1d8d6 | |||
d1decb8e58 | |||
7d04904109 | |||
a5acd3aa97 | |||
eea9a12560 | |||
0a4570b55c |
16
.github/workflows/Delete.yml
vendored
Normal file
16
.github/workflows/Delete.yml
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
name: Delete old workflow runs
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 0 1 * *'
|
||||||
|
# Run monthly, at 00:00 on the 1st day of month.
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
del_runs:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Delete workflow runs
|
||||||
|
uses: GitRML/delete-workflow-runs@main
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.AUTH_PAT }}
|
||||||
|
repository: ${{ github.repository }}
|
||||||
|
retain_days: 30
|
12
.github/workflows/build.yml
vendored
12
.github/workflows/build.yml
vendored
@ -268,18 +268,6 @@ jobs:
|
|||||||
generate_release_notes: true
|
generate_release_notes: true
|
||||||
body_path: release.txt
|
body_path: release.txt
|
||||||
|
|
||||||
- name: Git push assets to "release" branch
|
|
||||||
run: |
|
|
||||||
cd bin || exit 1
|
|
||||||
git init
|
|
||||||
git config --local user.name "github-actions[bot]"
|
|
||||||
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
||||||
git checkout -b release
|
|
||||||
git add .
|
|
||||||
git commit -m "${{ env.BUILDTIME }}"
|
|
||||||
git remote add origin "https://${{ github.actor }}:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}"
|
|
||||||
git push -f -u origin release
|
|
||||||
|
|
||||||
Upload-Release:
|
Upload-Release:
|
||||||
permissions: write-all
|
permissions: write-all
|
||||||
if: ${{ github.ref_type=='tag' }}
|
if: ${{ github.ref_type=='tag' }}
|
||||||
|
16
.github/workflows/delete.yml
vendored
Normal file
16
.github/workflows/delete.yml
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
name: Delete old workflow runs
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 0 1 * *'
|
||||||
|
# Run monthly, at 00:00 on the 1st day of month.
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
del_runs:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Delete workflow runs
|
||||||
|
uses: GitRML/delete-workflow-runs@main
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.AUTH_PAT }}
|
||||||
|
repository: ${{ github.repository }}
|
||||||
|
retain_days: 30
|
@ -30,8 +30,7 @@
|
|||||||
- Comprehensive HTTP RESTful API controller
|
- Comprehensive HTTP RESTful API controller
|
||||||
|
|
||||||
## Wiki
|
## Wiki
|
||||||
|
Configuration examples can be found at [/docs/config.yaml](https://github.com/MetaCubeX/Clash.Meta/blob/Alpha/docs/config.yaml), while documentation can be found [Clash.Meta Wiki](https://clash-meta.wiki).
|
||||||
Documentation and configuring examples are available on [Clash.Meta Wiki](https://clash-meta.wiki).
|
|
||||||
|
|
||||||
## Build
|
## Build
|
||||||
|
|
||||||
|
@ -42,6 +42,8 @@ func NewInner(conn net.Conn, dst string, host string) *context.ConnContext {
|
|||||||
if host == "" {
|
if host == "" {
|
||||||
if ip, err := netip.ParseAddr(h); err == nil {
|
if ip, err := netip.ParseAddr(h); err == nil {
|
||||||
metadata.DstIP = ip
|
metadata.DstIP = ip
|
||||||
|
} else {
|
||||||
|
metadata.Host = h
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ func HttpRequest(ctx context.Context, url, method string, header map[string][]st
|
|||||||
TLSHandshakeTimeout: 10 * time.Second,
|
TLSHandshakeTimeout: 10 * time.Second,
|
||||||
ExpectContinueTimeout: 1 * time.Second,
|
ExpectContinueTimeout: 1 * time.Second,
|
||||||
DialContext: func(ctx context.Context, network, address string) (net.Conn, error) {
|
DialContext: func(ctx context.Context, network, address string) (net.Conn, error) {
|
||||||
conn := inner.HandleTcp(address, urlRes.Hostname())
|
conn := inner.HandleTcp(address, "")
|
||||||
return conn, nil
|
return conn, nil
|
||||||
},
|
},
|
||||||
TLSClientConfig: tls.GetDefaultTLSConfig(),
|
TLSClientConfig: tls.GetDefaultTLSConfig(),
|
||||||
|
@ -66,7 +66,7 @@ func (p *path) MMDB() string {
|
|||||||
// 目录则直接跳过
|
// 目录则直接跳过
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
if strings.EqualFold(strings.ToLower(fi.Name()), "country.mmdb") {
|
if strings.EqualFold(fi.Name(), "Country.mmdb") {
|
||||||
GeoipName = fi.Name()
|
GeoipName = fi.Name()
|
||||||
return P.Join(p.homeDir, fi.Name())
|
return P.Join(p.homeDir, fi.Name())
|
||||||
}
|
}
|
||||||
@ -93,7 +93,7 @@ func (p *path) GeoIP() string {
|
|||||||
// 目录则直接跳过
|
// 目录则直接跳过
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
if strings.EqualFold(strings.ToLower(fi.Name()), "geoip.dat") {
|
if strings.EqualFold(fi.Name(), "GeoIP.dat") {
|
||||||
GeoipName = fi.Name()
|
GeoipName = fi.Name()
|
||||||
return P.Join(p.homeDir, fi.Name())
|
return P.Join(p.homeDir, fi.Name())
|
||||||
}
|
}
|
||||||
@ -112,7 +112,7 @@ func (p *path) GeoSite() string {
|
|||||||
// 目录则直接跳过
|
// 目录则直接跳过
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
if strings.EqualFold(strings.ToLower(fi.Name()), "geosite.dat") {
|
if strings.EqualFold(fi.Name(), "GeoSite.dat") {
|
||||||
GeositeName = fi.Name()
|
GeositeName = fi.Name()
|
||||||
return P.Join(p.homeDir, fi.Name())
|
return P.Join(p.homeDir, fi.Name())
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ func restart(w http.ResponseWriter, r *http.Request) {
|
|||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
err = cmd.Start()
|
err = cmd.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln("restarting:: %s", err)
|
log.Fatalln("restarting: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
|
@ -1,18 +1,12 @@
|
|||||||
package route
|
package route
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"runtime"
|
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"github.com/Dreamacro/clash/hub/updater"
|
"github.com/Dreamacro/clash/hub/updater"
|
||||||
"github.com/Dreamacro/clash/log"
|
"github.com/Dreamacro/clash/log"
|
||||||
|
|
||||||
"github.com/go-chi/chi/v5"
|
"github.com/go-chi/chi/v5"
|
||||||
"github.com/go-chi/render"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func upgradeRouter() http.Handler {
|
func upgradeRouter() http.Handler {
|
||||||
@ -30,41 +24,5 @@ func upgrade(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
execPath, err := os.Executable()
|
restart(w, r)
|
||||||
if err != nil {
|
|
||||||
render.Status(r, http.StatusInternalServerError)
|
|
||||||
render.JSON(w, r, newError(fmt.Sprintf("getting path: %s", err)))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
render.JSON(w, r, render.M{"status": "ok"})
|
|
||||||
if f, ok := w.(http.Flusher); ok {
|
|
||||||
f.Flush()
|
|
||||||
}
|
|
||||||
|
|
||||||
// modify from https://github.com/AdguardTeam/AdGuardHome/blob/595484e0b3fb4c457f9bb727a6b94faa78a66c5f/internal/home/controlupdate.go#L180
|
|
||||||
// The background context is used because the underlying functions wrap it
|
|
||||||
// with timeout and shut down the server, which handles current request. It
|
|
||||||
// also should be done in a separate goroutine for the same reason.
|
|
||||||
go func() {
|
|
||||||
if runtime.GOOS == "windows" {
|
|
||||||
cmd := exec.Command(execPath, os.Args[1:]...)
|
|
||||||
log.Infoln("restarting: %q %q", execPath, os.Args[1:])
|
|
||||||
cmd.Stdin = os.Stdin
|
|
||||||
cmd.Stdout = os.Stdout
|
|
||||||
cmd.Stderr = os.Stderr
|
|
||||||
err = cmd.Start()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalln("restarting: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Infoln("restarting: %q %q", execPath, os.Args[1:])
|
|
||||||
err = syscall.Exec(execPath, os.Args, os.Environ())
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalln("restarting: %s", err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package updater
|
|||||||
import (
|
import (
|
||||||
"archive/zip"
|
"archive/zip"
|
||||||
"compress/gzip"
|
"compress/gzip"
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
@ -11,7 +12,9 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
clashHttp "github.com/Dreamacro/clash/component/http"
|
||||||
"github.com/Dreamacro/clash/constant"
|
"github.com/Dreamacro/clash/constant"
|
||||||
"github.com/Dreamacro/clash/log"
|
"github.com/Dreamacro/clash/log"
|
||||||
)
|
)
|
||||||
@ -19,30 +22,24 @@ import (
|
|||||||
// modify from https://github.com/AdguardTeam/AdGuardHome/blob/595484e0b3fb4c457f9bb727a6b94faa78a66c5f/internal/updater/updater.go
|
// modify from https://github.com/AdguardTeam/AdGuardHome/blob/595484e0b3fb4c457f9bb727a6b94faa78a66c5f/internal/updater/updater.go
|
||||||
// Updater is the Clash.Meta updater.
|
// Updater is the Clash.Meta updater.
|
||||||
var (
|
var (
|
||||||
client http.Client
|
|
||||||
|
|
||||||
goarch string
|
goarch string
|
||||||
goos string
|
goos string
|
||||||
goarm string
|
goarm string
|
||||||
gomips string
|
gomips string
|
||||||
|
|
||||||
workDir string
|
workDir string
|
||||||
versionCheckURL string
|
|
||||||
|
|
||||||
// mu protects all fields below.
|
// mu protects all fields below.
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
|
|
||||||
// TODO(a.garipov): See if all of these fields actually have to be in
|
|
||||||
// this struct.
|
|
||||||
currentExeName string // 当前可执行文件
|
currentExeName string // 当前可执行文件
|
||||||
updateDir string // 更新目录
|
updateDir string // 更新目录
|
||||||
packageName string // 更新压缩文件
|
packageName string // 更新压缩文件
|
||||||
backupDir string // 备份目录
|
backupDir string // 备份目录
|
||||||
backupExeName string // 备份文件名
|
backupExeName string // 备份文件名
|
||||||
updateExeName string // 更新后的可执行文件
|
updateExeName string // 更新后的可执行文件
|
||||||
unpackedFile string
|
|
||||||
|
|
||||||
baseURL string = "https://ghproxy.com/https://github.com/MetaCubeX/Clash.Meta/releases/download/Prerelease-Alpha/clash.meta"
|
baseURL string = "https://github.com/MetaCubeX/Clash.Meta/releases/download/Prerelease-Alpha/clash.meta"
|
||||||
versionURL string = "https://github.com/MetaCubeX/Clash.Meta/releases/download/Prerelease-Alpha/version.txt"
|
versionURL string = "https://github.com/MetaCubeX/Clash.Meta/releases/download/Prerelease-Alpha/version.txt"
|
||||||
packageURL string
|
packageURL string
|
||||||
latestVersion string
|
latestVersion string
|
||||||
@ -59,9 +56,18 @@ func (e *updateError) Error() string {
|
|||||||
// Update performs the auto-updater. It returns an error if the updater failed.
|
// Update performs the auto-updater. It returns an error if the updater failed.
|
||||||
// If firstRun is true, it assumes the configuration file doesn't exist.
|
// If firstRun is true, it assumes the configuration file doesn't exist.
|
||||||
func Update() (err error) {
|
func Update() (err error) {
|
||||||
|
mu.Lock()
|
||||||
|
defer mu.Unlock()
|
||||||
|
|
||||||
goos = runtime.GOOS
|
goos = runtime.GOOS
|
||||||
goarch = runtime.GOARCH
|
goarch = runtime.GOARCH
|
||||||
latestVersion = getLatestVersion()
|
latestVersion, err = getLatestVersion()
|
||||||
|
if err != nil {
|
||||||
|
err := &updateError{Message: err.Error()}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Infoln("current version alpha-%s, latest version alpha-%s", constant.Version, latestVersion)
|
||||||
|
|
||||||
if latestVersion == constant.Version {
|
if latestVersion == constant.Version {
|
||||||
err := &updateError{Message: "Already using latest version"}
|
err := &updateError{Message: "Already using latest version"}
|
||||||
@ -69,10 +75,6 @@ func Update() (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateDownloadURL()
|
updateDownloadURL()
|
||||||
mu.Lock()
|
|
||||||
defer mu.Unlock()
|
|
||||||
|
|
||||||
log.Infoln("current version alpha-%s", constant.Version)
|
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -88,7 +90,6 @@ func Update() (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
workDir = filepath.Dir(execPath)
|
workDir = filepath.Dir(execPath)
|
||||||
//log.Infoln("workDir %s", execPath)
|
|
||||||
|
|
||||||
err = prepare(execPath)
|
err = prepare(execPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -107,6 +108,11 @@ func Update() (err error) {
|
|||||||
return fmt.Errorf("unpacking: %w", err)
|
return fmt.Errorf("unpacking: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = backup()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("replacing: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
err = replace()
|
err = replace()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("replacing: %w", err)
|
return fmt.Errorf("replacing: %w", err)
|
||||||
@ -115,14 +121,6 @@ func Update() (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// VersionCheckURL returns the version check URL.
|
|
||||||
func VersionCheckURL() (vcu string) {
|
|
||||||
mu.RLock()
|
|
||||||
defer mu.RUnlock()
|
|
||||||
|
|
||||||
return versionCheckURL
|
|
||||||
}
|
|
||||||
|
|
||||||
// prepare fills all necessary fields in Updater object.
|
// prepare fills all necessary fields in Updater object.
|
||||||
func prepare(exePath string) (err error) {
|
func prepare(exePath string) (err error) {
|
||||||
updateDir = filepath.Join(workDir, "meta-update")
|
updateDir = filepath.Join(workDir, "meta-update")
|
||||||
@ -142,7 +140,7 @@ func prepare(exePath string) (err error) {
|
|||||||
updateExeName = "clash.meta" + "-" + goos + "-" + goarch
|
updateExeName = "clash.meta" + "-" + goos + "-" + goarch
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infoln("updateExeName: %s ,currentExeName: %s", updateExeName, currentExeName)
|
log.Infoln("updateExeName: %s ", updateExeName)
|
||||||
|
|
||||||
backupExeName = filepath.Join(backupDir, filepath.Base(exePath))
|
backupExeName = filepath.Join(backupDir, filepath.Base(exePath))
|
||||||
updateExeName = filepath.Join(updateDir, updateExeName)
|
updateExeName = filepath.Join(updateDir, updateExeName)
|
||||||
@ -168,13 +166,13 @@ func unpack() error {
|
|||||||
|
|
||||||
log.Debugln("updater: unpacking package")
|
log.Debugln("updater: unpacking package")
|
||||||
if strings.HasSuffix(pkgNameOnly, ".zip") {
|
if strings.HasSuffix(pkgNameOnly, ".zip") {
|
||||||
unpackedFile, err = zipFileUnpack(packageName, updateDir)
|
_, err = zipFileUnpack(packageName, updateDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf(".zip unpack failed: %w", err)
|
return fmt.Errorf(".zip unpack failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if strings.HasSuffix(pkgNameOnly, ".gz") {
|
} else if strings.HasSuffix(pkgNameOnly, ".gz") {
|
||||||
unpackedFile, err = gzFileUnpack(packageName, updateDir)
|
_, err = gzFileUnpack(packageName, updateDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf(".gz unpack failed: %w", err)
|
return fmt.Errorf(".gz unpack failed: %w", err)
|
||||||
}
|
}
|
||||||
@ -186,25 +184,37 @@ func unpack() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// backup makes a backup of the current configuration and supporting files. It
|
||||||
|
// ignores the configuration file if firstRun is true.
|
||||||
|
func backup() (err error) {
|
||||||
|
log.Infoln("updater: backing up current Exefile")
|
||||||
|
_ = os.Mkdir(backupDir, 0o755)
|
||||||
|
|
||||||
|
err = copyFile(currentExeName, backupExeName)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("copySupportingFiles(%s, %s) failed: %w", currentExeName, backupExeName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// replace moves the current executable with the updated one and also copies the
|
// replace moves the current executable with the updated one and also copies the
|
||||||
// supporting files.
|
// supporting files.
|
||||||
func replace() error {
|
func replace() error {
|
||||||
//err := copySupportingFiles(unpackedFiles, updateDir, workDir)
|
var err error
|
||||||
//if err != nil {
|
|
||||||
// return fmt.Errorf("copySupportingFiles(%s, %s) failed: %w", updateDir, workDir, err)
|
|
||||||
//}
|
|
||||||
|
|
||||||
log.Infoln("updater: renaming: %s to %s", currentExeName, backupExeName)
|
// log.Infoln("updater: renaming: %s to %s", currentExeName, backupExeName)
|
||||||
err := os.Rename(currentExeName, backupExeName)
|
// err := os.Rename(currentExeName, backupExeName)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
return err
|
// return err
|
||||||
}
|
// }
|
||||||
|
|
||||||
if goos == "windows" {
|
if goos == "windows" {
|
||||||
// rename fails with "File in use" error
|
// rename fails with "File in use" error
|
||||||
log.Infoln("copying:%s to %s", updateExeName, currentExeName)
|
log.Infoln("copying: %s to %s", updateExeName, currentExeName)
|
||||||
err = copyFile(updateExeName, currentExeName)
|
err = copyFile(updateExeName, currentExeName)
|
||||||
} else {
|
} else {
|
||||||
|
log.Infoln("copying: %s to %s", updateExeName, currentExeName)
|
||||||
err = os.Rename(updateExeName, currentExeName)
|
err = os.Rename(updateExeName, currentExeName)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -226,8 +236,11 @@ const MaxPackageFileSize = 32 * 1024 * 1024
|
|||||||
|
|
||||||
// Download package file and save it to disk
|
// Download package file and save it to disk
|
||||||
func downloadPackageFile() (err error) {
|
func downloadPackageFile() (err error) {
|
||||||
var resp *http.Response
|
// var resp *http.Response
|
||||||
resp, err = client.Get(packageURL)
|
// resp, err = client.Get(packageURL)
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*90)
|
||||||
|
defer cancel()
|
||||||
|
resp, err := clashHttp.HttpRequest(ctx, packageURL, http.MethodGet, http.Header{"User-Agent": {"clash"}}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("http request failed: %w", err)
|
return fmt.Errorf("http request failed: %w", err)
|
||||||
}
|
}
|
||||||
@ -255,11 +268,11 @@ func downloadPackageFile() (err error) {
|
|||||||
log.Debugln("updateDir %s", updateDir)
|
log.Debugln("updateDir %s", updateDir)
|
||||||
err = os.Mkdir(updateDir, 0o755)
|
err = os.Mkdir(updateDir, 0o755)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Errorf("mkdir error: %w", err)
|
return fmt.Errorf("mkdir error: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugln("updater: saving package to file %s", packageName)
|
log.Debugln("updater: saving package to file %s", packageName)
|
||||||
err = os.WriteFile(packageName, body, 0o755)
|
err = os.WriteFile(packageName, body, 0o644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("os.WriteFile() failed: %w", err)
|
return fmt.Errorf("os.WriteFile() failed: %w", err)
|
||||||
}
|
}
|
||||||
@ -405,10 +418,12 @@ func copyFile(src, dst string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getLatestVersion() string {
|
func getLatestVersion() (version string, err error) {
|
||||||
resp, err := http.Get(versionURL)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||||
|
defer cancel()
|
||||||
|
resp, err := clashHttp.HttpRequest(ctx, versionURL, http.MethodGet, http.Header{"User-Agent": {"clash"}}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return "", fmt.Errorf("get Latest Version fail: %w", err)
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
closeErr := resp.Body.Close()
|
closeErr := resp.Body.Close()
|
||||||
@ -419,11 +434,10 @@ func getLatestVersion() string {
|
|||||||
|
|
||||||
body, err := io.ReadAll(resp.Body)
|
body, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return "", fmt.Errorf("get Latest Version fail: %w", err)
|
||||||
}
|
}
|
||||||
content := strings.TrimRight(string(body), "\n")
|
content := strings.TrimRight(string(body), "\n")
|
||||||
log.Infoln("latest:%s", content)
|
return content, nil
|
||||||
return content
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateDownloadURL() {
|
func updateDownloadURL() {
|
||||||
|
Reference in New Issue
Block a user