fix: resolve MongoDB connection and port configuration issues

- Added dotenv configuration for environment variables
- Fixed MongoDB connection string loading
- Configured server port to 3005
- Updated cron jobs for expired messages
This commit is contained in:
root
2026-07-11 14:06:46 +03:30
parent 51eb7d0224
commit c62e4c0577
175 changed files with 23463 additions and 21573 deletions

View File

@@ -1,72 +1,72 @@
/* eslint-disable camelcase */
const PostModel = require('../../../models/PostModel');
const jwt = require('jsonwebtoken');
const UserModel = require('../../../models/UserModel');
const LikeModel = require('../../../models/LikeModel');
const { createLikeNotification } = require('../../../utils/likeNotification');
const toggleLike = async (req, res, next) => {
try {
const { postId } = req.body;
const token = req.header('Authorization')?.split(' ')[1];
if (!token) {
return res.status(401).json({ message: 'توکن ارائه نشده است' });
}
let userId;
try {
const decodedToken = jwt.verify(token, process.env.APP_SECRET);
userId = decodedToken.id;
} catch (err) {
return res.status(401).json({ message: 'توکن نامعتبر است' });
}
if (!postId) {
return res.status(400).json({ message: 'شناسه پست الزامی است' });
}
const post = await PostModel.findById(postId);
if (!post) {
return res.status(404).json({ message: 'پست مورد نظر یافت نشد' });
}
const isLiked = post.likes.includes(userId);
if (isLiked) {
// unlike
post.likes.pull(userId);
await post.save();
await LikeModel.findOneAndDelete({ postId, userId });
return res.status(200).json({
message: 'لایک با موفقیت حذف شد',
is_liked: false,
likesCount: post.likes.length,
});
} else {
// like
post.likes.push(userId);
await post.save();
await LikeModel.create({ postId, userId });
await createLikeNotification({
ownerId: post.user_id,
likerId: userId,
entityId: post._id,
type: 'post_like'
});
return res.status(200).json({
message: 'پست با موفقیت لایک شد',
is_liked: true,
likesCount: post.likes.length,
});
}
} catch (error) {
console.error('خطا در toggleLike:', error);
res.status(500).json({ message: 'خطا در سرور' });
next(error);
}
};
/* eslint-disable camelcase */
const PostModel = require('../../../models/PostModel');
const jwt = require('jsonwebtoken');
const UserModel = require('../../../models/UserModel');
const LikeModel = require('../../../models/LikeModel');
const { createLikeNotification } = require('../../../utils/likeNotification');
const toggleLike = async (req, res, next) => {
try {
const { postId } = req.body;
const token = req.header('Authorization')?.split(' ')[1];
if (!token) {
return res.status(401).json({ message: 'توکن ارائه نشده است' });
}
let userId;
try {
const decodedToken = jwt.verify(token, process.env.APP_SECRET);
userId = decodedToken.id;
} catch (err) {
return res.status(401).json({ message: 'توکن نامعتبر است' });
}
if (!postId) {
return res.status(400).json({ message: 'شناسه پست الزامی است' });
}
const post = await PostModel.findById(postId);
if (!post) {
return res.status(404).json({ message: 'پست مورد نظر یافت نشد' });
}
const isLiked = post.likes.includes(userId);
if (isLiked) {
// unlike
post.likes.pull(userId);
await post.save();
await LikeModel.findOneAndDelete({ postId, userId });
return res.status(200).json({
message: 'لایک با موفقیت حذف شد',
is_liked: false,
likesCount: post.likes.length,
});
} else {
// like
post.likes.push(userId);
await post.save();
await LikeModel.create({ postId, userId });
await createLikeNotification({
ownerId: post.user_id,
likerId: userId,
entityId: post._id,
type: 'post_like'
});
return res.status(200).json({
message: 'پست با موفقیت لایک شد',
is_liked: true,
likesCount: post.likes.length,
});
}
} catch (error) {
console.error('خطا در toggleLike:', error);
res.status(500).json({ message: 'خطا در سرور' });
next(error);
}
};
module.exports = { toggleLike };

