reaper/reaper.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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package reaper import ( "fmt" "sort" "sync" "time" "git.j3s.sh/vore/sqlite" "github.com/SlyMarbo/rss" ) type Reaper struct { // internal list of all rss feeds where the map // key represents the primary id of the key in the db feeds []rss.Feed // this mutex is used for locking writes to Feeds mu sync.Mutex db *sqlite.DB } func Summon(db *sqlite.DB) *Reaper { var feeds []rss.Feed reaper := Reaper{ feeds: feeds, mu: sync.Mutex{}, db: db, } return &reaper } func (r *Reaper) Start() { fmt.Println("reaper: starting") // Make initial url list urls := r.db.GetAllFeedURLs() for _, url := range urls { // Setting UpdateURL lets us defer the actual fetching feed := rss.Feed{ UpdateURL: url, } r.feeds = append(r.feeds, feed) } for { r.UpdateAll() time.Sleep(2 * time.Hour) } } // Add fetches the given feed url and appends it to r.Feeds // If the given URL is already in reaper.Feeds, Add will do nothing func (r *Reaper) Add(url string) error { for i := range r.feeds { if r.feeds[i].UpdateURL == url { return nil } } feed, err := rss.Fetch(url) if err != nil { return err } r.mu.Lock() r.feeds = append(r.feeds, *feed) r.mu.Unlock() return nil } // UpdateAll fetches every feed & attempts updating them func (r *Reaper) UpdateAll() { start := time.Now() fmt.Printf("reaper: fetching %d feeds\n", len(r.feeds)) for i := range r.feeds { err := r.feeds[i].Update() if err != nil { fmt.Println(err) // TODO: write err to db? } } fmt.Printf("reaper: fetched %d feeds in %s\n", len(r.feeds), time.Since(start)) } // GetUserFeeds returns a list of feeds func (r *Reaper) GetUserFeeds(username string) []rss.Feed { urls := r.db.GetUserFeedURLs(username) var result []rss.Feed for i := range r.feeds { for _, url := range urls { if r.feeds[i].UpdateURL == url { result = append(result, r.feeds[i]) } } } r.SortFeeds(result) return result } func (r *Reaper) SortFeeds(f []rss.Feed) { sort.Slice(f, func(i, j int) bool { return f[i].Title < f[j].Title }) } func (r *Reaper) SortFeedItems(f []rss.Feed) []rss.Item { var posts []rss.Item for _, f := range f { for _, i := range f.Items { posts = append(posts, *i) } } // magick slice sorter by date sort.Slice(posts, func(i, j int) bool { return posts[i].Date.After(posts[j].Date) }) return posts }