full
This commit is contained in:
@@ -1,11 +1,23 @@
|
||||
const MessageModel = require('../../../models/MessageModel')
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const StoryModel = require('../../../models/StoryModel')
|
||||
const jwt = require('jsonwebtoken')
|
||||
const moment = require('moment-jalaali')
|
||||
const {
|
||||
viewerBlockedUser,
|
||||
userBlockedViewer,
|
||||
} = require('../../../utils/blockVisibility')
|
||||
const { formatChatUserLabel } = require('../../../utils/accountLifecycle')
|
||||
const { formatLastOnlineStatus } = require('../../../utils/onlineStatus')
|
||||
const { getShopChatsForUser } = require('../shop-chat/shopChatController')
|
||||
const { getOrSetCache } = require('../../../utils/cache')
|
||||
const { unreadMessagesCacheKey } = require('../../../utils/unreadMessagesCache')
|
||||
|
||||
// TTLِ کوتاه (نه یه شمارندهی incremental) عمداً — چون خواندهشدن/رسیدنِ پیام از
|
||||
// چندین مسیرِ مختلف اتفاق میافته (index.js، سوکت)، نگهداشتنِ یه شمارندهی دقیق
|
||||
// نیاز به ردیابیِ همهی اون نقاط داره و راحت drift پیدا میکنه؛ یه کشِ کوتاهمدت با
|
||||
// invalidate صریح توی نقاطِ اصلی (پایین) هم سریعه هم امن
|
||||
const UNREAD_COUNT_CACHE_TTL = 20
|
||||
const getMessages = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
@@ -57,25 +69,34 @@ const getMessages = async (req, res, next) => {
|
||||
]
|
||||
}
|
||||
|
||||
// استوری فعال طرفهای گفتگو — برای نمایش حلقهی استوری دور آواتار توی لیست چت
|
||||
const activeStories = await StoryModel.find({
|
||||
user_id: { $in: userIdsArray },
|
||||
expires_at: { $gt: new Date() }
|
||||
})
|
||||
.select('user_id viewers')
|
||||
.lean()
|
||||
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(userId))
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
// پیدا کردن اطلاعات کاربران مرتبط بر اساس فیلتر جستجو و شمارش تعداد پیامهای خوانده نشده برای هر کاربر
|
||||
const usersData = await UserModel.find(userFilter)
|
||||
const usersWithUnreadCount = await Promise.all(usersData.map(async (user) => {
|
||||
const unreadMessagesCount = await MessageModel.countDocuments({ receiverId: userId, senderId: user._id, readStatus: 0 })
|
||||
|
||||
let lastOnlineStatus
|
||||
const now = moment()
|
||||
const lastOnline = moment(user.last_online)
|
||||
const diffMinutes = now.diff(lastOnline, 'minutes')
|
||||
|
||||
if (diffMinutes < 1) {
|
||||
lastOnlineStatus = 'آنلاین'
|
||||
} else if (diffMinutes < 60) {
|
||||
lastOnlineStatus = `${diffMinutes} دقیقه پیش`
|
||||
} else if (diffMinutes < 1440) {
|
||||
lastOnlineStatus = `${Math.floor(diffMinutes / 60)} ساعت پیش`
|
||||
} else {
|
||||
lastOnlineStatus = `${Math.floor(diffMinutes / 1440)} روز پیش`
|
||||
}
|
||||
let lastOnlineStatus = formatLastOnlineStatus(user.last_online, user.ghost_mode)
|
||||
|
||||
// بررسی آیا کاربر فعلی در لیست بلاکشدههای این کاربر است یا خیر
|
||||
const blockedByCurrentUser = viewerBlockedUser(user, userId)
|
||||
@@ -85,9 +106,14 @@ const getMessages = async (req, res, next) => {
|
||||
first_name: user.first_name,
|
||||
last_name: user.last_name,
|
||||
user_name: user.user_name,
|
||||
display_name: formatChatUserLabel(user),
|
||||
account_deactivated: user.account_status === 'deactivated',
|
||||
is_verified: user.is_verified,
|
||||
verify_badge: user.verify_badge,
|
||||
profile_image: user.profile_image,
|
||||
last_online: lastOnlineStatus,
|
||||
has_story: hasStorySet.has(String(user._id)),
|
||||
has_unviewed_story: unviewedStorySet.has(String(user._id)),
|
||||
_id: user._id,
|
||||
unread_messages_count: unreadMessagesCount,
|
||||
is_blocked: blockedByCurrentUser,
|
||||
@@ -96,10 +122,21 @@ const getMessages = async (req, res, next) => {
|
||||
}
|
||||
}))
|
||||
|
||||
// حذف کاربر فعلی از آرایه و سورت کردن کاربران براساس آخرین پیام
|
||||
const filteredUsersData = usersWithUnreadCount
|
||||
// حذف کاربر فعلی از آرایه
|
||||
const directChats = usersWithUnreadCount
|
||||
.filter(user => user._id.toString() !== userId)
|
||||
.sort((a, b) => new Date(b.last_message_date) - new Date(a.last_message_date))
|
||||
.map(user => ({ ...user, chat_type: 'user' }))
|
||||
|
||||
// ادغام گفتگوهای فروشگاهی (ساختار کاملاً جدا، رمزنگارینشده) در همان لیست پیامها
|
||||
let shopChats = await getShopChatsForUser(userId)
|
||||
if (search) {
|
||||
const regex = new RegExp(search, 'i')
|
||||
shopChats = shopChats.filter(chat => regex.test(chat.display_name || ''))
|
||||
}
|
||||
|
||||
const filteredUsersData = [...directChats, ...shopChats].sort(
|
||||
(a, b) => new Date(b.last_message_date) - new Date(a.last_message_date)
|
||||
)
|
||||
|
||||
res.status(200).json({
|
||||
filteredUsersData,
|
||||
@@ -119,7 +156,11 @@ const getUnreadMessages = async (req, res, next) => {
|
||||
const userId = decodedToken.id
|
||||
|
||||
// پیدا کردن تمام پیامهای کاربر که هنوز خوانده نشدهاند
|
||||
const unreadMessagesCount = await MessageModel.countDocuments({ receiverId: userId, readStatus: 0 })
|
||||
const unreadMessagesCount = await getOrSetCache(
|
||||
unreadMessagesCacheKey(userId),
|
||||
UNREAD_COUNT_CACHE_TTL,
|
||||
() => MessageModel.countDocuments({ receiverId: userId, readStatus: 0 })
|
||||
)
|
||||
|
||||
res.status(200).json({ unread_messages_count: unreadMessagesCount })
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user