forked from
tangled.org/core
fork
Configure Feed
Select the types of activity you want to include in your feed.
Monorepo for Tangled
fork
Configure Feed
Select the types of activity you want to include in your feed.
1package db
2
3import (
4 "log"
5 "time"
6
7 "github.com/bluesky-social/indigo/atproto/syntax"
8 "tangled.org/core/appview/models"
9)
10
11func AddReaction(e Execer, reactedByDid string, threadAt syntax.ATURI, kind models.ReactionKind, rkey string) error {
12 query := `insert or ignore into reactions (reacted_by_did, thread_at, kind, rkey) values (?, ?, ?, ?)`
13 _, err := e.Exec(query, reactedByDid, threadAt, kind, rkey)
14 return err
15}
16
17// Get a reaction record
18func GetReaction(e Execer, reactedByDid string, threadAt syntax.ATURI, kind models.ReactionKind) (*models.Reaction, error) {
19 query := `
20 select reacted_by_did, thread_at, created, rkey
21 from reactions
22 where reacted_by_did = ? and thread_at = ? and kind = ?`
23 row := e.QueryRow(query, reactedByDid, threadAt, kind)
24
25 var reaction models.Reaction
26 var created string
27 err := row.Scan(&reaction.ReactedByDid, &reaction.ThreadAt, &created, &reaction.Rkey)
28 if err != nil {
29 return nil, err
30 }
31
32 createdAtTime, err := time.Parse(time.RFC3339, created)
33 if err != nil {
34 log.Println("unable to determine followed at time")
35 reaction.Created = time.Now()
36 } else {
37 reaction.Created = createdAtTime
38 }
39
40 return &reaction, nil
41}
42
43// Remove a reaction
44func DeleteReaction(e Execer, reactedByDid string, threadAt syntax.ATURI, kind models.ReactionKind) error {
45 _, err := e.Exec(`delete from reactions where reacted_by_did = ? and thread_at = ? and kind = ?`, reactedByDid, threadAt, kind)
46 return err
47}
48
49// Remove a reaction
50func DeleteReactionByRkey(e Execer, reactedByDid string, rkey string) error {
51 _, err := e.Exec(`delete from reactions where reacted_by_did = ? and rkey = ?`, reactedByDid, rkey)
52 return err
53}
54
55func GetReactionCount(e Execer, threadAt syntax.ATURI, kind models.ReactionKind) (int, error) {
56 count := 0
57 err := e.QueryRow(
58 `select count(reacted_by_did) from reactions where thread_at = ? and kind = ?`, threadAt, kind).Scan(&count)
59 if err != nil {
60 return 0, err
61 }
62 return count, nil
63}
64
65func GetReactionMap(e Execer, userLimit int, threadAt syntax.ATURI) (map[models.ReactionKind]models.ReactionDisplayData, error) {
66 query := `
67 select kind, reacted_by_did,
68 row_number() over (partition by kind order by created asc) as rn,
69 count(*) over (partition by kind) as total
70 from reactions
71 where thread_at = ?
72 order by kind, created asc`
73
74 rows, err := e.Query(query, threadAt)
75 if err != nil {
76 return nil, err
77 }
78 defer rows.Close()
79
80 reactionMap := map[models.ReactionKind]models.ReactionDisplayData{}
81 for _, kind := range models.OrderedReactionKinds {
82 reactionMap[kind] = models.ReactionDisplayData{Count: 0, Users: []string{}}
83 }
84
85 for rows.Next() {
86 var kind models.ReactionKind
87 var did string
88 var rn, total int
89 if err := rows.Scan(&kind, &did, &rn, &total); err != nil {
90 return nil, err
91 }
92
93 data := reactionMap[kind]
94 data.Count = total
95 if userLimit > 0 && rn <= userLimit {
96 data.Users = append(data.Users, did)
97 }
98 reactionMap[kind] = data
99 }
100
101 return reactionMap, rows.Err()
102}
103
104func GetReactionStatus(e Execer, userDid string, threadAt syntax.ATURI, kind models.ReactionKind) bool {
105 if _, err := GetReaction(e, userDid, threadAt, kind); err != nil {
106 return false
107 } else {
108 return true
109 }
110}
111
112func GetReactionStatusMap(e Execer, userDid string, threadAt syntax.ATURI) map[models.ReactionKind]bool {
113 statusMap := map[models.ReactionKind]bool{}
114 for _, kind := range models.OrderedReactionKinds {
115 count := GetReactionStatus(e, userDid, threadAt, kind)
116 statusMap[kind] = count
117 }
118 return statusMap
119}