Compare commits

..

12 commits

Author SHA1 Message Date
Slincnik
fbf79936c0
build: remove unusable packages 2025-01-15 00:31:22 +03:00
Slincnik
b8cc8d8d30
fix: fixing typing 2025-01-15 00:25:41 +03:00
Slincnik
d437e2b723
build: replacing aliases paths with relative 2025-01-15 00:24:41 +03:00
Slincnik
ca17bcaf44
fix: types and func 2025-01-15 00:01:24 +03:00
Slincnik
01b12023a1
fix: fixing config instance npt private 2025-01-14 23:51:12 +03:00
Slincnik
a0309c164a
refactor: added debug in many loading func 2025-01-14 23:50:48 +03:00
Slincnik
cc10969ccf
refactor: change logger func when called error, warn 2025-01-14 23:49:31 +03:00
Slincnik
7e7cbcae0b
refactor: remove unusable func 2025-01-14 23:49:05 +03:00
Slincnik
2eab0d541e
ci: changed eslint config 2025-01-14 22:48:11 +03:00
Slincnik
4c8c068245
fix: many times sending reminds 2025-01-14 22:20:22 +03:00
Slincnik
ac63acd993
feat(validations): added cooldown 2025-01-14 22:11:45 +03:00
Slincnik
ceea161dc4
fix: devOnly validation 2025-01-14 22:09:42 +03:00
16 changed files with 238 additions and 81 deletions

View file

@ -21,14 +21,8 @@ export default [
"@stylistic/js": stylisticJs, "@stylistic/js": stylisticJs,
}, },
rules: { rules: {
"no-unused-vars": [ "no-unused-vars": "off",
"error", "@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_", varsIgnorePattern: "^_", caughtErrorsIgnorePattern: "^_" }],
{
argsIgnorePattern: "^_", // Игнорировать переменные, начинающиеся с _
varsIgnorePattern: "^_", // Игнорировать переменные, начинающиеся с _
ignoreRestSiblings: true, // Игнорировать неиспользуемые параметры в деструктуризации
},
],
"arrow-body-style": ["error", "as-needed"], "arrow-body-style": ["error", "as-needed"],
camelcase: "error", camelcase: "error",
curly: ["error", "multi-line"], curly: ["error", "multi-line"],

View file

@ -7,7 +7,7 @@
"scripts": { "scripts": {
"start": "node dist/index.js", "start": "node dist/index.js",
"dev": "tsx watch src/index.ts", "dev": "tsx watch src/index.ts",
"build": "tsc" "build": "tsc && tsc-alias"
}, },
"author": "https://github.com/JonnyBro", "author": "https://github.com/JonnyBro",
"dependencies": { "dependencies": {
@ -17,7 +17,6 @@
"@napi-rs/canvas": "^0.1.63", "@napi-rs/canvas": "^0.1.63",
"chalk": "^4.1.2", "chalk": "^4.1.2",
"cron": "^3.2.1", "cron": "^3.2.1",
"discord-api-types": "^0.37.107",
"discord-giveaways": "^6.0.1", "discord-giveaways": "^6.0.1",
"discord-player": "^6.7.1", "discord-player": "^6.7.1",
"discord-player-youtubei": "1.3.5", "discord-player-youtubei": "1.3.5",
@ -42,6 +41,7 @@
"globals": "^15.13.0", "globals": "^15.13.0",
"prettier": "^3.4.2", "prettier": "^3.4.2",
"prettier-eslint": "^16.3.0", "prettier-eslint": "^16.3.0",
"tsc-alias": "^1.8.10",
"tsx": "^4.19.2", "tsx": "^4.19.2",
"typescript": "^5.7.3" "typescript": "^5.7.3"
} }

View file

