├── .gitattributes ├── .gitignore ├── README.md ├── app.ts ├── package-lock.json ├── package.json └── src ├── commands ├── Command.ts ├── General │ └── CommandPing.ts └── index.ts ├── events └── ServerListener.ts └── utils └── logUtils.ts /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | .pnpm-debug.log* 9 | 10 | # Diagnostic reports (https://nodejs.org/api/report.html) 11 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 12 | 13 | # Runtime data 14 | pids 15 | *.pid 16 | *.seed 17 | *.pid.lock 18 | 19 | # Directory for instrumented libs generated by jscoverage/JSCover 20 | lib-cov 21 | 22 | # Coverage directory used by tools like istanbul 23 | coverage 24 | *.lcov 25 | 26 | # nyc test coverage 27 | .nyc_output 28 | 29 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 30 | .grunt 31 | 32 | # Bower dependency directory (https://bower.io/) 33 | bower_components 34 | 35 | # node-waf configuration 36 | .lock-wscript 37 | 38 | # Compiled binary addons (https://nodejs.org/api/addons.html) 39 | build/Release 40 | 41 | # Dependency directories 42 | node_modules/ 43 | jspm_packages/ 44 | 45 | # Snowpack dependency directory (https://snowpack.dev/) 46 | web_modules/ 47 | 48 | # TypeScript cache 49 | *.tsbuildinfo 50 | 51 | # Optional npm cache directory 52 | .npm 53 | 54 | # Optional eslint cache 55 | .eslintcache 56 | 57 | # Optional stylelint cache 58 | .stylelintcache 59 | 60 | # Microbundle cache 61 | .rpt2_cache/ 62 | .rts2_cache_cjs/ 63 | .rts2_cache_es/ 64 | .rts2_cache_umd/ 65 | 66 | # Optional REPL history 67 | .node_repl_history 68 | 69 | # Output of 'npm pack' 70 | *.tgz 71 | 72 | # Yarn Integrity file 73 | .yarn-integrity 74 | 75 | # dotenv environment variable files 76 | .env 77 | .env.development.local 78 | .env.test.local 79 | .env.production.local 80 | .env.local 81 | 82 | # parcel-bundler cache (https://parceljs.org/) 83 | .cache 84 | .parcel-cache 85 | 86 | # Next.js build output 87 | .next 88 | out 89 | 90 | # Nuxt.js build / generate output 91 | .nuxt 92 | dist 93 | 94 | # Gatsby files 95 | .cache/ 96 | # Comment in the public line in if your project uses Gatsby and not Next.js 97 | # https://nextjs.org/blog/next-9-1#public-directory-support 98 | # public 99 | 100 | # vuepress build output 101 | .vuepress/dist 102 | 103 | # vuepress v2.x temp and cache directory 104 | .temp 105 | .cache 106 | 107 | # Serverless directories 108 | .serverless/ 109 | 110 | # FuseBox cache 111 | .fusebox/ 112 | 113 | # DynamoDB Local files 114 | .dynamodb/ 115 | 116 | # TernJS port file 117 | .tern-port 118 | 119 | # Stores VSCode versions used for testing VSCode extensions 120 | .vscode-test 121 | 122 | # yarn v2 123 | .yarn/cache 124 | .yarn/unplugged 125 | .yarn/build-state.yml 126 | .yarn/install-state.gz 127 | .pnp.* 128 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Discord Bot Base 2 | 3 | To run this project, you will need to add the following environment variables to your .env file 4 | 5 | `TOKEN` = Your discord bot token\ 6 | `PREFIX` = Prefix that your bot will use to respond\ 7 | `MAIN_GUILD_ID` = Server ID that slash commands will be added to 8 | 9 | ### Exemplo de `.env` 10 | 11 | ```env 12 | TOKEN=TOKEN_AQUI 13 | PREFIX=! 14 | MAIN_GUILD_ID=778802467604791337 15 | ``` 16 | 17 | ### How to install and run 18 | 19 | CMD:\ 20 | `npm i -g typescript && npm i -g ts-node && npm install` 21 | 22 | POWERSHELL:\ 23 | `npm i -g typescript ; npm i -g ts-node ; npm install` 24 | -------------------------------------------------------------------------------- /app.ts: -------------------------------------------------------------------------------- 1 | import { ActivityType, BitFieldResolvable, ChannelType, Client, GatewayIntentsString, IntentsBitField, PermissionsBitField } from "discord.js"; 2 | import { BotCommands } from "./src/commands/index"; 3 | import 'dotenv/config' 4 | import { startLog } from "./src/utils/logUtils"; 5 | import { ServerListener } from "./src/events/ServerListener"; 6 | import fs from 'fs'; 7 | 8 | async function main() { 9 | const client = new Client({ 10 | intents: Object.keys(IntentsBitField.Flags) as BitFieldResolvable 11 | }); 12 | 13 | await client.login(process.env.TOKEN); 14 | 15 | const serverListener = new ServerListener(); 16 | const botCommands = new BotCommands(client); 17 | 18 | client.on("messageCreate", async (message) => { 19 | if (message && message.guildId && message.guild?.available === true) { 20 | if ( 21 | message.channel && 22 | message.channel.isTextBased() && 23 | !message.channel.isDMBased() 24 | ) { 25 | const permissions = message.channel.permissionsFor( 26 | client.user?.id || "" 27 | ); 28 | 29 | if ( 30 | !permissions || 31 | !permissions.has(PermissionsBitField.Flags.SendMessages) || 32 | !message.channel.viewable 33 | ) { 34 | return; 35 | } 36 | 37 | botCommands.onMessage( 38 | client, 39 | message.channel, 40 | message.member, 41 | message 42 | ); 43 | } 44 | } 45 | }); 46 | 47 | client.on("guildMemberRemove", (guildMember) => { 48 | if (guildMember.guild.available === true) { 49 | serverListener.guildMemberRemove(guildMember.client, guildMember); 50 | } 51 | }); 52 | 53 | client.on("guildMemberAdd", (guildMember) => { 54 | if (guildMember.guild.available === true) { 55 | serverListener.guildMemberAdd(guildMember.client, guildMember.guild, guildMember); 56 | } 57 | }); 58 | 59 | client.on("interactionCreate", (interaction) => { 60 | if (interaction && interaction.guild && interaction.guild.available === true) { 61 | botCommands.handleInteractionCommand(interaction); 62 | } 63 | }); 64 | 65 | client.on("ready", async () => { 66 | client.user?.setPresence({ activities: [{ name: `fxrst`, type: ActivityType.Listening }], status: 'idle' }); 67 | }) 68 | 69 | startLog(client.user?.tag || "", process.env.PREFIX || "!", botCommands._commands.size, botCommands._slashs.length); 70 | } 71 | 72 | process.on("uncaughtException", function (err: Error) { 73 | console.error(err); 74 | fs.appendFileSync("./errors.txt", err.stack + "\n\n", { encoding: 'utf8' }); 75 | }); 76 | 77 | main(); 78 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Bot Base", 3 | "lockfileVersion": 3, 4 | "requires": true, 5 | "packages": { 6 | "": { 7 | "dependencies": { 8 | "discord.js": "^14.14.1", 9 | "dotenv": "^16.4.1", 10 | "glob": "^10.3.10" 11 | }, 12 | "devDependencies": { 13 | "@types/node": "^20.11.7" 14 | } 15 | }, 16 | "node_modules/@discordjs/builders": { 17 | "version": "1.7.0", 18 | "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.7.0.tgz", 19 | "integrity": "sha512-GDtbKMkg433cOZur8Dv6c25EHxduNIBsxeHrsRoIM8+AwmEZ8r0tEpckx/sHwTLwQPOF3e2JWloZh9ofCaMfAw==", 20 | "dependencies": { 21 | "@discordjs/formatters": "^0.3.3", 22 | "@discordjs/util": "^1.0.2", 23 | "@sapphire/shapeshift": "^3.9.3", 24 | "discord-api-types": "0.37.61", 25 | "fast-deep-equal": "^3.1.3", 26 | "ts-mixer": "^6.0.3", 27 | "tslib": "^2.6.2" 28 | }, 29 | "engines": { 30 | "node": ">=16.11.0" 31 | } 32 | }, 33 | "node_modules/@discordjs/collection": { 34 | "version": "1.5.3", 35 | "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-1.5.3.tgz", 36 | "integrity": "sha512-SVb428OMd3WO1paV3rm6tSjM4wC+Kecaa1EUGX7vc6/fddvw/6lg90z4QtCqm21zvVe92vMMDt9+DkIvjXImQQ==", 37 | "engines": { 38 | "node": ">=16.11.0" 39 | } 40 | }, 41 | "node_modules/@discordjs/formatters": { 42 | "version": "0.3.3", 43 | "resolved": "https://registry.npmjs.org/@discordjs/formatters/-/formatters-0.3.3.tgz", 44 | "integrity": "sha512-wTcI1Q5cps1eSGhl6+6AzzZkBBlVrBdc9IUhJbijRgVjCNIIIZPgqnUj3ntFODsHrdbGU8BEG9XmDQmgEEYn3w==", 45 | "dependencies": { 46 | "discord-api-types": "0.37.61" 47 | }, 48 | "engines": { 49 | "node": ">=16.11.0" 50 | } 51 | }, 52 | "node_modules/@discordjs/rest": { 53 | "version": "2.2.0", 54 | "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-2.2.0.tgz", 55 | "integrity": "sha512-nXm9wT8oqrYFRMEqTXQx9DUTeEtXUDMmnUKIhZn6O2EeDY9VCdwj23XCPq7fkqMPKdF7ldAfeVKyxxFdbZl59A==", 56 | "dependencies": { 57 | "@discordjs/collection": "^2.0.0", 58 | "@discordjs/util": "^1.0.2", 59 | "@sapphire/async-queue": "^1.5.0", 60 | "@sapphire/snowflake": "^3.5.1", 61 | "@vladfrangu/async_event_emitter": "^2.2.2", 62 | "discord-api-types": "0.37.61", 63 | "magic-bytes.js": "^1.5.0", 64 | "tslib": "^2.6.2", 65 | "undici": "5.27.2" 66 | }, 67 | "engines": { 68 | "node": ">=16.11.0" 69 | } 70 | }, 71 | "node_modules/@discordjs/rest/node_modules/@discordjs/collection": { 72 | "version": "2.0.0", 73 | "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-2.0.0.tgz", 74 | "integrity": "sha512-YTWIXLrf5FsrLMycpMM9Q6vnZoR/lN2AWX23/Cuo8uOOtS8eHB2dyQaaGnaF8aZPYnttf2bkLMcXn/j6JUOi3w==", 75 | "engines": { 76 | "node": ">=18" 77 | } 78 | }, 79 | "node_modules/@discordjs/util": { 80 | "version": "1.0.2", 81 | "resolved": "https://registry.npmjs.org/@discordjs/util/-/util-1.0.2.tgz", 82 | "integrity": "sha512-IRNbimrmfb75GMNEjyznqM1tkI7HrZOf14njX7tCAAUetyZM1Pr8hX/EK2lxBCOgWDRmigbp24fD1hdMfQK5lw==", 83 | "engines": { 84 | "node": ">=16.11.0" 85 | } 86 | }, 87 | "node_modules/@discordjs/ws": { 88 | "version": "1.0.2", 89 | "resolved": "https://registry.npmjs.org/@discordjs/ws/-/ws-1.0.2.tgz", 90 | "integrity": "sha512-+XI82Rm2hKnFwAySXEep4A7Kfoowt6weO6381jgW+wVdTpMS/56qCvoXyFRY0slcv7c/U8My2PwIB2/wEaAh7Q==", 91 | "dependencies": { 92 | "@discordjs/collection": "^2.0.0", 93 | "@discordjs/rest": "^2.1.0", 94 | "@discordjs/util": "^1.0.2", 95 | "@sapphire/async-queue": "^1.5.0", 96 | "@types/ws": "^8.5.9", 97 | "@vladfrangu/async_event_emitter": "^2.2.2", 98 | "discord-api-types": "0.37.61", 99 | "tslib": "^2.6.2", 100 | "ws": "^8.14.2" 101 | }, 102 | "engines": { 103 | "node": ">=16.11.0" 104 | } 105 | }, 106 | "node_modules/@discordjs/ws/node_modules/@discordjs/collection": { 107 | "version": "2.0.0", 108 | "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-2.0.0.tgz", 109 | "integrity": "sha512-YTWIXLrf5FsrLMycpMM9Q6vnZoR/lN2AWX23/Cuo8uOOtS8eHB2dyQaaGnaF8aZPYnttf2bkLMcXn/j6JUOi3w==", 110 | "engines": { 111 | "node": ">=18" 112 | } 113 | }, 114 | "node_modules/@fastify/busboy": { 115 | "version": "2.1.0", 116 | "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.0.tgz", 117 | "integrity": "sha512-+KpH+QxZU7O4675t3mnkQKcZZg56u+K/Ct2K+N2AZYNVK8kyeo/bI18tI8aPm3tvNNRyTWfj6s5tnGNlcbQRsA==", 118 | "engines": { 119 | "node": ">=14" 120 | } 121 | }, 122 | "node_modules/@isaacs/cliui": { 123 | "version": "8.0.2", 124 | "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", 125 | "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", 126 | "dependencies": { 127 | "string-width": "^5.1.2", 128 | "string-width-cjs": "npm:string-width@^4.2.0", 129 | "strip-ansi": "^7.0.1", 130 | "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", 131 | "wrap-ansi": "^8.1.0", 132 | "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" 133 | }, 134 | "engines": { 135 | "node": ">=12" 136 | } 137 | }, 138 | "node_modules/@pkgjs/parseargs": { 139 | "version": "0.11.0", 140 | "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", 141 | "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", 142 | "optional": true, 143 | "engines": { 144 | "node": ">=14" 145 | } 146 | }, 147 | "node_modules/@sapphire/async-queue": { 148 | "version": "1.5.2", 149 | "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.5.2.tgz", 150 | "integrity": "sha512-7X7FFAA4DngXUl95+hYbUF19bp1LGiffjJtu7ygrZrbdCSsdDDBaSjB7Akw0ZbOu6k0xpXyljnJ6/RZUvLfRdg==", 151 | "engines": { 152 | "node": ">=v14.0.0", 153 | "npm": ">=7.0.0" 154 | } 155 | }, 156 | "node_modules/@sapphire/shapeshift": { 157 | "version": "3.9.6", 158 | "resolved": "https://registry.npmjs.org/@sapphire/shapeshift/-/shapeshift-3.9.6.tgz", 159 | "integrity": "sha512-4+Na/fxu2SEepZRb9z0dbsVh59QtwPuBg/UVaDib3av7ZY14b14+z09z6QVn0P6Dv6eOU2NDTsjIi0mbtgP56g==", 160 | "dependencies": { 161 | "fast-deep-equal": "^3.1.3", 162 | "lodash": "^4.17.21" 163 | }, 164 | "engines": { 165 | "node": ">=v18" 166 | } 167 | }, 168 | "node_modules/@sapphire/snowflake": { 169 | "version": "3.5.1", 170 | "resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.5.1.tgz", 171 | "integrity": "sha512-BxcYGzgEsdlG0dKAyOm0ehLGm2CafIrfQTZGWgkfKYbj+pNNsorZ7EotuZukc2MT70E0UbppVbtpBrqpzVzjNA==", 172 | "engines": { 173 | "node": ">=v14.0.0", 174 | "npm": ">=7.0.0" 175 | } 176 | }, 177 | "node_modules/@types/node": { 178 | "version": "20.11.7", 179 | "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.7.tgz", 180 | "integrity": "sha512-GPmeN1C3XAyV5uybAf4cMLWT9fDWcmQhZVtMFu7OR32WjrqGG+Wnk2V1d0bmtUyE/Zy1QJ9BxyiTih9z8Oks8A==", 181 | "dependencies": { 182 | "undici-types": "~5.26.4" 183 | } 184 | }, 185 | "node_modules/@types/ws": { 186 | "version": "8.5.9", 187 | "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.9.tgz", 188 | "integrity": "sha512-jbdrY0a8lxfdTp/+r7Z4CkycbOFN8WX+IOchLJr3juT/xzbJ8URyTVSJ/hvNdadTgM1mnedb47n+Y31GsFnQlg==", 189 | "dependencies": { 190 | "@types/node": "*" 191 | } 192 | }, 193 | "node_modules/@vladfrangu/async_event_emitter": { 194 | "version": "2.2.4", 195 | "resolved": "https://registry.npmjs.org/@vladfrangu/async_event_emitter/-/async_event_emitter-2.2.4.tgz", 196 | "integrity": "sha512-ButUPz9E9cXMLgvAW8aLAKKJJsPu1dY1/l/E8xzLFuysowXygs6GBcyunK9rnGC4zTsnIc2mQo71rGw9U+Ykug==", 197 | "engines": { 198 | "node": ">=v14.0.0", 199 | "npm": ">=7.0.0" 200 | } 201 | }, 202 | "node_modules/ansi-regex": { 203 | "version": "6.0.1", 204 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", 205 | "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", 206 | "engines": { 207 | "node": ">=12" 208 | }, 209 | "funding": { 210 | "url": "https://github.com/chalk/ansi-regex?sponsor=1" 211 | } 212 | }, 213 | "node_modules/ansi-styles": { 214 | "version": "6.2.1", 215 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", 216 | "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", 217 | "engines": { 218 | "node": ">=12" 219 | }, 220 | "funding": { 221 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 222 | } 223 | }, 224 | "node_modules/balanced-match": { 225 | "version": "1.0.2", 226 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 227 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" 228 | }, 229 | "node_modules/brace-expansion": { 230 | "version": "2.0.1", 231 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", 232 | "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", 233 | "dependencies": { 234 | "balanced-match": "^1.0.0" 235 | } 236 | }, 237 | "node_modules/color-convert": { 238 | "version": "2.0.1", 239 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 240 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 241 | "dependencies": { 242 | "color-name": "~1.1.4" 243 | }, 244 | "engines": { 245 | "node": ">=7.0.0" 246 | } 247 | }, 248 | "node_modules/color-name": { 249 | "version": "1.1.4", 250 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 251 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" 252 | }, 253 | "node_modules/cross-spawn": { 254 | "version": "7.0.3", 255 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", 256 | "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", 257 | "dependencies": { 258 | "path-key": "^3.1.0", 259 | "shebang-command": "^2.0.0", 260 | "which": "^2.0.1" 261 | }, 262 | "engines": { 263 | "node": ">= 8" 264 | } 265 | }, 266 | "node_modules/discord-api-types": { 267 | "version": "0.37.61", 268 | "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.61.tgz", 269 | "integrity": "sha512-o/dXNFfhBpYHpQFdT6FWzeO7pKc838QeeZ9d91CfVAtpr5XLK4B/zYxQbYgPdoMiTDvJfzcsLW5naXgmHGDNXw==" 270 | }, 271 | "node_modules/discord.js": { 272 | "version": "14.14.1", 273 | "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.14.1.tgz", 274 | "integrity": "sha512-/hUVzkIerxKHyRKopJy5xejp4MYKDPTszAnpYxzVVv4qJYf+Tkt+jnT2N29PIPschicaEEpXwF2ARrTYHYwQ5w==", 275 | "dependencies": { 276 | "@discordjs/builders": "^1.7.0", 277 | "@discordjs/collection": "1.5.3", 278 | "@discordjs/formatters": "^0.3.3", 279 | "@discordjs/rest": "^2.1.0", 280 | "@discordjs/util": "^1.0.2", 281 | "@discordjs/ws": "^1.0.2", 282 | "@sapphire/snowflake": "3.5.1", 283 | "@types/ws": "8.5.9", 284 | "discord-api-types": "0.37.61", 285 | "fast-deep-equal": "3.1.3", 286 | "lodash.snakecase": "4.1.1", 287 | "tslib": "2.6.2", 288 | "undici": "5.27.2", 289 | "ws": "8.14.2" 290 | }, 291 | "engines": { 292 | "node": ">=16.11.0" 293 | } 294 | }, 295 | "node_modules/dotenv": { 296 | "version": "16.4.1", 297 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.1.tgz", 298 | "integrity": "sha512-CjA3y+Dr3FyFDOAMnxZEGtnW9KBR2M0JvvUtXNW+dYJL5ROWxP9DUHCwgFqpMk0OXCc0ljhaNTr2w/kutYIcHQ==", 299 | "engines": { 300 | "node": ">=12" 301 | }, 302 | "funding": { 303 | "url": "https://github.com/motdotla/dotenv?sponsor=1" 304 | } 305 | }, 306 | "node_modules/eastasianwidth": { 307 | "version": "0.2.0", 308 | "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", 309 | "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" 310 | }, 311 | "node_modules/emoji-regex": { 312 | "version": "9.2.2", 313 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", 314 | "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" 315 | }, 316 | "node_modules/fast-deep-equal": { 317 | "version": "3.1.3", 318 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 319 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" 320 | }, 321 | "node_modules/foreground-child": { 322 | "version": "3.1.1", 323 | "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", 324 | "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", 325 | "dependencies": { 326 | "cross-spawn": "^7.0.0", 327 | "signal-exit": "^4.0.1" 328 | }, 329 | "engines": { 330 | "node": ">=14" 331 | }, 332 | "funding": { 333 | "url": "https://github.com/sponsors/isaacs" 334 | } 335 | }, 336 | "node_modules/glob": { 337 | "version": "10.3.10", 338 | "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", 339 | "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", 340 | "dependencies": { 341 | "foreground-child": "^3.1.0", 342 | "jackspeak": "^2.3.5", 343 | "minimatch": "^9.0.1", 344 | "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", 345 | "path-scurry": "^1.10.1" 346 | }, 347 | "bin": { 348 | "glob": "dist/esm/bin.mjs" 349 | }, 350 | "engines": { 351 | "node": ">=16 || 14 >=14.17" 352 | }, 353 | "funding": { 354 | "url": "https://github.com/sponsors/isaacs" 355 | } 356 | }, 357 | "node_modules/is-fullwidth-code-point": { 358 | "version": "3.0.0", 359 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 360 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 361 | "engines": { 362 | "node": ">=8" 363 | } 364 | }, 365 | "node_modules/isexe": { 366 | "version": "2.0.0", 367 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 368 | "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" 369 | }, 370 | "node_modules/jackspeak": { 371 | "version": "2.3.6", 372 | "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", 373 | "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", 374 | "dependencies": { 375 | "@isaacs/cliui": "^8.0.2" 376 | }, 377 | "engines": { 378 | "node": ">=14" 379 | }, 380 | "funding": { 381 | "url": "https://github.com/sponsors/isaacs" 382 | }, 383 | "optionalDependencies": { 384 | "@pkgjs/parseargs": "^0.11.0" 385 | } 386 | }, 387 | "node_modules/lodash": { 388 | "version": "4.17.21", 389 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 390 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" 391 | }, 392 | "node_modules/lodash.snakecase": { 393 | "version": "4.1.1", 394 | "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", 395 | "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==" 396 | }, 397 | "node_modules/lru-cache": { 398 | "version": "10.2.0", 399 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", 400 | "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", 401 | "engines": { 402 | "node": "14 || >=16.14" 403 | } 404 | }, 405 | "node_modules/magic-bytes.js": { 406 | "version": "1.8.0", 407 | "resolved": "https://registry.npmjs.org/magic-bytes.js/-/magic-bytes.js-1.8.0.tgz", 408 | "integrity": "sha512-lyWpfvNGVb5lu8YUAbER0+UMBTdR63w2mcSUlhhBTyVbxJvjgqwyAf3AZD6MprgK0uHuBoWXSDAMWLupX83o3Q==" 409 | }, 410 | "node_modules/minimatch": { 411 | "version": "9.0.3", 412 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", 413 | "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", 414 | "dependencies": { 415 | "brace-expansion": "^2.0.1" 416 | }, 417 | "engines": { 418 | "node": ">=16 || 14 >=14.17" 419 | }, 420 | "funding": { 421 | "url": "https://github.com/sponsors/isaacs" 422 | } 423 | }, 424 | "node_modules/minipass": { 425 | "version": "7.0.4", 426 | "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", 427 | "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", 428 | "engines": { 429 | "node": ">=16 || 14 >=14.17" 430 | } 431 | }, 432 | "node_modules/path-key": { 433 | "version": "3.1.1", 434 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", 435 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", 436 | "engines": { 437 | "node": ">=8" 438 | } 439 | }, 440 | "node_modules/path-scurry": { 441 | "version": "1.10.1", 442 | "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", 443 | "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", 444 | "dependencies": { 445 | "lru-cache": "^9.1.1 || ^10.0.0", 446 | "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" 447 | }, 448 | "engines": { 449 | "node": ">=16 || 14 >=14.17" 450 | }, 451 | "funding": { 452 | "url": "https://github.com/sponsors/isaacs" 453 | } 454 | }, 455 | "node_modules/shebang-command": { 456 | "version": "2.0.0", 457 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 458 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 459 | "dependencies": { 460 | "shebang-regex": "^3.0.0" 461 | }, 462 | "engines": { 463 | "node": ">=8" 464 | } 465 | }, 466 | "node_modules/shebang-regex": { 467 | "version": "3.0.0", 468 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", 469 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", 470 | "engines": { 471 | "node": ">=8" 472 | } 473 | }, 474 | "node_modules/signal-exit": { 475 | "version": "4.1.0", 476 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", 477 | "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", 478 | "engines": { 479 | "node": ">=14" 480 | }, 481 | "funding": { 482 | "url": "https://github.com/sponsors/isaacs" 483 | } 484 | }, 485 | "node_modules/string-width": { 486 | "version": "5.1.2", 487 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", 488 | "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", 489 | "dependencies": { 490 | "eastasianwidth": "^0.2.0", 491 | "emoji-regex": "^9.2.2", 492 | "strip-ansi": "^7.0.1" 493 | }, 494 | "engines": { 495 | "node": ">=12" 496 | }, 497 | "funding": { 498 | "url": "https://github.com/sponsors/sindresorhus" 499 | } 500 | }, 501 | "node_modules/string-width-cjs": { 502 | "name": "string-width", 503 | "version": "4.2.3", 504 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 505 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 506 | "dependencies": { 507 | "emoji-regex": "^8.0.0", 508 | "is-fullwidth-code-point": "^3.0.0", 509 | "strip-ansi": "^6.0.1" 510 | }, 511 | "engines": { 512 | "node": ">=8" 513 | } 514 | }, 515 | "node_modules/string-width-cjs/node_modules/ansi-regex": { 516 | "version": "5.0.1", 517 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 518 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 519 | "engines": { 520 | "node": ">=8" 521 | } 522 | }, 523 | "node_modules/string-width-cjs/node_modules/emoji-regex": { 524 | "version": "8.0.0", 525 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 526 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" 527 | }, 528 | "node_modules/string-width-cjs/node_modules/strip-ansi": { 529 | "version": "6.0.1", 530 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 531 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 532 | "dependencies": { 533 | "ansi-regex": "^5.0.1" 534 | }, 535 | "engines": { 536 | "node": ">=8" 537 | } 538 | }, 539 | "node_modules/strip-ansi": { 540 | "version": "7.1.0", 541 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", 542 | "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", 543 | "dependencies": { 544 | "ansi-regex": "^6.0.1" 545 | }, 546 | "engines": { 547 | "node": ">=12" 548 | }, 549 | "funding": { 550 | "url": "https://github.com/chalk/strip-ansi?sponsor=1" 551 | } 552 | }, 553 | "node_modules/strip-ansi-cjs": { 554 | "name": "strip-ansi", 555 | "version": "6.0.1", 556 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 557 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 558 | "dependencies": { 559 | "ansi-regex": "^5.0.1" 560 | }, 561 | "engines": { 562 | "node": ">=8" 563 | } 564 | }, 565 | "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { 566 | "version": "5.0.1", 567 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 568 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 569 | "engines": { 570 | "node": ">=8" 571 | } 572 | }, 573 | "node_modules/ts-mixer": { 574 | "version": "6.0.3", 575 | "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.3.tgz", 576 | "integrity": "sha512-k43M7uCG1AkTyxgnmI5MPwKoUvS/bRvLvUb7+Pgpdlmok8AoqmUaZxUUw8zKM5B1lqZrt41GjYgnvAi0fppqgQ==" 577 | }, 578 | "node_modules/tslib": { 579 | "version": "2.6.2", 580 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", 581 | "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" 582 | }, 583 | "node_modules/undici": { 584 | "version": "5.27.2", 585 | "resolved": "https://registry.npmjs.org/undici/-/undici-5.27.2.tgz", 586 | "integrity": "sha512-iS857PdOEy/y3wlM3yRp+6SNQQ6xU0mmZcwRSriqk+et/cwWAtwmIGf6WkoDN2EK/AMdCO/dfXzIwi+rFMrjjQ==", 587 | "dependencies": { 588 | "@fastify/busboy": "^2.0.0" 589 | }, 590 | "engines": { 591 | "node": ">=14.0" 592 | } 593 | }, 594 | "node_modules/undici-types": { 595 | "version": "5.26.5", 596 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", 597 | "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" 598 | }, 599 | "node_modules/which": { 600 | "version": "2.0.2", 601 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 602 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 603 | "dependencies": { 604 | "isexe": "^2.0.0" 605 | }, 606 | "bin": { 607 | "node-which": "bin/node-which" 608 | }, 609 | "engines": { 610 | "node": ">= 8" 611 | } 612 | }, 613 | "node_modules/wrap-ansi": { 614 | "version": "8.1.0", 615 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", 616 | "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", 617 | "dependencies": { 618 | "ansi-styles": "^6.1.0", 619 | "string-width": "^5.0.1", 620 | "strip-ansi": "^7.0.1" 621 | }, 622 | "engines": { 623 | "node": ">=12" 624 | }, 625 | "funding": { 626 | "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 627 | } 628 | }, 629 | "node_modules/wrap-ansi-cjs": { 630 | "name": "wrap-ansi", 631 | "version": "7.0.0", 632 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 633 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 634 | "dependencies": { 635 | "ansi-styles": "^4.0.0", 636 | "string-width": "^4.1.0", 637 | "strip-ansi": "^6.0.0" 638 | }, 639 | "engines": { 640 | "node": ">=10" 641 | }, 642 | "funding": { 643 | "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 644 | } 645 | }, 646 | "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { 647 | "version": "5.0.1", 648 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 649 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 650 | "engines": { 651 | "node": ">=8" 652 | } 653 | }, 654 | "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { 655 | "version": "4.3.0", 656 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 657 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 658 | "dependencies": { 659 | "color-convert": "^2.0.1" 660 | }, 661 | "engines": { 662 | "node": ">=8" 663 | }, 664 | "funding": { 665 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 666 | } 667 | }, 668 | "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { 669 | "version": "8.0.0", 670 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 671 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" 672 | }, 673 | "node_modules/wrap-ansi-cjs/node_modules/string-width": { 674 | "version": "4.2.3", 675 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 676 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 677 | "dependencies": { 678 | "emoji-regex": "^8.0.0", 679 | "is-fullwidth-code-point": "^3.0.0", 680 | "strip-ansi": "^6.0.1" 681 | }, 682 | "engines": { 683 | "node": ">=8" 684 | } 685 | }, 686 | "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { 687 | "version": "6.0.1", 688 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 689 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 690 | "dependencies": { 691 | "ansi-regex": "^5.0.1" 692 | }, 693 | "engines": { 694 | "node": ">=8" 695 | } 696 | }, 697 | "node_modules/ws": { 698 | "version": "8.14.2", 699 | "resolved": "https://registry.npmjs.org/ws/-/ws-8.14.2.tgz", 700 | "integrity": "sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==", 701 | "engines": { 702 | "node": ">=10.0.0" 703 | }, 704 | "peerDependencies": { 705 | "bufferutil": "^4.0.1", 706 | "utf-8-validate": ">=5.0.2" 707 | }, 708 | "peerDependenciesMeta": { 709 | "bufferutil": { 710 | "optional": true 711 | }, 712 | "utf-8-validate": { 713 | "optional": true 714 | } 715 | } 716 | } 717 | } 718 | } 719 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "devDependencies": { 3 | "@types/node": "^20.11.7" 4 | }, 5 | "dependencies": { 6 | "discord.js": "^14.14.1", 7 | "dotenv": "^16.4.1", 8 | "glob": "^10.3.10" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/commands/Command.ts: -------------------------------------------------------------------------------- 1 | import {ApplicationCommandOption, Client, CommandInteraction, Guild, GuildTextBasedChannel, User } from 'discord.js'; 2 | 3 | export abstract class Command { 4 | name: string; 5 | name_localizations: any; 6 | description: string; 7 | user_permissions: bigint[]; 8 | user_bot_permissions: string[]; 9 | bot_permissions: bigint[]; 10 | cooldownToUse: number; 11 | cooldownType: string; 12 | enabled: boolean; 13 | slash: boolean; 14 | description_localizations: any; 15 | options: ApplicationCommandOption[]; 16 | aliases: string[]; 17 | 18 | constructor( 19 | name: string, 20 | name_localizations: any, 21 | description: string, 22 | user_permissions: bigint[], 23 | user_bot_permissions: string[], 24 | bot_permissions: bigint[], 25 | aliases: string[], 26 | ) { 27 | this.name = name; 28 | this.name_localizations = name_localizations; 29 | this.description = description; 30 | this.user_permissions = user_permissions; 31 | this.user_bot_permissions = user_bot_permissions; 32 | this.bot_permissions = bot_permissions; 33 | this.cooldownToUse = 0; 34 | this.cooldownType = 'global'; 35 | this.enabled = true; 36 | this.slash = true; 37 | this.description_localizations = {}; 38 | this.options = []; 39 | this.aliases = aliases; 40 | } 41 | 42 | abstract execute(client: Client, guild: Guild | null, user: User, channel: GuildTextBasedChannel | null, data: CommandInteraction | string[]): Promise | void; 43 | } -------------------------------------------------------------------------------- /src/commands/General/CommandPing.ts: -------------------------------------------------------------------------------- 1 | import { Client, CommandInteraction, Guild, GuildTextBasedChannel, PermissionsBitField, User } from 'discord.js'; 2 | import { Command } from "../Command"; 3 | export class Cmd extends Command { 4 | 5 | constructor() { 6 | super("ping", { "pt-BR": "ping" }, "Get 'pong' response.", [PermissionsBitField.Flags.SendMessages], [/*user_bot_permissions*/], [PermissionsBitField.Flags.SendMessages], ["p"]); 7 | this.options = []; 8 | this.enabled = true; 9 | this.description_localizations = { "pt-BR": "Receba 'pong' como resposta." } 10 | } 11 | 12 | async execute(client: Client, guild: Guild, user: User, channel: GuildTextBasedChannel, data: CommandInteraction | string[]) { 13 | 14 | const isSlash = data instanceof CommandInteraction; 15 | 16 | if (isSlash) { 17 | data.reply({ content: 'pong', ephemeral: true }); 18 | return; 19 | } 20 | 21 | channel.send({ content: 'pong' }); 22 | } 23 | } -------------------------------------------------------------------------------- /src/commands/index.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ApplicationCommandOption, 3 | ApplicationCommandType, 4 | Channel, 5 | Client, 6 | Collection, 7 | CommandInteraction, 8 | Guild, 9 | GuildMember, 10 | GuildTextBasedChannel, 11 | Interaction, 12 | Message, 13 | REST, 14 | Routes, 15 | Snowflake, 16 | User, 17 | } from "discord.js"; 18 | import * as glob from "glob"; 19 | import * as path from "path"; 20 | import { Command } from "./Command"; 21 | import "dotenv/config"; 22 | 23 | const rest = new REST().setToken(process.env.TOKEN || ""); 24 | 25 | type SlashCommand = { 26 | id?: Snowflake; 27 | type?: ApplicationCommandType; 28 | application_id: Snowflake; 29 | guild_id?: Snowflake; 30 | name: string; 31 | name_localizations?: any; 32 | description: string; 33 | description_localizations?: any; 34 | options: ApplicationCommandOption[]; 35 | default_member_permissions?: string; 36 | dm_permission?: boolean; 37 | default_permission?: boolean; 38 | nsfw?: boolean; 39 | version?: Snowflake; 40 | }; 41 | 42 | export class BotCommands { 43 | private readonly _client: Client; 44 | _commands: Collection; 45 | _slashs: SlashCommand[]; 46 | 47 | constructor(client: Client) { 48 | this._commands = new Collection(); 49 | this._client = client; 50 | this._slashs = []; 51 | this.loadCommands(); 52 | } 53 | 54 | async handleInteractionCommand(interaction: Interaction) { 55 | if (!interaction.isCommand()) { 56 | return; 57 | } 58 | 59 | if (interaction.guildId) { 60 | if ( 61 | interaction.channel && 62 | interaction.channel.isTextBased() && 63 | !interaction.channel.isDMBased() 64 | ) { 65 | this.handleCommand( 66 | interaction.client, 67 | interaction.guild, 68 | interaction.user, 69 | interaction.channel, 70 | interaction.commandName, 71 | interaction 72 | ); 73 | } 74 | } 75 | } 76 | 77 | loadCommands() { 78 | const commandFiles = glob.sync("**/*.ts", { 79 | cwd: path.join(__dirname, ""), 80 | }); 81 | 82 | for (const file of commandFiles) { 83 | if (file == "Command.ts" || file == "index.ts") continue; 84 | const { Cmd } = require(path.join(__dirname, file)); 85 | if (typeof Cmd == "function") { 86 | const command: Command = new Cmd(); 87 | if (command.enabled === true) { 88 | this._commands.set(command.name, command); 89 | if (command.slash) { 90 | this._slashs.push({ 91 | name: command.name, 92 | name_localizations: command.name_localizations, 93 | description_localizations: command.description_localizations, 94 | application_id: this._client.user?.id || "", 95 | guild_id: process.env.MAIN_GUILD_ID || "", 96 | description: command.description, 97 | options: command.options, 98 | }); 99 | } 100 | } 101 | } 102 | } 103 | 104 | rest.put( 105 | Routes.applicationGuildCommands( 106 | this._client.user?.id || "", 107 | process.env.MAIN_GUILD_ID || "" 108 | ), 109 | { body: this._slashs } 110 | ); 111 | } 112 | 113 | handleCommand( 114 | client: Client, 115 | guild: Guild | null, 116 | user: User, 117 | channel: GuildTextBasedChannel | null, 118 | commandName: string, 119 | data: string[] | CommandInteraction 120 | ) { 121 | let command = this._commands.get(commandName); 122 | 123 | if (!command) { 124 | this._commands.forEach((cmd) => { 125 | if (cmd.aliases && cmd.aliases.includes(commandName)) { 126 | command = cmd; 127 | } 128 | }); 129 | } 130 | 131 | if (!command) { 132 | return; 133 | } 134 | 135 | if (channel && !channel.isDMBased() && channel.isTextBased()) { 136 | const permissionsBot = channel.permissionsFor(client.user?.id || ""); 137 | if (!permissionsBot || !channel.viewable) { 138 | return; 139 | } 140 | if ( 141 | Array.isArray(command.bot_permissions) && 142 | command.bot_permissions.length > 0 143 | ) { 144 | for (const permission of command.bot_permissions) { 145 | if (!permissionsBot.has(permission)) { 146 | // Missing "permission" to execute command (BOT) 147 | return; 148 | } 149 | } 150 | } 151 | 152 | // Permissions for who Executed 153 | const permissionsUser = channel.permissionsFor(user.id); 154 | if (!permissionsUser) { 155 | return; 156 | } 157 | if ( 158 | Array.isArray(command.user_permissions) && 159 | command.user_permissions.length > 0 160 | ) { 161 | for (const permission of command.user_permissions) { 162 | if (!permissionsBot.has(permission)) { 163 | // Missing "permission" to execute command (USER) 164 | return; 165 | } 166 | } 167 | } 168 | } 169 | 170 | command.execute(client, guild, user, channel, data); 171 | } 172 | 173 | async onMessage( 174 | client: Client, 175 | channel: Channel, 176 | member: GuildMember | null, 177 | message: Message 178 | ): Promise { 179 | const content = message.content; 180 | const prefix = process.env.PREFIX || "!"; 181 | if (!content.toLowerCase().startsWith(prefix.toLowerCase())) { 182 | return; 183 | } 184 | 185 | const args = message.content 186 | .slice(prefix.length) 187 | .trim() 188 | .split(/ +/g); 189 | const commandName = args.shift()?.toLowerCase(); 190 | 191 | if (commandName) { 192 | if (channel.isTextBased() && !channel.isDMBased()) { 193 | message.delete().catch(() => { }); 194 | this.handleCommand( 195 | client, 196 | message.guild, 197 | message.author, 198 | channel, 199 | commandName, 200 | args 201 | ); 202 | } 203 | } 204 | } 205 | } -------------------------------------------------------------------------------- /src/events/ServerListener.ts: -------------------------------------------------------------------------------- 1 | import Discord, { AuditLogEvent, Message, Options, TextChannel } from "discord.js"; 2 | 3 | export class ServerListener { 4 | constructor() { } 5 | 6 | async guildMemberAdd( 7 | client: Discord.Client, 8 | guild: Discord.Guild, 9 | guildMember: Discord.GuildMember 10 | ): Promise { 11 | const generalChat = client.channels.cache.get("id_do_canal"); 12 | if (generalChat instanceof TextChannel) { 13 | generalChat.send({ content: `Bem vindo ${guildMember}!` }) 14 | } 15 | } 16 | 17 | async guildMemberRemove( 18 | client: Discord.Client, 19 | guildMember: Discord.GuildMember | Discord.PartialGuildMember 20 | ): Promise { 21 | const logChannel = client.channels.cache.get("id_do_canal"); 22 | if (logChannel instanceof TextChannel) { 23 | logChannel.send({ content: `${guildMember} saiu do servidor!` }) 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /src/utils/logUtils.ts: -------------------------------------------------------------------------------- 1 | export function startLog(tag: string, prefix: string, commands: number, slash: number) { 2 | console.clear(); 3 | console.log("Autenticado em: " + tag); 4 | console.log("Prefixo selecionado: " + prefix); 5 | console.log(""); 6 | console.log("Commands: " + `${commands} registered`) 7 | console.log("Slash Commands: " + `${slash} registered`) 8 | console.log(""); 9 | } --------------------------------------------------------------------------------