From ebc2115b4188cb7444ca9a7941073b8060d74e48 Mon Sep 17 00:00:00 2001 From: comp500 Date: Fri, 14 Jun 2019 20:13:00 +0100 Subject: [PATCH] Select file id, improve searching --- curseforge/curseforge.go | 70 ++++++++++++++++++++++++++++------------ curseforge/request.go | 14 +++++--- 2 files changed, 59 insertions(+), 25 deletions(-) diff --git a/curseforge/curseforge.go b/curseforge/curseforge.go index e9b7486..4c7f836 100644 --- a/curseforge/curseforge.go +++ b/curseforge/curseforge.go @@ -152,25 +152,34 @@ func cmdInstall(flags core.Flags, mod string, modArgsTail []string) error { return cli.NewExitError(err, 1) } - done, modID, fileID, err := getFileIDsFromString(mod) - 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) + if err != nil { + return cli.NewExitError(err, 1) + } - if !done { - done, modID, err = getModIDFromString(mod) - // Handle error later (e.g. lowercase to search instead of as a slug) + 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, " ") // TODO: Curse search // TODO: how to do interactive choices? automatically assume version? ask mod from list? choose first? - results, err := getSearch(searchTerm) + results, err := getSearch(searchTerm, mcVersion) if err != nil { return cli.NewExitError(err, 1) } @@ -200,7 +209,10 @@ func cmdInstall(flags core.Flags, mod string, modArgsTail []string) error { fmt.Println("Cancelled!") return nil } - modInfoData, ok := menuRes[0].Value.(modInfo) + + // Why is variable shadowing a thing!!!! + var ok bool + modInfoData, ok = menuRes[0].Value.(modInfo) if !ok { return errors.New("Error converting interface from wmenu") } @@ -227,11 +239,6 @@ func cmdInstall(flags core.Flags, mod string, modArgsTail []string) error { return cli.NewExitError(err, 1) } - fmt.Printf("ids: %d %d %v\n", modID, fileID, done) - - // TODO: get FileID if it isn't there - - fmt.Println(mcVersion) if !modInfoObtained { modInfoData, err = getModInfo(modID) if err != nil { @@ -239,17 +246,38 @@ func cmdInstall(flags core.Flags, mod string, modArgsTail []string) error { } } + fileInfoObtained := false + var fileInfoData modFileInfo if fileID == 0 { - fmt.Println("WIP: get an actual file ID!!!") - return nil + // TODO: how do we decide which version to use? + for _, v := range modInfoData.GameVersionLatestFiles { + // Choose "newest" version by largest ID + if v.GameVersion == mcVersion && v.ID > fileID { + fileID = v.ID + } + } + + if fileID == 0 { + return cli.NewExitError(errors.New("no files available for current Minecraft version"), 1) + } + + // The API also provides some files inline, because that's efficient! + for _, v := range modInfoData.LatestFiles { + if v.ID == fileID { + fileInfoObtained = true + fileInfoData = v + } + } } - fileInfo, err := getFileInfo(modID, fileID) - if err != nil { - return cli.NewExitError(err, 1) + if !fileInfoObtained { + fileInfoData, err = getFileInfo(modID, fileID) + if err != nil { + return cli.NewExitError(err, 1) + } } - err = createModFile(flags, modInfoData, fileInfo, &index) + err = createModFile(flags, modInfoData, fileInfoData, &index) if err != nil { return cli.NewExitError(err, 1) } @@ -267,7 +295,7 @@ func cmdInstall(flags core.Flags, mod string, modArgsTail []string) error { return cli.NewExitError(err, 1) } - fmt.Printf("Mod \"%s\" successfully installed!\n", modInfoData.Name) + fmt.Printf("Mod \"%s\" successfully installed! (%s)\n", modInfoData.Name, fileInfoData.FileName) return nil } diff --git a/curseforge/request.go b/curseforge/request.go index 8d9e659..e7893b3 100644 --- a/curseforge/request.go +++ b/curseforge/request.go @@ -204,8 +204,8 @@ func (f *cfDateFormat) UnmarshalJSON(input []byte) error { // modFileInfo is a subset of the deserialised JSON response from the Curse API for mod files type modFileInfo struct { ID int `json:"id"` - FileName string `json:"fileNameOnDisk"` - FriendlyName string `json:"fileName"` + FileName string `json:"fileName"` + FriendlyName string `json:"displayName"` Date cfDateFormat `json:"fileDate"` Length int `json:"fileLength"` FileType int `json:"releaseType"` @@ -253,13 +253,19 @@ func getFileInfo(modID int, fileID int) (modFileInfo, error) { } // TODO: pass gameVersion? -func getSearch(searchText string) ([]modInfo, error) { +func getSearch(searchText string, gameVersion string) ([]modInfo, error) { var infoRes []modInfo client := &http.Client{} textEscaped := url.QueryEscape(searchText) + var reqURL string + if len(gameVersion) > 0 { + reqURL = "https://addons-ecs.forgesvc.net/api/v2/addon/search?gameId=432&pageSize=10&categoryId=0§ionId=6&searchFilter=" + textEscaped + "&gameVersion=" + gameVersion + } else { + reqURL = "https://addons-ecs.forgesvc.net/api/v2/addon/search?gameId=432&pageSize=10&categoryId=0§ionId=6&searchFilter=" + textEscaped + } - req, err := http.NewRequest("GET", "https://addons-ecs.forgesvc.net/api/v2/addon/search?gameId=432&pageSize=10&categoryId=0§ionId=6&searchFilter="+textEscaped, nil) + req, err := http.NewRequest("GET", reqURL, nil) if err != nil { return []modInfo{}, err }