| 
									
										
										
										
											2014-03-21 15:40:37 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 'use strict'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var async = require('async'), | 
					
						
							|  |  |  | 	winston = require('winston'), | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-15 18:11:57 -04:00
										 |  |  | 	db = require('../database'), | 
					
						
							|  |  |  | 	user = require('../user'), | 
					
						
							|  |  |  | 	notifications = require('../notifications'), | 
					
						
							|  |  |  | 	categories = require('../categories'), | 
					
						
							| 
									
										
										
										
											2014-05-15 10:38:02 -04:00
										 |  |  | 	privileges = require('../privileges'); | 
					
						
							| 
									
										
										
										
											2014-03-21 15:40:37 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | module.exports = function(Topics) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-24 13:10:10 -04:00
										 |  |  | 	var unreadCutoff = 86400000; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-21 15:40:37 -04:00
										 |  |  | 	Topics.getTotalUnread = function(uid, callback) { | 
					
						
							|  |  |  | 		Topics.getUnreadTids(uid, 0, 20, function(err, tids) { | 
					
						
							|  |  |  | 			callback(err, tids ? tids.length : 0); | 
					
						
							|  |  |  | 		}); | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-29 14:50:24 -04:00
										 |  |  | 	Topics.getUnreadTopics = function(uid, start, stop, callback) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		var unreadTopics = { | 
					
						
							|  |  |  | 			showSelect: true, | 
					
						
							|  |  |  | 			nextStart : 0, | 
					
						
							|  |  |  | 			topics: [] | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-23 18:19:30 -05:00
										 |  |  | 		async.waterfall([ | 
					
						
							|  |  |  | 			function(next) { | 
					
						
							|  |  |  | 				Topics.getUnreadTids(uid, start, stop, next); | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			function(tids, next) { | 
					
						
							|  |  |  | 				if (!tids.length) { | 
					
						
							|  |  |  | 					return next(null, []); | 
					
						
							| 
									
										
										
										
											2014-08-29 14:50:24 -04:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2015-01-23 18:19:30 -05:00
										 |  |  | 				Topics.getTopicsByTids(tids, uid, next); | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			function(topicData, next) { | 
					
						
							| 
									
										
										
										
											2014-08-29 14:50:24 -04:00
										 |  |  | 				if (!Array.isArray(topicData) || !topicData.length) { | 
					
						
							| 
									
										
										
										
											2015-01-23 18:19:30 -05:00
										 |  |  | 					return next(null, unreadTopics); | 
					
						
							| 
									
										
										
										
											2014-08-29 14:50:24 -04:00
										 |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-02 17:46:39 -04:00
										 |  |  | 				unreadTopics.topics = topicData; | 
					
						
							|  |  |  | 				unreadTopics.nextStart = stop + 1; | 
					
						
							| 
									
										
										
										
											2015-01-23 18:19:30 -05:00
										 |  |  | 				next(null, unreadTopics); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		], callback); | 
					
						
							| 
									
										
										
										
											2014-08-29 14:50:24 -04:00
										 |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-21 15:40:37 -04:00
										 |  |  | 	Topics.getUnreadTids = function(uid, start, stop, callback) { | 
					
						
							|  |  |  | 		uid = parseInt(uid, 10); | 
					
						
							| 
									
										
										
										
											2014-08-09 16:15:22 -04:00
										 |  |  | 		if (uid === 0) { | 
					
						
							| 
									
										
										
										
											2014-09-16 12:38:27 -04:00
										 |  |  | 			return callback(null, []); | 
					
						
							| 
									
										
										
										
											2014-08-15 18:11:57 -04:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-03-21 15:40:37 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-24 13:10:10 -04:00
										 |  |  | 		var cutoff = Date.now() - unreadCutoff; | 
					
						
							| 
									
										
										
										
											2014-09-27 17:41:49 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-16 12:38:27 -04:00
										 |  |  | 		async.parallel({ | 
					
						
							|  |  |  | 			ignoredCids: function(next) { | 
					
						
							|  |  |  | 				user.getIgnoredCategories(uid, next); | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			recentTids: function(next) { | 
					
						
							| 
									
										
										
										
											2015-03-24 13:10:10 -04:00
										 |  |  | 				db.getSortedSetRevRangeByScoreWithScores('topics:recent', 0, -1, '+inf', cutoff, next); | 
					
						
							| 
									
										
										
										
											2014-09-27 17:41:49 -04:00
										 |  |  | 			}, | 
					
						
							|  |  |  | 			userScores: function(next) { | 
					
						
							| 
									
										
										
										
											2015-03-24 13:10:10 -04:00
										 |  |  | 				db.getSortedSetRevRangeByScoreWithScores('uid:' + uid + ':tids_read', 0, -1, '+inf', cutoff, next); | 
					
						
							| 
									
										
										
										
											2014-09-16 12:38:27 -04:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		}, function(err, results) { | 
					
						
							| 
									
										
										
										
											2014-08-29 15:57:20 -04:00
										 |  |  | 			if (err) { | 
					
						
							|  |  |  | 				return callback(err); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-03-21 15:40:37 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-16 12:38:27 -04:00
										 |  |  | 			if (results.recentTids && !results.recentTids.length) { | 
					
						
							|  |  |  | 				return callback(null, []); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-08-29 15:57:20 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-27 17:41:49 -04:00
										 |  |  | 			var userRead = {}; | 
					
						
							|  |  |  | 			results.userScores.forEach(function(userItem) { | 
					
						
							|  |  |  | 				userRead[userItem.value] = userItem.score; | 
					
						
							|  |  |  | 			}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			var tids = results.recentTids.filter(function(recentTopic, index) { | 
					
						
							|  |  |  | 				return !userRead[recentTopic.value] || recentTopic.score > userRead[recentTopic.value]; | 
					
						
							|  |  |  | 			}).map(function(topic) { | 
					
						
							|  |  |  | 				return topic.value; | 
					
						
							|  |  |  | 			}); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-14 14:27:45 -04:00
										 |  |  | 			tids = tids.slice(0, 100); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-27 17:41:49 -04:00
										 |  |  | 			filterTopics(uid, tids, results.ignoredCids, function(err, tids) { | 
					
						
							| 
									
										
										
										
											2014-09-16 12:38:27 -04:00
										 |  |  | 				if (err) { | 
					
						
							|  |  |  | 					return callback(err); | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2014-08-29 15:57:20 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-27 17:41:49 -04:00
										 |  |  | 				if (stop === -1) { | 
					
						
							|  |  |  | 					tids = tids.slice(start); | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					tids = tids.slice(start, stop + 1); | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2014-08-29 15:57:20 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-14 19:52:25 -05:00
										 |  |  | 				callback(null, tids); | 
					
						
							| 
									
										
										
										
											2014-03-21 15:40:37 -04:00
										 |  |  | 			}); | 
					
						
							|  |  |  | 		}); | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-16 12:38:27 -04:00
										 |  |  | 	function filterTopics(uid, tids, ignoredCids, callback) { | 
					
						
							|  |  |  | 		if (!Array.isArray(ignoredCids) || !tids.length) { | 
					
						
							| 
									
										
										
										
											2014-08-29 15:57:20 -04:00
										 |  |  | 			return callback(null, tids); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-14 19:52:25 -05:00
										 |  |  | 		async.waterfall([ | 
					
						
							|  |  |  | 			function(next) { | 
					
						
							|  |  |  | 				privileges.topics.filter('read', tids, uid, next); | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			function(tids, next) { | 
					
						
							|  |  |  | 				Topics.getTopicsFields(tids, ['tid', 'cid'], next); | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			function(topics, next) { | 
					
						
							|  |  |  | 				tids = topics.filter(function(topic) { | 
					
						
							|  |  |  | 					return topic && topic.cid && ignoredCids.indexOf(topic.cid.toString()) === -1; | 
					
						
							| 
									
										
										
										
											2014-09-16 12:38:27 -04:00
										 |  |  | 				}).map(function(topic) { | 
					
						
							| 
									
										
										
										
											2014-11-14 19:52:25 -05:00
										 |  |  | 					return topic.tid; | 
					
						
							| 
									
										
										
										
											2014-11-14 17:31:39 -05:00
										 |  |  | 				}); | 
					
						
							| 
									
										
										
										
											2014-11-14 19:52:25 -05:00
										 |  |  | 				next(null, tids); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		], callback); | 
					
						
							| 
									
										
										
										
											2014-08-29 15:57:20 -04:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-03-21 15:40:37 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-16 11:06:10 -04:00
										 |  |  | 	Topics.pushUnreadCount = function(uid, callback) { | 
					
						
							| 
									
										
										
										
											2014-09-16 11:07:59 -04:00
										 |  |  | 		callback = callback || function() {}; | 
					
						
							| 
									
										
										
										
											2014-03-21 15:40:37 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-16 11:06:10 -04:00
										 |  |  | 		if (!uid || parseInt(uid, 10) === 0) { | 
					
						
							|  |  |  | 			return callback(); | 
					
						
							| 
									
										
										
										
											2014-03-21 15:40:37 -04:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-09-16 11:06:10 -04:00
										 |  |  | 		Topics.getTotalUnread(uid, function(err, count) { | 
					
						
							| 
									
										
										
										
											2014-03-21 15:40:37 -04:00
										 |  |  | 			if (err) { | 
					
						
							| 
									
										
										
										
											2014-09-16 11:06:10 -04:00
										 |  |  | 				return callback(err); | 
					
						
							| 
									
										
										
										
											2014-03-21 15:40:37 -04:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-09-16 11:06:10 -04:00
										 |  |  | 			require('../socket.io').in('uid_' + uid).emit('event:unread.updateCount', null, count); | 
					
						
							|  |  |  | 			callback(); | 
					
						
							| 
									
										
										
										
											2014-03-21 15:40:37 -04:00
										 |  |  | 		}); | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Topics.markAsUnreadForAll = function(tid, callback) { | 
					
						
							| 
									
										
										
										
											2014-09-27 17:41:49 -04:00
										 |  |  | 		Topics.markCategoryUnreadForAll(tid, callback); | 
					
						
							| 
									
										
										
										
											2014-03-21 15:40:37 -04:00
										 |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-10 21:44:19 -04:00
										 |  |  | 	Topics.markAsRead = function(tids, uid, callback) { | 
					
						
							|  |  |  | 		callback = callback || function() {}; | 
					
						
							|  |  |  | 		if (!Array.isArray(tids) || !tids.length) { | 
					
						
							| 
									
										
										
										
											2014-03-21 15:40:37 -04:00
										 |  |  | 			return callback(); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-09-10 21:44:19 -04:00
										 |  |  | 		tids = tids.filter(Boolean); | 
					
						
							| 
									
										
										
										
											2015-01-27 10:36:30 -05:00
										 |  |  | 		if (!tids.length) { | 
					
						
							|  |  |  | 			return callback(); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-03-21 15:40:37 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-10 21:44:19 -04:00
										 |  |  | 		async.parallel({ | 
					
						
							| 
									
										
										
										
											2014-10-14 02:39:20 -04:00
										 |  |  | 			topicScores: function(next) { | 
					
						
							|  |  |  | 				db.sortedSetScores('topics:recent', tids, next); | 
					
						
							| 
									
										
										
										
											2014-09-10 21:44:19 -04:00
										 |  |  | 			}, | 
					
						
							| 
									
										
										
										
											2014-10-14 02:39:20 -04:00
										 |  |  | 			userScores: function(next) { | 
					
						
							|  |  |  | 				db.sortedSetScores('uid:' + uid + ':tids_read', tids, next); | 
					
						
							| 
									
										
										
										
											2014-09-10 21:44:19 -04:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		}, function(err, results) { | 
					
						
							| 
									
										
										
										
											2014-03-21 17:48:32 -04:00
										 |  |  | 			if (err) { | 
					
						
							|  |  |  | 				return callback(err); | 
					
						
							| 
									
										
										
										
											2014-03-21 15:40:37 -04:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-14 02:39:20 -04:00
										 |  |  | 			tids = tids.filter(function(tid, index) { | 
					
						
							|  |  |  | 				return !results.userScores[index] || results.userScores[index] < results.topicScores[index]; | 
					
						
							| 
									
										
										
										
											2014-03-21 17:48:32 -04:00
										 |  |  | 			}); | 
					
						
							| 
									
										
										
										
											2014-09-10 21:44:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-14 02:39:20 -04:00
										 |  |  | 			if (!tids.length) { | 
					
						
							|  |  |  | 				return callback(); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-27 10:36:30 -05:00
										 |  |  | 			var now = Date.now(); | 
					
						
							|  |  |  | 			var scores = tids.map(function(tid) { | 
					
						
							|  |  |  | 				return now; | 
					
						
							|  |  |  | 			}); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-14 02:39:20 -04:00
										 |  |  | 			async.parallel({ | 
					
						
							|  |  |  | 				markRead: function(next) { | 
					
						
							|  |  |  | 					db.sortedSetAdd('uid:' + uid + ':tids_read', scores, tids, next); | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 				topicData: function(next) { | 
					
						
							|  |  |  | 					Topics.getTopicsFields(tids, ['cid'], next); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			}, function(err, results) { | 
					
						
							|  |  |  | 				if (err) { | 
					
						
							|  |  |  | 					return callback(err); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				var cids = results.topicData.map(function(topic) { | 
					
						
							|  |  |  | 					return topic && topic.cid; | 
					
						
							|  |  |  | 				}).filter(function(topic, index, array) { | 
					
						
							|  |  |  | 					return topic && array.indexOf(topic) === index; | 
					
						
							|  |  |  | 				}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				categories.markAsRead(cids, uid, callback); | 
					
						
							|  |  |  | 			}); | 
					
						
							| 
									
										
										
										
											2014-03-21 15:40:37 -04:00
										 |  |  | 		}); | 
					
						
							| 
									
										
										
										
											2014-03-21 17:48:32 -04:00
										 |  |  | 	}; | 
					
						
							| 
									
										
										
										
											2014-03-21 15:40:37 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-21 17:48:32 -04:00
										 |  |  | 	Topics.markTopicNotificationsRead = function(tid, uid) { | 
					
						
							| 
									
										
										
										
											2014-09-19 19:45:16 -04:00
										 |  |  | 		if (!tid) { | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-07-28 15:52:33 -04:00
										 |  |  | 		user.notifications.getUnreadByField(uid, 'tid', tid, function(err, nids) { | 
					
						
							| 
									
										
										
										
											2014-09-08 23:03:37 -04:00
										 |  |  | 			if (err) { | 
					
						
							|  |  |  | 				return winston.error(err.stack); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-07-28 15:52:33 -04:00
										 |  |  | 			notifications.markReadMultiple(nids, uid, function() { | 
					
						
							| 
									
										
										
										
											2014-03-21 15:40:37 -04:00
										 |  |  | 				user.notifications.pushCount(uid); | 
					
						
							|  |  |  | 			}); | 
					
						
							|  |  |  | 		}); | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Topics.markCategoryUnreadForAll = function(tid, callback) { | 
					
						
							|  |  |  | 		Topics.getTopicField(tid, 'cid', function(err, cid) { | 
					
						
							|  |  |  | 			if(err) { | 
					
						
							|  |  |  | 				return callback(err); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			categories.markAsUnreadForAll(cid, callback); | 
					
						
							|  |  |  | 		}); | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Topics.hasReadTopics = function(tids, uid, callback) { | 
					
						
							|  |  |  | 		if(!parseInt(uid, 10)) { | 
					
						
							|  |  |  | 			return callback(null, tids.map(function() { | 
					
						
							|  |  |  | 				return false; | 
					
						
							|  |  |  | 			})); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-27 17:41:49 -04:00
										 |  |  | 		async.parallel({ | 
					
						
							|  |  |  | 			recentScores: function(next) { | 
					
						
							|  |  |  | 				db.sortedSetScores('topics:recent', tids, next); | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			userScores: function(next) { | 
					
						
							|  |  |  | 				db.sortedSetScores('uid:' + uid + ':tids_read', tids, next); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}, function(err, results) { | 
					
						
							|  |  |  | 			if (err) { | 
					
						
							|  |  |  | 				return callback(err); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-03-24 13:10:10 -04:00
										 |  |  | 			var cutoff = Date.now() - unreadCutoff; | 
					
						
							| 
									
										
										
										
											2014-09-27 17:41:49 -04:00
										 |  |  | 			var result = tids.map(function(tid, index) { | 
					
						
							| 
									
										
										
										
											2015-03-24 13:10:10 -04:00
										 |  |  | 				return results.recentScores[index] < cutoff || !!(results.userScores[index] && results.userScores[index] >= results.recentScores[index]); | 
					
						
							| 
									
										
										
										
											2014-09-27 17:41:49 -04:00
										 |  |  | 			}); | 
					
						
							| 
									
										
										
										
											2014-03-21 15:40:37 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-27 17:41:49 -04:00
										 |  |  | 			callback(null, result); | 
					
						
							|  |  |  | 		}); | 
					
						
							| 
									
										
										
										
											2014-03-21 15:40:37 -04:00
										 |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Topics.hasReadTopic = function(tid, uid, callback) { | 
					
						
							| 
									
										
										
										
											2014-09-27 17:41:49 -04:00
										 |  |  | 		Topics.hasReadTopics([tid], uid, function(err, hasRead) { | 
					
						
							|  |  |  | 			callback(err, Array.isArray(hasRead) && hasRead.length ? hasRead[0] : false); | 
					
						
							|  |  |  | 		}); | 
					
						
							| 
									
										
										
										
											2014-03-21 15:40:37 -04:00
										 |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-10 20:31:57 +01:00
										 |  |  | }; |