This repository has been archived on 2025-03-01. You can view files and clone it, but cannot push or open issues or pull requests.
trantor/lib/reader.go

249 lines
4.5 KiB
Go
Raw Normal View History

2016-05-02 21:36:49 -04:00
package trantor
2012-08-21 18:15:21 +02:00
import (
2014-08-30 13:17:50 -05:00
log "github.com/cihub/seelog"
2013-04-01 14:05:04 +02:00
"io"
2012-08-21 18:15:21 +02:00
"net/http"
2012-08-28 10:38:00 +02:00
"strconv"
2012-08-31 00:24:42 +02:00
"strings"
"github.com/gorilla/mux"
2015-04-21 21:32:01 -04:00
"github.com/meskio/epubgo"
2016-05-02 21:36:49 -04:00
"gitlab.com/trantor/trantor/lib/database"
2017-05-18 22:16:16 +00:00
"gitlab.com/trantor/trantor/lib/storage"
2012-08-21 18:15:21 +02:00
)
2012-08-28 10:38:00 +02:00
type chapter struct {
2012-08-31 00:24:42 +02:00
Label string
Link string
Depth int
2012-08-28 10:38:00 +02:00
Active bool
2012-08-31 00:24:42 +02:00
In []bool // one level in depth
Out []bool // one level out depth
2012-08-28 10:38:00 +02:00
}
2012-08-21 18:15:21 +02:00
type readData struct {
2012-08-31 00:24:42 +02:00
S Status
2014-06-29 19:41:29 -05:00
Book database.Book
2012-08-31 00:24:42 +02:00
Content string
2012-08-28 10:38:00 +02:00
Chapters []chapter
2012-08-31 00:24:42 +02:00
Next string
Prev string
Back string
2012-08-21 18:15:21 +02:00
}
func cleanHtml(html string) string {
str := strings.Split(html, "<body")
if len(str) < 2 {
return html
}
str = strings.SplitN(str[1], ">", 2)
if len(str) < 2 {
return str[0]
}
return "<div " + str[0] + ">" + strings.Split(str[1], "</body>")[0] + "</div>"
}
2012-08-28 10:38:00 +02:00
func genLink(id string, base string, link string) string {
return base + id + "/" + link
}
func cleanLink(link string) string {
for i := 0; i < len(link); i++ {
if link[i] == '%' {
c, _ := strconv.ParseInt(link[i+1:i+3], 16, 0)
2020-11-30 19:03:31 +00:00
link = link[:i] + string(rune(c)) + link[i+3:]
2012-08-28 10:38:00 +02:00
}
}
return link
}
2013-04-01 14:05:04 +02:00
func getNextPrev(e *epubgo.Epub, file string, id string, base string) (string, string) {
spine, err := e.Spine()
if err != nil {
return "", ""
}
prev := ""
next := ""
2013-04-01 14:05:04 +02:00
for err == nil {
2013-06-04 21:30:37 +02:00
if cleanLink(spine.URL()) == file {
2013-04-01 14:05:04 +02:00
break
}
2013-06-04 21:30:37 +02:00
prev = spine.URL()
2013-04-01 14:05:04 +02:00
err = spine.Next()
}
if err != nil {
return "", ""
}
if prev != "" {
prev = genLink(id, base, prev)
}
2013-04-01 14:05:04 +02:00
if spine.Next() == nil {
2013-06-04 21:30:37 +02:00
next = genLink(id, base, spine.URL())
2013-04-01 14:05:04 +02:00
}
return next, prev
}
func getChapters(e *epubgo.Epub, file string, id string, base string) []chapter {
nav, err := e.Navigation()
if err != nil {
return nil
}
chapters := listChapters(nav, 0)
for i, c := range chapters {
chapters[i].Link = genLink(id, base, c.Link)
if cleanLink(c.Link) == file {
chapters[i].Active = true
2012-08-28 11:50:08 +02:00
}
2013-04-01 14:05:04 +02:00
}
return chapters
}
func listChapters(nav *epubgo.NavigationIterator, depth int) []chapter {
var chapters []chapter
2017-05-18 22:16:16 +00:00
var err error
2013-04-01 14:05:04 +02:00
for err == nil {
var c chapter
c.Label = nav.Title()
2013-06-04 21:30:37 +02:00
c.Link = nav.URL()
2013-04-01 14:05:04 +02:00
c.Depth = depth
2012-08-28 10:38:00 +02:00
chapters = append(chapters, c)
2013-04-01 14:05:04 +02:00
if nav.HasChildren() {
nav.In()
children := listChapters(nav, depth+1)
chapters = append(chapters, children...)
nav.Out()
}
err = nav.Next()
}
chapters[0].In = append(chapters[0].In, true)
chapters[len(chapters)-1].Out = append(chapters[len(chapters)-1].Out, true)
2013-04-01 14:05:04 +02:00
return chapters
2012-08-28 10:38:00 +02:00
}
func readStartHandler(h handler) {
id := mux.Vars(h.r)["id"]
2017-05-18 22:16:16 +00:00
e := openReadEpub(id, h.store)
2013-04-16 03:28:38 +02:00
if e == nil {
2014-08-21 19:24:23 -05:00
log.Warn("Open epub returns an empty file")
notFound(h)
return
}
2013-04-16 03:28:38 +02:00
defer e.Close()
2013-04-16 03:28:38 +02:00
it, err := e.Spine()
2013-04-01 14:05:04 +02:00
if err != nil {
2014-08-21 19:24:23 -05:00
log.Warn("No spine in the epub")
notFound(h)
2013-04-01 14:05:04 +02:00
return
}
http.Redirect(h.w, h.r, "/read/"+id+"/"+it.URL(), http.StatusTemporaryRedirect)
2013-04-16 03:28:38 +02:00
}
func readHandler(h handler) {
id := mux.Vars(h.r)["id"]
file := mux.Vars(h.r)["file"]
2017-05-18 22:16:16 +00:00
e := openReadEpub(id, h.store)
2013-04-16 03:28:38 +02:00
if e == nil {
notFound(h)
return
2012-08-30 20:49:58 +02:00
}
2013-04-16 03:28:38 +02:00
defer e.Close()
2013-04-16 03:28:38 +02:00
var data readData
data.S = GetStatus(h)
2017-05-18 22:16:16 +00:00
book, err := h.db.GetBookID(id)
if err != nil {
notFound(h)
return
}
author := ""
if len(book.Authors) > 0 {
author = " by " + book.Authors[0]
}
data.S.Title = book.Title + author + " -- Read -- " + data.S.Title
2013-04-16 03:28:38 +02:00
data.Book = book
if !book.Active {
data.Back = "/submission/moderate/"
2013-04-16 03:28:38 +02:00
} else {
data.Back = "/book/" + id
}
2013-04-15 00:59:19 +02:00
data.Next, data.Prev = getNextPrev(e, file, id, "/read/")
data.Chapters = getChapters(e, file, id, "/read/")
data.Content = genLink(id, "/content/", file)
h.load("read", data)
2012-08-30 20:49:58 +02:00
}
2017-05-18 22:16:16 +00:00
func openReadEpub(id string, store storage.Store) *epubgo.Epub {
f, err := store.Get(id, epubFile)
2014-07-02 20:40:24 -05:00
if err != nil {
2017-05-18 22:16:16 +00:00
return nil
}
defer f.Close()
info, err := f.Stat()
if err != nil {
2017-05-18 22:16:16 +00:00
return nil
}
e, err := epubgo.Load(f, info.Size())
2013-04-16 03:28:38 +02:00
if err != nil {
2017-05-18 22:16:16 +00:00
return nil
2013-04-16 03:28:38 +02:00
}
2017-05-18 22:16:16 +00:00
return e
2013-04-16 03:28:38 +02:00
}
func contentHandler(h handler) {
vars := mux.Vars(h.r)
2013-04-15 00:59:19 +02:00
id := vars["id"]
file := vars["file"]
2014-08-21 19:24:23 -05:00
if file == "" || id == "" {
notFound(h)
2013-04-12 01:05:40 +02:00
return
}
err := openEpubFile(h, id, file)
2014-07-02 20:40:24 -05:00
if err != nil {
notFound(h)
return
}
}
func openEpubFile(h handler, id string, file string) error {
f, err := h.store.Get(id, epubFile)
if err != nil {
return err
}
defer f.Close()
info, err := f.Stat()
2013-04-12 01:05:40 +02:00
if err != nil {
return err
}
e, err := epubgo.Load(f, info.Size())
if err != nil {
return err
}
2013-04-12 01:05:40 +02:00
defer e.Close()
2013-04-01 14:05:04 +02:00
html, err := e.OpenFile(file)
if err != nil {
return err
2013-04-01 14:05:04 +02:00
}
defer html.Close()
addCacheControlHeader(h.w, false)
io.Copy(h.w, html)
return nil
2014-08-21 19:24:23 -05:00
}