akl/akl.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()
}
}
}