Rewrite part of importing to support other types

Going to scrap a load of this code though, as I am going to make it
re-request the file data
This commit is contained in:
comp500 2019-09-19 17:57:13 +01:00
parent bfa246ded4
commit fd9ecbe6d4

View File

@ -1,51 +1,39 @@
package curseforge package curseforge
import ( import (
"bufio"
"bytes"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io"
"io/ioutil"
"os" "os"
"path/filepath"
"strings"
"github.com/comp500/packwiz/core" "github.com/comp500/packwiz/core"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
type twitchPackMeta struct { type importPackFile interface {
Name string `json:"name"` Name() string
Path string `json:"installPath"` Open() (io.ReadCloser, error)
// TODO: javaArgsOverride? }
// TODO: allocatedMemory?
MCVersion string `json:"gameVersion"` type importPackMetadata interface {
Modloader struct { Name() string
Name string `json:"name"` Versions() map[string]string
} `json:"baseModLoader"` Mods() []struct {
// TODO: modpackOverrides? ID int
Mods []struct { File modFileInfo
ID int `json:"addonID"` }
File struct { GetFiles() ([]importPackFile, error)
// This is exactly the same as modFileInfo, but with capitalised
// FileNameOnDisk.
ID int `json:"id"`
FileName string `json:"FileNameOnDisk"`
FriendlyName string `json:"fileName"`
Date cfDateFormat `json:"fileDate"`
Length int `json:"fileLength"`
FileType int `json:"releaseType"`
// fileStatus? means latest/preferred?
DownloadURL string `json:"downloadUrl"`
GameVersions []string `json:"gameVersion"`
Fingerprint int `json:"packageFingerprint"`
Dependencies []struct {
ModID int `json:"addonId"`
Type int `json:"type"`
} `json:"dependencies"`
} `json:"installedFile"`
} `json:"installedAddons"`
} }
// importCmd represents the import command // importCmd represents the import command
var importCmd = &cobra.Command{ var importCmd = &cobra.Command{
Use: "import", Use: "import [modpack]",
Short: "Import an installed curseforge modpack", Short: "Import an installed curseforge modpack, from a download URL or a downloaded pack zip, or an installed metadata json file",
Args: cobra.ExactArgs(1), Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
pack, err := core.LoadPack() pack, err := core.LoadPack()
@ -59,25 +47,74 @@ var importCmd = &cobra.Command{
os.Exit(1) os.Exit(1)
} }
var packMeta twitchPackMeta var packImport importPackMetadata
// TODO: is this relative to something? if strings.HasPrefix(args[0], "http") {
f, err := os.Open(args[0]) fmt.Println("it do be a http doe")
if err != nil { os.Exit(0)
fmt.Println(err) } else {
os.Exit(1) // Attempt to read from file
} f, err := os.Open(args[0])
err = json.NewDecoder(f).Decode(&packMeta) if err != nil {
if err != nil { fmt.Printf("Error opening file: %s\n", err)
fmt.Println(err) os.Exit(1)
os.Exit(1) }
defer f.Close()
buf := bufio.NewReader(f)
header, err := buf.Peek(2)
if err != nil {
fmt.Printf("Error reading file: %s\n", err)
os.Exit(1)
}
// Check if file is a zip
if string(header) == "PK" {
fmt.Println("it do be a zip doe")
os.Exit(0)
} else {
// Read the whole file (as we are going to parse it multiple times)
fileData, err := ioutil.ReadAll(buf)
if err != nil {
fmt.Printf("Error reading file: %s\n", err)
os.Exit(1)
}
// Determine what format the file is
var jsonFile map[string]interface{}
err = json.Unmarshal(fileData, &jsonFile)
if err != nil {
fmt.Printf("Error parsing JSON: %s\n", err)
os.Exit(1)
}
isManifest := false
if v, ok := jsonFile["manifestType"]; ok {
isManifest = v.(string) == "minecraftModpack"
}
if isManifest {
fmt.Println("it do be a manifest doe")
os.Exit(0)
} else {
// Replace FileNameOnDisk with fileNameOnDisk
fileData = bytes.ReplaceAll(fileData, []byte("FileNameOnDisk"), []byte("fileNameOnDisk"))
packMeta := twitchInstalledPackMeta{}
err = json.Unmarshal(fileData, &packMeta)
if err != nil {
fmt.Printf("Error parsing JSON: %s\n", err)
os.Exit(1)
}
packImport = packMeta
}
}
} }
modIDs := make([]int, len(packMeta.Mods)) modsList := packImport.Mods()
for i, v := range packMeta.Mods { modIDs := make([]int, len(modsList))
for i, v := range modsList {
modIDs[i] = v.ID modIDs[i] = v.ID
} }
fmt.Println("Querying Curse API...") fmt.Println("Querying Curse API for mod info...")
modInfos, err := getModInfoMultiple(modIDs) modInfos, err := getModInfoMultiple(modIDs)
if err != nil { if err != nil {
@ -91,7 +128,7 @@ var importCmd = &cobra.Command{
} }
// TODO: multithreading???? // TODO: multithreading????
for _, v := range packMeta.Mods { for _, v := range modsList {
modInfoValue, ok := modInfosMap[v.ID] modInfoValue, ok := modInfosMap[v.ID]
if !ok { if !ok {
if len(v.File.FriendlyName) > 0 { if len(v.File.FriendlyName) > 0 {
@ -104,7 +141,7 @@ var importCmd = &cobra.Command{
fmt.Printf("Imported mod \"%s\" successfully!\n", modInfoValue.Name) fmt.Printf("Imported mod \"%s\" successfully!\n", modInfoValue.Name)
err = createModFile(modInfoValue, modFileInfo(v.File), &index) err = createModFile(modInfoValue, v.File, &index)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
os.Exit(1) os.Exit(1)
@ -134,3 +171,91 @@ var importCmd = &cobra.Command{
func init() { func init() {
curseforgeCmd.AddCommand(importCmd) curseforgeCmd.AddCommand(importCmd)
} }
type diskFile struct {
NameInternal string
Base string
}
func (f diskFile) Name() string {
return f.NameInternal
}
func (f diskFile) Open() (io.ReadCloser, error) {
return os.Open(filepath.Join(f.Base, f.NameInternal))
}
func diskFilesFromPath(base string) ([]importPackFile, error) {
list := make([]importPackFile, 0)
err := filepath.Walk(base, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
list = append(list, diskFile{base, path})
return nil
})
if err != nil {
return nil, err
}
return list, nil
}
type twitchInstalledPackMeta struct {
NameInternal string `json:"name"`
Path string `json:"installPath"`
// TODO: javaArgsOverride?
// TODO: allocatedMemory?
MCVersion string `json:"gameVersion"`
Modloader struct {
name string
mavenVersionString string
} `json:"baseModLoader"`
ModpackOverrides []string `json:"modpackOverrides"`
ModsInternal []struct {
ID int `json:"addonID"`
File modFileInfo `json:"installedFile"`
} `json:"installedAddons"`
// Used to determine if modpackOverrides should be used or not
IsUnlocked bool `json:"isUnlocked"`
}
func (m twitchInstalledPackMeta) Name() string {
return m.NameInternal
}
func (m twitchInstalledPackMeta) Versions() map[string]string {
vers := make(map[string]string)
vers["minecraft"] = m.MCVersion
if strings.HasPrefix(m.Modloader.name, "forge") {
if len(m.Modloader.mavenVersionString) > 0 {
vers["forge"] = strings.TrimPrefix(m.Modloader.mavenVersionString, "net.minecraftforge:forge:")
} else {
vers["forge"] = m.MCVersion + "-" + strings.TrimPrefix(m.Modloader.name, "forge-")
}
}
return vers
}
func (m twitchInstalledPackMeta) Mods() []struct {
ID int
File modFileInfo
} {
return []struct {
ID int
File modFileInfo
}(m.ModsInternal)
}
func (m twitchInstalledPackMeta) GetFiles() ([]importPackFile, error) {
if m.IsUnlocked {
return diskFilesFromPath(m.Path)
}
list := make([]importPackFile, len(m.ModpackOverrides))
for i, v := range m.ModpackOverrides {
list[i] = diskFile{
Base: m.Path,
NameInternal: v,
}
}
return list, nil
}