Monorepo for Tangled tangled.org
2

Configure Feed

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

1package db 2 3import ( 4 "database/sql" 5 6 "github.com/bluesky-social/indigo/atproto/syntax" 7) 8 9type Repo struct { 10 Knot string 11 Owner syntax.DID 12 Rkey syntax.RecordKey 13 RepoDid syntax.DID 14 CreatedAt string 15} 16 17func (d *DB) AddRepo(repo Repo) error { 18 var createdAt sql.NullString 19 if repo.CreatedAt != "" { 20 createdAt = sql.NullString{String: repo.CreatedAt, Valid: true} 21 } 22 _, err := d.Exec( 23 `insert into repos (knot, owner, rkey, repo_did, created_at) 24 values (?, ?, ?, ?, ?) 25 on conflict(owner, rkey) do update set 26 knot = excluded.knot, 27 repo_did = excluded.repo_did, 28 created_at = coalesce(excluded.created_at, repos.created_at)`, 29 repo.Knot, repo.Owner.String(), repo.Rkey.String(), repo.RepoDid.String(), createdAt, 30 ) 31 return err 32} 33 34func (d *DB) CollapseRepoSiblings(owner, repoDid syntax.DID) (int64, error) { 35 res, err := d.Exec( 36 `delete from repos 37 where owner = ? 38 and repo_did = ? 39 and ( 40 (created_at is null and exists ( 41 select 1 from repos r2 42 where r2.owner = repos.owner 43 and r2.repo_did = repos.repo_did 44 and r2.created_at is not null 45 and r2.rkey <> repos.rkey 46 )) 47 or (created_at is not null and created_at < ( 48 select max(created_at) from repos 49 where owner = ? and repo_did = ? and created_at is not null 50 )) 51 )`, 52 owner.String(), repoDid.String(), owner.String(), repoDid.String(), 53 ) 54 if err != nil { 55 return 0, err 56 } 57 return res.RowsAffected() 58} 59 60func (d *DB) Knots() ([]string, error) { 61 rows, err := d.Query(`select distinct knot from repos`) 62 if err != nil { 63 return nil, err 64 } 65 defer rows.Close() 66 67 var knots []string 68 for rows.Next() { 69 var knot string 70 if err := rows.Scan(&knot); err != nil { 71 return nil, err 72 } 73 knots = append(knots, knot) 74 } 75 76 if err := rows.Err(); err != nil { 77 return nil, err 78 } 79 80 return knots, nil 81} 82 83func scanRepo(row interface{ Scan(...any) error }) (*Repo, error) { 84 var knot, owner, rkey, repoDid string 85 if err := row.Scan(&knot, &owner, &rkey, &repoDid); err != nil { 86 return nil, err 87 } 88 return &Repo{ 89 Knot: knot, 90 Owner: syntax.DID(owner), 91 Rkey: syntax.RecordKey(rkey), 92 RepoDid: syntax.DID(repoDid), 93 }, nil 94} 95 96func (d *DB) SiblingRkeysForRepoDid(owner, repoDid syntax.DID, excludeRkey syntax.RecordKey) ([]string, error) { 97 rows, err := d.Query( 98 `select rkey from repos 99 where owner = ? 100 and coalesce(repo_did, '') = ? 101 and rkey <> ?`, 102 owner.String(), repoDid.String(), excludeRkey.String(), 103 ) 104 if err != nil { 105 return nil, err 106 } 107 defer rows.Close() 108 109 var collect func(acc []string) ([]string, error) 110 collect = func(acc []string) ([]string, error) { 111 if !rows.Next() { 112 return acc, rows.Err() 113 } 114 var r string 115 if err := rows.Scan(&r); err != nil { 116 return acc, err 117 } 118 return collect(append(acc, r)) 119 } 120 return collect(nil) 121} 122 123func (d *DB) GetRepoByDid(repoDid syntax.DID) (*Repo, error) { 124 return scanRepo(d.QueryRow( 125 `select knot, owner, rkey, coalesce(repo_did, '') from repos where repo_did = ?`, 126 repoDid.String(), 127 )) 128} 129 130func (d *DB) GetRepoByOwnerRkey(owner syntax.DID, rkey syntax.RecordKey) (*Repo, error) { 131 return scanRepo(d.QueryRow( 132 `select knot, owner, rkey, coalesce(repo_did, '') from repos where owner = ? and rkey = ?`, 133 owner.String(), rkey.String(), 134 )) 135} 136 137func (d *DB) AllRepos() ([]Repo, error) { 138 rows, err := d.Query(`select knot, owner, rkey, coalesce(repo_did, '') from repos`) 139 if err != nil { 140 return nil, err 141 } 142 defer rows.Close() 143 144 var repos []Repo 145 for rows.Next() { 146 r, err := scanRepo(rows) 147 if err != nil { 148 return nil, err 149 } 150 repos = append(repos, *r) 151 } 152 153 if err := rows.Err(); err != nil { 154 return nil, err 155 } 156 157 return repos, nil 158} 159 160func (d *DB) DeleteRepoByOwnerRkey(owner syntax.DID, rkey syntax.RecordKey) error { 161 _, err := d.Exec(`delete from repos where owner = ? and rkey = ?`, owner.String(), rkey.String()) 162 return err 163}