129 lines
4.3 KiB
JavaScript
129 lines
4.3 KiB
JavaScript
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, offerAgg, 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 } } },
|
|
]),
|
|
ExploreInteractionModel.aggregate([
|
|
{
|
|
$match: {
|
|
targetType: 'post',
|
|
targetId: { $in: postIds },
|
|
action: 'offer',
|
|
},
|
|
},
|
|
{ $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 offersMap = Object.fromEntries(
|
|
offerAgg.map((o) => [String(o._id), o.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,
|
|
offersCount: offersMap[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,
|
|
}
|