refactor: 3.7.0 code conventions. (#2148)

* Script Refactoring

* Script Refactoring

* Script Refactoring

* Script Refactoring

* Script Refactoring

* Script Refactoring

* Script Refactoring

* Script Refactoring

* Script Refactoring

* Script Refactoring

* Script Refactoring

* Script Refactoring

* feat: add code lint

* feat: add code lint

* Script Refactoring

* Script Refactoring

* Script Refactoring

* Script Refactoring

* Script Refactoring

* Script Refactoring

* Script Refactoring

* Script Refactoring

* Script Refactoring

* Script Refactoring

* Script Refactoring

* Script Refactoring

* Script Refactoring

* Script Refactoring

* Script Refactoring

* Script Refactoring

* Script Refactoring

* feat: code format

* Script Refactoring

* Script Refactoring

* Script Refactoring

* Adjust MinIO configuration settings

* Adjust configuration settings

* Adjust configuration settings

* refactor: config change.

* refactor: webhooks update.

* Adjust configuration settings

* refactor: webhooks update.

* Adjust configuration settings

* Adjust configuration settings

* Adjust configuration settings

* feat: s3 api addr

* refactor: webhooks update.

* Adjust configuration settings

* Adjust configuration settings

* Adjust configuration settings

* Adjust configuration settings

* Adjust configuration settings

* Adjust configuration settings

* Adjust configuration settings

* refactor: webhooks update.

* refactor: kafka update.

* Simplify the Docker Compose configuration, remove unnecessary environment variables, and eliminate the gateway service.

* refactor: kafka update.

* refactor: kafka update.

* Simplify the Docker Compose configuration, remove unnecessary environment variables, and eliminate the gateway service.

* Simplify the Docker Compose configuration, remove unnecessary environment variables, and eliminate the gateway service.

* Windows can compile and run.

* Windows can compile and run.

* refactor: kafka update.

* feat: msg cache split

* refactor: webhooks update

* refactor: webhooks update

* refactor: friends update

* refactor: group update

* refactor: third update

* refactor: api update

* refactor: crontab update

* refactor: msggateway update

* mage

* mage

* refactor: all module update.

* check

* refactor: all module update.

* load config

* load config

* load config

* load config

* refactor: all module update.

* refactor: all module update.

* refactor: all module update.

* refactor: all module update.

* refactor: all module update.

* Optimize Docker configuration and script.

* refactor: all module update.

* Optimize Docker configuration and script.

* Optimize Docker configuration and script.

* Optimize Docker configuration and script.

* refactor: all module update.

* Optimize Docker configuration and script.

* refactor: all module update.

* refactor: all module update.

* Optimize Docker configuration and script.

* Optimize Docker configuration and script.

* Optimize Docker configuration and script.

* Optimize Docker configuration and script.

* Optimize Docker configuration and script.

* Optimize Docker configuration and script.

* update tools

* update tools

* Optimize Docker configuration and script.

* Optimize Docker configuration and script.

* Optimize Docker configuration and script.

* Optimize Docker configuration and script.

* Optimize Docker configuration and script.

* Optimize Docker configuration and script.

* Optimize Docker configuration and script.

* Optimize Docker configuration and script.

* Optimize Docker configuration and script.

* Optimize Docker configuration and script.

* Optimize Docker configuration and script.

* update protocol

* Optimize Docker configuration and script.

* Optimize Docker configuration and script.

* refactor: all module update.

* Optimize Docker configuration and script.

* Optimize Docker configuration and script.

* Optimize Docker configuration and script.

* Optimize Docker configuration and script.

* refactor: api remove token auth by redis directly.

* Code Refactoring

* refactor: websocket auth change to call rpc of auth.

* refactor: kick online user and remove token change to call auth rpc.

* refactor: kick online user and remove token change to call auth rpc.

* refactor: remove msggateway redis.

* refactor: cmd update.

* refactor: cmd update.

* refactor: cmd update.

* refactor: cmd update.

* refactor: cmd update.

* refactor: cmd update.

* refactor: cmd update.

* refactor: cmd update.

* refactor: cmd update.

* refactor: cmd update.

* refactor: cmd update.

* refactor: cmd update.

* refactor: cmd update.

* refactor: cmd update.

* refactor: cmd update.

* refactor: cmd update.

* refactor: cmd update.

* refactor: cmd update.

* refactor: cmd update.

* refactor: cmd update.

* refactor: cmd update.

* refactor: cmd update.

* refactor: cmd update.

* refactor: cmd update.

* refactor: cmd update.

* refactor: cmd update.

* refactor webhook

* refactor: cmd update.

* refactor: cmd update.

* refactor: cmd update.

* refactor: cmd update.

* refactor webhook

* refactor: cmd update.

* refactor: cmd update.

* fix: runtime: goroutine stack exceeds

* refactor: cmd update.

* refactor notification

* refactor notification

* refactor

* refactor: cmd update.

* refactor: cmd update.

* refactor

* refactor

* refactor

* protojson

* protojson

* protojson

* go mod

* wrapperspb

* refactor: cmd update.

* refactor: cmd update.

* refactor: cmd update.

* refactor: context update.

* refactor: websocket update info.

* refactor: websocket update info.

* refactor: websocket update info.

* refactor: websocket update info.

* refactor: api name change.

* refactor: debug info.

* refactor: debug info.

* refactor: debug info.

* fix: update file

* refactor

* refactor

* refactor: debug info.

* refactor: debug info.

* refactor: debug info.

* refactor: debug info.

* refactor: debug info.

* refactor: debug info.

* fix: callback update.

* fix: callback update.

* refactor

* fix: update message.

* fix: msg cache timeout.

* refactor

* refactor

* fix: push update.

* fix: push update.

* fix: push update.

* fix: push update.

* fix: push update.

* fix: push update.

* fix: push update.

* fix: websocket handle error remove when upgrade error.

---------

Co-authored-by: skiffer-git <44203734@qq.com>
Co-authored-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
Co-authored-by: withchao <993506633@qq.com>
This commit is contained in:
OpenIM-Gordon
2024-04-19 22:23:08 +08:00
committed by GitHub
parent cca5336a8a
commit b76816bc14
438 changed files with 11525 additions and 15033 deletions
+47 -80
View File
@@ -17,19 +17,20 @@ package msg
import (
"context"
"github.com/OpenIMSDK/protocol/constant"
"github.com/OpenIMSDK/protocol/msg"
"github.com/OpenIMSDK/protocol/sdkws"
"github.com/OpenIMSDK/tools/errs"
"github.com/OpenIMSDK/tools/log"
utils2 "github.com/OpenIMSDK/tools/utils"
cbapi "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct"
"github.com/openimsdk/protocol/constant"
"github.com/openimsdk/protocol/msg"
"github.com/openimsdk/protocol/sdkws"
"github.com/openimsdk/tools/errs"
"github.com/openimsdk/tools/log"
"github.com/openimsdk/tools/utils/datautil"
"github.com/redis/go-redis/v9"
)
func (m *msgServer) GetConversationsHasReadAndMaxSeq(ctx context.Context, req *msg.GetConversationsHasReadAndMaxSeqReq) (resp *msg.GetConversationsHasReadAndMaxSeqResp, err error) {
func (m *msgServer) GetConversationsHasReadAndMaxSeq(ctx context.Context, req *msg.GetConversationsHasReadAndMaxSeqReq) (*msg.GetConversationsHasReadAndMaxSeqResp, error) {
var conversationIDs []string
if len(req.ConversationIDs) == 0 {
var err error
conversationIDs, err = m.ConversationLocalCache.GetConversationIDs(ctx, req.UserID)
if err != nil {
return nil, err
@@ -37,14 +38,17 @@ func (m *msgServer) GetConversationsHasReadAndMaxSeq(ctx context.Context, req *m
} else {
conversationIDs = req.ConversationIDs
}
hasReadSeqs, err := m.MsgDatabase.GetHasReadSeqs(ctx, req.UserID, conversationIDs)
if err != nil {
return nil, err
}
conversations, err := m.ConversationLocalCache.GetConversations(ctx, req.UserID, conversationIDs)
if err != nil {
return nil, err
}
conversationMaxSeqMap := make(map[string]int64)
for _, conversation := range conversations {
if conversation.MaxSeq != 0 {
@@ -55,95 +59,77 @@ func (m *msgServer) GetConversationsHasReadAndMaxSeq(ctx context.Context, req *m
if err != nil {
return nil, err
}
resp = &msg.GetConversationsHasReadAndMaxSeqResp{Seqs: make(map[string]*msg.Seqs)}
for conversarionID, maxSeq := range maxSeqs {
resp.Seqs[conversarionID] = &msg.Seqs{
HasReadSeq: hasReadSeqs[conversarionID],
resp := &msg.GetConversationsHasReadAndMaxSeqResp{Seqs: make(map[string]*msg.Seqs)}
for conversationID, maxSeq := range maxSeqs {
resp.Seqs[conversationID] = &msg.Seqs{
HasReadSeq: hasReadSeqs[conversationID],
MaxSeq: maxSeq,
}
if v, ok := conversationMaxSeqMap[conversarionID]; ok {
resp.Seqs[conversarionID].MaxSeq = v
if v, ok := conversationMaxSeqMap[conversationID]; ok {
resp.Seqs[conversationID].MaxSeq = v
}
}
return resp, nil
}
func (m *msgServer) SetConversationHasReadSeq(
ctx context.Context,
req *msg.SetConversationHasReadSeqReq,
) (resp *msg.SetConversationHasReadSeqResp, err error) {
func (m *msgServer) SetConversationHasReadSeq(ctx context.Context, req *msg.SetConversationHasReadSeqReq) (*msg.SetConversationHasReadSeqResp, error) {
maxSeq, err := m.MsgDatabase.GetMaxSeq(ctx, req.ConversationID)
if err != nil {
return
return nil, err
}
if req.HasReadSeq > maxSeq {
return nil, errs.ErrArgs.Wrap("hasReadSeq must not be bigger than maxSeq")
return nil, errs.ErrArgs.WrapMsg("hasReadSeq must not be bigger than maxSeq")
}
if err := m.MsgDatabase.SetHasReadSeq(ctx, req.UserID, req.ConversationID, req.HasReadSeq); err != nil {
return nil, err
}
if err = m.sendMarkAsReadNotification(ctx, req.ConversationID, constant.SingleChatType, req.UserID,
req.UserID, nil, req.HasReadSeq); err != nil {
return
}
m.sendMarkAsReadNotification(ctx, req.ConversationID, constant.SingleChatType, req.UserID, req.UserID, nil, req.HasReadSeq)
return &msg.SetConversationHasReadSeqResp{}, nil
}
func (m *msgServer) MarkMsgsAsRead(
ctx context.Context,
req *msg.MarkMsgsAsReadReq,
) (resp *msg.MarkMsgsAsReadResp, err error) {
func (m *msgServer) MarkMsgsAsRead(ctx context.Context, req *msg.MarkMsgsAsReadReq) (*msg.MarkMsgsAsReadResp, error) {
if len(req.Seqs) < 1 {
return nil, errs.ErrArgs.Wrap("seqs must not be empty")
return nil, errs.ErrArgs.WrapMsg("seqs must not be empty")
}
maxSeq, err := m.MsgDatabase.GetMaxSeq(ctx, req.ConversationID)
if err != nil {
return
return nil, err
}
hasReadSeq := req.Seqs[len(req.Seqs)-1]
if hasReadSeq > maxSeq {
return nil, errs.ErrArgs.Wrap("hasReadSeq must not be bigger than maxSeq")
return nil, errs.ErrArgs.WrapMsg("hasReadSeq must not be bigger than maxSeq")
}
conversation, err := m.ConversationLocalCache.GetConversation(ctx, req.UserID, req.ConversationID)
if err != nil {
return
return nil, err
}
if err = m.MsgDatabase.MarkSingleChatMsgsAsRead(ctx, req.UserID, req.ConversationID, req.Seqs); err != nil {
return
if err := m.MsgDatabase.MarkSingleChatMsgsAsRead(ctx, req.UserID, req.ConversationID, req.Seqs); err != nil {
return nil, err
}
currentHasReadSeq, err := m.MsgDatabase.GetHasReadSeq(ctx, req.UserID, req.ConversationID)
if err != nil && errs.Unwrap(err) != redis.Nil {
return
return nil, err
}
if hasReadSeq > currentHasReadSeq {
err = m.MsgDatabase.SetHasReadSeq(ctx, req.UserID, req.ConversationID, hasReadSeq)
if err != nil {
return
return nil, err
}
}
req_callback := &cbapi.CallbackSingleMsgReadReq{
reqCallback := &cbapi.CallbackSingleMsgReadReq{
ConversationID: conversation.ConversationID,
UserID: req.UserID,
Seqs: req.Seqs,
ContentType: conversation.ConversationType,
}
if err = CallbackSingleMsgRead(ctx, m.config, req_callback); err != nil {
return nil, err
}
if err = m.sendMarkAsReadNotification(ctx, req.ConversationID, conversation.ConversationType, req.UserID,
m.conversationAndGetRecvID(conversation, req.UserID), req.Seqs, hasReadSeq); err != nil {
return
}
m.webhookAfterSingleMsgRead(ctx, &m.config.WebhooksConfig.AfterSingleMsgRead, reqCallback)
m.sendMarkAsReadNotification(ctx, req.ConversationID, conversation.ConversationType, req.UserID,
m.conversationAndGetRecvID(conversation, req.UserID), req.Seqs, hasReadSeq)
return &msg.MarkMsgsAsReadResp{}, nil
}
func (m *msgServer) MarkConversationAsRead(
ctx context.Context,
req *msg.MarkConversationAsReadReq,
) (resp *msg.MarkConversationAsReadResp, err error) {
func (m *msgServer) MarkConversationAsRead(ctx context.Context, req *msg.MarkConversationAsReadReq) (*msg.MarkConversationAsReadResp, error) {
conversation, err := m.ConversationLocalCache.GetConversation(ctx, req.UserID, req.ConversationID)
if err != nil {
return nil, err
@@ -154,15 +140,14 @@ func (m *msgServer) MarkConversationAsRead(
}
var seqs []int64
log.ZDebug(ctx, "MarkConversationAsRead", "hasReadSeq", hasReadSeq,
"req.HasReadSeq", req.HasReadSeq)
log.ZDebug(ctx, "MarkConversationAsRead", "hasReadSeq", hasReadSeq, "req.HasReadSeq", req.HasReadSeq)
if conversation.ConversationType == constant.SingleChatType {
for i := hasReadSeq + 1; i <= req.HasReadSeq; i++ {
seqs = append(seqs, i)
}
//avoid client missed call MarkConversationMessageAsRead by order
// avoid client missed call MarkConversationMessageAsRead by order
for _, val := range req.Seqs {
if !utils2.Contain(val, seqs...) {
if !datautil.Contain(val, seqs...) {
seqs = append(seqs, val)
}
}
@@ -179,12 +164,9 @@ func (m *msgServer) MarkConversationAsRead(
}
hasReadSeq = req.HasReadSeq
}
if err = m.sendMarkAsReadNotification(ctx, req.ConversationID, conversation.ConversationType, req.UserID,
m.conversationAndGetRecvID(conversation, req.UserID), seqs, hasReadSeq); err != nil {
return nil, err
}
} else if conversation.ConversationType == constant.SuperGroupChatType ||
m.sendMarkAsReadNotification(ctx, req.ConversationID, conversation.ConversationType, req.UserID,
m.conversationAndGetRecvID(conversation, req.UserID), seqs, hasReadSeq)
} else if conversation.ConversationType == constant.ReadGroupChatType ||
conversation.ConversationType == constant.NotificationChatType {
if req.HasReadSeq > hasReadSeq {
err = m.MsgDatabase.SetHasReadSeq(ctx, req.UserID, req.ConversationID, req.HasReadSeq)
@@ -193,11 +175,8 @@ func (m *msgServer) MarkConversationAsRead(
}
hasReadSeq = req.HasReadSeq
}
if err = m.sendMarkAsReadNotification(ctx, req.ConversationID, constant.SingleChatType, req.UserID,
req.UserID, seqs, hasReadSeq); err != nil {
return nil, err
}
m.sendMarkAsReadNotification(ctx, req.ConversationID, constant.SingleChatType, req.UserID,
req.UserID, seqs, hasReadSeq)
}
reqCall := &cbapi.CallbackGroupMsgReadReq{
@@ -206,30 +185,18 @@ func (m *msgServer) MarkConversationAsRead(
UnreadMsgNum: req.HasReadSeq,
ContentType: int64(conversation.ConversationType),
}
if err := CallbackGroupMsgRead(ctx, m.config, reqCall); err != nil {
return nil, err
}
m.webhookAfterGroupMsgRead(ctx, &m.config.WebhooksConfig.AfterGroupMsgRead, reqCall)
return &msg.MarkConversationAsReadResp{}, nil
}
func (m *msgServer) sendMarkAsReadNotification(
ctx context.Context,
conversationID string,
sessionType int32,
sendID, recvID string,
seqs []int64,
hasReadSeq int64,
) error {
func (m *msgServer) sendMarkAsReadNotification(ctx context.Context, conversationID string, sessionType int32, sendID, recvID string, seqs []int64, hasReadSeq int64) {
tips := &sdkws.MarkAsReadTips{
MarkAsReadUserID: sendID,
ConversationID: conversationID,
Seqs: seqs,
HasReadSeq: hasReadSeq,
}
err := m.notificationSender.NotificationWithSesstionType(ctx, sendID, recvID, constant.HasReadReceipt, sessionType, tips)
if err != nil {
log.ZWarn(ctx, "send has read Receipt err", err)
}
return nil
m.notificationSender.NotificationWithSessionType(ctx, sendID, recvID, constant.HasReadReceipt, sessionType, tips)
}
+92 -113
View File
@@ -16,16 +16,15 @@ package msg
import (
"context"
"github.com/openimsdk/open-im-server/v3/pkg/common/webhook"
"github.com/OpenIMSDK/protocol/constant"
pbchat "github.com/OpenIMSDK/protocol/msg"
"github.com/OpenIMSDK/protocol/sdkws"
"github.com/OpenIMSDK/tools/log"
"github.com/OpenIMSDK/tools/mcontext"
"github.com/OpenIMSDK/tools/utils"
cbapi "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct"
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
"github.com/openimsdk/open-im-server/v3/pkg/common/http"
"github.com/openimsdk/protocol/constant"
pbchat "github.com/openimsdk/protocol/msg"
"github.com/openimsdk/protocol/sdkws"
"github.com/openimsdk/tools/mcontext"
"github.com/openimsdk/tools/utils/datautil"
"google.golang.org/protobuf/proto"
)
@@ -62,138 +61,118 @@ func GetContent(msg *sdkws.MsgData) string {
}
}
func callbackBeforeSendSingleMsg(ctx context.Context, globalConfig *config.GlobalConfig, msg *pbchat.SendMsgReq) error {
if !globalConfig.Callback.CallbackBeforeSendSingleMsg.Enable || msg.MsgData.ContentType == constant.Typing {
func (m *msgServer) webhookBeforeSendSingleMsg(ctx context.Context, before *config.BeforeConfig, msg *pbchat.SendMsgReq) error {
return webhook.WithCondition(ctx, before, func(ctx context.Context) error {
if msg.MsgData.ContentType == constant.Typing {
return nil
}
cbReq := &cbapi.CallbackBeforeSendSingleMsgReq{
CommonCallbackReq: toCommonCallback(ctx, msg, cbapi.CallbackBeforeSendSingleMsgCommand),
RecvID: msg.MsgData.RecvID,
}
resp := &cbapi.CallbackBeforeSendSingleMsgResp{}
if err := m.webhookClient.SyncPost(ctx, cbReq.GetCallbackCommand(), cbReq, resp, before); err != nil {
return err
}
return nil
}
req := &cbapi.CallbackBeforeSendSingleMsgReq{
CommonCallbackReq: toCommonCallback(ctx, msg, cbapi.CallbackBeforeSendSingleMsgCommand),
RecvID: msg.MsgData.RecvID,
}
resp := &cbapi.CallbackBeforeSendSingleMsgResp{}
if err := http.CallBackPostReturn(ctx, globalConfig.Callback.CallbackUrl, req, resp, globalConfig.Callback.CallbackBeforeSendSingleMsg); err != nil {
return err
}
return nil
})
}
func callbackAfterSendSingleMsg(ctx context.Context, globalConfig *config.GlobalConfig, msg *pbchat.SendMsgReq) error {
if !globalConfig.Callback.CallbackAfterSendSingleMsg.Enable || msg.MsgData.ContentType == constant.Typing {
return nil
func (m *msgServer) webhookAfterSendSingleMsg(ctx context.Context, after *config.AfterConfig, msg *pbchat.SendMsgReq) {
if msg.MsgData.ContentType == constant.Typing {
return
}
req := &cbapi.CallbackAfterSendSingleMsgReq{
cbReq := &cbapi.CallbackAfterSendSingleMsgReq{
CommonCallbackReq: toCommonCallback(ctx, msg, cbapi.CallbackAfterSendSingleMsgCommand),
RecvID: msg.MsgData.RecvID,
}
resp := &cbapi.CallbackAfterSendSingleMsgResp{}
if err := http.CallBackPostReturn(ctx, globalConfig.Callback.CallbackUrl, req, resp, globalConfig.Callback.CallbackAfterSendSingleMsg); err != nil {
return err
}
return nil
m.webhookClient.AsyncPost(ctx, cbReq.GetCallbackCommand(), cbReq, &cbapi.CallbackAfterSendSingleMsgResp{}, after)
}
func callbackBeforeSendGroupMsg(ctx context.Context, globalConfig *config.GlobalConfig, msg *pbchat.SendMsgReq) error {
if !globalConfig.Callback.CallbackBeforeSendGroupMsg.Enable || msg.MsgData.ContentType == constant.Typing {
func (m *msgServer) webhookBeforeSendGroupMsg(ctx context.Context, before *config.BeforeConfig, msg *pbchat.SendMsgReq) error {
return webhook.WithCondition(ctx, before, func(ctx context.Context) error {
if msg.MsgData.ContentType == constant.Typing {
return nil
}
cbReq := &cbapi.CallbackBeforeSendGroupMsgReq{
CommonCallbackReq: toCommonCallback(ctx, msg, cbapi.CallbackBeforeSendGroupMsgCommand),
GroupID: msg.MsgData.GroupID,
}
resp := &cbapi.CallbackBeforeSendGroupMsgResp{}
if err := m.webhookClient.SyncPost(ctx, cbReq.GetCallbackCommand(), cbReq, resp, before); err != nil {
return err
}
return nil
}
req := &cbapi.CallbackBeforeSendGroupMsgReq{
CommonCallbackReq: toCommonCallback(ctx, msg, cbapi.CallbackBeforeSendGroupMsgCommand),
GroupID: msg.MsgData.GroupID,
}
resp := &cbapi.CallbackBeforeSendGroupMsgResp{}
if err := http.CallBackPostReturn(ctx, globalConfig.Callback.CallbackUrl, req, resp, globalConfig.Callback.CallbackBeforeSendGroupMsg); err != nil {
return err
}
return nil
})
}
func callbackAfterSendGroupMsg(ctx context.Context, globalConfig *config.GlobalConfig, msg *pbchat.SendMsgReq) error {
if !globalConfig.Callback.CallbackAfterSendGroupMsg.Enable || msg.MsgData.ContentType == constant.Typing {
return nil
func (m *msgServer) webhookAfterSendGroupMsg(ctx context.Context, after *config.AfterConfig, msg *pbchat.SendMsgReq) {
if msg.MsgData.ContentType == constant.Typing {
return
}
req := &cbapi.CallbackAfterSendGroupMsgReq{
cbReq := &cbapi.CallbackAfterSendGroupMsgReq{
CommonCallbackReq: toCommonCallback(ctx, msg, cbapi.CallbackAfterSendGroupMsgCommand),
GroupID: msg.MsgData.GroupID,
}
resp := &cbapi.CallbackAfterSendGroupMsgResp{}
if err := http.CallBackPostReturn(ctx, globalConfig.Callback.CallbackUrl, req, resp, globalConfig.Callback.CallbackAfterSendGroupMsg); err != nil {
return err
}
return nil
m.webhookClient.AsyncPost(ctx, cbReq.GetCallbackCommand(), cbReq, &cbapi.CallbackAfterSendGroupMsgResp{}, after)
}
func callbackMsgModify(ctx context.Context, globalConfig *config.GlobalConfig, msg *pbchat.SendMsgReq) error {
if !globalConfig.Callback.CallbackMsgModify.Enable || msg.MsgData.ContentType != constant.Text {
return nil
}
req := &cbapi.CallbackMsgModifyCommandReq{
CommonCallbackReq: toCommonCallback(ctx, msg, cbapi.CallbackMsgModifyCommand),
}
resp := &cbapi.CallbackMsgModifyCommandResp{}
if err := http.CallBackPostReturn(ctx, globalConfig.Callback.CallbackUrl, req, resp, globalConfig.Callback.CallbackMsgModify); err != nil {
return err
}
if resp.Content != nil {
msg.MsgData.Content = []byte(*resp.Content)
}
utils.NotNilReplace(msg.MsgData.OfflinePushInfo, resp.OfflinePushInfo)
utils.NotNilReplace(&msg.MsgData.RecvID, resp.RecvID)
utils.NotNilReplace(&msg.MsgData.GroupID, resp.GroupID)
utils.NotNilReplace(&msg.MsgData.ClientMsgID, resp.ClientMsgID)
utils.NotNilReplace(&msg.MsgData.ServerMsgID, resp.ServerMsgID)
utils.NotNilReplace(&msg.MsgData.SenderPlatformID, resp.SenderPlatformID)
utils.NotNilReplace(&msg.MsgData.SenderNickname, resp.SenderNickname)
utils.NotNilReplace(&msg.MsgData.SenderFaceURL, resp.SenderFaceURL)
utils.NotNilReplace(&msg.MsgData.SessionType, resp.SessionType)
utils.NotNilReplace(&msg.MsgData.MsgFrom, resp.MsgFrom)
utils.NotNilReplace(&msg.MsgData.ContentType, resp.ContentType)
utils.NotNilReplace(&msg.MsgData.Status, resp.Status)
utils.NotNilReplace(&msg.MsgData.Options, resp.Options)
utils.NotNilReplace(&msg.MsgData.AtUserIDList, resp.AtUserIDList)
utils.NotNilReplace(&msg.MsgData.AttachedInfo, resp.AttachedInfo)
utils.NotNilReplace(&msg.MsgData.Ex, resp.Ex)
log.ZDebug(ctx, "callbackMsgModify", "msg", msg.MsgData)
return nil
}
func CallbackGroupMsgRead(ctx context.Context, globalConfig *config.GlobalConfig, req *cbapi.CallbackGroupMsgReadReq) error {
if !globalConfig.Callback.CallbackGroupMsgRead.Enable {
return nil
}
req.CallbackCommand = cbapi.CallbackGroupMsgReadCommand
func (m *msgServer) webhookBeforeMsgModify(ctx context.Context, before *config.BeforeConfig, msg *pbchat.SendMsgReq) error {
return webhook.WithCondition(ctx, before, func(ctx context.Context) error {
if msg.MsgData.ContentType != constant.Text {
return nil
}
cbReq := &cbapi.CallbackMsgModifyCommandReq{
CommonCallbackReq: toCommonCallback(ctx, msg, cbapi.CallbackBeforeMsgModifyCommand),
}
resp := &cbapi.CallbackMsgModifyCommandResp{}
if err := m.webhookClient.SyncPost(ctx, cbReq.GetCallbackCommand(), cbReq, resp, before); err != nil {
return err
}
resp := &cbapi.CallbackGroupMsgReadResp{}
if err := http.CallBackPostReturn(ctx, globalConfig.Callback.CallbackUrl, req, resp, globalConfig.Callback.CallbackGroupMsgRead); err != nil {
return err
}
return nil
if resp.Content != nil {
msg.MsgData.Content = []byte(*resp.Content)
}
datautil.NotNilReplace(msg.MsgData.OfflinePushInfo, resp.OfflinePushInfo)
datautil.NotNilReplace(&msg.MsgData.RecvID, resp.RecvID)
datautil.NotNilReplace(&msg.MsgData.GroupID, resp.GroupID)
datautil.NotNilReplace(&msg.MsgData.ClientMsgID, resp.ClientMsgID)
datautil.NotNilReplace(&msg.MsgData.ServerMsgID, resp.ServerMsgID)
datautil.NotNilReplace(&msg.MsgData.SenderPlatformID, resp.SenderPlatformID)
datautil.NotNilReplace(&msg.MsgData.SenderNickname, resp.SenderNickname)
datautil.NotNilReplace(&msg.MsgData.SenderFaceURL, resp.SenderFaceURL)
datautil.NotNilReplace(&msg.MsgData.SessionType, resp.SessionType)
datautil.NotNilReplace(&msg.MsgData.MsgFrom, resp.MsgFrom)
datautil.NotNilReplace(&msg.MsgData.ContentType, resp.ContentType)
datautil.NotNilReplace(&msg.MsgData.Status, resp.Status)
datautil.NotNilReplace(&msg.MsgData.Options, resp.Options)
datautil.NotNilReplace(&msg.MsgData.AtUserIDList, resp.AtUserIDList)
datautil.NotNilReplace(&msg.MsgData.AttachedInfo, resp.AttachedInfo)
datautil.NotNilReplace(&msg.MsgData.Ex, resp.Ex)
return nil
})
}
func CallbackSingleMsgRead(ctx context.Context, globalConfig *config.GlobalConfig, req *cbapi.CallbackSingleMsgReadReq) error {
if !globalConfig.Callback.CallbackSingleMsgRead.Enable {
return nil
}
req.CallbackCommand = cbapi.CallbackSingleMsgRead
resp := &cbapi.CallbackSingleMsgReadResp{}
if err := http.CallBackPostReturn(ctx, globalConfig.Callback.CallbackUrl, req, resp, globalConfig.Callback.CallbackSingleMsgRead); err != nil {
return err
}
return nil
func (m *msgServer) webhookAfterGroupMsgRead(ctx context.Context, after *config.AfterConfig, req *cbapi.CallbackGroupMsgReadReq) {
req.CallbackCommand = cbapi.CallbackAfterGroupMsgReadCommand
m.webhookClient.AsyncPost(ctx, req.GetCallbackCommand(), req, &cbapi.CallbackGroupMsgReadResp{}, after)
}
func CallbackAfterRevokeMsg(ctx context.Context, globalConfig *config.GlobalConfig, req *pbchat.RevokeMsgReq) error {
if !globalConfig.Callback.CallbackAfterRevokeMsg.Enable {
return nil
}
func (m *msgServer) webhookAfterSingleMsgRead(ctx context.Context, after *config.AfterConfig, req *cbapi.CallbackSingleMsgReadReq) {
req.CallbackCommand = cbapi.CallbackAfterSingleMsgReadCommand
m.webhookClient.AsyncPost(ctx, req.GetCallbackCommand(), req, &cbapi.CallbackSingleMsgReadResp{}, after)
}
func (m *msgServer) webhookAfterRevokeMsg(ctx context.Context, after *config.AfterConfig, req *pbchat.RevokeMsgReq) {
callbackReq := &cbapi.CallbackAfterRevokeMsgReq{
CallbackCommand: cbapi.CallbackAfterRevokeMsgCommand,
ConversationID: req.ConversationID,
Seq: req.Seq,
UserID: req.UserID,
}
resp := &cbapi.CallbackAfterRevokeMsgResp{}
if err := http.CallBackPostReturn(ctx, globalConfig.Callback.CallbackUrl, callbackReq, resp, globalConfig.Callback.CallbackAfterRevokeMsg); err != nil {
return err
}
return nil
m.webhookClient.AsyncPost(ctx, callbackReq.GetCallbackCommand(), callbackReq, &cbapi.CallbackAfterRevokeMsgResp{}, after)
}
+21 -55
View File
@@ -17,13 +17,13 @@ package msg
import (
"context"
"github.com/OpenIMSDK/protocol/constant"
"github.com/OpenIMSDK/protocol/conversation"
"github.com/OpenIMSDK/protocol/msg"
"github.com/OpenIMSDK/protocol/sdkws"
"github.com/OpenIMSDK/tools/log"
"github.com/OpenIMSDK/tools/utils"
"github.com/openimsdk/open-im-server/v3/pkg/authverify"
"github.com/openimsdk/protocol/constant"
"github.com/openimsdk/protocol/conversation"
"github.com/openimsdk/protocol/msg"
"github.com/openimsdk/protocol/sdkws"
"github.com/openimsdk/tools/log"
"github.com/openimsdk/tools/utils/timeutil"
)
func (m *msgServer) getMinSeqs(maxSeqs map[string]int64) map[string]int64 {
@@ -41,11 +41,8 @@ func (m *msgServer) validateDeleteSyncOpt(opt *msg.DeleteSyncOpt) (isSyncSelf, i
return opt.IsSyncSelf, opt.IsSyncOther
}
func (m *msgServer) ClearConversationsMsg(
ctx context.Context,
req *msg.ClearConversationsMsgReq,
) (*msg.ClearConversationsMsgResp, error) {
if err := authverify.CheckAccessV3(ctx, req.UserID, m.config); err != nil {
func (m *msgServer) ClearConversationsMsg(ctx context.Context, req *msg.ClearConversationsMsgReq) (*msg.ClearConversationsMsgResp, error) {
if err := authverify.CheckAccessV3(ctx, req.UserID, m.config.Share.IMAdminUserID); err != nil {
return nil, err
}
if err := m.clearConversation(ctx, req.ConversationIDs, req.UserID, req.DeleteSyncOpt); err != nil {
@@ -54,18 +51,14 @@ func (m *msgServer) ClearConversationsMsg(
return &msg.ClearConversationsMsgResp{}, nil
}
func (m *msgServer) UserClearAllMsg(
ctx context.Context,
req *msg.UserClearAllMsgReq,
) (*msg.UserClearAllMsgResp, error) {
if err := authverify.CheckAccessV3(ctx, req.UserID, m.config); err != nil {
func (m *msgServer) UserClearAllMsg(ctx context.Context, req *msg.UserClearAllMsgReq) (*msg.UserClearAllMsgResp, error) {
if err := authverify.CheckAccessV3(ctx, req.UserID, m.config.Share.IMAdminUserID); err != nil {
return nil, err
}
conversationIDs, err := m.ConversationLocalCache.GetConversationIDs(ctx, req.UserID)
if err != nil {
return nil, err
}
log.ZDebug(ctx, "GetMaxSeq", "conversationIDs", conversationIDs)
if err := m.clearConversation(ctx, conversationIDs, req.UserID, req.DeleteSyncOpt); err != nil {
return nil, err
}
@@ -73,7 +66,7 @@ func (m *msgServer) UserClearAllMsg(
}
func (m *msgServer) DeleteMsgs(ctx context.Context, req *msg.DeleteMsgsReq) (*msg.DeleteMsgsResp, error) {
if err := authverify.CheckAccessV3(ctx, req.UserID, m.config); err != nil {
if err := authverify.CheckAccessV3(ctx, req.UserID, m.config.Share.IMAdminUserID); err != nil {
return nil, err
}
isSyncSelf, isSyncOther := m.validateDeleteSyncOpt(req.DeleteSyncOpt)
@@ -86,7 +79,7 @@ func (m *msgServer) DeleteMsgs(ctx context.Context, req *msg.DeleteMsgsReq) (*ms
return nil, err
}
tips := &sdkws.DeleteMsgsTips{UserID: req.UserID, ConversationID: req.ConversationID, Seqs: req.Seqs}
m.notificationSender.NotificationWithSesstionType(
m.notificationSender.NotificationWithSessionType(
ctx,
req.UserID,
m.conversationAndGetRecvID(conversations[0], req.UserID),
@@ -100,16 +93,13 @@ func (m *msgServer) DeleteMsgs(ctx context.Context, req *msg.DeleteMsgsReq) (*ms
}
if isSyncSelf {
tips := &sdkws.DeleteMsgsTips{UserID: req.UserID, ConversationID: req.ConversationID, Seqs: req.Seqs}
m.notificationSender.NotificationWithSesstionType(ctx, req.UserID, req.UserID, constant.DeleteMsgsNotification, constant.SingleChatType, tips)
m.notificationSender.NotificationWithSessionType(ctx, req.UserID, req.UserID, constant.DeleteMsgsNotification, constant.SingleChatType, tips)
}
}
return &msg.DeleteMsgsResp{}, nil
}
func (m *msgServer) DeleteMsgPhysicalBySeq(
ctx context.Context,
req *msg.DeleteMsgPhysicalBySeqReq,
) (*msg.DeleteMsgPhysicalBySeqResp, error) {
func (m *msgServer) DeleteMsgPhysicalBySeq(ctx context.Context, req *msg.DeleteMsgPhysicalBySeqReq) (*msg.DeleteMsgPhysicalBySeqResp, error) {
err := m.MsgDatabase.DeleteMsgsPhysicalBySeqs(ctx, req.ConversationID, req.Seqs)
if err != nil {
return nil, err
@@ -117,37 +107,20 @@ func (m *msgServer) DeleteMsgPhysicalBySeq(
return &msg.DeleteMsgPhysicalBySeqResp{}, nil
}
func (m *msgServer) DeleteMsgPhysical(
ctx context.Context,
req *msg.DeleteMsgPhysicalReq,
) (*msg.DeleteMsgPhysicalResp, error) {
if err := authverify.CheckAdmin(ctx, m.config); err != nil {
func (m *msgServer) DeleteMsgPhysical(ctx context.Context, req *msg.DeleteMsgPhysicalReq) (*msg.DeleteMsgPhysicalResp, error) {
if err := authverify.CheckAdmin(ctx, m.config.Share.IMAdminUserID); err != nil {
return nil, err
}
remainTime := utils.GetCurrentTimestampBySecond() - req.Timestamp
remainTime := timeutil.GetCurrentTimestampBySecond() - req.Timestamp
for _, conversationID := range req.ConversationIDs {
if err := m.MsgDatabase.DeleteConversationMsgsAndSetMinSeq(ctx, conversationID, remainTime); err != nil {
log.ZWarn(
ctx,
"DeleteConversationMsgsAndSetMinSeq error",
err,
"conversationID",
conversationID,
"err",
err,
)
log.ZWarn(ctx, "DeleteConversationMsgsAndSetMinSeq error", err, "conversationID", conversationID, "err", err)
}
}
return &msg.DeleteMsgPhysicalResp{}, nil
}
func (m *msgServer) clearConversation(
ctx context.Context,
conversationIDs []string,
userID string,
deleteSyncOpt *msg.DeleteSyncOpt,
) error {
defer log.ZDebug(ctx, "clearConversation return line")
func (m *msgServer) clearConversation(ctx context.Context, conversationIDs []string, userID string, deleteSyncOpt *msg.DeleteSyncOpt) error {
conversations, err := m.Conversation.GetConversationsByConversationID(ctx, conversationIDs)
if err != nil {
return err
@@ -171,14 +144,7 @@ func (m *msgServer) clearConversation(
// notification 2 self
if isSyncSelf {
tips := &sdkws.ClearConversationTips{UserID: userID, ConversationIDs: existConversationIDs}
m.notificationSender.NotificationWithSesstionType(
ctx,
userID,
userID,
constant.ClearConversationNotification,
constant.SingleChatType,
tips,
)
m.notificationSender.NotificationWithSessionType(ctx, userID, userID, constant.ClearConversationNotification, constant.SingleChatType, tips)
}
} else {
if err := m.MsgDatabase.SetMinSeqs(ctx, m.getMinSeqs(maxSeqs)); err != nil {
@@ -186,7 +152,7 @@ func (m *msgServer) clearConversation(
}
for _, conversation := range existConversations {
tips := &sdkws.ClearConversationTips{UserID: userID, ConversationIDs: []string{conversation.ConversationID}}
m.notificationSender.NotificationWithSesstionType(ctx, userID, m.conversationAndGetRecvID(conversation, userID), constant.ClearConversationNotification, conversation.ConversationType, tips)
m.notificationSender.NotificationWithSessionType(ctx, userID, m.conversationAndGetRecvID(conversation, userID), constant.ClearConversationNotification, conversation.ConversationType, tips)
}
}
if err := m.MsgDatabase.UserSetHasReadSeqs(ctx, userID, maxSeqs); err != nil {
-43
View File
@@ -1,43 +0,0 @@
// Copyright © 2023 OpenIM. 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 msg
import (
"context"
"github.com/OpenIMSDK/protocol/constant"
"github.com/OpenIMSDK/protocol/msg"
"github.com/OpenIMSDK/protocol/sdkws"
"github.com/OpenIMSDK/tools/errs"
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
)
type MessageInterceptorFunc func(ctx context.Context, globalConfig *config.GlobalConfig, req *msg.SendMsgReq) (*sdkws.MsgData, error)
func MessageHasReadEnabled(_ context.Context, globalConfig *config.GlobalConfig, req *msg.SendMsgReq) (*sdkws.MsgData, error) {
switch {
case req.MsgData.ContentType == constant.HasReadReceipt && req.MsgData.SessionType == constant.SingleChatType:
if !globalConfig.SingleMessageHasReadReceiptEnable {
return nil, errs.ErrMessageHasReadDisable.Wrap()
}
return req.MsgData, nil
case req.MsgData.ContentType == constant.HasReadReceipt && req.MsgData.SessionType == constant.SuperGroupChatType:
if !globalConfig.GroupMessageHasReadReceiptEnable {
return nil, errs.ErrMessageHasReadDisable.Wrap()
}
return req.MsgData, nil
}
return req.MsgData, nil
}
+5 -11
View File
@@ -17,15 +17,12 @@ package msg
import (
"context"
"github.com/OpenIMSDK/protocol/constant"
pbmsg "github.com/OpenIMSDK/protocol/msg"
"github.com/OpenIMSDK/tools/mcontext"
"github.com/openimsdk/protocol/constant"
pbmsg "github.com/openimsdk/protocol/msg"
"github.com/openimsdk/tools/mcontext"
)
func (m *msgServer) SetSendMsgStatus(
ctx context.Context,
req *pbmsg.SetSendMsgStatusReq,
) (*pbmsg.SetSendMsgStatusResp, error) {
func (m *msgServer) SetSendMsgStatus(ctx context.Context, req *pbmsg.SetSendMsgStatusReq) (*pbmsg.SetSendMsgStatusResp, error) {
resp := &pbmsg.SetSendMsgStatusResp{}
if err := m.MsgDatabase.SetSendMsgStatus(ctx, mcontext.GetOperationID(ctx), req.Status); err != nil {
return nil, err
@@ -33,10 +30,7 @@ func (m *msgServer) SetSendMsgStatus(
return resp, nil
}
func (m *msgServer) GetSendMsgStatus(
ctx context.Context,
req *pbmsg.GetSendMsgStatusReq,
) (*pbmsg.GetSendMsgStatusResp, error) {
func (m *msgServer) GetSendMsgStatus(ctx context.Context, req *pbmsg.GetSendMsgStatusReq) (*pbmsg.GetSendMsgStatusResp, error) {
resp := &pbmsg.GetSendMsgStatusResp{}
status, err := m.MsgDatabase.GetSendMsgStatus(ctx, mcontext.GetOperationID(ctx))
if IsNotFound(err) {
+50
View File
@@ -0,0 +1,50 @@
// Copyright © 2023 OpenIM. 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 msg
import (
"context"
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
"github.com/openimsdk/protocol/constant"
"github.com/openimsdk/protocol/sdkws"
)
type MsgNotificationSender struct {
*rpcclient.NotificationSender
}
func NewMsgNotificationSender(config *Config, opts ...rpcclient.NotificationSenderOptions) *MsgNotificationSender {
return &MsgNotificationSender{rpcclient.NewNotificationSender(&config.NotificationConfig, opts...)}
}
func (m *MsgNotificationSender) UserDeleteMsgsNotification(ctx context.Context, userID, conversationID string, seqs []int64) {
tips := sdkws.DeleteMsgsTips{
UserID: userID,
ConversationID: conversationID,
Seqs: seqs,
}
m.Notification(ctx, userID, userID, constant.DeleteMsgsNotification, &tips)
}
func (m *MsgNotificationSender) MarkAsReadNotification(ctx context.Context, conversationID string, sessionType int32, sendID, recvID string, seqs []int64, hasReadSeq int64) {
tips := &sdkws.MarkAsReadTips{
MarkAsReadUserID: sendID,
ConversationID: conversationID,
Seqs: seqs,
HasReadSeq: hasReadSeq,
}
m.NotificationWithSessionType(ctx, sendID, recvID, constant.HasReadReceipt, sessionType, tips)
}
+30 -36
View File
@@ -19,29 +19,29 @@ import (
"encoding/json"
"time"
"github.com/OpenIMSDK/protocol/constant"
"github.com/OpenIMSDK/protocol/msg"
"github.com/OpenIMSDK/protocol/sdkws"
"github.com/OpenIMSDK/tools/errs"
"github.com/OpenIMSDK/tools/log"
"github.com/OpenIMSDK/tools/mcontext"
"github.com/OpenIMSDK/tools/utils"
"github.com/openimsdk/open-im-server/v3/pkg/authverify"
unrelationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/unrelation"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
"github.com/openimsdk/protocol/constant"
"github.com/openimsdk/protocol/msg"
"github.com/openimsdk/protocol/sdkws"
"github.com/openimsdk/tools/errs"
"github.com/openimsdk/tools/log"
"github.com/openimsdk/tools/mcontext"
"github.com/openimsdk/tools/utils/datautil"
)
func (m *msgServer) RevokeMsg(ctx context.Context, req *msg.RevokeMsgReq) (*msg.RevokeMsgResp, error) {
defer log.ZDebug(ctx, "RevokeMsg return line")
if req.UserID == "" {
return nil, errs.ErrArgs.Wrap("user_id is empty")
return nil, errs.ErrArgs.WrapMsg("user_id is empty")
}
if req.ConversationID == "" {
return nil, errs.ErrArgs.Wrap("conversation_id is empty")
return nil, errs.ErrArgs.WrapMsg("conversation_id is empty")
}
if req.Seq < 0 {
return nil, errs.ErrArgs.Wrap("seq is invalid")
return nil, errs.ErrArgs.WrapMsg("seq is invalid")
}
if err := authverify.CheckAccessV3(ctx, req.UserID, m.config); err != nil {
if err := authverify.CheckAccessV3(ctx, req.UserID, m.config.Share.IMAdminUserID); err != nil {
return nil, err
}
user, err := m.UserLocalCache.GetUserInfo(ctx, req.UserID)
@@ -53,24 +53,24 @@ func (m *msgServer) RevokeMsg(ctx context.Context, req *msg.RevokeMsgReq) (*msg.
return nil, err
}
if len(msgs) == 0 || msgs[0] == nil {
return nil, errs.ErrRecordNotFound.Wrap("msg not found")
return nil, errs.ErrRecordNotFound.WrapMsg("msg not found")
}
if msgs[0].ContentType == constant.MsgRevokeNotification {
return nil, errs.ErrMsgAlreadyRevoke.Wrap("msg already revoke")
return nil, servererrs.ErrMsgAlreadyRevoke.WrapMsg("msg already revoke")
}
data, _ := json.Marshal(msgs[0])
log.ZInfo(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
if !authverify.IsAppManagerUid(ctx, m.config) {
if !authverify.IsAppManagerUid(ctx, m.config.Share.IMAdminUserID) {
switch msgs[0].SessionType {
case constant.SingleChatType:
if err := authverify.CheckAccessV3(ctx, msgs[0].SendID, m.config); err != nil {
if err := authverify.CheckAccessV3(ctx, msgs[0].SendID, m.config.Share.IMAdminUserID); err != nil {
return nil, err
}
role = user.AppMangerLevel
case constant.SuperGroupChatType:
members, err := m.GroupLocalCache.GetGroupMemberInfoMap(ctx, msgs[0].GroupID, utils.Distinct([]string{req.UserID, msgs[0].SendID}))
case constant.ReadGroupChatType:
members, err := m.GroupLocalCache.GetGroupMemberInfoMap(ctx, msgs[0].GroupID, datautil.Distinct([]string{req.UserID, msgs[0].SendID}))
if err != nil {
return nil, err
}
@@ -79,21 +79,21 @@ func (m *msgServer) RevokeMsg(ctx context.Context, req *msg.RevokeMsgReq) (*msg.
case constant.GroupOwner:
case constant.GroupAdmin:
if members[msgs[0].SendID].RoleLevel != constant.GroupOrdinaryUsers {
return nil, errs.ErrNoPermission.Wrap("no permission")
return nil, errs.ErrNoPermission.WrapMsg("no permission")
}
default:
return nil, errs.ErrNoPermission.Wrap("no permission")
return nil, errs.ErrNoPermission.WrapMsg("no permission")
}
}
if member := members[req.UserID]; member != nil {
role = member.RoleLevel
}
default:
return nil, errs.ErrInternalServer.Wrap("msg sessionType not supported")
return nil, errs.ErrInternalServer.WrapMsg("msg sessionType not supported")
}
}
now := time.Now().UnixMilli()
err = m.MsgDatabase.RevokeMsg(ctx, req.ConversationID, req.Seq, &unrelationtb.RevokeModel{
err = m.MsgDatabase.RevokeMsg(ctx, req.ConversationID, req.Seq, &relation.RevokeModel{
Role: role,
UserID: req.UserID,
Nickname: user.Nickname,
@@ -104,11 +104,9 @@ func (m *msgServer) RevokeMsg(ctx context.Context, req *msg.RevokeMsgReq) (*msg.
}
revokerUserID := mcontext.GetOpUserID(ctx)
var flag bool
if len(m.config.Manager.UserID) > 0 {
flag = utils.Contain(revokerUserID, m.config.Manager.UserID...)
}
if len(m.config.Manager.UserID) == 0 && len(m.config.IMAdmin.UserID) > 0 {
flag = utils.Contain(revokerUserID, m.config.IMAdmin.UserID...)
if len(m.config.Share.IMAdminUserID) > 0 {
flag = datautil.Contain(revokerUserID, m.config.Share.IMAdminUserID...)
}
tips := sdkws.RevokeMsgTips{
RevokerUserID: revokerUserID,
@@ -120,16 +118,12 @@ func (m *msgServer) RevokeMsg(ctx context.Context, req *msg.RevokeMsgReq) (*msg.
IsAdminRevoke: flag,
}
var recvID string
if msgs[0].SessionType == constant.SuperGroupChatType {
if msgs[0].SessionType == constant.ReadGroupChatType {
recvID = msgs[0].GroupID
} else {
recvID = msgs[0].RecvID
}
if err := m.notificationSender.NotificationWithSesstionType(ctx, req.UserID, recvID, constant.MsgRevokeNotification, msgs[0].SessionType, &tips); err != nil {
return nil, err
}
if err = CallbackAfterRevokeMsg(ctx, m.config, req); err != nil {
return nil, err
}
m.notificationSender.NotificationWithSessionType(ctx, req.UserID, recvID, constant.MsgRevokeNotification, msgs[0].SessionType, &tips)
m.webhookAfterRevokeMsg(ctx, &m.config.WebhooksConfig.AfterRevokeMsg, req)
return &msg.RevokeMsgResp{}, nil
}
+44 -65
View File
@@ -17,67 +17,59 @@ package msg
import (
"context"
"github.com/OpenIMSDK/protocol/constant"
pbconversation "github.com/OpenIMSDK/protocol/conversation"
pbmsg "github.com/OpenIMSDK/protocol/msg"
"github.com/OpenIMSDK/protocol/sdkws"
"github.com/OpenIMSDK/protocol/wrapperspb"
"github.com/OpenIMSDK/tools/errs"
"github.com/OpenIMSDK/tools/log"
"github.com/OpenIMSDK/tools/mcontext"
"github.com/OpenIMSDK/tools/utils"
"github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics"
"github.com/openimsdk/open-im-server/v3/pkg/msgprocessor"
"github.com/openimsdk/open-im-server/v3/pkg/util/conversationutil"
"github.com/openimsdk/protocol/constant"
pbconversation "github.com/openimsdk/protocol/conversation"
pbmsg "github.com/openimsdk/protocol/msg"
"github.com/openimsdk/protocol/sdkws"
"github.com/openimsdk/protocol/wrapperspb"
"github.com/openimsdk/tools/errs"
"github.com/openimsdk/tools/log"
"github.com/openimsdk/tools/mcontext"
"github.com/openimsdk/tools/utils/datautil"
"github.com/openimsdk/tools/utils/stringutil"
)
func (m *msgServer) SendMsg(ctx context.Context, req *pbmsg.SendMsgReq) (resp *pbmsg.SendMsgResp, error error) {
resp = &pbmsg.SendMsgResp{}
func (m *msgServer) SendMsg(ctx context.Context, req *pbmsg.SendMsgReq) (*pbmsg.SendMsgResp, error) {
if req.MsgData != nil {
flag := isMessageHasReadEnabled(req.MsgData, m.config)
if !flag {
return nil, errs.ErrMessageHasReadDisable.Wrap()
}
m.encapsulateMsgData(req.MsgData)
switch req.MsgData.SessionType {
case constant.SingleChatType:
return m.sendMsgSingleChat(ctx, req)
case constant.NotificationChatType:
return m.sendMsgNotification(ctx, req)
case constant.SuperGroupChatType:
case constant.ReadGroupChatType:
return m.sendMsgSuperGroupChat(ctx, req)
default:
return nil, errs.ErrArgs.Wrap("unknown sessionType")
return nil, errs.ErrArgs.WrapMsg("unknown sessionType")
}
} else {
return nil, errs.ErrArgs.Wrap("msgData is nil")
}
return nil, errs.ErrArgs.WrapMsg("msgData is nil")
}
func (m *msgServer) sendMsgSuperGroupChat(
ctx context.Context,
req *pbmsg.SendMsgReq,
) (resp *pbmsg.SendMsgResp, err error) {
func (m *msgServer) sendMsgSuperGroupChat(ctx context.Context, req *pbmsg.SendMsgReq) (resp *pbmsg.SendMsgResp, err error) {
if err = m.messageVerification(ctx, req); err != nil {
prommetrics.GroupChatMsgProcessFailedCounter.Inc()
return nil, err
}
if err = callbackBeforeSendGroupMsg(ctx, m.config, req); err != nil {
return nil, err
}
if err := callbackMsgModify(ctx, m.config, req); err != nil {
if err = m.webhookBeforeSendGroupMsg(ctx, &m.config.WebhooksConfig.BeforeSendGroupMsg, req); err != nil {
return nil, err
}
err = m.MsgDatabase.MsgToMQ(ctx, utils.GenConversationUniqueKeyForGroup(req.MsgData.GroupID), req.MsgData)
if err := m.webhookBeforeMsgModify(ctx, &m.config.WebhooksConfig.BeforeMsgModify, req); err != nil {
return nil, err
}
err = m.MsgDatabase.MsgToMQ(ctx, conversationutil.GenConversationUniqueKeyForGroup(req.MsgData.GroupID), req.MsgData)
if err != nil {
return nil, err
}
if req.MsgData.ContentType == constant.AtText {
go m.setConversationAtInfo(ctx, req.MsgData)
}
if err = callbackAfterSendGroupMsg(ctx, m.config, req); err != nil {
log.ZWarn(ctx, "CallbackAfterSendGroupMsg", err)
}
m.webhookAfterSendGroupMsg(ctx, &m.config.WebhooksConfig.AfterSendGroupMsg, req)
prommetrics.GroupChatMsgProcessSuccessCounter.Inc()
resp = &pbmsg.SendMsgResp{}
resp.SendTime = req.MsgData.SendTime
@@ -95,43 +87,39 @@ func (m *msgServer) setConversationAtInfo(nctx context.Context, msg *sdkws.MsgDa
ConversationType: msg.SessionType,
GroupID: msg.GroupID,
}
tagAll := utils.IsContain(constant.AtAllString, msg.AtUserIDList)
tagAll := datautil.Contain(constant.AtAllString, msg.AtUserIDList...)
if tagAll {
memberUserIDList, err := m.GroupLocalCache.GetGroupMemberIDs(ctx, msg.GroupID)
if err != nil {
log.ZWarn(ctx, "GetGroupMemberIDs", err)
return
}
atUserID = utils.DifferenceString([]string{constant.AtAllString}, msg.AtUserIDList)
atUserID = stringutil.DifferenceString([]string{constant.AtAllString}, msg.AtUserIDList)
if len(atUserID) == 0 { // just @everyone
conversation.GroupAtType = &wrapperspb.Int32Value{Value: constant.AtAll}
} else { //@Everyone and @other people
} else { // @Everyone and @other people
conversation.GroupAtType = &wrapperspb.Int32Value{Value: constant.AtAllAtMe}
err = m.Conversation.SetConversations(ctx, atUserID, conversation)
if err != nil {
log.ZWarn(ctx, "SetConversations", err, "userID", atUserID, "conversation", conversation)
}
memberUserIDList = utils.DifferenceString(atUserID, memberUserIDList)
memberUserIDList = stringutil.DifferenceString(atUserID, memberUserIDList)
}
conversation.GroupAtType = &wrapperspb.Int32Value{Value: constant.AtAll}
err = m.Conversation.SetConversations(ctx, memberUserIDList, conversation)
if err != nil {
log.ZWarn(ctx, "SetConversations", err, "userID", memberUserIDList, "conversation", conversation)
}
} else {
conversation.GroupAtType = &wrapperspb.Int32Value{Value: constant.AtMe}
err := m.Conversation.SetConversations(ctx, msg.AtUserIDList, conversation)
if err != nil {
log.ZWarn(ctx, "SetConversations", err, msg.AtUserIDList, conversation)
}
}
conversation.GroupAtType = &wrapperspb.Int32Value{Value: constant.AtMe}
err := m.Conversation.SetConversations(ctx, msg.AtUserIDList, conversation)
if err != nil {
log.ZWarn(ctx, "SetConversations", err, msg.AtUserIDList, conversation)
}
}
func (m *msgServer) sendMsgNotification(
ctx context.Context,
req *pbmsg.SendMsgReq,
) (resp *pbmsg.SendMsgResp, err error) {
if err := m.MsgDatabase.MsgToMQ(ctx, utils.GenConversationUniqueKeyForSingle(req.MsgData.SendID, req.MsgData.RecvID), req.MsgData); err != nil {
func (m *msgServer) sendMsgNotification(ctx context.Context, req *pbmsg.SendMsgReq) (resp *pbmsg.SendMsgResp, err error) {
if err := m.MsgDatabase.MsgToMQ(ctx, conversationutil.GenConversationUniqueKeyForSingle(req.MsgData.SendID, req.MsgData.RecvID), req.MsgData); err != nil {
return nil, err
}
resp = &pbmsg.SendMsgResp{
@@ -143,7 +131,6 @@ func (m *msgServer) sendMsgNotification(
}
func (m *msgServer) sendMsgSingleChat(ctx context.Context, req *pbmsg.SendMsgReq) (resp *pbmsg.SendMsgResp, err error) {
log.ZDebug(ctx, "sendMsgSingleChat return")
if err := m.messageVerification(ctx, req); err != nil {
return nil, err
}
@@ -153,7 +140,7 @@ func (m *msgServer) sendMsgSingleChat(ctx context.Context, req *pbmsg.SendMsgReq
isSend, err = m.modifyMessageByUserMessageReceiveOpt(
ctx,
req.MsgData.RecvID,
utils.GenConversationIDForSingle(req.MsgData.SendID, req.MsgData.RecvID),
conversationutil.GenConversationIDForSingle(req.MsgData.SendID, req.MsgData.RecvID),
constant.SingleChatType,
req,
)
@@ -165,31 +152,23 @@ func (m *msgServer) sendMsgSingleChat(ctx context.Context, req *pbmsg.SendMsgReq
prommetrics.SingleChatMsgProcessFailedCounter.Inc()
return nil, nil
} else {
if err = callbackBeforeSendSingleMsg(ctx, m.config, req); err != nil {
if err = m.webhookBeforeSendSingleMsg(ctx, &m.config.WebhooksConfig.BeforeSendSingleMsg, req); err != nil {
return nil, err
}
if err := m.webhookBeforeMsgModify(ctx, &m.config.WebhooksConfig.BeforeMsgModify, req); err != nil {
return nil, err
}
if err := callbackMsgModify(ctx, m.config, req); err != nil {
return nil, err
}
if err := m.MsgDatabase.MsgToMQ(ctx, utils.GenConversationUniqueKeyForSingle(req.MsgData.SendID, req.MsgData.RecvID), req.MsgData); err != nil {
if err := m.MsgDatabase.MsgToMQ(ctx, conversationutil.GenConversationUniqueKeyForSingle(req.MsgData.SendID, req.MsgData.RecvID), req.MsgData); err != nil {
prommetrics.SingleChatMsgProcessFailedCounter.Inc()
return nil, err
}
err = callbackAfterSendSingleMsg(ctx, m.config, req)
if err != nil {
log.ZWarn(ctx, "CallbackAfterSendSingleMsg", err, "req", req)
}
resp = &pbmsg.SendMsgResp{
m.webhookAfterSendSingleMsg(ctx, &m.config.WebhooksConfig.AfterSendSingleMsg, req)
prommetrics.SingleChatMsgProcessSuccessCounter.Inc()
return &pbmsg.SendMsgResp{
ServerMsgID: req.MsgData.ServerMsgID,
ClientMsgID: req.MsgData.ClientMsgID,
SendTime: req.MsgData.SendTime,
}
prommetrics.SingleChatMsgProcessSuccessCounter.Inc()
return resp, nil
}, nil
}
}
func (m *msgServer) BatchSendMsg(ctx context.Context, in *pbmsg.BatchSendMessageReq) (*pbmsg.BatchSendMessageResp, error) {
return nil, nil
}
+2 -5
View File
@@ -17,13 +17,10 @@ package msg
import (
"context"
pbmsg "github.com/OpenIMSDK/protocol/msg"
pbmsg "github.com/openimsdk/protocol/msg"
)
func (m *msgServer) GetConversationMaxSeq(
ctx context.Context,
req *pbmsg.GetConversationMaxSeqReq,
) (resp *pbmsg.GetConversationMaxSeqResp, err error) {
func (m *msgServer) GetConversationMaxSeq(ctx context.Context, req *pbmsg.GetConversationMaxSeqReq) (*pbmsg.GetConversationMaxSeqResp, error) {
maxSeq, err := m.MsgDatabase.GetMaxSeq(ctx, req.ConversationID)
if err != nil {
return nil, err
+66 -50
View File
@@ -15,69 +15,84 @@
package msg
import (
"github.com/OpenIMSDK/protocol/constant"
"github.com/OpenIMSDK/protocol/conversation"
"github.com/OpenIMSDK/protocol/msg"
"github.com/OpenIMSDK/tools/discoveryregistry"
"context"
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
"github.com/openimsdk/open-im-server/v3/pkg/common/webhook"
"github.com/openimsdk/protocol/sdkws"
"github.com/openimsdk/tools/db/mongoutil"
"github.com/openimsdk/tools/db/redisutil"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/controller"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/unrelation"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo"
"github.com/openimsdk/open-im-server/v3/pkg/rpccache"
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
"github.com/openimsdk/protocol/constant"
"github.com/openimsdk/protocol/conversation"
"github.com/openimsdk/protocol/msg"
"github.com/openimsdk/tools/discovery"
"google.golang.org/grpc"
)
type MessageInterceptorFunc func(ctx context.Context, globalConfig *Config, req *msg.SendMsgReq) (*sdkws.MsgData, error)
type (
// MessageInterceptorChain defines a chain of message interceptor functions.
MessageInterceptorChain []MessageInterceptorFunc
msgServer struct {
RegisterCenter discoveryregistry.SvcDiscoveryRegistry
MsgDatabase controller.CommonMsgDatabase
Conversation *rpcclient.ConversationRpcClient
UserLocalCache *rpccache.UserLocalCache
FriendLocalCache *rpccache.FriendLocalCache
GroupLocalCache *rpccache.GroupLocalCache
ConversationLocalCache *rpccache.ConversationLocalCache
Handlers MessageInterceptorChain
notificationSender *rpcclient.NotificationSender
config *config.GlobalConfig
// MsgServer encapsulates dependencies required for message handling.
msgServer struct {
RegisterCenter discovery.SvcDiscoveryRegistry // Service discovery registry for service registration.
MsgDatabase controller.CommonMsgDatabase // Interface for message database operations.
Conversation *rpcclient.ConversationRpcClient // RPC client for conversation service.
UserLocalCache *rpccache.UserLocalCache // Local cache for user data.
FriendLocalCache *rpccache.FriendLocalCache // Local cache for friend data.
GroupLocalCache *rpccache.GroupLocalCache // Local cache for group data.
ConversationLocalCache *rpccache.ConversationLocalCache // Local cache for conversation data.
Handlers MessageInterceptorChain // Chain of handlers for processing messages.
notificationSender *rpcclient.NotificationSender // RPC client for sending notifications.
config *Config // Global configuration settings.
webhookClient *webhook.Client
}
Config struct {
RpcConfig config.Msg
RedisConfig config.Redis
MongodbConfig config.Mongo
KafkaConfig config.Kafka
ZookeeperConfig config.ZooKeeper
NotificationConfig config.Notification
Share config.Share
WebhooksConfig config.Webhooks
LocalCacheConfig config.LocalCache
}
)
func (m *msgServer) addInterceptorHandler(interceptorFunc ...MessageInterceptorFunc) {
m.Handlers = append(m.Handlers, interceptorFunc...)
}
//func (m *msgServer) execInterceptorHandler(ctx context.Context, config *config.GlobalConfig, req *msg.SendMsgReq) error {
// for _, handler := range m.Handlers {
// msgData, err := handler(ctx, config, req)
// if err != nil {
// return err
// }
// req.MsgData = msgData
// }
// return nil
//}
func Start(config *config.GlobalConfig, client discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) error {
rdb, err := cache.NewRedis(config)
func Start(ctx context.Context, config *Config, client discovery.SvcDiscoveryRegistry, server *grpc.Server) error {
mgocli, err := mongoutil.NewMongoDB(ctx, config.MongodbConfig.Build())
if err != nil {
return err
}
mongo, err := unrelation.NewMongo(config)
rdb, err := redisutil.NewRedisClient(ctx, config.RedisConfig.Build())
if err != nil {
return err
}
if err := mongo.CreateMsgIndex(); err != nil {
msgDocModel, err := mgo.NewMsgMongo(mgocli.GetDB())
if err != nil {
return err
}
cacheModel := cache.NewMsgCacheModel(rdb, config)
msgDocModel := unrelation.NewMsgMongoDriver(mongo.GetDatabase(config.Mongo.Database))
conversationClient := rpcclient.NewConversationRpcClient(client, config)
userRpcClient := rpcclient.NewUserRpcClient(client, config)
groupRpcClient := rpcclient.NewGroupRpcClient(client, config)
friendRpcClient := rpcclient.NewFriendRpcClient(client, config)
msgDatabase, err := controller.NewCommonMsgDatabase(msgDocModel, cacheModel, config)
//todo MsgCacheTimeout
msgModel := cache.NewMsgCache(rdb, config.RedisConfig.EnablePipeline)
seqModel := cache.NewSeqCache(rdb)
conversationClient := rpcclient.NewConversationRpcClient(client, config.Share.RpcRegisterName.Conversation)
userRpcClient := rpcclient.NewUserRpcClient(client, config.Share.RpcRegisterName.User, config.Share.IMAdminUserID)
groupRpcClient := rpcclient.NewGroupRpcClient(client, config.Share.RpcRegisterName.Group)
friendRpcClient := rpcclient.NewFriendRpcClient(client, config.Share.RpcRegisterName.Friend)
msgDatabase, err := controller.NewCommonMsgDatabase(msgDocModel, msgModel, seqModel, &config.KafkaConfig)
if err != nil {
return err
}
@@ -85,28 +100,29 @@ func Start(config *config.GlobalConfig, client discoveryregistry.SvcDiscoveryReg
Conversation: &conversationClient,
MsgDatabase: msgDatabase,
RegisterCenter: client,
UserLocalCache: rpccache.NewUserLocalCache(userRpcClient, rdb),
GroupLocalCache: rpccache.NewGroupLocalCache(groupRpcClient, rdb),
ConversationLocalCache: rpccache.NewConversationLocalCache(conversationClient, rdb),
FriendLocalCache: rpccache.NewFriendLocalCache(friendRpcClient, rdb),
UserLocalCache: rpccache.NewUserLocalCache(userRpcClient, &config.LocalCacheConfig, rdb),
GroupLocalCache: rpccache.NewGroupLocalCache(groupRpcClient, &config.LocalCacheConfig, rdb),
ConversationLocalCache: rpccache.NewConversationLocalCache(conversationClient, &config.LocalCacheConfig, rdb),
FriendLocalCache: rpccache.NewFriendLocalCache(friendRpcClient, &config.LocalCacheConfig, rdb),
config: config,
webhookClient: webhook.NewWebhookClient(config.WebhooksConfig.URL),
}
s.notificationSender = rpcclient.NewNotificationSender(config, rpcclient.WithLocalSendMsg(s.SendMsg))
s.addInterceptorHandler(MessageHasReadEnabled)
s.notificationSender = rpcclient.NewNotificationSender(&config.NotificationConfig, rpcclient.WithLocalSendMsg(s.SendMsg))
msg.RegisterMsgServer(server, s)
return nil
}
func (m *msgServer) conversationAndGetRecvID(conversation *conversation.Conversation, userID string) (recvID string) {
func (m *msgServer) conversationAndGetRecvID(conversation *conversation.Conversation, userID string) string {
if conversation.ConversationType == constant.SingleChatType ||
conversation.ConversationType == constant.NotificationChatType {
if userID == conversation.OwnerUserID {
recvID = conversation.UserID
return conversation.UserID
} else {
recvID = conversation.OwnerUserID
return conversation.OwnerUserID
}
} else if conversation.ConversationType == constant.SuperGroupChatType {
recvID = conversation.GroupID
} else if conversation.ConversationType == constant.ReadGroupChatType {
return conversation.GroupID
}
return
return ""
}
+8 -23
View File
@@ -18,28 +18,20 @@ import (
"context"
"time"
"github.com/OpenIMSDK/protocol/msg"
"github.com/OpenIMSDK/protocol/sdkws"
"github.com/OpenIMSDK/tools/utils"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/unrelation"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
"github.com/openimsdk/protocol/msg"
"github.com/openimsdk/protocol/sdkws"
"github.com/openimsdk/tools/utils/datautil"
)
func (m *msgServer) GetActiveUser(ctx context.Context, req *msg.GetActiveUserReq) (*msg.GetActiveUserResp, error) {
msgCount, userCount, users, dateCount, err := m.MsgDatabase.RangeUserSendCount(
ctx,
time.UnixMilli(req.Start),
time.UnixMilli(req.End),
req.Group,
req.Ase,
req.Pagination.PageNumber,
req.Pagination.ShowNumber,
)
msgCount, userCount, users, dateCount, err := m.MsgDatabase.RangeUserSendCount(ctx, time.UnixMilli(req.Start), time.UnixMilli(req.End), req.Group, req.Ase, req.Pagination.PageNumber, req.Pagination.ShowNumber)
if err != nil {
return nil, err
}
var pbUsers []*msg.ActiveUser
if len(users) > 0 {
userIDs := utils.Slice(users, func(e *unrelation.UserCount) string { return e.UserID })
userIDs := datautil.Slice(users, func(e *relation.UserCount) string { return e.UserID })
userMap, err := m.UserLocalCache.GetUsersInfoMap(ctx, userIDs)
if err != nil {
return nil, err
@@ -68,20 +60,13 @@ func (m *msgServer) GetActiveUser(ctx context.Context, req *msg.GetActiveUserReq
}
func (m *msgServer) GetActiveGroup(ctx context.Context, req *msg.GetActiveGroupReq) (*msg.GetActiveGroupResp, error) {
msgCount, groupCount, groups, dateCount, err := m.MsgDatabase.RangeGroupSendCount(
ctx,
time.UnixMilli(req.Start),
time.UnixMilli(req.End),
req.Ase,
req.Pagination.PageNumber,
req.Pagination.ShowNumber,
)
msgCount, groupCount, groups, dateCount, err := m.MsgDatabase.RangeGroupSendCount(ctx, time.UnixMilli(req.Start), time.UnixMilli(req.End), req.Ase, req.Pagination.PageNumber, req.Pagination.ShowNumber)
if err != nil {
return nil, err
}
var pbgroups []*msg.ActiveGroup
if len(groups) > 0 {
groupIDs := utils.Slice(groups, func(e *unrelation.GroupCount) string { return e.GroupID })
groupIDs := datautil.Slice(groups, func(e *relation.GroupCount) string { return e.GroupID })
resp, err := m.GroupLocalCache.GetGroupInfos(ctx, groupIDs)
if err != nil {
return nil, err
+15 -16
View File
@@ -16,20 +16,19 @@ package msg
import (
"context"
"github.com/openimsdk/open-im-server/v3/pkg/util/conversationutil"
"github.com/openimsdk/tools/utils/datautil"
"github.com/openimsdk/tools/utils/timeutil"
"github.com/OpenIMSDK/protocol/constant"
"github.com/OpenIMSDK/protocol/msg"
"github.com/OpenIMSDK/protocol/sdkws"
"github.com/OpenIMSDK/tools/log"
"github.com/OpenIMSDK/tools/utils"
"github.com/openimsdk/open-im-server/v3/pkg/authverify"
"github.com/openimsdk/open-im-server/v3/pkg/msgprocessor"
"github.com/openimsdk/protocol/constant"
"github.com/openimsdk/protocol/msg"
"github.com/openimsdk/protocol/sdkws"
"github.com/openimsdk/tools/log"
)
func (m *msgServer) PullMessageBySeqs(
ctx context.Context,
req *sdkws.PullMessageBySeqsReq,
) (*sdkws.PullMessageBySeqsResp, error) {
func (m *msgServer) PullMessageBySeqs(ctx context.Context, req *sdkws.PullMessageBySeqsReq) (*sdkws.PullMessageBySeqsResp, error) {
resp := &sdkws.PullMessageBySeqsResp{}
resp.Msgs = make(map[string]*sdkws.PullMsgs)
resp.NotificationMsgs = make(map[string]*sdkws.PullMsgs)
@@ -88,7 +87,7 @@ func (m *msgServer) PullMessageBySeqs(
}
func (m *msgServer) GetMaxSeq(ctx context.Context, req *sdkws.GetMaxSeqReq) (*sdkws.GetMaxSeqResp, error) {
if err := authverify.CheckAccessV3(ctx, req.UserID, m.config); err != nil {
if err := authverify.CheckAccessV3(ctx, req.UserID, m.config.Share.IMAdminUserID); err != nil {
return nil, err
}
conversationIDs, err := m.ConversationLocalCache.GetConversationIDs(ctx, req.UserID)
@@ -96,9 +95,9 @@ func (m *msgServer) GetMaxSeq(ctx context.Context, req *sdkws.GetMaxSeqReq) (*sd
return nil, err
}
for _, conversationID := range conversationIDs {
conversationIDs = append(conversationIDs, utils.GetNotificationConversationIDByConversationID(conversationID))
conversationIDs = append(conversationIDs, conversationutil.GetNotificationConversationIDByConversationID(conversationID))
}
conversationIDs = append(conversationIDs, utils.GetSelfNotificationConversationID(req.UserID))
conversationIDs = append(conversationIDs, conversationutil.GetSelfNotificationConversationID(req.UserID))
log.ZDebug(ctx, "GetMaxSeq", "conversationIDs", conversationIDs)
maxSeqs, err := m.MsgDatabase.GetMaxSeqs(ctx, conversationIDs)
if err != nil {
@@ -133,7 +132,7 @@ func (m *msgServer) SearchMessage(ctx context.Context, req *msg.SearchMessageReq
switch chatLog.SessionType {
case constant.SingleChatType, constant.NotificationChatType:
recvIDs = append(recvIDs, chatLog.RecvID)
case constant.GroupChatType, constant.SuperGroupChatType:
case constant.WriteGroupChatType, constant.ReadGroupChatType:
groupIDs = append(groupIDs, chatLog.GroupID)
}
}
@@ -175,7 +174,7 @@ func (m *msgServer) SearchMessage(ctx context.Context, req *msg.SearchMessageReq
// Construct response with updated information
for _, chatLog := range chatLogs {
pbchatLog := &msg.ChatLog{}
utils.CopyStructFields(pbchatLog, chatLog)
datautil.CopyStructFields(pbchatLog, chatLog)
pbchatLog.SendTime = chatLog.SendTime
pbchatLog.CreateTime = chatLog.CreateTime
if chatLog.SenderNickname == "" {
@@ -184,7 +183,7 @@ func (m *msgServer) SearchMessage(ctx context.Context, req *msg.SearchMessageReq
switch chatLog.SessionType {
case constant.SingleChatType, constant.NotificationChatType:
pbchatLog.RecvNickname = recvMap[chatLog.RecvID]
case constant.GroupChatType, constant.SuperGroupChatType:
case constant.WriteGroupChatType, constant.ReadGroupChatType:
groupInfo := groupMap[chatLog.GroupID]
pbchatLog.SenderFaceURL = groupInfo.FaceURL
pbchatLog.GroupMemberCount = groupInfo.MemberCount // Reflects actual member count
@@ -200,5 +199,5 @@ func (m *msgServer) SearchMessage(ctx context.Context, req *msg.SearchMessageReq
}
func (m *msgServer) GetServerTime(ctx context.Context, _ *msg.GetServerTimeReq) (*msg.GetServerTimeResp, error) {
return &msg.GetServerTimeResp{ServerTime: utils.GetCurrentTimestampByMill()}, nil
return &msg.GetServerTimeResp{ServerTime: timeutil.GetCurrentTimestampByMill()}, nil
}
+2 -23
View File
@@ -15,34 +15,13 @@
package msg
import (
"github.com/OpenIMSDK/protocol/constant"
"github.com/OpenIMSDK/protocol/sdkws"
"github.com/OpenIMSDK/tools/utils"
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
"github.com/openimsdk/tools/errs"
"github.com/redis/go-redis/v9"
"go.mongodb.org/mongo-driver/mongo"
)
func isMessageHasReadEnabled(msgData *sdkws.MsgData, config *config.GlobalConfig) bool {
switch {
case msgData.ContentType == constant.HasReadReceipt && msgData.SessionType == constant.SingleChatType:
if config.SingleMessageHasReadReceiptEnable {
return true
} else {
return false
}
case msgData.ContentType == constant.HasReadReceipt && msgData.SessionType == constant.SuperGroupChatType:
if config.GroupMessageHasReadReceiptEnable {
return true
} else {
return false
}
}
return true
}
func IsNotFound(err error) bool {
switch utils.Unwrap(err) {
switch errs.Unwrap(err) {
case redis.Nil, mongo.ErrNoDocuments:
return true
default:
+40 -50
View File
@@ -16,16 +16,18 @@ package msg
import (
"context"
"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
"github.com/openimsdk/tools/utils/datautil"
"github.com/openimsdk/tools/utils/encrypt"
"github.com/openimsdk/tools/utils/timeutil"
"math/rand"
"strconv"
"time"
"github.com/OpenIMSDK/protocol/constant"
"github.com/OpenIMSDK/protocol/msg"
"github.com/OpenIMSDK/protocol/sdkws"
"github.com/OpenIMSDK/tools/errs"
"github.com/OpenIMSDK/tools/log"
"github.com/OpenIMSDK/tools/utils"
"github.com/openimsdk/protocol/constant"
"github.com/openimsdk/protocol/msg"
"github.com/openimsdk/protocol/sdkws"
"github.com/openimsdk/tools/errs"
)
var ExcludeContentType = []int{constant.HasReadReceipt}
@@ -50,10 +52,7 @@ type MessageRevoked struct {
func (m *msgServer) messageVerification(ctx context.Context, data *msg.SendMsgReq) error {
switch data.MsgData.SessionType {
case constant.SingleChatType:
if len(m.config.Manager.UserID) > 0 && utils.IsContain(data.MsgData.SendID, m.config.Manager.UserID) {
return nil
}
if utils.IsContain(data.MsgData.SendID, m.config.IMAdmin.UserID) {
if datautil.Contain(data.MsgData.SendID, m.config.Share.IMAdminUserID...) {
return nil
}
if data.MsgData.ContentType <= constant.NotificationEnd &&
@@ -65,35 +64,33 @@ func (m *msgServer) messageVerification(ctx context.Context, data *msg.SendMsgRe
return err
}
if black {
return errs.ErrBlockedByPeer.Wrap()
return servererrs.ErrBlockedByPeer.Wrap()
}
if m.config.MessageVerify.FriendVerify != nil && *m.config.MessageVerify.FriendVerify {
if m.config.RpcConfig.FriendVerify {
friend, err := m.FriendLocalCache.IsFriend(ctx, data.MsgData.SendID, data.MsgData.RecvID)
if err != nil {
return err
}
if !friend {
return errs.ErrNotPeersFriend.Wrap()
return servererrs.ErrNotPeersFriend.Wrap()
}
return nil
}
return nil
case constant.SuperGroupChatType:
case constant.ReadGroupChatType:
groupInfo, err := m.GroupLocalCache.GetGroupInfo(ctx, data.MsgData.GroupID)
if err != nil {
return err
}
if groupInfo.Status == constant.GroupStatusDismissed &&
data.MsgData.ContentType != constant.GroupDismissedNotification {
return errs.ErrDismissedAlready.Wrap()
return servererrs.ErrDismissedAlready.Wrap()
}
if groupInfo.GroupType == constant.SuperGroup {
return nil
}
if len(m.config.Manager.UserID) > 0 && utils.IsContain(data.MsgData.SendID, m.config.Manager.UserID) {
return nil
}
if utils.IsContain(data.MsgData.SendID, m.config.IMAdmin.UserID) {
if datautil.Contain(data.MsgData.SendID, m.config.Share.IMAdminUserID...) {
return nil
}
if data.MsgData.ContentType <= constant.NotificationEnd &&
@@ -105,13 +102,13 @@ func (m *msgServer) messageVerification(ctx context.Context, data *msg.SendMsgRe
return err
}
if _, ok := memberIDs[data.MsgData.SendID]; !ok {
return errs.ErrNotInGroupYet.Wrap()
return servererrs.ErrNotInGroupYet.Wrap()
}
groupMemberInfo, err := m.GroupLocalCache.GetGroupMember(ctx, data.MsgData.GroupID, data.MsgData.SendID)
if err != nil {
if errs.ErrRecordNotFound.Is(err) {
return errs.ErrNotInGroupYet.Wrap(err.Error())
return servererrs.ErrNotInGroupYet.WrapMsg(err.Error())
}
return err
}
@@ -119,10 +116,10 @@ func (m *msgServer) messageVerification(ctx context.Context, data *msg.SendMsgRe
return nil
} else {
if groupMemberInfo.MuteEndTime >= time.Now().UnixMilli() {
return errs.ErrMutedInGroup.Wrap()
return servererrs.ErrMutedInGroup.Wrap()
}
if groupInfo.Status == constant.GroupStatusMuted && groupMemberInfo.RoleLevel != constant.GroupAdmin {
return errs.ErrMutedGroup.Wrap()
return servererrs.ErrMutedGroup.Wrap()
}
}
return nil
@@ -134,7 +131,7 @@ func (m *msgServer) messageVerification(ctx context.Context, data *msg.SendMsgRe
func (m *msgServer) encapsulateMsgData(msg *sdkws.MsgData) {
msg.ServerMsgID = GetMsgID(msg.SendID)
if msg.SendTime == 0 {
msg.SendTime = utils.GetCurrentTimestampByMill()
msg.SendTime = timeutil.GetCurrentTimestampByMill()
}
switch msg.ContentType {
case constant.Text:
@@ -159,36 +156,30 @@ func (m *msgServer) encapsulateMsgData(msg *sdkws.MsgData) {
fallthrough
case constant.Quote:
case constant.Revoke:
utils.SetSwitchFromOptions(msg.Options, constant.IsUnreadCount, false)
utils.SetSwitchFromOptions(msg.Options, constant.IsOfflinePush, false)
datautil.SetSwitchFromOptions(msg.Options, constant.IsUnreadCount, false)
datautil.SetSwitchFromOptions(msg.Options, constant.IsOfflinePush, false)
case constant.HasReadReceipt:
utils.SetSwitchFromOptions(msg.Options, constant.IsConversationUpdate, false)
utils.SetSwitchFromOptions(msg.Options, constant.IsSenderConversationUpdate, false)
utils.SetSwitchFromOptions(msg.Options, constant.IsUnreadCount, false)
utils.SetSwitchFromOptions(msg.Options, constant.IsOfflinePush, false)
datautil.SetSwitchFromOptions(msg.Options, constant.IsConversationUpdate, false)
datautil.SetSwitchFromOptions(msg.Options, constant.IsSenderConversationUpdate, false)
datautil.SetSwitchFromOptions(msg.Options, constant.IsUnreadCount, false)
datautil.SetSwitchFromOptions(msg.Options, constant.IsOfflinePush, false)
case constant.Typing:
utils.SetSwitchFromOptions(msg.Options, constant.IsHistory, false)
utils.SetSwitchFromOptions(msg.Options, constant.IsPersistent, false)
utils.SetSwitchFromOptions(msg.Options, constant.IsSenderSync, false)
utils.SetSwitchFromOptions(msg.Options, constant.IsConversationUpdate, false)
utils.SetSwitchFromOptions(msg.Options, constant.IsSenderConversationUpdate, false)
utils.SetSwitchFromOptions(msg.Options, constant.IsUnreadCount, false)
utils.SetSwitchFromOptions(msg.Options, constant.IsOfflinePush, false)
datautil.SetSwitchFromOptions(msg.Options, constant.IsHistory, false)
datautil.SetSwitchFromOptions(msg.Options, constant.IsPersistent, false)
datautil.SetSwitchFromOptions(msg.Options, constant.IsSenderSync, false)
datautil.SetSwitchFromOptions(msg.Options, constant.IsConversationUpdate, false)
datautil.SetSwitchFromOptions(msg.Options, constant.IsSenderConversationUpdate, false)
datautil.SetSwitchFromOptions(msg.Options, constant.IsUnreadCount, false)
datautil.SetSwitchFromOptions(msg.Options, constant.IsOfflinePush, false)
}
}
func GetMsgID(sendID string) string {
t := time.Now().Format("2006-01-02 15:04:05")
return utils.Md5(t + "-" + sendID + "-" + strconv.Itoa(rand.Int()))
t := timeutil.GetCurrentTimeFormatted()
return encrypt.Md5(t + "-" + sendID + "-" + strconv.Itoa(rand.Int()))
}
func (m *msgServer) modifyMessageByUserMessageReceiveOpt(
ctx context.Context,
userID, conversationID string,
sessionType int,
pb *msg.SendMsgReq,
) (bool, error) {
defer log.ZDebug(ctx, "modifyMessageByUserMessageReceiveOpt return")
func (m *msgServer) modifyMessageByUserMessageReceiveOpt(ctx context.Context, userID, conversationID string, sessionType int, pb *msg.SendMsgReq) (bool, error) {
opt, err := m.UserLocalCache.GetUserGlobalMsgRecvOpt(ctx, userID)
if err != nil {
return false, err
@@ -201,10 +192,9 @@ func (m *msgServer) modifyMessageByUserMessageReceiveOpt(
if pb.MsgData.Options == nil {
pb.MsgData.Options = make(map[string]bool, 10)
}
utils.SetSwitchFromOptions(pb.MsgData.Options, constant.IsOfflinePush, false)
datautil.SetSwitchFromOptions(pb.MsgData.Options, constant.IsOfflinePush, false)
return true, nil
}
// conversationID := utils.GetConversationIDBySessionType(conversationID, sessionType)
singleOpt, err := m.ConversationLocalCache.GetSingleConversationRecvMsgOpt(ctx, userID, conversationID)
if errs.ErrRecordNotFound.Is(err) {
return true, nil
@@ -215,7 +205,7 @@ func (m *msgServer) modifyMessageByUserMessageReceiveOpt(
case constant.ReceiveMessage:
return true, nil
case constant.NotReceiveMessage:
if utils.IsContainInt(int(pb.MsgData.ContentType), ExcludeContentType) {
if datautil.Contain(int(pb.MsgData.ContentType), ExcludeContentType...) {
return true, nil
}
return false, nil
@@ -223,7 +213,7 @@ func (m *msgServer) modifyMessageByUserMessageReceiveOpt(
if pb.MsgData.Options == nil {
pb.MsgData.Options = make(map[string]bool, 10)
}
utils.SetSwitchFromOptions(pb.MsgData.Options, constant.IsOfflinePush, false)
datautil.SetSwitchFromOptions(pb.MsgData.Options, constant.IsOfflinePush, false)
return true, nil
}
return true, nil