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  }