this repo has no description
1package db 2 3import ( 4 "database/sql" 5 "fmt" 6 "maps" 7 "slices" 8 "sort" 9 "strings" 10 "time" 11 12 "github.com/bluesky-social/indigo/atproto/syntax" 13 "tangled.org/core/appview/models" 14 "tangled.org/core/orm" 15) 16 17func PutComment(tx *sql.Tx, c *models.Comment) error { 18 result, err := tx.Exec( 19 `insert into comments ( 20 did, 21 rkey, 22 subject_at, 23 reply_to, 24 body, 25 pull_submission_id, 26 created 27 ) 28 values (?, ?, ?, ?, ?, ?, ?) 29 on conflict(did, rkey) do update set 30 subject_at = excluded.subject_at, 31 reply_to = excluded.reply_to, 32 body = excluded.body, 33 edited = case 34 when 35 comments.subject_at != excluded.subject_at 36 or comments.body != excluded.body 37 or comments.reply_to != excluded.reply_to 38 then ? 39 else comments.edited 40 end`, 41 c.Did, 42 c.Rkey, 43 c.Subject, 44 c.ReplyTo, 45 c.Body, 46 c.PullSubmissionId, 47 c.Created.Format(time.RFC3339), 48 time.Now().Format(time.RFC3339), 49 ) 50 if err != nil { 51 return err 52 } 53 54 c.Id, err = result.LastInsertId() 55 if err != nil { 56 return err 57 } 58 59 if err := putReferences(tx, c.AtUri(), c.References); err != nil { 60 return fmt.Errorf("put reference_links: %w", err) 61 } 62 63 return nil 64} 65 66func DeleteComments(e Execer, filters ...orm.Filter) error { 67 var conditions []string 68 var args []any 69 for _, filter := range filters { 70 conditions = append(conditions, filter.Condition()) 71 args = append(args, filter.Arg()...) 72 } 73 74 whereClause := "" 75 if conditions != nil { 76 whereClause = " where " + strings.Join(conditions, " and ") 77 } 78 79 query := fmt.Sprintf(`update comments set body = "", deleted = strftime('%%Y-%%m-%%dT%%H:%%M:%%SZ', 'now') %s`, whereClause) 80 81 _, err := e.Exec(query, args...) 82 return err 83} 84 85func GetComments(e Execer, filters ...orm.Filter) ([]models.Comment, error) { 86 commentMap := make(map[string]*models.Comment) 87 88 var conditions []string 89 var args []any 90 for _, filter := range filters { 91 conditions = append(conditions, filter.Condition()) 92 args = append(args, filter.Arg()...) 93 } 94 95 whereClause := "" 96 if conditions != nil { 97 whereClause = " where " + strings.Join(conditions, " and ") 98 } 99 100 query := fmt.Sprintf(` 101 select 102 id, 103 did, 104 rkey, 105 subject_at, 106 reply_to, 107 body, 108 pull_submission_id, 109 created, 110 edited, 111 deleted 112 from 113 comments 114 %s 115 `, whereClause) 116 117 rows, err := e.Query(query, args...) 118 if err != nil { 119 return nil, err 120 } 121 122 for rows.Next() { 123 var comment models.Comment 124 var created string 125 var rkey, edited, deleted, replyTo sql.Null[string] 126 err := rows.Scan( 127 &comment.Id, 128 &comment.Did, 129 &rkey, 130 &comment.Subject, 131 &replyTo, 132 &comment.Body, 133 &comment.PullSubmissionId, 134 &created, 135 &edited, 136 &deleted, 137 ) 138 if err != nil { 139 return nil, err 140 } 141 142 // this is a remnant from old times, newer comments always have rkey 143 if rkey.Valid { 144 comment.Rkey = rkey.V 145 } 146 147 if t, err := time.Parse(time.RFC3339, created); err == nil { 148 comment.Created = t 149 } 150 151 if edited.Valid { 152 if t, err := time.Parse(time.RFC3339, edited.V); err == nil { 153 comment.Edited = &t 154 } 155 } 156 157 if deleted.Valid { 158 if t, err := time.Parse(time.RFC3339, deleted.V); err == nil { 159 comment.Deleted = &t 160 } 161 } 162 163 if replyTo.Valid { 164 rt := syntax.ATURI(replyTo.V) 165 comment.ReplyTo = &rt 166 } 167 168 atUri := comment.AtUri().String() 169 commentMap[atUri] = &comment 170 } 171 172 if err := rows.Err(); err != nil { 173 return nil, err 174 } 175 defer rows.Close() 176 177 // collect references from each comments 178 commentAts := slices.Collect(maps.Keys(commentMap)) 179 allReferencs, err := GetReferencesAll(e, orm.FilterIn("from_at", commentAts)) 180 if err != nil { 181 return nil, fmt.Errorf("failed to query reference_links: %w", err) 182 } 183 for commentAt, references := range allReferencs { 184 if comment, ok := commentMap[commentAt.String()]; ok { 185 comment.References = references 186 } 187 } 188 189 var comments []models.Comment 190 for _, c := range commentMap { 191 comments = append(comments, *c) 192 } 193 194 sort.Slice(comments, func(i, j int) bool { 195 return comments[i].Created.After(comments[j].Created) 196 }) 197 198 return comments, nil 199}