const fs = require('fs') const jimp = require('jimp') const { body, validationResult } = require('express-validator') const moment = require('moment-jalaali') const Lottery = require('../models/Lottery') const { serialChecker } = require('../plugins/asanServiceSerialChecker') const { _sr } = require('../plugins/serverResponses') const { res404, res406, res500, checkValidations, removeWhiteSpaces, checkMobileNumber, normalizeMobileNumber } = require('../plugins/controllersHelperFunctions') const sms = require('../plugins/SMS_Module') /// const _faSr = _sr.fa module.exports.addLottery = [ [ body('title').notEmpty().withMessage(_faSr.required.title), body('winnersCount') .notEmpty() .withMessage('تعداد برندگان قرعه کشی را مشخص کنید') .bail() .isNumeric() .withMessage(_faSr.format.number) .bail() .custom((value, { req }) => { if (Number(value) < 1) return Promise.reject(new Error('تعداد برندگان نمیتواند کمتر از 1 باشد')) else return Promise.resolve() }), body('expireDate') .notEmpty() .withMessage('تاریخ پایان قرعه کشی را مشخص کنید') .bail() .isNumeric() .withMessage('فرمت صحیح نیست') .bail() .custom((value, { req }) => { if (Number(value) < Date.now()) return Promise.reject(new Error('نمیتوان تاریخ روز جاری یا قبل تر انتخاب کرد.')) else return Promise.resolve() }) ], checkValidations(validationResult), async (req, res) => { const { title, winnersCount, expireDate } = req.body const supportedImageFormats = ['png', 'jpg', 'jpeg', 'webp'] let entryBgImgName, resultBgImgName, entryWidth, entryHeight, resultWidth, resultHeight try { // check for other open lotteries const openLotteries = await Lottery.find({ expired: false }) if (openLotteries.length) return res406(res, 'تا بسته شدن قرعه کشی قبلی نمیتوان قرعه کشی جدید ثبت کرد') // required image validations if (!req.files || !req.files.entryBgImg) return res.status(422).json({ validation: { entryBgImg: { msg: 'عکس صفحه شرکت در قرعه کشی اجباری است' } } }) if (!req.files || !req.files.resultBgImg) return res.status(422).json({ validation: { resultBgImg: { msg: 'عکس صفحه نتایج قرعه کشی اجباری است' } } }) // save images if (req.files) { // save entry bg image if (req.files.entryBgImg) { const image = req.files.entryBgImg // validate image format if (!supportedImageFormats.includes(image.mimetype.split('/')[1])) { return res.status(422).json({ validation: { entryBgImg: { msg: _faSr.format.image } } }) } entryBgImgName = 'lotteryEntryBg_' + Date.now() + '.' + image.mimetype.split('/')[1] const jimpImg = await jimp.read(image.data) jimpImg.quality(100).write(`./static/uploads/images/lottery/${entryBgImgName}`) entryWidth = jimpImg.bitmap.width entryHeight = jimpImg.bitmap.height } // save result bg image if (req.files.resultBgImg) { const image = req.files.resultBgImg // validate image format if (!supportedImageFormats.includes(image.mimetype.split('/')[1])) { return res.status(422).json({ validation: { resultBgImg: { msg: _faSr.format.image } } }) } resultBgImgName = 'lotteryResultBg_' + Date.now() + '.' + image.mimetype.split('/')[1] const jimpImg = await jimp.read(image.data) jimpImg.quality(100).write(`./static/uploads/images/lottery/${resultBgImgName}`) resultWidth = jimpImg.bitmap.width resultHeight = jimpImg.bitmap.height } } const data = { title, winnersCount, expireDate } if (entryBgImgName) { data.entryWidth = entryWidth data.entryHeight = entryHeight data.entryBgImg = entryBgImgName } if (resultBgImgName) { data.resultWidth = resultWidth data.resultHeight = resultHeight data.resultBgImg = resultBgImgName } data.lotteryCode = 'L'.concat(moment(Date.now()).format('jMMMjDDjYYYY').toUpperCase()) const lottery = new Lottery(data) await lottery.save() return res.json({ message: _faSr.response.success_save }) } catch (e) { return res500(res, `there is an error here --- ${e}`) } } ] module.exports.updateLottery = [ [ body('title').notEmpty().withMessage(_faSr.required.title), body('winnersCount') .notEmpty() .withMessage('تعداد برندگان قرعه کشی را مشخص کنید') .bail() .isNumeric() .withMessage(_faSr.format.number) .bail() .custom((value, { req }) => { if (Number(value) < 1) return Promise.reject(new Error('تعداد برندگان نمیتواند کمتر از 1 باشد')) else return Promise.resolve() }), body('expireDate') .notEmpty() .withMessage('تاریخ پایان قرعه کشی را مشخص کنید') .bail() .isNumeric() .withMessage('فرمت صحیح نیست') .bail() .custom((value, { req }) => { if (Number(value) < Date.now()) return Promise.reject(new Error('نمیتوان تاریخ روز جاری یا قبل تر انتخاب کرد.')) else return Promise.resolve() }) ], checkValidations(validationResult), async (req, res) => { const { title, winnersCount, expireDate } = req.body const supportedImageFormats = ['png', 'jpg', 'jpeg', 'webp'] let entryBgImgName, resultBgImgName, entryWidth, entryHeight, resultWidth, resultHeight try { // check lottery expiration const lottery = await Lottery.findById(req.params?.lotteryId) if (lottery.expired) return res406(res, 'نمیتوان قرعه کشی بسته شده را ویرایش کرد') // save images if (req.files) { // save entry bg image if (req.files.entryBgImg) { const image = req.files.entryBgImg // validate image format if (!supportedImageFormats.includes(image.mimetype.split('/')[1])) { return res.status(422).json({ validation: { entryBgImg: { msg: _faSr.format.image } } }) } entryBgImgName = 'lotteryEntryBg_' + Date.now() + '.' + image.mimetype.split('/')[1] const jimpImg = await jimp.read(image.data) jimpImg.quality(100).write(`./static/uploads/images/lottery/${entryBgImgName}`) entryWidth = jimpImg.bitmap.width entryHeight = jimpImg.bitmap.height lottery.entryBgImg && fs.unlink(`./static/${lottery.entryBgImg}`, err => { if (err) console.log(err) }) } // save result bg image if (req.files.resultBgImg) { const image = req.files.resultBgImg // validate image format if (!supportedImageFormats.includes(image.mimetype.split('/')[1])) { return res.status(422).json({ validation: { resultBgImg: { msg: _faSr.format.image } } }) } resultBgImgName = 'lotteryResultBg_' + Date.now() + '.' + image.mimetype.split('/')[1] const jimpImg = await jimp.read(image.data) jimpImg.quality(100).write(`./static/uploads/images/lottery/${resultBgImgName}`) resultWidth = jimpImg.bitmap.width resultHeight = jimpImg.bitmap.height lottery.resultBgImg && fs.unlink(`./static/${lottery.resultBgImg}`, err => { if (err) console.log(err) }) } } lottery.title = title lottery.winnersCount = winnersCount lottery.expireDate = expireDate if (entryBgImgName) { lottery.entryWidth = entryWidth lottery.entryHeight = entryHeight lottery.entryBgImg = entryBgImgName } if (resultBgImgName) { lottery.resultWidth = resultWidth lottery.resultHeight = resultHeight lottery.resultBgImg = resultBgImgName } await lottery.save() return res.json({ message: _faSr.response.success_save }) } catch (e) { return res500(res, `there is an error here --- ${e}`) } } ] module.exports.getAllLotteries = [ (req, res) => { Lottery.find({}) .sort({ _id: -1 }) .exec((err, data) => { if (err || !data) return res500(res, err) else return res.json(data) }) } ] module.exports.getOneLottery = [ (req, res) => { Lottery.findById(req.params?.lotteryId, (err, data) => { if (err || !data) return res404(err) else return res.json(data) }) } ] module.exports.getLastLottery = [ (req, res) => { Lottery.find({}) .sort({ _id: -1 }) .select('-participants -winnersCount') .exec((err, data) => { if (err || !data?.length) return res404(res, 'هیچ قرعه کشی ای در دسترس نیست') else return res.json(data[0]) }) } ] module.exports.enrollParticipant = [ [ body('fullName') .notEmpty() .withMessage(_faSr.required.name) .bail() .isLength({ min: 4 }) .withMessage(_faSr.min_char.min4) .bail() .custom((value, { req }) => { if (removeWhiteSpaces(value).length < 4) return Promise.reject(_faSr.min_char.min4) if (removeWhiteSpaces(value).match(/^[A-Za-z]+$/g)) return Promise.reject(new Error('لطفا با حروف فارسی تایپ کنید.')) else return true }), body('mobile') .notEmpty() .withMessage(_faSr.required.phone_number) .bail() .custom((value, { req }) => { const mobileNStatus = checkMobileNumber(value) if (!mobileNStatus) return Promise.reject(_faSr.format.phone_number) else return Promise.resolve() }), body('serial') .notEmpty() .withMessage('شماره سریال گارانتی را وارد کنید') .bail() .custom(async (value, { req }) => { try { const serialStatus = await serialChecker(value) if (!serialStatus) return Promise.reject(new Error('شماره سریال معتبر نمیباشد')) else return Promise.resolve() } catch (e) { console.log('error in check serials for enrollLotteryController ---- error message: ', e) return Promise.reject(new Error('مشکلی در بررسی شماره سریال پیش آمده')) } }) ], checkValidations(validationResult), async (req, res) => { const { fullName, mobile, serial, lotteryId } = req.body try { const lottery = await Lottery.findById(lotteryId) if (!lottery) throw new Error('incorrect lottery id') if (lottery.expired) return res404(res, 'مهلت شرکت در قرعه کشی به پایان رسیده') for await (const item of lottery.participants) { if (item.serial === serial) return res404(res, 'این شماره سریال از قبل توسط شخص دیگری ثبت شده است') } const enrollCode = lottery.lotteryCode .concat(lottery.participants.length) .concat((Math.random() * 100).toFixed(0)) const normalizedMN = normalizeMobileNumber(mobile) const data = { fullName, mobile: normalizedMN, serial, enrollCode } lottery.participants.push(data) lottery.markModified('participants') await lottery.save() await sms.lottery.enrollment(normalizedMN, fullName, enrollCode, Date.now()) return res.json({ message: 'اطلاعات شما با موفیقت در سیستم ثبت شد. کد پیگیری به تلفن همراه شما ارسال گردید' }) } catch (e) { return res500(res, `there is an error here --- ${e}`) } } ] module.exports.deleteLottery = [ (req, res) => { Lottery.findByIdAndDelete(req.params?.lotteryId, (err, oldData) => { if (err || !oldData) return res404(res, err) fs.unlink(`./static/${oldData.entryBgImg}`, err => { if (err) console.log(err) }) fs.unlink(`./static/${oldData.resultBgImg}`, err => { if (err) console.log(err) }) return res.json({ message: _faSr.response.success_remove }) }) } ]