github.com/soulteary/pocket-bookcase@v0.0.0-20240428065142-0b5a9a0fc98a/internal/core/ebook.go (about) 1 package core 2 3 import ( 4 "os" 5 fp "path/filepath" 6 "strconv" 7 "strings" 8 9 epub "github.com/go-shiori/go-epub" 10 "github.com/pkg/errors" 11 "github.com/soulteary/pocket-bookcase/internal/dependencies" 12 "github.com/soulteary/pocket-bookcase/internal/model" 13 ) 14 15 // GenerateEbook receives a `ProcessRequest` and generates an ebook file in the destination path specified. 16 // The destination path `dstPath` should include file name with ".epub" extension 17 // The bookmark model will be used to update the UI based on whether this function is successful or not. 18 func GenerateEbook(deps *dependencies.Dependencies, req ProcessRequest, dstPath string) (book model.BookmarkDTO, err error) { 19 book = req.Bookmark 20 21 // Make sure bookmark ID is defined 22 if book.ID == 0 { 23 return book, errors.New("bookmark ID is not valid") 24 } 25 26 // Get current state of bookmark cheak archive and thumb 27 strID := strconv.Itoa(book.ID) 28 29 bookmarkThumbnailPath := model.GetThumbnailPath(&book) 30 bookmarkArchivePath := model.GetArchivePath(&book) 31 32 if deps.Domains.Storage.FileExists(bookmarkThumbnailPath) { 33 book.ImageURL = fp.Join("/", "bookmark", strID, "thumb") 34 } 35 36 if deps.Domains.Storage.FileExists(bookmarkArchivePath) { 37 book.HasArchive = true 38 } 39 40 // This function create ebook from reader mode of bookmark so 41 // we can't create ebook from PDF so we return error here if bookmark is a pdf 42 contentType := req.ContentType 43 if strings.Contains(contentType, "application/pdf") { 44 return book, errors.New("can't create ebook for pdf") 45 } 46 47 // Create temporary epub file 48 tmpFile, err := os.CreateTemp("", "ebook") 49 if err != nil { 50 return book, errors.Wrap(err, "can't create temporary EPUB file") 51 } 52 defer os.Remove(tmpFile.Name()) 53 54 // Create last line of ebook 55 lastline := `<hr/><p style="text-align:center">Generated By <a href="https://github.com/soulteary/pocket-bookcase">Shiori</a> From <a href="` + book.URL + `">This Page</a></p>` 56 57 // Create ebook 58 ebook, err := epub.NewEpub(book.Title) 59 if err != nil { 60 return book, errors.Wrap(err, "can't create EPUB") 61 } 62 63 ebook.SetTitle(book.Title) 64 ebook.SetAuthor(book.Author) 65 ebook.SetDescription(book.Excerpt) 66 _, err = ebook.AddSection(`<h1 style="text-align:center"> `+book.Title+` </h1>`+book.HTML+lastline, book.Title, "", "") 67 if err != nil { 68 return book, errors.Wrap(err, "can't add ebook Section") 69 } 70 ebook.EmbedImages() 71 err = ebook.Write(tmpFile.Name()) 72 if err != nil { 73 return book, errors.Wrap(err, "can't create ebook file") 74 } 75 76 defer tmpFile.Close() 77 78 // If everything go well we move ebook to dstPath 79 err = deps.Domains.Storage.WriteFile(dstPath, tmpFile) 80 if err != nil { 81 return book, errors.Wrap(err, "failed move ebook to destination") 82 } 83 84 book.HasEbook = true 85 return book, nil 86 }