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 var sourceRepo *Repo
42 if repo.Source != "" {
43 sourceRepo, err = GetRepoByAtUri(e, repo.Source)
44 if err != nil {
45 return nil, err
46 }
47 }
48
49 events = append(events, TimelineEvent{
50 Repo: &repo,
51 EventAt: repo.Created,
52 Source: sourceRepo,
53 })
54 }
55
56 for _, follow := range follows {
57 events = append(events, TimelineEvent{
58 Follow: &follow,
59 EventAt: follow.FollowedAt,
60 })
61 }
62
63 for _, star := range stars {
64 events = append(events, TimelineEvent{
65 Star: &star,
66 EventAt: star.Created,
67 })
68 }
69
70 sort.Slice(events, func(i, j int) bool {
71 return events[i].EventAt.After(events[j].EventAt)
72 })
73
74 // Limit the slice to 100 events
75 if len(events) > limit {
76 events = events[:limit]
77 }
78
79 return events, nil
80}