package main import ( "context" "encoding/json" "flag" "fmt" "io/ioutil" "log" "net/http" "time" "github.com/mmcdole/gofeed" ) // layoutUS is a human friendly date format. const layoutUS = "January 2, 2006" // feed is an RSS feed. type feed struct { Slug string `json:"slug"` // Slug for the RSS feed Title string `json:"title"` // Title of the RSS feed Url string `json:"url"` // URL of the RSS feed } // item is a single RSS feed item. type item struct { link string published *time.Time title string } // getFeeds retrieves all feeds from the FvA website API. func getFeeds() ([]feed, error) { var feeds []feed url := "https://test.fva.wtf/api/anarchokrant-list" resp, err := http.Get(url) if err != nil { return feeds, err } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { return feeds, err } if err := json.Unmarshal(body, &feeds); err != nil { return feeds, err } return feeds, nil } // parseRSSFeed parses a RSS feed. func parseRSSFeed(url string) (gofeed.Feed, error) { ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) defer cancel() feedParser := gofeed.NewParser() feed, err := feedParser.ParseURLWithContext(url, ctx) if err != nil { return gofeed.Feed{}, fmt.Errorf("parseRSSFeed: unable to parse %s: %w", url, err) } return *feed, nil } func linksFromFeed(day int, feed string, ch chan<- []item) { var items []item parsed, err := parseRSSFeed(feed) if err != nil { log.Printf("failed to parse feed: %s\n\n", feed) ch <- items } now := time.Now() lastMonth := time.Date(now.Year(), now.Month()-1, day, 0, 0, 0, 0, time.UTC) for _, i := range parsed.Items { if i.PublishedParsed.After(lastMonth) { items = append(items, item{ link: i.Link, published: i.PublishedParsed, title: i.Title, }) } } ch <- items } // show outputs an item. func (i item) show() { fmt.Printf("%s\n%s\n%s\n\n", i.published.Format(layoutUS), i.title, i.link) } func main() { var dayFlag int flag.IntVar(&dayFlag, "d", 28, "day of last month") flag.Parse() feeds, err := getFeeds() if err != nil { log.Fatal(err) } ch := make(chan []item, len(feeds)) for _, feed := range feeds { go linksFromFeed(dayFlag, feed.Url, ch) } for range feeds { items := <-ch for _, item := range items { item.show() } } }