diff --git a/internal/cache/cache.go b/internal/cache/cache.go deleted file mode 100644 index 617e075c6..000000000 --- a/internal/cache/cache.go +++ /dev/null @@ -1,156 +0,0 @@ -// Copyright © 2023 OpenIM SDK. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package cache - -import ( - "context" - "github.com/openimsdk/openim-sdk-core/v3/internal/friend" - "github.com/openimsdk/openim-sdk-core/v3/internal/user" - "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" - "github.com/openimsdk/openim-sdk-core/v3/pkg/sdkerrs" - "sync" - - userPb "github.com/OpenIMSDK/protocol/user" -) - -type UserInfo struct { - Nickname string - FaceURL string -} -type Cache struct { - user *user.User - friend *friend.Friend - userMap sync.Map - conversationMap sync.Map - SubscriptionStatusMap sync.Map -} - -func NewCache(user *user.User, friend *friend.Friend) *Cache { - return &Cache{user: user, friend: friend} -} -func (c *Cache) UpdateStatus(userID string, statusMap *userPb.OnlineStatus) { - c.SubscriptionStatusMap.Store(userID, statusMap) -} - -func (c *Cache) Update(userID, faceURL, nickname string) { - c.userMap.Store(userID, UserInfo{FaceURL: faceURL, Nickname: nickname}) -} -func (c *Cache) UpdateConversation(conversation model_struct.LocalConversation) { - c.conversationMap.Store(conversation.ConversationID, conversation) -} -func (c *Cache) UpdateConversations(conversations []*model_struct.LocalConversation) { - for _, conversation := range conversations { - c.conversationMap.Store(conversation.ConversationID, *conversation) - } -} -func (c *Cache) GetAllConversations() (conversations []*model_struct.LocalConversation) { - c.conversationMap.Range(func(key, value interface{}) bool { - temp := value.(model_struct.LocalConversation) - conversations = append(conversations, &temp) - return true - }) - return conversations -} -func (c *Cache) GetAllHasUnreadMessageConversations() (conversations []*model_struct.LocalConversation) { - c.conversationMap.Range(func(key, value interface{}) bool { - temp := value.(model_struct.LocalConversation) - if temp.UnreadCount > 0 { - conversations = append(conversations, &temp) - } - return true - }) - return conversations -} - -func (c *Cache) GetConversation(conversationID string) model_struct.LocalConversation { - var result model_struct.LocalConversation - conversation, ok := c.conversationMap.Load(conversationID) - if ok { - result = conversation.(model_struct.LocalConversation) - } - return result -} - -func (c *Cache) BatchGetUserNameAndFaceURL(ctx context.Context, userIDs ...string) (map[string]UserInfo, error) { - m := make(map[string]UserInfo) - if len(userIDs) == 0 { - return m, nil - } - var notCachedUserIDs, notCachedAndNotFriendUserIDs []string - for _, userID := range userIDs { - if value, ok := c.userMap.Load(userID); ok { - user := value.(UserInfo) - m[userID] = user - } else { - notCachedUserIDs = append(notCachedUserIDs, userID) - } - } - for _, notCachedUserID := range notCachedUserIDs { - localFriend, err := c.friend.Db().GetFriendInfoByFriendUserID(ctx, notCachedUserID) - if err == nil { - userInfo := UserInfo{FaceURL: localFriend.FaceURL} - if localFriend.Remark != "" { - userInfo.Nickname = localFriend.Remark - } else { - userInfo.Nickname = localFriend.Nickname - } - m[notCachedUserID] = userInfo - } else { - notCachedAndNotFriendUserIDs = append(notCachedAndNotFriendUserIDs, notCachedUserID) - } - } - - if len(notCachedAndNotFriendUserIDs) > 0 { - users, err := c.user.GetServerUserInfo(ctx, notCachedUserIDs) - if err != nil { - return nil, err - } - for _, user := range users { - userInfo := UserInfo{FaceURL: user.FaceURL, Nickname: user.Nickname} - m[user.UserID] = userInfo - c.userMap.Store(user.UserID, userInfo) - } - } - return m, nil -} - -func (c *Cache) GetUserNameAndFaceURL(ctx context.Context, userID string) (faceURL, name string, err error) { - //find in cache - if value, ok := c.userMap.Load(userID); ok { - info := value.(UserInfo) - return info.FaceURL, info.Nickname, nil - } - //get from local db - friendInfo, err := c.friend.Db().GetFriendInfoByFriendUserID(ctx, userID) - if err == nil { - faceURL = friendInfo.FaceURL - if friendInfo.Remark != "" { - name = friendInfo.Remark - } else { - name = friendInfo.Nickname - } - return faceURL, name, nil - } - //get from server db - users, err := c.user.GetServerUserInfo(ctx, []string{userID}) - if err != nil { - return "", "", err - } - if len(users) == 0 { - return "", "", sdkerrs.ErrUserIDNotFound.Wrap(userID) - } - c.userMap.Store(userID, UserInfo{FaceURL: users[0].FaceURL, Nickname: users[0].Nickname}) - return users[0].FaceURL, users[0].Nickname, nil -} diff --git a/internal/cache/cahe.go b/internal/cache/cahe.go new file mode 100644 index 000000000..ed719b1e7 --- /dev/null +++ b/internal/cache/cahe.go @@ -0,0 +1,72 @@ +package cache + +import "sync" + +// Cache is a Generic sync.Map structure. +type Cache[K comparable, V any] struct { + m sync.Map +} + +func NewCache[K comparable, V any]() *Cache[K, V] { + return &Cache[K, V]{} +} + +// Load returns the value stored in the map for a key, or nil if no value is present. +func (c *Cache[K, V]) Load(key K) (value V, ok bool) { + rawValue, ok := c.m.Load(key) + if !ok { + return + } + return rawValue.(V), ok +} + +// Store sets the value for a key. +func (c *Cache[K, V]) Store(key K, value V) { + c.m.Store(key, value) +} + +// StoreAll sets all value by f's key. +func (c *Cache[K, V]) StoreAll(f func(value V) K, values []V) { + for _, v := range values { + c.m.Store(f(v), v) + } +} + +// LoadOrStore returns the existing value for the key if present. +func (c *Cache[K, V]) LoadOrStore(key K, value V) (actual V, loaded bool) { + rawValue, loaded := c.m.LoadOrStore(key, value) + return rawValue.(V), loaded +} + +// Delete deletes the value for a key. +func (c *Cache[K, V]) Delete(key K) { + c.m.Delete(key) +} + +// DeleteAll deletes all values. +func (c *Cache[K, V]) DeleteAll() { + c.m.Range(func(key, value interface{}) bool { + c.m.Delete(key) + return true + }) +} + +// RangeAll returns all values in the map. +func (c *Cache[K, V]) RangeAll() (values []V) { + c.m.Range(func(rawKey, rawValue interface{}) bool { + values = append(values, rawValue.(V)) + return true + }) + return values +} + +// RangeCon returns values in the map that satisfy condition f. +func (c *Cache[K, V]) RangeCon(f func(key K, value V) bool) (values []V) { + c.m.Range(func(rawKey, rawValue interface{}) bool { + if f(rawKey.(K), rawValue.(V)) { + values = append(values, rawValue.(V)) + } + return true + }) + return values +} diff --git a/internal/conversation_msg/conversation_msg.go b/internal/conversation_msg/conversation_msg.go index 6982979d2..1ae7925c3 100644 --- a/internal/conversation_msg/conversation_msg.go +++ b/internal/conversation_msg/conversation_msg.go @@ -18,6 +18,7 @@ import ( "context" "encoding/json" "errors" + utils2 "github.com/OpenIMSDK/tools/utils" "github.com/openimsdk/openim-sdk-core/v3/internal/business" "github.com/openimsdk/openim-sdk-core/v3/internal/cache" "github.com/openimsdk/openim-sdk-core/v3/internal/file" @@ -33,6 +34,7 @@ import ( "github.com/openimsdk/openim-sdk-core/v3/pkg/db/db_interface" "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" sdk "github.com/openimsdk/openim-sdk-core/v3/pkg/sdk_params_callback" + "github.com/openimsdk/openim-sdk-core/v3/pkg/sdkerrs" "github.com/openimsdk/openim-sdk-core/v3/pkg/syncer" "github.com/OpenIMSDK/tools/log" @@ -65,7 +67,7 @@ type Conversation struct { file *file.File business *business.Business messageController *MessageController - cache *cache.Cache + cache *cache.Cache[string, *model_struct.LocalConversation] full *full.Full maxSeqRecorder MaxSeqRecorder IsExternalExtensions bool @@ -106,7 +108,7 @@ func NewConversation(ctx context.Context, longConnMgr *interaction.LongConnMgr, ch chan common.Cmd2Value, friend *friend.Friend, group *group.Group, user *user.User, conversationListener open_im_sdk_callback.OnConversationListener, - msgListener open_im_sdk_callback.OnAdvancedMsgListener, business *business.Business, cache *cache.Cache, full *full.Full, file *file.File) *Conversation { + msgListener open_im_sdk_callback.OnAdvancedMsgListener, business *business.Business, full *full.Full, file *file.File) *Conversation { info := ccontext.Info(ctx) n := &Conversation{db: db, LongConnMgr: longConnMgr, @@ -127,7 +129,7 @@ func NewConversation(ctx context.Context, longConnMgr *interaction.LongConnMgr, n.SetMsgListener(msgListener) n.SetConversationListener(conversationListener) n.initSyncer() - n.cache = cache + n.cache = cache.NewCache[string, *model_struct.LocalConversation]() return n } @@ -915,7 +917,7 @@ func mapConversationToList(m map[string]*model_struct.LocalConversation) (cs []* func (c *Conversation) addFaceURLAndName(ctx context.Context, lc *model_struct.LocalConversation) error { switch lc.ConversationType { case constant.SingleChatType, constant.NotificationChatType: - faceUrl, name, err := c.cache.GetUserNameAndFaceURL(ctx, lc.UserID) + faceUrl, name, err := c.getUserNameAndFaceURL(ctx, lc.UserID) if err != nil { return err } @@ -943,7 +945,7 @@ func (c *Conversation) batchAddFaceURLAndName(ctx context.Context, conversations groupIDs = append(groupIDs, conversation.GroupID) } } - users, err := c.cache.BatchGetUserNameAndFaceURL(ctx, userIDs...) + users, err := c.batchGetUserNameAndFaceURL(ctx, userIDs...) if err != nil { return err } @@ -974,3 +976,76 @@ func (c *Conversation) batchAddFaceURLAndName(ctx context.Context, conversations } return nil } +func (c *Conversation) batchGetUserNameAndFaceURL(ctx context.Context, userIDs ...string) (map[string]*user.BasicInfo, + error) { + m := make(map[string]*user.BasicInfo) + var notCachedUserIDs []string + var notInFriend []string + + friendList, err := c.friend.Db().GetFriendInfoList(ctx, userIDs) + if err != nil { + log.ZWarn(ctx, "BatchGetUserNameAndFaceURL", err, "userIDs", userIDs) + notInFriend = userIDs + } else { + notInFriend = utils2.SliceSub(userIDs, utils2.Slice(friendList, func(e *model_struct.LocalFriend) string { + return e.FriendUserID + })) + } + for _, localFriend := range friendList { + userInfo := &user.BasicInfo{FaceURL: localFriend.FaceURL} + if localFriend.Remark != "" { + userInfo.Nickname = localFriend.Remark + } else { + userInfo.Nickname = localFriend.Nickname + } + m[localFriend.FriendUserID] = userInfo + } + + for _, userID := range notInFriend { + if value, ok := c.user.UserBasicCache.Load(userID); ok { + m[userID] = value + } else { + notCachedUserIDs = append(notCachedUserIDs, userID) + } + } + + if len(notCachedUserIDs) > 0 { + users, err := c.user.GetServerUserInfo(ctx, notCachedUserIDs) + if err != nil { + return nil, err + } + for _, u := range users { + userInfo := &user.BasicInfo{FaceURL: u.FaceURL, Nickname: u.Nickname} + m[u.UserID] = userInfo + c.user.UserBasicCache.Store(u.UserID, userInfo) + } + } + return m, nil +} +func (c *Conversation) getUserNameAndFaceURL(ctx context.Context, userID string) (faceURL, name string, err error) { + //find in cache + if value, ok := c.user.UserBasicCache.Load(userID); ok { + return value.FaceURL, value.Nickname, nil + } + //get from local db + friendInfo, err := c.friend.Db().GetFriendInfoByFriendUserID(ctx, userID) + if err == nil { + faceURL = friendInfo.FaceURL + if friendInfo.Remark != "" { + name = friendInfo.Remark + } else { + name = friendInfo.Nickname + } + return faceURL, name, nil + } + //get from server db + users, err := c.user.GetServerUserInfo(ctx, []string{userID}) + if err != nil { + return "", "", err + } + if len(users) == 0 { + return "", "", sdkerrs.ErrUserIDNotFound.Wrap(userID) + } + c.user.UserBasicCache.Store(userID, &user.BasicInfo{FaceURL: users[0].FaceURL, Nickname: users[0].Nickname}) + return users[0].FaceURL, users[0].Nickname, nil +} diff --git a/internal/conversation_msg/conversation_notification.go b/internal/conversation_msg/conversation_notification.go index edae1c3e1..94b7240b6 100644 --- a/internal/conversation_msg/conversation_notification.go +++ b/internal/conversation_msg/conversation_notification.go @@ -260,18 +260,6 @@ func (c *Conversation) doUpdateConversation(c2v common.Cmd2Value) { } case constant.SyncConversation: - c.SyncAllConversations(ctx) - err := c.SyncConversationUnreadCount(ctx) - if err != nil { - // log.Error(operationID, "reconn sync conversation unread count err", err.Error()) - } - totalUnreadCount, err := c.db.GetTotalUnreadMsgCountDB(ctx) - if err != nil { - // log.Error("internal", "TotalUnreadMessageChanged database err:", err.Error()) - } else { - c.ConversationListener.OnTotalUnreadMessageCountChanged(totalUnreadCount) - } - } } @@ -640,10 +628,7 @@ func (c *Conversation) doNotificationNew(c2v common.Cmd2Value) { log.ZError(ctx, "SyncConversationHashReadSeqs err", err) } //clear SubscriptionStatusMap - c.cache.SubscriptionStatusMap.Range(func(key, value interface{}) bool { - c.cache.SubscriptionStatusMap.Delete(key) - return true - }) + c.user.OnlineStatusCache.DeleteAll() for _, syncFunc := range []func(c context.Context) error{ c.user.SyncLoginUserInfo, c.friend.SyncAllBlackList, c.friend.SyncAllFriendList, c.friend.SyncAllFriendApplication, c.friend.SyncAllSelfFriendApplication, @@ -703,7 +688,7 @@ func (c *Conversation) doNotificationNew(c2v common.Cmd2Value) { if v.ContentType > constant.FriendNotificationBegin && v.ContentType < constant.FriendNotificationEnd { c.friend.DoNotification(ctx, v) } else if v.ContentType > constant.UserNotificationBegin && v.ContentType < constant.UserNotificationEnd { - c.user.DoNotification(ctx, v, c.cache.UpdateStatus) + c.user.DoNotification(ctx, v) } else if utils2.Contain(v.ContentType, constant.GroupApplicationRejectedNotification, constant.GroupApplicationAcceptedNotification, constant.JoinGroupApplicationNotification) { c.group.DoNotification(ctx, v) } else if v.ContentType > constant.SignalingNotificationBegin && v.ContentType < constant.SignalingNotificationEnd { diff --git a/internal/conversation_msg/read_drawing.go b/internal/conversation_msg/read_drawing.go index 0de148721..62ff52d6d 100644 --- a/internal/conversation_msg/read_drawing.go +++ b/internal/conversation_msg/read_drawing.go @@ -87,7 +87,8 @@ func (c *Conversation) markConversationMessageAsRead(ctx context.Context, conver log.ZWarn(ctx, "seqs is empty", nil, "conversationID", conversationID) return nil } - log.ZDebug(ctx, "markConversationMessageAsRead", "conversationID", conversationID, "seqs", seqs, "peerUserMaxSeq", peerUserMaxSeq, "maxSeq", maxSeq) + log.ZDebug(ctx, "markConversationMessageAsRead", "conversationID", conversationID, "seqs", + seqs, "peerUserMaxSeq", peerUserMaxSeq, "maxSeq", maxSeq) if err := c.markConversationAsReadSvr(ctx, conversationID, maxSeq, seqs); err != nil { return err } @@ -135,13 +136,15 @@ func (c *Conversation) markMessagesAsReadByMsgID(ctx context.Context, conversati return err } if err := c.db.DecrConversationUnreadCount(ctx, conversationID, decrCount); err != nil { - log.ZError(ctx, "decrConversationUnreadCount err", err, "conversationID", conversationID, "decrCount", decrCount) + log.ZError(ctx, "decrConversationUnreadCount err", err, "conversationID", conversationID, + "decrCount", decrCount) } c.unreadChangeTrigger(ctx, conversationID, hasReadSeq == maxSeq && msgs[0].SendID != c.loginUserID) return nil } -func (c *Conversation) getAsReadMsgMapAndList(ctx context.Context, msgs []*model_struct.LocalChatLog) (asReadMsgIDs []string, seqs []int64) { +func (c *Conversation) getAsReadMsgMapAndList(ctx context.Context, + msgs []*model_struct.LocalChatLog) (asReadMsgIDs []string, seqs []int64) { for _, msg := range msgs { if !msg.IsRead && msg.SendID != c.loginUserID { if msg.Seq == 0 { @@ -159,10 +162,13 @@ func (c *Conversation) getAsReadMsgMapAndList(ctx context.Context, msgs []*model func (c *Conversation) unreadChangeTrigger(ctx context.Context, conversationID string, latestMsgIsRead bool) { if latestMsgIsRead { - c.doUpdateConversation(common.Cmd2Value{Value: common.UpdateConNode{ConID: conversationID, Action: constant.UpdateLatestMessageChange, Args: []string{conversationID}}, Ctx: ctx}) + c.doUpdateConversation(common.Cmd2Value{Value: common.UpdateConNode{ConID: conversationID, + Action: constant.UpdateLatestMessageChange, Args: []string{conversationID}}, Ctx: ctx}) } - c.doUpdateConversation(common.Cmd2Value{Value: common.UpdateConNode{ConID: conversationID, Action: constant.ConChange, Args: []string{conversationID}}, Ctx: ctx}) - c.doUpdateConversation(common.Cmd2Value{Value: common.UpdateConNode{Action: constant.TotalUnreadMessageChanged}, Ctx: ctx}) + c.doUpdateConversation(common.Cmd2Value{Value: common.UpdateConNode{ConID: conversationID, + Action: constant.ConChange, Args: []string{conversationID}}, Ctx: ctx}) + c.doUpdateConversation(common.Cmd2Value{Value: common.UpdateConNode{Action: constant.TotalUnreadMessageChanged}, + Ctx: ctx}) } func (c *Conversation) doUnreadCount(ctx context.Context, conversation *model_struct.LocalConversation, hasReadSeq int64, seqs []int64) { diff --git a/internal/conversation_msg/revoke.go b/internal/conversation_msg/revoke.go index b286572d4..16551e218 100644 --- a/internal/conversation_msg/revoke.go +++ b/internal/conversation_msg/revoke.go @@ -50,7 +50,7 @@ func (c *Conversation) revokeMessage(ctx context.Context, tips *sdkws.RevokeMsgT var revokerRole int32 var revokerNickname string if tips.IsAdminRevoke || tips.SesstionType == constant.SingleChatType { - _, userName, err := c.cache.GetUserNameAndFaceURL(ctx, tips.RevokerUserID) + _, userName, err := c.getUserNameAndFaceURL(ctx, tips.RevokerUserID) if err != nil { log.ZError(ctx, "GetUserNameAndFaceURL failed", err, "tips", &tips) } else { diff --git a/internal/conversation_msg/sdk.go b/internal/conversation_msg/sdk.go index 19874d30d..bf644b60e 100644 --- a/internal/conversation_msg/sdk.go +++ b/internal/conversation_msg/sdk.go @@ -55,7 +55,11 @@ func (c *Conversation) GetConversationListSplit(ctx context.Context, offset, cou } func (c *Conversation) HideConversation(ctx context.Context, conversationID string) error { - return c.db.UpdateColumnsConversation(ctx, conversationID, map[string]interface{}{"latest_msg_send_time": 0}) + err := c.db.ResetConversation(ctx, conversationID) + if err != nil { + return err + } + return nil } func (c *Conversation) GetAtAllTag(_ context.Context) string { @@ -90,7 +94,7 @@ func (c *Conversation) GetOneConversation(ctx context.Context, sessionType int32 switch sessionType { case constant.SingleChatType: newConversation.UserID = sourceID - faceUrl, name, err := c.cache.GetUserNameAndFaceURL(ctx, sourceID) + faceUrl, name, err := c.getUserNameAndFaceURL(ctx, sourceID) if err != nil { return nil, err } @@ -127,20 +131,13 @@ func (c *Conversation) GetMultipleConversation(ctx context.Context, conversation } -func (c *Conversation) DeleteAllConversationFromLocal(ctx context.Context) error { +func (c *Conversation) HideAllConversations(ctx context.Context) error { err := c.db.ResetAllConversation(ctx) if err != nil { return err } return nil } -func (c *Conversation) DeleteConversationFromLocal(ctx context.Context, conversationID string) error { - err := c.db.ResetConversation(ctx, conversationID) - if err != nil { - return err - } - return nil -} func (c *Conversation) SetConversationDraft(ctx context.Context, conversationID, draftText string) error { if draftText != "" { @@ -345,7 +342,7 @@ func (c *Conversation) checkID(ctx context.Context, s *sdk_struct.MsgStruct, } if err != nil { t := time.Now() - faceUrl, name, err := c.cache.GetUserNameAndFaceURL(ctx, recvID) + faceUrl, name, err := c.getUserNameAndFaceURL(ctx, recvID) log.ZDebug(ctx, "GetUserNameAndFaceURL", "cost time", time.Since(t)) if err != nil { return nil, err @@ -984,7 +981,7 @@ func (c *Conversation) InsertSingleMessageToLocalStorage(ctx context.Context, s } var conversation model_struct.LocalConversation if sendID != c.loginUserID { - faceUrl, name, err := c.cache.GetUserNameAndFaceURL(ctx, sendID) + faceUrl, name, err := c.getUserNameAndFaceURL(ctx, sendID) if err != nil { //log.Error(operationID, "GetUserNameAndFaceURL err", err.Error(), sendID) } @@ -1000,7 +997,7 @@ func (c *Conversation) InsertSingleMessageToLocalStorage(ctx context.Context, s conversation.ConversationID = c.getConversationIDBySessionType(recvID, constant.SingleChatType) _, err := c.db.GetConversation(ctx, conversation.ConversationID) if err != nil { - faceUrl, name, err := c.cache.GetUserNameAndFaceURL(ctx, recvID) + faceUrl, name, err := c.getUserNameAndFaceURL(ctx, recvID) if err != nil { return nil, err } @@ -1041,7 +1038,7 @@ func (c *Conversation) InsertGroupMessageToLocalStorage(ctx context.Context, s * conversation.ConversationID = c.getConversationIDBySessionType(groupID, int(conversation.ConversationType)) if sendID != c.loginUserID { - faceUrl, name, err := c.cache.GetUserNameAndFaceURL(ctx, sendID) + faceUrl, name, err := c.getUserNameAndFaceURL(ctx, sendID) if err != nil { // log.Error("", "getUserNameAndFaceUrlByUid err", err.Error(), sendID) } diff --git a/internal/conversation_msg/sync.go b/internal/conversation_msg/sync.go index c3cdb75ea..ce955eaab 100644 --- a/internal/conversation_msg/sync.go +++ b/internal/conversation_msg/sync.go @@ -43,11 +43,6 @@ func (c *Conversation) SyncConversationsAndTriggerCallback(ctx context.Context, }, true); err != nil { return err } - conversationsOnLocal, err = c.db.GetAllConversations(ctx) - if err != nil { - return err - } - c.cache.UpdateConversations(conversationsOnLocal) return nil } @@ -69,28 +64,6 @@ func (c *Conversation) SyncAllConversations(ctx context.Context) error { return c.SyncConversationsAndTriggerCallback(ctx, conversationsOnServer) } -func (c *Conversation) SyncConversationUnreadCount(ctx context.Context) error { - var conversationChangedList []string - allConversations := c.cache.GetAllHasUnreadMessageConversations() - log.ZDebug(ctx, "get unread message length", "len", len(allConversations)) - for _, conversation := range allConversations { - if deleteRows := c.db.DeleteConversationUnreadMessageList(ctx, conversation.ConversationID, conversation.UpdateUnreadCountTime); deleteRows > 0 { - log.ZDebug(ctx, "DeleteConversationUnreadMessageList", conversation.ConversationID, conversation.UpdateUnreadCountTime, "delete rows:", deleteRows) - if err := c.db.DecrConversationUnreadCount(ctx, conversation.ConversationID, deleteRows); err != nil { - log.ZDebug(ctx, "DecrConversationUnreadCount", conversation.ConversationID, conversation.UpdateUnreadCountTime, "decr unread count err:", err.Error()) - } else { - conversationChangedList = append(conversationChangedList, conversation.ConversationID) - } - } - } - if len(conversationChangedList) > 0 { - if err := common.TriggerCmdUpdateConversation(ctx, common.UpdateConNode{Action: constant.ConChange, Args: conversationChangedList}, c.GetCh()); err != nil { - return err - } - } - return nil -} - func (c *Conversation) SyncAllConversationHashReadSeqs(ctx context.Context) error { log.ZDebug(ctx, "start SyncConversationHashReadSeqs") seqs, err := c.getServerHasReadAndMaxSeqs(ctx) diff --git a/internal/full/full.go b/internal/full/full.go index a6f9d7f51..050cf6ac0 100644 --- a/internal/full/full.go +++ b/internal/full/full.go @@ -17,7 +17,6 @@ package full import ( "context" "fmt" - "github.com/openimsdk/openim-sdk-core/v3/internal/cache" "github.com/openimsdk/openim-sdk-core/v3/internal/friend" "github.com/openimsdk/openim-sdk-core/v3/internal/group" "github.com/openimsdk/openim-sdk-core/v3/internal/user" @@ -28,12 +27,11 @@ import ( ) type Full struct { - user *user.User - friend *friend.Friend - group *group.Group - ch chan common.Cmd2Value - userCache *cache.Cache - db db_interface.DataBase + user *user.User + friend *friend.Friend + group *group.Group + ch chan common.Cmd2Value + db db_interface.DataBase } func (u *Full) Group() *group.Group { @@ -41,8 +39,8 @@ func (u *Full) Group() *group.Group { } func NewFull(user *user.User, friend *friend.Friend, group *group.Group, ch chan common.Cmd2Value, - userCache *cache.Cache, db db_interface.DataBase) *Full { - return &Full{user: user, friend: friend, group: group, ch: ch, userCache: userCache, db: db} + db db_interface.DataBase) *Full { + return &Full{user: user, friend: friend, group: group, ch: ch, db: db} } func (u *Full) GetGroupInfoFromLocal2Svr(ctx context.Context, groupID string, sessionType int32) (*model_struct.LocalGroup, error) { diff --git a/internal/group/notification.go b/internal/group/notification.go index 82ddd87a3..c113b2d51 100644 --- a/internal/group/notification.go +++ b/internal/group/notification.go @@ -127,13 +127,6 @@ func (g *Group) doNotification(ctx context.Context, msg *sdkws.MsgData) error { } g.listener.OnGroupMemberDeleted(string(data)) } - //for _, member := range util.Batch(ServerGroupMemberToLocalGroupMember, detail.KickedUserList) { - // data, err := json.Marshal(member) - // if err != nil { - // return err - // } - // g.listener.OnGroupMemberDeleted(string(data)) - //} group, err := g.db.GetGroupInfoByGroupID(ctx, detail.Group.GroupID) if err != nil { return err @@ -161,24 +154,6 @@ func (g *Group) doNotification(ctx context.Context, msg *sdkws.MsgData) error { return err } if detail.QuitUser.UserID == g.loginUserID { - //if err := g.db.DeleteGroupAllMembers(ctx, detail.Group.GroupID); err != nil { - // return err - //} - //return g.SyncJoinedGroup(ctx) - //group, err := g.db.GetGroupInfoByGroupID(ctx, detail.Group.GroupID) - //if err != nil { - // return err - //} - //group.MemberCount = 0 - //data, err := json.Marshal(group) - //if err != nil { - // return err - //} - //if err := g.db.DeleteGroup(ctx, detail.Group.GroupID); err != nil { - // return err - //} - //g.listener.OnGroupInfoChanged(string(data)) - //return nil members, err := g.db.GetGroupMemberListSplit(ctx, detail.Group.GroupID, 0, 0, 999999) if err != nil { return err @@ -193,13 +168,6 @@ func (g *Group) doNotification(ctx context.Context, msg *sdkws.MsgData) error { } g.listener.OnGroupMemberDeleted(string(data)) } - //for _, member := range util.Batch(ServerGroupMemberToLocalGroupMember, detail.KickedUserList) { - // data, err := json.Marshal(member) - // if err != nil { - // return err - // } - // g.listener.OnGroupMemberDeleted(string(data)) - //} group, err := g.db.GetGroupInfoByGroupID(ctx, detail.Group.GroupID) if err != nil { return err @@ -296,14 +264,14 @@ func (g *Group) doNotification(ctx context.Context, msg *sdkws.MsgData) error { return err } return g.SyncGroupMembers(ctx, detail.Group.GroupID, detail.ChangedUser.UserID) - case 1519: // 1519 constant.GroupInfoSetAnnouncementNotification - var detail sdkws.GroupInfoSetTips // sdkws.GroupInfoSetAnnouncementTips + case constant.GroupInfoSetAnnouncementNotification: // 1519 + var detail sdkws.GroupInfoSetAnnouncementTips // if err := utils.UnmarshalNotificationElem(msg.Content, &detail); err != nil { return err } return g.SyncGroups(ctx, detail.Group.GroupID) - case 1520: // 1520 constant.GroupInfoSetNameNotification - var detail sdkws.GroupInfoSetTips // sdkws.GroupInfoSetNameTips + case constant.GroupInfoSetNameNotification: // 1520 + var detail sdkws.GroupInfoSetNameTips // if err := utils.UnmarshalNotificationElem(msg.Content, &detail); err != nil { return err } diff --git a/internal/login/init_login.go b/internal/login/init_login.go index 734c8cbff..9af1dfb4d 100644 --- a/internal/login/init_login.go +++ b/internal/login/init_login.go @@ -21,7 +21,6 @@ import ( "time" "github.com/openimsdk/openim-sdk-core/v3/internal/business" - "github.com/openimsdk/openim-sdk-core/v3/internal/cache" conv "github.com/openimsdk/openim-sdk-core/v3/internal/conversation_msg" "github.com/openimsdk/openim-sdk-core/v3/internal/file" "github.com/openimsdk/openim-sdk-core/v3/internal/friend" @@ -68,7 +67,6 @@ type LoginMgr struct { longConnMgr *interaction.LongConnMgr msgSyncer *interaction.MsgSyncer third *third.Third - cache *cache.Cache token string loginUserID string connListener open_im_sdk_callback.OnConnListener @@ -282,9 +280,8 @@ func (u *LoginMgr) login(ctx context.Context, userID, token string) error { u.friend.SetLoginTime(u.loginTime) u.group = group.NewGroup(u.loginUserID, u.db, u.conversationCh) u.group.SetGroupListener(u.groupListener) - u.full = full.NewFull(u.user, u.friend, u.group, u.conversationCh, u.cache, u.db) + u.full = full.NewFull(u.user, u.friend, u.group, u.conversationCh, u.db) u.business = business.NewBusiness(u.db) - u.cache = cache.NewCache(u.user, u.friend) if u.businessListener != nil { u.business.SetListener(u.businessListener) } @@ -294,7 +291,7 @@ func (u *LoginMgr) login(ctx context.Context, userID, token string) error { u.longConnMgr.Run(ctx) u.msgSyncer, _ = interaction.NewMsgSyncer(ctx, u.conversationCh, u.pushMsgAndMaxSeqCh, u.loginUserID, u.longConnMgr, u.db, 0) u.conversation = conv.NewConversation(ctx, u.longConnMgr, u.db, u.conversationCh, - u.friend, u.group, u.user, u.conversationListener, u.advancedMsgListener, u.business, u.cache, u.full, u.file) + u.friend, u.group, u.user, u.conversationListener, u.advancedMsgListener, u.business, u.full, u.file) u.conversation.SetLoginTime() if u.batchMsgListener != nil { u.conversation.SetBatchMsgListener(u.batchMsgListener) diff --git a/internal/third/log.go b/internal/third/log.go index aae7834ec..b2e7351fe 100644 --- a/internal/third/log.go +++ b/internal/third/log.go @@ -31,7 +31,7 @@ func (c *Third) UploadLogs(ctx context.Context, params []sdk_params_callback.Upl }() req := third.UploadLogsReq{} for _, file := range files { - if !c.checkLogPath(file.Name()) { + if !checkLogPath(file.Name()) { continue } logName := filepath.Join(logFilePath, file.Name()) @@ -57,15 +57,15 @@ func (c *Third) UploadLogs(ctx context.Context, params []sdk_params_callback.Upl return err } -func (c *Third) checkLogPath(logpath string) bool { - if len(logpath) < len("open-im-sdk-core.yyyy-mm-dd") { +func checkLogPath(logPath string) bool { + if len(logPath) < len("open-im-sdk-core.yyyy-mm-dd") { return false } - logTime := logpath[len(logpath)-len(".yyyy-mm-dd"):] + logTime := logPath[len(logPath)-len(".yyyy-mm-dd"):] if _, err := time.Parse(".2006-01-02", logTime); err != nil { return false } - if !strings.HasPrefix(logpath, "open-im-sdk-core.") { + if !strings.HasPrefix(logPath, "open-im-sdk-core.") { return false } diff --git a/internal/third/push.go b/internal/third/push.go deleted file mode 100644 index c2396b51c..000000000 --- a/internal/third/push.go +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright © 2023 OpenIM SDK. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package third - -import ( - "github.com/openimsdk/openim-sdk-core/v3/open_im_sdk_callback" - - "github.com/openimsdk/openim-sdk-core/v3/internal/file" - "github.com/openimsdk/openim-sdk-core/v3/pkg/log" - "github.com/openimsdk/openim-sdk-core/v3/pkg/sdk_params_callback" - "github.com/openimsdk/openim-sdk-core/v3/pkg/server_api_params" -) - -type Third struct { - platformID int32 - loginUserID string - version string - LogFilePath string - fileUploader *file.File -} - -func NewThird(platformID int32, loginUserID, version, LogFilePath string, fileUploader *file.File) *Third { - return &Third{platformID: platformID, loginUserID: loginUserID, version: version, LogFilePath: LogFilePath, fileUploader: fileUploader} -} - -func (c *Third) UpdateFcmToken(callback open_im_sdk_callback.Base, fcmToken, operationID string) { - if callback == nil { - return - } - go func() { - log.NewInfo(operationID, "UpdateFcmToken args: ", fcmToken) - c.fmcUpdateToken(callback, fcmToken, operationID) - callback.OnSuccess(sdk_params_callback.UpdateFcmTokenCallback) - log.NewInfo(operationID, "UpdateFcmToken callback: ", sdk_params_callback.UpdateFcmTokenCallback) - }() - -} - -func (c *Third) fmcUpdateToken(callback open_im_sdk_callback.Base, fcmToken, operationID string) { - apiReq := server_api_params.FcmUpdateTokenReq{} - apiReq.OperationID = operationID - apiReq.Platform = int(c.platformID) - apiReq.FcmToken = fcmToken - //c.p.PostFatalCallback(callback, constant.FcmUpdateTokenRouter, apiReq, nil, apiReq.OperationID) -} -func (c *Third) SetAppBadge(callback open_im_sdk_callback.Base, appUnreadCount int32, operationID string) { - if callback == nil { - return - } - go func() { - log.NewInfo(operationID, "SetAppBadge args: ", appUnreadCount) - c.setAppBadge(callback, appUnreadCount, operationID) - callback.OnSuccess(sdk_params_callback.SetAppBadgeCallback) - log.NewInfo(operationID, "SetAppBadge callback: ", sdk_params_callback.SetAppBadgeCallback) - }() -} -func (c *Third) setAppBadge(callback open_im_sdk_callback.Base, appUnreadCount int32, operationID string) { - apiReq := server_api_params.SetAppBadgeReq{} - apiReq.OperationID = operationID - apiReq.FromUserID = c.loginUserID - apiReq.AppUnreadCount = appUnreadCount - //c.p.PostFatalCallback(callback, constant.SetAppBadgeRouter, apiReq, nil, apiReq.OperationID) -} diff --git a/internal/third/third.go b/internal/third/third.go new file mode 100644 index 000000000..094870c5a --- /dev/null +++ b/internal/third/third.go @@ -0,0 +1,56 @@ +// Copyright © 2023 OpenIM SDK. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package third + +import ( + "context" + "github.com/OpenIMSDK/protocol/third" + "github.com/openimsdk/openim-sdk-core/v3/internal/util" + "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" + + "github.com/openimsdk/openim-sdk-core/v3/internal/file" +) + +type Third struct { + platformID int32 + loginUserID string + version string + LogFilePath string + fileUploader *file.File +} + +func NewThird(platformID int32, loginUserID, version, LogFilePath string, fileUploader *file.File) *Third { + return &Third{platformID: platformID, loginUserID: loginUserID, version: version, LogFilePath: LogFilePath, fileUploader: fileUploader} +} + +func (c *Third) UpdateFcmToken(ctx context.Context, fcmToken string, expireTime int64) error { + req := third.FcmUpdateTokenReq{ + PlatformID: c.platformID, + FcmToken: fcmToken, + Account: c.loginUserID, + ExpireTime: expireTime} + _, err := util.CallApi[third.FcmUpdateTokenResp](ctx, constant.FcmUpdateTokenRouter, &req) + return err + +} + +func (c *Third) SetAppBadge(ctx context.Context, appUnreadCount int32) error { + req := third.SetAppBadgeReq{ + UserID: c.loginUserID, + AppUnreadCount: appUnreadCount, + } + _, err := util.CallApi[third.SetAppBadgeResp](ctx, constant.SetAppBadgeRouter, &req) + return err +} diff --git a/internal/user/sdk.go b/internal/user/sdk.go index 9ae2e58d7..c53c2ddb3 100644 --- a/internal/user/sdk.go +++ b/internal/user/sdk.go @@ -60,10 +60,19 @@ func (u *User) UpdateMsgSenderInfo(ctx context.Context, nickname, faceURL string } func (u *User) SubscribeUsersStatus(ctx context.Context, userIDs []string) ([]*userPb.OnlineStatus, error) { - return u.subscribeUsersStatus(ctx, userIDs) + userStatus, err := u.subscribeUsersStatus(ctx, userIDs) + if err != nil { + return nil, err + } + u.OnlineStatusCache.DeleteAll() + u.OnlineStatusCache.StoreAll(func(value *userPb.OnlineStatus) string { + return value.UserID + }, userStatus) + return userStatus, nil } func (u *User) UnsubscribeUsersStatus(ctx context.Context, userIDs []string) error { + u.OnlineStatusCache.DeleteAll() return u.unsubscribeUsersStatus(ctx, userIDs) } diff --git a/internal/user/sync.go b/internal/user/sync.go index 6ab6d5c03..177052fcf 100644 --- a/internal/user/sync.go +++ b/internal/user/sync.go @@ -16,7 +16,9 @@ package user import ( "context" + "errors" userPb "github.com/OpenIMSDK/protocol/user" + "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" @@ -42,12 +44,32 @@ func (u *User) SyncLoginUserInfo(ctx context.Context) error { return u.userSyncer.Sync(ctx, []*model_struct.LocalUser{remoteUser}, localUsers, nil) } -func (u *User) SyncUserStatus(ctx context.Context, fromId string, toUserID string, status int32, platformID int32, c func(userID string, statusMap *userPb.OnlineStatus)) { - statusMap := userPb.OnlineStatus{ - UserID: fromId, +func (u *User) SyncUserStatus(ctx context.Context, fromUserID string, status int32, platformID int32) { + userOnlineStatus := userPb.OnlineStatus{ + UserID: fromUserID, Status: status, PlatformIDs: []int32{platformID}, } - c(fromId, &statusMap) - u.listener.OnUserStatusChanged(utils.StructToJsonString(statusMap)) + if v, ok := u.OnlineStatusCache.Load(fromUserID); ok { + if status == constant.Online { + v.PlatformIDs = utils.RemoveRepeatedElementsInList(append(v.PlatformIDs, platformID)) + u.OnlineStatusCache.Store(fromUserID, v) + } else { + v.PlatformIDs = utils.RemoveOneInList(v.PlatformIDs, platformID) + if len(v.PlatformIDs) == 0 { + v.Status = constant.Offline + v.PlatformIDs = []int32{} + u.OnlineStatusCache.Store(fromUserID, v) + } + } + u.listener.OnSelfInfoUpdated(utils.StructToJsonString(userOnlineStatus)) + } else { + if status == constant.Online { + u.OnlineStatusCache.Store(fromUserID, &userOnlineStatus) + u.listener.OnUserStatusChanged(utils.StructToJsonString(userOnlineStatus)) + } else { + log.ZWarn(ctx, "exception", errors.New("user not exist"), "fromUserID", fromUserID, + "status", status, "platformID", platformID) + } + } } diff --git a/internal/user/user.go b/internal/user/user.go index ffcd5241c..c2665c850 100644 --- a/internal/user/user.go +++ b/internal/user/user.go @@ -17,6 +17,7 @@ package user import ( "context" "fmt" + "github.com/openimsdk/openim-sdk-core/v3/internal/cache" "github.com/openimsdk/openim-sdk-core/v3/internal/util" "github.com/openimsdk/openim-sdk-core/v3/pkg/db/db_interface" "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" @@ -35,14 +36,21 @@ import ( "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" ) +type BasicInfo struct { + Nickname string + FaceURL string +} + // User is a struct that represents a user in the system. type User struct { db_interface.DataBase - loginUserID string - listener open_im_sdk_callback.OnUserListener - loginTime int64 - userSyncer *syncer.Syncer[*model_struct.LocalUser, string] - conversationCh chan common.Cmd2Value + loginUserID string + listener open_im_sdk_callback.OnUserListener + loginTime int64 + userSyncer *syncer.Syncer[*model_struct.LocalUser, string] + conversationCh chan common.Cmd2Value + UserBasicCache *cache.Cache[string, *BasicInfo] + OnlineStatusCache *cache.Cache[string, *userPb.OnlineStatus] } // LoginTime gets the login time of the user. @@ -64,6 +72,8 @@ func (u *User) SetListener(listener open_im_sdk_callback.OnUserListener) { func NewUser(dataBase db_interface.DataBase, loginUserID string, conversationCh chan common.Cmd2Value) *User { user := &User{DataBase: dataBase, loginUserID: loginUserID, conversationCh: conversationCh} user.initSyncer() + user.UserBasicCache = cache.NewCache[string, *BasicInfo]() + user.OnlineStatusCache = cache.NewCache[string, *userPb.OnlineStatus]() return user } @@ -131,7 +141,7 @@ func (u *User) initSyncer() { //} // DoNotification handles incoming notifications for the user. -func (u *User) DoNotification(ctx context.Context, msg *sdkws.MsgData, cache func(userID string, statusMap *userPb.OnlineStatus)) { +func (u *User) DoNotification(ctx context.Context, msg *sdkws.MsgData) { log.ZDebug(ctx, "user notification", "msg", *msg) if u.listener == nil { // log.Error(operationID, "listener == nil") @@ -146,7 +156,7 @@ func (u *User) DoNotification(ctx context.Context, msg *sdkws.MsgData, cache fun case constant.UserInfoUpdatedNotification: u.userInfoUpdatedNotification(ctx, msg) case constant.UserStatusChangeNotification: - u.userStatusChangeNotification(ctx, msg, cache) + u.userStatusChangeNotification(ctx, msg) default: // log.Error(operationID, "type failed ", msg.ClientMsgID, msg.ServerMsgID, msg.ContentType) } @@ -170,14 +180,18 @@ func (u *User) userInfoUpdatedNotification(ctx context.Context, msg *sdkws.MsgDa } // userStatusChangeNotification get subscriber status change callback -func (u *User) userStatusChangeNotification(ctx context.Context, msg *sdkws.MsgData, c func(userID string, statusMap *userPb.OnlineStatus)) { +func (u *User) userStatusChangeNotification(ctx context.Context, msg *sdkws.MsgData) { log.ZDebug(ctx, "userStatusChangeNotification", "msg", *msg) tips := sdkws.UserStatusChangeTips{} if err := utils.UnmarshalNotificationElem(msg.Content, &tips); err != nil { log.ZError(ctx, "comm.UnmarshalTips failed", err, "msg", msg.Content) return } - u.SyncUserStatus(ctx, tips.FromUserID, tips.ToUserID, tips.Status, tips.PlatformID, c) + if tips.FromUserID == u.loginUserID { + log.ZDebug(ctx, "self terminal login", "tips", tips) + return + } + u.SyncUserStatus(ctx, tips.FromUserID, tips.Status, tips.PlatformID) } // GetUsersInfoFromSvr retrieves user information from the server. @@ -258,7 +272,7 @@ func (u *User) subscribeUsersStatus(ctx context.Context, userIDs []string) ([]*u // unsubscribeUsersStatus Unsubscribe a user's presence. func (u *User) unsubscribeUsersStatus(ctx context.Context, userIDs []string) error { - _, err := util.CallApi[userPb.SubscribeOrCancelUsersStatusResp](ctx, constant.UnsubscribeUsersStatusRouter, &userPb.SubscribeOrCancelUsersStatusReq{ + _, err := util.CallApi[userPb.SubscribeOrCancelUsersStatusResp](ctx, constant.SubscribeUsersStatusRouter, &userPb.SubscribeOrCancelUsersStatusReq{ UserID: u.loginUserID, UserIDs: userIDs, Genre: PbConstant.Unsubscribe, diff --git a/open_im_sdk/conversation_msg.go b/open_im_sdk/conversation_msg.go index ebe663dc2..5a7d12acb 100644 --- a/open_im_sdk/conversation_msg.go +++ b/open_im_sdk/conversation_msg.go @@ -35,10 +35,6 @@ func GetMultipleConversation(callback open_im_sdk_callback.Base, operationID str call(callback, operationID, UserForSDK.Conversation().GetMultipleConversation, conversationIDList) } -// funcation SetConversationRecvMessageOpt(callback open_im_sdk_callback.Base, operationID string, conversationIDList string, opt int) { -// call(callback, operationID, UserForSDK.Conversation().SetConversationRecvMessageOpt, conversationIDList, opt) -// } - func SetConversationMsgDestructTime(callback open_im_sdk_callback.Base, operationID string, conversationID string, msgDestructTime int64) { call(callback, operationID, UserForSDK.Conversation().SetConversationMsgDestructTime, conversationID, msgDestructTime) } @@ -56,10 +52,6 @@ func GetConversationRecvMessageOpt(callback open_im_sdk_callback.Base, operation call(callback, operationID, UserForSDK.Conversation().GetConversationRecvMessageOpt, conversationIDList) } -func DeleteAllConversationFromLocal(callback open_im_sdk_callback.Base, operationID string) { - call(callback, operationID, UserForSDK.Conversation().DeleteAllConversationFromLocal) -} - func SetConversationDraft(callback open_im_sdk_callback.Base, operationID string, conversationID string, draftText string) { call(callback, operationID, UserForSDK.Conversation().SetConversationDraft, conversationID, draftText) } @@ -182,10 +174,6 @@ func FindMessageList(callback open_im_sdk_callback.Base, operationID string, fin call(callback, operationID, UserForSDK.Conversation().FindMessageList, findMessageOptions) } -//funcation GetHistoryMessageList(callback open_im_sdk_callback.Base, operationID string, getMessageOptions string) { -// call(callback, operationID, UserForSDK.Conversation().GetHistoryMessageList, getMessageOptions) -//} - func GetAdvancedHistoryMessageList(callback open_im_sdk_callback.Base, operationID string, getMessageOptions string) { call(callback, operationID, UserForSDK.Conversation().GetAdvancedHistoryMessageList, getMessageOptions) } @@ -194,10 +182,6 @@ func GetAdvancedHistoryMessageListReverse(callback open_im_sdk_callback.Base, op call(callback, operationID, UserForSDK.Conversation().GetAdvancedHistoryMessageListReverse, getMessageOptions) } -//funcation GetHistoryMessageListReverse(callback open_im_sdk_callback.Base, operationID string, getMessageOptions string) { -// call(callback, operationID, UserForSDK.Conversation().GetHistoryMessageListReverse, getMessageOptions) -//} - func RevokeMessage(callback open_im_sdk_callback.Base, operationID string, conversationID, clientMsgID string) { call(callback, operationID, UserForSDK.Conversation().RevokeMessage, conversationID, clientMsgID) } @@ -223,8 +207,8 @@ func DeleteMessage(callback open_im_sdk_callback.Base, operationID string, conve call(callback, operationID, UserForSDK.Conversation().DeleteMessage, conversationID, clientMsgID) } -func DeleteConversationFromLocal(callback open_im_sdk_callback.Base, operationID string, conversationID string) { - call(callback, operationID, UserForSDK.Conversation().DeleteConversationFromLocal, conversationID) +func HideAllConversations(callback open_im_sdk_callback.Base, operationID string) { + call(callback, operationID, UserForSDK.Conversation().HideAllConversations) } func DeleteAllMsgFromLocalAndSvr(callback open_im_sdk_callback.Base, operationID string) { diff --git a/open_im_sdk/third.go b/open_im_sdk/third.go index 3693ab315..96c7bdd59 100644 --- a/open_im_sdk/third.go +++ b/open_im_sdk/third.go @@ -18,14 +18,14 @@ import ( "github.com/openimsdk/openim-sdk-core/v3/open_im_sdk_callback" ) -func UpdateFcmToken(callback open_im_sdk_callback.Base, operationID, userIDList string) { - call(callback, operationID, UserForSDK.Third().UpdateFcmToken, userIDList) +func UpdateFcmToken(callback open_im_sdk_callback.Base, operationID, fcmToken string, expireTime int64) { + call(callback, operationID, UserForSDK.Third().UpdateFcmToken, fcmToken, expireTime) } func SetAppBadge(callback open_im_sdk_callback.Base, operationID string, appUnreadCount int32) { call(callback, operationID, UserForSDK.Third().SetAppBadge, appUnreadCount) } -func UploadLogs(callback open_im_sdk_callback.Base, operationID string, uploadlogParams string) { - call(callback, operationID, UserForSDK.Third().UploadLogs, uploadlogParams) +func UploadLogs(callback open_im_sdk_callback.Base, operationID string, uploadLogParams string) { + call(callback, operationID, UserForSDK.Third().UploadLogs, uploadLogParams) } diff --git a/open_im_sdk_callback/callback_client.go b/open_im_sdk_callback/callback_client.go index 0993e43d2..fceaff8af 100644 --- a/open_im_sdk_callback/callback_client.go +++ b/open_im_sdk_callback/callback_client.go @@ -84,7 +84,7 @@ type OnBatchMsgListener interface { type OnUserListener interface { OnSelfInfoUpdated(userInfo string) - OnUserStatusChanged(statusMap string) + OnUserStatusChanged(userOnlineStatus string) } type OnCustomBusinessListener interface { diff --git a/pkg/constant/constant.go b/pkg/constant/constant.go index 277701f61..6aed16419 100644 --- a/pkg/constant/constant.go +++ b/pkg/constant/constant.go @@ -109,6 +109,8 @@ const ( GroupMemberInfoSetNotification = 1516 GroupMemberSetToAdminNotification = 1517 GroupMemberSetToOrdinaryUserNotification = 1518 + GroupInfoSetAnnouncementNotification = 1519 + GroupInfoSetNameNotification = 1520 GroupNotificationEnd = 1599 SignalingNotificationBegin = 1600 @@ -308,6 +310,9 @@ const ( NotReceiveMessage = 1 ReceiveNotNotifyMessage = 2 + Online = 1 + Offline = 0 + //pinned Pinned = 1 NotPinned = 0 diff --git a/pkg/constant/server_api_router.go b/pkg/constant/server_api_router.go index 3f1e41a12..48c4566a9 100644 --- a/pkg/constant/server_api_router.go +++ b/pkg/constant/server_api_router.go @@ -23,7 +23,6 @@ const ( AccountCheck = "/user/account_check" UserRegister = "/user/user_register" SubscribeUsersStatusRouter = "/user/subscribe_users_status" - UnsubscribeUsersStatusRouter = "/user/unsubscribe_users_status" GetSubscribeUsersStatusRouter = "/user/get_subscribe_users_status" GetUserStatusRouter = "/user/get_users_status" diff --git a/pkg/sdk_params_callback/conversation_msg_sdk_struct.go b/pkg/sdk_params_callback/conversation_msg_sdk_struct.go index ab5051556..e6980eb21 100644 --- a/pkg/sdk_params_callback/conversation_msg_sdk_struct.go +++ b/pkg/sdk_params_callback/conversation_msg_sdk_struct.go @@ -15,42 +15,10 @@ package sdk_params_callback import ( - "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" - "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" "github.com/openimsdk/openim-sdk-core/v3/pkg/server_api_params" "github.com/openimsdk/openim-sdk-core/v3/sdk_struct" ) -// type GetAllConversationListParam null -type GetAllConversationListCallback []*model_struct.LocalConversation - -// type GetAllConversationListParam offset count -type GetConversationListSplitCallback []*model_struct.LocalConversation - -type SetConversationRecvMessageOptParams []string - -const SetConversationRecvMessageOptCallback = constant.SuccessCallbackDefault -const SetGlobalRecvMessageOptCallback = constant.SuccessCallbackDefault - -type GetConversationRecvMessageOptParams []string - -type GetMultipleConversationParams []string -type GetMultipleConversationCallback []*model_struct.LocalConversation - -const DeleteConversationCallback = constant.SuccessCallbackDefault -const DeleteAllConversationFromLocalCallback = constant.SuccessCallbackDefault - -const SetConversationDraftCallback = constant.SuccessCallbackDefault -const ResetConversationGroupAtTypeCallback = constant.SuccessCallbackDefault - -const PinConversationDraftCallback = constant.SuccessCallbackDefault -const HideConversationCallback = constant.SuccessCallbackDefault -const SetConversationMessageOptCallback = constant.SuccessCallbackDefault - -const SetConversationPrivateChatOptCallback = constant.SuccessCallbackDefault - -const SetConversationBurnDurationOptCallback = constant.SuccessCallbackDefault - type FindMessageListParams []*ConversationArgs type ConversationArgs struct { ConversationID string `json:"conversationID"` @@ -82,26 +50,6 @@ type GetAdvancedHistoryMessageListCallback struct { ErrMsg string `json:"errMsg"` } -type RevokeMessageParams sdk_struct.MsgStruct - -const RevokeMessageCallback = constant.SuccessCallbackDefault - -const TypingStatusUpdateCallback = constant.SuccessCallbackDefault - -type MarkC2CMessageAsReadParams []string - -const MarkC2CMessageAsReadCallback = constant.SuccessCallbackDefault - -const MarkGroupMessageHasReadCallback = constant.SuccessCallbackDefault - -type MarkGroupMessageAsReadParams []string - -const MarkGroupMessageAsReadCallback = constant.SuccessCallbackDefault - -type MarkMessageAsReadByConIDParams []string - -const MarkMessageAsReadByConIDCallback = constant.SuccessCallbackDefault - type SetConversationStatusParams struct { UserId string `json:"userID" validate:"required"` Status int `json:"status" validate:"required"` diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go index a25d3bc5c..9e44ae209 100644 --- a/pkg/utils/utils.go +++ b/pkg/utils/utils.go @@ -358,18 +358,31 @@ func GetTableName(conversationID string) string { func GetErrTableName(conversationID string) string { return constant.SuperGroupErrChatLogsTableNamePre + conversationID } -func RemoveRepeatedStringInList(slc []string) []string { - var result []string - tempMap := map[string]byte{} + +type Comparable interface { + ~int | ~string | ~float64 | ~int32 +} + +func RemoveRepeatedElementsInList[T Comparable](slc []T) []T { + var result []T + tempMap := map[T]struct{}{} for _, e := range slc { - l := len(tempMap) - tempMap[e] = 0 - if len(tempMap) != l { + if _, found := tempMap[e]; !found { + tempMap[e] = struct{}{} result = append(result, e) } } + return result } +func RemoveOneInList[T comparable](slice []T, val T) []T { + for i, v := range slice { + if v == val { + return append(slice[:i], slice[i+1:]...) + } + } + return slice +} /* * diff --git a/sdk_struct/sdk_struct.go b/sdk_struct/sdk_struct.go index e751e68b5..0cde1d7b0 100644 --- a/sdk_struct/sdk_struct.go +++ b/sdk_struct/sdk_struct.go @@ -247,14 +247,13 @@ type AtInfo struct { GroupNickname string `json:"groupNickname,omitempty"` } type AttachedInfoElem struct { - GroupHasReadInfo GroupHasReadInfo `json:"groupHasReadInfo,omitempty"` - IsPrivateChat bool `json:"isPrivateChat"` - BurnDuration int32 `json:"burnDuration"` - HasReadTime int64 `json:"hasReadTime"` - NotSenderNotificationPush bool `json:"notSenderNotificationPush"` - MessageEntityList []*MessageEntity `json:"messageEntityList,omitempty"` - IsEncryption bool `json:"isEncryption"` - InEncryptStatus bool `json:"inEncryptStatus"` + GroupHasReadInfo GroupHasReadInfo `json:"groupHasReadInfo,omitempty"` + IsPrivateChat bool `json:"isPrivateChat"` + BurnDuration int32 `json:"burnDuration"` + HasReadTime int64 `json:"hasReadTime"` + MessageEntityList []*MessageEntity `json:"messageEntityList,omitempty"` + IsEncryption bool `json:"isEncryption"` + InEncryptStatus bool `json:"inEncryptStatus"` //MessageReactionElem []*ReactionElem `json:"messageReactionElem,omitempty"` Progress *UploadProgress `json:"uploadProgress,omitempty"` } diff --git a/test/t_conversation_msg.go b/test/t_conversation_msg.go index df9f1a192..9c5d2a587 100644 --- a/test/t_conversation_msg.go +++ b/test/t_conversation_msg.go @@ -161,11 +161,6 @@ func DoTestGetMessageListReactionExtensions(operationID string) { //params = append(params, &temp1) // open_im_sdk.GetMessageListReactionExtensions(testGetMessageReactionExtensionsCallBack, testGetMessageReactionExtensionsCallBack.OperationID, utils.StructToJsonString(ss)) } -func DoTestUpdateFcmToken() { - var testUpdateFcmTokenCallBack UpdateFcmTokenCallBack - testUpdateFcmTokenCallBack.OperationID = utils.OperationIDGenerator() - open_im_sdk.UpdateFcmToken(testUpdateFcmTokenCallBack, "2132323", testUpdateFcmTokenCallBack.OperationID) -} func DoTestSetAppBadge() { var testSetAppBadgeCallBack SetAppBadgeCallBack testSetAppBadgeCallBack.OperationID = utils.OperationIDGenerator() diff --git a/testv2/conversation_test.go b/testv2/conversation_test.go index ae331133a..352a9f099 100644 --- a/testv2/conversation_test.go +++ b/testv2/conversation_test.go @@ -95,13 +95,6 @@ func Test_GetGetMultipleConversation(t *testing.T) { // } // } -func Test_DeleteAllConversationFromLocal(t *testing.T) { - err := open_im_sdk.UserForSDK.Conversation().DeleteAllConversationFromLocal(ctx) - if err != nil { - t.Fatal(err) - } -} - func Test_SetConversationDraft(t *testing.T) { err := open_im_sdk.UserForSDK.Conversation().SetConversationDraft(ctx, "group_17729585012", "draft") if err != nil { diff --git a/wasm/cmd/main.go b/wasm/cmd/main.go index eb46d4ffc..d4773126c 100644 --- a/wasm/cmd/main.go +++ b/wasm/cmd/main.go @@ -101,7 +101,6 @@ func registerFunc() { js.Global().Set("setConversationPrivateChat", js.FuncOf(wrapperConMsg.SetConversationPrivateChat)) js.Global().Set("setConversationRecvMessageOpt", js.FuncOf(wrapperConMsg.SetConversationRecvMessageOpt)) js.Global().Set("setGlobalRecvMessageOpt", js.FuncOf(wrapperConMsg.SetGlobalRecvMessageOpt)) - js.Global().Set("deleteAllConversationFromLocal", js.FuncOf(wrapperConMsg.DeleteAllConversationFromLocal)) js.Global().Set("hideConversation", js.FuncOf(wrapperConMsg.HideConversation)) js.Global().Set("setConversationDraft", js.FuncOf(wrapperConMsg.SetConversationDraft)) js.Global().Set("resetConversationGroupAtType", js.FuncOf(wrapperConMsg.ResetConversationGroupAtType)) @@ -114,6 +113,7 @@ func registerFunc() { js.Global().Set("typingStatusUpdate", js.FuncOf(wrapperConMsg.TypingStatusUpdate)) js.Global().Set("deleteMessageFromLocalStorage", js.FuncOf(wrapperConMsg.DeleteMessageFromLocalStorage)) js.Global().Set("deleteMessage", js.FuncOf(wrapperConMsg.DeleteMessage)) + js.Global().Set("hideAllConversations", js.FuncOf(wrapperConMsg.HideAllConversations)) js.Global().Set("deleteAllMsgFromLocalAndSvr", js.FuncOf(wrapperConMsg.DeleteAllMsgFromLocalAndSvr)) js.Global().Set("deleteAllMsgFromLocal", js.FuncOf(wrapperConMsg.DeleteAllMsgFromLocal)) js.Global().Set("clearConversationAndDeleteAllMsg", js.FuncOf(wrapperConMsg.ClearConversationAndDeleteAllMsg)) diff --git a/wasm/wasm_wrapper/wasm_conversation_msg.go b/wasm/wasm_wrapper/wasm_conversation_msg.go index 56346f615..a78d02993 100644 --- a/wasm/wasm_wrapper/wasm_conversation_msg.go +++ b/wasm/wasm_wrapper/wasm_conversation_msg.go @@ -117,15 +117,6 @@ func (w *WrapperConMsg) GetAtAllTag(_ js.Value, args []js.Value) interface{} { return event_listener.NewCaller(open_im_sdk.GetAtAllTag, nil, &args).AsyncCallWithOutCallback() } -// funcation (w *WrapperConMsg) MarkC2CMessageAsRead(_ js.Value, args []js.Value) interface{} { -// callback := event_listener.NewBaseCallback(utils.FirstLower(utils.GetSelfFuncName()), w.commonFunc) -// return event_listener.NewCaller(open_im_sdk.MarkC2CMessageAsRead, callback, &args).AsyncCallWithCallback() -// } -// -// funcation (w *WrapperConMsg) MarkMessageAsReadByConID(_ js.Value, args []js.Value) interface{} { -// callback := event_listener.NewBaseCallback(utils.FirstLower(utils.GetSelfFuncName()), w.commonFunc) -// return event_listener.NewCaller(open_im_sdk.MarkMessageAsReadByConID, callback, &args).AsyncCallWithCallback() -// } func (w *WrapperConMsg) MarkConversationMessageAsRead(_ js.Value, args []js.Value) interface{} { callback := event_listener.NewBaseCallback(utils.FirstLower(utils.GetSelfFuncName()), w.commonFunc) return event_listener.NewCaller(open_im_sdk.MarkConversationMessageAsRead, callback, &args).AsyncCallWithCallback() @@ -226,11 +217,6 @@ func (w *WrapperConMsg) FindMessageList(_ js.Value, args []js.Value) interface{} return event_listener.NewCaller(open_im_sdk.FindMessageList, callback, &args).AsyncCallWithCallback() } -// funcation (w *WrapperConMsg) GetHistoryMessageListReverse(_ js.Value, args []js.Value) interface{} { -// callback := event_listener.NewBaseCallback(utils.FirstLower(utils.GetSelfFuncName()), w.commonFunc) -// return event_listener.NewCaller(open_im_sdk.GetHistoryMessageListReverse, callback, &args).AsyncCallWithCallback() -// } - func (w *WrapperConMsg) RevokeMessage(_ js.Value, args []js.Value) interface{} { callback := event_listener.NewBaseCallback(utils.FirstLower(utils.GetSelfFuncName()), w.commonFunc) return event_listener.NewCaller(open_im_sdk.RevokeMessage, callback, &args).AsyncCallWithCallback() @@ -241,11 +227,6 @@ func (w *WrapperConMsg) TypingStatusUpdate(_ js.Value, args []js.Value) interfac return event_listener.NewCaller(open_im_sdk.TypingStatusUpdate, callback, &args).AsyncCallWithCallback() } -//funcation (w *WrapperConMsg) MarkGroupMessageAsRead(_ js.Value, args []js.Value) interface{} { -// callback := event_listener.NewBaseCallback(utils.FirstLower(utils.GetSelfFuncName()), w.commonFunc) -// return event_listener.NewCaller(open_im_sdk.MarkGroupMessageAsRead, callback, &args).AsyncCallWithCallback() -//} - func (w *WrapperConMsg) DeleteMessageFromLocalStorage(_ js.Value, args []js.Value) interface{} { callback := event_listener.NewBaseCallback(utils.FirstLower(utils.GetSelfFuncName()), w.commonFunc) return event_listener.NewCaller(open_im_sdk.DeleteMessageFromLocalStorage, callback, &args).AsyncCallWithCallback() @@ -256,6 +237,11 @@ func (w *WrapperConMsg) DeleteMessage(_ js.Value, args []js.Value) interface{} { return event_listener.NewCaller(open_im_sdk.DeleteMessage, callback, &args).AsyncCallWithCallback() } +func (w *WrapperConMsg) HideAllConversations(_ js.Value, args []js.Value) interface{} { + callback := event_listener.NewBaseCallback(utils.FirstLower(utils.GetSelfFuncName()), w.commonFunc) + return event_listener.NewCaller(open_im_sdk.HideAllConversations, callback, &args).AsyncCallWithCallback() +} + func (w *WrapperConMsg) DeleteAllMsgFromLocalAndSvr(_ js.Value, args []js.Value) interface{} { callback := event_listener.NewBaseCallback(utils.FirstLower(utils.GetSelfFuncName()), w.commonFunc) return event_listener.NewCaller(open_im_sdk.DeleteAllMsgFromLocalAndSvr, callback, &args).AsyncCallWithCallback() @@ -271,21 +257,6 @@ func (w *WrapperConMsg) ClearConversationAndDeleteAllMsg(_ js.Value, args []js.V return event_listener.NewCaller(open_im_sdk.ClearConversationAndDeleteAllMsg, callback, &args).AsyncCallWithCallback() } -//funcation (w *WrapperConMsg) ClearC2CHistoryMessageFromLocalAndSvr(_ js.Value, args []js.Value) interface{} { -// callback := event_listener.NewBaseCallback(utils.FirstLower(utils.GetSelfFuncName()), w.commonFunc) -// return event_listener.NewCaller(open_im_sdk.ClearC2CHistoryMessageFromLocalAndSvr, callback, &args).AsyncCallWithCallback() -//} -// -//funcation (w *WrapperConMsg) ClearGroupHistoryMessage(_ js.Value, args []js.Value) interface{} { -// callback := event_listener.NewBaseCallback(utils.FirstLower(utils.GetSelfFuncName()), w.commonFunc) -// return event_listener.NewCaller(open_im_sdk.ClearGroupHistoryMessage, callback, &args).AsyncCallWithCallback() -//} -// -//funcation (w *WrapperConMsg) ClearGroupHistoryMessageFromLocalAndSvr(_ js.Value, args []js.Value) interface{} { -// callback := event_listener.NewBaseCallback(utils.FirstLower(utils.GetSelfFuncName()), w.commonFunc) -// return event_listener.NewCaller(open_im_sdk.ClearGroupHistoryMessageFromLocalAndSvr, callback, &args).AsyncCallWithCallback() -//} - func (w *WrapperConMsg) InsertSingleMessageToLocalStorage(_ js.Value, args []js.Value) interface{} { callback := event_listener.NewBaseCallback(utils.FirstLower(utils.GetSelfFuncName()), w.commonFunc) return event_listener.NewCaller(open_im_sdk.InsertSingleMessageToLocalStorage, callback, &args).AsyncCallWithCallback() @@ -310,11 +281,6 @@ func (w *WrapperConMsg) DeleteConversationAndDeleteAllMsg(_ js.Value, args []js. return event_listener.NewCaller(open_im_sdk.DeleteConversationAndDeleteAllMsg, callback, &args).AsyncCallWithCallback() } -func (w *WrapperConMsg) DeleteAllConversationFromLocal(_ js.Value, args []js.Value) interface{} { - callback := event_listener.NewBaseCallback(utils.FirstLower(utils.GetSelfFuncName()), w.commonFunc) - return event_listener.NewCaller(open_im_sdk.DeleteAllConversationFromLocal, callback, &args).AsyncCallWithCallback() -} - func (w *WrapperConMsg) HideConversation(_ js.Value, args []js.Value) interface{} { callback := event_listener.NewBaseCallback(utils.FirstLower(utils.GetSelfFuncName()), w.commonFunc) return event_listener.NewCaller(open_im_sdk.HideConversation, callback, &args).AsyncCallWithCallback()