merge newest branch

This commit is contained in:
Gordon
2021-11-11 18:47:21 +08:00
202 changed files with 1700 additions and 1149 deletions
+95
View File
@@ -0,0 +1,95 @@
package apiAuth
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbAuth "Open_IM/pkg/proto/auth"
"context"
"github.com/gin-gonic/gin"
"net/http"
"strings"
)
type paramsUserRegister struct {
Secret string `json:"secret" binding:"required,max=32"`
Platform int32 `json:"platform" binding:"required,min=1,max=7"`
UID string `json:"uid" binding:"required,min=1,max=64"`
Name string `json:"name" binding:"required,min=1,max=64"`
Icon string `json:"icon" binding:"omitempty,max=1024"`
Gender int32 `json:"gender" binding:"omitempty,oneof=0 1 2"`
Mobile string `json:"mobile" binding:"omitempty,max=32"`
Birth string `json:"birth" binding:"omitempty,max=16"`
Email string `json:"email" binding:"omitempty,max=64"`
Ex string `json:"ex" binding:"omitempty,max=1024"`
}
func newUserRegisterReq(params *paramsUserRegister) *pbAuth.UserRegisterReq {
pbData := pbAuth.UserRegisterReq{
UID: params.UID,
Name: params.Name,
Icon: params.Icon,
Gender: params.Gender,
Mobile: params.Mobile,
Birth: params.Birth,
Email: params.Email,
Ex: params.Ex,
}
return &pbData
}
func UserRegister(c *gin.Context) {
log.Info("", "", "api user_register init ....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImAuthName)
client := pbAuth.NewAuthClient(etcdConn)
//defer etcdConn.Close()
params := paramsUserRegister{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
return
}
if params.Secret != config.Config.Secret {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 401, "errMsg": "not authorized"})
return
}
pbData := newUserRegisterReq(&params)
log.Info("", "", "api user_register is server, [data: %s]", pbData.String())
reply, err := client.UserRegister(context.Background(), pbData)
if err != nil || !reply.Success {
log.Error("", "", "api user_register call rpc fail, [data: %s] [err: %s]", pbData.String(), err.Error())
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": err.Error()})
return
}
log.Info("", "", "api user_register call rpc success, [data: %s] [reply: %s]", pbData.String(), reply.String())
pbDataToken := &pbAuth.UserTokenReq{
Platform: params.Platform,
UID: params.UID,
}
replyToken, err := client.UserToken(context.Background(), pbDataToken)
if err != nil {
log.Error("", "", "api user_register call rpc fail, [data: %s] [err: %s]", pbData.String(), err.Error())
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": err.Error()})
return
}
log.Info("", "", "api user_register call success, [data: %s] [reply: %s]", pbData.String(), reply.String())
if replyToken.ErrCode == 0 {
c.JSON(http.StatusOK, gin.H{
"errCode": replyToken.ErrCode,
"errMsg": replyToken.ErrMsg,
"data": gin.H{
"uid": pbData.UID,
"token": replyToken.Token,
"expiredTime": replyToken.ExpiredTime,
},
})
} else {
c.JSON(http.StatusOK, gin.H{
"errCode": replyToken.ErrCode,
"errMsg": replyToken.ErrMsg,
})
}
}
+72
View File
@@ -0,0 +1,72 @@
package apiAuth
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbAuth "Open_IM/pkg/proto/auth"
"context"
"github.com/gin-gonic/gin"
"net/http"
"strings"
)
type paramsUserToken struct {
Secret string `json:"secret" binding:"required,max=32"`
Platform int32 `json:"platform" binding:"required,min=1,max=8"`
UID string `json:"uid" binding:"required,min=1,max=64"`
}
func newUserTokenReq(params *paramsUserToken) *pbAuth.UserTokenReq {
pbData := pbAuth.UserTokenReq{
Platform: params.Platform,
UID: params.UID,
}
return &pbData
}
func UserToken(c *gin.Context) {
log.Info("", "", "api user_token init ....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImAuthName)
client := pbAuth.NewAuthClient(etcdConn)
//defer etcdConn.Close()
params := paramsUserToken{}
if err := c.BindJSON(&params); err != nil {
log.Error("", "", params.UID, params.Platform, params.Secret)
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
return
}
if params.Secret != config.Config.Secret {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 401, "errMsg": "not authorized"})
return
}
pbData := newUserTokenReq(&params)
log.Info("", "", "api user_token is server, [data: %s]", pbData.String())
reply, err := client.UserToken(context.Background(), pbData)
if err != nil {
log.Error("", "", "api user_token call rpc fail, [data: %s] [err: %s]", pbData.String(), err.Error())
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": err.Error()})
return
}
log.Info("", "", "api user_token call rpc success, [data: %s] [reply: %s]", pbData.String(), reply.String())
if reply.ErrCode == 0 {
c.JSON(http.StatusOK, gin.H{
"errCode": reply.ErrCode,
"errMsg": reply.ErrMsg,
"data": gin.H{
"uid": pbData.UID,
"token": reply.Token,
"expiredTime": reply.ExpiredTime,
},
})
} else {
c.JSON(http.StatusOK, gin.H{
"errCode": reply.ErrCode,
"errMsg": reply.ErrMsg,
})
}
}
+60
View File
@@ -0,0 +1,60 @@
package apiChat
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbMsg "Open_IM/pkg/proto/chat"
"Open_IM/pkg/utils"
"context"
"github.com/gin-gonic/gin"
"net/http"
"strings"
)
type paramsUserNewestSeq struct {
ReqIdentifier int `json:"reqIdentifier" binding:"required"`
SendID string `json:"sendID" binding:"required"`
OperationID string `json:"operationID" binding:"required"`
MsgIncr int `json:"msgIncr" binding:"required"`
}
func UserGetSeq(c *gin.Context) {
params := paramsUserNewestSeq{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
return
}
token := c.Request.Header.Get("token")
if !utils.VerifyToken(token, params.SendID) {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": "token validate err"})
return
}
pbData := pbMsg.GetMaxAndMinSeqReq{}
pbData.UserID = params.SendID
pbData.OperationID = params.OperationID
grpcConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImOfflineMessageName)
if grpcConn == nil {
log.ErrorByKv("get grpcConn err", pbData.OperationID, "args", params)
}
msgClient := pbMsg.NewChatClient(grpcConn)
reply, err := msgClient.GetMaxAndMinSeq(context.Background(), &pbData)
if err != nil {
log.ErrorByKv("rpc call failed to getNewSeq", pbData.OperationID, "err", err, "pbData", pbData.String())
return
}
c.JSON(http.StatusOK, gin.H{
"errCode": reply.ErrCode,
"errMsg": reply.ErrMsg,
"msgIncr": params.MsgIncr,
"reqIdentifier": params.ReqIdentifier,
"data": gin.H{
"maxSeq": reply.MaxSeq,
"minSeq": reply.MinSeq,
},
})
}
+127
View File
@@ -0,0 +1,127 @@
package apiChat
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
"Open_IM/pkg/proto/chat"
"Open_IM/pkg/utils"
"context"
"github.com/gin-gonic/gin"
"net/http"
"strings"
)
type paramsUserPullMsg struct {
ReqIdentifier *int `json:"reqIdentifier" binding:"required"`
SendID string `json:"sendID" binding:"required"`
OperationID string `json:"operationID" binding:"required"`
Data struct {
SeqBegin *int64 `json:"seqBegin" binding:"required"`
SeqEnd *int64 `json:"seqEnd" binding:"required"`
}
}
func UserPullMsg(c *gin.Context) {
params := paramsUserPullMsg{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
return
}
token := c.Request.Header.Get("token")
if !utils.VerifyToken(token, params.SendID) {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": "token validate err"})
return
}
pbData := pbChat.PullMessageReq{}
pbData.UserID = params.SendID
pbData.OperationID = params.OperationID
pbData.SeqBegin = *params.Data.SeqBegin
pbData.SeqEnd = *params.Data.SeqEnd
grpcConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImOfflineMessageName)
msgClient := pbChat.NewChatClient(grpcConn)
reply, err := msgClient.PullMessage(context.Background(), &pbData)
if err != nil {
log.ErrorByKv("PullMessage error", pbData.OperationID, "err", err.Error())
return
}
log.InfoByKv("rpc call success to pullMsgRep", pbData.OperationID, "ReplyArgs", reply.String(), "maxSeq", reply.GetMaxSeq(),
"MinSeq", reply.GetMinSeq(), "singLen", len(reply.GetSingleUserMsg()), "groupLen", len(reply.GetGroupUserMsg()))
msg := make(map[string]interface{})
if v := reply.GetSingleUserMsg(); v != nil {
msg["single"] = v
} else {
msg["single"] = []pbChat.GatherFormat{}
}
if v := reply.GetGroupUserMsg(); v != nil {
msg["group"] = v
} else {
msg["group"] = []pbChat.GatherFormat{}
}
msg["maxSeq"] = reply.GetMaxSeq()
msg["minSeq"] = reply.GetMinSeq()
c.JSON(http.StatusOK, gin.H{
"errCode": reply.ErrCode,
"errMsg": reply.ErrMsg,
"reqIdentifier": *params.ReqIdentifier,
"data": msg,
})
}
type paramsUserPullMsgBySeqList struct {
ReqIdentifier int `json:"reqIdentifier" binding:"required"`
SendID string `json:"sendID" binding:"required"`
OperationID string `json:"operationID" binding:"required"`
SeqList []int64 `json:"seqList"`
}
func UserPullMsgBySeqList(c *gin.Context) {
params := paramsUserPullMsgBySeqList{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
return
}
token := c.Request.Header.Get("token")
if !utils.VerifyToken(token, params.SendID) {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": "token validate err"})
return
}
pbData := pbChat.PullMessageBySeqListReq{}
pbData.UserID = params.SendID
pbData.OperationID = params.OperationID
pbData.SeqList = params.SeqList
grpcConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImOfflineMessageName)
msgClient := pbChat.NewChatClient(grpcConn)
reply, err := msgClient.PullMessageBySeqList(context.Background(), &pbData)
if err != nil {
log.ErrorByKv("PullMessageBySeqList error", pbData.OperationID, "err", err.Error())
return
}
log.InfoByKv("rpc call success to PullMessageBySeqList", pbData.OperationID, "ReplyArgs", reply.String(), "maxSeq", reply.GetMaxSeq(),
"MinSeq", reply.GetMinSeq(), "singLen", len(reply.GetSingleUserMsg()), "groupLen", len(reply.GetGroupUserMsg()))
msg := make(map[string]interface{})
if v := reply.GetSingleUserMsg(); v != nil {
msg["single"] = v
} else {
msg["single"] = []pbChat.GatherFormat{}
}
if v := reply.GetGroupUserMsg(); v != nil {
msg["group"] = v
} else {
msg["group"] = []pbChat.GatherFormat{}
}
msg["maxSeq"] = reply.GetMaxSeq()
msg["minSeq"] = reply.GetMinSeq()
c.JSON(http.StatusOK, gin.H{
"errCode": reply.ErrCode,
"errMsg": reply.ErrMsg,
"reqIdentifier": params.ReqIdentifier,
"data": msg,
})
}
+94
View File
@@ -0,0 +1,94 @@
package apiChat
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
pbChat "Open_IM/pkg/proto/chat"
"Open_IM/pkg/utils"
"context"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
"github.com/gin-gonic/gin"
"net/http"
"strings"
)
type paramsUserSendMsg struct {
ReqIdentifier int32 `json:"reqIdentifier" binding:"required"`
PlatformID int32 `json:"platformID" binding:"required"`
SendID string `json:"sendID" binding:"required"`
SenderNickName string `json:"senderNickName"`
SenderFaceURL string `json:"senderFaceUrl"`
OperationID string `json:"operationID" binding:"required"`
Data struct {
SessionType int32 `json:"sessionType" binding:"required"`
MsgFrom int32 `json:"msgFrom" binding:"required"`
ContentType int32 `json:"contentType" binding:"required"`
RecvID string `json:"recvID" binding:"required"`
ForceList []string `json:"forceList"`
Content string `json:"content" binding:"required"`
Options map[string]interface{} `json:"options" `
ClientMsgID string `json:"clientMsgID" binding:"required"`
OffLineInfo map[string]interface{} `json:"offlineInfo" `
Ex map[string]interface{} `json:"ext"`
}
}
func newUserSendMsgReq(token string, params *paramsUserSendMsg) *pbChat.UserSendMsgReq {
pbData := pbChat.UserSendMsgReq{
ReqIdentifier: params.ReqIdentifier,
Token: token,
SendID: params.SendID,
SenderNickName: params.SenderNickName,
SenderFaceURL: params.SenderFaceURL,
OperationID: params.OperationID,
PlatformID: params.PlatformID,
SessionType: params.Data.SessionType,
MsgFrom: params.Data.MsgFrom,
ContentType: params.Data.ContentType,
RecvID: params.Data.RecvID,
ForceList: params.Data.ForceList,
Content: params.Data.Content,
Options: utils.MapToJsonString(params.Data.Options),
ClientMsgID: params.Data.ClientMsgID,
OffLineInfo: utils.MapToJsonString(params.Data.OffLineInfo),
Ex: utils.MapToJsonString(params.Data.Ex),
}
return &pbData
}
func UserSendMsg(c *gin.Context) {
params := paramsUserSendMsg{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
log.ErrorByKv("json unmarshal err", "", "err", err.Error(), "data", c.PostForm("data"))
return
}
token := c.Request.Header.Get("token")
log.InfoByKv("api call success to sendMsgReq", params.OperationID, "Parameters", params)
pbData := newUserSendMsgReq(token, &params)
log.Info("", "", "api UserSendMsg call start..., [data: %s]", pbData.String())
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImOfflineMessageName)
client := pbChat.NewChatClient(etcdConn)
log.Info("", "", "api UserSendMsg call, api call rpc...")
reply, _ := client.UserSendMsg(context.Background(), pbData)
log.Info("", "", "api UserSendMsg call end..., [data: %s] [reply: %s]", pbData.String(), reply.String())
c.JSON(http.StatusOK, gin.H{
"errCode": reply.ErrCode,
"errMsg": reply.ErrMsg,
"reqIdentifier": reply.ReqIdentifier,
"data": gin.H{
"clientMsgID": reply.ClientMsgID,
"serverMsgID": reply.ServerMsgID,
"sendTime": reply.SendTime,
},
})
}
+49
View File
@@ -0,0 +1,49 @@
package friend
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbFriend "Open_IM/pkg/proto/friend"
"context"
"github.com/gin-gonic/gin"
"net/http"
"strings"
)
/*
type paramsAddBlackList struct {
OperationID string `json:"operationID" binding:"required"`
UID string `json:"uid" binding:"required"`
}*/
func AddBlacklist(c *gin.Context) {
log.Info("", "", "api add blacklist init ....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImFriendName)
client := pbFriend.NewFriendClient(etcdConn)
//defer etcdConn.Close()
params := paramsSearchFriend{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
return
}
req := &pbFriend.AddBlacklistReq{
Uid: params.UID,
OperationID: params.OperationID,
Token: c.Request.Header.Get("token"),
OwnerUid: params.OwnerUid,
}
log.Info(req.Token, req.OperationID, "api add blacklist is server:userID=%s", req.Uid)
RpcResp, err := client.AddBlacklist(context.Background(), req)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,call add blacklist rpc server failed", err)
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": "call add blacklist rpc server failed"})
return
}
log.InfoByArgs("call add blacklist rpc server success,args=%s", RpcResp.String())
resp := gin.H{"errCode": RpcResp.ErrorCode, "errMsg": RpcResp.ErrorMsg}
c.JSON(http.StatusOK, resp)
log.InfoByArgs("api add blacklist success return,get args=%s,return args=%s", req.String(), RpcResp.String())
}
+86
View File
@@ -0,0 +1,86 @@
package friend
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbFriend "Open_IM/pkg/proto/friend"
"context"
"github.com/gin-gonic/gin"
"net/http"
"strings"
)
type paramsImportFriendReq struct {
OperationID string `json:"operationID" binding:"required"`
UIDList []string `json:"uidList" binding:"required"`
OwnerUid string `json:"ownerUid" binding:"required"`
}
type paramsAddFriend struct {
OperationID string `json:"operationID" binding:"required"`
UID string `json:"uid" binding:"required"`
ReqMessage string `json:"reqMessage"`
}
//
func ImportFriend(c *gin.Context) {
log.Info("", "", "ImportFriend init ....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImFriendName)
client := pbFriend.NewFriendClient(etcdConn)
params := paramsImportFriendReq{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
return
}
req := &pbFriend.ImportFriendReq{
UidList: params.UIDList,
OperationID: params.OperationID,
OwnerUid: params.OwnerUid,
Token: c.Request.Header.Get("token"),
}
log.ErrorByKv("ImportFriend Test start", params.OperationID)
RpcResp, err := client.ImportFriend(context.Background(), req)
//log.ErrorByKv("ImportFriend Test end", params.OperationID, "resp", RpcResp, "err", err.Error())
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,ImportFriend failed", err)
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": "cImportFriend failed" + err.Error()})
return
}
log.InfoByArgs("ImportFriend success,args=%s", RpcResp.String())
resp := gin.H{"errCode": RpcResp.CommonResp.ErrorCode, "errMsg": RpcResp.CommonResp.ErrorMsg, "failedUidList": RpcResp.FailedUidList}
c.JSON(http.StatusOK, resp)
log.InfoByArgs("ImportFriend success return,get args=%s,return args=%s", req.String(), RpcResp.String())
}
func AddFriend(c *gin.Context) {
log.Info("", "", "api add friend init ....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImFriendName)
client := pbFriend.NewFriendClient(etcdConn)
params := paramsAddFriend{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
return
}
req := &pbFriend.AddFriendReq{
Uid: params.UID,
OperationID: params.OperationID,
ReqMessage: params.ReqMessage,
Token: c.Request.Header.Get("token"),
}
log.Info(req.Token, req.OperationID, "api add friend is server")
RpcResp, err := client.AddFriend(context.Background(), req)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,call add friend rpc server failed", err)
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": "call add friend rpc server failed"})
return
}
log.InfoByArgs("call add friend rpc server success,args=%s", RpcResp.String())
resp := gin.H{"errCode": RpcResp.ErrorCode, "errMsg": RpcResp.ErrorMsg}
c.JSON(http.StatusOK, resp)
log.InfoByArgs("api add friend success return,get args=%s,return args=%s", req.String(), RpcResp.String())
}
@@ -0,0 +1,49 @@
package friend
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbFriend "Open_IM/pkg/proto/friend"
"context"
"fmt"
"github.com/gin-gonic/gin"
"net/http"
"strings"
)
type paramsAddFriendResponse struct {
OperationID string `json:"operationID" binding:"required"`
UID string `json:"uid" binding:"required"`
Flag int32 `json:"flag" binding:"required"`
}
func AddFriendResponse(c *gin.Context) {
log.Info("", "", fmt.Sprintf("api add friend response init ...."))
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImFriendName)
client := pbFriend.NewFriendClient(etcdConn)
//defer etcdConn.Close()
params := paramsAddFriendResponse{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
return
}
req := &pbFriend.AddFriendResponseReq{
Uid: params.UID,
Flag: params.Flag,
OperationID: params.OperationID,
Token: c.Request.Header.Get("token"),
}
log.Info(req.Token, req.OperationID, "api add friend response is server:userID=%s", req.Uid)
RpcResp, err := client.AddFriendResponse(context.Background(), req)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,call add_friend_response rpc server failed", err)
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": "call add_friend_response rpc server failed"})
return
}
log.InfoByArgs("call add friend response rpc server success,args=%s", RpcResp.String())
c.JSON(http.StatusOK, gin.H{"errCode": RpcResp.ErrorCode, "errMsg": RpcResp.ErrorMsg})
log.InfoByArgs("api add friend response success return,get args=%s,return args=%s", req.String(), RpcResp.String())
}
+48
View File
@@ -0,0 +1,48 @@
package friend
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbFriend "Open_IM/pkg/proto/friend"
"context"
"fmt"
"github.com/gin-gonic/gin"
"net/http"
"strings"
)
type paramsDeleteFriend struct {
OperationID string `json:"operationID" binding:"required"`
UID string `json:"uid" binding:"required"`
}
func DeleteFriend(c *gin.Context) {
log.Info("", "", fmt.Sprintf("api delete_friend init ...."))
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImFriendName)
client := pbFriend.NewFriendClient(etcdConn)
//defer etcdConn.Close()
params := paramsDeleteFriend{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
return
}
req := &pbFriend.DeleteFriendReq{
Uid: params.UID,
OperationID: params.OperationID,
Token: c.Request.Header.Get("token"),
}
log.Info(req.Token, req.OperationID, "api delete_friend is server:%s", req.Uid)
RpcResp, err := client.DeleteFriend(context.Background(), req)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,call delete_friend rpc server failed", err)
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": "call delete_friend rpc server failed"})
return
}
log.InfoByArgs("call delete_friend rpc server,args=%s", RpcResp.String())
resp := gin.H{"errCode": RpcResp.ErrorCode, "errMsg": RpcResp.ErrorMsg}
c.JSON(http.StatusOK, resp)
log.InfoByArgs("api delete_friend success return,get args=%s,return args=%s", req.String(), RpcResp.String())
}
+79
View File
@@ -0,0 +1,79 @@
package friend
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbFriend "Open_IM/pkg/proto/friend"
"context"
"fmt"
"github.com/gin-gonic/gin"
"net/http"
"strings"
)
type paramsGetBlackList struct {
OperationID string `json:"operationID" binding:"required"`
}
type blackListUserInfo struct {
UID string `json:"uid"`
Name string `json:"name"`
Icon string `json:"icon"`
Gender int32 `json:"gender"`
Mobile string `json:"mobile"`
Birth string `json:"birth"`
Email string `json:"email"`
Ex string `json:"ex"`
}
func GetBlacklist(c *gin.Context) {
log.Info("", "", "api get blacklist init ....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImFriendName)
client := pbFriend.NewFriendClient(etcdConn)
//defer etcdConn.Close()
params := paramsGetBlackList{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
return
}
req := &pbFriend.GetBlacklistReq{
OperationID: params.OperationID,
Token: c.Request.Header.Get("token"),
}
log.Info(req.Token, req.OperationID, fmt.Sprintf("api get blacklist is server"))
RpcResp, err := client.GetBlacklist(context.Background(), req)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,call get_friend_list rpc server failed", err)
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": "call get blacklist rpc server failed"})
return
}
log.InfoByArgs("call get blacklist rpc server success,args=%s", RpcResp.String())
if RpcResp.ErrorCode == 0 {
userBlackList := make([]blackListUserInfo, 0)
for _, friend := range RpcResp.Data {
var fi blackListUserInfo
fi.UID = friend.Uid
fi.Name = friend.Name
fi.Icon = friend.Icon
fi.Gender = friend.Gender
fi.Mobile = friend.Mobile
fi.Birth = friend.Birth
fi.Email = friend.Email
fi.Ex = friend.Ex
userBlackList = append(userBlackList, fi)
}
resp := gin.H{
"errCode": RpcResp.ErrorCode,
"errMsg": RpcResp.ErrorMsg,
"data": userBlackList,
}
c.JSON(http.StatusOK, resp)
} else {
resp := gin.H{"errCode": RpcResp.ErrorCode, "errMsg": RpcResp.ErrorMsg}
c.JSON(http.StatusOK, resp)
}
log.InfoByArgs("api get black list success return,get args=%s,return=%s", req.String(), RpcResp.String())
}
@@ -0,0 +1,129 @@
package friend
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbFriend "Open_IM/pkg/proto/friend"
"context"
"github.com/gin-gonic/gin"
"net/http"
"strings"
)
type paramsGetApplyList struct {
OperationID string `json:"operationID" binding:"required"`
}
type UserInfo struct {
UID string `json:"uid"`
Name string `json:"name"`
Icon string `json:"icon"`
Gender int32 `json:"gender"`
Mobile string `json:"mobile"`
Birth string `json:"birth"`
Email string `json:"email"`
Ex string `json:"ex"`
ReqMessage string `json:"reqMessage"`
ApplyTime string `json:"applyTime"`
Flag int32 `json:"flag"`
}
func GetFriendApplyList(c *gin.Context) {
log.Info("", "", "api get_friend_apply_list init ....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImFriendName)
client := pbFriend.NewFriendClient(etcdConn)
//defer etcdConn.Close()
params := paramsGetApplyList{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
return
}
req := &pbFriend.GetFriendApplyReq{
OperationID: params.OperationID,
Token: c.Request.Header.Get("token"),
}
log.Info(req.Token, req.OperationID, "api get friend apply list is server")
RpcResp, err := client.GetFriendApplyList(context.Background(), req)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,call get friend apply list rpc server failed", err)
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": "call get friend apply list rpc server failed"})
return
}
log.InfoByArgs("call get friend apply list rpc server success,args=%s", RpcResp.String())
if RpcResp.ErrorCode == 0 {
userInfoList := make([]UserInfo, 0)
for _, applyUserinfo := range RpcResp.Data {
var un UserInfo
un.UID = applyUserinfo.Uid
un.Name = applyUserinfo.Name
un.Icon = applyUserinfo.Icon
un.Gender = applyUserinfo.Gender
un.Mobile = applyUserinfo.Mobile
un.Birth = applyUserinfo.Birth
un.Email = applyUserinfo.Email
un.Ex = applyUserinfo.Ex
un.Flag = applyUserinfo.Flag
un.ApplyTime = applyUserinfo.ApplyTime
un.ReqMessage = applyUserinfo.ReqMessage
userInfoList = append(userInfoList, un)
}
resp := gin.H{"errCode": RpcResp.ErrorCode, "errMsg": RpcResp.ErrorMsg, "data": userInfoList}
c.JSON(http.StatusOK, resp)
} else {
resp := gin.H{"errCode": RpcResp.ErrorCode, "errMsg": RpcResp.ErrorMsg}
c.JSON(http.StatusOK, resp)
}
log.InfoByArgs("api get friend apply list success return,get args=%s,return args=%s", req.String(), RpcResp.String())
}
func GetSelfApplyList(c *gin.Context) {
log.Info("", "", "api get self friend apply list init ....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImFriendName)
client := pbFriend.NewFriendClient(etcdConn)
//defer etcdConn.Close()
params := paramsGetApplyList{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
return
}
req := &pbFriend.GetFriendApplyReq{
OperationID: params.OperationID,
Token: c.Request.Header.Get("token"),
}
log.Info(req.Token, req.OperationID, "api get self apply list is server")
RpcResp, err := client.GetSelfApplyList(context.Background(), req)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,call get self apply list rpc server failed", err)
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": "call get self apply list rpc server failed"})
return
}
log.InfoByArgs("call get self apply list rpc server success,args=%s", RpcResp.String())
if RpcResp.ErrorCode == 0 {
userInfoList := make([]UserInfo, 0)
for _, selfApplyOtherUserinfo := range RpcResp.Data {
var un UserInfo
un.UID = selfApplyOtherUserinfo.Uid
un.Name = selfApplyOtherUserinfo.Name
un.Icon = selfApplyOtherUserinfo.Icon
un.Gender = selfApplyOtherUserinfo.Gender
un.Mobile = selfApplyOtherUserinfo.Mobile
un.Birth = selfApplyOtherUserinfo.Birth
un.Email = selfApplyOtherUserinfo.Email
un.Ex = selfApplyOtherUserinfo.Ex
un.Flag = selfApplyOtherUserinfo.Flag
un.ApplyTime = selfApplyOtherUserinfo.ApplyTime
un.ReqMessage = selfApplyOtherUserinfo.ReqMessage
userInfoList = append(userInfoList, un)
}
resp := gin.H{"errCode": RpcResp.ErrorCode, "errMsg": RpcResp.ErrorMsg, "data": userInfoList}
c.JSON(http.StatusOK, resp)
} else {
resp := gin.H{"errCode": RpcResp.ErrorCode, "errMsg": RpcResp.ErrorMsg}
c.JSON(http.StatusOK, resp)
}
log.InfoByArgs("api get self apply list success return,get args=%s,return args=%s", req.String(), RpcResp.String())
}
+83
View File
@@ -0,0 +1,83 @@
package friend
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbFriend "Open_IM/pkg/proto/friend"
"context"
"fmt"
"github.com/gin-gonic/gin"
"net/http"
"strings"
)
type paramsGetFriendLIst struct {
OperationID string `json:"operationID" binding:"required"`
}
type friendInfo struct {
UID string `json:"uid"`
Name string `json:"name"`
Icon string `json:"icon"`
Gender int32 `json:"gender"`
Mobile string `json:"mobile"`
Birth string `json:"birth"`
Email string `json:"email"`
Ex string `json:"ex"`
Comment string `json:"comment"`
IsInBlackList int32 `json:"isInBlackList"`
}
func GetFriendList(c *gin.Context) {
log.Info("", "", fmt.Sprintf("api get_friendlist init ...."))
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImFriendName)
client := pbFriend.NewFriendClient(etcdConn)
//defer etcdConn.Close()
params := paramsGetFriendLIst{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
return
}
req := &pbFriend.GetFriendListReq{
OperationID: params.OperationID,
Token: c.Request.Header.Get("token"),
}
log.Info(req.Token, req.OperationID, "api get friend list is server")
RpcResp, err := client.GetFriendList(context.Background(), req)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,call get friend list rpc server failed", err)
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": "call get friend list rpc server failed"})
return
}
log.InfoByArgs("call get friend list rpc server success,args=%s", RpcResp.String())
if RpcResp.ErrorCode == 0 {
friendsInfo := make([]friendInfo, 0)
for _, friend := range RpcResp.Data {
var fi friendInfo
fi.UID = friend.Uid
fi.Name = friend.Name
fi.Icon = friend.Icon
fi.Gender = friend.Gender
fi.Mobile = friend.Mobile
fi.Birth = friend.Birth
fi.Email = friend.Email
fi.Ex = friend.Ex
fi.Comment = friend.Comment
fi.IsInBlackList = friend.IsInBlackList
friendsInfo = append(friendsInfo, fi)
}
resp := gin.H{
"errCode": RpcResp.ErrorCode,
"errMsg": RpcResp.ErrorMsg,
"data": friendsInfo,
}
c.JSON(http.StatusOK, resp)
} else {
resp := gin.H{"errCode": RpcResp.ErrorCode, "errMsg": RpcResp.ErrorMsg}
c.JSON(http.StatusOK, resp)
}
log.InfoByArgs("api get friend list success return,get args=%s,return=%s", req.String(), RpcResp.String())
}
+70
View File
@@ -0,0 +1,70 @@
package friend
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbFriend "Open_IM/pkg/proto/friend"
"context"
"fmt"
"github.com/gin-gonic/gin"
"net/http"
"strings"
)
type paramsSearchFriend struct {
OperationID string `json:"operationID" binding:"required"`
UID string `json:"uid" binding:"required"`
OwnerUid string `json:"ownerUid"`
}
func GetFriendsInfo(c *gin.Context) {
log.Info("", "", fmt.Sprintf("api search friend init ...."))
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImFriendName)
client := pbFriend.NewFriendClient(etcdConn)
//defer etcdConn.Close()
params := paramsSearchFriend{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
return
}
req := &pbFriend.GetFriendsInfoReq{
Uid: params.UID,
OperationID: params.OperationID,
Token: c.Request.Header.Get("token"),
}
log.Info(req.Token, req.OperationID, "api search_friend is server")
RpcResp, err := client.GetFriendsInfo(context.Background(), req)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,call search friend rpc server failed", err)
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": "call search friend rpc server failed"})
return
}
log.InfoByArgs("call search friend rpc server success,args=%s", RpcResp.String())
if RpcResp.ErrorCode == 0 {
resp := gin.H{
"errCode": RpcResp.ErrorCode,
"errMsg": RpcResp.ErrorMsg,
"data": gin.H{
"uid": RpcResp.Data.Uid,
"icon": RpcResp.Data.Icon,
"name": RpcResp.Data.Name,
"gender": RpcResp.Data.Gender,
"mobile": RpcResp.Data.Mobile,
"birth": RpcResp.Data.Birth,
"email": RpcResp.Data.Email,
"ex": RpcResp.Data.Ex,
"comment": RpcResp.Data.Comment,
},
}
c.JSON(http.StatusOK, resp)
} else {
resp := gin.H{
"errCode": RpcResp.ErrorCode,
"errMsg": RpcResp.ErrorMsg,
}
c.JSON(http.StatusOK, resp)
}
log.InfoByArgs("api search_friend success return,get args=%s,return=%s", req.String(), RpcResp.String())
}
+47
View File
@@ -0,0 +1,47 @@
package friend
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbFriend "Open_IM/pkg/proto/friend"
"context"
"github.com/gin-gonic/gin"
"net/http"
"strings"
)
type paramsIsFriend struct {
OperationID string `json:"operationID" binding:"required"`
ReceiveUid string `json:"receive_uid"`
}
func IsFriend(c *gin.Context) {
log.Info("", "", "api is friend init....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImFriendName)
client := pbFriend.NewFriendClient(etcdConn)
//defer etcdConn.Close()
params := paramsIsFriend{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
return
}
req := &pbFriend.IsFriendReq{
OperationID: params.OperationID,
ReceiveUid: params.OperationID,
Token: c.Request.Header.Get("token"),
}
log.Info(req.Token, req.OperationID, "api is friend is server")
RpcResp, err := client.IsFriend(context.Background(), req)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,call add friend rpc server failed", err)
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": "call add friend rpc server failed"})
return
}
log.InfoByArgs("call is friend rpc server success,args=%s", RpcResp.String())
resp := gin.H{"errCode": RpcResp.ErrorCode, "errMsg": RpcResp.ErrorMsg, "isFriend": RpcResp.ShipType}
c.JSON(http.StatusOK, resp)
log.InfoByArgs("api is friend success return,get args=%s,return args=%s", req.String(), RpcResp.String())
}
+47
View File
@@ -0,0 +1,47 @@
package friend
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbFriend "Open_IM/pkg/proto/friend"
"context"
"github.com/gin-gonic/gin"
"net/http"
"strings"
)
type paramsRemoveBlackList struct {
OperationID string `json:"operationID" binding:"required"`
UID string `json:"uid" binding:"required"`
}
func RemoveBlacklist(c *gin.Context) {
log.Info("", "", "api remove_blacklist init ....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImFriendName)
client := pbFriend.NewFriendClient(etcdConn)
//defer etcdConn.Close()
params := paramsRemoveBlackList{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
return
}
req := &pbFriend.RemoveBlacklistReq{
Uid: params.UID,
OperationID: params.OperationID,
Token: c.Request.Header.Get("token"),
}
log.Info(req.Token, req.OperationID, "api remove blacklist is server:userID=%s", req.Uid)
RpcResp, err := client.RemoveBlacklist(context.Background(), req)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,call remove blacklist rpc server failed", err)
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": "call remove blacklist rpc server failed"})
return
}
log.InfoByArgs("call remove blacklist rpc server success,args=%s", RpcResp.String())
resp := gin.H{"errCode": RpcResp.ErrorCode, "errMsg": RpcResp.ErrorMsg}
c.JSON(http.StatusOK, resp)
log.InfoByArgs("api remove blacklist success return,get args=%s,return args=%s", req.String(), RpcResp.String())
}
+48
View File
@@ -0,0 +1,48 @@
package friend
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbFriend "Open_IM/pkg/proto/friend"
"context"
"github.com/gin-gonic/gin"
"net/http"
"strings"
)
type paramsSetFriendComment struct {
OperationID string `json:"operationID" binding:"required"`
UID string `json:"uid" binding:"required"`
Comment string `json:"comment"`
}
func SetFriendComment(c *gin.Context) {
log.Info("", "", "api set friend comment init ....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImFriendName)
client := pbFriend.NewFriendClient(etcdConn)
//defer etcdConn.Close()
params := paramsSetFriendComment{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
return
}
req := &pbFriend.SetFriendCommentReq{
Uid: params.UID,
OperationID: params.OperationID,
Comment: params.Comment,
Token: c.Request.Header.Get("token"),
}
log.Info(req.Token, req.OperationID, "api set friend comment is server")
RpcResp, err := client.SetFriendComment(context.Background(), req)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,call set friend comment rpc server failed", err)
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": "call set friend comment rpc server failed"})
return
}
log.Info("", "", "call set friend comment rpc server success,args=%s", RpcResp.String())
c.JSON(http.StatusOK, gin.H{"errCode": RpcResp.ErrorCode, "errMsg": RpcResp.ErrorMsg})
log.Info("", "", "api set friend comment success return,get args=%s,return args=%s", req.String(), RpcResp.String())
}
+61
View File
@@ -0,0 +1,61 @@
package group
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pb "Open_IM/pkg/proto/group"
"context"
"github.com/gin-gonic/gin"
"net/http"
"strings"
)
type paramsCreateGroupStruct struct {
MemberList []*pb.GroupAddMemberInfo `json:"memberList"`
GroupName string `json:"groupName"`
Introduction string `json:"introduction"`
Notification string `json:"notification"`
FaceUrl string `json:"faceUrl"`
OperationID string `json:"operationID" binding:"required"`
Ex string `json:"ex"`
}
func CreateGroup(c *gin.Context) {
log.Info("", "", "api create group init ....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImGroupName)
client := pb.NewGroupClient(etcdConn)
//defer etcdConn.Close()
params := paramsCreateGroupStruct{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
return
}
req := &pb.CreateGroupReq{
MemberList: params.MemberList,
GroupName: params.GroupName,
Introduction: params.Introduction,
Notification: params.Notification,
FaceUrl: params.FaceUrl,
OperationID: params.OperationID,
Ex: params.Ex,
Token: c.Request.Header.Get("token"),
}
log.Info(req.Token, req.OperationID, "api create group is server,params=%s", req.String())
RpcResp, err := client.CreateGroup(context.Background(), req)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,call create group rpc server failed", err.Error())
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": "call rpc server failed"})
return
}
log.InfoByArgs("call create group rpc server success,args=%s", RpcResp.String())
if RpcResp.ErrorCode == 0 {
resp := gin.H{"errCode": RpcResp.ErrorCode, "errMsg": RpcResp.ErrorMsg, "data": gin.H{"groupID": RpcResp.GroupID}}
c.JSON(http.StatusOK, resp)
} else {
c.JSON(http.StatusOK, gin.H{"errCode": RpcResp.ErrorCode, "errMsg": RpcResp.ErrorMsg})
}
log.InfoByArgs("api create group success return,get args=%s,return args=%s", req.String(), RpcResp.String())
}
@@ -0,0 +1,113 @@
package group
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
"Open_IM/pkg/proto/group"
"Open_IM/pkg/utils"
"context"
"github.com/gin-gonic/gin"
"net/http"
"strings"
)
type paramsGroupApplicationList struct {
OperationID string `json:"operationID" binding:"required"`
}
func newUserRegisterReq(params *paramsGroupApplicationList) *group.GetGroupApplicationListReq {
pbData := group.GetGroupApplicationListReq{
OperationID: params.OperationID,
}
return &pbData
}
type paramsGroupApplicationListRet struct {
ID string `json:"id"`
GroupID string `json:"groupID"`
FromUserID string `json:"fromUserID"`
ToUserID string `json:"toUserID"`
Flag int32 `json:"flag"`
RequestMsg string `json:"reqMsg"`
HandledMsg string `json:"handledMsg"`
AddTime int64 `json:"createTime"`
FromUserNickname string `json:"fromUserNickName"`
ToUserNickname string `json:"toUserNickName"`
FromUserFaceUrl string `json:"fromUserFaceURL"`
ToUserFaceUrl string `json:"toUserFaceURL"`
HandledUser string `json:"handledUser"`
Type int32 `json:"type"`
HandleStatus int32 `json:"handleStatus"`
HandleResult int32 `json:"handleResult"`
}
func GetGroupApplicationList(c *gin.Context) {
log.Info("", "", "api GetGroupApplicationList init ....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImGroupName)
client := group.NewGroupClient(etcdConn)
//defer etcdConn.Close()
params := paramsGroupApplicationList{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
return
}
pbData := newUserRegisterReq(&params)
token := c.Request.Header.Get("token")
if claims, err := utils.ParseToken(token); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": "token validate err"})
return
} else {
pbData.UID = claims.UID
}
log.Info("", "", "api GetGroupApplicationList is server, [data: %s]", pbData.String())
reply, err := client.GetGroupApplicationList(context.Background(), pbData)
if err != nil {
log.Error("", "", "api GetGroupApplicationList call rpc fail, [data: %s] [err: %s]", pbData.String(), err.Error())
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": err.Error()})
return
}
log.Info("", "", "api GetGroupApplicationList call rpc success, [data: %s] [reply: %s]", pbData.String(), reply.String())
unProcessCount := 0
userReq := make([]paramsGroupApplicationListRet, 0)
if reply != nil && reply.Data != nil && reply.Data.User != nil {
for i := 0; i < len(reply.Data.User); i++ {
req := paramsGroupApplicationListRet{}
req.ID = reply.Data.User[i].ID
req.GroupID = reply.Data.User[i].GroupID
req.FromUserID = reply.Data.User[i].FromUserID
req.ToUserID = reply.Data.User[i].ToUserID
req.Flag = reply.Data.User[i].Flag
req.RequestMsg = reply.Data.User[i].RequestMsg
req.HandledMsg = reply.Data.User[i].HandledMsg
req.AddTime = reply.Data.User[i].AddTime
req.FromUserNickname = reply.Data.User[i].FromUserNickname
req.ToUserNickname = reply.Data.User[i].ToUserNickname
req.FromUserFaceUrl = reply.Data.User[i].FromUserFaceUrl
req.ToUserFaceUrl = reply.Data.User[i].ToUserFaceUrl
req.HandledUser = reply.Data.User[i].HandledUser
req.Type = reply.Data.User[i].Type
req.HandleStatus = reply.Data.User[i].HandleStatus
req.HandleResult = reply.Data.User[i].HandleResult
userReq = append(userReq, req)
if req.Flag == 0 {
unProcessCount++
}
}
}
c.JSON(http.StatusOK, gin.H{
"errCode": reply.ErrCode,
"errMsg": reply.ErrMsg,
"data": gin.H{
"count": unProcessCount,
"user": userReq,
},
})
}
+67
View File
@@ -0,0 +1,67 @@
package group
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pb "Open_IM/pkg/proto/group"
"context"
"github.com/gin-gonic/gin"
"net/http"
"strings"
)
type paramsGetGroupInfo struct {
GroupIDList []string `json:"groupIDList" binding:"required"`
OperationID string `json:"operationID" binding:"required"`
}
func GetGroupsInfo(c *gin.Context) {
log.Info("", "", "api get groups info init ....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImGroupName)
client := pb.NewGroupClient(etcdConn)
//defer etcdConn.Close()
params := paramsGetGroupInfo{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
return
}
req := &pb.GetGroupsInfoReq{
GroupIDList: params.GroupIDList,
Token: c.Request.Header.Get("token"),
OperationID: params.OperationID,
}
log.Info(req.Token, req.OperationID, "get groups info is server,params=%s", req.String())
RpcResp, err := client.GetGroupsInfo(context.Background(), req)
if err != nil {
log.Error(req.Token, req.OperationID, "call get groups info rpc server failed,err=%s", err.Error())
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": "call rpc server failed"})
return
}
log.InfoByArgs("call get groups info rpc server success", RpcResp.String())
if RpcResp.ErrorCode == 0 {
groupsInfo := make([]pb.GroupInfo, 0)
for _, v := range RpcResp.Data {
var groupInfo pb.GroupInfo
groupInfo.GroupId = v.GroupId
groupInfo.GroupName = v.GroupName
groupInfo.Notification = v.Notification
groupInfo.Introduction = v.Introduction
groupInfo.FaceUrl = v.FaceUrl
groupInfo.CreateTime = v.CreateTime
groupInfo.OwnerId = v.OwnerId
groupInfo.MemberCount = v.MemberCount
groupsInfo = append(groupsInfo, groupInfo)
}
c.JSON(http.StatusOK, gin.H{
"errCode": RpcResp.ErrorCode,
"errMsg": RpcResp.ErrorMsg,
"data": groupsInfo,
})
} else {
c.JSON(http.StatusOK, gin.H{"errCode": RpcResp.ErrorCode, "errMsg": RpcResp.ErrorMsg})
}
}
+351
View File
@@ -0,0 +1,351 @@
package group
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pb "Open_IM/pkg/proto/group"
"context"
"fmt"
"github.com/gin-gonic/gin"
"net/http"
"strings"
)
type InviteUserToGroupReq struct {
GroupID string `json:"groupID" binding:"required"`
UidList []string `json:"uidList" binding:"required"`
Reason string `json:"reason"`
OperationID string `json:"operationID" binding:"required"`
}
type GetJoinedGroupListReq struct {
OperationID string `json:"operationID" binding:"required"`
}
type KickGroupMemberReq struct {
GroupID string `json:"groupID"`
UidListInfo []*pb.GroupMemberFullInfo `json:"uidListInfo" binding:"required"`
Reason string `json:"reason"`
OperationID string `json:"operationID" binding:"required"`
}
func KickGroupMember(c *gin.Context) {
log.Info("", "", "KickGroupMember start....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImGroupName)
client := pb.NewGroupClient(etcdConn)
params := KickGroupMemberReq{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
return
}
req := &pb.KickGroupMemberReq{
OperationID: params.OperationID,
GroupID: params.GroupID,
Token: c.Request.Header.Get("token"),
UidListInfo: params.UidListInfo,
}
log.Info(req.Token, req.OperationID, "recv req: ", req.String())
RpcResp, err := client.KickGroupMember(context.Background(), req)
if err != nil {
log.Error(req.Token, req.OperationID, "GetGroupMemberList failed, err: ", err.Error())
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": err.Error()})
return
}
type KickGroupMemberResp struct {
ErrorCode int32 `json:"errCode"`
ErrorMsg string `json:"errMsg"`
Data []Id2Result `json:"data"`
}
var memberListResp KickGroupMemberResp
memberListResp.ErrorMsg = RpcResp.ErrorMsg
memberListResp.ErrorCode = RpcResp.ErrorCode
for _, v := range RpcResp.Id2Result {
memberListResp.Data = append(memberListResp.Data,
Id2Result{UId: v.UId,
Result: v.Result})
}
c.JSON(http.StatusOK, memberListResp)
}
type GetGroupMembersInfoReq struct {
GroupID string `json:"groupID"`
MemberList []string `json:"memberList"`
OperationID string `json:"operationID"`
}
type GetGroupMembersInfoResp struct {
ErrorCode int32 `json:"errCode"`
ErrorMsg string `json:"errMsg"`
Data []MemberResult `json:"data"`
}
func GetGroupMembersInfo(c *gin.Context) {
log.Info("", "", "GetGroupMembersInfo start....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImGroupName)
client := pb.NewGroupClient(etcdConn)
params := GetGroupMembersInfoReq{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
return
}
req := &pb.GetGroupMembersInfoReq{
OperationID: params.OperationID,
GroupID: params.GroupID,
MemberList: params.MemberList,
Token: c.Request.Header.Get("token"),
}
log.Info(req.Token, req.OperationID, "recv req: ", len(params.MemberList))
RpcResp, err := client.GetGroupMembersInfo(context.Background(), req)
if err != nil {
log.Error(req.Token, req.OperationID, "GetGroupMemberList failed, err: ", err.Error())
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": err.Error()})
return
}
var memberListResp GetGroupMembersInfoResp
memberListResp.ErrorMsg = RpcResp.ErrorMsg
memberListResp.ErrorCode = RpcResp.ErrorCode
for _, v := range RpcResp.MemberList {
memberListResp.Data = append(memberListResp.Data,
MemberResult{GroupId: req.GroupID,
UserId: v.UserId,
Role: v.Role,
JoinTime: uint64(v.JoinTime),
Nickname: v.NickName,
FaceUrl: v.FaceUrl})
}
c.JSON(http.StatusOK, memberListResp)
}
type GetGroupMemberListReq struct {
GroupID string `json:"groupID"`
Filter int32 `json:"filter"`
NextSeq int32 `json:"nextSeq"`
OperationID string `json:"operationID"`
}
type getGroupAllMemberReq struct {
GroupID string `json:"groupID"`
OperationID string `json:"operationID"`
}
type MemberResult struct {
GroupId string `json:"groupID"`
UserId string `json:"userId"`
Role int32 `json:"role"`
JoinTime uint64 `json:"joinTime"`
Nickname string `json:"nickName"`
FaceUrl string `json:"faceUrl"`
}
func GetGroupMemberList(c *gin.Context) {
log.Info("", "", "GetGroupMemberList start....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImGroupName)
client := pb.NewGroupClient(etcdConn)
params := GetGroupMemberListReq{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
return
}
req := &pb.GetGroupMemberListReq{
OperationID: params.OperationID,
Filter: params.Filter,
NextSeq: params.NextSeq,
GroupID: params.GroupID,
Token: c.Request.Header.Get("token"),
}
log.Info(req.Token, req.OperationID, "recv req: ", req.String())
RpcResp, err := client.GetGroupMemberList(context.Background(), req)
if err != nil {
log.Error(req.Token, req.OperationID, "GetGroupMemberList failed, err: ", err.Error())
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": err.Error()})
return
}
type GetGroupMemberListResp struct {
ErrorCode int32 `json:"errCode"`
ErrorMsg string `json:"errMsg"`
NextSeq int32 `json:"nextSeq"`
Data []MemberResult `json:"data"`
}
var memberListResp GetGroupMemberListResp
memberListResp.ErrorMsg = RpcResp.ErrorMsg
memberListResp.ErrorCode = RpcResp.ErrorCode
memberListResp.NextSeq = RpcResp.NextSeq
for _, v := range RpcResp.MemberList {
memberListResp.Data = append(memberListResp.Data,
MemberResult{GroupId: req.GroupID,
UserId: v.UserId,
Role: v.Role,
JoinTime: uint64(v.JoinTime),
Nickname: v.NickName,
FaceUrl: v.FaceUrl})
}
c.JSON(http.StatusOK, memberListResp)
}
func GetGroupAllMember(c *gin.Context) {
log.Info("", "", "GetGroupAllMember start....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImGroupName)
client := pb.NewGroupClient(etcdConn)
params := getGroupAllMemberReq{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
return
}
req := &pb.GetGroupAllMemberReq{
GroupID: params.GroupID,
OperationID: params.OperationID,
Token: c.Request.Header.Get("token"),
}
log.Info(req.Token, req.OperationID, "recv req: ", req.String())
RpcResp, err := client.GetGroupAllMember(context.Background(), req)
if err != nil {
log.Error(req.Token, req.OperationID, "GetGroupAllMember failed, err: ", err.Error())
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": err.Error()})
return
}
type GetGroupMemberListResp struct {
ErrorCode int32 `json:"errCode"`
ErrorMsg string `json:"errMsg"`
Data []MemberResult `json:"data"`
}
var memberListResp GetGroupMemberListResp
memberListResp.ErrorMsg = RpcResp.ErrorMsg
memberListResp.ErrorCode = RpcResp.ErrorCode
for _, v := range RpcResp.MemberList {
memberListResp.Data = append(memberListResp.Data,
MemberResult{GroupId: req.GroupID,
UserId: v.UserId,
Role: v.Role,
JoinTime: uint64(v.JoinTime),
Nickname: v.NickName,
FaceUrl: v.FaceUrl})
}
c.JSON(http.StatusOK, memberListResp)
}
type groupResult struct {
GroupId string `json:"groupId"`
GroupName string `json:"groupName"`
Notification string `json:"notification"`
Introduction string `json:"introduction"`
FaceUrl string `json:"faceUrl"`
OwnerId string `json:"ownerId"`
CreateTime uint64 `json:"createTime"`
MemberCount uint32 `json:"memberCount"`
}
func GetJoinedGroupList(c *gin.Context) {
log.Info("", "", "GetJoinedGroupList start....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImGroupName)
fmt.Println("config: ", etcdConn, config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImGroupName)
client := pb.NewGroupClient(etcdConn)
params := GetJoinedGroupListReq{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
return
}
req := &pb.GetJoinedGroupListReq{
OperationID: params.OperationID,
Token: c.Request.Header.Get("token"),
}
log.Info(req.Token, req.OperationID, "recv req: ", req.String())
RpcResp, err := client.GetJoinedGroupList(context.Background(), req)
if err != nil {
log.Error(req.Token, req.OperationID, "GetJoinedGroupList failed, err: ", err.Error())
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": err.Error()})
return
}
log.Info(req.Token, req.OperationID, "GetJoinedGroupList: ", RpcResp)
type GetJoinedGroupListResp struct {
ErrorCode int32 `json:"errCode"`
ErrorMsg string `json:"errMsg"`
Data []groupResult `json:"data"`
}
var GroupListResp GetJoinedGroupListResp
GroupListResp.ErrorCode = RpcResp.ErrorCode
GroupListResp.ErrorMsg = RpcResp.ErrorMsg
for _, v := range RpcResp.GroupList {
GroupListResp.Data = append(GroupListResp.Data,
groupResult{GroupId: v.GroupId, GroupName: v.GroupName,
Notification: v.Notification,
Introduction: v.Introduction,
FaceUrl: v.FaceUrl,
OwnerId: v.OwnerId,
CreateTime: v.CreateTime,
MemberCount: v.MemberCount})
}
c.JSON(http.StatusOK, GroupListResp)
}
type Id2Result struct {
UId string `json:"uid"`
Result int32 `json:"result"`
}
func InviteUserToGroup(c *gin.Context) {
log.Info("", "", "InviteUserToGroup start....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImGroupName)
client := pb.NewGroupClient(etcdConn)
params := InviteUserToGroupReq{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
return
}
req := &pb.InviteUserToGroupReq{
OperationID: params.OperationID,
GroupID: params.GroupID,
Reason: params.Reason,
UidList: params.UidList,
Token: c.Request.Header.Get("token"),
}
log.Info(req.Token, req.OperationID, "recv req: ", req.String())
RpcResp, err := client.InviteUserToGroup(context.Background(), req)
if err != nil {
log.Error(req.Token, req.OperationID, "InviteUserToGroup failed, err: ", err.Error())
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": err.Error()})
return
}
type InviteUserToGroupResp struct {
ErrorCode int32 `json:"errCode"`
ErrorMsg string `json:"errMsg"`
I2R []Id2Result `json:"data"`
}
var iResp InviteUserToGroupResp
iResp.ErrorMsg = RpcResp.ErrorMsg
iResp.ErrorCode = RpcResp.ErrorCode
for _, v := range RpcResp.Id2Result {
iResp.I2R = append(iResp.I2R, Id2Result{UId: v.UId, Result: v.Result})
}
//resp := gin.H{"errCode": RpcResp.ErrorCode, "errMsg": RpcResp.ErrorMsg, "data": RpcResp.Id2Result}
c.JSON(http.StatusOK, iResp)
}
@@ -0,0 +1,87 @@
package group
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
"Open_IM/pkg/proto/group"
"Open_IM/pkg/utils"
"context"
"github.com/gin-gonic/gin"
"net/http"
"strings"
)
type paramsGroupApplicationResponse struct {
OperationID string `json:"operationID" binding:"required"`
GroupID string `json:"groupID" binding:"required"`
FromUserID string `json:"fromUserID" binding:"required"`
FromUserNickName string `json:"fromUserNickName"`
FromUserFaceUrl string `json:"fromUserFaceUrl"`
ToUserID string `json:"toUserID" binding:"required"`
ToUserNickName string `json:"toUserNickName"`
ToUserFaceUrl string `json:"toUserFaceUrl"`
AddTime int64 `json:"addTime"`
RequestMsg string `json:"requestMsg"`
HandledMsg string `json:"handledMsg"`
Type int32 `json:"type"`
HandleStatus int32 `json:"handleStatus"`
HandleResult int32 `json:"handleResult"`
}
func newGroupApplicationResponse(params *paramsGroupApplicationResponse) *group.GroupApplicationResponseReq {
pbData := group.GroupApplicationResponseReq{
OperationID: params.OperationID,
GroupID: params.GroupID,
FromUserID: params.FromUserID,
FromUserNickName: params.FromUserNickName,
FromUserFaceUrl: params.FromUserFaceUrl,
ToUserID: params.ToUserID,
ToUserNickName: params.ToUserNickName,
ToUserFaceUrl: params.ToUserFaceUrl,
AddTime: params.AddTime,
RequestMsg: params.RequestMsg,
HandledMsg: params.HandledMsg,
Type: params.Type,
HandleStatus: params.HandleStatus,
HandleResult: params.HandleResult,
}
return &pbData
}
func ApplicationGroupResponse(c *gin.Context) {
log.Info("", "", "api GroupApplicationResponse init ....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImGroupName)
client := group.NewGroupClient(etcdConn)
//defer etcdConn.Close()
params := paramsGroupApplicationResponse{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
return
}
pbData := newGroupApplicationResponse(&params)
token := c.Request.Header.Get("token")
if claims, err := utils.ParseToken(token); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": "token validate err"})
return
} else {
pbData.OwnerID = claims.UID
}
log.Info("", "", "api GroupApplicationResponse is server, [data: %s]", pbData.String())
reply, err := client.GroupApplicationResponse(context.Background(), pbData)
if err != nil {
log.Error("", "", "api GroupApplicationResponse call rpc fail, [data: %s] [err: %s]", pbData.String(), err.Error())
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": err.Error()})
return
}
log.Info("", "", "api GroupApplicationResponse call rpc success, [data: %s] [reply: %s]", pbData.String(), reply.String())
c.JSON(http.StatusOK, gin.H{
"errCode": reply.ErrCode,
"errMsg": reply.ErrMsg,
})
}
+47
View File
@@ -0,0 +1,47 @@
package group
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pb "Open_IM/pkg/proto/group"
"context"
"github.com/gin-gonic/gin"
"net/http"
"strings"
)
type paramsJoinGroup struct {
GroupID string `json:"groupID" binding:"required"`
Message string `json:"message"`
OperationID string `json:"operationID" binding:"required"`
}
func JoinGroup(c *gin.Context) {
log.Info("", "", "api join group init....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImGroupName)
client := pb.NewGroupClient(etcdConn)
//defer etcdConn.Close()
params := paramsJoinGroup{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
return
}
req := &pb.JoinGroupReq{
GroupID: params.GroupID,
Message: params.Message,
Token: c.Request.Header.Get("token"),
OperationID: params.OperationID,
}
log.Info(req.Token, req.OperationID, "api join group is server,params=%s", req.String())
RpcResp, err := client.JoinGroup(context.Background(), req)
if err != nil {
log.Error(req.Token, req.OperationID, "call join group rpc server failed,err=%s", err.Error())
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": "call rpc server failed"})
return
}
log.InfoByArgs("call join group rpc server success,args=%s", RpcResp.String())
c.JSON(http.StatusOK, gin.H{"errCode": RpcResp.ErrorCode, "errMsg": RpcResp.ErrorMsg})
}
+46
View File
@@ -0,0 +1,46 @@
package group
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pb "Open_IM/pkg/proto/group"
"context"
"github.com/gin-gonic/gin"
"net/http"
"strings"
)
type paramsQuitGroup struct {
GroupID string `json:"groupID" binding:"required"`
OperationID string `json:"operationID" binding:"required"`
}
func QuitGroup(c *gin.Context) {
log.Info("", "", "api quit group init ....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImGroupName)
client := pb.NewGroupClient(etcdConn)
//defer etcdConn.Close()
params := paramsQuitGroup{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
return
}
req := &pb.QuitGroupReq{
GroupID: params.GroupID,
OperationID: params.OperationID,
Token: c.Request.Header.Get("token"),
}
log.Info(req.Token, req.OperationID, "api quit group is server,params=%s", req.String())
RpcResp, err := client.QuitGroup(context.Background(), req)
if err != nil {
log.Error(req.Token, req.OperationID, "call quit group rpc server failed,err=%s", err.Error())
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": "call rpc server failed"})
return
}
log.InfoByArgs("call quit group rpc server success,args=%s", RpcResp.String())
c.JSON(http.StatusOK, gin.H{"errCode": RpcResp.ErrorCode, "errMsg": RpcResp.ErrorMsg})
log.InfoByArgs("api quit group success return,get args=%s,return args=%s", req.String(), RpcResp.String())
}
+53
View File
@@ -0,0 +1,53 @@
package group
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pb "Open_IM/pkg/proto/group"
"context"
"github.com/gin-gonic/gin"
"net/http"
"strings"
)
type paramsSetGroupInfo struct {
GroupID string `json:"groupId" binding:"required"`
GroupName string `json:"groupName"`
Notification string `json:"notification"`
Introduction string `json:"introduction"`
FaceUrl string `json:"faceUrl"`
OperationID string `json:"operationID" binding:"required"`
}
func SetGroupInfo(c *gin.Context) {
log.Info("", "", "api set group info init...")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImGroupName)
client := pb.NewGroupClient(etcdConn)
//defer etcdConn.Close()
params := paramsSetGroupInfo{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
return
}
req := &pb.SetGroupInfoReq{
GroupID: params.GroupID,
GroupName: params.GroupName,
Notification: params.Notification,
Introduction: params.Introduction,
FaceUrl: params.FaceUrl,
Token: c.Request.Header.Get("token"),
OperationID: params.OperationID,
}
log.Info(req.Token, req.OperationID, "api set group info is server,params=%s", req.String())
RpcResp, err := client.SetGroupInfo(context.Background(), req)
if err != nil {
log.Error(req.Token, req.OperationID, "call set group info rpc server failed,err=%s", err.Error())
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": "call rpc server failed"})
return
}
log.InfoByArgs("call set group info rpc server success,args=%s", RpcResp.String())
c.JSON(http.StatusOK, gin.H{"errCode": RpcResp.ErrorCode, "errMsg": RpcResp.ErrorMsg})
}
@@ -0,0 +1,65 @@
package group
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
"Open_IM/pkg/proto/group"
"Open_IM/pkg/utils"
"context"
"github.com/gin-gonic/gin"
"net/http"
"strings"
)
type paramsTransferGroupOwner struct {
OperationID string `json:"operationID" binding:"required"`
GroupID string `json:"groupID" binding:"required"`
UID string `json:"uid" binding:"required"`
}
func newTransferGroupOwnerReq(params *paramsTransferGroupOwner) *group.TransferGroupOwnerReq {
pbData := group.TransferGroupOwnerReq{
OperationID: params.OperationID,
GroupID: params.GroupID,
NewOwner: params.UID,
}
return &pbData
}
func TransferGroupOwner(c *gin.Context) {
log.Info("", "", "api TransferGroupOwner init ....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImGroupName)
client := group.NewGroupClient(etcdConn)
//defer etcdConn.Close()
params := paramsTransferGroupOwner{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
return
}
pbData := newTransferGroupOwnerReq(&params)
token := c.Request.Header.Get("token")
if claims, err := utils.ParseToken(token); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": "token validate err"})
return
} else {
pbData.OldOwner = claims.UID
}
log.Info("", "", "api TransferGroupOwner is server, [data: %s]", pbData.String())
reply, err := client.TransferGroupOwner(context.Background(), pbData)
if err != nil {
log.Error("", "", "api TransferGroupOwner call rpc fail, [data: %s] [err: %s]", pbData.String(), err.Error())
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": err.Error()})
return
}
log.Info("", "", "api TransferGroupOwner call rpc success, [data: %s] [reply: %s]", pbData.String(), reply.String())
c.JSON(http.StatusOK, gin.H{
"errCode": reply.ErrCode,
"errMsg": reply.ErrMsg,
})
}
+208
View File
@@ -0,0 +1,208 @@
/*
** description("").
** copyright('open-im,www.open-im.io').
** author("fg,Gordon@tuoyun.net").
** time(2021/9/15 15:23).
*/
package manage
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/constant"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbChat "Open_IM/pkg/proto/chat"
"Open_IM/pkg/utils"
"context"
"github.com/gin-gonic/gin"
"github.com/go-playground/validator/v10"
"github.com/mitchellh/mapstructure"
"net/http"
"strings"
)
var validate *validator.Validate
type paramsManagementSendMsg struct {
OperationID string `json:"operationID" binding:"required"`
SendID string `json:"sendID" binding:"required"`
RecvID string `json:"recvID" binding:"required"`
SenderNickName string `json:"senderNickName" `
SenderFaceURL string `json:"senderFaceURL" `
ForceList []string `json:"forceList" `
Content map[string]interface{} `json:"content" binding:"required"`
ContentType int32 `json:"contentType" binding:"required"`
SessionType int32 `json:"sessionType" binding:"required"`
}
func newUserSendMsgReq(params *paramsManagementSendMsg) *pbChat.UserSendMsgReq {
var newContent string
switch params.ContentType {
case constant.Text:
newContent = params.Content["text"].(string)
case constant.Picture:
fallthrough
case constant.Custom:
fallthrough
case constant.Voice:
fallthrough
case constant.File:
newContent = utils.StructToJsonString(params.Content)
default:
}
pbData := pbChat.UserSendMsgReq{
ReqIdentifier: constant.WSSendMsg,
SendID: params.SendID,
SenderNickName: params.SenderNickName,
SenderFaceURL: params.SenderFaceURL,
OperationID: params.OperationID,
PlatformID: 0,
SessionType: params.SessionType,
MsgFrom: constant.UserMsgType,
ContentType: params.ContentType,
RecvID: params.RecvID,
ForceList: params.ForceList,
Content: newContent,
ClientMsgID: utils.GetMsgID(params.SendID),
}
return &pbData
}
func init() {
validate = validator.New()
}
func ManagementSendMsg(c *gin.Context) {
var data interface{}
params := paramsManagementSendMsg{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
log.ErrorByKv("json unmarshal err", c.PostForm("operationID"), "err", err.Error(), "content", c.PostForm("content"))
return
}
switch params.ContentType {
case constant.Text:
data = TextElem{}
case constant.Picture:
data = PictureElem{}
case constant.Custom:
data = CustomElem{}
default:
c.JSON(http.StatusBadRequest, gin.H{"errCode": 404, "errMsg": "contentType err"})
log.ErrorByKv("contentType err", c.PostForm("operationID"), "content", c.PostForm("content"))
return
}
if err := mapstructure.WeakDecode(params.Content, &data); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 401, "errMsg": err.Error()})
log.ErrorByKv("content to Data struct err", "", "err", err.Error())
return
} else if err := validate.Struct(data); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 403, "errMsg": err.Error()})
log.ErrorByKv("data args validate err", "", "err", err.Error())
return
}
token := c.Request.Header.Get("token")
claims, err := utils.ParseToken(token)
if err != nil {
log.NewError(params.OperationID, "parse token failed", err.Error())
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": "parse token failed", "sendTime": 0, "MsgID": ""})
}
if !utils.IsContain(claims.UID, config.Config.Manager.AppManagerUid) {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": "not authorized", "sendTime": 0, "MsgID": ""})
return
}
log.InfoByKv("Ws call success to ManagementSendMsgReq", params.OperationID, "Parameters", params)
pbData := newUserSendMsgReq(&params)
log.Info("", "", "api ManagementSendMsg call start..., [data: %s]", pbData.String())
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImOfflineMessageName)
client := pbChat.NewChatClient(etcdConn)
log.Info("", "", "api ManagementSendMsg call, api call rpc...")
reply, _ := client.UserSendMsg(context.Background(), pbData)
log.Info("", "", "api ManagementSendMsg call end..., [data: %s] [reply: %s]", pbData.String(), reply.String())
c.JSON(http.StatusOK, gin.H{
"errCode": reply.ErrCode,
"errMsg": reply.ErrMsg,
"sendTime": reply.SendTime,
"msgID": reply.ClientMsgID,
})
}
type PictureBaseInfo struct {
UUID string `mapstructure:"uuid"`
Type string `mapstructure:"type" validate:"required"`
Size int64 `mapstructure:"size" validate:"required"`
Width int32 `mapstructure:"width" validate:"required"`
Height int32 `mapstructure:"height" validate:"required"`
Url string `mapstructure:"url" validate:"required"`
}
type PictureElem struct {
SourcePath string `mapstructure:"sourcePath"`
SourcePicture PictureBaseInfo `mapstructure:"sourcePicture" validate:"required"`
BigPicture PictureBaseInfo `mapstructure:"bigPicture" `
SnapshotPicture PictureBaseInfo `mapstructure:"snapshotPicture"`
}
type SoundElem struct {
UUID string `mapstructure:"uuid"`
SoundPath string `mapstructure:"soundPath"`
SourceURL string `mapstructure:"sourceUrl"`
DataSize int64 `mapstructure:"dataSize"`
Duration int64 `mapstructure:"duration"`
}
type VideoElem struct {
VideoPath string `mapstructure:"videoPath"`
VideoUUID string `mapstructure:"videoUUID"`
VideoURL string `mapstructure:"videoUrl"`
VideoType string `mapstructure:"videoType"`
VideoSize int64 `mapstructure:"videoSize"`
Duration int64 `mapstructure:"duration"`
SnapshotPath string `mapstructure:"snapshotPath"`
SnapshotUUID string `mapstructure:"snapshotUUID"`
SnapshotSize int64 `mapstructure:"snapshotSize"`
SnapshotURL string `mapstructure:"snapshotUrl"`
SnapshotWidth int32 `mapstructure:"snapshotWidth"`
SnapshotHeight int32 `mapstructure:"snapshotHeight"`
}
type FileElem struct {
FilePath string `mapstructure:"filePath"`
UUID string `mapstructure:"uuid"`
SourceURL string `mapstructure:"sourceUrl"`
FileName string `mapstructure:"fileName"`
FileSize int64 `mapstructure:"fileSize"`
}
//type MergeElem struct {
// Title string `json:"title"`
// AbstractList []string `json:"abstractList"`
// MultiMessage []*MsgStruct `json:"multiMessage"`
//}
type AtElem struct {
Text string `mapstructure:"text"`
AtUserList []string `mapstructure:"atUserList"`
IsAtSelf bool `mapstructure:"isAtSelf"`
}
type LocationElem struct {
Description string `mapstructure:"description"`
Longitude float64 `mapstructure:"longitude"`
Latitude float64 `mapstructure:"latitude"`
}
type CustomElem struct {
Data string `mapstructure:"data" validate:"required"`
Description string `mapstructure:"description"`
Extension string `mapstructure:"extension"`
}
type TextElem struct {
Text string `mapstructure:"text" validate:"required"`
}
//type QuoteElem struct {
// Text string `json:"text"`
// QuoteMessage *MsgStruct `json:"quoteMessage"`
//}
+78
View File
@@ -0,0 +1,78 @@
/*
** description("").
** copyright('open-im,www.open-im.io').
** author("fg,Gordon@tuoyun.net").
** time(2021/9/15 10:28).
*/
package manage
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbUser "Open_IM/pkg/proto/user"
"context"
"github.com/gin-gonic/gin"
"net/http"
"strings"
)
type paramsDeleteUsers struct {
OperationID string `json:"operationID" binding:"required"`
DeleteUidList []string `json:"deleteUidList" binding:"required"`
}
type paramsGetAllUsersUid struct {
OperationID string `json:"operationID" binding:"required"`
}
func DeleteUser(c *gin.Context) {
params := paramsDeleteUsers{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
return
}
log.InfoByKv("DeleteUser req come here", params.OperationID, "DeleteUidList", params.DeleteUidList)
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImUserName)
client := pbUser.NewUserClient(etcdConn)
//defer etcdConn.Close()
req := &pbUser.DeleteUsersReq{
OperationID: params.OperationID,
DeleteUidList: params.DeleteUidList,
Token: c.Request.Header.Get("token"),
}
RpcResp, err := client.DeleteUsers(context.Background(), req)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": "call delete users rpc server failed"})
return
}
log.InfoByKv("call delete user rpc server is success", params.OperationID, "resp args", RpcResp.String())
resp := gin.H{"errCode": RpcResp.CommonResp.ErrorCode, "errMsg": RpcResp.CommonResp.ErrorMsg, "failedUidList": RpcResp.FailedUidList}
c.JSON(http.StatusOK, resp)
}
func GetAllUsersUid(c *gin.Context) {
params := paramsGetAllUsersUid{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
return
}
log.InfoByKv("GetAllUsersUid req come here", params.OperationID)
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImUserName)
client := pbUser.NewUserClient(etcdConn)
//defer etcdConn.Close()
req := &pbUser.GetAllUsersUidReq{
OperationID: params.OperationID,
Token: c.Request.Header.Get("token"),
}
RpcResp, err := client.GetAllUsersUid(context.Background(), req)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": err.Error(), "uidList": []string{}})
return
}
log.InfoByKv("call GetAllUsersUid rpc server is success", params.OperationID, "resp args", RpcResp.String())
resp := gin.H{"errCode": RpcResp.CommonResp.ErrorCode, "errMsg": RpcResp.CommonResp.ErrorMsg, "uidList": RpcResp.UidList}
c.JSON(http.StatusOK, resp)
}
@@ -0,0 +1,92 @@
package apiThird
import (
"Open_IM/pkg/common/config"
log2 "Open_IM/pkg/common/log"
"github.com/gin-gonic/gin"
sts "github.com/tencentyun/qcloud-cos-sts-sdk/go"
"net/http"
"time"
)
type paramsTencentCloudStorageCredential struct {
Token string `json:"token"`
OperationID string `json:"operationID"`
}
var lastTime int64
var lastRes *sts.CredentialResult
func TencentCloudStorageCredential(c *gin.Context) {
params := paramsTencentCloudStorageCredential{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": "Parameter parsing errorplease check the parameters and request service again"})
return
}
log2.Info(params.Token, params.OperationID, "api TencentUpLoadCredential call start...")
if time.Now().Unix()-lastTime < 10 && lastRes != nil {
c.JSON(http.StatusOK, gin.H{
"errCode": 0,
"errMsg": "",
"region": config.Config.Credential.Tencent.Region,
"bucket": config.Config.Credential.Tencent.Bucket,
"data": lastRes,
})
return
}
lastTime = time.Now().Unix()
cli := sts.NewClient(
config.Config.Credential.Tencent.SecretID,
config.Config.Credential.Tencent.SecretKey,
nil,
)
log2.Info(c.Request.Header.Get("token"), c.PostForm("optionID"), "api TencentUpLoadCredential sts.NewClient cli = %v", cli)
opt := &sts.CredentialOptions{
DurationSeconds: int64(time.Hour.Seconds()),
Region: config.Config.Credential.Tencent.Region,
Policy: &sts.CredentialPolicy{
Statement: []sts.CredentialPolicyStatement{
{
Action: []string{
"name/cos:PostObject",
"name/cos:PutObject",
},
Effect: "allow",
Resource: []string{
"qcs::cos:" + config.Config.Credential.Tencent.Region + ":uid/" + config.Config.Credential.Tencent.AppID + ":" + config.Config.Credential.Tencent.Bucket + "/*",
},
},
},
},
}
log2.Info(c.Request.Header.Get("token"), c.PostForm("optionID"), "api TencentUpLoadCredential sts.CredentialOptions opt = %v", opt)
res, err := cli.GetCredential(opt)
if err != nil {
log2.Error(c.Request.Header.Get("token"), c.PostForm("optionID"), "api TencentUpLoadCredential cli.GetCredential err = %s", err.Error())
c.JSON(http.StatusOK, gin.H{
"errCode": config.ErrTencentCredential.ErrCode,
"errMsg": err.Error(),
"bucket": "",
"region": "",
"data": res,
})
return
}
log2.Info(c.Request.Header.Get("token"), c.PostForm("optionID"), "api TencentUpLoadCredential cli.GetCredential success res = %v, res.Credentials = %v", res, res.Credentials)
lastRes = res
c.JSON(http.StatusOK, gin.H{
"errCode": 0,
"errMsg": "",
"region": config.Config.Credential.Tencent.Region,
"bucket": config.Config.Credential.Tencent.Bucket,
"data": res,
})
}
+74
View File
@@ -0,0 +1,74 @@
package user
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbUser "Open_IM/pkg/proto/user"
"context"
"github.com/gin-gonic/gin"
"net/http"
"strings"
)
type userInfo struct {
UID string `json:"uid"`
Name string `json:"name"`
Icon string `json:"icon"`
Gender int32 `json:"gender"`
Mobile string `json:"mobile"`
Birth string `json:"birth"`
Email string `json:"email"`
Ex string `json:"ex"`
}
func GetUserInfo(c *gin.Context) {
log.InfoByKv("api get userinfo init...", "")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImUserName)
client := pbUser.NewUserClient(etcdConn)
//defer etcdConn.Close()
params := paramsStruct{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
return
}
req := &pbUser.GetUserInfoReq{
UserIDList: params.UIDList,
OperationID: params.OperationID,
Token: c.Request.Header.Get("token"),
}
log.InfoByKv("api get user info is server", c.PostForm("OperationID"), c.Request.Header.Get("token"))
RpcResp, err := client.GetUserInfo(context.Background(), req)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,call get user info rpc server failed", err)
c.JSON(http.StatusInternalServerError, gin.H{
"errorCode": 500,
"errorMsg": "call rpc server failed",
})
return
}
log.InfoByKv("call get user info rpc server success", params.OperationID)
if RpcResp.ErrorCode == 0 {
userInfoList := make([]userInfo, 0)
for _, user := range RpcResp.Data {
var ui userInfo
ui.UID = user.Uid
ui.Name = user.Name
ui.Icon = user.Icon
ui.Gender = user.Gender
ui.Mobile = user.Mobile
ui.Birth = user.Birth
ui.Email = user.Email
ui.Ex = user.Ex
userInfoList = append(userInfoList, ui)
}
resp := gin.H{"errCode": RpcResp.ErrorCode, "errMsg": RpcResp.ErrorMsg, "data": userInfoList}
c.JSON(http.StatusOK, resp)
} else {
resp := gin.H{"errCode": RpcResp.ErrorCode, "errMsg": RpcResp.ErrorMsg}
c.JSON(http.StatusOK, resp)
}
log.InfoByKv("api get user info return success", params.OperationID, "args=%s", RpcResp.String())
}
+62
View File
@@ -0,0 +1,62 @@
package user
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbUser "Open_IM/pkg/proto/user"
"context"
"github.com/gin-gonic/gin"
"net/http"
"strings"
)
type paramsStruct struct {
OperationID string `json:"operationID" binding:"required"`
UIDList []string `json:"uidList"`
Platform int32 `json:"platform"`
Name string `json:"name"`
Icon string `json:"icon"`
Gender int32 `json:"gender"`
Mobile string `json:"mobile"`
Birth string `json:"birth"`
Email string `json:"email"`
Ex string `json:"ex"`
Uid string `json:"uid"`
}
func UpdateUserInfo(c *gin.Context) {
log.InfoByKv("api update userinfo init...", "")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImUserName)
client := pbUser.NewUserClient(etcdConn)
//defer etcdConn.Close()
params := paramsStruct{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
return
}
req := &pbUser.UpdateUserInfoReq{
OperationID: params.OperationID,
Token: c.Request.Header.Get("token"),
Name: params.Name,
Icon: params.Icon,
Gender: params.Gender,
Mobile: params.Mobile,
Birth: params.Birth,
Email: params.Email,
Ex: params.Ex,
Uid: params.Uid,
}
log.InfoByKv("api update user info is server", req.OperationID, req.Token)
RpcResp, err := client.UpdateUserInfo(context.Background(), req)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,call get user info rpc server failed", err)
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": "call rpc server failed"})
return
}
log.InfoByKv("call update user info rpc server success", params.OperationID)
c.JSON(http.StatusOK, gin.H{"errCode": RpcResp.ErrorCode, "errMsg": RpcResp.ErrorMsg})
log.InfoByKv("api update user info return success", params.OperationID, "args=%s", RpcResp.String())
}
+29
View File
@@ -0,0 +1,29 @@
package gate
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"github.com/go-playground/validator/v10"
"sync"
)
var (
rwLock *sync.RWMutex
validate *validator.Validate
ws WServer
rpcSvr RPCServer
)
func Init(rpcPort, wsPort int) {
//log initialization
log.NewPrivateLog(config.Config.ModuleName.LongConnSvrName)
rwLock = new(sync.RWMutex)
validate = validator.New()
ws.onInit(wsPort)
rpcSvr.onInit(rpcPort)
}
func Run() {
go ws.run()
go rpcSvr.run()
}
+283
View File
@@ -0,0 +1,283 @@
package gate
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/constant"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbChat "Open_IM/pkg/proto/chat"
open_im_sdk "Open_IM/pkg/proto/sdk_ws"
"Open_IM/pkg/utils"
"bytes"
"context"
"encoding/gob"
"encoding/json"
"github.com/golang/protobuf/proto"
"github.com/gorilla/websocket"
"runtime"
"strings"
)
func (ws *WServer) msgParse(conn *UserConn, binaryMsg []byte) {
//ws online debug data
//{"ReqIdentifier":1001,"Token":"123","SendID":"c4ca4238a0b923820dcc509a6f75849b","Time":"123","OperationID":"123","MsgIncr":0}
//{"ReqIdentifier":1002,"Token":"123","SendID":"c4ca4238a0b923820dcc509a6f75849b","Time":"123","OperationID":"123","MsgIncr":0,"SeqBegin":1,"SeqEnd":6}
//{"ReqIdentifier":1003,"Token":"123","SendID":"c4ca4238a0b923820dcc509a6f75849b",
//"RecvID":"a87ff679a2f3e71d9181a67b7542122c","ClientMsgID":"2343","Time":"147878787","OperationID":
//"123","MsgIncr":0,"SubMsgType":101,"MsgType":100,"MsgFrom":1,"Content":"sdfsdf"}
b := bytes.NewBuffer(binaryMsg)
m := Req{}
dec := gob.NewDecoder(b)
err := dec.Decode(&m)
if err != nil {
log.ErrorByKv("ws json Unmarshal err", "", "err", err.Error())
ws.sendErrMsg(conn, 200, err.Error(), constant.WSDataError, "", "")
err = conn.Close()
if err != nil {
log.NewError("", "ws close err", err.Error())
}
return
}
if err := validate.Struct(m); err != nil {
log.ErrorByKv("ws args validate err", "", "err", err.Error())
ws.sendErrMsg(conn, 201, err.Error(), m.ReqIdentifier, m.MsgIncr, m.OperationID)
return
}
//if !utils.VerifyToken(m.Token, m.SendID) {
// ws.sendErrMsg(conn, 202, "token validate err", m.ReqIdentifier, m.MsgIncr,m.OperationID)
// return
//}
log.InfoByKv("Basic Info Authentication Success", m.OperationID, "reqIdentifier", m.ReqIdentifier, "sendID", m.SendID, "msgIncr", m.MsgIncr)
switch m.ReqIdentifier {
case constant.WSGetNewestSeq:
go ws.getSeqReq(conn, &m)
case constant.WSPullMsg:
go ws.pullMsgReq(conn, &m)
case constant.WSSendMsg:
sendTime := utils.GetCurrentTimestampByNano()
go ws.sendMsgReq(conn, &m, sendTime)
case constant.WSPullMsgBySeqList:
go ws.pullMsgBySeqListReq(conn, &m)
default:
}
log.NewInfo("", "goroutine num is ", runtime.NumGoroutine())
}
func (ws *WServer) getSeqReq(conn *UserConn, m *Req) {
log.NewInfo(m.OperationID, "Ws call success to getNewSeq", m.MsgIncr, m.SendID, m.ReqIdentifier)
pbData := pbChat.GetMaxAndMinSeqReq{}
nReply := new(pbChat.GetMaxAndMinSeqResp)
pbData.UserID = m.SendID
pbData.OperationID = m.OperationID
grpcConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImOfflineMessageName)
if grpcConn == nil {
log.ErrorByKv("get grpcConn err", pbData.OperationID, "args", m)
}
msgClient := pbChat.NewChatClient(grpcConn)
reply, err := msgClient.GetMaxAndMinSeq(context.Background(), &pbData)
if err != nil {
log.ErrorByKv("rpc call failed to getSeqReq", pbData.OperationID, "err", err, "pbData", pbData.String())
nReply.ErrCode = 200
nReply.ErrMsg = err.Error()
ws.getSeqResp(conn, m, nReply)
} else {
log.InfoByKv("rpc call success to getSeqReq", pbData.OperationID, "replyData", reply.String())
ws.getSeqResp(conn, m, reply)
}
}
func (ws *WServer) getSeqResp(conn *UserConn, m *Req, pb *pbChat.GetMaxAndMinSeqResp) {
var mReplyData open_im_sdk.GetMaxAndMinSeqResp
mReplyData.MaxSeq = pb.GetMaxSeq()
mReplyData.MinSeq = pb.GetMinSeq()
b, _ := proto.Marshal(&mReplyData)
mReply := Resp{
ReqIdentifier: m.ReqIdentifier,
MsgIncr: m.MsgIncr,
ErrCode: pb.GetErrCode(),
ErrMsg: pb.GetErrMsg(),
OperationID: m.OperationID,
Data: b,
}
ws.sendMsg(conn, mReply)
}
func (ws *WServer) pullMsgReq(conn *UserConn, m *Req) {
log.NewInfo(m.OperationID, "Ws call success to pullMsgReq", m.ReqIdentifier, m.MsgIncr, m.SendID)
nReply := new(pbChat.PullMessageResp)
isPass, errCode, errMsg, data := ws.argsValidate(m, constant.WSPullMsg)
if isPass {
pbData := pbChat.PullMessageReq{}
pbData.UserID = m.SendID
pbData.OperationID = m.OperationID
pbData.SeqBegin = data.(SeqData).SeqBegin
pbData.SeqEnd = data.(SeqData).SeqEnd
grpcConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImOfflineMessageName)
msgClient := pbChat.NewChatClient(grpcConn)
reply, err := msgClient.PullMessage(context.Background(), &pbData)
if err != nil {
log.ErrorByKv("PullMessage error", pbData.OperationID, "err", err.Error())
nReply.ErrCode = 200
nReply.ErrMsg = err.Error()
ws.pullMsgResp(conn, m, nReply)
} else {
log.InfoByKv("rpc call success to pullMsgRep", pbData.OperationID, "ReplyArgs", reply.String(), "maxSeq", reply.GetMaxSeq(),
"MinSeq", reply.GetMinSeq(), "singLen", len(reply.GetSingleUserMsg()), "groupLen", len(reply.GetGroupUserMsg()))
ws.pullMsgResp(conn, m, reply)
}
} else {
nReply.ErrCode = errCode
nReply.ErrMsg = errMsg
ws.pullMsgResp(conn, m, nReply)
}
}
func (ws *WServer) pullMsgResp(conn *UserConn, m *Req, pb *pbChat.PullMessageResp) {
log.NewInfo(m.OperationID, "pullMsgResp come here ", pb.String())
var mReplyData open_im_sdk.PullMessageBySeqListResp
a, err := json.Marshal(pb.SingleUserMsg)
if err != nil {
log.NewError(m.OperationID, "GetSingleUserMsg,json marshal,err", err.Error())
}
log.NewInfo(m.OperationID, "pullMsgResp json is ", len(pb.SingleUserMsg))
err = json.Unmarshal(a, &mReplyData.SingleUserMsg)
if err != nil {
log.NewError(m.OperationID, "SingleUserMsg,json Unmarshal,err", err.Error())
}
b, err := json.Marshal(pb.GroupUserMsg)
if err != nil {
log.NewError(m.OperationID, "mReplyData,json marshal,err", err.Error())
}
err = json.Unmarshal(b, &mReplyData.GroupUserMsg)
if err != nil {
log.NewError(m.OperationID, "test SingleUserMsg,json Unmarshal,err", err.Error())
}
c, err := proto.Marshal(&mReplyData)
log.NewInfo(m.OperationID, "test info is ", len(mReplyData.SingleUserMsg), mReplyData.SingleUserMsg)
mReply := Resp{
ReqIdentifier: m.ReqIdentifier,
MsgIncr: m.MsgIncr,
ErrCode: pb.GetErrCode(),
ErrMsg: pb.GetErrMsg(),
OperationID: m.OperationID,
Data: c,
}
log.NewInfo(m.OperationID, "pullMsgResp all data is ", mReply.ReqIdentifier, mReply.MsgIncr, mReply.ErrCode, mReply.ErrMsg,
len(mReply.Data))
ws.sendMsg(conn, mReply)
}
func (ws *WServer) pullMsgBySeqListReq(conn *UserConn, m *Req) {
log.NewInfo(m.OperationID, "Ws call success to pullMsgBySeqListReq start", m.SendID, m.ReqIdentifier, m.MsgIncr)
nReply := new(pbChat.PullMessageResp)
isPass, errCode, errMsg, data := ws.argsValidate(m, constant.WSPullMsgBySeqList)
log.NewInfo(m.OperationID, "Ws call success to pullMsgBySeqListReq middle", m.SendID, m.ReqIdentifier, m.MsgIncr, data.(open_im_sdk.PullMessageBySeqListReq).SeqList)
if isPass {
pbData := pbChat.PullMessageBySeqListReq{}
pbData.SeqList = data.(open_im_sdk.PullMessageBySeqListReq).SeqList
pbData.UserID = m.SendID
pbData.OperationID = m.OperationID
grpcConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImOfflineMessageName)
msgClient := pbChat.NewChatClient(grpcConn)
reply, err := msgClient.PullMessageBySeqList(context.Background(), &pbData)
if err != nil {
log.NewError(pbData.OperationID, "pullMsgBySeqListReq err", err.Error())
nReply.ErrCode = 200
nReply.ErrMsg = err.Error()
ws.pullMsgResp(conn, m, nReply)
} else {
log.NewInfo(pbData.OperationID, "rpc call success to pullMsgBySeqListReq", reply.String(), reply.GetMaxSeq(), reply.GetMinSeq(), len(reply.GetSingleUserMsg()), len(reply.GetGroupUserMsg()))
ws.pullMsgResp(conn, m, reply)
}
} else {
nReply.ErrCode = errCode
nReply.ErrMsg = errMsg
ws.pullMsgResp(conn, m, nReply)
}
}
func (ws *WServer) sendMsgReq(conn *UserConn, m *Req, sendTime int64) {
log.NewInfo(m.OperationID, "Ws call success to sendMsgReq start", m.MsgIncr, m.ReqIdentifier, m.SendID, sendTime)
nReply := new(pbChat.UserSendMsgResp)
isPass, errCode, errMsg, pData := ws.argsValidate(m, constant.WSSendMsg)
if isPass {
data := pData.(open_im_sdk.UserSendMsgReq)
pbData := pbChat.UserSendMsgReq{
ReqIdentifier: m.ReqIdentifier,
Token: m.Token,
SendID: m.SendID,
OperationID: m.OperationID,
PlatformID: data.PlatformID,
SessionType: data.SessionType,
MsgFrom: data.MsgFrom,
ContentType: data.ContentType,
RecvID: data.RecvID,
ForceList: data.ForceList,
SenderNickName: data.SenderNickName,
SenderFaceURL: data.SenderFaceURL,
Content: data.Content,
Options: utils.MapIntToJsonString(data.Options),
ClientMsgID: data.ClientMsgID,
SendTime: sendTime,
}
log.NewInfo(m.OperationID, "Ws call success to sendMsgReq middle", m.ReqIdentifier, m.SendID, m.MsgIncr, data)
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImOfflineMessageName)
client := pbChat.NewChatClient(etcdConn)
reply, err := client.UserSendMsg(context.Background(), &pbData)
if err != nil {
log.NewError(pbData.OperationID, "UserSendMsg err", err.Error())
nReply.ErrCode = 200
nReply.ErrMsg = err.Error()
ws.sendMsgResp(conn, m, nReply, sendTime)
} else {
log.NewInfo(pbData.OperationID, "rpc call success to sendMsgReq", reply.String())
ws.sendMsgResp(conn, m, reply, sendTime)
}
} else {
nReply.ErrCode = errCode
nReply.ErrMsg = errMsg
ws.sendMsgResp(conn, m, nReply, sendTime)
}
}
func (ws *WServer) sendMsgResp(conn *UserConn, m *Req, pb *pbChat.UserSendMsgResp, sendTime int64) {
// := make(map[string]interface{})
var mReplyData open_im_sdk.UserSendMsgResp
mReplyData.ClientMsgID = pb.GetClientMsgID()
mReplyData.ServerMsgID = pb.GetServerMsgID()
mReplyData.SendTime = sendTime
b, _ := proto.Marshal(&mReplyData)
mReply := Resp{
ReqIdentifier: m.ReqIdentifier,
MsgIncr: m.MsgIncr,
ErrCode: pb.GetErrCode(),
ErrMsg: pb.GetErrMsg(),
OperationID: m.OperationID,
Data: b,
}
ws.sendMsg(conn, mReply)
}
func (ws *WServer) sendMsg(conn *UserConn, mReply interface{}) {
var b bytes.Buffer
enc := gob.NewEncoder(&b)
err := enc.Encode(mReply)
if err != nil {
log.NewError(mReply.(Resp).OperationID, mReply.(Resp).ReqIdentifier, mReply.(Resp).ErrCode, mReply.(Resp).ErrMsg, "Encode Msg error", conn.RemoteAddr().String(), ws.getUserUid(conn), err.Error())
return
}
err = ws.writeMsg(conn, websocket.BinaryMessage, b.Bytes())
if err != nil {
log.NewError(mReply.(Resp).OperationID, mReply.(Resp).ReqIdentifier, mReply.(Resp).ErrCode, mReply.(Resp).ErrMsg, "WS WriteMsg error", conn.RemoteAddr().String(), ws.getUserUid(conn), err.Error())
}
}
func (ws *WServer) sendErrMsg(conn *UserConn, errCode int32, errMsg string, reqIdentifier int32, msgIncr string, operationID string) {
mReply := Resp{
ReqIdentifier: reqIdentifier,
MsgIncr: msgIncr,
ErrCode: errCode,
ErrMsg: errMsg,
OperationID: operationID,
}
ws.sendMsg(conn, mReply)
}
+145
View File
@@ -0,0 +1,145 @@
package gate
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/constant"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbRelay "Open_IM/pkg/proto/relay"
open_im_sdk "Open_IM/pkg/proto/sdk_ws"
"Open_IM/pkg/utils"
"bytes"
"context"
"encoding/gob"
"fmt"
"github.com/golang/protobuf/proto"
"net"
"strings"
"github.com/gorilla/websocket"
"google.golang.org/grpc"
)
type RPCServer struct {
rpcPort int
rpcRegisterName string
etcdSchema string
etcdAddr []string
}
func (r *RPCServer) onInit(rpcPort int) {
r.rpcPort = rpcPort
r.rpcRegisterName = config.Config.RpcRegisterName.OpenImOnlineMessageRelayName
r.etcdSchema = config.Config.Etcd.EtcdSchema
r.etcdAddr = config.Config.Etcd.EtcdAddr
}
func (r *RPCServer) run() {
ip := utils.ServerIP
registerAddress := ip + ":" + utils.IntToString(r.rpcPort)
listener, err := net.Listen("tcp", registerAddress)
if err != nil {
log.ErrorByArgs(fmt.Sprintf("fail to listening consumer, err:%v\n", err))
return
}
defer listener.Close()
srv := grpc.NewServer()
defer srv.GracefulStop()
pbRelay.RegisterOnlineMessageRelayServiceServer(srv, r)
err = getcdv3.RegisterEtcd4Unique(r.etcdSchema, strings.Join(r.etcdAddr, ","), ip, r.rpcPort, r.rpcRegisterName, 10)
if err != nil {
log.ErrorByKv("register push message rpc to etcd err", "", "err", err.Error())
}
err = srv.Serve(listener)
if err != nil {
log.ErrorByKv("push message rpc listening err", "", "err", err.Error())
return
}
}
func (r *RPCServer) MsgToUser(_ context.Context, in *pbRelay.MsgToUserReq) (*pbRelay.MsgToUserResp, error) {
log.InfoByKv("PushMsgToUser is arriving", in.OperationID, "args", in.String())
var resp []*pbRelay.SingleMsgToUser
var RecvID string
msg := open_im_sdk.MsgData{
SendID: in.SendID,
RecvID: in.RecvID,
MsgFrom: in.MsgFrom,
ContentType: in.ContentType,
SessionType: in.SessionType,
SenderNickName: in.SenderNickName,
SenderFaceURL: in.SenderFaceURL,
ClientMsgID: in.ClientMsgID,
ServerMsgID: in.ServerMsgID,
Content: in.Content,
Seq: in.RecvSeq,
SendTime: in.SendTime,
SenderPlatformID: in.PlatformID,
}
msgBytes, _ := proto.Marshal(&msg)
mReply := Resp{
ReqIdentifier: constant.WSPushMsg,
OperationID: in.OperationID,
Data: msgBytes,
}
var replyBytes bytes.Buffer
enc := gob.NewEncoder(&replyBytes)
err := enc.Encode(mReply)
if err != nil {
log.NewError(in.OperationID, "data encode err", err.Error())
}
switch in.GetSessionType() {
case constant.SingleChatType:
RecvID = in.GetRecvID()
case constant.GroupChatType:
RecvID = strings.Split(in.GetRecvID(), " ")[0]
}
var tag bool
var UIDAndPID []string
userIDList := genUidPlatformArray(RecvID)
for _, v := range userIDList {
UIDAndPID = strings.Split(v, " ")
if conn := ws.getUserConn(v); conn != nil {
tag = true
resultCode := sendMsgToUser(conn, replyBytes.Bytes(), in, UIDAndPID[1], UIDAndPID[0])
temp := &pbRelay.SingleMsgToUser{
ResultCode: resultCode,
RecvID: UIDAndPID[0],
RecvPlatFormID: utils.PlatformNameToID(UIDAndPID[1]),
}
resp = append(resp, temp)
} else {
temp := &pbRelay.SingleMsgToUser{
ResultCode: -1,
RecvID: UIDAndPID[0],
RecvPlatFormID: utils.PlatformNameToID(UIDAndPID[1]),
}
resp = append(resp, temp)
}
}
if !tag {
log.NewError(in.OperationID, "push err ,no matched ws conn not in map", in.String())
}
return &pbRelay.MsgToUserResp{
Resp: resp,
}, nil
}
func sendMsgToUser(conn *UserConn, bMsg []byte, in *pbRelay.MsgToUserReq, RecvPlatForm, RecvID string) (ResultCode int64) {
err := ws.writeMsg(conn, websocket.BinaryMessage, bMsg)
if err != nil {
log.ErrorByKv("PushMsgToUser is failed By Ws", "", "Addr", conn.RemoteAddr().String(),
"error", err, "senderPlatform", utils.PlatformIDToName(in.PlatformID), "recvPlatform", RecvPlatForm, "args", in.String(), "recvID", RecvID)
ResultCode = -2
return ResultCode
} else {
log.InfoByKv("PushMsgToUser is success By Ws", in.OperationID, "args", in.String(), "recvPlatForm", RecvPlatForm, "recvID", RecvID)
ResultCode = 0
return ResultCode
}
}
func genUidPlatformArray(uid string) (array []string) {
for i := 1; i <= utils.LinuxPlatformID; i++ {
array = append(array, uid+" "+utils.PlatformIDToName(int32(i)))
}
return array
}
+103
View File
@@ -0,0 +1,103 @@
/*
** description("").
** copyright('Open_IM,www.Open_IM.io').
** author("fg,Gordon@tuoyun.net").
** time(2021/5/21 15:29).
*/
package gate
import (
"Open_IM/pkg/common/constant"
"Open_IM/pkg/common/log"
open_im_sdk "Open_IM/pkg/proto/sdk_ws"
"github.com/golang/protobuf/proto"
)
type Req struct {
ReqIdentifier int32 `json:"reqIdentifier" validate:"required"`
Token string `json:"token" `
SendID string `json:"sendID" validate:"required"`
OperationID string `json:"operationID" validate:"required"`
MsgIncr string `json:"msgIncr" validate:"required"`
Data []byte `json:"data"`
}
type Resp struct {
ReqIdentifier int32 `json:"reqIdentifier"`
MsgIncr string `json:"msgIncr"`
OperationID string `json:"operationID"`
ErrCode int32 `json:"errCode"`
ErrMsg string `json:"errMsg"`
Data []byte `json:"data"`
}
type SeqData struct {
SeqBegin int64 `mapstructure:"seqBegin" validate:"required"`
SeqEnd int64 `mapstructure:"seqEnd" validate:"required"`
}
type MsgData struct {
PlatformID int32 `mapstructure:"platformID" validate:"required"`
SessionType int32 `mapstructure:"sessionType" validate:"required"`
MsgFrom int32 `mapstructure:"msgFrom" validate:"required"`
ContentType int32 `mapstructure:"contentType" validate:"required"`
RecvID string `mapstructure:"recvID" validate:"required"`
ForceList []string `mapstructure:"forceList"`
Content string `mapstructure:"content" validate:"required"`
Options map[string]interface{} `mapstructure:"options" validate:"required"`
ClientMsgID string `mapstructure:"clientMsgID" validate:"required"`
OfflineInfo map[string]interface{} `mapstructure:"offlineInfo" validate:"required"`
Ext map[string]interface{} `mapstructure:"ext"`
}
type MaxSeqResp struct {
MaxSeq int64 `json:"maxSeq"`
}
type PullMessageResp struct {
}
type SeqListData struct {
SeqList []int64 `mapstructure:"seqList" validate:"required"`
}
func (ws *WServer) argsValidate(m *Req, r int32) (isPass bool, errCode int32, errMsg string, returnData interface{}) {
switch r {
case constant.WSSendMsg:
data := open_im_sdk.UserSendMsgReq{}
if err := proto.Unmarshal(m.Data, &data); err != nil {
log.ErrorByKv("Decode Data struct err", "", "err", err.Error(), "reqIdentifier", r)
return false, 203, err.Error(), nil
}
if err := validate.Struct(data); err != nil {
log.ErrorByKv("data args validate err", "", "err", err.Error(), "reqIdentifier", r)
return false, 204, err.Error(), nil
}
return true, 0, "", data
case constant.WSPullMsgBySeqList:
data := open_im_sdk.PullMessageBySeqListReq{}
if err := proto.Unmarshal(m.Data, &data); err != nil {
log.ErrorByKv("Decode Data struct err", "", "err", err.Error(), "reqIdentifier", r)
return false, 203, err.Error(), nil
}
if err := validate.Struct(data); err != nil {
log.ErrorByKv("data args validate err", "", "err", err.Error(), "reqIdentifier", r)
return false, 204, err.Error(), nil
}
return true, 0, "", data
default:
}
return false, 204, "args err", nil
//b := bytes.NewBuffer(m.Data)
//dec := gob.NewDecoder(b)
//err := dec.Decode(&data)
//if err != nil {
// log.ErrorByKv("Decode Data struct err", "", "err", err.Error(), "reqIdentifier", r)
// return false, 203, err.Error(), nil
//}
//if err := mapstructure.WeakDecode(m.Data, &data); err != nil {
// log.ErrorByKv("map to Data struct err", "", "err", err.Error(), "reqIdentifier", r)
// return false, 203, err.Error(), nil
//} else
}
+165
View File
@@ -0,0 +1,165 @@
package gate
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/utils"
"github.com/gorilla/websocket"
"net/http"
"sync"
"time"
)
type UserConn struct {
*websocket.Conn
w *sync.Mutex
}
type WServer struct {
wsAddr string
wsMaxConnNum int
wsUpGrader *websocket.Upgrader
wsConnToUser map[*UserConn]string
wsUserToConn map[string]*UserConn
}
func (ws *WServer) onInit(wsPort int) {
ip := utils.ServerIP
ws.wsAddr = ip + ":" + utils.IntToString(wsPort)
ws.wsMaxConnNum = config.Config.LongConnSvr.WebsocketMaxConnNum
ws.wsConnToUser = make(map[*UserConn]string)
ws.wsUserToConn = make(map[string]*UserConn)
ws.wsUpGrader = &websocket.Upgrader{
HandshakeTimeout: time.Duration(config.Config.LongConnSvr.WebsocketTimeOut) * time.Second,
ReadBufferSize: config.Config.LongConnSvr.WebsocketMaxMsgLen,
CheckOrigin: func(r *http.Request) bool { return true },
}
}
func (ws *WServer) run() {
http.HandleFunc("/", ws.wsHandler) //Get request from client to handle by wsHandler
err := http.ListenAndServe(ws.wsAddr, nil) //Start listening
if err != nil {
log.ErrorByKv("Ws listening err", "", "err", err.Error())
}
}
func (ws *WServer) wsHandler(w http.ResponseWriter, r *http.Request) {
if ws.headerCheck(w, r) {
query := r.URL.Query()
conn, err := ws.wsUpGrader.Upgrade(w, r, nil) //Conn is obtained through the upgraded escalator
if err != nil {
log.ErrorByKv("upgrade http conn err", "", "err", err)
return
} else {
//Connection mapping relationship,
//userID+" "+platformID->conn
SendID := query["sendID"][0] + " " + utils.PlatformIDToName(int32(utils.StringToInt64(query["platformID"][0])))
//Initialize a lock for each user
newConn := &UserConn{conn, new(sync.Mutex)}
ws.addUserConn(SendID, newConn)
go ws.readMsg(newConn)
}
}
}
func (ws *WServer) readMsg(conn *UserConn) {
for {
messageType, msg, err := conn.ReadMessage()
if messageType == websocket.PingMessage {
log.NewInfo("", "this is a pingMessage")
}
if err != nil {
log.ErrorByKv("WS ReadMsg error", "", "userIP", conn.RemoteAddr().String(), "userUid", ws.getUserUid(conn), "error", err)
ws.delUserConn(conn)
return
} else {
//log.ErrorByKv("test", "", "msgType", msgType, "userIP", conn.RemoteAddr().String(), "userUid", ws.getUserUid(conn))
}
ws.msgParse(conn, msg)
//ws.writeMsg(conn, 1, chat)
}
}
func (ws *WServer) writeMsg(conn *UserConn, a int, msg []byte) error {
conn.w.Lock()
defer conn.w.Unlock()
return conn.WriteMessage(a, msg)
}
func (ws *WServer) addUserConn(uid string, conn *UserConn) {
rwLock.Lock()
defer rwLock.Unlock()
if oldConn, ok := ws.wsUserToConn[uid]; ok {
err := oldConn.Close()
delete(ws.wsConnToUser, oldConn)
if err != nil {
log.ErrorByKv("close err", "", "uid", uid, "conn", conn)
}
} else {
log.InfoByKv("this user is first login", "", "uid", uid)
}
ws.wsConnToUser[conn] = uid
ws.wsUserToConn[uid] = conn
log.WarnByKv("WS Add operation", "", "wsUser added", ws.wsUserToConn, "uid", uid, "online_num", len(ws.wsUserToConn))
}
func (ws *WServer) delUserConn(conn *UserConn) {
rwLock.Lock()
defer rwLock.Unlock()
var uidPlatform string
if uid, ok := ws.wsConnToUser[conn]; ok {
uidPlatform = uid
if _, ok = ws.wsUserToConn[uid]; ok {
delete(ws.wsUserToConn, uid)
log.WarnByKv("WS delete operation", "", "wsUser deleted", ws.wsUserToConn, "uid", uid, "online_num", len(ws.wsUserToConn))
} else {
log.WarnByKv("uid not exist", "", "wsUser deleted", ws.wsUserToConn, "uid", uid, "online_num", len(ws.wsUserToConn))
}
delete(ws.wsConnToUser, conn)
}
err := conn.Close()
if err != nil {
log.ErrorByKv("close err", "", "uid", uidPlatform)
}
}
func (ws *WServer) getUserConn(uid string) *UserConn {
rwLock.RLock()
defer rwLock.RUnlock()
if conn, ok := ws.wsUserToConn[uid]; ok {
return conn
}
return nil
}
func (ws *WServer) getUserUid(conn *UserConn) string {
rwLock.RLock()
defer rwLock.RUnlock()
if uid, ok := ws.wsConnToUser[conn]; ok {
return uid
}
return ""
}
func (ws *WServer) headerCheck(w http.ResponseWriter, r *http.Request) bool {
status := http.StatusUnauthorized
query := r.URL.Query()
if len(query["token"]) != 0 && len(query["sendID"]) != 0 && len(query["platformID"]) != 0 {
if !utils.VerifyToken(query["token"][0], query["sendID"][0]) {
log.ErrorByKv("Token verify failed", "", "query", query)
w.Header().Set("Sec-Websocket-Version", "13")
http.Error(w, http.StatusText(status), status)
return false
} else {
log.InfoByKv("Connection Authentication Success", "", "token", query["token"][0], "userID", query["sendID"][0])
return true
}
} else {
log.ErrorByKv("Args err", "", "query", query)
w.Header().Set("Sec-Websocket-Version", "13")
http.Error(w, http.StatusText(status), status)
return false
}
}
+25
View File
@@ -0,0 +1,25 @@
package logic
import (
"Open_IM/pkg/common/db"
"Open_IM/pkg/common/db/mysql_model/im_mysql_model"
"Open_IM/pkg/common/log"
pbMsg "Open_IM/pkg/proto/chat"
"Open_IM/pkg/utils"
)
func saveUserChat(uid string, pbMsg *pbMsg.MsgSvrToPushSvrChatMsg) error {
time := utils.GetCurrentTimestampByMill()
seq, err := db.DB.IncrUserSeq(uid)
if err != nil {
log.NewError(pbMsg.OperationID, "data insert to redis err", err.Error(), pbMsg.String())
return err
}
pbMsg.RecvSeq = seq
log.NewInfo(pbMsg.OperationID, "IncrUserSeq cost time", utils.GetCurrentTimestampByMill()-time)
return db.DB.SaveUserChat(uid, pbMsg.SendTime, pbMsg)
}
func getGroupList(groupID string) ([]string, error) {
return im_mysql_model.SelectGroupList(groupID)
}
@@ -0,0 +1,162 @@
package logic
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/constant"
kfk "Open_IM/pkg/common/kafka"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbMsg "Open_IM/pkg/proto/chat"
pbPush "Open_IM/pkg/proto/push"
"Open_IM/pkg/utils"
"context"
"github.com/Shopify/sarama"
"github.com/golang/protobuf/proto"
"strings"
)
type fcb func(msg []byte, msgKey string)
type HistoryConsumerHandler struct {
msgHandle map[string]fcb
historyConsumerGroup *kfk.MConsumerGroup
}
func (mc *HistoryConsumerHandler) Init() {
mc.msgHandle = make(map[string]fcb)
mc.msgHandle[config.Config.Kafka.Ws2mschat.Topic] = mc.handleChatWs2Mongo
mc.historyConsumerGroup = kfk.NewMConsumerGroup(&kfk.MConsumerGroupConfig{KafkaVersion: sarama.V0_10_2_0,
OffsetsInitial: sarama.OffsetNewest, IsReturnErr: false}, []string{config.Config.Kafka.Ws2mschat.Topic},
config.Config.Kafka.Ws2mschat.Addr, config.Config.Kafka.ConsumerGroupID.MsgToMongo)
}
func (mc *HistoryConsumerHandler) handleChatWs2Mongo(msg []byte, msgKey string) {
log.InfoByKv("chat come mongo!!!", "", "chat", string(msg))
time := utils.GetCurrentTimestampByNano()
pbData := pbMsg.WSToMsgSvrChatMsg{}
err := proto.Unmarshal(msg, &pbData)
if err != nil {
log.ErrorByKv("msg_transfer Unmarshal chat err", "", "chat", string(msg), "err", err.Error())
return
}
pbSaveData := pbMsg.MsgSvrToPushSvrChatMsg{}
pbSaveData.SendID = pbData.SendID
pbSaveData.SenderNickName = pbData.SenderNickName
pbSaveData.SenderFaceURL = pbData.SenderFaceURL
pbSaveData.ClientMsgID = pbData.ClientMsgID
pbSaveData.SendTime = pbData.SendTime
pbSaveData.Content = pbData.Content
pbSaveData.MsgFrom = pbData.MsgFrom
pbSaveData.ContentType = pbData.ContentType
pbSaveData.SessionType = pbData.SessionType
pbSaveData.MsgID = pbData.MsgID
pbSaveData.OperationID = pbData.OperationID
pbSaveData.RecvID = pbData.RecvID
pbSaveData.PlatformID = pbData.PlatformID
Options := utils.JsonStringToMap(pbData.Options)
//Control whether to store offline messages (mongo)
isHistory := utils.GetSwitchFromOptions(Options, "history")
//Control whether to store history messages (mysql)
isPersist := utils.GetSwitchFromOptions(Options, "persistent")
switch pbData.SessionType {
case constant.SingleChatType:
log.NewDebug(pbSaveData.OperationID, "msg_transfer chat type = SingleChatType", isHistory, isPersist)
if isHistory {
if msgKey == pbSaveData.RecvID {
err := saveUserChat(pbData.RecvID, &pbSaveData)
if err != nil {
log.NewError(pbSaveData.OperationID, "single data insert to mongo err", err.Error(), pbSaveData.String())
return
}
} else if msgKey == pbSaveData.SendID {
err := saveUserChat(pbData.SendID, &pbSaveData)
if err != nil {
log.NewError(pbSaveData.OperationID, "single data insert to mongo err", err.Error(), pbSaveData.String())
return
}
}
log.NewDebug(pbSaveData.OperationID, "saveUserChat cost time ", utils.GetCurrentTimestampByNano()-time)
}
if msgKey == pbSaveData.RecvID {
pbSaveData.Options = pbData.Options
pbSaveData.OfflineInfo = pbData.OfflineInfo
go sendMessageToPush(&pbSaveData)
log.NewDebug(pbSaveData.OperationID, "sendMessageToPush cost time ", utils.GetCurrentTimestampByNano()-time)
}
case constant.GroupChatType:
log.NewDebug(pbSaveData.OperationID, "msg_transfer chat type = GroupChatType", isHistory, isPersist)
if isHistory {
uidAndGroupID := strings.Split(pbData.RecvID, " ")
err := saveUserChat(uidAndGroupID[0], &pbSaveData)
if err != nil {
log.NewError(pbSaveData.OperationID, "group data insert to mongo err", pbSaveData.String(), uidAndGroupID[0], err.Error())
return
}
}
pbSaveData.Options = pbData.Options
pbSaveData.OfflineInfo = pbData.OfflineInfo
go sendMessageToPush(&pbSaveData)
default:
log.NewError(pbSaveData.OperationID, "SessionType error", pbSaveData.String())
return
}
log.NewDebug(pbSaveData.OperationID, "msg_transfer handle topic data to database success...", pbSaveData.String())
}
func (HistoryConsumerHandler) Setup(_ sarama.ConsumerGroupSession) error { return nil }
func (HistoryConsumerHandler) Cleanup(_ sarama.ConsumerGroupSession) error { return nil }
func (mc *HistoryConsumerHandler) ConsumeClaim(sess sarama.ConsumerGroupSession,
claim sarama.ConsumerGroupClaim) error {
for msg := range claim.Messages() {
log.InfoByKv("kafka get info to mongo", "", "msgTopic", msg.Topic, "msgPartition", msg.Partition, "chat", string(msg.Value))
mc.msgHandle[msg.Topic](msg.Value, string(msg.Key))
sess.MarkMessage(msg, "")
}
return nil
}
func sendMessageToPush(message *pbMsg.MsgSvrToPushSvrChatMsg) {
log.InfoByKv("msg_transfer send message to push", message.OperationID, "message", message.String())
msg := pbPush.PushMsgReq{}
msg.OperationID = message.OperationID
msg.PlatformID = message.PlatformID
msg.Content = message.Content
msg.ContentType = message.ContentType
msg.SessionType = message.SessionType
msg.RecvID = message.RecvID
msg.SendID = message.SendID
msg.SenderNickName = message.SenderNickName
msg.SenderFaceURL = message.SenderFaceURL
msg.ClientMsgID = message.ClientMsgID
msg.MsgFrom = message.MsgFrom
msg.Options = message.Options
msg.RecvSeq = message.RecvSeq
msg.SendTime = message.SendTime
msg.MsgID = message.MsgID
msg.OfflineInfo = message.OfflineInfo
grpcConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImPushName)
if grpcConn == nil {
log.ErrorByKv("rpc dial failed", msg.OperationID, "push data", msg.String())
pid, offset, err := producer.SendMessage(message)
if err != nil {
log.ErrorByKv("kafka send failed", msg.OperationID, "send data", message.String(), "pid", pid, "offset", offset, "err", err.Error())
}
return
}
msgClient := pbPush.NewPushMsgServiceClient(grpcConn)
_, err := msgClient.PushMsg(context.Background(), &msg)
if err != nil {
log.ErrorByKv("rpc send failed", msg.OperationID, "push data", msg.String(), "err", err.Error())
pid, offset, err := producer.SendMessage(message)
if err != nil {
log.ErrorByKv("kafka send failed", msg.OperationID, "send data", message.String(), "pid", pid, "offset", offset, "err", err.Error())
}
} else {
log.InfoByKv("rpc send success", msg.OperationID, "push data", msg.String())
}
}
+25
View File
@@ -0,0 +1,25 @@
package logic
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/kafka"
"Open_IM/pkg/common/log"
)
var (
persistentCH PersistentConsumerHandler
historyCH HistoryConsumerHandler
producer *kafka.Producer
)
func Init() {
log.NewPrivateLog(config.Config.ModuleName.MsgTransferName)
persistentCH.Init()
historyCH.Init()
producer = kafka.NewKafkaProducer(config.Config.Kafka.Ms2pschat.Addr, config.Config.Kafka.Ms2pschat.Topic)
}
func Run() {
//register mysqlConsumerHandler to
go persistentCH.persistentConsumerGroup.RegisterHandleAndConsumer(&persistentCH)
go historyCH.historyConsumerGroup.RegisterHandleAndConsumer(&historyCH)
}
@@ -0,0 +1,75 @@
/*
** description("").
** copyright('tuoyun,www.tuoyun.net').
** author("fg,Gordon@tuoyun.net").
** time(2021/5/11 15:37).
*/
package logic
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/constant"
"Open_IM/pkg/common/db/mysql_model/im_mysql_msg_model"
kfk "Open_IM/pkg/common/kafka"
"Open_IM/pkg/common/log"
pbMsg "Open_IM/pkg/proto/chat"
"Open_IM/pkg/utils"
"github.com/Shopify/sarama"
"github.com/golang/protobuf/proto"
"strings"
)
type PersistentConsumerHandler struct {
msgHandle map[string]fcb
persistentConsumerGroup *kfk.MConsumerGroup
}
func (pc *PersistentConsumerHandler) Init() {
pc.msgHandle = make(map[string]fcb)
pc.msgHandle[config.Config.Kafka.Ws2mschat.Topic] = pc.handleChatWs2Mysql
pc.persistentConsumerGroup = kfk.NewMConsumerGroup(&kfk.MConsumerGroupConfig{KafkaVersion: sarama.V0_10_2_0,
OffsetsInitial: sarama.OffsetNewest, IsReturnErr: false}, []string{config.Config.Kafka.Ws2mschat.Topic},
config.Config.Kafka.Ws2mschat.Addr, config.Config.Kafka.ConsumerGroupID.MsgToMySql)
}
func (pc *PersistentConsumerHandler) handleChatWs2Mysql(msg []byte, msgKey string) {
log.InfoByKv("chat come here mysql!!!", "", "chat", string(msg))
pbData := pbMsg.WSToMsgSvrChatMsg{}
err := proto.Unmarshal(msg, &pbData)
if err != nil {
log.ErrorByKv("msg_transfer Unmarshal chat err", "", "chat", string(msg), "err", err.Error())
return
}
Options := utils.JsonStringToMap(pbData.Options)
//Control whether to store history messages (mysql)
isPersist := utils.GetSwitchFromOptions(Options, "persistent")
//Only process receiver data
if isPersist {
if msgKey == pbData.RecvID && pbData.SessionType == constant.SingleChatType {
log.InfoByKv("msg_transfer chat persisting", pbData.OperationID)
if err = im_mysql_msg_model.InsertMessageToChatLog(pbData); err != nil {
log.ErrorByKv("Message insert failed", pbData.OperationID, "err", err.Error(), "chat", pbData.String())
return
}
} else if pbData.SessionType == constant.GroupChatType && msgKey == "0" {
pbData.RecvID = strings.Split(pbData.RecvID, " ")[1]
log.InfoByKv("msg_transfer chat persisting", pbData.OperationID)
if err = im_mysql_msg_model.InsertMessageToChatLog(pbData); err != nil {
log.ErrorByKv("Message insert failed", pbData.OperationID, "err", err.Error(), "chat", pbData.String())
return
}
}
}
}
func (PersistentConsumerHandler) Setup(_ sarama.ConsumerGroupSession) error { return nil }
func (PersistentConsumerHandler) Cleanup(_ sarama.ConsumerGroupSession) error { return nil }
func (pc *PersistentConsumerHandler) ConsumeClaim(sess sarama.ConsumerGroupSession,
claim sarama.ConsumerGroupClaim) error {
for msg := range claim.Messages() {
log.InfoByKv("kafka get info to mysql", "", "msgTopic", msg.Topic, "msgPartition", msg.Partition, "chat", string(msg.Value))
pc.msgHandle[msg.Topic](msg.Value, string(msg.Key))
sess.MarkMessage(msg, "")
}
return nil
}
+85
View File
@@ -0,0 +1,85 @@
/*
** description("").
** copyright('open-im,www.open-im.io').
** author("fg,Gordon@tuoyun.net").
** time(2021/5/27 11:24).
*/
package content_struct
import (
"encoding/json"
)
type Content struct {
IsDisplay int32 `json:"isDisplay"`
ID string `json:"id"`
Text string `json:"text"`
}
func NewContentStructString(isDisplay int32, ID string, text string) string {
c := Content{IsDisplay: isDisplay, ID: ID, Text: text}
return c.contentToString()
}
func (c *Content) contentToString() string {
data, _ := json.Marshal(c)
dataString := string(data)
return dataString
}
type groupMemberFullInfo struct {
GroupId string `json:"groupID"`
UserId string `json:"userId"`
Role int `json:"role"`
JoinTime uint64 `json:"joinTime"`
NickName string `json:"nickName"`
FaceUrl string `json:"faceUrl"`
}
type AgreeOrRejectGroupMember struct {
GroupId string `json:"groupID"`
UserId string `json:"userId"`
Role int `json:"role"`
JoinTime uint64 `json:"joinTime"`
NickName string `json:"nickName"`
FaceUrl string `json:"faceUrl"`
Reason string `json:"reason"`
}
type AtTextContent struct {
Text string `json:"text"`
AtUserList []string `json:"atUserList"`
IsAtSelf bool `json:"isAtSelf"`
}
type CreateGroupSysMsg struct {
uIdCreator string `creatorUid`
initMemberList []groupMemberFullInfo `json: initMemberList`
CreateTime uint64 `json:"CreateTime"`
Text string `json:"text"`
}
type NotificationContent struct {
IsDisplay int32 `json:"isDisplay"`
DefaultTips string `json:"defaultTips"`
Detail string `json:"detail"`
}
func (c *NotificationContent) ContentToString() string {
data, _ := json.Marshal(c)
dataString := string(data)
return dataString
}
type KickGroupMemberApiReq struct {
GroupID string `json:"groupID"`
UidList []string `json:"uidList"`
Reason string `json:"reason"`
OperationID string `json:"operationID"`
}
func NewCreateGroupSysMsgString(create *CreateGroupSysMsg, text string) string {
create.Text = text
jstring, _ := json.Marshal(create)
return string(jstring)
}
+13
View File
@@ -0,0 +1,13 @@
package common
import (
"encoding/base64"
"fmt"
)
func GetAuthorization(Appkey string, MasterSecret string) string {
str := fmt.Sprintf("%s:%s", Appkey, MasterSecret)
buf := []byte(str)
Authorization := fmt.Sprintf("Basic %s", base64.StdEncoding.EncodeToString(buf))
return Authorization
}
+55
View File
@@ -0,0 +1,55 @@
package push
import (
"Open_IM/internal/push/jpush/common"
"Open_IM/internal/push/jpush/requestBody"
"Open_IM/pkg/common/config"
"bytes"
"encoding/json"
"io/ioutil"
"net/http"
)
type JPushResp struct {
}
func JGAccountListPush(accounts []string, content, detailContent, platform string) ([]byte, error) {
var pf requestBody.Platform
_ = pf.SetPlatform(platform)
var au requestBody.Audience
au.SetAlias(accounts)
var no requestBody.Notification
no.SetAlert(content)
var me requestBody.Message
me.SetMsgContent(detailContent)
var po requestBody.PushObj
po.SetPlatform(&pf)
po.SetAudience(&au)
po.SetNotification(&no)
po.SetMessage(&me)
con, err := json.Marshal(po)
if err != nil {
return nil, err
}
client := &http.Client{}
req, err := http.NewRequest("POST", config.Config.Push.Jpns.PushUrl, bytes.NewBuffer(con))
if err != nil {
return nil, err
}
req.Header.Set("Authorization", common.GetAuthorization(config.Config.Push.Jpns.AppKey, config.Config.Push.Jpns.MasterSecret))
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
result, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
return result, nil
}
@@ -0,0 +1,53 @@
package requestBody
const (
TAG = "tag"
TAG_AND = "tag_and"
TAG_NOT = "tag_not"
ALIAS = "alias"
REGISTRATION_ID = "registration_id"
SEGMENT = "segment"
ABTEST = "abtest"
)
type Audience struct {
Object interface{}
audience map[string][]string
}
func (a *Audience) set(key string, v []string) {
if a.audience == nil {
a.audience = make(map[string][]string)
a.Object = a.audience
}
//v, ok = this.audience[key]
//if ok {
// return
//}
a.audience[key] = v
}
func (a *Audience) SetTag(tags []string) {
a.set(TAG, tags)
}
func (a *Audience) SetTagAnd(tags []string) {
a.set(TAG_AND, tags)
}
func (a *Audience) SetTagNot(tags []string) {
a.set(TAG_NOT, tags)
}
func (a *Audience) SetAlias(alias []string) {
a.set(ALIAS, alias)
}
func (a *Audience) SetRegistrationId(ids []string) {
a.set(REGISTRATION_ID, ids)
}
func (a *Audience) SetAll() {
a.Object = "all"
}
@@ -0,0 +1,27 @@
package requestBody
type Message struct {
MsgContent string `json:"msg_content"`
Title string `json:"title,omitempty"`
ContentType string `json:"content_type,omitempty"`
Extras map[string]interface{} `json:"extras,omitempty"`
}
func (m *Message) SetMsgContent(c string) {
m.MsgContent = c
}
func (m *Message) SetTitle(t string) {
m.Title = t
}
func (m *Message) SetContentType(c string) {
m.ContentType = c
}
func (m *Message) SetExtras(key string, value interface{}) {
if m.Extras == nil {
m.Extras = make(map[string]interface{})
}
m.Extras[key] = value
}
@@ -0,0 +1,17 @@
package requestBody
type Notification struct {
Alert string `json:"alert,omitempty"`
Android *Android `json:"android,omitempty"`
IOS *Ios `json:"ios,omitempty"`
}
type Android struct {
}
type Ios struct {
}
func (n *Notification) SetAlert(alert string) {
n.Alert = alert
}
@@ -0,0 +1,83 @@
package requestBody
import (
"Open_IM/pkg/utils"
"errors"
)
const (
ANDROID = "android"
IOS = "ios"
QUICKAPP = "quickapp"
WINDOWSPHONE = "winphone"
ALL = "all"
)
type Platform struct {
Os interface{}
osArry []string
}
func (p *Platform) Set(os string) error {
if p.Os == nil {
p.osArry = make([]string, 0, 4)
} else {
switch p.Os.(type) {
case string:
return errors.New("platform is all")
default:
}
}
for _, value := range p.osArry {
if os == value {
return nil
}
}
switch os {
case IOS:
fallthrough
case ANDROID:
fallthrough
case QUICKAPP:
fallthrough
case WINDOWSPHONE:
p.osArry = append(p.osArry, os)
p.Os = p.osArry
default:
return errors.New("unknow platform")
}
return nil
}
func (p *Platform) SetPlatform(platform string) error {
switch platform {
case utils.AndroidPlatformStr:
return p.SetAndroid()
case utils.IOSPlatformStr:
return p.SetIOS()
default:
return errors.New("platform err")
}
}
func (p *Platform) SetIOS() error {
return p.Set(IOS)
}
func (p *Platform) SetAndroid() error {
return p.Set(ANDROID)
}
func (p *Platform) SetQuickApp() error {
return p.Set(QUICKAPP)
}
func (p *Platform) SetWindowsPhone() error {
return p.Set(WINDOWSPHONE)
}
func (p *Platform) SetAll() {
p.Os = ALL
}
@@ -0,0 +1,24 @@
package requestBody
type PushObj struct {
Platform interface{} `json:"platform"`
Audience interface{} `json:"audience"`
Notification interface{} `json:"notification,omitempty"`
Message interface{} `json:"message,omitempty"`
}
func (p *PushObj) SetPlatform(pf *Platform) {
p.Platform = pf.Os
}
func (p *PushObj) SetAudience(ad *Audience) {
p.Audience = ad.Object
}
func (p *PushObj) SetNotification(no *Notification) {
p.Notification = no
}
func (p *PushObj) SetMessage(m *Message) {
p.Message = m
}
+36
View File
@@ -0,0 +1,36 @@
/*
** description("").
** copyright('open-im,www.open-im.io').
** author("fg,Gordon@open-im.io").
** time(2021/3/22 15:33).
*/
package logic
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/kafka"
"Open_IM/pkg/common/log"
"Open_IM/pkg/utils"
)
var (
rpcServer RPCServer
pushCh PushConsumerHandler
pushTerminal []int32
producer *kafka.Producer
)
func Init(rpcPort int) {
log.NewPrivateLog(config.Config.ModuleName.PushName)
rpcServer.Init(rpcPort)
pushCh.Init()
pushTerminal = []int32{utils.IOSPlatformID, utils.AndroidPlatformID}
}
func init() {
producer = kafka.NewKafkaProducer(config.Config.Kafka.Ws2mschat.Addr, config.Config.Kafka.Ws2mschat.Topic)
}
func Run() {
go rpcServer.run()
go pushCh.pushConsumerGroup.RegisterHandleAndConsumer(&pushCh)
}
+67
View File
@@ -0,0 +1,67 @@
/*
** description("").
** copyright('Open_IM,www.Open_IM.io').
** author("fg,Gordon@tuoyun.net").
** time(2021/5/13 10:33).
*/
package logic
import (
"Open_IM/pkg/common/config"
kfk "Open_IM/pkg/common/kafka"
"Open_IM/pkg/common/log"
pbChat "Open_IM/pkg/proto/chat"
pbRelay "Open_IM/pkg/proto/relay"
"github.com/Shopify/sarama"
"github.com/golang/protobuf/proto"
)
type fcb func(msg []byte)
type PushConsumerHandler struct {
msgHandle map[string]fcb
pushConsumerGroup *kfk.MConsumerGroup
}
func (ms *PushConsumerHandler) Init() {
ms.msgHandle = make(map[string]fcb)
ms.msgHandle[config.Config.Kafka.Ms2pschat.Topic] = ms.handleMs2PsChat
ms.pushConsumerGroup = kfk.NewMConsumerGroup(&kfk.MConsumerGroupConfig{KafkaVersion: sarama.V0_10_2_0,
OffsetsInitial: sarama.OffsetNewest, IsReturnErr: false}, []string{config.Config.Kafka.Ms2pschat.Topic}, config.Config.Kafka.Ms2pschat.Addr,
config.Config.Kafka.ConsumerGroupID.MsgToPush)
}
func (ms *PushConsumerHandler) handleMs2PsChat(msg []byte) {
log.InfoByKv("msg come from kafka And push!!!", "", "msg", string(msg))
pbData := pbChat.MsgSvrToPushSvrChatMsg{}
if err := proto.Unmarshal(msg, &pbData); err != nil {
log.ErrorByKv("push Unmarshal msg err", "", "msg", string(msg), "err", err.Error())
return
}
sendPbData := pbRelay.MsgToUserReq{}
sendPbData.SendTime = pbData.SendTime
sendPbData.OperationID = pbData.OperationID
sendPbData.ServerMsgID = pbData.MsgID
sendPbData.MsgFrom = pbData.MsgFrom
sendPbData.ContentType = pbData.ContentType
sendPbData.SessionType = pbData.SessionType
sendPbData.RecvID = pbData.RecvID
sendPbData.Content = pbData.Content
sendPbData.SendID = pbData.SendID
sendPbData.SenderNickName = pbData.SenderNickName
sendPbData.SenderFaceURL = pbData.SenderFaceURL
sendPbData.ClientMsgID = pbData.ClientMsgID
sendPbData.PlatformID = pbData.PlatformID
sendPbData.RecvSeq = pbData.RecvSeq
//Call push module to send message to the user
MsgToUser(&sendPbData, pbData.OfflineInfo, pbData.Options)
}
func (PushConsumerHandler) Setup(_ sarama.ConsumerGroupSession) error { return nil }
func (PushConsumerHandler) Cleanup(_ sarama.ConsumerGroupSession) error { return nil }
func (ms *PushConsumerHandler) ConsumeClaim(sess sarama.ConsumerGroupSession,
claim sarama.ConsumerGroupClaim) error {
for msg := range claim.Messages() {
log.InfoByKv("kafka get info to mysql", "", "msgTopic", msg.Topic, "msgPartition", msg.Partition, "msg", string(msg.Value))
ms.msgHandle[msg.Topic](msg.Value)
}
return nil
}
+73
View File
@@ -0,0 +1,73 @@
package logic
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
"Open_IM/pkg/proto/push"
pbRelay "Open_IM/pkg/proto/relay"
"Open_IM/pkg/utils"
"context"
"google.golang.org/grpc"
"net"
"strings"
)
type RPCServer struct {
rpcPort int
rpcRegisterName string
etcdSchema string
etcdAddr []string
}
func (r *RPCServer) Init(rpcPort int) {
r.rpcPort = rpcPort
r.rpcRegisterName = config.Config.RpcRegisterName.OpenImPushName
r.etcdSchema = config.Config.Etcd.EtcdSchema
r.etcdAddr = config.Config.Etcd.EtcdAddr
}
func (r *RPCServer) run() {
ip := utils.ServerIP
registerAddress := ip + ":" + utils.IntToString(r.rpcPort)
listener, err := net.Listen("tcp", registerAddress)
if err != nil {
log.ErrorByKv("push module rpc listening port err", "", "err", err.Error())
return
}
defer listener.Close()
srv := grpc.NewServer()
defer srv.GracefulStop()
pbPush.RegisterPushMsgServiceServer(srv, r)
err = getcdv3.RegisterEtcd(r.etcdSchema, strings.Join(r.etcdAddr, ","), ip, r.rpcPort, r.rpcRegisterName, 10)
if err != nil {
log.ErrorByKv("register push module rpc to etcd err", "", "err", err.Error())
}
err = srv.Serve(listener)
if err != nil {
log.ErrorByKv("push module rpc start err", "", "err", err.Error())
return
}
}
func (r *RPCServer) PushMsg(_ context.Context, pbData *pbPush.PushMsgReq) (*pbPush.PushMsgResp, error) {
sendPbData := pbRelay.MsgToUserReq{}
sendPbData.SendTime = pbData.SendTime
sendPbData.OperationID = pbData.OperationID
sendPbData.ServerMsgID = pbData.MsgID
sendPbData.MsgFrom = pbData.MsgFrom
sendPbData.ContentType = pbData.ContentType
sendPbData.SenderNickName = pbData.SenderNickName
sendPbData.SenderFaceURL = pbData.SenderFaceURL
sendPbData.ClientMsgID = pbData.ClientMsgID
sendPbData.SessionType = pbData.SessionType
sendPbData.RecvID = pbData.RecvID
sendPbData.Content = pbData.Content
sendPbData.SendID = pbData.SendID
sendPbData.PlatformID = pbData.PlatformID
sendPbData.RecvSeq = pbData.RecvSeq
//Call push module to send message to the user
MsgToUser(&sendPbData, pbData.OfflineInfo, pbData.Options)
return &pbPush.PushMsgResp{
ResultCode: 0,
}, nil
}
+155
View File
@@ -0,0 +1,155 @@
/*
** description("").
** copyright('open-im,www.open-im.io').
** author("fg,Gordon@open-im.io").
** time(2021/3/5 14:31).
*/
package logic
import (
push "Open_IM/internal/push/jpush"
rpcChat "Open_IM/internal/rpc/chat"
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/constant"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbChat "Open_IM/pkg/proto/chat"
pbGroup "Open_IM/pkg/proto/group"
pbRelay "Open_IM/pkg/proto/relay"
"Open_IM/pkg/utils"
"context"
"encoding/json"
"strings"
)
type OpenIMContent struct {
SessionType int `json:"sessionType"`
From string `json:"from"`
To string `json:"to"`
Seq int64 `json:"seq"`
}
type AtContent struct {
Text string `json:"text"`
AtUserList []string `json:"atUserList"`
IsAtSelf bool `json:"isAtSelf"`
}
func MsgToUser(sendPbData *pbRelay.MsgToUserReq, OfflineInfo, Options string) {
var wsResult []*pbRelay.SingleMsgToUser
MOptions := utils.JsonStringToMap(Options) //Control whether to push message to sender's other terminal
//isSenderSync := utils.GetSwitchFromOptions(MOptions, "senderSync")
isOfflinePush := utils.GetSwitchFromOptions(MOptions, "offlinePush")
log.InfoByKv("Get chat from msg_transfer And push chat", sendPbData.OperationID, "PushData", sendPbData)
grpcCons := getcdv3.GetConn4Unique(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImOnlineMessageRelayName)
//Online push message
log.InfoByKv("test", sendPbData.OperationID, "len grpc", len(grpcCons), "data", sendPbData)
for _, v := range grpcCons {
msgClient := pbRelay.NewOnlineMessageRelayServiceClient(v)
reply, err := msgClient.MsgToUser(context.Background(), sendPbData)
if err != nil {
log.InfoByKv("push data to client rpc err", sendPbData.OperationID, "err", err)
}
if reply != nil && reply.Resp != nil && err == nil {
wsResult = append(wsResult, reply.Resp...)
}
}
log.InfoByKv("push_result", sendPbData.OperationID, "result", wsResult, "sendData", sendPbData)
if sendPbData.ContentType != constant.Typing && sendPbData.ContentType != constant.HasReadReceipt {
if isOfflinePush {
for _, v := range wsResult {
if v.ResultCode == 0 {
continue
}
//supported terminal
for _, t := range pushTerminal {
if v.RecvPlatFormID == t {
//Use offline push messaging
var UIDList []string
UIDList = append(UIDList, v.RecvID)
customContent := OpenIMContent{
SessionType: int(sendPbData.SessionType),
From: sendPbData.SendID,
To: sendPbData.RecvID,
Seq: sendPbData.RecvSeq,
}
bCustomContent, _ := json.Marshal(customContent)
jsonCustomContent := string(bCustomContent)
var content string
switch sendPbData.ContentType {
case constant.Text:
content = constant.ContentType2PushContent[constant.Text]
case constant.Picture:
content = constant.ContentType2PushContent[constant.Picture]
case constant.Voice:
content = constant.ContentType2PushContent[constant.Voice]
case constant.Video:
content = constant.ContentType2PushContent[constant.Video]
case constant.File:
content = constant.ContentType2PushContent[constant.File]
case constant.AtText:
a := AtContent{}
_ = utils.JsonStringToStruct(sendPbData.Content, &a)
if utils.IsContain(v.RecvID, a.AtUserList) {
content = constant.ContentType2PushContent[constant.AtText] + constant.ContentType2PushContent[constant.Common]
} else {
content = constant.ContentType2PushContent[constant.GroupMsg]
}
default:
}
pushResult, err := push.JGAccountListPush(UIDList, content, jsonCustomContent, utils.PlatformIDToName(t))
if err != nil {
log.NewError(sendPbData.OperationID, "offline push error", sendPbData.String(), err.Error(), t)
} else {
log.NewDebug(sendPbData.OperationID, "offline push return result is ", string(pushResult), sendPbData, t)
}
}
}
}
}
}
}
func SendMsgByWS(m *pbChat.WSToMsgSvrChatMsg) {
m.MsgID = rpcChat.GetMsgID(m.SendID)
m.ClientMsgID = m.MsgID
switch m.SessionType {
case constant.SingleChatType:
sendMsgToKafka(m, m.SendID, "msgKey--sendID")
sendMsgToKafka(m, m.RecvID, "msgKey--recvID")
case constant.GroupChatType:
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImGroupName)
client := pbGroup.NewGroupClient(etcdConn)
req := &pbGroup.GetGroupAllMemberReq{
GroupID: m.RecvID,
Token: config.Config.Secret,
OperationID: m.OperationID,
}
reply, err := client.GetGroupAllMember(context.Background(), req)
if err != nil {
log.Error(m.Token, m.OperationID, "rpc getGroupInfo failed, err = %s", err.Error())
return
}
if reply.ErrorCode != 0 {
log.Error(m.Token, m.OperationID, "rpc getGroupInfo failed, err = %s", reply.ErrorMsg)
return
}
groupID := m.RecvID
for i, v := range reply.MemberList {
m.RecvID = v.UserId + " " + groupID
sendMsgToKafka(m, utils.IntToString(i), "msgKey--recvID+\" \"+groupID")
}
default:
}
}
func sendMsgToKafka(m *pbChat.WSToMsgSvrChatMsg, key string, flag string) {
pid, offset, err := producer.SendMessage(m, key)
if err != nil {
log.ErrorByKv("kafka send failed", m.OperationID, "send data", m.String(), "pid", pid, "offset", offset, "err", err.Error(), flag, key)
}
}
+34
View File
@@ -0,0 +1,34 @@
package logic
import (
tpns "Open_IM/internal/push/sdk/tpns-server-sdk-go/go"
"Open_IM/internal/push/sdk/tpns-server-sdk-go/go/auth"
"Open_IM/internal/push/sdk/tpns-server-sdk-go/go/common"
"Open_IM/internal/push/sdk/tpns-server-sdk-go/go/req"
"Open_IM/pkg/common/config"
)
var badgeType = -2
var iosAcceptId = auth.Auther{AccessID: config.Config.Push.Tpns.Ios.AccessID, SecretKey: config.Config.Push.Tpns.Ios.SecretKey}
func IOSAccountListPush(accounts []string, title, content, jsonCustomContent string) {
var iosMessage = tpns.Message{
Title: title,
Content: content,
IOS: &tpns.IOSParams{
Aps: &tpns.Aps{
BadgeType: &badgeType,
Sound: "default",
Category: "INVITE_CATEGORY",
},
CustomContent: jsonCustomContent,
//CustomContent: `"{"key\":\"value\"}"`,
},
}
pushReq, reqBody, err := req.NewListAccountPush(accounts, iosMessage)
if err != nil {
return
}
iosAcceptId.Auth(pushReq, auth.UseSignAuthored, iosAcceptId, reqBody)
common.PushAndGetResult(pushReq)
}
@@ -0,0 +1,62 @@
package auth
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
b64 "encoding/base64"
"encoding/hex"
"fmt"
"net/http"
"strconv"
"time"
)
type Auther struct {
AccessID string
SecretKey string
}
var UseSignAuthored = true
func (a *Auther) Auth(req *http.Request, useSignAuthored bool, auth Auther, reqBody string) {
if useSignAuthored {
now := time.Now()
timeStamp := now.Unix()
req.Header.Add("AccessId", auth.AccessID)
req.Header.Add("TimeStamp", strconv.Itoa(int(timeStamp)))
sign := GenSign(uint64(timeStamp), auth.AccessID, auth.SecretKey, reqBody)
req.Header.Add("Sign", sign)
} else {
author := makeAuthHeader(a.AccessID, a.SecretKey)
//log.Printf("author string:%v", author)
req.Header.Add("Authorization", author)
}
//req.Header.Add("Content-Type", "application/json")
}
func makeAuthHeader(appID, secretKey string) string {
base64Str := base64.StdEncoding.EncodeToString(
[]byte(
fmt.Sprintf("%s:%s", appID, secretKey),
),
)
return fmt.Sprintf("Basic %s", base64Str)
}
func GenSign(timeStamp uint64, accessId string, secretKey, requestBody string) string {
signBody := strconv.Itoa(int(timeStamp)) + accessId + requestBody
// Create a new HMAC by defining the hash type and the key (as byte array)
h := hmac.New(sha256.New, []byte(secretKey))
// Write Data to it
h.Write([]byte(signBody))
// Get result and encode as hexadecimal string
sha := hex.EncodeToString(h.Sum(nil))
//fmt.Println()
//fmt.Println("timeStamp: " + strconv.Itoa(int(timeStamp)) + " accessID:" + accessId + " body:" + requestBody)
sEnc := b64.StdEncoding.EncodeToString([]byte(sha))
//fmt.Println("final Result " + sEnc)
return sEnc
}
@@ -0,0 +1,18 @@
package client
import (
"net/http"
"time"
)
func New() *http.Client {
return &http.Client{
Transport: &http.Transport{
MaxIdleConns: 100,
MaxIdleConnsPerHost: 100,
IdleConnTimeout: 30 * time.Second,
DisableCompression: false,
DisableKeepAlives: false,
},
}
}
@@ -0,0 +1,62 @@
package common
import (
tpns "Open_IM/internal/push/sdk/tpns-server-sdk-go/go"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func PushAndGetResult(pushReq *http.Request) {
c := &http.Client{}
rsp, err := c.Do(pushReq)
fmt.Println()
if err != nil {
//fmt.Printf("http err:%v", err)
return
}
defer rsp.Body.Close()
body, err := ioutil.ReadAll(rsp.Body)
//fmt.Printf("http ReadAll err:%v, body:%v ", err, string(body))
if err != nil {
return
}
r := &tpns.CommonRsp{}
json.Unmarshal(body, r)
//fmt.Printf("push result: %+v", r)
}
func UploadFile(req *http.Request) (int, error) {
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return 0, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return 0, err
}
if resp.StatusCode != http.StatusOK {
return 0, fmt.Errorf("response error, status: %s, body: %s", resp.Status, string(body))
}
type uploadResponse struct {
RetCode int `json:"retCode"`
ErrMsg string `json:"errMsg"`
UploadId int `json:"uploadId"`
}
var ur uploadResponse
if err := json.Unmarshal(body, &ur); err != nil {
return 0, err
}
if ur.RetCode != 0 {
return 0, fmt.Errorf("response with %d:%s", ur.RetCode, ur.ErrMsg)
}
return ur.UploadId, nil
}
@@ -0,0 +1,8 @@
package common
import "encoding/json"
func ToJson(v interface{}) string {
bs, _ := json.Marshal(v)
return string(bs)
}
@@ -0,0 +1,256 @@
package tpns
type CommonRspEnv string
const (
// EnvProd
EnvProd CommonRspEnv = "product"
// EnvDev
EnvDev CommonRspEnv = "dev"
)
type CommonRsp struct {
// TODO: doc this
Seq int64 `json:"seq"`
PushID string `json:"push_id"`
RetCode int `json:"ret_code"`
Environment CommonRspEnv `json:"environment"`
ErrMsg string `json:"err_msg,omitempty"`
Result map[string]string `json:"result,omitempty"`
}
type AudienceType string
const (
AdAll AudienceType = "all"
AdTag AudienceType = "tag"
AdToken AudienceType = "token"
AdTokenList AudienceType = "token_list"
AdAccount AudienceType = "account"
AdAccountList AudienceType = "account_list"
AdPackageAccount AudienceType = "package_account_push"
AdPackageToken AudienceType = "package_token_push"
)
// MessageType push API message_type
type MessageType string
const (
MsgTypeNotify MessageType = "notify"
MsgTypeMessage MessageType = "message"
)
type Request struct {
AudienceType AudienceType `json:"audience_type"`
Message Message `json:"message"`
MessageType MessageType `json:"message_type"`
Tag []TagRule `json:"tag_rules,omitempty"`
TokenList []string `json:"token_list,omitempty"`
AccountList []string `json:"account_list,omitempty"`
Environment CommonRspEnv `json:"environment,omitempty"`
UploadId int `json:"upload_id,omitempty"`
ExpireTime int `json:"expire_time,omitempty"`
SendTime string `json:"send_time,omitempty"`
MultiPkg bool `json:"multi_pkg,omitempty"`
PlanId string `json:"plan_id,omitempty"`
AccountPushType int `json:"account_push_type,omitempty"`
PushSpeed int `json:"push_speed,omitempty"`
CollapseId int `json:"collapse_id"`
TPNSOnlinePushType int `json:"tpns_online_push_type"`
ChannelRules []*ChannelDistributeRule `json:"channel_rules,omitempty"`
LoopParam *PushLoopParam `json:"loop_param,omitempty"`
ForceCollapse bool `json:"force_collapse"`
}
type TagListOperation string
type ChannelDistributeRule struct {
ChannelName string `json:"channel"`
Disable bool `json:"disable"`
}
type PushLoopParam struct {
StartDate string `json:"startDate"`
EndDate string `json:"endDate"`
LoopType PushLoopType `json:"loopType"`
LoopDayIndexs []uint32 `json:"loopDayIndexs"`
DayTimes []string `json:"dayTimes"`
}
type PushLoopType int32
const (
TagListOpAnd TagListOperation = "AND"
TagListOpOr TagListOperation = "OR"
)
type TagType string
const (
XGAutoProvince TagType = "xg_auto_province"
XGAutoActive TagType = "xg_auto_active"
XGUserDefine TagType = "xg_user_define"
XGAutoVersion TagType = "xg_auto_version"
XGAutoSdkversion TagType = "xg_auto_sdkversion"
XGAutoDevicebrand TagType = "xg_auto_devicebrand"
XGAutoDeviceversion TagType = "xg_auto_deviceversion"
XGAutoCountry TagType = "xg_auto_country"
)
type TagRule struct {
TagItems []TagItem `json:"tag_items"`
IsNot bool `json:"is_not"`
Operator TagListOperation `json:"operator"`
}
type TagItem struct {
// 标签
Tags []string `json:"tags"`
IsNot bool `json:"is_not"`
TagsOperator TagListOperation `json:"tags_operator"`
ItemsOperator TagListOperation `json:"items_operator"`
TagType TagType `json:"tag_type"`
}
type Message struct {
Title string `json:"title,omitempty"`
Content string `json:"content,omitempty"`
AcceptTime []AcceptTimeItem `json:"accept_time,omitempty"`
Android *AndroidParams `json:"android,omitempty"`
IOS *IOSParams `json:"ios,omitempty"`
ThreadId string `json:"thread_id,omitempty"`
ThreadSumtext string `json:"thread_sumtext,omitempty"`
XGMediaResources string `json:"xg_media_resources,omitempty"`
XGMediaAudioResources string `json:"xg_media_audio_resources,omitempty"`
}
type AcceptTimeItem struct {
Start HourAndMin `json:"start,omitempty"`
End HourAndMin `json:"end,omitempty"`
}
type HourAndMin struct {
Hour string `json:"hour,omitempty"`
Min string `json:"min,omitempty"`
}
type AndroidParams struct {
BuilderId *int `json:"builder_id,omitempty"`
Ring *int `json:"ring,omitempty"`
RingRaw string `json:"ring_raw,omitempty"`
Vibrate *int `json:"vibrate,omitempty"`
Lights *int `json:"lights,omitempty"`
Clearable *int `json:"clearable,omitempty"`
IconType *int `json:"icon_type"`
IconRes string `json:"icon_res,omitempty"`
StyleId *int `json:"style_id,omitempty"`
SmallIcon string `json:"small_icon,omitempty"`
Action *Action `json:"action,omitempty"`
CustomContent string `json:"custom_content,omitempty"`
ShowType *int `json:"show_type,omitempty"`
NChId string `json:"n_ch_id,omitempty"`
NChName string `json:"n_ch_name,omitempty"`
HwChId string `json:"hw_ch_id,omitempty"`
XmChId string `json:"xm_ch_id,omitempty"`
OppoChId string `json:"oppo_ch_id,omitempty"`
VivoChId string `json:"vivo_ch_id,omitempty"`
BadgeType *int `json:"badge_type,omitempty"`
IconColor *int `json:"icon_color,omitempty"`
}
type Action struct {
ActionType *int `json:"action_type,omitempty"`
Activity string `json:"activity"`
AtyAttr AtyAttr `json:"aty_attr,omitempty"`
Intent string `json:"intent"`
Browser Browser `json:"browser,omitempty"`
}
type Browser struct {
Url string `json:"url,omitempty"`
Confirm *int `json:"confirm,omitempty"`
}
type AtyAttr struct {
AttrIf *int `json:"if,omitempty"`
Pf *int `json:"pf,omitempty"`
}
type IOSParams struct {
Aps *Aps `json:"aps,omitempty"`
CustomContent string `json:"custom_content,omitempty"`
}
type Aps struct {
Alert map[string]string `json:"alert,omitempty"`
BadgeType *int `json:"badge_type,omitempty"`
Category string `json:"category,omitempty"`
ContentAvailableInt *int `json:"content-available,omitempty"`
MutableContent *int `json:"mutable-content,omitempty"`
Sound string `json:"sound,omitempty"`
}
@@ -0,0 +1,403 @@
package req
import (
tpns "Open_IM/internal/push/sdk/tpns-server-sdk-go/go"
"bytes"
"encoding/json"
"io"
"mime/multipart"
"net/http"
"os"
"path/filepath"
)
var PushURL = "https://api.tpns.tencent.com/v3/push/app"
//var PushURL = "https://test.api.tpns.tencent.com/v3/push/app"
func URL(url string) {
PushURL = url
}
type ReqOpt func(*tpns.Request)
func NewPush(req *tpns.Request, opts ...ReqOpt) (*http.Request, string, error) {
return NewPushReq(req, opts...)
}
func NewUploadFileRequest(host string, file string) (*http.Request, error) {
fp, err := os.Open(file)
if err != nil {
return nil, err
}
defer fp.Close()
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
part, err := writer.CreateFormFile("file", filepath.Base(fp.Name()))
if err != nil {
return nil, err
}
io.Copy(part, fp)
writer.Close()
url := host + "/v3/push/package/upload"
req, err := http.NewRequest("POST", url, body)
if err != nil {
return nil, err
}
req.Header.Add("Content-Type", writer.FormDataContentType())
return req, nil
}
func NewSingleAccountPush(
message tpns.Message,
account string,
opts ...ReqOpt,
) (*http.Request, string, error) {
req := &tpns.Request{
MessageType: tpns.MsgTypeNotify,
AudienceType: tpns.AdAccountList,
AccountList: []string{account},
Message: message,
}
return NewPushReq(req, opts...)
}
func NewListAccountPush(
accounts []string, message tpns.Message,
opts ...ReqOpt,
) (*http.Request, string, error) {
req := &tpns.Request{
MessageType: tpns.MsgTypeNotify,
AudienceType: tpns.AdAccountList,
AccountList: accounts,
Message: message,
Environment: tpns.EnvDev,
}
return NewPushReq(req, opts...)
}
func NewTokenPush(
tokens []string, message tpns.Message,
opts ...ReqOpt,
) (*http.Request, string, error) {
req := &tpns.Request{
MessageType: tpns.MsgTypeNotify,
AudienceType: tpns.AdTokenList,
TokenList: tokens,
Message: message,
Environment: tpns.EnvProd,
}
//fmt.Printf("reqBody :%v", common.ToJson(req))
//fmt.Println()
return NewPushReq(req, opts...)
}
func NewTagsPush(
tagList []tpns.TagRule, message tpns.Message,
opts ...ReqOpt,
) (*http.Request, string, error) {
req := &tpns.Request{
MessageType: tpns.MsgTypeNotify,
AudienceType: tpns.AdTag,
Tag: tagList,
Message: message,
}
//fmt.Printf("reqBody :%v", common.ToJson(req))
//fmt.Println()
return NewPushReq(req, opts...)
}
func NewAllPush(
message tpns.Message,
opts ...ReqOpt,
) (*http.Request, string, error) {
req := &tpns.Request{
MessageType: tpns.MsgTypeNotify,
AudienceType: tpns.AdAll,
Message: message,
}
return NewPushReq(req, opts...)
}
func NewAccountPackagePush(
message tpns.Message,
opts ...ReqOpt,
) (*http.Request, string, error) {
req := &tpns.Request{
MessageType: tpns.MsgTypeNotify,
AudienceType: tpns.AdPackageAccount,
Message: message,
}
return NewPushReq(req, opts...)
}
func NewTokenPackagePush(
message tpns.Message,
opts ...ReqOpt,
) (*http.Request, string, error) {
req := &tpns.Request{
MessageType: tpns.MsgTypeNotify,
AudienceType: tpns.AdPackageToken,
Message: message,
}
return NewPushReq(req, opts...)
}
func NewPushReq(req *tpns.Request, opts ...ReqOpt) (request *http.Request, reqBody string, err error) {
for _, opt := range opts {
opt(req)
}
bodyBytes, err := json.Marshal(req)
if err != nil {
return nil, "", err
}
reqBody = string(bodyBytes)
//fmt.Printf("NewPushReq req:%v", reqBody)
request, err = http.NewRequest("POST", PushURL, bytes.NewReader(bodyBytes))
if err != nil {
return nil, "", err
}
request.Header.Add("Content-Type", "application/json")
return
}
func EnvProd() ReqOpt {
return func(r *tpns.Request) {
r.Environment = tpns.EnvProd
}
}
func EnvDev() ReqOpt {
return func(r *tpns.Request) {
r.Environment = tpns.EnvDev
}
}
func Title(t string) ReqOpt {
return func(r *tpns.Request) {
r.Message.Title = t
if r.Message.IOS != nil {
if r.Message.IOS.Aps != nil {
r.Message.IOS.Aps.Alert["title"] = t
} else {
r.Message.IOS.Aps = &tpns.Aps{
Alert: map[string]string{"title": t},
}
}
} else {
r.Message.IOS = &tpns.IOSParams{
Aps: &tpns.Aps{
Alert: map[string]string{"title": t},
},
}
}
}
}
func Content(c string) ReqOpt {
return func(r *tpns.Request) {
r.Message.Content = c
if r.Message.IOS != nil {
if r.Message.IOS.Aps != nil {
r.Message.IOS.Aps.Alert["body"] = c
} else {
r.Message.IOS.Aps = &tpns.Aps{
Alert: map[string]string{"body": c},
}
}
} else {
r.Message.IOS = &tpns.IOSParams{
Aps: &tpns.Aps{
Alert: map[string]string{"body": c},
},
}
}
}
}
func Ring(ring *int) ReqOpt {
return func(r *tpns.Request) {
r.Message.Android.Ring = ring
}
}
func RingRaw(rr string) ReqOpt {
return func(r *tpns.Request) {
r.Message.Android.RingRaw = rr
}
}
func Vibrate(v *int) ReqOpt {
return func(r *tpns.Request) {
r.Message.Android.Vibrate = v
}
}
func Lights(l *int) ReqOpt {
return func(r *tpns.Request) {
r.Message.Android.Lights = l
}
}
func Clearable(c *int) ReqOpt {
return func(r *tpns.Request) {
r.Message.Android.Clearable = c
}
}
func IconType(it *int) ReqOpt {
return func(r *tpns.Request) {
r.Message.Android.IconType = it
}
}
func IconRes(ir string) ReqOpt {
return func(r *tpns.Request) {
r.Message.Android.IconRes = ir
}
}
func AndroidCustomContent(ct string) ReqOpt {
return func(r *tpns.Request) {
r.Message.Android.CustomContent = ct
}
}
func Aps(aps *tpns.Aps) ReqOpt {
return func(r *tpns.Request) {
r.Message.IOS.Aps = aps
}
}
func AudienceType(at tpns.AudienceType) ReqOpt {
return func(r *tpns.Request) {
r.AudienceType = at
}
}
func Message(m tpns.Message) ReqOpt {
return func(r *tpns.Request) {
r.Message = m
}
}
func TokenList(tl []string) ReqOpt {
return func(r *tpns.Request) {
r.TokenList = tl
}
}
func TokenListAdd(t string) ReqOpt {
return func(r *tpns.Request) {
if r.TokenList != nil {
r.TokenList = append(r.TokenList, t)
} else {
r.TokenList = []string{t}
}
}
}
func AccountList(al []string) ReqOpt {
return func(r *tpns.Request) {
r.AccountList = al
}
}
//ChannelDistributeRules
func AddChannelRules(ChannelRules []*tpns.ChannelDistributeRule) ReqOpt {
return func(r *tpns.Request) {
r.ChannelRules = ChannelRules
}
}
//ChannelDistributeRules
func AddLoopParam(loopParam *tpns.PushLoopParam) ReqOpt {
return func(r *tpns.Request) {
r.LoopParam = loopParam
}
}
func AccountListAdd(a string) ReqOpt {
return func(r *tpns.Request) {
if r.AccountList != nil {
r.AccountList = append(r.AccountList, a)
} else {
r.AccountList = []string{a}
}
}
}
func MessageType(t tpns.MessageType) ReqOpt {
return func(r *tpns.Request) {
r.MessageType = t
}
}
func AddMultiPkg(multipPkg bool) ReqOpt {
return func(r *tpns.Request) {
r.MultiPkg = multipPkg
}
}
func AddForceCollapse(forceCollapse bool) ReqOpt {
return func(r *tpns.Request) {
r.ForceCollapse = forceCollapse
}
}
func AddTPNSOnlinePushType(onlinePushType int) ReqOpt {
return func(r *tpns.Request) {
r.TPNSOnlinePushType = onlinePushType
}
}
func AddCollapseId(collapseId int) ReqOpt {
return func(r *tpns.Request) {
r.CollapseId = collapseId
}
}
func AddPushSpeed(pushSpeed int) ReqOpt {
return func(r *tpns.Request) {
r.PushSpeed = pushSpeed
}
}
func AddAccountPushType(accountPushType int) ReqOpt {
return func(r *tpns.Request) {
r.AccountPushType = accountPushType
}
}
func AddPlanId(planId string) ReqOpt {
return func(r *tpns.Request) {
r.PlanId = planId
}
}
func AddSendTime(sendTime string) ReqOpt {
return func(r *tpns.Request) {
r.SendTime = sendTime
}
}
func AddExpireTime(expireTime int) ReqOpt {
return func(r *tpns.Request) {
r.ExpireTime = expireTime
}
}
func AddUploadId(UploadId int) ReqOpt {
return func(r *tpns.Request) {
r.UploadId = UploadId
}
}
func AddEnvironment(Environment tpns.CommonRspEnv) ReqOpt {
return func(r *tpns.Request) {
r.Environment = Environment
}
}
+62
View File
@@ -0,0 +1,62 @@
package auth
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbAuth "Open_IM/pkg/proto/auth"
"Open_IM/pkg/utils"
"google.golang.org/grpc"
"net"
"strconv"
"strings"
)
type rpcAuth struct {
rpcPort int
rpcRegisterName string
etcdSchema string
etcdAddr []string
}
func NewRpcAuthServer(port int) *rpcAuth {
log.NewPrivateLog("auth")
return &rpcAuth{
rpcPort: port,
rpcRegisterName: config.Config.RpcRegisterName.OpenImAuthName,
etcdSchema: config.Config.Etcd.EtcdSchema,
etcdAddr: config.Config.Etcd.EtcdAddr,
}
}
func (rpc *rpcAuth) Run() {
log.Info("", "", "rpc get_token init...")
address := utils.ServerIP + ":" + strconv.Itoa(rpc.rpcPort)
listener, err := net.Listen("tcp", address)
if err != nil {
log.Error("", "", "listen network failed, err = %s, address = %s", err.Error(), address)
return
}
log.Info("", "", "listen network success, address = %s", address)
//grpc server
srv := grpc.NewServer()
defer srv.GracefulStop()
//service registers with etcd
pbAuth.RegisterAuthServer(srv, rpc)
err = getcdv3.RegisterEtcd(rpc.etcdSchema, strings.Join(rpc.etcdAddr, ","), utils.ServerIP, rpc.rpcPort, rpc.rpcRegisterName, 10)
if err != nil {
log.Error("", "", "register rpc get_token to etcd failed, err = %s", err.Error())
return
}
err = srv.Serve(listener)
if err != nil {
log.Info("", "", "rpc get_token fail, err = %s", err.Error())
return
}
log.Info("", "", "rpc get_token init success")
}
+23
View File
@@ -0,0 +1,23 @@
package auth
import (
"Open_IM/pkg/common/db/mysql_model/im_mysql_model"
"Open_IM/pkg/common/log"
pbAuth "Open_IM/pkg/proto/auth"
"context"
)
func (rpc *rpcAuth) UserRegister(_ context.Context, pb *pbAuth.UserRegisterReq) (*pbAuth.UserRegisterResp, error) {
log.Info("", "", "rpc user_register start, [data: %s]", pb.String())
//if len(pb.UID) == 0 {
// pb.UID = utils.GenID()
//}
if err := im_mysql_model.UserRegister(pb); err != nil {
log.Error("", "", "rpc user_register error, [data: %s] [err: %s]", pb.String(), err.Error())
return &pbAuth.UserRegisterResp{Success: false}, err
}
log.Info("", "", "rpc user_register success return")
return &pbAuth.UserRegisterResp{Success: true}, nil
}
+29
View File
@@ -0,0 +1,29 @@
package auth
import (
"Open_IM/pkg/common/db/mysql_model/im_mysql_model"
"Open_IM/pkg/common/log"
pbAuth "Open_IM/pkg/proto/auth"
"Open_IM/pkg/utils"
"context"
)
func (rpc *rpcAuth) UserToken(_ context.Context, pb *pbAuth.UserTokenReq) (*pbAuth.UserTokenResp, error) {
log.Info("", "", "rpc user_token call start..., [pbTokenReq: %s]", pb.String())
_, err := im_mysql_model.FindUserByUID(pb.UID)
if err != nil {
log.Error("", "", "rpc user_token call..., im_mysql_model.AppServerFindFromUserByUserID fail [uid: %s] [err: %s]", pb.UID, err.Error())
return &pbAuth.UserTokenResp{ErrCode: 500, ErrMsg: err.Error()}, err
}
log.Info("", "", "rpc user_token call..., im_mysql_model.AppServerFindFromUserByUserID")
tokens, expTime, err := utils.CreateToken(pb.UID, pb.Platform)
if err != nil {
log.Error("", "", "rpc user_token call..., utils.CreateToken fail [uid: %s] [err: %s]", pb.UID, err.Error())
return &pbAuth.UserTokenResp{ErrCode: 500, ErrMsg: err.Error()}, err
}
log.Info("", "", "rpc user_token success return, [uid: %s] [tokens: %s]", pb.UID, tokens)
return &pbAuth.UserTokenResp{Token: tokens, ExpiredTime: expTime}, nil
}
+159
View File
@@ -0,0 +1,159 @@
package chat
import (
"context"
"github.com/garyburd/redigo/redis"
commonDB "Open_IM/pkg/common/db"
"Open_IM/pkg/common/log"
"sort"
"strings"
pbMsg "Open_IM/pkg/proto/chat"
)
func (rpc *rpcChat) GetMaxAndMinSeq(_ context.Context, in *pbMsg.GetMaxAndMinSeqReq) (*pbMsg.GetMaxAndMinSeqResp, error) {
log.InfoByKv("rpc getMaxAndMinSeq is arriving", in.OperationID, in.String())
//seq, err := model.GetBiggestSeqFromReceive(in.UserID)
maxSeq, err1 := commonDB.DB.GetUserMaxSeq(in.UserID)
minSeq, err2 := commonDB.DB.GetUserMinSeq(in.UserID)
resp := new(pbMsg.GetMaxAndMinSeqResp)
if err1 == nil {
resp.MaxSeq = maxSeq
} else if err1 == redis.ErrNil {
resp.MaxSeq = 0
} else {
log.NewError(in.OperationID, "getMaxSeq from redis error", in.String(), err1.Error())
resp.MaxSeq = -1
resp.ErrCode = 200
resp.ErrMsg = "redis get err"
}
if err2 == nil {
resp.MinSeq = minSeq
} else if err2 == redis.ErrNil {
resp.MinSeq = 0
} else {
log.NewError(in.OperationID, "getMaxSeq from redis error", in.String(), err2.Error())
resp.MinSeq = -1
resp.ErrCode = 201
resp.ErrMsg = "redis get err"
}
return resp, nil
}
func (rpc *rpcChat) PullMessage(_ context.Context, in *pbMsg.PullMessageReq) (*pbMsg.PullMessageResp, error) {
log.InfoByKv("rpc pullMessage is arriving", in.OperationID, "args", in.String())
resp := new(pbMsg.PullMessageResp)
var respSingleMsgFormat []*pbMsg.GatherFormat
var respGroupMsgFormat []*pbMsg.GatherFormat
SingleMsgFormat, GroupMsgFormat, MaxSeq, MinSeq, err := commonDB.DB.GetMsgBySeqRange(in.UserID, in.SeqBegin, in.SeqEnd)
if err != nil {
log.ErrorByKv("pullMsg data error", in.OperationID, in.String())
resp.ErrCode = 1
resp.ErrMsg = err.Error()
return resp, nil
}
respSingleMsgFormat = singleMsgHandleByUser(SingleMsgFormat, in.UserID)
respGroupMsgFormat = groupMsgHandleByUser(GroupMsgFormat)
return &pbMsg.PullMessageResp{
ErrCode: 0,
ErrMsg: "",
MaxSeq: MaxSeq,
MinSeq: MinSeq,
SingleUserMsg: respSingleMsgFormat,
GroupUserMsg: respGroupMsgFormat,
}, nil
}
func (rpc *rpcChat) PullMessageBySeqList(_ context.Context, in *pbMsg.PullMessageBySeqListReq) (*pbMsg.PullMessageResp, error) {
log.NewInfo(in.OperationID, "rpc PullMessageBySeqList is arriving", in.String())
resp := new(pbMsg.PullMessageResp)
var respSingleMsgFormat []*pbMsg.GatherFormat
var respGroupMsgFormat []*pbMsg.GatherFormat
SingleMsgFormat, GroupMsgFormat, MaxSeq, MinSeq, err := commonDB.DB.GetMsgBySeqList(in.UserID, in.SeqList)
if err != nil {
log.ErrorByKv("PullMessageBySeqList data error", in.OperationID, in.String())
resp.ErrCode = 1
resp.ErrMsg = err.Error()
return resp, nil
}
respSingleMsgFormat = singleMsgHandleByUser(SingleMsgFormat, in.UserID)
respGroupMsgFormat = groupMsgHandleByUser(GroupMsgFormat)
return &pbMsg.PullMessageResp{
ErrCode: 0,
ErrMsg: "",
MaxSeq: MaxSeq,
MinSeq: MinSeq,
SingleUserMsg: respSingleMsgFormat,
GroupUserMsg: respGroupMsgFormat,
}, nil
}
func singleMsgHandleByUser(allMsg []*pbMsg.MsgFormat, ownerId string) []*pbMsg.GatherFormat {
var userid string
var respMsgFormat []*pbMsg.GatherFormat
m := make(map[string]MsgFormats)
//Gather messages in the dimension of users
for _, v := range allMsg {
if v.RecvID != ownerId {
userid = v.RecvID
} else {
userid = v.SendID
}
if value, ok := m[userid]; !ok {
var t MsgFormats
m[userid] = append(t, v)
} else {
m[userid] = append(value, v)
}
}
//Return in pb format
for user, msg := range m {
tempUserMsg := new(pbMsg.GatherFormat)
tempUserMsg.ID = user
tempUserMsg.List = msg
sort.Sort(msg)
respMsgFormat = append(respMsgFormat, tempUserMsg)
}
return respMsgFormat
}
func groupMsgHandleByUser(allMsg []*pbMsg.MsgFormat) []*pbMsg.GatherFormat {
var respMsgFormat []*pbMsg.GatherFormat
m := make(map[string]MsgFormats)
//Gather messages in the dimension of users
for _, v := range allMsg {
//Get group ID
groupID := strings.Split(v.RecvID, " ")[1]
if value, ok := m[groupID]; !ok {
var t MsgFormats
m[groupID] = append(t, v)
} else {
m[groupID] = append(value, v)
}
}
//Return in pb format
for groupID, msg := range m {
tempUserMsg := new(pbMsg.GatherFormat)
tempUserMsg.ID = groupID
tempUserMsg.List = msg
sort.Sort(msg)
respMsgFormat = append(respMsgFormat, tempUserMsg)
}
return respMsgFormat
}
type MsgFormats []*pbMsg.MsgFormat
// Implement the sort.Interface interface to get the number of elements method
func (s MsgFormats) Len() int {
return len(s)
}
//Implement the sort.Interface interface comparison element method
func (s MsgFormats) Less(i, j int) bool {
return s[i].SendTime < s[j].SendTime
}
//Implement the sort.Interface interface exchange element method
func (s MsgFormats) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
+66
View File
@@ -0,0 +1,66 @@
package chat
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/kafka"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbChat "Open_IM/pkg/proto/chat"
"Open_IM/pkg/utils"
"google.golang.org/grpc"
"net"
"strconv"
"strings"
)
type rpcChat struct {
rpcPort int
rpcRegisterName string
etcdSchema string
etcdAddr []string
producer *kafka.Producer
}
func NewRpcChatServer(port int) *rpcChat {
log.NewPrivateLog("msg")
rc := rpcChat{
rpcPort: port,
rpcRegisterName: config.Config.RpcRegisterName.OpenImOfflineMessageName,
etcdSchema: config.Config.Etcd.EtcdSchema,
etcdAddr: config.Config.Etcd.EtcdAddr,
}
rc.producer = kafka.NewKafkaProducer(config.Config.Kafka.Ws2mschat.Addr, config.Config.Kafka.Ws2mschat.Topic)
return &rc
}
func (rpc *rpcChat) Run() {
log.Info("", "", "rpc get_token init...")
address := utils.ServerIP + ":" + strconv.Itoa(rpc.rpcPort)
listener, err := net.Listen("tcp", address)
if err != nil {
log.Error("", "", "listen network failed, err = %s, address = %s", err.Error(), address)
return
}
log.Info("", "", "listen network success, address = %s", address)
//grpc server
srv := grpc.NewServer()
defer srv.GracefulStop()
//service registers with etcd
pbChat.RegisterChatServer(srv, rpc)
err = getcdv3.RegisterEtcd(rpc.etcdSchema, strings.Join(rpc.etcdAddr, ","), utils.ServerIP, rpc.rpcPort, rpc.rpcRegisterName, 10)
if err != nil {
log.Error("", "", "register rpc get_token to etcd failed, err = %s", err.Error())
return
}
err = srv.Serve(listener)
if err != nil {
log.Info("", "", "rpc get_token fail, err = %s", err.Error())
return
}
log.Info("", "", "rpc get_token init success")
}
+186
View File
@@ -0,0 +1,186 @@
package chat
import (
"Open_IM/internal/api/group"
"Open_IM/internal/push/content_struct"
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/constant"
http2 "Open_IM/pkg/common/http"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbChat "Open_IM/pkg/proto/chat"
pbGroup "Open_IM/pkg/proto/group"
"Open_IM/pkg/utils"
"context"
"encoding/json"
"math/rand"
"net/http"
"strconv"
"strings"
"time"
)
type MsgCallBackReq struct {
SendID string `json:"sendID"`
RecvID string `json:"recvID"`
Content string `json:"content"`
SendTime int64 `json:"sendTime"`
MsgFrom int32 `json:"msgFrom"`
ContentType int32 `json:"contentType"`
SessionType int32 `json:"sessionType"`
PlatformID int32 `json:"senderPlatformID"`
}
type MsgCallBackResp struct {
ErrCode int32 `json:"errCode"`
ErrMsg string `json:"errMsg"`
ResponseErrCode int32 `json:"responseErrCode"`
ResponseResult struct {
ModifiedMsg string `json:"modifiedMsg"`
Ext string `json:"ext"`
}
}
func (rpc *rpcChat) UserSendMsg(_ context.Context, pb *pbChat.UserSendMsgReq) (*pbChat.UserSendMsgResp, error) {
replay := pbChat.UserSendMsgResp{}
log.NewDebug(pb.OperationID, "rpc sendMsg come here", pb.String())
//if !utils.VerifyToken(pb.Token, pb.SendID) {
// return returnMsg(&replay, pb, http.StatusUnauthorized, "token validate err,not authorized", "", 0)
serverMsgID := GetMsgID(pb.SendID)
pbData := pbChat.WSToMsgSvrChatMsg{}
pbData.MsgFrom = pb.MsgFrom
pbData.SessionType = pb.SessionType
pbData.ContentType = pb.ContentType
pbData.Content = pb.Content
pbData.RecvID = pb.RecvID
pbData.ForceList = pb.ForceList
pbData.OfflineInfo = pb.OffLineInfo
pbData.Options = pb.Options
pbData.PlatformID = pb.PlatformID
pbData.ClientMsgID = pb.ClientMsgID
pbData.SendID = pb.SendID
pbData.SenderNickName = pb.SenderNickName
pbData.SenderFaceURL = pb.SenderFaceURL
pbData.MsgID = serverMsgID
pbData.OperationID = pb.OperationID
pbData.Token = pb.Token
if pb.SendTime == 0 {
pbData.SendTime = utils.GetCurrentTimestampByNano()
} else {
pbData.SendTime = pb.SendTime
}
m := MsgCallBackResp{}
if config.Config.MessageCallBack.CallbackSwitch {
bMsg, err := http2.Post(config.Config.MessageCallBack.CallbackUrl, MsgCallBackReq{
SendID: pb.SendID,
RecvID: pb.RecvID,
Content: pb.Content,
SendTime: pbData.SendTime,
MsgFrom: pbData.MsgFrom,
ContentType: pb.ContentType,
SessionType: pb.SessionType,
PlatformID: pb.PlatformID,
}, "application/json; charset=utf-8")
if err != nil {
log.ErrorByKv("callback to Business server err", pb.OperationID, "args", pb.String(), "err", err.Error())
return returnMsg(&replay, pb, http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError), "", 0)
} else if err = json.Unmarshal(bMsg, &m); err != nil {
log.ErrorByKv("ws json Unmarshal err", pb.OperationID, "args", pb.String(), "err", err.Error())
return returnMsg(&replay, pb, 200, err.Error(), "", 0)
} else {
if m.ErrCode != 0 {
return returnMsg(&replay, pb, m.ResponseErrCode, m.ErrMsg, "", 0)
} else {
pbData.Content = m.ResponseResult.ModifiedMsg
}
}
}
switch pbData.SessionType {
case constant.SingleChatType:
err1 := rpc.sendMsgToKafka(&pbData, pbData.RecvID)
err2 := rpc.sendMsgToKafka(&pbData, pbData.SendID)
if err1 != nil || err2 != nil {
return returnMsg(&replay, pb, 201, "kafka send msg err", "", 0)
}
return returnMsg(&replay, pb, 0, "", serverMsgID, pbData.SendTime)
case constant.GroupChatType:
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImGroupName)
client := pbGroup.NewGroupClient(etcdConn)
req := &pbGroup.GetGroupAllMemberReq{
GroupID: pbData.RecvID,
Token: pbData.Token,
OperationID: pbData.OperationID,
}
reply, err := client.GetGroupAllMember(context.Background(), req)
if err != nil {
log.Error(pbData.Token, pbData.OperationID, "rpc send_msg getGroupInfo failed, err = %s", err.Error())
return returnMsg(&replay, pb, 201, err.Error(), "", 0)
}
if reply.ErrorCode != 0 {
log.Error(pbData.Token, pbData.OperationID, "rpc send_msg getGroupInfo failed, err = %s", reply.ErrorMsg)
return returnMsg(&replay, pb, reply.ErrorCode, reply.ErrorMsg, "", 0)
}
var addUidList []string
switch pbData.ContentType {
case constant.KickGroupMemberTip:
var notification content_struct.NotificationContent
var kickContent group.KickGroupMemberReq
err := utils.JsonStringToStruct(pbData.Content, &notification)
if err != nil {
log.ErrorByKv("json unmarshall err", pbData.OperationID, "err", err.Error())
return returnMsg(&replay, pb, 200, err.Error(), "", 0)
} else {
err := utils.JsonStringToStruct(notification.Detail, &kickContent)
if err != nil {
log.ErrorByKv("json unmarshall err", pbData.OperationID, "err", err.Error())
return returnMsg(&replay, pb, 200, err.Error(), "", 0)
}
for _, v := range kickContent.UidListInfo {
addUidList = append(addUidList, v.UserId)
}
}
case constant.QuitGroupTip:
addUidList = append(addUidList, pbData.SendID)
default:
}
groupID := pbData.RecvID
for i, v := range reply.MemberList {
pbData.RecvID = v.UserId + " " + groupID
err := rpc.sendMsgToKafka(&pbData, utils.IntToString(i))
if err != nil {
return returnMsg(&replay, pb, 201, "kafka send msg err", "", 0)
}
}
for i, v := range addUidList {
pbData.RecvID = v + " " + groupID
err := rpc.sendMsgToKafka(&pbData, utils.IntToString(i+1))
if err != nil {
return returnMsg(&replay, pb, 201, "kafka send msg err", "", 0)
}
}
return returnMsg(&replay, pb, 0, "", serverMsgID, pbData.SendTime)
default:
return returnMsg(&replay, pb, 203, "unkonwn sessionType", "", 0)
}
}
func (rpc *rpcChat) sendMsgToKafka(m *pbChat.WSToMsgSvrChatMsg, key string) error {
pid, offset, err := rpc.producer.SendMessage(m, key)
if err != nil {
log.ErrorByKv("kafka send failed", m.OperationID, "send data", m.String(), "pid", pid, "offset", offset, "err", err.Error(), "key", key)
}
return err
}
func GetMsgID(sendID string) string {
t := time.Now().Format("2006-01-02 15:04:05")
return t + "-" + sendID + "-" + strconv.Itoa(rand.Int())
}
func returnMsg(replay *pbChat.UserSendMsgResp, pb *pbChat.UserSendMsgReq, errCode int32, errMsg, serverMsgID string, sendTime int64) (*pbChat.UserSendMsgResp, error) {
replay.ErrCode = errCode
replay.ErrMsg = errMsg
replay.ReqIdentifier = pb.ReqIdentifier
replay.ClientMsgID = pb.ClientMsgID
replay.ServerMsgID = serverMsgID
replay.SendTime = sendTime
return replay, nil
}
+45
View File
@@ -0,0 +1,45 @@
package friend
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/db/mysql_model/im_mysql_model"
"Open_IM/pkg/common/log"
pbFriend "Open_IM/pkg/proto/friend"
"Open_IM/pkg/utils"
"context"
)
func (s *friendServer) AddBlacklist(ctx context.Context, req *pbFriend.AddBlacklistReq) (*pbFriend.CommonResp, error) {
log.Info(req.Token, req.OperationID, "rpc add blacklist is server,args=%s", req.String())
//Parse token, to find current user information
claims, err := utils.ParseToken(req.Token)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,parse token failed", err.Error())
return &pbFriend.CommonResp{ErrorCode: config.ErrParseToken.ErrCode, ErrorMsg: config.ErrParseToken.ErrMsg}, nil
}
isMagagerFlag := 0
tokenUid := claims.UID
if utils.IsContain(tokenUid, config.Config.Manager.AppManagerUid) {
isMagagerFlag = 1
}
if isMagagerFlag == 0 {
err = im_mysql_model.InsertInToUserBlackList(claims.UID, req.Uid)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,Failed to add blacklist", err.Error())
return &pbFriend.CommonResp{ErrorCode: config.ErrMysql.ErrCode, ErrorMsg: config.ErrMysql.ErrMsg}, nil
}
log.Info(req.Token, req.OperationID, "rpc add blacklist success return,uid=%s", req.Uid)
return &pbFriend.CommonResp{}, nil
}
err = im_mysql_model.InsertInToUserBlackList(req.OwnerUid, req.Uid)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,Failed to add blacklist", err.Error())
return &pbFriend.CommonResp{ErrorCode: config.ErrMysql.ErrCode, ErrorMsg: config.ErrMysql.ErrMsg}, nil
}
log.Info(req.Token, req.OperationID, "rpc add blacklist success return,uid=%s", req.Uid)
return &pbFriend.CommonResp{}, nil
}
+132
View File
@@ -0,0 +1,132 @@
package friend
import (
"Open_IM/internal/push/content_struct"
"Open_IM/internal/push/logic"
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/constant"
"Open_IM/pkg/common/db/mysql_model/im_mysql_model"
"Open_IM/pkg/common/log"
pbChat "Open_IM/pkg/proto/chat"
pbFriend "Open_IM/pkg/proto/friend"
"Open_IM/pkg/utils"
"context"
)
func (s *friendServer) AddFriend(ctx context.Context, req *pbFriend.AddFriendReq) (*pbFriend.CommonResp, error) {
log.Info(req.Token, req.OperationID, "rpc add friend is server,userid=%s", req.Uid)
//Parse token, to find current user information
claims, err := utils.ParseToken(req.Token)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,parse token failed", err.Error())
return &pbFriend.CommonResp{ErrorCode: config.ErrParseToken.ErrCode, ErrorMsg: config.ErrParseToken.ErrMsg}, nil
}
//Cannot add non-existent users
if _, err = im_mysql_model.FindUserByUID(req.Uid); err != nil {
log.Error(req.Token, req.OperationID, "this user not exists,cant not add friend")
return &pbFriend.CommonResp{ErrorCode: config.ErrAddFriend.ErrCode, ErrorMsg: config.ErrSearchUserInfo.ErrMsg}, nil
}
//Establish a latest relationship in the friend request table
err = im_mysql_model.ReplaceIntoFriendReq(claims.UID, req.Uid, constant.ApplicationFriendFlag, req.ReqMessage)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,create friend request record failed", err.Error())
return &pbFriend.CommonResp{ErrorCode: config.ErrAddFriend.ErrCode, ErrorMsg: config.ErrAddFriend.ErrMsg}, nil
}
log.Info(req.Token, req.OperationID, "rpc add friend is success return,uid=%s", req.Uid)
//Push message when add friend successfully
senderInfo, errSend := im_mysql_model.FindUserByUID(claims.UID)
receiverInfo, errReceive := im_mysql_model.FindUserByUID(req.Uid)
if errSend == nil && errReceive == nil {
logic.SendMsgByWS(&pbChat.WSToMsgSvrChatMsg{
SendID: senderInfo.UID,
RecvID: receiverInfo.UID,
Content: content_struct.NewContentStructString(0, "", senderInfo.Name+" asked to add you as a friend"),
SendTime: utils.GetCurrentTimestampBySecond(),
MsgFrom: constant.SysMsgType,
ContentType: constant.AddFriendTip,
SessionType: constant.SingleChatType,
OperationID: req.OperationID,
})
}
return &pbFriend.CommonResp{}, nil
}
func (s *friendServer) ImportFriend(ctx context.Context, req *pbFriend.ImportFriendReq) (*pbFriend.ImportFriendResp, error) {
log.Info(req.Token, req.OperationID, "ImportFriend come here,args=%s", req.String())
var resp pbFriend.ImportFriendResp
var c pbFriend.CommonResp
//Parse token, to find current user information
claims, err := utils.ParseToken(req.Token)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,parse token failed", err.Error())
c.ErrorCode = config.ErrAddFriend.ErrCode
c.ErrorMsg = config.ErrParseToken.ErrMsg
return &pbFriend.ImportFriendResp{CommonResp: &c, FailedUidList: req.UidList}, nil
}
if !utils.IsContain(claims.UID, config.Config.Manager.AppManagerUid) {
log.Error(req.Token, req.OperationID, "not manager uid", claims.UID)
c.ErrorCode = config.ErrAddFriend.ErrCode
c.ErrorMsg = "not authorized"
return &pbFriend.ImportFriendResp{CommonResp: &c, FailedUidList: req.UidList}, nil
}
if _, err = im_mysql_model.FindUserByUID(req.OwnerUid); err != nil {
log.Error(req.Token, req.OperationID, "this user not exists,cant not add friend", req.OwnerUid)
c.ErrorCode = config.ErrAddFriend.ErrCode
c.ErrorMsg = "this user not exists,cant not add friend"
return &pbFriend.ImportFriendResp{CommonResp: &c, FailedUidList: req.UidList}, nil
}
for _, v := range req.UidList {
if _, fErr := im_mysql_model.FindUserByUID(v); fErr != nil {
c.ErrorMsg = "some uid establish failed"
c.ErrorCode = 408
resp.CommonResp = &c
resp.FailedUidList = append(resp.FailedUidList, v)
} else {
if _, err = im_mysql_model.FindFriendRelationshipFromFriend(req.OwnerUid, v); err != nil {
//Establish two single friendship
err1 := im_mysql_model.InsertToFriend(req.OwnerUid, v, 1)
if err1 != nil {
resp.FailedUidList = append(resp.FailedUidList, v)
log.NewError(req.OperationID, "err1,create friendship failed", req.OwnerUid, v, err1.Error())
}
err2 := im_mysql_model.InsertToFriend(v, req.OwnerUid, 1)
if err2 != nil {
log.NewError(req.OperationID, "err2,create friendship failed", v, req.OwnerUid, err2.Error())
}
if err1 == nil && err2 == nil {
var name, faceUrl string
n := content_struct.NotificationContent{IsDisplay: 1, DefaultTips: constant.FriendAcceptTip}
r, err := im_mysql_model.FindUserByUID(v)
if err != nil {
log.NewError(req.OperationID, "get info failed", err.Error(), v)
}
if r != nil {
name, faceUrl = r.Name, r.Icon
}
logic.SendMsgByWS(&pbChat.WSToMsgSvrChatMsg{
SendID: v,
RecvID: req.OwnerUid,
SenderFaceURL: faceUrl,
SenderNickName: name,
Content: n.ContentToString(),
SendTime: utils.GetCurrentTimestampByNano(),
MsgFrom: constant.UserMsgType, //Notification message identification
ContentType: constant.AcceptFriendApplicationTip, //Add friend flag
SessionType: constant.SingleChatType,
OperationID: req.OperationID,
})
} else {
resp.CommonResp.ErrorMsg = "some uid establish failed"
resp.CommonResp.ErrorCode = 408
resp.FailedUidList = append(resp.FailedUidList, v)
}
}
}
}
return &resp, nil
}
@@ -0,0 +1,84 @@
package friend
import (
"Open_IM/internal/push/content_struct"
"Open_IM/internal/push/logic"
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/constant"
"Open_IM/pkg/common/db/mysql_model/im_mysql_model"
"Open_IM/pkg/common/log"
pbChat "Open_IM/pkg/proto/chat"
pbFriend "Open_IM/pkg/proto/friend"
"Open_IM/pkg/utils"
"context"
)
func (s *friendServer) AddFriendResponse(ctx context.Context, req *pbFriend.AddFriendResponseReq) (*pbFriend.CommonResp, error) {
log.Info(req.Token, req.OperationID, "rpc add friend response is server,args=%s", req.String())
//Parse token, to find current user information
claims, err := utils.ParseToken(req.Token)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,parse token failed", err.Error())
return &pbFriend.CommonResp{ErrorCode: config.ErrParseToken.ErrCode, ErrorMsg: config.ErrParseToken.ErrMsg}, nil
}
//Check there application before agreeing or refuse to a friend's application
if _, err = im_mysql_model.FindFriendApplyFromFriendReqByUid(req.Uid, claims.UID); err != nil {
log.Error(req.Token, req.OperationID, "No such application record")
return &pbFriend.CommonResp{ErrorCode: config.ErrAgreeToAddFriend.ErrCode, ErrorMsg: config.ErrAgreeToAddFriend.ErrMsg}, nil
}
//Change friend request status flag
err = im_mysql_model.UpdateFriendRelationshipToFriendReq(req.Uid, claims.UID, req.Flag)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,update friend request table failed", err.Error())
return &pbFriend.CommonResp{ErrorCode: config.ErrMysql.ErrCode, ErrorMsg: config.ErrAgreeToAddFriend.ErrMsg}, nil
}
log.Info(req.Token, req.OperationID, "rpc add friend response success return,userid=%s,flag=%d", req.Uid, req.Flag)
//Change the status of the friend request form
if req.Flag == constant.FriendFlag {
//Establish friendship after find friend relationship not exists
_, err := im_mysql_model.FindFriendRelationshipFromFriend(claims.UID, req.Uid)
//fixme If there is an error, it means that there is no friend record or database err, if no friend record should be inserted,Continue down execution
if err != nil {
log.Error("", req.OperationID, err.Error())
}
//Establish two single friendship
err = im_mysql_model.InsertToFriend(claims.UID, req.Uid, req.Flag)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,create friendship failed", err.Error())
}
err = im_mysql_model.InsertToFriend(req.Uid, claims.UID, req.Flag)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,create friendship failed", err.Error())
}
//Push message when establish friends successfully
//senderInfo, errSend := im_mysql_model.FindUserByUID(claims.UID)
//if errSend == nil {
// logic.SendMsgByWS(&pbChat.WSToMsgSvrChatMsg{
// SendID: claims.UID,
// RecvID: req.Uid,
// Content: content_struct.NewContentStructString(1, "", senderInfo.Name+" agreed to add you as a friend."),
// SendTime: utils.GetCurrentTimestampBySecond(),
// MsgFrom: constant.UserMsgType, //Notification message identification
// ContentType: constant.AcceptFriendApplicationTip, //Add friend flag
// SessionType: constant.SingleChatType,
// OperationID: req.OperationID,
// })
//}
}
if req.Flag == constant.RefuseFriendFlag {
senderInfo, errSend := im_mysql_model.FindUserByUID(claims.UID)
if errSend == nil {
logic.SendMsgByWS(&pbChat.WSToMsgSvrChatMsg{
SendID: claims.UID,
RecvID: req.Uid,
Content: content_struct.NewContentStructString(0, "", senderInfo.Name+" refuse to add you as a friend."),
SendTime: utils.GetCurrentTimestampBySecond(),
MsgFrom: constant.UserMsgType, //Notification message identification
ContentType: constant.RefuseFriendApplicationTip, //Add friend flag
SessionType: constant.SingleChatType,
OperationID: req.OperationID,
})
}
}
return &pbFriend.CommonResp{}, nil
}
+27
View File
@@ -0,0 +1,27 @@
package friend
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/db/mysql_model/im_mysql_model"
"Open_IM/pkg/common/log"
pbFriend "Open_IM/pkg/proto/friend"
"Open_IM/pkg/utils"
"context"
)
func (s *friendServer) DeleteFriend(ctx context.Context, req *pbFriend.DeleteFriendReq) (*pbFriend.CommonResp, error) {
log.Info(req.Token, req.OperationID, "rpc delete friend is server,args=%s", req.String())
//Parse token, to find current user information
claims, err := utils.ParseToken(req.Token)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,parse token failed", err.Error())
return &pbFriend.CommonResp{ErrorCode: config.ErrParseToken.ErrCode, ErrorMsg: config.ErrParseToken.ErrMsg}, nil
}
err = im_mysql_model.DeleteSingleFriendInfo(claims.UID, req.Uid)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,delete friend failed", err.Error())
return &pbFriend.CommonResp{ErrorCode: config.ErrMysql.ErrCode, ErrorMsg: config.ErrMysql.ErrMsg}, nil
}
log.Info(req.Token, req.OperationID, "rpc delete friend success return")
return &pbFriend.CommonResp{}, nil
}
+55
View File
@@ -0,0 +1,55 @@
package friend
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/db/mysql_model/im_mysql_model"
"Open_IM/pkg/common/log"
pbFriend "Open_IM/pkg/proto/friend"
"Open_IM/pkg/utils"
"context"
)
func (s *friendServer) GetBlacklist(ctx context.Context, req *pbFriend.GetBlacklistReq) (*pbFriend.GetBlacklistResp, error) {
log.Info(req.Token, req.OperationID, "rpc get blacklist is server,args=%s", req.String())
var (
userInfoList []*pbFriend.UserInfo
comment string
)
//Parse token, to find current user information
claims, err := utils.ParseToken(req.Token)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,parse token failed", err.Error())
return &pbFriend.GetBlacklistResp{ErrorCode: config.ErrParseToken.ErrCode, ErrorMsg: config.ErrParseToken.ErrMsg}, nil
}
blackListInfo, err := im_mysql_model.GetBlackListByUID(claims.UID)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s get blacklist failed", err.Error())
return &pbFriend.GetBlacklistResp{ErrorCode: config.ErrGetBlackList.ErrCode, ErrorMsg: config.ErrGetBlackList.ErrMsg}, nil
}
for _, blackUser := range blackListInfo {
var blackUserInfo pbFriend.UserInfo
//Find black user information
us, err := im_mysql_model.FindUserByUID(blackUser.BlockId)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s search black list userInfo failed", err.Error())
continue
}
friendShip, err := im_mysql_model.FindFriendRelationshipFromFriend(claims.UID, blackUser.BlockId)
if err == nil {
comment = friendShip.Comment
}
blackUserInfo.Uid = us.UID
blackUserInfo.Icon = us.Icon
blackUserInfo.Name = us.Name
blackUserInfo.Gender = us.Gender
blackUserInfo.Mobile = us.Mobile
blackUserInfo.Birth = us.Birth
blackUserInfo.Email = us.Email
blackUserInfo.Ex = us.Ex
blackUserInfo.Comment = comment
userInfoList = append(userInfoList, &blackUserInfo)
}
log.Info(req.Token, req.OperationID, "rpc get blacklist success return")
return &pbFriend.GetBlacklistResp{Data: userInfoList}, nil
}
+112
View File
@@ -0,0 +1,112 @@
package friend
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/constant"
"Open_IM/pkg/common/db/mysql_model/im_mysql_model"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbFriend "Open_IM/pkg/proto/friend"
"Open_IM/pkg/utils"
"context"
"fmt"
"google.golang.org/grpc"
"net"
"strconv"
"strings"
)
type friendServer struct {
rpcPort int
rpcRegisterName string
etcdSchema string
etcdAddr []string
}
func NewFriendServer(port int) *friendServer {
log.NewPrivateLog("friend")
return &friendServer{
rpcPort: port,
rpcRegisterName: config.Config.RpcRegisterName.OpenImFriendName,
etcdSchema: config.Config.Etcd.EtcdSchema,
etcdAddr: config.Config.Etcd.EtcdAddr,
}
}
func (s *friendServer) Run() {
log.Info("", "", fmt.Sprintf("rpc friend init...."))
ip := utils.ServerIP
registerAddress := ip + ":" + strconv.Itoa(s.rpcPort)
//listener network
listener, err := net.Listen("tcp", registerAddress)
if err != nil {
log.InfoByArgs(fmt.Sprintf("Failed to listen rpc friend network,err=%s", err.Error()))
return
}
log.Info("", "", "listen network success, address = %s", registerAddress)
defer listener.Close()
//grpc server
srv := grpc.NewServer()
defer srv.GracefulStop()
//User friend related services register to etcd
pbFriend.RegisterFriendServer(srv, s)
err = getcdv3.RegisterEtcd(s.etcdSchema, strings.Join(s.etcdAddr, ","), ip, s.rpcPort, s.rpcRegisterName, 10)
if err != nil {
log.ErrorByArgs("register rpc fiend service to etcd failed,err=%s", err.Error())
return
}
err = srv.Serve(listener)
if err != nil {
log.ErrorByArgs("listen rpc friend error,err=%s", err.Error())
return
}
}
func (s *friendServer) GetFriendsInfo(ctx context.Context, req *pbFriend.GetFriendsInfoReq) (*pbFriend.GetFriendInfoResp, error) {
log.Info(req.Token, req.OperationID, "rpc search user is server,args=%s", req.String())
var (
isInBlackList int32
isFriend int32
comment string
)
//Parse token, to find current user information
claims, err := utils.ParseToken(req.Token)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,parse token failed", err.Error())
return &pbFriend.GetFriendInfoResp{ErrorCode: config.ErrParseToken.ErrCode, ErrorMsg: config.ErrParseToken.ErrMsg}, nil
}
friendShip, err := im_mysql_model.FindFriendRelationshipFromFriend(claims.UID, req.Uid)
if err == nil {
isFriend = constant.FriendFlag
comment = friendShip.Comment
}
friendUserInfo, err := im_mysql_model.FindUserByUID(req.Uid)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,no this user", err.Error())
return &pbFriend.GetFriendInfoResp{ErrorCode: config.ErrSearchUserInfo.ErrCode, ErrorMsg: config.ErrSearchUserInfo.ErrMsg}, nil
}
err = im_mysql_model.FindRelationshipFromBlackList(claims.UID, req.Uid)
if err == nil {
isInBlackList = constant.BlackListFlag
}
log.Info(req.Token, req.OperationID, "rpc search friend success return")
return &pbFriend.GetFriendInfoResp{
ErrorCode: 0,
ErrorMsg: "",
Data: &pbFriend.GetFriendData{
Uid: friendUserInfo.UID,
Icon: friendUserInfo.Icon,
Name: friendUserInfo.Name,
Gender: friendUserInfo.Gender,
Mobile: friendUserInfo.Mobile,
Birth: friendUserInfo.Birth,
Email: friendUserInfo.Email,
Ex: friendUserInfo.Ex,
Comment: comment,
IsFriend: isFriend,
IsInBlackList: isInBlackList,
},
}, nil
}
@@ -0,0 +1,95 @@
package friend
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/db/mysql_model/im_mysql_model"
"Open_IM/pkg/common/log"
pbFriend "Open_IM/pkg/proto/friend"
"Open_IM/pkg/utils"
"context"
"fmt"
"strconv"
)
func (s *friendServer) GetFriendApplyList(ctx context.Context, req *pbFriend.GetFriendApplyReq) (*pbFriend.GetFriendApplyResp, error) {
log.Info(req.Token, req.OperationID, "rpc get friend apply list is server,args=%s", req.String())
var appleUserList []*pbFriend.ApplyUserInfo
//Parse token, to find current user information
claims, err := utils.ParseToken(req.Token)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,parse token failed", err.Error())
return &pbFriend.GetFriendApplyResp{ErrorCode: config.ErrParseToken.ErrCode, ErrorMsg: config.ErrParseToken.ErrMsg}, nil
}
// Find the current user friend applications received
ApplyUsersInfo, err := im_mysql_model.FindFriendsApplyFromFriendReq(claims.UID)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,search applyInfo failed", err.Error())
return &pbFriend.GetFriendApplyResp{ErrorCode: config.ErrMysql.ErrCode, ErrorMsg: config.ErrMysql.ErrMsg}, nil
}
for _, applyUserInfo := range ApplyUsersInfo {
var userInfo pbFriend.ApplyUserInfo
//Find friend application status
userInfo.Flag = applyUserInfo.Flag
userInfo.ReqMessage = applyUserInfo.ReqMessage
userInfo.ApplyTime = strconv.FormatInt(applyUserInfo.CreateTime.Unix(), 10)
//Find user information
us, err := im_mysql_model.FindUserByUID(applyUserInfo.ReqId)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,search userInfo failed", err.Error())
continue
}
userInfo.Uid = us.UID
userInfo.Icon = us.Icon
userInfo.Name = us.Name
userInfo.Gender = us.Gender
userInfo.Mobile = us.Mobile
userInfo.Birth = us.Birth
userInfo.Email = us.Email
userInfo.Ex = us.Ex
appleUserList = append(appleUserList, &userInfo)
}
log.Info(req.Token, req.OperationID, fmt.Sprintf("rpc get friendapplylist success return"))
return &pbFriend.GetFriendApplyResp{Data: appleUserList}, nil
}
func (s *friendServer) GetSelfApplyList(ctx context.Context, req *pbFriend.GetFriendApplyReq) (*pbFriend.GetFriendApplyResp, error) {
log.Info(req.Token, req.OperationID, "rpc get self apply list is server,args=%s", req.String())
var selfApplyOtherUserList []*pbFriend.ApplyUserInfo
//Parse token, to find current user information
claims, err := utils.ParseToken(req.Token)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,parse token failed", err.Error())
return &pbFriend.GetFriendApplyResp{ErrorCode: config.ErrParseToken.ErrCode, ErrorMsg: config.ErrParseToken.ErrMsg}, nil
}
// Find the self add other userinfo
usersInfo, err := im_mysql_model.FindSelfApplyFromFriendReq(claims.UID)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,search self to other user Info failed", err.Error())
return &pbFriend.GetFriendApplyResp{ErrorCode: config.ErrMysql.ErrCode, ErrorMsg: config.ErrMysql.ErrMsg}, nil
}
for _, selfApplyOtherUserInfo := range usersInfo {
var userInfo pbFriend.ApplyUserInfo
//Find friend application status
userInfo.Flag = selfApplyOtherUserInfo.Flag
userInfo.ReqMessage = selfApplyOtherUserInfo.ReqMessage
userInfo.ApplyTime = strconv.FormatInt(selfApplyOtherUserInfo.CreateTime.Unix(), 10)
//Find user information
us, err := im_mysql_model.FindUserByUID(selfApplyOtherUserInfo.Uid)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,search userInfo failed", err.Error())
continue
}
userInfo.Uid = us.UID
userInfo.Icon = us.Icon
userInfo.Name = us.Name
userInfo.Gender = us.Gender
userInfo.Mobile = us.Mobile
userInfo.Birth = us.Birth
userInfo.Email = us.Email
userInfo.Ex = us.Ex
selfApplyOtherUserList = append(selfApplyOtherUserList, &userInfo)
}
log.Info(req.Token, req.OperationID, fmt.Sprintf("rpc get self apply list success return"))
return &pbFriend.GetFriendApplyResp{Data: selfApplyOtherUserList}, nil
}
+58
View File
@@ -0,0 +1,58 @@
package friend
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/constant"
"Open_IM/pkg/common/db/mysql_model/im_mysql_model"
"Open_IM/pkg/common/log"
pbFriend "Open_IM/pkg/proto/friend"
"Open_IM/pkg/utils"
"context"
)
func (s *friendServer) GetFriendList(ctx context.Context, req *pbFriend.GetFriendListReq) (*pbFriend.GetFriendListResp, error) {
log.Info(req.Token, req.OperationID, "rpc get friend list is server,args=%s", req.String())
var userInfoList []*pbFriend.UserInfo
//Parse token, to find current user information
claims, err := utils.ParseToken(req.Token)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,parse token failed", err.Error())
return &pbFriend.GetFriendListResp{ErrorCode: config.ErrParseToken.ErrCode, ErrorMsg: config.ErrParseToken.ErrMsg}, nil
}
friends, err := im_mysql_model.FindUserInfoFromFriend(claims.UID)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s search friendInfo failed", err.Error())
return &pbFriend.GetFriendListResp{ErrorCode: config.ErrSearchUserInfo.ErrCode, ErrorMsg: config.ErrSearchUserInfo.ErrMsg}, nil
}
for _, friendUser := range friends {
var friendUserInfo pbFriend.UserInfo
//find user is in blackList
err = im_mysql_model.FindRelationshipFromBlackList(claims.UID, friendUser.FriendId)
if err == nil {
friendUserInfo.IsInBlackList = constant.BlackListFlag
} else {
friendUserInfo.IsInBlackList = 0
}
//Find user information
us, err := im_mysql_model.FindUserByUID(friendUser.FriendId)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s search userInfo failed", err.Error())
continue
}
friendUserInfo.Uid = friendUser.FriendId
friendUserInfo.Comment = friendUser.Comment
friendUserInfo.Icon = us.Icon
friendUserInfo.Name = us.Name
friendUserInfo.Gender = us.Gender
friendUserInfo.Mobile = us.Mobile
friendUserInfo.Birth = us.Birth
friendUserInfo.Email = us.Email
friendUserInfo.Ex = us.Ex
userInfoList = append(userInfoList, &friendUserInfo)
}
log.Info(req.Token, req.OperationID, "rpc get friend list success return")
return &pbFriend.GetFriendListResp{Data: userInfoList}, nil
}
+30
View File
@@ -0,0 +1,30 @@
package friend
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/constant"
"Open_IM/pkg/common/db/mysql_model/im_mysql_model"
"Open_IM/pkg/common/log"
pbFriend "Open_IM/pkg/proto/friend"
"Open_IM/pkg/utils"
"context"
"fmt"
)
func (s *friendServer) IsFriend(ctx context.Context, req *pbFriend.IsFriendReq) (*pbFriend.IsFriendResp, error) {
log.InfoByArgs("rpc is friend is server,args=%s", req.String())
var isFriend int32
claims, err := utils.ParseToken(req.Token)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,parse token failed", err.Error())
return &pbFriend.IsFriendResp{ErrorCode: config.ErrParseToken.ErrCode, ErrorMsg: config.ErrParseToken.ErrMsg}, nil
}
_, err = im_mysql_model.FindFriendRelationshipFromFriend(claims.UID, req.ReceiveUid)
if err == nil {
isFriend = constant.FriendFlag
} else {
isFriend = constant.ApplicationFriendFlag
}
log.InfoByArgs(fmt.Sprintf("rpc is friend success return"))
return &pbFriend.IsFriendResp{ShipType: isFriend}, nil
}
+20
View File
@@ -0,0 +1,20 @@
package friend
import (
"Open_IM/pkg/common/db/mysql_model/im_mysql_model"
"Open_IM/pkg/common/log"
pbFriend "Open_IM/pkg/proto/friend"
"context"
"fmt"
)
func (s *friendServer) IsInBlackList(ctx context.Context, req *pbFriend.IsInBlackListReq) (*pbFriend.IsInBlackListResp, error) {
log.InfoByArgs("rpc is in blacklist is server,args=%s", req.String())
var isInBlacklist = false
err := im_mysql_model.FindRelationshipFromBlackList(req.ReceiveUid, req.SendUid)
if err == nil {
isInBlacklist = true
}
log.InfoByArgs(fmt.Sprintf("rpc is in blackList success return"))
return &pbFriend.IsInBlackListResp{Response: isInBlacklist}, nil
}
+27
View File
@@ -0,0 +1,27 @@
package friend
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/db/mysql_model/im_mysql_model"
"Open_IM/pkg/common/log"
pbFriend "Open_IM/pkg/proto/friend"
"Open_IM/pkg/utils"
"context"
)
func (s *friendServer) RemoveBlacklist(ctx context.Context, req *pbFriend.RemoveBlacklistReq) (*pbFriend.CommonResp, error) {
log.Info(req.Token, req.OperationID, "rpc remove blacklist is server,userid=%s", req.Uid)
//Parse token, to find current user information
claims, err := utils.ParseToken(req.Token)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,parse token failed", err.Error())
return &pbFriend.CommonResp{ErrorCode: config.ErrParseToken.ErrCode, ErrorMsg: config.ErrParseToken.ErrMsg}, nil
}
err = im_mysql_model.RemoveBlackList(claims.UID, req.Uid)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,remove blacklist failed", err.Error())
return &pbFriend.CommonResp{ErrorCode: config.ErrMysql.ErrCode, ErrorMsg: config.ErrMysql.ErrMsg}, nil
}
log.Info(req.Token, req.OperationID, "rpc remove blacklist success return,userid=%s", req.Uid)
return &pbFriend.CommonResp{}, nil
}
+27
View File
@@ -0,0 +1,27 @@
package friend
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/db/mysql_model/im_mysql_model"
"Open_IM/pkg/common/log"
pbFriend "Open_IM/pkg/proto/friend"
"Open_IM/pkg/utils"
"context"
)
func (s *friendServer) SetFriendComment(ctx context.Context, req *pbFriend.SetFriendCommentReq) (*pbFriend.CommonResp, error) {
log.Info(req.Token, req.OperationID, "rpc set friend comment is server,params=%s", req.String())
//Parse token, to find current user information
claims, err := utils.ParseToken(req.Token)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,parse token failed", err.Error())
return &pbFriend.CommonResp{ErrorCode: config.ErrParseToken.ErrCode, ErrorMsg: config.ErrParseToken.ErrMsg}, nil
}
err = im_mysql_model.UpdateFriendComment(claims.UID, req.Uid, req.Comment)
if err != nil {
log.Error(req.Token, req.OperationID, "set friend comment failed,err=%s", err.Error())
return &pbFriend.CommonResp{ErrorCode: config.ErrSetFriendComment.ErrCode, ErrorMsg: config.ErrSetFriendComment.ErrMsg}, nil
}
log.Info(req.Token, req.OperationID, "rpc set friend comment is success return")
return &pbFriend.CommonResp{}, nil
}
+161
View File
@@ -0,0 +1,161 @@
package group
import (
"Open_IM/internal/push/content_struct"
"Open_IM/internal/push/logic"
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/constant"
"Open_IM/pkg/common/db"
"Open_IM/pkg/common/db/mysql_model/im_mysql_model"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbChat "Open_IM/pkg/proto/chat"
pbGroup "Open_IM/pkg/proto/group"
"Open_IM/pkg/utils"
"context"
"google.golang.org/grpc"
"net"
"strconv"
"strings"
"time"
)
type groupServer struct {
rpcPort int
rpcRegisterName string
etcdSchema string
etcdAddr []string
}
func NewGroupServer(port int) *groupServer {
log.NewPrivateLog("group")
return &groupServer{
rpcPort: port,
rpcRegisterName: config.Config.RpcRegisterName.OpenImGroupName,
etcdSchema: config.Config.Etcd.EtcdSchema,
etcdAddr: config.Config.Etcd.EtcdAddr,
}
}
func (s *groupServer) Run() {
log.Info("", "", "rpc group init....")
ip := utils.ServerIP
registerAddress := ip + ":" + strconv.Itoa(s.rpcPort)
//listener network
listener, err := net.Listen("tcp", registerAddress)
if err != nil {
log.InfoByArgs("listen network failed,err=%s", err.Error())
return
}
log.Info("", "", "listen network success, address = %s", registerAddress)
defer listener.Close()
//grpc server
srv := grpc.NewServer()
defer srv.GracefulStop()
//Service registers with etcd
pbGroup.RegisterGroupServer(srv, s)
err = getcdv3.RegisterEtcd(s.etcdSchema, strings.Join(s.etcdAddr, ","), ip, s.rpcPort, s.rpcRegisterName, 10)
if err != nil {
log.ErrorByArgs("get etcd failed,err=%s", err.Error())
return
}
err = srv.Serve(listener)
if err != nil {
log.ErrorByArgs("listen rpc_group error,err=%s", err.Error())
return
}
log.Info("", "", "rpc create group init success")
}
func (s *groupServer) CreateGroup(ctx context.Context, req *pbGroup.CreateGroupReq) (*pbGroup.CreateGroupResp, error) {
log.InfoByArgs("rpc create group is server,args=%s", req.String())
var (
groupId string
)
//Parse token, to find current user information
claims, err := utils.ParseToken(req.Token)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,parse token failed", err.Error())
return &pbGroup.CreateGroupResp{ErrorCode: config.ErrParseToken.ErrCode, ErrorMsg: config.ErrParseToken.ErrMsg}, nil
}
//Time stamp + MD5 to generate group chat id
groupId = utils.Md5(strconv.FormatInt(time.Now().UnixNano(), 10))
err = im_mysql_model.InsertIntoGroup(groupId, req.GroupName, req.Introduction, req.Notification, req.FaceUrl, req.Ex)
if err != nil {
log.ErrorByKv("create group chat failed", req.OperationID, "err=%s", err.Error())
return &pbGroup.CreateGroupResp{ErrorCode: config.ErrCreateGroup.ErrCode, ErrorMsg: config.ErrCreateGroup.ErrMsg}, nil
}
isMagagerFlag := 0
tokenUid := claims.UID
if utils.IsContain(tokenUid, config.Config.Manager.AppManagerUid) {
isMagagerFlag = 1
}
if isMagagerFlag == 0 {
//Add the group owner to the group first, otherwise the group creation will fail
us, err := im_mysql_model.FindUserByUID(claims.UID)
if err != nil {
log.Error("", req.OperationID, "find userInfo failed", err.Error())
return &pbGroup.CreateGroupResp{ErrorCode: config.ErrCreateGroup.ErrCode, ErrorMsg: config.ErrCreateGroup.ErrMsg}, nil
}
err = im_mysql_model.InsertIntoGroupMember(groupId, claims.UID, us.Name, us.Icon, constant.GroupOwner)
if err != nil {
log.Error("", req.OperationID, "create group chat failed,err=%s", err.Error())
return &pbGroup.CreateGroupResp{ErrorCode: config.ErrCreateGroup.ErrCode, ErrorMsg: config.ErrCreateGroup.ErrMsg}, nil
}
err = db.DB.AddGroupMember(groupId, claims.UID)
if err != nil {
log.Error("", "", "create mongo group member failed, db.DB.AddGroupMember fail [err: %s]", err.Error())
return &pbGroup.CreateGroupResp{ErrorCode: config.ErrCreateGroup.ErrCode, ErrorMsg: config.ErrCreateGroup.ErrMsg}, nil
}
}
//Binding group id and member id
for _, user := range req.MemberList {
us, err := im_mysql_model.FindUserByUID(user.Uid)
if err != nil {
log.Error("", req.OperationID, "find userInfo failed,uid=%s", user.Uid, err.Error())
continue
}
err = im_mysql_model.InsertIntoGroupMember(groupId, user.Uid, us.Name, us.Icon, user.SetRole)
if err != nil {
log.ErrorByArgs("pull %s to group %s failed,err=%s", user.Uid, groupId, err.Error())
}
err = db.DB.AddGroupMember(groupId, user.Uid)
if err != nil {
log.Error("", "", "add mongo group member failed, db.DB.AddGroupMember fail [err: %s]", err.Error())
}
}
if isMagagerFlag == 1 {
//type NotificationContent struct {
// IsDisplay int32 `json:"isDisplay"`
// DefaultTips string `json:"defaultTips"`
// Detail string `json:"detail"`
//} n := NotificationContent{
// IsDisplay: 1,
// DefaultTips: "You have joined the group chat:" + createGroupResp.Data.GroupName,
// Detail: createGroupResp.Data.GroupId,
// }
////Push message when create group chat
n := content_struct.NotificationContent{1, req.GroupName, groupId}
logic.SendMsgByWS(&pbChat.WSToMsgSvrChatMsg{
SendID: claims.UID,
RecvID: groupId,
Content: n.ContentToString(),
SendTime: utils.GetCurrentTimestampByNano(),
MsgFrom: constant.SysMsgType, //Notification message identification
ContentType: constant.CreateGroupTip, //Add friend flag
SessionType: constant.GroupChatType,
OperationID: req.OperationID,
})
}
log.Info(req.Token, req.OperationID, "rpc create group success return")
return &pbGroup.CreateGroupResp{GroupID: groupId}, nil
}
@@ -0,0 +1,21 @@
package group
import (
"Open_IM/pkg/common/db/mysql_model/im_mysql_model"
"Open_IM/pkg/common/log"
"Open_IM/pkg/proto/group"
"context"
)
func (s *groupServer) GetGroupApplicationList(_ context.Context, pb *group.GetGroupApplicationListReq) (*group.GetGroupApplicationListResp, error) {
log.Info("", "", "rpc GetGroupApplicationList call start..., [pb: %s]", pb.String())
reply, err := im_mysql_model.GetGroupApplicationList(pb.UID)
if err != nil {
log.Error("", "", "rpc GetGroupApplicationList call..., im_mysql_model.GetGroupApplicationList fail [uid: %s] [err: %s]", pb.UID, err.Error())
return &group.GetGroupApplicationListResp{ErrCode: 701, ErrMsg: "GetGroupApplicationList failed"}, nil
}
log.Info("", "", "rpc GetGroupApplicationList call..., im_mysql_model.GetGroupApplicationList")
return reply, nil
}
+42
View File
@@ -0,0 +1,42 @@
package group
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/db/mysql_model/im_mysql_model"
"Open_IM/pkg/common/log"
pbGroup "Open_IM/pkg/proto/group"
"Open_IM/pkg/utils"
"context"
)
func (s *groupServer) GetGroupsInfo(ctx context.Context, req *pbGroup.GetGroupsInfoReq) (*pbGroup.GetGroupsInfoResp, error) {
log.Info(req.Token, req.OperationID, "rpc get group info is server,args=%s", req.String())
//Parse token, to find current user information
claims, err := utils.ParseToken(req.Token)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,parse token failed", err.Error())
return &pbGroup.GetGroupsInfoResp{ErrorCode: config.ErrParseToken.ErrCode, ErrorMsg: config.ErrParseToken.ErrMsg}, nil
}
log.Info("", req.OperationID, "args:", req.GroupIDList, claims.UID)
groupsInfoList := make([]*pbGroup.GroupInfo, 0)
for _, groupID := range req.GroupIDList {
groupInfoFromMysql, err := im_mysql_model.FindGroupInfoByGroupId(groupID)
if err != nil {
log.Error(req.Token, req.OperationID, "find group info failed,err=%s", err.Error())
continue
}
var groupInfo pbGroup.GroupInfo
groupInfo.GroupId = groupID
groupInfo.GroupName = groupInfoFromMysql.Name
groupInfo.Introduction = groupInfoFromMysql.Introduction
groupInfo.Notification = groupInfoFromMysql.Notification
groupInfo.FaceUrl = groupInfoFromMysql.FaceUrl
groupInfo.OwnerId = im_mysql_model.GetGroupOwnerByGroupId(groupID)
groupInfo.MemberCount = uint32(im_mysql_model.GetGroupMemberNumByGroupId(groupID))
groupInfo.CreateTime = uint64(groupInfoFromMysql.CreateTime.Unix())
groupsInfoList = append(groupsInfoList, &groupInfo)
}
log.Info(req.Token, req.OperationID, "rpc get groupsInfo success return")
return &pbGroup.GetGroupsInfoResp{Data: groupsInfoList}, nil
}
+396
View File
@@ -0,0 +1,396 @@
package group
import (
"Open_IM/internal/push/content_struct"
"Open_IM/internal/push/logic"
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/constant"
"Open_IM/pkg/common/db"
pbChat "Open_IM/pkg/proto/chat"
"encoding/json"
imdb "Open_IM/pkg/common/db/mysql_model/im_mysql_model"
"Open_IM/pkg/common/log"
pbGroup "Open_IM/pkg/proto/group"
"Open_IM/pkg/utils"
"context"
"fmt"
)
func (s *groupServer) GetJoinedGroupList(ctx context.Context, req *pbGroup.GetJoinedGroupListReq) (*pbGroup.GetJoinedGroupListResp, error) {
claims, err := utils.ParseToken(req.Token)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,parse token failed", err.Error())
return &pbGroup.GetJoinedGroupListResp{ErrorCode: config.ErrParseToken.ErrCode, ErrorMsg: config.ErrParseToken.ErrMsg}, nil
}
log.Info(claims.UID, req.OperationID, "recv req: ", req.String())
joinedGroupList, err := imdb.GetJoinedGroupIdListByMemberId(claims.UID)
if err != nil {
log.Error(claims.UID, req.OperationID, "GetJoinedGroupIdListByMemberId failed, err: ", err.Error())
return &pbGroup.GetJoinedGroupListResp{ErrorCode: config.ErrParam.ErrCode, ErrorMsg: config.ErrParam.ErrMsg}, nil
}
var resp pbGroup.GetJoinedGroupListResp
for _, v := range joinedGroupList {
var groupNode pbGroup.GroupInfo
num := imdb.GetGroupMemberNumByGroupId(v.GroupId)
owner := imdb.GetGroupOwnerByGroupId(v.GroupId)
group, err := imdb.FindGroupInfoByGroupId(v.GroupId)
if num > 0 && owner != "" && err == nil {
groupNode.GroupId = v.GroupId
groupNode.FaceUrl = group.FaceUrl
groupNode.CreateTime = uint64(group.CreateTime.Unix())
groupNode.GroupName = group.Name
groupNode.Introduction = group.Introduction
groupNode.Notification = group.Notification
groupNode.OwnerId = owner
groupNode.MemberCount = uint32(int32(num))
resp.GroupList = append(resp.GroupList, &groupNode)
}
log.Info(claims.UID, req.OperationID, "member num: ", num, "owner: ", owner)
}
resp.ErrorCode = 0
return &resp, nil
}
func (s *groupServer) InviteUserToGroup(ctx context.Context, req *pbGroup.InviteUserToGroupReq) (*pbGroup.InviteUserToGroupResp, error) {
claims, err := utils.ParseToken(req.Token)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,parse token failed", err.Error())
return &pbGroup.InviteUserToGroupResp{ErrorCode: config.ErrParseToken.ErrCode, ErrorMsg: config.ErrParseToken.ErrMsg}, nil
}
log.Info(claims.UID, req.OperationID, "recv req: ", req.String())
// if !imdb.IsExistGroupMember(req.GroupID, claims.UID) && claims.UID != config.Config.AppManagerUid
if !imdb.IsExistGroupMember(req.GroupID, claims.UID) && !utils.IsContain(claims.UID, config.Config.Manager.AppManagerUid) {
log.Error(req.Token, req.OperationID, "err= invite user not in group")
return &pbGroup.InviteUserToGroupResp{ErrorCode: config.ErrAccess.ErrCode, ErrorMsg: config.ErrAccess.ErrMsg}, nil
}
groupInfoFromMysql, err := imdb.FindGroupInfoByGroupId(req.GroupID)
if err != nil || groupInfoFromMysql == nil {
log.NewError(req.OperationID, "get group info error", req.GroupID, req.UidList)
return &pbGroup.InviteUserToGroupResp{ErrorCode: config.ErrAccess.ErrCode, ErrorMsg: config.ErrAccess.ErrMsg}, nil
}
//
//from User: invite: applicant
//to user: invite: invited
//to application
var resp pbGroup.InviteUserToGroupResp
/*
fromUserInfo, err := imdb.FindUserByUID(claims.UID)
if err != nil {
log.Error(claims.UID, req.OperationID, "FindUserByUID failed, err: ", err.Error())
return &pbGroup.InviteUserToGroupResp{ErrorCode: config.ErrParam.ErrCode, ErrorMsg: config.ErrParam.ErrMsg}, nil
}*/
var nicknameList string
for _, v := range req.UidList {
var resultNode pbGroup.Id2Result
resultNode.UId = v
resultNode.Result = 0
toUserInfo, err := imdb.FindUserByUID(v)
if err != nil {
log.Error(v, req.OperationID, "FindUserByUID failed, err: ", err.Error())
resultNode.Result = -1
resp.Id2Result = append(resp.Id2Result, &resultNode)
continue
}
if imdb.IsExistGroupMember(req.GroupID, v) {
log.Error(v, req.OperationID, "user has already in group")
resultNode.Result = -1
resp.Id2Result = append(resp.Id2Result, &resultNode)
continue
}
err = imdb.InsertGroupMember(req.GroupID, toUserInfo.UID, toUserInfo.Name, toUserInfo.Icon, 0)
if err != nil {
log.Error(v, req.OperationID, "InsertGroupMember failed, ", err.Error(), "params: ",
req.GroupID, toUserInfo.UID, toUserInfo.Name, toUserInfo.Icon)
resultNode.Result = -1
resp.Id2Result = append(resp.Id2Result, &resultNode)
continue
}
err = db.DB.AddGroupMember(req.GroupID, toUserInfo.UID)
if err != nil {
log.Error("", "", "add mongo group member failed, db.DB.AddGroupMember fail [err: %s]", err.Error())
}
nicknameList = nicknameList + toUserInfo.Name + " "
resp.Id2Result = append(resp.Id2Result, &resultNode)
}
resp.ErrorCode = 0
resp.ErrorMsg = "ok"
//if claims.UID == config.Config.AppManagerUid
if utils.IsContain(claims.UID, config.Config.Manager.AppManagerUid) {
m, _ := imdb.FindUserByUID(claims.UID)
var iu inviteUserToGroupReq
iu.GroupID = req.GroupID
iu.OperationID = req.OperationID
iu.Reason = req.Reason
iu.UidList = req.UidList
n := content_struct.NotificationContent{1, nicknameList + " invited into the group chat by " + m.Name, iu.ContentToString()}
logic.SendMsgByWS(&pbChat.WSToMsgSvrChatMsg{
SendID: claims.UID,
RecvID: req.GroupID,
Content: n.ContentToString(),
SendTime: utils.GetCurrentTimestampByNano(),
MsgFrom: constant.UserMsgType,
ContentType: constant.InviteUserToGroupTip,
SessionType: constant.GroupChatType,
OperationID: req.OperationID,
})
}
return &resp, nil
}
type inviteUserToGroupReq struct {
GroupID string `json:"groupID"`
UidList []string `json:"uidList"`
Reason string `json:"reason"`
OperationID string `json:"operationID"`
}
func (c *inviteUserToGroupReq) ContentToString() string {
data, _ := json.Marshal(c)
dataString := string(data)
return dataString
}
func (s *groupServer) GetGroupAllMember(ctx context.Context, req *pbGroup.GetGroupAllMemberReq) (*pbGroup.GetGroupAllMemberResp, error) {
//claims, err := utils.ParseToken(req.Token)
//if err != nil {
// log.Error(req.Token, req.OperationID, "err=%s,parse token failed", err.Error())
// if req.Token != config.Config.Secret {
// return &pbGroup.GetGroupAllMemberResp{ErrorCode: config.ErrParseToken.ErrCode, ErrorMsg: config.ErrParseToken.ErrMsg}, nil
// }
//}
var resp pbGroup.GetGroupAllMemberResp
resp.ErrorCode = 0
memberList, err := imdb.FindGroupMemberListByGroupId(req.GroupID)
if err != nil {
resp.ErrorCode = config.ErrDb.ErrCode
resp.ErrorMsg = err.Error()
log.NewError(req.OperationID, "FindGroupMemberListByGroupId failed,", err.Error(), req.GroupID)
return &resp, nil
}
for _, v := range memberList {
var node pbGroup.GroupMemberFullInfo
node.Role = v.AdministratorLevel
node.NickName = v.NickName
node.UserId = v.Uid
node.FaceUrl = v.UserGroupFaceUrl
node.JoinTime = uint64(v.JoinTime.Unix())
resp.MemberList = append(resp.MemberList, &node)
}
resp.ErrorCode = 0
return &resp, nil
}
func (s *groupServer) GetGroupMemberList(ctx context.Context, req *pbGroup.GetGroupMemberListReq) (*pbGroup.GetGroupMemberListResp, error) {
claims, err := utils.ParseToken(req.Token)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,parse token failed", err.Error())
return &pbGroup.GetGroupMemberListResp{ErrorCode: config.ErrParseToken.ErrCode, ErrorMsg: config.ErrParseToken.ErrMsg}, nil
}
// log.Info(claims.UID, req.OperationID, "recv req: ", req.String())
fmt.Println("req: ", req.GroupID)
var resp pbGroup.GetGroupMemberListResp
resp.ErrorCode = 0
memberList, err := imdb.GetGroupMemberByGroupId(req.GroupID, req.Filter, req.NextSeq, 30)
if err != nil {
resp.ErrorCode = config.ErrDb.ErrCode
resp.ErrorMsg = err.Error()
log.Error(claims.UID, req.OperationID, "GetGroupMemberByGroupId failed, ", err.Error(), "params: ", req.GroupID, req.Filter, req.NextSeq)
return &resp, nil
}
for _, v := range memberList {
var node pbGroup.GroupMemberFullInfo
node.Role = v.AdministratorLevel
node.NickName = v.NickName
node.UserId = v.Uid
// node.FaceUrl =
node.JoinTime = uint64(v.JoinTime.Unix())
resp.MemberList = append(resp.MemberList, &node)
}
//db operate get db sorted by join time
if int32(len(memberList)) < 30 {
resp.NextSeq = 0
} else {
resp.NextSeq = req.NextSeq + int32(len(memberList))
}
resp.ErrorCode = 0
return &resp, nil
}
type groupMemberFullInfo struct {
GroupId string `json:"groupID"`
UserId string `json:"userId"`
Role int `json:"role"`
JoinTime uint64 `json:"joinTime"`
NickName string `json:"nickName"`
FaceUrl string `json:"faceUrl"`
}
type kickGroupMemberApiReq struct {
GroupID string `json:"groupID"`
UidListInfo []groupMemberFullInfo `json:"uidListInfo"`
Reason string `json:"reason"`
OperationID string `json:"operationID"`
}
func (c *kickGroupMemberApiReq) ContentToString() string {
data, _ := json.Marshal(c)
dataString := string(data)
return dataString
}
func (s *groupServer) KickGroupMember(ctx context.Context, req *pbGroup.KickGroupMemberReq) (*pbGroup.KickGroupMemberResp, error) {
claims, err := utils.ParseToken(req.Token)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,parse token failed", err.Error())
return &pbGroup.KickGroupMemberResp{ErrorCode: config.ErrParseToken.ErrCode, ErrorMsg: config.ErrParseToken.ErrMsg}, nil
}
log.Info(claims.UID, req.OperationID, "recv req: ", req.String())
ownerList, err := imdb.GetOwnerManagerByGroupId(req.GroupID)
if err != nil {
log.Error(claims.UID, req.OperationID, req.GroupID, "GetOwnerManagerByGroupId, ", err.Error())
return &pbGroup.KickGroupMemberResp{ErrorCode: config.ErrParam.ErrCode, ErrorMsg: config.ErrParam.ErrMsg}, nil
}
//op is group owner?
var flag = 0
for _, v := range ownerList {
if v.Uid == claims.UID {
flag = 1
break
}
}
if flag != 1 {
// if claims.UID == config.Config.AppManagerUid {
if utils.IsContain(claims.UID, config.Config.Manager.AppManagerUid) {
flag = 1
}
}
if flag != 1 {
log.Error(claims.UID, req.OperationID, "no access kick")
return &pbGroup.KickGroupMemberResp{ErrorCode: config.ErrAccess.ErrCode, ErrorMsg: config.ErrAccess.ErrMsg}, nil
}
if len(req.UidListInfo) == 0 {
log.Error(claims.UID, req.OperationID, "kick list 0")
return &pbGroup.KickGroupMemberResp{ErrorCode: config.ErrParam.ErrCode, ErrorMsg: config.ErrParam.ErrMsg}, nil
}
//remove
var resp pbGroup.KickGroupMemberResp
for _, v := range req.UidListInfo {
//owner cant kicked
if v.UserId == claims.UID {
log.Error(claims.UID, req.OperationID, v.UserId, "cant kick owner")
resp.Id2Result = append(resp.Id2Result, &pbGroup.Id2Result{UId: v.UserId, Result: -1})
continue
}
err := imdb.RemoveGroupMember(req.GroupID, v.UserId)
if err != nil {
log.Error(claims.UID, req.OperationID, v.UserId, req.GroupID, "RemoveGroupMember failed ", err.Error())
resp.Id2Result = append(resp.Id2Result, &pbGroup.Id2Result{UId: v.UserId, Result: -1})
} else {
resp.Id2Result = append(resp.Id2Result, &pbGroup.Id2Result{UId: v.UserId, Result: 0})
}
err = db.DB.DelGroupMember(req.GroupID, v.UserId)
if err != nil {
log.Error("", "", "delete mongo group member failed, db.DB.DelGroupMember fail [err: %s]", err.Error())
}
}
var kq kickGroupMemberApiReq
kq.GroupID = req.GroupID
kq.OperationID = req.OperationID
kq.Reason = req.Reason
var gf groupMemberFullInfo
for _, v := range req.UidListInfo {
gf.UserId = v.UserId
gf.GroupId = req.GroupID
kq.UidListInfo = append(kq.UidListInfo, gf)
}
n := content_struct.NotificationContent{1, req.GroupID, kq.ContentToString()}
if utils.IsContain(claims.UID, config.Config.Manager.AppManagerUid) {
log.Info("", req.OperationID, claims.UID, req.GroupID)
logic.SendMsgByWS(&pbChat.WSToMsgSvrChatMsg{
SendID: claims.UID,
RecvID: req.GroupID,
Content: n.ContentToString(),
SendTime: utils.GetCurrentTimestampByNano(),
MsgFrom: constant.UserMsgType,
ContentType: constant.KickGroupMemberTip,
SessionType: constant.GroupChatType,
OperationID: req.OperationID,
})
for _, v := range req.UidListInfo {
log.Info("", req.OperationID, claims.UID, v.UserId)
logic.SendMsgByWS(&pbChat.WSToMsgSvrChatMsg{
SendID: claims.UID,
RecvID: v.UserId,
Content: n.ContentToString(),
SendTime: utils.GetCurrentTimestampBySecond(),
MsgFrom: constant.UserMsgType,
ContentType: constant.KickGroupMemberTip,
SessionType: constant.SingleChatType,
OperationID: req.OperationID,
})
}
}
resp.ErrorCode = 0
return &resp, nil
}
func (s *groupServer) GetGroupMembersInfo(ctx context.Context, req *pbGroup.GetGroupMembersInfoReq) (*pbGroup.GetGroupMembersInfoResp, error) {
claims, err := utils.ParseToken(req.Token)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,parse token failed", err.Error())
return &pbGroup.GetGroupMembersInfoResp{ErrorCode: config.ErrParseToken.ErrCode, ErrorMsg: config.ErrParseToken.ErrMsg}, nil
}
log.InfoByKv(claims.UID, req.OperationID, "param: ", req.MemberList)
var resp pbGroup.GetGroupMembersInfoResp
for _, v := range req.MemberList {
var memberNode pbGroup.GroupMemberFullInfo
memberInfo, err := imdb.GetMemberInfoById(req.GroupID, v)
memberNode.UserId = v
fmt.Println("id : ", memberNode.UserId)
if err != nil {
log.Error(claims.UID, req.OperationID, req.GroupID, v, "GetMemberInfoById failed, ", err.Error())
//error occurs, only id is valid
resp.MemberList = append(resp.MemberList, &memberNode)
continue
}
user, err := imdb.FindUserByUID(v)
if err == nil && user != nil {
memberNode.FaceUrl = user.Icon
memberNode.JoinTime = uint64(memberInfo.JoinTime.Unix())
memberNode.UserId = user.UID
memberNode.NickName = memberInfo.NickName
memberNode.Role = memberInfo.AdministratorLevel
}
resp.MemberList = append(resp.MemberList, &memberNode)
}
resp.ErrorCode = 0
return &resp, nil
}
@@ -0,0 +1,39 @@
package group
import (
"Open_IM/pkg/common/db"
"Open_IM/pkg/common/db/mysql_model/im_mysql_model"
"Open_IM/pkg/common/log"
"Open_IM/pkg/proto/group"
"context"
)
func (s *groupServer) GroupApplicationResponse(_ context.Context, pb *group.GroupApplicationResponseReq) (*group.GroupApplicationResponseResp, error) {
log.Info("", "", "rpc GroupApplicationResponse call start..., [pb: %s]", pb.String())
reply, err := im_mysql_model.GroupApplicationResponse(pb)
if err != nil {
log.Error("", "", "rpc GroupApplicationResponse call..., im_mysql_model.GroupApplicationResponse fail [pb: %s] [err: %s]", pb.String(), err.Error())
return &group.GroupApplicationResponseResp{ErrCode: 702, ErrMsg: "rpc GroupApplicationResponse failed"}, nil
}
if pb.HandleResult == 1 {
if pb.ToUserID == "0" {
err = db.DB.AddGroupMember(pb.GroupID, pb.FromUserID)
if err != nil {
log.Error("", "", "rpc GroupApplicationResponse call..., db.DB.AddGroupMember fail [pb: %s] [err: %s]", pb.String(), err.Error())
return nil, err
}
} else {
err = db.DB.AddGroupMember(pb.GroupID, pb.ToUserID)
if err != nil {
log.Error("", "", "rpc GroupApplicationResponse call..., db.DB.AddGroupMember fail [pb: %s] [err: %s]", pb.String(), err.Error())
return nil, err
}
}
}
log.Info("", "", "rpc GroupApplicationResponse call..., im_mysql_model.GroupApplicationResponse")
return reply, nil
}
+57
View File
@@ -0,0 +1,57 @@
package group
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/db/mysql_model/im_mysql_model"
"Open_IM/pkg/common/log"
pbGroup "Open_IM/pkg/proto/group"
"Open_IM/pkg/utils"
"context"
)
func (s *groupServer) JoinGroup(ctx context.Context, req *pbGroup.JoinGroupReq) (*pbGroup.CommonResp, error) {
log.Info(req.Token, req.OperationID, "rpc join group is server,args=%s", req.String())
//Parse token, to find current user information
claims, err := utils.ParseToken(req.Token)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,parse token failed", err.Error())
return &pbGroup.CommonResp{ErrorCode: config.ErrParseToken.ErrCode, ErrorMsg: config.ErrParseToken.ErrMsg}, nil
}
applicationUserInfo, err := im_mysql_model.FindUserByUID(claims.UID)
if err != nil {
log.Error(req.Token, req.OperationID, "No this user,err=%s", err.Error())
return &pbGroup.CommonResp{ErrorCode: config.ErrSearchUserInfo.ErrCode, ErrorMsg: config.ErrSearchUserInfo.ErrMsg}, nil
}
_, err = im_mysql_model.FindGroupRequestUserInfoByGroupIDAndUid(req.GroupID, claims.UID)
if err == nil {
err = im_mysql_model.DelGroupRequest(req.GroupID, claims.UID, "0")
}
log.Info(req.Token, req.OperationID, "args: ", req.GroupID, claims.UID, "0", req.Message, applicationUserInfo.Name, applicationUserInfo.Icon)
if err = im_mysql_model.InsertIntoGroupRequest(req.GroupID, claims.UID, "0", req.Message, applicationUserInfo.Name, applicationUserInfo.Icon); err != nil {
log.Error(req.Token, req.OperationID, "Insert into group request failed,er=%s", err.Error())
return &pbGroup.CommonResp{ErrorCode: config.ErrJoinGroupApplication.ErrCode, ErrorMsg: config.ErrJoinGroupApplication.ErrMsg}, nil
}
////Find the the group owner
//groupCreatorInfo, err := im_mysql_model.FindGroupMemberListByGroupIdAndFilterInfo(req.GroupID, constant.GroupCreator)
//if err != nil {
// log.Error(req.Token, req.OperationID, "find group creator failed", err.Error())
//} else {
// //Push message when join group chat
// logic.SendMsgByWS(&pbChat.WSToMsgSvrChatMsg{
// SendID: claims.UID,
// RecvID: groupCreatorInfo[0].Uid,
// Content: content_struct.NewContentStructString(0, "", req.String()),
// SendTime: utils.GetCurrentTimestampBySecond(),
// MsgFrom: constant.SysMsgType,
// ContentType: constant.JoinGroupTip,
// SessionType: constant.SingleChatType,
// OperationID: req.OperationID,
// })
//}
log.Info(req.Token, req.OperationID, "rpc join group success return")
return &pbGroup.CommonResp{}, nil
}
+55
View File
@@ -0,0 +1,55 @@
package group
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/db"
"Open_IM/pkg/common/db/mysql_model/im_mysql_model"
"Open_IM/pkg/common/log"
pbGroup "Open_IM/pkg/proto/group"
"Open_IM/pkg/utils"
"context"
)
func (s *groupServer) QuitGroup(ctx context.Context, req *pbGroup.QuitGroupReq) (*pbGroup.CommonResp, error) {
log.InfoByArgs("rpc quit group is server,args:", req.String())
//Parse token, to find current user information
claims, err := utils.ParseToken(req.Token)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,parse token failed", err.Error())
return &pbGroup.CommonResp{ErrorCode: config.ErrParseToken.ErrCode, ErrorMsg: config.ErrParseToken.ErrMsg}, nil
}
log.InfoByKv("args:", req.OperationID, req.GetGroupID(), claims.UID)
//Check to see whether there is a user in the group.
_, err = im_mysql_model.FindGroupMemberInfoByGroupIdAndUserId(req.GroupID, claims.UID)
if err != nil {
log.Error(req.Token, req.OperationID, "no such group or you are not in the group,err=%s", err.Error(), req.OperationID, req.GroupID, claims.UID)
return &pbGroup.CommonResp{ErrorCode: config.ErrQuitGroup.ErrCode, ErrorMsg: config.ErrQuitGroup.ErrMsg}, nil
}
//After the user's verification is successful, user will quit the group chat.
err = im_mysql_model.DeleteGroupMemberByGroupIdAndUserId(req.GroupID, claims.UID)
if err != nil {
log.ErrorByArgs("this user exit the group failed,err=%s", err.Error(), req.OperationID, req.GroupID, claims.UID)
return &pbGroup.CommonResp{ErrorCode: config.ErrQuitGroup.ErrCode, ErrorMsg: config.ErrQuitGroup.ErrMsg}, nil
}
err = db.DB.DelGroupMember(req.GroupID, claims.UID)
if err != nil {
log.Error("", "", "delete mongo group member failed, db.DB.DelGroupMember fail [err: %s]", err.Error())
return &pbGroup.CommonResp{ErrorCode: config.ErrQuitGroup.ErrCode, ErrorMsg: config.ErrQuitGroup.ErrMsg}, nil
}
////Push message when quit group chat
//jsonInfo, _ := json.Marshal(req)
//logic.SendMsgByWS(&pbChat.WSToMsgSvrChatMsg{
// SendID: claims.UID,
// RecvID: req.GroupID,
// Content: string(jsonInfo),
// SendTime: utils.GetCurrentTimestampBySecond(),
// MsgFrom: constant.SysMsgType,
// ContentType: constant.QuitGroupTip,
// SessionType: constant.GroupChatType,
// OperationID: req.OperationID,
//})
log.Info(req.Token, req.OperationID, "rpc quit group is success return")
return &pbGroup.CommonResp{}, nil
}
+47
View File
@@ -0,0 +1,47 @@
package group
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/constant"
"Open_IM/pkg/common/db/mysql_model/im_mysql_model"
"Open_IM/pkg/common/log"
pbGroup "Open_IM/pkg/proto/group"
"Open_IM/pkg/utils"
"context"
)
func (s *groupServer) SetGroupInfo(ctx context.Context, req *pbGroup.SetGroupInfoReq) (*pbGroup.CommonResp, error) {
log.Info(req.Token, req.OperationID, "rpc set group info is server,args=%s", req.String())
//Parse token, to find current user information
claims, err := utils.ParseToken(req.Token)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,parse token failed", err.Error())
return &pbGroup.CommonResp{ErrorCode: config.ErrParseToken.ErrCode, ErrorMsg: config.ErrParseToken.ErrMsg}, nil
}
groupUserInfo, err := im_mysql_model.FindGroupMemberInfoByGroupIdAndUserId(req.GroupID, claims.UID)
if err != nil {
log.Error("", req.OperationID, "your are not in the group,can not change this group info,err=%s", err.Error())
return &pbGroup.CommonResp{ErrorCode: config.ErrSetGroupInfo.ErrCode, ErrorMsg: config.ErrSetGroupInfo.ErrMsg}, nil
}
if groupUserInfo.AdministratorLevel == constant.OrdinaryMember {
return &pbGroup.CommonResp{ErrorCode: config.ErrSetGroupInfo.ErrCode, ErrorMsg: config.ErrAccess.ErrMsg}, nil
}
//only administrators can set group information
if err = im_mysql_model.SetGroupInfo(req.GroupID, req.GroupName, req.Introduction, req.Notification, req.FaceUrl, ""); err != nil {
return &pbGroup.CommonResp{ErrorCode: config.ErrSetGroupInfo.ErrCode, ErrorMsg: config.ErrSetGroupInfo.ErrMsg}, nil
}
////Push message when set group info
//jsonInfo, _ := json.Marshal(req)
//logic.SendMsgByWS(&pbChat.WSToMsgSvrChatMsg{
// SendID: claims.UID,
// RecvID: req.GroupID,
// Content: string(jsonInfo),
// SendTime: utils.GetCurrentTimestampBySecond(),
// MsgFrom: constant.SysMsgType,
// ContentType: constant.SetGroupInfoTip,
// SessionType: constant.GroupChatType,
// OperationID: req.OperationID,
//})
return &pbGroup.CommonResp{}, nil
}
@@ -0,0 +1,21 @@
package group
import (
"Open_IM/pkg/common/db/mysql_model/im_mysql_model"
"Open_IM/pkg/common/log"
"Open_IM/pkg/proto/group"
"context"
)
func (s *groupServer) TransferGroupOwner(_ context.Context, pb *group.TransferGroupOwnerReq) (*group.TransferGroupOwnerResp, error) {
log.Info("", "", "rpc TransferGroupOwner call start..., [pb: %s]", pb.String())
reply, err := im_mysql_model.TransferGroupOwner(pb)
if err != nil {
log.Error("", "", "rpc TransferGroupOwner call..., im_mysql_model.TransferGroupOwner fail [pb: %s] [err: %s]", pb.String(), err.Error())
return nil, err
}
log.Info("", "", "rpc TransferGroupOwner call..., im_mysql_model.TransferGroupOwner")
return reply, nil
}
+97
View File
@@ -0,0 +1,97 @@
package user
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/db/mysql_model/im_mysql_model"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbUser "Open_IM/pkg/proto/user"
"Open_IM/pkg/utils"
"context"
"google.golang.org/grpc"
"net"
"strconv"
"strings"
)
type userServer struct {
rpcPort int
rpcRegisterName string
etcdSchema string
etcdAddr []string
}
func NewUserServer(port int) *userServer {
log.NewPrivateLog("user")
return &userServer{
rpcPort: port,
rpcRegisterName: config.Config.RpcRegisterName.OpenImUserName,
etcdSchema: config.Config.Etcd.EtcdSchema,
etcdAddr: config.Config.Etcd.EtcdAddr,
}
}
func (s *userServer) Run() {
log.Info("", "", "rpc user init....")
ip := utils.ServerIP
registerAddress := ip + ":" + strconv.Itoa(s.rpcPort)
//listener network
listener, err := net.Listen("tcp", registerAddress)
if err != nil {
log.InfoByArgs("listen network failed,err=%s", err.Error())
return
}
log.Info("", "", "listen network success, address = %s", registerAddress)
defer listener.Close()
//grpc server
srv := grpc.NewServer()
defer srv.GracefulStop()
//Service registers with etcd
pbUser.RegisterUserServer(srv, s)
err = getcdv3.RegisterEtcd(s.etcdSchema, strings.Join(s.etcdAddr, ","), ip, s.rpcPort, s.rpcRegisterName, 10)
if err != nil {
log.ErrorByArgs("register rpc token to etcd failed,err=%s", err.Error())
return
}
err = srv.Serve(listener)
if err != nil {
log.ErrorByArgs("listen token failed,err=%s", err.Error())
return
}
log.Info("", "", "rpc token init success")
}
func (s *userServer) GetUserInfo(ctx context.Context, req *pbUser.GetUserInfoReq) (*pbUser.GetUserInfoResp, error) {
log.InfoByKv("rpc get_user_info is server", req.OperationID)
var userInfoList []*pbUser.UserInfo
//Obtain user information according to userID
if len(req.UserIDList) > 0 {
for _, userID := range req.UserIDList {
var userInfo pbUser.UserInfo
user, err := im_mysql_model.FindUserByUID(userID)
if err != nil {
log.ErrorByKv("search userinfo failed", req.OperationID, "userID", userID, "err=%s", err.Error())
continue
}
userInfo.Uid = user.UID
userInfo.Icon = user.Icon
userInfo.Name = user.Name
userInfo.Gender = user.Gender
userInfo.Mobile = user.Mobile
userInfo.Birth = user.Birth
userInfo.Email = user.Email
userInfo.Ex = user.Ex
userInfoList = append(userInfoList, &userInfo)
}
} else {
return &pbUser.GetUserInfoResp{ErrorCode: 999, ErrorMsg: "uidList is nil"}, nil
}
log.InfoByKv("rpc get userInfo return success", req.OperationID, "token", req.Token)
return &pbUser.GetUserInfoResp{
ErrorCode: 0,
ErrorMsg: "",
Data: userInfoList,
}, nil
}
@@ -0,0 +1,16 @@
package internal_service
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbUser "Open_IM/pkg/proto/user"
"context"
"strings"
)
func GetUserInfoClient(req *pbUser.GetUserInfoReq) (*pbUser.GetUserInfoResp, error) {
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImUserName)
client := pbUser.NewUserClient(etcdConn)
RpcResp, err := client.GetUserInfo(context.Background(), req)
return RpcResp, err
}
+61
View File
@@ -0,0 +1,61 @@
/*
** description("").
** copyright('open-im,www.open-im.io').
** author("fg,Gordon@tuoyun.net").
** time(2021/9/15 10:28).
*/
package user
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/db/mysql_model/im_mysql_model"
"Open_IM/pkg/common/log"
pbUser "Open_IM/pkg/proto/user"
"Open_IM/pkg/utils"
"context"
)
func (s *userServer) DeleteUsers(_ context.Context, req *pbUser.DeleteUsersReq) (*pbUser.DeleteUsersResp, error) {
log.InfoByKv("rpc DeleteUsers arrived server", req.OperationID, "args", req.String())
var resp pbUser.DeleteUsersResp
c, err := utils.ParseToken(req.Token)
if err != nil {
log.ErrorByKv("parse token failed", req.OperationID, "err", err.Error())
return &pbUser.DeleteUsersResp{CommonResp: &pbUser.CommonResp{ErrorCode: config.ErrParseToken.ErrCode, ErrorMsg: err.Error()}, FailedUidList: req.DeleteUidList}, nil
}
if !utils.IsContain(c.UID, config.Config.Manager.AppManagerUid) {
log.ErrorByKv(" Authentication failed", req.OperationID, "args", c)
return &pbUser.DeleteUsersResp{CommonResp: &pbUser.CommonResp{ErrorCode: 401, ErrorMsg: "not authorized"}, FailedUidList: req.DeleteUidList}, nil
}
for _, uid := range req.DeleteUidList {
err = im_mysql_model.UserDelete(uid)
if err != nil {
resp.CommonResp.ErrorCode = 201
resp.CommonResp.ErrorMsg = "some uid deleted failed"
resp.FailedUidList = append(resp.FailedUidList, uid)
}
}
return &resp, nil
}
func (s *userServer) GetAllUsersUid(_ context.Context, req *pbUser.GetAllUsersUidReq) (*pbUser.GetAllUsersUidResp, error) {
log.InfoByKv("rpc GetAllUsersUid arrived server", req.OperationID, "args", req.String())
c, err := utils.ParseToken(req.Token)
if err != nil {
log.InfoByKv("parse token failed", req.OperationID, "err", err.Error())
return &pbUser.GetAllUsersUidResp{CommonResp: &pbUser.CommonResp{ErrorCode: config.ErrParseToken.ErrCode, ErrorMsg: err.Error()}}, nil
}
if !utils.IsContain(c.UID, config.Config.Manager.AppManagerUid) {
log.ErrorByKv(" Authentication failed", req.OperationID, "args", c)
return &pbUser.GetAllUsersUidResp{CommonResp: &pbUser.CommonResp{ErrorCode: 401, ErrorMsg: "not authorized"}}, nil
}
uidList, err := im_mysql_model.SelectAllUID()
if err != nil {
log.ErrorByKv("db get failed", req.OperationID, "err", err.Error())
return &pbUser.GetAllUsersUidResp{CommonResp: &pbUser.CommonResp{ErrorCode: config.ErrMysql.ErrCode, ErrorMsg: err.Error()}}, nil
} else {
return &pbUser.GetAllUsersUidResp{CommonResp: &pbUser.CommonResp{ErrorCode: 0, ErrorMsg: ""}, UidList: uidList}, nil
}
}
+81
View File
@@ -0,0 +1,81 @@
package user
import (
"Open_IM/internal/push/logic"
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/constant"
"Open_IM/pkg/common/db/mysql_model/im_mysql_model"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbChat "Open_IM/pkg/proto/chat"
pbFriend "Open_IM/pkg/proto/friend"
pbUser "Open_IM/pkg/proto/user"
"Open_IM/pkg/utils"
"context"
"strings"
)
func (s *userServer) UpdateUserInfo(ctx context.Context, req *pbUser.UpdateUserInfoReq) (*pbUser.CommonResp, error) {
log.Info(req.Token, req.OperationID, "rpc modify user is server,args=%s", req.String())
claims, err := utils.ParseToken(req.Token)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,parse token failed", err.Error())
return &pbUser.CommonResp{ErrorCode: config.ErrParseToken.ErrCode, ErrorMsg: err.Error()}, nil
}
ownerUid := ""
//if claims.UID == config.Config.AppManagerUid {
if utils.IsContain(claims.UID, config.Config.Manager.AppManagerUid) {
ownerUid = req.Uid
} else {
ownerUid = claims.UID
}
err = im_mysql_model.UpDateUserInfo(ownerUid, req.Name, req.Icon, req.Mobile, req.Birth, req.Email, req.Ex, req.Gender)
if err != nil {
log.Error(req.Token, req.OperationID, "update user some attribute failed,err=%s", err.Error())
return &pbUser.CommonResp{ErrorCode: config.ErrModifyUserInfo.ErrCode, ErrorMsg: config.ErrModifyUserInfo.ErrMsg}, nil
}
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImFriendName)
client := pbFriend.NewFriendClient(etcdConn)
newReq := &pbFriend.GetFriendListReq{
OperationID: req.OperationID,
Token: req.Token,
}
RpcResp, err := client.GetFriendList(context.Background(), newReq)
if err != nil {
log.ErrorByKv("get friend list rpc server failed", req.OperationID, "err", err.Error(), "req", req.String())
return &pbUser.CommonResp{}, nil
}
if RpcResp.ErrorCode != 0 {
log.ErrorByKv("get friend list rpc server failed", req.OperationID, "err", err.Error(), "req", req.String())
return &pbUser.CommonResp{}, nil
}
self, err := im_mysql_model.FindUserByUID(ownerUid)
if err != nil {
log.ErrorByKv("get self info failed", req.OperationID, "err", err.Error(), "req", req.String())
return &pbUser.CommonResp{}, nil
}
var name, faceUrl string
if self != nil {
name, faceUrl = self.Name, self.Icon
}
for _, v := range RpcResp.Data {
logic.SendMsgByWS(&pbChat.WSToMsgSvrChatMsg{
SendID: ownerUid,
RecvID: v.Uid,
SenderNickName: name,
SenderFaceURL: faceUrl,
Content: ownerUid + "'s info has changed",
SendTime: utils.GetCurrentTimestampByNano(),
MsgFrom: constant.SysMsgType,
ContentType: constant.SetSelfInfoTip,
SessionType: constant.SingleChatType,
OperationID: req.OperationID,
Token: req.Token,
})
}
return &pbUser.CommonResp{}, nil
}
+26
View File
@@ -0,0 +1,26 @@
package timed_task
type TimeTask struct {
delMgoChatChan chan bool
}
var timeTask TimeTask
func GetInstance() *TimeTask {
if timeTask.delMgoChatChan == nil {
timeTask.delMgoChatChan = make(chan bool)
go func() {
timeTask.delMgoChatChan <- true
}()
}
return &timeTask
}
func (t *TimeTask) Run() {
for {
select {
case <-t.delMgoChatChan:
t.timedDeleteUserChat()
}
}
}
+26
View File
@@ -0,0 +1,26 @@
package timed_task
import (
"Open_IM/pkg/common/db"
"time"
)
func (t *TimeTask) timedDeleteUserChat() {
now := time.Now()
next := now.Add(time.Hour * 24)
next = time.Date(next.Year(), next.Month(), next.Day(), 0, 0, 0, 0, next.Location())
tm := time.NewTimer(next.Sub(now))
<-tm.C
count, _ := db.DB.MgoUserCount()
for i := 0; i < count; i++ {
time.Sleep(10 * time.Millisecond)
uid, _ := db.DB.MgoSkipUID(i)
db.DB.DelUserChat(uid)
}
go func() {
t.delMgoChatChan <- true
}()
}
+68
View File
@@ -0,0 +1,68 @@
package utils
import (
"Open_IM/pkg/utils"
"net/http"
"net/http/httptest"
"testing"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
)
func init() {
gin.SetMode(gin.TestMode)
}
func performRequest(r http.Handler, method, origin string) *httptest.ResponseRecorder {
return performRequestWithHeaders(r, method, origin, http.Header{})
}
func performRequestWithHeaders(r http.Handler, method, origin string, header http.Header) *httptest.ResponseRecorder {
req, _ := http.NewRequest(method, "/", nil)
// From go/net/http/request.go:
// For incoming requests, the Host header is promoted to the
// Request.Host field and removed from the Header map.
req.Host = header.Get("Host")
header.Del("Host")
if len(origin) > 0 {
header.Set("Origin", origin)
}
req.Header = header
w := httptest.NewRecorder()
r.ServeHTTP(w, req)
return w
}
func newTestRouter() *gin.Engine {
router := gin.New()
router.Use(utils.CorsHandler())
router.GET("/", func(c *gin.Context) {
c.String(http.StatusOK, "get")
})
router.POST("/", func(c *gin.Context) {
c.String(http.StatusOK, "post")
})
router.PATCH("/", func(c *gin.Context) {
c.String(http.StatusOK, "patch")
})
return router
}
func Test_CorsHandler(t *testing.T) {
router := newTestRouter()
// no CORS request, origin == ""
w := performRequest(router, "GET", "")
assert.Equal(t, "get", w.Body.String())
assert.Equal(t, w.Header().Get("Access-Control-Allow-Origin"), "*")
assert.Equal(t, w.Header().Get("Access-Control-Allow-Methods"), "*")
assert.Equal(t, w.Header().Get("Access-Control-Allow-Headers"), "*")
assert.Equal(t, w.Header().Get("Access-Control-Expose-Headers"), "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers,Cache-Control,Content-Language,Content-Type,Expires,Last-Modified,Pragma,FooBar")
assert.Equal(t, w.Header().Get("Access-Control-Max-Age"), "172800")
assert.Equal(t, w.Header().Get("Access-Control-Allow-Credentials"), "false")
assert.Equal(t, w.Header().Get("content-type"), "application/json")
w = performRequest(router, "OPTIONS", "")
assert.Equal(t, w.Body.String(), "\"Options Request!\"")
}
+13
View File
@@ -0,0 +1,13 @@
package utils
import (
"Open_IM/pkg/utils"
"net"
"testing"
)
func TestServerIP(t *testing.T) {
if net.ParseIP(utils.ServerIP) == nil {
t.Fail()
}
}
+28
View File
@@ -0,0 +1,28 @@
package utils
import (
"github.com/bwmarrin/snowflake"
)
func init() {
var err error
idGenerator, err = snowflake.NewNode(getNodeNum())
if err != nil {
panic(err)
}
}
func getNodeNum() int64 {
return 1
}
var idGenerator *snowflake.Node
func GenID() string {
return idGenerator.Generate().String()
}
func GenIDs(count int) []string {
//impl
return []string{}
}
+15
View File
@@ -0,0 +1,15 @@
package utils
import "testing"
func TestGenID(t *testing.T) {
m := map[string]struct{}{}
for i := 0; i < 2000; i++ {
got := GenID()
if _, ok := m[got]; !ok {
m[got] = struct{}{}
} else {
t.Error("id generate error", got)
}
}
}
+28
View File
@@ -0,0 +1,28 @@
package utils
import (
"Open_IM/pkg/utils"
"path/filepath"
"runtime"
"testing"
"github.com/stretchr/testify/assert"
)
var (
_, b, _, _ = runtime.Caller(0)
// Root folder of this project
Root = filepath.Join(filepath.Dir(b), "../..")
)
func Test_GenSmallImage(t *testing.T) {
println(Root)
err := utils.GenSmallImage(Root+"/docs/open-im-logo.png", Root+"/out-test/open-im-logo-test.png")
assert.Nil(t, err)
err = utils.GenSmallImage(Root+"/docs/open-im-logo.png", "out-test/open-im-logo-test.png")
assert.Nil(t, err)
err = utils.GenSmallImage(Root+"/docs/Architecture.jpg", "out-test/Architecture-test.jpg")
assert.Nil(t, err)
}
+82
View File
@@ -0,0 +1,82 @@
package utils
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/utils"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
func Test_BuildClaims(t *testing.T) {
uid := "1"
platform := "PC"
ttl := int64(-1)
claim := utils.BuildClaims(uid, platform, ttl)
now := time.Now().Unix()
assert.Equal(t, claim.UID, uid, "uid should equal")
assert.Equal(t, claim.Platform, platform, "platform should equal")
assert.Equal(t, claim.RegisteredClaims.ExpiresAt, int64(-1), "StandardClaims.ExpiresAt should be equal")
// time difference within 1s
assert.Equal(t, claim.RegisteredClaims.IssuedAt, now, "StandardClaims.IssuedAt should be equal")
assert.Equal(t, claim.RegisteredClaims.NotBefore, now, "StandardClaims.NotBefore should be equal")
ttl = int64(60)
now = time.Now().Unix()
claim = utils.BuildClaims(uid, platform, ttl)
// time difference within 1s
assert.Equal(t, claim.RegisteredClaims.ExpiresAt, int64(60)+now, "StandardClaims.ExpiresAt should be equal")
assert.Equal(t, claim.RegisteredClaims.IssuedAt, now, "StandardClaims.IssuedAt should be equal")
assert.Equal(t, claim.RegisteredClaims.NotBefore, now, "StandardClaims.NotBefore should be equal")
}
func Test_CreateToken(t *testing.T) {
uid := "1"
platform := int32(1)
now := time.Now().Unix()
tokenString, expiresAt, err := utils.CreateToken(uid, platform)
assert.NotEmpty(t, tokenString)
assert.Equal(t, expiresAt, 604800+now)
assert.Nil(t, err)
}
func Test_VerifyToken(t *testing.T) {
uid := "1"
platform := int32(1)
tokenString, _, _ := utils.CreateToken(uid, platform)
result := utils.VerifyToken(tokenString, uid)
assert.True(t, result)
result = utils.VerifyToken(tokenString, "2")
assert.False(t, result)
}
func Test_ParseRedisInterfaceToken(t *testing.T) {
uid := "1"
platform := int32(1)
tokenString, _, _ := utils.CreateToken(uid, platform)
claims, err := utils.ParseRedisInterfaceToken([]uint8(tokenString))
assert.Nil(t, err)
assert.Equal(t, claims.UID, uid)
// timeout
config.Config.TokenPolicy.AccessExpire = -80
tokenString, _, _ = utils.CreateToken(uid, platform)
claims, err = utils.ParseRedisInterfaceToken([]uint8(tokenString))
assert.Equal(t, err, utils.TokenExpired)
assert.Nil(t, claims)
}
func Test_ParseToken(t *testing.T) {
uid := "1"
platform := int32(1)
tokenString, _, _ := utils.CreateToken(uid, platform)
claims, err := utils.ParseToken(tokenString)
if err == nil {
assert.Equal(t, claims.UID, uid)
}
}
+16
View File
@@ -0,0 +1,16 @@
package utils
import (
"Open_IM/pkg/utils"
"testing"
"github.com/stretchr/testify/assert"
)
func Test_Md5(t *testing.T) {
result := utils.Md5("go")
assert.Equal(t, result, "34d1f91fb2e514b8576fab1a75a89a6b")
result2 := utils.Md5("go")
assert.Equal(t, result, result2)
}
@@ -0,0 +1,46 @@
package utils
import (
"Open_IM/pkg/utils"
"testing"
"github.com/stretchr/testify/assert"
)
func Test_PlatformIDToName(t *testing.T) {
assert.Equal(t, utils.PlatformIDToName(1), "IOS")
assert.Equal(t, utils.PlatformIDToName(2), "Android")
assert.Equal(t, utils.PlatformIDToName(3), "Windows")
assert.Equal(t, utils.PlatformIDToName(4), "OSX")
assert.Equal(t, utils.PlatformIDToName(5), "Web")
assert.Equal(t, utils.PlatformIDToName(6), "MiniWeb")
assert.Equal(t, utils.PlatformIDToName(7), "Linux")
assert.Equal(t, utils.PlatformIDToName(0), "")
}
func Test_PlatformNameToID(t *testing.T) {
assert.Equal(t, utils.PlatformNameToID("IOS"), int32(1))
assert.Equal(t, utils.PlatformNameToID("Android"), int32(2))
assert.Equal(t, utils.PlatformNameToID("Windows"), int32(3))
assert.Equal(t, utils.PlatformNameToID("OSX"), int32(4))
assert.Equal(t, utils.PlatformNameToID("Web"), int32(5))
assert.Equal(t, utils.PlatformNameToID("MiniWeb"), int32(6))
assert.Equal(t, utils.PlatformNameToID("Linux"), int32(7))
assert.Equal(t, utils.PlatformNameToID("UnknownDevice"), int32(0))
assert.Equal(t, utils.PlatformNameToID(""), int32(0))
}
func Test_PlatformNameToClass(t *testing.T) {
assert.Equal(t, utils.PlatformNameToClass("IOS"), "Mobile")
assert.Equal(t, utils.PlatformNameToClass("Android"), "Mobile")
assert.Equal(t, utils.PlatformNameToClass("OSX"), "PC")
assert.Equal(t, utils.PlatformNameToClass("Windows"), "PC")
assert.Equal(t, utils.PlatformNameToClass("Web"), "PC")
assert.Equal(t, utils.PlatformNameToClass("MiniWeb"), "Mobile")
assert.Equal(t, utils.PlatformNameToClass("Linux"), "PC")
assert.Equal(t, utils.PlatformNameToClass("UnknownDevice"), "")
assert.Equal(t, utils.PlatformNameToClass(""), "")
}