Files
im-system/uni-im示例/uni_modules/uni-im/uniCloud/cloudfunctions/uni-im-co/index.obj.js
2023-09-24 17:55:19 +08:00

1132 lines
29 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.
// 云对象教程: https://uniapp.dcloud.net.cn/uniCloud/cloud-obj
// jsdoc语法提示教程https://ask.dcloud.net.cn/docs/#//ask.dcloud.net.cn/article/129
const db = uniCloud.database();
// 会话表
const conversationTable = db.collection('uni-im-conversation')
// 消息表
const msgTable = db.collection('uni-im-msg')
// 群成员表
const groupMemberTable = db.collection('uni-im-group-member')
// 用户表
const usersTable = db.collection('uni-id-users')
// uni-id公共模块
const uniIdCommon = require('uni-id-common')
const dbCmd = db.command
const $ = dbCmd.aggregate
// 哈希算法用于生成会话id
const md5 = require("md5");
// 获取uni-im配置
const createConfig = require("uni-config-center");
const uniImConfig = createConfig({
pluginId: 'uni-im', // 插件id
})
module.exports = {
async _before() {
// 获取客户端信息
this.clientInfo = this.getClientInfo()
// console.log(this.clientInfo);
// 定义uni-id公共模块对象
this.uniIdCommon = uniIdCommon.createInstance({
clientInfo: this.clientInfo
})
// 指定需要使用当前用户身份id的云对的方法名称需要验证用户的token信息
const needLoginMethodName = [
"sendMsg",
"revokeMsg",
"addFriendInvite",
"getJoinGroupList",
"getConversationList",
"chooseUserIntoGroup"
]
if (
needLoginMethodName.includes(this.getMethodName())
) {
// 云函数互调时免校验token直接使用传来的用户id
if (this.getClientInfo().source == 'function') {
this.current_uid = this.getParams()[1]
} else {
let res = await this.uniIdCommon.checkToken(this.clientInfo.uniIdToken)
if (res.errCode) {
// 如果token校验出错则抛出错误
throw res
} else {
// 通过token校验则拿去用户id
this.current_uid = res.uid
}
}
}
// 提醒用户需要连接云端云函数
// if(this.getMethodName() == 'sendMsg' && this.clientInfo.clientIP == "127.0.0.1"){
// throw {
// errSubject: 'uni-im-co-sendMsg',
// errCode: "uni-im-co-sendMsg-error",
// errMsg: '发送消息方法仅限连接云端云函数使用在HBuilderX uniCloud控制台切换'
// }
// }
// 封装push方法
this.sendPushMsg = async (param, appId) => {
let pushParam = {
// 验证token是否有效无效则不向此设备推送消息
check_token: true,
settings: {
//-1表示不设离线因为离线后重新打开数据统一从数据库中拉取。否则会重复
ttl: -1
},
// 离线推送厂商信息配置,需要到云厂商后台申请
channel: {
// 华为离线推送
"HW": "NORMAL",
// 小米离线推送
"XM": "high_system"
}
}
/**
* 如果不指定接收消息的客户端appid则指定为消息推送者的客户端appid。
* 用于两个客户端appid不同的场景比如电商项目商家和普通用户端appid不同
*/
if (!appId) {
appId = this.clientInfo.appId
if (!appId) {
throw new Error('appId is not definded')
}
}
pushParam = Object.assign(pushParam, param)
// 如果是im通知消息比如加好友申请用户请求加群用户退群等则记录到数据表uni-im-notification中
if (param.payload.type == "uni-im-notification") {
let {
title,
content,
payload,
sound,
open_url,
path,
user_id
} = pushParam
let notificationContent = {
title,
content,
payload,
sound,
open_url,
path
}
notificationContent.is_read = false
notificationContent.create_time = Date.now()
let notificationData;
// 如果接收消息的用户量不止一个,则需要插入数据表的记录为多条(数组)
if (Array.isArray(user_id)) {
notificationData = user_id.map(uid => {
return {
user_id: uid,
...notificationContent
}
})
} else {
notificationData = Object.assign(notificationContent, {
user_id
})
}
// 执行写入到数据库
let uinRes = await db.collection('uni-im-notification').add(notificationData)
// console.log('uinRes',uinRes)
param.payload.notificationId = uinRes.id
}
let res = await uniCloud.getPushManager({
appId
}).sendMessage(pushParam)
if (res.errCode) {
if (res.errCode == "uni-push-user-invalid") {
//可能因为用户长时间没有登录导致的cid过期而发送失败但是此时已将离线数据写入数据库登录后可获取。客户端不需要进入 catch
res = {
data: {
"uni-push-err-res": res
},
errCode: 0
}
} else {
console.log(res.errCode);
throw new Error(res.errMsg)
}
}
return res
}
},
_after(error, result) {
if (error) {
console.log({
error,
result
});
if (error.errCode && error.errMsg) {
// 符合响应体规范的错误,直接返回
return error
} else {
throw error // 直接抛出异常
}
}
return result
},
// 获取会话列表
async getConversationList({
// 会话条数
limit = 500,
// 最大的会话更新时间
maxUpdateTime = false,
// 不为false则表示获取指定的会话
conversation_id = false
}) {
let matchObj = {
// 限制只能查询当前用户自己的会话记录
"user_id": this.current_uid,
// "group_id": dbCmd.exists(false), //是否查询群聊会话
}
if (conversation_id) {
matchObj.id = conversation_id
} else if (maxUpdateTime) {
matchObj.update_time = dbCmd.lt(maxUpdateTime)
}
let res = await conversationTable.aggregate()
.sort({
// 根据更新时间倒序
update_time: -1
})
.match(matchObj)
.limit(limit)
// 联查获得最新的对话记录
.lookup({
from: "uni-im-msg",
let: {
id: '$id'
},
pipeline: $.pipeline()
.match(
dbCmd.expr($.eq(['$conversation_id', '$$id']))
)
.sort({
create_time: -1
})
.limit(1)
.project({
_id: 1,
type: 1,
body: 1,
to_uid: 1,
is_read: 1,
from_uid: 1,
create_time: 1,
conversation_id: 1
})
.done(),
as: 'msgList'
})
// 联查获得对话的用户信息
// .lookup({
// from: "uni-id-users",
// let: {
// friend_uid: '$friend_uid'
// },
// pipeline: $.pipeline()
// .match(
// dbCmd.expr($.eq(['$_id', '$$friend_uid']))
// )
// .limit(1)
// .project({
// _id: 1,
// avatar_file: 1,
// nickname: 1
// })
// .done(),
// as: 'user_info'
// })
// 联查获得对话的群信息
.lookup({
from: "uni-im-group",
let: {
group_id: '$group_id'
},
pipeline: $.pipeline()
.match(
dbCmd.expr($.eq(['$_id', '$$group_id']))
)
.project({
user_id: 1,
name: 1,
introduction: 1,
notification: 1,
avatar_file: 1,
join_option: 1
})
.done(),
as: 'group_info'
})
.end()
const dbJQL = uniCloud.databaseForJQL({
clientInfo: this.clientInfo
})
let friend_uids = res.data.map(item=>item.friend_uid).filter(i=>i)
let usersInfoRes = await dbJQL.collection('uni-id-users')
.where(`_id in ${JSON.stringify(friend_uids)}`)
.field('_id,avatar_file,nickname')
.get()
let usersInfoObj = {}
usersInfoRes.data.forEach(item=>{
usersInfoObj[item._id] = item
})
res.data.forEach(item=>{
item.user_info = [usersInfoObj[item.friend_uid]]
})
return {
data: res.data,
errCode: 0
}
},
// 发送消息方法(含:单聊和群聊)
async sendMsg(params, context) {
let {
// 指定接收消息的用户id
to_uid,
// 指定接收消息的群id
group_id,
// 消息内容
body,
// 消息类型
type,
// 是否为失败 重试
isRetries,
// 接收消息的客户端的DCloud appid
appId,
// 回复关联的消息的id
about_msg_id
} = params
// 校验参数是否合法
check_param(params, {
"required": ["body", "type", "appId"],
"type": {
to_uid: ["String"],
group_id: ["String"],
body: ["String", "Object"],
type: ["String"],
isRetries: ["Boolean"],
appId: ["String"],
about_msg_id: ['String']
}
})
// 补充特殊校验
if (!to_uid && !group_id) {
throw new Error('接收消息的用户id和群id最少指定一个') // alert否则表示将消息群发
}
//发送者身份id
const from_uid = this.current_uid
/** 读取配置的对话等级,校验是否有权发送消息
* 0 - 任何人可以发起会话
* 100 - 客服 or 好友或者群成员
* 200 - 必须是好友或者群成员
**/
const conversation_grade = uniImConfig.config('conversation_grade')
// 客服模式下如果配置的客服id。则只能向客服发起会话
async function chatToCustomerService() {
const customer_service_uids = uniImConfig.config('customer_service_uids_uids')
if (customer_service_uids) {
if (typeof customer_service_uids == 'string') {
customer_service_uids = [customer_service_uids]
}
if (
!(customer_service_uids.includes(from_uid) || customer_service_uids.includes(to_uid))
) {
throw new Error('非法通讯会话双方用户id均不属于uni-im-co中配置的customer_service_uids')
}
}
return true
}
// 只能是好友关系,或者群成员才能发送
async function chatToFriendOrGroupMember() {
if (group_id) {
let {
data: [has]
} = await db.collection('uni-im-group-member')
.where({
group_id,
user_id: this.current_uid
})
.get()
if (!has) {
throw new Error('非群成员不能发起会话')
}
}
if (to_uid) {
let {
data: [has]
} = await db.collection('uni-im-friend')
.where({
friend_uid: to_uid,
user_id: this.current_uid
})
.get()
if (!has) {
throw new Error('非好友不能发起会话')
}
}
return true
}
switch (conversation_grade) {
case 0:
//任何人可以发起会话,不校验
break;
case 100:
// 客服 or 好友或者群成员
try {
await chatToCustomerService()
} catch (error) {
console.error(error)
await chatToFriendOrGroupMember()
}
break;
case 200:
// 必须是好友或者群成员
await chatToFriendOrGroupMember()
break;
default:
break;
}
// 生成会话id
const conversation_id = group_id ? 'group_' + group_id : getConversationId([from_uid, to_uid])
// 构建基本消息内容
const msgData = {
body,
type,
from_uid,
to_uid,
//是否已读默认为false
is_read: false,
//创建时间
create_time: Date.now(),
conversation_id,
group_id,
appid: appId, //接收消息的appid撤回消息时会用到
about_msg_id
}
// 设置会话 最后一条消息 的描述。文本=>文本的前30个字 其他=>消息类型
let last_msg_note = '[多媒体]'
if (type == 'text') {
last_msg_note = body.toString()
last_msg_note = last_msg_note.replace(/[\r\n]/g, "");
last_msg_note = last_msg_note.slice(0, 30)
} else {
last_msg_note = {
"image": "[图片]",
"sound": "语音",
"video": "[视频]",
"file": "文件",
"location": "位置"
} [type]
}
// 查会话表是否存在
let {
data: [conversation]
} = await conversationTable.where({
id: conversation_id
}).get()
// 如果没有,需要先创建会话记录
if (!conversation) {
// 1.消息接收者 会话数据
let data1 = {
id: conversation_id,
type: msgData.group_id ? 2 : 1,
user_id: msgData.to_uid,
friend_uid: msgData.from_uid,
group_id: msgData.group_id,
unread_count: 1,
last_msg_note,
update_time: msgData.create_time,
create_time: msgData.create_time
}
// 2.消息发送者 会话数据
let data2 = {
...data1,
unread_count: 0,
user_id: msgData.from_uid,
friend_uid: msgData.to_uid
}
let res = await conversationTable.add([data1, data2])
// console.log(res);
} else {
// 对方的会话表更新,并且未读数+1
let res = await conversationTable.where({
id: conversation_id,
user_id: to_uid
}).update({
unread_count: dbCmd.inc(1),
last_msg_note,
update_time: msgData.create_time
})
// console.log(res);
//自己的会话表更新。仅更新最后一条消息的时间和内容
res = await conversationTable.where({
id: conversation_id,
user_id: from_uid
}).update({
last_msg_note,
update_time: msgData.create_time
})
// console.log(res);
}
// console.log({
// ...msgData,
// conversation_id
// });
// 将消息内容存到数据库,点击重发按钮的除外
if (!isRetries) {
let res = await msgTable.add({
...msgData,
conversation_id
})
msgData._id = res.id
// console.log('msgTable msgData:', res);
}
// 处理超长文本push发送不了的问题
if (msgData.body.length > 250) {
// 截断,但标识消息为长文本消息,客户端收到此标识,会从数据库中拉取完整消息内容
msgData.body = msgData.body.slice(0, 50)
msgData.LongMsg = true
}
// 查询消息发送者的头像和昵称
const dbJQL = uniCloud.databaseForJQL({
clientInfo: this.clientInfo
})
let res = await dbJQL.collection('uni-id-users')
.doc(from_uid)
.field('_id,nickname,avatar_file')
.get()
let {
nickname,
avatar_file
} = res.data[0]
let title = nickname.slice(0, 20)
let content = msgData.type == 'text' ? msgData.body : '[多媒体]'
// 定义推送参数
let pushParam = {
// 同时发给对方和当前用户自己包括了他的其他设备比如web和app、小程序同时登录时实现消息同步发送此消息的设备会在客户端过滤
"user_id": [msgData.to_uid, msgData.from_uid],
"payload": {
type: "uni-im",
data: msgData,
title, // "收到im消息在线时显示的标题",
content, // "在线时显示的副标题",
avatar_file, //头像文件对象,
device_id: this.clientInfo.deviceId // 发送消息的设备客户端id阻止当前用户收到自己发的消息
},
title: title.slice(0, 20), // "收到im消息离线时显示的标题",
content: content.slice(0, 50) //"离线时显示的内容"
}
if (msgData.to_uid) {
//单聊直接调用before中封装好的消息推送方法
res = await this.sendPushMsg(pushParam, appId)
// console.log('sendMessage', JSON.stringify(res))
/*
//判断是否已经有客户端接收到消息,注意:收到不等于已读
let taskData = res.data[Object.keys(res.data)]
let state = false;
for (let key in taskData) {
if (taskData[key] == 'successed_online') {
state = true
break
}
}
console.log('state : ============> ' + state);*/
} else if (msgData.group_id) {
// console.error('群聊消息*-----------------',pushParam);
delete pushParam.user_id
// 如果是群聊则调用sendMsgToGroup云方法递归发送500个为用户一批
uniCloud.importObject('uni-im-co')
.sendMsgToGroup({
pushParam,
appId
})
// 等待500毫秒给一个请求发出去的时间
await new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
}, 500)
})
res = {
errCode: 0
}
} else {
throw new Error('接受者标识,不能为空')
}
if (!res.data) {
res.data = {}
}
// 返回云端消息记录创建的时间
res.data.create_time = msgData.create_time
// 返回云端消息记录的id
res.data._id = msgData._id
return res
},
async sendPushMsg(pushParam, appId) {
// 注意这是用于在触发器中调用推送的方法。不是this.sendPushMsg调用的方法this.sendPushMsg定义在before中
if (this.getClientInfo().source != 'function') {
return {
errSubject: 'uni-im-co',
errCode: 0,
errMsg: '该方法仅支持云对象的方法,或者触发器调用'
}
}
// console.log('pushParam', pushParam);
return await this.sendPushMsg(pushParam, appId)
},
async sendMsgToGroup({
pushParam,
before_id,
push_clientids = [],
member = [],
appId
}) {
// 注意:这是一个递归云对象,用递归的方式处理批量任务
const limit = 500 //腾讯云收费版服务空间可以改成 1000
if (this.getClientInfo().source != 'function') {
return {
errSubject: 'uni-im-co',
errCode: 0,
errMsg: '该方法仅支持云对象的方法,或者触发器调用'
}
}
// console.log('sendMsgToGroup=========', {
// pushParam,
// before_id,
// push_clientids
// });
if (before_id || push_clientids) {
// console.log({
// before_id,
// push_clientids
// });
// return 123
}
if (push_clientids.length === 0) {
// console.log('开始查库', push_clientids.length, push_clientids);
let group_id = pushParam.payload.data.group_id
if (!group_id) {
throw new Error('群id不能为空')
}
let getMemberwhere = {
group_id
}
if (before_id) {
getMemberwhere._id = dbCmd.gt(before_id)
}
// console.log({
// getMemberwhere
// });
let res = await groupMemberTable
.aggregate()
.match(getMemberwhere)
.sort({
_id: 1
})
.limit(limit)
.project({
user_id: 1
})
.lookup({
from: "uni-id-device",
let: {
user_id: '$user_id'
},
pipeline: $.pipeline()
.match(
dbCmd.expr(
$.and([
$.eq(['$user_id', '$$user_id']),
$.gt(['$token_expired', Date.now()])
])
)
).project({
push_clientid: 1
})
.done(),
as: 'push_clientids',
})
.end()
member = res.data
// console.error('符合条件的用户数', member, member.length);
push_clientids = member.reduce((sum, item) => {
sum.push(...item.push_clientids.map(i => i.push_clientid))
return sum
}, [])
// console.error('查到需要接收消息的设备数:', push_clientids.length);
} else {
// console.log('不需要查库,继续发送任务', push_clientids.length);
}
if (push_clientids.length === 0) {
// console.error('没有更多用户需要接收消息');
return {
errCode: 0,
errMsg: ''
}
} else {
// console.log('push_clientids====>', push_clientids)
}
let next_push_clientids = push_clientids.slice(limit)
push_clientids = push_clientids.slice(0, limit)
pushParam.push_clientid = push_clientids
console.log("pushParam", pushParam);
let sendPushMsgRes = await this.sendPushMsg(pushParam, appId)
// console.error(sendPushMsgRes)
if (next_push_clientids.length !== 0) {
uniCloud.importObject('uni-im-co').sendMsgToGroup({
pushParam,
push_clientids: next_push_clientids,
member
}, appId)
// 等待500毫秒给一个请求发出去的时间
return await new Promise((resolve, reject) => {
setTimeout(() => {
resolve({
errCode: 0,
errMsg: ''
})
}, 500)
})
} else if (member.length == limit) {
// console.log('member---*--*', member);
before_id = member[member.length - limit]._id
uniCloud.importObject('uni-im-co').sendMsgToGroup({
pushParam,
before_id
}, appId)
// 等待500毫秒给一个请求发出去的时间
return await new Promise((resolve, reject) => {
setTimeout(() => {
resolve({
errCode: 0,
errMsg: ''
})
}, 500)
})
} else {
return {
errCode: 0,
errMsg: ''
}
}
},
async addFriendInvite({
to_uid,
message
}) {
const from_uid = this.current_uid
// console.log('from_uid-----', from_uid);
if (this.current_uid == to_uid) {
throw new Error('不能加自己为好友')
}
let {
data: [has]
} = await db.collection('uni-im-friend').where({
user_id: from_uid,
friend_uid: to_uid
}).get()
if (has) {
return {
errSubject: 'uni-im-co',
errCode: 1000,
errMsg: '已经是好友'
}
}
// 检查是不是黑名单
//略
let docId = md5(JSON.stringify([from_uid, to_uid]))
// 不存在就添加,存在就更新
let res = await db.collection('uni-im-friend-invite').doc(docId)
.set({
from_uid,
to_uid,
message
})
// console.log({
// res
// });
/*const dbJQL = uniCloud.databaseForJQL({
clientInfo
})
dbJQL.setUser({
uid: from_uid, // 建议此处使用真实uid
role: ['admin'], // 指定当前执行用户的角色为admin。如果只希望指定为admin身份可以删除uid和permission节点
permission: []
})*/
const dbJQL = uniCloud.databaseForJQL({
clientInfo: this.clientInfo
})
let {
data: [userInfo]
} = await dbJQL.collection('uni-id-users')
.doc(this.current_uid)
.field('_id,nickname,avatar_file')
.get()
// console.log({
// userInfo
// });
let {
nickname
} = userInfo
let title = nickname.slice(0, 20),
content = message || "请求添加对方为好友"
let pushParam = {
user_id: to_uid,
payload: {
type: "uni-im-notification", // im消息通知比如加好友请求有用户退群等
subType: "uni-im-friend-invite", // 通知子类型(可选)
avatar_file: userInfo.avatar_file, // 头像或图标的图片地址支持Base64
confirmText: "同意", // 确认按钮的文字(可选)
// cancelText: "拒绝", // 取消按钮的文字(可选)
state: false, // 是否已经处理过 false 未处理confirm已确认cancel已拒绝可选
unique: from_uid, // 去重字段,比如同一个用户重复申请加好友,通知数据始终只显示一条,但是会通知多次(可选)
data: { // 自定义的其他参数(可选)
"_id": docId,
from_uid
},
path: false
},
title, // "收到im消息离线时显示的标题",
content, //"离线时显示的内容"
path: false
}
return await this.sendPushMsg(pushParam, this.clientInfo.appId)
},
async chooseUserIntoGroup({
group_id,
user_ids
}) {
if (typeof user_ids != 'object') {
return {
errSubject: 'uni-im',
errCode: 1000,
errMsg: 'user_ids必须是数组'
}
} else {
if (user_ids.length > 499) {
return {
errSubject: 'uni-im',
errCode: 2000,
errMsg: "拉人进群一次不能超过500人请分多次操作"
}
}
}
const dbJQL = uniCloud.databaseForJQL({
clientInfo: this.clientInfo
})
// 如果群id不存在把当前操作的用户也加入群用户列表群管理员&&群创建者)
if (!group_id) {
user_ids.push(this.current_uid)
}
let {
data: userList
} = await dbJQL.collection('uni-id-users')
.where(`"_id" in ${JSON.stringify(user_ids)}`)
.field('_id,nickname,avatar_file')
.limit(500)
.get()
//如果没有输入群id就先创建群
if (!group_id) {
let groupName = userList.reduce((sum, {
nickname
}) => {
sum += nickname + ' '
return sum
}, '')
groupName = groupName.substring(0, 30)
// console.log({
// groupName
// });
// JQL触发器会自动把当前用户设置为群主
let res = await dbJQL.collection('uni-im-group').add({
name: groupName
})
// console.log(122121, res);
// 把群主从用户列表中删除,因为他已经进群
userList.splice(userList.findIndex(item => item._id == this.current_uid), 1)
user_ids.pop()
// console.error(123123121, userList);
group_id = res.id
} else {
let res = await db.collection('uni-im-group').doc(group_id).get()
if (!res.data[0]) {
throw new Error('群id不存在')
}
}
// 如果一个用户都没选直接创建群,则 结束。否则将用户加入群&&创建会话&&发push通知
if (user_ids.length === 0) {
return {
errSubject: 'uni-im',
errCode: 0,
data: {
group_id
},
errMsg: ''
}
}
// 1.成为群成员
let groupMemberList = user_ids.map(user_id => {
data = {
group_id,
user_id,
role: [],
create_time: Date.now()
}
return data
})
let res = await db.collection('uni-im-group-member').add(groupMemberList)
// console.log('uni-im-group-member- res', res);
// 2.会话表加上
let conversationList = user_ids.map(user_id => {
data = {
group_id,
id: 'group_' + group_id,
user_id: user_id,
type: 2,
unread_count: 0,
update_time: Date.now()
}
return data
})
res = await db.collection('uni-im-conversation').add(conversationList)
// console.log('uni-im-group-member- res', res);
// 通知用户
let title = "新用户加群通知",
content = "新用户加群通知",
pushParam = {
payload: {
"type": "uni-im",
"data": {
type: "system",
action: "join-group-notice",
from_uid: "system",
//是否已读默认为false
is_read: false,
//创建时间
create_time: Date.now(),
conversation_id: "group_" + group_id,
group_id,
body: {
user_list: userList
}
},
title, // "收到im消息在线时显示的标题",
content, // "在线时显示的副标题",
},
title, // "收到im消息离线时显示的标题",
content //"离线时显示的内容"
}
const uniImCo = uniCloud.importObject("uni-im-co")
let pushRes = await uniImCo.sendMsgToGroup({
pushParam,
appId: this.clientInfo.appId
})
return {
errSubject: 'uni-im',
errCode: 0,
data: {
pushRes,
group_id
},
errMsg: ''
}
},
async revokeMsg(msgId) {
//1. 先查到这条消息
let {
data: [msgData]
} = await db.collection('uni-im-msg').doc(msgId).get()
if (!msgData) {
throw new Error('无效的消息id')
}
let {
conversation_id,
from_uid,
appid: appId,
group_id,
create_time
} = msgData
// 判断是不是群主
let isGroupAdmin = false
if (group_id) {
let res = await db.collection('uni-im-group-member')
.where({
group_id,
user_id: this.current_uid
})
.get()
isGroupAdmin = res.data[0] && res.data[0].role.includes('admin')
}
// console.error('isGroupAdmin',isGroupAdmin)
//如果不是群主,且消息不是发送者的就无权撤回
if (!isGroupAdmin) {
if (from_uid != this.current_uid) {
throw new Error('你无权操作')
} else {
// 消息发送者为“当前用户”时消息创建时间需要时间小于2分钟
if (Date.now() - create_time > 1000 * 60 * 2) {
throw {
errSubject: 'uni-im-co',
errCode: 10004,
errMsg: '消息已超过2分钟不能撤回'
}
}
}
}
// 3. 改变云数据库中此消息的撤回状态
let res = await db.collection('uni-im-msg')
.doc(msgId)
.update({
"is_revoke": true
})
// 添加一个服务端任
const taskCreateTime = Date.now()
await db.collection('uni-im-task').add({
type: "revoke_msg",
user_id: [msgData.to_uid],
group_id: [group_id],
payload: {
msg_id: msgId,
conversation_id,
user_id: this.current_uid,
create_time: msgData.create_time
},
create_time: taskCreateTime
})
// console.log('res',res,this.current_uid)
if (res.updated) {
// 4. 通知客户端,所有收到此消息的会话撤回此消息
let pushParam = {
"user_id": msgData.to_uid,
"payload": {
type: "uni-im-revoke-msg",
data: {
msg_id: msgId,
create_time: msgData.create_time,
conversation_id,
user_id: this.current_uid,
taskCreateTime
}
},
title: '撤回消息', // "收到im消息离线时显示的标题"
content: '撤回消息', // "收到im消息离线时显示的标题"
settings: {
// ttl: 3 * 24 * 3600 * 1000,
strategy: {
default: 3
}
}
}
if (group_id) {
delete pushParam.user_id
pushParam.payload.data.group_id = group_id
return await uniCloud.importObject('uni-im-co').sendMsgToGroup({
pushParam,
appId
})
} else {
res = await this.sendPushMsg(pushParam, appId)
return res
}
}
}
}
function getConversationId(param) {
return 'single' + '_' + md5(param.sort().toString())
}
function hideEmailStr(email) {
if (email == undefined) {
return ''
}
const content = email.split("@")
return content[0].substr(0, content[0].length - 2) + '**' + content[1]
}
function hideMobileStr(mobile) {
return mobile.substr(0, 3) + '****' + mobile.substr(-1 * 4)
}
function check_param(params, rule) {
rule.required.forEach(item => {
if (!params[item]) {
throw new Error('错误,参数:' + item + "的值不能为空")
}
})
for (let key in rule.type) {
if (key in rule.type) {
let val = params[key],
type = rule.type[key]
if (val && !type.includes(getType(val))) {
throw new Error('错误,参数:' + key + '的数据类型必须为:' + rule.type[key].join('或'))
}
}
}
function getType(data) {
return Object.prototype.toString.call(data).replace(/[\[\]]/g, '').split(' ')[1]
}
}