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

     1  package protocol
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"crypto/ecdsa"
     7  	"database/sql"
     8  	"encoding/json"
     9  	"fmt"
    10  	"math/rand"
    11  	"os"
    12  	"strconv"
    13  	"strings"
    14  	"sync"
    15  	"time"
    16  
    17  	"github.com/golang/protobuf/proto"
    18  	"github.com/google/uuid"
    19  	"github.com/libp2p/go-libp2p/core/peer"
    20  	"github.com/pkg/errors"
    21  	"go.uber.org/zap"
    22  	"golang.org/x/time/rate"
    23  
    24  	datasyncnode "github.com/status-im/mvds/node"
    25  
    26  	gethcommon "github.com/ethereum/go-ethereum/common"
    27  	"github.com/ethereum/go-ethereum/common/hexutil"
    28  	"github.com/ethereum/go-ethereum/p2p"
    29  
    30  	"github.com/status-im/status-go/account"
    31  	"github.com/status-im/status-go/appmetrics"
    32  	utils "github.com/status-im/status-go/common"
    33  	"github.com/status-im/status-go/connection"
    34  	"github.com/status-im/status-go/contracts"
    35  	"github.com/status-im/status-go/deprecation"
    36  	"github.com/status-im/status-go/eth-node/crypto"
    37  	"github.com/status-im/status-go/eth-node/types"
    38  	"github.com/status-im/status-go/images"
    39  	multiaccountscommon "github.com/status-im/status-go/multiaccounts/common"
    40  
    41  	"github.com/status-im/status-go/multiaccounts"
    42  	"github.com/status-im/status-go/multiaccounts/accounts"
    43  	"github.com/status-im/status-go/multiaccounts/settings"
    44  	"github.com/status-im/status-go/protocol/anonmetrics"
    45  	"github.com/status-im/status-go/protocol/common"
    46  	"github.com/status-im/status-go/protocol/common/shard"
    47  	"github.com/status-im/status-go/protocol/communities"
    48  	"github.com/status-im/status-go/protocol/encryption"
    49  	"github.com/status-im/status-go/protocol/encryption/multidevice"
    50  	"github.com/status-im/status-go/protocol/encryption/sharedsecret"
    51  	"github.com/status-im/status-go/protocol/ens"
    52  	"github.com/status-im/status-go/protocol/identity/alias"
    53  	"github.com/status-im/status-go/protocol/identity/identicon"
    54  	"github.com/status-im/status-go/protocol/peersyncing"
    55  	"github.com/status-im/status-go/protocol/protobuf"
    56  	"github.com/status-im/status-go/protocol/pushnotificationclient"
    57  	"github.com/status-im/status-go/protocol/pushnotificationserver"
    58  	"github.com/status-im/status-go/protocol/requests"
    59  	"github.com/status-im/status-go/protocol/sqlite"
    60  	"github.com/status-im/status-go/protocol/storenodes"
    61  	"github.com/status-im/status-go/protocol/transport"
    62  	v1protocol "github.com/status-im/status-go/protocol/v1"
    63  	"github.com/status-im/status-go/protocol/verification"
    64  	"github.com/status-im/status-go/server"
    65  	"github.com/status-im/status-go/services/browsers"
    66  	ensservice "github.com/status-im/status-go/services/ens"
    67  	"github.com/status-im/status-go/services/ext/mailservers"
    68  	localnotifications "github.com/status-im/status-go/services/local-notifications"
    69  	mailserversDB "github.com/status-im/status-go/services/mailservers"
    70  	"github.com/status-im/status-go/services/wallet"
    71  	"github.com/status-im/status-go/services/wallet/community"
    72  	"github.com/status-im/status-go/services/wallet/token"
    73  	"github.com/status-im/status-go/signal"
    74  	"github.com/status-im/status-go/telemetry"
    75  )
    76  
    77  const (
    78  	PubKeyStringLength = 132
    79  
    80  	transactionSentTxt = "Transaction sent"
    81  
    82  	publicChat  ChatContext = "public-chat"
    83  	privateChat ChatContext = "private-chat"
    84  )
    85  
    86  // errors
    87  var (
    88  	ErrChatNotFoundError = errors.New("Chat not found")
    89  )
    90  
    91  const communityAdvertiseIntervalSecond int64 = 24 * 60 * 60
    92  
    93  // messageCacheIntervalMs is how long we should keep processed messages in the cache, in ms
    94  var messageCacheIntervalMs uint64 = 1000 * 60 * 60 * 48
    95  
    96  // Messenger is a entity managing chats and messages.
    97  // It acts as a bridge between the application and encryption
    98  // layers.
    99  // It needs to expose an interface to manage installations
   100  // because installations are managed by the user.
   101  // Similarly, it needs to expose an interface to manage
   102  // mailservers because they can also be managed by the user.
   103  type Messenger struct {
   104  	node                      types.Node
   105  	server                    *p2p.Server
   106  	peerStore                 *mailservers.PeerStore
   107  	config                    *config
   108  	identity                  *ecdsa.PrivateKey
   109  	persistence               *sqlitePersistence
   110  	transport                 *transport.Transport
   111  	encryptor                 *encryption.Protocol
   112  	sender                    *common.MessageSender
   113  	ensVerifier               *ens.Verifier
   114  	anonMetricsClient         *anonmetrics.Client
   115  	anonMetricsServer         *anonmetrics.Server
   116  	pushNotificationClient    *pushnotificationclient.Client
   117  	pushNotificationServer    *pushnotificationserver.Server
   118  	communitiesManager        *communities.Manager
   119  	archiveManager            communities.ArchiveService
   120  	communitiesKeyDistributor communities.KeyDistributor
   121  	accountsManager           account.Manager
   122  	mentionsManager           *MentionManager
   123  	storeNodeRequestsManager  *StoreNodeRequestManager
   124  	logger                    *zap.Logger
   125  
   126  	outputCSV bool
   127  	csvFile   *os.File
   128  
   129  	verifyTransactionClient    EthClient
   130  	featureFlags               common.FeatureFlags
   131  	shutdownTasks              []func() error
   132  	shouldPublishContactCode   bool
   133  	systemMessagesTranslations *systemMessageTranslationsMap
   134  	allChats                   *chatMap
   135  	selfContact                *Contact
   136  	selfContactSubscriptions   []chan *SelfContactChangeEvent
   137  	allContacts                *contactMap
   138  	allInstallations           *installationMap
   139  	modifiedInstallations      *stringBoolMap
   140  	installationID             string
   141  	mailserverCycle            mailserverCycle
   142  	communityStorenodes        *storenodes.CommunityStorenodes
   143  	database                   *sql.DB
   144  	multiAccounts              *multiaccounts.Database
   145  	settings                   *accounts.Database
   146  	account                    *multiaccounts.Account
   147  	mailserversDatabase        *mailserversDB.Database
   148  	browserDatabase            *browsers.Database
   149  	httpServer                 *server.MediaServer
   150  
   151  	started           bool
   152  	quit              chan struct{}
   153  	ctx               context.Context
   154  	cancel            context.CancelFunc
   155  	shutdownWaitGroup sync.WaitGroup
   156  
   157  	importingCommunities map[string]bool
   158  	importingChannels    map[string]bool
   159  	importRateLimiter    *rate.Limiter
   160  	importDelayer        struct {
   161  		wait chan struct{}
   162  		once sync.Once
   163  	}
   164  
   165  	connectionState       connection.State
   166  	telemetryClient       *telemetry.Client
   167  	contractMaker         *contracts.ContractMaker
   168  	verificationDatabase  *verification.Persistence
   169  	savedAddressesManager *wallet.SavedAddressesManager
   170  	walletAPI             *wallet.API
   171  
   172  	// TODO(samyoul) Determine if/how the remaining usage of this mutex can be removed
   173  	mutex                     sync.Mutex
   174  	mailPeersMutex            sync.RWMutex
   175  	handleMessagesMutex       sync.Mutex
   176  	handleImportMessagesMutex sync.Mutex
   177  
   178  	// flag to disable checking #hasPairedDevices
   179  	localPairing bool
   180  	// flag to enable backedup messages processing, false by default
   181  	processBackedupMessages bool
   182  
   183  	communityTokensService communities.CommunityTokensServiceInterface
   184  
   185  	// used to track dispatched messages
   186  	dispatchMessageTestCallback func(common.RawMessage)
   187  
   188  	// used to track unhandled messages
   189  	unhandledMessagesTracker func(*v1protocol.StatusMessage, error)
   190  
   191  	// enables control over chat messages iteration
   192  	retrievedMessagesIteratorFactory func(map[transport.Filter][]*types.Message) MessagesIterator
   193  
   194  	peersyncing         *peersyncing.PeerSyncing
   195  	peersyncingOffers   map[string]uint64
   196  	peersyncingRequests map[string]uint64
   197  
   198  	mvdsStatusChangeEvent chan datasyncnode.PeerStatusChangeEvent
   199  }
   200  
   201  type connStatus int
   202  
   203  const (
   204  	disconnected connStatus = iota + 1
   205  	connected
   206  )
   207  
   208  type peerStatus struct {
   209  	status                connStatus
   210  	canConnectAfter       time.Time
   211  	lastConnectionAttempt time.Time
   212  	mailserver            mailserversDB.Mailserver
   213  }
   214  type mailserverCycle struct {
   215  	sync.RWMutex
   216  	allMailservers            []mailserversDB.Mailserver
   217  	activeMailserver          *mailserversDB.Mailserver
   218  	peers                     map[string]peerStatus
   219  	availabilitySubscriptions *availabilitySubscriptions
   220  }
   221  
   222  type availabilitySubscriptions struct {
   223  	sync.Mutex
   224  	subscriptions []chan struct{}
   225  }
   226  
   227  func (s *availabilitySubscriptions) Subscribe() <-chan struct{} {
   228  	s.Lock()
   229  	defer s.Unlock()
   230  	c := make(chan struct{})
   231  	s.subscriptions = append(s.subscriptions, c)
   232  	return c
   233  }
   234  
   235  func (s *availabilitySubscriptions) EmitMailserverAvailable() {
   236  	s.Lock()
   237  	defer s.Unlock()
   238  
   239  	for _, subs := range s.subscriptions {
   240  		close(subs)
   241  	}
   242  	s.subscriptions = nil
   243  }
   244  
   245  type EnvelopeEventsInterceptor struct {
   246  	EnvelopeEventsHandler transport.EnvelopeEventsHandler
   247  	Messenger             *Messenger
   248  }
   249  
   250  type LatestContactRequest struct {
   251  	MessageID           string
   252  	ContactRequestState common.ContactRequestState
   253  	ContactID           string
   254  }
   255  
   256  func (m *Messenger) GetOwnPrimaryName() (string, error) {
   257  	ensName, err := m.settings.ENSName()
   258  	if err != nil {
   259  		return ensName, nil
   260  	}
   261  	return m.settings.DisplayName()
   262  }
   263  
   264  func (m *Messenger) ResolvePrimaryName(mentionID string) (string, error) {
   265  	if mentionID == m.myHexIdentity() {
   266  		return m.GetOwnPrimaryName()
   267  	}
   268  	contact, ok := m.allContacts.Load(mentionID)
   269  	if !ok {
   270  		var err error
   271  		contact, err = buildContactFromPkString(mentionID)
   272  		if err != nil {
   273  			return mentionID, err
   274  		}
   275  	}
   276  	return contact.PrimaryName(), nil
   277  }
   278  
   279  // EnvelopeSent triggered when envelope delivered at least to 1 peer.
   280  func (interceptor EnvelopeEventsInterceptor) EnvelopeSent(identifiers [][]byte) {
   281  	if interceptor.Messenger != nil {
   282  		signalIDs := make([][]byte, 0, len(identifiers))
   283  		for _, identifierBytes := range identifiers {
   284  			messageID := types.EncodeHex(identifierBytes)
   285  			err := interceptor.Messenger.processSentMessage(messageID)
   286  			if err != nil {
   287  				interceptor.Messenger.logger.Info("messenger failed to process sent messages", zap.Error(err))
   288  			}
   289  
   290  			message, err := interceptor.Messenger.MessageByID(messageID)
   291  			if err != nil {
   292  				interceptor.Messenger.logger.Error("failed to query message outgoing status", zap.Error(err))
   293  				continue
   294  			}
   295  			if message.OutgoingStatus == common.OutgoingStatusDelivered {
   296  				// We don't want to send the signal if the message was already marked as delivered
   297  				continue
   298  			}
   299  			signalIDs = append(signalIDs, identifierBytes)
   300  		}
   301  		interceptor.EnvelopeEventsHandler.EnvelopeSent(signalIDs)
   302  	} else {
   303  		// NOTE(rasom): In case if interceptor.Messenger is not nil and
   304  		// some error occurred on processing sent message we don't want
   305  		// to send envelop.sent signal to the client, thus `else` cause
   306  		// is necessary.
   307  		interceptor.EnvelopeEventsHandler.EnvelopeSent(identifiers)
   308  	}
   309  }
   310  
   311  // EnvelopeExpired triggered when envelope is expired but wasn't delivered to any peer.
   312  func (interceptor EnvelopeEventsInterceptor) EnvelopeExpired(identifiers [][]byte, err error) {
   313  	//we don't track expired events in Messenger, so just redirect to handler
   314  	interceptor.EnvelopeEventsHandler.EnvelopeExpired(identifiers, err)
   315  }
   316  
   317  // MailServerRequestCompleted triggered when the mailserver sends a message to notify that the request has been completed
   318  func (interceptor EnvelopeEventsInterceptor) MailServerRequestCompleted(requestID types.Hash, lastEnvelopeHash types.Hash, cursor []byte, err error) {
   319  	//we don't track mailserver requests in Messenger, so just redirect to handler
   320  	interceptor.EnvelopeEventsHandler.MailServerRequestCompleted(requestID, lastEnvelopeHash, cursor, err)
   321  }
   322  
   323  // MailServerRequestExpired triggered when the mailserver request expires
   324  func (interceptor EnvelopeEventsInterceptor) MailServerRequestExpired(hash types.Hash) {
   325  	//we don't track mailserver requests in Messenger, so just redirect to handler
   326  	interceptor.EnvelopeEventsHandler.MailServerRequestExpired(hash)
   327  }
   328  
   329  func NewMessenger(
   330  	nodeName string,
   331  	identity *ecdsa.PrivateKey,
   332  	node types.Node,
   333  	installationID string,
   334  	peerStore *mailservers.PeerStore,
   335  	version string,
   336  	opts ...Option,
   337  ) (*Messenger, error) {
   338  	var messenger *Messenger
   339  
   340  	c := messengerDefaultConfig()
   341  
   342  	for _, opt := range opts {
   343  		if err := opt(&c); err != nil {
   344  			return nil, err
   345  		}
   346  	}
   347  
   348  	logger := c.logger
   349  	if c.logger == nil {
   350  		var err error
   351  		if logger, err = zap.NewDevelopment(); err != nil {
   352  			return nil, errors.Wrap(err, "failed to create a logger")
   353  		}
   354  	}
   355  
   356  	if c.systemMessagesTranslations == nil {
   357  		c.systemMessagesTranslations = defaultSystemMessagesTranslations
   358  	}
   359  
   360  	// Configure the database.
   361  	if c.appDb == nil {
   362  		return nil, errors.New("database instance or database path needs to be provided")
   363  	}
   364  	database := c.appDb
   365  
   366  	// Apply any post database creation changes to the database
   367  	for _, opt := range c.afterDbCreatedHooks {
   368  		if err := opt(&c); err != nil {
   369  			return nil, err
   370  		}
   371  	}
   372  
   373  	// Apply migrations for all components.
   374  	err := sqlite.Migrate(database)
   375  	if err != nil {
   376  		return nil, errors.Wrap(err, "failed to apply migrations")
   377  	}
   378  
   379  	// Initialize transport layer.
   380  	var transp *transport.Transport
   381  	var peerId peer.ID
   382  
   383  	if waku, err := node.GetWaku(nil); err == nil && waku != nil {
   384  		transp, err = transport.NewTransport(
   385  			waku,
   386  			identity,
   387  			database,
   388  			"waku_keys",
   389  			nil,
   390  			c.envelopesMonitorConfig,
   391  			logger,
   392  		)
   393  		if err != nil {
   394  			return nil, errors.Wrap(err, "failed to create  Transport")
   395  		}
   396  	} else {
   397  		logger.Info("failed to find Waku service; trying WakuV2", zap.Error(err))
   398  		wakuV2, err := node.GetWakuV2(nil)
   399  		if err != nil || wakuV2 == nil {
   400  			return nil, errors.Wrap(err, "failed to find Whisper and Waku V1/V2 services")
   401  		}
   402  		peerId = wakuV2.PeerID()
   403  		transp, err = transport.NewTransport(
   404  			wakuV2,
   405  			identity,
   406  			database,
   407  			"wakuv2_keys",
   408  			nil,
   409  			c.envelopesMonitorConfig,
   410  			logger,
   411  		)
   412  		if err != nil {
   413  			return nil, errors.Wrap(err, "failed to create  Transport")
   414  		}
   415  	}
   416  
   417  	// Initialize encryption layer.
   418  	encryptionProtocol := encryption.New(
   419  		database,
   420  		installationID,
   421  		logger,
   422  	)
   423  
   424  	sender, err := common.NewMessageSender(
   425  		identity,
   426  		database,
   427  		encryptionProtocol,
   428  		transp,
   429  		logger,
   430  		c.featureFlags,
   431  	)
   432  	if err != nil {
   433  		return nil, errors.Wrap(err, "failed to create messageSender")
   434  	}
   435  
   436  	// Initialise anon metrics client
   437  	var anonMetricsClient *anonmetrics.Client
   438  	if c.anonMetricsClientConfig != nil &&
   439  		c.anonMetricsClientConfig.ShouldSend &&
   440  		c.anonMetricsClientConfig.Active == anonmetrics.ActiveClientPhrase {
   441  
   442  		anonMetricsClient = anonmetrics.NewClient(sender)
   443  		anonMetricsClient.Config = c.anonMetricsClientConfig
   444  		anonMetricsClient.Identity = identity
   445  		anonMetricsClient.DB = appmetrics.NewDB(database)
   446  		anonMetricsClient.Logger = logger
   447  	}
   448  
   449  	// Initialise anon metrics server
   450  	var anonMetricsServer *anonmetrics.Server
   451  	if c.anonMetricsServerConfig != nil &&
   452  		c.anonMetricsServerConfig.Enabled &&
   453  		c.anonMetricsServerConfig.Active == anonmetrics.ActiveServerPhrase {
   454  
   455  		server, err := anonmetrics.NewServer(c.anonMetricsServerConfig.PostgresURI)
   456  		if err != nil {
   457  			return nil, errors.Wrap(err, "failed to create anonmetrics.Server")
   458  		}
   459  
   460  		anonMetricsServer = server
   461  		anonMetricsServer.Config = c.anonMetricsServerConfig
   462  		anonMetricsServer.Logger = logger
   463  	}
   464  
   465  	// Initialize push notification server
   466  	var pushNotificationServer *pushnotificationserver.Server
   467  	if c.pushNotificationServerConfig != nil && c.pushNotificationServerConfig.Enabled {
   468  		c.pushNotificationServerConfig.Identity = identity
   469  		pushNotificationServerPersistence := pushnotificationserver.NewSQLitePersistence(database)
   470  		pushNotificationServer = pushnotificationserver.New(c.pushNotificationServerConfig, pushNotificationServerPersistence, sender)
   471  	}
   472  
   473  	// Initialize push notification client
   474  	pushNotificationClientPersistence := pushnotificationclient.NewPersistence(database)
   475  	pushNotificationClientConfig := c.pushNotificationClientConfig
   476  	if pushNotificationClientConfig == nil {
   477  		pushNotificationClientConfig = &pushnotificationclient.Config{}
   478  	}
   479  
   480  	sqlitePersistence := newSQLitePersistence(database)
   481  	// Overriding until we handle different identities
   482  	pushNotificationClientConfig.Identity = identity
   483  	pushNotificationClientConfig.Logger = logger
   484  	pushNotificationClientConfig.InstallationID = installationID
   485  
   486  	pushNotificationClient := pushnotificationclient.New(pushNotificationClientPersistence, pushNotificationClientConfig, sender, sqlitePersistence)
   487  
   488  	ensVerifier := ens.New(node, logger, transp, database, c.verifyENSURL, c.verifyENSContractAddress)
   489  
   490  	managerOptions := []communities.ManagerOption{
   491  		communities.WithAccountManager(c.accountsManager),
   492  	}
   493  
   494  	var walletAPI *wallet.API
   495  	if c.walletService != nil {
   496  		walletAPI = wallet.NewAPI(c.walletService)
   497  		managerOptions = append(managerOptions, communities.WithCollectiblesManager(walletAPI))
   498  	} else if c.collectiblesManager != nil {
   499  		managerOptions = append(managerOptions, communities.WithCollectiblesManager(c.collectiblesManager))
   500  	}
   501  
   502  	if c.tokenManager != nil {
   503  		managerOptions = append(managerOptions, communities.WithTokenManager(c.tokenManager))
   504  	} else if c.rpcClient != nil {
   505  		tokenManager := token.NewTokenManager(c.walletDb, c.rpcClient, community.NewManager(database, c.httpServer, nil), c.rpcClient.NetworkManager, database, c.httpServer, nil, nil, nil, token.NewPersistence(c.walletDb))
   506  		managerOptions = append(managerOptions, communities.WithTokenManager(communities.NewDefaultTokenManager(tokenManager, c.rpcClient.NetworkManager)))
   507  	}
   508  
   509  	if c.walletConfig != nil {
   510  		managerOptions = append(managerOptions, communities.WithWalletConfig(c.walletConfig))
   511  	}
   512  
   513  	if c.communityTokensService != nil {
   514  		managerOptions = append(managerOptions, communities.WithCommunityTokensService(c.communityTokensService))
   515  	}
   516  
   517  	managerOptions = append(managerOptions, c.communityManagerOptions...)
   518  
   519  	communitiesKeyDistributor := &CommunitiesKeyDistributorImpl{
   520  		sender:    sender,
   521  		encryptor: encryptionProtocol,
   522  	}
   523  
   524  	communitiesManager, err := communities.NewManager(
   525  		identity,
   526  		installationID,
   527  		database,
   528  		encryptionProtocol,
   529  		logger,
   530  		ensVerifier,
   531  		c.communityTokensService,
   532  		transp,
   533  		transp,
   534  		communitiesKeyDistributor,
   535  		c.httpServer,
   536  		managerOptions...,
   537  	)
   538  	if err != nil {
   539  		return nil, err
   540  	}
   541  
   542  	amc := &communities.ArchiveManagerConfig{
   543  		TorrentConfig: c.torrentConfig,
   544  		Logger:        logger,
   545  		Persistence:   communitiesManager.GetPersistence(),
   546  		Transport:     transp,
   547  		Identity:      identity,
   548  		Encryptor:     encryptionProtocol,
   549  		Publisher:     communitiesManager,
   550  	}
   551  
   552  	// Depending on the OS go will choose whether to use the "communities/manager_archive_nop.go" or
   553  	// "communities/manager_archive.go" version of this function based on the build instructions for those files.
   554  	// See those file for more details.
   555  	archiveManager := communities.NewArchiveManager(amc)
   556  	if err != nil {
   557  		return nil, err
   558  	}
   559  
   560  	settings, err := accounts.NewDB(database)
   561  	if err != nil {
   562  		return nil, err
   563  	}
   564  
   565  	savedAddressesManager := wallet.NewSavedAddressesManager(c.walletDb)
   566  
   567  	selfContact, err := buildSelfContact(identity, settings, c.multiAccount, c.account)
   568  	if err != nil {
   569  		return nil, fmt.Errorf("failed to build contact of ourself: %w", err)
   570  	}
   571  
   572  	ctx, cancel := context.WithCancel(context.Background())
   573  
   574  	var telemetryClient *telemetry.Client
   575  	if c.telemetryServerURL != "" {
   576  		options := []telemetry.TelemetryClientOption{
   577  			telemetry.WithPeerID(peerId.String()),
   578  		}
   579  		telemetryClient = telemetry.NewClient(logger, c.telemetryServerURL, c.account.KeyUID, nodeName, version, options...)
   580  		if c.wakuService != nil {
   581  			c.wakuService.SetStatusTelemetryClient(telemetryClient)
   582  		}
   583  		go telemetryClient.Start(ctx)
   584  	}
   585  
   586  	messenger = &Messenger{
   587  		config:                     &c,
   588  		node:                       node,
   589  		identity:                   identity,
   590  		persistence:                sqlitePersistence,
   591  		transport:                  transp,
   592  		encryptor:                  encryptionProtocol,
   593  		sender:                     sender,
   594  		anonMetricsClient:          anonMetricsClient,
   595  		anonMetricsServer:          anonMetricsServer,
   596  		telemetryClient:            telemetryClient,
   597  		communityTokensService:     c.communityTokensService,
   598  		pushNotificationClient:     pushNotificationClient,
   599  		pushNotificationServer:     pushNotificationServer,
   600  		communitiesManager:         communitiesManager,
   601  		communitiesKeyDistributor:  communitiesKeyDistributor,
   602  		archiveManager:             archiveManager,
   603  		accountsManager:            c.accountsManager,
   604  		ensVerifier:                ensVerifier,
   605  		featureFlags:               c.featureFlags,
   606  		systemMessagesTranslations: c.systemMessagesTranslations,
   607  		allChats:                   new(chatMap),
   608  		selfContact:                selfContact,
   609  		allContacts: &contactMap{
   610  			logger: logger,
   611  			me:     selfContact,
   612  		},
   613  		allInstallations:        new(installationMap),
   614  		installationID:          installationID,
   615  		modifiedInstallations:   new(stringBoolMap),
   616  		verifyTransactionClient: c.verifyTransactionClient,
   617  		database:                database,
   618  		multiAccounts:           c.multiAccount,
   619  		settings:                settings,
   620  		peersyncing:             peersyncing.New(peersyncing.Config{Database: database, Timesource: transp}),
   621  		peersyncingOffers:       make(map[string]uint64),
   622  		peersyncingRequests:     make(map[string]uint64),
   623  		peerStore:               peerStore,
   624  		mvdsStatusChangeEvent:   make(chan datasyncnode.PeerStatusChangeEvent, 5),
   625  		verificationDatabase:    verification.NewPersistence(database),
   626  		mailserverCycle: mailserverCycle{
   627  			peers:                     make(map[string]peerStatus),
   628  			availabilitySubscriptions: &availabilitySubscriptions{},
   629  		},
   630  		mailserversDatabase:  c.mailserversDatabase,
   631  		communityStorenodes:  storenodes.NewCommunityStorenodes(storenodes.NewDB(database), logger),
   632  		account:              c.account,
   633  		quit:                 make(chan struct{}),
   634  		ctx:                  ctx,
   635  		cancel:               cancel,
   636  		importingCommunities: make(map[string]bool),
   637  		importingChannels:    make(map[string]bool),
   638  		importRateLimiter:    rate.NewLimiter(rate.Every(importSlowRate), 1),
   639  		importDelayer: struct {
   640  			wait chan struct{}
   641  			once sync.Once
   642  		}{wait: make(chan struct{})},
   643  		browserDatabase: c.browserDatabase,
   644  		httpServer:      c.httpServer,
   645  		shutdownTasks: []func() error{
   646  			ensVerifier.Stop,
   647  			pushNotificationClient.Stop,
   648  			communitiesManager.Stop,
   649  			archiveManager.Stop,
   650  			encryptionProtocol.Stop,
   651  			func() error {
   652  				ctx, cancel := context.WithTimeout(context.Background(), time.Second)
   653  				defer cancel()
   654  				err := transp.ResetFilters(ctx)
   655  				if err != nil {
   656  					logger.Warn("could not reset filters", zap.Error(err))
   657  				}
   658  				// We don't want to thrown an error in this case, this is a soft
   659  				// fail
   660  				return nil
   661  			},
   662  			transp.Stop,
   663  			func() error { sender.Stop(); return nil },
   664  			// Currently this often fails, seems like it's safe to ignore them
   665  			// https://github.com/uber-go/zap/issues/328
   666  			func() error { _ = logger.Sync; return nil },
   667  			database.Close,
   668  		},
   669  		logger:                           logger,
   670  		savedAddressesManager:            savedAddressesManager,
   671  		retrievedMessagesIteratorFactory: NewDefaultMessagesIterator,
   672  	}
   673  
   674  	if c.rpcClient != nil {
   675  		contractMaker, err := contracts.NewContractMaker(c.rpcClient)
   676  		if err != nil {
   677  			return nil, err
   678  		}
   679  		messenger.contractMaker = contractMaker
   680  	}
   681  
   682  	messenger.mentionsManager = NewMentionManager(messenger)
   683  	messenger.storeNodeRequestsManager = NewStoreNodeRequestManager(messenger)
   684  
   685  	if c.walletService != nil {
   686  		messenger.walletAPI = walletAPI
   687  	}
   688  
   689  	if c.outputMessagesCSV {
   690  		messenger.outputCSV = c.outputMessagesCSV
   691  		csvFile, err := os.Create("messages-" + fmt.Sprint(time.Now().Unix()) + ".csv")
   692  		if err != nil {
   693  			return nil, err
   694  		}
   695  
   696  		_, err = csvFile.Write([]byte("timestamp\tmessageID\tfrom\ttopic\tchatID\tmessageType\tmessage\n"))
   697  		if err != nil {
   698  			return nil, err
   699  		}
   700  
   701  		messenger.csvFile = csvFile
   702  		messenger.shutdownTasks = append(messenger.shutdownTasks, csvFile.Close)
   703  	}
   704  
   705  	if anonMetricsClient != nil {
   706  		messenger.shutdownTasks = append(messenger.shutdownTasks, anonMetricsClient.Stop)
   707  	}
   708  	if anonMetricsServer != nil {
   709  		messenger.shutdownTasks = append(messenger.shutdownTasks, anonMetricsServer.Stop)
   710  	}
   711  
   712  	if c.envelopesMonitorConfig != nil {
   713  		interceptor := EnvelopeEventsInterceptor{c.envelopesMonitorConfig.EnvelopeEventsHandler, messenger}
   714  		err := messenger.transport.SetEnvelopeEventsHandler(interceptor)
   715  		if err != nil {
   716  			logger.Info("Unable to set envelopes event handler", zap.Error(err))
   717  		}
   718  	}
   719  
   720  	return messenger, nil
   721  }
   722  
   723  func (m *Messenger) SetP2PServer(server *p2p.Server) {
   724  	m.server = server
   725  }
   726  
   727  func (m *Messenger) EnableBackedupMessagesProcessing() {
   728  	m.processBackedupMessages = true
   729  }
   730  
   731  func (m *Messenger) processSentMessage(id string) error {
   732  	if m.connectionState.Offline {
   733  		return errors.New("Can't mark message as sent while offline")
   734  	}
   735  
   736  	rawMessage, err := m.persistence.RawMessageByID(id)
   737  	// If we have no raw message, we create a temporary one, so that
   738  	// the sent status is preserved
   739  	if err == sql.ErrNoRows || rawMessage == nil {
   740  		rawMessage = &common.RawMessage{
   741  			ID:          id,
   742  			MessageType: protobuf.ApplicationMetadataMessage_CHAT_MESSAGE,
   743  		}
   744  	} else if err != nil {
   745  		return errors.Wrapf(err, "Can't get raw message with id %v", id)
   746  	}
   747  
   748  	rawMessage.Sent = true
   749  
   750  	err = m.persistence.SaveRawMessage(rawMessage)
   751  	if err != nil {
   752  		return errors.Wrapf(err, "Can't save raw message marked as sent")
   753  	}
   754  
   755  	err = m.UpdateMessageOutgoingStatus(id, common.OutgoingStatusSent)
   756  	if err != nil {
   757  		return err
   758  	}
   759  
   760  	return nil
   761  }
   762  
   763  func (m *Messenger) ToForeground() {
   764  	if m.httpServer != nil {
   765  		m.httpServer.ToForeground()
   766  	}
   767  
   768  	m.asyncRequestAllHistoricMessages()
   769  }
   770  
   771  func (m *Messenger) ToBackground() {
   772  	if m.httpServer != nil {
   773  		m.httpServer.ToBackground()
   774  	}
   775  }
   776  
   777  func (m *Messenger) Start() (*MessengerResponse, error) {
   778  	if m.started {
   779  		return nil, errors.New("messenger already started")
   780  	}
   781  	m.started = true
   782  
   783  	err := m.InitFilters()
   784  	if err != nil {
   785  		return nil, err
   786  	}
   787  
   788  	now := time.Now().UnixMilli()
   789  	if err := m.settings.CheckAndDeleteExpiredKeypairsAndAccounts(uint64(now)); err != nil {
   790  		return nil, err
   791  	}
   792  
   793  	m.logger.Info("starting messenger", zap.String("identity", types.EncodeHex(crypto.FromECDSAPub(&m.identity.PublicKey))))
   794  	// Start push notification server
   795  	if m.pushNotificationServer != nil {
   796  		if err := m.pushNotificationServer.Start(); err != nil {
   797  			return nil, err
   798  		}
   799  	}
   800  
   801  	// Start push notification client
   802  	if m.pushNotificationClient != nil {
   803  		m.handlePushNotificationClientRegistrations(m.pushNotificationClient.SubscribeToRegistrations())
   804  
   805  		if err := m.pushNotificationClient.Start(); err != nil {
   806  			return nil, err
   807  		}
   808  	}
   809  
   810  	// Start anonymous metrics client
   811  	if m.anonMetricsClient != nil {
   812  		if err := m.anonMetricsClient.Start(); err != nil {
   813  			return nil, err
   814  		}
   815  	}
   816  
   817  	ensSubscription := m.ensVerifier.Subscribe()
   818  
   819  	// Subscrbe
   820  	if err := m.ensVerifier.Start(); err != nil {
   821  		return nil, err
   822  	}
   823  
   824  	if err := m.communitiesManager.Start(); err != nil {
   825  		return nil, err
   826  	}
   827  
   828  	// set shared secret handles
   829  	m.sender.SetHandleSharedSecrets(m.handleSharedSecrets)
   830  	if err := m.sender.StartDatasync(m.mvdsStatusChangeEvent, m.sendDataSync); err != nil {
   831  		return nil, err
   832  	}
   833  
   834  	subscriptions, err := m.encryptor.Start(m.identity)
   835  	if err != nil {
   836  		return nil, err
   837  	}
   838  
   839  	// handle stored shared secrets
   840  	err = m.handleSharedSecrets(subscriptions.SharedSecrets)
   841  	if err != nil {
   842  		return nil, err
   843  	}
   844  
   845  	m.handleEncryptionLayerSubscriptions(subscriptions)
   846  	m.handleCommunitiesSubscription(m.communitiesManager.Subscribe())
   847  	m.handleCommunitiesHistoryArchivesSubscription(m.communitiesManager.Subscribe())
   848  	m.updateCommunitiesActiveMembersPeriodically()
   849  	m.schedulePublishGrantsForControlledCommunities()
   850  	m.handleENSVerificationSubscription(ensSubscription)
   851  	m.watchConnectionChange()
   852  	m.watchChatsToUnmute()
   853  	m.watchCommunitiesToUnmute()
   854  	m.watchExpiredMessages()
   855  	m.watchIdentityImageChanges()
   856  	m.watchWalletBalances()
   857  	m.watchPendingCommunityRequestToJoin()
   858  	m.broadcastLatestUserStatus()
   859  	m.timeoutAutomaticStatusUpdates()
   860  	if !m.config.featureFlags.DisableCheckingForBackup {
   861  		m.startBackupLoop()
   862  	}
   863  	if !m.config.featureFlags.DisableAutoMessageLoop {
   864  		err = m.startAutoMessageLoop()
   865  		if err != nil {
   866  			return nil, err
   867  		}
   868  	}
   869  	m.startPeerSyncingLoop()
   870  	m.startSyncSettingsLoop()
   871  	m.startSettingsChangesLoop()
   872  	m.startCommunityRekeyLoop()
   873  	if m.config.codeControlFlags.CuratedCommunitiesUpdateLoopEnabled {
   874  		m.startCuratedCommunitiesUpdateLoop()
   875  	}
   876  	m.startMessageSegmentsCleanupLoop()
   877  	m.startHashRatchetEncryptedMessagesCleanupLoop()
   878  	m.startRequestMissingCommunityChannelsHRKeysLoop()
   879  
   880  	if err := m.cleanTopics(); err != nil {
   881  		return nil, err
   882  	}
   883  	response := &MessengerResponse{}
   884  
   885  	mailservers, err := m.allMailservers()
   886  	if err != nil {
   887  		return nil, err
   888  	}
   889  
   890  	response.Mailservers = mailservers
   891  	err = m.StartMailserverCycle(mailservers)
   892  	if err != nil {
   893  		return nil, err
   894  	}
   895  
   896  	if err := m.communityStorenodes.ReloadFromDB(); err != nil {
   897  		return nil, err
   898  	}
   899  
   900  	go m.checkForMissingMessagesLoop()
   901  
   902  	controlledCommunities, err := m.communitiesManager.Controlled()
   903  	if err != nil {
   904  		return nil, err
   905  	}
   906  
   907  	if m.archiveManager.IsReady() {
   908  		available := m.mailserverCycle.availabilitySubscriptions.Subscribe()
   909  		go func() {
   910  			<-available
   911  			m.InitHistoryArchiveTasks(controlledCommunities)
   912  		}()
   913  	}
   914  
   915  	for _, c := range controlledCommunities {
   916  		if c.Joined() && c.HasTokenPermissions() {
   917  			go m.communitiesManager.StartMembersReevaluationLoop(c.ID(), false)
   918  		}
   919  	}
   920  
   921  	joinedCommunities, err := m.communitiesManager.Joined()
   922  	if err != nil {
   923  		return nil, err
   924  	}
   925  
   926  	for _, joinedCommunity := range joinedCommunities {
   927  		// resume importing message history archives in case
   928  		// imports have been interrupted previously
   929  		err := m.resumeHistoryArchivesImport(joinedCommunity.ID())
   930  		if err != nil {
   931  			return nil, err
   932  		}
   933  	}
   934  	m.enableHistoryArchivesImportAfterDelay()
   935  
   936  	if m.httpServer != nil {
   937  		err = m.httpServer.Start()
   938  		if err != nil {
   939  			return nil, err
   940  		}
   941  	}
   942  
   943  	err = m.GarbageCollectRemovedBookmarks()
   944  	if err != nil {
   945  		return nil, err
   946  	}
   947  
   948  	err = m.garbageCollectRemovedSavedAddresses()
   949  	if err != nil {
   950  		return nil, err
   951  	}
   952  
   953  	displayName, err := m.settings.DisplayName()
   954  	if err != nil {
   955  		return nil, err
   956  	}
   957  	if err := utils.ValidateDisplayName(&displayName); err != nil {
   958  		// Somehow a wrong display name was saved. We need to update it so that others accept our messages
   959  		pubKey, err := m.settings.GetPublicKey()
   960  		if err != nil {
   961  			return nil, err
   962  		}
   963  		replacementDisplayName := pubKey[:12]
   964  		m.logger.Warn("unaccepted display name was saved to the setting, reverting to pubkey substring", zap.String("displayName", displayName), zap.String("replacement", replacementDisplayName))
   965  
   966  		if err := m.SetDisplayName(replacementDisplayName); err != nil {
   967  			// We do not return the error as we do not want to block the login for it
   968  			m.logger.Warn("error setting display name", zap.Error(err))
   969  		}
   970  	}
   971  
   972  	return response, nil
   973  }
   974  
   975  func (m *Messenger) SetMediaServer(server *server.MediaServer) {
   976  	m.httpServer = server
   977  	m.communitiesManager.SetMediaServer(server)
   978  }
   979  
   980  func (m *Messenger) IdentityPublicKey() *ecdsa.PublicKey {
   981  	return &m.identity.PublicKey
   982  }
   983  
   984  func (m *Messenger) IdentityPublicKeyCompressed() []byte {
   985  	return crypto.CompressPubkey(m.IdentityPublicKey())
   986  }
   987  
   988  func (m *Messenger) IdentityPublicKeyString() string {
   989  	return types.EncodeHex(crypto.FromECDSAPub(m.IdentityPublicKey()))
   990  }
   991  
   992  // cleanTopics remove any topic that does not have a Listen flag set
   993  func (m *Messenger) cleanTopics() error {
   994  	if m.mailserversDatabase == nil {
   995  		return nil
   996  	}
   997  	var filters []*transport.Filter
   998  	for _, f := range m.transport.Filters() {
   999  		if f.Listen && !f.Ephemeral {
  1000  			filters = append(filters, f)
  1001  		}
  1002  	}
  1003  
  1004  	m.logger.Debug("keeping topics", zap.Any("filters", filters))
  1005  
  1006  	return m.mailserversDatabase.SetTopics(filters)
  1007  }
  1008  
  1009  // handle connection change is called each time we go from offline/online or viceversa
  1010  func (m *Messenger) handleConnectionChange(online bool) {
  1011  	// Update pushNotificationClient
  1012  	if m.pushNotificationClient != nil {
  1013  		if online {
  1014  			m.pushNotificationClient.Online()
  1015  		} else {
  1016  			m.pushNotificationClient.Offline()
  1017  		}
  1018  	}
  1019  
  1020  	// Update torrent manager
  1021  	if m.archiveManager != nil {
  1022  		m.archiveManager.SetOnline(online)
  1023  	}
  1024  
  1025  	// Publish contact code
  1026  	if online && m.shouldPublishContactCode {
  1027  		if err := m.publishContactCode(); err != nil {
  1028  			m.logger.Error("could not publish on contact code", zap.Error(err))
  1029  		}
  1030  		m.shouldPublishContactCode = false
  1031  	}
  1032  
  1033  	// Start fetching messages from store nodes
  1034  	if online {
  1035  		m.asyncRequestAllHistoricMessages()
  1036  	}
  1037  
  1038  	// Update ENS verifier
  1039  	m.ensVerifier.SetOnline(online)
  1040  }
  1041  
  1042  func (m *Messenger) Online() bool {
  1043  	switch m.transport.WakuVersion() {
  1044  	case 2:
  1045  		return m.transport.PeerCount() > 0
  1046  	default:
  1047  		return m.node.PeersCount() > 0
  1048  	}
  1049  }
  1050  
  1051  func (m *Messenger) buildContactCodeAdvertisement() (*protobuf.ContactCodeAdvertisement, error) {
  1052  	if m.pushNotificationClient == nil || !m.pushNotificationClient.Enabled() {
  1053  		return nil, nil
  1054  	}
  1055  	m.logger.Debug("adding push notification info to contact code bundle")
  1056  	info, err := m.pushNotificationClient.MyPushNotificationQueryInfo()
  1057  	if err != nil {
  1058  		return nil, err
  1059  	}
  1060  	if len(info) == 0 {
  1061  		return nil, nil
  1062  	}
  1063  	return &protobuf.ContactCodeAdvertisement{
  1064  		PushNotificationInfo: info,
  1065  	}, nil
  1066  }
  1067  
  1068  // publishContactCode sends a public message wrapped in the encryption
  1069  // layer, which will propagate our bundle
  1070  func (m *Messenger) publishContactCode() error {
  1071  	var payload []byte
  1072  	m.logger.Debug("sending contact code")
  1073  	contactCodeAdvertisement, err := m.buildContactCodeAdvertisement()
  1074  	if err != nil {
  1075  		m.logger.Error("could not build contact code advertisement", zap.Error(err))
  1076  	}
  1077  
  1078  	if contactCodeAdvertisement == nil {
  1079  		contactCodeAdvertisement = &protobuf.ContactCodeAdvertisement{}
  1080  	}
  1081  
  1082  	err = m.attachChatIdentity(contactCodeAdvertisement)
  1083  	if err != nil {
  1084  		return err
  1085  	}
  1086  
  1087  	if contactCodeAdvertisement.ChatIdentity != nil {
  1088  		m.logger.Debug("attached chat identity", zap.Int("images len", len(contactCodeAdvertisement.ChatIdentity.Images)))
  1089  	} else {
  1090  		m.logger.Debug("no attached chat identity")
  1091  	}
  1092  
  1093  	payload, err = proto.Marshal(contactCodeAdvertisement)
  1094  	if err != nil {
  1095  		return err
  1096  	}
  1097  
  1098  	contactCodeTopic := transport.ContactCodeTopic(&m.identity.PublicKey)
  1099  	rawMessage := common.RawMessage{
  1100  		LocalChatID: contactCodeTopic,
  1101  		MessageType: protobuf.ApplicationMetadataMessage_CONTACT_CODE_ADVERTISEMENT,
  1102  		Payload:     payload,
  1103  		Priority:    &common.LowPriority,
  1104  	}
  1105  	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
  1106  	defer cancel()
  1107  
  1108  	_, err = m.sender.SendPublic(ctx, contactCodeTopic, rawMessage)
  1109  	if err != nil {
  1110  		m.logger.Warn("failed to send a contact code", zap.Error(err))
  1111  	}
  1112  
  1113  	joinedCommunities, err := m.communitiesManager.Joined()
  1114  	if err != nil {
  1115  		return err
  1116  	}
  1117  	for _, community := range joinedCommunities {
  1118  		rawMessage.LocalChatID = community.MemberUpdateChannelID()
  1119  		rawMessage.PubsubTopic = community.PubsubTopic()
  1120  		_, err = m.sender.SendPublic(ctx, rawMessage.LocalChatID, rawMessage)
  1121  		if err != nil {
  1122  			return err
  1123  		}
  1124  	}
  1125  
  1126  	m.logger.Debug("contact code sent")
  1127  	return err
  1128  }
  1129  
  1130  // contactCodeAdvertisement attaches a protobuf.ChatIdentity to the given protobuf.ContactCodeAdvertisement,
  1131  // if the `shouldPublish` conditions are met
  1132  func (m *Messenger) attachChatIdentity(cca *protobuf.ContactCodeAdvertisement) error {
  1133  	contactCodeTopic := transport.ContactCodeTopic(&m.identity.PublicKey)
  1134  	shouldPublish, err := m.shouldPublishChatIdentity(contactCodeTopic)
  1135  	if err != nil {
  1136  		return err
  1137  	}
  1138  
  1139  	if !shouldPublish {
  1140  		return nil
  1141  	}
  1142  
  1143  	cca.ChatIdentity, err = m.createChatIdentity(privateChat)
  1144  	if err != nil {
  1145  		return err
  1146  	}
  1147  
  1148  	img, err := m.multiAccounts.GetIdentityImage(m.account.KeyUID, images.SmallDimName)
  1149  	if err != nil {
  1150  		return err
  1151  	}
  1152  
  1153  	displayName, err := m.settings.DisplayName()
  1154  	if err != nil {
  1155  		return err
  1156  	}
  1157  
  1158  	bio, err := m.settings.Bio()
  1159  	if err != nil {
  1160  		return err
  1161  	}
  1162  
  1163  	profileShowcase, err := m.GetProfileShowcaseForSelfIdentity()
  1164  	if err != nil {
  1165  		return err
  1166  	}
  1167  
  1168  	identityHash, err := m.getIdentityHash(displayName, bio, img, profileShowcase, multiaccountscommon.IDToColorFallbackToBlue(cca.ChatIdentity.CustomizationColor))
  1169  	if err != nil {
  1170  		return err
  1171  	}
  1172  
  1173  	err = m.persistence.SaveWhenChatIdentityLastPublished(contactCodeTopic, identityHash)
  1174  	if err != nil {
  1175  		return err
  1176  	}
  1177  
  1178  	return nil
  1179  }
  1180  
  1181  // handleStandaloneChatIdentity sends a standalone ChatIdentity message to a public or private channel if the publish criteria is met
  1182  func (m *Messenger) handleStandaloneChatIdentity(chat *Chat) error {
  1183  	if chat.ChatType != ChatTypePublic && chat.ChatType != ChatTypeOneToOne {
  1184  		return nil
  1185  	}
  1186  	shouldPublishChatIdentity, err := m.shouldPublishChatIdentity(chat.ID)
  1187  	if err != nil {
  1188  		return err
  1189  	}
  1190  	if !shouldPublishChatIdentity {
  1191  		return nil
  1192  	}
  1193  
  1194  	chatContext := GetChatContextFromChatType(chat.ChatType)
  1195  
  1196  	ci, err := m.createChatIdentity(chatContext)
  1197  	if err != nil {
  1198  		return err
  1199  	}
  1200  
  1201  	payload, err := proto.Marshal(ci)
  1202  	if err != nil {
  1203  		return err
  1204  	}
  1205  
  1206  	rawMessage := common.RawMessage{
  1207  		LocalChatID: chat.ID,
  1208  		MessageType: protobuf.ApplicationMetadataMessage_CHAT_IDENTITY,
  1209  		Payload:     payload,
  1210  		Priority:    &common.LowPriority,
  1211  	}
  1212  	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
  1213  	defer cancel()
  1214  	if chat.ChatType == ChatTypePublic {
  1215  		_, err = m.sender.SendPublic(ctx, chat.ID, rawMessage)
  1216  		if err != nil {
  1217  			return err
  1218  		}
  1219  	} else {
  1220  		pk, err := chat.PublicKey()
  1221  		if err != nil {
  1222  			return err
  1223  		}
  1224  		_, err = m.sender.SendPrivate(ctx, pk, &rawMessage)
  1225  		if err != nil {
  1226  			return err
  1227  		}
  1228  
  1229  	}
  1230  
  1231  	img, err := m.multiAccounts.GetIdentityImage(m.account.KeyUID, images.SmallDimName)
  1232  	if err != nil {
  1233  		return err
  1234  	}
  1235  
  1236  	displayName, err := m.settings.DisplayName()
  1237  	if err != nil {
  1238  		return err
  1239  	}
  1240  
  1241  	bio, err := m.settings.Bio()
  1242  	if err != nil {
  1243  		return err
  1244  	}
  1245  
  1246  	profileShowcase, err := m.GetProfileShowcaseForSelfIdentity()
  1247  	if err != nil {
  1248  		return err
  1249  	}
  1250  
  1251  	identityHash, err := m.getIdentityHash(displayName, bio, img, profileShowcase, multiaccountscommon.IDToColorFallbackToBlue(ci.CustomizationColor))
  1252  	if err != nil {
  1253  		return err
  1254  	}
  1255  
  1256  	err = m.persistence.SaveWhenChatIdentityLastPublished(chat.ID, identityHash)
  1257  	if err != nil {
  1258  		return err
  1259  	}
  1260  
  1261  	return nil
  1262  }
  1263  
  1264  func (m *Messenger) getIdentityHash(displayName, bio string, img *images.IdentityImage, profileShowcase *protobuf.ProfileShowcase, customizationColor multiaccountscommon.CustomizationColor) ([]byte, error) {
  1265  	profileShowcaseData, err := proto.Marshal(profileShowcase)
  1266  	if err != nil {
  1267  		return []byte{}, err
  1268  	}
  1269  
  1270  	if img == nil {
  1271  		return crypto.Keccak256([]byte(displayName), []byte(bio), profileShowcaseData, []byte(customizationColor)), nil
  1272  	}
  1273  
  1274  	return crypto.Keccak256(img.Payload, []byte(displayName), []byte(bio), profileShowcaseData, []byte(customizationColor)), nil
  1275  }
  1276  
  1277  // shouldPublishChatIdentity returns true if the last time the ChatIdentity was attached was more than 24 hours ago
  1278  func (m *Messenger) shouldPublishChatIdentity(chatID string) (bool, error) {
  1279  	if m.account == nil {
  1280  		return false, nil
  1281  	}
  1282  
  1283  	// Check we have at least one image or a display name
  1284  	img, err := m.multiAccounts.GetIdentityImage(m.account.KeyUID, images.SmallDimName)
  1285  	if err != nil {
  1286  		return false, err
  1287  	}
  1288  
  1289  	displayName, err := m.settings.DisplayName()
  1290  	if err != nil {
  1291  		return false, err
  1292  	}
  1293  
  1294  	if img == nil && displayName == "" {
  1295  		return false, nil
  1296  	}
  1297  
  1298  	lp, hash, err := m.persistence.GetWhenChatIdentityLastPublished(chatID)
  1299  	if err != nil {
  1300  		return false, err
  1301  	}
  1302  
  1303  	bio, err := m.settings.Bio()
  1304  	if err != nil {
  1305  		return false, err
  1306  	}
  1307  
  1308  	profileShowcase, err := m.GetProfileShowcaseForSelfIdentity()
  1309  	if err != nil {
  1310  		return false, err
  1311  	}
  1312  
  1313  	identityHash, err := m.getIdentityHash(displayName, bio, img, profileShowcase, m.account.GetCustomizationColor())
  1314  	if err != nil {
  1315  		return false, err
  1316  	}
  1317  
  1318  	if !bytes.Equal(hash, identityHash) {
  1319  		return true, nil
  1320  	}
  1321  
  1322  	// Note: If Alice does not add bob as a contact she will not update her contact code with images
  1323  	return lp == 0 || time.Now().Unix()-lp > 24*60*60, nil
  1324  }
  1325  
  1326  // createChatIdentity creates a context based protobuf.ChatIdentity.
  1327  // context 'public-chat' will attach only the 'thumbnail' IdentityImage
  1328  // context 'private-chat' will attach all IdentityImage
  1329  func (m *Messenger) createChatIdentity(context ChatContext) (*protobuf.ChatIdentity, error) {
  1330  	m.logger.Info("called createChatIdentity",
  1331  		zap.String("account keyUID", m.account.KeyUID),
  1332  		zap.String("context", string(context)),
  1333  	)
  1334  
  1335  	displayName, err := m.settings.DisplayName()
  1336  	if err != nil {
  1337  		return nil, err
  1338  	}
  1339  
  1340  	bio, err := m.settings.Bio()
  1341  	if err != nil {
  1342  		return nil, err
  1343  	}
  1344  
  1345  	profileShowcase, err := m.GetProfileShowcaseForSelfIdentity()
  1346  	if err != nil {
  1347  		return nil, err
  1348  	}
  1349  
  1350  	ci := &protobuf.ChatIdentity{
  1351  		Clock:              m.transport.GetCurrentTime(),
  1352  		EnsName:            "", // TODO add ENS name handling to dedicate PR
  1353  		DisplayName:        displayName,
  1354  		Description:        bio,
  1355  		ProfileShowcase:    profileShowcase,
  1356  		CustomizationColor: m.account.GetCustomizationColorID(),
  1357  	}
  1358  
  1359  	err = m.attachIdentityImagesToChatIdentity(context, ci)
  1360  	if err != nil {
  1361  		return nil, err
  1362  	}
  1363  
  1364  	return ci, nil
  1365  }
  1366  
  1367  // adaptIdentityImageToProtobuf Adapts a images.IdentityImage to protobuf.IdentityImage
  1368  func (m *Messenger) adaptIdentityImageToProtobuf(img *images.IdentityImage) *protobuf.IdentityImage {
  1369  	return &protobuf.IdentityImage{
  1370  		Payload:     img.Payload,
  1371  		SourceType:  protobuf.IdentityImage_RAW_PAYLOAD, // TODO add ENS avatar handling to dedicated PR
  1372  		ImageFormat: images.GetProtobufImageFormat(img.Payload),
  1373  	}
  1374  }
  1375  
  1376  func (m *Messenger) attachIdentityImagesToChatIdentity(context ChatContext, ci *protobuf.ChatIdentity) error {
  1377  	s, err := m.getSettings()
  1378  	if err != nil {
  1379  		return err
  1380  	}
  1381  
  1382  	if s.ProfilePicturesShowTo == settings.ProfilePicturesShowToNone {
  1383  		m.logger.Info(fmt.Sprintf("settings.ProfilePicturesShowTo is set to '%d', skipping attaching IdentityImages", s.ProfilePicturesShowTo))
  1384  		return nil
  1385  	}
  1386  
  1387  	ciis := make(map[string]*protobuf.IdentityImage)
  1388  
  1389  	switch context {
  1390  	case publicChat:
  1391  		m.logger.Info(fmt.Sprintf("handling %s ChatIdentity", context))
  1392  
  1393  		img, err := m.multiAccounts.GetIdentityImage(m.account.KeyUID, images.SmallDimName)
  1394  		if err != nil {
  1395  			return err
  1396  		}
  1397  
  1398  		if img == nil {
  1399  			return nil
  1400  		}
  1401  
  1402  		ciis[images.SmallDimName] = m.adaptIdentityImageToProtobuf(img)
  1403  		ci.Images = ciis
  1404  
  1405  	case privateChat:
  1406  		m.logger.Info(fmt.Sprintf("handling %s ChatIdentity", context))
  1407  
  1408  		imgs, err := m.multiAccounts.GetIdentityImages(m.account.KeyUID)
  1409  		if err != nil {
  1410  			return err
  1411  		}
  1412  
  1413  		for _, img := range imgs {
  1414  			ciis[img.Name] = m.adaptIdentityImageToProtobuf(img)
  1415  		}
  1416  		ci.Images = ciis
  1417  
  1418  	default:
  1419  		return fmt.Errorf("unknown ChatIdentity context '%s'", context)
  1420  	}
  1421  
  1422  	if s.ProfilePicturesShowTo == settings.ProfilePicturesShowToContactsOnly {
  1423  		err := EncryptIdentityImagesWithContactPubKeys(ci.Images, m)
  1424  		if err != nil {
  1425  			return err
  1426  		}
  1427  	}
  1428  
  1429  	return nil
  1430  }
  1431  
  1432  // handleSharedSecrets process the negotiated secrets received from the encryption layer
  1433  func (m *Messenger) handleSharedSecrets(secrets []*sharedsecret.Secret) error {
  1434  	for _, secret := range secrets {
  1435  		fSecret := types.NegotiatedSecret{
  1436  			PublicKey: secret.Identity,
  1437  			Key:       secret.Key,
  1438  		}
  1439  		_, err := m.transport.ProcessNegotiatedSecret(fSecret)
  1440  		if err != nil {
  1441  			return err
  1442  		}
  1443  	}
  1444  	return nil
  1445  }
  1446  
  1447  // handleInstallations adds the installations in the installations map
  1448  func (m *Messenger) handleInstallations(installations []*multidevice.Installation) {
  1449  	for _, installation := range installations {
  1450  		if installation.Identity == contactIDFromPublicKey(&m.identity.PublicKey) {
  1451  			if _, ok := m.allInstallations.Load(installation.ID); !ok {
  1452  				m.allInstallations.Store(installation.ID, installation)
  1453  				m.modifiedInstallations.Store(installation.ID, true)
  1454  			}
  1455  		}
  1456  	}
  1457  }
  1458  
  1459  // handleEncryptionLayerSubscriptions handles events from the encryption layer
  1460  func (m *Messenger) handleEncryptionLayerSubscriptions(subscriptions *encryption.Subscriptions) {
  1461  	go func() {
  1462  		for {
  1463  			select {
  1464  			case <-subscriptions.SendContactCode:
  1465  				if err := m.publishContactCode(); err != nil {
  1466  					m.logger.Error("failed to publish contact code", zap.Error(err))
  1467  				}
  1468  				// we also piggy-back to clean up cached messages
  1469  				if err := m.transport.CleanMessagesProcessed(m.getTimesource().GetCurrentTime() - messageCacheIntervalMs); err != nil {
  1470  					m.logger.Error("failed to clean processed messages", zap.Error(err))
  1471  				}
  1472  
  1473  			case keys := <-subscriptions.NewHashRatchetKeys:
  1474  				if m.communitiesManager == nil {
  1475  					continue
  1476  				}
  1477  				if err := m.communitiesManager.NewHashRatchetKeys(keys); err != nil {
  1478  					m.logger.Error("failed to invalidate cache for decrypted communities", zap.Error(err))
  1479  				}
  1480  			case <-subscriptions.Quit:
  1481  				m.logger.Debug("quitting encryption subscription loop")
  1482  				return
  1483  			}
  1484  		}
  1485  	}()
  1486  }
  1487  
  1488  func (m *Messenger) handleENSVerified(records []*ens.VerificationRecord) {
  1489  	var contacts []*Contact
  1490  	for _, record := range records {
  1491  		m.logger.Info("handling record", zap.Any("record", record))
  1492  		contact, ok := m.allContacts.Load(record.PublicKey)
  1493  		if !ok {
  1494  			m.logger.Info("contact not found")
  1495  			continue
  1496  		}
  1497  
  1498  		contact.ENSVerified = record.Verified
  1499  		contact.EnsName = record.Name
  1500  		contacts = append(contacts, contact)
  1501  	}
  1502  
  1503  	m.logger.Info("handled records", zap.Any("contacts", contacts))
  1504  	if len(contacts) != 0 {
  1505  		if err := m.persistence.SaveContacts(contacts); err != nil {
  1506  			m.logger.Error("failed to save contacts", zap.Error(err))
  1507  			return
  1508  		}
  1509  	}
  1510  
  1511  	m.PublishMessengerResponse(&MessengerResponse{Contacts: contacts})
  1512  }
  1513  
  1514  func (m *Messenger) handleENSVerificationSubscription(c chan []*ens.VerificationRecord) {
  1515  	go func() {
  1516  		for {
  1517  			select {
  1518  			case records, more := <-c:
  1519  				if !more {
  1520  					m.logger.Info("No more records, quitting")
  1521  					return
  1522  				}
  1523  				if len(records) != 0 {
  1524  					m.logger.Info("handling records", zap.Any("records", records))
  1525  					m.handleENSVerified(records)
  1526  				}
  1527  			case <-m.quit:
  1528  				return
  1529  			}
  1530  		}
  1531  	}()
  1532  }
  1533  
  1534  // watchConnectionChange checks the connection status and call handleConnectionChange when this changes
  1535  func (m *Messenger) watchConnectionChange() {
  1536  	state := m.Online()
  1537  	// lastCheck, sleepDetention and keepAlive helps us recognizing when computer was offline because of sleep, lid closed, etc.
  1538  	lastCheck := time.Now().Unix()
  1539  	sleepDetentionInSecs := int64(20)
  1540  	keepAlivePeriod := 15 * time.Second // must be lower than sleepDetentionInSecs
  1541  
  1542  	processNewState := func(newState bool) {
  1543  		now := time.Now().Unix()
  1544  		force := now-lastCheck > sleepDetentionInSecs
  1545  		lastCheck = now
  1546  		if !force && state == newState {
  1547  			return
  1548  		}
  1549  		state = newState
  1550  		m.logger.Debug("connection changed", zap.Bool("online", state), zap.Bool("force", force))
  1551  		m.handleConnectionChange(state)
  1552  	}
  1553  
  1554  	pollConnectionStatus := func() {
  1555  		func() {
  1556  			for {
  1557  				select {
  1558  				case <-time.After(200 * time.Millisecond):
  1559  					processNewState(m.Online())
  1560  				case <-m.quit:
  1561  					return
  1562  				}
  1563  			}
  1564  		}()
  1565  	}
  1566  
  1567  	subscribedConnectionStatus := func(subscription *types.ConnStatusSubscription) {
  1568  		defer subscription.Unsubscribe()
  1569  		ticker := time.NewTicker(keepAlivePeriod)
  1570  		defer ticker.Stop()
  1571  		for {
  1572  			select {
  1573  			case status := <-subscription.C:
  1574  				processNewState(status.IsOnline)
  1575  			case <-ticker.C:
  1576  				processNewState(m.Online())
  1577  			case <-m.quit:
  1578  				return
  1579  			}
  1580  		}
  1581  	}
  1582  
  1583  	m.logger.Debug("watching connection changes")
  1584  	m.handleConnectionChange(state)
  1585  
  1586  	waku, err := m.node.GetWakuV2(nil)
  1587  	if err != nil {
  1588  		// No waku v2, we can't watch connection changes
  1589  		// Instead we will poll the connection status.
  1590  		m.logger.Warn("using WakuV1, can't watch connection changes, this might be have side-effects")
  1591  		go pollConnectionStatus()
  1592  		return
  1593  	}
  1594  
  1595  	// Wakuv2 is not going to return an error
  1596  	// from SubscribeToConnStatusChanges
  1597  	subscription, _ := waku.SubscribeToConnStatusChanges()
  1598  
  1599  	go subscribedConnectionStatus(subscription)
  1600  }
  1601  
  1602  // watchChatsToUnmute checks every minute to identify and unmute chats that should no longer be muted.
  1603  func (m *Messenger) watchChatsToUnmute() {
  1604  	m.logger.Debug("Checking for chats to unmute every minute")
  1605  	go func() {
  1606  		for {
  1607  			// Execute the check immediately upon starting
  1608  			response := &MessengerResponse{}
  1609  			currTime := time.Now()
  1610  
  1611  			m.allChats.Range(func(chatID string, c *Chat) bool {
  1612  				chatMuteTill := c.MuteTill
  1613  				if currTime.After(chatMuteTill) && !chatMuteTill.Equal(time.Time{}) && c.Muted {
  1614  					err := m.persistence.UnmuteChat(c.ID)
  1615  					if err != nil {
  1616  						m.logger.Warn("watchChatsToUnmute error", zap.Any("Couldn't unmute chat", err))
  1617  						return false
  1618  					}
  1619  					c.Muted = false
  1620  					c.MuteTill = time.Time{}
  1621  					response.AddChat(c)
  1622  				}
  1623  				return true
  1624  			})
  1625  
  1626  			if !response.IsEmpty() {
  1627  				signal.SendNewMessages(response)
  1628  			}
  1629  
  1630  			// Calculate the time until the next whole minute
  1631  			now := time.Now()
  1632  			waitDuration := time.Until(now.Truncate(time.Minute).Add(time.Minute))
  1633  
  1634  			// Wait until the next minute
  1635  			select {
  1636  			case <-time.After(waitDuration):
  1637  				// Continue to next iteration
  1638  			case <-m.quit:
  1639  				return
  1640  			}
  1641  		}
  1642  	}()
  1643  }
  1644  
  1645  // watchCommunitiesToUnmute checks every minute to identify and unmute communities that should no longer be muted.
  1646  func (m *Messenger) watchCommunitiesToUnmute() {
  1647  	m.logger.Debug("Checking for communities to unmute every minute")
  1648  	go func() {
  1649  		for {
  1650  			// Execute the check immediately upon starting
  1651  			response, err := m.CheckCommunitiesToUnmute()
  1652  			if err != nil {
  1653  				m.logger.Warn("watchCommunitiesToUnmute error", zap.Any("Couldn't unmute communities", err))
  1654  			} else if !response.IsEmpty() {
  1655  				signal.SendNewMessages(response)
  1656  			}
  1657  
  1658  			// Calculate the time until the next whole minute
  1659  			now := time.Now()
  1660  			waitDuration := time.Until(now.Truncate(time.Minute).Add(time.Minute))
  1661  
  1662  			// Wait until the next minute
  1663  			select {
  1664  			case <-time.After(waitDuration):
  1665  				// Continue to next iteration
  1666  			case <-m.quit:
  1667  				return
  1668  			}
  1669  		}
  1670  	}()
  1671  }
  1672  
  1673  // watchIdentityImageChanges checks for identity images changes and publishes to the contact code when it happens
  1674  func (m *Messenger) watchIdentityImageChanges() {
  1675  	m.logger.Debug("watching identity image changes")
  1676  	if m.multiAccounts == nil {
  1677  		return
  1678  	}
  1679  
  1680  	channel := m.multiAccounts.SubscribeToIdentityImageChanges()
  1681  
  1682  	go func() {
  1683  		for {
  1684  			select {
  1685  			case change := <-channel:
  1686  				identityImages, err := m.multiAccounts.GetIdentityImages(m.account.KeyUID)
  1687  				if err != nil {
  1688  					m.logger.Error("failed to get profile pictures to save self contact", zap.Error(err))
  1689  					break
  1690  				}
  1691  
  1692  				identityImagesMap := make(map[string]images.IdentityImage)
  1693  				for _, img := range identityImages {
  1694  					identityImagesMap[img.Name] = *img
  1695  				}
  1696  				m.selfContact.Images = identityImagesMap
  1697  				m.publishSelfContactSubscriptions(&SelfContactChangeEvent{ImagesChanged: true})
  1698  
  1699  				if change.PublishExpected {
  1700  					err = m.syncProfilePictures(m.dispatchMessage, identityImages)
  1701  					if err != nil {
  1702  						m.logger.Error("failed to sync profile pictures to paired devices", zap.Error(err))
  1703  					}
  1704  					err = m.PublishIdentityImage()
  1705  					if err != nil {
  1706  						m.logger.Error("failed to publish identity image", zap.Error(err))
  1707  					}
  1708  				}
  1709  			case <-m.quit:
  1710  				return
  1711  			}
  1712  		}
  1713  	}()
  1714  }
  1715  
  1716  func (m *Messenger) watchPendingCommunityRequestToJoin() {
  1717  	m.logger.Debug("watching community request to join")
  1718  
  1719  	go func() {
  1720  		for {
  1721  			select {
  1722  			case <-time.After(time.Minute * 10):
  1723  				_, err := m.CheckAndDeletePendingRequestToJoinCommunity(context.Background(), false)
  1724  				if err != nil {
  1725  					m.logger.Error("failed to check and delete pending request to join community", zap.Error(err))
  1726  				}
  1727  			case <-m.quit:
  1728  				return
  1729  			}
  1730  		}
  1731  	}()
  1732  }
  1733  
  1734  func (m *Messenger) PublishIdentityImage() error {
  1735  	// Reset last published time for ChatIdentity so new contact can receive data
  1736  	err := m.resetLastPublishedTimeForChatIdentity()
  1737  	if err != nil {
  1738  		m.logger.Error("failed to reset publish time", zap.Error(err))
  1739  		return err
  1740  	}
  1741  
  1742  	// If not online, we schedule it
  1743  	if !m.Online() {
  1744  		m.shouldPublishContactCode = true
  1745  		return nil
  1746  	}
  1747  
  1748  	return m.publishContactCode()
  1749  }
  1750  
  1751  // handlePushNotificationClientRegistration handles registration events
  1752  func (m *Messenger) handlePushNotificationClientRegistrations(c chan struct{}) {
  1753  	go func() {
  1754  		for {
  1755  			_, more := <-c
  1756  			if !more {
  1757  				return
  1758  			}
  1759  			if err := m.publishContactCode(); err != nil {
  1760  				m.logger.Error("failed to publish contact code", zap.Error(err))
  1761  			}
  1762  
  1763  		}
  1764  	}()
  1765  }
  1766  
  1767  // InitFilters analyzes chats and contacts in order to setup filters
  1768  // which are responsible for retrieving messages.
  1769  func (m *Messenger) InitFilters() error {
  1770  
  1771  	// Seed the for color generation
  1772  	rand.Seed(time.Now().Unix())
  1773  
  1774  	logger := m.logger.With(zap.String("site", "Init"))
  1775  
  1776  	// Community requests will arrive in this pubsub topic
  1777  	err := m.SubscribeToPubsubTopic(shard.DefaultNonProtectedPubsubTopic(), nil)
  1778  	if err != nil {
  1779  		return err
  1780  	}
  1781  
  1782  	var (
  1783  		filtersToInit []transport.FiltersToInitialize
  1784  		publicKeys    []*ecdsa.PublicKey
  1785  	)
  1786  
  1787  	joinedCommunities, err := m.communitiesManager.Joined()
  1788  	if err != nil {
  1789  		return err
  1790  	}
  1791  	for _, org := range joinedCommunities {
  1792  		// the org advertise on the public topic derived by the pk
  1793  		filtersToInit = append(filtersToInit, m.DefaultFilters(org)...)
  1794  
  1795  		// This is for status-go versions that didn't have `CommunitySettings`
  1796  		// We need to ensure communities that existed before community settings
  1797  		// were introduced will have community settings as well
  1798  		exists, err := m.communitiesManager.CommunitySettingsExist(org.ID())
  1799  		if err != nil {
  1800  			logger.Warn("failed to check if community settings exist", zap.Error(err))
  1801  			continue
  1802  		}
  1803  
  1804  		if !exists {
  1805  			communitySettings := communities.CommunitySettings{
  1806  				CommunityID:                  org.IDString(),
  1807  				HistoryArchiveSupportEnabled: true,
  1808  			}
  1809  
  1810  			err = m.communitiesManager.SaveCommunitySettings(communitySettings)
  1811  			if err != nil {
  1812  				logger.Warn("failed to save community settings", zap.Error(err))
  1813  			}
  1814  			continue
  1815  		}
  1816  
  1817  		// In case we do have settings, but the history archive support is disabled
  1818  		// for this community, we enable it, as this should be the default for all
  1819  		// non-admin communities
  1820  		communitySettings, err := m.communitiesManager.GetCommunitySettingsByID(org.ID())
  1821  		if err != nil {
  1822  			logger.Warn("failed to fetch community settings", zap.Error(err))
  1823  			continue
  1824  		}
  1825  
  1826  		if !org.IsControlNode() && !communitySettings.HistoryArchiveSupportEnabled {
  1827  			communitySettings.HistoryArchiveSupportEnabled = true
  1828  			err = m.communitiesManager.UpdateCommunitySettings(*communitySettings)
  1829  			if err != nil {
  1830  				logger.Warn("failed to update community settings", zap.Error(err))
  1831  			}
  1832  		}
  1833  	}
  1834  
  1835  	spectatedCommunities, err := m.communitiesManager.Spectated()
  1836  	if err != nil {
  1837  		return err
  1838  	}
  1839  	for _, org := range spectatedCommunities {
  1840  		filtersToInit = append(filtersToInit, m.DefaultFilters(org)...)
  1841  	}
  1842  
  1843  	// Get chat IDs and public keys from the existing chats.
  1844  	// TODO: Get only active chats by the query.
  1845  	chats, err := m.persistence.Chats()
  1846  	if err != nil {
  1847  		return err
  1848  	}
  1849  
  1850  	communityInfo := make(map[string]*communities.Community)
  1851  	for _, chat := range chats {
  1852  		if err := chat.Validate(); err != nil {
  1853  			logger.Warn("failed to validate chat", zap.Error(err))
  1854  			continue
  1855  		}
  1856  
  1857  		if err = m.initChatFirstMessageTimestamp(chat); err != nil {
  1858  			logger.Warn("failed to init first message timestamp", zap.Error(err))
  1859  			continue
  1860  		}
  1861  
  1862  		if !chat.Active || chat.Timeline() {
  1863  			m.allChats.Store(chat.ID, chat)
  1864  			continue
  1865  		}
  1866  
  1867  		switch chat.ChatType {
  1868  		case ChatTypePublic, ChatTypeProfile:
  1869  			filtersToInit = append(filtersToInit, transport.FiltersToInitialize{ChatID: chat.ID})
  1870  		case ChatTypeCommunityChat:
  1871  			community, ok := communityInfo[chat.CommunityID]
  1872  			if !ok {
  1873  				community, err = m.communitiesManager.GetByIDString(chat.CommunityID)
  1874  				if err != nil {
  1875  					return err
  1876  				}
  1877  				communityInfo[chat.CommunityID] = community
  1878  			}
  1879  
  1880  			if chat.UnviewedMessagesCount > 0 || chat.UnviewedMentionsCount > 0 {
  1881  				// Make sure the unread count is 0 for the channels the user cannot view
  1882  				// It's possible that the users received messages to a channel before permissions were added
  1883  				canView := community.CanView(&m.identity.PublicKey, chat.CommunityChatID())
  1884  
  1885  				if !canView {
  1886  					chat.UnviewedMessagesCount = 0
  1887  					chat.UnviewedMentionsCount = 0
  1888  				}
  1889  			}
  1890  
  1891  			filtersToInit = append(filtersToInit, transport.FiltersToInitialize{ChatID: chat.ID, PubsubTopic: community.PubsubTopic()})
  1892  		case ChatTypeOneToOne:
  1893  			pk, err := chat.PublicKey()
  1894  			if err != nil {
  1895  				return err
  1896  			}
  1897  			publicKeys = append(publicKeys, pk)
  1898  		case ChatTypePrivateGroupChat:
  1899  			for _, member := range chat.Members {
  1900  				publicKey, err := member.PublicKey()
  1901  				if err != nil {
  1902  					return errors.Wrapf(err, "invalid public key for member %s in chat %s", member.ID, chat.Name)
  1903  				}
  1904  				publicKeys = append(publicKeys, publicKey)
  1905  			}
  1906  		default:
  1907  			return errors.New("invalid chat type")
  1908  		}
  1909  
  1910  		m.allChats.Store(chat.ID, chat)
  1911  	}
  1912  
  1913  	// Timeline and profile chats are deprecated.
  1914  	// This code can be removed after some reasonable time.
  1915  
  1916  	// upsert timeline chat
  1917  	if !deprecation.ChatProfileDeprecated {
  1918  		err = m.ensureTimelineChat()
  1919  		if err != nil {
  1920  			return err
  1921  		}
  1922  	}
  1923  
  1924  	// upsert profile chat
  1925  	if !deprecation.ChatTimelineDeprecated {
  1926  		err = m.ensureMyOwnProfileChat()
  1927  		if err != nil {
  1928  			return err
  1929  		}
  1930  	}
  1931  
  1932  	// Get chat IDs and public keys from the contacts.
  1933  	contacts, err := m.persistence.Contacts()
  1934  	if err != nil {
  1935  		return err
  1936  	}
  1937  	for idx, contact := range contacts {
  1938  		if err = m.updateContactImagesURL(contact); err != nil {
  1939  			return err
  1940  		}
  1941  		m.allContacts.Store(contact.ID, contacts[idx])
  1942  		// We only need filters for contacts added by us and not blocked.
  1943  		if !contact.added() || contact.Blocked {
  1944  			continue
  1945  		}
  1946  		publicKey, err := contact.PublicKey()
  1947  		if err != nil {
  1948  			logger.Error("failed to get contact's public key", zap.Error(err))
  1949  			continue
  1950  		}
  1951  		publicKeys = append(publicKeys, publicKey)
  1952  	}
  1953  
  1954  	_, err = m.transport.InitFilters(filtersToInit, publicKeys)
  1955  	if err != nil {
  1956  		return err
  1957  	}
  1958  
  1959  	// Init filters for the communities we control
  1960  	var communityFiltersToInitialize []transport.CommunityFilterToInitialize
  1961  	controlledCommunities, err := m.communitiesManager.Controlled()
  1962  	if err != nil {
  1963  		return err
  1964  	}
  1965  
  1966  	for _, c := range controlledCommunities {
  1967  		communityFiltersToInitialize = append(communityFiltersToInitialize, transport.CommunityFilterToInitialize{
  1968  			Shard:   c.Shard(),
  1969  			PrivKey: c.PrivateKey(),
  1970  		})
  1971  	}
  1972  
  1973  	_, err = m.InitCommunityFilters(communityFiltersToInitialize)
  1974  	if err != nil {
  1975  		return err
  1976  	}
  1977  
  1978  	return nil
  1979  }
  1980  
  1981  // Shutdown takes care of ensuring a clean shutdown of Messenger
  1982  func (m *Messenger) Shutdown() (err error) {
  1983  	if m == nil {
  1984  		return nil
  1985  	}
  1986  
  1987  	select {
  1988  	case _, ok := <-m.quit:
  1989  		if !ok {
  1990  			return errors.New("messenger already shutdown")
  1991  		}
  1992  	default:
  1993  	}
  1994  
  1995  	close(m.quit)
  1996  	m.cancel()
  1997  	m.shutdownWaitGroup.Wait()
  1998  	for i, task := range m.shutdownTasks {
  1999  		m.logger.Debug("running shutdown task", zap.Int("n", i))
  2000  		if tErr := task(); tErr != nil {
  2001  			m.logger.Info("shutdown task failed", zap.Error(tErr))
  2002  			if err == nil {
  2003  				// First error appeared.
  2004  				err = tErr
  2005  			} else {
  2006  				// We return all errors. They will be concatenated in the order of occurrence,
  2007  				// however, they will also be returned as a single error.
  2008  				err = errors.Wrap(err, tErr.Error())
  2009  			}
  2010  		}
  2011  	}
  2012  	return
  2013  }
  2014  
  2015  // NOT IMPLEMENTED
  2016  func (m *Messenger) SelectMailserver(id string) error {
  2017  	return ErrNotImplemented
  2018  }
  2019  
  2020  // NOT IMPLEMENTED
  2021  func (m *Messenger) AddMailserver(enode string) error {
  2022  	return ErrNotImplemented
  2023  }
  2024  
  2025  // NOT IMPLEMENTED
  2026  func (m *Messenger) RemoveMailserver(id string) error {
  2027  	return ErrNotImplemented
  2028  }
  2029  
  2030  // NOT IMPLEMENTED
  2031  func (m *Messenger) Mailservers() ([]string, error) {
  2032  	return nil, ErrNotImplemented
  2033  }
  2034  
  2035  func (m *Messenger) initChatFirstMessageTimestamp(chat *Chat) error {
  2036  	if !chat.CommunityChat() || chat.FirstMessageTimestamp != FirstMessageTimestampUndefined {
  2037  		return nil
  2038  	}
  2039  
  2040  	oldestMessageTimestamp, hasAnyMessage, err := m.persistence.OldestMessageWhisperTimestampByChatID(chat.ID)
  2041  	if err != nil {
  2042  		return err
  2043  	}
  2044  
  2045  	if hasAnyMessage {
  2046  		if oldestMessageTimestamp == FirstMessageTimestampUndefined {
  2047  			return nil
  2048  		}
  2049  		return m.updateChatFirstMessageTimestamp(chat, whisperToUnixTimestamp(oldestMessageTimestamp), &MessengerResponse{})
  2050  	}
  2051  
  2052  	return m.updateChatFirstMessageTimestamp(chat, FirstMessageTimestampNoMessage, &MessengerResponse{})
  2053  }
  2054  
  2055  func (m *Messenger) addMessagesAndChat(chat *Chat, messages []*common.Message, response *MessengerResponse) (*MessengerResponse, error) {
  2056  	response.AddChat(chat)
  2057  	response.AddMessages(messages)
  2058  	err := m.persistence.SaveMessages(response.Messages())
  2059  	if err != nil {
  2060  		return nil, err
  2061  	}
  2062  
  2063  	return response, m.saveChat(chat)
  2064  }
  2065  
  2066  func (m *Messenger) reregisterForPushNotifications() error {
  2067  	m.logger.Info("contact state changed, re-registering for push notification")
  2068  	if m.pushNotificationClient == nil {
  2069  		return nil
  2070  	}
  2071  
  2072  	return m.pushNotificationClient.Reregister(m.pushNotificationOptions())
  2073  }
  2074  
  2075  // ReSendChatMessage pulls a message from the database and sends it again
  2076  func (m *Messenger) ReSendChatMessage(ctx context.Context, messageID string) error {
  2077  	return m.reSendRawMessage(ctx, messageID)
  2078  }
  2079  
  2080  func (m *Messenger) SetLocalPairing(localPairing bool) {
  2081  	m.localPairing = localPairing
  2082  }
  2083  func (m *Messenger) hasPairedDevices() bool {
  2084  	logger := m.logger.Named("hasPairedDevices")
  2085  
  2086  	if m.localPairing {
  2087  		return true
  2088  	}
  2089  
  2090  	var count int
  2091  	m.allInstallations.Range(func(installationID string, installation *multidevice.Installation) (shouldContinue bool) {
  2092  		if installation.Enabled {
  2093  			count++
  2094  		}
  2095  		return true
  2096  	})
  2097  	logger.Debug("installations info",
  2098  		zap.Int("Number of installations", m.allInstallations.Len()),
  2099  		zap.Int("Number of enabled installations", count))
  2100  	return count > 1
  2101  }
  2102  
  2103  func (m *Messenger) HasPairedDevices() bool {
  2104  	return m.hasPairedDevices()
  2105  }
  2106  
  2107  // sendToPairedDevices will check if we have any paired devices and send to them if necessary
  2108  func (m *Messenger) sendToPairedDevices(ctx context.Context, spec common.RawMessage) error {
  2109  	hasPairedDevices := m.hasPairedDevices()
  2110  	// We send a message to any paired device
  2111  	if hasPairedDevices {
  2112  		_, err := m.sender.SendPrivate(ctx, &m.identity.PublicKey, &spec)
  2113  		if err != nil {
  2114  			return err
  2115  		}
  2116  	}
  2117  	return nil
  2118  }
  2119  
  2120  func (m *Messenger) dispatchPairInstallationMessage(ctx context.Context, spec common.RawMessage) (common.RawMessage, error) {
  2121  	var err error
  2122  	var id []byte
  2123  
  2124  	id, err = m.sender.SendPairInstallation(ctx, &m.identity.PublicKey, spec)
  2125  
  2126  	if err != nil {
  2127  		return spec, err
  2128  	}
  2129  	spec.ID = types.EncodeHex(id)
  2130  	spec.SendCount++
  2131  	err = m.persistence.SaveRawMessage(&spec)
  2132  	if err != nil {
  2133  		return spec, err
  2134  	}
  2135  
  2136  	return spec, nil
  2137  }
  2138  
  2139  func (m *Messenger) dispatchMessage(ctx context.Context, rawMessage common.RawMessage) (common.RawMessage, error) {
  2140  	var err error
  2141  	var id []byte
  2142  	logger := m.logger.With(zap.String("site", "dispatchMessage"), zap.String("chatID", rawMessage.LocalChatID))
  2143  	chat, ok := m.allChats.Load(rawMessage.LocalChatID)
  2144  	if !ok {
  2145  		return rawMessage, errors.New("no chat found")
  2146  	}
  2147  
  2148  	switch chat.ChatType {
  2149  	case ChatTypeOneToOne:
  2150  		publicKey, err := chat.PublicKey()
  2151  		if err != nil {
  2152  			return rawMessage, err
  2153  		}
  2154  
  2155  		//SendPrivate will alter message identity and possibly datasyncid, so we save an unchanged
  2156  		//message for sending to paired devices later
  2157  		specCopyForPairedDevices := rawMessage
  2158  		if !common.IsPubKeyEqual(publicKey, &m.identity.PublicKey) || rawMessage.SkipEncryptionLayer {
  2159  			id, err = m.sender.SendPrivate(ctx, publicKey, &rawMessage)
  2160  
  2161  			if err != nil {
  2162  				return rawMessage, err
  2163  			}
  2164  		}
  2165  
  2166  		err = m.sendToPairedDevices(ctx, specCopyForPairedDevices)
  2167  
  2168  		if err != nil {
  2169  			return rawMessage, err
  2170  		}
  2171  
  2172  	case ChatTypePublic, ChatTypeProfile:
  2173  		logger.Debug("sending public message", zap.String("chatName", chat.Name))
  2174  		id, err = m.sender.SendPublic(ctx, chat.ID, rawMessage)
  2175  		if err != nil {
  2176  			return rawMessage, err
  2177  		}
  2178  
  2179  	case ChatTypeCommunityChat:
  2180  		community, err := m.communitiesManager.GetByIDString(chat.CommunityID)
  2181  		if err != nil {
  2182  			return rawMessage, err
  2183  		}
  2184  		rawMessage.PubsubTopic = community.PubsubTopic()
  2185  
  2186  		canPost, err := m.communitiesManager.CanPost(&m.identity.PublicKey, chat.CommunityID, chat.CommunityChatID(), rawMessage.MessageType)
  2187  		if err != nil {
  2188  			return rawMessage, err
  2189  		}
  2190  
  2191  		if !canPost {
  2192  			m.logger.Error("can't post on chat",
  2193  				zap.String("chatID", chat.ID),
  2194  				zap.String("chatName", chat.Name),
  2195  				zap.Any("messageType", rawMessage.MessageType),
  2196  			)
  2197  			return rawMessage, fmt.Errorf("can't post message type '%d' on chat '%s'", rawMessage.MessageType, chat.ID)
  2198  		}
  2199  
  2200  		logger.Debug("sending community chat message", zap.String("chatName", chat.Name))
  2201  		isCommunityEncrypted, err := m.communitiesManager.IsEncrypted(chat.CommunityID)
  2202  		if err != nil {
  2203  			return rawMessage, err
  2204  		}
  2205  		isChannelEncrypted, err := m.communitiesManager.IsChannelEncrypted(chat.CommunityID, chat.ID)
  2206  		if err != nil {
  2207  			return rawMessage, err
  2208  		}
  2209  		isEncrypted := isCommunityEncrypted || isChannelEncrypted
  2210  		if !isEncrypted {
  2211  			id, err = m.sender.SendPublic(ctx, chat.ID, rawMessage)
  2212  			if err != nil {
  2213  				return rawMessage, err
  2214  			}
  2215  		} else {
  2216  			rawMessage.CommunityID, err = types.DecodeHex(chat.CommunityID)
  2217  			if err != nil {
  2218  				return rawMessage, err
  2219  			}
  2220  
  2221  			if isChannelEncrypted {
  2222  				rawMessage.HashRatchetGroupID = []byte(chat.ID)
  2223  			} else {
  2224  				rawMessage.HashRatchetGroupID = rawMessage.CommunityID
  2225  			}
  2226  
  2227  			id, err = m.sender.SendCommunityMessage(ctx, &rawMessage)
  2228  			if err != nil {
  2229  				return rawMessage, err
  2230  			}
  2231  		}
  2232  	case ChatTypePrivateGroupChat:
  2233  		logger.Debug("sending group message", zap.String("chatName", chat.Name))
  2234  		if rawMessage.Recipients == nil {
  2235  			rawMessage.Recipients, err = chat.MembersAsPublicKeys()
  2236  			if err != nil {
  2237  				return rawMessage, err
  2238  			}
  2239  		}
  2240  
  2241  		hasPairedDevices := m.hasPairedDevices()
  2242  
  2243  		if !hasPairedDevices {
  2244  
  2245  			// Filter out my key from the recipients
  2246  			n := 0
  2247  			for _, recipient := range rawMessage.Recipients {
  2248  				if !common.IsPubKeyEqual(recipient, &m.identity.PublicKey) {
  2249  					rawMessage.Recipients[n] = recipient
  2250  					n++
  2251  				}
  2252  			}
  2253  			rawMessage.Recipients = rawMessage.Recipients[:n]
  2254  		}
  2255  
  2256  		// We won't really send the message out if there's no recipients
  2257  		if len(rawMessage.Recipients) == 0 {
  2258  			rawMessage.Sent = true
  2259  		}
  2260  
  2261  		// We skip wrapping in some cases (emoji reactions for example)
  2262  		if !rawMessage.SkipGroupMessageWrap {
  2263  			rawMessage.MessageType = protobuf.ApplicationMetadataMessage_MEMBERSHIP_UPDATE_MESSAGE
  2264  		}
  2265  
  2266  		id, err = m.sender.SendGroup(ctx, rawMessage.Recipients, rawMessage)
  2267  		if err != nil {
  2268  			return rawMessage, err
  2269  		}
  2270  
  2271  	default:
  2272  		return rawMessage, errors.New("chat type not supported")
  2273  	}
  2274  	rawMessage.ID = types.EncodeHex(id)
  2275  	rawMessage.SendCount++
  2276  	rawMessage.LastSent = m.getTimesource().GetCurrentTime()
  2277  	err = m.persistence.SaveRawMessage(&rawMessage)
  2278  	if err != nil {
  2279  		return rawMessage, err
  2280  	}
  2281  
  2282  	if m.dispatchMessageTestCallback != nil {
  2283  		m.dispatchMessageTestCallback(rawMessage)
  2284  	}
  2285  	return rawMessage, nil
  2286  }
  2287  
  2288  // SendChatMessage takes a minimal message and sends it based on the corresponding chat
  2289  func (m *Messenger) SendChatMessage(ctx context.Context, message *common.Message) (*MessengerResponse, error) {
  2290  	return m.sendChatMessage(ctx, message)
  2291  }
  2292  
  2293  // SendChatMessages takes a array of messages and sends it based on the corresponding chats
  2294  func (m *Messenger) SendChatMessages(ctx context.Context, messages []*common.Message) (*MessengerResponse, error) {
  2295  	var response MessengerResponse
  2296  
  2297  	generatedAlbumID, err := uuid.NewRandom()
  2298  	if err != nil {
  2299  		return nil, err
  2300  	}
  2301  
  2302  	imagesCount := uint32(0)
  2303  	for _, message := range messages {
  2304  		if message.ContentType == protobuf.ChatMessage_IMAGE {
  2305  			imagesCount++
  2306  		}
  2307  
  2308  	}
  2309  
  2310  	for _, message := range messages {
  2311  		if message.ContentType == protobuf.ChatMessage_IMAGE && len(messages) > 1 {
  2312  			err = message.SetAlbumIDAndImagesCount(generatedAlbumID.String(), imagesCount)
  2313  			if err != nil {
  2314  				return nil, err
  2315  			}
  2316  		}
  2317  		messageResponse, err := m.SendChatMessage(ctx, message)
  2318  		if err != nil {
  2319  			return nil, err
  2320  		}
  2321  		err = response.Merge(messageResponse)
  2322  		if err != nil {
  2323  			return nil, err
  2324  		}
  2325  	}
  2326  
  2327  	return &response, nil
  2328  }
  2329  
  2330  // sendChatMessage takes a minimal message and sends it based on the corresponding chat
  2331  func (m *Messenger) sendChatMessage(ctx context.Context, message *common.Message) (*MessengerResponse, error) {
  2332  	displayName, err := m.settings.DisplayName()
  2333  	if err != nil {
  2334  		return nil, err
  2335  	}
  2336  
  2337  	message.DisplayName = displayName
  2338  
  2339  	replacedText, err := m.mentionsManager.ReplaceWithPublicKey(message.ChatId, message.Text)
  2340  	if err == nil {
  2341  		message.Text = replacedText
  2342  	} else {
  2343  		m.logger.Error("failed to replace text with public key", zap.String("chatID", message.ChatId), zap.String("text", message.Text))
  2344  	}
  2345  
  2346  	if len(message.ImagePath) != 0 {
  2347  
  2348  		err := message.LoadImage()
  2349  		if err != nil {
  2350  			return nil, err
  2351  		}
  2352  
  2353  	} else if len(message.CommunityID) != 0 {
  2354  		community, err := m.communitiesManager.GetByIDString(message.CommunityID)
  2355  		if err != nil {
  2356  			return nil, err
  2357  		}
  2358  
  2359  		wrappedCommunity, err := community.ToProtocolMessageBytes()
  2360  		if err != nil {
  2361  			return nil, err
  2362  		}
  2363  
  2364  		message.Payload = &protobuf.ChatMessage_Community{Community: wrappedCommunity}
  2365  		message.Shard = community.Shard().Protobuffer()
  2366  
  2367  		message.ContentType = protobuf.ChatMessage_COMMUNITY
  2368  	} else if len(message.AudioPath) != 0 {
  2369  		err := message.LoadAudio()
  2370  		if err != nil {
  2371  			return nil, err
  2372  		}
  2373  	}
  2374  
  2375  	// We consider link previews non-critical data, so we do not want to block
  2376  	// messages from being sent.
  2377  
  2378  	unfurledLinks, err := message.ConvertLinkPreviewsToProto()
  2379  	if err != nil {
  2380  		m.logger.Error("failed to convert link previews", zap.Error(err))
  2381  	} else {
  2382  		message.UnfurledLinks = unfurledLinks
  2383  	}
  2384  
  2385  	unfurledStatusLinks, err := message.ConvertStatusLinkPreviewsToProto()
  2386  	if err != nil {
  2387  		m.logger.Error("failed to convert status link previews", zap.Error(err))
  2388  	} else {
  2389  		message.UnfurledStatusLinks = unfurledStatusLinks
  2390  	}
  2391  
  2392  	var response MessengerResponse
  2393  
  2394  	// A valid added chat is required.
  2395  	chat, ok := m.allChats.Load(message.ChatId)
  2396  	if !ok {
  2397  		return nil, ErrChatNotFoundError
  2398  	}
  2399  
  2400  	err = m.handleStandaloneChatIdentity(chat)
  2401  	if err != nil {
  2402  		return nil, err
  2403  	}
  2404  
  2405  	err = extendMessageFromChat(message, chat, &m.identity.PublicKey, m.getTimesource())
  2406  	if err != nil {
  2407  		return nil, err
  2408  	}
  2409  
  2410  	err = m.addContactRequestPropagatedState(message)
  2411  	if err != nil {
  2412  		return nil, err
  2413  	}
  2414  
  2415  	encodedMessage, err := m.encodeChatEntity(chat, message)
  2416  	if err != nil {
  2417  		return nil, err
  2418  	}
  2419  
  2420  	rawMessage := common.RawMessage{
  2421  		LocalChatID:          chat.ID,
  2422  		SendPushNotification: m.featureFlags.PushNotifications,
  2423  		Payload:              encodedMessage,
  2424  		MessageType:          protobuf.ApplicationMetadataMessage_CHAT_MESSAGE,
  2425  		ResendType:           chat.DefaultResendType(),
  2426  	}
  2427  
  2428  	// We want to save the raw message before dispatching it, to avoid race conditions
  2429  	// since it might get dispatched and confirmed before it's saved.
  2430  	// This is not the best solution, probably it would be better to split
  2431  	// the sent status in a different table and join on query for messages,
  2432  	// but that's a much larger change and it would require an expensive migration of clients
  2433  	rawMessage.BeforeDispatch = func(rawMessage *common.RawMessage) error {
  2434  
  2435  		if rawMessage.Sent {
  2436  			message.OutgoingStatus = common.OutgoingStatusSent
  2437  		}
  2438  		message.ID = rawMessage.ID
  2439  		err = message.PrepareContent(common.PubkeyToHex(&m.identity.PublicKey))
  2440  		if err != nil {
  2441  			return err
  2442  		}
  2443  
  2444  		err = chat.UpdateFromMessage(message, m.getTimesource())
  2445  		if err != nil {
  2446  			return err
  2447  		}
  2448  
  2449  		err := m.persistence.SaveMessages([]*common.Message{message})
  2450  		if err != nil {
  2451  			return err
  2452  		}
  2453  
  2454  		var syncMessageType peersyncing.SyncMessageType
  2455  		if chat.OneToOne() {
  2456  			syncMessageType = peersyncing.SyncMessageOneToOneType
  2457  		} else if chat.CommunityChat() {
  2458  			syncMessageType = peersyncing.SyncMessageCommunityType
  2459  		} else if chat.PrivateGroupChat() {
  2460  			syncMessageType = peersyncing.SyncMessagePrivateGroup
  2461  		}
  2462  
  2463  		wrappedMessage, err := v1protocol.WrapMessageV1(rawMessage.Payload, rawMessage.MessageType, rawMessage.Sender)
  2464  		if err != nil {
  2465  			return errors.Wrap(err, "failed to wrap message")
  2466  		}
  2467  
  2468  		syncMessage := peersyncing.SyncMessage{
  2469  			Type:      syncMessageType,
  2470  			ID:        types.Hex2Bytes(rawMessage.ID),
  2471  			ChatID:    []byte(chat.ID),
  2472  			Payload:   wrappedMessage,
  2473  			Timestamp: m.transport.GetCurrentTime() / 1000,
  2474  		}
  2475  
  2476  		// If the chat type is not supported, skip saving it
  2477  		if syncMessageType == 0 {
  2478  			return nil
  2479  		}
  2480  
  2481  		// ensure that the message is saved only once
  2482  		rawMessage.BeforeDispatch = nil
  2483  
  2484  		return m.peersyncing.Add(syncMessage)
  2485  	}
  2486  
  2487  	rawMessage, err = m.dispatchMessage(ctx, rawMessage)
  2488  	if err != nil {
  2489  		return nil, err
  2490  	}
  2491  
  2492  	msg, err := m.pullMessagesAndResponsesFromDB([]*common.Message{message})
  2493  	if err != nil {
  2494  		return nil, err
  2495  	}
  2496  
  2497  	if err := m.updateChatFirstMessageTimestamp(chat, whisperToUnixTimestamp(message.WhisperTimestamp), &response); err != nil {
  2498  		return nil, err
  2499  	}
  2500  
  2501  	response.SetMessages(msg)
  2502  	response.AddChat(chat)
  2503  
  2504  	m.logger.Debug("inside sendChatMessage",
  2505  		zap.String("id", message.ID),
  2506  		zap.String("from", message.From),
  2507  		zap.String("displayName", message.DisplayName),
  2508  		zap.String("ChatId", message.ChatId),
  2509  		zap.String("Clock", strconv.FormatUint(message.Clock, 10)),
  2510  		zap.String("Timestamp", strconv.FormatUint(message.Timestamp, 10)),
  2511  	)
  2512  	err = m.prepareMessages(response.messages)
  2513  
  2514  	if err != nil {
  2515  		return nil, err
  2516  	}
  2517  
  2518  	return &response, m.saveChat(chat)
  2519  }
  2520  
  2521  func whisperToUnixTimestamp(whisperTimestamp uint64) uint32 {
  2522  	return uint32(whisperTimestamp / 1000)
  2523  }
  2524  
  2525  func (m *Messenger) updateChatFirstMessageTimestamp(chat *Chat, timestamp uint32, response *MessengerResponse) error {
  2526  	// Currently supported only for communities
  2527  	if !chat.CommunityChat() {
  2528  		return nil
  2529  	}
  2530  
  2531  	community, err := m.communitiesManager.GetByIDString(chat.CommunityID)
  2532  	if err != nil {
  2533  		return err
  2534  	}
  2535  
  2536  	if community.IsControlNode() && chat.UpdateFirstMessageTimestamp(timestamp) {
  2537  		community, changes, err := m.communitiesManager.EditChatFirstMessageTimestamp(community.ID(), chat.ID, chat.FirstMessageTimestamp)
  2538  		if err != nil {
  2539  			return err
  2540  		}
  2541  
  2542  		response.AddCommunity(community)
  2543  		response.CommunityChanges = append(response.CommunityChanges, changes)
  2544  	}
  2545  
  2546  	return nil
  2547  }
  2548  
  2549  func (m *Messenger) ShareImageMessage(request *requests.ShareImageMessage) (*MessengerResponse, error) {
  2550  	if err := request.Validate(); err != nil {
  2551  		return nil, err
  2552  	}
  2553  	response := &MessengerResponse{}
  2554  
  2555  	msg, err := m.persistence.MessageByID(request.MessageID)
  2556  	if err != nil {
  2557  		return nil, err
  2558  	}
  2559  
  2560  	var messages []*common.Message
  2561  	for _, pk := range request.Users {
  2562  		message := common.NewMessage()
  2563  		message.ChatId = pk.String()
  2564  		message.Payload = msg.Payload
  2565  		message.Text = "This message has been shared with you"
  2566  		message.ContentType = protobuf.ChatMessage_IMAGE
  2567  		messages = append(messages, message)
  2568  
  2569  		r, err := m.CreateOneToOneChat(&requests.CreateOneToOneChat{ID: pk})
  2570  		if err != nil {
  2571  			return nil, err
  2572  		}
  2573  
  2574  		if err := response.Merge(r); err != nil {
  2575  			return nil, err
  2576  		}
  2577  	}
  2578  
  2579  	sendMessagesResponse, err := m.SendChatMessages(context.Background(), messages)
  2580  	if err != nil {
  2581  		return nil, err
  2582  	}
  2583  
  2584  	if err := response.Merge(sendMessagesResponse); err != nil {
  2585  		return nil, err
  2586  	}
  2587  
  2588  	return response, nil
  2589  }
  2590  
  2591  func (m *Messenger) InstallationID() string {
  2592  	return m.installationID
  2593  }
  2594  
  2595  func (m *Messenger) KeyUID() string {
  2596  	return m.account.KeyUID
  2597  }
  2598  
  2599  // syncChat sync a chat with paired devices
  2600  func (m *Messenger) syncChat(ctx context.Context, chatToSync *Chat, rawMessageHandler RawMessageHandler) error {
  2601  	var err error
  2602  	if !m.hasPairedDevices() {
  2603  		return nil
  2604  	}
  2605  	clock, chat := m.getLastClockWithRelatedChat()
  2606  
  2607  	syncMessage := &protobuf.SyncChat{
  2608  		Clock:    clock,
  2609  		Id:       chatToSync.ID,
  2610  		Name:     chatToSync.Name,
  2611  		ChatType: uint32(chatToSync.ChatType),
  2612  		Active:   chatToSync.Active,
  2613  	}
  2614  	chatMuteTill, _ := time.Parse(time.RFC3339, chatToSync.MuteTill.Format(time.RFC3339))
  2615  	if chatToSync.Muted && chatMuteTill.Equal(time.Time{}) {
  2616  		// Only set Muted if it is "permanently" muted
  2617  		syncMessage.Muted = true
  2618  	}
  2619  	if chatToSync.OneToOne() {
  2620  		syncMessage.Name = "" // The Name is useless in 1-1 chats
  2621  	}
  2622  	if chatToSync.PrivateGroupChat() {
  2623  		syncMessage.MembershipUpdateEvents = make([]*protobuf.MembershipUpdateEvents, len(chatToSync.MembershipUpdates))
  2624  		for i, membershipUpdate := range chatToSync.MembershipUpdates {
  2625  			syncMessage.MembershipUpdateEvents[i] = &protobuf.MembershipUpdateEvents{
  2626  				Clock:      membershipUpdate.ClockValue,
  2627  				Type:       uint32(membershipUpdate.Type),
  2628  				Members:    membershipUpdate.Members,
  2629  				Name:       membershipUpdate.Name,
  2630  				Signature:  membershipUpdate.Signature,
  2631  				ChatId:     membershipUpdate.ChatID,
  2632  				From:       membershipUpdate.From,
  2633  				RawPayload: membershipUpdate.RawPayload,
  2634  				Color:      membershipUpdate.Color,
  2635  				Image:      membershipUpdate.Image,
  2636  			}
  2637  		}
  2638  	}
  2639  	encodedMessage, err := proto.Marshal(syncMessage)
  2640  	if err != nil {
  2641  		return err
  2642  	}
  2643  
  2644  	rawMessage := common.RawMessage{
  2645  		LocalChatID: chat.ID,
  2646  		Payload:     encodedMessage,
  2647  		MessageType: protobuf.ApplicationMetadataMessage_SYNC_CHAT,
  2648  		ResendType:  common.ResendTypeDataSync,
  2649  	}
  2650  
  2651  	_, err = rawMessageHandler(ctx, rawMessage)
  2652  	if err != nil {
  2653  		return err
  2654  	}
  2655  
  2656  	chat.LastClockValue = clock
  2657  	return m.saveChat(chat)
  2658  }
  2659  
  2660  func (m *Messenger) syncClearHistory(ctx context.Context, publicChat *Chat, rawMessageHandler RawMessageHandler) error {
  2661  	var err error
  2662  	if !m.hasPairedDevices() {
  2663  		return nil
  2664  	}
  2665  	clock, chat := m.getLastClockWithRelatedChat()
  2666  
  2667  	syncMessage := &protobuf.SyncClearHistory{
  2668  		ChatId:    publicChat.ID,
  2669  		ClearedAt: publicChat.DeletedAtClockValue,
  2670  	}
  2671  
  2672  	encodedMessage, err := proto.Marshal(syncMessage)
  2673  	if err != nil {
  2674  		return err
  2675  	}
  2676  
  2677  	rawMessage := common.RawMessage{
  2678  		LocalChatID: chat.ID,
  2679  		Payload:     encodedMessage,
  2680  		MessageType: protobuf.ApplicationMetadataMessage_SYNC_CLEAR_HISTORY,
  2681  		ResendType:  common.ResendTypeDataSync,
  2682  	}
  2683  
  2684  	_, err = rawMessageHandler(ctx, rawMessage)
  2685  	if err != nil {
  2686  		return err
  2687  	}
  2688  
  2689  	chat.LastClockValue = clock
  2690  	return m.saveChat(chat)
  2691  }
  2692  
  2693  func (m *Messenger) syncChatRemoving(ctx context.Context, id string, rawMessageHandler RawMessageHandler) error {
  2694  	var err error
  2695  	if !m.hasPairedDevices() {
  2696  		return nil
  2697  	}
  2698  	clock, chat := m.getLastClockWithRelatedChat()
  2699  
  2700  	syncMessage := &protobuf.SyncChatRemoved{
  2701  		Clock: clock,
  2702  		Id:    id,
  2703  	}
  2704  	encodedMessage, err := proto.Marshal(syncMessage)
  2705  	if err != nil {
  2706  		return err
  2707  	}
  2708  
  2709  	rawMessage := common.RawMessage{
  2710  		LocalChatID: chat.ID,
  2711  		Payload:     encodedMessage,
  2712  		MessageType: protobuf.ApplicationMetadataMessage_SYNC_CHAT_REMOVED,
  2713  		ResendType:  common.ResendTypeDataSync,
  2714  	}
  2715  
  2716  	_, err = rawMessageHandler(ctx, rawMessage)
  2717  	if err != nil {
  2718  		return err
  2719  	}
  2720  
  2721  	chat.LastClockValue = clock
  2722  	return m.saveChat(chat)
  2723  }
  2724  
  2725  // syncContact sync as contact with paired devices
  2726  func (m *Messenger) syncContact(ctx context.Context, contact *Contact, rawMessageHandler RawMessageHandler) error {
  2727  	var err error
  2728  	if contact.IsSyncing {
  2729  		return nil
  2730  	}
  2731  	if !m.hasPairedDevices() {
  2732  		return nil
  2733  	}
  2734  	clock, chat := m.getLastClockWithRelatedChat()
  2735  
  2736  	syncMessage := m.buildSyncContactMessage(contact)
  2737  
  2738  	encodedMessage, err := proto.Marshal(syncMessage)
  2739  	if err != nil {
  2740  		return err
  2741  	}
  2742  
  2743  	rawMessage := common.RawMessage{
  2744  		LocalChatID: chat.ID,
  2745  		Payload:     encodedMessage,
  2746  		MessageType: protobuf.ApplicationMetadataMessage_SYNC_INSTALLATION_CONTACT_V2,
  2747  		ResendType:  common.ResendTypeDataSync,
  2748  	}
  2749  
  2750  	_, err = rawMessageHandler(ctx, rawMessage)
  2751  	if err != nil {
  2752  		return err
  2753  	}
  2754  
  2755  	chat.LastClockValue = clock
  2756  	return m.saveChat(chat)
  2757  }
  2758  
  2759  func (m *Messenger) propagateSyncInstallationCommunityWithHRKeys(msg *protobuf.SyncInstallationCommunity, c *communities.Community) error {
  2760  	communityKeys, err := m.encryptor.GetAllHRKeysMarshaledV1(c.ID())
  2761  	if err != nil {
  2762  		return err
  2763  	}
  2764  	msg.EncryptionKeysV1 = communityKeys
  2765  
  2766  	communityAndChannelKeys := [][]byte{}
  2767  	communityKeys, err = m.encryptor.GetAllHRKeysMarshaledV2(c.ID())
  2768  	if err != nil {
  2769  		return err
  2770  	}
  2771  	if len(communityKeys) > 0 {
  2772  		communityAndChannelKeys = append(communityAndChannelKeys, communityKeys)
  2773  	}
  2774  
  2775  	for channelID := range c.Chats() {
  2776  		channelKeys, err := m.encryptor.GetAllHRKeysMarshaledV2([]byte(c.IDString() + channelID))
  2777  		if err != nil {
  2778  			return err
  2779  		}
  2780  		if len(channelKeys) > 0 {
  2781  			communityAndChannelKeys = append(communityAndChannelKeys, channelKeys)
  2782  		}
  2783  	}
  2784  	msg.EncryptionKeysV2 = communityAndChannelKeys
  2785  
  2786  	return nil
  2787  }
  2788  
  2789  func (m *Messenger) buildSyncInstallationCommunity(community *communities.Community, clock uint64) (*protobuf.SyncInstallationCommunity, error) {
  2790  	communitySettings, err := m.communitiesManager.GetCommunitySettingsByID(community.ID())
  2791  	if err != nil {
  2792  		return nil, err
  2793  	}
  2794  
  2795  	syncControlNode, err := m.communitiesManager.GetSyncControlNode(community.ID())
  2796  	if err != nil {
  2797  		return nil, err
  2798  	}
  2799  
  2800  	syncMessage, err := community.ToSyncInstallationCommunityProtobuf(clock, communitySettings, syncControlNode)
  2801  	if err != nil {
  2802  		return nil, err
  2803  	}
  2804  
  2805  	err = m.propagateSyncInstallationCommunityWithHRKeys(syncMessage, community)
  2806  	if err != nil {
  2807  		return nil, err
  2808  	}
  2809  
  2810  	return syncMessage, nil
  2811  }
  2812  
  2813  func (m *Messenger) syncCommunity(ctx context.Context, community *communities.Community, rawMessageHandler RawMessageHandler) error {
  2814  	logger := m.logger.Named("syncCommunity")
  2815  	if !m.hasPairedDevices() {
  2816  		logger.Debug("device has no paired devices")
  2817  		return nil
  2818  	}
  2819  
  2820  	logger.Debug("device has paired device(s)")
  2821  
  2822  	clock, chat := m.getLastClockWithRelatedChat()
  2823  
  2824  	syncMessage, err := m.buildSyncInstallationCommunity(community, clock)
  2825  	if err != nil {
  2826  		return err
  2827  	}
  2828  
  2829  	encodedMessage, err := proto.Marshal(syncMessage)
  2830  	if err != nil {
  2831  		return err
  2832  	}
  2833  
  2834  	rawMessage := common.RawMessage{
  2835  		LocalChatID: chat.ID,
  2836  		Payload:     encodedMessage,
  2837  		MessageType: protobuf.ApplicationMetadataMessage_SYNC_INSTALLATION_COMMUNITY,
  2838  		ResendType:  common.ResendTypeDataSync,
  2839  	}
  2840  
  2841  	_, err = rawMessageHandler(ctx, rawMessage)
  2842  	if err != nil {
  2843  		return err
  2844  	}
  2845  	logger.Debug("message dispatched")
  2846  
  2847  	chat.LastClockValue = clock
  2848  	return m.saveChat(chat)
  2849  }
  2850  
  2851  func (m *Messenger) SyncBookmark(ctx context.Context, bookmark *browsers.Bookmark, rawMessageHandler RawMessageHandler) error {
  2852  	if !m.hasPairedDevices() {
  2853  		return nil
  2854  	}
  2855  
  2856  	clock, chat := m.getLastClockWithRelatedChat()
  2857  
  2858  	syncMessage := &protobuf.SyncBookmark{
  2859  		Clock:     clock,
  2860  		Url:       bookmark.URL,
  2861  		Name:      bookmark.Name,
  2862  		ImageUrl:  bookmark.ImageURL,
  2863  		Removed:   bookmark.Removed,
  2864  		DeletedAt: bookmark.DeletedAt,
  2865  	}
  2866  	encodedMessage, err := proto.Marshal(syncMessage)
  2867  	if err != nil {
  2868  		return err
  2869  	}
  2870  
  2871  	rawMessage := common.RawMessage{
  2872  		LocalChatID: chat.ID,
  2873  		Payload:     encodedMessage,
  2874  		MessageType: protobuf.ApplicationMetadataMessage_SYNC_BOOKMARK,
  2875  		ResendType:  common.ResendTypeDataSync,
  2876  	}
  2877  	_, err = rawMessageHandler(ctx, rawMessage)
  2878  	if err != nil {
  2879  		return err
  2880  	}
  2881  
  2882  	chat.LastClockValue = clock
  2883  	return m.saveChat(chat)
  2884  }
  2885  
  2886  func (m *Messenger) SyncEnsNamesWithDispatchMessage(ctx context.Context, usernameDetail *ensservice.UsernameDetail) error {
  2887  	return m.syncEnsUsernameDetail(ctx, usernameDetail, m.dispatchMessage)
  2888  }
  2889  
  2890  func (m *Messenger) syncEnsUsernameDetails(ctx context.Context, rawMessageHandler RawMessageHandler) error {
  2891  	if !m.hasPairedDevices() {
  2892  		return nil
  2893  	}
  2894  
  2895  	ensNameDetails, err := m.getEnsUsernameDetails()
  2896  	if err != nil {
  2897  		return err
  2898  	}
  2899  	for _, d := range ensNameDetails {
  2900  		if err = m.syncEnsUsernameDetail(ctx, d, rawMessageHandler); err != nil {
  2901  			return err
  2902  		}
  2903  	}
  2904  	return nil
  2905  }
  2906  
  2907  func (m *Messenger) saveEnsUsernameDetailProto(syncMessage *protobuf.SyncEnsUsernameDetail) (*ensservice.UsernameDetail, error) {
  2908  	ud := &ensservice.UsernameDetail{
  2909  		Username: syncMessage.Username,
  2910  		Clock:    syncMessage.Clock,
  2911  		ChainID:  syncMessage.ChainId,
  2912  		Removed:  syncMessage.Removed,
  2913  	}
  2914  	db := ensservice.NewEnsDatabase(m.database)
  2915  	err := db.SaveOrUpdateEnsUsername(ud)
  2916  	if err != nil {
  2917  		return nil, err
  2918  	}
  2919  	return ud, nil
  2920  }
  2921  
  2922  func (m *Messenger) HandleSyncEnsUsernameDetail(state *ReceivedMessageState, syncMessage *protobuf.SyncEnsUsernameDetail, statusMessage *v1protocol.StatusMessage) error {
  2923  	ud, err := m.saveEnsUsernameDetailProto(syncMessage)
  2924  	if err != nil {
  2925  		return err
  2926  	}
  2927  	state.Response.AddEnsUsernameDetail(ud)
  2928  	return nil
  2929  }
  2930  
  2931  func (m *Messenger) syncEnsUsernameDetail(ctx context.Context, usernameDetail *ensservice.UsernameDetail, rawMessageHandler RawMessageHandler) error {
  2932  	syncMessage := &protobuf.SyncEnsUsernameDetail{
  2933  		Clock:    usernameDetail.Clock,
  2934  		Username: usernameDetail.Username,
  2935  		ChainId:  usernameDetail.ChainID,
  2936  		Removed:  usernameDetail.Removed,
  2937  	}
  2938  	encodedMessage, err := proto.Marshal(syncMessage)
  2939  	if err != nil {
  2940  		return err
  2941  	}
  2942  
  2943  	_, chat := m.getLastClockWithRelatedChat()
  2944  	rawMessage := common.RawMessage{
  2945  		LocalChatID: chat.ID,
  2946  		Payload:     encodedMessage,
  2947  		MessageType: protobuf.ApplicationMetadataMessage_SYNC_ENS_USERNAME_DETAIL,
  2948  		ResendType:  common.ResendTypeDataSync,
  2949  	}
  2950  
  2951  	_, err = rawMessageHandler(ctx, rawMessage)
  2952  	return err
  2953  }
  2954  
  2955  func (m *Messenger) syncAccountCustomizationColor(ctx context.Context, acc *multiaccounts.Account) error {
  2956  	if !m.hasPairedDevices() {
  2957  		return nil
  2958  	}
  2959  
  2960  	_, chat := m.getLastClockWithRelatedChat()
  2961  
  2962  	message := &protobuf.SyncAccountCustomizationColor{
  2963  		KeyUid:             acc.KeyUID,
  2964  		CustomizationColor: string(acc.CustomizationColor),
  2965  		UpdatedAt:          acc.CustomizationColorClock,
  2966  	}
  2967  
  2968  	encodedMessage, err := proto.Marshal(message)
  2969  	if err != nil {
  2970  		return err
  2971  	}
  2972  
  2973  	rawMessage := common.RawMessage{
  2974  		LocalChatID: chat.ID,
  2975  		Payload:     encodedMessage,
  2976  		MessageType: protobuf.ApplicationMetadataMessage_SYNC_ACCOUNT_CUSTOMIZATION_COLOR,
  2977  		ResendType:  common.ResendTypeDataSync,
  2978  	}
  2979  
  2980  	_, err = m.dispatchMessage(ctx, rawMessage)
  2981  	return err
  2982  }
  2983  
  2984  func (m *Messenger) SyncTrustedUser(ctx context.Context, publicKey string, ts verification.TrustStatus, rawMessageHandler RawMessageHandler) error {
  2985  	if !m.hasPairedDevices() {
  2986  		return nil
  2987  	}
  2988  
  2989  	clock, chat := m.getLastClockWithRelatedChat()
  2990  
  2991  	syncMessage := &protobuf.SyncTrustedUser{
  2992  		Clock:  clock,
  2993  		Id:     publicKey,
  2994  		Status: protobuf.SyncTrustedUser_TrustStatus(ts),
  2995  	}
  2996  	encodedMessage, err := proto.Marshal(syncMessage)
  2997  	if err != nil {
  2998  		return err
  2999  	}
  3000  
  3001  	rawMessage := common.RawMessage{
  3002  		LocalChatID: chat.ID,
  3003  		Payload:     encodedMessage,
  3004  		MessageType: protobuf.ApplicationMetadataMessage_SYNC_TRUSTED_USER,
  3005  		ResendType:  common.ResendTypeDataSync,
  3006  	}
  3007  
  3008  	_, err = rawMessageHandler(ctx, rawMessage)
  3009  	if err != nil {
  3010  		return err
  3011  	}
  3012  
  3013  	chat.LastClockValue = clock
  3014  	return m.saveChat(chat)
  3015  }
  3016  
  3017  func (m *Messenger) SyncVerificationRequest(ctx context.Context, vr *verification.Request, rawMessageHandler RawMessageHandler) error {
  3018  	if !m.hasPairedDevices() {
  3019  		return nil
  3020  	}
  3021  
  3022  	clock, chat := m.getLastClockWithRelatedChat()
  3023  
  3024  	syncMessage := &protobuf.SyncVerificationRequest{
  3025  		Id:                 vr.ID,
  3026  		Clock:              clock,
  3027  		From:               vr.From,
  3028  		To:                 vr.To,
  3029  		Challenge:          vr.Challenge,
  3030  		Response:           vr.Response,
  3031  		RequestedAt:        vr.RequestedAt,
  3032  		RepliedAt:          vr.RepliedAt,
  3033  		VerificationStatus: protobuf.SyncVerificationRequest_VerificationStatus(vr.RequestStatus),
  3034  	}
  3035  	encodedMessage, err := proto.Marshal(syncMessage)
  3036  	if err != nil {
  3037  		return err
  3038  	}
  3039  
  3040  	rawMessage := common.RawMessage{
  3041  		LocalChatID: chat.ID,
  3042  		Payload:     encodedMessage,
  3043  		MessageType: protobuf.ApplicationMetadataMessage_SYNC_VERIFICATION_REQUEST,
  3044  		ResendType:  common.ResendTypeDataSync,
  3045  	}
  3046  
  3047  	_, err = rawMessageHandler(ctx, rawMessage)
  3048  	if err != nil {
  3049  		return err
  3050  	}
  3051  
  3052  	chat.LastClockValue = clock
  3053  	return m.saveChat(chat)
  3054  }
  3055  
  3056  // RetrieveAll retrieves messages from all filters, processes them and returns a
  3057  // MessengerResponse to the client
  3058  func (m *Messenger) RetrieveAll() (*MessengerResponse, error) {
  3059  	chatWithMessages, err := m.transport.RetrieveRawAll()
  3060  	if err != nil {
  3061  		return nil, err
  3062  	}
  3063  
  3064  	return m.handleRetrievedMessages(chatWithMessages, true, false)
  3065  }
  3066  
  3067  func (m *Messenger) StartRetrieveMessagesLoop(tick time.Duration, cancel <-chan struct{}) {
  3068  	m.shutdownWaitGroup.Add(1)
  3069  	go func() {
  3070  		defer m.shutdownWaitGroup.Done()
  3071  		ticker := time.NewTicker(tick)
  3072  		defer ticker.Stop()
  3073  		for {
  3074  			select {
  3075  			case <-ticker.C:
  3076  				m.ProcessAllMessages()
  3077  			case <-cancel:
  3078  				return
  3079  			}
  3080  		}
  3081  	}()
  3082  }
  3083  
  3084  func (m *Messenger) ProcessAllMessages() {
  3085  	response, err := m.RetrieveAll()
  3086  	if err != nil {
  3087  		m.logger.Error("failed to retrieve raw messages", zap.Error(err))
  3088  		return
  3089  	}
  3090  	m.PublishMessengerResponse(response)
  3091  }
  3092  
  3093  func (m *Messenger) PublishMessengerResponse(response *MessengerResponse) {
  3094  	if response.IsEmpty() {
  3095  		return
  3096  	}
  3097  
  3098  	notifications := response.Notifications()
  3099  	// Clear notifications as not used for now
  3100  	response.ClearNotifications()
  3101  	signal.SendNewMessages(response)
  3102  	localnotifications.PushMessages(notifications)
  3103  }
  3104  
  3105  func (m *Messenger) GetStats() types.StatsSummary {
  3106  	return m.transport.GetStats()
  3107  }
  3108  
  3109  func (m *Messenger) GetTransport() *transport.Transport {
  3110  	return m.transport
  3111  }
  3112  
  3113  type CurrentMessageState struct {
  3114  	// Message is the protobuf message received
  3115  	Message *protobuf.ChatMessage
  3116  	// MessageID is the ID of the message
  3117  	MessageID string
  3118  	// WhisperTimestamp is the whisper timestamp of the message
  3119  	WhisperTimestamp uint64
  3120  	// Contact is the contact associated with the author of the message
  3121  	Contact *Contact
  3122  	// PublicKey is the public key of the author of the message
  3123  	PublicKey *ecdsa.PublicKey
  3124  
  3125  	StatusMessage *v1protocol.StatusMessage
  3126  }
  3127  
  3128  type ReceivedMessageState struct {
  3129  	// State on the message being processed
  3130  	CurrentMessageState *CurrentMessageState
  3131  	// AllChats in memory
  3132  	AllChats *chatMap
  3133  	// All contacts in memory
  3134  	AllContacts *contactMap
  3135  	// List of contacts modified
  3136  	ModifiedContacts *stringBoolMap
  3137  	// All installations in memory
  3138  	AllInstallations *installationMap
  3139  	// List of communities modified
  3140  	ModifiedInstallations *stringBoolMap
  3141  	// Map of existing messages
  3142  	ExistingMessagesMap map[string]bool
  3143  	// EmojiReactions is a list of emoji reactions for the current batch
  3144  	// indexed by from-message-id-emoji-type
  3145  	EmojiReactions map[string]*EmojiReaction
  3146  	// GroupChatInvitations is a list of invitation requests or rejections
  3147  	GroupChatInvitations map[string]*GroupChatInvitation
  3148  	// Response to the client
  3149  	Response           *MessengerResponse
  3150  	ResolvePrimaryName func(string) (string, error)
  3151  	// Timesource is a time source for clock values/timestamps.
  3152  	Timesource              common.TimeSource
  3153  	AllBookmarks            map[string]*browsers.Bookmark
  3154  	AllVerificationRequests []*verification.Request
  3155  	AllTrustStatus          map[string]verification.TrustStatus
  3156  }
  3157  
  3158  // addNewMessageNotification takes a common.Message and generates a new NotificationBody and appends it to the
  3159  // []Response.Notifications if the message is m.New
  3160  func (r *ReceivedMessageState) addNewMessageNotification(publicKey ecdsa.PublicKey, m *common.Message, responseTo *common.Message, profilePicturesVisibility int) error {
  3161  	if !m.New {
  3162  		return nil
  3163  	}
  3164  
  3165  	pubKey, err := m.GetSenderPubKey()
  3166  	if err != nil {
  3167  		return err
  3168  	}
  3169  	contactID := contactIDFromPublicKey(pubKey)
  3170  
  3171  	chat, ok := r.AllChats.Load(m.LocalChatID)
  3172  	if !ok {
  3173  		return fmt.Errorf("chat ID '%s' not present", m.LocalChatID)
  3174  	}
  3175  
  3176  	contact, ok := r.AllContacts.Load(contactID)
  3177  	if !ok {
  3178  		return fmt.Errorf("contact ID '%s' not present", contactID)
  3179  	}
  3180  
  3181  	if !chat.Muted {
  3182  		if showMessageNotification(publicKey, m, chat, responseTo) {
  3183  			notification, err := NewMessageNotification(m.ID, m, chat, contact, r.ResolvePrimaryName, profilePicturesVisibility)
  3184  			if err != nil {
  3185  				return err
  3186  			}
  3187  			r.Response.AddNotification(notification)
  3188  		}
  3189  	}
  3190  
  3191  	return nil
  3192  }
  3193  
  3194  // updateExistingActivityCenterNotification updates AC notification if it exists and hasn't been read yet
  3195  func (r *ReceivedMessageState) updateExistingActivityCenterNotification(publicKey ecdsa.PublicKey, m *Messenger, message *common.Message, responseTo *common.Message) error {
  3196  	notification, err := m.persistence.GetActivityCenterNotificationByID(types.FromHex(message.ID))
  3197  	if err != nil {
  3198  		return err
  3199  	}
  3200  
  3201  	if notification == nil || notification.Read {
  3202  		return nil
  3203  	}
  3204  
  3205  	notification.Message = message
  3206  	notification.ReplyMessage = responseTo
  3207  	notification.UpdatedAt = m.GetCurrentTimeInMillis()
  3208  
  3209  	err = m.addActivityCenterNotification(r.Response, notification, nil)
  3210  	if err != nil {
  3211  		return err
  3212  	}
  3213  
  3214  	return nil
  3215  }
  3216  
  3217  // function returns if the community is joined before the clock
  3218  func (m *Messenger) isCommunityJoinedBeforeClock(publicKey ecdsa.PublicKey, communityID string, clock uint64) (bool, error) {
  3219  	community, err := m.communitiesManager.GetByIDString(communityID)
  3220  	if err != nil {
  3221  		return false, err
  3222  	}
  3223  
  3224  	if !community.Joined() || clock < uint64(community.JoinedAt()) {
  3225  		joinedClock, err := m.communitiesManager.GetCommunityRequestToJoinClock(&publicKey, communityID)
  3226  		if err != nil {
  3227  			return false, err
  3228  		}
  3229  
  3230  		// no request to join, or request to join is after the message
  3231  		if joinedClock == 0 || clock < joinedClock {
  3232  			return false, nil
  3233  		}
  3234  		return true, nil
  3235  	}
  3236  	return true, nil
  3237  }
  3238  
  3239  // addNewActivityCenterNotification takes a common.Message and generates a new ActivityCenterNotification and appends it to the
  3240  // []Response.ActivityCenterNotifications if the message is m.New
  3241  func (r *ReceivedMessageState) addNewActivityCenterNotification(publicKey ecdsa.PublicKey, m *Messenger, message *common.Message, responseTo *common.Message) error {
  3242  	if !message.New {
  3243  		return nil
  3244  	}
  3245  
  3246  	chat, ok := r.AllChats.Load(message.LocalChatID)
  3247  	if !ok {
  3248  		return fmt.Errorf("chat ID '%s' not present", message.LocalChatID)
  3249  	}
  3250  
  3251  	isNotification, notificationType := showMentionOrReplyActivityCenterNotification(publicKey, message, chat, responseTo)
  3252  	if !isNotification {
  3253  		return nil
  3254  	}
  3255  
  3256  	if chat.CommunityChat() {
  3257  		// Ignore mentions & replies in community before joining
  3258  		ok, err := m.isCommunityJoinedBeforeClock(publicKey, chat.CommunityID, message.Clock)
  3259  		if err != nil || !ok {
  3260  			return nil
  3261  		}
  3262  	}
  3263  
  3264  	// Use albumId as notificationId to prevent multiple notifications
  3265  	// for same message with multiple images
  3266  	var notificationID string
  3267  
  3268  	image := message.GetImage()
  3269  	var albumMessages = []*common.Message{}
  3270  	if image != nil && image.GetAlbumId() != "" {
  3271  		notificationID = image.GetAlbumId()
  3272  		album, err := m.persistence.albumMessages(message.LocalChatID, image.AlbumId)
  3273  		if err != nil {
  3274  			return err
  3275  		}
  3276  		if m.httpServer != nil {
  3277  			err = m.prepareMessagesList(album)
  3278  			if err != nil {
  3279  				return err
  3280  			}
  3281  		}
  3282  
  3283  		albumMessages = album
  3284  	} else {
  3285  		notificationID = message.ID
  3286  	}
  3287  
  3288  	notification := &ActivityCenterNotification{
  3289  		ID:            types.FromHex(notificationID),
  3290  		Name:          chat.Name,
  3291  		Message:       message,
  3292  		ReplyMessage:  responseTo,
  3293  		Type:          notificationType,
  3294  		Timestamp:     message.WhisperTimestamp,
  3295  		ChatID:        chat.ID,
  3296  		CommunityID:   chat.CommunityID,
  3297  		Author:        message.From,
  3298  		UpdatedAt:     m.GetCurrentTimeInMillis(),
  3299  		AlbumMessages: albumMessages,
  3300  		Read:          message.Seen,
  3301  	}
  3302  
  3303  	return m.addActivityCenterNotification(r.Response, notification, nil)
  3304  }
  3305  
  3306  func (m *Messenger) buildMessageState() *ReceivedMessageState {
  3307  	return &ReceivedMessageState{
  3308  		AllChats:              m.allChats,
  3309  		AllContacts:           m.allContacts,
  3310  		ModifiedContacts:      new(stringBoolMap),
  3311  		AllInstallations:      m.allInstallations,
  3312  		ModifiedInstallations: m.modifiedInstallations,
  3313  		ExistingMessagesMap:   make(map[string]bool),
  3314  		EmojiReactions:        make(map[string]*EmojiReaction),
  3315  		GroupChatInvitations:  make(map[string]*GroupChatInvitation),
  3316  		Response:              &MessengerResponse{},
  3317  		Timesource:            m.getTimesource(),
  3318  		ResolvePrimaryName:    m.ResolvePrimaryName,
  3319  		AllBookmarks:          make(map[string]*browsers.Bookmark),
  3320  		AllTrustStatus:        make(map[string]verification.TrustStatus),
  3321  	}
  3322  }
  3323  
  3324  func (m *Messenger) outputToCSV(timestamp uint32, messageID types.HexBytes, from string, topic types.TopicType, chatID string, msgType protobuf.ApplicationMetadataMessage_Type, parsedMessage interface{}) {
  3325  	if !m.outputCSV {
  3326  		return
  3327  	}
  3328  
  3329  	msgJSON, err := json.Marshal(parsedMessage)
  3330  	if err != nil {
  3331  		m.logger.Error("could not marshall message", zap.Error(err))
  3332  		return
  3333  	}
  3334  
  3335  	line := fmt.Sprintf("%d\t%s\t%s\t%s\t%s\t%s\t%s\n", timestamp, messageID.String(), from, topic.String(), chatID, msgType, msgJSON)
  3336  	_, err = m.csvFile.Write([]byte(line))
  3337  	if err != nil {
  3338  		m.logger.Error("could not write to csv", zap.Error(err))
  3339  		return
  3340  	}
  3341  }
  3342  
  3343  func (m *Messenger) shouldSkipDuplicate(messageType protobuf.ApplicationMetadataMessage_Type) bool {
  3344  	// Permit re-processing of ApplicationMetadataMessage_COMMUNITY_DESCRIPTION messages,
  3345  	// as they may be queued pending receipt of decryption keys.
  3346  	allowedDuplicateTypes := map[protobuf.ApplicationMetadataMessage_Type]struct{}{
  3347  		protobuf.ApplicationMetadataMessage_COMMUNITY_DESCRIPTION: struct{}{},
  3348  	}
  3349  	if _, isAllowedDuplicate := allowedDuplicateTypes[messageType]; isAllowedDuplicate {
  3350  		return false
  3351  	}
  3352  
  3353  	return true
  3354  }
  3355  
  3356  func (m *Messenger) handleImportedMessages(messagesToHandle map[transport.Filter][]*types.Message) error {
  3357  
  3358  	messageState := m.buildMessageState()
  3359  
  3360  	logger := m.logger.With(zap.String("site", "handleImportedMessages"))
  3361  
  3362  	for filter, messages := range messagesToHandle {
  3363  		for _, shhMessage := range messages {
  3364  
  3365  			handleMessageResponse, err := m.sender.HandleMessages(shhMessage)
  3366  			if err != nil {
  3367  				logger.Info("failed to decode messages", zap.Error(err))
  3368  				continue
  3369  			}
  3370  			statusMessages := handleMessageResponse.StatusMessages
  3371  
  3372  			for _, msg := range statusMessages {
  3373  				logger := logger.With(zap.String("message-id", msg.TransportLayer.Message.ThirdPartyID))
  3374  				logger.Debug("processing message")
  3375  
  3376  				publicKey := msg.SigPubKey()
  3377  				senderID := contactIDFromPublicKey(publicKey)
  3378  
  3379  				if len(msg.EncryptionLayer.HashRatchetInfo) != 0 {
  3380  					err := m.communitiesManager.NewHashRatchetKeys(msg.EncryptionLayer.HashRatchetInfo)
  3381  					if err != nil {
  3382  						m.logger.Warn("failed to invalidate communities description cache", zap.Error(err))
  3383  					}
  3384  
  3385  				}
  3386  				// Don't process duplicates
  3387  				messageID := msg.TransportLayer.Message.ThirdPartyID
  3388  				exists, err := m.messageExists(messageID, messageState.ExistingMessagesMap)
  3389  				if err != nil {
  3390  					logger.Warn("failed to check message exists", zap.Error(err))
  3391  				}
  3392  				if exists && m.shouldSkipDuplicate(msg.ApplicationLayer.Type) {
  3393  					logger.Debug("skipping duplicate", zap.String("messageID", messageID))
  3394  					continue
  3395  				}
  3396  
  3397  				var contact *Contact
  3398  				if c, ok := messageState.AllContacts.Load(senderID); ok {
  3399  					contact = c
  3400  				} else {
  3401  					c, err := buildContact(senderID, publicKey)
  3402  					if err != nil {
  3403  						logger.Info("failed to build contact", zap.Error(err))
  3404  						continue
  3405  					}
  3406  					contact = c
  3407  					messageState.AllContacts.Store(senderID, contact)
  3408  				}
  3409  				messageState.CurrentMessageState = &CurrentMessageState{
  3410  					MessageID:        messageID,
  3411  					WhisperTimestamp: uint64(msg.TransportLayer.Message.Timestamp) * 1000,
  3412  					Contact:          contact,
  3413  					PublicKey:        publicKey,
  3414  					StatusMessage:    msg,
  3415  				}
  3416  
  3417  				if msg.ApplicationLayer.Payload != nil {
  3418  
  3419  					logger.Debug("Handling parsed message")
  3420  
  3421  					switch msg.ApplicationLayer.Type {
  3422  
  3423  					case protobuf.ApplicationMetadataMessage_CHAT_MESSAGE:
  3424  						err = m.handleChatMessageProtobuf(messageState, msg.ApplicationLayer.Payload, msg, filter, true)
  3425  						if err != nil {
  3426  							logger.Warn("failed to handle ChatMessage", zap.Error(err))
  3427  							continue
  3428  						}
  3429  
  3430  					case protobuf.ApplicationMetadataMessage_PIN_MESSAGE:
  3431  						err = m.handlePinMessageProtobuf(messageState, msg.ApplicationLayer.Payload, msg, filter, true)
  3432  						if err != nil {
  3433  							logger.Warn("failed to handle PinMessage", zap.Error(err))
  3434  						}
  3435  					}
  3436  				}
  3437  			}
  3438  		}
  3439  	}
  3440  
  3441  	importMessageAuthors := messageState.Response.DiscordMessageAuthors()
  3442  	if len(importMessageAuthors) > 0 {
  3443  		err := m.persistence.SaveDiscordMessageAuthors(importMessageAuthors)
  3444  		if err != nil {
  3445  			return err
  3446  		}
  3447  	}
  3448  
  3449  	importMessagesToSave := messageState.Response.DiscordMessages()
  3450  	if len(importMessagesToSave) > 0 {
  3451  		m.logger.Debug("saving discord messages", zap.Int("count", len(importMessagesToSave)))
  3452  		m.handleImportMessagesMutex.Lock()
  3453  		err := m.persistence.SaveDiscordMessages(importMessagesToSave)
  3454  		if err != nil {
  3455  			m.logger.Debug("failed to save discord messages", zap.Error(err))
  3456  			m.handleImportMessagesMutex.Unlock()
  3457  			return err
  3458  		}
  3459  		m.handleImportMessagesMutex.Unlock()
  3460  	}
  3461  
  3462  	messageAttachmentsToSave := messageState.Response.DiscordMessageAttachments()
  3463  	if len(messageAttachmentsToSave) > 0 {
  3464  		m.logger.Debug("saving discord message attachments", zap.Int("count", len(messageAttachmentsToSave)))
  3465  		m.handleImportMessagesMutex.Lock()
  3466  		err := m.persistence.SaveDiscordMessageAttachments(messageAttachmentsToSave)
  3467  		if err != nil {
  3468  			m.logger.Debug("failed to save discord message attachments", zap.Error(err))
  3469  			m.handleImportMessagesMutex.Unlock()
  3470  			return err
  3471  		}
  3472  		m.handleImportMessagesMutex.Unlock()
  3473  	}
  3474  
  3475  	messagesToSave := messageState.Response.Messages()
  3476  	if len(messagesToSave) > 0 {
  3477  		m.logger.Debug("saving %d app messages", zap.Int("count", len(messagesToSave)))
  3478  		m.handleMessagesMutex.Lock()
  3479  		err := m.SaveMessages(messagesToSave)
  3480  		if err != nil {
  3481  			m.handleMessagesMutex.Unlock()
  3482  			return err
  3483  		}
  3484  		m.handleMessagesMutex.Unlock()
  3485  	}
  3486  
  3487  	// Save chats if they were modified
  3488  	if len(messageState.Response.chats) > 0 {
  3489  		err := m.saveChats(messageState.Response.Chats())
  3490  		if err != nil {
  3491  			return err
  3492  		}
  3493  	}
  3494  	return nil
  3495  }
  3496  
  3497  func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filter][]*types.Message, storeWakuMessages bool, fromArchive bool) (*MessengerResponse, error) {
  3498  
  3499  	m.handleMessagesMutex.Lock()
  3500  	defer m.handleMessagesMutex.Unlock()
  3501  
  3502  	messageState := m.buildMessageState()
  3503  
  3504  	logger := m.logger.With(zap.String("site", "RetrieveAll"))
  3505  
  3506  	controlledCommunitiesChatIDs, err := m.communitiesManager.GetOwnedCommunitiesChatIDs()
  3507  	if err != nil {
  3508  		logger.Info("failed to retrieve admin communities", zap.Error(err))
  3509  	}
  3510  
  3511  	iterator := m.retrievedMessagesIteratorFactory(chatWithMessages)
  3512  	for iterator.HasNext() {
  3513  		filter, messages := iterator.Next()
  3514  
  3515  		var processedMessages []string
  3516  		for _, shhMessage := range messages {
  3517  			logger := logger.With(zap.String("hash", types.EncodeHex(shhMessage.Hash)))
  3518  			// Indicates tha all messages in the batch have been processed correctly
  3519  			allMessagesProcessed := true
  3520  
  3521  			if controlledCommunitiesChatIDs[filter.ChatID] && storeWakuMessages {
  3522  				logger.Debug("storing waku message")
  3523  				err := m.communitiesManager.StoreWakuMessage(shhMessage)
  3524  				if err != nil {
  3525  					logger.Warn("failed to store waku message", zap.Error(err))
  3526  				}
  3527  			}
  3528  
  3529  			handleMessagesResponse, err := m.sender.HandleMessages(shhMessage)
  3530  			if err != nil {
  3531  				if m.telemetryClient != nil {
  3532  					go m.telemetryClient.UpdateEnvelopeProcessingError(shhMessage, err)
  3533  				}
  3534  				logger.Info("failed to decode messages", zap.Error(err))
  3535  				continue
  3536  			}
  3537  
  3538  			if handleMessagesResponse == nil {
  3539  				continue
  3540  			}
  3541  
  3542  			statusMessages := handleMessagesResponse.StatusMessages
  3543  
  3544  			if m.telemetryClient != nil {
  3545  				m.telemetryClient.PushReceivedMessages(m.ctx, telemetry.ReceivedMessages{
  3546  					Filter:     filter,
  3547  					SSHMessage: shhMessage,
  3548  					Messages:   statusMessages,
  3549  				})
  3550  			}
  3551  
  3552  			err = m.handleDatasyncMetadata(handleMessagesResponse)
  3553  			if err != nil {
  3554  				m.logger.Warn("failed to handle datasync metadata", zap.Error(err))
  3555  			}
  3556  
  3557  			logger.Debug("processing messages further", zap.Int("count", len(statusMessages)))
  3558  
  3559  			for _, msg := range statusMessages {
  3560  				logger := logger.With(zap.String("message-id", msg.ApplicationLayer.ID.String()))
  3561  
  3562  				publicKey := msg.SigPubKey()
  3563  
  3564  				m.handleInstallations(msg.EncryptionLayer.Installations)
  3565  				err := m.handleSharedSecrets(msg.EncryptionLayer.SharedSecrets)
  3566  				if err != nil {
  3567  					// log and continue, non-critical error
  3568  					logger.Warn("failed to handle shared secrets")
  3569  				}
  3570  
  3571  				senderID := contactIDFromPublicKey(publicKey)
  3572  				ownID := contactIDFromPublicKey(m.IdentityPublicKey())
  3573  				logger.Info("processing message", zap.Any("type", msg.ApplicationLayer.Type), zap.String("senderID", senderID))
  3574  
  3575  				if senderID == ownID {
  3576  					// Skip own messages of certain types
  3577  					if msg.ApplicationLayer.Type == protobuf.ApplicationMetadataMessage_CONTACT_CODE_ADVERTISEMENT {
  3578  						continue
  3579  					}
  3580  				}
  3581  
  3582  				contact, contactFound := messageState.AllContacts.Load(senderID)
  3583  
  3584  				// Check for messages from blocked users
  3585  				if contactFound && contact.Blocked {
  3586  					continue
  3587  				}
  3588  
  3589  				// Don't process duplicates
  3590  				messageID := types.EncodeHex(msg.ApplicationLayer.ID)
  3591  				exists, err := m.messageExists(messageID, messageState.ExistingMessagesMap)
  3592  				if err != nil {
  3593  					logger.Warn("failed to check message exists", zap.Error(err))
  3594  				}
  3595  				if exists && m.shouldSkipDuplicate(msg.ApplicationLayer.Type) {
  3596  					logger.Debug("skipping duplicate", zap.String("messageID", messageID))
  3597  					continue
  3598  				}
  3599  
  3600  				if !contactFound {
  3601  					c, err := buildContact(senderID, publicKey)
  3602  					if err != nil {
  3603  						logger.Info("failed to build contact", zap.Error(err))
  3604  						allMessagesProcessed = false
  3605  						continue
  3606  					}
  3607  					contact = c
  3608  					if msg.ApplicationLayer.Type != protobuf.ApplicationMetadataMessage_PUSH_NOTIFICATION_QUERY {
  3609  						messageState.AllContacts.Store(senderID, contact)
  3610  					}
  3611  				}
  3612  				messageState.CurrentMessageState = &CurrentMessageState{
  3613  					MessageID:        messageID,
  3614  					WhisperTimestamp: uint64(msg.TransportLayer.Message.Timestamp) * 1000,
  3615  					Contact:          contact,
  3616  					PublicKey:        publicKey,
  3617  					StatusMessage:    msg,
  3618  				}
  3619  
  3620  				if msg.ApplicationLayer.Payload != nil {
  3621  
  3622  					err := m.dispatchToHandler(messageState, msg.ApplicationLayer.Payload, msg, filter, fromArchive)
  3623  					if err != nil {
  3624  						allMessagesProcessed = false
  3625  						logger.Warn("failed to process protobuf", zap.Error(err))
  3626  						if m.unhandledMessagesTracker != nil {
  3627  							m.unhandledMessagesTracker(msg, err)
  3628  						}
  3629  						continue
  3630  					}
  3631  					logger.Debug("Handled parsed message")
  3632  
  3633  				} else {
  3634  					logger.Debug("parsed message is nil")
  3635  				}
  3636  			}
  3637  
  3638  			m.processCommunityChanges(messageState)
  3639  
  3640  			// NOTE: for now we confirm messages as processed regardless whether we
  3641  			// actually processed them, this is because we need to differentiate
  3642  			// from messages that we want to retry to process and messages that
  3643  			// are never going to be processed
  3644  			m.transport.MarkP2PMessageAsProcessed(gethcommon.BytesToHash(shhMessage.Hash))
  3645  
  3646  			if allMessagesProcessed {
  3647  				processedMessages = append(processedMessages, types.EncodeHex(shhMessage.Hash))
  3648  			}
  3649  		}
  3650  
  3651  		if len(processedMessages) != 0 {
  3652  			if err := m.transport.ConfirmMessagesProcessed(processedMessages, m.getTimesource().GetCurrentTime()); err != nil {
  3653  				logger.Warn("failed to confirm processed messages", zap.Error(err))
  3654  			}
  3655  		}
  3656  	}
  3657  
  3658  	return m.saveDataAndPrepareResponse(messageState)
  3659  }
  3660  
  3661  func (m *Messenger) saveDataAndPrepareResponse(messageState *ReceivedMessageState) (*MessengerResponse, error) {
  3662  	var err error
  3663  	var contactsToSave []*Contact
  3664  	messageState.ModifiedContacts.Range(func(id string, value bool) (shouldContinue bool) {
  3665  		contact, ok := messageState.AllContacts.Load(id)
  3666  		if ok {
  3667  			contactsToSave = append(contactsToSave, contact)
  3668  			messageState.Response.AddContact(contact)
  3669  		}
  3670  		return true
  3671  	})
  3672  
  3673  	// Hydrate chat alias and identicon
  3674  	for id := range messageState.Response.chats {
  3675  		chat, _ := messageState.AllChats.Load(id)
  3676  		if chat == nil {
  3677  			continue
  3678  		}
  3679  		if chat.OneToOne() {
  3680  			contact, ok := m.allContacts.Load(chat.ID)
  3681  			if ok {
  3682  				chat.Alias = contact.Alias
  3683  				chat.Identicon = contact.Identicon
  3684  			}
  3685  		}
  3686  
  3687  		messageState.Response.AddChat(chat)
  3688  	}
  3689  
  3690  	messageState.ModifiedInstallations.Range(func(id string, value bool) (shouldContinue bool) {
  3691  		installation, _ := messageState.AllInstallations.Load(id)
  3692  		messageState.Response.AddInstallation(installation)
  3693  		if installation.InstallationMetadata != nil {
  3694  			err = m.setInstallationMetadata(id, installation.InstallationMetadata)
  3695  			if err != nil {
  3696  				return false
  3697  			}
  3698  		}
  3699  
  3700  		return true
  3701  	})
  3702  	if err != nil {
  3703  		return nil, err
  3704  	}
  3705  
  3706  	if len(messageState.Response.chats) > 0 {
  3707  		err = m.saveChats(messageState.Response.Chats())
  3708  		if err != nil {
  3709  			return nil, err
  3710  		}
  3711  	}
  3712  
  3713  	messagesToSave := messageState.Response.Messages()
  3714  	if len(messagesToSave) > 0 {
  3715  		err = m.SaveMessages(messagesToSave)
  3716  		if err != nil {
  3717  			return nil, err
  3718  		}
  3719  	}
  3720  
  3721  	for _, emojiReaction := range messageState.EmojiReactions {
  3722  		messageState.Response.AddEmojiReaction(emojiReaction)
  3723  	}
  3724  
  3725  	for _, groupChatInvitation := range messageState.GroupChatInvitations {
  3726  		messageState.Response.Invitations = append(messageState.Response.Invitations, groupChatInvitation)
  3727  	}
  3728  
  3729  	if len(contactsToSave) > 0 {
  3730  		err = m.persistence.SaveContacts(contactsToSave)
  3731  		if err != nil {
  3732  			return nil, err
  3733  		}
  3734  	}
  3735  
  3736  	newMessagesIds := map[string]struct{}{}
  3737  	for _, message := range messagesToSave {
  3738  		if message.New {
  3739  			newMessagesIds[message.ID] = struct{}{}
  3740  		}
  3741  	}
  3742  
  3743  	messagesWithResponses, err := m.pullMessagesAndResponsesFromDB(messagesToSave)
  3744  	if err != nil {
  3745  		return nil, err
  3746  	}
  3747  	messagesByID := map[string]*common.Message{}
  3748  	for _, message := range messagesWithResponses {
  3749  		messagesByID[message.ID] = message
  3750  	}
  3751  	messageState.Response.SetMessages(messagesWithResponses)
  3752  
  3753  	notificationsEnabled, err := m.settings.GetNotificationsEnabled()
  3754  	if err != nil {
  3755  		return nil, err
  3756  	}
  3757  
  3758  	profilePicturesVisibility, err := m.settings.GetProfilePicturesVisibility()
  3759  	if err != nil {
  3760  		return nil, err
  3761  	}
  3762  
  3763  	err = m.prepareMessages(messageState.Response.messages)
  3764  	if err != nil {
  3765  		return nil, err
  3766  	}
  3767  
  3768  	for _, message := range messageState.Response.messages {
  3769  		if _, ok := newMessagesIds[message.ID]; ok {
  3770  			message.New = true
  3771  
  3772  			if notificationsEnabled {
  3773  				// Create notification body to be eventually passed to `localnotifications.SendMessageNotifications()`
  3774  				if err = messageState.addNewMessageNotification(m.identity.PublicKey, message, messagesByID[message.ResponseTo], profilePicturesVisibility); err != nil {
  3775  					return nil, err
  3776  				}
  3777  			}
  3778  
  3779  			// Create activity center notification body to be eventually passed to `activitycenter.SendActivityCenterNotifications()`
  3780  			if err = messageState.addNewActivityCenterNotification(m.identity.PublicKey, m, message, messagesByID[message.ResponseTo]); err != nil {
  3781  				return nil, err
  3782  			}
  3783  		}
  3784  	}
  3785  
  3786  	// Reset installations
  3787  	m.modifiedInstallations = new(stringBoolMap)
  3788  
  3789  	if len(messageState.AllBookmarks) > 0 {
  3790  		bookmarks, err := m.storeSyncBookmarks(messageState.AllBookmarks)
  3791  		if err != nil {
  3792  			return nil, err
  3793  		}
  3794  		messageState.Response.AddBookmarks(bookmarks)
  3795  	}
  3796  
  3797  	if len(messageState.AllVerificationRequests) > 0 {
  3798  		for _, vr := range messageState.AllVerificationRequests {
  3799  			messageState.Response.AddVerificationRequest(vr)
  3800  		}
  3801  	}
  3802  
  3803  	if len(messageState.AllTrustStatus) > 0 {
  3804  		messageState.Response.AddTrustStatuses(messageState.AllTrustStatus)
  3805  	}
  3806  
  3807  	// Hydrate pinned messages
  3808  	for _, pinnedMessage := range messageState.Response.PinMessages() {
  3809  		if pinnedMessage.Pinned {
  3810  			pinnedMessage.Message = &common.PinnedMessage{
  3811  				Message:  messageState.Response.GetMessage(pinnedMessage.MessageId),
  3812  				PinnedBy: pinnedMessage.From,
  3813  				PinnedAt: pinnedMessage.Clock,
  3814  			}
  3815  		}
  3816  	}
  3817  
  3818  	return messageState.Response, nil
  3819  }
  3820  
  3821  func (m *Messenger) storeSyncBookmarks(bookmarkMap map[string]*browsers.Bookmark) ([]*browsers.Bookmark, error) {
  3822  	var bookmarks []*browsers.Bookmark
  3823  	for _, bookmark := range bookmarkMap {
  3824  		bookmarks = append(bookmarks, bookmark)
  3825  	}
  3826  	return m.browserDatabase.StoreSyncBookmarks(bookmarks)
  3827  }
  3828  
  3829  func (m *Messenger) MessageByID(id string) (*common.Message, error) {
  3830  	msg, err := m.persistence.MessageByID(id)
  3831  	if err != nil {
  3832  		return nil, err
  3833  	}
  3834  	if m.httpServer != nil {
  3835  		err = m.prepareMessage(msg, m.httpServer)
  3836  		if err != nil {
  3837  			return nil, err
  3838  		}
  3839  	}
  3840  	return msg, nil
  3841  }
  3842  
  3843  func (m *Messenger) MessagesExist(ids []string) (map[string]bool, error) {
  3844  	return m.persistence.MessagesExist(ids)
  3845  }
  3846  
  3847  func (m *Messenger) FirstUnseenMessageID(chatID string) (string, error) {
  3848  	return m.persistence.FirstUnseenMessageID(chatID)
  3849  }
  3850  
  3851  func (m *Messenger) latestIncomingMessageClock(chatID string) (uint64, error) {
  3852  	return m.persistence.latestIncomingMessageClock(chatID)
  3853  }
  3854  
  3855  func (m *Messenger) MessageByChatID(chatID, cursor string, limit int) ([]*common.Message, string, error) {
  3856  	chat, err := m.persistence.Chat(chatID)
  3857  	if err != nil {
  3858  		return nil, "", err
  3859  	}
  3860  
  3861  	if chat == nil {
  3862  		return nil, "", ErrChatNotFound
  3863  	}
  3864  
  3865  	var msgs []*common.Message
  3866  	var nextCursor string
  3867  
  3868  	if chat.Timeline() {
  3869  		var chatIDs = []string{"@" + contactIDFromPublicKey(&m.identity.PublicKey)}
  3870  		m.allContacts.Range(func(contactID string, contact *Contact) (shouldContinue bool) {
  3871  			if contact.added() {
  3872  				chatIDs = append(chatIDs, "@"+contact.ID)
  3873  			}
  3874  			return true
  3875  		})
  3876  		msgs, nextCursor, err = m.persistence.MessageByChatIDs(chatIDs, cursor, limit)
  3877  		if err != nil {
  3878  			return nil, "", err
  3879  		}
  3880  	} else {
  3881  		msgs, nextCursor, err = m.persistence.MessageByChatID(chatID, cursor, limit)
  3882  		if err != nil {
  3883  			return nil, "", err
  3884  		}
  3885  
  3886  	}
  3887  
  3888  	if m.httpServer != nil {
  3889  		err = m.prepareMessagesList(msgs)
  3890  		if err != nil {
  3891  			return nil, "", err
  3892  		}
  3893  	}
  3894  
  3895  	return msgs, nextCursor, nil
  3896  }
  3897  
  3898  func (m *Messenger) prepareMessages(messages map[string]*common.Message) error {
  3899  	if m.httpServer == nil {
  3900  		return nil
  3901  	}
  3902  	for idx := range messages {
  3903  		err := m.prepareMessage(messages[idx], m.httpServer)
  3904  		if err != nil {
  3905  			return err
  3906  		}
  3907  	}
  3908  	return nil
  3909  }
  3910  
  3911  func (m *Messenger) prepareMessagesList(messages []*common.Message) error {
  3912  	if m.httpServer == nil {
  3913  		return nil
  3914  	}
  3915  	for idx := range messages {
  3916  		err := m.prepareMessage(messages[idx], m.httpServer)
  3917  		if err != nil {
  3918  			return err
  3919  		}
  3920  	}
  3921  	return nil
  3922  }
  3923  
  3924  func extractQuotedImages(messages []*common.Message, s *server.MediaServer) []string {
  3925  	var quotedImages []string
  3926  
  3927  	for _, message := range messages {
  3928  		if message.ChatMessage != nil && message.ChatMessage.ContentType == protobuf.ChatMessage_IMAGE {
  3929  			quotedImages = append(quotedImages, s.MakeImageURL(message.ID))
  3930  		}
  3931  	}
  3932  	return quotedImages
  3933  }
  3934  
  3935  func (m *Messenger) prepareTokenData(tokenData *ActivityTokenData, s *server.MediaServer) error {
  3936  	if tokenData.TokenType == int(protobuf.CommunityTokenType_ERC721) {
  3937  		tokenData.ImageURL = s.MakeWalletCollectibleImagesURL(tokenData.CollectibleID)
  3938  	} else if tokenData.TokenType == int(protobuf.CommunityTokenType_ERC20) {
  3939  		tokenData.ImageURL = s.MakeCommunityTokenImagesURL(tokenData.CommunityID, tokenData.ChainID, tokenData.Symbol)
  3940  	}
  3941  	return nil
  3942  }
  3943  
  3944  func (m *Messenger) prepareMessage(msg *common.Message, s *server.MediaServer) error {
  3945  	if msg.QuotedMessage != nil && msg.QuotedMessage.ContentType == int64(protobuf.ChatMessage_IMAGE) {
  3946  		msg.QuotedMessage.ImageLocalURL = s.MakeImageURL(msg.QuotedMessage.ID)
  3947  
  3948  		quotedMessage, err := m.MessageByID(msg.QuotedMessage.ID)
  3949  		if err != nil {
  3950  			return err
  3951  		}
  3952  		if quotedMessage == nil {
  3953  			return errors.New("message not found")
  3954  		}
  3955  
  3956  		if quotedMessage.ChatMessage != nil {
  3957  			image := quotedMessage.ChatMessage.GetImage()
  3958  			albumID := quotedMessage.ChatMessage.GetImage().AlbumId
  3959  
  3960  			if image != nil && image.GetAlbumId() != "" {
  3961  				albumMessages, err := m.persistence.albumMessages(quotedMessage.LocalChatID, albumID)
  3962  				if err != nil {
  3963  					return err
  3964  				}
  3965  
  3966  				quotedImages := extractQuotedImages(albumMessages, s)
  3967  				quotedImagesJSON, err := json.Marshal(quotedImages)
  3968  				if err != nil {
  3969  					return err
  3970  				}
  3971  
  3972  				msg.QuotedMessage.AlbumImages = quotedImagesJSON
  3973  			}
  3974  		}
  3975  	}
  3976  	if msg.QuotedMessage != nil && msg.QuotedMessage.ContentType == int64(protobuf.ChatMessage_AUDIO) {
  3977  		msg.QuotedMessage.AudioLocalURL = s.MakeAudioURL(msg.QuotedMessage.ID)
  3978  	}
  3979  	if msg.QuotedMessage != nil && msg.QuotedMessage.ContentType == int64(protobuf.ChatMessage_STICKER) {
  3980  		msg.QuotedMessage.HasSticker = true
  3981  	}
  3982  	if msg.QuotedMessage != nil && msg.QuotedMessage.ContentType == int64(protobuf.ChatMessage_DISCORD_MESSAGE) {
  3983  		dm := msg.QuotedMessage.DiscordMessage
  3984  		exists, err := m.persistence.HasDiscordMessageAuthorImagePayload(dm.Author.Id)
  3985  		if err != nil {
  3986  			return err
  3987  		}
  3988  
  3989  		if exists {
  3990  			msg.QuotedMessage.DiscordMessage.Author.LocalUrl = s.MakeDiscordAuthorAvatarURL(dm.Author.Id)
  3991  		}
  3992  	}
  3993  
  3994  	if msg.ContentType == protobuf.ChatMessage_IMAGE {
  3995  		msg.ImageLocalURL = s.MakeImageURL(msg.ID)
  3996  	}
  3997  
  3998  	if msg.ContentType == protobuf.ChatMessage_DISCORD_MESSAGE {
  3999  
  4000  		dm := msg.GetDiscordMessage()
  4001  		exists, err := m.persistence.HasDiscordMessageAuthorImagePayload(dm.Author.Id)
  4002  		if err != nil {
  4003  			return err
  4004  		}
  4005  
  4006  		if exists {
  4007  			dm.Author.LocalUrl = s.MakeDiscordAuthorAvatarURL(dm.Author.Id)
  4008  		}
  4009  
  4010  		for idx, attachment := range dm.Attachments {
  4011  			if strings.Contains(attachment.ContentType, "image") {
  4012  				hasPayload, err := m.persistence.HasDiscordMessageAttachmentPayload(attachment.Id, dm.Id)
  4013  				if err != nil {
  4014  					m.logger.Error("failed to check if message attachment exist", zap.Error(err))
  4015  					continue
  4016  				}
  4017  				if hasPayload {
  4018  					localURL := s.MakeDiscordAttachmentURL(dm.Id, attachment.Id)
  4019  					dm.Attachments[idx].LocalUrl = localURL
  4020  				}
  4021  			}
  4022  		}
  4023  		msg.Payload = &protobuf.ChatMessage_DiscordMessage{
  4024  			DiscordMessage: dm,
  4025  		}
  4026  	}
  4027  	if msg.ContentType == protobuf.ChatMessage_AUDIO {
  4028  		msg.AudioLocalURL = s.MakeAudioURL(msg.ID)
  4029  	}
  4030  	if msg.ContentType == protobuf.ChatMessage_STICKER {
  4031  		msg.StickerLocalURL = s.MakeStickerURL(msg.GetSticker().Hash)
  4032  	}
  4033  	msg.LinkPreviews = msg.ConvertFromProtoToLinkPreviews(s.MakeLinkPreviewThumbnailURL, s.MakeLinkPreviewFaviconURL)
  4034  	msg.StatusLinkPreviews = msg.ConvertFromProtoToStatusLinkPreviews(s.MakeStatusLinkPreviewThumbnailURL)
  4035  
  4036  	return nil
  4037  }
  4038  
  4039  func (m *Messenger) AllMessageByChatIDWhichMatchTerm(chatID string, searchTerm string, caseSensitive bool) ([]*common.Message, error) {
  4040  	_, err := m.persistence.Chat(chatID)
  4041  	if err != nil {
  4042  		return nil, err
  4043  	}
  4044  
  4045  	messages, err := m.persistence.AllMessageByChatIDWhichMatchTerm(chatID, searchTerm, caseSensitive)
  4046  	if err != nil {
  4047  		return nil, err
  4048  	}
  4049  
  4050  	return m.filterOutHiddenChatMessages(messages)
  4051  
  4052  }
  4053  
  4054  func (m *Messenger) AllMessagesFromChatsAndCommunitiesWhichMatchTerm(communityIds []string, chatIds []string, searchTerm string, caseSensitive bool) ([]*common.Message, error) {
  4055  	messages, err := m.persistence.AllMessagesFromChatsAndCommunitiesWhichMatchTerm(communityIds, chatIds, searchTerm, caseSensitive)
  4056  	if err != nil {
  4057  		return nil, err
  4058  	}
  4059  
  4060  	return m.filterOutHiddenChatMessages(messages)
  4061  }
  4062  
  4063  func (m *Messenger) filterOutHiddenChatMessages(messages []*common.Message) ([]*common.Message, error) {
  4064  	communitiesCache := make(map[string]*communities.Community)
  4065  	chatVisibilityCache := make(map[string]bool)
  4066  	var filteredMessages []*common.Message
  4067  
  4068  	for _, message := range messages {
  4069  		chatVisible, ok := chatVisibilityCache[message.ChatId]
  4070  		if ok && chatVisible {
  4071  			filteredMessages = append(filteredMessages, message)
  4072  			continue
  4073  		}
  4074  
  4075  		chat, ok := m.allChats.Load(message.ChatId)
  4076  		if !ok {
  4077  			return nil, ErrChatNotFoundError
  4078  		}
  4079  
  4080  		if chat.CommunityID == "" {
  4081  			filteredMessages = append(filteredMessages, message)
  4082  			continue
  4083  		}
  4084  
  4085  		community, ok := communitiesCache[chat.CommunityID]
  4086  		if !ok {
  4087  			communityID, err := hexutil.Decode(chat.CommunityID)
  4088  			if err != nil {
  4089  				return nil, err
  4090  			}
  4091  			comm, err := m.communitiesManager.GetByID(communityID)
  4092  			if err != nil {
  4093  				if err == communities.ErrOrgNotFound {
  4094  					continue
  4095  				}
  4096  				return nil, err
  4097  			}
  4098  			communitiesCache[chat.CommunityID] = comm
  4099  			community = comm
  4100  		}
  4101  
  4102  		canView := community.CanView(&m.identity.PublicKey, chat.CommunityChannelID())
  4103  		chatVisibilityCache[chat.ID] = canView
  4104  
  4105  		if canView {
  4106  			filteredMessages = append(filteredMessages, message)
  4107  		}
  4108  	}
  4109  
  4110  	return filteredMessages, nil
  4111  }
  4112  
  4113  func (m *Messenger) SaveMessages(messages []*common.Message) error {
  4114  	return m.persistence.SaveMessages(messages)
  4115  }
  4116  
  4117  func (m *Messenger) DeleteMessage(id string) error {
  4118  	return m.persistence.DeleteMessage(id)
  4119  }
  4120  
  4121  func (m *Messenger) DeleteMessagesByChatID(id string) error {
  4122  	return m.persistence.DeleteMessagesByChatID(id)
  4123  }
  4124  
  4125  func (m *Messenger) markMessageAsUnreadImpl(chatID string, messageID string) (uint64, uint64, error) {
  4126  	count, countWithMentions, err := m.persistence.MarkMessageAsUnread(chatID, messageID)
  4127  
  4128  	if err != nil {
  4129  		return 0, 0, err
  4130  	}
  4131  
  4132  	chat, err := m.persistence.Chat(chatID)
  4133  	if err != nil {
  4134  		return 0, 0, err
  4135  	}
  4136  	m.allChats.Store(chatID, chat)
  4137  	return count, countWithMentions, nil
  4138  }
  4139  
  4140  func (m *Messenger) MarkMessageAsUnread(chatID string, messageID string) (*MessengerResponse, error) {
  4141  	count, countWithMentions, err := m.markMessageAsUnreadImpl(chatID, messageID)
  4142  	if err != nil {
  4143  		return nil, err
  4144  	}
  4145  
  4146  	response := &MessengerResponse{}
  4147  	response.AddSeenAndUnseenMessages(&SeenUnseenMessages{
  4148  		ChatID:            chatID,
  4149  		Count:             count,
  4150  		CountWithMentions: countWithMentions,
  4151  		Seen:              false,
  4152  	})
  4153  
  4154  	ids, err := m.persistence.GetMessageIdsWithGreaterTimestamp(chatID, messageID)
  4155  	if err != nil {
  4156  		return nil, err
  4157  	}
  4158  
  4159  	hexBytesIds := []types.HexBytes{}
  4160  	for _, id := range ids {
  4161  		hexBytesIds = append(hexBytesIds, types.FromHex(id))
  4162  	}
  4163  
  4164  	updatedAt := m.GetCurrentTimeInMillis()
  4165  	notifications, err := m.persistence.MarkActivityCenterNotificationsUnread(hexBytesIds, updatedAt)
  4166  	if err != nil {
  4167  		return nil, err
  4168  	}
  4169  
  4170  	response.AddActivityCenterNotifications(notifications)
  4171  
  4172  	return response, nil
  4173  }
  4174  
  4175  // MarkMessagesSeen marks messages with `ids` as seen in the chat `chatID`.
  4176  // It returns the number of affected messages or error. If there is an error,
  4177  // the number of affected messages is always zero.
  4178  func (m *Messenger) markMessagesSeenImpl(chatID string, ids []string) (uint64, uint64, *Chat, error) {
  4179  	count, countWithMentions, err := m.persistence.MarkMessagesSeen(chatID, ids)
  4180  	if err != nil {
  4181  		return 0, 0, nil, err
  4182  	}
  4183  	chat, err := m.persistence.Chat(chatID)
  4184  	if err != nil {
  4185  		return 0, 0, nil, err
  4186  	}
  4187  	m.allChats.Store(chatID, chat)
  4188  	return count, countWithMentions, chat, nil
  4189  }
  4190  
  4191  // Deprecated: Use MarkMessagesRead instead
  4192  func (m *Messenger) MarkMessagesSeen(chatID string, ids []string) (uint64, uint64, []*ActivityCenterNotification, error) {
  4193  	count, countWithMentions, _, err := m.markMessagesSeenImpl(chatID, ids)
  4194  	if err != nil {
  4195  		return 0, 0, nil, err
  4196  	}
  4197  
  4198  	hexBytesIds := []types.HexBytes{}
  4199  	for _, id := range ids {
  4200  		hexBytesIds = append(hexBytesIds, types.FromHex(id))
  4201  	}
  4202  
  4203  	// Mark notifications as read in the database
  4204  	updatedAt := m.GetCurrentTimeInMillis()
  4205  	err = m.persistence.MarkActivityCenterNotificationsRead(hexBytesIds, updatedAt)
  4206  	if err != nil {
  4207  		return 0, 0, nil, err
  4208  	}
  4209  
  4210  	notifications, err := m.persistence.GetActivityCenterNotificationsByID(hexBytesIds)
  4211  	if err != nil {
  4212  		return 0, 0, nil, err
  4213  	}
  4214  
  4215  	return count, countWithMentions, notifications, nil
  4216  }
  4217  
  4218  func (m *Messenger) MarkMessagesRead(chatID string, ids []string) (*MessengerResponse, error) {
  4219  	count, countWithMentions, _, err := m.markMessagesSeenImpl(chatID, ids)
  4220  	if err != nil {
  4221  		return nil, err
  4222  	}
  4223  
  4224  	response := &MessengerResponse{}
  4225  	response.AddSeenAndUnseenMessages(&SeenUnseenMessages{
  4226  		ChatID:            chatID,
  4227  		Count:             count,
  4228  		CountWithMentions: countWithMentions,
  4229  		Seen:              true,
  4230  	})
  4231  
  4232  	hexBytesIds := []types.HexBytes{}
  4233  	for _, id := range ids {
  4234  		hexBytesIds = append(hexBytesIds, types.FromHex(id))
  4235  	}
  4236  
  4237  	// Mark notifications as read in the database
  4238  	updatedAt := m.GetCurrentTimeInMillis()
  4239  	err = m.persistence.MarkActivityCenterNotificationsRead(hexBytesIds, updatedAt)
  4240  	if err != nil {
  4241  		return nil, err
  4242  	}
  4243  
  4244  	notifications, err := m.persistence.GetActivityCenterNotificationsByID(hexBytesIds)
  4245  	if err != nil {
  4246  		return nil, err
  4247  	}
  4248  
  4249  	response.AddActivityCenterNotifications(notifications)
  4250  
  4251  	return response, nil
  4252  }
  4253  
  4254  func (m *Messenger) syncChatMessagesRead(ctx context.Context, chatID string, clock uint64, rawMessageHandler RawMessageHandler) error {
  4255  	if !m.hasPairedDevices() {
  4256  		return nil
  4257  	}
  4258  
  4259  	_, chat := m.getLastClockWithRelatedChat()
  4260  
  4261  	syncMessage := &protobuf.SyncChatMessagesRead{
  4262  		Clock: clock,
  4263  		Id:    chatID,
  4264  	}
  4265  	encodedMessage, err := proto.Marshal(syncMessage)
  4266  	if err != nil {
  4267  		return err
  4268  	}
  4269  
  4270  	rawMessage := common.RawMessage{
  4271  		LocalChatID: chat.ID,
  4272  		Payload:     encodedMessage,
  4273  		MessageType: protobuf.ApplicationMetadataMessage_SYNC_CHAT_MESSAGES_READ,
  4274  		ResendType:  common.ResendTypeDataSync,
  4275  	}
  4276  
  4277  	_, err = rawMessageHandler(ctx, rawMessage)
  4278  
  4279  	return err
  4280  }
  4281  
  4282  func (m *Messenger) markAllRead(chatID string, clock uint64, shouldBeSynced bool) error {
  4283  	chat, ok := m.allChats.Load(chatID)
  4284  	if !ok {
  4285  		return ErrChatNotFoundError
  4286  	}
  4287  
  4288  	_, _, err := m.persistence.MarkAllRead(chatID, clock)
  4289  	if err != nil {
  4290  		return err
  4291  	}
  4292  
  4293  	if shouldBeSynced {
  4294  		err := m.syncChatMessagesRead(context.Background(), chatID, clock, m.dispatchMessage)
  4295  		if err != nil {
  4296  			return err
  4297  		}
  4298  	}
  4299  
  4300  	chat.ReadMessagesAtClockValue = clock
  4301  	chat.Highlight = false
  4302  
  4303  	chat.UnviewedMessagesCount = 0
  4304  	chat.UnviewedMentionsCount = 0
  4305  
  4306  	if chat.LastMessage != nil {
  4307  		chat.LastMessage.Seen = true
  4308  	}
  4309  
  4310  	// TODO(samyoul) remove storing of an updated reference pointer?
  4311  	m.allChats.Store(chat.ID, chat)
  4312  	return m.persistence.SaveChats([]*Chat{chat})
  4313  }
  4314  
  4315  func (m *Messenger) MarkAllRead(ctx context.Context, chatID string) (*MessengerResponse, error) {
  4316  	response := &MessengerResponse{}
  4317  
  4318  	notifications, err := m.DismissAllActivityCenterNotificationsFromChatID(ctx, chatID, m.GetCurrentTimeInMillis())
  4319  	if err != nil {
  4320  		return nil, err
  4321  	}
  4322  	response.AddActivityCenterNotifications(notifications)
  4323  
  4324  	clock, _ := m.latestIncomingMessageClock(chatID)
  4325  
  4326  	if clock == 0 {
  4327  		chat, ok := m.allChats.Load(chatID)
  4328  		if !ok {
  4329  			return nil, ErrChatNotFoundError
  4330  		}
  4331  		clock, _ = chat.NextClockAndTimestamp(m.getTimesource())
  4332  	}
  4333  
  4334  	err = m.markAllRead(chatID, clock, true)
  4335  	if err != nil {
  4336  		return nil, err
  4337  	}
  4338  	return response, nil
  4339  }
  4340  
  4341  func (m *Messenger) MarkAllReadInCommunity(ctx context.Context, communityID string) (*MessengerResponse, error) {
  4342  	response := &MessengerResponse{}
  4343  
  4344  	notifications, err := m.DismissAllActivityCenterNotificationsFromCommunity(ctx, communityID, m.GetCurrentTimeInMillis())
  4345  	if err != nil {
  4346  		return nil, err
  4347  	}
  4348  	response.AddActivityCenterNotifications(notifications)
  4349  
  4350  	chatIDs, err := m.persistence.AllChatIDsByCommunity(nil, communityID)
  4351  	if err != nil {
  4352  		return nil, err
  4353  	}
  4354  
  4355  	err = m.persistence.MarkAllReadMultiple(chatIDs)
  4356  	if err != nil {
  4357  		return nil, err
  4358  	}
  4359  
  4360  	for _, chatID := range chatIDs {
  4361  		chat, ok := m.allChats.Load(chatID)
  4362  
  4363  		if ok {
  4364  			chat.UnviewedMessagesCount = 0
  4365  			chat.UnviewedMentionsCount = 0
  4366  			m.allChats.Store(chat.ID, chat)
  4367  			response.AddChat(chat)
  4368  		} else {
  4369  			err = fmt.Errorf("chat with chatID %s not found", chatID)
  4370  		}
  4371  	}
  4372  	return response, err
  4373  }
  4374  
  4375  // MuteChat signals to the messenger that we don't want to be notified
  4376  // on new messages from this chat
  4377  func (m *Messenger) MuteChat(request *requests.MuteChat) (time.Time, error) {
  4378  	chat, ok := m.allChats.Load(request.ChatID)
  4379  	if !ok {
  4380  		// Only one to one chan be muted when it's not in the database
  4381  		publicKey, err := common.HexToPubkey(request.ChatID)
  4382  		if err != nil {
  4383  			return time.Time{}, err
  4384  		}
  4385  
  4386  		// Create a one to one chat and set active to false
  4387  		chat = CreateOneToOneChat(request.ChatID, publicKey, m.getTimesource())
  4388  		chat.Active = false
  4389  		err = m.initChatSyncFields(chat)
  4390  		if err != nil {
  4391  			return time.Time{}, err
  4392  		}
  4393  		err = m.saveChat(chat)
  4394  		if err != nil {
  4395  			return time.Time{}, err
  4396  		}
  4397  	}
  4398  
  4399  	var contact *Contact
  4400  	if chat.OneToOne() {
  4401  		contact, _ = m.allContacts.Load(request.ChatID)
  4402  	}
  4403  
  4404  	var MuteTill time.Time
  4405  
  4406  	switch request.MutedType {
  4407  	case MuteTill1Min:
  4408  		MuteTill = time.Now().Add(MuteFor1MinDuration)
  4409  	case MuteFor15Min:
  4410  		MuteTill = time.Now().Add(MuteFor15MinsDuration)
  4411  	case MuteFor1Hr:
  4412  		MuteTill = time.Now().Add(MuteFor1HrsDuration)
  4413  	case MuteFor8Hr:
  4414  		MuteTill = time.Now().Add(MuteFor8HrsDuration)
  4415  	case MuteFor24Hr:
  4416  		MuteTill = time.Now().Add(MuteFor24HrsDuration)
  4417  	case MuteFor1Week:
  4418  		MuteTill = time.Now().Add(MuteFor1WeekDuration)
  4419  	default:
  4420  		MuteTill = time.Time{}
  4421  	}
  4422  	err := m.saveChat(chat)
  4423  	if err != nil {
  4424  		return time.Time{}, err
  4425  	}
  4426  
  4427  	muteTillTimeRemoveMs, err := time.Parse(time.RFC3339, MuteTill.Format(time.RFC3339))
  4428  
  4429  	if err != nil {
  4430  		return time.Time{}, err
  4431  	}
  4432  
  4433  	return m.muteChat(chat, contact, muteTillTimeRemoveMs)
  4434  }
  4435  
  4436  func (m *Messenger) MuteChatV2(muteParams *requests.MuteChat) (time.Time, error) {
  4437  	return m.MuteChat(muteParams)
  4438  }
  4439  
  4440  func (m *Messenger) muteChat(chat *Chat, contact *Contact, mutedTill time.Time) (time.Time, error) {
  4441  	err := m.persistence.MuteChat(chat.ID, mutedTill)
  4442  	if err != nil {
  4443  		return time.Time{}, err
  4444  	}
  4445  
  4446  	chat.Muted = true
  4447  	chat.MuteTill = mutedTill
  4448  	// TODO(samyoul) remove storing of an updated reference pointer?
  4449  	m.allChats.Store(chat.ID, chat)
  4450  
  4451  	if contact != nil {
  4452  		err := m.syncContact(context.Background(), contact, m.dispatchMessage)
  4453  		if err != nil {
  4454  			return time.Time{}, err
  4455  		}
  4456  	}
  4457  
  4458  	if !chat.MuteTill.IsZero() {
  4459  		err := m.reregisterForPushNotifications()
  4460  		if err != nil {
  4461  			return time.Time{}, err
  4462  		}
  4463  		return mutedTill, nil
  4464  	}
  4465  
  4466  	return time.Time{}, m.reregisterForPushNotifications()
  4467  }
  4468  
  4469  // UnmuteChat signals to the messenger that we want to be notified
  4470  // on new messages from this chat
  4471  func (m *Messenger) UnmuteChat(chatID string) error {
  4472  	chat, ok := m.allChats.Load(chatID)
  4473  	if !ok {
  4474  		return ErrChatNotFoundError
  4475  	}
  4476  
  4477  	var contact *Contact
  4478  	if chat.OneToOne() {
  4479  		contact, _ = m.allContacts.Load(chatID)
  4480  	}
  4481  
  4482  	return m.unmuteChat(chat, contact)
  4483  }
  4484  
  4485  func (m *Messenger) unmuteChat(chat *Chat, contact *Contact) error {
  4486  	err := m.persistence.UnmuteChat(chat.ID)
  4487  	if err != nil {
  4488  		return err
  4489  	}
  4490  
  4491  	chat.Muted = false
  4492  	chat.MuteTill = time.Time{}
  4493  	// TODO(samyoul) remove storing of an updated reference pointer?
  4494  	m.allChats.Store(chat.ID, chat)
  4495  
  4496  	if chat.CommunityChat() {
  4497  		community, err := m.communitiesManager.GetByIDString(chat.CommunityID)
  4498  		if err != nil {
  4499  			return err
  4500  		}
  4501  
  4502  		err = m.communitiesManager.SetMuted(community.ID(), false)
  4503  		if err != nil {
  4504  			return err
  4505  		}
  4506  	}
  4507  
  4508  	if contact != nil {
  4509  		err := m.syncContact(context.Background(), contact, m.dispatchMessage)
  4510  		if err != nil {
  4511  			return err
  4512  		}
  4513  	}
  4514  	return m.reregisterForPushNotifications()
  4515  }
  4516  
  4517  func (m *Messenger) UpdateMessageOutgoingStatus(id, newOutgoingStatus string) error {
  4518  	return m.persistence.UpdateMessageOutgoingStatus(id, newOutgoingStatus)
  4519  }
  4520  
  4521  // Identicon returns an identicon based on the input string
  4522  func Identicon(id string) (string, error) {
  4523  	return identicon.GenerateBase64(id)
  4524  }
  4525  
  4526  // GenerateAlias name returns the generated name given a public key hex encoded prefixed with 0x
  4527  func GenerateAlias(id string) (string, error) {
  4528  	return alias.GenerateFromPublicKeyString(id)
  4529  }
  4530  
  4531  func (m *Messenger) RequestTransaction(ctx context.Context, chatID, value, contract, address string) (*MessengerResponse, error) {
  4532  	var response MessengerResponse
  4533  
  4534  	// A valid added chat is required.
  4535  	chat, ok := m.allChats.Load(chatID)
  4536  	if !ok {
  4537  		return nil, ErrChatNotFoundError
  4538  	}
  4539  	if chat.ChatType != ChatTypeOneToOne {
  4540  		return nil, errors.New("Need to be a one-to-one chat")
  4541  	}
  4542  
  4543  	message := common.NewMessage()
  4544  	err := extendMessageFromChat(message, chat, &m.identity.PublicKey, m.transport)
  4545  	if err != nil {
  4546  		return nil, err
  4547  	}
  4548  
  4549  	message.MessageType = protobuf.MessageType_ONE_TO_ONE
  4550  	message.ContentType = protobuf.ChatMessage_TRANSACTION_COMMAND
  4551  	message.Seen = true
  4552  	message.Text = "Request transaction"
  4553  
  4554  	request := &protobuf.RequestTransaction{
  4555  		Clock:    message.Clock,
  4556  		Address:  address,
  4557  		Value:    value,
  4558  		Contract: contract,
  4559  		ChatId:   chatID,
  4560  	}
  4561  	encodedMessage, err := proto.Marshal(request)
  4562  	if err != nil {
  4563  		return nil, err
  4564  	}
  4565  	resendType := common.ResendTypeRawMessage
  4566  	if chat.ChatType == ChatTypeOneToOne {
  4567  		resendType = common.ResendTypeDataSync
  4568  	}
  4569  	rawMessage, err := m.dispatchMessage(ctx, common.RawMessage{
  4570  		LocalChatID: chat.ID,
  4571  		Payload:     encodedMessage,
  4572  		MessageType: protobuf.ApplicationMetadataMessage_REQUEST_TRANSACTION,
  4573  		ResendType:  resendType,
  4574  	})
  4575  
  4576  	message.CommandParameters = &common.CommandParameters{
  4577  		ID:           rawMessage.ID,
  4578  		Value:        value,
  4579  		Address:      address,
  4580  		Contract:     contract,
  4581  		CommandState: common.CommandStateRequestTransaction,
  4582  	}
  4583  
  4584  	if err != nil {
  4585  		return nil, err
  4586  	}
  4587  	messageID := rawMessage.ID
  4588  
  4589  	message.ID = messageID
  4590  	message.CommandParameters.ID = messageID
  4591  	err = message.PrepareContent(common.PubkeyToHex(&m.identity.PublicKey))
  4592  	if err != nil {
  4593  		return nil, err
  4594  	}
  4595  
  4596  	err = chat.UpdateFromMessage(message, m.transport)
  4597  	if err != nil {
  4598  		return nil, err
  4599  	}
  4600  
  4601  	err = m.persistence.SaveMessages([]*common.Message{message})
  4602  	if err != nil {
  4603  		return nil, err
  4604  	}
  4605  
  4606  	return m.addMessagesAndChat(chat, []*common.Message{message}, &response)
  4607  }
  4608  
  4609  func (m *Messenger) RequestAddressForTransaction(ctx context.Context, chatID, from, value, contract string) (*MessengerResponse, error) {
  4610  	var response MessengerResponse
  4611  
  4612  	// A valid added chat is required.
  4613  	chat, ok := m.allChats.Load(chatID)
  4614  	if !ok {
  4615  		return nil, ErrChatNotFoundError
  4616  	}
  4617  	if chat.ChatType != ChatTypeOneToOne {
  4618  		return nil, errors.New("Need to be a one-to-one chat")
  4619  	}
  4620  
  4621  	message := common.NewMessage()
  4622  	err := extendMessageFromChat(message, chat, &m.identity.PublicKey, m.transport)
  4623  	if err != nil {
  4624  		return nil, err
  4625  	}
  4626  
  4627  	message.MessageType = protobuf.MessageType_ONE_TO_ONE
  4628  	message.ContentType = protobuf.ChatMessage_TRANSACTION_COMMAND
  4629  	message.Seen = true
  4630  	message.Text = "Request address for transaction"
  4631  
  4632  	request := &protobuf.RequestAddressForTransaction{
  4633  		Clock:    message.Clock,
  4634  		Value:    value,
  4635  		Contract: contract,
  4636  		ChatId:   chatID,
  4637  	}
  4638  	encodedMessage, err := proto.Marshal(request)
  4639  	if err != nil {
  4640  		return nil, err
  4641  	}
  4642  
  4643  	resendType := common.ResendTypeRawMessage
  4644  	if chat.ChatType == ChatTypeOneToOne {
  4645  		resendType = common.ResendTypeDataSync
  4646  	}
  4647  	rawMessage, err := m.dispatchMessage(ctx, common.RawMessage{
  4648  		LocalChatID: chat.ID,
  4649  		Payload:     encodedMessage,
  4650  		MessageType: protobuf.ApplicationMetadataMessage_REQUEST_ADDRESS_FOR_TRANSACTION,
  4651  		ResendType:  resendType,
  4652  	})
  4653  
  4654  	message.CommandParameters = &common.CommandParameters{
  4655  		ID:           rawMessage.ID,
  4656  		From:         from,
  4657  		Value:        value,
  4658  		Contract:     contract,
  4659  		CommandState: common.CommandStateRequestAddressForTransaction,
  4660  	}
  4661  
  4662  	if err != nil {
  4663  		return nil, err
  4664  	}
  4665  	messageID := rawMessage.ID
  4666  
  4667  	message.ID = messageID
  4668  	message.CommandParameters.ID = messageID
  4669  	err = message.PrepareContent(common.PubkeyToHex(&m.identity.PublicKey))
  4670  	if err != nil {
  4671  		return nil, err
  4672  	}
  4673  
  4674  	err = chat.UpdateFromMessage(message, m.transport)
  4675  	if err != nil {
  4676  		return nil, err
  4677  	}
  4678  
  4679  	err = m.persistence.SaveMessages([]*common.Message{message})
  4680  	if err != nil {
  4681  		return nil, err
  4682  	}
  4683  
  4684  	return m.addMessagesAndChat(chat, []*common.Message{message}, &response)
  4685  }
  4686  
  4687  func (m *Messenger) AcceptRequestAddressForTransaction(ctx context.Context, messageID, address string) (*MessengerResponse, error) {
  4688  	var response MessengerResponse
  4689  
  4690  	message, err := m.MessageByID(messageID)
  4691  	if err != nil {
  4692  		return nil, err
  4693  	}
  4694  
  4695  	if message == nil {
  4696  		return nil, errors.New("message not found")
  4697  	}
  4698  
  4699  	chatID := message.LocalChatID
  4700  
  4701  	// A valid added chat is required.
  4702  	chat, ok := m.allChats.Load(chatID)
  4703  	if !ok {
  4704  		return nil, ErrChatNotFoundError
  4705  	}
  4706  	if chat.ChatType != ChatTypeOneToOne {
  4707  		return nil, errors.New("Need to be a one-to-one chat")
  4708  	}
  4709  
  4710  	clock, timestamp := chat.NextClockAndTimestamp(m.transport)
  4711  	message.Clock = clock
  4712  	message.WhisperTimestamp = timestamp
  4713  	message.Timestamp = timestamp
  4714  	message.Text = "Request address for transaction accepted"
  4715  	message.Seen = true
  4716  	message.OutgoingStatus = common.OutgoingStatusSending
  4717  
  4718  	// Hide previous message
  4719  	previousMessage, err := m.persistence.MessageByCommandID(chatID, messageID)
  4720  	if err != nil {
  4721  		return nil, err
  4722  	}
  4723  
  4724  	if previousMessage == nil {
  4725  		return nil, errors.New("No previous message found")
  4726  	}
  4727  
  4728  	err = m.persistence.HideMessage(previousMessage.ID)
  4729  	if err != nil {
  4730  		return nil, err
  4731  	}
  4732  
  4733  	message.Replace = previousMessage.ID
  4734  
  4735  	request := &protobuf.AcceptRequestAddressForTransaction{
  4736  		Clock:   message.Clock,
  4737  		Id:      messageID,
  4738  		Address: address,
  4739  		ChatId:  chatID,
  4740  	}
  4741  	encodedMessage, err := proto.Marshal(request)
  4742  	if err != nil {
  4743  		return nil, err
  4744  	}
  4745  
  4746  	resendType := common.ResendTypeRawMessage
  4747  	if chat.ChatType == ChatTypeOneToOne {
  4748  		resendType = common.ResendTypeDataSync
  4749  	}
  4750  	rawMessage, err := m.dispatchMessage(ctx, common.RawMessage{
  4751  		LocalChatID: chat.ID,
  4752  		Payload:     encodedMessage,
  4753  		MessageType: protobuf.ApplicationMetadataMessage_ACCEPT_REQUEST_ADDRESS_FOR_TRANSACTION,
  4754  		ResendType:  resendType,
  4755  	})
  4756  
  4757  	if err != nil {
  4758  		return nil, err
  4759  	}
  4760  
  4761  	message.ID = rawMessage.ID
  4762  	message.CommandParameters.Address = address
  4763  	message.CommandParameters.CommandState = common.CommandStateRequestAddressForTransactionAccepted
  4764  
  4765  	err = message.PrepareContent(common.PubkeyToHex(&m.identity.PublicKey))
  4766  	if err != nil {
  4767  		return nil, err
  4768  	}
  4769  
  4770  	err = chat.UpdateFromMessage(message, m.transport)
  4771  	if err != nil {
  4772  		return nil, err
  4773  	}
  4774  
  4775  	err = m.persistence.SaveMessages([]*common.Message{message})
  4776  	if err != nil {
  4777  		return nil, err
  4778  	}
  4779  
  4780  	return m.addMessagesAndChat(chat, []*common.Message{message}, &response)
  4781  }
  4782  
  4783  func (m *Messenger) DeclineRequestTransaction(ctx context.Context, messageID string) (*MessengerResponse, error) {
  4784  	var response MessengerResponse
  4785  
  4786  	message, err := m.MessageByID(messageID)
  4787  	if err != nil {
  4788  		return nil, err
  4789  	}
  4790  
  4791  	if message == nil {
  4792  		return nil, errors.New("message not found")
  4793  	}
  4794  
  4795  	chatID := message.LocalChatID
  4796  
  4797  	// A valid added chat is required.
  4798  	chat, ok := m.allChats.Load(chatID)
  4799  	if !ok {
  4800  		return nil, ErrChatNotFoundError
  4801  	}
  4802  	if chat.ChatType != ChatTypeOneToOne {
  4803  		return nil, errors.New("Need to be a one-to-one chat")
  4804  	}
  4805  
  4806  	clock, timestamp := chat.NextClockAndTimestamp(m.transport)
  4807  	message.Clock = clock
  4808  	message.WhisperTimestamp = timestamp
  4809  	message.Timestamp = timestamp
  4810  	message.Text = "Transaction request declined"
  4811  	message.Seen = true
  4812  	message.OutgoingStatus = common.OutgoingStatusSending
  4813  	message.Replace = messageID
  4814  
  4815  	err = m.persistence.HideMessage(messageID)
  4816  	if err != nil {
  4817  		return nil, err
  4818  	}
  4819  
  4820  	request := &protobuf.DeclineRequestTransaction{
  4821  		Clock:  message.Clock,
  4822  		Id:     messageID,
  4823  		ChatId: chatID,
  4824  	}
  4825  	encodedMessage, err := proto.Marshal(request)
  4826  	if err != nil {
  4827  		return nil, err
  4828  	}
  4829  
  4830  	resendType := common.ResendTypeRawMessage
  4831  	if chat.ChatType == ChatTypeOneToOne {
  4832  		resendType = common.ResendTypeDataSync
  4833  	}
  4834  	rawMessage, err := m.dispatchMessage(ctx, common.RawMessage{
  4835  		LocalChatID: chat.ID,
  4836  		Payload:     encodedMessage,
  4837  		MessageType: protobuf.ApplicationMetadataMessage_DECLINE_REQUEST_TRANSACTION,
  4838  		ResendType:  resendType,
  4839  	})
  4840  
  4841  	if err != nil {
  4842  		return nil, err
  4843  	}
  4844  
  4845  	message.ID = rawMessage.ID
  4846  	message.CommandParameters.CommandState = common.CommandStateRequestTransactionDeclined
  4847  
  4848  	err = message.PrepareContent(common.PubkeyToHex(&m.identity.PublicKey))
  4849  	if err != nil {
  4850  		return nil, err
  4851  	}
  4852  
  4853  	err = chat.UpdateFromMessage(message, m.transport)
  4854  	if err != nil {
  4855  		return nil, err
  4856  	}
  4857  
  4858  	err = m.persistence.SaveMessages([]*common.Message{message})
  4859  	if err != nil {
  4860  		return nil, err
  4861  	}
  4862  
  4863  	return m.addMessagesAndChat(chat, []*common.Message{message}, &response)
  4864  }
  4865  
  4866  func (m *Messenger) DeclineRequestAddressForTransaction(ctx context.Context, messageID string) (*MessengerResponse, error) {
  4867  	var response MessengerResponse
  4868  
  4869  	message, err := m.MessageByID(messageID)
  4870  	if err != nil {
  4871  		return nil, err
  4872  	}
  4873  
  4874  	if message == nil {
  4875  		return nil, errors.New("message not found")
  4876  	}
  4877  
  4878  	chatID := message.LocalChatID
  4879  
  4880  	// A valid added chat is required.
  4881  	chat, ok := m.allChats.Load(chatID)
  4882  	if !ok {
  4883  		return nil, ErrChatNotFoundError
  4884  	}
  4885  	if chat.ChatType != ChatTypeOneToOne {
  4886  		return nil, errors.New("Need to be a one-to-one chat")
  4887  	}
  4888  
  4889  	clock, timestamp := chat.NextClockAndTimestamp(m.transport)
  4890  	message.Clock = clock
  4891  	message.WhisperTimestamp = timestamp
  4892  	message.Timestamp = timestamp
  4893  	message.Text = "Request address for transaction declined"
  4894  	message.Seen = true
  4895  	message.OutgoingStatus = common.OutgoingStatusSending
  4896  	message.Replace = messageID
  4897  
  4898  	err = m.persistence.HideMessage(messageID)
  4899  	if err != nil {
  4900  		return nil, err
  4901  	}
  4902  
  4903  	request := &protobuf.DeclineRequestAddressForTransaction{
  4904  		Clock:  message.Clock,
  4905  		Id:     messageID,
  4906  		ChatId: chatID,
  4907  	}
  4908  	encodedMessage, err := proto.Marshal(request)
  4909  	if err != nil {
  4910  		return nil, err
  4911  	}
  4912  
  4913  	resendType := common.ResendTypeRawMessage
  4914  	if chat.ChatType == ChatTypeOneToOne {
  4915  		resendType = common.ResendTypeDataSync
  4916  	}
  4917  	rawMessage, err := m.dispatchMessage(ctx, common.RawMessage{
  4918  		LocalChatID: chat.ID,
  4919  		Payload:     encodedMessage,
  4920  		MessageType: protobuf.ApplicationMetadataMessage_DECLINE_REQUEST_ADDRESS_FOR_TRANSACTION,
  4921  		ResendType:  resendType,
  4922  	})
  4923  
  4924  	if err != nil {
  4925  		return nil, err
  4926  	}
  4927  
  4928  	message.ID = rawMessage.ID
  4929  	message.CommandParameters.CommandState = common.CommandStateRequestAddressForTransactionDeclined
  4930  
  4931  	err = message.PrepareContent(common.PubkeyToHex(&m.identity.PublicKey))
  4932  	if err != nil {
  4933  		return nil, err
  4934  	}
  4935  
  4936  	err = chat.UpdateFromMessage(message, m.transport)
  4937  	if err != nil {
  4938  		return nil, err
  4939  	}
  4940  
  4941  	err = m.persistence.SaveMessages([]*common.Message{message})
  4942  	if err != nil {
  4943  		return nil, err
  4944  	}
  4945  
  4946  	return m.addMessagesAndChat(chat, []*common.Message{message}, &response)
  4947  }
  4948  
  4949  func (m *Messenger) AcceptRequestTransaction(ctx context.Context, transactionHash, messageID string, signature []byte) (*MessengerResponse, error) {
  4950  	var response MessengerResponse
  4951  
  4952  	message, err := m.MessageByID(messageID)
  4953  	if err != nil {
  4954  		return nil, err
  4955  	}
  4956  
  4957  	if message == nil {
  4958  		return nil, errors.New("message not found")
  4959  	}
  4960  
  4961  	chatID := message.LocalChatID
  4962  
  4963  	// A valid added chat is required.
  4964  	chat, ok := m.allChats.Load(chatID)
  4965  	if !ok {
  4966  		return nil, ErrChatNotFoundError
  4967  	}
  4968  	if chat.ChatType != ChatTypeOneToOne {
  4969  		return nil, errors.New("Need to be a one-to-one chat")
  4970  	}
  4971  
  4972  	clock, timestamp := chat.NextClockAndTimestamp(m.transport)
  4973  	message.Clock = clock
  4974  	message.WhisperTimestamp = timestamp
  4975  	message.Timestamp = timestamp
  4976  	message.Seen = true
  4977  	message.Text = transactionSentTxt
  4978  	message.OutgoingStatus = common.OutgoingStatusSending
  4979  
  4980  	// Hide previous message
  4981  	previousMessage, err := m.persistence.MessageByCommandID(chatID, messageID)
  4982  	if err != nil && err != common.ErrRecordNotFound {
  4983  		return nil, err
  4984  	}
  4985  
  4986  	if previousMessage != nil {
  4987  		err = m.persistence.HideMessage(previousMessage.ID)
  4988  		if err != nil {
  4989  			return nil, err
  4990  		}
  4991  		message.Replace = previousMessage.ID
  4992  	}
  4993  
  4994  	err = m.persistence.HideMessage(messageID)
  4995  	if err != nil {
  4996  		return nil, err
  4997  	}
  4998  
  4999  	request := &protobuf.SendTransaction{
  5000  		Clock:           message.Clock,
  5001  		Id:              messageID,
  5002  		TransactionHash: transactionHash,
  5003  		Signature:       signature,
  5004  		ChatId:          chatID,
  5005  	}
  5006  	encodedMessage, err := proto.Marshal(request)
  5007  	if err != nil {
  5008  		return nil, err
  5009  	}
  5010  
  5011  	resendType := common.ResendTypeRawMessage
  5012  	if chat.ChatType == ChatTypeOneToOne {
  5013  		resendType = common.ResendTypeDataSync
  5014  	}
  5015  	rawMessage, err := m.dispatchMessage(ctx, common.RawMessage{
  5016  		LocalChatID: chat.ID,
  5017  		Payload:     encodedMessage,
  5018  		MessageType: protobuf.ApplicationMetadataMessage_SEND_TRANSACTION,
  5019  		ResendType:  resendType,
  5020  	})
  5021  
  5022  	if err != nil {
  5023  		return nil, err
  5024  	}
  5025  
  5026  	message.ID = rawMessage.ID
  5027  	message.CommandParameters.TransactionHash = transactionHash
  5028  	message.CommandParameters.Signature = signature
  5029  	message.CommandParameters.CommandState = common.CommandStateTransactionSent
  5030  
  5031  	err = message.PrepareContent(common.PubkeyToHex(&m.identity.PublicKey))
  5032  	if err != nil {
  5033  		return nil, err
  5034  	}
  5035  
  5036  	err = chat.UpdateFromMessage(message, m.transport)
  5037  	if err != nil {
  5038  		return nil, err
  5039  	}
  5040  
  5041  	err = m.persistence.SaveMessages([]*common.Message{message})
  5042  	if err != nil {
  5043  		return nil, err
  5044  	}
  5045  
  5046  	return m.addMessagesAndChat(chat, []*common.Message{message}, &response)
  5047  }
  5048  
  5049  func (m *Messenger) SendTransaction(ctx context.Context, chatID, value, contract, transactionHash string, signature []byte) (*MessengerResponse, error) {
  5050  	var response MessengerResponse
  5051  
  5052  	// A valid added chat is required.
  5053  	chat, ok := m.allChats.Load(chatID)
  5054  	if !ok {
  5055  		return nil, ErrChatNotFoundError
  5056  	}
  5057  	if chat.ChatType != ChatTypeOneToOne {
  5058  		return nil, errors.New("Need to be a one-to-one chat")
  5059  	}
  5060  
  5061  	message := common.NewMessage()
  5062  	err := extendMessageFromChat(message, chat, &m.identity.PublicKey, m.transport)
  5063  	if err != nil {
  5064  		return nil, err
  5065  	}
  5066  
  5067  	message.MessageType = protobuf.MessageType_ONE_TO_ONE
  5068  	message.ContentType = protobuf.ChatMessage_TRANSACTION_COMMAND
  5069  	message.LocalChatID = chatID
  5070  
  5071  	clock, timestamp := chat.NextClockAndTimestamp(m.transport)
  5072  	message.Clock = clock
  5073  	message.WhisperTimestamp = timestamp
  5074  	message.Seen = true
  5075  	message.Timestamp = timestamp
  5076  	message.Text = transactionSentTxt
  5077  
  5078  	request := &protobuf.SendTransaction{
  5079  		Clock:           message.Clock,
  5080  		TransactionHash: transactionHash,
  5081  		Signature:       signature,
  5082  		ChatId:          chatID,
  5083  	}
  5084  	encodedMessage, err := proto.Marshal(request)
  5085  	if err != nil {
  5086  		return nil, err
  5087  	}
  5088  
  5089  	resendType := common.ResendTypeRawMessage
  5090  	if chat.ChatType == ChatTypeOneToOne {
  5091  		resendType = common.ResendTypeDataSync
  5092  	}
  5093  	rawMessage, err := m.dispatchMessage(ctx, common.RawMessage{
  5094  		LocalChatID: chat.ID,
  5095  		Payload:     encodedMessage,
  5096  		MessageType: protobuf.ApplicationMetadataMessage_SEND_TRANSACTION,
  5097  		ResendType:  resendType,
  5098  	})
  5099  
  5100  	if err != nil {
  5101  		return nil, err
  5102  	}
  5103  
  5104  	message.ID = rawMessage.ID
  5105  	message.CommandParameters = &common.CommandParameters{
  5106  		TransactionHash: transactionHash,
  5107  		Value:           value,
  5108  		Contract:        contract,
  5109  		Signature:       signature,
  5110  		CommandState:    common.CommandStateTransactionSent,
  5111  	}
  5112  
  5113  	err = message.PrepareContent(common.PubkeyToHex(&m.identity.PublicKey))
  5114  	if err != nil {
  5115  		return nil, err
  5116  	}
  5117  
  5118  	err = chat.UpdateFromMessage(message, m.transport)
  5119  	if err != nil {
  5120  		return nil, err
  5121  	}
  5122  
  5123  	err = m.persistence.SaveMessages([]*common.Message{message})
  5124  	if err != nil {
  5125  		return nil, err
  5126  	}
  5127  
  5128  	return m.addMessagesAndChat(chat, []*common.Message{message}, &response)
  5129  }
  5130  
  5131  func (m *Messenger) ValidateTransactions(ctx context.Context, addresses []types.Address) (*MessengerResponse, error) {
  5132  	if m.verifyTransactionClient == nil {
  5133  		return nil, nil
  5134  	}
  5135  
  5136  	logger := m.logger.With(zap.String("site", "ValidateTransactions"))
  5137  	logger.Debug("Validating transactions")
  5138  	txs, err := m.persistence.TransactionsToValidate()
  5139  	if err != nil {
  5140  		logger.Error("Error pulling", zap.Error(err))
  5141  		return nil, err
  5142  	}
  5143  	logger.Debug("Txs", zap.Int("count", len(txs)), zap.Any("txs", txs))
  5144  	var response MessengerResponse
  5145  	validator := NewTransactionValidator(addresses, m.persistence, m.verifyTransactionClient, m.logger)
  5146  	responses, err := validator.ValidateTransactions(ctx)
  5147  	if err != nil {
  5148  		logger.Error("Error validating", zap.Error(err))
  5149  		return nil, err
  5150  	}
  5151  	for _, validationResult := range responses {
  5152  		var message *common.Message
  5153  		chatID := contactIDFromPublicKey(validationResult.Transaction.From)
  5154  		chat, ok := m.allChats.Load(chatID)
  5155  		if !ok {
  5156  			chat = OneToOneFromPublicKey(validationResult.Transaction.From, m.transport)
  5157  		}
  5158  		if validationResult.Message != nil {
  5159  			message = validationResult.Message
  5160  		} else {
  5161  			message = common.NewMessage()
  5162  			err := extendMessageFromChat(message, chat, &m.identity.PublicKey, m.transport)
  5163  			if err != nil {
  5164  				return nil, err
  5165  			}
  5166  		}
  5167  
  5168  		message.MessageType = protobuf.MessageType_ONE_TO_ONE
  5169  		message.ContentType = protobuf.ChatMessage_TRANSACTION_COMMAND
  5170  		message.LocalChatID = chatID
  5171  		message.OutgoingStatus = ""
  5172  
  5173  		clock, timestamp := chat.NextClockAndTimestamp(m.transport)
  5174  		message.Clock = clock
  5175  		message.Timestamp = timestamp
  5176  		message.WhisperTimestamp = timestamp
  5177  		message.Text = "Transaction received"
  5178  		message.Seen = false
  5179  
  5180  		message.ID = validationResult.Transaction.MessageID
  5181  		if message.CommandParameters == nil {
  5182  			message.CommandParameters = &common.CommandParameters{}
  5183  		} else {
  5184  			message.CommandParameters = validationResult.Message.CommandParameters
  5185  		}
  5186  
  5187  		message.CommandParameters.Value = validationResult.Value
  5188  		message.CommandParameters.Contract = validationResult.Contract
  5189  		message.CommandParameters.Address = validationResult.Address
  5190  		message.CommandParameters.CommandState = common.CommandStateTransactionSent
  5191  		message.CommandParameters.TransactionHash = validationResult.Transaction.TransactionHash
  5192  
  5193  		err = message.PrepareContent(common.PubkeyToHex(&m.identity.PublicKey))
  5194  		if err != nil {
  5195  			return nil, err
  5196  		}
  5197  
  5198  		err = chat.UpdateFromMessage(message, m.transport)
  5199  		if err != nil {
  5200  			return nil, err
  5201  		}
  5202  
  5203  		if len(message.CommandParameters.ID) != 0 {
  5204  			// Hide previous message
  5205  			previousMessage, err := m.persistence.MessageByCommandID(chatID, message.CommandParameters.ID)
  5206  			if err != nil && err != common.ErrRecordNotFound {
  5207  				return nil, err
  5208  			}
  5209  
  5210  			if previousMessage != nil {
  5211  				err = m.persistence.HideMessage(previousMessage.ID)
  5212  				if err != nil {
  5213  					return nil, err
  5214  				}
  5215  				message.Replace = previousMessage.ID
  5216  			}
  5217  		}
  5218  
  5219  		response.AddMessage(message)
  5220  		m.allChats.Store(chat.ID, chat)
  5221  		response.AddChat(chat)
  5222  
  5223  		contact, err := m.getOrBuildContactFromMessage(message)
  5224  		if err != nil {
  5225  			return nil, err
  5226  		}
  5227  
  5228  		notificationsEnabled, err := m.settings.GetNotificationsEnabled()
  5229  		if err != nil {
  5230  			return nil, err
  5231  		}
  5232  
  5233  		profilePicturesVisibility, err := m.settings.GetProfilePicturesVisibility()
  5234  		if err != nil {
  5235  			return nil, err
  5236  		}
  5237  
  5238  		if notificationsEnabled {
  5239  			notification, err := NewMessageNotification(message.ID, message, chat, contact, m.ResolvePrimaryName, profilePicturesVisibility)
  5240  			if err != nil {
  5241  				return nil, err
  5242  			}
  5243  			response.AddNotification(notification)
  5244  		}
  5245  
  5246  	}
  5247  
  5248  	if len(response.messages) > 0 {
  5249  		err = m.SaveMessages(response.Messages())
  5250  		if err != nil {
  5251  			return nil, err
  5252  		}
  5253  	}
  5254  	return &response, nil
  5255  }
  5256  
  5257  // pullMessagesAndResponsesFromDB pulls all the messages and the one that have
  5258  // been replied to from the database
  5259  func (m *Messenger) pullMessagesAndResponsesFromDB(messages []*common.Message) ([]*common.Message, error) {
  5260  	var messageIDs []string
  5261  	for _, message := range messages {
  5262  		messageIDs = append(messageIDs, message.ID)
  5263  		if len(message.ResponseTo) != 0 {
  5264  			messageIDs = append(messageIDs, message.ResponseTo)
  5265  		}
  5266  
  5267  	}
  5268  	// We pull from the database all the messages & replies involved,
  5269  	// so we let the db build the correct messages
  5270  	return m.persistence.MessagesByIDs(messageIDs)
  5271  }
  5272  
  5273  func (m *Messenger) SignMessage(message string) ([]byte, error) {
  5274  	hash := crypto.TextHash([]byte(message))
  5275  	return crypto.Sign(hash, m.identity)
  5276  }
  5277  
  5278  func (m *Messenger) CreateCommunityTokenDeploymentSignature(ctx context.Context, chainID uint64, addressFrom string, communityID string) ([]byte, error) {
  5279  	return m.communitiesManager.CreateCommunityTokenDeploymentSignature(ctx, chainID, addressFrom, communityID)
  5280  }
  5281  
  5282  func (m *Messenger) getTimesource() common.TimeSource {
  5283  	return m.transport
  5284  }
  5285  
  5286  func (m *Messenger) GetCurrentTimeInMillis() uint64 {
  5287  	return m.getTimesource().GetCurrentTime()
  5288  }
  5289  
  5290  // AddPushNotificationsServer adds a push notification server
  5291  func (m *Messenger) AddPushNotificationsServer(ctx context.Context, publicKey *ecdsa.PublicKey, serverType pushnotificationclient.ServerType) error {
  5292  	if m.pushNotificationClient == nil {
  5293  		return errors.New("push notification client not enabled")
  5294  	}
  5295  	return m.pushNotificationClient.AddPushNotificationsServer(publicKey, serverType)
  5296  }
  5297  
  5298  // RemovePushNotificationServer removes a push notification server
  5299  func (m *Messenger) RemovePushNotificationServer(ctx context.Context, publicKey *ecdsa.PublicKey) error {
  5300  	if m.pushNotificationClient == nil {
  5301  		return errors.New("push notification client not enabled")
  5302  	}
  5303  	return m.pushNotificationClient.RemovePushNotificationServer(publicKey)
  5304  }
  5305  
  5306  // UnregisterFromPushNotifications unregister from any server
  5307  func (m *Messenger) UnregisterFromPushNotifications(ctx context.Context) error {
  5308  	return m.pushNotificationClient.Unregister()
  5309  }
  5310  
  5311  // DisableSendingPushNotifications signals the client not to send any push notification
  5312  func (m *Messenger) DisableSendingPushNotifications() error {
  5313  	if m.pushNotificationClient == nil {
  5314  		return errors.New("push notification client not enabled")
  5315  	}
  5316  	m.pushNotificationClient.DisableSending()
  5317  	return nil
  5318  }
  5319  
  5320  // EnableSendingPushNotifications signals the client to send push notifications
  5321  func (m *Messenger) EnableSendingPushNotifications() error {
  5322  	if m.pushNotificationClient == nil {
  5323  		return errors.New("push notification client not enabled")
  5324  	}
  5325  	m.pushNotificationClient.EnableSending()
  5326  	return nil
  5327  }
  5328  
  5329  func (m *Messenger) pushNotificationOptions() *pushnotificationclient.RegistrationOptions {
  5330  	var contactIDs []*ecdsa.PublicKey
  5331  	var mutedChatIDs []string
  5332  	var publicChatIDs []string
  5333  	var blockedChatIDs []string
  5334  
  5335  	m.allContacts.Range(func(contactID string, contact *Contact) (shouldContinue bool) {
  5336  		if contact.added() && !contact.Blocked {
  5337  			pk, err := contact.PublicKey()
  5338  			if err != nil {
  5339  				m.logger.Warn("could not parse contact public key")
  5340  				return true
  5341  			}
  5342  			contactIDs = append(contactIDs, pk)
  5343  		} else if contact.Blocked {
  5344  			blockedChatIDs = append(blockedChatIDs, contact.ID)
  5345  		}
  5346  		return true
  5347  	})
  5348  
  5349  	m.allChats.Range(func(chatID string, chat *Chat) (shouldContinue bool) {
  5350  		if chat.Muted {
  5351  			mutedChatIDs = append(mutedChatIDs, chat.ID)
  5352  			return true
  5353  		}
  5354  		if chat.Active && (chat.Public() || chat.CommunityChat()) {
  5355  			publicChatIDs = append(publicChatIDs, chat.ID)
  5356  		}
  5357  		return true
  5358  	})
  5359  
  5360  	return &pushnotificationclient.RegistrationOptions{
  5361  		ContactIDs:     contactIDs,
  5362  		MutedChatIDs:   mutedChatIDs,
  5363  		PublicChatIDs:  publicChatIDs,
  5364  		BlockedChatIDs: blockedChatIDs,
  5365  	}
  5366  }
  5367  
  5368  // RegisterForPushNotification register deviceToken with any push notification server enabled
  5369  func (m *Messenger) RegisterForPushNotifications(ctx context.Context, deviceToken, apnTopic string, tokenType protobuf.PushNotificationRegistration_TokenType) error {
  5370  	if m.pushNotificationClient == nil {
  5371  		return errors.New("push notification client not enabled")
  5372  	}
  5373  	m.mutex.Lock()
  5374  	defer m.mutex.Unlock()
  5375  
  5376  	err := m.pushNotificationClient.Register(deviceToken, apnTopic, tokenType, m.pushNotificationOptions())
  5377  	if err != nil {
  5378  		m.logger.Error("failed to register for push notifications", zap.Error(err))
  5379  		return err
  5380  	}
  5381  	return nil
  5382  }
  5383  
  5384  // RegisteredForPushNotifications returns whether we successfully registered with all the servers
  5385  func (m *Messenger) RegisteredForPushNotifications() (bool, error) {
  5386  	if m.pushNotificationClient == nil {
  5387  		return false, errors.New("no push notification client")
  5388  	}
  5389  	return m.pushNotificationClient.Registered()
  5390  }
  5391  
  5392  // EnablePushNotificationsFromContactsOnly is used to indicate that we want to received push notifications only from contacts
  5393  func (m *Messenger) EnablePushNotificationsFromContactsOnly() error {
  5394  	if m.pushNotificationClient == nil {
  5395  		return errors.New("no push notification client")
  5396  	}
  5397  	m.mutex.Lock()
  5398  	defer m.mutex.Unlock()
  5399  
  5400  	return m.pushNotificationClient.EnablePushNotificationsFromContactsOnly(m.pushNotificationOptions())
  5401  }
  5402  
  5403  // DisablePushNotificationsFromContactsOnly is used to indicate that we want to received push notifications from anyone
  5404  func (m *Messenger) DisablePushNotificationsFromContactsOnly() error {
  5405  	if m.pushNotificationClient == nil {
  5406  		return errors.New("no push notification client")
  5407  	}
  5408  	m.mutex.Lock()
  5409  	defer m.mutex.Unlock()
  5410  
  5411  	return m.pushNotificationClient.DisablePushNotificationsFromContactsOnly(m.pushNotificationOptions())
  5412  }
  5413  
  5414  // EnablePushNotificationsBlockMentions is used to indicate that we dont want to received push notifications for mentions
  5415  func (m *Messenger) EnablePushNotificationsBlockMentions() error {
  5416  	if m.pushNotificationClient == nil {
  5417  		return errors.New("no push notification client")
  5418  	}
  5419  	m.mutex.Lock()
  5420  	defer m.mutex.Unlock()
  5421  
  5422  	return m.pushNotificationClient.EnablePushNotificationsBlockMentions(m.pushNotificationOptions())
  5423  }
  5424  
  5425  // DisablePushNotificationsBlockMentions is used to indicate that we want to received push notifications for mentions
  5426  func (m *Messenger) DisablePushNotificationsBlockMentions() error {
  5427  	if m.pushNotificationClient == nil {
  5428  		return errors.New("no push notification client")
  5429  	}
  5430  	m.mutex.Lock()
  5431  	defer m.mutex.Unlock()
  5432  
  5433  	return m.pushNotificationClient.DisablePushNotificationsBlockMentions(m.pushNotificationOptions())
  5434  }
  5435  
  5436  // GetPushNotificationsServers returns the servers used for push notifications
  5437  func (m *Messenger) GetPushNotificationsServers() ([]*pushnotificationclient.PushNotificationServer, error) {
  5438  	if m.pushNotificationClient == nil {
  5439  		return nil, errors.New("no push notification client")
  5440  	}
  5441  	return m.pushNotificationClient.GetServers()
  5442  }
  5443  
  5444  // StartPushNotificationsServer initialize and start a push notification server, using the current messenger identity key
  5445  func (m *Messenger) StartPushNotificationsServer() error {
  5446  	if m.pushNotificationServer == nil {
  5447  		pushNotificationServerPersistence := pushnotificationserver.NewSQLitePersistence(m.database)
  5448  		config := &pushnotificationserver.Config{
  5449  			Enabled:  true,
  5450  			Logger:   m.logger,
  5451  			Identity: m.identity,
  5452  		}
  5453  		m.pushNotificationServer = pushnotificationserver.New(config, pushNotificationServerPersistence, m.sender)
  5454  	}
  5455  
  5456  	return m.pushNotificationServer.Start()
  5457  }
  5458  
  5459  // StopPushNotificationServer stops the push notification server if running
  5460  func (m *Messenger) StopPushNotificationsServer() error {
  5461  	m.pushNotificationServer = nil
  5462  	return nil
  5463  }
  5464  
  5465  func generateAliasAndIdenticon(pk string) (string, string, error) {
  5466  	identicon, err := identicon.GenerateBase64(pk)
  5467  	if err != nil {
  5468  		return "", "", err
  5469  	}
  5470  
  5471  	name, err := alias.GenerateFromPublicKeyString(pk)
  5472  	if err != nil {
  5473  		return "", "", err
  5474  	}
  5475  	return name, identicon, nil
  5476  
  5477  }
  5478  
  5479  func (m *Messenger) encodeChatEntity(chat *Chat, message common.ChatEntity) ([]byte, error) {
  5480  	var encodedMessage []byte
  5481  	var err error
  5482  	l := m.logger.With(zap.String("site", "Send"), zap.String("chatID", chat.ID))
  5483  
  5484  	switch chat.ChatType {
  5485  	case ChatTypeOneToOne:
  5486  		l.Debug("sending private message")
  5487  		message.SetMessageType(protobuf.MessageType_ONE_TO_ONE)
  5488  		encodedMessage, err = proto.Marshal(message.GetProtobuf())
  5489  		if err != nil {
  5490  			return nil, err
  5491  		}
  5492  
  5493  	case ChatTypePublic, ChatTypeProfile:
  5494  		l.Debug("sending public message", zap.String("chatName", chat.Name))
  5495  		message.SetMessageType(protobuf.MessageType_PUBLIC_GROUP)
  5496  		encodedMessage, err = proto.Marshal(message.GetProtobuf())
  5497  		if err != nil {
  5498  			return nil, err
  5499  		}
  5500  
  5501  	case ChatTypeCommunityChat:
  5502  		l.Debug("sending community chat message", zap.String("chatName", chat.Name))
  5503  		message.SetMessageType(protobuf.MessageType_COMMUNITY_CHAT)
  5504  		encodedMessage, err = proto.Marshal(message.GetProtobuf())
  5505  		if err != nil {
  5506  			return nil, err
  5507  		}
  5508  
  5509  	case ChatTypePrivateGroupChat:
  5510  		message.SetMessageType(protobuf.MessageType_PRIVATE_GROUP)
  5511  		l.Debug("sending group message", zap.String("chatName", chat.Name))
  5512  		if !message.WrapGroupMessage() {
  5513  			encodedMessage, err = proto.Marshal(message.GetProtobuf())
  5514  			if err != nil {
  5515  				return nil, err
  5516  			}
  5517  		} else {
  5518  
  5519  			group, err := newProtocolGroupFromChat(chat)
  5520  			if err != nil {
  5521  				return nil, err
  5522  			}
  5523  
  5524  			// NOTE(cammellos): Disabling for now since the optimiziation is not
  5525  			// applicable anymore after we changed group rules to allow
  5526  			// anyone to change group details
  5527  			encodedMessage, err = m.sender.EncodeMembershipUpdate(group, message)
  5528  			if err != nil {
  5529  				return nil, err
  5530  			}
  5531  		}
  5532  
  5533  	default:
  5534  		return nil, errors.New("chat type not supported")
  5535  	}
  5536  
  5537  	return encodedMessage, nil
  5538  }
  5539  
  5540  func (m *Messenger) getOrBuildContactFromMessage(msg *common.Message) (*Contact, error) {
  5541  	if c, ok := m.allContacts.Load(msg.From); ok {
  5542  		return c, nil
  5543  	}
  5544  
  5545  	senderPubKey, err := msg.GetSenderPubKey()
  5546  	if err != nil {
  5547  		return nil, err
  5548  	}
  5549  	senderID := contactIDFromPublicKey(senderPubKey)
  5550  	c, err := buildContact(senderID, senderPubKey)
  5551  	if err != nil {
  5552  		return nil, err
  5553  	}
  5554  
  5555  	// TODO(samyoul) remove storing of an updated reference pointer?
  5556  	m.allContacts.Store(msg.From, c)
  5557  	return c, nil
  5558  }
  5559  
  5560  func (m *Messenger) BloomFilter() []byte {
  5561  	return m.transport.BloomFilter()
  5562  }
  5563  
  5564  func (m *Messenger) getSettings() (settings.Settings, error) {
  5565  	sDB, err := accounts.NewDB(m.database)
  5566  	if err != nil {
  5567  		return settings.Settings{}, err
  5568  	}
  5569  	return sDB.GetSettings()
  5570  }
  5571  
  5572  func (m *Messenger) getEnsUsernameDetails() (result []*ensservice.UsernameDetail, err error) {
  5573  	db := ensservice.NewEnsDatabase(m.database)
  5574  	return db.GetEnsUsernames(nil)
  5575  }
  5576  
  5577  func ToVerificationRequest(message *protobuf.SyncVerificationRequest) *verification.Request {
  5578  	return &verification.Request{
  5579  		From:          message.From,
  5580  		To:            message.To,
  5581  		Challenge:     message.Challenge,
  5582  		Response:      message.Response,
  5583  		RequestedAt:   message.RequestedAt,
  5584  		RepliedAt:     message.RepliedAt,
  5585  		RequestStatus: verification.RequestStatus(message.VerificationStatus),
  5586  	}
  5587  }
  5588  
  5589  func (m *Messenger) HandleSyncVerificationRequest(state *ReceivedMessageState, message *protobuf.SyncVerificationRequest, statusMessage *v1protocol.StatusMessage) error {
  5590  	verificationRequest := ToVerificationRequest(message)
  5591  
  5592  	err := m.verificationDatabase.SaveVerificationRequest(verificationRequest)
  5593  	if err != nil {
  5594  		return err
  5595  	}
  5596  
  5597  	myPubKey := hexutil.Encode(crypto.FromECDSAPub(&m.identity.PublicKey))
  5598  
  5599  	state.AllVerificationRequests = append(state.AllVerificationRequests, verificationRequest)
  5600  
  5601  	if message.From == myPubKey { // Verification requests we sent
  5602  		contact, ok := m.allContacts.Load(message.To)
  5603  		if !ok {
  5604  			m.logger.Info("contact not found")
  5605  			return nil
  5606  		}
  5607  
  5608  		contact.VerificationStatus = VerificationStatus(message.VerificationStatus)
  5609  		if err := m.persistence.SaveContact(contact, nil); err != nil {
  5610  			return err
  5611  		}
  5612  
  5613  		m.allContacts.Store(contact.ID, contact)
  5614  		state.ModifiedContacts.Store(contact.ID, true)
  5615  
  5616  		// TODO: create activity center notif
  5617  
  5618  	}
  5619  	// else { // Verification requests we received
  5620  	// // TODO: activity center notif
  5621  	//}
  5622  
  5623  	return nil
  5624  }
  5625  
  5626  func (m *Messenger) ImageServerURL() string {
  5627  	return m.httpServer.MakeImageServerURL()
  5628  }
  5629  
  5630  func (m *Messenger) myHexIdentity() string {
  5631  	return common.PubkeyToHex(&m.identity.PublicKey)
  5632  }
  5633  
  5634  func (m *Messenger) GetMentionsManager() *MentionManager {
  5635  	return m.mentionsManager
  5636  }
  5637  
  5638  func (m *Messenger) getOtherMessagesInAlbum(message *common.Message, chatID string) ([]*common.Message, error) {
  5639  	var connectedMessages []*common.Message
  5640  	// In case of Image messages, we need to delete all the images in the album
  5641  	if message.ContentType == protobuf.ChatMessage_IMAGE {
  5642  		image := message.GetImage()
  5643  		if image != nil && image.AlbumId != "" {
  5644  			messagesInTheAlbum, err := m.persistence.albumMessages(chatID, image.GetAlbumId())
  5645  			if err != nil {
  5646  				return nil, err
  5647  			}
  5648  			connectedMessages = append(connectedMessages, messagesInTheAlbum...)
  5649  			return connectedMessages, nil
  5650  		}
  5651  	}
  5652  	return append(connectedMessages, message), nil
  5653  }
  5654  
  5655  func (m *Messenger) withChatClock(callback func(string, uint64) error) error {
  5656  	clock, chat := m.getLastClockWithRelatedChat()
  5657  	err := callback(chat.ID, clock)
  5658  	if err != nil {
  5659  		return err
  5660  	}
  5661  	chat.LastClockValue = clock
  5662  	return m.saveChat(chat)
  5663  }
  5664  
  5665  func (m *Messenger) syncDeleteForMeMessage(ctx context.Context, rawMessageDispatcher RawMessageHandler) error {
  5666  	deleteForMes, err := m.persistence.GetDeleteForMeMessages()
  5667  	if err != nil {
  5668  		return err
  5669  	}
  5670  
  5671  	return m.withChatClock(func(chatID string, _ uint64) error {
  5672  		for _, deleteForMe := range deleteForMes {
  5673  			encodedMessage, err2 := proto.Marshal(deleteForMe)
  5674  			if err2 != nil {
  5675  				return err2
  5676  			}
  5677  			rawMessage := common.RawMessage{
  5678  				LocalChatID: chatID,
  5679  				Payload:     encodedMessage,
  5680  				MessageType: protobuf.ApplicationMetadataMessage_SYNC_DELETE_FOR_ME_MESSAGE,
  5681  				ResendType:  common.ResendTypeDataSync,
  5682  			}
  5683  			_, err2 = rawMessageDispatcher(ctx, rawMessage)
  5684  			if err2 != nil {
  5685  				return err2
  5686  			}
  5687  		}
  5688  		return nil
  5689  	})
  5690  }
  5691  
  5692  func (m *Messenger) GetDeleteForMeMessages() ([]*protobuf.SyncDeleteForMeMessage, error) {
  5693  	return m.persistence.GetDeleteForMeMessages()
  5694  }
  5695  
  5696  func (m *Messenger) startCleanupLoop(name string, cleanupFunc func() error) {
  5697  	logger := m.logger.Named(name)
  5698  
  5699  	go func() {
  5700  		// Delay by a few minutes to minimize messenger's startup time
  5701  		var interval time.Duration = 5 * time.Minute
  5702  		for {
  5703  			select {
  5704  			case <-time.After(interval):
  5705  				// Set the regular interval after the first execution
  5706  				interval = 1 * time.Hour
  5707  
  5708  				err := cleanupFunc()
  5709  				if err != nil {
  5710  					logger.Error("failed to cleanup", zap.Error(err))
  5711  				}
  5712  
  5713  			case <-m.quit:
  5714  				return
  5715  			}
  5716  		}
  5717  	}()
  5718  }
  5719  
  5720  func (m *Messenger) startMessageSegmentsCleanupLoop() {
  5721  	m.startCleanupLoop("messageSegmentsCleanupLoop", m.sender.CleanupSegments)
  5722  }
  5723  
  5724  func (m *Messenger) startHashRatchetEncryptedMessagesCleanupLoop() {
  5725  	m.startCleanupLoop("hashRatchetEncryptedMessagesCleanupLoop", m.sender.CleanupHashRatchetEncryptedMessages)
  5726  }
  5727  
  5728  func (m *Messenger) FindStatusMessageIDForBridgeMessageID(bridgeMessageID string) (string, error) {
  5729  	return m.persistence.FindStatusMessageIDForBridgeMessageID(bridgeMessageID)
  5730  }