mirror of
https://github.com/packwiz/packwiz.git
synced 2025-04-19 13:06:30 +02:00
- "file" -> "asset" - "version" -> "tag" or "release" (where appropriate) - fix updater.go for upstream changes - make printed log messages more similar to those of other modules - move http request function(s) to separate file "request.go" - remove the concept of a "Mod"; we're using "Repo"s (GitHub repositories) instead - remove unnecessary fields in structs - use sha256 instead of sha1 for asset checksums Signed-off-by: unilock <unilock@fennet.rentals>
111 lines
2.4 KiB
Go
111 lines
2.4 KiB
Go
package github
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
|
|
"github.com/mitchellh/mapstructure"
|
|
"github.com/packwiz/packwiz/cmd"
|
|
"github.com/packwiz/packwiz/core"
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
var githubCmd = &cobra.Command{
|
|
Use: "github",
|
|
Aliases: []string{"gh"},
|
|
Short: "Manage github-based mods",
|
|
}
|
|
|
|
func init() {
|
|
cmd.Add(githubCmd)
|
|
core.Updaters["github"] = ghUpdater{}
|
|
}
|
|
|
|
func fetchRepo(slug string) (Repo, error) {
|
|
var repo Repo
|
|
|
|
res, err := http.Get(githubApiUrl + "repos/" + slug)
|
|
if err != nil {
|
|
return repo, err
|
|
}
|
|
|
|
defer res.Body.Close()
|
|
|
|
repoBody, err := io.ReadAll(res.Body)
|
|
if err != nil {
|
|
return repo, err
|
|
}
|
|
|
|
err = json.Unmarshal(repoBody, &repo)
|
|
if err != nil {
|
|
return repo, err
|
|
}
|
|
|
|
if repo.FullName == "" {
|
|
return repo, errors.New("invalid json while fetching mod: " + slug)
|
|
}
|
|
|
|
return repo, nil
|
|
}
|
|
|
|
type Repo struct {
|
|
ID int `json:"id"`
|
|
NodeID string `json:"node_id"` // TODO: use this with GH API, instead of name (to acct. for repo renames?) + store in mod.pw.toml
|
|
Name string `json:"name"` // "hello_world"
|
|
FullName string `json:"full_name"` // "owner/hello_world"
|
|
}
|
|
|
|
type Release struct {
|
|
URL string `json:"url"`
|
|
NodeID string `json:"node_id"` // TODO: probably also use this with GH API
|
|
TagName string `json:"tag_name"`
|
|
TargetCommitish string `json:"target_commitish"` // The branch of the release
|
|
Name string `json:"name"`
|
|
CreatedAt string `json:"created_at"`
|
|
Assets []Asset `json:"assets"`
|
|
}
|
|
|
|
type Asset struct {
|
|
URL string `json:"url"`
|
|
BrowserDownloadURL string `json:"browser_download_url"`
|
|
Name string `json:"name"`
|
|
}
|
|
|
|
func (u ghUpdateData) ToMap() (map[string]interface{}, error) {
|
|
newMap := make(map[string]interface{})
|
|
err := mapstructure.Decode(u, &newMap)
|
|
return newMap, err
|
|
}
|
|
|
|
func (u Asset) getSha256() (string, error) {
|
|
// TODO potentionally cache downloads to speed things up and avoid getting ratelimited by github!
|
|
mainHasher, err := core.GetHashImpl("sha256")
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
resp, err := http.Get(u.BrowserDownloadURL)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if resp.StatusCode != 200 {
|
|
return "", fmt.Errorf("invalid response status: %v", resp.StatusCode)
|
|
}
|
|
|
|
defer resp.Body.Close()
|
|
|
|
body, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
mainHasher.Write(body)
|
|
|
|
hash := mainHasher.Sum(nil)
|
|
|
|
return mainHasher.HashToString(hash), nil
|
|
}
|