UNPKG

linagora-rse

Version:
247 lines (200 loc) 8.2 kB
'use strict'; var q = require('q'); module.exports = function(dependencies) { var logger = dependencies('logger'); var collaborationModule = dependencies('collaboration'); var messageModule = dependencies('message'); var userModule = dependencies('user'); var activitystreamsModule = dependencies('activitystreams'); var arrayHelper = dependencies('helpers').array; var tracker = activitystreamsModule.tracker; var readTracker = tracker.getTracker('read'); var pushTracker = tracker.getTracker('push'); var weight = require('./weight')(dependencies); var mail = require('./mail')(dependencies); var trackerUpdater = require('./tracker')(dependencies); return { setReadAndInvolvedFlags: function(message, thread, user) { // If thread.read is undefined then the message is read message.read = !('read' in thread) || thread.read; message.involved = Boolean(message.author && message.author.id === user.id); if (!arrayHelper.isNullOrEmpty(message.responses)) { message.responses.forEach(function(messageResponse) { if (!arrayHelper.isNullOrEmpty(thread.responses)) { // Find the response with the same id in the thread responses array and init the read field thread.responses.some(function(threadResponse) { if (threadResponse.message && messageResponse.id === threadResponse.message.id) { messageResponse.read = threadResponse.read; return true; } else { messageResponse.read = true; return false; } }); } else { messageResponse.read = true; } // Check involvement if (messageResponse.author && messageResponse.author.id === user.id) { message.involved = true; } }); } return q(message); }, buildMessageContext: function(thread, user) { if (!thread || !user) { return q.reject(new Error('Thread and user is required')); } var self = this; return q.nfcall(messageModule.get, thread.message._id).then( function(message) { return self.setReadAndInvolvedFlags(message, thread, user); }, function(err) { logger.error('Daily digest error when retrieving message from database, skip message', err); return q({}); } ); }, getMostRecentTimelineEntry: function(timelineEntryId1, timelineEntryId2) { if (!timelineEntryId1 && !timelineEntryId2) { return q(); } if (!timelineEntryId1 && timelineEntryId2) { return q(timelineEntryId2); } if (!timelineEntryId2 && timelineEntryId1) { return q(timelineEntryId1); } var _getTimelineEntry = q.denodeify(activitystreamsModule.getTimelineEntry); return q.spread([_getTimelineEntry(timelineEntryId1), _getTimelineEntry(timelineEntryId2)], function(timelineEntry1, timelineEntry2) { if (!timelineEntry1 && !timelineEntry2) { return; } if (!timelineEntry1) { return timelineEntryId2; } if (!timelineEntry2) { return timelineEntryId1; } return timelineEntry1.published > timelineEntry2.published ? timelineEntryId1 : timelineEntryId2; }); }, getTracker: function(user, collaboration) { if (!user || !collaboration) { return q.reject(new Error('User and collaboration are required')); } var self = this; var readTrackerGetLastTimelineEntry = q.denodeify(readTracker.getLastTimelineEntry); var pushTrackerGetLastTimelineEntry = q.denodeify(pushTracker.getLastTimelineEntry); return q.spread([ readTrackerGetLastTimelineEntry(user, collaboration.activity_stream.uuid), pushTrackerGetLastTimelineEntry(user, collaboration.activity_stream.uuid) ], function(read, push) { return self.getMostRecentTimelineEntry(read, push).then(function(result) { return !result || result === read ? readTracker : pushTracker; }); }); }, loadUserDataForCollaboration: function(user, collaboration) { if (!user || !collaboration) { return q.reject(new Error('User and collaboration are required')); } var self = this; return this.getTracker(user, collaboration).then(function(tracker) { return q.nfcall(tracker.buildThreadViewSinceLastTimelineEntry, user._id, collaboration.activity_stream.uuid).then(function(threads) { if (!threads || Object.keys(threads).length === 0) { return q({ messages: [], collaboration: collaboration }); } var messagesContext = []; Object.keys(threads).forEach(function(messageId) { messagesContext.push(self.buildMessageContext(threads[messageId], user)); }); return q.all(messagesContext).then(function(messages) { return { messages: messages.filter(function(message) { // Do not put !message.involved because if message.involved is undefined it must return false return message && message.involved === false; }), collaboration: collaboration }; }); }); }); }, userDailyDigest: function(user) { if (!user) { return q.reject(new Error('User is required')); } var self = this; logger.info('Processing daily digest for user', user._id.toString(), user.emails[0]); return q.nfcall(collaborationModule.getCollaborationsForTuple, { id: user._id, objectType: 'user' }).then(function(collaborations) { if (!collaborations || collaborations.length === 0) { return q.resolve({user: user, data: [], status: 'No collaborations found'}); } var collaborationData = collaborations.map(function(collaboration) { return self.loadUserDataForCollaboration(user, collaboration); }); function sendDigest(data) { var hasUnreadMessages = data.some(function(object) { return object.messages.length !== 0; }); if (!hasUnreadMessages) { logger.debug('No unread message for user %s %s', user._id.toString(), user.emails[0]); return data; } logger.info('Sending digest to user %s %s', user._id.toString(), user.emails[0]); return mail.process(user, data).then(function() { return data; }); } function processUserData(data) { logger.info('Processing data for user %s %s', user._id.toString(), user.emails[0]); return q.all(data.filter(Boolean).map(function(d) { return weight.compute(user, d); })); } function sendFailure(err) { logger.error('Failed to send digest for user %s', user._id, err.stack); return q.reject(err); } function updateTrackers(data) { return trackerUpdater.updateTracker(user, data); } return q.all(collaborationData) .then(processUserData) .then(sendDigest) .then(updateTrackers, sendFailure) .then(function(data) { return {user: user, data: data}; }, function(err) { logger.error('Error occured while processing daily digest for user %s', user._id.toString(), err); return {user: user, err: err}; }); }); }, digest: function() { logger.info('Running the digest'); var self = this; function getAllUsers() { return q.nfcall(userModule.list); } function populateDomain(user) { return q.ninvoke(user, 'populate', 'domains.domain_id'); } return getAllUsers().then(function(users) { return q.all((users || []).map(populateDomain)); }).then(function(users) { return q.all((users || []).map(self.userDailyDigest.bind(self))); }); } }; };