This repository has been archived by the owner on Mar 28, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 284
/
notifications.go
176 lines (154 loc) · 4.61 KB
/
notifications.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
package db
import (
"database/sql"
"encoding/json"
"fmt"
"strconv"
"strings"
"sync"
"time"
"github.com/OpenBazaar/openbazaar-go/repo"
)
type NotficationsDB struct {
modelStore
}
func NewNotificationStore(db *sql.DB, lock *sync.Mutex) repo.NotificationStore {
return &NotficationsDB{modelStore{db, lock}}
}
func (n *NotficationsDB) PutRecord(record *repo.Notification) error {
ser, err := json.Marshal(record)
if err != nil {
return err
}
var read int
if record.IsRead {
read = 1
}
n.lock.Lock()
defer n.lock.Unlock()
_, err = n.ExecuteQuery("insert into notifications(notifID, serializedNotification, type, timestamp, read) values(?,?,?,?,?)", record.GetID(), string(ser), strings.ToLower(record.GetTypeString()), record.GetUnixCreatedAt(), read)
if err != nil {
return err
}
return nil
}
func (n *NotficationsDB) GetAll(offsetId string, limit int, typeFilter []string) ([]*repo.Notification, int, error) {
var ret []*repo.Notification
var stm string
var cstm string
var filter string
typeFilterClause := ""
var types []string
if len(typeFilter) > 0 {
typeFilterClauseParts := make([]string, 0, len(typeFilter))
for i := 0; i < len(typeFilter); i++ {
types = append(types, strings.ToLower(typeFilter[i]))
typeFilterClauseParts = append(typeFilterClauseParts, "?")
}
typeFilterClause = "type in (" + strings.Join(typeFilterClauseParts, ",") + ")"
}
// Prepare statements
var args []interface{}
if offsetId != "" {
args = append(args, offsetId)
if len(types) > 0 {
filter = " and " + typeFilterClause
for _, a := range types {
args = append(args, a)
}
}
stm = "select serializedNotification, timestamp, read from notifications where rowid<(select rowid from notifications where notifID=?)" + filter + " order by rowid desc limit " + strconv.Itoa(limit) + ";"
cstm = "select Count(*) from notifications where timestamp<(select timestamp from notifications where notifID=?)" + filter + " order by rowid desc;"
} else {
if len(types) > 0 {
filter = " where " + typeFilterClause
for _, a := range types {
args = append(args, a)
}
}
stm = "select serializedNotification, timestamp, read from notifications" + filter + " order by rowid desc limit " + strconv.Itoa(limit) + ";"
cstm = "select Count(*) from notifications" + filter + " order by rowid desc;"
}
// Gather records
n.lock.Lock()
defer n.lock.Unlock()
rows, err := n.db.Query(stm, args...)
if err != nil {
return ret, 0, err
}
for rows.Next() {
var (
data []byte
readInt int
timestampInt int
)
if err := rows.Scan(&data, ×tampInt, &readInt); err != nil {
log.Errorf("notifications: GetAll: scanning: %s\n", err.Error())
continue
}
var notification = &repo.Notification{}
err := json.Unmarshal(data, notification)
if err != nil {
log.Errorf("notifications: GetAll: unmarshalling: %s\n", err.Error())
continue
}
// TODO: These should get removed when (*Notification).MarshalJSON begins to include
// these values. Overriding them here allows for the marshaled representation of
// the ID field to become out of sync with the DB version of ID, which is overridden
// here. (Making Notification.NotifierData.GetID() != Notification.GetID())
var read bool
if readInt == 1 {
read = true
}
notification.IsRead = read
notification.CreatedAt = repo.NewAPITime(time.Unix(int64(timestampInt), 0).UTC())
// END
ret = append(ret, notification)
}
row := n.db.QueryRow(cstm, args...)
var count int
err = row.Scan(&count)
if err != nil {
return ret, 0, err
}
return ret, count, nil
}
func (n *NotficationsDB) MarkAsRead(notifID string) error {
n.lock.Lock()
defer n.lock.Unlock()
stmt, err := n.PrepareQuery("update notifications set read=1 where notifID=?")
if err != nil {
return fmt.Errorf("prepare notification sql: %s", err.Error())
}
defer stmt.Close()
_, err = stmt.Exec(notifID)
if err != nil {
return fmt.Errorf("commit notification as read: %s", err.Error())
}
return nil
}
func (n *NotficationsDB) MarkAllAsRead() error {
n.lock.Lock()
defer n.lock.Unlock()
_, err := n.ExecuteQuery("update notifications set read=1")
return err
}
func (n *NotficationsDB) Delete(notifID string) error {
n.lock.Lock()
defer n.lock.Unlock()
_, err := n.ExecuteQuery("delete from notifications where notifID=?", notifID)
if err != nil {
return fmt.Errorf("notifications: delete: %s", err.Error())
}
return nil
}
func (n *NotficationsDB) GetUnreadCount() (int, error) {
stm := "select Count(*) from notifications where read=0;"
row := n.db.QueryRow(stm)
var count int
err := row.Scan(&count)
if err != nil {
return 0, err
}
return count, nil
}