From 6b09ccd9d885a3230a197f7d42fa1fcc760a25ef Mon Sep 17 00:00:00 2001 From: davy wybiral Date: Thu, 8 Aug 2019 06:04:39 -0500 Subject: [PATCH] cache rss feed (#19) --- pkg/app/app.go | 65 ++------------------------------------ pkg/app/feed.go | 77 ++++++++++++++++++++++++++++++++++++++++++++++ pkg/app/watcher.go | 4 +++ 3 files changed, 84 insertions(+), 62 deletions(-) create mode 100644 pkg/app/feed.go diff --git a/pkg/app/app.go b/pkg/app/app.go index 1f6b769..0efd22a 100644 --- a/pkg/app/app.go +++ b/pkg/app/app.go @@ -8,14 +8,9 @@ import ( "log" "net" "net/http" - "net/url" - "os" "path" - "strconv" - "time" "github.com/fsnotify/fsnotify" - "github.com/gorilla/feeds" "github.com/gorilla/mux" "github.com/wybiral/tube/pkg/media" "github.com/wybiral/tube/pkg/onionkey" @@ -27,6 +22,7 @@ type App struct { Library *media.Library Watcher *fsnotify.Watcher Templates *template.Template + Feed []byte Tor *tor Listener net.Listener Router *mux.Router @@ -123,6 +119,7 @@ func (a *App) Run() error { } a.Watcher.Add(p.Path) } + buildFeed(a) go startWatcher(a) return http.Serve(a.Listener, a.Router) } @@ -219,63 +216,7 @@ func (a *App) thumbHandler(w http.ResponseWriter, r *http.Request) { // HTTP handler for /feed.xml func (a *App) rssHandler(w http.ResponseWriter, r *http.Request) { - cfg := a.Config.Feed - now := time.Now() - f := &feeds.Feed{ - Title: cfg.Title, - Link: &feeds.Link{Href: cfg.Link}, - Description: cfg.Description, - Author: &feeds.Author{ - Name: cfg.Author.Name, - Email: cfg.Author.Email, - }, - Created: now, - Copyright: cfg.Copyright, - } - var externalURL string - if len(cfg.ExternalURL) > 0 { - externalURL = cfg.ExternalURL - } else if a.Tor != nil { - onion, err := a.Tor.OnionKey.Onion() - if err != nil { - return - } - externalURL = fmt.Sprintf("http://%s.onion", onion.ServiceID) - } else { - hostname, err := os.Hostname() - if err != nil { - host := a.Config.Server.Host - port := a.Config.Server.Port - externalURL = fmt.Sprintf("http://%s:%d", host, port) - } else { - externalURL = fmt.Sprintf("http://%s", hostname) - } - } - for _, v := range a.Library.Playlist() { - u, err := url.Parse(externalURL) - if err != nil { - return - } - u.Path = path.Join(u.Path, "v", v.ID) - id := u.String() - f.Items = append(f.Items, &feeds.Item{ - Id: id, - Title: v.Title, - Link: &feeds.Link{Href: id}, - Description: v.Description, - Enclosure: &feeds.Enclosure{ - Url: id + ".mp4", - Length: strconv.FormatInt(v.Size, 10), - Type: "video/mp4", - }, - Author: &feeds.Author{ - Name: cfg.Author.Name, - Email: cfg.Author.Email, - }, - Created: v.Timestamp, - }) - } w.Header().Set("Cache-Control", "public, max-age=7776000") w.Header().Set("Content-Type", "text/xml") - f.WriteRss(w) + w.Write(a.Feed) } diff --git a/pkg/app/feed.go b/pkg/app/feed.go new file mode 100644 index 0000000..e4c1ce2 --- /dev/null +++ b/pkg/app/feed.go @@ -0,0 +1,77 @@ +package app + +import ( + "fmt" + "net/url" + "os" + "path" + "strconv" + "time" + + "github.com/wybiral/feeds" +) + +// buildFeed creates RSS feed attribute for App based on Library contents. +func buildFeed(a *App) { + cfg := a.Config.Feed + now := time.Now() + f := &feeds.Feed{ + Title: cfg.Title, + Link: &feeds.Link{Href: cfg.Link}, + Description: cfg.Description, + Author: &feeds.Author{ + Name: cfg.Author.Name, + Email: cfg.Author.Email, + }, + Created: now, + Copyright: cfg.Copyright, + } + var externalURL string + if len(cfg.ExternalURL) > 0 { + externalURL = cfg.ExternalURL + } else if a.Tor != nil { + onion, err := a.Tor.OnionKey.Onion() + if err != nil { + return + } + externalURL = fmt.Sprintf("http://%s.onion", onion.ServiceID) + } else { + hostname, err := os.Hostname() + if err != nil { + host := a.Config.Server.Host + port := a.Config.Server.Port + externalURL = fmt.Sprintf("http://%s:%d", host, port) + } else { + externalURL = fmt.Sprintf("http://%s", hostname) + } + } + for _, v := range a.Library.Playlist() { + u, err := url.Parse(externalURL) + if err != nil { + return + } + u.Path = path.Join(u.Path, "v", v.ID) + id := u.String() + f.Items = append(f.Items, &feeds.Item{ + Id: id, + Title: v.Title, + Link: &feeds.Link{Href: id}, + Description: v.Description, + Enclosure: &feeds.Enclosure{ + Url: id + ".mp4", + Length: strconv.FormatInt(v.Size, 10), + Type: "video/mp4", + }, + Author: &feeds.Author{ + Name: cfg.Author.Name, + Email: cfg.Author.Email, + }, + Created: v.Timestamp, + }) + } + feed, err := f.ToRss() + if err != nil { + return + } + a.Feed = []byte(feed) +} diff --git a/pkg/app/watcher.go b/pkg/app/watcher.go index 2d7a761..624e470 100644 --- a/pkg/app/watcher.go +++ b/pkg/app/watcher.go @@ -36,6 +36,7 @@ func startWatcher(a *App) { // reset timer timer.Reset(debounceTimeout) case <-timer.C: + eventCount := len(removeEvents) + len(addEvents) // handle remove events first if len(removeEvents) > 0 { for p := range removeEvents { @@ -52,6 +53,9 @@ func startWatcher(a *App) { // clear map addEvents = make(map[string]struct{}) } + if eventCount > 0 { + buildFeed(a) + } // reset timer timer.Reset(debounceTimeout) }