907 lines
25 KiB
Go
907 lines
25 KiB
Go
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
|
||
}
|