forked from
tangled.org/core
fork
Configure Feed
Select the types of activity you want to include in your feed.
this repo has no description
fork
Configure Feed
Select the types of activity you want to include in your feed.
1package db
2
3import (
4 "database/sql"
5 "time"
6
7 "github.com/bluesky-social/indigo/atproto/syntax"
8)
9
10type Repo struct {
11 Did string
12 Name string
13 Knot string
14 Rkey string
15 Created time.Time
16 AtUri string
17 Description string
18
19 // optionally, populate this when querying for reverse mappings
20 RepoStats *RepoStats
21
22 // optional
23 Source string
24}
25
26func GetAllRepos(e Execer, limit int) ([]Repo, error) {
27 var repos []Repo
28
29 rows, err := e.Query(
30 `select did, name, knot, rkey, description, created, source
31 from repos
32 order by created desc
33 limit ?
34 `,
35 limit,
36 )
37 if err != nil {
38 return nil, err
39 }
40 defer rows.Close()
41
42 for rows.Next() {
43 var repo Repo
44 err := scanRepo(
45 rows, &repo.Did, &repo.Name, &repo.Knot, &repo.Rkey, &repo.Description, &repo.Created, &repo.Source,
46 )
47 if err != nil {
48 return nil, err
49 }
50 repos = append(repos, repo)
51 }
52
53 if err := rows.Err(); err != nil {
54 return nil, err
55 }
56
57 return repos, nil
58}
59
60func GetAllReposByDid(e Execer, did string) ([]Repo, error) {
61 var repos []Repo
62
63 rows, err := e.Query(
64 `select
65 r.did,
66 r.name,
67 r.knot,
68 r.rkey,
69 r.description,
70 r.created,
71 count(s.id) as star_count,
72 r.source
73 from
74 repos r
75 left join
76 stars s on r.at_uri = s.repo_at
77 where
78 r.did = ?
79 group by
80 r.at_uri
81 order by r.created desc`,
82 did)
83 if err != nil {
84 return nil, err
85 }
86 defer rows.Close()
87
88 for rows.Next() {
89 var repo Repo
90 var repoStats RepoStats
91 var createdAt string
92 var nullableDescription sql.NullString
93 var nullableSource sql.NullString
94
95 err := rows.Scan(&repo.Did, &repo.Name, &repo.Knot, &repo.Rkey, &nullableDescription, &createdAt, &repoStats.StarCount, &nullableSource)
96 if err != nil {
97 return nil, err
98 }
99
100 if nullableDescription.Valid {
101 repo.Description = nullableDescription.String
102 }
103
104 if nullableSource.Valid {
105 repo.Source = nullableSource.String
106 }
107
108 createdAtTime, err := time.Parse(time.RFC3339, createdAt)
109 if err != nil {
110 repo.Created = time.Now()
111 } else {
112 repo.Created = createdAtTime
113 }
114
115 repo.RepoStats = &repoStats
116
117 repos = append(repos, repo)
118 }
119
120 if err := rows.Err(); err != nil {
121 return nil, err
122 }
123
124 return repos, nil
125}
126
127func GetRepo(e Execer, did, name string) (*Repo, error) {
128 var repo Repo
129 var nullableDescription sql.NullString
130
131 row := e.QueryRow(`select did, name, knot, created, at_uri, description from repos where did = ? and name = ?`, did, name)
132
133 var createdAt string
134 if err := row.Scan(&repo.Did, &repo.Name, &repo.Knot, &createdAt, &repo.AtUri, &nullableDescription); err != nil {
135 return nil, err
136 }
137 createdAtTime, _ := time.Parse(time.RFC3339, createdAt)
138 repo.Created = createdAtTime
139
140 if nullableDescription.Valid {
141 repo.Description = nullableDescription.String
142 } else {
143 repo.Description = ""
144 }
145
146 return &repo, nil
147}
148
149func GetRepoByAtUri(e Execer, atUri string) (*Repo, error) {
150 var repo Repo
151 var nullableDescription sql.NullString
152
153 row := e.QueryRow(`select did, name, knot, created, at_uri, description from repos where at_uri = ?`, atUri)
154
155 var createdAt string
156 if err := row.Scan(&repo.Did, &repo.Name, &repo.Knot, &createdAt, &repo.AtUri, &nullableDescription); err != nil {
157 return nil, err
158 }
159 createdAtTime, _ := time.Parse(time.RFC3339, createdAt)
160 repo.Created = createdAtTime
161
162 if nullableDescription.Valid {
163 repo.Description = nullableDescription.String
164 } else {
165 repo.Description = ""
166 }
167
168 return &repo, nil
169}
170
171func AddRepo(e Execer, repo *Repo) error {
172 _, err := e.Exec(
173 `insert into repos
174 (did, name, knot, rkey, at_uri, description, source)
175 values (?, ?, ?, ?, ?, ?, ?)`,
176 repo.Did, repo.Name, repo.Knot, repo.Rkey, repo.AtUri, repo.Description, repo.Source,
177 )
178 return err
179}
180
181func RemoveRepo(e Execer, did, name string) error {
182 _, err := e.Exec(`delete from repos where did = ? and name = ?`, did, name)
183 return err
184}
185
186func GetRepoSource(e Execer, repoAt syntax.ATURI) (string, error) {
187 var nullableSource sql.NullString
188 err := e.QueryRow(`select source from repos where at_uri = ?`, repoAt).Scan(&nullableSource)
189 if err != nil {
190 return "", err
191 }
192 return nullableSource.String, nil
193}
194
195func GetForksByDid(e Execer, did string) ([]Repo, error) {
196 var repos []Repo
197
198 rows, err := e.Query(
199 `select did, name, knot, rkey, description, created, at_uri, source
200 from repos
201 where did = ? and source is not null and source != ''
202 order by created desc`,
203 did,
204 )
205 if err != nil {
206 return nil, err
207 }
208 defer rows.Close()
209
210 for rows.Next() {
211 var repo Repo
212 var createdAt string
213 var nullableDescription sql.NullString
214 var nullableSource sql.NullString
215
216 err := rows.Scan(&repo.Did, &repo.Name, &repo.Knot, &repo.Rkey, &nullableDescription, &createdAt, &repo.AtUri, &nullableSource)
217 if err != nil {
218 return nil, err
219 }
220
221 if nullableDescription.Valid {
222 repo.Description = nullableDescription.String
223 }
224
225 if nullableSource.Valid {
226 repo.Source = nullableSource.String
227 }
228
229 createdAtTime, err := time.Parse(time.RFC3339, createdAt)
230 if err != nil {
231 repo.Created = time.Now()
232 } else {
233 repo.Created = createdAtTime
234 }
235
236 repos = append(repos, repo)
237 }
238
239 if err := rows.Err(); err != nil {
240 return nil, err
241 }
242
243 return repos, nil
244}
245
246func GetForkByDid(e Execer, did string, name string) (*Repo, error) {
247 var repo Repo
248 var createdAt string
249 var nullableDescription sql.NullString
250 var nullableSource sql.NullString
251
252 row := e.QueryRow(
253 `select did, name, knot, rkey, description, created, at_uri, source
254 from repos
255 where did = ? and name = ? and source is not null and source != ''`,
256 did, name,
257 )
258
259 err := row.Scan(&repo.Did, &repo.Name, &repo.Knot, &repo.Rkey, &nullableDescription, &createdAt, &repo.AtUri, &nullableSource)
260 if err != nil {
261 return nil, err
262 }
263
264 if nullableDescription.Valid {
265 repo.Description = nullableDescription.String
266 }
267
268 if nullableSource.Valid {
269 repo.Source = nullableSource.String
270 }
271
272 createdAtTime, err := time.Parse(time.RFC3339, createdAt)
273 if err != nil {
274 repo.Created = time.Now()
275 } else {
276 repo.Created = createdAtTime
277 }
278
279 return &repo, nil
280}
281
282func AddCollaborator(e Execer, collaborator, repoOwnerDid, repoName, repoKnot string) error {
283 _, err := e.Exec(
284 `insert into collaborators (did, repo)
285 values (?, (select id from repos where did = ? and name = ? and knot = ?));`,
286 collaborator, repoOwnerDid, repoName, repoKnot)
287 return err
288}
289
290func UpdateDescription(e Execer, repoAt, newDescription string) error {
291 _, err := e.Exec(
292 `update repos set description = ? where at_uri = ?`, newDescription, repoAt)
293 return err
294}
295
296func CollaboratingIn(e Execer, collaborator string) ([]Repo, error) {
297 var repos []Repo
298
299 rows, err := e.Query(
300 `select
301 r.did, r.name, r.knot, r.rkey, r.description, r.created, count(s.id) as star_count
302 from
303 repos r
304 join
305 collaborators c on r.id = c.repo
306 left join
307 stars s on r.at_uri = s.repo_at
308 where
309 c.did = ?
310 group by
311 r.id;`, collaborator)
312 if err != nil {
313 return nil, err
314 }
315 defer rows.Close()
316
317 for rows.Next() {
318 var repo Repo
319 var repoStats RepoStats
320 var createdAt string
321 var nullableDescription sql.NullString
322
323 err := rows.Scan(&repo.Did, &repo.Name, &repo.Knot, &repo.Rkey, &nullableDescription, &createdAt, &repoStats.StarCount)
324 if err != nil {
325 return nil, err
326 }
327
328 if nullableDescription.Valid {
329 repo.Description = nullableDescription.String
330 } else {
331 repo.Description = ""
332 }
333
334 createdAtTime, err := time.Parse(time.RFC3339, createdAt)
335 if err != nil {
336 repo.Created = time.Now()
337 } else {
338 repo.Created = createdAtTime
339 }
340
341 repo.RepoStats = &repoStats
342
343 repos = append(repos, repo)
344 }
345
346 if err := rows.Err(); err != nil {
347 return nil, err
348 }
349
350 return repos, nil
351}
352
353type RepoStats struct {
354 StarCount int
355 IssueCount IssueCount
356 PullCount PullCount
357}
358
359func scanRepo(rows *sql.Rows, did, name, knot, rkey, description *string, created *time.Time, source *string) error {
360 var createdAt string
361 var nullableDescription sql.NullString
362 var nullableSource sql.NullString
363 if err := rows.Scan(did, name, knot, rkey, &nullableDescription, &createdAt, &nullableSource); err != nil {
364 return err
365 }
366
367 if nullableDescription.Valid {
368 *description = nullableDescription.String
369 } else {
370 *description = ""
371 }
372
373 createdAtTime, err := time.Parse(time.RFC3339, createdAt)
374 if err != nil {
375 *created = time.Now()
376 } else {
377 *created = createdAtTime
378 }
379
380 if nullableSource.Valid {
381 *source = nullableSource.String
382 } else {
383 *source = ""
384 }
385
386 return nil
387}