node build fixed
This commit is contained in:
300
seanime-2.9.10/internal/updater/download.go
Normal file
300
seanime-2.9.10/internal/updater/download.go
Normal file
@@ -0,0 +1,300 @@
|
||||
package updater
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"archive/zip"
|
||||
"compress/gzip"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"seanime/internal/util"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrExtractionFailed = errors.New("could not extract assets")
|
||||
)
|
||||
|
||||
// DownloadLatestRelease will download the latest release assets and extract them
|
||||
// If the decompression fails, the returned string will be the directory to the compressed file
|
||||
// If the decompression is successful, the returned string will be the directory to the extracted files
|
||||
func (u *Updater) DownloadLatestRelease(assetUrl, dest string) (string, error) {
|
||||
if u.LatestRelease == nil {
|
||||
return "", errors.New("no new release found")
|
||||
}
|
||||
|
||||
u.logger.Debug().Str("asset_url", assetUrl).Str("dest", dest).Msg("updater: Downloading latest release")
|
||||
|
||||
fpath, err := u.downloadAsset(assetUrl, dest)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
dest = filepath.Dir(fpath)
|
||||
|
||||
u.logger.Info().Str("dest", dest).Msg("updater: Downloaded release assets")
|
||||
|
||||
fp, err := u.decompressAsset(fpath, "")
|
||||
if err != nil {
|
||||
u.logger.Error().Err(err).Msg("updater: Failed to decompress release assets")
|
||||
return fp, ErrExtractionFailed
|
||||
}
|
||||
dest = fp
|
||||
|
||||
u.logger.Info().Str("dest", dest).Msg("updater: Successfully decompressed downloaded release assets")
|
||||
|
||||
return dest, nil
|
||||
}
|
||||
|
||||
func (u *Updater) DownloadLatestReleaseN(assetUrl, dest, folderName string) (string, error) {
|
||||
if u.LatestRelease == nil {
|
||||
return "", errors.New("no new release found")
|
||||
}
|
||||
|
||||
u.logger.Debug().Str("asset_url", assetUrl).Str("dest", dest).Msg("updater: Downloading latest release")
|
||||
|
||||
fpath, err := u.downloadAsset(assetUrl, dest)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
dest = filepath.Dir(fpath)
|
||||
|
||||
u.logger.Info().Str("dest", dest).Msg("updater: Downloaded release assets")
|
||||
|
||||
fp, err := u.decompressAsset(fpath, folderName)
|
||||
if err != nil {
|
||||
u.logger.Error().Err(err).Msg("updater: Failed to decompress release assets")
|
||||
return fp, err
|
||||
}
|
||||
dest = fp
|
||||
|
||||
u.logger.Info().Str("dest", dest).Msg("updater: Successfully decompressed downloaded release assets")
|
||||
|
||||
return dest, nil
|
||||
}
|
||||
|
||||
func (u *Updater) decompressZip(archivePath string, folderName string) (dest string, err error) {
|
||||
topFolderName := "seanime-" + u.LatestRelease.Version
|
||||
if folderName != "" {
|
||||
topFolderName = folderName
|
||||
}
|
||||
// "/seanime-repo/seanime-v1.0.0.zip" -> "/seanime-repo/seanime-1.0.0/"
|
||||
dest = filepath.Join(filepath.Dir(archivePath), topFolderName) // "/seanime-repo/seanime-v1.0.0"
|
||||
|
||||
// Check if the destination folder already exists
|
||||
if _, err := os.Stat(dest); err == nil {
|
||||
return dest, errors.New("destination folder already exists")
|
||||
}
|
||||
|
||||
// Create the destination folder
|
||||
err = os.MkdirAll(dest, os.ModePerm)
|
||||
if err != nil {
|
||||
return dest, err
|
||||
}
|
||||
|
||||
r, err := zip.OpenReader(archivePath)
|
||||
if err != nil {
|
||||
return dest, err
|
||||
}
|
||||
defer r.Close()
|
||||
|
||||
u.logger.Debug().Msg("updater: Decompressing release assets (zip)")
|
||||
|
||||
for _, f := range r.File {
|
||||
fpath := filepath.Join(dest, f.Name)
|
||||
if f.FileInfo().IsDir() {
|
||||
os.MkdirAll(fpath, os.ModePerm)
|
||||
continue
|
||||
}
|
||||
|
||||
if err = os.MkdirAll(filepath.Dir(fpath), os.ModePerm); err != nil {
|
||||
return dest, err
|
||||
}
|
||||
|
||||
outFile, err := os.OpenFile(fpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
|
||||
if err != nil {
|
||||
return dest, err
|
||||
}
|
||||
|
||||
rc, err := f.Open()
|
||||
if err != nil {
|
||||
outFile.Close()
|
||||
return dest, err
|
||||
}
|
||||
|
||||
_, err = io.Copy(outFile, rc)
|
||||
outFile.Close()
|
||||
rc.Close()
|
||||
|
||||
if err != nil {
|
||||
return dest, err
|
||||
}
|
||||
}
|
||||
|
||||
r.Close()
|
||||
|
||||
err = os.Remove(archivePath)
|
||||
if err != nil {
|
||||
u.logger.Error().Err(err).Msg("updater: Failed to remove compressed file")
|
||||
return dest, nil
|
||||
}
|
||||
|
||||
u.logger.Debug().Msg("updater: Decompressed release assets (zip)")
|
||||
|
||||
return dest, nil
|
||||
}
|
||||
|
||||
func (u *Updater) decompressTarGz(archivePath string, folderName string) (dest string, err error) {
|
||||
topFolderName := "seanime-" + u.LatestRelease.Version
|
||||
if folderName != "" {
|
||||
topFolderName = folderName
|
||||
}
|
||||
dest = filepath.Join(filepath.Dir(archivePath), topFolderName)
|
||||
|
||||
if _, err := os.Stat(dest); err == nil {
|
||||
return dest, errors.New("destination folder already exists")
|
||||
}
|
||||
|
||||
err = os.MkdirAll(dest, os.ModePerm)
|
||||
if err != nil {
|
||||
return dest, err
|
||||
}
|
||||
|
||||
file, err := os.Open(archivePath)
|
||||
if err != nil {
|
||||
return dest, err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
gzr, err := gzip.NewReader(file)
|
||||
if err != nil {
|
||||
return dest, err
|
||||
}
|
||||
defer gzr.Close()
|
||||
|
||||
tr := tar.NewReader(gzr)
|
||||
|
||||
u.logger.Debug().Msg("updater: Decompressing release assets (gzip)")
|
||||
|
||||
for {
|
||||
header, err := tr.Next()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return dest, err
|
||||
}
|
||||
|
||||
fpath := filepath.Join(dest, header.Name)
|
||||
if header.Typeflag == tar.TypeDir {
|
||||
if err := os.MkdirAll(fpath, os.ModePerm); err != nil {
|
||||
return dest, err
|
||||
}
|
||||
} else {
|
||||
if err := os.MkdirAll(filepath.Dir(fpath), os.ModePerm); err != nil {
|
||||
return dest, err
|
||||
}
|
||||
|
||||
outFile, err := os.Create(fpath)
|
||||
if err != nil {
|
||||
return dest, err
|
||||
}
|
||||
|
||||
if _, err := io.Copy(outFile, tr); err != nil {
|
||||
outFile.Close()
|
||||
return dest, err
|
||||
}
|
||||
outFile.Close()
|
||||
}
|
||||
}
|
||||
|
||||
gzr.Close()
|
||||
file.Close()
|
||||
|
||||
err = os.Remove(archivePath)
|
||||
if err != nil {
|
||||
u.logger.Error().Err(err).Msg("updater: Failed to remove compressed file")
|
||||
return dest, nil
|
||||
}
|
||||
|
||||
u.logger.Debug().Msg("updater: Decompressed release assets (gzip)")
|
||||
|
||||
return dest, nil
|
||||
}
|
||||
|
||||
// decompressAsset will uncompress the release assets and delete the compressed folder
|
||||
// - "/seanime-repo/seanime-v1.0.0.zip" -> "/seanime-repo/seanime-1.0.0/"
|
||||
func (u *Updater) decompressAsset(archivePath string, folderName string) (dest string, err error) {
|
||||
|
||||
defer util.HandlePanicInModuleWithError("updater/download/decompressAsset", &err)
|
||||
|
||||
u.logger.Debug().Str("archive_path", archivePath).Msg("updater: Decompressing release assets")
|
||||
|
||||
ext := filepath.Ext(archivePath)
|
||||
if ext == ".zip" {
|
||||
return u.decompressZip(archivePath, folderName)
|
||||
} else if ext == ".gz" {
|
||||
return u.decompressTarGz(archivePath, folderName)
|
||||
}
|
||||
|
||||
u.logger.Error().Msg("updater: Failed to decompress release assets, unsupported archive format")
|
||||
|
||||
return "", fmt.Errorf("unsupported archive format: %s", ext)
|
||||
|
||||
}
|
||||
|
||||
// downloadAsset will download the release assets to a folder
|
||||
// - "seanime-v1.zip" -> "/seanime-repo/seanime-v1.zip"
|
||||
func (u *Updater) downloadAsset(assetUrl, dest string) (fp string, err error) {
|
||||
|
||||
defer util.HandlePanicInModuleWithError("updater/download/downloadAsset", &err)
|
||||
|
||||
u.logger.Debug().Msg("updater: Downloading assets")
|
||||
|
||||
fp = u.getFilePath(assetUrl, dest)
|
||||
|
||||
// Get the data
|
||||
resp, err := http.Get(assetUrl)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
// Check if the request was successful (status code 200)
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return "", fmt.Errorf("failed to download file, %s", resp.Status)
|
||||
}
|
||||
|
||||
// Create the destination folder if it doesn't exist
|
||||
err = os.MkdirAll(dest, os.ModePerm)
|
||||
if err != nil {
|
||||
u.logger.Error().Err(err).Msg("updater: Failed to download assets")
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Create the file
|
||||
out, err := os.Create(fp)
|
||||
if err != nil {
|
||||
u.logger.Error().Err(err).Msg("updater: Failed to download assets")
|
||||
return "", err
|
||||
}
|
||||
defer out.Close()
|
||||
|
||||
// Write the body to file
|
||||
_, err = io.Copy(out, resp.Body)
|
||||
if err != nil {
|
||||
u.logger.Error().Err(err).Msg("updater: Failed to download assets")
|
||||
return "", err
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (u *Updater) getFilePath(url, dest string) string {
|
||||
// Get the file name from the URL
|
||||
fileName := filepath.Base(url)
|
||||
return filepath.Join(dest, fileName)
|
||||
}
|
||||
Reference in New Issue
Block a user