sessions.js 62 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377
  1. /**
  2. * 会话模型。
  3. */
  4. "use strict";
  5. let RedisClient = require('../../repository/redis/redis.client.js');
  6. let RedisModel = require('./../redis.model.js');
  7. let ModelUtil = require('../../util/model.util');
  8. let Messages = require('../messages/messages');
  9. let Users = require('../user/users');
  10. let Participants = require('./participants');
  11. let SessionRepo = require('../../repository/mysql/session.repo');
  12. let TopicRepo = require('../../repository/mysql/topics.repo');
  13. let ParticipantRepo = require('../../repository/mysql/participant.repo');
  14. let ImDb = require('../../repository/mysql/db/im.db');
  15. let WlyySDK = require("../../util/wlyy.sdk");
  16. let WechatClient = require("../client/wechat.client.js");
  17. let AppClient = require("../client/app.client.js");
  18. let configFile = require('../../include/commons').CONFIG_FILE;
  19. let config = require('../../resources/config/' + configFile);
  20. let redis = RedisClient.redisClient().connection;
  21. let logger = require('../../util/log.js');
  22. let mongoose = require('mongoose');
  23. let async = require("async");
  24. let log = require("../../util/log.js");
  25. const REDIS_KEYS = require('../../include/commons').REDIS_KEYS;
  26. const SESSION_TYPES = require('../../include/commons').SESSION_TYPES;
  27. const STICKY_SESSION_BASE_SCORE = require('../../include/commons').STICKY_SESSION_BASE_SCORE;
  28. const PARTICIPANT_ROLES = require('../../include/commons').PARTICIPANT_ROLES;
  29. const CONTENT_TYPES = require('../../include/commons').CONTENT_TYPES;
  30. const SESSION_BUSINESS_TYPE = require('../../include/commons').SESSION_BUSINESS_TYPE;
  31. class Sessions extends RedisModel {
  32. constructor() {
  33. super();
  34. }
  35. /**
  36. * 创建会话。会话的ID来源:
  37. * MUC:患者的ID
  38. * P2P:对成员的ID排序后,取hash值
  39. * GROUP:团队的ID
  40. *
  41. * @param sessionId
  42. * @param name 会话名称
  43. * @param type 会话类型
  44. * @param participantArray 会话成员
  45. * @param handler 回调,仅MUC模式使用
  46. */
  47. createSession(sessionId, name, type, participantArray, handler) {
  48. let self = this;
  49. let messageId = mongoose.Types.ObjectId().toString();
  50. //创建session到mysql
  51. self.createSessionToMysql(sessionId, name, type, participantArray, messageId, function (err, res) {
  52. if (err) {
  53. if (handler) {
  54. handler(err, null);
  55. return;
  56. }
  57. ModelUtil.emitError(self.eventEmitter, {message: err, status: -1}, null);
  58. } else {
  59. //创建session到redis
  60. self.createSessionToRedis(sessionId, name, type, participantArray, messageId, function (err, res) {
  61. if (err) {
  62. if (handler) {
  63. handler(err, null);
  64. return;
  65. }
  66. ModelUtil.emitError(self.eventEmitter, {message: err, status: -1}, null);
  67. } else {
  68. if (handler) {
  69. handler(null, res);
  70. return;
  71. }
  72. ModelUtil.emitOK(self.eventEmitter, {status: 200, data: res});
  73. }
  74. });
  75. }
  76. });
  77. }
  78. /**
  79. * 创建会话。REDIS
  80. * @param sessionId
  81. * @param name
  82. * @param type
  83. * @param participantArray
  84. * @param messageId
  85. * @param handler
  86. * @returns {boolean}
  87. */
  88. createSessionToRedis(sessionId, name, type, participantArray, messageId, handler) {
  89. let self = this;
  90. let messages = new Messages();
  91. let participantIdArray = [];
  92. for (let i in participantArray) {
  93. participantIdArray.push(participantArray[i].split(":")[0]);
  94. }
  95. if (type == SESSION_TYPES.P2P || type == SESSION_TYPES.SYSTEM) {
  96. if (sessionId) {
  97. callBusinessType(sessionId);
  98. return;
  99. }
  100. else if (participantIdArray.length != 2) {
  101. handler("P2P session only allow 2 participants.", null);
  102. return false;
  103. }else{
  104. ParticipantRepo.findSessionIdByParticipantIds(participantIdArray[0], participantIdArray[1], function (err, res) {
  105. sessionId = res;
  106. callBusinessType(sessionId);
  107. return;
  108. });
  109. }
  110. } else {
  111. if (!sessionId) {
  112. handler("MUC OR GROUP session sessionId is not allow null .", null);
  113. return;
  114. }
  115. callBusinessType(sessionId);
  116. }
  117. function callBusinessType(sessionId) {
  118. if(type == SESSION_TYPES.MUC){
  119. callCreate(sessionId, SESSION_BUSINESS_TYPE.PATIENT);
  120. }else {
  121. ParticipantRepo.getBusinessType(participantIdArray, function (err, businessType) {
  122. callCreate(sessionId, businessType);
  123. });
  124. }
  125. }
  126. function callCreate(sessionId, businessType) {
  127. let createDate = new Date();
  128. Participants.saveParticipantsToRedis(sessionId, participantArray, createDate, function (res) {
  129. let sessionKey = RedisModel.makeRedisKey(REDIS_KEYS.Session, sessionId);
  130. if (type == SESSION_TYPES.MUC) {
  131. businessType = 2;
  132. }
  133. let session = {
  134. id: sessionId,
  135. name: name,
  136. type: type,
  137. create_date: createDate.getTime(),
  138. business_type: businessType
  139. };
  140. //如果会话已经存在的就不需要发送会话成功的消息不更新最后一条消息
  141. redis.hexistsAsync(sessionKey, sessionId).then(function(res){
  142. if(res==0){
  143. redis.hmsetAsync(sessionKey, session).then(function () {
  144. handler(null, session);
  145. })
  146. }
  147. })
  148. });
  149. }
  150. }
  151. /**
  152. * 创建会话。mysql
  153. * @param sessionId
  154. * @param name
  155. * @param type
  156. * @param participantArray
  157. * @param messageId
  158. * @param handler
  159. */
  160. createSessionToMysql(sessionId, name, type, participantArray, messageId, handler) {
  161. let self = this;
  162. //如果sessionId不存在则执行创建sessionId过程
  163. let participantIdArray = [];
  164. for (let i in participantArray) {
  165. participantIdArray.push(participantArray[i].split(":")[0]);
  166. }
  167. //流程1-判断是否存在sessionId不存在则创建对应的sessionId;
  168. if (!sessionId) {
  169. if (type == SESSION_TYPES.P2P || type == SESSION_TYPES.SYSTEM) {
  170. ParticipantRepo.findSessionIdByParticipantIds(participantIdArray[0], participantIdArray[1], function (err, res) {
  171. sessionId = res;
  172. callBusinessType();
  173. });
  174. } else {
  175. return handler("MUC模式和团队模式,不允许sessionId为空!", null);
  176. }
  177. } else {
  178. callBusinessType();
  179. }
  180. //流程2-判断session的业务类型;
  181. function callBusinessType() {
  182. if(type==SESSION_TYPES.MUC){
  183. callCreateSession(SESSION_BUSINESS_TYPE.PATIENT);
  184. }else{
  185. ParticipantRepo.getBusinessType(participantIdArray, function (err, businessType) {
  186. if (err) {
  187. handler(err, null);
  188. return;
  189. }
  190. callCreateSession(businessType);
  191. });
  192. }
  193. }
  194. //流程3-发起session创建 返回session实例
  195. function callCreateSession(businessType) {
  196. //查找该sessionId是否存在存在则直接返回实例
  197. SessionRepo.findOne(sessionId, function (err, res) {
  198. if (res.length > 0) {//已经存在
  199. //更新成员
  200. Participants.saveParticipantsToMysql(sessionId, participantArray, function (err, update) {
  201. handler(null, res[0]);
  202. return;
  203. })
  204. let createDate = new Date();
  205. self.saveSessionToMysql(sessionId, name, type, createDate, businessType, function (err, res) {
  206. logger.info("update session status is true");
  207. })
  208. } else {
  209. let createDate = new Date();
  210. let session = {
  211. id: sessionId,
  212. name: name,
  213. type: type,
  214. create_date: createDate.getTime(),
  215. business_type: businessType
  216. };
  217. //将session写入数据库
  218. self.saveSessionToMysql(sessionId, name, type, createDate, businessType, function (err, res) {
  219. if (err) {
  220. handler(err, null);
  221. return;
  222. }
  223. callCreateParticipants(session);
  224. })
  225. }
  226. });
  227. }
  228. //流程4-发起session成员创建
  229. function callCreateParticipants(session) {
  230. Participants.saveParticipantsToMysql(sessionId, participantArray, function (err, res) {
  231. if (err) {
  232. handler(err, null);
  233. return;
  234. } else {
  235. handler(null, session);
  236. return;
  237. }
  238. })
  239. }
  240. }
  241. /**
  242. * 最近会话列表,7天内。
  243. *
  244. * @param userId
  245. * @param dateSpan
  246. */
  247. getRecentSessions(userId, dateSpan) {
  248. let self = this;
  249. SessionRepo.findAllByTimestampAndType(userId, dateSpan, function (err, res) {
  250. if (err) {
  251. ModelUtil.emitError(self.eventEmitter, "Get recent sessions failed", err);
  252. return;
  253. }
  254. let sessions = [];
  255. res.forEach(function (session) {
  256. //最近列表用于转发,过滤不可用的咨询
  257. if(session.last_content_type != CONTENT_TYPES.TopicEnd){
  258. sessions.push({
  259. id: session.id,
  260. name: session.name,
  261. type: session.type,
  262. business_type: session.business_type,
  263. create_date: session.create_date
  264. })
  265. }
  266. });
  267. ModelUtil.emitOK(self.eventEmitter, sessions);
  268. });
  269. }
  270. /**
  271. * 保存session到MySQL
  272. * @param sessionId
  273. * @param name
  274. * @param type
  275. * @param createDate
  276. * @param businessType
  277. * @param handler
  278. */
  279. saveSessionToMysql(sessionId, name, type, createDate, businessType, handler) {
  280. SessionRepo.saveSession(sessionId, name, type, createDate, businessType, handler);
  281. }
  282. /**
  283. * 获取某个用户的全部session列表
  284. * @param userId
  285. * @param handler
  286. */
  287. getUserSessionsFromMysql(userId, handler) {
  288. SessionRepo.findAll(userId, handler);
  289. }
  290. /**
  291. * 获取session单个对象
  292. * @param sessionId
  293. * @param handler
  294. */
  295. getSessions(sessionId, handler) {
  296. SessionRepo.findOne(sessionId, handler);
  297. }
  298. getSession(sessionId,userId,handler){
  299. let self = this;
  300. let sessionKey = RedisModel.makeRedisKey(REDIS_KEYS.Session, sessionId);
  301. redis.hgetallAsync(sessionKey).then(function(session){
  302. if(session.type==SESSION_TYPES.P2P){
  303. ParticipantRepo.findNameById(userId, function (err, res) {
  304. session.name = res[0].name;
  305. if(handler){
  306. handler(null,session);
  307. return;
  308. }
  309. ModelUtil.emitOK(self.eventEmitter, session);
  310. })
  311. }else{
  312. if(handler){
  313. handler(null,session);
  314. return;
  315. }
  316. ModelUtil.emitOK(self.eventEmitter, session);
  317. }
  318. }).catch(function (err) {
  319. logger.error("Get session failed: ", err);
  320. if(handler){
  321. handler(null,session);
  322. return;
  323. }
  324. ModelUtil.emitError(self.eventEmitter, {message: err, status: -1}, null);
  325. })
  326. }
  327. /**
  328. * 根据用户ID获取用户的session列表
  329. * @param userId
  330. * @param page
  331. * @param size
  332. * @param businessType
  333. */
  334. getUserSessions(userId, page, size, businessType) {
  335. let userSessionKey = RedisModel.makeRedisKey(REDIS_KEYS.UserSessions, userId);
  336. let self = this;
  337. if (page > 0) {
  338. if (page == 1) {
  339. page = 0;
  340. }
  341. page = page + page * size;
  342. }
  343. async.waterfall([
  344. // 获取会话ID列表
  345. function (callback) {
  346. redis.zrevrangeAsync(userSessionKey, page, size)
  347. .then(function (sessionIds) {
  348. if (sessionIds.length == 0) {
  349. ModelUtil.emitOK(self.eventEmitter, []);
  350. return;
  351. }
  352. callback(null, sessionIds);
  353. })
  354. },
  355. // 遍历会话
  356. function (sessionIds) {
  357. let sessionList = [];
  358. let functionList = [];
  359. for (let j = 0; j < sessionIds.length; j++) {
  360. let fun = function (index, callback) {
  361. if (!callback) {
  362. callback = index, index = 0
  363. }
  364. let sessionId = sessionIds[index];
  365. let sessionKey = RedisModel.makeRedisKey(REDIS_KEYS.Session, sessionId);
  366. let participantsRoleKey = RedisModel.makeRedisKey(REDIS_KEYS.SessionParticipantsRole, sessionId);
  367. let sessionParticipantsKey = RedisModel.makeRedisKey(REDIS_KEYS.SessionParticipants, sessionId);
  368. redis.multi()
  369. .hgetall(sessionKey) // 会话实体
  370. .hget(participantsRoleKey, userId) // 用户在此会话中的角色
  371. .zscore(sessionParticipantsKey, userId) // 用户在此会话中最后一次获取未读消息的时间
  372. .zrange(sessionParticipantsKey, 0, -1)
  373. .zrange(sessionParticipantsKey, 0,-1,'withscores') // 所有用户在此会话中最后一次获取未读消息的时间
  374. .hgetall(participantsRoleKey) // 所有用户在此会话中角色
  375. .execAsync()
  376. .then(function (res) {
  377. let session = res[0];
  378. let role = res[1];
  379. let lastFetchTime = res[2];
  380. let users = res[3];
  381. let participantsTimeArray = res[4];
  382. let userRoles = res[5];
  383. let participantsTime = [];
  384. let isInvite = true;
  385. for(var j in userRoles){
  386. if(userRoles[j]==1){
  387. isInvite = false;
  388. break;
  389. }
  390. }
  391. for(var j = 0 ;j<participantsTimeArray.length;j++){
  392. if(j%2!=0)continue;
  393. let participantsTimeJson = {};
  394. participantsTimeJson[participantsTimeArray[j]] = participantsTimeArray[j+1];
  395. participantsTime.push(participantsTimeJson);
  396. }
  397. let sessionName = "";
  398. let otherUserId = "";
  399. if (session.type == SESSION_TYPES.P2P) {
  400. for (let j in users) {
  401. if (users[j] != userId) {
  402. otherUserId = users[j];
  403. }
  404. }
  405. }
  406. if (!role) role = 0;
  407. if (!lastFetchTime) lastFetchTime = new Date().getTime();
  408. // 计算未读消息数
  409. let messagesByTimestampKey = RedisModel.makeRedisKey(REDIS_KEYS.MessagesByTimestamp, sessionId);
  410. redis.zcountAsync(messagesByTimestampKey, parseInt(lastFetchTime)+1, new Date().getTime())
  411. .then(function (count) {
  412. if (!otherUserId) otherUserId = userId;
  413. ParticipantRepo.findNameById(otherUserId, function (err, res) {
  414. if ((res && res.length == 0) || session.type != SESSION_TYPES.P2P) {
  415. sessionName = session.name;
  416. } else {
  417. sessionName = res[0].name;
  418. }
  419. var bir = new Date().getTime();
  420. if (res.length != 0 && res[0].birthdate) {
  421. bir = res[0].birthdate.getTime();
  422. }
  423. var sex = 1;
  424. if (res.length != 0 && res[0].sex) {
  425. sex = res[0].sex;
  426. }
  427. //end
  428. sessionList.push({
  429. id: sessionId,
  430. name: sessionName,
  431. create_date: session.create_date,
  432. last_content_type: session.last_content_type||"",
  433. last_content: session.last_content||"",
  434. sender_id: session.last_sender_id||"",
  435. type: session.type,
  436. sender_name: session.last_sender_name||"",
  437. unread_count: count,
  438. business_type: session.business_type,
  439. my_role: role,
  440. sender_sex: sex,
  441. sender_birthday: bir,
  442. participantsTimeArray:participantsTime,
  443. status:session.status,
  444. is_invite:isInvite
  445. });
  446. index = (parseInt(index) + 1);
  447. if (index == sessionIds.length) {
  448. ModelUtil.emitOK(self.eventEmitter, sessionList);
  449. } else {
  450. callback(null, index);
  451. }
  452. })
  453. })
  454. })
  455. .catch(function (err) {
  456. logger.error("Get sessions failed: ", err);
  457. });
  458. };
  459. functionList.push(fun);
  460. }
  461. async.waterfall(functionList);
  462. }
  463. ]);
  464. }
  465. /**
  466. * 根据用户ID获取用户已经结束咨询的session列表
  467. * @param userId
  468. * @param page
  469. * @param size
  470. * @param businessType
  471. */
  472. getUserStatusSessions(userId,status,businessType,page, size) {
  473. let userSessionKey = RedisModel.makeRedisKey(REDIS_KEYS.UserSessions, userId);
  474. let self = this;
  475. async.waterfall([
  476. // 获取会话ID列表
  477. function (callback) {
  478. SessionRepo.findAllByTypeAndStatus(userId,businessType,status,page,size,function(err,res){
  479. if (res.length == 0) {
  480. ModelUtil.emitOK(self.eventEmitter, []);
  481. return;
  482. }
  483. var sessionIds=[];
  484. for(var j in res){
  485. sessionIds.push(res[j].id);
  486. }
  487. callback(null,sessionIds);
  488. })
  489. },
  490. // 遍历会话
  491. function (sessionIds) {
  492. let sessionList = [];
  493. let functionList = [];
  494. for (let j = 0; j < sessionIds.length; j++) {
  495. let fun = function (index, callback) {
  496. if (!callback) {
  497. callback = index, index = 0
  498. }
  499. let sessionId = sessionIds[index];
  500. let sessionKey = RedisModel.makeRedisKey(REDIS_KEYS.Session, sessionId);
  501. let participantsRoleKey = RedisModel.makeRedisKey(REDIS_KEYS.SessionParticipantsRole, sessionId);
  502. let sessionParticipantsKey = RedisModel.makeRedisKey(REDIS_KEYS.SessionParticipants, sessionId);
  503. redis.multi()
  504. .hgetall(sessionKey) // 会话实体
  505. .hget(participantsRoleKey, userId) // 用户在此会话中的角色
  506. .zscore(sessionParticipantsKey, userId) // 用户在此会话中最后一次获取未读消息的时间
  507. .zrange(sessionParticipantsKey, 0, -1)
  508. .zrange(sessionParticipantsKey, 0,-1,'withscores') // 所有用户在此会话中最后一次获取未读消息的时间
  509. .hgetall(participantsRoleKey) // 所有用户在此会话中角色
  510. .execAsync()
  511. .then(function (res) {
  512. let session = res[0];
  513. let role = res[1];
  514. let lastFetchTime = res[2];
  515. let users = res[3];
  516. let participantsTimeArray = res[4];
  517. let userRoles = res[5];
  518. let participantsTime = [];
  519. let isInvite = true;
  520. for(var j in userRoles){
  521. if(userRoles[j]==1){
  522. isInvite = false;
  523. break;
  524. }
  525. }
  526. for(var j = 0 ;j<participantsTimeArray.length;j++){
  527. if(j%2!=0)continue;
  528. let participantsTimeJson = {};
  529. participantsTimeJson[participantsTimeArray[j]] = participantsTimeArray[j+1];
  530. participantsTime.push(participantsTimeJson);
  531. }
  532. let sessionName = "";
  533. let otherUserId = "";
  534. if (session.type == SESSION_TYPES.P2P) {
  535. for (let j in users) {
  536. if (users[j] != userId) {
  537. otherUserId = users[j];
  538. }
  539. }
  540. }
  541. if (!role) role = 0;
  542. if (!lastFetchTime) lastFetchTime = new Date().getTime();
  543. // 计算未读消息数
  544. let messagesByTimestampKey = RedisModel.makeRedisKey(REDIS_KEYS.MessagesByTimestamp, sessionId);
  545. redis.zcountAsync(messagesByTimestampKey, parseInt(lastFetchTime)+1, new Date().getTime())
  546. .then(function (count) {
  547. if (!otherUserId) otherUserId = userId;
  548. ParticipantRepo.findNameById(otherUserId, function (err, res) {
  549. if ((res && res.length == 0) || session.type != SESSION_TYPES.P2P) {
  550. sessionName = session.name;
  551. } else {
  552. sessionName = res[0].name;
  553. }
  554. var bir = new Date().getTime();
  555. if (res.length != 0 && res[0].birthdate) {
  556. bir = res[0].birthdate.getTime();
  557. }
  558. var sex = 1;
  559. if (res.length != 0 && res[0].sex) {
  560. sex = res[0].sex;
  561. }
  562. sessionList.push({
  563. id: sessionId,
  564. name: sessionName,
  565. create_date: session.create_date,
  566. last_content_type: session.last_content_type,
  567. last_content: session.last_content,
  568. sender_id: session.last_sender_id,
  569. type: session.type,
  570. sender_name: session.last_sender_name,
  571. unread_count: count,
  572. business_type: session.business_type,
  573. my_role: role,
  574. sender_sex: sex,
  575. sender_birthday: bir,
  576. participantsTimeArray:participantsTime,
  577. status:session.status,
  578. is_invite:isInvite
  579. });
  580. index = (parseInt(index) + 1);
  581. if (index == sessionIds.length) {
  582. ModelUtil.emitOK(self.eventEmitter, sessionList);
  583. } else {
  584. callback(null, index);
  585. }
  586. })
  587. })
  588. })
  589. .catch(function (err) {
  590. logger.error("Get sessions failed: ", err);
  591. });
  592. };
  593. functionList.push(fun);
  594. }
  595. async.waterfall(functionList);
  596. }
  597. ]);
  598. }
  599. /**
  600. * 获取会话消息。全部,不管已读/未读状态。
  601. *
  602. * @param sessionId 会话ID
  603. * @param userId 拉取消息的人
  604. * @param page 第几页
  605. * @param pagesize 分页数量
  606. * @param start_msg_id 消息会话最新的一条消息的ID
  607. * @param end_msg_id 消息会话刚开始的消息ID
  608. * @remark
  609. * start_msg_id end_msg_id 为空取会话倒序的根据分页的消息数据
  610. * start_msg_id 为空 end_msg_id 不为空根据end_msg_id取旧的消息(offset=1可以排除本身)返回指定分页的数据
  611. * end_msg_id 为空 start_msg_id 不为空 根据 start_msg_id 取出新消息(offset=1可以排除本身)返回指定分页的数据
  612. * end_msg_id start_msg_id 都不为空返回指定区间的消息
  613. */
  614. getMessages(sessionId, user, start_msg_id, end_msg_id, page, pagesize, isoffset, handler) {
  615. let self = this;
  616. let message_timestamp_key = RedisModel.makeRedisKey(REDIS_KEYS.MessagesByTimestamp, sessionId);
  617. if (!start_msg_id && !end_msg_id) {
  618. redis.zrevrangeAsync(message_timestamp_key, 0, 0).then(function (res) {
  619. if (res.length == 0) {
  620. if (handler) {
  621. handler(null, res);
  622. return;
  623. }
  624. ModelUtil.emitOK(self.eventEmitter, res);
  625. return;
  626. }
  627. start_msg_id = res[0];
  628. redis.zrangeAsync(message_timestamp_key, 0, 0).then(function (res) {
  629. if (res.length == 0) {
  630. if (handler) {
  631. handler(null, res);
  632. return;
  633. }
  634. ModelUtil.emitOK(self.eventEmitter, res);
  635. return;
  636. }
  637. end_msg_id = res[0];
  638. self.getMessagesByPage(sessionId, user, end_msg_id, start_msg_id, page, pagesize, isoffset, function (err, res) {
  639. if (err) {
  640. if (handler) {
  641. handler(err, null);
  642. return;
  643. }
  644. logger.error("getMessagesByPage error" + err);
  645. ModelUtil.emitError(self.eventEmitter, err, err);
  646. } else {
  647. if (handler) {
  648. handler(null, res);
  649. return;
  650. }
  651. ModelUtil.emitOK(self.eventEmitter, res);
  652. }
  653. })
  654. })
  655. })
  656. } else if (!start_msg_id) {
  657. redis.zrevrangeAsync(message_timestamp_key, 0, 0).then(function (res) {
  658. if (res.length == 0) {
  659. if (handler) {
  660. handler(null, res);
  661. return;
  662. }
  663. ModelUtil.emitOK(self.eventEmitter, res);
  664. return;
  665. }
  666. start_msg_id = res[0];
  667. self.getMessagesByPage(sessionId, user, start_msg_id,end_msg_id , page, pagesize, isoffset, function (err, res) {
  668. if (err) {
  669. if (handler) {
  670. handler(err, null);
  671. return;
  672. }
  673. logger.error("getMessagesByPage error" + err);
  674. ModelUtil.emitError(self.eventEmitter, err, err);
  675. } else {
  676. if (handler) {
  677. handler(null, res);
  678. return;
  679. }
  680. ModelUtil.emitOK(self.eventEmitter, res);
  681. }
  682. })
  683. })
  684. } else if (!end_msg_id) {
  685. redis.zrangeAsync(message_timestamp_key, 0, 0).then(function (res) {
  686. if (res.length == 0) {
  687. ModelUtil.emitOK(self.eventEmitter, res);
  688. return;
  689. }
  690. end_msg_id = res[0];
  691. self.getMessagesByPage(sessionId, user, end_msg_id,start_msg_id, page, pagesize, isoffset, function (err, res) {
  692. if (err) {
  693. if (handler) {
  694. handler(err, null);
  695. return;
  696. }
  697. logger.error("getMessagesByPage error" + err);
  698. ModelUtil.emitError(self.eventEmitter, err, err);
  699. } else {
  700. if (handler) {
  701. handler(null, res);
  702. return;
  703. }
  704. ModelUtil.emitOK(self.eventEmitter, res);
  705. }
  706. })
  707. })
  708. } else {
  709. self.getMessagesByPage(sessionId, user, end_msg_id, start_msg_id, page, pagesize, isoffset, function (err, res) {
  710. if (err) {
  711. if (handler) {
  712. handler(err, null);
  713. return;
  714. }
  715. logger.error("getMessagesByPage error" + err);
  716. ModelUtil.emitError(self.eventEmitter, err, err);
  717. } else {
  718. if (handler) {
  719. handler(null, res);
  720. return;
  721. }
  722. ModelUtil.emitOK(self.eventEmitter, res);
  723. }
  724. })
  725. }
  726. }
  727. /**
  728. * 分页获取会话消息。
  729. *
  730. * @param sessionId 必选。会话ID
  731. * @param userId 必选。用户ID
  732. * @param startMsgId 必选。会话的的起始消息ID,作为检索的起始依据
  733. * @param endMsgId 必选。会话中的结束消息ID
  734. * @param page 必选。页码
  735. * @param size 必选。页面大小
  736. * @param handler 必选。回调
  737. */
  738. getMessagesByPage(sessionId, userId, startMsgId, endMsgId, page, size, isoffset, handler) {
  739. let messagesTimestampKey = RedisModel.makeRedisKey(REDIS_KEYS.MessagesByTimestamp, sessionId);
  740. let messagesKey = RedisModel.makeRedisKey(REDIS_KEYS.Messages, sessionId);
  741. let sessionKey = RedisModel.makeRedisKey(REDIS_KEYS.Session, sessionId);
  742. let sessionParticipantsKey = RedisModel.makeRedisKey(REDIS_KEYS.SessionParticipants, sessionId);
  743. let participants = new Participants();
  744. let offset = (page - 1 < 0 ? 0 : page - 1) * size;
  745. let count = size;
  746. if (page > 1 || isoffset == 1) {
  747. offset += 1; // 翻页由于闭区间,需跳过本身数据
  748. }
  749. participants.existsParticipant(sessionId, userId, function (err, res) {
  750. if (!res) {
  751. handler(Error("User not found in session " + sessionId), null);
  752. } else {
  753. //将消息ID转换成分值
  754. redis.multi()
  755. .zscore(messagesTimestampKey, startMsgId)
  756. .zscore(messagesTimestampKey, endMsgId)
  757. .hgetall(sessionKey)
  758. .zrange(sessionParticipantsKey, 0, -1)
  759. .execAsync()
  760. .then(function (res) {
  761. let startMsgScore = res[1];
  762. let endMsgScore = res[0];
  763. let session = res[2];
  764. let users = res[3];
  765. if (startMsgScore == null || endMsgScore == null || (startMsgScore == endMsgScore && isoffset == 1)) {
  766. handler(null, []);
  767. return;
  768. }
  769. //结束大于开始,正序取数据,返回的数据顺序也是逆序的,反向拉取数据,
  770. // 当end>start取出来都是空的,为了给前端获取新数据使用,一般不出现这种情况
  771. if(endMsgScore>startMsgScore){
  772. redis.zrangebyscoreAsync(messagesTimestampKey, startMsgScore, endMsgScore, "limit", offset, count)
  773. .then(function (res) {
  774. if (res.length == 0) {
  775. handler(null, []);
  776. return;
  777. }
  778. redis.hmgetAsync(messagesKey, res).then(function (messages) {
  779. messages.reverse();
  780. handler(null, messages);
  781. }).then(function () {
  782. Sessions.updateParticipantLastFetchTime(sessionId, userId, new Date().getTime());
  783. if(session.type == SESSION_TYPES.P2P){
  784. for(var j in users){
  785. if(users[j]==userId)continue;
  786. WechatClient.sendAllRead(users[j],sessionId);
  787. }
  788. }else if(session.type == SESSION_TYPES.MUC){
  789. for(var j in users){
  790. if(users[j]==userId)continue;
  791. WechatClient.sendMucAllRead(users[j],userId,sessionId);
  792. }
  793. }
  794. })
  795. })
  796. .catch(function (err) {
  797. logger.error("Get message by page failed: ", err);
  798. handler(err, false);
  799. })
  800. }else{
  801. // 从消息时间表中过滤出要获取的消息ID列表,倒序取出消息
  802. redis.zrevrangebyscoreAsync(messagesTimestampKey, startMsgScore, endMsgScore, "limit", offset, count)
  803. .then(function (res) {
  804. if (res.length == 0) {
  805. handler(null, []);
  806. return;
  807. }
  808. redis.hmgetAsync(messagesKey, res).then(function (messages) {
  809. handler(null, messages);
  810. }).then(function () {
  811. Sessions.updateParticipantLastFetchTime(sessionId, userId, new Date().getTime());
  812. if(session.type == SESSION_TYPES.P2P){
  813. for(var j in users){
  814. if(users[j]==userId)continue;
  815. //通知对方自己已经读取数据
  816. WechatClient.sendAllRead(users[j],sessionId);
  817. }
  818. }else if(session.type == SESSION_TYPES.MUC){
  819. for(var j in users){
  820. if(users[j]==userId)continue;
  821. //如果是患者拉取数据告诉在线的医生患者已经读取数据
  822. WechatClient.sendMucAllRead(users[j],userId,sessionId);
  823. }
  824. }
  825. })
  826. })
  827. .catch(function (err) {
  828. logger.error("Get message by page failed: ", err);
  829. handler(err, false);
  830. })
  831. }
  832. })
  833. }
  834. })
  835. }
  836. /**
  837. * 获取所有会话的未读消息数。
  838. */
  839. getAllSessionsUnreadMessageCount(userId,handler) {
  840. let self = this;
  841. let count = 0;
  842. let patientCount = 0;
  843. let doctorCount = 0;
  844. SessionRepo.findAll(userId, function (err, res) {
  845. if (err) {
  846. if(handler)
  847. {
  848. handler(err,res);
  849. return;
  850. }
  851. ModelUtil.logError("getAllSessionsUnreadMessageCount is failed", err);
  852. return;
  853. }
  854. if (res.length == 0) {
  855. if(handler)
  856. {
  857. handler(err,count);
  858. return;
  859. }
  860. ModelUtil.emitOK(self.eventEmitter, {count: count});
  861. return;
  862. }
  863. for (let j in res) {
  864. if (res[j].type == SESSION_TYPES.SYSTEM) {
  865. if (j == res.length - 1) {
  866. if(handler){
  867. handler(err,count);
  868. return;
  869. }
  870. ModelUtil.emitOK(self.eventEmitter, {count: count, patient: patientCount, doctor: doctorCount});
  871. }
  872. continue;
  873. }
  874. callback(res, j, res[j]);
  875. }
  876. });
  877. function callback(res, j, session) {
  878. self.getSessionUnreadMessageCount(res[j].id, userId, function (err, con) {
  879. if (err) {
  880. if(handler)
  881. {
  882. handler(err,count);
  883. return;
  884. }
  885. ModelUtil.logError("getAllSessionsUnreadMessageCount is failed", err);
  886. }
  887. count = count + con;
  888. if (session.business_type == SESSION_BUSINESS_TYPE.PATIENT) {
  889. patientCount = patientCount + con;
  890. } else {
  891. doctorCount = doctorCount + con;
  892. }
  893. if (j == res.length - 1) {
  894. if(handler)
  895. {
  896. handler(err,count)
  897. return;
  898. }
  899. ModelUtil.emitOK(self.eventEmitter, {count: count, patient: patientCount, doctor: doctorCount});
  900. }
  901. })
  902. }
  903. }
  904. /**
  905. * 获取会话的未读消息数。根据成员最后一次获取消息的时候与当前时间。
  906. *
  907. * @param sessionId
  908. * @param userId
  909. */
  910. getSessionUnreadMessageCount(sessionId, userId, handler) {
  911. let self = this;
  912. let messagesByTimestampKey = RedisModel.makeRedisKey(REDIS_KEYS.MessagesByTimestamp, sessionId);
  913. let participantsKey = RedisModel.makeRedisKey(REDIS_KEYS.SessionParticipants, sessionId);
  914. async.waterfall([
  915. // 此成员最后获取消息的时间
  916. function (callback) {
  917. redis.zscoreAsync(participantsKey, userId)
  918. .then(function (lastFetchTime) {
  919. callback(null, lastFetchTime);
  920. })
  921. },
  922. // 计算最后获取消息的时间之后到现在有多少条消息
  923. function (lastFetchTime, callback) {
  924. if (!lastFetchTime) lastFetchTime = 0;
  925. let now = new Date().getTime();
  926. redis.zcountAsync(messagesByTimestampKey, lastFetchTime, now)
  927. .then(function (count) {
  928. if (handler) {
  929. handler(null, count);
  930. } else {
  931. ModelUtil.emitOK(self.eventEmitter, {count: count});
  932. }
  933. })
  934. }
  935. ], function (err, res) {
  936. if (err) {
  937. if (handler) {
  938. handler(err, 0);
  939. } else {
  940. ModelUtil.emitError(self.eventEmitter, "Get session unread message count failed.")
  941. }
  942. }
  943. });
  944. }
  945. /**
  946. * 获取会话未读消息数。根据成员最后一次获取消息的时候与当前时间。
  947. */
  948. getSessionUnreadMessages(sessionId, userId) {
  949. let self = this;
  950. let messagesByTimestampKey = RedisModel.makeRedisKey(REDIS_KEYS.MessagesByTimestamp, sessionId);
  951. let participantsKey = RedisModel.makeRedisKey(REDIS_KEYS.SessionParticipants, sessionId);
  952. async.waterfall([
  953. // 此成员最后获取消息的时间
  954. function (callback) {
  955. redis.zscoreAsync(participantsKey, userId)
  956. .then(function (lastFetchTime) {
  957. callback(null, lastFetchTime);
  958. })
  959. },
  960. // 最后获取消息的时间之后到现在的消息ID列表
  961. function (lastFetchTime, callback) {
  962. if (!lastFetchTime) lastFetchTime = 0;
  963. let now = new Date().getTime();
  964. redis.zrangebyscoreAsync(messagesByTimestampKey, lastFetchTime, now)
  965. .then(function (messageIds) {
  966. callback(null, messageIds);
  967. })
  968. },
  969. // 获取消息
  970. function (messageIds, callback) {
  971. if (messageIds.length == 0) {
  972. ModelUtil.emitOK(self.eventEmitter, []);
  973. return;
  974. }
  975. let startMsgId = messageIds[0];
  976. let endMsgId = messageIds[messageIds.length - 1];
  977. self.getMessagesByPage(sessionId, userId, startMsgId, endMsgId, 0, messageIds.length, 0, function (err, res) {
  978. if (err) {
  979. ModelUtil.emitError(self.eventEmitter, err.message);
  980. return;
  981. }
  982. ModelUtil.emitOK(self.eventEmitter, res);
  983. });
  984. }
  985. ], function (err, res) {
  986. if (err) {
  987. ModelUtil.emitError(self.eventEmitter, "Get session unread message count failed.")
  988. }
  989. });
  990. }
  991. /**
  992. * 保存消息。
  993. *
  994. * 也可以根据议题保存消息,但最终还是保存到与会话对象。
  995. *
  996. * see also: saveMessageByTopic
  997. *
  998. * @param message
  999. * @param sessionId
  1000. */
  1001. saveMessageBySession(sessionId, message) {
  1002. let self = this;
  1003. let messages = new Messages();
  1004. let participants = new Participants();
  1005. let sessionKey = RedisModel.makeRedisKey(REDIS_KEYS.Session, sessionId);
  1006. let messageId = mongoose.Types.ObjectId().toString();
  1007. let sessionType =0;
  1008. message.id = messageId;
  1009. // 检查会话中是否存在此成员
  1010. participants.existsParticipant(sessionId, message.sender_id, function (err, res) {
  1011. if (err) {
  1012. ModelUtil.emitError(self.eventEmitter, "Check session participant failed: ", err);
  1013. return;
  1014. }
  1015. if (res) {
  1016. redis.hmgetAsync(sessionKey, ["type", "name"]).then(function (res) {
  1017. sessionType = res[0];
  1018. let sessionName = res[1];
  1019. if (sessionType == null) {
  1020. ModelUtil.emitError(self.eventEmitter, "Session " + sessionId + " is not found.");
  1021. return;
  1022. }
  1023. if(sessionType == SESSION_TYPES.MUC&&(message.content_type == CONTENT_TYPES.PlainText ||
  1024. message.content_type == CONTENT_TYPES.Image ||
  1025. message.content_type == CONTENT_TYPES.Audio||
  1026. message.content_type == CONTENT_TYPES.Video)){
  1027. TopicRepo.findLastBySessionId(sessionId,function(err,res){
  1028. if(res&&res.length>0&&res[0].reply==0){
  1029. TopicRepo.updateTopics(res[0].id,{reply:1,reply_time:message.timestamp,reply_user:message.sender_id,reply_message_id:message.id},function(err,res){
  1030. if(err){
  1031. logger.error("update topic reply error");
  1032. }else{
  1033. logger.warn("update topic reply success");
  1034. }
  1035. });
  1036. }
  1037. })
  1038. }
  1039. // 消息保存到Redis,并更新会话最后状态、用户最后消息获取时间
  1040. messages.saveMessageToRedis(sessionId, sessionType, messageId, message);
  1041. Messages.updateLastContent(sessionKey, sessionType, sessionName, message);
  1042. Sessions.updateParticipantLastFetchTime(sessionId, message.sender_id, message.timestamp.getTime());
  1043. // 更新MYSQL中会话的最新状态,并保存消息
  1044. SessionRepo.updateSessionLastStatus(message.sender_id, message.sender_name, message.timestamp, message.content, message.content_type, sessionId);
  1045. messages.saveMessageToMysql(sessionId, sessionType, messageId, message, function (err, res) {
  1046. if (err) {
  1047. ModelUtil.emitError(self.eventEmitter, {message: "Failed to save message to mysql: " + err});
  1048. } else {
  1049. message.timestamp = message.timestamp.getTime();
  1050. ModelUtil.emitOK(self.eventEmitter, {count: 1, messages: [message]});
  1051. }
  1052. });
  1053. }).then(function (res) {
  1054. // 推送消息
  1055. ParticipantRepo.findIds(sessionId, function (err, res) {
  1056. if (err) {
  1057. ModelUtil.logError("Push message from session: get participant's id list failed: ", err);
  1058. } else {
  1059. message.session_id = sessionId;
  1060. res.forEach(function (participant) {
  1061. if (participant.id == message.sender_id||sessionType==SESSION_TYPES.SYSTEM){
  1062. message.sender_img = participant.avatar;
  1063. // if(participant.participant_role == PARTICIPANT_ROLES.REGULAR){
  1064. // if (message.content_type == CONTENT_TYPES.PlainText ||
  1065. // message.content_type == CONTENT_TYPES.Image ||
  1066. // message.content_type == CONTENT_TYPES.Audio||
  1067. // message.content_type == CONTENT_TYPES.Video){
  1068. // participants.updateUser(sessionId,message.sender_id,PARTICIPANT_ROLES.HOST);
  1069. // }
  1070. // }
  1071. callPush(res,message);
  1072. }
  1073. })
  1074. }
  1075. })
  1076. }).catch(function (err) {
  1077. ModelUtil.emitError(self.eventEmitter, {message: "Error occurred while save message to session: " + err});
  1078. })
  1079. } else {
  1080. ModelUtil.emitDataNotFound(self.eventEmitter, {message: "当前会话找不到此发送者"});
  1081. }
  1082. });
  1083. function callPush(participants,message){
  1084. participants.forEach(function (participant) {
  1085. if (participant.id !== message.sender_id &&
  1086. participant.participant_role == PARTICIPANT_ROLES.HOST) {
  1087. Sessions.pushNotification(participant.id, participant.name, message,sessionType);
  1088. }
  1089. });
  1090. }
  1091. }
  1092. sendTopicMessages(topicId, message) {
  1093. let self = this;
  1094. TopicRepo.findAllByTopicId(topicId, function (err, res) {
  1095. if (err || res.length == 0) {
  1096. ModelUtil.emitOK(self.eventEmitter, {status: -1, "message": "议题获取失败"});
  1097. return;
  1098. }
  1099. self.saveMessageByTopic(message, res[0].session_id, function (err, messageId) {
  1100. if (err) {
  1101. ModelUtil.emitOK(self.eventEmitter, {status: -1, "message": err});
  1102. } else {
  1103. message.id = messageId;
  1104. ModelUtil.emitOK(self.eventEmitter, {status: 200, "message": "发送成功", data: message});
  1105. }
  1106. });
  1107. });
  1108. }
  1109. /**
  1110. * 保存消息
  1111. *
  1112. * @param message
  1113. * @param sessionId
  1114. * @param handler
  1115. */
  1116. saveMessageByTopic(message, sessionId, handler) {
  1117. let messages = new Messages();
  1118. let participants = new Participants();
  1119. let session_key = RedisModel.makeRedisKey(REDIS_KEYS.Session, sessionId);
  1120. let messageId = mongoose.Types.ObjectId().toString();
  1121. let self = this;
  1122. let sessionType = 0;
  1123. let sessionName = "";
  1124. message.id = messageId;
  1125. if(!message.timestamp){
  1126. message.timestamp = new Date();
  1127. }
  1128. // 发送成员必须处于会话中
  1129. participants.existsParticipant(sessionId, message.sender_id, function (err, res) {
  1130. if (res) {
  1131. redis.hmgetAsync(session_key, ["type", "name"]).then(function (res) {
  1132. sessionType = res[0];
  1133. sessionName = res[1];
  1134. if (!sessionType || !sessionName) {
  1135. logger.error("Unknown session key " + session_key);
  1136. if (handler) {
  1137. handler(new Error("Unknown session key " + session_key));return;
  1138. };
  1139. }
  1140. }).then(function (res) {
  1141. // 消息数据双写,并更新用户最后消息获取时间,会话新状态等
  1142. messages.saveMessageToRedis(sessionId, sessionType, messageId, message);
  1143. messages.saveMessageToMysql(sessionId, sessionType, messageId, message);
  1144. // 更新会话最新状态及成员最后一次消息获取时间
  1145. Sessions.updateParticipantLastFetchTime(sessionId, message.sender_id, message.timestamp.getTime());
  1146. Messages.updateLastContent(session_key, sessionType, sessionName, message);
  1147. SessionRepo.updateSessionLastStatus(message.sender_id, message.sender_name, message.timestamp, message.content, message.content_type, sessionId);
  1148. if (handler) {
  1149. handler(null, messageId);
  1150. return;
  1151. }
  1152. }).then(function (res) {
  1153. // 推送消息
  1154. ParticipantRepo.findIds(sessionId, function (err, res) {
  1155. if (err) {
  1156. logger.error(err);
  1157. } else {
  1158. message.session_id = sessionId;
  1159. res.forEach(function (participant) {
  1160. if (participant.id == message.sender_id){
  1161. message.sender_img = participant.avatar;
  1162. callPush(res,message);
  1163. }
  1164. })
  1165. }
  1166. })
  1167. }).catch(function (err) {
  1168. log.error(err);
  1169. return;
  1170. })
  1171. } else {
  1172. if (handler){ handler("用户不在此会话当中!", messageId);return;}
  1173. }
  1174. });
  1175. function callPush(participants,message){
  1176. participants.forEach(function (participant) {
  1177. if (participant.id !== message.sender_id &&
  1178. participant.participant_role == PARTICIPANT_ROLES.HOST) {
  1179. Sessions.pushNotification(participant.id, participant.name, message,sessionType);
  1180. }
  1181. });
  1182. }
  1183. }
  1184. /**
  1185. * 置顶操作
  1186. */
  1187. stickSession(sessionId, user) {
  1188. let user_session_key = RedisModel.makeRedisKey(REDIS_KEYS.UserSessions, user);
  1189. let self = this;
  1190. //取出最大的session
  1191. redis.zrevrangeAsync(user_session_key, 0, 0).then(function (res) {
  1192. //获取该session的时间搓
  1193. redis.zscoreAsync(user_session_key, res).then(function (scoreres) {
  1194. let nowtime = new Date().getTime();
  1195. //当前时间搓比redis的时间搓更早证明没有置顶过
  1196. if (scoreres <= nowtime) {
  1197. //初始化置顶
  1198. redis.zaddAsync(user_session_key, STICKY_SESSION_BASE_SCORE, sessionId).then(function (res) {
  1199. logger.info("stickSession:" + sessionId + ",res:" + res);
  1200. ModelUtil.emitOK(self.eventEmitter, {});
  1201. }).then(function () {
  1202. SessionRepo.saveStickySession(sessionId, user, STICKY_SESSION_BASE_SCORE);
  1203. })
  1204. } else {
  1205. //已有置顶的数据,取出来加1保存回去
  1206. scoreres = Number(scoreres) + 1;
  1207. redis.zaddAsync(user_session_key, scoreres, sessionId).then(function () {
  1208. logger.info("stickSession:" + sessionId + ",res:" + res);
  1209. ModelUtil.emitOK(self.eventEmitter, {});
  1210. }).then(function () {
  1211. SessionRepo.saveStickySession(sessionId, user, scoreres);
  1212. })
  1213. }
  1214. })
  1215. })
  1216. }
  1217. /**
  1218. * 取消会话置顶
  1219. */
  1220. cancelStickSession(sessionId, user) {
  1221. let user_session_key = RedisModel.makeRedisKey(REDIS_KEYS.UserSessions, user);
  1222. let participants_key = RedisModel.makeRedisKey(REDIS_KEYS.SessionParticipants, sessionId);
  1223. let self = this;
  1224. redis.zscoreAsync(participants_key, user).then(function (res) {
  1225. if (!res) {
  1226. res = new Date().getTime();
  1227. }
  1228. redis.zaddAsync(user_session_key, res, sessionId).then(function (res) {
  1229. logger.info("cancelStickSession:" + sessionId);
  1230. ModelUtil.emitOK(self.eventEmitter, {});
  1231. }).then(function () {
  1232. SessionRepo.unStickySession(sessionId, user);
  1233. });
  1234. })
  1235. }
  1236. /**
  1237. * 更新会话参与者的最后消息获取时间。
  1238. *
  1239. * @param sessionId
  1240. * @param userId
  1241. */
  1242. static updateParticipantLastFetchTime(sessionId, userId, score) {
  1243. score = score + 1;
  1244. let participantsKey = RedisModel.makeRedisKey(REDIS_KEYS.SessionParticipants, sessionId);
  1245. redis.zaddAsync(participantsKey, score, userId)
  1246. .then(function (res) {
  1247. ParticipantRepo.updateLastFetchTime(new Date(score), sessionId, userId, function (err, res) {
  1248. if (err) {
  1249. logger.error("Update participant last fetch time failed: ", err);
  1250. }
  1251. });
  1252. })
  1253. .catch(function (err) {
  1254. logger.error("Update participant last fetch time failed: ", err);
  1255. });
  1256. }
  1257. /**
  1258. * 向用户推送通知,微信端用户直接推送消息,APP端通过个推发送通知消息。
  1259. *
  1260. * @param targetUserId
  1261. * @param message
  1262. */
  1263. static pushNotification(targetUserId, targetUserName, message,sessionType) {
  1264. let self = this;
  1265. Users.isPatientId(targetUserId, function (err, isPatient) {
  1266. if (isPatient) {
  1267. WechatClient.sendMessage(targetUserId, targetUserName, message);
  1268. }
  1269. else {
  1270. if(sessionType==SESSION_TYPES.P2P){
  1271. WechatClient.sendReadDoctorByDoctorId(targetUserId, message);
  1272. }
  1273. //告知医生新消息
  1274. WechatClient.sendSocketMessageToDoctor(targetUserId,message);
  1275. WlyySDK.request(targetUserId, '', '', '', '/im/common/message/messages', 'POST', function (err, res) {
  1276. let count = 0;
  1277. res = JSON.parse(res)
  1278. if (res.status == 200) {
  1279. let data = res.data;
  1280. count = parseInt(JSON.parse(data.imMsgCount).count) + parseInt(data.system.amount) + parseInt(data.healthIndex.amount) + parseInt(data.sign.amount);
  1281. }
  1282. AppClient.sendNotification(targetUserId, message,sessionType,count);
  1283. });
  1284. }
  1285. });
  1286. }
  1287. /**
  1288. * 针对MUC模式更新会话的当前状态
  1289. * @param sessionId
  1290. */
  1291. updateSessionStatus(sessionId,status,handler){
  1292. let self = this;
  1293. let sessionKey = RedisModel.makeRedisKey(REDIS_KEYS.Session,sessionId);
  1294. redis.hsetAsync(sessionKey,"status",status).then(function(res){
  1295. SessionRepo.updateSessionStatus(sessionId,status,function(err,sqlResult){
  1296. if(handler){
  1297. handler(err,sqlResult);
  1298. return;
  1299. }
  1300. if(err){
  1301. logger.error("set session status to mysql is error !");
  1302. }else{
  1303. logger.info("set session status is success");
  1304. ModelUtil.emitOK(self.eventEmitter, []);
  1305. }
  1306. });
  1307. });
  1308. }
  1309. }
  1310. // Expose class
  1311. module.exports = Sessions;