mirror of
https://github.com/packwiz/packwiz.git
synced 2025-04-19 21:16:30 +02:00
Mod metadata retrieval
This commit is contained in:
parent
6c820a3748
commit
3fdac51d22
10
core/pack.go
10
core/pack.go
@ -2,6 +2,7 @@ package core
|
|||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -89,3 +90,12 @@ func (pack Pack) Write() error {
|
|||||||
return enc.Encode(pack)
|
return enc.Encode(pack)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetMCVersion gets the version of Minecraft this pack uses, if it has been correctly specified
|
||||||
|
func (pack Pack) GetMCVersion() (string, error) {
|
||||||
|
mcVersion, ok := pack.Versions["minecraft"]
|
||||||
|
if !ok {
|
||||||
|
return "", errors.New("No Minecraft version specified in modpack!")
|
||||||
|
}
|
||||||
|
return mcVersion, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -91,24 +91,43 @@ func cmdInstall(flags core.Flags, mod string) error {
|
|||||||
if len(mod) == 0 {
|
if len(mod) == 0 {
|
||||||
return cli.NewExitError("You must specify a mod.", 1)
|
return cli.NewExitError("You must specify a mod.", 1)
|
||||||
}
|
}
|
||||||
//fmt.Println("Not implemented yet!")
|
pack, err := core.LoadPack(flags)
|
||||||
|
if err != nil {
|
||||||
|
return cli.NewExitError(err, 1)
|
||||||
|
}
|
||||||
|
index, err := pack.LoadIndex()
|
||||||
|
if err != nil {
|
||||||
|
return cli.NewExitError(err, 1)
|
||||||
|
}
|
||||||
|
mcVersion, err := pack.GetMCVersion()
|
||||||
|
if err != nil {
|
||||||
|
return cli.NewExitError(err, 1)
|
||||||
|
}
|
||||||
|
|
||||||
done, modID, fileID, err := getFileIDsFromString(mod)
|
done, modID, fileID, err := getFileIDsFromString(mod)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
return cli.NewExitError(err, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !done {
|
if !done {
|
||||||
done, modID, err = getModIDFromString(mod)
|
done, modID, err = getModIDFromString(mod)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
return cli.NewExitError(err, 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: fallback to CurseMeta search
|
// TODO: fallback to CurseMeta search
|
||||||
// TODO: how to do interactive choices? automatically assume version? ask mod from list? choose first?
|
// TODO: how to do interactive choices? automatically assume version? ask mod from list? choose first?
|
||||||
|
|
||||||
fmt.Printf("ids: %d %d %v", modID, fileID, done)
|
fmt.Printf("ids: %d %d %v\n", modID, fileID, done)
|
||||||
|
|
||||||
|
if done {
|
||||||
|
fmt.Println(mcVersion)
|
||||||
|
info, err := getModInfo(modID)
|
||||||
|
fmt.Println(err)
|
||||||
|
fmt.Println(info)
|
||||||
|
_ = index
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
package curseforge
|
package curseforge
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
@ -7,6 +8,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -109,10 +111,10 @@ type modInfo struct {
|
|||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Slug string `json:"slug"`
|
Slug string `json:"slug"`
|
||||||
ID int `json:"id"`
|
ID int `json:"id"`
|
||||||
LatestFiles []modFile `json:"latestFiles"`
|
LatestFiles []modFileInfo `json:"latestFiles"`
|
||||||
GameVersionLatestFiles []struct {
|
GameVersionLatestFiles []struct {
|
||||||
// TODO: check how twitch launcher chooses which one to use, when you are on beta/alpha channel?!
|
// TODO: check how twitch launcher chooses which one to use, when you are on beta/alpha channel?!
|
||||||
// or does it not have the concept of channels?!
|
// or does it not have the concept of release channels?!
|
||||||
GameVersion string `json:"gameVersion"`
|
GameVersion string `json:"gameVersion"`
|
||||||
ID int `json:"projectFileId"`
|
ID int `json:"projectFileId"`
|
||||||
Name string `json:"projectFileName"`
|
Name string `json:"projectFileName"`
|
||||||
@ -120,7 +122,7 @@ type modInfo struct {
|
|||||||
} `json:"gameVersionLatestFiles"`
|
} `json:"gameVersionLatestFiles"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func getModInfo(modid int) (modInfo, error) {
|
func getModInfo(modID int) (modInfo, error) {
|
||||||
// Uses the Staging CurseMeta api
|
// Uses the Staging CurseMeta api
|
||||||
var response struct {
|
var response struct {
|
||||||
modInfo
|
modInfo
|
||||||
@ -128,7 +130,7 @@ func getModInfo(modid int) (modInfo, error) {
|
|||||||
}
|
}
|
||||||
client := &http.Client{}
|
client := &http.Client{}
|
||||||
|
|
||||||
idStr := strconv.Itoa(modid)
|
idStr := strconv.Itoa(modID)
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", "https://staging_cursemeta.dries007.net/api/v3/direct/addon/"+idStr, nil)
|
req, err := http.NewRequest("GET", "https://staging_cursemeta.dries007.net/api/v3/direct/addon/"+idStr, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -153,25 +155,85 @@ func getModInfo(modid int) (modInfo, error) {
|
|||||||
return modInfo{}, fmt.Errorf("Error requesting mod metadata: %s", response.Description)
|
return modInfo{}, fmt.Errorf("Error requesting mod metadata: %s", response.Description)
|
||||||
}
|
}
|
||||||
|
|
||||||
if response.ID != modid {
|
if response.ID != modID {
|
||||||
return modInfo{}, fmt.Errorf("Unexpected addon ID in CurseForge response: %d/%d", modid, response.ID)
|
return modInfo{}, fmt.Errorf("Unexpected addon ID in CurseForge response: %d/%d", modID, response.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
return response.modInfo, nil
|
return response.modInfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type modFile struct {
|
const cfDateFormatString = "2006-01-02T15:04:05.999"
|
||||||
|
|
||||||
|
type cfDateFormat struct {
|
||||||
|
time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *cfDateFormat) UnmarshalJSON(input []byte) error {
|
||||||
|
trimmed := strings.Trim(string(input), `"`)
|
||||||
|
time, err := time.Parse(cfDateFormatString, trimmed)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
f.Time = time
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// modFileInfo is a subset of the deserialised JSON response from the Staging CurseMeta API for mod files
|
||||||
|
type modFileInfo struct {
|
||||||
ID int `json:"id"`
|
ID int `json:"id"`
|
||||||
FileName string `json:"fileNameOnDisk"`
|
FileName string `json:"fileNameOnDisk"`
|
||||||
FriendlyName string `json:"fileName"`
|
FriendlyName string `json:"fileName"`
|
||||||
Date time.Time `json:"fileDate"`
|
Date cfDateFormat `json:"fileDate"`
|
||||||
Length int `json:"fileLength"`
|
Length int `json:"fileLength"`
|
||||||
FileType int `json:"releaseType"`
|
FileType int `json:"releaseType"`
|
||||||
// fileStatus? means latest/preferred?
|
// fileStatus? means latest/preferred?
|
||||||
GameVersions []string `json:"gameVersion"`
|
GameVersions []string `json:"gameVersion"`
|
||||||
|
Fingerprint int `json:"packageFingerprint"`
|
||||||
Dependencies []struct {
|
Dependencies []struct {
|
||||||
ModID int `json:"addonId"`
|
ModID int `json:"addonId"`
|
||||||
Type int `json:"type"`
|
Type int `json:"type"`
|
||||||
} `json:"dependencies"`
|
} `json:"dependencies"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getFileInfo(modID int, fileID int) (modFileInfo, error) {
|
||||||
|
// Uses the Staging CurseMeta api
|
||||||
|
var response struct {
|
||||||
|
modFileInfo
|
||||||
|
curseMetaError
|
||||||
|
}
|
||||||
|
client := &http.Client{}
|
||||||
|
|
||||||
|
modIDStr := strconv.Itoa(modID)
|
||||||
|
fileIDStr := strconv.Itoa(fileID)
|
||||||
|
|
||||||
|
req, err := http.NewRequest("GET", "https://staging_cursemeta.dries007.net/api/v3/direct/addon/"+modIDStr+"/file/"+fileIDStr, nil)
|
||||||
|
if err != nil {
|
||||||
|
return modFileInfo{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: make this configurable application-wide
|
||||||
|
req.Header.Set("User-Agent", "comp500/packwiz client")
|
||||||
|
req.Header.Set("Accept", "application/json")
|
||||||
|
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return modFileInfo{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = json.NewDecoder(resp.Body).Decode(&response)
|
||||||
|
if err != nil && err != io.EOF {
|
||||||
|
return modFileInfo{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if response.Error {
|
||||||
|
return modFileInfo{}, fmt.Errorf("Error requesting mod file metadata: %s", response.Description)
|
||||||
|
}
|
||||||
|
|
||||||
|
if response.ID != fileID {
|
||||||
|
return modFileInfo{}, fmt.Errorf("Unexpected file ID in CurseForge response: %d/%d", modID, response.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.modFileInfo, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user