123 lines
2.3 KiB
Go
123 lines
2.3 KiB
Go
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()
|
|
}
|
|
}
|
|
}
|