265 lines
6.5 KiB
Go
265 lines
6.5 KiB
Go
package ws
|
||
|
||
import (
|
||
"encoding/json"
|
||
"fmt"
|
||
"github.com/gin-gonic/gin"
|
||
"github.com/gorilla/websocket"
|
||
"kefu/models"
|
||
"kefu/types"
|
||
"log"
|
||
"net/http"
|
||
"sync"
|
||
"time"
|
||
)
|
||
|
||
type User struct {
|
||
Conn *websocket.Conn
|
||
Name string
|
||
Id string
|
||
Avator string
|
||
To_id string
|
||
Ent_id string
|
||
Role_id string
|
||
Mux sync.Mutex
|
||
UpdateTime time.Time
|
||
}
|
||
type UserConnection struct {
|
||
Mux sync.Mutex
|
||
Users []*User
|
||
}
|
||
|
||
// 客服链接全局变量
|
||
var KefuList = make(map[string]*UserConnection)
|
||
|
||
// 客服
|
||
func NewKefuServer(c *gin.Context) {
|
||
conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
|
||
if err != nil {
|
||
http.NotFound(c.Writer, c.Request)
|
||
log.Print("upgrade:", err)
|
||
return
|
||
}
|
||
kefuId, _ := c.Get("kefu_id")
|
||
kefuName, _ := c.Get("kefu_name")
|
||
kefuInfo := models.FindUserById(kefuId)
|
||
if kefuInfo.ID == 0 {
|
||
errStr := "客服用户不存在:" + kefuName.(string)
|
||
log.Println(errStr)
|
||
conn.WriteMessage(websocket.TextMessage, []byte(errStr))
|
||
conn.Close()
|
||
return
|
||
}
|
||
var kefu User
|
||
kefu.Id = kefuInfo.Name
|
||
kefu.Name = kefuInfo.Nickname
|
||
kefu.Avator = kefuInfo.Avator
|
||
kefu.Role_id = kefuInfo.RoleId
|
||
if kefuInfo.RoleId <= "2" {
|
||
kefu.Ent_id = fmt.Sprintf("%d", kefuInfo.ID)
|
||
} else {
|
||
kefu.Ent_id = fmt.Sprintf("%d", kefuInfo.Pid)
|
||
}
|
||
kefu.Conn = conn
|
||
AddKefuToList(&kefu)
|
||
//更新客服正在接待数量
|
||
go models.UpdateUserRecNumZero(kefuInfo.Name, VisitorCount(kefuInfo.Name))
|
||
for {
|
||
//接受消息
|
||
//var receive []byte
|
||
_, _, err := conn.ReadMessage()
|
||
//每次读到消息,循环一圈我的conn
|
||
kefuConnection, ok := KefuList[kefuInfo.Name]
|
||
if !ok || len(kefuConnection.Users) == 0 {
|
||
conn.Close()
|
||
return
|
||
}
|
||
//kefuConnection.Users = removeUsersConn(kefuConnection.Users, conn)
|
||
var newKefuConns []*User
|
||
flag := false
|
||
for _, kefuConn := range kefuConnection.Users {
|
||
if kefuConn.Conn != conn {
|
||
newKefuConns = append(newKefuConns, kefuConn)
|
||
} else {
|
||
//找到我了
|
||
flag = true
|
||
}
|
||
}
|
||
//如果链接关闭了,把其他conn加进去就可以了
|
||
if err != nil {
|
||
log.Println("客服ws链接失败:ws/user.go,客服离开 ", kefuInfo.Name, err)
|
||
conn.Close()
|
||
kefuConnection.Users = newKefuConns
|
||
kefuConnection.Mux.Lock()
|
||
KefuList[kefuInfo.Name] = kefuConnection
|
||
kefuConnection.Mux.Unlock()
|
||
return
|
||
}
|
||
////链接没关闭,但是循环一圈没我这个链接
|
||
if !flag {
|
||
conn.Close()
|
||
return
|
||
}
|
||
}
|
||
}
|
||
func AddKefuToList(kefu *User) {
|
||
var newKefuConns = []*User{kefu}
|
||
kefuConnection, ok := KefuList[kefu.Id]
|
||
if !ok {
|
||
kefuConnection = &UserConnection{
|
||
Users: newKefuConns,
|
||
}
|
||
KefuList[kefu.Id] = kefuConnection
|
||
return
|
||
}
|
||
|
||
unreadNum := models.CountMessage("kefu_id = ? and mes_type='visitor' and status = 'unread'", kefu.Id)
|
||
msg := TypeMessage{
|
||
Type: "unread_num",
|
||
Data: unreadNum,
|
||
}
|
||
str, _ := json.Marshal(msg)
|
||
err := kefu.Conn.WriteMessage(websocket.TextMessage, str)
|
||
if err != nil {
|
||
kefu.Conn.Close()
|
||
log.Println("客服ws链接失败:", kefu.Id, err)
|
||
}
|
||
if len(kefuConnection.Users) != 0 {
|
||
for _, otherKefu := range kefuConnection.Users {
|
||
err := otherKefu.Conn.WriteMessage(websocket.TextMessage, str)
|
||
if err == nil {
|
||
newKefuConns = append(newKefuConns, otherKefu)
|
||
} else {
|
||
otherKefu.Conn.Close()
|
||
log.Println("客服ws链接失败:", kefu.Id, err)
|
||
}
|
||
}
|
||
}
|
||
kefuConnection.Users = newKefuConns
|
||
log.Println("客服ws链接成功:客服来了 ", kefu.Id, kefu.Name)
|
||
kefuConnection.Mux.Lock()
|
||
KefuList[kefu.Id] = kefuConnection
|
||
kefuConnection.Mux.Unlock()
|
||
|
||
}
|
||
|
||
// 给超管发消息
|
||
func SuperAdminMessage(str []byte) {
|
||
return
|
||
//给超管发
|
||
}
|
||
|
||
// 访客给客服发消息
|
||
func VisitorSendToKefu(kefuName string, visitorInfo models.Visitor, content string) {
|
||
msgId := models.CreateMessage(kefuName, visitorInfo.VisitorId, content, "visitor", visitorInfo.EntId, "read")
|
||
msg := TypeMessage{
|
||
Type: "message",
|
||
Data: ClientMessage{
|
||
MsgId: msgId,
|
||
Avator: visitorInfo.Avator,
|
||
Id: visitorInfo.VisitorId,
|
||
VisitorId: visitorInfo.VisitorId,
|
||
Name: visitorInfo.Name,
|
||
ToId: kefuName,
|
||
Content: content,
|
||
Time: time.Now().Format("2006-01-02 15:04:05"),
|
||
IsKefu: "no",
|
||
},
|
||
}
|
||
str, _ := json.Marshal(msg)
|
||
OneKefuMessage(kefuName, str)
|
||
}
|
||
|
||
// 给指定客服发消息
|
||
func OneKefuMessage(toId string, str []byte) {
|
||
//新版
|
||
kefuConnection, ok := KefuList[toId]
|
||
if ok && len(kefuConnection.Users) > 0 {
|
||
for _, kefu := range kefuConnection.Users {
|
||
kefu.Mux.Lock()
|
||
error := kefu.Conn.WriteMessage(websocket.TextMessage, str)
|
||
kefu.Mux.Unlock()
|
||
if error != nil {
|
||
log.Println("send_kefu_message", error, string(str))
|
||
}
|
||
}
|
||
}
|
||
SuperAdminMessage(str)
|
||
}
|
||
func KefuMessage(visitorId, content string, kefuInfo models.User) {
|
||
msg := TypeMessage{
|
||
Type: "message",
|
||
Data: ClientMessage{
|
||
Name: kefuInfo.Nickname,
|
||
Avator: kefuInfo.Avator,
|
||
Id: visitorId,
|
||
Time: time.Now().Format("2006-01-02 15:04:05"),
|
||
ToId: visitorId,
|
||
Content: content,
|
||
IsKefu: "yes",
|
||
},
|
||
}
|
||
str, _ := json.Marshal(msg)
|
||
OneKefuMessage(kefuInfo.Name, str)
|
||
}
|
||
|
||
// 给客服客户端发送消息判断客户端是否在线
|
||
func SendPingToKefuClient() {
|
||
for kefuId, kefuConnection := range KefuList {
|
||
var newKefuConns []*User
|
||
//lastDay := tools.GetPastDate(10)
|
||
//unreadNum := models.CountMessage("kefu_id = ? and created_at > ? and mes_type='visitor' and status = 'unread'", kefuId, lastDay)
|
||
var (
|
||
entId string
|
||
)
|
||
for _, kefuConn := range kefuConnection.Users {
|
||
entId = kefuConn.Ent_id
|
||
if kefuConn == nil {
|
||
continue
|
||
}
|
||
|
||
msg := TypeMessage{
|
||
Type: "ping",
|
||
//Data: unreadNum,
|
||
}
|
||
str, _ := json.Marshal(msg)
|
||
kefuConn.Mux.Lock()
|
||
err := kefuConn.Conn.WriteMessage(websocket.TextMessage, str)
|
||
kefuConn.Mux.Unlock()
|
||
if err == nil {
|
||
newKefuConns = append(newKefuConns, kefuConn)
|
||
} else {
|
||
log.Println("客服ws链接失败:", err)
|
||
}
|
||
}
|
||
kefuConnection.Users = newKefuConns
|
||
if len(newKefuConns) > 0 {
|
||
kefuConnection.Mux.Lock()
|
||
KefuList[kefuId] = kefuConnection
|
||
kefuConnection.Mux.Unlock()
|
||
} else {
|
||
online := &models.UpDownLine{
|
||
EntId: entId,
|
||
KefuName: kefuId,
|
||
OnlineStatus: 2,
|
||
ClientIp: "system clean",
|
||
CreatedAt: types.Time{},
|
||
}
|
||
online.AddUpDownLine()
|
||
go models.UpdateUserRecNumZero(kefuId, 0)
|
||
delete(KefuList, kefuId)
|
||
}
|
||
}
|
||
}
|
||
|
||
// 删除切片数据
|
||
func removeUsersConn(s []*User, conn *websocket.Conn) []*User {
|
||
for i := 0; i < len(s); i++ {
|
||
if s[i].Conn == conn {
|
||
s = append(s[:i], s[i+1:]...)
|
||
i--
|
||
}
|
||
}
|
||
return s
|
||
}
|