Feat: Refactor project's references to shared modules (#672)
* fix: to start im or chat, ZooKeeper must be started first. * fix: msg gateway start output err info Signed-off-by: Gordon <1432970085@qq.com> * fix: msg gateway start output err info Signed-off-by: Gordon <1432970085@qq.com> * chore: package path changes Signed-off-by: withchao <993506633@qq.com> * fix: go mod update Signed-off-by: Gordon <1432970085@qq.com> * fix: token update Signed-off-by: Gordon <1432970085@qq.com> * chore: package path changes Signed-off-by: withchao <993506633@qq.com> * chore: package path changes Signed-off-by: withchao <993506633@qq.com> * fix: token update Signed-off-by: Gordon <1432970085@qq.com> * fix: token update Signed-off-by: Gordon <1432970085@qq.com> * fix: token update Signed-off-by: Gordon <1432970085@qq.com> * fix: token update Signed-off-by: Gordon <1432970085@qq.com> * fix: token update Signed-off-by: Gordon <1432970085@qq.com> --------- Signed-off-by: Gordon <1432970085@qq.com> Signed-off-by: withchao <993506633@qq.com> Co-authored-by: withchao <993506633@qq.com>pull/678/head
parent
d7218dd5be
commit
5b85fa763a
@ -1,355 +0,0 @@
|
||||
// Copyright © 2023 OpenIM. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package tools
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
|
||||
"github.com/OpenIMSDK/Open-IM-Server/pkg/common/db/cache"
|
||||
"github.com/OpenIMSDK/tools/constant"
|
||||
"github.com/OpenIMSDK/tools/mcontext"
|
||||
"github.com/OpenIMSDK/tools/utils"
|
||||
|
||||
unRelationTb "github.com/OpenIMSDK/Open-IM-Server/pkg/common/db/table/unrelation"
|
||||
"github.com/OpenIMSDK/Open-IM-Server/pkg/common/db/unrelation"
|
||||
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func GenMsgDoc(startSeq, stopSeq, delSeq, index int64, conversationID string) *unRelationTb.MsgDocModel {
|
||||
msgDoc := &unRelationTb.MsgDocModel{DocID: conversationID + strconv.Itoa(int(index))}
|
||||
for i := 0; i < 5000; i++ {
|
||||
msgDoc.Msg = append(msgDoc.Msg, &unRelationTb.MsgInfoModel{})
|
||||
}
|
||||
for i := startSeq; i <= stopSeq; i++ {
|
||||
msg := &unRelationTb.MsgDataModel{
|
||||
SendID: "sendID1",
|
||||
RecvID: "recvID1",
|
||||
GroupID: "",
|
||||
ClientMsgID: "xxx",
|
||||
ServerMsgID: "xxx",
|
||||
SenderPlatformID: 1,
|
||||
SenderNickname: "testNickName",
|
||||
SenderFaceURL: "testFaceURL",
|
||||
SessionType: 1,
|
||||
MsgFrom: 100,
|
||||
ContentType: 101,
|
||||
Content: "testContent",
|
||||
Seq: i,
|
||||
CreateTime: time.Now().Unix(),
|
||||
Status: 1,
|
||||
}
|
||||
if i <= delSeq {
|
||||
msg.SendTime = 10000
|
||||
} else {
|
||||
msg.SendTime = utils.GetCurrentTimestampByMill()
|
||||
}
|
||||
msgDoc.Msg[i-1] = &unRelationTb.MsgInfoModel{Msg: msg}
|
||||
}
|
||||
return msgDoc
|
||||
}
|
||||
|
||||
func TestDeleteMongoMsgAndResetRedisSeq(t *testing.T) {
|
||||
operationID := "test"
|
||||
rdb, err := cache.NewRedis()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
mgo, err := unrelation.NewMongo()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
cacheModel := cache.NewMsgCacheModel(rdb)
|
||||
mongoClient := mgo.GetDatabase().Collection(unRelationTb.MsgDocModel{}.TableName())
|
||||
ctx := context.Background()
|
||||
ctx = mcontext.SetOperationID(ctx, operationID)
|
||||
|
||||
testUID1 := "test_del_id1"
|
||||
var conversationID string
|
||||
conversationID = utils.GetConversationIDBySessionType(constant.SuperGroupChatType, testUID1)
|
||||
_, err = mongoClient.DeleteOne(ctx, bson.M{"doc_id": conversationID + ":" + strconv.Itoa(0)})
|
||||
if err != nil {
|
||||
t.Error("DeleteOne failed")
|
||||
return
|
||||
}
|
||||
|
||||
err = cacheModel.SetMaxSeq(ctx, conversationID, 600)
|
||||
if err != nil {
|
||||
t.Error("SetUserMaxSeq failed")
|
||||
}
|
||||
msgDoc := GenMsgDoc(1, 600, 200, 0, conversationID)
|
||||
if _, err := mongoClient.InsertOne(ctx, msgDoc); err != nil {
|
||||
t.Error("InsertOne failed", conversationID)
|
||||
}
|
||||
|
||||
msgTools, err := InitMsgTool()
|
||||
if err != nil {
|
||||
t.Error("init failed")
|
||||
return
|
||||
}
|
||||
msgTools.ClearConversationsMsg(ctx, []string{conversationID})
|
||||
minSeqMongo, maxSeqMongo, minSeqCache, maxSeqCache, err := msgTools.msgDatabase.GetConversationMinMaxSeqInMongoAndCache(
|
||||
ctx,
|
||||
conversationID,
|
||||
)
|
||||
if err != nil {
|
||||
t.Error("GetSuperGroupMinMaxSeqInMongoAndCache failed")
|
||||
return
|
||||
}
|
||||
if maxSeqCache != maxSeqMongo {
|
||||
t.Error("checkMaxSeqWithMongo failed", conversationID)
|
||||
}
|
||||
if minSeqMongo != minSeqCache {
|
||||
t.Error("minSeqMongo != minSeqCache", minSeqMongo, minSeqCache)
|
||||
}
|
||||
if minSeqCache != 201 {
|
||||
t.Error("test1 is not the same", "minSeq:", minSeqCache, "targetSeq", 201)
|
||||
}
|
||||
|
||||
/////// uid2
|
||||
|
||||
testUID2 := "test_del_id2"
|
||||
conversationID = utils.GetConversationIDBySessionType(constant.SuperGroupChatType, testUID2)
|
||||
|
||||
_, err = mongoClient.DeleteOne(ctx, bson.M{"uid": conversationID + ":" + strconv.Itoa(0)})
|
||||
if err != nil {
|
||||
t.Error("delete failed")
|
||||
}
|
||||
_, err = mongoClient.DeleteOne(ctx, bson.M{"uid": conversationID + ":" + strconv.Itoa(1)})
|
||||
if err != nil {
|
||||
t.Error("delete failed")
|
||||
}
|
||||
|
||||
err = cacheModel.SetMaxSeq(ctx, conversationID, 7000)
|
||||
if err != nil {
|
||||
t.Error("SetUserMaxSeq failed")
|
||||
}
|
||||
msgDoc = GenMsgDoc(1, 4999, 5000, 0, conversationID)
|
||||
msgDoc2 := GenMsgDoc(5000, 7000, 6000, 1, conversationID)
|
||||
if _, err := mongoClient.InsertOne(ctx, msgDoc); err != nil {
|
||||
t.Error("InsertOne failed", testUID1)
|
||||
}
|
||||
if _, err := mongoClient.InsertOne(ctx, msgDoc2); err != nil {
|
||||
t.Error("InsertOne failed", testUID1)
|
||||
}
|
||||
|
||||
msgTools.ClearConversationsMsg(ctx, []string{conversationID})
|
||||
minSeqMongo, maxSeqMongo, minSeqCache, maxSeqCache, err = msgTools.msgDatabase.GetConversationMinMaxSeqInMongoAndCache(
|
||||
ctx,
|
||||
conversationID,
|
||||
)
|
||||
if err != nil {
|
||||
t.Error("GetSuperGroupMinMaxSeqInMongoAndCache failed")
|
||||
return
|
||||
}
|
||||
if maxSeqCache != maxSeqMongo {
|
||||
t.Error("checkMaxSeqWithMongo failed", conversationID)
|
||||
}
|
||||
if minSeqMongo != minSeqCache {
|
||||
t.Error("minSeqMongo != minSeqCache", minSeqMongo, minSeqCache)
|
||||
}
|
||||
if minSeqCache != 6001 {
|
||||
t.Error("test1 is not the same", "minSeq:", minSeqCache, "targetSeq", 201)
|
||||
}
|
||||
|
||||
/////// uid3
|
||||
testUID3 := "test_del_id3"
|
||||
conversationID = utils.GetConversationIDBySessionType(constant.SuperGroupChatType, testUID3)
|
||||
_, err = mongoClient.DeleteOne(ctx, bson.M{"uid": conversationID + ":" + strconv.Itoa(0)})
|
||||
if err != nil {
|
||||
t.Error("delete failed")
|
||||
}
|
||||
err = cacheModel.SetMaxSeq(ctx, conversationID, 4999)
|
||||
if err != nil {
|
||||
t.Error("SetUserMaxSeq failed")
|
||||
}
|
||||
msgDoc = GenMsgDoc(1, 4999, 5000, 0, conversationID)
|
||||
if _, err := mongoClient.InsertOne(ctx, msgDoc); err != nil {
|
||||
t.Error("InsertOne failed", conversationID)
|
||||
}
|
||||
|
||||
msgTools.ClearConversationsMsg(ctx, []string{conversationID})
|
||||
minSeqMongo, maxSeqMongo, minSeqCache, maxSeqCache, err = msgTools.msgDatabase.GetConversationMinMaxSeqInMongoAndCache(
|
||||
ctx,
|
||||
conversationID,
|
||||
)
|
||||
if err != nil {
|
||||
t.Error("GetSuperGroupMinMaxSeqInMongoAndCache failed")
|
||||
return
|
||||
}
|
||||
if maxSeqCache != maxSeqMongo {
|
||||
t.Error("checkMaxSeqWithMongo failed", conversationID)
|
||||
}
|
||||
if minSeqMongo != minSeqCache {
|
||||
t.Error("minSeqMongo != minSeqCache", minSeqMongo, minSeqCache)
|
||||
}
|
||||
if minSeqCache != 5000 {
|
||||
t.Error("test1 is not the same", "minSeq:", minSeqCache, "targetSeq", 201)
|
||||
}
|
||||
|
||||
//// uid4
|
||||
testUID4 := "test_del_id4"
|
||||
conversationID = utils.GetConversationIDBySessionType(constant.SuperGroupChatType, testUID4)
|
||||
_, err = mongoClient.DeleteOne(ctx, bson.M{"uid": conversationID + ":" + strconv.Itoa(0)})
|
||||
if err != nil {
|
||||
t.Error("delete failed")
|
||||
}
|
||||
_, err = mongoClient.DeleteOne(ctx, bson.M{"uid": conversationID + ":" + strconv.Itoa(1)})
|
||||
if err != nil {
|
||||
t.Error("delete failed")
|
||||
}
|
||||
_, err = mongoClient.DeleteOne(ctx, bson.M{"uid": conversationID + ":" + strconv.Itoa(2)})
|
||||
if err != nil {
|
||||
t.Error("delete failed")
|
||||
}
|
||||
|
||||
err = cacheModel.SetMaxSeq(ctx, conversationID, 12000)
|
||||
msgDoc = GenMsgDoc(1, 4999, 5000, 0, conversationID)
|
||||
msgDoc2 = GenMsgDoc(5000, 9999, 10000, 1, conversationID)
|
||||
msgDoc3 := GenMsgDoc(10000, 12000, 11000, 2, conversationID)
|
||||
if _, err := mongoClient.InsertOne(ctx, msgDoc); err != nil {
|
||||
t.Error("InsertOne failed", conversationID)
|
||||
}
|
||||
if _, err := mongoClient.InsertOne(ctx, msgDoc2); err != nil {
|
||||
t.Error("InsertOne failed", conversationID)
|
||||
}
|
||||
if _, err := mongoClient.InsertOne(ctx, msgDoc3); err != nil {
|
||||
t.Error("InsertOne failed", conversationID)
|
||||
}
|
||||
|
||||
msgTools.ClearConversationsMsg(ctx, []string{conversationID})
|
||||
if err != nil {
|
||||
t.Error("GetSuperGroupMinMaxSeqInMongoAndCache failed")
|
||||
return
|
||||
}
|
||||
minSeqMongo, maxSeqMongo, minSeqCache, maxSeqCache, err = msgTools.msgDatabase.GetConversationMinMaxSeqInMongoAndCache(
|
||||
ctx,
|
||||
conversationID,
|
||||
)
|
||||
if err != nil {
|
||||
t.Error("GetSuperGroupMinMaxSeqInMongoAndCache failed")
|
||||
return
|
||||
}
|
||||
if maxSeqCache != maxSeqMongo {
|
||||
t.Error("checkMaxSeqWithMongo failed", conversationID)
|
||||
}
|
||||
if minSeqMongo != minSeqCache {
|
||||
t.Error("minSeqMongo != minSeqCache", minSeqMongo, minSeqCache)
|
||||
}
|
||||
if minSeqCache != 5000 {
|
||||
t.Error("test1 is not the same", "minSeq:", minSeqCache)
|
||||
}
|
||||
|
||||
testUID5 := "test_del_id5"
|
||||
conversationID = utils.GetConversationIDBySessionType(constant.SuperGroupChatType, testUID5)
|
||||
|
||||
_, err = mongoClient.DeleteOne(ctx, bson.M{"uid": conversationID + ":" + strconv.Itoa(0)})
|
||||
if err != nil {
|
||||
t.Error("delete failed")
|
||||
}
|
||||
_, err = mongoClient.DeleteOne(ctx, bson.M{"uid": conversationID + ":" + strconv.Itoa(1)})
|
||||
if err != nil {
|
||||
t.Error("delete failed")
|
||||
}
|
||||
err = cacheModel.SetMaxSeq(ctx, conversationID, 9999)
|
||||
msgDoc = GenMsgDoc(1, 4999, 5000, 0, conversationID)
|
||||
msgDoc2 = GenMsgDoc(5000, 9999, 10000, 1, conversationID)
|
||||
if _, err := mongoClient.InsertOne(ctx, msgDoc); err != nil {
|
||||
t.Error("InsertOne failed", conversationID)
|
||||
}
|
||||
if _, err := mongoClient.InsertOne(ctx, msgDoc2); err != nil {
|
||||
t.Error("InsertOne failed", conversationID)
|
||||
}
|
||||
|
||||
msgTools.ClearConversationsMsg(ctx, []string{conversationID})
|
||||
if err != nil {
|
||||
t.Error("GetSuperGroupMinMaxSeqInMongoAndCache failed")
|
||||
return
|
||||
}
|
||||
minSeqMongo, maxSeqMongo, minSeqCache, maxSeqCache, err = msgTools.msgDatabase.GetConversationMinMaxSeqInMongoAndCache(
|
||||
ctx,
|
||||
conversationID,
|
||||
)
|
||||
if err != nil {
|
||||
t.Error("GetSuperGroupMinMaxSeqInMongoAndCache failed")
|
||||
return
|
||||
}
|
||||
if maxSeqCache != maxSeqMongo {
|
||||
t.Error("checkMaxSeqWithMongo failed", conversationID)
|
||||
}
|
||||
if minSeqMongo != minSeqCache {
|
||||
t.Error("minSeqMongo != minSeqCache", minSeqMongo, minSeqCache)
|
||||
}
|
||||
if minSeqCache != 10000 {
|
||||
t.Error("test1 is not the same", "minSeq:", minSeqCache)
|
||||
}
|
||||
|
||||
testUID6 := "test_del_id6"
|
||||
conversationID = utils.GetConversationIDBySessionType(constant.SuperGroupChatType, testUID6)
|
||||
|
||||
_, err = mongoClient.DeleteOne(ctx, bson.M{"uid": conversationID + ":" + strconv.Itoa(0)})
|
||||
if err != nil {
|
||||
t.Error("delete failed")
|
||||
}
|
||||
_, err = mongoClient.DeleteOne(ctx, bson.M{"uid": conversationID + ":" + strconv.Itoa(1)})
|
||||
if err != nil {
|
||||
t.Error("delete failed")
|
||||
}
|
||||
_, err = mongoClient.DeleteOne(ctx, bson.M{"uid": conversationID + ":" + strconv.Itoa(2)})
|
||||
if err != nil {
|
||||
t.Error("delete failed")
|
||||
}
|
||||
_, err = mongoClient.DeleteOne(ctx, bson.M{"uid": conversationID + ":" + strconv.Itoa(3)})
|
||||
if err != nil {
|
||||
t.Error("delete failed")
|
||||
}
|
||||
msgDoc = GenMsgDoc(1, 4999, 5000, 0, conversationID)
|
||||
msgDoc2 = GenMsgDoc(5000, 9999, 10000, 1, conversationID)
|
||||
msgDoc3 = GenMsgDoc(10000, 14999, 13000, 2, conversationID)
|
||||
msgDoc4 := GenMsgDoc(15000, 19999, 0, 3, conversationID)
|
||||
if _, err := mongoClient.InsertOne(ctx, msgDoc); err != nil {
|
||||
t.Error("InsertOne failed", testUID4)
|
||||
}
|
||||
if _, err := mongoClient.InsertOne(ctx, msgDoc2); err != nil {
|
||||
t.Error("InsertOne failed", testUID4)
|
||||
}
|
||||
if _, err := mongoClient.InsertOne(ctx, msgDoc3); err != nil {
|
||||
t.Error("InsertOne failed", testUID4)
|
||||
}
|
||||
if _, err := mongoClient.InsertOne(ctx, msgDoc4); err != nil {
|
||||
t.Error("InsertOne failed", testUID4)
|
||||
}
|
||||
minSeqMongo, maxSeqMongo, minSeqCache, maxSeqCache, err = msgTools.msgDatabase.GetConversationMinMaxSeqInMongoAndCache(
|
||||
ctx,
|
||||
conversationID,
|
||||
)
|
||||
if err != nil {
|
||||
t.Error("GetSuperGroupMinMaxSeqInMongoAndCache failed")
|
||||
return
|
||||
}
|
||||
if maxSeqCache != maxSeqMongo {
|
||||
t.Error("checkMaxSeqWithMongo failed", conversationID)
|
||||
}
|
||||
if minSeqMongo != minSeqCache {
|
||||
t.Error("minSeqMongo != minSeqCache", minSeqMongo, minSeqCache)
|
||||
}
|
||||
if minSeqCache != 13001 {
|
||||
t.Error("test1 is not the same", "minSeq:", minSeqCache)
|
||||
}
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
package authverify
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/OpenIMSDK/Open-IM-Server/pkg/common/config"
|
||||
"github.com/OpenIMSDK/tools/errs"
|
||||
"github.com/OpenIMSDK/tools/mcontext"
|
||||
"github.com/OpenIMSDK/tools/tokenverify"
|
||||
"github.com/OpenIMSDK/tools/utils"
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
)
|
||||
|
||||
func Secret() jwt.Keyfunc {
|
||||
return func(token *jwt.Token) (interface{}, error) {
|
||||
return []byte(config.Config.Secret), nil
|
||||
}
|
||||
}
|
||||
|
||||
func CheckAccessV3(ctx context.Context, ownerUserID string) (err error) {
|
||||
opUserID := mcontext.GetOpUserID(ctx)
|
||||
if utils.IsContain(opUserID, config.Config.Manager.UserID) {
|
||||
return nil
|
||||
}
|
||||
if opUserID == ownerUserID {
|
||||
return nil
|
||||
}
|
||||
return errs.ErrNoPermission.Wrap(utils.GetSelfFuncName())
|
||||
}
|
||||
|
||||
func IsAppManagerUid(ctx context.Context) bool {
|
||||
return utils.IsContain(mcontext.GetOpUserID(ctx), config.Config.Manager.UserID)
|
||||
}
|
||||
|
||||
func CheckAdmin(ctx context.Context) error {
|
||||
if utils.IsContain(mcontext.GetOpUserID(ctx), config.Config.Manager.UserID) {
|
||||
return nil
|
||||
}
|
||||
return errs.ErrNoPermission.Wrap(fmt.Sprintf("user %s is not admin userID", mcontext.GetOpUserID(ctx)))
|
||||
}
|
||||
|
||||
func ParseRedisInterfaceToken(redisToken interface{}) (*tokenverify.Claims, error) {
|
||||
return tokenverify.GetClaimFromToken(string(redisToken.([]uint8)), Secret())
|
||||
}
|
||||
|
||||
func IsManagerUserID(opUserID string) bool {
|
||||
return utils.IsContain(opUserID, config.Config.Manager.UserID)
|
||||
}
|
||||
|
||||
func WsVerifyToken(token, userID string, platformID int) error {
|
||||
claim, err := tokenverify.GetClaimFromToken(token, Secret())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if claim.UserID != userID {
|
||||
return errs.ErrTokenInvalid.Wrap(fmt.Sprintf("token uid %s != userID %s", claim.UserID, userID))
|
||||
}
|
||||
if claim.PlatformID != platformID {
|
||||
return errs.ErrTokenInvalid.Wrap(fmt.Sprintf("token platform %d != %d", claim.PlatformID, platformID))
|
||||
}
|
||||
return nil
|
||||
}
|
@ -0,0 +1,333 @@
|
||||
// Copyright © 2023 OpenIM. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"github.com/OpenIMSDK/tools/discoveryregistry"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
var Config configStruct
|
||||
|
||||
const ConfKey = "conf"
|
||||
|
||||
type CallBackConfig struct {
|
||||
Enable bool `yaml:"enable"`
|
||||
CallbackTimeOut int `yaml:"timeout"`
|
||||
CallbackFailedContinue *bool `yaml:"failedContinue"`
|
||||
}
|
||||
|
||||
type NotificationConf struct {
|
||||
IsSendMsg bool `yaml:"isSendMsg"`
|
||||
ReliabilityLevel int `yaml:"reliabilityLevel"` // 1 online 2 persistent
|
||||
UnreadCount bool `yaml:"unreadCount"`
|
||||
OfflinePush POfflinePush `yaml:"offlinePush"`
|
||||
}
|
||||
|
||||
type POfflinePush struct {
|
||||
Enable bool `yaml:"enable"`
|
||||
Title string `yaml:"title"`
|
||||
Desc string `yaml:"desc"`
|
||||
Ext string `yaml:"ext"`
|
||||
}
|
||||
|
||||
type configStruct struct {
|
||||
Zookeeper struct {
|
||||
Schema string `yaml:"schema"`
|
||||
ZkAddr []string `yaml:"address"`
|
||||
Username string `yaml:"username"`
|
||||
Password string `yaml:"password"`
|
||||
} `yaml:"zookeeper"`
|
||||
|
||||
Mysql struct {
|
||||
Address []string `yaml:"address"`
|
||||
Username string `yaml:"username"`
|
||||
Password string `yaml:"password"`
|
||||
Database string `yaml:"database"`
|
||||
MaxOpenConn int `yaml:"maxOpenConn"`
|
||||
MaxIdleConn int `yaml:"maxIdleConn"`
|
||||
MaxLifeTime int `yaml:"maxLifeTime"`
|
||||
LogLevel int `yaml:"logLevel"`
|
||||
SlowThreshold int `yaml:"slowThreshold"`
|
||||
} `yaml:"mysql"`
|
||||
|
||||
Mongo struct {
|
||||
Uri string `yaml:"uri"`
|
||||
Address []string `yaml:"address"`
|
||||
Database string `yaml:"database"`
|
||||
Username string `yaml:"username"`
|
||||
Password string `yaml:"password"`
|
||||
MaxPoolSize int `yaml:"maxPoolSize"`
|
||||
} `yaml:"mongo"`
|
||||
|
||||
Redis struct {
|
||||
Address []string `yaml:"address"`
|
||||
Username string `yaml:"username"`
|
||||
Password string `yaml:"password"`
|
||||
} `yaml:"redis"`
|
||||
|
||||
Kafka struct {
|
||||
Username string `yaml:"username"`
|
||||
Password string `yaml:"password"`
|
||||
Addr []string `yaml:"addr"`
|
||||
LatestMsgToRedis struct {
|
||||
Topic string `yaml:"topic"`
|
||||
} `yaml:"latestMsgToRedis"`
|
||||
MsgToMongo struct {
|
||||
Topic string `yaml:"topic"`
|
||||
} `yaml:"offlineMsgToMongo"`
|
||||
MsgToPush struct {
|
||||
Topic string `yaml:"topic"`
|
||||
} `yaml:"msgToPush"`
|
||||
ConsumerGroupID struct {
|
||||
MsgToRedis string `yaml:"msgToRedis"`
|
||||
MsgToMongo string `yaml:"msgToMongo"`
|
||||
MsgToMySql string `yaml:"msgToMySql"`
|
||||
MsgToPush string `yaml:"msgToPush"`
|
||||
} `yaml:"consumerGroupID"`
|
||||
} `yaml:"kafka"`
|
||||
|
||||
Rpc struct {
|
||||
RegisterIP string `yaml:"registerIP"`
|
||||
ListenIP string `yaml:"listenIP"`
|
||||
} `yaml:"rpc"`
|
||||
|
||||
Api struct {
|
||||
OpenImApiPort []int `yaml:"openImApiPort"`
|
||||
ListenIP string `yaml:"listenIP"`
|
||||
} `yaml:"api"`
|
||||
|
||||
Object struct {
|
||||
Enable string `yaml:"enable"`
|
||||
ApiURL string `yaml:"apiURL"`
|
||||
Minio struct {
|
||||
Bucket string `yaml:"bucket"`
|
||||
Endpoint string `yaml:"endpoint"`
|
||||
AccessKeyID string `yaml:"accessKeyID"`
|
||||
SecretAccessKey string `yaml:"secretAccessKey"`
|
||||
SessionToken string `yaml:"sessionToken"`
|
||||
} `yaml:"minio"`
|
||||
Cos struct {
|
||||
BucketURL string `yaml:"bucketURL"`
|
||||
SecretID string `yaml:"secretID"`
|
||||
SecretKey string `yaml:"secretKey"`
|
||||
SessionToken string `yaml:"sessionToken"`
|
||||
} `yaml:"cos"`
|
||||
Oss struct {
|
||||
Endpoint string `yaml:"endpoint"`
|
||||
Bucket string `yaml:"bucket"`
|
||||
BucketURL string `yaml:"bucketURL"`
|
||||
AccessKeyID string `yaml:"accessKeyID"`
|
||||
AccessKeySecret string `yaml:"accessKeySecret"`
|
||||
SessionToken string `yaml:"sessionToken"`
|
||||
} `yaml:"oss"`
|
||||
} `yaml:"object"`
|
||||
|
||||
RpcPort struct {
|
||||
OpenImUserPort []int `yaml:"openImUserPort"`
|
||||
OpenImFriendPort []int `yaml:"openImFriendPort"`
|
||||
OpenImMessagePort []int `yaml:"openImMessagePort"`
|
||||
OpenImMessageGatewayPort []int `yaml:"openImMessageGatewayPort"`
|
||||
OpenImGroupPort []int `yaml:"openImGroupPort"`
|
||||
OpenImAuthPort []int `yaml:"openImAuthPort"`
|
||||
OpenImPushPort []int `yaml:"openImPushPort"`
|
||||
OpenImConversationPort []int `yaml:"openImConversationPort"`
|
||||
OpenImRtcPort []int `yaml:"openImRtcPort"`
|
||||
OpenImThirdPort []int `yaml:"openImThirdPort"`
|
||||
} `yaml:"rpcPort"`
|
||||
|
||||
RpcRegisterName struct {
|
||||
OpenImUserName string `yaml:"openImUserName"`
|
||||
OpenImFriendName string `yaml:"openImFriendName"`
|
||||
OpenImMsgName string `yaml:"openImMsgName"`
|
||||
OpenImPushName string `yaml:"openImPushName"`
|
||||
OpenImMessageGatewayName string `yaml:"openImMessageGatewayName"`
|
||||
OpenImGroupName string `yaml:"openImGroupName"`
|
||||
OpenImAuthName string `yaml:"openImAuthName"`
|
||||
OpenImConversationName string `yaml:"openImConversationName"`
|
||||
OpenImThirdName string `yaml:"openImThirdName"`
|
||||
} `yaml:"rpcRegisterName"`
|
||||
|
||||
Log struct {
|
||||
StorageLocation string `yaml:"storageLocation"`
|
||||
RotationTime uint `yaml:"rotationTime"`
|
||||
RemainRotationCount uint `yaml:"remainRotationCount"`
|
||||
RemainLogLevel int `yaml:"remainLogLevel"`
|
||||
IsStdout bool `yaml:"isStdout"`
|
||||
IsJson bool `yaml:"isJson"`
|
||||
WithStack bool `yaml:"withStack"`
|
||||
} `yaml:"log"`
|
||||
|
||||
LongConnSvr struct {
|
||||
OpenImWsPort []int `yaml:"openImWsPort"`
|
||||
WebsocketMaxConnNum int `yaml:"websocketMaxConnNum"`
|
||||
WebsocketMaxMsgLen int `yaml:"websocketMaxMsgLen"`
|
||||
WebsocketTimeout int `yaml:"websocketTimeout"`
|
||||
} `yaml:"longConnSvr"`
|
||||
|
||||
Push struct {
|
||||
Enable string `yaml:"enable"`
|
||||
GeTui struct {
|
||||
PushUrl string `yaml:"pushUrl"`
|
||||
AppKey string `yaml:"appKey"`
|
||||
Intent string `yaml:"intent"`
|
||||
MasterSecret string `yaml:"masterSecret"`
|
||||
ChannelID string `yaml:"channelID"`
|
||||
ChannelName string `yaml:"channelName"`
|
||||
} `yaml:"geTui"`
|
||||
Fcm struct {
|
||||
ServiceAccount string `yaml:"serviceAccount"`
|
||||
} `yaml:"fcm"`
|
||||
Jpns struct {
|
||||
AppKey string `yaml:"appKey"`
|
||||
MasterSecret string `yaml:"masterSecret"`
|
||||
PushUrl string `yaml:"pushUrl"`
|
||||
PushIntent string `yaml:"pushIntent"`
|
||||
} `yaml:"jpns"`
|
||||
}
|
||||
Manager struct {
|
||||
UserID []string `yaml:"userID"`
|
||||
Nickname []string `yaml:"nickname"`
|
||||
} `yaml:"manager"`
|
||||
|
||||
MultiLoginPolicy int `yaml:"multiLoginPolicy"`
|
||||
ChatPersistenceMysql bool `yaml:"chatPersistenceMysql"`
|
||||
MsgCacheTimeout int `yaml:"msgCacheTimeout"`
|
||||
GroupMessageHasReadReceiptEnable bool `yaml:"groupMessageHasReadReceiptEnable"`
|
||||
SingleMessageHasReadReceiptEnable bool `yaml:"singleMessageHasReadReceiptEnable"`
|
||||
RetainChatRecords int `yaml:"retainChatRecords"`
|
||||
ChatRecordsClearTime string `yaml:"chatRecordsClearTime"`
|
||||
MsgDestructTime string `yaml:"msgDestructTime"`
|
||||
Secret string `yaml:"secret"`
|
||||
TokenPolicy struct {
|
||||
Expire int64 `yaml:"expire"`
|
||||
} `yaml:"tokenPolicy"`
|
||||
MessageVerify struct {
|
||||
FriendVerify *bool `yaml:"friendVerify"`
|
||||
} `yaml:"messageVerify"`
|
||||
|
||||
IOSPush struct {
|
||||
PushSound string `yaml:"pushSound"`
|
||||
BadgeCount bool `yaml:"badgeCount"`
|
||||
Production bool `yaml:"production"`
|
||||
} `yaml:"iosPush"`
|
||||
Callback struct {
|
||||
CallbackUrl string `yaml:"url"`
|
||||
CallbackBeforeSendSingleMsg CallBackConfig `yaml:"beforeSendSingleMsg"`
|
||||
CallbackAfterSendSingleMsg CallBackConfig `yaml:"afterSendSingleMsg"`
|
||||
CallbackBeforeSendGroupMsg CallBackConfig `yaml:"beforeSendGroupMsg"`
|
||||
CallbackAfterSendGroupMsg CallBackConfig `yaml:"afterSendGroupMsg"`
|
||||
CallbackMsgModify CallBackConfig `yaml:"msgModify"`
|
||||
CallbackUserOnline CallBackConfig `yaml:"userOnline"`
|
||||
CallbackUserOffline CallBackConfig `yaml:"userOffline"`
|
||||
CallbackUserKickOff CallBackConfig `yaml:"userKickOff"`
|
||||
CallbackOfflinePush CallBackConfig `yaml:"offlinePush"`
|
||||
CallbackOnlinePush CallBackConfig `yaml:"onlinePush"`
|
||||
CallbackBeforeSuperGroupOnlinePush CallBackConfig `yaml:"superGroupOnlinePush"`
|
||||
CallbackBeforeAddFriend CallBackConfig `yaml:"beforeAddFriend"`
|
||||
CallbackBeforeCreateGroup CallBackConfig `yaml:"beforeCreateGroup"`
|
||||
CallbackBeforeMemberJoinGroup CallBackConfig `yaml:"beforeMemberJoinGroup"`
|
||||
CallbackBeforeSetGroupMemberInfo CallBackConfig `yaml:"beforeSetGroupMemberInfo"`
|
||||
} `yaml:"callback"`
|
||||
|
||||
Prometheus struct {
|
||||
Enable bool `yaml:"enable"`
|
||||
UserPrometheusPort []int `yaml:"userPrometheusPort"`
|
||||
FriendPrometheusPort []int `yaml:"friendPrometheusPort"`
|
||||
MessagePrometheusPort []int `yaml:"messagePrometheusPort"`
|
||||
MessageGatewayPrometheusPort []int `yaml:"messageGatewayPrometheusPort"`
|
||||
GroupPrometheusPort []int `yaml:"groupPrometheusPort"`
|
||||
AuthPrometheusPort []int `yaml:"authPrometheusPort"`
|
||||
PushPrometheusPort []int `yaml:"pushPrometheusPort"`
|
||||
ConversationPrometheusPort []int `yaml:"conversationPrometheusPort"`
|
||||
RtcPrometheusPort []int `yaml:"rtcPrometheusPort"`
|
||||
MessageTransferPrometheusPort []int `yaml:"messageTransferPrometheusPort"`
|
||||
ThirdPrometheusPort []int `yaml:"thirdPrometheusPort"`
|
||||
} `yaml:"prometheus"`
|
||||
Notification notification `yaml:"notification"`
|
||||
}
|
||||
|
||||
type notification struct {
|
||||
GroupCreated NotificationConf `yaml:"groupCreated"`
|
||||
GroupInfoSet NotificationConf `yaml:"groupInfoSet"`
|
||||
JoinGroupApplication NotificationConf `yaml:"joinGroupApplication"`
|
||||
MemberQuit NotificationConf `yaml:"memberQuit"`
|
||||
GroupApplicationAccepted NotificationConf `yaml:"groupApplicationAccepted"`
|
||||
GroupApplicationRejected NotificationConf `yaml:"groupApplicationRejected"`
|
||||
GroupOwnerTransferred NotificationConf `yaml:"groupOwnerTransferred"`
|
||||
MemberKicked NotificationConf `yaml:"memberKicked"`
|
||||
MemberInvited NotificationConf `yaml:"memberInvited"`
|
||||
MemberEnter NotificationConf `yaml:"memberEnter"`
|
||||
GroupDismissed NotificationConf `yaml:"groupDismissed"`
|
||||
GroupMuted NotificationConf `yaml:"groupMuted"`
|
||||
GroupCancelMuted NotificationConf `yaml:"groupCancelMuted"`
|
||||
GroupMemberMuted NotificationConf `yaml:"groupMemberMuted"`
|
||||
GroupMemberCancelMuted NotificationConf `yaml:"groupMemberCancelMuted"`
|
||||
GroupMemberInfoSet NotificationConf `yaml:"groupMemberInfoSet"`
|
||||
GroupMemberSetToAdmin NotificationConf `yaml:"groupMemberSetToAdmin"`
|
||||
GroupMemberSetToOrdinary NotificationConf `yaml:"groupMemberSetToOrdinaryUser"`
|
||||
GroupInfoSetAnnouncement NotificationConf `yaml:"groupInfoSetAnnouncement"`
|
||||
GroupInfoSetName NotificationConf `yaml:"groupInfoSetName"`
|
||||
////////////////////////user///////////////////////
|
||||
UserInfoUpdated NotificationConf `yaml:"userInfoUpdated"`
|
||||
//////////////////////friend///////////////////////
|
||||
FriendApplicationAdded NotificationConf `yaml:"friendApplicationAdded"`
|
||||
FriendApplicationApproved NotificationConf `yaml:"friendApplicationApproved"`
|
||||
FriendApplicationRejected NotificationConf `yaml:"friendApplicationRejected"`
|
||||
FriendAdded NotificationConf `yaml:"friendAdded"`
|
||||
FriendDeleted NotificationConf `yaml:"friendDeleted"`
|
||||
FriendRemarkSet NotificationConf `yaml:"friendRemarkSet"`
|
||||
BlackAdded NotificationConf `yaml:"blackAdded"`
|
||||
BlackDeleted NotificationConf `yaml:"blackDeleted"`
|
||||
FriendInfoUpdated NotificationConf `yaml:"friendInfoUpdated"`
|
||||
//////////////////////conversation///////////////////////
|
||||
ConversationChanged NotificationConf `yaml:"conversationChanged"`
|
||||
ConversationSetPrivate NotificationConf `yaml:"conversationSetPrivate"`
|
||||
}
|
||||
|
||||
func (c *configStruct) GetServiceNames() []string {
|
||||
return []string{
|
||||
c.RpcRegisterName.OpenImUserName,
|
||||
c.RpcRegisterName.OpenImFriendName,
|
||||
c.RpcRegisterName.OpenImMsgName,
|
||||
c.RpcRegisterName.OpenImPushName,
|
||||
c.RpcRegisterName.OpenImMessageGatewayName,
|
||||
c.RpcRegisterName.OpenImGroupName,
|
||||
c.RpcRegisterName.OpenImAuthName,
|
||||
c.RpcRegisterName.OpenImConversationName,
|
||||
c.RpcRegisterName.OpenImThirdName,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *configStruct) RegisterConf2Registry(registry discoveryregistry.SvcDiscoveryRegistry) error {
|
||||
data, err := yaml.Marshal(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return registry.RegisterConf2Registry(ConfKey, data)
|
||||
}
|
||||
|
||||
func (c *configStruct) GetConfFromRegistry(registry discoveryregistry.SvcDiscoveryRegistry) ([]byte, error) {
|
||||
return registry.GetConfFromRegistry(ConfKey)
|
||||
}
|
||||
|
||||
func (c *configStruct) EncodeConfig() []byte {
|
||||
buf := bytes.NewBuffer(nil)
|
||||
if err := yaml.NewEncoder(buf).Encode(c); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return buf.Bytes()
|
||||
}
|
@ -0,0 +1,112 @@
|
||||
// Copyright © 2023 OpenIM. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package startrpc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/OpenIMSDK/Open-IM-Server/pkg/common/config"
|
||||
"net"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
grpcPrometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
|
||||
"github.com/OpenIMSDK/tools/discoveryregistry"
|
||||
"github.com/OpenIMSDK/tools/discoveryregistry/zookeeper"
|
||||
"github.com/OpenIMSDK/tools/log"
|
||||
"github.com/OpenIMSDK/tools/mw"
|
||||
"github.com/OpenIMSDK/tools/network"
|
||||
"github.com/OpenIMSDK/tools/prome"
|
||||
"github.com/OpenIMSDK/tools/utils"
|
||||
)
|
||||
|
||||
func Start(
|
||||
rpcPort int,
|
||||
rpcRegisterName string,
|
||||
prometheusPort int,
|
||||
rpcFn func(client discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) error,
|
||||
options ...grpc.ServerOption,
|
||||
) error {
|
||||
fmt.Println(
|
||||
"start",
|
||||
rpcRegisterName,
|
||||
"server, port: ",
|
||||
rpcPort,
|
||||
"prometheusPort:",
|
||||
prometheusPort,
|
||||
", OpenIM version: ",
|
||||
config.Version,
|
||||
)
|
||||
listener, err := net.Listen(
|
||||
"tcp",
|
||||
net.JoinHostPort(network.GetListenIP(config.Config.Rpc.ListenIP), strconv.Itoa(rpcPort)),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer listener.Close()
|
||||
zkClient, err := zookeeper.NewClient(config.Config.Zookeeper.ZkAddr, config.Config.Zookeeper.Schema,
|
||||
zookeeper.WithFreq(time.Hour), zookeeper.WithUserNameAndPassword(
|
||||
config.Config.Zookeeper.Username,
|
||||
config.Config.Zookeeper.Password,
|
||||
), zookeeper.WithRoundRobin(), zookeeper.WithTimeout(10), zookeeper.WithLogger(log.NewZkLogger()))
|
||||
if err != nil {
|
||||
return utils.Wrap1(err)
|
||||
}
|
||||
defer zkClient.CloseZK()
|
||||
zkClient.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
registerIP, err := network.GetRpcRegisterIP(config.Config.Rpc.RegisterIP)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// ctx 中间件
|
||||
if config.Config.Prometheus.Enable {
|
||||
prome.NewGrpcRequestCounter()
|
||||
prome.NewGrpcRequestFailedCounter()
|
||||
prome.NewGrpcRequestSuccessCounter()
|
||||
unaryInterceptor := mw.InterceptChain(grpcPrometheus.UnaryServerInterceptor, mw.RpcServerInterceptor)
|
||||
options = append(options, []grpc.ServerOption{
|
||||
grpc.StreamInterceptor(grpcPrometheus.StreamServerInterceptor),
|
||||
grpc.UnaryInterceptor(unaryInterceptor),
|
||||
}...)
|
||||
} else {
|
||||
options = append(options, mw.GrpcServer())
|
||||
}
|
||||
srv := grpc.NewServer(options...)
|
||||
defer srv.GracefulStop()
|
||||
err = rpcFn(zkClient, srv)
|
||||
if err != nil {
|
||||
return utils.Wrap1(err)
|
||||
}
|
||||
err = zkClient.Register(
|
||||
rpcRegisterName,
|
||||
registerIP,
|
||||
rpcPort,
|
||||
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||
)
|
||||
if err != nil {
|
||||
return utils.Wrap1(err)
|
||||
}
|
||||
go func() {
|
||||
if config.Config.Prometheus.Enable && prometheusPort != 0 {
|
||||
if err := prome.StartPrometheusSrv(prometheusPort); err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
}
|
||||
}()
|
||||
return utils.Wrap1(srv.Serve(listener))
|
||||
}
|
@ -0,0 +1,158 @@
|
||||
package msgprocessor
|
||||
|
||||
import (
|
||||
"github.com/OpenIMSDK/protocol/constant"
|
||||
"github.com/OpenIMSDK/protocol/sdkws"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func GetNotificationConversationID(msg *sdkws.MsgData) string {
|
||||
switch msg.SessionType {
|
||||
case constant.SingleChatType:
|
||||
l := []string{msg.SendID, msg.RecvID}
|
||||
sort.Strings(l)
|
||||
return "n_" + strings.Join(l, "_")
|
||||
case constant.GroupChatType:
|
||||
return "n_" + msg.GroupID
|
||||
case constant.SuperGroupChatType:
|
||||
return "n_" + msg.GroupID
|
||||
case constant.NotificationChatType:
|
||||
return "n_" + msg.SendID + "_" + msg.RecvID
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func GetChatConversationIDByMsg(msg *sdkws.MsgData) string {
|
||||
switch msg.SessionType {
|
||||
case constant.SingleChatType:
|
||||
l := []string{msg.SendID, msg.RecvID}
|
||||
sort.Strings(l)
|
||||
return "si_" + strings.Join(l, "_")
|
||||
case constant.GroupChatType:
|
||||
return "g_" + msg.GroupID
|
||||
case constant.SuperGroupChatType:
|
||||
return "sg_" + msg.GroupID
|
||||
case constant.NotificationChatType:
|
||||
return "sn_" + msg.SendID + "_" + msg.RecvID
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func GenConversationUniqueKey(msg *sdkws.MsgData) string {
|
||||
switch msg.SessionType {
|
||||
case constant.SingleChatType, constant.NotificationChatType:
|
||||
l := []string{msg.SendID, msg.RecvID}
|
||||
sort.Strings(l)
|
||||
return strings.Join(l, "_")
|
||||
case constant.SuperGroupChatType:
|
||||
return msg.GroupID
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func GetConversationIDByMsg(msg *sdkws.MsgData) string {
|
||||
options := Options(msg.Options)
|
||||
switch msg.SessionType {
|
||||
case constant.SingleChatType:
|
||||
l := []string{msg.SendID, msg.RecvID}
|
||||
sort.Strings(l)
|
||||
if !options.IsNotNotification() {
|
||||
return "n_" + strings.Join(l, "_")
|
||||
}
|
||||
return "si_" + strings.Join(l, "_") // single chat
|
||||
case constant.GroupChatType:
|
||||
if !options.IsNotNotification() {
|
||||
return "n_" + msg.GroupID // group chat
|
||||
}
|
||||
return "g_" + msg.GroupID // group chat
|
||||
case constant.SuperGroupChatType:
|
||||
if !options.IsNotNotification() {
|
||||
return "n_" + msg.GroupID // super group chat
|
||||
}
|
||||
return "sg_" + msg.GroupID // super group chat
|
||||
case constant.NotificationChatType:
|
||||
if !options.IsNotNotification() {
|
||||
return "n_" + msg.SendID + "_" + msg.RecvID // super group chat
|
||||
}
|
||||
return "sn_" + msg.SendID + "_" + msg.RecvID // server notification chat
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func GetConversationIDBySessionType(sessionType int, ids ...string) string {
|
||||
sort.Strings(ids)
|
||||
if len(ids) > 2 || len(ids) < 1 {
|
||||
return ""
|
||||
}
|
||||
switch sessionType {
|
||||
case constant.SingleChatType:
|
||||
return "si_" + strings.Join(ids, "_") // single chat
|
||||
case constant.GroupChatType:
|
||||
return "g_" + ids[0] // group chat
|
||||
case constant.SuperGroupChatType:
|
||||
return "sg_" + ids[0] // super group chat
|
||||
case constant.NotificationChatType:
|
||||
return "sn_" + ids[0] // server notification chat
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func IsNotification(conversationID string) bool {
|
||||
return strings.HasPrefix(conversationID, "n_")
|
||||
}
|
||||
|
||||
func IsNotificationByMsg(msg *sdkws.MsgData) bool {
|
||||
return !Options(msg.Options).IsNotNotification()
|
||||
}
|
||||
|
||||
func ParseConversationID(msg *sdkws.MsgData) (isNotification bool, conversationID string) {
|
||||
options := Options(msg.Options)
|
||||
switch msg.SessionType {
|
||||
case constant.SingleChatType:
|
||||
l := []string{msg.SendID, msg.RecvID}
|
||||
sort.Strings(l)
|
||||
if !options.IsNotNotification() {
|
||||
return true, "n_" + strings.Join(l, "_")
|
||||
}
|
||||
return false, "si_" + strings.Join(l, "_") // single chat
|
||||
case constant.SuperGroupChatType:
|
||||
if !options.IsNotNotification() {
|
||||
return true, "n_" + msg.GroupID // super group chat
|
||||
}
|
||||
return false, "sg_" + msg.GroupID // super group chat
|
||||
case constant.NotificationChatType:
|
||||
if !options.IsNotNotification() {
|
||||
return true, "n_" + msg.SendID + "_" + msg.RecvID // super group chat
|
||||
}
|
||||
return false, "sn_" + msg.SendID + "_" + msg.RecvID // server notification chat
|
||||
}
|
||||
return false, ""
|
||||
}
|
||||
|
||||
type MsgBySeq []*sdkws.MsgData
|
||||
|
||||
func (s MsgBySeq) Len() int {
|
||||
return len(s)
|
||||
}
|
||||
|
||||
func (s MsgBySeq) Less(i, j int) bool {
|
||||
return s[i].Seq < s[j].Seq
|
||||
}
|
||||
|
||||
func (s MsgBySeq) Swap(i, j int) {
|
||||
s[i], s[j] = s[j], s[i]
|
||||
}
|
||||
|
||||
func Pb2String(pb proto.Message) (string, error) {
|
||||
s, err := proto.Marshal(pb)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(s), nil
|
||||
}
|
||||
|
||||
func String2Pb(s string, pb proto.Message) error {
|
||||
return proto.Unmarshal([]byte(s), pb)
|
||||
}
|
@ -0,0 +1,181 @@
|
||||
// Copyright © 2023 OpenIM. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package msgprocessor
|
||||
|
||||
import "github.com/OpenIMSDK/protocol/constant"
|
||||
|
||||
type Options map[string]bool
|
||||
type OptionsOpt func(Options)
|
||||
|
||||
func NewOptions(opts ...OptionsOpt) Options {
|
||||
options := make(map[string]bool, 11)
|
||||
options[constant.IsNotNotification] = false
|
||||
options[constant.IsSendMsg] = false
|
||||
options[constant.IsHistory] = false
|
||||
options[constant.IsPersistent] = false
|
||||
options[constant.IsOfflinePush] = false
|
||||
options[constant.IsUnreadCount] = false
|
||||
options[constant.IsConversationUpdate] = false
|
||||
options[constant.IsSenderSync] = false
|
||||
options[constant.IsNotPrivate] = false
|
||||
options[constant.IsSenderConversationUpdate] = false
|
||||
options[constant.IsSenderNotificationPush] = false
|
||||
options[constant.IsReactionFromCache] = false
|
||||
for _, opt := range opts {
|
||||
opt(options)
|
||||
}
|
||||
return options
|
||||
}
|
||||
|
||||
func NewMsgOptions() Options {
|
||||
options := make(map[string]bool, 11)
|
||||
options[constant.IsOfflinePush] = false
|
||||
return make(map[string]bool)
|
||||
}
|
||||
|
||||
func WithOptions(options Options, opts ...OptionsOpt) Options {
|
||||
for _, opt := range opts {
|
||||
opt(options)
|
||||
}
|
||||
return options
|
||||
}
|
||||
|
||||
func WithNotNotification(b bool) OptionsOpt {
|
||||
return func(options Options) {
|
||||
options[constant.IsNotNotification] = b
|
||||
}
|
||||
}
|
||||
|
||||
func WithSendMsg(b bool) OptionsOpt {
|
||||
return func(options Options) {
|
||||
options[constant.IsSendMsg] = b
|
||||
}
|
||||
}
|
||||
|
||||
func WithHistory(b bool) OptionsOpt {
|
||||
return func(options Options) {
|
||||
options[constant.IsHistory] = b
|
||||
}
|
||||
}
|
||||
|
||||
func WithPersistent() OptionsOpt {
|
||||
return func(options Options) {
|
||||
options[constant.IsPersistent] = true
|
||||
}
|
||||
}
|
||||
|
||||
func WithOfflinePush(b bool) OptionsOpt {
|
||||
return func(options Options) {
|
||||
options[constant.IsOfflinePush] = b
|
||||
}
|
||||
}
|
||||
|
||||
func WithUnreadCount(b bool) OptionsOpt {
|
||||
return func(options Options) {
|
||||
options[constant.IsUnreadCount] = b
|
||||
}
|
||||
}
|
||||
|
||||
func WithConversationUpdate() OptionsOpt {
|
||||
return func(options Options) {
|
||||
options[constant.IsConversationUpdate] = true
|
||||
}
|
||||
}
|
||||
|
||||
func WithSenderSync() OptionsOpt {
|
||||
return func(options Options) {
|
||||
options[constant.IsSenderSync] = true
|
||||
}
|
||||
}
|
||||
|
||||
func WithNotPrivate() OptionsOpt {
|
||||
return func(options Options) {
|
||||
options[constant.IsNotPrivate] = true
|
||||
}
|
||||
}
|
||||
|
||||
func WithSenderConversationUpdate() OptionsOpt {
|
||||
return func(options Options) {
|
||||
options[constant.IsSenderConversationUpdate] = true
|
||||
}
|
||||
}
|
||||
|
||||
func WithSenderNotificationPush() OptionsOpt {
|
||||
return func(options Options) {
|
||||
options[constant.IsSenderNotificationPush] = true
|
||||
}
|
||||
}
|
||||
|
||||
func WithReactionFromCache() OptionsOpt {
|
||||
return func(options Options) {
|
||||
options[constant.IsReactionFromCache] = true
|
||||
}
|
||||
}
|
||||
|
||||
func (o Options) Is(notification string) bool {
|
||||
v, ok := o[notification]
|
||||
if !ok || v {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (o Options) IsNotNotification() bool {
|
||||
return o.Is(constant.IsNotNotification)
|
||||
}
|
||||
|
||||
func (o Options) IsSendMsg() bool {
|
||||
return o.Is(constant.IsSendMsg)
|
||||
}
|
||||
|
||||
func (o Options) IsHistory() bool {
|
||||
return o.Is(constant.IsHistory)
|
||||
}
|
||||
|
||||
func (o Options) IsPersistent() bool {
|
||||
return o.Is(constant.IsPersistent)
|
||||
}
|
||||
|
||||
func (o Options) IsOfflinePush() bool {
|
||||
return o.Is(constant.IsOfflinePush)
|
||||
}
|
||||
|
||||
func (o Options) IsUnreadCount() bool {
|
||||
return o.Is(constant.IsUnreadCount)
|
||||
}
|
||||
|
||||
func (o Options) IsConversationUpdate() bool {
|
||||
return o.Is(constant.IsConversationUpdate)
|
||||
}
|
||||
|
||||
func (o Options) IsSenderSync() bool {
|
||||
return o.Is(constant.IsSenderSync)
|
||||
}
|
||||
|
||||
func (o Options) IsNotPrivate() bool {
|
||||
return o.Is(constant.IsNotPrivate)
|
||||
}
|
||||
|
||||
func (o Options) IsSenderConversationUpdate() bool {
|
||||
return o.Is(constant.IsSenderConversationUpdate)
|
||||
}
|
||||
|
||||
func (o Options) IsSenderNotificationPush() bool {
|
||||
return o.Is(constant.IsSenderNotificationPush)
|
||||
}
|
||||
|
||||
func (o Options) IsReactionFromCache() bool {
|
||||
return o.Is(constant.IsReactionFromCache)
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue