This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

core / spindle / db / repos.go
2.9 kB 136 lines
1package db 2 3import ( 4 "database/sql" 5 "errors" 6 7 "github.com/bluesky-social/indigo/atproto/syntax" 8) 9 10type Repo struct { 11 Knot string 12 Owner syntax.DID 13 Rkey syntax.RecordKey 14 RepoDid syntax.DID 15 CreatedAt string 16} 17 18func (d *DB) UpsertRepo(repo Repo) error { 19 var createdAt sql.NullString 20 if repo.CreatedAt != "" { 21 createdAt = sql.NullString{String: repo.CreatedAt, Valid: true} 22 } 23 _, err := d.Exec( 24 `insert or replace into repos (repo_did, knot, owner, rkey, created_at) 25 values (?, ?, ?, ?, ?)`, 26 repo.RepoDid, repo.Knot, repo.Owner, repo.Rkey, createdAt, 27 ) 28 return err 29} 30 31func (d *DB) RepoOwners() ([]syntax.DID, error) { 32 repos, err := d.AllRepos() 33 if err != nil { 34 return nil, err 35 } 36 seen := make(map[syntax.DID]struct{}, len(repos)) 37 dids := make([]syntax.DID, 0, len(repos)) 38 for _, r := range repos { 39 if r.Owner == "" { 40 continue 41 } 42 if _, ok := seen[r.Owner]; ok { 43 continue 44 } 45 seen[r.Owner] = struct{}{} 46 dids = append(dids, r.Owner) 47 } 48 return dids, nil 49} 50 51func (d *DB) Knots() ([]string, error) { 52 rows, err := d.Query(`select distinct knot from repos`) 53 if err != nil { 54 return nil, err 55 } 56 defer rows.Close() 57 58 var knots []string 59 for rows.Next() { 60 var knot string 61 if err := rows.Scan(&knot); err != nil { 62 return nil, err 63 } 64 knots = append(knots, knot) 65 } 66 67 if err := rows.Err(); err != nil { 68 return nil, err 69 } 70 71 return knots, nil 72} 73 74func scanRepo(row interface{ Scan(...any) error }) (*Repo, error) { 75 var knot, owner, rkey, repoDid string 76 if err := row.Scan(&knot, &owner, &rkey, &repoDid); err != nil { 77 return nil, err 78 } 79 return &Repo{ 80 Knot: knot, 81 Owner: syntax.DID(owner), 82 Rkey: syntax.RecordKey(rkey), 83 RepoDid: syntax.DID(repoDid), 84 }, nil 85} 86 87func (d *DB) GetRepoByDid(repoDid syntax.DID) (*Repo, error) { 88 return scanRepo(d.QueryRow( 89 `select knot, owner, rkey, repo_did from repos where repo_did = ?`, 90 repoDid.String(), 91 )) 92} 93 94func (d *DB) AllRepos() ([]Repo, error) { 95 rows, err := d.Query(`select knot, owner, rkey, repo_did from repos`) 96 if err != nil { 97 return nil, err 98 } 99 defer rows.Close() 100 101 var repos []Repo 102 for rows.Next() { 103 r, err := scanRepo(rows) 104 if err != nil { 105 return nil, err 106 } 107 repos = append(repos, *r) 108 } 109 110 if err := rows.Err(); err != nil { 111 return nil, err 112 } 113 114 return repos, nil 115} 116 117func (d *DB) DeleteRepo(repoDid syntax.DID) error { 118 _, err := d.Exec(`delete from repos where repo_did = ?`, repoDid) 119 return err 120} 121 122// DeleteRepoByOwnerRkey deletes a repo by (owner,rkey) pair and returns deleted repos DID. 123func (d *DB) DeleteRepoByOwnerRkey(owner syntax.DID, rkey syntax.RecordKey) (syntax.DID, error) { 124 var repoDid string 125 err := d.QueryRow( 126 `delete from repos where owner = ? and rkey = ? returning repo_did`, 127 owner.String(), rkey.String(), 128 ).Scan(&repoDid) 129 if errors.Is(err, sql.ErrNoRows) { 130 return "", nil 131 } 132 if err != nil { 133 return "", err 134 } 135 return syntax.DID(repoDid), nil 136}