mirror of
https://github.com/openimsdk/open-im-server.git
synced 2026-07-13 08:31:08 +08:00
Compare commits
5 Commits
21c5e37043
...
09b7e5679a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
09b7e5679a | ||
|
|
1178808ba7 | ||
|
|
a0ccbf1883 | ||
|
|
d13d41f99f | ||
|
|
3651714950 |
2
go.mod
2
go.mod
@ -34,7 +34,7 @@ require (
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7
|
||||
github.com/kelindar/bitmap v1.5.2
|
||||
github.com/likexian/gokit v0.25.13
|
||||
github.com/openimsdk/gomake v0.0.15-alpha.2
|
||||
github.com/openimsdk/gomake v0.0.15-alpha.5
|
||||
github.com/redis/go-redis/v9 v9.4.0
|
||||
github.com/robfig/cron/v3 v3.0.1
|
||||
github.com/shirou/gopsutil v3.21.11+incompatible
|
||||
|
||||
4
go.sum
4
go.sum
@ -345,8 +345,8 @@ github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA
|
||||
github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To=
|
||||
github.com/onsi/gomega v1.25.0 h1:Vw7br2PCDYijJHSfBOWhov+8cAnUf8MfMaIOV323l6Y=
|
||||
github.com/onsi/gomega v1.25.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM=
|
||||
github.com/openimsdk/gomake v0.0.15-alpha.2 h1:5Q8yl8ezy2yx+q8/ucU/t4kJnDfCzNOrkXcDACCqtyM=
|
||||
github.com/openimsdk/gomake v0.0.15-alpha.2/go.mod h1:PndCozNc2IsQIciyn9mvEblYWZwJmAI+06z94EY+csI=
|
||||
github.com/openimsdk/gomake v0.0.15-alpha.5 h1:eEZCEHm+NsmcO3onXZPIUbGFCYPYbsX5beV3ZyOsGhY=
|
||||
github.com/openimsdk/gomake v0.0.15-alpha.5/go.mod h1:PndCozNc2IsQIciyn9mvEblYWZwJmAI+06z94EY+csI=
|
||||
github.com/openimsdk/protocol v0.0.73-alpha.6 h1:sna9coWG7HN1zObBPtvG0Ki/vzqHXiB4qKbA5P3w7kc=
|
||||
github.com/openimsdk/protocol v0.0.73-alpha.6/go.mod h1:WF7EuE55vQvpyUAzDXcqg+B+446xQyEba0X35lTINmw=
|
||||
github.com/openimsdk/tools v0.0.50-alpha.79 h1:jxYEbrzaze4Z2r4NrKad816buZ690ix0L9MTOOOH3ik=
|
||||
|
||||
@ -17,6 +17,8 @@ package msg
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
||||
@ -49,38 +51,94 @@ func (m *msgServer) RevokeMsg(ctx context.Context, req *msg.RevokeMsgReq) (*msg.
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Get message and add fault tolerance handling
|
||||
_, _, msgs, err := m.MsgDatabase.GetMsgBySeqs(ctx, req.UserID, req.ConversationID, []int64{req.Seq})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(msgs) == 0 || msgs[0] == nil {
|
||||
return nil, errs.ErrRecordNotFound.WrapMsg("msg not found")
|
||||
}
|
||||
if msgs[0].ContentType == constant.MsgRevokeNotification {
|
||||
return nil, servererrs.ErrMsgAlreadyRevoke.WrapMsg("msg already revoke")
|
||||
// Log the error but continue execution
|
||||
log.ZWarn(ctx, "GetMsgBySeqs error when revoking message", err,
|
||||
"userID", req.UserID, "conversationID", req.ConversationID, "seq", req.Seq)
|
||||
} else if len(msgs) == 0 || msgs[0] == nil {
|
||||
// Check if seq is within valid range for the current conversation
|
||||
maxSeq, err := m.MsgDatabase.GetMaxSeq(ctx, req.ConversationID)
|
||||
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")
|
||||
}
|
||||
|
||||
// Log warning but continue execution
|
||||
log.ZWarn(ctx, "Message not found when revoking, but will proceed", nil,
|
||||
"userID", req.UserID, "conversationID", req.ConversationID, "seq", req.Seq)
|
||||
}
|
||||
|
||||
data, _ := json.Marshal(msgs[0])
|
||||
// If message doesn't exist, create a minimal substitute for revocation notification
|
||||
var msgToRevoke *sdkws.MsgData
|
||||
if len(msgs) == 0 || msgs[0] == nil {
|
||||
// Create a minimal message object with necessary fields
|
||||
msgToRevoke = &sdkws.MsgData{
|
||||
SendID: req.UserID, // Use revoker as sender
|
||||
Seq: req.Seq,
|
||||
SessionType: getSessionTypeFromConversationID(req.ConversationID), // Helper function to get session type
|
||||
ClientMsgID: "missing_" + strconv.FormatInt(req.Seq, 10), // Generate a temporary ID
|
||||
SendTime: time.Now().UnixMilli() - 1000, // Set to a slightly earlier time
|
||||
}
|
||||
|
||||
// Set GroupID or RecvID based on session type
|
||||
if msgToRevoke.SessionType == constant.ReadGroupChatType {
|
||||
// Extract group ID from conversation ID
|
||||
if strings.HasPrefix(req.ConversationID, "sg_") {
|
||||
msgToRevoke.GroupID = req.ConversationID[3:] // Remove "sg_" prefix
|
||||
}
|
||||
} else {
|
||||
// For single chat, parse receiver ID from conversation ID
|
||||
if strings.HasPrefix(req.ConversationID, "si_") || strings.HasPrefix(req.ConversationID, "sp_") {
|
||||
parts := strings.Split(req.ConversationID[3:], "_")
|
||||
if len(parts) == 2 {
|
||||
// Conversation ID format is typically: si_senderID_receiverID
|
||||
// If current user is the sender, then receiver is the other party
|
||||
if parts[0] == req.UserID {
|
||||
msgToRevoke.RecvID = parts[1]
|
||||
} else {
|
||||
msgToRevoke.RecvID = parts[0]
|
||||
}
|
||||
} else {
|
||||
// Set empty if parsing fails
|
||||
msgToRevoke.RecvID = ""
|
||||
}
|
||||
} else {
|
||||
msgToRevoke.RecvID = ""
|
||||
}
|
||||
}
|
||||
} 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))
|
||||
var role int32
|
||||
if !authverify.IsAppManagerUid(ctx, m.config.Share.IMAdminUserID) {
|
||||
sessionType := msgs[0].SessionType
|
||||
sessionType := msgToRevoke.SessionType
|
||||
switch sessionType {
|
||||
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
|
||||
}
|
||||
role = user.AppMangerLevel
|
||||
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 {
|
||||
return nil, err
|
||||
}
|
||||
if req.UserID != msgs[0].SendID {
|
||||
if req.UserID != msgToRevoke.SendID {
|
||||
switch members[req.UserID].RoleLevel {
|
||||
case constant.GroupOwner:
|
||||
case constant.GroupAdmin:
|
||||
if sendMember, ok := members[msgs[0].SendID]; ok {
|
||||
if sendMember, ok := members[msgToRevoke.SendID]; ok {
|
||||
if sendMember.RoleLevel != constant.GroupOrdinaryUsers {
|
||||
return nil, errs.ErrNoPermission.WrapMsg("no permission")
|
||||
}
|
||||
@ -114,20 +172,31 @@ func (m *msgServer) RevokeMsg(ctx context.Context, req *msg.RevokeMsgReq) (*msg.
|
||||
}
|
||||
tips := sdkws.RevokeMsgTips{
|
||||
RevokerUserID: revokerUserID,
|
||||
ClientMsgID: msgs[0].ClientMsgID,
|
||||
ClientMsgID: msgToRevoke.ClientMsgID,
|
||||
RevokeTime: now,
|
||||
Seq: req.Seq,
|
||||
SesstionType: msgs[0].SessionType,
|
||||
SesstionType: msgToRevoke.SessionType,
|
||||
ConversationID: req.ConversationID,
|
||||
IsAdminRevoke: flag,
|
||||
}
|
||||
var recvID string
|
||||
if msgs[0].SessionType == constant.ReadGroupChatType {
|
||||
recvID = msgs[0].GroupID
|
||||
if msgToRevoke.SessionType == constant.ReadGroupChatType {
|
||||
recvID = msgToRevoke.GroupID
|
||||
} 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)
|
||||
return &msg.RevokeMsgResp{}, nil
|
||||
}
|
||||
|
||||
func getSessionTypeFromConversationID(conversationID string) int32 {
|
||||
// Conversation ID format is typically: "single chat prefix{userID}" or "group chat prefix{groupID}"
|
||||
if strings.HasPrefix(conversationID, "sp_") || strings.HasPrefix(conversationID, "si_") {
|
||||
return constant.SingleChatType
|
||||
} else if strings.HasPrefix(conversationID, "sg_") {
|
||||
return constant.ReadGroupChatType
|
||||
}
|
||||
// Default to single chat type
|
||||
return constant.SingleChatType
|
||||
}
|
||||
|
||||
@ -81,42 +81,10 @@ func (db *msgTransferDatabase) BatchInsertChat2DB(ctx context.Context, conversat
|
||||
continue
|
||||
}
|
||||
seqs[i] = msg.Seq
|
||||
var offlinePushModel *model.OfflinePushModel
|
||||
if msg.OfflinePushInfo != nil {
|
||||
offlinePushModel = &model.OfflinePushModel{
|
||||
Title: msg.OfflinePushInfo.Title,
|
||||
Desc: msg.OfflinePushInfo.Desc,
|
||||
Ex: msg.OfflinePushInfo.Ex,
|
||||
IOSPushSound: msg.OfflinePushInfo.IOSPushSound,
|
||||
IOSBadgeCount: msg.OfflinePushInfo.IOSBadgeCount,
|
||||
}
|
||||
}
|
||||
if msg.Status == constant.MsgStatusSending {
|
||||
msg.Status = constant.MsgStatusSendSuccess
|
||||
}
|
||||
msgs[i] = &model.MsgDataModel{
|
||||
SendID: msg.SendID,
|
||||
RecvID: msg.RecvID,
|
||||
GroupID: msg.GroupID,
|
||||
ClientMsgID: msg.ClientMsgID,
|
||||
ServerMsgID: msg.ServerMsgID,
|
||||
SenderPlatformID: msg.SenderPlatformID,
|
||||
SenderNickname: msg.SenderNickname,
|
||||
SenderFaceURL: msg.SenderFaceURL,
|
||||
SessionType: msg.SessionType,
|
||||
MsgFrom: msg.MsgFrom,
|
||||
ContentType: msg.ContentType,
|
||||
Content: string(msg.Content),
|
||||
Seq: msg.Seq,
|
||||
SendTime: msg.SendTime,
|
||||
CreateTime: msg.CreateTime,
|
||||
Status: msg.Status,
|
||||
Options: msg.Options,
|
||||
OfflinePush: offlinePushModel,
|
||||
AtUserIDList: msg.AtUserIDList,
|
||||
AttachedInfo: msg.AttachedInfo,
|
||||
Ex: msg.Ex,
|
||||
}
|
||||
msgs[i] = convert.MsgPb2DB(msg)
|
||||
}
|
||||
if err := db.BatchInsertBlock(ctx, conversationID, msgs, updateKeyMsg, msgList[0].Seq); err != nil {
|
||||
return err
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user