@ -26,9 +26,6 @@ importers:
cron: cron:
specifier: ^3.2.1 specifier: ^3.2.1
version: 3.2.1 version: 3.2.1
discord-api-types:
specifier: ^0.37.107
version: 0.37.107
discord-giveaways: discord-giveaways:
specifier: ^6.0.1 specifier: ^6.0.1
version: 6.0.1(discord.js@14.16.3) version: 6.0.1(discord.js@14.16.3)
@ -96,6 +93,9 @@ importers:
prettier-eslint: prettier-eslint:
specifier: ^16.3.0 specifier: ^16.3.0
version: 16.3.0 version: 16.3.0
tsc-alias:
specifier: ^1.8.10
version: 1.8.10
tsx: tsx:
specifier: ^4.19.2 specifier: ^4.19.2
version: 4.19.2 version: 4.19.2
@ -663,6 +663,10 @@ packages:
any-promise@1.3.0: any-promise@1.3.0:
resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==}
anymatch@3.1.3:
resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
engines: {node: '>= 8'}
aproba@2.0.0: aproba@2.0.0:
resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==}
@ -684,6 +688,10 @@ packages:
barse@0.4.3: barse@0.4.3:
resolution: {integrity: sha512-UEpvriJqAn8zuVinYICuKoPttZy3XxXEoqX/V2uYAL4zzJRuNzCK3+20nAu3YUIa2U7G53kf90wfBIp9/A+Odw==} resolution: {integrity: sha512-UEpvriJqAn8zuVinYICuKoPttZy3XxXEoqX/V2uYAL4zzJRuNzCK3+20nAu3YUIa2U7G53kf90wfBIp9/A+Odw==}
binary-extensions@2.3.0:
resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
engines: {node: '>=8'}
boolbase@1.0.0: boolbase@1.0.0:
resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==}
@ -731,6 +739,10 @@ packages:
resolution: {integrity: sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==} resolution: {integrity: sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==}
engines: {node: '>= 6'} engines: {node: '>= 6'}
chokidar@3.6.0:
resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
engines: {node: '>= 8.10.0'}
chownr@2.0.0: chownr@2.0.0:
resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==}
engines: {node: '>=10'} engines: {node: '>=10'}
@ -750,6 +762,10 @@ packages:
resolution: {integrity: sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==} resolution: {integrity: sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==}
engines: {node: '>= 6'} engines: {node: '>= 6'}
commander@9.5.0:
resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==}
engines: {node: ^12.20.0 || >=14}
common-tags@1.8.2: common-tags@1.8.2:
resolution: {integrity: sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==} resolution: {integrity: sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==}
engines: {node: '>=4.0.0'} engines: {node: '>=4.0.0'}
@ -1161,6 +1177,10 @@ packages:
resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==} resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==}
engines: {node: '>= 12'} engines: {node: '>= 12'}
is-binary-path@2.1.0:
resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
engines: {node: '>=8'}
is-buffer@1.1.6: is-buffer@1.1.6:
resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==}
@ -1368,6 +1388,10 @@ packages:
ms@2.1.3: ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
mylas@2.1.13:
resolution: {integrity: sha512-+MrqnJRtxdF+xngFfUUkIMQrUUL0KsxbADUkn23Z/4ibGg192Q+z+CQyiYwvWTsYjJygmMR8+w3ZDa98Zh6ESg==}
engines: {node: '>=12.0.0'}
natural-compare@1.4.0: natural-compare@1.4.0:
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
@ -1399,6 +1423,10 @@ packages:
engines: {node: '>=6'} engines: {node: '>=6'}
hasBin: true hasBin: true
normalize-path@3.0.0:
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
engines: {node: '>=0.10.0'}
normalize-url@8.0.1: normalize-url@8.0.1:
resolution: {integrity: sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==} resolution: {integrity: sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==}
engines: {node: '>=14.16'} engines: {node: '>=14.16'}
@ -1467,6 +1495,10 @@ packages:
resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
engines: {node: '>=8.6'} engines: {node: '>=8.6'}
plimit-lit@1.6.1:
resolution: {integrity: sha512-B7+VDyb8Tl6oMJT9oSO2CW8XC/T4UcJGrwOVoNGwOQsQYhlpfajmrMj5xeejqaASq3V/EqThyOeATEOMuSEXiA==}
engines: {node: '>=12'}
prelude-ls@1.2.1: prelude-ls@1.2.1:
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
engines: {node: '>= 0.8.0'} engines: {node: '>= 0.8.0'}
@ -1516,6 +1548,10 @@ packages:
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
engines: {node: '>=6'} engines: {node: '>=6'}
queue-lit@1.5.2:
resolution: {integrity: sha512-tLc36IOPeMAubu8BkW8YDBV+WyIgKlYU7zUNs0J5Vk9skSZ4JfGlPOqplP0aHdfv7HL0B2Pg6nwiq60Qc6M2Hw==}
engines: {node: '>=12'}
queue-microtask@1.2.3: queue-microtask@1.2.3:
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
@ -1543,6 +1579,10 @@ packages:
resolution: {integrity: sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==} resolution: {integrity: sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==}
engines: {node: '>=8'} engines: {node: '>=8'}
readdirp@3.6.0:
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
engines: {node: '>=8.10.0'}
regenerator-runtime@0.14.1: regenerator-runtime@0.14.1:
resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==}
@ -1732,6 +1772,10 @@ packages:
ts-mixer@6.0.4: ts-mixer@6.0.4:
resolution: {integrity: sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA==} resolution: {integrity: sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA==}
tsc-alias@1.8.10:
resolution: {integrity: sha512-Ibv4KAWfFkFdKJxnWfVtdOmB0Zi1RJVxcbPGiCDsFpCQSsmpWyuzHG3rQyI5YkobWwxFPEyQfu1hdo4qLG2zPw==}
hasBin: true
tslib@2.7.0: tslib@2.7.0:
resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==} resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==}
@ -2399,6 +2443,11 @@ snapshots:
any-promise@1.3.0: {} any-promise@1.3.0: {}
anymatch@3.1.3:
dependencies:
normalize-path: 3.0.0
picomatch: 2.3.1
aproba@2.0.0: {} aproba@2.0.0: {}
are-we-there-yet@2.0.0: are-we-there-yet@2.0.0:
@ -2416,6 +2465,8 @@ snapshots:
dependencies: dependencies:
readable-stream: 1.0.34 readable-stream: 1.0.34
binary-extensions@2.3.0: {}
boolbase@1.0.0: {} boolbase@1.0.0: {}
brace-expansion@1.1.11: brace-expansion@1.1.11:
@ -2481,6 +2532,18 @@ snapshots:
parse5: 7.2.1 parse5: 7.2.1
parse5-htmlparser2-tree-adapter: 7.1.0 parse5-htmlparser2-tree-adapter: 7.1.0
chokidar@3.6.0:
dependencies:
anymatch: 3.1.3
braces: 3.0.3
glob-parent: 5.1.2
is-binary-path: 2.1.0
is-glob: 4.0.3
normalize-path: 3.0.0
readdirp: 3.6.0
optionalDependencies:
fsevents: 2.3.3
chownr@2.0.0: {} chownr@2.0.0: {}
color-convert@2.0.1: color-convert@2.0.1:
@ -2493,6 +2556,8 @@ snapshots:
commander@6.2.1: {} commander@6.2.1: {}
commander@9.5.0: {}
common-tags@1.8.2: {} common-tags@1.8.2: {}
concat-map@0.0.1: {} concat-map@0.0.1: {}
@ -3038,6 +3103,10 @@ snapshots:
sprintf-js: 1.1.3 sprintf-js: 1.1.3
optional: true optional: true
is-binary-path@2.1.0:
dependencies:
binary-extensions: 2.3.0
is-buffer@1.1.6: {} is-buffer@1.1.6: {}
is-extglob@2.1.1: {} is-extglob@2.1.1: {}
@ -3214,6 +3283,8 @@ snapshots:
ms@2.1.3: {} ms@2.1.3: {}
mylas@2.1.13: {}
natural-compare@1.4.0: {} natural-compare@1.4.0: {}
node-addon-api@5.1.0: {} node-addon-api@5.1.0: {}
@ -3239,6 +3310,8 @@ snapshots:
dependencies: dependencies:
abbrev: 1.1.1 abbrev: 1.1.1
normalize-path@3.0.0: {}
normalize-url@8.0.1: {} normalize-url@8.0.1: {}
npmlog@5.0.1: npmlog@5.0.1:
@ -3302,6 +3375,10 @@ snapshots:
picomatch@2.3.1: {} picomatch@2.3.1: {}
plimit-lit@1.6.1:
dependencies:
queue-lit: 1.5.2
prelude-ls@1.2.1: {} prelude-ls@1.2.1: {}
prettier-eslint@16.3.0: prettier-eslint@16.3.0:
@ -3337,6 +3414,8 @@ snapshots:
punycode@2.3.1: {} punycode@2.3.1: {}
queue-lit@1.5.2: {}
queue-microtask@1.2.3: {} queue-microtask@1.2.3: {}
quick-lru@5.1.1: {} quick-lru@5.1.1: {}
@ -3374,6 +3453,10 @@ snapshots:
dependencies: dependencies:
readable-stream: 3.6.2 readable-stream: 3.6.2
readdirp@3.6.0:
dependencies:
picomatch: 2.3.1
regenerator-runtime@0.14.1: {} regenerator-runtime@0.14.1: {}
require-relative@0.8.7: {} require-relative@0.8.7: {}
@ -3545,6 +3628,15 @@ snapshots:
ts-mixer@6.0.4: {} ts-mixer@6.0.4: {}
tsc-alias@1.8.10:
dependencies:
chokidar: 3.6.0
commander: 9.5.0
globby: 11.1.0
mylas: 2.1.13
normalize-path: 3.0.0
plimit-lit: 1.6.1
tslib@2.7.0: {} tslib@2.7.0: {}
tsx@4.19.2: tsx@4.19.2:

