From daa926f74859bc9f9aae37b6b0484b4aa40656ec Mon Sep 17 00:00:00 2001 From: Jonathan Rainville Date: Tue, 14 Mar 2023 16:12:47 -0400 Subject: [PATCH] refactor(chat/api): change getChats to getChannelGroups Also adds getChannelGroupByID --- protocol/chat.go | 4 + services/chat/api.go | 220 +++++++++++++++++++++++------ services/chat/api_group_chats.go | 6 +- services/chat/api_send_messages.go | 2 +- 4 files changed, 181 insertions(+), 51 deletions(-) diff --git a/protocol/chat.go b/protocol/chat.go index 02dc063c7..3523decc2 100644 --- a/protocol/chat.go +++ b/protocol/chat.go @@ -228,6 +228,10 @@ func (c *Chat) PrivateGroupChat() bool { return c.ChatType == ChatTypePrivateGroupChat } +func (c *Chat) IsActivePersonalChat() bool { + return c.Active && (c.OneToOne() || c.PrivateGroupChat() && c.Public()) && c.CommunityID == "" +} + func (c *Chat) CommunityChatID() string { if c.ChatType != ChatTypeCommunityChat { return c.ID diff --git a/services/chat/api.go b/services/chat/api.go index 4a24dcb01..8a31154a9 100644 --- a/services/chat/api.go +++ b/services/chat/api.go @@ -101,6 +101,8 @@ type ChannelGroup struct { BanList []string `json:"banList"` Encrypted bool `json:"encrypted"` CommunityTokensMetadata []*protobuf.CommunityTokenMetadata `json:"communityTokensMetadata"` + UnviewedMessagesCount int `json:"unviewedMessagesCount"` + UnviewedMentionsCount int `json:"unviewedMentionsCount"` } func NewAPI(service *Service) *API { @@ -124,7 +126,7 @@ func unique(communities []*communities.Community) (result []*communities.Communi return result } -func (api *API) GetChats(ctx context.Context) (map[string]ChannelGroup, error) { +func (api *API) GetChannelGroups(ctx context.Context) (map[string]ChannelGroup, error) { joinedCommunities, err := api.s.messenger.JoinedCommunities() if err != nil { return nil, err @@ -134,12 +136,24 @@ func (api *API) GetChats(ctx context.Context) (map[string]ChannelGroup, error) { return nil, err } - channels := api.s.messenger.Chats() - pubKey := types.EncodeHex(crypto.FromECDSAPub(api.s.messenger.IdentityPublicKey())) result := make(map[string]ChannelGroup) + // Get chats from cache to get unviewed messages counts + channels := api.s.messenger.Chats() + totalUnviewedMessageCount := 0 + totalUnviewedMentionsCount := 0 + + for _, chat := range channels { + if !chat.IsActivePersonalChat() { + continue + } + + totalUnviewedMessageCount += int(chat.UnviewedMessagesCount) + totalUnviewedMentionsCount += int(chat.UnviewedMentionsCount) + } + result[pubKey] = ChannelGroup{ Type: Personal, Name: "", @@ -157,21 +171,23 @@ func (api *API) GetChats(ctx context.Context) (map[string]ChannelGroup, error) { Permissions: &protobuf.CommunityPermissions{}, Muted: false, CommunityTokensMetadata: []*protobuf.CommunityTokenMetadata{}, - } - - for _, chat := range channels { - if !chat.Active || (!chat.OneToOne() && !chat.PrivateGroupChat() && !chat.Public()) || chat.CommunityID != "" { - continue - } - - c, err := api.toAPIChat(chat, nil, pubKey) - if err != nil { - return nil, err - } - result[pubKey].Chats[chat.ID] = c + UnviewedMessagesCount: totalUnviewedMessageCount, + UnviewedMentionsCount: totalUnviewedMentionsCount, } for _, community := range unique(append(joinedCommunities, spectatedCommunities...)) { + totalUnviewedMessageCount = 0 + totalUnviewedMentionsCount = 0 + + for _, chat := range channels { + if chat.CommunityID != community.IDString() || !chat.Active { + continue + } + + totalUnviewedMessageCount += int(chat.UnviewedMessagesCount) + totalUnviewedMentionsCount += int(chat.UnviewedMentionsCount) + } + chGrp := ChannelGroup{ Type: Community, Name: community.Name(), @@ -192,32 +208,138 @@ func (api *API) GetChats(ctx context.Context) (map[string]ChannelGroup, error) { BanList: community.Description().BanList, Encrypted: community.Encrypted(), CommunityTokensMetadata: community.Description().CommunityTokensMetadata, + UnviewedMessagesCount: totalUnviewedMessageCount, + UnviewedMentionsCount: totalUnviewedMentionsCount, } for t, i := range community.Images() { chGrp.Images[t] = images.IdentityImage{Name: t, Payload: i.Payload} } - for _, cat := range community.Categories() { - chGrp.Categories[cat.CategoryId] = communities.CommunityCategory{ - ID: cat.CategoryId, - Name: cat.Name, - Position: int(cat.Position), - } + result[community.IDString()] = chGrp + } + + return result, nil +} + +func (api *API) GetChatsByChannelGroupID(ctx context.Context, channelGroupID string) (*ChannelGroup, error) { + pubKey := types.EncodeHex(crypto.FromECDSAPub(api.s.messenger.IdentityPublicKey())) + + if pubKey == channelGroupID { + result := &ChannelGroup{ + Type: Personal, + Name: "", + Images: make(map[string]images.IdentityImage), + Color: "", + Chats: make(map[string]*Chat), + Categories: make(map[string]communities.CommunityCategory), + EnsName: "", // Not implemented yet in communities + Admin: true, + Verified: true, + Description: "", + IntroMessage: "", + OutroMessage: "", + Tags: []communities.CommunityTag{}, + Permissions: &protobuf.CommunityPermissions{}, + Muted: false, + CommunityTokensMetadata: []*protobuf.CommunityTokenMetadata{}, } + channels := api.s.messenger.Chats() + for _, chat := range channels { - if chat.CommunityID == community.IDString() && chat.Active { - c, err := api.toAPIChat(chat, community, pubKey) - if err != nil { - return nil, err - } - - chGrp.Chats[c.ID] = c + if !chat.IsActivePersonalChat() { + continue } + + c, err := api.toAPIChat(chat, nil, pubKey, true) + if err != nil { + return nil, err + } + result.Chats[chat.ID] = c } - result[community.IDString()] = chGrp + return result, nil + } + + joinedCommunities, err := api.s.messenger.JoinedCommunities() + if err != nil { + return nil, err + } + + found := false + var community *communities.Community + for _, comm := range joinedCommunities { + if comm.IDString() == channelGroupID { + community = comm + found = true + break + } + } + + if !found { + spectatedCommunities, err := api.s.messenger.SpectatedCommunities() + if err != nil { + return nil, err + } + + for _, comm := range spectatedCommunities { + if comm.IDString() == channelGroupID { + community = comm + found = true + break + } + } + } + + if !found { + return nil, ErrCommunityNotFound + } + + result := &ChannelGroup{ + Type: Community, + Name: community.Name(), + Color: community.Color(), + Images: make(map[string]images.IdentityImage), + Chats: make(map[string]*Chat), + Categories: make(map[string]communities.CommunityCategory), + Admin: community.IsAdmin(), + Verified: community.Verified(), + Description: community.DescriptionText(), + IntroMessage: community.IntroMessage(), + OutroMessage: community.OutroMessage(), + Tags: community.Tags(), + Permissions: community.Description().Permissions, + Members: community.Description().Members, + CanManageUsers: community.CanManageUsers(community.MemberIdentity()), + Muted: community.Muted(), + BanList: community.Description().BanList, + Encrypted: community.Encrypted(), + CommunityTokensMetadata: community.Description().CommunityTokensMetadata, + } + + for t, i := range community.Images() { + result.Images[t] = images.IdentityImage{Name: t, Payload: i.Payload} + } + + for _, cat := range community.Categories() { + result.Categories[cat.CategoryId] = communities.CommunityCategory{ + ID: cat.CategoryId, + Name: cat.Name, + Position: int(cat.Position), + } + } + + channels := api.s.messenger.Chats() + for _, chat := range channels { + if chat.CommunityID == community.IDString() && chat.Active { + c, err := api.toAPIChat(chat, community, pubKey, true) + if err != nil { + return nil, err + } + + result.Chats[c.ID] = c + } } return result, nil @@ -234,7 +356,7 @@ func (api *API) GetChat(ctx context.Context, communityID types.HexBytes, chatID return nil, ErrChatNotFound } - result, err := api.toAPIChat(messengerChat, community, pubKey) + result, err := api.toAPIChat(messengerChat, community, pubKey, false) if err != nil { return nil, err } @@ -264,15 +386,10 @@ func (api *API) JoinChat(ctx context.Context, communityID types.HexBytes, chatID pubKey := types.EncodeHex(crypto.FromECDSAPub(api.s.messenger.IdentityPublicKey())) - return api.toAPIChat(response.Chats()[0], nil, pubKey) + return api.toAPIChat(response.Chats()[0], nil, pubKey, false) } -func (api *API) toAPIChat(protocolChat *protocol.Chat, community *communities.Community, pubKey string) (*Chat, error) { - pinnedMessages, cursor, err := api.s.messenger.PinnedMessageByChatID(protocolChat.ID, "", -1) - if err != nil { - return nil, err - } - +func (api *API) toAPIChat(protocolChat *protocol.Chat, community *communities.Community, pubKey string, onlyChat bool) (*Chat, error) { chat := &Chat{ ID: strings.TrimPrefix(protocolChat.ID, protocolChat.CommunityID), Name: protocolChat.Name, @@ -309,23 +426,32 @@ func (api *API) toAPIChat(protocolChat *protocol.Chat, community *communities.Co chat.Name = "" // Emptying since it contains non useful data } - if len(pinnedMessages) != 0 { - chat.PinnedMessages = &PinnedMessages{ - Cursor: cursor, - PinnedMessages: pinnedMessages, + if !onlyChat { + pinnedMessages, cursor, err := api.s.messenger.PinnedMessageByChatID(protocolChat.ID, "", -1) + if err != nil { + return nil, err + } + + if len(pinnedMessages) != 0 { + chat.PinnedMessages = &PinnedMessages{ + Cursor: cursor, + PinnedMessages: pinnedMessages, + } } } - err = chat.populateCommunityFields(community) + err := chat.populateCommunityFields(community) if err != nil { return nil, err } - chatMembers, err := getChatMembers(protocolChat, community, pubKey) - if err != nil { - return nil, err + if !onlyChat { + chatMembers, err := getChatMembers(protocolChat, community, pubKey) + if err != nil { + return nil, err + } + chat.Members = chatMembers } - chat.Members = chatMembers return chat, nil } @@ -470,5 +596,5 @@ func (api *API) EditChat(ctx context.Context, communityID types.HexBytes, chatID } pubKey := types.EncodeHex(crypto.FromECDSAPub(api.s.messenger.IdentityPublicKey())) - return api.toAPIChat(response.Chats()[0], nil, pubKey) + return api.toAPIChat(response.Chats()[0], nil, pubKey, false) } diff --git a/services/chat/api_group_chats.go b/services/chat/api_group_chats.go index f74abf7d5..f6b6cd906 100644 --- a/services/chat/api_group_chats.go +++ b/services/chat/api_group_chats.go @@ -43,7 +43,7 @@ func (api *API) CreateOneToOneChat(ctx context.Context, communityID types.HexByt return nil, err } - chat, err := api.toAPIChat(response.Chats()[0], nil, pubKey) + chat, err := api.toAPIChat(response.Chats()[0], nil, pubKey, false) if err != nil { return nil, err } @@ -178,7 +178,7 @@ func (api *API) StartGroupChat(ctx context.Context, communityID types.HexBytes, } } - chat, err := api.toAPIChat(response.Chats()[0], nil, pubKey) + chat, err := api.toAPIChat(response.Chats()[0], nil, pubKey, false) if err != nil { return nil, err } @@ -191,7 +191,7 @@ func (api *API) StartGroupChat(ctx context.Context, communityID types.HexBytes, } func (api *API) toGroupChatResponse(pubKey string, response *protocol.MessengerResponse) (*GroupChatResponse, error) { - chat, err := api.toAPIChat(response.Chats()[0], nil, pubKey) + chat, err := api.toAPIChat(response.Chats()[0], nil, pubKey, false) if err != nil { return nil, err } diff --git a/services/chat/api_send_messages.go b/services/chat/api_send_messages.go index d9797341a..4156b2e9b 100644 --- a/services/chat/api_send_messages.go +++ b/services/chat/api_send_messages.go @@ -55,7 +55,7 @@ func (api *API) toSendMessageResponse(response *protocol.MessengerResponse) (*Se } pubKey := types.EncodeHex(crypto.FromECDSAPub(api.s.messenger.IdentityPublicKey())) - chat, err := api.toAPIChat(protocolChat, community, pubKey) + chat, err := api.toAPIChat(protocolChat, community, pubKey, false) if err != nil { return nil, err }