This commit is contained in:
richboo111
2023-06-16 17:33:51 +08:00
parent 64e4339aeb
commit 061baad58f
9 changed files with 109 additions and 798 deletions

View File

@@ -1,85 +1,11 @@
package im
import (
"encoding/json"
"flag"
"fmt"
"io"
"log"
r "math/rand"
"net"
"net/http/httptest"
"sync"
"time"
"git.rosy.net.cn/baseapi/platformapi/mtwmapi"
"git.rosy.net.cn/jx-callback/globals/api"
"github.com/gazeboxu/mapstructure"
"github.com/gorilla/websocket"
"gopkg.in/ini.v1"
)
// ClientManager 连接管理
type ClientManager struct {
ClientIdMap map[string]*Client // 全部的连接
ClientIdMapLock sync.RWMutex // 读写锁
Connect chan *Client // 连接处理
DisConnect chan *Client // 断开连接处理
GroupLock sync.RWMutex
Groups map[string][]string
SystemClientsLock sync.RWMutex
SystemClients map[string][]string
}
// Client 客户端连接信息
type Client struct {
ClientId string // 标识ID
Socket *websocket.Conn // 用户连接
ClientType string //标识是美团/客户端长链接
ConnectTime uint64 // 首次连接时间
IsDeleted bool // 是否删除或下线
UserId string // 业务端标识用户ID
//Extend string // 扩展字段,用户可以自定义
//GroupList []string
}
//channel通道结构体
type clientInfo struct {
ClientId string `json:"clientId" validate:"required"` //链接ID
Data interface{}
SendUserId string
MessageId string
Code int
Msg string
}
// RetData 统一返回值结构体
type RetData struct {
Code int `json:"code"` //响应code
Msg string `json:"msg"` //响应msg success/fail
//MsgType string `json:"msgType"` //发送消息方类型mt;elm;jx
Data interface{} `json:"data"` //信息
//MessageType string `json:"messageType"` //消息类型 heart-心跳检测send-发送消息receive-接收消息
//MessageId string `json:"messageId"` //发送/接收信息 id
//UserId string `json:"userId"` //必须是平台方userID
}
type global struct {
LocalHost string //本机内网IP
ServerList map[string]string
ServerListLock sync.RWMutex
}
type commonConf struct {
HttpPort string
RPCPort string
Cluster bool
CryptoKey string
}
// SendData 客户端写入参数
type SendData struct {
VendorID int `json:"vendorID"` //消息来源平台ID 1-美团 3-饿了么
@@ -92,23 +18,9 @@ type JXMsg struct {
MsgContent interface{} `json:"msgContent"` //美团/饿了么 单聊消息
}
// GetUserListReq 获取门店用户聊天列表
type GetUserListReq struct {
VendorStoreID string `json:"vendorStoreID"` //平台门店id
VendorID string `json:"vendorID"` //平台标识id
AppID string `json:"appID"` //应用ID
}
type GetChatDetailReq struct {
VendorStoreID string `json:"vendorStoreID"` //平台门店id
VendorID string `json:"vendorID"` //平台标识id
AppID string `json:"appID"` //应用ID
UserID string `json:"userID"` //userID/groupID
}
// UserMessageList 用户消息列表
type UserMessageList struct {
VendorID int `json:"vendorID"` //平台品牌 10-美团 11-饿了么
VendorID int `json:"vendorID"` //平台品牌 1-美团 3-饿了么
UserID string `json:"userID"` //用户ID
NewMessageNum int `json:"NewMessageNum"` //新消息数量
LatestMsg string `json:"latestMsg"` //最新一条消息
@@ -128,222 +40,16 @@ type UserRelInfo struct {
UserID string `json:"userID"` //用户id/groupID
}
// UrlInfo 生成美团长链接url信息
type UrlInfo struct {
UrlMain string `json:"urlMain"` //主连接路由
ClientIDMain string `json:"ClientIDMain"` //主连接id
UrlSub string `json:"urlSub"` //副连接路由
ClientIDSub string `json:"ClientIDSub"` //副连接id
}
var (
cfg *ini.File
rdb = api.Cacher
//客户端相关
Manager = NewClientManager() // 管理者
ToClientChan chan clientInfo
ClientTypeJx = "jx" //京西客户端
ClientTypeMt = "mt" //美团客户端
//配置文件
CommonSetting = &commonConf{}
GlobalSetting = &global{}
//心跳相关
heartbeatInterval = 20 * time.Second // 心跳间隔
HeartCheckMsg = "~#HHHBBB#~" //心跳检测消息
HeartCheckSuccess = "HB" //成功发送返回心跳消息
HeartSuccessWord = "成功" //成功发送返回心跳消息
//平台标识
AppID5873 = float64(5873)
AppID589 = "589"
VendorIDMT = 1 //im美团
VendorIDELM = 3 //im饿了么
SendTypeJx = "jx" //京西客户端发送方标识
SendTypeMt = "mt" //美团用户发送方标识符
SendTypeElm = "elm" //饿了么用户发送方标识符
MTIMPushUrl = "wss://wpush.meituan.com/websocket" //buildPushConnect建立长连接
rdb = api.Cacher
VendorIDMT = 1 //im美团
VendorIDELM = 3 //im饿了么
SendTypeJx = "jx" //京西客户端发送方标识
SendTypeMt = "mt" //美团用户发送方标识符
SendTypeElm = "elm" //饿了么用户发送方标识符
)
const (
ExpireTimeDay = 2 * time.Hour //redis一天过期时间
maxMessageSize = 8192 // 最大的消息大小
ExpireTimeDay = 4 * time.Hour //redis过期时间
)
type renderData struct {
ClientId string `json:"clientId"`
}
const (
SuccessCode = 0
SuccessMsg = "success"
FailCode = -1
FailMsg = "fail"
SYSTEM_ID_ERROR = -1001
ONLINE_MESSAGE_CODE = 1001
OFFLINE_MESSAGE_CODE = 1002
)
// Render 统一返回值
func Render(conn *websocket.Conn, messageId string, code int, message string, data interface{}) error {
if data != nil {
str, _ := json.Marshal(data)
temp := string(str)
return conn.WriteJSON(RetData{
Code: code,
Msg: message,
//MsgType: temp.SendType,
Data: temp,
})
} else {
return conn.WriteJSON(RetData{
Code: code,
Msg: message,
})
}
}
// ClientRender http响应
func ClientRender(code int, msg string) (str string) {
var retData RetData
retData.Code = code
retData.Msg = msg
//retData.Data = data
retJson, _ := json.Marshal(retData)
str = string(retJson)
w := httptest.NewRecorder()
w.Header().Set("Content-Type", "application/json; charset=utf-8")
_, _ = io.WriteString(w, str)
return
}
func ConnRender(conn *websocket.Conn, data interface{}) (err error) {
err = conn.WriteJSON(RetData{
Code: SuccessCode,
Msg: "success",
Data: data,
})
return
}
// Default 给默认值
func Default() {
CommonSetting = &commonConf{
HttpPort: "6000",
RPCPort: "7000",
Cluster: false,
CryptoKey: "Adba723b7fe06819",
}
GlobalSetting = &global{
LocalHost: getIntranetIp(),
ServerList: make(map[string]string),
}
}
// Setup 初始化全局设置变量
func Setup() {
configFile := flag.String("c", "conf/app.ini", "-c conf/app.ini")
var err error
cfg, err = ini.Load(*configFile)
if err != nil {
log.Fatalf("setting.Setup, fail to parse 'conf/app.ini': %v", err)
}
mapTo("common", CommonSetting)
GlobalSetting = &global{
LocalHost: getIntranetIp(),
ServerList: make(map[string]string),
}
fmt.Printf("LocalHost=%s\n ", GlobalSetting.LocalHost)
}
// mapTo map section
func mapTo(section string, v interface{}) {
err := cfg.Section(section).MapTo(v)
if err != nil {
log.Fatalf("Cfg.MapTo %s err: %v", section, err)
}
}
//获取本机IP
func getIntranetIp() string {
addrs, _ := net.InterfaceAddrs()
for _, addr := range addrs {
// 检查ip地址判断是否回环地址
if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
if ipnet.IP.To4() != nil {
return ipnet.IP.String()
}
}
}
return ""
}
// GenFullUrl 组装完整websocket url以及生成clientID
func GenFullUrl(appID float64) (fullUrl string) {
if appID == AppID5873 {
if resp5873, err := api.Mtwm2API.GetConnectionToken(); err == nil {
r1 := mtwmapi.GetConnTokenResp{}
err = mapstructure.Decode(resp5873, &r1)
fullUrl = MTIMPushUrl + "/" + r1.AppKey + "/" + r1.ConnectionToken
return fullUrl
}
}
//589/4123
resp, err := api.MtwmAPI.GetConnectionToken()
if err != nil {
return ""
}
retVal := mtwmapi.GetConnTokenResp{}
err = mapstructure.Decode(resp, &retVal)
fullUrl = MTIMPushUrl + "/" + retVal.AppKey + "/" + retVal.ConnectionToken
return fullUrl
}
// GenFullUrl2 组装完整websocket url以及生成clientID
func GenFullUrl2() *UrlInfo {
urlInfo := &UrlInfo{}
//1 589/4123
resp, err := api.MtwmAPI.GetConnectionToken()
if err != nil {
return nil
}
retVal := mtwmapi.GetConnTokenResp{}
err = mapstructure.Decode(resp, &retVal)
urlInfo.UrlMain = MTIMPushUrl + "/" + retVal.AppKey + "/" + retVal.ConnectionToken
urlInfo.ClientIDMain = retVal.AppKey + ":" + retVal.ConnectionToken
if api.MtwmAPI.GetAppID() == AppID589 { //目前果园无4123
if resp5873, err := api.Mtwm2API.GetConnectionToken(); err == nil {
r1 := mtwmapi.GetConnTokenResp{}
err = mapstructure.Decode(resp5873, &r1)
urlInfo.UrlSub = MTIMPushUrl + "/" + r1.AppKey + "/" + r1.ConnectionToken
urlInfo.ClientIDSub = r1.AppKey + ":" + r1.ConnectionToken
}
}
return urlInfo
}
// RandString 生成随机字符串
func RandString() string {
bytes := make([]byte, 16)
for i := 0; i < 16; i++ {
b := r.Intn(26) + 65
bytes[i] = byte(b)
}
return string(bytes)
}
// JsonCommon json格式化
func JsonCommon(str string) (retVal string) {
temp, _ := json.Marshal(str)
_ = json.Unmarshal(temp, &retVal)
return retVal
}