kefu/controller/message.go

907 lines
25 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 controller
import (
"encoding/json"
"fmt"
"github.com/gin-gonic/gin"
"github.com/gorilla/websocket"
"kefu/common"
"kefu/lib"
"kefu/models"
"kefu/service"
"kefu/tools"
"kefu/types"
"kefu/ws"
"log"
"net/url"
"os"
"path"
"strconv"
"strings"
"time"
)
type VisitorMessageForm struct {
ToId string `form:"to_id" json:"to_id" uri:"to_id" xml:"to_id" binding:"required"`
FromId string `form:"from_id" json:"from_id" uri:"from_id" xml:"from_id" binding:"required"`
Content string `form:"content" json:"content" uri:"content" xml:"content" binding:"required"`
IsAutoReply string `form:"is_autoreply" json:"is_autoreply" uri:"is_autoreply" xml:"is_autoreply"`
}
func SendMessageV2(c *gin.Context) {
var form VisitorMessageForm
err := c.Bind(&form)
if err != nil {
c.JSON(200, gin.H{
"code": types.ApiCode.FAILED,
"msg": types.ApiCode.GetMessage(types.ApiCode.INVALID),
"result": err.Error(),
})
return
}
fromId := form.FromId
toId := form.ToId
content := form.Content
//判断是否离线
//_, ok := ws.ClientList[fromId]
//if !ok {
// c.JSON(200, gin.H{
// "code": types.ApiCode.VISITOR_OFFLINE,
// "msg": types.ApiCode.GetMessage(types.ApiCode.VISITOR_OFFLINE),
// })
// return
//}
//限流
if models.FindConfig("SystemFreqLimt") != "true" && !tools.LimitFreqSingle("sendmessage:"+c.ClientIP(), 1, 1) {
c.JSON(200, gin.H{
"code": types.ApiCode.FREQ_LIMIT,
"msg": c.ClientIP() + types.ApiCode.GetMessage(types.ApiCode.FREQ_LIMIT),
})
return
}
//验证黑名单
//验证访客黑名单
if !CheckVisitorBlack(fromId) {
c.JSON(200, gin.H{
"code": types.ApiCode.VISITOR_BAN,
"msg": types.ApiCode.GetMessage(types.ApiCode.VISITOR_BAN),
})
return
}
//过滤敏感词
content, isBlack := ReplaceBlackWords(content)
var kefuInfo models.User
var vistorInfo models.Visitor
vistorInfo = models.FindVisitorByVistorId(fromId)
//提示上班时间
//查询企业配置项
entConfigs := models.GetEntConfigsMap(vistorInfo.EntId, "workTimeStatus",
"workDay", "morningWorkTime", "afternoonWorkTime", "otherWorkTime", "afterWorkMessage", "BaiduFanyiAppId", "BaiduFanyiAppSec", "BaiduFanyiAuto")
if entConfigs["workTimeStatus"] == "yes" {
if !tools.IsWorkTime(strings.Split(entConfigs["workDay"], "|"),
strings.Split(entConfigs["morningWorkTime"], "|"),
strings.Split(entConfigs["afternoonWorkTime"], "|"),
strings.Split(entConfigs["otherWorkTime"], "|")) {
ws.VisitorNotice(vistorInfo.VisitorId, entConfigs["afterWorkMessage"])
}
}
kefuInfo = models.FindUser(toId)
if kefuInfo.ID == 0 || vistorInfo.ID == 0 {
c.JSON(200, gin.H{
"code": types.ApiCode.ACCOUNT_NO_EXIST,
"msg": types.ApiCode.GetMessage(types.ApiCode.ACCOUNT_NO_EXIST),
})
return
}
msgId := models.CreateMessage(kefuInfo.Name, vistorInfo.VisitorId, content, "visitor", vistorInfo.EntId, "unread")
guest, ok := ws.ClientList[vistorInfo.VisitorId]
if ok && guest != nil {
guest.UpdateTime = time.Now()
}
wsContent := content
//是否进行百度翻译
if entConfigs["BaiduFanyiAppId"] != "" && entConfigs["BaiduFanyiAppSec"] != "" && entConfigs["BaiduFanyiAuto"] == "on" {
baidu := &lib.BaiduFanyi{
AppId: entConfigs["BaiduFanyiAppId"],
AppSec: entConfigs["BaiduFanyiAppSec"],
}
res, err := baidu.Translate(content, "auto", "zh")
if err == nil && res != "" {
wsContent += "\n" + res
}
}
msg := ws.TypeMessage{
Type: "message",
Data: ws.ClientMessage{
MsgId: msgId,
Avator: vistorInfo.Avator,
Id: vistorInfo.VisitorId,
VisitorId: vistorInfo.VisitorId,
Name: vistorInfo.Name,
ToId: kefuInfo.Name,
Content: wsContent,
Time: time.Now().Format("2006-01-02 15:04:05"),
IsKefu: "no",
},
}
str, _ := json.Marshal(msg)
ws.OneKefuMessage(kefuInfo.Name, str)
//回调url
go SendVisitorMessageCallUrl(vistorInfo.EntId, vistorInfo.Name, kefuInfo.Name, vistorInfo.Name, vistorInfo.Avator, content)
go SendAppGetuiPush(kefuInfo.Name, "[信息]"+vistorInfo.Name, content)
go SendWechatVisitorMessageTemplate(kefuInfo.Name, vistorInfo.Name, vistorInfo.VisitorId, content, vistorInfo.EntId)
//go SendWechatKefuNotice(kefuInfo.Name, "[访客]"+vistorInfo.Name+",说:"+content, vistorInfo.EntId)
kefus, ok := ws.KefuList[kefuInfo.Name]
go service.SendWorkWechatMesage(vistorInfo.EntId, vistorInfo, kefuInfo, content, c)
if !ok || len(kefus.Users) == 0 {
go SendNoticeEmail(vistorInfo.Name, "[留言]"+vistorInfo.Name, vistorInfo.EntId, content)
}
//是否机器人回复
if form.IsAutoReply != "no" {
go ws.VisitorAutoReply(vistorInfo, kefuInfo, content)
}
go models.ReadMessageByVisitorId(vistorInfo.VisitorId, "kefu")
go models.UpdateVisitorVisitorId(vistorInfo.VisitorId, vistorInfo.VisitorId)
c.JSON(200, gin.H{
"code": 200,
"msg": "ok",
"result": gin.H{
"content": content,
"isBlack": isBlack,
},
})
}
func SendSyncMessage(c *gin.Context) {
visitorId := c.PostForm("visitor_id")
content := c.PostForm("content")
//验证访客黑名单
if !CheckVisitorBlack(visitorId) {
c.JSON(200, gin.H{
"code": types.ApiCode.VISITOR_BAN,
"msg": types.ApiCode.GetMessage(types.ApiCode.VISITOR_BAN),
})
return
}
//过滤敏感词
content, _ = ReplaceBlackWords(content)
var vistorInfo models.Visitor
vistorInfo = models.FindVisitorByVistorId(visitorId)
kefuInfo := models.FindUser(vistorInfo.ToId)
if kefuInfo.ID == 0 || vistorInfo.ID == 0 {
c.JSON(200, gin.H{
"code": types.ApiCode.ACCOUNT_NO_EXIST,
"msg": types.ApiCode.GetMessage(types.ApiCode.ACCOUNT_NO_EXIST),
})
return
}
models.CreateMessage(vistorInfo.ToId, vistorInfo.VisitorId, content, "kefu", vistorInfo.EntId, "read")
go ws.KefuMessage(visitorId, content, kefuInfo)
c.JSON(200, gin.H{
"code": types.ApiCode.SUCCESS,
"msg": types.ApiCode.GetMessage(types.ApiCode.SUCCESS),
})
}
func SendRobotMessage(c *gin.Context) {
visitorId := c.PostForm("visitor_id")
entId := c.PostForm("ent_id")
content := c.PostForm("content")
//限流
if !tools.LimitFreqSingle("sendmessage:"+c.ClientIP(), 1, 1) {
c.JSON(200, gin.H{
"code": types.ApiCode.FREQ_LIMIT,
"msg": c.ClientIP() + types.ApiCode.GetMessage(types.ApiCode.FREQ_LIMIT),
})
return
}
vistorInfo := models.FindVisitorByVistorId(visitorId)
kefuInfo := models.FindUserByUid(entId)
if kefuInfo.ID == 0 {
c.JSON(200, gin.H{
"code": types.ApiCode.ACCOUNT_NO_EXIST,
"msg": types.ApiCode.GetMessage(types.ApiCode.ACCOUNT_NO_EXIST),
})
return
}
//查询机器人信息
configs := models.GetEntConfigsMap(entId, "RobotName", "RobotAvator")
robotName := configs["RobotName"]
robotAvator := configs["RobotAvator"]
articles := models.FindArticleList(1, 10, "score desc", "ent_id= ? and title like ?", entId, "%"+content+"%")
result := ""
articleLen := len(articles)
//未匹配,进入学习库
if articleLen == 0 {
if len([]rune(content)) > 1 {
go AddUpdateLearn(entId, content)
}
} else if articleLen == 1 {
result = articles[0].Content
article := models.Article{
Score: articles[0].Score + 1,
}
go article.SaveArticle("ent_id = ? and id = ?", entId, articles[0].Id)
} else if articleLen > 1 {
result = "您是不是想问:"
for _, article := range articles {
title := strings.Split(strings.ReplaceAll(article.Title, "", ","), ",")[0]
result += fmt.Sprintf("<p><a href='#'>%s</a></p>", title)
}
}
//调用GPT3.5
if result == "" && models.CheckVisitorRobotReply(vistorInfo.State) {
result = ws.Gpt3Knowledge(entId, visitorId, kefuInfo, content)
}
//调用chatGPT
//if result == "" {
// result = ws.Gpt3dot5Message(entId, visitorId, kefuInfo, content)
//}
models.CreateMessage(kefuInfo.Name, vistorInfo.VisitorId, content, "visitor", vistorInfo.EntId, "read")
if result != "" {
go models.CreateMessage(kefuInfo.Name, vistorInfo.VisitorId, result, "kefu", vistorInfo.EntId, "read")
}
c.JSON(200, gin.H{
"code": types.ApiCode.SUCCESS,
"msg": "ok",
"result": gin.H{
"username": tools.Ifelse(robotName != "", robotName, kefuInfo.Nickname),
"avator": tools.Ifelse(robotAvator != "", robotAvator, kefuInfo.Avator),
"content": result,
},
})
}
func SendKefuMessage(c *gin.Context) {
entId, _ := c.Get("ent_id")
fromId, _ := c.Get("kefu_name")
toId := c.PostForm("to_id")
content := c.PostForm("content")
cType := c.PostForm("type")
if content == "" {
c.JSON(200, gin.H{
"code": 400,
"msg": "内容不能为空",
})
return
}
//过滤敏感词
content, _ = ReplaceBlackWords(content)
var kefuInfo models.User
var vistorInfo models.Visitor
kefuInfo = models.FindUser(fromId.(string))
vistorInfo = models.FindVisitorByVistorId(toId)
if kefuInfo.ID == 0 || vistorInfo.ID == 0 {
c.JSON(200, gin.H{
"code": 400,
"msg": "用户不存在",
})
return
}
roleId, _ := c.Get("role_id")
kefuInfo.RoleId = fmt.Sprintf("%v", roleId)
var msg ws.TypeMessage
guest, ok := ws.ClientList[vistorInfo.VisitorId]
isRead := "unread"
msgId := models.CreateMessage(kefuInfo.Name, vistorInfo.VisitorId, content, cType, entId.(string), isRead)
if guest != nil && ok {
conn := guest.Conn
msg = ws.TypeMessage{
Type: "message",
Data: ws.ClientMessage{
MsgId: msgId,
Name: kefuInfo.Nickname,
Avator: kefuInfo.Avator,
Id: kefuInfo.Name,
Time: time.Now().Format("2006-01-02 15:04:05"),
ToId: vistorInfo.VisitorId,
Content: content,
IsKefu: "no",
},
}
str, _ := json.Marshal(msg)
conn.WriteMessage(websocket.TextMessage, str)
} else {
//客服发送给公众号模板消息
//go SendWechatKefuTemplate(vistorInfo.VisitorId, kefuInfo.Name, kefuInfo.Nickname, content, fmt.Sprintf("%v", entId))
go SendKefuMessageCallUrl(kefuInfo.Name, vistorInfo.VisitorId, content, vistorInfo.EntId, kefuInfo.Nickname)
//客服发给小程序订阅模板消息
go service.SendMiniSubscribe(vistorInfo.VisitorId, content, fmt.Sprintf("%v", entId), kefuInfo.Nickname)
}
//客服发送给小程序访客消息
go SendMiniVisitorMessage(vistorInfo.VisitorId, content, fmt.Sprintf("%v", entId))
//客服发送给公众号用户信息
go SendWechatVisitorMessage(vistorInfo.VisitorId, content, fmt.Sprintf("%v", entId))
//客服发送给微信客服用户的消息
go SendWeworkKfVisitorMessage(vistorInfo, content)
//客服发送到抖音评论
go SendDouyinCommentMessage(vistorInfo, content)
//客服发送到抖音评论
go SendDouyinPrivateMessage(vistorInfo, content)
msg = ws.TypeMessage{
Type: "message",
Data: ws.ClientMessage{
MsgId: msgId,
Name: kefuInfo.Nickname,
Avator: kefuInfo.Avator,
Id: vistorInfo.VisitorId,
Time: time.Now().Format("2006-01-02 15:04:05"),
ToId: vistorInfo.VisitorId,
Content: content,
IsKefu: "yes",
},
}
str2, _ := json.Marshal(msg)
ws.OneKefuMessage(kefuInfo.Name, str2)
go models.ReadMessageByVisitorId(vistorInfo.VisitorId, "visitor")
c.JSON(200, gin.H{
"code": 200,
"msg": "ok",
})
}
func SendVisitorNotice(c *gin.Context) {
notice := c.Query("msg")
if notice == "" {
c.JSON(200, gin.H{
"code": 400,
"msg": "msg不能为空",
})
return
}
msg := ws.TypeMessage{
Type: "notice",
Data: notice,
}
str, _ := json.Marshal(msg)
for _, visitor := range ws.ClientList {
visitor.Conn.WriteMessage(websocket.TextMessage, str)
}
c.JSON(200, gin.H{
"code": 200,
"msg": "ok",
})
}
func SendCloseMessageV2(c *gin.Context) {
ent_id, _ := c.Get("ent_id")
visitorId := c.Query("visitor_id")
if visitorId == "" {
c.JSON(200, gin.H{
"code": 400,
"msg": "visitor_id不能为空",
})
return
}
config := models.FindEntConfig(ent_id, "CloseVisitorMessage")
oldUser, ok := ws.ClientList[visitorId]
if oldUser != nil || ok {
ws.VisitorOffline(oldUser.ToId, oldUser.Id, oldUser.Name)
if config.ConfValue != "" {
kefu := models.FindUserByUid(ent_id)
ws.VisitorMessage(visitorId, config.ConfValue, kefu)
}
msg := ws.TypeMessage{
Type: "force_close",
Data: visitorId,
}
str, _ := json.Marshal(msg)
err := oldUser.Conn.WriteMessage(websocket.TextMessage, str)
oldUser.Conn.Close()
delete(ws.ClientList, visitorId)
log.Println("close_message", oldUser, err)
}
c.JSON(200, gin.H{
"code": 200,
"msg": "ok",
})
}
func UploadImg(c *gin.Context) {
f, err := c.FormFile("imgfile")
if err != nil {
c.JSON(200, gin.H{
"code": 400,
"msg": "上传失败!",
})
return
} else {
fileExt := strings.ToLower(path.Ext(f.Filename))
if fileExt != ".png" && fileExt != ".jpg" && fileExt != ".gif" && fileExt != ".jpeg" {
c.JSON(200, gin.H{
"code": 400,
"msg": "上传失败!只允许png,jpg,gif,jpeg文件",
})
return
}
fileName := tools.Md5(fmt.Sprintf("%s%s", f.Filename, time.Now().String()))
fildDir := fmt.Sprintf("%s%d%s/", common.Upload, time.Now().Year(), time.Now().Month().String())
isExist, _ := tools.IsFileExist(fildDir)
if !isExist {
os.Mkdir(fildDir, os.ModePerm)
}
filepath := fmt.Sprintf("%s%s%s", fildDir, fileName, fileExt)
c.SaveUploadedFile(f, filepath)
path := "/" + filepath
//上传到阿里云oss
oss, err := lib.NewOssLib()
if err == nil {
dstUrl, err := oss.Upload(filepath, filepath)
if err == nil {
path = dstUrl
} else {
log.Println(err.Error())
}
} else {
log.Println(err.Error())
}
c.JSON(200, gin.H{
"code": 200,
"msg": "上传成功!",
"result": gin.H{
"path": path,
},
})
}
}
func UploadFile(c *gin.Context) {
SendAttachment, err := strconv.ParseBool(models.FindConfig("SendAttachment"))
if !SendAttachment || err != nil {
c.JSON(200, gin.H{
"code": 400,
"msg": "禁止上传附件!",
})
return
}
f, err := c.FormFile("realfile")
if err != nil {
c.JSON(200, gin.H{
"code": 400,
"msg": "上传失败!",
})
return
} else {
maxSize := 20 * 1024 * 1024
uploadMaxSize := models.FindConfig("UploadMaxSize")
if uploadMaxSize != "" {
uploadMaxSizeInt, _ := strconv.Atoi(uploadMaxSize)
maxSize = uploadMaxSizeInt * 1024 * 1024
}
fileExt := strings.ToLower(path.Ext(f.Filename))
if f.Size >= int64(maxSize) {
c.JSON(200, gin.H{
"code": 400,
"msg": "上传失败,文件大小超限!",
})
return
}
fileName := tools.Md5(fmt.Sprintf("%s%s", f.Filename, time.Now().String()))
fildDir := fmt.Sprintf("%s%d%s/", common.Upload, time.Now().Year(), time.Now().Month().String())
isExist, _ := tools.IsFileExist(fildDir)
if !isExist {
os.Mkdir(fildDir, os.ModePerm)
}
filepath := fmt.Sprintf("%s%s%s", fildDir, fileName, fileExt)
c.SaveUploadedFile(f, filepath)
path := "/" + filepath
//上传到阿里云oss
oss, err := lib.NewOssLib()
if err == nil {
dstUrl, err := oss.Upload(filepath, filepath)
if err == nil {
path = dstUrl
}
}
c.JSON(200, gin.H{
"code": 200,
"msg": "上传成功!",
"result": gin.H{
"path": path,
},
})
}
}
func UploadAudio(c *gin.Context) {
SendAttachment, err := strconv.ParseBool(models.FindConfig("SendAttachment"))
if !SendAttachment || err != nil {
c.JSON(200, gin.H{
"code": 400,
"msg": "禁止上传附件!",
})
return
}
f, err := c.FormFile("realfile")
if err != nil {
c.JSON(200, gin.H{
"code": 400,
"msg": "上传失败!",
})
return
} else {
fileExt := ".mp3"
if f.Size >= 20*1024*1024 {
c.JSON(200, gin.H{
"code": 400,
"msg": "上传失败!不允许超过20M",
})
return
}
fileName := tools.Md5(fmt.Sprintf("%s%s", f.Filename, time.Now().String()))
fildDir := fmt.Sprintf("%s%d%s/", common.Upload, time.Now().Year(), time.Now().Month().String())
isExist, _ := tools.IsFileExist(fildDir)
if !isExist {
os.Mkdir(fildDir, os.ModePerm)
}
filepath := fmt.Sprintf("%s%s%s", fildDir, fileName, fileExt)
c.SaveUploadedFile(f, filepath)
c.JSON(200, gin.H{
"code": 200,
"msg": "上传成功!",
"result": gin.H{
"path": filepath,
},
})
}
}
func GetMessagesV2(c *gin.Context) {
visitorId := c.Query("visitor_id")
messages := models.FindMessageByVisitorId(visitorId)
//result := make([]map[string]interface{}, 0)
chatMessages := make([]ChatMessage, 0)
for _, message := range messages {
//item := make(map[string]interface{})
var chatMessage ChatMessage
chatMessage.Time = message.CreatedAt.Format("2006-01-02 15:04:05")
chatMessage.Content = message.Content
chatMessage.MesType = message.MesType
if message.MesType == "kefu" {
chatMessage.Name = message.KefuName
chatMessage.Avator = message.KefuAvator
} else {
chatMessage.Name = message.VisitorName
chatMessage.Avator = message.VisitorAvator
}
chatMessages = append(chatMessages, chatMessage)
}
c.JSON(200, gin.H{
"code": 200,
"msg": "ok",
"result": chatMessages,
})
}
func PostMessagesVisitorRead(c *gin.Context) {
visitorId := c.PostForm("visitor_id")
toId := c.PostForm("kefu")
models.ReadMessageByVisitorId(visitorId, "kefu")
msg := ws.TypeMessage{
Type: "read",
Data: ws.ClientMessage{
VisitorId: visitorId,
ToId: toId,
},
}
str2, _ := json.Marshal(msg)
ws.OneKefuMessage(toId, str2)
c.JSON(200, gin.H{
"code": 200,
"msg": "ok",
})
}
func PostMessagesKefuRead(c *gin.Context) {
visitorId := c.PostForm("visitor_id")
entId, _ := c.Get("ent_id")
kefuName, _ := c.Get("kefu_name")
models.ReadMessageByEntIdVisitorId(visitorId, entId.(string), "visitor")
msg := ws.TypeMessage{
Type: "read",
Data: ws.ClientMessage{
VisitorId: visitorId,
},
}
ws.VisitorCustomMessage(visitorId, msg)
unreadNum := models.CountMessage("kefu_id = ? and mes_type='visitor' and status = 'unread'", kefuName)
msg2 := ws.TypeMessage{
Type: "unread_num",
Data: unreadNum,
}
str, _ := json.Marshal(msg2)
ws.OneKefuMessage(kefuName.(string), str)
c.JSON(200, gin.H{
"code": 200,
"msg": "ok",
})
}
func PostMessagesAsk(c *gin.Context) {
entId := c.PostForm("ent_id")
content := c.PostForm("content")
visitorId := c.PostForm("from_id")
if content == "" {
c.JSON(200, gin.H{
"code": 400,
"msg": "内容不能为空",
})
return
}
entInfo := models.FindUserByUid(entId)
go models.CreateMessage(entInfo.Name, visitorId, content, "visitor", entId, "unread")
reply := models.FindReplyItemByUserIdTitle(entInfo.Name, content)
if reply.Content != "" {
go models.CreateMessage(entInfo.Name, visitorId, reply.Content, "kefu", entId, "read")
c.JSON(200, gin.H{
"code": 200,
"msg": "ok",
"result": gin.H{
"content": reply.Content,
"name": entInfo.Nickname,
"avator": entInfo.Avator,
"time": time.Now().Format("2006-01-02 15:05:05"),
},
})
return
}
c.JSON(200, gin.H{
"code": 400,
"msg": "no result!",
})
}
func GetMessagesVisitorUnread(c *gin.Context) {
visitorId := c.Query("visitor_id")
messages := models.FindMessageByVisitorIdUnread(visitorId, "kefu")
chatMessages := make([]ChatMessage, 0)
for _, message := range messages {
//item := make(map[string]interface{})
var chatMessage ChatMessage
chatMessage.Time = message.CreatedAt.Format("2006-01-02 15:04:05")
chatMessage.Content = message.Content
chatMessage.MesType = message.MesType
if message.MesType == "kefu" {
chatMessage.Name = message.KefuName
chatMessage.Avator = message.KefuAvator
} else {
chatMessage.Name = message.VisitorName
chatMessage.Avator = message.VisitorAvator
}
chatMessages = append(chatMessages, chatMessage)
}
c.JSON(200, gin.H{
"code": 200,
"msg": "ok",
"result": chatMessages,
})
}
func GetAllVisitorMessagesByKefu(c *gin.Context) {
visitorId := c.Query("visitor_id")
messages := models.FindMessageByVisitorId(visitorId)
//result := make([]map[string]interface{}, 0)
chatMessages := make([]ChatMessage, 0)
for _, message := range messages {
//item := make(map[string]interface{})
var chatMessage ChatMessage
chatMessage.Time = message.CreatedAt.Format("2006-01-02 15:04:05")
chatMessage.Content = message.Content
chatMessage.MesType = message.MesType
if message.MesType == "kefu" {
chatMessage.Name = message.KefuName
chatMessage.Avator = message.KefuAvator
} else {
chatMessage.Name = message.VisitorName
chatMessage.Avator = message.VisitorAvator
}
chatMessages = append(chatMessages, chatMessage)
}
c.JSON(200, gin.H{
"code": 200,
"msg": "ok",
"result": chatMessages,
})
}
func GetVisitorListMessagesPage(c *gin.Context) {
visitorId := c.Query("visitor_id")
entId := c.Query("ent_id")
page, _ := strconv.Atoi(c.Query("page"))
pagesize, _ := strconv.Atoi(c.Query("pagesize"))
if pagesize == 0 {
pagesize = int(common.PageSize)
}
count := models.CountMessage("message.ent_id= ? and message.visitor_id=?", entId, visitorId)
chatMessages := CommonMessagesPage(uint(page), uint(pagesize), visitorId, entId)
c.JSON(200, gin.H{
"code": 200,
"msg": "获取成功",
"result": gin.H{
"count": count,
"page": page,
"list": chatMessages,
"pagesize": pagesize,
},
})
}
func GetVisitorListMessagesPageBykefu(c *gin.Context) {
visitorId := c.Query("visitor_id")
entId, _ := c.Get("ent_id")
page, _ := strconv.Atoi(c.Query("page"))
pagesize, _ := strconv.Atoi(c.Query("pagesize"))
if pagesize == 0 {
pagesize = int(common.PageSize)
}
count := models.CountMessage("message.ent_id= ? and message.visitor_id=?", entId.(string), visitorId)
chatMessages := CommonMessagesPage(uint(page), uint(pagesize), visitorId, entId.(string))
go func() {
models.ReadMessageByVisitorId(visitorId, "visitor")
msg := ws.TypeMessage{
Type: "read",
Data: ws.ClientMessage{
VisitorId: visitorId,
},
}
ws.VisitorCustomMessage(visitorId, msg)
}()
c.JSON(200, gin.H{
"code": 200,
"msg": "获取成功",
"result": gin.H{
"count": count,
"page": page,
"list": chatMessages,
"pagesize": common.PageSize,
},
})
}
func DeleteMessage(c *gin.Context) {
entId, _ := c.Get("ent_id")
visitorId := c.PostForm("visitor_id")
msgId := c.PostForm("msg_id")
message := models.FindOneMessageByWhere("id=? and visitor_id=? and ent_id=?", msgId, visitorId, entId)
//判断撤回时间限制
limitTime := tools.Now() - message.CreatedAt.Unix()
systemLimitTime := models.FindConfig("KefuDeleteMessageLimitTime")
if systemLimitTime != "" && limitTime > tools.Str2Int64(systemLimitTime) {
c.JSON(200, gin.H{
"code": types.ApiCode.DELETE_MESSAGE_OVERTIME,
"msg": types.ApiCode.GetMessage(types.ApiCode.DELETE_MESSAGE_OVERTIME),
})
return
}
models.DelMessage("id=? and visitor_id=? and ent_id=?", msgId, visitorId, entId)
msgIdInt, _ := strconv.Atoi(msgId)
msg := ws.TypeMessage{
Type: "delete",
Data: ws.ClientMessage{
MsgId: uint(msgIdInt),
VisitorId: visitorId,
},
}
ws.VisitorCustomMessage(visitorId, msg)
c.JSON(200, gin.H{
"code": 200,
"msg": "ok",
})
}
// 删除访客聊天记录
func DeleteVisitorMessage(c *gin.Context) {
entId, _ := c.Get("ent_id")
visitorId := c.Query("visitor_id")
models.DelMessage("visitor_id=? and ent_id=?", visitorId, entId)
c.JSON(200, gin.H{
"code": 200,
"msg": "ok",
})
}
// 一键已读
func GetClearUnread(c *gin.Context) {
entId, _ := c.Get("ent_id")
kefuName, _ := c.Get("kefu_name")
models.ReadMessageByEntIdKefuName(entId.(string), kefuName.(string))
msg := ws.TypeMessage{
Type: "unread_num",
Data: 0,
}
str, _ := json.Marshal(msg)
go ws.OneKefuMessage(kefuName.(string), str)
c.JSON(200, gin.H{
"code": 200,
"msg": "ok",
})
}
func CommonMessagesPage(page, pagesize uint, visitorId, entId string) []ChatMessage {
list := models.FindMessageByPage(page, pagesize, "message.ent_id= ? and message.visitor_id=?", entId, visitorId)
chatMessages := make([]ChatMessage, 0)
for _, message := range list {
//item := make(map[string]interface{})
var chatMessage ChatMessage
chatMessage.MsgId = message.ID
chatMessage.Time = message.CreatedAt.Format("2006-01-02 15:04:05")
chatMessage.Content = message.Content
chatMessage.MesType = message.MesType
chatMessage.ReadStatus = message.Status
if message.MesType == "kefu" {
chatMessage.Name = message.KefuName
chatMessage.Avator = message.KefuAvator
} else {
chatMessage.Name = message.VisitorName
chatMessage.Avator = message.VisitorAvator
}
chatMessages = append(chatMessages, chatMessage)
}
return chatMessages
}
// 调用回调通知url
func SendVisitorMessageCallUrl(entId, from, to, nickname, avatar, content string) string {
api := models.FindConfig("VisitorMessageCallUrl")
if api == "" {
api = models.FindEntConfig(entId, "VisitorMessageCallUrl").ConfValue
}
if api == "" {
return ""
}
data := url.Values{}
data.Set("from", from)
data.Set("to", to)
data.Set("content", content)
data.Set("nickname", nickname)
data.Set("avatar", avatar)
res, err := tools.PostForm(api, data)
if err != nil {
log.Println("访客消息发送回调错误:" + err.Error())
}
return res
}
// 客服调用回调通知url
func SendKefuMessageCallUrl(kefuName, visitorId, content, entId, nickname string) string {
api := models.FindConfig("KefuMessageCallUrl")
if api == "" {
api = models.FindEntConfig(entId, "KefuMessageCallUrl").ConfValue
}
if api == "" {
return ""
}
data := url.Values{}
data.Set("kefu_name", kefuName)
data.Set("visitor_id", visitorId)
data.Set("ent_id", entId)
data.Set("content", content)
data.Set("nickname", nickname)
res, err := tools.PostForm(api, data)
if err != nil {
log.Println("客服消息发送回调错误:" + err.Error())
}
log.Println("客服消息发送回调成功:" + data.Encode())
return res
}