generated from nhcarrigan/template
feat: add birthday system
This commit is contained in:
parent
1d2ae0e5a1
commit
1db7d33e22
@ -29,6 +29,7 @@
|
|||||||
"@nhcarrigan/prettier-config": "3.2.0",
|
"@nhcarrigan/prettier-config": "3.2.0",
|
||||||
"@nhcarrigan/typescript-config": "3.0.0",
|
"@nhcarrigan/typescript-config": "3.0.0",
|
||||||
"@types/express": "4.17.21",
|
"@types/express": "4.17.21",
|
||||||
|
"@types/node-schedule": "2.1.7",
|
||||||
"eslint": "8.57.0",
|
"eslint": "8.57.0",
|
||||||
"knip": "5.15.0",
|
"knip": "5.15.0",
|
||||||
"prettier": "3.2.5",
|
"prettier": "3.2.5",
|
||||||
@ -42,6 +43,7 @@
|
|||||||
"dotenv": "16.4.5",
|
"dotenv": "16.4.5",
|
||||||
"express": "4.19.2",
|
"express": "4.19.2",
|
||||||
"node-html-to-image": "4.0.0",
|
"node-html-to-image": "4.0.0",
|
||||||
|
"node-schedule": "2.1.1",
|
||||||
"winston": "3.13.0"
|
"winston": "3.13.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
78
pnpm-lock.yaml
generated
78
pnpm-lock.yaml
generated
@ -26,6 +26,9 @@ importers:
|
|||||||
node-html-to-image:
|
node-html-to-image:
|
||||||
specifier: 4.0.0
|
specifier: 4.0.0
|
||||||
version: 4.0.0
|
version: 4.0.0
|
||||||
|
node-schedule:
|
||||||
|
specifier: 2.1.1
|
||||||
|
version: 2.1.1
|
||||||
winston:
|
winston:
|
||||||
specifier: 3.13.0
|
specifier: 3.13.0
|
||||||
version: 3.13.0
|
version: 3.13.0
|
||||||
@ -42,6 +45,9 @@ importers:
|
|||||||
'@types/express':
|
'@types/express':
|
||||||
specifier: 4.17.21
|
specifier: 4.17.21
|
||||||
version: 4.17.21
|
version: 4.17.21
|
||||||
|
'@types/node-schedule':
|
||||||
|
specifier: 2.1.7
|
||||||
|
version: 2.1.7
|
||||||
eslint:
|
eslint:
|
||||||
specifier: 8.57.0
|
specifier: 8.57.0
|
||||||
version: 8.57.0
|
version: 8.57.0
|
||||||
@ -323,6 +329,9 @@ packages:
|
|||||||
'@types/mime@3.0.1':
|
'@types/mime@3.0.1':
|
||||||
resolution: {integrity: sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==}
|
resolution: {integrity: sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==}
|
||||||
|
|
||||||
|
'@types/node-schedule@2.1.7':
|
||||||
|
resolution: {integrity: sha512-G7Z3R9H7r3TowoH6D2pkzUHPhcJrDF4Jz1JOQ80AX0K2DWTHoN9VC94XzFAPNMdbW9TBzMZ3LjpFi7RYdbxtXA==}
|
||||||
|
|
||||||
'@types/node@20.3.1':
|
'@types/node@20.3.1':
|
||||||
resolution: {integrity: sha512-EhcH/wvidPy1WeML3TtYFGR83UzjxeWRen9V402T8aUGYsCHOmfoisV3ZSg03gAFIbLq8TnWOJ0f4cALtnSEUg==}
|
resolution: {integrity: sha512-EhcH/wvidPy1WeML3TtYFGR83UzjxeWRen9V402T8aUGYsCHOmfoisV3ZSg03gAFIbLq8TnWOJ0f4cALtnSEUg==}
|
||||||
|
|
||||||
@ -650,6 +659,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-3rTMnFJA1tCOPwRxtgF4wd7Ab2qvDbL8jX+3smjIbS4HlZBagTlpERbdN7iAbWlrfxE3M8c27kTwTawQ7st+OQ==}
|
resolution: {integrity: sha512-3rTMnFJA1tCOPwRxtgF4wd7Ab2qvDbL8jX+3smjIbS4HlZBagTlpERbdN7iAbWlrfxE3M8c27kTwTawQ7st+OQ==}
|
||||||
engines: {node: '>=14'}
|
engines: {node: '>=14'}
|
||||||
|
|
||||||
|
cron-parser@4.9.0:
|
||||||
|
resolution: {integrity: sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==}
|
||||||
|
engines: {node: '>=12.0.0'}
|
||||||
|
|
||||||
cross-fetch@4.0.0:
|
cross-fetch@4.0.0:
|
||||||
resolution: {integrity: sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==}
|
resolution: {integrity: sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==}
|
||||||
|
|
||||||
@ -1439,6 +1452,9 @@ packages:
|
|||||||
logform@2.5.1:
|
logform@2.5.1:
|
||||||
resolution: {integrity: sha512-9FyqAm9o9NKKfiAKfZoYo9bGXXuwMkxQiQttkT4YjjVtQVIQtK6LmVtlxmCaFswo6N4AfEkHqZTV0taDtPotNg==}
|
resolution: {integrity: sha512-9FyqAm9o9NKKfiAKfZoYo9bGXXuwMkxQiQttkT4YjjVtQVIQtK6LmVtlxmCaFswo6N4AfEkHqZTV0taDtPotNg==}
|
||||||
|
|
||||||
|
long-timeout@0.1.1:
|
||||||
|
resolution: {integrity: sha512-BFRuQUqc7x2NWxfJBCyUrN8iYUYznzL9JROmRz1gZ6KlOIgmoD+njPVbb+VNn2nGMKggMsK79iUNErillsrx7w==}
|
||||||
|
|
||||||
lru-cache@6.0.0:
|
lru-cache@6.0.0:
|
||||||
resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
|
resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
@ -1447,6 +1463,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==}
|
resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
|
luxon@3.4.4:
|
||||||
|
resolution: {integrity: sha512-zobTr7akeGHnv7eBOXcRgMeCP6+uyYsczwmeRCauvpvaAltgNyTbLH/+VaEAPUeWBT+1GuNmz4wC/6jtQzbbVA==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
magic-bytes.js@1.10.0:
|
magic-bytes.js@1.10.0:
|
||||||
resolution: {integrity: sha512-/k20Lg2q8LE5xiaaSkMXk4sfvI+9EGEykFS4b0CHHGWqDYU0bGUFSwchNOMA56D7TCs9GwVTkqe9als1/ns8UQ==}
|
resolution: {integrity: sha512-/k20Lg2q8LE5xiaaSkMXk4sfvI+9EGEykFS4b0CHHGWqDYU0bGUFSwchNOMA56D7TCs9GwVTkqe9als1/ns8UQ==}
|
||||||
|
|
||||||
@ -1539,6 +1559,10 @@ packages:
|
|||||||
node-html-to-image@4.0.0:
|
node-html-to-image@4.0.0:
|
||||||
resolution: {integrity: sha512-lB8fkRleAKG4afJ2Wr7qJzIA5+//ue9OEoz+BMxQsowriGKR8sf4j4lK/pIXKakYwf/3aZHoDUNgOXuJ4HOzYA==}
|
resolution: {integrity: sha512-lB8fkRleAKG4afJ2Wr7qJzIA5+//ue9OEoz+BMxQsowriGKR8sf4j4lK/pIXKakYwf/3aZHoDUNgOXuJ4HOzYA==}
|
||||||
|
|
||||||
|
node-schedule@2.1.1:
|
||||||
|
resolution: {integrity: sha512-OXdegQq03OmXEjt2hZP33W2YPs/E5BcFQks46+G2gAxs4gHOIVD1u7EqlYLYSKsaIpyKCK9Gbk0ta1/gjRSMRQ==}
|
||||||
|
engines: {node: '>=6'}
|
||||||
|
|
||||||
object-inspect@1.12.3:
|
object-inspect@1.12.3:
|
||||||
resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==}
|
resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==}
|
||||||
|
|
||||||
@ -1866,6 +1890,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==}
|
resolution: {integrity: sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==}
|
||||||
engines: {node: '>= 10.0.0', npm: '>= 3.0.0'}
|
engines: {node: '>= 10.0.0', npm: '>= 3.0.0'}
|
||||||
|
|
||||||
|
sorted-array-functions@1.3.0:
|
||||||
|
resolution: {integrity: sha512-2sqgzeFlid6N4Z2fUQ1cvFmTOLRi/sEDzSQ0OKYchqgoPmQBVyM3959qYx3fpS6Esef80KjmpgPeEr028dP3OA==}
|
||||||
|
|
||||||
source-map@0.6.1:
|
source-map@0.6.1:
|
||||||
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
|
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@ -2338,14 +2365,14 @@ snapshots:
|
|||||||
|
|
||||||
'@nhcarrigan/eslint-config@3.2.0(eslint@8.57.0)(prettier@3.2.5)(typescript@5.4.5)':
|
'@nhcarrigan/eslint-config@3.2.0(eslint@8.57.0)(prettier@3.2.5)(typescript@5.4.5)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.57.0)(typescript@5.4.5)
|
'@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5)
|
||||||
'@typescript-eslint/parser': 5.62.0(eslint@8.57.0)(typescript@5.4.5)
|
'@typescript-eslint/parser': 5.62.0(eslint@8.57.0)(typescript@5.4.5)
|
||||||
eslint: 8.57.0
|
eslint: 8.57.0
|
||||||
eslint-config-prettier: 9.0.0(eslint@8.57.0)
|
eslint-config-prettier: 9.0.0(eslint@8.57.0)
|
||||||
eslint-plugin-import: 2.28.1(@typescript-eslint/parser@5.62.0)(eslint@8.57.0)
|
eslint-plugin-import: 2.28.1(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)
|
||||||
eslint-plugin-jsdoc: 41.1.2(eslint@8.57.0)
|
eslint-plugin-jsdoc: 41.1.2(eslint@8.57.0)
|
||||||
eslint-plugin-no-only-tests: 3.1.0
|
eslint-plugin-no-only-tests: 3.1.0
|
||||||
eslint-plugin-prettier: 5.0.0(eslint-config-prettier@9.0.0)(eslint@8.57.0)(prettier@3.2.5)
|
eslint-plugin-prettier: 5.0.0(eslint-config-prettier@9.0.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.2.5)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@types/eslint'
|
- '@types/eslint'
|
||||||
- eslint-import-resolver-typescript
|
- eslint-import-resolver-typescript
|
||||||
@ -2452,7 +2479,7 @@ snapshots:
|
|||||||
'@pkgr/core@0.1.1': {}
|
'@pkgr/core@0.1.1': {}
|
||||||
|
|
||||||
'@prisma/client@5.13.0(prisma@5.13.0)':
|
'@prisma/client@5.13.0(prisma@5.13.0)':
|
||||||
dependencies:
|
optionalDependencies:
|
||||||
prisma: 5.13.0
|
prisma: 5.13.0
|
||||||
|
|
||||||
'@prisma/debug@5.13.0': {}
|
'@prisma/debug@5.13.0': {}
|
||||||
@ -2536,6 +2563,10 @@ snapshots:
|
|||||||
|
|
||||||
'@types/mime@3.0.1': {}
|
'@types/mime@3.0.1': {}
|
||||||
|
|
||||||
|
'@types/node-schedule@2.1.7':
|
||||||
|
dependencies:
|
||||||
|
'@types/node': 20.3.1
|
||||||
|
|
||||||
'@types/node@20.3.1': {}
|
'@types/node@20.3.1': {}
|
||||||
|
|
||||||
'@types/qs@6.9.7': {}
|
'@types/qs@6.9.7': {}
|
||||||
@ -2565,7 +2596,7 @@ snapshots:
|
|||||||
'@types/node': 20.3.1
|
'@types/node': 20.3.1
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.57.0)(typescript@5.4.5)':
|
'@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@eslint-community/regexpp': 4.5.1
|
'@eslint-community/regexpp': 4.5.1
|
||||||
'@typescript-eslint/parser': 5.62.0(eslint@8.57.0)(typescript@5.4.5)
|
'@typescript-eslint/parser': 5.62.0(eslint@8.57.0)(typescript@5.4.5)
|
||||||
@ -2579,6 +2610,7 @@ snapshots:
|
|||||||
natural-compare-lite: 1.4.0
|
natural-compare-lite: 1.4.0
|
||||||
semver: 7.5.2
|
semver: 7.5.2
|
||||||
tsutils: 3.21.0(typescript@5.4.5)
|
tsutils: 3.21.0(typescript@5.4.5)
|
||||||
|
optionalDependencies:
|
||||||
typescript: 5.4.5
|
typescript: 5.4.5
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
@ -2590,6 +2622,7 @@ snapshots:
|
|||||||
'@typescript-eslint/typescript-estree': 5.62.0(typescript@5.4.5)
|
'@typescript-eslint/typescript-estree': 5.62.0(typescript@5.4.5)
|
||||||
debug: 4.3.4
|
debug: 4.3.4
|
||||||
eslint: 8.57.0
|
eslint: 8.57.0
|
||||||
|
optionalDependencies:
|
||||||
typescript: 5.4.5
|
typescript: 5.4.5
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
@ -2606,6 +2639,7 @@ snapshots:
|
|||||||
debug: 4.3.4
|
debug: 4.3.4
|
||||||
eslint: 8.57.0
|
eslint: 8.57.0
|
||||||
tsutils: 3.21.0(typescript@5.4.5)
|
tsutils: 3.21.0(typescript@5.4.5)
|
||||||
|
optionalDependencies:
|
||||||
typescript: 5.4.5
|
typescript: 5.4.5
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
@ -2621,6 +2655,7 @@ snapshots:
|
|||||||
is-glob: 4.0.3
|
is-glob: 4.0.3
|
||||||
semver: 7.5.2
|
semver: 7.5.2
|
||||||
tsutils: 3.21.0(typescript@5.4.5)
|
tsutils: 3.21.0(typescript@5.4.5)
|
||||||
|
optionalDependencies:
|
||||||
typescript: 5.4.5
|
typescript: 5.4.5
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
@ -2912,6 +2947,10 @@ snapshots:
|
|||||||
parse-json: 5.2.0
|
parse-json: 5.2.0
|
||||||
path-type: 4.0.0
|
path-type: 4.0.0
|
||||||
|
|
||||||
|
cron-parser@4.9.0:
|
||||||
|
dependencies:
|
||||||
|
luxon: 3.4.4
|
||||||
|
|
||||||
cross-fetch@4.0.0:
|
cross-fetch@4.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
node-fetch: 2.7.0
|
node-fetch: 2.7.0
|
||||||
@ -3202,18 +3241,18 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
eslint-module-utils@2.8.0(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-node@0.3.7)(eslint@8.57.0):
|
eslint-module-utils@2.8.0(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.7)(eslint@8.57.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/parser': 5.62.0(eslint@8.57.0)(typescript@5.4.5)
|
|
||||||
debug: 3.2.7
|
debug: 3.2.7
|
||||||
|
optionalDependencies:
|
||||||
|
'@typescript-eslint/parser': 5.62.0(eslint@8.57.0)(typescript@5.4.5)
|
||||||
eslint: 8.57.0
|
eslint: 8.57.0
|
||||||
eslint-import-resolver-node: 0.3.7
|
eslint-import-resolver-node: 0.3.7
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
eslint-plugin-import@2.28.1(@typescript-eslint/parser@5.62.0)(eslint@8.57.0):
|
eslint-plugin-import@2.28.1(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/parser': 5.62.0(eslint@8.57.0)(typescript@5.4.5)
|
|
||||||
array-includes: 3.1.6
|
array-includes: 3.1.6
|
||||||
array.prototype.findlastindex: 1.2.5
|
array.prototype.findlastindex: 1.2.5
|
||||||
array.prototype.flat: 1.3.1
|
array.prototype.flat: 1.3.1
|
||||||
@ -3222,7 +3261,7 @@ snapshots:
|
|||||||
doctrine: 2.1.0
|
doctrine: 2.1.0
|
||||||
eslint: 8.57.0
|
eslint: 8.57.0
|
||||||
eslint-import-resolver-node: 0.3.7
|
eslint-import-resolver-node: 0.3.7
|
||||||
eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-node@0.3.7)(eslint@8.57.0)
|
eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.7)(eslint@8.57.0)
|
||||||
has: 1.0.3
|
has: 1.0.3
|
||||||
is-core-module: 2.13.1
|
is-core-module: 2.13.1
|
||||||
is-glob: 4.0.3
|
is-glob: 4.0.3
|
||||||
@ -3232,6 +3271,8 @@ snapshots:
|
|||||||
object.values: 1.1.6
|
object.values: 1.1.6
|
||||||
semver: 6.3.1
|
semver: 6.3.1
|
||||||
tsconfig-paths: 3.14.2
|
tsconfig-paths: 3.14.2
|
||||||
|
optionalDependencies:
|
||||||
|
'@typescript-eslint/parser': 5.62.0(eslint@8.57.0)(typescript@5.4.5)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- eslint-import-resolver-typescript
|
- eslint-import-resolver-typescript
|
||||||
- eslint-import-resolver-webpack
|
- eslint-import-resolver-webpack
|
||||||
@ -3253,13 +3294,14 @@ snapshots:
|
|||||||
|
|
||||||
eslint-plugin-no-only-tests@3.1.0: {}
|
eslint-plugin-no-only-tests@3.1.0: {}
|
||||||
|
|
||||||
eslint-plugin-prettier@5.0.0(eslint-config-prettier@9.0.0)(eslint@8.57.0)(prettier@3.2.5):
|
eslint-plugin-prettier@5.0.0(eslint-config-prettier@9.0.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.2.5):
|
||||||
dependencies:
|
dependencies:
|
||||||
eslint: 8.57.0
|
eslint: 8.57.0
|
||||||
eslint-config-prettier: 9.0.0(eslint@8.57.0)
|
|
||||||
prettier: 3.2.5
|
prettier: 3.2.5
|
||||||
prettier-linter-helpers: 1.0.0
|
prettier-linter-helpers: 1.0.0
|
||||||
synckit: 0.8.8
|
synckit: 0.8.8
|
||||||
|
optionalDependencies:
|
||||||
|
eslint-config-prettier: 9.0.0(eslint@8.57.0)
|
||||||
|
|
||||||
eslint-scope@5.1.1:
|
eslint-scope@5.1.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -3891,12 +3933,16 @@ snapshots:
|
|||||||
safe-stable-stringify: 2.4.3
|
safe-stable-stringify: 2.4.3
|
||||||
triple-beam: 1.3.0
|
triple-beam: 1.3.0
|
||||||
|
|
||||||
|
long-timeout@0.1.1: {}
|
||||||
|
|
||||||
lru-cache@6.0.0:
|
lru-cache@6.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
yallist: 4.0.0
|
yallist: 4.0.0
|
||||||
|
|
||||||
lru-cache@7.18.3: {}
|
lru-cache@7.18.3: {}
|
||||||
|
|
||||||
|
luxon@3.4.4: {}
|
||||||
|
|
||||||
magic-bytes.js@1.10.0: {}
|
magic-bytes.js@1.10.0: {}
|
||||||
|
|
||||||
magic-string@0.16.0:
|
magic-string@0.16.0:
|
||||||
@ -3967,6 +4013,12 @@ snapshots:
|
|||||||
- supports-color
|
- supports-color
|
||||||
- utf-8-validate
|
- utf-8-validate
|
||||||
|
|
||||||
|
node-schedule@2.1.1:
|
||||||
|
dependencies:
|
||||||
|
cron-parser: 4.9.0
|
||||||
|
long-timeout: 0.1.1
|
||||||
|
sorted-array-functions: 1.3.0
|
||||||
|
|
||||||
object-inspect@1.12.3: {}
|
object-inspect@1.12.3: {}
|
||||||
|
|
||||||
object-inspect@1.13.1: {}
|
object-inspect@1.13.1: {}
|
||||||
@ -4346,6 +4398,8 @@ snapshots:
|
|||||||
ip-address: 9.0.5
|
ip-address: 9.0.5
|
||||||
smart-buffer: 4.2.0
|
smart-buffer: 4.2.0
|
||||||
|
|
||||||
|
sorted-array-functions@1.3.0: {}
|
||||||
|
|
||||||
source-map@0.6.1: {}
|
source-map@0.6.1: {}
|
||||||
|
|
||||||
spdx-exceptions@2.3.0: {}
|
spdx-exceptions@2.3.0: {}
|
||||||
|
@ -60,6 +60,7 @@ model configs {
|
|||||||
eventLogChannel String @default("")
|
eventLogChannel String @default("")
|
||||||
messageReportChannel String @default("")
|
messageReportChannel String @default("")
|
||||||
joinRole String @default("")
|
joinRole String @default("")
|
||||||
|
birthdayChannel String @default("")
|
||||||
|
|
||||||
@@unique([serverId], map: "serverId")
|
@@unique([serverId], map: "serverId")
|
||||||
}
|
}
|
||||||
@ -80,3 +81,12 @@ model roles {
|
|||||||
|
|
||||||
@@unique([serverId, roleId], map: "serverId_roleId")
|
@@unique([serverId, roleId], map: "serverId_roleId")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
model birthdays {
|
||||||
|
id String @id @default(auto()) @map("_id") @db.ObjectId
|
||||||
|
serverId String
|
||||||
|
userId String
|
||||||
|
birthday DateTime
|
||||||
|
|
||||||
|
@@unique([serverId, userId], map: "serverId_userId")
|
||||||
|
}
|
||||||
|
143
src/commands/birthday.ts
Normal file
143
src/commands/birthday.ts
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
import { SlashCommandBuilder } from "discord.js";
|
||||||
|
|
||||||
|
import { Command } from "../interfaces/Command";
|
||||||
|
import { errorHandler } from "../utils/errorHandler";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates that the day provided is a valid day of the month.
|
||||||
|
*
|
||||||
|
* @param {string} month The month to validate.
|
||||||
|
* @param {number} day The day to validate.
|
||||||
|
* @returns {boolean} True if the day is within the month's range.
|
||||||
|
*/
|
||||||
|
const validateDate = (month: string, day: number): boolean => {
|
||||||
|
switch (month) {
|
||||||
|
case "Jan":
|
||||||
|
case "Mar":
|
||||||
|
case "May":
|
||||||
|
case "Jul":
|
||||||
|
case "Aug":
|
||||||
|
case "Oct":
|
||||||
|
case "Dec":
|
||||||
|
return day >= 1 && day <= 31;
|
||||||
|
case "Feb":
|
||||||
|
return day >= 1 && day <= 29;
|
||||||
|
case "Apr":
|
||||||
|
case "Jun":
|
||||||
|
case "Sep":
|
||||||
|
case "Nov":
|
||||||
|
return day >= 1 && day <= 30;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const bbset: Command = {
|
||||||
|
data: new SlashCommandBuilder()
|
||||||
|
.setName("bbset")
|
||||||
|
.setDescription("Set your birthday!")
|
||||||
|
.addStringOption((option) =>
|
||||||
|
option
|
||||||
|
.setName("month")
|
||||||
|
.setDescription("Your Birth Month")
|
||||||
|
.setRequired(true)
|
||||||
|
.setChoices(
|
||||||
|
{
|
||||||
|
name: "January",
|
||||||
|
value: "Jan"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "February",
|
||||||
|
value: "Feb"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "March",
|
||||||
|
value: "Mar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "April",
|
||||||
|
value: "Apr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "May",
|
||||||
|
value: "May"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "June",
|
||||||
|
value: "Jun"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "July",
|
||||||
|
value: "Jul"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "August",
|
||||||
|
value: "Aug"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "September",
|
||||||
|
value: "Sep"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "October",
|
||||||
|
value: "Oct"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "November",
|
||||||
|
value: "Nov"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "December",
|
||||||
|
value: "Dec"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.addIntegerOption((option) =>
|
||||||
|
option
|
||||||
|
.setName("day")
|
||||||
|
.setDescription("Your Birth Day (1-31)")
|
||||||
|
.setRequired(true)
|
||||||
|
.setMinValue(1)
|
||||||
|
.setMaxValue(31)
|
||||||
|
),
|
||||||
|
run: async (bot, interaction) => {
|
||||||
|
try {
|
||||||
|
await interaction.deferReply();
|
||||||
|
const month = interaction.options.getString("month", true);
|
||||||
|
const day = interaction.options.getInteger("day", true);
|
||||||
|
|
||||||
|
if (!validateDate(month, day)) {
|
||||||
|
await interaction.editReply({
|
||||||
|
content: `${month} ${day} is not a valid date!`
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await bot.db.birthdays.upsert({
|
||||||
|
where: {
|
||||||
|
serverId_userId: {
|
||||||
|
serverId: interaction.guild.id,
|
||||||
|
userId: interaction.user.id
|
||||||
|
}
|
||||||
|
},
|
||||||
|
update: {
|
||||||
|
birthday: new Date(`${month}-${day}-2000`)
|
||||||
|
},
|
||||||
|
create: {
|
||||||
|
serverId: interaction.guild.id,
|
||||||
|
userId: interaction.user.id,
|
||||||
|
birthday: new Date(`${month}-${day}-2000`)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await interaction.editReply(
|
||||||
|
`Your birthday has been set to ${month}-${day}!`
|
||||||
|
);
|
||||||
|
} catch (err) {
|
||||||
|
const id = await errorHandler(bot, "birthday command", err);
|
||||||
|
await interaction.editReply({
|
||||||
|
content: `Something went wrong. Please [join our support server](https://chat.naomi.lgbt) and provide this ID: \`${id}\``
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
@ -11,6 +11,7 @@ import { Command } from "../interfaces/Command";
|
|||||||
import { CommandHandler } from "../interfaces/CommandHandler";
|
import { CommandHandler } from "../interfaces/CommandHandler";
|
||||||
import { getConfig } from "../modules/data/getConfig";
|
import { getConfig } from "../modules/data/getConfig";
|
||||||
import { handleAppealLink } from "../modules/subcommands/config/handleAppealLink";
|
import { handleAppealLink } from "../modules/subcommands/config/handleAppealLink";
|
||||||
|
import { handleBirthdayChannel } from "../modules/subcommands/config/handleBirthdayChannel";
|
||||||
import { handleInviteLink } from "../modules/subcommands/config/handleInviteLink";
|
import { handleInviteLink } from "../modules/subcommands/config/handleInviteLink";
|
||||||
import { handleJoinRole } from "../modules/subcommands/config/handleJoinRole";
|
import { handleJoinRole } from "../modules/subcommands/config/handleJoinRole";
|
||||||
import { handleList } from "../modules/subcommands/config/handleList";
|
import { handleList } from "../modules/subcommands/config/handleList";
|
||||||
@ -24,7 +25,8 @@ const handlers: { [key: string]: CommandHandler } = {
|
|||||||
"appeal-link": handleAppealLink,
|
"appeal-link": handleAppealLink,
|
||||||
logging: handleLogging,
|
logging: handleLogging,
|
||||||
role: handleRole,
|
role: handleRole,
|
||||||
"join-role": handleJoinRole
|
"join-role": handleJoinRole,
|
||||||
|
"birthday-channel": handleBirthdayChannel
|
||||||
};
|
};
|
||||||
|
|
||||||
export const config: Command = {
|
export const config: Command = {
|
||||||
@ -101,6 +103,19 @@ export const config: Command = {
|
|||||||
.setDescription("The role to assign.")
|
.setDescription("The role to assign.")
|
||||||
.setRequired(true)
|
.setRequired(true)
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
.addSubcommand(
|
||||||
|
new SlashCommandSubcommandBuilder()
|
||||||
|
.setName("birthday-channel")
|
||||||
|
.setDescription(
|
||||||
|
"Configure a channel where members can be wished a happy birthday."
|
||||||
|
)
|
||||||
|
.addChannelOption((o) =>
|
||||||
|
o
|
||||||
|
.setName("channel")
|
||||||
|
.setDescription("The channel to send birthday messages in.")
|
||||||
|
.setRequired(true)
|
||||||
|
)
|
||||||
),
|
),
|
||||||
run: async (bot, interaction) => {
|
run: async (bot, interaction) => {
|
||||||
try {
|
try {
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
|
import { scheduleJob } from "node-schedule";
|
||||||
|
|
||||||
import { ExtendedClient } from "../../interfaces/ExtendedClient";
|
import { ExtendedClient } from "../../interfaces/ExtendedClient";
|
||||||
|
import { postBirthdays } from "../../modules/postBirthdays";
|
||||||
import { registerCommands } from "../../utils/registerCommands";
|
import { registerCommands } from "../../utils/registerCommands";
|
||||||
import { sendDebugMessage } from "../../utils/sendDebugMessage";
|
import { sendDebugMessage } from "../../utils/sendDebugMessage";
|
||||||
|
|
||||||
@ -10,4 +13,7 @@ import { sendDebugMessage } from "../../utils/sendDebugMessage";
|
|||||||
export const onReady = async (bot: ExtendedClient) => {
|
export const onReady = async (bot: ExtendedClient) => {
|
||||||
await sendDebugMessage(bot, `Logged in as ${bot.user?.tag}`);
|
await sendDebugMessage(bot, `Logged in as ${bot.user?.tag}`);
|
||||||
await registerCommands(bot);
|
await registerCommands(bot);
|
||||||
|
|
||||||
|
// Daily at 9am PST
|
||||||
|
scheduleJob("birthdays", "0 9 * * *", async () => await postBirthdays(bot));
|
||||||
};
|
};
|
||||||
|
@ -20,6 +20,12 @@ export const onMemberRemove = async (
|
|||||||
|
|
||||||
const config = await getConfig(bot, guild.id);
|
const config = await getConfig(bot, guild.id);
|
||||||
|
|
||||||
|
await bot.db.birthdays.delete({
|
||||||
|
where: {
|
||||||
|
serverId_userId: { serverId: guild.id, userId: user.id }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if (!config.eventLogChannel) {
|
if (!config.eventLogChannel) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
41
src/modules/postBirthdays.ts
Normal file
41
src/modules/postBirthdays.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import { ExtendedClient } from "../interfaces/ExtendedClient";
|
||||||
|
import { errorHandler } from "../utils/errorHandler";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches the configs from the database, then for each config that
|
||||||
|
* has a birthday channel set, fetch birthdays. If any are from today,
|
||||||
|
* post!
|
||||||
|
*
|
||||||
|
* @param {ExtendedClient} bot The bot's Discord instance.
|
||||||
|
*/
|
||||||
|
export const postBirthdays = async (bot: ExtendedClient) => {
|
||||||
|
try {
|
||||||
|
const configs = await bot.db.configs.findMany();
|
||||||
|
const withChannel = configs.filter((c) => c.birthdayChannel);
|
||||||
|
for (const record of withChannel) {
|
||||||
|
const guild = bot.guilds.cache.get(record.serverId);
|
||||||
|
if (!guild) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const channel = guild.channels.cache.get(record.birthdayChannel);
|
||||||
|
if (!channel || !("send" in channel)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const hasBirthdaySet = await bot.db.birthdays.findMany({
|
||||||
|
where: { serverId: guild.id }
|
||||||
|
});
|
||||||
|
const today = new Date();
|
||||||
|
const todayIn2000 = new Date(
|
||||||
|
`2000-${today.getMonth() + 1}-${today.getDate()}`
|
||||||
|
);
|
||||||
|
const isBirthdayToday = hasBirthdaySet.filter(
|
||||||
|
(r) => r.birthday === todayIn2000
|
||||||
|
);
|
||||||
|
const names = isBirthdayToday.map((r) => `<@${r.userId}>`).join(", ");
|
||||||
|
await channel.send(`Happy birthday to these lovely people~!\n${names}`);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
await errorHandler(bot, "post birthdays", err);
|
||||||
|
}
|
||||||
|
};
|
52
src/modules/subcommands/config/handleBirthdayChannel.ts
Normal file
52
src/modules/subcommands/config/handleBirthdayChannel.ts
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import { PermissionFlagsBits } from "discord.js";
|
||||||
|
|
||||||
|
import { CommandHandler } from "../../../interfaces/CommandHandler";
|
||||||
|
import { errorHandler } from "../../../utils/errorHandler";
|
||||||
|
import { setConfig } from "../../data/setConfig";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the birthday channel for the server.
|
||||||
|
*/
|
||||||
|
export const handleBirthdayChannel: CommandHandler = async (
|
||||||
|
bot,
|
||||||
|
interaction
|
||||||
|
) => {
|
||||||
|
try {
|
||||||
|
const channel = interaction.options.getChannel("channel", true);
|
||||||
|
if (!("send" in channel)) {
|
||||||
|
await interaction.editReply({
|
||||||
|
content: "You must specify a text channel!"
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const me = await interaction.guild.members.fetchMe();
|
||||||
|
if (!me.permissionsIn(channel).has(PermissionFlagsBits.SendMessages)) {
|
||||||
|
await interaction.editReply({
|
||||||
|
content: "I can't send messages there. :c"
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const success = await setConfig(
|
||||||
|
bot,
|
||||||
|
interaction.guild.id,
|
||||||
|
"birthdayChannel",
|
||||||
|
channel.id
|
||||||
|
);
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
await interaction.editReply({
|
||||||
|
content: `Birthdays will be posted in ${channel.toString()}. Members can set their birthdays with the \`/birthday\` command.`
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await interaction.editReply({
|
||||||
|
content: "Failed to set the settings."
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
const id = await errorHandler(bot, "automod logging subcommand", err);
|
||||||
|
await interaction.editReply({
|
||||||
|
content: `Something went wrong. Please [join our support server](https://chat.naomi.lgbt) and provide this ID: \`${id}\``
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
Loading…
x
Reference in New Issue
Block a user