Merge branch 'dev' into fix_join_group

pull/62/head
Gordon 4 years ago committed by GitHub
commit 06382d88d5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,71 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ main ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ main ]
schedule:
- cron: '23 2 * * 2'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'go' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
# Learn more:
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

7
.gitignore vendored

@ -1,2 +1,9 @@
bin
logs
.devcontainer
components
logs
out-test
.github
tmp

@ -103,6 +103,53 @@ All images are available at https://hub.docker.com/r/lyt1123/open_im_server
![OpenIMServersondockerpng](https://github.com/OpenIMSDK/Open-IM-Server/blob/main/docs/Open-IM-Servers-on-docker.png)
#### How to develop
1. Install [Go environment](https://golang.org/doc/install). Make sure Go version is at least 1.15.
2. Install `Nodejs` and `pm2`
```
curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash -
npm install pm2 -g
```
2. Clone the Open-IM project to your server.
```
git clone https://github.com/OpenIMSDK/Open-IM-Server.git --recursive
```
3. Start Service.
```
# run etcd/mongodb/mysql/redis/kafka
docker-compose -f docker-compose.local.yaml up -d
# run open-im services
pm2 start app.yaml --watch
pm2 ls
pm2 logs
```
or try with `docker-compose`
```
docker-compose -f docker-compose.dev.yaml up -d
docker-compose -f docker-compose.dev.yaml ps
docker-compose -f docker-compose.dev.yaml logs -f
```
### Api Swagger
run service by `pm2` firstly, then run visit `[ip]:10000/swagger/index.html`
run following command to generate swagger docs
```
go get -u github.com/swaggo/swag/cmd/swag
export PATH=$(go env GOPATH)/bin:$PATH
swag init --generalInfo cmd/open_im_api/main.go
```
### CONFIGURATION INSTRUCTIONS
> Open-IM configuration is divided into basic component configuration and business internal service configuration. Developers need to fill in the address of each component as the address of their server component when using the product, and ensure that the internal service port of the business is not occupied

@ -0,0 +1,44 @@
apps:
- name: open_im_api
script: "go run main.go"
cwd: "cmd/open_im_api"
env:
OPEN_IM_SWAGGER_API: true
watch: ["docs", "cmd", "internal", "pkg"]
- name: open_im_auth
script: "go run main.go"
cwd: "cmd/rpc/open_im_auth"
- name: open_im_offline_msg
script: "go run main.go"
cwd: "cmd/rpc/open_im_msg"
- name: open_im_friend
script: "go run main.go"
cwd: "cmd/rpc/open_im_friend"
- name: open_im_group
script: "go run main.go"
cwd: "cmd/rpc/open_im_group"
- name: open_im_user
script: "go run main.go"
cwd: "cmd/rpc/open_im_user"
- name: open_im_push
script: "go run main.go"
cwd: "cmd/open_im_push"
- name: open_im_timed_task
script: "go run main.go"
cwd: "cmd/open_im_timer_task"
- name: open_im_msg_transfer
script: "go run main.go"
cwd: "cmd/open_im_msg_transfer"
- name: open_im_msg_gateway
script: "go run main.go"
cwd: "cmd/open_im_msg_gateway"

@ -0,0 +1 @@
Subproject commit a85c10dbffbb797b5b2091e209ff67a5534b9bfc

@ -3,10 +3,11 @@
BINARY_NAME=open_im_api
BIN_DIR=../../bin/
all: gotool build
build:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-w -s"
run:
@go run ./

@ -1,6 +1,7 @@
package main
import (
docs "Open_IM/docs"
apiAuth "Open_IM/internal/api/auth"
apiChat "Open_IM/internal/api/chat"
"Open_IM/internal/api/friend"
@ -12,9 +13,12 @@ import (
"Open_IM/pkg/utils"
"flag"
"strconv"
"github.com/gin-gonic/gin"
//"syscall"
swaggerfiles "github.com/swaggo/files"
ginSwagger "github.com/swaggo/gin-swagger"
)
func main() {
@ -29,6 +33,12 @@ func main() {
//log.Info("", "", "api server running...")
r := gin.Default()
r.Use(utils.CorsHandler())
if os.Getenv("OPEN_IM_SWAGGER_API") == "true" {
docs.SwaggerInfo.BasePath = "/"
r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerfiles.Handler))
}
// user routing group, which handles user registration and login services
userRouterGroup := r.Group("/user")
{
@ -84,9 +94,10 @@ func main() {
//Message
chatGroup := r.Group("/chat")
{
chatGroup.POST("/newest_seq", apiChat.UserNewestSeq)
chatGroup.POST("/newest_seq", apiChat.UserGetSeq)
chatGroup.POST("/pull_msg", apiChat.UserPullMsg)
chatGroup.POST("/send_msg", apiChat.UserSendMsg)
chatGroup.POST("/pull_msg_by_seq", apiChat.UserPullMsgBySeqList)
}
//Manager
managementGroup := r.Group("/manager")
@ -98,5 +109,6 @@ func main() {
log.NewPrivateLog("api")
ginPort := flag.Int("port", 10000, "get ginServerPort from cmd,default 10000 as port")
flag.Parse()
r.Run(utils.ServerIP + ":" + strconv.Itoa(*ginPort))
}

@ -7,8 +7,8 @@ import (
)
func main() {
rpcPort := flag.Int("rpc_port", 10500, "rpc listening port")
wsPort := flag.Int("ws_port", 10800, "ws listening port")
rpcPort := flag.Int("rpc_port", 10400, "rpc listening port")
wsPort := flag.Int("ws_port", 17778, "ws listening port")
flag.Parse()
var wg sync.WaitGroup
wg.Add(1)

@ -3,6 +3,7 @@
BINARY_NAME=open_im_msg_transfer
BIN_DIR=../../bin/
all: gotool build
build:

@ -7,7 +7,7 @@ import (
)
func main() {
rpcPort := flag.Int("port", -1, "rpc listening port")
rpcPort := flag.Int("port", 10700, "rpc listening port")
flag.Parse()
var wg sync.WaitGroup
wg.Add(1)

@ -1,42 +0,0 @@
package main
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/db"
"fmt"
"time"
)
func main() {
for {
fmt.Println("start delete mongodb expired record")
timeUnixBegin := time.Now().Unix()
count, _ := db.DB.MgoUserCount()
fmt.Println("mongodb record count: ", count)
for i := 0; i < count; i++ {
time.Sleep(1 * time.Millisecond)
uid, _ := db.DB.MgoSkipUID(i)
fmt.Println("operate uid: ", uid)
err := db.DB.DelUserChat(uid)
if err != nil {
fmt.Println("operate uid failed: ", uid, err.Error())
}
}
timeUnixEnd := time.Now().Unix()
costTime := timeUnixEnd - timeUnixBegin
if costTime > int64(config.Config.Mongo.DBRetainChatRecords*24*3600) {
continue
} else {
sleepTime := 0
if int64(config.Config.Mongo.DBRetainChatRecords*24*3600)-costTime > 24*3600 {
sleepTime = 24 * 3600
} else {
sleepTime = config.Config.Mongo.DBRetainChatRecords*24*3600 - int(costTime)
}
fmt.Println("sleep: ", sleepTime)
time.Sleep(time.Duration(sleepTime) * time.Second)
}
}
}

@ -0,0 +1,25 @@
.PHONY: all build run gotool install clean help
BINARY_NAME=open_im_timer_task
BIN_DIR=../../bin/
all: gotool build
build:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-w -s"
run:
@go run ./
gotool:
go fmt ./
go vet ./
install:
make build
mv ${BINARY_NAME} ${BIN_DIR}
clean:
@if [ -f ${BINARY_NAME} ] ; then rm ${BINARY_NAME} ; fi

@ -0,0 +1,65 @@
package main
import (
commonDB "Open_IM/pkg/common/db"
"Open_IM/pkg/common/db/mysql_model/im_mysql_model"
"Open_IM/pkg/common/log"
"time"
)
func main() {
log.NewPrivateLog("timer")
//for {
// fmt.Println("start delete mongodb expired record")
// timeUnixBegin := time.Now().Unix()
// count, _ := db.DB.MgoUserCount()
// fmt.Println("mongodb record count: ", count)
// for i := 0; i < count; i++ {
// time.Sleep(1 * time.Millisecond)
// uid, _ := db.DB.MgoSkipUID(i)
// fmt.Println("operate uid: ", uid)
// err := db.DB.DelUserChat(uid)
// if err != nil {
// fmt.Println("operate uid failed: ", uid, err.Error())
// }
// }
//
// timeUnixEnd := time.Now().Unix()
// costTime := timeUnixEnd - timeUnixBegin
// if costTime > int64(config.Config.Mongo.DBRetainChatRecords*24*3600) {
// continue
// } else {
// sleepTime := 0
// if int64(config.Config.Mongo.DBRetainChatRecords*24*3600)-costTime > 24*3600 {
// sleepTime = 24 * 3600
// } else {
// sleepTime = config.Config.Mongo.DBRetainChatRecords*24*3600 - int(costTime)
// }
// fmt.Println("sleep: ", sleepTime)
// time.Sleep(time.Duration(sleepTime) * time.Second)
// }
//}
for {
uidList, err := im_mysql_model.SelectAllUID()
if err != nil {
log.NewError("999999", err.Error())
} else {
for _, v := range uidList {
minSeq, err := commonDB.DB.GetMinSeqFromMongo(v)
if err != nil {
log.NewError("999999", "get user minSeq err", err.Error(), v)
continue
} else {
err := commonDB.DB.SetUserMinSeq(v, minSeq)
if err != nil {
log.NewError("999999", "set user minSeq err", err.Error(), v)
}
}
time.Sleep(time.Duration(100) * time.Millisecond)
}
}
}
}

@ -6,7 +6,7 @@ BIN_DIR=../../../bin/
all: gotool build
build:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-w -s"
run:
@go run ./

@ -6,7 +6,7 @@ import (
)
func main() {
rpcPort := flag.Int("port", 10600, "RpcToken default listen port 10800")
rpcPort := flag.Int("port", 10600, "RpcToken default listen port 10600")
flag.Parse()
rpcServer := rpcAuth.NewRpcAuthServer(*rpcPort)
rpcServer.Run()

@ -6,7 +6,7 @@ BIN_DIR=../../../bin/
all: gotool build
build:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-w -s"
run:
@go run ./

@ -6,7 +6,7 @@ BIN_DIR=../../../bin/
all: gotool build
build:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-w -s"
run:
@go run ./

@ -2,13 +2,12 @@ package main
import (
rpcChat "Open_IM/internal/rpc/chat"
"Open_IM/pkg/utils"
"flag"
)
func main() {
rpcPort := flag.String("port", "", "rpc listening port")
rpcPort := flag.Int("port", 10300, "rpc listening port")
flag.Parse()
rpcServer := rpcChat.NewRpcChatServer(utils.StringToInt(*rpcPort))
rpcServer := rpcChat.NewRpcChatServer(*rpcPort)
rpcServer.Run()
}

@ -6,7 +6,7 @@ BIN_DIR=../../../bin/
all: gotool build
build:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-w -s"
run:
@go run ./

@ -0,0 +1,147 @@
# The class cannot be named by Pascal or camel case.
# If it is not used, the corresponding structure will not be set,
# and it will not be read naturally.
serverversion: 1.0.0
#---------------Infrastructure configuration---------------------#
etcd:
etcdSchema: openIM
etcdAddr: [ etcd:2379 ]
mysql:
dbMysqlAddress: [ mysql:3306 ]
dbMysqlUserName: root
dbMysqlPassword: openIM
dbMysqlDatabaseName: openIM
dbTableName: eMsg
dbMsgTableNum: 1
dbMaxOpenConns: 20
dbMaxIdleConns: 10
dbMaxLifeTime: 120
mongo:
dbAddress: [ mongodb:27017 ]
dbDirect: false
dbTimeout: 10
dbDatabase: openIM
dbSource: admin
dbUserName:
dbPassword:
dbMaxPoolSize: 20
dbRetainChatRecords: 7
redis:
dbAddress: redis:6379
dbMaxIdle: 128
dbMaxActive: 0
dbIdleTimeout: 120
dbPassWord: openIM
kafka:
ws2mschat:
addr: [ kafka:9092 ]
topic: "ws2ms_chat"
ms2pschat:
addr: [ kafka:9092 ]
topic: "ms2ps_chat"
consumergroupid:
msgToMongo: mongo
msgToMySql: mysql
msgToPush: push
#---------------Internal service configuration---------------------#
# The service ip default is empty,
# automatically obtain the machine's valid network card ip as the service ip,
# otherwise the configuration ip is preferred
serverip:
api:
openImApiPort: [ 10000 ]
sdk:
openImSdkWsPort: [ 30000 ]
credential:
tencent:
appID: 1302656840
region: ap-chengdu
bucket: echat-1302656840
secretID: AKIDGNYVChzIQinu7QEgtNp0hnNgqcV8vZTC
secretKey: kz15vW83qM6dBUWIq681eBZA0c0vlIbe
rpcport:
openImUserPort: [ 10100 ]
openImFriendPort: [ 10200 ]
openImOfflineMessagePort: [ 10300 ]
openImOnlineRelayPort: [ 10400 ]
openImGroupPort: [ 10500 ]
openImAuthPort: [ 10600 ]
openImPushPort: [ 10700 ]
rpcregistername:
openImUserName: User
openImFriendName: Friend
openImOfflineMessageName: OfflineMessage
openImPushName: Push
openImOnlineMessageRelayName: OnlineMessageRelay
openImGroupName: Group
openImAuthName: Auth
log:
storageLocation: ../logs/
rotationTime: 24
remainRotationCount: 5
remainLogLevel: 6
elasticSearchSwitch: false
elasticSearchAddr: [ 127.0.0.1:9201 ]
elasticSearchUser: ""
elasticSearchPassword: ""
modulename:
longConnSvrName: msg_gateway
msgTransferName: msg_transfer
pushName: push
longconnsvr:
openImWsPort: [ 17778 ]
websocketMaxConnNum: 10000
websocketMaxMsgLen: 4096
websocketTimeOut: 10
push:
tpns:
ios:
accessID: 1600018281
secretKey: 3cd68a77a95b89e5089a1aca523f318f
android:
accessID: 111
secretKey: 111
jpns:
appKey: 2783339cee4de379cc798fe1
masterSecret: 66e5f309e032c68cc668c28a
pushUrl: "https://api.jpush.cn/v3/push"
manager:
appManagerUid: ["openIM123456","openIM654321"]
secrets: ["openIM1","openIM2"]
secret: tuoyun
multiloginpolicy:
onlyOneTerminalAccess: false
mobileAndPCTerminalAccessButOtherTerminalKickEachOther: true
allTerminalAccess: false
#token config
tokenpolicy:
accessSecret: "open_im_server"
# Token effective time seconds as a unit
#Seven days 7*24*60*60
accessExpire: 604800
messagecallback:
callbackSwitch: false
callbackUrl: "http://www.xxx.com/msg/judge"

@ -1,16 +1,16 @@
# The class cannot be named by Pascal or camel case.
# If it is not used, the corresponding structure will not be set,
# and it will not be read naturally.
serverversion: 1.0.3
#---------------Infrastructure configuration---------------------#
etcd:
etcdSchema: openIM
etcdAddr: [ 81.68.126.69:2379 ]
etcdAddr: [ 127.0.0.1:2379 ]
mysql:
dbMysqlAddress: [ 81.68.126.69:13306 ]
dbMysqlUserName: openIM
dbMysqlPassword: 12345
dbMysqlAddress: [ 127.0.0.1:3306 ]
dbMysqlUserName: root
dbMysqlPassword: openIM
dbMysqlDatabaseName: openIM
dbTableName: eMsg
dbMsgTableNum: 1
@ -19,18 +19,18 @@ mysql:
dbMaxLifeTime: 120
mongo:
dbAddress: [ 81.68.126.69:27017 ]
dbAddress: [ 127.0.0.1:27017 ]
dbDirect: false
dbTimeout: 10
dbDatabase: openIM
dbSource: openIM
dbUserName: openIM
dbPassword: 12345
dbSource: admin
dbUserName:
dbPassword:
dbMaxPoolSize: 20
dbRetainChatRecords: 7
redis:
dbAddress: 81.68.126.69:16379
dbAddress: 127.0.0.1:6379
dbMaxIdle: 128
dbMaxActive: 0
dbIdleTimeout: 120
@ -38,10 +38,10 @@ redis:
kafka:
ws2mschat:
addr: [ 81.68.126.69:9092 ]
addr: [ 127.0.0.1:9092 ]
topic: "ws2ms_chat"
ms2pschat:
addr: [ 81.68.126.69:9092 ]
addr: [ 127.0.0.1:9092 ]
topic: "ms2ps_chat"
consumergroupid:
msgToMongo: mongo
@ -74,7 +74,7 @@ credential:
rpcport:
openImUserPort: [ 10100 ]
openImFriendPort: [ 10200 ]
openImOfflineMessagePort: [ 10300 ]
openImOfflineMessagePort: [ 10300]
openImOnlineRelayPort: [ 10400 ]
openImGroupPort: [ 10500 ]
openImAuthPort: [ 10600 ]
@ -119,6 +119,10 @@ push:
android:
accessID: 111
secretKey: 111
jpns:
appKey: cf47465a368f24c659608e7e
masterSecret: 02204efe3f3832947a236ee5
pushUrl: "https://api.jpush.cn/v3/push"
manager:
appManagerUid: ["openIM123456","openIM654321"]
secrets: ["openIM1","openIM2"]
@ -133,9 +137,8 @@ multiloginpolicy:
#token config
tokenpolicy:
accessSecret: "open_im_server"
# Token effective time seconds as a unit
#Seven days 7*24*60*60
accessExpire: 604800
# Token effective time day as a unit
accessExpire: 7
messagecallback:
callbackSwitch: false

@ -0,0 +1,11 @@
FROM golang:1.16 as base
FROM base as dev
ENV GO111MODULE=on
ENV GOPROXY=https://goproxy.cn,direct
RUN curl -sSfL https://raw.githubusercontent.com/cosmtrek/air/master/install.sh | sh -s -- -b $(go env GOPATH)/bin
CMD ["air"]

@ -0,0 +1,381 @@
version: "3"
services:
mysql:
image: mysql:5.7
ports:
- 3306:3306
container_name: mysql
volumes:
- ./components/mysql/data:/var/lib/mysql
- /etc/localtime:/etc/localtime
environment:
MYSQL_ROOT_PASSWORD: openIM
restart: always
mongodb:
image: mongo:4.0
ports:
- 27017:27017
container_name: mongo
volumes:
- ./components/mongodb/data:/data/db
environment:
TZ: Asia/Shanghai
restart: always
redis:
image: redis
ports:
- 6379:6379
container_name: redis
volumes:
- ./components/redis/data:/data
#redis config file
#- ./components/redis/config/redis.conf:/usr/local/redis/config/redis.conf
environment:
TZ: Asia/Shanghai
restart: always
sysctls:
net.core.somaxconn: 1024
command: redis-server --requirepass openIM --appendonly yes
zookeeper:
image: wurstmeister/zookeeper
ports:
- 2181:2181
container_name: zookeeper
volumes:
- /etc/localtime:/etc/localtime
environment:
TZ: Asia/Shanghai
restart: always
kafka:
image: wurstmeister/kafka
container_name: kafka
restart: always
environment:
TZ: Asia/Shanghai
KAFKA_BROKER_ID: 0
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092
KAFKA_LISTENERS: PLAINTEXT://kafka:9092
depends_on:
- zookeeper
links:
- zookeeper
ports:
- 9092:9092
etcd:
image: quay.io/coreos/etcd
ports:
- 2379:2379
- 2380:2380
container_name: etcd
volumes:
- /etc/timezone:/etc/timezone
- /etc/localtime:/etc/localtime
environment:
ETCDCTL_API: 3
restart: always
command: /usr/local/bin/etcd --name etcd0 --data-dir /etcd-data --listen-client-urls http://0.0.0.0:2379 --advertise-client-urls http://0.0.0.0:2379 --listen-peer-urls http://0.0.0.0:2380 --initial-advertise-peer-urls http://0.0.0.0:2380 --initial-cluster etcd0=http://0.0.0.0:2380 --initial-cluster-token tkn --initial-cluster-state new
open_im_api:
build:
dockerfile: dev.Dockerfile
context: .
target: dev
network: host
depends_on:
- kafka
- mysql
- mongodb
- redis
- etcd
container_name: open_im_api
volumes:
- ./cmd:/Open-IM-Server/cmd
- ./config/config.dev.yaml:/Open-IM-Server/config/config.yaml
- ./internal:/Open-IM-Server/internal
- ./pkg:/Open-IM-Server/pkg
- ./go.mod:/Open-IM-Server/go.mod
- ./go.sum:/Open-IM-Server/go.sum
working_dir: /Open-IM-Server/cmd/open_im_api
ports:
- 10000:10000
links:
- kafka
- mysql
- mongodb
- redis
- etcd
open_im_auth:
build:
dockerfile: dev.Dockerfile
context: .
target: dev
network: host
depends_on:
- kafka
- mysql
- mongodb
- redis
- etcd
links:
- kafka
- mysql
- mongodb
- redis
- etcd
container_name: open_im_auth
volumes:
- ./cmd:/Open-IM-Server/cmd
- ./config/config.dev.yaml:/Open-IM-Server/config/config.yaml
- ./internal:/Open-IM-Server/internal
- ./pkg:/Open-IM-Server/pkg
- ./go.mod:/Open-IM-Server/go.mod
- ./go.sum:/Open-IM-Server/go.sum
working_dir: /Open-IM-Server/cmd/rpc/open_im_auth
ports:
- 10600:10600
open_im_user:
build:
dockerfile: dev.Dockerfile
context: .
target: dev
network: host
depends_on:
- kafka
- mysql
- mongodb
- redis
- etcd
links:
- kafka
- mysql
- mongodb
- redis
- etcd
container_name: open_im_user
volumes:
- ./cmd:/Open-IM-Server/cmd
- ./config/config.dev.yaml:/Open-IM-Server/config/config.yaml
- ./internal:/Open-IM-Server/internal
- ./pkg:/Open-IM-Server/pkg
- ./go.mod:/Open-IM-Server/go.mod
- ./go.sum:/Open-IM-Server/go.sum
working_dir: /Open-IM-Server/cmd/rpc/open_im_user
ports:
- 10100:10100
open_im_friend:
build:
dockerfile: dev.Dockerfile
context: .
target: dev
network: host
depends_on:
- kafka
- mysql
- mongodb
- redis
- etcd
links:
- kafka
- mysql
- mongodb
- redis
- etcd
container_name: open_im_friend
volumes:
- ./cmd:/Open-IM-Server/cmd
- ./config/config.dev.yaml:/Open-IM-Server/config/config.yaml
- ./internal:/Open-IM-Server/internal
- ./pkg:/Open-IM-Server/pkg
- ./go.mod:/Open-IM-Server/go.mod
- ./go.sum:/Open-IM-Server/go.sum
working_dir: /Open-IM-Server/cmd/rpc/open_im_friend
ports:
- 10200:10200
open_im_group:
build:
dockerfile: dev.Dockerfile
context: .
target: dev
network: host
depends_on:
- kafka
- mysql
- mongodb
- redis
- etcd
links:
- kafka
- mysql
- mongodb
- redis
- etcd
container_name: open_im_group
volumes:
- ./cmd:/Open-IM-Server/cmd
- ./config/config.dev.yaml:/Open-IM-Server/config/config.yaml
- ./internal:/Open-IM-Server/internal
- ./pkg:/Open-IM-Server/pkg
- ./go.mod:/Open-IM-Server/go.mod
- ./go.sum:/Open-IM-Server/go.sum
working_dir: /Open-IM-Server/cmd/rpc/open_im_group
ports:
- 10500:10500
open_im_push:
build:
dockerfile: dev.Dockerfile
context: .
target: dev
network: host
depends_on:
- kafka
- mysql
- mongodb
- redis
- etcd
links:
- kafka
- mysql
- mongodb
- redis
- etcd
container_name: open_im_push
volumes:
- ./cmd:/Open-IM-Server/cmd
- ./config/config.dev.yaml:/Open-IM-Server/config/config.yaml
- ./internal:/Open-IM-Server/internal
- ./pkg:/Open-IM-Server/pkg
- ./go.mod:/Open-IM-Server/go.mod
- ./go.sum:/Open-IM-Server/go.sum
working_dir: /Open-IM-Server/cmd/open_im_push
ports:
- 10700:10700
open_im_timed_task:
build:
dockerfile: dev.Dockerfile
context: .
target: dev
network: host
depends_on:
- kafka
- mysql
- mongodb
- redis
- etcd
links:
- kafka
- mysql
- mongodb
- redis
- etcd
container_name: open_im_timed_task
volumes:
- ./cmd:/Open-IM-Server/cmd
- ./config/config.dev.yaml:/Open-IM-Server/config/config.yaml
- ./internal:/Open-IM-Server/internal
- ./pkg:/Open-IM-Server/pkg
- ./go.mod:/Open-IM-Server/go.mod
- ./go.sum:/Open-IM-Server/go.sum
working_dir: /Open-IM-Server/cmd/open_im_timer_task
open_im_offline_msg:
build:
dockerfile: dev.Dockerfile
context: .
target: dev
network: host
depends_on:
- kafka
- mysql
- mongodb
- redis
- etcd
links:
- kafka
- mysql
- mongodb
- redis
- etcd
container_name: open_im_offline_msg
volumes:
- ./cmd:/Open-IM-Server/cmd
- ./config/config.dev.yaml:/Open-IM-Server/config/config.yaml
- ./internal:/Open-IM-Server/internal
- ./pkg:/Open-IM-Server/pkg
- ./go.mod:/Open-IM-Server/go.mod
- ./go.sum:/Open-IM-Server/go.sum
working_dir: /Open-IM-Server/cmd/rpc/open_im_msg
ports:
- 10300:10300
open_im_msg_transfer:
build:
dockerfile: dev.Dockerfile
context: .
target: dev
network: host
depends_on:
- kafka
- mysql
- mongodb
- redis
- etcd
links:
- kafka
- mysql
- mongodb
- redis
- etcd
container_name: open_im_msg_transfer
volumes:
- ./cmd:/Open-IM-Server/cmd
- ./config/config.dev.yaml:/Open-IM-Server/config/config.yaml
- ./internal:/Open-IM-Server/internal
- ./pkg:/Open-IM-Server/pkg
- ./go.mod:/Open-IM-Server/go.mod
- ./go.sum:/Open-IM-Server/go.sum
working_dir: /Open-IM-Server/cmd/open_im_msg_transfer
open_im_msg_gateway:
build:
dockerfile: dev.Dockerfile
context: .
target: dev
network: host
depends_on:
- kafka
- mysql
- mongodb
- redis
- etcd
links:
- kafka
- mysql
- mongodb
- redis
- etcd
container_name: open_im_msg_gateway
volumes:
- ./cmd:/Open-IM-Server/cmd
- ./config/config.dev.yaml:/Open-IM-Server/config/config.yaml
- ./internal:/Open-IM-Server/internal
- ./pkg:/Open-IM-Server/pkg
- ./go.mod:/Open-IM-Server/go.mod
- ./go.sum:/Open-IM-Server/go.sum
working_dir: /Open-IM-Server/cmd/open_im_msg_gateway
ports:
- 10400:10400
- 17778:17778

@ -0,0 +1,85 @@
version: "3"
services:
mysql:
image: mysql:5.7
ports:
- 3306:3306
container_name: mysql
volumes:
- ./components/mysql/data:/var/lib/mysql
- /etc/localtime:/etc/localtime
environment:
MYSQL_ROOT_PASSWORD: openIM
restart: always
mongodb:
image: mongo:4.0
ports:
- 27017:27017
container_name: mongo
volumes:
- ./components/mongodb/data:/data/db
environment:
TZ: Asia/Shanghai
restart: always
redis:
image: redis
ports:
- 6379:6379
container_name: redis
volumes:
- ./components/redis/data:/data
#redis config file
#- ./components/redis/config/redis.conf:/usr/local/redis/config/redis.conf
environment:
TZ: Asia/Shanghai
restart: always
sysctls:
net.core.somaxconn: 1024
command: redis-server --requirepass openIM --appendonly yes
zookeeper:
image: wurstmeister/zookeeper
ports:
- 2181:2181
container_name: zookeeper
volumes:
- /etc/localtime:/etc/localtime
environment:
TZ: Asia/Shanghai
restart: always
kafka:
image: wurstmeister/kafka
container_name: kafka
restart: always
environment:
TZ: Asia/Shanghai
KAFKA_BROKER_ID: 0
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://127.0.0.1:9092
KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092
# network_mode: "host"
depends_on:
- zookeeper
links:
- zookeeper
ports:
- 9092:9092
etcd:
image: quay.io/coreos/etcd
ports:
- 2379:2379
- 2380:2380
container_name: etcd
volumes:
- /etc/timezone:/etc/timezone
- /etc/localtime:/etc/localtime
environment:
ETCDCTL_API: 3
restart: always
command: /usr/local/bin/etcd --name etcd0 --data-dir /etcd-data --listen-client-urls http://0.0.0.0:2379 --advertise-client-urls http://0.0.0.0:2379 --listen-peer-urls http://0.0.0.0:2380 --initial-advertise-peer-urls http://0.0.0.0:2380 --initial-cluster etcd0=http://0.0.0.0:2380 --initial-cluster-token tkn --initial-cluster-state new

@ -15,7 +15,7 @@ services:
restart: always
mongodb:
image: mongo
image: mongo:4.0
ports:
- 27017:27017
container_name: mongo

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -6,18 +6,21 @@ require (
github.com/Shopify/sarama v1.19.0
github.com/Shopify/toxiproxy v2.1.4+incompatible // indirect
github.com/antonfisher/nested-logrus-formatter v1.3.0
github.com/bwmarrin/snowflake v0.3.0
github.com/coreos/go-semver v0.3.0 // indirect
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect
github.com/dustin/go-humanize v1.0.0 // indirect
github.com/eapache/go-resiliency v1.2.0 // indirect
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 // indirect
github.com/eapache/queue v1.1.0 // indirect
github.com/frankban/quicktest v1.11.3 // indirect
github.com/frankban/quicktest v1.14.0 // indirect
github.com/garyburd/redigo v1.6.2
github.com/gin-gonic/gin v1.7.0
github.com/gin-gonic/gin v1.7.4
github.com/go-openapi/spec v0.20.4 // indirect
github.com/go-playground/validator/v10 v10.4.1
github.com/golang-jwt/jwt/v4 v4.1.0
github.com/golang/protobuf v1.5.2
github.com/golang/snappy v0.0.3 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/gorilla/websocket v1.4.2
github.com/jinzhu/gorm v1.9.16
github.com/jonboulle/clockwork v0.2.2 // indirect
@ -28,21 +31,25 @@ require (
github.com/mitchellh/mapstructure v1.4.1
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
github.com/olivere/elastic/v7 v7.0.23
github.com/pierrec/lz4 v2.6.0+incompatible // indirect
github.com/pierrec/lz4 v2.6.1+incompatible // indirect
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5
github.com/sirupsen/logrus v1.6.0
github.com/sirupsen/logrus v1.8.1
github.com/stretchr/testify v1.7.0
github.com/swaggo/files v0.0.0-20210815190702-a29dd2bc99b2 // indirect
github.com/swaggo/gin-swagger v1.3.3 // indirect
github.com/swaggo/swag v1.7.4 // indirect
github.com/tencentyun/qcloud-cos-sts-sdk v0.0.0-20210325043845-84a0811633ca
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 // indirect
go.etcd.io/etcd v0.0.0-20200402134248-51bdeb39e698
golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b
golang.org/x/tools v0.0.0-20210106214847-113979e3529a // indirect
golang.org/x/net v0.0.0-20211111160137-58aab5ef257a
golang.org/x/sys v0.0.0-20211112143042-c6105e7cf70d // indirect
golang.org/x/tools v0.1.7 // indirect
google.golang.org/grpc v1.33.2
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
sigs.k8s.io/yaml v1.2.0 // indirect
)
replace google.golang.org/grpc => google.golang.org/grpc v1.29.1

133
go.sum

@ -1,6 +1,12 @@
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/Shopify/sarama v1.19.0 h1:9oksLxC6uxVPHPVYUmq6xhr1BOF/hHobWH2UzO67z1s=
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
github.com/Shopify/toxiproxy v2.1.4+incompatible h1:TKdv8HiTLgE5wdJuEML90aBgNWsokNbMijUGhmcoBJc=
@ -15,6 +21,8 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24
github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bwmarrin/snowflake v0.3.0 h1:xm67bEhkKh6ij1790JB83OujPR5CzNe8QuQqAgISZN0=
github.com/bwmarrin/snowflake v0.3.0/go.mod h1:NdZxfVWX+oR6y2K0o6qAYv6gIOP9rjG0/E9WsDpxqwE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa h1:OaNxuTZr7kxeODyLWsRMC+OD03aFUH+mW6r2d+MWa5Y=
@ -24,7 +32,12 @@ github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmf
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd/v22 v22.0.0 h1:XJIw/+VlJ+87J+doOxznsAWIdmWuViOVhkQamW5YV28=
github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU=
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -48,32 +61,57 @@ github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
github.com/frankban/quicktest v1.11.3 h1:8sXhOn0uLys67V8EsXLc6eszDs8VXWxL3iRvebPhedY=
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
github.com/frankban/quicktest v1.14.0 h1:+cqqvzZV87b4adx/5ayVOaYZ2CrvM4ejQvUdBzPPUss=
github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og=
github.com/garyburd/redigo v1.6.2 h1:yE/pwKCrbLpLpQICzYTeZ7JsTA/C53wFTJHaEtRqniM=
github.com/garyburd/redigo v1.6.2/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gin-contrib/gzip v0.0.3/go.mod h1:YxxswVZIqOvcHEQpsSn+QF5guQtO1dCfy0shBPy4jFc=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
github.com/gin-gonic/gin v1.7.0 h1:jGB9xAJQ12AIGNB4HguylppmDK1Am9ppF7XnGXXJuoU=
github.com/gin-gonic/gin v1.7.0/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
github.com/gin-gonic/gin v1.7.4 h1:QmUZXrvJ9qZ3GfWvQ+2wnW/1ePrTEJqPKMYEU3lD/DM=
github.com/gin-gonic/gin v1.7.4/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonreference v0.19.5 h1:1WJP/wi4OjB4iV8KVbH73rQaoialJrqv8gitZLxGLtM=
github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
github.com/go-openapi/jsonreference v0.19.6 h1:UBIxjkht+AWIgYzCDSv2GN+E/togfwXUJFRTWhl2Jjs=
github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns=
github.com/go-openapi/spec v0.20.3 h1:uH9RQ6vdyPSs2pSy9fL8QPspDF2AMIMPtmK5coSSjtQ=
github.com/go-openapi/spec v0.20.3/go.mod h1:gG4F8wdEDN+YPBMVnzE85Rbhf+Th2DTvA9nFPQ5AYEg=
github.com/go-openapi/spec v0.20.4 h1:O8hJrt0UMnhHcluhIdUgCLRWyM2x7QkBXRvOs7m+O1M=
github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng=
github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM=
github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE=
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/golang-jwt/jwt/v4 v4.1.0 h1:XUgk2Ex5veyVFVeLm0xhusUTQybEbexJXrvPNOKkSY0=
github.com/golang-jwt/jwt/v4 v4.1.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
@ -94,8 +132,8 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA=
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
@ -103,9 +141,10 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.0.0 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA=
@ -141,15 +180,16 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc h1:RKf14vYWi2ttpEmkA4aQ3j4u9dStX2t4M8UM6qqNsG8=
@ -161,6 +201,9 @@ github.com/lestrrat-go/strftime v1.0.4/go.mod h1:E1nN3pCbtMSu1yjSVeyuRFVm/U0xoR7
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
@ -184,12 +227,13 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/olivere/elastic/v7 v7.0.23 h1:b7tjMogDMhf2CisGI+L02LXLVa0ZyE82Z15XfW1e8t8=
github.com/olivere/elastic/v7 v7.0.23/go.mod h1:OuWmD2DiuYhddWegBKPWQuelVKBLrW0fa/VUYgxuGTY=
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
github.com/pierrec/lz4 v2.6.0+incompatible h1:Ix9yFKn1nSPBLFl/yZknTp8TU5G4Ps0JDmguYK6iH1A=
github.com/pierrec/lz4 v2.6.0+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM=
github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@ -214,10 +258,19 @@ github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5 h1:mZHayPoR0lNmnH
github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5/go.mod h1:GEXHk5HgEKCvEIIrSpFI3ozzG5xOKA2DVlEX/gGnewM=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/smartystreets/assertions v1.1.1/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM=
github.com/smartystreets/gunit v1.4.2/go.mod h1:ZjM1ozSIMJlAz/ay4SG8PeKF00ckUp+zMHZXV9/bvak=
@ -231,8 +284,16 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14/go.mod h1:gxQT6pBGRuIGunNf/+tSOB5OHvguWi8Tbt82WOkf35E=
github.com/swaggo/files v0.0.0-20210815190702-a29dd2bc99b2 h1:+iNTcqQJy0OZ5jk6a5NLib47eqXK8uYcPX+O4+cBpEM=
github.com/swaggo/files v0.0.0-20210815190702-a29dd2bc99b2/go.mod h1:lKJPbtWzJ9JhsTN1k1gZgleJWY/cqq0psdoMmaThG3w=
github.com/swaggo/gin-swagger v1.3.3 h1:XHyYmeNVFG5PbyWHG4jXtxOm2P4kiZapDCWsyDDiQ/I=
github.com/swaggo/gin-swagger v1.3.3/go.mod h1:ymsZuGpbbu+S7ZoQ49QPpZoDBj6uqhb8WizgQPVgWl0=
github.com/swaggo/swag v1.7.4 h1:up+ixy8yOqJKiFcuhMgkuYuF4xnevuhnFAXXF8OSfNg=
github.com/swaggo/swag v1.7.4/go.mod h1:zD8h6h4SPv7t3l+4BKdRquqW1ASWjKZgT6Qv9z3kNqI=
github.com/tencentyun/qcloud-cos-sts-sdk v0.0.0-20210325043845-84a0811633ca h1:G/aIr3WiUesWHL2YGYgEqjM5tCAJ43Ml+0C18wDkWWs=
github.com/tencentyun/qcloud-cos-sts-sdk v0.0.0-20210325043845-84a0811633ca/go.mod h1:b18KQa4IxHbxeseW1GcZox53d7J0z39VNONTxvvlkXw=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
@ -242,10 +303,14 @@ github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M=
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go.etcd.io/bbolt v1.3.4 h1:hi1bXHMVrlQh6WwxAy+qZCV/SYIlqo+Ushwdpa4tAKg=
go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
go.etcd.io/etcd v0.0.0-20200402134248-51bdeb39e698 h1:jWtjCJX1qxhHISBMLRztWwR+EXkI7MJAF2HjHAE/x/I=
@ -277,6 +342,7 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -286,31 +352,52 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM=
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210917221730-978cfadd31cf h1:R150MpwJIv1MpS0N/pc+NhTM8ajzvlmxlY5OYsrevXQ=
golang.org/x/net v0.0.0-20210917221730-978cfadd31cf/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211111160137-58aab5ef257a h1:c83jeVQW0KGKNaKBRfelNYNHaev+qawl9yaA825s8XE=
golang.org/x/net v0.0.0-20211111160137-58aab5ef257a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da h1:b3NXsE2LusjYGGjL5bxEVZZORm/YEFFrWFjR8eFrw/c=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211112143042-c6105e7cf70d h1:jp6PtFmjL+vGsuzd86xYqaJGv6eXdLvmVGzVVLI6EPI=
golang.org/x/sys v0.0.0-20211112143042-c6105e7cf70d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2 h1:+DCIGbF/swA92ohVg0//6X2IVY3KZs6p9mix0ziNYJM=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@ -323,6 +410,10 @@ golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a h1:CB3a9Nez8M13wwlr/E2YtwoU+qYHKfC+JrDa45RXXoQ=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.7 h1:6j8CgantCy3yc8JGBqkDLMKWqZ0RDU2g1HVgacojGWQ=
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -347,6 +438,7 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 h1:VpOs+IwYnYBaFnrNAeB8UUWtL3vEUnzSCL1nVjPhqrw=
@ -355,10 +447,15 @@ gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=

@ -1,16 +1,17 @@
package apiAuth
import (
pbAuth "Open_IM/pkg/proto/auth"
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbAuth "Open_IM/pkg/proto/auth"
"context"
"github.com/gin-gonic/gin"
"net/http"
"strings"
"github.com/gin-gonic/gin"
)
// paramsUserRegister struct
type paramsUserRegister struct {
Secret string `json:"secret" binding:"required,max=32"`
Platform int32 `json:"platform" binding:"required,min=1,max=7"`
@ -24,6 +25,13 @@ type paramsUserRegister struct {
Ex string `json:"ex" binding:"omitempty,max=1024"`
}
// resultUserRegister struct
type resultUserRegister struct {
UID string `json:"uid"`
Token string `json:"token"`
ExpiredTime int64 `json:"expiredTime"`
}
func newUserRegisterReq(params *paramsUserRegister) *pbAuth.UserRegisterReq {
pbData := pbAuth.UserRegisterReq{
UID: params.UID,
@ -38,9 +46,20 @@ func newUserRegisterReq(params *paramsUserRegister) *pbAuth.UserRegisterReq {
return &pbData
}
// @Summary
// @Schemes
// @Description register a new user
// @Tags auth
// @Accept json
// @Produce json
// @Param body body apiAuth.paramsUserRegister true "new user params"
// @Success 200 {object} user.result{data=apiAuth.resultUserRegister}
// @Failure 400 {object} user.result
// @Failure 500 {object} user.result
// @Router /auth/user_register [post]
func UserRegister(c *gin.Context) {
log.Info("", "", "api user_register init ....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImAuthName)
etcdConn := getcdv3.GetAuthConn()
client := pbAuth.NewAuthClient(etcdConn)
//defer etcdConn.Close()
@ -49,6 +68,10 @@ func UserRegister(c *gin.Context) {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
return
}
if params.Secret != config.Config.Secret {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 401, "errMsg": "not authorized"})
return
}
pbData := newUserRegisterReq(&params)
log.Info("", "", "api user_register is server, [data: %s]", pbData.String())

@ -0,0 +1,25 @@
package apiAuth
import (
"bytes"
"net/http"
"net/http/httptest"
"testing"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
)
func init() {
gin.SetMode(gin.TestMode)
}
func Test_UserRegister(t *testing.T) {
res := httptest.NewRecorder()
c, _ := gin.CreateTestContext(res)
c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString(`{"secret": "tuoyun", "platform": 1, "uid": "3", "name": "1"}`))
UserRegister(c)
assert.Equal(t, res.Code, 200)
}

@ -1,16 +1,17 @@
package apiAuth
import (
pbAuth "Open_IM/pkg/proto/auth"
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbAuth "Open_IM/pkg/proto/auth"
"context"
"github.com/gin-gonic/gin"
"net/http"
"strings"
"github.com/gin-gonic/gin"
)
// paramsUserToken struct
type paramsUserToken struct {
Secret string `json:"secret" binding:"required,max=32"`
Platform int32 `json:"platform" binding:"required,min=1,max=8"`
@ -25,9 +26,20 @@ func newUserTokenReq(params *paramsUserToken) *pbAuth.UserTokenReq {
return &pbData
}
// @Summary
// @Schemes
// @Description get token
// @Tags auth
// @Accept json
// @Produce json
// @Param body body apiAuth.paramsUserToken true "get token params"
// @Success 200 {object} user.result{data=apiAuth.resultUserRegister}
// @Failure 400 {object} user.result
// @Failure 500 {object} user.result
// @Router /auth/user_token [post]
func UserToken(c *gin.Context) {
log.Info("", "", "api user_token init ....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImAuthName)
etcdConn := getcdv3.GetAuthConn()
client := pbAuth.NewAuthClient(etcdConn)
//defer etcdConn.Close()
@ -37,6 +49,10 @@ func UserToken(c *gin.Context) {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
return
}
if params.Secret != config.Config.Secret {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 401, "errMsg": "not authorized"})
return
}
pbData := newUserTokenReq(&params)
log.Info("", "", "api user_token is server, [data: %s]", pbData.String())

@ -1,17 +1,17 @@
package apiChat
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbMsg "Open_IM/pkg/proto/chat"
"Open_IM/pkg/utils"
"context"
"github.com/gin-gonic/gin"
"net/http"
"strings"
"github.com/gin-gonic/gin"
)
// paramsUserNewestSeq struct
type paramsUserNewestSeq struct {
ReqIdentifier int `json:"reqIdentifier" binding:"required"`
SendID string `json:"sendID" binding:"required"`
@ -19,7 +19,31 @@ type paramsUserNewestSeq struct {
MsgIncr int `json:"msgIncr" binding:"required"`
}
func UserNewestSeq(c *gin.Context) {
// resultUserNewestSeq struct
type resultUserNewestSeq struct {
ErrCode int32 `json:"errCode`
ErrMsg string `json:"errMsg"`
MsgIncr int `json:"msgIncr"`
ReqIdentifier int `json:"reqIdentifier"`
Data struct {
MaxSeq int64 `json:"maxSeq,omitempty"`
MinSeq int64 `json:"minSeq,omitempty"`
} `json:"data"`
}
// @Summary
// @Schemes
// @Description get latest message seq
// @Tags chat
// @Accept json
// @Produce json
// @Param body body apiChat.paramsUserNewestSeq true "user get latest seq params"
// @Param token header string true "token"
// @Success 200 {object} apiChat.resultUserNewestSeq
// @Failure 400 {object} user.result
// @Failure 500 {object} user.result
// @Router /chat/newest_seq [post]
func UserGetSeq(c *gin.Context) {
params := paramsUserNewestSeq{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
@ -31,18 +55,19 @@ func UserNewestSeq(c *gin.Context) {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": "token validate err"})
return
}
pbData := pbMsg.GetNewSeqReq{}
pbData := pbMsg.GetMaxAndMinSeqReq{}
pbData.UserID = params.SendID
pbData.OperationID = params.OperationID
grpcConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImOfflineMessageName)
grpcConn := getcdv3.GetOfflineMessageConn()
if grpcConn == nil {
log.ErrorByKv("get grpcConn err", pbData.OperationID, "args", params)
}
msgClient := pbMsg.NewChatClient(grpcConn)
reply, err := msgClient.GetNewSeq(context.Background(), &pbData)
reply, err := msgClient.GetMaxAndMinSeq(context.Background(), &pbData)
if err != nil {
log.ErrorByKv("rpc call failed to getNewSeq", pbData.OperationID, "err", err, "pbData", pbData.String())
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": err.Error()})
return
}
@ -52,7 +77,8 @@ func UserNewestSeq(c *gin.Context) {
"msgIncr": params.MsgIncr,
"reqIdentifier": params.ReqIdentifier,
"data": gin.H{
"seq": reply.Seq,
"maxSeq": reply.MaxSeq,
"minSeq": reply.MinSeq,
},
})

@ -1,17 +1,17 @@
package apiChat
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
"Open_IM/pkg/proto/chat"
pbChat "Open_IM/pkg/proto/chat"
"Open_IM/pkg/utils"
"context"
"github.com/gin-gonic/gin"
"net/http"
"strings"
"github.com/gin-gonic/gin"
)
// paramsUserPullMsg struct
type paramsUserPullMsg struct {
ReqIdentifier *int `json:"reqIdentifier" binding:"required"`
SendID string `json:"sendID" binding:"required"`
@ -22,6 +22,18 @@ type paramsUserPullMsg struct {
}
}
// @Summary
// @Schemes
// @Description user pull messages
// @Tags chat
// @Accept json
// @Produce json
// @Param body body apiChat.paramsUserPullMsg true "user pull messages"
// @Param token header string true "token"
// @Success 200 {object} user.result{reqIdentifier=int}
// @Failure 400 {object} user.result
// @Failure 500 {object} user.result
// @Router /chat/pull_msg [post]
func UserPullMsg(c *gin.Context) {
params := paramsUserPullMsg{}
if err := c.BindJSON(&params); err != nil {
@ -39,7 +51,7 @@ func UserPullMsg(c *gin.Context) {
pbData.OperationID = params.OperationID
pbData.SeqBegin = *params.Data.SeqBegin
pbData.SeqEnd = *params.Data.SeqEnd
grpcConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImOfflineMessageName)
grpcConn := getcdv3.GetOfflineMessageConn()
msgClient := pbChat.NewChatClient(grpcConn)
reply, err := msgClient.PullMessage(context.Background(), &pbData)
if err != nil {
@ -70,3 +82,72 @@ func UserPullMsg(c *gin.Context) {
})
}
// paramsUserPullMsgBySeqList struct
type paramsUserPullMsgBySeqList struct {
ReqIdentifier int `json:"reqIdentifier" binding:"required"`
SendID string `json:"sendID" binding:"required"`
OperationID string `json:"operationID" binding:"required"`
SeqList []int64 `json:"seqList"`
}
// @Summary
// @Schemes
// @Description user pull msg by seq
// @Tags chat
// @Accept json
// @Produce json
// @Param body body apiChat.paramsUserPullMsgBySeqList true "pull msg by seq"
// @Param token header string true "token"
// @Success 200 {object} user.result{reqIdentifier=int}
// @Failure 400 {object} user.result
// @Failure 500 {object} user.result
// @Router /chat/pull_msg_by_seq [post]
func UserPullMsgBySeqList(c *gin.Context) {
params := paramsUserPullMsgBySeqList{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
return
}
token := c.Request.Header.Get("token")
if !utils.VerifyToken(token, params.SendID) {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": "token validate err"})
return
}
pbData := pbChat.PullMessageBySeqListReq{}
pbData.UserID = params.SendID
pbData.OperationID = params.OperationID
pbData.SeqList = params.SeqList
grpcConn := getcdv3.GetOfflineMessageConn()
msgClient := pbChat.NewChatClient(grpcConn)
reply, err := msgClient.PullMessageBySeqList(context.Background(), &pbData)
if err != nil {
log.ErrorByKv("PullMessageBySeqList error", pbData.OperationID, "err", err.Error())
c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": err.Error()})
return
}
log.InfoByKv("rpc call success to PullMessageBySeqList", pbData.OperationID, "ReplyArgs", reply.String(), "maxSeq", reply.GetMaxSeq(),
"MinSeq", reply.GetMinSeq(), "singLen", len(reply.GetSingleUserMsg()), "groupLen", len(reply.GetGroupUserMsg()))
msg := make(map[string]interface{})
if v := reply.GetSingleUserMsg(); v != nil {
msg["single"] = v
} else {
msg["single"] = []pbChat.GatherFormat{}
}
if v := reply.GetGroupUserMsg(); v != nil {
msg["group"] = v
} else {
msg["group"] = []pbChat.GatherFormat{}
}
msg["maxSeq"] = reply.GetMaxSeq()
msg["minSeq"] = reply.GetMinSeq()
c.JSON(http.StatusOK, gin.H{
"errCode": reply.ErrCode,
"errMsg": reply.ErrMsg,
"reqIdentifier": params.ReqIdentifier,
"data": msg,
})
}

@ -1,18 +1,18 @@
package apiChat
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
pbChat "Open_IM/pkg/proto/chat"
"Open_IM/pkg/utils"
"context"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
"github.com/gin-gonic/gin"
"net/http"
"strings"
"github.com/gin-gonic/gin"
)
// paramsUserSendMsg struct
type paramsUserSendMsg struct {
ReqIdentifier int32 `json:"reqIdentifier" binding:"required"`
PlatformID int32 `json:"platformID" binding:"required"`
@ -57,6 +57,24 @@ func newUserSendMsgReq(token string, params *paramsUserSendMsg) *pbChat.UserSend
return &pbData
}
// resultSendMsg struct
type resultSendMsg struct {
ClientMsgID string `json:"clientMsgID"`
ServerMsgID string `json:"serverMsgID"`
SendTime int64 `json:"sendTime"`
}
// @Summary
// @Schemes
// @Description user send messages
// @Tags chat
// @Accept json
// @Produce json
// @Param body body apiChat.paramsUserSendMsg true "user send messages"
// @Param token header string true "token"
// @Success 200 {object} user.result{reqIdentifier=int,data=resultSendMsg}
// @Failure 400 {object} user.result
// @Router /chat/send_msg [post]
func UserSendMsg(c *gin.Context) {
params := paramsUserSendMsg{}
if err := c.BindJSON(&params); err != nil {
@ -67,12 +85,12 @@ func UserSendMsg(c *gin.Context) {
token := c.Request.Header.Get("token")
log.InfoByKv("Ws call success to sendMsgReq", params.OperationID, "Parameters", params)
log.InfoByKv("api call success to sendMsgReq", params.OperationID, "Parameters", params)
pbData := newUserSendMsgReq(token, &params)
log.Info("", "", "api UserSendMsg call start..., [data: %s]", pbData.String())
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImOfflineMessageName)
etcdConn := getcdv3.GetOfflineMessageConn()
client := pbChat.NewChatClient(etcdConn)
log.Info("", "", "api UserSendMsg call, api call rpc...")

@ -1,26 +1,31 @@
package friend
import (
pbFriend "Open_IM/pkg/proto/friend"
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbFriend "Open_IM/pkg/proto/friend"
"context"
"github.com/gin-gonic/gin"
"net/http"
"strings"
)
/*
type paramsAddBlackList struct {
OperationID string `json:"operationID" binding:"required"`
UID string `json:"uid" binding:"required"`
}*/
"github.com/gin-gonic/gin"
)
// @Summary
// @Schemes
// @Description add a user into black list
// @Tags friend
// @Accept json
// @Produce json
// @Param body body friend.paramsSearchFriend true "add black list params"
// @Param token header string true "token"
// @Success 200 {object} user.result
// @Failure 400 {object} user.result
// @Failure 500 {object} user.result
// @Router /friend/add_blacklist [post]
func AddBlacklist(c *gin.Context) {
log.Info("", "", "api add blacklist init ....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImFriendName)
etcdConn := getcdv3.GetFriendConn()
client := pbFriend.NewFriendClient(etcdConn)
//defer etcdConn.Close()

@ -1,33 +1,52 @@
package friend
import (
pbFriend "Open_IM/pkg/proto/friend"
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbFriend "Open_IM/pkg/proto/friend"
"context"
"github.com/gin-gonic/gin"
"net/http"
"strings"
"github.com/gin-gonic/gin"
)
// paramsImportFriendReq struct
type paramsImportFriendReq struct {
OperationID string `json:"operationID" binding:"required"`
UIDList []string `json:"uidList" binding:"required"`
OwnerUid string `json:"ownerUid" binding:"required"`
}
// resultImportFriend struct
type resultImportFriend struct {
ErrCode int `json:"errCode" example:"0"`
ErrMsg string `json:"errMsg" example:"error"`
FailedUidList []string `json:"failedUidList" example: []`
}
// paramsAddFriend struct
type paramsAddFriend struct {
OperationID string `json:"operationID" binding:"required"`
UID string `json:"uid" binding:"required"`
ReqMessage string `json:"reqMessage"`
}
//
// @Summary
// @Schemes
// @Description import friend
// @Tags friend
// @Accept json
// @Produce json
// @Param body body friend.paramsImportFriendReq true "import friend params"
// @Param token header string true "token"
// @Success 200 {object} friend.resultImportFriend
// @Failure 400 {object} user.result
// @Failure 500 {object} user.result
// @Router /friend/import_friend [post]
func ImportFriend(c *gin.Context) {
log.Info("", "", "ImportFriend init ....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImFriendName)
etcdConn := getcdv3.GetFriendConn()
client := pbFriend.NewFriendClient(etcdConn)
params := paramsImportFriendReq{}
@ -53,10 +72,22 @@ func ImportFriend(c *gin.Context) {
log.InfoByArgs("ImportFriend success return,get args=%s,return args=%s", req.String(), RpcResp.String())
}
// @Summary
// @Schemes
// @Description add a new friend by uid
// @Tags friend
// @Accept json
// @Produce json
// @Param body body friend.paramsAddFriend true "add friend params"
// @Param token header string true "token"
// @Success 200 {object} user.result
// @Failure 400 {object} user.result
// @Failure 500 {object} user.result
// @Router /friend/add_friend [post]
func AddFriend(c *gin.Context) {
log.Info("", "", "api add friend init ....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImFriendName)
etcdConn := getcdv3.GetFriendConn()
client := pbFriend.NewFriendClient(etcdConn)
params := paramsAddFriend{}

@ -1,27 +1,39 @@
package friend
import (
pbFriend "Open_IM/pkg/proto/friend"
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbFriend "Open_IM/pkg/proto/friend"
"context"
"fmt"
"github.com/gin-gonic/gin"
"net/http"
"strings"
"github.com/gin-gonic/gin"
)
// paramsAddFriendResponse struct
type paramsAddFriendResponse struct {
OperationID string `json:"operationID" binding:"required"`
UID string `json:"uid" binding:"required"`
Flag int32 `json:"flag" binding:"required"`
}
// @Summary
// @Schemes
// @Description the response of adding friend
// @Tags friend
// @Accept json
// @Produce json
// @Param body body friend.paramsAddFriendResponse true "response of adding friend"
// @Param token header string true "token"
// @Success 200 {object} user.result
// @Failure 400 {object} user.result
// @Failure 500 {object} user.result
// @Router /friend/add_friend_response [post]
func AddFriendResponse(c *gin.Context) {
log.Info("", "", fmt.Sprintf("api add friend response init ...."))
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImFriendName)
etcdConn := getcdv3.GetFriendConn()
client := pbFriend.NewFriendClient(etcdConn)
//defer etcdConn.Close()

@ -1,26 +1,38 @@
package friend
import (
pbFriend "Open_IM/pkg/proto/friend"
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbFriend "Open_IM/pkg/proto/friend"
"context"
"fmt"
"github.com/gin-gonic/gin"
"net/http"
"strings"
"github.com/gin-gonic/gin"
)
// paramsDeleteFriend struct
type paramsDeleteFriend struct {
OperationID string `json:"operationID" binding:"required"`
UID string `json:"uid" binding:"required"`
}
// @Summary
// @Schemes
// @Description delete friend
// @Tags friend
// @Accept json
// @Produce json
// @Param body body friend.paramsSearchFriend true "delete friend params"
// @Param token header string true "token"
// @Success 200 {object} user.result
// @Failure 400 {object} user.result
// @Failure 500 {object} user.result
// @Router /friend/delete_friend [post]
func DeleteFriend(c *gin.Context) {
log.Info("", "", fmt.Sprintf("api delete_friend init ...."))
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImFriendName)
etcdConn := getcdv3.GetFriendConn()
client := pbFriend.NewFriendClient(etcdConn)
//defer etcdConn.Close()

@ -1,21 +1,22 @@
package friend
import (
pbFriend "Open_IM/pkg/proto/friend"
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbFriend "Open_IM/pkg/proto/friend"
"context"
"fmt"
"github.com/gin-gonic/gin"
"net/http"
"strings"
"github.com/gin-gonic/gin"
)
// paramsGetBlackList struct
type paramsGetBlackList struct {
OperationID string `json:"operationID" binding:"required"`
}
// blackListUserInfo struct
type blackListUserInfo struct {
UID string `json:"uid"`
Name string `json:"name"`
@ -27,10 +28,22 @@ type blackListUserInfo struct {
Ex string `json:"ex"`
}
// @Summary
// @Schemes
// @Description get black list
// @Tags friend
// @Accept json
// @Produce json
// @Param body body friend.paramsSearchFriend true "get black list"
// @Param token header string true "token"
// @Success 200 {object} user.result{data=[]friend.blackListUserInfo}
// @Failure 400 {object} user.result
// @Failure 500 {object} user.result
// @Router /friend/get_blacklist [post]
func GetBlacklist(c *gin.Context) {
log.Info("", "", "api get blacklist init ....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImFriendName)
etcdConn := getcdv3.GetFriendConn()
client := pbFriend.NewFriendClient(etcdConn)
//defer etcdConn.Close()

@ -1,19 +1,21 @@
package friend
import (
pbFriend "Open_IM/pkg/proto/friend"
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbFriend "Open_IM/pkg/proto/friend"
"context"
"github.com/gin-gonic/gin"
"net/http"
"strings"
"github.com/gin-gonic/gin"
)
// paramsGetApplyList struct
type paramsGetApplyList struct {
OperationID string `json:"operationID" binding:"required"`
}
// UserInfo struct
type UserInfo struct {
UID string `json:"uid"`
Name string `json:"name"`
@ -28,10 +30,22 @@ type UserInfo struct {
Flag int32 `json:"flag"`
}
// @Summary
// @Schemes
// @Description get friend apply list
// @Tags friend
// @Accept json
// @Produce json
// @Param body body friend.paramsGetApplyList true "get friend apply list"
// @Param token header string true "token"
// @Success 200 {object} user.result{data=[]friend.UserInfo}
// @Failure 400 {object} user.result
// @Failure 500 {object} user.result
// @Router /friend/get_friend_apply_list [post]
func GetFriendApplyList(c *gin.Context) {
log.Info("", "", "api get_friend_apply_list init ....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImFriendName)
etcdConn := getcdv3.GetFriendConn()
client := pbFriend.NewFriendClient(etcdConn)
//defer etcdConn.Close()
@ -78,10 +92,22 @@ func GetFriendApplyList(c *gin.Context) {
log.InfoByArgs("api get friend apply list success return,get args=%s,return args=%s", req.String(), RpcResp.String())
}
// @Summary
// @Schemes
// @Description get self friend apply list
// @Tags friend
// @Accept json
// @Produce json
// @Param body body friend.paramsGetApplyList true "get self friend apply list"
// @Param token header string true "token"
// @Success 200 {object} user.result{data=[]friend.UserInfo}
// @Failure 400 {object} user.result
// @Failure 500 {object} user.result
// @Router /friend/get_self_apply_list [post]
func GetSelfApplyList(c *gin.Context) {
log.Info("", "", "api get self friend apply list init ....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImFriendName)
etcdConn := getcdv3.GetFriendConn()
client := pbFriend.NewFriendClient(etcdConn)
//defer etcdConn.Close()

@ -1,21 +1,22 @@
package friend
import (
pbFriend "Open_IM/pkg/proto/friend"
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbFriend "Open_IM/pkg/proto/friend"
"context"
"fmt"
"github.com/gin-gonic/gin"
"net/http"
"strings"
"github.com/gin-gonic/gin"
)
// paramsGetFriendLIst struct
type paramsGetFriendLIst struct {
OperationID string `json:"operationID" binding:"required"`
}
// friendInfo struct
type friendInfo struct {
UID string `json:"uid"`
Name string `json:"name"`
@ -29,10 +30,22 @@ type friendInfo struct {
IsInBlackList int32 `json:"isInBlackList"`
}
// @Summary
// @Schemes
// @Description get friend apply list
// @Tags friend
// @Accept json
// @Produce json
// @Param body body friend.paramsGetFriendLIst true "get friend apply list"
// @Param token header string true "token"
// @Success 200 {object} user.result{data=[]friend.friendInfo}
// @Failure 400 {object} user.result
// @Failure 500 {object} user.result
// @Router /friend/get_friend_list [post]
func GetFriendList(c *gin.Context) {
log.Info("", "", fmt.Sprintf("api get_friendlist init ...."))
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImFriendName)
etcdConn := getcdv3.GetFriendConn()
client := pbFriend.NewFriendClient(etcdConn)
//defer etcdConn.Close()

@ -1,26 +1,50 @@
package friend
import (
pbFriend "Open_IM/pkg/proto/friend"
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbFriend "Open_IM/pkg/proto/friend"
"context"
"fmt"
"github.com/gin-gonic/gin"
"net/http"
"strings"
"github.com/gin-gonic/gin"
)
// paramsSearchFriend struct
type paramsSearchFriend struct {
OperationID string `json:"operationID" binding:"required"`
UID string `json:"uid" binding:"required"`
OwnerUid string `json:"ownerUid"`
}
// resultFriendInfo struct
type resultFriendInfo struct {
UID string `json:"uid"`
Name string `json:"name"`
Icon string `json:"icon"`
Gender int32 `json:"gender"`
Mobile string `json:"mobile"`
Birth string `json:"birth"`
Email string `json:"email"`
Ex string `json:"ex"`
Comment string `json:"comment"`
}
// @Summary
// @Schemes
// @Description get friend info
// @Tags friend
// @Accept json
// @Produce json
// @Param body body friend.paramsSearchFriend true "search friend params"
// @Param token header string true "token"
// @Success 200 {object} user.result{data=friend.resultFriendInfo}
// @Failure 200 {object} user.result
// @Router /friend/get_friends_info [post]
func GetFriendsInfo(c *gin.Context) {
log.Info("", "", fmt.Sprintf("api search friend init ...."))
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImFriendName)
etcdConn := getcdv3.GetFriendConn()
client := pbFriend.NewFriendClient(etcdConn)
//defer etcdConn.Close()

@ -1,25 +1,37 @@
package friend
import (
pbFriend "Open_IM/pkg/proto/friend"
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbFriend "Open_IM/pkg/proto/friend"
"context"
"github.com/gin-gonic/gin"
"net/http"
"strings"
"github.com/gin-gonic/gin"
)
// paramsIsFriend struct
type paramsIsFriend struct {
OperationID string `json:"operationID" binding:"required"`
ReceiveUid string `json:"receive_uid"`
}
// @Summary
// @Schemes
// @Description check is friend
// @Tags friend
// @Accept json
// @Produce json
// @Param body body friend.paramsSearchFriend true "is friend params"
// @Param token header string true "token"
// @Success 200 {object} user.result
// @Failure 400 {object} user.result
// @Failure 500 {object} user.result
// @Router /friend/is_friend [post]
func IsFriend(c *gin.Context) {
log.Info("", "", "api is friend init....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImFriendName)
etcdConn := getcdv3.GetFriendConn()
client := pbFriend.NewFriendClient(etcdConn)
//defer etcdConn.Close()
@ -30,7 +42,7 @@ func IsFriend(c *gin.Context) {
}
req := &pbFriend.IsFriendReq{
OperationID: params.OperationID,
ReceiveUid: params.OperationID,
ReceiveUid: params.ReceiveUid,
Token: c.Request.Header.Get("token"),
}
log.Info(req.Token, req.OperationID, "api is friend is server")

@ -1,25 +1,37 @@
package friend
import (
pbFriend "Open_IM/pkg/proto/friend"
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbFriend "Open_IM/pkg/proto/friend"
"context"
"github.com/gin-gonic/gin"
"net/http"
"strings"
"github.com/gin-gonic/gin"
)
// paramsRemoveBlackList struct
type paramsRemoveBlackList struct {
OperationID string `json:"operationID" binding:"required"`
UID string `json:"uid" binding:"required"`
}
// @Summary
// @Schemes
// @Description remove black list
// @Tags friend
// @Accept json
// @Produce json
// @Param body body friend.paramsSearchFriend true "remove black list params"
// @Param token header string true "token"
// @Success 200 {object} user.result
// @Failure 400 {object} user.result
// @Failure 500 {object} user.result
// @Router /friend/remove_blacklist [post]
func RemoveBlacklist(c *gin.Context) {
log.Info("", "", "api remove_blacklist init ....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImFriendName)
etcdConn := getcdv3.GetFriendConn()
client := pbFriend.NewFriendClient(etcdConn)
//defer etcdConn.Close()

@ -1,26 +1,38 @@
package friend
import (
pbFriend "Open_IM/pkg/proto/friend"
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbFriend "Open_IM/pkg/proto/friend"
"context"
"github.com/gin-gonic/gin"
"net/http"
"strings"
"github.com/gin-gonic/gin"
)
// paramsSetFriendComment struct
type paramsSetFriendComment struct {
OperationID string `json:"operationID" binding:"required"`
UID string `json:"uid" binding:"required"`
Comment string `json:"comment"`
}
// @Summary
// @Schemes
// @Description set friend comment
// @Tags friend
// @Accept json
// @Produce json
// @Param body body friend.paramsSetFriendComment true "set friend comment"
// @Param token header string true "token"
// @Success 200 {object} user.result
// @Failure 400 {object} user.result
// @Failure 500 {object} user.result
// @Router /friend/set_friend_comment [post]
func SetFriendComment(c *gin.Context) {
log.Info("", "", "api set friend comment init ....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImFriendName)
etcdConn := getcdv3.GetFriendConn()
client := pbFriend.NewFriendClient(etcdConn)
//defer etcdConn.Close()

@ -1,16 +1,28 @@
package group
import (
pb "Open_IM/pkg/proto/group"
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pb "Open_IM/pkg/proto/group"
"context"
"github.com/gin-gonic/gin"
"net/http"
"strings"
"github.com/gin-gonic/gin"
)
// paramsCreateGroup struct
type paramsCreateGroup struct {
MemberList struct {
Uid string `json:"uid"`
SetRole string `json:"setRole,omitempty"`
} `json:"memberList"`
GroupName string `json:"groupName"`
Introduction string `json:"introduction"`
Notification string `json:"notification"`
FaceUrl string `json:"faceUrl"`
OperationID string `json:"operationID" binding:"required"`
Ex string `json:"ex"`
}
type paramsCreateGroupStruct struct {
MemberList []*pb.GroupAddMemberInfo `json:"memberList"`
GroupName string `json:"groupName"`
@ -21,10 +33,22 @@ type paramsCreateGroupStruct struct {
Ex string `json:"ex"`
}
// @Summary
// @Schemes
// @Description create group
// @Tags group
// @Accept json
// @Produce json
// @Param body body group.paramsCreateGroup true "create group params"
// @Param token header string true "token"
// @Success 200 {object} user.result
// @Failure 400 {object} user.result
// @Failure 500 {object} user.result
// @Router /group/create_group [post]
func CreateGroup(c *gin.Context) {
log.Info("", "", "api create group init ....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImGroupName)
etcdConn := getcdv3.GetGroupConn()
client := pb.NewGroupClient(etcdConn)
//defer etcdConn.Close()

@ -1,17 +1,17 @@
package group
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
"Open_IM/pkg/proto/group"
"Open_IM/pkg/utils"
"context"
"github.com/gin-gonic/gin"
"net/http"
"strings"
"github.com/gin-gonic/gin"
)
// paramsGroupApplicationList struct
type paramsGroupApplicationList struct {
OperationID string `json:"operationID" binding:"required"`
}
@ -23,6 +23,7 @@ func newUserRegisterReq(params *paramsGroupApplicationList) *group.GetGroupAppli
return &pbData
}
// paramsGroupApplicationListRet struct
type paramsGroupApplicationListRet struct {
ID string `json:"id"`
GroupID string `json:"groupID"`
@ -42,9 +43,27 @@ type paramsGroupApplicationListRet struct {
HandleResult int32 `json:"handleResult"`
}
// resultGroupApplication struct
type resultGroupApplication struct {
Count int `json:"count"`
User []paramsGroupApplicationListRet `json:"user"`
}
// @Summary
// @Schemes
// @Description get group application list
// @Tags group
// @Accept json
// @Produce json
// @Param body body group.paramsGroupApplicationList true "get group application list params"
// @Param token header string true "token"
// @Success 200 {object} user.result{data=group.resultGroupApplication}
// @Failure 400 {object} user.result
// @Failure 500 {object} user.result
// @Router /group/get_group_applicationList [post]
func GetGroupApplicationList(c *gin.Context) {
log.Info("", "", "api GetGroupApplicationList init ....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImGroupName)
etcdConn := getcdv3.GetGroupConn()
client := group.NewGroupClient(etcdConn)
//defer etcdConn.Close()

@ -1,14 +1,13 @@
package group
import (
pb "Open_IM/pkg/proto/group"
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pb "Open_IM/pkg/proto/group"
"context"
"github.com/gin-gonic/gin"
"net/http"
"strings"
"github.com/gin-gonic/gin"
)
type paramsGetGroupInfo struct {
@ -16,10 +15,22 @@ type paramsGetGroupInfo struct {
OperationID string `json:"operationID" binding:"required"`
}
// @Summary
// @Schemes
// @Description get groups info
// @Tags group
// @Accept json
// @Produce json
// @Param body body group.paramsGetGroupInfo true "get groups info params"
// @Param token header string true "token"
// @Success 200 {object} user.result{data=[]group.GroupInfo}
// @Failure 400 {object} user.result
// @Failure 500 {object} user.result
// @Router /group/get_groups_info [post]
func GetGroupsInfo(c *gin.Context) {
log.Info("", "", "api get groups info init ....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImGroupName)
etcdConn := getcdv3.GetGroupConn()
client := pb.NewGroupClient(etcdConn)
//defer etcdConn.Close()

@ -1,17 +1,19 @@
package group
import (
pb "Open_IM/pkg/proto/group"
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pb "Open_IM/pkg/proto/group"
"context"
"fmt"
"github.com/gin-gonic/gin"
"net/http"
"strings"
"github.com/gin-gonic/gin"
)
// InviteUserToGroupReq struct
type InviteUserToGroupReq struct {
GroupID string `json:"groupID" binding:"required"`
UidList []string `json:"uidList" binding:"required"`
@ -19,10 +21,25 @@ type InviteUserToGroupReq struct {
OperationID string `json:"operationID" binding:"required"`
}
// GetJoinedGroupListReq struct
type GetJoinedGroupListReq struct {
OperationID string `json:"operationID" binding:"required"`
}
// paramsKickGroupMember struct
type paramsKickGroupMember struct {
GroupID string `json:"groupID"`
UidListInfo []struct {
UserId string `json:"userId,omitempty"`
Role int32 `json:"role,omitempty"`
JoinTime uint64 `json:"joinTime,omitempty"`
NickName string `json:"nickName,omitempty"`
FaceUrl string `json:"faceUrl,omitempty"`
} `json:"uidListInfo" binding:"required"`
Reason string `json:"reason"`
OperationID string `json:"operationID" binding:"required"`
}
type KickGroupMemberReq struct {
GroupID string `json:"groupID"`
UidListInfo []*pb.GroupMemberFullInfo `json:"uidListInfo" binding:"required"`
@ -30,10 +47,22 @@ type KickGroupMemberReq struct {
OperationID string `json:"operationID" binding:"required"`
}
// @Summary
// @Schemes
// @Description kick member from group
// @Tags group
// @Accept json
// @Produce json
// @Param body body group.paramsKickGroupMember true "kick member from group params"
// @Param token header string true "token"
// @Success 200 {object} group.KickGroupMemberResp
// @Failure 400 {object} user.result
// @Failure 500 {object} user.result
// @Router /group/kick_group [post]
func KickGroupMember(c *gin.Context) {
log.Info("", "", "KickGroupMember start....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImGroupName)
etcdConn := getcdv3.GetGroupConn()
client := pb.NewGroupClient(etcdConn)
params := KickGroupMemberReq{}
@ -58,6 +87,7 @@ func KickGroupMember(c *gin.Context) {
return
}
// KickGroupMemberResp struct
type KickGroupMemberResp struct {
ErrorCode int32 `json:"errCode"`
ErrorMsg string `json:"errMsg"`
@ -75,21 +105,36 @@ func KickGroupMember(c *gin.Context) {
c.JSON(http.StatusOK, memberListResp)
}
// GetGroupMembersInfoReq struct
type GetGroupMembersInfoReq struct {
GroupID string `json:"groupID"`
MemberList []string `json:"memberList"`
OperationID string `json:"operationID"`
}
// GetGroupMembersInfoResp struct
type GetGroupMembersInfoResp struct {
ErrorCode int32 `json:"errCode"`
ErrorMsg string `json:"errMsg"`
Data []MemberResult `json:"data"`
}
// @Summary
// @Schemes
// @Description get group members info
// @Tags group
// @Accept json
// @Produce json
// @Param body body group.GetGroupMembersInfoReq true "get group members info params"
// @Param token header string true "token"
// @Success 200 {object} group.GetGroupMembersInfoResp
// @Failure 400 {object} user.result
// @Failure 500 {object} user.result
// @Router /group/get_group_members_info [post]
func GetGroupMembersInfo(c *gin.Context) {
log.Info("", "", "GetGroupMembersInfo start....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImGroupName)
etcdConn := getcdv3.GetGroupConn()
client := pb.NewGroupClient(etcdConn)
params := GetGroupMembersInfoReq{}
@ -128,17 +173,21 @@ func GetGroupMembersInfo(c *gin.Context) {
c.JSON(http.StatusOK, memberListResp)
}
// GetGroupMemberListReq struct
type GetGroupMemberListReq struct {
GroupID string `json:"groupID"`
Filter int32 `json:"filter"`
NextSeq int32 `json:"nextSeq"`
NextSeq int32 `json:"nextSeq,omitempty"`
OperationID string `json:"operationID"`
}
// getGroupAllMemberReq struct
type getGroupAllMemberReq struct {
GroupID string `json:"groupID"`
OperationID string `json:"operationID"`
}
// MemberResult struct
type MemberResult struct {
GroupId string `json:"groupID"`
UserId string `json:"userId"`
@ -148,10 +197,22 @@ type MemberResult struct {
FaceUrl string `json:"faceUrl"`
}
// @Summary
// @Schemes
// @Description get group member list
// @Tags group
// @Accept json
// @Produce json
// @Param body body group.GetGroupMemberListReq true "get group member list params"
// @Param token header string true "token"
// @Success 200 {object} group.GetGroupMemberListResp
// @Failure 400 {object} user.result
// @Failure 500 {object} user.result
// @Router /group/get_group_member_list [post]
func GetGroupMemberList(c *gin.Context) {
log.Info("", "", "GetGroupMemberList start....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImGroupName)
etcdConn := getcdv3.GetGroupConn()
client := pb.NewGroupClient(etcdConn)
params := GetGroupMemberListReq{}
@ -174,6 +235,7 @@ func GetGroupMemberList(c *gin.Context) {
return
}
// GetGroupMemberListResp struct
type GetGroupMemberListResp struct {
ErrorCode int32 `json:"errCode"`
ErrorMsg string `json:"errMsg"`
@ -198,10 +260,22 @@ func GetGroupMemberList(c *gin.Context) {
}
// @Summary
// @Schemes
// @Description get group all members
// @Tags group
// @Accept json
// @Produce json
// @Param body body group.getGroupAllMemberReq true "get group all members params"
// @Param token header string true "token"
// @Success 200 {object} group.GetGroupMemberListResp
// @Failure 400 {object} user.result
// @Failure 500 {object} user.result
// @Router /group/get_group_all_member_list [post]
func GetGroupAllMember(c *gin.Context) {
log.Info("", "", "GetGroupAllMember start....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImGroupName)
etcdConn := getcdv3.GetGroupConn()
client := pb.NewGroupClient(etcdConn)
params := getGroupAllMemberReq{}
@ -222,6 +296,7 @@ func GetGroupAllMember(c *gin.Context) {
return
}
// GetGroupMemberListResp struct
type GetGroupMemberListResp struct {
ErrorCode int32 `json:"errCode"`
ErrorMsg string `json:"errMsg"`
@ -243,6 +318,7 @@ func GetGroupAllMember(c *gin.Context) {
c.JSON(http.StatusOK, memberListResp)
}
// groupResult struct
type groupResult struct {
GroupId string `json:"groupId"`
GroupName string `json:"groupName"`
@ -254,10 +330,22 @@ type groupResult struct {
MemberCount uint32 `json:"memberCount"`
}
// @Summary
// @Schemes
// @Description get joined group list
// @Tags group
// @Accept json
// @Produce json
// @Param body body group.GetJoinedGroupListReq true "get joined group list params"
// @Param token header string true "token"
// @Success 200 {object} group.GetJoinedGroupListResp
// @Failure 400 {object} user.result
// @Failure 500 {object} user.result
// @Router /group/get_joined_group_list [post]
func GetJoinedGroupList(c *gin.Context) {
log.Info("", "", "GetJoinedGroupList start....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImGroupName)
etcdConn := getcdv3.GetGroupConn()
fmt.Println("config: ", etcdConn, config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImGroupName)
client := pb.NewGroupClient(etcdConn)
@ -280,6 +368,7 @@ func GetJoinedGroupList(c *gin.Context) {
}
log.Info(req.Token, req.OperationID, "GetJoinedGroupList: ", RpcResp)
// GetJoinedGroupListResp struct
type GetJoinedGroupListResp struct {
ErrorCode int32 `json:"errCode"`
ErrorMsg string `json:"errMsg"`
@ -302,14 +391,27 @@ func GetJoinedGroupList(c *gin.Context) {
c.JSON(http.StatusOK, GroupListResp)
}
// Id2Result struct
type Id2Result struct {
UId string `json:"uid"`
Result int32 `json:"result"`
}
// @Summary
// @Schemes
// @Description invite user to group
// @Tags group
// @Accept json
// @Produce json
// @Param body body group.InviteUserToGroupReq true "invite user to group params"
// @Param token header string true "token"
// @Success 200 {object} group.InviteUserToGroupResp
// @Failure 400 {object} user.result
// @Failure 500 {object} user.result
// @Router /group/invite_user_to_group [post]
func InviteUserToGroup(c *gin.Context) {
log.Info("", "", "InviteUserToGroup start....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImGroupName)
etcdConn := getcdv3.GetGroupConn()
client := pb.NewGroupClient(etcdConn)
params := InviteUserToGroupReq{}
@ -333,6 +435,7 @@ func InviteUserToGroup(c *gin.Context) {
return
}
// InviteUserToGroupResp struct
type InviteUserToGroupResp struct {
ErrorCode int32 `json:"errCode"`
ErrorMsg string `json:"errMsg"`

@ -1,17 +1,17 @@
package group
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
"Open_IM/pkg/proto/group"
"Open_IM/pkg/utils"
"context"
"github.com/gin-gonic/gin"
"net/http"
"strings"
"github.com/gin-gonic/gin"
)
// paramsGroupApplicationResponse struct
type paramsGroupApplicationResponse struct {
OperationID string `json:"operationID" binding:"required"`
GroupID string `json:"groupID" binding:"required"`
@ -49,9 +49,21 @@ func newGroupApplicationResponse(params *paramsGroupApplicationResponse) *group.
return &pbData
}
// @Summary
// @Schemes
// @Description response of application group
// @Tags group
// @Accept json
// @Produce json
// @Param body body group.paramsGroupApplicationResponse true "application group param"
// @Param token header string true "token"
// @Success 200 {object} user.result
// @Failure 400 {object} user.result
// @Failure 500 {object} user.result
// @Router /group/group_application_response [post]
func ApplicationGroupResponse(c *gin.Context) {
log.Info("", "", "api GroupApplicationResponse init ....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImGroupName)
etcdConn := getcdv3.GetGroupConn()
client := group.NewGroupClient(etcdConn)
//defer etcdConn.Close()

@ -1,26 +1,38 @@
package group
import (
pb "Open_IM/pkg/proto/group"
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pb "Open_IM/pkg/proto/group"
"context"
"github.com/gin-gonic/gin"
"net/http"
"strings"
"github.com/gin-gonic/gin"
)
// paramsJoinGroup struct
type paramsJoinGroup struct {
GroupID string `json:"groupID" binding:"required"`
Message string `json:"message"`
OperationID string `json:"operationID" binding:"required"`
}
// @Summary
// @Schemes
// @Description join group
// @Tags group
// @Accept json
// @Produce json
// @Param body body group.paramsJoinGroup true "join group params"
// @Param token header string true "token"
// @Success 200 {object} user.result
// @Failure 400 {object} user.result
// @Failure 500 {object} user.result
// @Router /group/set_group_info [post]
func JoinGroup(c *gin.Context) {
log.Info("", "", "api join group init....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImGroupName)
etcdConn := getcdv3.GetGroupConn()
client := pb.NewGroupClient(etcdConn)
//defer etcdConn.Close()

@ -1,25 +1,37 @@
package group
import (
pb "Open_IM/pkg/proto/group"
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pb "Open_IM/pkg/proto/group"
"context"
"github.com/gin-gonic/gin"
"net/http"
"strings"
"github.com/gin-gonic/gin"
)
// paramsQuitGroup struct
type paramsQuitGroup struct {
GroupID string `json:"groupID" binding:"required"`
OperationID string `json:"operationID" binding:"required"`
}
// @Summary
// @Schemes
// @Description quit group
// @Tags group
// @Accept json
// @Produce json
// @Param body body group.paramsQuitGroup true "quit group"
// @Param token header string true "token"
// @Success 200 {object} user.result
// @Failure 400 {object} user.result
// @Failure 500 {object} user.result
// @Router /group/set_group_info [post]
func QuitGroup(c *gin.Context) {
log.Info("", "", "api quit group init ....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImGroupName)
etcdConn := getcdv3.GetGroupConn()
client := pb.NewGroupClient(etcdConn)
//defer etcdConn.Close()

@ -1,16 +1,16 @@
package group
import (
pb "Open_IM/pkg/proto/group"
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pb "Open_IM/pkg/proto/group"
"context"
"github.com/gin-gonic/gin"
"net/http"
"strings"
"github.com/gin-gonic/gin"
)
// paramsSetGroupInfo struct
type paramsSetGroupInfo struct {
GroupID string `json:"groupId" binding:"required"`
GroupName string `json:"groupName"`
@ -20,10 +20,22 @@ type paramsSetGroupInfo struct {
OperationID string `json:"operationID" binding:"required"`
}
// @Summary
// @Schemes
// @Description set group info
// @Tags group
// @Accept json
// @Produce json
// @Param body body group.paramsSetGroupInfo true "set group info params"
// @Param token header string true "token"
// @Success 200 {object} user.result
// @Failure 400 {object} user.result
// @Failure 500 {object} user.result
// @Router /group/set_group_info [post]
func SetGroupInfo(c *gin.Context) {
log.Info("", "", "api set group info init...")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImGroupName)
etcdConn := getcdv3.GetGroupConn()
client := pb.NewGroupClient(etcdConn)
//defer etcdConn.Close()

@ -1,17 +1,17 @@
package group
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
"Open_IM/pkg/proto/group"
"Open_IM/pkg/utils"
"context"
"github.com/gin-gonic/gin"
"net/http"
"strings"
"github.com/gin-gonic/gin"
)
// paramsTransferGroupOwner struct
type paramsTransferGroupOwner struct {
OperationID string `json:"operationID" binding:"required"`
GroupID string `json:"groupID" binding:"required"`
@ -27,9 +27,21 @@ func newTransferGroupOwnerReq(params *paramsTransferGroupOwner) *group.TransferG
return &pbData
}
// @Summary
// @Schemes
// @Description transfer group owner
// @Tags group
// @Accept json
// @Produce json
// @Param body body group.paramsTransferGroupOwner true "transfer group owner param"
// @Param token header string true "token"
// @Success 200 {object} user.result
// @Failure 400 {object} user.result
// @Failure 500 {object} user.result
// @Router /group/transfer_group [post]
func TransferGroupOwner(c *gin.Context) {
log.Info("", "", "api TransferGroupOwner init ....")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImGroupName)
etcdConn := getcdv3.GetGroupConn()
client := group.NewGroupClient(etcdConn)
//defer etcdConn.Close()

@ -14,15 +14,16 @@ import (
pbChat "Open_IM/pkg/proto/chat"
"Open_IM/pkg/utils"
"context"
"net/http"
"github.com/gin-gonic/gin"
"github.com/go-playground/validator/v10"
"github.com/mitchellh/mapstructure"
"net/http"
"strings"
)
var validate *validator.Validate
// paramsManagementSendMsg struct
type paramsManagementSendMsg struct {
OperationID string `json:"operationID" binding:"required"`
SendID string `json:"sendID" binding:"required"`
@ -35,7 +36,15 @@ type paramsManagementSendMsg struct {
SessionType int32 `json:"sessionType" binding:"required"`
}
func newUserSendMsgReq(token string, params *paramsManagementSendMsg) *pbChat.UserSendMsgReq {
// sendMsgResult struct
type sendMsgResult struct {
ErrCode int `json:"errCode" example:"0"`
ErrMsg string `json:"errMsg" example:"error"`
SendTime int `json:"sendTime" example:0`
MsgID string `json:"msgID" example:""`
}
func newUserSendMsgReq(params *paramsManagementSendMsg) *pbChat.UserSendMsgReq {
var newContent string
switch params.ContentType {
case constant.Text:
@ -53,7 +62,6 @@ func newUserSendMsgReq(token string, params *paramsManagementSendMsg) *pbChat.Us
}
pbData := pbChat.UserSendMsgReq{
ReqIdentifier: constant.WSSendMsg,
Token: token,
SendID: params.SendID,
SenderNickName: params.SenderNickName,
SenderFaceURL: params.SenderFaceURL,
@ -72,6 +80,19 @@ func newUserSendMsgReq(token string, params *paramsManagementSendMsg) *pbChat.Us
func init() {
validate = validator.New()
}
// @Summary
// @Schemes
// @Description manage send message
// @Tags manage
// @Accept json
// @Produce json
// @Param body body manage.paramsManagementSendMsg true "manage send message"
// @Param token header string true "token"
// @Success 200 {object} manage.sendMsgResult
// @Failure 400 {object} user.result
// @Failure 500 {object} user.result
// @Router /manager/send_msg [post]
func ManagementSendMsg(c *gin.Context) {
var data interface{}
params := paramsManagementSendMsg{}
@ -103,18 +124,22 @@ func ManagementSendMsg(c *gin.Context) {
}
token := c.Request.Header.Get("token")
if !utils.IsContain(params.SendID, config.Config.Manager.AppManagerUid) {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": "not appManager", "sendTime": 0, "MsgID": ""})
claims, err := utils.ParseToken(token)
if err != nil {
log.NewError(params.OperationID, "parse token failed", err.Error())
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": "parse token failed", "sendTime": 0, "MsgID": ""})
}
if !utils.IsContain(claims.UID, config.Config.Manager.AppManagerUid) {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": "not authorized", "sendTime": 0, "MsgID": ""})
return
}
log.InfoByKv("Ws call success to ManagementSendMsgReq", params.OperationID, "Parameters", params)
pbData := newUserSendMsgReq(token, &params)
pbData := newUserSendMsgReq(&params)
log.Info("", "", "api ManagementSendMsg call start..., [data: %s]", pbData.String())
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImOfflineMessageName)
etcdConn := getcdv3.GetOfflineMessageConn()
client := pbChat.NewChatClient(etcdConn)
log.Info("", "", "api ManagementSendMsg call, api call rpc...")

@ -7,24 +7,52 @@
package manage
import (
pbUser "Open_IM/pkg/proto/user"
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbUser "Open_IM/pkg/proto/user"
"context"
"github.com/gin-gonic/gin"
"net/http"
"strings"
"github.com/gin-gonic/gin"
)
// paramsDeleteUsers struct
type paramsDeleteUsers struct {
OperationID string `json:"operationID" binding:"required"`
DeleteUidList []string `json:"deleteUidList" binding:"required"`
}
// paramsGetAllUsersUid struct
type paramsGetAllUsersUid struct {
OperationID string `json:"operationID" binding:"required"`
}
// deleteUserResult struct
type deleteUserResult struct {
ErrCode int `json:"errCode" example:"0"`
ErrMsg string `json:"errMsg" example:"error"`
FailedUidList []string `json:"failedUidList" example:[]`
}
// uidListResult struct
type uidListResult struct {
ErrCode int `json:"errCode" example:"0"`
ErrMsg string `json:"errMsg" example:"error"`
UidList []string `json:"uidList" example:[]`
}
// @Summary
// @Schemes
// @Description delete user
// @Tags manage
// @Accept json
// @Produce json
// @Param body body manage.paramsDeleteUsers true "user to be deleted"
// @Param token header string true "token"
// @Success 200 {object} manage.deleteUserResult
// @Failure 400 {object} user.result
// @Failure 500 {object} user.result
// @Router /manager/delete_user [post]
func DeleteUser(c *gin.Context) {
params := paramsDeleteUsers{}
if err := c.BindJSON(&params); err != nil {
@ -32,7 +60,7 @@ func DeleteUser(c *gin.Context) {
return
}
log.InfoByKv("DeleteUser req come here", params.OperationID, "DeleteUidList", params.DeleteUidList)
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImUserName)
etcdConn := getcdv3.GetUserConn()
client := pbUser.NewUserClient(etcdConn)
//defer etcdConn.Close()
@ -51,6 +79,18 @@ func DeleteUser(c *gin.Context) {
resp := gin.H{"errCode": RpcResp.CommonResp.ErrorCode, "errMsg": RpcResp.CommonResp.ErrorMsg, "failedUidList": RpcResp.FailedUidList}
c.JSON(http.StatusOK, resp)
}
// @Summary
// @Schemes
// @Description get all user ids
// @Tags manage
// @Accept json
// @Produce json
// @Param body body manage.paramsGetAllUsersUid true "all user ids"
// @Param token header string true "token"
// @Success 200 {object} manage.uidListResult
// @Failure 500 {object} manage.uidListResult
// @Router /manager/get_all_users_uid [post]
func GetAllUsersUid(c *gin.Context) {
params := paramsGetAllUsersUid{}
if err := c.BindJSON(&params); err != nil {
@ -58,7 +98,7 @@ func GetAllUsersUid(c *gin.Context) {
return
}
log.InfoByKv("GetAllUsersUid req come here", params.OperationID)
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImUserName)
etcdConn := getcdv3.GetUserConn()
client := pbUser.NewUserClient(etcdConn)
//defer etcdConn.Close()

@ -3,20 +3,43 @@ package apiThird
import (
"Open_IM/pkg/common/config"
log2 "Open_IM/pkg/common/log"
"github.com/gin-gonic/gin"
sts "github.com/tencentyun/qcloud-cos-sts-sdk/go"
"net/http"
"time"
"github.com/gin-gonic/gin"
sts "github.com/tencentyun/qcloud-cos-sts-sdk/go"
)
// paramsTencentCloudStorageCredential struct
type paramsTencentCloudStorageCredential struct {
Token string `json:"token"`
OperationID string `json:"operationID"`
}
// resultTencentCredential struct
type resultTencentCredential struct {
ErrCode int `json:"errCode`
ErrMsg string `json:"errMsg"`
Region string `json:"region"`
Bucket string `json:"bucket"`
Data interface{} `json:"data"`
}
var lastTime int64
var lastRes *sts.CredentialResult
// @Summary
// @Schemes
// @Description get Tencent cloud storage credential
// @Tags third
// @Accept json
// @Produce json
// @Param body body apiThird.paramsTencentCloudStorageCredential true "get Tencent cloud storage credential params"
// @Param token header string true "token"
// @Success 200 {object} apiThird.resultTencentCredential
// @Failure 400 {object} user.result
// @Failure 500 {object} user.result
// @Router /third/user_register [post]
func TencentCloudStorageCredential(c *gin.Context) {
params := paramsTencentCloudStorageCredential{}
if err := c.BindJSON(&params); err != nil {

@ -1,16 +1,23 @@
package user
import (
pbUser "Open_IM/pkg/proto/user"
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbUser "Open_IM/pkg/proto/user"
"context"
"github.com/gin-gonic/gin"
"net/http"
"strings"
"github.com/gin-gonic/gin"
)
// result struct
type result struct {
ErrCode int `json:"errCode" example:"0"`
ErrMsg string `json:"errMsg" example:"error"`
Data interface{} `json:"data,omitempty"`
}
// userInfo struct
type userInfo struct {
UID string `json:"uid"`
Name string `json:"name"`
@ -22,14 +29,30 @@ type userInfo struct {
Ex string `json:"ex"`
}
// queryUserInfoParam struct
type queryUserInfoParam struct {
OperationID string `json:"operationID" binding:"required"`
UIDList []string `json:"uidList"`
}
// @Summary
// @Description get user info by uid list
// @Tags user
// @Accept json
// @Produce json
// @Param body body user.queryUserInfoParam true "get userInfo by uidList"
// @Param token header string true "token"
// @Success 200 {object} user.result{data=[]user.userInfo}
// @Failure 400 {object} user.result
// @Router /user/get_user_info [post]
func GetUserInfo(c *gin.Context) {
log.InfoByKv("api get userinfo init...", "")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImUserName)
etcdConn := getcdv3.GetUserConn()
client := pbUser.NewUserClient(etcdConn)
//defer etcdConn.Close()
params := paramsStruct{}
params := queryUserInfoParam{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
return
@ -44,8 +67,8 @@ func GetUserInfo(c *gin.Context) {
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,call get user info rpc server failed", err)
c.JSON(http.StatusInternalServerError, gin.H{
"errorCode": 500,
"errorMsg": "call rpc server failed",
"errCode": 500,
"errMsg": "call rpc server failed",
})
return
}

@ -0,0 +1,31 @@
package user
import (
"bytes"
"net/http"
"net/http/httptest"
"testing"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
)
func init() {
gin.SetMode(gin.TestMode)
}
func Test_UserRegister(t *testing.T) {
res := httptest.NewRecorder()
c, _ := gin.CreateTestContext(res)
c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString(`{"uidList": []}`))
GetUserInfo(c)
assert.Equal(t, 400, res.Code)
res = httptest.NewRecorder()
c, _ = gin.CreateTestContext(res)
c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString(`{"operationID": "1", "uidList": []}`))
GetUserInfo(c)
assert.Equal(t, 200, res.Code)
}

@ -1,38 +1,46 @@
package user
import (
pbUser "Open_IM/pkg/proto/user"
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbUser "Open_IM/pkg/proto/user"
"context"
"github.com/gin-gonic/gin"
"net/http"
"strings"
"github.com/gin-gonic/gin"
)
type paramsStruct struct {
OperationID string `json:"operationID" binding:"required"`
UIDList []string `json:"uidList"`
Platform int32 `json:"platform"`
Name string `json:"name"`
Icon string `json:"icon"`
Gender int32 `json:"gender"`
Mobile string `json:"mobile"`
Birth string `json:"birth"`
Email string `json:"email"`
Ex string `json:"ex"`
Uid string `json:"uid"`
// updateUserInfoParam struct
type updateUserInfoParam struct {
OperationID string `json:"operationID" binding:"required"`
Name string `json:"name"`
Icon string `json:"icon"`
Gender int32 `json:"gender"`
Mobile string `json:"mobile"`
Birth string `json:"birth"`
Email string `json:"email"`
Ex string `json:"ex"`
Uid string `json:"uid"`
}
// @Summary
// @Description update user info
// @Tags user
// @Accept json
// @Produce json
// @Param body body user.updateUserInfoParam true "new user info"
// @Param token header string true "token"
// @Success 200 {object} user.result
// @Failure 500 {object} user.result
// @Router /user/update_user_info [post]
func UpdateUserInfo(c *gin.Context) {
log.InfoByKv("api update userinfo init...", "")
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImUserName)
etcdConn := getcdv3.GetUserConn()
client := pbUser.NewUserClient(etcdConn)
//defer etcdConn.Close()
params := paramsStruct{}
params := updateUserInfoParam{}
if err := c.BindJSON(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
return

@ -1,112 +1,107 @@
package gate
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/constant"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbChat "Open_IM/pkg/proto/chat"
open_im_sdk "Open_IM/pkg/proto/sdk_ws"
"Open_IM/pkg/utils"
"bytes"
"context"
"encoding/gob"
"encoding/json"
"runtime"
"github.com/golang/protobuf/proto"
"github.com/gorilla/websocket"
"strings"
)
func (ws *WServer) msgParse(conn *websocket.Conn, jsonMsg []byte) {
func (ws *WServer) msgParse(conn *UserConn, binaryMsg []byte) {
//ws online debug data
//{"ReqIdentifier":1001,"Token":"123","SendID":"c4ca4238a0b923820dcc509a6f75849b","Time":"123","OperationID":"123","MsgIncr":0}
//{"ReqIdentifier":1002,"Token":"123","SendID":"c4ca4238a0b923820dcc509a6f75849b","Time":"123","OperationID":"123","MsgIncr":0,"SeqBegin":1,"SeqEnd":6}
//{"ReqIdentifier":1003,"Token":"123","SendID":"c4ca4238a0b923820dcc509a6f75849b",
//"RecvID":"a87ff679a2f3e71d9181a67b7542122c","ClientMsgID":"2343","Time":"147878787","OperationID":
//"123","MsgIncr":0,"SubMsgType":101,"MsgType":100,"MsgFrom":1,"Content":"sdfsdf"}
b := bytes.NewBuffer(binaryMsg)
m := Req{}
if err := json.Unmarshal(jsonMsg, &m); err != nil {
dec := gob.NewDecoder(b)
err := dec.Decode(&m)
if err != nil {
log.ErrorByKv("ws json Unmarshal err", "", "err", err.Error())
ws.sendErrMsg(conn, 200, err.Error())
ws.sendErrMsg(conn, 200, err.Error(), constant.WSDataError, "", "")
err = conn.Close()
if err != nil {
log.NewError("", "ws close err", err.Error())
}
return
}
if err := validate.Struct(m); err != nil {
log.ErrorByKv("ws args validate err", "", "err", err.Error())
ws.sendErrMsg(conn, 201, err.Error())
return
}
if !utils.VerifyToken(m.Token, m.SendID) {
ws.sendErrMsg(conn, 202, "token validate err")
ws.sendErrMsg(conn, 201, err.Error(), m.ReqIdentifier, m.MsgIncr, m.OperationID)
return
}
log.InfoByKv("Basic Info Authentication Success", m.OperationID, "reqIdentifier", m.ReqIdentifier, "sendID", m.SendID)
//if !utils.VerifyToken(m.Token, m.SendID) {
// ws.sendErrMsg(conn, 202, "token validate err", m.ReqIdentifier, m.MsgIncr,m.OperationID)
// return
//}
log.InfoByKv("Basic Info Authentication Success", m.OperationID, "reqIdentifier", m.ReqIdentifier, "sendID", m.SendID, "msgIncr", m.MsgIncr)
switch m.ReqIdentifier {
case constant.WSGetNewestSeq:
ws.newestSeqReq(conn, &m)
go ws.getSeqReq(conn, &m)
case constant.WSPullMsg:
ws.pullMsgReq(conn, &m)
go ws.pullMsgReq(conn, &m)
case constant.WSSendMsg:
ws.sendMsgReq(conn, &m)
sendTime := utils.GetCurrentTimestampByNano()
go ws.sendMsgReq(conn, &m, sendTime)
case constant.WSPullMsgBySeqList:
go ws.pullMsgBySeqListReq(conn, &m)
default:
}
log.NewInfo("", "goroutine num is ", runtime.NumGoroutine())
}
func (ws *WServer) newestSeqResp(conn *websocket.Conn, m *Req, pb *pbChat.GetNewSeqResp) {
mReply := make(map[string]interface{})
mData := make(map[string]interface{})
mReply["reqIdentifier"] = m.ReqIdentifier
mReply["msgIncr"] = m.MsgIncr
mReply["errCode"] = pb.GetErrCode()
mReply["errMsg"] = pb.GetErrMsg()
mData["seq"] = pb.GetSeq()
mReply["data"] = mData
ws.sendMsg(conn, mReply)
}
func (ws *WServer) newestSeqReq(conn *websocket.Conn, m *Req) {
log.InfoByKv("Ws call success to getNewSeq", m.OperationID, "Parameters", m)
pbData := pbChat.GetNewSeqReq{}
func (ws *WServer) getSeqReq(conn *UserConn, m *Req) {
log.NewInfo(m.OperationID, "Ws call success to getNewSeq", m.MsgIncr, m.SendID, m.ReqIdentifier)
pbData := pbChat.GetMaxAndMinSeqReq{}
nReply := new(pbChat.GetMaxAndMinSeqResp)
pbData.UserID = m.SendID
pbData.OperationID = m.OperationID
grpcConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImOfflineMessageName)
grpcConn := getcdv3.GetOfflineMessageConn()
if grpcConn == nil {
log.ErrorByKv("get grpcConn err", pbData.OperationID, "args", m)
}
msgClient := pbChat.NewChatClient(grpcConn)
reply, err := msgClient.GetNewSeq(context.Background(), &pbData)
reply, err := msgClient.GetMaxAndMinSeq(context.Background(), &pbData)
if err != nil {
log.ErrorByKv("rpc call failed to getNewSeq", pbData.OperationID, "err", err, "pbData", pbData.String())
return
}
log.InfoByKv("rpc call success to getNewSeq", pbData.OperationID, "replyData", reply.String())
ws.newestSeqResp(conn, m, reply)
}
func (ws *WServer) pullMsgResp(conn *websocket.Conn, m *Req, pb *pbChat.PullMessageResp) {
mReply := make(map[string]interface{})
msg := make(map[string]interface{})
mReply["reqIdentifier"] = m.ReqIdentifier
mReply["msgIncr"] = m.MsgIncr
mReply["errCode"] = pb.GetErrCode()
mReply["errMsg"] = pb.GetErrMsg()
//空切片
if v := pb.GetSingleUserMsg(); v != nil {
msg["single"] = v
log.ErrorByKv("rpc call failed to getSeqReq", pbData.OperationID, "err", err, "pbData", pbData.String())
nReply.ErrCode = 200
nReply.ErrMsg = err.Error()
ws.getSeqResp(conn, m, nReply)
} else {
msg["single"] = []pbChat.GatherFormat{}
log.InfoByKv("rpc call success to getSeqReq", pbData.OperationID, "replyData", reply.String())
ws.getSeqResp(conn, m, reply)
}
if v := pb.GetGroupUserMsg(); v != nil {
msg["group"] = v
} else {
msg["group"] = []pbChat.GatherFormat{}
}
func (ws *WServer) getSeqResp(conn *UserConn, m *Req, pb *pbChat.GetMaxAndMinSeqResp) {
var mReplyData open_im_sdk.GetMaxAndMinSeqResp
mReplyData.MaxSeq = pb.GetMaxSeq()
mReplyData.MinSeq = pb.GetMinSeq()
b, _ := proto.Marshal(&mReplyData)
mReply := Resp{
ReqIdentifier: m.ReqIdentifier,
MsgIncr: m.MsgIncr,
ErrCode: pb.GetErrCode(),
ErrMsg: pb.GetErrMsg(),
OperationID: m.OperationID,
Data: b,
}
msg["maxSeq"] = pb.GetMaxSeq()
msg["minSeq"] = pb.GetMinSeq()
mReply["data"] = msg
ws.sendMsg(conn, mReply)
}
func (ws *WServer) pullMsgReq(conn *websocket.Conn, m *Req) {
log.InfoByKv("Ws call success to pullMsgReq", m.OperationID, "Parameters", m)
reply := new(pbChat.PullMessageResp)
func (ws *WServer) pullMsgReq(conn *UserConn, m *Req) {
log.NewInfo(m.OperationID, "Ws call success to pullMsgReq", m.ReqIdentifier, m.MsgIncr, m.SendID)
nReply := new(pbChat.PullMessageResp)
isPass, errCode, errMsg, data := ws.argsValidate(m, constant.WSPullMsg)
if isPass {
pbData := pbChat.PullMessageReq{}
@ -114,83 +109,174 @@ func (ws *WServer) pullMsgReq(conn *websocket.Conn, m *Req) {
pbData.OperationID = m.OperationID
pbData.SeqBegin = data.(SeqData).SeqBegin
pbData.SeqEnd = data.(SeqData).SeqEnd
grpcConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImOfflineMessageName)
grpcConn := getcdv3.GetOfflineMessageConn()
msgClient := pbChat.NewChatClient(grpcConn)
reply, err := msgClient.PullMessage(context.Background(), &pbData)
if err != nil {
log.ErrorByKv("PullMessage error", pbData.OperationID, "err", err.Error())
return
nReply.ErrCode = 200
nReply.ErrMsg = err.Error()
ws.pullMsgResp(conn, m, nReply)
} else {
log.InfoByKv("rpc call success to pullMsgRep", pbData.OperationID, "ReplyArgs", reply.String(), "maxSeq", reply.GetMaxSeq(),
"MinSeq", reply.GetMinSeq(), "singLen", len(reply.GetSingleUserMsg()), "groupLen", len(reply.GetGroupUserMsg()))
ws.pullMsgResp(conn, m, reply)
}
log.InfoByKv("rpc call success to pullMsgRep", pbData.OperationID, "ReplyArgs", reply.String(), "maxSeq", reply.GetMaxSeq(),
"MinSeq", reply.GetMinSeq(), "singLen", len(reply.GetSingleUserMsg()), "groupLen", len(reply.GetGroupUserMsg()))
ws.pullMsgResp(conn, m, reply)
} else {
reply.ErrCode = errCode
reply.ErrMsg = errMsg
ws.pullMsgResp(conn, m, reply)
nReply.ErrCode = errCode
nReply.ErrMsg = errMsg
ws.pullMsgResp(conn, m, nReply)
}
}
func (ws *WServer) pullMsgResp(conn *UserConn, m *Req, pb *pbChat.PullMessageResp) {
log.NewInfo(m.OperationID, "pullMsgResp come here ", pb.String())
var mReplyData open_im_sdk.PullMessageBySeqListResp
a, err := json.Marshal(pb.SingleUserMsg)
if err != nil {
log.NewError(m.OperationID, "GetSingleUserMsg,json marshal,err", err.Error())
}
log.NewInfo(m.OperationID, "pullMsgResp json is ", len(pb.SingleUserMsg))
err = json.Unmarshal(a, &mReplyData.SingleUserMsg)
if err != nil {
log.NewError(m.OperationID, "SingleUserMsg,json Unmarshal,err", err.Error())
}
b, err := json.Marshal(pb.GroupUserMsg)
if err != nil {
log.NewError(m.OperationID, "mReplyData,json marshal,err", err.Error())
}
err = json.Unmarshal(b, &mReplyData.GroupUserMsg)
if err != nil {
log.NewError(m.OperationID, "test SingleUserMsg,json Unmarshal,err", err.Error())
}
c, err := proto.Marshal(&mReplyData)
log.NewInfo(m.OperationID, "test info is ", len(mReplyData.SingleUserMsg), mReplyData.SingleUserMsg)
mReply := Resp{
ReqIdentifier: m.ReqIdentifier,
MsgIncr: m.MsgIncr,
ErrCode: pb.GetErrCode(),
ErrMsg: pb.GetErrMsg(),
OperationID: m.OperationID,
Data: c,
}
log.NewInfo(m.OperationID, "pullMsgResp all data is ", mReply.ReqIdentifier, mReply.MsgIncr, mReply.ErrCode, mReply.ErrMsg,
len(mReply.Data))
func (ws *WServer) sendMsgResp(conn *websocket.Conn, m *Req, pb *pbChat.UserSendMsgResp) {
mReply := make(map[string]interface{})
mReplyData := make(map[string]interface{})
mReply["reqIdentifier"] = m.ReqIdentifier
mReply["msgIncr"] = m.MsgIncr
mReply["errCode"] = pb.GetErrCode()
mReply["errMsg"] = pb.GetErrMsg()
mReplyData["clientMsgID"] = pb.GetClientMsgID()
mReplyData["serverMsgID"] = pb.GetServerMsgID()
mReply["data"] = mReplyData
ws.sendMsg(conn, mReply)
}
func (ws *WServer) sendMsgReq(conn *websocket.Conn, m *Req) {
log.InfoByKv("Ws call success to sendMsgReq", m.OperationID, "Parameters", m)
reply := new(pbChat.UserSendMsgResp)
}
func (ws *WServer) pullMsgBySeqListReq(conn *UserConn, m *Req) {
log.NewInfo(m.OperationID, "Ws call success to pullMsgBySeqListReq start", m.SendID, m.ReqIdentifier, m.MsgIncr)
nReply := new(pbChat.PullMessageResp)
isPass, errCode, errMsg, data := ws.argsValidate(m, constant.WSPullMsgBySeqList)
log.NewInfo(m.OperationID, "Ws call success to pullMsgBySeqListReq middle", m.SendID, m.ReqIdentifier, m.MsgIncr, data.(open_im_sdk.PullMessageBySeqListReq).SeqList)
if isPass {
pbData := pbChat.PullMessageBySeqListReq{}
pbData.SeqList = data.(open_im_sdk.PullMessageBySeqListReq).SeqList
pbData.UserID = m.SendID
pbData.OperationID = m.OperationID
grpcConn := getcdv3.GetOfflineMessageConn()
msgClient := pbChat.NewChatClient(grpcConn)
reply, err := msgClient.PullMessageBySeqList(context.Background(), &pbData)
if err != nil {
log.NewError(pbData.OperationID, "pullMsgBySeqListReq err", err.Error())
nReply.ErrCode = 200
nReply.ErrMsg = err.Error()
ws.pullMsgResp(conn, m, nReply)
} else {
log.NewInfo(pbData.OperationID, "rpc call success to pullMsgBySeqListReq", reply.String(), reply.GetMaxSeq(), reply.GetMinSeq(), len(reply.GetSingleUserMsg()), len(reply.GetGroupUserMsg()))
ws.pullMsgResp(conn, m, reply)
}
} else {
nReply.ErrCode = errCode
nReply.ErrMsg = errMsg
ws.pullMsgResp(conn, m, nReply)
}
}
func (ws *WServer) sendMsgReq(conn *UserConn, m *Req, sendTime int64) {
log.NewInfo(m.OperationID, "Ws call success to sendMsgReq start", m.MsgIncr, m.ReqIdentifier, m.SendID, sendTime)
nReply := new(pbChat.UserSendMsgResp)
isPass, errCode, errMsg, pData := ws.argsValidate(m, constant.WSSendMsg)
if isPass {
data := pData.(MsgData)
data := pData.(open_im_sdk.UserSendMsgReq)
pbData := pbChat.UserSendMsgReq{
ReqIdentifier: m.ReqIdentifier,
Token: m.Token,
SendID: m.SendID,
OperationID: m.OperationID,
PlatformID: data.PlatformID,
SessionType: data.SessionType,
MsgFrom: data.MsgFrom,
ContentType: data.ContentType,
RecvID: data.RecvID,
ForceList: data.ForceList,
Content: data.Content,
Options: utils.MapToJsonString(data.Options),
ClientMsgID: data.ClientMsgID,
OffLineInfo: utils.MapToJsonString(data.OfflineInfo),
ReqIdentifier: m.ReqIdentifier,
Token: m.Token,
SendID: m.SendID,
OperationID: m.OperationID,
PlatformID: data.PlatformID,
SessionType: data.SessionType,
MsgFrom: data.MsgFrom,
ContentType: data.ContentType,
RecvID: data.RecvID,
ForceList: data.ForceList,
SenderNickName: data.SenderNickName,
SenderFaceURL: data.SenderFaceURL,
Content: data.Content,
Options: utils.MapIntToJsonString(data.Options),
ClientMsgID: data.ClientMsgID,
SendTime: sendTime,
}
log.InfoByKv("Ws call success to sendMsgReq", m.OperationID, "Parameters", m)
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImOfflineMessageName)
log.NewInfo(m.OperationID, "Ws call success to sendMsgReq middle", m.ReqIdentifier, m.SendID, m.MsgIncr, data)
etcdConn := getcdv3.GetOfflineMessageConn()
client := pbChat.NewChatClient(etcdConn)
log.Info("", "", "api UserSendMsg call, api call rpc...")
reply, _ := client.UserSendMsg(context.Background(), &pbData)
log.Info("", "", "api UserSendMsg call end..., [data: %s] [reply: %s]", pbData.String(), reply.String())
ws.sendMsgResp(conn, m, reply)
reply, err := client.UserSendMsg(context.Background(), &pbData)
if err != nil {
log.NewError(pbData.OperationID, "UserSendMsg err", err.Error())
nReply.ErrCode = 200
nReply.ErrMsg = err.Error()
ws.sendMsgResp(conn, m, nReply, sendTime)
} else {
log.NewInfo(pbData.OperationID, "rpc call success to sendMsgReq", reply.String())
ws.sendMsgResp(conn, m, reply, sendTime)
}
} else {
reply.ErrCode = errCode
reply.ErrMsg = errMsg
ws.sendMsgResp(conn, m, reply)
nReply.ErrCode = errCode
nReply.ErrMsg = errMsg
ws.sendMsgResp(conn, m, nReply, sendTime)
}
}
func (ws *WServer) sendMsgResp(conn *UserConn, m *Req, pb *pbChat.UserSendMsgResp, sendTime int64) {
// := make(map[string]interface{})
var mReplyData open_im_sdk.UserSendMsgResp
mReplyData.ClientMsgID = pb.GetClientMsgID()
mReplyData.ServerMsgID = pb.GetServerMsgID()
mReplyData.SendTime = sendTime
b, _ := proto.Marshal(&mReplyData)
mReply := Resp{
ReqIdentifier: m.ReqIdentifier,
MsgIncr: m.MsgIncr,
ErrCode: pb.GetErrCode(),
ErrMsg: pb.GetErrMsg(),
OperationID: m.OperationID,
Data: b,
}
ws.sendMsg(conn, mReply)
}
func (ws *WServer) sendMsg(conn *websocket.Conn, mReply map[string]interface{}) {
bMsg, _ := json.Marshal(mReply)
err := ws.writeMsg(conn, websocket.TextMessage, bMsg)
func (ws *WServer) sendMsg(conn *UserConn, mReply interface{}) {
var b bytes.Buffer
enc := gob.NewEncoder(&b)
err := enc.Encode(mReply)
if err != nil {
log.NewError(mReply.(Resp).OperationID, mReply.(Resp).ReqIdentifier, mReply.(Resp).ErrCode, mReply.(Resp).ErrMsg, "Encode Msg error", conn.RemoteAddr().String(), ws.getUserUid(conn), err.Error())
return
}
err = ws.writeMsg(conn, websocket.BinaryMessage, b.Bytes())
if err != nil {
log.ErrorByKv("WS WriteMsg error", "", "userIP", conn.RemoteAddr().String(), "userUid", ws.getUserUid(conn), "error", err, "mReply", mReply)
log.NewError(mReply.(Resp).OperationID, mReply.(Resp).ReqIdentifier, mReply.(Resp).ErrCode, mReply.(Resp).ErrMsg, "WS WriteMsg error", conn.RemoteAddr().String(), ws.getUserUid(conn), err.Error())
}
}
func (ws *WServer) sendErrMsg(conn *websocket.Conn, errCode int32, errMsg string) {
mReply := make(map[string]interface{})
mReply["errCode"] = errCode
mReply["errMsg"] = errMsg
func (ws *WServer) sendErrMsg(conn *UserConn, errCode int32, errMsg string, reqIdentifier int32, msgIncr string, operationID string) {
mReply := Resp{
ReqIdentifier: reqIdentifier,
MsgIncr: msgIncr,
ErrCode: errCode,
ErrMsg: errMsg,
OperationID: operationID,
}
ws.sendMsg(conn, mReply)
}

@ -6,14 +6,18 @@ import (
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbRelay "Open_IM/pkg/proto/relay"
open_im_sdk "Open_IM/pkg/proto/sdk_ws"
"Open_IM/pkg/utils"
"bytes"
"context"
"encoding/json"
"encoding/gob"
"fmt"
"github.com/gorilla/websocket"
"google.golang.org/grpc"
"github.com/golang/protobuf/proto"
"net"
"strings"
"github.com/gorilla/websocket"
"google.golang.org/grpc"
)
type RPCServer struct {
@ -55,105 +59,87 @@ func (r *RPCServer) MsgToUser(_ context.Context, in *pbRelay.MsgToUserReq) (*pbR
log.InfoByKv("PushMsgToUser is arriving", in.OperationID, "args", in.String())
var resp []*pbRelay.SingleMsgToUser
var RecvID string
msg := make(map[string]interface{})
mReply := make(map[string]interface{})
mReply["reqIdentifier"] = constant.WSPushMsg
mReply["errCode"] = 0
mReply["errMsg"] = ""
msg["sendID"] = in.SendID
msg["recvID"] = in.RecvID
msg["msgFrom"] = in.MsgFrom
msg["contentType"] = in.ContentType
msg["sessionType"] = in.SessionType
msg["senderNickName"] = in.SenderNickName
msg["senderFaceUrl"] = in.SenderFaceURL
msg["clientMsgID"] = in.ClientMsgID
msg["serverMsgID"] = in.ServerMsgID
msg["content"] = in.Content
msg["seq"] = in.RecvSeq
msg["sendTime"] = in.SendTime
msg["senderPlatformID"] = in.PlatformID
mReply["data"] = msg
bMsg, _ := json.Marshal(mReply)
msg := open_im_sdk.MsgData{
SendID: in.SendID,
RecvID: in.RecvID,
MsgFrom: in.MsgFrom,
ContentType: in.ContentType,
SessionType: in.SessionType,
SenderNickName: in.SenderNickName,
SenderFaceURL: in.SenderFaceURL,
ClientMsgID: in.ClientMsgID,
ServerMsgID: in.ServerMsgID,
Content: in.Content,
Seq: in.RecvSeq,
SendTime: in.SendTime,
SenderPlatformID: in.PlatformID,
}
msgBytes, _ := proto.Marshal(&msg)
mReply := Resp{
ReqIdentifier: constant.WSPushMsg,
OperationID: in.OperationID,
Data: msgBytes,
}
var replyBytes bytes.Buffer
enc := gob.NewEncoder(&replyBytes)
err := enc.Encode(mReply)
if err != nil {
log.NewError(in.OperationID, "data encode err", err.Error())
}
switch in.GetSessionType() {
case constant.SingleChatType:
RecvID = in.GetRecvID()
case constant.GroupChatType:
RecvID = strings.Split(in.GetRecvID(), " ")[0]
}
log.InfoByKv("test", in.OperationID, "wsUserToConn", ws.wsUserToConn)
for key, conn := range ws.wsUserToConn {
UIDAndPID := strings.Split(key, " ")
if UIDAndPID[0] == RecvID {
resultCode := sendMsgToUser(conn, bMsg, in, UIDAndPID[1], UIDAndPID[0])
var tag bool
var UIDAndPID []string
userIDList := genUidPlatformArray(RecvID)
for _, v := range userIDList {
UIDAndPID = strings.Split(v, " ")
if conn := ws.getUserConn(v); conn != nil {
tag = true
resultCode := sendMsgToUser(conn, replyBytes.Bytes(), in, UIDAndPID[1], UIDAndPID[0])
temp := &pbRelay.SingleMsgToUser{
ResultCode: resultCode,
RecvID: UIDAndPID[0],
RecvPlatFormID: utils.PlatformNameToID(UIDAndPID[1]),
}
resp = append(resp, temp)
} else {
temp := &pbRelay.SingleMsgToUser{
ResultCode: -1,
RecvID: UIDAndPID[0],
RecvPlatFormID: utils.PlatformNameToID(UIDAndPID[1]),
}
resp = append(resp, temp)
}
}
//switch in.GetContentType() {
//case constant.SyncSenderMsg:
// log.InfoByKv("come sync", in.OperationID, "args", in.String())
// RecvID = in.GetSendID()
// if in.MsgFrom != constant.SysMsgType {
// for key, conn := range ws.wsUserToConn {
// UIDAndPID := strings.Split(key, " ")
// if UIDAndPID[0] == RecvID && utils.PlatformIDToName(in.GetPlatformID()) != UIDAndPID[1] {
// resultCode := sendMsgToUser(conn, bMsg, in, UIDAndPID[1], UIDAndPID[0])
// temp := &pbRelay.SingleMsgToUser{
// ResultCode: resultCode,
// RecvID: UIDAndPID[0],
// RecvPlatFormID: utils.PlatformNameToID(UIDAndPID[1]),
// }
// resp = append(resp, temp)
// }
//
// }
// }
//default:
// log.InfoByKv("not come sync", in.OperationID, "args", in.String())
// switch in.SessionType {
// case constant.SingleChatType:
// log.InfoByKv("come single", in.OperationID, "args", in.String())
// RecvID = in.GetRecvID()
// case constant.GroupChatType:
// RecvID = strings.Split(in.GetRecvID(), " ")[0]
// default:
// }
// log.InfoByKv("come for range", in.OperationID, "args", in.String())
//
// for key, conn := range ws.wsUserToConn {
// UIDAndPID := strings.Split(key, " ")
// if UIDAndPID[0] == RecvID {
// resultCode := sendMsgToUser(conn, bMsg, in, UIDAndPID[1], UIDAndPID[0])
// temp := &pbRelay.SingleMsgToUser{
// ResultCode: resultCode,
// RecvID: UIDAndPID[0],
// RecvPlatFormID: utils.PlatformNameToID(UIDAndPID[1]),
// }
// resp = append(resp, temp)
// }
// }
//}
if !tag {
log.NewError(in.OperationID, "push err ,no matched ws conn not in map", in.String())
}
return &pbRelay.MsgToUserResp{
Resp: resp,
}, nil
}
func sendMsgToUser(conn *websocket.Conn, bMsg []byte, in *pbRelay.MsgToUserReq, RecvPlatForm, RecvID string) (ResultCode int64) {
err := ws.writeMsg(conn, websocket.TextMessage, bMsg)
func sendMsgToUser(conn *UserConn, bMsg []byte, in *pbRelay.MsgToUserReq, RecvPlatForm, RecvID string) (ResultCode int64) {
err := ws.writeMsg(conn, websocket.BinaryMessage, bMsg)
if err != nil {
log.ErrorByKv("PushMsgToUser is failed By Ws", "", "Addr", conn.RemoteAddr().String(),
"error", err, "senderPlatform", utils.PlatformIDToName(in.PlatformID), "recvPlatform", RecvPlatForm, "args", in.String(), "recvID", RecvID)
ResultCode = -2
return ResultCode
} else {
log.InfoByKv("PushMsgToUser is success By Ws", in.OperationID, "args", in.String())
log.InfoByKv("PushMsgToUser is success By Ws", in.OperationID, "args", in.String(), "recvPlatForm", RecvPlatForm, "recvID", RecvID)
ResultCode = 0
return ResultCode
}
}
func genUidPlatformArray(uid string) (array []string) {
for i := 1; i <= utils.LinuxPlatformID; i++ {
array = append(array, uid+" "+utils.PlatformIDToName(int32(i)))
}
return array
}

@ -9,17 +9,27 @@ package gate
import (
"Open_IM/pkg/common/constant"
"Open_IM/pkg/common/log"
"github.com/mitchellh/mapstructure"
open_im_sdk "Open_IM/pkg/proto/sdk_ws"
"github.com/golang/protobuf/proto"
)
type Req struct {
ReqIdentifier int32 `json:"reqIdentifier" validate:"required"`
Token string `json:"token" validate:"required"`
SendID string `json:"sendID" validate:"required"`
OperationID string `json:"operationID" validate:"required"`
MsgIncr int32 `json:"msgIncr" validate:"required"`
Data map[string]interface{} `json:"data"`
ReqIdentifier int32 `json:"reqIdentifier" validate:"required"`
Token string `json:"token" `
SendID string `json:"sendID" validate:"required"`
OperationID string `json:"operationID" validate:"required"`
MsgIncr string `json:"msgIncr" validate:"required"`
Data []byte `json:"data"`
}
type Resp struct {
ReqIdentifier int32 `json:"reqIdentifier"`
MsgIncr string `json:"msgIncr"`
OperationID string `json:"operationID"`
ErrCode int32 `json:"errCode"`
ErrMsg string `json:"errMsg"`
Data []byte `json:"data"`
}
type SeqData struct {
SeqBegin int64 `mapstructure:"seqBegin" validate:"required"`
SeqEnd int64 `mapstructure:"seqEnd" validate:"required"`
@ -30,31 +40,64 @@ type MsgData struct {
MsgFrom int32 `mapstructure:"msgFrom" validate:"required"`
ContentType int32 `mapstructure:"contentType" validate:"required"`
RecvID string `mapstructure:"recvID" validate:"required"`
ForceList []string `mapstructure:"forceList" validate:"required"`
ForceList []string `mapstructure:"forceList"`
Content string `mapstructure:"content" validate:"required"`
Options map[string]interface{} `mapstructure:"options" validate:"required"`
ClientMsgID string `mapstructure:"clientMsgID" validate:"required"`
OfflineInfo map[string]interface{} `mapstructure:"offlineInfo" validate:"required"`
Ext map[string]interface{} `mapstructure:"ext"`
}
type MaxSeqResp struct {
MaxSeq int64 `json:"maxSeq"`
}
type PullMessageResp struct {
}
type SeqListData struct {
SeqList []int64 `mapstructure:"seqList" validate:"required"`
}
func (ws *WServer) argsValidate(m *Req, r int32) (isPass bool, errCode int32, errMsg string, data interface{}) {
func (ws *WServer) argsValidate(m *Req, r int32) (isPass bool, errCode int32, errMsg string, returnData interface{}) {
switch r {
case constant.WSPullMsg:
data = SeqData{}
case constant.WSSendMsg:
data = MsgData{}
default:
}
if err := mapstructure.WeakDecode(m.Data, &data); err != nil {
log.ErrorByKv("map to Data struct err", "", "err", err.Error(), "reqIdentifier", r)
return false, 203, err.Error(), nil
} else if err := validate.Struct(data); err != nil {
log.ErrorByKv("data args validate err", "", "err", err.Error(), "reqIdentifier", r)
return false, 204, err.Error(), nil
} else {
data := open_im_sdk.UserSendMsgReq{}
if err := proto.Unmarshal(m.Data, &data); err != nil {
log.ErrorByKv("Decode Data struct err", "", "err", err.Error(), "reqIdentifier", r)
return false, 203, err.Error(), nil
}
if err := validate.Struct(data); err != nil {
log.ErrorByKv("data args validate err", "", "err", err.Error(), "reqIdentifier", r)
return false, 204, err.Error(), nil
}
return true, 0, "", data
case constant.WSPullMsgBySeqList:
data := open_im_sdk.PullMessageBySeqListReq{}
if err := proto.Unmarshal(m.Data, &data); err != nil {
log.ErrorByKv("Decode Data struct err", "", "err", err.Error(), "reqIdentifier", r)
return false, 203, err.Error(), nil
}
if err := validate.Struct(data); err != nil {
log.ErrorByKv("data args validate err", "", "err", err.Error(), "reqIdentifier", r)
return false, 204, err.Error(), nil
}
return true, 0, "", data
default:
}
return false, 204, "args err", nil
//b := bytes.NewBuffer(m.Data)
//dec := gob.NewDecoder(b)
//err := dec.Decode(&data)
//if err != nil {
// log.ErrorByKv("Decode Data struct err", "", "err", err.Error(), "reqIdentifier", r)
// return false, 203, err.Error(), nil
//}
//if err := mapstructure.WeakDecode(m.Data, &data); err != nil {
// log.ErrorByKv("map to Data struct err", "", "err", err.Error(), "reqIdentifier", r)
// return false, 203, err.Error(), nil
//} else
}

@ -6,23 +6,28 @@ import (
"Open_IM/pkg/utils"
"github.com/gorilla/websocket"
"net/http"
"sync"
"time"
)
type UserConn struct {
*websocket.Conn
w *sync.Mutex
}
type WServer struct {
wsAddr string
wsMaxConnNum int
wsUpGrader *websocket.Upgrader
wsConnToUser map[*websocket.Conn]string
wsUserToConn map[string]*websocket.Conn
wsConnToUser map[*UserConn]string
wsUserToConn map[string]*UserConn
}
func (ws *WServer) onInit(wsPort int) {
ip := utils.ServerIP
ws.wsAddr = ip + ":" + utils.IntToString(wsPort)
ws.wsMaxConnNum = config.Config.LongConnSvr.WebsocketMaxConnNum
ws.wsConnToUser = make(map[*websocket.Conn]string)
ws.wsUserToConn = make(map[string]*websocket.Conn)
ws.wsConnToUser = make(map[*UserConn]string)
ws.wsUserToConn = make(map[string]*UserConn)
ws.wsUpGrader = &websocket.Upgrader{
HandshakeTimeout: time.Duration(config.Config.LongConnSvr.WebsocketTimeOut) * time.Second,
ReadBufferSize: config.Config.LongConnSvr.WebsocketMaxMsgLen,
@ -49,35 +54,39 @@ func (ws *WServer) wsHandler(w http.ResponseWriter, r *http.Request) {
//Connection mapping relationship,
//userID+" "+platformID->conn
SendID := query["sendID"][0] + " " + utils.PlatformIDToName(int32(utils.StringToInt64(query["platformID"][0])))
ws.addUserConn(SendID, conn)
go ws.readMsg(conn)
//Initialize a lock for each user
newConn := &UserConn{conn, new(sync.Mutex)}
ws.addUserConn(SendID, newConn)
go ws.readMsg(newConn)
}
}
}
func (ws *WServer) readMsg(conn *websocket.Conn) {
func (ws *WServer) readMsg(conn *UserConn) {
for {
msgType, msg, err := conn.ReadMessage()
messageType, msg, err := conn.ReadMessage()
if messageType == websocket.PingMessage {
log.NewInfo("", "this is a pingMessage")
}
if err != nil {
log.ErrorByKv("WS ReadMsg error", "", "userIP", conn.RemoteAddr().String(), "userUid", ws.getUserUid(conn), "error", err)
ws.delUserConn(conn)
return
} else {
log.ErrorByKv("test", "", "msgType", msgType, "userIP", conn.RemoteAddr().String(), "userUid", ws.getUserUid(conn))
//log.ErrorByKv("test", "", "msgType", msgType, "userIP", conn.RemoteAddr().String(), "userUid", ws.getUserUid(conn))
}
ws.msgParse(conn, msg)
//ws.writeMsg(conn, 1, chat)
}
}
func (ws *WServer) writeMsg(conn *websocket.Conn, a int, msg []byte) error {
rwLock.Lock()
defer rwLock.Unlock()
func (ws *WServer) writeMsg(conn *UserConn, a int, msg []byte) error {
conn.w.Lock()
defer conn.w.Unlock()
return conn.WriteMessage(a, msg)
}
func (ws *WServer) addUserConn(uid string, conn *websocket.Conn) {
func (ws *WServer) addUserConn(uid string, conn *UserConn) {
rwLock.Lock()
defer rwLock.Unlock()
if oldConn, ok := ws.wsUserToConn[uid]; ok {
@ -95,7 +104,7 @@ func (ws *WServer) addUserConn(uid string, conn *websocket.Conn) {
}
func (ws *WServer) delUserConn(conn *websocket.Conn) {
func (ws *WServer) delUserConn(conn *UserConn) {
rwLock.Lock()
defer rwLock.Unlock()
var uidPlatform string
@ -111,12 +120,12 @@ func (ws *WServer) delUserConn(conn *websocket.Conn) {
}
err := conn.Close()
if err != nil {
log.ErrorByKv("close err", "", "uid", uidPlatform, "conn", conn)
log.ErrorByKv("close err", "", "uid", uidPlatform)
}
}
func (ws *WServer) getUserConn(uid string) *websocket.Conn {
func (ws *WServer) getUserConn(uid string) *UserConn {
rwLock.RLock()
defer rwLock.RUnlock()
if conn, ok := ws.wsUserToConn[uid]; ok {
@ -124,7 +133,7 @@ func (ws *WServer) getUserConn(uid string) *websocket.Conn {
}
return nil
}
func (ws *WServer) getUserUid(conn *websocket.Conn) string {
func (ws *WServer) getUserUid(conn *UserConn) string {
rwLock.RLock()
defer rwLock.RUnlock()

@ -1,17 +1,22 @@
package logic
import (
pbMsg "Open_IM/pkg/proto/chat"
"Open_IM/pkg/common/db"
"Open_IM/pkg/common/db/mysql_model/im_mysql_model"
"Open_IM/pkg/common/log"
pbMsg "Open_IM/pkg/proto/chat"
"Open_IM/pkg/utils"
)
func saveUserChat(uid string, pbMsg *pbMsg.MsgSvrToPushSvrChatMsg) error {
time := utils.GetCurrentTimestampByMill()
seq, err := db.DB.IncrUserSeq(uid)
if err != nil {
log.NewError(pbMsg.OperationID, "data insert to redis err", err.Error(), pbMsg.String())
return err
}
pbMsg.RecvSeq = seq
log.NewInfo(pbMsg.OperationID, "IncrUserSeq cost time", utils.GetCurrentTimestampByMill()-time)
return db.DB.SaveUserChat(uid, pbMsg.SendTime, pbMsg)
}

@ -10,9 +10,10 @@ import (
pbPush "Open_IM/pkg/proto/push"
"Open_IM/pkg/utils"
"context"
"strings"
"github.com/Shopify/sarama"
"github.com/golang/protobuf/proto"
"strings"
)
type fcb func(msg []byte, msgKey string)
@ -33,6 +34,7 @@ func (mc *HistoryConsumerHandler) Init() {
func (mc *HistoryConsumerHandler) handleChatWs2Mongo(msg []byte, msgKey string) {
log.InfoByKv("chat come mongo!!!", "", "chat", string(msg))
time := utils.GetCurrentTimestampByNano()
pbData := pbMsg.WSToMsgSvrChatMsg{}
err := proto.Unmarshal(msg, &pbData)
if err != nil {
@ -58,48 +60,53 @@ func (mc *HistoryConsumerHandler) handleChatWs2Mongo(msg []byte, msgKey string)
isHistory := utils.GetSwitchFromOptions(Options, "history")
//Control whether to store history messages (mysql)
isPersist := utils.GetSwitchFromOptions(Options, "persistent")
if pbData.SessionType == constant.SingleChatType {
log.Info("", "", "msg_transfer chat type = SingleChatType", isHistory, isPersist)
switch pbData.SessionType {
case constant.SingleChatType:
log.NewDebug(pbSaveData.OperationID, "msg_transfer chat type = SingleChatType", isHistory, isPersist)
if isHistory {
if msgKey == pbSaveData.RecvID {
err := saveUserChat(pbData.RecvID, &pbSaveData)
if err != nil {
log.ErrorByKv("data insert to mongo err", pbSaveData.OperationID, "data", pbSaveData.String(), "err", err.Error())
log.NewError(pbSaveData.OperationID, "single data insert to mongo err", err.Error(), pbSaveData.String())
return
}
} else if msgKey == pbSaveData.SendID {
err := saveUserChat(pbData.SendID, &pbSaveData)
if err != nil {
log.ErrorByKv("data insert to mongo err", pbSaveData.OperationID, "data", pbSaveData.String(), "err", err.Error())
log.NewError(pbSaveData.OperationID, "single data insert to mongo err", err.Error(), pbSaveData.String())
return
}
//if isSenderSync {
// pbSaveData.ContentType = constant.SyncSenderMsg
// log.WarnByKv("SyncSenderMsg come here", pbData.OperationID, pbSaveData.String())
// sendMessageToPush(&pbSaveData)
//}
}
log.NewDebug(pbSaveData.OperationID, "saveUserChat cost time ", utils.GetCurrentTimestampByNano()-time)
}
if msgKey == pbSaveData.RecvID {
pbSaveData.Options = pbData.Options
pbSaveData.OfflineInfo = pbData.OfflineInfo
sendMessageToPush(&pbSaveData)
go sendMessageToPush(&pbSaveData)
log.NewDebug(pbSaveData.OperationID, "sendMessageToPush cost time ", utils.GetCurrentTimestampByNano()-time)
}
log.InfoByKv("msg_transfer handle topic success...", "", "")
} else if pbData.SessionType == constant.GroupChatType {
log.Info("", "", "msg_transfer chat type = GroupChatType")
case constant.GroupChatType:
log.NewDebug(pbSaveData.OperationID, "msg_transfer chat type = GroupChatType", isHistory, isPersist)
if isHistory {
uidAndGroupID := strings.Split(pbData.RecvID, " ")
saveUserChat(uidAndGroupID[0], &pbSaveData)
err := saveUserChat(uidAndGroupID[0], &pbSaveData)
if err != nil {
log.NewError(pbSaveData.OperationID, "group data insert to mongo err", pbSaveData.String(), uidAndGroupID[0], err.Error())
return
}
}
pbSaveData.Options = pbData.Options
pbSaveData.OfflineInfo = pbData.OfflineInfo
sendMessageToPush(&pbSaveData)
log.InfoByKv("msg_transfer handle topic success...", "", "")
} else {
log.Error("", "", "msg_transfer recv chat err, chat.MsgFrom = %d", pbData.SessionType)
go sendMessageToPush(&pbSaveData)
default:
log.NewError(pbSaveData.OperationID, "SessionType error", pbSaveData.String())
return
}
log.NewDebug(pbSaveData.OperationID, "msg_transfer handle topic data to database success...", pbSaveData.String())
}
func (HistoryConsumerHandler) Setup(_ sarama.ConsumerGroupSession) error { return nil }
@ -132,7 +139,7 @@ func sendMessageToPush(message *pbMsg.MsgSvrToPushSvrChatMsg) {
msg.SendTime = message.SendTime
msg.MsgID = message.MsgID
msg.OfflineInfo = message.OfflineInfo
grpcConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImPushName)
grpcConn := getcdv3.GetPushConn()
if grpcConn == nil {
log.ErrorByKv("rpc dial failed", msg.OperationID, "push data", msg.String())
pid, offset, err := producer.SendMessage(message)

@ -0,0 +1,13 @@
package common
import (
"encoding/base64"
"fmt"
)
func GetAuthorization(Appkey string, MasterSecret string) string {
str := fmt.Sprintf("%s:%s", Appkey, MasterSecret)
buf := []byte(str)
Authorization := fmt.Sprintf("Basic %s", base64.StdEncoding.EncodeToString(buf))
return Authorization
}

@ -0,0 +1,55 @@
package push
import (
"Open_IM/internal/push/jpush/common"
"Open_IM/internal/push/jpush/requestBody"
"Open_IM/pkg/common/config"
"bytes"
"encoding/json"
"io/ioutil"
"net/http"
)
type JPushResp struct {
}
func JGAccountListPush(accounts []string, content, detailContent, platform string) ([]byte, error) {
var pf requestBody.Platform
_ = pf.SetPlatform(platform)
var au requestBody.Audience
au.SetAlias(accounts)
var no requestBody.Notification
no.SetAlert(content)
var me requestBody.Message
me.SetMsgContent(detailContent)
var po requestBody.PushObj
po.SetPlatform(&pf)
po.SetAudience(&au)
po.SetNotification(&no)
po.SetMessage(&me)
con, err := json.Marshal(po)
if err != nil {
return nil, err
}
client := &http.Client{}
req, err := http.NewRequest("POST", config.Config.Push.Jpns.PushUrl, bytes.NewBuffer(con))
if err != nil {
return nil, err
}
req.Header.Set("Authorization", common.GetAuthorization(config.Config.Push.Jpns.AppKey, config.Config.Push.Jpns.MasterSecret))
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
result, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
return result, nil
}

@ -0,0 +1,53 @@
package requestBody
const (
TAG = "tag"
TAG_AND = "tag_and"
TAG_NOT = "tag_not"
ALIAS = "alias"
REGISTRATION_ID = "registration_id"
SEGMENT = "segment"
ABTEST = "abtest"
)
type Audience struct {
Object interface{}
audience map[string][]string
}
func (a *Audience) set(key string, v []string) {
if a.audience == nil {
a.audience = make(map[string][]string)
a.Object = a.audience
}
//v, ok = this.audience[key]
//if ok {
// return
//}
a.audience[key] = v
}
func (a *Audience) SetTag(tags []string) {
a.set(TAG, tags)
}
func (a *Audience) SetTagAnd(tags []string) {
a.set(TAG_AND, tags)
}
func (a *Audience) SetTagNot(tags []string) {
a.set(TAG_NOT, tags)
}
func (a *Audience) SetAlias(alias []string) {
a.set(ALIAS, alias)
}
func (a *Audience) SetRegistrationId(ids []string) {
a.set(REGISTRATION_ID, ids)
}
func (a *Audience) SetAll() {
a.Object = "all"
}

@ -0,0 +1,27 @@
package requestBody
type Message struct {
MsgContent string `json:"msg_content"`
Title string `json:"title,omitempty"`
ContentType string `json:"content_type,omitempty"`
Extras map[string]interface{} `json:"extras,omitempty"`
}
func (m *Message) SetMsgContent(c string) {
m.MsgContent = c
}
func (m *Message) SetTitle(t string) {
m.Title = t
}
func (m *Message) SetContentType(c string) {
m.ContentType = c
}
func (m *Message) SetExtras(key string, value interface{}) {
if m.Extras == nil {
m.Extras = make(map[string]interface{})
}
m.Extras[key] = value
}

@ -0,0 +1,17 @@
package requestBody
type Notification struct {
Alert string `json:"alert,omitempty"`
Android *Android `json:"android,omitempty"`
IOS *Ios `json:"ios,omitempty"`
}
type Android struct {
}
type Ios struct {
}
func (n *Notification) SetAlert(alert string) {
n.Alert = alert
}

@ -0,0 +1,83 @@
package requestBody
import (
"Open_IM/pkg/utils"
"errors"
)
const (
ANDROID = "android"
IOS = "ios"
QUICKAPP = "quickapp"
WINDOWSPHONE = "winphone"
ALL = "all"
)
type Platform struct {
Os interface{}
osArry []string
}
func (p *Platform) Set(os string) error {
if p.Os == nil {
p.osArry = make([]string, 0, 4)
} else {
switch p.Os.(type) {
case string:
return errors.New("platform is all")
default:
}
}
for _, value := range p.osArry {
if os == value {
return nil
}
}
switch os {
case IOS:
fallthrough
case ANDROID:
fallthrough
case QUICKAPP:
fallthrough
case WINDOWSPHONE:
p.osArry = append(p.osArry, os)
p.Os = p.osArry
default:
return errors.New("unknow platform")
}
return nil
}
func (p *Platform) SetPlatform(platform string) error {
switch platform {
case utils.AndroidPlatformStr:
return p.SetAndroid()
case utils.IOSPlatformStr:
return p.SetIOS()
default:
return errors.New("platform err")
}
}
func (p *Platform) SetIOS() error {
return p.Set(IOS)
}
func (p *Platform) SetAndroid() error {
return p.Set(ANDROID)
}
func (p *Platform) SetQuickApp() error {
return p.Set(QUICKAPP)
}
func (p *Platform) SetWindowsPhone() error {
return p.Set(WINDOWSPHONE)
}
func (p *Platform) SetAll() {
p.Os = ALL
}

@ -0,0 +1,24 @@
package requestBody
type PushObj struct {
Platform interface{} `json:"platform"`
Audience interface{} `json:"audience"`
Notification interface{} `json:"notification,omitempty"`
Message interface{} `json:"message,omitempty"`
}
func (p *PushObj) SetPlatform(pf *Platform) {
p.Platform = pf.Os
}
func (p *PushObj) SetAudience(ad *Audience) {
p.Audience = ad.Object
}
func (p *PushObj) SetNotification(no *Notification) {
p.Notification = no
}
func (p *PushObj) SetMessage(m *Message) {
p.Message = m
}

@ -24,7 +24,7 @@ func Init(rpcPort int) {
log.NewPrivateLog(config.Config.ModuleName.PushName)
rpcServer.Init(rpcPort)
pushCh.Init()
pushTerminal = []int32{utils.IOSPlatformID}
pushTerminal = []int32{utils.IOSPlatformID, utils.AndroidPlatformID}
}
func init() {
producer = kafka.NewKafkaProducer(config.Config.Kafka.Ws2mschat.Addr, config.Config.Kafka.Ws2mschat.Topic)

@ -7,38 +7,39 @@
package logic
import (
push "Open_IM/internal/push/jpush"
rpcChat "Open_IM/internal/rpc/chat"
"Open_IM/internal/rpc/user/internal_service"
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/constant"
"Open_IM/pkg/common/log"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbChat "Open_IM/pkg/proto/chat"
pbGroup "Open_IM/pkg/proto/group"
pbRelay "Open_IM/pkg/proto/relay"
pbGetInfo "Open_IM/pkg/proto/user"
"Open_IM/pkg/utils"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
"context"
"encoding/json"
"fmt"
"strings"
)
type EChatContent struct {
SessionType int `json:"chatType"`
type OpenIMContent struct {
SessionType int `json:"sessionType"`
From string `json:"from"`
To string `json:"to"`
Seq int64 `json:"seq"`
}
type AtContent struct {
Text string `json:"text"`
AtUserList []string `json:"atUserList"`
IsAtSelf bool `json:"isAtSelf"`
}
func MsgToUser(sendPbData *pbRelay.MsgToUserReq, OfflineInfo, Options string) {
var wsResult []*pbRelay.SingleMsgToUser
//isShouldOfflinePush := true
MOptions := utils.JsonStringToMap(Options) //Control whether to push message to sender's other terminal
//isSenderSync := utils.GetSwitchFromOptions(MOptions, "senderSync")
isOfflinePush := utils.GetSwitchFromOptions(MOptions, "offlinePush")
log.InfoByKv("Get chat from msg_transfer And push chat", sendPbData.OperationID, "PushData", sendPbData)
grpcCons := getcdv3.GetConn4Unique(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImOnlineMessageRelayName)
grpcCons := getcdv3.GetOnlineMessageConn()
//Online push message
log.InfoByKv("test", sendPbData.OperationID, "len grpc", len(grpcCons), "data", sendPbData)
for _, v := range grpcCons {
@ -51,101 +52,61 @@ func MsgToUser(sendPbData *pbRelay.MsgToUserReq, OfflineInfo, Options string) {
wsResult = append(wsResult, reply.Resp...)
}
}
log.InfoByKv("push_result", sendPbData.OperationID, "result", wsResult)
if isOfflinePush {
for _, v := range wsResult {
if v.ResultCode == 0 {
continue
}
//supported terminal
for _, t := range pushTerminal {
if v.RecvPlatFormID == t {
//Use offline push messaging
var UIDList []string
UIDList = append(UIDList, sendPbData.RecvID)
var sendUIDList []string
sendUIDList = append(sendUIDList, sendPbData.SendID)
userInfo, err := internal_service.GetUserInfoClient(&pbGetInfo.GetUserInfoReq{UserIDList: sendUIDList, OperationID: sendPbData.OperationID})
if err != nil {
log.ErrorByArgs(fmt.Sprintf("err=%v,call GetUserInfoClient rpc server failed", err))
return
}
customContent := EChatContent{
SessionType: int(sendPbData.SessionType),
From: sendPbData.SendID,
To: sendPbData.RecvID,
Seq: sendPbData.RecvSeq,
}
bCustomContent, _ := json.Marshal(customContent)
jsonCustomContent := string(bCustomContent)
switch sendPbData.ContentType {
case constant.Text:
IOSAccountListPush(UIDList, userInfo.Data[0].Name, sendPbData.Content, jsonCustomContent)
case constant.Picture:
IOSAccountListPush(UIDList, userInfo.Data[0].Name, constant.ContentType2PushContent[constant.Picture], jsonCustomContent)
case constant.Voice:
IOSAccountListPush(UIDList, userInfo.Data[0].Name, constant.ContentType2PushContent[constant.Voice], jsonCustomContent)
case constant.Video:
IOSAccountListPush(UIDList, userInfo.Data[0].Name, constant.ContentType2PushContent[constant.Video], jsonCustomContent)
case constant.File:
IOSAccountListPush(UIDList, userInfo.Data[0].Name, constant.ContentType2PushContent[constant.File], jsonCustomContent)
default:
}
}
}
}
/*for _, t := range pushTerminal {
log.InfoByKv("push_result", sendPbData.OperationID, "result", wsResult, "sendData", sendPbData)
if sendPbData.ContentType != constant.Typing && sendPbData.ContentType != constant.HasReadReceipt {
if isOfflinePush {
for _, v := range wsResult {
if v.RecvPlatFormID == t && v.ResultCode == 0 {
isShouldOfflinePush = false
break
}
}
if isShouldOfflinePush {
//Use offline push messaging
var UIDList []string
UIDList = append(UIDList, sendPbData.RecvID)
var sendUIDList []string
sendUIDList = append(sendUIDList, sendPbData.SendID)
userInfo, err := internal_service.GetUserInfoClient(&pbGetInfo.GetUserInfoReq{UserIDList: sendUIDList, OperationID: sendPbData.OperationID})
if err != nil {
log.ErrorByArgs(fmt.Sprintf("err=%v,call GetUserInfoClient rpc server failed", err))
return
if v.ResultCode == 0 {
continue
}
//supported terminal
for _, t := range pushTerminal {
if v.RecvPlatFormID == t {
//Use offline push messaging
var UIDList []string
UIDList = append(UIDList, v.RecvID)
customContent := OpenIMContent{
SessionType: int(sendPbData.SessionType),
From: sendPbData.SendID,
To: sendPbData.RecvID,
Seq: sendPbData.RecvSeq,
}
bCustomContent, _ := json.Marshal(customContent)
jsonCustomContent := string(bCustomContent)
var content string
switch sendPbData.ContentType {
case constant.Text:
content = constant.ContentType2PushContent[constant.Text]
case constant.Picture:
content = constant.ContentType2PushContent[constant.Picture]
case constant.Voice:
content = constant.ContentType2PushContent[constant.Voice]
case constant.Video:
content = constant.ContentType2PushContent[constant.Video]
case constant.File:
content = constant.ContentType2PushContent[constant.File]
case constant.AtText:
a := AtContent{}
_ = utils.JsonStringToStruct(sendPbData.Content, &a)
if utils.IsContain(v.RecvID, a.AtUserList) {
content = constant.ContentType2PushContent[constant.AtText] + constant.ContentType2PushContent[constant.Common]
} else {
content = constant.ContentType2PushContent[constant.GroupMsg]
}
default:
}
pushResult, err := push.JGAccountListPush(UIDList, content, jsonCustomContent, utils.PlatformIDToName(t))
if err != nil {
log.NewError(sendPbData.OperationID, "offline push error", sendPbData.String(), err.Error(), t)
} else {
log.NewDebug(sendPbData.OperationID, "offline push return result is ", string(pushResult), sendPbData, t)
}
customContent := EChatContent{
SessionType: int(sendPbData.SessionType),
From: sendPbData.SendID,
To: sendPbData.RecvID,
Seq: sendPbData.RecvSeq,
}
bCustomContent, _ := json.Marshal(customContent)
jsonCustomContent := string(bCustomContent)
switch sendPbData.ContentType {
case constant.Text:
IOSAccountListPush(UIDList, userInfo.Data[0].Name, sendPbData.Content, jsonCustomContent)
case constant.Picture:
IOSAccountListPush(UIDList, userInfo.Data[0].Name, constant.ContentType2PushContent[constant.Picture], jsonCustomContent)
case constant.Voice:
IOSAccountListPush(UIDList, userInfo.Data[0].Name, constant.ContentType2PushContent[constant.Voice], jsonCustomContent)
case constant.Video:
IOSAccountListPush(UIDList, userInfo.Data[0].Name, constant.ContentType2PushContent[constant.Video], jsonCustomContent)
case constant.File:
IOSAccountListPush(UIDList, userInfo.Data[0].Name, constant.ContentType2PushContent[constant.File], jsonCustomContent)
default:
}
}
} else {
isShouldOfflinePush = true
}
}*/
}
}
}
@ -158,7 +119,7 @@ func SendMsgByWS(m *pbChat.WSToMsgSvrChatMsg) {
sendMsgToKafka(m, m.SendID, "msgKey--sendID")
sendMsgToKafka(m, m.RecvID, "msgKey--recvID")
case constant.GroupChatType:
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImGroupName)
etcdConn := getcdv3.GetGroupConn()
client := pbGroup.NewGroupClient(etcdConn)
req := &pbGroup.GetGroupAllMemberReq{
GroupID: m.RecvID,

@ -10,6 +10,9 @@ import (
func (rpc *rpcAuth) UserRegister(_ context.Context, pb *pbAuth.UserRegisterReq) (*pbAuth.UserRegisterResp, error) {
log.Info("", "", "rpc user_register start, [data: %s]", pb.String())
//if len(pb.UID) == 0 {
// pb.UID = utils.GenID()
//}
if err := im_mysql_model.UserRegister(pb); err != nil {
log.Error("", "", "rpc user_register error, [data: %s] [err: %s]", pb.String(), err.Error())
return &pbAuth.UserRegisterResp{Success: false}, err

@ -18,7 +18,7 @@ func (rpc *rpcAuth) UserToken(_ context.Context, pb *pbAuth.UserTokenReq) (*pbAu
}
log.Info("", "", "rpc user_token call..., im_mysql_model.AppServerFindFromUserByUserID")
tokens, expTime, err := utils.CreateToken(pb.UID, "", pb.Platform)
tokens, expTime, err := utils.CreateToken(pb.UID, pb.Platform)
if err != nil {
log.Error("", "", "rpc user_token call..., utils.CreateToken fail [uid: %s] [err: %s]", pb.UID, err.Error())
return &pbAuth.UserTokenResp{ErrCode: 500, ErrMsg: err.Error()}, err

@ -13,35 +13,40 @@ import (
pbMsg "Open_IM/pkg/proto/chat"
)
func (rpc *rpcChat) GetNewSeq(_ context.Context, in *pbMsg.GetNewSeqReq) (*pbMsg.GetNewSeqResp, error) {
log.InfoByKv("rpc getNewSeq is arriving", in.OperationID, in.String())
func (rpc *rpcChat) GetMaxAndMinSeq(_ context.Context, in *pbMsg.GetMaxAndMinSeqReq) (*pbMsg.GetMaxAndMinSeqResp, error) {
log.InfoByKv("rpc getMaxAndMinSeq is arriving", in.OperationID, in.String())
//seq, err := model.GetBiggestSeqFromReceive(in.UserID)
seq, err := commonDB.DB.GetUserSeq(in.UserID)
resp := new(pbMsg.GetNewSeqResp)
if err == nil {
resp.Seq = seq
resp.ErrCode = 0
resp.ErrMsg = ""
return resp, err
maxSeq, err1 := commonDB.DB.GetUserMaxSeq(in.UserID)
minSeq, err2 := commonDB.DB.GetUserMinSeq(in.UserID)
resp := new(pbMsg.GetMaxAndMinSeqResp)
if err1 == nil {
resp.MaxSeq = maxSeq
} else if err1 == redis.ErrNil {
resp.MaxSeq = 0
} else {
if err == redis.ErrNil {
resp.Seq = 0
} else {
log.ErrorByKv("getSeq from redis error", in.OperationID, "args", in.String(), "err", err.Error())
resp.Seq = -1
}
resp.ErrCode = 0
resp.ErrMsg = ""
return resp, nil
log.NewError(in.OperationID, "getMaxSeq from redis error", in.String(), err1.Error())
resp.MaxSeq = -1
resp.ErrCode = 200
resp.ErrMsg = "redis get err"
}
if err2 == nil {
resp.MinSeq = minSeq
} else if err2 == redis.ErrNil {
resp.MinSeq = 0
} else {
log.NewError(in.OperationID, "getMaxSeq from redis error", in.String(), err2.Error())
resp.MinSeq = -1
resp.ErrCode = 201
resp.ErrMsg = "redis get err"
}
return resp, nil
}
func (rpc *rpcChat) PullMessage(_ context.Context, in *pbMsg.PullMessageReq) (*pbMsg.PullMessageResp, error) {
log.InfoByKv("rpc pullMessage is arriving", in.OperationID, "args", in.String())
resp := new(pbMsg.PullMessageResp)
var respSingleMsgFormat []*pbMsg.GatherFormat
var respGroupMsgFormat []*pbMsg.GatherFormat
SingleMsgFormat, GroupMsgFormat, MaxSeq, MinSeq, err := commonDB.DB.GetUserChat(in.UserID, in.SeqBegin, in.SeqEnd)
SingleMsgFormat, GroupMsgFormat, MaxSeq, MinSeq, err := commonDB.DB.GetMsgBySeqRange(in.UserID, in.SeqBegin, in.SeqEnd)
if err != nil {
log.ErrorByKv("pullMsg data error", in.OperationID, in.String())
resp.ErrCode = 1
@ -59,6 +64,29 @@ func (rpc *rpcChat) PullMessage(_ context.Context, in *pbMsg.PullMessageReq) (*p
GroupUserMsg: respGroupMsgFormat,
}, nil
}
func (rpc *rpcChat) PullMessageBySeqList(_ context.Context, in *pbMsg.PullMessageBySeqListReq) (*pbMsg.PullMessageResp, error) {
log.NewInfo(in.OperationID, "rpc PullMessageBySeqList is arriving", in.String())
resp := new(pbMsg.PullMessageResp)
var respSingleMsgFormat []*pbMsg.GatherFormat
var respGroupMsgFormat []*pbMsg.GatherFormat
SingleMsgFormat, GroupMsgFormat, MaxSeq, MinSeq, err := commonDB.DB.GetMsgBySeqList(in.UserID, in.SeqList)
if err != nil {
log.ErrorByKv("PullMessageBySeqList data error", in.OperationID, in.String())
resp.ErrCode = 1
resp.ErrMsg = err.Error()
return resp, nil
}
respSingleMsgFormat = singleMsgHandleByUser(SingleMsgFormat, in.UserID)
respGroupMsgFormat = groupMsgHandleByUser(GroupMsgFormat)
return &pbMsg.PullMessageResp{
ErrCode: 0,
ErrMsg: "",
MaxSeq: MaxSeq,
MinSeq: MinSeq,
SingleUserMsg: respSingleMsgFormat,
GroupUserMsg: respGroupMsgFormat,
}, nil
}
func singleMsgHandleByUser(allMsg []*pbMsg.MsgFormat, ownerId string) []*pbMsg.GatherFormat {
var userid string
var respMsgFormat []*pbMsg.GatherFormat

@ -16,7 +16,6 @@ import (
"math/rand"
"net/http"
"strconv"
"strings"
"time"
)
@ -42,10 +41,9 @@ type MsgCallBackResp struct {
func (rpc *rpcChat) UserSendMsg(_ context.Context, pb *pbChat.UserSendMsgReq) (*pbChat.UserSendMsgResp, error) {
replay := pbChat.UserSendMsgResp{}
log.InfoByKv("sendMsg", pb.OperationID, "args", pb.String())
if !utils.VerifyToken(pb.Token, pb.SendID) {
return returnMsg(&replay, pb, http.StatusUnauthorized, "token validate err,not authorized", "", 0)
}
log.NewDebug(pb.OperationID, "rpc sendMsg come here", pb.String())
//if !utils.VerifyToken(pb.Token, pb.SendID) {
// return returnMsg(&replay, pb, http.StatusUnauthorized, "token validate err,not authorized", "", 0)
serverMsgID := GetMsgID(pb.SendID)
pbData := pbChat.WSToMsgSvrChatMsg{}
pbData.MsgFrom = pb.MsgFrom
@ -64,7 +62,11 @@ func (rpc *rpcChat) UserSendMsg(_ context.Context, pb *pbChat.UserSendMsgReq) (*
pbData.MsgID = serverMsgID
pbData.OperationID = pb.OperationID
pbData.Token = pb.Token
pbData.SendTime = utils.GetCurrentTimestampByNano()
if pb.SendTime == 0 {
pbData.SendTime = utils.GetCurrentTimestampByNano()
} else {
pbData.SendTime = pb.SendTime
}
m := MsgCallBackResp{}
if config.Config.MessageCallBack.CallbackSwitch {
bMsg, err := http2.Post(config.Config.MessageCallBack.CallbackUrl, MsgCallBackReq{
@ -88,85 +90,77 @@ func (rpc *rpcChat) UserSendMsg(_ context.Context, pb *pbChat.UserSendMsgReq) (*
return returnMsg(&replay, pb, m.ResponseErrCode, m.ErrMsg, "", 0)
} else {
pbData.Content = m.ResponseResult.ModifiedMsg
err1 := rpc.sendMsgToKafka(&pbData, pbData.RecvID)
err2 := rpc.sendMsgToKafka(&pbData, pbData.SendID)
if err1 != nil || err2 != nil {
return returnMsg(&replay, pb, 201, "kafka send msg err", "", 0)
}
return returnMsg(&replay, pb, 0, "", serverMsgID, pbData.SendTime)
}
}
} else {
switch pbData.SessionType {
case constant.SingleChatType:
err1 := rpc.sendMsgToKafka(&pbData, pbData.RecvID)
err2 := rpc.sendMsgToKafka(&pbData, pbData.SendID)
if err1 != nil || err2 != nil {
return returnMsg(&replay, pb, 201, "kafka send msg err", "", 0)
}
return returnMsg(&replay, pb, 0, "", serverMsgID, pbData.SendTime)
case constant.GroupChatType:
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImGroupName)
client := pbGroup.NewGroupClient(etcdConn)
req := &pbGroup.GetGroupAllMemberReq{
GroupID: pbData.RecvID,
Token: pbData.Token,
OperationID: pbData.OperationID,
}
reply, err := client.GetGroupAllMember(context.Background(), req)
}
switch pbData.SessionType {
case constant.SingleChatType:
err1 := rpc.sendMsgToKafka(&pbData, pbData.RecvID)
err2 := rpc.sendMsgToKafka(&pbData, pbData.SendID)
if err1 != nil || err2 != nil {
return returnMsg(&replay, pb, 201, "kafka send msg err", "", 0)
}
return returnMsg(&replay, pb, 0, "", serverMsgID, pbData.SendTime)
case constant.GroupChatType:
etcdConn := getcdv3.GetGroupConn()
client := pbGroup.NewGroupClient(etcdConn)
req := &pbGroup.GetGroupAllMemberReq{
GroupID: pbData.RecvID,
Token: pbData.Token,
OperationID: pbData.OperationID,
}
reply, err := client.GetGroupAllMember(context.Background(), req)
if err != nil {
log.Error(pbData.Token, pbData.OperationID, "rpc send_msg getGroupInfo failed, err = %s", err.Error())
return returnMsg(&replay, pb, 201, err.Error(), "", 0)
}
if reply.ErrorCode != 0 {
log.Error(pbData.Token, pbData.OperationID, "rpc send_msg getGroupInfo failed, err = %s", reply.ErrorMsg)
return returnMsg(&replay, pb, reply.ErrorCode, reply.ErrorMsg, "", 0)
}
var addUidList []string
switch pbData.ContentType {
case constant.KickGroupMemberTip:
var notification content_struct.NotificationContent
var kickContent group.KickGroupMemberReq
err := utils.JsonStringToStruct(pbData.Content, &notification)
if err != nil {
log.Error(pbData.Token, pbData.OperationID, "rpc send_msg getGroupInfo failed, err = %s", err.Error())
return returnMsg(&replay, pb, 201, err.Error(), "", 0)
}
if reply.ErrorCode != 0 {
log.Error(pbData.Token, pbData.OperationID, "rpc send_msg getGroupInfo failed, err = %s", reply.ErrorMsg)
return returnMsg(&replay, pb, reply.ErrorCode, reply.ErrorMsg, "", 0)
}
var addUidList []string
switch pbData.ContentType {
case constant.KickGroupMemberTip:
var notification content_struct.NotificationContent
var kickContent group.KickGroupMemberReq
err := utils.JsonStringToStruct(pbData.Content, &notification)
log.ErrorByKv("json unmarshall err", pbData.OperationID, "err", err.Error())
return returnMsg(&replay, pb, 200, err.Error(), "", 0)
} else {
err := utils.JsonStringToStruct(notification.Detail, &kickContent)
if err != nil {
log.ErrorByKv("json unmarshall err", pbData.OperationID, "err", err.Error())
return returnMsg(&replay, pb, 200, err.Error(), "", 0)
} else {
err := utils.JsonStringToStruct(notification.Detail, &kickContent)
if err != nil {
log.ErrorByKv("json unmarshall err", pbData.OperationID, "err", err.Error())
return returnMsg(&replay, pb, 200, err.Error(), "", 0)
}
for _, v := range kickContent.UidListInfo {
addUidList = append(addUidList, v.UserId)
}
}
case constant.QuitGroupTip:
addUidList = append(addUidList, pbData.SendID)
default:
}
groupID := pbData.RecvID
for i, v := range reply.MemberList {
pbData.RecvID = v.UserId + " " + groupID
err := rpc.sendMsgToKafka(&pbData, utils.IntToString(i))
if err != nil {
return returnMsg(&replay, pb, 201, "kafka send msg err", "", 0)
}
}
for i, v := range addUidList {
pbData.RecvID = v + " " + groupID
err := rpc.sendMsgToKafka(&pbData, utils.IntToString(i+1))
if err != nil {
return returnMsg(&replay, pb, 201, "kafka send msg err", "", 0)
for _, v := range kickContent.UidListInfo {
addUidList = append(addUidList, v.UserId)
}
}
return returnMsg(&replay, pb, 0, "", serverMsgID, pbData.SendTime)
case constant.QuitGroupTip:
addUidList = append(addUidList, pbData.SendID)
default:
}
groupID := pbData.RecvID
for i, v := range reply.MemberList {
pbData.RecvID = v.UserId + " " + groupID
err := rpc.sendMsgToKafka(&pbData, utils.IntToString(i))
if err != nil {
return returnMsg(&replay, pb, 201, "kafka send msg err", "", 0)
}
}
for i, v := range addUidList {
pbData.RecvID = v + " " + groupID
err := rpc.sendMsgToKafka(&pbData, utils.IntToString(i+1))
if err != nil {
return returnMsg(&replay, pb, 201, "kafka send msg err", "", 0)
}
}
return returnMsg(&replay, pb, 0, "", serverMsgID, pbData.SendTime)
default:
return returnMsg(&replay, pb, 203, "unkonwn sessionType", "", 0)
}
return returnMsg(&replay, pb, 203, "unkonwn sessionType", "", 0)
}
func (rpc *rpcChat) sendMsgToKafka(m *pbChat.WSToMsgSvrChatMsg, key string) error {

@ -55,25 +55,33 @@ func (s *friendServer) AddFriend(ctx context.Context, req *pbFriend.AddFriendReq
func (s *friendServer) ImportFriend(ctx context.Context, req *pbFriend.ImportFriendReq) (*pbFriend.ImportFriendResp, error) {
log.Info(req.Token, req.OperationID, "ImportFriend come here,args=%s", req.String())
var resp pbFriend.ImportFriendResp
var c pbFriend.CommonResp
//Parse token, to find current user information
claims, err := utils.ParseToken(req.Token)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,parse token failed", err.Error())
return &pbFriend.ImportFriendResp{CommonResp: &pbFriend.CommonResp{ErrorCode: config.ErrAddFriend.ErrCode, ErrorMsg: config.ErrParseToken.ErrMsg}, FailedUidList: req.UidList}, nil
c.ErrorCode = config.ErrAddFriend.ErrCode
c.ErrorMsg = config.ErrParseToken.ErrMsg
return &pbFriend.ImportFriendResp{CommonResp: &c, FailedUidList: req.UidList}, nil
}
if !utils.IsContain(claims.UID, config.Config.Manager.AppManagerUid) {
log.Error(req.Token, req.OperationID, "not magager uid", claims.UID)
return &pbFriend.ImportFriendResp{CommonResp: &pbFriend.CommonResp{ErrorCode: config.ErrAddFriend.ErrCode, ErrorMsg: "not authorized"}, FailedUidList: req.UidList}, nil
log.Error(req.Token, req.OperationID, "not manager uid", claims.UID)
c.ErrorCode = config.ErrAddFriend.ErrCode
c.ErrorMsg = "not authorized"
return &pbFriend.ImportFriendResp{CommonResp: &c, FailedUidList: req.UidList}, nil
}
if _, err = im_mysql_model.FindUserByUID(req.OwnerUid); err != nil {
log.Error(req.Token, req.OperationID, "this user not exists,cant not add friend", req.OwnerUid)
return &pbFriend.ImportFriendResp{CommonResp: &pbFriend.CommonResp{ErrorCode: config.ErrAddFriend.ErrCode, ErrorMsg: "this user not exists,cant not add friend"}, FailedUidList: req.UidList}, nil
c.ErrorCode = config.ErrAddFriend.ErrCode
c.ErrorMsg = "this user not exists,cant not add friend"
return &pbFriend.ImportFriendResp{CommonResp: &c, FailedUidList: req.UidList}, nil
}
for _, v := range req.UidList {
if _, err = im_mysql_model.FindUserByUID(v); err != nil {
resp.CommonResp.ErrorMsg = "some uid establish failed"
resp.CommonResp.ErrorCode = 408
if _, fErr := im_mysql_model.FindUserByUID(v); fErr != nil {
c.ErrorMsg = "some uid establish failed"
c.ErrorCode = 408
resp.CommonResp = &c
resp.FailedUidList = append(resp.FailedUidList, v)
} else {
if _, err = im_mysql_model.FindFriendRelationshipFromFriend(req.OwnerUid, v); err != nil {
@ -81,18 +89,18 @@ func (s *friendServer) ImportFriend(ctx context.Context, req *pbFriend.ImportFri
err1 := im_mysql_model.InsertToFriend(req.OwnerUid, v, 1)
if err1 != nil {
resp.FailedUidList = append(resp.FailedUidList, v)
log.Error(req.Token, req.OperationID, "err=%s,create friendship failed", err.Error())
log.NewError(req.OperationID, "err1,create friendship failed", req.OwnerUid, v, err1.Error())
}
err2 := im_mysql_model.InsertToFriend(v, req.OwnerUid, 1)
if err2 != nil {
log.Error(req.Token, req.OperationID, "err=%s,create friendship failed", err.Error())
log.NewError(req.OperationID, "err2,create friendship failed", v, req.OwnerUid, err2.Error())
}
if err1 == nil && err2 == nil {
var name, faceUrl string
n := content_struct.NotificationContent{1, constant.FriendAcceptTip, ""}
n := content_struct.NotificationContent{IsDisplay: 1, DefaultTips: constant.FriendAcceptTip}
r, err := im_mysql_model.FindUserByUID(v)
if err != nil {
log.ErrorByKv("get info failed", req.OperationID, "err", err.Error(), "req", req.String())
log.NewError(req.OperationID, "get info failed", err.Error(), v)
}
if r != nil {
name, faceUrl = r.Name, r.Icon

@ -70,6 +70,12 @@ func (s *groupServer) InviteUserToGroup(ctx context.Context, req *pbGroup.Invite
return &pbGroup.InviteUserToGroupResp{ErrorCode: config.ErrAccess.ErrCode, ErrorMsg: config.ErrAccess.ErrMsg}, nil
}
groupInfoFromMysql, err := imdb.FindGroupInfoByGroupId(req.GroupID)
if err != nil || groupInfoFromMysql == nil {
log.NewError(req.OperationID, "get group info error", req.GroupID, req.UidList)
return &pbGroup.InviteUserToGroupResp{ErrorCode: config.ErrAccess.ErrCode, ErrorMsg: config.ErrAccess.ErrMsg}, nil
}
//
//from User: invite: applicant
//to user: invite: invited
@ -157,13 +163,13 @@ func (c *inviteUserToGroupReq) ContentToString() string {
}
func (s *groupServer) GetGroupAllMember(ctx context.Context, req *pbGroup.GetGroupAllMemberReq) (*pbGroup.GetGroupAllMemberResp, error) {
claims, err := utils.ParseToken(req.Token)
if err != nil {
log.Error(req.Token, req.OperationID, "err=%s,parse token failed", err.Error())
if req.Token != config.Config.Secret {
return &pbGroup.GetGroupAllMemberResp{ErrorCode: config.ErrParseToken.ErrCode, ErrorMsg: config.ErrParseToken.ErrMsg}, nil
}
}
//claims, err := utils.ParseToken(req.Token)
//if err != nil {
// log.Error(req.Token, req.OperationID, "err=%s,parse token failed", err.Error())
// if req.Token != config.Config.Secret {
// return &pbGroup.GetGroupAllMemberResp{ErrorCode: config.ErrParseToken.ErrCode, ErrorMsg: config.ErrParseToken.ErrMsg}, nil
// }
//}
var resp pbGroup.GetGroupAllMemberResp
resp.ErrorCode = 0
@ -171,7 +177,7 @@ func (s *groupServer) GetGroupAllMember(ctx context.Context, req *pbGroup.GetGro
if err != nil {
resp.ErrorCode = config.ErrDb.ErrCode
resp.ErrorMsg = err.Error()
log.Error(claims.UID, req.OperationID, "FindGroupMemberListByGroupId failed, ", err.Error(), "params: ", req.GroupID)
log.NewError(req.OperationID, "FindGroupMemberListByGroupId failed,", err.Error(), req.GroupID)
return &resp, nil
}

@ -1,15 +1,13 @@
package internal_service
import (
pbUser "Open_IM/pkg/proto/user"
"Open_IM/pkg/common/config"
"Open_IM/pkg/grpc-etcdv3/getcdv3"
pbUser "Open_IM/pkg/proto/user"
"context"
"strings"
)
func GetUserInfoClient(req *pbUser.GetUserInfoReq) (*pbUser.GetUserInfoResp, error) {
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImUserName)
etcdConn := getcdv3.GetUserConn()
client := pbUser.NewUserClient(etcdConn)
RpcResp, err := client.GetUserInfo(context.Background(), req)
return RpcResp, err

@ -12,7 +12,6 @@ import (
pbUser "Open_IM/pkg/proto/user"
"Open_IM/pkg/utils"
"context"
"strings"
)
func (s *userServer) UpdateUserInfo(ctx context.Context, req *pbUser.UpdateUserInfoReq) (*pbUser.CommonResp, error) {
@ -36,7 +35,7 @@ func (s *userServer) UpdateUserInfo(ctx context.Context, req *pbUser.UpdateUserI
log.Error(req.Token, req.OperationID, "update user some attribute failed,err=%s", err.Error())
return &pbUser.CommonResp{ErrorCode: config.ErrModifyUserInfo.ErrCode, ErrorMsg: config.ErrModifyUserInfo.ErrMsg}, nil
}
etcdConn := getcdv3.GetConn(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImFriendName)
etcdConn := getcdv3.GetFriendConn()
client := pbFriend.NewFriendClient(etcdConn)
newReq := &pbFriend.GetFriendListReq{
OperationID: req.OperationID,

@ -0,0 +1,68 @@
package utils
import (
"Open_IM/pkg/utils"
"net/http"
"net/http/httptest"
"testing"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
)
func init() {
gin.SetMode(gin.TestMode)
}
func performRequest(r http.Handler, method, origin string) *httptest.ResponseRecorder {
return performRequestWithHeaders(r, method, origin, http.Header{})
}
func performRequestWithHeaders(r http.Handler, method, origin string, header http.Header) *httptest.ResponseRecorder {
req, _ := http.NewRequest(method, "/", nil)
// From go/net/http/request.go:
// For incoming requests, the Host header is promoted to the
// Request.Host field and removed from the Header map.
req.Host = header.Get("Host")
header.Del("Host")
if len(origin) > 0 {
header.Set("Origin", origin)
}
req.Header = header
w := httptest.NewRecorder()
r.ServeHTTP(w, req)
return w
}
func newTestRouter() *gin.Engine {
router := gin.New()
router.Use(utils.CorsHandler())
router.GET("/", func(c *gin.Context) {
c.String(http.StatusOK, "get")
})
router.POST("/", func(c *gin.Context) {
c.String(http.StatusOK, "post")
})
router.PATCH("/", func(c *gin.Context) {
c.String(http.StatusOK, "patch")
})
return router
}
func Test_CorsHandler(t *testing.T) {
router := newTestRouter()
// no CORS request, origin == ""
w := performRequest(router, "GET", "")
assert.Equal(t, "get", w.Body.String())
assert.Equal(t, w.Header().Get("Access-Control-Allow-Origin"), "*")
assert.Equal(t, w.Header().Get("Access-Control-Allow-Methods"), "*")
assert.Equal(t, w.Header().Get("Access-Control-Allow-Headers"), "*")
assert.Equal(t, w.Header().Get("Access-Control-Expose-Headers"), "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers,Cache-Control,Content-Language,Content-Type,Expires,Last-Modified,Pragma,FooBar")
assert.Equal(t, w.Header().Get("Access-Control-Max-Age"), "172800")
assert.Equal(t, w.Header().Get("Access-Control-Allow-Credentials"), "false")
assert.Equal(t, w.Header().Get("content-type"), "application/json")
w = performRequest(router, "OPTIONS", "")
assert.Equal(t, w.Body.String(), "\"Options Request!\"")
}

@ -0,0 +1,13 @@
package utils
import (
"Open_IM/pkg/utils"
"net"
"testing"
)
func TestServerIP(t *testing.T) {
if net.ParseIP(utils.ServerIP) == nil {
t.Fail()
}
}

@ -0,0 +1,28 @@
package utils
import (
"github.com/bwmarrin/snowflake"
)
func init() {
var err error
idGenerator, err = snowflake.NewNode(getNodeNum())
if err != nil {
panic(err)
}
}
func getNodeNum() int64 {
return 1
}
var idGenerator *snowflake.Node
func GenID() string {
return idGenerator.Generate().String()
}
func GenIDs(count int) []string {
//impl
return []string{}
}

@ -0,0 +1,15 @@
package utils
import "testing"
func TestGenID(t *testing.T) {
m := map[string]struct{}{}
for i := 0; i < 2000; i++ {
got := GenID()
if _, ok := m[got]; !ok {
m[got] = struct{}{}
} else {
t.Error("id generate error", got)
}
}
}

@ -0,0 +1,28 @@
package utils
import (
"Open_IM/pkg/utils"
"path/filepath"
"runtime"
"testing"
"github.com/stretchr/testify/assert"
)
var (
_, b, _, _ = runtime.Caller(0)
// Root folder of this project
Root = filepath.Join(filepath.Dir(b), "../..")
)
func Test_GenSmallImage(t *testing.T) {
println(Root)
err := utils.GenSmallImage(Root+"/docs/open-im-logo.png", Root+"/out-test/open-im-logo-test.png")
assert.Nil(t, err)
err = utils.GenSmallImage(Root+"/docs/open-im-logo.png", "out-test/open-im-logo-test.png")
assert.Nil(t, err)
err = utils.GenSmallImage(Root+"/docs/Architecture.jpg", "out-test/Architecture-test.jpg")
assert.Nil(t, err)
}

@ -0,0 +1,82 @@
package utils
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/utils"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
func Test_BuildClaims(t *testing.T) {
uid := "1"
platform := "PC"
ttl := int64(-1)
claim := utils.BuildClaims(uid, platform, ttl)
now := time.Now().Unix()
assert.Equal(t, claim.UID, uid, "uid should equal")
assert.Equal(t, claim.Platform, platform, "platform should equal")
assert.Equal(t, claim.RegisteredClaims.ExpiresAt, int64(-1), "StandardClaims.ExpiresAt should be equal")
// time difference within 1s
assert.Equal(t, claim.RegisteredClaims.IssuedAt, now, "StandardClaims.IssuedAt should be equal")
assert.Equal(t, claim.RegisteredClaims.NotBefore, now, "StandardClaims.NotBefore should be equal")
ttl = int64(60)
now = time.Now().Unix()
claim = utils.BuildClaims(uid, platform, ttl)
// time difference within 1s
assert.Equal(t, claim.RegisteredClaims.ExpiresAt, int64(60)+now, "StandardClaims.ExpiresAt should be equal")
assert.Equal(t, claim.RegisteredClaims.IssuedAt, now, "StandardClaims.IssuedAt should be equal")
assert.Equal(t, claim.RegisteredClaims.NotBefore, now, "StandardClaims.NotBefore should be equal")
}
func Test_CreateToken(t *testing.T) {
uid := "1"
platform := int32(1)
now := time.Now().Unix()
tokenString, expiresAt, err := utils.CreateToken(uid, platform)
assert.NotEmpty(t, tokenString)
assert.Equal(t, expiresAt, 604800+now)
assert.Nil(t, err)
}
func Test_VerifyToken(t *testing.T) {
uid := "1"
platform := int32(1)
tokenString, _, _ := utils.CreateToken(uid, platform)
result := utils.VerifyToken(tokenString, uid)
assert.True(t, result)
result = utils.VerifyToken(tokenString, "2")
assert.False(t, result)
}
func Test_ParseRedisInterfaceToken(t *testing.T) {
uid := "1"
platform := int32(1)
tokenString, _, _ := utils.CreateToken(uid, platform)
claims, err := utils.ParseRedisInterfaceToken([]uint8(tokenString))
assert.Nil(t, err)
assert.Equal(t, claims.UID, uid)
// timeout
config.Config.TokenPolicy.AccessExpire = -80
tokenString, _, _ = utils.CreateToken(uid, platform)
claims, err = utils.ParseRedisInterfaceToken([]uint8(tokenString))
assert.Equal(t, err, utils.TokenExpired)
assert.Nil(t, claims)
}
func Test_ParseToken(t *testing.T) {
uid := "1"
platform := int32(1)
tokenString, _, _ := utils.CreateToken(uid, platform)
claims, err := utils.ParseToken(tokenString)
if err == nil {
assert.Equal(t, claims.UID, uid)
}
}

@ -0,0 +1,16 @@
package utils
import (
"Open_IM/pkg/utils"
"testing"
"github.com/stretchr/testify/assert"
)
func Test_Md5(t *testing.T) {
result := utils.Md5("go")
assert.Equal(t, result, "34d1f91fb2e514b8576fab1a75a89a6b")
result2 := utils.Md5("go")
assert.Equal(t, result, result2)
}

@ -0,0 +1,46 @@
package utils
import (
"Open_IM/pkg/utils"
"testing"
"github.com/stretchr/testify/assert"
)
func Test_PlatformIDToName(t *testing.T) {
assert.Equal(t, utils.PlatformIDToName(1), "IOS")
assert.Equal(t, utils.PlatformIDToName(2), "Android")
assert.Equal(t, utils.PlatformIDToName(3), "Windows")
assert.Equal(t, utils.PlatformIDToName(4), "OSX")
assert.Equal(t, utils.PlatformIDToName(5), "Web")
assert.Equal(t, utils.PlatformIDToName(6), "MiniWeb")
assert.Equal(t, utils.PlatformIDToName(7), "Linux")
assert.Equal(t, utils.PlatformIDToName(0), "")
}
func Test_PlatformNameToID(t *testing.T) {
assert.Equal(t, utils.PlatformNameToID("IOS"), int32(1))
assert.Equal(t, utils.PlatformNameToID("Android"), int32(2))
assert.Equal(t, utils.PlatformNameToID("Windows"), int32(3))
assert.Equal(t, utils.PlatformNameToID("OSX"), int32(4))
assert.Equal(t, utils.PlatformNameToID("Web"), int32(5))
assert.Equal(t, utils.PlatformNameToID("MiniWeb"), int32(6))
assert.Equal(t, utils.PlatformNameToID("Linux"), int32(7))
assert.Equal(t, utils.PlatformNameToID("UnknownDevice"), int32(0))
assert.Equal(t, utils.PlatformNameToID(""), int32(0))
}
func Test_PlatformNameToClass(t *testing.T) {
assert.Equal(t, utils.PlatformNameToClass("IOS"), "Mobile")
assert.Equal(t, utils.PlatformNameToClass("Android"), "Mobile")
assert.Equal(t, utils.PlatformNameToClass("OSX"), "PC")
assert.Equal(t, utils.PlatformNameToClass("Windows"), "PC")
assert.Equal(t, utils.PlatformNameToClass("Web"), "PC")
assert.Equal(t, utils.PlatformNameToClass("MiniWeb"), "Mobile")
assert.Equal(t, utils.PlatformNameToClass("Linux"), "PC")
assert.Equal(t, utils.PlatformNameToClass("UnknownDevice"), "")
assert.Equal(t, utils.PlatformNameToClass(""), "")
}

@ -1,16 +1,26 @@
package config
import (
"gopkg.in/yaml.v3"
"io/ioutil"
"gopkg.in/yaml.v3"
"path/filepath"
"runtime"
)
var Config config
type config struct {
ServerIP string `yaml:"serverip"`
var (
_, b, _, _ = runtime.Caller(0)
// Root folder of this project
Root = filepath.Join(filepath.Dir(b), "../../..")
)
Api struct {
type config struct {
ServerIP string `yaml:"serverip"`
ServerVersion string `yaml:"serverversion"`
Api struct {
GinPort []int `yaml:"openImApiPort"`
}
Sdk struct {
@ -110,6 +120,11 @@ type config struct {
SecretKey string `yaml:"secretKey"`
}
}
Jpns struct {
AppKey string `yaml:"appKey"`
MasterSecret string `yaml:"masterSecret"`
PushUrl string `yaml:"pushUrl"`
}
}
Manager struct {
AppManagerUid []string `yaml:"appManagerUid"`
@ -147,14 +162,14 @@ type config struct {
}
func init() {
bytes, err := ioutil.ReadFile("config/config.yaml")
// if we cd Open-IM-Server/src/utils and run go test
// it will panic cannot find config/config.yaml
bytes, err := ioutil.ReadFile(Root + "/config/config.yaml")
if err != nil {
panic(err)
return
}
if err = yaml.Unmarshal(bytes, &Config); err != nil {
panic(err)
return
}
}

@ -17,22 +17,27 @@ const (
RefuseFriendFlag = -1
//Websocket Protocol
WSGetNewestSeq = 1001
WSPullMsg = 1002
WSSendMsg = 1003
WSPushMsg = 2001
WSGetNewestSeq = 1001
WSPullMsg = 1002
WSSendMsg = 1003
WSPullMsgBySeqList = 1004
WSPushMsg = 2001
WSDataError = 3001
///ContentType
//UserRelated
Text = 101
Picture = 102
Voice = 103
Video = 104
File = 105
AtText = 106
Custom = 110
Text = 101
Picture = 102
Voice = 103
Video = 104
File = 105
AtText = 106
Custom = 110
HasReadReceipt = 112
Typing = 113
Common = 200
GroupMsg = 201
SyncSenderMsg = 108
//SysRelated
AcceptFriendApplicationTip = 201
AddFriendTip = 202
@ -64,10 +69,14 @@ const (
)
var ContentType2PushContent = map[int64]string{
Picture: "[picture]",
Voice: "[voice]",
Video: "[video]",
File: "[file]",
Picture: "[图片]",
Voice: "[语音]",
Video: "[视频]",
File: "[文件]",
Text: "你收到了一条文本消息",
AtText: "[有人@你]",
GroupMsg: "你收到一条群聊消息",
Common: "你收到一条新消息",
}
const FriendAcceptTip = "You have successfully become friends, so start chatting"

@ -39,6 +39,11 @@ func init() {
}
DB.mgoSession = mgoSession
DB.mgoSession.SetMode(mgo.Monotonic, true)
c := DB.mgoSession.DB(config.Config.Mongo.DBDatabase).C(cChat)
err = c.EnsureIndexKey("uid")
if err != nil {
panic(err)
}
// redis pool init
DB.redisPool = &redis.Pool{

@ -1,17 +1,21 @@
package db
import (
pbMsg "Open_IM/pkg/proto/chat"
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/constant"
"Open_IM/pkg/common/log"
pbMsg "Open_IM/pkg/proto/chat"
"errors"
"github.com/garyburd/redigo/redis"
"github.com/golang/protobuf/proto"
"gopkg.in/mgo.v2/bson"
"strconv"
"time"
)
const cChat = "chat"
const cGroup = "group"
const singleGocMsgNum = 5000
type MsgInfo struct {
SendTime int64
@ -28,8 +32,8 @@ type GroupMember struct {
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
func (d *DataBases) GetMsgBySeqRange(uid string, seqBegin, seqEnd int64) (SingleMsg []*pbMsg.MsgFormat, GroupMsg []*pbMsg.MsgFormat, MaxSeq int64, MinSeq int64, err error) {
var count int64
session := d.mgoSession.Clone()
if session == nil {
return nil, nil, MaxSeq, MinSeq, errors.New("session == nil")
@ -76,48 +80,152 @@ func (d *DataBases) GetUserChat(uid string, seqBegin, seqEnd int64) (SingleMsg [
GroupMsg = append(GroupMsg, temp)
}
count++
if count == (seqEnd - seqBegin + 1) {
break
}
}
}
return SingleMsg, GroupMsg, MaxSeq, MinSeq, nil
}
func (d *DataBases) GetMinSeqFromMongo(uid string) (MinSeq int64, err error) {
var i int64
var seqUid string
session := d.mgoSession.Clone()
if session == nil {
return MinSeq, errors.New("session == nil")
}
defer session.Close()
c := session.DB(config.Config.Mongo.DBDatabase).C(cChat)
MaxSeq, err := d.GetUserMaxSeq(uid)
if err != nil && err != redis.ErrNil {
return MinSeq, err
}
NB := MaxSeq / singleGocMsgNum
for i = 0; i <= NB; i++ {
seqUid = indexGen(uid, i)
n, err := c.Find(bson.M{"uid": seqUid}).Count()
if err == nil && n != 0 {
if i == 0 {
MinSeq = 1
} else {
MinSeq = i * singleGocMsgNum
}
break
}
}
return MinSeq, nil
}
func (d *DataBases) GetMsgBySeqList(uid string, seqList []int64) (SingleMsg []*pbMsg.MsgFormat, GroupMsg []*pbMsg.MsgFormat, MaxSeq int64, MinSeq int64, err error) {
allCount := 0
singleCount := 0
session := d.mgoSession.Clone()
if session == nil {
return nil, nil, MaxSeq, MinSeq, errors.New("session == nil")
}
defer session.Close()
func (d *DataBases) SaveUserChat(uid string, sendTime int64, m proto.Message) error {
c := session.DB(config.Config.Mongo.DBDatabase).C(cChat)
m := func(uid string, seqList []int64) map[string][]int64 {
t := make(map[string][]int64)
for i := 0; i < len(seqList); i++ {
seqUid := getSeqUid(uid, seqList[i])
if value, ok := t[seqUid]; !ok {
var temp []int64
t[seqUid] = append(temp, seqList[i])
} else {
t[seqUid] = append(value, seqList[i])
}
}
return t
}(uid, seqList)
sChat := UserChat{}
pChat := pbMsg.MsgSvrToPushSvrChatMsg{}
for seqUid, value := range m {
if err = c.Find(bson.M{"uid": seqUid}).One(&sChat); err != nil {
log.NewError("", "not find seqUid", seqUid, value, uid, seqList)
continue
}
singleCount = 0
for i := 0; i < len(sChat.Msg); i++ {
temp := new(pbMsg.MsgFormat)
if err = proto.Unmarshal(sChat.Msg[i].Msg, &pChat); err != nil {
log.NewError("", "not find seqUid", seqUid, value, uid, seqList)
return nil, nil, MaxSeq, MinSeq, err
}
if isContainInt64(pChat.RecvSeq, value) {
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 allCount == 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)
}
allCount++
singleCount++
if singleCount == len(value) {
break
}
}
}
}
return SingleMsg, GroupMsg, MaxSeq, MinSeq, nil
}
func (d *DataBases) SaveUserChat(uid string, sendTime int64, m *pbMsg.MsgSvrToPushSvrChatMsg) error {
var seqUid string
newTime := getCurrentTimestampByMill()
session := d.mgoSession.Clone()
if session == nil {
return errors.New("session == nil")
}
defer session.Close()
log.NewInfo("", "get mgoSession cost time", getCurrentTimestampByMill()-newTime)
c := session.DB(config.Config.Mongo.DBDatabase).C(cChat)
n, err := c.Find(bson.M{"uid": uid}).Count()
seqUid = getSeqUid(uid, m.RecvSeq)
n, err := c.Find(bson.M{"uid": seqUid}).Count()
if err != nil {
return err
}
log.NewInfo("", "find mgo uid cost time", getCurrentTimestampByMill()-newTime)
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.UID = seqUid
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}})
err = c.Update(bson.M{"uid": seqUid}, bson.M{"$push": bson.M{"msg": sMsg}})
if err != nil {
return err
}
}
log.NewInfo("", "insert mgo data cost time", getCurrentTimestampByMill()-newTime)
return nil
}
@ -231,3 +339,25 @@ func (d *DataBases) DelGroupMember(groupID, uid string) error {
return nil
}
func getCurrentTimestampByMill() int64 {
return time.Now().UnixNano() / 1e6
}
func getSeqUid(uid string, seq int64) string {
seqSuffix := seq / singleGocMsgNum
return indexGen(uid, seqSuffix)
}
func isContainInt64(target int64, List []int64) bool {
for _, element := range List {
if target == element {
return true
}
}
return false
}
func indexGen(uid string, seqSuffix int64) string {
return uid + ":" + strconv.FormatInt(seqSuffix, 10)
}

@ -1,9 +1,9 @@
package im_mysql_model
import (
"Open_IM/pkg/proto/group"
"Open_IM/pkg/common/db"
"Open_IM/pkg/common/log"
"Open_IM/pkg/proto/group"
"errors"
"time"
)

@ -3,7 +3,7 @@ package im_mysql_model
import "time"
type User struct {
UID string `gorm:"column:uid"`
UID string `gorm:"column:uid;primaryKey;"`
Name string `gorm:"column:name"`
Icon string `gorm:"column:icon"`
Gender int32 `gorm:"column:gender"`

@ -5,6 +5,7 @@ import (
"Open_IM/pkg/common/db"
pbAuth "Open_IM/pkg/proto/auth"
"Open_IM/pkg/utils"
"fmt"
_ "github.com/jinzhu/gorm/dialects/mysql"
"time"
)
@ -18,7 +19,7 @@ func init() {
pb.Name = "AppManager" + utils.IntToString(k+1)
err := UserRegister(&pb)
if err != nil {
panic(err)
fmt.Println("AppManager insert error", err.Error())
}
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save