This commit is contained in:
payacom
2026-07-11 20:52:56 +03:30
parent 3c90976f23
commit 54971578b0
6 changed files with 103 additions and 10 deletions

View File

@@ -21,6 +21,29 @@ function storyMediaUrl (storagePath) {
return normalized.replace('/root/modstagram-back/storage', '/storage')
}
function clamp01 (value, fallback) {
const num = Number(value)
if (Number.isNaN(num)) return fallback
return Math.min(1, Math.max(0, num))
}
function sanitizeOverlays (raw) {
if (!Array.isArray(raw)) return []
return raw
.filter((o) => o && typeof o.text === 'string' && o.text.trim().length)
.slice(0, 20)
.map((o) => ({
text: String(o.text).slice(0, 300),
x: clamp01(o.x, 0.5),
y: clamp01(o.y, 0.5),
font_size: clamp01(o.font_size, 0.06) || 0.06,
color: typeof o.color === 'string' ? o.color.slice(0, 32) : '#ffffff',
background: typeof o.background === 'string' ? o.background.slice(0, 32) : '',
rotation: Number.isFinite(Number(o.rotation)) ? Number(o.rotation) : 0,
align: ['left', 'center', 'right'].includes(o.align) ? o.align : 'center'
}))
}
async function resolveViewerId (req) {
const token = req.header('Authorization')?.split(' ')[1]
if (!token) return null
@@ -35,7 +58,7 @@ async function resolveViewerId (req) {
const createStoryBase64 = async (req, res) => {
try {
const userId = req.user._id
const { file } = req.body
const { file, overlays } = req.body
if (!file?.data || !file?.type) {
return res.status(400).json({ error: true, message: 'فایل استوری الزامی است' })
@@ -52,6 +75,7 @@ const createStoryBase64 = async (req, res) => {
user_id: userId,
media_path: filePath,
media_type: mediaType,
overlays: sanitizeOverlays(overlays),
expires_at: new Date(Date.now() + STORY_TTL_MS),
viewers: []
})
@@ -96,6 +120,7 @@ const getStoriesFeed = async (req, res, next) => {
_id: story._id,
media_path: storyMediaUrl(story.media_path),
media_type: story.media_type,
overlays: story.overlays || [],
createdAt: story.createdAt,
expires_at: story.expires_at,
viewed: viewerId
@@ -174,6 +199,30 @@ const markStoryViewed = async (req, res) => {
}
}
const updateStory = async (req, res) => {
try {
const userId = req.user._id
const { storyId } = req.params
const { overlays } = req.body
const story = await StoryModel.findOne({ _id: storyId, user_id: userId })
if (!story || story.expires_at <= new Date()) {
return res.status(404).json({ message: 'استوری یافت نشد' })
}
story.overlays = sanitizeOverlays(overlays)
await story.save()
return res.status(200).json({
message: 'استوری ویرایش شد',
overlays: story.overlays
})
} catch (err) {
console.error('updateStory:', err)
return res.status(500).json({ message: 'خطا در ویرایش استوری' })
}
}
const deleteStory = async (req, res) => {
try {
const userId = req.user._id
@@ -193,5 +242,6 @@ module.exports = {
createStoryBase64,
getStoriesFeed,
markStoryViewed,
updateStory,
deleteStory
}

View File

@@ -970,10 +970,13 @@ const getPostsWeb = async (req, res, next) => {
lng,
feedMode,
seedPostId,
sort,
} = req.query;
const reelsMode = feedMode === "reels" || type === "video";
const gridMode = feedMode === "grid";
// فید اصلی صفحه پست‌ها: فقط جدیدترین‌ها (بدون شخصی‌سازی)
const latestMode = sort === "latest" && !reelsMode;
const postFilter = { status: { $ne: null } };
if (type === 'video' || type === 'image') {
@@ -1090,6 +1093,24 @@ const getPostsWeb = async (req, res, next) => {
explorePosts = await mapPostsWithUsers(explorePosts, usersMap, decodedToken);
// فید اصلی: فقط جدیدترین‌ها بر اساس تاریخ ساخت
if (latestMode) {
explorePosts.sort(
(a, b) => new Date(b.createdAt) - new Date(a.createdAt)
);
const totalItems = explorePosts.length;
const startIndex = (parseInt(page, 10) - 1) * parseInt(limit, 10);
const paginatedPosts = explorePosts.slice(
startIndex,
startIndex + parseInt(limit, 10)
);
return res.status(200).json({
posts: paginatedPosts,
totalPages: Math.ceil(totalItems / limit) || 1,
totalItems,
});
}
const { posts: paginatedPosts, totalItems } = await paginatePersonalizedExplore({
posts: explorePosts,
usersById,