package main import ( "bytes" "io" "log" "net/http" "net/url" "strings" "text/template" "time" "github.com/SlyMarbo/rss" ) var ( conf *config ) type article struct { Title, URL, Summary string } func main() { log.Println("gof starting up...") conf = readConfig() var tpls = make(map[string]*template.Template) for _, a := range conf.Accounts { for _, f := range a.Feeds { tmpl, err := template.New(f.URL).Parse(f.Template) if err != nil { log.Fatalf("Failed to parse template [%s]. Error: %s", f.Template, err.Error()) } tpls[f.URL] = tmpl } } for _, account := range conf.Accounts { // Get feeds log.Println("Fetching feeds...") var feeds []*rss.Feed for _, source := range account.Feeds { feed, err := rss.Fetch(source.URL) if err != nil { log.Printf("Error fetching %s: %s", source.URL, err.Error()) continue } feeds = append(feeds, feed) log.Printf("Fetched %s", feed.Title) } if len(feeds) == 0 { log.Fatal("Expected at least one feed to successfully fetch.") } // Loop through feeds for _, feed := range feeds { // Get feed items if len(feed.Items) == 0 { log.Printf("Warning: feed %s has no items.", feed.Title) continue } items := feed.Items if len(items) > 1 { items = items[:1] } base, err := url.Parse(feed.UpdateURL) if err != nil { log.Fatal("failed parsing update URL of the feed") } feedLink, _ := url.Parse(feed.Link) if err != nil { log.Fatal("failed parsing canonical feed URL of the feed") } // Loop through items for _, item := range items { if item.Date.Before(conf.LastUpdated) { log.Println("No new items. Skipping.") continue } itemLink, err := url.Parse(item.Link) if err != nil { log.Fatal("failed parsing article URL of the feed item") } // Make sure data looks OK // TODO: remove before release log.Printf("Item Data:\n\tTimestamp: %s\n\tSite URL: %s\n\tFeed Title: %s\n\tItem Title: %s\n\tItem URL: %s\n", item.Date, base.ResolveReference(feedLink).String(), feed.Title, item.Title, base.ResolveReference(itemLink).String()) i := article{ Title: item.Title, URL: base.ResolveReference(itemLink).String(), } buf := new(bytes.Buffer) err = tpls[base.String()].Execute(buf, i) if err != nil { log.Fatalf("Error executing template [%s]. Error: %s", tpls[base.String()], err.Error()) } if err = postMessage(account, buf.String()); err != nil { log.Fatalf("Failed to post message \"%s\". Error: %s", buf.String(), err.Error()) } } } } // update timestamp in config conf.updateLastUpdated() // save config conf.Save() } func postMessage(account Account, message string) error { apiURL := account.InstanceURL + "/api/v1/statuses" data := url.Values{} data.Set("status", message) data.Set("visibility", "unlisted") var req *http.Request var body io.Reader body = strings.NewReader(data.Encode()) req, err := http.NewRequest("POST", apiURL, body) if err != nil { return err } // Set Headers req.Header.Set("Content-Type", "application/x-www-form-urlencoded") req.Header.Set("Authorization", "Bearer "+account.AccessToken) c := &http.Client{Timeout: time.Second * 10} resp, err := c.Do(req) if err != nil { return err } defer resp.Body.Close() log.Println("response Status: ", resp.Status) return nil }