func (sh *savehelper) UnpackAll() { z := sh.getzip() defer util.MustClose(z) for i := 0; i < len(z.File); i++ { zi := z.File[i] fln := "saves/" + zi.Name if zi.FileInfo().IsDir() { util.Must(util.MkDirIfNotExist(fln)) } else { zf, zfe := zi.Open() util.Must(zfe) fmt.Printf("Unpacking %#v...\n", zi.Name) pr := util.NewReadProgress(zf, zi.UncompressedSize64) f, fe := os.Create(fln) util.Must(fe) defer util.MustClose(f) _, ce := io.Copy(f, pr) util.Must(ce) util.MustClose(zf) util.MustClose(pr) } } }
func open(fname string) { db.o = true f, fe := os.OpenFile(fname, os.O_RDONLY, 0) defer f.Close() if os.IsNotExist(fe) { return } util.Must(fe) be := binary.BigEndian fpb := make([]byte, 20) var rp *MCPMPackage for { _, rer := f.Read(fpb) if rer != nil { break } rp = new(MCPMPackage) rp.id = be.Uint64(fpb) ln := be.Uint32(fpb[8:]) lt := be.Uint32(fpb[12:]) lp := be.Uint32(fpb[16:]) xb := make([]byte, ln+lt+lp) _, rer = f.Read(xb) util.Must(rer) rp.name = string(xb[:ln]) rp.title = string(xb[ln : ln+lt]) rp.ptype = string(xb[ln+lt:]) db.r[rp.name] = rp db.r[strconv.FormatUint(rp.id, 10)] = rp } }
func get(mo *ModeOptions) { pn := mo.Args[0] defer mcpmdb.Close() if pkg := mcpmdb.GetPackage(pn); pkg != nil { if fl := pkg.GetFileList(); fl != nil { pf := fl.GetLatest() if !mo.Confirm { fmt.Printf("Do you want to download %#v? [y|N] ", pf.Name) r := []byte{} _, se := fmt.Scanln(&r) util.Must(se) if len(r) == 0 { fmt.Println("Download cancelled by default") return } if r[0] != 0x79 && r[0] != 0x59 { fmt.Println("Cancelled file download.") return } } pkg.DownloadFileWithID(pf.ID, nil) } else { fmt.Println("Package exists but has no files to download.") } } else { if mo.Verbose { fmt.Printf("Package %#v not found.\n", pn) } fmt.Println("What is that package?") } }
// UnpackModpack downloads mods and unpacks file contents. func UnpackModpack(fname string) { z, ze := zip.OpenReader(fname) util.Must(ze) defer util.MustClose(z) info := new(modpackmanifest) var zf *zip.File ov := "overrides/" buf := make([]byte, 32*1024) for _, zf = range z.File { if zf.Name == "manifest.json" { ozf, oze := zf.Open() util.Must(oze) util.Must(json.NewDecoder(ozf).Decode(info)) util.MustClose(ozf) break } } if info != nil { ov = info.Overrides + "/" for i, xf := range info.Files { pid := strconv.FormatInt(int64(xf.PID), 10) pkg := GetPackage(pid) if pkg == nil { fmt.Printf("Package with ID %s is missing!\n", pid) continue } fmt.Printf("%d / %d ", i, len(info.Files)) pkg.DownloadFileWithID(strconv.FormatInt(int64(xf.FID), 10), buf) } } lov := len(ov) for _, zf = range z.File { if len(zf.Name) < lov { continue } n := zf.Name[:lov] if n == ov { n = zf.Name[lov:] if n == "" { continue } if zf.FileInfo().IsDir() { util.Must(util.MkDirIfNotExist(n)) } else { xf, xe := zf.Open() util.Must(xe) fmt.Printf("Unpacking %#v...\n", n) pr := util.NewReadProgress(xf, zf.UncompressedSize64) f, fe := os.Create(n) util.Must(fe) _, ce := io.CopyBuffer(f, pr, buf) util.Must(ce) util.MustClose(f) util.MustClose(xf) pr.Close() } } } }
func info(mo *ModeOptions) { pn := mo.Args[0] db := database.GetDatabase() if pkg := db.Packages().GetByName(pn); pkg != nil { pr, hte := util.DownloadPackageInfo(pkg.Type, pkg.ID, pkg.Name) util.Must(hte) defer pr.Close() var pi packageInfo jd := json.NewDecoder(pr) util.Must(jd.Decode(&pi)) fmt.Printf("Name: %s\nAuthors: %s\nVersions:\n", pi.Title, pi.Authors) for k, v := range pi.Versions { fmt.Printf(" %s:\n", k) for i := 0; i < len(v); i++ { fmt.Printf(" %s; %s (%d) (%s)\n", v[i].Name, v[i].Type, v[i].Id, v[i].CreatedAt) } } } }
func (mh *mcmodinfohelper) ReadContents() map[string]interface{} { z, ze := zip.OpenReader(mh.filename) util.Must(ze) defer util.MustClose(z) var zf *zip.File for i := 0; i < len(z.File); i++ { if z.File[i].Name == "mcmod.info" { zf = z.File[i] break } } if zf == nil { return nil } ozf, oze := zf.Open() util.Must(oze) defer util.MustClose(ozf) jd := json.NewDecoder(ozf) var jsf map[string]interface{} util.Must(jd.Decode(jsf)) return jsf }
// GetFileList creates list of files available for download. func (pkg *MCPMPackage) GetFileList() *MCPMFileList { cht, chte := get(util.DirPathJoin("http://curse.com/project", strconv.FormatUint(pkg.id, 10))) defer util.MustClose(cht.Body) defer util.Must(chte) cdoc, cdoce := goquery.NewDocumentFromResponse(cht) util.Must(cdoce) list := cdoc.Find("table.project-file-listing tbody tr") if list.Length() == 0 { return nil } fl := &MCPMFileList{make([]*MCPMFile, list.Length())} for i := range list.Nodes { n := list.Eq(i) td := n.Find("td") na := td.Eq(0).Find("a") nt := td.Eq(1) nv := td.Eq(2) tid := na.AttrOr("href", "") fl.a[i] = &MCPMFile{tid[strings.LastIndexByte(tid, '/')+1:], na.Text(), nt.Text(), nv.Text()} } return fl }
// Close checks if a database needs to be updated before application finishes. func Close() { f, fe := os.OpenFile(db.fn, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0666) defer util.MustClose(f) util.Must(fe) for _, v := range db.a { ln := len(v.name) lt := len(v.title) lp := len(v.ptype) tot := 20 + ln + lt + lp b := make([]byte, tot) be := binary.BigEndian bp := 20 be.PutUint64(b, v.id) be.PutUint32(b[8:], uint32(ln)) be.PutUint32(b[12:], uint32(lt)) be.PutUint32(b[16:], uint32(lp)) bp += copy(b[bp:], v.name) bp += copy(b[bp:], v.title) copy(b[bp:], v.ptype) _, wer := f.Write(b) util.Must(wer) } }
// DownloadFileWithID downloads file with a specified ID and unpacks its contents if necessary. func (pkg *MCPMPackage) DownloadFileWithID(fid string, buf []byte) { if buf == nil { buf = make([]byte, 32*1024) } po := util.GetPackageOptionsB(pkg.ptype) util.Must(util.MkDirIfNotExist(po.Dir)) us := fmt.Sprintf("http://minecraft.curseforge.com/projects/%s/files/%s/download", pkg.name, fid) ht, hte := get(us) defer util.MustClose(ht.Body) util.Must(hte) fname := ht.Request.URL.Path fname = fname[strings.LastIndex(fname, "/")+1:] sav := util.DirPathJoin(po.Dir, fname) sf, sfe := os.OpenFile(sav, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666) util.Must(sfe) defer util.MustClose(sf) fmt.Printf("Downloading \"%s\": %s\n", pkg.name, fname) pr := util.NewReadProgress(ht.Body, uint64(ht.ContentLength)) _, ce := io.CopyBuffer(sf, pr, buf) util.Must(ce) util.MustClose(pr) fmt.Printf("Successfully saved to \"%s\"\n", sav) if po.ShouldUnpack { switch pkg.ptype { case "modpacks": UnpackModpack(sav) fmt.Printf("Successfully installed modpack %#v\n", pkg.title) break case "worlds": svh := helper.NewSaveHelper(sav) svh.UnpackAll() fmt.Printf("Successfully unpacked world save %#v\n", pkg.title) break } } }
func get(ur string) (*http.Response, error) { u, ue := url.Parse(ur) util.Must(ue) req := &http.Request{ Method: "GET", URL: u, Proto: "HTTP/1.1", ProtoMajor: 1, ProtoMinor: 1, Header: http.Header{}, Body: nil, Host: u.Host, } req.Header.Set("User-Agent", uagent) return client.Do(req) }
func init() { var er error client.Jar, er = cookiejar.New(nil) util.Must(er) }
func (sh *savehelper) getzip() *zip.ReadCloser { z, ze := zip.OpenReader(sh.filename) util.Must(ze) return z }