/
feeds.go
106 lines (85 loc) · 2.19 KB
/
feeds.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
package client
import (
"errors"
xpp "github.com/mmcdole/goxpp"
"golang.org/x/net/html/charset"
"io"
"log"
)
func extractFeedLinks(r io.Reader) (string, string, error) {
p := xpp.NewXMLPullParser(r, false, charset.NewReaderLabel)
var hubUrl, selfUrl string
feedTag := firstTag(p)
if feedTag != "rss" && feedTag != "feed" && feedTag != "rdf" {
return "", "", errors.New("unexpected feed type")
}
switch feedTag {
case "rdf":
fallthrough
case "rss":
skipUntil(p, "channel")
if err := p.Expect(xpp.StartTag, "channel"); err != nil {
return "", "", err
}
case "feed":
break
}
for {
event, err := p.NextTag()
if err != nil {
return "", "", err
}
log.Println(p.Name)
if event == xpp.StartTag {
if p.Name == "link" {
// Handle
switch p.Attribute("rel") {
case "self":
selfUrl = p.Attribute("href")
case "hub":
hubUrl = p.Attribute("href")
}
if selfUrl != "" && hubUrl != "" {
break
}
} else {
p.Skip()
}
} else if event == xpp.EndTag {
if p.Name == "channel" {
break
}
} else if event == xpp.EndDocument {
break
}
}
return selfUrl, hubUrl, nil
}
// skipUntil skips tags from the parser until we have the expected tag
func skipUntil(p *xpp.XMLPullParser, tagName string) {
for {
event, err := p.NextTag()
if err != nil || event == xpp.EndDocument {
break
}
if event == xpp.StartTag {
if p.Name == tagName {
return
}
p.Skip()
}
}
}
// firstTag gets the first start tag
func firstTag(p *xpp.XMLPullParser) string {
for {
event, err := p.NextTag()
if err != nil || event == xpp.EndDocument {
break
}
if event == xpp.StartTag {
return p.Name
}
}
return ""
}