Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 94c79aa98d | |||
| 01c68fba43 | |||
| e0527e8ca6 | |||
| 1bb4c7efcc | |||
| 76f23a73e2 | |||
| a24f4ae766 | |||
| 096e653e64 | |||
| d6215b970f | |||
| 4c36880862 | |||
| dfb77cd8d2 | |||
| e95883eb6a | |||
| c73027540a | |||
| 85c8107799 | |||
| 99a9f9ace5 |
@@ -0,0 +1,7 @@
|
|||||||
|
# ParsPack S3 Storage
|
||||||
|
BUCKET_NAME=your_bucket_name
|
||||||
|
BUCKET_REGION=us-west-2
|
||||||
|
PARSPACK_S3_ENDPOINT=https://your_bucket_name.parspack.net
|
||||||
|
BUCKET_PUBLIC_URL=https://your_bucket_name.parspack.net
|
||||||
|
BUCKET_ACCESS_KEY=your_access_key
|
||||||
|
BUCKET_SECRET_KEY=your_secret_key
|
||||||
+4
-10
@@ -43,25 +43,19 @@ export default {
|
|||||||
type: "text/css",
|
type: "text/css",
|
||||||
href: "/js/flipBook/font-awesome.css",
|
href: "/js/flipBook/font-awesome.css",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
rel: "stylesheet",
|
|
||||||
href: "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js",
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
|
|
||||||
script: [
|
script: [
|
||||||
{ src: "https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.js" },
|
{ src: "/js/vendor/jquery-1.8.3.js" },
|
||||||
{
|
{ src: "/js/vendor/jquery-ui-1.9.2.min.js" },
|
||||||
src: "https://ajax.googleapis.com/ajax/libs/jqueryui/1.9.2/jquery-ui.min.js",
|
|
||||||
},
|
|
||||||
{ src: "/js/flipBook/flipbook.min.js" },
|
{ src: "/js/flipBook/flipbook.min.js" },
|
||||||
{ src: "/js/lightBox/simple-lightbox.min.js" },
|
{ src: "/js/lightBox/simple-lightbox.min.js" },
|
||||||
{
|
{
|
||||||
src: "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js",
|
src: "/js/vendor/jquery-3.6.0.min.js",
|
||||||
defer: true,
|
defer: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
src: "https://cdnjs.cloudflare.com/ajax/libs/jquery-flipbook/1.0.5/jquery.flipbook.min.js",
|
src: "/js/vendor/jquery.flipbook.min.js",
|
||||||
defer: true,
|
defer: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
Generated
+1154
-733
File diff suppressed because it is too large
Load Diff
+7
-1
@@ -11,6 +11,7 @@
|
|||||||
"generate": "nuxt generate"
|
"generate": "nuxt generate"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@aws-sdk/client-s3": "^3.1072.0",
|
||||||
"@coreui/coreui": "^3.2.2",
|
"@coreui/coreui": "^3.2.2",
|
||||||
"@coreui/icons": "^2.0.0-beta.5",
|
"@coreui/icons": "^2.0.0-beta.5",
|
||||||
"@coreui/utils": "^1.3.1",
|
"@coreui/utils": "^1.3.1",
|
||||||
@@ -25,10 +26,12 @@
|
|||||||
"archiver": "^5.3.0",
|
"archiver": "^5.3.0",
|
||||||
"axios": "^0.21.1",
|
"axios": "^0.21.1",
|
||||||
"bcryptjs": "^2.4.3",
|
"bcryptjs": "^2.4.3",
|
||||||
|
"ckeditor4": "^4.17.2",
|
||||||
"ckeditor4-vue": "^1.3.0",
|
"ckeditor4-vue": "^1.3.0",
|
||||||
"convertapi": "^1.14.0",
|
"convertapi": "^1.14.0",
|
||||||
"core-js": "^3.9.1",
|
"core-js": "^3.9.1",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
|
"dotenv": "^17.4.2",
|
||||||
"element-ui": "^2.15.1",
|
"element-ui": "^2.15.1",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"express-fileupload": "^1.2.1",
|
"express-fileupload": "^1.2.1",
|
||||||
@@ -49,7 +52,7 @@
|
|||||||
"nuxt": "^2.15.3",
|
"nuxt": "^2.15.3",
|
||||||
"nuxt-video-player": "^1.0.17",
|
"nuxt-video-player": "^1.0.17",
|
||||||
"request-ip": "^2.1.3",
|
"request-ip": "^2.1.3",
|
||||||
"sharp": "^0.28.1",
|
"sharp": "^0.33.5",
|
||||||
"slick-carousel": "^1.8.1",
|
"slick-carousel": "^1.8.1",
|
||||||
"svg-captcha": "^1.4.0",
|
"svg-captcha": "^1.4.0",
|
||||||
"swagger-jsdoc": "^6.2.8",
|
"swagger-jsdoc": "^6.2.8",
|
||||||
@@ -66,5 +69,8 @@
|
|||||||
"sass": "^1.77.3",
|
"sass": "^1.77.3",
|
||||||
"sass-loader": "^10.1.0",
|
"sass-loader": "^10.1.0",
|
||||||
"webpack": "^4.46.0"
|
"webpack": "^4.46.0"
|
||||||
|
},
|
||||||
|
"overrides": {
|
||||||
|
"sharp": "^0.33.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
v-for="(item, i) in items"
|
v-for="(item, i) in items"
|
||||||
:key="i"
|
:key="i"
|
||||||
class="item">
|
class="item">
|
||||||
<img :src="`/uploads/images/category/shafafiat/${item.icon}`" alt="شفافیت" />
|
<img :src="item.icon" alt="شفافیت" />
|
||||||
<div class="parent">
|
<div class="parent">
|
||||||
<div class="right"></div>
|
<div class="right"></div>
|
||||||
<div class="left"></div>
|
<div class="left"></div>
|
||||||
|
|||||||
@@ -1,4 +1,18 @@
|
|||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import CKEditor from 'ckeditor4-vue'
|
import CKEditor from 'ckeditor4-vue'
|
||||||
|
|
||||||
Vue.use(CKEditor)
|
const editorUrl = '/js/ckeditor/ckeditor.js'
|
||||||
|
|
||||||
|
window.CKEDITOR_BASEPATH = '/js/ckeditor/'
|
||||||
|
|
||||||
|
// editorUrl is a component prop, not a Vue.use() option — the default is the CDN.
|
||||||
|
Vue.component('ckeditor', {
|
||||||
|
...CKEditor.component,
|
||||||
|
props: {
|
||||||
|
...CKEditor.component.props,
|
||||||
|
editorUrl: {
|
||||||
|
type: String,
|
||||||
|
default: editorUrl,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|||||||
@@ -8,13 +8,19 @@ const {
|
|||||||
checkValidations,
|
checkValidations,
|
||||||
} = require("../plugins/controllersHelperFunctions");
|
} = require("../plugins/controllersHelperFunctions");
|
||||||
const News = require("../models/News");
|
const News = require("../models/News");
|
||||||
const sharp = require("sharp");
|
|
||||||
const fs = require("fs");
|
|
||||||
const { extname } = require("path");
|
const { extname } = require("path");
|
||||||
|
const {
|
||||||
|
deleteCategoryImage,
|
||||||
|
deleteShafafiatIcon,
|
||||||
|
uploadProcessedImage,
|
||||||
|
uploadShafafiatIcon,
|
||||||
|
uploadTermsFile,
|
||||||
|
deleteTermsFile,
|
||||||
|
getStoredImageName,
|
||||||
|
} = require("../plugins/categoryImageStorage");
|
||||||
|
|
||||||
// variables
|
// variables
|
||||||
const titleFilterRegex = new RegExp("/", "g");
|
const titleFilterRegex = new RegExp("/", "g");
|
||||||
const noCover = "/img/no-cover.jpg";
|
|
||||||
const coverNewsWidth = 400;
|
const coverNewsWidth = 400;
|
||||||
const coverNewsHeight = 400;
|
const coverNewsHeight = 400;
|
||||||
const coverQuality = 100;
|
const coverQuality = 100;
|
||||||
@@ -411,34 +417,13 @@ module.exports.addCategory = [
|
|||||||
image.mimetype.split("/")[1]
|
image.mimetype.split("/")[1]
|
||||||
}`;
|
}`;
|
||||||
try {
|
try {
|
||||||
const target = sharp(image.data);
|
await uploadProcessedImage(
|
||||||
await target
|
image.data,
|
||||||
.resize(coverNewsWidth, coverNewsHeight, { fit: "cover" })
|
imageName,
|
||||||
.jpeg({ quality: coverQuality })
|
coverNewsWidth,
|
||||||
.toFile(`./static/uploads/images/category/${imageName}`);
|
coverNewsHeight,
|
||||||
|
coverQuality
|
||||||
/**
|
);
|
||||||
* if exist old pic delete it from file
|
|
||||||
*/
|
|
||||||
// if (targetNews.cover !== noCover && !targetNews.imported) {
|
|
||||||
// let oldPic = `./static${targetNews.cover}`;
|
|
||||||
//
|
|
||||||
// if (await fs.existsSync(oldPic)) {
|
|
||||||
// fs.unlink(oldPic, (err) => {
|
|
||||||
// if (err) return res500(res, err?.message);
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (targetNews.thumbCover !== noCover && !targetNews.imported) {
|
|
||||||
// let oldPic = `./static${targetNews.thumbCover}`;
|
|
||||||
//
|
|
||||||
// if (await fs.existsSync(oldPic)) {
|
|
||||||
// fs.unlink(oldPic, (err) => {
|
|
||||||
// if (err) return res500(res, err?.message);
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
create.managerCover = imageName;
|
create.managerCover = imageName;
|
||||||
await create.save();
|
await create.save();
|
||||||
@@ -461,33 +446,12 @@ module.exports.addCategory = [
|
|||||||
const ext = extname(image.name);
|
const ext = extname(image.name);
|
||||||
const imageName = `shafafiat_icon_${Date.now()}${ext}`;
|
const imageName = `shafafiat_icon_${Date.now()}${ext}`;
|
||||||
try {
|
try {
|
||||||
await image.mv(
|
await uploadShafafiatIcon(
|
||||||
`${process.cwd()}/static/uploads/images/category/shafafiat/${imageName}`
|
image.data,
|
||||||
|
imageName,
|
||||||
|
image.mimetype
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
|
||||||
* if exist old pic delete it from file
|
|
||||||
*/
|
|
||||||
// if (targetNews.cover !== noCover && !targetNews.imported) {
|
|
||||||
// let oldPic = `./static${targetNews.cover}`;
|
|
||||||
//
|
|
||||||
// if (await fs.existsSync(oldPic)) {
|
|
||||||
// fs.unlink(oldPic, (err) => {
|
|
||||||
// if (err) return res500(res, err?.message);
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (targetNews.thumbCover !== noCover && !targetNews.imported) {
|
|
||||||
// let oldPic = `./static${targetNews.thumbCover}`;
|
|
||||||
//
|
|
||||||
// if (await fs.existsSync(oldPic)) {
|
|
||||||
// fs.unlink(oldPic, (err) => {
|
|
||||||
// if (err) return res500(res, err?.message);
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
create.icon = imageName;
|
create.icon = imageName;
|
||||||
await create.save();
|
await create.save();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -812,24 +776,15 @@ module.exports.updateCategory = [
|
|||||||
image.mimetype.split("/")[1]
|
image.mimetype.split("/")[1]
|
||||||
}`;
|
}`;
|
||||||
try {
|
try {
|
||||||
const target = sharp(image.data);
|
await deleteCategoryImage(targetCategory, "managerCover");
|
||||||
await target
|
|
||||||
.resize(coverNewsWidth, coverNewsHeight, { fit: "cover" })
|
|
||||||
.jpeg({ quality: coverQuality })
|
|
||||||
.toFile(`./static/uploads/images/category/${imageName}`);
|
|
||||||
|
|
||||||
/**
|
await uploadProcessedImage(
|
||||||
* if exist old pic delete it from file
|
image.data,
|
||||||
*/
|
imageName,
|
||||||
if (targetCategory.managerCover !== noCover) {
|
coverNewsWidth,
|
||||||
let oldPic = `./static${targetCategory.managerCover}`;
|
coverNewsHeight,
|
||||||
|
coverQuality
|
||||||
if (await fs.existsSync(oldPic)) {
|
);
|
||||||
fs.unlink(oldPic, (err) => {
|
|
||||||
if (err) return res500(res, err?.message);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
targetCategory.managerCover = imageName;
|
targetCategory.managerCover = imageName;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -839,7 +794,6 @@ module.exports.updateCategory = [
|
|||||||
|
|
||||||
if (req.files?.icon) {
|
if (req.files?.icon) {
|
||||||
const image = req.files.icon;
|
const image = req.files.icon;
|
||||||
console.log(image);
|
|
||||||
if (!_sr.supportedImageFormats.includes(image.mimetype.split("/")[1])) {
|
if (!_sr.supportedImageFormats.includes(image.mimetype.split("/")[1])) {
|
||||||
return res.status(422).json({
|
return res.status(422).json({
|
||||||
validation: {
|
validation: {
|
||||||
@@ -852,30 +806,17 @@ module.exports.updateCategory = [
|
|||||||
const ext = extname(image.name);
|
const ext = extname(image.name);
|
||||||
const imageName = `shafafiat_icon_${Date.now()}${ext}`;
|
const imageName = `shafafiat_icon_${Date.now()}${ext}`;
|
||||||
try {
|
try {
|
||||||
await image.mv(
|
await deleteShafafiatIcon(
|
||||||
`${process.cwd()}/static/uploads/images/category/shafafiat/${imageName}`
|
getStoredImageName(targetCategory, "icon")
|
||||||
);
|
);
|
||||||
// const target = sharp(image.data)
|
|
||||||
// await target
|
|
||||||
// .resize(coverNewsWidth, coverNewsHeight, {fit: 'cover'})
|
|
||||||
// .jpeg({quality: coverQuality})
|
|
||||||
// .toFile(`./static/uploads/images/category/shafafiat/${imageName}`);
|
|
||||||
|
|
||||||
/**
|
await uploadShafafiatIcon(
|
||||||
* if exist old pic delete it from file
|
image.data,
|
||||||
*/
|
imageName,
|
||||||
if (targetCategory.icon !== noCover) {
|
image.mimetype
|
||||||
let oldPic = `./static${targetCategory.icon}`;
|
);
|
||||||
|
|
||||||
if (await fs.existsSync(oldPic)) {
|
|
||||||
fs.unlink(oldPic, (err) => {
|
|
||||||
if (err) return res500(res, err?.message);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
targetCategory.icon = imageName;
|
targetCategory.icon = imageName;
|
||||||
console.log(targetCategory);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return res500(res, e?.message);
|
return res500(res, e?.message);
|
||||||
}
|
}
|
||||||
@@ -1223,7 +1164,8 @@ module.exports.getParent = [
|
|||||||
module.exports.addTermsFileToCategory = [
|
module.exports.addTermsFileToCategory = [
|
||||||
[body("termsTitle").notEmpty().withMessage(_sr["fa"].required.title)],
|
[body("termsTitle").notEmpty().withMessage(_sr["fa"].required.title)],
|
||||||
checkValidations(validationResult),
|
checkValidations(validationResult),
|
||||||
(req, res) => {
|
async (req, res) => {
|
||||||
|
try {
|
||||||
if (!req.files?.file)
|
if (!req.files?.file)
|
||||||
return res
|
return res
|
||||||
.status(422)
|
.status(422)
|
||||||
@@ -1233,42 +1175,48 @@ module.exports.addTermsFileToCategory = [
|
|||||||
.status(422)
|
.status(422)
|
||||||
.json({ validation: { file: { msg: "فقط فرمت PDF قابل قبول است" } } });
|
.json({ validation: { file: { msg: "فقط فرمت PDF قابل قبول است" } } });
|
||||||
|
|
||||||
const data = { title: req.body.termsTitle };
|
const category = await Category.findById(req.params.categoryId);
|
||||||
const file = req.files.file;
|
if (!category) return res404(res, "category not found");
|
||||||
|
|
||||||
const fileName =
|
const fileName =
|
||||||
req.body.termsTitle.replace(titleFilterRegex, "-") +
|
req.body.termsTitle.replace(titleFilterRegex, "-") +
|
||||||
"_" +
|
"_" +
|
||||||
Date.now() +
|
Date.now() +
|
||||||
".pdf";
|
".pdf";
|
||||||
file.mv(`./static/uploads/files/terms/${fileName}`);
|
|
||||||
data.file = fileName;
|
|
||||||
|
|
||||||
Category.findById(req.params.categoryId, (err, category) => {
|
await uploadTermsFile(req.files.file.data, fileName);
|
||||||
if (err || !category) return res404(res, err);
|
|
||||||
category.terms.push(data);
|
category.terms.push({
|
||||||
category.save((err) => {
|
title: req.body.termsTitle,
|
||||||
if (err) return res500(res, err);
|
file: fileName,
|
||||||
else return res.json({ message: _sr["fa"].response.success_save });
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
await category.save();
|
||||||
|
|
||||||
|
return res.json({ message: _sr["fa"].response.success_save });
|
||||||
|
} catch (err) {
|
||||||
|
return res500(res, err);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
module.exports.removeTermsFileFromCategory = [
|
module.exports.removeTermsFileFromCategory = [
|
||||||
(req, res) => {
|
async (req, res) => {
|
||||||
Category.findOne({ "terms._id": req.params.fileId }, (err, category) => {
|
try {
|
||||||
if (err || !category) return res404(res, err);
|
const category = await Category.findOne({ "terms._id": req.params.fileId });
|
||||||
const file = category.terms.id(req.params.fileId);
|
if (!category) return res404(res, "not found");
|
||||||
if (!file) return res404(res, "not found");
|
|
||||||
file.remove();
|
const termsFile = category.terms.id(req.params.fileId);
|
||||||
fs.unlink(`./static/${file.file}`, (err) => {
|
if (!termsFile) return res404(res, "not found");
|
||||||
if (err) console.log(err);
|
|
||||||
});
|
const fileName = getStoredImageName(termsFile, "file");
|
||||||
category.save((err) => {
|
termsFile.remove();
|
||||||
if (err) return res500(res, err);
|
await deleteTermsFile(fileName);
|
||||||
else return res.json({ message: _sr["fa"].response.success_remove });
|
await category.save();
|
||||||
});
|
|
||||||
});
|
return res.json({ message: _sr["fa"].response.success_remove });
|
||||||
|
} catch (err) {
|
||||||
|
return res500(res, err);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
const {body, validationResult} = require('express-validator');
|
const {body, validationResult} = require('express-validator');
|
||||||
const sharp = require('sharp');
|
|
||||||
const {_sr} = require('../plugins/serverResponses');
|
const {_sr} = require('../plugins/serverResponses');
|
||||||
const {res404, res500, hasWhiteSpaces, isLatinCharactersWithSymbol, generateRandomDigits} = require('../plugins/controllersHelperFunctions');
|
const {res404, res500, hasWhiteSpaces, isLatinCharactersWithSymbol, generateRandomDigits} = require('../plugins/controllersHelperFunctions');
|
||||||
const Content = require('../models/Content');
|
const Content = require('../models/Content');
|
||||||
const fs = require('fs');
|
const {
|
||||||
|
deleteContentImages,
|
||||||
|
uploadProcessedImage,
|
||||||
|
} = require('../plugins/contentImageStorage');
|
||||||
|
|
||||||
|
|
||||||
////// variables
|
////// variables
|
||||||
@@ -85,26 +87,23 @@ module.exports.addContent = [
|
|||||||
const imageName = `manager_${Date.now()}_${create._id}.${image.mimetype.split('/')[1]}`;
|
const imageName = `manager_${Date.now()}_${create._id}.${image.mimetype.split('/')[1]}`;
|
||||||
const thumbName = 'thumb_' + imageName
|
const thumbName = 'thumb_' + imageName
|
||||||
try {
|
try {
|
||||||
const target = sharp(image.data)
|
await uploadProcessedImage(
|
||||||
await target
|
image.data,
|
||||||
.resize(profileWidth, profileHeight, {
|
imageName,
|
||||||
fit: 'cover'
|
profileWidth,
|
||||||
})
|
profileHeight,
|
||||||
.jpeg({
|
profileQuality
|
||||||
quality: profileQuality
|
);
|
||||||
})
|
await uploadProcessedImage(
|
||||||
.toFile(`./static/uploads/images/content/${imageName}`)
|
image.data,
|
||||||
await target
|
thumbName,
|
||||||
.resize(profileThumbWidth, profileThumbHeight, {
|
profileThumbWidth,
|
||||||
fit: 'cover'
|
profileThumbHeight,
|
||||||
})
|
profileThumbQuality
|
||||||
.jpeg({
|
);
|
||||||
quality: profileThumbQuality
|
|
||||||
})
|
|
||||||
.toFile(`./static/uploads/images/content/${thumbName}`)
|
|
||||||
|
|
||||||
create.cover = imageName;
|
create.cover = imageName;
|
||||||
create.thumb = imageName;
|
create.thumb = thumbName;
|
||||||
|
|
||||||
await create.save();
|
await create.save();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -180,42 +179,22 @@ module.exports.updateContent = [
|
|||||||
const imageName = `manager_${Date.now()}_${targetContent._id}.${image.mimetype.split('/')[1]}`;
|
const imageName = `manager_${Date.now()}_${targetContent._id}.${image.mimetype.split('/')[1]}`;
|
||||||
const thumbName = 'thumb_' + imageName
|
const thumbName = 'thumb_' + imageName
|
||||||
try {
|
try {
|
||||||
const target = sharp(image.data)
|
await deleteContentImages(targetContent);
|
||||||
await target
|
|
||||||
.resize(profileWidth, profileHeight, {
|
|
||||||
fit: 'cover'
|
|
||||||
})
|
|
||||||
.jpeg({
|
|
||||||
quality: profileQuality
|
|
||||||
})
|
|
||||||
.toFile(`./static/uploads/images/content/${imageName}`)
|
|
||||||
await target
|
|
||||||
.resize(profileThumbWidth, profileThumbHeight, {
|
|
||||||
fit: 'cover'
|
|
||||||
})
|
|
||||||
.jpeg({
|
|
||||||
quality: profileThumbQuality
|
|
||||||
})
|
|
||||||
.toFile(`./static/uploads/images/content/${thumbName}`)
|
|
||||||
|
|
||||||
/**
|
await uploadProcessedImage(
|
||||||
* if exist old pic delete it from file
|
image.data,
|
||||||
*/
|
imageName,
|
||||||
if (targetContent.cover) {
|
profileWidth,
|
||||||
const oldPic = `./static${targetContent.cover}`
|
profileHeight,
|
||||||
const oldThumb = `./static${targetContent.thumb}`
|
profileQuality
|
||||||
|
);
|
||||||
if (fs.existsSync(oldPic)) {
|
await uploadProcessedImage(
|
||||||
fs.unlink(oldPic, (err) => {
|
image.data,
|
||||||
if (err) return res500(res, err?.message);
|
thumbName,
|
||||||
});
|
profileThumbWidth,
|
||||||
}
|
profileThumbHeight,
|
||||||
if (fs.existsSync(oldThumb)) {
|
profileThumbQuality
|
||||||
fs.unlink(oldThumb, (err) => {
|
);
|
||||||
if (err) return res500(res, err?.message);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
targetContent.cover = imageName;
|
targetContent.cover = imageName;
|
||||||
targetContent.thumb = thumbName;
|
targetContent.thumb = thumbName;
|
||||||
|
|||||||
@@ -1,9 +1,15 @@
|
|||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
|
const {PassThrough} = require('stream')
|
||||||
const archiver = require('archiver')
|
const archiver = require('archiver')
|
||||||
const moment = require('moment')
|
const moment = require('moment')
|
||||||
const jwt = require('jsonwebtoken')
|
const jwt = require('jsonwebtoken')
|
||||||
const {secretKey} = require('../authentication')
|
const {secretKey} = require('../authentication')
|
||||||
const {_sr} = require('../plugins/serverResponses')
|
const {_sr} = require('../plugins/serverResponses')
|
||||||
|
const {
|
||||||
|
appendS3UploadsToArchive,
|
||||||
|
uploadBackupArchive,
|
||||||
|
deleteOldBackups,
|
||||||
|
} = require('../plugins/backupStorage')
|
||||||
// models
|
// models
|
||||||
const Category = require('../models/Category')
|
const Category = require('../models/Category')
|
||||||
const Comment = require('../models/Comment')
|
const Comment = require('../models/Comment')
|
||||||
@@ -21,6 +27,8 @@ const Slider = require('../models/Slider')
|
|||||||
const User = require('../models/User')
|
const User = require('../models/User')
|
||||||
const YearBanner = require('../models/YearBanner')
|
const YearBanner = require('../models/YearBanner')
|
||||||
|
|
||||||
|
const hostFullError = '<h1 style="margin-top: 150px;text-align: center;direction: rtl;color: red;">فضای هاست پر میباشد.لطفا نسبت به پاک کردن بکاپ های قبلی یا افزایش فضای هاست اقدام فرمایید.</h1>'
|
||||||
|
|
||||||
module.exports.createBackUp = [
|
module.exports.createBackUp = [
|
||||||
// check user token and permission to backup
|
// check user token and permission to backup
|
||||||
async (req, res, next) => {
|
async (req, res, next) => {
|
||||||
@@ -85,86 +93,72 @@ module.exports.createBackUp = [
|
|||||||
|
|
||||||
const [categories, comments, contactus, contents, galleries, homepage, links, meetings, news, newsFiles, services, sliders, users, yearBanner, occasion] = await Promise.all(dataBaseQueries)
|
const [categories, comments, contactus, contents, galleries, homepage, links, meetings, news, newsFiles, services, sliders, users, yearBanner, occasion] = await Promise.all(dataBaseQueries)
|
||||||
|
|
||||||
if (await !fs.existsSync('./backup/database')) await fs.mkdirSync('./backup/database')
|
const dateStr = moment(Date.now()).format('YYYY-MM-DD')
|
||||||
|
const backupName = `backup_${dateStr}.zip`
|
||||||
await Promise.all([
|
|
||||||
fs.writeFileSync(`./backup/database/categories_${moment(Date.now()).format('YYYY-MM-DD')}.json`, JSON.stringify(categories)),
|
|
||||||
fs.writeFileSync(`./backup/database/comments_${moment(Date.now()).format('YYYY-MM-DD')}.json`, JSON.stringify(comments)),
|
|
||||||
fs.writeFileSync(`./backup/database/contactus_${moment(Date.now()).format('YYYY-MM-DD')}.json`, JSON.stringify(contactus)),
|
|
||||||
fs.writeFileSync(`./backup/database/contents_${moment(Date.now()).format('YYYY-MM-DD')}.json`, JSON.stringify(contents)),
|
|
||||||
fs.writeFileSync(`./backup/database/galleries_${moment(Date.now()).format('YYYY-MM-DD')}.json`, JSON.stringify(galleries)),
|
|
||||||
fs.writeFileSync(`./backup/database/homepage_${moment(Date.now()).format('YYYY-MM-DD')}.json`, JSON.stringify(homepage)),
|
|
||||||
fs.writeFileSync(`./backup/database/links_${moment(Date.now()).format('YYYY-MM-DD')}.json`, JSON.stringify(links)),
|
|
||||||
fs.writeFileSync(`./backup/database/meetings_${moment(Date.now()).format('YYYY-MM-DD')}.json`, JSON.stringify(meetings)),
|
|
||||||
fs.writeFileSync(`./backup/database/news_${moment(Date.now()).format('YYYY-MM-DD')}.json`, JSON.stringify(news)),
|
|
||||||
fs.writeFileSync(`./backup/database/newsFiles_${moment(Date.now()).format('YYYY-MM-DD')}.json`, JSON.stringify(newsFiles)),
|
|
||||||
fs.writeFileSync(`./backup/database/services_${moment(Date.now()).format('YYYY-MM-DD')}.json`, JSON.stringify(services)),
|
|
||||||
fs.writeFileSync(`./backup/database/sliders_${moment(Date.now()).format('YYYY-MM-DD')}.json`, JSON.stringify(sliders)),
|
|
||||||
fs.writeFileSync(`./backup/database/users_${moment(Date.now()).format('YYYY-MM-DD')}.json`, JSON.stringify(users)),
|
|
||||||
fs.writeFileSync(`./backup/database/yearBanner_${moment(Date.now()).format('YYYY-MM-DD')}.json`, JSON.stringify(yearBanner)),
|
|
||||||
fs.writeFileSync(`./backup/database/occasion_${moment(Date.now()).format('YYYY-MM-DD')}.json`, JSON.stringify(occasion))
|
|
||||||
])
|
|
||||||
|
|
||||||
/////////////////// create backup zip file
|
|
||||||
|
|
||||||
const backupName = 'backup_' + moment(Date.now()).format('YYYY-MM-DD') + '.zip'
|
|
||||||
// create a file to stream archive data to.
|
|
||||||
const output = fs.createWriteStream(`./backup/${backupName}`)
|
|
||||||
const archive = archiver('zip', {
|
const archive = archiver('zip', {
|
||||||
zlib: {level: 9} // Sets the compression level.
|
zlib: {level: 9}
|
||||||
})
|
})
|
||||||
|
const output = new PassThrough()
|
||||||
|
const chunks = []
|
||||||
|
|
||||||
|
output.on('data', (chunk) => chunks.push(chunk))
|
||||||
|
|
||||||
// listen for all archive data to be written
|
|
||||||
// 'close' event is fired only when a file descriptor is involved
|
|
||||||
output.on('close', function () {
|
|
||||||
console.log(archive.pointer() + ' total bytes')
|
|
||||||
console.log('archiver has been finalized and the output file descriptor has closed.')
|
|
||||||
return res.download(`./backup/${backupName}`)
|
|
||||||
})
|
|
||||||
|
|
||||||
// This event is fired when the data source is drained no matter what was the data source.
|
|
||||||
// It is not part of this library but rather from the NodeJS Stream API.
|
|
||||||
// @see: https://nodejs.org/api/stream.html#stream_event_end
|
|
||||||
output.on('end', function () {
|
|
||||||
console.log('Data has been drained')
|
|
||||||
return res.status(500).send('<h1 style="margin-top: 150px;text-align: center;direction: rtl;color: red;">فضای هاست پر میباشد.لطفا نسبت به پاک کردن بکاپ های قبلی یا افزایش فضای هاست اقدام فرمایید.</h1>')
|
|
||||||
})
|
|
||||||
|
|
||||||
// good practice to catch warnings (ie stat failures and other non-blocking errors)
|
|
||||||
archive.on('warning', function (err) {
|
archive.on('warning', function (err) {
|
||||||
|
|
||||||
if (err.code === 'ENOENT') {
|
if (err.code === 'ENOENT') {
|
||||||
// log warning
|
|
||||||
console.log('On archiver warning -- ENOENT error code', err)
|
console.log('On archiver warning -- ENOENT error code', err)
|
||||||
} else {
|
} else {
|
||||||
// throw error
|
|
||||||
console.log('On archiver warning -- other error codes ', err)
|
console.log('On archiver warning -- other error codes ', err)
|
||||||
}
|
}
|
||||||
return res.status(500).send('<h1 style="margin-top: 150px;text-align: center;direction: rtl;color: red;">فضای هاست پر میباشد.لطفا نسبت به پاک کردن بکاپ های قبلی یا افزایش فضای هاست اقدام فرمایید.</h1>')
|
return res.status(500).send(hostFullError)
|
||||||
})
|
})
|
||||||
|
|
||||||
// good practice to catch this error explicitly
|
|
||||||
archive.on('error', function (err) {
|
archive.on('error', function (err) {
|
||||||
// throw err
|
|
||||||
console.log(err)
|
console.log(err)
|
||||||
return res.status(500).json({message: 'مشکلی پیش آمده'})
|
return res.status(500).json({message: 'مشکلی پیش آمده'})
|
||||||
})
|
})
|
||||||
|
|
||||||
// pipe archive data to the file
|
archive.pipe(output)
|
||||||
await archive.pipe(output)
|
|
||||||
|
|
||||||
// append files from a sub-directory and naming it `new-subdir` within the archive
|
const databaseExports = [
|
||||||
await archive.directory(`./static/uploads/`, 'uploads')
|
['categories', categories],
|
||||||
await archive.directory(`./backup/database/`, 'database')
|
['comments', comments],
|
||||||
|
['contactus', contactus],
|
||||||
|
['contents', contents],
|
||||||
|
['galleries', galleries],
|
||||||
|
['homepage', homepage],
|
||||||
|
['links', links],
|
||||||
|
['meetings', meetings],
|
||||||
|
['news', news],
|
||||||
|
['newsFiles', newsFiles],
|
||||||
|
['services', services],
|
||||||
|
['sliders', sliders],
|
||||||
|
['users', users],
|
||||||
|
['yearBanner', yearBanner],
|
||||||
|
['occasion', occasion],
|
||||||
|
]
|
||||||
|
|
||||||
|
for (const [name, data] of databaseExports) {
|
||||||
|
archive.append(JSON.stringify(data), {name: `database/${name}_${dateStr}.json`})
|
||||||
|
}
|
||||||
|
|
||||||
|
await appendS3UploadsToArchive(archive)
|
||||||
|
|
||||||
// finalize the archive (ie we are done appending files but streams have to finish yet)
|
|
||||||
// 'close', 'end' or 'finish' may be fired right after calling this method so register to them beforehand
|
|
||||||
await archive.finalize()
|
await archive.finalize()
|
||||||
|
|
||||||
await fs.rmdirSync('./backup/database', {recursive: true})
|
await new Promise((resolve, reject) => {
|
||||||
|
output.on('end', resolve)
|
||||||
|
output.on('error', reject)
|
||||||
|
})
|
||||||
|
|
||||||
|
const buffer = Buffer.concat(chunks)
|
||||||
|
|
||||||
|
await uploadBackupArchive(buffer, backupName)
|
||||||
|
|
||||||
|
res.setHeader('Content-Type', 'application/zip')
|
||||||
|
res.setHeader('Content-Disposition', `attachment; filename="${backupName}"`)
|
||||||
|
return res.send(buffer)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return res.status(500).send('<h1 style="margin-top: 150px;text-align: center;direction: rtl;color: red;">فضای هاست پر میباشد.لطفا نسبت به پاک کردن بکاپ های قبلی یا افزایش فضای هاست اقدام فرمایید.</h1>')
|
return res.status(500).send(hostFullError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -173,12 +167,18 @@ module.exports.createBackUp = [
|
|||||||
module.exports.removeOldBackups = [
|
module.exports.removeOldBackups = [
|
||||||
async (req, res) => {
|
async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const files = await fs.readdirSync('./backup')
|
await deleteOldBackups()
|
||||||
for await (const file of files) {
|
|
||||||
const isDirectory = await fs.statSync(`./backup/${file}`).isDirectory()
|
if (fs.existsSync('./backup')) {
|
||||||
if (isDirectory) await fs.rmdirSync(`./backup/${file}`, {recursive: true})
|
const files = fs.readdirSync('./backup')
|
||||||
else await fs.unlinkSync(`./backup/${file}`)
|
for (const file of files) {
|
||||||
|
const filePath = `./backup/${file}`
|
||||||
|
const isDirectory = fs.statSync(filePath).isDirectory()
|
||||||
|
if (isDirectory) fs.rmdirSync(filePath, {recursive: true})
|
||||||
|
else fs.unlinkSync(filePath)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return res.json({message: _sr['fa'].response.success_remove})
|
return res.json({message: _sr['fa'].response.success_remove})
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return res.status(500).json({message: e})
|
return res.status(500).json({message: e})
|
||||||
|
|||||||
@@ -10,8 +10,11 @@ const {
|
|||||||
hasWhiteSpaces,
|
hasWhiteSpaces,
|
||||||
isLatinCharactersWithSymbol
|
isLatinCharactersWithSymbol
|
||||||
} = require('../plugins/controllersHelperFunctions');
|
} = require('../plugins/controllersHelperFunctions');
|
||||||
const fs = require('fs');
|
const {
|
||||||
const sharp = require('sharp');
|
deleteCandidateImage,
|
||||||
|
deleteElectionCandidateImages,
|
||||||
|
uploadProcessedImage,
|
||||||
|
} = require('../plugins/electionImageStorage');
|
||||||
|
|
||||||
////// variables
|
////// variables
|
||||||
const profileWidth = 300;
|
const profileWidth = 300;
|
||||||
@@ -292,17 +295,7 @@ module.exports.deletOneElection = [
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (deleteElection.candidates.length) {
|
if (deleteElection.candidates.length) {
|
||||||
const targetDir = `./static/uploads/images/election/`;
|
await deleteElectionCandidateImages(deleteElection);
|
||||||
|
|
||||||
const getFiles = fs.readdirSync(targetDir);
|
|
||||||
|
|
||||||
for (const file of getFiles) {
|
|
||||||
if (file.includes(deleteElection._id)) {
|
|
||||||
fs.unlink(`./static/uploads/images/election/${file}`, (err) => {
|
|
||||||
if (err) console.log(err)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await deleteElection.deleteOne();
|
await deleteElection.deleteOne();
|
||||||
@@ -457,16 +450,13 @@ module.exports.addCandidate = [
|
|||||||
}
|
}
|
||||||
const imageName = 'candidate_' + Date.now() + '_' + targetElection._id + '.jpg';
|
const imageName = 'candidate_' + Date.now() + '_' + targetElection._id + '.jpg';
|
||||||
data.profilePic = imageName;
|
data.profilePic = imageName;
|
||||||
const target = sharp(image.data)
|
await uploadProcessedImage(
|
||||||
await target
|
image.data,
|
||||||
.resize(profileWidth, profileHeight, {
|
imageName,
|
||||||
fit: 'cover'
|
profileWidth,
|
||||||
})
|
profileHeight,
|
||||||
.toFormat('jpg')
|
profileQuality
|
||||||
.jpeg({
|
);
|
||||||
quality: profileQuality
|
|
||||||
})
|
|
||||||
.toFile(`./static/uploads/images/election/${imageName}`)
|
|
||||||
|
|
||||||
|
|
||||||
targetElection.candidates.push(data);
|
targetElection.candidates.push(data);
|
||||||
@@ -528,29 +518,16 @@ module.exports.updateCandidate = [
|
|||||||
return res.status(422).json({validation: {profilePic: {msg: _sr['fa'].format.image}}});
|
return res.status(422).json({validation: {profilePic: {msg: _sr['fa'].format.image}}});
|
||||||
}
|
}
|
||||||
const imageName = 'candidate_' + Date.now() + '_' + targetElection._id + '.jpg';
|
const imageName = 'candidate_' + Date.now() + '_' + targetElection._id + '.jpg';
|
||||||
const target = sharp(image.data)
|
await deleteCandidateImage(candidate);
|
||||||
await target
|
|
||||||
.resize(profileWidth, profileHeight, {
|
|
||||||
fit: 'cover'
|
|
||||||
})
|
|
||||||
.toFormat('jpg')
|
|
||||||
.jpeg({
|
|
||||||
quality: profileQuality
|
|
||||||
})
|
|
||||||
.toFile(`./static/uploads/images/election/${imageName}`)
|
|
||||||
|
|
||||||
/**
|
await uploadProcessedImage(
|
||||||
* if exist old pic delete it from file
|
image.data,
|
||||||
*/
|
imageName,
|
||||||
if (candidate.profilePic) {
|
profileWidth,
|
||||||
const oldPic = `./static${candidate.profilePic}`;
|
profileHeight,
|
||||||
|
profileQuality
|
||||||
|
);
|
||||||
|
|
||||||
if (fs.existsSync(oldPic)) {
|
|
||||||
fs.unlink(oldPic, (err) => {
|
|
||||||
if (err) return res500(res, err?.message);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
candidate.profilePic = imageName;
|
candidate.profilePic = imageName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -586,15 +563,7 @@ module.exports.deleteCandidate = [
|
|||||||
|
|
||||||
if (!candidate) return res404(res, `کاندید مورد نظر پیدا نشد`);
|
if (!candidate) return res404(res, `کاندید مورد نظر پیدا نشد`);
|
||||||
|
|
||||||
if (candidate.profilePic) {
|
await deleteCandidateImage(candidate);
|
||||||
const oldPic = `./static${candidate.profilePic}`;
|
|
||||||
|
|
||||||
if (fs.existsSync(oldPic)) {
|
|
||||||
fs.unlink(oldPic, (err) => {
|
|
||||||
if (err) return res500(res, err?.message);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
await targetElection.candidates.id(candidateId).remove();
|
await targetElection.candidates.id(candidateId).remove();
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,20 @@
|
|||||||
const Gallery = require("../models/Gallery");
|
const Gallery = require("../models/Gallery");
|
||||||
const { body, validationResult } = require("express-validator");
|
const { body, validationResult } = require("express-validator");
|
||||||
const sharp = require("sharp");
|
|
||||||
const crypto = require("crypto");
|
const crypto = require("crypto");
|
||||||
const { _sr } = require("../plugins/serverResponses");
|
const { _sr } = require("../plugins/serverResponses");
|
||||||
const { res404, res500 } = require("../plugins/controllersHelperFunctions");
|
const { res404, res500 } = require("../plugins/controllersHelperFunctions");
|
||||||
const fs = require("fs");
|
|
||||||
const moment = require("moment-jalaali");
|
const moment = require("moment-jalaali");
|
||||||
const Category = require("./../models/Category");
|
const Category = require("./../models/Category");
|
||||||
|
const {
|
||||||
|
deleteGalleryFile,
|
||||||
|
uploadGalleryFile,
|
||||||
|
uploadProcessedImage,
|
||||||
|
deleteAllGalleryFiles,
|
||||||
|
deleteGalleryCover,
|
||||||
|
getStoredFileName,
|
||||||
|
getStoredArray,
|
||||||
|
GALLERY_IMAGE_PREFIX,
|
||||||
|
} = require("../plugins/galleryImageStorage");
|
||||||
|
|
||||||
////// variables
|
////// variables
|
||||||
const picsWidth = 1920;
|
const picsWidth = 1920;
|
||||||
@@ -45,139 +53,40 @@ const imageLimit = 2;
|
|||||||
const graphicLimit = 5;
|
const graphicLimit = 5;
|
||||||
const videoLimit = 20;
|
const videoLimit = 20;
|
||||||
////// functions
|
////// functions
|
||||||
const _upload = async (fileType, file, galleryId, Hash) => {
|
const _upload = async (fileType, file, galleryId) => {
|
||||||
try {
|
if (fileType === "graphic") {
|
||||||
const fileName = `gallery_${galleryId}_${Date.now()}.${
|
return uploadGalleryFile("graphic", file, galleryId, {
|
||||||
file.mimetype.split("/")[1]
|
mainQuality: graphicQuality,
|
||||||
}`;
|
thumbWidth: thumbGraphicWidth,
|
||||||
const uploadPath = `./static/uploads/${fileType}s/gallery/${fileName}`;
|
thumbHeight: thumbGraphicHeight,
|
||||||
const thumbUploadPath = `./static/uploads/${fileType}s/gallery/thumb_${fileName}`;
|
thumbQuality: thumbGraphicQuality,
|
||||||
|
});
|
||||||
switch (fileType) {
|
|
||||||
case "image":
|
|
||||||
try {
|
|
||||||
const target = sharp(file.data);
|
|
||||||
await target
|
|
||||||
.resize(picsWidth, picsHeight, {
|
|
||||||
fit: "cover",
|
|
||||||
})
|
|
||||||
.toFormat("jpg")
|
|
||||||
.jpeg({
|
|
||||||
quality: picsQuality,
|
|
||||||
})
|
|
||||||
.toFile(uploadPath);
|
|
||||||
|
|
||||||
await target
|
|
||||||
.resize(thumbPicsWidth, thumbPicsHeight, {
|
|
||||||
fit: "cover",
|
|
||||||
})
|
|
||||||
.toFormat("jpg")
|
|
||||||
.jpeg({
|
|
||||||
quality: thumbPicsQuality,
|
|
||||||
})
|
|
||||||
.toFile(thumbUploadPath);
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "graphic":
|
|
||||||
try {
|
|
||||||
const target = sharp(file.data);
|
|
||||||
await target
|
|
||||||
// .resize(graphicWidth, graphicHeight, {
|
|
||||||
// fit: 'cover'
|
|
||||||
// })
|
|
||||||
.toFormat("jpg")
|
|
||||||
.jpeg({
|
|
||||||
quality: graphicQuality,
|
|
||||||
})
|
|
||||||
.toFile(uploadPath);
|
|
||||||
|
|
||||||
await target
|
|
||||||
.resize(thumbGraphicWidth, thumbGraphicHeight, {
|
|
||||||
fit: "cover",
|
|
||||||
})
|
|
||||||
.toFormat("jpg")
|
|
||||||
.jpeg({
|
|
||||||
quality: thumbGraphicQuality,
|
|
||||||
})
|
|
||||||
.toFile(thumbUploadPath);
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "video":
|
|
||||||
await file.mv(uploadPath);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return fileName;
|
if (fileType === "video") {
|
||||||
} catch (error) {
|
return uploadGalleryFile("video", file, galleryId, {});
|
||||||
console.log(error);
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return uploadGalleryFile("image", file, galleryId, {
|
||||||
|
mainWidth: picsWidth,
|
||||||
|
mainHeight: picsHeight,
|
||||||
|
mainQuality: picsQuality,
|
||||||
|
thumbWidth: thumbPicsWidth,
|
||||||
|
thumbHeight: thumbPicsHeight,
|
||||||
|
thumbQuality: thumbPicsQuality,
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const _deleteOne = async (fileType, name) => {
|
const _deleteOne = async (fileType, name) => {
|
||||||
try {
|
try {
|
||||||
let targetFile = `./static/uploads/${fileType}s/gallery/${name}`;
|
await deleteGalleryFile(fileType, name);
|
||||||
let thumbTargetFile = `./static/uploads/${fileType}s/gallery/thumb_${name}`;
|
|
||||||
|
|
||||||
if (fs.existsSync(targetFile)) {
|
|
||||||
fs.unlink(targetFile, (err) => {
|
|
||||||
if (err) console.log(err);
|
|
||||||
});
|
|
||||||
if (fileType !== "video") {
|
|
||||||
fs.unlink(thumbTargetFile, (err) => {
|
|
||||||
if (err) console.log(err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return name;
|
return name;
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const _deleteAll = async (galleryId, galleryType) => {
|
|
||||||
try {
|
|
||||||
const targetDir = `./static/uploads/${galleryType}s/gallery/`;
|
|
||||||
|
|
||||||
const getFiles = fs.readdirSync(targetDir);
|
|
||||||
|
|
||||||
for (const file of getFiles) {
|
|
||||||
if (file.includes(galleryId)) {
|
|
||||||
fs.unlink(`./static/uploads/${galleryType}s/gallery/${file}`, (err) => {
|
|
||||||
if (err) console.log(err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const _deleteCover = async (galleryId) => {
|
|
||||||
try {
|
|
||||||
const targetDir = `./static/uploads/images/gallery/`;
|
|
||||||
|
|
||||||
const getFiles = fs.readdirSync(targetDir);
|
|
||||||
|
|
||||||
for (const file of getFiles) {
|
|
||||||
if (file.includes(galleryId) && file.includes("cover")) {
|
|
||||||
fs.unlink(`./static/uploads/images/gallery/${file}`, (err) => {
|
|
||||||
if (err) console.log(err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.log(err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const _randomGallery = async (queryObject) => {
|
const _randomGallery = async (queryObject) => {
|
||||||
let setSkip;
|
let setSkip;
|
||||||
try {
|
try {
|
||||||
@@ -599,7 +508,7 @@ module.exports.updateGallery = [
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (targetGallery.galleryType !== galleryType) {
|
if (targetGallery.galleryType !== galleryType) {
|
||||||
await _deleteAll(targetGallery._id, targetGallery.galleryType);
|
await deleteAllGalleryFiles(targetGallery);
|
||||||
targetGallery.images = [];
|
targetGallery.images = [];
|
||||||
targetGallery.thumbImages = [];
|
targetGallery.thumbImages = [];
|
||||||
targetGallery.video = null;
|
targetGallery.video = null;
|
||||||
@@ -722,8 +631,8 @@ module.exports.deletOneGallery = [
|
|||||||
return res500(res, `شما اجازه پاک کردن این گالری را ندارید`);
|
return res500(res, `شما اجازه پاک کردن این گالری را ندارید`);
|
||||||
}
|
}
|
||||||
|
|
||||||
await _deleteAll(targetGallery._id, targetGallery.galleryType);
|
await deleteAllGalleryFiles(targetGallery);
|
||||||
await _deleteCover(targetGallery._id);
|
await deleteGalleryCover(targetGallery);
|
||||||
|
|
||||||
/** delete gallery */
|
/** delete gallery */
|
||||||
await targetGallery.deleteOne();
|
await targetGallery.deleteOne();
|
||||||
@@ -1037,27 +946,20 @@ module.exports.uploadPDF = [
|
|||||||
targetGallery.thumbImages.push(`thumb_${fileName}`);
|
targetGallery.thumbImages.push(`thumb_${fileName}`);
|
||||||
break;
|
break;
|
||||||
case "video":
|
case "video":
|
||||||
if (
|
if (getStoredFileName(targetGallery, "video")) {
|
||||||
targetGallery.video &&
|
await deleteGalleryFile(
|
||||||
(await fs.existsSync(`./static/${targetGallery?.video}`))
|
"video",
|
||||||
) {
|
getStoredFileName(targetGallery, "video")
|
||||||
fs.unlink(`./static/${targetGallery.video}`, (err) => {
|
);
|
||||||
if (err) return res.status(500).json({ msg: err.message });
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
targetGallery.video = fileName;
|
targetGallery.video = fileName;
|
||||||
break;
|
break;
|
||||||
case "graphic":
|
case "graphic":
|
||||||
if (
|
if (getStoredFileName(targetGallery, "graphic")) {
|
||||||
targetGallery.graphic &&
|
await deleteGalleryFile(
|
||||||
(await fs.existsSync(`./static/${targetGallery?.graphic}`))
|
"graphic",
|
||||||
) {
|
getStoredFileName(targetGallery, "graphic")
|
||||||
fs.unlink(`./static/${targetGallery.graphic}`, (err) => {
|
);
|
||||||
if (err) return res.status(500).json({ msg: err.message });
|
|
||||||
});
|
|
||||||
fs.unlink(`./static/${targetGallery.thumbGraphic}`, (err) => {
|
|
||||||
if (err) return res.status(500).json({ msg: err.message });
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
targetGallery.graphic = fileName;
|
targetGallery.graphic = fileName;
|
||||||
targetGallery.thumbGraphic = `thumb_${fileName}`;
|
targetGallery.thumbGraphic = `thumb_${fileName}`;
|
||||||
@@ -1130,9 +1032,7 @@ module.exports.uploadFile = [
|
|||||||
return res.status(404).json({ msg: `گالری پیدا نشد` });
|
return res.status(404).json({ msg: `گالری پیدا نشد` });
|
||||||
}
|
}
|
||||||
|
|
||||||
const Hash = targetGallery.uidImage.map((path) =>
|
const Hash = getStoredArray(targetGallery, "uidImage");
|
||||||
path.replace("/uploads/images/gallery/", "")
|
|
||||||
);
|
|
||||||
if (Hash.includes(fileHash)) {
|
if (Hash.includes(fileHash)) {
|
||||||
return res.status(200).json({ msg: `این فایل قبلا بارگذاری شده` });
|
return res.status(200).json({ msg: `این فایل قبلا بارگذاری شده` });
|
||||||
}
|
}
|
||||||
@@ -1206,27 +1106,20 @@ module.exports.uploadFile = [
|
|||||||
targetGallery.thumbImages.push(`thumb_${fileName}`);
|
targetGallery.thumbImages.push(`thumb_${fileName}`);
|
||||||
break;
|
break;
|
||||||
case "video":
|
case "video":
|
||||||
if (
|
if (getStoredFileName(targetGallery, "video")) {
|
||||||
targetGallery.video &&
|
await deleteGalleryFile(
|
||||||
(await fs.existsSync(`./static/${targetGallery?.video}`))
|
"video",
|
||||||
) {
|
getStoredFileName(targetGallery, "video")
|
||||||
fs.unlink(`./static/${targetGallery.video}`, (err) => {
|
);
|
||||||
if (err) return res.status(500).json({ msg: err.message });
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
targetGallery.video = fileName;
|
targetGallery.video = fileName;
|
||||||
break;
|
break;
|
||||||
case "graphic":
|
case "graphic":
|
||||||
if (
|
if (getStoredFileName(targetGallery, "graphic")) {
|
||||||
targetGallery.graphic &&
|
await deleteGalleryFile(
|
||||||
(await fs.existsSync(`./static/${targetGallery?.graphic}`))
|
"graphic",
|
||||||
) {
|
getStoredFileName(targetGallery, "graphic")
|
||||||
fs.unlink(`./static/${targetGallery.graphic}`, (err) => {
|
);
|
||||||
if (err) return res.status(500).json({ msg: err.message });
|
|
||||||
});
|
|
||||||
fs.unlink(`./static/${targetGallery.thumbGraphic}`, (err) => {
|
|
||||||
if (err) return res.status(500).json({ msg: err.message });
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
targetGallery.graphic = fileName;
|
targetGallery.graphic = fileName;
|
||||||
targetGallery.thumbGraphic = `thumb_${fileName}`;
|
targetGallery.thumbGraphic = `thumb_${fileName}`;
|
||||||
@@ -1743,47 +1636,26 @@ module.exports.uploadCover = [
|
|||||||
const imageName = `cover_gallery_${Date.now()}_${targetGallery._id}.jpg`;
|
const imageName = `cover_gallery_${Date.now()}_${targetGallery._id}.jpg`;
|
||||||
const thumbImg = `thumb_${imageName}`;
|
const thumbImg = `thumb_${imageName}`;
|
||||||
try {
|
try {
|
||||||
const target = sharp(file.data);
|
await uploadProcessedImage(
|
||||||
|
file.data,
|
||||||
|
imageName,
|
||||||
|
coverWidth,
|
||||||
|
coverHeight,
|
||||||
|
coverQuality,
|
||||||
|
GALLERY_IMAGE_PREFIX
|
||||||
|
);
|
||||||
|
|
||||||
await target
|
await uploadProcessedImage(
|
||||||
.resize(coverWidth, coverHeight, {
|
file.data,
|
||||||
fit: "cover",
|
thumbImg,
|
||||||
})
|
thumbCoverWidth,
|
||||||
.toFormat("jpg")
|
thumbCoverHeight,
|
||||||
.jpeg({
|
thumbCoverQuality,
|
||||||
quality: coverQuality,
|
GALLERY_IMAGE_PREFIX
|
||||||
})
|
);
|
||||||
.toFile(`./static/uploads/images/gallery/${imageName}`);
|
|
||||||
|
|
||||||
await target
|
if (getStoredFileName(targetGallery, "cover")) {
|
||||||
.resize(thumbCoverWidth, thumbCoverHeight, {
|
await deleteGalleryCover(targetGallery);
|
||||||
fit: "cover",
|
|
||||||
})
|
|
||||||
.toFormat("jpg")
|
|
||||||
.jpeg({
|
|
||||||
quality: thumbCoverQuality,
|
|
||||||
})
|
|
||||||
.toFile(`./static/uploads/images/gallery/${thumbImg}`);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* if exist old pic delete it from file
|
|
||||||
*/
|
|
||||||
if (targetGallery.cover) {
|
|
||||||
let oldPic = `./static/uploads/images/gallery/${targetGallery.cover}`;
|
|
||||||
if (fs.existsSync(oldPic)) {
|
|
||||||
fs.unlink(oldPic, (err) => {
|
|
||||||
if (err) console.log("Error deleting old cover:", err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (targetGallery.thumbCover) {
|
|
||||||
let oldThumbPic = `./static/uploads/images/gallery/${targetGallery.thumbCover}`;
|
|
||||||
if (fs.existsSync(oldThumbPic)) {
|
|
||||||
fs.unlink(oldThumbPic, (err) => {
|
|
||||||
if (err) console.log("Error deleting old thumb cover:", err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update gallery record with new cover images
|
// Update gallery record with new cover images
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ const {
|
|||||||
body,
|
body,
|
||||||
validationResult
|
validationResult
|
||||||
} = require('express-validator');
|
} = require('express-validator');
|
||||||
const sharp = require('sharp');
|
|
||||||
const {
|
const {
|
||||||
_sr
|
_sr
|
||||||
} = require('../plugins/serverResponses');
|
} = require('../plugins/serverResponses');
|
||||||
@@ -14,7 +13,10 @@ const {
|
|||||||
isLatinCharactersWithSymbol,
|
isLatinCharactersWithSymbol,
|
||||||
generateRandomDigits
|
generateRandomDigits
|
||||||
} = require('../plugins/controllersHelperFunctions');
|
} = require('../plugins/controllersHelperFunctions');
|
||||||
const fs = require('fs');
|
const {
|
||||||
|
deleteLinksImage,
|
||||||
|
uploadProcessedImage,
|
||||||
|
} = require('../plugins/linksImageStorage');
|
||||||
|
|
||||||
////// variables
|
////// variables
|
||||||
const profileWidth = 50;
|
const profileWidth = 50;
|
||||||
@@ -108,15 +110,13 @@ module.exports.addLinks = [
|
|||||||
}
|
}
|
||||||
const imageName = `links_${Date.now()}_${createLinks._id}.${image.mimetype.split('/')[1]}`;
|
const imageName = `links_${Date.now()}_${createLinks._id}.${image.mimetype.split('/')[1]}`;
|
||||||
try {
|
try {
|
||||||
const target = sharp(image.data)
|
await uploadProcessedImage(
|
||||||
await target
|
image.data,
|
||||||
.resize(profileWidth, profileHeight, {
|
imageName,
|
||||||
fit: 'cover'
|
profileWidth,
|
||||||
})
|
profileHeight,
|
||||||
.jpeg({
|
profileQuality
|
||||||
quality: profileQuality
|
);
|
||||||
})
|
|
||||||
.toFile(`./static/uploads/images/links/${imageName}`);
|
|
||||||
|
|
||||||
createLinks.icon = imageName;
|
createLinks.icon = imageName;
|
||||||
|
|
||||||
@@ -243,28 +243,15 @@ module.exports.updateLinks = [
|
|||||||
}
|
}
|
||||||
const imageName = `links_${Date.now()}_${targetLinks._id}.${image.mimetype.split('/')[1]}`;
|
const imageName = `links_${Date.now()}_${targetLinks._id}.${image.mimetype.split('/')[1]}`;
|
||||||
try {
|
try {
|
||||||
const target = sharp(image.data)
|
await deleteLinksImage(targetLinks, 'icon');
|
||||||
await target
|
|
||||||
.resize(profileWidth, profileHeight, {
|
|
||||||
fit: 'cover'
|
|
||||||
})
|
|
||||||
.jpeg({
|
|
||||||
quality: profileQuality
|
|
||||||
})
|
|
||||||
.toFile(`./static/uploads/images/links/${imageName}`);
|
|
||||||
|
|
||||||
/**
|
await uploadProcessedImage(
|
||||||
* if exist old pic delete it from file
|
image.data,
|
||||||
*/
|
imageName,
|
||||||
if (targetLinks.icon) {
|
profileWidth,
|
||||||
var oldPic = `./static${targetLinks.icon}`;
|
profileHeight,
|
||||||
|
profileQuality
|
||||||
if (fs.existsSync(oldPic)) {
|
);
|
||||||
fs.unlink(oldPic, (err) => {
|
|
||||||
if (err) return res500(res, err?.message);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
targetLinks.icon = imageName;
|
targetLinks.icon = imageName;
|
||||||
targetLinks.linksStatus = true;
|
targetLinks.linksStatus = true;
|
||||||
@@ -312,15 +299,7 @@ module.exports.deletOneLinks = [
|
|||||||
return res500(res, `شما اجازه حذف این پیوند را ندارید`);
|
return res500(res, `شما اجازه حذف این پیوند را ندارید`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (targetLinks.icon) {
|
await deleteLinksImage(targetLinks, 'icon');
|
||||||
var oldPic = `./static${targetLinks.icon}`;
|
|
||||||
|
|
||||||
if (fs.existsSync(oldPic)) {
|
|
||||||
fs.unlink(oldPic, (error) => {
|
|
||||||
if (error) return res500(res, error?.message);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** delete links */
|
/** delete links */
|
||||||
await targetLinks.deleteOne();
|
await targetLinks.deleteOne();
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
const News = require("../models/News");
|
const News = require("../models/News");
|
||||||
const { body, validationResult } = require("express-validator");
|
const { body, validationResult } = require("express-validator");
|
||||||
const sharp = require("sharp");
|
|
||||||
const { _sr } = require("../plugins/serverResponses");
|
const { _sr } = require("../plugins/serverResponses");
|
||||||
const {
|
const {
|
||||||
res404,
|
res404,
|
||||||
@@ -10,13 +9,18 @@ const {
|
|||||||
const Category = require("../models/Category");
|
const Category = require("../models/Category");
|
||||||
const Comment = require("../models/Comment");
|
const Comment = require("../models/Comment");
|
||||||
const User = require("../models/User");
|
const User = require("../models/User");
|
||||||
const fs = require("fs");
|
|
||||||
const NewsFile = require("../models/NewsFile");
|
const NewsFile = require("../models/NewsFile");
|
||||||
const Polls = require("../models/Polls");
|
const Polls = require("../models/Polls");
|
||||||
const moment = require("moment-jalaali");
|
const moment = require("moment-jalaali");
|
||||||
|
const {
|
||||||
|
getStoredImageName,
|
||||||
|
deleteNewsImage,
|
||||||
|
deleteNewsAttachment,
|
||||||
|
uploadProcessedImage,
|
||||||
|
uploadNewsAttachment,
|
||||||
|
} = require("../plugins/newsImageStorage");
|
||||||
|
|
||||||
////// variables
|
////// variables
|
||||||
const noCover = "/img/no-cover.jpg";
|
|
||||||
const coverNewsWidth = 1920;
|
const coverNewsWidth = 1920;
|
||||||
const coverNewsHeight = 1080;
|
const coverNewsHeight = 1080;
|
||||||
const coverQuality = 100;
|
const coverQuality = 100;
|
||||||
@@ -111,31 +115,23 @@ const handleFileUploads = async (req, res, targetNews) => {
|
|||||||
|
|
||||||
if (req.files.cover) {
|
if (req.files.cover) {
|
||||||
const image = req.files.cover;
|
const image = req.files.cover;
|
||||||
if (!_sr.supportedImageFormats.includes(image.mimetype.split("/")[1])) {
|
if (!validateNewsImage(image)) {
|
||||||
throw new Error(_sr["fa"].format.image);
|
throw new Error(_sr["fa"].format.image);
|
||||||
}
|
}
|
||||||
|
|
||||||
// حذف کاور قدیمی در صورت وجود
|
await deleteNewsImage(targetNews, "cover");
|
||||||
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}.${
|
const imageName = `news_cover_${timestamp}_${targetNews._id}.${
|
||||||
image.mimetype.split("/")[1]
|
image.mimetype.split("/")[1]
|
||||||
}`;
|
}`;
|
||||||
try {
|
try {
|
||||||
const target = sharp(image.data);
|
await processAndUploadNewsImage(
|
||||||
await target
|
image.data,
|
||||||
.resize(coverNewsWidth, coverNewsHeight, {
|
imageName,
|
||||||
fit: "cover",
|
coverNewsWidth,
|
||||||
})
|
coverNewsHeight,
|
||||||
.jpeg({
|
coverQuality
|
||||||
quality: coverQuality,
|
);
|
||||||
})
|
|
||||||
.toFile(`./static/uploads/images/news/${imageName}`);
|
|
||||||
|
|
||||||
targetNews.cover = imageName;
|
targetNews.cover = imageName;
|
||||||
hasCover = true;
|
hasCover = true;
|
||||||
@@ -143,28 +139,20 @@ const handleFileUploads = async (req, res, targetNews) => {
|
|||||||
throw new Error(e?.message);
|
throw new Error(e?.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
// اگر thumbCover ارسال نشده، از همین تصویر thumbCover بسازیم
|
|
||||||
if (!req.files.thumbCover) {
|
if (!req.files.thumbCover) {
|
||||||
if (targetNews.thumbCover && targetNews.thumbCover !== noCover) {
|
await deleteNewsImage(targetNews, "thumbCover");
|
||||||
const oldThumbPath = `./static/uploads/images/news/${targetNews.thumbCover}`;
|
|
||||||
if (fs.existsSync(oldThumbPath)) {
|
|
||||||
fs.unlinkSync(oldThumbPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const thumbImageName = `news_thumb_${timestamp}_${targetNews._id}.${
|
const thumbImageName = `news_thumb_${timestamp}_${targetNews._id}.${
|
||||||
image.mimetype.split("/")[1]
|
image.mimetype.split("/")[1]
|
||||||
}`;
|
}`;
|
||||||
try {
|
try {
|
||||||
const target = sharp(image.data);
|
await processAndUploadNewsImage(
|
||||||
await target
|
image.data,
|
||||||
.resize(thumbCoverNewsWidth, thumbCoverNewsHeight, {
|
thumbImageName,
|
||||||
fit: "cover",
|
thumbCoverNewsWidth,
|
||||||
})
|
thumbCoverNewsHeight,
|
||||||
.jpeg({
|
thumbCoverQuality
|
||||||
quality: thumbCoverQuality,
|
);
|
||||||
})
|
|
||||||
.toFile(`./static/uploads/images/news/${thumbImageName}`);
|
|
||||||
|
|
||||||
targetNews.thumbCover = thumbImageName;
|
targetNews.thumbCover = thumbImageName;
|
||||||
hasThumb = true;
|
hasThumb = true;
|
||||||
@@ -176,31 +164,23 @@ const handleFileUploads = async (req, res, targetNews) => {
|
|||||||
|
|
||||||
if (req.files.thumbCover) {
|
if (req.files.thumbCover) {
|
||||||
const image = req.files.thumbCover;
|
const image = req.files.thumbCover;
|
||||||
if (!_sr.supportedImageFormats.includes(image.mimetype.split("/")[1])) {
|
if (!validateNewsImage(image)) {
|
||||||
throw new Error(_sr["fa"].format.image);
|
throw new Error(_sr["fa"].format.image);
|
||||||
}
|
}
|
||||||
|
|
||||||
// حذف thumb قدیمی در صورت وجود
|
await deleteNewsImage(targetNews, "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}.${
|
const thumbImageName = `news_thumb_${timestamp}_${targetNews._id}.${
|
||||||
image.mimetype.split("/")[1]
|
image.mimetype.split("/")[1]
|
||||||
}`;
|
}`;
|
||||||
try {
|
try {
|
||||||
const target = sharp(image.data);
|
await processAndUploadNewsImage(
|
||||||
await target
|
image.data,
|
||||||
.resize(thumbCoverNewsWidth, thumbCoverNewsHeight, {
|
thumbImageName,
|
||||||
fit: "cover",
|
thumbCoverNewsWidth,
|
||||||
})
|
thumbCoverNewsHeight,
|
||||||
.jpeg({
|
thumbCoverQuality
|
||||||
quality: thumbCoverQuality,
|
);
|
||||||
})
|
|
||||||
.toFile(`./static/uploads/images/news/${thumbImageName}`);
|
|
||||||
|
|
||||||
targetNews.thumbCover = thumbImageName;
|
targetNews.thumbCover = thumbImageName;
|
||||||
hasThumb = true;
|
hasThumb = true;
|
||||||
@@ -208,28 +188,20 @@ const handleFileUploads = async (req, res, targetNews) => {
|
|||||||
throw new Error(e?.message);
|
throw new Error(e?.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
// اگر cover ارسال نشده، از همین تصویر cover بسازیم
|
|
||||||
if (!req.files.cover) {
|
if (!req.files.cover) {
|
||||||
if (targetNews.cover && targetNews.cover !== noCover) {
|
await deleteNewsImage(targetNews, "cover");
|
||||||
const oldCoverPath = `./static/uploads/images/news/${targetNews.cover}`;
|
|
||||||
if (fs.existsSync(oldCoverPath)) {
|
|
||||||
fs.unlinkSync(oldCoverPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const coverImageName = `news_cover_${timestamp}_${targetNews._id}.${
|
const coverImageName = `news_cover_${timestamp}_${targetNews._id}.${
|
||||||
image.mimetype.split("/")[1]
|
image.mimetype.split("/")[1]
|
||||||
}`;
|
}`;
|
||||||
try {
|
try {
|
||||||
const target = sharp(image.data);
|
await processAndUploadNewsImage(
|
||||||
await target
|
image.data,
|
||||||
.resize(coverNewsWidth, coverNewsHeight, {
|
coverImageName,
|
||||||
fit: "cover",
|
coverNewsWidth,
|
||||||
})
|
coverNewsHeight,
|
||||||
.jpeg({
|
coverQuality
|
||||||
quality: coverQuality,
|
);
|
||||||
})
|
|
||||||
.toFile(`./static/uploads/images/news/${coverImageName}`);
|
|
||||||
|
|
||||||
targetNews.cover = coverImageName;
|
targetNews.cover = coverImageName;
|
||||||
hasCover = true;
|
hasCover = true;
|
||||||
@@ -239,14 +211,24 @@ const handleFileUploads = async (req, res, targetNews) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// بهروزرسانی وضعیت خبر - خبر کامل است اگر حداقل یکی از تصاویر آپلود شده باشد یا قبلاً موجود باشد
|
const currentHasCover = getStoredImageName(targetNews, "cover");
|
||||||
const currentHasCover = targetNews.cover && targetNews.cover !== noCover;
|
const currentHasThumb = getStoredImageName(targetNews, "thumbCover");
|
||||||
const currentHasThumb =
|
|
||||||
targetNews.thumbCover && targetNews.thumbCover !== noCover;
|
|
||||||
targetNews.newsStatus =
|
targetNews.newsStatus =
|
||||||
hasCover || hasThumb || currentHasCover || currentHasThumb;
|
hasCover || hasThumb || currentHasCover || currentHasThumb;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const processAndUploadNewsImage = async (
|
||||||
|
imageData,
|
||||||
|
imageName,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
quality
|
||||||
|
) => uploadProcessedImage(imageData, imageName, width, height, quality);
|
||||||
|
|
||||||
|
const validateNewsImage = (image) => {
|
||||||
|
return _sr.supportedImageFormats.includes(image.mimetype.split("/")[1]);
|
||||||
|
};
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////// admin
|
/////////////////////////////////////////////////////////////////////// admin
|
||||||
module.exports.addNews = [
|
module.exports.addNews = [
|
||||||
[
|
[
|
||||||
@@ -482,127 +464,16 @@ module.exports.addNews = [
|
|||||||
* if we have pic upload to server
|
* if we have pic upload to server
|
||||||
*/
|
*/
|
||||||
if (req.files) {
|
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 {
|
try {
|
||||||
const target = sharp(image.data);
|
await handleFileUploads(req, res, createNews);
|
||||||
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();
|
await createNews.save();
|
||||||
|
} catch (error) {
|
||||||
|
return res.status(422).json({
|
||||||
|
validation: {
|
||||||
|
cover: { msg: error.message },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -987,30 +858,18 @@ module.exports.deletOneNews = [
|
|||||||
return res500(res, `شما اجازه حذف این خبر را ندارید`);
|
return res500(res, `شما اجازه حذف این خبر را ندارید`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (targetNews.cover !== noCover) {
|
await deleteNewsImage(targetNews, "cover");
|
||||||
oldPic = `./static${targetNews.cover}`;
|
await deleteNewsImage(targetNews, "thumbCover");
|
||||||
|
|
||||||
if (fs.existsSync(oldPic)) {
|
for (const attachment of targetNews.attachments) {
|
||||||
fs.unlink(oldPic, (error) => {
|
const fileName = attachment.get("file", null, { getters: false });
|
||||||
if (error) return res500(res, error?.message);
|
await deleteNewsAttachment(fileName);
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 targetNews.deleteOne();
|
||||||
|
|
||||||
await Comment.deleteMany({ modelRef: targetNews._id });
|
await Comment.deleteMany({ modelRef: targetNews._id });
|
||||||
x;
|
|
||||||
return res.json(targetNews);
|
return res.json(targetNews);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return res500(res, error);
|
return res500(res, error);
|
||||||
@@ -1021,13 +880,22 @@ module.exports.deletOneNews = [
|
|||||||
module.exports.deleteAllNews = [
|
module.exports.deleteAllNews = [
|
||||||
async (req, res) => {
|
async (req, res) => {
|
||||||
try {
|
try {
|
||||||
|
const importedNews = await News.find({ imported: true });
|
||||||
|
|
||||||
|
for (const news of importedNews) {
|
||||||
|
await deleteNewsImage(news, "cover");
|
||||||
|
await deleteNewsImage(news, "thumbCover");
|
||||||
|
|
||||||
|
for (const attachment of news.attachments) {
|
||||||
|
const fileName = attachment.get("file", null, { getters: false });
|
||||||
|
await deleteNewsAttachment(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
await News.deleteMany({ imported: true });
|
await News.deleteMany({ imported: true });
|
||||||
|
|
||||||
return res.json("ok");
|
return res.json("ok");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
/**
|
|
||||||
* if we got unkown error show to client
|
|
||||||
*/
|
|
||||||
return res500(res, error.message);
|
return res500(res, error.message);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -1322,52 +1190,65 @@ module.exports.searchForSlider = [
|
|||||||
module.exports.addAttachmentToNews = [
|
module.exports.addAttachmentToNews = [
|
||||||
[body("attTitle").notEmpty().withMessage(_sr["fa"].required.title)],
|
[body("attTitle").notEmpty().withMessage(_sr["fa"].required.title)],
|
||||||
checkValidations(validationResult),
|
checkValidations(validationResult),
|
||||||
(req, res) => {
|
async (req, res) => {
|
||||||
if (!req.files?.file)
|
try {
|
||||||
|
if (!req.files?.file) {
|
||||||
return res
|
return res
|
||||||
.status(422)
|
.status(422)
|
||||||
.json({ validation: { file: { msg: _sr["fa"].required.file } } });
|
.json({ validation: { file: { msg: _sr["fa"].required.file } } });
|
||||||
if (req.files?.file.mimetype.split("/")[1] !== "pdf")
|
}
|
||||||
|
|
||||||
|
if (req.files.file.mimetype.split("/")[1] !== "pdf") {
|
||||||
return res
|
return res
|
||||||
.status(422)
|
.status(422)
|
||||||
.json({ validation: { file: { msg: "فقط فرمت PDF قابل قبول است" } } });
|
.json({ validation: { file: { msg: "فقط فرمت PDF قابل قبول است" } } });
|
||||||
|
}
|
||||||
|
|
||||||
|
const news = await News.findById(req.params.newsId);
|
||||||
|
if (!news) {
|
||||||
|
return res404(res, "خبر مورد نظر پیدا نشد");
|
||||||
|
}
|
||||||
|
|
||||||
const data = { title: req.body.attTitle };
|
|
||||||
const file = req.files.file;
|
|
||||||
const fileName =
|
const fileName =
|
||||||
req.body.attTitle.replace(titleFilterRegex, "-") +
|
req.body.attTitle.replace(titleFilterRegex, "-") +
|
||||||
"_" +
|
"_" +
|
||||||
Date.now() +
|
Date.now() +
|
||||||
".pdf";
|
".pdf";
|
||||||
file.mv(`./static/uploads/files/newsAttachments/${fileName}`);
|
|
||||||
data.file = fileName;
|
|
||||||
|
|
||||||
News.findById(req.params.newsId, (err, news) => {
|
await uploadNewsAttachment(req.files.file.data, fileName);
|
||||||
if (err || !news) return res404(res, err);
|
|
||||||
news.attachments.push(data);
|
news.attachments.push({ title: req.body.attTitle, file: fileName });
|
||||||
news.save((err) => {
|
await news.save();
|
||||||
if (err) return res500(res, err);
|
|
||||||
else return res.json({ message: _sr["fa"].response.success_save });
|
return res.json({ message: _sr["fa"].response.success_save });
|
||||||
});
|
} catch (error) {
|
||||||
});
|
return res500(res, error.message);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
module.exports.removeAttachmentFromNews = [
|
module.exports.removeAttachmentFromNews = [
|
||||||
(req, res) => {
|
async (req, res) => {
|
||||||
News.findOne({ "attachments._id": req.params.fileId }, (err, news) => {
|
try {
|
||||||
if (err || !news) return res404(res, err);
|
const news = await News.findOne({ "attachments._id": req.params.fileId });
|
||||||
const file = news.attachments.id(req.params.fileId);
|
if (!news) {
|
||||||
if (!file) return res404(res, "not found");
|
return res404(res, "not found");
|
||||||
file.remove();
|
}
|
||||||
fs.unlink(`./static/${file.file}`, (err) => {
|
|
||||||
if (err) console.log(err);
|
const attachment = news.attachments.id(req.params.fileId);
|
||||||
});
|
if (!attachment) {
|
||||||
news.save((err) => {
|
return res404(res, "not found");
|
||||||
if (err) return res500(res, err);
|
}
|
||||||
else return res.json({ message: _sr["fa"].response.success_remove });
|
|
||||||
});
|
const fileName = attachment.get("file", null, { getters: false });
|
||||||
});
|
attachment.remove();
|
||||||
|
await deleteNewsAttachment(fileName);
|
||||||
|
await news.save();
|
||||||
|
|
||||||
|
return res.json({ message: _sr["fa"].response.success_remove });
|
||||||
|
} catch (error) {
|
||||||
|
return res500(res, error.message);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -4,11 +4,12 @@ const {_sr} = require('../plugins/serverResponses')
|
|||||||
const {res404, res500} = require('../plugins/controllersHelperFunctions')
|
const {res404, res500} = require('../plugins/controllersHelperFunctions')
|
||||||
const News = require('../models/News')
|
const News = require('../models/News')
|
||||||
const Category = require('../models/Category')
|
const Category = require('../models/Category')
|
||||||
const sharp = require('sharp')
|
const {
|
||||||
const fs = require('fs')
|
deleteNewsImage,
|
||||||
|
uploadProcessedImage,
|
||||||
|
} = require('../plugins/newsImageStorage')
|
||||||
|
|
||||||
////// variables
|
////// variables
|
||||||
const noCover = '/img/no-cover.jpg'
|
|
||||||
const limit = 5;
|
const limit = 5;
|
||||||
const limitDetails = 11;
|
const limitDetails = 11;
|
||||||
const titleFilterRegex = new RegExp('/', 'g')
|
const titleFilterRegex = new RegExp('/', 'g')
|
||||||
@@ -187,19 +188,23 @@ module.exports.addNewsFile = [
|
|||||||
})
|
})
|
||||||
const imageName = `news_${Date.now()}_${createNewsFile._id}.${image.mimetype.split('/')[1]}`;
|
const imageName = `news_${Date.now()}_${createNewsFile._id}.${image.mimetype.split('/')[1]}`;
|
||||||
try {
|
try {
|
||||||
const target = sharp(image.data)
|
await uploadProcessedImage(
|
||||||
await target
|
image.data,
|
||||||
.resize(coverNewsWidth, coverNewsHeight, {fit: 'cover'})
|
imageName,
|
||||||
.jpeg({quality: coverQuality})
|
coverNewsWidth,
|
||||||
.toFile(`./static/uploads/images/news/${imageName}`);
|
coverNewsHeight,
|
||||||
|
coverQuality
|
||||||
|
);
|
||||||
|
|
||||||
|
await uploadProcessedImage(
|
||||||
|
image.data,
|
||||||
|
`thumb_${imageName}`,
|
||||||
|
thumbCoverNewsWidth,
|
||||||
|
thumbCoverNewsHeight,
|
||||||
|
thumbCoverQuality
|
||||||
|
);
|
||||||
|
|
||||||
createNewsFile.cover = imageName;
|
createNewsFile.cover = imageName;
|
||||||
|
|
||||||
await target
|
|
||||||
.resize(thumbCoverNewsWidth, thumbCoverNewsHeight, {fit: 'cover'})
|
|
||||||
.jpeg({quality: thumbCoverQuality})
|
|
||||||
.toFile(`./static/uploads/images/news/thumb_${imageName}`);
|
|
||||||
|
|
||||||
createNewsFile.thumbCover = `thumb_${imageName}`;
|
createNewsFile.thumbCover = `thumb_${imageName}`;
|
||||||
|
|
||||||
await createNewsFile.save();
|
await createNewsFile.save();
|
||||||
@@ -375,39 +380,24 @@ module.exports.updateNewsFile = [
|
|||||||
}
|
}
|
||||||
const imageName = `news_${Date.now()}_${targetNewsFile._id}.${image.mimetype.split('/')[1]}`;
|
const imageName = `news_${Date.now()}_${targetNewsFile._id}.${image.mimetype.split('/')[1]}`;
|
||||||
try {
|
try {
|
||||||
const target = sharp(image.data)
|
await deleteNewsImage(targetNewsFile, "cover");
|
||||||
await target
|
await deleteNewsImage(targetNewsFile, "thumbCover");
|
||||||
.resize(coverNewsWidth, coverNewsHeight, {fit: 'cover'})
|
|
||||||
.jpeg({quality: coverQuality})
|
|
||||||
.toFile(`./static/uploads/images/news/${imageName}`);
|
|
||||||
|
|
||||||
await target
|
await uploadProcessedImage(
|
||||||
.resize(thumbCoverNewsWidth, thumbCoverNewsHeight, {fit: 'cover'})
|
image.data,
|
||||||
.jpeg({quality: thumbCoverQuality})
|
imageName,
|
||||||
.toFile(`./static/uploads/images/news/thumb_${imageName}`);
|
coverNewsWidth,
|
||||||
|
coverNewsHeight,
|
||||||
|
coverQuality
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
await uploadProcessedImage(
|
||||||
* if exist old pic delete it from file
|
image.data,
|
||||||
*/
|
`thumb_${imageName}`,
|
||||||
if (targetNewsFile.cover !== noCover) {
|
thumbCoverNewsWidth,
|
||||||
let oldPic = `./static${targetNewsFile.cover}`;
|
thumbCoverNewsHeight,
|
||||||
|
thumbCoverQuality
|
||||||
if (await fs.existsSync(oldPic)) {
|
);
|
||||||
fs.unlink(oldPic, (err) => {
|
|
||||||
if (err) return res500(res, err?.message);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (targetNewsFile.thumbCover !== noCover) {
|
|
||||||
let oldPic = `./static${targetNewsFile.thumbCover}`;
|
|
||||||
|
|
||||||
if (await fs.existsSync(oldPic)) {
|
|
||||||
fs.unlink(oldPic, (err) => {
|
|
||||||
if (err) return res500(res, err?.message);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
targetNewsFile.cover = imageName;
|
targetNewsFile.cover = imageName;
|
||||||
targetNewsFile.thumbCover = `thumb_${imageName}`;
|
targetNewsFile.thumbCover = `thumb_${imageName}`;
|
||||||
|
|||||||
@@ -2,8 +2,10 @@ const Occasion = require('../models/Occasion');
|
|||||||
const {body, validationResult} = require('express-validator');
|
const {body, validationResult} = require('express-validator');
|
||||||
const {_sr} = require('../plugins/serverResponses');
|
const {_sr} = require('../plugins/serverResponses');
|
||||||
const {res404, res500} = require('../plugins/controllersHelperFunctions');
|
const {res404, res500} = require('../plugins/controllersHelperFunctions');
|
||||||
const fs = require('fs');
|
const {
|
||||||
const sharp = require('sharp');
|
deleteOccasionImage,
|
||||||
|
uploadProcessedImage,
|
||||||
|
} = require('../plugins/occasionImageStorage');
|
||||||
const moment = require('moment-jalaali');
|
const moment = require('moment-jalaali');
|
||||||
|
|
||||||
////// variables
|
////// variables
|
||||||
@@ -63,16 +65,13 @@ module.exports.addOccasion = [
|
|||||||
}
|
}
|
||||||
|
|
||||||
const imageName = `occasion_${addOccasion._id}_${Date.now()}.jpg`;
|
const imageName = `occasion_${addOccasion._id}_${Date.now()}.jpg`;
|
||||||
const target = sharp(image.data)
|
await uploadProcessedImage(
|
||||||
await target
|
image.data,
|
||||||
.resize(occasionWidth, occasionHeight, {
|
imageName,
|
||||||
fit: 'cover'
|
occasionWidth,
|
||||||
})
|
occasionHeight,
|
||||||
.toFormat('jpg')
|
occasionQuality
|
||||||
.jpeg({
|
);
|
||||||
quality: occasionQuality
|
|
||||||
})
|
|
||||||
.toFile(`./static/uploads/images/occasion/${imageName}`);
|
|
||||||
|
|
||||||
addOccasion.status = true;
|
addOccasion.status = true;
|
||||||
addOccasion.mainCover = imageName;
|
addOccasion.mainCover = imageName;
|
||||||
@@ -132,26 +131,15 @@ module.exports.updateOccasion = [
|
|||||||
}
|
}
|
||||||
|
|
||||||
const imageName = `occasion_${targetOccasion._id}_${Date.now()}.jpg`;
|
const imageName = `occasion_${targetOccasion._id}_${Date.now()}.jpg`;
|
||||||
const target = sharp(image.data)
|
await deleteOccasionImage(targetOccasion, 'mainCover');
|
||||||
await target
|
|
||||||
.resize(occasionWidth, occasionHeight, {
|
|
||||||
fit: 'cover'
|
|
||||||
})
|
|
||||||
.toFormat('jpg')
|
|
||||||
.jpeg({
|
|
||||||
quality: occasionQuality
|
|
||||||
})
|
|
||||||
.toFile(`./static/uploads/images/occasion/${imageName}`);
|
|
||||||
|
|
||||||
if (targetOccasion.mainCover) {
|
await uploadProcessedImage(
|
||||||
var oldPic = `./static${targetOccasion.mainCover}`;
|
image.data,
|
||||||
|
imageName,
|
||||||
if (fs.existsSync(oldPic)) {
|
occasionWidth,
|
||||||
fs.unlink(oldPic, (err) => {
|
occasionHeight,
|
||||||
if (err) return res500(res, err?.message);
|
occasionQuality
|
||||||
});
|
);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
targetOccasion.status = true;
|
targetOccasion.status = true;
|
||||||
targetOccasion.mainCover = imageName;
|
targetOccasion.mainCover = imageName;
|
||||||
@@ -184,15 +172,7 @@ module.exports.deleteOccasion = [
|
|||||||
return res404(res, `مناسبت مورد نظر پیدا نشد`);
|
return res404(res, `مناسبت مورد نظر پیدا نشد`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (targetOccasion.mainCover) {
|
await deleteOccasionImage(targetOccasion, 'mainCover');
|
||||||
var oldPic = `./static${targetOccasion.mainCover}`;
|
|
||||||
|
|
||||||
if (fs.existsSync(oldPic)) {
|
|
||||||
fs.unlink(oldPic, (err) => {
|
|
||||||
if (err) return res500(res, err?.message);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
await targetOccasion.deleteOne();
|
await targetOccasion.deleteOne();
|
||||||
|
|
||||||
|
|||||||
@@ -1,109 +1,148 @@
|
|||||||
|
const fs = require("fs/promises");
|
||||||
|
const os = require("os");
|
||||||
|
const path = require("path");
|
||||||
|
const axios = require("axios");
|
||||||
const { body, validationResult } = require("express-validator");
|
const { body, validationResult } = require("express-validator");
|
||||||
const { _sr } = require("../plugins/serverResponses");
|
const { _sr } = require("../plugins/serverResponses");
|
||||||
const { checkValidations } = require("../plugins/controllersHelperFunctions");
|
const { checkValidations } = require("../plugins/controllersHelperFunctions");
|
||||||
const Book = require("../models/Book");
|
const Book = require("../models/Book");
|
||||||
var convertapi = require('convertapi')('6zZB0nquI5V3P3Vg');
|
const {
|
||||||
|
uploadPdf,
|
||||||
|
uploadBookSlide,
|
||||||
|
deletePdf,
|
||||||
|
deleteBookSlide,
|
||||||
|
} = require("../plugins/bookImageStorage");
|
||||||
|
const convertapi = require("convertapi")("6zZB0nquI5V3P3Vg");
|
||||||
|
|
||||||
module.exports.AddPDF = [
|
module.exports.AddPDF = [
|
||||||
[
|
[body("title").notEmpty().withMessage(_sr["fa"].required.title)],
|
||||||
body('title')
|
|
||||||
.notEmpty().withMessage(_sr['fa'].required.title)
|
|
||||||
],
|
|
||||||
checkValidations(validationResult),
|
checkValidations(validationResult),
|
||||||
async (req, res) => {
|
async (req, res) => {
|
||||||
|
let tmpDir;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const firstbook = [];
|
const firstbook = [];
|
||||||
|
|
||||||
if (!req.files?.file) {
|
if (!req.files?.file) {
|
||||||
return res.status(422).json({ validation: { file: { msg: _sr['fa'].required.file } } });
|
return res
|
||||||
|
.status(422)
|
||||||
|
.json({ validation: { file: { msg: _sr["fa"].required.file } } });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req.files?.file.mimetype.split('/')[1] !== 'pdf') {
|
if (req.files?.file.mimetype.split("/")[1] !== "pdf") {
|
||||||
return res.status(422).json({ validation: { file: { msg: 'فقط فرمت PDF قابل قبول است' } } });
|
return res
|
||||||
|
.status(422)
|
||||||
|
.json({ validation: { file: { msg: "فقط فرمت PDF قابل قبول است" } } });
|
||||||
}
|
}
|
||||||
|
|
||||||
const book = await Book.findById(req.body.bookId);
|
const book = await Book.findById(req.body.bookId);
|
||||||
const bookId = book ? book._id : null;
|
const bookId = book ? book._id : null;
|
||||||
|
|
||||||
const data = { title: req.body.title };
|
|
||||||
const file = req.files.file;
|
const file = req.files.file;
|
||||||
const fileName = req.body.title.replace(Date.now(), '-') + '_' + Date.now() + '.pdf';
|
const fileName =
|
||||||
const imageName = req.body.title.replace(Date.now(), '-') + '_' + Date.now();
|
req.body.title.replace(Date.now(), "-") + "_" + Date.now() + ".pdf";
|
||||||
|
const imageName =
|
||||||
|
req.body.title.replace(Date.now(), "-") + "_" + Date.now();
|
||||||
|
|
||||||
const filePath = `./static/uploads/pdf/${fileName}`;
|
const { url: pdfUrl } = await uploadPdf(file.data, fileName);
|
||||||
|
|
||||||
await file.mv(filePath);
|
tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "book-"));
|
||||||
data.file = fileName;
|
const tmpPdfPath = path.join(tmpDir, fileName);
|
||||||
|
await fs.writeFile(tmpPdfPath, file.data);
|
||||||
|
|
||||||
const convertPromise = convertapi.convert('jpg', {
|
const result = await convertapi.convert(
|
||||||
File: filePath
|
"jpg",
|
||||||
}, 'pdf');
|
{ File: tmpPdfPath },
|
||||||
|
"pdf"
|
||||||
|
);
|
||||||
|
|
||||||
const result = await convertPromise;
|
const convertedResponse = await axios.get(result.files[0].url, {
|
||||||
const savedFiles = await result.saveFiles(`./static/uploads/books/${imageName}.jpeg`);
|
responseType: "arraybuffer",
|
||||||
|
});
|
||||||
const imagePath = `https://ostan-mr.ir/uploads/books/${imageName}.jpeg`;
|
const imagePath = await uploadBookSlide(
|
||||||
|
Buffer.from(convertedResponse.data),
|
||||||
|
imageName
|
||||||
|
);
|
||||||
firstbook.push(imagePath);
|
firstbook.push(imagePath);
|
||||||
|
|
||||||
if (bookId) {
|
if (bookId) {
|
||||||
const update = await Book.findByIdAndUpdate(
|
const update = await Book.findByIdAndUpdate(
|
||||||
{_id:bookId},
|
{ _id: bookId },
|
||||||
{ $push: { slides: imagePath } },
|
{ $push: { slides: imagePath } },
|
||||||
{ upsert: true }
|
{ upsert: true }
|
||||||
);
|
);
|
||||||
return res.status(201).json({ msg: "اسلاید کتاب اضافه شد", Data: update });
|
return res
|
||||||
} else {
|
.status(201)
|
||||||
|
.json({ msg: "اسلاید کتاب اضافه شد", Data: update });
|
||||||
|
}
|
||||||
|
|
||||||
const newBook = new Book({
|
const newBook = new Book({
|
||||||
title: req.body.title,
|
title: req.body.title,
|
||||||
uri: `https://ostan-mr.ir/uploads/pdf/${fileName}`,
|
uri: pdfUrl,
|
||||||
slides: firstbook
|
slides: firstbook,
|
||||||
});
|
});
|
||||||
await newBook.save();
|
await newBook.save();
|
||||||
return res.status(201).json({ msg: "کتاب ایجاد شد", Data: newBook });
|
return res.status(201).json({ msg: "کتاب ایجاد شد", Data: newBook });
|
||||||
}
|
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
return res.status(500).json({ msg: "خطایی در پردازش فایل رخ داد", error: error.message });
|
return res.status(500).json({
|
||||||
|
msg: "خطایی در پردازش فایل رخ داد",
|
||||||
|
error: error.message,
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
if (tmpDir) {
|
||||||
|
await fs.rm(tmpDir, { recursive: true, force: true }).catch(() => {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
module.exports.GetAll = [
|
module.exports.GetAll = [
|
||||||
async (req, res,next) => {
|
async (req, res, next) => {
|
||||||
try {
|
try {
|
||||||
const Books = await Book.find({});
|
const Books = await Book.find({});
|
||||||
return res.status(200).json({ Books });
|
return res.status(200).json({ Books });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
next(error)
|
next(error);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
module.exports.GetOne = [
|
module.exports.GetOne = [
|
||||||
async (req, res,next) => {
|
async (req, res, next) => {
|
||||||
try {
|
try {
|
||||||
const id = req.params.id
|
const id = req.params.id;
|
||||||
const book = await Book.findById(id);
|
const book = await Book.findById(id);
|
||||||
return res.status(200).json({ msg: book });
|
return res.status(200).json({ msg: book });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
next(error)
|
next(error);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
module.exports.DeleteOne = [
|
module.exports.DeleteOne = [
|
||||||
async(req,res,next)=>{
|
async (req, res, next) => {
|
||||||
try {
|
try {
|
||||||
const book = await Book.deleteOne({_id:req.params.id})
|
const book = await Book.findById(req.params.id);
|
||||||
if(!book){
|
if (!book) {
|
||||||
return res.status(200).json({ msg: 'کتاب وجود ندارد ' });
|
return res.status(200).json({ msg: "کتاب وجود ندارد " });
|
||||||
}
|
}
|
||||||
return res.status(200).json({ msg: 'کتاب حذف شد' });
|
|
||||||
|
const uri = book.get("uri", null, { getters: false });
|
||||||
|
if (uri) {
|
||||||
|
await deletePdf(uri.split("/").pop());
|
||||||
|
}
|
||||||
|
|
||||||
|
const slides = book.get("slides", [], { getters: false }) || [];
|
||||||
|
for (const slide of slides) {
|
||||||
|
const imageName = slide.split("/").pop().replace(/\.jpeg$/i, "");
|
||||||
|
await deleteBookSlide(imageName);
|
||||||
|
}
|
||||||
|
|
||||||
|
await book.deleteOne();
|
||||||
|
return res.status(200).json({ msg: "کتاب حذف شد" });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
next(error)
|
next(error);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
]
|
];
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ const {
|
|||||||
body,
|
body,
|
||||||
validationResult
|
validationResult
|
||||||
} = require('express-validator');
|
} = require('express-validator');
|
||||||
const sharp = require('sharp');
|
|
||||||
const {
|
const {
|
||||||
_sr
|
_sr
|
||||||
} = require('../plugins/serverResponses');
|
} = require('../plugins/serverResponses');
|
||||||
@@ -14,7 +13,10 @@ const {
|
|||||||
isLatinCharactersWithSymbol,
|
isLatinCharactersWithSymbol,
|
||||||
generateRandomDigits
|
generateRandomDigits
|
||||||
} = require('../plugins/controllersHelperFunctions');
|
} = require('../plugins/controllersHelperFunctions');
|
||||||
const fs = require('fs');
|
const {
|
||||||
|
deleteSliderImage,
|
||||||
|
uploadProcessedImage,
|
||||||
|
} = require('../plugins/sliderImageStorage');
|
||||||
|
|
||||||
////// variables
|
////// variables
|
||||||
const profileWidth = 600;
|
const profileWidth = 600;
|
||||||
@@ -113,15 +115,13 @@ module.exports.addSlider = [
|
|||||||
}
|
}
|
||||||
const imageName = `slider_${Date.now()}_${createSlider._id}.${image.mimetype.split('/')[1]}`;
|
const imageName = `slider_${Date.now()}_${createSlider._id}.${image.mimetype.split('/')[1]}`;
|
||||||
try {
|
try {
|
||||||
const target = sharp(image.data)
|
await uploadProcessedImage(
|
||||||
await target
|
image.data,
|
||||||
.resize(profileWidth, profileHeight, {
|
imageName,
|
||||||
fit: 'cover'
|
profileWidth,
|
||||||
})
|
profileHeight,
|
||||||
.jpeg({
|
profileQuality
|
||||||
quality: profileQuality
|
);
|
||||||
})
|
|
||||||
.toFile(`./static/uploads/images/slider/${imageName}`);
|
|
||||||
|
|
||||||
createSlider.cover = imageName;
|
createSlider.cover = imageName;
|
||||||
|
|
||||||
@@ -253,28 +253,15 @@ module.exports.updateSlider = [
|
|||||||
}
|
}
|
||||||
const imageName = `slider_${Date.now()}_${targetSlider._id}.${image.mimetype.split('/')[1]}`;
|
const imageName = `slider_${Date.now()}_${targetSlider._id}.${image.mimetype.split('/')[1]}`;
|
||||||
try {
|
try {
|
||||||
const target = sharp(image.data)
|
await deleteSliderImage(targetSlider, "cover");
|
||||||
await target
|
|
||||||
.resize(profileWidth, profileHeight, {
|
|
||||||
fit: 'cover'
|
|
||||||
})
|
|
||||||
.jpeg({
|
|
||||||
quality: profileQuality
|
|
||||||
})
|
|
||||||
.toFile(`./static/uploads/images/slider/${imageName}`);
|
|
||||||
|
|
||||||
/**
|
await uploadProcessedImage(
|
||||||
* if exist old pic delete it from file
|
image.data,
|
||||||
*/
|
imageName,
|
||||||
if (targetSlider.cover) {
|
profileWidth,
|
||||||
var oldPic = `./static${targetSlider.cover}`;
|
profileHeight,
|
||||||
|
profileQuality
|
||||||
if (fs.existsSync(oldPic)) {
|
);
|
||||||
fs.unlink(oldPic, (err) => {
|
|
||||||
if (err) return res500(res, err?.message);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
targetSlider.cover = imageName;
|
targetSlider.cover = imageName;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -322,15 +309,7 @@ module.exports.deletOneSlider = [
|
|||||||
return res500(res, `شما اجازه حذف این اسلایدر را ندارید`);
|
return res500(res, `شما اجازه حذف این اسلایدر را ندارید`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (targetSlider.cover) {
|
await deleteSliderImage(targetSlider, "cover");
|
||||||
var oldPic = `./static${targetSlider.cover}`;
|
|
||||||
|
|
||||||
if (fs.existsSync(oldPic)) {
|
|
||||||
fs.unlink(oldPic, (error) => {
|
|
||||||
if (error) return res500(res, error?.message);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** delete slider */
|
/** delete slider */
|
||||||
await targetSlider.deleteOne();
|
await targetSlider.deleteOne();
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ const {
|
|||||||
body,
|
body,
|
||||||
validationResult
|
validationResult
|
||||||
} = require('express-validator');
|
} = require('express-validator');
|
||||||
const sharp = require('sharp');
|
|
||||||
const {
|
const {
|
||||||
_sr
|
_sr
|
||||||
} = require('../plugins/serverResponses');
|
} = require('../plugins/serverResponses');
|
||||||
@@ -14,7 +13,10 @@ const {
|
|||||||
isLatinCharactersWithSymbol,
|
isLatinCharactersWithSymbol,
|
||||||
generateRandomDigits
|
generateRandomDigits
|
||||||
} = require('../plugins/controllersHelperFunctions');
|
} = require('../plugins/controllersHelperFunctions');
|
||||||
const fs = require('fs');
|
const {
|
||||||
|
deleteSliderImage,
|
||||||
|
uploadProcessedImage,
|
||||||
|
} = require('../plugins/sliderImageStorage');
|
||||||
|
|
||||||
////// variables
|
////// variables
|
||||||
const profileWidth = 880;
|
const profileWidth = 880;
|
||||||
@@ -113,15 +115,13 @@ module.exports.addSlider = [
|
|||||||
}
|
}
|
||||||
const imageName = `slider_${Date.now()}_${createSlider._id}.${image.mimetype.split('/')[1]}`;
|
const imageName = `slider_${Date.now()}_${createSlider._id}.${image.mimetype.split('/')[1]}`;
|
||||||
try {
|
try {
|
||||||
const target = sharp(image.data)
|
await uploadProcessedImage(
|
||||||
await target
|
image.data,
|
||||||
.resize(profileWidth, profileHeight, {
|
imageName,
|
||||||
fit: 'cover'
|
profileWidth,
|
||||||
})
|
profileHeight,
|
||||||
.jpeg({
|
profileQuality
|
||||||
quality: profileQuality
|
);
|
||||||
})
|
|
||||||
.toFile(`./static/uploads/images/slider/${imageName}`);
|
|
||||||
|
|
||||||
createSlider.cover = imageName;
|
createSlider.cover = imageName;
|
||||||
|
|
||||||
@@ -253,28 +253,15 @@ module.exports.updateSlider = [
|
|||||||
}
|
}
|
||||||
const imageName = `slider_${Date.now()}_${targetSlider._id}.${image.mimetype.split('/')[1]}`;
|
const imageName = `slider_${Date.now()}_${targetSlider._id}.${image.mimetype.split('/')[1]}`;
|
||||||
try {
|
try {
|
||||||
const target = sharp(image.data)
|
await deleteSliderImage(targetSlider, "cover");
|
||||||
await target
|
|
||||||
.resize(profileWidth, profileHeight, {
|
|
||||||
fit: 'cover'
|
|
||||||
})
|
|
||||||
.jpeg({
|
|
||||||
quality: profileQuality
|
|
||||||
})
|
|
||||||
.toFile(`./static/uploads/images/slider/${imageName}`);
|
|
||||||
|
|
||||||
/**
|
await uploadProcessedImage(
|
||||||
* if exist old pic delete it from file
|
image.data,
|
||||||
*/
|
imageName,
|
||||||
if (targetSlider.cover) {
|
profileWidth,
|
||||||
var oldPic = `./static${targetSlider.cover}`;
|
profileHeight,
|
||||||
|
profileQuality
|
||||||
if (fs.existsSync(oldPic)) {
|
);
|
||||||
fs.unlink(oldPic, (err) => {
|
|
||||||
if (err) return res500(res, err?.message);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
targetSlider.cover = imageName;
|
targetSlider.cover = imageName;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -322,15 +309,7 @@ module.exports.deletOneSlider = [
|
|||||||
return res500(res, `شما اجازه حذف این اسلایدر را ندارید`);
|
return res500(res, `شما اجازه حذف این اسلایدر را ندارید`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (targetSlider.cover) {
|
await deleteSliderImage(targetSlider, "cover");
|
||||||
var oldPic = `./static${targetSlider.cover}`;
|
|
||||||
|
|
||||||
if (fs.existsSync(oldPic)) {
|
|
||||||
fs.unlink(oldPic, (error) => {
|
|
||||||
if (error) return res500(res, error?.message);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** delete slider */
|
/** delete slider */
|
||||||
await targetSlider.deleteOne();
|
await targetSlider.deleteOne();
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ const { rateLimit } = require("express-rate-limit");
|
|||||||
const bcrypt = require("bcryptjs");
|
const bcrypt = require("bcryptjs");
|
||||||
const jwt = require("jsonwebtoken");
|
const jwt = require("jsonwebtoken");
|
||||||
const crypto = require("crypto");
|
const crypto = require("crypto");
|
||||||
const sharp = require("sharp");
|
|
||||||
const { secretKey } = require("./../authentication");
|
const { secretKey } = require("./../authentication");
|
||||||
const { _sr } = require("../plugins/serverResponses");
|
const { _sr } = require("../plugins/serverResponses");
|
||||||
const {
|
const {
|
||||||
@@ -14,7 +13,10 @@ const {
|
|||||||
isLatinCharactersWithSymbol,
|
isLatinCharactersWithSymbol,
|
||||||
generateRandomDigits,
|
generateRandomDigits,
|
||||||
} = require("../plugins/controllersHelperFunctions");
|
} = require("../plugins/controllersHelperFunctions");
|
||||||
const fs = require("fs");
|
const {
|
||||||
|
deleteUserImage,
|
||||||
|
uploadProcessedImage,
|
||||||
|
} = require("../plugins/userImageStorage");
|
||||||
const nodemailer = require("nodemailer");
|
const nodemailer = require("nodemailer");
|
||||||
const Category = require("../models/Category");
|
const Category = require("../models/Category");
|
||||||
const Logger = require("../models/Logger");
|
const Logger = require("../models/Logger");
|
||||||
@@ -566,15 +568,13 @@ module.exports.registerAdmin = [
|
|||||||
image.mimetype.split("/")[1];
|
image.mimetype.split("/")[1];
|
||||||
data.profilePic = imageName;
|
data.profilePic = imageName;
|
||||||
try {
|
try {
|
||||||
const target = sharp(image.data);
|
await uploadProcessedImage(
|
||||||
await target
|
image.data,
|
||||||
.resize(profileWidth, profileHeight, {
|
imageName,
|
||||||
fit: "cover",
|
profileWidth,
|
||||||
})
|
profileHeight,
|
||||||
.jpeg({
|
profileQuality
|
||||||
quality: profileQuality,
|
);
|
||||||
})
|
|
||||||
.toFile(`./static/uploads/images/users/${imageName}`);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return res500(res, e?.message);
|
return res500(res, e?.message);
|
||||||
}
|
}
|
||||||
@@ -713,18 +713,7 @@ module.exports.deleteOneUser = [
|
|||||||
.json({ message: `شما نمیتوانید این کاربر را حذف کنید` });
|
.json({ message: `شما نمیتوانید این کاربر را حذف کنید` });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
await deleteUserImage(user, "profilePic");
|
||||||
* if exist old pic delete it from file
|
|
||||||
*/
|
|
||||||
if (user.profilePic) {
|
|
||||||
var oldPic = `./static${user.profilePic}`;
|
|
||||||
|
|
||||||
if (fs.existsSync(oldPic)) {
|
|
||||||
fs.unlink(oldPic, (err) => {
|
|
||||||
if (err) return res500(res, err?.message);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** delete user */
|
/** delete user */
|
||||||
await user.deleteOne();
|
await user.deleteOne();
|
||||||
@@ -922,28 +911,15 @@ module.exports.updateUser = [
|
|||||||
image.mimetype.split("/")[1];
|
image.mimetype.split("/")[1];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const target = sharp(image.data);
|
await deleteUserImage(user, "profilePic");
|
||||||
await target
|
|
||||||
.resize(profileWidth, profileHeight, {
|
|
||||||
fit: "cover",
|
|
||||||
})
|
|
||||||
.jpeg({
|
|
||||||
quality: profileQuality,
|
|
||||||
})
|
|
||||||
.toFile(`./static/uploads/images/users/${imageName}`);
|
|
||||||
|
|
||||||
/**
|
await uploadProcessedImage(
|
||||||
* if exist old pic delete it from file
|
image.data,
|
||||||
*/
|
imageName,
|
||||||
if (user.profilePic) {
|
profileWidth,
|
||||||
var oldPic = `./static${user.profilePic}`;
|
profileHeight,
|
||||||
|
profileQuality
|
||||||
if (fs.existsSync(oldPic)) {
|
);
|
||||||
fs.unlink(oldPic, (err) => {
|
|
||||||
if (err) return res500(res, err?.message);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return res500(res, e?.message);
|
return res500(res, e?.message);
|
||||||
}
|
}
|
||||||
@@ -1129,28 +1105,15 @@ module.exports.updateProfile = [
|
|||||||
image.mimetype.split("/")[1];
|
image.mimetype.split("/")[1];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const target = sharp(image.data);
|
await deleteUserImage(user, "profilePic");
|
||||||
await target
|
|
||||||
.resize(profileWidth, profileHeight, {
|
|
||||||
fit: "cover",
|
|
||||||
})
|
|
||||||
.jpeg({
|
|
||||||
quality: profileQuality,
|
|
||||||
})
|
|
||||||
.toFile(`./static/uploads/images/users/${imageName}`);
|
|
||||||
|
|
||||||
/**
|
await uploadProcessedImage(
|
||||||
* if exist old pic delete it from file
|
image.data,
|
||||||
*/
|
imageName,
|
||||||
if (user.profilePic) {
|
profileWidth,
|
||||||
var oldPic = `./static${user.profilePic}`;
|
profileHeight,
|
||||||
|
profileQuality
|
||||||
if (fs.existsSync(oldPic)) {
|
);
|
||||||
fs.unlink(oldPic, (err) => {
|
|
||||||
if (err) return res500(res, err?.message);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return res500(res, e?.message);
|
return res500(res, e?.message);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,7 @@ const YearBanner = require('../models/YearBanner');
|
|||||||
const {body, validationResult, checkSchema} = require('express-validator');
|
const {body, validationResult, checkSchema} = require('express-validator');
|
||||||
const {_sr} = require('../plugins/serverResponses');
|
const {_sr} = require('../plugins/serverResponses');
|
||||||
const {res404, res500} = require('../plugins/controllersHelperFunctions');
|
const {res404, res500} = require('../plugins/controllersHelperFunctions');
|
||||||
const fs = require('fs');
|
const {uploadProcessedImage} = require('../plugins/yearBannerImageStorage');
|
||||||
const sharp = require('sharp');
|
|
||||||
|
|
||||||
////// variables
|
////// variables
|
||||||
const yearBannerWidth = 1920
|
const yearBannerWidth = 1920
|
||||||
@@ -51,12 +50,13 @@ module.exports.updateYearBanner = [
|
|||||||
|
|
||||||
imageName = `mainPage_cover.jpg`;
|
imageName = `mainPage_cover.jpg`;
|
||||||
|
|
||||||
const target = sharp(image.data)
|
await uploadProcessedImage(
|
||||||
await target
|
image.data,
|
||||||
.resize(yearBannerWidth, yearBannerHeight, {fit: 'cover'})
|
imageName,
|
||||||
.toFormat('jpg')
|
yearBannerWidth,
|
||||||
.jpeg({quality: yearBannerQuality})
|
yearBannerHeight,
|
||||||
.toFile(`./static/uploads/images/mainCover/${imageName}`);
|
yearBannerQuality
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (yearBanner) {
|
if (yearBanner) {
|
||||||
|
|||||||
@@ -7,7 +7,8 @@
|
|||||||
// const databaseURL = 'mongodb://ostanmri_user:admin1234@localhost:27017/ostanmri_database'
|
// const databaseURL = 'mongodb://ostanmri_user:admin1234@localhost:27017/ostanmri_database'
|
||||||
const databaseURL =
|
const databaseURL =
|
||||||
// "mongodb://root:f2d63313cc3ed6ff@srv-captain--ostandari-db:27017/ostan_db?authSource=admin";
|
// "mongodb://root:f2d63313cc3ed6ff@srv-captain--ostandari-db:27017/ostan_db?authSource=admin";
|
||||||
"mongodb://root:f2d63313cc3ed6ff@89.32.249.24:50123/ostan_db?authSource=admin";
|
"mongodb://root:e9a15xftSaqNgR1fNMSUEHVqYDVh5XiDSW8Dt9sG1UyHvOE6nSTtQguaO4vor4Fp@noxkpqjq8ufxq969ut0v5p3m:27017/ostan_db?directConnection=true&authSource=admin"
|
||||||
|
// "mongodb://root:f2d63313cc3ed6ff@89.32.249.24:50123/ostan_db?authSource=admin";
|
||||||
//const databaseURL = 'mongodb://danakcorp:danakcorp%212024@ostan-mr.ir:27017/ostan_db?serverSelectionTimeoutMS=5000&connectTimeoutMS=10000&authSource=admin&authMechanism=SCRAM-SHA-1'
|
//const databaseURL = 'mongodb://danakcorp:danakcorp%212024@ostan-mr.ir:27017/ostan_db?serverSelectionTimeoutMS=5000&connectTimeoutMS=10000&authSource=admin&authMechanism=SCRAM-SHA-1'
|
||||||
|
|
||||||
// const databaseURL = 'mongodb://ostanmri_user:admin1234@91.98.96.174:27017/ostanmri_database?serverSelectionTimeoutMS=5000&connectTimeoutMS=10000&authSource=ostanmri_database'
|
// const databaseURL = 'mongodb://ostanmri_user:admin1234@91.98.96.174:27017/ostanmri_database?serverSelectionTimeoutMS=5000&connectTimeoutMS=10000&authSource=ostanmri_database'
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
require("dotenv").config();
|
||||||
|
|
||||||
const express = require("express");
|
const express = require("express");
|
||||||
const database = require("./database");
|
const database = require("./database");
|
||||||
const fileUpload = require("express-fileupload");
|
const fileUpload = require("express-fileupload");
|
||||||
|
|||||||
+22
-7
@@ -1,16 +1,31 @@
|
|||||||
const mongoose = require('mongoose');
|
const mongoose = require('mongoose');
|
||||||
const mongoosePaginate = require('mongoose-paginate-v2');
|
const mongoosePaginate = require('mongoose-paginate-v2');
|
||||||
|
const s3Storage = require('../plugins/s3Storage');
|
||||||
|
|
||||||
|
function pdfUri(uri) {
|
||||||
function PDF(pdf) {
|
if (!uri) return null;
|
||||||
if (pdf) return '/uploads/files/ReadOnly-PDF' + pdf
|
if (uri.startsWith('http://') || uri.startsWith('https://')) return uri;
|
||||||
|
const fileName = uri.startsWith('/') ? uri.split('/').pop() : uri;
|
||||||
|
return s3Storage.getPublicUrl(`uploads/pdf/${fileName}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function slideUrl(slide) {
|
||||||
|
if (!slide) return null;
|
||||||
|
if (slide.startsWith('http://') || slide.startsWith('https://')) return slide;
|
||||||
|
const imageName = slide.startsWith('/') ? slide.split('/').pop() : slide;
|
||||||
|
const key = imageName.endsWith('.jpeg')
|
||||||
|
? `uploads/books/${imageName}`
|
||||||
|
: `uploads/books/${imageName}.jpeg`;
|
||||||
|
return s3Storage.getPublicUrl(key);
|
||||||
|
}
|
||||||
|
|
||||||
const BookSchema = mongoose.Schema({
|
const BookSchema = mongoose.Schema({
|
||||||
title: String,
|
title: String,
|
||||||
uri: String,
|
uri: { type: String, get: pdfUri, default: null },
|
||||||
slides:{
|
slides: {
|
||||||
default:[],
|
default: [],
|
||||||
type:Array
|
type: [String],
|
||||||
|
get: (slides) => (slides || []).map(slideUrl),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
const mongoose = require("mongoose");
|
const mongoose = require("mongoose");
|
||||||
|
const s3Storage = require("../plugins/s3Storage");
|
||||||
|
|
||||||
function autoPopulateSubs(next) {
|
function autoPopulateSubs(next) {
|
||||||
this.populate({
|
this.populate({
|
||||||
@@ -14,12 +15,21 @@ function autoPopulateSubs(next) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function file(file) {
|
function file(file) {
|
||||||
return "/uploads/files/terms/" + file;
|
if (!file) return null;
|
||||||
|
if (file.startsWith("http://") || file.startsWith("https://")) return file;
|
||||||
|
return s3Storage.getPublicUrl(`uploads/files/terms/${file}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function image(img) {
|
function image(img) {
|
||||||
if (img) return "/uploads/images/category/" + img;
|
if (!img) return "/img/no-cover.jpg";
|
||||||
else return "/img/no-cover.jpg";
|
if (img.startsWith("http://") || img.startsWith("https://")) return img;
|
||||||
|
return s3Storage.getPublicUrl(`uploads/images/category/${img}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
function shafafiatIcon(icon) {
|
||||||
|
if (!icon) return null;
|
||||||
|
if (icon.startsWith("http://") || icon.startsWith("https://")) return icon;
|
||||||
|
return s3Storage.getPublicUrl(`uploads/images/category/shafafiat/${icon}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const CategoryTermsFile = mongoose.Schema({
|
const CategoryTermsFile = mongoose.Schema({
|
||||||
@@ -71,7 +81,7 @@ const CategorySchema = mongoose.Schema({
|
|||||||
managerName: String,
|
managerName: String,
|
||||||
managerDescription: String,
|
managerDescription: String,
|
||||||
/** if category was shafafiat this icon is for that */
|
/** if category was shafafiat this icon is for that */
|
||||||
icon: String,
|
icon: { type: String, get: shafafiatIcon, default: null },
|
||||||
});
|
});
|
||||||
|
|
||||||
CategorySchema.index({ parent: 1, childs: 1 });
|
CategorySchema.index({ parent: 1, childs: 1 });
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
const mongoose = require('mongoose');
|
const mongoose = require('mongoose');
|
||||||
|
const s3Storage = require('../plugins/s3Storage');
|
||||||
|
|
||||||
function image(img) {
|
function image(img) {
|
||||||
if (img) return '/uploads/images/content/' + img
|
if (!img) return null;
|
||||||
|
if (img.startsWith('http://') || img.startsWith('https://')) return img;
|
||||||
|
return s3Storage.getPublicUrl(`uploads/images/content/${img}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
const mongoose = require('mongoose');
|
const mongoose = require('mongoose');
|
||||||
const mongoosePaginate = require('mongoose-paginate-v2');
|
const mongoosePaginate = require('mongoose-paginate-v2');
|
||||||
|
const s3Storage = require('../plugins/s3Storage');
|
||||||
|
|
||||||
function image(img) {
|
function image(img) {
|
||||||
if (img) return '/uploads/images/election/' + img
|
if (!img) return null;
|
||||||
|
if (img.startsWith('http://') || img.startsWith('https://')) return img;
|
||||||
|
return s3Storage.getPublicUrl(`uploads/images/election/${img}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const CandidatesSchema = mongoose.Schema({
|
const CandidatesSchema = mongoose.Schema({
|
||||||
|
|||||||
@@ -1,16 +1,23 @@
|
|||||||
const mongoose = require('mongoose');
|
const mongoose = require('mongoose');
|
||||||
const mongoosePaginate = require('mongoose-paginate-v2');
|
const mongoosePaginate = require('mongoose-paginate-v2');
|
||||||
|
const s3Storage = require('../plugins/s3Storage');
|
||||||
|
|
||||||
|
function galleryUrl(img, prefix) {
|
||||||
|
if (!img) return null;
|
||||||
|
if (img.startsWith('http://') || img.startsWith('https://')) return img;
|
||||||
|
return s3Storage.getPublicUrl(`${prefix}/${img}`);
|
||||||
|
}
|
||||||
|
|
||||||
function image(img) {
|
function image(img) {
|
||||||
if (img) return '/uploads/images/gallery/' + img
|
return galleryUrl(img, 'uploads/images/gallery');
|
||||||
}
|
}
|
||||||
|
|
||||||
function graphic(img) {
|
function graphic(img) {
|
||||||
if (img) return '/uploads/graphics/gallery/' + img
|
return galleryUrl(img, 'uploads/graphics/gallery');
|
||||||
}
|
}
|
||||||
|
|
||||||
function video(vdo) {
|
function video(vdo) {
|
||||||
if (vdo) return '/uploads/videos/gallery/' + vdo
|
return galleryUrl(vdo, 'uploads/videos/gallery');
|
||||||
}
|
}
|
||||||
|
|
||||||
const GallerySchema = mongoose.Schema({
|
const GallerySchema = mongoose.Schema({
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
const mongoose = require('mongoose');
|
const mongoose = require('mongoose');
|
||||||
|
const s3Storage = require('../plugins/s3Storage');
|
||||||
|
|
||||||
function image(img) {
|
function image(img) {
|
||||||
if (img) return '/uploads/images/links/' + img
|
if (!img) return null;
|
||||||
|
if (img.startsWith('http://') || img.startsWith('https://')) return img;
|
||||||
|
return s3Storage.getPublicUrl(`uploads/images/links/${img}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const LinksSchema = mongoose.Schema({
|
const LinksSchema = mongoose.Schema({
|
||||||
|
|||||||
@@ -1,17 +1,21 @@
|
|||||||
const mongoose = require('mongoose');
|
const mongoose = require('mongoose');
|
||||||
const mongoosePaginate = require('mongoose-paginate-v2');
|
const mongoosePaginate = require('mongoose-paginate-v2');
|
||||||
|
const s3Storage = require('../plugins/s3Storage');
|
||||||
|
|
||||||
function image(img) {
|
function image(img) {
|
||||||
if (img) return '/uploads/images/news/' + img
|
if (!img) return '/img/no-cover.jpg';
|
||||||
else return '/img/no-cover.jpg'
|
if (img.startsWith('http://') || img.startsWith('https://')) return img;
|
||||||
|
return s3Storage.getPublicUrl(`uploads/images/news/${img}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function file(file) {
|
function attachmentFile(file) {
|
||||||
return '/uploads/files/newsAttachments/' + file
|
if (!file) return null;
|
||||||
|
if (file.startsWith('http://') || file.startsWith('https://')) return file;
|
||||||
|
return s3Storage.getPublicUrl(`uploads/files/newsAttachments/${file}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const NewsAttachmentSchema = mongoose.Schema({
|
const NewsAttachmentSchema = mongoose.Schema({
|
||||||
file: {type: String, get: file},
|
file: {type: String, get: attachmentFile},
|
||||||
title: String
|
title: String
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
const mongoose = require('mongoose');
|
const mongoose = require('mongoose');
|
||||||
const mongoosePaginate = require('mongoose-paginate-v2');
|
const mongoosePaginate = require('mongoose-paginate-v2');
|
||||||
|
const s3Storage = require('../plugins/s3Storage');
|
||||||
|
|
||||||
function image(img) {
|
function image(img) {
|
||||||
if (img) return '/uploads/images/news/' + img
|
if (!img) return '/img/no-cover.jpg';
|
||||||
else return '/img/no-cover.jpg'
|
if (img.startsWith('http://') || img.startsWith('https://')) return img;
|
||||||
|
return s3Storage.getPublicUrl(`uploads/images/news/${img}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const NewsFileSchema = mongoose.Schema({
|
const NewsFileSchema = mongoose.Schema({
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
const mongoose = require('mongoose');
|
const mongoose = require('mongoose');
|
||||||
const mongoosePaginate = require('mongoose-paginate-v2');
|
const mongoosePaginate = require('mongoose-paginate-v2');
|
||||||
|
const s3Storage = require('../plugins/s3Storage');
|
||||||
|
|
||||||
function image(img) {
|
function image(img) {
|
||||||
if (img) return '/uploads/images/occasion/' + img
|
if (!img) return null;
|
||||||
|
if (img.startsWith('http://') || img.startsWith('https://')) return img;
|
||||||
|
return s3Storage.getPublicUrl(`uploads/images/occasion/${img}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const OccasionSchema = mongoose.Schema({
|
const OccasionSchema = mongoose.Schema({
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
const mongoose = require('mongoose');
|
const mongoose = require('mongoose');
|
||||||
const mongoosePaginate = require('mongoose-paginate-v2');
|
const mongoosePaginate = require('mongoose-paginate-v2');
|
||||||
|
const s3Storage = require('../plugins/s3Storage');
|
||||||
|
|
||||||
function image(img) {
|
function image(img) {
|
||||||
if (img) return '/uploads/images/slider/' + img
|
if (!img) return null;
|
||||||
|
if (img.startsWith('http://') || img.startsWith('https://')) return img;
|
||||||
|
return s3Storage.getPublicUrl(`uploads/images/slider/${img}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const SliderSchema = mongoose.Schema({
|
const SliderSchema = mongoose.Schema({
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
const mongoose = require('mongoose');
|
const mongoose = require('mongoose');
|
||||||
const mongoosePaginate = require('mongoose-paginate-v2');
|
const mongoosePaginate = require('mongoose-paginate-v2');
|
||||||
|
const s3Storage = require('../plugins/s3Storage');
|
||||||
|
|
||||||
function image(img) {
|
function image(img) {
|
||||||
if (img) return '/uploads/images/users/' + img
|
if (!img) return null;
|
||||||
|
if (img.startsWith('http://') || img.startsWith('https://')) return img;
|
||||||
|
return s3Storage.getPublicUrl(`uploads/images/users/${img}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const AdminSchema = mongoose.Schema({
|
const AdminSchema = mongoose.Schema({
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
const mongoose = require('mongoose');
|
const mongoose = require('mongoose');
|
||||||
|
const s3Storage = require('../plugins/s3Storage');
|
||||||
|
|
||||||
function image(img) {
|
function image(img) {
|
||||||
if (img) return '/uploads/images/mainCover/' + img
|
if (!img) return null;
|
||||||
|
if (img.startsWith('http://') || img.startsWith('https://')) return img;
|
||||||
|
return s3Storage.getPublicUrl(`uploads/images/mainCover/${img}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const YearBannerSchema = mongoose.Schema({
|
const YearBannerSchema = mongoose.Schema({
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
const s3Storage = require("./s3Storage");
|
||||||
|
|
||||||
|
const BACKUP_PREFIX = "backup";
|
||||||
|
const UPLOADS_PREFIX = "uploads";
|
||||||
|
|
||||||
|
const appendS3UploadsToArchive = async (archive) => {
|
||||||
|
const keys = await s3Storage.listObjects(UPLOADS_PREFIX);
|
||||||
|
|
||||||
|
for (const key of keys) {
|
||||||
|
const buffer = await s3Storage.getObjectBuffer(key);
|
||||||
|
archive.append(buffer, { name: key });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const uploadBackupArchive = async (buffer, fileName) => {
|
||||||
|
await s3Storage.uploadBuffer(
|
||||||
|
`${BACKUP_PREFIX}/${fileName}`,
|
||||||
|
buffer,
|
||||||
|
"application/zip"
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteOldBackups = async () => {
|
||||||
|
await s3Storage.deleteObjectsByPrefix(BACKUP_PREFIX);
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
BACKUP_PREFIX,
|
||||||
|
UPLOADS_PREFIX,
|
||||||
|
appendS3UploadsToArchive,
|
||||||
|
uploadBackupArchive,
|
||||||
|
deleteOldBackups,
|
||||||
|
};
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
const s3Storage = require("./s3Storage");
|
||||||
|
|
||||||
|
const PDF_PREFIX = "uploads/pdf";
|
||||||
|
const BOOK_SLIDE_PREFIX = "uploads/books";
|
||||||
|
|
||||||
|
const uploadPdf = async (fileData, fileName) => {
|
||||||
|
const key = `${PDF_PREFIX}/${fileName}`;
|
||||||
|
await s3Storage.uploadBuffer(key, fileData, "application/pdf");
|
||||||
|
return {
|
||||||
|
fileName,
|
||||||
|
url: s3Storage.getPublicUrl(key),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const uploadBookSlide = async (buffer, imageName) => {
|
||||||
|
const key = `${BOOK_SLIDE_PREFIX}/${imageName}.jpeg`;
|
||||||
|
await s3Storage.uploadBuffer(key, buffer, "image/jpeg");
|
||||||
|
return s3Storage.getPublicUrl(key);
|
||||||
|
};
|
||||||
|
|
||||||
|
const deletePdf = async (fileName) => {
|
||||||
|
if (!fileName) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await s3Storage.deleteObject(`${PDF_PREFIX}/${fileName}`);
|
||||||
|
} catch (error) {
|
||||||
|
console.log("Failed to delete PDF from S3:", error?.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteBookSlide = async (imageName) => {
|
||||||
|
if (!imageName) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await s3Storage.deleteObject(`${BOOK_SLIDE_PREFIX}/${imageName}.jpeg`);
|
||||||
|
} catch (error) {
|
||||||
|
console.log("Failed to delete book slide from S3:", error?.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
PDF_PREFIX,
|
||||||
|
BOOK_SLIDE_PREFIX,
|
||||||
|
uploadPdf,
|
||||||
|
uploadBookSlide,
|
||||||
|
deletePdf,
|
||||||
|
deleteBookSlide,
|
||||||
|
};
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
const sharp = require("sharp");
|
||||||
|
const s3Storage = require("./s3Storage");
|
||||||
|
|
||||||
|
const CATEGORY_IMAGE_PREFIX = "uploads/images/category";
|
||||||
|
const CATEGORY_SHAFAFIAT_PREFIX = "uploads/images/category/shafafiat";
|
||||||
|
const TERMS_FILE_PREFIX = "uploads/files/terms";
|
||||||
|
|
||||||
|
const getStoredImageName = (doc, field) =>
|
||||||
|
doc.get(field, null, { getters: false });
|
||||||
|
|
||||||
|
const deleteCategoryImage = async (doc, field) => {
|
||||||
|
const fileName = getStoredImageName(doc, field);
|
||||||
|
if (!fileName) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await s3Storage.deleteObject(`${CATEGORY_IMAGE_PREFIX}/${fileName}`);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(`Failed to delete ${field} from S3:`, error?.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteShafafiatIcon = async (fileName) => {
|
||||||
|
if (!fileName) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await s3Storage.deleteObject(`${CATEGORY_SHAFAFIAT_PREFIX}/${fileName}`);
|
||||||
|
} catch (error) {
|
||||||
|
console.log("Failed to delete shafafiat icon from S3:", error?.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const uploadProcessedImage = async (
|
||||||
|
imageData,
|
||||||
|
imageName,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
quality
|
||||||
|
) => {
|
||||||
|
const buffer = await sharp(imageData)
|
||||||
|
.resize(width, height, { fit: "cover" })
|
||||||
|
.jpeg({ quality })
|
||||||
|
.toBuffer();
|
||||||
|
|
||||||
|
await s3Storage.uploadBuffer(
|
||||||
|
`${CATEGORY_IMAGE_PREFIX}/${imageName}`,
|
||||||
|
buffer,
|
||||||
|
"image/jpeg"
|
||||||
|
);
|
||||||
|
|
||||||
|
return imageName;
|
||||||
|
};
|
||||||
|
|
||||||
|
const uploadShafafiatIcon = async (fileData, fileName, contentType) => {
|
||||||
|
await s3Storage.uploadBuffer(
|
||||||
|
`${CATEGORY_SHAFAFIAT_PREFIX}/${fileName}`,
|
||||||
|
fileData,
|
||||||
|
contentType
|
||||||
|
);
|
||||||
|
|
||||||
|
return fileName;
|
||||||
|
};
|
||||||
|
|
||||||
|
const uploadTermsFile = async (fileData, fileName) => {
|
||||||
|
await s3Storage.uploadBuffer(
|
||||||
|
`${TERMS_FILE_PREFIX}/${fileName}`,
|
||||||
|
fileData,
|
||||||
|
"application/pdf"
|
||||||
|
);
|
||||||
|
|
||||||
|
return fileName;
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteTermsFile = async (fileName) => {
|
||||||
|
if (!fileName) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await s3Storage.deleteObject(`${TERMS_FILE_PREFIX}/${fileName}`);
|
||||||
|
} catch (error) {
|
||||||
|
console.log("Failed to delete terms file from S3:", error?.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
CATEGORY_IMAGE_PREFIX,
|
||||||
|
CATEGORY_SHAFAFIAT_PREFIX,
|
||||||
|
TERMS_FILE_PREFIX,
|
||||||
|
getStoredImageName,
|
||||||
|
deleteCategoryImage,
|
||||||
|
deleteShafafiatIcon,
|
||||||
|
uploadProcessedImage,
|
||||||
|
uploadShafafiatIcon,
|
||||||
|
uploadTermsFile,
|
||||||
|
deleteTermsFile,
|
||||||
|
};
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
const sharp = require("sharp");
|
||||||
|
const s3Storage = require("./s3Storage");
|
||||||
|
|
||||||
|
const CONTENT_IMAGE_PREFIX = "uploads/images/content";
|
||||||
|
|
||||||
|
const getStoredImageName = (doc, field) =>
|
||||||
|
doc.get(field, null, { getters: false });
|
||||||
|
|
||||||
|
const deleteContentImage = async (doc, field) => {
|
||||||
|
const fileName = getStoredImageName(doc, field);
|
||||||
|
if (!fileName) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await s3Storage.deleteObject(`${CONTENT_IMAGE_PREFIX}/${fileName}`);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(`Failed to delete ${field} from S3:`, error?.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteContentImages = async (doc) => {
|
||||||
|
await deleteContentImage(doc, "cover");
|
||||||
|
await deleteContentImage(doc, "thumb");
|
||||||
|
};
|
||||||
|
|
||||||
|
const uploadProcessedImage = async (
|
||||||
|
imageData,
|
||||||
|
imageName,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
quality
|
||||||
|
) => {
|
||||||
|
const buffer = await sharp(imageData)
|
||||||
|
.resize(width, height, { fit: "cover" })
|
||||||
|
.jpeg({ quality })
|
||||||
|
.toBuffer();
|
||||||
|
|
||||||
|
await s3Storage.uploadBuffer(
|
||||||
|
`${CONTENT_IMAGE_PREFIX}/${imageName}`,
|
||||||
|
buffer,
|
||||||
|
"image/jpeg"
|
||||||
|
);
|
||||||
|
|
||||||
|
return imageName;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
CONTENT_IMAGE_PREFIX,
|
||||||
|
getStoredImageName,
|
||||||
|
deleteContentImage,
|
||||||
|
deleteContentImages,
|
||||||
|
uploadProcessedImage,
|
||||||
|
};
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
const sharp = require("sharp");
|
||||||
|
const s3Storage = require("./s3Storage");
|
||||||
|
|
||||||
|
const ELECTION_IMAGE_PREFIX = "uploads/images/election";
|
||||||
|
|
||||||
|
const getStoredImageName = (doc, field) =>
|
||||||
|
doc.get(field, null, { getters: false });
|
||||||
|
|
||||||
|
const deleteElectionImage = async (fileName) => {
|
||||||
|
if (!fileName) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await s3Storage.deleteObject(`${ELECTION_IMAGE_PREFIX}/${fileName}`);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(`Failed to delete election image from S3:`, error?.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteCandidateImage = async (candidate) => {
|
||||||
|
const fileName = getStoredImageName(candidate, "profilePic");
|
||||||
|
await deleteElectionImage(fileName);
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteElectionCandidateImages = async (election) => {
|
||||||
|
for (const candidate of election.candidates) {
|
||||||
|
await deleteCandidateImage(candidate);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const uploadProcessedImage = async (
|
||||||
|
imageData,
|
||||||
|
imageName,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
quality
|
||||||
|
) => {
|
||||||
|
const buffer = await sharp(imageData)
|
||||||
|
.resize(width, height, { fit: "cover" })
|
||||||
|
.jpeg({ quality })
|
||||||
|
.toBuffer();
|
||||||
|
|
||||||
|
await s3Storage.uploadBuffer(
|
||||||
|
`${ELECTION_IMAGE_PREFIX}/${imageName}`,
|
||||||
|
buffer,
|
||||||
|
"image/jpeg"
|
||||||
|
);
|
||||||
|
|
||||||
|
return imageName;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
ELECTION_IMAGE_PREFIX,
|
||||||
|
getStoredImageName,
|
||||||
|
deleteElectionImage,
|
||||||
|
deleteCandidateImage,
|
||||||
|
deleteElectionCandidateImages,
|
||||||
|
uploadProcessedImage,
|
||||||
|
};
|
||||||
@@ -0,0 +1,191 @@
|
|||||||
|
const sharp = require("sharp");
|
||||||
|
const s3Storage = require("./s3Storage");
|
||||||
|
|
||||||
|
const GALLERY_IMAGE_PREFIX = "uploads/images/gallery";
|
||||||
|
const GALLERY_GRAPHIC_PREFIX = "uploads/graphics/gallery";
|
||||||
|
const GALLERY_VIDEO_PREFIX = "uploads/videos/gallery";
|
||||||
|
|
||||||
|
const getPrefixForFileType = (fileType) => {
|
||||||
|
switch (fileType) {
|
||||||
|
case "graphic":
|
||||||
|
return GALLERY_GRAPHIC_PREFIX;
|
||||||
|
case "video":
|
||||||
|
return GALLERY_VIDEO_PREFIX;
|
||||||
|
default:
|
||||||
|
return GALLERY_IMAGE_PREFIX;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getGalleryObjectKey = (fileType, fileName) =>
|
||||||
|
`${getPrefixForFileType(fileType)}/${fileName}`;
|
||||||
|
|
||||||
|
const getStoredFileName = (doc, field) =>
|
||||||
|
doc.get(field, null, { getters: false });
|
||||||
|
|
||||||
|
const getStoredArray = (doc, field) => {
|
||||||
|
const value = doc.get(field, null, { getters: false });
|
||||||
|
return Array.isArray(value) ? value : [];
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteGalleryFile = async (fileType, fileName) => {
|
||||||
|
if (!fileName) return;
|
||||||
|
|
||||||
|
const baseName = fileName.replace(/^thumb_/, "");
|
||||||
|
|
||||||
|
try {
|
||||||
|
await s3Storage.deleteObject(getGalleryObjectKey(fileType, baseName));
|
||||||
|
} catch (error) {
|
||||||
|
console.log(`Failed to delete ${baseName} from S3:`, error?.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileType !== "video") {
|
||||||
|
try {
|
||||||
|
await s3Storage.deleteObject(
|
||||||
|
getGalleryObjectKey(fileType, `thumb_${baseName}`)
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(`Failed to delete thumb_${baseName} from S3:`, error?.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const uploadProcessedImage = async (
|
||||||
|
imageData,
|
||||||
|
imageName,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
quality,
|
||||||
|
prefix = GALLERY_IMAGE_PREFIX
|
||||||
|
) => {
|
||||||
|
let pipeline = sharp(imageData);
|
||||||
|
|
||||||
|
if (width && height) {
|
||||||
|
pipeline = pipeline.resize(width, height, { fit: "cover" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const buffer = await pipeline.jpeg({ quality }).toBuffer();
|
||||||
|
|
||||||
|
await s3Storage.uploadBuffer(
|
||||||
|
`${prefix}/${imageName}`,
|
||||||
|
buffer,
|
||||||
|
"image/jpeg"
|
||||||
|
);
|
||||||
|
|
||||||
|
return imageName;
|
||||||
|
};
|
||||||
|
|
||||||
|
const uploadGalleryVideo = async (fileData, fileName, contentType) => {
|
||||||
|
await s3Storage.uploadBuffer(
|
||||||
|
`${GALLERY_VIDEO_PREFIX}/${fileName}`,
|
||||||
|
fileData,
|
||||||
|
contentType
|
||||||
|
);
|
||||||
|
|
||||||
|
return fileName;
|
||||||
|
};
|
||||||
|
|
||||||
|
const uploadGalleryFile = async (fileType, file, galleryId, options = {}) => {
|
||||||
|
const fileName = `gallery_${galleryId}_${Date.now()}.${
|
||||||
|
file.mimetype.split("/")[1]
|
||||||
|
}`;
|
||||||
|
const prefix = getPrefixForFileType(fileType);
|
||||||
|
|
||||||
|
switch (fileType) {
|
||||||
|
case "image":
|
||||||
|
await uploadProcessedImage(
|
||||||
|
file.data,
|
||||||
|
fileName,
|
||||||
|
options.mainWidth,
|
||||||
|
options.mainHeight,
|
||||||
|
options.mainQuality,
|
||||||
|
prefix
|
||||||
|
);
|
||||||
|
await uploadProcessedImage(
|
||||||
|
file.data,
|
||||||
|
`thumb_${fileName}`,
|
||||||
|
options.thumbWidth,
|
||||||
|
options.thumbHeight,
|
||||||
|
options.thumbQuality,
|
||||||
|
prefix
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case "graphic":
|
||||||
|
await uploadProcessedImage(
|
||||||
|
file.data,
|
||||||
|
fileName,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
options.mainQuality,
|
||||||
|
prefix
|
||||||
|
);
|
||||||
|
await uploadProcessedImage(
|
||||||
|
file.data,
|
||||||
|
`thumb_${fileName}`,
|
||||||
|
options.thumbWidth,
|
||||||
|
options.thumbHeight,
|
||||||
|
options.thumbQuality,
|
||||||
|
prefix
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case "video":
|
||||||
|
await uploadGalleryVideo(file.data, fileName, file.mimetype);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fileName;
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteAllGalleryFiles = async (gallery) => {
|
||||||
|
const galleryType = getStoredFileName(gallery, "galleryType");
|
||||||
|
|
||||||
|
if (galleryType === "image") {
|
||||||
|
const images = getStoredArray(gallery, "images");
|
||||||
|
for (const fileName of images) {
|
||||||
|
await deleteGalleryFile("image", fileName);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (galleryType === "graphic") {
|
||||||
|
await deleteGalleryFile("graphic", getStoredFileName(gallery, "graphic"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (galleryType === "video") {
|
||||||
|
await deleteGalleryFile("video", getStoredFileName(gallery, "video"));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteGalleryCover = async (gallery) => {
|
||||||
|
const cover = getStoredFileName(gallery, "cover");
|
||||||
|
const thumbCover = getStoredFileName(gallery, "thumbCover");
|
||||||
|
|
||||||
|
if (cover) {
|
||||||
|
try {
|
||||||
|
await s3Storage.deleteObject(`${GALLERY_IMAGE_PREFIX}/${cover}`);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(`Failed to delete cover from S3:`, error?.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (thumbCover) {
|
||||||
|
try {
|
||||||
|
await s3Storage.deleteObject(`${GALLERY_IMAGE_PREFIX}/${thumbCover}`);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(`Failed to delete thumb cover from S3:`, error?.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
GALLERY_IMAGE_PREFIX,
|
||||||
|
GALLERY_GRAPHIC_PREFIX,
|
||||||
|
GALLERY_VIDEO_PREFIX,
|
||||||
|
getStoredFileName,
|
||||||
|
getStoredArray,
|
||||||
|
deleteGalleryFile,
|
||||||
|
uploadProcessedImage,
|
||||||
|
uploadGalleryFile,
|
||||||
|
deleteAllGalleryFiles,
|
||||||
|
deleteGalleryCover,
|
||||||
|
};
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
const sharp = require("sharp");
|
||||||
|
const s3Storage = require("./s3Storage");
|
||||||
|
|
||||||
|
const LINKS_IMAGE_PREFIX = "uploads/images/links";
|
||||||
|
|
||||||
|
const getStoredImageName = (doc, field) =>
|
||||||
|
doc.get(field, null, { getters: false });
|
||||||
|
|
||||||
|
const deleteLinksImage = async (doc, field) => {
|
||||||
|
const fileName = getStoredImageName(doc, field);
|
||||||
|
if (!fileName) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await s3Storage.deleteObject(`${LINKS_IMAGE_PREFIX}/${fileName}`);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(`Failed to delete ${field} from S3:`, error?.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const uploadProcessedImage = async (
|
||||||
|
imageData,
|
||||||
|
imageName,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
quality
|
||||||
|
) => {
|
||||||
|
const buffer = await sharp(imageData)
|
||||||
|
.resize(width, height, { fit: "cover" })
|
||||||
|
.jpeg({ quality })
|
||||||
|
.toBuffer();
|
||||||
|
|
||||||
|
await s3Storage.uploadBuffer(
|
||||||
|
`${LINKS_IMAGE_PREFIX}/${imageName}`,
|
||||||
|
buffer,
|
||||||
|
"image/jpeg"
|
||||||
|
);
|
||||||
|
|
||||||
|
return imageName;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
LINKS_IMAGE_PREFIX,
|
||||||
|
getStoredImageName,
|
||||||
|
deleteLinksImage,
|
||||||
|
uploadProcessedImage,
|
||||||
|
};
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
const sharp = require("sharp");
|
||||||
|
const s3Storage = require("./s3Storage");
|
||||||
|
|
||||||
|
const NEWS_IMAGE_PREFIX = "uploads/images/news";
|
||||||
|
const NEWS_ATTACHMENT_PREFIX = "uploads/files/newsAttachments";
|
||||||
|
|
||||||
|
const getStoredImageName = (doc, field) =>
|
||||||
|
doc.get(field, null, { getters: false });
|
||||||
|
|
||||||
|
const deleteNewsImage = async (doc, field) => {
|
||||||
|
const fileName = getStoredImageName(doc, field);
|
||||||
|
if (!fileName) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await s3Storage.deleteObject(`${NEWS_IMAGE_PREFIX}/${fileName}`);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(`Failed to delete ${field} from S3:`, error?.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const uploadProcessedImage = async (
|
||||||
|
imageData,
|
||||||
|
imageName,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
quality
|
||||||
|
) => {
|
||||||
|
const buffer = await sharp(imageData)
|
||||||
|
.resize(width, height, { fit: "cover" })
|
||||||
|
.jpeg({ quality })
|
||||||
|
.toBuffer();
|
||||||
|
|
||||||
|
await s3Storage.uploadBuffer(
|
||||||
|
`${NEWS_IMAGE_PREFIX}/${imageName}`,
|
||||||
|
buffer,
|
||||||
|
"image/jpeg"
|
||||||
|
);
|
||||||
|
|
||||||
|
return imageName;
|
||||||
|
};
|
||||||
|
|
||||||
|
const uploadNewsAttachment = async (
|
||||||
|
fileData,
|
||||||
|
fileName,
|
||||||
|
contentType = "application/pdf"
|
||||||
|
) => {
|
||||||
|
await s3Storage.uploadBuffer(
|
||||||
|
`${NEWS_ATTACHMENT_PREFIX}/${fileName}`,
|
||||||
|
fileData,
|
||||||
|
contentType
|
||||||
|
);
|
||||||
|
|
||||||
|
return fileName;
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteNewsAttachment = async (fileName) => {
|
||||||
|
if (!fileName) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await s3Storage.deleteObject(`${NEWS_ATTACHMENT_PREFIX}/${fileName}`);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(`Failed to delete attachment from S3:`, error?.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
NEWS_IMAGE_PREFIX,
|
||||||
|
NEWS_ATTACHMENT_PREFIX,
|
||||||
|
getStoredImageName,
|
||||||
|
deleteNewsImage,
|
||||||
|
uploadProcessedImage,
|
||||||
|
uploadNewsAttachment,
|
||||||
|
deleteNewsAttachment,
|
||||||
|
};
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
const sharp = require("sharp");
|
||||||
|
const s3Storage = require("./s3Storage");
|
||||||
|
|
||||||
|
const OCCASION_IMAGE_PREFIX = "uploads/images/occasion";
|
||||||
|
|
||||||
|
const getStoredImageName = (doc, field) =>
|
||||||
|
doc.get(field, null, { getters: false });
|
||||||
|
|
||||||
|
const deleteOccasionImage = async (doc, field) => {
|
||||||
|
const fileName = getStoredImageName(doc, field);
|
||||||
|
if (!fileName) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await s3Storage.deleteObject(`${OCCASION_IMAGE_PREFIX}/${fileName}`);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(`Failed to delete ${field} from S3:`, error?.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const uploadProcessedImage = async (
|
||||||
|
imageData,
|
||||||
|
imageName,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
quality
|
||||||
|
) => {
|
||||||
|
const buffer = await sharp(imageData)
|
||||||
|
.resize(width, height, { fit: "cover" })
|
||||||
|
.jpeg({ quality })
|
||||||
|
.toBuffer();
|
||||||
|
|
||||||
|
await s3Storage.uploadBuffer(
|
||||||
|
`${OCCASION_IMAGE_PREFIX}/${imageName}`,
|
||||||
|
buffer,
|
||||||
|
"image/jpeg"
|
||||||
|
);
|
||||||
|
|
||||||
|
return imageName;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
OCCASION_IMAGE_PREFIX,
|
||||||
|
getStoredImageName,
|
||||||
|
deleteOccasionImage,
|
||||||
|
uploadProcessedImage,
|
||||||
|
};
|
||||||
@@ -0,0 +1,140 @@
|
|||||||
|
const {
|
||||||
|
S3Client,
|
||||||
|
PutObjectCommand,
|
||||||
|
DeleteObjectCommand,
|
||||||
|
ListObjectsV2Command,
|
||||||
|
GetObjectCommand,
|
||||||
|
} = require("@aws-sdk/client-s3");
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
bucket: process.env.BUCKET_NAME,
|
||||||
|
region: process.env.BUCKET_REGION || "us-west-2",
|
||||||
|
endpoint: process.env.PARSPACK_S3_ENDPOINT,
|
||||||
|
accessKeyId: process.env.BUCKET_ACCESS_KEY,
|
||||||
|
secretAccessKey: process.env.BUCKET_SECRET_KEY,
|
||||||
|
publicUrl: process.env.BUCKET_PUBLIC_URL || process.env.PARSPACK_S3_ENDPOINT,
|
||||||
|
};
|
||||||
|
|
||||||
|
let s3Client = null;
|
||||||
|
|
||||||
|
const isConfigured = () =>
|
||||||
|
Boolean(
|
||||||
|
config.bucket &&
|
||||||
|
config.endpoint &&
|
||||||
|
config.accessKeyId &&
|
||||||
|
config.secretAccessKey
|
||||||
|
);
|
||||||
|
|
||||||
|
const getClient = () => {
|
||||||
|
if (!isConfigured()) {
|
||||||
|
throw new Error("S3 storage is not configured");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!s3Client) {
|
||||||
|
s3Client = new S3Client({
|
||||||
|
region: config.region,
|
||||||
|
endpoint: config.endpoint,
|
||||||
|
credentials: {
|
||||||
|
accessKeyId: config.accessKeyId,
|
||||||
|
secretAccessKey: config.secretAccessKey,
|
||||||
|
},
|
||||||
|
forcePathStyle: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return s3Client;
|
||||||
|
};
|
||||||
|
|
||||||
|
const normalizeKey = (key) => key.replace(/^\/+/, "");
|
||||||
|
|
||||||
|
const getPublicUrl = (key) => {
|
||||||
|
const normalizedKey = normalizeKey(key);
|
||||||
|
const baseUrl = (config.publicUrl || config.endpoint).replace(/\/+$/, "");
|
||||||
|
return `${baseUrl}/${normalizedKey}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const uploadBuffer = async (
|
||||||
|
key,
|
||||||
|
buffer,
|
||||||
|
contentType = "application/octet-stream"
|
||||||
|
) => {
|
||||||
|
const normalizedKey = normalizeKey(key);
|
||||||
|
|
||||||
|
await getClient().send(
|
||||||
|
new PutObjectCommand({
|
||||||
|
Bucket: config.bucket,
|
||||||
|
Key: normalizedKey,
|
||||||
|
Body: buffer,
|
||||||
|
ContentType: contentType,
|
||||||
|
ACL: "public-read",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
key: normalizedKey,
|
||||||
|
url: getPublicUrl(normalizedKey),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteObject = async (key) => {
|
||||||
|
const normalizedKey = normalizeKey(key);
|
||||||
|
|
||||||
|
await getClient().send(
|
||||||
|
new DeleteObjectCommand({
|
||||||
|
Bucket: config.bucket,
|
||||||
|
Key: normalizedKey,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const listObjects = async (prefix = "") => {
|
||||||
|
const keys = [];
|
||||||
|
let continuationToken;
|
||||||
|
|
||||||
|
do {
|
||||||
|
const response = await getClient().send(
|
||||||
|
new ListObjectsV2Command({
|
||||||
|
Bucket: config.bucket,
|
||||||
|
Prefix: normalizeKey(prefix),
|
||||||
|
ContinuationToken: continuationToken,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
for (const item of response.Contents || []) {
|
||||||
|
if (item.Key) keys.push(item.Key);
|
||||||
|
}
|
||||||
|
|
||||||
|
continuationToken = response.IsTruncated
|
||||||
|
? response.NextContinuationToken
|
||||||
|
: undefined;
|
||||||
|
} while (continuationToken);
|
||||||
|
|
||||||
|
return keys;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getObjectBuffer = async (key) => {
|
||||||
|
const response = await getClient().send(
|
||||||
|
new GetObjectCommand({
|
||||||
|
Bucket: config.bucket,
|
||||||
|
Key: normalizeKey(key),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
return Buffer.from(await response.Body.transformToByteArray());
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteObjectsByPrefix = async (prefix) => {
|
||||||
|
const keys = await listObjects(prefix);
|
||||||
|
|
||||||
|
await Promise.all(keys.map((key) => deleteObject(key)));
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
isConfigured,
|
||||||
|
getPublicUrl,
|
||||||
|
uploadBuffer,
|
||||||
|
deleteObject,
|
||||||
|
listObjects,
|
||||||
|
getObjectBuffer,
|
||||||
|
deleteObjectsByPrefix,
|
||||||
|
};
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
const sharp = require("sharp");
|
||||||
|
const s3Storage = require("./s3Storage");
|
||||||
|
|
||||||
|
const SLIDER_IMAGE_PREFIX = "uploads/images/slider";
|
||||||
|
|
||||||
|
const getStoredImageName = (doc, field) =>
|
||||||
|
doc.get(field, null, { getters: false });
|
||||||
|
|
||||||
|
const deleteSliderImage = async (doc, field) => {
|
||||||
|
const fileName = getStoredImageName(doc, field);
|
||||||
|
if (!fileName) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await s3Storage.deleteObject(`${SLIDER_IMAGE_PREFIX}/${fileName}`);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(`Failed to delete ${field} from S3:`, error?.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const uploadProcessedImage = async (
|
||||||
|
imageData,
|
||||||
|
imageName,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
quality
|
||||||
|
) => {
|
||||||
|
const buffer = await sharp(imageData)
|
||||||
|
.resize(width, height, { fit: "cover" })
|
||||||
|
.jpeg({ quality })
|
||||||
|
.toBuffer();
|
||||||
|
|
||||||
|
await s3Storage.uploadBuffer(
|
||||||
|
`${SLIDER_IMAGE_PREFIX}/${imageName}`,
|
||||||
|
buffer,
|
||||||
|
"image/jpeg"
|
||||||
|
);
|
||||||
|
|
||||||
|
return imageName;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
SLIDER_IMAGE_PREFIX,
|
||||||
|
getStoredImageName,
|
||||||
|
deleteSliderImage,
|
||||||
|
uploadProcessedImage,
|
||||||
|
};
|
||||||
+12
-7
@@ -1,18 +1,24 @@
|
|||||||
const axios = require("axios");
|
const axios = require("axios");
|
||||||
|
|
||||||
|
const SMS_API_KEY = "QkkNxhyXZ6GtEf1soOTtikomO3mA4LaNQDH8mol8huDIwh00";
|
||||||
|
|
||||||
module.exports.sms = async (phoneNumber, message) => {
|
module.exports.sms = async (phoneNumber, message) => {
|
||||||
const smsService = new SmsService("QkkNxhyXZ6GtEf1soOTtikomO3mA4LaNQDH8mol8huDIwh00");
|
const smsService = new SmsService(SMS_API_KEY);
|
||||||
return smsService.sendMessage(phoneNumber, message);
|
return smsService.sendMessage(phoneNumber, message);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Sends login/verification OTP via sms.ir template (verify endpoint). */
|
||||||
|
module.exports.sendOtpSms = async (phoneNumber, otp) => {
|
||||||
|
const smsService = new SmsService(SMS_API_KEY);
|
||||||
|
return smsService.sendOTPSms(otp, phoneNumber);
|
||||||
|
};
|
||||||
|
|
||||||
class SmsService {
|
class SmsService {
|
||||||
constructor(apiKey) {
|
constructor(apiKey) {
|
||||||
this.API_URL = "https://api.sms.ir/v1";
|
this.API_URL = "https://api.sms.ir/v1";
|
||||||
this.OTP_PATTERN = "83604";
|
this.OTP_PATTERN = "628767";
|
||||||
this.SMS_API_KEY = apiKey;
|
this.SMS_API_KEY = apiKey;
|
||||||
}
|
}
|
||||||
//******************************** */
|
|
||||||
|
|
||||||
//******************************** */
|
|
||||||
|
|
||||||
async sendMessage(phone, message) {
|
async sendMessage(phone, message) {
|
||||||
try {
|
try {
|
||||||
@@ -32,7 +38,7 @@ class SmsService {
|
|||||||
console.error("Error in sending SMS", error);
|
console.error("Error in sending SMS", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//******************************** */
|
|
||||||
async getLineNumber() {
|
async getLineNumber() {
|
||||||
try {
|
try {
|
||||||
const { data } = await axios.get(`${this.API_URL}/line`, {
|
const { data } = await axios.get(`${this.API_URL}/line`, {
|
||||||
@@ -45,7 +51,6 @@ class SmsService {
|
|||||||
console.error("Error in getting line number", error);
|
console.error("Error in getting line number", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//******************************** */
|
|
||||||
|
|
||||||
async sendOTPSms(otp, phone) {
|
async sendOTPSms(otp, phone) {
|
||||||
const smsData = {
|
const smsData = {
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
const sharp = require("sharp");
|
||||||
|
const s3Storage = require("./s3Storage");
|
||||||
|
|
||||||
|
const USER_IMAGE_PREFIX = "uploads/images/users";
|
||||||
|
|
||||||
|
const getStoredImageName = (doc, field) =>
|
||||||
|
doc.get(field, null, { getters: false });
|
||||||
|
|
||||||
|
const deleteUserImage = async (doc, field) => {
|
||||||
|
const fileName = getStoredImageName(doc, field);
|
||||||
|
if (!fileName) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await s3Storage.deleteObject(`${USER_IMAGE_PREFIX}/${fileName}`);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(`Failed to delete ${field} from S3:`, error?.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const uploadProcessedImage = async (
|
||||||
|
imageData,
|
||||||
|
imageName,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
quality
|
||||||
|
) => {
|
||||||
|
const buffer = await sharp(imageData)
|
||||||
|
.resize(width, height, { fit: "cover" })
|
||||||
|
.jpeg({ quality })
|
||||||
|
.toBuffer();
|
||||||
|
|
||||||
|
await s3Storage.uploadBuffer(
|
||||||
|
`${USER_IMAGE_PREFIX}/${imageName}`,
|
||||||
|
buffer,
|
||||||
|
"image/jpeg"
|
||||||
|
);
|
||||||
|
|
||||||
|
return imageName;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
USER_IMAGE_PREFIX,
|
||||||
|
getStoredImageName,
|
||||||
|
deleteUserImage,
|
||||||
|
uploadProcessedImage,
|
||||||
|
};
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
const sharp = require("sharp");
|
||||||
|
const s3Storage = require("./s3Storage");
|
||||||
|
|
||||||
|
const YEAR_BANNER_IMAGE_PREFIX = "uploads/images/mainCover";
|
||||||
|
|
||||||
|
const getStoredImageName = (doc, field) =>
|
||||||
|
doc.get(field, null, { getters: false });
|
||||||
|
|
||||||
|
const deleteYearBannerImage = async (doc, field) => {
|
||||||
|
const fileName = getStoredImageName(doc, field);
|
||||||
|
if (!fileName) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await s3Storage.deleteObject(`${YEAR_BANNER_IMAGE_PREFIX}/${fileName}`);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(`Failed to delete ${field} from S3:`, error?.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const uploadProcessedImage = async (
|
||||||
|
imageData,
|
||||||
|
imageName,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
quality
|
||||||
|
) => {
|
||||||
|
const buffer = await sharp(imageData)
|
||||||
|
.resize(width, height, { fit: "cover" })
|
||||||
|
.jpeg({ quality })
|
||||||
|
.toBuffer();
|
||||||
|
|
||||||
|
await s3Storage.uploadBuffer(
|
||||||
|
`${YEAR_BANNER_IMAGE_PREFIX}/${imageName}`,
|
||||||
|
buffer,
|
||||||
|
"image/jpeg"
|
||||||
|
);
|
||||||
|
|
||||||
|
return imageName;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
YEAR_BANNER_IMAGE_PREFIX,
|
||||||
|
getStoredImageName,
|
||||||
|
deleteYearBannerImage,
|
||||||
|
uploadProcessedImage,
|
||||||
|
};
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,79 @@
|
|||||||
|
# CKEditor 4 [](https://twitter.com/intent/tweet?text=Check%20out%20CKEditor%204%20on%20npm&url=https%3A%2F%2Fwww.npmjs.com%2Fpackage%2Fckeditor4)
|
||||||
|
|
||||||
|
[](https://github.com/ckeditor/ckeditor4-releases)
|
||||||
|
[](https://david-dm.org/ckeditor/ckeditor4)
|
||||||
|
[](https://david-dm.org/ckeditor/ckeditor4?type=dev)
|
||||||
|
|
||||||
|
[](http://eepurl.com/c3zRPr)
|
||||||
|
[](https://twitter.com/ckeditor)
|
||||||
|
|
||||||
|
A highly configurable WYSIWYG HTML editor with hundreds of features, from creating rich text content with captioned images, videos, tables, or media embeds to pasting from Word and drag&drop image upload.
|
||||||
|
|
||||||
|
Supports a broad range of browsers, including legacy ones.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
```
|
||||||
|
npm install --save ckeditor4
|
||||||
|
```
|
||||||
|
|
||||||
|
Use it on your website:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<div id="editor">
|
||||||
|
<p>This is the editor content.</p>
|
||||||
|
</div>
|
||||||
|
<script src="./node_modules/ckeditor4/ckeditor.js"></script>
|
||||||
|
<script>
|
||||||
|
CKEDITOR.replace( 'editor' );
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also load CKEditor 4 using [CDN](https://cdn.ckeditor.com/#ckeditor4).
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
* Over 500 plugins in the [Add-ons Repository](https://ckeditor.com/cke4/addons).
|
||||||
|
* Pasting from Microsoft Word and Excel.
|
||||||
|
* Drag&drop image uploads.
|
||||||
|
* Media embeds to insert videos, tweets, maps, slideshows.
|
||||||
|
* Powerful clipboard integration.
|
||||||
|
* Content quality control with Advanced Content Filter.
|
||||||
|
* Extensible widget system.
|
||||||
|
* Custom table selection.
|
||||||
|
* Accessibility conforming to WCAG and Section 508.
|
||||||
|
* Over 60 localizations available with full RTL support.
|
||||||
|
|
||||||
|
## Presets
|
||||||
|
|
||||||
|
The CKEditor 4 npm package comes in the `standard-all` preset, so it includes all official CKEditor plugins, with those from the [standard package](https://sdk.ckeditor.com/samples/standardpreset.html) active by default.
|
||||||
|
|
||||||
|
## Further Resources
|
||||||
|
|
||||||
|
* [CKEditor 4 demo](https://ckeditor.com/ckeditor-4/)
|
||||||
|
* [Documentation](https://ckeditor.com/docs/ckeditor4/latest/)
|
||||||
|
* [API documentation](https://ckeditor.com/docs/ckeditor4/latest/api/index.html)
|
||||||
|
* [Configuration reference](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html)
|
||||||
|
* [CKEditor SDK with more samples](https://sdk.ckeditor.com/)
|
||||||
|
|
||||||
|
If you are looking for CKEditor 5, here's a link to the relevant npm package: <https://www.npmjs.com/package/ckeditor5>
|
||||||
|
|
||||||
|
## Browser Support
|
||||||
|
|
||||||
|
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome (Android) | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari-ios/safari-ios_48x48.png" alt="iOS Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>iOS Safari | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/opera/opera_48x48.png" alt="Opera" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Opera |
|
||||||
|
| --------- | --------- | --------- | --------- | --------- | --------- | --------- |
|
||||||
|
| IE8, IE9, IE10, IE11, Edge| latest version| latest version| latest version| latest version| latest version| latest version
|
||||||
|
|
||||||
|
Find out more in the [Browser Compatibility guide](https://ckeditor.com/docs/ckeditor4/latest/guide/dev_browsers.html#officially-supported-browsers).
|
||||||
|
|
||||||
|
## Contribute
|
||||||
|
|
||||||
|
If you would like to help maintain the project, follow the [Contribution instructions](https://github.com/ckeditor/ckeditor4/blob/master/.github/CONTRIBUTING.md).
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
|
||||||
|
|
||||||
|
For licensing, see LICENSE.md or <https://ckeditor.com/legal/ckeditor-oss-license>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
# Reporting a security issues
|
||||||
|
|
||||||
|
If you believe you have found a security issue in the CKEditor 4 software, please contact us immediately.
|
||||||
|
|
||||||
|
When reporting a potential security problem, please bear this in mind:
|
||||||
|
|
||||||
|
* Make sure to provide as many details as possible about the vulnerability.
|
||||||
|
* Please do not disclose publicly any security issues until we fix them and publish security releases.
|
||||||
|
|
||||||
|
Contact the security team at security@cksource.com. As soon as we receive the security report, we will work promptly to confirm the issue and then to provide a security fix.
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
|
||||||
|
For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
||||||
|
*/
|
||||||
|
(function(a){if("undefined"==typeof a)throw Error("jQuery should be loaded before CKEditor jQuery adapter.");if("undefined"==typeof CKEDITOR)throw Error("CKEditor should be loaded before CKEditor jQuery adapter.");CKEDITOR.config.jqueryOverrideVal="undefined"==typeof CKEDITOR.config.jqueryOverrideVal?!0:CKEDITOR.config.jqueryOverrideVal;a.extend(a.fn,{ckeditorGet:function(){var a=this.eq(0).data("ckeditorInstance");if(!a)throw"CKEditor is not initialized yet, use ckeditor() with a callback.";return a},
|
||||||
|
ckeditor:function(g,e){if(!CKEDITOR.env.isCompatible)throw Error("The environment is incompatible.");if(!a.isFunction(g)){var m=e;e=g;g=m}var k=[];e=e||{};this.each(function(){var b=a(this),c=b.data("ckeditorInstance"),f=b.data("_ckeditorInstanceLock"),h=this,l=new a.Deferred;k.push(l.promise());if(c&&!f)g&&g.apply(c,[this]),l.resolve();else if(f)c.once("instanceReady",function(){setTimeout(function d(){c.element?(c.element.$==h&&g&&g.apply(c,[h]),l.resolve()):setTimeout(d,100)},0)},null,null,9999);
|
||||||
|
else{if(e.autoUpdateElement||"undefined"==typeof e.autoUpdateElement&&CKEDITOR.config.autoUpdateElement)e.autoUpdateElementJquery=!0;e.autoUpdateElement=!1;b.data("_ckeditorInstanceLock",!0);c=a(this).is("textarea")?CKEDITOR.replace(h,e):CKEDITOR.inline(h,e);b.data("ckeditorInstance",c);c.on("instanceReady",function(e){var d=e.editor;setTimeout(function n(){if(d.element){e.removeListener();d.on("dataReady",function(){b.trigger("dataReady.ckeditor",[d])});d.on("setData",function(a){b.trigger("setData.ckeditor",
|
||||||
|
[d,a.data])});d.on("getData",function(a){b.trigger("getData.ckeditor",[d,a.data])},999);d.on("destroy",function(){b.trigger("destroy.ckeditor",[d])});d.on("save",function(){a(h.form).submit();return!1},null,null,20);if(d.config.autoUpdateElementJquery&&b.is("textarea")&&a(h.form).length){var c=function(){b.ckeditor(function(){d.updateElement()})};a(h.form).submit(c);a(h.form).bind("form-pre-serialize",c);b.bind("destroy.ckeditor",function(){a(h.form).unbind("submit",c);a(h.form).unbind("form-pre-serialize",
|
||||||
|
c)})}d.on("destroy",function(){b.removeData("ckeditorInstance")});b.removeData("_ckeditorInstanceLock");b.trigger("instanceReady.ckeditor",[d]);g&&g.apply(d,[h]);l.resolve()}else setTimeout(n,100)},0)},null,null,9999)}});var f=new a.Deferred;this.promise=f.promise();a.when.apply(this,k).then(function(){f.resolve()});this.editor=this.eq(0).data("ckeditorInstance");return this}});CKEDITOR.config.jqueryOverrideVal&&(a.fn.val=CKEDITOR.tools.override(a.fn.val,function(g){return function(e){if(arguments.length){var m=
|
||||||
|
this,k=[],f=this.each(function(){var b=a(this),c=b.data("ckeditorInstance");if(b.is("textarea")&&c){var f=new a.Deferred;c.setData(e,function(){f.resolve()});k.push(f.promise());return!0}return g.call(b,e)});if(k.length){var b=new a.Deferred;a.when.apply(this,k).done(function(){b.resolveWith(m)});return b.promise()}return f}var f=a(this).eq(0),c=f.data("ckeditorInstance");return f.is("textarea")&&c?c.getData():g.call(f)}}))})(window.jQuery);
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 231 KiB |
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"bender": {
|
||||||
|
"port": 9001
|
||||||
|
},
|
||||||
|
"server": {
|
||||||
|
"port": 9002
|
||||||
|
},
|
||||||
|
"paths": {
|
||||||
|
"ckeditor4": "../ckeditor4/",
|
||||||
|
"runner": "./src/runner.html"
|
||||||
|
},
|
||||||
|
"browsers": {
|
||||||
|
"linux": [ "chrome", "firefox" ],
|
||||||
|
"macos": [ "safari" ]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"name": "ckeditor",
|
||||||
|
"description": "JavaScript WYSIWYG web text editor.",
|
||||||
|
"keywords": [ "ckeditor4", "ckeditor", "fckeditor", "editor", "wysiwyg", "html", "richtext", "text", "javascript" ],
|
||||||
|
"authors": "CKSource (https://cksource.com/)",
|
||||||
|
"license": "For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license/.",
|
||||||
|
"homepage": "https://ckeditor.com",
|
||||||
|
"main": "./ckeditor.js",
|
||||||
|
"moduleType": "globals"
|
||||||
|
}
|
||||||
Vendored
+1297
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"name": "ckeditor/ckeditor",
|
||||||
|
"description": "JavaScript WYSIWYG web text editor.",
|
||||||
|
"type": "library",
|
||||||
|
"keywords": [ "ckeditor4", "ckeditor", "fckeditor", "editor", "wysiwyg", "html", "richtext", "text", "javascript" ],
|
||||||
|
"homepage": "https://ckeditor.com/ckeditor-4/",
|
||||||
|
"license": [ "GPL-2.0+", "LGPL-2.1+", "MPL-1.1+" ],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "CKSource",
|
||||||
|
"homepage": "https://cksource.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/ckeditor/ckeditor4/issues",
|
||||||
|
"forum": "https://stackoverflow.com/tags/ckeditor",
|
||||||
|
"wiki": "https://ckeditor.com/docs/ckeditor4/latest/",
|
||||||
|
"source": "https://github.com/ckeditor/ckeditor4"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
/**
|
||||||
|
* @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
|
||||||
|
* For licensing, see https://ckeditor.com/legal/ckeditor-oss-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
CKEDITOR.editorConfig = function( config ) {
|
||||||
|
// Define changes to default configuration here.
|
||||||
|
// For complete reference see:
|
||||||
|
// https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html
|
||||||
|
|
||||||
|
// The toolbar groups arrangement, optimized for two toolbar rows.
|
||||||
|
config.toolbarGroups = [
|
||||||
|
{ name: 'clipboard', groups: [ 'clipboard', 'undo' ] },
|
||||||
|
{ name: 'editing', groups: [ 'find', 'selection', 'spellchecker' ] },
|
||||||
|
{ name: 'links' },
|
||||||
|
{ name: 'insert' },
|
||||||
|
{ name: 'forms' },
|
||||||
|
{ name: 'tools' },
|
||||||
|
{ name: 'document', groups: [ 'mode', 'document', 'doctools' ] },
|
||||||
|
{ name: 'others' },
|
||||||
|
'/',
|
||||||
|
{ name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ] },
|
||||||
|
{ name: 'paragraph', groups: [ 'list', 'indent', 'blocks', 'align', 'bidi' ] },
|
||||||
|
{ name: 'styles' },
|
||||||
|
{ name: 'colors' },
|
||||||
|
{ name: 'about' }
|
||||||
|
];
|
||||||
|
|
||||||
|
// Remove some buttons provided by the standard plugins, which are
|
||||||
|
// not needed in the Standard(s) toolbar.
|
||||||
|
config.removeButtons = 'Underline,Subscript,Superscript';
|
||||||
|
|
||||||
|
// Set the most common block elements.
|
||||||
|
config.format_tags = 'p;h1;h2;h3;pre';
|
||||||
|
|
||||||
|
// Simplify the dialog windows.
|
||||||
|
config.removeDialogTabs = 'image:advanced;link:advanced';
|
||||||
|
};
|
||||||
@@ -0,0 +1,208 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
|
||||||
|
For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
body
|
||||||
|
{
|
||||||
|
/* Font */
|
||||||
|
/* Emoji fonts are added to visualise them nicely in Internet Explorer. */
|
||||||
|
font-family: sans-serif, Arial, Verdana, "Trebuchet MS", "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
||||||
|
font-size: 12px;
|
||||||
|
|
||||||
|
/* Text color */
|
||||||
|
color: #333;
|
||||||
|
|
||||||
|
/* Remove the background color to make it transparent. */
|
||||||
|
background-color: #fff;
|
||||||
|
|
||||||
|
margin: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cke_editable
|
||||||
|
{
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 1.6;
|
||||||
|
|
||||||
|
/* Fix for missing scrollbars with RTL texts. (#10488) */
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote
|
||||||
|
{
|
||||||
|
font-style: italic;
|
||||||
|
font-family: Georgia, Times, "Times New Roman", serif;
|
||||||
|
padding: 2px 0;
|
||||||
|
border-style: solid;
|
||||||
|
border-color: #ccc;
|
||||||
|
border-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cke_contents_ltr blockquote
|
||||||
|
{
|
||||||
|
padding-left: 20px;
|
||||||
|
padding-right: 8px;
|
||||||
|
border-left-width: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cke_contents_rtl blockquote
|
||||||
|
{
|
||||||
|
padding-left: 8px;
|
||||||
|
padding-right: 20px;
|
||||||
|
border-right-width: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a
|
||||||
|
{
|
||||||
|
color: #0782C1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol,ul,dl
|
||||||
|
{
|
||||||
|
/* IE7: reset rtl list margin. (#7334) */
|
||||||
|
*margin-right: 0px;
|
||||||
|
/* Preserved spaces for list items with text direction different than the list. (#6249,#8049)*/
|
||||||
|
padding: 0 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,h2,h3,h4,h5,h6
|
||||||
|
{
|
||||||
|
font-weight: normal;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr
|
||||||
|
{
|
||||||
|
border: 0px;
|
||||||
|
border-top: 1px solid #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.right
|
||||||
|
{
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
float: right;
|
||||||
|
margin-left: 15px;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.left
|
||||||
|
{
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
float: left;
|
||||||
|
margin-right: 15px;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre
|
||||||
|
{
|
||||||
|
white-space: pre-wrap; /* CSS 2.1 */
|
||||||
|
word-wrap: break-word; /* IE7 */
|
||||||
|
-moz-tab-size: 4;
|
||||||
|
tab-size: 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.marker
|
||||||
|
{
|
||||||
|
background-color: Yellow;
|
||||||
|
}
|
||||||
|
|
||||||
|
span[lang]
|
||||||
|
{
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
figure
|
||||||
|
{
|
||||||
|
text-align: center;
|
||||||
|
outline: solid 1px #ccc;
|
||||||
|
background: rgba(0,0,0,0.05);
|
||||||
|
padding: 10px;
|
||||||
|
margin: 10px 20px;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
figure > figcaption
|
||||||
|
{
|
||||||
|
text-align: center;
|
||||||
|
display: block; /* For IE8 */
|
||||||
|
}
|
||||||
|
|
||||||
|
a > img {
|
||||||
|
padding: 1px;
|
||||||
|
margin: 1px;
|
||||||
|
border: none;
|
||||||
|
outline: 1px solid #0782C1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Widget Styles */
|
||||||
|
.code-featured
|
||||||
|
{
|
||||||
|
border: 5px solid red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.math-featured
|
||||||
|
{
|
||||||
|
padding: 20px;
|
||||||
|
box-shadow: 0 0 2px rgba(200, 0, 0, 1);
|
||||||
|
background-color: rgba(255, 0, 0, 0.05);
|
||||||
|
margin: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-clean
|
||||||
|
{
|
||||||
|
border: 0;
|
||||||
|
background: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-clean > figcaption
|
||||||
|
{
|
||||||
|
font-size: .9em;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-grayscale
|
||||||
|
{
|
||||||
|
background-color: white;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-grayscale img, img.image-grayscale
|
||||||
|
{
|
||||||
|
filter: grayscale(100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed-240p
|
||||||
|
{
|
||||||
|
max-width: 426px;
|
||||||
|
max-height: 240px;
|
||||||
|
margin:0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed-360p
|
||||||
|
{
|
||||||
|
max-width: 640px;
|
||||||
|
max-height: 360px;
|
||||||
|
margin:0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed-480p
|
||||||
|
{
|
||||||
|
max-width: 854px;
|
||||||
|
max-height: 480px;
|
||||||
|
margin:0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed-720p
|
||||||
|
{
|
||||||
|
max-width: 1280px;
|
||||||
|
max-height: 720px;
|
||||||
|
margin:0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed-1080p
|
||||||
|
{
|
||||||
|
max-width: 1920px;
|
||||||
|
max-height: 1080px;
|
||||||
|
margin:0 auto;
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
|
||||||
|
For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
||||||
|
|
||||||
|
af.js Found: 62 Missing: 4
|
||||||
|
ar.js Found: 51 Missing: 15
|
||||||
|
bg.js Found: 58 Missing: 8
|
||||||
|
bn.js Found: 40 Missing: 26
|
||||||
|
bs.js Found: 29 Missing: 37
|
||||||
|
ca.js Found: 61 Missing: 5
|
||||||
|
cs.js Found: 66 Missing: 0
|
||||||
|
cy.js Found: 66 Missing: 0
|
||||||
|
da.js Found: 66 Missing: 0
|
||||||
|
de.js Found: 66 Missing: 0
|
||||||
|
el.js Found: 59 Missing: 7
|
||||||
|
en-au.js Found: 38 Missing: 28
|
||||||
|
en-ca.js Found: 37 Missing: 29
|
||||||
|
en-gb.js Found: 61 Missing: 5
|
||||||
|
eo.js Found: 66 Missing: 0
|
||||||
|
es.js Found: 66 Missing: 0
|
||||||
|
et.js Found: 66 Missing: 0
|
||||||
|
eu.js Found: 48 Missing: 18
|
||||||
|
fa.js Found: 66 Missing: 0
|
||||||
|
fi.js Found: 66 Missing: 0
|
||||||
|
fo.js Found: 66 Missing: 0
|
||||||
|
fr-ca.js Found: 42 Missing: 24
|
||||||
|
fr.js Found: 66 Missing: 0
|
||||||
|
gl.js Found: 40 Missing: 26
|
||||||
|
gu.js Found: 66 Missing: 0
|
||||||
|
he.js Found: 66 Missing: 0
|
||||||
|
hi.js Found: 43 Missing: 23
|
||||||
|
hr.js Found: 66 Missing: 0
|
||||||
|
hu.js Found: 63 Missing: 3
|
||||||
|
is.js Found: 41 Missing: 25
|
||||||
|
it.js Found: 66 Missing: 0
|
||||||
|
ja.js Found: 62 Missing: 4
|
||||||
|
ka.js Found: 62 Missing: 4
|
||||||
|
km.js Found: 40 Missing: 26
|
||||||
|
ko.js Found: 40 Missing: 26
|
||||||
|
lt.js Found: 66 Missing: 0
|
||||||
|
lv.js Found: 40 Missing: 26
|
||||||
|
mk.js Found: 0 Missing: 66
|
||||||
|
mn.js Found: 40 Missing: 26
|
||||||
|
ms.js Found: 39 Missing: 27
|
||||||
|
nb.js Found: 66 Missing: 0
|
||||||
|
nl.js Found: 65 Missing: 1
|
||||||
|
no.js Found: 66 Missing: 0
|
||||||
|
pl.js Found: 66 Missing: 0
|
||||||
|
pt-br.js Found: 66 Missing: 0
|
||||||
|
pt.js Found: 52 Missing: 14
|
||||||
|
ro.js Found: 61 Missing: 5
|
||||||
|
ru.js Found: 66 Missing: 0
|
||||||
|
sk.js Found: 49 Missing: 17
|
||||||
|
sl.js Found: 48 Missing: 18
|
||||||
|
sr-latn.js Found: 40 Missing: 26
|
||||||
|
sr.js Found: 40 Missing: 26
|
||||||
|
sv.js Found: 62 Missing: 4
|
||||||
|
th.js Found: 40 Missing: 26
|
||||||
|
tr.js Found: 66 Missing: 0
|
||||||
|
ug.js Found: 66 Missing: 0
|
||||||
|
uk.js Found: 66 Missing: 0
|
||||||
|
vi.js Found: 66 Missing: 0
|
||||||
|
zh-cn.js Found: 66 Missing: 0
|
||||||
|
zh.js Found: 58 Missing: 8
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user