status-go/protocol/messenger_response.go

399 lines
12 KiB
Go
Raw Normal View History

package protocol
import (
2021-01-11 10:32:51 +00:00
"encoding/json"
2022-01-17 03:42:11 +00:00
"github.com/status-im/status-go/services/browsers"
Anon Metrics Broadcast (#2198) * Protobufs and adapters * Added basic anon metric service and config init * Added fibonacci interval incrementer * Added basic Client.Start func and integrated interval incrementer * Added new processed field to app metrics table * Added id column to app metrics table * Added migration clean up * Added appmetrics GetUnprocessed and SetToProcessedByIDs and tests There was a wierd bug where metrics in the db that did not explicitly insert a value would be NULL, so could not be found by . In addition I've added a new primary id field to the app_metrics table so that updates could be done against very specific metric rows. * Updated adaptors and db to handle proto_id I need a way to distinguish individual metric items from each other so that I can ignore the ones that have been seen before. * Moved incrementer into dedicated file * Resolve incrementer test fail * Finalised the main loop functionality * Implemented delete loop framework * Updated adaptors file name * Added delete loop delay and quit, and tweak on RawMessage gen * Completed delete loop logic * Added DBLock to prevent deletion during mainLoop * Added postgres DB connection, integrated into anonmetrics.Server * Removed proto_id from SQL migration and model * Integrated postgres with Server and updated adaptors * Function name update * Added sample config files for client and server * Fixes and testing for low level e2e * make generate * Fix lint * Fix for receiving an anonMetricBatch not in server mode * Postgres test fixes * Tidy up, make vendor and make generate * delinting * Fixing database tests * Attempted fix of does: cannot open `does' (No such file or directory) not: cannot open `not' (No such file or directory) exist: cannot open `exist' (No such file or directory) error on sql resource loas * Moved all anon metric postgres migration logic and sources into a the protocol/anonmetrics package or sub packages. I don't know if this will fix the does: cannot open `does' (No such file or directory) not: cannot open `not' (No such file or directory) exist: cannot open `exist' (No such file or directory) error that happens in Jenkins but this could work * Lint for the lint god * Why doesn't the linter list all its problems at once? * test tweaks * Fix for wakuV2 change * DB reset change * Fix for postgres db migrations fails * More robust implementation of postgres test setup and teardown * Added block for anon metrics functionality * Version Bump to 0.84.0 * Added test to check anon metrics broadcast is deactivated * Protobufs and adapters * Added basic anon metric service and config init * Added new processed field to app metrics table * Added id column to app metrics table * Added migration clean up * Added appmetrics GetUnprocessed and SetToProcessedByIDs and tests There was a wierd bug where metrics in the db that did not explicitly insert a value would be NULL, so could not be found by . In addition I've added a new primary id field to the app_metrics table so that updates could be done against very specific metric rows. * Updated adaptors and db to handle proto_id I need a way to distinguish individual metric items from each other so that I can ignore the ones that have been seen before. * Added postgres DB connection, integrated into anonmetrics.Server * Removed proto_id from SQL migration and model * Integrated postgres with Server and updated adaptors * Added sample config files for client and server * Fix lint * Fix for receiving an anonMetricBatch not in server mode * Postgres test fixes * Tidy up, make vendor and make generate * Moved all anon metric postgres migration logic and sources into a the protocol/anonmetrics package or sub packages. I don't know if this will fix the does: cannot open `does' (No such file or directory) not: cannot open `not' (No such file or directory) exist: cannot open `exist' (No such file or directory) error that happens in Jenkins but this could work
2021-09-01 12:02:18 +00:00
"github.com/status-im/status-go/appmetrics"
"github.com/status-im/status-go/protocol/common"
"github.com/status-im/status-go/protocol/communities"
"github.com/status-im/status-go/protocol/encryption/multidevice"
localnotifications "github.com/status-im/status-go/services/local-notifications"
"github.com/status-im/status-go/services/mailservers"
)
2021-08-20 14:26:13 +00:00
type RemovedMessage struct {
ChatID string `json:"chatId"`
MessageID string `json:"messageId"`
}
2022-02-10 10:00:59 +00:00
type ClearedHistory struct {
ChatID string `json:"chatId"`
ClearedAt uint64 `json:"clearedAt"`
}
type MessengerResponse struct {
2021-01-11 10:32:51 +00:00
Contacts []*Contact
Installations []*multidevice.Installation
EmojiReactions []*EmojiReaction
Invitations []*GroupChatInvitation
CommunityChanges []*communities.CommunityChanges
RequestsToJoinCommunity []*communities.RequestToJoin
Anon Metrics Broadcast (#2198) * Protobufs and adapters * Added basic anon metric service and config init * Added fibonacci interval incrementer * Added basic Client.Start func and integrated interval incrementer * Added new processed field to app metrics table * Added id column to app metrics table * Added migration clean up * Added appmetrics GetUnprocessed and SetToProcessedByIDs and tests There was a wierd bug where metrics in the db that did not explicitly insert a value would be NULL, so could not be found by . In addition I've added a new primary id field to the app_metrics table so that updates could be done against very specific metric rows. * Updated adaptors and db to handle proto_id I need a way to distinguish individual metric items from each other so that I can ignore the ones that have been seen before. * Moved incrementer into dedicated file * Resolve incrementer test fail * Finalised the main loop functionality * Implemented delete loop framework * Updated adaptors file name * Added delete loop delay and quit, and tweak on RawMessage gen * Completed delete loop logic * Added DBLock to prevent deletion during mainLoop * Added postgres DB connection, integrated into anonmetrics.Server * Removed proto_id from SQL migration and model * Integrated postgres with Server and updated adaptors * Function name update * Added sample config files for client and server * Fixes and testing for low level e2e * make generate * Fix lint * Fix for receiving an anonMetricBatch not in server mode * Postgres test fixes * Tidy up, make vendor and make generate * delinting * Fixing database tests * Attempted fix of does: cannot open `does' (No such file or directory) not: cannot open `not' (No such file or directory) exist: cannot open `exist' (No such file or directory) error on sql resource loas * Moved all anon metric postgres migration logic and sources into a the protocol/anonmetrics package or sub packages. I don't know if this will fix the does: cannot open `does' (No such file or directory) not: cannot open `not' (No such file or directory) exist: cannot open `exist' (No such file or directory) error that happens in Jenkins but this could work * Lint for the lint god * Why doesn't the linter list all its problems at once? * test tweaks * Fix for wakuV2 change * DB reset change * Fix for postgres db migrations fails * More robust implementation of postgres test setup and teardown * Added block for anon metrics functionality * Version Bump to 0.84.0 * Added test to check anon metrics broadcast is deactivated * Protobufs and adapters * Added basic anon metric service and config init * Added new processed field to app metrics table * Added id column to app metrics table * Added migration clean up * Added appmetrics GetUnprocessed and SetToProcessedByIDs and tests There was a wierd bug where metrics in the db that did not explicitly insert a value would be NULL, so could not be found by . In addition I've added a new primary id field to the app_metrics table so that updates could be done against very specific metric rows. * Updated adaptors and db to handle proto_id I need a way to distinguish individual metric items from each other so that I can ignore the ones that have been seen before. * Added postgres DB connection, integrated into anonmetrics.Server * Removed proto_id from SQL migration and model * Integrated postgres with Server and updated adaptors * Added sample config files for client and server * Fix lint * Fix for receiving an anonMetricBatch not in server mode * Postgres test fixes * Tidy up, make vendor and make generate * Moved all anon metric postgres migration logic and sources into a the protocol/anonmetrics package or sub packages. I don't know if this will fix the does: cannot open `does' (No such file or directory) not: cannot open `not' (No such file or directory) exist: cannot open `exist' (No such file or directory) error that happens in Jenkins but this could work
2021-09-01 12:02:18 +00:00
AnonymousMetrics []*appmetrics.AppMetric
2021-01-11 10:32:51 +00:00
Mailservers []mailservers.Mailserver
2022-01-17 03:42:11 +00:00
Bookmarks []*browsers.Bookmark
2021-01-11 10:32:51 +00:00
// notifications a list of notifications derived from messenger events
// that are useful to notify the user about
notifications map[string]*localnotifications.Notification
chats map[string]*Chat
removedChats map[string]bool
2021-08-20 14:26:13 +00:00
removedMessages map[string]*RemovedMessage
communities map[string]*communities.Community
activityCenterNotifications map[string]*ActivityCenterNotification
2021-06-03 13:11:55 +00:00
messages map[string]*common.Message
pinMessages map[string]*common.PinMessage
currentStatus *UserStatus
statusUpdates map[string]UserStatus
2022-02-10 10:00:59 +00:00
clearedHistories map[string]*ClearedHistory
2021-01-11 10:32:51 +00:00
}
func (r *MessengerResponse) MarshalJSON() ([]byte, error) {
responseItem := struct {
Chats []*Chat `json:"chats,omitempty"`
RemovedChats []string `json:"removedChats,omitempty"`
2021-08-20 14:26:13 +00:00
RemovedMessages []*RemovedMessage `json:"removedMessages,omitempty"`
2021-01-11 10:32:51 +00:00
Messages []*common.Message `json:"messages,omitempty"`
Contacts []*Contact `json:"contacts,omitempty"`
Installations []*multidevice.Installation `json:"installations,omitempty"`
2021-03-25 15:15:22 +00:00
PinMessages []*common.PinMessage `json:"pinMessages,omitempty"`
2021-01-11 10:32:51 +00:00
EmojiReactions []*EmojiReaction `json:"emojiReactions,omitempty"`
Invitations []*GroupChatInvitation `json:"invitations,omitempty"`
CommunityChanges []*communities.CommunityChanges `json:"communityChanges,omitempty"`
RequestsToJoinCommunity []*communities.RequestToJoin `json:"requestsToJoinCommunity,omitempty"`
Mailservers []mailservers.Mailserver `json:"mailservers,omitempty"`
2022-01-17 03:42:11 +00:00
Bookmarks []*browsers.Bookmark `json:"bookmarks,omitempty"`
2022-02-10 10:00:59 +00:00
ClearedHistories []*ClearedHistory `json:"clearedHistories,omitempty"`
// Notifications a list of notifications derived from messenger events
// that are useful to notify the user about
Notifications []*localnotifications.Notification `json:"notifications"`
Communities []*communities.Community `json:"communities,omitempty"`
ActivityCenterNotifications []*ActivityCenterNotification `json:"activityCenterNotifications,omitempty"`
CurrentStatus *UserStatus `json:"currentStatus,omitempty"`
StatusUpdates []UserStatus `json:"statusUpdates,omitempty"`
2021-01-11 10:32:51 +00:00
}{
Contacts: r.Contacts,
Installations: r.Installations,
EmojiReactions: r.EmojiReactions,
Invitations: r.Invitations,
CommunityChanges: r.CommunityChanges,
RequestsToJoinCommunity: r.RequestsToJoinCommunity,
Mailservers: r.Mailservers,
2022-01-17 03:42:11 +00:00
Bookmarks: r.Bookmarks,
CurrentStatus: r.currentStatus,
2021-01-11 10:32:51 +00:00
}
2021-06-03 13:11:55 +00:00
responseItem.Messages = r.Messages()
responseItem.Notifications = r.Notifications()
2021-01-11 10:32:51 +00:00
responseItem.Chats = r.Chats()
responseItem.Communities = r.Communities()
responseItem.RemovedChats = r.RemovedChats()
responseItem.RemovedMessages = r.RemovedMessages()
2022-02-10 10:00:59 +00:00
responseItem.ClearedHistories = r.ClearedHistories()
responseItem.ActivityCenterNotifications = r.ActivityCenterNotifications()
responseItem.PinMessages = r.PinMessages()
responseItem.StatusUpdates = r.StatusUpdates()
2021-01-11 10:32:51 +00:00
return json.Marshal(responseItem)
}
2021-01-11 10:32:51 +00:00
func (r *MessengerResponse) Chats() []*Chat {
var chats []*Chat
for _, chat := range r.chats {
chats = append(chats, chat)
}
return chats
}
func (r *MessengerResponse) RemovedChats() []string {
var chats []string
for chatID := range r.removedChats {
chats = append(chats, chatID)
}
return chats
}
2021-08-20 14:26:13 +00:00
func (r *MessengerResponse) RemovedMessages() []*RemovedMessage {
var messages []*RemovedMessage
for messageID := range r.removedMessages {
2021-08-20 14:26:13 +00:00
messages = append(messages, r.removedMessages[messageID])
}
return messages
}
2022-02-10 10:00:59 +00:00
func (r *MessengerResponse) ClearedHistories() []*ClearedHistory {
var clearedHistories []*ClearedHistory
for chatID := range r.clearedHistories {
clearedHistories = append(clearedHistories, r.clearedHistories[chatID])
}
return clearedHistories
}
2021-01-11 10:32:51 +00:00
func (r *MessengerResponse) Communities() []*communities.Community {
var communities []*communities.Community
for _, c := range r.communities {
communities = append(communities, c)
}
return communities
}
func (r *MessengerResponse) Notifications() []*localnotifications.Notification {
var notifications []*localnotifications.Notification
for _, n := range r.notifications {
notifications = append(notifications, n)
}
return notifications
}
func (r *MessengerResponse) PinMessages() []*common.PinMessage {
var pinMessages []*common.PinMessage
for _, pm := range r.pinMessages {
pinMessages = append(pinMessages, pm)
}
return pinMessages
}
func (r *MessengerResponse) StatusUpdates() []UserStatus {
var userStatus []UserStatus
for pk, s := range r.statusUpdates {
s.PublicKey = pk
userStatus = append(userStatus, s)
}
return userStatus
}
2021-01-11 10:32:51 +00:00
func (r *MessengerResponse) IsEmpty() bool {
return len(r.chats)+
2021-06-03 13:11:55 +00:00
len(r.messages)+
len(r.pinMessages)+
2021-01-11 10:32:51 +00:00
len(r.Contacts)+
2022-01-17 03:42:11 +00:00
len(r.Bookmarks)+
2022-02-10 10:00:59 +00:00
len(r.clearedHistories)+
2021-01-11 10:32:51 +00:00
len(r.Installations)+
len(r.Invitations)+
len(r.EmojiReactions)+
len(r.communities)+
len(r.CommunityChanges)+
len(r.removedChats)+
len(r.removedMessages)+
2021-01-11 10:32:51 +00:00
len(r.Mailservers)+
len(r.notifications)+
len(r.statusUpdates)+
len(r.activityCenterNotifications)+
len(r.RequestsToJoinCommunity) == 0 &&
r.currentStatus == nil
}
2020-12-03 17:04:38 +00:00
// Merge takes another response and appends the new Chats & new Messages and replaces
// the existing Messages & Chats if they have the same ID
2021-01-11 10:32:51 +00:00
func (r *MessengerResponse) Merge(response *MessengerResponse) error {
if len(response.Contacts)+
len(response.Installations)+
len(response.EmojiReactions)+
len(response.Invitations)+
len(response.RequestsToJoinCommunity)+
len(response.Mailservers)+
len(response.EmojiReactions)+
2022-01-17 03:42:11 +00:00
len(response.Bookmarks)+
2022-02-10 10:00:59 +00:00
len(response.clearedHistories)+
2021-01-11 10:32:51 +00:00
len(response.CommunityChanges) != 0 {
return ErrNotImplemented
}
2021-01-11 10:32:51 +00:00
r.AddChats(response.Chats())
r.AddRemovedChats(response.RemovedChats())
r.AddRemovedMessages(response.RemovedMessages())
r.AddNotifications(response.Notifications())
2021-06-03 13:11:55 +00:00
r.AddMessages(response.Messages())
2021-01-11 10:32:51 +00:00
r.AddCommunities(response.Communities())
r.AddPinMessages(response.PinMessages())
r.AddActivityCenterNotifications(response.ActivityCenterNotifications())
2020-12-03 17:04:38 +00:00
return nil
}
2021-01-11 10:32:51 +00:00
func (r *MessengerResponse) AddCommunities(communities []*communities.Community) {
for _, overrideCommunity := range communities {
r.AddCommunity(overrideCommunity)
}
}
func (r *MessengerResponse) AddCommunity(c *communities.Community) {
if r.communities == nil {
r.communities = make(map[string]*communities.Community)
}
r.communities[c.IDString()] = c
}
2022-01-17 03:42:11 +00:00
func (r *MessengerResponse) AddBookmark(bookmark *browsers.Bookmark) {
r.Bookmarks = append(r.Bookmarks, bookmark)
}
func (r *MessengerResponse) AddBookmarks(bookmarks []*browsers.Bookmark) {
for _, b := range bookmarks {
r.AddBookmark(b)
}
}
2021-01-11 10:32:51 +00:00
func (r *MessengerResponse) AddChat(c *Chat) {
if r.chats == nil {
r.chats = make(map[string]*Chat)
}
r.chats[c.ID] = c
}
func (r *MessengerResponse) AddChats(chats []*Chat) {
for _, c := range chats {
r.AddChat(c)
}
}
func (r *MessengerResponse) AddNotification(n *localnotifications.Notification) {
if r.notifications == nil {
r.notifications = make(map[string]*localnotifications.Notification)
}
r.notifications[n.ID.String()] = n
}
func (r *MessengerResponse) ClearNotifications() {
r.notifications = nil
}
func (r *MessengerResponse) AddNotifications(notifications []*localnotifications.Notification) {
for _, c := range notifications {
r.AddNotification(c)
}
}
2021-01-11 10:32:51 +00:00
func (r *MessengerResponse) AddRemovedChats(chats []string) {
for _, c := range chats {
r.AddRemovedChat(c)
}
}
func (r *MessengerResponse) AddRemovedChat(chatID string) {
if r.removedChats == nil {
r.removedChats = make(map[string]bool)
}
r.removedChats[chatID] = true
}
2021-08-20 14:26:13 +00:00
func (r *MessengerResponse) AddRemovedMessages(messages []*RemovedMessage) {
for _, m := range messages {
r.AddRemovedMessage(m)
}
}
2021-08-20 14:26:13 +00:00
func (r *MessengerResponse) AddRemovedMessage(rm *RemovedMessage) {
if r.removedMessages == nil {
2021-08-20 14:26:13 +00:00
r.removedMessages = make(map[string]*RemovedMessage)
}
2021-08-20 14:26:13 +00:00
r.removedMessages[rm.MessageID] = rm
2021-09-08 09:55:06 +00:00
// Remove original message from the map
if len(r.messages) != 0 && r.messages[rm.MessageID] != nil {
delete(r.messages, rm.MessageID)
}
}
2022-02-10 10:00:59 +00:00
func (r *MessengerResponse) AddClearedHistory(ch *ClearedHistory) {
if r.clearedHistories == nil {
r.clearedHistories = make(map[string]*ClearedHistory)
}
existingClearedHistory, ok := r.clearedHistories[ch.ChatID]
if !ok || existingClearedHistory.ClearedAt < ch.ClearedAt {
r.clearedHistories[ch.ChatID] = ch
}
}
func (r *MessengerResponse) AddActivityCenterNotifications(ns []*ActivityCenterNotification) {
for _, n := range ns {
r.AddActivityCenterNotification(n)
}
}
func (r *MessengerResponse) AddActivityCenterNotification(n *ActivityCenterNotification) {
if r.activityCenterNotifications == nil {
r.activityCenterNotifications = make(map[string]*ActivityCenterNotification)
}
r.activityCenterNotifications[n.ID.String()] = n
}
func (r *MessengerResponse) ActivityCenterNotifications() []*ActivityCenterNotification {
var ns []*ActivityCenterNotification
for _, n := range r.activityCenterNotifications {
ns = append(ns, n)
}
return ns
}
func (r *MessengerResponse) AddPinMessage(pm *common.PinMessage) {
if r.pinMessages == nil {
r.pinMessages = make(map[string]*common.PinMessage)
}
r.pinMessages[pm.ID] = pm
}
func (r *MessengerResponse) AddPinMessages(pms []*common.PinMessage) {
for _, pm := range pms {
r.AddPinMessage(pm)
}
}
2021-03-25 15:15:22 +00:00
func (r *MessengerResponse) SetCurrentStatus(status UserStatus) {
r.currentStatus = &status
}
func (r *MessengerResponse) AddStatusUpdate(upd UserStatus) {
if r.statusUpdates == nil {
r.statusUpdates = make(map[string]UserStatus)
}
r.statusUpdates[upd.PublicKey] = upd
}
2021-06-03 13:11:55 +00:00
func (r *MessengerResponse) Messages() []*common.Message {
var ms []*common.Message
for _, m := range r.messages {
ms = append(ms, m)
}
return ms
}
func (r *MessengerResponse) AddMessages(ms []*common.Message) {
for _, m := range ms {
r.AddMessage(m)
}
}
2021-03-25 15:15:22 +00:00
func (r *MessengerResponse) AddMessage(message *common.Message) {
2021-06-03 13:11:55 +00:00
if r.messages == nil {
r.messages = make(map[string]*common.Message)
}
if message.Deleted {
return
}
2021-06-03 13:11:55 +00:00
r.messages[message.ID] = message
}
func (r *MessengerResponse) SetMessages(messages []*common.Message) {
r.messages = make(map[string]*common.Message)
r.AddMessages(messages)
2021-03-25 15:15:22 +00:00
}
2021-06-03 14:09:30 +00:00
func (r *MessengerResponse) GetMessage(messageID string) *common.Message {
if r.messages == nil {
return nil
}
return r.messages[messageID]
}