diff --git a/cmd/ping-community/main.go b/cmd/ping-community/main.go index 8e0d37751..1af3b1122 100644 --- a/cmd/ping-community/main.go +++ b/cmd/ping-community/main.go @@ -155,7 +155,12 @@ func main() { } } - community, err := messenger.RequestCommunityInfoFromMailserver(*communityID, shard, true) + community, err := messenger.FetchCommunity(&protocol.FetchCommunityRequest{ + CommunityKey: *communityID, + Shard: shard, + TryDatabase: true, + WaitForResponse: true, + }) if err != nil { logger.Error("community error", "error", err) diff --git a/protocol/communities_messenger_test.go b/protocol/communities_messenger_test.go index 9ced927e9..2cf0515ad 100644 --- a/protocol/communities_messenger_test.go +++ b/protocol/communities_messenger_test.go @@ -3331,11 +3331,11 @@ func (s *MessengerCommunitiesSuite) TestGetCommunityIdFromKey() { privateKey := "0x3f932031cb5f94ba7eb8ab4c824c3677973ab01fde65d1b89e0b3f470003a2cd" // Public key returns the same - communityID := s.bob.GetCommunityIDFromKey(publicKey) + communityID := GetCommunityIDFromKey(publicKey) s.Require().Equal(communityID, publicKey) // Private key returns the public key - communityID = s.bob.GetCommunityIDFromKey(privateKey) + communityID = GetCommunityIDFromKey(privateKey) s.Require().Equal(communityID, publicKey) } diff --git a/protocol/linkpreview_unfurler_status.go b/protocol/linkpreview_unfurler_status.go index e6c42ec92..f9c19545d 100644 --- a/protocol/linkpreview_unfurler_status.go +++ b/protocol/linkpreview_unfurler_status.go @@ -92,9 +92,14 @@ func (u *StatusUnfurler) fillCommunityImages(community *communities.Community, i return nil } -func (u *StatusUnfurler) buildCommunityData(communityID string) (*communities.Community, *common.StatusCommunityLinkPreview, error) { +func (u *StatusUnfurler) buildCommunityData(communityID string, shard *common.Shard) (*communities.Community, *common.StatusCommunityLinkPreview, error) { // This automatically checks the database - community, err := u.m.RequestCommunityInfoFromMailserver(communityID, nil, true) + community, err := u.m.FetchCommunity(&FetchCommunityRequest{ + CommunityKey: communityID, + Shard: shard, + TryDatabase: true, + WaitForResponse: true, + }) if err != nil { return nil, nil, fmt.Errorf("failed to get community info for communityID '%s': %w", communityID, err) @@ -120,8 +125,8 @@ func (u *StatusUnfurler) buildCommunityData(communityID string) (*communities.Co return community, c, nil } -func (u *StatusUnfurler) buildChannelData(channelUUID string, communityID string) (*common.StatusCommunityChannelLinkPreview, error) { - community, communityData, err := u.buildCommunityData(communityID) +func (u *StatusUnfurler) buildChannelData(channelUUID string, communityID string, communityShard *common.Shard) (*common.StatusCommunityChannelLinkPreview, error) { + community, communityData, err := u.buildCommunityData(communityID, communityShard) if err != nil { return nil, fmt.Errorf("failed to build channel community data: %w", err) } @@ -169,7 +174,7 @@ func (u *StatusUnfurler) Unfurl() (*common.StatusLinkPreview, error) { if resp.Community == nil { return preview, fmt.Errorf("channel community can't be empty") } - preview.Channel, err = u.buildChannelData(resp.Channel.ChannelUUID, resp.Community.CommunityID) + preview.Channel, err = u.buildChannelData(resp.Channel.ChannelUUID, resp.Community.CommunityID, resp.Shard) if err != nil { return nil, fmt.Errorf("error when building channel data: %w", err) } @@ -177,7 +182,7 @@ func (u *StatusUnfurler) Unfurl() (*common.StatusLinkPreview, error) { } if resp.Community != nil { - _, preview.Community, err = u.buildCommunityData(resp.Community.CommunityID) + _, preview.Community, err = u.buildCommunityData(resp.Community.CommunityID, resp.Shard) if err != nil { return nil, fmt.Errorf("error when building community data: %w", err) } diff --git a/protocol/messenger_communities.go b/protocol/messenger_communities.go index 9b23a24f8..c826ca0fe 100644 --- a/protocol/messenger_communities.go +++ b/protocol/messenger_communities.go @@ -67,6 +67,36 @@ const ( maxChunkSizeBytes = 1500000 ) +type FetchCommunityRequest struct { + // CommunityKey should be either a public or a private community key + CommunityKey string `json:"communityKey"` + Shard *common.Shard `json:"shard"` + TryDatabase bool `json:"tryDatabase"` + WaitForResponse bool `json:"waitForResponse"` +} + +func (r *FetchCommunityRequest) Validate() error { + if len(r.CommunityKey) <= 2 { + return fmt.Errorf("community key is too short") + } + return nil +} + +func (r *FetchCommunityRequest) getCommunityID() string { + return GetCommunityIDFromKey(r.CommunityKey) +} + +func GetCommunityIDFromKey(communityKey string) string { + // Check if the key is a private key. strip the 0x at the start + if privateKey, err := crypto.HexToECDSA(communityKey[2:]); err == nil { + // It is a privateKey + return types.HexBytes(crypto.CompressPubkey(&privateKey.PublicKey)).String() + } + + // Not a private key, use the public key + return communityKey +} + func (m *Messenger) publishOrg(org *communities.Community) error { if org == nil { return nil @@ -2326,7 +2356,12 @@ func (m *Messenger) ImportCommunity(ctx context.Context, key *ecdsa.PrivateKey) return nil, err } - _, err = m.RequestCommunityInfoFromMailserver(community.IDString(), community.Shard(), false) + _, err = m.FetchCommunity(&FetchCommunityRequest{ + CommunityKey: community.IDString(), + Shard: community.Shard(), + TryDatabase: false, + WaitForResponse: true, + }) if err != nil { // TODO In the future we should add a mechanism to re-apply next steps (adding owner, joining) // if there is no connection with mailserver. Otherwise changes will be overwritten. @@ -2592,56 +2627,37 @@ func (m *Messenger) findCommunityInfoFromDB(communityID string) (*communities.Co return community, nil } -func (m *Messenger) GetCommunityIDFromKey(communityKey string) string { - // Check if the key is a private key. strip the 0x at the start - privateKey, err := crypto.HexToECDSA(communityKey[2:]) - communityID := "" - if err != nil { - // Not a private key, use the public key - communityID = communityKey - } else { - // It is a privateKey - communityID = types.HexBytes(crypto.CompressPubkey(&privateKey.PublicKey)).String() +// FetchCommunity installs filter for community and requests its details +// from mailserver. +// +// If `request.TryDatabase` is true, it first looks for community in database, +// and requests from mailserver only if it wasn't found locally. +// If `request.WaitForResponse` is true, it waits until it has the community before returning it. +// If `request.WaitForResponse` is false, it installs filter for community and requests its details +// from mailserver. When response received it will be passed through signals handler. +func (m *Messenger) FetchCommunity(request *FetchCommunityRequest) (*communities.Community, error) { + if err := request.Validate(); err != nil { + return nil, fmt.Errorf("invalid request: %w", err) } - return communityID -} + communityID := request.getCommunityID() -// RequestCommunityInfoFromMailserver installs filter for community and requests its details -// from mailserver. It waits until it has the community before returning it. -// If useDatabase is true, it searches for community in database and does not request mailserver. -func (m *Messenger) RequestCommunityInfoFromMailserver(privateOrPublicKey string, shard *common.Shard, useDatabase bool) (*communities.Community, error) { - communityID := m.GetCommunityIDFromKey(privateOrPublicKey) - if useDatabase { + if request.TryDatabase { community, err := m.findCommunityInfoFromDB(communityID) if err != nil { return nil, err } if community != nil { + if !request.WaitForResponse { + m.config.messengerSignalsHandler.CommunityInfoFound(community) + } return community, nil } } - return m.requestCommunityInfoFromMailserver(communityID, shard, true) + return m.requestCommunityInfoFromMailserver(communityID, request.Shard, request.WaitForResponse) } -// RequestCommunityInfoFromMailserverAsync installs filter for community and requests its details -// from mailserver. When response received it will be passed through signals handler -func (m *Messenger) RequestCommunityInfoFromMailserverAsync(privateOrPublicKey string, shard *common.Shard) error { - communityID := m.GetCommunityIDFromKey(privateOrPublicKey) - - community, err := m.findCommunityInfoFromDB(communityID) - if err != nil { - return err - } - if community != nil { - m.config.messengerSignalsHandler.CommunityInfoFound(community) - return nil - } - _, err = m.requestCommunityInfoFromMailserver(communityID, shard, false) - return err -} - -// RequestCommunityInfoFromMailserver installs filter for community and requests its details +// requestCommunityInfoFromMailserver installs filter for community and requests its details // from mailserver. When response received it will be passed through signals handler func (m *Messenger) requestCommunityInfoFromMailserver(communityID string, shard *common.Shard, waitForResponse bool) (*communities.Community, error) { @@ -2696,6 +2712,11 @@ func (m *Messenger) requestCommunityInfoFromMailserver(communityID string, shard return nil, err } + m.logger.Info("mailserver request performed", + zap.String("communityID", communityID), + zap.Bool("waitForResponse", waitForResponse), + ) + if !waitForResponse { return nil, nil } @@ -2712,6 +2733,9 @@ func (m *Messenger) requestCommunityInfoFromMailserver(communityID string, shard return nil, err } if community != nil && community.Name() != "" && community.DescriptionText() != "" { + m.logger.Debug("community info found", + zap.String("communityID", communityID), + zap.String("displayName", community.Name())) return community, nil } @@ -2722,7 +2746,7 @@ func (m *Messenger) requestCommunityInfoFromMailserver(communityID string, shard } } -// RequestCommunityInfoFromMailserver installs filter for community and requests its details +// requestCommunitiesFromMailserver installs filter for community and requests its details // from mailserver. When response received it will be passed through signals handler func (m *Messenger) requestCommunitiesFromMailserver(communities []communities.CommunityShard) { m.requestedCommunitiesLock.Lock() diff --git a/services/ext/api.go b/services/ext/api.go index a637971a9..cdba98a7c 100644 --- a/services/ext/api.go +++ b/services/ext/api.go @@ -463,7 +463,7 @@ func (api *PublicAPI) ImportCommunity(ctx context.Context, hexPrivateKey string) // GetCommunityPublicKeyFromPrivateKey gets the community's public key from its private key func (api *PublicAPI) GetCommunityPublicKeyFromPrivateKey(ctx context.Context, hexPrivateKey string) string { - publicKey := api.service.messenger.GetCommunityIDFromKey(hexPrivateKey) + publicKey := protocol.GetCommunityIDFromKey(hexPrivateKey) return publicKey } @@ -1205,22 +1205,58 @@ func (api *PublicAPI) EnsVerified(pk, ensName string) error { return api.service.messenger.ENSVerified(pk, ensName) } -// DEPRECATED +// Deprecated: RequestCommunityInfoFromMailserver is deprecated in favor of +// configurable FetchCommunity. func (api *PublicAPI) RequestCommunityInfoFromMailserver(communityID string) (*communities.Community, error) { - return api.service.messenger.RequestCommunityInfoFromMailserver(communityID, nil, true) + request := &protocol.FetchCommunityRequest{ + CommunityKey: communityID, + Shard: nil, + TryDatabase: true, + WaitForResponse: true, + } + return api.FetchCommunity(request) } +// Deprecated: RequestCommunityInfoFromMailserverWithShard is deprecated in favor of +// configurable FetchCommunity. func (api *PublicAPI) RequestCommunityInfoFromMailserverWithShard(communityID string, shard *common.Shard) (*communities.Community, error) { - return api.service.messenger.RequestCommunityInfoFromMailserver(communityID, shard, true) + request := &protocol.FetchCommunityRequest{ + CommunityKey: communityID, + Shard: shard, + TryDatabase: true, + WaitForResponse: true, + } + return api.FetchCommunity(request) } -// DEPRECATED +// Deprecated: RequestCommunityInfoFromMailserverAsync is deprecated in favor of +// configurable FetchCommunity. func (api *PublicAPI) RequestCommunityInfoFromMailserverAsync(communityID string) error { - return api.service.messenger.RequestCommunityInfoFromMailserverAsync(communityID, nil) + request := &protocol.FetchCommunityRequest{ + CommunityKey: communityID, + Shard: nil, + TryDatabase: true, + WaitForResponse: false, + } + _, err := api.FetchCommunity(request) + return err } +// Deprecated: RequestCommunityInfoFromMailserverAsyncWithShard is deprecated in favor of +// configurable FetchCommunity. func (api *PublicAPI) RequestCommunityInfoFromMailserverAsyncWithShard(communityID string, shard *common.Shard) error { - return api.service.messenger.RequestCommunityInfoFromMailserverAsync(communityID, shard) + request := &protocol.FetchCommunityRequest{ + CommunityKey: communityID, + Shard: shard, + TryDatabase: true, + WaitForResponse: false, + } + _, err := api.FetchCommunity(request) + return err +} + +func (api *PublicAPI) FetchCommunity(request *protocol.FetchCommunityRequest) (*communities.Community, error) { + return api.service.messenger.FetchCommunity(request) } func (api *PublicAPI) ActivityCenterNotifications(request protocol.ActivityCenterNotificationsRequest) (*protocol.ActivityCenterPaginationResponse, error) { diff --git a/services/ext/service.go b/services/ext/service.go index 281ceb108..238f2cec4 100644 --- a/services/ext/service.go +++ b/services/ext/service.go @@ -671,7 +671,12 @@ func (s *Service) fetchCommunity(communityID string) (*communities.Community, er // communities that have specific shards var shard *common.Shard = nil // TODO: build this with info from token - community, err := s.messenger.RequestCommunityInfoFromMailserver(communityID, shard, true) + community, err := s.messenger.FetchCommunity(&protocol.FetchCommunityRequest{ + CommunityKey: communityID, + Shard: shard, + TryDatabase: true, + WaitForResponse: true, + }) if err != nil { return nil, err diff --git a/services/status/service.go b/services/status/service.go index b0a11640c..cf9a1c5a1 100644 --- a/services/status/service.go +++ b/services/status/service.go @@ -75,7 +75,12 @@ func (p *PublicAPI) CommunityInfo(communityID types.HexBytes, shard *common.Shar return nil, ErrNotInitialized } - community, err := p.service.messenger.RequestCommunityInfoFromMailserver(communityID.String(), shard, true) + community, err := p.service.messenger.FetchCommunity(&protocol.FetchCommunityRequest{ + CommunityKey: communityID.String(), + Shard: shard, + TryDatabase: true, + WaitForResponse: true, + }) if err != nil { return nil, err }