Sfoglia il codice sorgente

initial feed reader

it reads feeds. who would have thought. it also follows redirects and
searches for feed urls already. seems as if it could be an alternative
with (quite) a bit more work on it.
Lucas Stadler 11 anni fa
parent
commit
7aa7fced57
1 ha cambiato i file con 114 aggiunte e 0 eliminazioni
  1. 114 0
      go/feeds.go

+ 114 - 0
go/feeds.go

@ -0,0 +1,114 @@
1
package main
2
3
import (
4
	"bufio"
5
	"errors"
6
	"fmt"
7
	"net/http"
8
	"net/url"
9
	"os"
10
	"strings"
11
12
	"code.google.com/p/cascadia"
13
	"code.google.com/p/go.net/html"
14
	feed "github.com/SlyMarbo/rss"
15
)
16
17
func main() {
18
	feeds, err := ReadConfig("config.txt")
19
	if err != nil {
20
		fmt.Println(err)
21
		os.Exit(1)
22
	}
23
24
	fmt.Printf("fetching %d feeds...\n", len(*feeds))
25
	for _, fn := range *feeds {
26
		fmt.Printf("fetching %s\n", fn)
27
		fu, err := GetFeedUrl(fn)
28
		if err != nil {
29
			fmt.Println(err)
30
			continue
31
		}
32
		fn = fu
33
34
		f, err :=  feed.Fetch(fn)
35
		if err != nil {
36
			fmt.Println(err)
37
			continue
38
		}
39
40
		fmt.Printf("%s: %d entries\n", fn, len(f.Items))
41
		//for _, item := range f.Items {
42
		//	fmt.Println(item.Title)
43
		//}
44
	}
45
}
46
47
func GetFeedUrl(u string) (string, error) {
48
	resp, err := http.Get(u)
49
	if err != nil {
50
		return "", err
51
	}
52
53
	if strings.Contains(resp.Header.Get("Content-Type"), "xml") {
54
		return u, nil
55
	}
56
57
	tree, err := html.Parse(resp.Body)
58
	if err != nil {
59
		return "", err
60
	}
61
62
	sel := cascadia.MustCompile("link[rel=alternate][type*=xml]")
63
	alt := sel.MatchFirst(tree)
64
	if alt == nil {
65
		return "", errors.New("no feed link found")
66
	}
67
68
	altUrl, found := FindAttr("href", alt.Attr)
69
	if !found {
70
		return "", errors.New("missing link in alternate")
71
	}
72
73
	return ToAbsolute(resp.Request.URL, altUrl.Val), nil
74
}
75
76
func FindAttr(name string, attributes []html.Attribute) (*html.Attribute, bool) {
77
	for _, attr := range attributes {
78
		if attr.Key == name {
79
			return &attr, true
80
		}
81
	}
82
	return nil, false
83
}
84
85
func ToAbsolute(base *url.URL, rawUrl string) string {
86
	url, err := url.Parse(rawUrl)
87
	if err != nil {
88
		return rawUrl
89
	}
90
	return base.ResolveReference(url).String()
91
}
92
93
func ReadConfig(fileName string) (*[]string, error) {
94
	f, err := os.Open(fileName)
95
	if err != nil {
96
		return nil, err
97
	}
98
99
	lines := make([]string, 0)
100
101
	r := bufio.NewReader(f)
102
103
	line, err := r.ReadString('\n')
104
	for err == nil {
105
		line = strings.TrimSpace(line)
106
		if line != "" && line[0] != '#' && line[0] != ';' {
107
			lines = append(lines, line)
108
		}
109
110
		line, err = r.ReadString('\n')
111
	}
112
113
	return &lines, nil
114
}