package main import ( "archive/zip" "encoding/json" "io/ioutil" "log" "os" ) // Fabric/Quilt Mod Json type FabricModJson struct { ID string `json:"id"` Version string `json:"version"` Name string `json:"name"` } type QuiltModJson struct { QuiltLoader struct { ID string `json:"id"` Version string `json:"version"` Metadata struct { Name string `json:"name"` } `json:"metadata"` } `json:"quilt_loader"` } var ( fabricMods []FabricModJson quiltMods []QuiltModJson ) // deduplicate mod jars based off the name of the jar // if the jar name is the same, then we will only keep the one with the highest version // or the latest modified date func main() { // get list of jars in ./mods files, err := ioutil.ReadDir("./mods") if err != nil { log.Fatalln("[READ DIR]", err) } // for modjars, for _, file := range files { // read the mod.json file and return the name, version, and filename name, version, loader := readMod("./mods/" + file.Name()) if loader != "" { // remove invalid path characters from the name using regex // name = regexp.MustCompile(`[^\w\-. ]`).ReplaceAllString(name, "") err := os.Rename("./mods/"+file.Name(), "./mods/"+name+"-"+version+".jar") if err != nil { log.Fatalln("[RENAME MOD]", err) } else { log.Println("[RENAME MOD]", file.Name(), ">>", name+"-"+version+".jar") } } else { log.Println("Unsupported Loader", file.Name()) } } for _, mod := range fabricMods { // check if there is a duplicate in the list for _, mod2 := range fabricMods { if mod.Name == mod2.Name && mod.Version != mod2.Version { // if there is a duplicate, delete the one with the lower semver version if mod.Version < mod2.Version { err := os.Remove("./mods/" + mod.Name + "-" + mod.Version + ".jar") if err != nil { log.Fatalln("[REMOVE MOD]", err) } } } } } } // read the mod.json file and return the name, version, and filename func readMod(filename string) (string, string, string) { var fabricJson FabricModJson var quiltJson QuiltModJson var loader string zipReader, err := zip.OpenReader(filename) if err != nil { log.Fatalln("[READ ZIP]", err) } defer zipReader.Close() for _, file := range zipReader.File { contents, _ := file.Open() if file.Name == "fabric.mod.json" { loader = "fabric" // add to fabric list fabricJsonErr := json.NewDecoder(contents).Decode(&fabricJson) if fabricJsonErr != nil { log.Println("[DECODE ERROR]", filename) log.Fatalln("[DECODE FABRIC MOD]", fabricJsonErr) } } if file.Name == "quilt.mod.json" { loader = "quilt" quiltJsonErr := json.NewDecoder(contents).Decode(&quiltJson) if quiltJsonErr != nil { log.Println(filename) log.Println("[DECODE ERROR]", filename) log.Fatalln("[DECODE QUILT MOD]", quiltJsonErr) } } } if loader == "fabric" { fabricMods = append(fabricMods, fabricJson) return fabricJson.Name, fabricJson.Version, loader } if loader == "quilt" { quiltMods = append(quiltMods, quiltJson) return quiltJson.QuiltLoader.Metadata.Name, quiltJson.QuiltLoader.Version, loader } return "", "", "" }