index.obj.js 8.3 KB
Newer Older
DCloud_JSON's avatar
init  
DCloud_JSON 已提交
1 2 3 4 5 6 7 8 9 10 11
// 云对象教程: 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 usersTable = db.collection('uni-id-users')
const uniIdCommon = require('uni-id-common')
const dbCmd = db.command
const $ = dbCmd.aggregate
const md5 = require("md5");
const jwt = require("jsonwebtoken");
12 13 14 15
const createConfig = require("uni-config-center");
const uniImConfig = createConfig({
	pluginId: 'uni-im', // 插件id
})
DCloud_JSON's avatar
init  
DCloud_JSON 已提交
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
module.exports = {
	_before() {
		this.clientInfo = this.getClientInfo()
		this.uniIdCommon = uniIdCommon.createInstance({ // 创建uni-id实例,其上方法同uniIdCommon
			clientInfo: this.clientInfo
		})
	},
	async getConversationList({
		limit = 500,
		page = 0,
		conversation_id = false
	}) {
		let res = await this.uniIdCommon.checkToken(this.clientInfo.uniIdToken)
		if (res.errCode) {
			return res
		}
		res = await conversationTable.aggregate()
			.sort({
34
				update_time: -1
DCloud_JSON's avatar
init  
DCloud_JSON 已提交
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
			})
			.match({
				"owner_uid": res.uid,
				"group_id": dbCmd.exists(false),
				"id":conversation_id||dbCmd.neq(null)
			})
			.skip(page * limit)
			.limit(limit)
			.lookup({
				from: "uni-id-users",
				let: {
					user_id: '$user_id'
				},
				pipeline: $.pipeline()
					.match(
						dbCmd.expr($.eq(['$_id', '$$user_id']))
					).project({
						_id: 1,
						nickname: 1,
						avatar_file: 1,
						mobile: 1,
						email: 1
					})
					.done(),
				as: 'user_info'
			})
			.lookup({
				from: "uni-im-msg",
				let: {
					user_id: '$user_id'
				},
				pipeline: $.pipeline()
					.match(
						dbCmd.expr($.or(
							$.eq(['$$user_id', '$from_uid']),
							$.eq(['$$user_id', '$to_uid'])
						))
					)
					.sort({
						create_time: 1
					})
					.limit(1)
					.project({
						_id: 1,
						nickname: 1,
						avatar_file: 1,
						mobile: 1,
						email: 1
					})
					.done(),
				as: 'msgList'
			})
			.end()
		return {
			data: res.data,
			errCode: 0
		}
	},
	async sendMsg(params, context) {
		const {
			to_uid,
			// group_id,
			body,
			type,
			isRetries
		} = params

		//校验是否登录
		let res = await this.uniIdCommon.checkToken(this.clientInfo.uniIdToken)
		if (res.errCode) {
			return res
		}

		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)
		}
		//发送者身份id
		const from_uid = res.uid
116 117 118 119 120 121 122 123 124 125 126 127 128 129
		let admin_uid =  uniImConfig.config('admin_uid')
		if(admin_uid){
			if(typeof admin_uid == 'string'){
				admin_uid = [admin_uid]
			}
			if(
				!(admin_uid.includes(from_uid) || admin_uid.includes(to_uid))
			){
				return {
					errMsg: '非法通讯,会话双方用户id,均不属于uni-im-co中配置的admin_uid',
					errSubject: "uni-im",
					errCode: 40001
				}
			}
DCloud_JSON's avatar
init  
DCloud_JSON 已提交
130 131
		}
		
132
		
