diff --git a/lib/rss.go b/lib/rss.go new file mode 100644 index 0000000..28f23d7 --- /dev/null +++ b/lib/rss.go @@ -0,0 +1,158 @@ +package trantor + +import ( + "encoding/xml" + "errors" + "net/http" + "strings" + + "gitlab.com/trantor/trantor/lib/database" +) + +type rss struct { + XMLName xml.Name `xml:"rss"` + Version string `xml:"version,attr"` + Channel channel `xml:"channel"` +} + +type channel struct { + Title string `xml:"title"` + Description string `xml:"description"` + Link string `xml:"link"` + ManagingEditor string `xml:"managingEditor,omitempty"` + Item []item `xml:"item"` +} + +type item struct { + Title string `xml:"title"` + Description string `xml:"description"` + Link string `xml:"link"` + GUID *guid `xml:"guid,omitempty"` + Enclosure *enclosure `xml:"enclosure,omitempty"` + Category []string `xml:"category"` +} + +type guid struct { + IsPermaLink bool `xml:"isPermaLink,attr"` + Chardata string `xml:",chardata"` +} + +type enclosure struct { + URL string `xml:"url,attr"` + Length int `xml:"length,attr"` + Type string `xml:"type,attr"` +} + +func loadRss(w http.ResponseWriter, tmpl string, data interface{}) error { + var err error + var res rss + switch tmpl { + case "news": + res, err = newsRss(data) + case "search": + res, err = searchRss(data) + case "list": + res, err = listRss(data) + } + if err != nil { + return err + } + w.Write([]byte(xml.Header)) + enc := xml.NewEncoder(w) + enc.Indent("", " ") + return enc.Encode(res) +} + +func newsRss(data interface{}) (rss, error) { + news, ok := data.(newsData) + if !ok { + return rss{}, errors.New("Data is not valid") + } + + feed := rss{ + Version: "2.0", + Channel: channel{ + Title: news.S.Title, + Description: "News of the library", + Link: news.S.BaseURL + "/news/", + Item: make([]item, len(news.News)), + }, + } + for i, n := range news.News { + feed.Channel.Item[i] = item{ + Title: n.Date, + Description: n.Text, + Link: news.S.BaseURL + "/news/", + } + } + + return feed, nil +} + +func searchRss(data interface{}) (rss, error) { + search, ok := data.(searchData) + if !ok { + return rss{}, errors.New("Data is not valid") + } + + description := "Last books added" + link := search.S.BaseURL + if search.S.Search != "" { + description = "Book search: " + search.S.Search + link += "/search/?q=" + search.S.Search + } + + feed := rss{ + Version: "2.0", + Channel: channel{ + Title: search.S.Title, + Description: description, + Link: link, + Item: bookListRss(search.Books, search.S.BaseURL), + }, + } + return feed, nil +} + +func listRss(data interface{}) (rss, error) { + lb, ok := data.(listData) + if !ok { + return rss{}, errors.New("Data is not valid") + } + + feed := rss{ + Version: "2.0", + Channel: channel{ + Title: lb.S.Title, + Description: strings.Join(lb.List.Description, "\n"), + Link: lb.S.BaseURL + "/list/" + lb.List.ListID, + ManagingEditor: lb.List.User.Username, + Item: bookListRss(lb.List.Books, lb.S.BaseURL), + }, + } + return feed, nil +} + +func bookListRss(books []database.Book, baseURL string) []item { + items := make([]item, len(books)) + for i, b := range books { + items[i] = item{ + Title: b.Title, + Description: b.Description, + Link: baseURL + "/download/" + b.ID, + Category: b.Tags, + Enclosure: &enclosure{ + URL: baseURL + "/download/" + b.ID + "/" + b.Title + ".epub", + Length: b.FileSize, + Type: "application/epub+zip", + }, + } + if b.Isbn != "" { + items[i].GUID = &guid{ + IsPermaLink: false, + Chardata: "ISBN: " + b.Isbn, + } + } + } + return items +} diff --git a/lib/stats.go b/lib/stats.go index b12bb86..9e663f9 100644 --- a/lib/stats.go +++ b/lib/stats.go @@ -35,7 +35,7 @@ func (h handler) load(tmpl string, data interface{}) { fmt := h.r.FormValue("fmt") switch fmt { case "rss": - err = h.template.rss.ExecuteTemplate(h.w, tmpl+".rss", data) + err = loadRss(h.w, tmpl, data) case "opds": err = h.template.opds.ExecuteTemplate(h.w, tmpl+".opds", data) case "json": diff --git a/lib/template.go b/lib/template.go index 8b73d3d..2b6fb6f 100644 --- a/lib/template.go +++ b/lib/template.go @@ -55,7 +55,6 @@ func GetStatus(h handler) Status { type Template struct { html *html_tmpl.Template - rss *txt_tmpl.Template opds *txt_tmpl.Template } @@ -71,18 +70,6 @@ func InitTemplate(assetsPath string) *Template { log.Critical("Error loading html templates: ", err) } - t.rss, err = txt_tmpl.New("rss").Funcs(txt_tmpl.FuncMap{ - "book_list": func(books, baseURL interface{}) (map[string]interface{}, error) { - data := make(map[string]interface{}, 2) - data["Books"] = books - data["BaseURL"] = baseURL - return data, nil - }, - }).ParseGlob(path.Join(templatePath, "*.rss")) - if err != nil { - log.Critical("Error loading rss templates: ", err) - } - t.opds, err = txt_tmpl.ParseGlob(path.Join(templatePath, "*.opds")) if err != nil { log.Critical("Error loading opds templates: ", err) diff --git a/templates/book_list.rss b/templates/book_list.rss deleted file mode 100644 index 89ab859..0000000 --- a/templates/book_list.rss +++ /dev/null @@ -1,17 +0,0 @@ -{{$baseURL := .BaseURL}} -{{range .Books}} - - {{.Title}} - {{index .Authors 0}} - {{.Description}} - {{$baseURL}}/book/{{.ID}} -{{if .Isbn}} - ISBN: {{.Isbn}} -{{end}} - -{{range .Authors}} - {{if .}} - {{.}} - {{end}} -{{end}} - -{{end}} diff --git a/templates/list.rss b/templates/list.rss deleted file mode 100644 index 73a7dab..0000000 --- a/templates/list.rss +++ /dev/null @@ -1,14 +0,0 @@ - - - - {{.S.Title}} - {{range .List.Description}} - {{.}} -{{end}} - {{.S.BaseURL}}/list/{{.List.ListID}} - {{.List.User.Username}} - -{{template "book_list.rss" book_list .List.Books .S.BaseURL}} - - - diff --git a/templates/news.rss b/templates/news.rss deleted file mode 100644 index 228c4a9..0000000 --- a/templates/news.rss +++ /dev/null @@ -1,20 +0,0 @@ - - - -{{with .S}} - {{.Title}} - News of the library - {{.BaseURL}}/news/ -{{end}} - -{{$baseURL := .S.BaseURL}} -{{range .News}} - - {{.Date}} - {{.Text}} - {{$baseURL}}/news/ - -{{end}} - - - diff --git a/templates/search.rss b/templates/search.rss deleted file mode 100644 index bba18d9..0000000 --- a/templates/search.rss +++ /dev/null @@ -1,17 +0,0 @@ - - - -{{with .S}} - {{.Title}} -{{if .Search}} - Book search: {{.Search}} -{{else}} - Last books added -{{end}} - {{.BaseURL}} -{{end}} - -{{template "book_list.rss" book_list .Books .S.BaseURL}} - - -