ref: 551c536f36519048eb4aa87242ef640ad13d08f1
dir: /main.go/
// RSS feed reader that outputs plain text, werc/apps/barf, or werc/apps/blagh format. package main import ( "bufio" "crypto/tls" "flag" "fmt" "github.com/SlyMarbo/rss" "html" "io/ioutil" "log" "net/http" "os" "sort" "strconv" "strings" "time" ) var ( debug = flag.Bool("d", false, "print debug msgs to stderr") format = flag.String("f", "", "output format") root = flag.String("r", "", "output root") tag = flag.String("t", "", "feed tag (barf only)") url = flag.String("u", "", "feed url") ) func usage() { os.Stderr.WriteString("usage: rrss [-f barf|blagh] [-r root] [-t tag] [-u url]\n") flag.PrintDefaults() os.Exit(2) } func check(err error) { if err != nil { log.Fatal(err) } } func fetchfeed(url string) (resp *http.Response, err error) { defaultTransport := http.DefaultTransport.(*http.Transport) // Create new Transport that ignores self-signed SSL customTransport := &http.Transport{ Proxy: defaultTransport.Proxy, DialContext: defaultTransport.DialContext, MaxIdleConns: defaultTransport.MaxIdleConns, IdleConnTimeout: defaultTransport.IdleConnTimeout, ExpectContinueTimeout: defaultTransport.ExpectContinueTimeout, TLSHandshakeTimeout: defaultTransport.TLSHandshakeTimeout, TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, } client := &http.Client{Transport: customTransport} req, err := http.NewRequest("GET", url, nil) if err != nil { return nil, err } req.Header.Add("User-Agent", "Mozilla/5.0 (compatible; hjdicks)") return client.Do(req) } func isold(date time.Time, link string, path string) bool { file, err := os.OpenFile(path, os.O_CREATE|os.O_RDONLY, 0775) if err != nil { return true } defer file.Close() s := fmt.Sprintf("%d_%s", date.Unix(), link) scanner := bufio.NewScanner(file) for scanner.Scan() { if strings.Contains(s, scanner.Text()) { return true } } return false } func makeold(date time.Time, link string, path string) (int, error) { f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0775) defer f.Close() check(err) if link == "" { link = "empty" } s := fmt.Sprintf("%d_%s", date.Unix(), link) return f.WriteString(s + "\n") } // https://code.9front.org/hg/barf func barf(url string) { feed, err := rss.FetchByFunc(fetchfeed, url) if *debug { log.Printf("Tried fetching feed '%s' => err: %v\n", url, err) } check(err) for _, i := range feed.Items { d := "src" links := "links" if *root != "" { d = *root + "/" + d links = *root + "/" + links } if isold(i.Date, i.Link, links) { continue } err = os.MkdirAll(d, 0775) check(err) f, err := os.Open(d) defer f.Close() check(err) dn, err := f.Readdirnames(0) check(err) var di []int for _, j := range dn { k, _ := strconv.Atoi(j) di = append(di, k) } sort.Ints(di) n := 1 if di != nil { n = di[len(di)-1] + 1 } d = fmt.Sprintf("%s/%d", d, n) if *debug == true { fmt.Printf("%s len(di): %d n: %d d: %s\n", i.Link, len(di), n, d) } err = os.MkdirAll(d, 0775) check(err) err = ioutil.WriteFile(d+"/title", []byte(i.Title+"\n"), 0775) check(err) err = ioutil.WriteFile(d+"/link", []byte(i.Link+"\n"), 0775) check(err) err = ioutil.WriteFile(d+"/date", []byte(i.Date.String()+"\n"), 0775) check(err) err = ioutil.WriteFile(d+"/body", []byte(conorsum(i)+"\n"), 0775) check(err) if *tag != "" { err = os.MkdirAll(d+"/tags", 0775) check(err) for _, j := range strings.Split(*tag, " ") { f, err := os.Create(d + "/tags/" + j) f.Close() check(err) } } _, err = makeold(i.Date, i.Link, links) check(err) } } // http://werc.cat-v.org/apps/blagh func blagh(url string) { feed, err := rss.FetchByFunc(fetchfeed, url) check(err) for _, i := range feed.Items { d := fmt.Sprintf("%d/%02d/%02d", i.Date.Year(), i.Date.Month(), i.Date.Day()) links := "links" if *root != "" { d = *root + "/" + d links = *root + "/" + links } if isold(i.Date, i.Link, links) { continue } f, _ := os.Open(d) // directory will usually not exist yet defer f.Close() n, _ := f.Readdirnames(0) d = fmt.Sprintf("%s/%d", d, len(n)) err = os.MkdirAll(d, 0775) check(err) err = ioutil.WriteFile( d+"/index.md", []byte(i.Title+"\n===\n\n"+conorsum(i)+"\n"), 0775, ) check(err) _, err = makeold(i.Date, i.Link, links) check(err) } } func stdout(url string) { feed, err := rss.FetchByFunc(fetchfeed, url) if *debug { log.Printf("Tried fetching feed '%s' => err: %v\n", url, err) } check(err) for _, i := range feed.Items { fmt.Printf("title: %s\nlink: %s\ndate: %s\n%s\n\n", i.Title, i.Link, i.Date, conorsum(i)) } } func conorsum(i *rss.Item) string { var s string switch { case len(i.Content) > 0: s = i.Content case len(i.Summary) > 0: s = i.Summary default: return "" } return html.UnescapeString(s) } func main() { flag.Usage = usage flag.Parse() if *url == "" { usage() } switch *format { case "barf": barf(*url) case "blagh": blagh(*url) case "": stdout(*url) default: usage() } }