View File

@@ -1,272 +1,272 @@
/* eslint-disable camelcase */
const PostModel = require('../../../models/PostModel');
const UserModel = require('../../../models/UserModel');
const { check, validationResult } = require('express-validator');
const jwt = require('jsonwebtoken');
const path = require('path');
const { default: mongoose } = require('mongoose');
const { viewerIsBlockedBy } = require('../../../utils/blockVisibility');
const createPostValidationRules = () => {
console.log(4);
return [
check('caption')
.notEmpty().withMessage('توضیحات نمی‌تواند خالی باشد'),
];
};
const createPost = async (req, res) => {
try {
console.log('DEBUG: createPost called');
console.log('DEBUG: req.files:', req.files);
console.log('DEBUG: req.body:', req.body);
const { caption } = req.body;
const files = req.files || [];
const userId = req.user.id; // از میدل‌ویر auth
if (!files || files.length === 0) {
console.log('DEBUG: No files provided');
return res.status(400).json({ error: true, message: 'هیچ فایلی آپلود نشده است' });
}
if (!caption) {
console.log('DEBUG: No caption provided');
return res.status(400).json({ error: true, message: 'کپشن الزامی است' });
}
const filePaths = files.map((file) => ({
path: file.path,
type: file.mimetype.startsWith('video/') ? 'video' : 'image',
}));
console.log('DEBUG: Saving post to MongoDB, filePaths:', filePaths);
const post = new PostModel({
user_id: userId,
caption,
files: filePaths,
type: files[0].mimetype.startsWith('video/') ? 'video' : 'image', // اضافه کردن فیلد type
createdAt: new Date(),
});
await post.save();
console.log('DEBUG: Post saved:', post._id);
res.status(201).json({ message: 'پست با موفقیت ایجاد شد', postId: post._id });
} catch (err) {
console.error('DEBUG: createPost error:', err.message);
res.status(500).json({ error: true, message: `خطا در سرور: ${err.message}` });
}
};
const getUserPosts = async (req, res, next) => {
try {
const token = req.header('Authorization').split(' ')[1]
if (!token) return res.status(401).send('Access Denied')
const user_id = req.query.user_id
// eslint-disable-next-line no-unused-vars
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
const userReqId = decodedToken.id
if (!mongoose.Types.ObjectId.isValid(user_id)) {
return res.status(400).json({ message: 'شناسه کاربر معتبر نیست' })
}
const user = await UserModel.findById(user_id)
if (!user) {
return res.status(404).json({ message: 'کاربر مورد نظر یافت نشد' })
}
const response = {}
const options = {
page: req.query.page || 1, // صفحه پیش‌فرض ۱
limit: req.query.limit || 10, // حداکثر تعداد موارد برای هر صفحه
sort: { createdAt: -1 }
}
if (user_id.toString() === userReqId.toString()) {
// کاربر خودش است، همه پست‌هایش را بررسی می‌کند
const posts = await PostModel.paginate(
{ user_id: user._id, status: { $in: ['pending', 'accept'] } }, // فیلتر
options // گزینه‌های پیجینیشن
)
response.posts = posts.docs
response.postsCount = posts.totalDocs
response.totalPages = posts.totalPages // ارسال تعداد کل صفحات
response.totalItems = posts.totalDocs
} else {
// دیگران، فقط پست‌هایی که وضعیتشان "accept" است را ببینند
const posts = await PostModel.paginate(
{ user_id: user._id, status: 'accept' }, // فیلتر
options // گزینه‌های پیجینیشن
)
response.posts = posts.docs
response.postsCount = posts.totalDocs
response.totalPages = posts.totalPages // ارسال تعداد کل صفحات
response.totalItems = posts.totalDocs
}
return res.status(200).json({ data: response })
} catch (error) {
next(error)
}
}
const getUserPostsWeb = async (req, res, next) => {
try {
let userReqId = null
// دریافت توکن و بررسی معتبر بودنش (اگر وجود داشت)
const authHeader = req.header('Authorization')
if (authHeader) {
const token = authHeader.split(' ')[1]
try {
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
userReqId = decodedToken.id
} catch (err) {
console.warn('توکن نامعتبر است، ادامه بدون احراز هویت') // فقط هشدار، نه ارور
}
}
const user_id = req.query.user_id
if (!mongoose.Types.ObjectId.isValid(user_id)) {
return res.status(400).json({ message: 'شناسه کاربر معتبر نیست' })
}
const user = await UserModel.findById(user_id)
if (!user) {
return res.status(404).json({ message: 'کاربر مورد نظر یافت نشد' })
}
if (userReqId && viewerIsBlockedBy(user, userReqId)) {
return res.status(200).json({
posts: [],
postsCount: 0,
totalPages: 0,
totalItems: 0,
})
}
const data = {}
const options = {
page: req.query.page || 1,
limit: req.query.limit || 10,
sort: { createdAt: -1 }
}
if (userReqId && user_id.toString() === userReqId.toString()) {
// اگر کاربر لاگین کرده و درخواست برای خودش است، همه پست‌هایش را ببیند
const posts = await PostModel.paginate(
{ user_id: user._id, status: { $in: ['pending', 'accept'] } },
options
)
data.posts = posts.docs
data.postsCount = posts.totalDocs
data.totalPages = posts.totalPages
data.totalItems = posts.totalDocs
} else {
// برای بقیه، فقط پست‌هایی که وضعیتشان "accept" است نمایش داده شود
const posts = await PostModel.paginate(
{ user_id: user._id, status: 'accept' },
options
)
data.posts = posts.docs
data.postsCount = posts.totalDocs
data.totalPages = posts.totalPages
data.totalItems = posts.totalDocs
}
return res.status(200).json(data)
} catch (error) {
next(error)
}
}
const getPostByIdWeb = async (req, res, next) => {
try {
const { postId } = req.params
if (!mongoose.Types.ObjectId.isValid(postId)) {
return res.status(400).json({ message: 'شناسه پست معتبر نیست' })
}
let userReqId = null
const authHeader = req.header('Authorization')
if (authHeader) {
const token = authHeader.split(' ')[1]
try {
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
userReqId = decodedToken.id
} catch (err) {
console.warn('توکن نامعتبر است، ادامه بدون احراز هویت')
}
}
const post = await PostModel.findById(postId).lean()
if (!post || post.status !== 'accept') {
return res.status(404).json({ message: 'پست یافت نشد' })
}
const user = await UserModel.findById(post.user_id)
.select(
'_id user_name first_name last_name expertise sub_expertise province city user_level show_location profile_image blocked_users'
)
.lean()
if (!user) {
return res.status(404).json({ message: 'پست یافت نشد' })
}
if (userReqId && viewerIsBlockedBy(user, userReqId)) {
return res.status(404).json({ message: 'پست یافت نشد' })
}
const LikeModel = require('../../../models/LikeModel')
const CommentModel = require('../../../models/CommentModel')
let is_liked = false
if (userReqId) {
const like = await LikeModel.findOne({
userId: userReqId,
postId: post._id,
}).lean()
is_liked = !!like
}
const commentsCount = await CommentModel.countDocuments({
post: post._id,
status: 'accepted',
})
return res.status(200).json({
post: {
...post,
user_name: user.user_name || '',
first_name: user.first_name || '',
last_name: user.last_name || '',
expertise: user.expertise || '',
sub_expertise: user.sub_expertise || [],
province: user.show_location ? user.province || {} : {},
city: user.show_location ? user.city || {} : {},
show_location: user.show_location,
user_level: user.user_level || '',
profile_image: user.profile_image || '',
likesCount: post.likes ? post.likes.length : 0,
is_liked,
commentsCount,
},
})
} catch (error) {
next(error)
}
}
module.exports = {
createPostValidationRules,
createPost,
getUserPosts,
getUserPostsWeb,
getPostByIdWeb
}
/* eslint-disable camelcase */
const PostModel = require('../../../models/PostModel');
const UserModel = require('../../../models/UserModel');
const { check, validationResult } = require('express-validator');
const jwt = require('jsonwebtoken');
const path = require('path');
const { default: mongoose } = require('mongoose');
const { viewerIsBlockedBy } = require('../../../utils/blockVisibility');
const createPostValidationRules = () => {
console.log(4);
return [
check('caption')
.notEmpty().withMessage('توضیحات نمی‌تواند خالی باشد'),
];
};
const createPost = async (req, res) => {
try {
console.log('DEBUG: createPost called');
console.log('DEBUG: req.files:', req.files);
console.log('DEBUG: req.body:', req.body);
const { caption } = req.body;
const files = req.files || [];
const userId = req.user.id; // از میدل‌ویر auth
if (!files || files.length === 0) {
console.log('DEBUG: No files provided');
return res.status(400).json({ error: true, message: 'هیچ فایلی آپلود نشده است' });
}
if (!caption) {
console.log('DEBUG: No caption provided');
return res.status(400).json({ error: true, message: 'کپشن الزامی است' });
}
const filePaths = files.map((file) => ({
path: file.path,
type: file.mimetype.startsWith('video/') ? 'video' : 'image',
}));
console.log('DEBUG: Saving post to MongoDB, filePaths:', filePaths);
const post = new PostModel({
user_id: userId,
caption,
files: filePaths,
type: files[0].mimetype.startsWith('video/') ? 'video' : 'image', // اضافه کردن فیلد type
createdAt: new Date(),
});
await post.save();
console.log('DEBUG: Post saved:', post._id);
res.status(201).json({ message: 'پست با موفقیت ایجاد شد', postId: post._id });
} catch (err) {
console.error('DEBUG: createPost error:', err.message);
res.status(500).json({ error: true, message: `خطا در سرور: ${err.message}` });
}
};
const getUserPosts = async (req, res, next) => {
try {
const token = req.header('Authorization').split(' ')[1]
if (!token) return res.status(401).send('Access Denied')
const user_id = req.query.user_id
// eslint-disable-next-line no-unused-vars
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
const userReqId = decodedToken.id
if (!mongoose.Types.ObjectId.isValid(user_id)) {
return res.status(400).json({ message: 'شناسه کاربر معتبر نیست' })
}
const user = await UserModel.findById(user_id)
if (!user) {
return res.status(404).json({ message: 'کاربر مورد نظر یافت نشد' })
}
const response = {}
const options = {
page: req.query.page || 1, // صفحه پیش‌فرض ۱
limit: req.query.limit || 10, // حداکثر تعداد موارد برای هر صفحه
sort: { createdAt: -1 }
}
if (user_id.toString() === userReqId.toString()) {
// کاربر خودش است، همه پست‌هایش را بررسی می‌کند
const posts = await PostModel.paginate(
{ user_id: user._id, status: { $in: ['pending', 'accept'] } }, // فیلتر
options // گزینه‌های پیجینیشن
)
response.posts = posts.docs
response.postsCount = posts.totalDocs
response.totalPages = posts.totalPages // ارسال تعداد کل صفحات
response.totalItems = posts.totalDocs
} else {
// دیگران، فقط پست‌هایی که وضعیتشان "accept" است را ببینند
const posts = await PostModel.paginate(
{ user_id: user._id, status: 'accept' }, // فیلتر
options // گزینه‌های پیجینیشن
)
response.posts = posts.docs
response.postsCount = posts.totalDocs
response.totalPages = posts.totalPages // ارسال تعداد کل صفحات
response.totalItems = posts.totalDocs
}
return res.status(200).json({ data: response })
} catch (error) {
next(error)
}
}
const getUserPostsWeb = async (req, res, next) => {
try {
let userReqId = null
// دریافت توکن و بررسی معتبر بودنش (اگر وجود داشت)
const authHeader = req.header('Authorization')
if (authHeader) {
const token = authHeader.split(' ')[1]
try {
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
userReqId = decodedToken.id
} catch (err) {
console.warn('توکن نامعتبر است، ادامه بدون احراز هویت') // فقط هشدار، نه ارور
}
}
const user_id = req.query.user_id
if (!mongoose.Types.ObjectId.isValid(user_id)) {
return res.status(400).json({ message: 'شناسه کاربر معتبر نیست' })
}
const user = await UserModel.findById(user_id)
if (!user) {
return res.status(404).json({ message: 'کاربر مورد نظر یافت نشد' })
}
if (userReqId && viewerIsBlockedBy(user, userReqId)) {
return res.status(200).json({
posts: [],
postsCount: 0,
totalPages: 0,
totalItems: 0,
})
}
const data = {}
const options = {
page: req.query.page || 1,
limit: req.query.limit || 10,
sort: { createdAt: -1 }
}
if (userReqId && user_id.toString() === userReqId.toString()) {
// اگر کاربر لاگین کرده و درخواست برای خودش است، همه پست‌هایش را ببیند
const posts = await PostModel.paginate(
{ user_id: user._id, status: { $in: ['pending', 'accept'] } },
options
)
data.posts = posts.docs
data.postsCount = posts.totalDocs
data.totalPages = posts.totalPages
data.totalItems = posts.totalDocs
} else {
// برای بقیه، فقط پست‌هایی که وضعیتشان "accept" است نمایش داده شود
const posts = await PostModel.paginate(
{ user_id: user._id, status: 'accept' },
options
)
data.posts = posts.docs
data.postsCount = posts.totalDocs
data.totalPages = posts.totalPages
data.totalItems = posts.totalDocs
}
return res.status(200).json(data)
} catch (error) {
next(error)
}
}
const getPostByIdWeb = async (req, res, next) => {
try {
const { postId } = req.params
if (!mongoose.Types.ObjectId.isValid(postId)) {
return res.status(400).json({ message: 'شناسه پست معتبر نیست' })
}
let userReqId = null
const authHeader = req.header('Authorization')
if (authHeader) {
const token = authHeader.split(' ')[1]
try {
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
userReqId = decodedToken.id
} catch (err) {
console.warn('توکن نامعتبر است، ادامه بدون احراز هویت')
}
}
const post = await PostModel.findById(postId).lean()
if (!post || post.status !== 'accept') {
return res.status(404).json({ message: 'پست یافت نشد' })
}
const user = await UserModel.findById(post.user_id)
.select(
'_id user_name first_name last_name expertise sub_expertise province city user_level show_location profile_image blocked_users'
)
.lean()
if (!user) {
return res.status(404).json({ message: 'پست یافت نشد' })
}
if (userReqId && viewerIsBlockedBy(user, userReqId)) {
return res.status(404).json({ message: 'پست یافت نشد' })
}
const LikeModel = require('../../../models/LikeModel')
const CommentModel = require('../../../models/CommentModel')
let is_liked = false
if (userReqId) {
const like = await LikeModel.findOne({
userId: userReqId,
postId: post._id,
}).lean()
is_liked = !!like
}
const commentsCount = await CommentModel.countDocuments({
post: post._id,
status: 'accepted',
})
return res.status(200).json({
post: {
...post,
user_name: user.user_name || '',
first_name: user.first_name || '',
last_name: user.last_name || '',
expertise: user.expertise || '',
sub_expertise: user.sub_expertise || [],
province: user.show_location ? user.province || {} : {},
city: user.show_location ? user.city || {} : {},
show_location: user.show_location,
user_level: user.user_level || '',
profile_image: user.profile_image || '',
likesCount: post.likes ? post.likes.length : 0,
is_liked,
commentsCount,
},
})
} catch (error) {
next(error)
}
}
module.exports = {
createPostValidationRules,
createPost,
getUserPosts,
getUserPostsWeb,
getPostByIdWeb
}