diff --git a/.env.example b/.env.example
index d2bedea..2fe2fcd 100644
--- a/.env.example
+++ b/.env.example
@@ -12,5 +12,14 @@ MOORE_CLIENT_ID=
# This is the test guild id
MOORE_GUILD_ID=
-# Set to production if you want to deploy command globally
-NODE_ENV=
\ No newline at end of file
+# Set to production if you are running in production
+NODE_ENV=
+
+# This was inserted by `prisma init`:
+# Environment variables declared in this file are automatically made available to Prisma.
+# See the documentation for more detail: https://pris.ly/d/prisma-schema#accessing-environment-variables-from-the-schema
+
+# Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB.
+# See the documentation for all the connection string options: https://pris.ly/d/connection-strings
+
+DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public"
\ No newline at end of file
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
new file mode 100644
index 0000000..f55fffc
--- /dev/null
+++ b/.idea/codeStyles/Project.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..79ee123
--- /dev/null
+++ b/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/prettier.xml b/.idea/prettier.xml
new file mode 100644
index 0000000..b0ab31a
--- /dev/null
+++ b/.idea/prettier.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/package.json b/package.json
index 12fdc4b..059699e 100644
--- a/package.json
+++ b/package.json
@@ -6,9 +6,11 @@
"type": "module",
"scripts": {
"start": "cd dist && node index",
+ "start:watch": "cd dist && nodemon --delay 1000ms index",
"format": "prettier -w .",
"lint": "eslint . --no-error-on-unmatched-pattern",
"build": "pnpm run build:files && pnpm run copy:dotfiles",
+ "dev": "conc --kill-others \"pnpm run build:watch\" \"pnpm run start:watch\"",
"build:files": "tsc -p .",
"build:watch": "tsc -p . --watch",
"copy:dotfiles": "cp .env dist"
@@ -24,11 +26,16 @@
"@types/node": "^18.11.3",
"@typescript-eslint/eslint-plugin": "^5.40.1",
"@typescript-eslint/parser": "^5.40.1",
+ "axios": "^1.1.3",
"discord-api-types": "^0.37.14",
"discord.js": "~14.6.0",
"discordx": "^11.4.0",
"dotenv": "^16.0.3",
"eslint": "8.22",
+ "prisma": "^4.5.0",
"typescript": "^4.8.4"
+ },
+ "devDependencies": {
+ "concurrently": "^7.5.0"
}
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index abee2c1..1fbbff8 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -8,11 +8,14 @@ specifiers:
'@types/node': ^18.11.3
'@typescript-eslint/eslint-plugin': ^5.40.1
'@typescript-eslint/parser': ^5.40.1
+ axios: ^1.1.3
+ concurrently: ^7.5.0
discord-api-types: ^0.37.14
discord.js: ~14.6.0
discordx: ^11.4.0
dotenv: ^16.0.3
eslint: '8.22'
+ prisma: ^4.5.0
typescript: ^4.8.4
dependencies:
@@ -23,13 +26,18 @@ dependencies:
'@types/node': 18.11.3
'@typescript-eslint/eslint-plugin': 5.40.1_7l7rruczv4daimtr3qpeu6yv5e
'@typescript-eslint/parser': 5.40.1_yv3nvntfnealqm77uomj2fi4ki
+ axios: 1.1.3
discord-api-types: 0.37.14
discord.js: 14.6.0
discordx: 11.4.0_discord.js@14.6.0
dotenv: 16.0.3
eslint: 8.22.0
+ prisma: 4.5.0
typescript: 4.8.4
+devDependencies:
+ concurrently: 7.5.0
+
packages:
/@discordjs/builders/1.3.0:
@@ -170,6 +178,11 @@ packages:
fastq: 1.13.0
dev: false
+ /@prisma/engines/4.5.0:
+ resolution: {integrity: sha512-4t9ir2SbQQr/wMCNU4YpHWp5hU14J2m3wHUZnGJPpmBF8YtkisxyVyQsKd1e6FyLTaGq8LOLhm6VLYHKqKNm+g==}
+ requiresBuild: true
+ dev: false
+
/@sapphire/async-queue/1.5.0:
resolution: {integrity: sha512-JkLdIsP8fPAdh9ZZjrbHWR/+mZj0wvKS5ICibcLrRI1j84UmLMshx5n9QmL8b95d4onJ2xxiyugTgSAX7AalmA==}
engines: {node: '>=v14.0.0', npm: '>=7.0.0'}
@@ -364,14 +377,12 @@ packages:
/ansi-regex/5.0.1:
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
engines: {node: '>=8'}
- dev: false
/ansi-styles/4.3.0:
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
engines: {node: '>=8'}
dependencies:
color-convert: 2.0.1
- dev: false
/argparse/2.0.1:
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
@@ -382,6 +393,20 @@ packages:
engines: {node: '>=8'}
dev: false
+ /asynckit/0.4.0:
+ resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
+ dev: false
+
+ /axios/1.1.3:
+ resolution: {integrity: sha512-00tXVRwKx/FZr/IDVFt4C+f9FYairX517WoGCL6dpOntqLkZofjhu43F/Xl44UOpqa+9sLFDrG/XAnFsUYgkDA==}
+ dependencies:
+ follow-redirects: 1.15.2
+ form-data: 4.0.0
+ proxy-from-env: 1.1.0
+ transitivePeerDependencies:
+ - debug
+ dev: false
+
/balanced-match/1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
dev: false
@@ -424,23 +449,52 @@ packages:
dependencies:
ansi-styles: 4.3.0
supports-color: 7.2.0
- dev: false
+
+ /cliui/8.0.1:
+ resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
+ engines: {node: '>=12'}
+ dependencies:
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+ wrap-ansi: 7.0.0
+ dev: true
/color-convert/2.0.1:
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
engines: {node: '>=7.0.0'}
dependencies:
color-name: 1.1.4
- dev: false
/color-name/1.1.4:
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
+
+ /combined-stream/1.0.8:
+ resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
+ engines: {node: '>= 0.8'}
+ dependencies:
+ delayed-stream: 1.0.0
dev: false
/concat-map/0.0.1:
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
dev: false
+ /concurrently/7.5.0:
+ resolution: {integrity: sha512-5E3mwiS+i2JYBzr5BpXkFxOnleZTMsG+WnE/dCG4/P+oiVXrbmrBwJ2ozn4SxwB2EZDrKR568X+puVohxz3/Mg==}
+ engines: {node: ^12.20.0 || ^14.13.0 || >=16.0.0}
+ hasBin: true
+ dependencies:
+ chalk: 4.1.2
+ date-fns: 2.29.3
+ lodash: 4.17.21
+ rxjs: 7.5.7
+ shell-quote: 1.7.4
+ spawn-command: 0.0.2-1
+ supports-color: 8.1.1
+ tree-kill: 1.2.2
+ yargs: 17.6.2
+ dev: true
+
/cross-spawn/7.0.3:
resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
engines: {node: '>= 8'}
@@ -450,6 +504,11 @@ packages:
which: 2.0.2
dev: false
+ /date-fns/2.29.3:
+ resolution: {integrity: sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==}
+ engines: {node: '>=0.11'}
+ dev: true
+
/debug/4.3.4:
resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
engines: {node: '>=6.0'}
@@ -466,6 +525,11 @@ packages:
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
dev: false
+ /delayed-stream/1.0.0:
+ resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
+ engines: {node: '>=0.4.0'}
+ dev: false
+
/dir-glob/3.0.1:
resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
engines: {node: '>=8'}
@@ -523,6 +587,15 @@ packages:
engines: {node: '>=12'}
dev: false
+ /emoji-regex/8.0.0:
+ resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
+ dev: true
+
+ /escalade/3.1.1:
+ resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==}
+ engines: {node: '>=6'}
+ dev: true
+
/escape-string-regexp/4.0.0:
resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
engines: {node: '>=10'}
@@ -722,6 +795,25 @@ packages:
resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==}
dev: false
+ /follow-redirects/1.15.2:
+ resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==}
+ engines: {node: '>=4.0'}
+ peerDependencies:
+ debug: '*'
+ peerDependenciesMeta:
+ debug:
+ optional: true
+ dev: false
+
+ /form-data/4.0.0:
+ resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
+ engines: {node: '>= 6'}
+ dependencies:
+ asynckit: 0.4.0
+ combined-stream: 1.0.8
+ mime-types: 2.1.35
+ dev: false
+
/fs.realpath/1.0.0:
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
dev: false
@@ -730,6 +822,11 @@ packages:
resolution: {integrity: sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==}
dev: false
+ /get-caller-file/2.0.5:
+ resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
+ engines: {node: 6.* || 8.* || >= 10.*}
+ dev: true
+
/glob-parent/5.1.2:
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
engines: {node: '>= 6'}
@@ -792,7 +889,6 @@ packages:
/has-flag/4.0.0:
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
engines: {node: '>=8'}
- dev: false
/ieee754/1.2.1:
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
@@ -832,6 +928,11 @@ packages:
engines: {node: '>=0.10.0'}
dev: false
+ /is-fullwidth-code-point/3.0.0:
+ resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
+ engines: {node: '>=8'}
+ dev: true
+
/is-glob/4.0.3:
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
engines: {node: '>=0.10.0'}
@@ -892,7 +993,6 @@ packages:
/lodash/4.17.21:
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
- dev: false
/lru-cache/6.0.0:
resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
@@ -914,6 +1014,18 @@ packages:
picomatch: 2.3.1
dev: false
+ /mime-db/1.52.0:
+ resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
+ engines: {node: '>= 0.6'}
+ dev: false
+
+ /mime-types/2.1.35:
+ resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
+ engines: {node: '>= 0.6'}
+ dependencies:
+ mime-db: 1.52.0
+ dev: false
+
/minimatch/3.1.2:
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
dependencies:
@@ -1009,6 +1121,19 @@ packages:
engines: {node: '>= 0.8.0'}
dev: false
+ /prisma/4.5.0:
+ resolution: {integrity: sha512-9Aeg4qiKlv9Wsjz4NO8k2CzRzlvS3A4FYVJ5+28sBBZ0eEwbiVOE/Jj7v6rZC1tFW2s4GSICQOAyuOjc6WsNew==}
+ engines: {node: '>=14.17'}
+ hasBin: true
+ requiresBuild: true
+ dependencies:
+ '@prisma/engines': 4.5.0
+ dev: false
+
+ /proxy-from-env/1.1.0:
+ resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
+ dev: false
+
/punycode/2.1.1:
resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==}
engines: {node: '>=6'}
@@ -1039,6 +1164,11 @@ packages:
engines: {node: '>=8'}
dev: false
+ /require-directory/2.1.1:
+ resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
/resolve-from/4.0.0:
resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
engines: {node: '>=4'}
@@ -1062,6 +1192,12 @@ packages:
queue-microtask: 1.2.3
dev: false
+ /rxjs/7.5.7:
+ resolution: {integrity: sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==}
+ dependencies:
+ tslib: 2.4.0
+ dev: true
+
/safe-buffer/5.2.1:
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
dev: false
@@ -1086,16 +1222,33 @@ packages:
engines: {node: '>=8'}
dev: false
+ /shell-quote/1.7.4:
+ resolution: {integrity: sha512-8o/QEhSSRb1a5i7TFR0iM4G16Z0vYB2OQVs4G3aAFXjn3T6yEx8AZxy1PgDF7I00LZHYA3WxaSYIf5e5sAX8Rw==}
+ dev: true
+
/slash/3.0.0:
resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
engines: {node: '>=8'}
dev: false
+ /spawn-command/0.0.2-1:
+ resolution: {integrity: sha512-n98l9E2RMSJ9ON1AKisHzz7V42VDiBQGY6PB1BwRglz99wpVsSuGzQ+jOi6lFXBGVTCrRpltvjm+/XA+tpeJrg==}
+ dev: true
+
/streamsearch/1.1.0:
resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==}
engines: {node: '>=10.0.0'}
dev: false
+ /string-width/4.2.3:
+ resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
+ engines: {node: '>=8'}
+ dependencies:
+ emoji-regex: 8.0.0
+ is-fullwidth-code-point: 3.0.0
+ strip-ansi: 6.0.1
+ dev: true
+
/string_decoder/1.3.0:
resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
dependencies:
@@ -1107,7 +1260,6 @@ packages:
engines: {node: '>=8'}
dependencies:
ansi-regex: 5.0.1
- dev: false
/strip-json-comments/3.1.1:
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
@@ -1127,7 +1279,13 @@ packages:
engines: {node: '>=8'}
dependencies:
has-flag: 4.0.0
- dev: false
+
+ /supports-color/8.1.1:
+ resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==}
+ engines: {node: '>=10'}
+ dependencies:
+ has-flag: 4.0.0
+ dev: true
/text-table/0.2.0:
resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
@@ -1148,6 +1306,11 @@ packages:
ieee754: 1.2.1
dev: false
+ /tree-kill/1.2.2:
+ resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==}
+ hasBin: true
+ dev: true
+
/ts-mixer/6.0.1:
resolution: {integrity: sha512-hvE+ZYXuINrx6Ei6D6hz+PTim0Uf++dYbK9FFifLNwQj+RwKquhQpn868yZsCtJYiclZF1u8l6WZxxKi+vv7Rg==}
dev: false
@@ -1158,7 +1321,6 @@ packages:
/tslib/2.4.0:
resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==}
- dev: false
/tsutils/3.21.0_typescript@4.8.4:
resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==}
@@ -1233,6 +1395,15 @@ packages:
engines: {node: '>=0.10.0'}
dev: false
+ /wrap-ansi/7.0.0:
+ resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
+ engines: {node: '>=10'}
+ dependencies:
+ ansi-styles: 4.3.0
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+ dev: true
+
/wrappy/1.0.2:
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
dev: false
@@ -1250,10 +1421,33 @@ packages:
optional: true
dev: false
+ /y18n/5.0.8:
+ resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
+ engines: {node: '>=10'}
+ dev: true
+
/yallist/4.0.0:
resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
dev: false
+ /yargs-parser/21.1.1:
+ resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
+ engines: {node: '>=12'}
+ dev: true
+
+ /yargs/17.6.2:
+ resolution: {integrity: sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==}
+ engines: {node: '>=12'}
+ dependencies:
+ cliui: 8.0.1
+ escalade: 3.1.1
+ get-caller-file: 2.0.5
+ require-directory: 2.1.1
+ string-width: 4.2.3
+ y18n: 5.0.8
+ yargs-parser: 21.1.1
+ dev: true
+
/yocto-queue/0.1.0:
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
engines: {node: '>=10'}
diff --git a/prisma/schema.prisma b/prisma/schema.prisma
new file mode 100644
index 0000000..d205f42
--- /dev/null
+++ b/prisma/schema.prisma
@@ -0,0 +1,11 @@
+// This is your Prisma schema file,
+// learn more about it in the docs: https://pris.ly/d/prisma-schema
+
+generator client {
+ provider = "prisma-client-js"
+}
+
+datasource db {
+ provider = "postgresql"
+ url = env("DATABASE_URL")
+}
diff --git a/src/commands/fun/deepfry.ts b/src/commands/fun/deepfry.ts
new file mode 100644
index 0000000..ce9ce9c
--- /dev/null
+++ b/src/commands/fun/deepfry.ts
@@ -0,0 +1,34 @@
+import type { CommandInteraction } from "discord.js";
+import { Discord, Slash, SlashOption } from "discordx";
+import { Category } from "@discordx/utilities";
+import axios from "axios";
+import { ApplicationCommandOptionType, User } from "discord.js";
+
+@Discord()
+@Category("Fun")
+export class DeepfryCommand {
+ @Slash({ description: "DEEP-FRY selected user", name: "deepfry" })
+ async deepfry(
+ @SlashOption({
+ description: "User to deep-fry",
+ name: "user",
+ type: ApplicationCommandOptionType.User,
+ required: true,
+ })
+ user: User,
+ interaction: CommandInteraction,
+ ): Promise {
+ await interaction.deferReply();
+ const avatar = user.displayAvatarURL({ size: 512 });
+ const { data } = await axios.get(`https://nekobot.xyz/api/imagegen?type=deepfry&image=${avatar}`);
+
+ await interaction.editReply({
+ files: [
+ {
+ attachment: data.message,
+ name: "deepfry.png",
+ },
+ ],
+ });
+ }
+}
diff --git a/src/commands/fun/magik.ts b/src/commands/fun/magik.ts
new file mode 100644
index 0000000..8028387
--- /dev/null
+++ b/src/commands/fun/magik.ts
@@ -0,0 +1,34 @@
+import type { CommandInteraction } from "discord.js";
+import { ApplicationCommandOptionType, User } from "discord.js";
+import { Discord, Slash, SlashOption } from "discordx";
+import { Category } from "@discordx/utilities";
+import axios from "axios";
+
+@Discord()
+@Category("Fun")
+export class MagikCommand {
+ @Slash({ description: "Somehow perform ritual to selected user", name: "magik" })
+ async magik(
+ @SlashOption({
+ description: "User to perform ritual on",
+ name: "user",
+ type: ApplicationCommandOptionType.User,
+ required: true,
+ })
+ user: User,
+ interaction: CommandInteraction,
+ ): Promise {
+ await interaction.deferReply();
+ const avatar = user.displayAvatarURL({ size: 512 });
+ const { data } = await axios.get(`https://nekobot.xyz/api/imagegen?type=magik&image=${avatar}&intensity=1`);
+
+ await interaction.editReply({
+ files: [
+ {
+ attachment: data.message,
+ name: "magik.png",
+ },
+ ],
+ });
+ }
+}
diff --git a/src/commands/fun/meme.ts b/src/commands/fun/meme.ts
new file mode 100644
index 0000000..9b92525
--- /dev/null
+++ b/src/commands/fun/meme.ts
@@ -0,0 +1,59 @@
+import type { CommandInteraction } from "discord.js";
+import {
+ ActionRowBuilder,
+ ButtonBuilder, ButtonInteraction,
+ ButtonStyle, Colors,
+ EmbedBuilder,
+} from "discord.js";
+import { ButtonComponent, Discord, Slash } from "discordx";
+import { Category } from "@discordx/utilities";
+import axios from "axios";
+
+@Discord()
+@Category("Fun")
+export class MemeCommand {
+ public static buttonRow = new ActionRowBuilder().addComponents(
+ new ButtonBuilder()
+ .setLabel("NEXT")
+ .setCustomId("next")
+ .setStyle(ButtonStyle.Primary),
+ );
+
+ public static async fetchMemes(): Promise {
+ const { data } = await axios.get("https://meme-api.herokuapp.com/gimme");
+ return data;
+ }
+
+ @ButtonComponent({ id: "next" })
+ async handler(interaction: ButtonInteraction): Promise {
+ await interaction.deferUpdate();
+ const data = await MemeCommand.fetchMemes();
+ await interaction.editReply({
+ embeds: [
+ new EmbedBuilder()
+ .setTitle(data.title)
+ .setImage(data.url)
+ .setURL(data.postLink)
+ .setColor(Colors.Green),
+ ],
+ components: [MemeCommand.buttonRow],
+ });
+ }
+
+ @Slash({ description: "Get random memes", name: "meme" })
+ async meme(
+ interaction: CommandInteraction,
+ ): Promise {
+ const data = await MemeCommand.fetchMemes();
+ await interaction.reply({
+ embeds: [
+ new EmbedBuilder()
+ .setTitle(data.title)
+ .setImage(data.url)
+ .setURL(data.postLink)
+ .setColor(Colors.Green),
+ ],
+ components: [MemeCommand.buttonRow],
+ });
+ }
+}
diff --git a/src/commands/misc/help.ts b/src/commands/misc/help.ts
index ce806d9..2003e96 100644
--- a/src/commands/misc/help.ts
+++ b/src/commands/misc/help.ts
@@ -1,9 +1,9 @@
-import { Discord, MetadataStorage, Slash, SlashGroup } from "discordx";
-import { EmbedBuilder, Colors, CommandInteraction } from "discord.js";
+import type { DApplicationCommand } from "discordx";
+import { Discord, MetadataStorage, Slash, SlashGroup, SlashOption } from "discordx";
+import { ApplicationCommandOptionType, Colors, CommandInteraction, EmbedBuilder } from "discord.js";
import { Category, ICategory } from "@discordx/utilities";
import { Pagination } from "@discordx/pagination";
import { bot } from "../../index.js";
-import type { DApplicationCommand } from "discordx";
@Discord()
@Category("Miscellaneous")
@@ -17,7 +17,11 @@ export class HelpCommand {
async all(interaction: CommandInteraction) {
const commands = MetadataStorage.instance.applicationCommandSlashesFlat.map(
(cmd: DApplicationCommand & ICategory) => {
- return { description: cmd.description, name: cmd.name, category: cmd.category };
+ return {
+ description: cmd.description,
+ name: cmd.group ? `${cmd.group} (${cmd.name})` : cmd.name,
+ category: cmd.category,
+ };
},
);
const categories = new Set(commands.map((c) => c.category));
@@ -41,4 +45,50 @@ export class HelpCommand {
const pagination = new Pagination(interaction, pages);
await pagination.send();
}
+
+ @Slash({ description: "Show info about a specific command" })
+ async command(
+ @SlashOption({
+ description: "Command to get info from",
+ name: "command",
+ type: ApplicationCommandOptionType.String,
+ required: true,
+ })
+ command: string,
+ interaction: CommandInteraction,
+ ): Promise {
+ const cmd = MetadataStorage.instance.applicationCommandSlashesFlat.find(
+ (c: DApplicationCommand & ICategory) => c.name === command,
+ ) as DApplicationCommand & ICategory;
+ if (!cmd) {
+ await interaction.reply({
+ content: `Command \`${command}\` not found.`,
+ ephemeral: true,
+ });
+ return;
+ }
+
+ const embed = new EmbedBuilder()
+ .setColor(Colors.Blue)
+ .setFooter({
+ text: "You can send `/help all` to get a list of all commands.",
+ iconURL: interaction.user.avatarURL()!,
+ })
+ .setThumbnail(bot.user!.displayAvatarURL())
+ .setTitle(cmd.name.toUpperCase())
+ .addFields({
+ name: "Description",
+ value: cmd.description,
+ })
+ .addFields({
+ name: "Category",
+ value: String(cmd.category),
+ })
+ .addFields({
+ name: "Options",
+ value: cmd.options?.map((o) => `\`${o.name}\` - ${o.description}`).join("\n") || "None",
+ });
+
+ await interaction.reply({ embeds: [embed] });
+ }
}
diff --git a/src/index.ts b/src/index.ts
index ce6fb3b..347ac24 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -5,10 +5,10 @@ import { ActivityType, GatewayIntentBits } from "discord-api-types/v10";
import { debuglog } from "util";
import type { Interaction } from "discord.js";
+export const botLog = debuglog("bot");
const NODE_ENV = process.env.NODE_ENV === "production";
const TOKEN = NODE_ENV ? process.env.MOORE_TOKEN : process.env.MOORE_DEV_TOKEN;
const CLIENT_ID = NODE_ENV ? process.env.MOORE_CLIENT_ID : process.env.MOORE_DEV_CLIENT_ID;
-const BOT_LOG = debuglog("bot");
export const bot = new Client({
botId: CLIENT_ID,
@@ -21,6 +21,14 @@ export const bot = new Client({
});
bot.once("ready", async () => {
+ // To clear all guild commands, uncomment this line,
+ // This is useful when moving from guild commands to global commands
+ // It must only be executed once
+ //
+ // await bot.clearApplicationCommands(
+ // ...bot.guilds.cache.map((g) => g.id)
+ // );
+
await bot.guilds.fetch();
await bot.initApplicationCommands();
@@ -28,7 +36,7 @@ bot.once("ready", async () => {
type: ActivityType.Watching,
});
- BOT_LOG("Logged in as %s", bot.user?.tag);
+ botLog("Logged in as %s", bot.user?.tag);
});
bot.on("interactionCreate", (interaction: Interaction) => {