chore: add loger for the telegram sender

This commit is contained in:
mahyargdz
2025-03-28 16:10:12 +03:30
parent cb9860853e
commit 0b62341908
13 changed files with 200 additions and 85 deletions
+2 -2
View File
@@ -60,13 +60,14 @@
"dotenv": "^16.4.7", "dotenv": "^16.4.7",
"fastify": "^5.2.1", "fastify": "^5.2.1",
"handlebars": "^4.7.8", "handlebars": "^4.7.8",
"node-jose": "^2.2.0", "nestjs-telegraf": "^2.8.1",
"nodemailer": "^6.9.16", "nodemailer": "^6.9.16",
"passport-jwt": "^4.0.1", "passport-jwt": "^4.0.1",
"pg": "^8.13.1", "pg": "^8.13.1",
"reflect-metadata": "^0.2.2", "reflect-metadata": "^0.2.2",
"rxjs": "^7.8.1", "rxjs": "^7.8.1",
"slugify": "^1.6.6", "slugify": "^1.6.6",
"telegraf": "^4.16.3",
"typeorm": "^0.3.20" "typeorm": "^0.3.20"
}, },
"devDependencies": { "devDependencies": {
@@ -78,7 +79,6 @@
"@types/bcrypt": "^5.0.2", "@types/bcrypt": "^5.0.2",
"@types/jest": "^29.5.14", "@types/jest": "^29.5.14",
"@types/node": "^20.17.14", "@types/node": "^20.17.14",
"@types/node-jose": "^1.1.13",
"@types/nodemailer": "^6.4.17", "@types/nodemailer": "^6.4.17",
"@types/passport-jwt": "^4.0.1", "@types/passport-jwt": "^4.0.1",
"@types/supertest": "^6.0.2", "@types/supertest": "^6.0.2",
+105 -61
View File
@@ -101,9 +101,9 @@ importers:
handlebars: handlebars:
specifier: ^4.7.8 specifier: ^4.7.8
version: 4.7.8 version: 4.7.8
node-jose: nestjs-telegraf:
specifier: ^2.2.0 specifier: ^2.8.1
version: 2.2.0 version: 2.8.1(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.15(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2)(telegraf@4.16.3)(typescript@5.7.3)
nodemailer: nodemailer:
specifier: ^6.9.16 specifier: ^6.9.16
version: 6.9.16 version: 6.9.16
@@ -122,6 +122,9 @@ importers:
slugify: slugify:
specifier: ^1.6.6 specifier: ^1.6.6
version: 1.6.6 version: 1.6.6
telegraf:
specifier: ^4.16.3
version: 4.16.3
typeorm: typeorm:
specifier: ^0.3.20 specifier: ^0.3.20
version: 0.3.20(ioredis@5.4.2)(pg@8.13.1)(redis@4.7.0)(ts-node@10.9.2(@types/node@20.17.15)(typescript@5.7.3)) version: 0.3.20(ioredis@5.4.2)(pg@8.13.1)(redis@4.7.0)(ts-node@10.9.2(@types/node@20.17.15)(typescript@5.7.3))
@@ -147,9 +150,6 @@ importers:
'@types/node': '@types/node':
specifier: ^20.17.14 specifier: ^20.17.14
version: 20.17.15 version: 20.17.15
'@types/node-jose':
specifier: ^1.1.13
version: 1.1.13
'@types/nodemailer': '@types/nodemailer':
specifier: ^6.4.17 specifier: ^6.4.17
version: 6.4.17 version: 6.4.17
@@ -1415,6 +1415,9 @@ packages:
'@sqltools/formatter@1.2.5': '@sqltools/formatter@1.2.5':
resolution: {integrity: sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==} resolution: {integrity: sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==}
'@telegraf/types@7.1.0':
resolution: {integrity: sha512-kGevOIbpMcIlCDeorKGpwZmdH7kHbqlk/Yj6dEpJMKEQw5lk0KVQY0OLXaCswy8GqlIVLd5625OB+rAntP9xVw==}
'@tsconfig/node10@1.0.11': '@tsconfig/node10@1.0.11':
resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==}
@@ -1511,9 +1514,6 @@ packages:
'@types/mjml@4.7.4': '@types/mjml@4.7.4':
resolution: {integrity: sha512-vyi1vzWgMzFMwZY7GSZYX0GU0dmtC8vLHwpgk+NWmwbwRSrlieVyJ9sn5elodwUfklJM7yGl0zQeet1brKTWaQ==} resolution: {integrity: sha512-vyi1vzWgMzFMwZY7GSZYX0GU0dmtC8vLHwpgk+NWmwbwRSrlieVyJ9sn5elodwUfklJM7yGl0zQeet1brKTWaQ==}
'@types/node-jose@1.1.13':
resolution: {integrity: sha512-QjMd4yhwy1EvSToQn0YI3cD29YhyfxFwj7NecuymjLys2/P0FwxWnkgBlFxCai6Y3aBCe7rbwmqwJJawxlgcXw==}
'@types/node@20.17.15': '@types/node@20.17.15':
resolution: {integrity: sha512-ymrDMpEhuYz7PXTItXhY0ZDBDZT/RgsmFM9rBiRLOSVX1HKJhhrLXuLY00fHsFsugYT1wZU3IC4dleUUC22UDQ==} resolution: {integrity: sha512-ymrDMpEhuYz7PXTItXhY0ZDBDZT/RgsmFM9rBiRLOSVX1HKJhhrLXuLY00fHsFsugYT1wZU3IC4dleUUC22UDQ==}
@@ -1674,6 +1674,10 @@ packages:
resolution: {integrity: sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==} resolution: {integrity: sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==}
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
abort-controller@3.0.0:
resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==}
engines: {node: '>=6.5'}
abstract-logging@2.0.1: abstract-logging@2.0.1:
resolution: {integrity: sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==} resolution: {integrity: sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==}
@@ -1900,10 +1904,6 @@ packages:
base64-js@1.5.1: base64-js@1.5.1:
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
base64url@3.0.1:
resolution: {integrity: sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==}
engines: {node: '>=6.0.0'}
bcrypt@5.1.1: bcrypt@5.1.1:
resolution: {integrity: sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==} resolution: {integrity: sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==}
engines: {node: '>= 10.0.0'} engines: {node: '>= 10.0.0'}
@@ -1943,9 +1943,18 @@ packages:
bser@2.1.1: bser@2.1.1:
resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==}
buffer-alloc-unsafe@1.1.0:
resolution: {integrity: sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==}
buffer-alloc@1.2.0:
resolution: {integrity: sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==}
buffer-equal-constant-time@1.0.1: buffer-equal-constant-time@1.0.1:
resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==}
buffer-fill@1.0.0:
resolution: {integrity: sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==}
buffer-from@1.1.2: buffer-from@1.1.2:
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
@@ -2523,9 +2532,6 @@ packages:
resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
es6-promise@4.2.8:
resolution: {integrity: sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==}
escalade@3.2.0: escalade@3.2.0:
resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
engines: {node: '>=6'} engines: {node: '>=6'}
@@ -2667,6 +2673,10 @@ packages:
resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
event-target-shim@5.0.1:
resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==}
engines: {node: '>=6'}
eventemitter3@5.0.1: eventemitter3@5.0.1:
resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==}
@@ -3752,9 +3762,6 @@ packages:
resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==} resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==}
engines: {node: '>=18'} engines: {node: '>=18'}
long@5.3.1:
resolution: {integrity: sha512-ka87Jz3gcx/I7Hal94xaN2tZEOPoUOEVftkQqZx2EeQRN7LGdfLlI3FvZ+7WDplm+vK2Urx9ULrvSowtdCieng==}
lower-case@1.1.4: lower-case@1.1.4:
resolution: {integrity: sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA==} resolution: {integrity: sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA==}
@@ -4002,6 +4009,10 @@ packages:
mnemonist@0.39.6: mnemonist@0.39.6:
resolution: {integrity: sha512-A/0v5Z59y63US00cRSLiloEIw3t5G+MiKz4BhX21FI+YBJXBOGW0ohFxTxO08dsOYlzxo87T7vGfZKYp2bcAWA==} resolution: {integrity: sha512-A/0v5Z59y63US00cRSLiloEIw3t5G+MiKz4BhX21FI+YBJXBOGW0ohFxTxO08dsOYlzxo87T7vGfZKYp2bcAWA==}
mri@1.2.0:
resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
engines: {node: '>=4'}
ms@2.1.3: ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
@@ -4028,6 +4039,15 @@ packages:
neo-async@2.6.2: neo-async@2.6.2:
resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==}
nestjs-telegraf@2.8.1:
resolution: {integrity: sha512-7H3r6Yl4YNnJn/YSPcP26O2ESAKLJTgjKP6XuBkKw5OrYBXguGWmeUdNHYISCZTjKegHxfq8/9bjmfMrWrGIIA==}
peerDependencies:
'@nestjs/common': ^9.0.0 || ^10.0.0
'@nestjs/core': ^9.0.0 || ^10.0.0
reflect-metadata: ^0.2.2
telegraf: ^4.0.0
typescript: ^4.1.2 || ^5.0.0
nice-try@1.0.5: nice-try@1.0.5:
resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==} resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==}
@@ -4052,10 +4072,6 @@ packages:
encoding: encoding:
optional: true optional: true
node-forge@1.3.1:
resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==}
engines: {node: '>= 6.13.0'}
node-gyp-build-optional-packages@5.2.2: node-gyp-build-optional-packages@5.2.2:
resolution: {integrity: sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==} resolution: {integrity: sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==}
hasBin: true hasBin: true
@@ -4063,9 +4079,6 @@ packages:
node-int64@0.4.0: node-int64@0.4.0:
resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==}
node-jose@2.2.0:
resolution: {integrity: sha512-XPCvJRr94SjLrSIm4pbYHKLEaOsDvJCpyFw/6V/KK/IXmyZ6SFBzAUDO9HQf4DB/nTEFcRGH87mNciOP23kFjw==}
node-releases@2.0.19: node-releases@2.0.19:
resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==}
@@ -4216,6 +4229,10 @@ packages:
resolution: {integrity: sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==} resolution: {integrity: sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==}
engines: {node: '>=8'} engines: {node: '>=8'}
p-timeout@4.1.0:
resolution: {integrity: sha512-+/wmHtzJuWii1sXn3HCuH/FTwGhrp4tmJTxSKJbfS+vkipci6osxXM5mY0jUiRzWKMTgUT8l7HFbeSwZAynqHw==}
engines: {node: '>=10'}
p-try@2.2.0: p-try@2.2.0:
resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
engines: {node: '>=6'} engines: {node: '>=6'}
@@ -4227,9 +4244,6 @@ packages:
package-json-from-dist@1.0.1: package-json-from-dist@1.0.1:
resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==}
pako@2.1.0:
resolution: {integrity: sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==}
param-case@2.1.1: param-case@2.1.1:
resolution: {integrity: sha512-eQE845L6ot89sk2N8liD8HAuH4ca6Vvr7VWAWwt7+kvvG5aBcPmmphQ68JsEG2qa9n1TykS2DLeMt363AAH8/w==} resolution: {integrity: sha512-eQE845L6ot89sk2N8liD8HAuH4ca6Vvr7VWAWwt7+kvvG5aBcPmmphQ68JsEG2qa9n1TykS2DLeMt363AAH8/w==}
@@ -4436,10 +4450,6 @@ packages:
process-warning@4.0.1: process-warning@4.0.1:
resolution: {integrity: sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q==} resolution: {integrity: sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q==}
process@0.11.10:
resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==}
engines: {node: '>= 0.6.0'}
promise@7.3.1: promise@7.3.1:
resolution: {integrity: sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==} resolution: {integrity: sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==}
@@ -4659,6 +4669,9 @@ packages:
safe-buffer@5.2.1: safe-buffer@5.2.1:
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
safe-compare@1.1.4:
resolution: {integrity: sha512-b9wZ986HHCo/HbKrRpBJb2kqXMK9CEWIE1egeEvZsYn69ay3kdfl9nG3RyOcR+jInTDf7a86WQ1d4VJX7goSSQ==}
safe-push-apply@1.0.0: safe-push-apply@1.0.0:
resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
@@ -4680,6 +4693,10 @@ packages:
safer-buffer@2.1.2: safer-buffer@2.1.2:
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
sandwich-stream@2.0.2:
resolution: {integrity: sha512-jLYV0DORrzY3xaz/S9ydJL6Iz7essZeAfnAavsJ+zsJGZ1MOnsS52yRjU3uF3pJa/lla7+wisp//fxOwOH8SKQ==}
engines: {node: '>= 0.10'}
sax@1.2.1: sax@1.2.1:
resolution: {integrity: sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==} resolution: {integrity: sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==}
@@ -4950,6 +4967,11 @@ packages:
resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==}
engines: {node: '>=10'} engines: {node: '>=10'}
telegraf@4.16.3:
resolution: {integrity: sha512-yjEu2NwkHlXu0OARWoNhJlIjX09dRktiMQFsM678BAH/PEPVwctzL67+tvXqLCRQQvm3SDtki2saGO9hLlz68w==}
engines: {node: ^12.20.0 || >=14.13.1}
hasBin: true
terser-webpack-plugin@5.3.11: terser-webpack-plugin@5.3.11:
resolution: {integrity: sha512-RVCsMfuD0+cTt3EwX8hSl2Ks56EbFHWmhluwcqoPKtBnfjiT6olaq7PRIRfhyU8nnC2MrnDrBLfrD/RGE+cVXQ==} resolution: {integrity: sha512-RVCsMfuD0+cTt3EwX8hSl2Ks56EbFHWmhluwcqoPKtBnfjiT6olaq7PRIRfhyU8nnC2MrnDrBLfrD/RGE+cVXQ==}
engines: {node: '>= 10.13.0'} engines: {node: '>= 10.13.0'}
@@ -7287,6 +7309,8 @@ snapshots:
'@sqltools/formatter@1.2.5': {} '@sqltools/formatter@1.2.5': {}
'@telegraf/types@7.1.0': {}
'@tsconfig/node10@1.0.11': {} '@tsconfig/node10@1.0.11': {}
'@tsconfig/node12@1.0.11': {} '@tsconfig/node12@1.0.11': {}
@@ -7405,10 +7429,6 @@ snapshots:
'@types/mjml-core': 4.15.1 '@types/mjml-core': 4.15.1
optional: true optional: true
'@types/node-jose@1.1.13':
dependencies:
'@types/node': 20.17.15
'@types/node@20.17.15': '@types/node@20.17.15':
dependencies: dependencies:
undici-types: 6.19.8 undici-types: 6.19.8
@@ -7640,6 +7660,10 @@ snapshots:
abbrev@2.0.0: abbrev@2.0.0:
optional: true optional: true
abort-controller@3.0.0:
dependencies:
event-target-shim: 5.0.1
abstract-logging@2.0.1: {} abstract-logging@2.0.1: {}
acorn-jsx@5.3.2(acorn@8.14.0): acorn-jsx@5.3.2(acorn@8.14.0):
@@ -7918,8 +7942,6 @@ snapshots:
base64-js@1.5.1: {} base64-js@1.5.1: {}
base64url@3.0.1: {}
bcrypt@5.1.1: bcrypt@5.1.1:
dependencies: dependencies:
'@mapbox/node-pre-gyp': 1.0.11 '@mapbox/node-pre-gyp': 1.0.11
@@ -7969,8 +7991,17 @@ snapshots:
dependencies: dependencies:
node-int64: 0.4.0 node-int64: 0.4.0
buffer-alloc-unsafe@1.1.0: {}
buffer-alloc@1.2.0:
dependencies:
buffer-alloc-unsafe: 1.1.0
buffer-fill: 1.0.0
buffer-equal-constant-time@1.0.1: {} buffer-equal-constant-time@1.0.1: {}
buffer-fill@1.0.0: {}
buffer-from@1.1.2: {} buffer-from@1.1.2: {}
buffer@4.9.2: buffer@4.9.2:
@@ -8632,8 +8663,6 @@ snapshots:
is-date-object: 1.1.0 is-date-object: 1.1.0
is-symbol: 1.1.1 is-symbol: 1.1.1
es6-promise@4.2.8: {}
escalade@3.2.0: {} escalade@3.2.0: {}
escape-goat@3.0.0: escape-goat@3.0.0:
@@ -8796,6 +8825,8 @@ snapshots:
esutils@2.0.3: {} esutils@2.0.3: {}
event-target-shim@5.0.1: {}
eventemitter3@5.0.1: {} eventemitter3@5.0.1: {}
events@1.1.1: {} events@1.1.1: {}
@@ -10246,8 +10277,6 @@ snapshots:
strip-ansi: 7.1.0 strip-ansi: 7.1.0
wrap-ansi: 9.0.0 wrap-ansi: 9.0.0
long@5.3.1: {}
lower-case@1.1.4: lower-case@1.1.4:
optional: true optional: true
@@ -10707,6 +10736,8 @@ snapshots:
dependencies: dependencies:
obliterator: 2.0.5 obliterator: 2.0.5
mri@1.2.0: {}
ms@2.1.3: {} ms@2.1.3: {}
msgpackr-extract@3.0.3: msgpackr-extract@3.0.3:
@@ -10739,6 +10770,15 @@ snapshots:
neo-async@2.6.2: {} neo-async@2.6.2: {}
nestjs-telegraf@2.8.1(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.15(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2)(telegraf@4.16.3)(typescript@5.7.3):
dependencies:
'@nestjs/common': 10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1)
'@nestjs/core': 10.4.15(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2)(rxjs@7.8.1)
lodash: 4.17.21
reflect-metadata: 0.2.2
telegraf: 4.16.3
typescript: 5.7.3
nice-try@1.0.5: nice-try@1.0.5:
optional: true optional: true
@@ -10759,8 +10799,6 @@ snapshots:
dependencies: dependencies:
whatwg-url: 5.0.0 whatwg-url: 5.0.0
node-forge@1.3.1: {}
node-gyp-build-optional-packages@5.2.2: node-gyp-build-optional-packages@5.2.2:
dependencies: dependencies:
detect-libc: 2.0.3 detect-libc: 2.0.3
@@ -10768,18 +10806,6 @@ snapshots:
node-int64@0.4.0: {} node-int64@0.4.0: {}
node-jose@2.2.0:
dependencies:
base64url: 3.0.1
buffer: 6.0.3
es6-promise: 4.2.8
lodash: 4.17.21
long: 5.3.1
node-forge: 1.3.1
pako: 2.1.0
process: 0.11.10
uuid: 9.0.1
node-releases@2.0.19: {} node-releases@2.0.19: {}
nodemailer@6.9.16: {} nodemailer@6.9.16: {}
@@ -10951,6 +10977,8 @@ snapshots:
p-finally: 1.0.0 p-finally: 1.0.0
optional: true optional: true
p-timeout@4.1.0: {}
p-try@2.2.0: {} p-try@2.2.0: {}
p-wait-for@3.2.0: p-wait-for@3.2.0:
@@ -10960,8 +10988,6 @@ snapshots:
package-json-from-dist@1.0.1: {} package-json-from-dist@1.0.1: {}
pako@2.1.0: {}
param-case@2.1.1: param-case@2.1.1:
dependencies: dependencies:
no-case: 2.3.2 no-case: 2.3.2
@@ -11163,8 +11189,6 @@ snapshots:
process-warning@4.0.1: {} process-warning@4.0.1: {}
process@0.11.10: {}
promise@7.3.1: promise@7.3.1:
dependencies: dependencies:
asap: 2.0.6 asap: 2.0.6
@@ -11423,6 +11447,10 @@ snapshots:
safe-buffer@5.2.1: {} safe-buffer@5.2.1: {}
safe-compare@1.1.4:
dependencies:
buffer-alloc: 1.2.0
safe-push-apply@1.0.0: safe-push-apply@1.0.0:
dependencies: dependencies:
es-errors: 1.3.0 es-errors: 1.3.0
@@ -11446,6 +11474,8 @@ snapshots:
safer-buffer@2.1.2: {} safer-buffer@2.1.2: {}
sandwich-stream@2.0.2: {}
sax@1.2.1: {} sax@1.2.1: {}
schema-utils@3.3.0: schema-utils@3.3.0:
@@ -11740,6 +11770,20 @@ snapshots:
mkdirp: 1.0.4 mkdirp: 1.0.4
yallist: 4.0.0 yallist: 4.0.0
telegraf@4.16.3:
dependencies:
'@telegraf/types': 7.1.0
abort-controller: 3.0.0
debug: 4.4.0
mri: 1.2.0
node-fetch: 2.7.0
p-timeout: 4.1.0
safe-compare: 1.1.4
sandwich-stream: 2.0.2
transitivePeerDependencies:
- encoding
- supports-color
terser-webpack-plugin@5.3.11(webpack@5.97.1): terser-webpack-plugin@5.3.11(webpack@5.97.1):
dependencies: dependencies:
'@jridgewell/trace-mapping': 0.3.25 '@jridgewell/trace-mapping': 0.3.25
+5
View File
@@ -7,11 +7,13 @@ import { ConfigModule } from "@nestjs/config";
import { ThrottlerModule } from "@nestjs/throttler"; import { ThrottlerModule } from "@nestjs/throttler";
import { TypeOrmModule } from "@nestjs/typeorm"; import { TypeOrmModule } from "@nestjs/typeorm";
import { MailerModule } from "@nestjs-modules/mailer"; import { MailerModule } from "@nestjs-modules/mailer";
import { TelegrafModule } from "nestjs-telegraf";
import { bullMqConfig } from "./configs/bullmq.config"; import { bullMqConfig } from "./configs/bullmq.config";
import { cacheConfig } from "./configs/cache.config"; import { cacheConfig } from "./configs/cache.config";
import { mailerConfig } from "./configs/mailer.config"; import { mailerConfig } from "./configs/mailer.config";
import { rateLimitConfig } from "./configs/rateLimit.config"; import { rateLimitConfig } from "./configs/rateLimit.config";
import { telegrafConfig } from "./configs/telegraf.config";
import { databaseConfigs } from "./configs/typeorm.config"; import { databaseConfigs } from "./configs/typeorm.config";
import { HTTPLogger } from "./core/middlewares/logger.middleware"; import { HTTPLogger } from "./core/middlewares/logger.middleware";
import { AddressModule } from "./modules/address/address.module"; import { AddressModule } from "./modules/address/address.module";
@@ -24,6 +26,7 @@ import { DanakServicesModule } from "./modules/danak-services/danak-services.mod
import { DashboardModule } from "./modules/dashboards/dashboard.module"; import { DashboardModule } from "./modules/dashboards/dashboard.module";
import { InvoicesModule } from "./modules/invoices/invoices.module"; import { InvoicesModule } from "./modules/invoices/invoices.module";
import { LearningModule } from "./modules/learnings/learning.module"; import { LearningModule } from "./modules/learnings/learning.module";
import { LoggerModule } from "./modules/logger/logger.module";
import { NotificationModule } from "./modules/notifications/notifications.module"; import { NotificationModule } from "./modules/notifications/notifications.module";
import { PaymentsModule } from "./modules/payments/payments.module"; import { PaymentsModule } from "./modules/payments/payments.module";
import { SettingModule } from "./modules/settings/settings.module"; import { SettingModule } from "./modules/settings/settings.module";
@@ -35,6 +38,7 @@ import { WalletsModule } from "./modules/wallets/wallets.module";
@Module({ @Module({
imports: [ imports: [
TelegrafModule.forRootAsync(telegrafConfig()),
MailerModule.forRootAsync(mailerConfig()), MailerModule.forRootAsync(mailerConfig()),
BullModule.forRootAsync(bullMqConfig()), BullModule.forRootAsync(bullMqConfig()),
ThrottlerModule.forRootAsync(rateLimitConfig()), ThrottlerModule.forRootAsync(rateLimitConfig()),
@@ -61,6 +65,7 @@ import { WalletsModule } from "./modules/wallets/wallets.module";
AdsModule, AdsModule,
AddressModule, AddressModule,
DashboardModule, DashboardModule,
LoggerModule,
], ],
controllers: [], controllers: [],
providers: [], providers: [],
+3 -4
View File
@@ -9,10 +9,9 @@ export function bullMqConfig(): SharedBullAsyncConfiguration {
url: configService.getOrThrow<string>("REDIS_URI"), url: configService.getOrThrow<string>("REDIS_URI"),
}, },
defaultJobOptions: { defaultJobOptions: {
removeOnComplete: 2000, // Consider lower values in high-volume production removeOnComplete: false,
removeOnFail: 5000, // Consider lower values to reduce Redis memory usage removeOnFail: false,
attempts: 3, // Reasonable default, adjust based on job criticality attempts: 5, // Reasonable default, adjust based on job criticality
backoff: { type: "exponential", delay: 2000 }, // Consider adding for better retry behavior
}, },
}), }),
}; };
+12
View File
@@ -0,0 +1,12 @@
import { ConfigService } from "@nestjs/config";
import { TelegrafModuleAsyncOptions } from "nestjs-telegraf";
export function telegrafConfig(): TelegrafModuleAsyncOptions {
return {
inject: [ConfigService],
useFactory: async (configService: ConfigService) => ({
token: configService.getOrThrow<string>("TELEGRAM_BOT_TOKEN"),
botName: configService.getOrThrow<string>("TELEGRAM_BOT_NAME"),
}),
};
}
+1 -1
View File
@@ -5,7 +5,7 @@ export const ANNOUNCEMENT = Object.freeze({
// //
ANNOUNCEMENT_SEND_JOB_PRIORITY: 1, ANNOUNCEMENT_SEND_JOB_PRIORITY: 1,
ANNOUNCEMENT_SEND_JOB_ATTEMPTS: 3, ANNOUNCEMENT_SEND_JOB_ATTEMPTS: 3,
ANNOUNCEMENT_SEND_JOB_BACKOFF: 1000, ANNOUNCEMENT_SEND_JOB_BACKOFF: 5 * 1000,
ANNOUNCEMENT_SEND_JOB_TIMEOUT: 10000, ANNOUNCEMENT_SEND_JOB_TIMEOUT: 10000,
// //
ANNOUNCEMENT_PUBLISH_JOB_PRIORITY: 1, ANNOUNCEMENT_PUBLISH_JOB_PRIORITY: 1,
@@ -57,7 +57,7 @@ export class AnnouncementService {
{ {
delay: dayjs(announcement.publishAt).diff(dayjs(), "millisecond"), delay: dayjs(announcement.publishAt).diff(dayjs(), "millisecond"),
attempts: ANNOUNCEMENT.ANNOUNCEMENT_SEND_JOB_ATTEMPTS, attempts: ANNOUNCEMENT.ANNOUNCEMENT_SEND_JOB_ATTEMPTS,
backoff: ANNOUNCEMENT.ANNOUNCEMENT_SEND_JOB_BACKOFF, backoff: { type: "exponential", delay: ANNOUNCEMENT.ANNOUNCEMENT_SEND_JOB_BACKOFF },
}, },
); );
+9 -9
View File
@@ -3,17 +3,17 @@ export const INVOICE = Object.freeze({
INVOICE_REMINDER_JOB_NAME: "reminderInvoice", INVOICE_REMINDER_JOB_NAME: "reminderInvoice",
INVOICE_RECURRING_JOB_NAME: "recurringInvoice", INVOICE_RECURRING_JOB_NAME: "recurringInvoice",
// //
INVOICE_REMINDER_JOB_PRIORITY: 1, // High priority INVOICE_REMINDER_JOB_PRIORITY: 1, // high priority
INVOICE_REMINDER_JOB_ATTEMPTS: 3, // Retry 3 times INVOICE_REMINDER_JOB_ATTEMPTS: 3, // 3 times
INVOICE_REMINDER_JOB_BACKOFF: 1000, // Retry after 1 second INVOICE_REMINDER_JOB_BACKOFF: 5 * 1000, // ms
INVOICE_REMINDER_JOB_TIMEOUT: 10000, // Timeout after 10 seconds INVOICE_REMINDER_JOB_TIMEOUT: 10000, // timeout after 10 seconds
INVOICE_REMINDER_REPEAT_DELAY: 86400000, // 1 day delay in milliseconds INVOICE_REMINDER_REPEAT_DELAY: 1 * 24 * 60 * 60 * 1000, // 1 day delay in milliseconds
// //
INVOICE_RECURRING_JOB_PRIORITY: 1, // High priority INVOICE_RECURRING_JOB_PRIORITY: 1, // high priority
INVOICE_RECURRING_JOB_ATTEMPTS: 3, // Retry 3 times INVOICE_RECURRING_JOB_ATTEMPTS: 3, // retry 3 times
INVOICE_RECURRING_JOB_BACKOFF: 1000, // Retry after 1 second INVOICE_RECURRING_JOB_BACKOFF: 5 * 1000, // retry after 1 second
INVOICE_RECURRING_JOB_TIMEOUT: 10000, // Timeout after 10 seconds INVOICE_RECURRING_JOB_TIMEOUT: 10000, // timeout after 10 seconds
// //
FINE_PERCENTAGE: 0.01, // 1% of the total price FINE_PERCENTAGE: 0.01, // 1% of the total price
MAX_DAYS_AFTER_OVERDUE: 10, MAX_DAYS_AFTER_OVERDUE: 10,
+2
View File
@@ -18,9 +18,11 @@ import { UtilsModule } from "../utils/utils.module";
import { WalletsModule } from "../wallets/wallets.module"; import { WalletsModule } from "../wallets/wallets.module";
import { InvoiceProcessor } from "./queue/invoice.processor"; import { InvoiceProcessor } from "./queue/invoice.processor";
import { InvoiceItemsRepository } from "./repositories/invoice-items.repository"; import { InvoiceItemsRepository } from "./repositories/invoice-items.repository";
import { LoggerModule } from "../logger/logger.module";
@Module({ @Module({
imports: [ imports: [
LoggerModule,
BullModule.registerQueue({ name: INVOICE.INVOICE_QUEUE_NAME }), BullModule.registerQueue({ name: INVOICE.INVOICE_QUEUE_NAME }),
TypeOrmModule.forFeature([Invoice, InvoiceItem, Discount, UsageDiscount]), TypeOrmModule.forFeature([Invoice, InvoiceItem, Discount, UsageDiscount]),
UsersModule, UsersModule,
@@ -1,5 +1,4 @@
import { InjectQueue, Processor } from "@nestjs/bullmq"; import { InjectQueue, Processor } from "@nestjs/bullmq";
import { Logger } from "@nestjs/common";
import { Job, Queue } from "bullmq"; import { Job, Queue } from "bullmq";
import dayjs from "dayjs"; import dayjs from "dayjs";
// eslint-disable-next-line import/no-named-as-default // eslint-disable-next-line import/no-named-as-default
@@ -7,6 +6,7 @@ import Decimal from "decimal.js";
import { DataSource, QueryRunner } from "typeorm"; import { DataSource, QueryRunner } from "typeorm";
import { WorkerProcessor } from "../../../common/queues/worker.processor"; import { WorkerProcessor } from "../../../common/queues/worker.processor";
import { LoggerService } from "../../logger/logger.service";
import { NotificationsService } from "../../notifications/providers/notifications.service"; import { NotificationsService } from "../../notifications/providers/notifications.service";
import { SubscriptionStatus } from "../../subscriptions/enums/subscription-status.enum"; import { SubscriptionStatus } from "../../subscriptions/enums/subscription-status.enum";
import { User } from "../../users/entities/user.entity"; import { User } from "../../users/entities/user.entity";
@@ -16,21 +16,22 @@ import { Invoice } from "../entities/invoice.entity";
import { InvoiceStatus } from "../enums/invoice-status.enum"; import { InvoiceStatus } from "../enums/invoice-status.enum";
import { InvoicesService } from "../providers/invoices.service"; import { InvoicesService } from "../providers/invoices.service";
@Processor(INVOICE.INVOICE_QUEUE_NAME) @Processor(INVOICE.INVOICE_QUEUE_NAME, { concurrency: 5 })
export class InvoiceProcessor extends WorkerProcessor { export class InvoiceProcessor extends WorkerProcessor {
protected readonly logger = new Logger(InvoiceProcessor.name); // protected readonly logger = new Logger(InvoiceProcessor.name);
constructor( constructor(
@InjectQueue(INVOICE.INVOICE_QUEUE_NAME) private readonly invoiceQueue: Queue, @InjectQueue(INVOICE.INVOICE_QUEUE_NAME) private readonly invoiceQueue: Queue,
private readonly invoicesService: InvoicesService, private readonly invoicesService: InvoicesService,
private readonly dataSource: DataSource, private readonly dataSource: DataSource,
private readonly notificationService: NotificationsService, private readonly notificationService: NotificationsService,
protected readonly logger: LoggerService,
) { ) {
super(); super();
} }
async process(job: Job, token?: string) { async process(job: Job, token?: string) {
this.logger.log(job, token); this.logger.log(job);
switch (job.name) { switch (job.name) {
case INVOICE.INVOICE_REMINDER_JOB_NAME: case INVOICE.INVOICE_REMINDER_JOB_NAME:
return this.sendBillInvoiceReminder(job, token); return this.sendBillInvoiceReminder(job, token);
@@ -234,7 +235,7 @@ export class InvoiceProcessor extends WorkerProcessor {
{ {
delay: INVOICE.INVOICE_REMINDER_REPEAT_DELAY, // 1 day delay in milliseconds delay: INVOICE.INVOICE_REMINDER_REPEAT_DELAY, // 1 day delay in milliseconds
attempts: INVOICE.INVOICE_REMINDER_JOB_ATTEMPTS, attempts: INVOICE.INVOICE_REMINDER_JOB_ATTEMPTS,
backoff: INVOICE.INVOICE_REMINDER_JOB_BACKOFF, backoff: { type: "exponential", delay: INVOICE.INVOICE_REMINDER_JOB_BACKOFF },
}, },
); );
} }
@@ -261,7 +262,7 @@ export class InvoiceProcessor extends WorkerProcessor {
}; };
await Promise.all( await Promise.all(
admins.map((admin) => this.notificationService.createRucurringInvoiceNotification(admin.id, notificationPayload, queryRunner)), admins.map((admin) => this.notificationService.createRecurringInvoiceNotification(admin.id, notificationPayload, queryRunner)),
); );
} }
} }
+9
View File
@@ -0,0 +1,9 @@
import { Module } from "@nestjs/common";
import { LoggerService } from "./logger.service";
@Module({
providers: [LoggerService],
exports: [LoggerService],
})
export class LoggerModule {}
+43
View File
@@ -0,0 +1,43 @@
import { Injectable, Logger } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { InjectBot } from "nestjs-telegraf";
import { Telegraf } from "telegraf";
@Injectable()
export class LoggerService extends Logger {
private chatId: string;
constructor(
@InjectBot() private bot: Telegraf,
private configService: ConfigService,
) {
super();
this.chatId = this.configService.getOrThrow<string>("TELEGRAM_CHAT_ID");
}
async sendLogToTelegram(level: string, message: string) {
try {
const logMessage = `🚨 *${level.toUpperCase()} Log:*\n${message}`;
await this.bot.telegram.sendMessage(this.chatId, logMessage, {
parse_mode: "Markdown",
});
} catch (error) {
super.error(`Failed to send log to Telegram:`, error);
}
}
override log(message: any) {
this.sendLogToTelegram("test", message);
super.log(message);
}
override error(message: any, trace?: any) {
super.error(message, trace);
this.sendLogToTelegram("error", `${message}\nTrace: ${trace}`);
}
override warn(message: any) {
super.warn(message);
this.sendLogToTelegram("warn", message);
}
}
@@ -317,7 +317,7 @@ export class NotificationsService {
// //************************ */ // //************************ */
async createRucurringInvoiceNotification(recipientId: string, data: IInvoiceNotificationData, queryRunner: QueryRunner) { async createRecurringInvoiceNotification(recipientId: string, data: IInvoiceNotificationData, queryRunner: QueryRunner) {
const message = NotificationMessage.RECURRING_INVOICE_MESSAGE.replace("[invoiceNumber]", data.invoiceId); const message = NotificationMessage.RECURRING_INVOICE_MESSAGE.replace("[invoiceNumber]", data.invoiceId);
//sent notification based on the userSettings //sent notification based on the userSettings
const { isActive } = await this.userSettingsService.getUserNotificationSettingWithType(NotifType.RECURRING_INVOICE, recipientId); const { isActive } = await this.userSettingsService.getUserNotificationSettingWithType(NotifType.RECURRING_INVOICE, recipientId);