mirror of
https://github.com/openimsdk/open-im-server.git
synced 2025-04-06 04:15:46 +08:00
Merge branch 'v2.3.0release'
This commit is contained in:
commit
7ac790e4d0
@ -163,6 +163,11 @@ func main() {
|
||||
chatGroup.POST("/batch_send_msg", manage.ManagementBatchSendMsg)
|
||||
chatGroup.POST("/check_msg_is_send_success", manage.CheckMsgIsSendSuccess)
|
||||
chatGroup.POST("/set_msg_min_seq", apiChat.SetMsgMinSeq)
|
||||
|
||||
chatGroup.POST("/set_message_reaction_extensions", apiChat.SetMessageReactionExtensions)
|
||||
chatGroup.POST("/get_message_list_reaction_extensions", apiChat.GetMessageListReactionExtensions)
|
||||
chatGroup.POST("/add_message_reaction_extensions", apiChat.AddMessageReactionExtensions)
|
||||
chatGroup.POST("/delete_message_reaction_extensions", apiChat.DeleteMessageReactionExtensions)
|
||||
}
|
||||
//Conversation
|
||||
conversationGroup := r.Group("/conversation")
|
||||
@ -232,7 +237,7 @@ func main() {
|
||||
if config.Config.Api.ListenIP != "" {
|
||||
address = config.Config.Api.ListenIP + ":" + strconv.Itoa(*ginPort)
|
||||
}
|
||||
fmt.Println("start api server, address: ", address, "OpenIM version: ", constant.CurrentVersion, "\n")
|
||||
fmt.Println("start api server, address: ", address, ", OpenIM version: ", constant.CurrentVersion)
|
||||
err := r.Run(address)
|
||||
if err != nil {
|
||||
log.Error("", "api run failed ", address, err.Error())
|
||||
|
@ -25,6 +25,6 @@ func main() {
|
||||
address = config.Config.Api.ListenIP + ":" + strconv.Itoa(*ginPort)
|
||||
}
|
||||
address = config.Config.CmsApi.ListenIP + ":" + strconv.Itoa(*ginPort)
|
||||
fmt.Println("start cms api server, address: ", address, "OpenIM version: ", constant.CurrentVersion, "\n")
|
||||
fmt.Println("start cms api server, address: ", address, ", OpenIM version: ", constant.CurrentVersion, "\n")
|
||||
router.Run(address)
|
||||
}
|
||||
|
@ -2,10 +2,15 @@ package main
|
||||
|
||||
import (
|
||||
"Open_IM/internal/cron_task"
|
||||
"flag"
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println("start cronTask")
|
||||
cronTask.StartCronTask()
|
||||
var userID = flag.String("userID", "", "userID to clear msg and reset seq")
|
||||
var workingGroupID = flag.String("workingGroupID", "", "workingGroupID to clear msg and reset seq")
|
||||
flag.Parse()
|
||||
fmt.Println(time.Now(), "start cronTask", *userID, *workingGroupID)
|
||||
cronTask.StartCronTask(*userID, *workingGroupID)
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ func main() {
|
||||
address = config.Config.Api.ListenIP + ":" + strconv.Itoa(*ginPort)
|
||||
}
|
||||
address = config.Config.CmsApi.ListenIP + ":" + strconv.Itoa(*ginPort)
|
||||
fmt.Println("start demo api server address: ", address, "OpenIM version: ", constant.CurrentVersion, "\n")
|
||||
fmt.Println("start demo api server address: ", address, ", OpenIM version: ", constant.CurrentVersion, "\n")
|
||||
go register.OnboardingProcessRoutine()
|
||||
go register.ImportFriendRoutine()
|
||||
err := r.Run(address)
|
||||
|
@ -21,7 +21,7 @@ func main() {
|
||||
flag.Parse()
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
fmt.Println("start rpc/msg_gateway server, port: ", *rpcPort, *wsPort, *prometheusPort, "OpenIM version: ", constant.CurrentVersion, "\n")
|
||||
fmt.Println("start rpc/msg_gateway server, port: ", *rpcPort, *wsPort, *prometheusPort, ", OpenIM version: ", constant.CurrentVersion, "\n")
|
||||
gate.Init(*rpcPort, *wsPort)
|
||||
gate.Run(*prometheusPort)
|
||||
wg.Wait()
|
||||
|
@ -17,7 +17,7 @@ func main() {
|
||||
flag.Parse()
|
||||
log.NewPrivateLog(constant.LogFileName)
|
||||
logic.Init()
|
||||
fmt.Println("start msg_transfer server ", "OpenIM version: ", constant.CurrentVersion, "\n")
|
||||
fmt.Println("start msg_transfer server ", ", OpenIM version: ", constant.CurrentVersion, "\n")
|
||||
logic.Run(*prometheusPort)
|
||||
wg.Wait()
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ func main() {
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
log.NewPrivateLog(constant.LogFileName)
|
||||
fmt.Println("start push rpc server, port: ", *rpcPort, "OpenIM version: ", constant.CurrentVersion, "\n")
|
||||
fmt.Println("start push rpc server, port: ", *rpcPort, ", OpenIM version: ", constant.CurrentVersion, "\n")
|
||||
logic.Init(*rpcPort)
|
||||
logic.Run(*prometheusPort)
|
||||
wg.Wait()
|
||||
|
@ -14,7 +14,7 @@ func main() {
|
||||
rpcPort := flag.Int("port", defaultPorts[0], "rpc listening port")
|
||||
prometheusPort := flag.Int("prometheus_port", config.Config.Prometheus.AdminCmsPrometheusPort[0], "adminCMSPrometheusPort default listen port")
|
||||
flag.Parse()
|
||||
fmt.Println("start cms rpc server, port: ", *rpcPort, "OpenIM version: ", constant.CurrentVersion, "\n")
|
||||
fmt.Println("start cms rpc server, port: ", *rpcPort, ", OpenIM version: ", constant.CurrentVersion, "\n")
|
||||
rpcServer := rpcMessageCMS.NewAdminCMSServer(*rpcPort)
|
||||
go func() {
|
||||
err := promePkg.StartPromeSrv(*prometheusPort)
|
||||
|
@ -14,7 +14,7 @@ func main() {
|
||||
rpcPort := flag.Int("port", defaultPorts[0], "RpcToken default listen port 10800")
|
||||
prometheusPort := flag.Int("prometheus_port", config.Config.Prometheus.AuthPrometheusPort[0], "authPrometheusPort default listen port")
|
||||
flag.Parse()
|
||||
fmt.Println("start auth rpc server, port: ", *rpcPort, "OpenIM version: ", constant.CurrentVersion, "\n")
|
||||
fmt.Println("start auth rpc server, port: ", *rpcPort, ", OpenIM version: ", constant.CurrentVersion, "\n")
|
||||
rpcServer := rpcAuth.NewRpcAuthServer(*rpcPort)
|
||||
go func() {
|
||||
err := promePkg.StartPromeSrv(*prometheusPort)
|
||||
|
@ -15,7 +15,7 @@ func main() {
|
||||
rpcPort := flag.Int("port", defaultPorts[0], "RpcToken default listen port 10800")
|
||||
prometheusPort := flag.Int("prometheus_port", config.Config.Prometheus.CachePrometheusPort[0], "cachePrometheusPort default listen port")
|
||||
flag.Parse()
|
||||
fmt.Println("start cache rpc server, port: ", *rpcPort, "OpenIM version: ", constant.CurrentVersion, "\n")
|
||||
fmt.Println("start cache rpc server, port: ", *rpcPort, ", OpenIM version: ", constant.CurrentVersion, "\n")
|
||||
rpcServer := rpcCache.NewCacheServer(*rpcPort)
|
||||
go func() {
|
||||
err := promePkg.StartPromeSrv(*prometheusPort)
|
||||
|
@ -14,7 +14,7 @@ func main() {
|
||||
rpcPort := flag.Int("port", defaultPorts[0], "RpcConversation default listen port 11300")
|
||||
prometheusPort := flag.Int("prometheus_port", config.Config.Prometheus.ConversationPrometheusPort[0], "conversationPrometheusPort default listen port")
|
||||
flag.Parse()
|
||||
fmt.Println("start conversation rpc server, port: ", *rpcPort, "OpenIM version: ", constant.CurrentVersion, "\n")
|
||||
fmt.Println("start conversation rpc server, port: ", *rpcPort, ", OpenIM version: ", constant.CurrentVersion, "\n")
|
||||
rpcServer := rpcConversation.NewRpcConversationServer(*rpcPort)
|
||||
go func() {
|
||||
err := promePkg.StartPromeSrv(*prometheusPort)
|
||||
|
@ -14,7 +14,7 @@ func main() {
|
||||
rpcPort := flag.Int("port", defaultPorts[0], "get RpcFriendPort from cmd,default 12000 as port")
|
||||
prometheusPort := flag.Int("prometheus_port", config.Config.Prometheus.FriendPrometheusPort[0], "friendPrometheusPort default listen port")
|
||||
flag.Parse()
|
||||
fmt.Println("start friend rpc server, port: ", *rpcPort, "OpenIM version: ", constant.CurrentVersion, "\n")
|
||||
fmt.Println("start friend rpc server, port: ", *rpcPort, ", OpenIM version: ", constant.CurrentVersion, "\n")
|
||||
rpcServer := friend.NewFriendServer(*rpcPort)
|
||||
go func() {
|
||||
err := promePkg.StartPromeSrv(*prometheusPort)
|
||||
|
@ -14,7 +14,7 @@ func main() {
|
||||
rpcPort := flag.Int("port", defaultPorts[0], "get RpcGroupPort from cmd,default 16000 as port")
|
||||
prometheusPort := flag.Int("prometheus_port", config.Config.Prometheus.GroupPrometheusPort[0], "groupPrometheusPort default listen port")
|
||||
flag.Parse()
|
||||
fmt.Println("start group rpc server, port: ", *rpcPort, "OpenIM version: ", constant.CurrentVersion, "\n")
|
||||
fmt.Println("start group rpc server, port: ", *rpcPort, ", OpenIM version: ", constant.CurrentVersion, "\n")
|
||||
rpcServer := group.NewGroupServer(*rpcPort)
|
||||
go func() {
|
||||
err := promePkg.StartPromeSrv(*prometheusPort)
|
||||
|
@ -14,7 +14,7 @@ func main() {
|
||||
rpcPort := flag.Int("port", defaultPorts[0], "rpc listening port")
|
||||
prometheusPort := flag.Int("prometheus_port", config.Config.Prometheus.MessagePrometheusPort[0], "msgPrometheusPort default listen port")
|
||||
flag.Parse()
|
||||
fmt.Println("start msg rpc server, port: ", *rpcPort, "OpenIM version: ", constant.CurrentVersion, "\n")
|
||||
fmt.Println("start msg rpc server, port: ", *rpcPort, ", OpenIM version: ", constant.CurrentVersion, "\n")
|
||||
rpcServer := msg.NewRpcChatServer(*rpcPort)
|
||||
go func() {
|
||||
err := promePkg.StartPromeSrv(*prometheusPort)
|
||||
|
@ -14,7 +14,7 @@ func main() {
|
||||
rpcPort := flag.Int("port", defaultPorts[0], "rpc listening port")
|
||||
prometheusPort := flag.Int("prometheus_port", config.Config.Prometheus.OfficePrometheusPort[0], "officePrometheusPort default listen port")
|
||||
flag.Parse()
|
||||
fmt.Println("start office rpc server, port: ", *rpcPort, "OpenIM version: ", constant.CurrentVersion, "\n")
|
||||
fmt.Println("start office rpc server, port: ", *rpcPort, ", OpenIM version: ", constant.CurrentVersion, "\n")
|
||||
rpcServer := rpc.NewOfficeServer(*rpcPort)
|
||||
go func() {
|
||||
err := promePkg.StartPromeSrv(*prometheusPort)
|
||||
|
@ -14,7 +14,7 @@ func main() {
|
||||
rpcPort := flag.Int("port", defaultPorts[0], "get RpcOrganizationPort from cmd,default 11200 as port")
|
||||
prometheusPort := flag.Int("prometheus_port", config.Config.Prometheus.OrganizationPrometheusPort[0], "organizationPrometheusPort default listen port")
|
||||
flag.Parse()
|
||||
fmt.Println("start organization rpc server, port: ", *rpcPort, "OpenIM version: ", constant.CurrentVersion, "\n")
|
||||
fmt.Println("start organization rpc server, port: ", *rpcPort, ", OpenIM version: ", constant.CurrentVersion, "\n")
|
||||
rpcServer := organization.NewServer(*rpcPort)
|
||||
go func() {
|
||||
err := promePkg.StartPromeSrv(*prometheusPort)
|
||||
|
@ -14,7 +14,7 @@ func main() {
|
||||
rpcPort := flag.Int("port", defaultPorts[0], "rpc listening port")
|
||||
prometheusPort := flag.Int("prometheus_port", config.Config.Prometheus.UserPrometheusPort[0], "userPrometheusPort default listen port")
|
||||
flag.Parse()
|
||||
fmt.Println("start user rpc server, port: ", *rpcPort, "OpenIM version: ", constant.CurrentVersion, "\n")
|
||||
fmt.Println("start user rpc server, port: ", *rpcPort, ", OpenIM version: ", constant.CurrentVersion, "\n")
|
||||
rpcServer := user.NewUserServer(*rpcPort)
|
||||
go func() {
|
||||
err := promePkg.StartPromeSrv(*prometheusPort)
|
||||
|
@ -36,7 +36,7 @@ mongo:
|
||||
dbPassword: #mongo密码,建议先不设置
|
||||
dbMaxPoolSize: 100
|
||||
dbRetainChatRecords: 3650 #mongo保存离线消息时间(天),根据需求修改
|
||||
chatRecordsClearTime: "* * * * *" # 每天凌晨3点清除消息,该配置和linux定时任务一样, 清理操作建议设置在用户活跃少的时候 # 0 3 * * *
|
||||
chatRecordsClearTime: "0 3 * * *" # 每天凌晨3点清除消息,该配置和linux定时任务一样, 清理操作建议设置在用户活跃少的时候 # 0 3 * * *
|
||||
|
||||
redis:
|
||||
dbAddress: [ 127.0.0.1:16379 ] #redis地址 单机时,填写一个地址即可,使用redis集群时候,填写集群中多个节点地址(主从地址都可以填写,增加容灾能力),默认即可
|
||||
@ -62,12 +62,15 @@ kafka:
|
||||
ms2pschat:
|
||||
addr: [ 127.0.0.1:9092 ] #kafka配置,默认即可
|
||||
topic: "ms2ps_chat" #消息push
|
||||
msgtomodify:
|
||||
addr: [ 127.0.0.1:9092 ] #kafka配置,默认即可
|
||||
topic: "msg_to_modify"
|
||||
consumergroupid:
|
||||
msgToTransfer: mongo
|
||||
msgToMongo: mongo_ex
|
||||
msgToMySql: mysql
|
||||
msgToPush: push
|
||||
|
||||
msgToModify: modify
|
||||
|
||||
|
||||
#---------------Internal service configuration---------------------#
|
||||
@ -341,6 +344,19 @@ callback:
|
||||
enable: false
|
||||
callbackTimeOut: 2
|
||||
callbackFailedContinue: true # 回调超时是否继续
|
||||
callbackBeforeMemberJoinGroup:
|
||||
enable: false
|
||||
callbackTimeOut: 2
|
||||
callbackFailedContinue: true # 回调超时是否继续
|
||||
callbackBeforeSetGroupMemberInfo:
|
||||
enable: false
|
||||
callbackTimeOut: 2
|
||||
callbackFailedContinue: true # 回调超时是否继续
|
||||
callbackSetMessageReactionExtensions:
|
||||
enable: false
|
||||
callbackTimeOut: 2
|
||||
callbackFailedContinue: true # 回调超时是否继续
|
||||
|
||||
|
||||
notification:
|
||||
groupCreated:
|
||||
@ -661,6 +677,19 @@ notification:
|
||||
defaultTips:
|
||||
tips: "Remove a blocked user"
|
||||
|
||||
friendInfoUpdated:
|
||||
conversation:
|
||||
reliabilityLevel: 2
|
||||
unreadCount: false
|
||||
offlinePush:
|
||||
switch: true
|
||||
title: "friend info updated"
|
||||
desc: "friend info updated"
|
||||
ext: "friend info updated"
|
||||
defaultTips:
|
||||
tips: "friend info updated"
|
||||
|
||||
|
||||
#####################user#########################
|
||||
userInfoUpdated:
|
||||
conversation:
|
||||
|
@ -115,7 +115,7 @@ services:
|
||||
|
||||
|
||||
open_im_server:
|
||||
image: openim/open_im_server:v2.3.6
|
||||
image: openim/open_im_server:v2.3.7
|
||||
container_name: open_im_server
|
||||
volumes:
|
||||
- ./logs:/Open-IM-Server/logs
|
||||
@ -139,7 +139,7 @@ services:
|
||||
max-file: "2"
|
||||
|
||||
open_im_enterprise:
|
||||
image: openim/open_im_enterprise:v1.0.2
|
||||
image: openim/open_im_enterprise:v1.0.3
|
||||
container_name: open_im_enterprise
|
||||
volumes:
|
||||
- ./logs:/Open-IM-Enterprise/logs
|
||||
|
1
go.mod
1
go.mod
@ -29,7 +29,6 @@ require (
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
|
||||
github.com/jinzhu/copier v0.3.4
|
||||
github.com/jinzhu/gorm v1.9.16
|
||||
github.com/jonboulle/clockwork v0.2.2 // indirect
|
||||
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible
|
||||
github.com/lestrrat-go/strftime v1.0.4 // indirect
|
||||
|
2
go.sum
2
go.sum
@ -368,8 +368,6 @@ github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZ
|
||||
github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
|
||||
github.com/jinzhu/copier v0.3.4 h1:mfU6jI9PtCeUjkjQ322dlff9ELjGDu975C2p/nrubVI=
|
||||
github.com/jinzhu/copier v0.3.4/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
|
||||
github.com/jinzhu/gorm v1.9.16 h1:+IyIjPEABKRpsu/F8OvDPy9fyQlgsg2luMV2ZIH5i5o=
|
||||
github.com/jinzhu/gorm v1.9.16/go.mod h1:G3LB3wezTOWM2ITLzPxEXgSkOXAntiLHS7UdBefADcs=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
|
@ -199,7 +199,6 @@ func ForceLogout(c *gin.Context) {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": errMsg})
|
||||
return
|
||||
}
|
||||
|
||||
req := &rpc.ForceLogoutReq{}
|
||||
utils.CopyStructFields(req, ¶ms)
|
||||
|
||||
|
@ -9,7 +9,6 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/jinzhu/gorm"
|
||||
)
|
||||
|
||||
func SetClientInitConfig(c *gin.Context) {
|
||||
@ -62,11 +61,10 @@ func GetClientInitConfig(c *gin.Context) {
|
||||
}
|
||||
config, err := imdb.GetClientInitConfig()
|
||||
if err != nil {
|
||||
if !gorm.IsRecordNotFoundError(err) {
|
||||
log.NewError(req.OperationID, utils.GetSelfFuncName(), err.Error())
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": err.Error()})
|
||||
return
|
||||
}
|
||||
log.NewError(req.OperationID, utils.GetSelfFuncName(), err.Error())
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": err.Error()})
|
||||
return
|
||||
|
||||
}
|
||||
resp.Data.DiscoverPageURL = config.DiscoverPageURL
|
||||
log.NewInfo(req.OperationID, utils.GetSelfFuncName(), "resp ", resp)
|
||||
|
@ -52,6 +52,10 @@ func newUserSendMsgReq(params *api.ManagementSendMsgReq) *pbChat.SendMsgReq {
|
||||
fallthrough
|
||||
case constant.File:
|
||||
fallthrough
|
||||
case constant.CustomNotTriggerConversation:
|
||||
fallthrough
|
||||
case constant.CustomOnlineOnly:
|
||||
fallthrough
|
||||
case constant.AdvancedRevoke:
|
||||
newContent = utils.StructToJsonString(params.Content)
|
||||
case constant.Revoke:
|
||||
|
203
internal/api/msg/extend_msg.go
Normal file
203
internal/api/msg/extend_msg.go
Normal file
@ -0,0 +1,203 @@
|
||||
package msg
|
||||
|
||||
import (
|
||||
api "Open_IM/pkg/base_info"
|
||||
"Open_IM/pkg/common/config"
|
||||
"Open_IM/pkg/common/constant"
|
||||
"Open_IM/pkg/common/log"
|
||||
"Open_IM/pkg/common/token_verify"
|
||||
"Open_IM/pkg/grpc-etcdv3/getcdv3"
|
||||
rpc "Open_IM/pkg/proto/msg"
|
||||
"Open_IM/pkg/utils"
|
||||
"context"
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func SetMessageReactionExtensions(c *gin.Context) {
|
||||
var (
|
||||
req api.SetMessageReactionExtensionsCallbackReq
|
||||
resp api.SetMessageReactionExtensionsCallbackResp
|
||||
reqPb rpc.SetMessageReactionExtensionsReq
|
||||
)
|
||||
|
||||
if err := c.BindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
|
||||
return
|
||||
}
|
||||
log.NewInfo(req.OperationID, utils.GetSelfFuncName(), "req:", req)
|
||||
|
||||
if err := utils.CopyStructFields(&reqPb, &req); err != nil {
|
||||
log.NewDebug(req.OperationID, utils.GetSelfFuncName(), "CopyStructFields", err.Error())
|
||||
}
|
||||
var ok bool
|
||||
var errInfo string
|
||||
ok, reqPb.OpUserID, errInfo = token_verify.GetUserIDFromToken(c.Request.Header.Get("token"), req.OperationID)
|
||||
if !ok {
|
||||
errMsg := req.OperationID + " " + "GetUserIDFromToken failed " + errInfo + " token:" + c.Request.Header.Get("token")
|
||||
log.NewError(req.OperationID, errMsg)
|
||||
c.JSON(http.StatusBadRequest, gin.H{"errCode": 500, "errMsg": errMsg})
|
||||
return
|
||||
}
|
||||
|
||||
grpcConn := getcdv3.GetDefaultConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImMsgName, req.OperationID)
|
||||
if grpcConn == nil {
|
||||
errMsg := req.OperationID + " getcdv3.GetDefaultConn == nil"
|
||||
log.NewError(req.OperationID, errMsg)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": errMsg})
|
||||
return
|
||||
}
|
||||
msgClient := rpc.NewMsgClient(grpcConn)
|
||||
respPb, err := msgClient.SetMessageReactionExtensions(context.Background(), &reqPb)
|
||||
if err != nil {
|
||||
log.NewError(req.OperationID, utils.GetSelfFuncName(), "DelMsgList failed", err.Error(), reqPb)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"errCode": constant.ErrServer.ErrCode, "errMsg": constant.ErrServer.ErrMsg + err.Error()})
|
||||
return
|
||||
}
|
||||
resp.ErrCode = respPb.ErrCode
|
||||
resp.ErrMsg = respPb.ErrMsg
|
||||
resp.Data.ResultKeyValue = respPb.Result
|
||||
resp.Data.MsgFirstModifyTime = reqPb.MsgFirstModifyTime
|
||||
resp.Data.IsReact = reqPb.IsReact
|
||||
log.NewInfo(req.OperationID, utils.GetSelfFuncName(), resp)
|
||||
c.JSON(http.StatusOK, resp)
|
||||
|
||||
}
|
||||
|
||||
func GetMessageListReactionExtensions(c *gin.Context) {
|
||||
var (
|
||||
req api.GetMessageListReactionExtensionsReq
|
||||
resp api.GetMessageListReactionExtensionsResp
|
||||
reqPb rpc.GetMessageListReactionExtensionsReq
|
||||
)
|
||||
if err := c.BindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
|
||||
return
|
||||
}
|
||||
log.NewInfo(req.OperationID, utils.GetSelfFuncName(), "req:", req)
|
||||
|
||||
if err := utils.CopyStructFields(&reqPb, &req); err != nil {
|
||||
log.NewDebug(req.OperationID, utils.GetSelfFuncName(), "CopyStructFields", err.Error())
|
||||
}
|
||||
var ok bool
|
||||
var errInfo string
|
||||
ok, reqPb.OpUserID, errInfo = token_verify.GetUserIDFromToken(c.Request.Header.Get("token"), req.OperationID)
|
||||
if !ok {
|
||||
errMsg := req.OperationID + " " + "GetUserIDFromToken failed " + errInfo + " token:" + c.Request.Header.Get("token")
|
||||
log.NewError(req.OperationID, errMsg)
|
||||
c.JSON(http.StatusBadRequest, gin.H{"errCode": 500, "errMsg": errMsg})
|
||||
return
|
||||
}
|
||||
|
||||
grpcConn := getcdv3.GetDefaultConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImMsgName, req.OperationID)
|
||||
if grpcConn == nil {
|
||||
errMsg := req.OperationID + " getcdv3.GetDefaultConn == nil"
|
||||
log.NewError(req.OperationID, errMsg)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": errMsg})
|
||||
return
|
||||
}
|
||||
msgClient := rpc.NewMsgClient(grpcConn)
|
||||
respPb, err := msgClient.GetMessageListReactionExtensions(context.Background(), &reqPb)
|
||||
if err != nil {
|
||||
log.NewError(req.OperationID, utils.GetSelfFuncName(), "DelMsgList failed", err.Error(), reqPb)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"errCode": constant.ErrServer.ErrCode, "errMsg": constant.ErrServer.ErrMsg + err.Error()})
|
||||
return
|
||||
}
|
||||
resp.ErrCode = respPb.ErrCode
|
||||
resp.ErrMsg = respPb.ErrMsg
|
||||
resp.Data = respPb.SingleMessageResult
|
||||
log.NewInfo(req.OperationID, utils.GetSelfFuncName(), resp)
|
||||
c.JSON(http.StatusOK, resp)
|
||||
}
|
||||
|
||||
func AddMessageReactionExtensions(c *gin.Context) {
|
||||
var (
|
||||
req api.AddMessageReactionExtensionsReq
|
||||
resp api.AddMessageReactionExtensionsResp
|
||||
reqPb rpc.ModifyMessageReactionExtensionsReq
|
||||
)
|
||||
if err := c.BindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
|
||||
return
|
||||
}
|
||||
log.NewInfo(req.OperationID, utils.GetSelfFuncName(), "req:", req)
|
||||
|
||||
if err := utils.CopyStructFields(&reqPb, &req); err != nil {
|
||||
log.NewDebug(req.OperationID, utils.GetSelfFuncName(), "CopyStructFields", err.Error())
|
||||
}
|
||||
var ok bool
|
||||
var errInfo string
|
||||
ok, reqPb.OpUserID, errInfo = token_verify.GetUserIDFromToken(c.Request.Header.Get("token"), req.OperationID)
|
||||
if !ok {
|
||||
errMsg := req.OperationID + " " + "GetUserIDFromToken failed " + errInfo + " token:" + c.Request.Header.Get("token")
|
||||
log.NewError(req.OperationID, errMsg)
|
||||
c.JSON(http.StatusBadRequest, gin.H{"errCode": 500, "errMsg": errMsg})
|
||||
return
|
||||
}
|
||||
|
||||
grpcConn := getcdv3.GetDefaultConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImMsgName, req.OperationID)
|
||||
if grpcConn == nil {
|
||||
errMsg := req.OperationID + " getcdv3.GetDefaultConn == nil"
|
||||
log.NewError(req.OperationID, errMsg)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": errMsg})
|
||||
return
|
||||
}
|
||||
msgClient := rpc.NewMsgClient(grpcConn)
|
||||
respPb, err := msgClient.AddMessageReactionExtensions(context.Background(), &reqPb)
|
||||
if err != nil {
|
||||
log.NewError(req.OperationID, utils.GetSelfFuncName(), "DelMsgList failed", err.Error(), reqPb)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"errCode": constant.ErrServer.ErrCode, "errMsg": constant.ErrServer.ErrMsg + err.Error()})
|
||||
return
|
||||
}
|
||||
resp.ErrCode = respPb.ErrCode
|
||||
resp.ErrMsg = respPb.ErrMsg
|
||||
log.NewInfo(req.OperationID, utils.GetSelfFuncName(), resp)
|
||||
c.JSON(http.StatusOK, resp)
|
||||
}
|
||||
|
||||
func DeleteMessageReactionExtensions(c *gin.Context) {
|
||||
var (
|
||||
req api.DeleteMessageReactionExtensionsReq
|
||||
resp api.DeleteMessageReactionExtensionsResp
|
||||
reqPb rpc.DeleteMessageListReactionExtensionsReq
|
||||
)
|
||||
if err := c.BindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
|
||||
return
|
||||
}
|
||||
log.NewInfo(req.OperationID, utils.GetSelfFuncName(), "req:", req)
|
||||
|
||||
if err := utils.CopyStructFields(&reqPb, &req); err != nil {
|
||||
log.NewDebug(req.OperationID, utils.GetSelfFuncName(), "CopyStructFields", err.Error())
|
||||
}
|
||||
var ok bool
|
||||
var errInfo string
|
||||
ok, reqPb.OpUserID, errInfo = token_verify.GetUserIDFromToken(c.Request.Header.Get("token"), req.OperationID)
|
||||
if !ok {
|
||||
errMsg := req.OperationID + " " + "GetUserIDFromToken failed " + errInfo + " token:" + c.Request.Header.Get("token")
|
||||
log.NewError(req.OperationID, errMsg)
|
||||
c.JSON(http.StatusBadRequest, gin.H{"errCode": 500, "errMsg": errMsg})
|
||||
return
|
||||
}
|
||||
|
||||
grpcConn := getcdv3.GetDefaultConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImMsgName, req.OperationID)
|
||||
if grpcConn == nil {
|
||||
errMsg := req.OperationID + " getcdv3.GetDefaultConn == nil"
|
||||
log.NewError(req.OperationID, errMsg)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": errMsg})
|
||||
return
|
||||
}
|
||||
msgClient := rpc.NewMsgClient(grpcConn)
|
||||
respPb, err := msgClient.DeleteMessageReactionExtensions(context.Background(), &reqPb)
|
||||
if err != nil {
|
||||
log.NewError(req.OperationID, utils.GetSelfFuncName(), "DelMsgList failed", err.Error(), reqPb)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"errCode": constant.ErrServer.ErrCode, "errMsg": constant.ErrServer.ErrMsg + err.Error()})
|
||||
return
|
||||
}
|
||||
resp.ErrCode = respPb.ErrCode
|
||||
resp.ErrMsg = respPb.ErrMsg
|
||||
resp.Data = respPb.Result
|
||||
log.NewInfo(req.OperationID, utils.GetSelfFuncName(), resp)
|
||||
c.JSON(http.StatusOK, resp)
|
||||
}
|
@ -58,6 +58,40 @@ func init() {
|
||||
}
|
||||
}
|
||||
|
||||
func GetUserToken(c *gin.Context) {
|
||||
var (
|
||||
req apiStruct.GetUserTokenRequest
|
||||
resp apiStruct.GetUserTokenResponse
|
||||
reqPb pbAdmin.GetUserTokenReq
|
||||
respPb *pbAdmin.GetUserTokenResp
|
||||
)
|
||||
if err := c.BindJSON(&req); err != nil {
|
||||
log.NewError(req.OperationID, utils.GetSelfFuncName(), err.Error())
|
||||
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
|
||||
return
|
||||
}
|
||||
reqPb.OperationID = req.OperationID
|
||||
reqPb.UserID = req.UserID
|
||||
reqPb.PlatformID = req.PlatFormID
|
||||
etcdConn := getcdv3.GetDefaultConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImAdminCMSName, reqPb.OperationID)
|
||||
if etcdConn == nil {
|
||||
errMsg := reqPb.OperationID + "getcdv3.GetDefaultConn == nil"
|
||||
log.NewError(reqPb.OperationID, errMsg)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": errMsg})
|
||||
return
|
||||
}
|
||||
client := pbAdmin.NewAdminCMSClient(etcdConn)
|
||||
respPb, err := client.GetUserToken(context.Background(), &reqPb)
|
||||
if err != nil {
|
||||
log.NewError(reqPb.OperationID, utils.GetSelfFuncName(), "rpc failed", err.Error())
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": err.Error()})
|
||||
return
|
||||
}
|
||||
resp.Token = respPb.Token
|
||||
resp.ExpTime = respPb.ExpTime
|
||||
c.JSON(http.StatusOK, gin.H{"errCode": respPb.CommonResp.ErrCode, "errMsg": respPb.CommonResp.ErrMsg, "data": resp})
|
||||
}
|
||||
|
||||
// register
|
||||
func AdminLogin(c *gin.Context) {
|
||||
var (
|
||||
|
@ -1,6 +1,7 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"Open_IM/pkg/common/config"
|
||||
"Open_IM/pkg/common/log"
|
||||
"Open_IM/pkg/common/token_verify"
|
||||
"Open_IM/pkg/utils"
|
||||
@ -20,6 +21,11 @@ func JWTAuth() gin.HandlerFunc {
|
||||
c.JSON(http.StatusOK, gin.H{"errCode": 400, "errMsg": errInfo})
|
||||
return
|
||||
} else {
|
||||
if !utils.IsContain(userID, config.Config.Manager.AppManagerUid) {
|
||||
c.Abort()
|
||||
c.JSON(http.StatusOK, gin.H{"errCode": 400, "errMsg": "user is not admin"})
|
||||
return
|
||||
}
|
||||
log.NewInfo("0", utils.GetSelfFuncName(), "failed: ", errInfo)
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,8 @@ func NewGinRouter() *gin.Engine {
|
||||
{
|
||||
adminRouterGroup.POST("/login", admin.AdminLogin)
|
||||
adminRouterGroup.Use(middleware.JWTAuth())
|
||||
adminRouterGroup.POST("/get_user_token", admin.GetUserToken)
|
||||
|
||||
adminRouterGroup.POST("/add_user_register_add_friend_id", admin.AddUserRegisterAddFriendIDList)
|
||||
adminRouterGroup.POST("/reduce_user_register_reduce_friend_id", admin.ReduceUserRegisterAddFriendIDList)
|
||||
adminRouterGroup.POST("/get_user_register_reduce_friend_id_list", admin.GetUserRegisterAddFriendIDList)
|
||||
|
@ -7,11 +7,12 @@ import (
|
||||
"Open_IM/pkg/common/log"
|
||||
server_api_params "Open_IM/pkg/proto/sdk_ws"
|
||||
"Open_IM/pkg/utils"
|
||||
goRedis "github.com/go-redis/redis/v8"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
goRedis "github.com/go-redis/redis/v8"
|
||||
"github.com/golang/protobuf/proto"
|
||||
)
|
||||
|
||||
const oldestList = 0
|
||||
@ -54,7 +55,7 @@ func DeleteMongoMsgAndResetRedisSeq(operationID, userID string) error {
|
||||
if minSeq == 0 {
|
||||
return nil
|
||||
}
|
||||
log.NewDebug(operationID, utils.GetSelfFuncName(), "delMsgIDMap: ", delStruct, "minSeq", minSeq)
|
||||
log.NewDebug(operationID, utils.GetSelfFuncName(), "delMsgIDStruct: ", delStruct, "minSeq", minSeq)
|
||||
err = db.DB.SetUserMinSeq(userID, minSeq)
|
||||
return utils.Wrap(err, "")
|
||||
}
|
||||
@ -82,7 +83,7 @@ func (d *delMsgRecursionStruct) getSetMinSeq() uint32 {
|
||||
// index 0....19(del) 20...69
|
||||
// seq 70
|
||||
// set minSeq 21
|
||||
// recursion
|
||||
// recursion 删除list并且返回设置的最小seq
|
||||
func deleteMongoMsg(operationID string, ID string, index int64, delStruct *delMsgRecursionStruct) (uint32, error) {
|
||||
// find from oldest list
|
||||
msgs, err := db.DB.GetUserMsgListByIndex(ID, index)
|
||||
@ -105,49 +106,52 @@ func deleteMongoMsg(operationID string, ID string, index int64, delStruct *delMs
|
||||
if len(msgs.Msg) > db.GetSingleGocMsgNum() {
|
||||
log.NewWarn(operationID, utils.GetSelfFuncName(), "msgs too large", len(msgs.Msg), msgs.UID)
|
||||
}
|
||||
for i, msg := range msgs.Msg {
|
||||
// 找到列表中不需要删除的消息了, 表示为递归到最后一个块
|
||||
if utils.GetCurrentTimestampByMill() < msg.SendTime+(int64(config.Config.Mongo.DBRetainChatRecords)*24*60*60*1000) {
|
||||
log.NewDebug(operationID, ID, "find uid", msgs.UID)
|
||||
// 删除块失败 递归结束 返回0
|
||||
if err := delMongoMsgsPhysical(delStruct.delUidList); err != nil {
|
||||
return 0, err
|
||||
if msgs.Msg[len(msgs.Msg)-1].SendTime+(int64(config.Config.Mongo.DBRetainChatRecords)*24*60*60*1000) < utils.GetCurrentTimestampByMill() && msgListIsFull(msgs) {
|
||||
delStruct.delUidList = append(delStruct.delUidList, msgs.UID)
|
||||
lastMsgPb := &server_api_params.MsgData{}
|
||||
err = proto.Unmarshal(msgs.Msg[len(msgs.Msg)-1].Msg, lastMsgPb)
|
||||
if err != nil {
|
||||
log.NewError(operationID, utils.GetSelfFuncName(), err.Error(), len(msgs.Msg)-1, msgs.UID)
|
||||
return 0, utils.Wrap(err, "proto.Unmarshal failed")
|
||||
}
|
||||
delStruct.minSeq = lastMsgPb.Seq + 1
|
||||
log.NewDebug(operationID, utils.GetSelfFuncName(), msgs.UID, "add to delUidList", "minSeq", lastMsgPb.Seq+1)
|
||||
} else {
|
||||
var hasMarkDelFlag bool
|
||||
for index, msg := range msgs.Msg {
|
||||
if msg.SendTime == 0 {
|
||||
continue
|
||||
}
|
||||
// unMarshall失败 块删除成功 设置为最小seq
|
||||
msgPb := &server_api_params.MsgData{}
|
||||
if err = proto.Unmarshal(msg.Msg, msgPb); err != nil {
|
||||
return delStruct.getSetMinSeq(), utils.Wrap(err, "")
|
||||
err = proto.Unmarshal(msg.Msg, msgPb)
|
||||
if err != nil {
|
||||
log.NewError(operationID, utils.GetSelfFuncName(), err.Error(), len(msgs.Msg)-1, msgs.UID)
|
||||
return 0, utils.Wrap(err, "proto.Unmarshal failed")
|
||||
}
|
||||
// 如果不是块中第一个,就把前面比他早插入的全部设置空 seq字段除外。
|
||||
if i > 0 {
|
||||
err = db.DB.ReplaceMsgToBlankByIndex(msgs.UID, i-1)
|
||||
if err != nil {
|
||||
log.NewError(operationID, utils.GetSelfFuncName(), err.Error(), msgs.UID, i)
|
||||
return delStruct.getSetMinSeq(), utils.Wrap(err, "")
|
||||
if utils.GetCurrentTimestampByMill() > msg.SendTime+(int64(config.Config.Mongo.DBRetainChatRecords)*24*60*60*1000) {
|
||||
msgPb.Status = constant.MsgDeleted
|
||||
bytes, _ := proto.Marshal(msgPb)
|
||||
msgs.Msg[index].Msg = bytes
|
||||
msgs.Msg[index].SendTime = 0
|
||||
hasMarkDelFlag = true
|
||||
} else {
|
||||
if err := delMongoMsgsPhysical(delStruct.delUidList); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if hasMarkDelFlag {
|
||||
log.NewInfo(operationID, ID, "hasMarkDelFlag", "index:", index, "msgPb:", msgPb, msgs.UID)
|
||||
if err := db.DB.UpdateOneMsgList(msgs); err != nil {
|
||||
return delStruct.getSetMinSeq(), utils.Wrap(err, "")
|
||||
}
|
||||
}
|
||||
return msgPb.Seq, nil
|
||||
}
|
||||
// 递归结束
|
||||
return msgPb.Seq, nil
|
||||
}
|
||||
}
|
||||
// 该列表中消息全部为老消息并且列表满了, 加入删除列表继续递归
|
||||
lastMsgPb := &server_api_params.MsgData{}
|
||||
err = proto.Unmarshal(msgs.Msg[len(msgs.Msg)-1].Msg, lastMsgPb)
|
||||
if err != nil {
|
||||
log.NewError(operationID, utils.GetSelfFuncName(), err.Error(), len(msgs.Msg)-1, msgs.UID)
|
||||
return 0, utils.Wrap(err, "proto.Unmarshal failed")
|
||||
}
|
||||
delStruct.minSeq = lastMsgPb.Seq
|
||||
if msgListIsFull(msgs) {
|
||||
delStruct.delUidList = append(delStruct.delUidList, msgs.UID)
|
||||
}
|
||||
log.NewDebug(operationID, ID, "continue", delStruct)
|
||||
log.NewDebug(operationID, ID, "continue to", delStruct)
|
||||
// 继续递归 index+1
|
||||
seq, err := deleteMongoMsg(operationID, ID, index+1, delStruct)
|
||||
if err != nil {
|
||||
return seq, utils.Wrap(err, "deleteMongoMsg failed")
|
||||
}
|
||||
return seq, nil
|
||||
return seq, utils.Wrap(err, "deleteMongoMsg failed")
|
||||
}
|
||||
|
||||
func msgListIsFull(chat *db.UserChat) bool {
|
||||
@ -184,17 +188,10 @@ func checkMaxSeqWithMongo(operationID, ID string, diffusionType int) error {
|
||||
if msg == nil {
|
||||
return nil
|
||||
}
|
||||
var seqMongo uint32
|
||||
msgPb := &server_api_params.MsgData{}
|
||||
err = proto.Unmarshal(msg.Msg, msgPb)
|
||||
if err != nil {
|
||||
return utils.Wrap(err, "")
|
||||
}
|
||||
seqMongo = msgPb.Seq
|
||||
if math.Abs(float64(seqMongo-uint32(seqRedis))) > 10 {
|
||||
log.NewWarn(operationID, utils.GetSelfFuncName(), seqMongo, seqRedis, "redis maxSeq is different with msg.Seq > 10", ID, diffusionType)
|
||||
if math.Abs(float64(msg.Seq-uint32(seqRedis))) > 10 {
|
||||
log.NewWarn(operationID, utils.GetSelfFuncName(), "seqMongo, seqRedis", msg.Seq, seqRedis, ID, "redis maxSeq is different with msg.Seq > 10", "status: ", msg.Status, msg.SendTime)
|
||||
} else {
|
||||
log.NewInfo(operationID, utils.GetSelfFuncName(), diffusionType, ID, "seq and msg OK", seqMongo, seqRedis)
|
||||
log.NewInfo(operationID, utils.GetSelfFuncName(), "seqMongo, seqRedis", msg.Seq, seqRedis, ID, "seq and msg OK", "status:", msg.Status, msg.SendTime)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -2,33 +2,225 @@ package cronTask
|
||||
|
||||
import (
|
||||
"Open_IM/pkg/common/constant"
|
||||
"Open_IM/pkg/common/log"
|
||||
"Open_IM/pkg/common/db"
|
||||
server_api_params "Open_IM/pkg/proto/sdk_ws"
|
||||
"Open_IM/pkg/utils"
|
||||
"context"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/go-redis/redis/v8"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
"gopkg.in/mgo.v2/bson"
|
||||
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
redisClient *redis.Client
|
||||
mongoClient *mongo.Collection
|
||||
)
|
||||
|
||||
func GenUserChat(startSeq, stopSeq, delSeq, index uint32, userID string) *db.UserChat {
|
||||
chat := &db.UserChat{UID: userID + ":" + strconv.Itoa(int(index))}
|
||||
for i := startSeq; i <= stopSeq; i++ {
|
||||
msg := server_api_params.MsgData{
|
||||
SendID: "sendID1",
|
||||
RecvID: "recvID1",
|
||||
GroupID: "",
|
||||
ClientMsgID: "xxx",
|
||||
ServerMsgID: "xxx",
|
||||
SenderPlatformID: 1,
|
||||
SenderNickname: "testNickName",
|
||||
SenderFaceURL: "testFaceURL",
|
||||
SessionType: 1,
|
||||
MsgFrom: 100,
|
||||
ContentType: 101,
|
||||
Content: []byte("testFaceURL"),
|
||||
Seq: uint32(i),
|
||||
SendTime: time.Now().Unix(),
|
||||
CreateTime: time.Now().Unix(),
|
||||
Status: 1,
|
||||
}
|
||||
bytes, _ := proto.Marshal(&msg)
|
||||
var sendTime int64
|
||||
if i <= delSeq {
|
||||
sendTime = 10000
|
||||
} else {
|
||||
sendTime = utils.GetCurrentTimestampByMill()
|
||||
}
|
||||
chat.Msg = append(chat.Msg, db.MsgInfo{SendTime: int64(sendTime), Msg: bytes})
|
||||
}
|
||||
return chat
|
||||
}
|
||||
|
||||
func SetUserMaxSeq(userID string, seq int) error {
|
||||
return redisClient.Set(context.Background(), "REDIS_USER_INCR_SEQ"+userID, seq, 0).Err()
|
||||
}
|
||||
|
||||
func GetUserMinSeq(userID string) (uint64, error) {
|
||||
key := "REDIS_USER_MIN_SEQ:" + userID
|
||||
seq, err := redisClient.Get(context.Background(), key).Result()
|
||||
return uint64(utils.StringToInt(seq)), err
|
||||
}
|
||||
|
||||
func CreateChat(userChat *db.UserChat) error {
|
||||
_, err := mongoClient.InsertOne(context.Background(), userChat)
|
||||
return err
|
||||
}
|
||||
|
||||
func DelChat(uid string, index int) error {
|
||||
_, err := mongoClient.DeleteOne(context.Background(), bson.M{"uid": uid + ":" + strconv.Itoa(index)})
|
||||
return err
|
||||
}
|
||||
|
||||
func TestDeleteMongoMsgAndResetRedisSeq(t *testing.T) {
|
||||
operationID := getCronTaskOperationID()
|
||||
testUserIDList := []string{"test_del_id1", "test_del_id2", "test_del_id3", "test_del_id4", "test_del_id5"}
|
||||
for _, userID := range testUserIDList {
|
||||
operationID = userID + "-" + operationID
|
||||
if err := DeleteMongoMsgAndResetRedisSeq(operationID, userID); err != nil {
|
||||
t.Error("checkMaxSeqWithMongo failed", userID)
|
||||
}
|
||||
if err := checkMaxSeqWithMongo(operationID, userID, constant.WriteDiffusion); err != nil {
|
||||
t.Error("checkMaxSeqWithMongo failed", userID)
|
||||
}
|
||||
redisClient = redis.NewClient(&redis.Options{
|
||||
Addr: "127.0.0.1:16379",
|
||||
Password: "openIM123", // no password set
|
||||
DB: 0, // use default DB
|
||||
})
|
||||
mongoUri := fmt.Sprintf("mongodb://%s:%s@%s/%s?maxPoolSize=%d&authSource=admin",
|
||||
"root", "openIM123", "127.0.0.1:37017",
|
||||
"openIM", 100)
|
||||
client, err := mongo.Connect(context.TODO(), options.Client().ApplyURI(mongoUri))
|
||||
mongoClient = client.Database("openIM").Collection("msg")
|
||||
testUID1 := "test_del_id1"
|
||||
err = DelChat(testUID1, 0)
|
||||
err = SetUserMaxSeq(testUID1, 600)
|
||||
userChat := GenUserChat(1, 600, 200, 0, testUID1)
|
||||
err = CreateChat(userChat)
|
||||
if err := DeleteMongoMsgAndResetRedisSeq(operationID, testUID1); err != nil {
|
||||
t.Error("checkMaxSeqWithMongo failed", testUID1)
|
||||
}
|
||||
if err := checkMaxSeqWithMongo(operationID, testUID1, constant.WriteDiffusion); err != nil {
|
||||
t.Error("checkMaxSeqWithMongo failed", testUID1)
|
||||
}
|
||||
minSeq, err := GetUserMinSeq(testUID1)
|
||||
if err != nil {
|
||||
t.Error("err is not nil", testUID1, err.Error())
|
||||
}
|
||||
if minSeq != 201 {
|
||||
t.Error("test1 is not the same", "minSeq:", minSeq, "targetSeq", 201)
|
||||
}
|
||||
|
||||
testWorkingGroupIDList := []string{"test_del_id1", "test_del_id2", "test_del_id3", "test_del_id4", "test_del_id5"}
|
||||
for _, groupID := range testWorkingGroupIDList {
|
||||
operationID = groupID + "-" + operationID
|
||||
log.NewDebug(operationID, utils.GetSelfFuncName(), "groupID:", groupID, "userIDList:", testUserIDList)
|
||||
if err := ResetUserGroupMinSeq(operationID, groupID, testUserIDList); err != nil {
|
||||
t.Error("checkMaxSeqWithMongo failed", groupID)
|
||||
}
|
||||
if err := checkMaxSeqWithMongo(operationID, groupID, constant.ReadDiffusion); err != nil {
|
||||
t.Error("checkMaxSeqWithMongo failed", groupID)
|
||||
}
|
||||
testUID2 := "test_del_id2"
|
||||
err = DelChat(testUID2, 0)
|
||||
err = DelChat(testUID2, 1)
|
||||
err = SetUserMaxSeq(testUID2, 7000)
|
||||
userChat = GenUserChat(1, 4999, 5000, 0, testUID2)
|
||||
userChat2 := GenUserChat(5000, 7000, 6000, 1, testUID2)
|
||||
err = CreateChat(userChat)
|
||||
err = CreateChat(userChat2)
|
||||
|
||||
if err := DeleteMongoMsgAndResetRedisSeq(operationID, testUID2); err != nil {
|
||||
t.Error("checkMaxSeqWithMongo failed", testUID2)
|
||||
}
|
||||
if err := checkMaxSeqWithMongo(operationID, testUID2, constant.WriteDiffusion); err != nil {
|
||||
t.Error("checkMaxSeqWithMongo failed", testUID2)
|
||||
}
|
||||
minSeq, err = GetUserMinSeq(testUID2)
|
||||
if err != nil {
|
||||
t.Error("err is not nil", testUID2, err.Error())
|
||||
}
|
||||
if minSeq != 6001 {
|
||||
t.Error("test2 is not the same", "minSeq:", minSeq, "targetSeq", 6001)
|
||||
}
|
||||
|
||||
testUID3 := "test_del_id3"
|
||||
err = DelChat(testUID3, 0)
|
||||
err = SetUserMaxSeq(testUID3, 4999)
|
||||
userChat = GenUserChat(1, 4999, 5000, 0, testUID3)
|
||||
err = CreateChat(userChat)
|
||||
if err := DeleteMongoMsgAndResetRedisSeq(operationID, testUID3); err != nil {
|
||||
t.Error("checkMaxSeqWithMongo failed", testUID3)
|
||||
}
|
||||
if err := checkMaxSeqWithMongo(operationID, testUID3, constant.WriteDiffusion); err != nil {
|
||||
t.Error("checkMaxSeqWithMongo failed", testUID3)
|
||||
}
|
||||
minSeq, err = GetUserMinSeq(testUID3)
|
||||
if err != nil {
|
||||
t.Error("err is not nil", testUID3, err.Error())
|
||||
}
|
||||
if minSeq != 5000 {
|
||||
t.Error("test3 is not the same", "minSeq:", minSeq, "targetSeq", 5000)
|
||||
}
|
||||
|
||||
testUID4 := "test_del_id4"
|
||||
err = DelChat(testUID4, 0)
|
||||
err = DelChat(testUID4, 1)
|
||||
err = DelChat(testUID4, 2)
|
||||
err = SetUserMaxSeq(testUID4, 12000)
|
||||
userChat = GenUserChat(1, 4999, 5000, 0, testUID4)
|
||||
userChat2 = GenUserChat(5000, 9999, 10000, 1, testUID4)
|
||||
userChat3 := GenUserChat(10000, 12000, 11000, 2, testUID4)
|
||||
err = CreateChat(userChat)
|
||||
err = CreateChat(userChat2)
|
||||
err = CreateChat(userChat3)
|
||||
if err := DeleteMongoMsgAndResetRedisSeq(operationID, testUID4); err != nil {
|
||||
t.Error("checkMaxSeqWithMongo failed", testUID4)
|
||||
}
|
||||
if err := checkMaxSeqWithMongo(operationID, testUID4, constant.WriteDiffusion); err != nil {
|
||||
t.Error("checkMaxSeqWithMongo failed", testUID4)
|
||||
}
|
||||
minSeq, err = GetUserMinSeq(testUID4)
|
||||
if err != nil {
|
||||
t.Error("err is not nil", testUID4, err.Error())
|
||||
}
|
||||
if minSeq != 11001 {
|
||||
t.Error("test4 is not the same", "minSeq:", minSeq, "targetSeq", 11001)
|
||||
}
|
||||
|
||||
testUID5 := "test_del_id5"
|
||||
err = DelChat(testUID5, 0)
|
||||
err = DelChat(testUID5, 1)
|
||||
err = SetUserMaxSeq(testUID5, 9999)
|
||||
userChat = GenUserChat(1, 4999, 5000, 0, testUID5)
|
||||
userChat2 = GenUserChat(5000, 9999, 10000, 1, testUID5)
|
||||
err = CreateChat(userChat)
|
||||
err = CreateChat(userChat2)
|
||||
if err := DeleteMongoMsgAndResetRedisSeq(operationID, testUID5); err != nil {
|
||||
t.Error("checkMaxSeqWithMongo failed", testUID4)
|
||||
}
|
||||
if err := checkMaxSeqWithMongo(operationID, testUID5, constant.WriteDiffusion); err != nil {
|
||||
t.Error("checkMaxSeqWithMongo failed", testUID5)
|
||||
}
|
||||
minSeq, err = GetUserMinSeq(testUID5)
|
||||
if err != nil {
|
||||
t.Error("err is not nil", testUID5, err.Error())
|
||||
}
|
||||
if minSeq != 10000 {
|
||||
t.Error("test5 is not the same", "minSeq:", minSeq, "targetSeq", 10000)
|
||||
}
|
||||
|
||||
testUID6 := "test_del_id6"
|
||||
err = DelChat(testUID5, 0)
|
||||
err = DelChat(testUID5, 1)
|
||||
err = DelChat(testUID5, 2)
|
||||
err = DelChat(testUID5, 3)
|
||||
userChat = GenUserChat(1, 4999, 5000, 0, testUID6)
|
||||
userChat2 = GenUserChat(5000, 9999, 10000, 1, testUID6)
|
||||
userChat3 = GenUserChat(10000, 14999, 13000, 2, testUID6)
|
||||
userChat4 := GenUserChat(15000, 19999, 0, 3, testUID6)
|
||||
err = CreateChat(userChat)
|
||||
err = CreateChat(userChat2)
|
||||
err = CreateChat(userChat3)
|
||||
err = CreateChat(userChat4)
|
||||
if err := DeleteMongoMsgAndResetRedisSeq(operationID, testUID6); err != nil {
|
||||
t.Error("checkMaxSeqWithMongo failed", testUID6)
|
||||
}
|
||||
if err := checkMaxSeqWithMongo(operationID, testUID6, constant.WriteDiffusion); err != nil {
|
||||
t.Error("checkMaxSeqWithMongo failed", testUID6)
|
||||
}
|
||||
minSeq, err = GetUserMinSeq(testUID6)
|
||||
if err != nil {
|
||||
t.Error("err is not nil", testUID6, err.Error())
|
||||
}
|
||||
if minSeq != 13001 {
|
||||
t.Error("test3 is not the same", "minSeq:", minSeq, "targetSeq", 13001)
|
||||
}
|
||||
}
|
||||
|
@ -8,66 +8,35 @@ import (
|
||||
"Open_IM/pkg/common/log"
|
||||
"Open_IM/pkg/utils"
|
||||
"fmt"
|
||||
"github.com/robfig/cron/v3"
|
||||
"time"
|
||||
|
||||
"github.com/robfig/cron/v3"
|
||||
)
|
||||
|
||||
const cronTaskOperationID = "cronTaskOperationID-"
|
||||
|
||||
func StartCronTask() {
|
||||
func StartCronTask(userID, workingGroupID string) {
|
||||
log.NewPrivateLog("cron")
|
||||
log.NewInfo(utils.OperationIDGenerator(), "start cron task", "cron config", config.Config.Mongo.ChatRecordsClearTime)
|
||||
c := cron.New()
|
||||
fmt.Println("cron config", config.Config.Mongo.ChatRecordsClearTime)
|
||||
_, err := c.AddFunc(config.Config.Mongo.ChatRecordsClearTime, func() {
|
||||
// user msg clear
|
||||
if userID != "" {
|
||||
operationID := getCronTaskOperationID()
|
||||
log.NewInfo(operationID, "====================== start del cron task ======================")
|
||||
userIDList, err := im_mysql_model.SelectAllUserID()
|
||||
if err == nil {
|
||||
log.NewDebug(operationID, utils.GetSelfFuncName(), "userIDList: ", userIDList)
|
||||
userIDList = []string{"4158779020"}
|
||||
for _, userID := range userIDList {
|
||||
if err := DeleteMongoMsgAndResetRedisSeq(operationID, userID); err != nil {
|
||||
log.NewError(operationID, utils.GetSelfFuncName(), err.Error(), userID)
|
||||
}
|
||||
//if err := checkMaxSeqWithMongo(operationID, userID, constant.WriteDiffusion); err != nil {
|
||||
// log.NewError(operationID, utils.GetSelfFuncName(), userID, err)
|
||||
//}
|
||||
}
|
||||
} else {
|
||||
log.NewError(operationID, utils.GetSelfFuncName(), err.Error())
|
||||
}
|
||||
StartClearMsg(operationID, []string{userID})
|
||||
}
|
||||
if workingGroupID != "" {
|
||||
operationID := getCronTaskOperationID()
|
||||
StartClearWorkingGroupMsg(operationID, []string{workingGroupID})
|
||||
}
|
||||
if userID != "" || workingGroupID != "" {
|
||||
fmt.Println("clear msg finished")
|
||||
return
|
||||
// working group msg clear
|
||||
workingGroupIDList, err := im_mysql_model.GetGroupIDListByGroupType(constant.WorkingGroup)
|
||||
if err == nil {
|
||||
log.NewDebug(operationID, utils.GetSelfFuncName(), "workingGroupIDList: ", workingGroupIDList)
|
||||
for _, groupID := range workingGroupIDList {
|
||||
userIDList, err = rocksCache.GetGroupMemberIDListFromCache(groupID)
|
||||
if err != nil {
|
||||
log.NewError(operationID, utils.GetSelfFuncName(), err.Error(), groupID)
|
||||
continue
|
||||
}
|
||||
log.NewDebug(operationID, utils.GetSelfFuncName(), "groupID:", groupID, "userIDList:", userIDList)
|
||||
if err := ResetUserGroupMinSeq(operationID, groupID, userIDList); err != nil {
|
||||
log.NewError(operationID, utils.GetSelfFuncName(), err.Error(), groupID, userIDList)
|
||||
}
|
||||
//if err := checkMaxSeqWithMongo(operationID, groupID, constant.ReadDiffusion); err != nil {
|
||||
// log.NewError(operationID, utils.GetSelfFuncName(), groupID, err)
|
||||
//}
|
||||
}
|
||||
} else {
|
||||
log.NewError(operationID, utils.GetSelfFuncName(), err.Error())
|
||||
}
|
||||
|
||||
log.NewInfo(operationID, "====================== start del cron finished ======================")
|
||||
})
|
||||
}
|
||||
c := cron.New()
|
||||
_, err := c.AddFunc(config.Config.Mongo.ChatRecordsClearTime, ClearAll)
|
||||
if err != nil {
|
||||
fmt.Println("start cron failed", err.Error(), config.Config.Mongo.ChatRecordsClearTime)
|
||||
panic(err)
|
||||
}
|
||||
|
||||
c.Start()
|
||||
fmt.Println("start cron task success")
|
||||
for {
|
||||
@ -78,3 +47,55 @@ func StartCronTask() {
|
||||
func getCronTaskOperationID() string {
|
||||
return cronTaskOperationID + utils.OperationIDGenerator()
|
||||
}
|
||||
|
||||
func ClearAll() {
|
||||
operationID := getCronTaskOperationID()
|
||||
log.NewInfo(operationID, "====================== start del cron task ======================")
|
||||
var err error
|
||||
userIDList, err := im_mysql_model.SelectAllUserID()
|
||||
if err == nil {
|
||||
StartClearMsg(operationID, userIDList)
|
||||
} else {
|
||||
log.NewError(operationID, utils.GetSelfFuncName(), err.Error())
|
||||
}
|
||||
|
||||
// working group msg clear
|
||||
workingGroupIDList, err := im_mysql_model.GetGroupIDListByGroupType(constant.WorkingGroup)
|
||||
if err == nil {
|
||||
StartClearWorkingGroupMsg(operationID, workingGroupIDList)
|
||||
} else {
|
||||
log.NewError(operationID, utils.GetSelfFuncName(), err.Error())
|
||||
}
|
||||
|
||||
log.NewInfo(operationID, "====================== start del cron finished ======================")
|
||||
}
|
||||
|
||||
func StartClearMsg(operationID string, userIDList []string) {
|
||||
log.NewDebug(operationID, utils.GetSelfFuncName(), "userIDList: ", userIDList)
|
||||
for _, userID := range userIDList {
|
||||
if err := DeleteMongoMsgAndResetRedisSeq(operationID, userID); err != nil {
|
||||
log.NewError(operationID, utils.GetSelfFuncName(), err.Error(), userID)
|
||||
}
|
||||
if err := checkMaxSeqWithMongo(operationID, userID, constant.WriteDiffusion); err != nil {
|
||||
log.NewError(operationID, utils.GetSelfFuncName(), userID, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func StartClearWorkingGroupMsg(operationID string, workingGroupIDList []string) {
|
||||
log.NewDebug(operationID, utils.GetSelfFuncName(), "workingGroupIDList: ", workingGroupIDList)
|
||||
for _, groupID := range workingGroupIDList {
|
||||
userIDList, err := rocksCache.GetGroupMemberIDListFromCache(groupID)
|
||||
if err != nil {
|
||||
log.NewError(operationID, utils.GetSelfFuncName(), err.Error(), groupID)
|
||||
continue
|
||||
}
|
||||
log.NewDebug(operationID, utils.GetSelfFuncName(), "groupID:", groupID, "workingGroupIDList:", userIDList)
|
||||
if err := ResetUserGroupMinSeq(operationID, groupID, userIDList); err != nil {
|
||||
log.NewError(operationID, utils.GetSelfFuncName(), err.Error(), groupID, userIDList)
|
||||
}
|
||||
if err := checkMaxSeqWithMongo(operationID, groupID, constant.ReadDiffusion); err != nil {
|
||||
log.NewError(operationID, utils.GetSelfFuncName(), groupID, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +0,0 @@
|
||||
package main
|
||||
|
||||
//
|
||||
//func main() {
|
||||
// db.DB.BatchInsertChat()
|
||||
//}
|
@ -10,7 +10,6 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
//"github.com/jinzhu/gorm"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
@ -9,7 +9,7 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
func callbackUserOnline(operationID, userID string, platformID int, token string) cbApi.CommonCallbackResp {
|
||||
func callbackUserOnline(operationID, userID string, platformID int, token string, isAppBackground bool, connID string) cbApi.CommonCallbackResp {
|
||||
callbackResp := cbApi.CommonCallbackResp{OperationID: operationID}
|
||||
if !config.Config.Callback.CallbackUserOnline.Enable {
|
||||
return callbackResp
|
||||
@ -25,7 +25,9 @@ func callbackUserOnline(operationID, userID string, platformID int, token string
|
||||
},
|
||||
UserID: userID,
|
||||
},
|
||||
Seq: int(time.Now().UnixNano() / 1e6),
|
||||
Seq: int(time.Now().UnixNano() / 1e6),
|
||||
IsAppBackground: isAppBackground,
|
||||
ConnID: connID,
|
||||
}
|
||||
callbackUserOnlineResp := &cbApi.CallbackUserOnlineResp{CommonCallbackResp: &callbackResp}
|
||||
if err := http.CallBackPostReturn(config.Config.Callback.CallbackUrl, constant.CallbackUserOnlineCommand, callbackUserOnlineReq, callbackUserOnlineResp, config.Config.Callback.CallbackUserOnline.CallbackTimeOut); err != nil {
|
||||
@ -35,7 +37,7 @@ func callbackUserOnline(operationID, userID string, platformID int, token string
|
||||
return callbackResp
|
||||
}
|
||||
|
||||
func callbackUserOffline(operationID, userID string, platformID int) cbApi.CommonCallbackResp {
|
||||
func callbackUserOffline(operationID, userID string, platformID int, connID string) cbApi.CommonCallbackResp {
|
||||
callbackResp := cbApi.CommonCallbackResp{OperationID: operationID}
|
||||
if !config.Config.Callback.CallbackUserOffline.Enable {
|
||||
return callbackResp
|
||||
@ -50,7 +52,8 @@ func callbackUserOffline(operationID, userID string, platformID int) cbApi.Commo
|
||||
},
|
||||
UserID: userID,
|
||||
},
|
||||
Seq: int(time.Now().UnixNano() / 1e6),
|
||||
Seq: int(time.Now().UnixNano() / 1e6),
|
||||
ConnID: connID,
|
||||
}
|
||||
callbackUserOfflineResp := &cbApi.CallbackUserOfflineResp{CommonCallbackResp: &callbackResp}
|
||||
if err := http.CallBackPostReturn(config.Config.Callback.CallbackUrl, constant.CallbackUserOfflineCommand, callbackOfflineReq, callbackUserOfflineResp, config.Config.Callback.CallbackUserOffline.CallbackTimeOut); err != nil {
|
||||
|
@ -15,10 +15,12 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/gob"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/gorilla/websocket"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/gorilla/websocket"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
func (ws *WServer) msgParse(conn *UserConn, binaryMsg []byte) {
|
||||
@ -65,6 +67,9 @@ func (ws *WServer) msgParse(conn *UserConn, binaryMsg []byte) {
|
||||
case constant.WsLogoutMsg:
|
||||
log.NewInfo(m.OperationID, "conn.Close()", m.SendID, m.MsgIncr, m.ReqIdentifier)
|
||||
ws.userLogoutReq(conn, &m)
|
||||
case constant.WsSetBackgroundStatus:
|
||||
log.NewInfo(m.OperationID, "WsSetBackgroundStatus", m.SendID, m.MsgIncr, m.ReqIdentifier)
|
||||
ws.setUserDeviceBackground(conn, &m)
|
||||
default:
|
||||
log.Error(m.OperationID, "ReqIdentifier failed ", m.SendID, m.MsgIncr, m.ReqIdentifier)
|
||||
}
|
||||
@ -147,7 +152,8 @@ func (ws *WServer) pullMsgBySeqListReq(conn *UserConn, m *Req) {
|
||||
return
|
||||
}
|
||||
msgClient := pbChat.NewMsgClient(grpcConn)
|
||||
reply, err := msgClient.PullMessageBySeqList(context.Background(), &rpcReq)
|
||||
maxSizeOption := grpc.MaxCallRecvMsgSize(1024 * 1024 * 20)
|
||||
reply, err := msgClient.PullMessageBySeqList(context.Background(), &rpcReq, maxSizeOption)
|
||||
if err != nil {
|
||||
log.NewError(rpcReq.OperationID, "pullMsgBySeqListReq err", err.Error())
|
||||
nReply.ErrCode = 200
|
||||
@ -180,8 +186,10 @@ func (ws *WServer) pullMsgBySeqListResp(conn *UserConn, m *Req, pb *sdk_ws.PullM
|
||||
}
|
||||
func (ws *WServer) userLogoutReq(conn *UserConn, m *Req) {
|
||||
log.NewInfo(m.OperationID, "Ws call success to userLogoutReq start", m.SendID, m.ReqIdentifier, m.MsgIncr, string(m.Data))
|
||||
|
||||
rpcReq := push.DelUserPushTokenReq{}
|
||||
rpcReq.UserID = m.SendID
|
||||
rpcReq.PlatformID = conn.PlatformID
|
||||
rpcReq.OperationID = m.OperationID
|
||||
grpcConn := getcdv3.GetDefaultConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImPushName, m.OperationID)
|
||||
if grpcConn == nil {
|
||||
@ -394,3 +402,28 @@ func SetTokenKicked(userID string, platformID int, operationID string) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (ws *WServer) setUserDeviceBackground(conn *UserConn, m *Req) {
|
||||
isPass, errCode, errMsg, pData := ws.argsValidate(m, constant.WsSetBackgroundStatus, m.OperationID)
|
||||
if isPass {
|
||||
req := pData.(*sdk_ws.SetAppBackgroundStatusReq)
|
||||
conn.IsBackground = req.IsBackground
|
||||
callbackResp := callbackUserOnline(m.OperationID, conn.userID, int(conn.PlatformID), conn.token, conn.IsBackground, conn.connID)
|
||||
if callbackResp.ErrCode != 0 {
|
||||
log.NewError(m.OperationID, utils.GetSelfFuncName(), "callbackUserOffline failed", callbackResp)
|
||||
}
|
||||
log.NewInfo(m.OperationID, "SetUserDeviceBackground", "success", *conn, req.IsBackground)
|
||||
}
|
||||
ws.setUserDeviceBackgroundResp(conn, m, errCode, errMsg)
|
||||
}
|
||||
|
||||
func (ws *WServer) setUserDeviceBackgroundResp(conn *UserConn, m *Req, errCode int32, errMsg string) {
|
||||
mReply := Resp{
|
||||
ReqIdentifier: m.ReqIdentifier,
|
||||
MsgIncr: m.MsgIncr,
|
||||
OperationID: m.OperationID,
|
||||
ErrCode: errCode,
|
||||
ErrMsg: errMsg,
|
||||
}
|
||||
ws.sendMsg(conn, mReply)
|
||||
}
|
||||
|
@ -159,6 +159,8 @@ func (r *RPCServer) GetUsersOnlineStatus(_ context.Context, req *pbRelay.GetUser
|
||||
ps := new(pbRelay.GetUsersOnlineStatusResp_SuccessDetail)
|
||||
ps.Platform = constant.PlatformIDToName(platform)
|
||||
ps.Status = constant.OnlineStatus
|
||||
ps.ConnID = userConn.connID
|
||||
ps.IsBackground = userConn.IsBackground
|
||||
temp.Status = constant.OnlineStatus
|
||||
temp.DetailPlatformStatus = append(temp.DetailPlatformStatus, ps)
|
||||
}
|
||||
@ -196,24 +198,75 @@ func (r *RPCServer) SuperGroupOnlineBatchPushOneMsg(_ context.Context, req *pbRe
|
||||
userConnMap := ws.getUserAllCons(v)
|
||||
for platform, userConn := range userConnMap {
|
||||
if userConn != nil {
|
||||
resultCode := sendMsgBatchToUser(userConn, replyBytes.Bytes(), req, platform, v)
|
||||
if resultCode == 0 && utils.IsContainInt(platform, r.pushTerminal) {
|
||||
tempT.OnlinePush = true
|
||||
promePkg.PromeInc(promePkg.MsgOnlinePushSuccessCounter)
|
||||
log.Info(req.OperationID, "PushSuperMsgToUser is success By Ws", "args", req.String(), "recvPlatForm", constant.PlatformIDToName(platform), "recvID", v)
|
||||
temp := &pbRelay.SingleMsgToUserPlatform{
|
||||
ResultCode: resultCode,
|
||||
RecvID: v,
|
||||
RecvPlatFormID: int32(platform),
|
||||
temp := &pbRelay.SingleMsgToUserPlatform{
|
||||
RecvID: v,
|
||||
RecvPlatFormID: int32(platform),
|
||||
}
|
||||
if !userConn.IsBackground {
|
||||
resultCode := sendMsgBatchToUser(userConn, replyBytes.Bytes(), req, platform, v)
|
||||
if resultCode == 0 && utils.IsContainInt(platform, r.pushTerminal) {
|
||||
tempT.OnlinePush = true
|
||||
promePkg.PromeInc(promePkg.MsgOnlinePushSuccessCounter)
|
||||
log.Info(req.OperationID, "PushSuperMsgToUser is success By Ws", "args", req.String(), "recvPlatForm", constant.PlatformIDToName(platform), "recvID", v)
|
||||
temp.ResultCode = resultCode
|
||||
resp = append(resp, temp)
|
||||
}
|
||||
} else {
|
||||
temp.ResultCode = -2
|
||||
resp = append(resp, temp)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
tempT.Resp = resp
|
||||
singleUserResult = append(singleUserResult, tempT)
|
||||
}
|
||||
|
||||
return &pbRelay.OnlineBatchPushOneMsgResp{
|
||||
SinglePushResult: singleUserResult,
|
||||
}, nil
|
||||
}
|
||||
func (r *RPCServer) SuperGroupBackgroundOnlinePush(_ context.Context, req *pbRelay.OnlineBatchPushOneMsgReq) (*pbRelay.OnlineBatchPushOneMsgResp, error) {
|
||||
log.NewInfo(req.OperationID, "BatchPushMsgToUser is arriving", req.String())
|
||||
var singleUserResult []*pbRelay.SingelMsgToUserResultList
|
||||
//r.GetBatchMsgForPush(req.OperationID,req.MsgData,req.PushToUserIDList,)
|
||||
msgBytes, _ := proto.Marshal(req.MsgData)
|
||||
mReply := Resp{
|
||||
ReqIdentifier: constant.WSPushMsg,
|
||||
OperationID: req.OperationID,
|
||||
Data: msgBytes,
|
||||
}
|
||||
var replyBytes bytes.Buffer
|
||||
enc := gob.NewEncoder(&replyBytes)
|
||||
err := enc.Encode(mReply)
|
||||
if err != nil {
|
||||
log.NewError(req.OperationID, "data encode err", err.Error())
|
||||
}
|
||||
for _, v := range req.PushToUserIDList {
|
||||
var resp []*pbRelay.SingleMsgToUserPlatform
|
||||
tempT := &pbRelay.SingelMsgToUserResultList{
|
||||
UserID: v,
|
||||
}
|
||||
userConnMap := ws.getUserAllCons(v)
|
||||
for platform, userConn := range userConnMap {
|
||||
if userConn != nil && userConn.IsBackground {
|
||||
temp := &pbRelay.SingleMsgToUserPlatform{
|
||||
RecvID: v,
|
||||
RecvPlatFormID: int32(platform),
|
||||
}
|
||||
if constant.PlatformIDToClass(int(userConn.PlatformID)) == constant.TerminalPC || userConn.PlatformID == constant.WebPlatformID {
|
||||
resultCode := sendMsgBatchToUser(userConn, replyBytes.Bytes(), req, platform, v)
|
||||
if resultCode == 0 && utils.IsContainInt(platform, r.pushTerminal) {
|
||||
tempT.OnlinePush = true
|
||||
promePkg.PromeInc(promePkg.MsgOnlinePushSuccessCounter)
|
||||
log.Info(req.OperationID, "PushSuperMsgToUser is success By Ws", "args", req.String(), "recvPlatForm", constant.PlatformIDToName(platform), "recvID", v)
|
||||
temp.ResultCode = resultCode
|
||||
resp = append(resp, temp)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
tempT.Resp = resp
|
||||
singleUserResult = append(singleUserResult, tempT)
|
||||
}
|
||||
|
||||
return &pbRelay.OnlineBatchPushOneMsgResp{
|
||||
|
@ -107,6 +107,18 @@ func (ws *WServer) argsValidate(m *Req, r int32, operationID string) (isPass boo
|
||||
|
||||
}
|
||||
return true, 0, "", data
|
||||
case constant.WsSetBackgroundStatus:
|
||||
data := open_im_sdk.SetAppBackgroundStatusReq{}
|
||||
if err := proto.Unmarshal(m.Data, &data); err != nil {
|
||||
log.Error(operationID, "Decode Data struct err", err.Error(), r)
|
||||
return false, 203, err.Error(), nil
|
||||
}
|
||||
if err := validate.Struct(data); err != nil {
|
||||
log.Error(operationID, "data args validate err", err.Error(), r)
|
||||
return false, 204, err.Error(), nil
|
||||
|
||||
}
|
||||
return true, 0, "", &data
|
||||
default:
|
||||
}
|
||||
return false, 204, "args err", nil
|
||||
|
@ -15,6 +15,7 @@ import (
|
||||
"context"
|
||||
"encoding/gob"
|
||||
"io/ioutil"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
go_redis "github.com/go-redis/redis/v8"
|
||||
@ -31,11 +32,15 @@ import (
|
||||
type UserConn struct {
|
||||
*websocket.Conn
|
||||
w *sync.Mutex
|
||||
platformID int32
|
||||
PlatformID int32
|
||||
PushedMaxSeq uint32
|
||||
IsCompress bool
|
||||
userID string
|
||||
IsBackground bool
|
||||
token string
|
||||
connID string
|
||||
}
|
||||
|
||||
type WServer struct {
|
||||
wsAddr string
|
||||
wsMaxConnNum int
|
||||
@ -73,20 +78,15 @@ func (ws *WServer) wsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
operationID = utils.OperationIDGenerator()
|
||||
}
|
||||
log.Debug(operationID, utils.GetSelfFuncName(), " args: ", query)
|
||||
if ws.headerCheck(w, r, operationID) {
|
||||
if isPass, compression := ws.headerCheck(w, r, operationID); isPass {
|
||||
conn, err := ws.wsUpGrader.Upgrade(w, r, nil) //Conn is obtained through the upgraded escalator
|
||||
if err != nil {
|
||||
log.Error(operationID, "upgrade http conn err", err.Error(), query)
|
||||
return
|
||||
} else {
|
||||
var isCompress = false
|
||||
if r.Header.Get("compression") == "gzip" {
|
||||
log.NewDebug(operationID, query["sendID"][0], "enable compression")
|
||||
isCompress = true
|
||||
}
|
||||
newConn := &UserConn{conn, new(sync.Mutex), utils.StringToInt32(query["platformID"][0]), 0, isCompress, query["sendID"][0]}
|
||||
newConn := &UserConn{conn, new(sync.Mutex), utils.StringToInt32(query["platformID"][0]), 0, compression, query["sendID"][0], false, query["token"][0], conn.RemoteAddr().String() + "_" + strconv.Itoa(int(utils.GetCurrentTimestampByMill()))}
|
||||
userCount++
|
||||
ws.addUserConn(query["sendID"][0], utils.StringToInt(query["platformID"][0]), newConn, query["token"][0], operationID)
|
||||
ws.addUserConn(query["sendID"][0], utils.StringToInt(query["platformID"][0]), newConn, query["token"][0], newConn.connID, operationID)
|
||||
go ws.readMsg(newConn)
|
||||
}
|
||||
} else {
|
||||
@ -221,7 +221,7 @@ func (ws *WServer) MultiTerminalLoginCheckerWithLock(uid string, platformID int,
|
||||
return
|
||||
}
|
||||
err = oldConn.Close()
|
||||
delete(oldConnMap, platformID)
|
||||
//delete(oldConnMap, platformID)
|
||||
ws.wsUserToConn[uid] = oldConnMap
|
||||
if len(oldConnMap) == 0 {
|
||||
delete(ws.wsUserToConn, uid)
|
||||
@ -321,11 +321,11 @@ func (ws *WServer) sendKickMsg(oldConn *UserConn) {
|
||||
}
|
||||
}
|
||||
|
||||
func (ws *WServer) addUserConn(uid string, platformID int, conn *UserConn, token string, operationID string) {
|
||||
func (ws *WServer) addUserConn(uid string, platformID int, conn *UserConn, token string, connID, operationID string) {
|
||||
rwLock.Lock()
|
||||
defer rwLock.Unlock()
|
||||
log.Info(operationID, utils.GetSelfFuncName(), " args: ", uid, platformID, conn, token, "ip: ", conn.RemoteAddr().String())
|
||||
callbackResp := callbackUserOnline(operationID, uid, platformID, token)
|
||||
callbackResp := callbackUserOnline(operationID, uid, platformID, token, false, connID)
|
||||
if callbackResp.ErrCode != 0 {
|
||||
log.NewError(operationID, utils.GetSelfFuncName(), "callbackUserOnline resp:", callbackResp)
|
||||
}
|
||||
@ -363,7 +363,7 @@ func (ws *WServer) delUserConn(conn *UserConn) {
|
||||
operationID := utils.OperationIDGenerator()
|
||||
var uid string
|
||||
var platform int
|
||||
if oldStringMap, ok := ws.wsConnToUser[conn]; ok {
|
||||
if oldStringMap, okg := ws.wsConnToUser[conn]; okg {
|
||||
for k, v := range oldStringMap {
|
||||
platform = k
|
||||
uid = v
|
||||
@ -383,17 +383,20 @@ func (ws *WServer) delUserConn(conn *UserConn) {
|
||||
log.Debug(operationID, "WS delete operation", "", "wsUser deleted", ws.wsUserToConn, "disconnection_uid", uid, "disconnection_platform", platform, "online_user_num", len(ws.wsUserToConn))
|
||||
}
|
||||
delete(ws.wsConnToUser, conn)
|
||||
|
||||
}
|
||||
err := conn.Close()
|
||||
if err != nil {
|
||||
log.Error(operationID, " close err", "", "uid", uid, "platform", platform)
|
||||
}
|
||||
callbackResp := callbackUserOffline(operationID, uid, platform)
|
||||
if conn.PlatformID == 0 || conn.connID == "" {
|
||||
log.NewWarn(operationID, utils.GetSelfFuncName(), "PlatformID or connID is null", conn.PlatformID, conn.connID)
|
||||
}
|
||||
callbackResp := callbackUserOffline(operationID, conn.userID, int(conn.PlatformID), conn.connID)
|
||||
if callbackResp.ErrCode != 0 {
|
||||
log.NewError(operationID, utils.GetSelfFuncName(), "callbackUserOffline failed", callbackResp)
|
||||
}
|
||||
promePkg.PromeGaugeDec(promePkg.OnlineUserGauge)
|
||||
|
||||
}
|
||||
|
||||
func (ws *WServer) getUserConn(uid string, platform int) *UserConn {
|
||||
@ -432,7 +435,7 @@ func (ws *WServer) getUserAllCons(uid string) map[int]*UserConn {
|
||||
// }
|
||||
// return "", 0
|
||||
//}
|
||||
func (ws *WServer) headerCheck(w http.ResponseWriter, r *http.Request, operationID string) bool {
|
||||
func (ws *WServer) headerCheck(w http.ResponseWriter, r *http.Request, operationID string) (isPass, compression bool) {
|
||||
status := http.StatusUnauthorized
|
||||
query := r.URL.Query()
|
||||
if len(query["token"]) != 0 && len(query["sendID"]) != 0 && len(query["platformID"]) != 0 {
|
||||
@ -484,10 +487,16 @@ func (ws *WServer) headerCheck(w http.ResponseWriter, r *http.Request, operation
|
||||
w.Header().Set("Sec-Websocket-Version", "13")
|
||||
w.Header().Set("ws_err_msg", err.Error())
|
||||
http.Error(w, err.Error(), status)
|
||||
return false
|
||||
return false, false
|
||||
} else {
|
||||
log.Info(operationID, "Connection Authentication Success", "", "token ", query["token"][0], "userID ", query["sendID"][0], "platformID ", query["platformID"][0])
|
||||
return true
|
||||
if r.Header.Get("compression") == "gzip" {
|
||||
compression = true
|
||||
}
|
||||
if len(query["compression"]) != 0 && query["compression"][0] == "gzip" {
|
||||
compression = true
|
||||
}
|
||||
log.Info(operationID, "Connection Authentication Success", "", "token ", query["token"][0], "userID ", query["sendID"][0], "platformID ", query["platformID"][0], "compression", compression)
|
||||
return true, compression
|
||||
}
|
||||
} else {
|
||||
status = int(constant.ErrArgs.ErrCode)
|
||||
@ -496,6 +505,6 @@ func (ws *WServer) headerCheck(w http.ResponseWriter, r *http.Request, operation
|
||||
errMsg := "args err, need token, sendID, platformID"
|
||||
w.Header().Set("ws_err_msg", errMsg)
|
||||
http.Error(w, errMsg, status)
|
||||
return false
|
||||
return false, false
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,9 @@ var (
|
||||
persistentCH PersistentConsumerHandler
|
||||
historyCH OnlineHistoryRedisConsumerHandler
|
||||
historyMongoCH OnlineHistoryMongoConsumerHandler
|
||||
modifyCH ModifyMsgConsumerHandler
|
||||
producer *kafka.Producer
|
||||
producerToModify *kafka.Producer
|
||||
producerToMongo *kafka.Producer
|
||||
cmdCh chan Cmd2Value
|
||||
onlineTopicStatus int
|
||||
@ -43,11 +45,13 @@ func Init() {
|
||||
persistentCH.Init() // ws2mschat save mysql
|
||||
historyCH.Init(cmdCh) //
|
||||
historyMongoCH.Init()
|
||||
modifyCH.Init()
|
||||
onlineTopicStatus = OnlineTopicVacancy
|
||||
//offlineHistoryCH.Init(cmdCh)
|
||||
statistics.NewStatistics(&singleMsgSuccessCount, config.Config.ModuleName.MsgTransferName, fmt.Sprintf("%d second singleMsgCount insert to mongo", constant.StatisticsTimeInterval), constant.StatisticsTimeInterval)
|
||||
statistics.NewStatistics(&groupMsgCount, config.Config.ModuleName.MsgTransferName, fmt.Sprintf("%d second groupMsgCount insert to mongo", constant.StatisticsTimeInterval), constant.StatisticsTimeInterval)
|
||||
producer = kafka.NewKafkaProducer(config.Config.Kafka.Ms2pschat.Addr, config.Config.Kafka.Ms2pschat.Topic)
|
||||
producerToModify = kafka.NewKafkaProducer(config.Config.Kafka.MsgToModify.Addr, config.Config.Kafka.MsgToModify.Topic)
|
||||
producerToMongo = kafka.NewKafkaProducer(config.Config.Kafka.MsgToMongo.Addr, config.Config.Kafka.MsgToMongo.Topic)
|
||||
}
|
||||
func Run(promethuesPort int) {
|
||||
@ -59,6 +63,7 @@ func Run(promethuesPort int) {
|
||||
}
|
||||
go historyCH.historyConsumerGroup.RegisterHandleAndConsumer(&historyCH)
|
||||
go historyMongoCH.historyConsumerGroup.RegisterHandleAndConsumer(&historyMongoCH)
|
||||
go modifyCH.modifyMsgConsumerGroup.RegisterHandleAndConsumer(&modifyCH)
|
||||
//go offlineHistoryCH.historyConsumerGroup.RegisterHandleAndConsumer(&offlineHistoryCH)
|
||||
go func() {
|
||||
err := promePkg.StartPromeSrv(promethuesPort)
|
||||
|
121
internal/msg_transfer/logic/modify_msg_handler.go
Normal file
121
internal/msg_transfer/logic/modify_msg_handler.go
Normal file
@ -0,0 +1,121 @@
|
||||
package logic
|
||||
|
||||
import (
|
||||
"Open_IM/pkg/base_info"
|
||||
"Open_IM/pkg/common/config"
|
||||
"Open_IM/pkg/common/constant"
|
||||
"Open_IM/pkg/common/db"
|
||||
kfk "Open_IM/pkg/common/kafka"
|
||||
"Open_IM/pkg/common/log"
|
||||
pbMsg "Open_IM/pkg/proto/msg"
|
||||
server_api_params "Open_IM/pkg/proto/sdk_ws"
|
||||
"Open_IM/pkg/utils"
|
||||
"encoding/json"
|
||||
"github.com/Shopify/sarama"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
)
|
||||
|
||||
type ModifyMsgConsumerHandler struct {
|
||||
msgHandle map[string]fcb
|
||||
modifyMsgConsumerGroup *kfk.MConsumerGroup
|
||||
}
|
||||
|
||||
func (mmc *ModifyMsgConsumerHandler) Init() {
|
||||
mmc.msgHandle = make(map[string]fcb)
|
||||
mmc.msgHandle[config.Config.Kafka.MsgToModify.Topic] = mmc.ModifyMsg
|
||||
mmc.modifyMsgConsumerGroup = kfk.NewMConsumerGroup(&kfk.MConsumerGroupConfig{KafkaVersion: sarama.V2_0_0_0,
|
||||
OffsetsInitial: sarama.OffsetNewest, IsReturnErr: false}, []string{config.Config.Kafka.MsgToModify.Topic},
|
||||
config.Config.Kafka.MsgToModify.Addr, config.Config.Kafka.ConsumerGroupID.MsgToModify)
|
||||
}
|
||||
|
||||
func (ModifyMsgConsumerHandler) Setup(_ sarama.ConsumerGroupSession) error { return nil }
|
||||
func (ModifyMsgConsumerHandler) Cleanup(_ sarama.ConsumerGroupSession) error { return nil }
|
||||
func (mmc *ModifyMsgConsumerHandler) ConsumeClaim(sess sarama.ConsumerGroupSession,
|
||||
claim sarama.ConsumerGroupClaim) error {
|
||||
for msg := range claim.Messages() {
|
||||
log.NewDebug("", "kafka get info to mysql", "ModifyMsgConsumerHandler", msg.Topic, "msgPartition", msg.Partition, "msg", string(msg.Value), "key", string(msg.Key))
|
||||
if len(msg.Value) != 0 {
|
||||
mmc.msgHandle[msg.Topic](msg, string(msg.Key), sess)
|
||||
} else {
|
||||
log.Error("", "msg get from kafka but is nil", msg.Key)
|
||||
}
|
||||
sess.MarkMessage(msg, "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mmc *ModifyMsgConsumerHandler) ModifyMsg(cMsg *sarama.ConsumerMessage, msgKey string, _ sarama.ConsumerGroupSession) {
|
||||
log.NewInfo("msg come here ModifyMsg!!!", "", "msg", string(cMsg.Value), msgKey)
|
||||
msgFromMQ := pbMsg.MsgDataToModifyByMQ{}
|
||||
err := proto.Unmarshal(cMsg.Value, &msgFromMQ)
|
||||
if err != nil {
|
||||
log.NewError(msgFromMQ.TriggerID, "msg_transfer Unmarshal msg err", "msg", string(cMsg.Value), "err", err.Error())
|
||||
return
|
||||
}
|
||||
log.Debug(msgFromMQ.TriggerID, "proto.Unmarshal MsgDataToMQ", msgFromMQ.String())
|
||||
for _, msgDataToMQ := range msgFromMQ.MessageList {
|
||||
isReactionFromCache := utils.GetSwitchFromOptions(msgDataToMQ.MsgData.Options, constant.IsReactionFromCache)
|
||||
if !isReactionFromCache {
|
||||
continue
|
||||
}
|
||||
if msgDataToMQ.MsgData.ContentType == constant.ReactionMessageModifier {
|
||||
notification := &base_info.ReactionMessageModifierNotification{}
|
||||
if err := json.Unmarshal(msgDataToMQ.MsgData.Content, notification); err != nil {
|
||||
continue
|
||||
}
|
||||
if notification.IsExternalExtensions {
|
||||
log.NewInfo(msgDataToMQ.OperationID, "msg:", notification, "this is external extensions")
|
||||
continue
|
||||
}
|
||||
if !notification.IsReact {
|
||||
// first time to modify
|
||||
var reactionExtensionList = make(map[string]db.KeyValue)
|
||||
extendMsg := db.ExtendMsg{
|
||||
ReactionExtensionList: reactionExtensionList,
|
||||
ClientMsgID: notification.ClientMsgID,
|
||||
MsgFirstModifyTime: notification.MsgFirstModifyTime,
|
||||
}
|
||||
for _, v := range notification.SuccessReactionExtensionList {
|
||||
reactionExtensionList[v.TypeKey] = db.KeyValue{
|
||||
TypeKey: v.TypeKey,
|
||||
Value: v.Value,
|
||||
LatestUpdateTime: v.LatestUpdateTime,
|
||||
}
|
||||
}
|
||||
|
||||
if err := db.DB.InsertExtendMsg(notification.SourceID, notification.SessionType, &extendMsg); err != nil {
|
||||
log.NewError(msgDataToMQ.OperationID, "MsgFirstModify InsertExtendMsg failed", notification.SourceID, notification.SessionType, extendMsg, err.Error())
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
var reactionExtensionList = make(map[string]*server_api_params.KeyValue)
|
||||
for _, v := range notification.SuccessReactionExtensionList {
|
||||
reactionExtensionList[v.TypeKey] = &server_api_params.KeyValue{
|
||||
TypeKey: v.TypeKey,
|
||||
Value: v.Value,
|
||||
LatestUpdateTime: v.LatestUpdateTime,
|
||||
}
|
||||
}
|
||||
// is already modify
|
||||
if err := db.DB.InsertOrUpdateReactionExtendMsgSet(notification.SourceID, notification.SessionType, notification.ClientMsgID, notification.MsgFirstModifyTime, reactionExtensionList); err != nil {
|
||||
log.NewError(msgDataToMQ.OperationID, "InsertOrUpdateReactionExtendMsgSet failed")
|
||||
}
|
||||
}
|
||||
} else if msgDataToMQ.MsgData.ContentType == constant.ReactionMessageDeleter {
|
||||
notification := &base_info.ReactionMessageDeleteNotification{}
|
||||
if err := json.Unmarshal(msgDataToMQ.MsgData.Content, notification); err != nil {
|
||||
continue
|
||||
}
|
||||
if err := db.DB.DeleteReactionExtendMsgSet(notification.SourceID, notification.SessionType, notification.ClientMsgID, notification.MsgFirstModifyTime, notification.SuccessReactionExtensionList); err != nil {
|
||||
log.NewError(msgDataToMQ.OperationID, "InsertOrUpdateReactionExtendMsgSet failed")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func UnMarshallSetReactionMsgContent(content []byte) (notification *base_info.ReactionMessageModifierNotification, err error) {
|
||||
|
||||
return notification, nil
|
||||
}
|
@ -72,6 +72,7 @@ func (och *OnlineHistoryRedisConsumerHandler) Run(channelID int) {
|
||||
storageMsgList := make([]*pbMsg.MsgDataToMQ, 0, 80)
|
||||
notStoragePushMsgList := make([]*pbMsg.MsgDataToMQ, 0, 80)
|
||||
log.Debug(triggerID, "msg arrived channel", "channel id", channelID, msgList, msgChannelValue.aggregationID, len(msgList))
|
||||
var modifyMsgList []*pbMsg.MsgDataToMQ
|
||||
for _, v := range msgList {
|
||||
log.Debug(triggerID, "msg come to storage center", v.String())
|
||||
isHistory := utils.GetSwitchFromOptions(v.MsgData.Options, constant.IsHistory)
|
||||
@ -83,11 +84,15 @@ func (och *OnlineHistoryRedisConsumerHandler) Run(channelID int) {
|
||||
if !(!isSenderSync && msgChannelValue.aggregationID == v.MsgData.SendID) {
|
||||
notStoragePushMsgList = append(notStoragePushMsgList, v)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if v.MsgData.ContentType == constant.ReactionMessageModifier || v.MsgData.ContentType == constant.ReactionMessageDeleter {
|
||||
modifyMsgList = append(modifyMsgList, v)
|
||||
}
|
||||
}
|
||||
if len(modifyMsgList) > 0 {
|
||||
sendMessageToModifyMQ(msgChannelValue.aggregationID, triggerID, modifyMsgList)
|
||||
}
|
||||
|
||||
//switch msgChannelValue.msg.MsgData.SessionType {
|
||||
//case constant.SingleChatType:
|
||||
//case constant.GroupChatType:
|
||||
@ -107,6 +112,7 @@ func (och *OnlineHistoryRedisConsumerHandler) Run(channelID int) {
|
||||
singleMsgSuccessCount += uint64(len(storageMsgList))
|
||||
singleMsgSuccessCountMutex.Unlock()
|
||||
och.SendMessageToMongoCH(msgChannelValue.aggregationID, triggerID, storageMsgList, lastSeq)
|
||||
|
||||
for _, v := range storageMsgList {
|
||||
sendMessageToPushMQ(v, msgChannelValue.aggregationID)
|
||||
}
|
||||
@ -552,6 +558,17 @@ func sendMessageToPushMQ(message *pbMsg.MsgDataToMQ, pushToUserID string) {
|
||||
return
|
||||
}
|
||||
|
||||
func sendMessageToModifyMQ(aggregationID string, triggerID string, messages []*pbMsg.MsgDataToMQ) {
|
||||
if len(messages) > 0 {
|
||||
pid, offset, err := producerToModify.SendMessage(&pbMsg.MsgDataToModifyByMQ{AggregationID: aggregationID, MessageList: messages, TriggerID: triggerID}, aggregationID, triggerID)
|
||||
if err != nil {
|
||||
log.Error(triggerID, "kafka send failed", "send data", len(messages), "pid", pid, "offset", offset, "err", err.Error(), "key", aggregationID)
|
||||
} else {
|
||||
// log.NewWarn(m.OperationID, "sendMsgToKafka client msgID ", m.MsgData.ClientMsgID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// String hashes a string to a unique hashcode.
|
||||
//
|
||||
// crc32 returns a uint32, but for our use we need
|
||||
|
@ -61,7 +61,6 @@ func (mc *OnlineHistoryMongoConsumerHandler) handleChatWs2Mongo(cMsg *sarama.Con
|
||||
if unexistSeqList, err := db.DB.DelMsgBySeqList(DeleteMessageTips.UserID, DeleteMessageTips.SeqList, v.OperationID); err != nil {
|
||||
log.NewError(v.OperationID, utils.GetSelfFuncName(), "DelMsgBySeqList args: ", DeleteMessageTips.UserID, DeleteMessageTips.SeqList, v.OperationID, err.Error(), unexistSeqList)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,8 +26,10 @@ var (
|
||||
)
|
||||
|
||||
const (
|
||||
PushURL = "/push/single/alias"
|
||||
AuthURL = "/auth"
|
||||
PushURL = "/push/single/alias"
|
||||
AuthURL = "/auth"
|
||||
TaskURL = "/push/list/message"
|
||||
BatchPushURL = "/push/list/alias"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@ -53,23 +55,42 @@ type AuthResp struct {
|
||||
Token string `json:"token"`
|
||||
}
|
||||
|
||||
type TaskResp struct {
|
||||
TaskID string `json:"taskID"`
|
||||
}
|
||||
|
||||
type Settings struct {
|
||||
TTL *int64 `json:"ttl"`
|
||||
}
|
||||
|
||||
type Audience struct {
|
||||
Alias []string `json:"alias"`
|
||||
}
|
||||
|
||||
type PushMessage struct {
|
||||
Notification *Notification `json:"notification,omitempty"`
|
||||
Transmission *string `json:"transmission,omitempty"`
|
||||
}
|
||||
|
||||
type PushChannel struct {
|
||||
Ios *Ios `json:"ios"`
|
||||
Android *Android `json:"android"`
|
||||
}
|
||||
|
||||
type PushReq struct {
|
||||
RequestID string `json:"request_id"`
|
||||
Audience struct {
|
||||
Alias []string `json:"alias"`
|
||||
} `json:"audience"`
|
||||
PushMessage struct {
|
||||
Notification Notification `json:"notification,omitempty"`
|
||||
Transmission string `json:"transmission,omitempty"`
|
||||
} `json:"push_message"`
|
||||
PushChannel struct {
|
||||
Ios Ios `json:"ios"`
|
||||
Android Android `json:"android"`
|
||||
} `json:"push_channel"`
|
||||
RequestID *string `json:"request_id"`
|
||||
Settings *Settings `json:"settings"`
|
||||
Audience *Audience `json:"audience"`
|
||||
PushMessage *PushMessage `json:"push_message"`
|
||||
PushChannel *PushChannel `json:"push_channel"`
|
||||
IsAsync *bool `json:"is_async"`
|
||||
Taskid *string `json:"taskid"`
|
||||
}
|
||||
|
||||
type Ios struct {
|
||||
Aps struct {
|
||||
NotiType *string `json:"type"`
|
||||
AutoBadge *string `json:"auto_badge"`
|
||||
Aps struct {
|
||||
Sound string `json:"sound"`
|
||||
Alert Alert `json:"alert"`
|
||||
} `json:"aps"`
|
||||
@ -119,9 +140,9 @@ func newGetuiClient() *Getui {
|
||||
|
||||
func (g *Getui) Push(userIDList []string, title, detailContent, operationID string, opts push.PushOpts) (resp string, err error) {
|
||||
token, err := db.DB.GetGetuiToken()
|
||||
log.NewDebug(operationID, utils.GetSelfFuncName(), "token:", token)
|
||||
log.NewDebug(operationID, utils.GetSelfFuncName(), "token:", token, userIDList)
|
||||
if err != nil {
|
||||
log.NewError(operationID, utils.OperationIDGenerator(), "GetGetuiToken failed", err.Error())
|
||||
log.NewError(operationID, utils.GetSelfFuncName(), "GetGetuiToken failed", err.Error())
|
||||
}
|
||||
if token == "" || err != nil {
|
||||
token, err = g.getTokenAndSave2Redis(operationID)
|
||||
@ -130,47 +151,32 @@ func (g *Getui) Push(userIDList []string, title, detailContent, operationID stri
|
||||
return "", utils.Wrap(err, "")
|
||||
}
|
||||
}
|
||||
pushReq := PushReq{
|
||||
RequestID: utils.OperationIDGenerator(),
|
||||
Audience: struct {
|
||||
Alias []string `json:"alias"`
|
||||
}{Alias: []string{userIDList[0]}},
|
||||
}
|
||||
pushReq.PushMessage.Notification = Notification{
|
||||
|
||||
pushReq := PushReq{PushMessage: &PushMessage{Notification: &Notification{
|
||||
Title: title,
|
||||
Body: detailContent,
|
||||
ClickType: "startapp",
|
||||
ChannelID: config.Config.Push.Getui.ChannelID,
|
||||
ChannelName: config.Config.Push.Getui.ChannelName,
|
||||
}
|
||||
pushReq.PushChannel.Ios.Aps.Sound = "default"
|
||||
pushReq.PushChannel.Ios.Aps.Alert = Alert{
|
||||
Title: title,
|
||||
Body: title,
|
||||
}
|
||||
pushReq.PushChannel.Android.Ups.Notification = Notification{
|
||||
Title: title,
|
||||
Body: title,
|
||||
ClickType: "startapp",
|
||||
}
|
||||
pushReq.PushChannel.Android.Ups.Options = Options{
|
||||
HW: struct {
|
||||
DefaultSound bool `json:"/message/android/notification/default_sound"`
|
||||
ChannelID string `json:"/message/android/notification/channel_id"`
|
||||
Sound string `json:"/message/android/notification/sound"`
|
||||
Importance string `json:"/message/android/notification/importance"`
|
||||
}{ChannelID: "RingRing4", Sound: "/raw/ring001", Importance: "NORMAL"},
|
||||
XM: struct {
|
||||
ChannelID string `json:"/extra.channel_id"`
|
||||
}{ChannelID: "high_system"},
|
||||
VV: struct {
|
||||
Classification int "json:\"/classification\""
|
||||
}{
|
||||
Classification: 1,
|
||||
},
|
||||
}
|
||||
}}}
|
||||
pushReq.setPushChannel(title, detailContent)
|
||||
pushResp := PushResp{}
|
||||
err = g.request(PushURL, pushReq, token, &pushResp, operationID)
|
||||
if len(userIDList) > 1 {
|
||||
taskID, err := g.GetTaskID(operationID, token, pushReq)
|
||||
if err != nil {
|
||||
return "", utils.Wrap(err, "GetTaskIDAndSave2Redis failed")
|
||||
}
|
||||
pushReq = PushReq{Audience: &Audience{Alias: userIDList}}
|
||||
var IsAsync = true
|
||||
pushReq.IsAsync = &IsAsync
|
||||
pushReq.Taskid = &taskID
|
||||
err = g.request(BatchPushURL, pushReq, token, &pushResp, operationID)
|
||||
} else {
|
||||
reqID := utils.OperationIDGenerator()
|
||||
pushReq.RequestID = &reqID
|
||||
pushReq.Audience = &Audience{Alias: []string{userIDList[0]}}
|
||||
err = g.request(PushURL, pushReq, token, &pushResp, operationID)
|
||||
}
|
||||
switch err {
|
||||
case TokenExpireError:
|
||||
token, err = g.getTokenAndSave2Redis(operationID)
|
||||
@ -209,6 +215,17 @@ func (g *Getui) Auth(operationID string, timeStamp int64) (token string, expireT
|
||||
return respAuth.Token, int64(expire), err
|
||||
}
|
||||
|
||||
func (g *Getui) GetTaskID(operationID, token string, pushReq PushReq) (string, error) {
|
||||
respTask := TaskResp{}
|
||||
ttl := int64(1000 * 60 * 5)
|
||||
pushReq.Settings = &Settings{TTL: &ttl}
|
||||
err := g.request(TaskURL, pushReq, token, &respTask, operationID)
|
||||
if err != nil {
|
||||
return "", utils.Wrap(err, "")
|
||||
}
|
||||
return respTask.TaskID, nil
|
||||
}
|
||||
|
||||
func (g *Getui) request(url string, content interface{}, token string, returnStruct interface{}, operationID string) error {
|
||||
con, err := json.Marshal(content)
|
||||
if err != nil {
|
||||
@ -245,6 +262,41 @@ func (g *Getui) request(url string, content interface{}, token string, returnStr
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pushReq *PushReq) setPushChannel(title string, body string) {
|
||||
pushReq.PushChannel = &PushChannel{}
|
||||
autoBadge := "+1"
|
||||
pushReq.PushChannel.Ios = &Ios{AutoBadge: &autoBadge}
|
||||
notify := "notify"
|
||||
pushReq.PushChannel.Ios.NotiType = ¬ify
|
||||
pushReq.PushChannel.Ios.Aps.Sound = "default"
|
||||
pushReq.PushChannel.Ios.Aps.Alert = Alert{
|
||||
Title: title,
|
||||
Body: body,
|
||||
}
|
||||
pushReq.PushChannel.Android = &Android{}
|
||||
pushReq.PushChannel.Android.Ups.Notification = Notification{
|
||||
Title: title,
|
||||
Body: body,
|
||||
ClickType: "startapp",
|
||||
}
|
||||
pushReq.PushChannel.Android.Ups.Options = Options{
|
||||
HW: struct {
|
||||
DefaultSound bool `json:"/message/android/notification/default_sound"`
|
||||
ChannelID string `json:"/message/android/notification/channel_id"`
|
||||
Sound string `json:"/message/android/notification/sound"`
|
||||
Importance string `json:"/message/android/notification/importance"`
|
||||
}{ChannelID: "RingRing4", Sound: "/raw/ring001", Importance: "NORMAL"},
|
||||
XM: struct {
|
||||
ChannelID string `json:"/extra.channel_id"`
|
||||
}{ChannelID: "high_system"},
|
||||
VV: struct {
|
||||
Classification int "json:\"/classification\""
|
||||
}{
|
||||
Classification: 1,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Getui) getTokenAndSave2Redis(operationID string) (token string, err error) {
|
||||
token, expireTime, err := g.Auth(operationID, time.Now().UnixNano()/1e6)
|
||||
if err != nil {
|
||||
@ -257,3 +309,17 @@ func (g *Getui) getTokenAndSave2Redis(operationID string) (token string, err err
|
||||
}
|
||||
return token, nil
|
||||
}
|
||||
|
||||
func (g *Getui) GetTaskIDAndSave2Redis(operationID, token string, pushReq PushReq) (taskID string, err error) {
|
||||
ttl := int64(1000 * 60 * 60 * 24)
|
||||
pushReq.Settings = &Settings{TTL: &ttl}
|
||||
taskID, err = g.GetTaskID(operationID, token, pushReq)
|
||||
if err != nil {
|
||||
return "", utils.Wrap(err, "GetTaskIDAndSave2Redis failed")
|
||||
}
|
||||
err = db.DB.SetGetuiTaskID(taskID, 60*60*23)
|
||||
if err != nil {
|
||||
return "", utils.Wrap(err, "Auth failed")
|
||||
}
|
||||
return token, nil
|
||||
}
|
||||
|
@ -75,14 +75,14 @@ func callbackOnlinePush(operationID string, userIDList []string, msg *commonPb.M
|
||||
},
|
||||
UserIDList: userIDList,
|
||||
},
|
||||
OfflinePushInfo: msg.OfflinePushInfo,
|
||||
ClientMsgID: msg.ClientMsgID,
|
||||
SendID: msg.SendID,
|
||||
GroupID: msg.GroupID,
|
||||
ContentType: msg.ContentType,
|
||||
SessionType: msg.SessionType,
|
||||
AtUserIDList: msg.AtUserIDList,
|
||||
Content: callback.GetContent(msg),
|
||||
//OfflinePushInfo: msg.OfflinePushInfo,
|
||||
ClientMsgID: msg.ClientMsgID,
|
||||
SendID: msg.SendID,
|
||||
GroupID: msg.GroupID,
|
||||
ContentType: msg.ContentType,
|
||||
SessionType: msg.SessionType,
|
||||
AtUserIDList: msg.AtUserIDList,
|
||||
Content: callback.GetContent(msg),
|
||||
}
|
||||
resp := &cbApi.CallbackBeforePushResp{CommonCallbackResp: &callbackResp}
|
||||
if err := http.CallBackPostReturn(config.Config.Callback.CallbackUrl, constant.CallbackOnlinePushCommand, req, resp, config.Config.Callback.CallbackOnlinePush.CallbackTimeOut); err != nil {
|
||||
@ -97,9 +97,9 @@ func callbackOnlinePush(operationID string, userIDList []string, msg *commonPb.M
|
||||
}
|
||||
}
|
||||
if resp.ErrCode == constant.CallbackHandleSuccess && resp.ActionCode == constant.ActionAllow {
|
||||
if resp.OfflinePushInfo != nil {
|
||||
msg.OfflinePushInfo = resp.OfflinePushInfo
|
||||
}
|
||||
//if resp.OfflinePushInfo != nil {
|
||||
// msg.OfflinePushInfo = resp.OfflinePushInfo
|
||||
//}
|
||||
}
|
||||
return callbackResp
|
||||
}
|
||||
@ -117,14 +117,15 @@ func callbackBeforeSuperGroupOnlinePush(operationID string, groupID string, msg
|
||||
PlatformID: msg.SenderPlatformID,
|
||||
Platform: constant.PlatformIDToName(int(msg.SenderPlatformID)),
|
||||
},
|
||||
OfflinePushInfo: msg.OfflinePushInfo,
|
||||
ClientMsgID: msg.ClientMsgID,
|
||||
SendID: msg.SendID,
|
||||
GroupID: groupID,
|
||||
ContentType: msg.ContentType,
|
||||
SessionType: msg.SessionType,
|
||||
AtUserIDList: msg.AtUserIDList,
|
||||
Content: callback.GetContent(msg),
|
||||
//OfflinePushInfo: msg.OfflinePushInfo,
|
||||
ClientMsgID: msg.ClientMsgID,
|
||||
SendID: msg.SendID,
|
||||
GroupID: groupID,
|
||||
ContentType: msg.ContentType,
|
||||
SessionType: msg.SessionType,
|
||||
AtUserIDList: msg.AtUserIDList,
|
||||
Content: callback.GetContent(msg),
|
||||
Seq: msg.Seq,
|
||||
}
|
||||
resp := &cbApi.CallbackBeforeSuperGroupOnlinePushResp{CommonCallbackResp: &callbackResp}
|
||||
if err := http.CallBackPostReturn(config.Config.Callback.CallbackUrl, constant.CallbackSuperGroupOnlinePushCommand, req, resp, config.Config.Callback.CallbackBeforeSuperGroupOnlinePush.CallbackTimeOut); err != nil {
|
||||
@ -142,9 +143,9 @@ func callbackBeforeSuperGroupOnlinePush(operationID string, groupID string, msg
|
||||
if len(resp.UserIDList) != 0 {
|
||||
*pushToUserList = resp.UserIDList
|
||||
}
|
||||
if resp.OfflinePushInfo != nil {
|
||||
msg.OfflinePushInfo = resp.OfflinePushInfo
|
||||
}
|
||||
//if resp.OfflinePushInfo != nil {
|
||||
// msg.OfflinePushInfo = resp.OfflinePushInfo
|
||||
//}
|
||||
}
|
||||
log.NewDebug(operationID, utils.GetSelfFuncName(), pushToUserList, resp.UserIDList)
|
||||
return callbackResp
|
||||
|
@ -93,10 +93,11 @@ func (r *RPCServer) PushMsg(_ context.Context, pbData *pbPush.PushMsgReq) (*pbPu
|
||||
}
|
||||
|
||||
func (r *RPCServer) DelUserPushToken(c context.Context, req *pbPush.DelUserPushTokenReq) (*pbPush.DelUserPushTokenResp, error) {
|
||||
log.Debug(req.OperationID, utils.GetSelfFuncName(), "req", req.String())
|
||||
var resp pbPush.DelUserPushTokenResp
|
||||
err := db.DB.DelFcmToken(req.UserID, int(req.PlatformID))
|
||||
if err != nil {
|
||||
errMsg := req.OperationID + " " + "SetFcmToken failed " + err.Error()
|
||||
errMsg := req.OperationID + " " + "DelFcmToken failed " + err.Error()
|
||||
log.NewError(req.OperationID, errMsg)
|
||||
resp.ErrCode = 500
|
||||
resp.ErrMsg = errMsg
|
||||
|
@ -70,7 +70,7 @@ func MsgToUser(pushMsg *pbPush.PushMsgReq) {
|
||||
wsResult = append(wsResult, reply.SinglePushResult...)
|
||||
}
|
||||
}
|
||||
log.NewInfo(pushMsg.OperationID, "push_result", wsResult, "sendData", pushMsg.MsgData)
|
||||
log.NewInfo(pushMsg.OperationID, "push_result", wsResult, "sendData", pushMsg.MsgData, "isOfflinePush", isOfflinePush)
|
||||
successCount++
|
||||
if isOfflinePush && pushMsg.PushToUserID != pushMsg.MsgData.SendID {
|
||||
// save invitation info for offline push
|
||||
@ -79,6 +79,9 @@ func MsgToUser(pushMsg *pbPush.PushMsgReq) {
|
||||
return
|
||||
}
|
||||
}
|
||||
if pushMsg.MsgData.ContentType > constant.NotificationBegin && pushMsg.MsgData.ContentType < constant.NotificationEnd && pushMsg.MsgData.ContentType != constant.SignalingNotification {
|
||||
return
|
||||
}
|
||||
if pushMsg.MsgData.ContentType == constant.SignalingNotification {
|
||||
isSend, err := db.DB.HandleSignalInfo(pushMsg.OperationID, pushMsg.MsgData, pushMsg.PushToUserID)
|
||||
if err != nil {
|
||||
@ -198,12 +201,29 @@ func MsgToSuperGroupUser(pushMsg *pbPush.PushMsgReq) {
|
||||
log.Debug(pushMsg.OperationID, "push_result", wsResult, "sendData", pushMsg.MsgData)
|
||||
successCount++
|
||||
if isOfflinePush {
|
||||
if pushMsg.MsgData.ContentType > constant.NotificationBegin && pushMsg.MsgData.ContentType < constant.NotificationEnd && pushMsg.MsgData.ContentType != constant.SignalingNotification {
|
||||
return
|
||||
}
|
||||
var onlineSuccessUserIDList []string
|
||||
var WebAndPcBackgroundUserIDList []string
|
||||
onlineSuccessUserIDList = append(onlineSuccessUserIDList, pushMsg.MsgData.SendID)
|
||||
for _, v := range wsResult {
|
||||
if v.OnlinePush && v.UserID != pushMsg.MsgData.SendID {
|
||||
onlineSuccessUserIDList = append(onlineSuccessUserIDList, v.UserID)
|
||||
}
|
||||
if !v.OnlinePush {
|
||||
if len(v.Resp) != 0 {
|
||||
for _, singleResult := range v.Resp {
|
||||
if singleResult.ResultCode == -2 {
|
||||
if constant.PlatformIDToClass(int(singleResult.RecvPlatFormID)) == constant.TerminalPC ||
|
||||
singleResult.RecvPlatFormID == constant.WebPlatformID {
|
||||
WebAndPcBackgroundUserIDList = append(WebAndPcBackgroundUserIDList, v.UserID)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
onlineFailedUserIDList := utils.DifferenceString(onlineSuccessUserIDList, pushToUserIDList)
|
||||
//Use offline push messaging
|
||||
@ -237,7 +257,7 @@ func MsgToSuperGroupUser(pushMsg *pbPush.PushMsgReq) {
|
||||
if err != nil {
|
||||
log.NewError(pushMsg.OperationID, utils.GetSelfFuncName(), "GetOfflinePushOpts failed", pushMsg, err.Error())
|
||||
}
|
||||
log.NewInfo(pushMsg.OperationID, utils.GetSelfFuncName(), onlineFailedUserIDList, title, detailContent, "opts:", opts)
|
||||
log.NewInfo(pushMsg.OperationID, utils.GetSelfFuncName(), needOfflinePushUserIDList, title, detailContent, "opts:", opts)
|
||||
if title == "" {
|
||||
switch pushMsg.MsgData.ContentType {
|
||||
case constant.Text:
|
||||
@ -274,6 +294,22 @@ func MsgToSuperGroupUser(pushMsg *pbPush.PushMsgReq) {
|
||||
promePkg.PromeInc(promePkg.MsgOfflinePushSuccessCounter)
|
||||
log.NewDebug(pushMsg.OperationID, "offline push return result is ", pushResult, pushMsg.MsgData)
|
||||
}
|
||||
needBackgroupPushUserID := utils.IntersectString(needOfflinePushUserIDList, WebAndPcBackgroundUserIDList)
|
||||
grpcCons := getcdv3.GetDefaultGatewayConn4Unique(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), pushMsg.OperationID)
|
||||
if len(needBackgroupPushUserID) > 0 {
|
||||
//Online push message
|
||||
log.Debug(pushMsg.OperationID, "len grpc", len(grpcCons), "data", pushMsg.String())
|
||||
for _, v := range grpcCons {
|
||||
msgClient := pbRelay.NewRelayClient(v)
|
||||
_, err := msgClient.SuperGroupBackgroundOnlinePush(context.Background(), &pbRelay.OnlineBatchPushOneMsgReq{OperationID: pushMsg.OperationID, MsgData: pushMsg.MsgData,
|
||||
PushToUserIDList: needBackgroupPushUserID})
|
||||
if err != nil {
|
||||
log.NewError("push data to client rpc err", pushMsg.OperationID, "err", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ package push
|
||||
|
||||
import "Open_IM/pkg/common/constant"
|
||||
|
||||
var PushTerminal = []int{constant.IOSPlatformID, constant.AndroidPlatformID}
|
||||
var PushTerminal = []int{constant.IOSPlatformID, constant.AndroidPlatformID, constant.WebPlatformID}
|
||||
|
||||
type OfflinePusher interface {
|
||||
Push(userIDList []string, title, detailContent, operationID string, opts PushOpts) (resp string, err error)
|
||||
|
@ -133,6 +133,24 @@ func (s *adminCMSServer) AdminLogin(_ context.Context, req *pbAdminCMS.AdminLogi
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (s *adminCMSServer) GetUserToken(_ context.Context, req *pbAdminCMS.GetUserTokenReq) (*pbAdminCMS.GetUserTokenResp, error) {
|
||||
log.NewInfo(req.OperationID, utils.GetSelfFuncName(), "req: ", req.String())
|
||||
resp := &pbAdminCMS.GetUserTokenResp{
|
||||
CommonResp: &pbAdminCMS.CommonResp{},
|
||||
}
|
||||
token, expTime, err := token_verify.CreateToken(req.UserID, int(req.PlatformID))
|
||||
if err != nil {
|
||||
log.NewError(req.OperationID, utils.GetSelfFuncName(), "generate token failed", "userID: ", req.UserID, req.PlatformID, err.Error())
|
||||
resp.CommonResp.ErrCode = constant.ErrTokenUnknown.ErrCode
|
||||
resp.CommonResp.ErrMsg = err.Error()
|
||||
return resp, nil
|
||||
}
|
||||
resp.Token = token
|
||||
resp.ExpTime = expTime
|
||||
log.NewInfo(req.OperationID, utils.GetSelfFuncName(), "req: ", resp.String())
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (s *adminCMSServer) AddUserRegisterAddFriendIDList(_ context.Context, req *pbAdminCMS.AddUserRegisterAddFriendIDListReq) (*pbAdminCMS.AddUserRegisterAddFriendIDListResp, error) {
|
||||
log.NewInfo(req.OperationID, utils.GetSelfFuncName(), "req: ", req.String())
|
||||
resp := &pbAdminCMS.AddUserRegisterAddFriendIDListResp{CommonResp: &pbAdminCMS.CommonResp{}}
|
||||
@ -197,37 +215,50 @@ func (s *adminCMSServer) GetUserRegisterAddFriendIDList(_ context.Context, req *
|
||||
func (s *adminCMSServer) GetChatLogs(_ context.Context, req *pbAdminCMS.GetChatLogsReq) (*pbAdminCMS.GetChatLogsResp, error) {
|
||||
log.NewInfo(req.OperationID, utils.GetSelfFuncName(), "GetChatLogs", req.String())
|
||||
resp := &pbAdminCMS.GetChatLogsResp{CommonResp: &pbAdminCMS.CommonResp{}, Pagination: &server_api_params.ResponsePagination{}}
|
||||
time, err := utils.TimeStringToTime(req.SendTime)
|
||||
if err != nil {
|
||||
log.NewError(req.OperationID, utils.GetSelfFuncName(), "time string parse error", err.Error())
|
||||
resp.CommonResp.ErrCode = constant.ErrArgs.ErrCode
|
||||
resp.CommonResp.ErrMsg = err.Error()
|
||||
return resp, nil
|
||||
}
|
||||
chatLog := db.ChatLog{
|
||||
Content: req.Content,
|
||||
SendTime: time,
|
||||
ContentType: req.ContentType,
|
||||
SessionType: req.SessionType,
|
||||
RecvID: req.RecvID,
|
||||
SendID: req.SendID,
|
||||
}
|
||||
log.NewDebug(req.OperationID, utils.GetSelfFuncName(), "chat_log: ", chatLog)
|
||||
nums, err := imdb.GetChatLogCount(chatLog)
|
||||
if err != nil {
|
||||
log.NewError(req.OperationID, utils.GetSelfFuncName(), "GetChatLogCount", err.Error())
|
||||
resp.CommonResp.ErrCode = constant.ErrDB.ErrCode
|
||||
resp.CommonResp.ErrMsg = err.Error()
|
||||
return resp, nil
|
||||
if req.SendTime != "" {
|
||||
sendTime, err := utils.TimeStringToTime(req.SendTime)
|
||||
if err != nil {
|
||||
log.NewError(req.OperationID, utils.GetSelfFuncName(), "time string parse error", err.Error())
|
||||
resp.CommonResp.ErrCode = constant.ErrArgs.ErrCode
|
||||
resp.CommonResp.ErrMsg = err.Error()
|
||||
return resp, nil
|
||||
}
|
||||
chatLog.SendTime = sendTime
|
||||
}
|
||||
resp.ChatLogsNum = int32(nums)
|
||||
chatLogs, err := imdb.GetChatLog(chatLog, req.Pagination.PageNumber, req.Pagination.ShowNumber)
|
||||
|
||||
log.NewDebug(req.OperationID, utils.GetSelfFuncName(), "chat_log: ", chatLog)
|
||||
|
||||
num, chatLogs, err := imdb.GetChatLog(&chatLog, req.Pagination.PageNumber, req.Pagination.ShowNumber, []int32{
|
||||
constant.Text,
|
||||
constant.Picture,
|
||||
constant.Voice,
|
||||
constant.Video,
|
||||
constant.File,
|
||||
constant.AtText,
|
||||
constant.Merger,
|
||||
constant.Card,
|
||||
constant.Location,
|
||||
constant.Custom,
|
||||
constant.Revoke,
|
||||
constant.Quote,
|
||||
constant.AdvancedText,
|
||||
constant.AdvancedRevoke,
|
||||
constant.CustomNotTriggerConversation,
|
||||
})
|
||||
if err != nil {
|
||||
log.NewError(req.OperationID, utils.GetSelfFuncName(), "GetChatLog", err.Error())
|
||||
resp.CommonResp.ErrCode = constant.ErrDB.ErrCode
|
||||
resp.CommonResp.ErrMsg = err.Error()
|
||||
return resp, nil
|
||||
}
|
||||
resp.ChatLogsNum = int32(num)
|
||||
for _, chatLog := range chatLogs {
|
||||
pbChatLog := &pbAdminCMS.ChatLog{}
|
||||
utils.CopyStructFields(pbChatLog, chatLog)
|
||||
@ -265,7 +296,6 @@ func (s *adminCMSServer) GetChatLogs(_ context.Context, req *pbAdminCMS.GetChatL
|
||||
CurrentPage: req.Pagination.PageNumber,
|
||||
ShowNumber: req.Pagination.ShowNumber,
|
||||
}
|
||||
|
||||
log.NewInfo(req.OperationID, utils.GetSelfFuncName(), "resp output: ", resp.String())
|
||||
return resp, nil
|
||||
}
|
||||
|
@ -50,6 +50,11 @@ func (rpc *rpcAuth) UserRegister(_ context.Context, req *pbAuth.UserRegisterReq)
|
||||
|
||||
func (rpc *rpcAuth) UserToken(_ context.Context, req *pbAuth.UserTokenReq) (*pbAuth.UserTokenResp, error) {
|
||||
log.NewInfo(req.OperationID, utils.GetSelfFuncName(), " rpc args ", req.String())
|
||||
_, err := imdb.GetUserByUserID(req.FromUserID)
|
||||
if err != nil {
|
||||
log.NewError(req.OperationID, "not this user:", req.FromUserID, req.String())
|
||||
return &pbAuth.UserTokenResp{CommonResp: &pbAuth.CommonResp{ErrCode: constant.ErrDB.ErrCode, ErrMsg: err.Error()}}, nil
|
||||
}
|
||||
tokens, expTime, err := token_verify.CreateToken(req.FromUserID, int(req.Platform))
|
||||
if err != nil {
|
||||
errMsg := req.OperationID + " token_verify.CreateToken failed " + err.Error() + req.FromUserID + utils.Int32ToString(req.Platform)
|
||||
|
@ -4,11 +4,14 @@ import (
|
||||
cbApi "Open_IM/pkg/call_back_struct"
|
||||
"Open_IM/pkg/common/config"
|
||||
"Open_IM/pkg/common/constant"
|
||||
"Open_IM/pkg/common/db"
|
||||
"Open_IM/pkg/common/http"
|
||||
"Open_IM/pkg/common/log"
|
||||
pbGroup "Open_IM/pkg/proto/group"
|
||||
"Open_IM/pkg/utils"
|
||||
http2 "net/http"
|
||||
|
||||
"google.golang.org/protobuf/types/known/wrapperspb"
|
||||
)
|
||||
|
||||
func callbackBeforeCreateGroup(req *pbGroup.CreateGroupReq) cbApi.CommonCallbackResp {
|
||||
@ -19,6 +22,9 @@ func callbackBeforeCreateGroup(req *pbGroup.CreateGroupReq) cbApi.CommonCallback
|
||||
log.NewDebug(req.OperationID, utils.GetSelfFuncName(), req.String())
|
||||
commonCallbackReq := &cbApi.CallbackBeforeCreateGroupReq{
|
||||
CallbackCommand: constant.CallbackBeforeCreateGroupCommand,
|
||||
OperationID: req.OperationID,
|
||||
GroupInfo: *req.GroupInfo,
|
||||
InitMemberList: req.InitMemberList,
|
||||
}
|
||||
resp := &cbApi.CallbackBeforeCreateGroupResp{
|
||||
CommonCallbackResp: &callbackResp,
|
||||
@ -41,7 +47,7 @@ func callbackBeforeCreateGroup(req *pbGroup.CreateGroupReq) cbApi.CommonCallback
|
||||
req.GroupInfo.GroupID = *resp.GroupID
|
||||
}
|
||||
if resp.GroupName != nil {
|
||||
req.GroupInfo.GroupName = *resp.GroupID
|
||||
req.GroupInfo.GroupName = *resp.GroupName
|
||||
}
|
||||
if resp.Notification != nil {
|
||||
req.GroupInfo.Notification = *resp.Notification
|
||||
@ -68,7 +74,7 @@ func callbackBeforeCreateGroup(req *pbGroup.CreateGroupReq) cbApi.CommonCallback
|
||||
req.GroupInfo.GroupType = *resp.GroupType
|
||||
}
|
||||
if resp.NeedVerification != nil {
|
||||
req.GroupInfo.NeedVerification = *resp.GroupType
|
||||
req.GroupInfo.NeedVerification = *resp.NeedVerification
|
||||
}
|
||||
if resp.LookMemberInfo != nil {
|
||||
req.GroupInfo.LookMemberInfo = *resp.LookMemberInfo
|
||||
@ -76,3 +82,102 @@ func callbackBeforeCreateGroup(req *pbGroup.CreateGroupReq) cbApi.CommonCallback
|
||||
}
|
||||
return callbackResp
|
||||
}
|
||||
|
||||
func CallbackBeforeMemberJoinGroup(operationID string, groupMember *db.GroupMember, groupEx string) cbApi.CommonCallbackResp {
|
||||
callbackResp := cbApi.CommonCallbackResp{OperationID: operationID}
|
||||
if !config.Config.Callback.CallbackBeforeMemberJoinGroup.Enable {
|
||||
return callbackResp
|
||||
}
|
||||
log.NewDebug(operationID, "args: ", *groupMember)
|
||||
callbackReq := cbApi.CallbackBeforeMemberJoinGroupReq{
|
||||
CallbackCommand: constant.CallbackBeforeMemberJoinGroupCommand,
|
||||
OperationID: operationID,
|
||||
GroupID: groupMember.GroupID,
|
||||
UserID: groupMember.UserID,
|
||||
Ex: groupMember.Ex,
|
||||
GroupEx: groupEx,
|
||||
}
|
||||
resp := &cbApi.CallbackBeforeMemberJoinGroupResp{
|
||||
CommonCallbackResp: &callbackResp,
|
||||
}
|
||||
if err := http.CallBackPostReturn(config.Config.Callback.CallbackUrl, constant.CallbackBeforeMemberJoinGroupCommand, callbackReq, resp, config.Config.Callback.CallbackBeforeMemberJoinGroup.CallbackTimeOut); err != nil {
|
||||
callbackResp.ErrCode = http2.StatusInternalServerError
|
||||
callbackResp.ErrMsg = err.Error()
|
||||
if !config.Config.Callback.CallbackBeforeMemberJoinGroup.CallbackFailedContinue {
|
||||
callbackResp.ActionCode = constant.ActionForbidden
|
||||
return callbackResp
|
||||
} else {
|
||||
callbackResp.ActionCode = constant.ActionAllow
|
||||
return callbackResp
|
||||
}
|
||||
}
|
||||
if resp.MuteEndTime != nil {
|
||||
groupMember.MuteEndTime = utils.UnixSecondToTime(*resp.MuteEndTime)
|
||||
}
|
||||
if resp.FaceURL != nil {
|
||||
groupMember.FaceURL = *resp.FaceURL
|
||||
}
|
||||
if resp.Ex != nil {
|
||||
groupMember.Ex = *resp.Ex
|
||||
}
|
||||
if resp.NickName != nil {
|
||||
groupMember.Nickname = *resp.NickName
|
||||
}
|
||||
if resp.RoleLevel != nil {
|
||||
groupMember.RoleLevel = *resp.RoleLevel
|
||||
}
|
||||
return callbackResp
|
||||
}
|
||||
|
||||
func CallbackBeforeSetGroupMemberInfo(req *pbGroup.SetGroupMemberInfoReq) cbApi.CommonCallbackResp {
|
||||
callbackResp := cbApi.CommonCallbackResp{OperationID: req.OperationID}
|
||||
if !config.Config.Callback.CallbackBeforeSetGroupMemberInfo.Enable {
|
||||
return callbackResp
|
||||
}
|
||||
callbackReq := cbApi.CallbackBeforeSetGroupMemberInfoReq{
|
||||
CallbackCommand: constant.CallbackBeforeSetGroupMemberInfoCommand,
|
||||
OperationID: req.OperationID,
|
||||
GroupID: req.GroupID,
|
||||
UserID: req.UserID,
|
||||
}
|
||||
if req.Nickname != nil {
|
||||
callbackReq.Nickname = req.Nickname.Value
|
||||
}
|
||||
if req.FaceURL != nil {
|
||||
callbackReq.FaceURL = req.FaceURL.Value
|
||||
}
|
||||
if req.RoleLevel != nil {
|
||||
callbackReq.RoleLevel = req.RoleLevel.Value
|
||||
}
|
||||
if req.Ex != nil {
|
||||
callbackReq.Ex = req.Ex.Value
|
||||
}
|
||||
resp := &cbApi.CallbackBeforeSetGroupMemberInfoResp{
|
||||
CommonCallbackResp: &callbackResp,
|
||||
}
|
||||
|
||||
if err := http.CallBackPostReturn(config.Config.Callback.CallbackUrl, constant.CallbackBeforeSetGroupMemberInfoCommand, callbackReq, resp, config.Config.Callback.CallbackBeforeSetGroupMemberInfo.CallbackTimeOut); err != nil {
|
||||
callbackResp.ErrCode = http2.StatusInternalServerError
|
||||
callbackResp.ErrMsg = err.Error()
|
||||
if !config.Config.Callback.CallbackBeforeSetGroupMemberInfo.CallbackFailedContinue {
|
||||
callbackResp.ActionCode = constant.ActionForbidden
|
||||
return callbackResp
|
||||
} else {
|
||||
callbackResp.ActionCode = constant.ActionAllow
|
||||
return callbackResp
|
||||
}
|
||||
}
|
||||
if resp.FaceURL != nil {
|
||||
req.FaceURL = &wrapperspb.StringValue{Value: *resp.FaceURL}
|
||||
}
|
||||
if resp.Nickname != nil {
|
||||
req.Nickname = &wrapperspb.StringValue{Value: *resp.Nickname}
|
||||
}
|
||||
if resp.RoleLevel != nil {
|
||||
req.RoleLevel = &wrapperspb.Int32Value{Value: *resp.RoleLevel}
|
||||
}
|
||||
if resp.Ex != nil {
|
||||
req.Ex = &wrapperspb.StringValue{Value: *resp.Ex}
|
||||
}
|
||||
return callbackResp
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -8,6 +8,7 @@ import (
|
||||
commonPb "Open_IM/pkg/proto/sdk_ws"
|
||||
"Open_IM/pkg/utils"
|
||||
"context"
|
||||
|
||||
"github.com/go-redis/redis/v8"
|
||||
)
|
||||
|
||||
|
435
internal/rpc/msg/extend_msg.go
Normal file
435
internal/rpc/msg/extend_msg.go
Normal file
@ -0,0 +1,435 @@
|
||||
package msg
|
||||
|
||||
import (
|
||||
"Open_IM/pkg/common/constant"
|
||||
"Open_IM/pkg/common/db"
|
||||
"Open_IM/pkg/common/log"
|
||||
"Open_IM/pkg/proto/msg"
|
||||
"Open_IM/pkg/proto/sdk_ws"
|
||||
"Open_IM/pkg/utils"
|
||||
"context"
|
||||
go_redis "github.com/go-redis/redis/v8"
|
||||
|
||||
"time"
|
||||
)
|
||||
|
||||
func (rpc *rpcChat) SetMessageReactionExtensions(ctx context.Context, req *msg.SetMessageReactionExtensionsReq) (resp *msg.SetMessageReactionExtensionsResp, err error) {
|
||||
log.Debug(req.OperationID, utils.GetSelfFuncName(), "rpc args is:", req.String())
|
||||
var rResp msg.SetMessageReactionExtensionsResp
|
||||
rResp.ClientMsgID = req.ClientMsgID
|
||||
rResp.MsgFirstModifyTime = req.MsgFirstModifyTime
|
||||
callbackResp := callbackSetMessageReactionExtensions(req)
|
||||
if callbackResp.ActionCode != constant.ActionAllow || callbackResp.ErrCode != 0 {
|
||||
rResp.ErrCode = int32(callbackResp.ErrCode)
|
||||
rResp.ErrMsg = callbackResp.ErrMsg
|
||||
for _, value := range req.ReactionExtensionList {
|
||||
temp := new(msg.KeyValueResp)
|
||||
temp.KeyValue = value
|
||||
temp.ErrMsg = callbackResp.ErrMsg
|
||||
temp.ErrCode = 100
|
||||
rResp.Result = append(rResp.Result, temp)
|
||||
}
|
||||
return &rResp, nil
|
||||
}
|
||||
//if ExternalExtension
|
||||
if req.IsExternalExtensions {
|
||||
var isHistory bool
|
||||
if req.IsReact {
|
||||
isHistory = false
|
||||
} else {
|
||||
isHistory = true
|
||||
}
|
||||
rResp.MsgFirstModifyTime = callbackResp.MsgFirstModifyTime
|
||||
rResp.Result = callbackResp.ResultReactionExtensionList
|
||||
ExtendMessageUpdatedNotification(req.OperationID, req.OpUserID, req.SourceID, req.SessionType, req, &rResp, isHistory, false)
|
||||
return &rResp, nil
|
||||
}
|
||||
for _, v := range callbackResp.ResultReactionExtensionList {
|
||||
if v.ErrCode == 0 {
|
||||
req.ReactionExtensionList[v.KeyValue.TypeKey] = v.KeyValue
|
||||
} else {
|
||||
delete(req.ReactionExtensionList, v.KeyValue.TypeKey)
|
||||
rResp.Result = append(rResp.Result, v)
|
||||
}
|
||||
}
|
||||
isExists, err := db.DB.JudgeMessageReactionEXISTS(req.ClientMsgID, req.SessionType)
|
||||
if err != nil {
|
||||
rResp.ErrCode = 100
|
||||
rResp.ErrMsg = err.Error()
|
||||
for _, value := range req.ReactionExtensionList {
|
||||
temp := new(msg.KeyValueResp)
|
||||
temp.KeyValue = value
|
||||
temp.ErrMsg = err.Error()
|
||||
temp.ErrCode = 100
|
||||
rResp.Result = append(rResp.Result, temp)
|
||||
}
|
||||
return &rResp, nil
|
||||
}
|
||||
|
||||
if !isExists {
|
||||
if !req.IsReact {
|
||||
log.Debug(req.OperationID, "redis handle firstly", req.String())
|
||||
rResp.MsgFirstModifyTime = utils.GetCurrentTimestampByMill()
|
||||
for k, v := range req.ReactionExtensionList {
|
||||
err := rpc.dMessageLocker.LockMessageTypeKey(req.ClientMsgID, k)
|
||||
if err != nil {
|
||||
setKeyResultInfo(&rResp, 100, err.Error(), req.ClientMsgID, k, v)
|
||||
continue
|
||||
}
|
||||
v.LatestUpdateTime = utils.GetCurrentTimestampByMill()
|
||||
newerr := db.DB.SetMessageTypeKeyValue(req.ClientMsgID, req.SessionType, k, utils.StructToJsonString(v))
|
||||
if newerr != nil {
|
||||
setKeyResultInfo(&rResp, 201, newerr.Error(), req.ClientMsgID, k, v)
|
||||
continue
|
||||
}
|
||||
setKeyResultInfo(&rResp, 0, "", req.ClientMsgID, k, v)
|
||||
}
|
||||
rResp.IsReact = true
|
||||
_, err := db.DB.SetMessageReactionExpire(req.ClientMsgID, req.SessionType, time.Duration(24*3)*time.Hour)
|
||||
if err != nil {
|
||||
log.Error(req.OperationID, "SetMessageReactionExpire err:", err.Error(), req.String())
|
||||
}
|
||||
} else {
|
||||
err := rpc.dMessageLocker.LockGlobalMessage(req.ClientMsgID)
|
||||
if err != nil {
|
||||
rResp.ErrCode = 100
|
||||
rResp.ErrMsg = err.Error()
|
||||
for _, value := range req.ReactionExtensionList {
|
||||
temp := new(msg.KeyValueResp)
|
||||
temp.KeyValue = value
|
||||
temp.ErrMsg = err.Error()
|
||||
temp.ErrCode = 100
|
||||
rResp.Result = append(rResp.Result, temp)
|
||||
}
|
||||
return &rResp, nil
|
||||
}
|
||||
mongoValue, err := db.DB.GetExtendMsg(req.SourceID, req.SessionType, req.ClientMsgID, req.MsgFirstModifyTime)
|
||||
if err != nil {
|
||||
rResp.ErrCode = 200
|
||||
rResp.ErrMsg = err.Error()
|
||||
for _, value := range req.ReactionExtensionList {
|
||||
temp := new(msg.KeyValueResp)
|
||||
temp.KeyValue = value
|
||||
temp.ErrMsg = err.Error()
|
||||
temp.ErrCode = 100
|
||||
rResp.Result = append(rResp.Result, temp)
|
||||
}
|
||||
return &rResp, nil
|
||||
}
|
||||
setValue := make(map[string]*server_api_params.KeyValue)
|
||||
for k, v := range req.ReactionExtensionList {
|
||||
|
||||
temp := new(server_api_params.KeyValue)
|
||||
if vv, ok := mongoValue.ReactionExtensionList[k]; ok {
|
||||
utils.CopyStructFields(temp, &vv)
|
||||
if v.LatestUpdateTime != vv.LatestUpdateTime {
|
||||
setKeyResultInfo(&rResp, 300, "message have update", req.ClientMsgID, k, temp)
|
||||
continue
|
||||
}
|
||||
}
|
||||
temp.TypeKey = k
|
||||
temp.Value = v.Value
|
||||
temp.LatestUpdateTime = utils.GetCurrentTimestampByMill()
|
||||
setValue[k] = temp
|
||||
}
|
||||
err = db.DB.InsertOrUpdateReactionExtendMsgSet(req.SourceID, req.SessionType, req.ClientMsgID, req.MsgFirstModifyTime, setValue)
|
||||
if err != nil {
|
||||
for _, value := range setValue {
|
||||
temp := new(msg.KeyValueResp)
|
||||
temp.KeyValue = value
|
||||
temp.ErrMsg = err.Error()
|
||||
temp.ErrCode = 100
|
||||
rResp.Result = append(rResp.Result, temp)
|
||||
}
|
||||
} else {
|
||||
for _, value := range setValue {
|
||||
temp := new(msg.KeyValueResp)
|
||||
temp.KeyValue = value
|
||||
rResp.Result = append(rResp.Result, temp)
|
||||
}
|
||||
}
|
||||
lockErr := rpc.dMessageLocker.UnLockGlobalMessage(req.ClientMsgID)
|
||||
if lockErr != nil {
|
||||
log.Error(req.OperationID, "UnLockGlobalMessage err:", lockErr.Error())
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
log.Debug(req.OperationID, "redis handle secondly", req.String())
|
||||
|
||||
for k, v := range req.ReactionExtensionList {
|
||||
err := rpc.dMessageLocker.LockMessageTypeKey(req.ClientMsgID, k)
|
||||
if err != nil {
|
||||
setKeyResultInfo(&rResp, 100, err.Error(), req.ClientMsgID, k, v)
|
||||
continue
|
||||
}
|
||||
redisValue, err := db.DB.GetMessageTypeKeyValue(req.ClientMsgID, req.SessionType, k)
|
||||
if err != nil && err != go_redis.Nil {
|
||||
setKeyResultInfo(&rResp, 200, err.Error(), req.ClientMsgID, k, v)
|
||||
continue
|
||||
}
|
||||
temp := new(server_api_params.KeyValue)
|
||||
utils.JsonStringToStruct(redisValue, temp)
|
||||
if v.LatestUpdateTime != temp.LatestUpdateTime {
|
||||
setKeyResultInfo(&rResp, 300, "message have update", req.ClientMsgID, k, temp)
|
||||
continue
|
||||
} else {
|
||||
v.LatestUpdateTime = utils.GetCurrentTimestampByMill()
|
||||
newerr := db.DB.SetMessageTypeKeyValue(req.ClientMsgID, req.SessionType, k, utils.StructToJsonString(v))
|
||||
if newerr != nil {
|
||||
setKeyResultInfo(&rResp, 201, newerr.Error(), req.ClientMsgID, k, temp)
|
||||
continue
|
||||
}
|
||||
setKeyResultInfo(&rResp, 0, "", req.ClientMsgID, k, v)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if !isExists {
|
||||
if !req.IsReact {
|
||||
ExtendMessageUpdatedNotification(req.OperationID, req.OpUserID, req.SourceID, req.SessionType, req, &rResp, true, true)
|
||||
} else {
|
||||
ExtendMessageUpdatedNotification(req.OperationID, req.OpUserID, req.SourceID, req.SessionType, req, &rResp, false, false)
|
||||
}
|
||||
} else {
|
||||
ExtendMessageUpdatedNotification(req.OperationID, req.OpUserID, req.SourceID, req.SessionType, req, &rResp, false, true)
|
||||
}
|
||||
log.Debug(req.OperationID, utils.GetSelfFuncName(), "rpc return is:", rResp.String())
|
||||
return &rResp, nil
|
||||
|
||||
}
|
||||
func setKeyResultInfo(r *msg.SetMessageReactionExtensionsResp, errCode int32, errMsg, clientMsgID, typeKey string, keyValue *server_api_params.KeyValue) {
|
||||
temp := new(msg.KeyValueResp)
|
||||
temp.KeyValue = keyValue
|
||||
temp.ErrCode = errCode
|
||||
temp.ErrMsg = errMsg
|
||||
r.Result = append(r.Result, temp)
|
||||
_ = db.DB.UnLockMessageTypeKey(clientMsgID, typeKey)
|
||||
}
|
||||
func setDeleteKeyResultInfo(r *msg.DeleteMessageListReactionExtensionsResp, errCode int32, errMsg, clientMsgID, typeKey string, keyValue *server_api_params.KeyValue) {
|
||||
temp := new(msg.KeyValueResp)
|
||||
temp.KeyValue = keyValue
|
||||
temp.ErrCode = errCode
|
||||
temp.ErrMsg = errMsg
|
||||
r.Result = append(r.Result, temp)
|
||||
_ = db.DB.UnLockMessageTypeKey(clientMsgID, typeKey)
|
||||
}
|
||||
|
||||
func (rpc *rpcChat) GetMessageListReactionExtensions(ctx context.Context, req *msg.GetMessageListReactionExtensionsReq) (resp *msg.GetMessageListReactionExtensionsResp, err error) {
|
||||
log.Debug(req.OperationID, utils.GetSelfFuncName(), "rpc args is:", req.String())
|
||||
var rResp msg.GetMessageListReactionExtensionsResp
|
||||
if req.IsExternalExtensions {
|
||||
callbackResp := callbackGetMessageListReactionExtensions(req)
|
||||
if callbackResp.ActionCode != constant.ActionAllow || callbackResp.ErrCode != 0 {
|
||||
rResp.ErrCode = int32(callbackResp.ErrCode)
|
||||
rResp.ErrMsg = callbackResp.ErrMsg
|
||||
return &rResp, nil
|
||||
} else {
|
||||
rResp.SingleMessageResult = callbackResp.MessageResultList
|
||||
return &rResp, nil
|
||||
}
|
||||
}
|
||||
for _, messageValue := range req.MessageReactionKeyList {
|
||||
var oneMessage msg.SingleMessageExtensionResult
|
||||
oneMessage.ClientMsgID = messageValue.ClientMsgID
|
||||
|
||||
isExists, err := db.DB.JudgeMessageReactionEXISTS(messageValue.ClientMsgID, req.SessionType)
|
||||
if err != nil {
|
||||
rResp.ErrCode = 100
|
||||
rResp.ErrMsg = err.Error()
|
||||
return &rResp, nil
|
||||
}
|
||||
if isExists {
|
||||
redisValue, err := db.DB.GetOneMessageAllReactionList(messageValue.ClientMsgID, req.SessionType)
|
||||
if err != nil {
|
||||
oneMessage.ErrCode = 100
|
||||
oneMessage.ErrMsg = err.Error()
|
||||
rResp.SingleMessageResult = append(rResp.SingleMessageResult, &oneMessage)
|
||||
continue
|
||||
}
|
||||
keyMap := make(map[string]*server_api_params.KeyValue)
|
||||
|
||||
for k, v := range redisValue {
|
||||
temp := new(server_api_params.KeyValue)
|
||||
utils.JsonStringToStruct(v, temp)
|
||||
keyMap[k] = temp
|
||||
}
|
||||
oneMessage.ReactionExtensionList = keyMap
|
||||
|
||||
} else {
|
||||
mongoValue, err := db.DB.GetExtendMsg(req.SourceID, req.SessionType, messageValue.ClientMsgID, messageValue.MsgFirstModifyTime)
|
||||
if err != nil {
|
||||
oneMessage.ErrCode = 100
|
||||
oneMessage.ErrMsg = err.Error()
|
||||
rResp.SingleMessageResult = append(rResp.SingleMessageResult, &oneMessage)
|
||||
continue
|
||||
}
|
||||
keyMap := make(map[string]*server_api_params.KeyValue)
|
||||
|
||||
for k, v := range mongoValue.ReactionExtensionList {
|
||||
temp := new(server_api_params.KeyValue)
|
||||
temp.TypeKey = v.TypeKey
|
||||
temp.Value = v.Value
|
||||
temp.LatestUpdateTime = v.LatestUpdateTime
|
||||
keyMap[k] = temp
|
||||
}
|
||||
oneMessage.ReactionExtensionList = keyMap
|
||||
}
|
||||
rResp.SingleMessageResult = append(rResp.SingleMessageResult, &oneMessage)
|
||||
}
|
||||
log.Debug(req.OperationID, utils.GetSelfFuncName(), "rpc return is:", rResp.String())
|
||||
return &rResp, nil
|
||||
|
||||
}
|
||||
|
||||
func (rpc *rpcChat) AddMessageReactionExtensions(ctx context.Context, req *msg.ModifyMessageReactionExtensionsReq) (resp *msg.ModifyMessageReactionExtensionsResp, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (rpc *rpcChat) DeleteMessageReactionExtensions(ctx context.Context, req *msg.DeleteMessageListReactionExtensionsReq) (resp *msg.DeleteMessageListReactionExtensionsResp, err error) {
|
||||
log.Debug(req.OperationID, utils.GetSelfFuncName(), "rpc args is:", req.String())
|
||||
var rResp msg.DeleteMessageListReactionExtensionsResp
|
||||
callbackResp := callbackDeleteMessageReactionExtensions(req)
|
||||
if callbackResp.ActionCode != constant.ActionAllow || callbackResp.ErrCode != 0 {
|
||||
rResp.ErrCode = int32(callbackResp.ErrCode)
|
||||
rResp.ErrMsg = callbackResp.ErrMsg
|
||||
for _, value := range req.ReactionExtensionList {
|
||||
temp := new(msg.KeyValueResp)
|
||||
temp.KeyValue = value
|
||||
temp.ErrMsg = callbackResp.ErrMsg
|
||||
temp.ErrCode = 100
|
||||
rResp.Result = append(rResp.Result, temp)
|
||||
}
|
||||
return &rResp, nil
|
||||
}
|
||||
//if ExternalExtension
|
||||
if req.IsExternalExtensions {
|
||||
rResp.Result = callbackResp.ResultReactionExtensionList
|
||||
ExtendMessageDeleteNotification(req.OperationID, req.OpUserID, req.SourceID, req.SessionType, req, &rResp, false, false)
|
||||
return &rResp, nil
|
||||
|
||||
}
|
||||
for _, v := range callbackResp.ResultReactionExtensionList {
|
||||
if v.ErrCode != 0 {
|
||||
func(req *[]*server_api_params.KeyValue, typeKey string) {
|
||||
for i := 0; i < len(*req); i++ {
|
||||
if (*req)[i].TypeKey == typeKey {
|
||||
*req = append((*req)[:i], (*req)[i+1:]...)
|
||||
}
|
||||
}
|
||||
}(&req.ReactionExtensionList, v.KeyValue.TypeKey)
|
||||
rResp.Result = append(rResp.Result, v)
|
||||
}
|
||||
}
|
||||
isExists, err := db.DB.JudgeMessageReactionEXISTS(req.ClientMsgID, req.SessionType)
|
||||
if err != nil {
|
||||
rResp.ErrCode = 100
|
||||
rResp.ErrMsg = err.Error()
|
||||
for _, value := range req.ReactionExtensionList {
|
||||
temp := new(msg.KeyValueResp)
|
||||
temp.KeyValue = value
|
||||
temp.ErrMsg = err.Error()
|
||||
temp.ErrCode = 100
|
||||
rResp.Result = append(rResp.Result, temp)
|
||||
}
|
||||
return &rResp, nil
|
||||
}
|
||||
|
||||
if isExists {
|
||||
log.Debug(req.OperationID, "redis handle this delete", req.String())
|
||||
for _, v := range req.ReactionExtensionList {
|
||||
err := rpc.dMessageLocker.LockMessageTypeKey(req.ClientMsgID, v.TypeKey)
|
||||
if err != nil {
|
||||
setDeleteKeyResultInfo(&rResp, 100, err.Error(), req.ClientMsgID, v.TypeKey, v)
|
||||
continue
|
||||
}
|
||||
|
||||
redisValue, err := db.DB.GetMessageTypeKeyValue(req.ClientMsgID, req.SessionType, v.TypeKey)
|
||||
if err != nil && err != go_redis.Nil {
|
||||
setDeleteKeyResultInfo(&rResp, 200, err.Error(), req.ClientMsgID, v.TypeKey, v)
|
||||
continue
|
||||
}
|
||||
temp := new(server_api_params.KeyValue)
|
||||
utils.JsonStringToStruct(redisValue, temp)
|
||||
if v.LatestUpdateTime != temp.LatestUpdateTime {
|
||||
setDeleteKeyResultInfo(&rResp, 300, "message have update", req.ClientMsgID, v.TypeKey, temp)
|
||||
continue
|
||||
} else {
|
||||
newErr := db.DB.DeleteOneMessageKey(req.ClientMsgID, req.SessionType, v.TypeKey)
|
||||
if newErr != nil {
|
||||
setDeleteKeyResultInfo(&rResp, 201, newErr.Error(), req.ClientMsgID, v.TypeKey, temp)
|
||||
continue
|
||||
}
|
||||
setDeleteKeyResultInfo(&rResp, 0, "", req.ClientMsgID, v.TypeKey, v)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err := rpc.dMessageLocker.LockGlobalMessage(req.ClientMsgID)
|
||||
if err != nil {
|
||||
rResp.ErrCode = 100
|
||||
rResp.ErrMsg = err.Error()
|
||||
for _, value := range req.ReactionExtensionList {
|
||||
temp := new(msg.KeyValueResp)
|
||||
temp.KeyValue = value
|
||||
temp.ErrMsg = err.Error()
|
||||
temp.ErrCode = 100
|
||||
rResp.Result = append(rResp.Result, temp)
|
||||
}
|
||||
return &rResp, nil
|
||||
}
|
||||
mongoValue, err := db.DB.GetExtendMsg(req.SourceID, req.SessionType, req.ClientMsgID, req.MsgFirstModifyTime)
|
||||
if err != nil {
|
||||
rResp.ErrCode = 200
|
||||
rResp.ErrMsg = err.Error()
|
||||
for _, value := range req.ReactionExtensionList {
|
||||
temp := new(msg.KeyValueResp)
|
||||
temp.KeyValue = value
|
||||
temp.ErrMsg = err.Error()
|
||||
temp.ErrCode = 100
|
||||
rResp.Result = append(rResp.Result, temp)
|
||||
}
|
||||
return &rResp, nil
|
||||
}
|
||||
setValue := make(map[string]*server_api_params.KeyValue)
|
||||
for _, v := range req.ReactionExtensionList {
|
||||
|
||||
temp := new(server_api_params.KeyValue)
|
||||
if vv, ok := mongoValue.ReactionExtensionList[v.TypeKey]; ok {
|
||||
utils.CopyStructFields(temp, &vv)
|
||||
if v.LatestUpdateTime != vv.LatestUpdateTime {
|
||||
setDeleteKeyResultInfo(&rResp, 300, "message have update", req.ClientMsgID, v.TypeKey, temp)
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
setDeleteKeyResultInfo(&rResp, 400, "key not in", req.ClientMsgID, v.TypeKey, v)
|
||||
continue
|
||||
}
|
||||
temp.TypeKey = v.TypeKey
|
||||
setValue[v.TypeKey] = temp
|
||||
}
|
||||
err = db.DB.DeleteReactionExtendMsgSet(req.SourceID, req.SessionType, req.ClientMsgID, req.MsgFirstModifyTime, setValue)
|
||||
if err != nil {
|
||||
for _, value := range setValue {
|
||||
temp := new(msg.KeyValueResp)
|
||||
temp.KeyValue = value
|
||||
temp.ErrMsg = err.Error()
|
||||
temp.ErrCode = 100
|
||||
rResp.Result = append(rResp.Result, temp)
|
||||
}
|
||||
} else {
|
||||
for _, value := range setValue {
|
||||
temp := new(msg.KeyValueResp)
|
||||
temp.KeyValue = value
|
||||
rResp.Result = append(rResp.Result, temp)
|
||||
}
|
||||
}
|
||||
lockErr := rpc.dMessageLocker.UnLockGlobalMessage(req.ClientMsgID)
|
||||
if lockErr != nil {
|
||||
log.Error(req.OperationID, "UnLockGlobalMessage err:", lockErr.Error())
|
||||
}
|
||||
|
||||
}
|
||||
ExtendMessageDeleteNotification(req.OperationID, req.OpUserID, req.SourceID, req.SessionType, req, &rResp, false, isExists)
|
||||
log.Debug(req.OperationID, utils.GetSelfFuncName(), "rpc return is:", rResp.String())
|
||||
return &rResp, nil
|
||||
}
|
106
internal/rpc/msg/extend_msg.notification.go
Normal file
106
internal/rpc/msg/extend_msg.notification.go
Normal file
@ -0,0 +1,106 @@
|
||||
package msg
|
||||
|
||||
import (
|
||||
"Open_IM/pkg/base_info"
|
||||
"Open_IM/pkg/common/config"
|
||||
"Open_IM/pkg/common/constant"
|
||||
"Open_IM/pkg/common/log"
|
||||
"Open_IM/pkg/grpc-etcdv3/getcdv3"
|
||||
"Open_IM/pkg/proto/msg"
|
||||
open_im_sdk "Open_IM/pkg/proto/sdk_ws"
|
||||
"Open_IM/pkg/utils"
|
||||
"context"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func ExtendMessageUpdatedNotification(operationID, sendID string, sourceID string, sessionType int32,
|
||||
req *msg.SetMessageReactionExtensionsReq, resp *msg.SetMessageReactionExtensionsResp, isHistory bool, isReactionFromCache bool) {
|
||||
var m base_info.ReactionMessageModifierNotification
|
||||
m.SourceID = req.SourceID
|
||||
m.OpUserID = req.OpUserID
|
||||
m.SessionType = req.SessionType
|
||||
keyMap := make(map[string]*open_im_sdk.KeyValue)
|
||||
for _, valueResp := range resp.Result {
|
||||
if valueResp.ErrCode == 0 {
|
||||
keyMap[valueResp.KeyValue.TypeKey] = valueResp.KeyValue
|
||||
}
|
||||
}
|
||||
if len(keyMap) == 0 {
|
||||
log.NewWarn(operationID, "all key set failed can not send notification", *req)
|
||||
return
|
||||
}
|
||||
m.SuccessReactionExtensionList = keyMap
|
||||
m.ClientMsgID = req.ClientMsgID
|
||||
m.IsReact = resp.IsReact
|
||||
m.IsExternalExtensions = req.IsExternalExtensions
|
||||
m.MsgFirstModifyTime = resp.MsgFirstModifyTime
|
||||
messageReactionSender(operationID, sendID, sourceID, sessionType, constant.ReactionMessageModifier, utils.StructToJsonString(m), isHistory, isReactionFromCache)
|
||||
}
|
||||
func ExtendMessageDeleteNotification(operationID, sendID string, sourceID string, sessionType int32,
|
||||
req *msg.DeleteMessageListReactionExtensionsReq, resp *msg.DeleteMessageListReactionExtensionsResp, isHistory bool, isReactionFromCache bool) {
|
||||
var m base_info.ReactionMessageDeleteNotification
|
||||
m.SourceID = req.SourceID
|
||||
m.OpUserID = req.OpUserID
|
||||
m.SessionType = req.SessionType
|
||||
keyMap := make(map[string]*open_im_sdk.KeyValue)
|
||||
for _, valueResp := range resp.Result {
|
||||
if valueResp.ErrCode == 0 {
|
||||
keyMap[valueResp.KeyValue.TypeKey] = valueResp.KeyValue
|
||||
}
|
||||
}
|
||||
if len(keyMap) == 0 {
|
||||
log.NewWarn(operationID, "all key set failed can not send notification", *req)
|
||||
return
|
||||
}
|
||||
m.SuccessReactionExtensionList = keyMap
|
||||
m.ClientMsgID = req.ClientMsgID
|
||||
m.MsgFirstModifyTime = req.MsgFirstModifyTime
|
||||
|
||||
messageReactionSender(operationID, sendID, sourceID, sessionType, constant.ReactionMessageDeleter, utils.StructToJsonString(m), isHistory, isReactionFromCache)
|
||||
}
|
||||
func messageReactionSender(operationID, sendID string, sourceID string, sessionType, contentType int32, content string, isHistory bool, isReactionFromCache bool) {
|
||||
options := make(map[string]bool, 5)
|
||||
utils.SetSwitchFromOptions(options, constant.IsOfflinePush, false)
|
||||
utils.SetSwitchFromOptions(options, constant.IsConversationUpdate, false)
|
||||
utils.SetSwitchFromOptions(options, constant.IsSenderConversationUpdate, false)
|
||||
utils.SetSwitchFromOptions(options, constant.IsUnreadCount, false)
|
||||
utils.SetSwitchFromOptions(options, constant.IsReactionFromCache, isReactionFromCache)
|
||||
if !isHistory {
|
||||
utils.SetSwitchFromOptions(options, constant.IsHistory, false)
|
||||
utils.SetSwitchFromOptions(options, constant.IsPersistent, false)
|
||||
}
|
||||
pbData := msg.SendMsgReq{
|
||||
OperationID: operationID,
|
||||
MsgData: &open_im_sdk.MsgData{
|
||||
SendID: sendID,
|
||||
ClientMsgID: utils.GetMsgID(sendID),
|
||||
SessionType: sessionType,
|
||||
MsgFrom: constant.SysMsgType,
|
||||
ContentType: contentType,
|
||||
Content: []byte(content),
|
||||
// ForceList: params.ForceList,
|
||||
CreateTime: utils.GetCurrentTimestampByMill(),
|
||||
Options: options,
|
||||
},
|
||||
}
|
||||
switch sessionType {
|
||||
case constant.SingleChatType, constant.NotificationChatType:
|
||||
pbData.MsgData.RecvID = sourceID
|
||||
case constant.GroupChatType, constant.SuperGroupChatType:
|
||||
pbData.MsgData.GroupID = sourceID
|
||||
}
|
||||
etcdConn := getcdv3.GetDefaultConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImMsgName, operationID)
|
||||
if etcdConn == nil {
|
||||
errMsg := operationID + "getcdv3.GetDefaultConn == nil"
|
||||
log.NewError(operationID, errMsg)
|
||||
return
|
||||
}
|
||||
client := msg.NewMsgClient(etcdConn)
|
||||
reply, err := client.SendMsg(context.Background(), &pbData)
|
||||
if err != nil {
|
||||
log.NewError(operationID, "SendMsg rpc failed, ", pbData.String(), err.Error())
|
||||
} else if reply.ErrCode != 0 {
|
||||
log.NewError(operationID, "SendMsg rpc failed, ", pbData.String(), reply.ErrCode, reply.ErrMsg)
|
||||
}
|
||||
|
||||
}
|
79
internal/rpc/msg/extend_msg_callback.go
Normal file
79
internal/rpc/msg/extend_msg_callback.go
Normal file
@ -0,0 +1,79 @@
|
||||
package msg
|
||||
|
||||
import (
|
||||
cbApi "Open_IM/pkg/call_back_struct"
|
||||
"Open_IM/pkg/common/config"
|
||||
"Open_IM/pkg/common/constant"
|
||||
"Open_IM/pkg/common/http"
|
||||
"Open_IM/pkg/common/log"
|
||||
"Open_IM/pkg/proto/msg"
|
||||
"Open_IM/pkg/utils"
|
||||
http2 "net/http"
|
||||
)
|
||||
|
||||
func callbackSetMessageReactionExtensions(setReq *msg.SetMessageReactionExtensionsReq) *cbApi.CallbackBeforeSetMessageReactionExtResp {
|
||||
callbackResp := cbApi.CommonCallbackResp{OperationID: setReq.OperationID}
|
||||
log.NewDebug(setReq.OperationID, utils.GetSelfFuncName(), setReq.String())
|
||||
req := cbApi.CallbackBeforeSetMessageReactionExtReq{
|
||||
OperationID: setReq.OperationID,
|
||||
CallbackCommand: constant.CallbackBeforeSetMessageReactionExtensionCommand,
|
||||
SourceID: setReq.SourceID,
|
||||
OpUserID: setReq.OpUserID,
|
||||
SessionType: setReq.SessionType,
|
||||
ReactionExtensionList: setReq.ReactionExtensionList,
|
||||
ClientMsgID: setReq.ClientMsgID,
|
||||
IsReact: setReq.IsReact,
|
||||
IsExternalExtensions: setReq.IsExternalExtensions,
|
||||
MsgFirstModifyTime: setReq.MsgFirstModifyTime,
|
||||
}
|
||||
resp := &cbApi.CallbackBeforeSetMessageReactionExtResp{CommonCallbackResp: &callbackResp}
|
||||
defer log.NewDebug(setReq.OperationID, utils.GetSelfFuncName(), req, *resp)
|
||||
if err := http.CallBackPostReturn(config.Config.Callback.CallbackUrl, constant.CallbackBeforeSetMessageReactionExtensionCommand, req, resp, config.Config.Callback.CallbackAfterSendGroupMsg.CallbackTimeOut); err != nil {
|
||||
callbackResp.ErrCode = http2.StatusInternalServerError
|
||||
callbackResp.ErrMsg = err.Error()
|
||||
}
|
||||
return resp
|
||||
|
||||
}
|
||||
|
||||
func callbackDeleteMessageReactionExtensions(setReq *msg.DeleteMessageListReactionExtensionsReq) *cbApi.CallbackDeleteMessageReactionExtResp {
|
||||
callbackResp := cbApi.CommonCallbackResp{OperationID: setReq.OperationID}
|
||||
log.NewDebug(setReq.OperationID, utils.GetSelfFuncName(), setReq.String())
|
||||
req := cbApi.CallbackDeleteMessageReactionExtReq{
|
||||
OperationID: setReq.OperationID,
|
||||
CallbackCommand: constant.CallbackBeforeDeleteMessageReactionExtensionsCommand,
|
||||
SourceID: setReq.SourceID,
|
||||
OpUserID: setReq.OpUserID,
|
||||
SessionType: setReq.SessionType,
|
||||
ReactionExtensionList: setReq.ReactionExtensionList,
|
||||
ClientMsgID: setReq.ClientMsgID,
|
||||
IsExternalExtensions: setReq.IsExternalExtensions,
|
||||
MsgFirstModifyTime: setReq.MsgFirstModifyTime,
|
||||
}
|
||||
resp := &cbApi.CallbackDeleteMessageReactionExtResp{CommonCallbackResp: &callbackResp}
|
||||
defer log.NewDebug(setReq.OperationID, utils.GetSelfFuncName(), req, *resp)
|
||||
if err := http.CallBackPostReturn(config.Config.Callback.CallbackUrl, constant.CallbackBeforeDeleteMessageReactionExtensionsCommand, req, resp, config.Config.Callback.CallbackAfterSendGroupMsg.CallbackTimeOut); err != nil {
|
||||
callbackResp.ErrCode = http2.StatusInternalServerError
|
||||
callbackResp.ErrMsg = err.Error()
|
||||
}
|
||||
return resp
|
||||
}
|
||||
func callbackGetMessageListReactionExtensions(setReq *msg.GetMessageListReactionExtensionsReq) *cbApi.CallbackGetMessageListReactionExtResp {
|
||||
callbackResp := cbApi.CommonCallbackResp{OperationID: setReq.OperationID}
|
||||
log.NewDebug(setReq.OperationID, utils.GetSelfFuncName(), setReq.String())
|
||||
req := cbApi.CallbackGetMessageListReactionExtReq{
|
||||
OperationID: setReq.OperationID,
|
||||
CallbackCommand: constant.CallbackGetMessageListReactionExtensionsCommand,
|
||||
SourceID: setReq.SourceID,
|
||||
OpUserID: setReq.OpUserID,
|
||||
SessionType: setReq.SessionType,
|
||||
MessageKeyList: setReq.MessageReactionKeyList,
|
||||
}
|
||||
resp := &cbApi.CallbackGetMessageListReactionExtResp{CommonCallbackResp: &callbackResp}
|
||||
defer log.NewDebug(setReq.OperationID, utils.GetSelfFuncName(), req, *resp)
|
||||
if err := http.CallBackPostReturn(config.Config.Callback.CallbackUrl, constant.CallbackGetMessageListReactionExtensionsCommand, req, resp, config.Config.Callback.CallbackAfterSendGroupMsg.CallbackTimeOut); err != nil {
|
||||
callbackResp.ErrCode = http2.StatusInternalServerError
|
||||
callbackResp.ErrMsg = err.Error()
|
||||
}
|
||||
return resp
|
||||
}
|
@ -68,6 +68,8 @@ func friendNotification(commID *pbFriend.CommID, contentType int32, m proto.Mess
|
||||
tips.DefaultTips = cn.BlackDeleted.DefaultTips.Tips + toUserNickname
|
||||
case constant.UserInfoUpdatedNotification:
|
||||
tips.DefaultTips = cn.UserInfoUpdated.DefaultTips.Tips
|
||||
case constant.FriendInfoUpdatedNotification:
|
||||
tips.DefaultTips = cn.FriendInfoUpdated.DefaultTips.Tips + toUserNickname
|
||||
default:
|
||||
log.Error(commID.OperationID, "contentType failed ", contentType)
|
||||
return
|
||||
@ -158,8 +160,15 @@ func BlackDeletedNotification(req *pbFriend.RemoveBlacklistReq) {
|
||||
friendNotification(req.CommID, constant.BlackDeletedNotification, &blackDeletedTips)
|
||||
}
|
||||
|
||||
func UserInfoUpdatedNotification(operationID, userID string, needNotifiedUserID string) {
|
||||
selfInfoUpdatedTips := open_im_sdk.UserInfoUpdatedTips{UserID: userID}
|
||||
commID := pbFriend.CommID{FromUserID: userID, ToUserID: needNotifiedUserID, OpUserID: userID, OperationID: operationID}
|
||||
//send to myself
|
||||
func UserInfoUpdatedNotification(operationID, opUserID string, changedUserID string) {
|
||||
selfInfoUpdatedTips := open_im_sdk.UserInfoUpdatedTips{UserID: changedUserID}
|
||||
commID := pbFriend.CommID{FromUserID: opUserID, ToUserID: changedUserID, OpUserID: opUserID, OperationID: operationID}
|
||||
friendNotification(&commID, constant.UserInfoUpdatedNotification, &selfInfoUpdatedTips)
|
||||
}
|
||||
|
||||
func FriendInfoUpdatedNotification(operationID, changedUserID string, needNotifiedUserID string, opUserID string) {
|
||||
selfInfoUpdatedTips := open_im_sdk.UserInfoUpdatedTips{UserID: changedUserID}
|
||||
commID := pbFriend.CommID{FromUserID: opUserID, ToUserID: needNotifiedUserID, OpUserID: opUserID, OperationID: operationID}
|
||||
friendNotification(&commID, constant.FriendInfoUpdatedNotification, &selfInfoUpdatedTips)
|
||||
}
|
||||
|
@ -416,8 +416,6 @@ func MemberQuitNotification(req *pbGroup.QuitGroupReq) {
|
||||
}
|
||||
|
||||
groupNotification(constant.MemberQuitNotification, &MemberQuitTips, req.OpUserID, req.GroupID, "", req.OperationID)
|
||||
// groupNotification(constant.MemberQuitNotification, &MemberQuitTips, req.OpUserID, "", req.OpUserID, req.OperationID)
|
||||
|
||||
}
|
||||
|
||||
//message ApplicationProcessedTips{
|
||||
@ -437,7 +435,20 @@ func GroupApplicationAcceptedNotification(req *pbGroup.GroupApplicationResponseR
|
||||
log.Error(req.OperationID, "setOpUserInfo failed", req.OpUserID, req.GroupID, GroupApplicationAcceptedTips.OpUser)
|
||||
return
|
||||
}
|
||||
|
||||
groupNotification(constant.GroupApplicationAcceptedNotification, &GroupApplicationAcceptedTips, req.OpUserID, "", req.FromUserID, req.OperationID)
|
||||
adminList, err := imdb.GetOwnerManagerByGroupID(req.GroupID)
|
||||
if err != nil {
|
||||
log.Error(req.OperationID, "GetOwnerManagerByGroupID failed", req.GroupID)
|
||||
return
|
||||
}
|
||||
for _, v := range adminList {
|
||||
if v.UserID == req.OpUserID {
|
||||
continue
|
||||
}
|
||||
GroupApplicationAcceptedTips.ReceiverAs = 1
|
||||
groupNotification(constant.GroupApplicationAcceptedNotification, &GroupApplicationAcceptedTips, req.OpUserID, "", v.UserID, req.OperationID)
|
||||
}
|
||||
}
|
||||
|
||||
func GroupApplicationRejectedNotification(req *pbGroup.GroupApplicationResponseReq) {
|
||||
@ -451,6 +462,18 @@ func GroupApplicationRejectedNotification(req *pbGroup.GroupApplicationResponseR
|
||||
return
|
||||
}
|
||||
groupNotification(constant.GroupApplicationRejectedNotification, &GroupApplicationRejectedTips, req.OpUserID, "", req.FromUserID, req.OperationID)
|
||||
adminList, err := imdb.GetOwnerManagerByGroupID(req.GroupID)
|
||||
if err != nil {
|
||||
log.Error(req.OperationID, "GetOwnerManagerByGroupID failed", req.GroupID)
|
||||
return
|
||||
}
|
||||
for _, v := range adminList {
|
||||
if v.UserID == req.OpUserID {
|
||||
continue
|
||||
}
|
||||
GroupApplicationRejectedTips.ReceiverAs = 1
|
||||
groupNotification(constant.GroupApplicationRejectedNotification, &GroupApplicationRejectedTips, req.OpUserID, "", v.UserID, req.OperationID)
|
||||
}
|
||||
}
|
||||
|
||||
func GroupOwnerTransferredNotification(req *pbGroup.TransferGroupOwnerReq) {
|
||||
|
52
internal/rpc/msg/lock.go
Normal file
52
internal/rpc/msg/lock.go
Normal file
@ -0,0 +1,52 @@
|
||||
package msg
|
||||
|
||||
import (
|
||||
"Open_IM/pkg/common/db"
|
||||
"time"
|
||||
)
|
||||
|
||||
const GlOBLLOCK = "GLOBAL_LOCK"
|
||||
|
||||
type MessageLocker interface {
|
||||
LockMessageTypeKey(clientMsgID, typeKey string) (err error)
|
||||
UnLockMessageTypeKey(clientMsgID string, typeKey string) error
|
||||
LockGlobalMessage(clientMsgID string) (err error)
|
||||
UnLockGlobalMessage(clientMsgID string) (err error)
|
||||
}
|
||||
type LockerMessage struct{}
|
||||
|
||||
func NewLockerMessage() *LockerMessage {
|
||||
return &LockerMessage{}
|
||||
}
|
||||
func (l *LockerMessage) LockMessageTypeKey(clientMsgID, typeKey string) (err error) {
|
||||
for i := 0; i < 3; i++ {
|
||||
err = db.DB.LockMessageTypeKey(clientMsgID, typeKey)
|
||||
if err != nil {
|
||||
time.Sleep(time.Millisecond * 100)
|
||||
continue
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
return err
|
||||
|
||||
}
|
||||
func (l *LockerMessage) LockGlobalMessage(clientMsgID string) (err error) {
|
||||
for i := 0; i < 3; i++ {
|
||||
err = db.DB.LockMessageTypeKey(clientMsgID, GlOBLLOCK)
|
||||
if err != nil {
|
||||
time.Sleep(time.Millisecond * 100)
|
||||
continue
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
return err
|
||||
|
||||
}
|
||||
func (l *LockerMessage) UnLockMessageTypeKey(clientMsgID string, typeKey string) error {
|
||||
return db.DB.UnLockMessageTypeKey(clientMsgID, typeKey)
|
||||
}
|
||||
func (l *LockerMessage) UnLockGlobalMessage(clientMsgID string) error {
|
||||
return db.DB.UnLockMessageTypeKey(clientMsgID, GlOBLLOCK)
|
||||
}
|
@ -10,11 +10,12 @@ import (
|
||||
"Open_IM/pkg/grpc-etcdv3/getcdv3"
|
||||
"Open_IM/pkg/proto/msg"
|
||||
"Open_IM/pkg/utils"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
|
||||
grpcPrometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
@ -30,7 +31,8 @@ type rpcChat struct {
|
||||
etcdAddr []string
|
||||
messageWriter MessageWriter
|
||||
//offlineProducer *kafka.Producer
|
||||
delMsgCh chan deleteMsg
|
||||
delMsgCh chan deleteMsg
|
||||
dMessageLocker MessageLocker
|
||||
}
|
||||
|
||||
type deleteMsg struct {
|
||||
@ -47,6 +49,7 @@ func NewRpcChatServer(port int) *rpcChat {
|
||||
rpcRegisterName: config.Config.RpcRegisterName.OpenImMsgName,
|
||||
etcdSchema: config.Config.Etcd.EtcdSchema,
|
||||
etcdAddr: config.Config.Etcd.EtcdAddr,
|
||||
dMessageLocker: NewLockerMessage(),
|
||||
}
|
||||
rc.messageWriter = kafka.NewKafkaProducer(config.Config.Kafka.Ws2mschat.Addr, config.Config.Kafka.Ws2mschat.Topic)
|
||||
//rc.offlineProducer = kafka.NewKafkaProducer(config.Config.Kafka.Ws2mschatOffline.Addr, config.Config.Kafka.Ws2mschatOffline.Topic)
|
||||
@ -94,8 +97,12 @@ func (rpc *rpcChat) Run() {
|
||||
panic("listening err:" + err.Error() + rpc.rpcRegisterName)
|
||||
}
|
||||
log.Info("", "listen network success, address ", address)
|
||||
|
||||
var grpcOpts []grpc.ServerOption
|
||||
recvSize := 1024 * 1024 * 30
|
||||
sendSize := 1024 * 1024 * 30
|
||||
var grpcOpts = []grpc.ServerOption{
|
||||
grpc.MaxRecvMsgSize(recvSize),
|
||||
grpc.MaxSendMsgSize(sendSize),
|
||||
}
|
||||
if config.Config.Prometheus.Enable {
|
||||
promePkg.NewGrpcRequestCounter()
|
||||
promePkg.NewGrpcRequestFailedCounter()
|
||||
|
@ -25,6 +25,7 @@ import (
|
||||
"time"
|
||||
|
||||
promePkg "Open_IM/pkg/common/prometheus"
|
||||
|
||||
go_redis "github.com/go-redis/redis/v8"
|
||||
"github.com/golang/protobuf/proto"
|
||||
)
|
||||
@ -96,12 +97,24 @@ func isMessageHasReadEnabled(pb *pbChat.SendMsgReq) (bool, int32, string) {
|
||||
return true, 0, ""
|
||||
}
|
||||
|
||||
func userIsMuteInGroup(groupID, userID string) (bool, error) {
|
||||
func userIsMuteAndIsAdminInGroup(groupID, userID string) (isMute bool, isAdmin bool, err error) {
|
||||
groupMemberInfo, err := rocksCache.GetGroupMemberInfoFromCache(groupID, userID)
|
||||
if err != nil {
|
||||
return false, utils.Wrap(err, "")
|
||||
return false, false, utils.Wrap(err, "")
|
||||
}
|
||||
|
||||
if groupMemberInfo.MuteEndTime.Unix() >= time.Now().Unix() {
|
||||
return true, groupMemberInfo.RoleLevel > constant.GroupOrdinaryUsers, nil
|
||||
}
|
||||
return false, groupMemberInfo.RoleLevel > constant.GroupOrdinaryUsers, nil
|
||||
}
|
||||
|
||||
func groupIsMuted(groupID string) (bool, error) {
|
||||
groupInfo, err := rocksCache.GetGroupInfoFromCache(groupID)
|
||||
if err != nil {
|
||||
return false, utils.Wrap(err, "GetGroupInfoFromCache failed")
|
||||
}
|
||||
if groupInfo.Status == constant.GroupStatusMuted {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
@ -113,7 +126,7 @@ func (rpc *rpcChat) messageVerification(data *pbChat.SendMsgReq) (bool, int32, s
|
||||
if utils.IsContain(data.MsgData.SendID, config.Config.Manager.AppManagerUid) {
|
||||
return true, 0, "", nil
|
||||
}
|
||||
if data.MsgData.ContentType <= constant.NotificationEnd && data.MsgData.ContentType >= constant.NotificationBegin {
|
||||
if data.MsgData.ContentType <= constant.NotificationEnd && data.MsgData.ContentType >= constant.NotificationBegin && data.MsgData.ContentType != constant.SignalingNotification {
|
||||
return true, 0, "", nil
|
||||
}
|
||||
log.NewDebug(data.OperationID, *config.Config.MessageVerify.FriendVerify)
|
||||
@ -171,16 +184,18 @@ func (rpc *rpcChat) messageVerification(data *pbChat.SendMsgReq) (bool, int32, s
|
||||
log.NewError(data.OperationID, errMsg)
|
||||
return false, 201, errMsg, nil
|
||||
}
|
||||
if !token_verify.IsManagerUserID(data.MsgData.SendID) {
|
||||
if data.MsgData.ContentType <= constant.NotificationEnd && data.MsgData.ContentType >= constant.NotificationBegin {
|
||||
return true, 0, "", userIDList
|
||||
}
|
||||
if token_verify.IsManagerUserID(data.MsgData.SendID) {
|
||||
return true, 0, "", userIDList
|
||||
}
|
||||
if data.MsgData.ContentType <= constant.NotificationEnd && data.MsgData.ContentType >= constant.NotificationBegin {
|
||||
return true, 0, "", userIDList
|
||||
} else {
|
||||
if !utils.IsContain(data.MsgData.SendID, userIDList) {
|
||||
//return returnMsg(&replay, pb, 202, "you are not in group", "", 0)
|
||||
return false, 202, "you are not in group", nil
|
||||
}
|
||||
}
|
||||
isMute, err := userIsMuteInGroup(data.MsgData.GroupID, data.MsgData.SendID)
|
||||
isMute, isAdmin, err := userIsMuteAndIsAdminInGroup(data.MsgData.GroupID, data.MsgData.SendID)
|
||||
if err != nil {
|
||||
errMsg := data.OperationID + err.Error()
|
||||
return false, 223, errMsg, nil
|
||||
@ -188,6 +203,17 @@ func (rpc *rpcChat) messageVerification(data *pbChat.SendMsgReq) (bool, int32, s
|
||||
if isMute {
|
||||
return false, 224, "you are muted", nil
|
||||
}
|
||||
if isAdmin {
|
||||
return true, 0, "", userIDList
|
||||
}
|
||||
isMute, err = groupIsMuted(data.MsgData.GroupID)
|
||||
if err != nil {
|
||||
errMsg := data.OperationID + err.Error()
|
||||
return false, 223, errMsg, nil
|
||||
}
|
||||
if isMute {
|
||||
return false, 225, "group id muted", nil
|
||||
}
|
||||
return true, 0, "", userIDList
|
||||
case constant.SuperGroupChatType:
|
||||
groupInfo, err := rocksCache.GetGroupInfoFromCache(data.MsgData.GroupID)
|
||||
@ -232,16 +258,18 @@ func (rpc *rpcChat) messageVerification(data *pbChat.SendMsgReq) (bool, int32, s
|
||||
log.NewError(data.OperationID, errMsg)
|
||||
return false, 201, errMsg, nil
|
||||
}
|
||||
if !token_verify.IsManagerUserID(data.MsgData.SendID) {
|
||||
if data.MsgData.ContentType <= constant.NotificationEnd && data.MsgData.ContentType >= constant.NotificationBegin {
|
||||
return true, 0, "", userIDList
|
||||
}
|
||||
if token_verify.IsManagerUserID(data.MsgData.SendID) {
|
||||
return true, 0, "", userIDList
|
||||
}
|
||||
if data.MsgData.ContentType <= constant.NotificationEnd && data.MsgData.ContentType >= constant.NotificationBegin {
|
||||
return true, 0, "", userIDList
|
||||
} else {
|
||||
if !utils.IsContain(data.MsgData.SendID, userIDList) {
|
||||
//return returnMsg(&replay, pb, 202, "you are not in group", "", 0)
|
||||
return false, 202, "you are not in group", nil
|
||||
}
|
||||
}
|
||||
isMute, err := userIsMuteInGroup(data.MsgData.GroupID, data.MsgData.SendID)
|
||||
isMute, isAdmin, err := userIsMuteAndIsAdminInGroup(data.MsgData.GroupID, data.MsgData.SendID)
|
||||
if err != nil {
|
||||
errMsg := data.OperationID + err.Error()
|
||||
return false, 223, errMsg, nil
|
||||
@ -249,6 +277,17 @@ func (rpc *rpcChat) messageVerification(data *pbChat.SendMsgReq) (bool, int32, s
|
||||
if isMute {
|
||||
return false, 224, "you are muted", nil
|
||||
}
|
||||
if isAdmin {
|
||||
return true, 0, "", userIDList
|
||||
}
|
||||
isMute, err = groupIsMuted(data.MsgData.GroupID)
|
||||
if err != nil {
|
||||
errMsg := data.OperationID + err.Error()
|
||||
return false, 223, errMsg, nil
|
||||
}
|
||||
if isMute {
|
||||
return false, 225, "group id muted", nil
|
||||
}
|
||||
return true, 0, "", userIDList
|
||||
}
|
||||
default:
|
||||
@ -962,6 +1001,13 @@ func Notification(n *NotificationMsg) {
|
||||
ex = config.Config.Notification.ConversationSetPrivate.OfflinePush.Ext
|
||||
reliabilityLevel = config.Config.Notification.ConversationSetPrivate.Conversation.ReliabilityLevel
|
||||
unReadCount = config.Config.Notification.ConversationSetPrivate.Conversation.UnreadCount
|
||||
case constant.FriendInfoUpdatedNotification:
|
||||
pushSwitch = config.Config.Notification.FriendInfoUpdated.OfflinePush.PushSwitch
|
||||
title = config.Config.Notification.FriendInfoUpdated.OfflinePush.Title
|
||||
desc = config.Config.Notification.FriendInfoUpdated.OfflinePush.Desc
|
||||
ex = config.Config.Notification.FriendInfoUpdated.OfflinePush.Ext
|
||||
reliabilityLevel = config.Config.Notification.FriendInfoUpdated.Conversation.ReliabilityLevel
|
||||
unReadCount = config.Config.Notification.FriendInfoUpdated.Conversation.UnreadCount
|
||||
case constant.DeleteMessageNotification:
|
||||
reliabilityLevel = constant.ReliableNotificationNoMsg
|
||||
case constant.ConversationUnreadNotification, constant.SuperGroupUpdateNotification:
|
||||
|
@ -10,15 +10,6 @@ import (
|
||||
)
|
||||
|
||||
func SuperGroupNotification(operationID, sendID, recvID string) {
|
||||
|
||||
//var tips sdk.TipsComm
|
||||
//var err error
|
||||
//marshaler := jsonpb.Marshaler{
|
||||
// OrigName: true,
|
||||
// EnumsAsInts: false,
|
||||
// EmitDefaults: false,
|
||||
//}
|
||||
//tips.JsonDetail, _ = marshaler.MarshalToString(m)
|
||||
n := &NotificationMsg{
|
||||
SendID: sendID,
|
||||
RecvID: recvID,
|
||||
@ -27,11 +18,6 @@ func SuperGroupNotification(operationID, sendID, recvID string) {
|
||||
SessionType: constant.SingleChatType,
|
||||
OperationID: operationID,
|
||||
}
|
||||
//n.Content, err = proto.Marshal(&tips)
|
||||
//if err != nil {
|
||||
// log.NewError(operationID, utils.GetSelfFuncName(), "proto.Marshal failed")
|
||||
// return
|
||||
//}
|
||||
log.NewInfo(operationID, utils.GetSelfFuncName(), string(n.Content))
|
||||
Notification(n)
|
||||
}
|
||||
|
@ -444,13 +444,15 @@ func (s *userServer) UpdateUserInfo(ctx context.Context, req *pbUser.UpdateUserI
|
||||
}
|
||||
for _, v := range rpcResp.FriendInfoList {
|
||||
log.Info(req.OperationID, "UserInfoUpdatedNotification ", req.UserInfo.UserID, v.FriendUser.UserID)
|
||||
chat.UserInfoUpdatedNotification(req.OperationID, req.UserInfo.UserID, v.FriendUser.UserID)
|
||||
// chat.UserInfoUpdatedNotification(req.OperationID, req.UserInfo.UserID, v.FriendUser.UserID)
|
||||
chat.FriendInfoUpdatedNotification(req.OperationID, req.UserInfo.UserID, v.FriendUser.UserID, req.OpUserID)
|
||||
}
|
||||
if err := rocksCache.DelUserInfoFromCache(user.UserID); err != nil {
|
||||
log.NewError(req.OperationID, "GetFriendList failed ", err.Error(), newReq)
|
||||
return &pbUser.UpdateUserInfoResp{CommonResp: &pbUser.CommonResp{ErrCode: constant.ErrDB.ErrCode, ErrMsg: err.Error()}}, nil
|
||||
}
|
||||
chat.UserInfoUpdatedNotification(req.OperationID, req.UserInfo.UserID, req.OpUserID)
|
||||
//chat.UserInfoUpdatedNotification(req.OperationID, req.OpUserID, req.UserInfo.UserID)
|
||||
chat.UserInfoUpdatedNotification(req.OperationID, req.OpUserID, req.UserInfo.UserID)
|
||||
log.Info(req.OperationID, "UserInfoUpdatedNotification ", req.UserInfo.UserID, req.OpUserID)
|
||||
if req.UserInfo.FaceURL != "" {
|
||||
s.SyncJoinedGroupMemberFaceURL(req.UserInfo.UserID, req.UserInfo.FaceURL, req.OperationID, req.OpUserID)
|
||||
|
@ -1,5 +1,10 @@
|
||||
package base_info
|
||||
|
||||
import (
|
||||
"Open_IM/pkg/proto/msg"
|
||||
sdk_ws "Open_IM/pkg/proto/sdk_ws"
|
||||
)
|
||||
|
||||
type DelMsgReq struct {
|
||||
UserID string `json:"userID,omitempty" binding:"required"`
|
||||
SeqList []uint32 `json:"seqList,omitempty" binding:"required"`
|
||||
@ -18,6 +23,7 @@ type CleanUpMsgReq struct {
|
||||
type CleanUpMsgResp struct {
|
||||
CommResp
|
||||
}
|
||||
|
||||
type DelSuperGroupMsgReq struct {
|
||||
UserID string `json:"userID" binding:"required"`
|
||||
GroupID string `json:"groupID" binding:"required"`
|
||||
@ -29,23 +35,108 @@ type DelSuperGroupMsgReq struct {
|
||||
type DelSuperGroupMsgResp struct {
|
||||
CommResp
|
||||
}
|
||||
|
||||
type MsgDeleteNotificationElem struct {
|
||||
GroupID string `json:"groupID"`
|
||||
IsAllDelete bool `json:"isAllDelete"`
|
||||
SeqList []uint32 `json:"seqList"`
|
||||
}
|
||||
|
||||
//UserID string `protobuf:"bytes,1,opt,name=userID" json:"userID,omitempty"`
|
||||
// GroupID string `protobuf:"bytes,2,opt,name=groupID" json:"groupID,omitempty"`
|
||||
// MinSeq uint32 `protobuf:"varint,3,opt,name=minSeq" json:"minSeq,omitempty"`
|
||||
// OperationID string `protobuf:"bytes,4,opt,name=operationID" json:"operationID,omitempty"`
|
||||
// OpUserID string `protobuf:"bytes,5,opt,name=opUserID" json:"opUserID,omitempty"`
|
||||
type SetMsgMinSeqReq struct {
|
||||
UserID string `json:"userID" binding:"required"`
|
||||
GroupID string `json:"groupID"`
|
||||
MinSeq uint32 `json:"minSeq" binding:"required"`
|
||||
OperationID string `json:"operationID" binding:"required"`
|
||||
}
|
||||
|
||||
type SetMsgMinSeqResp struct {
|
||||
CommResp
|
||||
}
|
||||
|
||||
type ModifyMessageReactionExtensionsReq struct {
|
||||
OperationID string `json:"operationID" binding:"required"`
|
||||
SourceID string `json:"sourceID" binding:"required"`
|
||||
SessionType int32 `json:"sessionType" binding:"required"`
|
||||
ReactionExtensionList map[string]*sdk_ws.KeyValue `json:"reactionExtensionList,omitempty" binding:"required"`
|
||||
ClientMsgID string `json:"clientMsgID" binding:"required"`
|
||||
Ex *string `json:"ex"`
|
||||
AttachedInfo *string `json:"attachedInfo"`
|
||||
IsReact bool `json:"isReact"`
|
||||
IsExternalExtensions bool `json:"isExternalExtensions"`
|
||||
MsgFirstModifyTime int64 `json:"msgFirstModifyTime"`
|
||||
}
|
||||
|
||||
type ModifyMessageReactionExtensionsResp struct {
|
||||
CommResp
|
||||
Data struct {
|
||||
ResultKeyValue []*msg.KeyValueResp `json:"result"`
|
||||
MsgFirstModifyTime int64 `json:"msgFirstModifyTime"`
|
||||
IsReact bool `json:"isReact"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
type OperateMessageListReactionExtensionsReq struct {
|
||||
OperationID string `json:"operationID" binding:"required"`
|
||||
SourceID string `json:"sourceID" binding:"required"`
|
||||
SessionType string `json:"sessionType" binding:"required"`
|
||||
IsExternalExtensions bool `json:"isExternalExtensions"`
|
||||
MessageReactionKeyList []*msg.GetMessageListReactionExtensionsReq_MessageReactionKey `json:"messageReactionKeyList" binding:"required"`
|
||||
}
|
||||
|
||||
type OperateMessageListReactionExtensionsResp struct {
|
||||
CommResp
|
||||
Data struct {
|
||||
SuccessList []*msg.ExtendMsgResp `json:"successList"`
|
||||
FailedList []*msg.ExtendMsgResp `json:"failedList"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
type SetMessageReactionExtensionsCallbackReq ModifyMessageReactionExtensionsReq
|
||||
|
||||
type SetMessageReactionExtensionsCallbackResp ModifyMessageReactionExtensionsResp
|
||||
|
||||
type GetMessageListReactionExtensionsReq OperateMessageListReactionExtensionsReq
|
||||
|
||||
type GetMessageListReactionExtensionsResp struct {
|
||||
CommResp
|
||||
Data []*msg.SingleMessageExtensionResult `json:"data"`
|
||||
}
|
||||
|
||||
type AddMessageReactionExtensionsReq ModifyMessageReactionExtensionsReq
|
||||
|
||||
type AddMessageReactionExtensionsResp ModifyMessageReactionExtensionsResp
|
||||
|
||||
type DeleteMessageReactionExtensionsReq struct {
|
||||
OperationID string `json:"operationID" binding:"required"`
|
||||
SourceID string `json:"sourceID" binding:"required"`
|
||||
SessionType int32 `json:"sessionType" binding:"required"`
|
||||
ClientMsgID string `json:"clientMsgID" binding:"required"`
|
||||
IsExternalExtensions bool `json:"isExternalExtensions"`
|
||||
MsgFirstModifyTime int64 `json:"msgFirstModifyTime" binding:"required"`
|
||||
ReactionExtensionList []*sdk_ws.KeyValue `json:"reactionExtensionList" binding:"required"`
|
||||
}
|
||||
|
||||
type DeleteMessageReactionExtensionsResp struct {
|
||||
CommResp
|
||||
Data []*msg.KeyValueResp
|
||||
}
|
||||
|
||||
type ReactionMessageModifierNotification struct {
|
||||
SourceID string `json:"sourceID" binding:"required"`
|
||||
OpUserID string `json:"opUserID" binding:"required"`
|
||||
SessionType int32 `json:"sessionType" binding:"required"`
|
||||
SuccessReactionExtensionList map[string]*sdk_ws.KeyValue `json:"reactionExtensionList,omitempty" binding:"required"`
|
||||
ClientMsgID string `json:"clientMsgID" binding:"required"`
|
||||
IsReact bool `json:"isReact"`
|
||||
IsExternalExtensions bool `json:"isExternalExtensions"`
|
||||
MsgFirstModifyTime int64 `json:"msgFirstModifyTime"`
|
||||
}
|
||||
|
||||
type ReactionMessageDeleteNotification struct {
|
||||
SourceID string `json:"sourceID" binding:"required"`
|
||||
OpUserID string `json:"opUserID" binding:"required"`
|
||||
SessionType int32 `json:"sessionType" binding:"required"`
|
||||
SuccessReactionExtensionList map[string]*sdk_ws.KeyValue `json:"reactionExtensionList,omitempty" binding:"required"`
|
||||
ClientMsgID string `json:"clientMsgID" binding:"required"`
|
||||
MsgFirstModifyTime int64 `json:"msgFirstModifyTime"`
|
||||
}
|
||||
|
@ -1,12 +1,15 @@
|
||||
package call_back_struct
|
||||
|
||||
import (
|
||||
"Open_IM/pkg/proto/group"
|
||||
commonPb "Open_IM/pkg/proto/sdk_ws"
|
||||
)
|
||||
|
||||
type CallbackBeforeCreateGroupReq struct {
|
||||
CallbackCommand string `json:"callbackCommand"`
|
||||
OperationID string `json:"operationID"`
|
||||
commonPb.GroupInfo
|
||||
InitMemberList []*group.GroupAddMemberInfo `json:"initMemberList"`
|
||||
}
|
||||
|
||||
type CallbackBeforeCreateGroupResp struct {
|
||||
@ -25,3 +28,40 @@ type CallbackBeforeCreateGroupResp struct {
|
||||
LookMemberInfo *int32 `json:"lookMemberInfo"`
|
||||
ApplyMemberFriend *int32 `json:"applyMemberFriend"`
|
||||
}
|
||||
|
||||
type CallbackBeforeMemberJoinGroupReq struct {
|
||||
CallbackCommand string `json:"callbackCommand"`
|
||||
OperationID string `json:"operationID"`
|
||||
GroupID string `json:"groupID"`
|
||||
UserID string `json:"userID"`
|
||||
Ex string `json:"ex"`
|
||||
GroupEx string `json:"groupEx"`
|
||||
}
|
||||
|
||||
type CallbackBeforeMemberJoinGroupResp struct {
|
||||
*CommonCallbackResp
|
||||
NickName *string `json:"nickName"`
|
||||
FaceURL *string `json:"faceURL"`
|
||||
RoleLevel *int32 `json:"roleLevel"`
|
||||
MuteEndTime *int64 `json:"muteEndTime"`
|
||||
Ex *string `json:"ex"`
|
||||
}
|
||||
|
||||
type CallbackBeforeSetGroupMemberInfoReq struct {
|
||||
CallbackCommand string `json:"callbackCommand"`
|
||||
OperationID string `json:"operationID"`
|
||||
GroupID string `json:"groupID"`
|
||||
UserID string `json:"userID"`
|
||||
Nickname string `json:"nickName"`
|
||||
FaceURL string `json:"faceURL"`
|
||||
RoleLevel int32 `json:"roleLevel"`
|
||||
Ex string `json:"ex"`
|
||||
}
|
||||
|
||||
type CallbackBeforeSetGroupMemberInfoResp struct {
|
||||
*CommonCallbackResp
|
||||
Ex *string `json:"ex"`
|
||||
Nickname *string `json:"nickName"`
|
||||
FaceURL *string `json:"faceURL"`
|
||||
RoleLevel *int32 `json:"roleLevel"`
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
package call_back_struct
|
||||
|
||||
import sdk_ws "Open_IM/pkg/proto/sdk_ws"
|
||||
import (
|
||||
"Open_IM/pkg/proto/msg"
|
||||
sdk_ws "Open_IM/pkg/proto/sdk_ws"
|
||||
)
|
||||
|
||||
type CallbackBeforeSendSingleMsgReq struct {
|
||||
CommonCallbackReq
|
||||
@ -63,3 +66,48 @@ type CallbackMsgModifyCommandResp struct {
|
||||
AttachedInfo *string `json:"attachedInfo"`
|
||||
Ex *string `json:"ex"`
|
||||
}
|
||||
type CallbackBeforeSetMessageReactionExtReq struct {
|
||||
OperationID string `json:"operationID"`
|
||||
CallbackCommand string `json:"callbackCommand"`
|
||||
SourceID string `json:"sourceID"`
|
||||
OpUserID string `json:"opUserID"`
|
||||
SessionType int32 `json:"sessionType"`
|
||||
ReactionExtensionList map[string]*sdk_ws.KeyValue `json:"reactionExtensionList"`
|
||||
ClientMsgID string `json:"clientMsgID"`
|
||||
IsReact bool `json:"isReact"`
|
||||
IsExternalExtensions bool `json:"isExternalExtensions"`
|
||||
MsgFirstModifyTime int64 `json:"msgFirstModifyTime"`
|
||||
}
|
||||
type CallbackBeforeSetMessageReactionExtResp struct {
|
||||
*CommonCallbackResp
|
||||
ResultReactionExtensionList []*msg.KeyValueResp `json:"resultReactionExtensionList"`
|
||||
MsgFirstModifyTime int64 `json:"msgFirstModifyTime"`
|
||||
}
|
||||
type CallbackDeleteMessageReactionExtReq struct {
|
||||
OperationID string `json:"operationID"`
|
||||
CallbackCommand string `json:"callbackCommand"`
|
||||
SourceID string `json:"sourceID"`
|
||||
OpUserID string `json:"opUserID"`
|
||||
SessionType int32 `json:"sessionType"`
|
||||
ReactionExtensionList []*sdk_ws.KeyValue `json:"reactionExtensionList"`
|
||||
ClientMsgID string `json:"clientMsgID"`
|
||||
IsExternalExtensions bool `json:"isExternalExtensions"`
|
||||
MsgFirstModifyTime int64 `json:"msgFirstModifyTime"`
|
||||
}
|
||||
type CallbackDeleteMessageReactionExtResp struct {
|
||||
*CommonCallbackResp
|
||||
ResultReactionExtensionList []*msg.KeyValueResp `json:"resultReactionExtensionList"`
|
||||
MsgFirstModifyTime int64 `json:"msgFirstModifyTime"`
|
||||
}
|
||||
type CallbackGetMessageListReactionExtReq struct {
|
||||
OperationID string `json:"operationID"`
|
||||
CallbackCommand string `json:"callbackCommand"`
|
||||
SourceID string `json:"sourceID"`
|
||||
OpUserID string `json:"opUserID"`
|
||||
SessionType int32 `json:"sessionType"`
|
||||
MessageKeyList []*msg.GetMessageListReactionExtensionsReq_MessageReactionKey `json:"messageKeyList"`
|
||||
}
|
||||
type CallbackGetMessageListReactionExtResp struct {
|
||||
*CommonCallbackResp
|
||||
MessageResultList []*msg.SingleMessageExtensionResult `json:"messageResultList"`
|
||||
}
|
||||
|
@ -2,8 +2,10 @@ package call_back_struct
|
||||
|
||||
type CallbackUserOnlineReq struct {
|
||||
UserStatusCallbackReq
|
||||
Token string `json:"token"`
|
||||
Seq int `json:"seq"`
|
||||
Token string `json:"token"`
|
||||
Seq int `json:"seq"`
|
||||
IsAppBackground bool `json:"isAppBackground"`
|
||||
ConnID string `json:"connID"`
|
||||
}
|
||||
|
||||
type CallbackUserOnlineResp struct {
|
||||
@ -12,7 +14,8 @@ type CallbackUserOnlineResp struct {
|
||||
|
||||
type CallbackUserOfflineReq struct {
|
||||
UserStatusCallbackReq
|
||||
Seq int `json:"seq"`
|
||||
Seq int `json:"seq"`
|
||||
ConnID string `json:"connID"`
|
||||
}
|
||||
|
||||
type CallbackUserOfflineResp struct {
|
||||
|
@ -21,7 +21,7 @@ type CallbackBeforePushResp struct {
|
||||
}
|
||||
|
||||
type CallbackBeforeSuperGroupOnlinePushReq struct {
|
||||
*commonPb.OfflinePushInfo
|
||||
//*commonPb.OfflinePushInfo
|
||||
UserStatusBaseCallback
|
||||
ClientMsgID string `json:"clientMsgID"`
|
||||
SendID string `json:"sendID"`
|
||||
@ -30,6 +30,7 @@ type CallbackBeforeSuperGroupOnlinePushReq struct {
|
||||
SessionType int32 `json:"sessionType"`
|
||||
AtUserIDList []string `json:"atUserIDList"`
|
||||
Content string `json:"content"`
|
||||
Seq uint32 `json:"seq"`
|
||||
}
|
||||
|
||||
type CallbackBeforeSuperGroupOnlinePushResp struct {
|
||||
|
@ -17,6 +17,17 @@ type AdminLoginResponse struct {
|
||||
FaceURL string `json:"faceURL"`
|
||||
}
|
||||
|
||||
type GetUserTokenRequest struct {
|
||||
UserID string `json:"userID" binding:"required"`
|
||||
OperationID string `json:"operationID" binding:"required"`
|
||||
PlatFormID int32 `json:"platformID" binding:"required"`
|
||||
}
|
||||
|
||||
type GetUserTokenResponse struct {
|
||||
Token string `json:"token"`
|
||||
ExpTime int64 `json:"expTime"`
|
||||
}
|
||||
|
||||
type AddUserRegisterAddFriendIDListRequest struct {
|
||||
OperationID string `json:"operationID" binding:"required"`
|
||||
UserIDList []string `json:"userIDList" binding:"required"`
|
||||
|
@ -248,11 +248,16 @@ type config struct {
|
||||
Addr []string `yaml:"addr"`
|
||||
Topic string `yaml:"topic"`
|
||||
}
|
||||
MsgToModify struct {
|
||||
Addr []string `yaml:"addr"`
|
||||
Topic string `yaml:"topic"`
|
||||
}
|
||||
ConsumerGroupID struct {
|
||||
MsgToRedis string `yaml:"msgToTransfer"`
|
||||
MsgToMongo string `yaml:"msgToMongo"`
|
||||
MsgToMySql string `yaml:"msgToMySql"`
|
||||
MsgToPush string `yaml:"msgToPush"`
|
||||
MsgToRedis string `yaml:"msgToTransfer"`
|
||||
MsgToMongo string `yaml:"msgToMongo"`
|
||||
MsgToMySql string `yaml:"msgToMySql"`
|
||||
MsgToPush string `yaml:"msgToPush"`
|
||||
MsgToModify string `yaml:"msgToModify"`
|
||||
}
|
||||
}
|
||||
Secret string `yaml:"secret"`
|
||||
@ -291,6 +296,8 @@ type config struct {
|
||||
CallbackBeforeSuperGroupOnlinePush callBackConfig `yaml:"callbackSuperGroupOnlinePush"`
|
||||
CallbackBeforeAddFriend callBackConfig `yaml:"callbackBeforeAddFriend"`
|
||||
CallbackBeforeCreateGroup callBackConfig `yaml:"callbackBeforeCreateGroup"`
|
||||
CallbackBeforeMemberJoinGroup callBackConfig `yaml:"callbackBeforeMemberJoinGroup"`
|
||||
CallbackBeforeSetGroupMemberInfo callBackConfig `yaml:"callbackBeforeSetGroupMemberInfo"`
|
||||
} `yaml:"callback"`
|
||||
Notification struct {
|
||||
///////////////////////group/////////////////////////////
|
||||
@ -455,6 +462,12 @@ type config struct {
|
||||
OfflinePush POfflinePush `yaml:"offlinePush"`
|
||||
DefaultTips PDefaultTips `yaml:"defaultTips"`
|
||||
} `yaml:"blackDeleted"`
|
||||
FriendInfoUpdated struct {
|
||||
Conversation PConversation `yaml:"conversation"`
|
||||
OfflinePush POfflinePush `yaml:"offlinePush"`
|
||||
DefaultTips PDefaultTips `yaml:"defaultTips"`
|
||||
} `yaml:"friendInfoUpdated"`
|
||||
|
||||
ConversationOptUpdate struct {
|
||||
Conversation PConversation `yaml:"conversation"`
|
||||
OfflinePush POfflinePush `yaml:"offlinePush"`
|
||||
@ -640,7 +653,7 @@ func unmarshalConfig(config interface{}, configName string) {
|
||||
} else {
|
||||
bytes, err := ioutil.ReadFile(fmt.Sprintf("../config/%s", configName))
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
panic(err.Error() + configName)
|
||||
}
|
||||
if err = yaml.Unmarshal(bytes, config); err != nil {
|
||||
panic(err.Error())
|
||||
|
@ -17,14 +17,15 @@ const (
|
||||
RefuseFriendFlag = -1
|
||||
|
||||
//Websocket Protocol
|
||||
WSGetNewestSeq = 1001
|
||||
WSPullMsgBySeqList = 1002
|
||||
WSSendMsg = 1003
|
||||
WSSendSignalMsg = 1004
|
||||
WSPushMsg = 2001
|
||||
WSKickOnlineMsg = 2002
|
||||
WsLogoutMsg = 2003
|
||||
WSDataError = 3001
|
||||
WSGetNewestSeq = 1001
|
||||
WSPullMsgBySeqList = 1002
|
||||
WSSendMsg = 1003
|
||||
WSSendSignalMsg = 1004
|
||||
WSPushMsg = 2001
|
||||
WSKickOnlineMsg = 2002
|
||||
WsLogoutMsg = 2003
|
||||
WsSetBackgroundStatus = 2004
|
||||
WSDataError = 3001
|
||||
|
||||
///ContentType
|
||||
//UserRelated
|
||||
@ -47,6 +48,8 @@ const (
|
||||
AdvancedRevoke = 118 //影响前者消息
|
||||
CustomNotTriggerConversation = 119
|
||||
CustomOnlineOnly = 120
|
||||
ReactionMessageModifier = 121
|
||||
ReactionMessageDeleter = 122
|
||||
|
||||
Common = 200
|
||||
GroupMsg = 201
|
||||
@ -64,11 +67,12 @@ const (
|
||||
FriendRemarkSetNotification = 1206 //set_friend_remark?
|
||||
BlackAddedNotification = 1207 //add_black
|
||||
BlackDeletedNotification = 1208 //remove_black
|
||||
FriendInfoUpdatedNotification = 1209
|
||||
|
||||
ConversationOptChangeNotification = 1300 // change conversation opt
|
||||
|
||||
UserNotificationBegin = 1301
|
||||
UserInfoUpdatedNotification = 1303 //SetSelfInfoTip = 204
|
||||
UserInfoUpdatedNotification = 1303 //SetSelfInfoTip = 204
|
||||
UserNotificationEnd = 1399
|
||||
OANotification = 1400
|
||||
|
||||
@ -110,6 +114,10 @@ const (
|
||||
WorkMomentNotificationBegin = 1900
|
||||
WorkMomentNotification = 1901
|
||||
|
||||
BusinessNotificationBegin = 2000
|
||||
BusinessNotification = 2001
|
||||
BusinessNotificationEnd = 2099
|
||||
|
||||
NotificationEnd = 3000
|
||||
|
||||
//status
|
||||
@ -163,6 +171,7 @@ const (
|
||||
IsNotPrivate = "notPrivate"
|
||||
IsSenderConversationUpdate = "senderConversationUpdate"
|
||||
IsSenderNotificationPush = "senderNotificationPush"
|
||||
IsReactionFromCache = "reactionFromCache"
|
||||
|
||||
//GroupStatus
|
||||
GroupOk = 0
|
||||
@ -196,19 +205,24 @@ const (
|
||||
VerificationCodeForResetSuffix = "_forReset"
|
||||
|
||||
//callbackCommand
|
||||
CallbackBeforeSendSingleMsgCommand = "callbackBeforeSendSingleMsgCommand"
|
||||
CallbackAfterSendSingleMsgCommand = "callbackAfterSendSingleMsgCommand"
|
||||
CallbackBeforeSendGroupMsgCommand = "callbackBeforeSendGroupMsgCommand"
|
||||
CallbackAfterSendGroupMsgCommand = "callbackAfterSendGroupMsgCommand"
|
||||
CallbackMsgModifyCommand = "callbackMsgModifyCommand"
|
||||
CallbackUserOnlineCommand = "callbackUserOnlineCommand"
|
||||
CallbackUserOfflineCommand = "callbackUserOfflineCommand"
|
||||
CallbackUserKickOffCommand = "callbackUserKickOffCommand"
|
||||
CallbackOfflinePushCommand = "callbackOfflinePushCommand"
|
||||
CallbackOnlinePushCommand = "callbackOnlinePushCommand"
|
||||
CallbackSuperGroupOnlinePushCommand = "callbackSuperGroupOnlinePushCommand"
|
||||
CallbackBeforeAddFriendCommand = "callbackBeforeAddFriendCommand"
|
||||
CallbackBeforeCreateGroupCommand = "callbackBeforeCreateGroup"
|
||||
CallbackBeforeSendSingleMsgCommand = "callbackBeforeSendSingleMsgCommand"
|
||||
CallbackAfterSendSingleMsgCommand = "callbackAfterSendSingleMsgCommand"
|
||||
CallbackBeforeSendGroupMsgCommand = "callbackBeforeSendGroupMsgCommand"
|
||||
CallbackAfterSendGroupMsgCommand = "callbackAfterSendGroupMsgCommand"
|
||||
CallbackMsgModifyCommand = "callbackMsgModifyCommand"
|
||||
CallbackUserOnlineCommand = "callbackUserOnlineCommand"
|
||||
CallbackUserOfflineCommand = "callbackUserOfflineCommand"
|
||||
CallbackUserKickOffCommand = "callbackUserKickOffCommand"
|
||||
CallbackOfflinePushCommand = "callbackOfflinePushCommand"
|
||||
CallbackOnlinePushCommand = "callbackOnlinePushCommand"
|
||||
CallbackSuperGroupOnlinePushCommand = "callbackSuperGroupOnlinePushCommand"
|
||||
CallbackBeforeAddFriendCommand = "callbackBeforeAddFriendCommand"
|
||||
CallbackBeforeCreateGroupCommand = "callbackBeforeCreateGroupCommand"
|
||||
CallbackBeforeMemberJoinGroupCommand = "callbackBeforeMemberJoinGroupCommand"
|
||||
CallbackBeforeSetGroupMemberInfoCommand = "CallbackBeforeSetGroupMemberInfoCommand"
|
||||
CallbackBeforeSetMessageReactionExtensionCommand = "callbackBeforeSetMessageReactionExtensionCommand"
|
||||
CallbackBeforeDeleteMessageReactionExtensionsCommand = "callbackBeforeDeleteMessageReactionExtensionsCommand"
|
||||
CallbackGetMessageListReactionExtensionsCommand = "callbackGetMessageListReactionExtensionsCommand"
|
||||
|
||||
//callback actionCode
|
||||
ActionAllow = 0
|
||||
@ -339,6 +353,6 @@ const LogFileName = "OpenIM.log"
|
||||
|
||||
const StatisticsTimeInterval = 60
|
||||
|
||||
const MaxNotificationNum = 100
|
||||
const MaxNotificationNum = 500
|
||||
|
||||
const CurrentVersion = "v2.3.4-rc0"
|
||||
|
@ -33,6 +33,7 @@ var (
|
||||
ErrSendLimit = ErrInfo{ErrCode: 810, ErrMsg: "send msg limit, to many request, try again later"}
|
||||
ErrMessageHasReadDisable = ErrInfo{ErrCode: 811, ErrMsg: "message has read disable"}
|
||||
ErrInternal = ErrInfo{ErrCode: 812, ErrMsg: "internal error"}
|
||||
ErrWsConnNotExist = ErrInfo{ErrCode: 813, ErrMsg: "ws conn not exist"}
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -14,6 +14,7 @@ const (
|
||||
LinuxPlatformID = 7
|
||||
AndroidPadPlatformID = 8
|
||||
IPadPlatformID = 9
|
||||
AdminPlatformID = 10
|
||||
|
||||
//Platform string match to Platform ID
|
||||
IOSPlatformStr = "IOS"
|
||||
@ -25,6 +26,7 @@ const (
|
||||
LinuxPlatformStr = "Linux"
|
||||
AndroidPadPlatformStr = "APad"
|
||||
IPadPlatformStr = "IPad"
|
||||
AdminPlatformStr = "Admin"
|
||||
|
||||
//terminal types
|
||||
TerminalPC = "PC"
|
||||
@ -41,6 +43,7 @@ var PlatformID2Name = map[int]string{
|
||||
LinuxPlatformID: LinuxPlatformStr,
|
||||
AndroidPadPlatformID: AndroidPadPlatformStr,
|
||||
IPadPlatformID: IPadPlatformStr,
|
||||
AdminPlatformID: AdminPlatformStr,
|
||||
}
|
||||
var PlatformName2ID = map[string]int{
|
||||
IOSPlatformStr: IOSPlatformID,
|
||||
@ -52,8 +55,9 @@ var PlatformName2ID = map[string]int{
|
||||
LinuxPlatformStr: LinuxPlatformID,
|
||||
AndroidPadPlatformStr: AndroidPadPlatformID,
|
||||
IPadPlatformStr: IPadPlatformID,
|
||||
AdminPlatformStr: AdminPlatformID,
|
||||
}
|
||||
var Platform2class = map[string]string{
|
||||
var PlatformName2class = map[string]string{
|
||||
IOSPlatformStr: TerminalMobile,
|
||||
AndroidPlatformStr: TerminalMobile,
|
||||
MiniWebPlatformStr: WebPlatformStr,
|
||||
@ -62,6 +66,15 @@ var Platform2class = map[string]string{
|
||||
OSXPlatformStr: TerminalPC,
|
||||
LinuxPlatformStr: TerminalPC,
|
||||
}
|
||||
var PlatformID2class = map[int]string{
|
||||
IOSPlatformID: TerminalMobile,
|
||||
AndroidPlatformID: TerminalMobile,
|
||||
MiniWebPlatformID: WebPlatformStr,
|
||||
WebPlatformID: WebPlatformStr,
|
||||
WindowsPlatformID: TerminalPC,
|
||||
OSXPlatformID: TerminalPC,
|
||||
LinuxPlatformID: TerminalPC,
|
||||
}
|
||||
|
||||
func PlatformIDToName(num int) string {
|
||||
return PlatformID2Name[num]
|
||||
@ -70,5 +83,8 @@ func PlatformNameToID(name string) int {
|
||||
return PlatformName2ID[name]
|
||||
}
|
||||
func PlatformNameToClass(name string) string {
|
||||
return Platform2class[name]
|
||||
return PlatformName2class[name]
|
||||
}
|
||||
func PlatformIDToClass(num int) string {
|
||||
return PlatformID2class[num]
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ const (
|
||||
uidPidToken = "UID_PID_TOKEN_STATUS:"
|
||||
conversationReceiveMessageOpt = "CON_RECV_MSG_OPT:"
|
||||
getuiToken = "GETUI_TOKEN"
|
||||
getuiTaskID = "GETUI_TASK_ID"
|
||||
messageCache = "MESSAGE_CACHE:"
|
||||
SignalCache = "SIGNAL_CACHE:"
|
||||
SignalListCache = "SIGNAL_LIST_CACHE:"
|
||||
@ -38,6 +39,7 @@ const (
|
||||
groupMinSeq = "GROUP_MIN_SEQ:"
|
||||
sendMsgFailedFlag = "SEND_MSG_FAILED_FLAG:"
|
||||
userBadgeUnreadCountSum = "USER_BADGE_UNREAD_COUNT_SUM:"
|
||||
exTypeKeyLocker = "EX_LOCK:"
|
||||
)
|
||||
|
||||
func (d *DataBases) JudgeAccountEXISTS(account string) (bool, error) {
|
||||
@ -397,6 +399,15 @@ func (d *DataBases) GetGetuiToken() (string, error) {
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (d *DataBases) SetGetuiTaskID(taskID string, expireTime int64) error {
|
||||
return d.RDB.Set(context.Background(), getuiTaskID, taskID, time.Duration(expireTime)*time.Second).Err()
|
||||
}
|
||||
|
||||
func (d *DataBases) GetGetuiTaskID() (string, error) {
|
||||
result, err := d.RDB.Get(context.Background(), getuiTaskID).Result()
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (d *DataBases) SetSendMsgStatus(status int32, operationID string) error {
|
||||
return d.RDB.Set(context.Background(), sendMsgFailedFlag+operationID, status, time.Hour*24).Err()
|
||||
}
|
||||
@ -437,3 +448,61 @@ func (d *DataBases) GetUserBadgeUnreadCountSum(uid string) (int, error) {
|
||||
seq, err := d.RDB.Get(context.Background(), key).Result()
|
||||
return utils.StringToInt(seq), err
|
||||
}
|
||||
func (d *DataBases) JudgeMessageReactionEXISTS(clientMsgID string, sessionType int32) (bool, error) {
|
||||
key := getMessageReactionExPrefix(clientMsgID, sessionType)
|
||||
n, err := d.RDB.Exists(context.Background(), key).Result()
|
||||
if n > 0 {
|
||||
return true, err
|
||||
} else {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
|
||||
func (d *DataBases) GetOneMessageAllReactionList(clientMsgID string, sessionType int32) (map[string]string, error) {
|
||||
key := getMessageReactionExPrefix(clientMsgID, sessionType)
|
||||
return d.RDB.HGetAll(context.Background(), key).Result()
|
||||
|
||||
}
|
||||
func (d *DataBases) DeleteOneMessageKey(clientMsgID string, sessionType int32, subKey string) error {
|
||||
key := getMessageReactionExPrefix(clientMsgID, sessionType)
|
||||
return d.RDB.HDel(context.Background(), key, subKey).Err()
|
||||
|
||||
}
|
||||
func (d *DataBases) SetMessageReactionExpire(clientMsgID string, sessionType int32, expiration time.Duration) (bool, error) {
|
||||
key := getMessageReactionExPrefix(clientMsgID, sessionType)
|
||||
return d.RDB.Expire(context.Background(), key, expiration).Result()
|
||||
}
|
||||
func (d *DataBases) GetMessageTypeKeyValue(clientMsgID string, sessionType int32, typeKey string) (string, error) {
|
||||
key := getMessageReactionExPrefix(clientMsgID, sessionType)
|
||||
result, err := d.RDB.HGet(context.Background(), key, typeKey).Result()
|
||||
return result, err
|
||||
|
||||
}
|
||||
func (d *DataBases) SetMessageTypeKeyValue(clientMsgID string, sessionType int32, typeKey, value string) error {
|
||||
key := getMessageReactionExPrefix(clientMsgID, sessionType)
|
||||
return d.RDB.HSet(context.Background(), key, typeKey, value).Err()
|
||||
|
||||
}
|
||||
func (d *DataBases) LockMessageTypeKey(clientMsgID string, TypeKey string) error {
|
||||
key := exTypeKeyLocker + clientMsgID + "_" + TypeKey
|
||||
return d.RDB.SetNX(context.Background(), key, 1, time.Minute).Err()
|
||||
}
|
||||
func (d *DataBases) UnLockMessageTypeKey(clientMsgID string, TypeKey string) error {
|
||||
key := exTypeKeyLocker + clientMsgID + "_" + TypeKey
|
||||
return d.RDB.Del(context.Background(), key).Err()
|
||||
|
||||
}
|
||||
|
||||
func getMessageReactionExPrefix(clientMsgID string, sessionType int32) string {
|
||||
switch sessionType {
|
||||
case constant.SingleChatType:
|
||||
return "EX_SINGLE_" + clientMsgID
|
||||
case constant.GroupChatType:
|
||||
return "EX_GROUP_" + clientMsgID
|
||||
case constant.SuperGroupChatType:
|
||||
return "EX_SUPER_GROUP_" + clientMsgID
|
||||
case constant.NotificationChatType:
|
||||
return "EX_NOTIFICATION" + clientMsgID
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
205
pkg/common/db/extend_msg_mongo_model.go
Normal file
205
pkg/common/db/extend_msg_mongo_model.go
Normal file
@ -0,0 +1,205 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"Open_IM/pkg/common/config"
|
||||
server_api_params "Open_IM/pkg/proto/sdk_ws"
|
||||
"Open_IM/pkg/utils"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
)
|
||||
|
||||
const cExtendMsgSet = "extend_msgs"
|
||||
const MaxNum = 100
|
||||
|
||||
type ExtendMsgSet struct {
|
||||
SourceID string `bson:"source_id" json:"sourceID"`
|
||||
SessionType int32 `bson:"session_type" json:"sessionType"`
|
||||
ExtendMsgs map[string]ExtendMsg `bson:"extend_msgs" json:"extendMsgs"`
|
||||
ExtendMsgNum int32 `bson:"extend_msg_num" json:"extendMsgNum"`
|
||||
CreateTime int64 `bson:"create_time" json:"createTime"` // this block's create time
|
||||
MaxMsgUpdateTime int64 `bson:"max_msg_update_time" json:"maxMsgUpdateTime"` // index find msg
|
||||
}
|
||||
|
||||
type KeyValue struct {
|
||||
TypeKey string `bson:"type_key" json:"typeKey"`
|
||||
Value string `bson:"value" json:"value"`
|
||||
LatestUpdateTime int64 `bson:"latest_update_time" json:"latestUpdateTime"`
|
||||
}
|
||||
|
||||
type ExtendMsg struct {
|
||||
ReactionExtensionList map[string]KeyValue `bson:"reaction_extension_list" json:"reactionExtensionList"`
|
||||
ClientMsgID string `bson:"client_msg_id" json:"clientMsgID"`
|
||||
MsgFirstModifyTime int64 `bson:"msg_first_modify_time" json:"msgFirstModifyTime"` // this extendMsg create time
|
||||
AttachedInfo string `bson:"attached_info" json:"attachedInfo"`
|
||||
Ex string `bson:"ex" json:"ex"`
|
||||
}
|
||||
|
||||
func GetExtendMsgMaxNum() int32 {
|
||||
return MaxNum
|
||||
}
|
||||
|
||||
func GetExtendMsgSourceID(ID string, index int32) string {
|
||||
return ID + ":" + strconv.Itoa(int(index))
|
||||
}
|
||||
|
||||
func SplitSourceIDAndGetIndex(sourceID string) int32 {
|
||||
l := strings.Split(sourceID, ":")
|
||||
index, _ := strconv.Atoi(l[len(l)-1])
|
||||
return int32(index)
|
||||
}
|
||||
|
||||
func (d *DataBases) CreateExtendMsgSet(set *ExtendMsgSet) error {
|
||||
ctx, _ := context.WithTimeout(context.Background(), time.Duration(config.Config.Mongo.DBTimeout)*time.Second)
|
||||
c := d.mongoClient.Database(config.Config.Mongo.DBDatabase).Collection(cExtendMsgSet)
|
||||
_, err := c.InsertOne(ctx, set)
|
||||
return err
|
||||
}
|
||||
|
||||
type GetAllExtendMsgSetOpts struct {
|
||||
ExcludeExtendMsgs bool
|
||||
}
|
||||
|
||||
func (d *DataBases) GetAllExtendMsgSet(ID string, opts *GetAllExtendMsgSetOpts) (sets []*ExtendMsgSet, err error) {
|
||||
ctx, _ := context.WithTimeout(context.Background(), time.Duration(config.Config.Mongo.DBTimeout)*time.Second)
|
||||
c := d.mongoClient.Database(config.Config.Mongo.DBDatabase).Collection(cExtendMsgSet)
|
||||
regex := fmt.Sprintf("^%s", ID)
|
||||
var findOpts *options.FindOptions
|
||||
if opts != nil {
|
||||
if opts.ExcludeExtendMsgs {
|
||||
findOpts = &options.FindOptions{}
|
||||
findOpts.SetProjection(bson.M{"extend_msgs": 0})
|
||||
}
|
||||
}
|
||||
cursor, err := c.Find(ctx, bson.M{"uid": primitive.Regex{Pattern: regex}}, findOpts)
|
||||
if err != nil {
|
||||
return nil, utils.Wrap(err, "")
|
||||
}
|
||||
err = cursor.All(context.Background(), &sets)
|
||||
if err != nil {
|
||||
return nil, utils.Wrap(err, fmt.Sprintf("cursor is %s", cursor.Current.String()))
|
||||
}
|
||||
return sets, nil
|
||||
}
|
||||
|
||||
func (d *DataBases) GetExtendMsgSet(ctx context.Context, sourceID string, sessionType int32, maxMsgUpdateTime int64, c *mongo.Collection) (*ExtendMsgSet, error) {
|
||||
regex := fmt.Sprintf("^%s", sourceID)
|
||||
var err error
|
||||
findOpts := options.Find().SetLimit(1).SetSkip(0).SetSort(bson.M{"source_id": -1}).SetProjection(bson.M{"extend_msgs": 0})
|
||||
// update newest
|
||||
find := bson.M{"source_id": primitive.Regex{Pattern: regex}, "session_type": sessionType}
|
||||
if maxMsgUpdateTime > 0 {
|
||||
find["max_msg_update_time"] = maxMsgUpdateTime
|
||||
}
|
||||
result, err := c.Find(ctx, find, findOpts)
|
||||
if err != nil {
|
||||
return nil, utils.Wrap(err, "")
|
||||
}
|
||||
var setList []ExtendMsgSet
|
||||
if err := result.All(ctx, &setList); err != nil {
|
||||
return nil, utils.Wrap(err, "")
|
||||
}
|
||||
if len(setList) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
return &setList[0], nil
|
||||
}
|
||||
|
||||
// first modify msg
|
||||
func (d *DataBases) InsertExtendMsg(sourceID string, sessionType int32, msg *ExtendMsg) error {
|
||||
ctx, _ := context.WithTimeout(context.Background(), time.Duration(config.Config.Mongo.DBTimeout)*time.Second)
|
||||
c := d.mongoClient.Database(config.Config.Mongo.DBDatabase).Collection(cExtendMsgSet)
|
||||
set, err := d.GetExtendMsgSet(ctx, sourceID, sessionType, 0, c)
|
||||
if err != nil {
|
||||
return utils.Wrap(err, "")
|
||||
}
|
||||
if set == nil || set.ExtendMsgNum >= GetExtendMsgMaxNum() {
|
||||
var index int32
|
||||
if set != nil {
|
||||
index = SplitSourceIDAndGetIndex(set.SourceID)
|
||||
}
|
||||
err = d.CreateExtendMsgSet(&ExtendMsgSet{
|
||||
SourceID: GetExtendMsgSourceID(sourceID, index),
|
||||
SessionType: sessionType,
|
||||
ExtendMsgs: map[string]ExtendMsg{msg.ClientMsgID: *msg},
|
||||
ExtendMsgNum: 1,
|
||||
CreateTime: msg.MsgFirstModifyTime,
|
||||
MaxMsgUpdateTime: msg.MsgFirstModifyTime,
|
||||
})
|
||||
} else {
|
||||
_, err = c.UpdateOne(ctx, bson.M{"source_id": set.SourceID, "session_type": sessionType}, bson.M{"$set": bson.M{"max_msg_update_time": msg.MsgFirstModifyTime, "$inc": bson.M{"extend_msg_num": 1}, fmt.Sprintf("extend_msgs.%s", msg.ClientMsgID): msg}})
|
||||
}
|
||||
return utils.Wrap(err, "")
|
||||
}
|
||||
|
||||
// insert or update
|
||||
func (d *DataBases) InsertOrUpdateReactionExtendMsgSet(sourceID string, sessionType int32, clientMsgID string, msgFirstModifyTime int64, reactionExtensionList map[string]*server_api_params.KeyValue) error {
|
||||
ctx, _ := context.WithTimeout(context.Background(), time.Duration(config.Config.Mongo.DBTimeout)*time.Second)
|
||||
c := d.mongoClient.Database(config.Config.Mongo.DBDatabase).Collection(cExtendMsgSet)
|
||||
var updateBson = bson.M{}
|
||||
for _, v := range reactionExtensionList {
|
||||
updateBson[fmt.Sprintf("extend_msgs.%s.%s", clientMsgID, v.TypeKey)] = v
|
||||
}
|
||||
upsert := true
|
||||
opt := &options.UpdateOptions{
|
||||
Upsert: &upsert,
|
||||
}
|
||||
set, err := d.GetExtendMsgSet(ctx, sourceID, sessionType, msgFirstModifyTime, c)
|
||||
if err != nil {
|
||||
return utils.Wrap(err, "")
|
||||
}
|
||||
if set == nil {
|
||||
return errors.New(fmt.Sprintf("sourceID %s has no set", sourceID))
|
||||
}
|
||||
_, err = c.UpdateOne(ctx, bson.M{"source_id": set.SourceID, "session_type": sessionType}, bson.M{"$set": updateBson}, opt)
|
||||
return utils.Wrap(err, "")
|
||||
}
|
||||
|
||||
// delete TypeKey
|
||||
func (d *DataBases) DeleteReactionExtendMsgSet(sourceID string, sessionType int32, clientMsgID string, msgFirstModifyTime int64, reactionExtensionList map[string]*server_api_params.KeyValue) error {
|
||||
ctx, _ := context.WithTimeout(context.Background(), time.Duration(config.Config.Mongo.DBTimeout)*time.Second)
|
||||
c := d.mongoClient.Database(config.Config.Mongo.DBDatabase).Collection(cExtendMsgSet)
|
||||
var updateBson = bson.M{}
|
||||
for _, v := range reactionExtensionList {
|
||||
updateBson[fmt.Sprintf("extend_msgs.%s.%s", clientMsgID, v.TypeKey)] = ""
|
||||
}
|
||||
set, err := d.GetExtendMsgSet(ctx, sourceID, sessionType, msgFirstModifyTime, c)
|
||||
if err != nil {
|
||||
return utils.Wrap(err, "")
|
||||
}
|
||||
if set == nil {
|
||||
return errors.New(fmt.Sprintf("sourceID %s has no set", sourceID))
|
||||
}
|
||||
_, err = c.UpdateOne(ctx, bson.M{"source_id": set.SourceID, "session_type": sessionType}, bson.M{"$unset": updateBson})
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *DataBases) GetExtendMsg(sourceID string, sessionType int32, clientMsgID string, maxMsgUpdateTime int64) (extendMsg *ExtendMsg, err error) {
|
||||
ctx, _ := context.WithTimeout(context.Background(), time.Duration(config.Config.Mongo.DBTimeout)*time.Second)
|
||||
c := d.mongoClient.Database(config.Config.Mongo.DBDatabase).Collection(cExtendMsgSet)
|
||||
findOpts := options.Find().SetLimit(1).SetSkip(0).SetSort(bson.M{"source_id": -1}).SetProjection(bson.M{fmt.Sprintf("extend_msgs.%s", clientMsgID): 1})
|
||||
regex := fmt.Sprintf("^%s", sourceID)
|
||||
result, err := c.Find(ctx, bson.M{"source_id": primitive.Regex{Pattern: regex}, "session_type": sessionType, "max_msg_update_time": bson.M{"$lte": maxMsgUpdateTime}}, findOpts)
|
||||
if err != nil {
|
||||
return nil, utils.Wrap(err, "")
|
||||
}
|
||||
var setList []ExtendMsgSet
|
||||
if err := result.All(ctx, &setList); err != nil {
|
||||
return nil, utils.Wrap(err, "")
|
||||
}
|
||||
if len(setList) == 0 {
|
||||
return nil, utils.Wrap(errors.New("GetExtendMsg failed, len(setList) == 0"), "")
|
||||
}
|
||||
if v, ok := setList[0].ExtendMsgs[clientMsgID]; ok {
|
||||
return &v, nil
|
||||
}
|
||||
return nil, errors.New(fmt.Sprintf("cant find client msg id: %s", clientMsgID))
|
||||
}
|
@ -46,10 +46,10 @@ func key(dbAddress, dbName string) string {
|
||||
}
|
||||
|
||||
func init() {
|
||||
//log.NewPrivateLog(constant.LogFileName)
|
||||
var mongoClient *mongo.Client
|
||||
var err1 error
|
||||
//mysql init
|
||||
fmt.Println("init mysql redis mongo ")
|
||||
|
||||
initMysqlDB()
|
||||
// mongo init
|
||||
// "mongodb://sysop:moon@localhost/records"
|
||||
@ -84,45 +84,34 @@ func init() {
|
||||
|
||||
mongoClient, err := mongo.Connect(context.TODO(), options.Client().ApplyURI(uri))
|
||||
if err != nil {
|
||||
fmt.Println(" mongo.Connect failed, try ", utils.GetSelfFuncName(), err.Error(), uri)
|
||||
time.Sleep(time.Duration(30) * time.Second)
|
||||
mongoClient, err1 = mongo.Connect(context.TODO(), options.Client().ApplyURI(uri))
|
||||
if err1 != nil {
|
||||
fmt.Println(" mongo.Connect retry failed, panic", err.Error(), uri)
|
||||
panic(err1.Error())
|
||||
panic(err1.Error() + " mongo.Connect failed " + uri)
|
||||
}
|
||||
}
|
||||
fmt.Println("mongo driver client init success: ", uri)
|
||||
// mongodb create index
|
||||
if err := createMongoIndex(mongoClient, cSendLog, false, "send_id", "-send_time"); err != nil {
|
||||
fmt.Println("send_id", "-send_time", "index create failed", err.Error())
|
||||
panic(err.Error())
|
||||
panic(err.Error() + " index create failed " + cSendLog + " send_id, -send_time")
|
||||
}
|
||||
if err := createMongoIndex(mongoClient, cChat, false, "uid"); err != nil {
|
||||
fmt.Println("uid", " index create failed", err.Error())
|
||||
//panic(err.Error())
|
||||
fmt.Println(err.Error() + " index create failed " + cChat + " uid ")
|
||||
}
|
||||
if err := createMongoIndex(mongoClient, cWorkMoment, true, "-create_time", "work_moment_id"); err != nil {
|
||||
fmt.Println("-create_time", "work_moment_id", "index create failed", err.Error())
|
||||
panic(err.Error())
|
||||
panic(err.Error() + "index create failed " + cWorkMoment + " -create_time, work_moment_id")
|
||||
}
|
||||
if err := createMongoIndex(mongoClient, cWorkMoment, true, "work_moment_id"); err != nil {
|
||||
fmt.Println("work_moment_id", "index create failed", err.Error())
|
||||
panic(err.Error())
|
||||
panic(err.Error() + "index create failed " + cWorkMoment + " work_moment_id ")
|
||||
}
|
||||
if err := createMongoIndex(mongoClient, cWorkMoment, false, "user_id", "-create_time"); err != nil {
|
||||
fmt.Println("user_id", "-create_time", "index create failed", err.Error())
|
||||
panic(err.Error())
|
||||
panic(err.Error() + "index create failed " + cWorkMoment + "user_id, -create_time")
|
||||
}
|
||||
if err := createMongoIndex(mongoClient, cTag, false, "user_id", "-create_time"); err != nil {
|
||||
fmt.Println("user_id", "-create_time", "index create failed", err.Error())
|
||||
panic(err.Error())
|
||||
panic(err.Error() + "index create failed " + cTag + " user_id, -create_time")
|
||||
}
|
||||
if err := createMongoIndex(mongoClient, cTag, true, "tag_id"); err != nil {
|
||||
fmt.Println("tag_id", "index create failed", err.Error())
|
||||
panic(err.Error())
|
||||
panic(err.Error() + "index create failed " + cTag + " tag_id")
|
||||
}
|
||||
fmt.Println("createMongoIndex success")
|
||||
DB.mongoClient = mongoClient
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
@ -136,7 +125,8 @@ func init() {
|
||||
})
|
||||
_, err = DB.RDB.Ping(ctx).Result()
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
fmt.Println("redis cluster failed address ", config.Config.Redis.DBAddress)
|
||||
panic(err.Error() + " redis cluster " + config.Config.Redis.DBUserName + config.Config.Redis.DBPassWord)
|
||||
}
|
||||
} else {
|
||||
DB.RDB = go_redis.NewClient(&go_redis.Options{
|
||||
@ -148,7 +138,7 @@ func init() {
|
||||
})
|
||||
_, err = DB.RDB.Ping(ctx).Result()
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
panic(err.Error() + " redis " + config.Config.Redis.DBAddress[0] + config.Config.Redis.DBUserName + config.Config.Redis.DBPassWord)
|
||||
}
|
||||
}
|
||||
// 强一致性缓存,当一个key被标记删除,其他请求线程会被锁住轮询直到新的key生成,适合各种同步的拉取, 如果弱一致可能导致拉取还是老数据,毫无意义
|
||||
@ -158,6 +148,8 @@ func init() {
|
||||
// 弱一致性缓存,当一个key被标记删除,其他请求线程直接返回该key的value,适合高频并且生成很缓存很慢的情况 如大群发消息缓存的缓存
|
||||
DB.WeakRc = rockscache.NewClient(DB.RDB, rockscache.NewDefaultOptions())
|
||||
DB.WeakRc.Options.StrongConsistency = false
|
||||
|
||||
fmt.Println("init mysql redis mongo ok ")
|
||||
}
|
||||
|
||||
func createMongoIndex(client *mongo.Client, collection string, isUnique bool, keys ...string) error {
|
||||
|
@ -10,13 +10,14 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"sync"
|
||||
|
||||
"github.com/go-redis/redis/v8"
|
||||
"github.com/gogo/protobuf/sortkeys"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
"math/rand"
|
||||
"sync"
|
||||
|
||||
//"github.com/garyburd/redigo/redis"
|
||||
"github.com/golang/protobuf/proto"
|
||||
@ -206,6 +207,13 @@ func (d *DataBases) ReplaceMsgBySeq(uid string, msg *open_im_sdk.MsgData, operat
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *DataBases) UpdateOneMsgList(msg *UserChat) error {
|
||||
ctx, _ := context.WithTimeout(context.Background(), time.Duration(config.Config.Mongo.DBTimeout)*time.Second)
|
||||
c := d.mongoClient.Database(config.Config.Mongo.DBDatabase).Collection(cChat)
|
||||
_, err := c.UpdateOne(ctx, bson.M{"uid": msg.UID}, bson.M{"$set": bson.M{"msg": msg.Msg}})
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *DataBases) GetMsgBySeqList(uid string, seqList []uint32, operationID string) (seqMsg []*open_im_sdk.MsgData, err error) {
|
||||
log.NewInfo(operationID, utils.GetSelfFuncName(), uid, seqList)
|
||||
var hasSeqList []uint32
|
||||
@ -291,13 +299,13 @@ func (d *DataBases) DelMongoMsgs(IDList []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *DataBases) ReplaceMsgToBlankByIndex(suffixID string, index int) error {
|
||||
func (d *DataBases) ReplaceMsgToBlankByIndex(suffixID string, index int) (replaceMaxSeq uint32, err error) {
|
||||
ctx, _ := context.WithTimeout(context.Background(), time.Duration(config.Config.Mongo.DBTimeout)*time.Second)
|
||||
c := d.mongoClient.Database(config.Config.Mongo.DBDatabase).Collection(cChat)
|
||||
userChat := &UserChat{}
|
||||
err := c.FindOne(ctx, bson.M{"uid": suffixID}).Decode(&userChat)
|
||||
err = c.FindOne(ctx, bson.M{"uid": suffixID}).Decode(&userChat)
|
||||
if err != nil {
|
||||
return err
|
||||
return 0, err
|
||||
}
|
||||
for i, msg := range userChat.Msg {
|
||||
if i <= index {
|
||||
@ -312,13 +320,14 @@ func (d *DataBases) ReplaceMsgToBlankByIndex(suffixID string, index int) error {
|
||||
}
|
||||
msg.Msg = bytes
|
||||
msg.SendTime = 0
|
||||
replaceMaxSeq = msgPb.Seq
|
||||
}
|
||||
}
|
||||
_, err = c.UpdateOne(ctx, bson.M{"uid": suffixID}, bson.M{"$set": bson.M{"msg": userChat.Msg}})
|
||||
return err
|
||||
return replaceMaxSeq, err
|
||||
}
|
||||
|
||||
func (d *DataBases) GetNewestMsg(ID string) (msg *MsgInfo, err error) {
|
||||
func (d *DataBases) GetNewestMsg(ID string) (msg *open_im_sdk.MsgData, err error) {
|
||||
ctx, _ := context.WithTimeout(context.Background(), time.Duration(config.Config.Mongo.DBTimeout)*time.Second)
|
||||
c := d.mongoClient.Database(config.Config.Mongo.DBDatabase).Collection(cChat)
|
||||
regex := fmt.Sprintf("^%s", ID)
|
||||
@ -334,13 +343,53 @@ func (d *DataBases) GetNewestMsg(ID string) (msg *MsgInfo, err error) {
|
||||
}
|
||||
if len(userChats) > 0 {
|
||||
if len(userChats[0].Msg) > 0 {
|
||||
return &userChats[0].Msg[len(userChats[0].Msg)-1], nil
|
||||
msgPb := &open_im_sdk.MsgData{}
|
||||
err = proto.Unmarshal(userChats[0].Msg[len(userChats[0].Msg)-1].Msg, msgPb)
|
||||
if err != nil {
|
||||
return nil, utils.Wrap(err, "")
|
||||
}
|
||||
return msgPb, nil
|
||||
}
|
||||
return nil, errors.New("len(userChats[0].Msg) < 0")
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (d *DataBases) GetOldestMsg(ID string) (msg *open_im_sdk.MsgData, err error) {
|
||||
ctx, _ := context.WithTimeout(context.Background(), time.Duration(config.Config.Mongo.DBTimeout)*time.Second)
|
||||
c := d.mongoClient.Database(config.Config.Mongo.DBDatabase).Collection(cChat)
|
||||
regex := fmt.Sprintf("^%s", ID)
|
||||
findOpts := options.Find().SetLimit(1).SetSort(bson.M{"uid": 1})
|
||||
var userChats []UserChat
|
||||
cursor, err := c.Find(ctx, bson.M{"uid": bson.M{"$regex": regex}}, findOpts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = cursor.All(ctx, &userChats)
|
||||
if err != nil {
|
||||
return nil, utils.Wrap(err, "")
|
||||
}
|
||||
var oldestMsg []byte
|
||||
if len(userChats) > 0 {
|
||||
for _, v := range userChats[0].Msg {
|
||||
if v.SendTime != 0 {
|
||||
oldestMsg = v.Msg
|
||||
break
|
||||
}
|
||||
}
|
||||
if len(oldestMsg) == 0 {
|
||||
oldestMsg = userChats[0].Msg[len(userChats[0].Msg)-1].Msg
|
||||
}
|
||||
msgPb := &open_im_sdk.MsgData{}
|
||||
err = proto.Unmarshal(oldestMsg, msgPb)
|
||||
if err != nil {
|
||||
return nil, utils.Wrap(err, "")
|
||||
}
|
||||
return msgPb, nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (d *DataBases) GetMsgBySeqListMongo2(uid string, seqList []uint32, operationID string) (seqMsg []*open_im_sdk.MsgData, err error) {
|
||||
var hasSeqList []uint32
|
||||
singleCount := 0
|
||||
|
@ -22,37 +22,26 @@ func (w Writer) Printf(format string, args ...interface{}) {
|
||||
}
|
||||
|
||||
func initMysqlDB() {
|
||||
fmt.Println("init mysqlDB start")
|
||||
//When there is no open IM database, connect to the mysql built-in database to create openIM database
|
||||
dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=true&loc=Local",
|
||||
config.Config.Mysql.DBUserName, config.Config.Mysql.DBPassword, config.Config.Mysql.DBAddress[0], "mysql")
|
||||
var db *gorm.DB
|
||||
var err1 error
|
||||
db, err := gorm.Open(mysql.Open(dsn), nil)
|
||||
if err != nil {
|
||||
fmt.Println("Open failed ", err.Error(), dsn)
|
||||
}
|
||||
if err != nil {
|
||||
time.Sleep(time.Duration(30) * time.Second)
|
||||
db, err1 = gorm.Open(mysql.Open(dsn), nil)
|
||||
if err1 != nil {
|
||||
fmt.Println("Open failed ", err1.Error(), dsn)
|
||||
panic(err1.Error())
|
||||
panic(err1.Error() + " open failed " + dsn)
|
||||
}
|
||||
}
|
||||
|
||||
//Check the database and table during initialization
|
||||
sql := fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %s default charset utf8 COLLATE utf8_general_ci;", config.Config.Mysql.DBDatabaseName)
|
||||
fmt.Println("exec sql: ", sql, " begin")
|
||||
err = db.Exec(sql).Error
|
||||
if err != nil {
|
||||
fmt.Println("Exec failed ", err.Error(), sql)
|
||||
panic(err.Error())
|
||||
panic(err.Error() + " Exec failed " + sql)
|
||||
}
|
||||
fmt.Println("exec sql: ", sql, " end")
|
||||
dsn = fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=true&loc=Local",
|
||||
config.Config.Mysql.DBUserName, config.Config.Mysql.DBPassword, config.Config.Mysql.DBAddress[0], config.Config.Mysql.DBDatabaseName)
|
||||
|
||||
newLogger := logger.New(
|
||||
Writer{},
|
||||
logger.Config{
|
||||
@ -66,20 +55,18 @@ func initMysqlDB() {
|
||||
Logger: newLogger,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Println("Open failed ", err.Error(), dsn)
|
||||
panic(err.Error())
|
||||
panic(err.Error() + " Open failed " + dsn)
|
||||
}
|
||||
|
||||
sqlDB, err := db.DB()
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
panic(err.Error() + " db.DB() failed ")
|
||||
}
|
||||
|
||||
sqlDB.SetConnMaxLifetime(time.Second * time.Duration(config.Config.Mysql.DBMaxLifeTime))
|
||||
sqlDB.SetMaxOpenConns(config.Config.Mysql.DBMaxOpenConns)
|
||||
sqlDB.SetMaxIdleConns(config.Config.Mysql.DBMaxIdleConns)
|
||||
|
||||
fmt.Println("open mysql ok ", dsn)
|
||||
db.AutoMigrate(
|
||||
&Register{},
|
||||
&Friend{},
|
||||
@ -94,99 +81,69 @@ func initMysqlDB() {
|
||||
db.Set("gorm:table_options", "collation=utf8_unicode_ci")
|
||||
|
||||
if !db.Migrator().HasTable(&Friend{}) {
|
||||
fmt.Println("CreateTable Friend")
|
||||
db.Migrator().CreateTable(&Friend{})
|
||||
}
|
||||
|
||||
if !db.Migrator().HasTable(&FriendRequest{}) {
|
||||
fmt.Println("CreateTable FriendRequest")
|
||||
db.Migrator().CreateTable(&FriendRequest{})
|
||||
}
|
||||
|
||||
if !db.Migrator().HasTable(&Group{}) {
|
||||
fmt.Println("CreateTable Group")
|
||||
db.Migrator().CreateTable(&Group{})
|
||||
}
|
||||
|
||||
if !db.Migrator().HasTable(&GroupMember{}) {
|
||||
fmt.Println("CreateTable GroupMember")
|
||||
db.Migrator().CreateTable(&GroupMember{})
|
||||
}
|
||||
if !db.Migrator().HasTable(&GroupRequest{}) {
|
||||
fmt.Println("CreateTable GroupRequest")
|
||||
db.Migrator().CreateTable(&GroupRequest{})
|
||||
}
|
||||
if !db.Migrator().HasTable(&User{}) {
|
||||
fmt.Println("CreateTable User")
|
||||
db.Migrator().CreateTable(&User{})
|
||||
}
|
||||
if !db.Migrator().HasTable(&Black{}) {
|
||||
fmt.Println("CreateTable Black")
|
||||
db.Migrator().CreateTable(&Black{})
|
||||
}
|
||||
if !db.Migrator().HasTable(&ChatLog{}) {
|
||||
fmt.Println("CreateTable ChatLog")
|
||||
db.Migrator().CreateTable(&ChatLog{})
|
||||
}
|
||||
if !db.Migrator().HasTable(&Register{}) {
|
||||
fmt.Println("CreateTable Register")
|
||||
db.Migrator().CreateTable(&Register{})
|
||||
}
|
||||
if !db.Migrator().HasTable(&Conversation{}) {
|
||||
fmt.Println("CreateTable Conversation")
|
||||
db.Migrator().CreateTable(&Conversation{})
|
||||
}
|
||||
|
||||
if !db.Migrator().HasTable(&Department{}) {
|
||||
fmt.Println("CreateTable Department")
|
||||
db.Migrator().CreateTable(&Department{})
|
||||
}
|
||||
if !db.Migrator().HasTable(&OrganizationUser{}) {
|
||||
fmt.Println("CreateTable OrganizationUser")
|
||||
db.Migrator().CreateTable(&OrganizationUser{})
|
||||
}
|
||||
if !db.Migrator().HasTable(&DepartmentMember{}) {
|
||||
fmt.Println("CreateTable DepartmentMember")
|
||||
db.Migrator().CreateTable(&DepartmentMember{})
|
||||
}
|
||||
if !db.Migrator().HasTable(&AppVersion{}) {
|
||||
fmt.Println("CreateTable DepartmentMember")
|
||||
db.Migrator().CreateTable(&AppVersion{})
|
||||
}
|
||||
if !db.Migrator().HasTable(&BlackList{}) {
|
||||
fmt.Println("CreateTable BlackList")
|
||||
db.Migrator().CreateTable(&BlackList{})
|
||||
}
|
||||
if !db.Migrator().HasTable(&IpLimit{}) {
|
||||
fmt.Println("CreateTable IpLimit")
|
||||
db.Migrator().CreateTable(&IpLimit{})
|
||||
}
|
||||
if !db.Migrator().HasTable(&UserIpLimit{}) {
|
||||
fmt.Println("CreateTable UserIpLimit")
|
||||
db.Migrator().CreateTable(&UserIpLimit{})
|
||||
}
|
||||
|
||||
if !db.Migrator().HasTable(&RegisterAddFriend{}) {
|
||||
fmt.Println("CreateTable RegisterAddFriend")
|
||||
db.Migrator().CreateTable(&RegisterAddFriend{})
|
||||
}
|
||||
if !db.Migrator().HasTable(&Invitation{}) {
|
||||
fmt.Println("CreateTable Invitation")
|
||||
db.Migrator().CreateTable(&Invitation{})
|
||||
}
|
||||
|
||||
if !db.Migrator().HasTable(&ClientInitConfig{}) {
|
||||
fmt.Println("CreateTable ClientInitConfig")
|
||||
db.Migrator().CreateTable(&ClientInitConfig{})
|
||||
}
|
||||
|
||||
if !db.Migrator().HasTable(&UserIpRecord{}) {
|
||||
fmt.Println("CreateTable Friend")
|
||||
db.Migrator().CreateTable(&UserIpRecord{})
|
||||
}
|
||||
|
||||
DB.MysqlDB.db = db
|
||||
return
|
||||
}
|
||||
|
||||
func (m *mysqlDB) DefaultGormDB() *gorm.DB {
|
||||
|
@ -4,8 +4,6 @@ import (
|
||||
"Open_IM/pkg/common/db"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
_ "github.com/jinzhu/gorm/dialects/mysql"
|
||||
)
|
||||
|
||||
func InsertToFriend(toInsertFollow *db.Friend) error {
|
||||
|
@ -27,7 +27,9 @@ func UpdateGroupRequest(groupRequest db.GroupRequest) error {
|
||||
}
|
||||
|
||||
func InsertIntoGroupRequest(toInsertInfo db.GroupRequest) error {
|
||||
DelGroupRequestByGroupIDAndUserID(toInsertInfo.GroupID, toInsertInfo.UserID)
|
||||
if err := DelGroupRequestByGroupIDAndUserID(toInsertInfo.GroupID, toInsertInfo.UserID); err != nil {
|
||||
return err
|
||||
}
|
||||
if toInsertInfo.HandledTime.Unix() < 0 {
|
||||
toInsertInfo.HandledTime = utils.UnixSecondToTime(0)
|
||||
}
|
||||
@ -70,7 +72,7 @@ func GetGroupRequestByGroupID(groupID string) ([]db.GroupRequest, error) {
|
||||
return groupRequestList, nil
|
||||
}
|
||||
|
||||
//received
|
||||
// received
|
||||
func GetGroupApplicationList(userID string) ([]db.GroupRequest, error) {
|
||||
var groupRequestList []db.GroupRequest
|
||||
memberList, err := GetGroupMemberListByUserID(userID)
|
||||
|
@ -5,8 +5,6 @@ import (
|
||||
"errors"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"github.com/jinzhu/gorm"
|
||||
)
|
||||
|
||||
/**
|
||||
@ -89,9 +87,6 @@ func GetInvitationCode(code string) (*db.Invitation, error) {
|
||||
InvitationCode: code,
|
||||
}
|
||||
err := db.DB.MysqlDB.DefaultGormDB().Model(invitation).Find(invitation).Error
|
||||
if gorm.IsRecordNotFoundError(err) {
|
||||
return invitation, nil
|
||||
}
|
||||
return invitation, err
|
||||
}
|
||||
|
||||
|
@ -3,65 +3,42 @@ package im_mysql_model
|
||||
import (
|
||||
"Open_IM/pkg/common/constant"
|
||||
"Open_IM/pkg/common/db"
|
||||
"Open_IM/pkg/common/log"
|
||||
"Open_IM/pkg/utils"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func GetChatLog(chatLog db.ChatLog, pageNumber, showNumber int32) ([]db.ChatLog, error) {
|
||||
var chatLogs []db.ChatLog
|
||||
db := db.DB.MysqlDB.DefaultGormDB().Table("chat_logs").
|
||||
Limit(int(showNumber)).Offset(int(showNumber * (pageNumber - 1)))
|
||||
func GetChatLog(chatLog *db.ChatLog, pageNumber, showNumber int32, contentTypeList []int32) (int64, []db.ChatLog, error) {
|
||||
mdb := db.DB.MysqlDB.DefaultGormDB().Table("chat_logs")
|
||||
if chatLog.SendTime.Unix() > 0 {
|
||||
db = db.Where("send_time > ? and send_time < ?", chatLog.SendTime, chatLog.SendTime.AddDate(0, 0, 1))
|
||||
mdb = mdb.Where("send_time > ? and send_time < ?", chatLog.SendTime, chatLog.SendTime.AddDate(0, 0, 1))
|
||||
}
|
||||
if chatLog.Content != "" {
|
||||
db = db.Where(" content like ? ", fmt.Sprintf("%%%s%%", chatLog.Content))
|
||||
mdb = mdb.Where(" content like ? ", fmt.Sprintf("%%%s%%", chatLog.Content))
|
||||
}
|
||||
if chatLog.SessionType == 1 {
|
||||
db = db.Where("session_type = ?", chatLog.SessionType)
|
||||
mdb = mdb.Where("session_type = ?", chatLog.SessionType)
|
||||
} else if chatLog.SessionType == 2 {
|
||||
db = db.Where("session_type in (?)", []int{constant.GroupChatType, constant.SuperGroupChatType})
|
||||
mdb = mdb.Where("session_type in (?)", []int{constant.GroupChatType, constant.SuperGroupChatType})
|
||||
}
|
||||
if chatLog.ContentType != 0 {
|
||||
db = db.Where("content_type = ?", chatLog.ContentType)
|
||||
mdb = mdb.Where("content_type = ?", chatLog.ContentType)
|
||||
}
|
||||
if chatLog.SendID != "" {
|
||||
db = db.Where("send_id = ?", chatLog.SendID)
|
||||
mdb = mdb.Where("send_id = ?", chatLog.SendID)
|
||||
}
|
||||
if chatLog.RecvID != "" {
|
||||
db = db.Where("recv_id = ?", chatLog.RecvID)
|
||||
mdb = mdb.Where("recv_id = ?", chatLog.RecvID)
|
||||
}
|
||||
if len(contentTypeList) > 0 {
|
||||
mdb = mdb.Where("content_type in (?)", contentTypeList)
|
||||
}
|
||||
|
||||
err := db.Find(&chatLogs).Error
|
||||
return chatLogs, err
|
||||
}
|
||||
|
||||
func GetChatLogCount(chatLog db.ChatLog) (int64, error) {
|
||||
var count int64
|
||||
db := db.DB.MysqlDB.DefaultGormDB().Table("chat_logs")
|
||||
if chatLog.SendTime.Unix() > 0 {
|
||||
log.NewDebug("", utils.GetSelfFuncName(), chatLog.SendTime, chatLog.SendTime.AddDate(0, 0, 1))
|
||||
db = db.Where("send_time > ? and send_time < ?", chatLog.SendTime, chatLog.SendTime.AddDate(0, 0, 1))
|
||||
if err := mdb.Count(&count).Error; err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
if chatLog.Content != "" {
|
||||
db = db.Where(" content like ? ", fmt.Sprintf("%%%s%%", chatLog.Content))
|
||||
var chatLogs []db.ChatLog
|
||||
mdb = mdb.Limit(int(showNumber)).Offset(int(showNumber * (pageNumber - 1)))
|
||||
if err := mdb.Find(&chatLogs).Error; err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
if chatLog.SessionType == 1 {
|
||||
db = db.Where("session_type = ?", chatLog.SessionType)
|
||||
} else if chatLog.SessionType == 2 {
|
||||
db = db.Where("session_type in (?)", []int{constant.GroupChatType, constant.SuperGroupChatType})
|
||||
}
|
||||
if chatLog.ContentType != 0 {
|
||||
db = db.Where("content_type = ?", chatLog.ContentType)
|
||||
}
|
||||
if chatLog.SendID != "" {
|
||||
db = db.Where("send_id = ?", chatLog.SendID)
|
||||
}
|
||||
if chatLog.RecvID != "" {
|
||||
db = db.Where("recv_id = ?", chatLog.RecvID)
|
||||
}
|
||||
|
||||
err := db.Count(&count).Error
|
||||
return count, err
|
||||
return count, chatLogs, nil
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ import (
|
||||
"Open_IM/pkg/utils"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"sort"
|
||||
@ -34,6 +33,8 @@ const (
|
||||
groupMemberNumCache = "GROUP_MEMBER_NUM_CACHE:"
|
||||
conversationCache = "CONVERSATION_CACHE:"
|
||||
conversationIDListCache = "CONVERSATION_ID_LIST_CACHE:"
|
||||
extendMsgSetCache = "EXTEND_MSG_SET_CACHE:"
|
||||
extendMsgCache = "EXTEND_MSG_CACHE:"
|
||||
)
|
||||
|
||||
func DelKeys() {
|
||||
@ -408,9 +409,6 @@ func GetJoinedSuperGroupListFromCache(userID string) ([]string, error) {
|
||||
if err != nil {
|
||||
return "", utils.Wrap(err, "")
|
||||
}
|
||||
if len(userToSuperGroup.GroupIDList) == 0 {
|
||||
return "", errors.New("GroupIDList == 0")
|
||||
}
|
||||
bytes, err := json.Marshal(userToSuperGroup.GroupIDList)
|
||||
if err != nil {
|
||||
return "", utils.Wrap(err, "")
|
||||
@ -568,3 +566,32 @@ func GetUserAllConversationList(ownerUserID string) ([]db.Conversation, error) {
|
||||
func DelConversationFromCache(ownerUserID, conversationID string) error {
|
||||
return utils.Wrap(db.DB.Rc.TagAsDeleted(conversationCache+ownerUserID+":"+conversationID), "DelConversationFromCache err")
|
||||
}
|
||||
|
||||
func GetExtendMsg(sourceID string, sessionType int32, clientMsgID string, firstModifyTime int64) (*db.ExtendMsg, error) {
|
||||
getExtendMsg := func() (string, error) {
|
||||
extendMsg, err := db.DB.GetExtendMsg(sourceID, sessionType, clientMsgID, firstModifyTime)
|
||||
if err != nil {
|
||||
return "", utils.Wrap(err, "GetExtendMsgList failed")
|
||||
}
|
||||
bytes, err := json.Marshal(extendMsg)
|
||||
if err != nil {
|
||||
return "", utils.Wrap(err, "Marshal failed")
|
||||
}
|
||||
return string(bytes), nil
|
||||
}
|
||||
|
||||
extendMsgStr, err := db.DB.Rc.Fetch(extendMsgCache+clientMsgID, time.Second*30*60, getExtendMsg)
|
||||
if err != nil {
|
||||
return nil, utils.Wrap(err, "Fetch failed")
|
||||
}
|
||||
extendMsg := &db.ExtendMsg{}
|
||||
err = json.Unmarshal([]byte(extendMsgStr), extendMsg)
|
||||
if err != nil {
|
||||
return nil, utils.Wrap(err, "Unmarshal failed")
|
||||
}
|
||||
return extendMsg, nil
|
||||
}
|
||||
|
||||
func DelExtendMsg(ID string, index int32, clientMsgID string) error {
|
||||
return utils.Wrap(db.DB.Rc.TagAsDeleted(extendMsgCache+clientMsgID), "DelExtendMsg err")
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ package kafka
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/Shopify/sarama"
|
||||
)
|
||||
|
||||
@ -29,9 +30,10 @@ func NewMConsumerGroup(consumerConfig *MConsumerGroupConfig, topics, addrs []str
|
||||
config.Version = consumerConfig.KafkaVersion
|
||||
config.Consumer.Offsets.Initial = consumerConfig.OffsetsInitial
|
||||
config.Consumer.Return.Errors = consumerConfig.IsReturnErr
|
||||
fmt.Println("init address is ", addrs, "topics is ", topics)
|
||||
//fmt.Println("init address is ", addrs, "topics is ", topics)
|
||||
consumerGroup, err := sarama.NewConsumerGroup(addrs, groupID, config)
|
||||
if err != nil {
|
||||
fmt.Println("args:", addrs, groupID, config)
|
||||
panic(err.Error())
|
||||
}
|
||||
return &MConsumerGroup{
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -23,6 +23,18 @@ message AdminLoginResp {
|
||||
CommonResp commonResp = 4;
|
||||
}
|
||||
|
||||
message GetUserTokenReq {
|
||||
string operationID = 1;
|
||||
string userID = 2;
|
||||
int32 platformID = 3;
|
||||
}
|
||||
|
||||
message GetUserTokenResp {
|
||||
CommonResp commonResp = 1;
|
||||
string token = 2;
|
||||
int64 expTime = 3;
|
||||
}
|
||||
|
||||
message AddUserRegisterAddFriendIDListReq {
|
||||
string operationID = 1;
|
||||
repeated string userIDList = 2;
|
||||
@ -62,7 +74,7 @@ message GetChatLogsReq {
|
||||
int32 contentType = 6;
|
||||
server_api_params.RequestPagination pagination = 7;
|
||||
string operationID = 8;
|
||||
|
||||
string opUserID = 9;
|
||||
}
|
||||
|
||||
message ChatLog {
|
||||
@ -328,6 +340,7 @@ message GetUserIDByEmailAndPhoneNumberResp{
|
||||
|
||||
service adminCMS {
|
||||
rpc AdminLogin(AdminLoginReq) returns(AdminLoginResp);
|
||||
|
||||
rpc AddUserRegisterAddFriendIDList(AddUserRegisterAddFriendIDListReq) returns(AddUserRegisterAddFriendIDListResp);
|
||||
rpc ReduceUserRegisterAddFriendIDList(ReduceUserRegisterAddFriendIDListReq) returns(ReduceUserRegisterAddFriendIDListResp);
|
||||
rpc GetUserRegisterAddFriendIDList(GetUserRegisterAddFriendIDListReq) returns(GetUserRegisterAddFriendIDListResp);
|
||||
@ -357,4 +370,6 @@ service adminCMS {
|
||||
rpc GetUserFriends(GetUserFriendsReq) returns(GetUserFriendsResp);
|
||||
|
||||
rpc GetUserIDByEmailAndPhoneNumber(GetUserIDByEmailAndPhoneNumberReq) returns(GetUserIDByEmailAndPhoneNumberResp);
|
||||
|
||||
rpc GetUserToken(GetUserTokenReq) returns(GetUserTokenResp);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,6 @@
|
||||
syntax = "proto3";
|
||||
import "Open-IM-Server/pkg/proto/sdk_ws/ws.proto";
|
||||
import "Open-IM-Server/pkg/proto/sdk_ws/wrappers.proto";
|
||||
option go_package = "Open_IM/pkg/proto/msg;msg";
|
||||
package msg;
|
||||
|
||||
@ -153,6 +154,118 @@ message GetWriteDiffMsgResp{
|
||||
server_api_params.MsgData msgData = 3;
|
||||
}
|
||||
|
||||
message ModifyMessageReactionExtensionsReq {
|
||||
string operationID = 1;
|
||||
string sourceID = 2;
|
||||
string opUserID = 3;
|
||||
int32 sessionType = 4;
|
||||
map <string, server_api_params.KeyValue>reactionExtensionList = 5;
|
||||
string clientMsgID = 6;
|
||||
google.protobuf.StringValue ex = 7;
|
||||
google.protobuf.StringValue attachedInfo = 8;
|
||||
bool isReact = 9;
|
||||
bool isExternalExtensions = 10;
|
||||
int64 msgFirstModifyTime = 11;
|
||||
}
|
||||
message SetMessageReactionExtensionsReq {
|
||||
string operationID = 1;
|
||||
string sourceID = 2;
|
||||
string opUserID = 3;
|
||||
int32 sessionType = 4;
|
||||
map <string, server_api_params.KeyValue>reactionExtensionList = 5;
|
||||
string clientMsgID = 6;
|
||||
google.protobuf.StringValue ex = 7;
|
||||
google.protobuf.StringValue attachedInfo = 8;
|
||||
bool isReact = 9;
|
||||
bool isExternalExtensions = 10;
|
||||
int64 msgFirstModifyTime = 11;
|
||||
}
|
||||
message SetMessageReactionExtensionsResp {
|
||||
int32 errCode = 1;
|
||||
string errMsg = 2;
|
||||
string clientMsgID = 3;
|
||||
int64 msgFirstModifyTime = 4;
|
||||
bool isReact = 5;
|
||||
repeated KeyValueResp result = 6;
|
||||
}
|
||||
|
||||
|
||||
message GetMessageListReactionExtensionsReq {
|
||||
string operationID = 1;
|
||||
string opUserID = 2;
|
||||
string sourceID = 3;
|
||||
int32 sessionType = 4;
|
||||
bool isExternalExtensions = 5;
|
||||
message MessageReactionKey {
|
||||
string clientMsgID = 1;
|
||||
int64 msgFirstModifyTime = 2;
|
||||
}
|
||||
repeated MessageReactionKey messageReactionKeyList = 6;
|
||||
}
|
||||
message GetMessageListReactionExtensionsResp{
|
||||
int32 errCode = 1;
|
||||
string errMsg = 2;
|
||||
repeated SingleMessageExtensionResult singleMessageResult =3;
|
||||
|
||||
}
|
||||
message SingleMessageExtensionResult {
|
||||
int32 errCode = 1;
|
||||
string errMsg = 2;
|
||||
map <string, server_api_params.KeyValue>reactionExtensionList = 3;
|
||||
string clientMsgID = 4;
|
||||
}
|
||||
|
||||
|
||||
message ModifyMessageReactionExtensionsResp {
|
||||
int32 errCode = 1;
|
||||
string errMsg = 2;
|
||||
repeated ExtendMsgResp successList = 3;
|
||||
repeated ExtendMsgResp failedList = 4;
|
||||
}
|
||||
|
||||
message DeleteMessageListReactionExtensionsReq {
|
||||
string operationID = 1;
|
||||
string opUserID = 2;
|
||||
string sourceID = 3;
|
||||
int32 sessionType = 4;
|
||||
string clientMsgID = 5;
|
||||
bool isExternalExtensions = 6;
|
||||
int64 msgFirstModifyTime = 7;
|
||||
repeated server_api_params.KeyValue reactionExtensionList = 8;
|
||||
}
|
||||
|
||||
message DeleteMessageListReactionExtensionsResp {
|
||||
int32 errCode = 1;
|
||||
string errMsg = 2;
|
||||
repeated KeyValueResp result = 6;
|
||||
}
|
||||
|
||||
message ExtendMsgResp {
|
||||
ExtendMsg extendMsg = 1;
|
||||
int32 errCode = 2;
|
||||
string errMsg = 3;
|
||||
}
|
||||
|
||||
message ExtendMsg {
|
||||
map <string, KeyValueResp>reactionExtensionList = 1;
|
||||
string clientMsgID = 2;
|
||||
int64 msgFirstModifyTime = 3;
|
||||
string attachedInfo = 4;
|
||||
string ex = 5;
|
||||
}
|
||||
|
||||
message KeyValueResp {
|
||||
server_api_params.KeyValue keyValue = 1;
|
||||
int32 errCode = 2;
|
||||
string errMsg = 3;
|
||||
}
|
||||
|
||||
message MsgDataToModifyByMQ{
|
||||
string aggregationID = 1;
|
||||
repeated MsgDataToMQ messageList = 2;
|
||||
string triggerID = 3;
|
||||
}
|
||||
|
||||
|
||||
service msg {
|
||||
rpc GetMaxAndMinSeq(server_api_params.GetMaxAndMinSeqReq) returns(server_api_params.GetMaxAndMinSeqResp);
|
||||
@ -167,4 +280,9 @@ service msg {
|
||||
rpc GetSuperGroupMsg(GetSuperGroupMsgReq) returns(GetSuperGroupMsgResp);
|
||||
rpc GetWriteDiffMsg(GetWriteDiffMsgReq) returns(GetWriteDiffMsgResp);
|
||||
|
||||
// modify msg
|
||||
rpc SetMessageReactionExtensions(SetMessageReactionExtensionsReq) returns(SetMessageReactionExtensionsResp);
|
||||
rpc GetMessageListReactionExtensions(GetMessageListReactionExtensionsReq) returns(GetMessageListReactionExtensionsResp);
|
||||
rpc AddMessageReactionExtensions(ModifyMessageReactionExtensionsReq) returns(ModifyMessageReactionExtensionsResp);
|
||||
rpc DeleteMessageReactionExtensions(DeleteMessageListReactionExtensionsReq) returns(DeleteMessageListReactionExtensionsResp);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -55,6 +55,8 @@ message GetUsersOnlineStatusResp{
|
||||
message SuccessDetail{
|
||||
string platform = 1;
|
||||
string status = 2;
|
||||
string connID = 3;
|
||||
bool isBackground = 4;
|
||||
}
|
||||
message FailedDetail{
|
||||
string userID = 3;
|
||||
@ -89,7 +91,6 @@ message MultiTerminalLoginCheckResp{
|
||||
string errMsg = 2;
|
||||
}
|
||||
|
||||
|
||||
service relay {
|
||||
rpc OnlinePushMsg(OnlinePushMsgReq) returns(OnlinePushMsgResp);
|
||||
rpc GetUsersOnlineStatus(GetUsersOnlineStatusReq) returns(GetUsersOnlineStatusResp);
|
||||
@ -97,5 +98,6 @@ service relay {
|
||||
rpc SuperGroupOnlineBatchPushOneMsg(OnlineBatchPushOneMsgReq) returns(OnlineBatchPushOneMsgResp);
|
||||
rpc KickUserOffline(KickUserOfflineReq) returns(KickUserOfflineResp);
|
||||
rpc MultiTerminalLoginCheck(MultiTerminalLoginCheckReq) returns(MultiTerminalLoginCheckResp);
|
||||
rpc SuperGroupBackgroundOnlinePush(OnlineBatchPushOneMsgReq) returns(OnlineBatchPushOneMsgResp);
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -330,6 +330,7 @@ message GroupApplicationAcceptedTips{
|
||||
GroupInfo group = 1;
|
||||
GroupMemberFullInfo opUser = 2;
|
||||
string handleMsg = 4;
|
||||
int32 receiverAs = 5; // admin(==1) or applicant(==0)
|
||||
}
|
||||
|
||||
// OnApplicationGroupRejected()
|
||||
@ -337,6 +338,7 @@ message GroupApplicationRejectedTips{
|
||||
GroupInfo group = 1;
|
||||
GroupMemberFullInfo opUser = 2;
|
||||
string handleMsg = 4;
|
||||
int32 receiverAs = 5; // admin(==1) or applicant(==0)
|
||||
}
|
||||
|
||||
// OnTransferGroupOwner()
|
||||
@ -696,4 +698,38 @@ message DelMsgListResp{
|
||||
string errMsg = 2;
|
||||
}
|
||||
|
||||
message SetAppBackgroundStatusReq {
|
||||
string userID = 1;
|
||||
bool isBackground = 2;
|
||||
}
|
||||
|
||||
message SetAppBackgroundStatusResp {
|
||||
int32 errCode = 1;
|
||||
string errMsg = 2;
|
||||
}
|
||||
|
||||
message ExtendMsgSet {
|
||||
string sourceID = 1;
|
||||
int32 sessionType = 2;
|
||||
map <string, ExtendMsg>extendMsgs = 3;
|
||||
int64 MaxMsgUpdateTime = 4;
|
||||
int32 extendMsgNum = 5;
|
||||
int64 createTime = 6;
|
||||
}
|
||||
|
||||
message ExtendMsg {
|
||||
map <string, KeyValue>reactionExtensionList = 1;
|
||||
string clientMsgID = 2;
|
||||
int64 msgFirstModifyTime = 3;
|
||||
string attachedInfo = 4;
|
||||
string ex = 5;
|
||||
}
|
||||
|
||||
message KeyValue {
|
||||
string typeKey = 1;
|
||||
string value = 2;
|
||||
int64 latestUpdateTime = 3;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -96,6 +96,8 @@ func GetConversationIDBySessionType(sourceID string, sessionType int) string {
|
||||
return "single_" + sourceID
|
||||
case constant.GroupChatType:
|
||||
return "group_" + sourceID
|
||||
case constant.SuperGroupChatType:
|
||||
return "super_group_" + sourceID
|
||||
case constant.NotificationChatType:
|
||||
return "notification_" + sourceID
|
||||
}
|
||||
|
@ -54,13 +54,13 @@ else
|
||||
fi
|
||||
|
||||
|
||||
#check=$(ps aux | grep -w ./${cron_task_name} | grep -v grep | wc -l)
|
||||
#if [ $check -ge 1 ]; then
|
||||
# echo -e ${GREEN_PREFIX}"none port has been listening,belongs service is openImCronTask"${COLOR_SUFFIX}
|
||||
#else
|
||||
# echo -e ${RED_PREFIX}"cron_task_name service does not start normally"${COLOR_SUFFIX}
|
||||
# echo -e ${RED_PREFIX}"please check ../logs/openIM.log "${COLOR_SUFFIX}
|
||||
# exit -1
|
||||
#fi
|
||||
#
|
||||
#echo -e ${YELLOW_PREFIX}"all services launch success"${COLOR_SUFFIX}
|
||||
check=$(ps aux | grep -w ./${cron_task_name} | grep -v grep | wc -l)
|
||||
if [ $check -ge 1 ]; then
|
||||
echo -e ${GREEN_PREFIX}"none port has been listening,belongs service is openImCronTask"${COLOR_SUFFIX}
|
||||
else
|
||||
echo -e ${RED_PREFIX}"cron_task_name service does not start normally"${COLOR_SUFFIX}
|
||||
echo -e ${RED_PREFIX}"please check ../logs/openIM.log "${COLOR_SUFFIX}
|
||||
exit -1
|
||||
fi
|
||||
|
||||
echo -e ${YELLOW_PREFIX}"all services launch success"${COLOR_SUFFIX}
|
||||
|
@ -1,12 +1,25 @@
|
||||
#!/usr/bin/env bash
|
||||
source ./style_info.cfg
|
||||
|
||||
echo -e "check time synchronize.................................."
|
||||
t=`curl http://time.akamai.com/?iso -s`
|
||||
t1=`date -d $t +%s`
|
||||
t2=`date +%s`
|
||||
let between=t2-t1
|
||||
if [[ $between -gt 10 ]] || [[ $between -lt -10 ]]; then
|
||||
echo -e ${RED_PREFIX}"Warning: The difference between the iso time and the server's time is too large: "$between"s" ${COLOR_SUFFIX}
|
||||
else
|
||||
echo -e ${GREEN_PREFIX} "ok: Server time is synchronized " ${COLOR_SUFFIX}
|
||||
fi
|
||||
|
||||
|
||||
|
||||
echo -e "check login user........................................"
|
||||
user=`whoami`
|
||||
if [ $user == "root" ] ; then
|
||||
echo -e ${GREEN_PREFIX} "ok: login user is root" ${COLOR_SUFFIX}
|
||||
echo -e ${GREEN_PREFIX} "ok: login user is root" ${COLOR_SUFFIX}
|
||||
else
|
||||
echo -e ${RED_PREFIX}"Warning: The current user is not root "${COLOR_SUFFIX}
|
||||
echo -e ${RED_PREFIX}"Warning: The current user is not root "${COLOR_SUFFIX}
|
||||
fi
|
||||
|
||||
|
||||
|
@ -10,7 +10,7 @@ need_to_start_server_shell=(
|
||||
sdk_svr_start.sh
|
||||
msg_gateway_start.sh
|
||||
demo_svr_start.sh
|
||||
# start_cron.sh
|
||||
start_cron.sh
|
||||
)
|
||||
time=`date +"%Y-%m-%d %H:%M:%S"`
|
||||
echo "==========================================================">>../logs/openIM.log 2>&1 &
|
||||
|
Loading…
x
Reference in New Issue
Block a user