mirror of
				https://github.com/NodeBB/NodeBB.git
				synced 2025-10-31 11:05:54 +01:00 
			
		
		
		
	feat: add tools to recent/unread (#8477)
* feat: add tools to recent/unread * fix: open api spec * fix: more api spec
This commit is contained in:
		
				
					committed by
					
						 GitHub
						GitHub
					
				
			
			
				
	
			
			
			
						parent
						
							14eafcb6b8
						
					
				
				
					commit
					658dd03b03
				
			| @@ -3810,6 +3810,10 @@ paths: | ||||
|                           type: number | ||||
|                       canPost: | ||||
|                         type: boolean | ||||
|                       showSelect: | ||||
|                         type: boolean | ||||
|                       showTopicTools: | ||||
|                         type: boolean | ||||
|                       categories: | ||||
|                         type: array | ||||
|                         items: | ||||
| @@ -3871,6 +3875,8 @@ paths: | ||||
|                               type: boolean | ||||
|                             filter: | ||||
|                               type: string | ||||
|                             icon: | ||||
|                               type: string | ||||
|                       selectedFilter: | ||||
|                         type: object | ||||
|                         properties: | ||||
| @@ -3882,6 +3888,8 @@ paths: | ||||
|                             type: boolean | ||||
|                           filter: | ||||
|                             type: string | ||||
|                           icon: | ||||
|                             type: string | ||||
|                       terms: | ||||
|                         type: array | ||||
|                         items: | ||||
| @@ -3946,6 +3954,8 @@ paths: | ||||
|                     properties: | ||||
|                       showSelect: | ||||
|                         type: boolean | ||||
|                       showTopicTools: | ||||
|                         type: boolean | ||||
|                       nextStart: | ||||
|                         type: number | ||||
|                       topics: | ||||
| @@ -4199,6 +4209,8 @@ paths: | ||||
|                               type: boolean | ||||
|                             filter: | ||||
|                               type: string | ||||
|                             icon: | ||||
|                               type: string | ||||
|                       selectedFilter: | ||||
|                         type: object | ||||
|                         properties: | ||||
| @@ -4210,6 +4222,8 @@ paths: | ||||
|                             type: boolean | ||||
|                           filter: | ||||
|                             type: string | ||||
|                           icon: | ||||
|                             type: string | ||||
|                   - $ref: components/schemas/Pagination.yaml#/Pagination | ||||
|                   - $ref: components/schemas/Breadcrumbs.yaml#/Breadcrumbs | ||||
|                   - $ref: components/schemas/CommonProps.yaml#/CommonProps | ||||
| @@ -5492,6 +5506,10 @@ paths: | ||||
|                           type: number | ||||
|                       canPost: | ||||
|                         type: boolean | ||||
|                       showSelect: | ||||
|                         type: boolean | ||||
|                       showTopicTools: | ||||
|                         type: boolean | ||||
|                       categories: | ||||
|                         type: array | ||||
|                         items: | ||||
| @@ -5553,6 +5571,8 @@ paths: | ||||
|                               type: boolean | ||||
|                             filter: | ||||
|                               type: string | ||||
|                             icon: | ||||
|                               type: string | ||||
|                       selectedFilter: | ||||
|                         type: object | ||||
|                         properties: | ||||
| @@ -5564,6 +5584,8 @@ paths: | ||||
|                             type: boolean | ||||
|                           filter: | ||||
|                             type: string | ||||
|                           icon: | ||||
|                             type: string | ||||
|                       terms: | ||||
|                         type: array | ||||
|                         items: | ||||
| @@ -5620,6 +5642,10 @@ paths: | ||||
|                           type: number | ||||
|                       canPost: | ||||
|                         type: boolean | ||||
|                       showSelect: | ||||
|                         type: boolean | ||||
|                       showTopicTools: | ||||
|                         type: boolean | ||||
|                       categories: | ||||
|                         type: array | ||||
|                         items: | ||||
| @@ -5694,6 +5720,8 @@ paths: | ||||
|                               type: boolean | ||||
|                             filter: | ||||
|                               type: string | ||||
|                             icon: | ||||
|                               type: string | ||||
|                       selectedFilter: | ||||
|                         type: object | ||||
|                         properties: | ||||
| @@ -5705,6 +5733,8 @@ paths: | ||||
|                             type: boolean | ||||
|                           filter: | ||||
|                             type: string | ||||
|                           icon: | ||||
|                             type: string | ||||
|                       terms: | ||||
|                         type: array | ||||
|                         items: | ||||
| @@ -5817,6 +5847,8 @@ paths: | ||||
|                             type: boolean | ||||
|                       showSelect: | ||||
|                         type: boolean | ||||
|                       showTopicTools: | ||||
|                         type: boolean | ||||
|                       rssFeedUrl: | ||||
|                         type: string | ||||
|                       feeds:disableRSS: | ||||
|   | ||||
| @@ -4,25 +4,17 @@ define('forum/category', [ | ||||
| 	'forum/infinitescroll', | ||||
| 	'share', | ||||
| 	'navigator', | ||||
| 	'forum/category/tools', | ||||
| 	'topicList', | ||||
| 	'sort', | ||||
| ], function (infinitescroll, share, navigator, categoryTools, topicList, sort) { | ||||
| ], function (infinitescroll, share, navigator, topicList, sort) { | ||||
| 	var Category = {}; | ||||
|  | ||||
| 	$(window).on('action:ajaxify.start', function (ev, data) { | ||||
| 		if (!String(data.url).startsWith('category/')) { | ||||
| 			navigator.disable(); | ||||
|  | ||||
| 			removeListeners(); | ||||
| 		} | ||||
| 	}); | ||||
|  | ||||
| 	function removeListeners() { | ||||
| 		categoryTools.removeListeners(); | ||||
| 		topicList.removeListeners(); | ||||
| 	} | ||||
|  | ||||
| 	Category.init = function () { | ||||
| 		var	cid = ajaxify.data.cid; | ||||
|  | ||||
| @@ -30,8 +22,6 @@ define('forum/category', [ | ||||
|  | ||||
| 		share.addShareHandlers(ajaxify.data.name); | ||||
|  | ||||
| 		categoryTools.init(cid); | ||||
|  | ||||
| 		topicList.init('category', loadTopicsAfter); | ||||
|  | ||||
| 		sort.handleSort('categoryTopicSort', 'user.setCategorySort', 'category/' + ajaxify.data.slug); | ||||
|   | ||||
| @@ -9,9 +9,7 @@ define('forum/category/tools', [ | ||||
| ], function (topicSelect, components, translator) { | ||||
| 	var CategoryTools = {}; | ||||
|  | ||||
| 	CategoryTools.init = function (cid) { | ||||
| 		CategoryTools.cid = cid; | ||||
|  | ||||
| 	CategoryTools.init = function () { | ||||
| 		topicSelect.init(updateDropdownOptions); | ||||
|  | ||||
| 		handlePinnedTopicSort(); | ||||
| @@ -36,7 +34,7 @@ define('forum/category/tools', [ | ||||
| 			if (!tids.length) { | ||||
| 				return app.alertError('[[error:no-topics-selected]]'); | ||||
| 			} | ||||
| 			socket.emit('topics.lock', { tids: tids, cid: CategoryTools.cid }, onCommandComplete); | ||||
| 			socket.emit('topics.lock', { tids: tids }, onCommandComplete); | ||||
| 			return false; | ||||
| 		}); | ||||
|  | ||||
| @@ -45,7 +43,7 @@ define('forum/category/tools', [ | ||||
| 			if (!tids.length) { | ||||
| 				return app.alertError('[[error:no-topics-selected]]'); | ||||
| 			} | ||||
| 			socket.emit('topics.unlock', { tids: tids, cid: CategoryTools.cid }, onCommandComplete); | ||||
| 			socket.emit('topics.unlock', { tids: tids }, onCommandComplete); | ||||
| 			return false; | ||||
| 		}); | ||||
|  | ||||
| @@ -54,7 +52,7 @@ define('forum/category/tools', [ | ||||
| 			if (!tids.length) { | ||||
| 				return app.alertError('[[error:no-topics-selected]]'); | ||||
| 			} | ||||
| 			socket.emit('topics.pin', { tids: tids, cid: CategoryTools.cid }, onCommandComplete); | ||||
| 			socket.emit('topics.pin', { tids: tids }, onCommandComplete); | ||||
| 			return false; | ||||
| 		}); | ||||
|  | ||||
| @@ -63,7 +61,7 @@ define('forum/category/tools', [ | ||||
| 			if (!tids.length) { | ||||
| 				return app.alertError('[[error:no-topics-selected]]'); | ||||
| 			} | ||||
| 			socket.emit('topics.unpin', { tids: tids, cid: CategoryTools.cid }, onCommandComplete); | ||||
| 			socket.emit('topics.unpin', { tids: tids }, onCommandComplete); | ||||
| 			return false; | ||||
| 		}); | ||||
|  | ||||
| @@ -92,13 +90,17 @@ define('forum/category/tools', [ | ||||
| 				if (!tids.length) { | ||||
| 					return app.alertError('[[error:no-topics-selected]]'); | ||||
| 				} | ||||
| 				move.init(tids, cid, onCommandComplete); | ||||
| 				move.init(tids, null, onCommandComplete); | ||||
| 			}); | ||||
|  | ||||
| 			return false; | ||||
| 		}); | ||||
|  | ||||
| 		components.get('topic/move-all').on('click', function () { | ||||
| 			var cid = ajaxify.data.cid; | ||||
| 			if (!ajaxify.data.template.category) { | ||||
| 				return app.alertError('[[error:invalid-data]]'); | ||||
| 			} | ||||
| 			require(['forum/topic/move'], function (move) { | ||||
| 				move.init(null, cid, function (err) { | ||||
| 					if (err) { | ||||
| @@ -110,7 +112,7 @@ define('forum/category/tools', [ | ||||
| 			}); | ||||
| 		}); | ||||
|  | ||||
| 		$('.category').on('click', '[component="topic/merge"]', function () { | ||||
| 		components.get('topic/merge').on('click', function () { | ||||
| 			require(['forum/topic/merge'], function (merge) { | ||||
| 				merge.init(); | ||||
| 			}); | ||||
| @@ -138,7 +140,7 @@ define('forum/category/tools', [ | ||||
| 					return; | ||||
| 				} | ||||
|  | ||||
| 				socket.emit('topics.' + command, { tids: tids, cid: CategoryTools.cid }, onDeletePurgeComplete); | ||||
| 				socket.emit('topics.' + command, { tids: tids }, onDeletePurgeComplete); | ||||
| 			}); | ||||
| 		}); | ||||
| 	} | ||||
| @@ -259,7 +261,7 @@ define('forum/category/tools', [ | ||||
| 			return memo; | ||||
| 		}, 0); | ||||
|  | ||||
| 		if (!ajaxify.data.privileges.isAdminOrMod || numPinned < 2) { | ||||
| 		if ((!app.user.isAdmin && !app.user.isMod) || numPinned < 2) { | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
|   | ||||
| @@ -5,7 +5,8 @@ define('topicList', [ | ||||
| 	'handleBack', | ||||
| 	'topicSelect', | ||||
| 	'categorySearch', | ||||
| ], function (infinitescroll, handleBack, topicSelect, categorySearch) { | ||||
| 	'forum/category/tools', | ||||
| ], function (infinitescroll, handleBack, topicSelect, categorySearch, categoryTools) { | ||||
| 	var TopicList = {}; | ||||
| 	var templateName = ''; | ||||
|  | ||||
| @@ -24,6 +25,7 @@ define('topicList', [ | ||||
|  | ||||
| 	$(window).on('action:ajaxify.start', function () { | ||||
| 		TopicList.removeListeners(); | ||||
| 		categoryTools.removeListeners(); | ||||
| 	}); | ||||
|  | ||||
| 	TopicList.init = function (template, cb) { | ||||
| @@ -32,6 +34,8 @@ define('topicList', [ | ||||
| 		templateName = template; | ||||
| 		loadTopicsCallback = cb || loadTopicsAfter; | ||||
|  | ||||
| 		categoryTools.init(); | ||||
|  | ||||
| 		TopicList.watchForNewPosts(); | ||||
|  | ||||
| 		TopicList.handleCategorySelection(); | ||||
|   | ||||
| @@ -32,6 +32,9 @@ module.exports = function (Categories) { | ||||
| 			'cid:' + cid + ':tids', | ||||
| 			'cid:' + cid + ':tids:pinned', | ||||
| 			'cid:' + cid + ':tids:posts', | ||||
| 			'cid:' + cid + ':tids:votes', | ||||
| 			'cid:' + cid + ':tids:lastposttime', | ||||
| 			'cid:' + cid + ':recent_tids', | ||||
| 			'cid:' + cid + ':pids', | ||||
| 			'cid:' + cid + ':read_by_uid', | ||||
| 			'cid:' + cid + ':uid:watch:state', | ||||
|   | ||||
| @@ -95,6 +95,7 @@ categoryController.get = async function (req, res, next) { | ||||
| 	categoryData.description = translator.escape(categoryData.description); | ||||
| 	categoryData.privileges = userPrivileges; | ||||
| 	categoryData.showSelect = userPrivileges.editable; | ||||
| 	categoryData.showTopicTools = userPrivileges.editable; | ||||
| 	categoryData.rssFeedUrl = nconf.get('url') + '/category/' + categoryData.cid + '.rss'; | ||||
| 	if (parseInt(req.uid, 10)) { | ||||
| 		categories.markAsRead([cid], req.uid); | ||||
|   | ||||
| @@ -72,21 +72,25 @@ helpers.buildFilters = function (url, filter, query) { | ||||
| 		url: url + helpers.buildQueryString(query.cid, '', query.term), | ||||
| 		selected: filter === '', | ||||
| 		filter: '', | ||||
| 		icon: 'fa-book', | ||||
| 	}, { | ||||
| 		name: '[[unread:new-topics]]', | ||||
| 		url: url + helpers.buildQueryString(query.cid, 'new', query.term), | ||||
| 		selected: filter === 'new', | ||||
| 		filter: 'new', | ||||
| 		icon: 'fa-clock-o', | ||||
| 	}, { | ||||
| 		name: '[[unread:watched-topics]]', | ||||
| 		url: url + helpers.buildQueryString(query.cid, 'watched', query.term), | ||||
| 		selected: filter === 'watched', | ||||
| 		filter: 'watched', | ||||
| 		icon: 'fa-bell-o', | ||||
| 	}, { | ||||
| 		name: '[[unread:unreplied-topics]]', | ||||
| 		url: url + helpers.buildQueryString(query.cid, 'unreplied', query.term), | ||||
| 		selected: filter === 'unreplied', | ||||
| 		filter: 'unreplied', | ||||
| 		icon: 'fa-reply', | ||||
| 	}]; | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -37,11 +37,12 @@ recentController.getData = async function (req, url, sort) { | ||||
| 		states.push(categories.watchStates.ignoring); | ||||
| 	} | ||||
|  | ||||
| 	const [settings, categoryData, rssToken, canPost] = await Promise.all([ | ||||
| 	const [settings, categoryData, rssToken, canPost, isPrivileged] = await Promise.all([ | ||||
| 		user.getSettings(req.uid), | ||||
| 		helpers.getCategoriesByStates(req.uid, cid, states), | ||||
| 		user.auth.getFeedToken(req.uid), | ||||
| 		canPostTopic(req.uid), | ||||
| 		user.isPrivileged(req.uid), | ||||
| 	]); | ||||
|  | ||||
| 	const start = Math.max(0, (page - 1) * settings.topicsPerPage); | ||||
| @@ -60,6 +61,8 @@ recentController.getData = async function (req, url, sort) { | ||||
| 	}); | ||||
|  | ||||
| 	data.canPost = canPost; | ||||
| 	data.showSelect = isPrivileged; | ||||
| 	data.showTopicTools = isPrivileged; | ||||
| 	data.categories = categoryData.categories; | ||||
| 	data.allCategoriesUrl = url + helpers.buildQueryString('', filter, ''); | ||||
| 	data.selectedCategory = categoryData.selectedCategory || null; | ||||
|   | ||||
| @@ -22,9 +22,10 @@ unreadController.get = async function (req, res, next) { | ||||
| 	if (!filterData.filters[filter]) { | ||||
| 		return next(); | ||||
| 	} | ||||
| 	const [watchedCategories, userSettings] = await Promise.all([ | ||||
| 	const [watchedCategories, userSettings, isPrivileged] = await Promise.all([ | ||||
| 		getWatchedCategories(req.uid, cid, filter), | ||||
| 		user.getSettings(req.uid), | ||||
| 		user.isPrivileged(req.uid), | ||||
| 	]); | ||||
|  | ||||
| 	const page = parseInt(req.query.page, 10) || 1; | ||||
| @@ -48,7 +49,8 @@ unreadController.get = async function (req, res, next) { | ||||
| 		req.query.page = Math.max(1, Math.min(data.pageCount, page)); | ||||
| 		return helpers.redirect(res, '/unread?' + querystring.stringify(req.query)); | ||||
| 	} | ||||
|  | ||||
| 	data.showSelect = isPrivileged; | ||||
| 	data.showTopicTools = isPrivileged; | ||||
| 	data.categories = watchedCategories.categories; | ||||
| 	data.allCategoriesUrl = 'unread' + helpers.buildQueryString('', filter, ''); | ||||
| 	data.selectedCategory = watchedCategories.selectedCategory; | ||||
|   | ||||
| @@ -191,9 +191,8 @@ SocketHelpers.rescindUpvoteNotification = async function (pid, fromuid) { | ||||
| 	websockets.in('uid_' + uid).emit('event:notifications.updateCount', count); | ||||
| }; | ||||
|  | ||||
| SocketHelpers.emitToTopicAndCategory = function (event, data) { | ||||
| 	websockets.in('topic_' + data.tid).emit(event, data); | ||||
| 	websockets.in('category_' + data.cid).emit(event, data); | ||||
| SocketHelpers.emitToTopicAndCategory = async function (event, data, uids) { | ||||
| 	uids.forEach(toUid => websockets.in('uid_' + toUid).emit(event, data)); | ||||
| }; | ||||
|  | ||||
| require('../promisify')(SocketHelpers); | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| 'use strict'; | ||||
|  | ||||
| const async = require('async'); | ||||
| const user = require('../../user'); | ||||
| const topics = require('../../topics'); | ||||
| const categories = require('../../categories'); | ||||
| const privileges = require('../../privileges'); | ||||
| @@ -12,6 +13,8 @@ module.exports = function (SocketTopics) { | ||||
| 			throw new Error('[[error:invalid-data]]'); | ||||
| 		} | ||||
|  | ||||
| 		const uids = await user.getUidsFromSet('users:online', 0, -1); | ||||
|  | ||||
| 		await async.eachLimit(data.tids, 10, async function (tid) { | ||||
| 			const canMove = await privileges.topics.isAdminOrMod(tid, socket.uid); | ||||
| 			if (!canMove) { | ||||
| @@ -21,7 +24,8 @@ module.exports = function (SocketTopics) { | ||||
| 			data.uid = socket.uid; | ||||
| 			await topics.tools.move(tid, data); | ||||
|  | ||||
| 			socketHelpers.emitToTopicAndCategory('event:topic_moved', topicData); | ||||
| 			const notifyUids = await privileges.categories.filterUids('topics:read', topicData.cid, uids); | ||||
| 			socketHelpers.emitToTopicAndCategory('event:topic_moved', topicData, notifyUids); | ||||
| 			if (!topicData.deleted) { | ||||
| 				socketHelpers.sendNotificationToTopicOwner(tid, socket.uid, 'move', 'notifications:moved_your_topic'); | ||||
| 			} | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| 'use strict'; | ||||
|  | ||||
| const user = require('../../user'); | ||||
| const topics = require('../../topics'); | ||||
| const events = require('../../events'); | ||||
| const privileges = require('../../privileges'); | ||||
| @@ -65,17 +66,21 @@ module.exports = function (SocketTopics) { | ||||
| 			throw new Error('[[error:no-privileges]]'); | ||||
| 		} | ||||
|  | ||||
| 		if (!data || !Array.isArray(data.tids) || !data.cid) { | ||||
| 		if (!data || !Array.isArray(data.tids)) { | ||||
| 			throw new Error('[[error:invalid-tid]]'); | ||||
| 		} | ||||
|  | ||||
| 		if (typeof topics.tools[action] !== 'function') { | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		const uids = await user.getUidsFromSet('users:online', 0, -1); | ||||
|  | ||||
| 		await Promise.all(data.tids.map(async function (tid) { | ||||
| 			const title = await topics.getTopicField(tid, 'title'); | ||||
| 			const data = await topics.tools[action](tid, socket.uid); | ||||
| 			socketHelpers.emitToTopicAndCategory(event, data); | ||||
| 			const notifyUids = await privileges.categories.filterUids('topics:read', data.cid, uids); | ||||
| 			socketHelpers.emitToTopicAndCategory(event, data, notifyUids); | ||||
| 			await logTopicAction(action, socket, tid, title); | ||||
| 		})); | ||||
| 	}; | ||||
|   | ||||
| @@ -48,7 +48,11 @@ module.exports = function (Topics) { | ||||
| 				'cid:' + topicData.cid + ':tids', | ||||
| 				'cid:' + topicData.cid + ':uid:' + topicData.uid + ':tids', | ||||
| 			], timestamp, topicData.tid), | ||||
| 			db.sortedSetAdd('cid:' + topicData.cid + ':tids:votes', 0, topicData.tid), | ||||
| 			db.sortedSetsAdd([ | ||||
| 				'topics:views', 'topics:posts', 'topics:votes', | ||||
| 				'cid:' + topicData.cid + ':tids:votes', | ||||
| 				'cid:' + topicData.cid + ':tids:posts', | ||||
| 			], 0, topicData.tid), | ||||
| 			categories.updateRecentTid(topicData.cid, topicData.tid), | ||||
| 			user.addTopicIdToUser(topicData.uid, topicData.tid, timestamp), | ||||
| 			db.incrObjectField('category:' + topicData.cid, 'topic_count'), | ||||
|   | ||||
| @@ -18,12 +18,6 @@ module.exports = function (Topics) { | ||||
| 				deleterUid: uid, | ||||
| 				deletedTimestamp: Date.now(), | ||||
| 			}), | ||||
| 			db.sortedSetsRemove([ | ||||
| 				'topics:recent', | ||||
| 				'topics:posts', | ||||
| 				'topics:views', | ||||
| 				'topics:votes', | ||||
| 			], tid), | ||||
| 			removeTopicPidsFromCid(tid), | ||||
| 		]); | ||||
| 	}; | ||||
| @@ -55,16 +49,11 @@ module.exports = function (Topics) { | ||||
| 	} | ||||
|  | ||||
| 	Topics.restore = async function (tid) { | ||||
| 		const topicData = await Topics.getTopicData(tid); | ||||
| 		await Topics.deleteTopicFields(tid, [ | ||||
| 			'deleterUid', 'deletedTimestamp', | ||||
| 		]); | ||||
| 		await Promise.all([ | ||||
| 			Topics.setTopicField(tid, 'deleted', 0), | ||||
| 			Topics.deleteTopicFields(tid, ['deleterUid', 'deletedTimestamp']), | ||||
| 			Topics.updateRecent(tid, topicData.lastposttime), | ||||
| 			db.sortedSetAddBulk([ | ||||
| 				['topics:posts', topicData.postcount, tid], | ||||
| 				['topics:views', topicData.viewcount, tid], | ||||
| 				['topics:votes', parseInt(topicData.votes, 10) || 0, tid], | ||||
| 			]), | ||||
| 			addTopicPidsToCid(tid), | ||||
| 		]); | ||||
| 	}; | ||||
|   | ||||
| @@ -60,9 +60,7 @@ module.exports = function (Topics) { | ||||
|  | ||||
| 		await db.sortedSetAdd('cid:' + topicData.cid + ':tids:lastposttime', lastposttime, tid); | ||||
|  | ||||
| 		if (!topicData.deleted) { | ||||
| 			await Topics.updateRecent(tid, lastposttime); | ||||
| 		} | ||||
| 		await Topics.updateRecent(tid, lastposttime); | ||||
|  | ||||
| 		if (!topicData.pinned) { | ||||
| 			await db.sortedSetAdd('cid:' + topicData.cid + ':tids', lastposttime, tid); | ||||
|   | ||||
							
								
								
									
										49
									
								
								src/upgrades/1.14.1/readd_deleted_recent_topics.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								src/upgrades/1.14.1/readd_deleted_recent_topics.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | ||||
| 'use strict'; | ||||
|  | ||||
| const db = require('../../database'); | ||||
|  | ||||
| const batch = require('../../batch'); | ||||
|  | ||||
| module.exports = { | ||||
| 	name: 'Re add deleted topics to topics:recent', | ||||
| 	timestamp: Date.UTC(2018, 9, 11), | ||||
| 	method: async function () { | ||||
| 		const progress = this.progress; | ||||
|  | ||||
| 		await batch.processSortedSet('topics:tid', async function (tids) { | ||||
| 			progress.incr(tids.length); | ||||
| 			const topicData = await db.getObjectsFields( | ||||
| 				tids.map(tid => 'topic:' + tid), | ||||
| 				['tid', 'lastposttime', 'viewcount', 'postcount', 'upvotes', 'downvotes'] | ||||
| 			); | ||||
| 			topicData.forEach((t) => { | ||||
| 				if (t.hasOwnProperty('upvotes') && t.hasOwnProperty('downvotes')) { | ||||
| 					t.votes = parseInt(t.upvotes, 10) - parseInt(t.downvotes, 10); | ||||
| 				} | ||||
| 			}); | ||||
|  | ||||
| 			await db.sortedSetAdd('topics:recent', | ||||
| 				topicData.map(t => t.lastposttime), | ||||
| 				topicData.map(t => t.tid) | ||||
| 			); | ||||
|  | ||||
| 			await db.sortedSetAdd('topics:views', | ||||
| 				topicData.map(t => t.viewcount || 0), | ||||
| 				topicData.map(t => t.tid) | ||||
| 			); | ||||
|  | ||||
| 			await db.sortedSetAdd('topics:posts', | ||||
| 				topicData.map(t => t.postcount || 0), | ||||
| 				topicData.map(t => t.tid) | ||||
| 			); | ||||
|  | ||||
| 			await db.sortedSetAdd('topics:votes', | ||||
| 				topicData.map(t => t.votes || 0), | ||||
| 				topicData.map(t => t.tid) | ||||
| 			); | ||||
| 		}, { | ||||
| 			progress: progress, | ||||
| 			batchSize: 500, | ||||
| 		}); | ||||
| 	}, | ||||
| }; | ||||
		Reference in New Issue
	
	Block a user