packwiz/github/github.go
unilock 6116393310 github: fixes and improvements
- "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>
2024-04-15 14:48:57 -04:00

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
}