import { TUINotification } from "../../../TUIPlugin"; import Message from "../../../TUICore/tim/index"; import IComponentServer from "../IComponentServer"; import { JSONToObject } from "./utils/utils"; /** * class TUIChatServer * * TUIChat 逻辑主体 */ export default class TUIChatServer extends IComponentServer { public TUICore: any; public store: any; public currentStore: any = {}; constructor(TUICore: any) { super(); this.TUICore = TUICore; this.bindTIMEvent(); this.store = TUICore.setComponentStore("TUIChat", {}, this.updateStore.bind(this)); } /** * 组件销毁 * destroy */ public destroyed() { this.unbindTIMEvent(); } /** * 数据监听回调 * data listener callback * * @param {any} newValue 新数据 * @param {any} oldValue 旧数据 * */ updateStore(newValue: any, oldValue: any) { Object.assign(this.currentStore, newValue); if (!newValue.conversation.conversationID) { this.currentStore.messageList = []; return; } if (newValue.conversation.conversationID && newValue.conversation.conversationID !== oldValue.conversation.conversationID) { this.render(newValue.conversation); } } public render(conversation: any) { const len = 15; this.currentStore.isFirstRender = true; this.currentStore.messageList = []; this.currentStore.readSet.clear(); this.getMessageList({ conversationID: conversation.conversationID, count: len, }); if (conversation.type === this.TUICore.TIM.TYPES.CONV_GROUP) { this.currentStore.userInfo.isGroup = true; const options = { groupID: conversation.groupProfile.groupID, userIDList: [conversation.groupProfile.selfInfo.userID], }; this.getGroupProfile({ groupID: conversation.groupProfile.groupID }); this.getGroupMemberProfile(options).then((res: any) => { const { memberList } = res.data; const [selfInfo] = memberList; this.currentStore.selfInfo = selfInfo; }); this?.TUICore?.TUIServer?.TUIGroup?.getGroupMemberList({ groupID: conversation.groupProfile.groupID, count: 100, offset: 0, }).then((res: any) => { this.currentStore.allMemberList = res.data?.memberList; }); } else { this.currentStore.userInfo.isGroup = false; this.currentStore.userInfo.list = [conversation?.userProfile]; } } /** * ///////////////////////////////////////////////////////////////////////////////// * // * // TIM 事件监听注册接口 * // TIM Event listener registration interface * // * ///////////////////////////////////////////////////////////////////////////////// */ private bindTIMEvent() { this.TUICore.tim.on(this.TUICore.TIM.EVENT.MESSAGE_RECEIVED, this.handleMessageReceived, this); this.TUICore.tim.on(this.TUICore.TIM.EVENT.MESSAGE_MODIFIED, this.handleMessageModified, this); this.TUICore.tim.on(this.TUICore.TIM.EVENT.MESSAGE_REVOKED, this.handleMessageRevoked, this); this.TUICore.tim.on(this.TUICore.TIM.EVENT.MESSAGE_READ_BY_PEER, this.handleMessageReadByPeer, this); this.TUICore.tim.on(this.TUICore.TIM.EVENT.GROUP_LIST_UPDATED, this.handleGroupListUpdated, this); this.TUICore.tim.on(this.TUICore.TIM.EVENT.MESSAGE_READ_RECEIPT_RECEIVED, this.handleMessageReadReceiptReceived, this); } private unbindTIMEvent() { this.TUICore.tim.off(this.TUICore.TIM.EVENT.MESSAGE_RECEIVED, this.handleMessageReceived); this.TUICore.tim.off(this.TUICore.TIM.EVENT.MESSAGE_MODIFIED, this.handleMessageModified); this.TUICore.tim.off(this.TUICore.TIM.EVENT.MESSAGE_REVOKED, this.handleMessageRevoked); this.TUICore.tim.off(this.TUICore.TIM.EVENT.MESSAGE_READ_BY_PEER, this.handleMessageReadByPeer); this.TUICore.tim.off(this.TUICore.TIM.EVENT.GROUP_LIST_UPDATED, this.handleGroupListUpdated); this.TUICore.tim.off(this.TUICore.TIM.EVENT.MESSAGE_READ_RECEIPT_RECEIVED, this.handleMessageReadReceiptReceived); } private handleMessageReceived(event: any) { event?.data?.forEach((message: Message) => { if (message?.conversationID === this?.store?.conversation?.conversationID) { this.currentStore.messageList = [...this.currentStore.messageList, message]; } TUINotification.getInstance().notify(message); }); } private handleMessageModified(event: any) { const middleData = this.currentStore.messageList; this.currentStore.messageList = []; this.currentStore.messageList = middleData; } private handleMessageRevoked(event: any) { const middleData = this.currentStore.messageList; this.currentStore.messageList = []; this.currentStore.messageList = middleData; } private handleMessageReadByPeer(event: any) { const middleData = this.currentStore.messageList; this.currentStore.messageList = []; this.currentStore.messageList = middleData; } private handleGroupListUpdated(event: any) { event?.data.map((item: any) => { if (item?.groupID === this?.store?.conversation?.groupProfile?.groupID) { this.store.conversation.groupProfile = item; this.currentStore.conversation = {}; this.currentStore.conversation = this.store.conversation; } return item; }); } private handleMessageReadReceiptReceived(event: any) { const middleData = this.currentStore.messageList; this.currentStore.messageList = []; this.currentStore.messageList = middleData; } /** * ///////////////////////////////////////////////////////////////////////////////// * // * // 处理 TIM 接口参数及回调 * // Handling TIM interface parameters and callbacks * // * ///////////////////////////////////////////////////////////////////////////////// */ /** * 创建消息生成参数 * Create message generation parameters * * @param {Object} content 消息体 * @param {String} type 消息类型 text: 文本类型 file: 文件类型 face: 表情 location: 地址 custom: 自定义 merger: 合并 forward: 转发 * @param {Callback} callback 回调函数 * @param {any} to 发送的对象 * @returns {options} 消息参数 */ public handleMessageOptions(content: any, type: string, callback?: any, to?: any) { const options: any = { to: "", conversationType: to?.type || this.store.conversation.type, payload: content, needReadReceipt: this.currentStore.needReadReceipt, }; if (this.currentStore.needTyping) { options.cloudCustomData = { messageFeature: { needTyping: 1, version: 1, }, }; options.cloudCustomData = JSON.stringify(options.cloudCustomData); } if (type === "file" && callback) { options.onProgress = callback; } switch (options.conversationType) { case this.TUICore.TIM.TYPES.CONV_C2C: options.to = to?.userProfile?.userID || this.store.conversation?.userProfile?.userID || ""; break; case this.TUICore.TIM.TYPES.CONV_GROUP: options.to = to?.groupProfile?.groupID || this.store.conversation?.groupProfile?.groupID || ""; break; default: break; } return options; } /** * 处理异步函数 * Handling asynchronous functions * * @param {callback} callback 回调函数 * @returns {Promise} 返回异步函数 */ public handlePromiseCallback(callback: any) { return new Promise((resolve, reject) => { const config = { TUIName: "TUIChat", callback: () => { callback && callback(resolve, reject); }, }; this.TUICore.setAwaitFunc(config.TUIName, config.callback); }); } /** * 重试异步函数 * Retry asynchronous functions * 默认执行一次,之后按时间间隔列表重复执行直到成功,重复次数完毕后仍失败则失败 * Execute once by default, and then repeat it according to the time interval list until it succeeds. * If it still fails after the number of repetitions is complete, it will reject. * * @param {callback} callback 回调函数/callback function * @param {Array} intervalList 间隔时间列表/interval list * @param {callback} retryBreakFn 强制重复结束条件函数/break retry function * @returns {Promise} 返回异步函数/return */ public handlePromiseCallbackRetry( callback: any, intervalList: Array = [], retryBreakFn: any = function () { return false; } ): Promise { return new Promise((resolve, reject) => { let times = 0; function tryFn() { times++; callback() .then(resolve) .catch((error: any) => { if (times > intervalList.length || (retryBreakFn && retryBreakFn(error))) { reject(error); return; } setTimeout(tryFn, intervalList[times - 1]); }); } tryFn(); }); } /** * 文件上传进度函数处理 * File upload progress function processing * * @param {number} progress 文件上传进度 1表示完成 * @param {message} message 文件消息 */ public handleUploadProgress(progress: number, message: any) { this.currentStore.messageList.map((item: any) => { if (item.ID === message.ID) { item.progress = progress; } return item; }); } /** * 删除会话 * * @param {string} conversationID 会话ID * @returns {Promise} */ public async deleteConversation(conversationID: string) { return this.handlePromiseCallback(async (resolve: any, reject: any) => { try { const imResponse: any = await this.TUICore.tim.deleteConversation(conversationID); resolve(imResponse); } catch (error) { reject(error); } }); } /** * ///////////////////////////////////////////////////////////////////////////////// * // * // TIM 方法 * // TIM methods * // * ///////////////////////////////////////////////////////////////////////////////// */ /** * 发送表情消息 * Send face messages * * @param {Object} data 消息内容/message content * @param {Number} data.index 表情索引/face index * @param {String} data.data 额外数据/extra data * @returns {Promise} */ public sendFaceMessage(data: any): Promise { return this.handlePromiseCallback(async (resolve: any, reject: any) => { try { const options = this.handleMessageOptions(data, "face"); const message = this.TUICore.tim.createFaceMessage(options); this.currentStore.messageList.push(message); const imResponse = await this.TUICore.tim.sendMessage(message); this.currentStore.messageList = this.currentStore.messageList.map((item: any) => { if (item.ID === imResponse.data.message.ID) { return imResponse.data.message; } return item; }); resolve(imResponse); } catch (error) { reject(error); const middleData = this.currentStore.messageList; this.currentStore.messageList = []; this.currentStore.messageList = middleData; } }); } /** * 发送图片消息 * Send image message * * @param {Image} image 图片文件/image * @returns {Promise} */ public sendImageMessage(image: any): Promise { return this.handlePromiseCallback(async (resolve: any, reject: any) => { try { const options = this.handleMessageOptions({ file: image }, "file", (progress: number) => { this.handleUploadProgress(progress, message); }); const message = this.TUICore.tim.createImageMessage(options); message.progress = 0.01; this.currentStore.messageList.push(message); const imResponse = await this.TUICore.tim.sendMessage(message); this.currentStore.messageList = this.currentStore.messageList.map((item: any) => { if (item.ID === imResponse.data.message.ID) { return imResponse.data.message; } return item; }); resolve(imResponse); } catch (error) { reject(error); const middleData = this.currentStore.messageList; this.currentStore.messageList = []; this.currentStore.messageList = middleData; } }); } /** * 发送视频消息 * Send video message * * @param {Video} video 视频文件/video * @returns {Promise} */ public sendVideoMessage(video: any): Promise { return this.handlePromiseCallback(async (resolve: any, reject: any) => { try { const options = this.handleMessageOptions({ file: video }, "file", (progress: number) => { this.handleUploadProgress(progress, message); }); const message = this.TUICore.tim.createVideoMessage(options); message.progress = 0.01; this.currentStore.messageList.push(message); const imResponse = await this.TUICore.tim.sendMessage(message); this.currentStore.messageList = this.currentStore.messageList.map((item: any) => { if (item.ID === imResponse.data.message.ID) { return imResponse.data.message; } return item; }); resolve(imResponse); } catch (error) { reject(error); const middleData = this.currentStore.messageList; this.currentStore.messageList = []; this.currentStore.messageList = middleData; } }); } /** * 发送文件消息 * Send file message * * @param {File} file 文件/file * @returns {Promise} */ public sendFileMessage(file: any): Promise { return this.handlePromiseCallback(async (resolve: any, reject: any) => { try { const options = this.handleMessageOptions({ file }, "file", (progress: number) => { this.handleUploadProgress(progress, message); }); const message = this.TUICore.tim.createFileMessage(options); message.progress = 0.01; this.currentStore.messageList.push(message); const imResponse = await this.TUICore.tim.sendMessage(message); this.currentStore.messageList = this.currentStore.messageList.map((item: any) => { if (item.ID === imResponse.data.message.ID) { return imResponse.data.message; } return item; }); resolve(imResponse); } catch (error) { reject(error); const middleData = this.currentStore.messageList; this.currentStore.messageList = []; this.currentStore.messageList = middleData; } }); } /** * 发送自定义消息 * Send Custom message * * @param {Object} data 消息内容/message content * @param {String} data.data 自定义消息的数据字段/custom message data fields * @param {String} data.description 自定义消息的说明字段/custom message description fields * @param {String} data.extension 自定义消息的扩展字段/custom message extension fields * @returns {Promise} */ public sendCustomMessage(data: any): Promise { return this.handlePromiseCallback(async (resolve: any, reject: any) => { try { data.data = JSON.stringify(data.data); const options = this.handleMessageOptions(data, "custom"); const message = this.TUICore.tim.createCustomMessage(options); this.currentStore.messageList.push(message); const imResponse = await this.TUICore.tim.sendMessage(message); this.currentStore.messageList = this.currentStore.messageList.map((item: any) => { if (item.ID === imResponse.data.message.ID) { return imResponse.data.message; } return item; }); resolve(imResponse); } catch (error) { reject(error); const middleData = this.currentStore.messageList; this.currentStore.messageList = []; this.currentStore.messageList = middleData; } }); } /** * 发送地理位置消息 * Send location message * * @param {Object} data 消息内容/message content * @param {String} data.description 地理位置描述信息/geographic descriptive information * @param {Number} data.longitude 经度/longitude * @param {Number} data.latitude 纬度/latitude * @returns {Promise} */ public sendLocationMessage(data: any): Promise { return this.handlePromiseCallback(async (resolve: any, reject: any) => { try { const options = this.handleMessageOptions(data, "location"); const message = this.TUICore.tim.createLocationMessage(options); this.currentStore.messageList.push(message); const imResponse = await this.TUICore.tim.sendMessage(message); resolve(imResponse); } catch (error) { reject(error); const middleData = this.currentStore.messageList; this.currentStore.messageList = []; this.currentStore.messageList = middleData; } }); } /** * 转发消息 * forward message * * @param {message} message 消息实例/message * @param {any} to 转发的对象/forward to * @returns {Promise} */ public forwardMessage(message: any, to: any): Promise { return this.handlePromiseCallback(async (resolve: any, reject: any) => { try { const options = this.handleMessageOptions(message, "forward", {}, to); const imMessage = this.TUICore.tim.createForwardMessage(options); const imResponse = await this.TUICore.tim.sendMessage(imMessage); if (this.store.conversation.conversationID === imResponse.data.message.conversationID) { this.currentStore.messageList.push(imResponse.data.message); } resolve(imResponse); } catch (error) { reject(error); const middleData = this.currentStore.messageList; this.currentStore.messageList = []; this.currentStore.messageList = middleData; } }); } /** * 发送消息已读回执 * Send message read receipt * * @param {Array} messageList 同一个 C2C 或 GROUP 会话的消息列表,最大长度为30/A list of messages for the same C2C or GROUP conversation, with a maximum length of 30 * @returns {Promise} */ public async sendMessageReadReceipt(messageList: Array) { return this.handlePromiseCallback(async (resolve: any, reject: any) => { try { const imResponse: any = await this.TUICore.tim.sendMessageReadReceipt(messageList); resolve(imResponse); } catch (error) { reject(error); } }); } /** * 拉取已读回执列表 * Pull read receipt list * * @param {Array} messageList 同一群会话的消息列表/The message list of the same group of the conversation * @returns {Promise} */ public async getMessageReadReceiptList(messageList: Array) { return this.handlePromiseCallback(async (resolve: any, reject: any) => { try { const imResponse: any = await this.TUICore.tim.getMessageReadReceiptList(messageList); resolve(imResponse); } catch (error) { reject(error); } }); } /** * ///////////////////////////////////////////////////////////////////////////////// * // * // 对外方法 * // * ///////////////////////////////////////////////////////////////////////////////// */ /** * 获取 messageList * get messagelist * * @param {any} options 获取 messageList 参数/messageList options * @param {Boolean} history 是否获取历史消息/Whether to get historical information * @returns {Promise} */ public async getMessageList(options: any, history?: boolean) { return this.handlePromiseCallback(async (resolve: any, reject: any) => { try { const imResponse = await this.TUICore.tim.getMessageList(options); if (imResponse.data.messageList.length) { await this.getMessageReadReceiptList(imResponse.data.messageList); } if (!history) { this.currentStore.messageList = imResponse.data.messageList; } else { this.currentStore.messageList = [...imResponse.data.messageList, ...this.currentStore.messageList]; } this.currentStore.nextReqMessageID = imResponse.data.nextReqMessageID; this.currentStore.isCompleted = imResponse.data.isCompleted; resolve(imResponse); } catch (error) { reject(error); } }); } /** * 获取历史消息 * get history messagelist * * @returns {Promise} */ public async getHistoryMessageList() { const options = { conversationID: this.currentStore.conversation.conversationID, nextReqMessageID: this.currentStore.nextReqMessageID, count: 15, }; if (!this.currentStore.isCompleted) { this.getMessageList(options, true); } } /** * 发送文本消息 * send text message * * @param {any} text 发送的消息/text message * @param {object} data 被引用消息的内容/The content of the quoted message * @returns {Promise} */ public sendTextMessage(text: any, data: any): Promise { return this.handlePromiseCallback(async (resolve: any, reject: any) => { try { const options = this.handleMessageOptions({ text }, "text"); let cloudCustomDataObj = {}; if (options.cloudCustomData) { try { cloudCustomDataObj = JSONToObject(options.cloudCustomData); } catch { cloudCustomDataObj = {}; } } const cloudCustomData = JSON.stringify(data); const secondOptions = Object.assign(options, { cloudCustomData, ...cloudCustomDataObj, }); const message = this.TUICore.tim.createTextMessage(secondOptions); this.currentStore.messageList.push(message); const imResponse = await this.TUICore.tim.sendMessage(message); this.currentStore.messageList = this.currentStore.messageList.map((item: any) => { if (item.ID === imResponse.data.message.ID) { return imResponse.data.message; } return item; }); resolve(imResponse); } catch (error) { reject(error); const middleData = this.currentStore.messageList; this.currentStore.messageList = []; this.currentStore.messageList = middleData; } }); } /** * 发送【对方正在输入中】在线自定义消息 * send typing online custom message * * @param {Object} data 消息内容/message content * @param {String} data.data 自定义消息的数据字段/custom message data field * @param {String} data.description 自定义消息的说明字段/custom message description field * @param {String} data.extension 自定义消息的扩展字段/custom message extension field * @returns {Promise} */ public sendTypingMessage(data: any): Promise { return this.handlePromiseCallback(async (resolve: any, reject: any) => { try { data.data = JSON.stringify(data.data); const options = this.handleMessageOptions(data, "custom"); const message = this.TUICore.tim.createCustomMessage(options); const imResponse = await this.TUICore.tim.sendMessage(message, { onlineUserOnly: true, }); resolve(imResponse); } catch (error) { reject(error); const middleData = this.currentStore.messageList; this.currentStore.messageList = []; this.currentStore.messageList = middleData; } }); } /** * 发送@ 提醒功能的文本消息 * Send @ Reminder text message * * @param {any} data 消息内容/message content * @param {String} data.text 文本消息/text message * @param {Array} data.atUserList 需要 @ 的用户列表,如果需要 @ALL,请传入 TIM.TYPES.MSG_AT_ALL / List of users who need @, if you need @ALL, please pass in TIM.TYPES.MSG_AT_ALL * @returns {message} * * - 注:此接口仅用于群聊/This interface is only used for group chat */ public sendTextAtMessage(data: any) { return this.handlePromiseCallback(async (resolve: any, reject: any) => { try { const options = this.handleMessageOptions(data, "text"); const message = this.TUICore.tim.createTextAtMessage(options); this.currentStore.messageList.push(message); const imResponse = await this.TUICore.tim.sendMessage(message); this.currentStore.messageList = this.currentStore.messageList.map((item: any) => { if (item.ID === imResponse.data.message.ID) { return imResponse.data.message; } return item; }); resolve(imResponse); } catch (error) { reject(error); const middleData = this.currentStore.messageList; this.currentStore.messageList = []; this.currentStore.messageList = middleData; } }); } /** * 发送合并消息 * send merger message * * @param {Object} data 消息内容/message content * @param {Array.} data.messageList 合并的消息列表/merger message list * @param {String} data.title 合并的标题/merger title * @param {String} data.abstractList 摘要列表,不同的消息类型可以设置不同的摘要信息/Summary list, different message types can set different summary information * @param {String} data.compatibleText 兼容文本/ompatible text * @returns {Promise} */ public sendMergerMessage(data: any): Promise { return this.handlePromiseCallback(async (resolve: any, reject: any) => { try { const options = this.handleMessageOptions(data, "merger"); const message = this.TUICore.tim.createMergerMessage(options); this.currentStore.messageList.push(message); const imResponse = await this.TUICore.tim.sendMessage(message); this.currentStore.messageList = this.currentStore.messageList.map((item: any) => { if (item.ID === imResponse.data.message.ID) { return imResponse.data.message; } return item; }); resolve(imResponse); } catch (error) { reject(error); const middleData = this.currentStore.messageList; this.currentStore.messageList = []; this.currentStore.messageList = middleData; } }); } /** * 消息撤回 * revoke message * * @param {message} message 消息实例/message * @returns {Promise} */ public revokeMessage(message: any): Promise { return this.handlePromiseCallback(async (resolve: any, reject: any) => { try { const imResponse = await this.TUICore.tim.revokeMessage(message); const cloudCustomData = JSONToObject(message?.cloudCustomData); if (cloudCustomData?.messageReply?.messageRootID) { await this.revokeReplyMessage(message); } resolve(imResponse); } catch (error) { reject(error); const middleData = this.currentStore.messageList; this.currentStore.messageList = []; this.currentStore.messageList = middleData; } }); } /** * 重发消息 * resend message * * @param {message} message 消息实例/message * @returns {Promise} */ public resendMessage(message: any): Promise { return this.handlePromiseCallback(async (resolve: any, reject: any) => { try { const imResponse = await this.TUICore.tim.resendMessage(message); this.currentStore.messageList = this.currentStore.messageList.filter((item: any) => item.ID !== message.ID); this.currentStore.messageList.push(imResponse.data.message); resolve(imResponse); } catch (error) { reject(error); } }); } /** * 删除消息 * delete message * * @param {Array.} messages 消息实例/message * @returns {Promise} */ public deleteMessage(messages: any): Promise { return this.handlePromiseCallback(async (resolve: any, reject: any) => { try { const imResponse = await this.TUICore.tim.deleteMessage(messages); resolve(imResponse); const middleData = this.currentStore.messageList; this.currentStore.messageList = []; this.currentStore.messageList = middleData; } catch (error) { reject(error); } }); } /** * 变更消息 * modify message * * @param {Array.} message 消息实例/message * @returns {Promise} */ public modifyMessage(message: any): Promise { return this.handlePromiseCallback(async (resolve: any, reject: any) => { try { const imResponse = await this.TUICore.tim.modifyMessage(message); resolve(imResponse); } catch (error) { // 修改消息失败 // Modify message error const code = (error as any)?.code; const data = (error as any)?.data; if (code === 2480) { console.warn("MODIFY_MESSAGE_ERROR", "修改消息发生冲突,data.message 是最新的消息", "data.message:", data?.message); } else if (code === 2481) { console.warn("MODIFY_MESSAGE_ERROR", "不支持修改直播群消息"); } else if (code === 20026) { console.warn("MODIFY_MESSAGE_ERROR", "消息不存在"); } reject(error); } }); } /** * 回复消息 * reply message * @param {Array.} message 消息实例/message * @returns {Promise} */ public replyMessage(message: any, messageRoot?: any): Promise { const replyFunction = () => { return this.handlePromiseCallback(async (resolve: any, reject: any) => { try { const repliesObject = { messageAbstract: message?.payload?.text, messageSender: message?.from, messageID: message?.ID, messageType: message?.type, messageTime: message?.time, messageSequence: message?.sequence, version: 1, }; if (!messageRoot) { const cloudCustomData = JSONToObject(message?.cloudCustomData); const messageRootID = cloudCustomData?.messageReply?.messageRootID; messageRoot = (await this?.currentStore?.messageList?.find((item: any) => item?.ID === messageRootID)) || this.findMessage(messageRootID); } const rootCloudCustomData = messageRoot?.cloudCustomData ? JSONToObject(messageRoot?.cloudCustomData) : { messageReplies: {} }; if (rootCloudCustomData?.messageReplies?.replies) { rootCloudCustomData.messageReplies.replies = [ // eslint-disable-next-line no-unsafe-optional-chaining ...rootCloudCustomData?.messageReplies?.replies, repliesObject, ]; } else { rootCloudCustomData.messageReplies = { replies: [repliesObject], version: 1, }; } messageRoot.cloudCustomData = JSON.stringify(rootCloudCustomData); const imResponse = this.modifyMessage(messageRoot); resolve(imResponse); } catch (error) { reject(error); } }); }; const retryBreakFunction = function (error: any) { if (error && error?.code === 2480) return false; return true; }; return this.handlePromiseCallbackRetry(replyFunction, [500, 1000, 3000], retryBreakFunction); } /** * 撤回回复消息 * revoke reply message * @param {Array.} message 消息实例/message * @returns {Promise} */ public revokeReplyMessage(message: any, messageRoot?: any): Promise { const revokeReplyFunction = () => { return this.handlePromiseCallback(async (resolve: any, reject: any) => { try { if (!messageRoot) { const cloudCustomData = JSONToObject(message?.cloudCustomData); const messageRootID = cloudCustomData?.messageReply?.messageRootID; messageRoot = (await this?.currentStore?.messageList?.find((item: any) => item?.ID === messageRootID)) || this.findMessage(messageRootID); } const rootCloudCustomData = messageRoot?.cloudCustomData ? JSONToObject(messageRoot?.cloudCustomData) : { messageReplies: {} }; if (rootCloudCustomData?.messageReplies?.replies) { const index = rootCloudCustomData.messageReplies.replies.findIndex((item: any) => item?.messageID === message?.ID); rootCloudCustomData?.messageReplies?.replies?.splice(index, 1); } messageRoot.cloudCustomData = JSON.stringify(rootCloudCustomData); const imResponse = this.modifyMessage(messageRoot); resolve(imResponse); } catch (error) { reject(error); } }); }; const retryBreakFunction = function (error: any) { if (error && error?.code === 2480) return false; return true; }; return this.handlePromiseCallbackRetry(revokeReplyFunction, [500, 1000, 3000], retryBreakFunction); } /** * 表情回应 * emoji react * @param {Array.} message 消息实例/message * @returns {Promise} */ public emojiReact(message: any, emojiID: any): Promise { const emojiReactFunction = () => { return this.handlePromiseCallback(async (resolve: any, reject: any) => { try { if (!message || !message?.ID || !emojiID) reject(); const userID = this.TUICore?.TUIServer?.TUIProfile?.store?.profile?.userID; message = (await this?.currentStore?.messageList?.find((item: any) => item?.ID === message?.ID)) || this.findMessage(message?.ID); const cloudCustomData = message?.cloudCustomData ? JSONToObject(message?.cloudCustomData) : { messageReact: {} }; if (cloudCustomData?.messageReact?.reacts) { if (cloudCustomData?.messageReact?.reacts[emojiID]) { const index = cloudCustomData?.messageReact?.reacts[emojiID]?.indexOf(userID); if (index === -1) { cloudCustomData?.messageReact?.reacts[emojiID]?.push(userID); } else { cloudCustomData?.messageReact?.reacts[emojiID]?.splice(index, 1); if (cloudCustomData?.messageReact?.reacts[emojiID]?.length === 0) { delete cloudCustomData?.messageReact?.reacts[emojiID]; } } } else { cloudCustomData.messageReact.reacts[emojiID] = [userID]; } } else { cloudCustomData.messageReact = { reacts: {}, version: 1, }; cloudCustomData.messageReact.reacts[emojiID] = [userID]; } message.cloudCustomData = JSON.stringify(cloudCustomData); const imResponse = this.modifyMessage(message); resolve(imResponse); } catch (error) { reject(error); } }); }; const retryBreakFunction = function (error: any) { if (error && error?.code === 2480) return false; return true; }; return this.handlePromiseCallbackRetry(emojiReactFunction, [500, 1000, 3000], retryBreakFunction); } /** * 查询消息 * find message * @param {String} messageID 消息实例ID/messageID * @returns {Promise} */ public findMessage(messageID: string): Promise { return this.handlePromiseCallback(async (resolve: any, reject: any) => { try { const imResponse = await this.TUICore.tim.findMessage(messageID); resolve(imResponse); } catch (error) { reject(error); } }); } /** * 获取群组属性 * get group profile * * @param {any} options 参数 * @param {String} options.groupID 群组ID * @param {Array.} options.groupProfileFilter 群资料过滤器 * @returns {Promise} */ public getGroupProfile(options: any): Promise { return this.handlePromiseCallback(async (resolve: any, reject: any) => { try { const imResponse = await this.TUICore.tim.getGroupProfile(options); this.currentStore.conversation.groupProfile = imResponse.data.group; resolve(imResponse); } catch (error) { reject(error); } }); } /** * 获取群成员资料 * get group member profile * * @param {any} options 参数 * @param {String} options.groupID 群组ID * @param {Array.} options.userIDList 要查询的群成员用户 ID 列表 * @param { Array.} options.memberCustomFieldFilter 群成员自定义字段筛选 * @returns {Promise} */ public getGroupMemberProfile(options: any): Promise { return this.handlePromiseCallback(async (resolve: any, reject: any) => { try { const imResponse = await this.TUICore.tim.getGroupMemberProfile(options); resolve(imResponse); } catch (error) { reject(error); } }); } /** * 处理申请加群 * handling group application * - 管理员 * administrator * * @param {any} options 参数 * @param {String} options.handleAction 处理结果 Agree(同意) / Reject(拒绝) * @param {String} options.handleMessage 附言 * @param {Message} options.message 对应【群系统通知】的消息实例 * @returns {Promise} */ public handleGroupApplication(options: any): Promise { return this.handlePromiseCallback(async (resolve: any, reject: any) => { try { const imResponse = await this.TUICore.tim.handleGroupApplication(options); resolve(imResponse); } catch (error) { reject(error); } }); } /** * 获取其他用户资料 * get user profile * * @param {Array} userIDList 用户的账号列表/userID list * @returns {Promise} */ public async getUserProfile(userIDList: Array) { return this.handlePromiseCallback(async (resolve: any, reject: any) => { try { const imResponse = await this.TUICore.tim.getUserProfile({ userIDList, }); resolve(imResponse); } catch (error) { reject(error); } }); } /** * 获取 SDK 缓存的好友列表 * Get the friend list cached by the SDK * * @param {Array} userIDList 用户的账号列表 * @returns {Promise} */ public async getFriendList(): Promise { return this.handlePromiseCallback(async (resolve: any, reject: any) => { try { const imResponse = await this.TUICore.tim.getFriendList(); resolve(imResponse); } catch (error) { reject(error); } }); } /** * 校验好友关系 * check friend * * @param {string} userID 用户账号 * @returns {Promise} */ public async checkFriend(userID: string, type: string): Promise { return this.handlePromiseCallback(async (resolve: any, reject: any) => { try { const imResponse = await this.TUICore.tim.checkFriend({ userIDList: [userID], type, }); const isFriendShip = imResponse?.data?.successUserIDList[0]?.relation; resolve(isFriendShip); } catch (error) { reject(error); } }); } /** * 获取群消息已读成员列表 * Get the list of memebers who have read the group message. * * @param {message} message 消息实例/message * @param {string} cursor 分页拉取的游标,第一次拉取传''/Paging pull the cursor,first pull pass '' * @param {number} count 分页拉取的个数/The number of page pulls * @returns {Promise} */ public async getGroupReadMemberList(message: any, cursor = "", count = 15): Promise { return this.handlePromiseCallback(async (resolve: any, reject: any) => { try { const imResponse = await this.TUICore.tim.getGroupMessageReadMemberList({ message, filter: 0, cursor, count, }); resolve(imResponse); } catch (error) { reject(error); } }); } /** * 获取群消息未读成员列表 * Get the list of memebers who have not read the group message. * * @param {message} message 消息实例/message * @param {string} cursor 分页拉取的游标,第一次拉取传''/Paging pull the cursor,first pull pass '' * @param {number} count 分页拉取的个数/The number of page pulls * @returns {Promise} */ public async getGroupUnreadMemberList(message: any, cursor = "", count = 15): Promise { return this.handlePromiseCallback(async (resolve: any, reject: any) => { try { const imResponse = await this.TUICore.tim.getGroupMessageReadMemberList({ message, filter: 1, cursor, count, }); resolve(imResponse); } catch (error) { reject(error); } }); } /** * 自己发送消息上屏显示 * * @param {message} message 消息实例/message */ public async handleMessageSentByMeToView(message: any) { if (message?.conversationID === this?.store?.conversation?.conversationID) { this.currentStore.messageList.push(message); } return; } /** * ///////////////////////////////////////////////////////////////////////////////// * // * // UI 数据绑定server数据同步 * // UI data binding server data synchronization * // * ///////////////////////////////////////////////////////////////////////////////// */ /** * 赋值 * bind * * @param {Object} params 使用的数据/params * @returns {Object} 数据/data */ public bind(params: any) { return (this.currentStore = params); } }