mirror of
				https://github.com/openimsdk/open-im-server.git
				synced 2025-10-26 21:22:16 +08:00 
			
		
		
		
	fix Client failed to withdraw the message
This commit is contained in:
		
							parent
							
								
									73934fd955
								
							
						
					
					
						commit
						3651714950
					
				| @ -17,6 +17,8 @@ package msg | |||||||
| import ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
|  | 	"strconv" | ||||||
|  | 	"strings" | ||||||
| 	"time" | 	"time" | ||||||
| 
 | 
 | ||||||
| 	"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model" | 	"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model" | ||||||
| @ -49,38 +51,69 @@ func (m *msgServer) RevokeMsg(ctx context.Context, req *msg.RevokeMsgReq) (*msg. | |||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|  | 	 | ||||||
|  | 	// 获取消息并添加容错处理 | ||||||
| 	_, _, msgs, err := m.MsgDatabase.GetMsgBySeqs(ctx, req.UserID, req.ConversationID, []int64{req.Seq}) | 	_, _, msgs, err := m.MsgDatabase.GetMsgBySeqs(ctx, req.UserID, req.ConversationID, []int64{req.Seq}) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		// 记录错误但继续执行 | ||||||
| 	} | 		log.ZWarn(ctx, "GetMsgBySeqs error when revoking message", err,  | ||||||
| 	if len(msgs) == 0 || msgs[0] == nil { | 				"userID", req.UserID, "conversationID", req.ConversationID, "seq", req.Seq) | ||||||
| 		return nil, errs.ErrRecordNotFound.WrapMsg("msg not found") | 	} else if len(msgs) == 0 || msgs[0] == nil { | ||||||
| 	} | 		// 检查seq是否在当前会话的有效范围内 | ||||||
| 	if msgs[0].ContentType == constant.MsgRevokeNotification { | 		maxSeq, err := m.MsgDatabase.GetMaxSeq(ctx, req.ConversationID) | ||||||
| 		return nil, servererrs.ErrMsgAlreadyRevoke.WrapMsg("msg already revoke") | 		if err != nil { | ||||||
|  | 			log.ZWarn(ctx, "GetMaxSeq error when revoking message", err,  | ||||||
|  | 					"conversationID", req.ConversationID) | ||||||
|  | 		} else if req.Seq > maxSeq { | ||||||
|  | 			return nil, errs.ErrArgs.WrapMsg("seq exceeds maxSeq") | ||||||
| 		} | 		} | ||||||
| 		 | 		 | ||||||
| 	data, _ := json.Marshal(msgs[0]) | 		// 记录警告但继续执行 | ||||||
|  | 		log.ZWarn(ctx, "Message not found when revoking, but will proceed", nil, | ||||||
|  | 				"userID", req.UserID, "conversationID", req.ConversationID, "seq", req.Seq) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// 如果消息不存在,创建一个最小化的替代对象用于撤回通知 | ||||||
|  | 	var msgToRevoke *sdkws.MsgData | ||||||
|  | 	if len(msgs) == 0 || msgs[0] == nil { | ||||||
|  | 		// 创建一个最小的消息对象,包含必要的字段 | ||||||
|  | 		msgToRevoke = &sdkws.MsgData{ | ||||||
|  | 			SendID:         req.UserID,  // 使用撤回者作为发送者 | ||||||
|  | 			ConversationID: req.ConversationID, | ||||||
|  | 			Seq:            req.Seq, | ||||||
|  | 			SessionType:    getSessionTypeFromConversationID(req.ConversationID), // 辅助函数获取会话类型 | ||||||
|  | 			ClientMsgID:    "missing_" + strconv.FormatInt(req.Seq, 10), // 生成一个临时ID | ||||||
|  | 			SendTime:       time.Now().UnixMilli() - 1000, // 设置为稍早的时间 | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		msgToRevoke = msgs[0] | ||||||
|  | 		// 检查是否已经撤回 | ||||||
|  | 		if msgToRevoke.ContentType == constant.MsgRevokeNotification { | ||||||
|  | 			return nil, servererrs.ErrMsgAlreadyRevoke.WrapMsg("msg already revoke") | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	data, _ := json.Marshal(msgToRevoke) | ||||||
| 	log.ZDebug(ctx, "GetMsgBySeqs", "conversationID", req.ConversationID, "seq", req.Seq, "msg", string(data)) | 	log.ZDebug(ctx, "GetMsgBySeqs", "conversationID", req.ConversationID, "seq", req.Seq, "msg", string(data)) | ||||||
| 	var role int32 | 	var role int32 | ||||||
| 	if !authverify.IsAppManagerUid(ctx, m.config.Share.IMAdminUserID) { | 	if !authverify.IsAppManagerUid(ctx, m.config.Share.IMAdminUserID) { | ||||||
| 		sessionType := msgs[0].SessionType | 		sessionType := msgToRevoke.SessionType | ||||||
| 		switch sessionType { | 		switch sessionType { | ||||||
| 		case constant.SingleChatType: | 		case constant.SingleChatType: | ||||||
| 			if err := authverify.CheckAccessV3(ctx, msgs[0].SendID, m.config.Share.IMAdminUserID); err != nil { | 			if err := authverify.CheckAccessV3(ctx, msgToRevoke.SendID, m.config.Share.IMAdminUserID); err != nil { | ||||||
| 				return nil, err | 				return nil, err | ||||||
| 			} | 			} | ||||||
| 			role = user.AppMangerLevel | 			role = user.AppMangerLevel | ||||||
| 		case constant.ReadGroupChatType: | 		case constant.ReadGroupChatType: | ||||||
| 			members, err := m.GroupLocalCache.GetGroupMemberInfoMap(ctx, msgs[0].GroupID, datautil.Distinct([]string{req.UserID, msgs[0].SendID})) | 			members, err := m.GroupLocalCache.GetGroupMemberInfoMap(ctx, msgToRevoke.GroupID, datautil.Distinct([]string{req.UserID, msgToRevoke.SendID})) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				return nil, err | 				return nil, err | ||||||
| 			} | 			} | ||||||
| 			if req.UserID != msgs[0].SendID { | 			if req.UserID != msgToRevoke.SendID { | ||||||
| 				switch members[req.UserID].RoleLevel { | 				switch members[req.UserID].RoleLevel { | ||||||
| 				case constant.GroupOwner: | 				case constant.GroupOwner: | ||||||
| 				case constant.GroupAdmin: | 				case constant.GroupAdmin: | ||||||
| 					if sendMember, ok := members[msgs[0].SendID]; ok { | 					if sendMember, ok := members[msgToRevoke.SendID]; ok { | ||||||
| 						if sendMember.RoleLevel != constant.GroupOrdinaryUsers { | 						if sendMember.RoleLevel != constant.GroupOrdinaryUsers { | ||||||
| 							return nil, errs.ErrNoPermission.WrapMsg("no permission") | 							return nil, errs.ErrNoPermission.WrapMsg("no permission") | ||||||
| 						} | 						} | ||||||
| @ -114,20 +147,31 @@ func (m *msgServer) RevokeMsg(ctx context.Context, req *msg.RevokeMsgReq) (*msg. | |||||||
| 	} | 	} | ||||||
| 	tips := sdkws.RevokeMsgTips{ | 	tips := sdkws.RevokeMsgTips{ | ||||||
| 		RevokerUserID:  revokerUserID, | 		RevokerUserID:  revokerUserID, | ||||||
| 		ClientMsgID:    msgs[0].ClientMsgID, | 		ClientMsgID:    msgToRevoke.ClientMsgID, | ||||||
| 		RevokeTime:     now, | 		RevokeTime:     now, | ||||||
| 		Seq:            req.Seq, | 		Seq:            req.Seq, | ||||||
| 		SesstionType:   msgs[0].SessionType, | 		SesstionType:   msgToRevoke.SessionType, | ||||||
| 		ConversationID: req.ConversationID, | 		ConversationID: req.ConversationID, | ||||||
| 		IsAdminRevoke:  flag, | 		IsAdminRevoke:  flag, | ||||||
| 	} | 	} | ||||||
| 	var recvID string | 	var recvID string | ||||||
| 	if msgs[0].SessionType == constant.ReadGroupChatType { | 	if msgToRevoke.SessionType == constant.ReadGroupChatType { | ||||||
| 		recvID = msgs[0].GroupID | 		recvID = msgToRevoke.GroupID | ||||||
| 	} else { | 	} else { | ||||||
| 		recvID = msgs[0].RecvID | 		recvID = msgToRevoke.RecvID | ||||||
| 	} | 	} | ||||||
| 	m.notificationSender.NotificationWithSessionType(ctx, req.UserID, recvID, constant.MsgRevokeNotification, msgs[0].SessionType, &tips) | 	m.notificationSender.NotificationWithSessionType(ctx, req.UserID, recvID, constant.MsgRevokeNotification, msgToRevoke.SessionType, &tips) | ||||||
| 	m.webhookAfterRevokeMsg(ctx, &m.config.WebhooksConfig.AfterRevokeMsg, req) | 	m.webhookAfterRevokeMsg(ctx, &m.config.WebhooksConfig.AfterRevokeMsg, req) | ||||||
| 	return &msg.RevokeMsgResp{}, nil | 	return &msg.RevokeMsgResp{}, nil | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func getSessionTypeFromConversationID(conversationID string) int32 { | ||||||
|  | 	// 通常会话ID格式为: "单聊前缀{userID}" 或 "群聊前缀{groupID}" | ||||||
|  | 	if strings.HasPrefix(conversationID, "sp_") || strings.HasPrefix(conversationID, "si_") { | ||||||
|  | 		return constant.SingleChatType | ||||||
|  | 	} else if strings.HasPrefix(conversationID, "sg_") { | ||||||
|  | 		return constant.ReadGroupChatType | ||||||
|  | 	} | ||||||
|  | 	// 默认返回单聊类型 | ||||||
|  | 	return constant.SingleChatType | ||||||
|  | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user