Files
jx-callback/business/partner/im/im.go
邹宗楠 ad2b46b2cc 1
2025-08-01 17:27:24 +08:00

1082 lines
30 KiB
Go
Raw 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 im
import (
"crypto/rand"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"math/big"
"strings"
"time"
"git.rosy.net.cn/jx-callback/business/model/dao"
"git.rosy.net.cn/jx-callback/business/partner"
"git.rosy.net.cn/jx-callback/business/model"
"git.rosy.net.cn/baseapi/utils/errlist"
"git.rosy.net.cn/jx-callback/globals"
"git.rosy.net.cn/baseapi/platformapi/ebaiapi"
"git.rosy.net.cn/baseapi/platformapi/mtwmapi"
"git.rosy.net.cn/baseapi/utils"
push "git.rosy.net.cn/jx-callback/business/jxutils/unipush"
)
func SendVendorV2(data SendData, vendorOrgCode string) (err error) {
if data.VendorID == model.VendorIDMTWM {
dataStr, _ := json.Marshal(data.Data)
temp := string(dataStr)
globals.SugarLogger.Debugf("SendVendorV2 mtwmtemp=%s", temp)
if _, err = partner.CurAPIManager.GetAPI(model.VendorIDMTWM, vendorOrgCode).(*mtwmapi.API).MsgSend(string(dataStr)); err != nil {
return err
}
}
if data.VendorID == model.VendorIDEBAI {
str, _ := json.Marshal(data.Data)
param := &ebaiapi.BusinessSendMsgReq{}
err = json.Unmarshal(str, &param)
globals.SugarLogger.Debugf("SendVendorV2 ebaiparam=%s", utils.Format4Output(param, false))
err = partner.CurAPIManager.GetAPI(model.VendorIDEBAI, vendorOrgCode).(*ebaiapi.API).BusinessSendMsg(param)
}
err = ReadMsgFromClient(data.VendorID, vendorOrgCode, data.Data)
if err != nil {
globals.SugarLogger.Debugf("SendVendorV2:%v", err)
}
return nil
}
type GetPoiIMStatusReq struct {
VendorID int `json:"vendorID"`
VendorStoreID string `json:"vendorStoreID"`
VendorOrgCode string `json:"vendorOrgCode"`
}
type GetPoiIMStatusResp struct {
VendorID int `json:"vendorID"`
ImStatus int `json:"imStatus"`
ErrMsg string `json:"errMsg"`
}
// GetPoiIMStatus 查询门店IM单聊开关状态
func GetPoiIMStatus(param []GetPoiIMStatusReq) (retVal []*GetPoiIMStatusResp) {
var (
ans1 = &GetPoiIMStatusResp{}
ans2 = &GetPoiIMStatusResp{}
)
if len(param) == 0 {
return nil
}
for _, v := range param {
switch v.VendorID {
case model.VendorIDMTWM:
api := partner.CurAPIManager.GetAPI(model.VendorIDMTWM, v.VendorOrgCode).(*mtwmapi.API)
switch v.VendorOrgCode {
case "5873":
storeDetail, err := dao.GetStoreDetailByVendorStoreID(dao.GetDB(), v.VendorStoreID, model.VendorIDMTWM, v.VendorOrgCode)
if err != nil || storeDetail == nil {
return nil
}
api.SetToken(storeDetail.MtwmToken)
default:
}
temp, err := api.GetPoiIMStatus(v.VendorStoreID)
if err != nil {
ans1.ErrMsg = fmt.Sprintf("1:%v", err)
continue
}
ans1.VendorID = model.VendorIDMTWM
ans1.ImStatus = temp.ImStatus
case model.VendorIDEBAI:
status, err := partner.CurAPIManager.GetAPI(model.VendorIDEBAI, v.VendorOrgCode).(*ebaiapi.API).GetStoreIMStatus(v.VendorStoreID)
if err != nil {
ans1.ErrMsg = fmt.Sprintf("3:%v", err)
continue
}
ans2.VendorID = model.VendorIDEBAI
ans2.ImStatus = utils.Str2Int(status)
}
}
retVal = append(retVal, ans1, ans2)
return retVal
}
type SetPoiIMStatusReq struct {
VendorID int `json:"vendorID"`
VendorStoreID string `json:"vendorStoreID"`
VendorOrgCode string `json:"vendorOrgCode"`
ImStatus int `json:"imStatus"`
}
// SetPoiIMStatus 设置平台门店im状态
func SetPoiIMStatus(param []SetPoiIMStatusReq) error {
var errList errlist.ErrList
if len(param) == 0 {
return nil
}
for _, v := range param {
switch v.VendorID {
case model.VendorIDMTWM:
if err := partner.CurAPIManager.GetAPI(model.VendorIDMTWM, v.VendorOrgCode).(*mtwmapi.API).SetPoiIMStatus(v.VendorStoreID, v.ImStatus); err != nil {
errList.AddErr(fmt.Errorf("mtwm:%v", err))
}
case model.VendorIDEBAI:
if err := partner.CurAPIManager.GetAPI(model.VendorIDEBAI, v.VendorOrgCode).(*ebaiapi.API).UpdateIMStatus(v.VendorStoreID, v.ImStatus); err != nil {
errList.AddErr(fmt.Errorf("ebai:%v", err))
}
}
}
return errList.GetErrListAsOne()
}
// ReadMsgFromClient 存储客户端发送的消息
func ReadMsgFromClient(vendorID int, elmAppID string, msg interface{}) error {
var (
err error
elmTime int
jxMsg = &JXMsg{}
errList errlist.ErrList
userList = &UserMessageList{}
)
data, err := json.Marshal(msg)
if err != nil {
errList.AddErr(fmt.Errorf("json处理数据错误%v", err))
}
if vendorID == VendorIDMT {
var pushContent = mtwmapi.PushContentReq{}
err = json.Unmarshal(data, &pushContent)
jxMsg = &JXMsg{
SendType: SendTypeJx,
MsgContent: pushContent,
}
userList = &UserMessageList{
VendorID: VendorIDMT,
UserID: utils.Int2Str(pushContent.OpenUserID),
LatestMsg: pushContent.MsgContent,
LatestTime: pushContent.Cts,
OrderID: "",
}
if pushContent.OrderID != 0 {
userList.OrderID = utils.Int2Str(pushContent.OrderID)
}
}
if vendorID == VendorIDELM {
var ElmData = ebaiapi.ImMessageSend{}
err = json.Unmarshal(data, &ElmData)
jxMsg = &JXMsg{
SendType: SendTypeJx,
MsgContent: ElmData,
}
if ElmData.PayLoad.CreateTime == 0 {
elmTime = int(time.Now().Unix())
}
userList = &UserMessageList{
VendorID: VendorIDELM,
UserID: ElmData.PayLoad.GroupID,
LatestMsg: ElmData.PayLoad.Content,
LatestTime: elmTime,
}
}
//1 存储展示列表时单条数据
if err = SetMessageDetail(jxMsg, vendorID, elmAppID); err != nil {
errList.AddErr(fmt.Errorf("存储详细聊天记录错误:%v", err))
}
//2 存储详细聊天记录list
if err = SetUserList(jxMsg, userList, vendorID, elmAppID); err != nil {
errList.AddErr(fmt.Errorf("存储STU聊天记录错误%v", err))
}
if errList.GetErrListAsOne() != nil {
return fmt.Errorf("ReadMsgFromClient:%v", errList.GetErrListAsOne())
}
return nil
}
// ReadMsgFromVendor 读取数据并存储到redis
func ReadMsgFromVendor(vendorID int, elmAppID string, msg []byte) error {
var (
err error
jxMsg = &JXMsg{}
vendorStoreID string
errList errlist.ErrList
userList = &UserMessageList{}
)
if len(string(msg)) == 0 {
errList.AddErr(fmt.Errorf("读取平台数据为空,请检查"))
}
switch vendorID {
case VendorIDMT:
var PushContentReq = mtwmapi.PushContentReq{}
err = json.Unmarshal(msg, &PushContentReq)
if len(PushContentReq.MsgContent) != 0 || PushContentReq.MsgContent != "" {
if FilterIm(PushContentReq.AppID, PushContentReq.MsgContent) { //自动回复消息过滤
return nil
}
}
jxMsg = &JXMsg{
SendType: SendTypeMt,
MsgContent: PushContentReq,
}
userList = &UserMessageList{
VendorID: VendorIDMT,
UserID: utils.Int2Str(PushContentReq.OpenUserID),
LatestMsg: PushContentReq.MsgContent,
LatestTime: PushContentReq.Cts,
OrderID: "",
}
vendorStoreID = PushContentReq.AppPoiCode
if PushContentReq.OrderID != 0 {
userList.OrderID = utils.Int2Str(PushContentReq.OrderID)
}
case VendorIDELM:
var ElmData = ebaiapi.ImMessageSend{}
err = json.Unmarshal(msg, &ElmData)
jxMsg = &JXMsg{
SendType: SendTypeElm,
MsgContent: ElmData,
}
userList = &UserMessageList{
VendorID: VendorIDELM,
UserID: ElmData.PayLoad.GroupID,
LatestMsg: ElmData.PayLoad.Content,
LatestTime: int(ElmData.PayLoad.CreateTime / 1000),
}
}
//1 存储详细聊天记录list
if err = SetMessageDetail(jxMsg, vendorID, elmAppID); err != nil {
errList.AddErr(fmt.Errorf("存储详细聊天记录错误:%v", err))
}
//2 存储展示列表时单条数据
if err = SetUserList(jxMsg, userList, vendorID, elmAppID); err != nil {
errList.AddErr(fmt.Errorf("存储STU聊天记录错误%v", err))
}
//3 cid推送新消息
if err = PushMsgByCid(vendorStoreID, vendorID, string(msg)); err != nil {
errList.AddErr(fmt.Errorf("向商家cid推送新消息错误%v", err))
}
//4 客服自动回复
if err = CheckAndReply(jxMsg, elmAppID); err != nil {
errList.AddErr(fmt.Errorf("客服自动回复出错:%v", err))
}
//5延迟40s 自动回复
//timer := time.NewTimer(30 * time.Second)
if errList.GetErrListAsOne() != nil {
return fmt.Errorf("ReadMsgFromVendor:%v", errList.GetErrListAsOne())
}
return nil
}
// PushMsgByCid 通过cid push用户
func PushMsgByCid(vendorStoreID string, vendorID int, msg string) error {
if err := push.NotifyImNewMessage(vendorStoreID, vendorID, msg); err != nil {
return err
}
return nil
}
// SetMessageDetail 赋值
//格式 AppID:AppPoiCode:1:OpenUserID
func SetMessageDetail(req *JXMsg, vendorID int, elmAppID string) error {
if req == nil {
return nil
}
//生成京西消息ID detail
msgID := GenMsgDetailID(req, vendorID, elmAppID)
if len(msgID) == 0 {
return nil
}
data, _ := json.Marshal(req)
err := rdb.RPush(msgID, string(data))
ok, err := rdb.ExpireResult(msgID, ExpireTimeDay)
if err != nil || !ok {
return err
}
return nil
}
// SetUserList 赋值
//AppPoiCode:10 [userid1:{SingleChat},userid2:{}]
func SetUserList(jxMsg *JXMsg, userList *UserMessageList, vendorID int, elmAppID string) error {
//生成msgID
msgID := GenMsgListID(jxMsg, vendorID, elmAppID)
if len(msgID) == 0 {
return nil
}
//获取未读消息条数并删除旧数据
cnt, err := GetNewAndTrim(msgID, userList.UserID)
if cnt > 0 {
userList.NewMessageNum = cnt
} else {
userList.NewMessageNum = 1
}
//存储当前数据
data, _ := json.Marshal(userList)
err = rdb.RPush(msgID, string(data))
ok, err := rdb.ExpireResult(msgID, ExpireTimeDay)
if err != nil || !ok {
return err
}
return nil
}
// GetNewAndTrim 获取未读条数并清除旧数据
func GetNewAndTrim(key string, flag string) (cnt int, err error) {
cnt = 0
if n, err := rdb.Exists(key); n > 0 && err == nil {
s2 := rdb.LRange(key)
for i := 0; i < len(s2); i++ {
v := UserMessageList{}
_ = json.Unmarshal([]byte(s2[i]), &v)
if v.UserID == flag {
err = rdb.LSet(key, i, "del")
err = rdb.LRem(key, 0, "del")
s2 = append(s2[:i], s2[i+1:]...)
i--
if v.NewMessageNum == 0 { //目前为首条
cnt++ //赋值1
} else {
cnt = v.NewMessageNum
}
}
}
} else {
return 0, nil
}
return cnt, err
}
// GenMsgDetailID 生成查询详细聊天记录ID
func GenMsgDetailID(jxMsg *JXMsg, vendorID int, elmAppID string) (msgID string) {
//globals.SugarLogger.Debugf("GenMsgDetailID test0124 jxMsg=%s", utils.Format4Output(jxMsg, false))
if jxMsg == nil {
return ""
}
if vendorID == VendorIDMT {
var d1 = jxMsg.MsgContent.(mtwmapi.PushContentReq)
msgID = utils.Int2Str(d1.AppID) + ":" + d1.AppPoiCode + ":1:" + utils.Int2Str(d1.OpenUserID)
}
if vendorID == VendorIDELM {
var ElmData = ebaiapi.ImMessageSend{}
tempMsgContent, _ := json.Marshal(jxMsg.MsgContent)
if err := json.Unmarshal(tempMsgContent, &ElmData); err != nil {
return ""
}
//var d2 = jxMsg.MsgContent.(ebaiapi.ImMessageSend)
//msgID = elmAppID + ":" + d2.PlatformShopID + ":3:" + d2.PayLoad.GroupID
msgID = elmAppID + ":" + ElmData.PlatformShopID + ":3:" + ElmData.PayLoad.GroupID
}
return msgID
}
// GenMsgListID 生成展示列表时单条数据ID部分
func GenMsgListID(jxMsg *JXMsg, vendorID int, elmAppID string) (msgID string) {
//globals.SugarLogger.Debugf("GenMsgListID test0124 jxMsg=%s,vendorID=%d", utils.Format4Output(jxMsg, false), vendorID)
if jxMsg == nil {
return ""
}
if vendorID == VendorIDMT {
var d1 = jxMsg.MsgContent.(mtwmapi.PushContentReq)
msgID = utils.Int2Str(d1.AppID) + ":" + d1.AppPoiCode + ":1"
}
if vendorID == VendorIDELM {
var ElmData = ebaiapi.ImMessageSend{}
tempMsgContent, _ := json.Marshal(jxMsg.MsgContent)
err := json.Unmarshal(tempMsgContent, &ElmData)
fmt.Println(err)
//var d2 = jxMsg.MsgContent.(ebaiapi.ImMessageSend)
//msgID = elmAppID + ":" + d2.PlatformShopID + ":3"
msgID = elmAppID + ":" + ElmData.PlatformShopID + ":3"
}
return msgID
}
// GetImUserList 获取门店用户聊天列表
func GetImUserList(req []RelInfo) (map[string][]interface{}, error) {
retVal := make(map[string][]interface{}, 0)
if len(req) == 0 {
return nil, errors.New("msgID不允许为空")
}
var keys []string
for _, i := range req {
key := i.AppID + ":" + i.VendorStoreID + ":" + i.VendorID
keys = append(keys, key)
}
for _, j := range keys {
temp := rdb.LRange(j)
for _, v := range temp {
//过滤过期信息
if FilterUserList(v) {
retVal[j] = append(retVal[j], v)
}
}
}
return retVal, nil
}
func FilterUserList(val string) bool {
retVal := UserMessageList{}
err := json.Unmarshal([]byte(val), &retVal)
if err != nil || time.Now().Unix()-int64(retVal.LatestTime) >= 3600*6 {
return false
}
return true
}
// FilterChatDetail 去重
func FilterChatDetail(req *JXMsg, vendorID int) {
//if vendorID == VendorIDMT {
// mt := req.MsgContent.(mtwmapi.PushContentReq)
// temp, _ := GetImChatDetail([]UserRelInfo{{
// VendorStoreID: mt.AppPoiCode,
// VendorID: "1",
// AppID: utils.Int2Str(mt.AppID),
// UserID: utils.Int2Str(mt.OpenUserID),
// }})
//
//}
//
//if vendorID == VendorIDELM {
// elm := req.MsgContent.(ebaiapi.ImMessageSend)
// temp, _ := GetImChatDetail([]UserRelInfo{{
// VendorStoreID: elm.PlatformShopID,
// VendorID: "3",
// AppID: "34665",
// UserID: elm.PayLoad.SenderID,
// }})
//}
}
// GetImChatDetail 获取门店用户聊天详情
func GetImChatDetail(req []UserRelInfo) (map[string][]interface{}, error) {
retVal := make(map[string][]interface{}, 0)
if len(req) == 0 {
return nil, errors.New("msgID不允许为空")
}
var keys []string
for _, i := range req {
key := i.AppID + ":" + i.VendorStoreID + ":" + i.VendorID + ":" + i.UserID
keys = append(keys, key)
}
for _, j := range keys {
temp := rdb.LRange(j)
for _, v := range temp {
retVal[j] = append(retVal[j], v)
//retVal["chatDetail"] = append(retVal["chatDetail"], v)
}
}
return retVal, nil
}
// SetJxMsgRead 设置jx消息已读 userID(美团openUserID;饿了么groupID)
func SetJxMsgRead(appID, vendorStoreID, vendorID, userID string) error {
var (
temp = UserMessageList{}
key = appID + ":" + vendorStoreID + ":" + vendorID
)
if n, err := rdb.Exists(key); n > 0 && err == nil {
s2 := rdb.LRange(key)
for i := 0; i < len(s2); i++ {
v := UserMessageList{}
_ = json.Unmarshal([]byte(s2[i]), &v)
if v.UserID == userID {
//删除此条数据
err = rdb.LSet(key, i, "del")
err = rdb.LRem(key, 0, "del")
s2 = append(s2[:i], s2[i+1:]...)
i--
//cnt=0 重新赋值
temp = UserMessageList{
VendorID: v.VendorID,
UserID: v.UserID,
OrderID: v.OrderID,
NewMessageNum: 0,
LatestMsg: v.LatestMsg,
LatestTime: v.LatestTime,
}
}
}
str, _ := json.Marshal(temp)
err = rdb.RPush(key, str)
}
return nil
}
// AutoReply 是否已回复
//key=AppID+:+UserID+:+msgID(mt)
//key=AppID+:+UserID+:+msgID(elm)
type AutoReply struct {
UserID int `json:"userID"`
MsgID int `json:"msgID"` //消息ID
IsApply bool `json:"IsApply"` //是否已回复
Timestamp int `json:"timestamp"` //消息接收时间
}
// CheckAndReply 判断并回复V1
func CheckAndReply(req *JXMsg, elmAppID string) (err error) {
var (
key string
//keyDetail UserRelInfo
flag = false
vendorID int
errList errlist.ErrList
apply *AutoReply
jxMsg = &JXMsg{}
//userList = &UserMessageList{}
)
if req.SendType == SendTypeMt {
vendorID = VendorIDMT
mt := req.MsgContent.(mtwmapi.PushContentReq)
//跳过12小时内商家消息自动回复
if mt.MsgSource != mtwmapi.MsgSourceUser {
return nil
}
key = utils.Int2Str(mt.AppID) + ":" + utils.Int2Str(mt.OpenUserID) + ":autoReply"
keyDetailMt := UserRelInfo{
AppID: utils.Int2Str(mt.AppID),
VendorStoreID: mt.AppPoiCode,
VendorID: VendorIDMTStr,
UserID: utils.Int2Str(mt.OpenUserID),
}
//1 检测是否已自动回复
flag = GetIfReply(key, keyDetailMt)
//判断flag状态
if !flag {
apply = &AutoReply{
UserID: mt.AppID,
MsgID: mt.MsgID,
IsApply: true,
Timestamp: mt.Cts,
}
temp := mt
//获取自定义回复模板
if template := GetCustomTemplate(utils.Int2Str(mt.AppID), mt.AppPoiCode); len(template.Template) > 0 {
// 关闭自动回复
if template.Template == "3ASOkN9WiU3AUae2tYGChA==" {
return nil
}
temp.MsgContent = template.Template
} else {
temp.MsgContent, err = GetDefaultTemplate(utils.Int2Str(mt.AppID), mt.AppPoiCode, VendorIDMT)
if err != nil {
temp.MsgContent = AutoReplyByAppID[mt.AppID]
}
}
temp.MsgType = mtwmapi.MsgTypeText
temp.MsgSource = mtwmapi.MsgSourceStore
temp.Cts = int(time.Now().Unix())
temp.MsgID = RandTimeNumber()
dataStr, _ := json.Marshal(temp)
if _, err = partner.CurAPIManager.GetAPI(model.VendorIDMTWM, utils.Int2Str(mt.AppID)).(*mtwmapi.API).MsgSend(string(dataStr)); err != nil {
apply.IsApply = false
globals.SugarLogger.Debugf("CheckAndReply mtSend err:%v", err)
} else {
jxMsg = &JXMsg{
SendType: SendTypeJx,
MsgContent: temp,
}
// 存储详细聊天记录
if err = SetMessageDetail(jxMsg, vendorID, elmAppID); err != nil {
errList.AddErr(fmt.Errorf("自动回复:存储详细聊天记录错误:%v", err))
}
}
//3 记录自动回复状态
if err = RecordAutoStatus(key, apply); err != nil {
errList.AddErr(fmt.Errorf("自动回复:记录自动回复状态错误:%v", err))
}
}
}
if req.SendType == SendTypeElm {
vendorID = VendorIDELM
elm := req.MsgContent.(ebaiapi.ImMessageSend)
key = elmAppID + ":" + elm.PayLoad.SenderID + ":autoReply"
if elm.PayLoad.SenderID == "" || elm.PayLoad.SenderID[:2] != ebaiapi.SenderTypeUser {
return nil
}
keyDetailElm := UserRelInfo{
AppID: elmAppID,
VendorStoreID: elm.PlatformShopID,
VendorID: VendorIDELMStr,
UserID: elm.PayLoad.GroupID,
}
//1 检测是否已自动回复
flag = GetIfReply(key, keyDetailElm)
if !flag {
apply = &AutoReply{
UserID: utils.Str2Int(elm.PayLoad.SenderID),
MsgID: utils.Str2Int(elm.PayLoad.MsgID),
IsApply: true,
Timestamp: elm.PayLoad.CreateTime,
}
param := &ebaiapi.BusinessSendMsgReq{
PlatformShopId: elm.PlatformShopID,
BizType: ebaiapi.IMType,
SubBizType: ebaiapi.IMTypeSendMsg,
PayLoad: ebaiapi.BusinessMsgPayload{
GroupId: elm.PayLoad.GroupID,
MsgId: utils.Int2Str(RandTimeNumber()),
ReceiverIds: elm.PayLoad.ReceiverIDs,
ContentType: utils.Int2Str(ebaiapi.ContentTypeNormal),
},
}
temp := ""
if template := GetCustomTemplate(elmAppID, elm.PlatformShopID); len(template.Template) > 0 {
temp = template.Template
} else {
temp, err = GetDefaultTemplate(elmAppID, elm.PlatformShopID, VendorIDELM)
if err != nil {
temp = LastTemplate
}
}
tempStr, _ := json.Marshal(temp)
tempContent := ebaiapi.Content{
Text: string(tempStr),
//Text: temp,
}
tempContentStr, _ := json.Marshal(tempContent)
param.PayLoad.Content = string(tempContentStr)
if err = partner.CurAPIManager.GetAPI(model.VendorIDEBAI, elmAppID).(*ebaiapi.API).BusinessSendMsg(param); err != nil {
apply.IsApply = false
globals.SugarLogger.Debugf("CheckAndReply mtSend err:%v", err)
} else {
jxMsg = &JXMsg{
SendType: SendTypeJx,
MsgContent: param,
}
//存储详细聊天记录list
if err = SetMessageDetail(jxMsg, vendorID, elmAppID); err != nil {
errList.AddErr(fmt.Errorf("自动回复:存储详细聊天记录错误:%v", err))
}
}
//3 记录自动回复状态
if err = RecordAutoStatus(key, apply); err != nil {
errList.AddErr(fmt.Errorf("自动回复:记录自动回复状态错误:%v", err))
}
}
}
if errList.GetErrListAsOne() != nil {
return fmt.Errorf("CheckAndReply err=%v", errList.GetErrListAsOne())
}
return nil
}
// CheckAndReplyV2 判断并回复V2 延迟35s
//func CheckAndReplyV2(req *JXMsg, elmAppID string) (err error) {
// var (
// key string
// vendorID int
// errList errlist.ErrList
// jxMsg = &JXMsg{}
// )
//
// if req.SendType == SendTypeMt {
// vendorID = VendorIDMT
// mt := req.MsgContent.(mtwmapi.PushContentReq)
// //获取聊天详情
// imDetail, err := GetImChatDetail([]UserRelInfo{{
// VendorStoreID: mt.AppPoiCode,
// VendorID: VendorIDMTStr,
// AppID: utils.Int2Str(mt.AppID),
// UserID: utils.Int2Str(mt.OpenUserID),
// }})
// if err != nil {
// return err
// }
// if len(imDetail) > 0 {
// //获取此消息列表最后一条数据
// key = GenMsgDetailID(req, VendorIDMT, elmAppID)
// temp := imDetail[key][len(imDetail)-1]
// tStr, _ := json.Marshal(temp)
//
// lastMsg := &JXMsg{}
// err = json.Unmarshal(tStr, lastMsg)
// if err != nil {
// return err
// }
// //京西发送或美团商家发送 跳过
// if lastMsg.SendType == SendTypeJx {
// return nil
// }
//
// lastMt := lastMsg.MsgContent.(mtwmapi.PushContentReq)
// if lastMt.MsgSource == mtwmapi.MsgSourceStore {
// return nil
// }
//
// //生成回复消息体
// sendMt := mt
// //获取自定义回复模板
// if template := GetCustomTemplate(utils.Int2Str(mt.AppID), mt.AppPoiCode); len(template) > 0 {
// sendMt.MsgContent = template
// } else {
// sendMt.MsgContent, err = GetDefaultTemplate(utils.Int2Str(mt.AppID), mt.AppPoiCode, VendorIDMT)
// if err != nil {
// sendMt.MsgContent = AutoReplyByAppID[mt.AppID]
// }
// }
// sendMt.MsgType = mtwmapi.MsgTypeText
// sendMt.MsgSource = mtwmapi.MsgSourceStore
// sendMt.Cts = int(time.Now().Unix())
// sendMt.MsgID = RandTimeNumber()
//
// //向美团发送消息
// dataStr, _ := json.Marshal(sendMt)
// if _, err = partner.CurAPIManager.GetAPI(model.VendorIDMTWM, utils.Int2Str(mt.AppID)).(*mtwmapi.API).MsgSend(string(dataStr)); err != nil {
// globals.SugarLogger.Debugf("CheckAndReply mtSend err:%v", err)
// return err
// } else {
// jxMsg = &JXMsg{
// SendType: SendTypeJx,
// MsgContent: temp,
// }
// if err = SetMessageDetail(jxMsg, vendorID, elmAppID); err != nil {
// errList.AddErr(fmt.Errorf("自动回复V2存储详细聊天记录错误%v", err))
// }
// }
// }
// }
//
// if req.SendType == SendTypeElm {
// vendorID = VendorIDELM
// elm := req.MsgContent.(ebaiapi.ImMessageSend)
// imDetail, err := GetImChatDetail([]UserRelInfo{{
// VendorStoreID: elm.PlatformShopID,
// VendorID: VendorIDELMStr,
// AppID: elmAppID,
// UserID: elm.PayLoad.SenderID,
// }})
// if err != nil {
// return err
// }
// if len(imDetail) > 0 {
// //获取此消息列表最后一条数据
// key = GenMsgDetailID(req, VendorIDELM, elmAppID)
// temp := imDetail[key][len(imDetail)-1]
// tStr, _ := json.Marshal(temp)
//
// lastMsg := &JXMsg{}
// err = json.Unmarshal(tStr, lastMsg)
// if err != nil {
// return err
// }
// //京西发送或美团商家发送 跳过
// if lastMsg.SendType == SendTypeJx {
// return nil
// }
//
// //结构不一样后解
// lastElm := lastMsg.MsgContent.(ebaiapi.ImMessageSend)
// if lastElm.PayLoad.SenderID == "" || elm.PayLoad.SenderID[:2] != ebaiapi.SenderTypeUser {
// return nil
// }
//
// param := &ebaiapi.BusinessSendMsgReq{
// PlatformShopId: elm.PlatformShopID,
// BizType: ebaiapi.IMType,
// SubBizType: ebaiapi.IMTypeSendMsg,
// PayLoad: ebaiapi.BusinessMsgPayload{
// GroupId: elm.PayLoad.GroupID,
// MsgId: utils.Int2Str(RandTimeNumber()),
// ReceiverIds: elm.PayLoad.ReceiverIDs,
// ContentType: utils.Int2Str(ebaiapi.ContentTypeNormal),
// },
// }
//
// data := ""
// if template := GetCustomTemplate(elmAppID, elm.PlatformShopID); len(template) > 0 {
// data = template
// } else {
// data, err = GetDefaultTemplate(elmAppID, elm.PlatformShopID, VendorIDELM)
// if err != nil {
// data = LastTemplate
// }
// }
// dataStr, _ := json.Marshal(data)
// tempContent := ebaiapi.Content{
// Text: string(dataStr),
// }
// tempContentStr, _ := json.Marshal(tempContent)
// param.PayLoad.Content = string(tempContentStr)
//
// if err = partner.CurAPIManager.GetAPI(model.VendorIDEBAI, elmAppID).(*ebaiapi.API).BusinessSendMsg(param); err != nil {
// globals.SugarLogger.Debugf("CheckAndReply mtSend err:%v", err)
// return err
// } else {
// jxMsg = &JXMsg{
// SendType: SendTypeJx,
// MsgContent: param,
// }
// if err = SetMessageDetail(jxMsg, vendorID, elmAppID); err != nil {
// errList.AddErr(fmt.Errorf("自动回复V2存储详细聊天记录错误%v", err))
// }
// }
//
// }
//
// }
//
// if errList.GetErrListAsOne() != nil {
// return fmt.Errorf("CheckAndReplyV2 err=%v", errList.GetErrListAsOne())
// }
//
// return nil
//}
// GetIfReply 检查是否已回复
// 美团只需要第一条消息在一分钟之内回复就达标了,后面不需要自动回复了
func GetIfReply(key string, keyDetail UserRelInfo) (flag bool) {
flag = false
if n, err := rdb.Exists(key); n > 0 && err == nil {
str := rdb.LRange(key)
for i := 0; i < len(str); i++ {
v := AutoReply{}
if err = json.Unmarshal([]byte(str[i]), &v); err == nil {
flag = v.IsApply
}
}
}
//检测是否商家回复
var param []UserRelInfo
temp := append(param, keyDetail)
detail, err := GetImChatDetail(temp)
if err == nil && detail != nil {
tKey := keyDetail.AppID + ":" + keyDetail.VendorStoreID + ":" + keyDetail.VendorID + ":" + keyDetail.UserID
if detail[tKey] != nil {
for _, v := range detail[tKey] {
b := v.(string)
lastMsg := &JXMsg{}
err = json.Unmarshal([]byte(b), lastMsg)
if err != nil {
return false
}
switch keyDetail.VendorID {
case VendorIDMTStr:
mt := lastMsg.MsgContent.(map[string]interface{})
if mt["msg_source"].(float64) == mtwmapi.MsgSourceStore {
return true
}
case VendorIDELMStr:
elm := lastMsg.MsgContent.(map[string]interface{})
s := ""
if elm["payLoad"].(map[string]interface{})["senderId"] != nil {
s = elm["payLoad"].(map[string]interface{})["senderId"].(string)
}
if s == "" || s[:2] == ebaiapi.SenderTypeBusiness || s[:2] == ebaiapi.SenderTypeChainedAccountLogin || s[:2] == ebaiapi.SenderTypeSystem {
return true
}
}
}
//tDetail := detail[tKey][len(detail[tKey])-1]
//b := tDetail.(string)
//lastMsg := &JXMsg{}
//err = json.Unmarshal([]byte(b), lastMsg)
//if err != nil || lastMsg.SendType == SendTypeJx {
// return false
//}
//switch keyDetail.VendorID {
//case VendorIDMTStr:
// mt := lastMsg.MsgContent.(map[string]interface{})
// if mt["msg_source"].(float64) != mtwmapi.MsgSourceUser {
// return false
// }
//case VendorIDELMStr:
// elm := lastMsg.MsgContent.(map[string]interface{})
// s := elm["payLoad"].(map[string]interface{})["senderId"].(string)
// if s == "" || s[:2] != ebaiapi.SenderTypeUser {
// return false
// }
//}
}
}
return flag
}
// RecordAutoStatus 记录是否已自动回复状态
func RecordAutoStatus(key string, apply *AutoReply) error {
data, _ := json.Marshal(apply)
err := rdb.RPush(key, string(data))
ok, err := rdb.ExpireResult(key, ExpireTimeAutoReply)
if err != nil || !ok {
globals.SugarLogger.Debugf("CheckAndReply apply err:%v", err)
return err
}
return nil
}
// GenCustomReplyID 生成门店自动回复模板ID
func GenCustomReplyID(appID, vendorStoreID string) string {
return BaseCusKey + ":" + appID + ":" + vendorStoreID
}
// GetCustomTemplate 获取自动回复模板
func GetCustomTemplate(appID, vendorStoreID string) (storeTemplate StoreTemplate) {
var retVal string
key := GenCustomReplyID(appID, vendorStoreID)
data := rdb.LRange(key)
if data != nil {
retVal = data[0]
}
//temp := rdb.Get(key)
//temp := regexp.MustCompile(`^"(.*)"$`).ReplaceAllString(retVal, `$1`)
//storeTemplate = strings.Trim(retVal, "/")
//fmt.Println(temp)
temp := StoreTemplate{}
_ = json.Unmarshal([]byte(retVal), &temp)
storeTemplate = temp
return storeTemplate
}
// AddCustomReply 增加门店自定义回复模板
func AddCustomReply(appID, vendorStoreID, replyTemplate string) (storeTemplate string, err error) {
if len(appID) == 0 || len(vendorStoreID) == 0 {
return "", errors.New("参数错误请检查!")
}
key := GenCustomReplyID(appID, vendorStoreID)
template := StoreTemplate{
Template: replyTemplate,
}
data, _ := json.Marshal(template)
err = rdb.Del(key)
if err == nil && replyTemplate != "" {
err = rdb.RPush(key, data)
//err = rdb.Set(key, replyTemplate, 0)
}
return "", err
}
// GetDefaultTemplate 获取门店默认回复模板
func GetDefaultTemplate(appID, vendorStoreID string, vendorID int) (string, error) {
var (
phoneNum = " "
t string
)
store, err := dao.GetStoreDetailByVendorStoreID(dao.GetDB(), vendorStoreID, vendorID, "")
if err != nil {
return "", err
}
//if err != nil && err == orm.ErrNoRows {
// t = BasePhoneNum
//}
if len(store.Tel1) > 0 {
t = store.Tel1
}
phoneNum = t[:3] + "-" + t[3:7] + "-" + t[7:]
temp := BaseTemplate + phoneNum
if vendorID == VendorIDMT {
data, err := EncryptIm(utils.Str2Int(appID), temp)
if err != nil {
return "", err
}
return data, nil
}
if vendorID == VendorIDELM {
return temp, nil
}
return "", nil
}
/************************工具函数*/
// DelRedisByKey 清除redis数据
func DelRedisByKey(keys []string) {
var errList errlist.ErrList
for _, key := range keys {
err := rdb.Del(key)
if err != nil {
errList.AddErr(err)
}
}
if errList.GetErrListAsOne() != nil {
globals.SugarLogger.Debugf("DelRedisByKey err=%v", errList.GetErrListAsOne())
}
return
}
var rel = map[int]string{
589: "a81eb3df418d83d6a1a4b7c572156d2f",
5873: "41c479790a76f86326f89e8048964739",
4123: "df2c88338b85f830cebce2a9eab56628",
}
// DecryptIm 解密操作
func DecryptIm(appID int, msg string) (string, error) {
data, _ := base64.StdEncoding.DecodeString(msg)
key := utils.LimitUTF8StringLen2(rel[appID], 16)
res, err := utils.AESCBCDecpryt(data, []byte(key), []byte(key))
if len(string(res)) > 0 && err == nil {
return string(res), nil
}
return "", err
}
// EncryptIm 加密操作
func EncryptIm(appID int, msg string) (retVal string, err error) {
key := utils.LimitUTF8StringLen2(rel[appID], 16)
if data, err := utils.AESCBCEncpryt([]byte(msg), []byte(key), []byte(key)); err == nil {
retVal = base64.StdEncoding.EncodeToString(data)
}
return retVal, err
}
// FilterIm 过滤操作
func FilterIm(appID int, msg string) bool {
var check = "[自动回复]"
data, _ := DecryptIm(appID, msg)
if len(data) > 0 && strings.Contains(data, check) {
return true
}
return false
}
// RandTimeNumber 生成int类型 随机数+时间戳
func RandTimeNumber() int {
num, _ := rand.Int(rand.Reader, big.NewInt(100000))
str := utils.Int64ToStr(num.Int64()) + utils.Int2Str(int(time.Now().Unix()))
return utils.Str2Int(str)
}