1package db
2
3import (
4 "sort"
5 "time"
6)
7
8type TimelineEvent struct {
9 *Repo
10 *Follow
11 *Star
12
13 EventAt time.Time
14
15 // optional: populate only if Repo is a fork
16 Source *Repo
17}
18
19// TODO: this gathers heterogenous events from different sources and aggregates
20// them in code; if we did this entirely in sql, we could order and limit and paginate easily
21func MakeTimeline(e Execer) ([]TimelineEvent, error) {
22 var events []TimelineEvent
23 limit := 50
24
25 repos, err := GetAllRepos(e, limit)
26 if err != nil {
27 return nil, err
28 }
29
30 follows, err := GetAllFollows(e, limit)
31 if err != nil {
32 return nil, err
33 }
34
35 stars, err := GetAllStars(e, limit)
36 if err != nil {
37 return nil, err
38 }
39
40 for _, repo := range repos {
41 if repo.Source != "" {
42 sourceRepo, err := GetRepoByAtUri(e, repo.Source)
43 if err != nil {
44 return nil, err
45 }
46
47 events = append(events, TimelineEvent{
48 Repo: &repo,
49 EventAt: repo.Created,
50 Source: sourceRepo,
51 })
52 }
53
54 events = append(events, TimelineEvent{
55 Repo: &repo,
56 EventAt: repo.Created,
57 })
58 }
59
60 for _, follow := range follows {
61 events = append(events, TimelineEvent{
62 Follow: &follow,
63 EventAt: follow.FollowedAt,
64 })
65 }
66
67 for _, star := range stars {
68 events = append(events, TimelineEvent{
69 Star: &star,
70 EventAt: star.Created,
71 })
72 }
73
74 sort.Slice(events, func(i, j int) bool {
75 return events[i].EventAt.After(events[j].EventAt)
76 })
77
78 // Limit the slice to 100 events
79 if len(events) > limit {
80 events = events[:limit]
81 }
82
83 return events, nil
84}