forked from
tangled.org/core
Monorepo for Tangled — https://tangled.org
1package db
2
3import (
4 "log"
5 "time"
6)
7
8type Follow struct {
9 UserDid string
10 SubjectDid string
11 FollowedAt time.Time
12 RKey string
13}
14
15func AddFollow(e Execer, userDid, subjectDid, rkey string) error {
16 query := `insert or ignore into follows (user_did, subject_did, rkey) values (?, ?, ?)`
17 _, err := e.Exec(query, userDid, subjectDid, rkey)
18 return err
19}
20
21// Get a follow record
22func GetFollow(e Execer, userDid, subjectDid string) (*Follow, error) {
23 query := `select user_did, subject_did, followed_at, rkey from follows where user_did = ? and subject_did = ?`
24 row := e.QueryRow(query, userDid, subjectDid)
25
26 var follow Follow
27 var followedAt string
28 err := row.Scan(&follow.UserDid, &follow.SubjectDid, &followedAt, &follow.RKey)
29 if err != nil {
30 return nil, err
31 }
32
33 followedAtTime, err := time.Parse(time.RFC3339, followedAt)
34 if err != nil {
35 log.Println("unable to determine followed at time")
36 follow.FollowedAt = time.Now()
37 } else {
38 follow.FollowedAt = followedAtTime
39 }
40
41 return &follow, nil
42}
43
44// Get a follow record
45func DeleteFollow(e Execer, userDid, subjectDid string) error {
46 _, err := e.Exec(`delete from follows where user_did = ? and subject_did = ?`, userDid, subjectDid)
47 return err
48}
49
50func GetFollowerFollowing(e Execer, did string) (int, int, error) {
51 followers, following := 0, 0
52 err := e.QueryRow(
53 `SELECT
54 COUNT(CASE WHEN subject_did = ? THEN 1 END) AS followers,
55 COUNT(CASE WHEN user_did = ? THEN 1 END) AS following
56 FROM follows;`, did, did).Scan(&followers, &following)
57 if err != nil {
58 return 0, 0, err
59 }
60 return followers, following, nil
61}
62
63type FollowStatus int
64
65const (
66 IsNotFollowing FollowStatus = iota
67 IsFollowing
68 IsSelf
69)
70
71func (s FollowStatus) String() string {
72 switch s {
73 case IsNotFollowing:
74 return "IsNotFollowing"
75 case IsFollowing:
76 return "IsFollowing"
77 case IsSelf:
78 return "IsSelf"
79 default:
80 return "IsNotFollowing"
81 }
82}
83
84func GetFollowStatus(e Execer, userDid, subjectDid string) FollowStatus {
85 if userDid == subjectDid {
86 return IsSelf
87 } else if _, err := GetFollow(e, userDid, subjectDid); err != nil {
88 return IsNotFollowing
89 } else {
90 return IsFollowing
91 }
92}
93
94func GetAllFollows(e Execer) ([]Follow, error) {
95 var follows []Follow
96
97 rows, err := e.Query(`select user_did, subject_did, followed_at, rkey from follows`)
98 if err != nil {
99 return nil, err
100 }
101 defer rows.Close()
102
103 for rows.Next() {
104 var follow Follow
105 var followedAt string
106 if err := rows.Scan(&follow.UserDid, &follow.SubjectDid, &followedAt, &follow.RKey); err != nil {
107 return nil, err
108 }
109
110 followedAtTime, err := time.Parse(time.RFC3339, followedAt)
111 if err != nil {
112 log.Println("unable to determine followed at time")
113 follow.FollowedAt = time.Now()
114 } else {
115 follow.FollowedAt = followedAtTime
116 }
117
118 follows = append(follows, follow)
119 }
120
121 if err := rows.Err(); err != nil {
122 return nil, err
123 }
124
125 return follows, nil
126}