芝麻web文件管理V1.00
编辑当前文件:/home/freeclou/app.optimyar.com/backend/api/helpers/services/helpers.js
'use strict'; const request = require('request'); var soap = require('soap'); const axios = require('axios'); const moment = require("moment"); //https://nodemailer.com/about/ const nodemailer = require("nodemailer"); //https://github.com/aakatev/bigbluebutton-js const bbb = require('bigbluebutton-js'); const xml2js = require('xml2js'); const url = require("url"); const fs = require("fs"); module.exports = { async expiredUserSession(user) { return true; }, async sendBlackListMessage(user,appName){ const data = fs.readFileSync(`resources/emailTemplate/BlackListAlert.html`, 'utf8'); const html = data.replace(/APP_NAME/g, appName).replace(/USER_FULL_NAME/g,user.name) .replace(/USER_PHONE_NO/g,user.phoneNo); this.sendEmail(user.email, "هشدار!!!", html).then(); const inputData= [ {"software":appName}, {"name": user.name} ]; this.sendSms(user.phoneNo,'bheqcyif4gkqde0',inputData).then(); }, async getBBBMeetings() { let api = bbb.api( process.env.BBB_URL, process.env.BBB_SECRET ); const url = api.monitoring.getMeetings(); const result = await bbb.http(url); return result; }, async checkVersion(ctx){ const queryObject = url.parse(ctx.request.url, true).query; const {version} = queryObject; if (!version || version < process.env.CLIENT_NEED_VERSION){ return false; }else{ ctx.request.url = ctx.request.url.replace("?version="+version,""); return true; } }, async isAdobeRunning(levelId, returnLink = false) { return false; // TODO:: until adobe be used again let lastSession = await strapi.services.session.findOne({ course_level: levelId, _sort: "updatedAt:DESC", _limit: 1 }); if (!lastSession || !lastSession.isAdobe || !lastSession.internalMeetingID || lastSession.isPublished) { return false; } const instance = axios.create({ baseURL: `${process.env.AC_SERVER}`, withCredentials: true }); let apiCall = `/api/xml?action=login&login=${process.env.AC_USER}&password=${process.env.AC_PASSWORD}`; try { let apiResp = await instance.get(apiCall, {withCredentials: true}); instance.defaults.headers = { Cookie: apiResp.headers["set-cookie"][0] }; apiResp = await strapi.services.helpers.xml2Json(apiResp.data); apiResp = JSON.parse(apiResp); if (apiResp && apiResp.results && apiResp.results.status[0].$.code === "ok") { apiCall = `/api/xml?action=sco-contents&sco-id=${process.env.AC_MEETING_FOLDER}&filter-url-path=${lastSession.internalMeetingID}`; let apiResp = await instance.get(encodeURI(apiCall), {withCredentials: true}); if (apiResp && apiResp.data) { apiResp = await strapi.services.helpers.xml2Json(apiResp.data); apiResp = JSON.parse(apiResp); if (apiResp && apiResp.results && apiResp.results.status[0].$.code === "ok") { let scoId = apiResp.results.scos[0].sco[0].$["sco-id"]; apiCall = `/api/xml?action=report-my-meetings&filter-sco-id=${scoId}`; apiResp = await instance.get(encodeURI(apiCall), {withCredentials: true}); if (apiResp && apiResp.data) { apiResp = await strapi.services.helpers.xml2Json(apiResp.data); apiResp = JSON.parse(apiResp); if (apiResp && apiResp.results && apiResp.results.status[0].$.code === "ok") { const info = apiResp.results["my-meetings"][0].meeting[0].$; if (Number(info["active-participants"])) { if (returnLink) { return `${process.env.AC_SERVER}${lastSession.internalMeetingID.replace(/\//g, '')}`; } return true; } } } } } return false; } } catch (ex) { console.error("isAdobeRunning", ex); return false; } }, async isBBBMeetingRunning(id) { try { const api = bbb.api( process.env.BBB_URL, process.env.BBB_SECRET ); const url = api.monitoring.isMeetingRunning(id); const result = await bbb.http(url); return result && result.returncode === "SUCCESS" && result.running; } catch (ex) { strapi.services["system-log"].create({ type: "checkBBBIsRunning", message: ex }); return false; } }, async getBBBPublicSessions(isPrivate,isLogin=false) { let api = bbb.api( process.env.BBB_URL, process.env.BBB_SECRET ); const url = api.monitoring.getMeetings(); const result = await bbb.http(url); let publics = []; const noMeeting = result.messageKey === "noMeetings"; if (!noMeeting && result.returncode === "SUCCESS" && result.meetings && result.meetings.meeting) { const isArray = Array.isArray(result.meetings.meeting); if (isArray) { if (isPrivate) { publics = result.meetings.meeting.filter(m => m.metadata.isprivate && m.running); } else { publics = result.meetings.meeting.filter(m => (m.metadata.ispublic || m.metadata.ispublicregistred) && m.running); } } else if (!isPrivate && (result.meetings.meeting.metadata.ispublic || result.meetings.meeting.metadata.ispublicregistred)) { publics = [result.meetings.meeting]; } else if (isPrivate && result.meetings.meeting.metadata.isprivate) { publics = [result.meetings.meeting]; } } return publics; }, async deleteBBBRecordings(id) { let api = bbb.api( process.env.BBB_URL, process.env.BBB_SECRET ); const url = api.recording.deleteRecordings(id); return await bbb.http(url); }, async getBBBRecordings() { let api = bbb.api( process.env.BBB_URL, process.env.BBB_SECRET ); const url = api.recording.getRecordings(); return await bbb.http(url); }, isEmail(email) { const emailRegExp = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; return emailRegExp.test(email); }, async makeUserIdForBBBSession(email, phoneNo, ip) { return [email, phoneNo, ip].join(" - "); }, async verifyBBBUserNotJoined(meetingInfo, userId) { if (meetingInfo && meetingInfo.attendees && meetingInfo.attendees.attendee && meetingInfo.attendees.attendee.length) { const exist = meetingInfo.attendees.attendee.find(x => x.userID === userId); if (exist) { return { result: false, entity: exist } } } return { result: true, entity: null }; }, async getBBBMeetingInfo(id) { let api = bbb.api( process.env.BBB_URL, process.env.BBB_SECRET ); const url = api.monitoring.getMeetingInfo(id); const result = await bbb.http(url); return result; }, async getBBBMeetingInfoByInternalId(id) { const userSessions = await strapi.services.session.find({internalMeetingID: id}); if (!userSessions || userSessions.length !== 1) { return {result: false, entity: "session.errors.invalidMeetingId"}; } const userSession = userSessions[0]; let api = bbb.api( process.env.BBB_URL, process.env.BBB_SECRET ); const meetingId= userSession.course_level? userSession.course_level.id: userSession.id; const url = api.monitoring.getMeetingInfo(meetingId); const result = await bbb.http(url); return {result:true,entity:result}; }, async createBBBMeeting(name, id, params) { let api = bbb.api( process.env.BBB_URL, process.env.BBB_SECRET ); const meetingCreateUrl = api.administration.create(name, id, params); return await bbb.http(meetingCreateUrl); }, async joinUserToMeeting(fullName, meetingId, password, userID, guest = true) { let api = bbb.api( process.env.BBB_URL, process.env.BBB_SECRET ); const kwparams = {userID}; if (guest) { kwparams.guest = guest; } let userUrl = api.administration.join(fullName, meetingId, password, kwparams); return userUrl; }, async endJoin(user, meetingID, password) { let api = bbb.api( process.env.BBB_URL, process.env.BBB_SECRET ); let endUrl = api.administration.end(meetingID, password); }, async joinBBB(user) { let api = bbb.api( process.env.BBB_URL, process.env.BBB_SECRET ); let http = bbb.http; // api module itslef is responsible for constructing URLs let meetingCreateUrl = api.administration.create('My Meeting Number 1', '1', { attendeePW: 'secret', moderatorPW: 'supersecret', }); //let meetingEndUrl = api.administration.end('1', 'supersecret'); //console.log(`End meeting link: ${meetingEndUrl}`); // http method should be used in order to make calls let result = await http(meetingCreateUrl); let moderatorUrl = api.administration.join('moderator', '1', 'supersecret', { user_id: 'papinaser', redirect: "FALSE" }); let result1 = await http(moderatorUrl); let attendeeUrl = api.administration.join('attendee', '1', 'secret', { user_id: 'user1', redirect: "FALSE" }); let result2 = await http(attendeeUrl); return { moderatorUrl: result1, attendeeUrl: result2 }; }, makeRandomNumber(from, to) { return Math.floor((Math.random() * to) + from); }, async sendEmail(to, subject, html) { // create reusable transporter object using the default SMTP transport let transporter = nodemailer.createTransport({ host: process.env.SMTP_SERVER, port: process.env.SMTP_PORT, secure: false, // true for 465, false for other ports auth: { user: process.env.SMTP_USER, // generated ethereal user pass: process.env.SMTP_PASS, // generated ethereal password }, // here it goes tls: {rejectUnauthorized: false}, }); // send mail with defined transport object let info = await transporter.sendMail({ from: process.env.SMTP_SENDER, // sender address to: to, //"bar@example.com, baz@example.com", // list of receivers cc: process.env.MANAGER_EMAIL, subject: subject,// "Hello ✔", // Subject line //text: "Hello world?", // plain text body html, amp: html//"
Hello world?
", // html body }); console.log("Message sent: %s", info.messageId); // Message sent:
}, async xml2Json(xml) { return new Promise(resolve => { xml2js.parseString(xml, (err, result) => { if (err) { strapi.services["system-log"].create({ type: "xml2Json", message: err.message }); } // `result` is a JavaScript object // convert it to a JSON string const json = JSON.stringify(result, null, 4); // log JSON string resolve(json); }); }); }, async sendSms(phoneNo, patternCode, inputData) { phoneNo = phoneNo.toString(); if (!phoneNo.startsWith("0")) { phoneNo = "0" + phoneNo; } return new Promise((resolve) => { request.post({ url: 'http://ippanel.com/api/select', body: { "op": "pattern", "user": "09106116696", "pass": "NabZ2020$", "fromNum": "5000125475", "toNum": phoneNo, "patternCode": patternCode, "inputData": inputData }, json: true, }, function (error, response, body) { if (!error && response.statusCode === 200) { //YOU CAN CHECK THE RESPONSE AND SEE ERROR OR SUCCESS MESSAGE resolve({result: true, entity: response}); } else { if (error) { resolve({result: false, entity: error}); } else if (response.statusCode === 504) { resolve({result: false, entity: "errors.timout"}); } else { resolve({result: false, entity: "errors.serverSideError"}); } } }); }); }, async saveListEntity(name, list) { const result = await list.reduce(async (memo, item) => { const results = await memo; const entity = await strapi.services[name].create(item); return [...results, entity._id] }, []); return result; }, reverseString(str) { return str.split("").reverse().join(""); }, normalizePhoneNo(phoneNo) { //always return a number if (phoneNo.length < 10 || (phoneNo.length > 11 && !phoneNo.startsWith("0")) || (phoneNo.length > 10 && phoneNo.startsWith("9")) || (phoneNo.length === 10 && !phoneNo.startsWith("9"))) { return false; } else { return Number(phoneNo); // if (phoneNo.startsWith("0")){ // return phoneNo; // } // return "0" + phoneNo; } }, async verifyPhoneNoExist(ctx, phoneNo) { const user = await strapi.query('user', 'users-permissions').findOne({phoneNo}); if (!user) { ctx.badRequest( null, "auth.errors.phoneNoNotExist" ); return false; } return true; }, isAdmin(user) { return user.role === "AdvanceUser" || user.role.name === "AdvanceUser"; }, howMuchDaysLeft(toDate){ const now = moment(new Date()); //todays date const end = moment(toDate); // another date return Math.abs(now.diff(end, 'days'))+1; }, isNowAfterDate(fromData){ const check = new Date(); return check.getTime() > fromData.getTime(); }, isNowBetweenDates(fromDate, toDate) { const check = new Date(); return (check.getTime() <= toDate.getTime() && check.getTime() >= fromDate.getTime()); }, addMinutes(date, minutes) { if (typeof date === "string") { date = new Date(date) } return new Date(date.getTime() + minutes * 60000); }, addSecond(date, sec) { if (typeof date === "string") { date = new Date(date) } return new Date(date.getTime() + sec * 1000); }, sleep(second) { return new Promise(resolve => { setTimeout(resolve, second * 1000); }) }, async getCourseLevels(levelId) { const courseInfo = await strapi.services["course-level"].findOne({id: levelId}); const result = []; if (courseInfo.isGeneral) { const arr = courseInfo.course.course_levels.map(id => { return new Promise(async resolve => { const lInfo = await strapi.services["course-level"].findOne({id}); resolve(lInfo) }) }); result.push(...await Promise.all(arr)); } else { result.push(courseInfo); } return result; }, async hasUserAccessToLevel(levelId, user) { if (user.blocked) { return false; } const levels = await this.getCourseLevels(levelId); const arr = levels.map(level => { return new Promise(async resolve => { const uci = await strapi.services["user-course"] .find({course_levels: [level.id], user: user.id, isConfirm: true}); resolve(uci && uci.length > 0); }); }); const isValid = await Promise.all(arr); return isValid.includes(true); }, addDays(theDate, days) { console.log("theDate",theDate); return new Date(theDate.getTime() + days*24*60*60*1000); }, async verifyUserAccessToMeeting(meetingId, user) { const userSessions = await strapi.services.session.find({internalMeetingID: meetingId}); if (!userSessions || userSessions.length !== 1) { return {result: false, entity: "session.errors.invalidMeetingId"}; } const userSession = userSessions[0]; if (this.isAdmin(user)) { return {result: true, entity: userSessions}; } if (userSession.disallow_users && userSession.disallow_users.includes(user.id)) { return {result: false, entity: "sessions.errors.userHasNoAccess"}; } const levelGeneral = await strapi.services.course.findOne({ course_levels_in: [userSession.course_level.id] });//may a level don't have general const lIds = [userSession.course_level.id]; if (levelGeneral) { const gl = await strapi.services["course-level"].findOne({ course: levelGeneral.id }); if (gl) { lIds.push(gl.id); } } const uci = await strapi.services["user-course"] .find({course_levels_in: lIds, user: user.id, isConfirm: true}); const hasAccess = uci && uci.length !== 0; if (!hasAccess) { return {result: false, entity: "sessions.errors.userHasNoAccess"}; } return {result: true, entity: userSession}; }, async toDataURL(url) { const file = await axios.get(url, {responseType: 'arraybuffer'}); let raw = Buffer.from(file.data).toString('base64'); return raw; }, async verifyMellatPay (facId,amount,saleReferenceId){ const url = 'https://bpm.shaparak.ir/pgwchannel/services/pgw?wsdl'; const args = {terminalId: 6860806,userName:'optimyar88',userPassword:'26959182', orderId:facId, saleOrderId:facId, saleReferenceId:saleReferenceId}; const options = { overrideRootElement: { namespace: 'ns1' } }; return new Promise((resolve)=>{ soap.createClient(url, options, (err, client) => { if (err){ console.log("bpVerifyRequest Step1",err); resolve({result:true,entity:{code:'VS1'}}); return; } client.bpVerifyRequest(args, (err, result, body) => { if(err) { console.log("requestForPayBP Step2",err); resolve({result:true,entity:{code:'VS2'}}); }else{ console.log("result!!!!!!",result); const arr = result? result.return.split(",") : [200]; if (arr[0]!=="0"){ console.log("requestForPayBP Step3",result); client.bpVerifyRequest(args, (err, result2, body) => { if(err) { console.log("requestForPayBP Step3",err); resolve({result:true,entity:{code:'VS3'}}); }else{ console.log("result repeat",result2); const arr = result2? result2.return.split(",") : [300]; if (arr[0]!=="0" && arr[0]!=='43'){ resolve({result:true,entity:{code:'VS4'}}); }else { resolve({result:true,entity:{code:101}}); } } }) }else{ console.log("result 1",result); resolve({result:true,entity:{code:100}}); } } }) }); }); }, async verifyZarinpalPay(authority, amount) { return new Promise(resolve => { axios.post("https://api.zarinpal.com/pg/v4/payment/verify.json", { merchant_id: "7527a218-5adb-401f-bd3e-72eee628b25d",//"ce442962-6b0f-4094-ae81-296bc6a5b5ea", amount: amount * 10,//rial authority }).then(resp => { resolve({result: true, entity: resp.data.data}); }).catch(err => { resolve({result: true, entity: {code: err.response.data.errors.code}}); }) }); }, async requestForPayBP(amount,description, mobile, email,facId){ const url = 'https://bpm.shaparak.ir/pgwchannel/services/pgw?wsdl'; const localDate = moment().format('YYYYMMDD'); const localTime = moment().format('HHmmss'); const args = {terminalId: 6860806,userName:'optimyar88',userPassword:'26959182', payerId:0, orderId:facId, callBackUrl:"https://api.optimyar.com/user-courses/paycallBack", localDate,localTime, amount:amount*10,mobileNo:mobile,additionalData:description}; const options = { overrideRootElement: { namespace: 'ns1' } }; // return { // result:true, // entity: { // mobile:'989106116696', // result:true, // authority:'00000000000000' // } // }; return new Promise((resolve)=>{ soap.createClient(url, options, (err, client) => { if (err){ console.log("requestForPayBP Step1",err); resolve({result:false,entity:"errors.errorInInitPay"}); return; } client.bpPayRequest(args, (err, result, body) => { if(err) { console.log("requestForPayBP Step2",err); resolve({result:false,entity:"errors.errorInInitPay"}); }else{ console.log("result!!!!!!",result); const arr = result? result.return.split(",") : [100]; if (arr[0]!=="0"){ console.log("requestForPayBP Step3",result); resolve({result:false,entity:"errors.errorInInitPay"}); }else{ const entity= { code:arr[0], authority:arr[1],mobileNo: mobile } resolve({result:true,entity}); } } }) }); }); }, async verifyForPayZarinpal(amount, description, mobile, email) { return new Promise(resolve => { axios.post("https://api.zarinpal.com/pg/v4/payment/request.json", { merchant_id: "7527a218-5adb-401f-bd3e-72eee628b25d",//"ce442962-6b0f-4094-ae81-296bc6a5b5ea", amount: amount * 10,//rial description, callback_url: "https://app.optimyar.com/bankCallBack", //callback_url: "http://localhost:3000/bankCallBack", metadata: { mobile, email } }).then(resp => { const {code, authority} = resp.data.data; resolve({ result: true, entity: { code, authority } }) }).catch(err => { resolve({ result: false, entity: "errors.errorInInitPay" }) }) }); } };