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); } }, ];