kefu/ws/user.go

265 lines
6.5 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
}