mirror of
				https://github.com/NodeBB/NodeBB.git
				synced 2025-10-30 18:46:01 +01:00 
			
		
		
		
	feat: expose uploaded thumbnails to client-side via API
+ plugin hook: filter:topics.getThumbs
This commit is contained in:
		| @@ -75,12 +75,13 @@ Topics.getTopicsByTids = async function (tids, options) { | |||||||
| 			return postData.map(p => p.handle); | 			return postData.map(p => p.handle); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		const [teasers, users, userSettings, categoriesData, guestHandles] = await Promise.all([ | 		const [teasers, users, userSettings, categoriesData, guestHandles, thumbs] = await Promise.all([ | ||||||
| 			Topics.getTeasers(topics, options), | 			Topics.getTeasers(topics, options), | ||||||
| 			user.getUsersFields(uids, ['uid', 'username', 'fullname', 'userslug', 'reputation', 'postcount', 'picture', 'signature', 'banned', 'status']), | 			user.getUsersFields(uids, ['uid', 'username', 'fullname', 'userslug', 'reputation', 'postcount', 'picture', 'signature', 'banned', 'status']), | ||||||
| 			user.getMultipleUserSettings(uids), | 			user.getMultipleUserSettings(uids), | ||||||
| 			categories.getCategoriesFields(cids, ['cid', 'name', 'slug', 'icon', 'backgroundImage', 'imageClass', 'bgColor', 'color', 'disabled']), | 			categories.getCategoriesFields(cids, ['cid', 'name', 'slug', 'icon', 'backgroundImage', 'imageClass', 'bgColor', 'color', 'disabled']), | ||||||
| 			loadGuestHandles(), | 			loadGuestHandles(), | ||||||
|  | 			Topics.thumbs.get(tids), | ||||||
| 		]); | 		]); | ||||||
|  |  | ||||||
| 		users.forEach((userObj, idx) => { | 		users.forEach((userObj, idx) => { | ||||||
| @@ -96,6 +97,7 @@ Topics.getTopicsByTids = async function (tids, options) { | |||||||
| 			usersMap: _.zipObject(uids, users), | 			usersMap: _.zipObject(uids, users), | ||||||
| 			categoriesMap: _.zipObject(cids, categoriesData), | 			categoriesMap: _.zipObject(cids, categoriesData), | ||||||
| 			tidToGuestHandle: _.zipObject(guestTopics.map(t => t.tid), guestHandles), | 			tidToGuestHandle: _.zipObject(guestTopics.map(t => t.tid), guestHandles), | ||||||
|  | 			thumbs, | ||||||
| 		}; | 		}; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -111,6 +113,7 @@ Topics.getTopicsByTids = async function (tids, options) { | |||||||
| 	const sortOldToNew = callerSettings.topicPostSort === 'newest_to_oldest'; | 	const sortOldToNew = callerSettings.topicPostSort === 'newest_to_oldest'; | ||||||
| 	result.topics.forEach(function (topic, i) { | 	result.topics.forEach(function (topic, i) { | ||||||
| 		if (topic) { | 		if (topic) { | ||||||
|  | 			topic.thumbs = result.thumbs[i]; | ||||||
| 			topic.category = result.categoriesMap[topic.cid]; | 			topic.category = result.categoriesMap[topic.cid]; | ||||||
| 			topic.user = topic.uid ? result.usersMap[topic.uid] : { ...result.usersMap[topic.uid] }; | 			topic.user = topic.uid ? result.usersMap[topic.uid] : { ...result.usersMap[topic.uid] }; | ||||||
| 			if (result.tidToGuestHandle[topic.tid]) { | 			if (result.tidToGuestHandle[topic.tid]) { | ||||||
| @@ -150,6 +153,7 @@ Topics.getTopicWithPosts = async function (topicData, set, uid, start, stop, rev | |||||||
| 		deleter, | 		deleter, | ||||||
| 		merger, | 		merger, | ||||||
| 		related, | 		related, | ||||||
|  | 		thumbs, | ||||||
| 	] = await Promise.all([ | 	] = await Promise.all([ | ||||||
| 		getMainPostAndReplies(topicData, set, uid, start, stop, reverse), | 		getMainPostAndReplies(topicData, set, uid, start, stop, reverse), | ||||||
| 		categories.getCategoryData(topicData.cid), | 		categories.getCategoryData(topicData.cid), | ||||||
| @@ -161,8 +165,20 @@ Topics.getTopicWithPosts = async function (topicData, set, uid, start, stop, rev | |||||||
| 		getDeleter(topicData), | 		getDeleter(topicData), | ||||||
| 		getMerger(topicData), | 		getMerger(topicData), | ||||||
| 		getRelated(topicData, uid), | 		getRelated(topicData, uid), | ||||||
|  | 		Topics.thumbs.get(topicData.tid), | ||||||
| 	]); | 	]); | ||||||
|  |  | ||||||
|  | 	topicData.thumbs = thumbs; | ||||||
|  | 	// Note: Backwards compatibility with old thumb logic, remove in v1.16.0 | ||||||
|  | 	if (topicData.thumb && !topicData.thumbs.length) { | ||||||
|  | 		topicData.thumbs = [{ | ||||||
|  | 			url: topicData.thumb, | ||||||
|  | 		}]; | ||||||
|  | 	} else if (topicData.thumbs.length) { | ||||||
|  | 		topicData.thumb = topicData.thumbs[0].url; | ||||||
|  | 	} | ||||||
|  | 	// end | ||||||
|  |  | ||||||
| 	topicData.posts = posts; | 	topicData.posts = posts; | ||||||
| 	topicData.category = category; | 	topicData.category = category; | ||||||
| 	topicData.tagWhitelist = tagWhitelist[0]; | 	topicData.tagWhitelist = tagWhitelist[0]; | ||||||
|   | |||||||
| @@ -30,9 +30,22 @@ Thumbs.exists = async function (tid, path) { | |||||||
| 	return db.isSortedSetMember(`topic:${tid}:thumbs`, path); | 	return db.isSortedSetMember(`topic:${tid}:thumbs`, path); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| Thumbs.get = async function (tid) { | Thumbs.get = async function (tids) { | ||||||
| 	const thumbs = await db.getSortedSetRange(`topic:${tid}:thumbs`, 0, -1); | 	// Allow singular or plural usage | ||||||
| 	return thumbs.map(thumb => path.join(nconf.get('upload_path'), thumb)); | 	let singular = false; | ||||||
|  | 	if (!Array.isArray(tids)) { | ||||||
|  | 		tids = [tids]; | ||||||
|  | 		singular = true; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	const sets = tids.map(tid => `topic:${tid}:thumbs`); | ||||||
|  | 	const thumbs = await db.getSortedSetsMembers(sets); | ||||||
|  | 	let response = thumbs.map(thumbSet => thumbSet.map(thumb => ({ | ||||||
|  | 		url: path.join(nconf.get('upload_url'), thumb), | ||||||
|  | 	}))); | ||||||
|  |  | ||||||
|  | 	({ thumbs: response } = await plugins.hooks.fire('filter:topics.getThumbs', { tids, thumbs: response })); | ||||||
|  | 	return singular ? response.pop() : response; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| Thumbs.associate = async function (id, path, isDraft) { | Thumbs.associate = async function (id, path, isDraft) { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user