mirror of
https://github.com/zoriya/vex.git
synced 2026-05-23 06:56:24 +00:00
94 lines
1.7 KiB
Go
94 lines
1.7 KiB
Go
package vex
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/mmcdole/gofeed"
|
|
)
|
|
|
|
type Reader struct {
|
|
feedReader *gofeed.Parser
|
|
client *http.Client
|
|
}
|
|
|
|
func NewRssReader(client *http.Client) Reader {
|
|
return Reader{
|
|
feedReader: gofeed.NewParser(),
|
|
client: client,
|
|
}
|
|
}
|
|
|
|
type GoFeed struct {
|
|
*gofeed.Feed
|
|
|
|
ETag string
|
|
LastModified time.Time
|
|
}
|
|
|
|
var gmt, _ = time.LoadLocation("GMT")
|
|
|
|
func (r *Reader) ReadFeed(url string, etag string, lastModified *time.Time) (*GoFeed, error) {
|
|
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
|
defer cancel()
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
req.Header.Set("User-Agent", "Gofeed/1.0")
|
|
|
|
if etag != "" {
|
|
req.Header.Set("If-None-Match", etag)
|
|
}
|
|
if lastModified != nil {
|
|
req.Header.Set("If-Modified-Since", lastModified.In(gmt).Format(time.RFC1123))
|
|
}
|
|
|
|
resp, err := r.client.Do(req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if resp != nil {
|
|
defer func() {
|
|
ce := resp.Body.Close()
|
|
if ce != nil {
|
|
err = ce
|
|
}
|
|
}()
|
|
}
|
|
|
|
if resp.StatusCode == http.StatusNotModified {
|
|
return nil, nil
|
|
}
|
|
|
|
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
|
return nil, gofeed.HTTPError{
|
|
StatusCode: resp.StatusCode,
|
|
Status: resp.Status,
|
|
}
|
|
}
|
|
|
|
feed := &GoFeed{}
|
|
|
|
feedBody, err := r.feedReader.Parse(resp.Body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
feed.Feed = feedBody
|
|
|
|
if eTag := resp.Header.Get("Etag"); eTag != "" {
|
|
feed.ETag = eTag
|
|
}
|
|
|
|
if lastModified := resp.Header.Get("Last-Modified"); lastModified != "" {
|
|
parsed, err := time.ParseInLocation(time.RFC1123, lastModified, time.UTC)
|
|
if err == nil {
|
|
feed.LastModified = parsed
|
|
}
|
|
}
|
|
|
|
return feed, nil
|
|
}
|