View file

@ -37,6 +37,7 @@ const registerGlobalCommands = async (client: ExtendedClient, commands: CommandF
logger.log(`Edited command globally: ${data.name}`); logger.log(`Edited command globally: ${data.name}`);
} else if (!targetCommand) { } else if (!targetCommand) {
await appCommandsManager.create(data).catch(() => logger.error(`Failed to register command: ${data.name}`)); await appCommandsManager.create(data).catch(() => logger.error(`Failed to register command: ${data.name}`));
logger.debug(`Command ${data.name} loaded globally`);
} }
}), }),
); );
@ -77,6 +78,7 @@ const registerDevCommands = async (client: ExtendedClient, commands: CommandFile
logger.log(`Edited command globally: ${data.name}`); logger.log(`Edited command globally: ${data.name}`);
} else if (!targetCommand) { } else if (!targetCommand) {
await guildCommands.create(data).catch(() => logger.error(`Failed to register command: ${data.name} in ${guildCommands.guild.name} server`)); await guildCommands.create(data).catch(() => logger.error(`Failed to register command: ${data.name} in ${guildCommands.guild.name} server`));
logger.debug(`Command ${data.name} loaded in dev`);
} }
}); });
}), }),

View file

@ -34,7 +34,7 @@ export class CommandHandler {
const commandFilePaths = (await getFilePaths(cmdPath, true)).filter(path => path.endsWith(".js") || path.endsWith(".ts")); const commandFilePaths = (await getFilePaths(cmdPath, true)).filter(path => path.endsWith(".js") || path.endsWith(".ts"));
for (const cmdFilePath of commandFilePaths) { for (const cmdFilePath of commandFilePaths) {
const { data, run } = await import(toFileURL(cmdFilePath)); const { data, run, options } = await import(toFileURL(cmdFilePath));
if (!data || !data.name) { if (!data || !data.name) {
logger.warn(`Command ${cmdFilePath} does not have a data object or name`); logger.warn(`Command ${cmdFilePath} does not have a data object or name`);
@ -46,7 +46,7 @@ export class CommandHandler {
continue; continue;
} }
this.commands.push({ data, run }); this.commands.push({ data, run, options });
} }
} }
@ -94,7 +94,7 @@ export class CommandHandler {
interaction, interaction,
}); });
} catch (error) { } catch (error) {
logger.error(error); logger.error(error, "Command cannot be executed");
} }
}); });
} }

