diff options
Diffstat (limited to 'reader/feed/parser.go')
-rw-r--r-- | reader/feed/parser.go | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/reader/feed/parser.go b/reader/feed/parser.go new file mode 100644 index 00000000..8df6b46d --- /dev/null +++ b/reader/feed/parser.go @@ -0,0 +1,82 @@ +// Copyright 2017 Frédéric Guillot. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +package feed + +import ( + "bytes" + "encoding/xml" + "errors" + "github.com/miniflux/miniflux2/helper" + "github.com/miniflux/miniflux2/model" + "github.com/miniflux/miniflux2/reader/feed/atom" + "github.com/miniflux/miniflux2/reader/feed/json" + "github.com/miniflux/miniflux2/reader/feed/rss" + "io" + "strings" + "time" + + "golang.org/x/net/html/charset" +) + +const ( + FormatRss = "rss" + FormatAtom = "atom" + FormatJson = "json" + FormatUnknown = "unknown" +) + +func DetectFeedFormat(data io.Reader) string { + defer helper.ExecutionTime(time.Now(), "[Feed:DetectFeedFormat]") + + var buffer bytes.Buffer + tee := io.TeeReader(data, &buffer) + + decoder := xml.NewDecoder(tee) + decoder.CharsetReader = charset.NewReaderLabel + + for { + token, _ := decoder.Token() + if token == nil { + break + } + + if element, ok := token.(xml.StartElement); ok { + switch element.Name.Local { + case "rss": + return FormatRss + case "feed": + return FormatAtom + } + } + } + + if strings.HasPrefix(strings.TrimSpace(buffer.String()), "{") { + return FormatJson + } + + return FormatUnknown +} + +func parseFeed(data io.Reader) (*model.Feed, error) { + defer helper.ExecutionTime(time.Now(), "[Feed:ParseFeed]") + + var buffer bytes.Buffer + io.Copy(&buffer, data) + + reader := bytes.NewReader(buffer.Bytes()) + format := DetectFeedFormat(reader) + reader.Seek(0, io.SeekStart) + + switch format { + case FormatAtom: + return atom.Parse(reader) + case FormatRss: + return rss.Parse(reader) + case FormatJson: + return json.Parse(reader) + default: + return nil, errors.New("Unsupported feed format") + } +} |