diff --git a/curseforge/curseforge.go b/curseforge/curseforge.go index dd582b7..c58ca38 100644 --- a/curseforge/curseforge.go +++ b/curseforge/curseforge.go @@ -110,6 +110,7 @@ func createModFile(flags core.Flags, modInfo modInfo, fileInfo modFileInfo) erro Download: core.ModDownload{ URL: fileInfo.DownloadURL, // TODO: murmur2 hashing may be unstable in curse api, calculate the hash manually? + // TODO: check if the hash is invalid (e.g. 0) HashFormat: "murmur2", Hash: strconv.Itoa(fileInfo.Fingerprint), }, @@ -117,9 +118,11 @@ func createModFile(flags core.Flags, modInfo modInfo, fileInfo modFileInfo) erro } modMeta.SetMetaName(modInfo.Slug, flags) - fmt.Printf("%#v\n", modMeta) + // If the file already exists, this will overwrite it!!! + // TODO: Should this be improved? + // Current strategy is to go ahead and do stuff without asking, with the assumption that you are using + // VCS anyway. - // TODO: what to do if it already exists? // TODO: add to index return modMeta.Write() } @@ -212,6 +215,7 @@ type cfUpdater struct { } func (u cfUpdater) DoUpdate(mod core.Mod) (bool, error) { + // TODO: implement updating return false, nil } @@ -220,4 +224,3 @@ func (u cfUpdater) ToMap() (map[string]interface{}, error) { err := mapstructure.Decode(u, &newMap) return newMap, err } - diff --git a/curseforge/import.go b/curseforge/import.go index 5a81aaa..fcba61e 100644 --- a/curseforge/import.go +++ b/curseforge/import.go @@ -1,4 +1,5 @@ package curseforge + import ( "encoding/json" "fmt" @@ -42,38 +43,55 @@ type twitchPackMeta struct { } func cmdImport(flags core.Flags, file string) error { - // TODO: implement var packMeta twitchPackMeta // TODO: is this relative to something? f, err := os.Open(file) if err != nil { - return err + return cli.NewExitError(err, 1) } err = json.NewDecoder(f).Decode(&packMeta) if err != nil { - return err + return cli.NewExitError(err, 1) } - // TODO: magic involving existing files + 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 { - // TODO: progress bar? - - // TODO: batch requests? - modInfo, err := getModInfo(v.ID) - if err != nil { - // TODO: Fail more quietly? - return cli.NewExitError(err, 1) + 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.Println(v) - fmt.Println(modFileInfo(v.File)) - err = createModFile(flags, modInfo, modFileInfo(v.File)) + fmt.Printf("Imported \"%s\" successfully!\n", modInfoValue.Name) + + err = createModFile(flags, modInfoValue, modFileInfo(v.File)) if err != nil { return cli.NewExitError(err, 1) } } + // TODO: import existing files (config etc.) + return nil } - diff --git a/curseforge/request.go b/curseforge/request.go index 7a13446..8cea222 100644 --- a/curseforge/request.go +++ b/curseforge/request.go @@ -147,6 +147,38 @@ func getModInfo(modID int) (modInfo, error) { return infoRes, nil } +func getModInfoMultiple(modIDs []int) ([]modInfo, error) { + var infoRes []modInfo + client := &http.Client{} + + modIDsData, err := json.Marshal(modIDs) + if err != nil { + return []modInfo{}, err + } + + req, err := http.NewRequest("POST", "https://addons-ecs.forgesvc.net/api/v2/addon/", bytes.NewBuffer(modIDsData)) + if err != nil { + return []modInfo{}, err + } + + // TODO: make this configurable application-wide + req.Header.Set("User-Agent", "comp500/packwiz client") + req.Header.Set("Accept", "application/json") + req.Header.Set("Content-Type", "application/json") + + resp, err := client.Do(req) + if err != nil { + return []modInfo{}, err + } + + err = json.NewDecoder(resp.Body).Decode(&infoRes) + if err != nil && err != io.EOF { + return []modInfo{}, err + } + + return infoRes, nil +} + const cfDateFormatString = "2006-01-02T15:04:05.999" type cfDateFormat struct { diff --git a/go.mod b/go.mod index 5e1084e..d96abfa 100644 --- a/go.mod +++ b/go.mod @@ -2,6 +2,7 @@ module github.com/comp500/packwiz require ( github.com/BurntSushi/toml v0.3.1 + github.com/manifoldco/promptui v0.3.2 // indirect github.com/mitchellh/mapstructure v1.1.2 github.com/urfave/cli v1.20.0 github.com/vbauerster/mpb/v4 v4.7.0 diff --git a/go.sum b/go.sum index 3cd392f..4bc8942 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,34 @@ github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/VividCortex/ewma v1.1.1 h1:MnEK4VOv6n0RSY4vtRe3h11qjxL3+t0B8yOL8iMXdcM= github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA= +github.com/alecthomas/gometalinter v2.0.11+incompatible/go.mod h1:qfIpQGGz3d+NmgyPBqv+LSh50emm1pt72EtcX2vKYQk= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/golang/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= +github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf/go.mod h1:RpwtwJQFrIEPstU94h88MWPXP2ektJZ8cZ0YntAmXiE= +github.com/gordonklaus/ineffassign v0.0.0-20180909121442-1003c8bd00dc/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU= +github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a h1:FaWFmfWdAUKbSCtOU2QjDaorUexogfaMgbipgYATUMU= +github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a h1:weJVJJRzAJBFRlAiJQROKQs8oC9vOxvm4rZmBBk0ONw= +github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= +github.com/manifoldco/promptui v0.3.2 h1:rir7oByTERac6jhpHUPErHuopoRDvO3jxS+FdadEns8= +github.com/manifoldco/promptui v0.3.2/go.mod h1:8JU+igZ+eeiiRku4T5BjtKh2ms8sziGpSYl1gN8Bazw= +github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/tsenart/deadcode v0.0.0-20160724212837-210d2dc333e9/go.mod h1:q+QjxYvZ+fpjMXqs+XEriussHjSYqeXVnAdSV1tkMYk= github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/vbauerster/mpb/v4 v4.7.0 h1:Et+zVewxG6qmfBf4Ez+nDhLbCSh6WhZrUPHg9a6e+hw= @@ -11,9 +37,13 @@ github.com/vbauerster/mpb/v4 v4.7.0/go.mod h1:ugxYn2kSUrY10WK5CWDUZvQxjdwKFN9K3J golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734 h1:p/H982KKEjUnLJkM3tt/LemDnOc1GiZL5FCVlORJ5zo= golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190429190828-d89cdac9e872 h1:cGjJzUd8RgBw428LXP65YXni0aiGNA4Bl+ls8SmLOm8= golang.org/x/sys v0.0.0-20190429190828-d89cdac9e872/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/tools v0.0.0-20181122213734-04b5d21e00f1/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=