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/typescript-config": "3.0.0",
|
||||
"@types/express": "4.17.21",
|
||||
"@types/node-schedule": "2.1.7",
|
||||
"eslint": "8.57.0",
|
||||
"knip": "5.15.0",
|
||||
"prettier": "3.2.5",
|
||||
@ -42,6 +43,7 @@
|
||||
"dotenv": "16.4.5",
|
||||
"express": "4.19.2",
|
||||
"node-html-to-image": "4.0.0",
|
||||
"node-schedule": "2.1.1",
|
||||
"winston": "3.13.0"
|
||||
}
|
||||
}
|
||||
|
78
pnpm-lock.yaml
generated
78
pnpm-lock.yaml
generated
@ -26,6 +26,9 @@ importers:
|
||||
node-html-to-image:
|
||||
specifier: 4.0.0
|
||||
version: 4.0.0
|
||||
node-schedule:
|
||||
specifier: 2.1.1
|
||||
version: 2.1.1
|
||||
winston:
|
||||
specifier: 3.13.0
|
||||
version: 3.13.0
|
||||
@ -42,6 +45,9 @@ importers:
|
||||
'@types/express':
|
||||
specifier: 4.17.21
|
||||
version: 4.17.21
|
||||
'@types/node-schedule':
|
||||
specifier: 2.1.7
|
||||
version: 2.1.7
|
||||
eslint:
|
||||
specifier: 8.57.0
|
||||
version: 8.57.0
|
||||
@ -323,6 +329,9 @@ packages:
|
||||
'@types/mime@3.0.1':
|
||||
resolution: {integrity: sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==}
|
||||
|
||||
'@types/node-schedule@2.1.7':
|
||||
resolution: {integrity: sha512-G7Z3R9H7r3TowoH6D2pkzUHPhcJrDF4Jz1JOQ80AX0K2DWTHoN9VC94XzFAPNMdbW9TBzMZ3LjpFi7RYdbxtXA==}
|
||||
|
||||
'@types/node@20.3.1':
|
||||
resolution: {integrity: sha512-EhcH/wvidPy1WeML3TtYFGR83UzjxeWRen9V402T8aUGYsCHOmfoisV3ZSg03gAFIbLq8TnWOJ0f4cALtnSEUg==}
|
||||
|
||||
@ -650,6 +659,10 @@ packages:
|
||||
resolution: {integrity: sha512-3rTMnFJA1tCOPwRxtgF4wd7Ab2qvDbL8jX+3smjIbS4HlZBagTlpERbdN7iAbWlrfxE3M8c27kTwTawQ7st+OQ==}
|
||||
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:
|
||||
resolution: {integrity: sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==}
|
||||
|
||||
@ -1439,6 +1452,9 @@ packages:
|
||||
logform@2.5.1:
|
||||
resolution: {integrity: sha512-9FyqAm9o9NKKfiAKfZoYo9bGXXuwMkxQiQttkT4YjjVtQVIQtK6LmVtlxmCaFswo6N4AfEkHqZTV0taDtPotNg==}
|
||||
|
||||
long-timeout@0.1.1:
|
||||
resolution: {integrity: sha512-BFRuQUqc7x2NWxfJBCyUrN8iYUYznzL9JROmRz1gZ6KlOIgmoD+njPVbb+VNn2nGMKggMsK79iUNErillsrx7w==}
|
||||
|
||||
lru-cache@6.0.0:
|
||||
resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
|
||||
engines: {node: '>=10'}
|
||||
@ -1447,6 +1463,10 @@ packages:
|
||||
resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
luxon@3.4.4:
|
||||
resolution: {integrity: sha512-zobTr7akeGHnv7eBOXcRgMeCP6+uyYsczwmeRCauvpvaAltgNyTbLH/+VaEAPUeWBT+1GuNmz4wC/6jtQzbbVA==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
magic-bytes.js@1.10.0:
|
||||
resolution: {integrity: sha512-/k20Lg2q8LE5xiaaSkMXk4sfvI+9EGEykFS4b0CHHGWqDYU0bGUFSwchNOMA56D7TCs9GwVTkqe9als1/ns8UQ==}
|
||||
|
||||
@ -1539,6 +1559,10 @@ packages:
|
||||
node-html-to-image@4.0.0:
|
||||
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:
|
||||
resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==}
|
||||
|
||||
@ -1866,6 +1890,9 @@ packages:
|
||||
resolution: {integrity: sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==}
|
||||
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:
|
||||
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
|
||||
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)':
|
||||
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)
|
||||
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-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:
|
||||
- '@types/eslint'
|
||||
- eslint-import-resolver-typescript
|
||||
@ -2452,7 +2479,7 @@ snapshots:
|
||||
'@pkgr/core@0.1.1': {}
|
||||
|
||||
'@prisma/client@5.13.0(prisma@5.13.0)':
|
||||
dependencies:
|
||||
optionalDependencies:
|
||||
prisma: 5.13.0
|
||||
|
||||
'@prisma/debug@5.13.0': {}
|
||||
@ -2536,6 +2563,10 @@ snapshots:
|
||||
|
||||
'@types/mime@3.0.1': {}
|
||||
|
||||
'@types/node-schedule@2.1.7':
|
||||
dependencies:
|
||||
'@types/node': 20.3.1
|
||||
|
||||
'@types/node@20.3.1': {}
|
||||
|
||||
'@types/qs@6.9.7': {}
|
||||
@ -2565,7 +2596,7 @@ snapshots:
|
||||
'@types/node': 20.3.1
|
||||
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:
|
||||
'@eslint-community/regexpp': 4.5.1
|
||||
'@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
|
||||
semver: 7.5.2
|
||||
tsutils: 3.21.0(typescript@5.4.5)
|
||||
optionalDependencies:
|
||||
typescript: 5.4.5
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
@ -2590,6 +2622,7 @@ snapshots:
|
||||
'@typescript-eslint/typescript-estree': 5.62.0(typescript@5.4.5)
|
||||
debug: 4.3.4
|
||||
eslint: 8.57.0
|
||||
optionalDependencies:
|
||||
typescript: 5.4.5
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
@ -2606,6 +2639,7 @@ snapshots:
|
||||
debug: 4.3.4
|
||||
eslint: 8.57.0
|
||||
tsutils: 3.21.0(typescript@5.4.5)
|
||||
optionalDependencies:
|
||||
typescript: 5.4.5
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
@ -2621,6 +2655,7 @@ snapshots:
|
||||
is-glob: 4.0.3
|
||||
semver: 7.5.2
|
||||
tsutils: 3.21.0(typescript@5.4.5)
|
||||
optionalDependencies:
|
||||
typescript: 5.4.5
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
@ -2912,6 +2947,10 @@ snapshots:
|
||||
parse-json: 5.2.0
|
||||
path-type: 4.0.0
|
||||
|
||||
cron-parser@4.9.0:
|
||||
dependencies:
|
||||
luxon: 3.4.4
|
||||
|
||||
cross-fetch@4.0.0:
|
||||
dependencies:
|
||||
node-fetch: 2.7.0
|
||||
@ -3202,18 +3241,18 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- 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:
|
||||
'@typescript-eslint/parser': 5.62.0(eslint@8.57.0)(typescript@5.4.5)
|
||||
debug: 3.2.7
|
||||
optionalDependencies:
|
||||
'@typescript-eslint/parser': 5.62.0(eslint@8.57.0)(typescript@5.4.5)
|
||||
eslint: 8.57.0
|
||||
eslint-import-resolver-node: 0.3.7
|
||||
transitivePeerDependencies:
|
||||
- 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:
|
||||
'@typescript-eslint/parser': 5.62.0(eslint@8.57.0)(typescript@5.4.5)
|
||||
array-includes: 3.1.6
|
||||
array.prototype.findlastindex: 1.2.5
|
||||
array.prototype.flat: 1.3.1
|
||||
@ -3222,7 +3261,7 @@ snapshots:
|
||||
doctrine: 2.1.0
|
||||
eslint: 8.57.0
|
||||
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
|
||||
is-core-module: 2.13.1
|
||||
is-glob: 4.0.3
|
||||
@ -3232,6 +3271,8 @@ snapshots:
|
||||
object.values: 1.1.6
|
||||
semver: 6.3.1
|
||||
tsconfig-paths: 3.14.2
|
||||
optionalDependencies:
|
||||
'@typescript-eslint/parser': 5.62.0(eslint@8.57.0)(typescript@5.4.5)
|
||||
transitivePeerDependencies:
|
||||
- eslint-import-resolver-typescript
|
||||
- eslint-import-resolver-webpack
|
||||
@ -3253,13 +3294,14 @@ snapshots:
|
||||
|
||||
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:
|
||||
eslint: 8.57.0
|
||||
eslint-config-prettier: 9.0.0(eslint@8.57.0)
|
||||
prettier: 3.2.5
|
||||
prettier-linter-helpers: 1.0.0
|
||||
synckit: 0.8.8
|
||||
optionalDependencies:
|
||||
eslint-config-prettier: 9.0.0(eslint@8.57.0)
|
||||
|
||||
eslint-scope@5.1.1:
|
||||
dependencies:
|
||||
@ -3891,12 +3933,16 @@ snapshots:
|
||||
safe-stable-stringify: 2.4.3
|
||||
triple-beam: 1.3.0
|
||||
|
||||
long-timeout@0.1.1: {}
|
||||
|
||||
lru-cache@6.0.0:
|
||||
dependencies:
|
||||
yallist: 4.0.0
|
||||
|
||||
lru-cache@7.18.3: {}
|
||||
|
||||
luxon@3.4.4: {}
|
||||
|
||||
magic-bytes.js@1.10.0: {}
|
||||
|
||||
magic-string@0.16.0:
|
||||
@ -3967,6 +4013,12 @@ snapshots:
|
||||
- supports-color
|
||||
- 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.13.1: {}
|
||||
@ -4346,6 +4398,8 @@ snapshots:
|
||||
ip-address: 9.0.5
|
||||
smart-buffer: 4.2.0
|
||||
|
||||
sorted-array-functions@1.3.0: {}
|
||||
|
||||
source-map@0.6.1: {}
|
||||
|
||||
spdx-exceptions@2.3.0: {}
|
||||
|
@ -60,6 +60,7 @@ model configs {
|
||||
eventLogChannel String @default("")
|
||||
messageReportChannel String @default("")
|
||||
joinRole String @default("")
|
||||
birthdayChannel String @default("")
|
||||
|
||||
@@unique([serverId], map: "serverId")
|
||||
}
|
||||
@ -80,3 +81,12 @@ model roles {
|
||||
|
||||
@@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 { getConfig } from "../modules/data/getConfig";
|
||||
import { handleAppealLink } from "../modules/subcommands/config/handleAppealLink";
|
||||
import { handleBirthdayChannel } from "../modules/subcommands/config/handleBirthdayChannel";
|
||||
import { handleInviteLink } from "../modules/subcommands/config/handleInviteLink";
|
||||
import { handleJoinRole } from "../modules/subcommands/config/handleJoinRole";
|
||||
import { handleList } from "../modules/subcommands/config/handleList";
|
||||
@ -24,7 +25,8 @@ const handlers: { [key: string]: CommandHandler } = {
|
||||
"appeal-link": handleAppealLink,
|
||||
logging: handleLogging,
|
||||
role: handleRole,
|
||||
"join-role": handleJoinRole
|
||||
"join-role": handleJoinRole,
|
||||
"birthday-channel": handleBirthdayChannel
|
||||
};
|
||||
|
||||
export const config: Command = {
|
||||
@ -101,6 +103,19 @@ export const config: Command = {
|
||||
.setDescription("The role to assign.")
|
||||
.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) => {
|
||||
try {
|
||||
|
@ -1,4 +1,7 @@
|
||||
import { scheduleJob } from "node-schedule";
|
||||
|
||||
import { ExtendedClient } from "../../interfaces/ExtendedClient";
|
||||
import { postBirthdays } from "../../modules/postBirthdays";
|
||||
import { registerCommands } from "../../utils/registerCommands";
|
||||
import { sendDebugMessage } from "../../utils/sendDebugMessage";
|
||||
|
||||
@ -10,4 +13,7 @@ import { sendDebugMessage } from "../../utils/sendDebugMessage";
|
||||
export const onReady = async (bot: ExtendedClient) => {
|
||||
await sendDebugMessage(bot, `Logged in as ${bot.user?.tag}`);
|
||||
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);
|
||||
|
||||
await bot.db.birthdays.delete({
|
||||
where: {
|
||||
serverId_userId: { serverId: guild.id, userId: user.id }
|
||||
}
|
||||
});
|
||||
|
||||
if (!config.eventLogChannel) {
|
||||
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