Basic OPDS support
This commit is contained in:
parent
078b210392
commit
b0a0b68561
6 changed files with 175 additions and 0 deletions
|
@ -34,6 +34,7 @@ const (
|
|||
IMG_PATH = "img/"
|
||||
ROBOTS_PATH = "robots.txt"
|
||||
DESCRIPTION_PATH = "description.json"
|
||||
OPENSEARCH_PATH = "opensearch.xml"
|
||||
LOGGER_CONFIG = "logger.xml"
|
||||
|
||||
IMG_WIDTH_BIG = 300
|
||||
|
|
11
opensearch.xml
Normal file
11
opensearch.xml
Normal file
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
|
||||
<ShortName>Imperial Library of Trantor</ShortName>
|
||||
<Description>Book search in the library.</Description>
|
||||
<InputEncoding>UTF-8</InputEncoding>
|
||||
<OutputEncoding>UTF-8</OutputEncoding>
|
||||
<Tags>books epub</Tags>
|
||||
<Image type="image/x-icon" width="16" height="16">/img/favicon.ico</Image>
|
||||
<Contact>zenow@riseup.net</Contact>
|
||||
<Url type="application/atom+xml" template="/search/?fmt=opds&q={searchTerms}"/>
|
||||
</OpenSearchDescription>
|
10
template.go
10
template.go
|
@ -9,6 +9,7 @@ import (
|
|||
"errors"
|
||||
"html/template"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"git.gitorious.org/trantor/trantor.git/database"
|
||||
)
|
||||
|
@ -20,6 +21,7 @@ type Status struct {
|
|||
User string
|
||||
IsAdmin bool
|
||||
Notif []Notification
|
||||
Updated string
|
||||
Home bool
|
||||
About bool
|
||||
News bool
|
||||
|
@ -36,6 +38,7 @@ func GetStatus(h handler) Status {
|
|||
s.User = h.sess.User
|
||||
s.IsAdmin = h.sess.IsAdmin()
|
||||
s.Notif = h.sess.GetNotif()
|
||||
s.Updated = time.Now().UTC().Format("2006-01-02T15:04:05Z")
|
||||
h.sess.Save(h.w, h.r)
|
||||
return s
|
||||
}
|
||||
|
@ -66,12 +69,19 @@ var tmpl_rss = txt_tmpl.Must(txt_tmpl.ParseFiles(
|
|||
TEMPLATE_PATH+"news.rss",
|
||||
))
|
||||
|
||||
var tmpl_opds = txt_tmpl.Must(txt_tmpl.ParseFiles(
|
||||
TEMPLATE_PATH+"index.opds",
|
||||
TEMPLATE_PATH+"search.opds",
|
||||
))
|
||||
|
||||
func loadTemplate(h handler, tmpl string, data interface{}) {
|
||||
var err error
|
||||
fmt := h.r.FormValue("fmt")
|
||||
switch fmt {
|
||||
case "rss":
|
||||
err = tmpl_rss.ExecuteTemplate(h.w, tmpl+".rss", data)
|
||||
case "opds":
|
||||
err = tmpl_opds.ExecuteTemplate(h.w, tmpl+".opds", data)
|
||||
case "json":
|
||||
err = loadJson(h.w, tmpl, data)
|
||||
default:
|
||||
|
|
52
templates/index.opds
Normal file
52
templates/index.opds
Normal file
|
@ -0,0 +1,52 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<feed xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:odl="http://opds-spec.org/odl"
|
||||
xml:lang="en"
|
||||
xmlns="http://www.w3.org/2005/Atom"
|
||||
xmlns:dcterms="http://purl.org/dc/terms/"
|
||||
xmlns:app="http://www.w3.org/2007/app"
|
||||
xmlns:opds="http://opds-spec.org/2010/catalog"
|
||||
xmlns:thr="http://purl.org/syndication/thread/1.0"
|
||||
xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/">
|
||||
<id>{{.S.BaseURL}}</id>
|
||||
<link rel="self"
|
||||
href="/?fmt=opds"
|
||||
type="application/atom+xml;profile=opds-catalog;kind=navigation"/>
|
||||
<link rel="start"
|
||||
href="/?fmt=opds"
|
||||
type="application/atom+xml;profile=opds-catalog;kind=navigation"/>
|
||||
<link rel="search"
|
||||
href="/opensearch.xml"
|
||||
type="application/opensearchdescription+xml"/>
|
||||
|
||||
<title>The Imperial Libary of Trantor</title>
|
||||
<author>
|
||||
<name>The Imperial Library of Trantor</name>
|
||||
<uri>{{.S.BaseURL}}</uri>
|
||||
<email>zenow@riseup.net</email>
|
||||
</author>
|
||||
<updated>{{.S.Updated}}</updated>
|
||||
<icon>{{.S.BaseURL}}/img/favicon.ico</icon>
|
||||
|
||||
<entry>
|
||||
<title>Last books added</title>
|
||||
<link rel="http://opds-spec.org/sort/new"
|
||||
href="/search/?fmt=opds"
|
||||
type="application/atom+xml;profile=opds-catalog;kind=acquisition"/>
|
||||
<updated>{{.S.Updated}}</updated>
|
||||
<id>{{.S.BaseURL}}/search/</id>
|
||||
</entry>
|
||||
{{$updated := .S.Updated}}
|
||||
{{$baseurl := .S.BaseURL}}
|
||||
{{range .Tags}}
|
||||
<entry>
|
||||
<title>{{html .}}</title>
|
||||
<link rel="http://opds-spec.org/facet"
|
||||
href="/search/?q=subject:{{urlquery .}}&fmt=opds"
|
||||
title="{{html .}}"
|
||||
type="application/atom+xml;profile=opds-catalog;kind=acquisition"/>
|
||||
<updated>{{$updated}}</updated>
|
||||
<id>{{$baseurl}}/search/?subject:{{urlquery .}}</id>
|
||||
</entry>
|
||||
{{end}}
|
||||
</feed>
|
100
templates/search.opds
Normal file
100
templates/search.opds
Normal file
|
@ -0,0 +1,100 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<feed xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:odl="http://opds-spec.org/odl"
|
||||
xml:lang="en"
|
||||
xmlns="http://www.w3.org/2005/Atom"
|
||||
xmlns:dcterms="http://purl.org/dc/terms/"
|
||||
xmlns:app="http://www.w3.org/2007/app"
|
||||
xmlns:opds="http://opds-spec.org/2010/catalog"
|
||||
xmlns:thr="http://purl.org/syndication/thread/1.0"
|
||||
xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/">
|
||||
<id>{{.S.BaseURL}}/search/?q={{.S.Search}}</id>
|
||||
<icon>{{.S.BaseURL}}/img/favicon.ico</icon>
|
||||
|
||||
<link rel="self"
|
||||
href="/search/?q={{.S.Search}}&p={{.Page}}&fmt=opds"
|
||||
type="application/atom+xml;profile=opds-catalog;kind=acquisition"/>
|
||||
<link rel="start"
|
||||
href="/?fmt=opds"
|
||||
type="application/atom+xml;profile=opds-catalog;kind=navigation"/>
|
||||
<link rel="up"
|
||||
href="/?fmt=opds"
|
||||
type="application/atom+xml;profile=opds-catalog;kind=navigation"/>
|
||||
{{if .Prev}}
|
||||
<link rel="first"
|
||||
href="/search/?q={{.S.Search}}&fmt=opds"
|
||||
type="application/atom+xml;profile=opds-catalog;kind=acquisition"/>
|
||||
<link rel="previous"
|
||||
href="{{html .Prev}}&fmt=opds"
|
||||
type="application/atom+xml;profile=opds-catalog;kind=acquisition"/>
|
||||
{{end}}
|
||||
{{if .Next}}
|
||||
<link rel="next"
|
||||
href="{{html .Next}}&fmt=opds"
|
||||
type="application/atom+xml;profile=opds-catalog;kind=acquisition"/>
|
||||
{{end}}
|
||||
<link rel="search"
|
||||
title="Search The Imperial Libary of Trantor"
|
||||
href="/search/?q={searchTerms}&fmt=opds"
|
||||
type="application/atom+xml"/>
|
||||
<link rel="search"
|
||||
href="opensearch.xml"
|
||||
type="application/opensearchdescription+xml"/>
|
||||
|
||||
<opensearch:totalResults>{{.Found}}</opensearch:totalResults>
|
||||
<opensearch:itemsPerPage>{{.ItemsPage}}</opensearch:itemsPerPage>
|
||||
|
||||
<title>search {{.S.Search}}</title>
|
||||
<author>
|
||||
<name>The Imperial Library of Trantor</name>
|
||||
<uri>{{.S.BaseURL}}</uri>
|
||||
<email>zenow@riseup.net</email>
|
||||
</author>
|
||||
<updated>{{.S.Updated}}</updated>
|
||||
|
||||
|
||||
{{$updated := .S.Updated}}
|
||||
{{$baseurl := .S.BaseURL}}
|
||||
{{range .Books}}
|
||||
<entry>
|
||||
<title>{{html .Title}}</title>
|
||||
<id>{{$baseurl}}/book/{{.Id}}</id>
|
||||
<updated>{{$updated}}</updated>
|
||||
|
||||
{{range .Author}}
|
||||
<author>
|
||||
<name>{{html .}}</name>
|
||||
</author>
|
||||
{{end}}
|
||||
{{if .Contributor}}
|
||||
<contributor>
|
||||
<name>{{html .Contributor}}</name>
|
||||
</contributor>
|
||||
{{end}}
|
||||
|
||||
{{if .Isbn}}
|
||||
<dcterms:identifier>urn:isbn:{{.Isbn}}</dcterms:identifier>
|
||||
{{end}}
|
||||
<dcterms:publisher>{{html .Publisher}}</dcterms:publisher>
|
||||
{{if .Date}}
|
||||
<dcterms:issued>{{.Date}}</dcterms:issued>
|
||||
{{end}}
|
||||
|
||||
{{range .Lang}}
|
||||
<dcterms:language>{{.}}</dcterms:language>
|
||||
{{end}}
|
||||
{{range .Subject}}
|
||||
<category term="{{html .}}"
|
||||
label="{{html .}}"/>
|
||||
{{end}}
|
||||
<summary>{{html .Description}}</summary>
|
||||
|
||||
<link type="image/jpeg" href="/cover/{{.Id}}/big/cover.jpg" rel="http://opds-spec.org/image"/>
|
||||
<link type="image/jpg" href="/cover/{{.Id}}/small/thumbnail.jpg" rel="http://opds-spec.org/image/thumbnail" />
|
||||
|
||||
<link rel="http://opds-spec.org/acquisition"
|
||||
href="/download/{{.Id}}/{{urlquery .Title}}.epub"
|
||||
type="application/epub+zip" />
|
||||
</entry>
|
||||
{{end}}
|
||||
</feed>
|
|
@ -187,6 +187,7 @@ func initRouter(db *database.DB, sg *StatsGatherer) {
|
|||
r.HandleFunc("/", sg.Gather(indexHandler))
|
||||
r.HandleFunc("/robots.txt", func(w http.ResponseWriter, r *http.Request) { http.ServeFile(w, r, ROBOTS_PATH) })
|
||||
r.HandleFunc("/description.json", func(w http.ResponseWriter, r *http.Request) { http.ServeFile(w, r, DESCRIPTION_PATH) })
|
||||
r.HandleFunc("/opensearch.xml", func(w http.ResponseWriter, r *http.Request) { http.ServeFile(w, r, OPENSEARCH_PATH) })
|
||||
|
||||
r.HandleFunc("/book/{id:"+id_pattern+"}", sg.Gather(bookHandler))
|
||||
r.HandleFunc("/search/", sg.Gather(searchHandler))
|
||||
|
|
Reference in a new issue