1package db
2
3import (
4 "log"
5 "time"
6
7 "github.com/bluesky-social/indigo/atproto/syntax"
8)
9
10type Star struct {
11 StarredByDid string
12 RepoAt syntax.ATURI
13 Repo *Repo
14 Created time.Time
15 Rkey string
16}
17
18func (star *Star) ResolveRepo(e Execer) error {
19 if star.Repo != nil {
20 return nil
21 }
22
23 repo, err := GetRepoByAtUri(e, star.RepoAt.String())
24 if err != nil {
25 return err
26 }
27
28 star.Repo = repo
29 return nil
30}
31
32func AddStar(e Execer, starredByDid string, repoAt syntax.ATURI, rkey string) error {
33 query := `insert or ignore into stars (starred_by_did, repo_at, rkey) values (?, ?, ?)`
34 _, err := e.Exec(query, starredByDid, repoAt, rkey)
35 return err
36}
37
38// Get a star record
39func GetStar(e Execer, starredByDid string, repoAt syntax.ATURI) (*Star, error) {
40 query := `
41 select starred_by_did, repo_at, created, rkey
42 from stars
43 where starred_by_did = ? and repo_at = ?`
44 row := e.QueryRow(query, starredByDid, repoAt)
45
46 var star Star
47 var created string
48 err := row.Scan(&star.StarredByDid, &star.RepoAt, &created, &star.Rkey)
49 if err != nil {
50 return nil, err
51 }
52
53 createdAtTime, err := time.Parse(time.RFC3339, created)
54 if err != nil {
55 log.Println("unable to determine followed at time")
56 star.Created = time.Now()
57 } else {
58 star.Created = createdAtTime
59 }
60
61 return &star, nil
62}
63
64// Remove a star
65func DeleteStar(e Execer, starredByDid string, repoAt syntax.ATURI) error {
66 _, err := e.Exec(`delete from stars where starred_by_did = ? and repo_at = ?`, starredByDid, repoAt)
67 return err
68}
69
70func GetStarCount(e Execer, repoAt syntax.ATURI) (int, error) {
71 stars := 0
72 err := e.QueryRow(
73 `select count(starred_by_did) from stars where repo_at = ?`, repoAt).Scan(&stars)
74 if err != nil {
75 return 0, err
76 }
77 return stars, nil
78}
79
80func GetStarStatus(e Execer, userDid string, repoAt syntax.ATURI) bool {
81 if _, err := GetStar(e, userDid, repoAt); err != nil {
82 return false
83 } else {
84 return true
85 }
86}
87
88func GetAllStars(e Execer, limit int) ([]Star, error) {
89 var stars []Star
90
91 rows, err := e.Query(`
92 select
93 s.starred_by_did,
94 s.repo_at,
95 s.rkey,
96 s.created,
97 r.did,
98 r.name,
99 r.knot,
100 r.rkey,
101 r.created,
102 r.at_uri
103 from stars s
104 join repos r on s.repo_at = r.at_uri
105 `)
106
107 if err != nil {
108 return nil, err
109 }
110 defer rows.Close()
111
112 for rows.Next() {
113 var star Star
114 var repo Repo
115 var starCreatedAt, repoCreatedAt string
116
117 if err := rows.Scan(
118 &star.StarredByDid,
119 &star.RepoAt,
120 &star.Rkey,
121 &starCreatedAt,
122 &repo.Did,
123 &repo.Name,
124 &repo.Knot,
125 &repo.Rkey,
126 &repoCreatedAt,
127 &repo.AtUri,
128 ); err != nil {
129 return nil, err
130 }
131
132 star.Created, err = time.Parse(time.RFC3339, starCreatedAt)
133 if err != nil {
134 star.Created = time.Now()
135 }
136 repo.Created, err = time.Parse(time.RFC3339, repoCreatedAt)
137 if err != nil {
138 repo.Created = time.Now()
139 }
140 star.Repo = &repo
141
142 stars = append(stars, star)
143 }
144
145 if err := rows.Err(); err != nil {
146 return nil, err
147 }
148
149 return stars, nil
150}