├── .gitignore ├── .prettierrc ├── LICENSE ├── package-lock.json ├── package.json ├── readme.md ├── src ├── core │ ├── InteractionsClient.ts │ └── interfaces.ts └── index.ts ├── tests └── main.test.js ├── tsconfig-cjs.json └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /lib 3 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "tabWidth": 4, 3 | "printWidth": 100 4 | } 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 MatteZ02 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "discord-slash-commands-client", 3 | "version": "1.2.2", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "discord-slash-commands-client", 9 | "version": "1.2.2", 10 | "license": "MIT", 11 | "dependencies": { 12 | "axios": "^0.21.2" 13 | }, 14 | "devDependencies": { 15 | "@types/node": "^15.0.1", 16 | "discord.js": "https://github.com/MatteZ02/discord.js", 17 | "typescript": "^4.2.4" 18 | } 19 | }, 20 | "node_modules/@discordjs/collection": { 21 | "version": "0.1.6", 22 | "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.1.6.tgz", 23 | "integrity": "sha512-utRNxnd9kSS2qhyivo9lMlt5qgAUasH2gb7BEOn6p0efFh24gjGomHzWKMAPn2hEReOPQZCJaRKoURwRotKucQ==", 24 | "dev": true 25 | }, 26 | "node_modules/@discordjs/form-data": { 27 | "version": "3.0.1", 28 | "resolved": "https://registry.npmjs.org/@discordjs/form-data/-/form-data-3.0.1.tgz", 29 | "integrity": "sha512-ZfFsbgEXW71Rw/6EtBdrP5VxBJy4dthyC0tpQKGKmYFImlmmrykO14Za+BiIVduwjte0jXEBlhSKf0MWbFp9Eg==", 30 | "dev": true, 31 | "dependencies": { 32 | "asynckit": "^0.4.0", 33 | "combined-stream": "^1.0.8", 34 | "mime-types": "^2.1.12" 35 | }, 36 | "engines": { 37 | "node": ">= 6" 38 | } 39 | }, 40 | "node_modules/@types/node": { 41 | "version": "15.0.1", 42 | "resolved": "https://registry.npmjs.org/@types/node/-/node-15.0.1.tgz", 43 | "integrity": "sha512-TMkXt0Ck1y0KKsGr9gJtWGjttxlZnnvDtphxUOSd0bfaR6Q1jle+sPvrzNR1urqYTWMinoKvjKfXUGsumaO1PA==", 44 | "dev": true 45 | }, 46 | "node_modules/abort-controller": { 47 | "version": "3.0.0", 48 | "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", 49 | "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", 50 | "dev": true, 51 | "dependencies": { 52 | "event-target-shim": "^5.0.0" 53 | }, 54 | "engines": { 55 | "node": ">=6.5" 56 | } 57 | }, 58 | "node_modules/asynckit": { 59 | "version": "0.4.0", 60 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 61 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", 62 | "dev": true 63 | }, 64 | "node_modules/axios": { 65 | "version": "0.21.2", 66 | "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.2.tgz", 67 | "integrity": "sha512-87otirqUw3e8CzHTMO+/9kh/FSgXt/eVDvipijwDtEuwbkySWZ9SBm6VEubmJ/kLKEoLQV/POhxXFb66bfekfg==", 68 | "dependencies": { 69 | "follow-redirects": "^1.14.0" 70 | } 71 | }, 72 | "node_modules/combined-stream": { 73 | "version": "1.0.8", 74 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 75 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 76 | "dev": true, 77 | "dependencies": { 78 | "delayed-stream": "~1.0.0" 79 | }, 80 | "engines": { 81 | "node": ">= 0.8" 82 | } 83 | }, 84 | "node_modules/delayed-stream": { 85 | "version": "1.0.0", 86 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 87 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", 88 | "dev": true, 89 | "engines": { 90 | "node": ">=0.4.0" 91 | } 92 | }, 93 | "node_modules/discord.js": { 94 | "version": "12.5.0", 95 | "resolved": "git+ssh://git@github.com/MatteZ02/discord.js.git#3bb14488c687d34bc0d9360bdc50a0396fc3230b", 96 | "dev": true, 97 | "license": "Apache-2.0", 98 | "dependencies": { 99 | "@discordjs/collection": "^0.1.6", 100 | "@discordjs/form-data": "^3.0.1", 101 | "abort-controller": "^3.0.0", 102 | "node-fetch": "^2.6.1", 103 | "prism-media": "^1.2.2", 104 | "setimmediate": "^1.0.5", 105 | "tweetnacl": "^1.0.3", 106 | "ws": "^7.3.1" 107 | }, 108 | "engines": { 109 | "node": ">=14.0.0" 110 | } 111 | }, 112 | "node_modules/event-target-shim": { 113 | "version": "5.0.1", 114 | "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", 115 | "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", 116 | "dev": true, 117 | "engines": { 118 | "node": ">=6" 119 | } 120 | }, 121 | "node_modules/follow-redirects": { 122 | "version": "1.14.3", 123 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.3.tgz", 124 | "integrity": "sha512-3MkHxknWMUtb23apkgz/83fDoe+y+qr0TdgacGIA7bew+QLBo3vdgEN2xEsuXNivpFy4CyDhBBZnNZOtalmenw==", 125 | "funding": [ 126 | { 127 | "type": "individual", 128 | "url": "https://github.com/sponsors/RubenVerborgh" 129 | } 130 | ], 131 | "engines": { 132 | "node": ">=4.0" 133 | }, 134 | "peerDependenciesMeta": { 135 | "debug": { 136 | "optional": true 137 | } 138 | } 139 | }, 140 | "node_modules/mime-db": { 141 | "version": "1.44.0", 142 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", 143 | "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", 144 | "dev": true, 145 | "engines": { 146 | "node": ">= 0.6" 147 | } 148 | }, 149 | "node_modules/mime-types": { 150 | "version": "2.1.27", 151 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", 152 | "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", 153 | "dev": true, 154 | "dependencies": { 155 | "mime-db": "1.44.0" 156 | }, 157 | "engines": { 158 | "node": ">= 0.6" 159 | } 160 | }, 161 | "node_modules/node-fetch": { 162 | "version": "2.6.1", 163 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", 164 | "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", 165 | "dev": true, 166 | "engines": { 167 | "node": "4.x || >=6.0.0" 168 | } 169 | }, 170 | "node_modules/prism-media": { 171 | "version": "1.2.3", 172 | "resolved": "https://registry.npmjs.org/prism-media/-/prism-media-1.2.3.tgz", 173 | "integrity": "sha512-fSrR66n0l6roW9Rx4rSLMyTPTjRTiXy5RVqDOurACQ6si1rKHHKDU5gwBJoCsIV0R3o9gi+K50akl/qyw1C74A==", 174 | "dev": true, 175 | "peerDependencies": { 176 | "@discordjs/opus": "^0.3.3", 177 | "ffmpeg-static": "^4.2.7 || ^3.0.0 || ^2.4.0", 178 | "node-opus": "^0.3.3", 179 | "opusscript": "^0.0.7" 180 | }, 181 | "peerDependenciesMeta": { 182 | "@discordjs/opus": { 183 | "optional": true 184 | }, 185 | "ffmpeg-static": { 186 | "optional": true 187 | }, 188 | "node-opus": { 189 | "optional": true 190 | }, 191 | "opusscript": { 192 | "optional": true 193 | } 194 | } 195 | }, 196 | "node_modules/setimmediate": { 197 | "version": "1.0.5", 198 | "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", 199 | "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", 200 | "dev": true 201 | }, 202 | "node_modules/tweetnacl": { 203 | "version": "1.0.3", 204 | "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", 205 | "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", 206 | "dev": true 207 | }, 208 | "node_modules/typescript": { 209 | "version": "4.2.4", 210 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.4.tgz", 211 | "integrity": "sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==", 212 | "dev": true, 213 | "bin": { 214 | "tsc": "bin/tsc", 215 | "tsserver": "bin/tsserver" 216 | }, 217 | "engines": { 218 | "node": ">=4.2.0" 219 | } 220 | }, 221 | "node_modules/ws": { 222 | "version": "7.5.4", 223 | "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.4.tgz", 224 | "integrity": "sha512-zP9z6GXm6zC27YtspwH99T3qTG7bBFv2VIkeHstMLrLlDJuzA7tQ5ls3OJ1hOGGCzTQPniNJoHXIAOS0Jljohg==", 225 | "dev": true, 226 | "engines": { 227 | "node": ">=8.3.0" 228 | }, 229 | "peerDependencies": { 230 | "bufferutil": "^4.0.1", 231 | "utf-8-validate": "^5.0.2" 232 | }, 233 | "peerDependenciesMeta": { 234 | "bufferutil": { 235 | "optional": true 236 | }, 237 | "utf-8-validate": { 238 | "optional": true 239 | } 240 | } 241 | } 242 | }, 243 | "dependencies": { 244 | "@discordjs/collection": { 245 | "version": "0.1.6", 246 | "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.1.6.tgz", 247 | "integrity": "sha512-utRNxnd9kSS2qhyivo9lMlt5qgAUasH2gb7BEOn6p0efFh24gjGomHzWKMAPn2hEReOPQZCJaRKoURwRotKucQ==", 248 | "dev": true 249 | }, 250 | "@discordjs/form-data": { 251 | "version": "3.0.1", 252 | "resolved": "https://registry.npmjs.org/@discordjs/form-data/-/form-data-3.0.1.tgz", 253 | "integrity": "sha512-ZfFsbgEXW71Rw/6EtBdrP5VxBJy4dthyC0tpQKGKmYFImlmmrykO14Za+BiIVduwjte0jXEBlhSKf0MWbFp9Eg==", 254 | "dev": true, 255 | "requires": { 256 | "asynckit": "^0.4.0", 257 | "combined-stream": "^1.0.8", 258 | "mime-types": "^2.1.12" 259 | } 260 | }, 261 | "@types/node": { 262 | "version": "15.0.1", 263 | "resolved": "https://registry.npmjs.org/@types/node/-/node-15.0.1.tgz", 264 | "integrity": "sha512-TMkXt0Ck1y0KKsGr9gJtWGjttxlZnnvDtphxUOSd0bfaR6Q1jle+sPvrzNR1urqYTWMinoKvjKfXUGsumaO1PA==", 265 | "dev": true 266 | }, 267 | "abort-controller": { 268 | "version": "3.0.0", 269 | "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", 270 | "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", 271 | "dev": true, 272 | "requires": { 273 | "event-target-shim": "^5.0.0" 274 | } 275 | }, 276 | "asynckit": { 277 | "version": "0.4.0", 278 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 279 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", 280 | "dev": true 281 | }, 282 | "axios": { 283 | "version": "0.21.2", 284 | "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.2.tgz", 285 | "integrity": "sha512-87otirqUw3e8CzHTMO+/9kh/FSgXt/eVDvipijwDtEuwbkySWZ9SBm6VEubmJ/kLKEoLQV/POhxXFb66bfekfg==", 286 | "requires": { 287 | "follow-redirects": "^1.14.0" 288 | } 289 | }, 290 | "combined-stream": { 291 | "version": "1.0.8", 292 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 293 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 294 | "dev": true, 295 | "requires": { 296 | "delayed-stream": "~1.0.0" 297 | } 298 | }, 299 | "delayed-stream": { 300 | "version": "1.0.0", 301 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 302 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", 303 | "dev": true 304 | }, 305 | "discord.js": { 306 | "version": "git+ssh://git@github.com/MatteZ02/discord.js.git#3bb14488c687d34bc0d9360bdc50a0396fc3230b", 307 | "dev": true, 308 | "from": "discord.js@https://github.com/MatteZ02/discord.js", 309 | "requires": { 310 | "@discordjs/collection": "^0.1.6", 311 | "@discordjs/form-data": "^3.0.1", 312 | "abort-controller": "^3.0.0", 313 | "node-fetch": "^2.6.1", 314 | "prism-media": "^1.2.2", 315 | "setimmediate": "^1.0.5", 316 | "tweetnacl": "^1.0.3", 317 | "ws": "^7.3.1" 318 | } 319 | }, 320 | "event-target-shim": { 321 | "version": "5.0.1", 322 | "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", 323 | "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", 324 | "dev": true 325 | }, 326 | "follow-redirects": { 327 | "version": "1.14.3", 328 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.3.tgz", 329 | "integrity": "sha512-3MkHxknWMUtb23apkgz/83fDoe+y+qr0TdgacGIA7bew+QLBo3vdgEN2xEsuXNivpFy4CyDhBBZnNZOtalmenw==" 330 | }, 331 | "mime-db": { 332 | "version": "1.44.0", 333 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", 334 | "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", 335 | "dev": true 336 | }, 337 | "mime-types": { 338 | "version": "2.1.27", 339 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", 340 | "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", 341 | "dev": true, 342 | "requires": { 343 | "mime-db": "1.44.0" 344 | } 345 | }, 346 | "node-fetch": { 347 | "version": "2.6.1", 348 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", 349 | "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", 350 | "dev": true 351 | }, 352 | "prism-media": { 353 | "version": "1.2.3", 354 | "resolved": "https://registry.npmjs.org/prism-media/-/prism-media-1.2.3.tgz", 355 | "integrity": "sha512-fSrR66n0l6roW9Rx4rSLMyTPTjRTiXy5RVqDOurACQ6si1rKHHKDU5gwBJoCsIV0R3o9gi+K50akl/qyw1C74A==", 356 | "dev": true, 357 | "requires": {} 358 | }, 359 | "setimmediate": { 360 | "version": "1.0.5", 361 | "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", 362 | "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", 363 | "dev": true 364 | }, 365 | "tweetnacl": { 366 | "version": "1.0.3", 367 | "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", 368 | "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", 369 | "dev": true 370 | }, 371 | "typescript": { 372 | "version": "4.2.4", 373 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.4.tgz", 374 | "integrity": "sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==", 375 | "dev": true 376 | }, 377 | "ws": { 378 | "version": "7.5.4", 379 | "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.4.tgz", 380 | "integrity": "sha512-zP9z6GXm6zC27YtspwH99T3qTG7bBFv2VIkeHstMLrLlDJuzA7tQ5ls3OJ1hOGGCzTQPniNJoHXIAOS0Jljohg==", 381 | "dev": true, 382 | "requires": {} 383 | } 384 | } 385 | } 386 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "discord-slash-commands-client", 3 | "version": "1.2.2", 4 | "description": "A simple way to interact and manage discord slash-commands", 5 | "main": "./lib/cjs/index.js", 6 | "module": "./lib/esm/index.js", 7 | "files": [ 8 | "lib/**/*" 9 | ], 10 | "scripts": { 11 | "pretest": "npm run build", 12 | "test": "node tests/main.test.js", 13 | "build": "tsc -p tsconfig.json && tsc -p tsconfig-cjs.json", 14 | "prepare": "npm run build" 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "git+https://github.com/MatteZ02/discord-interactions.git" 19 | }, 20 | "author": "MatteZ02", 21 | "license": "MIT", 22 | "bugs": { 23 | "url": "https://github.com/MatteZ02/discord-interactions/issues" 24 | }, 25 | "homepage": "https://github.com/MatteZ02/discord-interactions#readme", 26 | "dependencies": { 27 | "axios": "^0.21.2" 28 | }, 29 | "devDependencies": { 30 | "@types/node": "^15.0.1", 31 | "discord.js": "https://github.com/MatteZ02/discord.js", 32 | "typescript": "^4.2.4" 33 | }, 34 | "keywords": [ 35 | "discord", 36 | "slash-commands", 37 | "disord-slash-commands", 38 | "discord-api", 39 | "discord.js" 40 | ] 41 | } -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # discord-slash-commands-client 2 | 3 | An easy way to create and manage discord slash-commands. 4 | 5 | # Support 6 | 7 | You can contact us on our [Discord server](https://discord.gg/2qFkF3qqmu) 8 | 9 | # Usage 10 | 11 | ```js 12 | const { Client } = require("discord-slash-commands-client"); 13 | // TypeScript: import { Client } from "discord-slash-commands-client"; 14 | 15 | const client = new Client( 16 | "you unique bot token", 17 | "your bots user id" 18 | ); 19 | 20 | // list all your existing commands. 21 | client.getCommands().then(console.log).catch(console.error); 22 | 23 | // will create a new command and log its data. If a command with this name already exist will that be overwritten. 24 | client 25 | .createCommand({ 26 | name: "unique command name", 27 | description: "description for this unique command", 28 | }) 29 | .then(console.log) 30 | .catch(console.error); 31 | 32 | // will edit the details of a command. 33 | client 34 | .editCommand( 35 | { name: "new command name", description: "new command description" }, 36 | "id of the command you wish to edit" 37 | ) 38 | .then(console.log) 39 | .catch(console.error); 40 | 41 | // will delete a command 42 | client 43 | .deleteCommand("id of the command you wish to delete") 44 | .then(console.log) 45 | .catch(console.error); 46 | ``` 47 | 48 | # API 49 | 50 | Passing a guildID is optional. Doing so will make the command only be available on that guild. 51 | Guild commands update **instantly**. We recommend you use guild commands for quick testing, and global commands when they're ready for public use. 52 | 53 | [Discord api documentation on slash commands](https://discord.com/developers/docs/interactions/slash-commands) 54 | 55 | ### getCommands(options: getCommandOptions) returns Promise< array of ApplicationOptions> 56 | 57 | - `getCommandsOptions` - List of options can be found [here](#options). 58 | 59 | ### createCommand(options: ApplicationCommandOptions, guildID?: string) returns Promise 60 | 61 | - `ApplicationOptions` - List of options can be found [here](#options). 62 | - `guildID` - guild to create this command on. 63 | 64 | ### editCommand(options: ApplicationCommandOptions, commandID: string, guildID?: string) returns Promise 65 | 66 | - `ApplicationOptions` - List of options can be found [here](#options). 67 | - `commandID` - ID of the command you wish to edit. 68 | - `guildID` - If the command is a part of a guild you must pass the guildID here. 69 | 70 | ### deleteCommand(commandID: string, guildID?: string) returns Promise 71 | 72 | - `commandID` - ID of the command you wish to delete. 73 | - `guildID` - If the command is a part of a guild you must pass the guildID here. 74 | 75 | ### getCommandPermissions(guildID: string, commandID?: string) returns Promise; 76 | 77 | - `guildID` - the guild id to get permissions for 78 | - `commandID` - ID of the command you wish to get permissions for 79 | 80 | ### editCommandPermissions(permissions: ApplicationCommandPermissions[], guildID: string, commandID: string) returns Promise 81 | 82 | - `ApplicationCommandPermissions` - list of permissions 83 | - `guildID` - The guild ID the permissions should apply for 84 | - `commandID` - The command ID the permissions should apply for 85 | 86 | # Options 87 | 88 | Properties marked with `?` are optional. 89 | 90 | ### ApplicationCommandOption 91 | 92 | ```js 93 | { 94 | name: "name of this unique command", 95 | description: "description for this unique command", 96 | options?: [ 97 | { 98 | name: "name of this option", 99 | description: "description for this option", 100 | type: 1,// Type for this option. for a list of types see https://discord.com/developers/docs/interactions/slash-commands#applicationcommandoptiontype 101 | default?: true, 102 | required?: true, 103 | choices?: [ 104 | { 105 | name: "string to prefill for this choice", 106 | value: "value of this choice that will be returned when command is used." 107 | } 108 | ] 109 | } 110 | ] 111 | } 112 | ``` 113 | 114 | ```js 115 | { 116 | name: "name of the command"; 117 | description: "description of the command"; 118 | options?: Array of ApplicationCommandOption; 119 | } 120 | ``` 121 | 122 | ### getCommandsOptions 123 | 124 | ```js 125 | { 126 | commandID?: "id of the command you wish to get", 127 | guildID?: "if the command is a part of a guild u should put the guild id here" 128 | } 129 | ``` 130 | 131 | # Permissions 132 | 133 | ### [ApplicationCommandPermissions](https://discord.com/developers/docs/interactions/slash-commands#applicationcommandpermissions) 134 | 135 | ```ts 136 | /** 137 | * Application command permissions allow you to enable or disable commands for specific users or roles within a guild. 138 | */ 139 | interface ApplicationCommandPermissions { 140 | /** Id of the role or user */ 141 | id: string; 142 | 143 | /** The type of permission (1 = Role, 2 = User) */ 144 | type: 1 | 2; 145 | 146 | /** `true` to allow, `false` to disallow */ 147 | permission: boolean; 148 | } 149 | ``` 150 | 151 | ### [GuildApplicationCommandPermissions](https://discord.com/developers/docs/interactions/slash-commands#guildapplicationcommandpermissions) 152 | 153 | ```ts 154 | /** 155 | * Returned when fetching the permissions for a command in a guild. 156 | */ 157 | interface GuildApplicationCommandPermissions { 158 | /** Id of the command */ 159 | id: string; 160 | 161 | /** Id of the application the command belongs to */ 162 | application_id: string; 163 | 164 | /** Id of the guild */ 165 | guild_id: string; 166 | 167 | /** Array of ApplicationCommandPermissions */ 168 | permissions: ApplicationCommandPermissions[]; 169 | } 170 | ``` 171 | 172 | # Types 173 | 174 | You can find a list of Data Models and Types from [here](https://discord.com/developers/docs/interactions/slash-commands#data-models-and-types) 175 | 176 | # Interaction with the command 177 | 178 | To receive an interaction with the command (when an user uses the command) there are 2 options. 179 | 180 | 1. You can setup a webhook-based interaction. You can read more about how to do this from the [documentation](https://discord.com/developers/docs/interactions/slash-commands#receiving-an-interaction) 181 | 2. If you're using [discord.js](https://discord.js.org/) you can use my own [fork](https://github.com/MatteZ02/discord.js) to receive events for interaction. 182 | 183 | ## Events 184 | 185 | We'll cover using the 2nd option. 186 | 187 | Replace your current discord.js with my fork `npm i https://github.com/MatteZ02/discord.js` 188 | You can listen to the interactionCreate event which will fire every time someone uses any of the commands created for your bot. 189 | 190 | ### Usage with djs 191 | 192 | ```js 193 | const Discord = require("discord.js"); 194 | const interactions = require("discord-slash-commands-client"); 195 | 196 | // create a new client 197 | const client = new Discord.Client(); 198 | const token = "Your unique bot token"; 199 | 200 | // attach the interaction client to discord.js client 201 | client.interactions = new interactions.Client(token, "You bots user id"); 202 | 203 | // attach and event listener for the ready event 204 | client.on("ready", () => { 205 | console.log("Client is ready!"); 206 | 207 | // Create a new command that we can test 208 | client.interactions 209 | .createCommand({ 210 | name: "ping", 211 | description: "ping pong", 212 | }) 213 | .then(console.log) 214 | .catch(console.error); 215 | }); 216 | 217 | // attach and event listener for the interactionCreate event 218 | client.on("interactionCreate", async (interaction) => { 219 | if (interaction.name === "ping") { 220 | // send an initial reply 221 | await interaction.reply("Pong"); 222 | 223 | // send a followup 224 | const messageId = await interaction.reply({ 225 | content: "Follow up message", 226 | embeds: [new MessageEmbed().setDescription("Follow up test")], 227 | }); 228 | 229 | setTimeout(() => { 230 | // delete initial reply 231 | interaction.delete(); 232 | 233 | // edit 1st followup 234 | interaction.edit("Edited follow up message", messageId); 235 | }, 5000); 236 | } 237 | }); 238 | 239 | // login 240 | client.login(token); 241 | ``` 242 | 243 | ### interaction example response 244 | 245 | ```JS 246 | id: string; 247 | token: string; 248 | channel: Discord.TextChannel;// The channel where this interaction occurred 249 | guild: Discord.Guild;// The guild where this interaction occurred 250 | member: Discord.GuildMember | null;// The guild member who issued the interaction (will be null if we cannot obtain a guildMember) 251 | author: Discord.User | null;// The user who issued the interaction (will be null if we cannot obtain an user) 252 | name: string;// name of this command 253 | content: string;// content of this command (everything after the main command name) 254 | createdTimestamp: number;// timestamp of this command being used 255 | options: { value: string; name: string }[] | null;// list of options this user inputted to the command 256 | /** 257 | * Replies to this Interaction. 258 | * 259 | * **Note:** Ephemeral messages don't appear to support embeds at this time. 260 | * @arg input - A message string, embed array, or object containing both 261 | * @arg ephemeral - Make the reply viewable only to the command sender. If false, reply is public 262 | * @returns A Promise that resolves a `messageId` which can be used with `.edit(...)` and `.delete(...)` 263 | */ 264 | reply: ( 265 | input?: string | MessageEmbed[] | { content: string; embeds: MessageEmbed[] }, 266 | ephemeral?: boolean, 267 | ) => Promise; 268 | /** 269 | * Edit a previous reply to this Interaction 270 | * 271 | * **Note:** Ephemeral messages don't appear to support embeds at this time. 272 | * @arg input - A message string, embed array, or object containing both 273 | * @arg messageId - The id of the message to delete. If omitted, the original reply message is deleted. 274 | */ 275 | edit: ( 276 | input?: string | MessageEmbed[] | { content: string; embeds: MessageEmbed[] }, 277 | messageId?: string, 278 | ) => Promise; 279 | /** 280 | * Sends a simple reply that makes the bot say "is thinking..." 281 | * 282 | * **Note:** You must use `.edit(...)` if you want to update the reply with an actual message later on. 283 | * @arg ephemeral - Make the reply viewable only to the command sender. If false, reply is public 284 | */ 285 | thinking: (ephemeral?: boolean) => Promise; 286 | /** 287 | * Deletes a reply to the Interaction 288 | * 289 | * **Note:** You cannot delete ephemeral messages. 290 | * @arg messageId - The id of the message to delete. If omitted, the original reply message is deleted. 291 | */ 292 | delete: (messageId?: string) => Promise; 293 | ``` 294 | -------------------------------------------------------------------------------- /src/core/InteractionsClient.ts: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | import { 3 | ApplicationCommand, 4 | ApplicationCommandPermissions, 5 | ApplicationOptions, 6 | getCommandsOptions, 7 | GuildApplicationCommandPermissions, 8 | } from "./interfaces"; 9 | 10 | const apiUrl = "https://discord.com/api/v8"; 11 | 12 | export class InteractionsClient { 13 | private token: string; 14 | public clientID: string; 15 | 16 | constructor(token: string, clientID: string) { 17 | if (!token) { 18 | throw new Error("discord-slash-commands-client | No token provided"); 19 | } 20 | if (!clientID) { 21 | throw new Error("discord-slash-commands-client | No clientID provided"); 22 | } 23 | this.token = token; 24 | this.clientID = clientID; 25 | } 26 | 27 | async getCommands( 28 | options?: getCommandsOptions 29 | ): Promise { 30 | if (typeof options !== "object") 31 | throw new Error("options must be of type object. Received: " + typeof options); 32 | 33 | if (options.commandID && typeof options.commandID !== "string") 34 | throw new Error( 35 | "commandID received but wasn't of type string. received: " + 36 | typeof options.commandID 37 | ); 38 | 39 | if (options.guildID && typeof options.guildID !== "string") 40 | throw new Error( 41 | "guildID received but wasn't of type string. received: " + typeof options.guildID 42 | ); 43 | 44 | let url = options.guildID 45 | ? `${apiUrl}/applications/${this.clientID}/guilds/${options.guildID}/commands` 46 | : `${apiUrl}/applications/${this.clientID}/commands`; 47 | 48 | if (options.commandID) url += `/${options.commandID}`; 49 | 50 | const res = await axios.get(url, { 51 | headers: { Authorization: `Bot ${this.token}` }, 52 | }); 53 | 54 | return res.data; 55 | } 56 | 57 | async createCommand( 58 | options: ApplicationOptions, 59 | guildID?: string 60 | ): Promise { 61 | if (typeof options !== "object") 62 | throw new Error("options must be of type object. Received: " + typeof options); 63 | 64 | if (!options.name || !options.description) 65 | throw new Error("options is missing name or description property!"); 66 | 67 | const url = guildID 68 | ? `${apiUrl}/applications/${this.clientID}/guilds/${guildID}/commands` 69 | : `${apiUrl}/applications/${this.clientID}/commands`; 70 | 71 | const res = await axios.post(url, options, { 72 | headers: { Authorization: `Bot ${this.token}` }, 73 | }); 74 | 75 | return res.data; 76 | } 77 | 78 | async editCommand( 79 | options: ApplicationOptions, 80 | commandID: string, 81 | guildID?: string 82 | ): Promise { 83 | if (typeof options !== "object") 84 | throw new Error("options must be of type object. Received: " + typeof options); 85 | 86 | if (typeof commandID !== "string") 87 | throw new Error("commandID must be of type string. Received: " + typeof commandID); 88 | 89 | if (!options.name || !options.description) 90 | throw new Error("options is missing name or description property!"); 91 | 92 | if (guildID && typeof guildID !== "string") 93 | throw new Error( 94 | "guildID received but wasn't of type string. received: " + typeof guildID 95 | ); 96 | 97 | const url = guildID 98 | ? `${apiUrl}/applications/${this.clientID}/guilds/${guildID}/commands/${commandID}` 99 | : `${apiUrl}/applications/${this.clientID}/commands/${commandID}`; 100 | 101 | const res = await axios.patch(url, options, { 102 | headers: { Authorization: `Bot ${this.token}` }, 103 | }); 104 | 105 | return res.data; 106 | } 107 | 108 | async deleteCommand(commandID: string, guildID?: string): Promise { 109 | if (typeof commandID !== "string") 110 | throw new Error("commandID must be of type string. Received: " + typeof commandID); 111 | 112 | const url = guildID 113 | ? `${apiUrl}/applications/${this.clientID}/guilds/${guildID}/commands/${commandID}` 114 | : `${apiUrl}/applications/${this.clientID}/commands/${commandID}`; 115 | 116 | const res = await axios.delete(url, { 117 | headers: { Authorization: `Bot ${this.token}` }, 118 | }); 119 | 120 | return res.data; 121 | } 122 | 123 | async getCommandPermissions( 124 | guildID: string, 125 | commandID?: string 126 | ): Promise { 127 | if (typeof guildID !== "string") 128 | throw new Error("guildID must be of type string. Received: " + typeof guildID); 129 | 130 | if (commandID && typeof commandID !== "string") 131 | throw new Error( 132 | "commandID received but wasn't of type string. received: " + typeof commandID 133 | ); 134 | 135 | const url = commandID 136 | ? `${apiUrl}/applications/${this.clientID}/guilds/${guildID}/commands/${commandID}/permissions` 137 | : `${apiUrl}/applications/${this.clientID}/guilds/${guildID}/commands/permissions`; 138 | 139 | const res = await axios.get(url, { 140 | headers: { Authorization: `Bot ${this.token}` }, 141 | }); 142 | 143 | return res.data; 144 | } 145 | 146 | public async editCommandPermissions( 147 | permissions: ApplicationCommandPermissions[], 148 | guildID: string, 149 | commandID: string 150 | ): Promise { 151 | if (!Array.isArray(permissions)) 152 | throw new Error("permissions must be of type array. Received: " + typeof permissions); 153 | if (typeof guildID !== "string") 154 | throw new Error("guildID must be of type string. Received: " + typeof guildID); 155 | if (typeof commandID !== "string") 156 | throw new Error("commandID must be of type string. Received: " + typeof commandID); 157 | 158 | const url = `${apiUrl}/applications/${this.clientID}/guilds/${guildID}/commands/${commandID}/permissions`; 159 | 160 | const res = await axios.put( 161 | url, 162 | { permissions: permissions }, 163 | { 164 | headers: { Authorization: `Bot ${this.token}` }, 165 | } 166 | ); 167 | 168 | return res.data; 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /src/core/interfaces.ts: -------------------------------------------------------------------------------- 1 | export interface getCommandsOptions { 2 | commandID?: string; 3 | guildID?: string; 4 | } 5 | 6 | // ApplicationCommand https://discord.com/developers/docs/interactions/slash-commands#applicationcommand 7 | export interface ApplicationCommand { 8 | id: string; 9 | application_id: string; 10 | name: string; 11 | description: string; 12 | options?: ApplicationCommandOption[]; 13 | } 14 | 15 | // ApplicationCommandOption https://discord.com/developers/docs/interactions/slash-commands#applicationcommandoption 16 | export interface ApplicationCommandOption { 17 | name: string; 18 | description: string; 19 | type: number; 20 | default?: boolean; 21 | required?: boolean; 22 | choices?: ApplicationCommandOptionChoice[]; 23 | options?: ApplicationCommandOption[]; 24 | } 25 | 26 | // ApplicationCommandOptionType https://discord.com/developers/docs/interactions/slash-commands#applicationcommandoptiontype 27 | 28 | //type ApplicationCommandOptionType = "SUB_COMMAND": 1 | "SUB_COMMAND_GROUP": 2 | "STRING": 3 | "INTEGER": 4 | "BOOLEAN": 5 | "USER": 6 | "CHANNEL": 7 | "ROLE": 8; 29 | export interface ApplicationCommandOptionChoice { 30 | name: string; 31 | value: string; 32 | } 33 | export interface ApplicationOptions { 34 | name: string; 35 | description: string; 36 | options?: ApplicationCommandOption[]; 37 | } 38 | 39 | /** 40 | * Application command permissions allow you to enable or disable commands for specific users or roles within a guild. 41 | * {@link https://discord.com/developers/docs/interactions/slash-commands#applicationcommandpermissions See discord docs} 42 | */ 43 | export interface ApplicationCommandPermissions { 44 | /** Id of the role or user */ 45 | id: string; 46 | 47 | /** The type of permission (1 = Role, 2 = User) */ 48 | type: 1 | 2; 49 | 50 | /** `true` to allow, `false` to disallow */ 51 | permission: boolean; 52 | } 53 | 54 | /** 55 | * Returned when fetching the permissions for a command in a guild. 56 | * {@link https://discord.com/developers/docs/interactions/slash-commands#guildapplicationcommandpermissions See discord docs} 57 | */ 58 | export interface GuildApplicationCommandPermissions { 59 | /** Id of the command */ 60 | id: string; 61 | 62 | /** Id of the application the command belongs to */ 63 | application_id: string; 64 | 65 | /** Id of the guild */ 66 | guild_id: string; 67 | 68 | /** Array of ApplicationCommandPermissions */ 69 | permissions: ApplicationCommandPermissions[]; 70 | } 71 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export { InteractionsClient as Client } from "./core/InteractionsClient"; 2 | export { 3 | ApplicationCommand, 4 | ApplicationCommandOption, 5 | ApplicationCommandOptionChoice, 6 | ApplicationCommandPermissions, 7 | ApplicationOptions, 8 | getCommandsOptions, 9 | GuildApplicationCommandPermissions, 10 | } from "./core/interfaces"; 11 | -------------------------------------------------------------------------------- /tests/main.test.js: -------------------------------------------------------------------------------- 1 | const Discord = require("discord.js"); 2 | const interactions = require("../lib/index"); 3 | 4 | // create a new client 5 | const client = new Discord.Client(); 6 | const token = "NzE0ODEwNTkyNTg5OTA1OTIy.Xs0FPQ.TgCDJpjUwGv_3dVLAVWk0zS_gew"; 7 | 8 | // attach the interaction client to discord.js client 9 | client.interactions = new interactions.Client(token, "714810592589905922"); 10 | 11 | // attach and event listener for the ready event 12 | client.on("ready", () => { 13 | console.log("Client is ready!"); 14 | 15 | // Create a new command that we can test 16 | client.interactions.createCommand().catch(console.error).then(console.log); 17 | }); 18 | 19 | // attach and event listener for the interactionCreate event 20 | client.on("interactionCreate", (interaction) => { 21 | console.log(interaction); 22 | }); 23 | 24 | // login 25 | client.login(token); 26 | -------------------------------------------------------------------------------- /tsconfig-cjs.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "module": "CommonJS", 5 | "outDir": "./lib/cjs" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2015", 4 | "module": "ES2020", 5 | "declaration": true, 6 | "outDir": "./lib/esm", 7 | 8 | "strict": true, 9 | 10 | "esModuleInterop": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "moduleResolution": "node" 13 | }, 14 | "include": ["./src"], 15 | "exclude": ["node_modules", "**/__tests__/*"] 16 | } 17 | --------------------------------------------------------------------------------