Read podcast list from saved file and merge new entries. Add daysAgo() selector.
Remember length of podcast episodes so we know if we need to download it again.
This commit is contained in:
parent
08ef8abf35
commit
95e73fd219
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,2 +1,3 @@
|
||||||
rssd.conf
|
rssd.conf
|
||||||
output.conf
|
output.conf
|
||||||
|
*.mp3
|
||||||
|
|
132
main.go
132
main.go
|
@ -3,6 +3,7 @@ package main
|
||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/BurntSushi/toml"
|
"github.com/BurntSushi/toml"
|
||||||
|
@ -15,10 +16,11 @@ type Config struct {
|
||||||
|
|
||||||
type Item struct {
|
type Item struct {
|
||||||
Title, Description, Url, Filename string
|
Title, Description, Url, Filename string
|
||||||
|
Length int
|
||||||
}
|
}
|
||||||
|
|
||||||
type Podcast struct {
|
type Podcast struct {
|
||||||
Title, Description string
|
Title, Description, Url string
|
||||||
Items []Item
|
Items []Item
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,32 +28,79 @@ type pcList struct {
|
||||||
Podcasts []Podcast
|
Podcasts []Podcast
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newpcList(confs ...string) (ret *pcList) {
|
||||||
|
ret = &pcList{}
|
||||||
|
ret.Podcasts = make([]Podcast,0)
|
||||||
|
if len(confs) > 0 {
|
||||||
|
if _, err := toml.DecodeFile("output.conf", &ret); err != nil {
|
||||||
|
log.Print("Error reading podcast list:",err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *pcList) Find(x *Podcast) (int, bool) {
|
||||||
|
for i,y := range p.Podcasts {
|
||||||
|
if y.Title == x.Title {
|
||||||
|
return i, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
func (p *pcList) Add(x *Podcast) {
|
func (p *pcList) Add(x *Podcast) {
|
||||||
(*p).Podcasts = append((*p).Podcasts,*x)
|
if x == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if i,ok := p.Find(x); ok == true {
|
||||||
|
log.Print(" Existing podcast")
|
||||||
|
p.Podcasts[i].Merge(x)
|
||||||
|
} else {
|
||||||
|
log.Print(" New podcast")
|
||||||
|
p.Podcasts = append((*p).Podcasts,*x)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Db struct {
|
func (p *Podcast) Merge(x *Podcast) {
|
||||||
Podcasts []Podcast
|
for _,item := range x.Items {
|
||||||
|
if !p.Has(item) {
|
||||||
|
log.Print(" Appending '",item.Title,"'")
|
||||||
|
p.Items = append(p.Items,item)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Selector func(*gofeed.Item) bool
|
func (p *Podcast) Has(i Item) bool {
|
||||||
|
for _,x := range p.Items {
|
||||||
func Any(ss []Selector, i *gofeed.Item) bool {
|
if x.Title == i.Title {
|
||||||
for _, s := range ss {
|
|
||||||
if s(i) {
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func All(ss []Selector, i *gofeed.Item) bool {
|
type Selector func(*gofeed.Item) bool
|
||||||
for _, s := range ss {
|
|
||||||
if !s(i) {
|
func AllSelectors(ss ...Selector) Selector {
|
||||||
return false
|
return func(i *gofeed.Item) bool {
|
||||||
|
for _, s := range ss {
|
||||||
|
if !s(i) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func AnySelector(ss ...Selector) Selector {
|
||||||
|
return func(i *gofeed.Item) bool {
|
||||||
|
for _, s := range ss {
|
||||||
|
if s(i) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newerThan(t time.Time) Selector {
|
func newerThan(t time.Time) Selector {
|
||||||
|
@ -63,20 +112,46 @@ func newerThan(t time.Time) Selector {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func readFeed(url string,ss ...Selector) *Podcast {
|
func daysAgo(x int) Selector {
|
||||||
|
d := time.Now()
|
||||||
|
return newerThan(time.Date(d.Year(),d.Month(),d.Day()-x,0,0,0,0,time.Local))
|
||||||
|
}
|
||||||
|
|
||||||
|
func toPodcast(sel Selector, url string, feed *gofeed.Feed) (ret *Podcast) {
|
||||||
|
ret = &Podcast{
|
||||||
|
Title: feed.Title,
|
||||||
|
Description: feed.Description,
|
||||||
|
Url: url,
|
||||||
|
Items: []Item{},
|
||||||
|
}
|
||||||
|
for _, i := range feed.Items {
|
||||||
|
if sel(i) {
|
||||||
|
it := Item{
|
||||||
|
Title: i.Title,
|
||||||
|
Description: i.Description,
|
||||||
|
}
|
||||||
|
for _, n := range i.Enclosures {
|
||||||
|
if n.Type == "audio/mpeg" {
|
||||||
|
it.Url = n.URL
|
||||||
|
if l, err := strconv.Atoi(n.Length); err == nil {
|
||||||
|
it.Length = l
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret.Items = append(ret.Items,it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func readFeed(url string,sel Selector) *Podcast {
|
||||||
fp := gofeed.NewParser()
|
fp := gofeed.NewParser()
|
||||||
feed, err := fp.ParseURL(url)
|
feed, err := fp.ParseURL(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Print(err)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
pc := Podcast{ feed.Title, feed.Description, []Item{} }
|
return toPodcast(sel,url,feed)
|
||||||
for _, i := range feed.Items {
|
|
||||||
if All(ss,i) {
|
|
||||||
it := Item{ Title: i.Title, Description: i.Description }
|
|
||||||
pc.Items = append(pc.Items,it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return &pc
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@ -86,15 +161,12 @@ func main() {
|
||||||
if _, err := toml.DecodeFile("rssd.conf", &conf); err != nil {
|
if _, err := toml.DecodeFile("rssd.conf", &conf); err != nil {
|
||||||
log.Fatal("Error reading config file:",err)
|
log.Fatal("Error reading config file:",err)
|
||||||
}
|
}
|
||||||
pl := &pcList{}
|
pl := newpcList("output.conf")
|
||||||
pl.Podcasts = make([]Podcast,0)
|
|
||||||
|
|
||||||
d := time.Now()
|
|
||||||
lastMonth := newerThan(time.Date(d.Year(),d.Month()-1,d.Day(),0,0,0,0,time.Local))
|
|
||||||
|
|
||||||
|
sel := daysAgo(60)
|
||||||
for _,url := range conf.Urls {
|
for _,url := range conf.Urls {
|
||||||
log.Print(" -> ",url)
|
log.Print(" -> ",url)
|
||||||
pl.Add(readFeed(url,lastMonth))
|
pl.Add(readFeed(url,sel))
|
||||||
}
|
}
|
||||||
of,err := os.Create("output.conf")
|
of,err := os.Create("output.conf")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user