More work on reservation waiting list support: adding waiting list module and connecting to email queue
This commit is contained in:
parent
56dda6fd28
commit
e7503e3074
12 changed files with 248 additions and 300 deletions
309
package-lock.json
generated
309
package-lock.json
generated
|
|
@ -21,7 +21,8 @@
|
||||||
"class-transformer": "^0.5.1",
|
"class-transformer": "^0.5.1",
|
||||||
"class-validator": "^0.14.0",
|
"class-validator": "^0.14.0",
|
||||||
"dayjs": "^1.11.7",
|
"dayjs": "^1.11.7",
|
||||||
"imapflow": "^1.0.134",
|
"imap": "^0.8.19",
|
||||||
|
"mailparser-mit": "^1.0.0",
|
||||||
"puppeteer": "^20.4.0",
|
"puppeteer": "^20.4.0",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rxjs": "^7.2.0",
|
"rxjs": "^7.2.0",
|
||||||
|
|
@ -34,8 +35,8 @@
|
||||||
"@types/cron": "^2.0.1",
|
"@types/cron": "^2.0.1",
|
||||||
"@types/express": "^4.17.13",
|
"@types/express": "^4.17.13",
|
||||||
"@types/imap": "^0.8.37",
|
"@types/imap": "^0.8.37",
|
||||||
"@types/imapflow": "^1.0.13",
|
|
||||||
"@types/jest": "29.5.1",
|
"@types/jest": "29.5.1",
|
||||||
|
"@types/mailparser-mit": "^1.0.1",
|
||||||
"@types/node": "18.16.12",
|
"@types/node": "18.16.12",
|
||||||
"@types/puppeteer": "^7.0.4",
|
"@types/puppeteer": "^7.0.4",
|
||||||
"@types/supertest": "^2.0.11",
|
"@types/supertest": "^2.0.11",
|
||||||
|
|
@ -45,7 +46,6 @@
|
||||||
"eslint-config-prettier": "^8.3.0",
|
"eslint-config-prettier": "^8.3.0",
|
||||||
"eslint-plugin-prettier": "^4.0.0",
|
"eslint-plugin-prettier": "^4.0.0",
|
||||||
"eslint-plugin-simple-import-sort": "^10.0.0",
|
"eslint-plugin-simple-import-sort": "^10.0.0",
|
||||||
"imap": "^0.8.19",
|
|
||||||
"jest": "29.5.0",
|
"jest": "29.5.0",
|
||||||
"prettier": "^2.3.2",
|
"prettier": "^2.3.2",
|
||||||
"source-map-support": "^0.5.20",
|
"source-map-support": "^0.5.20",
|
||||||
|
|
@ -2596,15 +2596,6 @@
|
||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/imapflow": {
|
|
||||||
"version": "1.0.13",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/imapflow/-/imapflow-1.0.13.tgz",
|
|
||||||
"integrity": "sha512-TD8h02jSTDsXTE79HL0cSkjrU/ufXmSIsZv96O2sNBDA1VluqzKkjV2LrXSPIuXE1tn7JhND7o0iyP4r7haNFw==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@types/node": "*"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@types/istanbul-lib-coverage": {
|
"node_modules/@types/istanbul-lib-coverage": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz",
|
||||||
|
|
@ -2650,6 +2641,15 @@
|
||||||
"integrity": "sha512-uKRI5QORDnrGFYgcdAVnHvEIvEZ8noTpP/Bg+HeUzZghwinDlIS87DEenV5r1YoOF9G4x600YsUXLWZ19rmTmg==",
|
"integrity": "sha512-uKRI5QORDnrGFYgcdAVnHvEIvEZ8noTpP/Bg+HeUzZghwinDlIS87DEenV5r1YoOF9G4x600YsUXLWZ19rmTmg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/mailparser-mit": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/mailparser-mit/-/mailparser-mit-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-OKfkaDuyIOTixMDv5a3ypKXPFb2oY3NVKUlLrhQGkqFh6VwiE1sfzGnKCiMPKcvBEUwi7sqyZpAzcTMP6zxqJw==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/mime": {
|
"node_modules/@types/mime": {
|
||||||
"version": "1.3.2",
|
"version": "1.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz",
|
||||||
|
|
@ -3152,17 +3152,6 @@
|
||||||
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
||||||
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
|
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
|
||||||
},
|
},
|
||||||
"node_modules/abort-controller": {
|
|
||||||
"version": "3.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
|
|
||||||
"integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
|
|
||||||
"dependencies": {
|
|
||||||
"event-target-shim": "^5.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6.5"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/accepts": {
|
"node_modules/accepts": {
|
||||||
"version": "1.3.8",
|
"version": "1.3.8",
|
||||||
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
|
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
|
||||||
|
|
@ -3211,6 +3200,11 @@
|
||||||
"node": ">=0.4.0"
|
"node": ">=0.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/addressparser": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/addressparser/-/addressparser-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-aQX7AISOMM7HFE0iZ3+YnD07oIeJqWGVnJ+ZIKaBZAk03ftmVYVqsGas/rbXKR21n4D/hKCSHypvcyOkds/xzg=="
|
||||||
|
},
|
||||||
"node_modules/agent-base": {
|
"node_modules/agent-base": {
|
||||||
"version": "6.0.2",
|
"version": "6.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
|
||||||
|
|
@ -3460,14 +3454,6 @@
|
||||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
|
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/atomic-sleep": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz",
|
|
||||||
"integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/babel-jest": {
|
"node_modules/babel-jest": {
|
||||||
"version": "29.5.0",
|
"version": "29.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.5.0.tgz",
|
||||||
|
|
@ -4797,14 +4783,6 @@
|
||||||
"iconv-lite": "^0.6.2"
|
"iconv-lite": "^0.6.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/encoding-japanese": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/encoding-japanese/-/encoding-japanese-2.0.0.tgz",
|
|
||||||
"integrity": "sha512-++P0RhebUC8MJAwJOsT93dT+5oc5oPImp1HubZpAuCZ5kTLnhuuBhKHj2jJeO/Gj93idPBWmIuQ9QWMe5rX3pQ==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8.10.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/end-of-stream": {
|
"node_modules/end-of-stream": {
|
||||||
"version": "1.4.4",
|
"version": "1.4.4",
|
||||||
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
|
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
|
||||||
|
|
@ -5361,14 +5339,6 @@
|
||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/event-target-shim": {
|
|
||||||
"version": "5.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
|
|
||||||
"integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/events": {
|
"node_modules/events": {
|
||||||
"version": "3.3.0",
|
"version": "3.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
|
||||||
|
|
@ -5544,6 +5514,11 @@
|
||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/extend": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
||||||
|
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
|
||||||
|
},
|
||||||
"node_modules/external-editor": {
|
"node_modules/external-editor": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
|
||||||
|
|
@ -5636,14 +5611,6 @@
|
||||||
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
|
||||||
"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="
|
"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="
|
||||||
},
|
},
|
||||||
"node_modules/fast-redact": {
|
|
||||||
"version": "3.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.2.0.tgz",
|
|
||||||
"integrity": "sha512-zaTadChr+NekyzallAMXATXLOR8MNx3zqpZ0MUF2aGf4EathnG0f32VLODNlY8IuGY3HoRO2L6/6fSzNsLaHIw==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/fast-safe-stringify": {
|
"node_modules/fast-safe-stringify": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz",
|
||||||
|
|
@ -6337,6 +6304,7 @@
|
||||||
"version": "0.6.3",
|
"version": "0.6.3",
|
||||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
||||||
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
|
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
|
||||||
|
"optional": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
||||||
},
|
},
|
||||||
|
|
@ -6376,7 +6344,6 @@
|
||||||
"version": "0.8.19",
|
"version": "0.8.19",
|
||||||
"resolved": "https://registry.npmjs.org/imap/-/imap-0.8.19.tgz",
|
"resolved": "https://registry.npmjs.org/imap/-/imap-0.8.19.tgz",
|
||||||
"integrity": "sha512-z5DxEA1uRnZG73UcPA4ES5NSCGnPuuouUx43OPX7KZx1yzq3N8/vx2mtXEShT5inxB3pRgnfG1hijfu7XN2YMw==",
|
"integrity": "sha512-z5DxEA1uRnZG73UcPA4ES5NSCGnPuuouUx43OPX7KZx1yzq3N8/vx2mtXEShT5inxB3pRgnfG1hijfu7XN2YMw==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"readable-stream": "1.1.x",
|
"readable-stream": "1.1.x",
|
||||||
"utf7": ">=1.0.2"
|
"utf7": ">=1.0.2"
|
||||||
|
|
@ -6388,14 +6355,12 @@
|
||||||
"node_modules/imap/node_modules/isarray": {
|
"node_modules/imap/node_modules/isarray": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
|
||||||
"integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==",
|
"integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/imap/node_modules/readable-stream": {
|
"node_modules/imap/node_modules/readable-stream": {
|
||||||
"version": "1.1.14",
|
"version": "1.1.14",
|
||||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
|
||||||
"integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==",
|
"integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"core-util-is": "~1.0.0",
|
"core-util-is": "~1.0.0",
|
||||||
"inherits": "~2.0.1",
|
"inherits": "~2.0.1",
|
||||||
|
|
@ -6406,24 +6371,7 @@
|
||||||
"node_modules/imap/node_modules/string_decoder": {
|
"node_modules/imap/node_modules/string_decoder": {
|
||||||
"version": "0.10.31",
|
"version": "0.10.31",
|
||||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
|
||||||
"integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==",
|
"integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ=="
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/imapflow": {
|
|
||||||
"version": "1.0.134",
|
|
||||||
"resolved": "https://registry.npmjs.org/imapflow/-/imapflow-1.0.134.tgz",
|
|
||||||
"integrity": "sha512-giJ9Byi89fzt5T7WHdroZonOoSQ9k7Bi9cSmfRT6zGC/v6/gKFnNG0xyoYyxpiKsJvYRImUsG6MBEKVdlbp2Eg==",
|
|
||||||
"dependencies": {
|
|
||||||
"encoding-japanese": "2.0.0",
|
|
||||||
"iconv-lite": "0.6.3",
|
|
||||||
"libbase64": "1.2.1",
|
|
||||||
"libmime": "5.2.1",
|
|
||||||
"libqp": "2.0.1",
|
|
||||||
"mailsplit": "5.4.0",
|
|
||||||
"nodemailer": "6.9.4",
|
|
||||||
"pino": "8.14.1",
|
|
||||||
"socks": "2.7.1"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"node_modules/import-fresh": {
|
"node_modules/import-fresh": {
|
||||||
"version": "3.3.0",
|
"version": "3.3.0",
|
||||||
|
|
@ -8576,32 +8524,11 @@
|
||||||
"node": ">= 0.8.0"
|
"node": ">= 0.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/libbase64": {
|
|
||||||
"version": "1.2.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/libbase64/-/libbase64-1.2.1.tgz",
|
|
||||||
"integrity": "sha512-l+nePcPbIG1fNlqMzrh68MLkX/gTxk/+vdvAb388Ssi7UuUN31MI44w4Yf33mM3Cm4xDfw48mdf3rkdHszLNew=="
|
|
||||||
},
|
|
||||||
"node_modules/libmime": {
|
|
||||||
"version": "5.2.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/libmime/-/libmime-5.2.1.tgz",
|
|
||||||
"integrity": "sha512-A0z9O4+5q+ZTj7QwNe/Juy1KARNb4WaviO4mYeFC4b8dBT2EEqK2pkM+GC8MVnkOjqhl5nYQxRgnPYRRTNmuSQ==",
|
|
||||||
"dependencies": {
|
|
||||||
"encoding-japanese": "2.0.0",
|
|
||||||
"iconv-lite": "0.6.3",
|
|
||||||
"libbase64": "1.2.1",
|
|
||||||
"libqp": "2.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/libphonenumber-js": {
|
"node_modules/libphonenumber-js": {
|
||||||
"version": "1.10.30",
|
"version": "1.10.30",
|
||||||
"resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.30.tgz",
|
"resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.30.tgz",
|
||||||
"integrity": "sha512-PLGc+xfrQrkya/YK2/5X+bPpxRmyJBHM+xxz9krUdSgk4Vs2ZwxX5/Ow0lv3r9PDlDtNWb4u+it8MY5rZ0IyGw=="
|
"integrity": "sha512-PLGc+xfrQrkya/YK2/5X+bPpxRmyJBHM+xxz9krUdSgk4Vs2ZwxX5/Ow0lv3r9PDlDtNWb4u+it8MY5rZ0IyGw=="
|
||||||
},
|
},
|
||||||
"node_modules/libqp": {
|
|
||||||
"version": "2.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/libqp/-/libqp-2.0.1.tgz",
|
|
||||||
"integrity": "sha512-Ka0eC5LkF3IPNQHJmYBWljJsw0UvM6j+QdKRbWyCdTmYwvIDE6a7bCm0UkTAL/K+3KXK5qXT/ClcInU01OpdLg=="
|
|
||||||
},
|
|
||||||
"node_modules/lines-and-columns": {
|
"node_modules/lines-and-columns": {
|
||||||
"version": "1.2.4",
|
"version": "1.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
|
||||||
|
|
@ -8774,25 +8701,26 @@
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/mailsplit": {
|
"node_modules/mailparser-mit": {
|
||||||
"version": "5.4.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/mailsplit/-/mailsplit-5.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/mailparser-mit/-/mailparser-mit-1.0.0.tgz",
|
||||||
"integrity": "sha512-wnYxX5D5qymGIPYLwnp6h8n1+6P6vz/MJn5AzGjZ8pwICWssL+CCQjWBIToOVHASmATot4ktvlLo6CyLfOXWYA==",
|
"integrity": "sha512-sckRITNb3VCT1sQ275g47MAN786pQ5lU20bLY5f794dF/ARGzuVATQ64gO13FOw8jayjFT10e5ttsripKGGXcw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"libbase64": "1.2.1",
|
"addressparser": "^1.0.1",
|
||||||
"libmime": "5.2.0",
|
"iconv-lite": "~0.4.24",
|
||||||
"libqp": "2.0.1"
|
"mime": "^1.6.0",
|
||||||
|
"uue": "^3.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/mailsplit/node_modules/libmime": {
|
"node_modules/mailparser-mit/node_modules/iconv-lite": {
|
||||||
"version": "5.2.0",
|
"version": "0.4.24",
|
||||||
"resolved": "https://registry.npmjs.org/libmime/-/libmime-5.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||||
"integrity": "sha512-X2U5Wx0YmK0rXFbk67ASMeqYIkZ6E5vY7pNWRKtnNzqjvdYYG8xtPDpCnuUEnPU9vlgNev+JoSrcaKSUaNvfsw==",
|
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"encoding-japanese": "2.0.0",
|
"safer-buffer": ">= 2.1.2 < 3"
|
||||||
"iconv-lite": "0.6.3",
|
},
|
||||||
"libbase64": "1.2.1",
|
"engines": {
|
||||||
"libqp": "2.0.1"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/make-dir": {
|
"node_modules/make-dir": {
|
||||||
|
|
@ -9331,14 +9259,6 @@
|
||||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.8.tgz",
|
||||||
"integrity": "sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A=="
|
"integrity": "sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A=="
|
||||||
},
|
},
|
||||||
"node_modules/nodemailer": {
|
|
||||||
"version": "6.9.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.4.tgz",
|
|
||||||
"integrity": "sha512-CXjQvrQZV4+6X5wP6ZIgdehJamI63MFoYFGGPtHudWym9qaEHDNdPzaj5bfMCvxG1vhAileSWW90q7nL0N36mA==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/nopt": {
|
"node_modules/nopt": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
|
||||||
|
|
@ -9399,11 +9319,6 @@
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/on-exit-leak-free": {
|
|
||||||
"version": "2.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.0.tgz",
|
|
||||||
"integrity": "sha512-VuCaZZAjReZ3vUwgOB8LxAosIurDiAW0s13rI1YwmaP++jvcxP77AWoQvenZebpCA2m8WC1/EosPYPMjnRAp/w=="
|
|
||||||
},
|
|
||||||
"node_modules/on-finished": {
|
"node_modules/on-finished": {
|
||||||
"version": "2.4.1",
|
"version": "2.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
|
||||||
|
|
@ -9846,79 +9761,6 @@
|
||||||
"url": "https://github.com/sponsors/jonschlinkert"
|
"url": "https://github.com/sponsors/jonschlinkert"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/pino": {
|
|
||||||
"version": "8.14.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/pino/-/pino-8.14.1.tgz",
|
|
||||||
"integrity": "sha512-8LYNv7BKWXSfS+k6oEc6occy5La+q2sPwU3q2ljTX5AZk7v+5kND2o5W794FyRaqha6DJajmkNRsWtPpFyMUdw==",
|
|
||||||
"dependencies": {
|
|
||||||
"atomic-sleep": "^1.0.0",
|
|
||||||
"fast-redact": "^3.1.1",
|
|
||||||
"on-exit-leak-free": "^2.1.0",
|
|
||||||
"pino-abstract-transport": "v1.0.0",
|
|
||||||
"pino-std-serializers": "^6.0.0",
|
|
||||||
"process-warning": "^2.0.0",
|
|
||||||
"quick-format-unescaped": "^4.0.3",
|
|
||||||
"real-require": "^0.2.0",
|
|
||||||
"safe-stable-stringify": "^2.3.1",
|
|
||||||
"sonic-boom": "^3.1.0",
|
|
||||||
"thread-stream": "^2.0.0"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"pino": "bin.js"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/pino-abstract-transport": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.0.0.tgz",
|
|
||||||
"integrity": "sha512-c7vo5OpW4wIS42hUVcT5REsL8ZljsUfBjqV/e2sFxmFEFZiq1XLUp5EYLtuDH6PEHq9W1egWqRbnLUP5FuZmOA==",
|
|
||||||
"dependencies": {
|
|
||||||
"readable-stream": "^4.0.0",
|
|
||||||
"split2": "^4.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/pino-abstract-transport/node_modules/buffer": {
|
|
||||||
"version": "6.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
|
|
||||||
"integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/feross"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "patreon",
|
|
||||||
"url": "https://www.patreon.com/feross"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "consulting",
|
|
||||||
"url": "https://feross.org/support"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"dependencies": {
|
|
||||||
"base64-js": "^1.3.1",
|
|
||||||
"ieee754": "^1.2.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/pino-abstract-transport/node_modules/readable-stream": {
|
|
||||||
"version": "4.4.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.4.2.tgz",
|
|
||||||
"integrity": "sha512-Lk/fICSyIhodxy1IDK2HazkeGjSmezAWX2egdtJnYhtzKEsBPJowlI6F6LPb5tqIQILrMbx22S5o3GuJavPusA==",
|
|
||||||
"dependencies": {
|
|
||||||
"abort-controller": "^3.0.0",
|
|
||||||
"buffer": "^6.0.3",
|
|
||||||
"events": "^3.3.0",
|
|
||||||
"process": "^0.11.10",
|
|
||||||
"string_decoder": "^1.3.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/pino-std-serializers": {
|
|
||||||
"version": "6.2.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz",
|
|
||||||
"integrity": "sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA=="
|
|
||||||
},
|
|
||||||
"node_modules/pirates": {
|
"node_modules/pirates": {
|
||||||
"version": "4.0.5",
|
"version": "4.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz",
|
||||||
|
|
@ -10010,24 +9852,11 @@
|
||||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/process": {
|
|
||||||
"version": "0.11.10",
|
|
||||||
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
|
|
||||||
"integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.6.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/process-nextick-args": {
|
"node_modules/process-nextick-args": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||||
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
|
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
|
||||||
},
|
},
|
||||||
"node_modules/process-warning": {
|
|
||||||
"version": "2.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/process-warning/-/process-warning-2.2.0.tgz",
|
|
||||||
"integrity": "sha512-/1WZ8+VQjR6avWOgHeEPd7SDQmFQ1B5mC1eRXsCm5TarlNmx/wCsa5GEaxGm05BORRtyG/Ex/3xq3TuRvq57qg=="
|
|
||||||
},
|
|
||||||
"node_modules/progress": {
|
"node_modules/progress": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
|
||||||
|
|
@ -10261,11 +10090,6 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/quick-format-unescaped": {
|
|
||||||
"version": "4.0.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz",
|
|
||||||
"integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg=="
|
|
||||||
},
|
|
||||||
"node_modules/randombytes": {
|
"node_modules/randombytes": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
||||||
|
|
@ -10337,14 +10161,6 @@
|
||||||
"node": ">=8.10.0"
|
"node": ">=8.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/real-require": {
|
|
||||||
"version": "0.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz",
|
|
||||||
"integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 12.13.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/rechoir": {
|
"node_modules/rechoir": {
|
||||||
"version": "0.6.2",
|
"version": "0.6.2",
|
||||||
"resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
|
||||||
|
|
@ -10571,14 +10387,6 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/safe-stable-stringify": {
|
|
||||||
"version": "2.4.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz",
|
|
||||||
"integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/safer-buffer": {
|
"node_modules/safer-buffer": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||||
|
|
@ -10798,14 +10606,6 @@
|
||||||
"node": ">= 10"
|
"node": ">= 10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/sonic-boom": {
|
|
||||||
"version": "3.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.3.0.tgz",
|
|
||||||
"integrity": "sha512-LYxp34KlZ1a2Jb8ZQgFCK3niIHzibdwtwNUWKg0qQRzsDoJ3Gfgkf8KdBTFU3SkejDEIlWwnSnpVdOZIhFMl/g==",
|
|
||||||
"dependencies": {
|
|
||||||
"atomic-sleep": "^1.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/source-map": {
|
"node_modules/source-map": {
|
||||||
"version": "0.6.1",
|
"version": "0.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||||
|
|
@ -10823,14 +10623,6 @@
|
||||||
"source-map": "^0.6.0"
|
"source-map": "^0.6.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/split2": {
|
|
||||||
"version": "4.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
|
|
||||||
"integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10.x"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/sprintf-js": {
|
"node_modules/sprintf-js": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
||||||
|
|
@ -11259,14 +11051,6 @@
|
||||||
"node": ">=0.8"
|
"node": ">=0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/thread-stream": {
|
|
||||||
"version": "2.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.3.0.tgz",
|
|
||||||
"integrity": "sha512-kaDqm1DET9pp3NXwR8382WHbnpXnRkN9xGN9dQt3B2+dmXiW8X1SOwmFOxAErEQ47ObhZ96J6yhZNXuyCOL7KA==",
|
|
||||||
"dependencies": {
|
|
||||||
"real-require": "^0.2.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/through": {
|
"node_modules/through": {
|
||||||
"version": "2.3.8",
|
"version": "2.3.8",
|
||||||
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
||||||
|
|
@ -12063,7 +11847,6 @@
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/utf7/-/utf7-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/utf7/-/utf7-1.0.2.tgz",
|
||||||
"integrity": "sha512-qQrPtYLLLl12NF4DrM9CvfkxkYI97xOb5dsnGZHE3teFr0tWiEZ9UdgMPczv24vl708cYMpe6mGXGHrotIp3Bw==",
|
"integrity": "sha512-qQrPtYLLLl12NF4DrM9CvfkxkYI97xOb5dsnGZHE3teFr0tWiEZ9UdgMPczv24vl708cYMpe6mGXGHrotIp3Bw==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"semver": "~5.3.0"
|
"semver": "~5.3.0"
|
||||||
}
|
}
|
||||||
|
|
@ -12072,7 +11855,6 @@
|
||||||
"version": "5.3.0",
|
"version": "5.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
|
||||||
"integrity": "sha512-mfmm3/H9+67MCVix1h+IXTpDwL6710LyHuk7+cWC9T1mE0qz4iHhh6r4hU2wrIT9iTsAAC2XQRvfblL028cpLw==",
|
"integrity": "sha512-mfmm3/H9+67MCVix1h+IXTpDwL6710LyHuk7+cWC9T1mE0qz4iHhh6r4hU2wrIT9iTsAAC2XQRvfblL028cpLw==",
|
||||||
"dev": true,
|
|
||||||
"bin": {
|
"bin": {
|
||||||
"semver": "bin/semver"
|
"semver": "bin/semver"
|
||||||
}
|
}
|
||||||
|
|
@ -12090,6 +11872,15 @@
|
||||||
"node": ">= 0.4.0"
|
"node": ">= 0.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/uue": {
|
||||||
|
"version": "3.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/uue/-/uue-3.1.2.tgz",
|
||||||
|
"integrity": "sha512-axKLXVqwtdI/czrjG0X8hyV1KLgeWx8F4KvSbvVCnS+RUvsQMGRjx0kfuZDXXqj0LYvVJmx3B9kWlKtEdRrJLg==",
|
||||||
|
"dependencies": {
|
||||||
|
"escape-string-regexp": "~1.0.5",
|
||||||
|
"extend": "~3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/uuid": {
|
"node_modules/uuid": {
|
||||||
"version": "8.3.2",
|
"version": "8.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@
|
||||||
"class-validator": "^0.14.0",
|
"class-validator": "^0.14.0",
|
||||||
"dayjs": "^1.11.7",
|
"dayjs": "^1.11.7",
|
||||||
"imap": "^0.8.19",
|
"imap": "^0.8.19",
|
||||||
|
"mailparser-mit": "^1.0.0",
|
||||||
"puppeteer": "^20.4.0",
|
"puppeteer": "^20.4.0",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rxjs": "^7.2.0",
|
"rxjs": "^7.2.0",
|
||||||
|
|
@ -51,6 +52,7 @@
|
||||||
"@types/express": "^4.17.13",
|
"@types/express": "^4.17.13",
|
||||||
"@types/imap": "^0.8.37",
|
"@types/imap": "^0.8.37",
|
||||||
"@types/jest": "29.5.1",
|
"@types/jest": "29.5.1",
|
||||||
|
"@types/mailparser-mit": "^1.0.1",
|
||||||
"@types/node": "18.16.12",
|
"@types/node": "18.16.12",
|
||||||
"@types/puppeteer": "^7.0.4",
|
"@types/puppeteer": "^7.0.4",
|
||||||
"@types/supertest": "^2.0.11",
|
"@types/supertest": "^2.0.11",
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import { LoggerModule } from './logger/module'
|
||||||
import { RecurringReservationsModule } from './recurringReservations/module'
|
import { RecurringReservationsModule } from './recurringReservations/module'
|
||||||
import { ReservationsModule } from './reservations/module'
|
import { ReservationsModule } from './reservations/module'
|
||||||
import { RunnerModule } from './runner/module'
|
import { RunnerModule } from './runner/module'
|
||||||
|
import { WaitingListModule } from './waitingList/module'
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
|
|
@ -48,6 +49,7 @@ import { RunnerModule } from './runner/module'
|
||||||
RunnerModule,
|
RunnerModule,
|
||||||
LoggerModule,
|
LoggerModule,
|
||||||
EmailModule,
|
EmailModule,
|
||||||
|
WaitingListModule,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class AppModule implements NestModule {
|
export class AppModule implements NestModule {
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
import { Inject, Injectable } from '@nestjs/common'
|
import { Inject, Injectable } from '@nestjs/common'
|
||||||
import { ConfigService } from '@nestjs/config'
|
import { ConfigService } from '@nestjs/config'
|
||||||
import { Dayjs } from 'dayjs'
|
|
||||||
import * as Imap from 'imap'
|
import * as Imap from 'imap'
|
||||||
|
import { MailParser, ParsedEmail } from 'mailparser-mit'
|
||||||
|
|
||||||
import dayjs from '../common/dayjs'
|
|
||||||
import { LoggerService } from '../logger/service'
|
import { LoggerService } from '../logger/service'
|
||||||
import { Email } from './types'
|
import { Email } from './types'
|
||||||
|
|
||||||
|
|
@ -59,12 +58,12 @@ export class EmailClient {
|
||||||
if (current > max) {
|
if (current > max) {
|
||||||
throw Error(`Max attempts reached for ${label}`)
|
throw Error(`Max attempts reached for ${label}`)
|
||||||
}
|
}
|
||||||
this.loggerService.log(`Attempting ${label} [${current} / ${max}]`)
|
this.loggerService.debug(`Attempting ${label} [${current} / ${max}]`)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
fn()
|
fn()
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
this.loggerService.warn(
|
this.loggerService.debug(
|
||||||
`Attempting ${label} hit error at attempt ${current}`,
|
`Attempting ${label} hit error at attempt ${current}`,
|
||||||
)
|
)
|
||||||
setTimeout(
|
setTimeout(
|
||||||
|
|
@ -85,6 +84,10 @@ export class EmailClient {
|
||||||
messages: { total: totalMessages, new: newMessages },
|
messages: { total: totalMessages, new: newMessages },
|
||||||
} = mailbox
|
} = mailbox
|
||||||
|
|
||||||
|
this.loggerService.debug(
|
||||||
|
`Total messages: ${totalMessages}; New messages: ${newMessages}; Received messages: ${numMessages}`,
|
||||||
|
)
|
||||||
|
|
||||||
if (newMessages > 0) {
|
if (newMessages > 0) {
|
||||||
const startingMessage = totalMessages - newMessages + 1 // starting message is inclusive
|
const startingMessage = totalMessages - newMessages + 1 // starting message is inclusive
|
||||||
const emails = await this.fetchMails(`${startingMessage}`, '*')
|
const emails = await this.fetchMails(`${startingMessage}`, '*')
|
||||||
|
|
@ -132,47 +135,36 @@ export class EmailClient {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private async generateEmailBody(
|
|
||||||
stream: NodeJS.ReadableStream,
|
|
||||||
): Promise<Buffer> {
|
|
||||||
return new Promise<Buffer>((res, rej) => {
|
|
||||||
const bufferData: any[] = []
|
|
||||||
stream.on('data', (chunk) => {
|
|
||||||
bufferData.push(chunk)
|
|
||||||
})
|
|
||||||
stream.on('end', () => {
|
|
||||||
res(Buffer.concat(bufferData))
|
|
||||||
})
|
|
||||||
stream.on('error', (error: Error) => rej(error))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
private async generateEmail(msg: Imap.ImapMessage): Promise<Email> {
|
private async generateEmail(msg: Imap.ImapMessage): Promise<Email> {
|
||||||
return new Promise((res, rej) => {
|
return new Promise((res, rej) => {
|
||||||
let id: number
|
const mailParser = new MailParser({ defaultCharset: 'utf-8' })
|
||||||
let date: Dayjs
|
let id: string
|
||||||
let bodyPromise: Promise<Buffer>
|
|
||||||
msg.on('body', async (stream) => {
|
msg.on('body', async (stream) => {
|
||||||
try {
|
try {
|
||||||
bodyPromise = this.generateEmailBody(stream)
|
stream.pipe(mailParser)
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
rej(error)
|
rej(error)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
msg.on('attributes', (attr) => {
|
msg.on('attributes', (attr) => {
|
||||||
id = attr.uid
|
id = `${attr.uid}`
|
||||||
date = dayjs(attr.date)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
msg.on('error', (error: Error) => rej(error))
|
msg.on('error', (error: Error) => rej(error))
|
||||||
|
|
||||||
msg.on('end', async () => {
|
mailParser.on('error', (error: Error) => rej(error))
|
||||||
const body = (await bodyPromise).toString()
|
|
||||||
|
mailParser.on('end', (mail: ParsedEmail) => {
|
||||||
|
const { from = [], subject = '', text = '' } = mail
|
||||||
|
const fromString = from
|
||||||
|
.map(({ address, name }) => `${name} <${address}>`)
|
||||||
|
.join(';')
|
||||||
res({
|
res({
|
||||||
id,
|
id,
|
||||||
date,
|
from: fromString,
|
||||||
body,
|
subject,
|
||||||
|
text,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
@ -186,7 +178,7 @@ export class EmailClient {
|
||||||
`${startingMessageId}:${endingMessageId}`,
|
`${startingMessageId}:${endingMessageId}`,
|
||||||
{
|
{
|
||||||
bodies: '',
|
bodies: '',
|
||||||
struct: true,
|
markSeen: true,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -220,6 +212,10 @@ export class EmailClient {
|
||||||
this.loggerService.debug('email client end')
|
this.loggerService.debug('email client end')
|
||||||
this.setStatus(EmailClientStatus.NotReady)
|
this.setStatus(EmailClientStatus.NotReady)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
this.imapClient.on('error', (error: Error) => {
|
||||||
|
this.loggerService.error(`Error with imap client ${error.message}`)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
public addCustomListener(
|
public addCustomListener(
|
||||||
|
|
|
||||||
1
src/email/config.ts
Normal file
1
src/email/config.ts
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
export const EMAILS_QUEUE_NAME = 'emails'
|
||||||
|
|
@ -1,12 +1,17 @@
|
||||||
|
import { BullModule } from '@nestjs/bull'
|
||||||
import { Module } from '@nestjs/common'
|
import { Module } from '@nestjs/common'
|
||||||
|
|
||||||
import { LoggerModule } from '../logger/module'
|
import { LoggerModule } from '../logger/module'
|
||||||
import { EmailClient } from './client'
|
import { EmailClient } from './client'
|
||||||
|
import { EMAILS_QUEUE_NAME } from './config'
|
||||||
import { EmailProvider } from './provider'
|
import { EmailProvider } from './provider'
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
|
imports: [
|
||||||
|
LoggerModule,
|
||||||
|
BullModule.registerQueue({ name: EMAILS_QUEUE_NAME }),
|
||||||
|
],
|
||||||
providers: [EmailClient, EmailProvider],
|
providers: [EmailClient, EmailProvider],
|
||||||
imports: [LoggerModule],
|
|
||||||
exports: [EmailClient, EmailProvider],
|
exports: [EmailClient, EmailProvider],
|
||||||
})
|
})
|
||||||
export class EmailModule {}
|
export class EmailModule {}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
|
import { InjectQueue } from '@nestjs/bull'
|
||||||
import { Inject, Injectable } from '@nestjs/common'
|
import { Inject, Injectable } from '@nestjs/common'
|
||||||
import { Box } from 'imap'
|
import { Queue } from 'bull'
|
||||||
|
|
||||||
import { LoggerService } from '../logger/service'
|
|
||||||
import { EmailClient } from './client'
|
import { EmailClient } from './client'
|
||||||
|
import { EMAILS_QUEUE_NAME } from './config'
|
||||||
import { Email } from './types'
|
import { Email } from './types'
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
|
@ -11,14 +12,16 @@ export class EmailProvider {
|
||||||
@Inject(EmailClient)
|
@Inject(EmailClient)
|
||||||
private readonly emailClient: EmailClient,
|
private readonly emailClient: EmailClient,
|
||||||
|
|
||||||
@Inject(LoggerService)
|
@InjectQueue(EMAILS_QUEUE_NAME)
|
||||||
private readonly loggerService: LoggerService,
|
private readonly emailsQueue: Queue,
|
||||||
) {
|
) {
|
||||||
this.registerEmailListener()
|
this.registerEmailListener()
|
||||||
}
|
}
|
||||||
|
|
||||||
private async handleReceivedEmails(emails: Email[]) {
|
private async handleReceivedEmails(emails: Email[]) {
|
||||||
this.loggerService.debug(JSON.stringify(emails))
|
this.emailsQueue.addBulk(
|
||||||
|
emails.map((email) => ({ name: email.id, data: email })),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
public registerEmailListener() {
|
public registerEmailListener() {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import { Dayjs } from 'dayjs'
|
|
||||||
|
|
||||||
export interface Email {
|
export interface Email {
|
||||||
id: number
|
id: string
|
||||||
date: Dayjs
|
from: string
|
||||||
body: string
|
subject: string
|
||||||
|
text: string
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,14 @@ export class ReservationsService {
|
||||||
.getMany()
|
.getMany()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getByDateOnWaitingList(date = dayjs()) {
|
||||||
|
return this.reservationsRepository
|
||||||
|
.createQueryBuilder()
|
||||||
|
.where(`DATE(dateRangeStart, '-7 day') = DATE(:date)`, { date })
|
||||||
|
.andWhere('waitListed = true')
|
||||||
|
.getMany()
|
||||||
|
}
|
||||||
|
|
||||||
create(reservation: Reservation) {
|
create(reservation: Reservation) {
|
||||||
return this.reservationsRepository.save(reservation)
|
return this.reservationsRepository.save(reservation)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
20
src/waitingList/module.ts
Normal file
20
src/waitingList/module.ts
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { BullModule } from '@nestjs/bull'
|
||||||
|
import { Module } from '@nestjs/common'
|
||||||
|
import { ReservationsModule } from 'src/reservations/module'
|
||||||
|
|
||||||
|
import { EMAILS_QUEUE_NAME } from '../email/config'
|
||||||
|
import { LoggerModule } from '../logger/module'
|
||||||
|
import { RESERVATIONS_QUEUE_NAME } from '../reservations/config'
|
||||||
|
import { WaitingListService } from './service'
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [
|
||||||
|
LoggerModule,
|
||||||
|
ReservationsModule,
|
||||||
|
BullModule.registerQueue({ name: EMAILS_QUEUE_NAME }),
|
||||||
|
BullModule.registerQueue({ name: RESERVATIONS_QUEUE_NAME }),
|
||||||
|
],
|
||||||
|
providers: [WaitingListService],
|
||||||
|
exports: [WaitingListService],
|
||||||
|
})
|
||||||
|
export class WaitingListModule {}
|
||||||
116
src/waitingList/service.ts
Normal file
116
src/waitingList/service.ts
Normal file
|
|
@ -0,0 +1,116 @@
|
||||||
|
import { InjectQueue, Process, Processor } from '@nestjs/bull'
|
||||||
|
import { Inject } from '@nestjs/common'
|
||||||
|
import { Job, Queue } from 'bull'
|
||||||
|
import { ReservationsService } from 'src/reservations/service'
|
||||||
|
|
||||||
|
import dayjs from '../common/dayjs'
|
||||||
|
import { EMAILS_QUEUE_NAME } from '../email/config'
|
||||||
|
import { Email } from '../email/types'
|
||||||
|
import { LoggerService } from '../logger/service'
|
||||||
|
import { RESERVATIONS_QUEUE_NAME } from '../reservations/config'
|
||||||
|
import { WaitingListDetails } from './types'
|
||||||
|
|
||||||
|
const EMAIL_SUBJECT_REGEX = new RegExp(
|
||||||
|
/^personal waitinglist reservation free at/i,
|
||||||
|
)
|
||||||
|
const EMAIL_ADDRESS = 'Squash City <no-reply@i-reservations.nl>'
|
||||||
|
const EMAIL_DATE_REGEX = new RegExp(
|
||||||
|
/^Datum: ([0-9]{1,2}-[0-9]{1,2}-[0,9]{4})$/im,
|
||||||
|
)
|
||||||
|
const EMAIL_START_TIME_REGEX = new RegExp(
|
||||||
|
/^Begintijd: ([0-9]{1,2}:[0-9]{1,2})$/im,
|
||||||
|
)
|
||||||
|
const EMAIL_END_TIME_REGEX = new RegExp(/^Eindtijd: ([0-9]{1,2}:[0-9]{1,2})$/im)
|
||||||
|
|
||||||
|
@Processor(EMAILS_QUEUE_NAME)
|
||||||
|
export class WaitingListService {
|
||||||
|
constructor(
|
||||||
|
@InjectQueue(RESERVATIONS_QUEUE_NAME)
|
||||||
|
private readonly reservationsQueue: Queue,
|
||||||
|
|
||||||
|
@Inject(ReservationsService)
|
||||||
|
private readonly reservationsService: ReservationsService,
|
||||||
|
|
||||||
|
@Inject(LoggerService)
|
||||||
|
private readonly loggerService: LoggerService,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
@Process()
|
||||||
|
async processEmail(job: Job<Email>) {
|
||||||
|
const { data: email } = job
|
||||||
|
this.loggerService.log('Handling email', {
|
||||||
|
id: email.id,
|
||||||
|
from: email.from,
|
||||||
|
subject: email.subject,
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!this.isRelevantEmail) return
|
||||||
|
|
||||||
|
await this.handleWaitingListEmail(email)
|
||||||
|
}
|
||||||
|
|
||||||
|
private async handleWaitingListEmail(email: Email) {
|
||||||
|
const { date, startTime } = this.getWaitingListDetails(email)
|
||||||
|
const dateRangeStart = dayjs(`${date} ${startTime}`)
|
||||||
|
const reservations = await this.reservationsService.getByDateOnWaitingList(
|
||||||
|
dateRangeStart,
|
||||||
|
)
|
||||||
|
|
||||||
|
if (reservations.length) {
|
||||||
|
this.loggerService.error('Found no reservations on waiting list')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.loggerService.log(
|
||||||
|
`Found ${reservations.length} reservations on waiting list`,
|
||||||
|
)
|
||||||
|
|
||||||
|
await this.reservationsQueue.addBulk(reservations.map((r) => ({ data: r })))
|
||||||
|
}
|
||||||
|
|
||||||
|
private getWaitingListDetails(email: Email): WaitingListDetails {
|
||||||
|
const dateResult = EMAIL_DATE_REGEX.exec(email.text)
|
||||||
|
const startTimeResult = EMAIL_START_TIME_REGEX.exec(email.text)
|
||||||
|
const endTimeResult = EMAIL_END_TIME_REGEX.exec(email.text)
|
||||||
|
|
||||||
|
if (dateResult == null || dateResult[1] == null) {
|
||||||
|
throw new WaitingListDetailsError('Date not found')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (startTimeResult == null || startTimeResult[1] == null) {
|
||||||
|
throw new WaitingListDetailsError('Start time not found')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (endTimeResult == null || endTimeResult[1] == null) {
|
||||||
|
throw new WaitingListDetailsError('End time not found')
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
date: dateResult[1],
|
||||||
|
startTime: startTimeResult[1],
|
||||||
|
endTime: endTimeResult[1],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private isRelevantEmail(email: Email): boolean {
|
||||||
|
if (!EMAIL_SUBJECT_REGEX.test(email.subject)) {
|
||||||
|
this.loggerService.log('Ignoring email, irrelevant subject', {
|
||||||
|
id: email.id,
|
||||||
|
subject: email.subject,
|
||||||
|
})
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EMAIL_ADDRESS !== email.from) {
|
||||||
|
this.loggerService.log('Ignoring email, irrelevant sender', {
|
||||||
|
id: email.id,
|
||||||
|
sender: email.from,
|
||||||
|
})
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class WaitingListDetailsError extends Error {}
|
||||||
5
src/waitingList/types.ts
Normal file
5
src/waitingList/types.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
export interface WaitingListDetails {
|
||||||
|
date: string
|
||||||
|
startTime: string
|
||||||
|
endTime: string
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue