package gamebanana import ( "errors" "fmt" "io" "io/fs" "net/http" "os" "path" "path/filepath" "strings" "github.com/charmbracelet/log" "github.com/gen2brain/go-unarr" ) var dlurl string func DownloadGameBananaMod(id, outdir string) (error) { modData, err := GetGameBananaMod(id) if err != nil { return err } // create temporary file to download mod to tmpFolderDownload, err := os.MkdirTemp("", "diva-mod-download-*") log.Info("created temp folder for downloading", "name", tmpFolderDownload) if err != nil { return err } // really really jank, but api doesn't really have a better way of doing this for _, x := range modData.FilesAFiles { dlurl = x.SDownloadURL break } fileDlPath := path.Join(tmpFolderDownload, "download") fileDl, err := os.Create(fileDlPath) if err != nil { return err } defer fileDl.Close() // download mod resp, err := http.Get(dlurl) log.Info("downloading mod", "url", dlurl, "modid", id, "path", fileDl) // TODO: handle error code properly if err != nil || resp.StatusCode != 200 { return err } defer resp.Body.Close() // save to temp file _, err = io.Copy(fileDl, resp.Body) if err != nil { return err } // extract files to same directory a, err := unarr.NewArchive(fileDlPath) if err != nil { return err } _, err = a.Extract(tmpFolderDownload) if err != nil { return err } // such jank but ive spent wayyy too long on this var moddir string = "" err = filepath.Walk(tmpFolderDownload, func(filePath string, _ fs.FileInfo, err error) error { if path.Base(filePath) == "config.toml" { moddir = path.Dir(filePath) log.Info("found mod folder", "configloc", filePath) } return nil }) if moddir == "" { errors.New("config.toml not found in mod dir") } if err != nil { return err } // create a folder put the mod in outpath := path.Join(outdir, fmt.Sprintf("%s@%d", id, modData.Udate)) err = os.Mkdir(outpath, 0600) if err != nil { return err } err = filepath.Walk(moddir, func(filePath string, fileinfo fs.FileInfo, err error) error { relativepath := strings.Replace(filePath, moddir, "", 1) newpath := path.Join(outdir, relativepath) if relativepath == "" { return nil } if fileinfo.IsDir() == true { log.Warn("found directory, creating it!", "path", filePath, "relpath", relativepath, "newpath", newpath) err = os.Mkdir(newpath, 0744) if err != nil { return err } return nil } var src *os.File var dst *os.File if src, err = os.Open(filePath); err != nil { return err } defer src.Close() if dst, err = os.Create(newpath); err != nil { return err } defer dst.Close() if _, err = io.Copy(dst, src); err != nil { return err } log.Info("copied file!!!", "src", filePath, "dst", newpath, "relativepath", relativepath) return os.Chmod(newpath, 0744) }) if err != nil { return err } // TODO: cleanup temp files err = os.RemoveAll(fileDlPath) if err != nil { return err } return nil }