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("

%s

", 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 }