func writeHTML(j *job.Job) { file := openFile(j.HTMLFilePath()) defer file.Close() if err := template.Execute(file, j); err != nil { logger.Panicf("Failed rendering HTML to file: %s", err.Error()) } }
func Do(logger *log.Logger, j *job.Job, progress string, f func()) { defer func() { if r := recover(); r != nil { if err, ok := r.(friendly); ok { progress = err.Friendly() logger.Printf("%s: %#v", progress, j) } else { logger.Printf("%v: %#v", r, j) } logger.Printf("%s", pruneStack(debug.Stack())) j.Progress(progress) cleanup.Clean(j) } }() f() }
func rewriteAndDownloadImages(j *job.Job, doc *h5.Node) *h5.Node { var wg sync.WaitGroup root := j.Root() t := transform.NewTransform(doc) fix := transform.TransformAttrib("src", func(uri string) string { altered := fmt.Sprintf("%x.jpg", hashie.Sha1([]byte(uri))) wg.Add(1) go safely.Ignore(logger, func() { defer wg.Done() downloadToFile(uri, fmt.Sprintf("%s/%s", root, altered)) }) return altered }) t.Apply(fix, "img") wg.Wait() return t.Doc() }
func Convert(j *job.Job) { go safely.Do(logger, j, FriendlyMessage, func() { writeHTML(j) cmd := exec.Command(kindlegen, []string{j.HTMLFilename()}...) cmd.Dir = j.Root() out, err := cmd.CombinedOutput() if !util.FileExists(j.MobiFilePath()) { logger.Panicf("Failed running kindlegen: %s {output=%s}", err.Error(), string(out)) } j.Progress("Conversion complete...") postmark.Mail(j) }) }
func Extract(j *job.Job) { go safely.Do(logger, j, FriendlyMessage, func() { makeRoot(j) data := downloadAndParse(j) checkDoc(data, j) doc := parseHTML(data["content"].(string)) j.Doc = rewriteAndDownloadImages(j, doc) j.Title = data["title"].(string) j.Domain = data["domain"].(string) if author := data["author"]; author != nil { j.Author = author.(string) } j.Progress("Extraction complete...") kindlegen.Convert(j) }) }
func Mail(j *job.Job) { go safely.Do(logger, j, FriendlyMessage, func() { if stat, err := os.Stat(j.MobiFilePath()); err != nil { logger.Panicf("Something weird happen. Mobi is missing in postmark.go: %s", err.Error()) } else { if stat.Size() > MaxAttachmentSize { blacklist.Blacklist(j.Url.String()) failFriendly("Sorry, this article is too big to send!") } } payload := map[string]Any{ "From": from, "To": j.Email, "Subject": Subject, "TextBody": fmt.Sprintf("Straight to your Kindle! %s: %s", j.Title, j.Url), "Attachments": []Any{ map[string]Any{ "Name": j.MobiFilename(), "ContentType": "application/octet-stream", "Content": readFile(j.MobiFilePath()), }, }, } var buffer bytes.Buffer json.NewEncoder(&buffer).Encode(payload) req, err := http.NewRequest("POST", Endpoint, &buffer) if err != nil { logger.Panicf("Making HTTP Request failed: %s", err.Error()) } setupHeaders(req) resp, err := client.Do(req) if err != nil { logger.Panicf("Postmark failed: %s", err.Error()) } defer resp.Body.Close() answer := util.ParseJSON(resp.Body, func(err error) { logger.Panicf("Something bad happened with Postmark: %s", err.Error()) }) if answer["ErrorCode"] != nil { code := int(answer["ErrorCode"].(float64)) switch code { case 0: // All is well case 300: blacklist.Blacklist(j.Email) failFriendly("Your email appears invalid. Please try carefully remaking the bookmarklet.") default: logger.Panicf("Unknown error code from Postmark: %d, %s", code, answer) } } j.Progress("All done! Grab your Kindle and hang tight!") cleanup.Clean(j) }) }
func makeRoot(j *job.Job) { if err := os.MkdirAll(j.Root(), 0755); err != nil { logger.Panicf("Failed to make working directory: %s", err.Error()) } }