View file

@ -0,0 +1,37 @@
import { BuiltInValidationParams } from "@/types.js";
const cooldowns = new Map<string, Map<string, number>>();
export default function ({ targetCommand, interaction }: BuiltInValidationParams) {
const { cooldown } = targetCommand.options || {};
if (!cooldown) return;
const now = Date.now();
const userId = interaction.user.id;
const commandName = targetCommand.data.name;
if (!cooldowns.has(commandName)) {
cooldowns.set(commandName, new Map());
}
const userCooldowns = cooldowns.get(commandName)!;
if (userCooldowns) {
const expirationTime = userCooldowns.get(userId)! + cooldown * 1000;
if (now < expirationTime) {
const timeLeft = (expirationTime - now) / 1000;
if (!interaction.isRepliable()) return;
interaction.reply({
content: `❌ You can use this command again in ${timeLeft.toFixed(1)} seconds.`,
ephemeral: true,
});
return true;
}
}
userCooldowns.set(userId, now);
return false;
}

View file

@ -1,4 +1,5 @@
import { BuiltInValidationParams } from "@/types.js"; import { BuiltInValidationParams } from "@/types.js";
import { ChannelType } from "discord.js";
export default function ({ interaction, targetCommand, client }: BuiltInValidationParams) { export default function ({ interaction, targetCommand, client }: BuiltInValidationParams) {
if (interaction.isAutocomplete()) return; if (interaction.isAutocomplete()) return;
@ -7,6 +8,17 @@ export default function ({ interaction, targetCommand, client }: BuiltInValidati
if (!targetCommand.options?.devOnly) return; if (!targetCommand.options?.devOnly) return;
if (!interaction.isRepliable()) return;
if (interaction.channel?.type === ChannelType.DM) {
interaction.reply({
content: "❌ This command is only available in development servers.",
ephemeral: true,
});
return true;
}
if (interaction.inGuild() && !devGuildsIds.includes(interaction.guildId)) { if (interaction.inGuild() && !devGuildsIds.includes(interaction.guildId)) {
interaction.reply({ interaction.reply({
content: "❌ This command is only available in development servers.", content: "❌ This command is only available in development servers.",

View file

@ -1,3 +1,4 @@
import devOnly from "./devOnly.js"; import devOnly from "./devOnly.js";
import cooldown from "./cooldown.js";
export default [devOnly]; export default [devOnly, cooldown];

View file

@ -6,14 +6,14 @@ import { GuildQueueEvents, useMainPlayer } from "discord-player";
import { ExtendedClient } from "@/structures/client.js"; import { ExtendedClient } from "@/structures/client.js";
import { ClientEvents } from "discord.js"; import { ClientEvents } from "discord.js";
interface EventHandlerEvents { type EventHandlerEvents = {
data: { data: {
name: keyof ClientEvents; name: keyof ClientEvents;
once?: boolean; once?: boolean;
player?: boolean; player?: boolean;
}; };
run: Function; run: (...args: unknown[]) => void;
} };
export class EventHandler { export class EventHandler {
events: EventHandlerEvents[] = []; events: EventHandlerEvents[] = [];
@ -53,6 +53,8 @@ export class EventHandler {
} }
this.events.push({ data, run }); this.events.push({ data, run });
logger.debug(`Event ${eventFilePath} loaded`);
} }
} catch (error) { } catch (error) {
logger.error("Error build events: ", error); logger.error("Error build events: ", error);

View file

@ -1,6 +1,13 @@
import { BaseInteraction, User } from "discord.js"; import { BaseInteraction, CacheType, Interaction, InteractionReplyOptions, Message, User } from "discord.js";
import useClient from "@/utils/use-client.js"; import useClient from "@/utils/use-client.js";
interface Options extends InteractionReplyOptions {
prefixEmoji: string;
locale?: string;
edit?: boolean;
mention?: boolean;
}
export const getLocale = async (guildId: string) => { export const getLocale = async (guildId: string) => {
const client = useClient(); const client = useClient();
const guild = await client.getGuildData(guildId); const guild = await client.getGuildData(guildId);
@ -10,18 +17,18 @@ export const getLocale = async (guildId: string) => {
const getAppEmojis = () => { const getAppEmojis = () => {
const client = useClient(); const client = useClient();
return client.application?.emojis.cache; return client.application.emojis.cache;
}; };
const formatReply = (prefixEmoji: string, message: string) => { const formatReply = (prefixEmoji: string, message: string) => {
const emojis = getAppEmojis()!; const emojis = getAppEmojis();
return prefixEmoji ? `${emojis.find(e => e.name === prefixEmoji).toString()} ${message}` : `${message}`; const emoji = emojis.find(emoji => emoji.name === prefixEmoji);
return prefixEmoji ? `${emoji?.toString()} ${message}` : `${message}`;
}; };
export const getUsername = (user: User) => (user.discriminator === "0" ? user.username : user.tag); export const getUsername = (user: User) => (user.discriminator === "0" ? user.username : user.tag);
export const replyTranslated = async (context, key, args, options = {}) => { export const replyTranslated = async <T extends CacheType = CacheType>(context: Interaction<T> | Message, key: string, args: unknown[], options: Options) => {
const client = useClient(); const client = useClient();
const locale = options.locale || client.configService.get("defaultLang"); const locale = options.locale || client.configService.get("defaultLang");
const translated = client.translate(key, { const translated = client.translate(key, {
@ -31,33 +38,39 @@ export const replyTranslated = async (context, key, args, options = {}) => {
const content = formatReply(options.prefixEmoji, translated); const content = formatReply(options.prefixEmoji, translated);
const isInteraction = context instanceof BaseInteraction; if (context instanceof BaseInteraction) {
if (!context.isRepliable()) return;
if (options.edit) { if (options.edit) {
return isInteraction await context.editReply({ content });
? await context.editReply({ return;
content,
ephemeral: options.ephemeral || false,
})
: await context.edit({ content, allowedMentions: { repliedUser: options.mention || false } });
} }
return isInteraction await context.reply({
? await context.reply({
content, content,
ephemeral: options.ephemeral || false, ephemeral: options.ephemeral || false,
}) });
: await context.reply({ return;
}
if (options.edit) {
await context.edit({
content,
allowedMentions: { repliedUser: options.mention || false },
});
return;
}
await context.reply({
content, content,
allowedMentions: { repliedUser: options.mention || false }, allowedMentions: { repliedUser: options.mention || false },
}); });
}; };
export const replySuccess = async (context, key, args, options) => { export const replySuccess = async <T extends CacheType = CacheType>(context: Interaction<T> | Message, key: string, args: unknown[], options: Options) => {
options.prefixEmoji = "success"; options.prefixEmoji = "success";
return await replyTranslated(context, key, args, options); return await replyTranslated(context, key, args, options);
}; };
export const replyError = async (context, key, args, options) => { export const replyError = async <T extends CacheType = CacheType>(context: Interaction<T> | Message, key: string, args: unknown[], options: Options) => {
options.prefixEmoji = "error"; options.prefixEmoji = "error";
return await replyTranslated(context, key, args, options); return await replyTranslated(context, key, args, options);
}; };

View file

@ -6,14 +6,6 @@ export async function asyncForEach<T>(collection: T[], callback: (_item: T) => P
return await Promise.all(allPromises); return await Promise.all(allPromises);
} }
export function sortByKey<T>(array: T[], key: string) {
return array.sort(function (a, b) {
const x = a[key];
const y = b[key];
return x < y ? 1 : x > y ? -1 : 0;
});
}
export function shuffle<T>(pArray: T[]) { export function shuffle<T>(pArray: T[]) {
const array: T[] = []; const array: T[] = [];

View file

@ -1,3 +1,4 @@
import useClient from "@/utils/use-client.js";
import chalk from "chalk"; import chalk from "chalk";
function format(tDate: Date | number) { function format(tDate: Date | number) {
@ -34,6 +35,10 @@ export default {
}, },
debug(...content: unknown[]) { debug(...content: unknown[]) {
const client = useClient();
const isProd = client.configService.get("production");
console.log(isProd);
if (isProd) return;
return console.log(`[${format(Date.now())}]: ${logLevels.DEBUG} ${content.join(" ")}`); return console.log(`[${format(Date.now())}]: ${logLevels.DEBUG} ${content.join(" ")}`);
}, },

View file

@ -8,16 +8,18 @@ export const data: CronTaskData = {
task: async () => { task: async () => {
const client = useClient(); const client = useClient();
client.adapter.find(UserModel, { reminds: { $gt: [] } }).then(users => { const users = await client.adapter.find(UserModel, { reminds: { $gt: [] } });
for (const user of users) { for (const user of users) {
if (!client.users.cache.has(user.id)) client.users.fetch(user.id); if (!client.users.cache.has(user.id)) {
client.users.fetch(user.id);
}
client.cacheReminds.set(user.id, { client.cacheReminds.set(user.id, {
id: user.id, id: user.id,
reminds: user.reminds, reminds: user.reminds,
}); });
} }
});
client.cacheReminds.forEach(async ({ id, reminds }) => { client.cacheReminds.forEach(async ({ id, reminds }) => {
const cachedUser = client.users.cache.get(id); const cachedUser = client.users.cache.get(id);
@ -28,7 +30,7 @@ export const data: CronTaskData = {
if (!mustSent.length) return; if (!mustSent.length) return;
mustSent.forEach(r => { mustSent.forEach(async r => {
const embed = createEmbed({ const embed = createEmbed({
author: { author: {
name: client.translate("general/remindme:EMBED_TITLE"), name: client.translate("general/remindme:EMBED_TITLE"),
@ -51,12 +53,11 @@ export const data: CronTaskData = {
], ],
}); });
cachedUser await cachedUser.send({
.send({
embeds: [embed], embeds: [embed],
}) });
.then(() => {
client.adapter.updateOne( await client.adapter.updateOne(
UserModel, UserModel,
{ id }, { id },
{ {
@ -68,11 +69,14 @@ export const data: CronTaskData = {
}, },
); );
}); });
});
reminds = reminds.filter(r => r.sendAt >= Math.floor(Date.now() / 1000)); const updatedReminds = reminds.filter(r => r.sendAt >= Math.floor(Date.now() / 1000));
if (!reminds.length) client.cacheReminds.delete(id); if (!updatedReminds.length) {
client.cacheReminds.delete(id);
} else {
client.cacheReminds.set(id, { id, reminds: updatedReminds });
}
}); });
}, },
schedule: "* * * * * *", schedule: "* * * * * *",

View file

@ -1,9 +1,11 @@
import { ExtendedClient } from "./structures/client.js"; import { ExtendedClient } from "./structures/client.js";
import logger from "./helpers/logger.js"; import logger from "./helpers/logger.js";
import { CLIENT_INTENTS, CLIENT_ALLOWED_MENTIONS } from "./constants/index.js"; import { CLIENT_INTENTS, CLIENT_ALLOWED_MENTIONS } from "./constants/index.js";
import { Partials } from "discord.js";
const client = new ExtendedClient({ const client = new ExtendedClient({
intents: CLIENT_INTENTS, intents: CLIENT_INTENTS,
partials: [Partials.Channel],
allowedMentions: CLIENT_ALLOWED_MENTIONS, allowedMentions: CLIENT_ALLOWED_MENTIONS,
}); });
@ -12,7 +14,7 @@ client.init();
client client
.on("disconnect", () => logger.warn("Bot disconnected.")) .on("disconnect", () => logger.warn("Bot disconnected."))
.on("reconnecting", () => logger.warn("Bot reconnecting...")) .on("reconnecting", () => logger.warn("Bot reconnecting..."))
.on("warn", logger.log) .on("warn", logger.warn)
.on("error", logger.log); .on("error", logger.error);
process.on("unhandledRejection", logger.log).on("uncaughtException", logger.log); process.on("unhandledRejection", logger.error).on("uncaughtException", logger.error);

View file

@ -3,7 +3,7 @@ import { CONFIG_PATH } from "@/constants/index.js";
import logger from "@/helpers/logger.js"; import logger from "@/helpers/logger.js";
class ConfigService { class ConfigService {
config = this.loadConfig(); private config = this.loadConfig();
get<T>(key: string): T { get<T>(key: string): T {
const keys = key.split("."); const keys = key.split(".");

1
src/types.d.ts vendored
View file

@ -49,6 +49,7 @@ export interface CommandContext<_T extends Interaction, _Cached extends CacheTyp
export interface CommandOptions { export interface CommandOptions {
devOnly?: boolean; devOnly?: boolean;
cooldown?: number;
} }
export interface CommandFileObject { export interface CommandFileObject {