Нет описания

archive.go 2.1KB

    package main import ( "crypto/rand" "encoding/json" "fmt" "net/url" "os" "os/exec" "path" "path/filepath" ) type Archive struct { Mappings map[string]string `json:"mappings"` } func main() { u, err := url.Parse(os.Args[1]) if err != nil { exit("url.Parse", err) } f, err := os.Open("archive.json") if err != nil { exit("os.Open", err) } var archive Archive dec := json.NewDecoder(f) err = dec.Decode(&archive) if err != nil { exit("dec.Decode", err) } f.Close() p, ok := archive.Mappings[u.String()] if ok { fmt.Println("==> Archived at", p) return } if u.Scheme != "http" && u.Scheme != "https" { fmt.Fprintf(os.Stderr, "Unknown url scheme %q\n", u.Scheme) os.Exit(1) } fmt.Println("==> Archiving", u) buf := make([]byte, 16) _, err = rand.Read(buf) if err != nil { exit("rand.Read", err) } cmd := exec.Command("prince", "--javascript", "--raster-output", fmt.Sprintf(".archive/%x-%%d.png", buf), u.String()) cmd.Stderr = os.Stderr cmd.Stdout = os.Stdout err = cmd.Run() if err != nil { exit("prince", err) } parts, err := filepath.Glob(fmt.Sprintf(".archive/%x-*.png", buf)) if err != nil { exit("filepath.Glob", err) } h := fmt.Sprintf(".archive/%x.html", buf) f, err = os.OpenFile(h, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0660) if err != nil { exit("os.OpenFile", err) } fmt.Fprintf(f, `<doctype html> <html> <head> <title>%s</title> </head> <body> `, u) wd, err := os.Getwd() if err != nil { exit("os.Getwd", err) } for _, p := range parts { fmt.Fprintf(f, "<img src=%q />\n", path.Join(wd, p)) } fmt.Fprintf(f, "\n\t</body>\n</html>") f.Close() if archive.Mappings == nil { archive.Mappings = make(map[string]string, 1) } p = fmt.Sprintf("file://%s", path.Join(wd, h)) archive.Mappings[u.String()] = p f, err = os.OpenFile("archive.json", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0660) if err != nil { exit("os.OpenFile", err) } enc := json.NewEncoder(f) err = enc.Encode(&archive) if err != nil { exit("enc.Encode", err) } f.Close() fmt.Println("==> Archived at", p) } func exit(msg string, err error) { fmt.Fprintf(os.Stderr, "Error: %s: %s\n", msg, err) os.Exit(1) }