package im import ( "encoding/json" "errors" "fmt" "git.rosy.net.cn/jx-callback/business/jxutils" "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" "git.rosy.net.cn/jx-callback/globals/api" "github.com/gorilla/websocket" ) // SendToVendor 向平台发消息 func SendToVendor(msg []byte) { var ( sendData SendData err error elmAppID = api.EbaiAPI.GetSource() ) //解析数据 if err = json.Unmarshal(msg, &sendData); err != nil { return } //存储数据 ReadMsgFromClient(sendData.VendorID, elmAppID, sendData.Data) //发送信息 if sendData.VendorID == VendorIDMT { temp, _ := json.Marshal(sendData.Data) if sendData.Data.(map[string]interface{})["app_id"] == nil { globals.SugarLogger.Debug("SendToVendor appId=null") return } Send(temp, sendData.Data.(map[string]interface{})["app_id"]) } if sendData.VendorID == VendorIDELM { param := sendData.Data.(ebaiapi.BusinessSendMsgReq) if err := api.EbaiAPI.BusinessSendMsg(¶m); err != nil { globals.SugarLogger.Debugf("elm发送信息错误:%v", err) return } } //if err != nil { // ClientRender(Fail, FailMsg, map[string]string{ // "errMsg": fmt.Sprintf("%v", err), // }) // return err //} else { // ClientRender(SuccessCode, SuccessMsg, map[string]interface{}{ // "vendorID": sendData.VendorID, // "msg": "ok", // }) // return nil //} return } func Send(data []byte, appID interface{}) { //根据appID生成完整url fullUrl := GenFullUrl(appID.(float64)) //clientID暂时不用 conn, resp, err := websocket.DefaultDialer.Dial(fullUrl, nil) if err != nil || resp.StatusCode != 101 { fmt.Printf("连接失败:%v http响应不成功", err) } //关闭 defer func(conn *websocket.Conn) { err := conn.Close() if err != nil { return } }(conn) err = conn.WriteMessage(websocket.TextMessage, data) if err != nil { fmt.Println(err) } for { _, msg, err := conn.ReadMessage() temp := string(msg) if err != nil { break } else { if temp != HeartSuccessWord { ReadMsgFromVendor(VendorIDMT, "", msg) } } fmt.Printf("%s receive: %s\n", conn.RemoteAddr(), string(msg)) } return } // MtInit 发送心跳 func MtInit() { data := []byte(HeartCheckMsg) //生成完整url url := GenFullUrl2() //主连接 jxutils.CallMsgHandlerAsync(func() { conn, resp, err := websocket.DefaultDialer.Dial(url.UrlMain, nil) if err != nil || resp.StatusCode != 101 { fmt.Printf("连接失败:%v http响应不成功", err) } //关闭 defer func(conn *websocket.Conn) { err := conn.Close() if err != nil { return } }(conn) //client连接事件 client := NewClient(url.ClientIDMain, conn, ClientTypeMt) Manager.Connect <- client err = conn.WriteMessage(websocket.TextMessage, data) if err != nil { fmt.Println(err) } for { _, msg, err := conn.ReadMessage() temp := string(msg) if err != nil || temp != "HB" { break } fmt.Printf("%s receive: %s\n", conn.RemoteAddr(), string(msg)) } }, url.ClientIDMain) //副连接 if url.UrlSub != "" { jxutils.CallMsgHandlerAsync(func() { connSub, respSub, errSub := websocket.DefaultDialer.Dial(url.UrlSub, nil) if errSub != nil || respSub.StatusCode != 101 { fmt.Printf("连接失败:%v http响应不成功", errSub) } //关闭 defer func(conn *websocket.Conn) { err := conn.Close() if err != nil { return } }(connSub) //client连接事件 client := NewClient(url.ClientIDSub, connSub, ClientTypeMt) Manager.Connect <- client errSub = connSub.WriteMessage(websocket.TextMessage, data) if errSub != nil { fmt.Println(errSub) } for { _, msg, err := connSub.ReadMessage() temp := string(msg) if err != nil || temp != HeartCheckSuccess { break } fmt.Printf("%s connSub:receive: %s\n", connSub.RemoteAddr(), string(msg)) } }, url.ClientIDSub) } } // ReadMsgFromClient 存储客户端发送的消息 func ReadMsgFromClient(vendorID int, elmAppID string, msg interface{}) { var ( err error jxMsg = &JXMsg{} userList = &UserMessageList{} ) data, err := json.Marshal(msg) if err != nil { return } if vendorID == VendorIDMT { var MtSingleChat = mtwmapi.SingleChat{} err = json.Unmarshal(data, &MtSingleChat) jxMsg = &JXMsg{ SendType: SendTypeJx, MsgContent: MtSingleChat, } userList = &UserMessageList{ VendorID: VendorIDMT, UserID: utils.Int2Str(MtSingleChat.OpenUserID), LatestMsg: MtSingleChat.MsgContent, LatestTime: MtSingleChat.Cts, } } if vendorID == VendorIDELM { var ElmData = ebaiapi.ImMessageSend{} err = json.Unmarshal(data, &ElmData) jxMsg = &JXMsg{ SendType: SendTypeJx, MsgContent: ElmData, } userList = &UserMessageList{ VendorID: VendorIDMT, UserID: ElmData.PayLoad.GroupID, LatestMsg: ElmData.PayLoad.Content, LatestTime: int(ElmData.PayLoad.CreateTime), } } //1 存储详细聊天记录list if err = SetMessageDetail(jxMsg, vendorID, elmAppID); err != nil { globals.SugarLogger.Debugf("ReadMsgFromClient SetMessageDetail err:=%v\n", err) //return } //2 存储展示列表时单条数据 if err = SetUserList(jxMsg, userList, vendorID, elmAppID); err != nil { globals.SugarLogger.Debugf("ReadMsgFromClient SetUserList err:=%v\n", err) //return } } // ReadMsgFromVendor 读取数据并存储到redis func ReadMsgFromVendor(vendorID int, elmAppID string, msg []byte) { if string(msg) == "" { return } var ( err error vendorStoreID string jxMsg = &JXMsg{} userList = &UserMessageList{} ) if vendorID == VendorIDMT { var MtSingleChat = mtwmapi.SingleChat{} err = json.Unmarshal(msg, &MtSingleChat) jxMsg = &JXMsg{ SendType: SendTypeMt, MsgContent: MtSingleChat, } userList = &UserMessageList{ VendorID: VendorIDMT, UserID: utils.Int2Str(MtSingleChat.OpenUserID), LatestMsg: MtSingleChat.MsgContent, LatestTime: MtSingleChat.Cts, } vendorStoreID = MtSingleChat.AppPoiCode } if vendorID == VendorIDELM { var ElmData = ebaiapi.ImMessageSend{} err = json.Unmarshal(msg, &ElmData) jxMsg = &JXMsg{ SendType: SendTypeElm, MsgContent: ElmData, } userList = &UserMessageList{ VendorID: VendorIDMT, UserID: ElmData.PayLoad.GroupID, LatestMsg: ElmData.PayLoad.Content, LatestTime: int(ElmData.PayLoad.CreateTime), } } //1 存储详细聊天记录list if err = SetMessageDetail(jxMsg, vendorID, elmAppID); err != nil { globals.SugarLogger.Debugf("ReadMsgFromVendor SetMessageDetail err:=%v\n", err) //return } //2 存储展示列表时单条数据 if err = SetUserList(jxMsg, userList, vendorID, elmAppID); err != nil { globals.SugarLogger.Debugf("ReadMsgFromVendor SetUserList err:=%v\n", err) //return } //3 cid推送新消息 err = PushMsgByCid(vendorStoreID, vendorID) //4 长链接通知给客户端 ToClientChan <- clientInfo{Code: SuccessCode, Msg: fmt.Sprintf("%v", err), Data: jxMsg} return } // PushMsgByCid 通过cid push用户 func PushMsgByCid(vendorStoreID string, vendorID int) error { if err := push.NotifyImNewMessage(vendorStoreID, vendorID); err != nil { return err } return nil } // SetMessageDetail 赋值 //格式 AppID:AppPoiCode:10:OpenUserID func SetMessageDetail(req *JXMsg, vendorID int, elmAppID string) error { //生成京西消息ID detail msgID := GenMsgDetailID(req, vendorID, elmAppID) 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) //获取未读消息条数并删除旧数据 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) { if vendorID == VendorIDMT { var d1 = jxMsg.MsgContent.(mtwmapi.SingleChat) msgID = utils.Int2Str(d1.AppID) + ":" + d1.AppPoiCode + ":10:" + utils.Int2Str(d1.OpenUserID) } if vendorID == VendorIDELM { var d2 = jxMsg.MsgContent.(ebaiapi.ImMessageSend) msgID = elmAppID + ":" + d2.PlatformShopID + ":11:" + 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.SingleChat) msgID = utils.Int2Str(d1.AppID) + ":" + d1.AppPoiCode + ":10" } if vendorID == VendorIDELM { var d2 = jxMsg.MsgContent.(ebaiapi.ImMessageSend) msgID = elmAppID + ":" + d2.PlatformShopID + ":11" } 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 { retVal[j] = append(retVal[j], v) //暂时写死 //retVal["userList"] = append(retVal["userList"], v) } } return retVal, nil } // 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, 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 }