app.client.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. /**
  2. * App客户端。
  3. */
  4. "use strict";
  5. let RedisClient = require('../../repository/redis/redis.client');
  6. let RedisModel = require('./../redis.model');
  7. let AppStatusRepo = require('../../repository/mysql/app.status.repo');
  8. let ModelUtil = require('../../util/model.util');
  9. let clientCache = require('../socket.io/client.cache').clientCache();
  10. let log = require("../../util/log.js");
  11. let pusher = require('../push/pusher');
  12. let redisConn = RedisClient.redisClient().connection;
  13. const CONTENT_TYPES = require('../../include/commons').CONTENT_TYPES;
  14. const SESSION_TYPES = require('../../include/commons').SESSION_TYPES;
  15. const REDIS_KEYS = require('../../include/commons').REDIS_KEYS;
  16. const PLATFORMS = require('../../include/commons').PLATFORM;
  17. class AppClient extends RedisModel {
  18. constructor() {
  19. super();
  20. }
  21. /**
  22. * 更新客户端App状态。
  23. *
  24. * @param userId
  25. * @param appInBg
  26. * @param handler
  27. */
  28. updateAppStatus(userId, appInBg, handler) {
  29. let self = this;
  30. let userStatusKey = RedisModel.makeRedisKey(REDIS_KEYS.UserAppStatus, userId);
  31. redisConn.hgetAsync(userStatusKey, 'app_in_bg').then(function (res) {
  32. if (res !== null) {
  33. redisConn.hsetAsync(userStatusKey, 'app_in_bg', appInBg ? 1 : 0).then(function (res) {
  34. if (handler) {
  35. handler(null, true);
  36. } else {
  37. ModelUtil.emitOK(self.eventEmitter, {});
  38. }
  39. });
  40. } else {
  41. if (handler) {
  42. handler(null, true);
  43. } else {
  44. ModelUtil.emitDataNotFound(self.eventEmitter, {"message": "User is offline, unable to update app status."});
  45. }
  46. }
  47. });
  48. }
  49. /**
  50. * 获取用户App端状态。若Redis中找不到,则从MySQL中查找。
  51. *
  52. * @param userId
  53. * @param handler
  54. */
  55. static getAppStatus(userId, handler) {
  56. let userStatusKey = RedisModel.makeRedisKey(REDIS_KEYS.UserAppStatus, userId);
  57. redisConn.hgetallAsync(userStatusKey)
  58. .then(function (res) {
  59. if (res) {
  60. handler(null, res);
  61. } else {
  62. AppStatusRepo.findOne(userId, function (err, res) {
  63. if (err) throw err;
  64. let userStatus = null;
  65. if (res.length > 0) {
  66. userStatus = {
  67. platform: res[0].platform,
  68. device_token: res[0].device_token,
  69. client_id: res[0].client_id,
  70. app_in_bg: res[0].app_in_bg == 1,
  71. last_login_time: res[0].last_login_time
  72. }
  73. }
  74. handler(null, userStatus);
  75. });
  76. }
  77. })
  78. .catch(function (err) {
  79. handler(err, null);
  80. });
  81. }
  82. /**
  83. * 向App端推送消息。指令性消息不推。
  84. *
  85. * @param targetId
  86. * @param message
  87. * @param sessionType
  88. */
  89. static sendNotification(targetId, message, sessionType,badge) {
  90. if (message.content_type == CONTENT_TYPES.PlainText ||
  91. message.content_type == CONTENT_TYPES.Image ||
  92. message.content_type == CONTENT_TYPES.Audio||
  93. message.content_type == CONTENT_TYPES.Video||
  94. message.content_type == CONTENT_TYPES.GoTo||
  95. sessionType==SESSION_TYPES.SYSTEM) {
  96. AppClient.getAppStatus(targetId, function (err, userStatus) {
  97. if (err) {
  98. ModelUtil.logError("Get user app status failed", err);
  99. return;
  100. }
  101. // let pc_doctorClient = clientCache.findByIdAndType("pc_"+targetId,SOCKET_TYPES.PC_DOCTOR);
  102. // if(pc_doctorClient){
  103. // log.warn("User's pc is online, user id: " + targetId + ", we cannot send getui.");
  104. // return;
  105. // }
  106. if (!userStatus) {
  107. log.warn("User's app status is not found, user id: " + targetId + ", maybe user never login yet or logout?");
  108. return;
  109. }
  110. let tipMessage = CONTENT_TYPES.typeToDescription(parseInt(message.content_type), "您有一条新消息") || message.content;
  111. let customData = {
  112. session_id: message.session_id||'',
  113. session_type: sessionType,
  114. from: message.sender_id|| '',
  115. data: message.content,
  116. business_type: message.business_type || 1
  117. };
  118. if (userStatus.platform == PLATFORMS.iOS) {
  119. pusher.pushToSingleViaAPN(tipMessage, customData, message.content_type, userStatus.device_token,badge, function (err, res) {
  120. if (err) {
  121. ModelUtil.logError("Send notification via APN failed:"+userStatus.device_token, err);
  122. } else {
  123. log.info("Send notification via APN succeed: ", JSON.stringify(res));
  124. }
  125. });
  126. } else if (userStatus.platform == PLATFORMS.Android) {
  127. let title = '新消息';
  128. pusher.pushToSingleViaAndroid(title, tipMessage, customData, userStatus.client_id, userStatus.app_in_bg, function (err, res) {
  129. if (err) {
  130. ModelUtil.logError("Send notification via Android failed", err);
  131. } else {
  132. log.info("Send notification via Android succeed: ", JSON.stringify(res));
  133. }
  134. });
  135. }
  136. });
  137. }
  138. }
  139. }
  140. // Expose class
  141. module.exports = AppClient;