5 files changed,
101 insertions(+),
0 deletions(-)
Author:
Oleksandr Smirnov
olexsmir@gmail.com
Committed at:
2026-01-01 00:53:44 +0200
Change ID:
runlpqxpmopzxkzpnwwrrqoykrnqquyv
jump to
| A | .gitignore |
| A | config.example.yaml |
| A | go.mod |
| A | go.sum |
| A | main.go |
A
config.example.yaml
@@ -0,0 +1,5 @@
+api_key: "<your_tmdb_api_key>" +port: 8080 +shows: + - "tt0944947" # Game of Thrones IMDB ID + - "1399" # The Office (US) TMDB ID
A
go.mod
@@ -0,0 +1,8 @@
+module olexsmir.xyz/moviefeed + +go 1.25.3 + +require ( + github.com/gorilla/feeds v1.2.0 + gopkg.in/yaml.v2 v2.4.0 +)
A
go.sum
@@ -0,0 +1,12 @@
+github.com/gorilla/feeds v1.2.0 h1:O6pBiXJ5JHhPvqy53NsjKOThq+dNFm8+DFrxBEdzSCc= +github.com/gorilla/feeds v1.2.0/go.mod h1:WMib8uJP3BbY+X8Szd1rA5Pzhdfh+HCCAYT2z7Fza6Y= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
A
main.go
@@ -0,0 +1,74 @@
+package main + +import ( + "flag" + "fmt" + "log/slog" + "net/http" + "os" + "time" + + "github.com/gorilla/feeds" +) + +func main() { + configFile := flag.String("config", "config.yaml", "Path to config file") + flag.Parse() + + config, err := loadConfig(*configFile) + if err != nil { + slog.Error("failed to load config", "err", err) + os.Exit(1) + } + + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + episodes, err := fetchNewEpisodes(config) + if err != nil { + slog.Error("failed to fetch episodes", "err", err) + os.Exit(1) + } + + rssFeed := generateRSS(episodes) + w.Header().Set("Content-Type", "application/rss+xml") + w.Write([]byte(rssFeed)) + }) + + slog.Info("server starting", "port", config.Port) + http.ListenAndServe(":"+config.Port, nil) +} + +func generateRSS(episodes []TMDBEpisode) string { + feed := &feeds.Feed{ + Title: "moviefeed", + Link: &feeds.Link{Href: "http://localhost"}, + Description: "Latest episodes from followed shows", + Created: time.Now(), + } + + for _, ep := range episodes { + airDate, _ := time.Parse("2006-01-02", ep.AirDate) + feed.Items = append(feed.Items, &feeds.Item{ + Id: fmt.Sprintf("%s-%d-%d", ep.ShowID, ep.SeasonNumber, ep.EpisodeNumber), + Title: fmt.Sprintf( + "%s S%dE%d: %s", + ep.ShowName, + ep.SeasonNumber, + ep.EpisodeNumber, + ep.Name, + ), + Link: &feeds.Link{ + Href: fmt.Sprintf("https://www.themoviedb.org/tv/episode/%d", ep.ID), + }, + Description: ep.Overview, + Created: airDate, + }) + } + + rss, err := feed.ToRss() + if err != nil { + slog.Error("error generating RSS", "err", err) + return "" + } + + return rss +}