2021-04-07 12:57:14 +00:00
package protocol
import (
"context"
"database/sql"
"encoding/json"
"fmt"
"strings"
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/protocol/common"
2022-08-31 14:41:58 +00:00
"github.com/status-im/status-go/protocol/verification"
2021-04-07 12:57:14 +00:00
)
func ( db sqlitePersistence ) DeleteActivityCenterNotification ( id [ ] byte ) error {
_ , err := db . db . Exec ( ` DELETE FROM activity_center_notifications WHERE id = ? ` , id )
return err
}
2021-08-23 14:23:55 +00:00
func ( db sqlitePersistence ) DeleteActivityCenterNotificationForMessage ( chatID string , messageID string ) error {
var tx * sql . Tx
var err error
tx , err = db . db . BeginTx ( context . Background ( ) , & sql . TxOptions { } )
if err != nil {
return err
}
defer func ( ) {
if err == nil {
err = tx . Commit ( )
return
}
// don't shadow original error
_ = tx . Rollback ( )
} ( )
2022-08-31 14:41:58 +00:00
params := activityCenterQueryParams {
chatID : chatID ,
activityCenterType : ActivityCenterNotificationNoType ,
}
_ , notifications , err := db . buildActivityCenterQuery ( tx , params )
2021-08-23 14:23:55 +00:00
if err != nil {
return err
}
var ids [ ] types . HexBytes
for _ , notification := range notifications {
2022-09-12 13:39:07 +00:00
if notification . LastMessage != nil && notification . LastMessage . ID == messageID {
ids = append ( ids , notification . ID )
}
2021-08-23 14:23:55 +00:00
if notification . Message != nil && notification . Message . ID == messageID {
ids = append ( ids , notification . ID )
}
}
if len ( ids ) > 0 {
idsArgs := make ( [ ] interface { } , 0 , len ( ids ) )
for _ , id := range ids {
idsArgs = append ( idsArgs , id )
}
inVector := strings . Repeat ( "?, " , len ( ids ) - 1 ) + "?"
2021-12-07 14:34:43 +00:00
query := "UPDATE activity_center_notifications SET read = 1, dismissed = 1 WHERE id IN (" + inVector + ")" // nolint: gosec
2021-08-23 14:23:55 +00:00
_ , err = tx . Exec ( query , idsArgs ... )
return err
}
return nil
}
2021-04-07 12:57:14 +00:00
func ( db sqlitePersistence ) SaveActivityCenterNotification ( notification * ActivityCenterNotification ) error {
var tx * sql . Tx
var err error
err = notification . Valid ( )
if err != nil {
return err
}
tx , err = db . db . BeginTx ( context . Background ( ) , & sql . TxOptions { } )
if err != nil {
return err
}
defer func ( ) {
if err == nil {
err = tx . Commit ( )
return
}
// don't shadow original error
_ = tx . Rollback ( )
} ( )
2021-11-19 14:32:04 +00:00
if notification . Type == ActivityCenterNotificationTypeNewOneToOne ||
notification . Type == ActivityCenterNotificationTypeNewPrivateGroupChat {
2021-04-07 12:57:14 +00:00
// Delete other notifications so it pop us again if not currently dismissed
2021-06-29 08:27:11 +00:00
_ , err = tx . Exec ( ` DELETE FROM activity_center_notifications WHERE id = ? AND (dismissed OR accepted) ` , notification . ID )
2021-04-07 12:57:14 +00:00
if err != nil {
return err
}
}
2021-05-29 17:05:25 +00:00
// encode message
var encodedMessage [ ] byte
if notification . Message != nil {
encodedMessage , err = json . Marshal ( notification . Message )
if err != nil {
return err
}
}
2021-07-15 20:21:44 +00:00
// encode message
var encodedReplyMessage [ ] byte
if notification . ReplyMessage != nil {
encodedReplyMessage , err = json . Marshal ( notification . ReplyMessage )
if err != nil {
return err
}
}
2022-10-24 11:33:47 +00:00
_ , err = tx . Exec ( ` INSERT OR REPLACE INTO activity_center_notifications (id, timestamp, notification_type, chat_id, community_id, membership_status, message, reply_message, author, contact_verification_status) VALUES (?,?,?,?,?,?,?,?,?,?) ` , notification . ID , notification . Timestamp , notification . Type , notification . ChatID , notification . CommunityID , notification . MembershipStatus , encodedMessage , encodedReplyMessage , notification . Author , notification . ContactVerificationStatus )
2021-04-07 12:57:14 +00:00
return err
}
2022-01-18 16:31:34 +00:00
func ( db sqlitePersistence ) unmarshalActivityCenterNotificationRow ( row * sql . Row ) ( * ActivityCenterNotification , error ) {
var chatID sql . NullString
2022-10-25 22:06:20 +00:00
var communityID sql . NullString
2022-01-18 16:31:34 +00:00
var lastMessageBytes [ ] byte
var messageBytes [ ] byte
var replyMessageBytes [ ] byte
var name sql . NullString
var author sql . NullString
notification := & ActivityCenterNotification { }
err := row . Scan (
& notification . ID ,
& notification . Timestamp ,
& notification . Type ,
& chatID ,
2022-10-25 22:06:20 +00:00
& communityID ,
& notification . MembershipStatus ,
2022-01-18 16:31:34 +00:00
& notification . Read ,
& notification . Accepted ,
& notification . Dismissed ,
& messageBytes ,
& lastMessageBytes ,
& replyMessageBytes ,
2022-10-24 11:33:47 +00:00
& notification . ContactVerificationStatus ,
2022-01-18 16:31:34 +00:00
& name ,
& author )
if err != nil {
return nil , err
}
2022-10-25 22:06:20 +00:00
2022-01-18 16:31:34 +00:00
if chatID . Valid {
notification . ChatID = chatID . String
2022-10-25 22:06:20 +00:00
}
2022-01-18 16:31:34 +00:00
2022-10-25 22:06:20 +00:00
if communityID . Valid {
notification . CommunityID = communityID . String
2022-01-18 16:31:34 +00:00
}
if name . Valid {
notification . Name = name . String
}
if author . Valid {
notification . Author = author . String
}
// Restore last message
if lastMessageBytes != nil {
lastMessage := & common . Message { }
if err = json . Unmarshal ( lastMessageBytes , lastMessage ) ; err != nil {
return nil , err
}
notification . LastMessage = lastMessage
}
// Restore message
if messageBytes != nil {
message := & common . Message { }
if err = json . Unmarshal ( messageBytes , message ) ; err != nil {
return nil , err
}
notification . Message = message
}
// Restore reply message
if replyMessageBytes != nil {
replyMessage := & common . Message { }
if err = json . Unmarshal ( replyMessageBytes , replyMessage ) ; err != nil {
return nil , err
}
notification . ReplyMessage = replyMessage
}
return notification , nil
}
2021-04-07 12:57:14 +00:00
func ( db sqlitePersistence ) unmarshalActivityCenterNotificationRows ( rows * sql . Rows ) ( string , [ ] * ActivityCenterNotification , error ) {
var notifications [ ] * ActivityCenterNotification
latestCursor := ""
for rows . Next ( ) {
var chatID sql . NullString
2022-10-25 22:06:20 +00:00
var communityID sql . NullString
2021-04-07 12:57:14 +00:00
var lastMessageBytes [ ] byte
2021-05-29 17:05:25 +00:00
var messageBytes [ ] byte
2021-07-15 20:21:44 +00:00
var replyMessageBytes [ ] byte
2021-04-07 12:57:14 +00:00
var name sql . NullString
2021-06-17 15:08:28 +00:00
var author sql . NullString
2021-04-07 12:57:14 +00:00
notification := & ActivityCenterNotification { }
err := rows . Scan (
& notification . ID ,
& notification . Timestamp ,
& notification . Type ,
& chatID ,
2022-10-25 22:06:20 +00:00
& communityID ,
& notification . MembershipStatus ,
2021-04-07 12:57:14 +00:00
& notification . Read ,
& notification . Accepted ,
& notification . Dismissed ,
2021-05-29 17:05:25 +00:00
& messageBytes ,
2021-04-07 12:57:14 +00:00
& lastMessageBytes ,
2021-07-15 20:21:44 +00:00
& replyMessageBytes ,
2022-08-31 14:41:58 +00:00
& notification . ContactVerificationStatus ,
2021-04-07 12:57:14 +00:00
& name ,
2021-06-17 15:08:28 +00:00
& author ,
2021-04-07 12:57:14 +00:00
& latestCursor )
if err != nil {
return "" , nil , err
}
2022-10-25 22:06:20 +00:00
2021-04-07 12:57:14 +00:00
if chatID . Valid {
notification . ChatID = chatID . String
2022-10-25 22:06:20 +00:00
}
2021-04-07 12:57:14 +00:00
2022-10-25 22:06:20 +00:00
if communityID . Valid {
notification . CommunityID = communityID . String
2021-04-07 12:57:14 +00:00
}
if name . Valid {
notification . Name = name . String
}
2021-06-17 15:08:28 +00:00
if author . Valid {
2021-06-21 15:39:00 +00:00
notification . Author = author . String
2021-06-17 15:08:28 +00:00
}
2021-04-07 12:57:14 +00:00
// Restore last message
if lastMessageBytes != nil {
2021-05-29 17:05:25 +00:00
lastMessage := & common . Message { }
if err = json . Unmarshal ( lastMessageBytes , lastMessage ) ; err != nil {
return "" , nil , err
}
notification . LastMessage = lastMessage
}
// Restore message
if messageBytes != nil {
2021-04-07 12:57:14 +00:00
message := & common . Message { }
2021-05-29 17:05:25 +00:00
if err = json . Unmarshal ( messageBytes , message ) ; err != nil {
2021-04-07 12:57:14 +00:00
return "" , nil , err
}
2021-05-29 17:05:25 +00:00
notification . Message = message
2021-04-07 12:57:14 +00:00
}
2021-07-15 20:21:44 +00:00
// Restore reply message
if replyMessageBytes != nil {
replyMessage := & common . Message { }
if err = json . Unmarshal ( replyMessageBytes , replyMessage ) ; err != nil {
return "" , nil , err
}
notification . ReplyMessage = replyMessage
}
2021-04-07 12:57:14 +00:00
notifications = append ( notifications , notification )
}
return latestCursor , notifications , nil
}
2022-08-31 14:41:58 +00:00
2022-11-10 13:18:50 +00:00
type ActivityCenterQueryParamsRead uint
2022-08-31 14:41:58 +00:00
const (
2022-11-10 13:18:50 +00:00
ActivityCenterQueryParamsReadRead = iota + 1
ActivityCenterQueryParamsReadUnread
ActivityCenterQueryParamsReadAll
2022-08-31 14:41:58 +00:00
)
type activityCenterQueryParams struct {
cursor string
limit uint64
ids [ ] types . HexBytes
chatID string
author string
2022-11-10 13:18:50 +00:00
read ActivityCenterQueryParamsRead
2022-08-31 14:41:58 +00:00
activityCenterType ActivityCenterType
}
func ( db sqlitePersistence ) buildActivityCenterQuery ( tx * sql . Tx , params activityCenterQueryParams ) ( string , [ ] * ActivityCenterNotification , error ) {
2021-04-07 12:57:14 +00:00
var args [ ] interface { }
2021-11-25 15:21:42 +00:00
2022-08-31 14:41:58 +00:00
var cursorWhere , inQueryWhere , inChatWhere , fromAuthorWhere , ofTypeWhere , readWhere string
cursor := params . cursor
ids := params . ids
author := params . author
activityCenterType := params . activityCenterType
limit := params . limit
chatID := params . chatID
read := params . read
2021-11-25 15:21:42 +00:00
2021-04-07 12:57:14 +00:00
if cursor != "" {
cursorWhere = "AND cursor <= ?" //nolint: goconst
args = append ( args , cursor )
}
if len ( ids ) != 0 {
inVector := strings . Repeat ( "?, " , len ( ids ) - 1 ) + "?"
inQueryWhere = fmt . Sprintf ( " AND a.id IN (%s)" , inVector )
for _ , id := range ids {
args = append ( args , id )
}
}
2022-08-31 14:41:58 +00:00
switch read {
2022-11-10 13:18:50 +00:00
case ActivityCenterQueryParamsReadRead :
2022-08-31 14:41:58 +00:00
readWhere = "AND a.read = 1"
2022-11-10 13:18:50 +00:00
case ActivityCenterQueryParamsReadUnread :
2022-08-31 14:41:58 +00:00
readWhere = "AND NOT(a.read)"
}
2021-08-23 14:23:55 +00:00
if chatID != "" {
inChatWhere = "AND a.chat_id = ?" //nolint: goconst
args = append ( args , chatID )
}
2021-11-25 15:21:42 +00:00
if author != "" {
fromAuthorWhere = " AND author = ?"
args = append ( args , author )
}
if activityCenterType != ActivityCenterNotificationNoType {
ofTypeWhere = " AND notification_type = ?"
args = append ( args , activityCenterType )
}
2021-04-07 12:57:14 +00:00
query := fmt . Sprintf ( // nolint: gosec
`
SELECT
a . id ,
a . timestamp ,
a . notification_type ,
a . chat_id ,
2022-10-25 22:06:20 +00:00
a . community_id ,
a . membership_status ,
2021-04-07 12:57:14 +00:00
a . read ,
a . accepted ,
a . dismissed ,
2021-05-29 17:05:25 +00:00
a . message ,
2021-04-07 12:57:14 +00:00
c . last_message ,
2021-07-15 20:21:44 +00:00
a . reply_message ,
2022-08-31 14:41:58 +00:00
a . contact_verification_status ,
2021-04-07 12:57:14 +00:00
c . name ,
2021-06-17 15:08:28 +00:00
a . author ,
2021-04-07 12:57:14 +00:00
substr ( ' 0000000000000000000000000000000000000000000000000000000000000000 ' || a . timestamp , - 64 , 64 ) || a . id as cursor
FROM activity_center_notifications a
LEFT JOIN chats c
ON
c . id = a . chat_id
WHERE NOT a . dismissed AND NOT a . accepted
% s
% s
2021-08-23 14:23:55 +00:00
% s
2021-11-25 15:21:42 +00:00
% s
% s
2022-08-31 14:41:58 +00:00
% s
ORDER BY cursor DESC ` , cursorWhere , inQueryWhere , inChatWhere , fromAuthorWhere , ofTypeWhere , readWhere )
2021-11-25 15:21:42 +00:00
2021-04-07 12:57:14 +00:00
if limit != 0 {
args = append ( args , limit )
query += ` LIMIT ? `
}
rows , err := tx . Query ( query , args ... )
if err != nil {
return "" , nil , err
}
return db . unmarshalActivityCenterNotificationRows ( rows )
}
2021-12-02 14:23:02 +00:00
func ( db sqlitePersistence ) runActivityCenterIDQuery ( query string ) ( [ ] [ ] byte , error ) {
rows , err := db . db . Query ( query )
if err != nil {
return nil , err
}
var ids [ ] [ ] byte
for rows . Next ( ) {
var id [ ] byte
err = rows . Scan ( & id )
if err != nil {
return nil , err
}
ids = append ( ids , id )
}
return ids , nil
}
func ( db sqlitePersistence ) GetNotReadActivityCenterNotificationIds ( ) ( [ ] [ ] byte , error ) {
return db . runActivityCenterIDQuery ( "SELECT a.id FROM activity_center_notifications a WHERE NOT a.read" )
}
func ( db sqlitePersistence ) GetToProcessActivityCenterNotificationIds ( ) ( [ ] [ ] byte , error ) {
return db . runActivityCenterIDQuery ( "SELECT a.id FROM activity_center_notifications a WHERE NOT a.dismissed AND NOT a.accepted" )
}
2021-12-07 14:34:43 +00:00
func ( db sqlitePersistence ) HasPendingNotificationsForChat ( chatID string ) ( bool , error ) {
2021-12-10 14:34:16 +00:00
rows , err := db . db . Query ( "SELECT 1 FROM activity_center_notifications a WHERE a.chat_id = ? AND NOT a.dismissed AND NOT a.accepted" , chatID )
2021-12-07 14:34:43 +00:00
if err != nil {
return false , err
}
2022-02-23 11:09:46 +00:00
result := false
if rows . Next ( ) {
result = true
rows . Close ( )
}
return result , nil
2021-12-07 14:34:43 +00:00
}
2021-12-02 14:23:02 +00:00
func ( db sqlitePersistence ) GetActivityCenterNotificationsByID ( ids [ ] types . HexBytes ) ( [ ] * ActivityCenterNotification , error ) {
idsArgs := make ( [ ] interface { } , 0 , len ( ids ) )
for _ , id := range ids {
idsArgs = append ( idsArgs , id )
}
inVector := strings . Repeat ( "?, " , len ( ids ) - 1 ) + "?"
rows , err := db . db . Query ( "SELECT a.id, a.read, a.accepted, a.dismissed FROM activity_center_notifications a WHERE a.id IN (" + inVector + ")" , idsArgs ... ) // nolint: gosec
if err != nil {
return nil , err
}
var notifications [ ] * ActivityCenterNotification
for rows . Next ( ) {
notification := & ActivityCenterNotification { }
err := rows . Scan (
& notification . ID ,
& notification . Read ,
& notification . Accepted ,
& notification . Dismissed )
if err != nil {
return nil , err
}
notifications = append ( notifications , notification )
}
return notifications , nil
}
2022-01-18 16:31:34 +00:00
func ( db sqlitePersistence ) GetActivityCenterNotificationByID ( id types . HexBytes ) ( * ActivityCenterNotification , error ) {
row := db . db . QueryRow ( `
2022-06-13 10:57:51 +00:00
SELECT
a . id ,
a . timestamp ,
a . notification_type ,
a . chat_id ,
2022-10-25 22:06:20 +00:00
a . community_id ,
a . membership_status ,
2022-06-13 10:57:51 +00:00
a . read ,
a . accepted ,
a . dismissed ,
a . message ,
c . last_message ,
a . reply_message ,
2022-08-31 14:41:58 +00:00
a . contact_verification_status ,
2022-06-13 10:57:51 +00:00
c . name ,
a . author
FROM activity_center_notifications a
LEFT JOIN chats c
ON
c . id = a . chat_id
WHERE a . id = ? ` , id )
notification , err := db . unmarshalActivityCenterNotificationRow ( row )
if err == sql . ErrNoRows {
return nil , nil
}
return notification , err
2022-01-18 16:31:34 +00:00
}
2022-08-31 14:41:58 +00:00
func ( db sqlitePersistence ) UnreadActivityCenterNotifications ( cursor string , limit uint64 , activityType ActivityCenterType ) ( string , [ ] * ActivityCenterNotification , error ) {
params := activityCenterQueryParams {
activityCenterType : activityType ,
cursor : cursor ,
limit : limit ,
2022-11-10 13:18:50 +00:00
read : ActivityCenterQueryParamsReadUnread ,
2022-08-31 14:41:58 +00:00
}
return db . activityCenterNotifications ( params )
}
func ( db sqlitePersistence ) ReadActivityCenterNotifications ( cursor string , limit uint64 , activityType ActivityCenterType ) ( string , [ ] * ActivityCenterNotification , error ) {
params := activityCenterQueryParams {
activityCenterType : activityType ,
cursor : cursor ,
limit : limit ,
2022-11-10 13:18:50 +00:00
read : ActivityCenterQueryParamsReadRead ,
}
return db . activityCenterNotifications ( params )
}
func ( db sqlitePersistence ) ActivityCenterNotificationsBy ( cursor string , limit uint64 , activityType ActivityCenterType , readType ActivityCenterQueryParamsRead ) ( string , [ ] * ActivityCenterNotification , error ) {
params := activityCenterQueryParams {
activityCenterType : activityType ,
cursor : cursor ,
limit : limit ,
read : readType ,
2022-08-31 14:41:58 +00:00
}
return db . activityCenterNotifications ( params )
}
func ( db sqlitePersistence ) activityCenterNotifications ( params activityCenterQueryParams ) ( string , [ ] * ActivityCenterNotification , error ) {
2021-04-07 12:57:14 +00:00
var tx * sql . Tx
var err error
// We fetch limit + 1 to check for pagination
2022-08-31 14:41:58 +00:00
nonIncrementedLimit := params . limit
incrementedLimit := int ( params . limit ) + 1
2021-04-07 12:57:14 +00:00
tx , err = db . db . BeginTx ( context . Background ( ) , & sql . TxOptions { } )
if err != nil {
return "" , nil , err
}
defer func ( ) {
if err == nil {
err = tx . Commit ( )
return
}
// don't shadow original error
_ = tx . Rollback ( )
} ( )
2022-08-31 14:41:58 +00:00
params . limit = uint64 ( incrementedLimit )
latestCursor , notifications , err := db . buildActivityCenterQuery ( tx , params )
2021-04-07 12:57:14 +00:00
if err != nil {
return "" , nil , err
}
if len ( notifications ) == incrementedLimit {
2022-08-31 14:41:58 +00:00
notifications = notifications [ 0 : nonIncrementedLimit ]
2021-04-07 12:57:14 +00:00
} else {
latestCursor = ""
}
return latestCursor , notifications , nil
}
2022-08-31 14:41:58 +00:00
func ( db sqlitePersistence ) ActivityCenterNotifications ( currCursor string , limit uint64 ) ( string , [ ] * ActivityCenterNotification , error ) {
params := activityCenterQueryParams {
cursor : currCursor ,
limit : limit ,
}
return db . activityCenterNotifications ( params )
}
2021-04-07 12:57:14 +00:00
func ( db sqlitePersistence ) DismissAllActivityCenterNotifications ( ) error {
2021-12-07 14:34:43 +00:00
_ , err := db . db . Exec ( ` UPDATE activity_center_notifications SET read = 1, dismissed = 1 WHERE NOT dismissed AND NOT accepted ` )
2021-04-07 12:57:14 +00:00
return err
}
2021-12-06 12:44:40 +00:00
func ( db sqlitePersistence ) DismissAllActivityCenterNotificationsFromUser ( userPublicKey string ) error {
2021-12-07 14:34:43 +00:00
_ , err := db . db . Exec ( ` UPDATE activity_center_notifications SET read = 1, dismissed = 1 WHERE NOT dismissed AND NOT accepted AND author = ? ` , userPublicKey )
2021-12-06 12:44:40 +00:00
return err
}
2021-04-07 12:57:14 +00:00
func ( db sqlitePersistence ) DismissActivityCenterNotifications ( ids [ ] types . HexBytes ) error {
idsArgs := make ( [ ] interface { } , 0 , len ( ids ) )
for _ , id := range ids {
idsArgs = append ( idsArgs , id )
}
inVector := strings . Repeat ( "?, " , len ( ids ) - 1 ) + "?"
2021-12-07 14:34:43 +00:00
query := "UPDATE activity_center_notifications SET read = 1, dismissed = 1 WHERE id IN (" + inVector + ")" // nolint: gosec
2021-04-07 12:57:14 +00:00
_ , err := db . db . Exec ( query , idsArgs ... )
return err
}
2022-04-04 01:02:40 +00:00
func ( db sqlitePersistence ) DismissAllActivityCenterNotificationsFromCommunity ( communityID string ) error {
chatIDs , err := db . AllChatIDsByCommunity ( communityID )
if err != nil {
return err
}
chatIDsCount := len ( chatIDs )
if chatIDsCount == 0 {
return nil
}
chatIDsArgs := make ( [ ] interface { } , 0 , chatIDsCount )
for _ , chatID := range chatIDs {
chatIDsArgs = append ( chatIDsArgs , chatID )
}
inVector := strings . Repeat ( "?, " , chatIDsCount - 1 ) + "?"
query := "UPDATE activity_center_notifications SET read = 1, dismissed = 1 WHERE chat_id IN (" + inVector + ")" // nolint: gosec
_ , err = db . db . Exec ( query , chatIDsArgs ... )
return err
}
2022-04-06 17:01:24 +00:00
func ( db sqlitePersistence ) DismissAllActivityCenterNotificationsFromChatID ( chatID string ) error {
2022-01-18 16:31:34 +00:00
// We exclude notifications related to contacts, since those we don't want to be cleared
_ , err := db . db . Exec ( `
UPDATE activity_center_notifications SET read = 1 , dismissed = 1
WHERE
NOT dismissed
AND NOT accepted
AND chat_id = ?
AND notification_type != ?
` , chatID , ActivityCenterNotificationTypeContactRequest )
2022-04-06 17:01:24 +00:00
return err
}
2021-04-07 12:57:14 +00:00
func ( db sqlitePersistence ) AcceptAllActivityCenterNotifications ( ) ( [ ] * ActivityCenterNotification , error ) {
var tx * sql . Tx
var err error
tx , err = db . db . BeginTx ( context . Background ( ) , & sql . TxOptions { } )
if err != nil {
return nil , err
}
defer func ( ) {
if err == nil {
err = tx . Commit ( )
return
}
// don't shadow original error
_ = tx . Rollback ( )
} ( )
2022-08-31 14:41:58 +00:00
params := activityCenterQueryParams {
activityCenterType : ActivityCenterNotificationNoType ,
}
_ , notifications , err := db . buildActivityCenterQuery ( tx , params )
2021-04-07 12:57:14 +00:00
2021-12-07 14:34:43 +00:00
_ , err = tx . Exec ( ` UPDATE activity_center_notifications SET read = 1, accepted = 1 WHERE NOT accepted AND NOT dismissed ` )
2021-04-07 12:57:14 +00:00
if err != nil {
return nil , err
}
return notifications , nil
}
func ( db sqlitePersistence ) AcceptActivityCenterNotifications ( ids [ ] types . HexBytes ) ( [ ] * ActivityCenterNotification , error ) {
var tx * sql . Tx
var err error
tx , err = db . db . BeginTx ( context . Background ( ) , & sql . TxOptions { } )
if err != nil {
return nil , err
}
defer func ( ) {
if err == nil {
err = tx . Commit ( )
return
}
// don't shadow original error
_ = tx . Rollback ( )
} ( )
2022-08-31 14:41:58 +00:00
params := activityCenterQueryParams {
ids : ids ,
activityCenterType : ActivityCenterNotificationNoType ,
}
_ , notifications , err := db . buildActivityCenterQuery ( tx , params )
2021-04-07 12:57:14 +00:00
if err != nil {
return nil , err
}
idsArgs := make ( [ ] interface { } , 0 , len ( ids ) )
for _ , id := range ids {
idsArgs = append ( idsArgs , id )
}
inVector := strings . Repeat ( "?, " , len ( ids ) - 1 ) + "?"
2021-12-07 14:34:43 +00:00
query := "UPDATE activity_center_notifications SET read = 1, accepted = 1 WHERE id IN (" + inVector + ")" // nolint: gosec
2021-04-07 12:57:14 +00:00
_ , err = tx . Exec ( query , idsArgs ... )
return notifications , err
}
2022-01-18 16:31:34 +00:00
func ( db sqlitePersistence ) UpdateActivityCenterNotificationMessage ( id types . HexBytes , message * common . Message ) error {
encodedMessage , err := json . Marshal ( message )
if err != nil {
return err
}
_ , err = db . db . Exec ( ` UPDATE activity_center_notifications SET message = ? WHERE id = ? ` , encodedMessage , id )
return err
}
2022-08-31 14:41:58 +00:00
func ( db sqlitePersistence ) UpdateActivityCenterNotificationContactVerificationStatus ( id types . HexBytes , status verification . RequestStatus ) error {
2022-10-24 11:33:47 +00:00
_ , err := db . db . Exec ( ` UPDATE activity_center_notifications SET contact_verification_status = ? WHERE id = ? ` , status , id )
return err
2022-08-31 14:41:58 +00:00
}
2022-10-28 09:51:54 +00:00
func ( db sqlitePersistence ) UpdateActivityCenterNotificationFields ( id types . HexBytes , message * common . Message , replyMessage * common . Message , status verification . RequestStatus ) error {
encodedMessage , err := json . Marshal ( message )
if err != nil {
return err
}
encodedReplyMessage , err := json . Marshal ( replyMessage )
if err != nil {
return err
}
_ , err = db . db . Exec ( ` UPDATE activity_center_notifications SET message = ?, reply_message = ?, contact_verification_status = ? WHERE id = ? ` , encodedMessage , encodedReplyMessage , status , id )
return err
}
2021-11-25 15:21:42 +00:00
func ( db sqlitePersistence ) AcceptActivityCenterNotificationsForInvitesFromUser ( userPublicKey string ) ( [ ] * ActivityCenterNotification , error ) {
var tx * sql . Tx
var err error
tx , err = db . db . BeginTx ( context . Background ( ) , & sql . TxOptions { } )
if err != nil {
return nil , err
}
defer func ( ) {
if err == nil {
err = tx . Commit ( )
return
}
// don't shadow original error
_ = tx . Rollback ( )
} ( )
2022-08-31 14:41:58 +00:00
params := activityCenterQueryParams {
author : userPublicKey ,
activityCenterType : ActivityCenterNotificationTypeNewPrivateGroupChat ,
}
_ , notifications , err := db . buildActivityCenterQuery ( tx , params )
2021-11-25 15:21:42 +00:00
if err != nil {
return nil , err
}
2021-12-07 14:34:43 +00:00
_ , err = tx . Exec ( ` UPDATE activity_center_notifications SET read = 1, accepted = 1 WHERE NOT accepted AND NOT dismissed AND author = ? AND notification_type = ? ` , userPublicKey , ActivityCenterNotificationTypeNewPrivateGroupChat )
2021-11-25 15:21:42 +00:00
if err != nil {
return nil , err
}
return notifications , nil
}
2021-04-07 12:57:14 +00:00
func ( db sqlitePersistence ) MarkAllActivityCenterNotificationsRead ( ) error {
_ , err := db . db . Exec ( ` UPDATE activity_center_notifications SET read = 1 WHERE NOT read ` )
return err
}
2021-06-11 16:47:53 +00:00
func ( db sqlitePersistence ) MarkActivityCenterNotificationsRead ( ids [ ] types . HexBytes ) error {
idsArgs := make ( [ ] interface { } , 0 , len ( ids ) )
for _ , id := range ids {
idsArgs = append ( idsArgs , id )
}
inVector := strings . Repeat ( "?, " , len ( ids ) - 1 ) + "?"
query := "UPDATE activity_center_notifications SET read = 1 WHERE id IN (" + inVector + ")" // nolint: gosec
_ , err := db . db . Exec ( query , idsArgs ... )
return err
}
2021-09-24 10:57:15 +00:00
func ( db sqlitePersistence ) MarkActivityCenterNotificationsUnread ( ids [ ] types . HexBytes ) error {
idsArgs := make ( [ ] interface { } , 0 , len ( ids ) )
for _ , id := range ids {
idsArgs = append ( idsArgs , id )
}
inVector := strings . Repeat ( "?, " , len ( ids ) - 1 ) + "?"
query := "UPDATE activity_center_notifications SET read = 0 WHERE id IN (" + inVector + ")" // nolint: gosec
_ , err := db . db . Exec ( query , idsArgs ... )
return err
}
2021-04-07 12:57:14 +00:00
func ( db sqlitePersistence ) UnreadActivityCenterNotificationsCount ( ) ( uint64 , error ) {
var count uint64
2021-07-06 16:07:41 +00:00
err := db . db . QueryRow ( ` SELECT COUNT(1) FROM activity_center_notifications WHERE NOT read AND NOT dismissed AND NOT accepted ` ) . Scan ( & count )
2021-04-07 12:57:14 +00:00
return count , err
}
2022-06-13 10:57:51 +00:00
func ( db sqlitePersistence ) ActiveContactRequestNotification ( contactID string ) ( * ActivityCenterNotification , error ) {
row := db . db . QueryRow ( `
SELECT
a . id ,
a . timestamp ,
a . notification_type ,
a . chat_id ,
2022-10-25 22:06:20 +00:00
a . community_id ,
a . membership_status ,
2022-06-13 10:57:51 +00:00
a . read ,
a . accepted ,
a . dismissed ,
a . message ,
c . last_message ,
a . reply_message ,
2022-08-31 14:41:58 +00:00
a . contact_verification_status ,
2022-06-13 10:57:51 +00:00
c . name ,
a . author
FROM activity_center_notifications a
LEFT JOIN chats c
ON
c . id = a . chat_id
WHERE NOT dismissed AND NOT a . accepted AND notification_type = ? AND author = ? ` , ActivityCenterNotificationTypeContactRequest , contactID )
notification , err := db . unmarshalActivityCenterNotificationRow ( row )
if err == sql . ErrNoRows {
return nil , nil
}
return notification , err
}
func ( db sqlitePersistence ) RemoveAllContactRequestActivityCenterNotifications ( chatID string ) error {
_ , err := db . db . Exec ( `
2022-08-31 14:41:58 +00:00
DELETE FROM activity_center_notifications
2022-06-13 10:57:51 +00:00
WHERE
chat_id = ?
AND notification_type = ?
` , chatID , ActivityCenterNotificationTypeContactRequest )
return err
}