Files
2025-07-21 09:40:58 +03:30

1708 lines
45 KiB
JavaScript

const News = require("../models/News");
const { body, validationResult } = require("express-validator");
const sharp = require("sharp");
const { _sr } = require("../plugins/serverResponses");
const {
res404,
res500,
checkValidations,
} = require("../plugins/controllersHelperFunctions");
const Category = require("../models/Category");
const Comment = require("../models/Comment");
const User = require("../models/User");
const fs = require("fs");
const NewsFile = require("../models/NewsFile");
const Polls = require("../models/Polls");
const moment = require("moment-jalaali");
////// variables
const noCover = "/img/no-cover.jpg";
const coverNewsWidth = 1920;
const coverNewsHeight = 1080;
const coverQuality = 100;
const thumbCoverNewsWidth = 600;
const thumbCoverNewsHeight = 300;
const thumbCoverQuality = 100;
const limit = 20;
const newsPerPageLimit = 16;
const galleryPerPageLimit = 5;
const shortTitleFront = 150;
const shortTitlePanel = 20;
const shortSumTitle = 250;
const titleFilterRegex = new RegExp("/", "g");
// helper functions
const changePriority = async (catId, modelType) => {
try {
const getAllNews = await News.find({
catId,
modelType,
priority: true,
});
for (const item of getAllNews) {
item.priority = false;
await item.save();
}
return true;
} catch (error) {
console.log(error);
return false;
}
};
const randomNews = async (queryObject) => {
let setSkip;
try {
let temp = [];
const result = [];
/** total of news */
const count = await News.countDocuments(queryObject);
if (count < 3) {
return await News.find(queryObject);
}
/** get random index number */
while (temp.length < 3) {
setSkip = Math.floor(Math.random() * count);
temp.push(setSkip);
/** remove duplicate numbers */
temp = [...new Set(temp)];
}
/** get news and push to result */
for (let i = 0; i < 3; i++) {
const getNews = await News.findOne(queryObject).skip(temp[i]);
if (getNews) {
result.push(getNews);
}
}
/** return result */
return result;
} catch (error) {
console.log(error);
/** return error */
return [];
}
};
const _checkSpecPermission = async (req, category) => {
return (
!req.user.specialPermissions.includes(category._id) && //check parent id exist in special permissions or not
!req.user.specialPermissions.some((item) =>
category?.treeCat?.join().includes(item)
)
);
};
const handleFileUploads = async (req, res, targetNews) => {
let hasCover = false;
let hasThumb = false;
const timestamp = Date.now();
if (req.files.cover) {
const image = req.files.cover;
if (!_sr.supportedImageFormats.includes(image.mimetype.split("/")[1])) {
throw new Error(_sr["fa"].format.image);
}
// حذف کاور قدیمی در صورت وجود
if (targetNews.cover && targetNews.cover !== noCover) {
const oldCoverPath = `./static/uploads/images/news/${targetNews.cover}`;
if (fs.existsSync(oldCoverPath)) {
fs.unlinkSync(oldCoverPath);
}
}
const imageName = `news_cover_${timestamp}_${targetNews._id}.${
image.mimetype.split("/")[1]
}`;
try {
const target = sharp(image.data);
await target
.resize(coverNewsWidth, coverNewsHeight, {
fit: "cover",
})
.jpeg({
quality: coverQuality,
})
.toFile(`./static/uploads/images/news/${imageName}`);
targetNews.cover = imageName;
hasCover = true;
} catch (e) {
throw new Error(e?.message);
}
// اگر thumbCover ارسال نشده، از همین تصویر thumbCover بسازیم
if (!req.files.thumbCover) {
if (targetNews.thumbCover && targetNews.thumbCover !== noCover) {
const oldThumbPath = `./static/uploads/images/news/${targetNews.thumbCover}`;
if (fs.existsSync(oldThumbPath)) {
fs.unlinkSync(oldThumbPath);
}
}
const thumbImageName = `news_thumb_${timestamp}_${targetNews._id}.${
image.mimetype.split("/")[1]
}`;
try {
const target = sharp(image.data);
await target
.resize(thumbCoverNewsWidth, thumbCoverNewsHeight, {
fit: "cover",
})
.jpeg({
quality: thumbCoverQuality,
})
.toFile(`./static/uploads/images/news/${thumbImageName}`);
targetNews.thumbCover = thumbImageName;
hasThumb = true;
} catch (e) {
throw new Error(e?.message);
}
}
}
if (req.files.thumbCover) {
const image = req.files.thumbCover;
if (!_sr.supportedImageFormats.includes(image.mimetype.split("/")[1])) {
throw new Error(_sr["fa"].format.image);
}
// حذف thumb قدیمی در صورت وجود
if (targetNews.thumbCover && targetNews.thumbCover !== noCover) {
const oldThumbPath = `./static/uploads/images/news/${targetNews.thumbCover}`;
if (fs.existsSync(oldThumbPath)) {
fs.unlinkSync(oldThumbPath);
}
}
const thumbImageName = `news_thumb_${timestamp}_${targetNews._id}.${
image.mimetype.split("/")[1]
}`;
try {
const target = sharp(image.data);
await target
.resize(thumbCoverNewsWidth, thumbCoverNewsHeight, {
fit: "cover",
})
.jpeg({
quality: thumbCoverQuality,
})
.toFile(`./static/uploads/images/news/${thumbImageName}`);
targetNews.thumbCover = thumbImageName;
hasThumb = true;
} catch (e) {
throw new Error(e?.message);
}
// اگر cover ارسال نشده، از همین تصویر cover بسازیم
if (!req.files.cover) {
if (targetNews.cover && targetNews.cover !== noCover) {
const oldCoverPath = `./static/uploads/images/news/${targetNews.cover}`;
if (fs.existsSync(oldCoverPath)) {
fs.unlinkSync(oldCoverPath);
}
}
const coverImageName = `news_cover_${timestamp}_${targetNews._id}.${
image.mimetype.split("/")[1]
}`;
try {
const target = sharp(image.data);
await target
.resize(coverNewsWidth, coverNewsHeight, {
fit: "cover",
})
.jpeg({
quality: coverQuality,
})
.toFile(`./static/uploads/images/news/${coverImageName}`);
targetNews.cover = coverImageName;
hasCover = true;
} catch (e) {
throw new Error(e?.message);
}
}
}
// به‌روزرسانی وضعیت خبر - خبر کامل است اگر حداقل یکی از تصاویر آپلود شده باشد یا قبلاً موجود باشد
const currentHasCover = targetNews.cover && targetNews.cover !== noCover;
const currentHasThumb =
targetNews.thumbCover && targetNews.thumbCover !== noCover;
targetNews.newsStatus =
hasCover || hasThumb || currentHasCover || currentHasThumb;
};
/////////////////////////////////////////////////////////////////////// admin
module.exports.addNews = [
[
body("title")
.notEmpty()
.withMessage(_sr["fa"].required.title)
.custom((value) => {
return News.findOne({
title: value,
}).then((news) => {
if (news) return Promise.reject(_sr["fa"].duplicated.title);
else return true;
});
}),
// body('summaryTitle')
// .notEmpty().withMessage(_sr['fa'].required.caption),
body("leadTitle").notEmpty().withMessage(_sr["fa"].required.caption),
body("catId")
.isMongoId()
.withMessage(_sr["fa"].required.field)
.if((value, { req }) => {
return req.body.catId;
})
.custom((value) => {
return Category.findOne({
_id: value,
}).then((category) => {
if (!category) return Promise.reject(_sr["fa"].not_found.category);
else return true;
});
}),
body("priority")
.optional()
.isBoolean()
.withMessage(_sr["fa"].format.boolean),
body("allowComment")
.optional()
.isBoolean()
.withMessage(_sr["fa"].format.boolean),
body("showInHome").isBoolean().withMessage(_sr["fa"].format.boolean),
body("notifications").isBoolean().withMessage(_sr["fa"].format.boolean),
// body('slider')
// .optional().isBoolean().withMessage(_sr['fa'].format.boolean),
body("special").isBoolean().withMessage(_sr["fa"].format.boolean),
body("siteMap")
.optional()
.isBoolean()
.withMessage(_sr["fa"].format.boolean),
body("publish").isBoolean().withMessage(_sr["fa"].format.boolean),
body("keywords")
.if((value) => {
return value;
})
.custom((value) => {
const keywords = _.isString(value) ? JSON.parse(value) : value;
if (!_.isArray(keywords)) {
return Promise.reject(`این فیلد باید به صورت آرایه فرستاده شود`);
}
return true;
}),
body("metaTagDesc").optional(),
body("modelType").custom((value, { req }) => {
if (req.user.portals.join() === portal.join()) {
if (!portal.includes(value)) {
return Promise.reject(`${_sr["fa"].optional.onlyValid} => ${portal}`);
} else {
return true;
}
} else {
return true;
}
}),
body("newsFileId")
.optional()
.isMongoId()
.withMessage(`لطفا یک ای دی صحیح ارسال کنید`),
],
async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty())
return res.status(422).json({
validation: errors.mapped(),
});
try {
let {
title,
summaryTitle,
leadTitle,
catId,
PublisherId,
priority,
allowComment,
showInHome,
special,
notifications,
siteMap,
publish,
pageContent,
content,
keywords,
metaTagDesc,
modelType,
// slider,
newsFileId,
} = req.body;
keywords = _.isString(keywords) ? JSON.parse(keywords) : keywords;
/** set portals */
modelType =
req.user.portals.join() === portal.join()
? modelType
: req.user.portals[0];
// const isPublisher = await User.findById(PublisherId)
// if(!isPublisher){
// return res.status(404).json({message:"کاربر وجود ندارد"})
// }
// if(!isPublisher.scope.includes('PublisherNews')){
// return res.status(401).json({message:"شما دسترسی برای انتشار را ندارید"})
// }
if (newsFileId) {
let checkNewsFile = await NewsFile.findOne({
_id: newsFileId,
});
if (!checkNewsFile) {
return res404(res, `پرونده خبری انخاب شده وجود ندارد`);
}
if (checkNewsFile.modelType !== modelType) {
return res.status(422).json({
validation: {
newsFileId: {
msg: `نوع خبر مورد نظر با نوع پرونده خبری متفاوت است`,
},
},
});
}
}
const newsData = {
title: title?.trim()?.replace(titleFilterRegex, "/"),
summaryTitle: summaryTitle?.trim(),
leadTitle: leadTitle?.trim(),
catId,
priority,
showInHome,
publish,
pageContent,
PublisherId,
special,
content,
allowComment,
notifications,
siteMap,
keywords,
// slider,
_creator: req.user._id,
_updatedBy: req.user._id,
metaTagDesc: metaTagDesc ? metaTagDesc : leadTitle,
modelType,
newsFileId,
shortTitleFront: title?.trim()?.slice(0, shortTitleFront),
shortTitlePanel: title?.trim()?.slice(0, shortTitlePanel),
shortSummaryTitle: summaryTitle?.trim()?.slice(0, shortSumTitle),
};
if (catId) {
/** get category with populate parent */
const category = await Category.findOne({
_id: catId,
}).populate({
path: "parent",
populate: {
path: "parent",
model: "Category",
},
});
/** if undefined we have error from database */
if (!category) {
return res404(res, `دسته بندی انتخاب شده برای این خبر پیدا نشد`);
}
/** check special permission */
if (
req.user.specialPermissions.length &&
(await _checkSpecPermission(req, category))
) {
return res.status(403).json({
message: `شما نمیتوانید این دسته بندی را انتخاب کنید`,
});
}
if (category.modelType !== modelType) {
return res.status(403).json({
message: `شما اجازه استفاده از این دسته بندی را ندارید`,
});
}
newsData.allCat = category.treeCat;
newsData.rootParent = category.rootParent || category._id;
if (priority === "true") {
await changePriority(category._id, modelType);
}
}
const createNews = await News.create(newsData);
if (!createNews) {
return res500(res, `error in add news to data base`);
}
/**
* if we have pic upload to server
*/
if (req.files) {
let hasCover = false;
let hasThumb = false;
const timestamp = Date.now();
if (req.files.cover) {
const image = req.files.cover;
if (
!_sr.supportedImageFormats.includes(image.mimetype.split("/")[1])
) {
return res.status(422).json({
validation: {
cover: {
msg: _sr["fa"].format.image,
},
},
});
}
const imageName = `news_cover_${timestamp}_${createNews._id}.${
image.mimetype.split("/")[1]
}`;
try {
const target = sharp(image.data);
await target
.resize(coverNewsWidth, coverNewsHeight, {
fit: "cover",
})
.jpeg({
quality: coverQuality,
})
.toFile(`./static/uploads/images/news/${imageName}`);
createNews.cover = imageName;
hasCover = true;
} catch (e) {
return res500(res, e?.message);
}
// اگر thumbCover ارسال نشده، از همین تصویر thumbCover بسازیم
if (!req.files.thumbCover) {
const thumbImageName = `news_thumb_${timestamp}_${createNews._id}.${
image.mimetype.split("/")[1]
}`;
try {
const target = sharp(image.data);
await target
.resize(thumbCoverNewsWidth, thumbCoverNewsHeight, {
fit: "cover",
})
.jpeg({
quality: thumbCoverQuality,
})
.toFile(`./static/uploads/images/news/${thumbImageName}`);
createNews.thumbCover = thumbImageName;
hasThumb = true;
} catch (e) {
return res500(res, e?.message);
}
}
}
if (req.files.thumbCover) {
const image = req.files.thumbCover;
if (
!_sr.supportedImageFormats.includes(image.mimetype.split("/")[1])
) {
return res.status(422).json({
validation: {
thumbCover: {
msg: _sr["fa"].format.image,
},
},
});
}
const thumbImageName = `news_thumb_${timestamp}_${createNews._id}.${
image.mimetype.split("/")[1]
}`;
try {
const target = sharp(image.data);
await target
.resize(thumbCoverNewsWidth, thumbCoverNewsHeight, {
fit: "cover",
})
.jpeg({
quality: thumbCoverQuality,
})
.toFile(`./static/uploads/images/news/${thumbImageName}`);
createNews.thumbCover = thumbImageName;
hasThumb = true;
} catch (e) {
return res500(res, e?.message);
}
// اگر cover ارسال نشده، از همین تصویر cover بسازیم
if (!req.files.cover) {
const coverImageName = `news_cover_${timestamp}_${createNews._id}.${
image.mimetype.split("/")[1]
}`;
try {
const target = sharp(image.data);
await target
.resize(coverNewsWidth, coverNewsHeight, {
fit: "cover",
})
.jpeg({
quality: coverQuality,
})
.toFile(`./static/uploads/images/news/${coverImageName}`);
createNews.cover = coverImageName;
hasCover = true;
} catch (e) {
return res500(res, e?.message);
}
}
}
// خبر کامل است اگر حداقل یکی از تصاویر آپلود شده باشد
createNews.newsStatus = hasCover || hasThumb;
await createNews.save();
}
/**
* show result
*/
return res.json(createNews);
} catch (error) {
console.log(error);
/**
* if we got unkown error show to client
*/
res500(res, error.message);
}
},
];
module.exports.addAllNews = [
async (req, res) => {
try {
// // const parsedData = req.files.file
// const {rootParent, category, creator, catIdOstan} = req.body
// const rawFile = await fs.readFileSync(`./server/csvjson.json`)
// const parsedData = await JSON.parse(rawFile)
//
// // console.log(parsedData)
//
// const posts = []
//
// // dynamic
// // const rootParent = '60e95a43111ba696ea3d5171' // فرمانداری ها
// // const category = '60e95c7d111ba696ea3d5301' // فرماندای شهرستان خنداب
//
// // static
// // const creator = '60eaaf8db36930ef88d3d377'
//
// const newArray = []
//
// for (const item of parsedData) {
// if (item.term_taxonomy_id.toString() === catIdOstan) {
// // console.log(item.term_taxonomy_id)
// newArray.push(item)
// }
// }
//
// console.log('-- posts length: ', newArray.length)
//
// let index = 0
// for (const item of newArray) {
// const newPost = new News({
// title: item.post_title,
// shortTitlePanel: item.post_title,
// shortTitleFront: item.post_title,
// summaryTitle: item.post_title,
// leadTitle: '',
// shortSummaryTitle: item.post_title,
// customDate: item.post_date,
// /// ****************************************
// catId: category,
// /// ****************************************
// allCat: [],
// newsFileId: null,
// /// ****************************************
// rootParent: rootParent,
// /// ****************************************
// priority: false,
// allowComment: false,
// showInHome: false,
// slider: false,
// publish: true,
// pageContent: item.post_content,
// cover: null,
// thumbCover: null,
// userViews: 200,
// special: false,
// notifications: false,
// _creator: creator,
// _updatedBy: creator,
// siteMap: true,
// keywords: [],
// metaTagDesc: item.post_title,
// newsStatus: true,
// modelType: 'ostandari',
// attachments: [],
// imported: true
// })
// await newPost.save()
// if (index === newArray.length - 1) console.log('---- data entry finished')
// index++
// }
const news = await News.find({ catId: "60e931d5111ba696ea3d483b" });
// const regex = new RegExp('/', 'g')
let index = 0;
for await (const item of news) {
console.log(index);
// item.title = item.title.replace(regex, ',')
item.catId = "60e931fc111ba696ea3d485b";
item.allCat = ["60e931d5111ba696ea3d483b"];
await item.save();
if (index === news.length - 1) console.log("update finished");
index++;
}
/**
* show result
*/
return res.json(news);
} catch (error) {
console.log(error);
/**
* if we got unkown error show to client
*/
return res500(res, error.message);
}
},
];
module.exports.updateNews = [
[
body("title").notEmpty().withMessage(_sr["fa"].required.title),
body("leadTitle").notEmpty().withMessage(_sr["fa"].required.field),
body("catId")
.notEmpty()
.withMessage(_sr["fa"].required.field)
.bail()
.isMongoId()
.withMessage("شناسه دسته بندی معتبر نیست")
.bail()
.custom((value) => {
return Category.findById(value).then((category) => {
if (!category) {
return Promise.reject(_sr["fa"].not_found.category);
}
});
}),
body("priority")
.optional()
.isBoolean()
.withMessage(_sr["fa"].format.boolean),
body("allowComment")
.optional()
.isBoolean()
.withMessage(_sr["fa"].format.boolean),
body("notifications").isBoolean().withMessage(_sr["fa"].format.boolean),
body("showInHome").isBoolean().withMessage(_sr["fa"].format.boolean),
body("special").isBoolean().withMessage(_sr["fa"].format.boolean),
body("siteMap")
.optional()
.isBoolean()
.withMessage(_sr["fa"].format.boolean),
body("publish").isBoolean().withMessage(_sr["fa"].format.boolean),
body("keywords")
.optional()
.custom((value) => {
try {
const keywords = _.isString(value) ? JSON.parse(value) : value;
if (!Array.isArray(keywords)) {
throw new Error("این فیلد باید به صورت آرایه فرستاده شود");
}
return true;
} catch (error) {
throw new Error("این فیلد باید به صورت آرایه فرستاده شود");
}
}),
body("metaTagDesc").optional(),
body("modelType").custom((value, { req }) => {
if (req.user.portals.join() === portal.join()) {
if (!portal.includes(value)) {
return Promise.reject(`${_sr["fa"].optional.onlyValid} => ${portal}`);
}
}
return true;
}),
body("newsFileId")
.optional()
.isMongoId()
.withMessage("شناسه فایل خبری معتبر نیست"),
body("customDate")
.optional()
.isString()
.withMessage("لطفا یک تاریخ صحیح وارد نمایید"),
],
async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(422).json({ validation: errors.mapped() });
}
try {
const {
title,
summaryTitle,
leadTitle,
catId,
priority,
notifications,
showInHome,
special,
siteMap,
content,
publish,
pageContent,
allowComment,
keywords,
metaTagDesc,
modelType,
newsFileId,
customDate,
} = req.body;
let parsedKeywords = keywords;
if (_.isString(keywords)) {
parsedKeywords = JSON.parse(keywords);
}
const newsId = req.params.id;
const targetNews = await News.findById(newsId).populate("catId");
if (!targetNews) {
return res404(res, "خبر مورد نظر پیدا نشد");
}
if (
req.user.specialPermissions.length &&
(await _checkSpecPermission(req, targetNews.catId))
) {
return res
.status(403)
.json({ message: "شما اجازه بروزرسانی این خبر را ندارید" });
}
if (!req.user.portals.includes(targetNews.modelType)) {
return res500(res, "شما اجازه آپدیت این خبر را ندارید");
}
if (targetNews.title !== title) {
const checkDuppTitle = await News.findOne({ title });
if (checkDuppTitle) {
return res.status(422).json({
validation: { title: { msg: _sr["fa"].duplicated.title } },
});
}
}
const category = await Category.findById(catId).populate({
path: "parent",
populate: {
path: "parent",
model: "Category",
},
});
if (catId && targetNews.catId.toString() !== catId.toString()) {
targetNews.allCat = category.treeCat;
targetNews.rootParent = category.rootParent || category._id;
}
if (priority === "true") {
await changePriority(category._id, modelType);
}
if (newsFileId) {
const checkNewsFile = await NewsFile.findById(newsFileId);
if (!checkNewsFile) {
return res404(res, "پرونده خبری انخاب شده وجود ندارد");
}
if (checkNewsFile.modelType !== modelType) {
return res.status(422).json({
validation: {
newsFileId: {
msg: "نوع خبر مورد نظر با نوع پرونده خبری متفاوت است",
},
},
});
}
}
if (req.files) {
try {
await handleFileUploads(req, res, targetNews);
} catch (error) {
return res.status(422).json({
validation: {
cover: { msg: error.message },
},
});
}
}
Object.assign(targetNews, {
title: title.trim().replace(titleFilterRegex, "/"),
summaryTitle: summaryTitle?.trim(),
leadTitle: leadTitle?.trim(),
catId,
priority,
notifications,
showInHome,
special,
siteMap,
publish,
allowComment,
content,
pageContent,
keywords: parsedKeywords,
metaTagDesc: metaTagDesc?.trim() || leadTitle?.trim(),
newsFileId,
shortTitleFront: title.slice(0, shortTitleFront),
shortTitlePanel: title.slice(0, shortTitlePanel),
shortSummaryTitle: summaryTitle?.trim()?.slice(0, shortSumTitle),
customDate: customDate || targetNews.created_at,
_updatedBy: req.user._id,
});
if (customDate) {
targetNews.customDateHistory.push({
customDate,
_updatedBy: req.user._id,
});
}
await targetNews.save();
return res.json(targetNews);
} catch (error) {
return res500(res, error.message);
}
},
];
module.exports.MostViewdNews = [
async (req, res) => {
const thirtyDaysAgo = new Date();
thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);
try {
const mostViewedNews = await News.find({
customDate: { $gte: thirtyDaysAgo },
})
.sort({ userViews: -1 })
.limit(10);
return res.status(200).json({ mostViewedNews });
} catch (error) {
res.status(500).send("خطا");
}
},
];
module.exports.deletOneNews = [
async (req, res) => {
let oldPic;
try {
const newsId = req.params.id;
const targetNews = await News.findOne({
_id: newsId,
}).populate("catId");
/** check news exist or not */
if (!targetNews) {
return res404(res, `خبر مورد نظر پیدا نشد`);
}
/** check special permission */
if (
req.user.specialPermissions.length &&
(await _checkSpecPermission(req, targetNews.catId))
) {
return res.status(403).json({
message: `شما مجاز به حذف این خبر نمی باشید`,
});
}
if (
targetNews?.superNews &&
req.user._id.toString() !== targetNews._creator.toString()
) {
return res.status(403).json({
message: `شما مجاز به حذف این خبر نمی باشید`,
});
}
/** check access portal */
if (!req.user.portals.includes(targetNews.modelType)) {
return res500(res, `شما اجازه حذف این خبر را ندارید`);
}
if (targetNews.cover !== noCover) {
oldPic = `./static${targetNews.cover}`;
if (fs.existsSync(oldPic)) {
fs.unlink(oldPic, (error) => {
if (error) return res500(res, error?.message);
});
}
}
if (targetNews.thumbCover !== noCover) {
oldPic = `./static${targetNews.thumbCover}`;
if (fs.existsSync(oldPic)) {
fs.unlink(oldPic, (error) => {
if (error) return res500(res, error?.message);
});
}
}
await targetNews.deleteOne();
await Comment.deleteMany({ modelRef: targetNews._id });
x;
return res.json(targetNews);
} catch (error) {
return res500(res, error);
}
},
];
module.exports.deleteAllNews = [
async (req, res) => {
try {
await News.deleteMany({ imported: true });
return res.json("ok");
} catch (error) {
/**
* if we got unkown error show to client
*/
return res500(res, error.message);
}
},
];
module.exports.getOneNews = [
async (req, res) => {
try {
const newsId = req.params.id;
const findQuery = {
_id: newsId,
};
const news = await News.findOne(findQuery).populate("catId");
if (!news) {
return res404(res, `خبر مورد نظر پیدا نشد`);
}
/** check special permission */
if (
req.user.specialPermissions.length &&
(await _checkSpecPermission(req, news.catId))
) {
return res.status(403).json({
message: `شما مجاز به دیدن اطلاعات این خبر نمی باشید`,
});
}
/** check access portal */
if (!req.user.portals.includes(news.modelType)) {
return res.status(403).json({
message: `شما اجازه دسترسی به اطلاعات این خبر را ندارید`,
});
}
/**
* show result
*/
return res.json(news);
} catch (error) {
/**
* if we got unknown error show to client
*/
res500(res, error);
}
},
];
module.exports.getAll = [
async (req, res) => {
try {
let findQuery = {};
// @todo can change it
if (req.user.specialPermissions.length) {
findQuery.catId = { $in: req.user.specialPermissions };
}
if (req.user.portals.length) {
findQuery.modelType = {
$in: req.user.portals,
};
}
/** get all news */
// var allNews = await News.find(findQuery).populate('_creator', {
// firstName: 1,
// lastName: 1,
// profilePic: 1
// })
// .populate('catId')
// .sort({
// created_at: -1
// });
let allNews = await News.paginate(findQuery, {
page: req.query.page,
limit,
populate: [
{
path: "_creator",
select: {
firstName: 1,
lastName: 1,
profilePic: 1,
},
},
{
path: "catId",
},
],
sort: {
customDate: -1,
},
});
/** if null we have error */
if (!allNews) {
return res500(res, `مشکلی در گرفتن اطلاعات پیش آمده است`);
}
/** show result to client */
return res.json(allNews);
} catch (error) {
console.log(error);
/** if we have unknown error show it */
return res500(res, error?.message);
}
},
];
module.exports.search = [
async (req, res) => {
try {
let findQuery = {};
findQuery["$and"] = [];
findQuery["$or"] = [];
let {
term,
catId,
showInHome,
publish,
portals,
status,
notifications,
special,
newsFile,
date,
} = req.body;
/** search by term */
if (term && !_.isEmpty(term)) {
findQuery["$or"].push(
{
title: {
$regex: ".*" + term + ".*",
},
},
{
summaryTitle: {
$regex: ".*" + term + ".*",
},
}
);
}
/** search by catId */
if (req.user.specialPermissions.length) {
findQuery.catId = { $in: req.user.specialPermissions };
} else if (catId && !_.isEmpty(catId)) {
findQuery["$and"].push({
catId,
});
}
/** search by showInHome */
if (!_.isUndefined(showInHome) && _.isBoolean(showInHome)) {
findQuery["$and"].push({
showInHome,
});
}
/** search by publish */
if (!_.isUndefined(publish) && _.isBoolean(publish)) {
findQuery["$and"].push({
publish,
});
}
/** search by portals */
if (req.user.portals.length) {
findQuery.modelType = {
$in: req.user.portals,
};
} else if (portals && !_.isEmpty(portals)) {
findQuery["$and"].push({
modelType: {
$in: portals,
},
});
}
/** search by status */
if (!_.isUndefined(status) && _.isBoolean(status)) {
findQuery["$and"].push({
newsStatus: status,
});
}
/** search by notifications */
if (!_.isUndefined(notifications) && _.isBoolean(notifications)) {
findQuery["$and"].push({
notifications,
});
}
/** search by special */
if (!_.isUndefined(special) && _.isBoolean(special)) {
findQuery["$and"].push({
special,
});
}
/** search by special */
if (newsFile && !_.isEmpty(newsFile)) {
findQuery["$and"].push({
newsFileId: newsFile,
});
}
/** search by date */
if (date && !_.isEmpty(date)) {
if (date.length === 1) {
findQuery["$and"].push({
customDate: {
$gte: moment(date[0]).startOf("days"),
$lt: moment(date[0]).endOf("days"),
},
});
} else {
findQuery["$and"].push({
customDate: {
$gte: new Date(date[0]),
$lt: new Date(date[1]),
},
});
}
}
_.isEmpty(findQuery["$and"]) && delete findQuery["$and"];
_.isEmpty(findQuery["$or"]) && delete findQuery["$or"];
/** get news */
const news = await News.paginate(findQuery, {
page: req.query.page,
limit,
populate: [
{
path: "_creator",
select: {
firstName: 1,
lastName: 1,
profilePic: 1,
},
},
{
path: "catId",
},
],
sort: {
customDate: -1,
},
});
/** show result */
return res.json(news);
} catch (error) {
return res500(res, error?.message);
}
},
];
module.exports.searchForSlider = [
async (req, res) => {
try {
var findQuery = { publish: true, newsStatus: true };
findQuery["$and"] = [];
findQuery["$or"] = [];
let term = req.params.title;
/** search by term */
if (term && !_.isEmpty(term)) {
findQuery["$or"].push({
title: {
$regex: ".*" + term + ".*",
},
});
}
_.isEmpty(findQuery["$and"]) && delete findQuery["$and"];
_.isEmpty(findQuery["$or"]) && delete findQuery["$or"];
/** get news */
var news = await News.find(findQuery);
/** show result */
return res.json(news);
} catch (error) {
return res500(res, error?.message);
}
},
];
//////////// add attachment file to category
module.exports.addAttachmentToNews = [
[body("attTitle").notEmpty().withMessage(_sr["fa"].required.title)],
checkValidations(validationResult),
(req, res) => {
if (!req.files?.file)
return res
.status(422)
.json({ validation: { file: { msg: _sr["fa"].required.file } } });
if (req.files?.file.mimetype.split("/")[1] !== "pdf")
return res
.status(422)
.json({ validation: { file: { msg: "فقط فرمت PDF قابل قبول است" } } });
const data = { title: req.body.attTitle };
const file = req.files.file;
const fileName =
req.body.attTitle.replace(titleFilterRegex, "-") +
"_" +
Date.now() +
".pdf";
file.mv(`./static/uploads/files/newsAttachments/${fileName}`);
data.file = fileName;
News.findById(req.params.newsId, (err, news) => {
if (err || !news) return res404(res, err);
news.attachments.push(data);
news.save((err) => {
if (err) return res500(res, err);
else return res.json({ message: _sr["fa"].response.success_save });
});
});
},
];
module.exports.removeAttachmentFromNews = [
(req, res) => {
News.findOne({ "attachments._id": req.params.fileId }, (err, news) => {
if (err || !news) return res404(res, err);
const file = news.attachments.id(req.params.fileId);
if (!file) return res404(res, "not found");
file.remove();
fs.unlink(`./static/${file.file}`, (err) => {
if (err) console.log(err);
});
news.save((err) => {
if (err) return res500(res, err);
else return res.json({ message: _sr["fa"].response.success_remove });
});
});
},
];
/////////////////////////////////////////////////////////////////////// public
module.exports.EDITNEWS = [async (req, res) => {}];
module.exports.viewNews = [
async (req, res) => {
try {
var newsTitle = req.params.title;
var targetNews = await News.findOne({
_id: newsTitle,
newsStatus: true,
publish: true,
})
.populate("_creator", {
firstName: 1,
lastName: 1,
profilePic: 1,
})
.populate({
path: "catId",
select: "title",
});
if (!targetNews) {
return res404(res, `خبر مورد نطر پیدا نشد`);
}
++targetNews.userViews;
await targetNews.save();
/** get comments */
var comments = await Comment.find({
modelRef: targetNews._id,
allowShow: true,
});
var result = {
news: targetNews,
comments,
};
return res.json(result);
} catch (error) {
return res500(res, error?.message);
}
},
];
module.exports.FilterNews = [
async (req, res) => {
const length = parseInt(req.params.length);
const views = parseInt(req.params.userViews);
try {
const news = await News.find().sort({ date: -1 }).limit(length);
const filteredNews = await News.find({
userViews: { $gte: views },
}).sort({ date: -1 });
res.json({ filteredNews, news });
} catch (error) {
res.status(500).json({ message: error.message });
}
},
];
module.exports.OstandarNews = [
async (req, res) => {
try {
const news = await News.find({ modelType: "ostandari" });
res.status(200).json(news);
} catch (e) {
return res.status(500).json(e.message);
}
},
];
module.exports.getNewsByCategory = [
async (req, res) => {
try {
const catTitle = req.params.title;
const page = req.query.page;
/** check category */
const targetCategory = await Category.findOne({
title: catTitle,
});
if (!targetCategory) {
return res404(res, `دسته بندی مورد نظر پیدا نشد`);
}
const requests = [
// priority news
News.findOne({
catId: targetCategory._id,
publish: true,
newsStatus: true,
priority: true,
}),
// news
News.paginate(
{
catId: targetCategory._id,
publish: true,
newsStatus: true,
priority: false,
},
{
page: page || 1,
limit: newsPerPageLimit,
sort: { customDate: -1 },
}
),
//news file
NewsFile.find({ catId: targetCategory._id, publish: true }),
// special
News.find({
catId: targetCategory._id,
publish: true,
newsStatus: true,
special: true,
}).sort({ customDate: -1 }),
// events
News.find({
catId: targetCategory._id,
publish: true,
newsStatus: true,
notifications: true,
}).sort({ customDate: -1 }),
//polls
Polls.find({
catId: targetCategory._id,
publish: true,
startDate: { $lte: new Date() },
endDate: { $gte: new Date() },
}),
// latestNews
News.find({
publish: true,
newsStatus: true,
})
.sort({ _id: -1 })
.limit(8),
];
const fetch = await Promise.all(requests);
const [heroNews, news, newsFile, specials, events, polls, latestNews] =
fetch;
const result = {
category: targetCategory,
heroNews,
news,
newsFile,
specials,
events,
polls,
latestNews,
};
return res.json(result);
} catch (error) {
return res500(res, error?.message);
}
},
];
module.exports.getAllNews = [
async (req, res) => {
try {
let { flag, catId, portal, limit, page } = req.query;
var findQuery = {};
var setLimit = parseInt(limit) || 10;
var setSort = {};
findQuery.modelType = portal;
findQuery.newsStatus = true;
findQuery.publish = true;
switch (flag) {
case "category":
setLimit = 20;
setSort.customDate = -1;
findQuery.rootParent = catId;
break;
case "all":
setLimit = 20;
setSort.customDate = -1;
break;
case "new":
setSort.customDate = -1;
setLimit = 5;
break;
case "slider":
findQuery.slider = true;
setSort.customDate = -1;
setLimit = 3;
break;
case "special":
findQuery.special = true;
setSort.customDate = -1;
setLimit = 4;
break;
case "random":
var result = await randomNews(findQuery);
return res.json(result);
case "popular":
setSort.userViews = -1;
setSort.customDate = -1;
setLimit = 5;
break;
case "events":
findQuery.notifications = true;
findQuery.showInHome = true;
setSort.customDate = -1;
setLimit = 5;
break;
default:
return res.json([]);
}
var getNews = await News.paginate(findQuery, {
page: page || 1,
limit: setLimit,
sort: setSort,
});
return res.json(getNews);
} catch (error) {
return res500(res, error?.message);
}
},
];
module.exports.getSections = [
async (req, res) => {
try {
const portal = req.query.portal;
let result = {};
result.sectionOne = [];
result.sectionTwo = [];
result.sectionThree = [];
let getSectionsTitle = await Category.find({
$or: [
{ showInSectionOne: true },
{ showInSectionTwo: true },
{ showInSectionThree: true },
],
modelType: portal,
});
for (const item of getSectionsTitle) {
let section = {};
let news = await News.find({
catId: item._id,
showInHome: true,
publish: true,
modelType: portal,
})
.limit(limit)
.sort({ _id: -1 });
section.nameTag = item.title;
section.data = news;
if (item.showInSectionOne) {
result.sectionOne = section;
}
if (item.showInSectionTwo) {
result.sectionTwo = section;
}
if (item.showInSectionThree) {
result.sectionThree.push(section);
}
}
// let findQuery = {};
// let setLimit = parseInt(limit) || 10;
// let setSort = {};
// let setSkip = parseInt(skip) || 0;
// findQuery.modelType = portal;
// findQuery.newsStatus = true;
// findQuery.publish = true;
return res.json(result);
} catch (error) {
return res500(res, error?.message);
}
},
];
/** @todo mabe change it in future */
module.exports.getRelated = [
async (req, res) => {
try {
const { portal, title } = req.query;
let getNews = {};
let findQuery = {};
findQuery.modelType = portal;
findQuery._id = {
$ne: title,
};
findQuery.newsStatus = true;
findQuery.publish = true;
const targetNews = await News.findById(title);
if (targetNews) {
findQuery.catId = targetNews.catId;
getNews = await randomNews(findQuery);
}
return res.json(getNews);
} catch (error) {
return res500(res, error?.message);
}
},
];