kefu/controller/message.go

907 lines
25 KiB
Go
Raw Normal View History

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