mv src/common src/utils src/grpc-etcdv3 to pkg
This commit is contained in:
@@ -0,0 +1,159 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"gopkg.in/yaml.v3"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
var Config config
|
||||
|
||||
type config struct {
|
||||
ServerIP string `yaml:"serverip"`
|
||||
|
||||
Api struct {
|
||||
GinPort []int `yaml:"openImApiPort"`
|
||||
}
|
||||
Sdk struct {
|
||||
WsPort []int `yaml:"sdkWsPort"`
|
||||
}
|
||||
Credential struct {
|
||||
Tencent struct {
|
||||
AppID string `yaml:"appID"`
|
||||
Region string `yaml:"region"`
|
||||
Bucket string `yaml:"bucket"`
|
||||
SecretID string `yaml:"secretID"`
|
||||
SecretKey string `yaml:"secretKey"`
|
||||
}
|
||||
}
|
||||
|
||||
Mysql struct {
|
||||
DBAddress []string `yaml:"dbMysqlAddress"`
|
||||
DBUserName string `yaml:"dbMysqlUserName"`
|
||||
DBPassword string `yaml:"dbMysqlPassword"`
|
||||
DBDatabaseName string `yaml:"dbMysqlDatabaseName"`
|
||||
DBTableName string `yaml:"DBTableName"`
|
||||
DBMsgTableNum int `yaml:"dbMsgTableNum"`
|
||||
DBMaxOpenConns int `yaml:"dbMaxOpenConns"`
|
||||
DBMaxIdleConns int `yaml:"dbMaxIdleConns"`
|
||||
DBMaxLifeTime int `yaml:"dbMaxLifeTime"`
|
||||
}
|
||||
Mongo struct {
|
||||
DBAddress []string `yaml:"dbAddress"`
|
||||
DBDirect bool `yaml:"dbDirect"`
|
||||
DBTimeout int `yaml:"dbTimeout"`
|
||||
DBDatabase string `yaml:"dbDatabase"`
|
||||
DBSource string `yaml:"dbSource"`
|
||||
DBUserName string `yaml:"dbUserName"`
|
||||
DBPassword string `yaml:"dbPassword"`
|
||||
DBMaxPoolSize int `yaml:"dbMaxPoolSize"`
|
||||
DBRetainChatRecords int `yaml:"dbRetainChatRecords"`
|
||||
}
|
||||
Redis struct {
|
||||
DBAddress string `yaml:"dbAddress"`
|
||||
DBMaxIdle int `yaml:"dbMaxIdle"`
|
||||
DBMaxActive int `yaml:"dbMaxActive"`
|
||||
DBIdleTimeout int `yaml:"dbIdleTimeout"`
|
||||
DBPassWord string `yaml:"dbPassWord"`
|
||||
}
|
||||
RpcPort struct {
|
||||
OpenImUserPort []int `yaml:"openImUserPort"`
|
||||
openImFriendPort []int `yaml:"openImFriendPort"`
|
||||
RpcMessagePort []int `yaml:"rpcMessagePort"`
|
||||
RpcPushMessagePort []int `yaml:"rpcPushMessagePort"`
|
||||
OpenImGroupPort []int `yaml:"openImGroupPort"`
|
||||
RpcModifyUserInfoPort []int `yaml:"rpcModifyUserInfoPort"`
|
||||
RpcGetTokenPort []int `yaml:"rpcGetTokenPort"`
|
||||
}
|
||||
RpcRegisterName struct {
|
||||
OpenImUserName string `yaml:"openImUserName"`
|
||||
OpenImFriendName string `yaml:"openImFriendName"`
|
||||
OpenImOfflineMessageName string `yaml:"openImOfflineMessageName"`
|
||||
OpenImPushName string `yaml:"openImPushName"`
|
||||
OpenImOnlineMessageRelayName string `yaml:"openImOnlineMessageRelayName"`
|
||||
OpenImGroupName string `yaml:"openImGroupName"`
|
||||
RpcGetTokenName string `yaml:"rpcGetTokenName"`
|
||||
}
|
||||
Etcd struct {
|
||||
EtcdSchema string `yaml:"etcdSchema"`
|
||||
EtcdAddr []string `yaml:"etcdAddr"`
|
||||
}
|
||||
Log struct {
|
||||
StorageLocation string `yaml:"storageLocation"`
|
||||
RotationTime int `yaml:"rotationTime"`
|
||||
RemainRotationCount uint `yaml:"remainRotationCount"`
|
||||
ElasticSearchSwitch bool `yaml:"elasticSearchSwitch"`
|
||||
ElasticSearchAddr []string `yaml:"elasticSearchAddr"`
|
||||
ElasticSearchUser string `yaml:"elasticSearchUser"`
|
||||
ElasticSearchPassword string `yaml:"elasticSearchPassword"`
|
||||
}
|
||||
ModuleName struct {
|
||||
LongConnSvrName string `yaml:"longConnSvrName"`
|
||||
MsgTransferName string `yaml:"msgTransferName"`
|
||||
PushName string `yaml:"pushName"`
|
||||
}
|
||||
LongConnSvr struct {
|
||||
WebsocketPort []int `yaml:"websocketPort"`
|
||||
WebsocketMaxConnNum int `yaml:"websocketMaxConnNum"`
|
||||
WebsocketMaxMsgLen int `yaml:"websocketMaxMsgLen"`
|
||||
WebsocketTimeOut int `yaml:"websocketTimeOut"`
|
||||
}
|
||||
|
||||
Push struct {
|
||||
Tpns struct {
|
||||
Ios struct {
|
||||
AccessID string `yaml:"accessID"`
|
||||
SecretKey string `yaml:"secretKey"`
|
||||
}
|
||||
Android struct {
|
||||
AccessID string `yaml:"accessID"`
|
||||
SecretKey string `yaml:"secretKey"`
|
||||
}
|
||||
}
|
||||
}
|
||||
Manager struct {
|
||||
AppManagerUid []string `yaml:"appManagerUid"`
|
||||
Secrets []string `yaml:"secrets"`
|
||||
}
|
||||
Kafka struct {
|
||||
Ws2mschat struct {
|
||||
Addr []string `yaml:"addr"`
|
||||
Topic string `yaml:"topic"`
|
||||
}
|
||||
Ms2pschat struct {
|
||||
Addr []string `yaml:"addr"`
|
||||
Topic string `yaml:"topic"`
|
||||
}
|
||||
ConsumerGroupID struct {
|
||||
MsgToMongo string `yaml:"msgToMongo"`
|
||||
MsgToMySql string `yaml:"msgToMySql"`
|
||||
MsgToPush string `yaml:"msgToPush"`
|
||||
}
|
||||
}
|
||||
Secret string `yaml:"secret"`
|
||||
MultiLoginPolicy struct {
|
||||
OnlyOneTerminalAccess bool `yaml:"onlyOneTerminalAccess"`
|
||||
MobileAndPCTerminalAccessButOtherTerminalKickEachOther bool `yaml:"mobileAndPCTerminalAccessButOtherTerminalKickEachOther"`
|
||||
AllTerminalAccess bool `yaml:"allTerminalAccess"`
|
||||
}
|
||||
TokenPolicy struct {
|
||||
AccessSecret string `yaml:"accessSecret"`
|
||||
AccessExpire int64 `yaml:"accessExpire"`
|
||||
}
|
||||
MessageCallBack struct {
|
||||
CallbackSwitch bool `yaml:"callbackSwitch"`
|
||||
CallbackUrl string `yaml:"callbackUrl"`
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
bytes, err := ioutil.ReadFile("config/config.yaml")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return
|
||||
}
|
||||
if err = yaml.Unmarshal(bytes, &Config); err != nil {
|
||||
panic(err)
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package config
|
||||
|
||||
// key = errCode, string = errMsg
|
||||
type ErrInfo struct {
|
||||
ErrCode int32
|
||||
ErrMsg string
|
||||
}
|
||||
|
||||
var (
|
||||
OK = ErrInfo{0, ""}
|
||||
|
||||
ErrMysql = ErrInfo{100, ""}
|
||||
ErrMongo = ErrInfo{110, ""}
|
||||
ErrRedis = ErrInfo{120, ""}
|
||||
ErrParseToken = ErrInfo{200, "Parse token failed"}
|
||||
ErrCreateToken = ErrInfo{201, "Create token failed"}
|
||||
ErrAppServerKey = ErrInfo{300, "key error"}
|
||||
ErrTencentCredential = ErrInfo{400, ""}
|
||||
|
||||
ErrorUserRegister = ErrInfo{600, "User registration failed"}
|
||||
ErrAccountExists = ErrInfo{601, "The account is already registered and cannot be registered again"}
|
||||
ErrUserPassword = ErrInfo{602, "User password error"}
|
||||
ErrTokenIncorrect = ErrInfo{603, "Invalid token"}
|
||||
ErrTokenExpired = ErrInfo{604, "Expired token"}
|
||||
ErrRefreshToken = ErrInfo{605, "Failed to refresh token"}
|
||||
ErrAddFriend = ErrInfo{606, "Failed to add friends"}
|
||||
ErrAgreeToAddFriend = ErrInfo{607, "Failed to agree application"}
|
||||
ErrAddFriendToBlack = ErrInfo{608, "Failed to add friends to the blacklist"}
|
||||
ErrGetBlackList = ErrInfo{609, "Failed to get blacklist"}
|
||||
ErrDeleteFriend = ErrInfo{610, "Failed to delete friend"}
|
||||
ErrGetFriendApplyList = ErrInfo{611, "Failed to get friend application list"}
|
||||
ErrGetFriendList = ErrInfo{612, "Failed to get friend list"}
|
||||
ErrRemoveBlackList = ErrInfo{613, "Failed to remove blacklist"}
|
||||
ErrSearchUserInfo = ErrInfo{614, "Can't find the user information"}
|
||||
ErrDelAppleDeviceToken = ErrInfo{615, ""}
|
||||
ErrModifyUserInfo = ErrInfo{616, "update user some attribute failed"}
|
||||
ErrSetFriendComment = ErrInfo{617, "set friend comment failed"}
|
||||
ErrSearchUserInfoFromTheGroup = ErrInfo{618, "There is no such group or the user not in the group"}
|
||||
ErrCreateGroup = ErrInfo{619, "create group chat failed"}
|
||||
ErrJoinGroupApplication = ErrInfo{620, "Failed to apply to join the group"}
|
||||
ErrQuitGroup = ErrInfo{621, "Failed to quit the group"}
|
||||
ErrSetGroupInfo = ErrInfo{622, "Failed to set group info"}
|
||||
ErrParam = ErrInfo{ErrCode: 700, ErrMsg: "param failed"}
|
||||
|
||||
ErrAccess = ErrInfo{ErrCode: 800, ErrMsg: "no permission"}
|
||||
|
||||
ErrDb = ErrInfo{ErrCode: 900, ErrMsg: "db failed"}
|
||||
)
|
||||
@@ -0,0 +1,73 @@
|
||||
package constant
|
||||
|
||||
const (
|
||||
|
||||
//group admin
|
||||
OrdinaryMember = 0
|
||||
GroupOwner = 1
|
||||
Administrator = 2
|
||||
//group application
|
||||
Application = 0
|
||||
AgreeApplication = 1
|
||||
|
||||
//feiend related
|
||||
BlackListFlag = 1
|
||||
ApplicationFriendFlag = 0
|
||||
FriendFlag = 1
|
||||
RefuseFriendFlag = -1
|
||||
|
||||
//Websocket Protocol
|
||||
WSGetNewestSeq = 1001
|
||||
WSPullMsg = 1002
|
||||
WSSendMsg = 1003
|
||||
WSPushMsg = 2001
|
||||
|
||||
///ContentType
|
||||
//UserRelated
|
||||
Text = 101
|
||||
Picture = 102
|
||||
Voice = 103
|
||||
Video = 104
|
||||
File = 105
|
||||
AtText = 106
|
||||
Custom = 110
|
||||
|
||||
SyncSenderMsg = 108
|
||||
//SysRelated
|
||||
AcceptFriendApplicationTip = 201
|
||||
AddFriendTip = 202
|
||||
RefuseFriendApplicationTip = 203
|
||||
SetSelfInfoTip = 204
|
||||
Revoke = 205
|
||||
C2CMessageAsRead = 206
|
||||
|
||||
KickOnlineTip = 303
|
||||
|
||||
TransferGroupOwnerTip = 501
|
||||
CreateGroupTip = 502
|
||||
GroupApplicationResponseTip = 503
|
||||
JoinGroupTip = 504
|
||||
QuitGroupTip = 505
|
||||
SetGroupInfoTip = 506
|
||||
AcceptGroupApplicationTip = 507
|
||||
RefuseGroupApplicationTip = 508
|
||||
KickGroupMemberTip = 509
|
||||
InviteUserToGroupTip = 510
|
||||
|
||||
//MsgFrom
|
||||
UserMsgType = 100
|
||||
SysMsgType = 200
|
||||
|
||||
//SessionType
|
||||
SingleChatType = 1
|
||||
GroupChatType = 2
|
||||
)
|
||||
|
||||
var ContentType2PushContent = map[int64]string{
|
||||
Picture: "[picture]",
|
||||
Voice: "[voice]",
|
||||
Video: "[video]",
|
||||
File: "[file]",
|
||||
}
|
||||
|
||||
const FriendAcceptTip = "You have successfully become friends, so start chatting"
|
||||
@@ -0,0 +1,60 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"Open_IM/pkg/common/config"
|
||||
"github.com/garyburd/redigo/redis"
|
||||
"gopkg.in/mgo.v2"
|
||||
"time"
|
||||
)
|
||||
|
||||
var DB DataBases
|
||||
|
||||
type DataBases struct {
|
||||
MysqlDB mysqlDB
|
||||
mgoSession *mgo.Session
|
||||
redisPool *redis.Pool
|
||||
}
|
||||
|
||||
func key(dbAddress, dbName string) string {
|
||||
return dbAddress + "_" + dbName
|
||||
}
|
||||
|
||||
func init() {
|
||||
//mysql init
|
||||
initMysqlDB()
|
||||
// mongo init
|
||||
mgoDailInfo := &mgo.DialInfo{
|
||||
Addrs: config.Config.Mongo.DBAddress,
|
||||
Direct: config.Config.Mongo.DBDirect,
|
||||
Timeout: time.Second * time.Duration(config.Config.Mongo.DBTimeout),
|
||||
Database: config.Config.Mongo.DBDatabase,
|
||||
Source: config.Config.Mongo.DBSource,
|
||||
Username: config.Config.Mongo.DBUserName,
|
||||
Password: config.Config.Mongo.DBPassword,
|
||||
PoolLimit: config.Config.Mongo.DBMaxPoolSize,
|
||||
}
|
||||
mgoSession, err := mgo.DialWithInfo(mgoDailInfo)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
DB.mgoSession = mgoSession
|
||||
DB.mgoSession.SetMode(mgo.Monotonic, true)
|
||||
|
||||
// redis pool init
|
||||
DB.redisPool = &redis.Pool{
|
||||
MaxIdle: config.Config.Redis.DBMaxIdle,
|
||||
MaxActive: config.Config.Redis.DBMaxActive,
|
||||
IdleTimeout: time.Duration(config.Config.Redis.DBIdleTimeout) * time.Second,
|
||||
Dial: func() (redis.Conn, error) {
|
||||
return redis.Dial(
|
||||
"tcp",
|
||||
config.Config.Redis.DBAddress,
|
||||
redis.DialReadTimeout(time.Duration(1000)*time.Millisecond),
|
||||
redis.DialWriteTimeout(time.Duration(1000)*time.Millisecond),
|
||||
redis.DialConnectTimeout(time.Duration(1000)*time.Millisecond),
|
||||
redis.DialDatabase(0),
|
||||
redis.DialPassword(config.Config.Redis.DBPassWord),
|
||||
)
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,233 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
pbMsg "Open_IM/pkg/proto/chat"
|
||||
"Open_IM/pkg/common/config"
|
||||
"Open_IM/pkg/common/constant"
|
||||
"errors"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"gopkg.in/mgo.v2/bson"
|
||||
"time"
|
||||
)
|
||||
|
||||
const cChat = "chat"
|
||||
const cGroup = "group"
|
||||
|
||||
type MsgInfo struct {
|
||||
SendTime int64
|
||||
Msg []byte
|
||||
}
|
||||
|
||||
type UserChat struct {
|
||||
UID string
|
||||
Msg []MsgInfo
|
||||
}
|
||||
|
||||
type GroupMember struct {
|
||||
GroupID string
|
||||
UIDList []string
|
||||
}
|
||||
|
||||
func (d *DataBases) GetUserChat(uid string, seqBegin, seqEnd int64) (SingleMsg []*pbMsg.MsgFormat, GroupMsg []*pbMsg.MsgFormat, MaxSeq int64, MinSeq int64, err error) {
|
||||
count := 0
|
||||
session := d.mgoSession.Clone()
|
||||
if session == nil {
|
||||
return nil, nil, MaxSeq, MinSeq, errors.New("session == nil")
|
||||
}
|
||||
defer session.Close()
|
||||
|
||||
c := session.DB(config.Config.Mongo.DBDatabase).C(cChat)
|
||||
|
||||
sChat := UserChat{}
|
||||
if err = c.Find(bson.M{"uid": uid}).One(&sChat); err != nil {
|
||||
return nil, nil, MaxSeq, MinSeq, err
|
||||
}
|
||||
pChat := pbMsg.MsgSvrToPushSvrChatMsg{}
|
||||
for i := 0; i < len(sChat.Msg); i++ {
|
||||
temp := new(pbMsg.MsgFormat)
|
||||
if err = proto.Unmarshal(sChat.Msg[i].Msg, &pChat); err != nil {
|
||||
return nil, nil, MaxSeq, MinSeq, err
|
||||
}
|
||||
if pChat.RecvSeq >= seqBegin && pChat.RecvSeq <= seqEnd {
|
||||
temp.SendID = pChat.SendID
|
||||
temp.RecvID = pChat.RecvID
|
||||
temp.MsgFrom = pChat.MsgFrom
|
||||
temp.Seq = pChat.RecvSeq
|
||||
temp.ServerMsgID = pChat.MsgID
|
||||
temp.SendTime = pChat.SendTime
|
||||
temp.Content = pChat.Content
|
||||
temp.ContentType = pChat.ContentType
|
||||
temp.SenderPlatformID = pChat.PlatformID
|
||||
temp.ClientMsgID = pChat.ClientMsgID
|
||||
temp.SenderFaceURL = pChat.SenderFaceURL
|
||||
temp.SenderNickName = pChat.SenderNickName
|
||||
if pChat.RecvSeq > MaxSeq {
|
||||
MaxSeq = pChat.RecvSeq
|
||||
}
|
||||
if count == 0 {
|
||||
MinSeq = pChat.RecvSeq
|
||||
}
|
||||
if pChat.RecvSeq < MinSeq {
|
||||
MinSeq = pChat.RecvSeq
|
||||
}
|
||||
if pChat.SessionType == constant.SingleChatType {
|
||||
SingleMsg = append(SingleMsg, temp)
|
||||
} else {
|
||||
GroupMsg = append(GroupMsg, temp)
|
||||
}
|
||||
count++
|
||||
}
|
||||
}
|
||||
|
||||
return SingleMsg, GroupMsg, MaxSeq, MinSeq, nil
|
||||
}
|
||||
|
||||
func (d *DataBases) SaveUserChat(uid string, sendTime int64, m proto.Message) error {
|
||||
|
||||
session := d.mgoSession.Clone()
|
||||
if session == nil {
|
||||
return errors.New("session == nil")
|
||||
}
|
||||
defer session.Close()
|
||||
|
||||
c := session.DB(config.Config.Mongo.DBDatabase).C(cChat)
|
||||
|
||||
n, err := c.Find(bson.M{"uid": uid}).Count()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sMsg := MsgInfo{}
|
||||
sMsg.SendTime = sendTime
|
||||
if sMsg.Msg, err = proto.Marshal(m); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if n == 0 {
|
||||
sChat := UserChat{}
|
||||
sChat.UID = uid
|
||||
sChat.Msg = append(sChat.Msg, sMsg)
|
||||
err = c.Insert(&sChat)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
err = c.Update(bson.M{"uid": uid}, bson.M{"$push": bson.M{"msg": sMsg}})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *DataBases) DelUserChat(uid string) error {
|
||||
session := d.mgoSession.Clone()
|
||||
if session == nil {
|
||||
return errors.New("session == nil")
|
||||
}
|
||||
defer session.Close()
|
||||
|
||||
c := session.DB(config.Config.Mongo.DBDatabase).C(cChat)
|
||||
|
||||
delTime := time.Now().Unix() - int64(config.Config.Mongo.DBRetainChatRecords)*24*3600
|
||||
if err := c.Update(bson.M{"uid": uid}, bson.M{"$pull": bson.M{"msg": bson.M{"sendtime": bson.M{"$lte": delTime}}}}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *DataBases) MgoUserCount() (int, error) {
|
||||
session := d.mgoSession.Clone()
|
||||
if session == nil {
|
||||
return 0, errors.New("session == nil")
|
||||
}
|
||||
defer session.Close()
|
||||
|
||||
c := session.DB(config.Config.Mongo.DBDatabase).C(cChat)
|
||||
|
||||
return c.Find(nil).Count()
|
||||
}
|
||||
|
||||
func (d *DataBases) MgoSkipUID(count int) (string, error) {
|
||||
session := d.mgoSession.Clone()
|
||||
if session == nil {
|
||||
return "", errors.New("session == nil")
|
||||
}
|
||||
defer session.Close()
|
||||
|
||||
c := session.DB(config.Config.Mongo.DBDatabase).C(cChat)
|
||||
|
||||
sChat := UserChat{}
|
||||
c.Find(nil).Skip(count).Limit(1).One(&sChat)
|
||||
return sChat.UID, nil
|
||||
}
|
||||
|
||||
func (d *DataBases) GetGroupMember(groupID string) []string {
|
||||
groupInfo := GroupMember{}
|
||||
groupInfo.GroupID = groupID
|
||||
groupInfo.UIDList = make([]string, 0)
|
||||
|
||||
session := d.mgoSession.Clone()
|
||||
if session == nil {
|
||||
return groupInfo.UIDList
|
||||
}
|
||||
defer session.Close()
|
||||
|
||||
c := session.DB(config.Config.Mongo.DBDatabase).C(cGroup)
|
||||
|
||||
if err := c.Find(bson.M{"groupid": groupInfo.GroupID}).One(&groupInfo); err != nil {
|
||||
return groupInfo.UIDList
|
||||
}
|
||||
|
||||
return groupInfo.UIDList
|
||||
}
|
||||
|
||||
func (d *DataBases) AddGroupMember(groupID, uid string) error {
|
||||
session := d.mgoSession.Clone()
|
||||
if session == nil {
|
||||
return errors.New("session == nil")
|
||||
}
|
||||
defer session.Close()
|
||||
|
||||
c := session.DB(config.Config.Mongo.DBDatabase).C(cGroup)
|
||||
|
||||
n, err := c.Find(bson.M{"groupid": groupID}).Count()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if n == 0 {
|
||||
groupInfo := GroupMember{}
|
||||
groupInfo.GroupID = groupID
|
||||
groupInfo.UIDList = append(groupInfo.UIDList, uid)
|
||||
err = c.Insert(&groupInfo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
err = c.Update(bson.M{"groupid": groupID}, bson.M{"$addToSet": bson.M{"uidlist": uid}})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *DataBases) DelGroupMember(groupID, uid string) error {
|
||||
session := d.mgoSession.Clone()
|
||||
if session == nil {
|
||||
return errors.New("session == nil")
|
||||
}
|
||||
defer session.Close()
|
||||
|
||||
c := session.DB(config.Config.Mongo.DBDatabase).C(cGroup)
|
||||
|
||||
if err := c.Update(bson.M{"groupid": groupID}, bson.M{"$pull": bson.M{"uidlist": uid}}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"Open_IM/pkg/common/config"
|
||||
"Open_IM/pkg/common/log"
|
||||
"fmt"
|
||||
"github.com/jinzhu/gorm"
|
||||
_ "github.com/jinzhu/gorm/dialects/mysql"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type mysqlDB struct {
|
||||
sync.RWMutex
|
||||
dbMap map[string]*gorm.DB
|
||||
}
|
||||
|
||||
func initMysqlDB() {
|
||||
//When there is no open IM database, connect to the mysql built-in database to create openIM database
|
||||
dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=true&loc=Local",
|
||||
config.Config.Mysql.DBUserName, config.Config.Mysql.DBPassword, config.Config.Mysql.DBAddress[0], "mysql")
|
||||
|
||||
db, err := gorm.Open("mysql", dsn)
|
||||
if err != nil {
|
||||
log.Error("", "", dsn)
|
||||
panic(err)
|
||||
}
|
||||
|
||||
//Check the database and table during initialization
|
||||
sql := fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %s ;", config.Config.Mysql.DBDatabaseName)
|
||||
err = db.Exec(sql).Error
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
db.Close()
|
||||
|
||||
dsn = fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=true&loc=Local",
|
||||
config.Config.Mysql.DBUserName, config.Config.Mysql.DBPassword, config.Config.Mysql.DBAddress[0], config.Config.Mysql.DBDatabaseName)
|
||||
db, err = gorm.Open("mysql", dsn)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
sqlTable := "CREATE TABLE IF NOT EXISTS `user` (\n `uid` varchar(64) NOT NULL,\n `name` varchar(64) DEFAULT NULL,\n `icon` varchar(1024) DEFAULT NULL,\n `gender` int(11) unsigned zerofill DEFAULT NULL,\n `mobile` varchar(32) DEFAULT NULL,\n `birth` varchar(16) DEFAULT NULL,\n `email` varchar(64) DEFAULT NULL,\n `ex` varchar(1024) DEFAULT NULL,\n `create_time` datetime DEFAULT NULL,\n PRIMARY KEY (`uid`),\n UNIQUE KEY `uk_uid` (`uid`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;"
|
||||
err = db.Exec(sqlTable).Error
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
sqlTable = "CREATE TABLE IF NOT EXISTS `friend` (\n `owner_id` varchar(255) NOT NULL,\n `friend_id` varchar(255) NOT NULL,\n `comment` varchar(255) DEFAULT NULL,\n `friend_flag` int(11) NOT NULL,\n `create_time` datetime NOT NULL,\n PRIMARY KEY (`owner_id`,`friend_id`) USING BTREE\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;"
|
||||
err = db.Exec(sqlTable).Error
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
sqlTable = "CREATE TABLE IF NOT EXISTS `friend_request` (\n `req_id` varchar(255) NOT NULL,\n `user_id` varchar(255) NOT NULL,\n `flag` int(11) NOT NULL DEFAULT '0',\n `req_message` varchar(255) DEFAULT NULL,\n `create_time` datetime NOT NULL,\n PRIMARY KEY (`user_id`,`req_id`) USING BTREE\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;"
|
||||
err = db.Exec(sqlTable).Error
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
sqlTable = "CREATE TABLE IF NOT EXISTS `black_list` (\n `uid` varchar(32) NOT NULL COMMENT 'uid',\n `begin_disable_time` datetime DEFAULT NULL,\n `end_disable_time` datetime DEFAULT NULL,\n `ex` varchar(1024) DEFAULT NULL,\n PRIMARY KEY (`uid`) USING BTREE\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;"
|
||||
err = db.Exec(sqlTable).Error
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
sqlTable = "CREATE TABLE IF NOT EXISTS `user_black_list` (\n `owner_id` varchar(255) NOT NULL,\n `block_id` varchar(255) NOT NULL,\n `create_time` datetime NOT NULL,\n PRIMARY KEY (`owner_id`,`block_id`) USING BTREE\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;"
|
||||
err = db.Exec(sqlTable).Error
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
sqlTable = "CREATE TABLE IF NOT EXISTS `group` (\n `group_id` varchar(255) NOT NULL,\n `name` varchar(255) DEFAULT NULL,\n `introduction` varchar(255) DEFAULT NULL,\n `notification` varchar(255) DEFAULT NULL,\n `face_url` varchar(255) DEFAULT NULL,\n `create_time` datetime DEFAULT NULL,\n `ex` varchar(255) DEFAULT NULL,\n PRIMARY KEY (`group_id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;"
|
||||
err = db.Exec(sqlTable).Error
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
sqlTable = "CREATE TABLE IF NOT EXISTS `group_member` (\n `group_id` varchar(255) NOT NULL,\n `uid` varchar(255) NOT NULL,\n `nickname` varchar(255) DEFAULT NULL,\n `user_group_face_url` varchar(255) DEFAULT NULL,\n `administrator_level` int(11) NOT NULL,\n `join_time` datetime NOT NULL,\n PRIMARY KEY (`group_id`,`uid`) USING BTREE\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;"
|
||||
err = db.Exec(sqlTable).Error
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
sqlTable = "CREATE TABLE IF NOT EXISTS `group_request` (\n `id` int(11) NOT NULL AUTO_INCREMENT,\n `group_id` varchar(255) NOT NULL,\n `from_user_id` varchar(255) NOT NULL,\n `to_user_id` varchar(255) NOT NULL,\n `flag` int(10) NOT NULL DEFAULT '0',\n `req_msg` varchar(255) DEFAULT '',\n `handled_msg` varchar(255) DEFAULT '',\n `create_time` datetime NOT NULL,\n `from_user_nickname` varchar(255) DEFAULT '',\n `to_user_nickname` varchar(255) DEFAULT NULL,\n `from_user_face_url` varchar(255) DEFAULT '',\n `to_user_face_url` varchar(255) DEFAULT '',\n `handled_user` varchar(255) DEFAULT '',\n PRIMARY KEY (`id`)\n) ENGINE=InnoDB AUTO_INCREMENT=38 DEFAULT CHARSET=utf8mb4;"
|
||||
err = db.Exec(sqlTable).Error
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
sqlTable = "CREATE TABLE IF NOT EXISTS `chat_log` (\n `msg_id` varchar(128) NOT NULL,\n `send_id` varchar(255) NOT NULL,\n `session_type` int(11) NOT NULL,\n `recv_id` varchar(255) NOT NULL,\n `content_type` int(11) NOT NULL,\n `msg_from` int(11) NOT NULL,\n `content` varchar(1000) NOT NULL,\n `remark` varchar(100) DEFAULT NULL,\n `sender_platform_id` int(11) NOT NULL,\n `send_time` datetime NOT NULL,\n PRIMARY KEY (`msg_id`) USING BTREE\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;"
|
||||
err = db.Exec(sqlTable).Error
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (m *mysqlDB) DefaultGormDB() (*gorm.DB, error) {
|
||||
return m.GormDB(config.Config.Mysql.DBAddress[0], config.Config.Mysql.DBDatabaseName)
|
||||
}
|
||||
|
||||
func (m *mysqlDB) GormDB(dbAddress, dbName string) (*gorm.DB, error) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
|
||||
k := key(dbAddress, dbName)
|
||||
if _, ok := m.dbMap[k]; !ok {
|
||||
if err := m.open(dbAddress, dbName); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return m.dbMap[k], nil
|
||||
}
|
||||
|
||||
func (m *mysqlDB) open(dbAddress, dbName string) error {
|
||||
dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=true&loc=Local",
|
||||
config.Config.Mysql.DBUserName, config.Config.Mysql.DBPassword, dbAddress, dbName)
|
||||
db, err := gorm.Open("mysql", dsn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
db.SingularTable(true)
|
||||
db.DB().SetMaxOpenConns(config.Config.Mysql.DBMaxOpenConns)
|
||||
db.DB().SetMaxIdleConns(config.Config.Mysql.DBMaxIdleConns)
|
||||
db.DB().SetConnMaxLifetime(time.Duration(config.Config.Mysql.DBMaxLifeTime) * time.Second)
|
||||
|
||||
if m.dbMap == nil {
|
||||
m.dbMap = make(map[string]*gorm.DB)
|
||||
}
|
||||
k := key(dbAddress, dbName)
|
||||
m.dbMap[k] = db
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package im_mysql_model
|
||||
|
||||
import (
|
||||
"Open_IM/pkg/common/db"
|
||||
_ "github.com/jinzhu/gorm/dialects/mysql"
|
||||
"time"
|
||||
)
|
||||
|
||||
func InsertToFriend(ownerId, friendId string, flag int32) error {
|
||||
dbConn, err := db.DB.MysqlDB.DefaultGormDB()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
toInsertFollow := Friend{
|
||||
OwnerId: ownerId,
|
||||
FriendId: friendId,
|
||||
FriendFlag: flag,
|
||||
CreateTime: time.Now(),
|
||||
}
|
||||
err = dbConn.Table("friend").Create(toInsertFollow).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func FindFriendRelationshipFromFriend(ownerId, friendId string) (*Friend, error) {
|
||||
dbConn, err := db.DB.MysqlDB.DefaultGormDB()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var friend Friend
|
||||
err = dbConn.Table("friend").Where("owner_id=? and friend_id=?", ownerId, friendId).Find(&friend).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &friend, err
|
||||
}
|
||||
|
||||
func FindUserInfoFromFriend(ownerId string) ([]Friend, error) {
|
||||
dbConn, err := db.DB.MysqlDB.DefaultGormDB()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var friends []Friend
|
||||
err = dbConn.Table("friend").Where("owner_id=?", ownerId).Find(&friends).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return friends, nil
|
||||
}
|
||||
|
||||
func UpdateFriendComment(ownerId, friendId, comment string) error {
|
||||
dbConn, err := db.DB.MysqlDB.DefaultGormDB()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = dbConn.Exec("update friend set comment=? where owner_id=? and friend_id=?", comment, ownerId, friendId).Error
|
||||
return err
|
||||
}
|
||||
|
||||
func DeleteSingleFriendInfo(ownerId, friendId string) error {
|
||||
dbConn, err := db.DB.MysqlDB.DefaultGormDB()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = dbConn.Table("friend").Where("owner_id=? and friend_id=?", ownerId, friendId).Delete(Friend{}).Error
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package im_mysql_model
|
||||
|
||||
import (
|
||||
"Open_IM/pkg/common/db"
|
||||
"time"
|
||||
)
|
||||
|
||||
func ReplaceIntoFriendReq(reqId, userId string, flag int32, reqMessage string) error {
|
||||
dbConn, err := db.DB.MysqlDB.DefaultGormDB()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = dbConn.Exec("replace into friend_request(req_id,user_id,flag,req_message,create_time) values(?,?,?,?,?)", reqId, userId, flag, reqMessage, time.Now()).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func FindFriendsApplyFromFriendReq(userId string) ([]FriendRequest, error) {
|
||||
dbConn, err := db.DB.MysqlDB.DefaultGormDB()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var usersInfo []FriendRequest
|
||||
//dbConn.LogMode(true)
|
||||
err = dbConn.Table("friend_request").Where("user_id=?", userId).Find(&usersInfo).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return usersInfo, nil
|
||||
}
|
||||
|
||||
func FindSelfApplyFromFriendReq(userId string) ([]FriendRequest, error) {
|
||||
dbConn, err := db.DB.MysqlDB.DefaultGormDB()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var usersInfo []FriendRequest
|
||||
err = dbConn.Table("friend_request").Where("req_id=?", userId).Find(&usersInfo).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return usersInfo, nil
|
||||
}
|
||||
|
||||
func FindFriendApplyFromFriendReqByUid(reqId, userId string) (*FriendRequest, error) {
|
||||
dbConn, err := db.DB.MysqlDB.DefaultGormDB()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var friendRequest FriendRequest
|
||||
err = dbConn.Table("friend_request").Where("req_id=? and user_id=?", reqId, userId).Find(&friendRequest).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &friendRequest, nil
|
||||
}
|
||||
|
||||
func UpdateFriendRelationshipToFriendReq(reqId, userId string, flag int32) error {
|
||||
dbConn, err := db.DB.MysqlDB.DefaultGormDB()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = dbConn.Exec("update friend_request set flag=? where req_id=? and user_id=?", flag, reqId, userId).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
package im_mysql_model
|
||||
|
||||
import (
|
||||
"Open_IM/pkg/common/db"
|
||||
"time"
|
||||
)
|
||||
|
||||
func InsertIntoGroupMember(groupId, uid, nickName, userGroupFaceUrl string, administratorLevel int32) error {
|
||||
dbConn, err := db.DB.MysqlDB.DefaultGormDB()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
toInsertInfo := GroupMember{GroupId: groupId, Uid: uid, NickName: nickName, AdministratorLevel: administratorLevel, JoinTime: time.Now(), UserGroupFaceUrl: userGroupFaceUrl}
|
||||
err = dbConn.Table("group_member").Create(toInsertInfo).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func FindGroupMemberListByUserId(uid string) ([]GroupMember, error) {
|
||||
dbConn, err := db.DB.MysqlDB.DefaultGormDB()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var groupMemberList []GroupMember
|
||||
err = dbConn.Raw("select * from `group_member` where uid=?", uid).Find(&groupMemberList).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return groupMemberList, nil
|
||||
}
|
||||
|
||||
func FindGroupMemberListByGroupId(groupId string) ([]GroupMember, error) {
|
||||
dbConn, err := db.DB.MysqlDB.DefaultGormDB()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var groupMemberList []GroupMember
|
||||
err = dbConn.Raw("select * from `group_member` where group_id=?", groupId).Find(&groupMemberList).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return groupMemberList, nil
|
||||
}
|
||||
|
||||
func FindGroupMemberListByGroupIdAndFilterInfo(groupId string, filter int32) ([]GroupMember, error) {
|
||||
dbConn, err := db.DB.MysqlDB.DefaultGormDB()
|
||||
dbConn.LogMode(true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var groupMemberList []GroupMember
|
||||
err = dbConn.Raw("select * from `group_member` where group_id=? and administrator_level=?", groupId, filter).Find(&groupMemberList).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return groupMemberList, nil
|
||||
}
|
||||
func FindGroupMemberInfoByGroupIdAndUserId(groupId, uid string) (*GroupMember, error) {
|
||||
dbConn, err := db.DB.MysqlDB.DefaultGormDB()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var groupMember GroupMember
|
||||
err = dbConn.Raw("select * from `group_member` where group_id=? and uid=? limit 1", groupId, uid).Scan(&groupMember).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &groupMember, nil
|
||||
}
|
||||
|
||||
func DeleteGroupMemberByGroupIdAndUserId(groupId, uid string) error {
|
||||
dbConn, err := db.DB.MysqlDB.DefaultGormDB()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = dbConn.Exec("delete from `group_member` where group_id=? and uid=?", groupId, uid).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func UpdateOwnerGroupNickName(groupId, userId, groupNickName string) error {
|
||||
dbConn, err := db.DB.MysqlDB.DefaultGormDB()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = dbConn.Exec("update `group_member` set nickname=? where group_id=? and uid=?", groupNickName, groupId, userId).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func SelectGroupList(groupID string) ([]string, error) {
|
||||
var groupUserID string
|
||||
var groupList []string
|
||||
dbConn, err := db.DB.MysqlDB.DefaultGormDB()
|
||||
if err != nil {
|
||||
return groupList, err
|
||||
}
|
||||
|
||||
rows, err := dbConn.Model(&GroupMember{}).Where("group_id = ?", groupID).Select("user_id").Rows()
|
||||
if err != nil {
|
||||
return groupList, err
|
||||
}
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
rows.Scan(&groupUserID)
|
||||
groupList = append(groupList, groupUserID)
|
||||
}
|
||||
return groupList, nil
|
||||
}
|
||||
|
||||
func UpdateTheUserAdministratorLevel(groupId, uid string, administratorLevel int64) error {
|
||||
dbConn, err := db.DB.MysqlDB.DefaultGormDB()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = dbConn.Exec("update `group_member` set administrator_level=? where group_id=? and uid=?", administratorLevel, groupId, uid).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetOwnerManagerByGroupId(groupId string) ([]GroupMember, error) {
|
||||
dbConn, err := db.DB.MysqlDB.DefaultGormDB()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var groupMemberList []GroupMember
|
||||
err = dbConn.Raw("select * from `group_member` where group_id=? and administrator_level > 0", groupId).Find(&groupMemberList).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return groupMemberList, nil
|
||||
}
|
||||
|
||||
func IsExistGroupMember(groupId, uid string) bool {
|
||||
dbConn, err := db.DB.MysqlDB.DefaultGormDB()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
var number int32
|
||||
err = dbConn.Raw("select count(*) from `group_member` where group_id = ? and uid = ?", groupId, uid).Count(&number).Error
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if number != 1 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func RemoveGroupMember(groupId string, memberId string) error {
|
||||
return DeleteGroupMemberByGroupIdAndUserId(groupId, memberId)
|
||||
}
|
||||
|
||||
func GetMemberInfoById(groupId string, memberId string) (*GroupMember, error) {
|
||||
return FindGroupMemberInfoByGroupIdAndUserId(groupId, memberId)
|
||||
}
|
||||
|
||||
func GetGroupMemberByGroupId(groupId string, filter int32, begin int32, maxNumber int32) ([]GroupMember, error) {
|
||||
memberList, err := FindGroupMemberListByGroupId(groupId) //sorted by join time
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if begin >= int32(len(memberList)) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var end int32
|
||||
if begin+int32(maxNumber) < int32(len(memberList)) {
|
||||
end = begin + maxNumber
|
||||
} else {
|
||||
end = int32(len(memberList))
|
||||
}
|
||||
return memberList[begin:end], nil
|
||||
}
|
||||
|
||||
func GetJoinedGroupIdListByMemberId(memberId string) ([]GroupMember, error) {
|
||||
return FindGroupMemberListByUserId(memberId)
|
||||
}
|
||||
|
||||
func GetGroupMemberNumByGroupId(groupId string) int32 {
|
||||
dbConn, err := db.DB.MysqlDB.DefaultGormDB()
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
var number int32
|
||||
err = dbConn.Raw("select count(*) from `group_member` where group_id=? ", groupId).Count(&number).Error
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return number
|
||||
}
|
||||
|
||||
func GetGroupOwnerByGroupId(groupId string) string {
|
||||
omList, err := GetOwnerManagerByGroupId(groupId)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
for _, v := range omList {
|
||||
if v.AdministratorLevel == 1 {
|
||||
return v.Uid
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func InsertGroupMember(groupId, userId, nickName, userFaceUrl string, role int32) error {
|
||||
return InsertIntoGroupMember(groupId, userId, nickName, userFaceUrl, role)
|
||||
}
|
||||
@@ -0,0 +1,302 @@
|
||||
package im_mysql_model
|
||||
|
||||
import (
|
||||
"Open_IM/pkg/proto/group"
|
||||
"Open_IM/pkg/common/db"
|
||||
"Open_IM/pkg/common/log"
|
||||
"errors"
|
||||
"time"
|
||||
)
|
||||
|
||||
func InsertIntoGroup(groupId, name, introduction, notification, faceUrl, ex string) error {
|
||||
dbConn, err := db.DB.MysqlDB.DefaultGormDB()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
//Default group name
|
||||
if name == "" {
|
||||
name = "groupChat"
|
||||
}
|
||||
toInsertInfo := Group{GroupId: groupId, Name: name, Introduction: introduction, Notification: notification, FaceUrl: faceUrl, CreateTime: time.Now(), Ex: ex}
|
||||
err = dbConn.Table("group").Create(toInsertInfo).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func FindGroupInfoByGroupId(groupId string) (*Group, error) {
|
||||
dbConn, err := db.DB.MysqlDB.DefaultGormDB()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var groupInfo Group
|
||||
err = dbConn.Raw("select * from `group` where group_id=?", groupId).Scan(&groupInfo).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &groupInfo, nil
|
||||
}
|
||||
|
||||
func SetGroupInfo(groupId, groupName, introduction, notification, groupFaceUrl, ex string) error {
|
||||
dbConn, err := db.DB.MysqlDB.DefaultGormDB()
|
||||
dbConn.LogMode(true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if groupName != "" {
|
||||
if err = dbConn.Exec("update `group` set name=? where group_id=?", groupName, groupId).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if introduction != "" {
|
||||
if err = dbConn.Exec("update `group` set introduction=? where group_id=?", introduction, groupId).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if notification != "" {
|
||||
if err = dbConn.Exec("update `group` set notification=? where group_id=?", notification, groupId).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if groupFaceUrl != "" {
|
||||
if err = dbConn.Exec("update `group` set face_url=? where group_id=?", groupFaceUrl, groupId).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if ex != "" {
|
||||
if err = dbConn.Exec("update `group` set ex=? where group_id=?", ex, groupId).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetGroupApplicationList(uid string) (*group.GetGroupApplicationListResp, error) {
|
||||
dbConn, err := db.DB.MysqlDB.DefaultGormDB()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var gID string
|
||||
var gIDs []string
|
||||
rows, err := dbConn.Raw("select group_id from `group_member` where uid = ? and administrator_level > 0", uid).Rows()
|
||||
defer rows.Close()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for rows.Next() {
|
||||
rows.Scan(&gID)
|
||||
gIDs = append(gIDs, gID)
|
||||
}
|
||||
|
||||
if len(gIDs) == 0 {
|
||||
return &group.GetGroupApplicationListResp{}, nil
|
||||
}
|
||||
|
||||
sql := "select id, group_id, from_user_id, to_user_id, flag, req_msg, handled_msg, create_time, " +
|
||||
"from_user_nickname, to_user_nickname, from_user_face_url, to_user_face_url, handled_user from `group_request` where group_id in ( "
|
||||
for i := 0; i < len(gIDs); i++ {
|
||||
if i == len(gIDs)-1 {
|
||||
sql = sql + "\"" + gIDs[i] + "\"" + " )"
|
||||
} else {
|
||||
sql = sql + "\"" + gIDs[i] + "\"" + ", "
|
||||
}
|
||||
}
|
||||
|
||||
var groupRequest GroupRequest
|
||||
var groupRequests []GroupRequest
|
||||
log.Info("", "", sql)
|
||||
rows, err = dbConn.Raw(sql).Rows()
|
||||
defer rows.Close()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for rows.Next() {
|
||||
rows.Scan(&groupRequest.ID, &groupRequest.GroupID, &groupRequest.FromUserID, &groupRequest.ToUserID, &groupRequest.Flag, &groupRequest.ReqMsg,
|
||||
&groupRequest.HandledMsg, &groupRequest.CreateTime, &groupRequest.FromUserNickname, &groupRequest.ToUserNickname,
|
||||
&groupRequest.FromUserFaceUrl, &groupRequest.ToUserFaceUrl, &groupRequest.HandledUser)
|
||||
groupRequests = append(groupRequests, groupRequest)
|
||||
}
|
||||
|
||||
reply := &group.GetGroupApplicationListResp{}
|
||||
reply.Data = &group.GetGroupApplicationListData{}
|
||||
reply.Data.Count = int32(len(groupRequests))
|
||||
for i := 0; i < int(reply.Data.Count); i++ {
|
||||
addUser := group.GetGroupApplicationList_Data_User{
|
||||
ID: groupRequests[i].ID,
|
||||
GroupID: groupRequests[i].GroupID,
|
||||
FromUserID: groupRequests[i].FromUserID,
|
||||
FromUserNickname: groupRequests[i].FromUserNickname,
|
||||
FromUserFaceUrl: groupRequests[i].FromUserFaceUrl,
|
||||
ToUserID: groupRequests[i].ToUserID,
|
||||
AddTime: groupRequests[i].CreateTime.Unix(),
|
||||
RequestMsg: groupRequests[i].ReqMsg,
|
||||
HandledMsg: groupRequests[i].HandledMsg,
|
||||
Flag: groupRequests[i].Flag,
|
||||
ToUserNickname: groupRequests[i].ToUserNickname,
|
||||
ToUserFaceUrl: groupRequests[i].ToUserFaceUrl,
|
||||
HandledUser: groupRequests[i].HandledUser,
|
||||
Type: 0,
|
||||
HandleStatus: 0,
|
||||
HandleResult: 0,
|
||||
}
|
||||
|
||||
if addUser.ToUserID != "0" {
|
||||
addUser.Type = 1
|
||||
}
|
||||
|
||||
if len(groupRequests[i].HandledUser) > 0 {
|
||||
if groupRequests[i].HandledUser == uid {
|
||||
addUser.HandleStatus = 2
|
||||
} else {
|
||||
addUser.HandleStatus = 1
|
||||
}
|
||||
}
|
||||
|
||||
if groupRequests[i].Flag == 1 {
|
||||
addUser.HandleResult = 1
|
||||
}
|
||||
|
||||
reply.Data.User = append(reply.Data.User, &addUser)
|
||||
}
|
||||
return reply, nil
|
||||
}
|
||||
|
||||
func TransferGroupOwner(pb *group.TransferGroupOwnerReq) (*group.TransferGroupOwnerResp, error) {
|
||||
oldOwner, err := FindGroupMemberInfoByGroupIdAndUserId(pb.GroupID, pb.OldOwner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newOwner, err := FindGroupMemberInfoByGroupIdAndUserId(pb.GroupID, pb.NewOwner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if oldOwner.Uid == newOwner.Uid {
|
||||
return nil, errors.New("the self")
|
||||
}
|
||||
|
||||
if err = UpdateTheUserAdministratorLevel(pb.GroupID, pb.OldOwner, 0); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = UpdateTheUserAdministratorLevel(pb.GroupID, pb.NewOwner, 1); err != nil {
|
||||
UpdateTheUserAdministratorLevel(pb.GroupID, pb.OldOwner, 1)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &group.TransferGroupOwnerResp{}, nil
|
||||
}
|
||||
|
||||
func GroupApplicationResponse(pb *group.GroupApplicationResponseReq) (*group.GroupApplicationResponseResp, error) {
|
||||
|
||||
ownerUser, err := FindGroupMemberInfoByGroupIdAndUserId(pb.GroupID, pb.OwnerID)
|
||||
if err != nil {
|
||||
log.ErrorByKv("FindGroupMemberInfoByGroupIdAndUserId failed", pb.OperationID, "groupId", pb.GroupID, "ownerID", pb.OwnerID)
|
||||
return nil, err
|
||||
}
|
||||
if ownerUser.AdministratorLevel <= 0 {
|
||||
return nil, errors.New("insufficient permissions")
|
||||
}
|
||||
|
||||
dbConn, err := db.DB.MysqlDB.DefaultGormDB()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var groupRequest GroupRequest
|
||||
err = dbConn.Raw("select * from `group_request` where handled_user = ? and group_id = ? and from_user_id = ? and to_user_id = ?",
|
||||
"", pb.GroupID, pb.FromUserID, pb.ToUserID).Scan(&groupRequest).Error
|
||||
if err != nil {
|
||||
log.ErrorByKv("find group_request info failed", pb.OperationID, "groupId", pb.GroupID, "fromUserId", pb.FromUserID, "toUserId", pb.OwnerID)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if groupRequest.Flag != 0 {
|
||||
return nil, errors.New("application has already handle")
|
||||
}
|
||||
|
||||
var saveFlag int
|
||||
if pb.HandleResult == 0 {
|
||||
saveFlag = -1
|
||||
} else if pb.HandleResult == 1 {
|
||||
saveFlag = 1
|
||||
} else {
|
||||
return nil, errors.New("parma HandleResult error")
|
||||
}
|
||||
err = dbConn.Exec("update `group_request` set flag = ?, handled_msg = ?, handled_user = ? where group_id = ? and from_user_id = ? and to_user_id = ?",
|
||||
saveFlag, pb.HandledMsg, pb.OwnerID, groupRequest.GroupID, groupRequest.FromUserID, groupRequest.ToUserID).Error
|
||||
if err != nil {
|
||||
log.ErrorByKv("update group request failed", pb.OperationID, "groupID", pb.GroupID, "flag", saveFlag, "ownerId", pb.OwnerID, "fromUserId", pb.FromUserID, "toUserID", pb.ToUserID)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if saveFlag == 1 {
|
||||
if groupRequest.ToUserID == "0" {
|
||||
err = InsertIntoGroupMember(pb.GroupID, pb.FromUserID, groupRequest.FromUserNickname, groupRequest.FromUserFaceUrl, 0)
|
||||
if err != nil {
|
||||
log.ErrorByKv("InsertIntoGroupMember failed", pb.OperationID, "groupID", pb.GroupID, "fromUserId", pb.FromUserID)
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
err = InsertIntoGroupMember(pb.GroupID, pb.ToUserID, groupRequest.ToUserNickname, groupRequest.ToUserFaceUrl, 0)
|
||||
if err != nil {
|
||||
log.ErrorByKv("InsertIntoGroupMember failed", pb.OperationID, "groupID", pb.GroupID, "fromUserId", pb.FromUserID)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//if err != nil {
|
||||
// err = dbConn.Raw("select * from `group_request` where handled_user = ? and group_id = ? and to_user_id = ? and from_user_id = ?", "", pb.GroupID, "0", pb.UID).Scan(&groupRequest).Error
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// if pb.Flag == 1 {
|
||||
// err = dbConn.Exec("update `group_request` set flag = ?, handled_msg = ?, handled_user = ? where group_id = ? and to_user_id = ? and from_user_id = ?",
|
||||
// pb.Flag, pb.RespMsg, pb.OwnerID, pb.GroupID, "0", pb.UID).Error
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
//
|
||||
// // add to group member
|
||||
// err = InsertIntoGroupMember(pb.GroupID, pb.UID, groupRequest.FromUserNickname, groupRequest.FromUserFaceUrl, 0)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// } else if pb.Flag == -1 {
|
||||
// err = dbConn.Exec("update `group_request` set flag = ?, handled_msg = ?, handled_user = ? where group_id = ? and to_user_id = ? and from_user_id = ?",
|
||||
// pb.Flag, pb.RespMsg, pb.OwnerID, pb.GroupID, "0", pb.UID).Error
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// } else {
|
||||
// return nil, errors.New("flag error")
|
||||
// }
|
||||
//} else {
|
||||
// if pb.Flag == 1 {
|
||||
// err = dbConn.Exec("update `group_request` set flag = ?, handled_msg = ?, handled_user = ? where group_id = ? and to_user_id = ?",
|
||||
// pb.Flag, pb.RespMsg, pb.OwnerID, pb.GroupID, pb.UID).Error
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
//
|
||||
// // add to group member
|
||||
// err = InsertIntoGroupMember(pb.GroupID, pb.UID, groupRequest.ToUserNickname, groupRequest.ToUserFaceUrl, 0)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// } else if pb.Flag == -1 {
|
||||
// err = dbConn.Exec("update `group_request` set flag = ?, handled_msg = ?, handled_user = ? where group_id = ? and to_user_id = ?",
|
||||
// pb.Flag, pb.RespMsg, pb.OwnerID, pb.GroupID, pb.UID).Error
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// } else {
|
||||
// return nil, errors.New("flag error")
|
||||
// }
|
||||
//}
|
||||
|
||||
return &group.GroupApplicationResponseResp{}, nil
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package im_mysql_model
|
||||
|
||||
import (
|
||||
"Open_IM/pkg/common/db"
|
||||
"time"
|
||||
)
|
||||
|
||||
func InsertIntoGroupRequest(groupId, fromUserId, toUserId, reqMsg, fromUserNickName, fromUserFaceUrl string) error {
|
||||
dbConn, err := db.DB.MysqlDB.DefaultGormDB()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
toInsertInfo := GroupRequest{GroupID: groupId, FromUserID: fromUserId, ToUserID: toUserId, ReqMsg: reqMsg, FromUserNickname: fromUserNickName, FromUserFaceUrl: fromUserFaceUrl, CreateTime: time.Now()}
|
||||
err = dbConn.Table("group_request").Create(&toInsertInfo).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func FindGroupRequestUserInfoByGroupIDAndUid(groupId, uid string) (*GroupRequest, error) {
|
||||
dbConn, err := db.DB.MysqlDB.DefaultGormDB()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var requestUserInfo GroupRequest
|
||||
err = dbConn.Table("group_request").Where("from_user_id=? and group_id=?", uid, groupId).Find(&requestUserInfo).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &requestUserInfo, nil
|
||||
}
|
||||
|
||||
func DelGroupRequest(groupId, fromUserId, toUserId string) error {
|
||||
dbConn, err := db.DB.MysqlDB.DefaultGormDB()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = dbConn.Exec("delete from group_request where group_id=? and from_user_id=? and to_user_id=?", groupId, fromUserId, toUserId).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func FindGroupBeInvitedRequestInfoByUidAndGroupID(groupId, uid string) (*GroupRequest, error) {
|
||||
dbConn, err := db.DB.MysqlDB.DefaultGormDB()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var beInvitedRequestUserInfo GroupRequest
|
||||
err = dbConn.Table("group_request").Where("to_user_id=? and group_id=?", uid, groupId).Find(&beInvitedRequestUserInfo).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &beInvitedRequestUserInfo, nil
|
||||
|
||||
}
|
||||
|
||||
func InsertGroupRequest(groupId, fromUser, fromUserNickName, fromUserFaceUrl, toUser, requestMsg, handledMsg string, handleStatus int) error {
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package im_mysql_model
|
||||
|
||||
import "time"
|
||||
|
||||
type User struct {
|
||||
UID string `gorm:"column:uid"`
|
||||
Name string `gorm:"column:name"`
|
||||
Icon string `gorm:"column:icon"`
|
||||
Gender int32 `gorm:"column:gender"`
|
||||
Mobile string `gorm:"column:mobile"`
|
||||
Birth string `gorm:"column:birth"`
|
||||
Email string `gorm:"column:email"`
|
||||
Ex string `gorm:"column:ex"`
|
||||
CreateTime time.Time `gorm:"column:create_time"`
|
||||
}
|
||||
|
||||
type Friend struct {
|
||||
OwnerId string `gorm:"column:owner_id"`
|
||||
FriendId string `gorm:"column:friend_id"`
|
||||
Comment string `gorm:"column:comment"`
|
||||
FriendFlag int32 `gorm:"column:friend_flag"`
|
||||
CreateTime time.Time `gorm:"column:create_time"`
|
||||
}
|
||||
type FriendRequest struct {
|
||||
ReqId string `gorm:"column:req_id"`
|
||||
Uid string `gorm:"column:user_id"`
|
||||
Flag int32 `gorm:"column:flag"`
|
||||
ReqMessage string `gorm:"column:req_message"`
|
||||
CreateTime time.Time `gorm:"column:create_time"`
|
||||
}
|
||||
type BlackList struct {
|
||||
OwnerId string `gorm:"column:owner_id"`
|
||||
BlockId string `gorm:"column:block_id"`
|
||||
CreateTime time.Time `gorm:"column:create_time"`
|
||||
}
|
||||
|
||||
type Group struct {
|
||||
GroupId string `gorm:"column:group_id"`
|
||||
Name string `gorm:"column:name"`
|
||||
Introduction string `gorm:"column:introduction"`
|
||||
Notification string `gorm:"column:notification"`
|
||||
FaceUrl string `gorm:"column:face_url"`
|
||||
CreateTime time.Time `gorm:"column:create_time"`
|
||||
Ex string `gorm:"column:ex"`
|
||||
}
|
||||
|
||||
type GroupMember struct {
|
||||
GroupId string `gorm:"column:group_id"`
|
||||
Uid string `gorm:"column:uid"`
|
||||
NickName string `gorm:"column:nickname"`
|
||||
AdministratorLevel int32 `gorm:"column:administrator_level"`
|
||||
JoinTime time.Time `gorm:"column:join_time"`
|
||||
UserGroupFaceUrl string `gorm:"user_group_face_url"`
|
||||
}
|
||||
|
||||
type GroupRequest struct {
|
||||
ID string `gorm:"column:id"`
|
||||
GroupID string `gorm:"column:group_id"`
|
||||
FromUserID string `gorm:"column:from_user_id"`
|
||||
ToUserID string `gorm:"column:to_user_id"`
|
||||
Flag int32 `gorm:"column:flag"`
|
||||
ReqMsg string `gorm:"column:req_msg"`
|
||||
HandledMsg string `gorm:"column:handled_msg"`
|
||||
CreateTime time.Time `gorm:"column:create_time"`
|
||||
FromUserNickname string `gorm:"from_user_nickname"`
|
||||
ToUserNickname string `gorm:"to_user_nickname"`
|
||||
FromUserFaceUrl string `gorm:"from_user_face_url"`
|
||||
ToUserFaceUrl string `gorm:"to_user_face_url"`
|
||||
HandledUser string `gorm:"handled_user"`
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package im_mysql_model
|
||||
|
||||
import (
|
||||
"Open_IM/pkg/common/db"
|
||||
"time"
|
||||
)
|
||||
|
||||
func InsertInToUserBlackList(ownerID, blockID string) error {
|
||||
dbConn, err := db.DB.MysqlDB.DefaultGormDB()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
toInsertInfo := BlackList{OwnerId: ownerID, BlockId: blockID, CreateTime: time.Now()}
|
||||
err = dbConn.Table("user_black_list").Create(toInsertInfo).Error
|
||||
return err
|
||||
}
|
||||
|
||||
func FindRelationshipFromBlackList(ownerID, blockID string) error {
|
||||
dbConn, err := db.DB.MysqlDB.DefaultGormDB()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var blackList BlackList
|
||||
err = dbConn.Table("user_black_list").Where("owner_id=? and block_id=?", ownerID, blockID).Find(&blackList).Error
|
||||
return err
|
||||
}
|
||||
|
||||
func RemoveBlackList(ownerID, blockID string) error {
|
||||
dbConn, err := db.DB.MysqlDB.DefaultGormDB()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = dbConn.Exec("delete from user_black_list where owner_id=? and block_id=?", ownerID, blockID).Error
|
||||
return err
|
||||
}
|
||||
|
||||
func GetBlackListByUID(ownerID string) ([]BlackList, error) {
|
||||
dbConn, err := db.DB.MysqlDB.DefaultGormDB()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var blackListUsersInfo []BlackList
|
||||
err = dbConn.Table("user_black_list").Where("owner_id=?", ownerID).Find(&blackListUsersInfo).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return blackListUsersInfo, nil
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
package im_mysql_model
|
||||
|
||||
import (
|
||||
"Open_IM/pkg/common/config"
|
||||
"Open_IM/pkg/common/db"
|
||||
pbAuth "Open_IM/pkg/proto/auth"
|
||||
"Open_IM/pkg/utils"
|
||||
_ "github.com/jinzhu/gorm/dialects/mysql"
|
||||
"time"
|
||||
)
|
||||
|
||||
func init() {
|
||||
//init managers
|
||||
var pb pbAuth.UserRegisterReq
|
||||
for k, v := range config.Config.Manager.AppManagerUid {
|
||||
if !IsExistUser(v) {
|
||||
pb.UID = v
|
||||
pb.Name = "AppManager" + utils.IntToString(k+1)
|
||||
err := UserRegister(&pb)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
func UserRegister(pb *pbAuth.UserRegisterReq) error {
|
||||
dbConn, err := db.DB.MysqlDB.DefaultGormDB()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
addUser := User{
|
||||
UID: pb.UID,
|
||||
Name: pb.Name,
|
||||
Icon: pb.Icon,
|
||||
Gender: pb.Gender,
|
||||
Mobile: pb.Mobile,
|
||||
Birth: pb.Birth,
|
||||
Email: pb.Email,
|
||||
Ex: pb.Ex,
|
||||
CreateTime: time.Now(),
|
||||
}
|
||||
err = dbConn.Table("user").Create(&addUser).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func UserDelete(uid string) error {
|
||||
dbConn, err := db.DB.MysqlDB.DefaultGormDB()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = dbConn.Table("user").Where("uid=?", uid).Delete(User{}).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func FindUserByUID(uid string) (*User, error) {
|
||||
dbConn, err := db.DB.MysqlDB.DefaultGormDB()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var user User
|
||||
err = dbConn.Table("user").Where("uid=?", uid).First(&user).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &user, nil
|
||||
}
|
||||
|
||||
func UpDateUserInfo(uid, name, headUrl, mobilePhoneNum, birth, email, extendInfo string, gender int32) error {
|
||||
dbConn, err := db.DB.MysqlDB.DefaultGormDB()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if name != "" {
|
||||
if err = dbConn.Exec("update user set name=? where uid=?", name, uid).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if headUrl != "" {
|
||||
if err = dbConn.Exec("update user set icon=? where uid=?", headUrl, uid).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if mobilePhoneNum != "" {
|
||||
if err = dbConn.Exec("update user set mobile=? where uid=?", mobilePhoneNum, uid).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if birth != "" {
|
||||
if err = dbConn.Exec("update user set birth=? where uid=?", birth, uid).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if email != "" {
|
||||
if err = dbConn.Exec("update user set email=? where uid=?", email, uid).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if extendInfo != "" {
|
||||
if err = dbConn.Exec("update user set ex=? where uid=?", extendInfo, uid).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if gender != 0 {
|
||||
if err = dbConn.Exec("update user set gender=? where uid=?", gender, uid).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func SelectAllUID() ([]string, error) {
|
||||
var uid []string
|
||||
|
||||
dbConn, err := db.DB.MysqlDB.DefaultGormDB()
|
||||
if err != nil {
|
||||
return uid, err
|
||||
}
|
||||
rows, _ := dbConn.Raw("select uid from user").Rows()
|
||||
defer rows.Close()
|
||||
var strUID string
|
||||
for rows.Next() {
|
||||
rows.Scan(&strUID)
|
||||
uid = append(uid, strUID)
|
||||
}
|
||||
return uid, nil
|
||||
}
|
||||
|
||||
func IsExistUser(uid string) bool {
|
||||
dbConn, err := db.DB.MysqlDB.DefaultGormDB()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
var number int32
|
||||
err = dbConn.Raw("select count(*) from `user` where uid = ?", uid).Count(&number).Error
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
if number != 1 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
** description("").
|
||||
** copyright('tuoyun,www.tuoyun.net').
|
||||
** author("fg,Gordon@tuoyun.net").
|
||||
** time(2021/3/4 11:18).
|
||||
*/
|
||||
package im_mysql_msg_model
|
||||
|
||||
import (
|
||||
"Open_IM/pkg/common/db"
|
||||
pbMsg "Open_IM/pkg/proto/chat"
|
||||
"Open_IM/pkg/utils"
|
||||
"database/sql"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ChatLog Chat information table structure
|
||||
type ChatLog struct {
|
||||
MsgId string `gorm:"primary_key"` // Chat history primary key ID
|
||||
SendID string `gorm:"column:send_id"` // Send ID
|
||||
RecvID string `gorm:"column:recv_id"` //Receive ID
|
||||
SendTime time.Time `gorm:"column:send_time"` // Send time
|
||||
SessionType int32 `gorm:"column:session_type"` // Session type
|
||||
ContentType int32 `gorm:"column:content_type"` // Message content type
|
||||
MsgFrom int32 `gorm:"column:msg_from"` // Source, user, system
|
||||
Content string `gorm:"column:content"` // Chat content
|
||||
SenderPlatformID int32 `gorm:"column:sender_platform_id"` //The sender's platform ID
|
||||
Remark sql.NullString `gorm:"column:remark"` // remark
|
||||
}
|
||||
|
||||
func InsertMessageToChatLog(msgData pbMsg.WSToMsgSvrChatMsg) error {
|
||||
dbConn, err := db.DB.MysqlDB.DefaultGormDB()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
chatLog := ChatLog{
|
||||
MsgId: msgData.MsgID,
|
||||
SendID: msgData.SendID,
|
||||
RecvID: msgData.RecvID,
|
||||
SendTime: utils.UnixNanoSecondToTime(msgData.SendTime),
|
||||
SessionType: msgData.SessionType,
|
||||
ContentType: msgData.ContentType,
|
||||
MsgFrom: msgData.MsgFrom,
|
||||
Content: msgData.Content,
|
||||
SenderPlatformID: msgData.PlatformID,
|
||||
}
|
||||
return dbConn.Table("chat_log").Create(chatLog).Error
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package im_mysql_msg_model
|
||||
|
||||
import (
|
||||
"Open_IM/pkg/common/config"
|
||||
"Open_IM/pkg/common/db"
|
||||
"hash/crc32"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func getHashMsgDBAddr(userID string) string {
|
||||
hCode := crc32.ChecksumIEEE([]byte(userID))
|
||||
return config.Config.Mysql.DBAddress[hCode%uint32(len(config.Config.Mysql.DBAddress))]
|
||||
}
|
||||
|
||||
func getHashMsgTableIndex(userID string) int {
|
||||
hCode := crc32.ChecksumIEEE([]byte(userID))
|
||||
return int(hCode % uint32(config.Config.Mysql.DBMsgTableNum))
|
||||
}
|
||||
|
||||
func QueryUserMsgID(userID string) ([]string, error) {
|
||||
dbAddress, dbTableIndex := getHashMsgDBAddr(userID), getHashMsgTableIndex(userID)
|
||||
dbTableName := "receive" + strconv.Itoa(dbTableIndex)
|
||||
|
||||
dbConn, _ := db.DB.MysqlDB.GormDB(dbAddress, config.Config.Mysql.DBTableName)
|
||||
|
||||
var msgID string
|
||||
var msgIDList []string
|
||||
rows, _ := dbConn.Raw("select msg_id from ? where user_id = ?", dbTableName, userID).Rows()
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
rows.Scan(&msgID)
|
||||
msgIDList = append(msgIDList, msgID)
|
||||
}
|
||||
|
||||
return msgIDList, nil
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
** description("").
|
||||
** copyright('tuoyun,www.tuoyun.net').
|
||||
** author("fg,Gordon@tuoyun.net").
|
||||
** time(2021/3/4 11:18).
|
||||
*/
|
||||
package im_mysql_msg_model
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// Receive Inbox table structure
|
||||
type Receive struct {
|
||||
UserId string `gorm:"primary_key"` // 收件箱主键ID
|
||||
Seq int64 `gorm:"primary_key"` // 收件箱主键ID
|
||||
MsgId string
|
||||
CreateTime *time.Time
|
||||
}
|
||||
|
||||
//func InsertMessageToReceive(seq int64, userid, msgid string) error {
|
||||
// conn := db.NewDbConnection()
|
||||
// receive := Receive{
|
||||
// UID: userid,
|
||||
// Seq: seq,
|
||||
// MsgId: msgid,
|
||||
// }
|
||||
// err := conn.Table("receive").Create(&receive).Error
|
||||
// return err
|
||||
//}
|
||||
//func GetBiggestSeqFromReceive(userid string) (seq int64, err error) {
|
||||
// //得到数据库的连接(并非真连接,调用时才连接,由gorm自动维护数据库连接池)
|
||||
// conn := db.NewDbConnection()
|
||||
// err = conn.Raw("select max(seq) from receive where user_id = ?", userid).Row().Scan(&seq)
|
||||
// return seq, err
|
||||
//}
|
||||
@@ -0,0 +1,92 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
log2 "Open_IM/pkg/common/log"
|
||||
"github.com/garyburd/redigo/redis"
|
||||
)
|
||||
|
||||
const (
|
||||
userIncrSeq = "REDIS_USER_INCR_SEQ:" // user incr seq
|
||||
appleDeviceToken = "DEVICE_TOKEN"
|
||||
lastGetSeq = "LAST_GET_SEQ"
|
||||
)
|
||||
|
||||
func (d *DataBases) Exec(cmd string, key interface{}, args ...interface{}) (interface{}, error) {
|
||||
con := d.redisPool.Get()
|
||||
if err := con.Err(); err != nil {
|
||||
log2.Error("", "", "redis cmd = %v, err = %v", cmd, err)
|
||||
return nil, err
|
||||
}
|
||||
defer con.Close()
|
||||
|
||||
params := make([]interface{}, 0)
|
||||
params = append(params, key)
|
||||
|
||||
if len(args) > 0 {
|
||||
for _, v := range args {
|
||||
params = append(params, v)
|
||||
}
|
||||
}
|
||||
|
||||
return con.Do(cmd, params...)
|
||||
}
|
||||
|
||||
//执行用户消息的seq自增操作
|
||||
func (d *DataBases) IncrUserSeq(uid string) (int64, error) {
|
||||
key := userIncrSeq + uid
|
||||
return redis.Int64(d.Exec("INCR", key))
|
||||
}
|
||||
|
||||
//获取最新的seq
|
||||
func (d *DataBases) GetUserSeq(uid string) (int64, error) {
|
||||
key := userIncrSeq + uid
|
||||
return redis.Int64(d.Exec("GET", key))
|
||||
}
|
||||
|
||||
//存储苹果的设备token到redis
|
||||
func (d *DataBases) SetAppleDeviceToken(accountAddress, value string) (err error) {
|
||||
key := appleDeviceToken + accountAddress
|
||||
_, err = d.Exec("SET", key, value)
|
||||
return err
|
||||
}
|
||||
|
||||
//删除苹果设备token
|
||||
func (d *DataBases) DelAppleDeviceToken(accountAddress string) (err error) {
|
||||
key := appleDeviceToken + accountAddress
|
||||
_, err = d.Exec("DEL", key)
|
||||
return err
|
||||
}
|
||||
|
||||
//记录用户上一次主动拉取Seq的值
|
||||
func (d *DataBases) SetLastGetSeq(uid string) (err error) {
|
||||
key := lastGetSeq + uid
|
||||
_, err = d.Exec("SET", key)
|
||||
return err
|
||||
}
|
||||
|
||||
//获取用户上一次主动拉取Seq的值
|
||||
func (d *DataBases) GetLastGetSeq(uid string) (int64, error) {
|
||||
key := userIncrSeq + uid
|
||||
return redis.Int64(d.Exec("GET", key))
|
||||
}
|
||||
|
||||
//Store userid and platform class to redis
|
||||
func (d *DataBases) SetUserIDAndPlatform(userID, platformClass, value string, ttl int64) error {
|
||||
key := userID + platformClass
|
||||
_, err := d.Exec("SET", key, value, "EX", ttl)
|
||||
return err
|
||||
}
|
||||
|
||||
//Check exists userid and platform class from redis
|
||||
func (d *DataBases) ExistsUserIDAndPlatform(userID, platformClass string) (interface{}, error) {
|
||||
key := userID + platformClass
|
||||
exists, err := d.Exec("EXISTS", key)
|
||||
return exists, err
|
||||
}
|
||||
|
||||
//Get platform class Token
|
||||
func (d *DataBases) GetPlatformToken(userID, platformClass string) (interface{}, error) {
|
||||
key := userID + platformClass
|
||||
token, err := d.Exec("GET", key)
|
||||
return token, err
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
** description("").
|
||||
** copyright('open-im,www.open-im.io').
|
||||
** author("fg,Gordon@tuoyun.net").
|
||||
** time(2021/5/27 10:31).
|
||||
*/
|
||||
package http
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
func Get(url string) (response []byte, err error) {
|
||||
client := http.Client{Timeout: 5 * time.Second}
|
||||
resp, err := client.Get(url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return body, nil
|
||||
}
|
||||
|
||||
//application/json; charset=utf-8
|
||||
func Post(url string, data interface{}, contentType string) (content []byte, err error) {
|
||||
jsonStr, _ := json.Marshal(data)
|
||||
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonStr))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Add("content-type", contentType)
|
||||
defer req.Body.Close()
|
||||
|
||||
client := &http.Client{Timeout: 5 * time.Second}
|
||||
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,36 @@
|
||||
package kafka
|
||||
|
||||
import (
|
||||
"github.com/Shopify/sarama"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type Consumer struct {
|
||||
addr []string
|
||||
WG sync.WaitGroup
|
||||
Topic string
|
||||
PartitionList []int32
|
||||
Consumer sarama.Consumer
|
||||
}
|
||||
|
||||
func NewKafkaConsumer(addr []string, topic string) *Consumer {
|
||||
p := Consumer{}
|
||||
p.Topic = topic
|
||||
p.addr = addr
|
||||
|
||||
consumer, err := sarama.NewConsumer(p.addr, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return nil
|
||||
}
|
||||
p.Consumer = consumer
|
||||
|
||||
partitionList, err := consumer.Partitions(p.Topic)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return nil
|
||||
}
|
||||
p.PartitionList = partitionList
|
||||
|
||||
return &p
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
** description("").
|
||||
** copyright('tuoyun,www.tuoyun.net').
|
||||
** author("fg,Gordon@tuoyun.net").
|
||||
** time(2021/5/11 9:36).
|
||||
*/
|
||||
package kafka
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/Shopify/sarama"
|
||||
)
|
||||
|
||||
type MConsumerGroup struct {
|
||||
sarama.ConsumerGroup
|
||||
groupID string
|
||||
topics []string
|
||||
}
|
||||
|
||||
type MConsumerGroupConfig struct {
|
||||
KafkaVersion sarama.KafkaVersion
|
||||
OffsetsInitial int64
|
||||
IsReturnErr bool
|
||||
}
|
||||
|
||||
func NewMConsumerGroup(consumerConfig *MConsumerGroupConfig, topics, addr []string, groupID string) *MConsumerGroup {
|
||||
config := sarama.NewConfig()
|
||||
config.Version = consumerConfig.KafkaVersion
|
||||
config.Consumer.Offsets.Initial = consumerConfig.OffsetsInitial
|
||||
config.Consumer.Return.Errors = consumerConfig.IsReturnErr
|
||||
client, err := sarama.NewClient(addr, config)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
consumerGroup, err := sarama.NewConsumerGroupFromClient(groupID, client)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return &MConsumerGroup{
|
||||
consumerGroup,
|
||||
groupID,
|
||||
topics,
|
||||
}
|
||||
}
|
||||
func (mc *MConsumerGroup) RegisterHandleAndConsumer(handler sarama.ConsumerGroupHandler) {
|
||||
ctx := context.Background()
|
||||
for {
|
||||
err := mc.ConsumerGroup.Consume(ctx, mc.topics, handler)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package kafka
|
||||
|
||||
import (
|
||||
log2 "Open_IM/pkg/common/log"
|
||||
"github.com/Shopify/sarama"
|
||||
"github.com/golang/protobuf/proto"
|
||||
)
|
||||
|
||||
type Producer struct {
|
||||
topic string
|
||||
addr []string
|
||||
config *sarama.Config
|
||||
producer sarama.SyncProducer
|
||||
}
|
||||
|
||||
func NewKafkaProducer(addr []string, topic string) *Producer {
|
||||
p := Producer{}
|
||||
p.config = sarama.NewConfig() //Instantiate a sarama Config
|
||||
p.config.Producer.Return.Successes = true //Whether to enable the successes channel to be notified after the message is sent successfully
|
||||
p.config.Producer.RequiredAcks = sarama.WaitForAll //Set producer Message Reply level 0 1 all
|
||||
p.config.Producer.Partitioner = sarama.NewHashPartitioner //Set the hash-key automatic hash partition. When sending a message, you must specify the key value of the message. If there is no key, the partition will be selected randomly
|
||||
|
||||
p.addr = addr
|
||||
p.topic = topic
|
||||
|
||||
producer, err := sarama.NewSyncProducer(p.addr, p.config) //Initialize the client
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return nil
|
||||
}
|
||||
p.producer = producer
|
||||
return &p
|
||||
}
|
||||
|
||||
func (p *Producer) SendMessage(m proto.Message, key ...string) (int32, int64, error) {
|
||||
kMsg := &sarama.ProducerMessage{}
|
||||
kMsg.Topic = p.topic
|
||||
if len(key) == 1 {
|
||||
kMsg.Key = sarama.StringEncoder(key[0])
|
||||
}
|
||||
bMsg, err := proto.Marshal(m)
|
||||
if err != nil {
|
||||
log2.Error("", "", "proto marshal err = %s", err.Error())
|
||||
return -1, -1, err
|
||||
}
|
||||
kMsg.Value = sarama.ByteEncoder(bMsg)
|
||||
|
||||
return p.producer.SendMessage(kMsg)
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package multi_terminal_login
|
||||
|
||||
import (
|
||||
"Open_IM/internal/push/content_struct"
|
||||
"Open_IM/internal/push/logic"
|
||||
pbChat "Open_IM/pkg/proto/chat"
|
||||
"Open_IM/pkg/common/config"
|
||||
"Open_IM/pkg/common/constant"
|
||||
"Open_IM/pkg/common/db"
|
||||
"Open_IM/pkg/common"
|
||||
)
|
||||
|
||||
func MultiTerminalLoginChecker(uid, token string, platformID int32) error {
|
||||
// 1.check userid and platform class 0 not exists and 1 exists
|
||||
existsInterface, err := db.DB.ExistsUserIDAndPlatform(uid, utils.PlatformNameToClass(utils.PlatformIDToName(platformID)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
exists := existsInterface.(int64)
|
||||
//get config multi login policy
|
||||
if config.Config.MultiLoginPolicy.OnlyOneTerminalAccess {
|
||||
//OnlyOneTerminalAccess policy need to check all terminal
|
||||
if utils.PlatformNameToClass(utils.PlatformIDToName(platformID)) == "PC" {
|
||||
existsInterface, err = db.DB.ExistsUserIDAndPlatform(uid, "Mobile")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
existsInterface, err = db.DB.ExistsUserIDAndPlatform(uid, "PC")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
exists = existsInterface.(int64)
|
||||
if exists == 1 {
|
||||
err := db.DB.SetUserIDAndPlatform(uid, utils.PlatformNameToClass(utils.PlatformIDToName(platformID)), token, config.Config.TokenPolicy.AccessExpire)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
PushMessageToTheTerminal(uid, platformID)
|
||||
return nil
|
||||
}
|
||||
} else if config.Config.MultiLoginPolicy.MobileAndPCTerminalAccessButOtherTerminalKickEachOther {
|
||||
// common terminal need to kick eich other
|
||||
if exists == 1 {
|
||||
err := db.DB.SetUserIDAndPlatform(uid, utils.PlatformNameToClass(utils.PlatformIDToName(platformID)), token, config.Config.TokenPolicy.AccessExpire)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
PushMessageToTheTerminal(uid, platformID)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
err = db.DB.SetUserIDAndPlatform(uid, utils.PlatformNameToClass(utils.PlatformIDToName(platformID)), token, config.Config.TokenPolicy.AccessExpire)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
PushMessageToTheTerminal(uid, platformID)
|
||||
return nil
|
||||
}
|
||||
|
||||
func PushMessageToTheTerminal(uid string, platform int32) {
|
||||
|
||||
logic.SendMsgByWS(&pbChat.WSToMsgSvrChatMsg{
|
||||
SendID: uid,
|
||||
RecvID: uid,
|
||||
Content: content_struct.NewContentStructString(1, "", "Your account is already logged on other terminal,please confirm"),
|
||||
SendTime: utils.GetCurrentTimestampBySecond(),
|
||||
MsgFrom: constant.SysMsgType,
|
||||
ContentType: constant.KickOnlineTip,
|
||||
PlatformID: platform,
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,254 @@
|
||||
// Package grpcpool provides a pool of grpc clients
|
||||
package getcdv3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrClosed is the error when the client pool is closed
|
||||
ErrClosed = errors.New("grpc pool: client pool is closed")
|
||||
// ErrTimeout is the error when the client pool timed out
|
||||
ErrTimeout = errors.New("grpc pool: client pool timed out")
|
||||
// ErrAlreadyClosed is the error when the client conn was already closed
|
||||
ErrAlreadyClosed = errors.New("grpc pool: the connection was already closed")
|
||||
// ErrFullPool is the error when the pool is already full
|
||||
ErrFullPool = errors.New("grpc pool: closing a ClientConn into a full pool")
|
||||
)
|
||||
|
||||
// Factory is a function type creating a grpc client
|
||||
type Factory func(schema, etcdaddr, servicename string) (*grpc.ClientConn, error)
|
||||
|
||||
// FactoryWithContext is a function type creating a grpc client
|
||||
// that accepts the context parameter that could be passed from
|
||||
// Get or NewWithContext method.
|
||||
type FactoryWithContext func(context.Context) (*grpc.ClientConn, error)
|
||||
|
||||
// Pool is the grpc client pool
|
||||
type Pool struct {
|
||||
clients chan ClientConn
|
||||
factory FactoryWithContext
|
||||
idleTimeout time.Duration
|
||||
maxLifeDuration time.Duration
|
||||
mu sync.RWMutex
|
||||
}
|
||||
|
||||
// ClientConn is the wrapper for a grpc client conn
|
||||
type ClientConn struct {
|
||||
*grpc.ClientConn
|
||||
pool *Pool
|
||||
timeUsed time.Time
|
||||
timeInitiated time.Time
|
||||
unhealthy bool
|
||||
}
|
||||
|
||||
// New creates a new clients pool with the given initial and maximum capacity,
|
||||
// and the timeout for the idle clients. Returns an error if the initial
|
||||
// clients could not be created
|
||||
func New(factory Factory, schema, etcdaddr, servicename string, init, capacity int, idleTimeout time.Duration,
|
||||
maxLifeDuration ...time.Duration) (*Pool, error) {
|
||||
return NewWithContext(context.Background(), func(ctx context.Context) (*grpc.ClientConn, error) { return factory(schema, etcdaddr, servicename) },
|
||||
init, capacity, idleTimeout, maxLifeDuration...)
|
||||
}
|
||||
|
||||
// NewWithContext creates a new clients pool with the given initial and maximum
|
||||
// capacity, and the timeout for the idle clients. The context parameter would
|
||||
// be passed to the factory method during initialization. Returns an error if the
|
||||
// initial clients could not be created.
|
||||
func NewWithContext(ctx context.Context, factory FactoryWithContext, init, capacity int, idleTimeout time.Duration,
|
||||
maxLifeDuration ...time.Duration) (*Pool, error) {
|
||||
|
||||
if capacity <= 0 {
|
||||
capacity = 1
|
||||
}
|
||||
if init < 0 {
|
||||
init = 0
|
||||
}
|
||||
if init > capacity {
|
||||
init = capacity
|
||||
}
|
||||
p := &Pool{
|
||||
clients: make(chan ClientConn, capacity),
|
||||
factory: factory,
|
||||
idleTimeout: idleTimeout,
|
||||
}
|
||||
if len(maxLifeDuration) > 0 {
|
||||
p.maxLifeDuration = maxLifeDuration[0]
|
||||
}
|
||||
for i := 0; i < init; i++ {
|
||||
c, err := factory(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
p.clients <- ClientConn{
|
||||
ClientConn: c,
|
||||
pool: p,
|
||||
timeUsed: time.Now(),
|
||||
timeInitiated: time.Now(),
|
||||
}
|
||||
}
|
||||
// Fill the rest of the pool with empty clients
|
||||
for i := 0; i < capacity-init; i++ {
|
||||
p.clients <- ClientConn{
|
||||
pool: p,
|
||||
}
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func (p *Pool) getClients() chan ClientConn {
|
||||
p.mu.RLock()
|
||||
defer p.mu.RUnlock()
|
||||
|
||||
return p.clients
|
||||
}
|
||||
|
||||
// Close empties the pool calling Close on all its clients.
|
||||
// You can call Close while there are outstanding clients.
|
||||
// The pool channel is then closed, and Get will not be allowed anymore
|
||||
func (p *Pool) Close() {
|
||||
p.mu.Lock()
|
||||
clients := p.clients
|
||||
p.clients = nil
|
||||
p.mu.Unlock()
|
||||
|
||||
if clients == nil {
|
||||
return
|
||||
}
|
||||
|
||||
close(clients)
|
||||
for client := range clients {
|
||||
if client.ClientConn == nil {
|
||||
continue
|
||||
}
|
||||
client.ClientConn.Close()
|
||||
}
|
||||
}
|
||||
|
||||
// IsClosed returns true if the client pool is closed.
|
||||
func (p *Pool) IsClosed() bool {
|
||||
return p == nil || p.getClients() == nil
|
||||
}
|
||||
|
||||
// Get will return the next available client. If capacity
|
||||
// has not been reached, it will create a new one using the factory. Otherwise,
|
||||
// it will wait till the next client becomes available or a timeout.
|
||||
// A timeout of 0 is an indefinite wait
|
||||
func (p *Pool) Get(ctx context.Context) (*ClientConn, error) {
|
||||
clients := p.getClients()
|
||||
if clients == nil {
|
||||
return nil, ErrClosed
|
||||
}
|
||||
|
||||
wrapper := ClientConn{
|
||||
pool: p,
|
||||
}
|
||||
select {
|
||||
case wrapper = <-clients:
|
||||
// All good
|
||||
case <-ctx.Done():
|
||||
return nil, ErrTimeout // it would better returns ctx.Err()
|
||||
}
|
||||
|
||||
// If the wrapper was idle too long, close the connection and create a new
|
||||
// one. It's safe to assume that there isn't any newer client as the client
|
||||
// we fetched is the first in the channel
|
||||
idleTimeout := p.idleTimeout
|
||||
if wrapper.ClientConn != nil && idleTimeout > 0 &&
|
||||
wrapper.timeUsed.Add(idleTimeout).Before(time.Now()) {
|
||||
|
||||
wrapper.ClientConn.Close()
|
||||
wrapper.ClientConn = nil
|
||||
}
|
||||
|
||||
var err error
|
||||
if wrapper.ClientConn == nil {
|
||||
wrapper.ClientConn, err = p.factory(ctx)
|
||||
if err != nil {
|
||||
// If there was an error, we want to put back a placeholder
|
||||
// client in the channel
|
||||
clients <- ClientConn{
|
||||
pool: p,
|
||||
}
|
||||
}
|
||||
// This is a new connection, reset its initiated time
|
||||
wrapper.timeInitiated = time.Now()
|
||||
}
|
||||
|
||||
return &wrapper, err
|
||||
}
|
||||
|
||||
// Unhealthy marks the client conn as unhealthy, so that the connection
|
||||
// gets reset when closed
|
||||
func (c *ClientConn) Unhealthy() {
|
||||
c.unhealthy = true
|
||||
}
|
||||
|
||||
// Close returns a ClientConn to the pool. It is safe to call multiple time,
|
||||
// but will return an error after first time
|
||||
func (c *ClientConn) Close() error {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
if c.ClientConn == nil {
|
||||
return ErrAlreadyClosed
|
||||
}
|
||||
if c.pool.IsClosed() {
|
||||
return ErrClosed
|
||||
}
|
||||
// If the wrapper connection has become too old, we want to recycle it. To
|
||||
// clarify the logic: if the sum of the initialization time and the max
|
||||
// duration is before Now(), it means the initialization is so old adding
|
||||
// the maximum duration couldn't put in the future. This sum therefore
|
||||
// corresponds to the cut-off point: if it's in the future we still have
|
||||
// time, if it's in the past it's too old
|
||||
maxDuration := c.pool.maxLifeDuration
|
||||
if maxDuration > 0 && c.timeInitiated.Add(maxDuration).Before(time.Now()) {
|
||||
c.Unhealthy()
|
||||
}
|
||||
|
||||
// We're cloning the wrapper so we can set ClientConn to nil in the one
|
||||
// used by the user
|
||||
wrapper := ClientConn{
|
||||
pool: c.pool,
|
||||
ClientConn: c.ClientConn,
|
||||
timeUsed: time.Now(),
|
||||
}
|
||||
if c.unhealthy {
|
||||
wrapper.ClientConn.Close()
|
||||
wrapper.ClientConn = nil
|
||||
} else {
|
||||
wrapper.timeInitiated = c.timeInitiated
|
||||
}
|
||||
select {
|
||||
case c.pool.clients <- wrapper:
|
||||
// All good
|
||||
default:
|
||||
return ErrFullPool
|
||||
}
|
||||
|
||||
c.ClientConn = nil // Mark as closed
|
||||
return nil
|
||||
}
|
||||
|
||||
// Capacity returns the capacity
|
||||
func (p *Pool) Capacity() int {
|
||||
if p.IsClosed() {
|
||||
return 0
|
||||
}
|
||||
return cap(p.clients)
|
||||
}
|
||||
|
||||
// Available returns the number of currently unused clients
|
||||
func (p *Pool) Available() int {
|
||||
if p.IsClosed() {
|
||||
return 0
|
||||
}
|
||||
return len(p.clients)
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package getcdv3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"go.etcd.io/etcd/clientv3"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type RegEtcd struct {
|
||||
cli *clientv3.Client
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
key string
|
||||
}
|
||||
|
||||
var rEtcd *RegEtcd
|
||||
|
||||
// "%s:///%s/"
|
||||
func GetPrefix(schema, serviceName string) string {
|
||||
return fmt.Sprintf("%s:///%s/", schema, serviceName)
|
||||
}
|
||||
|
||||
// "%s:///%s"
|
||||
func GetPrefix4Unique(schema, serviceName string) string {
|
||||
return fmt.Sprintf("%s:///%s", schema, serviceName)
|
||||
}
|
||||
|
||||
// "%s:///%s/" -> "%s:///%s:ip:port"
|
||||
func RegisterEtcd4Unique(schema, etcdAddr, myHost string, myPort int, serviceName string, ttl int) error {
|
||||
serviceName = serviceName + ":" + net.JoinHostPort(myHost, strconv.Itoa(myPort))
|
||||
return RegisterEtcd(schema, etcdAddr, myHost, myPort, serviceName, ttl)
|
||||
}
|
||||
|
||||
//etcdAddr separated by commas
|
||||
func RegisterEtcd(schema, etcdAddr, myHost string, myPort int, serviceName string, ttl int) error {
|
||||
cli, err := clientv3.New(clientv3.Config{
|
||||
Endpoints: strings.Split(etcdAddr, ","),
|
||||
})
|
||||
fmt.Println("RegisterEtcd")
|
||||
if err != nil {
|
||||
// return fmt.Errorf("grpclb: create clientv3 client failed: %v", err)
|
||||
return fmt.Errorf("create etcd clientv3 client failed, errmsg:%v, etcd addr:%s", err, etcdAddr)
|
||||
}
|
||||
|
||||
//lease
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
resp, err := cli.Grant(ctx, int64(ttl))
|
||||
if err != nil {
|
||||
return fmt.Errorf("grant failed")
|
||||
}
|
||||
|
||||
// schema:///serviceName/ip:port ->ip:port
|
||||
serviceValue := net.JoinHostPort(myHost, strconv.Itoa(myPort))
|
||||
serviceKey := GetPrefix(schema, serviceName) + serviceValue
|
||||
|
||||
//set key->value
|
||||
if _, err := cli.Put(ctx, serviceKey, serviceValue, clientv3.WithLease(resp.ID)); err != nil {
|
||||
return fmt.Errorf("put failed, errmsg:%v, key:%s, value:%s", err, serviceKey, serviceValue)
|
||||
}
|
||||
|
||||
//keepalive
|
||||
kresp, err := cli.KeepAlive(ctx, resp.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("keepalive faild, errmsg:%v, lease id:%d", err, resp.ID)
|
||||
}
|
||||
|
||||
go func() {
|
||||
FLOOP:
|
||||
for {
|
||||
select {
|
||||
case _, ok := <-kresp:
|
||||
if ok == true {
|
||||
} else {
|
||||
break FLOOP
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
rEtcd = &RegEtcd{ctx: ctx,
|
||||
cli: cli,
|
||||
cancel: cancel,
|
||||
key: serviceKey}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func UnRegisterEtcd() {
|
||||
//delete
|
||||
rEtcd.cancel()
|
||||
rEtcd.cli.Delete(rEtcd.ctx, rEtcd.key)
|
||||
}
|
||||
@@ -0,0 +1,262 @@
|
||||
package getcdv3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"go.etcd.io/etcd/clientv3"
|
||||
"go.etcd.io/etcd/mvcc/mvccpb"
|
||||
//"google.golang.org/genproto/googleapis/ads/googleads/v1/services"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/balancer/roundrobin"
|
||||
"google.golang.org/grpc/resolver"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Resolver struct {
|
||||
cc resolver.ClientConn
|
||||
serviceName string
|
||||
grpcClientConn *grpc.ClientConn
|
||||
cli *clientv3.Client
|
||||
schema string
|
||||
etcdAddr string
|
||||
watchStartRevision int64
|
||||
}
|
||||
|
||||
var (
|
||||
nameResolver = make(map[string]*Resolver)
|
||||
rwNameResolverMutex sync.RWMutex
|
||||
)
|
||||
|
||||
func NewResolver(schema, etcdAddr, serviceName string) (*Resolver, error) {
|
||||
etcdCli, err := clientv3.New(clientv3.Config{
|
||||
Endpoints: strings.Split(etcdAddr, ","),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var r Resolver
|
||||
r.serviceName = serviceName
|
||||
r.cli = etcdCli
|
||||
r.schema = schema
|
||||
r.etcdAddr = etcdAddr
|
||||
resolver.Register(&r)
|
||||
|
||||
conn, err := grpc.Dial(
|
||||
GetPrefix(schema, serviceName),
|
||||
grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"LoadBalancingPolicy": "%s"}`, roundrobin.Name)),
|
||||
grpc.WithInsecure(),
|
||||
grpc.WithTimeout(time.Duration(5)*time.Second),
|
||||
)
|
||||
if err == nil {
|
||||
r.grpcClientConn = conn
|
||||
}
|
||||
return &r, err
|
||||
}
|
||||
|
||||
func (r1 *Resolver) ResolveNow(rn resolver.ResolveNowOptions) {
|
||||
}
|
||||
|
||||
func (r1 *Resolver) Close() {
|
||||
}
|
||||
|
||||
func GetConn(schema, etcdaddr, serviceName string) *grpc.ClientConn {
|
||||
rwNameResolverMutex.RLock()
|
||||
r, ok := nameResolver[schema+serviceName]
|
||||
rwNameResolverMutex.RUnlock()
|
||||
if ok {
|
||||
return r.grpcClientConn
|
||||
}
|
||||
|
||||
rwNameResolverMutex.Lock()
|
||||
r, ok = nameResolver[schema+serviceName]
|
||||
if ok {
|
||||
rwNameResolverMutex.Unlock()
|
||||
return r.grpcClientConn
|
||||
}
|
||||
|
||||
r, err := NewResolver(schema, etcdaddr, serviceName)
|
||||
if err != nil {
|
||||
rwNameResolverMutex.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
nameResolver[schema+serviceName] = r
|
||||
rwNameResolverMutex.Unlock()
|
||||
return r.grpcClientConn
|
||||
}
|
||||
|
||||
func (r *Resolver) Build(target resolver.Target, cc resolver.ClientConn, opts resolver.BuildOptions) (resolver.Resolver, error) {
|
||||
if r.cli == nil {
|
||||
return nil, fmt.Errorf("etcd clientv3 client failed, etcd:%s", target)
|
||||
}
|
||||
r.cc = cc
|
||||
|
||||
ctx, _ := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
// "%s:///%s"
|
||||
prefix := GetPrefix(r.schema, r.serviceName)
|
||||
// get key first
|
||||
resp, err := r.cli.Get(ctx, prefix, clientv3.WithPrefix())
|
||||
if err == nil {
|
||||
var addrList []resolver.Address
|
||||
for i := range resp.Kvs {
|
||||
fmt.Println("init addr: ", string(resp.Kvs[i].Value))
|
||||
addrList = append(addrList, resolver.Address{Addr: string(resp.Kvs[i].Value)})
|
||||
}
|
||||
r.cc.UpdateState(resolver.State{Addresses: addrList})
|
||||
r.watchStartRevision = resp.Header.Revision + 1
|
||||
go r.watch(prefix, addrList)
|
||||
} else {
|
||||
return nil, fmt.Errorf("etcd get failed, prefix: %s", prefix)
|
||||
}
|
||||
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func (r *Resolver) Scheme() string {
|
||||
return r.schema
|
||||
}
|
||||
|
||||
func exists(addrList []resolver.Address, addr string) bool {
|
||||
for _, v := range addrList {
|
||||
if v.Addr == addr {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func remove(s []resolver.Address, addr string) ([]resolver.Address, bool) {
|
||||
for i := range s {
|
||||
if s[i].Addr == addr {
|
||||
s[i] = s[len(s)-1]
|
||||
return s[:len(s)-1], true
|
||||
}
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (r *Resolver) watch(prefix string, addrList []resolver.Address) {
|
||||
rch := r.cli.Watch(context.Background(), prefix, clientv3.WithPrefix(), clientv3.WithPrefix())
|
||||
for n := range rch {
|
||||
flag := 0
|
||||
for _, ev := range n.Events {
|
||||
switch ev.Type {
|
||||
case mvccpb.PUT:
|
||||
if !exists(addrList, string(ev.Kv.Value)) {
|
||||
flag = 1
|
||||
addrList = append(addrList, resolver.Address{Addr: string(ev.Kv.Value)})
|
||||
fmt.Println("after add, new list: ", addrList)
|
||||
}
|
||||
case mvccpb.DELETE:
|
||||
fmt.Println("remove addr key: ", string(ev.Kv.Key), "value:", string(ev.Kv.Value))
|
||||
i := strings.LastIndexAny(string(ev.Kv.Key), "/")
|
||||
if i < 0 {
|
||||
return
|
||||
}
|
||||
t := string(ev.Kv.Key)[i+1:]
|
||||
fmt.Println("remove addr key: ", string(ev.Kv.Key), "value:", string(ev.Kv.Value), "addr:", t)
|
||||
if s, ok := remove(addrList, t); ok {
|
||||
flag = 1
|
||||
addrList = s
|
||||
fmt.Println("after remove, new list: ", addrList)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if flag == 1 {
|
||||
r.cc.UpdateState(resolver.State{Addresses: addrList})
|
||||
fmt.Println("update: ", addrList)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func GetConn4Unique(schema, etcdaddr, servicename string) []*grpc.ClientConn {
|
||||
gEtcdCli, err := clientv3.New(clientv3.Config{Endpoints: strings.Split(etcdaddr, ",")})
|
||||
if err != nil {
|
||||
fmt.Println("eeeeeeeeeeeee", err.Error())
|
||||
return nil
|
||||
}
|
||||
|
||||
ctx, _ := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
// "%s:///%s"
|
||||
prefix := GetPrefix4Unique(schema, servicename)
|
||||
|
||||
resp, err := gEtcdCli.Get(ctx, prefix, clientv3.WithPrefix())
|
||||
// "%s:///%s:ip:port" -> %s:ip:port
|
||||
allService := make([]string, 0)
|
||||
if err == nil {
|
||||
for i := range resp.Kvs {
|
||||
k := string(resp.Kvs[i].Key)
|
||||
|
||||
b := strings.LastIndex(k, "///")
|
||||
k1 := k[b+len("///"):]
|
||||
|
||||
e := strings.Index(k1, "/")
|
||||
k2 := k1[:e]
|
||||
allService = append(allService, k2)
|
||||
}
|
||||
} else {
|
||||
gEtcdCli.Close()
|
||||
fmt.Println("rrrrrrrrrrr", err.Error())
|
||||
return nil
|
||||
}
|
||||
gEtcdCli.Close()
|
||||
|
||||
allConn := make([]*grpc.ClientConn, 0)
|
||||
for _, v := range allService {
|
||||
r := GetConn(schema, etcdaddr, v)
|
||||
allConn = append(allConn, r)
|
||||
}
|
||||
|
||||
return allConn
|
||||
}
|
||||
|
||||
var (
|
||||
service2pool = make(map[string]*Pool)
|
||||
service2poolMu sync.Mutex
|
||||
)
|
||||
|
||||
func GetconnFactory(schema, etcdaddr, servicename string) (*grpc.ClientConn, error) {
|
||||
c := GetConn(schema, etcdaddr, servicename)
|
||||
if c != nil {
|
||||
return c, nil
|
||||
} else {
|
||||
return c, fmt.Errorf("GetConn failed")
|
||||
}
|
||||
}
|
||||
|
||||
func GetConnPool(schema, etcdaddr, servicename string) (*ClientConn, error) {
|
||||
//get pool
|
||||
p := NewPool(schema, etcdaddr, servicename)
|
||||
//poo->get
|
||||
|
||||
ctx, _ := context.WithDeadline(context.Background(), time.Now().Add(1000*time.Millisecond))
|
||||
|
||||
c, err := p.Get(ctx)
|
||||
fmt.Println(err)
|
||||
return c, err
|
||||
|
||||
}
|
||||
|
||||
func NewPool(schema, etcdaddr, servicename string) *Pool {
|
||||
|
||||
if _, ok := service2pool[schema+servicename]; !ok {
|
||||
//
|
||||
service2poolMu.Lock()
|
||||
if _, ok1 := service2pool[schema+servicename]; !ok1 {
|
||||
p, err := New(GetconnFactory, schema, etcdaddr, servicename, 5, 10, 1)
|
||||
if err == nil {
|
||||
service2pool[schema+servicename] = p
|
||||
}
|
||||
}
|
||||
service2poolMu.Unlock()
|
||||
}
|
||||
|
||||
return service2pool[schema+servicename]
|
||||
}
|
||||
func GetGrpcConn(schema, etcdaddr, servicename string) *grpc.ClientConn {
|
||||
return nameResolver[schema+servicename].grpcClientConn
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func CorsHandler() gin.HandlerFunc {
|
||||
return func(context *gin.Context) {
|
||||
context.Writer.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
context.Header("Access-Control-Allow-Methods", "*")
|
||||
context.Header("Access-Control-Allow-Headers", "*")
|
||||
context.Header("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") // 跨域关键设置 让浏览器可以解析
|
||||
context.Header("Access-Control-Max-Age", "172800") // 缓存请求信息 单位为秒
|
||||
context.Header("Access-Control-Allow-Credentials", "false") // 跨域请求是否需要带cookie信息 默认设置为true
|
||||
context.Header("content-type", "application/json") // 设置返回格式是json
|
||||
//Release all option pre-requests
|
||||
if context.Request.Method == http.MethodOptions {
|
||||
context.JSON(http.StatusOK, "Options Request!")
|
||||
}
|
||||
context.Next()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package utils
|
||||
|
||||
import "os"
|
||||
|
||||
// Determine whether the given path is a folder
|
||||
func IsDir(path string) bool {
|
||||
s, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return s.IsDir()
|
||||
}
|
||||
|
||||
// Determine whether the given path is a file
|
||||
func IsFile(path string) bool {
|
||||
return !IsDir(path)
|
||||
}
|
||||
|
||||
// Create a directory
|
||||
func MkDir(path string) error {
|
||||
return os.MkdirAll(path, os.ModePerm)
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"Open_IM/pkg/common/config"
|
||||
"net"
|
||||
)
|
||||
|
||||
var ServerIP = ""
|
||||
|
||||
func init() {
|
||||
//fixme In the configuration file, ip takes precedence, if not, get the valid network card ip of the machine
|
||||
if config.Config.ServerIP != "" {
|
||||
ServerIP = config.Config.ServerIP
|
||||
return
|
||||
}
|
||||
//fixme Get the ip of the local network card
|
||||
netInterfaces, err := net.Interfaces()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for i := 0; i < len(netInterfaces); i++ {
|
||||
//Exclude useless network cards by judging the net.flag Up flag
|
||||
if (netInterfaces[i].Flags & net.FlagUp) != 0 {
|
||||
address, _ := netInterfaces[i].Addrs()
|
||||
for _, addr := range address {
|
||||
if ipNet, ok := addr.(*net.IPNet); ok && !ipNet.IP.IsLoopback() {
|
||||
if ipNet.IP.To4() != nil {
|
||||
ServerIP = ipNet.IP.String()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/nfnt/resize"
|
||||
"golang.org/x/image/bmp"
|
||||
"image"
|
||||
"image/gif"
|
||||
"image/jpeg"
|
||||
"image/png"
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
func GenSmallImage(src, dst string) error {
|
||||
fIn, _ := os.Open(src)
|
||||
defer fIn.Close()
|
||||
|
||||
fOut, _ := os.Create(dst)
|
||||
defer fOut.Close()
|
||||
|
||||
if err := scale(fIn, fOut, 0, 0, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func scale(in io.Reader, out io.Writer, width, height, quality int) error {
|
||||
origin, fm, err := image.Decode(in)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if width == 0 || height == 0 {
|
||||
width = origin.Bounds().Max.X / 2
|
||||
height = origin.Bounds().Max.Y / 2
|
||||
}
|
||||
if quality == 0 {
|
||||
quality = 25
|
||||
}
|
||||
canvas := resize.Thumbnail(uint(width), uint(height), origin, resize.Lanczos3)
|
||||
|
||||
switch fm {
|
||||
case "jpeg":
|
||||
return jpeg.Encode(out, canvas, &jpeg.Options{quality})
|
||||
case "png":
|
||||
return png.Encode(out, canvas)
|
||||
case "gif":
|
||||
return gif.Encode(out, canvas, &gif.Options{})
|
||||
case "bmp":
|
||||
return bmp.Encode(out, canvas)
|
||||
default:
|
||||
return errors.New("ERROR FORMAT")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,193 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"Open_IM/pkg/common/config"
|
||||
"Open_IM/pkg/common/db"
|
||||
"errors"
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
TokenExpired = errors.New("token is timed out, please log in again")
|
||||
TokenInvalid = errors.New("token has been invalidated")
|
||||
TokenNotValidYet = errors.New("token not active yet")
|
||||
TokenMalformed = errors.New("that's not even a token")
|
||||
TokenUnknown = errors.New("couldn't handle this token")
|
||||
)
|
||||
|
||||
type Claims struct {
|
||||
UID string
|
||||
Platform string //login platform
|
||||
jwt.StandardClaims
|
||||
}
|
||||
|
||||
func BuildClaims(uid, accountAddr, platform string, ttl int64) Claims {
|
||||
now := time.Now().Unix()
|
||||
//if ttl=-1 Permanent token
|
||||
if ttl == -1 {
|
||||
return Claims{
|
||||
UID: uid,
|
||||
Platform: platform,
|
||||
StandardClaims: jwt.StandardClaims{
|
||||
ExpiresAt: -1,
|
||||
IssuedAt: now,
|
||||
NotBefore: now,
|
||||
}}
|
||||
}
|
||||
return Claims{
|
||||
UID: uid,
|
||||
Platform: platform,
|
||||
StandardClaims: jwt.StandardClaims{
|
||||
ExpiresAt: now + ttl, //Expiration time
|
||||
IssuedAt: now, //Issuing time
|
||||
NotBefore: now, //Begin Effective time
|
||||
}}
|
||||
}
|
||||
|
||||
func CreateToken(userID, accountAddr string, platform int32) (string, int64, error) {
|
||||
claims := BuildClaims(userID, accountAddr, PlatformIDToName(platform), config.Config.TokenPolicy.AccessExpire)
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
tokenString, err := token.SignedString([]byte(config.Config.TokenPolicy.AccessSecret))
|
||||
|
||||
return tokenString, claims.ExpiresAt, err
|
||||
}
|
||||
|
||||
func secret() jwt.Keyfunc {
|
||||
return func(token *jwt.Token) (interface{}, error) {
|
||||
return []byte(config.Config.TokenPolicy.AccessSecret), nil
|
||||
}
|
||||
}
|
||||
|
||||
func ParseToken(tokensString string) (claims *Claims, err error) {
|
||||
token, err := jwt.ParseWithClaims(tokensString, &Claims{}, secret())
|
||||
if err != nil {
|
||||
if ve, ok := err.(*jwt.ValidationError); ok {
|
||||
if ve.Errors&jwt.ValidationErrorMalformed != 0 {
|
||||
return nil, TokenMalformed
|
||||
} else if ve.Errors&jwt.ValidationErrorExpired != 0 {
|
||||
return nil, TokenExpired
|
||||
} else if ve.Errors&jwt.ValidationErrorNotValidYet != 0 {
|
||||
return nil, TokenNotValidYet
|
||||
} else {
|
||||
return nil, TokenUnknown
|
||||
}
|
||||
}
|
||||
}
|
||||
if claims, ok := token.Claims.(*Claims); ok && token.Valid {
|
||||
// 1.check userid and platform class 0 not exists and 1 exists
|
||||
existsInterface, err := db.DB.ExistsUserIDAndPlatform(claims.UID, Platform2class[claims.Platform])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
exists := existsInterface.(int64)
|
||||
//get config multi login policy
|
||||
if config.Config.MultiLoginPolicy.OnlyOneTerminalAccess {
|
||||
//OnlyOneTerminalAccess policy need to check all terminal
|
||||
//When only one end is allowed to log in, there is a situation that needs to be paid attention to. After PC login,
|
||||
//mobile login should check two platform times. One of them is less than the redis storage time, which is the invalid token.
|
||||
if Platform2class[claims.Platform] == "PC" {
|
||||
existsInterface, err = db.DB.ExistsUserIDAndPlatform(claims.UID, "Mobile")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
exists = existsInterface.(int64)
|
||||
if exists == 1 {
|
||||
res, err := MakeTheTokenInvalid(*claims, "Mobile")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if res {
|
||||
return nil, TokenInvalid
|
||||
}
|
||||
}
|
||||
} else {
|
||||
existsInterface, err = db.DB.ExistsUserIDAndPlatform(claims.UID, "PC")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
exists = existsInterface.(int64)
|
||||
if exists == 1 {
|
||||
res, err := MakeTheTokenInvalid(*claims, "PC")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if res {
|
||||
return nil, TokenInvalid
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if exists == 1 {
|
||||
res, err := MakeTheTokenInvalid(*claims, Platform2class[claims.Platform])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if res {
|
||||
return nil, TokenInvalid
|
||||
}
|
||||
}
|
||||
|
||||
} else if config.Config.MultiLoginPolicy.MobileAndPCTerminalAccessButOtherTerminalKickEachOther {
|
||||
if exists == 1 {
|
||||
res, err := MakeTheTokenInvalid(*claims, Platform2class[claims.Platform])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if res {
|
||||
return nil, TokenInvalid
|
||||
}
|
||||
}
|
||||
}
|
||||
return claims, nil
|
||||
}
|
||||
return nil, TokenUnknown
|
||||
}
|
||||
|
||||
func MakeTheTokenInvalid(currentClaims Claims, platformClass string) (bool, error) {
|
||||
storedRedisTokenInterface, err := db.DB.GetPlatformToken(currentClaims.UID, platformClass)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
storedRedisPlatformClaims, err := ParseRedisInterfaceToken(storedRedisTokenInterface)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
//if issue time less than redis token then make this token invalid
|
||||
if currentClaims.IssuedAt < storedRedisPlatformClaims.IssuedAt {
|
||||
return true, TokenInvalid
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
func ParseRedisInterfaceToken(redisToken interface{}) (*Claims, error) {
|
||||
token, err := jwt.ParseWithClaims(string(redisToken.([]uint8)), &Claims{}, secret())
|
||||
if err != nil {
|
||||
if ve, ok := err.(*jwt.ValidationError); ok {
|
||||
if ve.Errors&jwt.ValidationErrorMalformed != 0 {
|
||||
return nil, TokenMalformed
|
||||
} else if ve.Errors&jwt.ValidationErrorExpired != 0 {
|
||||
return nil, TokenExpired
|
||||
} else if ve.Errors&jwt.ValidationErrorNotValidYet != 0 {
|
||||
return nil, TokenNotValidYet
|
||||
} else {
|
||||
return nil, TokenInvalid
|
||||
}
|
||||
}
|
||||
}
|
||||
if claims, ok := token.Claims.(*Claims); ok && token.Valid {
|
||||
return claims, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
//Validation token, false means failure, true means successful verification
|
||||
func VerifyToken(token, uid string) bool {
|
||||
claims, err := ParseToken(token)
|
||||
if err != nil {
|
||||
return false
|
||||
} else if claims.UID != uid {
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type Map struct {
|
||||
sync.RWMutex
|
||||
m map[interface{}]interface{}
|
||||
}
|
||||
|
||||
func (m *Map) init() {
|
||||
if m.m == nil {
|
||||
m.m = make(map[interface{}]interface{})
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Map) UnsafeGet(key interface{}) interface{} {
|
||||
if m.m == nil {
|
||||
return nil
|
||||
} else {
|
||||
return m.m[key]
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Map) Get(key interface{}) interface{} {
|
||||
m.RLock()
|
||||
defer m.RUnlock()
|
||||
return m.UnsafeGet(key)
|
||||
}
|
||||
|
||||
func (m *Map) UnsafeSet(key interface{}, value interface{}) {
|
||||
m.init()
|
||||
m.m[key] = value
|
||||
}
|
||||
|
||||
func (m *Map) Set(key interface{}, value interface{}) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
m.UnsafeSet(key, value)
|
||||
}
|
||||
|
||||
func (m *Map) TestAndSet(key interface{}, value interface{}) interface{} {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
|
||||
m.init()
|
||||
|
||||
if v, ok := m.m[key]; ok {
|
||||
return v
|
||||
} else {
|
||||
m.m[key] = value
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Map) UnsafeDel(key interface{}) {
|
||||
m.init()
|
||||
delete(m.m, key)
|
||||
}
|
||||
|
||||
func (m *Map) Del(key interface{}) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
m.UnsafeDel(key)
|
||||
}
|
||||
|
||||
func (m *Map) UnsafeLen() int {
|
||||
if m.m == nil {
|
||||
return 0
|
||||
} else {
|
||||
return len(m.m)
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Map) Len() int {
|
||||
m.RLock()
|
||||
defer m.RUnlock()
|
||||
return m.UnsafeLen()
|
||||
}
|
||||
|
||||
func (m *Map) UnsafeRange(f func(interface{}, interface{})) {
|
||||
if m.m == nil {
|
||||
return
|
||||
}
|
||||
for k, v := range m.m {
|
||||
f(k, v)
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Map) RLockRange(f func(interface{}, interface{})) {
|
||||
m.RLock()
|
||||
defer m.RUnlock()
|
||||
m.UnsafeRange(f)
|
||||
}
|
||||
|
||||
func (m *Map) LockRange(f func(interface{}, interface{})) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
m.UnsafeRange(f)
|
||||
}
|
||||
|
||||
func MapToJsonString(param map[string]interface{}) string {
|
||||
dataType, _ := json.Marshal(param)
|
||||
dataString := string(dataType)
|
||||
return dataString
|
||||
}
|
||||
func JsonStringToMap(str string) (tempMap map[string]interface{}) {
|
||||
_ = json.Unmarshal([]byte(str), &tempMap)
|
||||
return tempMap
|
||||
}
|
||||
func GetSwitchFromOptions(Options map[string]interface{}, key string) (result bool) {
|
||||
if flag, ok := Options[key]; !ok || flag == 1 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
)
|
||||
|
||||
func Md5(s string) string {
|
||||
h := md5.New()
|
||||
h.Write([]byte(s))
|
||||
cipher := h.Sum(nil)
|
||||
return hex.EncodeToString(cipher)
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package utils
|
||||
|
||||
// fixme 1<--->IOS 2<--->Android 3<--->Windows
|
||||
//fixme 4<--->OSX 5<--->Web 6<--->MiniWeb 7<--->Linux
|
||||
|
||||
const (
|
||||
//Platform ID
|
||||
IOSPlatformID = 1
|
||||
AndroidPlatformID = 2
|
||||
WindowsPlatformID = 3
|
||||
OSXPlatformID = 4
|
||||
WebPlatformID = 5
|
||||
MiniWebPlatformID = 6
|
||||
LinuxPlatformID = 7
|
||||
|
||||
//Platform string match to Platform ID
|
||||
IOSPlatformStr = "IOS"
|
||||
AndroidPlatformStr = "Android"
|
||||
WindowsPlatformStr = "Windows"
|
||||
OSXPlatformStr = "OSX"
|
||||
WebPlatformStr = "Web"
|
||||
MiniWebPlatformStr = "MiniWeb"
|
||||
LinuxPlatformStr = "Linux"
|
||||
|
||||
//terminal types
|
||||
TerminalPC = "PC"
|
||||
TerminalMobile = "Mobile"
|
||||
)
|
||||
|
||||
var PlatformID2Name = map[int32]string{
|
||||
IOSPlatformID: IOSPlatformStr,
|
||||
AndroidPlatformID: AndroidPlatformStr,
|
||||
WindowsPlatformID: WindowsPlatformStr,
|
||||
OSXPlatformID: OSXPlatformStr,
|
||||
WebPlatformID: WebPlatformStr,
|
||||
MiniWebPlatformID: MiniWebPlatformStr,
|
||||
LinuxPlatformID: LinuxPlatformStr,
|
||||
}
|
||||
var PlatformName2ID = map[string]int32{
|
||||
IOSPlatformStr: IOSPlatformID,
|
||||
AndroidPlatformStr: AndroidPlatformID,
|
||||
WindowsPlatformStr: WindowsPlatformID,
|
||||
OSXPlatformStr: OSXPlatformID,
|
||||
WebPlatformStr: WebPlatformID,
|
||||
MiniWebPlatformStr: MiniWebPlatformID,
|
||||
LinuxPlatformStr: LinuxPlatformID,
|
||||
}
|
||||
var Platform2class = map[string]string{
|
||||
IOSPlatformStr: TerminalMobile,
|
||||
AndroidPlatformStr: TerminalMobile,
|
||||
MiniWebPlatformStr: TerminalMobile,
|
||||
WindowsPlatformStr: TerminalPC,
|
||||
OSXPlatformStr: TerminalPC,
|
||||
WebPlatformStr: TerminalPC,
|
||||
LinuxPlatformStr: TerminalPC,
|
||||
}
|
||||
|
||||
func PlatformIDToName(num int32) string {
|
||||
return PlatformID2Name[num]
|
||||
}
|
||||
func PlatformNameToID(name string) int32 {
|
||||
return PlatformName2ID[name]
|
||||
}
|
||||
func PlatformNameToClass(name string) string {
|
||||
return Platform2class[name]
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
** description("").
|
||||
** copyright('tuoyun,www.tuoyun.net').
|
||||
** author("fg,Gordon@tuoyun.net").
|
||||
** time(2021/4/8 15:09).
|
||||
*/
|
||||
package utils
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"math/rand"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func IntToString(i int) string {
|
||||
return strconv.FormatInt(int64(i), 10)
|
||||
}
|
||||
|
||||
func StringToInt(i string) int {
|
||||
j, _ := strconv.Atoi(i)
|
||||
return j
|
||||
}
|
||||
func StringToInt64(i string) int64 {
|
||||
j, _ := strconv.ParseInt(i, 10, 64)
|
||||
return j
|
||||
}
|
||||
|
||||
//judge a string whether in the string list
|
||||
func IsContain(target string, List []string) bool {
|
||||
|
||||
for _, element := range List {
|
||||
|
||||
if target == element {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
|
||||
}
|
||||
func InterfaceArrayToStringArray(data []interface{}) (i []string) {
|
||||
for _, param := range data {
|
||||
i = append(i, param.(string))
|
||||
}
|
||||
return i
|
||||
}
|
||||
func StructToJsonString(param interface{}) string {
|
||||
dataType, _ := json.Marshal(param)
|
||||
dataString := string(dataType)
|
||||
return dataString
|
||||
}
|
||||
|
||||
//The incoming parameter must be a pointer
|
||||
func JsonStringToStruct(s string, args interface{}) error {
|
||||
err := json.Unmarshal([]byte(s), args)
|
||||
return err
|
||||
}
|
||||
|
||||
func GetMsgID(sendID string) string {
|
||||
t := int64ToString(GetCurrentTimestampByNano())
|
||||
return Md5(t + sendID + int64ToString(rand.Int63n(GetCurrentTimestampByNano())))
|
||||
}
|
||||
func int64ToString(i int64) string {
|
||||
return strconv.FormatInt(i, 10)
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
** description("").
|
||||
** copyright('tuoyun,www.tuoyun.net').
|
||||
** author("fg,Gordon@tuoyun.net").
|
||||
** time(2021/2/22 11:52).
|
||||
*/
|
||||
package utils
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
TimeOffset = 8 * 3600 //8 hour offset
|
||||
HalfOffset = 12 * 3600 //Half-day hourly offset
|
||||
)
|
||||
|
||||
//Get the current timestamp by Second
|
||||
func GetCurrentTimestampBySecond() int64 {
|
||||
return time.Now().Unix()
|
||||
}
|
||||
|
||||
//Convert timestamp to time.Time type
|
||||
func UnixSecondToTime(second int64) time.Time {
|
||||
return time.Unix(second, 0)
|
||||
}
|
||||
|
||||
//Convert nano timestamp to time.Time type
|
||||
func UnixNanoSecondToTime(nanoSecond int64) time.Time {
|
||||
return time.Unix(0, nanoSecond)
|
||||
}
|
||||
|
||||
//Get the current timestamp by Nano
|
||||
func GetCurrentTimestampByNano() int64 {
|
||||
return time.Now().UnixNano()
|
||||
}
|
||||
|
||||
//Get the current timestamp by Mill
|
||||
func GetCurrentTimestampByMill() int64 {
|
||||
return time.Now().UnixNano() / 1e6
|
||||
}
|
||||
|
||||
//Get the timestamp at 0 o'clock of the day
|
||||
func GetCurDayZeroTimestamp() int64 {
|
||||
timeStr := time.Now().Format("2006-01-02")
|
||||
t, _ := time.Parse("2006-01-02", timeStr)
|
||||
return t.Unix() - TimeOffset
|
||||
}
|
||||
|
||||
//Get the timestamp at 12 o'clock on the day
|
||||
func GetCurDayHalfTimestamp() int64 {
|
||||
return GetCurDayZeroTimestamp() + HalfOffset
|
||||
|
||||
}
|
||||
|
||||
//Get the formatted time at 0 o'clock of the day, the format is "2006-01-02_00-00-00"
|
||||
func GetCurDayZeroTimeFormat() string {
|
||||
return time.Unix(GetCurDayZeroTimestamp(), 0).Format("2006-01-02_15-04-05")
|
||||
}
|
||||
|
||||
//Get the formatted time at 12 o'clock of the day, the format is "2006-01-02_12-00-00"
|
||||
func GetCurDayHalfTimeFormat() string {
|
||||
return time.Unix(GetCurDayZeroTimestamp()+HalfOffset, 0).Format("2006-01-02_15-04-05")
|
||||
}
|
||||
func GetTimeStampByFormat(datetime string) string {
|
||||
timeLayout := "2006-01-02 15:04:05"
|
||||
loc, _ := time.LoadLocation("Local")
|
||||
tmp, _ := time.ParseInLocation(timeLayout, datetime, loc)
|
||||
timestamp := tmp.Unix()
|
||||
return strconv.FormatInt(timestamp, 10)
|
||||
}
|
||||
|
||||
func TimeStringFormatTimeUnix(timeFormat string, timeSrc string) int64 {
|
||||
tm, _ := time.Parse(timeFormat, timeSrc)
|
||||
return tm.Unix()
|
||||
}
|
||||
Reference in New Issue
Block a user