Files
jx-callback/business/partner/im/im.go
richboo111 32d0b41f85 1
2023-10-27 15:58:38 +08:00

482 lines
14 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 (
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"strings"
"time"
"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"`
}
// GetPoiIMStatus 查询门店IM单聊开关状态
func GetPoiIMStatus(param []GetPoiIMStatusReq) (retVal []*GetPoiIMStatusResp, err error) {
if len(param) == 0 {
return nil, nil
}
for _, v := range param {
switch v.VendorID {
case model.VendorIDMTWM:
temp, err := partner.CurAPIManager.GetAPI(model.VendorIDMTWM, v.VendorOrgCode).(*mtwmapi.API).GetPoiIMStatus(v.VendorStoreID)
if err != nil {
continue
}
retVal = append(retVal, &GetPoiIMStatusResp{
VendorID: model.VendorIDMTWM,
ImStatus: temp.ImStatus,
})
case model.VendorIDEBAI:
//status, err := api.EbaiAPI.GetStoreIMStatus(v.VendorStoreID)
status, err := partner.CurAPIManager.GetAPI(model.VendorIDEBAI, v.VendorOrgCode).(*ebaiapi.API).GetStoreIMStatus(v.VendorStoreID)
if err != nil {
continue
}
retVal = append(retVal, &GetPoiIMStatusResp{
VendorID: model.VendorIDMTWM,
ImStatus: utils.Str2Int(status),
})
}
}
return retVal, nil
}
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 存储详细聊天记录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))
}
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("读取平台数据为空,请检查"))
}
if vendorID == VendorIDMT {
var PushContentReq = mtwmapi.PushContentReq{}
err = json.Unmarshal(msg, &PushContentReq)
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)
}
}
if vendorID == 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),
}
globals.SugarLogger.Debugf("elm userList=%s", utils.Format4Output(userList, false))
}
//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))
}
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 {
//生成京西消息ID detail
msgID := GenMsgDetailID(req, vendorID, elmAppID)
data, _ := json.Marshal(req)
globals.SugarLogger.Debugf("SetMessageDetail data=%s", string(data))
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)
//获取未读消息条数并删除旧数据
cnt, err := GetNewAndTrim(msgID, userList.UserID)
if cnt > 0 {
userList.NewMessageNum = cnt
} else {
userList.NewMessageNum = 1
}
//存储当前数据
data, _ := json.Marshal(userList)
globals.SugarLogger.Debugf("SetUserList data=%s", string(data))
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) {
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 d2 = jxMsg.MsgContent.(ebaiapi.ImMessageSend)
msgID = elmAppID + ":" + d2.PlatformShopID + ":3:" + d2.PayLoad.GroupID
}
return msgID
}
// GenMsgListID 生成展示列表时单条数据ID部分
func GenMsgListID(jxMsg *JXMsg, vendorID int, elmAppID string) (msgID string) {
if vendorID == VendorIDMT {
var d1 = jxMsg.MsgContent.(mtwmapi.PushContentReq)
msgID = utils.Int2Str(d1.AppID) + ":" + d1.AppPoiCode + ":1"
}
if vendorID == VendorIDELM {
var d2 = jxMsg.MsgContent.(ebaiapi.ImMessageSend)
msgID = elmAppID + ":" + d2.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
}
// 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
}
// 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
}
// 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
}