You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
openim-sdk-cpp/go/chao-sdk-core/internal/group/sync.go

338 lines
11 KiB

// 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 group
import (
"context"
"crypto/md5"
"encoding/binary"
"encoding/json"
"errors"
"fmt"
"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/pkg/db/model_struct"
"github.com/openimsdk/protocol/group"
"github.com/openimsdk/protocol/sdkws"
"github.com/openimsdk/tools/log"
"github.com/openimsdk/tools/utils/datautil"
"time"
)
func (g *Group) getGroupHash(members []*model_struct.LocalGroupMember) uint64 {
userIDs := datautil.Slice(members, func(member *model_struct.LocalGroupMember) string {
return member.UserID
})
datautil.Sort(userIDs, true)
memberMap := make(map[string]*sdkws.GroupMemberFullInfo)
for _, member := range members {
memberMap[member.UserID] = &sdkws.GroupMemberFullInfo{
GroupID: member.GroupID,
UserID: member.UserID,
RoleLevel: member.RoleLevel,
JoinTime: member.JoinTime,
Nickname: member.Nickname,
FaceURL: member.FaceURL,
AppMangerLevel: 0,
JoinSource: member.JoinSource,
OperatorUserID: member.OperatorUserID,
Ex: member.Ex,
MuteEndTime: member.MuteEndTime,
InviterUserID: member.InviterUserID,
}
}
res := make([]*sdkws.GroupMemberFullInfo, 0, len(members))
for _, userID := range userIDs {
res = append(res, memberMap[userID])
}
val, _ := json.Marshal(res)
sum := md5.Sum(val)
return binary.BigEndian.Uint64(sum[:])
}
func (g *Group) SyncAllGroupMember(ctx context.Context, groupID string) error {
absInfo, err := g.GetGroupAbstractInfo(ctx, groupID)
if err != nil {
return err
}
localData, err := g.db.GetGroupMemberListSplit(ctx, groupID, 0, 0, 9999999)
if err != nil {
return err
}
hashCode := g.getGroupHash(localData)
if len(localData) == int(absInfo.GroupMemberNumber) && hashCode == absInfo.GroupMemberListHash {
log.ZDebug(ctx, "SyncAllGroupMember no change in personnel", "groupID", groupID, "hashCode", hashCode, "absInfo.GroupMemberListHash", absInfo.GroupMemberListHash)
return nil
}
members, err := g.GetServerGroupMembers(ctx, groupID)
if err != nil {
return err
}
return g.syncGroupMembers(ctx, groupID, members, localData)
}
func (g *Group) SyncAllGroupMember2(ctx context.Context, groupID string) error {
return g.IncrSyncGroupAndMember(ctx, groupID)
}
func (g *Group) syncGroupMembers(ctx context.Context, groupID string, members []*sdkws.GroupMemberFullInfo, localData []*model_struct.LocalGroupMember) error {
log.ZInfo(ctx, "SyncGroupMember Info", "groupID", groupID, "members", len(members), "localData", len(localData))
err := g.groupMemberSyncer.Sync(ctx, datautil.Batch(ServerGroupMemberToLocalGroupMember, members), localData, nil)
if err != nil {
return err
}
//if len(members) != len(localData) {
log.ZInfo(ctx, "SyncGroupMember Sync Group Member Count", "groupID", groupID, "members", len(members), "localData", len(localData))
gs, err := g.GetSpecifiedGroupsInfo(ctx, []string{groupID})
if err != nil {
return err
}
log.ZInfo(ctx, "SyncGroupMember GetGroupsInfo", "groupID", groupID, "len", len(gs), "gs", gs)
if len(gs) > 0 {
v := gs[0]
count, err := g.db.GetGroupMemberCount(ctx, groupID)
if err != nil {
return err
}
if v.MemberCount != count {
v.MemberCount = count
if v.GroupType == constant.SuperGroupChatType {
if err := g.db.UpdateSuperGroup(ctx, v); err != nil {
//return err
log.ZError(ctx, "SyncGroupMember UpdateSuperGroup", err, "groupID", groupID, "info", v)
}
} else {
if err := g.db.UpdateGroup(ctx, v); err != nil {
log.ZError(ctx, "SyncGroupMember UpdateGroup", err, "groupID", groupID, "info", v)
}
}
data, err := json.Marshal(v)
if err != nil {
return err
}
log.ZInfo(ctx, "SyncGroupMember OnGroupInfoChanged", "groupID", groupID, "data", string(data))
g.listener().OnGroupInfoChanged(string(data))
}
}
//}
return nil
}
func (g *Group) SyncGroupMembers(ctx context.Context, groupID string, userIDs ...string) error {
return g.IncrSyncGroupAndMember(ctx, groupID)
//members, err := g.GetDesignatedGroupMembers(ctx, groupID, userIDs)
//if err != nil {
// return err
//}
//localData, err := g.db.GetGroupSomeMemberInfo(ctx, groupID, userIDs)
//if err != nil {
// return err
//}
//return g.syncGroupMembers(ctx, groupID, members, localData)
}
func (g *Group) SyncGroups(ctx context.Context, groupIDs ...string) error {
return g.IncrSyncJoinGroup(ctx)
//groups, err := g.getGroupsInfoFromSvr(ctx, groupIDs)
//if err != nil {
// return err
//}
//localData, err := g.db.GetGroups(ctx, groupIDs)
//if err != nil {
// return err
//}
//if err := g.groupSyncer.Sync(ctx, util.Batch(ServerGroupToLocalGroup, groups), localData, nil); err != nil {
// return err
//}
//return nil
}
func (g *Group) deleteGroup(ctx context.Context, groupID string) error {
return g.IncrSyncJoinGroup(ctx)
//groupInfo, err := g.db.GetGroupInfoByGroupID(ctx, groupID)
//if err != nil {
// return err
//}
//if err := g.db.DeleteGroup(ctx, groupID); err != nil {
// return err
//}
//g.listener().OnJoinedGroupDeleted(utils.StructToJsonString(groupInfo))
//return nil
}
// func (g *Group) SyncAllJoinedGroupsAndMembers(ctx context.Context) error {
// t := time.Now()
// defer func(start time.Time) {
//
// elapsed := time.Since(start).Milliseconds()
// log.ZDebug(ctx, "SyncAllJoinedGroupsAndMembers fn call end", "cost time", fmt.Sprintf("%d ms", elapsed))
//
// }(t)
// _, err := g.syncAllJoinedGroups(ctx)
// if err != nil {
// return err
// }
// groups, err := g.db.GetJoinedGroupListDB(ctx)
// if err != nil {
// return err
// }
// var wg sync.WaitGroup
// for _, group := range groups {
// wg.Add(1)
// go func(groupID string) {
// defer wg.Done()
// if err := g.SyncAllGroupMember(ctx, groupID); err != nil {
// log.ZError(ctx, "SyncGroupMember failed", err)
// }
// }(group.GroupID)
// }
// wg.Wait()
// return nil
// }
func (g *Group) SyncAllJoinedGroupsAndMembers(ctx context.Context) error {
t := time.Now()
defer func(start time.Time) {
elapsed := time.Since(start).Milliseconds()
log.ZDebug(ctx, "SyncAllJoinedGroupsAndMembers fn call end", "cost time", fmt.Sprintf("%d ms", elapsed))
}(t)
if err := g.IncrSyncJoinGroup(ctx); err != nil {
return err
}
return g.IncrSyncJoinGroupMember(ctx)
}
func (g *Group) syncAllJoinedGroups(ctx context.Context) ([]*sdkws.GroupInfo, error) {
groups, err := g.GetServerJoinGroup(ctx)
if err != nil {
return nil, err
}
localData, err := g.db.GetJoinedGroupListDB(ctx)
if err != nil {
return nil, err
}
if err := g.groupSyncer.Sync(ctx, datautil.Batch(ServerGroupToLocalGroup, groups), localData, nil); err != nil {
return nil, err
}
return groups, nil
}
func (g *Group) SyncAllSelfGroupApplication(ctx context.Context) error {
list, err := g.GetServerSelfGroupApplication(ctx)
if err != nil {
return err
}
localData, err := g.db.GetSendGroupApplication(ctx)
if err != nil {
return err
}
if err := g.groupRequestSyncer.Sync(ctx, datautil.Batch(ServerGroupRequestToLocalGroupRequest, list), localData, nil); err != nil {
return err
}
// todo
return nil
}
func (g *Group) SyncAllSelfGroupApplicationWithoutNotice(ctx context.Context) error {
list, err := g.GetServerSelfGroupApplication(ctx)
if err != nil {
return err
}
localData, err := g.db.GetSendGroupApplication(ctx)
if err != nil {
return err
}
if err := g.groupRequestSyncer.Sync(ctx, datautil.Batch(ServerGroupRequestToLocalGroupRequest, list), localData, nil, false, true); err != nil {
return err
}
// todo
return nil
}
func (g *Group) SyncSelfGroupApplications(ctx context.Context, groupIDs ...string) error {
return g.SyncAllSelfGroupApplication(ctx)
}
func (g *Group) SyncAllAdminGroupApplication(ctx context.Context) error {
requests, err := g.GetServerAdminGroupApplicationList(ctx)
if err != nil {
return err
}
localData, err := g.db.GetAdminGroupApplication(ctx)
if err != nil {
return err
}
return g.groupAdminRequestSyncer.Sync(ctx, datautil.Batch(ServerGroupRequestToLocalAdminGroupRequest, requests), localData, nil)
}
func (g *Group) SyncAllAdminGroupApplicationWithoutNotice(ctx context.Context) error {
requests, err := g.GetServerAdminGroupApplicationList(ctx)
if err != nil {
return err
}
localData, err := g.db.GetAdminGroupApplication(ctx)
if err != nil {
return err
}
return g.groupAdminRequestSyncer.Sync(ctx, datautil.Batch(ServerGroupRequestToLocalAdminGroupRequest, requests), localData, nil, false, true)
}
func (g *Group) SyncAdminGroupApplications(ctx context.Context, groupIDs ...string) error {
return g.SyncAllAdminGroupApplication(ctx)
}
func (g *Group) GetServerJoinGroup(ctx context.Context) ([]*sdkws.GroupInfo, error) {
fn := func(resp *group.GetJoinedGroupListResp) []*sdkws.GroupInfo { return resp.Groups }
req := &group.GetJoinedGroupListReq{FromUserID: g.loginUserID, Pagination: &sdkws.RequestPagination{}}
return util.GetPageAll(ctx, constant.GetJoinedGroupListRouter, req, fn)
}
func (g *Group) GetServerAdminGroupApplicationList(ctx context.Context) ([]*sdkws.GroupRequest, error) {
fn := func(resp *group.GetGroupApplicationListResp) []*sdkws.GroupRequest { return resp.GroupRequests }
req := &group.GetGroupApplicationListReq{FromUserID: g.loginUserID, Pagination: &sdkws.RequestPagination{}}
return util.GetPageAll(ctx, constant.GetRecvGroupApplicationListRouter, req, fn)
}
func (g *Group) GetServerSelfGroupApplication(ctx context.Context) ([]*sdkws.GroupRequest, error) {
fn := func(resp *group.GetGroupApplicationListResp) []*sdkws.GroupRequest { return resp.GroupRequests }
req := &group.GetUserReqApplicationListReq{UserID: g.loginUserID, Pagination: &sdkws.RequestPagination{}}
return util.GetPageAll(ctx, constant.GetSendGroupApplicationListRouter, req, fn)
}
func (g *Group) GetServerGroupMembers(ctx context.Context, groupID string) ([]*sdkws.GroupMemberFullInfo, error) {
req := &group.GetGroupMemberListReq{GroupID: groupID, Pagination: &sdkws.RequestPagination{}}
fn := func(resp *group.GetGroupMemberListResp) []*sdkws.GroupMemberFullInfo { return resp.Members }
return util.GetPageAll(ctx, constant.GetGroupMemberListRouter, req, fn)
}
func (g *Group) GetDesignatedGroupMembers(ctx context.Context, groupID string, userID []string) ([]*sdkws.GroupMemberFullInfo, error) {
resp := &group.GetGroupMembersInfoResp{}
if err := util.ApiPost(ctx, constant.GetGroupMembersInfoRouter, &group.GetGroupMembersInfoReq{GroupID: groupID, UserIDs: userID}, resp); err != nil {
return nil, err
}
return resp.Members, nil
}
func (g *Group) GetGroupAbstractInfo(ctx context.Context, groupID string) (*group.GroupAbstractInfo, error) {
resp, err := util.CallApi[group.GetGroupAbstractInfoResp](ctx, constant.GetGroupAbstractInfoRouter, &group.GetGroupAbstractInfoReq{GroupIDs: []string{groupID}})
if err != nil {
return nil, err
}
if len(resp.GroupAbstractInfos) == 0 {
return nil, errors.New("group not found")
}
return resp.GroupAbstractInfos[0], nil
}