DCloud_JSON's avatar
init  
DCloud_JSON 已提交
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257
		const conversation_id = getConversationId([from_uid, to_uid])
		const msgData = {
			body,
			type,
			from_uid,
			to_uid,
			//默认已读为false
			is_read: false,
			//创建时间
			create_time: Date.now(),
			conversation_id
		}

		//会话表
		let {
			data: [conversation]
		} = await conversationTable.where({
			id: conversation_id
		}).get()
		if (conversation) {
			//对方的会话表更新,并且未读数+1
			let res = await conversationTable.where({
				id: conversation_id,
				owner_uid: 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,
				owner_uid: from_uid
			}).update({
				// unread_count: dbCmd.inc(1),
				last_msg_note,
				update_time: msgData.create_time
			})
			console.log(res);
		} else {
			// 消息接收者 会话数据
			let data1 = {
				id: conversation_id,
				type: msgData.group_id ? 2 : 1,
				owner_uid: msgData.to_uid,
				user_id: msgData.from_uid,
				group_id: msgData.group_id,
				unread_count: 1,
				last_msg_note,
				update_time: msgData.create_time
			}
			// 消息发送者 会话数据
			let data2 = {
				...data1,
				unread_count: 0,
				owner_uid: msgData.from_uid,
				user_id: msgData.to_uid
			}
			// console.log(123231123,data,[data1,data2]);
			let res = await conversationTable.add([data1, data2])
			// console.log(res);
		}
		console.log({
			...msgData,
			conversation_id
		});
		if(!isRetries){
			res = await msgTable.add({
				...msgData,
				conversation_id
			})
			console.log('msgTable msgData:', res);
		}
		res = await db.collection('uni-id-users').doc(from_uid)
		.field({
			'username': true ,
			'_id': true ,
			'nickname': true ,
			'avatar_file': true 
		}).get()
		let {username,nickname,avatar_file} = res.data[0]
		let title = username||nickname
		let content = msgData.body
		let param = {
			"user_id": msgData.to_uid,
			"payload": {
				"type": "im",
				"data":msgData,
				title,// "收到im消息,在线时显示的标题",
				content,// "在线时显示的副标题",
				avatar_file//头像文件对象
			},
			title,// "收到im消息,离线时显示的标题",
			content,//"离线时显示的内容"
			settings:{
				//-1表示不设离线,因为离线后重新打开数据统一从数据库中拉取。否则会重复
				ttl:-1
			},
			channel:{
				"HW":"NORMAL"
			}
		}
		if (msgData.to_uid) {
			//单聊
			param.user_id = msgData.to_uid
		} else if (msgData.group_id) {
			return {
				errCode: 1000,
				errMsg: '群聊功能正在开发中',
				errSubject: "uni-im"
			}
			console.log('param====', param);
		} else {
			return {
				errCode: 404,
				errMsg: '接受者id不能为空',
				errSubject: "uni-im"
			}
		}
		
		let uniPush = uniCloud.getPushManager({appId:params.appId})
		res = await uniPush.sendMessage(param)
		if (res.errCode) {
258 259 260 261 262 263 264 265
			if(res.errCode == "uni-push-user-invalid"){
				//可能因为用户长时间没有登录导致的cid过期而发送失败,但是此时已将离线数据写入数据库,登录后可获取。客户端不需要进入 catch
				res = {
					cause:res,
					errCode:0
				}
			}else{
				return res
DCloud_JSON's avatar
init  
DCloud_JSON 已提交
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280
			}
		}
		console.log('sendMessage',JSON.stringify(res))
		/*
		//判断是否已经有客户端接收到消息,注意:收到不等于已读
		console.log('sendMessage res', 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);*/
281 282 283 284
		if(!res.data){
			res.data = {}
		}
		res.data.create_time = msgData.create_time
		return res
DCloud_JSON's avatar
init  
DCloud_JSON 已提交
285 286
	},
	async loginWithJWT(sign){
287 288 289 290 291 292
		let jwtSecret = uniImConfig.config('jwtSecret')
		if(!jwtSecret){
			return {
				errCode: 4000,
				errMsg: 'jwtSecret的值不能为空'
			}
DCloud_JSON's avatar
init  
DCloud_JSON 已提交
293
		}
294 295 296 297 298 299 300
		if(jwtSecret == 'jwtSecretDemo'){
			console.error('[warn]: 不要使用默认的:jwtSecret的值');
			return {
				errCode: 4100,
				errMsg: '不要使用默认的:jwtSecret的值'
			}
		}
DCloud_JSON's avatar
init  
DCloud_JSON 已提交
301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339
		let userInfo;
		try{
			let decoded = jwt.verify(sign, jwtSecret);
			if(decoded.exp && decoded.exp < Date.now()){
				throw '签名数据过期'
			}
			userInfo = decoded.userInfo
			if(!userInfo.openid){
				return {
					errCode: 2,
					errMsg: 'userInfo.openid不能为空',
					errSubject: "uni-im"
				}
			}
		}catch(e){
			console.error(e);
			return {
				errCode: 1,
				errMsg: '签名验证失败',
				errSubject: "uni-im"
			}
		}
		console.log(userInfo);
		let {openid} = userInfo
		let res = await usersTable.where({openid}).get()
		console.log(res);
		if(res.data.length){
			res = await usersTable.where({openid}).updateAndReturn(userInfo)
		}else{
			res = await usersTable.add(userInfo)
		}
		console.log(res);
		let newToken = await this.uniIdCommon.createToken({
		  uid: res.id || res.doc._id
		})
		return {
			errCode: 0,
			newToken
		}
340
	}
DCloud_JSON's avatar
init  
DCloud_JSON 已提交
341 342 343 344 345
}

function getConversationId(param) {
	return 'single' + '_' + md5(param.sort().toString())
}