github.com/status-im/status-go@v1.1.0/protocol/messenger_response.go (about)

     1  package protocol
     2  
     3  import (
     4  	"encoding/json"
     5  
     6  	"golang.org/x/exp/maps"
     7  
     8  	ensservice "github.com/status-im/status-go/services/ens"
     9  
    10  	"github.com/status-im/status-go/services/browsers"
    11  	"github.com/status-im/status-go/services/wallet"
    12  
    13  	"github.com/status-im/status-go/appmetrics"
    14  	"github.com/status-im/status-go/images"
    15  	"github.com/status-im/status-go/multiaccounts/accounts"
    16  	"github.com/status-im/status-go/multiaccounts/settings"
    17  	walletsettings "github.com/status-im/status-go/multiaccounts/settings_wallet"
    18  	"github.com/status-im/status-go/protocol/common"
    19  	"github.com/status-im/status-go/protocol/communities"
    20  	"github.com/status-im/status-go/protocol/discord"
    21  	"github.com/status-im/status-go/protocol/encryption/multidevice"
    22  	"github.com/status-im/status-go/protocol/protobuf"
    23  	"github.com/status-im/status-go/protocol/storenodes"
    24  	"github.com/status-im/status-go/protocol/verification"
    25  	localnotifications "github.com/status-im/status-go/services/local-notifications"
    26  	"github.com/status-im/status-go/services/mailservers"
    27  )
    28  
    29  type RemovedMessage struct {
    30  	ChatID    string `json:"chatId"`
    31  	MessageID string `json:"messageId"`
    32  	DeletedBy string `json:"deletedBy,omitempty"`
    33  }
    34  
    35  type ClearedHistory struct {
    36  	ChatID    string `json:"chatId"`
    37  	ClearedAt uint64 `json:"clearedAt"`
    38  }
    39  
    40  type SeenUnseenMessages struct {
    41  	ChatID            string `json:"chatId"`
    42  	Count             uint64 `json:"count"`
    43  	CountWithMentions uint64 `json:"countWithMentions"`
    44  	Seen              bool   `json:"seen"`
    45  }
    46  
    47  type MessengerResponse struct {
    48  	Contacts                      []*Contact
    49  	Invitations                   []*GroupChatInvitation
    50  	CommunityChanges              []*communities.CommunityChanges
    51  	AnonymousMetrics              []*appmetrics.AppMetric
    52  	Mailservers                   []mailservers.Mailserver
    53  	CommunityStorenodes           []storenodes.Storenode
    54  	Bookmarks                     []*browsers.Bookmark
    55  	Settings                      []*settings.SyncSettingField
    56  	IdentityImages                []images.IdentityImage
    57  	CustomizationColor            string
    58  	WatchOnlyAccounts             []*accounts.Account
    59  	Keypairs                      []*accounts.Keypair
    60  	AccountsPositions             []*accounts.Account
    61  	TokenPreferences              []walletsettings.TokenPreferences
    62  	CollectiblePreferences        []walletsettings.CollectiblePreferences
    63  	DiscordCategories             []*discord.Category
    64  	DiscordChannels               []*discord.Channel
    65  	DiscordOldestMessageTimestamp int
    66  	BackupHandled                 bool
    67  
    68  	// notifications a list of notifications derived from messenger events
    69  	// that are useful to notify the user about
    70  	installations                    map[string]*multidevice.Installation
    71  	notifications                    map[string]*localnotifications.Notification
    72  	requestsToJoinCommunity          map[string]*communities.RequestToJoin
    73  	chats                            map[string]*Chat
    74  	removedChats                     map[string]bool
    75  	removedMessages                  map[string]*RemovedMessage
    76  	deletedMessages                  map[string]string
    77  	communities                      map[string]*communities.Community
    78  	communitiesSettings              map[string]*communities.CommunitySettings
    79  	activityCenterNotifications      map[string]*ActivityCenterNotification
    80  	activityCenterState              *ActivityCenterState
    81  	messages                         map[string]*common.Message
    82  	pinMessages                      map[string]*common.PinMessage
    83  	discordMessages                  map[string]*protobuf.DiscordMessage
    84  	discordMessageAttachments        map[string]*protobuf.DiscordMessageAttachment
    85  	discordMessageAuthors            map[string]*protobuf.DiscordMessageAuthor
    86  	currentStatus                    *UserStatus
    87  	statusUpdates                    map[string]UserStatus
    88  	clearedHistories                 map[string]*ClearedHistory
    89  	verificationRequests             map[string]*verification.Request
    90  	trustStatus                      map[string]verification.TrustStatus
    91  	emojiReactions                   map[string]*EmojiReaction
    92  	savedAddresses                   map[string]*wallet.SavedAddress
    93  	ensUsernameDetails               []*ensservice.UsernameDetail
    94  	updatedProfileShowcaseContactIDs map[string]bool
    95  	seenAndUnseenMessages            map[string]*SeenUnseenMessages
    96  }
    97  
    98  func (r *MessengerResponse) MarshalJSON() ([]byte, error) {
    99  	responseItem := struct {
   100  		Chats                   []*Chat                             `json:"chats,omitempty"`
   101  		RemovedChats            []string                            `json:"removedChats,omitempty"`
   102  		RemovedMessages         []*RemovedMessage                   `json:"removedMessages,omitempty"`
   103  		DeletedMessages         map[string][]string                 `json:"deletedMessages,omitempty"`
   104  		Messages                []*common.Message                   `json:"messages,omitempty"`
   105  		Contacts                []*Contact                          `json:"contacts,omitempty"`
   106  		Installations           []*multidevice.Installation         `json:"installations,omitempty"`
   107  		PinMessages             []*common.PinMessage                `json:"pinMessages,omitempty"`
   108  		EmojiReactions          []*EmojiReaction                    `json:"emojiReactions,omitempty"`
   109  		Invitations             []*GroupChatInvitation              `json:"invitations,omitempty"`
   110  		CommunityChanges        []*communities.CommunityChanges     `json:"communityChanges,omitempty"`
   111  		RequestsToJoinCommunity []*communities.RequestToJoin        `json:"requestsToJoinCommunity,omitempty"`
   112  		Mailservers             []mailservers.Mailserver            `json:"mailservers,omitempty"`
   113  		CommunityStorenodes     []storenodes.Storenode              `json:"communityStorenodes,omitempty"`
   114  		Bookmarks               []*browsers.Bookmark                `json:"bookmarks,omitempty"`
   115  		ClearedHistories        []*ClearedHistory                   `json:"clearedHistories,omitempty"`
   116  		VerificationRequests    []*verification.Request             `json:"verificationRequests,omitempty"`
   117  		TrustStatus             map[string]verification.TrustStatus `json:"trustStatus,omitempty"`
   118  		// Notifications a list of notifications derived from messenger events
   119  		// that are useful to notify the user about
   120  		Notifications                    []*localnotifications.Notification      `json:"notifications"`
   121  		Communities                      []*communities.Community                `json:"communities,omitempty"`
   122  		CommunitiesSettings              []*communities.CommunitySettings        `json:"communitiesSettings,omitempty"`
   123  		ActivityCenterNotifications      []*ActivityCenterNotification           `json:"activityCenterNotifications,omitempty"`
   124  		ActivityCenterState              *ActivityCenterState                    `json:"activityCenterState,omitempty"`
   125  		CurrentStatus                    *UserStatus                             `json:"currentStatus,omitempty"`
   126  		StatusUpdates                    []UserStatus                            `json:"statusUpdates,omitempty"`
   127  		Settings                         []*settings.SyncSettingField            `json:"settings,omitempty"`
   128  		IdentityImages                   []images.IdentityImage                  `json:"identityImages,omitempty"`
   129  		CustomizationColor               string                                  `json:"customizationColor,omitempty"`
   130  		WatchOnlyAccounts                []*accounts.Account                     `json:"watchOnlyAccounts,omitempty"`
   131  		Keypairs                         []*accounts.Keypair                     `json:"keypairs,omitempty"`
   132  		AccountsPositions                []*accounts.Account                     `json:"accountsPositions,omitempty"`
   133  		TokenPreferences                 []walletsettings.TokenPreferences       `json:"tokenPreferences,omitempty"`
   134  		CollectiblePreferences           []walletsettings.CollectiblePreferences `json:"collectiblePreferences,omitempty"`
   135  		DiscordCategories                []*discord.Category                     `json:"discordCategories,omitempty"`
   136  		DiscordChannels                  []*discord.Channel                      `json:"discordChannels,omitempty"`
   137  		DiscordOldestMessageTimestamp    int                                     `json:"discordOldestMessageTimestamp"`
   138  		DiscordMessages                  []*protobuf.DiscordMessage              `json:"discordMessages,omitempty"`
   139  		DiscordMessageAttachments        []*protobuf.DiscordMessageAttachment    `json:"discordMessageAtachments,omitempty"`
   140  		SavedAddresses                   []*wallet.SavedAddress                  `json:"savedAddresses,omitempty"`
   141  		EnsUsernameDetails               []*ensservice.UsernameDetail            `json:"ensUsernameDetails,omitempty"`
   142  		UpdatedProfileShowcaseContactIDs []string                                `json:"updatedProfileShowcaseContactIDs,omitempty"`
   143  		SeenAndUnseenMessages            []*SeenUnseenMessages                   `json:"seenAndUnseenMessages,omitempty"`
   144  	}{
   145  		Contacts:                r.Contacts,
   146  		Installations:           r.Installations(),
   147  		Invitations:             r.Invitations,
   148  		CommunityChanges:        r.CommunityChanges,
   149  		RequestsToJoinCommunity: r.RequestsToJoinCommunity(),
   150  		Mailservers:             r.Mailservers,
   151  		CommunityStorenodes:     r.CommunityStorenodes,
   152  		Bookmarks:               r.Bookmarks,
   153  		CurrentStatus:           r.currentStatus,
   154  		Settings:                r.Settings,
   155  		IdentityImages:          r.IdentityImages,
   156  		CustomizationColor:      r.CustomizationColor,
   157  		WatchOnlyAccounts:       r.WatchOnlyAccounts,
   158  		Keypairs:                r.Keypairs,
   159  		AccountsPositions:       r.AccountsPositions,
   160  		TokenPreferences:        r.TokenPreferences,
   161  		CollectiblePreferences:  r.CollectiblePreferences,
   162  
   163  		Messages:                         r.Messages(),
   164  		VerificationRequests:             r.VerificationRequests(),
   165  		SavedAddresses:                   r.SavedAddresses(),
   166  		Notifications:                    r.Notifications(),
   167  		Chats:                            r.Chats(),
   168  		Communities:                      r.Communities(),
   169  		CommunitiesSettings:              r.CommunitiesSettings(),
   170  		RemovedChats:                     r.RemovedChats(),
   171  		RemovedMessages:                  r.RemovedMessages(),
   172  		DeletedMessages:                  r.DeletedMessagesInChats(),
   173  		ClearedHistories:                 r.ClearedHistories(),
   174  		ActivityCenterNotifications:      r.ActivityCenterNotifications(),
   175  		ActivityCenterState:              r.ActivityCenterState(),
   176  		PinMessages:                      r.PinMessages(),
   177  		EmojiReactions:                   r.EmojiReactions(),
   178  		StatusUpdates:                    r.StatusUpdates(),
   179  		DiscordCategories:                r.DiscordCategories,
   180  		DiscordChannels:                  r.DiscordChannels,
   181  		DiscordOldestMessageTimestamp:    r.DiscordOldestMessageTimestamp,
   182  		EnsUsernameDetails:               r.EnsUsernameDetails(),
   183  		UpdatedProfileShowcaseContactIDs: r.GetUpdatedProfileShowcaseContactIDs(),
   184  		SeenAndUnseenMessages:            r.GetSeenAndUnseenMessages(),
   185  	}
   186  
   187  	responseItem.TrustStatus = r.TrustStatus()
   188  	return json.Marshal(responseItem)
   189  }
   190  
   191  func (r *MessengerResponse) Chats() []*Chat {
   192  	var chats []*Chat
   193  	for _, chat := range r.chats {
   194  		chats = append(chats, chat)
   195  	}
   196  	return chats
   197  }
   198  
   199  func (r *MessengerResponse) Installations() []*multidevice.Installation {
   200  	var is []*multidevice.Installation
   201  	for _, i := range r.installations {
   202  		is = append(is, i)
   203  	}
   204  	return is
   205  }
   206  
   207  func (r *MessengerResponse) RemovedChats() []string {
   208  	var chats []string
   209  	for chatID := range r.removedChats {
   210  		chats = append(chats, chatID)
   211  	}
   212  	return chats
   213  }
   214  
   215  func (r *MessengerResponse) RemovedMessages() []*RemovedMessage {
   216  	var messages []*RemovedMessage
   217  	for messageID := range r.removedMessages {
   218  		messages = append(messages, r.removedMessages[messageID])
   219  	}
   220  	return messages
   221  }
   222  
   223  func (r *MessengerResponse) DeletedMessages() map[string]string {
   224  	return r.deletedMessages
   225  }
   226  
   227  func (r *MessengerResponse) DeletedMessagesInChats() map[string][]string {
   228  	deletedMessagesInChats := make(map[string][]string)
   229  	for messageID, chatID := range r.deletedMessages {
   230  		deletedMessagesInChats[chatID] = append(deletedMessagesInChats[chatID], messageID)
   231  	}
   232  	return deletedMessagesInChats
   233  }
   234  
   235  func (r *MessengerResponse) ClearedHistories() []*ClearedHistory {
   236  	var clearedHistories []*ClearedHistory
   237  	for chatID := range r.clearedHistories {
   238  		clearedHistories = append(clearedHistories, r.clearedHistories[chatID])
   239  	}
   240  	return clearedHistories
   241  }
   242  
   243  func (r *MessengerResponse) Communities() []*communities.Community {
   244  	var communities []*communities.Community
   245  	for _, c := range r.communities {
   246  		communities = append(communities, c)
   247  	}
   248  	return communities
   249  }
   250  
   251  func (r *MessengerResponse) CommunitiesSettings() []*communities.CommunitySettings {
   252  	var settings []*communities.CommunitySettings
   253  	for _, s := range r.communitiesSettings {
   254  		settings = append(settings, s)
   255  	}
   256  	return settings
   257  }
   258  
   259  func (r *MessengerResponse) Notifications() []*localnotifications.Notification {
   260  	var notifications []*localnotifications.Notification
   261  	for _, n := range r.notifications {
   262  		notifications = append(notifications, n)
   263  	}
   264  	return notifications
   265  }
   266  
   267  func (r *MessengerResponse) VerificationRequests() []*verification.Request {
   268  	var verifications []*verification.Request
   269  	for _, v := range r.verificationRequests {
   270  		verifications = append(verifications, v)
   271  	}
   272  	return verifications
   273  }
   274  
   275  func (r *MessengerResponse) PinMessages() []*common.PinMessage {
   276  	var pinMessages []*common.PinMessage
   277  	for _, pm := range r.pinMessages {
   278  		pinMessages = append(pinMessages, pm)
   279  	}
   280  	return pinMessages
   281  }
   282  
   283  func (r *MessengerResponse) TrustStatus() map[string]verification.TrustStatus {
   284  	if len(r.trustStatus) == 0 {
   285  		return nil
   286  	}
   287  
   288  	result := make(map[string]verification.TrustStatus)
   289  	for contactID, trustStatus := range r.trustStatus {
   290  		result[contactID] = trustStatus
   291  	}
   292  	return result
   293  }
   294  
   295  func (r *MessengerResponse) StatusUpdates() []UserStatus {
   296  	var userStatus []UserStatus
   297  	for pk, s := range r.statusUpdates {
   298  		s.PublicKey = pk
   299  		userStatus = append(userStatus, s)
   300  	}
   301  	return userStatus
   302  }
   303  
   304  func (r *MessengerResponse) IsEmpty() bool {
   305  	return len(r.chats)+
   306  		len(r.messages)+
   307  		len(r.pinMessages)+
   308  		len(r.Contacts)+
   309  		len(r.Bookmarks)+
   310  		len(r.clearedHistories)+
   311  		len(r.Settings)+
   312  		len(r.installations)+
   313  		len(r.Invitations)+
   314  		len(r.emojiReactions)+
   315  		len(r.communities)+
   316  		len(r.CommunityChanges)+
   317  		len(r.removedChats)+
   318  		len(r.removedMessages)+
   319  		len(r.deletedMessages)+
   320  		len(r.Mailservers)+
   321  		len(r.CommunityStorenodes)+
   322  		len(r.IdentityImages)+
   323  		len(r.WatchOnlyAccounts)+
   324  		len(r.Keypairs)+
   325  		len(r.AccountsPositions)+
   326  		len(r.TokenPreferences)+
   327  		len(r.CollectiblePreferences)+
   328  		len(r.notifications)+
   329  		len(r.statusUpdates)+
   330  		len(r.activityCenterNotifications)+
   331  		len(r.trustStatus)+
   332  		len(r.verificationRequests)+
   333  		len(r.requestsToJoinCommunity)+
   334  		len(r.savedAddresses)+
   335  		len(r.updatedProfileShowcaseContactIDs)+
   336  		len(r.seenAndUnseenMessages)+
   337  		len(r.ensUsernameDetails) == 0 &&
   338  		r.currentStatus == nil &&
   339  		r.activityCenterState == nil &&
   340  		r.CustomizationColor == ""
   341  }
   342  
   343  // Merge takes another response and appends the new Chats & new Messages and replaces
   344  // the existing Messages & Chats if they have the same ID
   345  func (r *MessengerResponse) Merge(response *MessengerResponse) error {
   346  	if len(response.Invitations)+
   347  		len(response.Mailservers)+
   348  		len(response.clearedHistories)+
   349  		len(response.DiscordChannels)+
   350  		len(response.DiscordCategories) != 0 {
   351  		return ErrNotImplemented
   352  	}
   353  
   354  	r.AddChats(response.Chats())
   355  	r.AddRemovedChats(response.RemovedChats())
   356  	r.AddRemovedMessages(response.RemovedMessages())
   357  	r.MergeDeletedMessages(response.DeletedMessages())
   358  	r.AddNotifications(response.Notifications())
   359  	r.AddMessages(response.Messages())
   360  	r.AddContacts(response.Contacts)
   361  	r.AddCommunities(response.Communities())
   362  	r.UpdateCommunitySettings(response.CommunitiesSettings())
   363  	r.AddPinMessages(response.PinMessages())
   364  	r.AddVerificationRequests(response.VerificationRequests())
   365  	r.AddTrustStatuses(response.trustStatus)
   366  	r.AddActivityCenterNotifications(response.ActivityCenterNotifications())
   367  	r.SetActivityCenterState(response.ActivityCenterState())
   368  	r.AddEmojiReactions(response.EmojiReactions())
   369  	r.AddInstallations(response.Installations())
   370  	r.AddSavedAddresses(response.SavedAddresses())
   371  	r.AddEnsUsernameDetails(response.EnsUsernameDetails())
   372  	r.AddRequestsToJoinCommunity(response.RequestsToJoinCommunity())
   373  	r.AddBookmarks(response.GetBookmarks())
   374  	r.AddSeveralUpdatedProfileShowcaseContactIDs(response.GetUpdatedProfileShowcaseContactIDs())
   375  	r.AddSeveralSeenAndUnseenMessages(response.GetSeenAndUnseenMessages())
   376  	r.CommunityChanges = append(r.CommunityChanges, response.CommunityChanges...)
   377  	r.BackupHandled = response.BackupHandled
   378  	r.CustomizationColor = response.CustomizationColor
   379  	r.WatchOnlyAccounts = append(r.WatchOnlyAccounts, response.WatchOnlyAccounts...)
   380  	r.Keypairs = append(r.Keypairs, response.Keypairs...)
   381  	r.AccountsPositions = append(r.AccountsPositions, response.AccountsPositions...)
   382  	r.TokenPreferences = append(r.TokenPreferences, response.TokenPreferences...)
   383  	r.CollectiblePreferences = append(r.CollectiblePreferences, response.CollectiblePreferences...)
   384  
   385  	return nil
   386  }
   387  
   388  func (r *MessengerResponse) AddCommunities(communities []*communities.Community) {
   389  	for _, overrideCommunity := range communities {
   390  		r.AddCommunity(overrideCommunity)
   391  	}
   392  }
   393  
   394  func (r *MessengerResponse) AddCommunity(c *communities.Community) {
   395  	if r.communities == nil {
   396  		r.communities = make(map[string]*communities.Community)
   397  	}
   398  
   399  	r.communities[c.IDString()] = c
   400  }
   401  
   402  func (r *MessengerResponse) AddCommunitySettings(c *communities.CommunitySettings) {
   403  	if r.communitiesSettings == nil {
   404  		r.communitiesSettings = make(map[string]*communities.CommunitySettings)
   405  	}
   406  
   407  	r.communitiesSettings[c.CommunityID] = c
   408  }
   409  
   410  func (r *MessengerResponse) UpdateCommunitySettings(communitySettings []*communities.CommunitySettings) {
   411  	for _, communitySetting := range communitySettings {
   412  		r.AddCommunitySettings(communitySetting)
   413  	}
   414  }
   415  
   416  func (r *MessengerResponse) AddRequestsToJoinCommunity(requestsToJoin []*communities.RequestToJoin) {
   417  	for _, rq := range requestsToJoin {
   418  		r.AddRequestToJoinCommunity(rq)
   419  	}
   420  }
   421  
   422  func (r *MessengerResponse) AddRequestToJoinCommunity(requestToJoin *communities.RequestToJoin) {
   423  	if r.requestsToJoinCommunity == nil {
   424  		r.requestsToJoinCommunity = make(map[string]*communities.RequestToJoin)
   425  	}
   426  	r.requestsToJoinCommunity[requestToJoin.ID.String()] = requestToJoin
   427  }
   428  
   429  func (r *MessengerResponse) RequestsToJoinCommunity() []*communities.RequestToJoin {
   430  	var rs []*communities.RequestToJoin
   431  	for _, r := range r.requestsToJoinCommunity {
   432  		rs = append(rs, r)
   433  	}
   434  
   435  	return rs
   436  }
   437  
   438  func (r *MessengerResponse) AddSetting(s *settings.SyncSettingField) {
   439  	r.Settings = append(r.Settings, s)
   440  }
   441  
   442  func (r *MessengerResponse) AddBookmark(bookmark *browsers.Bookmark) {
   443  	r.Bookmarks = append(r.Bookmarks, bookmark)
   444  }
   445  
   446  func (r *MessengerResponse) AddBookmarks(bookmarks []*browsers.Bookmark) {
   447  	for _, b := range bookmarks {
   448  		r.AddBookmark(b)
   449  	}
   450  }
   451  
   452  func (r *MessengerResponse) GetBookmarks() []*browsers.Bookmark {
   453  	return r.Bookmarks
   454  }
   455  
   456  func (r *MessengerResponse) AddVerificationRequest(vr *verification.Request) {
   457  	if r.verificationRequests == nil {
   458  		r.verificationRequests = make(map[string]*verification.Request)
   459  	}
   460  
   461  	r.verificationRequests[vr.ID] = vr
   462  }
   463  
   464  func (r *MessengerResponse) AddVerificationRequests(vrs []*verification.Request) {
   465  	for _, vr := range vrs {
   466  		r.AddVerificationRequest(vr)
   467  	}
   468  }
   469  
   470  func (r *MessengerResponse) AddTrustStatus(contactID string, trustStatus verification.TrustStatus) {
   471  	if r.trustStatus == nil {
   472  		r.trustStatus = make(map[string]verification.TrustStatus)
   473  	}
   474  
   475  	r.trustStatus[contactID] = trustStatus
   476  }
   477  
   478  func (r *MessengerResponse) AddTrustStatuses(ts map[string]verification.TrustStatus) {
   479  	if r.trustStatus == nil {
   480  		r.trustStatus = make(map[string]verification.TrustStatus)
   481  	}
   482  
   483  	for k, v := range ts {
   484  		r.trustStatus[k] = v
   485  	}
   486  }
   487  
   488  func (r *MessengerResponse) AddChat(c *Chat) {
   489  	if r.chats == nil {
   490  		r.chats = make(map[string]*Chat)
   491  	}
   492  
   493  	r.chats[c.ID] = c
   494  }
   495  
   496  func (r *MessengerResponse) AddChats(chats []*Chat) {
   497  	for _, c := range chats {
   498  		r.AddChat(c)
   499  	}
   500  }
   501  
   502  func (r *MessengerResponse) AddEmojiReactions(ers []*EmojiReaction) {
   503  	for _, e := range ers {
   504  		r.AddEmojiReaction(e)
   505  	}
   506  }
   507  
   508  func (r *MessengerResponse) AddEmojiReaction(er *EmojiReaction) {
   509  	if r.emojiReactions == nil {
   510  		r.emojiReactions = make(map[string]*EmojiReaction)
   511  	}
   512  
   513  	r.emojiReactions[er.ID()] = er
   514  }
   515  
   516  func (r *MessengerResponse) EmojiReactions() []*EmojiReaction {
   517  	var ers []*EmojiReaction
   518  	for _, er := range r.emojiReactions {
   519  		ers = append(ers, er)
   520  	}
   521  	return ers
   522  }
   523  
   524  func (r *MessengerResponse) AddSavedAddresses(ers []*wallet.SavedAddress) {
   525  	for _, e := range ers {
   526  		r.AddSavedAddress(e)
   527  	}
   528  }
   529  
   530  func (r *MessengerResponse) AddSavedAddress(er *wallet.SavedAddress) {
   531  	if r.savedAddresses == nil {
   532  		r.savedAddresses = make(map[string]*wallet.SavedAddress)
   533  	}
   534  
   535  	r.savedAddresses[er.ID()] = er
   536  }
   537  
   538  func (r *MessengerResponse) SavedAddresses() []*wallet.SavedAddress {
   539  	return maps.Values(r.savedAddresses)
   540  }
   541  
   542  func (r *MessengerResponse) AddEnsUsernameDetail(detail *ensservice.UsernameDetail) {
   543  	r.ensUsernameDetails = append(r.ensUsernameDetails, detail)
   544  }
   545  
   546  func (r *MessengerResponse) AddEnsUsernameDetails(details []*ensservice.UsernameDetail) {
   547  	r.ensUsernameDetails = append(r.ensUsernameDetails, details...)
   548  }
   549  
   550  func (r *MessengerResponse) EnsUsernameDetails() []*ensservice.UsernameDetail {
   551  	return r.ensUsernameDetails
   552  }
   553  
   554  func (r *MessengerResponse) AddNotification(n *localnotifications.Notification) {
   555  	if r.notifications == nil {
   556  		r.notifications = make(map[string]*localnotifications.Notification)
   557  	}
   558  
   559  	r.notifications[n.ID.String()] = n
   560  }
   561  
   562  func (r *MessengerResponse) ClearNotifications() {
   563  	r.notifications = nil
   564  }
   565  
   566  func (r *MessengerResponse) AddNotifications(notifications []*localnotifications.Notification) {
   567  	for _, c := range notifications {
   568  		r.AddNotification(c)
   569  	}
   570  }
   571  
   572  func (r *MessengerResponse) AddRemovedChats(chats []string) {
   573  	for _, c := range chats {
   574  		r.AddRemovedChat(c)
   575  	}
   576  }
   577  
   578  func (r *MessengerResponse) AddRemovedChat(chatID string) {
   579  	if r.removedChats == nil {
   580  		r.removedChats = make(map[string]bool)
   581  	}
   582  
   583  	r.removedChats[chatID] = true
   584  }
   585  
   586  func (r *MessengerResponse) AddRemovedMessages(messages []*RemovedMessage) {
   587  	for _, m := range messages {
   588  		r.AddRemovedMessage(m)
   589  	}
   590  }
   591  
   592  func (r *MessengerResponse) AddRemovedMessage(rm *RemovedMessage) {
   593  	if r.removedMessages == nil {
   594  		r.removedMessages = make(map[string]*RemovedMessage)
   595  	}
   596  
   597  	r.removedMessages[rm.MessageID] = rm
   598  	// Remove original message from the map
   599  
   600  	if len(r.messages) != 0 && r.messages[rm.MessageID] != nil {
   601  		delete(r.messages, rm.MessageID)
   602  	}
   603  }
   604  
   605  func (r *MessengerResponse) AddDeletedMessages(messagesToAdd []*protobuf.DeleteCommunityMemberMessage) {
   606  	if r.deletedMessages == nil {
   607  		r.deletedMessages = make(map[string]string)
   608  	}
   609  
   610  	for _, message := range messagesToAdd {
   611  		r.deletedMessages[message.Id] = message.ChatId
   612  	}
   613  }
   614  
   615  func (r *MessengerResponse) MergeDeletedMessages(messagesToAdd map[string]string) {
   616  	if r.deletedMessages == nil {
   617  		r.deletedMessages = make(map[string]string)
   618  	}
   619  
   620  	for messageID, chatID := range messagesToAdd {
   621  		r.deletedMessages[messageID] = chatID
   622  	}
   623  }
   624  
   625  func (r *MessengerResponse) AddClearedHistory(ch *ClearedHistory) {
   626  	if r.clearedHistories == nil {
   627  		r.clearedHistories = make(map[string]*ClearedHistory)
   628  	}
   629  
   630  	existingClearedHistory, ok := r.clearedHistories[ch.ChatID]
   631  	if !ok || existingClearedHistory.ClearedAt < ch.ClearedAt {
   632  		r.clearedHistories[ch.ChatID] = ch
   633  	}
   634  }
   635  
   636  func (r *MessengerResponse) AddActivityCenterNotifications(ns []*ActivityCenterNotification) {
   637  	for _, n := range ns {
   638  		r.AddActivityCenterNotification(n)
   639  	}
   640  }
   641  
   642  func (r *MessengerResponse) AddActivityCenterNotification(n *ActivityCenterNotification) {
   643  	if r.activityCenterNotifications == nil {
   644  		r.activityCenterNotifications = make(map[string]*ActivityCenterNotification)
   645  	}
   646  
   647  	r.activityCenterNotifications[n.ID.String()] = n
   648  }
   649  
   650  func (r *MessengerResponse) RemoveActivityCenterNotification(id string) bool {
   651  	if r.activityCenterNotifications == nil {
   652  		return false
   653  	}
   654  
   655  	if _, ok := r.activityCenterNotifications[id]; ok {
   656  		delete(r.activityCenterNotifications, id)
   657  		return true
   658  	}
   659  
   660  	return false
   661  }
   662  
   663  func (r *MessengerResponse) ActivityCenterNotifications() []*ActivityCenterNotification {
   664  	var ns []*ActivityCenterNotification
   665  	for _, n := range r.activityCenterNotifications {
   666  		ns = append(ns, n)
   667  	}
   668  	return ns
   669  }
   670  
   671  func (r *MessengerResponse) SetActivityCenterState(activityCenterState *ActivityCenterState) {
   672  	r.activityCenterState = activityCenterState
   673  }
   674  
   675  func (r *MessengerResponse) ActivityCenterState() *ActivityCenterState {
   676  	return r.activityCenterState
   677  }
   678  
   679  func (r *MessengerResponse) AddPinMessage(pm *common.PinMessage) {
   680  	if r.pinMessages == nil {
   681  		r.pinMessages = make(map[string]*common.PinMessage)
   682  	}
   683  
   684  	r.pinMessages[pm.ID] = pm
   685  }
   686  
   687  func (r *MessengerResponse) AddPinMessages(pms []*common.PinMessage) {
   688  	for _, pm := range pms {
   689  		r.AddPinMessage(pm)
   690  	}
   691  }
   692  
   693  func (r *MessengerResponse) SetCurrentStatus(status UserStatus) {
   694  	r.currentStatus = &status
   695  }
   696  
   697  func (r *MessengerResponse) AddStatusUpdate(upd UserStatus) {
   698  	if r.statusUpdates == nil {
   699  		r.statusUpdates = make(map[string]UserStatus)
   700  	}
   701  
   702  	r.statusUpdates[upd.PublicKey] = upd
   703  }
   704  
   705  func (r *MessengerResponse) DiscordMessages() []*protobuf.DiscordMessage {
   706  	var ms []*protobuf.DiscordMessage
   707  	for _, m := range r.discordMessages {
   708  		ms = append(ms, m)
   709  	}
   710  	return ms
   711  }
   712  
   713  func (r *MessengerResponse) DiscordMessageAuthors() []*protobuf.DiscordMessageAuthor {
   714  	var authors []*protobuf.DiscordMessageAuthor
   715  	for _, author := range r.discordMessageAuthors {
   716  		authors = append(authors, author)
   717  	}
   718  	return authors
   719  }
   720  
   721  func (r *MessengerResponse) DiscordMessageAttachments() []*protobuf.DiscordMessageAttachment {
   722  	var attachments []*protobuf.DiscordMessageAttachment
   723  	for _, a := range r.discordMessageAttachments {
   724  		attachments = append(attachments, a)
   725  	}
   726  	return attachments
   727  }
   728  
   729  // Messages extracts the messages from the response and returns them as a slice.
   730  // Since 'r.messages' is a map, the order of messages in the resulting slice is not
   731  // guaranteed and can vary with each call to this method. This is inherent to Go's map
   732  // iteration behavior, which does not define a sequence for the order of map elements.
   733  // Consumers should not depend on the ordering of messages in the slice for any logic
   734  // that requires consistent ordering, as map iteration order can change when keys are
   735  // added or deleted. Consider sorting the slice after retrieval if a specific order is needed.
   736  func (r *MessengerResponse) Messages() []*common.Message {
   737  	var ms []*common.Message
   738  	for _, m := range r.messages {
   739  		ms = append(ms, m)
   740  	}
   741  	return ms
   742  }
   743  
   744  func (r *MessengerResponse) AddDiscordMessageAuthor(author *protobuf.DiscordMessageAuthor) {
   745  	if r.discordMessageAuthors == nil {
   746  		r.discordMessageAuthors = make(map[string]*protobuf.DiscordMessageAuthor)
   747  	}
   748  	r.discordMessageAuthors[author.Id] = author
   749  }
   750  
   751  func (r *MessengerResponse) AddDiscordMessageAttachment(attachment *protobuf.DiscordMessageAttachment) {
   752  	if r.discordMessageAttachments == nil {
   753  		r.discordMessageAttachments = make(map[string]*protobuf.DiscordMessageAttachment)
   754  	}
   755  	r.discordMessageAttachments[attachment.Id] = attachment
   756  }
   757  
   758  func (r *MessengerResponse) AddDiscordMessageAttachments(attachments []*protobuf.DiscordMessageAttachment) {
   759  	for _, attachment := range attachments {
   760  		r.AddDiscordMessageAttachment(attachment)
   761  	}
   762  }
   763  
   764  func (r *MessengerResponse) AddDiscordMessage(message *protobuf.DiscordMessage) {
   765  	if r.discordMessages == nil {
   766  		r.discordMessages = make(map[string]*protobuf.DiscordMessage)
   767  	}
   768  	r.discordMessages[message.Id] = message
   769  }
   770  
   771  func (r *MessengerResponse) AddMessages(ms []*common.Message) {
   772  	for _, m := range ms {
   773  		r.AddMessage(m)
   774  	}
   775  }
   776  
   777  func (r *MessengerResponse) AddMessage(message *common.Message) {
   778  	if r.messages == nil {
   779  		r.messages = make(map[string]*common.Message)
   780  	}
   781  	if message.Deleted {
   782  		return
   783  	}
   784  	r.messages[message.ID] = message
   785  }
   786  
   787  func (r *MessengerResponse) AddContact(c *Contact) {
   788  
   789  	for idx, c1 := range r.Contacts {
   790  		if c1.ID == c.ID {
   791  			r.Contacts[idx] = c
   792  			return
   793  		}
   794  	}
   795  
   796  	r.Contacts = append(r.Contacts, c)
   797  }
   798  
   799  func (r *MessengerResponse) AddContacts(contacts []*Contact) {
   800  	for idx := range contacts {
   801  		r.AddContact(contacts[idx])
   802  	}
   803  }
   804  
   805  func (r *MessengerResponse) AddInstallation(i *multidevice.Installation) {
   806  	if len(r.installations) == 0 {
   807  		r.installations = make(map[string]*multidevice.Installation)
   808  	}
   809  	r.installations[i.UniqueKey()] = i
   810  }
   811  
   812  func (r *MessengerResponse) AddInstallations(installations []*multidevice.Installation) {
   813  	for idx := range installations {
   814  		r.AddInstallation(installations[idx])
   815  	}
   816  }
   817  
   818  func (r *MessengerResponse) SetMessages(messages []*common.Message) {
   819  	r.messages = make(map[string]*common.Message)
   820  	r.AddMessages(messages)
   821  }
   822  
   823  func (r *MessengerResponse) GetMessage(messageID string) *common.Message {
   824  	if r.messages == nil {
   825  		return nil
   826  	}
   827  	return r.messages[messageID]
   828  }
   829  
   830  func (r *MessengerResponse) AddDiscordCategory(dc *discord.Category) {
   831  	for idx, c := range r.DiscordCategories {
   832  		if dc.ID == c.ID {
   833  			r.DiscordCategories[idx] = dc
   834  			return
   835  		}
   836  	}
   837  
   838  	r.DiscordCategories = append(r.DiscordCategories, dc)
   839  }
   840  
   841  func (r *MessengerResponse) AddDiscordChannel(dc *discord.Channel) {
   842  	for idx, c := range r.DiscordChannels {
   843  		if dc.ID == c.ID {
   844  			r.DiscordChannels[idx] = dc
   845  			return
   846  		}
   847  	}
   848  
   849  	r.DiscordChannels = append(r.DiscordChannels, dc)
   850  }
   851  
   852  func (r *MessengerResponse) HasDiscordCategory(id string) bool {
   853  	for _, c := range r.DiscordCategories {
   854  		if id == c.ID {
   855  			return true
   856  		}
   857  	}
   858  	return false
   859  }
   860  
   861  func (r *MessengerResponse) HasDiscordChannel(id string) bool {
   862  	for _, c := range r.DiscordChannels {
   863  		if id == c.ID {
   864  			return true
   865  		}
   866  	}
   867  	return false
   868  }
   869  
   870  func (r *MessengerResponse) AddSeveralUpdatedProfileShowcaseContactIDs(contactIDs []string) {
   871  	for _, contactID := range contactIDs {
   872  		r.AddUpdatedProfileShowcaseContactID(contactID)
   873  	}
   874  }
   875  
   876  func (r *MessengerResponse) AddUpdatedProfileShowcaseContactID(contactID string) {
   877  	if r.updatedProfileShowcaseContactIDs == nil {
   878  		r.updatedProfileShowcaseContactIDs = make(map[string]bool)
   879  	}
   880  
   881  	if _, exists := r.updatedProfileShowcaseContactIDs[contactID]; exists {
   882  		return
   883  	}
   884  
   885  	r.updatedProfileShowcaseContactIDs[contactID] = true
   886  }
   887  
   888  func (r *MessengerResponse) GetUpdatedProfileShowcaseContactIDs() []string {
   889  	var contactIDs []string
   890  	for contactID := range r.updatedProfileShowcaseContactIDs {
   891  		contactIDs = append(contactIDs, contactID)
   892  	}
   893  	return contactIDs
   894  }
   895  
   896  func (r *MessengerResponse) AddSeveralSeenAndUnseenMessages(messages []*SeenUnseenMessages) {
   897  	for _, message := range messages {
   898  		r.AddSeenAndUnseenMessages(message)
   899  	}
   900  }
   901  
   902  func (r *MessengerResponse) AddSeenAndUnseenMessages(message *SeenUnseenMessages) {
   903  	if r.seenAndUnseenMessages == nil {
   904  		r.seenAndUnseenMessages = make(map[string]*SeenUnseenMessages)
   905  	}
   906  
   907  	r.seenAndUnseenMessages[message.ChatID] = message
   908  }
   909  
   910  func (r *MessengerResponse) GetSeenAndUnseenMessages() []*SeenUnseenMessages {
   911  	var messages []*SeenUnseenMessages
   912  	for _, message := range r.seenAndUnseenMessages {
   913  		messages = append(messages, message)
   914  	}
   915  	return messages
   916  }