diff --git a/.github/workflows/ci.dev.yml b/.github/workflows/ci.dev.yml index 52f6744..2b42707 100644 --- a/.github/workflows/ci.dev.yml +++ b/.github/workflows/ci.dev.yml @@ -78,4 +78,5 @@ jobs: aws ecr get-login-password --region ap-southeast-1 | docker login --username AWS --password-stdin 844772501268.dkr.ecr.ap-southeast-1.amazonaws.com docker pull $DOCKER_IMAGE_WITH_TAG docker stop training-api | true + docker rm training-api | true docker run -p 3001:3001 --name training-api -d $DOCKER_IMAGE_WITH_TAG -e $DB_URI diff --git a/.github/workflows/ci.prod.yml b/.github/workflows/ci.prod.yml index eb4fa64..811e7a7 100644 --- a/.github/workflows/ci.prod.yml +++ b/.github/workflows/ci.prod.yml @@ -78,4 +78,5 @@ jobs: aws ecr get-login-password --region ap-southeast-1 | docker login --username AWS --password-stdin 844772501268.dkr.ecr.ap-southeast-1.amazonaws.com docker pull $DOCKER_IMAGE_WITH_TAG docker stop training-api | true + docker rm training-api | true docker run -p 3001:3001 --name training-api -d $DOCKER_IMAGE_WITH_TAG -e $DB_URI diff --git a/README.md b/README.md index 5348621..966b4fe 100644 --- a/README.md +++ b/README.md @@ -4,4 +4,10 @@ node v20 npm i -npm run start \ No newline at end of file +npm run start + +------ +กรณีที่ต้องการใช้ email service ให้ทำการ set up ดังนี้ + +1. ติดตั้ง [aws cli](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) +2. configure aws credentials ด้วย command `aws configure` (credentials อยู่ใน discord) diff --git a/package-lock.json b/package-lock.json index 7a66bfc..5fa8b12 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@babel/core": "^7.24.3", "@babel/node": "^7.23.9", "@babel/preset-env": "^7.24.3", + "aws-sdk": "^2.1589.0", "body-parser": "^1.20.2", "cors": "^2.8.5", "dotenv": "^16.4.5", @@ -1802,6 +1803,27 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/aws-sdk": { + "version": "2.1589.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1589.0.tgz", + "integrity": "sha512-Tt3UHH6hoUEAjbCscqvfEAoq9VSTN5iSQO9XSisiiH/QJo8sf+iLCYmfJHM4tVkd92bQH61/xxj9t2Mazwc/WQ==", + "hasInstallScript": true, + "dependencies": { + "buffer": "4.9.2", + "events": "1.1.1", + "ieee754": "1.1.13", + "jmespath": "0.16.0", + "querystring": "0.2.0", + "sax": "1.2.1", + "url": "0.10.3", + "util": "^0.12.4", + "uuid": "8.0.0", + "xml2js": "0.6.2" + }, + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/babel-plugin-polyfill-corejs2": { "version": "0.4.10", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.10.tgz", @@ -1844,6 +1866,25 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", @@ -1953,11 +1994,26 @@ "node": ">=16.20.1" } }, + "node_modules/buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, + "node_modules/buffer/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -2458,6 +2514,14 @@ "node": ">= 0.6" } }, + "node_modules/events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw==", + "engines": { + "node": ">=0.4.x" + } + }, "node_modules/express": { "version": "4.19.2", "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", @@ -2847,6 +2911,11 @@ "node": ">=0.10.0" } }, + "node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, "node_modules/ignore-by-default": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", @@ -2879,6 +2948,21 @@ "node": ">= 0.10" } }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-array-buffer": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", @@ -2991,6 +3075,20 @@ "node": ">=0.10.0" } }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -3143,6 +3241,14 @@ "node": ">=0.10.0" } }, + "node_modules/jmespath": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz", + "integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -3749,6 +3855,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==", + "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", + "engines": { + "node": ">=0.4.x" + } + }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -3937,6 +4052,11 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "node_modules/sax": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", + "integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==" + }, "node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -4439,6 +4559,32 @@ "browserslist": ">= 4.21.0" } }, + "node_modules/url": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", + "integrity": "sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ==", + "dependencies": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "node_modules/url/node_modules/punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==" + }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -4447,6 +4593,14 @@ "node": ">= 0.4.0" } }, + "node_modules/uuid": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz", + "integrity": "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/v8flags": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", @@ -4519,6 +4673,26 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/xml2js": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz", + "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "engines": { + "node": ">=4.0" + } + }, "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", diff --git a/package.json b/package.json index a7bdb29..6669d84 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "@babel/core": "^7.24.3", "@babel/node": "^7.23.9", "@babel/preset-env": "^7.24.3", + "aws-sdk": "^2.1589.0", "body-parser": "^1.20.2", "cors": "^2.8.5", "dotenv": "^16.4.5", diff --git a/src/controllers/reminder.js b/src/controllers/reminder.js index 8bf6faa..5597f6f 100644 --- a/src/controllers/reminder.js +++ b/src/controllers/reminder.js @@ -1,46 +1,17 @@ -const createContent = function (class_detail, enrollmentInfo) { - return `Hello ${enrollmentInfo.fullName}
Welcome! Also looking forward to joining with you for 3 days of Certified LeSS Practitioner: Principles to Practices by Bas Vodde.
` -} +const classService = require('../services/classes'); +const enrollmentService = require('../services/classes'); const setEmailClassReminder = function (req, res){ - - const classes = [{ - id: 1, - description: `ตอนผู้สอนทั้ง 2 มาเป็น ScrumMaster ใหม่ ๆ เราพบช่วงเวลายากลำบากหลายครั้ง`, - place:"Geeky Base All Star", - googleMapUrl: "https://maps.app.goo.gl/UQKuNzejJNNwVB2K9", - startDate: "2024-03-22T04:51:16.100Z", - endDate: "31/3/2024", - instructor: [{name: 'Jane'}] - }, - { - id: 2, - description: `ตอนผู้สอนทั้ง 2 มาเป็น ScrumMaster ใหม่ ๆ เราพบช่วงเวลายากลำบากหลายครั้ง`, - place:"Geeky Base All Star", - googleMapUrl: "https://maps.app.goo.gl/UQKuNzejJNNwVB2K9", - startDate: "2024-03-22T04:51:16.100Z", - endDate: "31/3/2024", - instructor: [{name: 'Jane'}] - }] - - for (let cls in classes) { - const enrollmentInfo = { - classId: 1, - email: 1, - fullName: "Roofimon", - } - const content = createContent(cls, enrollmentInfo); - console.log(content) - const startDate = new Date(cls.startDate) - console.log("ss", startDate) - const dateNow = Date.now() - // if (startDate.getDate() - 5 === dateNow) { - // // sendEmail(enrollmentInfo.email, cls.name, content); - // console.log("Send email") - // } - } - - res.send("Success") + const classesData = classService.getClasses(); + for (let cls in classesData) { + const enrollmentData = enrollmentService.getEnrollmentByClassId(cls.classId) + const startDate = new Date(cls.startDate) + const dateNow = Date.now() + if (startDate.getDate() - 5 === dateNow) { + sendEmail(enrollmentData.email, cls.name, cls.preClassContent); + } + } + res.send("Success") } exports.setEmailClassReminder = setEmailClassReminder; \ No newline at end of file diff --git a/src/services/enrollment.js b/src/services/enrollment.js index d652003..dd20315 100644 --- a/src/services/enrollment.js +++ b/src/services/enrollment.js @@ -7,3 +7,12 @@ export const create = async (body) => { console.log(error); } }; + +export const getEnrollmentByClassId = async (classId) => { + try { + const data = await EnrollmentModel.findOne({ classId }); + return data; + } catch (error) { + console.log(error); + } +}; diff --git a/src/services/mailingService.js b/src/services/mailingService.js new file mode 100644 index 0000000..990ec4a --- /dev/null +++ b/src/services/mailingService.js @@ -0,0 +1,45 @@ +var AWS = require("aws-sdk"); + +AWS.config.update({ region: "ap-southeast-1" }); + +class MailingService { + ses = new AWS.SES({ apiVersion: "2010-12-01" }); + + sendEmail(to, cc, subject, message) { + var ccList = []; + if (cc != "") { + ccList = cc.split(","); + } + + var params = { + Destination: { + ToAddresses: to.split(","), + CcAddresses: ccList, + }, + Message: { + Body: { + Text: { + Charset: "UTF-8", + Data: message, + }, + }, + Subject: { + Charset: "UTF-8", + Data: subject, + }, + }, + Source: "jane@odds.team", + ReplyToAddresses: [], + }; + + this.ses.sendEmail(params, (err, data) => { + if (err) { + console.log("Error sending email:", err); + } else { + console.log("Email sent:", data); + } + }); + } +} + +module.exports = MailingService;