├── .gitignore
├── README.md
├── package-lock.json
├── package.json
└── src
├── bot.ts
├── classes
├── Bot.ts
├── CommandListener.ts
└── Rest.ts
├── commands
├── index.ts
└── ping.ts
└── interfaces
└── Command.ts
/.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 | # Microbundle cache
58 | .rpt2_cache/
59 | .rts2_cache_cjs/
60 | .rts2_cache_es/
61 | .rts2_cache_umd/
62 |
63 | # Optional REPL history
64 | .node_repl_history
65 |
66 | # Output of 'npm pack'
67 | *.tgz
68 |
69 | # Yarn Integrity file
70 | .yarn-integrity
71 |
72 | # dotenv environment variables file
73 | .env
74 | .env.test
75 | .env.production
76 |
77 | # parcel-bundler cache (https://parceljs.org/)
78 | .cache
79 | .parcel-cache
80 |
81 | # Next.js build output
82 | .next
83 | out
84 |
85 | # Nuxt.js build / generate output
86 | .nuxt
87 | dist
88 |
89 | # Gatsby files
90 | .cache/
91 | # Comment in the public line in if your project uses Gatsby and not Next.js
92 | # https://nextjs.org/blog/next-9-1#public-directory-support
93 | # public
94 |
95 | # vuepress build output
96 | .vuepress/dist
97 |
98 | # Serverless directories
99 | .serverless/
100 |
101 | # FuseBox cache
102 | .fusebox/
103 |
104 | # DynamoDB Local files
105 | .dynamodb/
106 |
107 | # TernJS port file
108 | .tern-port
109 |
110 | # Stores VSCode versions used for testing VSCode extensions
111 | .vscode-test
112 |
113 | # yarn v2
114 | .yarn/cache
115 | .yarn/unplugged
116 | .yarn/build-state.yml
117 | .yarn/install-state.gz
118 | .pnp.*
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Tutorial Discord Bot
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | Este é um projeto gravado em uma série de videos no meu [canal](https://www.youtube.com/gumpflash) do youtube, onde ensino como criar um bot no Discord com [discord.js](https://discord.js.org).
23 |
24 | ### Acompanhe os videos do projeto:
25 |
26 | 1. [Configurando o Projeto](https://youtu.be/5d_SAvD9xuQ)
27 | 2. [Iniciando o Bot](https://youtu.be/IkyveMOEPHg)
28 | 3. [Comandos](https://youtu.be/HBma8LJRm7U)
29 | 4. [Opções de comandos](https://youtu.be/xQzjgyeoEfI)
30 |
31 | ### Instalação e Configuração
32 |
33 | Para baixar e instalar o projeto você precisa ter o [node](https://nodejs.org/en/), npm e git instalado.
34 |
35 | ```bash
36 | # Clone/Baixe o projeto
37 | $ git clone https://github.com/GumpFlash/tutorial-discord-bot.git
38 |
39 | # Entre na pasta baixada
40 | $ cd tutorial-discord-bot
41 |
42 | # Instale as dependências
43 | $ npm install
44 |
45 | # Se já tiver configurado -> Inicia o bot
46 | $ npm start
47 | ```
48 |
49 | As configurações vão sendo feitas durante os videos, para saber como pegar seu token e iniciar seu bot veja o [1º Video](https://youtu.be/5d_SAvD9xuQ)
50 |
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tutorialbot",
3 | "version": "1.0.0",
4 | "lockfileVersion": 2,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "tutorialbot",
9 | "version": "1.0.0",
10 | "license": "ISC",
11 | "dependencies": {
12 | "@discordjs/builders": "^0.5.0",
13 | "@discordjs/rest": "^0.1.0-canary.0",
14 | "discord-api-types": "^0.22.0",
15 | "discord.js": "^13.1.0",
16 | "dotenv": "^10.0.0"
17 | }
18 | },
19 | "node_modules/@discordjs/builders": {
20 | "version": "0.5.0",
21 | "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.5.0.tgz",
22 | "integrity": "sha512-HP5y4Rqw68o61Qv4qM5tVmDbWi4mdTFftqIOGRo33SNPpLJ1Ga3KEIR2ibKofkmsoQhEpLmopD1AZDs3cKpHuw==",
23 | "dependencies": {
24 | "@sindresorhus/is": "^4.0.1",
25 | "discord-api-types": "^0.22.0",
26 | "ow": "^0.27.0",
27 | "ts-mixer": "^6.0.0",
28 | "tslib": "^2.3.0"
29 | },
30 | "engines": {
31 | "node": ">=14.0.0",
32 | "npm": ">=7.0.0"
33 | }
34 | },
35 | "node_modules/@discordjs/collection": {
36 | "version": "0.1.6",
37 | "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.1.6.tgz",
38 | "integrity": "sha512-utRNxnd9kSS2qhyivo9lMlt5qgAUasH2gb7BEOn6p0efFh24gjGomHzWKMAPn2hEReOPQZCJaRKoURwRotKucQ=="
39 | },
40 | "node_modules/@discordjs/form-data": {
41 | "version": "3.0.1",
42 | "resolved": "https://registry.npmjs.org/@discordjs/form-data/-/form-data-3.0.1.tgz",
43 | "integrity": "sha512-ZfFsbgEXW71Rw/6EtBdrP5VxBJy4dthyC0tpQKGKmYFImlmmrykO14Za+BiIVduwjte0jXEBlhSKf0MWbFp9Eg==",
44 | "dependencies": {
45 | "asynckit": "^0.4.0",
46 | "combined-stream": "^1.0.8",
47 | "mime-types": "^2.1.12"
48 | },
49 | "engines": {
50 | "node": ">= 6"
51 | }
52 | },
53 | "node_modules/@discordjs/rest": {
54 | "version": "0.1.0-canary.0",
55 | "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-0.1.0-canary.0.tgz",
56 | "integrity": "sha512-d+s//ISYVV+e0w/926wMEeO7vju+Pn11x1JM4tcmVMCHSDgpi6pnFCNAXF1TEdnDcy7xf9tq5cf2pQkb/7ySTQ==",
57 | "dependencies": {
58 | "@discordjs/collection": "^0.1.6",
59 | "@sapphire/async-queue": "^1.1.4",
60 | "@sapphire/snowflake": "^1.3.5",
61 | "abort-controller": "^3.0.0",
62 | "discord-api-types": "^0.18.1",
63 | "form-data": "^4.0.0",
64 | "node-fetch": "^2.6.1",
65 | "tslib": "^2.3.0"
66 | },
67 | "engines": {
68 | "node": ">=16.0.0"
69 | }
70 | },
71 | "node_modules/@discordjs/rest/node_modules/discord-api-types": {
72 | "version": "0.18.1",
73 | "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.18.1.tgz",
74 | "integrity": "sha512-hNC38R9ZF4uaujaZQtQfm5CdQO58uhdkoHQAVvMfIL0LgOSZeW575W8H6upngQOuoxWd8tiRII3LLJm9zuQKYg==",
75 | "deprecated": "No longer supported. Install the latest release (0.20.2)",
76 | "engines": {
77 | "node": ">=12"
78 | }
79 | },
80 | "node_modules/@sapphire/async-queue": {
81 | "version": "1.1.4",
82 | "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.1.4.tgz",
83 | "integrity": "sha512-fFrlF/uWpGOX5djw5Mu2Hnnrunao75WGey0sP0J3jnhmrJ5TAPzHYOmytD5iN/+pMxS+f+u/gezqHa9tPhRHEA==",
84 | "engines": {
85 | "node": ">=14",
86 | "npm": ">=6"
87 | }
88 | },
89 | "node_modules/@sapphire/snowflake": {
90 | "version": "1.3.6",
91 | "resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-1.3.6.tgz",
92 | "integrity": "sha512-QnzuLp+p9D7agynVub/zqlDVriDza9y3STArBhNiNBUgIX8+GL5FpQxstRfw1jDr5jkZUjcuKYAHxjIuXKdJAg==",
93 | "engines": {
94 | "node": ">=12",
95 | "npm": ">=6"
96 | }
97 | },
98 | "node_modules/@sindresorhus/is": {
99 | "version": "4.0.1",
100 | "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.1.tgz",
101 | "integrity": "sha512-Qm9hBEBu18wt1PO2flE7LPb30BHMQt1eQgbV76YntdNk73XZGpn3izvGTYxbGgzXKgbCjiia0uxTd3aTNQrY/g==",
102 | "engines": {
103 | "node": ">=10"
104 | },
105 | "funding": {
106 | "url": "https://github.com/sindresorhus/is?sponsor=1"
107 | }
108 | },
109 | "node_modules/@types/node": {
110 | "version": "16.6.2",
111 | "resolved": "https://registry.npmjs.org/@types/node/-/node-16.6.2.tgz",
112 | "integrity": "sha512-LSw8TZt12ZudbpHc6EkIyDM3nHVWKYrAvGy6EAJfNfjusbwnThqjqxUKKRwuV3iWYeW/LYMzNgaq3MaLffQ2xA=="
113 | },
114 | "node_modules/@types/ws": {
115 | "version": "7.4.7",
116 | "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz",
117 | "integrity": "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==",
118 | "dependencies": {
119 | "@types/node": "*"
120 | }
121 | },
122 | "node_modules/abort-controller": {
123 | "version": "3.0.0",
124 | "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
125 | "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
126 | "dependencies": {
127 | "event-target-shim": "^5.0.0"
128 | },
129 | "engines": {
130 | "node": ">=6.5"
131 | }
132 | },
133 | "node_modules/asynckit": {
134 | "version": "0.4.0",
135 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
136 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
137 | },
138 | "node_modules/callsites": {
139 | "version": "3.1.0",
140 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
141 | "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
142 | "engines": {
143 | "node": ">=6"
144 | }
145 | },
146 | "node_modules/combined-stream": {
147 | "version": "1.0.8",
148 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
149 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
150 | "dependencies": {
151 | "delayed-stream": "~1.0.0"
152 | },
153 | "engines": {
154 | "node": ">= 0.8"
155 | }
156 | },
157 | "node_modules/delayed-stream": {
158 | "version": "1.0.0",
159 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
160 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
161 | "engines": {
162 | "node": ">=0.4.0"
163 | }
164 | },
165 | "node_modules/discord-api-types": {
166 | "version": "0.22.0",
167 | "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.22.0.tgz",
168 | "integrity": "sha512-l8yD/2zRbZItUQpy7ZxBJwaLX/Bs2TGaCthRppk8Sw24LOIWg12t9JEreezPoYD0SQcC2htNNo27kYEpYW/Srg==",
169 | "engines": {
170 | "node": ">=12"
171 | }
172 | },
173 | "node_modules/discord.js": {
174 | "version": "13.1.0",
175 | "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-13.1.0.tgz",
176 | "integrity": "sha512-gxO4CXKdHpqA+WKG+f5RNnd3srTDj5uFJHgOathksDE90YNq/Qijkd2WlMgTTMS6AJoEnHxI7G9eDQHCuZ+xDA==",
177 | "dependencies": {
178 | "@discordjs/builders": "^0.5.0",
179 | "@discordjs/collection": "^0.2.1",
180 | "@discordjs/form-data": "^3.0.1",
181 | "@sapphire/async-queue": "^1.1.4",
182 | "@types/ws": "^7.4.7",
183 | "discord-api-types": "^0.22.0",
184 | "node-fetch": "^2.6.1",
185 | "ws": "^7.5.1"
186 | },
187 | "engines": {
188 | "node": ">=16.6.0",
189 | "npm": ">=7.0.0"
190 | }
191 | },
192 | "node_modules/discord.js/node_modules/@discordjs/collection": {
193 | "version": "0.2.1",
194 | "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.2.1.tgz",
195 | "integrity": "sha512-vhxqzzM8gkomw0TYRF3tgx7SwElzUlXT/Aa41O7mOcyN6wIJfj5JmDWaO5XGKsGSsNx7F3i5oIlrucCCWV1Nog==",
196 | "engines": {
197 | "node": ">=14.0.0"
198 | }
199 | },
200 | "node_modules/dot-prop": {
201 | "version": "6.0.1",
202 | "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz",
203 | "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==",
204 | "dependencies": {
205 | "is-obj": "^2.0.0"
206 | },
207 | "engines": {
208 | "node": ">=10"
209 | },
210 | "funding": {
211 | "url": "https://github.com/sponsors/sindresorhus"
212 | }
213 | },
214 | "node_modules/dotenv": {
215 | "version": "10.0.0",
216 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz",
217 | "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==",
218 | "engines": {
219 | "node": ">=10"
220 | }
221 | },
222 | "node_modules/event-target-shim": {
223 | "version": "5.0.1",
224 | "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
225 | "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
226 | "engines": {
227 | "node": ">=6"
228 | }
229 | },
230 | "node_modules/form-data": {
231 | "version": "4.0.0",
232 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
233 | "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
234 | "dependencies": {
235 | "asynckit": "^0.4.0",
236 | "combined-stream": "^1.0.8",
237 | "mime-types": "^2.1.12"
238 | },
239 | "engines": {
240 | "node": ">= 6"
241 | }
242 | },
243 | "node_modules/is-obj": {
244 | "version": "2.0.0",
245 | "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
246 | "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==",
247 | "engines": {
248 | "node": ">=8"
249 | }
250 | },
251 | "node_modules/lodash.isequal": {
252 | "version": "4.5.0",
253 | "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
254 | "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA="
255 | },
256 | "node_modules/mime-db": {
257 | "version": "1.49.0",
258 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.49.0.tgz",
259 | "integrity": "sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA==",
260 | "engines": {
261 | "node": ">= 0.6"
262 | }
263 | },
264 | "node_modules/mime-types": {
265 | "version": "2.1.32",
266 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.32.tgz",
267 | "integrity": "sha512-hJGaVS4G4c9TSMYh2n6SQAGrC4RnfU+daP8G7cSCmaqNjiOoUY0VHCMS42pxnQmVF1GWwFhbHWn3RIxCqTmZ9A==",
268 | "dependencies": {
269 | "mime-db": "1.49.0"
270 | },
271 | "engines": {
272 | "node": ">= 0.6"
273 | }
274 | },
275 | "node_modules/node-fetch": {
276 | "version": "2.6.1",
277 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
278 | "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==",
279 | "engines": {
280 | "node": "4.x || >=6.0.0"
281 | }
282 | },
283 | "node_modules/ow": {
284 | "version": "0.27.0",
285 | "resolved": "https://registry.npmjs.org/ow/-/ow-0.27.0.tgz",
286 | "integrity": "sha512-SGnrGUbhn4VaUGdU0EJLMwZWSupPmF46hnTRII7aCLCrqixTAC5eKo8kI4/XXf1eaaI8YEVT+3FeGNJI9himAQ==",
287 | "dependencies": {
288 | "@sindresorhus/is": "^4.0.1",
289 | "callsites": "^3.1.0",
290 | "dot-prop": "^6.0.1",
291 | "lodash.isequal": "^4.5.0",
292 | "type-fest": "^1.2.1",
293 | "vali-date": "^1.0.0"
294 | },
295 | "engines": {
296 | "node": ">=12"
297 | },
298 | "funding": {
299 | "url": "https://github.com/sponsors/sindresorhus"
300 | }
301 | },
302 | "node_modules/ts-mixer": {
303 | "version": "6.0.0",
304 | "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.0.tgz",
305 | "integrity": "sha512-nXIb1fvdY5CBSrDIblLn73NW0qRDk5yJ0Sk1qPBF560OdJfQp9jhl+0tzcY09OZ9U+6GpeoI9RjwoIKFIoB9MQ=="
306 | },
307 | "node_modules/tslib": {
308 | "version": "2.3.1",
309 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
310 | "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
311 | },
312 | "node_modules/type-fest": {
313 | "version": "1.4.0",
314 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz",
315 | "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==",
316 | "engines": {
317 | "node": ">=10"
318 | },
319 | "funding": {
320 | "url": "https://github.com/sponsors/sindresorhus"
321 | }
322 | },
323 | "node_modules/vali-date": {
324 | "version": "1.0.0",
325 | "resolved": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz",
326 | "integrity": "sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY=",
327 | "engines": {
328 | "node": ">=0.10.0"
329 | }
330 | },
331 | "node_modules/ws": {
332 | "version": "7.5.3",
333 | "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.3.tgz",
334 | "integrity": "sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg==",
335 | "engines": {
336 | "node": ">=8.3.0"
337 | },
338 | "peerDependencies": {
339 | "bufferutil": "^4.0.1",
340 | "utf-8-validate": "^5.0.2"
341 | },
342 | "peerDependenciesMeta": {
343 | "bufferutil": {
344 | "optional": true
345 | },
346 | "utf-8-validate": {
347 | "optional": true
348 | }
349 | }
350 | }
351 | },
352 | "dependencies": {
353 | "@discordjs/builders": {
354 | "version": "0.5.0",
355 | "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.5.0.tgz",
356 | "integrity": "sha512-HP5y4Rqw68o61Qv4qM5tVmDbWi4mdTFftqIOGRo33SNPpLJ1Ga3KEIR2ibKofkmsoQhEpLmopD1AZDs3cKpHuw==",
357 | "requires": {
358 | "@sindresorhus/is": "^4.0.1",
359 | "discord-api-types": "^0.22.0",
360 | "ow": "^0.27.0",
361 | "ts-mixer": "^6.0.0",
362 | "tslib": "^2.3.0"
363 | }
364 | },
365 | "@discordjs/collection": {
366 | "version": "0.1.6",
367 | "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.1.6.tgz",
368 | "integrity": "sha512-utRNxnd9kSS2qhyivo9lMlt5qgAUasH2gb7BEOn6p0efFh24gjGomHzWKMAPn2hEReOPQZCJaRKoURwRotKucQ=="
369 | },
370 | "@discordjs/form-data": {
371 | "version": "3.0.1",
372 | "resolved": "https://registry.npmjs.org/@discordjs/form-data/-/form-data-3.0.1.tgz",
373 | "integrity": "sha512-ZfFsbgEXW71Rw/6EtBdrP5VxBJy4dthyC0tpQKGKmYFImlmmrykO14Za+BiIVduwjte0jXEBlhSKf0MWbFp9Eg==",
374 | "requires": {
375 | "asynckit": "^0.4.0",
376 | "combined-stream": "^1.0.8",
377 | "mime-types": "^2.1.12"
378 | }
379 | },
380 | "@discordjs/rest": {
381 | "version": "0.1.0-canary.0",
382 | "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-0.1.0-canary.0.tgz",
383 | "integrity": "sha512-d+s//ISYVV+e0w/926wMEeO7vju+Pn11x1JM4tcmVMCHSDgpi6pnFCNAXF1TEdnDcy7xf9tq5cf2pQkb/7ySTQ==",
384 | "requires": {
385 | "@discordjs/collection": "^0.1.6",
386 | "@sapphire/async-queue": "^1.1.4",
387 | "@sapphire/snowflake": "^1.3.5",
388 | "abort-controller": "^3.0.0",
389 | "discord-api-types": "^0.18.1",
390 | "form-data": "^4.0.0",
391 | "node-fetch": "^2.6.1",
392 | "tslib": "^2.3.0"
393 | },
394 | "dependencies": {
395 | "discord-api-types": {
396 | "version": "0.18.1",
397 | "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.18.1.tgz",
398 | "integrity": "sha512-hNC38R9ZF4uaujaZQtQfm5CdQO58uhdkoHQAVvMfIL0LgOSZeW575W8H6upngQOuoxWd8tiRII3LLJm9zuQKYg=="
399 | }
400 | }
401 | },
402 | "@sapphire/async-queue": {
403 | "version": "1.1.4",
404 | "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.1.4.tgz",
405 | "integrity": "sha512-fFrlF/uWpGOX5djw5Mu2Hnnrunao75WGey0sP0J3jnhmrJ5TAPzHYOmytD5iN/+pMxS+f+u/gezqHa9tPhRHEA=="
406 | },
407 | "@sapphire/snowflake": {
408 | "version": "1.3.6",
409 | "resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-1.3.6.tgz",
410 | "integrity": "sha512-QnzuLp+p9D7agynVub/zqlDVriDza9y3STArBhNiNBUgIX8+GL5FpQxstRfw1jDr5jkZUjcuKYAHxjIuXKdJAg=="
411 | },
412 | "@sindresorhus/is": {
413 | "version": "4.0.1",
414 | "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.1.tgz",
415 | "integrity": "sha512-Qm9hBEBu18wt1PO2flE7LPb30BHMQt1eQgbV76YntdNk73XZGpn3izvGTYxbGgzXKgbCjiia0uxTd3aTNQrY/g=="
416 | },
417 | "@types/node": {
418 | "version": "16.6.2",
419 | "resolved": "https://registry.npmjs.org/@types/node/-/node-16.6.2.tgz",
420 | "integrity": "sha512-LSw8TZt12ZudbpHc6EkIyDM3nHVWKYrAvGy6EAJfNfjusbwnThqjqxUKKRwuV3iWYeW/LYMzNgaq3MaLffQ2xA=="
421 | },
422 | "@types/ws": {
423 | "version": "7.4.7",
424 | "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz",
425 | "integrity": "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==",
426 | "requires": {
427 | "@types/node": "*"
428 | }
429 | },
430 | "abort-controller": {
431 | "version": "3.0.0",
432 | "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
433 | "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
434 | "requires": {
435 | "event-target-shim": "^5.0.0"
436 | }
437 | },
438 | "asynckit": {
439 | "version": "0.4.0",
440 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
441 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
442 | },
443 | "callsites": {
444 | "version": "3.1.0",
445 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
446 | "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="
447 | },
448 | "combined-stream": {
449 | "version": "1.0.8",
450 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
451 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
452 | "requires": {
453 | "delayed-stream": "~1.0.0"
454 | }
455 | },
456 | "delayed-stream": {
457 | "version": "1.0.0",
458 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
459 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
460 | },
461 | "discord-api-types": {
462 | "version": "0.22.0",
463 | "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.22.0.tgz",
464 | "integrity": "sha512-l8yD/2zRbZItUQpy7ZxBJwaLX/Bs2TGaCthRppk8Sw24LOIWg12t9JEreezPoYD0SQcC2htNNo27kYEpYW/Srg=="
465 | },
466 | "discord.js": {
467 | "version": "13.1.0",
468 | "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-13.1.0.tgz",
469 | "integrity": "sha512-gxO4CXKdHpqA+WKG+f5RNnd3srTDj5uFJHgOathksDE90YNq/Qijkd2WlMgTTMS6AJoEnHxI7G9eDQHCuZ+xDA==",
470 | "requires": {
471 | "@discordjs/builders": "^0.5.0",
472 | "@discordjs/collection": "^0.2.1",
473 | "@discordjs/form-data": "^3.0.1",
474 | "@sapphire/async-queue": "^1.1.4",
475 | "@types/ws": "^7.4.7",
476 | "discord-api-types": "^0.22.0",
477 | "node-fetch": "^2.6.1",
478 | "ws": "^7.5.1"
479 | },
480 | "dependencies": {
481 | "@discordjs/collection": {
482 | "version": "0.2.1",
483 | "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.2.1.tgz",
484 | "integrity": "sha512-vhxqzzM8gkomw0TYRF3tgx7SwElzUlXT/Aa41O7mOcyN6wIJfj5JmDWaO5XGKsGSsNx7F3i5oIlrucCCWV1Nog=="
485 | }
486 | }
487 | },
488 | "dot-prop": {
489 | "version": "6.0.1",
490 | "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz",
491 | "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==",
492 | "requires": {
493 | "is-obj": "^2.0.0"
494 | }
495 | },
496 | "dotenv": {
497 | "version": "10.0.0",
498 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz",
499 | "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q=="
500 | },
501 | "event-target-shim": {
502 | "version": "5.0.1",
503 | "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
504 | "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="
505 | },
506 | "form-data": {
507 | "version": "4.0.0",
508 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
509 | "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
510 | "requires": {
511 | "asynckit": "^0.4.0",
512 | "combined-stream": "^1.0.8",
513 | "mime-types": "^2.1.12"
514 | }
515 | },
516 | "is-obj": {
517 | "version": "2.0.0",
518 | "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
519 | "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w=="
520 | },
521 | "lodash.isequal": {
522 | "version": "4.5.0",
523 | "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
524 | "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA="
525 | },
526 | "mime-db": {
527 | "version": "1.49.0",
528 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.49.0.tgz",
529 | "integrity": "sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA=="
530 | },
531 | "mime-types": {
532 | "version": "2.1.32",
533 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.32.tgz",
534 | "integrity": "sha512-hJGaVS4G4c9TSMYh2n6SQAGrC4RnfU+daP8G7cSCmaqNjiOoUY0VHCMS42pxnQmVF1GWwFhbHWn3RIxCqTmZ9A==",
535 | "requires": {
536 | "mime-db": "1.49.0"
537 | }
538 | },
539 | "node-fetch": {
540 | "version": "2.6.1",
541 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
542 | "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw=="
543 | },
544 | "ow": {
545 | "version": "0.27.0",
546 | "resolved": "https://registry.npmjs.org/ow/-/ow-0.27.0.tgz",
547 | "integrity": "sha512-SGnrGUbhn4VaUGdU0EJLMwZWSupPmF46hnTRII7aCLCrqixTAC5eKo8kI4/XXf1eaaI8YEVT+3FeGNJI9himAQ==",
548 | "requires": {
549 | "@sindresorhus/is": "^4.0.1",
550 | "callsites": "^3.1.0",
551 | "dot-prop": "^6.0.1",
552 | "lodash.isequal": "^4.5.0",
553 | "type-fest": "^1.2.1",
554 | "vali-date": "^1.0.0"
555 | }
556 | },
557 | "ts-mixer": {
558 | "version": "6.0.0",
559 | "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.0.tgz",
560 | "integrity": "sha512-nXIb1fvdY5CBSrDIblLn73NW0qRDk5yJ0Sk1qPBF560OdJfQp9jhl+0tzcY09OZ9U+6GpeoI9RjwoIKFIoB9MQ=="
561 | },
562 | "tslib": {
563 | "version": "2.3.1",
564 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
565 | "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
566 | },
567 | "type-fest": {
568 | "version": "1.4.0",
569 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz",
570 | "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA=="
571 | },
572 | "vali-date": {
573 | "version": "1.0.0",
574 | "resolved": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz",
575 | "integrity": "sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY="
576 | },
577 | "ws": {
578 | "version": "7.5.3",
579 | "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.3.tgz",
580 | "integrity": "sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg==",
581 | "requires": {}
582 | }
583 | }
584 | }
585 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tutorialbot",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "src/bot.ts",
6 | "scripts": {
7 | "start": "ts-node-dev .",
8 | "prod": "ts-node .",
9 | "test": "echo \"Error: no test specified\" && exit 1"
10 | },
11 | "author": "",
12 | "license": "ISC",
13 | "dependencies": {
14 | "@discordjs/builders": "^0.5.0",
15 | "@discordjs/rest": "^0.1.0-canary.0",
16 | "discord-api-types": "^0.22.0",
17 | "discord.js": "^13.1.0",
18 | "dotenv": "^10.0.0"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/bot.ts:
--------------------------------------------------------------------------------
1 | import Bot from "./classes/Bot";
2 | import { config } from "dotenv";
3 | import Rest from "./classes/Rest";
4 | import Commands from "./commands";
5 | import CommandListener from "./classes/CommandListener";
6 |
7 | config();
8 |
9 | const init = () => {
10 | if (!process.env.TOKEN) {
11 | console.error("O Token não foi encontrado!");
12 | return;
13 | }
14 | if (!process.env.CLIENT_ID) {
15 | console.error("O ClientId não foi encontrado!");
16 | return;
17 | }
18 |
19 | const rest = new Rest(process.env.TOKEN, process.env.CLIENT_ID);
20 | rest.registerCommands(Commands);
21 | rest.start();
22 | const bot = new Bot(process.env.TOKEN);
23 | const commands = new CommandListener(Commands);
24 | bot.start();
25 | };
26 | init();
27 |
--------------------------------------------------------------------------------
/src/classes/Bot.ts:
--------------------------------------------------------------------------------
1 | import { Client, Intents } from "discord.js";
2 |
3 | const intents = [Intents.FLAGS.GUILDS];
4 |
5 | class Bot {
6 | public static client: Client;
7 | constructor(private token: string) {
8 | Bot.client = new Client({ intents });
9 | Bot.client.on("ready", () => {
10 | if (Bot.client.user)
11 | console.log(`O bot está funcionando como ${Bot.client.user.tag}!`);
12 | });
13 | }
14 | start() {
15 | Bot.client.login(this.token);
16 | }
17 | }
18 |
19 | export default Bot;
20 |
--------------------------------------------------------------------------------
/src/classes/CommandListener.ts:
--------------------------------------------------------------------------------
1 | import Command from "../interfaces/Command";
2 | import Bot from "./Bot";
3 |
4 | class CommandListener {
5 | constructor(private commands: Command[]) {
6 | if (!Bot.client) return;
7 | Bot.client.on("interactionCreate", async (interaction) => {
8 | if (!interaction.isCommand()) return;
9 |
10 | this.commands.forEach((command) => {
11 | if (interaction.commandName === command.name) command.run(interaction);
12 | });
13 | });
14 | }
15 | }
16 |
17 | export default CommandListener;
18 |
--------------------------------------------------------------------------------
/src/classes/Rest.ts:
--------------------------------------------------------------------------------
1 | import { SlashCommandBuilder } from "@discordjs/builders";
2 | import { SlashCommandOptionBase } from "@discordjs/builders/dist/interactions/slashCommands/mixins/CommandOptionBase";
3 | import { REST } from "@discordjs/rest";
4 | import { Routes } from "discord-api-types/v9";
5 | import Command, { Option, OptionType } from "../interfaces/Command";
6 |
7 | class Rest {
8 | private rest: REST;
9 | private commands: Command[] = [];
10 | constructor(private token: string, private clientId: string) {
11 | this.rest = new REST({ version: "9" }).setToken(this.token);
12 | }
13 | registerCommands(commands: Command[]) {
14 | this.commands = commands;
15 | }
16 | start() {
17 | (async () => {
18 | try {
19 | console.log("Recarregando os comandos de barra da aplicação...");
20 | await this.rest.put(Routes.applicationCommands(this.clientId), {
21 | body: this.commands.map((command) => {
22 | const data = new SlashCommandBuilder()
23 | .setName(command.name.toLowerCase())
24 | .setDescription(command.description);
25 | const dataWithOptions = this.addFields(data, command.options);
26 | return dataWithOptions.toJSON();
27 | }),
28 | });
29 | console.log(
30 | "Os comandos de barra da aplicação foram recarregados com sucesso!"
31 | );
32 | } catch (error) {
33 | console.error(error);
34 | }
35 | })();
36 | }
37 | addField(slashOption: T, option: Option) {
38 | return slashOption
39 | .setName(option.name.toLowerCase())
40 | .setDescription(option.description)
41 | .setRequired(option.required ? true : false);
42 | }
43 | addFields(data: SlashCommandBuilder, options?: Option[]) {
44 | options &&
45 | options.forEach((option) => {
46 | switch (option.type) {
47 | case OptionType.Boolean:
48 | data.addBooleanOption((slashOption) =>
49 | this.addField(slashOption, option)
50 | );
51 | break;
52 | case OptionType.Channel:
53 | data.addChannelOption((slashOption) =>
54 | this.addField(slashOption, option)
55 | );
56 | break;
57 | case OptionType.Integer:
58 | data.addIntegerOption((slashOption) => {
59 | const newSlashOption = this.addField(slashOption, option);
60 |
61 | option.choices &&
62 | option.choices.forEach((choice) =>
63 | newSlashOption.addChoice(choice.name, parseInt(choice.value))
64 | );
65 |
66 | return newSlashOption;
67 | });
68 | break;
69 | case OptionType.Mention:
70 | data.addMentionableOption((slashOption) =>
71 | this.addField(slashOption, option)
72 | );
73 | break;
74 | case OptionType.Role:
75 | data.addRoleOption((slashOption) =>
76 | this.addField(slashOption, option)
77 | );
78 | break;
79 | case OptionType.String:
80 | data.addStringOption((slashOption) => {
81 | const newSlashOption = this.addField(slashOption, option);
82 |
83 | option.choices &&
84 | option.choices.forEach((choice) =>
85 | newSlashOption.addChoice(choice.name, choice.value)
86 | );
87 |
88 | return newSlashOption;
89 | });
90 | break;
91 | case OptionType.User:
92 | data.addUserOption((slashOption) =>
93 | this.addField(slashOption, option)
94 | );
95 | break;
96 | }
97 | });
98 | return data;
99 | }
100 | }
101 |
102 | export default Rest;
103 |
--------------------------------------------------------------------------------
/src/commands/index.ts:
--------------------------------------------------------------------------------
1 | import { ping } from "./ping";
2 |
3 | export default [ping];
4 |
--------------------------------------------------------------------------------
/src/commands/ping.ts:
--------------------------------------------------------------------------------
1 | import Command, { OptionType } from "../interfaces/Command";
2 |
3 | export const ping: Command = {
4 | name: "ping",
5 | description: "responde com pong",
6 | options: [
7 | {
8 | name: "nome",
9 | description: "nome da pessoa que vai receber o pong",
10 | type: OptionType.String,
11 | required: true,
12 | choices: [
13 | {
14 | name: "Gump",
15 | value: "gump",
16 | },
17 | {
18 | name: "Discord",
19 | value: "discord",
20 | },
21 | ],
22 | },
23 | ],
24 | run: async (interaction) => {
25 | const nome = interaction.options.data[0].value;
26 |
27 | await interaction.reply(`PONG ${nome}`);
28 | },
29 | };
30 |
--------------------------------------------------------------------------------
/src/interfaces/Command.ts:
--------------------------------------------------------------------------------
1 | import { CommandInteraction } from "discord.js";
2 |
3 | export interface Option {
4 | name: string;
5 | description: string;
6 | type: OptionType;
7 | required?: boolean;
8 | choices?: {
9 | name: string;
10 | value: string;
11 | }[];
12 | }
13 |
14 | export enum OptionType {
15 | Boolean,
16 | Channel,
17 | Integer,
18 | Mention,
19 | Role,
20 | String,
21 | User,
22 | }
23 |
24 | export default interface Command {
25 | name: string;
26 | description: string;
27 | options?: Option[];
28 | run: (interaction: CommandInteraction) => void;
29 | }
30 |
--------------------------------------------------------------------------------