full
This commit is contained in:
114
utils/postEngagement.js
Normal file
114
utils/postEngagement.js
Normal file
@@ -0,0 +1,114 @@
|
||||
const PostBookmarkModel = require('../models/PostBookmarkModel')
|
||||
const PostSendModel = require('../models/PostSendModel')
|
||||
const PostShareModel = require('../models/PostShareModel')
|
||||
const UserFollowModel = require('../models/UserFollowModel')
|
||||
const ExploreInteractionModel = require('../models/ExploreInteractionModel')
|
||||
const UserModel = require('../models/UserModel')
|
||||
const StoryModel = require('../models/StoryModel')
|
||||
|
||||
async function attachPostEngagementFields(posts, viewerId) {
|
||||
if (!posts?.length) return posts
|
||||
|
||||
const postIds = posts.map((p) => p._id)
|
||||
const authorIds = [...new Set(posts.map((p) => String(p.user_id)))]
|
||||
|
||||
const [bookmarkAgg, sendAgg, shareAgg, viewAgg, authorDocs, userBookmarks, userFollows, activeStories] = await Promise.all([
|
||||
PostBookmarkModel.aggregate([
|
||||
{ $match: { postId: { $in: postIds } } },
|
||||
{ $group: { _id: '$postId', count: { $sum: 1 } } },
|
||||
]),
|
||||
PostSendModel.aggregate([
|
||||
{ $match: { postId: { $in: postIds } } },
|
||||
{ $group: { _id: '$postId', count: { $sum: 1 } } },
|
||||
]),
|
||||
PostShareModel.aggregate([
|
||||
{ $match: { postId: { $in: postIds } } },
|
||||
{ $group: { _id: '$postId', count: { $sum: 1 } } },
|
||||
]),
|
||||
ExploreInteractionModel.aggregate([
|
||||
{
|
||||
$match: {
|
||||
targetType: 'post',
|
||||
targetId: { $in: postIds },
|
||||
action: 'view',
|
||||
},
|
||||
},
|
||||
{ $group: { _id: '$targetId', count: { $sum: 1 } } },
|
||||
]),
|
||||
UserModel.find({ _id: { $in: authorIds } })
|
||||
.select('_id allow_save_posts')
|
||||
.lean(),
|
||||
viewerId
|
||||
? PostBookmarkModel.find({ userId: viewerId, postId: { $in: postIds } })
|
||||
.select('postId')
|
||||
.lean()
|
||||
: [],
|
||||
viewerId
|
||||
? UserFollowModel.find({
|
||||
followerId: viewerId,
|
||||
followingId: { $in: authorIds },
|
||||
})
|
||||
.select('followingId')
|
||||
.lean()
|
||||
: [],
|
||||
StoryModel.find({ user_id: { $in: authorIds }, expires_at: { $gt: new Date() } })
|
||||
.select('user_id viewers')
|
||||
.lean(),
|
||||
])
|
||||
|
||||
const savesMap = Object.fromEntries(
|
||||
bookmarkAgg.map((b) => [String(b._id), b.count])
|
||||
)
|
||||
const sendsMap = Object.fromEntries(
|
||||
sendAgg.map((s) => [String(s._id), s.count])
|
||||
)
|
||||
const sharesMap = Object.fromEntries(
|
||||
shareAgg.map((s) => [String(s._id), s.count])
|
||||
)
|
||||
const viewsMap = Object.fromEntries(
|
||||
viewAgg.map((v) => [String(v._id), v.count])
|
||||
)
|
||||
const allowSaveMap = Object.fromEntries(
|
||||
authorDocs.map((u) => [String(u._id), u.allow_save_posts !== false])
|
||||
)
|
||||
const savedSet = new Set(userBookmarks.map((b) => String(b.postId)))
|
||||
const followSet = new Set(userFollows.map((f) => String(f.followingId)))
|
||||
|
||||
const storiesByAuthor = {}
|
||||
activeStories.forEach((s) => {
|
||||
const key = String(s.user_id)
|
||||
if (!storiesByAuthor[key]) storiesByAuthor[key] = []
|
||||
storiesByAuthor[key].push(s)
|
||||
})
|
||||
const hasStorySet = new Set(Object.keys(storiesByAuthor))
|
||||
const unviewedStorySet = new Set(
|
||||
Object.keys(storiesByAuthor).filter((authorId) =>
|
||||
storiesByAuthor[authorId].some(
|
||||
(s) => !s.viewers?.some((v) => String(v.user_id) === String(viewerId))
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
return posts.map((post) => ({
|
||||
...post,
|
||||
savesCount: savesMap[String(post._id)] || 0,
|
||||
sendsCount: sendsMap[String(post._id)] || 0,
|
||||
sharesCount: sharesMap[String(post._id)] || 0,
|
||||
viewsCount: viewsMap[String(post._id)] || 0,
|
||||
author_allow_save: allowSaveMap[String(post.user_id)] !== false,
|
||||
is_saved: savedSet.has(String(post._id)),
|
||||
is_following: followSet.has(String(post.user_id)),
|
||||
has_story: hasStorySet.has(String(post.user_id)),
|
||||
has_unviewed_story: viewerId ? unviewedStorySet.has(String(post.user_id)) : hasStorySet.has(String(post.user_id)),
|
||||
}))
|
||||
}
|
||||
|
||||
async function attachSinglePostEngagement(post, viewerId) {
|
||||
const [enriched] = await attachPostEngagementFields([post], viewerId)
|
||||
return enriched
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
attachPostEngagementFields,
|
||||
attachSinglePostEngagement,
|
||||
}
|
||||
Reference in New Issue
Block a user