3 var pushNotificationFilter = require('gitter-web-push-notification-filter');
4 var pushNotificationGateway = require('../../gateways/push-notification-gateway');
5 var serializer = require('../../serializers/notification-serializer');
6 var unreadItemService = require('gitter-web-unread-items');
7 var debug = require('debug')('gitter:app:push-notification-generator');
8 var Promise = require('bluebird');
9 var _ = require('lodash');
11 var MAX_MESSAGES_FOR_NOTIFICATION = 3;
13 function serializeItems(troupeId, recipientUserId, chatIds) {
14 var troupeStrategy = new serializer.TroupeIdStrategy({ recipientUserId: recipientUserId });
15 var chatStrategy = new serializer.ChatIdStrategy();
18 serializer.serializeObject(troupeId, troupeStrategy),
19 serializer.serialize(chatIds, chatStrategy)
24 * Given a set of unread items and mentions, return `n` items
25 * which will be presented to the user in the push notification
27 function selectChatsForNotification(unreadItems, mentions) {
28 // Trivial case: there are three or less unread items, send them immediately
29 if (unreadItems.length <= MAX_MESSAGES_FOR_NOTIFICATION) return unreadItems;
31 unreadItems.sort(); // Default sorting works fine with mongoids
33 // Simple case: there are no mentions. Just send the first three unread items
34 if (!mentions.length) {
35 return unreadItems.slice(0, MAX_MESSAGES_FOR_NOTIFICATION);
38 // Mentions case: get the first mention and then get the two closest unread items
39 // to that mention (ie, the two before, the two around or the two after)
40 var firstMention = _.min(mentions);
41 var indexOfFirstMention = unreadItems.indexOf(firstMention);
42 if (indexOfFirstMention <= 0) {
43 /* This should never happen. Things are broken. Failback */
44 return unreadItems.slice(0, MAX_MESSAGES_FOR_NOTIFICATION);
47 if (indexOfFirstMention === unreadItems.length - 1) {
48 /* Mention is the last message */
49 return unreadItems.slice(-MAX_MESSAGES_FOR_NOTIFICATION);
53 .slice(indexOfFirstMention - Math.floor(MAX_MESSAGES_FOR_NOTIFICATION / 2))
54 .slice(0, MAX_MESSAGES_FOR_NOTIFICATION);
57 function notifyUserOfActivitySince(userId, troupeId, since, notificationNumber) {
59 'notifyUserOfActivitySince userId=%s, troupeId=%s, since=%s, notificationNumber=%s',
66 return unreadItemService
67 .getUnreadItemsForUserTroupeSince(userId, troupeId, since)
68 .spread(function(unreadItems, mentions) {
69 // mentions should always be a subset of unreadItems
70 if (!unreadItems.length) {
71 debug('User %s has no unread items since %s in troupeId=%s', userId, since, troupeId);
75 var chatIdsForNotification = selectChatsForNotification(unreadItems, mentions);
77 return serializeItems(troupeId, userId, chatIdsForNotification).spread(function(
81 if (!troupe || !chats || !chats.length) return;
83 return pushNotificationGateway.sendUserNotification('new_chat', userId, {
86 hasMentions: !!(mentions && mentions.length)
92 function sendUserTroupeNotification(
96 userNotifySetting /*, mentioned*/
98 return pushNotificationFilter
99 .canUnlockForNotification(userId, troupeId, notificationNumber)
100 .then(function(startTime) {
103 'Unable to obtain lock to notify %s for user %s troupe %s. Skipping',
111 // TODO: remove this....
112 if (userNotifySetting === 'mute') {
113 /* Mute this troupe for this user */
117 return notifyUserOfActivitySince(
127 module.exports.sendUserTroupeNotification = sendUserTroupeNotification;
128 module.exports.testOnly = {
129 selectChatsForNotification: selectChatsForNotification,
130 serializeItems: serializeItems