/** * 消息端点。 * * 此控制器处理点对点,组及消息消息。为三类消息提供发送及查询功能。 */ "use strict"; let express = require('express'); let router = express.Router(); let http = require('http'); let getui = require('getui'); let log = require('../util/log.js'); let objectUtil = require("../util/objectUtil.js"); let Patient = new require("../models/patient"); let patient = new Patient(); let smRepo = require("../repository/system.msg.repo.js"); let pmRepo = require('../repository/private.msg.repo.js'); let gmRepo = require("../repository/group.msg.repo.js"); let nmRepo = require("../repository/notify.msg.repo.js"); let statsRepo = require("../repository/stats.msg.repo.js"); let doctorRepo = require("../repository/doctor.repo.js"); let groupRepo = require("../repository/group.repo.js"); let searchRepo = require('../repository/search.repo.js'); let APIv1 = require('../include/endpoints').APIv1; let CONTENT_TYPES = require('../include/commons').CONTENT_TYPE; let GROUP_TYPE = require('../include/commons').GROUP_TYPE; let PLATFORMS = require('../include/commons').PLATFORM; let MAX_INT = 9007199254740992; let DEFAULT_PAGE_SIZE = 100; //--------------------------------------------------------------// //----------------------------消息发送----------------------------// //--------------------------------------------------------------// /** * 发送System消息。 * * 请求URL: * /chats/sm * * 消息格式: * { * to: "Rose", * title: "System Message", * summary: "You have new job", * contentType: "1", * content: "The patient has been followed in the scheduler, please make new follow plan as soon as possible." * } * * @param message */ router.post(APIv1.Chats.SM, function (req, res) { // 检查消息体及消息格式是否正确 let message = req.body; if (!objectUtil.isJsonObject(message)) { throw {httpStatus: 406, message: 'Problems parsing JSON.'} } // 字段判断 let testing = objectUtil.fieldsCheck(message, "to", "title", "summary", "contentType", "content"); if (!testing.pass) { throw {httpStatus: 406, message: testing.message} } // 消息处理 doctorRepo.getUserStatus(message.to, function (err, rows) { if (err) { console.log("Lookup system message receiver failed: ", err); res.status(500).send({message: "Lookup system message receiver failed."}); return; } if (rows.length == 0) { res.status(404).send({message: "User not found: " + message.to}); return; } let pushable = rows.length > 0 && rows[0].is_online; let notifyMessage = JSON.stringify({type: 'system_msg', data: message.content}); let userStatus = rows[0]; // 保存该条推送信息 smRepo.save(message.to, message.contentType, message.title, message.summary, message.content, function (err, result) { if (err) { log.error("Save system notify message failed, ", err); res.status(500).send({message: "Save system notify message failed."}); } else { // 先结束网络连接,再处理后续操作,减少客户端等待 res.status(200).send(); // 保存通知到数据库中 nmRepo.save(message.to, message.contentType, message.title, message.summary, notifyMessage, pushable, function (err, result) { if (err) { log.error("Save system notify message failed, ", err); res.status(500).send({message: "Save system notify message failed."}); } else { if (pushable) { if (userStatus.platform === PLATFORMS.iOS) { getui.pushAPN(message.to, userStatus.token, message.contentType, message.title, message.content, notifyMessage, function (err, result) { err != null ? console.log(err) : console.log(result); }); } else if (userStatus.platform === PLATFORMS.Android) { getui.pushAndroid(userStatus.client_id, message.contentType, message.title, message.content, notifyMessage, userStatus.status, function (err, result) { err != null ? console.log(err) : console.log(result); }); } } } }); } }); }); }); /** * 处理Private消息。处理流程分: * 1 解析消息,并保存到数据库 * 2 更新消息统计数据 * 3 获取目标的状态并构建通知消息,如果用户在线就推送通知消息 * * 请求URL: * /chats/pm * * 消息格式: * { * from: sand, * to: Rose, * contentType: "1,2,3,4", * content: "Please follow the patient as soon as possible." * } * * @param message */ router.post(APIv1.Chats.PM, function (req, res) { // 检查消息体及消息格式是否正确 let message = req.body; if (!objectUtil.isJsonObject(message)) { throw {httpStatus: 406, message: 'Problems parsing JSON.'} } // 字段判断 let testing = objectUtil.fieldsCheck(message, "from", "to", "contentType", "content"); if (!testing.pass) { throw {httpStatus: 406, message: testing.message}; } patient.sendMessage(message.to, message); res.status(200).send({}); return; // 保存消息 let tempContent = message.contentType === CONTENT_TYPES.Article ? JSON.stringify(message.content) : message.content; pmRepo.save(message.to, message.from, message.contentType, tempContent, function (err, result) { if (err) { res.status(500).send({message: 'Save private message failed.'}); return; } // 结束网络连接,后续操作继续执行 pmRepo.findOneMessage(result.insertId, function (err, msg) { if (err) { res.status(500).send({message: "Save private message success, but return last message failed."}); return; } let feedback = fillMessages(msg); res.status(200).send(feedback); patient.isPatientCode( message.to, function () { // 推送给患者 patient.sendMessage(message.to, 1, feedback); }, function () { // 推送给医生。获取对方状态,即对端的系统平台,token等信息,并推送通知消息给对端 doctorRepo.isExist(message.to, function (err, rows) { if (err) { console.log('Lookup receiving users failed or user not found: ', err); return; } doctorRepo.getUserStatus(message.to, function (err, result) { if (err) { log.error('Get target user status for private message failed: ' + message.to); return; } // 构建通知消息 let title = '新消息'; let content = ''; if (message.contentType === CONTENT_TYPES.PlainText) { content = message.content; } else if (message.contentType === CONTENT_TYPES.Image) { content = '[图片]'; } else if (message.contentType === CONTENT_TYPES.Audio) { content = '[语音]'; } else { content = '接收到一条新消息'; } let target = result[0]; let isOnline = result.length > 0 && target.is_online === 1; let notifyMessage = JSON.stringify({type: 'p2p_msg', from_uid: message.from}); // 保存通知消息到数据库中并根据用户在线状态推送此消息 nmRepo.save(message.to, message.contentType, title, content, notifyMessage, isOnline, function (err, result) { if (err) { log.error('Save private notify message failed, ', err); return; } if (!isOnline) return; if (target.platform === PLATFORMS.iOS) { getui.pushAPN(message.to, target.token, message.contentType, title, content, notifyMessage, function (err, result) { if (err != null) { console.log(err); } else { console.log(result); } }); } else if (target.platform === PLATFORMS.Android) { getui.pushAndroid(target.client_id, message.contentType, title, content, notifyMessage, target.status, function (err, result) { if (err != null) { console.log(err); } else { console.log(result); } }); } }); }); }); }); }); // 更新自身的聊天统计信息 statsRepo.updatePrivateChatSummary(message.from, message.to, message.from, message.contentType, message.content, function (err, result) { if (err) log.error(err); }); // 更新对端的聊天统计信息 statsRepo.updatePrivateChatSummary(message.to, message.from, message.from, message.contentType, message.content, function (err, result) { if (err) log.error(err); }); }); }); /** * 处理讨论组消息。 * * 请求URL: * /chats/gm * * 消息格式: * { * from: "sand", // 发送者id * at: "Rose", // @人 * group: "DiscussionGroupId", // 所在组 * groupType: "1 or 2", // 组类型:行政团队或讨论组 * contentType: "1,2,3", // 内容类型 * content: "The patient mess me up" // 内容 * } * * @param message */ router.post(APIv1.Chats.GM, function (req, res) { // 检查消息体及消息格式是否正确 let message = req.body; if (!objectUtil.isJsonObject(message)) { throw {httpStatus: 406, message: 'Problems parsing JSON.'}; } // 字段判断 let testing = objectUtil.fieldsCheck(message, 'from', 'at', 'group', 'groupType', 'contentType', 'content'); if (!testing.pass) { throw {httpStatus: 406, message: testing.message} } // 消息处理 groupRepo.isGroupMember(message.group, message.groupType, message.from, function (err, result) { if (err) { log.error('Check group member failed: ', err); res.status(500).send({message: 'Check group member failed.'}); return; } if (result.length == 0) { res.status(404).send({message: 'Member with id "' + message.from + '" is not in group "' + message.group + '"'}); return; } // 保存群组消息 gmRepo.save(message.from, message.group, message.at, message.contentType, message.content, function (err, insertedRow) { if (err) { log.error('Save group message failed: ', err); res.status(500).send({message: 'Save group message failed.'}); return; } gmRepo.findOneMessage(insertedRow.insertId, function (err, groupMsg) { if (err) { log.error("Save group message success, but return this message failed."); res.status(500).send({message: "Save group message success, but return this message failed."}); } // 关闭网络连接后执行后续操作 let feedback = fillMessages(groupMsg); res.status(200).send(feedback); // 推送通知消息给群组成员 groupRepo.getMembers(message.group, message.groupType, function (err, members) { if (err) { log.error('Get group members failed: ', err); return; } if (members.length == 0) { log.warn('No members in group ', message.group, message.groupType === GROUP_TYPE.AdminTeam ? " of admin team." : "of discussion group."); return; } // 逐个推送通知,患者与医生推送方式不一样 for (let i = 0; i < members.length; i++) { let member = members[i]; if (member.user_id === message.from) continue; (function (user_id) { patient.isPatientCode(user_id, function () { patient.sendMessage(user_id, 2, feedback); }, function () { doctorRepo.getUserStatus(user_id, function (err, result) { if (err) { console.error('Get group member status failed: ', err); return; } let title = ''; let content = ''; if (message.contentType === CONTENT_TYPES.PlainText) { title = '群组消息'; content = message.content; } else if (message.contentType === CONTENT_TYPES.Image) { title = '群组消息'; content = '[图片]'; } else if (message.contentType === CONTENT_TYPES.Audio) { title = '群组消息'; content = '[语音]'; } else { title = '群组消息'; content = '接收到一条新消息'; } let pushable = result.length > 0 && result[0].is_online === 1; let notifyMessage = JSON.stringify({type: 'group_msg', gid: message.group}); // 发送并保存通知到数据库中 if (pushable) { let userStatus = result[0]; if (userStatus.platform === PLATFORMS.iOS) { getui.pushAPN(user_id, userStatus.token, message.contentType, title, content, notifyMessage, function (err, result) { err != null ? console.error(err) : console.log(result); // 这段代码重复 nmRepo.save(user_id, message.contentType, title, content, notifyMessage, err != null ? 0 : 1, function (err, result) { if (err) { console.log('Save group notify message failed: ', err); } else { } }); }); } else if (userStatus.platform === PLATFORMS.Android) { getui.pushAndroid(data.client_id, message.contentType, title, content, notifyMessage, userStatus.status, function (err, result) { err != null ? console.error(err) : console.log(result); // 这段代码重复 nmRepo.save(user_id, message.contentType, title, content, notifyMessage, err != null ? 0 : 1, function (err, result) { if (err) { console.log('Save group notify message failed: ', err); } else { } }); }); } } else { // 这段代码重复 nmRepo.save(user_id, message.contentType, title, content, notifyMessage, 0, function (err, result) { if (err) { console.log('Save group notify message failed: ', err); } else { } }); } }); // 统计'@'信息 let at = message.at == user_id ? 1 : 0; statsRepo.updateGroupChatSummary(user_id, message.group, message.from, at, message.contentType, message.content, true, function (err, result) { if (err) console.log(err); }); }); })(member.user_id); } }); }); // 更新组内统计信息 statsRepo.updateGroupChatSummary(message.from, message.group, message.from, 0, message.contentType, message.content, false, function (err, result) { if (err) log.error(err); }); }); }); }); //--------------------------------------------------------------// //----------------------------消息提取----------------------------// //--------------------------------------------------------------// /** * 获取参与的聊天列表,包括:点对点,@我,参与的讨论组,系统消息等。 * * 请求URL: * /chats/list?user_id=sand */ router.get(APIv1.Chats.List, function (req, res) { let userId = req.query.user_id; if (userId === null) { throw {httpStatus: 406, message: 'Missing fields.'}; } // 与患者的私信 pmRepo.findAllP2PWithPatient(userId, function (err, patients) { if (err) { log.error('Get chat list with patient failed: ', err); res.status(500).send({message: 'Get chat list with patient failed.'}); return; } let chats = {patients: [], doctors: [], groups: []}; for (let i = 0; i < patients.length; i++) { let patient = patients[i]; chats.patients.push({ code: patient.code, name: patient.name, birthday: patient.birthday, sex: patient.sex, avatar: patient.photo == null ? "" : patient.photo, newMessageCount: patient.new_msg_count, lastContentType: patient.last_content_type, lastContent: patient.last_content, timestamp: objectUtil.timestampToLong(patient.timestamp) }); } // 含有患者的群 gmRepo.findAllGroupsWithPatient(userId, function (err, groups) { if (err) { log.error('Get group list with patient failed: ', err); res.status(500).send({message: 'Get group list with patient failed.'}); return; } for (let i = 0; i < groups.length; i++) { let group = groups[i]; // 过滤掉医生间的求助团队 if (group.group_type === 2) continue; //查找医生在讨论组的最新的消息记录数 chats.groups.push({ code: group.code, name: group.name, groupType: group.msg_type, newMessageCount: group.new_msg_count, lastContentType: group.last_content_type, lastContent: group.last_content, timestamp: objectUtil.timestampToLong(group.timestamp) }); } // 医生间的私聊 pmRepo.findAllP2PWithDoctor(userId, function (err, doctors) { if (err) { log.error('Get chat list with doctor failed: ', err); res.status(500).send({message: 'Get chat list with doctor failed.'}); return; } for (let i = 0; i < doctors.length; i++) { let doctor = doctors[i]; chats.doctors.push({ code: doctor.code, name: doctor.name, sex: doctor.sex, avatar: doctor.photo === null ? "" : doctor.photo, newMessageCount: doctor.new_msg_count, lastContentType: doctor.last_content_type, lastContent: doctor.last_content, timestamp: objectUtil.timestampToLong(doctor.timestamp) }); } // 获取医生间的组 gmRepo.findAllGroupsWithDoctor(userId, function (err, groups) { if (err) { log.error('Get group list with doctor failed: ', err); res.status(500).send({message: 'Get group list with doctor failed.'}); return; } for (let i = 0; i < groups.length; i++) { let group = groups[i]; chats.groups.push({ code: group.code, name: group.name, groupType: group.group_type, // 行政团队 or 求助 newMessageCount: group.new_msg_count, lastContentType: group.last_content_type, lastContent: group.last_content, timestamp: objectUtil.timestampToLong(group.timestamp) }); } res.status(200).send(chats); }); }); }) }); }); /** * 获取与患者的聊天列表,包括:P2P,参与的讨论组和行政团队。 * * 请求URL: * /chats/list/patient */ router.get(APIv1.Chats.ListWithPatient, function (req, res) { let userId = req.query.user_id; if (userId === null) { throw {httpStatus: 406, message: 'Missing fields.'}; } pmRepo.findAllP2PWithPatient(userId, function (err, patients) { if (err) { log.error('Get chat list with patient failed: ', err); res.status(500).send({message: 'Get chat list with patient failed.'}); return; } let chats = {patients: [], groups: []}; for (let i = 0; i < patients.length; i++) { let patient = patients[i]; chats.patients.push({ code: patient.code, name: patient.name, birthday: patient.birthday, sex: patient.sex, avatar: patient.photo == null ? "" : patient.photo, newMessageCount: patient.new_msg_count, lastContentType: patient.last_content_type, lastContent: patient.last_content, timestamp: objectUtil.timestampToLong(patient.timestamp) }); } gmRepo.findAllGroupsWithPatient(userId, function (err, groups) { if (err) { log.error('Get group list with patient failed: ', err); res.status(500).send({message: 'Get group list with patient failed.'}); return; } for (let i = 0; i < groups.length; i++) { let group = groups[i]; // 过滤掉医生间的求助团队 if (group.group_type === 2) continue; chats.groups.push({ code: group.code, name: group.name, groupType: group.msg_type, newMessageCount: group.new_msg_count, lastContentType: group.last_content_type, lastContent: group.last_content, timestamp: objectUtil.timestampToLong(group.timestamp) }); } res.status(200).send(chats); }) }); }); /** * 获取与医生的聊天列表,包括:点对点,参与的讨论组。 * * 请求URL: * /chats/list/doctor */ router.get(APIv1.Chats.ListWithDoctor, function (req, res) { let userId = req.query.user_id; if (userId === null) { throw {httpStatus: 406, message: 'Missing fields.'}; } // 先获取医生间的私聊 pmRepo.findAllP2PWithDoctor(userId, function (err, doctors) { if (err) { log.error('Get chat list with doctor failed: ', err); res.status(500).send({message: 'Get chat list with doctor failed.'}); return; } let chats = {doctors: [], groups: []}; for (let i = 0; i < doctors.length; i++) { let doctor = doctors[i]; chats.doctors.push({ code: doctor.code, name: doctor.name, sex: doctor.sex, avatar: doctor.photo === null ? "" : doctor.photo, newMessageCount: doctor.new_msg_count, lastContentType: doctor.last_content_type, lastContent: doctor.last_content, timestamp: objectUtil.timestampToLong(doctor.timestamp) }); } // 再获取医生间的组 gmRepo.findAllGroupsWithDoctor(userId, function (err, groups) { if (err) { log.error('Get group list with doctor failed: ', err); res.status(500).send({message: 'Get group list with doctor failed.'}); return; } for (let i = 0; i < groups.length; i++) { let group = groups[i]; chats.groups.push({ code: group.code, name: group.name, groupType: group.group_type, // 行政团队 or 求助 newMessageCount: group.new_msg_count, lastContentType: group.last_content_type, lastContent: group.last_content, timestamp: objectUtil.timestampToLong(group.timestamp) }); } res.status(200).send(chats); }); }); }); /** * 获取最近聊天对象:包括患者,医生与讨论组。客户端自行根据需要提取患者、医生或讨论组数据。 * * 请求URL: * /chats/recent?user_id=0de7295862dd11e69faffa163e8aee56&days=7 * * 参数: * user_id: 用户ID * target_type: 对象类型,1患者,2医生,3讨论组 * days: 最近天数 */ router.get(APIv1.Chats.Recent, function (req, res) { var userId = req.query.user_id; var days = req.query.days; if (userId === null) { throw {httpStatus: 406, message: 'Missing field: user_id'}; } if (days === null) { throw {httpStatus: 406, message: 'Missing field: days'}; } statsRepo.getRecentChats(userId, days, function (err, result) { if (err) { log.error('Get recent chat objects failed: ', err); res.status(500).send({message: 'Get recent chat objects failed.'}); return; } var data = {patients: [], doctors: [], groups: []}; if (result.length === 0) { res.status(200).send(data); return; } for (var i = 0; i < result.length; ++i) { var row = result[i]; if (row.type.indexOf('patient') > -1) { data.patients.push({ code: row.code, name: row.name, birthday: row.birthday === null ? "" : row.birthday, sex: row.sex, avatar: row.photo === null ? "" : row.photo }); } else if (row.type.indexOf('doctor') > -1) { data.doctors.push({ code: row.code, name: row.name, birthday: row.birthday === null ? "" : row.birthday, sex: row.sex, avatar: row.photo === null ? "" : row.photo }); } else if (row.type.indexOf('group') > -1) { data.groups.push({ code: row.code, name: row.name }); } } res.status(200).send(data); }); }); /** * 获取私信。倒序排列。 * * 参数: * user_id 必须,医生ID * peer_id 必须,对方医生ID * content_type 必须,消息类型 * message_start_id 可选,消息的起始ID,如果为空从最新的一条开始获取 * message_end_id 可选,消息的结束ID,如果为空从第一条开始获取 * count 可选,消息数量,如果不指定、小于零或大于50,默认为100条。若message_start_id与message_end_id均不为空,则此参数无效,方法是设置为10000条 * closed_interval 消息范围是否使用闭区间 * * 请求URL: * /chats/pm?user_id=sand&peer_id=Rose&content_type=2&message_start_id=10000&message_end_id=0&count=20&closed_interval=false */ router.get(APIv1.Chats.PM, function (req, res) { var userId = req.query.user_id; var peerId = req.query.peer_id; var contentType = req.query.content_type; var msgStartId = !req.query.message_start_id ? MAX_INT : parseInt(req.query.message_start_id); var msgEndId = !req.query.message_end_id ? 0 : parseInt(req.query.message_end_id); var count = req.query.count === undefined ? DEFAULT_PAGE_SIZE : parseInt(req.query.count); var closedInterval = (req.query.closed_interval != false && req.query.closed_interval === "true"); if (contentType !== undefined && parseInt(contentType) === CONTENT_TYPES.Image) count = DEFAULT_PAGE_SIZE; if (req.query.message_start_id && req.query.message_end_id) count = 10000; if (!userId) { throw {httpStatus: 400, message: "Missing field: user_id."}; } pmRepo.findAllMessages(userId, peerId, contentType === undefined ? "1,2,3,5,6" : contentType, msgStartId, msgEndId, count, closedInterval, function (err, rows) { if (err) { log.error("Get private message failed, ", err); res.status(500).send({message: "Get private messages failed."}); return; } var messages = fillMessages(rows); // 清空统计信息 statsRepo.clearPrivateChatSummary(userId, peerId, function (err, result) { if (err) console.log(err); }); res.status(200).send(messages); }); }); /** * 获取未读私信。倒序排列。 * * 参数: * user_id 必须,医生ID * peer_id 必须,对方医生ID * * 请求URL: * /chats/pm/unread?user_id=sand&peer_id=Rose */ router.get(APIv1.Chats.PMUnread, function (req, res) { var userId = req.query.user_id; var peerId = req.query.peer_id; if (userId === undefined) { throw {httpStatus: 400, message: "Missing field: user_id."}; } statsRepo.getPrivateChatSummary(userId, peerId, function (err, summary) { if (err) { log.error("Get unread private messages failed: ", err); res.status(500).send({message: "Get unread private messages failed."}); return; } // 没有未读消息,直接返回 if (summary.length == 0 || summary[0].new_msg_count === 0) { res.status(200).send({startId: 0, count: 0, records: []}); return; } pmRepo.findUnread(peerId, userId, MAX_INT, summary[0].new_msg_count, function (err, rows) { if (err) { log.error("Get unread private messages failed: ", err); res.status(500).send({message: "Get unread private messages failed."}); return; } var messages = fillMessages(rows); res.status(200).send(messages); }); }); }); /** * 按时间倒序获取群消息。 * * 参数: * user_id 必须,医生ID * group_id 必须,组ID * message_start_id 可选,消息的起始ID,如果为空从最新的一条开始获取 * count 可选,消息数量,如果不指定、小于零或大于50,默认为50条 * * 请求URL: * /chats/gm?user_id=D2016008240002&group_id=494&content_type=2&message_start_id=0&message_end_id=0&count=20 */ router.get(APIv1.Chats.GM, function (req, res) { var groupId = req.query.group_id; var userId = req.query.user_id; var contentType = req.query.content_type; var msgStartId = !req.query.message_start_id ? MAX_INT : parseInt(req.query.message_start_id); var msgEndId = !req.query.message_end_id ? 0 : parseInt(req.query.message_end_id); var count = req.query.count === undefined ? DEFAULT_PAGE_SIZE : parseInt(req.query.count); if (groupId === undefined) { throw {httpStatus: 400, message: "Missing field: group_id."}; } if (contentType !== undefined && parseInt(contentType) === CONTENT_TYPES.Image) count = DEFAULT_PAGE_SIZE; if (req.query.message_start_id && req.query.message_end_id) count = 100000; gmRepo.findAllMessages(groupId, !contentType ? "1,2,3,5,6" : contentType, msgStartId, msgEndId, count, function (err, rows) { if (err) { console.log('Get group message failed: ', err); res.status(500).send({message: 'Get group message failed.'}); return; } var messages = fillMessages(rows); // 清空统计信息 statsRepo.clearGroupChatSummary(userId, groupId, function (err, result) { if (err) console.log(err); }); res.status(200).send(messages); }); }); /** * 获取未读群消息。 * * 请求URL: * /chats/gm/unread?group_id=discussionGroupId&user_id=sand */ router.get(APIv1.Chats.GMUnread, function (req, res) { var userId = req.query.user_id; var groupId = req.query.group_id; if (userId === undefined) { throw {httpStatus: 400, message: "Missing field: user_id."}; } if (groupId === undefined) { throw {httpStatus: 400, message: "Missing field: group_id."}; } statsRepo.getGroupChatSummary(userId, groupId, function (err, summary) { if (err) { log.error("Get unread group messages failed: ", err); res.status(500).send({message: "Get unread group messages failed."}); return; } var messages = {startId: 0, count: 0, records: []}; if (summary.length == 0 || summary[0].new_msg_count === 0) { res.status(200).send(messages); return; } messages.count = summary[0].new_msg_count; gmRepo.findUnread(groupId, MAX_INT, messages.count, function (err, rows) { if (err) { log.error("Get unread group messages failed: ", err); res.status(500).send({message: "Get unread group messages failed."}); return; } var messages = fillMessages(rows); res.status(200).send(messages); }); }); }); /** * 将消息的返回结果合并成JSON。 * * @param rows * * @returns {startId: 0, count: 0, records: []} */ function fillMessages(rows) { var messages = {startId: rows.length > 0 ? rows[0].msg_id : '', count: rows.length, records: []}; for (var i = 0; i < rows.length; i++) { var row = rows[i]; var record = { id: row.msg_id, from: row.from_uid, contentType: row.type, content: row.content, timestamp: objectUtil.timestampToLong(row.timestamp) }; if (row.to_uid !== undefined) record.to = row.to_uid; if (row.at_uid !== undefined) record.at = row.at_uid; messages.records.push(record); } return messages; } //--------------------------------------------------------------// //----------------------------消息统计----------------------------// //--------------------------------------------------------------// /** * 获取所有群组未读消息总数。 * * 请求URL: * /chats/gm/unread_count?user_id=sand * * 参数: * user_id:医生ID */ router.get(APIv1.Chats.GMUnreadCount, function (req, res) { var userId = req.query.user_id; if (userId === null) { throw {httpStatus: 406, message: 'Missing fields.'}; } statsRepo.getGroupChatAllUnReadCount(userId, function (err, result) { if (err) { console.log('Get all unread messages failed: ', err); res.status(500).send({message: 'Get all unread messages failed.'}); } var data = { userId: userId, messageType: 2, newMessageCount: 0 }; if (result.length > 0) { for (var index = 0; index < result.length; index++) { data.newMessageCount += result[index].new_msg_count; } } res.send(data); }); }); /** * 获取特定群组消息统计情况。 * * /chats/gm/statistic?group_id=GGG&&user_id=sand * * 参数: * user_id:信息所有者id * group_id:群组id */ router.get(APIv1.Chats.GMStats, function (req, res) { var userId = req.query.user_id; var groupId = req.query.group_id; if (userId === null || groupId === null) { throw {httpStatus: 406, message: 'Miss fields.'}; } statsRepo.getGroupChatSummary(userId, groupId, function (err, result) { if (err) { console.log('Get group stats failed: ', err); res.status(500).send({message: 'Get group stats failed.'}); return; } var data = { userId: userId, from: "", groupId: groupId, atMe: 0, lastContentType: 1, lastContent: "", newMessageCount: 0, timestamp: 0 }; if (result.length > 0) { var row = result[0]; data.from = row.from_uid; data.groupId = row.gid; data.atMe = row.at_me; data.lastContentType = row.last_content_type; data.lastContent = row.lastContent; data.newMessageCount = row.new_msg_count; data.timestamp = objectUtil.timestampToLong(row.timestamp) } res.status(200).send(data); }); }); /** * 获取与某人的私信统计。 * * /chats/pm/statistic?user_id=sand&&peer_id=rose * * 参数: * user_id:信息所有者id * peer_id:聊天对端id */ router.get(APIv1.Chats.PMStats, function (req, res) { var userId = req.query.user_id; var peerId = req.query.peer_id; if (userId == null || peerId == null) { throw {httpStatus: 406, message: "Missing fields."}; } statsRepo.getPrivateChatSummary(userId, peerId, function (err, result) { if (err) { console.log("Get private messages stats failed: ", err); res.status(500).send({message: "Get private messages stats failed."}); } var data = { userId: userId, peerId: peerId, lastCContentType: 1, lastContent: "", newMessageCount: 0, timestamp: 0 }; if (result.length > 0) { var row = result[0]; data.userId = row.uid; data.peerId = row.from_uid; data.lastContentType = row.last_content_type; data.lastContent = row.last_content; data.newMessageCount = row.new_msg_count; data.timestamp = objectUtil.timestampToLong(row.timestamp) } res.status(0).send(data); }); }); /** * 获取所有未读私信总数。 * * /chats/pm/unread_count?user_id=sand * * 参数: * uid:信息所有者id */ router.get(APIv1.Chats.PMUnreadCount, function (req, res) { var userId = req.query.user_id; statsRepo.getPrivateChatAllUnReadCount(userId, function (err, result) { if (err) { console.log("Get unread private message count failed: ", err); res.status(500).send({message: "Get unread private message count failed."}); } var data = {userId: userId, messageType: 1, newMessageCount: 0}; if (result.length > 0) { for (var i = 0; i < result.length; i++) { data.newMessageCount += result[i].new_msg_count; } } res.send(data); }); }); /** * 所有聊天消息未读数。 * * 请求URL: * /chats/chats/unread_count?user_id=sand * * 参数: * user_id:信息所有者id */ router.get(APIv1.Chats.UnreadMsgCount, function (req, res) { var userId = req.query.user_id; if (userId === null) { throw {httpStatus: 406, message: "Missing fields."}; } statsRepo.getChatAllUnReadCount(userId, function (err, result) { if (err) { console.error("Get all unread message count failed: ", err); res.status(500).send({message: "Get all unread message count failed."}); } var data = {userId: userId, messageType: 0, newMessageCount: 0}; if (result.length > 0) { for (var index = 0; index < result.length; index++) { data.newMessageCount += result[index].new_msg_count; } } res.send(data); }); }); /** * 搜索患者相关的数据,包括患者信息与相关的私信记录。关键词不支持空格拆分。 * * 请求URL: * /search/patient?user_id=3b723bb8699a11e69f7c005056850d66&user_role=1&keyword=庄 * * 参数: * keywords: 关键词 */ router.get(APIv1.Chats.SearchAboutPatient, function (req, res) { var userId = req.query.user_id; var userRole = req.query.user_role; var keyword = req.query.keyword; if (!userId) throw {httpStatus: 406, message: "Missing fields: user_id."}; if (!userRole) throw {httpStatus: 406, message: "Missing fields: user_role."}; if (!keyword) throw {httpStatus: 406, message: "Missing fields: keyword."}; searchRepo.searchPatients(userId, userRole, keyword, function (err, patients) { if (err) { log.error("Search patient on basic information failed: ", err); res.status(500).send({message: "Search patient on basic information failed."}); return; } var data = {patients: [], chats: []}; for (var i = 0; i < patients.length; ++i) { var patient = patients[i]; data.patients.push({ code: patient.code, name: patient.name, sex: patient.sex, birthday: objectUtil.timestampToLong(patient.birthday), avatar: patient.photo === null ? "" : patient.photo }); } searchRepo.searchPatientPM(userId, keyword, function (err, chats) { if (err) { log.error("Search patient on private messages failed: ", err); res.status(500).send({message: "Search patient on private messages failed."}); return; } var lastPatientCode = ''; var lastPatient = {code: '', name: '', sex: '', avatar: '', messages: []}; for (var i = 0; i < chats.length; ++i) { var chat = chats[i]; if (lastPatientCode !== chat.code) { lastPatientCode = chat.code; lastPatient.code = chat.code; lastPatient.name = chat.name; lastPatient.sex = chat.sex; lastPatient.birthday = objectUtil.timestampToLong(patient.birthday); lastPatient.avatar = chat.photo === null ? "" : chat.photo; data.chats.push(lastPatient); } lastPatient.messages.push({ id: chat.msg_id, content: chat.content }); } res.status(200).send(data); }); }); }); /** * 搜索医生相关的数据,包括医生信息与相关的聊天记录,包括私信与群信。 * * 请求URL: * /search/doctor?user_id=5fa5e88f7a4111e69f7c005056850d66&keyword=丘 * * 参数: * keywords: 关键词 */ router.get(APIv1.Chats.SearchAboutDoctor, function (req, res) { var userId = req.query.user_id; var keyword = req.query.keyword; if (!userId) throw {httpStatus: 406, message: "Missing fields: user_id."}; if (!keyword) throw {httpStatus: 406, message: "Missing fields: keyword."}; // 搜索医生 searchRepo.searchDoctors(userId, keyword, function (err, doctors) { if (err) { log.error("Search doctor on basic information failed: ", err); res.status(500).send({message: "Search doctor on basic information failed."}); return; } var data = {doctors: [], groups: [], chats: {doctors: [], groups: []}}; for (var i = 0; i < doctors.length; ++i) { var doctor = doctors[i]; data.doctors.push({ code: doctor.code, name: doctor.name, sex: doctor.sex, avatar: doctor.photo === null ? "" : doctor.photo }); } // 搜索讨论组名称及成员名称 searchRepo.searchGroups(userId, keyword, function (err, groups) { if (err) { log.error("Search talk group failed: ", err); res.status(500).send({message: "Search talk group failed."}); return; } var lastGroupCode = ''; var lastGroup = null; for (var i = 0; i < groups.length; ++i) { var group = groups[i]; if (lastGroupCode !== group.code) { lastGroupCode = group.code; lastGroup = { code: group.code, name: group.name, type: GROUP_TYPE.DiscussionGroup, members: [] }; data.groups.push(lastGroup); } lastGroup.members.push({ code: group.member_code, name: group.member_name }); } // 搜索医生间的私信 searchRepo.searchDoctorMessages(userId, keyword, function (err, messages) { if (err) { log.error("Search doctor private messages failed: ", err); res.status(500).send({message: "Search doctor private messages failed."}); return; } var lastDoctor; var lastDoctorCode = ''; for (var i = 0; i < messages.length; ++i) { var message = messages[i]; if (lastDoctorCode !== message.code) { lastDoctorCode = message.code; lastDoctor = { code: message.code, name: message.name, photo: message.photo === null ? "" : message.photo, messages: [] }; data.chats.doctors.push(lastDoctor); } lastDoctor.messages.push({ id: message.msg_id, content: message.content }); } // 搜索医生间的讨论组消息 searchRepo.searchGroupMessages(userId, keyword, function (err, messages) { if (err) { log.error("Search doctor group messages failed: ", err); res.status(500).send({message: "Search doctor group messages failed."}); return; } // g.code, g.name, gm.msg_id, gm.content var lastGroup; var lastGroupCode = ''; for (var i = 0; i < messages.length; ++i) { var message = messages[i]; if (lastGroupCode !== message.code) { lastGroupCode = message.code; lastGroup = { code: message.code, name: message.name, messages: [] }; data.chats.groups.push(lastGroup); } lastGroup.messages.push({ id: message.msg_id, content: message.content }); } res.status(200).send(data); }); }); }); }); }); /** * 获取单条消息。 * * URL: * /chats/message?id=1234&type=1 */ router.get(APIv1.Chats.Message, function (req, res) { var messageId = req.query.id; var messageType = req.query.type; // 私信 if (messageType == 1) { pmRepo.findOneMessage(messageId, function (err, result) { if (err) { log.error("Get message failed: ", err); res.status(500).send({message: "Get message failed."}); return; } if (result.length == 0) { res.status(404).send({message: "Message not found."}); return; } res.status(200).send({ id: result[0].msg_id, from: result[0].from_uid, to: result[0].to_uid, contentType: result[0].type, content: result[0].content, timestamp: objectUtil.timestampToLong(result[0].timestamp) }); }) } else { gmRepo.findOneMessage(messageId, function (err, result) { if (err) { log.error("Get message failed: ", err); res.status(500).send({message: "Get message failed."}); return; } if (result.length == 0) { res.status(404).send({message: "Message not found."}); return; } res.status(200).send({ id: result[0].msg_id, from: result[0].from_uid, at: result[0].at_uid, groupId: result[0].to_gid, contentType: result[0].type, content: result[0].content, timestamp: objectUtil.timestampToLong(result[0].timestamp) }); }); } }); /** * 判断当前会话是否已经结束。 * * 请求URL: * /chats/pm/finished?user_id=sand&peer_id=rose */ router.get(APIv1.Chats.PMFinished, function (req, res) { var doctorId = req.query.doctor_id; var patientId = req.query.patient_id; if (!doctorId) { throw {httpStatus: 406, message: "Missing field: doctor_id"}; } if (!patientId) { throw {httpStatus: 406, message: "Missing field: patient_id"}; } pmRepo.isCurrentSessionFinished(doctorId, patientId, function (err, result) { if (err) { log.error("Get session finish status failed: ", err); throw {httpStatus: 500, message: "Get session finish status failed."}; } var data = {finished: true, consultId: ''}; if (result.length > 0) { var finishRow = result[0]; data.finished = finishRow.finished === 1; if (!data.finished) { data.consultId = finishRow.consult_id; } } res.status(200).send(data); }) }); module.exports = router;