mirror of
https://github.com/packwiz/packwiz.git
synced 2025-10-14 15:04:32 +02:00
Switch to cobra/viper
This commit is contained in:
@@ -2,44 +2,23 @@ package curseforge
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
"github.com/comp500/packwiz/cmd"
|
||||
"github.com/comp500/packwiz/core"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"github.com/skratchdot/open-golang/open"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var curseforgeCmd = &cobra.Command{
|
||||
Use: "curseforge",
|
||||
Aliases: []string{"cf", "curse"},
|
||||
Short: "Manage curseforge-based mods",
|
||||
}
|
||||
|
||||
func init() {
|
||||
core.Commands = append(core.Commands, cli.Command{
|
||||
Name: "curseforge",
|
||||
Aliases: []string{"cf", "curse"},
|
||||
Usage: "Manage curseforge-based mods",
|
||||
Subcommands: []cli.Command{{
|
||||
Name: "install",
|
||||
Usage: "Install a mod from a curseforge URL, slug or ID",
|
||||
Aliases: []string{"add", "get"},
|
||||
Action: func(c *cli.Context) error {
|
||||
return cmdInstall(core.FlagsFromContext(c), c.Args().Get(0), c.Args().Tail())
|
||||
},
|
||||
}, {
|
||||
Name: "import",
|
||||
Usage: "Import an installed curseforge modpack",
|
||||
Action: func(c *cli.Context) error {
|
||||
return cmdImport(core.FlagsFromContext(c), c.Args().Get(0))
|
||||
},
|
||||
}, {
|
||||
Name: "open",
|
||||
// TODO: change semantics to "project" rather than "mod", as this supports texture packs and misc content as well?
|
||||
Usage: "Open the project page for a curseforge mod in your browser",
|
||||
Aliases: []string{"doc"},
|
||||
Action: func(c *cli.Context) error {
|
||||
return cmdDoc(core.FlagsFromContext(c), c.Args().Get(0))
|
||||
},
|
||||
}},
|
||||
})
|
||||
cmd.Add(curseforgeCmd)
|
||||
core.Updaters["curseforge"] = cfUpdater{}
|
||||
}
|
||||
|
||||
@@ -99,7 +78,7 @@ func getModIDFromString(mod string) (bool, int, error) {
|
||||
return false, 0, nil
|
||||
}
|
||||
|
||||
func createModFile(flags core.Flags, modInfo modInfo, fileInfo modFileInfo, index *core.Index) error {
|
||||
func createModFile(modInfo modInfo, fileInfo modFileInfo, index *core.Index) error {
|
||||
updateMap := make(map[string]map[string]interface{})
|
||||
var err error
|
||||
|
||||
@@ -126,7 +105,7 @@ func createModFile(flags core.Flags, modInfo modInfo, fileInfo modFileInfo, inde
|
||||
},
|
||||
Update: updateMap,
|
||||
}
|
||||
path := modMeta.SetMetaName(modInfo.Slug, flags)
|
||||
path := modMeta.SetMetaName(modInfo.Slug)
|
||||
|
||||
// If the file already exists, this will overwrite it!!!
|
||||
// TODO: Should this be improved?
|
||||
@@ -141,45 +120,6 @@ func createModFile(flags core.Flags, modInfo modInfo, fileInfo modFileInfo, inde
|
||||
return index.RefreshFileWithHash(path, format, hash, true)
|
||||
}
|
||||
|
||||
func cmdDoc(flags core.Flags, mod string) error {
|
||||
if len(mod) == 0 {
|
||||
return cli.NewExitError("You must specify a mod.", 1)
|
||||
}
|
||||
|
||||
fmt.Println("Loading modpack...")
|
||||
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)
|
||||
}
|
||||
resolvedMod, ok := index.FindMod(mod)
|
||||
if !ok {
|
||||
// TODO: should this auto-refresh???????
|
||||
return cli.NewExitError("You don't have this mod installed.", 1)
|
||||
}
|
||||
modData, err := core.LoadMod(resolvedMod)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
}
|
||||
updateData, ok := modData.GetParsedUpdateData("curseforge")
|
||||
if !ok {
|
||||
return cli.NewExitError("This mod doesn't seem to be a curseforge mod!", 1)
|
||||
}
|
||||
cfUpdateData := updateData.(cfUpdateData)
|
||||
fmt.Println("Opening browser...")
|
||||
url := "https://minecraft.curseforge.com/projects/" + strconv.Itoa(cfUpdateData.ProjectID)
|
||||
err = open.Start(url)
|
||||
if err != nil {
|
||||
fmt.Println("Opening page failed, direct link:")
|
||||
fmt.Println(url)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type cfUpdateData struct {
|
||||
ProjectID int `mapstructure:"project-id"`
|
||||
FileID int `mapstructure:"file-id"`
|
||||
|
@@ -6,7 +6,7 @@ import (
|
||||
"os"
|
||||
|
||||
"github.com/comp500/packwiz/core"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
type twitchPackMeta struct {
|
||||
@@ -42,78 +42,95 @@ type twitchPackMeta struct {
|
||||
} `json:"installedAddons"`
|
||||
}
|
||||
|
||||
func cmdImport(flags core.Flags, file string) error {
|
||||
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)
|
||||
}
|
||||
|
||||
var packMeta twitchPackMeta
|
||||
// TODO: is this relative to something?
|
||||
f, err := os.Open(file)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
}
|
||||
err = json.NewDecoder(f).Decode(&packMeta)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
}
|
||||
|
||||
modIDs := make([]int, len(packMeta.Mods))
|
||||
for i, v := range packMeta.Mods {
|
||||
modIDs[i] = v.ID
|
||||
}
|
||||
|
||||
fmt.Println("Querying Curse API...")
|
||||
|
||||
modInfos, err := getModInfoMultiple(modIDs)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
}
|
||||
|
||||
modInfosMap := make(map[int]modInfo)
|
||||
for _, v := range modInfos {
|
||||
modInfosMap[v.ID] = v
|
||||
}
|
||||
|
||||
// TODO: multithreading????
|
||||
for _, v := range packMeta.Mods {
|
||||
modInfoValue, ok := modInfosMap[v.ID]
|
||||
if !ok {
|
||||
if len(v.File.FriendlyName) > 0 {
|
||||
fmt.Printf("Failed to obtain mod information for \"%s\"\n", v.File.FriendlyName)
|
||||
} else {
|
||||
fmt.Printf("Failed to obtain mod information for \"%s\"\n", v.File.FileName)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
fmt.Printf("Imported mod \"%s\" successfully!\n", modInfoValue.Name)
|
||||
|
||||
err = createModFile(flags, modInfoValue, modFileInfo(v.File), &index)
|
||||
// importCmd represents the import command
|
||||
var importCmd = &cobra.Command{
|
||||
Use: "import",
|
||||
Short: "Import an installed curseforge modpack",
|
||||
Args: cobra.ExactArgs(1),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
pack, err := core.LoadPack()
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
index, err := pack.LoadIndex()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: import existing files (config etc.)
|
||||
var packMeta twitchPackMeta
|
||||
// TODO: is this relative to something?
|
||||
f, err := os.Open(args[0])
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
err = json.NewDecoder(f).Decode(&packMeta)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
err = index.Write()
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
}
|
||||
err = pack.UpdateIndexHash()
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
}
|
||||
err = pack.Write()
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
}
|
||||
modIDs := make([]int, len(packMeta.Mods))
|
||||
for i, v := range packMeta.Mods {
|
||||
modIDs[i] = v.ID
|
||||
}
|
||||
|
||||
return nil
|
||||
fmt.Println("Querying Curse API...")
|
||||
|
||||
modInfos, err := getModInfoMultiple(modIDs)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
modInfosMap := make(map[int]modInfo)
|
||||
for _, v := range modInfos {
|
||||
modInfosMap[v.ID] = v
|
||||
}
|
||||
|
||||
// TODO: multithreading????
|
||||
for _, v := range packMeta.Mods {
|
||||
modInfoValue, ok := modInfosMap[v.ID]
|
||||
if !ok {
|
||||
if len(v.File.FriendlyName) > 0 {
|
||||
fmt.Printf("Failed to obtain mod information for \"%s\"\n", v.File.FriendlyName)
|
||||
} else {
|
||||
fmt.Printf("Failed to obtain mod information for \"%s\"\n", v.File.FileName)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
fmt.Printf("Imported mod \"%s\" successfully!\n", modInfoValue.Name)
|
||||
|
||||
err = createModFile(modInfoValue, modFileInfo(v.File), &index)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: import existing files (config etc.)
|
||||
|
||||
err = index.Write()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
err = pack.UpdateIndexHash()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
err = pack.Write()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
curseforgeCmd.AddCommand(importCmd)
|
||||
}
|
||||
|
@@ -10,7 +10,7 @@ import (
|
||||
|
||||
"github.com/agnivade/levenshtein"
|
||||
"github.com/comp500/packwiz/core"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
"gopkg.in/dixonwille/wmenu.v4"
|
||||
)
|
||||
|
||||
@@ -21,255 +21,279 @@ type installableDep struct {
|
||||
fileInfo modFileInfo
|
||||
}
|
||||
|
||||
func cmdInstall(flags core.Flags, mod string, modArgsTail []string) error {
|
||||
if len(mod) == 0 {
|
||||
return cli.NewExitError("You must specify a mod.", 1)
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
||||
var done bool
|
||||
var modID, fileID int
|
||||
// If modArgsTail has anything, go straight to searching - URLs/Slugs should not have spaces!
|
||||
if len(modArgsTail) == 0 {
|
||||
done, modID, fileID, err = getFileIDsFromString(mod)
|
||||
// installCmd represents the install command
|
||||
var installCmd = &cobra.Command{
|
||||
Use: "install",
|
||||
Short: "Install a mod from a curseforge URL, slug or ID",
|
||||
Aliases: []string{"add", "get"},
|
||||
Args: cobra.ArbitraryArgs,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if len(args[0]) == 0 {
|
||||
fmt.Println("You must specify a mod.")
|
||||
os.Exit(1)
|
||||
}
|
||||
pack, err := core.LoadPack()
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if !done {
|
||||
done, modID, err = getModIDFromString(mod)
|
||||
// Ignore error, go to search instead (e.g. lowercase to search instead of as a slug)
|
||||
if err != nil {
|
||||
done = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
modInfoObtained := false
|
||||
var modInfoData modInfo
|
||||
|
||||
if !done {
|
||||
fmt.Println("Searching CurseForge...")
|
||||
modArgs := append([]string{mod}, modArgsTail...)
|
||||
searchTerm := strings.Join(modArgs, " ")
|
||||
results, err := getSearch(searchTerm, mcVersion)
|
||||
index, err := pack.LoadIndex()
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
mcVersion, err := pack.GetMCVersion()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if len(results) == 0 {
|
||||
return cli.NewExitError("No mods found!", 1)
|
||||
} else if len(results) == 1 {
|
||||
modInfoData = results[0]
|
||||
modID = modInfoData.ID
|
||||
modInfoObtained = true
|
||||
done = true
|
||||
} else {
|
||||
// Find the closest value to the search term
|
||||
sort.Slice(results, func(i, j int) bool {
|
||||
return levenshtein.ComputeDistance(searchTerm, results[i].Name) < levenshtein.ComputeDistance(searchTerm, results[j].Name)
|
||||
})
|
||||
|
||||
menu := wmenu.NewMenu("Choose a number:")
|
||||
|
||||
for i, v := range results {
|
||||
menu.Option(v.Name, v, i == 0, nil)
|
||||
}
|
||||
menu.Option("Cancel", nil, false, nil)
|
||||
|
||||
menu.Action(func(menuRes []wmenu.Opt) error {
|
||||
if len(menuRes) != 1 || menuRes[0].Value == nil {
|
||||
fmt.Println("Cancelled!")
|
||||
return nil
|
||||
}
|
||||
|
||||
// Why is variable shadowing a thing!!!!
|
||||
var ok bool
|
||||
modInfoData, ok = menuRes[0].Value.(modInfo)
|
||||
if !ok {
|
||||
return cli.NewExitError("Error converting interface from wmenu", 1)
|
||||
}
|
||||
modID = modInfoData.ID
|
||||
modInfoObtained = true
|
||||
done = true
|
||||
return nil
|
||||
})
|
||||
err = menu.Run()
|
||||
var done bool
|
||||
var modID, fileID int
|
||||
// If there are more than 1 argument, go straight to searching - URLs/Slugs should not have spaces!
|
||||
if len(args) == 1 {
|
||||
done, modID, fileID, err = getFileIDsFromString(args[0])
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if !done {
|
||||
return nil
|
||||
done, modID, err = getModIDFromString(args[0])
|
||||
// Ignore error, go to search instead (e.g. lowercase to search instead of as a slug)
|
||||
if err != nil {
|
||||
done = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !done {
|
||||
if err == nil {
|
||||
return cli.NewExitError("No mods found!", 1)
|
||||
modInfoObtained := false
|
||||
var modInfoData modInfo
|
||||
|
||||
if !done {
|
||||
fmt.Println("Searching CurseForge...")
|
||||
searchTerm := strings.Join(args, " ")
|
||||
results, err := getSearch(searchTerm, mcVersion)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if len(results) == 0 {
|
||||
fmt.Println("No mods found!")
|
||||
os.Exit(1)
|
||||
} else if len(results) == 1 {
|
||||
modInfoData = results[0]
|
||||
modID = modInfoData.ID
|
||||
modInfoObtained = true
|
||||
done = true
|
||||
} else {
|
||||
// Find the closest value to the search term
|
||||
sort.Slice(results, func(i, j int) bool {
|
||||
return levenshtein.ComputeDistance(searchTerm, results[i].Name) < levenshtein.ComputeDistance(searchTerm, results[j].Name)
|
||||
})
|
||||
|
||||
menu := wmenu.NewMenu("Choose a number:")
|
||||
|
||||
for i, v := range results {
|
||||
menu.Option(v.Name, v, i == 0, nil)
|
||||
}
|
||||
menu.Option("Cancel", nil, false, nil)
|
||||
|
||||
menu.Action(func(menuRes []wmenu.Opt) error {
|
||||
if len(menuRes) != 1 || menuRes[0].Value == nil {
|
||||
fmt.Println("Cancelled!")
|
||||
return nil
|
||||
}
|
||||
|
||||
// Why is variable shadowing a thing!!!!
|
||||
var ok bool
|
||||
modInfoData, ok = menuRes[0].Value.(modInfo)
|
||||
if !ok {
|
||||
fmt.Println("Error converting interface from wmenu")
|
||||
os.Exit(1)
|
||||
}
|
||||
modID = modInfoData.ID
|
||||
modInfoObtained = true
|
||||
done = true
|
||||
return nil
|
||||
})
|
||||
err = menu.Run()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if !done {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
return cli.NewExitError(err, 1)
|
||||
}
|
||||
|
||||
if !modInfoObtained {
|
||||
modInfoData, err = getModInfo(modID)
|
||||
if !done {
|
||||
if err == nil {
|
||||
fmt.Println("No mods found!")
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if !modInfoObtained {
|
||||
modInfoData, err = getModInfo(modID)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
var fileInfoData modFileInfo
|
||||
fileInfoData, err = getLatestFile(modInfoData, mcVersion, fileID)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
var fileInfoData modFileInfo
|
||||
fileInfoData, err = getLatestFile(modInfoData, mcVersion, fileID)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
}
|
||||
|
||||
if len(fileInfoData.Dependencies) > 0 {
|
||||
var depsInstallable []installableDep
|
||||
var depIDPendingQueue []int
|
||||
for _, dep := range fileInfoData.Dependencies {
|
||||
if dep.Type == dependencyTypeRequired {
|
||||
depIDPendingQueue = append(depIDPendingQueue, dep.ModID)
|
||||
if len(fileInfoData.Dependencies) > 0 {
|
||||
var depsInstallable []installableDep
|
||||
var depIDPendingQueue []int
|
||||
for _, dep := range fileInfoData.Dependencies {
|
||||
if dep.Type == dependencyTypeRequired {
|
||||
depIDPendingQueue = append(depIDPendingQueue, dep.ModID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(depIDPendingQueue) > 0 {
|
||||
fmt.Println("Finding dependencies...")
|
||||
if len(depIDPendingQueue) > 0 {
|
||||
fmt.Println("Finding dependencies...")
|
||||
|
||||
cycles := 0
|
||||
var installedIDList []int
|
||||
for len(depIDPendingQueue) > 0 && cycles < maxCycles {
|
||||
if installedIDList == nil {
|
||||
// Get modids of all mods
|
||||
for _, modPath := range index.GetAllMods() {
|
||||
mod, err := core.LoadMod(modPath)
|
||||
if err == nil {
|
||||
data, ok := mod.GetParsedUpdateData("curseforge")
|
||||
if ok {
|
||||
updateData, ok := data.(cfUpdateData)
|
||||
cycles := 0
|
||||
var installedIDList []int
|
||||
for len(depIDPendingQueue) > 0 && cycles < maxCycles {
|
||||
if installedIDList == nil {
|
||||
// Get modids of all mods
|
||||
for _, modPath := range index.GetAllMods() {
|
||||
mod, err := core.LoadMod(modPath)
|
||||
if err == nil {
|
||||
data, ok := mod.GetParsedUpdateData("curseforge")
|
||||
if ok {
|
||||
if updateData.ProjectID > 0 {
|
||||
installedIDList = append(installedIDList, updateData.ProjectID)
|
||||
updateData, ok := data.(cfUpdateData)
|
||||
if ok {
|
||||
if updateData.ProjectID > 0 {
|
||||
installedIDList = append(installedIDList, updateData.ProjectID)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove installed IDs from dep queue
|
||||
i := 0
|
||||
for _, id := range depIDPendingQueue {
|
||||
contains := false
|
||||
for _, id2 := range installedIDList {
|
||||
if id == id2 {
|
||||
contains = true
|
||||
break
|
||||
// Remove installed IDs from dep queue
|
||||
i := 0
|
||||
for _, id := range depIDPendingQueue {
|
||||
contains := false
|
||||
for _, id2 := range installedIDList {
|
||||
if id == id2 {
|
||||
contains = true
|
||||
break
|
||||
}
|
||||
}
|
||||
for _, data := range depsInstallable {
|
||||
if id == data.ID {
|
||||
contains = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !contains {
|
||||
depIDPendingQueue[i] = id
|
||||
i++
|
||||
}
|
||||
}
|
||||
for _, data := range depsInstallable {
|
||||
if id == data.ID {
|
||||
contains = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !contains {
|
||||
depIDPendingQueue[i] = id
|
||||
i++
|
||||
}
|
||||
}
|
||||
depIDPendingQueue = depIDPendingQueue[:i]
|
||||
depIDPendingQueue = depIDPendingQueue[:i]
|
||||
|
||||
depInfoData, err := getModInfoMultiple(depIDPendingQueue)
|
||||
if err != nil {
|
||||
fmt.Printf("Error retrieving dependency data: %s\n", err.Error())
|
||||
}
|
||||
depIDPendingQueue = depIDPendingQueue[:0]
|
||||
|
||||
for _, currData := range depInfoData {
|
||||
depFileInfo, err := getLatestFile(currData, mcVersion, 0)
|
||||
depInfoData, err := getModInfoMultiple(depIDPendingQueue)
|
||||
if err != nil {
|
||||
fmt.Printf("Error retrieving dependency data: %s\n", err.Error())
|
||||
}
|
||||
depIDPendingQueue = depIDPendingQueue[:0]
|
||||
|
||||
for _, dep := range depFileInfo.Dependencies {
|
||||
if dep.Type == dependencyTypeRequired {
|
||||
depIDPendingQueue = append(depIDPendingQueue, dep.ModID)
|
||||
}
|
||||
}
|
||||
|
||||
depsInstallable = append(depsInstallable, installableDep{
|
||||
currData, depFileInfo,
|
||||
})
|
||||
}
|
||||
|
||||
cycles++
|
||||
}
|
||||
if cycles >= maxCycles {
|
||||
return cli.NewExitError("Dependencies recurse too deeply! Try increasing maxCycles.", 1)
|
||||
}
|
||||
|
||||
if len(depsInstallable) > 0 {
|
||||
fmt.Println("Dependencies found:")
|
||||
for _, v := range depsInstallable {
|
||||
fmt.Println(v.Name)
|
||||
}
|
||||
|
||||
fmt.Print("Would you like to install them? [Y/n]: ")
|
||||
answer, err := bufio.NewReader(os.Stdin).ReadString('\n')
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
}
|
||||
|
||||
ansNormal := strings.ToLower(strings.TrimSpace(answer))
|
||||
if !(len(ansNormal) > 0 && ansNormal[0] == 'n') {
|
||||
for _, v := range depsInstallable {
|
||||
err = createModFile(flags, v.modInfo, v.fileInfo, &index)
|
||||
for _, currData := range depInfoData {
|
||||
depFileInfo, err := getLatestFile(currData, mcVersion, 0)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
fmt.Printf("Error retrieving dependency data: %s\n", err.Error())
|
||||
}
|
||||
fmt.Printf("Dependency \"%s\" successfully installed! (%s)\n", v.modInfo.Name, v.fileInfo.FileName)
|
||||
|
||||
for _, dep := range depFileInfo.Dependencies {
|
||||
if dep.Type == dependencyTypeRequired {
|
||||
depIDPendingQueue = append(depIDPendingQueue, dep.ModID)
|
||||
}
|
||||
}
|
||||
|
||||
depsInstallable = append(depsInstallable, installableDep{
|
||||
currData, depFileInfo,
|
||||
})
|
||||
}
|
||||
|
||||
cycles++
|
||||
}
|
||||
if cycles >= maxCycles {
|
||||
fmt.Println("Dependencies recurse too deeply! Try increasing maxCycles.")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if len(depsInstallable) > 0 {
|
||||
fmt.Println("Dependencies found:")
|
||||
for _, v := range depsInstallable {
|
||||
fmt.Println(v.Name)
|
||||
}
|
||||
|
||||
fmt.Print("Would you like to install them? [Y/n]: ")
|
||||
answer, err := bufio.NewReader(os.Stdin).ReadString('\n')
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
ansNormal := strings.ToLower(strings.TrimSpace(answer))
|
||||
if !(len(ansNormal) > 0 && ansNormal[0] == 'n') {
|
||||
for _, v := range depsInstallable {
|
||||
err = createModFile(v.modInfo, v.fileInfo, &index)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Printf("Dependency \"%s\" successfully installed! (%s)\n", v.modInfo.Name, v.fileInfo.FileName)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fmt.Println("All dependencies are already installed!")
|
||||
}
|
||||
} else {
|
||||
fmt.Println("All dependencies are already installed!")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err = createModFile(flags, modInfoData, fileInfoData, &index)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
}
|
||||
err = createModFile(modInfoData, fileInfoData, &index)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
err = index.Write()
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
}
|
||||
err = pack.UpdateIndexHash()
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
}
|
||||
err = pack.Write()
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
}
|
||||
err = index.Write()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
err = pack.UpdateIndexHash()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
err = pack.Write()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fmt.Printf("Mod \"%s\" successfully installed! (%s)\n", modInfoData.Name, fileInfoData.FileName)
|
||||
|
||||
return nil
|
||||
fmt.Printf("Mod \"%s\" successfully installed! (%s)\n", modInfoData.Name, fileInfoData.FileName)
|
||||
},
|
||||
}
|
||||
|
||||
func getLatestFile(modInfoData modInfo, mcVersion string, fileID int) (modFileInfo, error) {
|
||||
@@ -300,3 +324,7 @@ func getLatestFile(modInfoData modInfo, mcVersion string, fileID int) (modFileIn
|
||||
}
|
||||
return fileInfoData, nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
curseforgeCmd.AddCommand(installCmd)
|
||||
}
|
||||
|
66
curseforge/open.go
Normal file
66
curseforge/open.go
Normal file
@@ -0,0 +1,66 @@
|
||||
package curseforge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/comp500/packwiz/core"
|
||||
"github.com/skratchdot/open-golang/open"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// openCmd represents the open command
|
||||
var openCmd = &cobra.Command{
|
||||
Use: "open",
|
||||
// TODO: change semantics to "project" rather than "mod", as this supports texture packs and misc content as well?
|
||||
Short: "Open the project page for a curseforge mod in your browser",
|
||||
Aliases: []string{"doc"},
|
||||
Args: cobra.ExactArgs(1),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if len(args[0]) == 0 {
|
||||
fmt.Println("You must specify a mod.")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fmt.Println("Loading modpack...")
|
||||
pack, err := core.LoadPack()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
index, err := pack.LoadIndex()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
resolvedMod, ok := index.FindMod(args[0])
|
||||
if !ok {
|
||||
// TODO: should this auto-refresh???????
|
||||
fmt.Println("You don't have this mod installed.")
|
||||
os.Exit(1)
|
||||
}
|
||||
modData, err := core.LoadMod(resolvedMod)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
updateData, ok := modData.GetParsedUpdateData("curseforge")
|
||||
if !ok {
|
||||
fmt.Println("This mod doesn't seem to be a curseforge mod!")
|
||||
os.Exit(1)
|
||||
}
|
||||
cfUpdateData := updateData.(cfUpdateData)
|
||||
fmt.Println("Opening browser...")
|
||||
url := "https://minecraft.curseforge.com/projects/" + strconv.Itoa(cfUpdateData.ProjectID)
|
||||
err = open.Start(url)
|
||||
if err != nil {
|
||||
fmt.Println("Opening page failed, direct link:")
|
||||
fmt.Println(url)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
curseforgeCmd.AddCommand(openCmd)
|
||||
}
|
Reference in New Issue
Block a user