Advertisement
Guest User

Untitled

a guest
Oct 20th, 2017
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 25.69 KB | None | 0 0
  1. function ChatroomsModule(siberian, io) {
  2. var _ = require('lodash');
  3. var Base64 = require('js-base64').Base64;
  4. var Q = require('q');
  5. var escapeStringRegexp = require('escape-string-regexp');
  6. var globals = {};
  7. var emojis = _.fromPairs(_.map(require('./emoji.json'), function (emoji, code) {
  8. return [escapeStringRegexp(emoji), ':' + code + ':'];
  9. }));
  10. var functions = {
  11. replaceEmojisWithCodes: function (message) {
  12. var localMessage = message;
  13. if (emojis.length) {
  14. for (var emoji in emojis) {
  15. localMessage = localMessage.replace(new RegExp(emoji, 'g'), emojis[emoji]);
  16. }
  17. }
  18. return localMessage;
  19. },
  20. getFriendship: function (customerId, buddyId) {
  21. var deferred = Q.defer();
  22.  
  23. var result = {
  24. friend: false,
  25. blocked: false,
  26. requested: false,
  27. pending_accept: false,
  28. itsyou: false
  29. };
  30.  
  31. var friendship = null;
  32. var inverse = null;
  33.  
  34. if (parseInt(customerId, 10) === parseInt(buddyId, 10)) {
  35. result.itsyou = true;
  36. deferred.resolve(result);
  37. } else {
  38. result.itsyou = false;
  39.  
  40. siberian.application.db.query(
  41. "SELECT * FROM chatroom_friend WHERE customer_id=? AND buddy_id=?",
  42. [customerId, buddyId],
  43. function (err, data) {
  44. if (err) {
  45. console.error(err);
  46. }
  47.  
  48. if (data.length > 0) {
  49. friendship = data[0];
  50. }
  51.  
  52. siberian.application.db.query(
  53. "SELECT * FROM chatroom_friend WHERE customer_id=? AND buddy_id=?",
  54. [buddyId, customerId],
  55. function (cbErr, cbData) {
  56. if (cbErr) {
  57. console.error(cbErr);
  58. }
  59.  
  60. if (cbData.length > 0) {
  61. inverse = cbData[0];
  62. }
  63.  
  64. result.friend = (_.isObject(friendship) && _.isObject(inverse) &&
  65. !parseInt(friendship.is_blocked, 10) &&
  66. !parseInt(friendship.is_request, 10) &&
  67. !parseInt(inverse.is_blocked, 10) &&
  68. !parseInt(inverse.is_request, 10));
  69.  
  70. result.blocked = _.isObject(friendship) && parseInt(friendship.is_blocked, 10) === 1;
  71. result.requested = _.isObject(friendship) && parseInt(friendship.is_request, 10) === 1;
  72. result.pending_accept = _.isObject(inverse) && parseInt(inverse.is_request, 10) === 1;
  73.  
  74. deferred.resolve(result);
  75. }
  76. );
  77. }
  78. );
  79. }
  80.  
  81. return deferred.promise;
  82. },
  83. getUsersToNotify: function (senderId, receiverId, privateChat) {
  84. var q = Q.defer(),
  85. params = [senderId],
  86. query = "SELECT c.customer_id, cc.chatroom_customer_id, cco.chatroom_customer_options_id, c.nickname, c.customer_id, cco.is_subscribed, cco.is_subscribed_to_all FROM customer as c INNER JOIN chatroom_customer AS cc ON cc.customer_id=c.customer_id INNER JOIN chatroom_customer_options AS cco ON cco.chatroom_customer_id=cc.chatroom_customer_id WHERE (is_subscribed = 1 OR is_subscribed_to_all = 1) AND cc.is_online <> 1 AND c.customer_id <> ?";
  87.  
  88. if (privateChat) {
  89. query += " AND c.customer_id = ? AND cco.recipient_id = ?";
  90. params.push(receiverId);
  91. params.push(senderId);
  92. } else {
  93. query += " AND cco.chatroom_id = ?";
  94. params.push(receiverId);
  95. }
  96.  
  97. siberian.application.db.query(
  98. query,
  99. params,
  100. function (err, data) {
  101. if (err) {
  102. return q.reject(err);
  103. }
  104.  
  105. if (_.isArray(data) && data.length) {
  106. return q.resolve(data);
  107. }
  108.  
  109. return q.resolve([]); // No results
  110. }
  111. );
  112.  
  113. return q.promise;
  114. },
  115. getUser: function (data) {
  116. if (_.isObject (data)) {
  117. if (_.isString(data.sessionID) && data.sessionID.length > 0) {
  118. return siberian.customers
  119. .fromSessionID(data.sessionID, data.appID).then(
  120. function (user) {
  121. if (user) {
  122. var deferred = Q.defer();
  123.  
  124. siberian.application.db.query(
  125. "SELECT c.*, cc.chatroom_customer_id, cc.is_online FROM customer AS c LEFT JOIN chatroom_customer AS cc ON c.customer_id=cc.customer_id WHERE c.customer_id=?",
  126. [user.customer_id],
  127. function (cbErr, cbData) {
  128. if (cbErr) {
  129. return deferred.reject(cbErr);
  130. }
  131.  
  132. if (cbData.length > 0) {
  133. deferred.resolve(_.merge({}, user, cbData[0]));
  134. }
  135. }
  136. );
  137.  
  138. return deferred.promise;
  139. }
  140. return Q.reject(user);
  141. }
  142. );
  143. }
  144. } else if (_.isNumber(+data)) {
  145. var deferred = Q.defer();
  146.  
  147. siberian.application.db.query(
  148. "SELECT c.*, cc.chatroom_customer_id, cc.is_online, cc.last_push, cc.push_sent FROM customer AS c LEFT JOIN chatroom_customer AS cc ON c.customer_id=cc.customer_id WHERE c.customer_id=?",
  149. [data],
  150. function (cbErr, cbData) {
  151. if (cbErr) {
  152. return deferred.reject(cbErr);
  153. }
  154.  
  155. if (cbData.length > 0) {
  156. deferred.resolve(cbData[0]);
  157. }
  158. }
  159. );
  160.  
  161. return deferred.promise;
  162. }
  163.  
  164. return Q.reject(false);
  165. },
  166. setUserOnline: function (localConnection, data) {
  167. return functions.getUser(data)
  168. .then(function (user) {
  169. localConnection.socketUser = user;
  170. localConnection.socket.join('notify/' + (+user.customer_id));
  171.  
  172. return Q.Promise(function (res, rej) {
  173. var sql = "UPDATE chatroom_customer SET is_online = ?, updated_at = ?, push_sent = ?, last_push = ? WHERE customer_id=?";
  174. var params = [1, new Date(), 0, "2007-01-08 00:00:00", user.customer_id];
  175. if (user.chatroom_customer_id === null) {
  176. sql = "INSERT INTO chatroom_customer SET is_online = ?, updated_at = ?, push_sent = ?, last_push = ?, customer_id=?, created_at = ?";
  177. params.push(new Date());
  178. }
  179.  
  180. var query = siberian.application.db.query(
  181. sql,
  182. params,
  183. function (err, result) {
  184. if (err) {
  185. rej(err);
  186. }
  187.  
  188. if (user.chatroom_customer_id === null) {
  189. user.chatroom_customer_id = result.insertId;
  190. }
  191.  
  192. globals.chatio.to('customer_status/' + user.customer_id)
  193. .emit('customer_status_update', {
  194. id: user.customer_id,
  195. nickname: user.nickname,
  196. online: true
  197. });
  198.  
  199. globals.connectedUsers[user.customer_id] = user;
  200.  
  201. res(user);
  202. }
  203. );
  204. });
  205. });
  206. },
  207. setUserOffline: function (localConnection) {
  208. if (_.isObject(localConnection.socketUser)) {
  209. return Q.Promise(function (res, rej) {
  210. siberian.application.db.query(
  211. "UPDATE chatroom_customer SET is_online = ?, updated_at = ? WHERE customer_id=?",
  212. [0, new Date(), localConnection.socketUser.customer_id],
  213. function (err, result) {
  214. if (err) {
  215. rej(err);
  216. }
  217.  
  218. globals.chatio.to('customer_status/' + localConnection.socketUser.customer_id).emit('customer_status_update', {
  219. id: localConnection.socketUser.customer_id,
  220. nickname: localConnection.socketUser.nickname,
  221. online: false
  222. });
  223.  
  224. globals.connectedUsers[localConnection.socketUser.customer_id] = undefined;
  225. delete globals.connectedUsers[localConnection.socketUser.customer_id];
  226.  
  227. _.forEach(globals.UsersByRoom, function (users, room) {
  228. globals.UsersByRoom[room] = _.reject(users, {
  229. customer_id: localConnection.socketUser
  230. });
  231. });
  232.  
  233. res();
  234. }
  235. );
  236. }).then(function () {
  237. localConnection.socketUser = null;
  238. return Q.resolve();
  239. });
  240. }
  241. return Q.resolve();
  242. },
  243. roomDoorman: function (localConnection, join, data) {
  244. if (!_.isString(data.room) || data.room.length < 1) {
  245. return;
  246. }
  247.  
  248. functions.setUserOnline(localConnection, data)
  249. .then(function (user) {
  250. var room = data.room;
  251. var isPrivateMessage = room.match(/^privroom:/);
  252. var roomId = room.match(/^(?:(?:priv)?room):(.*)$/)[1];
  253. var channel = (isPrivateMessage ? 'private' : 'chatroom') + '/' + roomId;
  254.  
  255. if (join) {
  256. localConnection.socket.join(channel);
  257.  
  258. if (!_.isArray(globals.UsersByRoom[room])) {
  259. globals.UsersByRoom[room] = [];
  260. }
  261.  
  262. if (!_.includes(globals.UsersByRoom[room], user.customer_id)) {
  263. globals.UsersByRoom[room].push(user.customer_id);
  264. }
  265.  
  266. functions.sendRoomUserlist(room);
  267. } else {
  268. localConnection.socket.leave(channel);
  269.  
  270. if (!_.isArray(globals.UsersByRoom[room])) {
  271. globals.UsersByRoom[room] = [];
  272. }
  273.  
  274. if (_.includes(globals.UsersByRoom[room], user.customer_id)) {
  275. globals.UsersByRoom[room] = _.reject(globals.UsersByRoom[room], function (id) {
  276. return parseInt(id, 10) === parseInt(user.customer_id, 10);
  277. });
  278. }
  279.  
  280. var recipientId = +data.recipient_id;
  281. var chatroomId = +data.chatroom_id;
  282.  
  283. if (recipientId || chatroomId) {
  284. siberian.application.db.query(
  285. "DELETE FROM chatroom_customer_options WHERE chatroom_customer_id = (SELECT chatroom_customer_id FROM chatroom_customer WHERE customer_id = ?) AND "+
  286. (isPrivateMessage ? "recipient_id = ?" : "chatroom_id = ?"),
  287. [user.customer_id, (isPrivateMessage ? recipientId : chatroomId)],
  288. function (err) {
  289. if (err) {
  290. console.error(err);
  291. }
  292. }
  293. );
  294. }
  295. }
  296. });
  297. },
  298. sendRoomUserlist: function (room) {
  299. var isPrivateMessage = room.match(/^privroom:/);
  300. var roomId = room.match(/^(?:(?:priv)?room):(.*)$/)[1];
  301. var channel = (isPrivateMessage ? 'private' : 'chatroom') + '/' + roomId;
  302.  
  303. if (_.isArray(globals.UsersByRoom[room])) {
  304. var users = _(_.map(globals.UsersByRoom[room], function (userId) {
  305. return _.pick(globals.connectedUsers[userId], ['customer_id', 'nickname']);
  306. })).compact().uniq().reject(function (o) {
  307. return !_.isObject(o) || !_.isNumber(o.customer_id) || o.customer_id < 1;
  308. }).value();
  309.  
  310. globals.chatio.to(channel).emit('userlist', {
  311. room: room,
  312. users: users
  313. });
  314. }
  315. },
  316. storeAndRelayMessage: function (localConnection, isPrivateMessage, data) {
  317. var receiver = isPrivateMessage ? 'recipient_id' : 'chatroom_id';
  318. var roomId = isPrivateMessage ?
  319. ([data.receiver_id, localConnection.socketUser.customer_id].sort().join(':')) :
  320. data.receiver_id;
  321. var channel = (isPrivateMessage ? 'private' : 'chatroom') + '/' + roomId;
  322.  
  323. // Just in case of a disconnect!
  324. localConnection.socket.join(channel);
  325.  
  326. var message = _.isString(data.message) && data.message.length > 0 ?
  327. functions.replaceEmojisWithCodes(data.message) : null;
  328. var image = _.isString(data.image) && data.image.length > 0 ? data.image : null;
  329.  
  330. var date = (new Date()).toISOString();
  331. var messageRow = {
  332. sender_id: localConnection.socketUser.customer_id,
  333. sender_nickname: localConnection.socketUser.nickname,
  334. message: (message && Base64.encode(message)) || null,
  335. image: image || null,
  336. created_at: date,
  337. updated_at: date
  338. };
  339.  
  340. messageRow[receiver] = data.receiver_id;
  341.  
  342. siberian.application.db.query(
  343. "INSERT INTO chatroom_message SET ?",
  344. messageRow,
  345. function (err, result) {
  346. if (err) {
  347. return console.error(err);
  348. }
  349.  
  350. messageRow.message = data.message; // reuse message with emojis, not base64
  351. messageRow.id = result.insertId;
  352.  
  353. var fullRoomId = (isPrivateMessage ? 'privroom' : 'room') + ':' + roomId;
  354.  
  355. var pushMessage = message !== null ? messageRow.message : image !== null ? ' ' : null;
  356.  
  357. if (pushMessage !== null) {
  358. var push_row = _.extend({}, messageRow, {
  359. app_id: data.appID, // we add app ID
  360. value_id: data.valueID,
  361. message: pushMessage,
  362. sender_avatar: data.sender_avatar
  363. });
  364.  
  365. // Do we have individual push ?
  366. siberian.application.db.query(
  367. "SELECT 1 FROM push_customer_message LIMIT 1",
  368. function (cbErr, cbResult) {
  369. if (!cbErr) {
  370. functions.handlePushNotification(push_row);
  371. }
  372. }
  373. );
  374. }
  375.  
  376. var msg = {
  377. id: messageRow.id,
  378. senderID: messageRow.sender_id,
  379. nickname: messageRow.sender_nickname,
  380. message: messageRow.message,
  381. image: messageRow.image,
  382. date: messageRow.created_at,
  383. room: fullRoomId
  384. };
  385. msg[receiver] = messageRow[receiver];
  386.  
  387. return globals.chatio.to(channel).emit((isPrivateMessage ? 'privmsg' : 'msg'), msg);
  388. }
  389. );
  390. },
  391. notify: function (userCustomerId, messageRow) {
  392. functions.getUser(userCustomerId)
  393. .then(function (user) {
  394. if (_.isObject(user) && user.customer_id > 0) {
  395. if (((Date.parse(user.last_push) || 0)+15*60*1000) < (+new Date())) {
  396. user.push_sent = 0;
  397. }
  398. if (user.push_sent < 5) {
  399. user.push_sent = user.push_sent + 1;
  400.  
  401. siberian.application.db.query(
  402. "INSERT INTO push_messages SET ?",
  403. {
  404. app_id: messageRow.app_id,
  405. type_id: 1,
  406. title: (new Buffer(messageRow.sender_nickname).toString('base64')),
  407. text: (new Buffer(messageRow.message).toString('base64')),
  408. base64: 1,
  409. cover: messageRow.sender_avatar,
  410. send_to_all: 0,
  411. send_to_specific_customer: 1,
  412. action_value: messageRow.value_id,
  413. value_id: messageRow.value_id,
  414. created_at: new Date(),
  415. updated_at: new Date()
  416. },
  417. function (err, result) {
  418. if (!err && _.isObject(result) && result.insertId > 0) {
  419. siberian.application.db.query(
  420. "INSERT INTO push_customer_message SET ?",
  421. {
  422. message_id: result.insertId,
  423. customer_id: user.customer_id
  424. },
  425. function (cbErr, cbResult) {
  426. if (!cbErr) {
  427. siberian.application.db.query(
  428. "UPDATE chatroom_customer SET push_sent=?,last_push=? WHERE customer_id=?",
  429. [user.push_sent, new Date(), user.customer_id],
  430. function () {
  431. // We actually don't have anything to do after this
  432. }
  433. );
  434. }
  435. }
  436. );
  437. }
  438. }
  439. );
  440. }
  441. }
  442. });
  443. },
  444. handlePushNotification: function (messageRow) {
  445. var receiverId = messageRow.recipient_id || messageRow.chatroom_id;
  446. var privateChat = +messageRow.recipient_id > 0;
  447.  
  448. functions.getUsersToNotify(messageRow.sender_id, receiverId, privateChat)
  449. .then(function (users) {
  450. if (_.isArray(users)) {
  451. _.forEach(users, function (user) {
  452. functions.getFriendship(user.customer_id, messageRow.sender_id)
  453. .then(function (result) {
  454. if (!result.blocked) {
  455. if (user.is_subscribed_to_all) {
  456. functions.notify(user.customer_id, messageRow);
  457. } else if (user.is_subscribed) {
  458. var mentioned = new RegExp('\\b@?'+user.nickname+'\\b', 'gi');
  459. if (messageRow.message.match(mentioned)) {
  460. functions.notify(user.customer_id, messageRow);
  461. }
  462. }
  463. }
  464. });
  465. });
  466. }
  467. });
  468. },
  469. processMessage: function (localConnection, isPrivateMessage, data) {
  470. functions.setUserOnline(localConnection, data)
  471. .then(function (user) {
  472. localConnection.socketUser = user;
  473.  
  474. if (!_.isObject(data)) {
  475. return;
  476. }
  477.  
  478. if (!_.isNumber(+data.receiver_id) || +data.receiver_id < 1) {
  479. return;
  480. }
  481.  
  482. if (isPrivateMessage) {
  483. functions.getFriendship(user.customer_id, data.receiver_id)
  484. .then(function (result) {
  485. if (result.friend) {
  486. functions.storeAndRelayMessage(localConnection, isPrivateMessage, data);
  487. }
  488. });
  489. } else {
  490. functions.storeAndRelayMessage(localConnection, isPrivateMessage, data);
  491. }
  492. });
  493. }
  494. };
  495.  
  496. this.run = function () {
  497. globals.connectedUsers = {};
  498. globals.UsersByRoom = {};
  499. globals.chatio = io.of('/chatrooms');
  500.  
  501. globals.chatio.on('connection', function (socket) {
  502. var localConnection = {
  503. socket: socket,
  504. socketUser: null
  505. };
  506.  
  507. localConnection.socket.on('online', function (data) {
  508. functions.setUserOnline(localConnection, data);
  509. });
  510.  
  511. localConnection.socket.on('join_room', functions.roomDoorman.bind(this, localConnection, true));
  512. localConnection.socket.on('leave_room', functions.roomDoorman.bind(this, localConnection, false));
  513.  
  514. localConnection.socket.on('watch_customer', function (data) {
  515. functions.setUserOnline(localConnection, data);
  516.  
  517. if (!_.isNumber(+data.customer_id) || +data.customer_id < 1) {
  518. return;
  519. }
  520.  
  521. var channel = 'customer_status/' + data.customer_id;
  522. localConnection.socket.join(channel);
  523. });
  524.  
  525. localConnection.socket.on('unwatch_customer', function (data) {
  526. functions.setUserOnline(localConnection, data);
  527.  
  528. if (!_.isNumber(+data.customer_id) || +data.customer_id < 1) {
  529. return;
  530. }
  531.  
  532. var channel = 'customer_status/' + data.customer_id;
  533. localConnection.socket.leave(channel);
  534. });
  535.  
  536. localConnection.socket.on('sendmsg', functions.processMessage.bind(this, localConnection, false));
  537. localConnection.socket.on('sendprivmsg', functions.processMessage.bind(this, localConnection, true));
  538.  
  539. localConnection.socket.on('buddy_list_update', function (data) {
  540. if (!_.isObject(data)) {
  541. return;
  542. }
  543.  
  544. if (!_.isNumber(+data.customer_id) || +data.customer_id < 1) {
  545. return;
  546. }
  547.  
  548. functions.setUserOnline(data)
  549. .then(function (user) {
  550. globals.chatio
  551. .to('notify/' + (+data.customer_id))
  552. .to('notify/' + (+user.customer_id))
  553. .emit('buddy_list_update', null);
  554. });
  555. });
  556.  
  557. localConnection.socket.on('disconnect', functions.setUserOffline.bind(this, localConnection));
  558. });
  559. };
  560. }
  561.  
  562. module.exports = function (siberian, io) {
  563. return new ChatroomsModule(siberian, io);
  564. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement