Files
BedrockFetch/bds/bds.go
Matheus Sampaio Queiroga 0f0eeef675 Remove javascript
Signed-off-by: Matheus Sampaio Queiroga <srherobrine20@gmail.com>
2024-04-04 00:29:33 -03:00

234 lines
5.6 KiB
Go

package bds
import (
"archive/tar"
"archive/zip"
"compress/gzip"
"encoding/json"
"fmt"
"io"
"os"
"path/filepath"
"strings"
"time"
"sirherobrine23.org/minecraft-server/bedrockfetch/internal/convert"
"sirherobrine23.org/minecraft-server/bedrockfetch/internal/request"
gitea "sirherobrine23.org/minecraft-server/bedrockfetch/internal/tea"
)
type BedrockVersionsTarget struct {
NodePlatform string `json:"Platform"` // Nodejs Platform string
NodeArch string `json:"Arch"` // Nodejs Archs
ZipFile string `json:"zip"` // Local file and http to remote
ZipSHA1 string `json:"zipSHA1"` // File SHA1
TarFile string `json:"tar"` // Local file and http to remote
TarSHA1 string `json:"tarSHA1"` // File SHA1
}
type BedrockVersions struct {
Version string `json:"version"`
DateRelease time.Time `json:"releaseDate"`
ReleaseType string `json:"type"`
Targets []BedrockVersionsTarget `json:"targets"`
}
var (
VersionsPathFile, _ = filepath.Abs("./versions.json")
Versions = make(map[string]BedrockVersions)
)
func init() {
LoadLocalVersions()
}
func AddNewVersion(v BedrockVersions) {
Versions[v.Version] = v
}
func LoadLocalVersions() error {
file, err := os.Open(VersionsPathFile)
if err != nil {
return err
}
defer file.Close()
localEnv := []BedrockVersions{}
err = json.NewDecoder(file).Decode(&localEnv)
if err != nil {
return err
}
for _, ver := range localEnv {
Versions[ver.Version] = ver
}
return nil
}
func SaveLocalVersions() error {
doArray := []BedrockVersions{}
for _, ver := range Versions {
doArray = append(doArray, ver)
}
data, err := json.MarshalIndent(&doArray, "", " ")
if err != nil {
return err
}
return os.WriteFile(VersionsPathFile, data, os.FileMode(0o666))
}
func (bdsRelease *BedrockVersions) UploadRelease() error {
tea, err := gitea.CreateRelease(gitea.GiteaRelease{
AuthToken: gitea.Token,
TagName: bdsRelease.Version,
Name: bdsRelease.Version,
IsPrerelease: bdsRelease.ReleaseType != "release",
IsDraft: true,
FileAssets: []gitea.GiteaAsset{},
})
if err != nil {
return err
}
fmt.Printf("Uploading %s\n", bdsRelease.Version)
for targetIndex, target := range bdsRelease.Targets {
// Zip upload
zipStr, err := os.Open(target.ZipFile)
if err != nil {
return err
}
filename := fmt.Sprintf("%s-%s.zip", target.NodeArch, target.NodePlatform)
fmt.Printf("Uploading %s: %s\n", bdsRelease.Version, filename)
infoZip, err := tea.UploadAsset(filename, zipStr)
if err != nil {
return err
}
bdsRelease.Targets[targetIndex].ZipFile = infoZip.FileUrl
// Tar upload
tarStr, err := os.Open(target.TarFile)
if err != nil {
return err
}
filename = fmt.Sprintf("%s-%s.tgz", target.NodeArch, target.NodePlatform)
fmt.Printf("Uploading %s: %s\n", bdsRelease.Version, filename)
infoTar, err := tea.UploadAsset(filename, tarStr)
if err != nil {
return err
}
bdsRelease.Targets[targetIndex].TarFile = infoTar.FileUrl
}
tea.IsDraft = false
err = tea.UpdateRelease()
if err != nil {
return err
}
return nil
}
// Download zip file and convert to .tgz and set file path to ZipFile and TarFile
func (assert *BedrockVersionsTarget) Download() error {
zipSplited := strings.Split(assert.ZipFile, "/")[len(strings.Split(assert.ZipFile, "/"))-2:]
zipFile := filepath.Join(os.TempDir(), "bdsfetch", filepath.Join(zipSplited...))
tarFile := strings.Replace(zipFile, ".zip", ".tgz", 1)
os.MkdirAll(filepath.Dir(zipFile), os.FileMode(0o666))
// Get file stream
_, res, err := request.Request(request.RequestOptions{
Url: assert.ZipFile,
HttpError: true,
Method: "GET",
})
defer res.Body.Close()
if err != nil {
return err
}
fmt.Printf("Downloading %s, size %s\n", assert.ZipFile, convert.ByteCountSI(res.ContentLength))
// Create zip file
zipFileStream, err := os.Create(zipFile)
if err != nil {
return err
}
// Copy to file
_, err = io.Copy(zipFileStream, res.Body)
if err != nil {
return err
}
fmt.Printf("Download %q complete\n", assert.ZipFile)
// Create zip file
tarFileStream, err := os.Create(tarFile)
if err != nil {
return err
}
gzStr := gzip.NewWriter(tarFileStream)
tarStr := tar.NewWriter(gzStr)
defer (func() {
tarStr.Close()
gzStr.Close()
tarFileStream.Close()
})()
zipStats, _ := zipFileStream.Stat()
zipStr, err := zip.NewReader(zipFileStream, zipStats.Size())
if err != nil {
return err
}
fmt.Printf("zip (%q) to tgz (%q)\n", filepath.Base(zipFile), filepath.Base(tarFile))
for _, fileEntry := range zipStr.File {
fileInfo := fileEntry.FileInfo()
tarhead := tar.Header{
Name: fileEntry.Name,
ChangeTime: fileEntry.Modified,
ModTime: fileEntry.Modified,
Size: fileInfo.Size(),
Mode: int64(fileInfo.Mode()),
}
if fileInfo.IsDir() {
tarhead.Size = 0
}
if err = tarStr.WriteHeader(&tarhead); err != nil {
return fmt.Errorf("unable to get entry content: %s", err)
}
// fmt.Printf("zip (%q) to tgz (%q): %s, size: %s\n", filepath.Base(zipFile), filepath.Base(tarFile), fileEntry.Name, convert.ByteCountSI(fileInfo.Size()))
if !fileInfo.IsDir() {
fileContent, _err := fileEntry.Open()
if _err != nil {
return fmt.Errorf("unable to get entry content: %s", _err)
}
_, err = io.Copy(tarStr, fileContent)
if !(err == nil || err == io.EOF) {
return fmt.Errorf("cannot copy file (%s) content: %s", fileEntry.Name, err)
}
fileContent.Close()
}
}
// Save zip info
assert.ZipFile = zipFile
assert.ZipSHA1, _ = convert.FileSHA1(zipFile)
// Save tgz info
assert.TarFile = tarFile
assert.TarSHA1, _ = convert.FileSHA1(tarFile)
return nil
}