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

     1  package protocol
     2  
     3  import (
     4  	"context"
     5  	"crypto/ecdsa"
     6  	"database/sql"
     7  	"encoding/json"
     8  	"errors"
     9  	"fmt"
    10  	"strings"
    11  	"sync"
    12  	"time"
    13  
    14  	"golang.org/x/exp/slices"
    15  	"golang.org/x/time/rate"
    16  
    17  	"github.com/golang/protobuf/proto"
    18  	"github.com/google/uuid"
    19  
    20  	gethcommon "github.com/ethereum/go-ethereum/common"
    21  	"github.com/ethereum/go-ethereum/common/hexutil"
    22  
    23  	"go.uber.org/zap"
    24  
    25  	utils "github.com/status-im/status-go/common"
    26  
    27  	"github.com/status-im/status-go/account"
    28  	multiaccountscommon "github.com/status-im/status-go/multiaccounts/common"
    29  
    30  	"github.com/status-im/status-go/eth-node/crypto"
    31  	"github.com/status-im/status-go/eth-node/types"
    32  	"github.com/status-im/status-go/images"
    33  	"github.com/status-im/status-go/multiaccounts/accounts"
    34  	"github.com/status-im/status-go/protocol/common"
    35  	"github.com/status-im/status-go/protocol/common/shard"
    36  	"github.com/status-im/status-go/protocol/communities"
    37  	"github.com/status-im/status-go/protocol/communities/token"
    38  	"github.com/status-im/status-go/protocol/discord"
    39  	"github.com/status-im/status-go/protocol/encryption"
    40  	"github.com/status-im/status-go/protocol/protobuf"
    41  	"github.com/status-im/status-go/protocol/requests"
    42  	"github.com/status-im/status-go/protocol/transport"
    43  	v1protocol "github.com/status-im/status-go/protocol/v1"
    44  	localnotifications "github.com/status-im/status-go/services/local-notifications"
    45  	"github.com/status-im/status-go/services/wallet/bigint"
    46  	"github.com/status-im/status-go/signal"
    47  )
    48  
    49  // 7 days interval
    50  var messageArchiveInterval = 7 * 24 * time.Hour
    51  
    52  // 1 day interval
    53  var updateActiveMembersInterval = 24 * time.Hour
    54  
    55  // 1 day interval
    56  var grantUpdateInterval = 24 * time.Hour
    57  
    58  // 4 hours interval
    59  var grantInvokesProfileDispatchInterval = 4 * time.Hour
    60  
    61  const discordTimestampLayout = time.RFC3339
    62  
    63  const (
    64  	importSlowRate          = time.Second / 1
    65  	importFastRate          = time.Second / 100
    66  	importMessagesChunkSize = 10
    67  	importInitialDelay      = time.Minute * 5
    68  )
    69  
    70  const (
    71  	maxChunkSizeMessages = 1000
    72  	maxChunkSizeBytes    = 1500000
    73  )
    74  
    75  const (
    76  	ErrOwnerTokenNeeded                     = "Owner token is needed" // #nosec G101
    77  	ErrMissingCommunityID                   = "CommunityID has to be provided"
    78  	ErrForbiddenProfileOrWatchOnlyAccount   = "Cannot join a community using profile chat or watch-only account"
    79  	ErrSigningJoinRequestForKeycardAccounts = "Signing a joining community request for accounts migrated to keycard must be done with a keycard"
    80  	ErrNotPartOfCommunity                   = "Not part of the community"
    81  	ErrNotAdminOrOwner                      = "Not admin or owner"
    82  	ErrSignerIsNil                          = "Signer can't be nil"
    83  	ErrSyncMessagesSentByNonControlNode     = "Accepted/requested to join sync messages can be send only by the control node"
    84  	ErrReceiverIsNil                        = "Receiver can't be nil"
    85  )
    86  
    87  type FetchCommunityRequest struct {
    88  	// CommunityKey should be either a public or a private community key
    89  	CommunityKey    string       `json:"communityKey"`
    90  	Shard           *shard.Shard `json:"shard"`
    91  	TryDatabase     bool         `json:"tryDatabase"`
    92  	WaitForResponse bool         `json:"waitForResponse"`
    93  }
    94  
    95  func (r *FetchCommunityRequest) Validate() error {
    96  	if len(r.CommunityKey) <= 2 {
    97  		return fmt.Errorf("community key is too short")
    98  	}
    99  	if _, err := types.DecodeHex(r.CommunityKey); err != nil {
   100  		return fmt.Errorf("invalid community key")
   101  	}
   102  	return nil
   103  }
   104  
   105  func (r *FetchCommunityRequest) getCommunityID() string {
   106  	return GetCommunityIDFromKey(r.CommunityKey)
   107  }
   108  
   109  func GetCommunityIDFromKey(communityKey string) string {
   110  	// Check if the key is a private key. strip the 0x at the start
   111  	if privateKey, err := crypto.HexToECDSA(communityKey[2:]); err == nil {
   112  		// It is a privateKey
   113  		return types.HexBytes(crypto.CompressPubkey(&privateKey.PublicKey)).String()
   114  	}
   115  
   116  	// Not a private key, use the public key
   117  	return communityKey
   118  }
   119  
   120  func (m *Messenger) publishOrg(org *communities.Community, shouldRekey bool) error {
   121  	if org == nil {
   122  		return nil
   123  	}
   124  
   125  	m.logger.Debug("publishing community",
   126  		zap.Uint64("clock", org.Clock()),
   127  		zap.String("communityID", org.IDString()),
   128  		zap.Any("community", org),
   129  	)
   130  
   131  	payload, err := org.MarshaledDescription()
   132  
   133  	if err != nil {
   134  		return err
   135  	}
   136  
   137  	rawMessage := common.RawMessage{
   138  		Payload: payload,
   139  		Sender:  org.PrivateKey(),
   140  		// we don't want to wrap in an encryption layer message
   141  		SkipEncryptionLayer: true,
   142  		CommunityID:         org.ID(),
   143  		MessageType:         protobuf.ApplicationMetadataMessage_COMMUNITY_DESCRIPTION,
   144  		PubsubTopic:         org.PubsubTopic(), // TODO: confirm if it should be sent in community pubsub topic
   145  		Priority:            &common.HighPriority,
   146  	}
   147  	if org.Encrypted() {
   148  		members := org.GetMemberPubkeys()
   149  		if err != nil {
   150  			return err
   151  		}
   152  		rawMessage.CommunityKeyExMsgType = common.KeyExMsgRekey
   153  		// This should be the one that it was used to encrypt this community
   154  		rawMessage.HashRatchetGroupID = org.ID()
   155  		rawMessage.Recipients = members
   156  	}
   157  	messageID, err := m.sender.SendPublic(context.Background(), org.IDString(), rawMessage)
   158  	if err == nil {
   159  		m.logger.Debug("published community",
   160  			zap.String("pubsubTopic", org.PubsubTopic()),
   161  			zap.String("communityID", org.IDString()),
   162  			zap.String("messageID", hexutil.Encode(messageID)),
   163  			zap.Uint64("clock", org.Clock()),
   164  		)
   165  	}
   166  	return err
   167  }
   168  
   169  func (m *Messenger) publishCommunityEvents(community *communities.Community, msg *communities.CommunityEventsMessage) error {
   170  	m.logger.Debug("publishing community events", zap.String("admin-id", common.PubkeyToHex(&m.identity.PublicKey)), zap.Any("event", msg))
   171  
   172  	payload, err := msg.Marshal()
   173  	if err != nil {
   174  		return err
   175  	}
   176  
   177  	rawMessage := common.RawMessage{
   178  		Payload: payload,
   179  		Sender:  m.identity,
   180  		// we don't want to wrap in an encryption layer message
   181  		SkipEncryptionLayer: true,
   182  		MessageType:         protobuf.ApplicationMetadataMessage_COMMUNITY_EVENTS_MESSAGE,
   183  		PubsubTopic:         community.PubsubTopic(), // TODO: confirm if it should be sent in community pubsub topic
   184  		Priority:            &common.LowPriority,
   185  	}
   186  
   187  	// TODO: resend in case of failure?
   188  	_, err = m.sender.SendPublic(context.Background(), types.EncodeHex(msg.CommunityID), rawMessage)
   189  	return err
   190  }
   191  
   192  func (m *Messenger) publishCommunityPrivilegedMemberSyncMessage(msg *communities.CommunityPrivilegedMemberSyncMessage) error {
   193  	community, err := m.GetCommunityByID(msg.CommunityPrivilegedUserSyncMessage.CommunityId)
   194  	if err != nil {
   195  		return err
   196  	}
   197  
   198  	m.logger.Debug("publishing privileged user sync message",
   199  		zap.Any("receivers", msg.Receivers), zap.Any("type", msg.CommunityPrivilegedUserSyncMessage.Type))
   200  
   201  	payload, err := proto.Marshal(msg.CommunityPrivilegedUserSyncMessage)
   202  	if err != nil {
   203  		return err
   204  	}
   205  
   206  	rawMessage := &common.RawMessage{
   207  		Payload:             payload,
   208  		Sender:              community.PrivateKey(),
   209  		SkipEncryptionLayer: true,
   210  		MessageType:         protobuf.ApplicationMetadataMessage_COMMUNITY_PRIVILEGED_USER_SYNC_MESSAGE,
   211  	}
   212  
   213  	for _, receivers := range msg.Receivers {
   214  		_, err = m.sender.SendPrivate(context.Background(), receivers, rawMessage)
   215  	}
   216  
   217  	return err
   218  }
   219  
   220  func (m *Messenger) handleCommunitiesHistoryArchivesSubscription(c chan *communities.Subscription) {
   221  
   222  	go func() {
   223  		for {
   224  			select {
   225  			case sub, more := <-c:
   226  				if !more {
   227  					return
   228  				}
   229  
   230  				if sub.CreatingHistoryArchivesSignal != nil {
   231  					m.config.messengerSignalsHandler.CreatingHistoryArchives(sub.CreatingHistoryArchivesSignal.CommunityID)
   232  				}
   233  
   234  				if sub.HistoryArchivesCreatedSignal != nil {
   235  					m.config.messengerSignalsHandler.HistoryArchivesCreated(
   236  						sub.HistoryArchivesCreatedSignal.CommunityID,
   237  						sub.HistoryArchivesCreatedSignal.From,
   238  						sub.HistoryArchivesCreatedSignal.To,
   239  					)
   240  				}
   241  
   242  				if sub.NoHistoryArchivesCreatedSignal != nil {
   243  					m.config.messengerSignalsHandler.NoHistoryArchivesCreated(
   244  						sub.NoHistoryArchivesCreatedSignal.CommunityID,
   245  						sub.NoHistoryArchivesCreatedSignal.From,
   246  						sub.NoHistoryArchivesCreatedSignal.To,
   247  					)
   248  				}
   249  
   250  				if sub.HistoryArchivesSeedingSignal != nil {
   251  
   252  					m.config.messengerSignalsHandler.HistoryArchivesSeeding(sub.HistoryArchivesSeedingSignal.CommunityID)
   253  
   254  					c, err := m.communitiesManager.GetByIDString(sub.HistoryArchivesSeedingSignal.CommunityID)
   255  					if err != nil {
   256  						m.logger.Debug("failed to retrieve community by id string", zap.Error(err))
   257  					}
   258  
   259  					if c.IsControlNode() {
   260  						err := m.dispatchMagnetlinkMessage(sub.HistoryArchivesSeedingSignal.CommunityID)
   261  						if err != nil {
   262  							m.logger.Debug("failed to dispatch magnetlink message", zap.Error(err))
   263  						}
   264  					}
   265  				}
   266  
   267  				if sub.HistoryArchivesUnseededSignal != nil {
   268  					m.config.messengerSignalsHandler.HistoryArchivesUnseeded(sub.HistoryArchivesUnseededSignal.CommunityID)
   269  				}
   270  
   271  				if sub.HistoryArchiveDownloadedSignal != nil {
   272  					m.config.messengerSignalsHandler.HistoryArchiveDownloaded(
   273  						sub.HistoryArchiveDownloadedSignal.CommunityID,
   274  						sub.HistoryArchiveDownloadedSignal.From,
   275  						sub.HistoryArchiveDownloadedSignal.To,
   276  					)
   277  				}
   278  
   279  				if sub.DownloadingHistoryArchivesFinishedSignal != nil {
   280  					m.config.messengerSignalsHandler.DownloadingHistoryArchivesFinished(sub.DownloadingHistoryArchivesFinishedSignal.CommunityID)
   281  				}
   282  
   283  				if sub.DownloadingHistoryArchivesStartedSignal != nil {
   284  					m.config.messengerSignalsHandler.DownloadingHistoryArchivesStarted(sub.DownloadingHistoryArchivesStartedSignal.CommunityID)
   285  				}
   286  
   287  				if sub.ImportingHistoryArchiveMessagesSignal != nil {
   288  					m.config.messengerSignalsHandler.ImportingHistoryArchiveMessages(sub.ImportingHistoryArchiveMessagesSignal.CommunityID)
   289  				}
   290  
   291  			case <-m.quit:
   292  				return
   293  			}
   294  		}
   295  	}()
   296  }
   297  
   298  // handleCommunitiesSubscription handles events from communities
   299  func (m *Messenger) handleCommunitiesSubscription(c chan *communities.Subscription) {
   300  	var lastPublished int64
   301  	// We check every 5 minutes if we need to publish
   302  	ticker := time.NewTicker(5 * time.Minute)
   303  
   304  	recentlyPublishedOrgs := make(map[string]*communities.Community, 0)
   305  
   306  	publishOrgAndDistributeEncryptionKeys := func(community *communities.Community) {
   307  		recentlyPublishedOrg := recentlyPublishedOrgs[community.IDString()]
   308  
   309  		if recentlyPublishedOrg != nil && community.Clock() < recentlyPublishedOrg.Clock() {
   310  			return
   311  		}
   312  
   313  		// evaluate and distribute encryption keys (if any)
   314  		encryptionKeyActions := communities.EvaluateCommunityEncryptionKeyActions(recentlyPublishedOrg, community)
   315  		err := m.communitiesKeyDistributor.Distribute(community, encryptionKeyActions)
   316  		if err != nil {
   317  			m.logger.Warn("failed to distribute encryption keys", zap.Error(err))
   318  		}
   319  
   320  		shouldRekey := encryptionKeyActions.CommunityKeyAction.ActionType == communities.EncryptionKeyRekey
   321  		if community.Encrypted() {
   322  			clock := community.Clock()
   323  			clock++
   324  			userKicked := &protobuf.CommunityUserKicked{
   325  				Clock:       clock,
   326  				CommunityId: community.ID(),
   327  			}
   328  
   329  			for pkString := range encryptionKeyActions.CommunityKeyAction.RemovedMembers {
   330  				pk, err := common.HexToPubkey(pkString)
   331  				if err != nil {
   332  					m.logger.Error("failed to decode public key", zap.Error(err), zap.String("pk", pkString))
   333  				}
   334  				payload, err := proto.Marshal(userKicked)
   335  				if err != nil {
   336  					m.logger.Error("failed to marshal user kicked message", zap.Error(err))
   337  					continue
   338  				}
   339  
   340  				rawMessage := &common.RawMessage{
   341  					Payload:             payload,
   342  					Sender:              community.PrivateKey(),
   343  					SkipEncryptionLayer: true,
   344  					MessageType:         protobuf.ApplicationMetadataMessage_COMMUNITY_USER_KICKED,
   345  					PubsubTopic:         shard.DefaultNonProtectedPubsubTopic(),
   346  				}
   347  
   348  				_, err = m.sender.SendPrivate(context.Background(), pk, rawMessage)
   349  				if err != nil {
   350  					m.logger.Error("failed to send used kicked message", zap.Error(err))
   351  					continue
   352  				}
   353  
   354  			}
   355  
   356  		}
   357  
   358  		err = m.publishOrg(community, shouldRekey)
   359  		if err != nil {
   360  			m.logger.Warn("failed to publish org", zap.Error(err))
   361  			return
   362  		}
   363  		m.logger.Debug("published org")
   364  
   365  		// publish shard information
   366  		err = m.sendPublicCommunityShardInfo(community)
   367  		if err != nil {
   368  			m.logger.Warn("failed to publish public shard info", zap.Error(err))
   369  			return
   370  		}
   371  
   372  		// signal client with published community
   373  		if m.config.messengerSignalsHandler != nil {
   374  			if recentlyPublishedOrg == nil || community.Clock() > recentlyPublishedOrg.Clock() {
   375  				response := &MessengerResponse{}
   376  				response.AddCommunity(community)
   377  				m.config.messengerSignalsHandler.MessengerResponse(response)
   378  			}
   379  		}
   380  
   381  		recentlyPublishedOrgs[community.IDString()] = community.CreateDeepCopy()
   382  	}
   383  
   384  	go func() {
   385  		for {
   386  			select {
   387  			case sub, more := <-c:
   388  				if !more {
   389  					return
   390  				}
   391  				if sub.Community != nil {
   392  					if sub.Community == nil {
   393  						continue
   394  					}
   395  					// NOTE: because we use a pointer here, there's a race condition where the community would be updated before it's compared to the previous one.
   396  					// This results in keys not being propagated as the copy would not see any changes
   397  					communityCopy := sub.Community.CreateDeepCopy()
   398  
   399  					publishOrgAndDistributeEncryptionKeys(communityCopy)
   400  				}
   401  
   402  				if sub.CommunityEventsMessage != nil {
   403  					err := m.publishCommunityEvents(sub.Community, sub.CommunityEventsMessage)
   404  					if err != nil {
   405  						m.logger.Warn("failed to publish community events", zap.Error(err))
   406  					}
   407  				}
   408  
   409  				if sub.AcceptedRequestsToJoin != nil {
   410  					for _, requestID := range sub.AcceptedRequestsToJoin {
   411  						accept := &requests.AcceptRequestToJoinCommunity{
   412  							ID: requestID,
   413  						}
   414  						response, err := m.AcceptRequestToJoinCommunity(accept)
   415  						if err != nil {
   416  							m.logger.Warn("failed to accept request to join ", zap.Error(err))
   417  						}
   418  						if m.config.messengerSignalsHandler != nil {
   419  							m.config.messengerSignalsHandler.MessengerResponse(response)
   420  						}
   421  					}
   422  				}
   423  
   424  				if sub.RejectedRequestsToJoin != nil {
   425  					for _, requestID := range sub.RejectedRequestsToJoin {
   426  						reject := &requests.DeclineRequestToJoinCommunity{
   427  							ID: requestID,
   428  						}
   429  						response, err := m.DeclineRequestToJoinCommunity(reject)
   430  						if err != nil {
   431  							m.logger.Warn("failed to decline request to join ", zap.Error(err))
   432  						}
   433  						if m.config.messengerSignalsHandler != nil {
   434  							m.config.messengerSignalsHandler.MessengerResponse(response)
   435  						}
   436  					}
   437  				}
   438  
   439  				if sub.CommunityPrivilegedMemberSyncMessage != nil {
   440  					if err := m.publishCommunityPrivilegedMemberSyncMessage(sub.CommunityPrivilegedMemberSyncMessage); err != nil {
   441  						m.logger.Warn("failed to publish community private members sync message", zap.Error(err))
   442  					}
   443  				}
   444  				if sub.TokenCommunityValidated != nil {
   445  					state := m.buildMessageState()
   446  					communityResponse := sub.TokenCommunityValidated
   447  
   448  					err := m.handleCommunityResponse(state, communityResponse)
   449  					if err != nil {
   450  						m.logger.Error("failed to handle community response", zap.Error(err))
   451  					}
   452  
   453  					m.processCommunityChanges(state)
   454  
   455  					_, err = m.saveDataAndPrepareResponse(state)
   456  					if err != nil {
   457  						m.logger.Error("failed to save data and prepare response")
   458  					}
   459  
   460  					if m.config.messengerSignalsHandler != nil {
   461  						m.config.messengerSignalsHandler.MessengerResponse(state.Response)
   462  					}
   463  				}
   464  
   465  			case <-ticker.C:
   466  				// If we are not online, we don't even try
   467  				if !m.Online() {
   468  					continue
   469  				}
   470  
   471  				// If not enough time has passed since last advertisement, we skip this
   472  				if time.Now().Unix()-lastPublished < communityAdvertiseIntervalSecond {
   473  					continue
   474  				}
   475  
   476  				controlledCommunities, err := m.communitiesManager.Controlled()
   477  				if err != nil {
   478  					m.logger.Warn("failed to retrieve orgs", zap.Error(err))
   479  				}
   480  
   481  				for idx := range controlledCommunities {
   482  					org := controlledCommunities[idx]
   483  					_, beingImported := m.importingCommunities[org.IDString()]
   484  					if !beingImported {
   485  						publishOrgAndDistributeEncryptionKeys(org)
   486  					}
   487  				}
   488  
   489  				// set lastPublished
   490  				lastPublished = time.Now().Unix()
   491  
   492  			case <-m.quit:
   493  				ticker.Stop()
   494  				return
   495  			}
   496  		}
   497  	}()
   498  }
   499  
   500  func (m *Messenger) updateCommunitiesActiveMembersPeriodically() {
   501  	communitiesLastUpdated := make(map[string]int64)
   502  
   503  	// We check every 5 minutes if we need to update
   504  	ticker := time.NewTicker(5 * time.Minute)
   505  
   506  	go func() {
   507  		for {
   508  			select {
   509  			case <-ticker.C:
   510  				controlledCommunities, err := m.communitiesManager.Controlled()
   511  				if err != nil {
   512  					m.logger.Error("failed to update community active members count", zap.Error(err))
   513  				}
   514  
   515  				for _, community := range controlledCommunities {
   516  					lastUpdated, ok := communitiesLastUpdated[community.IDString()]
   517  					if !ok {
   518  						lastUpdated = 0
   519  					}
   520  
   521  					// If not enough time has passed since last update, we skip this
   522  					if time.Now().Unix()-lastUpdated < int64(updateActiveMembersInterval.Seconds()) {
   523  						continue
   524  					}
   525  
   526  					if err := m.updateCommunityActiveMembers(community.IDString()); err == nil {
   527  						communitiesLastUpdated[community.IDString()] = time.Now().Unix()
   528  
   529  						// Perf: ensure `updateCommunityActiveMembers` is not called few times in a row
   530  						// Next communities will be handled in subsequent ticks
   531  						break
   532  					} else {
   533  						m.logger.Error("failed to update community active members count", zap.Error(err))
   534  					}
   535  				}
   536  
   537  			case <-m.quit:
   538  				ticker.Stop()
   539  				return
   540  			}
   541  		}
   542  	}()
   543  }
   544  
   545  func (m *Messenger) HandleCommunityUpdateGrant(state *ReceivedMessageState, message *protobuf.CommunityUpdateGrant, statusMessage *v1protocol.StatusMessage) error {
   546  	community, err := m.communitiesManager.GetByID(message.CommunityId)
   547  	if err != nil {
   548  		return err
   549  	}
   550  
   551  	grant, err := m.encryptor.DecryptCommunityGrant(m.identity, state.CurrentMessageState.PublicKey, message.Grants)
   552  	if err != nil {
   553  		return err
   554  	}
   555  
   556  	return m.handleCommunityGrant(community, grant, message.Timestamp)
   557  }
   558  
   559  func (m *Messenger) HandleCommunityEncryptionKeysRequest(state *ReceivedMessageState, message *protobuf.CommunityEncryptionKeysRequest, statusMessage *v1protocol.StatusMessage) error {
   560  	community, err := m.communitiesManager.GetByID(message.CommunityId)
   561  	if err != nil {
   562  		return err
   563  	}
   564  
   565  	if !community.IsControlNode() {
   566  		return communities.ErrNotControlNode
   567  	}
   568  	signer := state.CurrentMessageState.PublicKey
   569  	return m.handleCommunityEncryptionKeysRequest(community, message.ChatIds, signer)
   570  }
   571  
   572  func (m *Messenger) HandleCommunitySharedAddressesRequest(state *ReceivedMessageState, message *protobuf.CommunitySharedAddressesRequest, statusMessage *v1protocol.StatusMessage) error {
   573  	community, err := m.communitiesManager.GetByID(message.CommunityId)
   574  	if err != nil {
   575  		return err
   576  	}
   577  
   578  	if !community.IsControlNode() {
   579  		return communities.ErrNotControlNode
   580  	}
   581  	signer := state.CurrentMessageState.PublicKey
   582  	return m.handleCommunitySharedAddressesRequest(state, community, signer)
   583  }
   584  
   585  func (m *Messenger) HandleCommunitySharedAddressesResponse(state *ReceivedMessageState, message *protobuf.CommunitySharedAddressesResponse, statusMessage *v1protocol.StatusMessage) error {
   586  	community, err := m.communitiesManager.GetByID(message.CommunityId)
   587  	if err != nil {
   588  		return err
   589  	}
   590  
   591  	signer := state.CurrentMessageState.PublicKey
   592  	return m.handleCommunitySharedAddressesResponse(state, community, signer, message.RevealedAccounts)
   593  }
   594  
   595  func (m *Messenger) HandleCommunityTokenAction(state *ReceivedMessageState, message *protobuf.CommunityTokenAction, statusMessage *v1protocol.StatusMessage) error {
   596  	return m.communityTokensService.ProcessCommunityTokenAction(message)
   597  }
   598  
   599  func (m *Messenger) handleCommunityEncryptionKeysRequest(community *communities.Community, channelIDs []string, signer *ecdsa.PublicKey) error {
   600  	if !community.HasMember(signer) {
   601  		return communities.ErrMemberNotFound
   602  	}
   603  
   604  	keyActions := &communities.EncryptionKeyActions{
   605  		CommunityKeyAction: communities.EncryptionKeyAction{},
   606  		ChannelKeysActions: map[string]communities.EncryptionKeyAction{},
   607  	}
   608  
   609  	pkStr := common.PubkeyToHex(signer)
   610  	members := make(map[string]*protobuf.CommunityMember)
   611  	members[pkStr] = community.GetMember(signer)
   612  
   613  	if community.Encrypted() {
   614  		keyActions.CommunityKeyAction = communities.EncryptionKeyAction{
   615  			ActionType: communities.EncryptionKeySendToMembers,
   616  			Members:    members,
   617  		}
   618  	}
   619  
   620  	requestedChannelIDs := map[string]bool{}
   621  	for _, channelID := range channelIDs {
   622  		requestedChannelIDs[channelID] = true
   623  	}
   624  
   625  	for channelID, channel := range community.Chats() {
   626  		// Skip channels that weren't requested
   627  		if len(requestedChannelIDs) > 0 && !requestedChannelIDs[channelID] {
   628  			continue
   629  		}
   630  
   631  		channelMembers := channel.GetMembers()
   632  		member, exists := channelMembers[pkStr]
   633  		if exists && community.ChannelEncrypted(channelID) {
   634  			members[pkStr] = member
   635  			keyActions.ChannelKeysActions[channelID] = communities.EncryptionKeyAction{
   636  				ActionType: communities.EncryptionKeySendToMembers,
   637  				Members:    members,
   638  			}
   639  		}
   640  	}
   641  
   642  	err := m.communitiesKeyDistributor.Distribute(community, keyActions)
   643  	if err != nil {
   644  		m.logger.Error("failed to send community keys", zap.Error(err), zap.String("community ID", community.IDString()))
   645  	}
   646  
   647  	return nil
   648  }
   649  
   650  func (m *Messenger) handleCommunitySharedAddressesRequest(state *ReceivedMessageState, community *communities.Community, signer *ecdsa.PublicKey) error {
   651  	if !community.HasMember(signer) {
   652  		return communities.ErrMemberNotFound
   653  	}
   654  
   655  	pkStr := common.PubkeyToHex(signer)
   656  
   657  	revealedAccounts, err := m.communitiesManager.GetRevealedAddresses(community.ID(), pkStr)
   658  	if err != nil {
   659  		return err
   660  	}
   661  
   662  	usersSharedAddressesProto := &protobuf.CommunitySharedAddressesResponse{
   663  		CommunityId:      community.ID(),
   664  		RevealedAccounts: revealedAccounts,
   665  	}
   666  
   667  	payload, err := proto.Marshal(usersSharedAddressesProto)
   668  	if err != nil {
   669  		return err
   670  	}
   671  
   672  	rawMessage := common.RawMessage{
   673  		Payload:             payload,
   674  		Sender:              community.PrivateKey(),
   675  		CommunityID:         community.ID(),
   676  		SkipEncryptionLayer: true,
   677  		MessageType:         protobuf.ApplicationMetadataMessage_COMMUNITY_SHARED_ADDRESSES_RESPONSE,
   678  		PubsubTopic:         shard.DefaultNonProtectedPubsubTopic(),
   679  		ResendType:          common.ResendTypeRawMessage,
   680  		ResendMethod:        common.ResendMethodSendPrivate,
   681  		Recipients:          []*ecdsa.PublicKey{signer},
   682  	}
   683  
   684  	_, err = m.sender.SendPrivate(context.Background(), signer, &rawMessage)
   685  	if err != nil {
   686  		return err
   687  	}
   688  
   689  	if community.IsPrivilegedMember(signer) {
   690  		memberRole := community.MemberRole(signer)
   691  		newPrivilegedMember := make(map[protobuf.CommunityMember_Roles][]*ecdsa.PublicKey)
   692  		newPrivilegedMember[memberRole] = []*ecdsa.PublicKey{signer}
   693  		if err = m.communitiesManager.ShareRequestsToJoinWithPrivilegedMembers(community, newPrivilegedMember); err != nil {
   694  			return err
   695  		}
   696  	}
   697  
   698  	return nil
   699  }
   700  
   701  func (m *Messenger) handleCommunitySharedAddressesResponse(state *ReceivedMessageState, community *communities.Community, signer *ecdsa.PublicKey, revealedAccounts []*protobuf.RevealedAccount) error {
   702  	isControlNodeMsg := common.IsPubKeyEqual(community.ControlNode(), signer)
   703  	if !isControlNodeMsg {
   704  		return errors.New(ErrSyncMessagesSentByNonControlNode)
   705  	}
   706  
   707  	requestID := communities.CalculateRequestID(common.PubkeyToHex(&m.identity.PublicKey), community.ID())
   708  	err := m.communitiesManager.SaveRequestToJoinRevealedAddresses(requestID, revealedAccounts)
   709  	if err != nil {
   710  		return nil
   711  	}
   712  
   713  	requestsToJoin, err := m.communitiesManager.GetCommunityRequestsToJoinWithRevealedAddresses(community.ID())
   714  	if err != nil {
   715  		return nil
   716  	}
   717  
   718  	state.Response.AddRequestsToJoinCommunity(requestsToJoin)
   719  
   720  	return nil
   721  }
   722  
   723  func (m *Messenger) handleCommunityGrant(community *communities.Community, grant []byte, clock uint64) error {
   724  	difference, err := m.communitiesManager.HandleCommunityGrant(community, grant, clock)
   725  	if err == communities.ErrGrantOlder || err == communities.ErrGrantExpired {
   726  		// Don't log an error for these cases
   727  		return nil
   728  	}
   729  	if err != nil {
   730  		return err
   731  	}
   732  
   733  	// if grant is significantly newer than the one we have, we should check the profile showcase
   734  	if time.Duration(difference)*time.Millisecond > grantInvokesProfileDispatchInterval {
   735  		err = m.UpdateProfileShowcaseCommunity(community)
   736  		if err != nil {
   737  			return err
   738  		}
   739  	}
   740  	return nil
   741  }
   742  
   743  func (m *Messenger) publishGroupGrantMessage(community *communities.Community, timestamp uint64, recipientGrants map[*ecdsa.PublicKey][]byte) error {
   744  	grants, err := m.encryptor.EncryptCommunityGrants(community.PrivateKey(), recipientGrants)
   745  	if err != nil {
   746  		return err
   747  	}
   748  
   749  	message := &protobuf.CommunityUpdateGrant{
   750  		Timestamp:   timestamp,
   751  		CommunityId: community.ID(),
   752  		Grants:      grants,
   753  	}
   754  
   755  	payload, err := proto.Marshal(message)
   756  	if err != nil {
   757  		return err
   758  	}
   759  
   760  	rawMessage := common.RawMessage{
   761  		Payload:             payload,
   762  		Sender:              community.PrivateKey(),
   763  		SkipEncryptionLayer: true,
   764  		MessageType:         protobuf.ApplicationMetadataMessage_COMMUNITY_UPDATE_GRANT,
   765  		PubsubTopic:         community.PubsubTopic(),
   766  		Priority:            &common.LowPriority,
   767  	}
   768  
   769  	_, err = m.sender.SendPublic(context.Background(), community.IDString(), rawMessage)
   770  	return err
   771  }
   772  
   773  func (m *Messenger) updateGrantsForControlledCommunities() {
   774  	controlledCommunities, err := m.communitiesManager.Controlled()
   775  	if err != nil {
   776  		m.logger.Error("failed fetch controlled communities for grants update", zap.Error(err))
   777  	}
   778  
   779  	for _, community := range controlledCommunities {
   780  		// Skip unencrypted communities
   781  		if !community.Encrypted() {
   782  			continue
   783  		}
   784  
   785  		memberGrants := map[*ecdsa.PublicKey][]byte{}
   786  		for memberKey := range community.Members() {
   787  			if memberKey == m.IdentityPublicKeyString() {
   788  				grant, err := community.BuildGrant(m.IdentityPublicKey(), "")
   789  				if err != nil {
   790  					m.logger.Error("can't build own grant for controlled community", zap.Error(err))
   791  				}
   792  
   793  				err = m.handleCommunityGrant(community, grant, uint64(time.Now().UnixMilli()))
   794  				if err != nil {
   795  					m.logger.Error("error handling grant for controlled community", zap.Error(err))
   796  				}
   797  			} else {
   798  				memberPubKey, err := common.HexToPubkey(memberKey)
   799  				if err != nil {
   800  					m.logger.Error("Pubkey decode ", zap.Error(err))
   801  				}
   802  
   803  				grant, err := community.BuildGrant(memberPubKey, "")
   804  				if err != nil {
   805  					m.logger.Error("can't build member's grant for controlled community", zap.Error(err))
   806  				}
   807  
   808  				memberGrants[memberPubKey] = grant
   809  			}
   810  		}
   811  		err = m.publishGroupGrantMessage(community, uint64(time.Now().UnixMilli()), memberGrants)
   812  		if err != nil {
   813  			m.logger.Error("failed to update grant for community members", zap.Error(err))
   814  		}
   815  	}
   816  }
   817  
   818  func (m *Messenger) schedulePublishGrantsForControlledCommunities() {
   819  	// Send once immediately
   820  	m.updateGrantsForControlledCommunities()
   821  
   822  	ticker := time.NewTicker(grantUpdateInterval)
   823  
   824  	go func() {
   825  		for {
   826  			select {
   827  			case <-ticker.C:
   828  				m.updateGrantsForControlledCommunities()
   829  			case <-m.quit:
   830  				ticker.Stop()
   831  				return
   832  			}
   833  		}
   834  	}()
   835  }
   836  
   837  func (m *Messenger) CheckCommunitiesToUnmute() (*MessengerResponse, error) {
   838  	m.logger.Debug("watching communities to unmute")
   839  	response := &MessengerResponse{}
   840  	communities, err := m.communitiesManager.All()
   841  	currTime := time.Now()
   842  	if err != nil {
   843  		return nil, fmt.Errorf("couldn't get all communities: %v", err)
   844  	}
   845  	for _, community := range communities {
   846  		communityMuteTill := community.MuteTill()
   847  
   848  		if currTime.After(communityMuteTill) && !communityMuteTill.Equal(time.Time{}) && community.Muted() {
   849  			err := m.communitiesManager.SetMuted(community.ID(), false)
   850  			if err != nil {
   851  				m.logger.Info("CheckCommunitiesToUnmute err", zap.Any("Couldn't unmute community", err))
   852  				break
   853  			}
   854  
   855  			err = m.MuteCommunityTill(community.ID(), time.Time{})
   856  			if err != nil {
   857  				m.logger.Info("MuteCommunityTill err", zap.Any("Could not set mute community till", err))
   858  				break
   859  			}
   860  
   861  			unmutedCommunity, err := m.communitiesManager.GetByID(community.ID())
   862  			if err != nil {
   863  				return nil, err
   864  			}
   865  			response.AddCommunity(unmutedCommunity)
   866  
   867  		}
   868  
   869  	}
   870  
   871  	return response, nil
   872  }
   873  
   874  func (m *Messenger) updateCommunityActiveMembers(communityID string) error {
   875  	lastWeek := time.Now().AddDate(0, 0, -7).Unix()
   876  	count, err := m.persistence.CountActiveChattersInCommunity(communityID, lastWeek)
   877  	if err != nil {
   878  		return err
   879  	}
   880  
   881  	if err = m.communitiesManager.SetCommunityActiveMembersCount(communityID, uint64(count)); err != nil {
   882  		return err
   883  	}
   884  
   885  	m.logger.Debug("community active members updated", zap.String("communityID", communityID), zap.Uint("count", count))
   886  	return nil
   887  }
   888  
   889  func (m *Messenger) Communities() ([]*communities.Community, error) {
   890  	return m.communitiesManager.All()
   891  }
   892  
   893  func (m *Messenger) ControlledCommunities() ([]*communities.Community, error) {
   894  	return m.communitiesManager.Controlled()
   895  }
   896  
   897  func (m *Messenger) JoinedCommunities() ([]*communities.Community, error) {
   898  	return m.communitiesManager.Joined()
   899  }
   900  
   901  func (m *Messenger) IsDisplayNameDupeOfCommunityMember(name string) (bool, error) {
   902  	controlled, err := m.communitiesManager.Controlled()
   903  	if err != nil {
   904  		return false, err
   905  	}
   906  
   907  	joined, err := m.communitiesManager.Joined()
   908  	if err != nil {
   909  		return false, err
   910  	}
   911  
   912  	for _, community := range append(controlled, joined...) {
   913  		for memberKey := range community.Members() {
   914  			contact := m.GetContactByID(memberKey)
   915  			if contact == nil {
   916  				continue
   917  			}
   918  			if strings.Compare(contact.DisplayName, name) == 0 {
   919  				return true, nil
   920  			}
   921  		}
   922  	}
   923  	return false, nil
   924  }
   925  
   926  func (m *Messenger) CommunityUpdateLastOpenedAt(communityID string) (int64, error) {
   927  	id, err := hexutil.Decode(communityID)
   928  	if err != nil {
   929  		return 0, err
   930  	}
   931  	currentTime := time.Now().Unix()
   932  	updatedCommunity, err := m.communitiesManager.CommunityUpdateLastOpenedAt(id, currentTime)
   933  	if err != nil {
   934  		return 0, err
   935  	}
   936  	err = m.syncCommunity(context.Background(), updatedCommunity, m.dispatchMessage)
   937  	if err != nil {
   938  		return 0, err
   939  	}
   940  	return currentTime, nil
   941  }
   942  
   943  func (m *Messenger) SpectatedCommunities() ([]*communities.Community, error) {
   944  	return m.communitiesManager.Spectated()
   945  }
   946  
   947  func (m *Messenger) initCommunityChats(community *communities.Community) ([]*Chat, error) {
   948  	logger := m.logger.Named("initCommunityChats")
   949  	publicFiltersToInit := m.DefaultFilters(community)
   950  
   951  	chats := CreateCommunityChats(community, m.getTimesource())
   952  
   953  	for _, chat := range chats {
   954  		publicFiltersToInit = append(publicFiltersToInit, transport.FiltersToInitialize{ChatID: chat.ID, PubsubTopic: community.PubsubTopic()})
   955  
   956  	}
   957  
   958  	// Load transport filters
   959  	filters, err := m.transport.InitPublicFilters(publicFiltersToInit)
   960  	if err != nil {
   961  		logger.Debug("m.transport.InitPublicFilters error", zap.Error(err))
   962  		return nil, err
   963  	}
   964  
   965  	if community.IsControlNode() {
   966  		// Init the community filter so we can receive messages on the community
   967  
   968  		communityFilters, err := m.InitCommunityFilters([]transport.CommunityFilterToInitialize{{
   969  			Shard:   community.Shard(),
   970  			PrivKey: community.PrivateKey(),
   971  		}})
   972  
   973  		if err != nil {
   974  			return nil, err
   975  		}
   976  		filters = append(filters, communityFilters...)
   977  	}
   978  
   979  	willSync, err := m.scheduleSyncFilters(filters)
   980  	if err != nil {
   981  		logger.Debug("m.scheduleSyncFilters error", zap.Error(err))
   982  		return nil, err
   983  	}
   984  
   985  	if !willSync {
   986  		defaultSyncPeriod, err := m.settings.GetDefaultSyncPeriod()
   987  		if err != nil {
   988  			logger.Debug("m.settings.GetDefaultSyncPeriod error", zap.Error(err))
   989  			return nil, err
   990  		}
   991  
   992  		timestamp := uint32(m.getTimesource().GetCurrentTime()/1000) - defaultSyncPeriod
   993  		for idx := range chats {
   994  			chats[idx].SyncedTo = timestamp
   995  			chats[idx].SyncedFrom = timestamp
   996  		}
   997  	}
   998  
   999  	if err = m.saveChats(chats); err != nil {
  1000  		logger.Debug("m.saveChats error", zap.Error(err))
  1001  		return nil, err
  1002  	}
  1003  
  1004  	return chats, nil
  1005  }
  1006  
  1007  func (m *Messenger) initCommunitySettings(communityID types.HexBytes) (*communities.CommunitySettings, error) {
  1008  	communitySettings, err := m.communitiesManager.GetCommunitySettingsByID(communityID)
  1009  	if err != nil {
  1010  		return nil, err
  1011  	}
  1012  	if communitySettings != nil {
  1013  		return communitySettings, nil
  1014  	}
  1015  
  1016  	communitySettings = &communities.CommunitySettings{
  1017  		CommunityID:                  communityID.String(),
  1018  		HistoryArchiveSupportEnabled: true,
  1019  	}
  1020  
  1021  	if err := m.communitiesManager.SaveCommunitySettings(*communitySettings); err != nil {
  1022  		return nil, err
  1023  	}
  1024  
  1025  	return communitySettings, nil
  1026  }
  1027  
  1028  func (m *Messenger) JoinCommunity(ctx context.Context, communityID types.HexBytes, forceJoin bool) (*MessengerResponse, error) {
  1029  	mr, err := m.joinCommunity(ctx, communityID, forceJoin)
  1030  	if err != nil {
  1031  		return nil, err
  1032  	}
  1033  
  1034  	if com, ok := mr.communities[communityID.String()]; ok {
  1035  		err = m.syncCommunity(context.Background(), com, m.dispatchMessage)
  1036  		if err != nil {
  1037  			return nil, err
  1038  		}
  1039  	}
  1040  
  1041  	return mr, nil
  1042  }
  1043  
  1044  func (m *Messenger) subscribeToCommunityShard(communityID []byte, shard *shard.Shard) error {
  1045  	if m.transport.WakuVersion() != 2 {
  1046  		return nil
  1047  	}
  1048  
  1049  	// TODO: this should probably be moved completely to transport once pubsub topic logic is implemented
  1050  	pubsubTopic := shard.PubsubTopic()
  1051  
  1052  	privK, err := m.transport.RetrievePubsubTopicKey(pubsubTopic)
  1053  	if err != nil {
  1054  		return err
  1055  	}
  1056  
  1057  	var pubK *ecdsa.PublicKey
  1058  	if privK != nil {
  1059  		pubK = &privK.PublicKey
  1060  	}
  1061  
  1062  	return m.transport.SubscribeToPubsubTopic(pubsubTopic, pubK)
  1063  }
  1064  
  1065  func (m *Messenger) unsubscribeFromShard(shard *shard.Shard) error {
  1066  	if m.transport.WakuVersion() != 2 {
  1067  		return nil
  1068  	}
  1069  
  1070  	// TODO: this should probably be moved completely to transport once pubsub topic logic is implemented
  1071  
  1072  	return m.transport.UnsubscribeFromPubsubTopic(shard.PubsubTopic())
  1073  }
  1074  
  1075  func (m *Messenger) joinCommunity(ctx context.Context, communityID types.HexBytes, forceJoin bool) (*MessengerResponse, error) {
  1076  	logger := m.logger.Named("joinCommunity")
  1077  	response := &MessengerResponse{}
  1078  	community, _ := m.communitiesManager.GetByID(communityID)
  1079  	isCommunityMember := community.Joined()
  1080  
  1081  	community, err := m.communitiesManager.JoinCommunity(communityID, forceJoin)
  1082  	if err != nil {
  1083  		logger.Debug("m.communitiesManager.JoinCommunity error", zap.Error(err))
  1084  		return nil, err
  1085  	}
  1086  
  1087  	// chats and settings are already initialized for spectated communities
  1088  	if !community.Spectated() {
  1089  		chats, err := m.initCommunityChats(community)
  1090  		if err != nil {
  1091  			return nil, err
  1092  		}
  1093  		response.AddChats(chats)
  1094  
  1095  		if _, err = m.initCommunitySettings(communityID); err != nil {
  1096  			return nil, err
  1097  		}
  1098  
  1099  		if err = m.subscribeToCommunityShard(community.ID(), community.Shard()); err != nil {
  1100  			return nil, err
  1101  		}
  1102  	}
  1103  
  1104  	communitySettings, err := m.communitiesManager.GetCommunitySettingsByID(communityID)
  1105  	if err != nil {
  1106  		return nil, err
  1107  	}
  1108  
  1109  	response.AddCommunity(community)
  1110  	response.AddCommunitySettings(communitySettings)
  1111  
  1112  	if err = m.reregisterForPushNotifications(); err != nil {
  1113  		return nil, err
  1114  	}
  1115  
  1116  	if err = m.sendCurrentUserStatusToCommunity(ctx, community); err != nil {
  1117  		logger.Debug("m.sendCurrentUserStatusToCommunity error", zap.Error(err))
  1118  		return nil, err
  1119  	}
  1120  
  1121  	if err = m.PublishIdentityImage(); err != nil {
  1122  		return nil, err
  1123  	}
  1124  
  1125  	// Was applicant not a member and successfully joined?
  1126  	if !isCommunityMember && community.Joined() {
  1127  		joinedNotification := &localnotifications.Notification{
  1128  			ID:       gethcommon.Hash(types.BytesToHash([]byte(`you-joined-` + communityID.String()))),
  1129  			Title:    community.Name(),
  1130  			Message:  community.Name(),
  1131  			BodyType: localnotifications.CategoryCommunityJoined,
  1132  			Category: localnotifications.CategoryCommunityJoined,
  1133  			Deeplink: "status-app://cr/" + community.IDString(),
  1134  			Image:    "",
  1135  		}
  1136  		response.AddNotification(joinedNotification)
  1137  
  1138  		// Activity Center notification
  1139  		requestID := communities.CalculateRequestID(common.PubkeyToHex(&m.identity.PublicKey), communityID)
  1140  		notification, err := m.persistence.GetActivityCenterNotificationByID(requestID)
  1141  		if err != nil {
  1142  			return nil, err
  1143  		}
  1144  
  1145  		if notification != nil && notification.MembershipStatus != ActivityCenterMembershipStatusAccepted {
  1146  			notification.MembershipStatus = ActivityCenterMembershipStatusAccepted
  1147  			notification.Read = false
  1148  			notification.Deleted = false
  1149  
  1150  			notification.UpdatedAt = m.GetCurrentTimeInMillis()
  1151  			err = m.addActivityCenterNotification(response, notification, nil)
  1152  			if err != nil {
  1153  				m.logger.Error("failed to update request to join accepted notification", zap.Error(err))
  1154  				return nil, err
  1155  			}
  1156  		}
  1157  	}
  1158  
  1159  	return response, nil
  1160  }
  1161  
  1162  func (m *Messenger) SpectateCommunity(communityID types.HexBytes) (*MessengerResponse, error) {
  1163  	logger := m.logger.Named("SpectateCommunity")
  1164  
  1165  	response := &MessengerResponse{}
  1166  
  1167  	community, err := m.communitiesManager.SpectateCommunity(communityID)
  1168  	if err != nil {
  1169  		logger.Debug("SpectateCommunity error", zap.Error(err))
  1170  		return nil, err
  1171  	}
  1172  
  1173  	chats, err := m.initCommunityChats(community)
  1174  	if err != nil {
  1175  		return nil, err
  1176  	}
  1177  	response.AddChats(chats)
  1178  
  1179  	settings, err := m.initCommunitySettings(communityID)
  1180  	if err != nil {
  1181  		return nil, err
  1182  	}
  1183  	response.AddCommunitySettings(settings)
  1184  
  1185  	response.AddCommunity(community)
  1186  
  1187  	if err = m.subscribeToCommunityShard(community.ID(), community.Shard()); err != nil {
  1188  		return nil, err
  1189  	}
  1190  
  1191  	// sync community
  1192  	m.asyncRequestAllHistoricMessages()
  1193  
  1194  	return response, nil
  1195  }
  1196  
  1197  func (m *Messenger) MuteDuration(mutedType requests.MutingVariation) (time.Time, error) {
  1198  	var MuteTill time.Time
  1199  
  1200  	switch mutedType {
  1201  	case MuteTill1Min:
  1202  		MuteTill = time.Now().Add(MuteFor1MinDuration)
  1203  	case MuteFor15Min:
  1204  		MuteTill = time.Now().Add(MuteFor15MinsDuration)
  1205  	case MuteFor1Hr:
  1206  		MuteTill = time.Now().Add(MuteFor1HrsDuration)
  1207  	case MuteFor8Hr:
  1208  		MuteTill = time.Now().Add(MuteFor8HrsDuration)
  1209  	case MuteFor24Hr:
  1210  		MuteTill = time.Now().Add(MuteFor24HrsDuration)
  1211  	case MuteFor1Week:
  1212  		MuteTill = time.Now().Add(MuteFor1WeekDuration)
  1213  	default:
  1214  		MuteTill = time.Time{}
  1215  	}
  1216  
  1217  	muteTillTimeRemoveMs, err := time.Parse(time.RFC3339, MuteTill.Format(time.RFC3339))
  1218  	if err != nil {
  1219  		return time.Time{}, err
  1220  	}
  1221  
  1222  	return muteTillTimeRemoveMs, nil
  1223  }
  1224  
  1225  func (m *Messenger) SetMuted(request *requests.MuteCommunity) error {
  1226  	if err := request.Validate(); err != nil {
  1227  		return err
  1228  	}
  1229  
  1230  	if request.MutedType == Unmuted {
  1231  		return m.communitiesManager.SetMuted(request.CommunityID, false)
  1232  	}
  1233  
  1234  	return m.communitiesManager.SetMuted(request.CommunityID, true)
  1235  }
  1236  
  1237  func (m *Messenger) MuteCommunityTill(communityID []byte, muteTill time.Time) error {
  1238  	return m.communitiesManager.MuteCommunityTill(communityID, muteTill)
  1239  }
  1240  
  1241  func (m *Messenger) MuteAllCommunityChats(request *requests.MuteCommunity) (time.Time, error) {
  1242  	return m.UpdateMuteCommunityStatus(request.CommunityID.String(), true, request.MutedType)
  1243  }
  1244  
  1245  func (m *Messenger) UnMuteAllCommunityChats(communityID string) (time.Time, error) {
  1246  	return m.UpdateMuteCommunityStatus(communityID, false, Unmuted)
  1247  }
  1248  
  1249  func (m *Messenger) UpdateMuteCommunityStatus(communityID string, muted bool, mutedType requests.MutingVariation) (time.Time, error) {
  1250  	community, err := m.communitiesManager.GetByIDString(communityID)
  1251  	if err != nil {
  1252  		return time.Time{}, err
  1253  	}
  1254  
  1255  	request := &requests.MuteCommunity{
  1256  		CommunityID: community.ID(),
  1257  		MutedType:   mutedType,
  1258  	}
  1259  
  1260  	err = m.SetMuted(request)
  1261  	if err != nil {
  1262  		return time.Time{}, err
  1263  	}
  1264  
  1265  	muteTill, err := m.MuteDuration(mutedType)
  1266  	if err != nil {
  1267  		return time.Time{}, err
  1268  	}
  1269  
  1270  	err = m.MuteCommunityTill(community.ID(), muteTill)
  1271  
  1272  	for _, chatID := range community.CommunityChatsIDs() {
  1273  		if muted {
  1274  			_, err := m.MuteChat(&requests.MuteChat{ChatID: communityID + chatID, MutedType: mutedType})
  1275  			if err != nil {
  1276  				return time.Time{}, err
  1277  			}
  1278  
  1279  		} else {
  1280  			err = m.UnmuteChat(communityID + chatID)
  1281  			if err != nil {
  1282  				return time.Time{}, err
  1283  			}
  1284  
  1285  		}
  1286  
  1287  		if err != nil {
  1288  			return time.Time{}, err
  1289  		}
  1290  	}
  1291  
  1292  	return muteTill, err
  1293  }
  1294  
  1295  func (m *Messenger) SetMutePropertyOnChatsByCategory(request *requests.MuteCategory, muted bool) error {
  1296  	if err := request.Validate(); err != nil {
  1297  		return err
  1298  	}
  1299  	community, err := m.communitiesManager.GetByIDString(request.CommunityID)
  1300  	if err != nil {
  1301  		return err
  1302  	}
  1303  
  1304  	for _, chatID := range community.ChatsByCategoryID(request.CategoryID) {
  1305  		if muted {
  1306  			_, err = m.MuteChat(&requests.MuteChat{ChatID: request.CommunityID + chatID, MutedType: request.MutedType})
  1307  		} else {
  1308  			err = m.UnmuteChat(request.CommunityID + chatID)
  1309  		}
  1310  		if err != nil {
  1311  			return err
  1312  		}
  1313  	}
  1314  
  1315  	return nil
  1316  }
  1317  
  1318  // Generates a single hash for each address that needs to be revealed to a community.
  1319  // Each hash needs to be signed.
  1320  // The order of retuned hashes corresponds to the order of addresses in addressesToReveal.
  1321  func (m *Messenger) generateCommunityRequestsForSigning(memberPubKey string, communityID types.HexBytes, addressesToReveal []string, isEdit bool) ([]account.SignParams, error) {
  1322  	walletAccounts, err := m.settings.GetActiveAccounts()
  1323  	if err != nil {
  1324  		return nil, err
  1325  	}
  1326  
  1327  	containsAddress := func(addresses []string, targetAddress string) bool {
  1328  		for _, address := range addresses {
  1329  			if types.HexToAddress(address) == types.HexToAddress(targetAddress) {
  1330  				return true
  1331  			}
  1332  		}
  1333  		return false
  1334  	}
  1335  
  1336  	msgsToSign := make([]account.SignParams, 0)
  1337  	for _, walletAccount := range walletAccounts {
  1338  		if walletAccount.Chat || walletAccount.Type == accounts.AccountTypeWatch {
  1339  			continue
  1340  		}
  1341  
  1342  		if len(addressesToReveal) > 0 && !containsAddress(addressesToReveal, walletAccount.Address.Hex()) {
  1343  			continue
  1344  		}
  1345  
  1346  		requestID := []byte{}
  1347  		if !isEdit {
  1348  			requestID = communities.CalculateRequestID(memberPubKey, communityID)
  1349  		}
  1350  		msgsToSign = append(msgsToSign, account.SignParams{
  1351  			Data:    types.EncodeHex(crypto.Keccak256(m.IdentityPublicKeyCompressed(), communityID, requestID)),
  1352  			Address: walletAccount.Address.Hex(),
  1353  		})
  1354  	}
  1355  
  1356  	return msgsToSign, nil
  1357  }
  1358  
  1359  func (m *Messenger) GenerateJoiningCommunityRequestsForSigning(memberPubKey string, communityID types.HexBytes, addressesToReveal []string) ([]account.SignParams, error) {
  1360  	if len(communityID) == 0 {
  1361  		return nil, errors.New(ErrMissingCommunityID)
  1362  	}
  1363  	return m.generateCommunityRequestsForSigning(memberPubKey, communityID, addressesToReveal, false)
  1364  }
  1365  
  1366  func (m *Messenger) GenerateEditCommunityRequestsForSigning(memberPubKey string, communityID types.HexBytes, addressesToReveal []string) ([]account.SignParams, error) {
  1367  	return m.generateCommunityRequestsForSigning(memberPubKey, communityID, addressesToReveal, true)
  1368  }
  1369  
  1370  // Signs the provided messages with the provided accounts and password.
  1371  // Provided accounts must not belong to a keypair that is migrated to a keycard.
  1372  // Otherwise, the signing will fail, cause such accounts should be signed with a keycard.
  1373  func (m *Messenger) SignData(signParams []account.SignParams) ([]string, error) {
  1374  	signatures := make([]string, len(signParams))
  1375  	for i, param := range signParams {
  1376  		if err := param.Validate(true); err != nil {
  1377  			return nil, err
  1378  		}
  1379  
  1380  		account, err := m.settings.GetAccountByAddress(types.HexToAddress(param.Address))
  1381  		if err != nil {
  1382  			return nil, err
  1383  		}
  1384  
  1385  		if account.Chat || account.Type == accounts.AccountTypeWatch {
  1386  			return nil, errors.New(ErrForbiddenProfileOrWatchOnlyAccount)
  1387  		}
  1388  
  1389  		keypair, err := m.settings.GetKeypairByKeyUID(account.KeyUID)
  1390  		if err != nil {
  1391  			return nil, err
  1392  		}
  1393  
  1394  		if keypair.MigratedToKeycard() {
  1395  			return nil, errors.New(ErrSigningJoinRequestForKeycardAccounts)
  1396  		}
  1397  
  1398  		verifiedAccount, err := m.accountsManager.GetVerifiedWalletAccount(m.settings, param.Address, param.Password)
  1399  		if err != nil {
  1400  			return nil, err
  1401  		}
  1402  
  1403  		signature, err := m.accountsManager.Sign(param, verifiedAccount)
  1404  		if err != nil {
  1405  			return nil, err
  1406  		}
  1407  
  1408  		signatures[i] = types.EncodeHex(signature)
  1409  	}
  1410  
  1411  	return signatures, nil
  1412  }
  1413  
  1414  func (m *Messenger) RequestToJoinCommunity(request *requests.RequestToJoinCommunity) (*MessengerResponse, error) {
  1415  	// TODO: Because of changes that need to be done in tests, calling this function and providing `request` without `AddressesToReveal`
  1416  	//       is not an error, but it should be.
  1417  	logger := m.logger.Named("RequestToJoinCommunity")
  1418  	logger.Debug("Addresses to reveal", zap.Any("Addresses:", request.AddressesToReveal))
  1419  
  1420  	if err := request.Validate(); err != nil {
  1421  		logger.Debug("request failed to validate", zap.Error(err), zap.Any("request", request))
  1422  		return nil, err
  1423  	}
  1424  
  1425  	community, err := m.communitiesManager.GetByID(request.CommunityID)
  1426  	if err != nil {
  1427  		return nil, err
  1428  	}
  1429  
  1430  	// We don't allow requesting access if already joined
  1431  	if community.Joined() {
  1432  		return nil, communities.ErrAlreadyJoined
  1433  	}
  1434  
  1435  	requestToJoin := m.communitiesManager.CreateRequestToJoin(request, m.account.GetCustomizationColor())
  1436  
  1437  	if len(request.AddressesToReveal) > 0 {
  1438  		revealedAddresses := make([]gethcommon.Address, 0)
  1439  		for _, addr := range request.AddressesToReveal {
  1440  			revealedAddresses = append(revealedAddresses, gethcommon.HexToAddress(addr))
  1441  		}
  1442  
  1443  		permissions, err := m.communitiesManager.CheckPermissionToJoin(request.CommunityID, revealedAddresses)
  1444  		if err != nil {
  1445  			return nil, err
  1446  		}
  1447  		if !permissions.Satisfied {
  1448  			return nil, communities.ErrPermissionToJoinNotSatisfied
  1449  		}
  1450  
  1451  		for _, accountAndChainIDs := range permissions.ValidCombinations {
  1452  			for i := range requestToJoin.RevealedAccounts {
  1453  				if gethcommon.HexToAddress(requestToJoin.RevealedAccounts[i].Address) == accountAndChainIDs.Address {
  1454  					requestToJoin.RevealedAccounts[i].ChainIds = accountAndChainIDs.ChainIDs
  1455  				}
  1456  			}
  1457  		}
  1458  	}
  1459  
  1460  	displayName, err := m.settings.DisplayName()
  1461  	if err != nil {
  1462  		return nil, err
  1463  	}
  1464  
  1465  	requestToJoinProto := &protobuf.CommunityRequestToJoin{
  1466  		Clock:              requestToJoin.Clock,
  1467  		EnsName:            requestToJoin.ENSName,
  1468  		DisplayName:        displayName,
  1469  		CommunityId:        request.CommunityID,
  1470  		RevealedAccounts:   requestToJoin.RevealedAccounts,
  1471  		CustomizationColor: multiaccountscommon.ColorToIDFallbackToBlue(requestToJoin.CustomizationColor),
  1472  	}
  1473  
  1474  	community, _, err = m.communitiesManager.SaveRequestToJoinAndCommunity(requestToJoin, community)
  1475  	if err != nil {
  1476  		return nil, err
  1477  	}
  1478  	err = m.syncCommunity(context.Background(), community, m.dispatchMessage)
  1479  	if err != nil {
  1480  		return nil, err
  1481  	}
  1482  
  1483  	payload, err := proto.Marshal(requestToJoinProto)
  1484  	if err != nil {
  1485  		return nil, err
  1486  	}
  1487  
  1488  	rawMessage := &common.RawMessage{
  1489  		Payload:             payload,
  1490  		CommunityID:         community.ID(),
  1491  		ResendType:          common.ResendTypeRawMessage,
  1492  		SkipEncryptionLayer: true,
  1493  		MessageType:         protobuf.ApplicationMetadataMessage_COMMUNITY_REQUEST_TO_JOIN,
  1494  		PubsubTopic:         shard.DefaultNonProtectedPubsubTopic(),
  1495  		Priority:            &common.HighPriority,
  1496  	}
  1497  
  1498  	_, err = m.SendMessageToControlNode(community, rawMessage)
  1499  	if err != nil {
  1500  		return nil, err
  1501  	}
  1502  
  1503  	if rawMessage.ResendType == common.ResendTypeRawMessage {
  1504  		if _, err = m.AddRawMessageToWatch(rawMessage); err != nil {
  1505  			return nil, err
  1506  		}
  1507  	}
  1508  
  1509  	if !community.AutoAccept() {
  1510  		privilegedMembersSorted := community.GetFilteredPrivilegedMembers(map[string]struct{}{m.IdentityPublicKeyString(): {}})
  1511  		privMembersArray := []*ecdsa.PublicKey{}
  1512  
  1513  		if rawMessage.ResendMethod != common.ResendMethodSendPrivate {
  1514  			privMembersArray = append(privMembersArray, privilegedMembersSorted[protobuf.CommunityMember_ROLE_OWNER]...)
  1515  		}
  1516  
  1517  		privMembersArray = append(privMembersArray, privilegedMembersSorted[protobuf.CommunityMember_ROLE_TOKEN_MASTER]...)
  1518  		privMembersArray = append(privMembersArray, privilegedMembersSorted[protobuf.CommunityMember_ROLE_ADMIN]...)
  1519  
  1520  		rawMessage.ResendMethod = common.ResendMethodSendPrivate
  1521  		rawMessage.ResendType = common.ResendTypeDataSync
  1522  		// MVDS only supports sending encrypted message
  1523  		rawMessage.SkipEncryptionLayer = false
  1524  		rawMessage.ID = ""
  1525  		rawMessage.Recipients = privMembersArray
  1526  
  1527  		// don't send revealed addresses to privileged members
  1528  		// tokenMaster and owner without community private key will receive them from control node
  1529  		requestToJoinProto.RevealedAccounts = make([]*protobuf.RevealedAccount, 0)
  1530  		payload, err = proto.Marshal(requestToJoinProto)
  1531  		if err != nil {
  1532  			return nil, err
  1533  		}
  1534  		rawMessage.Payload = payload
  1535  
  1536  		for _, member := range rawMessage.Recipients {
  1537  			rawMessage.Sender = nil
  1538  			_, err := m.sender.SendPrivate(context.Background(), member, rawMessage)
  1539  			if err != nil {
  1540  				return nil, err
  1541  			}
  1542  		}
  1543  	}
  1544  
  1545  	response := &MessengerResponse{}
  1546  	response.AddRequestToJoinCommunity(requestToJoin)
  1547  	response.AddCommunity(community)
  1548  
  1549  	// We send a push notification in the background
  1550  	go func() {
  1551  		if m.pushNotificationClient != nil {
  1552  			pks, err := community.CanManageUsersPublicKeys()
  1553  			if err != nil {
  1554  				m.logger.Error("failed to get pks", zap.Error(err))
  1555  				return
  1556  			}
  1557  			for _, publicKey := range pks {
  1558  				pkString := common.PubkeyToHex(publicKey)
  1559  				_, err = m.pushNotificationClient.SendNotification(publicKey, nil, requestToJoin.ID, pkString, protobuf.PushNotification_REQUEST_TO_JOIN_COMMUNITY)
  1560  				if err != nil {
  1561  					m.logger.Error("error sending notification", zap.Error(err))
  1562  					return
  1563  				}
  1564  			}
  1565  		}
  1566  	}()
  1567  
  1568  	// Activity center notification
  1569  	notification := &ActivityCenterNotification{
  1570  		ID:               types.FromHex(requestToJoin.ID.String()),
  1571  		Type:             ActivityCenterNotificationTypeCommunityRequest,
  1572  		Timestamp:        m.getTimesource().GetCurrentTime(),
  1573  		CommunityID:      community.IDString(),
  1574  		MembershipStatus: ActivityCenterMembershipStatusPending,
  1575  		Read:             true,
  1576  		Deleted:          false,
  1577  		UpdatedAt:        m.GetCurrentTimeInMillis(),
  1578  	}
  1579  
  1580  	err = m.addActivityCenterNotification(response, notification, nil)
  1581  	if err != nil {
  1582  		m.logger.Error("failed to save notification", zap.Error(err))
  1583  		return nil, err
  1584  	}
  1585  
  1586  	for _, account := range requestToJoin.RevealedAccounts {
  1587  		err := m.settings.AddressWasShown(types.HexToAddress(account.Address))
  1588  		if err != nil {
  1589  			return nil, err
  1590  		}
  1591  	}
  1592  
  1593  	return response, nil
  1594  }
  1595  
  1596  func (m *Messenger) EditSharedAddressesForCommunity(request *requests.EditSharedAddresses) (*MessengerResponse, error) {
  1597  	logger := m.logger.Named("EditSharedAddressesForCommunity")
  1598  	if err := request.Validate(); err != nil {
  1599  		logger.Debug("request failed to validate", zap.Error(err), zap.Any("request", request))
  1600  		return nil, err
  1601  	}
  1602  
  1603  	community, err := m.communitiesManager.GetByID(request.CommunityID)
  1604  	if err != nil {
  1605  		return nil, err
  1606  	}
  1607  
  1608  	if !community.HasMember(m.IdentityPublicKey()) {
  1609  		return nil, errors.New(ErrNotPartOfCommunity)
  1610  	}
  1611  
  1612  	revealedAddresses := make([]gethcommon.Address, 0)
  1613  	for _, addr := range request.AddressesToReveal {
  1614  		revealedAddresses = append(revealedAddresses, gethcommon.HexToAddress(addr))
  1615  	}
  1616  
  1617  	checkPermissionResponse, err := m.communitiesManager.CheckPermissionToJoin(community.ID(), revealedAddresses)
  1618  	if err != nil {
  1619  		return nil, err
  1620  	}
  1621  
  1622  	member := community.GetMember(m.IdentityPublicKey())
  1623  
  1624  	requestToEditRevealedAccountsProto := &protobuf.CommunityEditSharedAddresses{
  1625  		Clock:            member.LastUpdateClock + 1,
  1626  		CommunityId:      community.ID(),
  1627  		RevealedAccounts: make([]*protobuf.RevealedAccount, 0),
  1628  	}
  1629  
  1630  	for i := range request.AddressesToReveal {
  1631  		revealedAcc := &protobuf.RevealedAccount{
  1632  			Address:          request.AddressesToReveal[i],
  1633  			IsAirdropAddress: types.HexToAddress(request.AddressesToReveal[i]) == types.HexToAddress(request.AirdropAddress),
  1634  			Signature:        request.Signatures[i],
  1635  		}
  1636  
  1637  		for _, accountAndChainIDs := range checkPermissionResponse.ValidCombinations {
  1638  			if accountAndChainIDs.Address == gethcommon.HexToAddress(request.AddressesToReveal[i]) {
  1639  				revealedAcc.ChainIds = accountAndChainIDs.ChainIDs
  1640  				break
  1641  			}
  1642  		}
  1643  
  1644  		requestToEditRevealedAccountsProto.RevealedAccounts = append(requestToEditRevealedAccountsProto.RevealedAccounts, revealedAcc)
  1645  	}
  1646  
  1647  	requestID := communities.CalculateRequestID(common.PubkeyToHex(&m.identity.PublicKey), request.CommunityID)
  1648  	err = m.communitiesManager.RemoveRequestToJoinRevealedAddresses(requestID)
  1649  	if err != nil {
  1650  		return nil, err
  1651  	}
  1652  	err = m.communitiesManager.SaveRequestToJoinRevealedAddresses(requestID, requestToEditRevealedAccountsProto.RevealedAccounts)
  1653  	if err != nil {
  1654  		return nil, err
  1655  	}
  1656  
  1657  	payload, err := proto.Marshal(requestToEditRevealedAccountsProto)
  1658  	if err != nil {
  1659  		return nil, err
  1660  	}
  1661  
  1662  	rawMessage := common.RawMessage{
  1663  		Payload:             payload,
  1664  		CommunityID:         community.ID(),
  1665  		SkipEncryptionLayer: true,
  1666  		MessageType:         protobuf.ApplicationMetadataMessage_COMMUNITY_EDIT_SHARED_ADDRESSES,
  1667  		PubsubTopic:         community.PubsubTopic(), // TODO: confirm if it should be sent in community pubsub topic
  1668  		ResendType:          common.ResendTypeRawMessage,
  1669  	}
  1670  
  1671  	_, err = m.SendMessageToControlNode(community, &rawMessage)
  1672  	if err != nil {
  1673  		return nil, err
  1674  	}
  1675  
  1676  	if _, err = m.AddRawMessageToWatch(&rawMessage); err != nil {
  1677  		return nil, err
  1678  	}
  1679  
  1680  	response := &MessengerResponse{}
  1681  	response.AddCommunity(community)
  1682  
  1683  	return response, nil
  1684  }
  1685  
  1686  func (m *Messenger) PublishTokenActionToPrivilegedMembers(communityID []byte, chainID uint64, contractAddress string, actionType protobuf.CommunityTokenAction_ActionType) error {
  1687  
  1688  	community, err := m.communitiesManager.GetByID(communityID)
  1689  	if err != nil {
  1690  		return err
  1691  	}
  1692  
  1693  	tokenActionProto := &protobuf.CommunityTokenAction{
  1694  		ChainId:         chainID,
  1695  		ContractAddress: contractAddress,
  1696  		ActionType:      actionType,
  1697  	}
  1698  
  1699  	payload, err := proto.Marshal(tokenActionProto)
  1700  	if err != nil {
  1701  		return err
  1702  	}
  1703  
  1704  	rawMessage := common.RawMessage{
  1705  		Payload:      payload,
  1706  		CommunityID:  community.ID(),
  1707  		ResendType:   common.ResendTypeRawMessage,
  1708  		ResendMethod: common.ResendMethodSendPrivate,
  1709  		MessageType:  protobuf.ApplicationMetadataMessage_COMMUNITY_TOKEN_ACTION,
  1710  		PubsubTopic:  community.PubsubTopic(),
  1711  	}
  1712  
  1713  	skipMembers := make(map[string]struct{})
  1714  	skipMembers[common.PubkeyToHex(&m.identity.PublicKey)] = struct{}{}
  1715  	privilegedMembers := community.GetFilteredPrivilegedMembers(skipMembers)
  1716  
  1717  	allRecipients := privilegedMembers[protobuf.CommunityMember_ROLE_OWNER]
  1718  	allRecipients = append(allRecipients, privilegedMembers[protobuf.CommunityMember_ROLE_TOKEN_MASTER]...)
  1719  	rawMessage.Recipients = allRecipients
  1720  
  1721  	for _, recipient := range rawMessage.Recipients {
  1722  		_, err := m.sender.SendPrivate(context.Background(), recipient, &rawMessage)
  1723  		if err != nil {
  1724  			return err
  1725  		}
  1726  	}
  1727  
  1728  	if len(allRecipients) > 0 {
  1729  		if _, err = m.AddRawMessageToWatch(&rawMessage); err != nil {
  1730  			return err
  1731  		}
  1732  	}
  1733  
  1734  	return nil
  1735  }
  1736  
  1737  func (m *Messenger) GetRevealedAccounts(communityID types.HexBytes, memberPk string) ([]*protobuf.RevealedAccount, error) {
  1738  	return m.communitiesManager.GetRevealedAddresses(communityID, memberPk)
  1739  }
  1740  
  1741  func (m *Messenger) GetRevealedAccountsForAllMembers(communityID types.HexBytes) (map[string][]*protobuf.RevealedAccount, error) {
  1742  	community, err := m.communitiesManager.GetByID(communityID)
  1743  	if err != nil {
  1744  		return nil, err
  1745  	}
  1746  	membersRevealedAccounts := map[string][]*protobuf.RevealedAccount{}
  1747  	for _, memberPubKey := range community.GetMemberPubkeys() {
  1748  		memberPubKeyStr := common.PubkeyToHex(memberPubKey)
  1749  		accounts, err := m.communitiesManager.GetRevealedAddresses(communityID, memberPubKeyStr)
  1750  		if err != nil {
  1751  			return nil, err
  1752  		}
  1753  		membersRevealedAccounts[memberPubKeyStr] = accounts
  1754  	}
  1755  	return membersRevealedAccounts, nil
  1756  }
  1757  
  1758  func (m *Messenger) CreateCommunityCategory(request *requests.CreateCommunityCategory) (*MessengerResponse, error) {
  1759  	if err := request.Validate(); err != nil {
  1760  		return nil, err
  1761  	}
  1762  
  1763  	var response MessengerResponse
  1764  	_, changes, err := m.communitiesManager.CreateCategory(request, true)
  1765  	if err != nil {
  1766  		return nil, err
  1767  	}
  1768  	response.AddCommunity(changes.Community)
  1769  	response.CommunityChanges = []*communities.CommunityChanges{changes}
  1770  
  1771  	return &response, nil
  1772  }
  1773  
  1774  func (m *Messenger) EditCommunityCategory(request *requests.EditCommunityCategory) (*MessengerResponse, error) {
  1775  	if err := request.Validate(); err != nil {
  1776  		return nil, err
  1777  	}
  1778  
  1779  	var response MessengerResponse
  1780  	community, changes, err := m.communitiesManager.EditCategory(request)
  1781  	if err != nil {
  1782  		return nil, err
  1783  	}
  1784  	response.AddCommunity(community)
  1785  	response.CommunityChanges = []*communities.CommunityChanges{changes}
  1786  
  1787  	return &response, nil
  1788  }
  1789  
  1790  func (m *Messenger) ReorderCommunityCategories(request *requests.ReorderCommunityCategories) (*MessengerResponse, error) {
  1791  	if err := request.Validate(); err != nil {
  1792  		return nil, err
  1793  	}
  1794  
  1795  	var response MessengerResponse
  1796  	community, changes, err := m.communitiesManager.ReorderCategories(request)
  1797  	if err != nil {
  1798  		return nil, err
  1799  	}
  1800  	response.AddCommunity(community)
  1801  	response.CommunityChanges = []*communities.CommunityChanges{changes}
  1802  
  1803  	return &response, nil
  1804  }
  1805  
  1806  func (m *Messenger) ReorderCommunityChat(request *requests.ReorderCommunityChat) (*MessengerResponse, error) {
  1807  	if err := request.Validate(); err != nil {
  1808  		return nil, err
  1809  	}
  1810  
  1811  	var response MessengerResponse
  1812  	community, changes, err := m.communitiesManager.ReorderChat(request)
  1813  	if err != nil {
  1814  		return nil, err
  1815  	}
  1816  	response.AddCommunity(community)
  1817  	response.CommunityChanges = []*communities.CommunityChanges{changes}
  1818  
  1819  	return &response, nil
  1820  }
  1821  
  1822  func (m *Messenger) DeleteCommunityCategory(request *requests.DeleteCommunityCategory) (*MessengerResponse, error) {
  1823  	if err := request.Validate(); err != nil {
  1824  		return nil, err
  1825  	}
  1826  
  1827  	var response MessengerResponse
  1828  	community, changes, err := m.communitiesManager.DeleteCategory(request)
  1829  	if err != nil {
  1830  		return nil, err
  1831  	}
  1832  	response.AddCommunity(community)
  1833  	response.CommunityChanges = []*communities.CommunityChanges{changes}
  1834  
  1835  	return &response, nil
  1836  }
  1837  
  1838  func (m *Messenger) CancelRequestToJoinCommunity(ctx context.Context, request *requests.CancelRequestToJoinCommunity) (*MessengerResponse, error) {
  1839  	if err := request.Validate(); err != nil {
  1840  		return nil, err
  1841  	}
  1842  
  1843  	requestToJoin, community, err := m.communitiesManager.CancelRequestToJoin(request)
  1844  	if err != nil {
  1845  		return nil, err
  1846  	}
  1847  
  1848  	displayName, err := m.settings.DisplayName()
  1849  	if err != nil {
  1850  		return nil, err
  1851  	}
  1852  
  1853  	cancelRequestToJoinProto := &protobuf.CommunityCancelRequestToJoin{
  1854  		Clock:              community.Clock(),
  1855  		EnsName:            requestToJoin.ENSName,
  1856  		DisplayName:        displayName,
  1857  		CommunityId:        community.ID(),
  1858  		CustomizationColor: multiaccountscommon.ColorToIDFallbackToBlue(requestToJoin.CustomizationColor),
  1859  	}
  1860  
  1861  	payload, err := proto.Marshal(cancelRequestToJoinProto)
  1862  	if err != nil {
  1863  		return nil, err
  1864  	}
  1865  
  1866  	rawMessage := common.RawMessage{
  1867  		Payload:             payload,
  1868  		CommunityID:         community.ID(),
  1869  		SkipEncryptionLayer: true,
  1870  		MessageType:         protobuf.ApplicationMetadataMessage_COMMUNITY_CANCEL_REQUEST_TO_JOIN,
  1871  		PubsubTopic:         shard.DefaultNonProtectedPubsubTopic(),
  1872  		ResendType:          common.ResendTypeRawMessage,
  1873  		Priority:            &common.HighPriority,
  1874  	}
  1875  
  1876  	_, err = m.SendMessageToControlNode(community, &rawMessage)
  1877  	if err != nil {
  1878  		return nil, err
  1879  	}
  1880  
  1881  	// NOTE: rawMessage.ID is generated from payload + sender + messageType
  1882  	// rawMessage.ID will be the same for control node and privileged members, but for
  1883  	// community without owner token resend type is different
  1884  	// in order not to override msg to control node by message for privileged members,
  1885  	// we skip storing the same message for privileged members
  1886  	avoidDuplicateWatchingForPrivilegedMembers := community.AutoAccept() || rawMessage.ResendMethod != common.ResendMethodSendPrivate
  1887  	if avoidDuplicateWatchingForPrivilegedMembers {
  1888  		if _, err = m.AddRawMessageToWatch(&rawMessage); err != nil {
  1889  			return nil, err
  1890  		}
  1891  	}
  1892  
  1893  	if !community.AutoAccept() {
  1894  		// send cancelation to community admins also
  1895  		rawMessage.Payload = payload
  1896  		rawMessage.ResendMethod = common.ResendMethodSendPrivate
  1897  
  1898  		privilegedMembersSorted := community.GetFilteredPrivilegedMembers(map[string]struct{}{m.IdentityPublicKeyString(): {}})
  1899  		privMembersArray := privilegedMembersSorted[protobuf.CommunityMember_ROLE_TOKEN_MASTER]
  1900  		privMembersArray = append(privMembersArray, privilegedMembersSorted[protobuf.CommunityMember_ROLE_ADMIN]...)
  1901  
  1902  		if !avoidDuplicateWatchingForPrivilegedMembers {
  1903  			// control node was added to the recipients during 'SendMessageToControlNode'
  1904  			rawMessage.Recipients = append(rawMessage.Recipients, privMembersArray...)
  1905  		} else {
  1906  			privMembersArray = append(privMembersArray, privilegedMembersSorted[protobuf.CommunityMember_ROLE_OWNER]...)
  1907  			rawMessage.Recipients = privMembersArray
  1908  		}
  1909  
  1910  		for _, privilegedMember := range privMembersArray {
  1911  			_, err := m.sender.SendPrivate(context.Background(), privilegedMember, &rawMessage)
  1912  			if err != nil {
  1913  				return nil, err
  1914  			}
  1915  		}
  1916  
  1917  		if !avoidDuplicateWatchingForPrivilegedMembers {
  1918  			if _, err = m.AddRawMessageToWatch(&rawMessage); err != nil {
  1919  				return nil, err
  1920  			}
  1921  		}
  1922  	}
  1923  
  1924  	response := &MessengerResponse{}
  1925  	response.AddCommunity(community)
  1926  	response.AddRequestToJoinCommunity(requestToJoin)
  1927  
  1928  	// delete activity center notification
  1929  	notification, err := m.persistence.GetActivityCenterNotificationByID(requestToJoin.ID)
  1930  	if err != nil {
  1931  		return nil, err
  1932  	}
  1933  
  1934  	if notification != nil {
  1935  		notification.IncrementUpdatedAt(m.getTimesource())
  1936  		err = m.persistence.DeleteActivityCenterNotificationByID(types.FromHex(requestToJoin.ID.String()), notification.UpdatedAt)
  1937  		if err != nil {
  1938  			m.logger.Error("failed to delete notification from Activity Center", zap.Error(err))
  1939  			return nil, err
  1940  		}
  1941  
  1942  		// set notification as deleted, so that the client will remove the activity center notification from UI
  1943  		notification.Deleted = true
  1944  		err = m.syncActivityCenterDeletedByIDs(ctx, []types.HexBytes{notification.ID}, notification.UpdatedAt)
  1945  		if err != nil {
  1946  			m.logger.Error("CancelRequestToJoinCommunity, failed to sync activity center notification as deleted", zap.Error(err))
  1947  			return nil, err
  1948  		}
  1949  		response.AddActivityCenterNotification(notification)
  1950  	}
  1951  
  1952  	return response, nil
  1953  }
  1954  
  1955  func (m *Messenger) acceptRequestToJoinCommunity(requestToJoin *communities.RequestToJoin) (*MessengerResponse, error) {
  1956  	m.logger.Debug("accept request to join community",
  1957  		zap.String("community", requestToJoin.CommunityID.String()),
  1958  		zap.String("pubkey", requestToJoin.PublicKey))
  1959  
  1960  	community, err := m.communitiesManager.AcceptRequestToJoin(requestToJoin)
  1961  	if err != nil {
  1962  		return nil, err
  1963  	}
  1964  
  1965  	if community.IsControlNode() {
  1966  		// If we are the control node, we send the response to the user
  1967  		pk, err := common.HexToPubkey(requestToJoin.PublicKey)
  1968  		if err != nil {
  1969  			return nil, err
  1970  		}
  1971  
  1972  		grant, err := community.BuildGrant(pk, "")
  1973  		if err != nil {
  1974  			return nil, err
  1975  		}
  1976  
  1977  		var key *ecdsa.PrivateKey
  1978  		if m.transport.WakuVersion() == 2 {
  1979  			key, err = m.transport.RetrievePubsubTopicKey(community.PubsubTopic())
  1980  			if err != nil {
  1981  				return nil, err
  1982  			}
  1983  		}
  1984  
  1985  		encryptedDescription, err := community.EncryptedDescription()
  1986  		if err != nil {
  1987  			return nil, err
  1988  		}
  1989  
  1990  		requestToJoinResponseProto := &protobuf.CommunityRequestToJoinResponse{
  1991  			Clock:                    community.Clock(),
  1992  			Accepted:                 true,
  1993  			CommunityId:              community.ID(),
  1994  			Community:                encryptedDescription,
  1995  			Grant:                    grant,
  1996  			ProtectedTopicPrivateKey: crypto.FromECDSA(key),
  1997  			Shard:                    community.Shard().Protobuffer(),
  1998  		}
  1999  
  2000  		// The purpose of this torrent code is to get the 'magnetlink' to populate 'requestToJoinResponseProto.MagnetUri'
  2001  		if m.archiveManager.IsReady() && m.archiveManager.TorrentFileExists(community.IDString()) {
  2002  			magnetlink, err := m.archiveManager.GetHistoryArchiveMagnetlink(community.ID())
  2003  			if err != nil {
  2004  				m.logger.Warn("couldn't get magnet link for community", zap.Error(err))
  2005  				return nil, err
  2006  			}
  2007  			requestToJoinResponseProto.MagnetUri = magnetlink
  2008  		}
  2009  
  2010  		payload, err := proto.Marshal(requestToJoinResponseProto)
  2011  		if err != nil {
  2012  			return nil, err
  2013  		}
  2014  
  2015  		rawMessage := &common.RawMessage{
  2016  			Payload:             payload,
  2017  			Sender:              community.PrivateKey(),
  2018  			CommunityID:         community.ID(),
  2019  			SkipEncryptionLayer: true,
  2020  			MessageType:         protobuf.ApplicationMetadataMessage_COMMUNITY_REQUEST_TO_JOIN_RESPONSE,
  2021  			PubsubTopic:         shard.DefaultNonProtectedPubsubTopic(),
  2022  			ResendType:          common.ResendTypeRawMessage,
  2023  			ResendMethod:        common.ResendMethodSendPrivate,
  2024  			Recipients:          []*ecdsa.PublicKey{pk},
  2025  			Priority:            &common.HighPriority,
  2026  		}
  2027  
  2028  		// Non-tokenized community treat community public key as the control node,
  2029  		// tokenized community set control node to the public key of token owner.
  2030  		// MVDS doesn't support custom sender, and use the identity key for signing messages,
  2031  		// receiver will verify the message of community join response is signed by control node.
  2032  		if !community.PublicKey().Equal(community.ControlNode()) {
  2033  			rawMessage.ResendType = common.ResendTypeDataSync
  2034  			rawMessage.SkipEncryptionLayer = false
  2035  			rawMessage.Sender = nil
  2036  		}
  2037  
  2038  		if community.Encrypted() {
  2039  			rawMessage.HashRatchetGroupID = community.ID()
  2040  			rawMessage.CommunityKeyExMsgType = common.KeyExMsgReuse
  2041  		}
  2042  
  2043  		_, err = m.sender.SendPrivate(context.Background(), pk, rawMessage)
  2044  		if err != nil {
  2045  			return nil, err
  2046  		}
  2047  
  2048  		if rawMessage.ResendType == common.ResendTypeRawMessage {
  2049  			if _, err = m.AddRawMessageToWatch(rawMessage); err != nil {
  2050  				return nil, err
  2051  			}
  2052  		}
  2053  	}
  2054  
  2055  	response := &MessengerResponse{}
  2056  	response.AddCommunity(community)
  2057  	response.AddRequestToJoinCommunity(requestToJoin)
  2058  
  2059  	// Update existing notification
  2060  	notification, err := m.persistence.GetActivityCenterNotificationByID(requestToJoin.ID)
  2061  	if err != nil {
  2062  		return nil, err
  2063  	}
  2064  	if notification != nil {
  2065  		notification.MembershipStatus = ActivityCenterMembershipStatusAccepted
  2066  		if community.HasPermissionToSendCommunityEvents() {
  2067  			notification.MembershipStatus = ActivityCenterMembershipStatusAcceptedPending
  2068  		}
  2069  		notification.Read = true
  2070  		notification.Accepted = true
  2071  		notification.IncrementUpdatedAt(m.getTimesource())
  2072  
  2073  		err = m.addActivityCenterNotification(response, notification, m.syncActivityCenterCommunityRequestDecisionAdapter)
  2074  		if err != nil {
  2075  			m.logger.Error("failed to save notification", zap.Error(err))
  2076  			return nil, err
  2077  		}
  2078  	}
  2079  
  2080  	return response, nil
  2081  }
  2082  
  2083  func (m *Messenger) AcceptRequestToJoinCommunity(request *requests.AcceptRequestToJoinCommunity) (*MessengerResponse, error) {
  2084  	if err := request.Validate(); err != nil {
  2085  		return nil, err
  2086  	}
  2087  
  2088  	requestToJoin, err := m.communitiesManager.GetRequestToJoin(request.ID)
  2089  	if err != nil {
  2090  		return nil, err
  2091  	}
  2092  
  2093  	return m.acceptRequestToJoinCommunity(requestToJoin)
  2094  }
  2095  
  2096  func (m *Messenger) declineRequestToJoinCommunity(requestToJoin *communities.RequestToJoin) (*MessengerResponse, error) {
  2097  	community, err := m.communitiesManager.DeclineRequestToJoin(requestToJoin)
  2098  	if err != nil {
  2099  		return nil, err
  2100  	}
  2101  
  2102  	if community.IsControlNode() {
  2103  		// Notify privileged members that request to join was rejected
  2104  		// Send request to join without revealed addresses
  2105  		requestToJoin.RevealedAccounts = make([]*protobuf.RevealedAccount, 0)
  2106  		declinedRequestsToJoin := make(map[string]*protobuf.CommunityRequestToJoin)
  2107  		declinedRequestsToJoin[requestToJoin.PublicKey] = requestToJoin.ToCommunityRequestToJoinProtobuf()
  2108  
  2109  		syncMsg := &protobuf.CommunityPrivilegedUserSyncMessage{
  2110  			Type:          protobuf.CommunityPrivilegedUserSyncMessage_CONTROL_NODE_REJECT_REQUEST_TO_JOIN,
  2111  			CommunityId:   community.ID(),
  2112  			RequestToJoin: declinedRequestsToJoin,
  2113  		}
  2114  
  2115  		payloadSyncMsg, err := proto.Marshal(syncMsg)
  2116  		if err != nil {
  2117  			return nil, err
  2118  		}
  2119  
  2120  		rawSyncMessage := &common.RawMessage{
  2121  			Payload:             payloadSyncMsg,
  2122  			Sender:              community.PrivateKey(),
  2123  			SkipEncryptionLayer: true,
  2124  			MessageType:         protobuf.ApplicationMetadataMessage_COMMUNITY_PRIVILEGED_USER_SYNC_MESSAGE,
  2125  		}
  2126  
  2127  		privilegedMembers := community.GetPrivilegedMembers()
  2128  		for _, privilegedMember := range privilegedMembers {
  2129  			if privilegedMember.Equal(&m.identity.PublicKey) {
  2130  				continue
  2131  			}
  2132  			_, err := m.sender.SendPrivate(context.Background(), privilegedMember, rawSyncMessage)
  2133  			if err != nil {
  2134  				return nil, err
  2135  			}
  2136  		}
  2137  	}
  2138  
  2139  	response := &MessengerResponse{}
  2140  	response.AddCommunity(community)
  2141  	response.AddRequestToJoinCommunity(requestToJoin)
  2142  
  2143  	// Update existing notification
  2144  	notification, err := m.persistence.GetActivityCenterNotificationByID(requestToJoin.ID)
  2145  	if err != nil {
  2146  		return nil, err
  2147  	}
  2148  	if notification != nil {
  2149  		notification.MembershipStatus = ActivityCenterMembershipStatusDeclined
  2150  		if community.HasPermissionToSendCommunityEvents() {
  2151  			notification.MembershipStatus = ActivityCenterMembershipStatusDeclinedPending
  2152  		}
  2153  		notification.Read = true
  2154  		notification.Dismissed = true
  2155  		notification.IncrementUpdatedAt(m.getTimesource())
  2156  
  2157  		err = m.addActivityCenterNotification(response, notification, m.syncActivityCenterCommunityRequestDecisionAdapter)
  2158  		if err != nil {
  2159  			m.logger.Error("failed to save notification", zap.Error(err))
  2160  			return nil, err
  2161  		}
  2162  	}
  2163  
  2164  	return response, nil
  2165  }
  2166  
  2167  func (m *Messenger) DeclineRequestToJoinCommunity(request *requests.DeclineRequestToJoinCommunity) (*MessengerResponse, error) {
  2168  	if err := request.Validate(); err != nil {
  2169  		return nil, err
  2170  	}
  2171  
  2172  	requestToJoin, err := m.communitiesManager.GetRequestToJoin(request.ID)
  2173  	if err != nil {
  2174  		return nil, err
  2175  	}
  2176  
  2177  	return m.declineRequestToJoinCommunity(requestToJoin)
  2178  }
  2179  
  2180  func (m *Messenger) LeaveCommunity(communityID types.HexBytes) (*MessengerResponse, error) {
  2181  	_, err := m.persistence.DismissAllActivityCenterNotificationsFromCommunity(communityID.String(), m.GetCurrentTimeInMillis())
  2182  	if err != nil {
  2183  		return nil, err
  2184  	}
  2185  
  2186  	mr, err := m.leaveCommunity(communityID)
  2187  	if err != nil {
  2188  		return nil, err
  2189  	}
  2190  
  2191  	community, ok := mr.communities[communityID.String()]
  2192  	if !ok {
  2193  		return nil, communities.ErrOrgNotFound
  2194  	}
  2195  
  2196  	err = m.communitiesManager.DeleteCommunitySettings(communityID)
  2197  	if err != nil {
  2198  		return nil, err
  2199  	}
  2200  
  2201  	m.archiveManager.StopHistoryArchiveTasksInterval(communityID)
  2202  
  2203  	err = m.syncCommunity(context.Background(), community, m.dispatchMessage)
  2204  	if err != nil {
  2205  		return nil, err
  2206  	}
  2207  
  2208  	if !community.IsControlNode() {
  2209  		requestToLeaveProto := &protobuf.CommunityRequestToLeave{
  2210  			Clock:       uint64(time.Now().Unix()),
  2211  			CommunityId: communityID,
  2212  		}
  2213  
  2214  		payload, err := proto.Marshal(requestToLeaveProto)
  2215  		if err != nil {
  2216  			return nil, err
  2217  		}
  2218  
  2219  		community, err := m.communitiesManager.GetByID(communityID)
  2220  		if err != nil {
  2221  			return nil, err
  2222  		}
  2223  
  2224  		rawMessage := common.RawMessage{
  2225  			Payload:             payload,
  2226  			CommunityID:         communityID,
  2227  			SkipEncryptionLayer: true,
  2228  			MessageType:         protobuf.ApplicationMetadataMessage_COMMUNITY_REQUEST_TO_LEAVE,
  2229  			PubsubTopic:         community.PubsubTopic(), // TODO: confirm if it should be sent in the community pubsub topic
  2230  			ResendType:          common.ResendTypeRawMessage,
  2231  			Priority:            &common.HighPriority,
  2232  		}
  2233  
  2234  		_, err = m.SendMessageToControlNode(community, &rawMessage)
  2235  		if err != nil {
  2236  			return nil, err
  2237  		}
  2238  
  2239  		if _, err = m.AddRawMessageToWatch(&rawMessage); err != nil {
  2240  			return nil, err
  2241  		}
  2242  	}
  2243  
  2244  	return mr, nil
  2245  }
  2246  
  2247  func (m *Messenger) leaveCommunity(communityID types.HexBytes) (*MessengerResponse, error) {
  2248  	response := &MessengerResponse{}
  2249  
  2250  	community, err := m.communitiesManager.LeaveCommunity(communityID)
  2251  	if err != nil {
  2252  		return nil, err
  2253  	}
  2254  
  2255  	// Make chat inactive
  2256  	for chatID := range community.Chats() {
  2257  		communityChatID := communityID.String() + chatID
  2258  		response.AddRemovedChat(communityChatID)
  2259  
  2260  		_, err = m.deactivateChat(communityChatID, 0, false, false)
  2261  		if err != nil {
  2262  			return nil, err
  2263  		}
  2264  		_, err = m.transport.RemoveFilterByChatID(communityChatID)
  2265  		if err != nil {
  2266  			return nil, err
  2267  		}
  2268  	}
  2269  
  2270  	err = m.DeleteProfileShowcaseCommunity(community)
  2271  	if err != nil {
  2272  		return nil, err
  2273  	}
  2274  
  2275  	_, err = m.transport.RemoveFilterByChatID(communityID.String())
  2276  	if err != nil {
  2277  		return nil, err
  2278  	}
  2279  
  2280  	response.AddCommunity(community)
  2281  	return response, nil
  2282  }
  2283  
  2284  func (m *Messenger) kickedOutOfCommunity(communityID types.HexBytes, spectateMode bool) (*MessengerResponse, error) {
  2285  	response := &MessengerResponse{}
  2286  
  2287  	community, err := m.communitiesManager.KickedOutOfCommunity(communityID, spectateMode)
  2288  	if err != nil {
  2289  		return nil, err
  2290  	}
  2291  
  2292  	if !spectateMode {
  2293  		err = m.DeleteProfileShowcaseCommunity(community)
  2294  		if err != nil {
  2295  			return nil, err
  2296  		}
  2297  	}
  2298  
  2299  	response.AddCommunity(community)
  2300  	return response, nil
  2301  }
  2302  
  2303  func (m *Messenger) CheckAndDeletePendingRequestToJoinCommunity(ctx context.Context, sendResponse bool) (*MessengerResponse, error) {
  2304  	sendSignal := false
  2305  
  2306  	pendingRequestsToJoin, err := m.communitiesManager.PendingRequestsToJoin()
  2307  	if err != nil {
  2308  		m.logger.Error("failed to fetch pending request to join", zap.Error(err))
  2309  		return nil, err
  2310  	}
  2311  
  2312  	if len(pendingRequestsToJoin) == 0 {
  2313  		return nil, nil
  2314  	}
  2315  
  2316  	response := &MessengerResponse{}
  2317  	timeNow := uint64(time.Now().Unix())
  2318  
  2319  	for _, requestToJoin := range pendingRequestsToJoin {
  2320  		requestTimeOutClock, err := communities.AddTimeoutToRequestToJoinClock(requestToJoin.Clock)
  2321  		if err != nil {
  2322  			return nil, err
  2323  		}
  2324  
  2325  		if timeNow >= requestTimeOutClock {
  2326  			err := m.communitiesManager.DeletePendingRequestToJoin(requestToJoin)
  2327  			if err != nil {
  2328  				m.logger.Error("failed to delete pending request to join", zap.String("req-id", requestToJoin.ID.String()), zap.Error(err))
  2329  				return nil, err
  2330  			}
  2331  
  2332  			requestToJoin.Deleted = true
  2333  			response.AddRequestToJoinCommunity(requestToJoin)
  2334  
  2335  			notification, err := m.persistence.GetActivityCenterNotificationByID(requestToJoin.ID)
  2336  			if err != nil {
  2337  				m.logger.Error("failed to fetch pending request to join", zap.Error(err))
  2338  				return nil, err
  2339  			}
  2340  
  2341  			if notification != nil {
  2342  				// Delete activity centre notification for community admin
  2343  				if notification.Type == ActivityCenterNotificationTypeCommunityMembershipRequest {
  2344  					response2, err := m.MarkActivityCenterNotificationsDeleted(ctx, []types.HexBytes{notification.ID}, m.GetCurrentTimeInMillis(), true)
  2345  					if err != nil {
  2346  						m.logger.Error("[CheckAndDeletePendingRequestToJoinCommunity] failed to mark notification as deleted", zap.Error(err))
  2347  						return nil, err
  2348  					}
  2349  					response.AddActivityCenterNotifications(response2.ActivityCenterNotifications())
  2350  					response.SetActivityCenterState(response2.ActivityCenterState())
  2351  				}
  2352  				// Update activity centre notification for requester
  2353  				if notification.Type == ActivityCenterNotificationTypeCommunityRequest {
  2354  					notification.MembershipStatus = ActivityCenterMembershipStatusIdle
  2355  					notification.Read = false
  2356  					notification.Deleted = false
  2357  					notification.IncrementUpdatedAt(m.getTimesource())
  2358  					err = m.addActivityCenterNotification(response, notification, m.syncActivityCenterUnreadByIDs)
  2359  					if err != nil {
  2360  						m.logger.Error("failed to update notification in activity center", zap.Error(err))
  2361  						return nil, err
  2362  					}
  2363  				}
  2364  			}
  2365  
  2366  			sendSignal = true
  2367  		}
  2368  	}
  2369  
  2370  	if sendSignal && !sendResponse {
  2371  		signal.SendNewMessages(response)
  2372  	}
  2373  
  2374  	if sendResponse {
  2375  		return response, nil
  2376  	}
  2377  
  2378  	return nil, nil
  2379  }
  2380  
  2381  func (m *Messenger) CreateCommunityChat(communityID types.HexBytes, c *protobuf.CommunityChat) (*MessengerResponse, error) {
  2382  	var response MessengerResponse
  2383  
  2384  	c.Identity.FirstMessageTimestamp = FirstMessageTimestampNoMessage
  2385  	changes, err := m.communitiesManager.CreateChat(communityID, c, true, "")
  2386  	if err != nil {
  2387  		return nil, err
  2388  	}
  2389  	response.AddCommunity(changes.Community)
  2390  	response.CommunityChanges = []*communities.CommunityChanges{changes}
  2391  
  2392  	var chats []*Chat
  2393  	var publicFiltersToInit []transport.FiltersToInitialize
  2394  	for chatID, chat := range changes.ChatsAdded {
  2395  		c := CreateCommunityChat(changes.Community.IDString(), chatID, chat, m.getTimesource())
  2396  		chats = append(chats, c)
  2397  		publicFiltersToInit = append(publicFiltersToInit, transport.FiltersToInitialize{ChatID: c.ID, PubsubTopic: changes.Community.PubsubTopic()})
  2398  
  2399  		response.AddChat(c)
  2400  	}
  2401  
  2402  	// Load filters
  2403  	filters, err := m.transport.InitPublicFilters(publicFiltersToInit)
  2404  	if err != nil {
  2405  		return nil, err
  2406  	}
  2407  	_, err = m.scheduleSyncFilters(filters)
  2408  	if err != nil {
  2409  		return nil, err
  2410  	}
  2411  
  2412  	err = m.saveChats(chats)
  2413  	if err != nil {
  2414  		return nil, err
  2415  	}
  2416  
  2417  	err = m.reregisterForPushNotifications()
  2418  	if err != nil {
  2419  		return nil, err
  2420  	}
  2421  
  2422  	return &response, nil
  2423  }
  2424  
  2425  func (m *Messenger) EditCommunityChat(communityID types.HexBytes, chatID string, c *protobuf.CommunityChat) (*MessengerResponse, error) {
  2426  	var response MessengerResponse
  2427  	community, changes, err := m.communitiesManager.EditChat(communityID, chatID, c)
  2428  	if err != nil {
  2429  		return nil, err
  2430  	}
  2431  	response.AddCommunity(community)
  2432  	response.CommunityChanges = []*communities.CommunityChanges{changes}
  2433  
  2434  	var chats []*Chat
  2435  	var publicFiltersToInit []transport.FiltersToInitialize
  2436  	for chatID, change := range changes.ChatsModified {
  2437  		c := CreateCommunityChat(community.IDString(), chatID, change.ChatModified, m.getTimesource())
  2438  		chats = append(chats, c)
  2439  		publicFiltersToInit = append(publicFiltersToInit, transport.FiltersToInitialize{ChatID: c.ID, PubsubTopic: community.PubsubTopic()})
  2440  		response.AddChat(c)
  2441  	}
  2442  
  2443  	// Load filters
  2444  	filters, err := m.transport.InitPublicFilters(publicFiltersToInit)
  2445  	if err != nil {
  2446  		return nil, err
  2447  	}
  2448  	_, err = m.scheduleSyncFilters(filters)
  2449  	if err != nil {
  2450  		return nil, err
  2451  	}
  2452  
  2453  	return &response, m.saveChats(chats)
  2454  }
  2455  
  2456  func (m *Messenger) DeleteCommunityChat(communityID types.HexBytes, chatID string) (*MessengerResponse, error) {
  2457  	response := &MessengerResponse{}
  2458  
  2459  	community, _, err := m.communitiesManager.DeleteChat(communityID, chatID)
  2460  	if err != nil {
  2461  		return nil, err
  2462  	}
  2463  	err = m.deleteChat(chatID)
  2464  	if err != nil {
  2465  		return nil, err
  2466  	}
  2467  	response.AddRemovedChat(chatID)
  2468  
  2469  	_, err = m.transport.RemoveFilterByChatID(chatID)
  2470  	if err != nil {
  2471  		return nil, err
  2472  	}
  2473  
  2474  	response.AddCommunity(community)
  2475  	return response, nil
  2476  }
  2477  
  2478  func (m *Messenger) InitCommunityFilters(communityFiltersToInitialize []transport.CommunityFilterToInitialize) ([]*transport.Filter, error) {
  2479  	return m.transport.InitCommunityFilters(communityFiltersToInitialize)
  2480  }
  2481  
  2482  func (m *Messenger) DefaultFilters(o *communities.Community) []transport.FiltersToInitialize {
  2483  	cID := o.IDString()
  2484  	uncompressedPubKey := common.PubkeyToHex(o.PublicKey())[2:]
  2485  	updatesChannelID := o.StatusUpdatesChannelID()
  2486  	mlChannelID := o.MagnetlinkMessageChannelID()
  2487  	memberUpdateChannelID := o.MemberUpdateChannelID()
  2488  
  2489  	communityPubsubTopic := o.PubsubTopic()
  2490  
  2491  	filters := []transport.FiltersToInitialize{
  2492  		{ChatID: cID, PubsubTopic: communityPubsubTopic},
  2493  		{ChatID: updatesChannelID, PubsubTopic: communityPubsubTopic},
  2494  		{ChatID: mlChannelID, PubsubTopic: communityPubsubTopic},
  2495  		{ChatID: memberUpdateChannelID, PubsubTopic: communityPubsubTopic},
  2496  		{ChatID: uncompressedPubKey, PubsubTopic: shard.DefaultNonProtectedPubsubTopic()},
  2497  	}
  2498  
  2499  	return filters
  2500  }
  2501  
  2502  func (m *Messenger) CreateCommunity(request *requests.CreateCommunity, createDefaultChannel bool) (*MessengerResponse, error) {
  2503  	if err := request.Validate(); err != nil {
  2504  		return nil, err
  2505  	}
  2506  
  2507  	response := &MessengerResponse{}
  2508  
  2509  	community, err := m.communitiesManager.CreateCommunity(request, true)
  2510  	if err != nil {
  2511  		return nil, err
  2512  	}
  2513  
  2514  	communitySettings := communities.CommunitySettings{
  2515  		CommunityID:                  community.IDString(),
  2516  		HistoryArchiveSupportEnabled: request.HistoryArchiveSupportEnabled,
  2517  	}
  2518  	err = m.communitiesManager.SaveCommunitySettings(communitySettings)
  2519  	if err != nil {
  2520  		return nil, err
  2521  	}
  2522  
  2523  	if err = m.subscribeToCommunityShard(community.ID(), community.Shard()); err != nil {
  2524  		return nil, err
  2525  	}
  2526  
  2527  	// Init the community filter so we can receive messages on the community
  2528  	_, err = m.InitCommunityFilters([]transport.CommunityFilterToInitialize{{
  2529  		Shard:   community.Shard(),
  2530  		PrivKey: community.PrivateKey(),
  2531  	}})
  2532  	if err != nil {
  2533  		return nil, err
  2534  	}
  2535  
  2536  	// Init the default community filters
  2537  	_, err = m.transport.InitPublicFilters(m.DefaultFilters(community))
  2538  	if err != nil {
  2539  		return nil, err
  2540  	}
  2541  
  2542  	if createDefaultChannel {
  2543  		chatResponse, err := m.CreateCommunityChat(community.ID(), &protobuf.CommunityChat{
  2544  			Identity: &protobuf.ChatIdentity{
  2545  				DisplayName:           "general",
  2546  				Description:           "General channel for the community",
  2547  				Color:                 community.Description().Identity.Color,
  2548  				FirstMessageTimestamp: FirstMessageTimestampNoMessage,
  2549  			},
  2550  			Permissions: &protobuf.CommunityPermissions{
  2551  				Access: protobuf.CommunityPermissions_AUTO_ACCEPT,
  2552  			},
  2553  		})
  2554  		if err != nil {
  2555  			return nil, err
  2556  		}
  2557  
  2558  		// updating community so it contains the general chat
  2559  		community = chatResponse.Communities()[0]
  2560  		response.AddChat(chatResponse.Chats()[0])
  2561  	}
  2562  
  2563  	response.AddCommunity(community)
  2564  	response.AddCommunitySettings(&communitySettings)
  2565  	err = m.syncCommunity(context.Background(), community, m.dispatchMessage)
  2566  	if err != nil {
  2567  		return nil, err
  2568  	}
  2569  
  2570  	if m.config.torrentConfig != nil && m.config.torrentConfig.Enabled && communitySettings.HistoryArchiveSupportEnabled {
  2571  		go m.archiveManager.StartHistoryArchiveTasksInterval(community, messageArchiveInterval)
  2572  	}
  2573  
  2574  	return response, nil
  2575  }
  2576  
  2577  func (m *Messenger) SetCommunityShard(request *requests.SetCommunityShard) (*MessengerResponse, error) {
  2578  	if err := request.Validate(); err != nil {
  2579  		return nil, err
  2580  	}
  2581  
  2582  	community, err := m.communitiesManager.GetByID(request.CommunityID)
  2583  	if err != nil {
  2584  		return nil, err
  2585  	}
  2586  
  2587  	if !community.IsControlNode() {
  2588  		return nil, errors.New(ErrNotAdminOrOwner)
  2589  	}
  2590  
  2591  	// Reset the community private key
  2592  	community.SetPubsubTopicPrivateKey(nil)
  2593  
  2594  	// Removing the private key (if it exist)
  2595  	err = m.RemovePubsubTopicPrivateKey(community.PubsubTopic())
  2596  	if err != nil {
  2597  		return nil, err
  2598  	}
  2599  
  2600  	// Unsubscribing from existing shard
  2601  	if community.Shard() != nil {
  2602  		err := m.unsubscribeFromShard(community.Shard())
  2603  		if err != nil {
  2604  			return nil, err
  2605  		}
  2606  	}
  2607  
  2608  	community, err = m.communitiesManager.SetShard(request.CommunityID, request.Shard)
  2609  	if err != nil {
  2610  		return nil, err
  2611  	}
  2612  
  2613  	if request.Shard != nil {
  2614  		var topicPrivKey *ecdsa.PrivateKey
  2615  		if request.PrivateKey != nil {
  2616  			topicPrivKey, err = crypto.ToECDSA(*request.PrivateKey)
  2617  		} else {
  2618  			topicPrivKey, err = crypto.GenerateKey()
  2619  		}
  2620  		if err != nil {
  2621  			return nil, err
  2622  		}
  2623  
  2624  		community.SetPubsubTopicPrivateKey(topicPrivKey)
  2625  
  2626  		err = m.communitiesManager.UpdatePubsubTopicPrivateKey(community.PubsubTopic(), topicPrivKey)
  2627  		if err != nil {
  2628  			return nil, err
  2629  		}
  2630  	}
  2631  
  2632  	// TODO: Check
  2633  	err = m.UpdateCommunityFilters(community)
  2634  	if err != nil {
  2635  		return nil, err
  2636  	}
  2637  
  2638  	err = m.SendCommunityShardKey(community, community.GetMemberPubkeys())
  2639  	if err != nil {
  2640  		return nil, err
  2641  	}
  2642  
  2643  	err = m.sendPublicCommunityShardInfo(community)
  2644  	if err != nil {
  2645  		return nil, err
  2646  	}
  2647  
  2648  	response := &MessengerResponse{}
  2649  	response.AddCommunity(community)
  2650  
  2651  	return response, nil
  2652  }
  2653  
  2654  func (m *Messenger) RemovePubsubTopicPrivateKey(topic string) error {
  2655  	return m.transport.RemovePubsubTopicKey(topic)
  2656  }
  2657  
  2658  func (m *Messenger) SetCommunityStorenodes(request *requests.SetCommunityStorenodes) (*MessengerResponse, error) {
  2659  	if err := request.Validate(); err != nil {
  2660  		return nil, err
  2661  	}
  2662  	community, err := m.communitiesManager.GetByID(request.CommunityID)
  2663  	if err != nil {
  2664  		return nil, err
  2665  	}
  2666  	if !community.IsControlNode() {
  2667  		return nil, errors.New(ErrNotAdminOrOwner)
  2668  	}
  2669  
  2670  	if err := m.communityStorenodes.UpdateStorenodesInDB(request.CommunityID, request.Storenodes, 0); err != nil {
  2671  		return nil, err
  2672  	}
  2673  	err = m.sendCommunityPublicStorenodesInfo(community, request.Storenodes)
  2674  	if err != nil {
  2675  		return nil, err
  2676  	}
  2677  	response := &MessengerResponse{
  2678  		CommunityStorenodes: request.Storenodes,
  2679  	}
  2680  	return response, nil
  2681  }
  2682  
  2683  func (m *Messenger) GetCommunityStorenodes(communityID types.HexBytes) (*MessengerResponse, error) {
  2684  	community, err := m.communitiesManager.GetByID(communityID)
  2685  	if err != nil {
  2686  		return nil, err
  2687  	}
  2688  	if community == nil {
  2689  		return nil, communities.ErrOrgNotFound
  2690  	}
  2691  
  2692  	snodes, err := m.communityStorenodes.GetStorenodesFromDB(communityID)
  2693  	if err != nil {
  2694  		return nil, err
  2695  	}
  2696  
  2697  	response := &MessengerResponse{
  2698  		CommunityStorenodes: snodes,
  2699  	}
  2700  	return response, nil
  2701  }
  2702  
  2703  func (m *Messenger) UpdateCommunityFilters(community *communities.Community) error {
  2704  	defaultFilters := m.DefaultFilters(community)
  2705  	publicFiltersToInit := make([]transport.FiltersToInitialize, 0, len(defaultFilters)+len(community.Chats()))
  2706  
  2707  	publicFiltersToInit = append(publicFiltersToInit, defaultFilters...)
  2708  
  2709  	for chatID := range community.Chats() {
  2710  		communityChatID := community.IDString() + chatID
  2711  		_, err := m.transport.RemoveFilterByChatID(communityChatID)
  2712  		if err != nil {
  2713  			return err
  2714  		}
  2715  		publicFiltersToInit = append(publicFiltersToInit, transport.FiltersToInitialize{ChatID: communityChatID, PubsubTopic: community.PubsubTopic()})
  2716  	}
  2717  
  2718  	_, err := m.transport.InitPublicFilters(publicFiltersToInit)
  2719  	if err != nil {
  2720  		return err
  2721  	}
  2722  
  2723  	// Init the community filter so we can receive messages on the community
  2724  	_, err = m.InitCommunityFilters([]transport.CommunityFilterToInitialize{{
  2725  		Shard:   community.Shard(),
  2726  		PrivKey: community.PrivateKey(),
  2727  	}})
  2728  	if err != nil {
  2729  		return err
  2730  	}
  2731  
  2732  	// Init the default community filters
  2733  	_, err = m.transport.InitPublicFilters(publicFiltersToInit)
  2734  	if err != nil {
  2735  		return err
  2736  	}
  2737  
  2738  	if err = m.subscribeToCommunityShard(community.ID(), community.Shard()); err != nil {
  2739  		return err
  2740  	}
  2741  
  2742  	return nil
  2743  }
  2744  
  2745  func (m *Messenger) CreateCommunityTokenPermission(request *requests.CreateCommunityTokenPermission) (*MessengerResponse, error) {
  2746  	request.FillDeprecatedAmount()
  2747  
  2748  	if err := request.Validate(); err != nil {
  2749  		return nil, err
  2750  	}
  2751  
  2752  	community, changes, err := m.communitiesManager.CreateCommunityTokenPermission(request)
  2753  	if err != nil {
  2754  		return nil, err
  2755  	}
  2756  
  2757  	if community.IsControlNode() {
  2758  		err = m.communitiesManager.ScheduleMembersReevaluation(community.ID())
  2759  		if err != nil {
  2760  			return nil, err
  2761  		}
  2762  	}
  2763  
  2764  	// ensure HRkeys are synced
  2765  	err = m.syncCommunity(context.Background(), community, m.dispatchMessage)
  2766  	if err != nil {
  2767  		return nil, err
  2768  	}
  2769  
  2770  	response := &MessengerResponse{}
  2771  	response.AddCommunity(community)
  2772  	response.CommunityChanges = []*communities.CommunityChanges{changes}
  2773  
  2774  	return response, nil
  2775  }
  2776  
  2777  func (m *Messenger) EditCommunityTokenPermission(request *requests.EditCommunityTokenPermission) (*MessengerResponse, error) {
  2778  	request.FillDeprecatedAmount()
  2779  
  2780  	if err := request.Validate(); err != nil {
  2781  		return nil, err
  2782  	}
  2783  
  2784  	community, changes, err := m.communitiesManager.EditCommunityTokenPermission(request)
  2785  	if err != nil {
  2786  		return nil, err
  2787  	}
  2788  
  2789  	// check if members still fulfill the token criteria of all
  2790  	// BECOME_MEMBER permissions and kick them if necessary
  2791  	//
  2792  	// We do this in a separate routine to not block this function
  2793  	if community.IsControlNode() {
  2794  		err = m.communitiesManager.ScheduleMembersReevaluation(community.ID())
  2795  		if err != nil {
  2796  			return nil, err
  2797  		}
  2798  	}
  2799  
  2800  	response := &MessengerResponse{}
  2801  	response.AddCommunity(community)
  2802  	response.CommunityChanges = []*communities.CommunityChanges{changes}
  2803  
  2804  	return response, nil
  2805  }
  2806  
  2807  func (m *Messenger) DeleteCommunityTokenPermission(request *requests.DeleteCommunityTokenPermission) (*MessengerResponse, error) {
  2808  	if err := request.Validate(); err != nil {
  2809  		return nil, err
  2810  	}
  2811  
  2812  	community, changes, err := m.communitiesManager.DeleteCommunityTokenPermission(request)
  2813  	if err != nil {
  2814  		return nil, err
  2815  	}
  2816  
  2817  	// check if members still fulfill the token criteria
  2818  	// We do this in a separate routine to not block this function
  2819  	if community.IsControlNode() {
  2820  		err = m.communitiesManager.ScheduleMembersReevaluation(community.ID())
  2821  		if err != nil {
  2822  			return nil, err
  2823  		}
  2824  	}
  2825  
  2826  	response := &MessengerResponse{}
  2827  	response.AddCommunity(community)
  2828  	response.CommunityChanges = []*communities.CommunityChanges{changes}
  2829  
  2830  	return response, nil
  2831  }
  2832  
  2833  func (m *Messenger) HandleCommunityReevaluatePermissionsRequest(state *ReceivedMessageState, request *protobuf.CommunityReevaluatePermissionsRequest, statusMessage *v1protocol.StatusMessage) error {
  2834  	community, err := m.communitiesManager.GetByID(request.CommunityId)
  2835  	if err != nil {
  2836  		return err
  2837  	}
  2838  
  2839  	if !community.IsControlNode() {
  2840  		return communities.ErrNotControlNode
  2841  	}
  2842  
  2843  	if !community.IsMemberTokenMaster(statusMessage.SigPubKey()) {
  2844  		return communities.ErrNotAuthorized
  2845  	}
  2846  
  2847  	return m.communitiesManager.ScheduleMembersReevaluation(request.CommunityId)
  2848  }
  2849  
  2850  func (m *Messenger) ReevaluateCommunityMembersPermissions(request *requests.ReevaluateCommunityMembersPermissions) (*MessengerResponse, error) {
  2851  	if err := request.Validate(); err != nil {
  2852  		return nil, err
  2853  	}
  2854  
  2855  	community, err := m.communitiesManager.GetByID(request.CommunityID)
  2856  	if err != nil {
  2857  		return nil, err
  2858  	}
  2859  
  2860  	if community.IsControlNode() {
  2861  		err = m.communitiesManager.ScheduleMembersReevaluation(request.CommunityID)
  2862  		if err != nil {
  2863  			return nil, err
  2864  		}
  2865  	} else if community.IsTokenMaster() {
  2866  		reevaluateRequest := &protobuf.CommunityReevaluatePermissionsRequest{
  2867  			CommunityId: request.CommunityID,
  2868  		}
  2869  
  2870  		encodedMessage, err := proto.Marshal(reevaluateRequest)
  2871  		if err != nil {
  2872  			return nil, err
  2873  		}
  2874  
  2875  		rawMessage := common.RawMessage{
  2876  			Payload:             encodedMessage,
  2877  			CommunityID:         request.CommunityID,
  2878  			SkipEncryptionLayer: true,
  2879  			MessageType:         protobuf.ApplicationMetadataMessage_COMMUNITY_REEVALUATE_PERMISSIONS_REQUEST,
  2880  			PubsubTopic:         community.PubsubTopic(),
  2881  		}
  2882  		_, err = m.SendMessageToControlNode(community, &rawMessage)
  2883  		if err != nil {
  2884  			return nil, err
  2885  		}
  2886  	} else {
  2887  		return nil, communities.ErrNotAuthorized
  2888  	}
  2889  
  2890  	return &MessengerResponse{}, nil
  2891  }
  2892  
  2893  func (m *Messenger) EditCommunity(request *requests.EditCommunity) (*MessengerResponse, error) {
  2894  	if err := request.Validate(); err != nil {
  2895  		return nil, err
  2896  	}
  2897  
  2898  	community, err := m.communitiesManager.EditCommunity(request)
  2899  	if err != nil {
  2900  		return nil, err
  2901  	}
  2902  
  2903  	communitySettings := communities.CommunitySettings{
  2904  		CommunityID:                  community.IDString(),
  2905  		HistoryArchiveSupportEnabled: request.HistoryArchiveSupportEnabled,
  2906  	}
  2907  	err = m.communitiesManager.UpdateCommunitySettings(communitySettings)
  2908  	if err != nil {
  2909  		return nil, err
  2910  	}
  2911  
  2912  	id := community.ID()
  2913  
  2914  	if m.archiveManager.IsReady() {
  2915  		if !communitySettings.HistoryArchiveSupportEnabled {
  2916  			m.archiveManager.StopHistoryArchiveTasksInterval(id)
  2917  		} else if !m.archiveManager.IsSeedingHistoryArchiveTorrent(id) {
  2918  			var communities []*communities.Community
  2919  			communities = append(communities, community)
  2920  			go m.InitHistoryArchiveTasks(communities)
  2921  		}
  2922  	}
  2923  
  2924  	response := &MessengerResponse{}
  2925  	response.AddCommunity(community)
  2926  	response.AddCommunitySettings(&communitySettings)
  2927  	err = m.SyncCommunitySettings(context.Background(), &communitySettings)
  2928  	if err != nil {
  2929  		return nil, err
  2930  	}
  2931  
  2932  	return response, nil
  2933  }
  2934  
  2935  func (m *Messenger) RemovePrivateKey(id types.HexBytes) (*MessengerResponse, error) {
  2936  	community, err := m.communitiesManager.RemovePrivateKey(id)
  2937  	if err != nil {
  2938  		return nil, err
  2939  	}
  2940  
  2941  	response := &MessengerResponse{}
  2942  	response.AddCommunity(community)
  2943  
  2944  	return response, nil
  2945  }
  2946  
  2947  func (m *Messenger) ExportCommunity(id types.HexBytes) (*ecdsa.PrivateKey, error) {
  2948  	return m.communitiesManager.ExportCommunity(id)
  2949  }
  2950  
  2951  func (m *Messenger) ImportCommunity(ctx context.Context, key *ecdsa.PrivateKey) (*MessengerResponse, error) {
  2952  	clock, _ := m.getLastClockWithRelatedChat()
  2953  
  2954  	community, err := m.communitiesManager.ImportCommunity(key, clock)
  2955  	if err != nil {
  2956  		return nil, err
  2957  	}
  2958  
  2959  	// Load filters
  2960  	_, err = m.transport.InitPublicFilters(m.DefaultFilters(community))
  2961  	if err != nil {
  2962  		return nil, err
  2963  	}
  2964  
  2965  	if err != nil {
  2966  		return nil, err
  2967  	}
  2968  
  2969  	_, err = m.FetchCommunity(&FetchCommunityRequest{
  2970  		CommunityKey:    community.IDString(),
  2971  		Shard:           community.Shard(),
  2972  		TryDatabase:     false,
  2973  		WaitForResponse: true,
  2974  	})
  2975  	if err != nil {
  2976  		// TODO In the future we should add a mechanism to re-apply next steps (adding owner, joining)
  2977  		// if there is no connection with mailserver. Otherwise changes will be overwritten.
  2978  		// Do not return error to make tests pass.
  2979  		m.logger.Error("Can't request community info from mailserver")
  2980  	}
  2981  
  2982  	// We add ourselves
  2983  	community, err = m.communitiesManager.AddMemberOwnerToCommunity(community.ID(), &m.identity.PublicKey)
  2984  	if err != nil {
  2985  		return nil, err
  2986  	}
  2987  
  2988  	response, err := m.JoinCommunity(ctx, community.ID(), true)
  2989  	if err != nil {
  2990  		return nil, err
  2991  	}
  2992  
  2993  	// Notify other clients we are the control node now
  2994  	err = m.syncCommunity(context.Background(), community, m.dispatchMessage)
  2995  	if err != nil {
  2996  		return nil, err
  2997  	}
  2998  
  2999  	if m.archiveManager.IsReady() {
  3000  		var communities []*communities.Community
  3001  		communities = append(communities, community)
  3002  		go m.InitHistoryArchiveTasks(communities)
  3003  	}
  3004  	return response, nil
  3005  }
  3006  
  3007  func (m *Messenger) GetCommunityByID(communityID types.HexBytes) (*communities.Community, error) {
  3008  	return m.communitiesManager.GetByID(communityID)
  3009  }
  3010  
  3011  func (m *Messenger) ShareCommunity(request *requests.ShareCommunity) (*MessengerResponse, error) {
  3012  	if err := request.Validate(); err != nil {
  3013  		return nil, err
  3014  	}
  3015  	community, err := m.GetCommunityByID(request.CommunityID)
  3016  	if err != nil {
  3017  		return nil, err
  3018  	}
  3019  
  3020  	response := &MessengerResponse{}
  3021  	communityURL, err := m.ShareCommunityURLWithData(request.CommunityID)
  3022  	if err != nil {
  3023  		return nil, err
  3024  	}
  3025  
  3026  	var statusLinkPreview common.StatusLinkPreview
  3027  	statusCommunityLinkPreview, err := community.ToStatusLinkPreview()
  3028  	if err != nil {
  3029  		return nil, err
  3030  	}
  3031  
  3032  	statusLinkPreview.URL = communityURL
  3033  	statusLinkPreview.Community = statusCommunityLinkPreview
  3034  	var messages []*common.Message
  3035  	for _, pk := range request.Users {
  3036  		message := common.NewMessage()
  3037  		message.StatusLinkPreviews = []common.StatusLinkPreview{statusLinkPreview}
  3038  		message.ChatId = pk.String()
  3039  		message.Shard = community.Shard().Protobuffer()
  3040  		message.ContentType = protobuf.ChatMessage_TEXT_PLAIN
  3041  		message.Text = communityURL
  3042  		if request.InviteMessage != "" {
  3043  			message.Text = fmt.Sprintf("%s\n%s", request.InviteMessage, communityURL)
  3044  		}
  3045  		messages = append(messages, message)
  3046  		r, err := m.CreateOneToOneChat(&requests.CreateOneToOneChat{ID: pk})
  3047  		if err != nil {
  3048  			return nil, err
  3049  		}
  3050  
  3051  		if err := response.Merge(r); err != nil {
  3052  			return nil, err
  3053  		}
  3054  	}
  3055  
  3056  	sendMessagesResponse, err := m.SendChatMessages(context.Background(), messages)
  3057  	if err != nil {
  3058  		return nil, err
  3059  	}
  3060  
  3061  	if err := response.Merge(sendMessagesResponse); err != nil {
  3062  		return nil, err
  3063  	}
  3064  
  3065  	return response, nil
  3066  }
  3067  
  3068  func (m *Messenger) MyCanceledRequestsToJoin() ([]*communities.RequestToJoin, error) {
  3069  	return m.communitiesManager.CanceledRequestsToJoinForUser(&m.identity.PublicKey)
  3070  }
  3071  
  3072  func (m *Messenger) MyPendingRequestsToJoin() ([]*communities.RequestToJoin, error) {
  3073  	return m.communitiesManager.PendingRequestsToJoinForUser(&m.identity.PublicKey)
  3074  }
  3075  
  3076  func (m *Messenger) LatestRequestToJoinForCommunity(communityID types.HexBytes) (*communities.RequestToJoin, error) {
  3077  	return m.communitiesManager.GetCommunityRequestToJoinWithRevealedAddresses(m.myHexIdentity(), communityID)
  3078  }
  3079  
  3080  func (m *Messenger) PendingRequestsToJoinForCommunity(id types.HexBytes) ([]*communities.RequestToJoin, error) {
  3081  	return m.communitiesManager.PendingRequestsToJoinForCommunity(id)
  3082  }
  3083  
  3084  func (m *Messenger) DeclinedRequestsToJoinForCommunity(id types.HexBytes) ([]*communities.RequestToJoin, error) {
  3085  	return m.communitiesManager.DeclinedRequestsToJoinForCommunity(id)
  3086  }
  3087  
  3088  func (m *Messenger) CanceledRequestsToJoinForCommunity(id types.HexBytes) ([]*communities.RequestToJoin, error) {
  3089  	return m.communitiesManager.CanceledRequestsToJoinForCommunity(id)
  3090  }
  3091  
  3092  func (m *Messenger) AcceptedRequestsToJoinForCommunity(id types.HexBytes) ([]*communities.RequestToJoin, error) {
  3093  	return m.communitiesManager.AcceptedRequestsToJoinForCommunity(id)
  3094  }
  3095  
  3096  func (m *Messenger) AcceptedPendingRequestsToJoinForCommunity(id types.HexBytes) ([]*communities.RequestToJoin, error) {
  3097  	return m.communitiesManager.AcceptedPendingRequestsToJoinForCommunity(id)
  3098  }
  3099  
  3100  func (m *Messenger) DeclinedPendingRequestsToJoinForCommunity(id types.HexBytes) ([]*communities.RequestToJoin, error) {
  3101  	return m.communitiesManager.DeclinedPendingRequestsToJoinForCommunity(id)
  3102  }
  3103  
  3104  func (m *Messenger) AllNonApprovedCommunitiesRequestsToJoin() ([]*communities.RequestToJoin, error) {
  3105  	return m.communitiesManager.AllNonApprovedCommunitiesRequestsToJoin()
  3106  }
  3107  
  3108  func (m *Messenger) RemoveUserFromCommunity(id types.HexBytes, pkString string) (*MessengerResponse, error) {
  3109  	publicKey, err := common.HexToPubkey(pkString)
  3110  	if err != nil {
  3111  		return nil, err
  3112  	}
  3113  
  3114  	community, err := m.communitiesManager.RemoveUserFromCommunity(id, publicKey)
  3115  	if err != nil {
  3116  		return nil, err
  3117  	}
  3118  
  3119  	response := &MessengerResponse{}
  3120  	response.AddCommunity(community)
  3121  	return response, nil
  3122  }
  3123  
  3124  func (m *Messenger) SendCommunityShardKey(community *communities.Community, pubkeys []*ecdsa.PublicKey) error {
  3125  	if m.transport.WakuVersion() != 2 {
  3126  		return nil
  3127  	}
  3128  
  3129  	if !community.IsControlNode() {
  3130  		return nil
  3131  	}
  3132  
  3133  	keyBytes := make([]byte, 0)
  3134  	key := community.PubsubTopicPrivateKey()
  3135  	if key != nil {
  3136  		keyBytes = crypto.FromECDSA(key)
  3137  	}
  3138  
  3139  	communityShardKey := &protobuf.CommunityShardKey{
  3140  		Clock:       community.Clock(),
  3141  		CommunityId: community.ID(),
  3142  		PrivateKey:  keyBytes,
  3143  		Shard:       community.Shard().Protobuffer(),
  3144  	}
  3145  
  3146  	encodedMessage, err := proto.Marshal(communityShardKey)
  3147  	if err != nil {
  3148  		return err
  3149  	}
  3150  
  3151  	rawMessage := common.RawMessage{
  3152  		Recipients:  pubkeys,
  3153  		ResendType:  common.ResendTypeDataSync,
  3154  		MessageType: protobuf.ApplicationMetadataMessage_COMMUNITY_SHARD_KEY,
  3155  		Payload:     encodedMessage,
  3156  	}
  3157  
  3158  	_, err = m.sender.SendPubsubTopicKey(context.Background(), &rawMessage)
  3159  
  3160  	return err
  3161  }
  3162  
  3163  func (m *Messenger) UnbanUserFromCommunity(request *requests.UnbanUserFromCommunity) (*MessengerResponse, error) {
  3164  	community, err := m.communitiesManager.UnbanUserFromCommunity(request)
  3165  	if err != nil {
  3166  		return nil, err
  3167  	}
  3168  
  3169  	response := &MessengerResponse{}
  3170  	response.AddCommunity(community)
  3171  	return response, nil
  3172  }
  3173  
  3174  func (m *Messenger) BanUserFromCommunity(ctx context.Context, request *requests.BanUserFromCommunity) (*MessengerResponse, error) {
  3175  	community, err := m.communitiesManager.BanUserFromCommunity(request)
  3176  	if err != nil {
  3177  		return nil, err
  3178  	}
  3179  
  3180  	response := &MessengerResponse{}
  3181  	response, err = m.DeclineAllPendingGroupInvitesFromUser(ctx, response, request.User.String())
  3182  	if err != nil {
  3183  		return nil, err
  3184  	}
  3185  
  3186  	response.AddCommunity(community)
  3187  
  3188  	if request.DeleteAllMessages && community.IsControlNode() {
  3189  		deleteMessagesResponse, err := m.deleteCommunityMemberMessages(request.User.String(), request.CommunityID.String(), []*protobuf.DeleteCommunityMemberMessage{})
  3190  		if err != nil {
  3191  			return nil, err
  3192  		}
  3193  
  3194  		err = response.Merge(deleteMessagesResponse)
  3195  		if err != nil {
  3196  			return nil, err
  3197  		}
  3198  
  3199  		// signal client with community and messages changes
  3200  		if m.config.messengerSignalsHandler != nil {
  3201  			m.config.messengerSignalsHandler.MessengerResponse(deleteMessagesResponse)
  3202  		}
  3203  	}
  3204  
  3205  	return response, nil
  3206  }
  3207  
  3208  func (m *Messenger) AddRoleToMember(request *requests.AddRoleToMember) (*MessengerResponse, error) {
  3209  	if err := request.Validate(); err != nil {
  3210  		return nil, err
  3211  	}
  3212  	community, err := m.communitiesManager.AddRoleToMember(request)
  3213  	if err != nil {
  3214  		return nil, err
  3215  	}
  3216  
  3217  	response := &MessengerResponse{}
  3218  	response.AddCommunity(community)
  3219  	return response, nil
  3220  }
  3221  
  3222  func (m *Messenger) RemoveRoleFromMember(request *requests.RemoveRoleFromMember) (*MessengerResponse, error) {
  3223  	if err := request.Validate(); err != nil {
  3224  		return nil, err
  3225  	}
  3226  	community, err := m.communitiesManager.RemoveRoleFromMember(request)
  3227  	if err != nil {
  3228  		return nil, err
  3229  	}
  3230  
  3231  	response := &MessengerResponse{}
  3232  	response.AddCommunity(community)
  3233  	return response, nil
  3234  }
  3235  
  3236  func (m *Messenger) FindCommunityInfoFromDB(communityID string) (*communities.Community, error) {
  3237  	id, err := hexutil.Decode(communityID)
  3238  	if err != nil {
  3239  		return nil, err
  3240  	}
  3241  
  3242  	var community *communities.Community
  3243  	community, err = m.GetCommunityByID(id)
  3244  	if err != nil {
  3245  		return nil, err
  3246  	}
  3247  	return community, nil
  3248  }
  3249  
  3250  // FetchCommunity installs filter for community and requests its details
  3251  // from mailserver.
  3252  //
  3253  // If `request.TryDatabase` is true, it first looks for community in database,
  3254  // and requests from mailserver only if it wasn't found locally.
  3255  // If `request.WaitForResponse` is true, it waits until it has the community before returning it.
  3256  // If `request.WaitForResponse` is false, it installs filter for community and requests its details
  3257  // from mailserver. When response received it will be passed through signals handler.
  3258  func (m *Messenger) FetchCommunity(request *FetchCommunityRequest) (*communities.Community, error) {
  3259  	if err := request.Validate(); err != nil {
  3260  		return nil, fmt.Errorf("invalid request: %w", err)
  3261  	}
  3262  	communityID := request.getCommunityID()
  3263  
  3264  	if request.TryDatabase {
  3265  		community, err := m.FindCommunityInfoFromDB(communityID)
  3266  		if err != nil && err != communities.ErrOrgNotFound {
  3267  			return nil, err
  3268  		}
  3269  		if community != nil {
  3270  			if !request.WaitForResponse {
  3271  				m.config.messengerSignalsHandler.CommunityInfoFound(community)
  3272  			}
  3273  			return community, nil
  3274  		}
  3275  	}
  3276  
  3277  	communityAddress := communities.CommunityShard{
  3278  		CommunityID: communityID,
  3279  		Shard:       request.Shard,
  3280  	}
  3281  
  3282  	options := []StoreNodeRequestOption{
  3283  		WithWaitForResponseOption(request.WaitForResponse),
  3284  	}
  3285  
  3286  	community, _, err := m.storeNodeRequestsManager.FetchCommunity(communityAddress, options)
  3287  
  3288  	return community, err
  3289  }
  3290  
  3291  // fetchCommunities installs filter for community and requests its details from store node.
  3292  // When response received it will be passed through signals handler.
  3293  func (m *Messenger) fetchCommunities(communities []communities.CommunityShard) error {
  3294  	return m.storeNodeRequestsManager.FetchCommunities(communities, []StoreNodeRequestOption{})
  3295  }
  3296  
  3297  // passStoredCommunityInfoToSignalHandler calls signal handler with community info
  3298  func (m *Messenger) passStoredCommunityInfoToSignalHandler(community *communities.Community) {
  3299  	if m.config.messengerSignalsHandler == nil {
  3300  		return
  3301  	}
  3302  	m.config.messengerSignalsHandler.CommunityInfoFound(community)
  3303  }
  3304  
  3305  // handleCommunityDescription handles an community description
  3306  func (m *Messenger) handleCommunityDescription(state *ReceivedMessageState, signer *ecdsa.PublicKey, description *protobuf.CommunityDescription, rawPayload []byte, verifiedOwner *ecdsa.PublicKey, shard *protobuf.Shard) error {
  3307  	communityResponse, err := m.communitiesManager.HandleCommunityDescriptionMessage(signer, description, rawPayload, verifiedOwner, shard)
  3308  	if err != nil {
  3309  		return err
  3310  	}
  3311  
  3312  	// If response is nil, but not error, it will be processed async
  3313  	if communityResponse == nil {
  3314  		return nil
  3315  	}
  3316  
  3317  	if len(communityResponse.FailedToDecrypt) != 0 {
  3318  		for _, r := range communityResponse.FailedToDecrypt {
  3319  			if state.CurrentMessageState != nil && state.CurrentMessageState.StatusMessage != nil {
  3320  				err := m.persistence.SaveHashRatchetMessage(r.GroupID, r.KeyID, state.CurrentMessageState.StatusMessage.TransportLayer.Message)
  3321  				m.logger.Info("saving failed to decrypt community description", zap.String("hash", types.Bytes2Hex(state.CurrentMessageState.StatusMessage.TransportLayer.Message.Hash)))
  3322  				if err != nil {
  3323  					m.logger.Warn("failed to save waku message")
  3324  				}
  3325  			}
  3326  
  3327  		}
  3328  		// We stop here if we could not decrypt the community main metadata
  3329  		if communityResponse.Community == nil {
  3330  			return nil
  3331  		}
  3332  	}
  3333  
  3334  	return m.handleCommunityResponse(state, communityResponse)
  3335  }
  3336  
  3337  func (m *Messenger) handleCommunityResponse(state *ReceivedMessageState, communityResponse *communities.CommunityResponse) error {
  3338  	community := communityResponse.Community
  3339  
  3340  	if len(communityResponse.Changes.MembersBanned) > 0 {
  3341  		for memberID, deleteAllMessages := range communityResponse.Changes.MembersBanned {
  3342  			if deleteAllMessages {
  3343  				response, err := m.deleteCommunityMemberMessages(memberID, community.IDString(), []*protobuf.DeleteCommunityMemberMessage{})
  3344  				if err != nil {
  3345  					return err
  3346  				}
  3347  
  3348  				if err = state.Response.Merge(response); err != nil {
  3349  					return err
  3350  				}
  3351  			}
  3352  		}
  3353  	}
  3354  
  3355  	state.Response.AddCommunity(community)
  3356  	state.Response.CommunityChanges = append(state.Response.CommunityChanges, communityResponse.Changes)
  3357  	state.Response.AddRequestsToJoinCommunity(communityResponse.RequestsToJoin)
  3358  
  3359  	// If we haven't joined/spectated the org, nothing to do
  3360  	if !community.Joined() && !community.Spectated() {
  3361  		return nil
  3362  	}
  3363  
  3364  	removedChatIDs := make([]string, 0)
  3365  	for id := range communityResponse.Changes.ChatsRemoved {
  3366  		chatID := community.ChatID(id)
  3367  		_, ok := state.AllChats.Load(chatID)
  3368  		if ok {
  3369  			removedChatIDs = append(removedChatIDs, chatID)
  3370  			state.AllChats.Delete(chatID)
  3371  			err := m.DeleteChat(chatID)
  3372  			if err != nil {
  3373  				m.logger.Error("couldn't delete chat", zap.Error(err))
  3374  			}
  3375  		}
  3376  	}
  3377  
  3378  	// Check if we have been removed from a chat (ie no longer have access)
  3379  	for channelID, changes := range communityResponse.Changes.ChatsModified {
  3380  		if _, ok := changes.MembersRemoved[common.PubkeyToHex(&m.identity.PublicKey)]; ok {
  3381  			chatID := community.ChatID(channelID)
  3382  
  3383  			if chat, ok := state.AllChats.Load(chatID); ok {
  3384  				// Reset the chat's message counts
  3385  				chat.UnviewedMessagesCount = 0
  3386  				chat.UnviewedMentionsCount = 0
  3387  				err := m.saveChat(chat)
  3388  				if err != nil {
  3389  					return err
  3390  				}
  3391  				state.Response.AddChat(chat)
  3392  			}
  3393  		}
  3394  	}
  3395  
  3396  	// Update relevant chats names and add new ones
  3397  	// Currently removal is not supported
  3398  	chats := CreateCommunityChats(community, state.Timesource)
  3399  	var publicFiltersToInit []transport.FiltersToInitialize
  3400  	for i, chat := range chats {
  3401  
  3402  		oldChat, ok := state.AllChats.Load(chat.ID)
  3403  		if !ok {
  3404  			// Beware, don't use the reference in the range (i.e chat) as it's a shallow copy
  3405  			state.AllChats.Store(chat.ID, chats[i])
  3406  
  3407  			state.Response.AddChat(chat)
  3408  			publicFiltersToInit = append(publicFiltersToInit, transport.FiltersToInitialize{
  3409  				ChatID:      chat.ID,
  3410  				PubsubTopic: community.PubsubTopic(),
  3411  			})
  3412  			// Update name, currently is the only field is mutable
  3413  		} else if oldChat.Name != chat.Name ||
  3414  			oldChat.Description != chat.Description ||
  3415  			oldChat.Emoji != chat.Emoji ||
  3416  			oldChat.Color != chat.Color ||
  3417  			oldChat.HideIfPermissionsNotMet != chat.HideIfPermissionsNotMet ||
  3418  			oldChat.UpdateFirstMessageTimestamp(chat.FirstMessageTimestamp) {
  3419  			oldChat.Name = chat.Name
  3420  			oldChat.Description = chat.Description
  3421  			oldChat.Emoji = chat.Emoji
  3422  			oldChat.Color = chat.Color
  3423  			oldChat.HideIfPermissionsNotMet = chat.HideIfPermissionsNotMet
  3424  			// TODO(samyoul) remove storing of an updated reference pointer?
  3425  			state.AllChats.Store(chat.ID, oldChat)
  3426  			state.Response.AddChat(chat)
  3427  		}
  3428  	}
  3429  
  3430  	for _, chatID := range removedChatIDs {
  3431  		_, err := m.transport.RemoveFilterByChatID(chatID)
  3432  		if err != nil {
  3433  			m.logger.Error("couldn't remove filter", zap.Error(err))
  3434  		}
  3435  	}
  3436  
  3437  	// Load transport filters
  3438  	filters, err := m.transport.InitPublicFilters(publicFiltersToInit)
  3439  	if err != nil {
  3440  		return err
  3441  	}
  3442  	_, err = m.scheduleSyncFilters(filters)
  3443  	if err != nil {
  3444  		return err
  3445  	}
  3446  
  3447  	for _, requestToJoin := range communityResponse.RequestsToJoin {
  3448  		// Activity Center notification
  3449  		notification, err := m.persistence.GetActivityCenterNotificationByID(requestToJoin.ID)
  3450  		if err != nil {
  3451  			return err
  3452  		}
  3453  
  3454  		if notification != nil {
  3455  			notification.MembershipStatus = ActivityCenterMembershipStatusAccepted
  3456  			switch requestToJoin.State {
  3457  			case communities.RequestToJoinStateDeclined:
  3458  				notification.MembershipStatus = ActivityCenterMembershipStatusDeclined
  3459  			case communities.RequestToJoinStateAccepted:
  3460  				notification.MembershipStatus = ActivityCenterMembershipStatusAccepted
  3461  			case communities.RequestToJoinStateAcceptedPending:
  3462  				notification.MembershipStatus = ActivityCenterMembershipStatusAcceptedPending
  3463  			case communities.RequestToJoinStateDeclinedPending:
  3464  				notification.MembershipStatus = ActivityCenterMembershipStatusDeclinedPending
  3465  			case communities.RequestToJoinStateAwaitingAddresses:
  3466  				notification.MembershipStatus = ActivityCenterMembershipOwnershipChanged
  3467  			default:
  3468  				notification.MembershipStatus = ActivityCenterMembershipStatusPending
  3469  
  3470  			}
  3471  
  3472  			notification.Read = true
  3473  			notification.Accepted = true
  3474  			notification.IncrementUpdatedAt(m.getTimesource())
  3475  
  3476  			err = m.addActivityCenterNotification(state.Response, notification, nil)
  3477  			if err != nil {
  3478  				m.logger.Error("failed to save notification", zap.Error(err))
  3479  				return err
  3480  			}
  3481  		}
  3482  	}
  3483  
  3484  	return nil
  3485  }
  3486  
  3487  func (m *Messenger) HandleCommunityUserKicked(state *ReceivedMessageState, message *protobuf.CommunityUserKicked, statusMessage *v1protocol.StatusMessage) error {
  3488  	// TODO: validate the user can be removed checking the signer
  3489  	if len(message.CommunityId) == 0 {
  3490  		return nil
  3491  	}
  3492  	community, err := m.communitiesManager.GetByID(message.CommunityId)
  3493  	if err != nil {
  3494  		return err
  3495  	}
  3496  	if community == nil || !community.Joined() {
  3497  		return nil
  3498  	}
  3499  	if community.Clock() > message.Clock {
  3500  		return nil
  3501  	}
  3502  
  3503  	response, err := m.kickedOutOfCommunity(community.ID(), false)
  3504  	if err != nil {
  3505  		m.logger.Error("cannot leave community", zap.Error(err))
  3506  		return err
  3507  	}
  3508  
  3509  	if err := state.Response.Merge(response); err != nil {
  3510  		m.logger.Error("cannot merge join community response", zap.Error(err))
  3511  		return err
  3512  	}
  3513  
  3514  	return nil
  3515  }
  3516  
  3517  func (m *Messenger) HandleCommunityEventsMessage(state *ReceivedMessageState, message *protobuf.CommunityEventsMessage, statusMessage *v1protocol.StatusMessage) error {
  3518  	signer := state.CurrentMessageState.PublicKey
  3519  	communityResponse, err := m.communitiesManager.HandleCommunityEventsMessage(signer, message)
  3520  	if err != nil {
  3521  		return err
  3522  	}
  3523  
  3524  	return m.handleCommunityResponse(state, communityResponse)
  3525  }
  3526  
  3527  // HandleCommunityShardKey handles the private keys for the community shards
  3528  func (m *Messenger) HandleCommunityShardKey(state *ReceivedMessageState, message *protobuf.CommunityShardKey, statusMessage *v1protocol.StatusMessage) error {
  3529  	community, err := m.communitiesManager.GetByID(message.CommunityId)
  3530  	if err != nil {
  3531  		return err
  3532  	}
  3533  
  3534  	// If we haven't joined the community, nothing to do
  3535  	if !community.Joined() {
  3536  		return nil
  3537  	}
  3538  
  3539  	signer := state.CurrentMessageState.PublicKey
  3540  	if signer == nil {
  3541  		return errors.New(ErrReceiverIsNil)
  3542  	}
  3543  
  3544  	err = m.handleCommunityShardAndFiltersFromProto(community, message)
  3545  	if err != nil {
  3546  		return err
  3547  	}
  3548  
  3549  	state.Response.AddCommunity(community)
  3550  
  3551  	return nil
  3552  }
  3553  
  3554  func (m *Messenger) handleCommunityShardAndFiltersFromProto(community *communities.Community, message *protobuf.CommunityShardKey) error {
  3555  	err := m.communitiesManager.UpdateShard(community, shard.FromProtobuff(message.Shard), message.Clock)
  3556  	if err != nil {
  3557  		return err
  3558  	}
  3559  
  3560  	var privKey *ecdsa.PrivateKey = nil
  3561  	if message.Shard != nil {
  3562  		if message.PrivateKey != nil {
  3563  			privKey, err = crypto.ToECDSA(message.PrivateKey)
  3564  			if err != nil {
  3565  				return err
  3566  			}
  3567  		}
  3568  	}
  3569  
  3570  	// Removing the existing private key (if any)
  3571  	err = m.RemovePubsubTopicPrivateKey(community.PubsubTopic())
  3572  	if err != nil {
  3573  		return err
  3574  	}
  3575  
  3576  	// Unsubscribing from existing shard
  3577  	if community.Shard() != nil && community.Shard() != shard.FromProtobuff(message.GetShard()) {
  3578  		err := m.unsubscribeFromShard(community.Shard())
  3579  		if err != nil {
  3580  			return err
  3581  		}
  3582  	}
  3583  
  3584  	community.SetPubsubTopicPrivateKey(privKey)
  3585  
  3586  	err = m.communitiesManager.UpdatePubsubTopicPrivateKey(community.PubsubTopic(), privKey)
  3587  	if err != nil {
  3588  		return err
  3589  	}
  3590  	// Update community filters in case of change of shard
  3591  	if community.Shard() != shard.FromProtobuff(message.GetShard()) {
  3592  		err = m.UpdateCommunityFilters(community)
  3593  		if err != nil {
  3594  			return err
  3595  		}
  3596  
  3597  	}
  3598  	return nil
  3599  }
  3600  
  3601  func (m *Messenger) handleCommunityPrivilegedUserSyncMessage(state *ReceivedMessageState, signer *ecdsa.PublicKey, message *protobuf.CommunityPrivilegedUserSyncMessage) error {
  3602  	if signer == nil {
  3603  		return errors.New(ErrSignerIsNil)
  3604  	}
  3605  
  3606  	community, err := m.communitiesManager.GetByID(message.CommunityId)
  3607  	if err != nil {
  3608  		return err
  3609  	}
  3610  
  3611  	if community.IsControlNode() {
  3612  		return nil
  3613  	}
  3614  
  3615  	// Currently this type of msg coming from the control node.
  3616  	// If it will change in the future, check that events types starting from
  3617  	// CONTROL_NODE were sent by a control node
  3618  	isControlNodeMsg := common.IsPubKeyEqual(community.ControlNode(), signer)
  3619  	if !isControlNodeMsg {
  3620  		return errors.New(ErrSyncMessagesSentByNonControlNode)
  3621  	}
  3622  
  3623  	err = m.communitiesManager.ValidateCommunityPrivilegedUserSyncMessage(message)
  3624  	if err != nil {
  3625  		return err
  3626  	}
  3627  
  3628  	switch message.Type {
  3629  	case protobuf.CommunityPrivilegedUserSyncMessage_CONTROL_NODE_ACCEPT_REQUEST_TO_JOIN:
  3630  		fallthrough
  3631  	case protobuf.CommunityPrivilegedUserSyncMessage_CONTROL_NODE_REJECT_REQUEST_TO_JOIN:
  3632  		requestsToJoin, err := m.communitiesManager.HandleRequestToJoinPrivilegedUserSyncMessage(message, community)
  3633  		if err != nil {
  3634  			return err
  3635  		}
  3636  		state.Response.AddRequestsToJoinCommunity(requestsToJoin)
  3637  
  3638  	case protobuf.CommunityPrivilegedUserSyncMessage_CONTROL_NODE_ALL_SYNC_REQUESTS_TO_JOIN:
  3639  		nonAcceptedRequestsToJoin, err := m.communitiesManager.HandleSyncAllRequestToJoinForNewPrivilegedMember(message, community)
  3640  		if err != nil {
  3641  			return err
  3642  		}
  3643  		state.Response.AddRequestsToJoinCommunity(nonAcceptedRequestsToJoin)
  3644  	case protobuf.CommunityPrivilegedUserSyncMessage_CONTROL_NODE_MEMBER_EDIT_SHARED_ADDRESSES:
  3645  		err = m.communitiesManager.HandleEditSharedAddressesPrivilegedUserSyncMessage(message, community)
  3646  		if err != nil {
  3647  			return err
  3648  		}
  3649  	}
  3650  
  3651  	return nil
  3652  }
  3653  
  3654  func (m *Messenger) HandleCommunityPrivilegedUserSyncMessage(state *ReceivedMessageState, message *protobuf.CommunityPrivilegedUserSyncMessage, statusMessage *v1protocol.StatusMessage) error {
  3655  	signer := state.CurrentMessageState.PublicKey
  3656  	return m.handleCommunityPrivilegedUserSyncMessage(state, signer, message)
  3657  }
  3658  
  3659  func (m *Messenger) sendSharedAddressToControlNode(receiver *ecdsa.PublicKey, community *communities.Community) (*communities.RequestToJoin, error) {
  3660  	if receiver == nil {
  3661  		return nil, errors.New(ErrReceiverIsNil)
  3662  	}
  3663  
  3664  	if community == nil {
  3665  		return nil, communities.ErrOrgNotFound
  3666  	}
  3667  
  3668  	m.logger.Info("share address to the new owner ", zap.String("community id", community.IDString()))
  3669  
  3670  	pk := common.PubkeyToHex(&m.identity.PublicKey)
  3671  
  3672  	requestToJoin, err := m.communitiesManager.GetCommunityRequestToJoinWithRevealedAddresses(pk, community.ID())
  3673  	if err != nil {
  3674  		if err == sql.ErrNoRows {
  3675  			return nil, communities.ErrRevealedAccountsAbsent
  3676  		}
  3677  		return nil, err
  3678  	}
  3679  
  3680  	if len(requestToJoin.RevealedAccounts) == 0 {
  3681  		return nil, communities.ErrRevealedAccountsAbsent
  3682  	}
  3683  
  3684  	// check if at least one account is signed
  3685  	// old community users can not keep locally the signature of their revealed accounts in the DB
  3686  	revealedAccountSigned := false
  3687  	for _, account := range requestToJoin.RevealedAccounts {
  3688  		revealedAccountSigned = len(account.Signature) > 0
  3689  		if revealedAccountSigned {
  3690  			break
  3691  		}
  3692  	}
  3693  
  3694  	if !revealedAccountSigned {
  3695  		return nil, communities.ErrNoRevealedAccountsSignature
  3696  	}
  3697  
  3698  	requestToJoin.Clock = uint64(time.Now().Unix())
  3699  	requestToJoin.State = communities.RequestToJoinStateAwaitingAddresses
  3700  	payload, err := proto.Marshal(requestToJoin.ToCommunityRequestToJoinProtobuf())
  3701  	if err != nil {
  3702  		return nil, err
  3703  	}
  3704  
  3705  	rawMessage := common.RawMessage{
  3706  		Payload:             payload,
  3707  		CommunityID:         community.ID(),
  3708  		SkipEncryptionLayer: false,
  3709  		MessageType:         protobuf.ApplicationMetadataMessage_COMMUNITY_REQUEST_TO_JOIN,
  3710  		PubsubTopic:         community.PubsubTopic(), // TODO: confirm if it should be sent in community pubsub topic
  3711  		ResendType:          common.ResendTypeDataSync,
  3712  		ResendMethod:        common.ResendMethodSendPrivate,
  3713  		Recipients:          []*ecdsa.PublicKey{receiver},
  3714  	}
  3715  
  3716  	if err = m.communitiesManager.SaveRequestToJoin(requestToJoin); err != nil {
  3717  		return nil, err
  3718  	}
  3719  
  3720  	_, err = m.sender.SendPrivate(context.Background(), receiver, &rawMessage)
  3721  	if err != nil {
  3722  		return nil, err
  3723  	}
  3724  
  3725  	return requestToJoin, err
  3726  }
  3727  
  3728  func (m *Messenger) HandleSyncInstallationCommunity(messageState *ReceivedMessageState, syncCommunity *protobuf.SyncInstallationCommunity, statusMessage *v1protocol.StatusMessage) error {
  3729  	return m.handleSyncInstallationCommunity(messageState, syncCommunity)
  3730  }
  3731  
  3732  func (m *Messenger) handleSyncInstallationCommunity(messageState *ReceivedMessageState, syncCommunity *protobuf.SyncInstallationCommunity) error {
  3733  	logger := m.logger.Named("handleSyncInstallationCommunity")
  3734  
  3735  	// Should handle community
  3736  	shouldHandle, err := m.communitiesManager.ShouldHandleSyncCommunity(syncCommunity)
  3737  	if err != nil {
  3738  		logger.Debug("m.communitiesManager.ShouldHandleSyncCommunity error", zap.Error(err))
  3739  		return err
  3740  	}
  3741  	logger.Debug("ShouldHandleSyncCommunity result", zap.Bool("shouldHandle", shouldHandle))
  3742  	if !shouldHandle {
  3743  		return nil
  3744  	}
  3745  
  3746  	// Handle deprecated community keys
  3747  	if len(syncCommunity.EncryptionKeysV1) != 0 {
  3748  		//  We pass nil,nil as private key/public key as they won't be encrypted
  3749  		_, err := m.encryptor.HandleHashRatchetKeysPayload(syncCommunity.Id, syncCommunity.EncryptionKeysV1, nil, nil)
  3750  		if err != nil {
  3751  			return err
  3752  		}
  3753  	}
  3754  
  3755  	// Handle community and channel keys
  3756  	if len(syncCommunity.EncryptionKeysV2) != 0 {
  3757  		err := m.encryptor.HandleHashRatchetHeadersPayload(syncCommunity.EncryptionKeysV2)
  3758  		if err != nil {
  3759  			return err
  3760  		}
  3761  	}
  3762  
  3763  	// Handle any community requests to join.
  3764  	// MUST BE HANDLED BEFORE DESCRIPTION!
  3765  	pending := false
  3766  	for _, rtj := range syncCommunity.RequestsToJoin {
  3767  		req := new(communities.RequestToJoin)
  3768  		req.InitFromSyncProtobuf(rtj)
  3769  
  3770  		if req.State == communities.RequestToJoinStatePending {
  3771  			pending = true
  3772  		}
  3773  
  3774  		err = m.communitiesManager.SaveRequestToJoin(req)
  3775  		if err != nil && err != communities.ErrOldRequestToJoin {
  3776  			logger.Debug("m.communitiesManager.SaveRequestToJoin error", zap.Error(err))
  3777  			return err
  3778  		}
  3779  	}
  3780  	logger.Debug("community requests to join pending state", zap.Bool("pending", pending))
  3781  
  3782  	// Don't use the public key of the private key, uncompress the community id
  3783  	orgPubKey, err := crypto.DecompressPubkey(syncCommunity.Id)
  3784  	if err != nil {
  3785  		logger.Debug("crypto.DecompressPubkey error", zap.Error(err))
  3786  		return err
  3787  	}
  3788  	logger.Debug("crypto.DecompressPubkey result", zap.Any("orgPubKey", orgPubKey))
  3789  
  3790  	var amm protobuf.ApplicationMetadataMessage
  3791  	err = proto.Unmarshal(syncCommunity.Description, &amm)
  3792  	if err != nil {
  3793  		logger.Debug("proto.Unmarshal protobuf.ApplicationMetadataMessage error", zap.Error(err))
  3794  		return err
  3795  	}
  3796  
  3797  	var cd protobuf.CommunityDescription
  3798  	err = proto.Unmarshal(amm.Payload, &cd)
  3799  	if err != nil {
  3800  		logger.Debug("proto.Unmarshal protobuf.CommunityDescription error", zap.Error(err))
  3801  		return err
  3802  	}
  3803  
  3804  	// This is our own message, so we can trust the set community owner
  3805  	// This is good to do so that we don't have to queue all the actions done after the handled community description.
  3806  	// `signer` is `communityID` for a community with no owner token and `owner public key` otherwise
  3807  	signer, err := utils.RecoverKey(&amm)
  3808  	if err != nil {
  3809  		logger.Debug("failed to recover community description signer", zap.Error(err))
  3810  		return err
  3811  	}
  3812  
  3813  	// Passing shard as nil so that defaultProtected shard 32 is considered
  3814  	err = m.handleCommunityDescription(messageState, signer, &cd, syncCommunity.Description, signer, nil)
  3815  	// Even if the Description is outdated we should proceed in order to sync settings and joined state
  3816  	if err != nil && err != communities.ErrInvalidCommunityDescriptionClockOutdated {
  3817  		logger.Debug("m.handleCommunityDescription error", zap.Error(err))
  3818  		return err
  3819  	}
  3820  	descriptionOutdated := err == communities.ErrInvalidCommunityDescriptionClockOutdated
  3821  
  3822  	if syncCommunity.Settings != nil {
  3823  		err = m.HandleSyncCommunitySettings(messageState, syncCommunity.Settings, nil)
  3824  		if err != nil {
  3825  			logger.Debug("m.handleSyncCommunitySettings error", zap.Error(err))
  3826  			return err
  3827  		}
  3828  	}
  3829  
  3830  	if syncCommunity.ControlNode != nil {
  3831  		err = m.communitiesManager.SetSyncControlNode(syncCommunity.Id, syncCommunity.ControlNode)
  3832  		if err != nil {
  3833  			logger.Debug("m.SetSyncControlNode", zap.Error(err))
  3834  			return err
  3835  		}
  3836  	}
  3837  
  3838  	// Handle community last updated
  3839  	if syncCommunity.LastOpenedAt > 0 {
  3840  		_, err = m.communitiesManager.CommunityUpdateLastOpenedAt(syncCommunity.Id, syncCommunity.LastOpenedAt)
  3841  		if err != nil {
  3842  			logger.Debug("m.CommunityUpdateLastOpenedAt", zap.Error(err))
  3843  			return err
  3844  		}
  3845  	}
  3846  
  3847  	// if we are not waiting for approval, join or leave the community
  3848  	if !pending && !descriptionOutdated {
  3849  		var mr *MessengerResponse
  3850  		if syncCommunity.Joined {
  3851  			mr, err = m.joinCommunity(context.Background(), syncCommunity.Id, false)
  3852  			if err != nil && err != communities.ErrOrgAlreadyJoined {
  3853  				logger.Debug("m.joinCommunity error", zap.Error(err))
  3854  				return err
  3855  			}
  3856  		} else {
  3857  			mr, err = m.leaveCommunity(syncCommunity.Id)
  3858  			if err != nil {
  3859  				logger.Debug("m.leaveCommunity error", zap.Error(err))
  3860  				return err
  3861  			}
  3862  		}
  3863  		if mr != nil {
  3864  			err = messageState.Response.Merge(mr)
  3865  			if err != nil {
  3866  				logger.Debug("messageState.Response.Merge error", zap.Error(err))
  3867  				return err
  3868  			}
  3869  		}
  3870  	}
  3871  
  3872  	// update the clock value
  3873  	err = m.communitiesManager.SetSyncClock(syncCommunity.Id, syncCommunity.Clock)
  3874  	if err != nil {
  3875  		logger.Debug("m.communitiesManager.SetSyncClock", zap.Error(err))
  3876  		return err
  3877  	}
  3878  
  3879  	return nil
  3880  }
  3881  
  3882  func (m *Messenger) HandleSyncCommunitySettings(messageState *ReceivedMessageState, syncCommunitySettings *protobuf.SyncCommunitySettings, statusMessage *v1protocol.StatusMessage) error {
  3883  	shouldHandle, err := m.communitiesManager.ShouldHandleSyncCommunitySettings(syncCommunitySettings)
  3884  	if err != nil {
  3885  		m.logger.Debug("m.communitiesManager.ShouldHandleSyncCommunitySettings error", zap.Error(err))
  3886  		return err
  3887  	}
  3888  	m.logger.Debug("ShouldHandleSyncCommunity result", zap.Bool("shouldHandle", shouldHandle))
  3889  	if !shouldHandle {
  3890  		return nil
  3891  	}
  3892  
  3893  	communitySettings, err := m.communitiesManager.HandleSyncCommunitySettings(syncCommunitySettings)
  3894  	if err != nil {
  3895  		return err
  3896  	}
  3897  
  3898  	messageState.Response.AddCommunitySettings(communitySettings)
  3899  	return nil
  3900  }
  3901  
  3902  func (m *Messenger) InitHistoryArchiveTasks(communities []*communities.Community) {
  3903  
  3904  	m.logger.Debug("initializing history archive tasks")
  3905  
  3906  	for _, c := range communities {
  3907  
  3908  		if c.Joined() {
  3909  			settings, err := m.communitiesManager.GetCommunitySettingsByID(c.ID())
  3910  			if err != nil {
  3911  				m.logger.Error("failed to get community settings", zap.Error(err))
  3912  				continue
  3913  			}
  3914  			if !settings.HistoryArchiveSupportEnabled {
  3915  				m.logger.Debug("history archive support disabled for community", zap.String("id", c.IDString()))
  3916  				continue
  3917  			}
  3918  
  3919  			// Check if there's already a torrent file for this community and seed it
  3920  			if m.archiveManager.TorrentFileExists(c.IDString()) {
  3921  				err = m.archiveManager.SeedHistoryArchiveTorrent(c.ID())
  3922  				if err != nil {
  3923  					m.logger.Error("failed to seed history archive", zap.Error(err))
  3924  				}
  3925  			}
  3926  
  3927  			filters, err := m.archiveManager.GetCommunityChatsFilters(c.ID())
  3928  			if err != nil {
  3929  				m.logger.Error("failed to get community chats filters for community", zap.Error(err))
  3930  				continue
  3931  			}
  3932  
  3933  			if len(filters) == 0 {
  3934  				m.logger.Debug("no filters or chats for this community starting interval", zap.String("id", c.IDString()))
  3935  				go m.archiveManager.StartHistoryArchiveTasksInterval(c, messageArchiveInterval)
  3936  				continue
  3937  			}
  3938  
  3939  			topics := []types.TopicType{}
  3940  
  3941  			for _, filter := range filters {
  3942  				topics = append(topics, filter.ContentTopic)
  3943  			}
  3944  
  3945  			// First we need to know the timestamp of the latest waku message
  3946  			// we've received for this community, so we can request messages we've
  3947  			// possibly missed since then
  3948  			latestWakuMessageTimestamp, err := m.communitiesManager.GetLatestWakuMessageTimestamp(topics)
  3949  			if err != nil {
  3950  				m.logger.Error("failed to get Latest waku message timestamp", zap.Error(err))
  3951  				continue
  3952  			}
  3953  
  3954  			if latestWakuMessageTimestamp == 0 {
  3955  				// This means we don't have any waku messages for this community
  3956  				// yet, either because no messages were sent in the community so far,
  3957  				// or because messages haven't reached this node
  3958  				//
  3959  				// In this case we default to requesting messages from the store nodes
  3960  				// for the past 30 days
  3961  				latestWakuMessageTimestamp = uint64(time.Now().AddDate(0, 0, -30).Unix())
  3962  			}
  3963  
  3964  			// Request possibly missed waku messages for community
  3965  			ms := m.getActiveMailserver(c.ID().String())
  3966  			_, err = m.syncFiltersFrom(*ms, filters, uint32(latestWakuMessageTimestamp))
  3967  			if err != nil {
  3968  				m.logger.Error("failed to request missing messages", zap.Error(err))
  3969  				continue
  3970  			}
  3971  
  3972  			// We figure out the end date of the last created archive and schedule
  3973  			// the interval for creating future archives
  3974  			// If the last end date is at least `interval` ago, we create an archive immediately first
  3975  			lastArchiveEndDateTimestamp, err := m.archiveManager.GetHistoryArchivePartitionStartTimestamp(c.ID())
  3976  			if err != nil {
  3977  				m.logger.Error("failed to get archive partition start timestamp", zap.Error(err))
  3978  				continue
  3979  			}
  3980  
  3981  			to := time.Now()
  3982  			lastArchiveEndDate := time.Unix(int64(lastArchiveEndDateTimestamp), 0)
  3983  			durationSinceLastArchive := to.Sub(lastArchiveEndDate)
  3984  
  3985  			if lastArchiveEndDateTimestamp == 0 {
  3986  				// No prior messages to be archived, so we just kick off the archive creation loop
  3987  				// for future archives
  3988  				go m.archiveManager.StartHistoryArchiveTasksInterval(c, messageArchiveInterval)
  3989  			} else if durationSinceLastArchive < messageArchiveInterval {
  3990  				// Last archive is less than `interval` old, wait until `interval` is complete,
  3991  				// then create archive and kick off archive creation loop for future archives
  3992  				// Seed current archive in the meantime
  3993  				err := m.archiveManager.SeedHistoryArchiveTorrent(c.ID())
  3994  				if err != nil {
  3995  					m.logger.Error("failed to seed history archive", zap.Error(err))
  3996  				}
  3997  				timeToNextInterval := messageArchiveInterval - durationSinceLastArchive
  3998  
  3999  				m.logger.Debug("starting history archive tasks interval in", zap.Any("timeLeft", timeToNextInterval))
  4000  				time.AfterFunc(timeToNextInterval, func() {
  4001  					err := m.archiveManager.CreateAndSeedHistoryArchive(c.ID(), topics, lastArchiveEndDate, to.Add(timeToNextInterval), messageArchiveInterval, c.Encrypted())
  4002  					if err != nil {
  4003  						m.logger.Error("failed to get create and seed history archive", zap.Error(err))
  4004  					}
  4005  					go m.archiveManager.StartHistoryArchiveTasksInterval(c, messageArchiveInterval)
  4006  				})
  4007  			} else {
  4008  				// Looks like the last archive was generated more than `interval`
  4009  				// ago, so lets create a new archive now and then schedule the archive
  4010  				// creation loop
  4011  				err := m.archiveManager.CreateAndSeedHistoryArchive(c.ID(), topics, lastArchiveEndDate, to, messageArchiveInterval, c.Encrypted())
  4012  				if err != nil {
  4013  					m.logger.Error("failed to get create and seed history archive", zap.Error(err))
  4014  				}
  4015  
  4016  				go m.archiveManager.StartHistoryArchiveTasksInterval(c, messageArchiveInterval)
  4017  			}
  4018  		}
  4019  	}
  4020  }
  4021  
  4022  func (m *Messenger) enableHistoryArchivesImportAfterDelay() {
  4023  	go func() {
  4024  		time.Sleep(importInitialDelay)
  4025  		m.importDelayer.once.Do(func() {
  4026  			close(m.importDelayer.wait)
  4027  		})
  4028  	}()
  4029  }
  4030  
  4031  func (m *Messenger) checkIfIMemberOfCommunity(communityID types.HexBytes) error {
  4032  	community, err := m.communitiesManager.GetByID(communityID)
  4033  	if err != nil {
  4034  		m.logger.Error("couldn't get community to import archives", zap.Error(err))
  4035  		return err
  4036  	}
  4037  
  4038  	if !community.HasMember(&m.identity.PublicKey) {
  4039  		m.logger.Error("can't import archives when user not a member of community")
  4040  		return ErrUserNotMember
  4041  	}
  4042  
  4043  	return nil
  4044  }
  4045  
  4046  func (m *Messenger) resumeHistoryArchivesImport(communityID types.HexBytes) error {
  4047  	archiveIDsToImport, err := m.archiveManager.GetMessageArchiveIDsToImport(communityID)
  4048  	if err != nil {
  4049  		return err
  4050  	}
  4051  
  4052  	if len(archiveIDsToImport) == 0 {
  4053  		return nil
  4054  	}
  4055  
  4056  	err = m.checkIfIMemberOfCommunity(communityID)
  4057  	if err != nil {
  4058  		return err
  4059  	}
  4060  
  4061  	currentTask := m.archiveManager.GetHistoryArchiveDownloadTask(communityID.String())
  4062  	// no need to resume imports if there's already a task ongoing
  4063  	if currentTask != nil {
  4064  		return nil
  4065  	}
  4066  
  4067  	// Create new task
  4068  	task := &communities.HistoryArchiveDownloadTask{
  4069  		CancelChan: make(chan struct{}),
  4070  		Waiter:     *new(sync.WaitGroup),
  4071  		Cancelled:  false,
  4072  	}
  4073  
  4074  	m.archiveManager.AddHistoryArchiveDownloadTask(communityID.String(), task)
  4075  
  4076  	// this wait groups tracks the ongoing task for a particular community
  4077  	task.Waiter.Add(1)
  4078  
  4079  	go func() {
  4080  		defer task.Waiter.Done()
  4081  		err := m.importHistoryArchives(communityID, task.CancelChan)
  4082  		if err != nil {
  4083  			m.logger.Error("failed to import history archives", zap.Error(err))
  4084  		}
  4085  		m.config.messengerSignalsHandler.DownloadingHistoryArchivesFinished(types.EncodeHex(communityID))
  4086  	}()
  4087  	return nil
  4088  }
  4089  
  4090  func (m *Messenger) SpeedupArchivesImport() {
  4091  	m.importRateLimiter.SetLimit(rate.Every(importFastRate))
  4092  }
  4093  
  4094  func (m *Messenger) SlowdownArchivesImport() {
  4095  	m.importRateLimiter.SetLimit(rate.Every(importSlowRate))
  4096  }
  4097  
  4098  func (m *Messenger) importHistoryArchives(communityID types.HexBytes, cancel chan struct{}) error {
  4099  	importTicker := time.NewTicker(100 * time.Millisecond)
  4100  	defer importTicker.Stop()
  4101  
  4102  	ctx, cancelFunc := context.WithCancel(context.Background())
  4103  	go func() {
  4104  		<-cancel
  4105  		cancelFunc()
  4106  	}()
  4107  
  4108  	// don't proceed until initial import delay has passed
  4109  	select {
  4110  	case <-m.importDelayer.wait:
  4111  	case <-ctx.Done():
  4112  		return nil
  4113  	}
  4114  
  4115  	delayImport := false
  4116  
  4117  importMessageArchivesLoop:
  4118  	for {
  4119  		if delayImport {
  4120  			select {
  4121  			case <-ctx.Done():
  4122  				m.logger.Debug("interrupted importing history archive messages")
  4123  				return nil
  4124  			case <-time.After(1 * time.Hour):
  4125  				delayImport = false
  4126  			}
  4127  		}
  4128  
  4129  		select {
  4130  		case <-ctx.Done():
  4131  			m.logger.Debug("interrupted importing history archive messages")
  4132  			return nil
  4133  		case <-importTicker.C:
  4134  			err := m.checkIfIMemberOfCommunity(communityID)
  4135  			if err != nil {
  4136  				break importMessageArchivesLoop
  4137  			}
  4138  			archiveIDsToImport, err := m.archiveManager.GetMessageArchiveIDsToImport(communityID)
  4139  			if err != nil {
  4140  				m.logger.Error("couldn't get message archive IDs to import", zap.Error(err))
  4141  				return err
  4142  			}
  4143  
  4144  			if len(archiveIDsToImport) == 0 {
  4145  				m.logger.Debug("no message archives to import")
  4146  				break importMessageArchivesLoop
  4147  			}
  4148  
  4149  			m.logger.Info("importing message archive", zap.Int("left", len(archiveIDsToImport)))
  4150  
  4151  			// only process one archive at a time, so in case of cancel we don't
  4152  			// wait for all archives to be processed first
  4153  			downloadedArchiveID := archiveIDsToImport[0]
  4154  
  4155  			archiveMessages, err := m.archiveManager.ExtractMessagesFromHistoryArchive(communityID, downloadedArchiveID)
  4156  			if err != nil {
  4157  				if errors.Is(err, encryption.ErrHashRatchetGroupIDNotFound) {
  4158  					// In case we're missing hash ratchet keys, best we can do is
  4159  					// to wait for them to be received and try import again.
  4160  					delayImport = true
  4161  					continue
  4162  				}
  4163  				m.logger.Error("failed to extract history archive messages", zap.Error(err))
  4164  				continue
  4165  			}
  4166  
  4167  			m.config.messengerSignalsHandler.ImportingHistoryArchiveMessages(types.EncodeHex(communityID))
  4168  
  4169  			for _, messagesChunk := range chunkSlice(archiveMessages, importMessagesChunkSize) {
  4170  				if err := m.importRateLimiter.Wait(ctx); err != nil {
  4171  					if !errors.Is(err, context.Canceled) {
  4172  						m.logger.Error("rate limiter error when handling archive messages", zap.Error(err))
  4173  					}
  4174  					continue importMessageArchivesLoop
  4175  				}
  4176  
  4177  				response, err := m.handleArchiveMessages(messagesChunk)
  4178  				if err != nil {
  4179  					m.logger.Error("failed to handle archive messages", zap.Error(err))
  4180  					continue importMessageArchivesLoop
  4181  				}
  4182  
  4183  				if !response.IsEmpty() {
  4184  					notifications := response.Notifications()
  4185  					response.ClearNotifications()
  4186  					signal.SendNewMessages(response)
  4187  					localnotifications.PushMessages(notifications)
  4188  				}
  4189  			}
  4190  
  4191  			err = m.archiveManager.SetMessageArchiveIDImported(communityID, downloadedArchiveID, true)
  4192  			if err != nil {
  4193  				m.logger.Error("failed to mark history message archive as imported", zap.Error(err))
  4194  				continue
  4195  			}
  4196  		}
  4197  	}
  4198  	return nil
  4199  }
  4200  
  4201  func (m *Messenger) dispatchMagnetlinkMessage(communityID string) error {
  4202  
  4203  	community, err := m.communitiesManager.GetByIDString(communityID)
  4204  	if err != nil {
  4205  		return err
  4206  	}
  4207  
  4208  	magnetlink, err := m.archiveManager.GetHistoryArchiveMagnetlink(community.ID())
  4209  	if err != nil {
  4210  		return err
  4211  	}
  4212  
  4213  	magnetLinkMessage := &protobuf.CommunityMessageArchiveMagnetlink{
  4214  		Clock:     m.getTimesource().GetCurrentTime(),
  4215  		MagnetUri: magnetlink,
  4216  	}
  4217  
  4218  	encodedMessage, err := proto.Marshal(magnetLinkMessage)
  4219  	if err != nil {
  4220  		return err
  4221  	}
  4222  
  4223  	chatID := community.MagnetlinkMessageChannelID()
  4224  	rawMessage := common.RawMessage{
  4225  		LocalChatID:          chatID,
  4226  		Sender:               community.PrivateKey(),
  4227  		Payload:              encodedMessage,
  4228  		MessageType:          protobuf.ApplicationMetadataMessage_COMMUNITY_MESSAGE_ARCHIVE_MAGNETLINK,
  4229  		SkipGroupMessageWrap: true,
  4230  		PubsubTopic:          community.PubsubTopic(),
  4231  		Priority:             &common.LowPriority,
  4232  	}
  4233  
  4234  	_, err = m.sender.SendPublic(context.Background(), chatID, rawMessage)
  4235  	if err != nil {
  4236  		return err
  4237  	}
  4238  
  4239  	err = m.communitiesManager.UpdateCommunityDescriptionMagnetlinkMessageClock(community.ID(), magnetLinkMessage.Clock)
  4240  	if err != nil {
  4241  		return err
  4242  	}
  4243  	return m.communitiesManager.UpdateMagnetlinkMessageClock(community.ID(), magnetLinkMessage.Clock)
  4244  }
  4245  
  4246  func (m *Messenger) EnableCommunityHistoryArchiveProtocol() error {
  4247  	nodeConfig, err := m.settings.GetNodeConfig()
  4248  	if err != nil {
  4249  		return err
  4250  	}
  4251  
  4252  	if nodeConfig.TorrentConfig.Enabled {
  4253  		return nil
  4254  	}
  4255  
  4256  	nodeConfig.TorrentConfig.Enabled = true
  4257  	err = m.settings.SaveSetting("node-config", nodeConfig)
  4258  	if err != nil {
  4259  		return err
  4260  	}
  4261  
  4262  	m.config.torrentConfig = &nodeConfig.TorrentConfig
  4263  	m.archiveManager.SetTorrentConfig(&nodeConfig.TorrentConfig)
  4264  	err = m.archiveManager.StartTorrentClient()
  4265  	if err != nil {
  4266  		return err
  4267  	}
  4268  
  4269  	controlledCommunities, err := m.communitiesManager.Controlled()
  4270  	if err != nil {
  4271  		return err
  4272  	}
  4273  
  4274  	if len(controlledCommunities) > 0 {
  4275  		go m.InitHistoryArchiveTasks(controlledCommunities)
  4276  	}
  4277  	if m.config.messengerSignalsHandler != nil {
  4278  		m.config.messengerSignalsHandler.HistoryArchivesProtocolEnabled()
  4279  	}
  4280  	return nil
  4281  }
  4282  
  4283  func (m *Messenger) DisableCommunityHistoryArchiveProtocol() error {
  4284  
  4285  	nodeConfig, err := m.settings.GetNodeConfig()
  4286  	if err != nil {
  4287  		return err
  4288  	}
  4289  	if !nodeConfig.TorrentConfig.Enabled {
  4290  		return nil
  4291  	}
  4292  
  4293  	err = m.archiveManager.Stop()
  4294  	if err != nil {
  4295  		m.logger.Error("failed to stop torrent manager", zap.Error(err))
  4296  	}
  4297  
  4298  	nodeConfig.TorrentConfig.Enabled = false
  4299  	err = m.settings.SaveSetting("node-config", nodeConfig)
  4300  	m.config.torrentConfig = &nodeConfig.TorrentConfig
  4301  	m.archiveManager.SetTorrentConfig(&nodeConfig.TorrentConfig)
  4302  	if err != nil {
  4303  		return err
  4304  	}
  4305  	if m.config.messengerSignalsHandler != nil {
  4306  		m.config.messengerSignalsHandler.HistoryArchivesProtocolDisabled()
  4307  	}
  4308  	return nil
  4309  }
  4310  
  4311  func (m *Messenger) GetCommunitiesSettings() ([]communities.CommunitySettings, error) {
  4312  	settings, err := m.communitiesManager.GetCommunitiesSettings()
  4313  	if err != nil {
  4314  		return nil, err
  4315  	}
  4316  	return settings, nil
  4317  }
  4318  
  4319  func (m *Messenger) SyncCommunitySettings(ctx context.Context, settings *communities.CommunitySettings) error {
  4320  
  4321  	if !m.hasPairedDevices() {
  4322  		return nil
  4323  	}
  4324  
  4325  	clock, chat := m.getLastClockWithRelatedChat()
  4326  
  4327  	syncMessage := &protobuf.SyncCommunitySettings{
  4328  		Clock:                        clock,
  4329  		CommunityId:                  settings.CommunityID,
  4330  		HistoryArchiveSupportEnabled: settings.HistoryArchiveSupportEnabled,
  4331  	}
  4332  	encodedMessage, err := proto.Marshal(syncMessage)
  4333  	if err != nil {
  4334  		return err
  4335  	}
  4336  
  4337  	_, err = m.dispatchMessage(ctx, common.RawMessage{
  4338  		LocalChatID: chat.ID,
  4339  		Payload:     encodedMessage,
  4340  		MessageType: protobuf.ApplicationMetadataMessage_SYNC_COMMUNITY_SETTINGS,
  4341  		ResendType:  common.ResendTypeDataSync,
  4342  	})
  4343  	if err != nil {
  4344  		return err
  4345  	}
  4346  
  4347  	chat.LastClockValue = clock
  4348  	return m.saveChat(chat)
  4349  }
  4350  
  4351  func (m *Messenger) generateSystemPinnedMessage(pinMessage *common.PinMessage, channel *Chat, clockAndTimestamp uint64, pinnedMessageID string) (*common.Message, *discord.ImportError) {
  4352  	id, err := generatePinMessageNotificationID(&m.identity.PublicKey, pinMessage, channel)
  4353  	if err != nil {
  4354  		m.logger.Warn("failed to generate pin message notification ID",
  4355  			zap.String("PinMessageId", pinMessage.ID))
  4356  		return nil, discord.Warning(err.Error())
  4357  	}
  4358  	systemMessage := &common.Message{
  4359  		ChatMessage: &protobuf.ChatMessage{
  4360  			Clock:       pinMessage.Clock,
  4361  			Timestamp:   clockAndTimestamp,
  4362  			ChatId:      channel.ID,
  4363  			MessageType: pinMessage.MessageType,
  4364  			ResponseTo:  pinnedMessageID,
  4365  			ContentType: protobuf.ChatMessage_SYSTEM_MESSAGE_PINNED_MESSAGE,
  4366  		},
  4367  		WhisperTimestamp: clockAndTimestamp,
  4368  		ID:               id,
  4369  		LocalChatID:      channel.ID,
  4370  		From:             pinMessage.From,
  4371  		Seen:             true,
  4372  	}
  4373  
  4374  	return systemMessage, nil
  4375  }
  4376  
  4377  func (m *Messenger) pinMessagesToWakuMessages(pinMessages []*common.PinMessage, c *communities.Community) ([]*types.Message, error) {
  4378  	wakuMessages := make([]*types.Message, 0)
  4379  	for _, msg := range pinMessages {
  4380  
  4381  		filter := m.transport.FilterByChatID(msg.LocalChatID)
  4382  		encodedPayload, err := proto.Marshal(msg.GetProtobuf())
  4383  		if err != nil {
  4384  			return nil, err
  4385  		}
  4386  		wrappedPayload, err := v1protocol.WrapMessageV1(encodedPayload, protobuf.ApplicationMetadataMessage_PIN_MESSAGE, c.PrivateKey())
  4387  		if err != nil {
  4388  			return nil, err
  4389  		}
  4390  
  4391  		hash := crypto.Keccak256Hash(append([]byte(c.IDString()), wrappedPayload...))
  4392  		wakuMessage := &types.Message{
  4393  			Sig:          crypto.FromECDSAPub(&c.PrivateKey().PublicKey),
  4394  			Timestamp:    uint32(msg.WhisperTimestamp / 1000),
  4395  			Topic:        filter.ContentTopic,
  4396  			Payload:      wrappedPayload,
  4397  			Padding:      []byte{1},
  4398  			Hash:         hash[:],
  4399  			ThirdPartyID: msg.ID, // CommunityID + DiscordMessageID
  4400  		}
  4401  		wakuMessages = append(wakuMessages, wakuMessage)
  4402  	}
  4403  
  4404  	return wakuMessages, nil
  4405  }
  4406  
  4407  func (m *Messenger) chatMessagesToWakuMessages(chatMessages []*common.Message, c *communities.Community) ([]*types.Message, error) {
  4408  	wakuMessages := make([]*types.Message, 0)
  4409  	for _, msg := range chatMessages {
  4410  
  4411  		filter := m.transport.FilterByChatID(msg.LocalChatID)
  4412  		encodedPayload, err := proto.Marshal(msg.GetProtobuf())
  4413  		if err != nil {
  4414  			return nil, err
  4415  		}
  4416  
  4417  		wrappedPayload, err := v1protocol.WrapMessageV1(encodedPayload, protobuf.ApplicationMetadataMessage_CHAT_MESSAGE, c.PrivateKey())
  4418  		if err != nil {
  4419  			return nil, err
  4420  		}
  4421  
  4422  		hash := crypto.Keccak256Hash([]byte(msg.ID))
  4423  		wakuMessage := &types.Message{
  4424  			Sig:          crypto.FromECDSAPub(&c.PrivateKey().PublicKey),
  4425  			Timestamp:    uint32(msg.WhisperTimestamp / 1000),
  4426  			Topic:        filter.ContentTopic,
  4427  			Payload:      wrappedPayload,
  4428  			Padding:      []byte{1},
  4429  			Hash:         hash[:],
  4430  			ThirdPartyID: msg.ID, // CommunityID + DiscordMessageID
  4431  		}
  4432  		wakuMessages = append(wakuMessages, wakuMessage)
  4433  	}
  4434  
  4435  	return wakuMessages, nil
  4436  }
  4437  
  4438  func (m *Messenger) GetCommunityToken(communityID string, chainID int, address string) (*token.CommunityToken, error) {
  4439  	return m.communitiesManager.GetCommunityToken(communityID, chainID, address)
  4440  }
  4441  
  4442  func (m *Messenger) GetCommunityTokenByChainAndAddress(chainID int, address string) (*token.CommunityToken, error) {
  4443  	return m.communitiesManager.GetCommunityTokenByChainAndAddress(chainID, address)
  4444  }
  4445  
  4446  func (m *Messenger) GetCommunityTokens(communityID string) ([]*token.CommunityToken, error) {
  4447  	return m.communitiesManager.GetCommunityTokens(communityID)
  4448  }
  4449  
  4450  func (m *Messenger) GetCommunityPermissionedBalances(request *requests.GetPermissionedBalances) (map[gethcommon.Address][]communities.PermissionedBalance, error) {
  4451  	err := request.Validate()
  4452  	if err != nil {
  4453  		return nil, err
  4454  	}
  4455  
  4456  	accountAddresses, err := m.settings.GetWalletAddresses()
  4457  	if err != nil {
  4458  		return nil, err
  4459  	}
  4460  
  4461  	gethAddresses := make([]gethcommon.Address, 0, len(accountAddresses))
  4462  	for _, address := range accountAddresses {
  4463  		gethAddresses = append(gethAddresses, gethcommon.HexToAddress(address.Hex()))
  4464  	}
  4465  
  4466  	return m.communitiesManager.GetPermissionedBalances(
  4467  		context.Background(),
  4468  		request.CommunityID,
  4469  		gethAddresses,
  4470  	)
  4471  }
  4472  
  4473  func (m *Messenger) GetAllCommunityTokens() ([]*token.CommunityToken, error) {
  4474  	return m.communitiesManager.GetAllCommunityTokens()
  4475  }
  4476  
  4477  func (m *Messenger) SaveCommunityToken(token *token.CommunityToken, croppedImage *images.CroppedImage) (*token.CommunityToken, error) {
  4478  	return m.communitiesManager.SaveCommunityToken(token, croppedImage)
  4479  }
  4480  
  4481  func (m *Messenger) AddCommunityToken(communityID string, chainID int, address string) error {
  4482  	communityToken, err := m.communitiesManager.GetCommunityToken(communityID, chainID, address)
  4483  	if err != nil {
  4484  		return err
  4485  	}
  4486  
  4487  	clock, _ := m.getLastClockWithRelatedChat()
  4488  	community, err := m.communitiesManager.AddCommunityToken(communityToken, clock)
  4489  	if err != nil {
  4490  		return err
  4491  	}
  4492  
  4493  	err = m.syncCommunity(context.Background(), community, m.dispatchMessage)
  4494  	if err != nil {
  4495  		return err
  4496  	}
  4497  
  4498  	return nil
  4499  }
  4500  
  4501  func (m *Messenger) UpdateCommunityTokenState(chainID int, contractAddress string, deployState token.DeployState) error {
  4502  	return m.communitiesManager.UpdateCommunityTokenState(chainID, contractAddress, deployState)
  4503  }
  4504  
  4505  func (m *Messenger) UpdateCommunityTokenAddress(chainID int, oldContractAddress string, newContractAddress string) error {
  4506  	return m.communitiesManager.UpdateCommunityTokenAddress(chainID, oldContractAddress, newContractAddress)
  4507  }
  4508  
  4509  func (m *Messenger) UpdateCommunityTokenSupply(chainID int, contractAddress string, supply *bigint.BigInt) error {
  4510  	return m.communitiesManager.UpdateCommunityTokenSupply(chainID, contractAddress, supply)
  4511  }
  4512  
  4513  func (m *Messenger) RemoveCommunityToken(chainID int, contractAddress string) error {
  4514  	return m.communitiesManager.RemoveCommunityToken(chainID, contractAddress)
  4515  }
  4516  
  4517  func (m *Messenger) CheckPermissionsToJoinCommunity(request *requests.CheckPermissionToJoinCommunity) (*communities.CheckPermissionToJoinResponse, error) {
  4518  	if err := request.Validate(); err != nil {
  4519  		return nil, err
  4520  	}
  4521  	var addresses []gethcommon.Address
  4522  
  4523  	if len(request.Addresses) == 0 {
  4524  		accounts, err := m.settings.GetActiveAccounts()
  4525  		if err != nil {
  4526  			return nil, err
  4527  		}
  4528  
  4529  		for _, a := range accounts {
  4530  			if a.IsWalletNonWatchOnlyAccount() {
  4531  				addresses = append(addresses, gethcommon.HexToAddress(a.Address.Hex()))
  4532  			}
  4533  		}
  4534  	} else {
  4535  		for _, v := range request.Addresses {
  4536  			addresses = append(addresses, gethcommon.HexToAddress(v))
  4537  		}
  4538  	}
  4539  
  4540  	return m.communitiesManager.CheckPermissionToJoin(request.CommunityID, addresses)
  4541  }
  4542  
  4543  func (m *Messenger) getSharedAddresses(communityID types.HexBytes, requestAddresses []string) ([]gethcommon.Address, error) {
  4544  	addressesMap := make(map[string]struct{})
  4545  
  4546  	for _, v := range requestAddresses {
  4547  		addressesMap[v] = struct{}{}
  4548  	}
  4549  
  4550  	if len(requestAddresses) == 0 {
  4551  		sharedAddresses, err := m.GetRevealedAccounts(communityID, common.PubkeyToHex(&m.identity.PublicKey))
  4552  		if err != nil {
  4553  			return nil, err
  4554  		}
  4555  
  4556  		for _, v := range sharedAddresses {
  4557  			addressesMap[v.Address] = struct{}{}
  4558  		}
  4559  	}
  4560  
  4561  	if len(addressesMap) == 0 {
  4562  		accounts, err := m.settings.GetActiveAccounts()
  4563  		if err != nil {
  4564  			return nil, err
  4565  		}
  4566  
  4567  		for _, a := range accounts {
  4568  			addressesMap[a.Address.Hex()] = struct{}{}
  4569  		}
  4570  	}
  4571  
  4572  	var addresses []gethcommon.Address
  4573  	for addr := range addressesMap {
  4574  		addresses = append(addresses, gethcommon.HexToAddress(addr))
  4575  	}
  4576  
  4577  	return addresses, nil
  4578  }
  4579  
  4580  func (m *Messenger) CheckCommunityChannelPermissions(request *requests.CheckCommunityChannelPermissions) (*communities.CheckChannelPermissionsResponse, error) {
  4581  	if err := request.Validate(); err != nil {
  4582  		return nil, err
  4583  	}
  4584  
  4585  	addresses, err := m.getSharedAddresses(request.CommunityID, request.Addresses)
  4586  	if err != nil {
  4587  		return nil, err
  4588  	}
  4589  
  4590  	return m.communitiesManager.CheckChannelPermissions(request.CommunityID, request.ChatID, addresses)
  4591  }
  4592  
  4593  func (m *Messenger) CheckAllCommunityChannelsPermissions(request *requests.CheckAllCommunityChannelsPermissions) (*communities.CheckAllChannelsPermissionsResponse, error) {
  4594  	if err := request.Validate(); err != nil {
  4595  		return nil, err
  4596  	}
  4597  
  4598  	addresses, err := m.getSharedAddresses(request.CommunityID, request.Addresses)
  4599  	if err != nil {
  4600  		return nil, err
  4601  	}
  4602  
  4603  	return m.communitiesManager.CheckAllChannelsPermissions(request.CommunityID, addresses)
  4604  }
  4605  
  4606  func (m *Messenger) GetCommunityCheckChannelPermissionResponses(communityID types.HexBytes) (*communities.CheckAllChannelsPermissionsResponse, error) {
  4607  	return m.communitiesManager.GetCheckChannelPermissionResponses(communityID)
  4608  }
  4609  
  4610  func chunkSlice[T comparable](slice []T, chunkSize int) [][]T {
  4611  	var chunks [][]T
  4612  	for i := 0; i < len(slice); i += chunkSize {
  4613  		end := i + chunkSize
  4614  
  4615  		// necessary check to avoid slicing beyond
  4616  		// slice capacity
  4617  		if end > len(slice) {
  4618  			end = len(slice)
  4619  		}
  4620  
  4621  		chunks = append(chunks, slice[i:end])
  4622  	}
  4623  
  4624  	return chunks
  4625  }
  4626  
  4627  func chunkAttachmentsByByteSize(slice []*protobuf.DiscordMessageAttachment, maxFileSizeBytes uint64) [][]*protobuf.DiscordMessageAttachment {
  4628  	var chunks [][]*protobuf.DiscordMessageAttachment
  4629  
  4630  	currentChunkSize := uint64(0)
  4631  	currentChunk := make([]*protobuf.DiscordMessageAttachment, 0)
  4632  
  4633  	for i, attachment := range slice {
  4634  		payloadBytes := attachment.GetFileSizeBytes()
  4635  		if currentChunkSize+payloadBytes > maxFileSizeBytes && len(currentChunk) > 0 {
  4636  			chunks = append(chunks, currentChunk)
  4637  			currentChunk = make([]*protobuf.DiscordMessageAttachment, 0)
  4638  			currentChunkSize = uint64(0)
  4639  		}
  4640  		currentChunk = append(currentChunk, attachment)
  4641  		currentChunkSize = currentChunkSize + payloadBytes
  4642  		if i == len(slice)-1 {
  4643  			chunks = append(chunks, currentChunk)
  4644  		}
  4645  	}
  4646  	return chunks
  4647  }
  4648  
  4649  // startCommunityRekeyLoop creates a 5-minute ticker and starts a routine that attempts to rekey every community every tick
  4650  func (m *Messenger) startCommunityRekeyLoop() {
  4651  	logger := m.logger.Named("CommunityRekeyLoop")
  4652  	var d time.Duration
  4653  	if m.communitiesManager.RekeyInterval != 0 {
  4654  		if m.communitiesManager.RekeyInterval < 10 {
  4655  			d = time.Nanosecond
  4656  		} else {
  4657  			d = m.communitiesManager.RekeyInterval / 10
  4658  		}
  4659  	} else {
  4660  		d = 5 * time.Minute
  4661  	}
  4662  
  4663  	ticker := time.NewTicker(d)
  4664  	go func() {
  4665  		for {
  4666  			select {
  4667  			case <-ticker.C:
  4668  				m.rekeyCommunities(logger)
  4669  			case <-m.quit:
  4670  				ticker.Stop()
  4671  				logger.Debug("CommunityRekeyLoop stopped")
  4672  				return
  4673  			}
  4674  		}
  4675  	}()
  4676  }
  4677  
  4678  // rekeyCommunities loops over controlled communities and rekeys if rekey interval elapsed
  4679  func (m *Messenger) rekeyCommunities(logger *zap.Logger) {
  4680  	// TODO in future have a community level rki rather than a global rki
  4681  	var rekeyInterval time.Duration
  4682  	if m.communitiesManager.RekeyInterval == 0 {
  4683  		rekeyInterval = 48 * time.Hour
  4684  	} else {
  4685  		rekeyInterval = m.communitiesManager.RekeyInterval
  4686  	}
  4687  
  4688  	shouldRekey := func(hashRatchetGroupID []byte) bool {
  4689  		key, err := m.sender.GetCurrentKeyForGroup(hashRatchetGroupID)
  4690  		if err != nil {
  4691  			logger.Error("failed to get current hash ratchet key", zap.Error(err))
  4692  			return false
  4693  		}
  4694  
  4695  		keyDistributedAt := time.UnixMilli(int64(key.Timestamp))
  4696  		return time.Now().After(keyDistributedAt.Add(rekeyInterval))
  4697  	}
  4698  
  4699  	controlledCommunities, err := m.ControlledCommunities()
  4700  	if err != nil {
  4701  		logger.Error("error getting communities", zap.Error(err))
  4702  		return
  4703  	}
  4704  
  4705  	for _, c := range controlledCommunities {
  4706  		keyActions := &communities.EncryptionKeyActions{
  4707  			CommunityKeyAction: communities.EncryptionKeyAction{},
  4708  			ChannelKeysActions: map[string]communities.EncryptionKeyAction{},
  4709  		}
  4710  
  4711  		if c.Encrypted() && shouldRekey(c.ID()) {
  4712  			keyActions.CommunityKeyAction = communities.EncryptionKeyAction{
  4713  				ActionType: communities.EncryptionKeyRekey,
  4714  				Members:    c.Members(),
  4715  			}
  4716  		}
  4717  
  4718  		for channelID, channel := range c.Chats() {
  4719  			if c.ChannelEncrypted(channelID) && shouldRekey([]byte(c.IDString()+channelID)) {
  4720  				keyActions.ChannelKeysActions[channelID] = communities.EncryptionKeyAction{
  4721  					ActionType: communities.EncryptionKeyRekey,
  4722  					Members:    channel.Members,
  4723  				}
  4724  			}
  4725  		}
  4726  
  4727  		err = m.communitiesKeyDistributor.Distribute(c, keyActions)
  4728  		if err != nil {
  4729  			logger.Error("failed to rekey community", zap.Error(err), zap.String("community ID", c.IDString()))
  4730  			continue
  4731  		}
  4732  	}
  4733  }
  4734  
  4735  func (m *Messenger) GetCommunityMembersForWalletAddresses(communityID types.HexBytes, chainID uint64) (map[string]*Contact, error) {
  4736  	community, err := m.communitiesManager.GetByID(communityID)
  4737  	if err != nil {
  4738  		return nil, err
  4739  	}
  4740  
  4741  	membersForAddresses := map[string]*Contact{}
  4742  
  4743  	for _, memberPubKey := range community.GetMemberPubkeys() {
  4744  		memberPubKeyStr := common.PubkeyToHex(memberPubKey)
  4745  		revealedAccounts, err := m.communitiesManager.GetRevealedAddresses(communityID, memberPubKeyStr)
  4746  		if err != nil {
  4747  			return nil, err
  4748  		}
  4749  		for _, revealedAccount := range revealedAccounts {
  4750  			if !slices.Contains(revealedAccount.ChainIds, chainID) {
  4751  				continue
  4752  			}
  4753  
  4754  			contact, ok := m.allContacts.Load(memberPubKeyStr)
  4755  			if ok {
  4756  				membersForAddresses[revealedAccount.Address] = contact
  4757  			} else {
  4758  				m.logger.Error("community member is not a contact", zap.String("contact ID", memberPubKeyStr))
  4759  			}
  4760  		}
  4761  	}
  4762  
  4763  	return membersForAddresses, nil
  4764  }
  4765  
  4766  func (m *Messenger) processCommunityChanges(messageState *ReceivedMessageState) {
  4767  	// Process any community changes
  4768  	pkString := common.PubkeyToHex(&m.identity.PublicKey)
  4769  	for _, changes := range messageState.Response.CommunityChanges {
  4770  		if changes.ShouldMemberJoin {
  4771  			response, err := m.joinCommunity(context.TODO(), changes.Community.ID(), false)
  4772  			if err != nil {
  4773  				m.logger.Error("cannot join community", zap.Error(err))
  4774  				continue
  4775  			}
  4776  
  4777  			if err := messageState.Response.Merge(response); err != nil {
  4778  				m.logger.Error("cannot merge join community response", zap.Error(err))
  4779  				continue
  4780  			}
  4781  		} else if changes.MemberSoftKicked {
  4782  			m.leaveCommunityOnSoftKick(changes.Community, messageState.Response)
  4783  			m.shareRevealedAccountsOnSoftKick(changes.Community, messageState.Response)
  4784  
  4785  		} else if changes.MemberKicked {
  4786  			notificationType := ActivityCenterNotificationTypeCommunityKicked
  4787  			if changes.IsMemberBanned(pkString) {
  4788  				notificationType = ActivityCenterNotificationTypeCommunityBanned
  4789  			}
  4790  			m.leaveCommunityDueToKickOrBan(changes, notificationType, messageState.Response)
  4791  		} else if changes.IsMemberUnbanned(pkString) {
  4792  			m.AddActivityCenterNotificationToResponse(changes.Community.IDString(), ActivityCenterNotificationTypeCommunityUnbanned, messageState.Response)
  4793  		}
  4794  	}
  4795  	// Clean up as not used by clients currently
  4796  	messageState.Response.CommunityChanges = nil
  4797  }
  4798  
  4799  func (m *Messenger) PromoteSelfToControlNode(communityID types.HexBytes) (*MessengerResponse, error) {
  4800  	clock, _ := m.getLastClockWithRelatedChat()
  4801  
  4802  	community, err := m.FetchCommunity(&FetchCommunityRequest{
  4803  		CommunityKey:    types.EncodeHex(communityID),
  4804  		Shard:           nil,
  4805  		TryDatabase:     true,
  4806  		WaitForResponse: true,
  4807  	})
  4808  
  4809  	if err != nil {
  4810  		return nil, err
  4811  	}
  4812  
  4813  	if !communities.HasTokenOwnership(community.Description()) {
  4814  		return nil, errors.New(ErrOwnerTokenNeeded)
  4815  	}
  4816  
  4817  	changes, err := m.communitiesManager.PromoteSelfToControlNode(community, clock)
  4818  	if err != nil {
  4819  		return nil, err
  4820  	}
  4821  
  4822  	var response MessengerResponse
  4823  
  4824  	if len(changes.MembersRemoved) > 0 {
  4825  		requestsToJoin, err := m.communitiesManager.GenerateRequestsToJoinForAutoApprovalOnNewOwnership(changes.Community.ID(), changes.MembersRemoved)
  4826  		if err != nil {
  4827  			return nil, err
  4828  		}
  4829  		response.AddRequestsToJoinCommunity(requestsToJoin)
  4830  	}
  4831  
  4832  	err = m.syncCommunity(context.Background(), changes.Community, m.dispatchMessage)
  4833  	if err != nil {
  4834  		return nil, err
  4835  	}
  4836  
  4837  	response.AddCommunity(changes.Community)
  4838  	response.CommunityChanges = []*communities.CommunityChanges{changes}
  4839  
  4840  	if m.config.messengerSignalsHandler != nil {
  4841  		m.config.messengerSignalsHandler.MessengerResponse(&response)
  4842  	}
  4843  
  4844  	m.communitiesManager.StartMembersReevaluationLoop(community.ID(), false)
  4845  
  4846  	return &response, nil
  4847  }
  4848  
  4849  func (m *Messenger) CreateResponseWithACNotification(communityID string, acType ActivityCenterType, isRead bool, tokenDataJSON string) (*MessengerResponse, error) {
  4850  	tokenData := ActivityTokenData{}
  4851  	err := json.Unmarshal([]byte(tokenDataJSON), &tokenData)
  4852  	if len(tokenDataJSON) > 0 && err != nil {
  4853  		// Only return error when activityDataString is not empty
  4854  		return nil, err
  4855  	}
  4856  	// Activity center notification
  4857  	notification := &ActivityCenterNotification{
  4858  		ID:          types.FromHex(uuid.New().String()),
  4859  		Type:        acType,
  4860  		Timestamp:   m.getTimesource().GetCurrentTime(),
  4861  		CommunityID: communityID,
  4862  		Read:        isRead,
  4863  		Deleted:     false,
  4864  		UpdatedAt:   m.GetCurrentTimeInMillis(),
  4865  		TokenData:   &tokenData,
  4866  	}
  4867  
  4868  	err = m.prepareTokenData(notification.TokenData, m.httpServer)
  4869  	if err != nil {
  4870  		return nil, err
  4871  	}
  4872  
  4873  	response := &MessengerResponse{}
  4874  
  4875  	err = m.addActivityCenterNotification(response, notification, nil)
  4876  	if err != nil {
  4877  		m.logger.Error("failed to save notification", zap.Error(err))
  4878  		return response, err
  4879  	}
  4880  
  4881  	return response, nil
  4882  }
  4883  
  4884  // SendMessageToControlNode sends a message to the control node of the community.
  4885  // use pointer to rawMessage to get the message ID and other updated properties.
  4886  func (m *Messenger) SendMessageToControlNode(community *communities.Community, rawMessage *common.RawMessage) ([]byte, error) {
  4887  	if !community.PublicKey().Equal(community.ControlNode()) {
  4888  		m.logger.Debug("control node is different with community pubkey", zap.Any("control:", community.ControlNode()), zap.Any("communityPubkey:", community.PublicKey()))
  4889  		rawMessage.ResendMethod = common.ResendMethodSendPrivate
  4890  		rawMessage.ResendType = common.ResendTypeDataSync
  4891  		// MVDS only supports sending encrypted message
  4892  		rawMessage.SkipEncryptionLayer = false
  4893  		rawMessage.Recipients = append(rawMessage.Recipients, community.ControlNode())
  4894  		return m.sender.SendPrivate(context.Background(), community.ControlNode(), rawMessage)
  4895  	}
  4896  	rawMessage.ResendMethod = common.ResendMethodSendCommunityMessage
  4897  	// Note: There are multiple instances where SendMessageToControlNode is invoked throughout the codebase.
  4898  	// Additionally, some callers may invoke SendPrivate before SendMessageToControlNode. This could potentially
  4899  	// lead to a situation where the same raw message is sent using different methods, which, from a code perspective,
  4900  	// seems erroneous when implementing raw message resending. However, this behavior is intentional and is not considered
  4901  	// an issue. For a detailed explanation, refer https://github.com/status-im/status-go/pull/4969#issuecomment-2040891184
  4902  	return m.sender.SendCommunityMessage(context.Background(), rawMessage)
  4903  }
  4904  
  4905  func (m *Messenger) AddActivityCenterNotificationToResponse(communityID string, acType ActivityCenterType, response *MessengerResponse) {
  4906  	// Activity Center notification
  4907  	notification := &ActivityCenterNotification{
  4908  		ID:          types.FromHex(uuid.New().String()),
  4909  		Type:        acType,
  4910  		Timestamp:   m.getTimesource().GetCurrentTime(),
  4911  		CommunityID: communityID,
  4912  		Read:        false,
  4913  		Deleted:     false,
  4914  		UpdatedAt:   m.GetCurrentTimeInMillis(),
  4915  	}
  4916  
  4917  	err := m.addActivityCenterNotification(response, notification, nil)
  4918  	if err != nil {
  4919  		m.logger.Error("failed to save notification", zap.Error(err))
  4920  	}
  4921  }
  4922  
  4923  func (m *Messenger) leaveCommunityDueToKickOrBan(changes *communities.CommunityChanges, acType ActivityCenterType, stateResponse *MessengerResponse) {
  4924  	response, err := m.kickedOutOfCommunity(changes.Community.ID(), false)
  4925  	if err != nil {
  4926  		m.logger.Error("cannot leave community", zap.Error(err))
  4927  		return
  4928  	}
  4929  
  4930  	// Activity Center notification
  4931  	notification := &ActivityCenterNotification{
  4932  		ID:          types.FromHex(uuid.New().String()),
  4933  		Type:        acType,
  4934  		Timestamp:   m.getTimesource().GetCurrentTime(),
  4935  		CommunityID: changes.Community.IDString(),
  4936  		Read:        false,
  4937  		UpdatedAt:   m.GetCurrentTimeInMillis(),
  4938  	}
  4939  
  4940  	err = m.addActivityCenterNotification(response, notification, nil)
  4941  	if err != nil {
  4942  		m.logger.Error("failed to save notification", zap.Error(err))
  4943  		return
  4944  	}
  4945  
  4946  	if err := stateResponse.Merge(response); err != nil {
  4947  		m.logger.Error("cannot merge leave and notification response", zap.Error(err))
  4948  	}
  4949  }
  4950  
  4951  func (m *Messenger) GetCommunityMemberAllMessages(request *requests.CommunityMemberMessages) ([]*common.Message, error) {
  4952  	if err := request.Validate(); err != nil {
  4953  		return nil, err
  4954  	}
  4955  
  4956  	messages, err := m.persistence.GetCommunityMemberAllMessages(request.MemberPublicKey, request.CommunityID)
  4957  	if err != nil {
  4958  		return nil, err
  4959  	}
  4960  
  4961  	for _, message := range messages {
  4962  		updatedMessages, err := m.persistence.MessagesByResponseTo(message.ID)
  4963  		if err != nil {
  4964  			return nil, err
  4965  		}
  4966  
  4967  		messages = append(messages, updatedMessages...)
  4968  	}
  4969  	err = m.prepareMessagesList(messages)
  4970  	if err != nil {
  4971  		return nil, err
  4972  	}
  4973  	return messages, nil
  4974  
  4975  }
  4976  
  4977  func (m *Messenger) DeleteCommunityMemberMessages(request *requests.DeleteCommunityMemberMessages) (*MessengerResponse, error) {
  4978  	if err := request.Validate(); err != nil {
  4979  		return nil, err
  4980  	}
  4981  
  4982  	community, err := m.GetCommunityByID(request.CommunityID)
  4983  	if err != nil {
  4984  		return nil, err
  4985  	}
  4986  
  4987  	if community == nil {
  4988  		return nil, communities.ErrOrgNotFound
  4989  	}
  4990  
  4991  	if !community.IsControlNode() && !community.IsPrivilegedMember(m.IdentityPublicKey()) {
  4992  		return nil, communities.ErrNotEnoughPermissions
  4993  	}
  4994  
  4995  	memberPubKey, err := common.HexToPubkey(request.MemberPubKey)
  4996  	if err != nil {
  4997  		return nil, err
  4998  	}
  4999  
  5000  	if community.IsMemberOwner(memberPubKey) && !m.IdentityPublicKey().Equal(memberPubKey) {
  5001  		return nil, communities.ErrNotOwner
  5002  	}
  5003  
  5004  	deleteMessagesResponse, err := m.deleteCommunityMemberMessages(request.MemberPubKey, request.CommunityID.String(), request.Messages)
  5005  	if err != nil {
  5006  		return nil, err
  5007  	}
  5008  
  5009  	deletedMessages := &protobuf.DeleteCommunityMemberMessages{
  5010  		Clock:       uint64(time.Now().Unix()),
  5011  		CommunityId: community.ID(),
  5012  		MemberId:    request.MemberPubKey,
  5013  		Messages:    request.Messages,
  5014  	}
  5015  
  5016  	payload, err := proto.Marshal(deletedMessages)
  5017  	if err != nil {
  5018  		return nil, err
  5019  	}
  5020  
  5021  	rawMessage := common.RawMessage{
  5022  		Payload:             payload,
  5023  		Sender:              community.PrivateKey(),
  5024  		SkipEncryptionLayer: true,
  5025  		MessageType:         protobuf.ApplicationMetadataMessage_DELETE_COMMUNITY_MEMBER_MESSAGES,
  5026  		PubsubTopic:         community.PubsubTopic(),
  5027  	}
  5028  
  5029  	_, err = m.sender.SendPublic(context.Background(), community.IDString(), rawMessage)
  5030  
  5031  	return deleteMessagesResponse, err
  5032  }
  5033  
  5034  func (m *Messenger) HandleDeleteCommunityMemberMessages(state *ReceivedMessageState, request *protobuf.DeleteCommunityMemberMessages, statusMessage *v1protocol.StatusMessage) error {
  5035  	community, err := m.communitiesManager.GetByID(request.CommunityId)
  5036  	if err != nil {
  5037  		return err
  5038  	}
  5039  
  5040  	if community == nil {
  5041  		return communities.ErrOrgNotFound
  5042  	}
  5043  
  5044  	if !community.ControlNode().Equal(state.CurrentMessageState.PublicKey) && !community.IsPrivilegedMember(state.CurrentMessageState.PublicKey) {
  5045  		return communities.ErrNotAuthorized
  5046  	}
  5047  
  5048  	deleteMessagesResponse, err := m.deleteCommunityMemberMessages(request.MemberId, community.IDString(), request.Messages)
  5049  	if err != nil {
  5050  		return err
  5051  	}
  5052  
  5053  	return state.Response.Merge(deleteMessagesResponse)
  5054  }
  5055  
  5056  func (m *Messenger) leaveCommunityOnSoftKick(community *communities.Community, messengerResponse *MessengerResponse) {
  5057  	response, err := m.kickedOutOfCommunity(community.ID(), true)
  5058  	if err != nil {
  5059  		m.logger.Error("member soft kick error", zap.String("communityID", types.EncodeHex(community.ID())), zap.Error(err))
  5060  	}
  5061  
  5062  	if err := messengerResponse.Merge(response); err != nil {
  5063  		m.logger.Error("cannot merge leaveCommunityOnSoftKick response", zap.String("communityID", types.EncodeHex(community.ID())), zap.Error(err))
  5064  	}
  5065  }
  5066  
  5067  func (m *Messenger) shareRevealedAccountsOnSoftKick(community *communities.Community, messengerResponse *MessengerResponse) {
  5068  	requestToJoin, err := m.sendSharedAddressToControlNode(community.ControlNode(), community)
  5069  	if err != nil {
  5070  		m.logger.Error("share address to control node failed", zap.String("id", types.EncodeHex(community.ID())), zap.Error(err))
  5071  
  5072  		if err == communities.ErrRevealedAccountsAbsent || err == communities.ErrNoRevealedAccountsSignature {
  5073  			m.AddActivityCenterNotificationToResponse(community.IDString(), ActivityCenterNotificationTypeShareAccounts, messengerResponse)
  5074  		}
  5075  	} else {
  5076  		messengerResponse.AddRequestToJoinCommunity(requestToJoin)
  5077  	}
  5078  }
  5079  
  5080  func (m *Messenger) requestCommunityEncryptionKeys(community *communities.Community, channelIDs []string) error {
  5081  	m.logger.Debug("request community encryption keys",
  5082  		zap.String("communityID", community.IDString()),
  5083  		zap.Strings("channels", channelIDs))
  5084  
  5085  	request := &protobuf.CommunityEncryptionKeysRequest{
  5086  		CommunityId: community.ID(),
  5087  		ChatIds:     channelIDs,
  5088  	}
  5089  
  5090  	payload, err := proto.Marshal(request)
  5091  	if err != nil {
  5092  		return err
  5093  	}
  5094  
  5095  	rawMessage := &common.RawMessage{
  5096  		Payload:             payload,
  5097  		Sender:              m.identity,
  5098  		CommunityID:         community.ID(),
  5099  		SkipEncryptionLayer: true,
  5100  		MessageType:         protobuf.ApplicationMetadataMessage_COMMUNITY_ENCRYPTION_KEYS_REQUEST,
  5101  	}
  5102  
  5103  	_, err = m.SendMessageToControlNode(community, rawMessage)
  5104  	return err
  5105  }
  5106  
  5107  func (m *Messenger) startRequestMissingCommunityChannelsHRKeysLoop() {
  5108  	logger := m.logger.Named("requestMissingCommunityChannelsHRKeysLoop")
  5109  
  5110  	go func() {
  5111  		for {
  5112  			select {
  5113  			case <-time.After(5 * time.Minute):
  5114  				communitiesChannels, err := m.communitiesManager.DetermineChannelsForHRKeysRequest()
  5115  				if err != nil {
  5116  					logger.Error("failed to determine channels for encryption keys request", zap.Error(err))
  5117  					continue
  5118  				}
  5119  
  5120  				for _, cc := range communitiesChannels {
  5121  					err := m.requestCommunityEncryptionKeys(cc.Community, cc.ChannelIDs)
  5122  					if err != nil {
  5123  						logger.Error("failed to request channels' encryption keys",
  5124  							zap.String("communityID", cc.Community.IDString()),
  5125  							zap.Strings("channelIDs", cc.ChannelIDs),
  5126  							zap.Error(err))
  5127  						continue
  5128  					}
  5129  
  5130  					err = m.communitiesManager.UpdateEncryptionKeysRequests(cc.Community.ID(), cc.ChannelIDs)
  5131  					if err != nil {
  5132  						logger.Error("failed to update channels' encryption keys requests",
  5133  							zap.String("communityID", cc.Community.IDString()),
  5134  							zap.Strings("channelIDs", cc.ChannelIDs),
  5135  							zap.Error(err))
  5136  					}
  5137  				}
  5138  
  5139  			case <-m.quit:
  5140  				return
  5141  			}
  5142  		}
  5143  	}()
  5144  }