Matheus Sampaio Queiroga
27021fde73
All checks were successful
Find and Upload Minecraft Server versions / build (push) Successful in 14s
Signed-off-by: Matheus Sampaio Queiroga <srherobrine20@gmail.com>
227 lines
6.5 KiB
Go
227 lines
6.5 KiB
Go
package tea
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"mime/multipart"
|
|
"net/http"
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
|
|
"sirherobrine23.org/go-bds/go-bds/request"
|
|
)
|
|
|
|
const Repo string = "go-bds/BedrockFetch" // Default repository
|
|
|
|
var (
|
|
Token string = (func() string {
|
|
if ghToken := os.Getenv("GH_TOKEN"); len(ghToken) > 0 {
|
|
return ghToken
|
|
} else if githubToken := os.Getenv("GITHUB_TOKEN"); len(githubToken) > 0 {
|
|
return githubToken
|
|
} else if giteaToken := os.Getenv("GITEA_TOKEN"); len(giteaToken) > 0 {
|
|
return giteaToken
|
|
}
|
|
return ""
|
|
})()
|
|
|
|
RootURL string = func() string {
|
|
if data := os.Getenv("GITHUB_SERVER_URL"); data != "" {
|
|
return data
|
|
}
|
|
return "https://sirherobrine23.com.br"
|
|
}()
|
|
|
|
GiteaReleaseURI = fmt.Sprintf("%s/api/v1/repos/%s/releases", RootURL, Repo) // Gitea api release
|
|
|
|
ErrToken error = errors.New("set Gitea token in Env (GH_TOKEN || GITHUB_TOKEN || GITEA_TOKEN)")
|
|
ErrBackend error = errors.New("catch 500 error in server api")
|
|
ErrNoExist error = errors.New("repository, organization or endpoint dont exists")
|
|
)
|
|
|
|
type GiteaAsset struct {
|
|
Id int64 `json:"id"`
|
|
FileSize int64 `json:"size"`
|
|
Downloads int64 `json:"download_count"`
|
|
Uuid string `json:"uuid"`
|
|
FileUrl string `json:"browser_download_url"`
|
|
FileName string `json:"name"`
|
|
Create time.Time `json:"created_at"`
|
|
}
|
|
|
|
type GiteaRelease struct {
|
|
ReleaseId int64 `json:"id,omitempty"` // Release id
|
|
TagName string `json:"tag_name"` // Release tag name
|
|
Name string `json:"name,omitempty"` // Release name
|
|
Body string `json:"body,omitempty"` // Release body
|
|
IsPrerelease bool `json:"prerelease"` // Set Pre-release
|
|
IsDraft bool `json:"draft"` // Set release to draft
|
|
FileAssets []GiteaAsset `json:"assets,omitempty"` // Files in release
|
|
}
|
|
|
|
type giteaError struct {
|
|
Errors []string `json:"errors"`
|
|
TeaError string `json:"error"`
|
|
Message string `json:"message"`
|
|
Url string `json:"url"`
|
|
}
|
|
|
|
func processGiteaError(res *http.Response) error {
|
|
switch res.StatusCode {
|
|
case 401:
|
|
return ErrToken
|
|
case 409:
|
|
return fmt.Errorf("error format response")
|
|
case 422:
|
|
return fmt.Errorf("error in format response related to input validation")
|
|
case 404:
|
|
if strings.Contains(res.Header.Get("Content-Type"), "application/json") {
|
|
var data giteaError
|
|
defer res.Body.Close()
|
|
if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
|
|
return ErrNoExist
|
|
} else if len(data.Errors) > 0 {
|
|
return fmt.Errorf("gitea api, errors: %s, %s", data.Message, strings.Join(data.Errors, ", "))
|
|
}
|
|
return fmt.Errorf(data.Message)
|
|
}
|
|
return ErrNoExist
|
|
case 500, 501:
|
|
if strings.Contains(res.Header.Get("Content-Type"), "application/json") {
|
|
var data giteaError
|
|
defer res.Body.Close()
|
|
if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
|
|
return ErrNoExist
|
|
} else if len(data.Errors) > 0 {
|
|
return fmt.Errorf("gitea api, errors: %s, %s", data.Message, strings.Join(data.Errors, ", "))
|
|
}
|
|
return fmt.Errorf(data.Message)
|
|
}
|
|
return ErrBackend
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func processJsonRequest(req request.RequestOptions, targetStruct any) (*http.Response, error) {
|
|
res, err := req.Request()
|
|
if err != nil {
|
|
if res == nil {
|
|
return res, err
|
|
}
|
|
originalErr := err
|
|
if err = processGiteaError(res); err != nil {
|
|
return res, err
|
|
}
|
|
return res, originalErr
|
|
}
|
|
defer res.Body.Close()
|
|
if err = processGiteaError(res); err != nil {
|
|
return res, err
|
|
} else if err := json.NewDecoder(res.Body).Decode(targetStruct); err != nil {
|
|
return res, err
|
|
}
|
|
return res, nil
|
|
}
|
|
|
|
// Get release, if not exists create
|
|
func Release(IsPrerelease, Draft bool, TagName, Name, Body string) (*GiteaRelease, error) {
|
|
if TagName = strings.TrimSpace(TagName); len(TagName) == 0 {
|
|
return nil, fmt.Errorf("set valid tag to create release")
|
|
} else if Name = strings.TrimSpace(Name); len(Name) == 0 {
|
|
Name = TagName
|
|
}
|
|
|
|
var req request.RequestOptions
|
|
req.Url = fmt.Sprintf("%s/tags/%s", GiteaReleaseURI, TagName)
|
|
req.Headers = http.Header{}
|
|
if Token != "" {
|
|
req.Headers.Set("Authorization", fmt.Sprintf("token %s", Token))
|
|
}
|
|
|
|
var giteaRel GiteaRelease
|
|
res, err := processJsonRequest(req, &giteaRel)
|
|
if err != nil {
|
|
if res.StatusCode == 404 {
|
|
if len(Token) == 0 {
|
|
return nil, ErrToken
|
|
}
|
|
body, err := json.Marshal(&GiteaRelease{TagName: TagName, Name: Name, Body: Body, IsPrerelease: IsPrerelease, IsDraft: Draft})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
req.Method = "POST"
|
|
req.Url = GiteaReleaseURI
|
|
req.Body = bytes.NewReader(body)
|
|
req.Headers.Set("Content-Type", "application/json")
|
|
|
|
_, err = processJsonRequest(req, &giteaRel)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("gitea api, create release: %s", err.Error())
|
|
}
|
|
return &giteaRel, nil
|
|
}
|
|
return nil, fmt.Errorf("gitea api: %s", err.Error())
|
|
}
|
|
return &giteaRel, nil
|
|
}
|
|
|
|
func (rel GiteaRelease) ExistsFile(filename string) bool {
|
|
return rel.GetFile(filename) != nil
|
|
}
|
|
|
|
func (rel GiteaRelease) GetFile(filename string) *GiteaAsset {
|
|
for _, asset := range rel.FileAssets {
|
|
if asset.FileName == filename {
|
|
return &asset
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (asset GiteaAsset) Download() (io.ReadCloser, error) {
|
|
var req request.RequestOptions
|
|
req.Headers = http.Header{"Authorization": {fmt.Sprintf("token %s", Token)}}
|
|
res, err := req.Request()
|
|
if err != nil {
|
|
return nil, err
|
|
} else if res.StatusCode != 200 {
|
|
return nil, fmt.Errorf("cannot get file")
|
|
}
|
|
return res.Body, err
|
|
}
|
|
|
|
type UploadMap map[string]io.Reader
|
|
|
|
func (rel *GiteaRelease) Upload(filename string, fileBody io.Reader) (*GiteaAsset, error) {
|
|
body := new(bytes.Buffer)
|
|
writer := multipart.NewWriter(body)
|
|
part, err := writer.CreateFormFile("attachment", filename)
|
|
if err != nil {
|
|
return nil, err
|
|
} else if _, err = io.Copy(part, fileBody); err != nil {
|
|
return nil, err
|
|
} else if err = writer.Close(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var req request.RequestOptions
|
|
req.Url = fmt.Sprintf("%s/%d/assets", GiteaReleaseURI, rel.ReleaseId)
|
|
req.Method = "POST"
|
|
req.Headers = http.Header{"Authorization": {fmt.Sprintf("token %s", Token)}, "Content-Type": {writer.FormDataContentType()}}
|
|
req.Body = body
|
|
|
|
var asset GiteaAsset
|
|
res, err := req.Do(&asset)
|
|
if err != nil {
|
|
return nil, err
|
|
} else if res.StatusCode != 201 {
|
|
return nil, fmt.Errorf("cannot upload %q to release, code: %d (%s)", filename, res.StatusCode, res.Status)
|
|
}
|
|
rel.FileAssets = append(rel.FileAssets, asset)
|
|
return &asset, nil
|
|
}
|