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