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/reader.go

220 lines
4.2 KiB
Go
Raw Normal View History

2012-08-21 18:15:21 +02:00
package main
import (
2013-04-01 14:05:04 +02:00
"git.gitorious.org/go-pkg/epubgo.git"
"io"
2012-08-21 18:15:21 +02:00
"labix.org/v2/mgo/bson"
"net/http"
"regexp"
2012-08-28 10:38:00 +02:00
"strconv"
2012-08-31 00:24:42 +02:00
"strings"
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
Book Book
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
}
2012-08-30 20:49:58 +02:00
func parseUrl(url string) (string, string, string) {
exp, _ := regexp.Compile("^(\\/[^\\/]*\\/)([^\\/]*)\\/?(.*)?$")
2012-08-21 18:15:21 +02:00
res := exp.FindStringSubmatch(url)
2012-08-21 20:54:57 +02:00
base := res[1]
2012-08-21 21:22:56 +02:00
id := res[2]
2012-08-21 18:15:21 +02:00
file := ""
2012-08-30 20:49:58 +02:00
if len(res) == 4 {
2012-08-21 20:54:57 +02:00
file = res[3]
2012-08-21 18:15:21 +02:00
}
2012-08-30 20:49:58 +02:00
return base, id, file
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)
link = link[:i] + string(c) + link[i+3:]
}
}
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 {
if cleanLink(spine.Url()) == file {
break
}
2013-04-01 14:05:04 +02:00
prev = spine.Url()
err = spine.Next()
}
if err != nil {
return "", ""
}
prev = genLink(id, base, prev)
if spine.Next() == nil {
next = genLink(id, base, spine.Url())
}
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
var err error = nil
for err == nil {
var c chapter
c.Label = nav.Title()
c.Link = nav.Url()
c.Depth = depth
2012-08-28 12:24:11 +02:00
for c.Depth < depth {
c.Out = append(c.Out, true)
depth--
2012-08-28 11:50:08 +02:00
}
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)
children[0].In = []bool{true}
children[len(children)-1].Out = []bool{true}
chapters = append(chapters, children...)
nav.Out()
}
err = nav.Next()
}
2013-04-01 14:05:04 +02:00
chapters[0].In = []bool{true}
chapters[len(chapters)-1].Out = []bool{true}
return chapters
2012-08-28 10:38:00 +02:00
}
func readHandler(w http.ResponseWriter, r *http.Request) {
base, id, file := parseUrl(r.URL.Path)
books, _, err := db.GetBooks(bson.M{"_id": bson.ObjectIdHex(id)})
if err != nil || len(books) == 0 {
http.NotFound(w, r)
return
}
var data readData
data.Book = books[0]
2012-09-14 00:34:13 +02:00
if !data.Book.Active {
sess := GetSession(r)
if sess.User == "" {
2012-08-21 18:15:21 +02:00
http.NotFound(w, r)
return
}
data.Back = "/new/"
} else {
data.Back = "/book/" + id
}
2013-04-12 01:05:40 +02:00
e, err := OpenBook(data.Book.File)
2013-04-01 14:05:04 +02:00
if err != nil {
http.NotFound(w, r)
return
}
defer e.Close()
if file == "" {
2013-04-01 14:05:04 +02:00
it, err := e.Spine()
if err != nil {
http.NotFound(w, r)
return
}
http.Redirect(w, r, base+id+"/"+it.Url(), http.StatusTemporaryRedirect)
return
2012-08-30 20:49:58 +02:00
}
data.S = GetStatus(w, r)
2013-04-01 14:05:04 +02:00
data.Next, data.Prev = getNextPrev(e, file, id, base)
data.Chapters = getChapters(e, file, id, base)
data.Content = genLink(id, "/content/", file)
loadTemplate(w, "read", data)
2012-08-30 20:49:58 +02:00
}
func contentHandler(w http.ResponseWriter, r *http.Request) {
_, id, file := parseUrl(r.URL.Path)
2013-04-12 01:05:40 +02:00
if file == "" {
http.NotFound(w, r)
return
}
books, _, err := db.GetBooks(bson.M{"_id": bson.ObjectIdHex(id)})
if err != nil || len(books) == 0 {
http.NotFound(w, r)
return
}
book := books[0]
2012-09-14 00:34:13 +02:00
if !book.Active {
sess := GetSession(r)
if sess.User == "" {
2012-08-30 20:49:58 +02:00
http.NotFound(w, r)
return
}
2012-08-21 18:15:21 +02:00
}
2013-04-12 01:05:40 +02:00
e, err := OpenBook(book.File)
if err != nil {
http.NotFound(w, r)
return
}
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 {
http.NotFound(w, r)
return
}
defer html.Close()
io.Copy(w, html)
2012-08-21 18:15:21 +02:00
}