chat pic
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user