mirror of
				https://github.com/NodeBB/NodeBB.git
				synced 2025-10-30 18:46:01 +01:00 
			
		
		
		
	feat(topic-events): support for uids in topic event payloads
This commit is contained in:
		| @@ -115,6 +115,8 @@ | |||||||
| 	"guest": "Guest", | 	"guest": "Guest", | ||||||
| 	"guests": "Guests", | 	"guests": "Guests", | ||||||
| 	"former_user": "A Former User", | 	"former_user": "A Former User", | ||||||
|  | 	"system-user": "System", | ||||||
|  | 	"unknown-user": "Unknown user", | ||||||
|  |  | ||||||
| 	"updated.title": "Forum Updated", | 	"updated.title": "Forum Updated", | ||||||
| 	"updated.message": "This forum has just been updated to the latest version. Click here to refresh the page.", | 	"updated.message": "This forum has just been updated to the latest version. Click here to refresh the page.", | ||||||
|   | |||||||
| @@ -22,10 +22,8 @@ | |||||||
| 	"login-to-view": "🔒 Log in to view", | 	"login-to-view": "🔒 Log in to view", | ||||||
| 	"edit": "Edit", | 	"edit": "Edit", | ||||||
| 	"delete": "Delete", | 	"delete": "Delete", | ||||||
| 	"deleted": "Deleted", |  | ||||||
| 	"purge": "Purge", | 	"purge": "Purge", | ||||||
| 	"restore": "Restore", | 	"restore": "Restore", | ||||||
| 	"restored": "Restored", |  | ||||||
| 	"move": "Move", | 	"move": "Move", | ||||||
| 	"change-owner": "Change Owner", | 	"change-owner": "Change Owner", | ||||||
| 	"fork": "Fork", | 	"fork": "Fork", | ||||||
| @@ -33,16 +31,21 @@ | |||||||
| 	"share": "Share", | 	"share": "Share", | ||||||
| 	"tools": "Tools", | 	"tools": "Tools", | ||||||
| 	"locked": "Locked", | 	"locked": "Locked", | ||||||
| 	"unlocked": "Unlocked", |  | ||||||
| 	"pinned": "Pinned", | 	"pinned": "Pinned", | ||||||
| 	"pinned-with-expiry": "Pinned until %1", | 	"pinned-with-expiry": "Pinned until %1", | ||||||
| 	"unpinned": "Unpinned", |  | ||||||
| 	"moved": "Moved", | 	"moved": "Moved", | ||||||
| 	"moved-from": "Moved from %1", | 	"moved-from": "Moved from %1", | ||||||
| 	"copy-ip": "Copy IP", | 	"copy-ip": "Copy IP", | ||||||
| 	"ban-ip": "Ban IP", | 	"ban-ip": "Ban IP", | ||||||
| 	"view-history": "Edit History", | 	"view-history": "Edit History", | ||||||
|  |  | ||||||
|  | 	"locked-by": "Locked by", | ||||||
|  | 	"unlocked-by": "Unlocked by", | ||||||
|  | 	"pinned-by": "Pinned by", | ||||||
|  | 	"unpinned-by": "Unpinned by", | ||||||
|  | 	"deleted-by": "Deleted by", | ||||||
|  | 	"restored-by": "Restored by", | ||||||
|  |  | ||||||
| 	"bookmark_instructions" : "Click here to return to the last read post in this thread.", | 	"bookmark_instructions" : "Click here to return to the last read post in this thread.", | ||||||
|  |  | ||||||
| 	"flag-post": "Flag this post", | 	"flag-post": "Flag this post", | ||||||
|   | |||||||
| @@ -1,38 +1,44 @@ | |||||||
| 'use strict'; | 'use strict'; | ||||||
|  |  | ||||||
| const db = require('../database'); | const db = require('../database'); | ||||||
|  | const user = require('../user'); | ||||||
| const plugins = require('../plugins'); | const plugins = require('../plugins'); | ||||||
|  |  | ||||||
| const Events = module.exports; | const Events = module.exports; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Note: Plugins! | ||||||
|  |  * | ||||||
|  |  * You are able to define additional topic event types here. | ||||||
|  |  * Register to hook `filter:topicEvents.init` and append your custom type to the `types` object. | ||||||
|  |  * You can then log a custom topic event by calling `topics.events.log(tid, { type, uid });` | ||||||
|  |  * `uid` is optional; if you pass in a valid uid in the payload, the user avatar/username will be rendered as part of the event text | ||||||
|  |  * | ||||||
|  |  */ | ||||||
| Events._types = { | Events._types = { | ||||||
| 	pin: { | 	pin: { | ||||||
| 		icon: 'fa-thumb-tack', | 		icon: 'fa-thumb-tack', | ||||||
| 		text: '[[topic:pinned]]', | 		text: '[[topic:pinned-by]]', | ||||||
| 	}, |  | ||||||
| 	pin_expiry: { |  | ||||||
| 		icon: 'fa-thumb-tack', |  | ||||||
| 		text: '[[topic:pinned-with-expiry]]', |  | ||||||
| 	}, | 	}, | ||||||
| 	unpin: { | 	unpin: { | ||||||
| 		icon: 'fa-thumb-tack', | 		icon: 'fa-thumb-tack', | ||||||
| 		text: '[[topic:unpinned]]', | 		text: '[[topic:unpinned-by]]', | ||||||
| 	}, | 	}, | ||||||
| 	lock: { | 	lock: { | ||||||
| 		icon: 'fa-lock', | 		icon: 'fa-lock', | ||||||
| 		text: '[[topic:locked]]', | 		text: '[[topic:locked-by]]', | ||||||
| 	}, | 	}, | ||||||
| 	unlock: { | 	unlock: { | ||||||
| 		icon: 'fa-unlock', | 		icon: 'fa-unlock', | ||||||
| 		text: '[[topic:unlocked]]', | 		text: '[[topic:unlocked-by]]', | ||||||
| 	}, | 	}, | ||||||
| 	delete: { | 	delete: { | ||||||
| 		icon: 'fa-trash', | 		icon: 'fa-trash', | ||||||
| 		text: '[[topic:deleted]]', | 		text: '[[topic:deleted-by]]', | ||||||
| 	}, | 	}, | ||||||
| 	restore: { | 	restore: { | ||||||
| 		icon: 'fa-trash-o', | 		icon: 'fa-trash-o', | ||||||
| 		text: '[[topic:restored]]', | 		text: '[[topic:restored-by]]', | ||||||
| 	}, | 	}, | ||||||
| }; | }; | ||||||
| Events._ready = false; | Events._ready = false; | ||||||
| @@ -57,11 +63,20 @@ Events.get = async (tid) => { | |||||||
| 	const eventIds = await db.getSortedSetRangeWithScores(`topic:${tid}:events`, 0, -1); | 	const eventIds = await db.getSortedSetRangeWithScores(`topic:${tid}:events`, 0, -1); | ||||||
| 	const keys = eventIds.map(obj => `topicEvent:${obj.value}`); | 	const keys = eventIds.map(obj => `topicEvent:${obj.value}`); | ||||||
| 	const timestamps = eventIds.map(obj => obj.score); | 	const timestamps = eventIds.map(obj => obj.score); | ||||||
| 	const events = await db.getObjects(keys); | 	let events = await db.getObjects(keys); | ||||||
|  | 	const users = await getUserInfo(events.map(event => event.uid).filter(Boolean)); | ||||||
|  |  | ||||||
|  | 	// Remove events whose types no longer exist (e.g. plugin uninstalled) | ||||||
|  | 	events = events.filter(event => Events._types.hasOwnProperty(event.type)); | ||||||
|  |  | ||||||
|  | 	// Add user & metadata | ||||||
| 	events.forEach((event, idx) => { | 	events.forEach((event, idx) => { | ||||||
| 		event.id = parseInt(eventIds[idx].value, 10); | 		event.id = parseInt(eventIds[idx].value, 10); | ||||||
| 		event.timestamp = timestamps[idx]; | 		event.timestamp = timestamps[idx]; | ||||||
| 		event.timestampISO = new Date(timestamps[idx]).toISOString(); | 		event.timestampISO = new Date(timestamps[idx]).toISOString(); | ||||||
|  | 		if (event.hasOwnProperty('uid')) { | ||||||
|  | 			event.user = users.get(event.uid === 'system' ? 'system' : parseInt(event.uid, 10)); | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		Object.assign(event, Events._types[event.type]); | 		Object.assign(event, Events._types[event.type]); | ||||||
| 	}); | 	}); | ||||||
| @@ -69,6 +84,17 @@ Events.get = async (tid) => { | |||||||
| 	return events; | 	return events; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | async function getUserInfo(uids) { | ||||||
|  | 	uids = uids.filter((uid, idx) => !isNaN(parseInt(uid, 10)) && uids.indexOf(uid) === idx); | ||||||
|  | 	const userData = await user.getUsersFields(uids, ['picture', 'username', 'userslug']); | ||||||
|  | 	const userMap = userData.reduce((memo, cur) => memo.set(cur.uid, cur), new Map()); | ||||||
|  | 	userMap.set('system', { | ||||||
|  | 		system: true, | ||||||
|  | 	}); | ||||||
|  |  | ||||||
|  | 	return userMap; | ||||||
|  | } | ||||||
|  |  | ||||||
| Events.log = async (tid, payload) => { | Events.log = async (tid, payload) => { | ||||||
| 	await Events.init(); | 	await Events.init(); | ||||||
| 	const topics = require('.'); | 	const topics = require('.'); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user