This repository has no description
1package db
2
3import (
4 "context"
5 "database/sql"
6 "fmt"
7 "slices"
8 "strings"
9 "time"
10
11 "github.com/bluesky-social/indigo/atproto/syntax"
12 "tangled.org/core/appview/models"
13 "tangled.org/core/consts"
14 "tangled.org/core/orm"
15)
16
17// RecentSpindles suggests spindles for the spindle picker: ones this user already
18// pointed a repo at, most recently created first, plus the default spindle.
19func RecentSpindles(ctx context.Context, e Execer, user syntax.DID) ([]string, error) {
20 rows, err := e.QueryContext(ctx, `
21 select spindle from repos
22 where did = ? and coalesce(spindle, '') != ''
23 group by spindle
24 order by max(id) desc
25 limit 5
26 `, user)
27 if err != nil {
28 return nil, err
29 }
30 defer rows.Close()
31
32 var spindles []string
33 for rows.Next() {
34 var spindle string
35 if err := rows.Scan(&spindle); err != nil {
36 return nil, err
37 }
38 spindles = append(spindles, spindle)
39 }
40 if err := rows.Err(); err != nil {
41 return nil, err
42 }
43
44 // a fresh account owns no repos, and a bare text input gives it nothing to go on
45 if !slices.Contains(spindles, consts.DefaultSpindle) {
46 spindles = append(spindles, consts.DefaultSpindle)
47 }
48
49 return spindles, nil
50}
51
52func GetSpindles(ctx context.Context, e Execer, filters ...orm.Filter) ([]models.Spindle, error) {
53 var spindles []models.Spindle
54
55 var conditions []string
56 var args []any
57 for _, filter := range filters {
58 conditions = append(conditions, filter.Condition())
59 args = append(args, filter.Arg()...)
60 }
61
62 whereClause := ""
63 if conditions != nil {
64 whereClause = " where " + strings.Join(conditions, " and ")
65 }
66
67 query := fmt.Sprintf(
68 `select id, owner, instance, verified, created, needs_upgrade
69 from spindles
70 %s
71 order by created
72 `,
73 whereClause,
74 )
75
76 rows, err := e.QueryContext(ctx, query, args...)
77
78 if err != nil {
79 return nil, err
80 }
81 defer rows.Close()
82
83 for rows.Next() {
84 var spindle models.Spindle
85 var createdAt string
86 var verified sql.NullString
87 var needsUpgrade int
88
89 if err := rows.Scan(
90 &spindle.Id,
91 &spindle.Owner,
92 &spindle.Instance,
93 &verified,
94 &createdAt,
95 &needsUpgrade,
96 ); err != nil {
97 return nil, err
98 }
99
100 spindle.Created, err = time.Parse(time.RFC3339, createdAt)
101 if err != nil {
102 spindle.Created = time.Now()
103 }
104
105 if verified.Valid {
106 t, err := time.Parse(time.RFC3339, verified.String)
107 if err != nil {
108 now := time.Now()
109 spindle.Verified = &now
110 }
111 spindle.Verified = &t
112 }
113
114 if needsUpgrade != 0 {
115 spindle.NeedsUpgrade = true
116 }
117
118 spindles = append(spindles, spindle)
119 }
120
121 return spindles, nil
122}
123
124func VerifySpindle(e Execer, filters ...orm.Filter) (int64, error) {
125 var conditions []string
126 var args []any
127 for _, filter := range filters {
128 conditions = append(conditions, filter.Condition())
129 args = append(args, filter.Arg()...)
130 }
131
132 whereClause := ""
133 if conditions != nil {
134 whereClause = " where " + strings.Join(conditions, " and ")
135 }
136
137 query := fmt.Sprintf(`update spindles set verified = strftime('%%Y-%%m-%%dT%%H:%%M:%%SZ', 'now'), needs_upgrade = 0 %s`, whereClause)
138
139 res, err := e.Exec(query, args...)
140 if err != nil {
141 return 0, err
142 }
143
144 return res.RowsAffected()
145}