mirror of
https://github.com/packwiz/packwiz.git
synced 2025-04-19 21:16:30 +02:00
Add cf detect command (experimental but should mostly work)
This commit is contained in:
parent
48971d7b5a
commit
4d4f0d143e
148
curseforge/detect.go
Normal file
148
curseforge/detect.go
Normal file
@ -0,0 +1,148 @@
|
||||
package curseforge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/aviddiviner/go-murmur"
|
||||
"github.com/comp500/packwiz/core"
|
||||
"github.com/spf13/cobra"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// TODO: make all of this less bad and hardcoded
|
||||
|
||||
// detectCmd represents the detect command
|
||||
var detectCmd = &cobra.Command{
|
||||
Use: "detect",
|
||||
Short: "Detect .jar files in the mods folder (experimental)",
|
||||
Args: cobra.NoArgs,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
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)
|
||||
}
|
||||
|
||||
// Walk files in the mods folder
|
||||
var hashes []int
|
||||
modPaths := make(map[int]string)
|
||||
err = filepath.Walk("mods", func(path string, info os.FileInfo, err error) error {
|
||||
if info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
if !strings.HasSuffix(path, ".jar") {
|
||||
// TODO: make this less bad
|
||||
return nil
|
||||
}
|
||||
fmt.Println("Hashing " + path)
|
||||
bytes, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
hash := getByteArrayHash(bytes)
|
||||
hashes = append(hashes, int(hash))
|
||||
modPaths[int(hash)] = path
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Printf("Found %d files, submitting...\n", len(hashes))
|
||||
|
||||
res, err := getFingerprintInfo(hashes)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("Successfully matched %d files\n", len(res.ExactFingerprints))
|
||||
if len(res.PartialMatches) > 0 {
|
||||
fmt.Println("The following fingerprints were partial and I don't know what to do!!!")
|
||||
for _, v := range res.PartialMatches {
|
||||
fmt.Printf("%s (%d)", modPaths[v], v)
|
||||
}
|
||||
}
|
||||
if len(res.UnmatchedFingerprints) > 0 {
|
||||
fmt.Printf("Failed to match the following %d files:\n", len(res.UnmatchedFingerprints))
|
||||
for _, v := range res.UnmatchedFingerprints {
|
||||
fmt.Printf("%s (%d)\n", modPaths[v], v)
|
||||
}
|
||||
}
|
||||
fmt.Println("Installing...")
|
||||
for _, v := range res.ExactMatches {
|
||||
modInfoData, err := getModInfo(v.ID)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
err = createModFile(modInfoData, v.File, &index)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
path, ok := modPaths[v.File.Fingerprint]
|
||||
if ok {
|
||||
err = os.Remove(path)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt.Println("Installation done")
|
||||
|
||||
err = index.Refresh()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
err = index.Write()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
err = pack.UpdateIndexHash()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
err = pack.Write()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
curseforgeCmd.AddCommand(detectCmd)
|
||||
}
|
||||
|
||||
func getByteArrayHash(bytes []byte) uint64 {
|
||||
return uint64(murmur.MurmurHash2(computeNormalizedArray(bytes), 1))
|
||||
}
|
||||
|
||||
func computeNormalizedArray(bytes []byte) []byte {
|
||||
var newArray []byte
|
||||
for _, b := range bytes {
|
||||
if !isWhitespaceCharacter(b) {
|
||||
newArray = append(newArray, b)
|
||||
}
|
||||
}
|
||||
return newArray
|
||||
}
|
||||
|
||||
func isWhitespaceCharacter(b byte) bool {
|
||||
return b == 9 || b == 10 || b == 13 || b == 32
|
||||
}
|
@ -291,3 +291,49 @@ func getSearch(searchText string, gameVersion string) ([]modInfo, error) {
|
||||
|
||||
return infoRes, nil
|
||||
}
|
||||
|
||||
type addonFingerprintResponse struct {
|
||||
IsCacheBuilt bool `json:"isCacheBuilt"`
|
||||
ExactMatches []struct {
|
||||
ID int `json:"id"`
|
||||
File modFileInfo `json:"file"`
|
||||
LatestFiles []modFileInfo `json:"latestFiles"`
|
||||
} `json:"exactMatches"`
|
||||
ExactFingerprints []int `json:"exactFingerprints"`
|
||||
PartialMatches []int `json:"partialMatches"`
|
||||
PartialMatchFingerprints struct{} `json:"partialMatchFingerprints"`
|
||||
InstalledFingerprints []int `json:"installedFingerprints"`
|
||||
UnmatchedFingerprints []int `json:"unmatchedFingerprints"`
|
||||
}
|
||||
|
||||
func getFingerprintInfo(hashes []int) (addonFingerprintResponse, error) {
|
||||
var infoRes addonFingerprintResponse
|
||||
client := &http.Client{}
|
||||
|
||||
hashesData, err := json.Marshal(hashes)
|
||||
if err != nil {
|
||||
return addonFingerprintResponse{}, err
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("POST", "https://addons-ecs.forgesvc.net/api/v2/fingerprint", bytes.NewBuffer(hashesData))
|
||||
if err != nil {
|
||||
return addonFingerprintResponse{}, 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 addonFingerprintResponse{}, err
|
||||
}
|
||||
|
||||
err = json.NewDecoder(resp.Body).Decode(&infoRes)
|
||||
if err != nil && err != io.EOF {
|
||||
return addonFingerprintResponse{}, err
|
||||
}
|
||||
|
||||
return infoRes, nil
|
||||
}
|
||||
|
1
go.mod
1
go.mod
@ -2,6 +2,7 @@ module github.com/comp500/packwiz
|
||||
|
||||
require (
|
||||
github.com/BurntSushi/toml v0.3.1
|
||||
github.com/aviddiviner/go-murmur v0.0.0-20150519214947-b9740d71e571
|
||||
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 // indirect
|
||||
github.com/daviddengcn/go-colortext v0.0.0-20180409174941-186a3d44e920 // indirect
|
||||
github.com/denormal/go-gitignore v0.0.0-20180930084346-ae8ad1d07817
|
||||
|
2
go.sum
2
go.sum
@ -7,6 +7,8 @@ github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmx
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/aviddiviner/go-murmur v0.0.0-20150519214947-b9740d71e571 h1:seCdAEDyB0Hti/v1VajB7pAOIk9zmz/0/KE0D0oFqnc=
|
||||
github.com/aviddiviner/go-murmur v0.0.0-20150519214947-b9740d71e571/go.mod h1:VzSzsYCY3W9xWYWD8T2GLDidWTe5rTZv+UdDMGhLfjg=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
|
Loading…
x
Reference in New Issue
Block a user