kefu/ws/user.go

265 lines
6.5 KiB
Go
Raw Permalink Normal View History

2024-12-10 02:50:12 +00:00
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
}