shop-live/static/js/webim_wx.js

6044 lines
245 KiB
JavaScript
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.

var reqSeq = 0,reqNum = 0;
module.exports = function() {
/* webim javascript SDK
* VER 1.7.0
*/
/* webim API definitions
*/
var msgCache = {};
var webim = { // namespace object webim
/* function init
* sdk登录
* params:
* loginInfo - Object, 登录身份相关参数集合,详见下面
* {
* sdkAppID - String, 用户标识接入SDK的应用ID必填
* accountType - int, 账号类型,必填
* identifier - String, 用户帐号,必须是字符串类型,必填
* identifierNick - String, 用户昵称,选填
* userSig - String, 鉴权Token必须是字符串类型必填
* }
* listeners - Object, 事件回调函数集合, 详见下面
* {
* onConnNotify - function(connInfo), 用于收到连接状态相关通知的回调函数,目前未使用
* jsonpCallback -function(rspData),//IE9(含)以下浏览器用到的jsonp回调函数
* onMsgNotify - function(newMsgList), 用于收到消息通知的回调函数,
* newMsgList为新消息数组格式为[Msg对象]
* 使用方有两种处理回调: 1)处理newMsgList中的增量消息,2)直接访问webim.MsgStore获取最新的消息
* onGroupInfoChangeNotify - function(groupInfo), 用于监听群组资料变更的回调函数,
* groupInfo为新的群组资料信息
* onGroupSystemNotifys - Object, 用于监听(多终端同步)群系统消息的回调函数对象
*
* }
* options - Object, 其它选项, 目前未使用
* return:
* (无)
*/
login: function (loginInfo, listeners, options) {
},
/* function syncMsgs
* 拉取最新C2C消息
* 一般不需要使用方直接调用, SDK底层会自动同步最新消息并通知使用方, 一种有用的调用场景是用户手动触发刷新消息
* params:
* cbOk - function(msgList)类型, 当同步消息成功时的回调函数, msgList为新消息数组格式为[Msg对象],
* 如果此参数为null或undefined则同步消息成功后会像自动同步那样回调cbNotify
* cbErr - function(err)类型, 当同步消息失败时的回调函数, err为错误对象
* return:
* (无)
*/
syncMsgs: function (cbOk, cbErr) {
},
/* function getC2CHistoryMsgs
* 拉取C2C漫游消息
* params:
* options - 请求参数
* cbOk - function(msgList)类型, 成功时的回调函数, msgList为消息数组格式为[Msg对象],
* cbErr - function(err)类型, 失败时回调函数, err为错误对象
* return:
* (无)
*/
getC2CHistoryMsgs: function (options, cbOk, cbErr) {
},
/* function syncGroupMsgs
* 拉取群漫游消息
* params:
* options - 请求参数
* cbOk - function(msgList)类型, 成功时的回调函数, msgList为消息数组格式为[Msg对象],
* cbErr - function(err)类型, 失败时回调函数, err为错误对象
* return:
* (无)
*/
syncGroupMsgs: function (options, cbOk, cbErr) {
},
/* function sendMsg
* 发送一条消息
* params:
* msg - webim.Msg类型, 要发送的消息对象
* cbOk - function()类型, 当发送消息成功时的回调函数
* cbErr - function(err)类型, 当发送消息失败时的回调函数, err为错误对象
* return:
* (无)
*/
sendMsg: function (msg, cbOk, cbErr) {
},
/* function logout
* sdk登出
* params:
* cbOk - function()类型, 成功时回调函数
* cbErr - function(err)类型, 失败时回调函数, err为错误对象
* return:
* (无)
*/
logout: function (cbOk, cbErr) {
},
/* function setAutoRead
* 设置会话自动已读上报标志
* params:
* selSess - webim.Session类型, 当前会话
* isOn - boolean, 将selSess的自动已读消息标志改为isOn同时是否上报当前会话已读消息
* isResetAll - boolean是否重置所有会话的自动已读标志
* return:
* (无)
*/
setAutoRead: function (selSess, isOn, isResetAll) {
},
/* function getProfilePortrait
* 拉取资料(搜索用户)
* params:
* cbOk - function()类型, 成功时回调函数
* cbErr - function(err)类型, 失败时回调函数, err为错误对象
* return:
* (无)
*/
getProfilePortrait: function (options, cbOk, cbErr) {
},
/* function setProfilePortrait
* 设置个人资料
* params:
* cbOk - function()类型, 成功时回调函数
* cbErr - function(err)类型, 失败时回调函数, err为错误对象
* return:
* (无)
*/
setProfilePortrait: function (options, cbOk, cbErr) {
},
/* function applyAddFriend
* 申请添加好友
* params:
* cbOk - function()类型, 成功时回调函数
* cbErr - function(err)类型, 失败时回调函数, err为错误对象
* return:
* (无)
*/
applyAddFriend: function (options, cbOk, cbErr) {
},
/* function getPendency
* 拉取好友申请
* params:
* cbOk - function()类型, 成功时回调函数
* cbErr - function(err)类型, 失败时回调函数, err为错误对象
* return:
* (无)
*/
getPendency: function (options, cbOk, cbErr) {
},
/* function deletePendency
* 删除好友申请
* params:
* cbOk - function()类型, 成功时回调函数
* cbErr - function(err)类型, 失败时回调函数, err为错误对象
* return:
* (无)
*/
deletePendency: function (options, cbOk, cbErr) {
},
/* function responseFriend
* 响应好友申请
* params:
* cbOk - function()类型, 成功时回调函数
* cbErr - function(err)类型, 失败时回调函数, err为错误对象
* return:
* (无)
*/
responseFriend: function (options, cbOk, cbErr) {
},
/* function getAllFriend
* 拉取我的好友
* params:
* cbOk - function()类型, 成功时回调函数
* cbErr - function(err)类型, 失败时回调函数, err为错误对象
* return:
* (无)
*/
getAllFriend: function (options, cbOk, cbErr) {
},
/* function deleteFriend
* 删除好友
* params:
* cbOk - function()类型, 成功时回调函数
* cbErr - function(err)类型, 失败时回调函数, err为错误对象
* return:
* (无)
*/
deleteFriend: function (options, cbOk, cbErr) {
},
/* function addBlackList
* 增加黑名单
* params:
* cbOk - function()类型, 成功时回调函数
* cbErr - function(err)类型, 失败时回调函数, err为错误对象
* return:
* (无)
*/
addBlackList: function (options, cbOk, cbErr) {
},
/* function getBlackList
* 删除黑名单
* params:
* cbOk - function()类型, 成功时回调函数
* cbErr - function(err)类型, 失败时回调函数, err为错误对象
* return:
* (无)
*/
getBlackList: function (options, cbOk, cbErr) {
},
/* function deleteBlackList
* 我的黑名单
* params:
* cbOk - function()类型, 成功时回调函数
* cbErr - function(err)类型, 失败时回调函数, err为错误对象
* return:
* (无)
*/
deleteBlackList: function (options, cbOk, cbErr) {
},
/* function uploadPic
* 上传图片
* params:
* options - 请求参数详见api文档
* cbOk - function()类型, 成功时回调函数
* cbErr - function(err)类型, 失败时回调函数, err为错误对象
* return:
* (无)
*/
uploadPic: function (options, cbOk, cbErr) {
},
/* function createGroup
* 创建群
* params:
* options - 请求参数详见api文档
* cbOk - function()类型, 成功时回调函数
* cbErr - function(err)类型, 失败时回调函数, err为错误对象
* return:
* (无)
*/
createGroup: function (options, cbOk, cbErr) {
},
/* function applyJoinGroup
* 申请加群
* params:
* options - 请求参数详见api文档
* cbOk - function()类型, 成功时回调函数
* cbErr - function(err)类型, 失败时回调函数, err为错误对象
* return:
* (无)
*/
applyJoinGroup: function (options, cbOk, cbErr) {
},
/* function handleApplyJoinGroup
* 处理申请加群(同意或拒绝)
* params:
* options - 请求参数详见api文档
* cbOk - function()类型, 成功时回调函数
* cbErr - function(err)类型, 失败时回调函数, err为错误对象
* return:
* (无)
*/
handleApplyJoinGroup: function (options, cbOk, cbErr) {
},
/* function deleteApplyJoinGroupPendency
* 删除加群申请
* params:
* options - 请求参数详见api文档
* cbOk - function()类型, 成功时回调函数
* cbErr - function(err)类型, 失败时回调函数, err为错误对象
* return:
* (无)
*/
deleteApplyJoinGroupPendency: function (options, cbOk, cbErr) {
},
/* function quitGroup
* 主动退群
* params:
* options - 请求参数详见api文档
* cbOk - function()类型, 成功时回调函数
* cbErr - function(err)类型, 失败时回调函数, err为错误对象
* return:
* (无)
*/
quitGroup: function (options, cbOk, cbErr) {
},
/* function getGroupPublicInfo
* 读取群公开资料-高级接口
* params:
* options - 请求参数详见api文档
* cbOk - function()类型, 成功时回调函数
* cbErr - function(err)类型, 失败时回调函数, err为错误对象
* return:
* (无)
*/
getGroupPublicInfo: function (options, cbOk, cbErr) {
},
/* function getGroupInfo
* 读取群详细资料-高级接口
* params:
* options - 请求参数详见api文档
* cbOk - function()类型, 成功时回调函数
* cbErr - function(err)类型, 失败时回调函数, err为错误对象
* return:
* (无)
*/
getGroupInfo: function (options, cbOk, cbErr) {
},
/* function modifyGroupBaseInfo
* 修改群基本资料
* params:
* options - 请求参数详见api文档
* cbOk - function()类型, 成功时回调函数
* cbErr - function(err)类型, 失败时回调函数, err为错误对象
* return:
* (无)
*/
modifyGroupBaseInfo: function (options, cbOk, cbErr) {
},
/* function destroyGroup
* 解散群
* params:
* options - 请求参数详见api文档
* cbOk - function()类型, 成功时回调函数
* cbErr - function(err)类型, 失败时回调函数, err为错误对象
* return:
* (无)
*/
destroyGroup: function (options, cbOk, cbErr) {
},
/* function getJoinedGroupListHigh
* 获取我的群组-高级接口
* params:
* options - 请求参数详见api文档
* cbOk - function()类型, 成功时回调函数
* cbErr - function(err)类型, 失败时回调函数, err为错误对象
* return:
* (无)
*/
getJoinedGroupListHigh: function (options, cbOk, cbErr) {
},
/* function getGroupMemberInfo
* 获取群组成员列表
* params:
* options - 请求参数详见api文档
* cbOk - function()类型, 成功时回调函数
* cbErr - function(err)类型, 失败时回调函数, err为错误对象
* return:
* (无)
*/
getGroupMemberInfo: function (options, cbOk, cbErr) {
},
/* function addGroupMember
* 邀请好友加群
* params:
* options - 请求参数详见api文档
* cbOk - function()类型, 成功时回调函数
* cbErr - function(err)类型, 失败时回调函数, err为错误对象
* return:
* (无)
*/
addGroupMember: function (options, cbOk, cbErr) {
},
/* function modifyGroupMember
* 修改群成员资料(角色或者群消息提类型示)
* params:
* options - 请求参数详见api文档
* cbOk - function()类型, 成功时回调函数
* cbErr - function(err)类型, 失败时回调函数, err为错误对象
* return:
* (无)
*/
modifyGroupMember: function (options, cbOk, cbErr) {
},
/* function forbidSendMsg
* 设置群成员禁言时间
* params:
* options - 请求参数详见api文档
* cbOk - function()类型, 成功时回调函数
* cbErr - function(err)类型, 失败时回调函数, err为错误对象
* return:
* (无)
*/
forbidSendMsg: function (options, cbOk, cbErr) {
},
/* function deleteGroupMember
* 删除群成员
* params:
* options - 请求参数详见api文档
* cbOk - function()类型, 成功时回调函数
* cbErr - function(err)类型, 失败时回调函数, err为错误对象
* return:
* (无)
*/
deleteGroupMember: function (options, cbOk, cbErr) {
},
/* function sendCustomGroupNotify
* 发送自定义群通知
* params:
* options - 请求参数详见api文档
* cbOk - function()类型, 成功时回调函数
* cbErr - function(err)类型, 失败时回调函数, err为错误对象
* return:
* (无)
*/
sendCustomGroupNotify: function (options, cbOk, cbErr) {
},
/* class webim.Msg
* 一条消息的描述类, 消息发送、接收的API中都会涉及此类型的对象
* properties:
* sess - Session object-ref, 消息所属的会话(e.g:我与好友A的C2C会话我与群组G的GROUP会话)
* isSend - Boolean, true表示是我发出消息, false表示是发给我的消息)
* seq - Integer, 消息序列号, 用于判断消息是否同一条
* random - Integer, 消息随机数,用于判断消息是否同一条
* time - Integer, 消息时间戳, 为unix timestamp
* fromAccount -String, 消息发送者帐号
* subType -Integer, 消息子类型c2c消息时0-表示普通消息群消息时0-普通消息1-点赞消息2-提示消息
* fromAccountNick -String, 消息发送者昵称
* elems - Array of webim.Msg.Elem, 描述消息内容的元素列表
* constructor:
* Msg(sess, isSend, seq,random time,fromAccount) - 构造函数, 参数定义同上面properties中定义
* methods:
* addText(text) - 向elems中添加一个TEXT元素
* addFace(face) - 向elems中添加一个FACE元素
* toHtml() - 转成可展示的html String
*addFace
* sub-class webim.Msg.Elem
* 消息中一个组成元素的描述类, 一条消息的内容被抽象描述为N个元素的有序列表
* properties:
* type - 元素类型, 目前有TEXT(文本)、FACE(表情)、IMAGE(图片)等
* content- 元素内容体, 当TEXT时为String, 当PIC时为UrlString
* constructor:
* Elem(type, content) - 构造函数, 参数定义同上面properties中定义
*
* sub-class webim.Msg.Elem.TextElem
* 文本
* properties:
* text - String 内容
* constructor:
* TextElem(text) - 构造函数, 参数定义同上面properties中定义
*
* sub-class webim.Msg.Elem.FaceElem
* 表情
* properties:
* index - Integer 表情索引, 用户自定义
* data - String 额外数据,用户自定义
* constructor:
* FaceElem(index,data) - 构造函数, 参数定义同上面properties中定义
*
*
*/
Msg: function (sess, isSend, seq, random, time, fromAccount, subType, fromAccountNick) {/*Class constructor*/
},
/* singleton object MsgStore
* webim.MsgStore是消息数据的Model对象(参考MVC概念), 它提供接口访问当前存储的会话和消息数据
* 下面说明下会话数据类型: Session
*
* class Session
* 一个Session对象描述一个会话会话可简单理解为最近会话列表的一个条目它由两个字段唯一标识:
* type - String, 会话类型(如"C2C", "GROUP", ...)
* id - String, 会话ID(如C2C类型中为对方帐号,"C2C"时为好友ID,"GROUP"时为群ID)
* properties:
* (Session对象未对外暴露任何属性字段, 所有访问通过下面的getter方法进行)
* methods:
* type() - String, 返回会话类型,"C2C"表示与好友私聊,"GROUP"表示群聊
* id() - String, 返回会话ID
* name() - String, 返回会话标题(如C2C类型中为对方的昵称,暂不支持)
* icon() - String, 返回会话图标(对C2C类型中为对方的头像URL暂不支持)
* unread() - Integer, 返回会话未读条数
* time() - Integer, 返回会话最后活跃时间, 为unix timestamp
* curMaxMsgSeq() - Integer, 返回会话最大消息序列号
* msgCount() - Integer, 返回会话中所有消息条数
* msg(index) - webim.Msg, 返回会话中第index条消息
*/
MsgStore: {
/* function sessMap
* 获取所有会话
* return:
* 所有会话对象
*/
sessMap: function () {
return {/*Object*/};
},
/* function sessCount
* 获取当前会话的个数
* return:
* Integer, 会话个数
*/
sessCount: function () {
return 0;
},
/* function sessByTypeId
* 根据会话类型和会话ID取得相应会话
* params:
* type - String, 会话类型(如"C2C", "GROUP", ...)
* id - String, 会话ID(如对方ID)
* return:
* Session, 会话对象(说明见上面)
*/
sessByTypeId: function (type, id) {
return {/*Session Object*/};
},
/* function delSessByTypeId
* 根据会话类型和会话ID删除相应会话
* params:
* type - String, 会话类型(如"C2C", "GROUP", ...)
* id - String, 会话ID(如对方ID)
* return:
* Boolean, 布尔类型
*/
delSessByTypeId: function (type, id) {
return true;
},
/* function resetCookieAndSyncFlag
* 重置上一次读取新c2c消息Cookie和是否继续拉取标记
* return:
*
*/
resetCookieAndSyncFlag: function () {
},
downloadMap: {}
}
};
/* webim API implementation
*/
(function (webim) {
//sdk版本
var SDK = {
'VERSION': '1.7.0',//sdk版本号
'APPID': '537048168'//web im sdk 版本 APPID
};
//是否启用正式环境,默认启用
var isAccessFormaEnvironment = true;
// var isAccessFormaEnvironment = false;
//后台接口主机
var SRV_HOST = {
'FORMAL': {
'COMMON': 'https://webim.tim.qq.com',
'PIC': 'https://pic.tim.qq.com'
},
'TEST': {
'COMMON': 'https://test.tim.qq.com',
'PIC': 'https://pic.tim.qq.com'
}
};
//浏览器版本信息
var BROWSER_INFO = {};
//是否为ie9以下
var lowerBR = false;
//服务名称
var SRV_NAME = {
'OPEN_IM': 'openim',//私聊拉取未读c2c消息长轮询c2c消息已读上报等服务名
'GROUP': 'group_open_http_svc',//群组管理(拉取群消息,创建群,群成员管理,群消息已读上报等)服务名
'FRIEND': 'sns',//关系链管理(好友管理,黑名单管理等)服务名
'PROFILE': 'profile',//资料管理(查询,设置个人资料等)服务名
'RECENT_CONTACT': 'recentcontact',//最近联系人服务名
'PIC': 'openpic',//图片(或文件)服务名
'BIG_GROUP': 'group_open_http_noauth_svc',//直播大群 群组管理(申请加大群)服务名
'BIG_GROUP_LONG_POLLING': 'group_open_long_polling_http_noauth_svc',//直播大群 长轮询(拉取消息等)服务名
'IM_OPEN_STAT': 'imopenstat'//质量上报,统计接口错误率
};
//不同服务对应的版本号
var SRV_NAME_VER = {
'openim': 'v4',
'group_open_http_svc': 'v4',
'sns': 'v4',
'profile': 'v4',
'recentcontact': 'v4',
'openpic': 'v4',
'group_open_http_noauth_svc': 'v1',
'group_open_long_polling_http_noauth_svc': 'v1',
'imopenstat': 'v4'
};
//不同的命令名对应的上报类型ID用于接口质量上报
var CMD_EVENT_ID_MAP = {
'login': 1,//登录
'pic_up': 3,//上传图片
'apply_join_group': 9,//申请加入群组
'create_group': 10,//创建群组
'longpolling': 18,//普通长轮询
'send_group_msg': 19,//群聊
'sendmsg': 20//私聊
};
//聊天类型
var SESSION_TYPE = {
'C2C': 'C2C',//私聊
'GROUP': 'GROUP'//群聊
};
//最近联系人类型
var RECENT_CONTACT_TYPE = {
'C2C': 1,//好友
'GROUP': 2//群
};
//消息最大长度(字节)
var MSG_MAX_LENGTH = {
'C2C': 12000,//私聊消息
'GROUP': 8898//群聊
};
//后台接口返回类型
var ACTION_STATUS = {
'OK': 'OK',//成功
'FAIL': 'FAIL'//失败
};
var ERROR_CODE_CUSTOM = 99999;//自定义后台接口返回错误码
//消息元素类型
var MSG_ELEMENT_TYPE = {
'TEXT': 'TIMTextElem',//文本
'FACE': 'TIMFaceElem',//表情
'IMAGE': 'TIMImageElem',//图片
'CUSTOM': 'TIMCustomElem',//自定义
'SOUND': 'TIMSoundElem',//语音,只支持显示
'FILE': 'TIMFileElem',//文件,只支持显示
'LOCATION': 'TIMLocationElem',//地理位置
'GROUP_TIP': 'TIMGroupTipElem'//群提示消息,只支持显示
};
//图片类型
var IMAGE_TYPE = {
'ORIGIN': 1,//原图
'LARGE': 2,//缩略大图
'SMALL': 3//缩略小图
};
//上传资源包类型
var UPLOAD_RES_PKG_FLAG = {
'RAW_DATA': 0,//原始数据
'BASE64_DATA': 1//base64编码数据
};
//下载文件配置
var DOWNLOAD_FILE = {
'BUSSINESS_ID': '10001',//下载文件业务ID
'AUTH_KEY': '617574686b6579',//下载文件authkey
'SERVER_IP': '182.140.186.147'//下载文件服务器IP
};
//下载文件类型
var DOWNLOAD_FILE_TYPE = {
"SOUND": 2106,//语音
"FILE": 2107//普通文件
};
//上传资源类型
var UPLOAD_RES_TYPE = {
"IMAGE": 1,//图片
"FILE": 2,//文件
"SHORT_VIDEO": 3,//短视频
"SOUND": 4//语音PTT
};
//版本号,用于上传图片或文件接口
var VERSION_INFO = {
'APP_VERSION': '2.1',//应用版本号
'SERVER_VERSION': 1//服务端版本号
};
//长轮询消息类型
var LONG_POLLINNG_EVENT_TYPE = {
"C2C": 1//新的c2c消息通知
,"GROUP_COMMON": 3//新的群普通消息
,"GROUP_TIP": 4//新的群提示消息
,"GROUP_SYSTEM": 5//新的群系统消息
,"GROUP_TIP2": 6//新的群提示消息2
,"FRIEND_NOTICE": 7//好友系统通知
,"PROFILE_NOTICE": 8//资料系统通知
,"C2C_COMMON": 9//新的C2C消息
,"C2C_EVENT": 10
};
//c2c消息子类型
var C2C_MSG_SUB_TYPE = {
"COMMON": 0//普通消息
};
//c2c消息子类型
var C2C_EVENT_SUB_TYPE = {
"READED": 92//已读消息同步
};
//群消息子类型
var GROUP_MSG_SUB_TYPE = {
"COMMON": 0,//普通消息
"LOVEMSG": 1,//点赞消息
"TIP": 2,//提示消息
"REDPACKET": 3//红包消息
};
//群消息优先级类型
var GROUP_MSG_PRIORITY_TYPE = {
"REDPACKET": 1,//红包消息
"COMMON": 2,//普通消息
"LOVEMSG": 3//点赞消息
};
//群提示消息类型
var GROUP_TIP_TYPE = {
"JOIN": 1,//加入群组
"QUIT": 2,//退出群组
"KICK": 3,//被踢出群组
"SET_ADMIN": 4,//被设置为管理员
"CANCEL_ADMIN": 5,//被取消管理员
"MODIFY_GROUP_INFO": 6,//修改群资料
"MODIFY_MEMBER_INFO": 7//修改群成员信息
};
//群提示消息-群资料变更类型
var GROUP_TIP_MODIFY_GROUP_INFO_TYPE = {
"FACE_URL": 1,//修改群头像URL
"NAME": 2,//修改群名称
"OWNER": 3,//修改群主
"NOTIFICATION": 4,//修改群公告
"INTRODUCTION": 5//修改群简介
};
//群系统消息类型
var GROUP_SYSTEM_TYPE = {
"JOIN_GROUP_REQUEST": 1,//申请加群请求(只有管理员会收到)
"JOIN_GROUP_ACCEPT": 2,//申请加群被同意(只有申请人能够收到)
"JOIN_GROUP_REFUSE": 3,//申请加群被拒绝(只有申请人能够收到)
"KICK": 4,//被管理员踢出群(只有被踢者接收到)
"DESTORY": 5,//群被解散(全员接收)
"CREATE": 6,//创建群(创建者接收, 不展示)
"INVITED_JOIN_GROUP_REQUEST": 7,//邀请加群(被邀请者接收)
"QUIT": 8,//主动退群(主动退出者接收, 不展示)
"SET_ADMIN": 9,//设置管理员(被设置者接收)
"CANCEL_ADMIN": 10,//取消管理员(被取消者接收)
"REVOKE": 11,//群已被回收(全员接收, 不展示)
"READED": 15,//群消息已读同步
"CUSTOM": 255//用户自定义通知(默认全员接收)
};
//好友系统通知子类型
var FRIEND_NOTICE_TYPE = {
"FRIEND_ADD": 1,//好友表增加
"FRIEND_DELETE": 2,//好友表删除
"PENDENCY_ADD": 3,//未决增加
"PENDENCY_DELETE": 4,//未决删除
"BLACK_LIST_ADD": 5,//黑名单增加
"BLACK_LIST_DELETE": 6,//黑名单删除
"PENDENCY_REPORT": 7,//未决已读上报
"FRIEND_UPDATE": 8//好友数据更新
};
//资料系统通知子类型
var PROFILE_NOTICE_TYPE = {
"PROFILE_MODIFY": 1//资料修改
};
//腾讯登录服务错误码(用于托管模式)
var TLS_ERROR_CODE = {
'OK': 0,//成功
'SIGNATURE_EXPIRATION': 11//用户身份凭证过期
};
//长轮询连接状态
var CONNECTION_STATUS = {
'INIT': -1,//初始化
'ON': 0,//连接正常
'RECONNECT': 1,//连接恢复正常
'OFF': 9999//连接已断开,可能是用户网络问题,或者长轮询接口报错引起的
};
var UPLOAD_PIC_BUSSINESS_TYPE = {//图片业务类型
'GROUP_MSG': 1,//私聊图片
'C2C_MSG': 2,//群聊图片
'USER_HEAD': 3,//用户头像
'GROUP_HEAD': 4//群头像
};
var FRIEND_WRITE_MSG_ACTION = {//好友输入消息状态
'ING': 14,//正在输入
'STOP': 15//停止输入
};
//ajax默认超时时间单位毫秒
var ajaxDefaultTimeOut = 15000;
//大群长轮询接口返回正常时,延时一定时间再发起下一次请求
var OK_DELAY_TIME = 1000;
//大群长轮询接口发生错误时,延时一定时间再发起下一次请求
var ERROR_DELAY_TIME = 5000;
//群提示消息最多显示人数
var GROUP_TIP_MAX_USER_COUNT = 10;
//长轮询连接状态
var curLongPollingStatus = CONNECTION_STATUS.INIT;
//当长轮询连接断开后,是否已经回调过
var longPollingOffCallbackFlag = false;
//当前长轮询返回错误次数
var curLongPollingRetErrorCount = 0;
//长轮询默认超时时间,单位:毫秒
var longPollingDefaultTimeOut = 60000;
//长轮询返回错误次数达到一定值后,发起新的长轮询请求间隔时间,单位:毫秒
var longPollingIntervalTime = 5000;
//没有新消息时长轮询返回60008错误码是正常的
var longPollingTimeOutErrorCode = 60008;
//多实例登录被kick的错误码
var longPollingKickedErrorCode = 91101;
var LongPollingId = null;
//当前大群长轮询返回错误次数
var curBigGroupLongPollingRetErrorCount = 0;
//最大允许长轮询返回错误次数
var LONG_POLLING_MAX_RET_ERROR_COUNT = 10;
//上传重试累计
var Upload_Retry_Times = 0;
//最大上传重试
var Upload_Retry_Max_Times = 20;
//ie7/8/9采用jsonp方法解决ajax跨域限制
var jsonpRequestId = 0;//jsonp请求id
//最新jsonp请求返回的json数据
var jsonpLastRspData = null;
//兼容ie7/8/9,jsonp回调函数
var jsonpCallback = null;
var uploadResultIframeId = 0;//用于上传图片的iframe id
var ipList = [];//文件下载地址
var authkey = null;//文件下载票据
var expireTime = null;//文件下载票据超时时间
//错误码
var ERROR = {};
//当前登录用户
var ctx = {
sdkAppID: null,
appIDAt3rd: null,
accountType: null,
identifier: null,
tinyid: null,
identifierNick: null,
userSig: null,
a2: null,
contentType: 'json',
apn: 1
};
var opt = {};
var xmlHttpObjSeq = 0;//ajax请求id
var xmlHttpObjMap = {};//发起的ajax请求
var curSeq = 0;//消息seq
var tempC2CMsgList = [];//新c2c消息临时缓存
var tempC2CHistoryMsgList = [];//漫游c2c消息临时缓存
var maxApiReportItemCount = 20;//一次最多上报条数
var apiReportItems = [];//暂存api接口质量上报数据
var Resources = {
downloadMap : {}
};
//表情标识字符和索引映射关系对象,用户可以自定义
var emotionDataIndexs = {
"[惊讶]": 0,
"[撇嘴]": 1,
"[色]": 2,
"[发呆]": 3,
"[得意]": 4,
"[流泪]": 5,
"[害羞]": 6,
"[闭嘴]": 7,
"[睡]": 8,
"[大哭]": 9,
"[尴尬]": 10,
"[发怒]": 11,
"[调皮]": 12,
"[龇牙]": 13,
"[微笑]": 14,
"[难过]": 15,
"[酷]": 16,
"[冷汗]": 17,
"[抓狂]": 18,
"[吐]": 19,
"[偷笑]": 20,
"[可爱]": 21,
"[白眼]": 22,
"[傲慢]": 23,
"[饿]": 24,
"[困]": 25,
"[惊恐]": 26,
"[流汗]": 27,
"[憨笑]": 28,
"[大兵]": 29,
"[奋斗]": 30,
"[咒骂]": 31,
"[疑问]": 32,
"[嘘]": 33,
"[晕]": 34
};
//表情对象,用户可以自定义
var emotions = { };
//工具类
var tool = new function () {
//格式化时间戳
//format格式如下
//yyyy-MM-dd hh:mm:ss 年月日时分秒(默认格式)
//yyyy-MM-dd 年月日
//hh:mm:ss 时分秒
this.formatTimeStamp = function (timestamp, format) {
if (!timestamp) {
return 0;
}
var formatTime;
format = format || 'yyyy-MM-dd hh:mm:ss';
var date = new Date(timestamp * 1000);
var o = {
"M+": date.getMonth() + 1, //月份
"d+": date.getDate(), //日
"h+": date.getHours(), //小时
"m+": date.getMinutes(), //分
"s+": date.getSeconds() //秒
};
if (/(y+)/.test(format)) {
formatTime = format.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
} else {
formatTime = format;
}
for (var k in o) {
if (new RegExp("(" + k + ")").test(formatTime))
formatTime = formatTime.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
}
return formatTime;
};
//根据群类型英文名转换成中文名
this.groupTypeEn2Ch = function (type_en) {
var type_ch = null;
switch (type_en) {
case 'Public':
type_ch = '公开群';
break;
case 'ChatRoom':
type_ch = '聊天室';
break;
case 'Private':
type_ch = '讨论组';
break;
case 'AVChatRoom':
type_ch = '直播聊天室';
break;
default:
type_ch = type_en;
break;
}
return type_ch;
};
//根据群类型中文名转换成英文名
this.groupTypeCh2En = function (type_ch) {
var type_en = null;
switch (type_ch) {
case '公开群':
type_en = 'Public';
break;
case '聊天室':
type_en = 'ChatRoom';
break;
case '讨论组':
type_en = 'Private';
break;
case '直播聊天室':
type_en = 'AVChatRoom';
break;
default:
type_en = type_ch;
break;
}
return type_en;
};
//根据群身份英文名转换成群身份中文名
this.groupRoleEn2Ch = function (role_en) {
var role_ch = null;
switch (role_en) {
case 'Member':
role_ch = '成员';
break;
case 'Admin':
role_ch = '管理员';
break;
case 'Owner':
role_ch = '群主';
break;
default:
role_ch = role_en;
break;
}
return role_ch;
};
//根据群身份中文名转换成群身份英文名
this.groupRoleCh2En = function (role_ch) {
var role_en = null;
switch (role_ch) {
case '成员':
role_en = 'Member';
break;
case '管理员':
role_en = 'Admin';
break;
case '群主':
role_en = 'Owner';
break;
default:
role_en = role_ch;
break;
}
return role_en;
};
//根据群消息提示类型英文转换中文
this.groupMsgFlagEn2Ch = function (msg_flag_en) {
var msg_flag_ch = null;
switch (msg_flag_en) {
case 'AcceptAndNotify':
msg_flag_ch = '接收并提示';
break;
case 'AcceptNotNotify':
msg_flag_ch = '接收不提示';
break;
case 'Discard':
msg_flag_ch = '屏蔽';
break;
default:
msg_flag_ch = msg_flag_en;
break;
}
return msg_flag_ch;
};
//根据群消息提示类型中文名转换英文名
this.groupMsgFlagCh2En = function (msg_flag_ch) {
var msg_flag_en = null;
switch (msg_flag_ch) {
case '接收并提示':
msg_flag_en = 'AcceptAndNotify';
break;
case '接收不提示':
msg_flag_en = 'AcceptNotNotify';
break;
case '屏蔽':
msg_flag_en = 'Discard';
break;
default:
msg_flag_en = msg_flag_ch;
break;
}
return msg_flag_en;
};
//将空格和换行符转换成HTML标签
this.formatText2Html = function (text) {
var html = text;
if (html) {
html = this.xssFilter(html);//用户昵称或群名称等字段会出现脚本字符串
html = html.replace(/ /g, " ");
html = html.replace(/\n/g, "<br/>");
}
return html;
};
//将HTML标签转换成空格和换行符
this.formatHtml2Text = function (html) {
var text = html;
if (text) {
text = text.replace(/&nbsp;/g, " ");
text = text.replace(/<br\/>/g, "\n");
}
return text;
};
//获取字符串(UTF-8编码)所占字节数
//参考http://zh.wikipedia.org/zh-cn/UTF-8
this.getStrBytes = function (str) {
if (str == null || str === undefined) return 0;
if (typeof str != "string") {
return 0;
}
var total = 0, charCode, i, len;
for (i = 0, len = str.length; i < len; i++) {
charCode = str.charCodeAt(i);
if (charCode <= 0x007f) {
total += 1;//字符代码在000000 00007F之间的用一个字节编码
} else if (charCode <= 0x07ff) {
total += 2;//000080 0007FF之间的字符用两个字节
} else if (charCode <= 0xffff) {
total += 3;//000800 00D7FF 和 00E000 00FFFF之间的用三个字节注: Unicode在范围 D800-DFFF 中不存在任何字符
} else {
total += 4;//010000 10FFFF之间的用4个字节
}
}
return total;
};
//防止XSS攻击
this.xssFilter = function (val) {
val = val.toString();
val = val.replace(/[<]/g, "&lt;");
val = val.replace(/[>]/g, "&gt;");
val = val.replace(/"/g, "&quot;");
//val = val.replace(/'/g, "&#039;");
return val;
};
//去掉头尾空白符
this.trimStr = function (str) {
if (!str) return '';
str = str.toString();
return str.replace(/(^\s*)|(\s*$)/g, "");
};
//判断是否为8位整数
this.validNumber = function (str) {
str = str.toString();
return str.match(/(^\d{1,8}$)/g);
};
this.getReturnError = function (errorInfo, errorCode) {
if (!errorCode) {
errorCode = -100;
}
var error = {
'ActionStatus': ACTION_STATUS.FAIL,
'ErrorCode': errorCode,
'ErrorInfo': errorInfo + "[" + errorCode + "]"
};
return error;
};
//设置cookie
//name 名字
//value 值
//expires 有效期(单位:秒)
//path
//domain 作用域
this.setCookie = function (name, value, expires, path, domain) {
var exp = new Date();
exp.setTime(exp.getTime() + expires * 1000);
document.cookie = name + "=" + escape(value) + ";expires=" + exp.toGMTString();
};
//获取cookie
this.getCookie = function (name) {
var result = document.cookie.match(new RegExp("(^| )" + name + "=([^;]*)(;|$)"));
if (result != null) {
return unescape(result[2]);
}
return null;
};
//删除cookie
this.delCookie = function (name) {
var exp = new Date();
exp.setTime(exp.getTime() - 1);
var value = this.getCookie(name);
if (value != null)
document.cookie = name + "=" + escape(value) + ";expires=" + exp.toGMTString();
};
//根据名字获取url参数值
this.getQueryString = function (name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
var r = location.search.substr(1).match(reg);
if (r != null) return unescape(r[2]);
return null;
};
};
//日志对象
var log = new function () {
var on = true;
this.setOn = function (onFlag) {
on = onFlag;
};
this.getOn = function () {
return on;
};
this.error = function (logStr) {
try {
on && console.error(logStr);
} catch (e) {
}
};
this.warn = function (logStr) {
try {
on && console.warn(logStr);
} catch (e) {
}
};
this.info = function (logStr) {
try {
on && console.info(logStr);
} catch (e) {
}
};
this.debug = function (logStr) {
try {
on && console.debug(logStr);
} catch (e) {
}
};
};
//获取unix时间戳
var unixtime = function (d) {
if (!d) d = new Date();
return Math.round(d.getTime() / 1000);
};
//时间戳转日期
var fromunixtime = function (t) {
return new Date(t * 1000);
};
//获取下一个消息序号
var nextSeq = function () {
if (curSeq) {
curSeq = curSeq + 1;
} else {
curSeq = Math.round(Math.random() * 10000000);
}
return curSeq;
};
//产生随机数
var createRandom = function () {
return Math.round(Math.random() * 4294967296);
};
//发起ajax请求
var ajaxRequest = function (meth, url, req, timeout, isLongPolling, cbOk, cbErr) {
reqSeq++;
reqNum++;
// console.log('IM reqNum: ',reqNum);
xmlHttpObjMap[xmlHttpObjSeq++] = uni.request({
url : url + "&reqSeq="+reqSeq,
data : req,
dataType : 'json',
method : meth,
header: {
'Content-Type': 'application/json'
},
success : function(res){
reqNum--;
// console.log('IM complete reqNum: ',reqNum);
curLongPollingRetErrorCount = curBigGroupLongPollingRetErrorCount = 0;
if (cbOk) cbOk(res.data);
},
fail : function(res){
reqNum--;
// console.log('IM complete reqNum: ',reqNum);
setTimeout(function(){
// console.log('IM请求服务器失败:'+reqSeq,url,req,res);
var errInfo = "请求服务器失败,请检查你的网络是否正常";
var error = tool.getReturnError(errInfo, -2);
//if (!isLongPolling && cbErr) cbErr(error);
if (cbErr) cbErr(error);
},16);
}
});
}
//发起ajax请求json格式数据
var ajaxRequestJson = function (meth, url, req, timeout, isLongPolling, cbOk, cbErr) {
ajaxRequest(meth, url, JSON.stringify(req), timeout, isLongPolling, function (resp) {
var json = null;
//if (resp) eval('json=('+resp+');');//将返回的json字符串转换成json对象
//if (resp) json=eval('('+resp+')');//将返回的json字符串转换成json对象
if (resp) json = resp; //将返回的json字符串转换成json对象
if (cbOk) cbOk(json);
}, cbErr);
}
//判断用户是否已登录
var isLogin = function () {
return ctx.sdkAppID && ctx.identifier;
};
//检查是否登录
var checkLogin = function (cbErr, isNeedCallBack) {
if (!isLogin()) {
if (isNeedCallBack) {
var errInfo = "请登录";
var error = tool.getReturnError(errInfo, -4);
if (cbErr) cbErr(error);
}
return false;
}
return true;
};
//检查是否访问正式环境
var isAccessFormalEnv = function () {
return isAccessFormaEnvironment;
};
//根据不同的服务名和命令,获取对应的接口地址
var getApiUrl = function (srvName, cmd, cbOk, cbErr) {
var srvHost = SRV_HOST;
if (isAccessFormalEnv()) {
srvHost = SRV_HOST.FORMAL.COMMON;
} else {
srvHost = SRV_HOST.TEST.COMMON;
}
//if (srvName == SRV_NAME.RECENT_CONTACT) {
// srvHost = SRV_HOST.TEST.COMMON;
//}
if (srvName == SRV_NAME.PIC) {
if (isAccessFormalEnv()) {
srvHost = SRV_HOST.FORMAL.PIC;
} else {
srvHost = SRV_HOST.TEST.PIC;
}
}
var url = srvHost + '/' + SRV_NAME_VER[srvName] + '/' + srvName + '/' + cmd + '?websdkappid=' + SDK.APPID + "&v=" + SDK.VERSION;
if (isLogin()) {
if (cmd == 'login') {
url += '&identifier=' + encodeURIComponent(ctx.identifier) + '&usersig=' + ctx.userSig;
} else {
if (ctx.tinyid && ctx.a2) {
url += '&tinyid=' + ctx.tinyid + '&a2=' + ctx.a2;
} else {
if (cbErr) {
log.error("tinyid或a2为空[" + srvName + "][" + cmd + "]");
cbErr(tool.getReturnError("tinyid或a2为空[" + srvName + "][" + cmd + "]", -5));
return false;
}
}
}
url += '&contenttype=' + ctx.contentType;
}
url += '&sdkappid=' + ctx.sdkAppID + '&accounttype=' + ctx.accountType + '&apn=' + ctx.apn + '&reqtime=' + unixtime();
return url;
};
//获取语音下载url
var getSoundDownUrl = function (uuid, senderId) {
var soundUrl = null;
if (authkey && ipList[0]) {
soundUrl = "http://" + ipList[0] + "/asn.com/stddownload_common_file?authkey=" + authkey + "&bid=" + DOWNLOAD_FILE.BUSSINESS_ID + "&subbid=" + ctx.sdkAppID + "&fileid=" + uuid + "&filetype=" + DOWNLOAD_FILE_TYPE.SOUND + "&openid=" + senderId + "&ver=0";
} else {
log.error("拼接语音下载url不报错ip或者authkey为空");
}
return soundUrl;
};
//获取文件下载地址
var getFileDownUrl = function (uuid, senderId, fileName) {
var fileUrl = null;
if (authkey && ipList[0]) {
fileUrl = "http://" + ipList[0] + "/asn.com/stddownload_common_file?authkey=" + authkey + "&bid=" + DOWNLOAD_FILE.BUSSINESS_ID + "&subbid=" + ctx.sdkAppID + "&fileid=" + uuid + "&filetype=" + DOWNLOAD_FILE_TYPE.FILE + "&openid=" + senderId + "&ver=0&filename=" + encodeURIComponent(fileName);
} else {
log.error("拼接文件下载url不报错ip或者authkey为空");
}
Resources.downloadMap["uuid_"+uuid] = fileUrl;
return fileUrl;
};
//获取文件下载地址
var getFileDownUrlV2 = function (uuid, senderId, fileName, downFlag, receiverId, busiId, type) {
var options = {
"From_Account": senderId,//"identifer_0", // 类型: String, 发送者tinyid
"To_Account": receiverId,//"identifer_1", // 类型: String, 接收者tinyid
"os_platform": 10, // 类型: Number, 终端的类型 1(android) 2(ios) 3(windows) 10(others...)
"Timestamp": unixtime().toString(), // 类型: Number, 时间戳
"Random": createRandom().toString(), // 类型: Number, 随机值
"request_info": [ // 类型: Array
{
"busi_id": busiId, // 类型: Number, 群(1) C2C(2) 其他请联系sdk开发者分配
"download_flag": downFlag, // 类型: Number, 申请下载地址标识 0(申请架平下载地址) 1(申请COS平台下载地址) 2(不需要申请, 直接拿url下载(这里应该不会为2))
"type": type, // 类型: Number, 0(短视频缩略图), 1(文件), 2(短视频), 3(ptt), 其他待分配
"uuid": uuid, // 类型: Number, 唯一标识一个文件的uuid
"version": VERSION_INFO.SERVER_VERSION, // 类型: Number, 架平server版本
"auth_key": authkey, // 类型: String, 认证签名
"ip": ipList[0] // 类型: Number, 架平IP
}
]
};
//获取下载地址
proto_applyDownload(options,function(resp){
if(resp.error_code == 0 && resp.response_info){
Resources.downloadMap["uuid_"+options.uuid] = resp.response_info.url;
}
if(onAppliedDownloadUrl){
onAppliedDownloadUrl({
uuid : options.uuid,
url : resp.response_info.url,
maps : Resources.downloadMap
});
}
}, function(resp){
log.error("获取下载地址失败",options.uuid)
});
};
//重置ajax请求
var clearXmlHttpObjMap = function () {
//遍历xmlHttpObjMap{}
for (var seq in xmlHttpObjMap) {
var xmlHttpObj = xmlHttpObjMap[seq];
if (xmlHttpObj) {
xmlHttpObj.abort();//中断ajax请求(长轮询)
xmlHttpObjMap[xmlHttpObjSeq] = null;//清空
}
}
xmlHttpObjSeq = 0;
xmlHttpObjMap = {};
};
//重置sdk全局变量
var clearSdk = function () {
clearXmlHttpObjMap();
//当前登录用户
ctx = {
sdkAppID: null,
appIDAt3rd: null,
accountType: null,
identifier: null,
identifierNick: null,
userSig: null,
contentType: 'json',
apn: 1
};
opt = {};
curSeq = 0;
//ie8,9采用jsonp方法解决ajax跨域限制
jsonpRequestId = 0;//jsonp请求id
//最新jsonp请求返回的json数据
jsonpLastRspData = null;
apiReportItems = [];
MsgManager.clear();
//重置longpollingId
LongPollingId = null;
};
//登录
var _login = function (loginInfo, listeners, options, cbOk, cbErr) {
clearSdk();
if (options) opt = options;
if (opt.isAccessFormalEnv == false) {
log.error("请切换为正式环境");
isAccessFormaEnvironment = opt.isAccessFormalEnv;
}
if (opt.isLogOn == false) {
log.setOn(opt.isLogOn);
}
/*
if(opt.emotions){
emotions=opt.emotions;
webim.Emotions= emotions;
}
if(opt.emotionDataIndexs){
emotionDataIndexs=opt.emotionDataIndexs;
webim.EmotionDataIndexs= emotionDataIndexs;
}*/
if (!loginInfo) {
if (cbErr) {
cbErr(tool.getReturnError("loginInfo is empty", -6));
return;
}
}
if (!loginInfo.sdkAppID) {
if (cbErr) {
cbErr(tool.getReturnError("loginInfo.sdkAppID is empty", -7));
return;
}
}
if (!loginInfo.accountType) {
if (cbErr) {
cbErr(tool.getReturnError("loginInfo.accountType is empty", -8));
return;
}
}
if (loginInfo.identifier) {
ctx.identifier = loginInfo.identifier.toString();
}
if (loginInfo.identifier && !loginInfo.userSig) {
if (cbErr) {
cbErr(tool.getReturnError("loginInfo.userSig is empty", -9));
return;
}
}
if (loginInfo.userSig) {
ctx.userSig = loginInfo.userSig.toString();
}
ctx.sdkAppID = loginInfo.sdkAppID;
ctx.accountType = loginInfo.accountType;
if (ctx.identifier && ctx.userSig) {//带登录态
//登录
proto_login(
function(identifierNick, headurl) {
MsgManager.init(
listeners,
function (mmInitResp) {
if (cbOk) {
mmInitResp.identifierNick = identifierNick;
mmInitResp.headurl = headurl;
cbOk(mmInitResp);
}
}, cbErr
);
},
cbErr
);
} else {//不带登录态进入直播场景sdk
MsgManager.init(
listeners,
cbOk,
cbErr
);
}
};
//初始化浏览器信息
var initBrowserInfo = function () {
//初始化浏览器类型
BROWSER_INFO = "wechat"
};
//接口质量上报
var reportApiQuality = function (cmd, errorCode, errorInfo) {
if (cmd == 'longpolling' && (errorCode == longPollingTimeOutErrorCode || errorCode == longPollingKickedErrorCode)) {//longpolling 返回60008错误可以视为正常,可以不上报
return;
}
var eventId = CMD_EVENT_ID_MAP[cmd];
if (eventId) {
var reportTime = unixtime();
var uniqKey = null;
var msgCmdErrorCode = {
'Code': errorCode,
'ErrMsg': errorInfo
};
if (ctx.a2) {
uniqKey = ctx.a2.substring(0, 10) + "_" + reportTime + "_" + createRandom();
} else if (ctx.userSig) {
uniqKey = ctx.userSig.substring(0, 10) + "_" + reportTime + "_" + createRandom();
}
if (uniqKey) {
var rptEvtItem = {
"UniqKey": uniqKey,
"EventId": eventId,
"ReportTime": reportTime,
"MsgCmdErrorCode": msgCmdErrorCode
};
if (cmd == 'login') {
var loginApiReportItems = [];
loginApiReportItems.push(rptEvtItem);
var loginReportOpt = {
"EvtItems": loginApiReportItems,
"MainVersion": SDK.VERSION,
"Version": "0"
};
proto_reportApiQuality(loginReportOpt,
function (resp) {
loginApiReportItems = null;//
},
function (err) {
loginApiReportItems = null;//
}
);
} else {
apiReportItems.push(rptEvtItem);
if (apiReportItems.length >= maxApiReportItemCount) {//累计一定条数再上报
var reportOpt = {
"EvtItems": apiReportItems,
"MainVersion": SDK.VERSION,
"Version": "0"
};
proto_reportApiQuality(reportOpt,
function (resp) {
apiReportItems = [];//清空
},
function (err) {
apiReportItems = [];//清空
}
);
}
}
}
}
};
// REST API calls
//上线
var proto_login = function (cbOk, cbErr) {
ConnManager.apiCall(SRV_NAME.OPEN_IM, "login", {"State": "Online"},
function (loginResp) {
if (loginResp.TinyId) {
ctx.tinyid = loginResp.TinyId;
} else {
if (cbErr) {
cbErr(tool.getReturnError("TinyId is empty", -10));
return;
}
}
if (loginResp.A2Key) {
ctx.a2 = loginResp.A2Key;
} else {
if (cbErr) {
cbErr(tool.getReturnError("A2Key is empty", -11));
return;
}
}
var tag_list = [
"Tag_Profile_IM_Nick",
"Tag_Profile_IM_Image"
];
var options = {
'From_Account': ctx.identifier,
'To_Account': [ctx.identifier],
'LastStandardSequence': 0,
'TagList': tag_list
};
proto_getProfilePortrait(
options,
function (resp) {
var nick, gender, allowType, image;
if (resp.UserProfileItem && resp.UserProfileItem.length > 0) {
for (var i in resp.UserProfileItem) {
for (var j in resp.UserProfileItem[i].ProfileItem) {
switch (resp.UserProfileItem[i].ProfileItem[j].Tag) {
case 'Tag_Profile_IM_Nick':
nick = resp.UserProfileItem[i].ProfileItem[j].Value;
if (nick) ctx.identifierNick = nick;
break;
case 'Tag_Profile_IM_Image':
image = resp.UserProfileItem[i].ProfileItem[j].Value;
if (image) ctx.headurl = image;
break;
}
}
}
}
if (cbOk) cbOk(ctx.identifierNick, ctx.headurl); //回传当前用户昵称
}, cbErr);
}
, cbErr);
};
//下线
var proto_logout = function (type , cbOk, cbErr) {
if (!checkLogin(cbErr, false)) {//不带登录态
clearSdk();
if (cbOk) cbOk({
'ActionStatus': ACTION_STATUS.OK,
'ErrorCode': 0,
'ErrorInfo': 'logout success'
});
return;
}
if(type == "all"){
ConnManager.apiCall(SRV_NAME.OPEN_IM, "logout", {},
function (resp) {
clearSdk();
if (cbOk) cbOk(resp);
},
cbErr);
}else{
ConnManager.apiCall(SRV_NAME.OPEN_IM, "longpollinglogout", { LongPollingId : LongPollingId },
function (resp) {
clearSdk();
if (cbOk) cbOk(resp);
},
cbErr);
}
};
//发送消息,包括私聊和群聊
var proto_sendMsg = function (msg, cbOk, cbErr) {
if (!checkLogin(cbErr, true)) return;
var msgInfo = null;
switch (msg.sess.type()) {
case SESSION_TYPE.C2C:
msgInfo = {
'From_Account': ctx.identifier,
'To_Account': msg.sess.id().toString(),
'MsgTimeStamp': msg.time,
'MsgSeq': msg.seq,
'MsgRandom': msg.random,
'MsgBody': []
};
break;
case SESSION_TYPE.GROUP:
var subType = msg.getSubType();
msgInfo = {
'GroupId': msg.sess.id().toString(),
'From_Account': ctx.identifier,
'Random': msg.random,
'MsgBody': []
};
switch (subType) {
case GROUP_MSG_SUB_TYPE.COMMON:
msgInfo.MsgPriority = "COMMON";
break;
case GROUP_MSG_SUB_TYPE.REDPACKET:
msgInfo.MsgPriority = "REDPACKET";
break;
case GROUP_MSG_SUB_TYPE.LOVEMSG:
msgInfo.MsgPriority = "LOVEMSG";
break;
case GROUP_MSG_SUB_TYPE.TIP:
log.error("不能主动发送群提示消息,subType=" + subType);
break;
default:
log.error("发送群消息时出现未知子消息类型subType=" + subType);
return;
break;
}
break;
default:
break;
}
for (var i in msg.elems) {
var elem = msg.elems[i];
var msgContent = null;
var msgType = elem.type;
switch (msgType) {
case MSG_ELEMENT_TYPE.TEXT://文本
msgContent = {'Text': elem.content.text};
break;
case MSG_ELEMENT_TYPE.FACE://表情
msgContent = {'Index': elem.content.index, 'Data': elem.content.data};
break;
case MSG_ELEMENT_TYPE.IMAGE://图片
var ImageInfoArray = [];
for (var j in elem.content.ImageInfoArray) {
ImageInfoArray.push(
{
'Type': elem.content.ImageInfoArray[j].type,
'Size': elem.content.ImageInfoArray[j].size,
'Width': elem.content.ImageInfoArray[j].width,
'Height': elem.content.ImageInfoArray[j].height,
'URL': elem.content.ImageInfoArray[j].url
}
);
}
msgContent = {'UUID': elem.content.UUID, 'ImageInfoArray': ImageInfoArray};
break;
case MSG_ELEMENT_TYPE.SOUND://
log.warn('web端暂不支持发送语音消息');
continue;
break;
case MSG_ELEMENT_TYPE.LOCATION://
log.warn('web端暂不支持发送地理位置消息');
continue;
break;
case MSG_ELEMENT_TYPE.FILE://
msgContent = {
'UUID': elem.content.uuid,
'FileName': elem.content.name,
'FileSize': elem.content.size,
'DownloadFlag' : elem.content.downFlag
};
break;
case MSG_ELEMENT_TYPE.CUSTOM://
msgContent = {'Data': elem.content.data, 'Desc': elem.content.desc, 'Ext': elem.content.ext};
msgType = MSG_ELEMENT_TYPE.CUSTOM;
break;
default :
log.warn('web端暂不支持发送' + elem.type + '消息');
continue;
break;
}
if (msg.PushInfoBoolean) {
msgInfo.OfflinePushInfo = msg.PushInfo; //当android终端进程被杀掉时才走pushIOS退到后台即可
}
msgInfo.MsgBody.push({
'MsgType': msgType,
'MsgContent': msgContent
});
}
if (msg.sess.type() == SESSION_TYPE.C2C) {//私聊
ConnManager.apiCall(SRV_NAME.OPEN_IM, "sendmsg", msgInfo, cbOk, cbErr);
} else if (msg.sess.type() == SESSION_TYPE.GROUP) {//群聊
ConnManager.apiCall(SRV_NAME.GROUP, "send_group_msg", msgInfo, cbOk, cbErr);
}
};
//长轮询接口
var proto_longPolling = function (options, cbOk, cbErr) {
if(!isAccessFormaEnvironment && typeof stopPolling !="undefined" && stopPolling == true){
return;
}
if (!checkLogin(cbErr, true)) return;
ConnManager.apiCall(SRV_NAME.OPEN_IM, "longpolling", options, cbOk, cbErr, longPollingDefaultTimeOut, true);
};
//长轮询接口(拉取直播聊天室新消息)
var proto_bigGroupLongPolling = function (options, cbOk, cbErr, timeout) {
ConnManager.apiCall(SRV_NAME.BIG_GROUP_LONG_POLLING, "get_msg", options, cbOk, cbErr, timeout);
};
//拉取未读c2c消息接口
var proto_getMsgs = function (cookie, syncFlag, cbOk, cbErr) {
if (!checkLogin(cbErr, true)) return;
ConnManager.apiCall(SRV_NAME.OPEN_IM, "getmsg", {'Cookie': cookie, 'SyncFlag': syncFlag},
function (resp) {
if (resp.MsgList && resp.MsgList.length) {
for (var i in resp.MsgList) {
tempC2CMsgList.push(resp.MsgList[i]);
}
}
if (resp.SyncFlag == 1) {
proto_getMsgs(resp.Cookie, resp.SyncFlag, cbOk, cbErr);
} else {
resp.MsgList = tempC2CMsgList;
tempC2CMsgList = [];
if (cbOk) cbOk(resp);
}
},
cbErr);
};
//C2C消息已读上报接口
var proto_c2CMsgReaded = function (cookie, c2CMsgReadedItem, cbOk, cbErr) {
if (!checkLogin(cbErr, true)) return;
var tmpC2CMsgReadedItem = [];
for (var i in c2CMsgReadedItem) {
var item = {
'To_Account': c2CMsgReadedItem[i].toAccount,
'LastedMsgTime': c2CMsgReadedItem[i].lastedMsgTime
};
tmpC2CMsgReadedItem.push(item);
}
ConnManager.apiCall(SRV_NAME.OPEN_IM, "msgreaded", {
C2CMsgReaded: {
'Cookie': cookie,
'C2CMsgReadedItem': tmpC2CMsgReadedItem
}
}, cbOk, cbErr);
};
//删除c2c消息
var proto_deleteC2CMsg = function (options, cbOk, cbErr) {
if (!checkLogin(cbErr, true)) return;
ConnManager.apiCall(SRV_NAME.OPEN_IM, "deletemsg", options,
cbOk, cbErr);
};
//拉取c2c历史消息接口
var proto_getC2CHistoryMsgs = function (options, cbOk, cbErr) {
if (!checkLogin(cbErr, true)) return;
ConnManager.apiCall(SRV_NAME.OPEN_IM, "getroammsg", options,
function (resp) {
var reqMsgCount = options.MaxCnt;
var complete = resp.Complete;
var rspMsgCount = resp.MaxCnt;
var msgKey = resp.MsgKey;
var lastMsgTime = resp.LastMsgTime;
if (resp.MsgList && resp.MsgList.length) {
for (var i in resp.MsgList) {
tempC2CHistoryMsgList.push(resp.MsgList[i]);
}
}
var netxOptions = null;
if (complete == 0) {//还有历史消息可拉取
if (rspMsgCount < reqMsgCount) {
netxOptions = {
'Peer_Account': options.Peer_Account,
'MaxCnt': reqMsgCount - rspMsgCount,
'LastMsgTime': lastMsgTime,
'MsgKey': msgKey
};
}
}
if (netxOptions) {//继续拉取
proto_getC2CHistoryMsgs(netxOptions, cbOk, cbErr);
} else {
resp.MsgList = tempC2CHistoryMsgList;
tempC2CHistoryMsgList = [];
if (cbOk) cbOk(resp);
}
},
cbErr);
};
//群组接口
//创建群组
//协议参考https://www.qcloud.com/doc/product/269/1615
var proto_createGroup = function (options, cbOk, cbErr) {
if (!checkLogin(cbErr, true)) return;
var opt = {
//必填 群组形态包括Public公开群Private私密群ChatRoom聊天室AVChatRoom互动直播聊天室
'Type': options.Type,
//必填 群名称最长30字节。
'Name': options.Name
};
var member_list = [];
//Array 选填 初始群成员列表最多500个。成员信息字段详情参见群成员资料。
for (var i = 0; i < options.MemberList.length; i++) {
member_list.push({'Member_Account': options.MemberList[i]})
}
opt.MemberList = member_list;
//选填 为了使得群组ID更加简单便于记忆传播腾讯云支持APP在通过REST API创建群组时自定义群组ID。详情参见自定义群组ID。
if (options.GroupId) {
opt.GroupId = options.GroupId;
}
//选填 群主id自动添加到群成员中。如果不填群没有群主。
if (options.Owner_Account) {
opt.Owner_Account = options.Owner_Account;
}
//选填 群简介最长240字节。
if (options.Introduction) {
opt.Introduction = options.Introduction;
}
//选填 群公告最长300字节。
if (options.Notification) {
opt.Notification = options.Notification;
}
//选填 最大群成员数量最大为10000不填默认为2000个。
if (options.MaxMemberCount) {
opt.MaxMemberCount = options.MaxMemberCount;
}
//选填 申请加群处理方式。包含FreeAccess自由加入NeedPermission需要验证DisableApply禁止加群不填默认为NeedPermission需要验证
if (options.ApplyJoinOption) {//
opt.ApplyJoinOption = options.ApplyJoinOption;
}
//Array 选填 群组维度的自定义字段,默认情况是没有的,需要开通,详情参见:自定义字段。
if (options.AppDefinedData) {
opt.AppDefinedData = options.AppDefinedData;
}
//选填 群头像URL最长100字节。
if (options.FaceUrl) {
opt.FaceUrl = options.FaceUrl;
}
ConnManager.apiCall(SRV_NAME.GROUP, "create_group", opt,
function (resp) {
if (resp && resp.ErrorCode == 0 && options.Type == "AVChatRoom") {
if (resp.LongPollingKey) {
MsgManager.resetBigGroupLongPollingInfo();
MsgManager.setBigGroupLongPollingOn(true);//开启长轮询
MsgManager.setBigGroupLongPollingKey(resp.LongPollingKey);//更新大群长轮询key
MsgManager.setBigGroupLongPollingMsgMap(options.GroupId, 0);//收到的群消息置0
MsgManager.bigGroupLongPolling();//开启长轮询
}
}
if (cbOk) cbOk(resp);
},
function (err) {
if (err && err.ErrorCode == 10025 && options.Type == "AVChatRoom") {
//群组 ID 已被使用,并且操作者为群主,可以直接使用
if (err.LongPollingKey) {
MsgManager.resetBigGroupLongPollingInfo();
MsgManager.setBigGroupLongPollingOn(true);//开启长轮询
MsgManager.setBigGroupLongPollingKey(err.LongPollingKey);//更新大群长轮询key
MsgManager.setBigGroupLongPollingMsgMap(options.GroupId, 0);//收到的群消息置0
MsgManager.bigGroupLongPolling();//开启长轮询
}
}
if (cbErr) cbErr(err);
});
};
//创建群组-高级接口
//协议参考https://www.qcloud.com/doc/product/269/1615
var proto_createGroupHigh = function (options, cbOk, cbErr) {
if (!checkLogin(cbErr, true)) return;
ConnManager.apiCall(SRV_NAME.GROUP, "create_group", options,
cbOk, cbErr);
};
//修改群组基本资料
//协议参考https://www.qcloud.com/doc/product/269/1620
var proto_modifyGroupBaseInfo = function (options, cbOk, cbErr) {
if (!checkLogin(cbErr, true)) return;
ConnManager.apiCall(SRV_NAME.GROUP, "modify_group_base_info", options,
cbOk, cbErr);
};
//申请加群
var proto_applyJoinGroup = function (options, cbOk, cbErr) {
if (!checkLogin(cbErr, true)) return;
ConnManager.apiCall(SRV_NAME.GROUP, "apply_join_group", {
'GroupId': options.GroupId,
'ApplyMsg': options.ApplyMsg,
'UserDefinedField': options.UserDefinedField
},
cbOk, cbErr);
};
//申请加入大群
var proto_applyJoinBigGroup = function (options, cbOk, cbErr) {
var srvName;
if (!checkLogin(cbErr, false)) {//未登录
srvName = SRV_NAME.BIG_GROUP;
} else {//已登录
srvName = SRV_NAME.GROUP;
}
ConnManager.apiCall(srvName, "apply_join_group", {
'GroupId': options.GroupId,
'ApplyMsg': options.ApplyMsg,
'UserDefinedField': options.UserDefinedField
},
function (resp) {
if (resp.JoinedStatus && resp.JoinedStatus == 'JoinedSuccess') {
if (resp.LongPollingKey) {
MsgManager.resetBigGroupLongPollingInfo();
MsgManager.setBigGroupLongPollingOn(true);//开启长轮询
MsgManager.setBigGroupLongPollingKey(resp.LongPollingKey);//更新大群长轮询key
MsgManager.setBigGroupLongPollingMsgMap(options.GroupId, 0);//收到的群消息置0
MsgManager.bigGroupLongPolling();//开启长轮询
} else {//没有返回LongPollingKey说明申请加的群不是直播聊天室(AVChatRoom)
cbErr && cbErr(tool.getReturnError("The type of group is not AVChatRoom: groupid=" + options.GroupId, -12));
return;
}
}
if (cbOk) cbOk(resp);
}
, function (err) {
if (cbErr) cbErr(err);
});
};
//处理加群申请(同意或拒绝)
var proto_handleApplyJoinGroupPendency = function (options, cbOk, cbErr) {
if (!checkLogin(cbErr, true)) return;
ConnManager.apiCall(SRV_NAME.GROUP, "handle_apply_join_group", {
'GroupId': options.GroupId,
'Applicant_Account': options.Applicant_Account,
'HandleMsg': options.HandleMsg,
'Authentication': options.Authentication,
'MsgKey': options.MsgKey,
'ApprovalMsg': options.ApprovalMsg,
'UserDefinedField': options.UserDefinedField
},
cbOk,
function (err) {
if (err.ErrorCode == 10024) {//apply has be handled
if (cbOk) {
var resp = {
'ActionStatus': ACTION_STATUS.OK,
'ErrorCode': 0,
'ErrorInfo': '该申请已经被处理过'
};
cbOk(resp);
}
} else {
if (cbErr) cbErr(err);
}
}
);
};
//主动退群
var proto_quitGroup = function (options, cbOk, cbErr) {
if (!checkLogin(cbErr, true)) return;
ConnManager.apiCall(SRV_NAME.GROUP, "quit_group", {
'GroupId': options.GroupId
},
cbOk, cbErr);
};
//退出大群
var proto_quitBigGroup = function (options, cbOk, cbErr) {
var srvName;
if (!checkLogin(cbErr, false)) {//未登录
srvName = SRV_NAME.BIG_GROUP;
} else {//已登录
srvName = SRV_NAME.GROUP;
}
MsgManager.resetBigGroupLongPollingInfo();
ConnManager.apiCall(srvName, "quit_group",
{'GroupId': options.GroupId},
function (resp) {
//重置当前再请求中的ajax
//clearXmlHttpObjMap();
//退出大群成功之后需要重置长轮询信息
MsgManager.resetBigGroupLongPollingInfo();
if (cbOk) cbOk(resp);
},
cbErr);
};
//查找群(按名称)
var proto_searchGroupByName = function (options, cbOk, cbErr) {
ConnManager.apiCall(SRV_NAME.GROUP, "search_group", options, cbOk, cbErr);
};
//获取群组公开资料
var proto_getGroupPublicInfo = function (options, cbOk, cbErr) {
if (!checkLogin(cbErr, true)) return;
ConnManager.apiCall(SRV_NAME.GROUP, "get_group_public_info", {
'GroupIdList': options.GroupIdList,
'ResponseFilter': {
'GroupBasePublicInfoFilter': options.GroupBasePublicInfoFilter
}
},
function (resp) {
resp.ErrorInfo = '';
if (resp.GroupInfo) {
for (var i in resp.GroupInfo) {
var errorCode = resp.GroupInfo[i].ErrorCode;
if (errorCode > 0) {
resp.ActionStatus = ACTION_STATUS.FAIL;
resp.GroupInfo[i].ErrorInfo = "[" + errorCode + "]" + resp.GroupInfo[i].ErrorInfo;
resp.ErrorInfo += resp.GroupInfo[i].ErrorInfo + '\n';
}
}
}
if (resp.ActionStatus == ACTION_STATUS.FAIL) {
if (cbErr) {
cbErr(resp);
}
} else if (cbOk) {
cbOk(resp);
}
},
cbErr);
};
//获取群组详细资料--高级
//请求协议参考https://www.qcloud.com/doc/product/269/1616
var proto_getGroupInfo = function (options, cbOk, cbErr) {
if (!checkLogin(cbErr, true)) return;
var opt = {
'GroupIdList': options.GroupIdList,
'ResponseFilter': {
'GroupBaseInfoFilter': options.GroupBaseInfoFilter,
'MemberInfoFilter': options.MemberInfoFilter
}
};
if (options.AppDefinedDataFilter_Group) {
opt.ResponseFilter.AppDefinedDataFilter_Group = options.AppDefinedDataFilter_Group;
}
if (options.AppDefinedDataFilter_GroupMember) {
opt.ResponseFilter.AppDefinedDataFilter_GroupMember = options.AppDefinedDataFilter_GroupMember;
}
ConnManager.apiCall(SRV_NAME.GROUP, "get_group_info", opt,
cbOk, cbErr);
};
//获取群组成员-高级接口
//协议参考https://www.qcloud.com/doc/product/269/1617
var proto_getGroupMemberInfo = function (options, cbOk, cbErr) {
if (!checkLogin(cbErr, true)) return;
ConnManager.apiCall(SRV_NAME.GROUP, "get_group_member_info", {
'GroupId': options.GroupId,
'Offset': options.Offset,
'Limit': options.Limit,
'MemberInfoFilter': options.MemberInfoFilter,
'MemberRoleFilter': options.MemberRoleFilter,
'AppDefinedDataFilter_GroupMember': options.AppDefinedDataFilter_GroupMember
},
cbOk, cbErr);
};
//增加群组成员
//协议参考https://www.qcloud.com/doc/product/269/1621
var proto_addGroupMember = function (options, cbOk, cbErr) {
if (!checkLogin(cbErr, true)) return;
ConnManager.apiCall(SRV_NAME.GROUP, "add_group_member", {
'GroupId': options.GroupId,
'Silence': options.Silence,
'MemberList': options.MemberList
},
cbOk, cbErr);
};
//修改群组成员资料
//协议参考https://www.qcloud.com/doc/product/269/1623
var proto_modifyGroupMember = function (options, cbOk, cbErr) {
if (!checkLogin(cbErr, true)) return;
var opt = {};
if (options.GroupId) {
opt.GroupId = options.GroupId;
}
if (options.Member_Account) {
opt.Member_Account = options.Member_Account;
}
//Admin或者Member
if (options.Role) {
opt.Role = options.Role;
}
// AcceptAndNotify代表解收并提示消息Discard代表不接收也不提示消息AcceptNotNotify代表接收消息但不提示
if (options.MsgFlag) {
opt.MsgFlag = options.MsgFlag;
}
if (options.ShutUpTime) {//禁言时间
opt.ShutUpTime = options.ShutUpTime;
}
if (options.NameCard) {//群名片,最大不超过50个字节
opt.NameCard = options.NameCard;
}
if (options.AppMemberDefinedData) {//群成员维度的自定义字段,默认情况是没有的,需要开通
opt.AppMemberDefinedData = options.AppMemberDefinedData;
}
ConnManager.apiCall(SRV_NAME.GROUP, "modify_group_member_info", opt,
cbOk, cbErr);
};
//删除群组成员
//协议参考https://www.qcloud.com/doc/product/269/1622
var proto_deleteGroupMember = function (options, cbOk, cbErr) {
if (!checkLogin(cbErr, true)) return;
ConnManager.apiCall(SRV_NAME.GROUP, "delete_group_member", {
'GroupId': options.GroupId,
'Silence': options.Silence,
'MemberToDel_Account': options.MemberToDel_Account,
'Reason': options.Reason
},
cbOk, cbErr);
};
//解散群组
//协议参考https://www.qcloud.com/doc/product/269/1624
var proto_destroyGroup = function (options, cbOk, cbErr) {
if (!checkLogin(cbErr, true)) return;
ConnManager.apiCall(SRV_NAME.GROUP, "destroy_group", {
'GroupId': options.GroupId
},
function (resp) {
if (options.Type == "AVChatRoom") {
//退出大群成功之后需要重置长轮询信息
MsgManager.resetBigGroupLongPollingInfo();
}
if (cbOk) cbOk(resp);
}, cbErr);
};
//转让群组
//协议参考https://www.qcloud.com/doc/product/269/1633
var proto_changeGroupOwner = function (options, cbOk, cbErr) {
if (!checkLogin(cbErr, true)) return;
ConnManager.apiCall(SRV_NAME.GROUP, "change_group_owner", options, cbOk, cbErr);
};
//获取用户所加入的群组-高级接口
//协议参考https://www.qcloud.com/doc/product/269/1625
var proto_getJoinedGroupListHigh = function (options, cbOk, cbErr) {
if (!checkLogin(cbErr, true)) return;
ConnManager.apiCall(SRV_NAME.GROUP, "get_joined_group_list", {
'Member_Account': options.Member_Account,
'Limit': options.Limit,
'Offset': options.Offset,
'GroupType': options.GroupType,
'ResponseFilter': {
'GroupBaseInfoFilter': options.GroupBaseInfoFilter,
'SelfInfoFilter': options.SelfInfoFilter
}
},
cbOk, cbErr);
};
//查询一组UserId在群中的身份
//协议参考https://www.qcloud.com/doc/product/269/1626
var proto_getRoleInGroup = function (options, cbOk, cbErr) {
if (!checkLogin(cbErr, true)) return;
ConnManager.apiCall(SRV_NAME.GROUP, "get_role_in_group", {
'GroupId': options.GroupId,
'User_Account': options.User_Account
},
cbOk, cbErr);
};
//设置取消成员禁言时间
//协议参考https://www.qcloud.com/doc/product/269/1627
var proto_forbidSendMsg = function (options, cbOk, cbErr) {
if (!checkLogin(cbErr, true)) return;
ConnManager.apiCall(SRV_NAME.GROUP, "forbid_send_msg", {
'GroupId': options.GroupId,
'Members_Account': options.Members_Account,
'ShutUpTime': options.ShutUpTime//单位为秒为0时表示取消禁言
},
cbOk, cbErr);
};
//发送自定义群系统通知
var proto_sendCustomGroupNotify = function (options, cbOk, cbErr) {
if (!checkLogin(cbErr, true)) return;
ConnManager.apiCall(SRV_NAME.GROUP, "send_group_system_notification", options,
cbOk, cbErr);
};
//拉取群消息接口
var proto_getGroupMsgs = function (options, cbOk, cbErr) {
if (!checkLogin(cbErr, true)) return;
ConnManager.apiCall(SRV_NAME.GROUP, "group_msg_get", {
"GroupId": options.GroupId,
"ReqMsgSeq": options.ReqMsgSeq,
"ReqMsgNumber": options.ReqMsgNumber
},
cbOk, cbErr);
};
//群消息已读上报接口
var proto_groupMsgReaded = function (options, cbOk, cbErr) {
if (!checkLogin(cbErr, true)) return;
ConnManager.apiCall(SRV_NAME.GROUP, "msg_read_report", {
'GroupId': options.GroupId,
'MsgReadedSeq': options.MsgReadedSeq
},
cbOk, cbErr);
};
//end
//好友接口
//处理好友接口返回的错误码
var convertErrorEn2ZhFriend = function (resp) {
var errorAccount = [];
if (resp.Fail_Account && resp.Fail_Account.length) {
errorAccount = resp.Fail_Account;
}
if (resp.Invalid_Account && resp.Invalid_Account.length) {
for (var k in resp.Invalid_Account) {
errorAccount.push(resp.Invalid_Account[k]);
}
}
if (errorAccount.length) {
resp.ActionStatus = ACTION_STATUS.FAIL;
resp.ErrorCode = ERROR_CODE_CUSTOM;
resp.ErrorInfo = '';
for (var i in errorAccount) {
var failCount = errorAccount[i];
for (var j in resp.ResultItem) {
if (resp.ResultItem[j].To_Account == failCount) {
var resultCode = resp.ResultItem[j].ResultCode;
resp.ResultItem[j].ResultInfo = "[" + resultCode + "]" + resp.ResultItem[j].ResultInfo;
resp.ErrorInfo += resp.ResultItem[j].ResultInfo + "\n";
break;
}
}
}
}
return resp;
};
//添加好友
var proto_applyAddFriend = function (options, cbOk, cbErr) {
if (!checkLogin(cbErr, true)) return;
ConnManager.apiCall(SRV_NAME.FRIEND, "friend_add", {
'From_Account': ctx.identifier,
'AddFriendItem': options.AddFriendItem
},
function (resp) {
var newResp = convertErrorEn2ZhFriend(resp);
if (newResp.ActionStatus == ACTION_STATUS.FAIL) {
if (cbErr) cbErr(newResp);
} else if (cbOk) {
cbOk(newResp);
}
}, cbErr);
};
//删除好友
var proto_deleteFriend = function (options, cbOk, cbErr) {
if (!checkLogin(cbErr, true)) return;
ConnManager.apiCall(SRV_NAME.FRIEND, "friend_delete", {
'From_Account': ctx.identifier,
'To_Account': options.To_Account,
'DeleteType': options.DeleteType
},
function (resp) {
var newResp = convertErrorEn2ZhFriend(resp);
if (newResp.ActionStatus == ACTION_STATUS.FAIL) {
if (cbErr) cbErr(newResp);
} else if (cbOk) {
cbOk(newResp);
}
}, cbErr);
};
//获取好友申请
var proto_getPendency = function (options, cbOk, cbErr) {
if (!checkLogin(cbErr, true)) return;
ConnManager.apiCall(SRV_NAME.FRIEND, "pendency_get", {
"From_Account": ctx.identifier,
"PendencyType": options.PendencyType,
"StartTime": options.StartTime,
"MaxLimited": options.MaxLimited,
"LastSequence": options.LastSequence
},
cbOk, cbErr);
};
//删除好友申请
var proto_deletePendency = function (options, cbOk, cbErr) {
if (!checkLogin(cbErr, true)) return;
ConnManager.apiCall(SRV_NAME.FRIEND, "pendency_delete", {
"From_Account": ctx.identifier,
"PendencyType": options.PendencyType,
"To_Account": options.To_Account
},
function (resp) {
var newResp = convertErrorEn2ZhFriend(resp);
if (newResp.ActionStatus == ACTION_STATUS.FAIL) {
if (cbErr) cbErr(newResp);
} else if (cbOk) {
cbOk(newResp);
}
}, cbErr);
};
//处理好友申请
var proto_responseFriend = function (options, cbOk, cbErr) {
if (!checkLogin(cbErr, true)) return;
ConnManager.apiCall(SRV_NAME.FRIEND, "friend_response", {
'From_Account': ctx.identifier,
'ResponseFriendItem': options.ResponseFriendItem
},
function (resp) {
var newResp = convertErrorEn2ZhFriend(resp);
if (newResp.ActionStatus == ACTION_STATUS.FAIL) {
if (cbErr) cbErr(newResp);
} else if (cbOk) {
cbOk(newResp);
}
}, cbErr);
};
//我的好友
var proto_getAllFriend = function (options, cbOk, cbErr) {
if (!checkLogin(cbErr, true)) return;
ConnManager.apiCall(SRV_NAME.FRIEND, "friend_get_all", {
'From_Account': ctx.identifier,
'TimeStamp': options.TimeStamp,
'StartIndex': options.StartIndex,
'GetCount': options.GetCount,
'LastStandardSequence': options.LastStandardSequence,
'TagList': options.TagList
},
cbOk, cbErr);
};
//资料接口
//查看个人资料
var proto_getProfilePortrait = function (options, cbOk, cbErr) {
if (!checkLogin(cbErr, true)) return;
ConnManager.apiCall(SRV_NAME.PROFILE, "portrait_get", {
'From_Account': ctx.identifier,
'To_Account': options.To_Account,
//'LastStandardSequence':options.LastStandardSequence,
'TagList': options.TagList
},
function (resp) {
var errorAccount = [];
if (resp.Fail_Account && resp.Fail_Account.length) {
errorAccount = resp.Fail_Account;
}
if (resp.Invalid_Account && resp.Invalid_Account.length) {
for (var k in resp.Invalid_Account) {
errorAccount.push(resp.Invalid_Account[k]);
}
}
if (errorAccount.length) {
resp.ActionStatus = ACTION_STATUS.FAIL;
resp.ErrorCode = ERROR_CODE_CUSTOM;
resp.ErrorInfo = '';
for (var i in errorAccount) {
var failCount = errorAccount[i];
for (var j in resp.UserProfileItem) {
if (resp.UserProfileItem[j].To_Account == failCount) {
var resultCode = resp.UserProfileItem[j].ResultCode;
resp.UserProfileItem[j].ResultInfo = "[" + resultCode + "]" + resp.UserProfileItem[j].ResultInfo;
resp.ErrorInfo += "账号:" + failCount + "," + resp.UserProfileItem[j].ResultInfo + "\n";
break;
}
}
}
}
if (resp.ActionStatus == ACTION_STATUS.FAIL) {
if (cbErr) cbErr(resp);
} else if (cbOk) {
cbOk(resp);
}
},
cbErr);
};
//设置个人资料
var proto_setProfilePortrait = function (options, cbOk, cbErr) {
if (!checkLogin(cbErr, true)) return;
ConnManager.apiCall(SRV_NAME.PROFILE, "portrait_set",
{
'From_Account': ctx.identifier,
'ProfileItem': options.ProfileItem
},
function (resp) {
for (var i in options.ProfileItem) {
var profile = options.ProfileItem[i];
if (profile.Tag == 'Tag_Profile_IM_Nick') {
ctx.identifierNick = profile.Value;//更新昵称
break;
}
}
if (cbOk) cbOk(resp);
}
, cbErr);
};
//增加黑名单
var proto_addBlackList = function (options, cbOk, cbErr) {
if (!checkLogin(cbErr, true)) return;
ConnManager.apiCall(SRV_NAME.FRIEND, "black_list_add", {
'From_Account': ctx.identifier,
'To_Account': options.To_Account
},
function (resp) {
var newResp = convertErrorEn2ZhFriend(resp);
if (newResp.ActionStatus == ACTION_STATUS.FAIL) {
if (cbErr) cbErr(newResp);
} else if (cbOk) {
cbOk(newResp);
}
}, cbErr);
};
//删除黑名单
var proto_deleteBlackList = function (options, cbOk, cbErr) {
if (!checkLogin(cbErr, true)) return;
ConnManager.apiCall(SRV_NAME.FRIEND, "black_list_delete", {
'From_Account': ctx.identifier,
'To_Account': options.To_Account
},
function (resp) {
var newResp = convertErrorEn2ZhFriend(resp);
if (newResp.ActionStatus == ACTION_STATUS.FAIL) {
if (cbErr) cbErr(newResp);
} else if (cbOk) {
cbOk(newResp);
}
}, cbErr);
};
//我的黑名单
var proto_getBlackList = function (options, cbOk, cbErr) {
if (!checkLogin(cbErr, true)) return;
ConnManager.apiCall(SRV_NAME.FRIEND, "black_list_get", {
'From_Account': ctx.identifier,
'StartIndex': options.StartIndex,
'MaxLimited': options.MaxLimited,
'LastSequence': options.LastSequence
},
cbOk, cbErr);
};
//获取最近联系人
var proto_getRecentContactList = function (options, cbOk, cbErr) {
if (!checkLogin(cbErr, true)) return;
ConnManager.apiCall(SRV_NAME.RECENT_CONTACT, "get", {
'From_Account': ctx.identifier,
'Count': options.Count
},
cbOk, cbErr);
};
//上传图片或文件
var proto_uploadPic = function (options, cbOk, cbErr) {
if (!checkLogin(cbErr, true)) return;
var cmdName;
if (isAccessFormalEnv()) {
cmdName = 'pic_up';
} else {
cmdName = 'pic_up_test';
}
ConnManager.apiCall(SRV_NAME.PIC, cmdName, {
'App_Version': VERSION_INFO.APP_VERSION,
'From_Account': ctx.identifier,
'To_Account': options.To_Account,
'Seq': options.Seq,
'Timestamp': options.Timestamp,
'Random': options.Random,
'File_Str_Md5': options.File_Str_Md5,
'File_Size': options.File_Size,
'File_Type': options.File_Type,
'Server_Ver': VERSION_INFO.SERVER_VERSION,
'Auth_Key': authkey,
'Busi_Id': options.Busi_Id,
'PkgFlag': options.PkgFlag,
'Slice_Offset': options.Slice_Offset,
'Slice_Size': options.Slice_Size,
'Slice_Data': options.Slice_Data
},
cbOk, cbErr);
};
//获取语音和文件下载IP和authkey
var proto_getIpAndAuthkey = function (cbOk, cbErr) {
if (!checkLogin(cbErr, true)) return;
ConnManager.apiCall(SRV_NAME.OPEN_IM, "authkey", {}, cbOk, cbErr);
};
//接口质量上报
var proto_reportApiQuality = function (options, cbOk, cbErr) {
if (!checkLogin(cbErr, true)) return;
ConnManager.apiCall(SRV_NAME.IM_OPEN_STAT, "web_report", options, cbOk, cbErr);
};
var proto_getLongPollingId = function (options, cbOk, cbErr) {
if (!checkLogin(cbErr, true)) return;
ConnManager.apiCall( SRV_NAME.OPEN_IM, "getlongpollingid",{},
function (resp) {
cbOk && cbOk(resp);
}, cbErr);
}
var proto_applyDownload = function (options, cbOk, cbErr) {
//把下载地址push到map中
ConnManager.apiCall( SRV_NAME.PIC, "apply_download", options, cbOk, cbErr);
}
//end
initBrowserInfo();
// singleton object ConnManager
var ConnManager = lowerBR == false
? new function () {
var onConnCallback = null; //回调函数
this.init = function (onConnNotify, cbOk, cbErr) {
if (onConnNotify) onConnCallback = onConnNotify;
};
this.callBack = function (info) {
if (onConnCallback) onConnCallback(info);
};
this.clear = function () {
onConnCallback = null;
};
//请求后台服务接口
this.apiCall = function (type, cmd, data, cbOk, cbErr, timeout, isLongPolling) {
//封装后台服务接口地址
var url = getApiUrl(type, cmd, cbOk, cbErr);
if (url == false) return;
//发起ajax请求
ajaxRequestJson("POST", url, data, timeout, isLongPolling, function (resp) {
var errorCode = null, tempErrorInfo = '';
if(cmd=='pic_up'){
data.Slice_Data='';
}
var info = "\n request url: \n" + url + "\n request body: \n" + JSON.stringify(data) + "\n response: \n" + JSON.stringify(resp);
//成功
if (resp.ActionStatus == ACTION_STATUS.OK) {
log.info("[" + type + "][" + cmd + "]success: " + info);
if (cbOk) cbOk(resp);//回调
errorCode = 0;
tempErrorInfo = '';
} else {
errorCode = resp.ErrorCode;
tempErrorInfo = resp.ErrorInfo;
//报错
if (cbErr) {
resp.SrcErrorInfo = resp.ErrorInfo;
resp.ErrorInfo = "[" + type + "][" + cmd + "]failed: " + info;
if (cmd != 'longpolling' || resp.ErrorCode != longPollingTimeOutErrorCode) {
log.error(resp.ErrorInfo);
}
cbErr(resp);
}
}
reportApiQuality(cmd, errorCode, tempErrorInfo);//接口质量上报
}, function (err) {
cbErr && cbErr(err);
reportApiQuality(cmd, err.ErrorCode, err.ErrorInfo);//接口质量上报
});
};
}
: new function () {
var onConnCallback = null; //回调函数
this.init = function (onConnNotify, cbOk, cbErr) {
if (onConnNotify) onConnCallback = onConnNotify;
};
this.callBack = function (info) {
if (onConnCallback) onConnCallback(info);
};
this.clear = function () {
onConnCallback = null;
};
//请求后台服务接口
this.apiCall = function (type, cmd, data, cbOk, cbErr, timeout, isLongPolling) {
//封装后台服务接口地址
var url = getApiUrl(type, cmd, cbOk, cbErr);
if (url == false) return;
//发起jsonp请求
var reqId = jsonpRequestId++,
cbkey = 'jsonpcallback', // the 'callback' key
cbval = 'jsonpRequest' + reqId, // the 'callback' value
script = document.createElement('script'),
loaded = 0;
window[cbval] = jsonpCallback;
script.type = 'text/javascript';
url = url + "&" + cbkey + "=" + cbval + "&jsonpbody=" + encodeURIComponent(JSON.stringify(data));
script.src = url;
script.async = true;
if (typeof script.onreadystatechange !== 'undefined') {
// need this for IE due to out-of-order onreadystatechange(), binding script
// execution to an event listener gives us control over when the script
// is executed. See http://jaubourg.net/2010/07/loading-script-as-onclick-handler-of.html
script.event = 'onclick';
script.htmlFor = script.id = '_jsonpRequest_' + reqId;
}
script.onload = script.onreadystatechange = function () {
if ((this.readyState && this.readyState !== 'complete' && this.readyState !== 'loaded') || loaded) {
return false;
}
script.onload = script.onreadystatechange = null;
script.onclick && script.onclick();
// Call the user callback with the last value stored and clean up values and scripts.
var resp = jsonpLastRspData;
var info = "\n request url: \n" + url + "\n request body: \n" + JSON.stringify(data) + "\n response: \n" + JSON.stringify(resp);
if (resp.ActionStatus == ACTION_STATUS.OK) {
log.info("[" + type + "][" + cmd + "]success: " + info);
cbOk && cbOk(resp);
} else {
resp.ErrorInfo = "[" + type + "][" + cmd + "]failed " + info;
if (cmd != 'longpolling' || resp.ErrorCode != longPollingTimeOutErrorCode) {
log.error(resp.ErrorInfo);
} else {
log.warn("[" + type + "][" + cmd + "]success: " + info);
}
cbErr && cbErr(resp);
}
jsonpLastRspData = undefined;
document.body.removeChild(script);
loaded = 1;
};
// Add the script to the DOM head
document.body.appendChild(script);
};
};
// class Session
var Session = function (type, id, name, icon, time, seq) {
this._impl = {
skey: Session.skey(type, id),
type: type,
id: id,
name: name,
icon: icon,
unread: 0,//未读消息数
isAutoRead: false,
time: time >= 0 ? time : 0,
curMaxMsgSeq: seq >= 0 ? seq : 0,
msgs: [],
isFinished : 1
};
};
Session.skey = function (type, id) {
return type + id;
};
Session.prototype.type = function () {
return this._impl.type;
};
Session.prototype.id = function () {
return this._impl.id;
};
Session.prototype.name = function () {
return this._impl.name;
};
Session.prototype.icon = function () {
return this._impl.icon;
};
Session.prototype.unread = function (val) {
if(typeof val !== 'undefined'){
this._impl.unread = val;
}else{
return this._impl.unread;
}
};
Session.prototype.isFinished = function (val) {
if(typeof val !== 'undefined'){
this._impl.isFinished = val;
}else{
return this._impl.isFinished;
}
};
Session.prototype.time = function () {
return this._impl.time;
};
Session.prototype.curMaxMsgSeq = function (seq) {
if(typeof seq !== 'undefined'){
this._impl.curMaxMsgSeq = seq;
}else{
return this._impl.curMaxMsgSeq;
}
};
Session.prototype.msgCount = function () {
return this._impl.msgs.length;
};
Session.prototype.msg = function (index) {
return this._impl.msgs[index];
};
Session.prototype.msgs = function () {
return this._impl.msgs;
};
Session.prototype._impl_addMsg = function (msg) {
this._impl.msgs.push(msg);
//if (!msg.isSend && msg.time > this._impl.time)
if (msg.time > this._impl.time)
this._impl.time = msg.time;
//if (!msg.isSend && msg.seq > this._impl.curMaxMsgSeq)
if (msg.seq > this._impl.curMaxMsgSeq)
this._impl.curMaxMsgSeq = msg.seq;
//自己发送的消息不计入未读数
if (!msg.isSend && !this._impl.isAutoRead) {
this._impl.unread++;
}
};
//class C2CMsgReadedItem
var C2CMsgReadedItem = function (toAccount, lastedMsgTime) {
this.toAccount = toAccount;
this.lastedMsgTime = lastedMsgTime;
}
// class Msg
var Msg = function (sess, isSend, seq, random, time, fromAccount, subType, fromAccountNick) {
this.sess = sess;
this.subType = subType >= 0 ? subType : 0;//消息类型,c2c消息时type取值为0group消息时type取值0和10-普通群消息1-群提示消息
this.fromAccount = fromAccount;
this.fromAccountNick = fromAccountNick ? fromAccountNick : fromAccount;
this.isSend = Boolean(isSend);
this.seq = seq >= 0 ? seq : nextSeq();
this.random = random >= 0 ? random : createRandom();
this.time = time >= 0 ? time : unixtime();
this.elems = [];
};
Msg.prototype.getSession = function () {
return this.sess;
};
Msg.prototype.getType = function () {
return this.subType;
};
Msg.prototype.getSubType = function () {
return this.subType;
};
Msg.prototype.getFromAccount = function () {
return this.fromAccount;
};
Msg.prototype.getFromAccountNick = function () {
return this.fromAccountNick;
};
Msg.prototype.getIsSend = function () {
return this.isSend;
};
Msg.prototype.getSeq = function () {
return this.seq;
};
Msg.prototype.getTime = function () {
return this.time;
};
Msg.prototype.getRandom = function () {
return this.random;
};
Msg.prototype.getElems = function () {
return this.elems;
};
//文本
Msg.prototype.addText = function (text) {
this.addElem(new webim.Msg.Elem(MSG_ELEMENT_TYPE.TEXT, text));
};
//表情
Msg.prototype.addFace = function (face) {
this.addElem(new webim.Msg.Elem(MSG_ELEMENT_TYPE.FACE, face));
};
//图片
Msg.prototype.addImage = function (image) {
this.addElem(new webim.Msg.Elem(MSG_ELEMENT_TYPE.IMAGE, image));
};
//地理位置
Msg.prototype.addLocation = function (location) {
this.addElem(new webim.Msg.Elem(MSG_ELEMENT_TYPE.LOCATION, location));
};
//文件
Msg.prototype.addFile = function (file) {
this.addElem(new webim.Msg.Elem(MSG_ELEMENT_TYPE.FILE, file));
};
//自定义
Msg.prototype.addCustom = function (custom) {
this.addElem(new webim.Msg.Elem(MSG_ELEMENT_TYPE.CUSTOM, custom));
};
Msg.prototype.addElem = function (elem) {
this.elems.push(elem);
};
Msg.prototype.toHtml = function () {
var html = "";
for (var i in this.elems) {
var elem = this.elems[i];
html += elem.toHtml();
}
return html;
};
// class Msg.Elem
Msg.Elem = function (type, value) {
this.type = type;
this.content = value;
};
Msg.Elem.prototype.getType = function () {
return this.type;
};
Msg.Elem.prototype.getContent = function () {
return this.content;
};
Msg.Elem.prototype.toHtml = function () {
var html;
html = this.content.toHtml();
return html;
};
// class Msg.Elem.Text
Msg.Elem.Text = function (text) {
this.text = tool.xssFilter(text);
};
Msg.Elem.Text.prototype.getText = function () {
return this.text;
};
Msg.Elem.Text.prototype.toHtml = function () {
return this.text;
};
// class Msg.Elem.Face
Msg.Elem.Face = function (index, data) {
this.index = index;
this.data = data;
};
Msg.Elem.Face.prototype.getIndex = function () {
return this.index;
};
Msg.Elem.Face.prototype.getData = function () {
return this.data;
};
Msg.Elem.Face.prototype.toHtml = function () {
var faceUrl = null;
var index = emotionDataIndexs[this.data];
var emotion = emotions[index];
if (emotion && emotion[1]) {
faceUrl = emotion[1];
}
if (faceUrl) {
return "<img src='" + faceUrl + "'/>";
} else {
return this.data;
}
};
// 地理位置消息 class Msg.Elem.Location
Msg.Elem.Location = function (longitude, latitude, desc) {
this.latitude = latitude;//纬度
this.longitude = longitude;//经度
this.desc = desc;//描述
};
Msg.Elem.Location.prototype.getLatitude = function () {
return this.latitude;
};
Msg.Elem.Location.prototype.getLongitude = function () {
return this.longitude;
};
Msg.Elem.Location.prototype.getDesc = function () {
return this.desc;
};
Msg.Elem.Location.prototype.toHtml = function () {
return '经度=' + this.longitude + ',纬度=' + this.latitude + ',描述=' + this.desc;
};
//图片消息
// class Msg.Elem.Images
Msg.Elem.Images = function (imageId) {
this.UUID = imageId;
this.ImageInfoArray = [];
};
Msg.Elem.Images.prototype.addImage = function (image) {
this.ImageInfoArray.push(image);
};
Msg.Elem.Images.prototype.toHtml = function () {
var smallImage = this.getImage(IMAGE_TYPE.SMALL);
var bigImage = this.getImage(IMAGE_TYPE.LARGE);
var oriImage = this.getImage(IMAGE_TYPE.ORIGIN);
if (!bigImage) {
bigImage = smallImage;
}
if (!oriImage) {
oriImage = smallImage;
}
return "<img src='" + smallImage.getUrl() + "#" + bigImage.getUrl() + "#" + oriImage.getUrl() + "' style='CURSOR: hand' id='" + this.getImageId() + "' bigImgUrl='" + bigImage.getUrl() + "' onclick='imageClick(this)' />";
};
Msg.Elem.Images.prototype.getImageId = function () {
return this.UUID;
};
Msg.Elem.Images.prototype.getImage = function (type) {
for (var i in this.ImageInfoArray) {
if (this.ImageInfoArray[i].getType() == type) {
return this.ImageInfoArray[i];
}
}
return null;
};
// class Msg.Elem.Images.Image
Msg.Elem.Images.Image = function (type, size, width, height, url) {
this.type = type;
this.size = size;
this.width = width;
this.height = height;
this.url = url;
};
Msg.Elem.Images.Image.prototype.getType = function () {
return this.type;
};
Msg.Elem.Images.Image.prototype.getSize = function () {
return this.size;
};
Msg.Elem.Images.Image.prototype.getWidth = function () {
return this.width;
};
Msg.Elem.Images.Image.prototype.getHeight = function () {
return this.height;
};
Msg.Elem.Images.Image.prototype.getUrl = function () {
return this.url;
};
// class Msg.Elem.Sound
Msg.Elem.Sound = function (uuid, second, size, senderId, receiverId, downFlag, chatType) {
this.uuid = uuid;//文件id
this.second = second;//时长,单位:秒
this.size = size;//大小,单位:字节
this.senderId = senderId;//发送者
this.receiverId = receiverId;//接收方id
this.downFlag = downFlag;//下载标志位
this.busiId = chatType == SESSION_TYPE.C2C ? 2 : 1;//busi_id ( 1群 2:C2C)
//根据不同情况拉取数据
//是否需要申请下载地址 0:到架平申请 1:到cos申请 2:不需要申请, 直接拿url下载
if(downFlag !== undefined && busiId !== undefined){
getFileDownUrlV2(uuid, senderId, second, downFlag,receiverId, this.busiId , UPLOAD_RES_TYPE.SOUND);
}else{
this.downUrl = getSoundDownUrl(uuid, senderId, second);//下载地址
}
};
Msg.Elem.Sound.prototype.getUUID = function () {
return this.uuid;
};
Msg.Elem.Sound.prototype.getSecond = function () {
return this.second;
};
Msg.Elem.Sound.prototype.getSize = function () {
return this.size;
};
Msg.Elem.Sound.prototype.getSenderId = function () {
return this.senderId;
};
Msg.Elem.Sound.prototype.getDownUrl = function () {
return this.downUrl;
};
Msg.Elem.Sound.prototype.toHtml = function () {
if (BROWSER_INFO.type == 'ie' && parseInt(BROWSER_INFO.ver) <= 8) {
return '[这是一条语音消息]demo暂不支持ie8(含)以下浏览器播放语音,语音URL:' + this.downUrl;
}
return '<audio id="uuid_'+this.uuid+'" src="' + this.downUrl + '" controls="controls" onplay="onChangePlayAudio(this)" preload="none"></audio>';
};
// class Msg.Elem.File
Msg.Elem.File = function (uuid, name, size, senderId, receiverId, downFlag, chatType) {
this.uuid = uuid;//文件id
this.name = name;//文件名
this.size = size;//大小,单位:字节
this.senderId = senderId;//发送者
this.receiverId = receiverId;//接收方id
this.downFlag = downFlag;//下载标志位
this.busiId = chatType == SESSION_TYPE.C2C ? 2 : 1;//busi_id ( 1群 2:C2C)
//根据不同情况拉取数据
//是否需要申请下载地址 0:到架平申请 1:到cos申请 2:不需要申请, 直接拿url下载
if(downFlag !== undefined && busiId !== undefined){
getFileDownUrlV2(uuid, senderId, name, downFlag,receiverId, this.busiId , UPLOAD_RES_TYPE.FILE);
}else{
this.downUrl = getFileDownUrl(uuid, senderId, name);//下载地址
}
};
Msg.Elem.File.prototype.getUUID = function () {
return this.uuid;
};
Msg.Elem.File.prototype.getName = function () {
return this.name;
};
Msg.Elem.File.prototype.getSize = function () {
return this.size;
};
Msg.Elem.File.prototype.getSenderId = function () {
return this.senderId;
};
Msg.Elem.File.prototype.getDownUrl = function () {
return this.downUrl;
};
Msg.Elem.File.prototype.getDownFlag = function () {
return this.downFlag;
};
Msg.Elem.File.prototype.toHtml = function () {
var fileSize, unitStr;
fileSize = this.size;
unitStr = "Byte";
if (this.size >= 1024) {
fileSize = Math.round(this.size / 1024);
unitStr = "KB";
}
return '<a href="javascript" onclick="webim.onDownFile("'+this.uuid+'")" title="点击下载文件" ><i class="glyphicon glyphicon-file">&nbsp;' + this.name + '(' + fileSize + unitStr + ')</i></a>';
};
// class Msg.Elem.GroupTip 群提示消息对象
Msg.Elem.GroupTip = function (opType, opUserId, groupId, groupName, userIdList) {
this.opType = opType;//操作类型
this.opUserId = opUserId;//操作者id
this.groupId = groupId;//群id
this.groupName = groupName;//群名称
this.userIdList = userIdList ? userIdList : [];//被操作的用户id列表
this.groupInfoList = [];//新的群资料信息,群资料变更时才有值
this.memberInfoList = [];//新的群成员资料信息,群成员资料变更时才有值
this.groupMemberNum = null;//群成员数,操作类型为加群或者退群时才有值
};
Msg.Elem.GroupTip.prototype.addGroupInfo = function (groupInfo) {
this.groupInfoList.push(groupInfo);
};
Msg.Elem.GroupTip.prototype.addMemberInfo = function (memberInfo) {
this.memberInfoList.push(memberInfo);
};
Msg.Elem.GroupTip.prototype.getOpType = function () {
return this.opType;
};
Msg.Elem.GroupTip.prototype.getOpUserId = function () {
return this.opUserId;
};
Msg.Elem.GroupTip.prototype.getGroupId = function () {
return this.groupId;
};
Msg.Elem.GroupTip.prototype.getGroupName = function () {
return this.groupName;
};
Msg.Elem.GroupTip.prototype.getUserIdList = function () {
return this.userIdList;
};
Msg.Elem.GroupTip.prototype.getGroupInfoList = function () {
return this.groupInfoList;
};
Msg.Elem.GroupTip.prototype.getMemberInfoList = function () {
return this.memberInfoList;
};
Msg.Elem.GroupTip.prototype.getGroupMemberNum = function () {
return this.groupMemberNum;
};
Msg.Elem.GroupTip.prototype.setGroupMemberNum = function (groupMemberNum) {
return this.groupMemberNum = groupMemberNum;
};
Msg.Elem.GroupTip.prototype.toHtml = function () {
var text = "[群提示消息]";
var maxIndex = GROUP_TIP_MAX_USER_COUNT - 1;
switch (this.opType) {
case GROUP_TIP_TYPE.JOIN://加入群
text += this.opUserId + "邀请了";
for (var m in this.userIdList) {
text += this.userIdList[m] + ",";
if (this.userIdList.length > GROUP_TIP_MAX_USER_COUNT && m == maxIndex) {
text += "等" + this.userIdList.length + "人";
break;
}
}
text += "加入该群";
break;
case GROUP_TIP_TYPE.QUIT://退出群
text += this.opUserId + "主动退出该群";
break;
case GROUP_TIP_TYPE.KICK://踢出群
text += this.opUserId + "将";
for (var m in this.userIdList) {
text += this.userIdList[m] + ",";
if (this.userIdList.length > GROUP_TIP_MAX_USER_COUNT && m == maxIndex) {
text += "等" + this.userIdList.length + "人";
break;
}
}
text += "踢出该群";
break;
case GROUP_TIP_TYPE.SET_ADMIN://设置管理员
text += this.opUserId + "将";
for (var m in this.userIdList) {
text += this.userIdList[m] + ",";
if (this.userIdList.length > GROUP_TIP_MAX_USER_COUNT && m == maxIndex) {
text += "等" + this.userIdList.length + "人";
break;
}
}
text += "设为管理员";
break;
case GROUP_TIP_TYPE.CANCEL_ADMIN://取消管理员
text += this.opUserId + "取消";
for (var m in this.userIdList) {
text += this.userIdList[m] + ",";
if (this.userIdList.length > GROUP_TIP_MAX_USER_COUNT && m == maxIndex) {
text += "等" + this.userIdList.length + "人";
break;
}
}
text += "的管理员资格";
break;
case GROUP_TIP_TYPE.MODIFY_GROUP_INFO://群资料变更
text += this.opUserId + "修改了群资料:";
for (var m in this.groupInfoList) {
var type = this.groupInfoList[m].getType();
var value = this.groupInfoList[m].getValue();
switch (type) {
case GROUP_TIP_MODIFY_GROUP_INFO_TYPE.FACE_URL:
text += "群头像为" + value + "; ";
break;
case GROUP_TIP_MODIFY_GROUP_INFO_TYPE.NAME:
text += "群名称为" + value + "; ";
break;
case GROUP_TIP_MODIFY_GROUP_INFO_TYPE.OWNER:
text += "群主为" + value + "; ";
break;
case GROUP_TIP_MODIFY_GROUP_INFO_TYPE.NOTIFICATION:
text += "群公告为" + value + "; ";
break;
case GROUP_TIP_MODIFY_GROUP_INFO_TYPE.INTRODUCTION:
text += "群简介为" + value + "; ";
break;
default:
text += "未知信息为:type=" + type + ",value=" + value + "; ";
break;
}
}
break;
case GROUP_TIP_TYPE.MODIFY_MEMBER_INFO://群成员资料变更(禁言时间)
text += this.opUserId + "修改了群成员资料:";
for (var m in this.memberInfoList) {
var userId = this.memberInfoList[m].getUserId();
var shutupTime = this.memberInfoList[m].getShutupTime();
text += userId + ": ";
if (shutupTime != null && shutupTime !== undefined) {
if (shutupTime == 0) {
text += "取消禁言; ";
} else {
text += "禁言" + shutupTime + "秒; ";
}
} else {
text += " shutupTime为空";
}
if (this.memberInfoList.length > GROUP_TIP_MAX_USER_COUNT && m == maxIndex) {
text += "等" + this.memberInfoList.length + "人";
break;
}
}
break;
case GROUP_TIP_TYPE.READED://消息已读
/**/
Log.info("消息已读同步")
break;
default:
text += "未知群提示消息类型type=" + this.opType;
break;
}
return text;
};
// class Msg.Elem.GroupTip.GroupInfo变更的群资料信息对象
Msg.Elem.GroupTip.GroupInfo = function (type, value) {
this.type = type;//群资料信息类型
this.value = value;//对应的值
};
Msg.Elem.GroupTip.GroupInfo.prototype.getType = function () {
return this.type;
};
Msg.Elem.GroupTip.GroupInfo.prototype.getValue = function () {
return this.value;
};
// class Msg.Elem.GroupTip.MemberInfo变更的群成员资料信息对象
Msg.Elem.GroupTip.MemberInfo = function (userId, shutupTime) {
this.userId = userId;//群成员id
this.shutupTime = shutupTime;//群成员被禁言时间0表示取消禁言大于0表示被禁言时长单位
};
Msg.Elem.GroupTip.MemberInfo.prototype.getUserId = function () {
return this.userId;
};
Msg.Elem.GroupTip.MemberInfo.prototype.getShutupTime = function () {
return this.shutupTime;
};
// 自定义消息类型 class Msg.Elem.Custom
Msg.Elem.Custom = function (data, desc, ext) {
this.data = data;//数据
this.desc = desc;//描述
this.ext = ext;//扩展字段
};
Msg.Elem.Custom.prototype.getData = function () {
return this.data;
};
Msg.Elem.Custom.prototype.getDesc = function () {
return this.desc;
};
Msg.Elem.Custom.prototype.getExt = function () {
return this.ext;
};
Msg.Elem.Custom.prototype.toHtml = function () {
return this.data;
};
// singleton object MsgStore
var MsgStore = new function () {
var sessMap = {};//跟所有用户或群的聊天记录MAP
var sessTimeline = [];//按时间降序排列的会话列表
msgCache = {};//消息缓存,用于判重
//C2C
this.cookie = "";//上一次拉取新c2c消息的cookie
this.syncFlag = 0;//上一次拉取新c2c消息的是否继续拉取标记
var visitSess = function (visitor) {
for (var i in sessMap) {
visitor(sessMap[i]);
}
};
// window.msgCache = msgCache;
//消息查重
var checkDupMsg = function (msg) {
var dup = false;
var first_key = msg.sess._impl.skey;
var second_key = msg.isSend + msg.seq + msg.random;
var tempMsg = msgCache[first_key] && msgCache[first_key][second_key];
if (tempMsg){
dup = true;
}
if (msgCache[first_key]) {
msgCache[first_key][second_key] = {time: msg.time};
} else {
msgCache[first_key] = {};
msgCache[first_key][second_key] = {time: msg.time};
}
return dup;
};
this.sessMap = function () {
return sessMap;
};
this.sessCount = function () {
return sessTimeline.length;
};
this.sessByTypeId = function (type, id) {
var skey = Session.skey(type, id);
if (skey === undefined || skey == null) return null;
return sessMap[skey];
};
this.delSessByTypeId = function (type, id) {
var skey = Session.skey(type, id);
if (skey === undefined || skey == null) return false;
if (sessMap[skey]) {
delete sessMap[skey];
delete msgCache[skey];
}
return true;
};
this.resetCookieAndSyncFlag = function () {
this.cookie = "";
this.syncFlag = 0;
};
//切换将当前会话的自动读取消息标志为isOn,重置其他会话的自动读取消息标志为false
this.setAutoRead = function (selSess, isOn, isResetAll) {
if (isResetAll)
visitSess(function (s) {
s._impl.isAutoRead = false;
});
if (selSess) {
selSess._impl.isAutoRead = isOn;//
if (isOn) {//是否调用已读上报接口
selSess._impl.unread = 0;
if (selSess._impl.type == SESSION_TYPE.C2C) {//私聊消息已读上报
var tmpC2CMsgReadedItem = [];
tmpC2CMsgReadedItem.push(new C2CMsgReadedItem(selSess._impl.id, selSess._impl.time));
//调用C2C消息已读上报接口
proto_c2CMsgReaded(MsgStore.cookie,
tmpC2CMsgReadedItem,
function (resp) {
log.info("[setAutoRead]: c2CMsgReaded success");
},
function (err) {
log.error("[setAutoRead}: c2CMsgReaded failed:" + err.ErrorInfo);
});
} else if (selSess._impl.type == SESSION_TYPE.GROUP) {//群聊消息已读上报
var tmpOpt = {
'GroupId': selSess._impl.id,
'MsgReadedSeq': selSess._impl.curMaxMsgSeq
};
//调用group消息已读上报接口
proto_groupMsgReaded(tmpOpt,
function (resp) {
log.info("groupMsgReaded success");
},
function (err) {
log.error("groupMsgReaded failed:" + err.ErrorInfo);
});
}
}
}
};
this.c2CMsgReaded = function (opts, cbOk, cbErr) {
var tmpC2CMsgReadedItem = [];
tmpC2CMsgReadedItem.push(new C2CMsgReadedItem(opts.To_Account, opts.LastedMsgTime));
//调用C2C消息已读上报接口
proto_c2CMsgReaded(MsgStore.cookie,
tmpC2CMsgReadedItem,
function (resp) {
if (cbOk) {
log.info("c2CMsgReaded success");
cbOk(resp);
}
},
function (err) {
if (cbErr) {
log.error("c2CMsgReaded failed:" + err.ErrorInfo);
cbErr(err);
}
});
};
this.addSession = function (sess) {
sessMap[sess._impl.skey] = sess;
};
this.delSession = function (sess) {
delete sessMap[sess._impl.skey];
};
this.addMsg = function (msg) {
if (checkDupMsg(msg)) return false;
var sess = msg.sess;
if (!sessMap[sess._impl.skey]) this.addSession(sess);
sess._impl_addMsg(msg);
return true;
};
this.updateTimeline = function () {
var arr = new Array;
visitSess(function (sess) {
arr.push(sess);
});
arr.sort(function (a, b) {
return b.time - a.time;
});
sessTimeline = arr;
};
};
// singleton object MsgManager
var MsgManager = new function () {
var onMsgCallback = null;//新消息(c2c和group)回调
var onGroupInfoChangeCallback = null;//群资料变化回调
//收到新群系统消息回调列表
var onGroupSystemNotifyCallbacks = {
"1": null,
"2": null,
"3": null,
"4": null,
"5": null,
"6": null,
"7": null,
"8": null,
"9": null,
"10": null,
"11": null,
"15": null,
"255": null
};
//监听好友系统通知函数
var onFriendSystemNotifyCallbacks={
"1":null,
"2":null,
"3":null,
"4":null,
"5":null,
"6":null,
"7":null,
"8":null
};
var onProfileSystemNotifyCallbacks= {
"1" :null
};
var onKickedEventCall = null;
var onMsgReadCallback = null;
//普通长轮询
var longPollingOn = false;//是否开启普通长轮询
var isLongPollingRequesting = false;//是否在长轮询ing
var notifySeq = 0;//c2c通知seq
var noticeSeq = 0;//群消息seq
//大群长轮询
var onBigGroupMsgCallback = null;//大群消息回调
var bigGroupLongPollingOn = false;//是否开启长轮询
var bigGroupLongPollingStartSeq = 0;//请求拉消息的起始seq(大群长轮询)
var bigGroupLongPollingHoldTime = 90;//客户端长轮询的超时时间,单位是秒(大群长轮询)
var bigGroupLongPollingKey = null;//客户端加入群组后收到的的Key(大群长轮询)
var bigGroupLongPollingMsgMap = {};//记录收到的群消息数
var getLostGroupMsgCount = 0;//补拉丢失的群消息次数
//我的群当前最大的seq
var myGroupMaxSeqs = {};//用于补拉丢失的群消息
var groupSystemMsgsCache = {};//群组系统消息缓存,用于判重
//设置长轮询开关
//isOn=true 开启
//isOn=false 停止
this.setLongPollingOn = function (isOn) {
longPollingOn = isOn;
};
this.getLongPollingOn = function () {
return longPollingOn;
};
//重置长轮询变量
this.resetLongPollingInfo = function () {
longPollingOn = false;
notifySeq = 0;
noticeSeq = 0;
};
//设置大群长轮询开关
//isOn=true 开启
//isOn=false 停止
this.setBigGroupLongPollingOn = function (isOn) {
bigGroupLongPollingOn = isOn;
};
//设置大群长轮询key
this.setBigGroupLongPollingKey = function (key) {
bigGroupLongPollingKey = key;
};
//重置大群长轮询变量
this.resetBigGroupLongPollingInfo = function () {
bigGroupLongPollingOn = false;
bigGroupLongPollingStartSeq = 0;
bigGroupLongPollingKey = null;
bigGroupLongPollingMsgMap = {};
};
//设置群消息数据条数
this.setBigGroupLongPollingMsgMap = function (groupId, count) {
var bigGroupLongPollingMsgCount = bigGroupLongPollingMsgMap[groupId];
if (bigGroupLongPollingMsgCount) {
bigGroupLongPollingMsgCount = parseInt(bigGroupLongPollingMsgCount) + count;
bigGroupLongPollingMsgMap[groupId] = bigGroupLongPollingMsgCount;
} else {
bigGroupLongPollingMsgMap[groupId] = count;
}
};
//重置
this.clear = function () {
onGroupInfoChangeCallback = null;
onGroupSystemNotifyCallbacks = {
"1": null,//申请加群请求(只有管理员会收到)
"2": null,//申请加群被同意(只有申请人能够收到)
"3": null,//申请加群被拒绝(只有申请人能够收到)
"4": null,//被管理员踢出群(只有被踢者接收到)
"5": null,//群被解散(全员接收)
"6": null,//创建群(创建者接收)
"7": null,//邀请加群(被邀请者接收)
"8": null,//主动退群(主动退出者接收)
"9": null,//设置管理员(被设置者接收)
"10": null,//取消管理员(被取消者接收)
"11": null,//群已被回收(全员接收)
"15": null,//群已被回收(全员接收)
"255": null//用户自定义通知(默认全员接收)
};
onFriendSystemNotifyCallbacks = {
"1": null,//好友表增加
"2": null,//好友表删除
"3": null,//未决增加
"4": null,//未决删除
"5": null,//黑名单增加
"6": null,//黑名单删除
"7": null,//未决已读上报
"8": null//好友信息(备注,分组)变更
};
onProfileSystemNotifyCallbacks = {
"1": null//资料修改
};
//重置普通长轮询参数
onMsgCallback = null;
longPollingOn = false;
notifySeq = 0;//c2c新消息通知seq
noticeSeq = 0;//group新消息seq
//重置大群长轮询参数
onBigGroupMsgCallback = null;
bigGroupLongPollingOn = false;
bigGroupLongPollingStartSeq = 0;
bigGroupLongPollingKey = null;
bigGroupLongPollingMsgMap = {};
groupSystemMsgsCache = {};
ipList = [];//文件下载地址
authkey = null;//文件下载票据
expireTime = null;//票据超时时间
};
//初始化文件下载ip和票据
var initIpAndAuthkey = function (cbOk, cbErr) {
proto_getIpAndAuthkey(function (resp) {
ipList = resp.IpList;
authkey = resp.AuthKey;
expireTime = resp.ExpireTime;
if (cbOk) cbOk(resp);
},
function (err) {
log.error("initIpAndAuthkey failed:" + err.ErrorInfo);
if (cbErr) cbErr(err);
}
);
};
//初始化我的群当前最大的seq用于补拉丢失的群消息
var initMyGroupMaxSeqs = function (cbOk, cbErr) {
var opts = {
'Member_Account': ctx.identifier,
'Limit': 1000,
'Offset': 0,
'GroupBaseInfoFilter': [
'NextMsgSeq'
]
};
proto_getJoinedGroupListHigh(opts, function (resp) {
if (!resp.GroupIdList || resp.GroupIdList.length == 0) {
log.info("initMyGroupMaxSeqs: 目前还没有加入任何群组");
if (cbOk) cbOk(resp);
return;
}
for (var i = 0; i < resp.GroupIdList.length; i++) {
var group_id = resp.GroupIdList[i].GroupId;
var curMaxSeq = resp.GroupIdList[i].NextMsgSeq - 1;
myGroupMaxSeqs[group_id] = curMaxSeq;
}
if (cbOk) cbOk(resp);
},
function (err) {
log.error("initMyGroupMaxSeqs failed:" + err.ErrorInfo);
if (cbErr) cbErr(err);
}
);
};
//补拉群消息
var getLostGroupMsgs = function (groupId, reqMsgSeq, reqMsgNumber) {
getLostGroupMsgCount++;
//发起一个拉群群消息请求
var tempOpts = {
'GroupId': groupId,
'ReqMsgSeq': reqMsgSeq,
'ReqMsgNumber': reqMsgNumber
};
//发起一个拉群群消息请求
log.warn("第" + getLostGroupMsgCount + "次补齐群消息,参数=" + JSON.stringify(tempOpts));
MsgManager.syncGroupMsgs(tempOpts);
};
//更新群当前最大消息seq
var updateMyGroupCurMaxSeq=function(groupId,msgSeq){
//更新myGroupMaxSeqs中的群最大seq
var curMsgSeq=myGroupMaxSeqs[groupId]
if(curMsgSeq){//如果存在,比较大小
if(msgSeq>curMsgSeq){
myGroupMaxSeqs[groupId]=msgSeq;
}
}else{//不存在,新增
myGroupMaxSeqs[groupId]=msgSeq;
}
};
//添加群消息列表
var addGroupMsgList = function (msgs, new_group_msgs) {
for (var p in msgs) {
var newGroupMsg = msgs[p];
//发群消息时,长轮询接口会返回用户自己发的群消息
//if(newGroupMsg.From_Account && newGroupMsg.From_Account!=ctx.identifier ){
if (newGroupMsg.From_Account) {
//false-不是主动拉取的历史消息
//true-需要保存到sdk本地session,并且需要判重
var msg = handlerGroupMsg(newGroupMsg, false, true);
if (msg) {//不为空,加到新消息里
new_group_msgs.push(msg);
}
//更新myGroupMaxSeqs中的群最大seq
updateMyGroupCurMaxSeq(newGroupMsg.ToGroupId,newGroupMsg.MsgSeq);
}
}
return new_group_msgs;
};
//处理收到的群普通和提示消息
var handlerOrdinaryAndTipC2cMsgs = function (eventType, groupMsgArray) {
var groupMsgMap = {};//保存收到的C2c消息信息群号最小最大消息seq消息列表
var new_group_msgs = [];
var minGroupMsgSeq = 99999999;
var maxGroupMsgSeq = -1;
for (var j in groupMsgArray) {
var groupMsgs = groupMsgMap[groupMsgArray[j].ToGroupId];
if (!groupMsgs) {
groupMsgs = groupMsgMap[groupMsgArray[j].ToGroupId] = {
"min": minGroupMsgSeq,//收到新消息最小seq
"max": maxGroupMsgSeq,//收到新消息最大seq
"msgs": []//收到的新消息
};
}
//更新长轮询的群NoticeSeq
if (groupMsgArray[j].NoticeSeq > noticeSeq) {
log.warn("noticeSeq=" + noticeSeq + ",msgNoticeSeq=" + groupMsgArray[j].NoticeSeq);
noticeSeq = groupMsgArray[j].NoticeSeq;
}
groupMsgArray[j].Event = eventType;
groupMsgMap[groupMsgArray[j].ToGroupId].msgs.push(groupMsgArray[j]);//新增一条消息
if (groupMsgArray[j].MsgSeq < groupMsgs.min) {//记录最小的消息seq
groupMsgMap[groupMsgArray[j].ToGroupId].min = groupMsgArray[j].MsgSeq;
}
if (groupMsgArray[j].MsgSeq > groupMsgs.max) {//记录最大的消息seq
groupMsgMap[groupMsgArray[j].ToGroupId].max = groupMsgArray[j].MsgSeq;
}
}
for (var groupId in groupMsgMap) {
var tempCount = groupMsgMap[groupId].max - groupMsgMap[groupId].min + 1;//收到的新的群消息数
var curMaxMsgSeq = myGroupMaxSeqs[groupId];//获取本地保存的群最大消息seq
if (curMaxMsgSeq) {//存在这个群的最大消息seq
//高并发情况下,长轮询可能存在丢消息,这时需要客户端通过拉取群消息接口补齐下
//1、如果收到的新消息最小seq比当前最大群消息seq大于1则表示收到的群消息发生跳跃需要补齐
//2、收到的新群消息seq存在不连续情况也需要补齐
if (groupMsgMap[groupId].min - curMaxMsgSeq > 1 || groupMsgMap[groupId].msgs.length < tempCount) {
//发起一个拉群群消息请求
log.warn("发起一次补齐群消息请求,curMaxMsgSeq=" + curMaxMsgSeq + ", minMsgSeq=" + groupMsgMap[groupId].min + ", maxMsgSeq=" + groupMsgMap[groupId].max + ", msgs.length=" + groupMsgMap[groupId].msgs.length + ", tempCount=" + tempCount);
getLostGroupMsgs(groupId, groupMsgMap[groupId].max, groupMsgMap[groupId].max - curMaxMsgSeq);
//更新myGroupMaxSeqs中的群最大seq
updateMyGroupCurMaxSeq(groupId,groupMsgMap[groupId].max);
} else {
new_group_msgs = addGroupMsgList(groupMsgMap[groupId].msgs, new_group_msgs);
}
} else {//不存在该群的最大消息seq
log.warn("不存在该群的最大消息seq群id=" + groupId);
//高并发情况下,长轮询可能存在丢消息,这时需要客户端通过拉取群消息接口补齐下
//1、收到的新群消息seq存在不连续情况也需要补齐
if (groupMsgMap[groupId].msgs.length < tempCount) {
//发起一个拉群群消息请求
log.warn("发起一次补齐群消息请求,minMsgSeq=" + groupMsgMap[groupId].min + ", maxMsgSeq=" + groupMsgMap[groupId].max + ", msgs.length=" + groupMsgMap[groupId].msgs.length + ", tempCount=" + tempCount);
getLostGroupMsgs(groupId, groupMsgMap[groupId].max, tempCount);
//更新myGroupMaxSeqs中的群最大seq
updateMyGroupCurMaxSeq(groupId,groupMsgMap[groupId].max);
} else {
new_group_msgs = addGroupMsgList(groupMsgMap[groupId].msgs, new_group_msgs);
}
}
}
if (new_group_msgs.length) {
MsgStore.updateTimeline();
}
if (onMsgCallback && new_group_msgs.length) onMsgCallback(new_group_msgs);
};
//处理收到的群普通和提示消息
var handlerOrdinaryAndTipGroupMsgs = function (eventType, groupMsgArray) {
var groupMsgMap = {};//保存收到的群消息信息群号最小最大消息seq消息列表
var new_group_msgs = [];
var minGroupMsgSeq = 99999999;
var maxGroupMsgSeq = -1;
for (var j in groupMsgArray) {
var groupMsgs = groupMsgMap[groupMsgArray[j].ToGroupId];
if (!groupMsgs) {
groupMsgs = groupMsgMap[groupMsgArray[j].ToGroupId] = {
"min": minGroupMsgSeq,//收到新消息最小seq
"max": maxGroupMsgSeq,//收到新消息最大seq
"msgs": []//收到的新消息
};
}
//更新长轮询的群NoticeSeq
if (groupMsgArray[j].NoticeSeq > noticeSeq) {
log.warn("noticeSeq=" + noticeSeq + ",msgNoticeSeq=" + groupMsgArray[j].NoticeSeq);
noticeSeq = groupMsgArray[j].NoticeSeq;
}
groupMsgArray[j].Event = eventType;
groupMsgMap[groupMsgArray[j].ToGroupId].msgs.push(groupMsgArray[j]);//新增一条消息
if (groupMsgArray[j].MsgSeq < groupMsgs.min) {//记录最小的消息seq
groupMsgMap[groupMsgArray[j].ToGroupId].min = groupMsgArray[j].MsgSeq;
}
if (groupMsgArray[j].MsgSeq > groupMsgs.max) {//记录最大的消息seq
groupMsgMap[groupMsgArray[j].ToGroupId].max = groupMsgArray[j].MsgSeq;
}
}
for (var groupId in groupMsgMap) {
var tempCount = groupMsgMap[groupId].max - groupMsgMap[groupId].min + 1;//收到的新的群消息数
var curMaxMsgSeq = myGroupMaxSeqs[groupId];//获取本地保存的群最大消息seq
if (curMaxMsgSeq) {//存在这个群的最大消息seq
//高并发情况下,长轮询可能存在丢消息,这时需要客户端通过拉取群消息接口补齐下
//1、如果收到的新消息最小seq比当前最大群消息seq大于1则表示收到的群消息发生跳跃需要补齐
//2、收到的新群消息seq存在不连续情况也需要补齐
if (groupMsgMap[groupId].min - curMaxMsgSeq > 1 || groupMsgMap[groupId].msgs.length < tempCount) {
//发起一个拉群群消息请求
log.warn("发起一次补齐群消息请求,curMaxMsgSeq=" + curMaxMsgSeq + ", minMsgSeq=" + groupMsgMap[groupId].min + ", maxMsgSeq=" + groupMsgMap[groupId].max + ", msgs.length=" + groupMsgMap[groupId].msgs.length + ", tempCount=" + tempCount);
getLostGroupMsgs(groupId, groupMsgMap[groupId].max, groupMsgMap[groupId].max - curMaxMsgSeq);
//更新myGroupMaxSeqs中的群最大seq
updateMyGroupCurMaxSeq(groupId,groupMsgMap[groupId].max);
} else {
new_group_msgs = addGroupMsgList(groupMsgMap[groupId].msgs, new_group_msgs);
}
} else {//不存在该群的最大消息seq
log.warn("不存在该群的最大消息seq群id=" + groupId);
//高并发情况下,长轮询可能存在丢消息,这时需要客户端通过拉取群消息接口补齐下
//1、收到的新群消息seq存在不连续情况也需要补齐
if (groupMsgMap[groupId].msgs.length < tempCount) {
//发起一个拉群群消息请求
log.warn("发起一次补齐群消息请求,minMsgSeq=" + groupMsgMap[groupId].min + ", maxMsgSeq=" + groupMsgMap[groupId].max + ", msgs.length=" + groupMsgMap[groupId].msgs.length + ", tempCount=" + tempCount);
getLostGroupMsgs(groupId, groupMsgMap[groupId].max, tempCount);
//更新myGroupMaxSeqs中的群最大seq
updateMyGroupCurMaxSeq(groupId,groupMsgMap[groupId].max);
} else {
new_group_msgs = addGroupMsgList(groupMsgMap[groupId].msgs, new_group_msgs);
}
}
}
if (new_group_msgs.length) {
MsgStore.updateTimeline();
}
if (onMsgCallback && new_group_msgs.length) onMsgCallback(new_group_msgs);
};
//处理新的群提示消息
var handlerGroupTips = function (groupTips) {
var new_group_msgs = [];
for (var o in groupTips) {
var groupTip = groupTips[o];
//添加event字段
groupTip.Event = LONG_POLLINNG_EVENT_TYPE.GROUP_TIP;
//更新群消息通知seq
if (groupTip.NoticeSeq > noticeSeq) {
noticeSeq = groupTip.NoticeSeq;
}
var msg = handlerGroupMsg(groupTip, false, true);
if (msg) {
new_group_msgs.push(msg);
}
}
if (new_group_msgs.length) {
MsgStore.updateTimeline();
}
if (onMsgCallback && new_group_msgs.length) onMsgCallback(new_group_msgs);
};
//处理新的群系统消息
//isNeedValidRepeatMsg 是否需要判重
var handlerGroupSystemMsgs = function (groupSystemMsgs, isNeedValidRepeatMsg) {
for (var k in groupSystemMsgs) {
var groupTip = groupSystemMsgs[k];
var groupReportTypeMsg = groupTip.MsgBody;
var reportType = groupReportTypeMsg.ReportType;
//当长轮询返回的群系统消息才需要更新群消息通知seq
if (isNeedValidRepeatMsg == false && groupTip.NoticeSeq && groupTip.NoticeSeq > noticeSeq) {
noticeSeq = groupTip.NoticeSeq;
}
var toAccount = groupTip.GroupInfo.To_Account;
//过滤本不应该给自己的系统消息
/*if (!toAccount || toAccount != ctx.identifier) {
log.error("收到本不应该给自己的系统消息: To_Account=" + toAccount);
continue;
}*/
if (isNeedValidRepeatMsg) {
//var key=groupTip.ToGroupId+"_"+reportType+"_"+groupTip.MsgTimeStamp+"_"+groupReportTypeMsg.Operator_Account;
var key = groupTip.ToGroupId + "_" + reportType + "_" + groupReportTypeMsg.Operator_Account;
var isExist = groupSystemMsgsCache[key];
if (isExist) {
log.warn("收到重复的群系统消息key=" + key);
continue;
}
groupSystemMsgsCache[key] = true;
}
var notify = {
"SrcFlag": 0,
"ReportType": reportType,
"GroupId": groupTip.ToGroupId,
"GroupName": groupTip.GroupInfo.GroupName,
"Operator_Account": groupReportTypeMsg.Operator_Account,
"MsgTime": groupTip.MsgTimeStamp,
"groupReportTypeMsg" : groupReportTypeMsg
};
switch (reportType) {
case GROUP_SYSTEM_TYPE.JOIN_GROUP_REQUEST://申请加群(只有管理员会接收到)
notify["RemarkInfo"] = groupReportTypeMsg.RemarkInfo;
notify["MsgKey"] = groupReportTypeMsg.MsgKey;
notify["Authentication"] = groupReportTypeMsg.Authentication;
notify["UserDefinedField"] = groupTip.UserDefinedField;
notify["From_Account"] = groupTip.From_Account;
notify["MsgSeq"] = groupTip.ClientSeq;
notify["MsgRandom"] = groupTip.MsgRandom;
break;
case GROUP_SYSTEM_TYPE.JOIN_GROUP_ACCEPT://申请加群被同意(只有申请人自己接收到)
case GROUP_SYSTEM_TYPE.JOIN_GROUP_REFUSE://申请加群被拒绝(只有申请人自己接收到)
notify["RemarkInfo"] = groupReportTypeMsg.RemarkInfo;
break;
case GROUP_SYSTEM_TYPE.KICK://被管理员踢出群(只有被踢者接收到)
case GROUP_SYSTEM_TYPE.DESTORY://群被解散(全员接收)
case GROUP_SYSTEM_TYPE.CREATE://创建群(创建者接收, 不展示)
case GROUP_SYSTEM_TYPE.INVITED_JOIN_GROUP_REQUEST://邀请加群(被邀请者接收)
case GROUP_SYSTEM_TYPE.QUIT://主动退群(主动退出者接收, 不展示)
case GROUP_SYSTEM_TYPE.SET_ADMIN://群设置管理员(被设置者接收)
case GROUP_SYSTEM_TYPE.CANCEL_ADMIN://取消管理员(被取消者接收)
case GROUP_SYSTEM_TYPE.REVOKE://群已被回收(全员接收, 不展示)
break;
case GROUP_SYSTEM_TYPE.READED://群消息已读同步
break;
case GROUP_SYSTEM_TYPE.CUSTOM://用户自定义通知(默认全员接收)
notify["MsgSeq"] = groupTip.MsgSeq;
notify["UserDefinedField"] = groupReportTypeMsg.UserDefinedField;
break;
default:
log.error("未知群系统消息类型reportType=" + reportType);
break;
}
if (isNeedValidRepeatMsg) {
if (reportType == GROUP_SYSTEM_TYPE.JOIN_GROUP_REQUEST) {
//回调
if (onGroupSystemNotifyCallbacks[reportType]) onGroupSystemNotifyCallbacks[reportType](notify);
}
} else {
//回调
if (onGroupSystemNotifyCallbacks[reportType]) {
if(reportType == GROUP_SYSTEM_TYPE.READED){
var arr = notify.groupReportTypeMsg.GroupReadInfoArray;
for(var i = 0 , l = arr.length; i < l ; i++){
var item = arr[i];
onGroupSystemNotifyCallbacks[reportType](item);
}
}else{
onGroupSystemNotifyCallbacks[reportType](notify);
}
}
}
}//loop
};
//处理新的好友系统通知
//isNeedValidRepeatMsg 是否需要判重
var handlerFriendSystemNotices = function (friendSystemNotices, isNeedValidRepeatMsg) {
var friendNotice, type, notify;
for (var k in friendSystemNotices) {
friendNotice = friendSystemNotices[k];
type = friendNotice.PushType;
//当长轮询返回的群系统消息才需要更新通知seq
if (isNeedValidRepeatMsg == false && friendNotice.NoticeSeq && friendNotice.NoticeSeq > noticeSeq) {
noticeSeq = friendNotice.NoticeSeq;
}
notify = {'Type': type};
switch (type) {
case FRIEND_NOTICE_TYPE.FRIEND_ADD://好友表增加
notify["Accounts"] = friendNotice.FriendAdd_Account;
break;
case FRIEND_NOTICE_TYPE.FRIEND_DELETE://好友表删除
notify["Accounts"] = friendNotice.FriendDel_Account;
break;
case FRIEND_NOTICE_TYPE.PENDENCY_ADD://未决增加
notify["PendencyList"] = friendNotice.PendencyAdd;
break;
case FRIEND_NOTICE_TYPE.PENDENCY_DELETE://未决删除
notify["Accounts"] = friendNotice.FrienPencydDel_Account;
break;
case FRIEND_NOTICE_TYPE.BLACK_LIST_ADD://黑名单增加
notify["Accounts"] = friendNotice.BlackListAdd_Account;
break;
case FRIEND_NOTICE_TYPE.BLACK_LIST_DELETE://黑名单删除
notify["Accounts"] = friendNotice.BlackListDel_Account;
break;
/*case FRIEND_NOTICE_TYPE.PENDENCY_REPORT://未决已读上报
break;
case FRIEND_NOTICE_TYPE.FRIEND_UPDATE://好友数据更新
break;
*/
default:
log.error("未知好友系统通知类型friendNotice=" + JSON.stringify(friendNotice));
break;
}
if (isNeedValidRepeatMsg) {
if (type == FRIEND_NOTICE_TYPE.PENDENCY_ADD) {
//回调
if (onFriendSystemNotifyCallbacks[type]) onFriendSystemNotifyCallbacks[type](notify);
}
} else {
//回调
if (onFriendSystemNotifyCallbacks[type]) onFriendSystemNotifyCallbacks[type](notify);
}
}//loop
};
//处理新的资料系统通知
//isNeedValidRepeatMsg 是否需要判重
var handlerProfileSystemNotices = function (profileSystemNotices, isNeedValidRepeatMsg) {
var profileNotice, type, notify;
for (var k in profileSystemNotices) {
profileNotice = profileSystemNotices[k];
type = profileNotice.PushType;
//当长轮询返回的群系统消息才需要更新通知seq
if (isNeedValidRepeatMsg == false && profileNotice.NoticeSeq && profileNotice.NoticeSeq > noticeSeq) {
noticeSeq = profileNotice.NoticeSeq;
}
notify = {'Type': type};
switch (type) {
case PROFILE_NOTICE_TYPE.PROFILE_MODIFY://资料修改
notify["Profile_Account"] = profileNotice.Profile_Account;
notify["ProfileList"] = profileNotice.ProfileList;
break;
default:
log.error("未知资料系统通知类型profileNotice=" + JSON.stringify(profileNotice));
break;
}
if (isNeedValidRepeatMsg) {
if (type == PROFILE_NOTICE_TYPE.PROFILE_MODIFY) {
//回调
if (onProfileSystemNotifyCallbacks[type]) onProfileSystemNotifyCallbacks[type](notify);
}
} else {
//回调
if (onProfileSystemNotifyCallbacks[type]) onProfileSystemNotifyCallbacks[type](notify);
}
}//loop
};
//处理新的群系统消息(用于直播大群长轮询)
var handlerGroupSystemMsg = function (groupTip) {
var groupReportTypeMsg = groupTip.MsgBody;
var reportType = groupReportTypeMsg.ReportType;
var toAccount = groupTip.GroupInfo.To_Account;
//过滤本不应该给自己的系统消息
//if(!toAccount || toAccount!=ctx.identifier){
// log.error("收到本不应该给自己的系统消息: To_Account="+toAccount);
// continue;
//}
var notify = {
"SrcFlag": 1,
"ReportType": reportType,
"GroupId": groupTip.ToGroupId,
"GroupName": groupTip.GroupInfo.GroupName,
"Operator_Account": groupReportTypeMsg.Operator_Account,
"MsgTime": groupTip.MsgTimeStamp
};
switch (reportType) {
case GROUP_SYSTEM_TYPE.JOIN_GROUP_REQUEST://申请加群(只有管理员会接收到)
notify["RemarkInfo"] = groupReportTypeMsg.RemarkInfo;
notify["MsgKey"] = groupReportTypeMsg.MsgKey;
notify["Authentication"] = groupReportTypeMsg.Authentication;
notify["UserDefinedField"] = groupTip.UserDefinedField;
notify["From_Account"] = groupTip.From_Account;
notify["MsgSeq"] = groupTip.ClientSeq;
notify["MsgRandom"] = groupTip.MsgRandom;
break;
case GROUP_SYSTEM_TYPE.JOIN_GROUP_ACCEPT://申请加群被同意(只有申请人自己接收到)
case GROUP_SYSTEM_TYPE.JOIN_GROUP_REFUSE://申请加群被拒绝(只有申请人自己接收到)
notify["RemarkInfo"] = groupReportTypeMsg.RemarkInfo;
break;
case GROUP_SYSTEM_TYPE.KICK://被管理员踢出群(只有被踢者接收到)
case GROUP_SYSTEM_TYPE.DESTORY://群被解散(全员接收)
case GROUP_SYSTEM_TYPE.CREATE://创建群(创建者接收, 不展示)
case GROUP_SYSTEM_TYPE.INVITED_JOIN_GROUP_REQUEST://邀请加群(被邀请者接收)
case GROUP_SYSTEM_TYPE.QUIT://主动退群(主动退出者接收, 不展示)
case GROUP_SYSTEM_TYPE.SET_ADMIN://群设置管理员(被设置者接收)
case GROUP_SYSTEM_TYPE.CANCEL_ADMIN://取消管理员(被取消者接收)
case GROUP_SYSTEM_TYPE.REVOKE://群已被回收(全员接收, 不展示)
break;
case GROUP_SYSTEM_TYPE.CUSTOM://用户自定义通知(默认全员接收)
notify["MsgSeq"] = groupTip.MsgSeq;
notify["UserDefinedField"] = groupReportTypeMsg.UserDefinedField;
break;
default:
log.error("未知群系统消息类型reportType=" + reportType);
break;
}
//回调
if (onGroupSystemNotifyCallbacks[reportType]) onGroupSystemNotifyCallbacks[reportType](notify);
};
//处理C2C EVENT 消息通道Array
var handlerC2cNotifyMsgArray = function(arr){
for(var i =0,l=arr.length; i<l ;i++){
handlerC2cEventMsg(arr[i]);
}
}
//处理C2C EVENT 消息通道Item
var handlerC2cEventMsg = function (notify) {
var subType = notify.SubMsgType;
switch (subType) {
case C2C_EVENT_SUB_TYPE.READED://已读通知
break;
default:
log.error("未知C2c系统消息reportType=" + reportType);
break;
}
// stopPolling = true;
//回调onMsgReadCallback
if(notify.ReadC2cMsgNotify.UinPairReadArray && onC2cEventCallbacks[subType]){
for(var i = 0 ,l = notify.ReadC2cMsgNotify.UinPairReadArray.length; i < l ; i++){
var item = notify.ReadC2cMsgNotify.UinPairReadArray[i];
onC2cEventCallbacks[subType](item);
}
}
};
//长轮询
this.longPolling = function (cbOk, cbErr) {
var opts = {
'Timeout': longPollingDefaultTimeOut/1000,
'Cookie': {
'NotifySeq': notifySeq,
'NoticeSeq': noticeSeq
}
};
if(LongPollingId){
opts.Cookie.LongPollingId = LongPollingId;
doPolling();
}else{
proto_getLongPollingId({},function(resp){
LongPollingId = opts.Cookie.LongPollingId = resp.LongPollingId;
//根据回包设置超时时间,超时时长不能>60秒因为webkit手机端的最长超时时间不能大于60s
longPollingDefaultTimeOut = resp.Timeout > 60 ? longPollingDefaultTimeOut : resp.Timeout * 1000 ;
doPolling();
});
}
function doPolling(){
proto_longPolling(opts, function (resp) {
for (var i in resp.EventArray) {
var e = resp.EventArray[i];
switch (e.Event) {
case LONG_POLLINNG_EVENT_TYPE.C2C://c2c消息通知
//更新C2C消息通知seq
notifySeq = e.NotifySeq;
log.warn("longpolling: received new c2c msg");
//获取新消息
MsgManager.syncMsgs();
break;
case LONG_POLLINNG_EVENT_TYPE.GROUP_COMMON://普通群消息通知
log.warn("longpolling: received new group msgs");
handlerOrdinaryAndTipGroupMsgs(e.Event, e.GroupMsgArray);
break;
case LONG_POLLINNG_EVENT_TYPE.GROUP_TIP://(全员广播)群提示消息
log.warn("longpolling: received new group tips");
handlerOrdinaryAndTipGroupMsgs(e.Event, e.GroupTips);
break;
case LONG_POLLINNG_EVENT_TYPE.GROUP_SYSTEM://(多终端同步)群系统消息
log.warn("longpolling: received new group system msgs");
//false 表示 通过长轮询收到的群系统消息,可以不判重
handlerGroupSystemMsgs(e.GroupTips, false);
break;
case LONG_POLLINNG_EVENT_TYPE.FRIEND_NOTICE://好友系统通知
log.warn("longpolling: received new friend system notice");
//false 表示 通过长轮询收到的好友系统通知,可以不判重
handlerFriendSystemNotices(e.FriendListMod, false);
break;
case LONG_POLLINNG_EVENT_TYPE.PROFILE_NOTICE://资料系统通知
log.warn("longpolling: received new profile system notice");
//false 表示 通过长轮询收到的资料系统通知,可以不判重
handlerProfileSystemNotices(e.ProfileDataMod, false);
break;
case LONG_POLLINNG_EVENT_TYPE.C2C_COMMON://c2c消息通知
noticeSeq = e.C2cMsgArray[0].NoticeSeq;
//更新C2C消息通知seq
log.warn("longpolling: received new c2c_common msg",noticeSeq);
handlerOrdinaryAndTipC2cMsgs(e.Event, e.C2cMsgArray);
break;
case LONG_POLLINNG_EVENT_TYPE.C2C_EVENT://c2c已读消息通知
noticeSeq = e.C2cNotifyMsgArray[0].NoticeSeq;
log.warn("longpolling: received new c2c_event msg");
handlerC2cNotifyMsgArray(e.C2cNotifyMsgArray);
break;
default:
log.error("longpolling收到未知新消息类型: Event=" + e.Event);
break;
}
}
var successInfo = {
'ActionStatus': ACTION_STATUS.OK,
'ErrorCode': 0
};
updatecLongPollingStatus(successInfo);
}, function (err) {
//log.error(err);
updatecLongPollingStatus(err);
if (cbErr) cbErr(err);
});
}
};
//大群 长轮询
this.bigGroupLongPolling = function (cbOk, cbErr) {
var opts = {
'StartSeq': bigGroupLongPollingStartSeq,//请求拉消息的起始seq
'HoldTime': bigGroupLongPollingHoldTime,//客户端长轮询的超时时间,单位是秒
'Key': bigGroupLongPollingKey//客户端加入群组后收到的的Key
};
proto_bigGroupLongPolling(opts, function (resp) {
var msgObjList = [];
bigGroupLongPollingStartSeq = resp.NextSeq;
bigGroupLongPollingHoldTime = resp.HoldTime;
bigGroupLongPollingKey = resp.Key;
if (resp.RspMsgList && resp.RspMsgList.length > 0) {
var msgCount = 0, msgInfo, event, msg;
for (var i = resp.RspMsgList.length - 1; i >= 0; i--) {
msgInfo = resp.RspMsgList[i];
//如果是已经删除的消息或者发送者帐号为空或者消息内容为空
//IsPlaceMsg=1
if (msgInfo.IsPlaceMsg || !msgInfo.From_Account || !msgInfo.MsgBody || msgInfo.MsgBody.length == 0) {
continue;
}
event = msgInfo.Event;//群消息类型
switch (event) {
case LONG_POLLINNG_EVENT_TYPE.GROUP_COMMON://群普通消息
log.info("bigGroupLongPolling: return new group msg");
msg = handlerGroupMsg(msgInfo, false, false);
msg && msgObjList.push(msg);
msgCount = msgCount + 1;
break;
case LONG_POLLINNG_EVENT_TYPE.GROUP_TIP://群提示消息
case LONG_POLLINNG_EVENT_TYPE.GROUP_TIP2://群提示消息
log.info("bigGroupLongPolling: return new group tip");
msg = handlerGroupMsg(msgInfo, false, false);
msg && msgObjList.push(msg);
//msgCount=msgCount+1;
break;
case LONG_POLLINNG_EVENT_TYPE.GROUP_SYSTEM://群系统消息
log.info("bigGroupLongPolling: new group system msg");
handlerGroupSystemMsg(msgInfo);
break;
default:
log.error("bigGroupLongPolling收到未知新消息类型: Event=" + event);
break;
}
} // for loop
if (msgCount > 0) {
MsgManager.setBigGroupLongPollingMsgMap(msgInfo.ToGroupId, msgCount);//
log.warn("current bigGroupLongPollingMsgMap: " + JSON.stringify(bigGroupLongPollingMsgMap));
}
}
curBigGroupLongPollingRetErrorCount = 0;
//返回连接状态
var successInfo = {
'ActionStatus': ACTION_STATUS.OK,
'ErrorCode': CONNECTION_STATUS.ON,
'ErrorInfo': 'connection is ok...'
};
ConnManager.callBack(successInfo);
if (cbOk) cbOk(msgObjList);
else if (onBigGroupMsgCallback) onBigGroupMsgCallback(msgObjList);//返回新消息
//重新启动长轮询
bigGroupLongPollingOn && MsgManager.bigGroupLongPolling();
}, function (err) {
//
if (err.ErrorCode != longPollingTimeOutErrorCode) {
log.error(err.ErrorInfo);
//记录长轮询返回错误次数
curBigGroupLongPollingRetErrorCount++;
}
if (err.ErrorCode != longPollingKickedErrorCode) {
//登出
log.error("多实例登录被kick");
if (onKickedEventCall) {onKickedEventCall();}
/* return;
proto_logout(function(){
if (onKickedEventCall) {onKickedEventCall();}
});*/
}
//累计超过一定次数,不再发起长轮询请求
if (curBigGroupLongPollingRetErrorCount < LONG_POLLING_MAX_RET_ERROR_COUNT) {
bigGroupLongPollingOn && MsgManager.bigGroupLongPolling();
} else {
var errInfo = {
'ActionStatus': ACTION_STATUS.FAIL,
'ErrorCode': CONNECTION_STATUS.OFF,
'ErrorInfo': 'connection is off'
};
ConnManager.callBack(errInfo);
}
if (cbErr) cbErr(err);
}, bigGroupLongPollingHoldTime * 1000);
};
//更新连接状态
var updatecLongPollingStatus = function (errObj) {
if (errObj.ErrorCode == 0 || errObj.ErrorCode == longPollingTimeOutErrorCode) {
curLongPollingRetErrorCount = 0;
longPollingOffCallbackFlag = false;
var errorInfo;
var isNeedCallback = false;
switch (curLongPollingStatus) {
case CONNECTION_STATUS.INIT:
isNeedCallback = true;
curLongPollingStatus = CONNECTION_STATUS.ON;
errorInfo = "create connection successfully(INIT->ON)";
break;
case CONNECTION_STATUS.ON:
errorInfo = "connection is on...(ON->ON)";
break;
case CONNECTION_STATUS.RECONNECT:
curLongPollingStatus = CONNECTION_STATUS.ON;
errorInfo = "connection is on...(RECONNECT->ON)";
break;
case CONNECTION_STATUS.OFF:
isNeedCallback = true;
curLongPollingStatus = CONNECTION_STATUS.RECONNECT;
errorInfo = "reconnect successfully(OFF->RECONNECT)";
break;
}
var successInfo = {
'ActionStatus': ACTION_STATUS.OK,
'ErrorCode': curLongPollingStatus,
'ErrorInfo': errorInfo
};
isNeedCallback && ConnManager.callBack(successInfo);
longPollingOn && MsgManager.longPolling();
} else if( errObj.ErrorCode == longPollingKickedErrorCode){
//登出
log.error("多实例登录被kick");
if (onKickedEventCall) {onKickedEventCall();}
// return;
// proto_logout(function(){
// if (onKickedEventCall) {onKickedEventCall();}
// });
}else {
//记录长轮询返回解析json错误次数
curLongPollingRetErrorCount++;
log.warn("longPolling接口第" + curLongPollingRetErrorCount + "次报错: " + errObj.ErrorInfo);
//累计超过一定次数
if (curLongPollingRetErrorCount <= LONG_POLLING_MAX_RET_ERROR_COUNT) {
setTimeout(startNextLongPolling, 100);//
} else {
curLongPollingStatus = CONNECTION_STATUS.OFF;
var errInfo = {
'ActionStatus': ACTION_STATUS.FAIL,
'ErrorCode': CONNECTION_STATUS.OFF,
'ErrorInfo': 'connection is off'
};
longPollingOffCallbackFlag == false && ConnManager.callBack(errInfo);
longPollingOffCallbackFlag = true;
log.warn(longPollingIntervalTime + "毫秒之后,SDK会发起新的longPolling请求...");
setTimeout(startNextLongPolling, longPollingIntervalTime);//长轮询接口报错次数达到一定值每间隔5s发起新的长轮询
}
}
};
//处理收到的普通C2C消息
var handlerOrdinaryAndTipC2cMsgs = function (eventType, C2cMsgArray) {
//处理c2c消息
console.log('处理收到的普通C2C消息',C2cMsgArray)
var notifyInfo = [];
var msgInfos = [];
msgInfos = C2cMsgArray; //返回的消息列表
// MsgStore.cookie = resp.Cookie;//cookies记录当前读到的最新消息位置
for (var i in msgInfos) {
var msgInfo = msgInfos[i];
var isSendMsg, id, headUrl;
if (msgInfo.From_Account == ctx.identifier) {//当前用户发送的消息
isSendMsg = true;
id = msgInfo.To_Account;//读取接收者信息
headUrl = '';
} else {//当前用户收到的消息
isSendMsg = false;
id = msgInfo.From_Account;//读取发送者信息
headUrl = '';
}
var sess = MsgStore.sessByTypeId(SESSION_TYPE.C2C, id);
if (!sess) {
sess = new Session(SESSION_TYPE.C2C, id, id, headUrl, 0, 0);
}
var msg = new Msg(sess, isSendMsg, msgInfo.MsgSeq, msgInfo.MsgRandom, msgInfo.MsgTimeStamp, msgInfo.From_Account);
var msgBody = null;
var msgContent = null;
var msgType = null;
for (var mi in msgInfo.MsgBody) {
msgBody = msgInfo.MsgBody[mi];
msgType = msgBody.MsgType;
switch (msgType) {
case MSG_ELEMENT_TYPE.TEXT:
msgContent = new Msg.Elem.Text(msgBody.MsgContent.Text);
break;
case MSG_ELEMENT_TYPE.FACE:
msgContent = new Msg.Elem.Face(
msgBody.MsgContent.Index,
msgBody.MsgContent.Data
);
break;
case MSG_ELEMENT_TYPE.IMAGE:
msgContent = new Msg.Elem.Images(
msgBody.MsgContent.UUID
);
for (var j in msgBody.MsgContent.ImageInfoArray) {
var tempImg = msgBody.MsgContent.ImageInfoArray[j];
msgContent.addImage(
new Msg.Elem.Images.Image(
tempImg.Type,
tempImg.Size,
tempImg.Width,
tempImg.Height,
tempImg.URL
)
);
}
break;
case MSG_ELEMENT_TYPE.SOUND:
if (msgBody.MsgContent) {
msgContent = new Msg.Elem.Sound(
msgBody.MsgContent.UUID,
msgBody.MsgContent.Second,
msgBody.MsgContent.Size,
msgInfo.From_Account,
msgInfo.To_Account,
msgBody.MsgContent.Download_Flag,
SESSION_TYPE.C2C
);
} else {
msgType = MSG_ELEMENT_TYPE.TEXT;
msgContent = new Msg.Elem.Text('[语音消息]下载地址解析出错');
}
break;
case MSG_ELEMENT_TYPE.LOCATION:
msgContent = new Msg.Elem.Location(
msgBody.MsgContent.Longitude,
msgBody.MsgContent.Latitude,
msgBody.MsgContent.Desc
);
break;
case MSG_ELEMENT_TYPE.FILE:
case MSG_ELEMENT_TYPE.FILE + " ":
msgType = MSG_ELEMENT_TYPE.FILE;
if (msgBody.MsgContent) {
msgContent = new Msg.Elem.File(
msgBody.MsgContent.UUID,
msgBody.MsgContent.FileName,
msgBody.MsgContent.FileSize,
msgInfo.From_Account,
msgInfo.To_Account,
msgBody.MsgContent.Download_Flag,
SESSION_TYPE.C2C
);
} else {
msgType = MSG_ELEMENT_TYPE.TEXT;
msgContent = new Msg.Elem.Text('[文件消息下载地址解析出错]');
}
break;
case MSG_ELEMENT_TYPE.CUSTOM:
try {
var data = JSON.parse(msgBody.MsgContent.Data);
if (data && data.userAction && data.userAction == FRIEND_WRITE_MSG_ACTION.ING) {//过滤安卓或ios的正在输入自定义消息
continue;
}
} catch (e) {
}
msgType = MSG_ELEMENT_TYPE.CUSTOM;
msgContent = new Msg.Elem.Custom(
msgBody.MsgContent.Data,
msgBody.MsgContent.Desc,
msgBody.MsgContent.Ext
);
break;
default :
msgType = MSG_ELEMENT_TYPE.TEXT;
msgContent = new Msg.Elem.Text('web端暂不支持' + msgBody.MsgType + '消息');
break;
}
msg.elems.push(new Msg.Elem(msgType, msgContent));
}
if (msg.elems.length > 0 && MsgStore.addMsg(msg)) {
notifyInfo.push(msg);
}
} // for loop
if (notifyInfo.length > 0)
MsgStore.updateTimeline();
if (notifyInfo.length > 0) {
if (onMsgCallback) onMsgCallback(notifyInfo);
}
};
//发起新的长轮询请求
var startNextLongPolling = function () {
longPollingOn && MsgManager.longPolling();
};
//处理未决的加群申请消息列表
var handlerApplyJoinGroupSystemMsgs = function (eventArray) {
for (var i in eventArray) {
var e = eventArray[i];
switch (e.Event) {
case LONG_POLLINNG_EVENT_TYPE.GROUP_SYSTEM://(多终端同步)群系统消息
log.warn("handlerApplyJoinGroupSystemMsgs handler new group system msg");
//true 表示 解决加群申请通知存在重复的问题(已处理的通知,下次登录还会拉到),需要判重
handlerGroupSystemMsgs(e.GroupTips, true);
break;
default:
log.error("syncMsgs收到未知的群系统消息类型: Event=" + e.Event);
break;
}
}
};
//拉取c2c消息(包含加群未决消息,需要处理)
this.syncMsgs = function (cbOk, cbErr) {
var notifyInfo = [];
var msgInfos = [];
//读取C2C消息
proto_getMsgs(MsgStore.cookie, MsgStore.syncFlag, function (resp) {
//拉取完毕
if (resp.SyncFlag == 2) {
MsgStore.syncFlag = 0;
}
//处理c2c消息
msgInfos = resp.MsgList;//返回的消息列表
MsgStore.cookie = resp.Cookie;//cookies记录当前读到的最新消息位置
for (var i in msgInfos) {
var msgInfo = msgInfos[i];
var isSendMsg, id, headUrl;
if (msgInfo.From_Account == ctx.identifier) {//当前用户发送的消息
isSendMsg = true;
id = msgInfo.To_Account;//读取接收者信息
headUrl = '';
} else {//当前用户收到的消息
isSendMsg = false;
id = msgInfo.From_Account;//读取发送者信息
headUrl = '';
}
var sess = MsgStore.sessByTypeId(SESSION_TYPE.C2C, id);
if (!sess) {
sess = new Session(SESSION_TYPE.C2C, id, id, headUrl, 0, 0);
}
var msg = new Msg(sess, isSendMsg, msgInfo.MsgSeq, msgInfo.MsgRandom, msgInfo.MsgTimeStamp, msgInfo.From_Account);
var msgBody = null;
var msgContent = null;
var msgType = null;
for (var mi in msgInfo.MsgBody) {
msgBody = msgInfo.MsgBody[mi];
msgType = msgBody.MsgType;
switch (msgType) {
case MSG_ELEMENT_TYPE.TEXT:
msgContent = new Msg.Elem.Text(msgBody.MsgContent.Text);
break;
case MSG_ELEMENT_TYPE.FACE:
msgContent = new Msg.Elem.Face(
msgBody.MsgContent.Index,
msgBody.MsgContent.Data
);
break;
case MSG_ELEMENT_TYPE.IMAGE:
msgContent = new Msg.Elem.Images(
msgBody.MsgContent.UUID
);
for (var j in msgBody.MsgContent.ImageInfoArray) {
var tempImg = msgBody.MsgContent.ImageInfoArray[j];
msgContent.addImage(
new Msg.Elem.Images.Image(
tempImg.Type,
tempImg.Size,
tempImg.Width,
tempImg.Height,
tempImg.URL
)
);
}
break;
case MSG_ELEMENT_TYPE.SOUND:
// var soundUrl = getSoundDownUrl(msgBody.MsgContent.UUID, msgInfo.From_Account);
if (msgBody.MsgContent) {
msgContent = new Msg.Elem.Sound(
msgBody.MsgContent.UUID,
msgBody.MsgContent.Second,
msgBody.MsgContent.Size,
msgInfo.From_Account,
msgInfo.To_Account,
msgBody.MsgContent.Download_Flag,
SESSION_TYPE.C2C
);
} else {
msgType = MSG_ELEMENT_TYPE.TEXT;
msgContent = new Msg.Elem.Text('[语音消息]下载地址解析出错');
}
break;
case MSG_ELEMENT_TYPE.LOCATION:
msgContent = new Msg.Elem.Location(
msgBody.MsgContent.Longitude,
msgBody.MsgContent.Latitude,
msgBody.MsgContent.Desc
);
break;
case MSG_ELEMENT_TYPE.FILE:
case MSG_ELEMENT_TYPE.FILE + " ":
msgType = MSG_ELEMENT_TYPE.FILE;
// var fileUrl = getFileDownUrl(msgBody.MsgContent.UUID, msgInfo.From_Account, msgBody.MsgContent.FileName);
if (msgBody.MsgContent) {
msgContent = new Msg.Elem.File(
msgBody.MsgContent.UUID,
msgBody.MsgContent.FileName,
msgBody.MsgContent.FileSize,
msgInfo.From_Account,
msgInfo.To_Account,
msgBody.MsgContent.Download_Flag,
SESSION_TYPE.C2C
);
} else {
msgType = MSG_ELEMENT_TYPE.TEXT;
msgContent = new Msg.Elem.Text('[文件消息下载地址解析出错]');
}
break;
case MSG_ELEMENT_TYPE.CUSTOM:
try {
var data = JSON.parse(msgBody.MsgContent.Data);
if (data && data.userAction && data.userAction == FRIEND_WRITE_MSG_ACTION.ING) {//过滤安卓或ios的正在输入自定义消息
continue;
}
} catch (e) {
}
msgType = MSG_ELEMENT_TYPE.CUSTOM;
msgContent = new Msg.Elem.Custom(
msgBody.MsgContent.Data,
msgBody.MsgContent.Desc,
msgBody.MsgContent.Ext
);
break;
default :
msgType = MSG_ELEMENT_TYPE.TEXT;
msgContent = new Msg.Elem.Text('web端暂不支持' + msgBody.MsgType + '消息');
break;
}
msg.elems.push(new Msg.Elem(msgType, msgContent));
}
if (msg.elems.length > 0 && MsgStore.addMsg(msg)) {
notifyInfo.push(msg);
}
} // for loop
//处理加群未决申请消息
handlerApplyJoinGroupSystemMsgs(resp.EventArray);
if (notifyInfo.length > 0)
MsgStore.updateTimeline();
if (cbOk) cbOk(notifyInfo);
else if (notifyInfo.length > 0) {
if (onMsgCallback) onMsgCallback(notifyInfo);
}
}, function (err) {
log.error("getMsgs failed:" + err.ErrorInfo);
if (cbErr) cbErr(err);
});
};
//拉取C2C漫游消息
this.getC2CHistoryMsgs = function (options, cbOk, cbErr) {
if (!options.Peer_Account) {
if (cbErr) {
cbErr(tool.getReturnError("Peer_Account is empty", -13));
return;
}
}
if (!options.MaxCnt) {
options.MaxCnt = 15;
}
if (options.MaxCnt <= 0) {
if (cbErr) {
cbErr(tool.getReturnError("MaxCnt should be greater than 0", -14));
return;
}
}
if (options.MaxCnt > 15) {
if (cbErr) {
cbErr(tool.getReturnError("MaxCnt can not be greater than 15", -15));
return;
}
return;
}
if (options.MsgKey == null || options.MsgKey === undefined) {
options.MsgKey = '';
}
var opts = {
'Peer_Account': options.Peer_Account,
'MaxCnt': options.MaxCnt,
'LastMsgTime': options.LastMsgTime,
'MsgKey': options.MsgKey
};
//读取c2c漫游消息
proto_getC2CHistoryMsgs(opts, function (resp) {
var msgObjList = [];
var msgInfos = [];
//处理c2c消息
msgInfos = resp.MsgList;//返回的消息列表
var sess = MsgStore.sessByTypeId(SESSION_TYPE.C2C, options.Peer_Account);
if (!sess) {
sess = new Session(SESSION_TYPE.C2C, options.Peer_Account, options.Peer_Account, '', 0, 0);
}
for (var i in msgInfos) {
var msgInfo = msgInfos[i];
var isSendMsg, id, headUrl;
if (msgInfo.From_Account == ctx.identifier) {//当前用户发送的消息
isSendMsg = true;
id = msgInfo.To_Account;//读取接收者信息
headUrl = '';
} else {//当前用户收到的消息
isSendMsg = false;
id = msgInfo.From_Account;//读取发送者信息
headUrl = '';
}
var msg = new Msg(sess, isSendMsg, msgInfo.MsgSeq, msgInfo.MsgRandom, msgInfo.MsgTimeStamp, msgInfo.From_Account);
var msgBody = null;
var msgContent = null;
var msgType = null;
for (var mi in msgInfo.MsgBody) {
msgBody = msgInfo.MsgBody[mi];
msgType = msgBody.MsgType;
switch (msgType) {
case MSG_ELEMENT_TYPE.TEXT:
msgContent = new Msg.Elem.Text(msgBody.MsgContent.Text);
break;
case MSG_ELEMENT_TYPE.FACE:
msgContent = new Msg.Elem.Face(
msgBody.MsgContent.Index,
msgBody.MsgContent.Data
);
break;
case MSG_ELEMENT_TYPE.IMAGE:
msgContent = new Msg.Elem.Images(
msgBody.MsgContent.UUID
);
for (var j in msgBody.MsgContent.ImageInfoArray) {
var tempImg = msgBody.MsgContent.ImageInfoArray[j];
msgContent.addImage(
new Msg.Elem.Images.Image(
tempImg.Type,
tempImg.Size,
tempImg.Width,
tempImg.Height,
tempImg.URL
)
);
}
break;
case MSG_ELEMENT_TYPE.SOUND:
// var soundUrl = getSoundDownUrl(msgBody.MsgContent.UUID, msgInfo.From_Account);
if (msgBody.MsgContent) {
msgContent = new Msg.Elem.Sound(
msgBody.MsgContent.UUID,
msgBody.MsgContent.Second,
msgBody.MsgContent.Size,
msgInfo.From_Account,
msgInfo.To_Account,
msgBody.MsgContent.Download_Flag,
SESSION_TYPE.C2C
);
} else {
msgType = MSG_ELEMENT_TYPE.TEXT;
msgContent = new Msg.Elem.Text('[语音消息]下载地址解析出错');
}
break;
case MSG_ELEMENT_TYPE.LOCATION:
msgContent = new Msg.Elem.Location(
msgBody.MsgContent.Longitude,
msgBody.MsgContent.Latitude,
msgBody.MsgContent.Desc
);
break;
case MSG_ELEMENT_TYPE.FILE:
case MSG_ELEMENT_TYPE.FILE + " ":
msgType = MSG_ELEMENT_TYPE.FILE;
// var fileUrl = getFileDownUrl(msgBody.MsgContent.UUID, msgInfo.From_Account, msgBody.MsgContent.FileName);
if (msgBody.MsgContent) {
msgContent = new Msg.Elem.File(
msgBody.MsgContent.UUID,
msgBody.MsgContent.FileName,
msgBody.MsgContent.FileSize,
msgInfo.From_Account,
msgInfo.To_Account,
msgBody.MsgContent.Download_Flag,
SESSION_TYPE.C2C
);
} else {
msgType = MSG_ELEMENT_TYPE.TEXT;
msgContent = new Msg.Elem.Text('[文件消息下载地址解析出错]');
}
break;
case MSG_ELEMENT_TYPE.CUSTOM:
msgType = MSG_ELEMENT_TYPE.CUSTOM;
msgContent = new Msg.Elem.Custom(
msgBody.MsgContent.Data,
msgBody.MsgContent.Desc,
msgBody.MsgContent.Ext
);
break;
default :
msgType = MSG_ELEMENT_TYPE.TEXT;
msgContent = new Msg.Elem.Text('web端暂不支持' + msgBody.MsgType + '消息');
break;
}
msg.elems.push(new Msg.Elem(msgType, msgContent));
}
MsgStore.addMsg(msg);
msgObjList.push(msg);
} // for loop
MsgStore.updateTimeline();
if (cbOk) {
var newResp = {
'Complete': resp.Complete,
'MsgCount': msgObjList.length,
'LastMsgTime': resp.LastMsgTime,
'MsgKey': resp.MsgKey,
'MsgList': msgObjList
};
sess.isFinished(resp.Complete);
cbOk(newResp);
}
}, function (err) {
log.error("getC2CHistoryMsgs failed:" + err.ErrorInfo);
if (cbErr) cbErr(err);
});
};
//拉群历史消息
//不传cbOk 和 cbErr则会调用新消息回调函数
this.syncGroupMsgs = function (options, cbOk, cbErr) {
if (options.ReqMsgSeq <= 0) {
if (cbErr) {
var errInfo = "ReqMsgSeq must be greater than 0";
var error = tool.getReturnError(errInfo, -16);
cbErr(error);
}
return;
}
var opts = {
'GroupId': options.GroupId,
'ReqMsgSeq': options.ReqMsgSeq,
'ReqMsgNumber': options.ReqMsgNumber
};
//读群漫游消息
proto_getGroupMsgs(opts, function (resp) {
var notifyInfo = [];
var group_id = resp.GroupId;//返回的群id
var msgInfos = resp.RspMsgList;//返回的消息列表
var isFinished = resp.IsFinished;
if (msgInfos == null || msgInfos === undefined) {
if (cbOk) {
cbOk([]);
}
return;
}
for (var i = msgInfos.length - 1; i >= 0; i--) {
var msgInfo = msgInfos[i];
//如果是已经删除的消息或者发送者帐号为空或者消息内容为空
//IsPlaceMsg=1
if (msgInfo.IsPlaceMsg || !msgInfo.From_Account || !msgInfo.MsgBody || msgInfo.MsgBody.length == 0) {
continue;
}
var msg = handlerGroupMsg(msgInfo, true, true,isFinished);
if (msg) {
notifyInfo.push(msg);
}
} // for loop
if (notifyInfo.length > 0)
MsgStore.updateTimeline();
if (cbOk) cbOk(notifyInfo);
else if (notifyInfo.length > 0) {
if (onMsgCallback) onMsgCallback(notifyInfo);
}
}, function (err) {
log.error("getGroupMsgs failed:" + err.ErrorInfo);
if (cbErr) cbErr(err);
});
};
//处理群消息(普通消息+提示消息)
//isSyncGroupMsgs 是否主动拉取群消息标志
//isAddMsgFlag 是否需要保存到MsgStore如果需要这里会存在判重逻辑
var handlerGroupMsg = function (msgInfo, isSyncGroupMsgs, isAddMsgFlag ,isFinished) {
if (msgInfo.IsPlaceMsg || !msgInfo.From_Account || !msgInfo.MsgBody || msgInfo.MsgBody.length == 0) {
return null;
}
var isSendMsg, id, headUrl, fromAccountNick;
var group_id = msgInfo.ToGroupId;
var group_name = group_id;
if (msgInfo.GroupInfo) {//取出群名称
if (msgInfo.GroupInfo.GroupName) {
group_name = msgInfo.GroupInfo.GroupName;
}
}
//取出成员昵称
fromAccountNick = msgInfo.From_Account;
if (msgInfo.GroupInfo) {
if (msgInfo.GroupInfo.From_AccountNick) {
fromAccountNick = msgInfo.GroupInfo.From_AccountNick;
}
}
if (msgInfo.From_Account == ctx.identifier) {//当前用户发送的消息
isSendMsg = true;
id = msgInfo.From_Account;//读取接收者信息
headUrl = '';
} else {//当前用户收到的消息
isSendMsg = false;
id = msgInfo.From_Account;//读取发送者信息
headUrl = '';
}
var sess = MsgStore.sessByTypeId(SESSION_TYPE.GROUP, group_id);
if (!sess) {
sess = new Session(SESSION_TYPE.GROUP, group_id, group_name, headUrl, 0, 0);
}
if(typeof isFinished !=="undefined") {
sess.isFinished(isFinished || 0);
}
var subType = GROUP_MSG_SUB_TYPE.COMMON;//消息类型
//群提示消息,重新封装下
if (LONG_POLLINNG_EVENT_TYPE.GROUP_TIP == msgInfo.Event || LONG_POLLINNG_EVENT_TYPE.GROUP_TIP2 == msgInfo.Event) {
subType = GROUP_MSG_SUB_TYPE.TIP;
var groupTip = msgInfo.MsgBody;
msgInfo.MsgBody = [];
msgInfo.MsgBody.push({
"MsgType": MSG_ELEMENT_TYPE.GROUP_TIP,
"MsgContent": groupTip
}
);
} else if (msgInfo.MsgPriority) {//群点赞消息
if (msgInfo.MsgPriority == GROUP_MSG_PRIORITY_TYPE.REDPACKET) {
subType = GROUP_MSG_SUB_TYPE.REDPACKET;
} else if (msgInfo.MsgPriority == GROUP_MSG_PRIORITY_TYPE.LOVEMSG) {
subType = GROUP_MSG_SUB_TYPE.LOVEMSG;
}
}
var msg = new Msg(sess, isSendMsg, msgInfo.MsgSeq, msgInfo.MsgRandom, msgInfo.MsgTimeStamp, msgInfo.From_Account, subType, fromAccountNick);
var msgBody = null;
var msgContent = null;
var msgType = null;
for (var mi in msgInfo.MsgBody) {
msgBody = msgInfo.MsgBody[mi];
msgType = msgBody.MsgType;
switch (msgType) {
case MSG_ELEMENT_TYPE.TEXT:
msgContent = new Msg.Elem.Text(msgBody.MsgContent.Text);
break;
case MSG_ELEMENT_TYPE.FACE:
msgContent = new Msg.Elem.Face(
msgBody.MsgContent.Index,
msgBody.MsgContent.Data
);
break;
case MSG_ELEMENT_TYPE.IMAGE:
msgContent = new Msg.Elem.Images(
msgBody.MsgContent.UUID
);
for (var j in msgBody.MsgContent.ImageInfoArray) {
msgContent.addImage(
new Msg.Elem.Images.Image(
msgBody.MsgContent.ImageInfoArray[j].Type,
msgBody.MsgContent.ImageInfoArray[j].Size,
msgBody.MsgContent.ImageInfoArray[j].Width,
msgBody.MsgContent.ImageInfoArray[j].Height,
msgBody.MsgContent.ImageInfoArray[j].URL
)
);
}
break;
case MSG_ELEMENT_TYPE.SOUND:
if (msgBody.MsgContent) {
msgContent = new Msg.Elem.Sound(
msgBody.MsgContent.UUID,
msgBody.MsgContent.Second,
msgBody.MsgContent.Size,
msgInfo.From_Account,
msgInfo.To_Account,
msgBody.MsgContent.Download_Flag,
SESSION_TYPE.GROUP
);
} else {
msgType = MSG_ELEMENT_TYPE.TEXT;
msgContent = new Msg.Elem.Text('[语音消息]下载地址解析出错');
}
break;
case MSG_ELEMENT_TYPE.LOCATION:
msgContent = new Msg.Elem.Location(
msgBody.MsgContent.Longitude,
msgBody.MsgContent.Latitude,
msgBody.MsgContent.Desc
);
break;
case MSG_ELEMENT_TYPE.FILE:
case MSG_ELEMENT_TYPE.FILE + " ":
msgType = MSG_ELEMENT_TYPE.FILE;
var fileUrl = getFileDownUrl(msgBody.MsgContent.UUID, msgInfo.From_Account, msgBody.MsgContent.FileName);
if (msgBody.MsgContent) {
msgContent = new Msg.Elem.File(
msgBody.MsgContent.UUID,
msgBody.MsgContent.FileName,
msgBody.MsgContent.FileSize,
msgInfo.From_Account,
msgInfo.To_Account,
msgBody.MsgContent.Download_Flag,
SESSION_TYPE.GROUP
);
} else {
msgType = MSG_ELEMENT_TYPE.TEXT;
msgContent = new Msg.Elem.Text('[文件消息]地址解析出错');
}
break;
case MSG_ELEMENT_TYPE.GROUP_TIP:
var opType = msgBody.MsgContent.OpType;
msgContent = new Msg.Elem.GroupTip(
opType,
msgBody.MsgContent.Operator_Account,
group_id,
msgInfo.GroupInfo.GroupName,
msgBody.MsgContent.List_Account
);
if (GROUP_TIP_TYPE.JOIN == opType || GROUP_TIP_TYPE.QUIT == opType) {//加群或退群时,设置最新群成员数
msgContent.setGroupMemberNum(msgBody.MsgContent.MemberNum);
} else if (GROUP_TIP_TYPE.MODIFY_GROUP_INFO == opType) {//群资料变更
var tempIsCallbackFlag = false;
var tempNewGroupInfo = {
"GroupId": group_id,
"GroupFaceUrl": null,
"GroupName": null,
"OwnerAccount": null,
"GroupNotification": null,
"GroupIntroduction": null
};
var msgGroupNewInfo = msgBody.MsgContent.MsgGroupNewInfo;
if (msgGroupNewInfo.GroupFaceUrl) {
var tmpNGIFaceUrl = new Msg.Elem.GroupTip.GroupInfo(
GROUP_TIP_MODIFY_GROUP_INFO_TYPE.FACE_URL,
msgGroupNewInfo.GroupFaceUrl
);
msgContent.addGroupInfo(tmpNGIFaceUrl);
tempIsCallbackFlag = true;
tempNewGroupInfo.GroupFaceUrl = msgGroupNewInfo.GroupFaceUrl;
}
if (msgGroupNewInfo.GroupName) {
var tmpNGIName = new Msg.Elem.GroupTip.GroupInfo(
GROUP_TIP_MODIFY_GROUP_INFO_TYPE.NAME,
msgGroupNewInfo.GroupName
);
msgContent.addGroupInfo(tmpNGIName);
tempIsCallbackFlag = true;
tempNewGroupInfo.GroupName = msgGroupNewInfo.GroupName;
}
if (msgGroupNewInfo.Owner_Account) {
var tmpNGIOwner = new Msg.Elem.GroupTip.GroupInfo(
GROUP_TIP_MODIFY_GROUP_INFO_TYPE.OWNER,
msgGroupNewInfo.Owner_Account
);
msgContent.addGroupInfo(tmpNGIOwner);
tempIsCallbackFlag = true;
tempNewGroupInfo.OwnerAccount = msgGroupNewInfo.Owner_Account;
}
if (msgGroupNewInfo.GroupNotification) {
var tmpNGINotification = new Msg.Elem.GroupTip.GroupInfo(
GROUP_TIP_MODIFY_GROUP_INFO_TYPE.NOTIFICATION,
msgGroupNewInfo.GroupNotification
);
msgContent.addGroupInfo(tmpNGINotification);
tempIsCallbackFlag = true;
tempNewGroupInfo.GroupNotification = msgGroupNewInfo.GroupNotification;
}
if (msgGroupNewInfo.GroupIntroduction) {
var tmpNGIIntroduction = new Msg.Elem.GroupTip.GroupInfo(
GROUP_TIP_MODIFY_GROUP_INFO_TYPE.INTRODUCTION,
msgGroupNewInfo.GroupIntroduction
);
msgContent.addGroupInfo(tmpNGIIntroduction);
tempIsCallbackFlag = true;
tempNewGroupInfo.GroupIntroduction = msgGroupNewInfo.GroupIntroduction;
}
//回调群资料变化通知方法
if (isSyncGroupMsgs == false && tempIsCallbackFlag && onGroupInfoChangeCallback) {
onGroupInfoChangeCallback(tempNewGroupInfo);
}
} else if (GROUP_TIP_TYPE.MODIFY_MEMBER_INFO == opType) {//群成员变更
var memberInfos = msgBody.MsgContent.MsgMemberInfo;
for (var n in memberInfos) {
var memberInfo = memberInfos[n];
msgContent.addMemberInfo(
new Msg.Elem.GroupTip.MemberInfo(
memberInfo.User_Account, memberInfo.ShutupTime
)
);
}
}
break;
case MSG_ELEMENT_TYPE.CUSTOM:
msgType = MSG_ELEMENT_TYPE.CUSTOM;
msgContent = new Msg.Elem.Custom(
msgBody.MsgContent.Data,
msgBody.MsgContent.Desc,
msgBody.MsgContent.Ext
);
break;
default :
msgType = MSG_ELEMENT_TYPE.TEXT;
msgContent = new Msg.Elem.Text('web端暂不支持' + msgBody.MsgType + '消息');
break;
}
msg.elems.push(new Msg.Elem(msgType, msgContent));
}
if (isAddMsgFlag == false) {//不需要保存消息
return msg;
}
if (MsgStore.addMsg(msg)) {
return msg;
} else {
return null;
}
};
//初始化
this.init = function (listeners, cbOk, cbErr) {
if (!listeners.onMsgNotify) {
log.warn('listeners.onMsgNotify is empty');
}
onMsgCallback = listeners.onMsgNotify;
if (listeners.onBigGroupMsgNotify) {
onBigGroupMsgCallback = listeners.onBigGroupMsgNotify;
} else {
log.warn('listeners.onBigGroupMsgNotify is empty');
}
if (listeners.onC2cEventNotifys) {
onC2cEventCallbacks = listeners.onC2cEventNotifys;
} else {
log.warn('listeners.onC2cEventNotifys is empty');
}
if (listeners.onGroupSystemNotifys) {
onGroupSystemNotifyCallbacks = listeners.onGroupSystemNotifys;
} else {
log.warn('listeners.onGroupSystemNotifys is empty');
}
if (listeners.onGroupInfoChangeNotify) {
onGroupInfoChangeCallback = listeners.onGroupInfoChangeNotify;
} else {
log.warn('listeners.onGroupInfoChangeNotify is empty');
}
if (listeners.onFriendSystemNotifys) {
onFriendSystemNotifyCallbacks = listeners.onFriendSystemNotifys;
} else {
log.warn('listeners.onFriendSystemNotifys is empty');
}
if (listeners.onProfileSystemNotifys) {
onProfileSystemNotifyCallbacks = listeners.onProfileSystemNotifys;
} else {
log.warn('listeners.onProfileSystemNotifys is empty');
}
if (listeners.onKickedEventCall) {
onKickedEventCall = listeners.onKickedEventCall;
} else {
log.warn('listeners.onKickedEventCall is empty');
}
if (listeners.onAppliedDownloadUrl) {
onAppliedDownloadUrl = listeners.onAppliedDownloadUrl;
} else {
log.warn('listeners.onAppliedDownloadUrl is empty');
}
if (!ctx.identifier || !ctx.userSig) {
if (cbOk) {
var success = {
'ActionStatus': ACTION_STATUS.OK,
'ErrorCode': 0,
'ErrorInfo': "login success(no login state)"
};
cbOk(success);
}
return;
}
//初始化
initMyGroupMaxSeqs(
function (resp) {
log.info('initMyGroupMaxSeqs success');
//初始化文件
initIpAndAuthkey(
function (initIpAndAuthkeyResp) {
log.info('initIpAndAuthkey success');
if (cbOk) {
log.info('login success(have login state))');
var success = {
'ActionStatus': ACTION_STATUS.OK,
'ErrorCode': 0,
'ErrorInfo': "login success"
};
cbOk(success);
}
MsgManager.setLongPollingOn(true);//开启长轮询
longPollingOn && MsgManager.longPolling(cbOk);
}, cbErr);
}, cbErr);
};
//发消息(私聊或群聊)
this.sendMsg = function (msg, cbOk, cbErr) {
proto_sendMsg(msg, function (resp) {
//私聊时加入自己的发的消息群聊时由于seq和服务器的seq不一样所以不作处理
if (msg.sess.type() == SESSION_TYPE.C2C) {
if (!MsgStore.addMsg(msg)) {
var errInfo = "sendMsg: addMsg failed!";
var error = tool.getReturnError(errInfo, -17);
log.error(errInfo);
if (cbErr) cbErr(error);
return;
}
//更新信息流时间
MsgStore.updateTimeline();
}
if (cbOk) cbOk(resp);
}, function (err) {
if (cbErr) cbErr(err);
});
};
};
//上传文件
var FileUploader = new function () {
this.fileMd5 = null;
//获取文件MD5
var getFileMD5 = function (file, cbOk, cbErr) {
//FileReader pc浏览器兼容性
//Feature Firefox (Gecko) Chrome Internet Explorer Opera Safari
//Basic support 3.6 7 10 12.02 6.0.2
var fileReader = null;
try {
fileReader = new FileReader();//分块读取文件对象
} catch (e) {
if (cbErr) {
cbErr(tool.getReturnError('当前浏览器不支持FileReader', -18));
return;
}
}
//file的slice方法注意它的兼容性在不同浏览器的写法不同
var blobSlice = File.prototype.mozSlice || File.prototype.webkitSlice || File.prototype.slice;
if (!blobSlice) {
if (cbErr) {
cbErr(tool.getReturnError('当前浏览器不支持FileAPI', -19));
return;
}
}
var chunkSize = 2 * 1024 * 1024;//分块大小2M
var chunks = Math.ceil(file.size / chunkSize);//总块数
var currentChunk = 0;//当前块数
var spark = new SparkMD5();//获取MD5对象
fileReader.onload = function (e) {//数据加载完毕事件
var binaryStr = "";
var bytes = new Uint8Array(e.target.result);
var length = bytes.byteLength;
for (var i = 0; i < length; i++) {
binaryStr += String.fromCharCode(bytes[i]);//二进制转换字符串
}
spark.appendBinary(binaryStr);
currentChunk++;
if (currentChunk < chunks) {
loadNext();//读取下一块数据
} else {
this.fileMd5 = spark.end();//得到文件MD5值
if (cbOk) {
cbOk(this.fileMd5);
}
}
};
//分片读取文件
function loadNext() {
var start = currentChunk * chunkSize, end = start + chunkSize >= file.size ? file.size : start + chunkSize;
//根据开始和结束位置,切割文件
var b = blobSlice.call(file, start, end);
//readAsBinaryString ie浏览器不兼容此方法
//fileReader.readAsBinaryString(blobSlice.call(file, start, end));
fileReader.readAsArrayBuffer(b);//iechromefirefox等主流浏览器兼容此方法
}
loadNext();//开始读取
};
//提交上传图片表单(用于低版本IE9以下)
this.submitUploadFileForm = function (options, cbOk, cbErr) {
var errInfo;
var error;
var formId = options.formId;
var fileId = options.fileId;
var iframeNum = uploadResultIframeId++;
var iframeName = "uploadResultIframe_" + iframeNum;
var toAccount = options.To_Account;
var businessType = options.businessType;
var form = document.getElementById(formId);
if (!form) {
errInfo = "获取表单对象为空: formId=" + formId + "(formId非法)";
error = tool.getReturnError(errInfo, -20);
if (cbErr) cbErr(error);
return;
}
var fileObj = document.getElementById(fileId);
if (!fileObj) {
errInfo = "获取文件对象为空: fileId=" + fileId + "(没有选择文件或者fileId非法)";
error = tool.getReturnError(errInfo, -21);
if (cbErr) cbErr(error);
return;
}
//fileObj.type="file";//ie8下不起作用必须由业务自己设置
fileObj.name = "file";
var iframe = document.createElement("iframe");
iframe.name = iframeName;
iframe.id = iframeName;
iframe.style.display = "none";
document.body.appendChild(iframe);
var cmdName;
if (isAccessFormalEnv()) {
cmdName = 'pic_up';
} else {
cmdName = 'pic_up_test';
}
var uploadApiUrl = "https://pic.tim.qq.com/v4/openpic/" + cmdName + "?tinyid=" + ctx.tinyid + "&a2=" + ctx.a2 + "&sdkappid=" + ctx.sdkAppID + "&accounttype=" + ctx.accountType + "&contenttype=http";
form.action = uploadApiUrl;
form.method = 'post';
//form.enctype='multipart/form-data';//ie8下不起作用必须由业务自己设置
form.target = iframeName;
function createFormInput(name, value) {
var tempInput = document.createElement("input");
tempInput.type = "hidden";
tempInput.name = name;
tempInput.value = value;
form.appendChild(tempInput);
}
createFormInput("App_Version", VERSION_INFO.APP_VERSION);
createFormInput("From_Account", ctx.identifier);
createFormInput("To_Account", toAccount);
createFormInput("Seq", nextSeq().toString());
createFormInput("Timestamp", unixtime().toString());
createFormInput("Random", createRandom().toString());
createFormInput("Busi_Id", businessType);
createFormInput("PkgFlag", UPLOAD_RES_PKG_FLAG.RAW_DATA.toString());
createFormInput("Auth_Key", authkey);
createFormInput("Server_Ver", VERSION_INFO.SERVER_VERSION.toString());
createFormInput("File_Type", options.fileType);
//检测iframe.contentWindow.name是否有值
function checkFrameName() {
var resp;
try {
resp = JSON.parse(iframe.contentWindow.name) || {};
} catch (e) {
resp = {};
}
if (resp.ActionStatus) {//上传接口返回
// We've got what we need. Stop the iframe from loading further content.
iframe.src = "about:blank";
iframe.parentNode.removeChild(iframe);
iframe = null;
if (resp.ActionStatus == ACTION_STATUS.OK) {
cbOk && cbOk(resp);
} else {
cbErr && cbErr(resp);
}
} else {
setTimeout(checkFrameName, 100);
}
}
setTimeout(checkFrameName, 500);
form.submit();//提交上传图片表单
};
//上传图片或文件(用于高版本浏览器支持FileAPI)
this.uploadFile = function (options, cbOk, cbErr) {
var file_upload = {
//初始化
init: function (options, cbOk, cbErr) {
var me = this;
me.file = options.file;
//分片上传进度回调事件
me.onProgressCallBack = options.onProgressCallBack;
//停止上传图片按钮
if (options.abortButton) {
options.abortButton.onclick = me.abortHandler;
}
me.total = me.file.size;//文件总大小
me.loaded = 0;//已读取字节数
me.step = 1080 * 1024;//分块大小1080K
me.sliceSize = 0;//分片大小
me.sliceOffset = 0;//当前分片位置
me.timestamp = unixtime();//当前时间戳
me.seq = nextSeq();//请求seq
me.random = createRandom();//请求随机数
me.fromAccount = ctx.identifier;//发送者
me.toAccount = options.To_Account;//接收者
me.fileMd5 = options.fileMd5;//文件MD5
me.businessType = options.businessType;//图片或文件的业务类型,群消息:1; c2c消息:2; 个人头像3; 群头像4;
me.fileType = options.fileType;//文件类型不填为默认认为上传的是图片1图片2文件3短视频4PTT
me.cbOk = cbOk;//上传成功回调事件
me.cbErr = cbErr;//上传失败回调事件
me.reader = new FileReader();//读取文件对象
me.blobSlice = File.prototype.mozSlice || File.prototype.webkitSlice || File.prototype.slice;//file的slice方法,不同浏览器不一样
me.reader.onloadstart = me.onLoadStart;//开始读取回调事件
me.reader.onprogress = me.onProgress;//读取文件进度回调事件
me.reader.onabort = me.onAbort;//停止读取回调事件
me.reader.onerror = me.onerror;//读取发生错误回调事件
me.reader.onload = me.onLoad;//分片加载完毕回调事件
me.reader.onloadend = me.onLoadEnd;//读取文件完毕回调事件
},
//上传方法
upload: function () {
var me = file_upload;
//读取第一块
me.readBlob(0);
},
onLoadStart: function () {
var me = file_upload;
},
onProgress: function (e) {
var me = file_upload;
me.loaded += e.loaded;
if (me.onProgressCallBack) {
me.onProgressCallBack(me.loaded, me.total);
}
},
onAbort: function () {
var me = file_upload;
},
onError: function () {
var me = file_upload;
},
onLoad: function (e) {
var me = file_upload;
if (e.target.readyState == FileReader.DONE) {
var slice_data_base64 = e.target.result;
//注意一定要去除base64编码头部
var pos = slice_data_base64.indexOf(",");
if (pos != -1) {
slice_data_base64 = slice_data_base64.substr(pos + 1);
}
//封装上传图片接口的请求参数
var opt = {
'From_Account': me.fromAccount,
'To_Account': me.toAccount,
'Busi_Id': me.businessType,
'File_Type': me.fileType,
'File_Str_Md5': me.fileMd5,
'PkgFlag': UPLOAD_RES_PKG_FLAG.BASE64_DATA,
'File_Size': me.total,
'Slice_Offset': me.sliceOffset,
'Slice_Size': me.sliceSize,
'Slice_Data': slice_data_base64,
'Seq': me.seq,
'Timestamp': me.timestamp,
'Random': me.random
};
//上传成功的成功回调
var succCallback = function (resp) {
if (resp.IsFinish == 0) {
me.loaded = resp.Next_Offset;
if (me.loaded < me.total) {
me.readBlob(me.loaded);
} else {
me.loaded = me.total;
}
} else {
if (me.cbOk) {
var tempResp = {
'ActionStatus': resp.ActionStatus,
'ErrorCode': resp.ErrorCode,
'ErrorInfo': resp.ErrorInfo,
'File_UUID': resp.File_UUID,
'File_Size': resp.Next_Offset,
'URL_INFO': resp.URL_INFO,
'Download_Flag':resp.Download_Flag
};
if (me.fileType == UPLOAD_RES_TYPE.FILE) {//如果上传的是文件下载地址需要sdk内部拼接
tempResp.URL_INFO = getFileDownUrl(resp.File_UUID, ctx.identifier, me.file.name);
}
me.cbOk(tempResp);
}
}
Upload_Retry_Times = 0;
};
//上传失败的回调
var errorCallback = function(resp){
if(Upload_Retry_Times < Upload_Retry_Max_Times){
Upload_Retry_Times ++;
setTimeout(function(){
proto_uploadPic(opt,succCallback,errorCallback);
},1000);
}else{
me.cbErr(resp);
}
//me.cbErr
};
//分片上传图片接口
proto_uploadPic(opt, succCallback,errorCallback);
}
},
onLoadEnd: function () {
var me = file_upload;
},
//分片读取文件方法
readBlob: function (start) {
var me = file_upload;
var blob, file = me.file;
var end = start + me.step;
if (end > me.total) {
end = me.total;
me.sliceSize = end - start;
} else {
me.sliceSize = me.step;
}
me.sliceOffset = start;
//根据起始和结束位置,分片读取文件
blob = me.blobSlice.call(file, start, end);
//将分片的二进制数据转换为base64编码
me.reader.readAsDataURL(blob);
},
abortHandler: function () {
var me = file_upload;
if (me.reader) {
me.reader.abort();
}
}
};
//读取文件MD5
getFileMD5(options.file,
function (fileMd5) {
log.info('fileMd5: ' + fileMd5);
options.fileMd5 = fileMd5;
//初始化上传参数
file_upload.init(options, cbOk, cbErr);
//开始上传文件
file_upload.upload();
},
cbErr
);
};
};
//web im 基础对象
//常量对象
//会话类型
webim.SESSION_TYPE = SESSION_TYPE;
webim.MSG_MAX_LENGTH = MSG_MAX_LENGTH;
//c2c消息子类型
webim.C2C_MSG_SUB_TYPE = C2C_MSG_SUB_TYPE;
//群消息子类型
webim.GROUP_MSG_SUB_TYPE = GROUP_MSG_SUB_TYPE;
//消息元素类型
webim.MSG_ELEMENT_TYPE = MSG_ELEMENT_TYPE;
//群提示消息类型
webim.GROUP_TIP_TYPE = GROUP_TIP_TYPE;
//图片类型
webim.IMAGE_TYPE = IMAGE_TYPE;
//群系统消息类型
webim.GROUP_SYSTEM_TYPE = GROUP_SYSTEM_TYPE;
//好友系统通知子类型
webim.FRIEND_NOTICE_TYPE = FRIEND_NOTICE_TYPE;
//群提示消息-群资料变更类型
webim.GROUP_TIP_MODIFY_GROUP_INFO_TYPE = GROUP_TIP_MODIFY_GROUP_INFO_TYPE;
//浏览器信息
webim.BROWSER_INFO = BROWSER_INFO;
//表情对象
webim.Emotions = webim.EmotionPicData = emotions;
//表情标识符和index Map
webim.EmotionDataIndexs = webim.EmotionPicDataIndex = emotionDataIndexs;
//腾讯登录服务错误码(托管模式)
webim.TLS_ERROR_CODE = TLS_ERROR_CODE;
//连接状态
webim.CONNECTION_STATUS = CONNECTION_STATUS;
//上传图片业务类型
webim.UPLOAD_PIC_BUSSINESS_TYPE = UPLOAD_PIC_BUSSINESS_TYPE;
//最近联系人类型
webim.RECENT_CONTACT_TYPE = RECENT_CONTACT_TYPE;
//上传资源类型
webim.UPLOAD_RES_TYPE = UPLOAD_RES_TYPE;
/**************************************/
//类对象
//
//工具对象
webim.Tool = tool;
//控制台打印日志对象
webim.Log = log;
//消息对象
webim.Msg = Msg;
//会话对象
webim.Session = Session;
//会话存储对象
webim.MsgStore = {
sessMap: function () {
return MsgStore.sessMap();
},
sessCount: function () {
return MsgStore.sessCount();
},
sessByTypeId: function (type, id) {
return MsgStore.sessByTypeId(type, id);
},
delSessByTypeId: function (type, id) {
return MsgStore.delSessByTypeId(type, id);
},
resetCookieAndSyncFlag: function () {
return MsgStore.resetCookieAndSyncFlag();
}
};
webim.Resources = Resources;
/**************************************/
// webim API impl
//
//基本接口
//登录
webim.login = webim.init = function (loginInfo, listeners, opts, cbOk, cbErr) {
MsgManager.resetLongPollingInfo();
//初始化连接状态回调函数
ConnManager.init(listeners.onConnNotify, cbOk, cbErr);
//设置ie9以下浏览器jsonp回调
if (listeners.jsonpCallback) jsonpCallback = listeners.jsonpCallback;
//登录
_login(loginInfo, listeners, opts, cbOk, cbErr);
};
//登出
//需要传长轮询id
//这样登出之后其他的登录实例还可以继续收取消息
webim.logout = webim.offline = function (cbOk, cbErr) {
return proto_logout('instance',cbOk, cbErr);
};
//登出
//这种登出方式,所有的实例都将不会收到消息推送,直到重新登录
webim.logoutAll = function (cbOk, cbErr) {
return proto_logout('all',cbOk, cbErr);
};
//消息管理接口
//发消息接口(私聊和群聊)
webim.sendMsg = function (msg, cbOk, cbErr) {
return MsgManager.sendMsg(msg, cbOk, cbErr);
};
//拉取未读c2c消息
webim.syncMsgs = function (cbOk, cbErr) {
return MsgManager.syncMsgs(cbOk, cbErr);
};
//拉取C2C漫游消息
webim.getC2CHistoryMsgs = function (options, cbOk, cbErr) {
return MsgManager.getC2CHistoryMsgs(options, cbOk, cbErr);
};
//拉取群漫游消息
webim.syncGroupMsgs = function (options, cbOk, cbErr) {
return MsgManager.syncGroupMsgs(options, cbOk, cbErr);
};
//上报c2c消息已读
webim.c2CMsgReaded = function (options, cbOk, cbErr) {
return MsgStore.c2CMsgReaded(options, cbOk, cbErr);
};
//上报群消息已读
webim.groupMsgReaded = function (options, cbOk, cbErr) {
return proto_groupMsgReaded(options, cbOk, cbErr);
};
//设置聊天会话自动标记已读
webim.setAutoRead = function (selSess, isOn, isResetAll) {
return MsgStore.setAutoRead(selSess, isOn, isResetAll);
};
//群组管理接口
//
//创建群
webim.createGroup = function (options, cbOk, cbErr) {
return proto_createGroup(options, cbOk, cbErr);
};
//创建群-高级接口
webim.createGroupHigh = function (options, cbOk, cbErr) {
return proto_createGroupHigh(options, cbOk, cbErr);
};
//申请加群
webim.applyJoinGroup = function (options, cbOk, cbErr) {
return proto_applyJoinGroup(options, cbOk, cbErr);
};
//处理加群申请(同意或拒绝)
webim.handleApplyJoinGroupPendency = function (options, cbOk, cbErr) {
return proto_handleApplyJoinGroupPendency(options, cbOk, cbErr);
};
//删除加群申请
webim.deleteApplyJoinGroupPendency = function (options, cbOk, cbErr) {
return proto_deleteC2CMsg(options, cbOk, cbErr);
};
//主动退群
webim.quitGroup = function (options, cbOk, cbErr) {
return proto_quitGroup(options, cbOk, cbErr);
};
//搜索群组(根据名称)
webim.searchGroupByName = function (options, cbOk, cbErr) {
return proto_searchGroupByName(options, cbOk, cbErr);
};
//获取群组公开资料(根据群id搜索)
webim.getGroupPublicInfo = function (options, cbOk, cbErr) {
return proto_getGroupPublicInfo(options, cbOk, cbErr);
};
//获取群组详细资料-高级接口
webim.getGroupInfo = function (options, cbOk, cbErr) {
return proto_getGroupInfo(options, cbOk, cbErr);
};
//修改群基本资料
webim.modifyGroupBaseInfo = function (options, cbOk, cbErr) {
return proto_modifyGroupBaseInfo(options, cbOk, cbErr);
};
//获取群成员列表
webim.getGroupMemberInfo = function (options, cbOk, cbErr) {
return proto_getGroupMemberInfo(options, cbOk, cbErr);
};
//邀请好友加群
webim.addGroupMember = function (options, cbOk, cbErr) {
return proto_addGroupMember(options, cbOk, cbErr);
};
//修改群成员资料
webim.modifyGroupMember = function (options, cbOk, cbErr) {
return proto_modifyGroupMember(options, cbOk, cbErr);
};
//删除群成员
webim.deleteGroupMember = function (options, cbOk, cbErr) {
return proto_deleteGroupMember(options, cbOk, cbErr);
};
//解散群
webim.destroyGroup = function (options, cbOk, cbErr) {
return proto_destroyGroup(options, cbOk, cbErr);
};
//转让群组
webim.changeGroupOwner = function (options, cbOk, cbErr) {
return proto_changeGroupOwner(options, cbOk, cbErr);
};
//获取我的群组列表-高级接口
webim.getJoinedGroupListHigh = function (options, cbOk, cbErr) {
return proto_getJoinedGroupListHigh(options, cbOk, cbErr);
};
//获取群成员角色
webim.getRoleInGroup = function (options, cbOk, cbErr) {
return proto_getRoleInGroup(options, cbOk, cbErr);
};
//设置群成员禁言时间
webim.forbidSendMsg = function (options, cbOk, cbErr) {
return proto_forbidSendMsg(options, cbOk, cbErr);
};
//发送自定义群系统通知
webim.sendCustomGroupNotify = function (options, cbOk, cbErr) {
return proto_sendCustomGroupNotify(options, cbOk, cbErr);
};
//进入大群
webim.applyJoinBigGroup = function (options, cbOk, cbErr) {
return proto_applyJoinBigGroup(options, cbOk, cbErr);
};
//退出大群
webim.quitBigGroup = function (options, cbOk, cbErr) {
return proto_quitBigGroup(options, cbOk, cbErr);
};
//资料关系链管理接口
//
//获取个人资料接口,可用于搜索用户
webim.getProfilePortrait = function (options, cbOk, cbErr) {
return proto_getProfilePortrait(options, cbOk, cbErr);
};
//设置个人资料
webim.setProfilePortrait = function (options, cbOk, cbErr) {
return proto_setProfilePortrait(options, cbOk, cbErr);
};
//申请加好友
webim.applyAddFriend = function (options, cbOk, cbErr) {
return proto_applyAddFriend(options, cbOk, cbErr);
};
//获取好友申请列表
webim.getPendency = function (options, cbOk, cbErr) {
return proto_getPendency(options, cbOk, cbErr);
};
//删除好友申请
webim.deletePendency = function (options, cbOk, cbErr) {
return proto_deletePendency(options, cbOk, cbErr);
};
//处理好友申请
webim.responseFriend = function (options, cbOk, cbErr) {
return proto_responseFriend(options, cbOk, cbErr);
};
//获取我的好友
webim.getAllFriend = function (options, cbOk, cbErr) {
return proto_getAllFriend(options, cbOk, cbErr);
};
//删除好友
webim.deleteFriend = function (options, cbOk, cbErr) {
return proto_deleteFriend(options, cbOk, cbErr);
};
//拉黑
webim.addBlackList = function (options, cbOk, cbErr) {
return proto_addBlackList(options, cbOk, cbErr);
};
//删除黑名单
webim.deleteBlackList = function (options, cbOk, cbErr) {
return proto_deleteBlackList(options, cbOk, cbErr);
};
//获取我的黑名单
webim.getBlackList = function (options, cbOk, cbErr) {
return proto_getBlackList(options, cbOk, cbErr);
};
//获取最近会话
webim.getRecentContactList = function (options, cbOk, cbErr) {
return proto_getRecentContactList(options, cbOk, cbErr);
};
//图片或文件服务接口
//
//上传文件接口(高版本浏览器)
webim.uploadFile = webim.uploadPic = function (options, cbOk, cbErr) {
return FileUploader.uploadFile(options, cbOk, cbErr);
};
//提交上传图片表单接口用于低版本ie
webim.submitUploadFileForm = function (options, cbOk, cbErr) {
return FileUploader.submitUploadFileForm(options, cbOk, cbErr);
};
//上传图片或文件(Base64)接口
webim.uploadFileByBase64 = webim.uploadPicByBase64 = function (options, cbOk, cbErr) {
//请求参数
var opt = {
'To_Account': options.toAccount,
'Busi_Id': options.businessType,
'File_Type': options.File_Type,
'File_Str_Md5': options.fileMd5,
'PkgFlag': UPLOAD_RES_PKG_FLAG.BASE64_DATA,
'File_Size': options.totalSize,
'Slice_Offset': 0,
'Slice_Size': options.totalSize,
'Slice_Data': options.base64Str,
'Seq': nextSeq(),
'Timestamp': unixtime(),
'Random': createRandom()
};
return proto_uploadPic(opt, cbOk, cbErr);
};
//设置jsonp返回的值
webim.setJsonpLastRspData = function (rspData) {
jsonpLastRspData = typeof (rspData) == "string" ? JSON.parse(rspData) : rspData;
};
//获取长轮询ID
webim.getLongPollingId = function (options, cbOk, cbErr) {
return proto_getLongPollingId(options, cbOk, cbErr);
};
//获取下载地址
webim.applyDownload = function (options, cbOk, cbErr) {
return proto_applyDownload(options, cbOk, cbErr);
};
//获取下载地址
webim.onDownFile = function (uuid) {
window.open(Resources.downloadMap["uuid_"+uuid]);
};
//检查是否登录
webim.checkLogin = function (cbErr, isNeedCallBack) {
return checkLogin(cbErr, isNeedCallBack);
};
})(webim);
return webim;
}();