package content import ( "archive/tar" "bytes" "compress/gzip" "encoding/json" "fmt" "io" "io/ioutil" "net/url" "os" "path/filepath" "strings" httputil "github.com/criticalstack/quake-kube/internal/util/net/http" ) func CopyAssets(u *url.URL, dir string) error { url := strings.TrimSuffix(u.String(), "/") files, err := getManifest(url) if err != nil { return err } for _, f := range files { path := filepath.Join(dir, f.Name) if _, err := os.Stat(path); !os.IsNotExist(err) { continue } data, err := httputil.GetBody(url + fmt.Sprintf("/assets/%d-%s", f.Checksum, f.Name)) if err != nil { return err } if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil { return err } if err := ioutil.WriteFile(path, data, 0644); err != nil { return err } if strings.HasPrefix(f.Name, "linuxq3ademo") { if err := extractDemoPack(path, dir); err != nil { return err } } if strings.HasPrefix(f.Name, "linuxq3apoint") { if err := extractPointPacks(path, dir); err != nil { return err } } } return nil } func getManifest(url string) ([]*File, error) { data, err := httputil.GetBody(url + "/assets/manifest.json") if err != nil { return nil, err } files := make([]*File, 0) if err := json.Unmarshal(data, &files); err != nil { return nil, err } return files, nil } var gzipMagicHeader = []byte{'\x1f', '\x8b'} func extractDemoPack(path, dir string) error { data, err := ioutil.ReadFile(path) if err != nil { return err } idx := bytes.Index(data, gzipMagicHeader) data = data[idx:] gr, err := gzip.NewReader(bytes.NewReader(data)) if err != nil { return err } defer gr.Close() data, err = ioutil.ReadAll(gr) if err != nil { return err } tr := tar.NewReader(bytes.NewReader(data)) for { hdr, err := tr.Next() if err == io.EOF { break } if err != nil { return err } if strings.HasSuffix(hdr.Name, ".pk3") { fmt.Printf("Downloaded %s\n", hdr.Name) data, err := ioutil.ReadAll(tr) if err != nil { return err } path := filepath.Join(dir, "baseq3", filepath.Base(hdr.Name)) if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil { return err } if err := ioutil.WriteFile(path, data, 0644); err != nil { return err } } } return nil } func extractPointPacks(path, dir string) error { data, err := ioutil.ReadFile(path) if err != nil { return err } idx := bytes.Index(data, gzipMagicHeader) data = data[idx:] gr, err := gzip.NewReader(bytes.NewReader(data)) if err != nil { return err } defer gr.Close() data, err = ioutil.ReadAll(gr) if err != nil { return err } tr := tar.NewReader(bytes.NewReader(data)) for { hdr, err := tr.Next() if err == io.EOF { break } if err != nil { return err } if strings.HasSuffix(hdr.Name, ".pk3") { fmt.Printf("Downloaded %s\n", hdr.Name) data, err := ioutil.ReadAll(tr) if err != nil { return err } path := filepath.Join(dir, hdr.Name) if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil { return err } if err := ioutil.WriteFile(path, data, 0644); err != nil { return err } } } return nil }