1
This commit is contained in:
@@ -1,275 +1,276 @@
|
||||
package im
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"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 // 用户连接
|
||||
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
|
||||
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 {
|
||||
//ClientId string `json:"clientId" validate:"required"` //链接ID
|
||||
VendorID int `json:"vendorID"` //消息来源平台ID
|
||||
Data interface{} `json:"data"` //发送给平台 美团/饿了么消息结构体
|
||||
//返回值
|
||||
//Code int `json:"code"`
|
||||
//Msg string `json:"msg"`
|
||||
//SendUserId string `json:"sendUserId"`
|
||||
}
|
||||
|
||||
// JXMsg 京西消息结构体
|
||||
type JXMsg struct {
|
||||
SendType string `json:"sendType"` //消息发送方 jx-商家;mt-美团;elm-饿了么
|
||||
Data interface{} `json:"data"` //美团/饿了么 单聊消息
|
||||
}
|
||||
|
||||
// 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-饿了么
|
||||
UserID string `json:"userID"` //用户ID
|
||||
NewMessageNum int `json:"NewMessageNum"` //新消息数量
|
||||
LatestMsg string `json:"latestMsg"` //最新一条消息
|
||||
LatestTime int `json:"latestTime"` //最新一条消息发送时间
|
||||
}
|
||||
|
||||
type RelInfo struct {
|
||||
VendorStoreID string `json:"vendorStoreID"` //平台门店id
|
||||
VendorID string `json:"vendorID"` //平台标识id
|
||||
AppID string `json:"appID"` //应用ID
|
||||
}
|
||||
|
||||
type UserRelInfo struct {
|
||||
VendorStoreID string `json:"vendorStoreID"` //平台门店id
|
||||
VendorID string `json:"vendorID"` //平台标识id
|
||||
AppID string `json:"appID"` //应用ID
|
||||
UserID string `json:"userID"` //用户id/groupID
|
||||
}
|
||||
|
||||
var (
|
||||
cfg *ini.File
|
||||
rdb = api.Cacher
|
||||
Manager = NewClientManager() // 管理者
|
||||
CommonSetting = &commonConf{}
|
||||
GlobalSetting = &global{}
|
||||
ToClientChan chan clientInfo
|
||||
heartbeatInterval = 60 * time.Second // 心跳间隔
|
||||
HeartCheckMsg = "~#HHHBBB#~" //心跳检测消息
|
||||
HeartCheckSuccess = "HB" //成功发送返回心跳消息
|
||||
VendorIDMT = 10 //im美团
|
||||
VendorIDELM = 11 //im饿了么
|
||||
SendTypeJx = "jx" //京西客户端发送方标识
|
||||
SendTypeMt = "mt" //美团用户发送方标识符
|
||||
SendTypeElm = "elm" //饿了么用户发送方标识符
|
||||
MTIMPushUrl = "wss://wpush.meituan.com/websocket" //buildPushConnect建立长连接
|
||||
)
|
||||
|
||||
const (
|
||||
ExpireTimeDay = 24 * time.Hour //redis一天过期时间
|
||||
maxMessageSize = 8192 // 最大的消息大小
|
||||
)
|
||||
|
||||
type renderData struct {
|
||||
ClientId string `json:"clientId"`
|
||||
}
|
||||
|
||||
const (
|
||||
SuccessCode = 0
|
||||
SuccessMsg = "success"
|
||||
Fail = -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 {
|
||||
return conn.WriteJSON(RetData{
|
||||
Code: code,
|
||||
Msg: message,
|
||||
Data: data,
|
||||
})
|
||||
}
|
||||
|
||||
func ClientRender(w http.ResponseWriter, code int, msg string, data interface{}) (str string) {
|
||||
var retData RetData
|
||||
|
||||
retData.Code = code
|
||||
retData.Msg = msg
|
||||
retData.Data = data
|
||||
|
||||
retJson, _ := json.Marshal(retData)
|
||||
str = string(retJson)
|
||||
|
||||
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 ServerList=%s\n", GlobalSetting.LocalHost, utils.Format4Output(GlobalSetting.ServerList, false))
|
||||
}
|
||||
|
||||
// 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() (fullUrl string) {
|
||||
resp, err := api.MtwmAPI.GetConnectionToken()
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
retVal := mtwmapi.GetConnTokenResp{}
|
||||
err = mapstructure.Decode(resp, &retVal)
|
||||
fullUrl = MTIMPushUrl + "/" + retVal.AppKey + "/" + retVal.ConnectionToken
|
||||
//clientID = api.MtwmAPI.GetAppID() + ":" + retVal.ConnectionToken
|
||||
//打印输出
|
||||
//fmt.Printf("Create websocket connect failCount:%d", retVal.UserCount)
|
||||
return fullUrl
|
||||
}
|
||||
//
|
||||
//import (
|
||||
// "encoding/json"
|
||||
// "flag"
|
||||
// "fmt"
|
||||
// "git.rosy.net.cn/baseapi/utils"
|
||||
// "io"
|
||||
// "log"
|
||||
// "net"
|
||||
// "net/http"
|
||||
// "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 // 用户连接
|
||||
// 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
|
||||
// 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 {
|
||||
// //ClientId string `json:"clientId" validate:"required"` //链接ID
|
||||
// VendorID int `json:"vendorID"` //消息来源平台ID
|
||||
// Data interface{} `json:"data"` //发送给平台 美团/饿了么消息结构体
|
||||
// //返回值
|
||||
// //Code int `json:"code"`
|
||||
// //Msg string `json:"msg"`
|
||||
// //SendUserId string `json:"sendUserId"`
|
||||
//}
|
||||
//
|
||||
//// JXMsg 京西消息结构体
|
||||
//type JXMsg struct {
|
||||
// SendType string `json:"sendType"` //消息发送方 jx-商家;mt-美团;elm-饿了么
|
||||
// Data interface{} `json:"data"` //美团/饿了么 单聊消息
|
||||
//}
|
||||
//
|
||||
//// 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-饿了么
|
||||
// UserID string `json:"userID"` //用户ID
|
||||
// NewMessageNum int `json:"NewMessageNum"` //新消息数量
|
||||
// LatestMsg string `json:"latestMsg"` //最新一条消息
|
||||
// LatestTime int `json:"latestTime"` //最新一条消息发送时间
|
||||
//}
|
||||
//
|
||||
//type RelInfo struct {
|
||||
// VendorStoreID string `json:"vendorStoreID"` //平台门店id
|
||||
// VendorID string `json:"vendorID"` //平台标识id
|
||||
// AppID string `json:"appID"` //应用ID
|
||||
//}
|
||||
//
|
||||
//type UserRelInfo struct {
|
||||
// VendorStoreID string `json:"vendorStoreID"` //平台门店id
|
||||
// VendorID string `json:"vendorID"` //平台标识id
|
||||
// AppID string `json:"appID"` //应用ID
|
||||
// UserID string `json:"userID"` //用户id/groupID
|
||||
//}
|
||||
//
|
||||
//var (
|
||||
// cfg *ini.File
|
||||
// rdb = api.Cacher
|
||||
// Manager = NewClientManager() // 管理者
|
||||
// CommonSetting = &commonConf{}
|
||||
// GlobalSetting = &global{}
|
||||
// ToClientChan chan clientInfo
|
||||
// heartbeatInterval = 60 * time.Second // 心跳间隔
|
||||
// HeartCheckMsg = "~#HHHBBB#~" //心跳检测消息
|
||||
// HeartCheckSuccess = "HB" //成功发送返回心跳消息
|
||||
// VendorIDMT = 10 //im美团
|
||||
// VendorIDELM = 11 //im饿了么
|
||||
// SendTypeJx = "jx" //京西客户端发送方标识
|
||||
// SendTypeMt = "mt" //美团用户发送方标识符
|
||||
// SendTypeElm = "elm" //饿了么用户发送方标识符
|
||||
// MTIMPushUrl = "wss://wpush.meituan.com/websocket" //buildPushConnect建立长连接
|
||||
//)
|
||||
//
|
||||
//const (
|
||||
// ExpireTimeDay = 24 * time.Hour //redis一天过期时间
|
||||
// maxMessageSize = 8192 // 最大的消息大小
|
||||
//)
|
||||
//
|
||||
//type renderData struct {
|
||||
// ClientId string `json:"clientId"`
|
||||
//}
|
||||
//
|
||||
//const (
|
||||
// SuccessCode = 0
|
||||
// SuccessMsg = "success"
|
||||
// Fail = -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 {
|
||||
// return conn.WriteJSON(RetData{
|
||||
// Code: code,
|
||||
// Msg: message,
|
||||
// Data: data,
|
||||
// })
|
||||
//}
|
||||
//
|
||||
//func ClientRender(w http.ResponseWriter, code int, msg string, data interface{}) (str string) {
|
||||
// var retData RetData
|
||||
//
|
||||
// retData.Code = code
|
||||
// retData.Msg = msg
|
||||
// retData.Data = data
|
||||
//
|
||||
// retJson, _ := json.Marshal(retData)
|
||||
// str = string(retJson)
|
||||
//
|
||||
// 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 ServerList=%s\n", GlobalSetting.LocalHost, utils.Format4Output(GlobalSetting.ServerList, false))
|
||||
//}
|
||||
//
|
||||
//// 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() (fullUrl string) {
|
||||
// resp, err := api.MtwmAPI.GetConnectionToken()
|
||||
// if err != nil {
|
||||
// return ""
|
||||
// }
|
||||
// retVal := mtwmapi.GetConnTokenResp{}
|
||||
// err = mapstructure.Decode(resp, &retVal)
|
||||
// fullUrl = MTIMPushUrl + "/" + retVal.AppKey + "/" + retVal.ConnectionToken
|
||||
// //clientID = api.MtwmAPI.GetAppID() + ":" + retVal.ConnectionToken
|
||||
// //打印输出
|
||||
// //fmt.Printf("Create websocket connect failCount:%d", retVal.UserCount)
|
||||
// return fullUrl
|
||||
//}
|
||||
|
||||
Reference in New Issue
Block a user