main
Raw Download raw file
 1package lobsters
 2
 3import (
 4	"context"
 5	"errors"
 6	"fmt"
 7	"net/url"
 8
 9	"mill/internal/content"
10
11	"github.com/mmcdole/gofeed"
12)
13
14var (
15	ErrMissingLink = errors.New("link fileld unset")
16)
17
18type Source struct {
19	name string
20	url  *url.URL
21	feed *gofeed.Feed
22}
23
24func New(name, feedURL string) (*Source, error) {
25	u, err := url.Parse(feedURL)
26	if err != nil {
27		return nil, err
28	}
29
30	return &Source{
31		name: name,
32		url:  u,
33	}, nil
34}
35
36func (s *Source) Name() string {
37	return s.name
38}
39
40func (s *Source) Fetch(ctx context.Context) ([]*content.Observation, error) {
41	fp := gofeed.NewParser()
42	feed, err := fp.ParseURLWithContext(s.url.String(), ctx)
43	if err != nil {
44		err = fmt.Errorf("rss feed parsing: %w", err)
45		return nil, err
46	}
47	s.feed = feed
48
49	observations := make([]*content.Observation, len(s.feed.Items))
50	for i, item := range s.feed.Items {
51
52		if item.Link == "" {
53			return nil, ErrMissingLink
54		}
55
56		targetURL, err := url.Parse(item.Link)
57		if err != nil {
58			return nil, err
59		}
60
61		discussionURL, err := url.Parse(item.GUID)
62		if err != nil {
63			return nil, err
64		}
65
66		obs, err := content.NewObservation(
67			s.url,         // observation url
68			targetURL,     // target url
69			discussionURL, // discussion url
70			s.Name(),      // source name
71			item.Title,    // item title
72		)
73		if err != nil {
74			err = fmt.Errorf("creating new observation: %w", err)
75			return nil, err
76		}
77		observations[i] = obs
78	}
79	return observations, nil
80}