This commit is contained in:
+153
@@ -0,0 +1,153 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"podstalk/store"
|
||||
)
|
||||
|
||||
type RSSHandler struct {
|
||||
Store *store.Store
|
||||
BaseTitle string
|
||||
Link string
|
||||
Author string
|
||||
}
|
||||
|
||||
func (h *RSSHandler) resolveTitle() string {
|
||||
title, err := h.Store.GetSetting("podcast_title")
|
||||
if err == nil && title != "" {
|
||||
return title
|
||||
}
|
||||
if h.BaseTitle != "" {
|
||||
return h.BaseTitle
|
||||
}
|
||||
return "Podstalk"
|
||||
}
|
||||
|
||||
func (h *RSSHandler) resolveImage() string {
|
||||
img, err := h.Store.GetSetting("podcast_image")
|
||||
if err == nil && img != "" {
|
||||
return img
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type rssFeed struct {
|
||||
XMLName xml.Name `xml:"rss"`
|
||||
Version string `xml:"version,attr"`
|
||||
ItunesNS string `xml:"xmlns:itunes,attr"`
|
||||
Channel rssChannel `xml:"channel"`
|
||||
}
|
||||
|
||||
type rssChannel struct {
|
||||
Title string `xml:"title"`
|
||||
Link string `xml:"link"`
|
||||
Description string `xml:"description"`
|
||||
Language string `xml:"language"`
|
||||
Image *rssImage `xml:"image,omitempty"`
|
||||
ItunesImage *rssItunesImage `xml:"itunes:image,omitempty"`
|
||||
Items []rssItem `xml:"item"`
|
||||
}
|
||||
|
||||
type rssImage struct {
|
||||
URL string `xml:"url"`
|
||||
Title string `xml:"title"`
|
||||
Link string `xml:"link"`
|
||||
}
|
||||
|
||||
type rssItunesImage struct {
|
||||
Href string `xml:"href,attr"`
|
||||
}
|
||||
|
||||
type rssItem struct {
|
||||
Title string `xml:"title"`
|
||||
Description string `xml:"description"`
|
||||
Enclosure rssEnclosure `xml:"enclosure"`
|
||||
PubDate string `xml:"pubDate"`
|
||||
GUID string `xml:"guid"`
|
||||
ItunesImage *rssItunesImage `xml:"itunes:image,omitempty"`
|
||||
}
|
||||
|
||||
type rssEnclosure struct {
|
||||
URL string `xml:"url,attr"`
|
||||
Length string `xml:"length,attr,omitempty"`
|
||||
Type string `xml:"type,attr"`
|
||||
}
|
||||
|
||||
func (h *RSSHandler) ServeRSS(w http.ResponseWriter, r *http.Request) {
|
||||
episodes, err := h.Store.ListEpisodes()
|
||||
if err != nil {
|
||||
http.Error(w, "failed to load episodes", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
podcastTitle := h.resolveTitle()
|
||||
podcastImage := h.resolveImage()
|
||||
|
||||
items := make([]rssItem, 0, len(episodes))
|
||||
for _, ep := range episodes {
|
||||
var itemImage *rssItunesImage
|
||||
epImage := ep.ImagePath
|
||||
if epImage == "" {
|
||||
epImage = podcastImage
|
||||
}
|
||||
if epImage != "" {
|
||||
itemImage = &rssItunesImage{Href: h.fullURL(epImage)}
|
||||
}
|
||||
|
||||
items = append(items, rssItem{
|
||||
Title: ep.Title,
|
||||
Description: ep.Description,
|
||||
Enclosure: rssEnclosure{
|
||||
URL: h.fullURL(ep.AudioPath),
|
||||
Type: "audio/mpeg",
|
||||
},
|
||||
PubDate: ep.PublishedAt.Format(time.RFC1123Z),
|
||||
GUID: h.fullURL(ep.AudioPath),
|
||||
ItunesImage: itemImage,
|
||||
})
|
||||
}
|
||||
|
||||
var chanImage *rssImage
|
||||
var chanItunesImage *rssItunesImage
|
||||
if podcastImage != "" {
|
||||
chanImage = &rssImage{
|
||||
URL: h.fullURL(podcastImage),
|
||||
Title: podcastTitle,
|
||||
Link: h.Link,
|
||||
}
|
||||
chanItunesImage = &rssItunesImage{Href: h.fullURL(podcastImage)}
|
||||
}
|
||||
|
||||
feed := rssFeed{
|
||||
Version: "2.0",
|
||||
ItunesNS: "http://www.itunes.com/dtds/podcast-1.0.dtd",
|
||||
Channel: rssChannel{
|
||||
Title: podcastTitle,
|
||||
Link: h.Link,
|
||||
Description: podcastTitle,
|
||||
Language: "en-us",
|
||||
Image: chanImage,
|
||||
ItunesImage: chanItunesImage,
|
||||
Items: items,
|
||||
},
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/rss+xml; charset=utf-8")
|
||||
w.Write([]byte(xml.Header))
|
||||
enc := xml.NewEncoder(w)
|
||||
enc.Indent("", " ")
|
||||
enc.Encode(feed)
|
||||
}
|
||||
|
||||
func (h *RSSHandler) fullURL(path string) string {
|
||||
if path == "" {
|
||||
return ""
|
||||
}
|
||||
if h.Link == "" {
|
||||
return path
|
||||
}
|
||||
return h.Link + "/uploads/" + path
|
||||
}
|
||||
Reference in New Issue
Block a user