diff --git a/Komugari-master/assets/json/actions.json b/Ajuda/Komugari-master/assets/json/actions.json similarity index 99% rename from Komugari-master/assets/json/actions.json rename to Ajuda/Komugari-master/assets/json/actions.json index aa1688f..79b16fd 100644 --- a/Komugari-master/assets/json/actions.json +++ b/Ajuda/Komugari-master/assets/json/actions.json @@ -20,7 +20,6 @@ ], "hugP": [ - "http://i.imgur.com/pZa9Ppe.gif", "http://i.imgur.com/QghzxNa.gif", "http://i.imgur.com/Z5DpKer.gif", "http://i.imgur.com/J9EDW2g.gif", diff --git a/Komugari-master/assets/json/errors.json b/Ajuda/Komugari-master/assets/json/errors.json similarity index 100% rename from Komugari-master/assets/json/errors.json rename to Ajuda/Komugari-master/assets/json/errors.json diff --git a/Komugari-master/assets/json/fortune.json b/Ajuda/Komugari-master/assets/json/fortune.json similarity index 100% rename from Komugari-master/assets/json/fortune.json rename to Ajuda/Komugari-master/assets/json/fortune.json diff --git a/Komugari-master/assets/json/iku.json b/Ajuda/Komugari-master/assets/json/iku.json similarity index 100% rename from Komugari-master/assets/json/iku.json rename to Ajuda/Komugari-master/assets/json/iku.json diff --git a/Komugari-master/assets/json/kaomoji.json b/Ajuda/Komugari-master/assets/json/kaomoji.json similarity index 100% rename from Komugari-master/assets/json/kaomoji.json rename to Ajuda/Komugari-master/assets/json/kaomoji.json diff --git a/Komugari-master/assets/json/pasta.json b/Ajuda/Komugari-master/assets/json/pasta.json similarity index 100% rename from Komugari-master/assets/json/pasta.json rename to Ajuda/Komugari-master/assets/json/pasta.json diff --git a/Komugari-master/assets/json/permissions.json b/Ajuda/Komugari-master/assets/json/permissions.json similarity index 100% rename from Komugari-master/assets/json/permissions.json rename to Ajuda/Komugari-master/assets/json/permissions.json diff --git a/Komugari-master/assets/json/pickuplines.json b/Ajuda/Komugari-master/assets/json/pickuplines.json similarity index 100% rename from Komugari-master/assets/json/pickuplines.json rename to Ajuda/Komugari-master/assets/json/pickuplines.json diff --git a/Komugari-master/assets/json/rightthere.json b/Ajuda/Komugari-master/assets/json/rightthere.json similarity index 100% rename from Komugari-master/assets/json/rightthere.json rename to Ajuda/Komugari-master/assets/json/rightthere.json diff --git a/Komugari-master/assets/json/skyrim.json b/Ajuda/Komugari-master/assets/json/skyrim.json similarity index 100% rename from Komugari-master/assets/json/skyrim.json rename to Ajuda/Komugari-master/assets/json/skyrim.json diff --git a/Komugari-master/assets/json/waifus.json b/Ajuda/Komugari-master/assets/json/waifus.json similarity index 100% rename from Komugari-master/assets/json/waifus.json rename to Ajuda/Komugari-master/assets/json/waifus.json diff --git a/Komugari-master/commands/README.md b/Ajuda/Komugari-master/commands/README.md similarity index 100% rename from Komugari-master/commands/README.md rename to Ajuda/Komugari-master/commands/README.md diff --git a/Komugari-master/commands/action/cry.js b/Ajuda/Komugari-master/commands/action/cry.js similarity index 100% rename from Komugari-master/commands/action/cry.js rename to Ajuda/Komugari-master/commands/action/cry.js diff --git a/Komugari-master/commands/action/disgust.js b/Ajuda/Komugari-master/commands/action/disgust.js similarity index 100% rename from Komugari-master/commands/action/disgust.js rename to Ajuda/Komugari-master/commands/action/disgust.js diff --git a/Komugari-master/commands/action/grope.js b/Ajuda/Komugari-master/commands/action/grope.js similarity index 100% rename from Komugari-master/commands/action/grope.js rename to Ajuda/Komugari-master/commands/action/grope.js diff --git a/Komugari-master/commands/action/hand.js b/Ajuda/Komugari-master/commands/action/hand.js similarity index 100% rename from Komugari-master/commands/action/hand.js rename to Ajuda/Komugari-master/commands/action/hand.js diff --git a/Komugari-master/commands/action/hug.js b/Ajuda/Komugari-master/commands/action/hug.js similarity index 100% rename from Komugari-master/commands/action/hug.js rename to Ajuda/Komugari-master/commands/action/hug.js diff --git a/Komugari-master/commands/action/kiss.js b/Ajuda/Komugari-master/commands/action/kiss.js similarity index 100% rename from Komugari-master/commands/action/kiss.js rename to Ajuda/Komugari-master/commands/action/kiss.js diff --git a/Komugari-master/commands/action/lewd.js b/Ajuda/Komugari-master/commands/action/lewd.js similarity index 100% rename from Komugari-master/commands/action/lewd.js rename to Ajuda/Komugari-master/commands/action/lewd.js diff --git a/Komugari-master/commands/action/lick.js b/Ajuda/Komugari-master/commands/action/lick.js similarity index 100% rename from Komugari-master/commands/action/lick.js rename to Ajuda/Komugari-master/commands/action/lick.js diff --git a/Komugari-master/commands/action/nobully.js b/Ajuda/Komugari-master/commands/action/nobully.js similarity index 100% rename from Komugari-master/commands/action/nobully.js rename to Ajuda/Komugari-master/commands/action/nobully.js diff --git a/Komugari-master/commands/action/nom.js b/Ajuda/Komugari-master/commands/action/nom.js similarity index 100% rename from Komugari-master/commands/action/nom.js rename to Ajuda/Komugari-master/commands/action/nom.js diff --git a/Komugari-master/commands/action/noswearing.js b/Ajuda/Komugari-master/commands/action/noswearing.js similarity index 100% rename from Komugari-master/commands/action/noswearing.js rename to Ajuda/Komugari-master/commands/action/noswearing.js diff --git a/Komugari-master/commands/action/nyan.js b/Ajuda/Komugari-master/commands/action/nyan.js similarity index 100% rename from Komugari-master/commands/action/nyan.js rename to Ajuda/Komugari-master/commands/action/nyan.js diff --git a/Komugari-master/commands/action/owo.js b/Ajuda/Komugari-master/commands/action/owo.js similarity index 100% rename from Komugari-master/commands/action/owo.js rename to Ajuda/Komugari-master/commands/action/owo.js diff --git a/Komugari-master/commands/action/pat.js b/Ajuda/Komugari-master/commands/action/pat.js similarity index 100% rename from Komugari-master/commands/action/pat.js rename to Ajuda/Komugari-master/commands/action/pat.js diff --git a/Komugari-master/commands/action/pout.js b/Ajuda/Komugari-master/commands/action/pout.js similarity index 100% rename from Komugari-master/commands/action/pout.js rename to Ajuda/Komugari-master/commands/action/pout.js diff --git a/Komugari-master/commands/action/slap.js b/Ajuda/Komugari-master/commands/action/slap.js similarity index 100% rename from Komugari-master/commands/action/slap.js rename to Ajuda/Komugari-master/commands/action/slap.js diff --git a/Komugari-master/commands/action/smug.js b/Ajuda/Komugari-master/commands/action/smug.js similarity index 100% rename from Komugari-master/commands/action/smug.js rename to Ajuda/Komugari-master/commands/action/smug.js diff --git a/Komugari-master/commands/action/stare.js b/Ajuda/Komugari-master/commands/action/stare.js similarity index 100% rename from Komugari-master/commands/action/stare.js rename to Ajuda/Komugari-master/commands/action/stare.js diff --git a/Komugari-master/commands/action/tickle.js b/Ajuda/Komugari-master/commands/action/tickle.js similarity index 100% rename from Komugari-master/commands/action/tickle.js rename to Ajuda/Komugari-master/commands/action/tickle.js diff --git a/Komugari-master/commands/action/wasted.js b/Ajuda/Komugari-master/commands/action/wasted.js similarity index 100% rename from Komugari-master/commands/action/wasted.js rename to Ajuda/Komugari-master/commands/action/wasted.js diff --git a/Komugari-master/commands/action/wink.js b/Ajuda/Komugari-master/commands/action/wink.js similarity index 100% rename from Komugari-master/commands/action/wink.js rename to Ajuda/Komugari-master/commands/action/wink.js diff --git a/Komugari-master/commands/fun/advice.js b/Ajuda/Komugari-master/commands/fun/advice.js similarity index 100% rename from Komugari-master/commands/fun/advice.js rename to Ajuda/Komugari-master/commands/fun/advice.js diff --git a/Komugari-master/commands/fun/dadjoke.js b/Ajuda/Komugari-master/commands/fun/dadjoke.js similarity index 100% rename from Komugari-master/commands/fun/dadjoke.js rename to Ajuda/Komugari-master/commands/fun/dadjoke.js diff --git a/Komugari-master/commands/fun/fortune.js b/Ajuda/Komugari-master/commands/fun/fortune.js similarity index 100% rename from Komugari-master/commands/fun/fortune.js rename to Ajuda/Komugari-master/commands/fun/fortune.js diff --git a/Komugari-master/commands/fun/garfield.js b/Ajuda/Komugari-master/commands/fun/garfield.js similarity index 100% rename from Komugari-master/commands/fun/garfield.js rename to Ajuda/Komugari-master/commands/fun/garfield.js diff --git a/Komugari-master/commands/fun/giphy.js b/Ajuda/Komugari-master/commands/fun/giphy.js similarity index 100% rename from Komugari-master/commands/fun/giphy.js rename to Ajuda/Komugari-master/commands/fun/giphy.js diff --git a/Komugari-master/commands/fun/kaomoji.js b/Ajuda/Komugari-master/commands/fun/kaomoji.js similarity index 100% rename from Komugari-master/commands/fun/kaomoji.js rename to Ajuda/Komugari-master/commands/fun/kaomoji.js diff --git a/Komugari-master/commands/fun/pasta.js b/Ajuda/Komugari-master/commands/fun/pasta.js similarity index 100% rename from Komugari-master/commands/fun/pasta.js rename to Ajuda/Komugari-master/commands/fun/pasta.js diff --git a/Komugari-master/commands/fun/pickup.js b/Ajuda/Komugari-master/commands/fun/pickup.js similarity index 100% rename from Komugari-master/commands/fun/pickup.js rename to Ajuda/Komugari-master/commands/fun/pickup.js diff --git a/Komugari-master/commands/fun/rightthere.js b/Ajuda/Komugari-master/commands/fun/rightthere.js similarity index 100% rename from Komugari-master/commands/fun/rightthere.js rename to Ajuda/Komugari-master/commands/fun/rightthere.js diff --git a/Komugari-master/commands/fun/skyrim.js b/Ajuda/Komugari-master/commands/fun/skyrim.js similarity index 100% rename from Komugari-master/commands/fun/skyrim.js rename to Ajuda/Komugari-master/commands/fun/skyrim.js diff --git a/Komugari-master/commands/info/avatar.js b/Ajuda/Komugari-master/commands/info/avatar.js similarity index 100% rename from Komugari-master/commands/info/avatar.js rename to Ajuda/Komugari-master/commands/info/avatar.js diff --git a/Komugari-master/commands/info/role.js b/Ajuda/Komugari-master/commands/info/role.js similarity index 100% rename from Komugari-master/commands/info/role.js rename to Ajuda/Komugari-master/commands/info/role.js diff --git a/Komugari-master/commands/moderation/lockdown.js b/Ajuda/Komugari-master/commands/moderation/lockdown.js similarity index 100% rename from Komugari-master/commands/moderation/lockdown.js rename to Ajuda/Komugari-master/commands/moderation/lockdown.js diff --git a/Komugari-master/commands/utility/color.js b/Ajuda/Komugari-master/commands/utility/color.js similarity index 100% rename from Komugari-master/commands/utility/color.js rename to Ajuda/Komugari-master/commands/utility/color.js diff --git a/Komugari-master/commands/utility/jisho.js b/Ajuda/Komugari-master/commands/utility/jisho.js similarity index 100% rename from Komugari-master/commands/utility/jisho.js rename to Ajuda/Komugari-master/commands/utility/jisho.js diff --git a/Komugari-master/commands/utility/remindme.js b/Ajuda/Komugari-master/commands/utility/remindme.js similarity index 100% rename from Komugari-master/commands/utility/remindme.js rename to Ajuda/Komugari-master/commands/utility/remindme.js diff --git a/Komugari-master/commands/utility/steam.js b/Ajuda/Komugari-master/commands/utility/steam.js similarity index 100% rename from Komugari-master/commands/utility/steam.js rename to Ajuda/Komugari-master/commands/utility/steam.js diff --git a/Komugari-master/commands/utility/temperature.js b/Ajuda/Komugari-master/commands/utility/temperature.js similarity index 100% rename from Komugari-master/commands/utility/temperature.js rename to Ajuda/Komugari-master/commands/utility/temperature.js diff --git a/Komugari-master/commands/utility/time.js b/Ajuda/Komugari-master/commands/utility/time.js similarity index 100% rename from Komugari-master/commands/utility/time.js rename to Ajuda/Komugari-master/commands/utility/time.js diff --git a/Komugari-master/commands/utility/weather.js b/Ajuda/Komugari-master/commands/utility/weather.js similarity index 100% rename from Komugari-master/commands/utility/weather.js rename to Ajuda/Komugari-master/commands/utility/weather.js diff --git a/Ajuda/guide-master/.circleci/config.yml b/Ajuda/guide-master/.circleci/config.yml deleted file mode 100644 index 089d77e..0000000 --- a/Ajuda/guide-master/.circleci/config.yml +++ /dev/null @@ -1,39 +0,0 @@ -# Javascript Node CircleCI 2.0 configuration file -# -# Check https://circleci.com/docs/2.0/language-javascript/ for more details -# -version: 2 -jobs: - build: - docker: - # specify the version you desire here - - image: circleci/node:8.10 - - # Specify service dependencies here if necessary - # CircleCI maintains a library of pre-built images - # documented at https://circleci.com/docs/2.0/circleci-images/ - # - image: circleci/mongo:3.4.4 - - working_directory: ~/guide - - steps: - - checkout - - # Download and cache dependencies - - restore_cache: - name: Restore Yarn Package Cache - keys: - - yarn-packages-{{ checksum "yarn.lock" }} - - - run: - name: Install Dependencies - command: yarn install - - - save_cache: - name: Save Yarn Package Cache - key: yarn-packages-{{ checksum "yarn.lock" }} - paths: - - ~/.cache/yarn - - # run tests! - - run: yarn lint diff --git a/Ajuda/guide-master/.editorconfig b/Ajuda/guide-master/.editorconfig deleted file mode 100644 index 2d120e1..0000000 --- a/Ajuda/guide-master/.editorconfig +++ /dev/null @@ -1,11 +0,0 @@ -root = true - -[*.{css,js,jsx,md,scss,ts,tsx,vue}] -end_of_line = lf -indent_size = 4 -indent_style = tab -insert_final_newline = true -trim_trailing_whitespace = true - -[*.md] -trim_trailing_whitespace = false diff --git a/Ajuda/guide-master/.eslintignore b/Ajuda/guide-master/.eslintignore deleted file mode 100644 index 198b9c5..0000000 --- a/Ajuda/guide-master/.eslintignore +++ /dev/null @@ -1,2 +0,0 @@ -!/guide/.vuepress -guide/.vuepress/dist diff --git a/Ajuda/guide-master/.eslintrc.js b/Ajuda/guide-master/.eslintrc.js deleted file mode 100644 index 9d9f39d..0000000 --- a/Ajuda/guide-master/.eslintrc.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - extends: 'sora/vue', - plugins: ['markdown'], -}; diff --git a/Ajuda/guide-master/.github/ISSUE_TEMPLATE/branching-content.md b/Ajuda/guide-master/.github/ISSUE_TEMPLATE/branching-content.md deleted file mode 100644 index 0952512..0000000 --- a/Ajuda/guide-master/.github/ISSUE_TEMPLATE/branching-content.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -name: Branching Content -about: Content is missing for a certain version and requires branching sections - or code samples -labels: 'type: enhancement','meta: branching' - ---- - -**Part of the guide or code sample that needs a branching update** - - -**Additional notes** - \ No newline at end of file diff --git a/Ajuda/guide-master/.github/ISSUE_TEMPLATE/bug_report.md b/Ajuda/guide-master/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index c610f49..0000000 --- a/Ajuda/guide-master/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve -labels: 'type: bug' - ---- - -**Describe the bug** - - -**To Reproduce** - - -**Screenshots** - - -**Device (please complete the following information):** - - -**Additional notes** - \ No newline at end of file diff --git a/Ajuda/guide-master/.github/ISSUE_TEMPLATE/config.yml b/Ajuda/guide-master/.github/ISSUE_TEMPLATE/config.yml deleted file mode 100644 index e2f857b..0000000 --- a/Ajuda/guide-master/.github/ISSUE_TEMPLATE/config.yml +++ /dev/null @@ -1,8 +0,0 @@ -blank_issues_enabled: false -contact_links: - - name: discord.js discord server - url: https://discord.gg/bRCvFy9 - about: Please use this Discord Server to ask questions and get support on discord.js. We don't typically answer questions here and they will likely be closed and redirected to the Discord server. - - name: discord.js Github repository issues page - url: https://github.com/discordjs/discord.js/issues/new/choose - about: Please use this issue tracker to suggest new features and/or report bugs about discord.js itself. diff --git a/Ajuda/guide-master/.github/ISSUE_TEMPLATE/feature_request.md b/Ajuda/guide-master/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index d7d45b4..0000000 --- a/Ajuda/guide-master/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for this project -labels: 'type: request/suggestion' - ---- - -**Is your feature request related to a problem? Please describe.** - - -**Describe the solution you'd like** - - -**Describe alternatives you've considered** - - -**Additional notes** - \ No newline at end of file diff --git a/Ajuda/guide-master/.github/ISSUE_TEMPLATE/question.md b/Ajuda/guide-master/.github/ISSUE_TEMPLATE/question.md deleted file mode 100644 index a33337d..0000000 --- a/Ajuda/guide-master/.github/ISSUE_TEMPLATE/question.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -name: Question/General support request -about: This template is for asking questions about the guide. -labels: 'type: question' ---- - - - -**Part of the guide or code sample the question is about** - - -**Question** - diff --git a/Ajuda/guide-master/.github/PULL_REQUEST_TEMPLATE/bug_fix.md b/Ajuda/guide-master/.github/PULL_REQUEST_TEMPLATE/bug_fix.md deleted file mode 100644 index 8ec45ce..0000000 --- a/Ajuda/guide-master/.github/PULL_REQUEST_TEMPLATE/bug_fix.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -name: Bug fix -about: Fixed a bug -labels: 'type: bug fix' - ---- - -**Describe the bug** - - -**Additional notes** - \ No newline at end of file diff --git a/Ajuda/guide-master/.github/PULL_REQUEST_TEMPLATE/typo_fix.md b/Ajuda/guide-master/.github/PULL_REQUEST_TEMPLATE/typo_fix.md deleted file mode 100644 index 0fc00bd..0000000 --- a/Ajuda/guide-master/.github/PULL_REQUEST_TEMPLATE/typo_fix.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -name: Typo fix -about: Fixed a typo -labels: 'type: spelling/grammar' - ---- - -**Spelling/Grammar fix** -**This Pull Request does not include any semantical changes** \ No newline at end of file diff --git a/Ajuda/guide-master/.gitignore b/Ajuda/guide-master/.gitignore deleted file mode 100644 index 84160b5..0000000 --- a/Ajuda/guide-master/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -node_modules -guide/.vuepress/dist diff --git a/Ajuda/guide-master/CONTRIBUTING.md b/Ajuda/guide-master/CONTRIBUTING.md deleted file mode 100644 index 8962de5..0000000 --- a/Ajuda/guide-master/CONTRIBUTING.md +++ /dev/null @@ -1,280 +0,0 @@ -# Contributing - -## Local development - -Clone the repo into your desired folder, `cd` into it, and install the dependencies. - -```bash -git clone https://github.com/discordjs/guide.git -cd guide -yarn # or npm install -``` - -You should install the necessary dev dependencies afterwards, so that view the site locally. You can use `yarn serve` to open up a local version of the site at http://localhost:8080. If you need to use a different port, run it as `yarn serve --port=1234`. - -### Linting - -Remember to always lint your edits/additions before making a commit to ensure everything's lined up and consistent with the rest of the guide. We use ESLint and have a package.json script for linting both JS files and JS codeblocks inside Markdown files. Just install the dependencies and run the lint script. - -```bash -yarn -yarn lint -``` - -#### Caveats - -There might come a time where a snippet will contain a parse error, and ESLint won't be able to lint it properly. For example: - - - -```js -const sent = await message.channel.send('Hi!'); -console.log(sent.content) -``` - -ESLint would error with `Parsing error: Unexpected token message` instead of letting you know that you're missing a semicolon. In this case, it's because of the use of `await` outside of an async function. In situations like this, after you've fixed any obvious errors, you can add an `` comment above the codeblock to have it ignored entirely by ESLint when running the lint script. - -## Adding pages - -To add a new page to the guide, create a `file-name.md` file inside the folder of your choice. If you want to link to `/dir/some-tutorial.html`, you would create a `some-tutorial.md` file inside a `dir` folder. [VuePress](https://github.com/vuejs/vuepress) will pick up on it and set up the routing appropriately. - -With that being said, you will still need to add the link to the sidebar manually. Go to the `/guide/.vuepress/sidebar.js` file and insert a new item with the path to your newly created page. - -## General guidelines - -Because we want to keep everything as consistent and clean as possible, here are some guidelines we strongly recommend you try to follow when making a contribution. - -### Spelling, grammar, and wording - -Improper grammar, strange wording, and incorrect spelling are all things that may lead to confusion when a user reads a guide page. It's very important to attempt to keep the content clear and concise. Re-read what you've written and place yourself in the shoes of someone else for a moment to see if you can fully understand everything without any confusion. - -Don't worry if you aren't super confident with your grammar/spelling/wording skills; all pull requests get thoroughly reviewed, and comments are left in areas that need to be fixed or could be done better/differently. - -#### "You"/"your" instead of "we"/"our" - -When explaining parts of a guide, it'd recommended to use "you" instead of "we" in most situations. For example: - -```diff -- To check our Node version, we can run `node -v`. -+ To check your Node version, you can run `node -v`. - -- To delete a message, we can do: `message.delete();` -+ To delete a message, you can do: `message.delete();` - -- Our final code should look like this: ... -+ Your final code should look like this: ... - -- Before we can actually do this, we need to update our configuration file. -+ Before you can actually do this, you need to update your configuration file. -``` - -#### "We" instead of "I" - -When refering to yourself, use "we" (as in "the writers of this guide") instead of "I". For example: - -```diff -- If you don't already have this package installed, I would highly recommend doing so. -+ If you don't already have this package installed, we would highly recommend doing so. -# Valid alternative: -+ If you don't already have this package installed, it's highly recommended that you do so. - -- In this section, I'll be covering how to do that really cool thing everyone's asking about. -+ In this section, we'll be covering how to do that really cool thing everyone's asking about. -``` - -### Paragraph structure - -Tied in with the section above, try to keep things as neatly formatted as possible! If a paragraph gets long, split it up into multiple paragraphs so that it adds some spacing and is easier on the eyes. - -#### Tips, warnings, and danger messages - -If you have a tip to share with to user, you can format them in a specific way so that it looks appealing and noticable. The same goes for warning and "danger" messages. - -```md -In this section, we'll be doing some stuff! - -::: tip -You can do this stuff even faster if you do this cool thing listed in this tip! -::: - -::: warning -Make sure you're on version 2.0.0 or above before trying this. -::: - -::: danger -Be careful; this action is irreversible! -::: -``` - -![Utility tags preview](https://i.imgur.com/CnzVBmr.png) - -### General styling - -#### Spacing between entities - -Even though this generally does not affect the actual output, you should space out your entities with a single blank line between them; it keeps the source code clean and easier to read. For example: - -```md -## Section title - -Here's an example of how you'd do that really cool thing: - -```js -const { data } = request; -console.log(data); -`​`` - -And here's a sentence that would explain how that works, maybe. - -::: tip -Here's where you'd tell them something even cooler than the really cool thing they just learned. -::: - -::: warning -This is where you'd warn them about the possible issues that arise when using this method. -::: -``` - -#### Headers and sidebar links - -Section headers and sidebar links should generally be short and right to the point. In terms of casing, it should be cased as if it were a regular sentence. - -```diff -# Assuming the page is titled "Embeds" -- ## How To Make Inline Fields In An Embed -+ ## Inline fields - -# Assuming the page is titled "Webhooks" -- ## Setting An Avatar On Your Webhook Client -+ ## Setting an avatar -``` - -#### References to code - -When making references to pieces of code (e.g. variables, properties, etc.), place those references inside backticks. For example: - -```md -After accessing the `icon` property off of the `data` object, you can send that as a file to Discord. - ---- - -If you want to change your bot's username username, you can use the `ClientUser#setUsername` method. -``` - -References to class names should be capitalized, but remain outside of backticks. For example: - -```md -Since `guild.members` returns a Collection, we can interate over it with `.forEach()` or a `for ... of` loop. - ---- - -Since the `.delete()` method returns a Promise, we need to `await` it when inside a `try`/`catch` block. -``` - -### Images and links - -If you want to include an image in a page, the image you add should be saved to the repo itself instead of using external services. If you want to link to other sections of the guide, be sure to use relative paths instead of full URLs to the live site. For example: - -```diff -- Here's what the final result would look like: -- -- ![Final result](https://i.imgur.com/78fcCsF.png) -- -- If you want to read more about this, you can check out the page on [that other cool stuff](https://discordjs.guide/#/some-really-cool-stuff). - -+ Here's what the final result would look like: -+ -+ ![Final result](~@/images/78fcCsF.png) -+ -+ If you want to read more about this, you can check out the page on [that other cool stuff](/some-really-cool-stuff). -``` - -Do note the `~@/images/*` syntax used. The `~@/` part is a shortcut to the base `/guide` directory, which holds all the .md files and the `/images` folder. When it comes to images, this syntax should always be used. - -### Code samples - -If you're writing a page that teaches the reader how to build something step-by-step, make sure to include the final piece of code in a file inside the `/code-samples` directory. The folder destination inside the `/code-samples` folder should match the destination inside the `/guide` folder. For example: `guide/foo/bar.md` -> `code-samples/foo/bar/index.js`. - -```md - -## Resulting code - - - -``` - -This will automatically generate the link to the proper directory on GitHub for that specific page. Should you need to overwrite the path, you can do so: - -```md - -## Resulting code - - - - - - -``` - -### Faking Discord messages - -We have some useful custom helper components that you can use to "fake" Discord message. The reason for this is to make it easy for you to create, easy for anyone in the future to edit, and avoid having to take screenshots and using too many images on a page at once. Here's a preview of the components: - -![Discord message faker preview](https://i.imgur.com/1qZodqm.png) - -The syntax to make this display is quite simple as well: - -```html -
- - !ping - - - Pong! Took 250ms - -
-``` - -The `author` and `avatar` attributes must be strings, and the `bot` attribute must be a boolean. Do note the colon in `:bot="true"`. These components are made with Vue, but if you aren't familiar with Vue, don't worry about it. Just understand that this allows us to pass in the actual boolean `true` and not the string `'true'`. All `` tags must be children of a single `
` tag for it to display properly. - -Do note the `
` syntax instead of ``. This is due to how VuePress renders markdown and HTML inside markdown files and doesn't recognize `` as an HTML element, therefore rendering anything indented inside as a regular codeblock. - -You can read more about how to use these components by checking out [the package's GitHub repo](https://github.com/Danktuary/vue-discord-message). - -### Branch-specific content - -On some pages, you'll want to display content that applies only to the stable branch and other content that applies to a different branch. You can use the `` component inside any .md file like so: - -```md -You can use -`message.channel.fetchMessages()` -`message.channel.messages.fetch()` -to fetch all messages in a channel -``` - -If you're on the `11.x` branch, you'd see "You can use `message.channel.fetchMessages()` to fetch all messages in a channel. Use the `inline` attribute to make content display inline with the content around it. Otherwise, it'll be displayed on its own line. - -You can refer to the `guide/.vuepress/branches.js` file to see which values are valid to use for the `version` attribute. - -#### Codeblocks and other markdown - -A common use-case for this component would be with codeblocks. Using Vue components inside markdown can get tricky and cause weird errors, so in order for everything to render properly, an extra blank line should be added before and after the component tag. For example (ignoring the `\` before the backticks): - -```md -You can use the following to fetch all messages in a channel: - - - -\```js -message.channel.fetchMessages(); -\``` - - - - -\```js -message.channel.messages.fetch(); -\``` - - -``` diff --git a/Ajuda/guide-master/README.md b/Ajuda/guide-master/README.md deleted file mode 100644 index 54eecfe..0000000 --- a/Ajuda/guide-master/README.md +++ /dev/null @@ -1,24 +0,0 @@ -
- Discord.js Guide -
- -# Discord.js Guide - -The official guide for [discord.js](https://github.com/discordjs/discord.js), created and maintained by core members of its community and contributed to by [various others](https://github.com/discordjs/guide/graphs/contributors?type=a). - -## About - -This guide is aimed at users who are either unfamiliar or inexperienced with Node.js and creating Discord bots. It assumes you have a basic understanding of JavaScript. - -There are many different subjects covered, such as: - -- How to get a bot [up and running](https://discordjs.guide/#/preparations/) from scratch; -- How to properly [create](https://discordjs.guide/#/creating-your-bot/), [organize](https://discordjs.guide/#/command-handling/), and [expand](https://discordjs.guide/#/command-handling/adding-features) on your commands; -- In-depth explanations and examples regarding popular topics (e.g. [reactions](https://discordjs.guide/#/popular-topics/reactions), [embeds](https://discordjs.guide/#/popular-topics/embeds), [canvas](https://discordjs.guide/#/popular-topics/canvas)); -- Working with databases (e.g. [sequelize](https://discordjs.guide/#/sequelize/) and [keyv](https://discordjs.guide/#/keyv/)); -- Getting started with [sharding](https://discordjs.guide/#/sharding/); -- And much more. - -## Contributing - -If you're interested in contributing to the guide, you should check out our [GitHub Projects](https://github.com/discordjs/guide/projects) page or [open issues](https://github.com/discordjs/guide/issues). There's a [contribution guide](https://github.com/discordjs/guide/blob/master/CONTRIBUTING.md) you should read once you decide on what you want to contribute. diff --git a/Ajuda/guide-master/code-samples/.eslintrc.js b/Ajuda/guide-master/code-samples/.eslintrc.js deleted file mode 100644 index cea0fd9..0000000 --- a/Ajuda/guide-master/code-samples/.eslintrc.js +++ /dev/null @@ -1,8 +0,0 @@ -const path = require('path'); - -module.exports = { - extends: path.join(__dirname, '..', '.eslintrc.js'), - env: { - node: true, - }, -}; diff --git a/Ajuda/guide-master/code-samples/additional-info/rest-api/11/index.js b/Ajuda/guide-master/code-samples/additional-info/rest-api/11/index.js deleted file mode 100644 index cf5d200..0000000 --- a/Ajuda/guide-master/code-samples/additional-info/rest-api/11/index.js +++ /dev/null @@ -1,51 +0,0 @@ -const Discord = require('discord.js'); -const fetch = require('node-fetch'); -const querystring = require('querystring'); - -const client = new Discord.Client(); -const prefix = '!'; - -const trim = (str, max) => str.length > max ? `${str.slice(0, max - 3)}...` : str; - -client.once('ready', () => { - console.log('Ready!'); -}); - -client.on('message', async message => { - if (!message.content.startsWith(prefix) || message.author.bot) return; - - const args = message.content.slice(prefix.length).split(/ +/); - const command = args.shift().toLowerCase(); - - if (command === 'cat') { - const { file } = await fetch('https://aws.random.cat/meow').then(response => response.json()); - - message.channel.send(file); - } else if (command === 'urban') { - if (!args.length) { - return message.channel.send('You need to supply a search term!'); - } - - const query = querystring.stringify({ term: args.join(' ') }); - - const { list } = await fetch(`https://api.urbandictionary.com/v0/define?${query}`).then(response => response.json()); - - if (!list.length) { - return message.channel.send(`No results found for **${args.join(' ')}**.`); - } - - const [answer] = list; - - const embed = new Discord.RichEmbed() - .setColor('#EFFF00') - .setTitle(answer.word) - .setURL(answer.permalink) - .addField('Definition', trim(answer.definition, 1024)) - .addField('Example', trim(answer.example, 1024)) - .addField('Rating', `${answer.thumbs_up} thumbs up. ${answer.thumbs_down} thumbs down.`); - - message.channel.send(embed); - } -}); - -client.login('your-token-goes-here'); diff --git a/Ajuda/guide-master/code-samples/additional-info/rest-api/12/index.js b/Ajuda/guide-master/code-samples/additional-info/rest-api/12/index.js deleted file mode 100644 index aa52d6a..0000000 --- a/Ajuda/guide-master/code-samples/additional-info/rest-api/12/index.js +++ /dev/null @@ -1,51 +0,0 @@ -const Discord = require('discord.js'); -const fetch = require('node-fetch'); -const querystring = require('querystring'); - -const client = new Discord.Client(); -const prefix = '!'; - -const trim = (str, max) => (str.length > max ? `${str.slice(0, max - 3)}...` : str); - -client.once('ready', () => { - console.log('Ready!'); -}); - -client.on('message', async message => { - if (!message.content.startsWith(prefix) || message.author.bot) return; - - const args = message.content.slice(prefix.length).split(/ +/); - const command = args.shift().toLowerCase(); - - if (command === 'cat') { - const { file } = await fetch('https://aws.random.cat/meow').then(response => response.json()); - - message.channel.send(file); - } else if (command === 'urban') { - if (!args.length) { - return message.channel.send('You need to supply a search term!'); - } - - const query = querystring.stringify({ term: args.join(' ') }); - - const { list } = await fetch(`https://api.urbandictionary.com/v0/define?${query}`).then(response => response.json()); - - if (!list.length) { - return message.channel.send(`No results found for **${args.join(' ')}**.`); - } - - const [answer] = list; - - const embed = new Discord.MessageEmbed() - .setColor('#EFFF00') - .setTitle(answer.word) - .setURL(answer.permalink) - .addField('Definition', trim(answer.definition, 1024)) - .addField('Example', trim(answer.example, 1024)) - .addField('Rating', `${answer.thumbs_up} thumbs up. ${answer.thumbs_down} thumbs down.`); - - message.channel.send(embed); - } -}); - -client.login('your-token-goes-here'); diff --git a/Ajuda/guide-master/code-samples/command-handling/adding-features/11/commands/args-info.js b/Ajuda/guide-master/code-samples/command-handling/adding-features/11/commands/args-info.js deleted file mode 100644 index 289f544..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/adding-features/11/commands/args-info.js +++ /dev/null @@ -1,12 +0,0 @@ -module.exports = { - name: 'args-info', - description: 'Information about the arguments provided.', - args: true, - execute(message, args) { - if (args[0] === 'foo') { - return message.channel.send('bar'); - } - - message.channel.send(`First argument: ${args[0]}`); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/adding-features/11/commands/avatar.js b/Ajuda/guide-master/code-samples/command-handling/adding-features/11/commands/avatar.js deleted file mode 100644 index c213c3c..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/adding-features/11/commands/avatar.js +++ /dev/null @@ -1,16 +0,0 @@ -module.exports = { - name: 'avatar', - description: 'Get the avatar URL of the tagged user(s), or your own avatar.', - aliases: ['icon', 'pfp'], - execute(message) { - if (!message.mentions.users.size) { - return message.channel.send(`Your avatar: <${message.author.displayAvatarURL}>`); - } - - const avatarList = message.mentions.users.map(user => { - return `${user.username}'s avatar: <${user.displayAvatarURL}>`; - }); - - message.channel.send(avatarList); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/adding-features/11/commands/beep.js b/Ajuda/guide-master/code-samples/command-handling/adding-features/11/commands/beep.js deleted file mode 100644 index e3345e9..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/adding-features/11/commands/beep.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = { - name: 'beep', - description: 'Beep!', - execute(message) { - message.channel.send('Boop.'); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/adding-features/11/commands/help.js b/Ajuda/guide-master/code-samples/command-handling/adding-features/11/commands/help.js deleted file mode 100644 index 1f08793..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/adding-features/11/commands/help.js +++ /dev/null @@ -1,46 +0,0 @@ -const { prefix } = require('../config.json'); - -module.exports = { - name: 'help', - description: 'List all of my commands or info about a specific command.', - aliases: ['commands'], - usage: '[command name]', - cooldown: 5, - execute(message, args) { - const data = []; - const { commands } = message.client; - - if (!args.length) { - data.push('Here\'s a list of all my commands:'); - data.push(commands.map(command => command.name).join(', ')); - data.push(`\nYou can send \`${prefix}help [command name]\` to get info on a specific command!`); - - return message.author.send(data, { split: true }) - .then(() => { - if (message.channel.type === 'dm') return; - message.reply('I\'ve sent you a DM with all my commands!'); - }) - .catch(error => { - console.error(`Could not send help DM to ${message.author.tag}.\n`, error); - message.reply('it seems like I can\'t DM you!'); - }); - } - - const name = args[0].toLowerCase(); - const command = commands.get(name) || commands.find(c => c.aliases && c.aliases.includes(name)); - - if (!command) { - return message.reply('that\'s not a valid command!'); - } - - data.push(`**Name:** ${command.name}`); - - if (command.aliases) data.push(`**Aliases:** ${command.aliases.join(', ')}`); - if (command.description) data.push(`**Description:** ${command.description}`); - if (command.usage) data.push(`**Usage:** ${prefix}${command.name} ${command.usage}`); - - data.push(`**Cooldown:** ${command.cooldown || 3} second(s)`); - - message.channel.send(data, { split: true }); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/adding-features/11/commands/kick.js b/Ajuda/guide-master/code-samples/command-handling/adding-features/11/commands/kick.js deleted file mode 100644 index 8428e8d..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/adding-features/11/commands/kick.js +++ /dev/null @@ -1,14 +0,0 @@ -module.exports = { - name: 'kick', - description: 'Tag a member and kick them (but not really).', - guildOnly: true, - execute(message) { - if (!message.mentions.users.size) { - return message.reply('you need to tag a user in order to kick them!'); - } - - const taggedUser = message.mentions.users.first(); - - message.channel.send(`You wanted to kick: ${taggedUser.username}`); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/adding-features/11/commands/ping.js b/Ajuda/guide-master/code-samples/command-handling/adding-features/11/commands/ping.js deleted file mode 100644 index 8e6810f..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/adding-features/11/commands/ping.js +++ /dev/null @@ -1,8 +0,0 @@ -module.exports = { - name: 'ping', - description: 'Ping!', - cooldown: 5, - execute(message) { - message.channel.send('Pong.'); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/adding-features/11/commands/prune.js b/Ajuda/guide-master/code-samples/command-handling/adding-features/11/commands/prune.js deleted file mode 100644 index 94f20cc..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/adding-features/11/commands/prune.js +++ /dev/null @@ -1,18 +0,0 @@ -module.exports = { - name: 'prune', - description: 'Prune up to 99 messages.', - execute(message, args) { - const amount = parseInt(args[0]) + 1; - - if (isNaN(amount)) { - return message.reply('that doesn\'t seem to be a valid number.'); - } else if (amount <= 1 || amount > 100) { - return message.reply('you need to input a number between 1 and 99.'); - } - - message.channel.bulkDelete(amount, true).catch(err => { - console.error(err); - message.channel.send('there was an error trying to prune messages in this channel!'); - }); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/adding-features/11/commands/reload.js b/Ajuda/guide-master/code-samples/command-handling/adding-features/11/commands/reload.js deleted file mode 100644 index 84cee46..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/adding-features/11/commands/reload.js +++ /dev/null @@ -1,25 +0,0 @@ -module.exports = { - name: 'reload', - description: 'Reloads a command', - args: true, - execute(message, args) { - const commandName = args[0].toLowerCase(); - const command = message.client.commands.get(commandName) - || message.client.commands.find(cmd => cmd.aliases && cmd.aliases.includes(commandName)); - - if (!command) { - return message.channel.send(`There is no command with name or alias \`${commandName}\`, ${message.author}!`); - } - - delete require.cache[require.resolve(`./${commandName}.js`)]; - - try { - const newCommand = require(`./${commandName}.js`); - message.client.commands.set(newCommand.name, newCommand); - } catch (error) { - console.log(error); - return message.channel.send(`There was an error while reloading a command \`${commandName}\`:\n\`${error.message}\``); - } - message.channel.send(`Command \`${commandName}\` was reloaded!`); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/adding-features/11/commands/server.js b/Ajuda/guide-master/code-samples/command-handling/adding-features/11/commands/server.js deleted file mode 100644 index d8e6de8..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/adding-features/11/commands/server.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = { - name: 'server', - description: 'Display info about this server.', - execute(message) { - message.channel.send(`Server name: ${message.guild.name}\nTotal members: ${message.guild.memberCount}`); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/adding-features/11/commands/user-info.js b/Ajuda/guide-master/code-samples/command-handling/adding-features/11/commands/user-info.js deleted file mode 100644 index a1f5664..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/adding-features/11/commands/user-info.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = { - name: 'user-info', - description: 'Display info about yourself.', - execute(message) { - message.channel.send(`Your username: ${message.author.username}\nYour ID: ${message.author.id}`); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/adding-features/11/config.json b/Ajuda/guide-master/code-samples/command-handling/adding-features/11/config.json deleted file mode 100644 index 74c3e2e..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/adding-features/11/config.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "prefix": "!", - "token": "your-token-goes-here" -} diff --git a/Ajuda/guide-master/code-samples/command-handling/adding-features/11/index.js b/Ajuda/guide-master/code-samples/command-handling/adding-features/11/index.js deleted file mode 100644 index 046a41d..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/adding-features/11/index.js +++ /dev/null @@ -1,74 +0,0 @@ -const fs = require('fs'); -const Discord = require('discord.js'); -const { prefix, token } = require('./config.json'); - -const client = new Discord.Client(); -client.commands = new Discord.Collection(); - -const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js')); - -for (const file of commandFiles) { - const command = require(`./commands/${file}`); - client.commands.set(command.name, command); -} - -const cooldowns = new Discord.Collection(); - -client.once('ready', () => { - console.log('Ready!'); -}); - -client.on('message', message => { - if (!message.content.startsWith(prefix) || message.author.bot) return; - - const args = message.content.slice(prefix.length).split(/ +/); - const commandName = args.shift().toLowerCase(); - - const command = client.commands.get(commandName) - || client.commands.find(cmd => cmd.aliases && cmd.aliases.includes(commandName)); - - if (!command) return; - - if (command.guildOnly && message.channel.type !== 'text') { - return message.reply('I can\'t execute that command inside DMs!'); - } - - if (command.args && !args.length) { - let reply = `You didn't provide any arguments, ${message.author}!`; - - if (command.usage) { - reply += `\nThe proper usage would be: \`${prefix}${command.name} ${command.usage}\``; - } - - return message.channel.send(reply); - } - - if (!cooldowns.has(command.name)) { - cooldowns.set(command.name, new Discord.Collection()); - } - - const now = Date.now(); - const timestamps = cooldowns.get(command.name); - const cooldownAmount = (command.cooldown || 3) * 1000; - - if (timestamps.has(message.author.id)) { - const expirationTime = timestamps.get(message.author.id) + cooldownAmount; - - if (now < expirationTime) { - const timeLeft = (expirationTime - now) / 1000; - return message.reply(`please wait ${timeLeft.toFixed(1)} more second(s) before reusing the \`${command.name}\` command.`); - } - } - - timestamps.set(message.author.id, now); - setTimeout(() => timestamps.delete(message.author.id), cooldownAmount); - - try { - command.execute(message, args); - } catch (error) { - console.error(error); - message.reply('there was an error trying to execute that command!'); - } -}); - -client.login(token); diff --git a/Ajuda/guide-master/code-samples/command-handling/adding-features/12/commands/args-info.js b/Ajuda/guide-master/code-samples/command-handling/adding-features/12/commands/args-info.js deleted file mode 100644 index 289f544..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/adding-features/12/commands/args-info.js +++ /dev/null @@ -1,12 +0,0 @@ -module.exports = { - name: 'args-info', - description: 'Information about the arguments provided.', - args: true, - execute(message, args) { - if (args[0] === 'foo') { - return message.channel.send('bar'); - } - - message.channel.send(`First argument: ${args[0]}`); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/adding-features/12/commands/avatar.js b/Ajuda/guide-master/code-samples/command-handling/adding-features/12/commands/avatar.js deleted file mode 100644 index 2f5711f..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/adding-features/12/commands/avatar.js +++ /dev/null @@ -1,16 +0,0 @@ -module.exports = { - name: 'avatar', - description: 'Get the avatar URL of the tagged user(s), or your own avatar.', - aliases: ['icon', 'pfp'], - execute(message) { - if (!message.mentions.users.size) { - return message.channel.send(`Your avatar: <${message.author.displayAvatarURL()}>`); - } - - const avatarList = message.mentions.users.map(user => { - return `${user.username}'s avatar: <${user.displayAvatarURL()}>`; - }); - - message.channel.send(avatarList); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/adding-features/12/commands/beep.js b/Ajuda/guide-master/code-samples/command-handling/adding-features/12/commands/beep.js deleted file mode 100644 index e3345e9..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/adding-features/12/commands/beep.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = { - name: 'beep', - description: 'Beep!', - execute(message) { - message.channel.send('Boop.'); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/adding-features/12/commands/help.js b/Ajuda/guide-master/code-samples/command-handling/adding-features/12/commands/help.js deleted file mode 100644 index 1f08793..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/adding-features/12/commands/help.js +++ /dev/null @@ -1,46 +0,0 @@ -const { prefix } = require('../config.json'); - -module.exports = { - name: 'help', - description: 'List all of my commands or info about a specific command.', - aliases: ['commands'], - usage: '[command name]', - cooldown: 5, - execute(message, args) { - const data = []; - const { commands } = message.client; - - if (!args.length) { - data.push('Here\'s a list of all my commands:'); - data.push(commands.map(command => command.name).join(', ')); - data.push(`\nYou can send \`${prefix}help [command name]\` to get info on a specific command!`); - - return message.author.send(data, { split: true }) - .then(() => { - if (message.channel.type === 'dm') return; - message.reply('I\'ve sent you a DM with all my commands!'); - }) - .catch(error => { - console.error(`Could not send help DM to ${message.author.tag}.\n`, error); - message.reply('it seems like I can\'t DM you!'); - }); - } - - const name = args[0].toLowerCase(); - const command = commands.get(name) || commands.find(c => c.aliases && c.aliases.includes(name)); - - if (!command) { - return message.reply('that\'s not a valid command!'); - } - - data.push(`**Name:** ${command.name}`); - - if (command.aliases) data.push(`**Aliases:** ${command.aliases.join(', ')}`); - if (command.description) data.push(`**Description:** ${command.description}`); - if (command.usage) data.push(`**Usage:** ${prefix}${command.name} ${command.usage}`); - - data.push(`**Cooldown:** ${command.cooldown || 3} second(s)`); - - message.channel.send(data, { split: true }); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/adding-features/12/commands/kick.js b/Ajuda/guide-master/code-samples/command-handling/adding-features/12/commands/kick.js deleted file mode 100644 index 8428e8d..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/adding-features/12/commands/kick.js +++ /dev/null @@ -1,14 +0,0 @@ -module.exports = { - name: 'kick', - description: 'Tag a member and kick them (but not really).', - guildOnly: true, - execute(message) { - if (!message.mentions.users.size) { - return message.reply('you need to tag a user in order to kick them!'); - } - - const taggedUser = message.mentions.users.first(); - - message.channel.send(`You wanted to kick: ${taggedUser.username}`); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/adding-features/12/commands/ping.js b/Ajuda/guide-master/code-samples/command-handling/adding-features/12/commands/ping.js deleted file mode 100644 index 8e6810f..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/adding-features/12/commands/ping.js +++ /dev/null @@ -1,8 +0,0 @@ -module.exports = { - name: 'ping', - description: 'Ping!', - cooldown: 5, - execute(message) { - message.channel.send('Pong.'); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/adding-features/12/commands/prune.js b/Ajuda/guide-master/code-samples/command-handling/adding-features/12/commands/prune.js deleted file mode 100644 index 94f20cc..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/adding-features/12/commands/prune.js +++ /dev/null @@ -1,18 +0,0 @@ -module.exports = { - name: 'prune', - description: 'Prune up to 99 messages.', - execute(message, args) { - const amount = parseInt(args[0]) + 1; - - if (isNaN(amount)) { - return message.reply('that doesn\'t seem to be a valid number.'); - } else if (amount <= 1 || amount > 100) { - return message.reply('you need to input a number between 1 and 99.'); - } - - message.channel.bulkDelete(amount, true).catch(err => { - console.error(err); - message.channel.send('there was an error trying to prune messages in this channel!'); - }); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/adding-features/12/commands/reload.js b/Ajuda/guide-master/code-samples/command-handling/adding-features/12/commands/reload.js deleted file mode 100644 index 84cee46..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/adding-features/12/commands/reload.js +++ /dev/null @@ -1,25 +0,0 @@ -module.exports = { - name: 'reload', - description: 'Reloads a command', - args: true, - execute(message, args) { - const commandName = args[0].toLowerCase(); - const command = message.client.commands.get(commandName) - || message.client.commands.find(cmd => cmd.aliases && cmd.aliases.includes(commandName)); - - if (!command) { - return message.channel.send(`There is no command with name or alias \`${commandName}\`, ${message.author}!`); - } - - delete require.cache[require.resolve(`./${commandName}.js`)]; - - try { - const newCommand = require(`./${commandName}.js`); - message.client.commands.set(newCommand.name, newCommand); - } catch (error) { - console.log(error); - return message.channel.send(`There was an error while reloading a command \`${commandName}\`:\n\`${error.message}\``); - } - message.channel.send(`Command \`${commandName}\` was reloaded!`); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/adding-features/12/commands/server.js b/Ajuda/guide-master/code-samples/command-handling/adding-features/12/commands/server.js deleted file mode 100644 index d8e6de8..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/adding-features/12/commands/server.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = { - name: 'server', - description: 'Display info about this server.', - execute(message) { - message.channel.send(`Server name: ${message.guild.name}\nTotal members: ${message.guild.memberCount}`); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/adding-features/12/commands/user-info.js b/Ajuda/guide-master/code-samples/command-handling/adding-features/12/commands/user-info.js deleted file mode 100644 index a1f5664..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/adding-features/12/commands/user-info.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = { - name: 'user-info', - description: 'Display info about yourself.', - execute(message) { - message.channel.send(`Your username: ${message.author.username}\nYour ID: ${message.author.id}`); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/adding-features/12/config.json b/Ajuda/guide-master/code-samples/command-handling/adding-features/12/config.json deleted file mode 100644 index 74c3e2e..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/adding-features/12/config.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "prefix": "!", - "token": "your-token-goes-here" -} diff --git a/Ajuda/guide-master/code-samples/command-handling/adding-features/12/index.js b/Ajuda/guide-master/code-samples/command-handling/adding-features/12/index.js deleted file mode 100644 index 046a41d..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/adding-features/12/index.js +++ /dev/null @@ -1,74 +0,0 @@ -const fs = require('fs'); -const Discord = require('discord.js'); -const { prefix, token } = require('./config.json'); - -const client = new Discord.Client(); -client.commands = new Discord.Collection(); - -const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js')); - -for (const file of commandFiles) { - const command = require(`./commands/${file}`); - client.commands.set(command.name, command); -} - -const cooldowns = new Discord.Collection(); - -client.once('ready', () => { - console.log('Ready!'); -}); - -client.on('message', message => { - if (!message.content.startsWith(prefix) || message.author.bot) return; - - const args = message.content.slice(prefix.length).split(/ +/); - const commandName = args.shift().toLowerCase(); - - const command = client.commands.get(commandName) - || client.commands.find(cmd => cmd.aliases && cmd.aliases.includes(commandName)); - - if (!command) return; - - if (command.guildOnly && message.channel.type !== 'text') { - return message.reply('I can\'t execute that command inside DMs!'); - } - - if (command.args && !args.length) { - let reply = `You didn't provide any arguments, ${message.author}!`; - - if (command.usage) { - reply += `\nThe proper usage would be: \`${prefix}${command.name} ${command.usage}\``; - } - - return message.channel.send(reply); - } - - if (!cooldowns.has(command.name)) { - cooldowns.set(command.name, new Discord.Collection()); - } - - const now = Date.now(); - const timestamps = cooldowns.get(command.name); - const cooldownAmount = (command.cooldown || 3) * 1000; - - if (timestamps.has(message.author.id)) { - const expirationTime = timestamps.get(message.author.id) + cooldownAmount; - - if (now < expirationTime) { - const timeLeft = (expirationTime - now) / 1000; - return message.reply(`please wait ${timeLeft.toFixed(1)} more second(s) before reusing the \`${command.name}\` command.`); - } - } - - timestamps.set(message.author.id, now); - setTimeout(() => timestamps.delete(message.author.id), cooldownAmount); - - try { - command.execute(message, args); - } catch (error) { - console.error(error); - message.reply('there was an error trying to execute that command!'); - } -}); - -client.login(token); diff --git a/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/11/commands/args-info.js b/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/11/commands/args-info.js deleted file mode 100644 index 289f544..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/11/commands/args-info.js +++ /dev/null @@ -1,12 +0,0 @@ -module.exports = { - name: 'args-info', - description: 'Information about the arguments provided.', - args: true, - execute(message, args) { - if (args[0] === 'foo') { - return message.channel.send('bar'); - } - - message.channel.send(`First argument: ${args[0]}`); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/11/commands/avatar.js b/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/11/commands/avatar.js deleted file mode 100644 index ab2dbcd..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/11/commands/avatar.js +++ /dev/null @@ -1,15 +0,0 @@ -module.exports = { - name: 'avatar', - description: 'Get the avatar URL of the tagged user(s), or your own avatar.', - execute(message) { - if (!message.mentions.users.size) { - return message.channel.send(`Your avatar: ${message.author.displayAvatarURL}`); - } - - const avatarList = message.mentions.users.map(user => { - return `${user.username}'s avatar: ${user.displayAvatarURL}`; - }); - - message.channel.send(avatarList); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/11/commands/beep.js b/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/11/commands/beep.js deleted file mode 100644 index e3345e9..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/11/commands/beep.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = { - name: 'beep', - description: 'Beep!', - execute(message) { - message.channel.send('Boop.'); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/11/commands/kick.js b/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/11/commands/kick.js deleted file mode 100644 index e892c66..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/11/commands/kick.js +++ /dev/null @@ -1,13 +0,0 @@ -module.exports = { - name: 'kick', - description: 'Tag a member and kick them (but not really).', - execute(message) { - if (!message.mentions.users.size) { - return message.reply('you need to tag a user in order to kick them!'); - } - - const taggedUser = message.mentions.users.first(); - - message.channel.send(`You wanted to kick: ${taggedUser.username}`); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/11/commands/ping.js b/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/11/commands/ping.js deleted file mode 100644 index 56e6756..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/11/commands/ping.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = { - name: 'ping', - description: 'Ping!', - execute(message) { - message.channel.send('Pong.'); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/11/commands/prune.js b/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/11/commands/prune.js deleted file mode 100644 index 94f20cc..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/11/commands/prune.js +++ /dev/null @@ -1,18 +0,0 @@ -module.exports = { - name: 'prune', - description: 'Prune up to 99 messages.', - execute(message, args) { - const amount = parseInt(args[0]) + 1; - - if (isNaN(amount)) { - return message.reply('that doesn\'t seem to be a valid number.'); - } else if (amount <= 1 || amount > 100) { - return message.reply('you need to input a number between 1 and 99.'); - } - - message.channel.bulkDelete(amount, true).catch(err => { - console.error(err); - message.channel.send('there was an error trying to prune messages in this channel!'); - }); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/11/commands/server.js b/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/11/commands/server.js deleted file mode 100644 index d8e6de8..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/11/commands/server.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = { - name: 'server', - description: 'Display info about this server.', - execute(message) { - message.channel.send(`Server name: ${message.guild.name}\nTotal members: ${message.guild.memberCount}`); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/11/commands/user-info.js b/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/11/commands/user-info.js deleted file mode 100644 index a1f5664..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/11/commands/user-info.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = { - name: 'user-info', - description: 'Display info about yourself.', - execute(message) { - message.channel.send(`Your username: ${message.author.username}\nYour ID: ${message.author.id}`); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/11/config.json b/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/11/config.json deleted file mode 100644 index 74c3e2e..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/11/config.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "prefix": "!", - "token": "your-token-goes-here" -} diff --git a/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/11/index.js b/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/11/index.js deleted file mode 100644 index 531489d..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/11/index.js +++ /dev/null @@ -1,35 +0,0 @@ -const fs = require('fs'); -const Discord = require('discord.js'); -const { prefix, token } = require('./config.json'); - -const client = new Discord.Client(); -client.commands = new Discord.Collection(); - -const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js')); - -for (const file of commandFiles) { - const command = require(`./commands/${file}`); - client.commands.set(command.name, command); -} - -client.once('ready', () => { - console.log('Ready!'); -}); - -client.on('message', message => { - if (!message.content.startsWith(prefix) || message.author.bot) return; - - const args = message.content.slice(prefix.length).split(/ +/); - const command = args.shift().toLowerCase(); - - if (!client.commands.has(command)) return; - - try { - client.commands.get(command).execute(message, args); - } catch (error) { - console.error(error); - message.reply('there was an error trying to execute that command!'); - } -}); - -client.login(token); diff --git a/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/12/commands/args-info.js b/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/12/commands/args-info.js deleted file mode 100644 index 289f544..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/12/commands/args-info.js +++ /dev/null @@ -1,12 +0,0 @@ -module.exports = { - name: 'args-info', - description: 'Information about the arguments provided.', - args: true, - execute(message, args) { - if (args[0] === 'foo') { - return message.channel.send('bar'); - } - - message.channel.send(`First argument: ${args[0]}`); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/12/commands/avatar.js b/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/12/commands/avatar.js deleted file mode 100644 index dfadc7f..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/12/commands/avatar.js +++ /dev/null @@ -1,15 +0,0 @@ -module.exports = { - name: 'avatar', - description: 'Get the avatar URL of the tagged user(s), or your own avatar.', - execute(message) { - if (!message.mentions.users.size) { - return message.channel.send(`Your avatar: ${message.author.displayAvatarURL()}`); - } - - const avatarList = message.mentions.users.map(user => { - return `${user.username}'s avatar: ${user.displayAvatarURL()}`; - }); - - message.channel.send(avatarList); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/12/commands/beep.js b/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/12/commands/beep.js deleted file mode 100644 index e3345e9..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/12/commands/beep.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = { - name: 'beep', - description: 'Beep!', - execute(message) { - message.channel.send('Boop.'); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/12/commands/kick.js b/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/12/commands/kick.js deleted file mode 100644 index e892c66..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/12/commands/kick.js +++ /dev/null @@ -1,13 +0,0 @@ -module.exports = { - name: 'kick', - description: 'Tag a member and kick them (but not really).', - execute(message) { - if (!message.mentions.users.size) { - return message.reply('you need to tag a user in order to kick them!'); - } - - const taggedUser = message.mentions.users.first(); - - message.channel.send(`You wanted to kick: ${taggedUser.username}`); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/12/commands/ping.js b/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/12/commands/ping.js deleted file mode 100644 index 56e6756..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/12/commands/ping.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = { - name: 'ping', - description: 'Ping!', - execute(message) { - message.channel.send('Pong.'); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/12/commands/prune.js b/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/12/commands/prune.js deleted file mode 100644 index 94f20cc..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/12/commands/prune.js +++ /dev/null @@ -1,18 +0,0 @@ -module.exports = { - name: 'prune', - description: 'Prune up to 99 messages.', - execute(message, args) { - const amount = parseInt(args[0]) + 1; - - if (isNaN(amount)) { - return message.reply('that doesn\'t seem to be a valid number.'); - } else if (amount <= 1 || amount > 100) { - return message.reply('you need to input a number between 1 and 99.'); - } - - message.channel.bulkDelete(amount, true).catch(err => { - console.error(err); - message.channel.send('there was an error trying to prune messages in this channel!'); - }); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/12/commands/server.js b/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/12/commands/server.js deleted file mode 100644 index d8e6de8..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/12/commands/server.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = { - name: 'server', - description: 'Display info about this server.', - execute(message) { - message.channel.send(`Server name: ${message.guild.name}\nTotal members: ${message.guild.memberCount}`); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/12/commands/user-info.js b/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/12/commands/user-info.js deleted file mode 100644 index a1f5664..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/12/commands/user-info.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = { - name: 'user-info', - description: 'Display info about yourself.', - execute(message) { - message.channel.send(`Your username: ${message.author.username}\nYour ID: ${message.author.id}`); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/12/config.json b/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/12/config.json deleted file mode 100644 index 74c3e2e..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/12/config.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "prefix": "!", - "token": "your-token-goes-here" -} diff --git a/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/12/index.js b/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/12/index.js deleted file mode 100644 index 531489d..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/dynamic-commands/12/index.js +++ /dev/null @@ -1,35 +0,0 @@ -const fs = require('fs'); -const Discord = require('discord.js'); -const { prefix, token } = require('./config.json'); - -const client = new Discord.Client(); -client.commands = new Discord.Collection(); - -const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js')); - -for (const file of commandFiles) { - const command = require(`./commands/${file}`); - client.commands.set(command.name, command); -} - -client.once('ready', () => { - console.log('Ready!'); -}); - -client.on('message', message => { - if (!message.content.startsWith(prefix) || message.author.bot) return; - - const args = message.content.slice(prefix.length).split(/ +/); - const command = args.shift().toLowerCase(); - - if (!client.commands.has(command)) return; - - try { - client.commands.get(command).execute(message, args); - } catch (error) { - console.error(error); - message.reply('there was an error trying to execute that command!'); - } -}); - -client.login(token); diff --git a/Ajuda/guide-master/code-samples/command-handling/file-setup/11/commands/args-info.js b/Ajuda/guide-master/code-samples/command-handling/file-setup/11/commands/args-info.js deleted file mode 100644 index b9d674c..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/file-setup/11/commands/args-info.js +++ /dev/null @@ -1,13 +0,0 @@ -module.exports = { - name: 'args-info', - description: 'Information about the arguments provided.', - execute(message, args) { - if (!args.length) { - return message.channel.send(`You didn't provide any arguments, ${message.author}!`); - } else if (args[0] === 'foo') { - return message.channel.send('bar'); - } - - message.channel.send(`First argument: ${args[0]}`); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/file-setup/11/commands/avatar.js b/Ajuda/guide-master/code-samples/command-handling/file-setup/11/commands/avatar.js deleted file mode 100644 index ab2dbcd..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/file-setup/11/commands/avatar.js +++ /dev/null @@ -1,15 +0,0 @@ -module.exports = { - name: 'avatar', - description: 'Get the avatar URL of the tagged user(s), or your own avatar.', - execute(message) { - if (!message.mentions.users.size) { - return message.channel.send(`Your avatar: ${message.author.displayAvatarURL}`); - } - - const avatarList = message.mentions.users.map(user => { - return `${user.username}'s avatar: ${user.displayAvatarURL}`; - }); - - message.channel.send(avatarList); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/file-setup/11/commands/beep.js b/Ajuda/guide-master/code-samples/command-handling/file-setup/11/commands/beep.js deleted file mode 100644 index e3345e9..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/file-setup/11/commands/beep.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = { - name: 'beep', - description: 'Beep!', - execute(message) { - message.channel.send('Boop.'); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/file-setup/11/commands/kick.js b/Ajuda/guide-master/code-samples/command-handling/file-setup/11/commands/kick.js deleted file mode 100644 index e892c66..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/file-setup/11/commands/kick.js +++ /dev/null @@ -1,13 +0,0 @@ -module.exports = { - name: 'kick', - description: 'Tag a member and kick them (but not really).', - execute(message) { - if (!message.mentions.users.size) { - return message.reply('you need to tag a user in order to kick them!'); - } - - const taggedUser = message.mentions.users.first(); - - message.channel.send(`You wanted to kick: ${taggedUser.username}`); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/file-setup/11/commands/ping.js b/Ajuda/guide-master/code-samples/command-handling/file-setup/11/commands/ping.js deleted file mode 100644 index 56e6756..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/file-setup/11/commands/ping.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = { - name: 'ping', - description: 'Ping!', - execute(message) { - message.channel.send('Pong.'); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/file-setup/11/commands/prune.js b/Ajuda/guide-master/code-samples/command-handling/file-setup/11/commands/prune.js deleted file mode 100644 index 94f20cc..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/file-setup/11/commands/prune.js +++ /dev/null @@ -1,18 +0,0 @@ -module.exports = { - name: 'prune', - description: 'Prune up to 99 messages.', - execute(message, args) { - const amount = parseInt(args[0]) + 1; - - if (isNaN(amount)) { - return message.reply('that doesn\'t seem to be a valid number.'); - } else if (amount <= 1 || amount > 100) { - return message.reply('you need to input a number between 1 and 99.'); - } - - message.channel.bulkDelete(amount, true).catch(err => { - console.error(err); - message.channel.send('there was an error trying to prune messages in this channel!'); - }); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/file-setup/11/commands/server.js b/Ajuda/guide-master/code-samples/command-handling/file-setup/11/commands/server.js deleted file mode 100644 index d8e6de8..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/file-setup/11/commands/server.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = { - name: 'server', - description: 'Display info about this server.', - execute(message) { - message.channel.send(`Server name: ${message.guild.name}\nTotal members: ${message.guild.memberCount}`); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/file-setup/11/commands/user-info.js b/Ajuda/guide-master/code-samples/command-handling/file-setup/11/commands/user-info.js deleted file mode 100644 index a1f5664..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/file-setup/11/commands/user-info.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = { - name: 'user-info', - description: 'Display info about yourself.', - execute(message) { - message.channel.send(`Your username: ${message.author.username}\nYour ID: ${message.author.id}`); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/file-setup/11/config.json b/Ajuda/guide-master/code-samples/command-handling/file-setup/11/config.json deleted file mode 100644 index 74c3e2e..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/file-setup/11/config.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "prefix": "!", - "token": "your-token-goes-here" -} diff --git a/Ajuda/guide-master/code-samples/command-handling/file-setup/11/index.js b/Ajuda/guide-master/code-samples/command-handling/file-setup/11/index.js deleted file mode 100644 index 3751022..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/file-setup/11/index.js +++ /dev/null @@ -1,75 +0,0 @@ -const fs = require('fs'); -const Discord = require('discord.js'); -const { prefix, token } = require('./config.json'); - -const client = new Discord.Client(); -client.commands = new Discord.Collection(); - -const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js')); - -for (const file of commandFiles) { - const command = require(`./commands/${file}`); - client.commands.set(command.name, command); -} - -client.once('ready', () => { - console.log('Ready!'); -}); - -client.on('message', message => { - if (!message.content.startsWith(prefix) || message.author.bot) return; - - const args = message.content.slice(prefix.length).split(/ +/); - const command = args.shift().toLowerCase(); - - if (command === 'ping') { - message.channel.send('Pong.'); - } else if (command === 'beep') { - message.channel.send('Boop.'); - } else if (command === 'server') { - message.channel.send(`Server name: ${message.guild.name}\nTotal members: ${message.guild.memberCount}`); - } else if (command === 'user-info') { - message.channel.send(`Your username: ${message.author.username}\nYour ID: ${message.author.id}`); - } else if (command === 'info') { - if (!args.length) { - return message.channel.send(`You didn't provide any arguments, ${message.author}!`); - } else if (args[0] === 'foo') { - return message.channel.send('bar'); - } - - message.channel.send(`First argument: ${args[0]}`); - } else if (command === 'kick') { - if (!message.mentions.users.size) { - return message.reply('you need to tag a user in order to kick them!'); - } - - const taggedUser = message.mentions.users.first(); - - message.channel.send(`You wanted to kick: ${taggedUser.username}`); - } else if (command === 'avatar') { - if (!message.mentions.users.size) { - return message.channel.send(`Your avatar: ${message.author.displayAvatarURL}`); - } - - const avatarList = message.mentions.users.map(user => { - return `${user.username}'s avatar: ${user.displayAvatarURL}`; - }); - - message.channel.send(avatarList); - } else if (command === 'prune') { - const amount = parseInt(args[0]) + 1; - - if (isNaN(amount)) { - return message.reply('that doesn\'t seem to be a valid number.'); - } else if (amount <= 1 || amount > 100) { - return message.reply('you need to input a number between 1 and 99.'); - } - - message.channel.bulkDelete(amount, true).catch(err => { - console.error(err); - message.channel.send('there was an error trying to prune messages in this channel!'); - }); - } -}); - -client.login(token); diff --git a/Ajuda/guide-master/code-samples/command-handling/file-setup/12/commands/args-info.js b/Ajuda/guide-master/code-samples/command-handling/file-setup/12/commands/args-info.js deleted file mode 100644 index b9d674c..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/file-setup/12/commands/args-info.js +++ /dev/null @@ -1,13 +0,0 @@ -module.exports = { - name: 'args-info', - description: 'Information about the arguments provided.', - execute(message, args) { - if (!args.length) { - return message.channel.send(`You didn't provide any arguments, ${message.author}!`); - } else if (args[0] === 'foo') { - return message.channel.send('bar'); - } - - message.channel.send(`First argument: ${args[0]}`); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/file-setup/12/commands/avatar.js b/Ajuda/guide-master/code-samples/command-handling/file-setup/12/commands/avatar.js deleted file mode 100644 index dfadc7f..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/file-setup/12/commands/avatar.js +++ /dev/null @@ -1,15 +0,0 @@ -module.exports = { - name: 'avatar', - description: 'Get the avatar URL of the tagged user(s), or your own avatar.', - execute(message) { - if (!message.mentions.users.size) { - return message.channel.send(`Your avatar: ${message.author.displayAvatarURL()}`); - } - - const avatarList = message.mentions.users.map(user => { - return `${user.username}'s avatar: ${user.displayAvatarURL()}`; - }); - - message.channel.send(avatarList); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/file-setup/12/commands/beep.js b/Ajuda/guide-master/code-samples/command-handling/file-setup/12/commands/beep.js deleted file mode 100644 index e3345e9..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/file-setup/12/commands/beep.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = { - name: 'beep', - description: 'Beep!', - execute(message) { - message.channel.send('Boop.'); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/file-setup/12/commands/kick.js b/Ajuda/guide-master/code-samples/command-handling/file-setup/12/commands/kick.js deleted file mode 100644 index e892c66..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/file-setup/12/commands/kick.js +++ /dev/null @@ -1,13 +0,0 @@ -module.exports = { - name: 'kick', - description: 'Tag a member and kick them (but not really).', - execute(message) { - if (!message.mentions.users.size) { - return message.reply('you need to tag a user in order to kick them!'); - } - - const taggedUser = message.mentions.users.first(); - - message.channel.send(`You wanted to kick: ${taggedUser.username}`); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/file-setup/12/commands/ping.js b/Ajuda/guide-master/code-samples/command-handling/file-setup/12/commands/ping.js deleted file mode 100644 index 56e6756..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/file-setup/12/commands/ping.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = { - name: 'ping', - description: 'Ping!', - execute(message) { - message.channel.send('Pong.'); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/file-setup/12/commands/prune.js b/Ajuda/guide-master/code-samples/command-handling/file-setup/12/commands/prune.js deleted file mode 100644 index 94f20cc..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/file-setup/12/commands/prune.js +++ /dev/null @@ -1,18 +0,0 @@ -module.exports = { - name: 'prune', - description: 'Prune up to 99 messages.', - execute(message, args) { - const amount = parseInt(args[0]) + 1; - - if (isNaN(amount)) { - return message.reply('that doesn\'t seem to be a valid number.'); - } else if (amount <= 1 || amount > 100) { - return message.reply('you need to input a number between 1 and 99.'); - } - - message.channel.bulkDelete(amount, true).catch(err => { - console.error(err); - message.channel.send('there was an error trying to prune messages in this channel!'); - }); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/file-setup/12/commands/server.js b/Ajuda/guide-master/code-samples/command-handling/file-setup/12/commands/server.js deleted file mode 100644 index d8e6de8..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/file-setup/12/commands/server.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = { - name: 'server', - description: 'Display info about this server.', - execute(message) { - message.channel.send(`Server name: ${message.guild.name}\nTotal members: ${message.guild.memberCount}`); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/file-setup/12/commands/user-info.js b/Ajuda/guide-master/code-samples/command-handling/file-setup/12/commands/user-info.js deleted file mode 100644 index a1f5664..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/file-setup/12/commands/user-info.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = { - name: 'user-info', - description: 'Display info about yourself.', - execute(message) { - message.channel.send(`Your username: ${message.author.username}\nYour ID: ${message.author.id}`); - }, -}; diff --git a/Ajuda/guide-master/code-samples/command-handling/file-setup/12/config.json b/Ajuda/guide-master/code-samples/command-handling/file-setup/12/config.json deleted file mode 100644 index 74c3e2e..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/file-setup/12/config.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "prefix": "!", - "token": "your-token-goes-here" -} diff --git a/Ajuda/guide-master/code-samples/command-handling/file-setup/12/index.js b/Ajuda/guide-master/code-samples/command-handling/file-setup/12/index.js deleted file mode 100644 index 3751022..0000000 --- a/Ajuda/guide-master/code-samples/command-handling/file-setup/12/index.js +++ /dev/null @@ -1,75 +0,0 @@ -const fs = require('fs'); -const Discord = require('discord.js'); -const { prefix, token } = require('./config.json'); - -const client = new Discord.Client(); -client.commands = new Discord.Collection(); - -const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js')); - -for (const file of commandFiles) { - const command = require(`./commands/${file}`); - client.commands.set(command.name, command); -} - -client.once('ready', () => { - console.log('Ready!'); -}); - -client.on('message', message => { - if (!message.content.startsWith(prefix) || message.author.bot) return; - - const args = message.content.slice(prefix.length).split(/ +/); - const command = args.shift().toLowerCase(); - - if (command === 'ping') { - message.channel.send('Pong.'); - } else if (command === 'beep') { - message.channel.send('Boop.'); - } else if (command === 'server') { - message.channel.send(`Server name: ${message.guild.name}\nTotal members: ${message.guild.memberCount}`); - } else if (command === 'user-info') { - message.channel.send(`Your username: ${message.author.username}\nYour ID: ${message.author.id}`); - } else if (command === 'info') { - if (!args.length) { - return message.channel.send(`You didn't provide any arguments, ${message.author}!`); - } else if (args[0] === 'foo') { - return message.channel.send('bar'); - } - - message.channel.send(`First argument: ${args[0]}`); - } else if (command === 'kick') { - if (!message.mentions.users.size) { - return message.reply('you need to tag a user in order to kick them!'); - } - - const taggedUser = message.mentions.users.first(); - - message.channel.send(`You wanted to kick: ${taggedUser.username}`); - } else if (command === 'avatar') { - if (!message.mentions.users.size) { - return message.channel.send(`Your avatar: ${message.author.displayAvatarURL}`); - } - - const avatarList = message.mentions.users.map(user => { - return `${user.username}'s avatar: ${user.displayAvatarURL}`; - }); - - message.channel.send(avatarList); - } else if (command === 'prune') { - const amount = parseInt(args[0]) + 1; - - if (isNaN(amount)) { - return message.reply('that doesn\'t seem to be a valid number.'); - } else if (amount <= 1 || amount > 100) { - return message.reply('you need to input a number between 1 and 99.'); - } - - message.channel.bulkDelete(amount, true).catch(err => { - console.error(err); - message.channel.send('there was an error trying to prune messages in this channel!'); - }); - } -}); - -client.login(token); diff --git a/Ajuda/guide-master/code-samples/commando/args/commands/first/say.js b/Ajuda/guide-master/code-samples/commando/args/commands/first/say.js deleted file mode 100644 index 3bb9b0f..0000000 --- a/Ajuda/guide-master/code-samples/commando/args/commands/first/say.js +++ /dev/null @@ -1,24 +0,0 @@ -const { Command } = require('discord.js-commando'); - -module.exports = class SayCommand extends Command { - constructor(client) { - super(client, { - name: 'say', - aliases: ['parrot', 'copy'], - group: 'first', - memberName: 'say', - description: 'Replies with the text you provide.', - args: [ - { - key: 'text', - prompt: 'What text would you like the bot to say?', - type: 'string', - }, - ], - }); - } - - run(message, { text }) { - return message.reply(text); - } -}; diff --git a/Ajuda/guide-master/code-samples/commando/first-command/commands/first/meow.js b/Ajuda/guide-master/code-samples/commando/first-command/commands/first/meow.js deleted file mode 100644 index 9e7bc0b..0000000 --- a/Ajuda/guide-master/code-samples/commando/first-command/commands/first/meow.js +++ /dev/null @@ -1,16 +0,0 @@ -const { Command } = require('discord.js-commando'); - -module.exports = class MeowCommand extends Command { - constructor(client) { - super(client, { - name: 'meow', - group: 'first', - memberName: 'meow', - description: 'Replies with a meow, kitty cat.', - }); - } - - run(message) { - return message.say('Meow!'); - } -}; diff --git a/Ajuda/guide-master/code-samples/commando/getting-started/index.js b/Ajuda/guide-master/code-samples/commando/getting-started/index.js deleted file mode 100644 index 9ad9359..0000000 --- a/Ajuda/guide-master/code-samples/commando/getting-started/index.js +++ /dev/null @@ -1,26 +0,0 @@ -const { CommandoClient } = require('discord.js-commando'); -const path = require('path'); - -const client = new CommandoClient({ - commandPrefix: '?', - owner: '278305350804045834', - invite: 'https://discord.gg/bRCvFy9', -}); - -client.registry - .registerDefaultTypes() - .registerGroups([ - ['first', 'Your First Command Group'], - ]) - .registerDefaultGroups() - .registerDefaultCommands() - .registerCommandsIn(path.join(__dirname, 'commands')); - -client.once('ready', () => { - console.log(`Logged in as ${client.user.tag}! (${client.user.id})`); - client.user.setActivity('with Commando'); -}); - -client.on('error', console.error); - -client.login('Your Secret Token'); diff --git a/Ajuda/guide-master/code-samples/creating-your-bot/adding-more-commands/config.json b/Ajuda/guide-master/code-samples/creating-your-bot/adding-more-commands/config.json deleted file mode 100644 index 74c3e2e..0000000 --- a/Ajuda/guide-master/code-samples/creating-your-bot/adding-more-commands/config.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "prefix": "!", - "token": "your-token-goes-here" -} diff --git a/Ajuda/guide-master/code-samples/creating-your-bot/adding-more-commands/index.js b/Ajuda/guide-master/code-samples/creating-your-bot/adding-more-commands/index.js deleted file mode 100644 index 81e720f..0000000 --- a/Ajuda/guide-master/code-samples/creating-your-bot/adding-more-commands/index.js +++ /dev/null @@ -1,21 +0,0 @@ -const Discord = require('discord.js'); -const { prefix, token } = require('./config.json'); -const client = new Discord.Client(); - -client.once('ready', () => { - console.log('Ready!'); -}); - -client.on('message', message => { - if (message.content === `${prefix}ping`) { - message.channel.send('Pong.'); - } else if (message.content === `${prefix}beep`) { - message.channel.send('Boop.'); - } else if (message.content === `${prefix}server`) { - message.channel.send(`Server name: ${message.guild.name}\nTotal members: ${message.guild.memberCount}`); - } else if (message.content === `${prefix}user-info`) { - message.channel.send(`Your username: ${message.author.username}\nYour ID: ${message.author.id}`); - } -}); - -client.login(token); diff --git a/Ajuda/guide-master/code-samples/creating-your-bot/commands-with-user-input/11/config.json b/Ajuda/guide-master/code-samples/creating-your-bot/commands-with-user-input/11/config.json deleted file mode 100644 index 74c3e2e..0000000 --- a/Ajuda/guide-master/code-samples/creating-your-bot/commands-with-user-input/11/config.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "prefix": "!", - "token": "your-token-goes-here" -} diff --git a/Ajuda/guide-master/code-samples/creating-your-bot/commands-with-user-input/11/index.js b/Ajuda/guide-master/code-samples/creating-your-bot/commands-with-user-input/11/index.js deleted file mode 100644 index e33b93f..0000000 --- a/Ajuda/guide-master/code-samples/creating-your-bot/commands-with-user-input/11/index.js +++ /dev/null @@ -1,65 +0,0 @@ -const Discord = require('discord.js'); -const { prefix, token } = require('./config.json'); -const client = new Discord.Client(); - -client.once('ready', () => { - console.log('Ready!'); -}); - -client.on('message', message => { - if (!message.content.startsWith(prefix) || message.author.bot) return; - - const args = message.content.slice(prefix.length).split(/ +/); - const command = args.shift().toLowerCase(); - - if (command === 'ping') { - message.channel.send('Pong.'); - } else if (command === 'beep') { - message.channel.send('Boop.'); - } else if (command === 'server') { - message.channel.send(`Server name: ${message.guild.name}\nTotal members: ${message.guild.memberCount}`); - } else if (command === 'user-info') { - message.channel.send(`Your username: ${message.author.username}\nYour ID: ${message.author.id}`); - } else if (command === 'info') { - if (!args.length) { - return message.channel.send(`You didn't provide any arguments, ${message.author}!`); - } else if (args[0] === 'foo') { - return message.channel.send('bar'); - } - - message.channel.send(`First argument: ${args[0]}`); - } else if (command === 'kick') { - if (!message.mentions.users.size) { - return message.reply('you need to tag a user in order to kick them!'); - } - - const taggedUser = message.mentions.users.first(); - - message.channel.send(`You wanted to kick: ${taggedUser.username}`); - } else if (command === 'avatar') { - if (!message.mentions.users.size) { - return message.channel.send(`Your avatar: <${message.author.displayAvatarURL}>`); - } - - const avatarList = message.mentions.users.map(user => { - return `${user.username}'s avatar: <${user.displayAvatarURL}>`; - }); - - message.channel.send(avatarList); - } else if (command === 'prune') { - const amount = parseInt(args[0]) + 1; - - if (isNaN(amount)) { - return message.reply('that doesn\'t seem to be a valid number.'); - } else if (amount <= 1 || amount > 100) { - return message.reply('you need to input a number between 1 and 99.'); - } - - message.channel.bulkDelete(amount, true).catch(err => { - console.error(err); - message.channel.send('there was an error trying to prune messages in this channel!'); - }); - } -}); - -client.login(token); diff --git a/Ajuda/guide-master/code-samples/creating-your-bot/commands-with-user-input/12/config.json b/Ajuda/guide-master/code-samples/creating-your-bot/commands-with-user-input/12/config.json deleted file mode 100644 index 74c3e2e..0000000 --- a/Ajuda/guide-master/code-samples/creating-your-bot/commands-with-user-input/12/config.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "prefix": "!", - "token": "your-token-goes-here" -} diff --git a/Ajuda/guide-master/code-samples/creating-your-bot/commands-with-user-input/12/index.js b/Ajuda/guide-master/code-samples/creating-your-bot/commands-with-user-input/12/index.js deleted file mode 100644 index db12d79..0000000 --- a/Ajuda/guide-master/code-samples/creating-your-bot/commands-with-user-input/12/index.js +++ /dev/null @@ -1,65 +0,0 @@ -const Discord = require('discord.js'); -const { prefix, token } = require('./config.json'); -const client = new Discord.Client(); - -client.once('ready', () => { - console.log('Ready!'); -}); - -client.on('message', message => { - if (!message.content.startsWith(prefix) || message.author.bot) return; - - const args = message.content.slice(prefix.length).split(/ +/); - const command = args.shift().toLowerCase(); - - if (command === 'ping') { - message.channel.send('Pong.'); - } else if (command === 'beep') { - message.channel.send('Boop.'); - } else if (command === 'server') { - message.channel.send(`Server name: ${message.guild.name}\nTotal members: ${message.guild.memberCount}`); - } else if (command === 'user-info') { - message.channel.send(`Your username: ${message.author.username}\nYour ID: ${message.author.id}`); - } else if (command === 'info') { - if (!args.length) { - return message.channel.send(`You didn't provide any arguments, ${message.author}!`); - } else if (args[0] === 'foo') { - return message.channel.send('bar'); - } - - message.channel.send(`First argument: ${args[0]}`); - } else if (command === 'kick') { - if (!message.mentions.users.size) { - return message.reply('you need to tag a user in order to kick them!'); - } - - const taggedUser = message.mentions.users.first(); - - message.channel.send(`You wanted to kick: ${taggedUser.username}`); - } else if (command === 'avatar') { - if (!message.mentions.users.size) { - return message.channel.send(`Your avatar: <${message.author.displayAvatarURL()}>`); - } - - const avatarList = message.mentions.users.map(user => { - return `${user.username}'s avatar: <${user.displayAvatarURL()}>`; - }); - - message.channel.send(avatarList); - } else if (command === 'prune') { - const amount = parseInt(args[0]) + 1; - - if (isNaN(amount)) { - return message.reply('that doesn\'t seem to be a valid number.'); - } else if (amount <= 1 || amount > 100) { - return message.reply('you need to input a number between 1 and 99.'); - } - - message.channel.bulkDelete(amount, true).catch(err => { - console.error(err); - message.channel.send('there was an error trying to prune messages in this channel!'); - }); - } -}); - -client.login(token); diff --git a/Ajuda/guide-master/code-samples/creating-your-bot/configuration-files/config.json b/Ajuda/guide-master/code-samples/creating-your-bot/configuration-files/config.json deleted file mode 100644 index 74c3e2e..0000000 --- a/Ajuda/guide-master/code-samples/creating-your-bot/configuration-files/config.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "prefix": "!", - "token": "your-token-goes-here" -} diff --git a/Ajuda/guide-master/code-samples/creating-your-bot/configuration-files/index.js b/Ajuda/guide-master/code-samples/creating-your-bot/configuration-files/index.js deleted file mode 100644 index 97823bf..0000000 --- a/Ajuda/guide-master/code-samples/creating-your-bot/configuration-files/index.js +++ /dev/null @@ -1,15 +0,0 @@ -const Discord = require('discord.js'); -const config = require('./config.json'); -const client = new Discord.Client(); - -client.once('ready', () => { - console.log('Ready!'); -}); - -client.on('message', message => { - if (message.content === '!ping') { - message.channel.send('Pong.'); - } -}); - -client.login(config.token); diff --git a/Ajuda/guide-master/code-samples/creating-your-bot/up-and-running/index.js b/Ajuda/guide-master/code-samples/creating-your-bot/up-and-running/index.js deleted file mode 100644 index bea736f..0000000 --- a/Ajuda/guide-master/code-samples/creating-your-bot/up-and-running/index.js +++ /dev/null @@ -1,14 +0,0 @@ -const Discord = require('discord.js'); -const client = new Discord.Client(); - -client.once('ready', () => { - console.log('Ready!'); -}); - -client.on('message', message => { - if (message.content === '!ping') { - message.channel.send('Pong.'); - } -}); - -client.login('your-token-goes-here'); diff --git a/Ajuda/guide-master/code-samples/miscellaneous/parsing-mention-arguments/11/config.json b/Ajuda/guide-master/code-samples/miscellaneous/parsing-mention-arguments/11/config.json deleted file mode 100644 index 74c3e2e..0000000 --- a/Ajuda/guide-master/code-samples/miscellaneous/parsing-mention-arguments/11/config.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "prefix": "!", - "token": "your-token-goes-here" -} diff --git a/Ajuda/guide-master/code-samples/miscellaneous/parsing-mention-arguments/11/index.js b/Ajuda/guide-master/code-samples/miscellaneous/parsing-mention-arguments/11/index.js deleted file mode 100644 index 8a697e6..0000000 --- a/Ajuda/guide-master/code-samples/miscellaneous/parsing-mention-arguments/11/index.js +++ /dev/null @@ -1,59 +0,0 @@ -const Discord = require('discord.js'); -const config = require('./config.json'); - -const client = new Discord.Client(); - -function getUserFromMention(mention) { - if (!mention) return; - - if (mention.startsWith('<@') && mention.endsWith('>')) { - mention = mention.slice(2, -1); - - if (mention.startsWith('!')) { - mention = mention.slice(1); - } - - return client.users.get(mention); - } -} - -// eslint-disable-next-line no-unused-vars -function getUserFromMentionRegEx(mention) { - // The id is the first and only match found by the RegEx. - const matches = mention.match(/^<@!?(\d+)>$/); - - // If supplied variable was not a mention, matches will be null instead of an array. - if (!matches) return; - - // However the first element in the matches array will be the entire mention, not just the ID, - // so use index 1. - const id = matches[1]; - - return client.users.get(id); -} - -client.on('message', message => { - if (!message.content.startsWith(config.prefix)) return; - - const withoutPrefix = message.content.slice(config.prefix.length); - const split = withoutPrefix.split(/ +/); - const command = split[0]; - const args = split.slice(1); - - if (command === 'avatar') { - if (args[0]) { - // Change `getUserFromMention` to `getUserFromMentionRegEx` to try the RegEx variant. - const user = getUserFromMention(args[0]); - - if (!user) { - return message.reply('Please use a proper mention if you want to see someone else\'s avatar.'); - } - - return message.channel.send(`${user.username}'s avatar: ${user.displayAvatarURL}`); - } - - return message.channel.send(`${message.author.username}, your avatar: ${message.author.displayAvatarURL}`); - } -}); - -client.login(config.token); diff --git a/Ajuda/guide-master/code-samples/miscellaneous/parsing-mention-arguments/12/config.json b/Ajuda/guide-master/code-samples/miscellaneous/parsing-mention-arguments/12/config.json deleted file mode 100644 index 74c3e2e..0000000 --- a/Ajuda/guide-master/code-samples/miscellaneous/parsing-mention-arguments/12/config.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "prefix": "!", - "token": "your-token-goes-here" -} diff --git a/Ajuda/guide-master/code-samples/miscellaneous/parsing-mention-arguments/12/index.js b/Ajuda/guide-master/code-samples/miscellaneous/parsing-mention-arguments/12/index.js deleted file mode 100644 index 2ac75a0..0000000 --- a/Ajuda/guide-master/code-samples/miscellaneous/parsing-mention-arguments/12/index.js +++ /dev/null @@ -1,55 +0,0 @@ -const Discord = require('discord.js'); -const config = require('./config.json'); - -const client = new Discord.Client(); - -function getUserFromMention(mention) { - if (!mention) return; - - if (mention.startsWith('<@') && mention.endsWith('>')) { - mention = mention.slice(2, -1); - - if (mention.startsWith('!')) { - mention = mention.slice(1); - } - - return client.users.get(mention); - } -} - -// eslint-disable-next-line no-unused-vars -function getUserFromMentionRegEx(mention) { - const matches = mention.match(/^<@!?(\d+)>$/); - // The id is the first and only match found by the RegEx. - // However the first element in the matches array will be the entire mention, not just the ID, - // so use index 1. - const id = matches[1]; - - return client.users.get(id); -} - -client.on('message', message => { - if (!message.content.startsWith(config.prefix)) return; - - const withoutPrefix = message.content.slice(config.prefix.length); - const split = withoutPrefix.split(/ +/); - const command = split[0]; - const args = split.slice(1); - - if (command === 'avatar') { - if (args[0]) { - // Change `getUserFromMention` to `getUserFromMentionRegEx` to try the RegEx variant. - const user = getUserFromMention(args[0]); - - if (!user) { - return message.reply('Please use a proper mention if you want to see someone else\'s avatar.'); - } - - return message.channel.send(`${user.username}'s avatar: ${user.displayAvatarURL()}`); - } - - return message.channel.send(`${message.author.username}, your avatar: ${message.author.displayAvatarURL()}`); - } -}); - -client.login(config.token); diff --git a/Ajuda/guide-master/code-samples/oauth/simple-oauth-webserver/index.html b/Ajuda/guide-master/code-samples/oauth/simple-oauth-webserver/index.html deleted file mode 100644 index 98970c0..0000000 --- a/Ajuda/guide-master/code-samples/oauth/simple-oauth-webserver/index.html +++ /dev/null @@ -1,60 +0,0 @@ - - - - My First OAuth2 App - - -
- Hoi! -
- - - - diff --git a/Ajuda/guide-master/code-samples/oauth/simple-oauth-webserver/index.js b/Ajuda/guide-master/code-samples/oauth/simple-oauth-webserver/index.js deleted file mode 100644 index b0752a1..0000000 --- a/Ajuda/guide-master/code-samples/oauth/simple-oauth-webserver/index.js +++ /dev/null @@ -1,56 +0,0 @@ -const http = require('http'); -const fs = require('fs'); -const url = require('url'); -const fetch = require('node-fetch'); -const FormData = require('form-data'); - -const port = 53134; - -http.createServer((req, res) => { - let responseCode = 404; - let content = '404 Error'; - - const urlObj = url.parse(req.url, true); - - if (urlObj.query.code) { - const accessCode = urlObj.query.code; - const data = new FormData(); - - data.append('client_id', 'your client id'); - data.append('client_secret', 'your client secret'); - data.append('grant_type', 'authorization_code'); - data.append('redirect_uri', 'your redirect url'); - data.append('scope', 'your scopes'); - data.append('code', accessCode); - - fetch('https://discordapp.com/api/oauth2/token', { - method: 'POST', - body: data, - }) - .then(discordRes => discordRes.json()) - .then(info => { - console.log(info); - return info; - }) - .then(info => fetch('https://discordapp.com/api/users/@me', { - headers: { - authorization: `${info.token_type} ${info.access_token}`, - }, - })) - .then(userRes => userRes.json()) - .then(console.log); - } - - if (urlObj.pathname === '/') { - responseCode = 200; - content = fs.readFileSync('./index.html'); - } - - res.writeHead(responseCode, { - 'content-type': 'text/html;charset=utf-8', - }); - - res.write(content); - res.end(); -}) - .listen(port); diff --git a/Ajuda/guide-master/code-samples/popular-topics/canvas/11/index.js b/Ajuda/guide-master/code-samples/popular-topics/canvas/11/index.js deleted file mode 100644 index 8f30a48..0000000 --- a/Ajuda/guide-master/code-samples/popular-topics/canvas/11/index.js +++ /dev/null @@ -1,61 +0,0 @@ -const Discord = require('discord.js'); -const Canvas = require('canvas'); - -const client = new Discord.Client(); - -client.once('ready', () => { - console.log('Ready!'); -}); - -const applyText = (canvas, text) => { - const ctx = canvas.getContext('2d'); - let fontSize = 70; - - do { - ctx.font = `${fontSize -= 10}px sans-serif`; - } while (ctx.measureText(text).width > canvas.width - 300); - - return ctx.font; -}; - -client.on('guildMemberAdd', async member => { - const channel = member.guild.channels.find(ch => ch.name === 'member-log'); - if (!channel) return; - - const canvas = Canvas.createCanvas(700, 250); - const ctx = canvas.getContext('2d'); - - const background = await Canvas.loadImage('./wallpaper.jpg'); - ctx.drawImage(background, 0, 0, canvas.width, canvas.height); - - ctx.strokeStyle = '#74037b'; - ctx.strokeRect(0, 0, canvas.width, canvas.height); - - ctx.font = '28px sans-serif'; - ctx.fillStyle = '#ffffff'; - ctx.fillText('Welcome to the server,', canvas.width / 2.5, canvas.height / 3.5); - - ctx.font = applyText(canvas, `${member.displayName}!`); - ctx.fillStyle = '#ffffff'; - ctx.fillText(`${member.displayName}!`, canvas.width / 2.5, canvas.height / 1.8); - - ctx.beginPath(); - ctx.arc(125, 125, 100, 0, Math.PI * 2, true); - ctx.closePath(); - ctx.clip(); - - const avatar = await Canvas.loadImage(member.user.displayAvatarURL); - ctx.drawImage(avatar, 25, 25, 200, 200); - - const attachment = new Discord.Attachment(canvas.toBuffer(), 'welcome-image.png'); - - channel.send(`Welcome to the server, ${member}!`, attachment); -}); - -client.on('message', async message => { - if (message.content === '!join') { - client.emit('guildMemberAdd', message.member || await message.guild.fetchMember(message.author)); - } -}); - -client.login('your-token-goes-here'); diff --git a/Ajuda/guide-master/code-samples/popular-topics/canvas/11/wallpaper.jpg b/Ajuda/guide-master/code-samples/popular-topics/canvas/11/wallpaper.jpg deleted file mode 100644 index dda9156..0000000 Binary files a/Ajuda/guide-master/code-samples/popular-topics/canvas/11/wallpaper.jpg and /dev/null differ diff --git a/Ajuda/guide-master/code-samples/popular-topics/canvas/12/index.js b/Ajuda/guide-master/code-samples/popular-topics/canvas/12/index.js deleted file mode 100644 index 431ae6c..0000000 --- a/Ajuda/guide-master/code-samples/popular-topics/canvas/12/index.js +++ /dev/null @@ -1,61 +0,0 @@ -const Discord = require('discord.js'); -const Canvas = require('canvas'); - -const client = new Discord.Client(); - -client.once('ready', () => { - console.log('Ready!'); -}); - -const applyText = (canvas, text) => { - const ctx = canvas.getContext('2d'); - let fontSize = 70; - - do { - ctx.font = `${fontSize -= 10}px sans-serif`; - } while (ctx.measureText(text).width > canvas.width - 300); - - return ctx.font; -}; - -client.on('guildMemberAdd', async member => { - const channel = member.guild.channels.find(ch => ch.name === 'member-log'); - if (!channel) return; - - const canvas = Canvas.createCanvas(700, 250); - const ctx = canvas.getContext('2d'); - - const background = await Canvas.loadImage('./wallpaper.jpg'); - ctx.drawImage(background, 0, 0, canvas.width, canvas.height); - - ctx.strokeStyle = '#74037b'; - ctx.strokeRect(0, 0, canvas.width, canvas.height); - - ctx.font = '28px sans-serif'; - ctx.fillStyle = '#ffffff'; - ctx.fillText('Welcome to the server,', canvas.width / 2.5, canvas.height / 3.5); - - ctx.font = applyText(canvas, `${member.displayName}!`); - ctx.fillStyle = '#ffffff'; - ctx.fillText(`${member.displayName}!`, canvas.width / 2.5, canvas.height / 1.8); - - ctx.beginPath(); - ctx.arc(125, 125, 100, 0, Math.PI * 2, true); - ctx.closePath(); - ctx.clip(); - - const avatar = await Canvas.loadImage(member.user.displayAvatarURL({ format: 'jpg' })); - ctx.drawImage(avatar, 25, 25, 200, 200); - - const attachment = new Discord.MessageAttachment(canvas.toBuffer(), 'welcome-image.png'); - - channel.send(`Welcome to the server, ${member}!`, attachment); -}); - -client.on('message', message => { - if (message.content === '!join') { - client.emit('guildMemberAdd', message.member); - } -}); - -client.login('your-token-goes-here'); diff --git a/Ajuda/guide-master/code-samples/popular-topics/canvas/12/wallpaper.jpg b/Ajuda/guide-master/code-samples/popular-topics/canvas/12/wallpaper.jpg deleted file mode 100644 index dda9156..0000000 Binary files a/Ajuda/guide-master/code-samples/popular-topics/canvas/12/wallpaper.jpg and /dev/null differ diff --git a/Ajuda/guide-master/code-samples/popular-topics/permissions/11/index.js b/Ajuda/guide-master/code-samples/popular-topics/permissions/11/index.js deleted file mode 100644 index 9ebec7a..0000000 --- a/Ajuda/guide-master/code-samples/popular-topics/permissions/11/index.js +++ /dev/null @@ -1,126 +0,0 @@ -const util = require('util'); -const { Client, Permissions } = require('discord.js'); -const client = new Client(); - -client.once('ready', () => { - console.log('Ready!'); -}); - -client.on('message', message => { - if (message.author.bot || !message.content.startsWith('!')) return; - if (!message.channel.permissionsFor(client.user).has('SEND_MESSAGES')) return; - - const botPerms = ['MANAGE_MESSAGES', 'KICK_MEMBERS', 'MANAGE_ROLES', 'MANAGE_CHANNELS']; - - if (!message.guild.me.permissions.has(botPerms)) { - return message.reply(`I need the permissions ${botPerms.join(', ')} for this demonstration to work properly`); - } - - if (message.content === '!mod-everyone') { - const everyonePerms = new Permissions(message.guild.defaultRole.permissions); - const newPerms = everyonePerms.add(['MANAGE_MESSAGES', 'KICK_MEMBERS']); - - message.guild.defaultRole.setPermissions(newPerms.bitfield) - .then(() => message.channel.send('Added mod permissions to `@everyone`.')) - .catch(console.error); - } else if (message.content === '!unmod-everyone') { - const everyonePerms = new Permissions(message.guild.defaultRole.permissions); - const newPerms = everyonePerms.remove(['MANAGE_MESSAGES', 'KICK_MEMBERS']); - - message.guild.defaultRole.setPermissions(newPerms.bitfield) - .then(() => message.channel.send('Removed mod permissions from `@everyone`.')) - .catch(console.error); - } else if (message.content === '!create-mod') { - if (message.guild.roles.some(role => role.name === 'Mod')) { - return message.channel.send('A role with the name "Mod" already exists on this server.'); - } - - message.guild.createRole({ name: 'Mod', permissions: ['MANAGE_MESSAGES', 'KICK_MEMBERS'] }) - .then(() => message.channel.send('Created Mod role.')) - .catch(console.error); - } else if (message.content === '!check-mod') { - if (message.member.roles.some(role => role.name === 'Mod')) { - return message.channel.send('You do have a role called Mod.'); - } - - message.channel.send('You don\'t have a role called Mod.'); - } else if (message.content === '!can-kick') { - if (message.member.hasPermission('KICK_MEMBERS')) { - return message.channel.send('You can kick members.'); - } - - message.channel.send('You cannot kick members.'); - } else if (message.content === '!make-private') { - if (!message.channel.permissionsFor(client.user).has('MANAGE_ROLES')) { - return message.channel.send('Please make sure I have the `MANAGE_ROLES` permissions in this channel and retry.'); - } - - message.channel.replacePermissionOverwrites({ - overwrites: [ - { - id: message.guild.id, - deny: ['VIEW_CHANNEL'], - }, - { - id: client.user.id, - allow: ['VIEW_CHANNEL'], - }, - { - id: message.author.id, - allow: ['VIEW_CHANNEL'], - }, - ], - }) - .then(() => message.channel.send(`Made channel \`${message.channel.name}\` private.`)) - .catch(console.error); - } else if (message.content === '!create-private') { - message.guild.createChannel('private', 'text', [ - { - id: message.guild.id, - deny: ['VIEW_CHANNEL'], - }, - { - id: message.author.id, - allow: ['VIEW_CHANNEL'], - }, - { - id: client.user.id, - allow: ['VIEW_CHANNEL'], - }, - ]) - .then(() => message.channel.send('Created a private channel.')) - .catch(console.error); - } else if (message.content === '!unprivate') { - if (!message.channel.permissionsFor(client.user).has('MANAGE_ROLES')) { - return message.channel.send('Please make sure i have the permissions MANAGE_ROLES in this channel and retry.'); - } - - message.channel.permissionOverwrites.get(message.guild.id).delete() - .then(() => message.channel.send(`Made channel ${message.channel.name} public.`)) - .catch(console.error); - } else if (message.content === '!my-permissions') { - const finalPermissions = message.channel.permissionsFor(message.member); - - message.channel.send(util.inspect(finalPermissions.serialize()), { code: 'js' }); - } else if (message.content === '!lock-permissions') { - if (!message.channel.parent) { - return message.channel.send('This channel is not placed under a category.'); - } - - if (!message.channel.permissionsFor(client.user).has('MANAGE_ROLES')) { - return message.channel.send('Please make sure i have the permissions MANAGE_ROLES in this channel and retry.'); - } - - message.channel.lockPermissions() - .then(() => { - message.channel.send(`Synchronized overwrites of \`${message.channel.name}\` with \`${message.channel.parent.name}\`.`); - }) - .catch(console.error); - } else if (message.content === '!role-permissions') { - const roleFinalPermissions = message.channel.permissionsFor(message.member.highestRole); - - message.channel.send(util.inspect(roleFinalPermissions.serialize()), { code: 'js' }); - } -}); - -client.login('your-token-goes-here'); diff --git a/Ajuda/guide-master/code-samples/popular-topics/permissions/12/index.js b/Ajuda/guide-master/code-samples/popular-topics/permissions/12/index.js deleted file mode 100644 index 49011d3..0000000 --- a/Ajuda/guide-master/code-samples/popular-topics/permissions/12/index.js +++ /dev/null @@ -1,128 +0,0 @@ -const util = require('util'); -const { Client, Permissions } = require('discord.js'); -const client = new Client(); - -client.once('ready', () => { - console.log('Ready!'); -}); - -client.on('message', message => { - if (message.author.bot || !message.content.startsWith('!')) return; - if (!message.channel.permissionsFor(client.user).has('SEND_MESSAGES')) return; - - const botPerms = ['MANAGE_MESSAGES', 'KICK_MEMBERS', 'MANAGE_ROLES', 'MANAGE_CHANNELS']; - - if (!message.guild.me.permissions.has(botPerms)) { - return message.reply(`I need the permissions ${botPerms.join(', ')} for this demonstration to work properly`); - } - - if (message.content === '!mod-everyone') { - const everyonePerms = new Permissions(message.guild.defaultRole.permissions); - const newPerms = everyonePerms.add(['MANAGE_MESSAGES', 'KICK_MEMBERS']); - - message.guild.defaultRole.setPermissions(newPerms.bitfield) - .then(() => message.channel.send('Added mod permissions to `@everyone`.')) - .catch(console.error); - } else if (message.content === '!unmod-everyone') { - const everyonePerms = new Permissions(message.guild.defaultRole.permissions); - const newPerms = everyonePerms.remove(['MANAGE_MESSAGES', 'KICK_MEMBERS']); - - message.guild.defaultRole.setPermissions(newPerms.bitfield) - .then(() => message.channel.send('Removed mod permissions from `@everyone`.')) - .catch(console.error); - } else if (message.content === '!create-mod') { - if (message.guild.roles.some(role => role.name === 'Mod')) { - return message.channel.send('A role with the name "Mod" already exists on this server.'); - } - - message.guild.roles.create({ data: { name: 'Mod', permissions: ['MANAGE_MESSAGES', 'KICK_MEMBERS'] } }) - .then(() => message.channel.send('Created Mod role.')) - .catch(console.error); - } else if (message.content === '!check-mod') { - if (message.member.roles.some(role => role.name === 'Mod')) { - return message.channel.send('You do have a role called Mod.'); - } - - message.channel.send('You don\'t have a role called Mod.'); - } else if (message.content === '!can-kick') { - if (message.member.hasPermission('KICK_MEMBERS')) { - return message.channel.send('You can kick members.'); - } - - message.channel.send('You cannot kick members.'); - } else if (message.content === '!make-private') { - if (!message.channel.permissionsFor(client.user).has('MANAGE_ROLES')) { - return message.channel.send('Please make sure I have the `MANAGE_ROLES` permissions in this channel and retry.'); - } - - message.channel.overwritePermissions({ - permissionOverwrites: [ - { - id: message.guild.id, - deny: ['VIEW_CHANNEL'], - }, - { - id: client.user.id, - allow: ['VIEW_CHANNEL'], - }, - { - id: message.author.id, - allow: ['VIEW_CHANNEL'], - }, - ], - }) - .then(() => message.channel.send(`Made channel \`${message.channel.name}\` private.`)) - .catch(console.error); - } else if (message.content === '!create-private') { - message.guild.channels.create('private', { - type: 'text', permissionOverwrites: [ - { - id: message.guild.id, - deny: ['VIEW_CHANNEL'], - }, - { - id: message.author.id, - allow: ['VIEW_CHANNEL'], - }, - { - id: client.user.id, - allow: ['VIEW_CHANNEL'], - }, - ], - }) - .then(() => message.channel.send('Created a private channel.')) - .catch(console.error); - } else if (message.content === '!unprivate') { - if (!message.channel.permissionsFor(client.user).has('MANAGE_ROLES')) { - return message.channel.send('Please make sure i have the permissions MANAGE_ROLES in this channel and retry.'); - } - - message.channel.permissionOverwrites.get(message.guild.id).delete() - .then(() => message.channel.send(`Made channel ${message.channel.name} public.`)) - .catch(console.error); - } else if (message.content === '!my-permissions') { - const finalPermissions = message.channel.permissionsFor(message.member); - - message.channel.send(util.inspect(finalPermissions.serialize()), { code: 'js' }); - } else if (message.content === '!lock-permissions') { - if (!message.channel.parent) { - return message.channel.send('This channel is not placed under a category.'); - } - - if (!message.channel.permissionsFor(client.user).has('MANAGE_ROLES')) { - return message.channel.send('Please make sure i have the permissions MANAGE_ROLES in this channel and retry.'); - } - - message.channel.lockPermissions() - .then(() => { - message.channel.send(`Synchronized overwrites of \`${message.channel.name}\` with \`${message.channel.parent.name}\`.`); - }) - .catch(console.error); - } else if (message.content === '!role-permissions') { - const roleFinalPermissions = message.channel.permissionsFor(message.member.roles.highest); - - message.channel.send(util.inspect(roleFinalPermissions.serialize()), { code: 'js' }); - } -}); - -client.login('your-token-goes-here'); diff --git a/Ajuda/guide-master/code-samples/popular-topics/reactions/11/awaiting-reactions.js b/Ajuda/guide-master/code-samples/popular-topics/reactions/11/awaiting-reactions.js deleted file mode 100644 index 92caf59..0000000 --- a/Ajuda/guide-master/code-samples/popular-topics/reactions/11/awaiting-reactions.js +++ /dev/null @@ -1,33 +0,0 @@ -const Discord = require('discord.js'); -const client = new Discord.Client(); - -client.once('ready', () => { - console.log('Ready!'); -}); - -client.on('message', message => { - if (message.content === '!react-await') { - message.react('👍').then(() => message.react('👎')); - - const filter = (reaction, user) => { - return ['👍', '👎'].includes(reaction.emoji.name) && user.id === message.author.id; - }; - - message.awaitReactions(filter, { maxMatches: 1, time: 60000, errors: ['time'] }) - .then(collected => { - const reaction = collected.first(); - - if (reaction.emoji.name === '👍') { - message.reply('you reacted with a thumbs up.'); - } else { - message.reply('you reacted with a thumbs down.'); - } - }) - .catch(collected => { - console.log(`After a minute, only ${collected.size} out of 4 reacted.`); - message.reply('you didn\'t react with neither a thumbs up, nor a thumbs down.'); - }); - } -}); - -client.login('your-token-goes-here'); diff --git a/Ajuda/guide-master/code-samples/popular-topics/reactions/11/basic-reacting.js b/Ajuda/guide-master/code-samples/popular-topics/reactions/11/basic-reacting.js deleted file mode 100644 index a1c4e62..0000000 --- a/Ajuda/guide-master/code-samples/popular-topics/reactions/11/basic-reacting.js +++ /dev/null @@ -1,21 +0,0 @@ -const Discord = require('discord.js'); -const client = new Discord.Client(); - -client.once('ready', () => { - console.log('Ready!'); -}); - -client.on('message', message => { - if (message.content === '!react') { - message.react('😄'); - } else if (message.content === '!react-custom') { - message.react('396548322053062656'); - } else if (message.content === '!fruits') { - message.react('🍎') - .then(() => message.react('🍊')) - .then(() => message.react('🍇')) - .catch(() => console.error('One of the emojis failed to react.')); - } -}); - -client.login('your-token-goes-here'); diff --git a/Ajuda/guide-master/code-samples/popular-topics/reactions/12/awaiting-reactions.js b/Ajuda/guide-master/code-samples/popular-topics/reactions/12/awaiting-reactions.js deleted file mode 100644 index 2c494e8..0000000 --- a/Ajuda/guide-master/code-samples/popular-topics/reactions/12/awaiting-reactions.js +++ /dev/null @@ -1,33 +0,0 @@ -const Discord = require('discord.js'); -const client = new Discord.Client(); - -client.once('ready', () => { - console.log('Ready!'); -}); - -client.on('message', message => { - if (message.content === '!react-await') { - message.react('👍').then(() => message.react('👎')); - - const filter = (reaction, user) => { - return ['👍', '👎'].includes(reaction.emoji.name) && user.id === message.author.id; - }; - - message.awaitReactions(filter, { max: 1, time: 60000, errors: ['time'] }) - .then(collected => { - const reaction = collected.first(); - - if (reaction.emoji.name === '👍') { - message.reply('you reacted with a thumbs up.'); - } else { - message.reply('you reacted with a thumbs down.'); - } - }) - .catch(collected => { - console.log(`After a minute, only ${collected.size} out of 4 reacted.`); - message.reply('you didn\'t react with neither a thumbs up, nor a thumbs down.'); - }); - } -}); - -client.login('your-token-goes-here'); diff --git a/Ajuda/guide-master/code-samples/popular-topics/reactions/12/basic-reacting.js b/Ajuda/guide-master/code-samples/popular-topics/reactions/12/basic-reacting.js deleted file mode 100644 index a1c4e62..0000000 --- a/Ajuda/guide-master/code-samples/popular-topics/reactions/12/basic-reacting.js +++ /dev/null @@ -1,21 +0,0 @@ -const Discord = require('discord.js'); -const client = new Discord.Client(); - -client.once('ready', () => { - console.log('Ready!'); -}); - -client.on('message', message => { - if (message.content === '!react') { - message.react('😄'); - } else if (message.content === '!react-custom') { - message.react('396548322053062656'); - } else if (message.content === '!fruits') { - message.react('🍎') - .then(() => message.react('🍊')) - .then(() => message.react('🍇')) - .catch(() => console.error('One of the emojis failed to react.')); - } -}); - -client.login('your-token-goes-here'); diff --git a/Ajuda/guide-master/code-samples/popular-topics/reactions/12/uncached-messages.js b/Ajuda/guide-master/code-samples/popular-topics/reactions/12/uncached-messages.js deleted file mode 100644 index 2d6c5cf..0000000 --- a/Ajuda/guide-master/code-samples/popular-topics/reactions/12/uncached-messages.js +++ /dev/null @@ -1,30 +0,0 @@ -const Discord = require('discord.js'); -const client = new Discord.Client({ partials: ['MESSAGE', 'CHANNEL'] }); - -client.once('ready', () => { - console.log('Ready!'); -}); - -client.on('messageReactionAdd', async (reaction, user) => { - if (reaction.message.partial) { - try { - await reaction.message.fetch(); - } catch (error) { - console.log('Something went wrong when fetching the message: ', error); - } - } - console.log(`${user.username} reacted with "${reaction.emoji.name}".`); -}); - -client.on('messageReactionRemove', async (reaction, user) => { - if (reaction.message.partial) { - try { - await reaction.message.fetch(); - } catch (error) { - console.log('Something went wrong when fetching the message: ', error); - } - } - console.log(`${user.username} removed their "${reaction.emoji.name}" reaction.`); -}); - -client.login('your-token-goes-here'); diff --git a/Ajuda/guide-master/code-samples/sequelize/currency/app.js b/Ajuda/guide-master/code-samples/sequelize/currency/app.js deleted file mode 100644 index d332ba0..0000000 --- a/Ajuda/guide-master/code-samples/sequelize/currency/app.js +++ /dev/null @@ -1,100 +0,0 @@ -const config = require('./config'); -const Discord = require('discord.js'); - -const client = new Discord.Client(); -const { Users, CurrencyShop } = require('./dbObjects'); -const { Op } = require('sequelize'); -const currency = new Discord.Collection(); -const PREFIX = '!'; - -/* - * Make sure you are on at least version 5 of Sequelize! Version 4 as used in this guide will pose a security threat. - * You can read more about this issue On the [Sequelize issue tracker](https://github.com/sequelize/sequelize/issues/7310). - */ - -Reflect.defineProperty(currency, 'add', { - value: async function add(id, amount) { - const user = currency.get(id); - if (user) { - user.balance += Number(amount); - return user.save(); - } - const newUser = await Users.create({ user_id: id, balance: amount }); - currency.set(id, newUser); - return newUser; - }, -}); - -Reflect.defineProperty(currency, 'getBalance', { - value: function getBalance(id) { - const user = currency.get(id); - return user ? user.balance : 0; - }, -}); - -client.once('ready', async () => { - const storedBalances = await Users.findAll(); - storedBalances.forEach(b => currency.set(b.user_id, b)); - console.log(`Logged in as ${client.user.tag}!`); -}); - -client.on('message', async message => { - if (message.author.bot) return; - currency.add(message.author.id, 1); - - if (!message.content.startsWith(PREFIX)) return; - const input = message.content.slice(PREFIX.length).trim(); - if (!input.length) return; - const [, command, commandArgs] = input.match(/(\w+)\s*([\s\S]*)/); - - if (command === 'balance') { - const target = message.mentions.users.first() || message.author; - return message.channel.send(`${target.tag} has ${currency.getBalance(target.id)}💰`); - } else if (command === 'inventory') { - const target = message.mentions.users.first() || message.author; - const user = await Users.findOne({ where: { user_id: target.id } }); - const items = await user.getItems(); - - if (!items.length) return message.channel.send(`${target.tag} has nothing!`); - return message.channel.send(`${target.tag} currently has ${items.map(t => `${t.amount} ${t.item.name}`).join(', ')}`); - } else if (command === 'transfer') { - const currentAmount = currency.getBalance(message.author.id); - const transferAmount = commandArgs.split(/ +/).find(arg => !/<@!?\d+>/.test(arg)); - const transferTarget = message.mentions.users.first(); - - if (!transferAmount || isNaN(transferAmount)) return message.channel.send(`Sorry ${message.author}, that's an invalid amount`); - if (transferAmount > currentAmount) return message.channel.send(`Sorry ${message.author} you don't have that much.`); - if (transferAmount <= 0) return message.channel.send(`Please enter an amount greater than zero, ${message.author}`); - - currency.add(message.author.id, -transferAmount); - currency.add(transferTarget.id, transferAmount); - - return message.channel.send(`Successfully transferred ${transferAmount}💰 to ${transferTarget.tag}. Your current balance is ${currency.getBalance(message.author.id)}💰`); - } else if (command === 'buy') { - const item = await CurrencyShop.findOne({ where: { name: { [Op.like]: commandArgs } } }); - if (!item) return message.channel.send('That item doesn\'t exist.'); - if (item.cost > currency.getBalance(message.author.id)) { - return message.channel.send(`You don't have enough currency, ${message.author}`); - } - - const user = await Users.findOne({ where: { user_id: message.author.id } }); - currency.add(message.author.id, -item.cost); - await user.addItem(item); - - message.channel.send(`You've bought a ${item.name}`); - } else if (command === 'shop') { - const items = await CurrencyShop.findAll(); - return message.channel.send(items.map(i => `${i.name}: ${i.cost}💰`).join('\n'), { code: true }); - } else if (command === 'leaderboard') { - return message.channel.send( - currency.sort((a, b) => b.balance - a.balance) - .filter(user => client.users.has(user.user_id)) - .first(10) - .map((user, position) => `(${position + 1}) ${(client.users.get(user.user_id).tag)}: ${user.balance}💰`) - .join('\n'), - { code: true } - ); - } -}); - -client.login(config.token); diff --git a/Ajuda/guide-master/code-samples/sequelize/currency/dbInit.js b/Ajuda/guide-master/code-samples/sequelize/currency/dbInit.js deleted file mode 100644 index 144dbc0..0000000 --- a/Ajuda/guide-master/code-samples/sequelize/currency/dbInit.js +++ /dev/null @@ -1,30 +0,0 @@ -const Sequelize = require('sequelize'); - -/* - * Make sure you are on at least version 5 of Sequelize! Version 4 as used in this guide will pose a security threat. - * You can read more about this issue On the [Sequelize issue tracker](https://github.com/sequelize/sequelize/issues/7310). - */ - -const sequelize = new Sequelize('database', 'username', 'password', { - host: 'localhost', - dialect: 'sqlite', - logging: false, - storage: 'database.sqlite', -}); - -const CurrencyShop = sequelize.import('models/CurrencyShop'); -sequelize.import('models/Users'); -sequelize.import('models/UserItems'); - -const force = process.argv.includes('--force') || process.argv.includes('-f'); - -sequelize.sync({ force }).then(async () => { - const shop = [ - CurrencyShop.upsert({ name: 'Tea', cost: 1 }), - CurrencyShop.upsert({ name: 'Coffee', cost: 2 }), - CurrencyShop.upsert({ name: 'Cake', cost: 5 }), - ]; - await Promise.all(shop); - console.log('Database synced'); - sequelize.close(); -}).catch(console.error); diff --git a/Ajuda/guide-master/code-samples/sequelize/currency/dbObjects.js b/Ajuda/guide-master/code-samples/sequelize/currency/dbObjects.js deleted file mode 100644 index 4be89ca..0000000 --- a/Ajuda/guide-master/code-samples/sequelize/currency/dbObjects.js +++ /dev/null @@ -1,41 +0,0 @@ -const Sequelize = require('sequelize'); - -/* - * Make sure you are on at least version 5 of Sequelize! Version 4 as used in this guide will pose a security threat. - * You can read more about this issue On the [Sequelize issue tracker](https://github.com/sequelize/sequelize/issues/7310). - */ - -const sequelize = new Sequelize('database', 'username', 'password', { - host: 'localhost', - dialect: 'sqlite', - logging: false, - storage: 'database.sqlite', -}); - -const Users = sequelize.import('models/Users'); -const CurrencyShop = sequelize.import('models/CurrencyShop'); -const UserItems = sequelize.import('models/UserItems'); - -UserItems.belongsTo(CurrencyShop, { foreignKey: 'item_id', as: 'item' }); - -Users.prototype.addItem = async function(item) { - const useritem = await UserItems.findOne({ - where: { user_id: this.user_id, item_id: item.id }, - }); - - if (useritem) { - useritem.amount += 1; - return useritem.save(); - } - - return UserItems.create({ user_id: this.user_id, item_id: item.id, amount: 1 }); -}; - -Users.prototype.getItems = function() { - return UserItems.findAll({ - where: { user_id: this.user_id }, - include: ['item'], - }); -}; - -module.exports = { Users, CurrencyShop, UserItems }; diff --git a/Ajuda/guide-master/code-samples/sequelize/currency/models/CurrencyShop.js b/Ajuda/guide-master/code-samples/sequelize/currency/models/CurrencyShop.js deleted file mode 100644 index 1c9099d..0000000 --- a/Ajuda/guide-master/code-samples/sequelize/currency/models/CurrencyShop.js +++ /dev/null @@ -1,14 +0,0 @@ -module.exports = (sequelize, DataTypes) => { - return sequelize.define('currency_shop', { - name: { - type: DataTypes.STRING, - unique: true, - }, - cost: { - type: DataTypes.INTEGER, - allowNull: false, - }, - }, { - timestamps: false, - }); -}; diff --git a/Ajuda/guide-master/code-samples/sequelize/currency/models/UserItems.js b/Ajuda/guide-master/code-samples/sequelize/currency/models/UserItems.js deleted file mode 100644 index d7854e4..0000000 --- a/Ajuda/guide-master/code-samples/sequelize/currency/models/UserItems.js +++ /dev/null @@ -1,13 +0,0 @@ -module.exports = (sequelize, DataTypes) => { - return sequelize.define('user_item', { - user_id: DataTypes.STRING, - item_id: DataTypes.STRING, - amount: { - type: DataTypes.INTEGER, - allowNull: false, - 'default': 0, - }, - }, { - timestamps: false, - }); -}; diff --git a/Ajuda/guide-master/code-samples/sequelize/currency/models/Users.js b/Ajuda/guide-master/code-samples/sequelize/currency/models/Users.js deleted file mode 100644 index 67d4f6f..0000000 --- a/Ajuda/guide-master/code-samples/sequelize/currency/models/Users.js +++ /dev/null @@ -1,15 +0,0 @@ -module.exports = (sequelize, DataTypes) => { - return sequelize.define('users', { - user_id: { - type: DataTypes.STRING, - primaryKey: true, - }, - balance: { - type: DataTypes.INTEGER, - defaultValue: 0, - allowNull: false, - }, - }, { - timestamps: false, - }); -}; diff --git a/Ajuda/guide-master/code-samples/sequelize/tags/sequelize.js b/Ajuda/guide-master/code-samples/sequelize/tags/sequelize.js deleted file mode 100644 index 7cdabfb..0000000 --- a/Ajuda/guide-master/code-samples/sequelize/tags/sequelize.js +++ /dev/null @@ -1,118 +0,0 @@ -const Discord = require('discord.js'); -const Sequelize = require('sequelize'); - -const client = new Discord.Client(); -const PREFIX = '!'; - -/* - * Make sure you are on at least version 5 of Sequelize! Version 4 as used in this guide will pose a security threat. - * You can read more about this issue On the [Sequelize issue tracker](https://github.com/sequelize/sequelize/issues/7310). - */ - -const sequelize = new Sequelize('database', 'username', 'password', { - host: 'localhost', - dialect: 'sqlite', - logging: false, - // SQLite only - storage: 'database.sqlite', -}); - -const Tags = sequelize.define('tags', { - name: { - type: Sequelize.STRING, - unique: true, - }, - description: Sequelize.TEXT, - username: Sequelize.STRING, - usage_count: { - type: Sequelize.INTEGER, - defaultValue: 0, - allowNull: false, - }, -}); - -client.once('ready', () => { - /* - * equivalent to: CREATE TABLE tags( - * name VARCHAR(255), - * description TEXT, - * username VARCHAR(255), - * usage INT - * ); - */ - Tags.sync(); -}); - -client.on('message', async message => { - if (message.content.startsWith(PREFIX)) { - const input = message.content.slice(PREFIX.length).split(' '); - const command = input.shift(); - const commandArgs = input.join(' '); - - if (command === 'addtag') { - const splitArgs = commandArgs.split(' '); - const tagName = splitArgs.shift(); - const tagDescription = splitArgs.join(' '); - - try { - // equivalent to: INSERT INTO tags (name, descrption, username) values (?, ?, ?); - const tag = await Tags.create({ - name: tagName, - description: tagDescription, - username: message.author.username, - }); - return message.reply(`Tag ${tag.name} added.`); - } catch (e) { - if (e.name === 'SequelizeUniqueConstraintError') { - return message.reply('That tag already exists.'); - } - return message.reply('Something went wrong with adding a tag.'); - } - } else if (command === 'tag') { - const tagName = commandArgs; - - // equivalent to: SELECT * FROM tags WHERE name = 'tagName' LIMIT 1; - const tag = await Tags.findOne({ where: { name: tagName } }); - if (tag) { - // equivalent to: UPDATE tags SET usage_count = usage_count + 1 WHERE name = 'tagName'; - tag.increment('usage_count'); - return message.channel.send(tag.get('description')); - } - return message.reply(`Could not find tag: ${tagName}`); - } else if (command === 'edittag') { - const splitArgs = commandArgs.split(' '); - const tagName = splitArgs.shift(); - const tagDescription = splitArgs.join(' '); - - // equivalent to: UPDATE tags (descrption) values (?) WHERE name = ?; - const affectedRows = await Tags.update({ description: tagDescription }, { where: { name: tagName } }); - if (affectedRows > 0) { - return message.reply(`Tag ${tagName} was edited.`); - } - return message.reply(`Could not find a tag with name ${tagName}.`); - } else if (command === 'taginfo') { - const tagName = commandArgs; - - // equivalent to: SELECT * FROM tags WHERE name = 'tagName' LIMIT 1; - const tag = await Tags.findOne({ where: { name: tagName } }); - if (tag) { - return message.channel.send(`${tagName} was created by ${tag.username} at ${tag.createdAt} and has been used ${tag.usage_count} times.`); - } - return message.reply(`Could not find tag: ${tagName}`); - } else if (command === 'showtags') { - // equivalent to: SELECT name FROM tags; - const tagList = await Tags.findAll({ attributes: ['name'] }); - const tagString = tagList.map(t => t.name).join(', ') || 'No tags set.'; - return message.channel.send(`List of tags: ${tagString}`); - } else if (command === 'removetag') { - // equivalent to: DELETE from tags WHERE name = ?; - const tagName = commandArgs; - const rowCount = await Tags.destroy({ where: { name: tagName } }); - if (!rowCount) return message.reply('That tag did not exist.'); - - return message.reply('Tag deleted.'); - } - } -}); - -client.login('your-token-goes-here'); diff --git a/Ajuda/guide-master/code-samples/sharding/extended/bot.js b/Ajuda/guide-master/code-samples/sharding/extended/bot.js deleted file mode 100644 index 94dc4cf..0000000 --- a/Ajuda/guide-master/code-samples/sharding/extended/bot.js +++ /dev/null @@ -1,70 +0,0 @@ -const Discord = require('discord.js'); -const client = new Discord.Client(); -const prefix = '!'; - -function findEmoji(id) { - const temp = this.emojis.get(id); - if (!temp) return null; - - const emoji = Object.assign({}, temp); - if (emoji.guild) emoji.guild = emoji.guild.id; - emoji.require_colons = emoji.requiresColons; - - return emoji; -} - -client.on('message', message => { - if (!message.content.startsWith(prefix) || message.author.bot) return; - - const args = message.content.slice(prefix.length).split(/ +/); - const command = args.shift().toLowerCase(); - - if (command === 'stats') { - return client.shard.broadcastEval('this.guilds.size') - .then(results => { - return message.channel.send(`Server count: ${results.reduce((prev, val) => prev + val, 0)}`); - }) - .catch(console.error); - } - - if (command === 'send') { - if (!args.length) return message.reply('please specify a destination channel id.'); - - return client.shard.broadcastEval(` - const channel = this.channels.get('${args[0]}'); - if (channel) { - channel.send('This is a message from shard ${this.shard.id}!'); - true; - } - else { - false; - } - `) - .then(sentArray => { - if (!sentArray.includes(true)) { - return message.reply('I could not find such a channel.'); - } - - return message.reply(`I have sent a message to channel \`${args[0]}\`!`); - }); - } - - if (command === 'emoji') { - if (!args.length) return message.reply('please specify an emoji id to search for.'); - - return client.shard.broadcastEval(`(${findEmoji}).call(this, '${args[0]}')`) - .then(emojiArray => { - const foundEmoji = emojiArray.find(emoji => emoji); - if (!foundEmoji) return message.reply('I could not find such an emoji.'); - - return client.rest.makeRequest('get', Discord.Constants.Endpoints.Guild(foundEmoji.guild).toString(), true) - .then(raw => { - const guild = new Discord.Guild(client, raw); - const emoji = new Discord.Emoji(guild, foundEmoji); - return message.reply(`I have found an emoji ${emoji.toString()}!`); - }); - }); - } -}); - -client.login('token'); diff --git a/Ajuda/guide-master/code-samples/sharding/extended/index.js b/Ajuda/guide-master/code-samples/sharding/extended/index.js deleted file mode 100644 index 36b1daa..0000000 --- a/Ajuda/guide-master/code-samples/sharding/extended/index.js +++ /dev/null @@ -1,5 +0,0 @@ -const { ShardingManager } = require('discord.js'); -const manager = new ShardingManager('./bot.js', { token: 'your-token-goes-here' }); - -manager.spawn(); -manager.on('launch', shard => console.log(`Launched shard ${shard.id}`)); diff --git a/Ajuda/guide-master/code-samples/sharding/getting-started/bot.js b/Ajuda/guide-master/code-samples/sharding/getting-started/bot.js deleted file mode 100644 index 720e24c..0000000 --- a/Ajuda/guide-master/code-samples/sharding/getting-started/bot.js +++ /dev/null @@ -1,28 +0,0 @@ -const Discord = require('discord.js'); -const client = new Discord.Client(); -const prefix = '!'; - - -client.on('message', message => { - if (!message.content.startsWith(prefix) || message.author.bot) return; - - const args = message.content.slice(prefix.length).split(/ +/); - const command = args.shift().toLowerCase(); - - if (command === 'stats') { - const promises = [ - client.shard.fetchClientValues('guilds.size'), - client.shard.broadcastEval('this.guilds.reduce((prev, guild) => prev + guild.memberCount, 0)'), - ]; - - return Promise.all(promises) - .then(results => { - const totalGuilds = results[0].reduce((prev, guildCount) => prev + guildCount, 0); - const totalMembers = results[1].reduce((prev, memberCount) => prev + memberCount, 0); - return message.channel.send(`Server count: ${totalGuilds}\nMember count: ${totalMembers}`); - }) - .catch(console.error); - } -}); - -client.login('token'); diff --git a/Ajuda/guide-master/code-samples/sharding/getting-started/index.js b/Ajuda/guide-master/code-samples/sharding/getting-started/index.js deleted file mode 100644 index 36b1daa..0000000 --- a/Ajuda/guide-master/code-samples/sharding/getting-started/index.js +++ /dev/null @@ -1,5 +0,0 @@ -const { ShardingManager } = require('discord.js'); -const manager = new ShardingManager('./bot.js', { token: 'your-token-goes-here' }); - -manager.spawn(); -manager.on('launch', shard => console.log(`Launched shard ${shard.id}`)); diff --git a/Ajuda/guide-master/guide/.eslintrc.js b/Ajuda/guide-master/guide/.eslintrc.js deleted file mode 100644 index ff5319c..0000000 --- a/Ajuda/guide-master/guide/.eslintrc.js +++ /dev/null @@ -1,9 +0,0 @@ -const path = require('path'); - -module.exports = { - extends: path.join(__dirname, '..', '.eslintrc.js'), - rules: { - 'no-undef': 'off', - 'no-unused-vars': 'off', - }, -}; diff --git a/Ajuda/guide-master/guide/.vuepress/branches.js b/Ajuda/guide-master/guide/.vuepress/branches.js deleted file mode 100644 index cc1acad..0000000 --- a/Ajuda/guide-master/guide/.vuepress/branches.js +++ /dev/null @@ -1,12 +0,0 @@ -export default [ - { - label: 'v11.5 (stable)', - version: '11.x', - aliases: ['11', 'stable'], - }, - { - label: 'v12.x (master)', - version: '12.x', - aliases: ['12', 'master'], - }, -]; diff --git a/Ajuda/guide-master/guide/.vuepress/components/Branch.vue b/Ajuda/guide-master/guide/.vuepress/components/Branch.vue deleted file mode 100644 index 8c0e866..0000000 --- a/Ajuda/guide-master/guide/.vuepress/components/Branch.vue +++ /dev/null @@ -1,55 +0,0 @@ - - - diff --git a/Ajuda/guide-master/guide/.vuepress/components/BranchSelector.vue b/Ajuda/guide-master/guide/.vuepress/components/BranchSelector.vue deleted file mode 100644 index ea649c5..0000000 --- a/Ajuda/guide-master/guide/.vuepress/components/BranchSelector.vue +++ /dev/null @@ -1,97 +0,0 @@ - - - - - diff --git a/Ajuda/guide-master/guide/.vuepress/components/ResultingCode.vue b/Ajuda/guide-master/guide/.vuepress/components/ResultingCode.vue deleted file mode 100644 index 785c36f..0000000 --- a/Ajuda/guide-master/guide/.vuepress/components/ResultingCode.vue +++ /dev/null @@ -1,28 +0,0 @@ - - - diff --git a/Ajuda/guide-master/guide/.vuepress/config.js b/Ajuda/guide-master/guide/.vuepress/config.js deleted file mode 100644 index d0aaee4..0000000 --- a/Ajuda/guide-master/guide/.vuepress/config.js +++ /dev/null @@ -1,69 +0,0 @@ -const sidebar = require('./sidebar.js'); - -const config = { - title: 'Discord.js Guide', - description: 'A guide made by the community of discord.js for its users.', - head: [ - ['link', { rel: 'icon', href: '/favicon.png' }], - ['meta', { name: 'theme-color', content: '#42b983' }], - ['meta', { name: 'twitter:card', content: 'summary' }], - ['meta', { name: 'og:title', content: 'Discord.js Guide' }], - ['meta', { name: 'og:description', content: 'A guide made by the community of discord.js for its users.' }], - ['meta', { name: 'og:type', content: 'website' }], - ['meta', { name: 'og:url', content: 'https://discordjs.guide/' }], - ['meta', { name: 'og:locale', content: 'en_US' }], - ['meta', { name: 'og:image', content: '/meta-image.png' }], - ], - plugins: [], - theme: 'yuu', - themeConfig: { - yuu: { - extraOptions: { before: 'BranchSelector' }, - }, - repo: 'discordjs/guide', - docsDir: 'guide', - sidebarDepth: 3, - editLinks: true, - lastUpdated: true, - nav: [ - { - text: 'Home', - link: '/', - }, - { - text: 'Commando', - link: '/commando/', - }, - { - text: 'Discord.js Documentation', - link: 'https://discord.js.org/#/docs/main/stable/general/welcome', - }, - ], - sidebar, - }, - configureWebpack: { - resolve: { - alias: { - '@': '../', - }, - }, - }, -}; - -for (const group of Object.values(config.themeConfig.sidebar)) { - for (const section of group) { - if (section.collapsable) continue; - section.collapsable = false; - } -} - -if (process.env.NODE_ENV === 'production') { - config.themeConfig.algolia = { - apiKey: 'c8d9361fb8403f7c5111887e0edf4b5e', - indexName: 'discordjs', - }; - - config.plugins.push(['@vuepress/google-analytics', { ga: 'UA-108513187-1' }]); -} - -module.exports = config; diff --git a/Ajuda/guide-master/guide/.vuepress/enhanceApp.js b/Ajuda/guide-master/guide/.vuepress/enhanceApp.js deleted file mode 100644 index ae6bcf2..0000000 --- a/Ajuda/guide-master/guide/.vuepress/enhanceApp.js +++ /dev/null @@ -1,9 +0,0 @@ -import VueDiscordMessage from 'vue-discord-message'; - -export default ({ Vue }) => { - Vue.use(VueDiscordMessage, { - avatars: { - djs: require('../images/discord-avatar-djs.png'), - }, - }); -}; diff --git a/Ajuda/guide-master/guide/.vuepress/eventBus.js b/Ajuda/guide-master/guide/.vuepress/eventBus.js deleted file mode 100644 index c17d88a..0000000 --- a/Ajuda/guide-master/guide/.vuepress/eventBus.js +++ /dev/null @@ -1,2 +0,0 @@ -import Vue from 'vue'; -export default new Vue(); diff --git a/Ajuda/guide-master/guide/.vuepress/public/favicon.png b/Ajuda/guide-master/guide/.vuepress/public/favicon.png deleted file mode 100644 index 123bd61..0000000 Binary files a/Ajuda/guide-master/guide/.vuepress/public/favicon.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/.vuepress/public/meta-image.png b/Ajuda/guide-master/guide/.vuepress/public/meta-image.png deleted file mode 100644 index c07f381..0000000 Binary files a/Ajuda/guide-master/guide/.vuepress/public/meta-image.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/.vuepress/sidebar.js b/Ajuda/guide-master/guide/.vuepress/sidebar.js deleted file mode 100644 index b1399bd..0000000 --- a/Ajuda/guide-master/guide/.vuepress/sidebar.js +++ /dev/null @@ -1,137 +0,0 @@ -module.exports = { - '/commando/': [ - { - title: 'Home', - children: [ - '/', - '/requesting-more-content', - ], - }, - { - title: 'Getting Started', - children: [ - '/commando/', - '/commando/first-command', - ], - }, - { - title: 'Extra Command Info', - children: [ - '/commando/throttling', - '/commando/guild-only', - '/commando/permissions', - ], - }, - { - title: 'Arguments', - children: [ - '/commando/args', - '/commando/validators', - ], - }, - { - title: 'Additional Information', - children: [ - '/commando/client-values', - '/commando/unknown-command-response', - ], - }, - ], - '/': [ - { - title: 'Home', - children: [ - '/', - 'requesting-more-content', - ], - }, - { - title: 'Installations & Preparations', - children: [ - '/preparations/', - '/preparations/setting-up-a-linter', - '/preparations/setting-up-a-bot-application', - '/preparations/adding-your-bot-to-servers', - ], - }, - { - title: 'Creating Your Bot', - children: [ - '/creating-your-bot/', - '/creating-your-bot/configuration-files', - '/creating-your-bot/adding-more-commands', - '/creating-your-bot/commands-with-user-input', - ], - }, - { - title: 'Command Handler', - children: [ - '/command-handling/', - '/command-handling/dynamic-commands', - '/command-handling/adding-features', - ], - }, - { - title: 'Popular Topics', - children: [ - '/popular-topics/embeds', - '/popular-topics/errors', - '/popular-topics/permissions', - '/popular-topics/permissions-extended', - '/popular-topics/reactions', - '/popular-topics/collectors', - '/popular-topics/partials', - '/popular-topics/canvas', - '/popular-topics/common-questions', - '/popular-topics/miscellaneous-examples', - ], - }, - { - title: 'Miscellaneous', - children: [ - '/miscellaneous/parsing-mention-arguments', - '/miscellaneous/useful-packages', - ], - }, - { - title: 'Databases', - children: [ - '/sequelize/', - '/sequelize/currency', - '/keyv/', - ], - }, - { - title: 'Sharding', - children: [ - '/sharding/', - '/sharding/additional-information', - '/sharding/extended', - ], - }, - { - title: 'OAuth2', - children: [ - '/oauth2/', - ], - }, - { - title: 'Improving Your Dev Environment', - children: [ - '/improving-dev-environment/pm2', - '/improving-dev-environment/package-json-scripts', - ], - }, - { - title: 'Additional Information', - children: [ - '/additional-info/notation', - '/additional-info/es6-syntax', - '/additional-info/collections', - '/additional-info/async-await', - '/additional-info/rest-api', - '/additional-info/changes-in-v12', - ], - }, - ], -}; diff --git a/Ajuda/guide-master/guide/.vuepress/styles/index.styl b/Ajuda/guide-master/guide/.vuepress/styles/index.styl deleted file mode 100644 index f5574e3..0000000 --- a/Ajuda/guide-master/guide/.vuepress/styles/index.styl +++ /dev/null @@ -1,13 +0,0 @@ -@media screen and (max-width: 600px) { - .navbar .home-link .site-name { - background: url('/favicon.png') top left / contain no-repeat; - text-indent: -999px; - } -} - -@media screen and (max-width: 360px) { - // so that the branch selector and book icon don't overlap each other - .navbar .links { - padding-left: 0.25rem !important; - } -} diff --git a/Ajuda/guide-master/guide/README.md b/Ajuda/guide-master/guide/README.md deleted file mode 100644 index bcf524f..0000000 --- a/Ajuda/guide-master/guide/README.md +++ /dev/null @@ -1,26 +0,0 @@ -# Introduction - -If you're reading this, it probably means you want to learn how to make a bot with discord.js. Awesome! You've come to the right place. -This guide will teach you things such as: -* How to get a bot up and running from scratch; -* How to properly create, organize, and expand on your commands; -* How to use the best practices for common situations; -* and much more. - -This guide will also cover subjects like common errors and how to solve them, keeping your code clean, setting up a proper development environment, etc. -Sounds good? Great! Let's get started, then. - -## Before you begin... - -Alright, making a bot is cool and all, but there are some prerequisites to it. To create a bot with discord.js, you should have a fairly decent grasp of JavaScript itself. -While you _can_ make a bot with very little JS and programming knowledge, trying to do so without understanding the language first will only hinder you. You may get stuck on many uncomplicated issues, struggle with solutions to incredibly easy problems, and all-in-all end up frustrated. Sounds pretty annoying if you ask me. - -If you don't know JS but would like to learn about it, here are a few links to help get you started: - -* [CodeCademy's interactive JavaScript course](https://www.codecademy.com/learn/learn-javascript) -* [Eloquent JavaScript, a free online book](http://eloquentjavascript.net/) -* [Nodeschool, for both JavaScript and Node.js lessons](https://nodeschool.io/) -* [MDN's JavaScript guide and full documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript) -* [Google, your best friend](https://google.com) - -Take your pick, learn some JS, and once you feel like you're confident enough to make a bot, come back and get started! diff --git a/Ajuda/guide-master/guide/additional-info/async-await.md b/Ajuda/guide-master/guide/additional-info/async-await.md deleted file mode 100644 index ce232e3..0000000 --- a/Ajuda/guide-master/guide/additional-info/async-await.md +++ /dev/null @@ -1,185 +0,0 @@ -# Understanding async/await - -If you aren't very familiar with ECMAScript 2017, you may not know about async/await. It's a useful way to handle Promises in a hoisted manner. In addition, it looks cleaner, increases overall readability, and is slightly faster. - -## How do Promises work? - -Before we can get into async/await, you should know what Promises are and how they work, because async/await is just a way to handle Promises. If you know what Promises are and how to deal with them, then you can skip this part. - -Promises are a way to handle asynchronous tasks in Javascript; they are the newer alternative to callbacks. A Promise has a lot of similarities to a progress bar; Promises represent an ongoing process that has not yet finished. A good example for that is a request to a server (e.g discord.js sends requests to Discord's API). - -A Promise can have 3 states; pending, resolved, and rejected - -The **pending** state means that the Promise still is ongoing and nether resolved nor rejected. -The **resolved** state means that the Promise is done and was executed without any errors. -The **rejected** state means that the Promise encountered an error and could not be executed correctly. - -One important thing to know is that a Promise can only have one state at a time; it can never be pending and resolved, rejected and resolved, or pending and rejected. You may be asking "How would that look in code?". Here is a small example: - -::: tip -ES6 code is being used in this example. If you do not know what that is, you should read up on that [here](/additional-info/es6-syntax.md). -::: - -```js -function deleteMessages(amount) { - return new Promise(resolve => { - if (amount > 10) throw new Error('You can\'t delete more than 10 Messages at a time.'); - setTimeout(() => resolve('Deleted 10 messages.'), 2000); - }); -} - -deleteMessages(5).then(value => { - // `deleteMessages` is complete and has not encountered any errors - // the resolved value will be the string "Deleted 10 messages" -}).catch(error => { - // `deleteMessages` encountered an error - // the error will be an Error Object -}); -``` - -In this scenario, the `deleteMessages` function returns a Promise. The `.then()` method will trigger if the Promise was resolved, and the `.catch()` method if the Promise was rejected. But with our function, we resolve the Promise after 2 seconds with the String "Deleted 10 messages.", so the `.catch()` method will never be executed. You can also pass the `.catch()` function as the second parameter of `.then()`. - -## How to implement async/await - -### Theory - -The following information is important to know before working with async/await. You can only use the `await` keyword inside a function that is declared as `async` (you put the `async` keyword before the `function` keyword or before the parameters when using a callback function). - -A simple example would be: - -```js -async function declaredAsAsync() { - // code -} -``` - -or - -```js -const declaredAsAsync = async () => { - // code -}; -``` - -You can use that as well if you use the arrow function as an event listener. - -```js -client.on('event', async (first, last) => { - // code -}); -``` - -An important thing to know is that a function declared as `async` will always return a Promise. In addition to this, if you return something, the Promise will resolve with that value, and if you throw an error, it will reject the Promise with that error. - -### Execution with discord.js code - -After knowing how Promises work and what they are for, as well as about the theory, let's look at an example in which we'll handle multiple Promises. Let's say you want to react with letters (regional indicators) in a certain order. For this example, you will take the basic template for a discord.js bot with some ES6 adjustments. - -```js -const Discord = require('discord.js'); -const client = new Discord.Client(); - -const prefix = '?'; - -client.once('ready', () => { - console.log('I am ready!'); -}); - -client.on('message', message => { - if (message.content === `${prefix}react`) { - // code inside here - } -}); - -client.login('tokeninhere'); -``` - -So now we need to put the code in. If you don't know how Node.js asynchronous execution works, you would probably try something like this: - -```js -client.on('message', message => { - if (message.content === `${prefix}react`) { - message.react('🇦'); - message.react('🇧'); - message.react('🇨'); - } -}); -``` - -But since all of these react methods are started at the same time, it would just be a race to which server request finished first, so there would be no guarantee that it would react in the order you wanted it to. In order to make sure it reacts in order (a, b, c), we need to use the `.then()` callback from the Promises that these methods return. As a result the code we want would mostly look like this: - -```js -client.on('message', message => { - if (message.content === `${prefix}react`) { - message.react('🇦') - .then(() => message.react('🇧')) - .then(() => message.react('🇨')) - .catch(error => { - // handle failure of any Promise rejection inside here - }); - } -}); -``` - -In this piece of code, we [chain resolve](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then#Chaining) Promises with each other, and if one of the Promises gets rejected, the function we passed to `.catch()` get called. So let's look at how the same code would look with async/await. - -```js -client.on('message', async message => { - if (message.content === `${prefix}react`) { - await message.react('🇦'); - await message.react('🇧'); - await message.react('🇨'); - } -}); -``` - -That would mostly be the same code with async/await, but how do we catch Promise rejections now since we won't use `.catch()` anymore? That is also a useful feature with async/await; the error will be thrown if you await it so you can just wrap the awaited Promises inside a try/catch and you're good to go. - -```js -client.on('message', async message => { - if (message.content === `${prefix}react`) { - try { - await message.react('🇦'); - await message.react('🇧'); - await message.react('🇨'); - } catch (error) { - // handle failure of any Promise rejection inside here - } - } -}); -``` - -This looks clean and is also nice and easy to read. - -So you may be asking, "How would I get the value the Promise resolved with?". - -Well let's look at an example where you want to delete a sent message. - -```js -client.on('message', message => { - if (message.content === `${prefix}delete`) { - message.channel.send('this message will be deleted') - .then(sentMessage => sentMessage.delete(10000)) - .catch(error => { - // handle error - }); - } -}); -``` - -The return value of a `.send()` is a Promise what resolves with the sent Message object, but how would the same code with async/await look like? - -```js -client.on('message', async message => { - if (message.content === `${prefix}delete`) { - try { - const sentMessage = await message.channel.send('This message will be deleted in 10 seconds.'); - await sentMessage.delete(10000); - } catch (error) { - // handle error - } - } -}); -``` - -With async/await you can just assign the awaited function to a variable that will represent the returned value. Now you know how you use async/await. diff --git a/Ajuda/guide-master/guide/additional-info/changes-in-v12.md b/Ajuda/guide-master/guide/additional-info/changes-in-v12.md deleted file mode 100644 index dbf9f88..0000000 --- a/Ajuda/guide-master/guide/additional-info/changes-in-v12.md +++ /dev/null @@ -1,2303 +0,0 @@ -# Updating from v11 to v12 - -After a long time in development, Discord.js v12 is nearing a stable release, meaning it's time to update from v11 to get new features for your bots! However, with those new features comes a lot of changes to the library that will break code written for v11. This guide will serve as a handy reference for updating your code, covering the most commonly-used methods that have been changed, new topics such as partials and internal sharding, and will also include a comprehensive list of the method and property changes at the end. - -## Before You Start - -v12 requires Node 10.x or higher to use, so make sure you're up-to-date. To check your Node version, use `node -v` in your terminal or command prompt, and if it's not high enough, update it! There are many resources online to help you get up-to-date. - -For now, you do need Git installed and added to your PATH environment, so ensure that's done as well - again, guides are available online for a wide variety of operating systems. Once you have Node up-to-date and Git installed, you can install v12 by running `npm install discordjs/discord.js` in your terminal or command prompt for text-only use, or `npm install discordjs/discord.js node-opus` for voice support. - -## Commonly Used Methods That Changed - -* All section headers are named in the following convention: `Class#methodOrProperty`. -* The use of parenthesis designates optional inclusion. For example, `Channel#fetch(Pinned)Message(s)` means that this section will include changes for `Channel#fetchPinnedMessages`, `Channel#fetchMessages`, and `Channel#fetchMessage`. -* The use of asterisks designates a wildcard. For example, `Channel#send***` means that this section will include changes for `Channel#sendMessage`, `Channel#sendFile`, `Channel#sendEmbed`, and so forth. - -### Collection - -#### Collection#exists - -`collection.exists()` was removed entirely, `collection.some()` should be used to check if an element exists in the collection that satisfies the provided value. - -```diff -- client.users.exists('username', 'Bob'); -+ client.users.some(user => user.username === 'Bob'); -``` - -#### Collection#filterArray - -`collection.filterArray()` was removed entirely, as it was just a helper method for `collection.filter().array()` and most of the time converting a collection to an array is an unnecessary step. - -#### Collection#find - -`collection.find('property', value)` has been removed entirely, and `collection.find()` only accepts a function in v12. - -```diff -- client.users.find('username', 'Bob'); -+ client.users.find(user => user.username === 'Bob'); -``` - -#### Collection#findAll - -`collection.findAll()` was removed entirely as it just duplicated `collection.filterArray()`'s results. - -### Fetch - -Some methods that retrieve uncached data have been changed, transformed in the shape of a DataStore. - -```diff -- client.fetchUser('123456789012345678'); -+ client.users.fetch('123456789012345678'); - -- guild.fetchMember('123456789012345678'); -+ guild.members.fetch('123456789012345678'); - -- guild.fetchMembers(); -+ guild.members.fetch(); - -- textChannel.fetchMessage('123456789012345678'); -+ textChannel.messages.fetch('123456789012345678'); - -- textChannel.fetchMessages({ limit: 10 }); -+ textChannel.messages.fetch({ limit: 10 }); - -- textChannel.fetchPinnedMessages(); -+ textChannel.messages.fetchPinned(); -``` - -### Send - -All the `.send***()` methods have been removed in favor of one general `.send()` method. - -```diff -- channel.sendMessage('Hey!'); -+ channel.send('Hey!'); - -- channel.sendEmbed(embedVariable); -+ channel.send(embedVariable); -+ channel.send({ embed: embedVariable }); -``` - -`channel.send(embedVariable)` will only work if that variable is an instance of the `MessageEmbed` class; object literals won't give you the expected result unless your embed data is inside an `embed` key. - -```diff -- channel.sendCode('js', 'const version = 11;'); -+ channel.send('const version = 12;', { code: 'js' }); - -- channel.sendFile('./file.png'); -- channel.sendFiles(['./file-one.png', './file-two.png']); -+ channel.send({ - files: [{ - attachment: 'entire/path/to/file.jpg', - name: 'file.jpg' - }] -+ channel.send({ - files: ['https://cdn.discordapp.com/icons/222078108977594368/6e1019b3179d71046e463a75915e7244.png?size=2048'] -}); -``` - -### Roles - -The `GuildMember.roles` Collection has been changed to a DataStore in v12, so a lot of the associated methods for interacting with a member's roles have changed as well. They're no longer on the GuildMember object itself, but instead now on the `GuildMemberRoleStore` DataStore. - -```diff -- guildMember.addRole('123456789012345678'); -- guildMember.addRoles(['123456789012345678', '098765432109876543']); -+ guildMember.roles.add('123456789012345678'); -+ guildMember.roles.add(['123456789012345678', '098765432109876543']); - -- guildMember.removeRole('123456789012345678'); -- guildMember.removeRoles(['123456789012345678', '098765432109876543']); -+ guildMember.roles.remove('123456789012345678'); -+ guildMember.roles.remove(['123456789012345678', '098765432109876543']); - -- guildMember.setRoles(['123456789012345678', '098765432109876543']); -+ guildMember.roles.set(['123456789012345678', '098765432109876543']); -``` - -In addition, the GuildMember properties related to roles have also been moved to the `GuildMemberRoleStore` DataStore. - -```diff -- guildMember.colorRole; -+ guildMember.roles.color; - -- guildMember.highestRole; -+ guildMember.roles.highest; - -- guildMember.hoistRole; -+ guildMember.roles.hoist; -``` - -### Ban and Unban - -The method to ban members and users have been moved to the `GuildMemberStore` Data Store. - -```diff -- guild.ban('123456789012345678'); -+ guild.members.ban('123456789012345678'); - -- guild.unban('123456789012345678'); -+ guild.members.unban('123456789012345678'); -``` - -### Image URLs - -Some image-related properties like `user.avatarURL` are now a method in v12, so that you can apply some options to them, eg. to affect their display size. - -```diff -- user.avatarURL; -+ user.avatarURL(); - -- user.displayAvatarURL; -+ user.displayAvatarURL(); - -- guild.iconURL; -+ guild.iconURL(); - -- guild.splashURL; -+ guild.splashURL(); -``` - -### RichEmbed Constructor - -The RichEmbed constructor has been removed and now the `MessageEmbed` constructor is used. It is largely the same to use, the only difference being the removal of `RichEmbed.attachFile()` - `MessageEmbed.attachFiles()` accepts a single file as a parameter as well. - -### String Concatenation - -v12 has changed how string concatenation works with stringifying objects. The `valueOf` any data structure will return its id, which affects how it behaves in strings, eg. using an object for a mention. In v11, you used to be able to use `channel.send(userObject + ' has joined!')` and it would automatically stringify the object and it would become the mention (`@user has joined!`), but in v12, it will now send a message that says `123456789012345678 has joined` instead. Using template literals (\`\`) will still return the mention, however. - -```diff -- channel.send(userObject + ' has joined!') -+ channel.send(`${userObject} has joined!`) -``` - -### User Account-Only Methods - -All user account-only methods have been removed, as they are no longer publicly accessible from the API. - -### Voice - -v12 has a new voice system that improves stability but also comes with some changes to playing audio: - -```diff -# Applies to VoiceConnection and VoiceBroadcast -- connection.playFile('file.mp3') -+ connection.play('file.mp3') - -- connection.playStream(stream) -+ connection.play(stream) - -- connection.playArbitraryInput(input) -+ connection.play(input) - -- connection.playBroadcast(broadcast) -+ connection.play(broadcast) - -- connection.playOpusStream(stream) -+ connection.play(stream, { type: 'opus' }) - -- connection.playConvertedStream(stream) -+ connection.play(stream, { type: 'converted' }) -``` - -You can now also play Ogg Opus files or WebM Opus files directly without the need for FFmpeg in v12: - -```js -connection.play(fs.createReadStream('file.ogg'), { type: 'ogg/opus' }); -connection.play(fs.createReadStream('file.webm'), { type: 'webm/opus' }); -``` - -It is also possible to define initial values for `plp`, `fec` and `bitrate` when playing a stream. Minus bitrate, these are new configurable options in v12 that can help when playing audio on unstable network connections. - -```diff -- connection.playStream(stream).setBitrate(96) -+ connection.play(stream, { bitrate: 96 }) -``` - -If you don't want to alter the volume of a stream while you're playing it, you can disable volume to improve performance. This cannot be reverted during playback. - -```js -connection.play(stream, { volume: false }); -``` - -The internal voice system in v12 now uses streams where possible, and as such StreamDispatcher itself is now a WritableStream. It also comes with new changes: - -```diff -- dispatcher.end() -+ dispatcher.destroy() - -- dispatcher.on('end', handler) -+ dispatcher.on('finish', handler) -``` - -You can manually control how many audio packets should be queued before playing audio for more consistent playback using the `highWaterMark` option (defaults to 12) -```js -connection.play(stream, { highWaterMark: 512 }); -``` - -If you're frequently pausing/resuming an audio stream, you can enable playing silence packets while paused to prevent audio glitches on the Discord client -```js -// Passing true plays silence -dispatcher.pause(true); -``` - -#### Broadcasts - -Broadcasts themselves now contain a `BroadcastDispatcher` that shares a similar interface to the `StreamDispatcher` and can be used to control the playback of an audio stream. - -```diff -- client.createVoiceBroadcast() -+ client.voice.createBroadcast() - -- broadcast.dispatchers -+ broadcast.subscribers -``` - ---- -::: danger -This stuff should keep getting shoved to the bottom, with the commonly-used methods that are changed, as well as topic overviews added before it. -::: - -The section headers for breaking changes will be named after the v11 classes/methods/properties and will be in alphabetical order, so that you can easily find what you're looking for. The section headers for additions will be named after the v12 classes/methods/properties, to reflect their current syntax appropriately. - -"Difference" codeblocks will be used to display the old methods vs the newer ones—the red being what's been removed and the green being its replacement. Some bits may have more than one version of being handled. Regular JavaScript syntax codeblocks will be used to display the additions. - -::: danger -While this list has been carefully crafted, it may be incomplete! If you notice pieces of missing or inaccurate data, we encourage you to [submit a pull request](https://github.com/Danktuary/Making-Bots-with-Discord.js)! -::: - -## Breaking Changes and Deletions - -Stuff that has gone through and updated - anything under Additions at the end will still likely need descriptions: - -Any voice-related classes may change at any time, as they're still actively being worked on, and will be finalized at a later date. - -* Activity [(additions)](/additional-info/changes-in-v12.md#activity) -* ActivityFlags [(additions)](/additional-info/changes-in-v12.md#activityflags) -* APIMessage [(additions)](/additional-info/changes-in-v12.md#apimessage) -* Base [(additions)](/additional-info/changes-in-v12.md#base) -* BaseClient [(additions)](/additional-info/changes-in-v12.md#baseclient) -* BitField [(additions)](/additional-info/changes-in-v12.md#bitfield) -* BroadcastDispatcher [(additions)](/additional-info/changes-in-v12.md#broadcastdispatcher) -* Channel (changed send/fetch to TextChannel) [(additions)](/additional-info/changes-in-v12.md#channel) -* ClientApplication [(additions)](/additional-info/changes-in-v12.md#clientapplication) -* Client [(changes)](/additional-info/changes-in-v12.md#client) [(additions)](/additional-info/changes-in-v12.md#client-1) -* ClientOptions [(changes)](/additional-info/changes-in-v12.md#clientoptions) [(additions)](/additional-info/changes-in-v12.md#clientoptions-1) -* ClientUser [(changes)](/additional-info/changes-in-v12.md#clientuser) [(additions)](/additional-info/changes-in-v12.md#clientuser-1) -* Collection [(changes)](/additional-info/changes-in-v12.md#collection) -* Collector [(changes)](/additional-info/changes-in-v12.md#collector) [(additions)](/additional-info/changes-in-v12.md#collector-1) -* CollectorOptions [(additions)](/additional-info/changes-in-v12.md#collectoroptions) -* DMChannel [(changes)](/additional-info/changes-in-v12.md#dmchannel) [(additions)](/additional-info/changes-in-v12.md#dmchannel-1) -* Emoji [(changes)](/additional-info/changes-in-v12.md#emoji) -* EvaluatedPermissions [(changes)](/additional-info/changes-in-v12.md#evaluatedpermissions) -* Game [(changes)](/additional-info/changes-in-v12.md#game) -* GroupDMChannel [(changes)](/additional-info/changes-in-v12.md#groupdmchannel) -* Guild [(changes)](/additional-info/changes-in-v12.md#guild) [(additions)](/additional-info/changes-in-v12.md#guild-1) -* GuildChannel [(changes)](/additional-info/changes-in-v12.md#guildchannel) [(additions)](/additional-info/changes-in-v12.md#guildchannel-1) -* GuildMember [(changes)](/additional-info/changes-in-v12.md#guildmember) -* HTTPError [(additions)](/additional-info/changes-in-v12.md#httperror) -* Integration [(additions)](/additional-info/changes-in-v12.md#integrations) -* Invite [(changes)](/additional-info/changes-in-v12.md#invite) -* Message [(changes)](/additional-info/changes-in-v12.md#message) [(additions)](/additional-info/changes-in-v12.md#message-1) -* MessageAttachment [(changes)](/additional-info/changes-in-v12.md#messageattachment) [(additions)](/additional-info/changes-in-v12.md#messageattachment-1) -* MessageCollectorOptions [(changes)](/additional-info/changes-in-v12.md#messagecollectoroptions) -* MessageEmbed [(changes)](/additional-info/changes-in-v12.md#messageembed) [(additions)](/additional-info/changes-in-v12.md#messageembed-1) -* MessageMentions [(changes)](/additional-info/changes-in-v12.md#messagementions) -* MessageReaction [(changes)](/additional-info/changes-in-v12.md#messagereaction) -* OAuth2Application [(changes)](/additional-info/changes-in-v12.md#oauth2application) -* PartialGuild [(changes)](/additional-info/changes-in-v12.md#partialguildchannel) -* PartialGuildChannel [(changes)](/additional-info/changes-in-v12.md#partialguildchannel) -* Permissions [(changes)](/additional-info/changes-in-v12.md#permissions) [(additions)](/additional-info/changes-in-v12.md#permissions-1) -* Presence [(changes)](/additional-info/changes-in-v12.md#presence) [(additions)](/additional-info/changes-in-v12.md#presence-1) -* ReactionCollector [(additions)](/additional-info/changes-in-v12.md#reactioncollector) -* ReactionEmoji [(changes)](/additional-info/changes-in-v12.md#) -* RichEmbed [(changes)](/additional-info/changes-in-v12.md#richembed) -* RichPresenceAssets [(changes)](/additional-info/changes-in-v12.md#richpresenceassets) -* Role [(changes)](/additional-info/changes-in-v12.md#role) -* Shard [(changes)](/additional-info/changes-in-v12.md#shard) -* ShardClientUtil [(changes)](/additional-info/changes-in-v12.md#shardclientutil) -* ShardingManager [(changes)](/additional-info/changes-in-v12.md#shardingmanager) -* StreamDispatcher [(changes)](/additional-info/changes-in-v12.md#streamdispatcher) -* TextChannel [(changes)](/additional-info/changes-in-v12.md#textchannel) [(additions)](/additional-info/changes-in-v12.md#textchannel-1) -* User [(changes)](/additional-info/changes-in-v12.md#user) [(additions)](/additional-info/changes-in-v12.md#user-1) -* Util [(changes)](/additional-info/changes-in-v12.md#util) [(additions)](/additional-info/changes-in-v12.md#util-1) -* VoiceBroadcast [(changes)](/additional-info/changes-in-v12.md#voicebroadcast) [(additions)](/additional-info/changes-in-v12.md#voicebroadcast-1) -* VoiceChannel [(additions)](/additional-info/changes-in-v12.md#voicechannel) -* VoiceConnection [(changes)](/additional-info/changes-in-v12.md#voiceconnection) -* VoiceReceiver [(changes)](/additional-info/changes-in-v12.md#voicereceiver) [(additions)](/additional-info/changes-in-v12.md#voicereceiver-1) -* VoiceRegion [(changes)](/additional-info/changes-in-v12.md#voiceregion) -* VoiceState [(additions)](/additional-info/changes-in-v12.md#voicestate) -* VolumeInterface [(changes)](/additional-info/changes-in-v12.md#volumeinterface) [(additions)](/additional-info/changes-in-v12.md#volumeinterface-1) -* Webhook [(changes)](/additional-info/changes-in-v12.md#webhook) [(additions)](/additional-info/changes-in-v12.md#webhook-1) -* WebhookClient [(changes)](/additional-info/changes-in-v12.md#webhookclient) -* WebSocketManager [(additions)](/additional-info/changes-in-v12.md#websocketmanager) -* WebSocketShard [(additions)](/additional-info/changes-in-v12.md#websocketshard) - -Stuff Mark didn't do: - -* MessageAttachment - -### Dependencies - -#### Snekfetch - -Please note that `snekfetch` has been removed as a dependency, and has been replaced by `node-fetch`. `snekfetch` has been deprecated by its developer and is no longer maintained. - -### Attachment - -The `Attachment` class has been removed in favor of the `MessageAttachment` class. - -### Client - -#### Client#fetchUser - -`client.fetchUser()` has been removed and transformed in the shape of a DataStore. - -```diff -- client.fetchUser('123456789012345678'); -+ client.users.fetch('123456789012345678'); -``` - -#### Client#broadcasts - -`client.broadcasts` has been removed and is now in the `ClientVoiceManager` class. - -```diff -- client.broadcasts; -+ client.voice.broadcasts; -``` - -#### Client#browser - -`client.browser` has been changed to be an internal constant and is no longer available publicly. - -#### Client#channels - -`client.channels` has been changed from a Collection to a DataStore. - -#### Client#clientUserGuildSettingsUpdate - -The `client.clientUserGuildSettingsUpdate` event has been removed entirely, along with all other user account-only properties and methods. - -#### Client#clientUserSettingsUpdate - -The `client.clientUserSettingsUpdate` event has been removed entirely, along with all other user account-only properties and methods. - -#### Client#disconnect - -The `client.disconnect` event has been removed in favor of the `client.shardDisconnected` event to make use of internal sharding. - -```diff -- client.on('disconnect', event => {}); -+ client.on('shardDisconnected', (event, shardID) => {}); -``` - -#### Client#emojis - -`client.emojis` has been changed from a Collection to a DataStore. - -#### Client#guildMemberSpeaking - -The `speaking` parameter has been changed from a `boolean` value to a read-only `Speaking` class. - -#### Client#guilds - -`client.guilds` has been changed from a Collection to a DataStore. - -#### Client#ping - -`client.ping` has been moved to the WebSocketManager under `client.ws.ping` - -```diff -- client.ping -+ client.ws.ping -``` - -#### Client#pings - -`client.pings` has been moved to the `WebSocketShard` class to make use of internal sharding. The `Client` class has a `Collection` of `WebSocketShard`s available via `client.ws.shards`; alternatively, the `WebSocketShard` can be found as a property of other structures, eg `guild.shard`. - -```diff -- client.pings; -+ guild.shard.pings; -``` - -#### Client#presences - -`client.presences` has been removed to reduce extraneous getters. - -#### Client#reconnecting - -The `client.reconnecting` event has been removed in favor of the `client.shardReconnecting` event to make use of internal sharding. - -```diff -- client.on('reconnecting', () => console.log('Successfully reconnected.')); -+ client.on('shardReconnecting', id => console.log(`Shard with ID ${id} reconnected.`)); -``` - -#### Client#resume - -The `client.resume` event has been removed in favor of the `client.shardResumed` event to make use of internal sharding. - -```diff -- client.on('resume', replayed => console.log(`Resumed connection and replayed ${replayed} events.`)); -+ client.on('shardResumed', (replayed, shardID) => console.log(`Shard ID ${shardID} resumed connection and replayed ${replayed} events.`)); -``` - -#### Client#status - -The `client.status` property has been removed and is now in the `WebSocketManager` class. In addition, it is no longer a getter. - -```diff -- client.status; -+ client.ws.status; -``` - -#### Client#syncGuilds - -`client.syncGuilds()` has been removed entirely, along with all other user account-only properties and methods. - -#### Client#typingStop - -The `client.typingStop` event has been removed entirely, as it was an event created by the library and not an actual Discord WebSocket event. - -#### Client#userNoteUpdate - -The `client.userNoteUpdate` event has been removed entirely, along with all other user account-only properties and methods. - -#### Client#users - -`client.users` has been changed from a Collection to a DataStore. - -#### Client#voiceConnections - -`client.voiceConnections` has been removed and is now in the `ClientVoiceManager` class. In addition, the `Collection` is no longer a getter. - -```diff -- client.voiceConnections; -+ client.voice.connections; -``` - -#### Client#voiceStateUpdate - -The `client.voiceStateUpdate` event now returns `oldState` and `newState` representing the `VoiceState` of the member before and after the update, as opposed to the member itself. - -```diff -- client.on('voiceStateUpdate', (oldMember, newMember) => console.log(oldMember)); -+ client.on('voiceStateUpdate', (oldState, newState) => console.log(oldState)); -``` - -### ClientOptions - -There have been several changes made to the `ClientOptions` object located in `client#options`. - -#### ClientOptions#apiRequestMethod - -`clientOptions.apiRequestMethod` has been made sequential and is used internally. - -#### ClientOptions#shardId - -`clientOptions.shardId` has been changed to `clientOptions.shards` and now also accepts an array of numbers. - -```diff -- options.shardId: 1 -+ options.shards: [1, 2, 3] -``` - -#### ClientOptions#shards - -`clientOptions.shards` has been removed and is functionally equivalent to `clientOptions.totalShardCount` on v12. - -#### ClientOptions#sync - -`clientOptions.sync` has been removed entirely, along with all other user account-only properties and methods. - -### ClientUser - -#### ClientUser#acceptInvite - -`clientUser.acceptInvite()` has been removed entirely, along with all other user account-only properties and methods. - -#### ClientUser#addFriend - -`clientUser.addFriend()` has been removed entirely, along with all other user account-only properties and methods. - -#### ClientUser#avatarURL - -`clientUser.avatarURL` is now a method, as opposed to a property. It also allows you to determine the file format and size to return. - -```diff -- clientUser.avatarURL; -+ clientUser.avatarURL(); -+ clientUser.avatarURL({ format: 'png', size: 1024 }); -``` - -#### ClientUser#block - -`clientUser.block()` has been removed entirely, along with all other user account-only properties and methods. - -#### ClientUser#blocked - -`clientUser.blocked` has been removed entirely, along with all other user account-only properties and methods. - -#### ClientUser#createGuild - -`clientUser.createGuild()` has been transformed in the shape of a DataStore. In addition, the second and third parameters in `clientUser.createGuild()` have been changed/removed, leaving it with a total of two parameters. The `region` and `icon` parameters from v11 have been merged into an object as the second parameter. - -```diff -- clientUser.createGuild('New server', 'us-east', './path/to/file.png'); -+ clientUser.guilds.create('New server', { region: 'us-east', icon: './path/to/file.png' }); -``` - -#### ClientUser#displayAvatarURL - -`clientUser.displayAvatarURL` is now a method, as opposed to a property. It also allows you to determine the file format and size to return. - -```diff -- clientUser.displayAvatarURL; -+ clientUser.displayAvatarURL(); -+ clientUser.displayAvatarURL({ format: 'png', size: 1024 }); -``` - -#### ClientUser#email - -`clientUser.email` has been removed entirely, along with all other user account-only properties and methods. - -#### ClientUser#fetchMentions - -`clientUser.fetchMentions()` has been removed entirely, along with all other user account-only properties and methods. - -#### ClientUser#fetchProfile - -`clientUser.fetchProfile()` has been removed entirely, along with all other user account-only properties and methods. - -#### ClientUser#friends - -`clientUser.friends` has been removed entirely, along with all other user account-only properties and methods. - -#### ClientUser#guildSettings - -`clientUser.guildSettings` has been removed entirely, along with all other user account-only properties and methods. - -#### ClientUser#mfaEnabled - -`clientUser.mfaEnabled` has been removed entirely, along with all other user account-only properties and methods. - -#### ClientUser#mobile - -`clientUser.mobile` has been removed entirely, along with all other user account-only properties and methods. - -#### ClientUser#note - -`clientUser.note` has been removed entirely, along with all other user account-only properties and methods. - -#### ClientUser#notes - -`clientUser.notes` has been removed entirely, along with all other user account-only properties and methods. - -#### ClientUser#premium - -`clientUser.premium` has been removed entirely, along with all other user account-only properties and methods. - -#### ClientUser#removeFriend - -`clientUser.removeFriend()` has been removed entirely, along with all other user account-only properties and methods. - -#### ClientUser#send\*\*\* - -Just like the `TextChannel#send***` methods, all the `.send***()` methods have been removed in favor of one general `.send()` method. Read through the [TextChannel#send\*\*\*](/additional-info/changes-in-v12.md#channelsend) section for more information. - -#### ClientUser#setGame - -`clientUser.setGame()` has been changed to `clientUser.setActivity()`. The second parameter is no longer for providing a streaming URL, but rather an object that allows you to provide the URL and activity type. - -```diff -- clientUser.setGame('with my bot friends!'); -+ clientUser.setActivity('with my bot friends!'); - -- clientUser.setGame('with my bot friends!', 'https://twitch.tv/your/stream/here'); -+ clientUser.setActivity('with my bot friends!', { url: 'https://twitch.tv/your/stream/here', type: 'STREAMING' }); -``` - -#### ClientUser#setNote - -`clientUser.setNote()` has been removed entirely, along with all other user account-only properties and methods. - -#### ClientUser#setPassword - -`clientUser.setPassword()` has been removed entirely, along with all other user account-only properties and methods. - -#### ClientUser#settings - -`clentUser.settings` has been removed entirely, along with all other user account-only properties and methods. - -#### ClientUser#unblock - -`clientUser.unblock()` has been removed entirely, along with all other user account-only properties and methods. - -### ClientUserChannelOverride - -The `ClientUserChannelOverride` class has been removed entirely, along with all other user account-only properties and methods. - -### ClientUserGuildSettings - -The `ClientUserGuildSettings` class has been removed entirely, along with all other user account-only properties and methods. - -### ClientUserSettings - -The `ClientUserSettings` class has been removed entirely, along with all other user account-only properties and methods. - -### ClientUserChannelOverride - -The `ClientUserChannelOverride` class has been removed entirely. - -### ClientUserGuildSettings - -The `ClientUserGuildSettings` class has been removed entirely. - -### ClientUserSettings - -The `ClientUserSettings` class has been removed entirely. - -### Collection - -#### Collection#find/findKey - -Both methods will now return `undefined` if nothing is found. - -#### Collection#deleteAll - -`collection.deleteAll()` has been removed in favor of map's default `clear()` method. - -```diff -- roles.deleteAll(); -+ roles.clear(); -``` - -#### Collection#exists - -`collection.exists()` has been removed entirely in favor of `collection.some()` - -```diff -- client.users.exists('username', 'Bob'); -+ client.users.some(user => user.username === 'Bob'); -``` - -#### Collection#filterArray - -`collection.filterArray()` has been removed completely. - -#### Collection#findAll - -`collection.findAll()` has been removed completely as the same functionality can be obtained through `collection.filter()`. - -#### Collection#first/firstKey/last/lastKey/random/randomKey - -The `amount` parameter of these methods now allows a negative number which will start the query from the end of the collection instead of the start. - -#### Collection#tap - -`collection.tap` runs a specific function over the collection instead of mimicking `.forEach()`, this functionality was moved to `collection.each()`. - -### Collector - -#### Collector#cleanup - -`collector.cleanup()` has been removed entirely. - -#### Collector#handle - -`collector.handle()` has been changed to `collector.handleCollect()`. - -#### Collector#postCheck - -`collector.postCheck()` has been changed to `collector.checkEnd()`. - -### DMChannel - -#### DMChannel#acknowledge - -`dmChannel.acknowledge()` has been removed entirely, along with all other user account-only properties and methods. - -#### DMChannel#createCollector - -`dmChannel.createCollector()` has been removed in favor of `dmChannel.createMessageCollector()`. - -#### DMChannel#fetch(Pinned)Message(s) - -`dmChannel.fetchMessage(s)` has been transformed in the shape of a DataStore. See the [TextChannel#fetch(Pinned)Message(s)](/additional-info/changes-inv-v12.md#channel) section for more information. - -#### DMChannel#search - -`dmChannel.search()` has been removed entirely, along with all other user account-only properties and methods. - -#### DMChannel#send\*\*\* - -Just like the `TextChannel#send***` methods, all the `.send***()` methods have been removed in favor of one general `.send()` method. Read through the [TextChannel#send\*\*\*](/additional-info/changes-in-v12.md#channelsend) section for more information. - -### Emoji - -`Emoji` now extends `Base` and represent either a `GuildEmoji` or `ReactionEmoji`, and some of the specific properties have moved to their respective object, instead of everything on the base `Emoji` object. - -#### Emoji#\*\*\*RestrictedRole(s) - -The helper methods to add and remove a role or roles from the roles allowed to use the emoji have been removed from `emoji.edit()` and are now set via `guildEmoji.edit()`. - -```diff -- emoji.addRestrictedRole('123456789012345678'); -- emoji.addRestrictedRoles(['123456789012345678', '098765432109876543']); -- emoji.removeRestrictedRole('1234567890123345678'); -- emoji.removedRestrictedRoles(['123456789012345678', '098765432109876543']); -+ emoji.edit({ roles: ['123456789012345678', '098765432109876543'] }) -``` - -#### Emoji#deletable - -`emoji.deletable` has been moved to `guildEmoji.deletable`. - -#### Emoji#fetchAuthor - -`emoji.fetchAuthor()` has been moved to `guildEmoji.fetchAuthor()`. - -#### Emoji#guild - -`emoji.guild` has been moved to `guildEmoji.guild`. - -#### Emoji#setName - -`emoji.setName()` has been moved to `guildEmoji.setName()`. - -### EvaluatedPermissions - -`evaluatedPermissions` has been removed entirely, see the `Permissions` page. - -### Game - -The `Game` class has been removed in favor of the `Activity` class to be consistent with the API. - -```diff -- user.presence.game -+ user.presence.activity -``` - -### GroupDMChannel - -The `GroupDMChannel` class has been deprecated from the Discord API. While it's still available through Gamebridge for now, that will also be removed in the future. In addition, group DM's has always been unreliable and hacky to work with a bot. - -### Guild - -#### Guild#acknowledge - -`guild.acknowledge()` has been removed entirely, along with all other user account-only properties and methods. - -#### Guild#allowDMs - -`guild.allowDMs()` has been removed entirely, along with all other user account-only properties and methods. - -#### Guild#ban - -`guild.ban()` has been moved to the `GuildMemberStore`. In addition, the second parameter in `guild.members.ban()` has been changed. The `options` parameter no longer accepts a number, nor a string. - -```diff -- guild.ban(user, 7); -+ guild.members.ban(user, { days: 7 }); - -- guild.ban(user, 'Too much trolling'); -+ guild.members.ban(user, { reason: 'Too much trolling' }); -``` - -#### Guild#Channels - -`guild.channels` is now a DataStore instead of a Collection. - -#### Guild#createChannel - -`guild.createChannel()` has been transformed in the shape of a DataStore. The second, third and fourth parameters in `guild.createChannel()` have been changed/removed, leaving it with a total of two parameters, the second one being an object with all of the options available in `ChannelData`. - -```diff -- guild.createChannel('new-channel', 'text', permissionOverwriteArray, 'New channel added for fun!'); -+ guild.channels.create('new-channel', 'text', { overwrites: permissionOverwriteArray, reason: 'New channel added for fun!' }); -``` - -#### Guild#createEmoji - -`guild.createEmoji()` has been transformed in the shape of a DataStore. The third and fourth parameters in `guild.createEmoji()` have been changed/removed, leaving it with a total of three parameters. The `roles` and `reason` parameters from v11 have been merged into an object as the third parameter. - -```diff -- guild.createEmoji('./path/to/file.png', 'NewEmoji', collectionOfRoles, 'New emoji added for fun!'); -+ guild.emojis.create('./path/to/file.png', 'NewEmoji', { roles: collectionOfRoles, reason: 'New emoji added for fun!' }); -``` - -#### Guild#createRole - -`guild.createRole()` has been transformed in the shape of a DataStore. The first and second parameters in `guild.createRole()` have been changed/removed, leaving it with a total of one parameter. The `data` and `reason` parameters from v11 have been moved into an object as the first parameter. - -```diff -- guild.createRole(roleData, 'New staff role!'); -+ guild.roles.create({ data: roleData, reason: 'New staff role!' }); -``` - -#### Guild#deleteEmoji - -`Guild.deleteEmoji()` has been removed and transformed in the shape of a DataStore. Note the possible use of `resolve()` as a broader alternative to `get()`. - -```diff -- guild.deleteEmoji('123456789012345678'); -+ guild.emojis.resolve('123456789012345678').delete(); -``` - -#### Guild#defaultChannel - -Unfortunately, "default" channels don't exist in Discord anymore, and as such, the `guild.defaultChannel` property has been removed with no alternative. - -**Q:** "I previously had a welcome message system (or something similar) set up using that property. What can I do now?" - -**A:** There are a few ways to tackle this. Using the example of a welcome message system, you can: - -1. Set up a database table to store the channel ID in a column when someone uses a `!welcome-channel #channel-name` command, for example. Then inside the `guildMemberAdd` event, use `client.channels.get('id')` and send a message to that channel. This is the most reliable method and gives server staff freedom to rename the channel as they please. -2. Make a new command that creates a `welcome-messages` channel, use `guild.channels.find(channel => channel.name === 'welcome-messages')`, and send a message to that channel. This method will work fine in most cases, but will break if someone on that server decides to rename the channel. This may also give you unexpected results, due to Discord allowing multiple channels to have the same name. - -::: tip -Not sure how to set up a database? Check out [this page](/sequelize/)! -::: - -#### Guild#emojis - -`guild.emojis` has been transformed in the shape of a DataStore. - -#### Guild#fetchBans - -`guild.fetchBans()` will return a `Collection` of objects in v12, whereas v11 would return a `Collection` of `User` objects. - -```diff -- guild.fetchBans().then(bans => console.log(`${bans.first().tag} was banned`)); -+ guild.fetchBans().then(bans => console.log(`${bans.first().user.tag} was banned because "${bans.first().reason}"`)); -``` - -#### Guild#fetchMember(s) - -`guild.fetchMember()` and `guild.fetchMembers()` were both removed and transformed in the shape of DataStores. In addition, `guild.members.fetch()` will return a `Collection` of `GuildMember` objects in v12, whereas v11 would return a `Guild` object. - -```diff -- guild.fetchMember('123456789012345678'); -+ guild.members.fetch('123456789012345678'); -``` - -```diff -- guild.fetchMembers(); -+ guild.members.fetch(); -``` - -#### Guild#iconURL - -`guild.iconURL` is now a method, as opposed to a property. It also allows you to determine the file format and size to return. - -```diff -- guild.iconURL; -+ guild.iconURL(); -+ guild.iconURL({ format: 'png', size: 1024 }); -``` - -#### Guild#messageNotifications - -`guild.messageNotifications` has been removed entirely, along with all other user account-only properties and methods. - -#### Guild#mobilePush - -`guild.mobilePush` has been removed entirely, along with all other user account-only properties and methods. - -#### Guild#muted - -`guild.muted` has been removed entirely, along with all other user account-only properties and methods. - -#### Guild#position - -`guild.position` has been removed entirely, along with all other user account-only properties and methods. - -#### Guild#presences - -`guild.presences` is now a DataStore instead of a Collection. - -#### Guild#pruneMembers - -`guild.pruneMembers()` has been transformed in the shape of a DataStore. In addition, the first, second, and third parameters in the method have been changed or removed, leaving it with a total of one parameter. The `days`, `dry`, and `reason` parameters from v11 have been merged into an object as the first parameter. - -```diff -- guild.pruneMembers(7, true, 'Scheduled pruning'); -+ guild.members.prune({ days: 7, dry: true, reason: 'Scheduled pruning' }); -``` - -#### Guild#roles - -`guild.roles` is now a DataStore instead of a Collection. - -#### Guild#search - -`guild.search()` has been removed entirely, along with all other user account-only properties and methods. - -#### Guild#setChannelPosition - -`guild.setChannelPosition()` has been removed entirely. As an alternative, you can use `channel.setPosition()`, or `guild.setChannelPositions()`, which accepts accepts the same form of data as `guild.setChannelPosition` but inside an array. - -```diff -- guild.setChannelPosition({ channel: '123456789012345678', position: 1 }); -+ guild.setChannelPositions([{ channel: '123456789012345678', position: 1 }]); -+ channel.setPosition(1); -``` - -#### Guild#setPosition - -`guild.setPosition()` has been removed entirely, along with all other user account-only properties and methods. - -#### Guild#setRolePosition - -`guild.setRolePosition()` has been removed entirely as an extraneous helper method. As an alternative, you can use `role.setPosition()`. - -```diff -- guild.setRolePosition({ role: '123456789012345678', position: 1 }); -+ role.setPosition(1); -``` - -#### Guild#splashURL - -`guild.splashURL` is now a method, as opposed to a property. It also allows you to determine the file format and size to return. - -```diff -- guild.splashURL; -+ guild.splashURL(); -+ guild.splashURL({ format: 'png', size: 1024 }); -``` - -#### Guild#suppressEveryone - -`guild.suppressEveryone` has been removed entirely, along with all other user account-only properties and methods. - -#### Guild#sync - -`guild.sync()` has been removed entirely, along with all other user account-only properties and methods. - -#### Guild#unban - -`guild.unban()` has been transformed in the shape of a DataStore and is now a method on `GuildMemberStore`. In addition, it also now optionally accepts a string as a second parameter for `reason`. - -```diff -- guild.unban('123456789012345678'); -+ guild.members.unban('123456789012345678', 'Ban appealed.'); -``` - -### GuildChannel - -The properties of a channel relating to its position have been renamed. `guildChannel.calculatedPosition` is now `guildChannel.position`. `guildChannel.position` is now more clearly named `guildChannel.rawPosition` to denote that it's directly from the API without any sorting. - -```diff -- channel.calculatedPosition; -+ channel.position; - -- channel.position; -+ channel.rawPosition; -``` - -#### GuildChannel#clone - -The first, second, third, and fourth parameters in `channel.clone()` have been changed/removed, leaving it with a total of one parameter. The `name`, `withPermissions`, `withTopic`, and `reason` parameters from v11 have been merged into an object as the first parameter. Several other parameters have also been added to the options object. - -#### GuildChannel#createInvite - -The second parameter in `channel.createInvite()` has been removed, leaving it with a total of one parameter. The `reason` parameter from v11 have been merged into an object as the first parameter. - -```diff -- channel.createInvite({ temporary: true }, 'Just testing'); -+ channel.createInvite({ temporary: true, reason: 'Just testing' }); -``` - -#### GuildChannel#members - -`guildChannel.members` has been removed from `guildChannel.members` and added to `textChannel.members` and `voiceChannel.members`. - -#### GuildChannel#messageNotifications - -`guildChannel.messageNotifications` has been removed entirely, along with all other user account-only properties. - -#### GuildChannel#muted - -`guildChannel.muted` has been removed entirely, along with all other user account-only properties. - -#### GuildChannel#\*\*\*Permissions - -`guildChannel.memberPermissions` and `guildChannel.rolePermissions` are now private. - -#### GuildChannel#replacePermissionOverwrites - -`guildChannel.replacePermissionOverwrites` has been removed entirely. - -#### GuildChannel#setPosition - -The second parameter in `channel.setPosition()` has been changed. The `relative` parameter from v11 has been merged into an object. - -```diff -- channel.setPosition(10, true); -+ channel.setPosition(10, { relative: true, reason: 'Basic organization' }); -``` - -### GuildMember - -#### GuildMember\*\*\*Role(s) - -All of the methods to modify a member's roles have been moved to the `GuildMemberRoleStore`. - -```diff -- guildMember.addRole('123456789012345678'); -- guildMember.addRoles(['123456789012345678', '098765432109876543']); -+ guildMember.roles.add('123456789012345678'); -+ guildMember.roles.add(['123456789012345678', '098765432109876543']); - -- guildMember.removeRole('123456789012345678'); -- guildMember.removeRoles(['123456789012345678', '098765432109876543']); -+ guildMember.roles.remove('123456789012345678'); -+ guildMember.roles.remove(['123456789012345678', '098765432109876543']); - -- guildMember.setRoles(['123456789012345678', '098765432109876543']); -+ guildMember.roles.set(['123456789012345678', '098765432109876543']); -``` - -#### GuildMember#ban - -`guildMember.ban()` has been transformed in the shape of a DataStore and is now a method on `GuildMemberStore`. The second parameter has been changed from a string or an object to only accept an object. The `reason` and `days` parameters are keys in the `options` object. - -```diff -- member.ban(user, 7); -+ guild.members.ban(user, { days: 7 }); - -- member.ban(user, 'Too much trolling'); -+ guild.members.ban(user, { reason: 'Too much trolling' }); -``` - -#### GuildMember#\*\*\*Role - -`guildMember.colorRole`, `guildMember.highestRole` and `guildMember.hoistRole` have all been moved to the `GuildMemberRoleStore` DataStore. - -```diff -- guildMember.colorRole; -+ guildMember.roles.color; - -- guildMember.highestRole; -+ guildMember.roles.highest; - -- guildMember.hoistRole; -+ guildMember.roles.hoist; -``` - -#### GuildMember#\*\*\*deaf - -`guildMember.deaf`, `guildMember.selfDeaf` and `guildMember.serverDeaf` have all been moved to the `VoiceState` class. - -```diff -- guildMember.deaf; -+ guildMember.voice.deaf; - -- guildMember.selfDeaf; -+ guildMember.voice.selfDeaf; - -- guildMember.serverDeaf; -+ guildMember.voice.serverDeaf; -``` - -#### GuildMember#hasPermission - -The `explicit` parameter has been removed entirely. The `checkAdmin` and `checkOwner` parameters have been changed into a single `options` object with those values as keys. - -```diff -- guildMember.hasPermission('MANAGE_MESSAGES', true, false, false); -+ guildMember.hasPermission('MANAGE_MESSAGES', { checkAdmin: false, checkOwner: false }); -``` - -#### GuildMember#hasPermissions - -`guildMember.hasPermissions()` has been removed in favor of `guildMember.hasPermission()`. - -```diff -- guildMember.hasPermissions(['MANAGE_MESSAGES', 'MANAGE_ROLES']); -+ guildMember.hasPermission(['MANAGE_MESSAGES', 'MANAGE_ROLES']); -``` - -#### GuildMember#lastMessage - -The `guildMember.lastMessage` property is now read-only. - -#### GuildMember#missingPermissions - -`guildMember.missingPermissions` has been removed entirely. - -#### GuildMember#\*\*\*mute - -`guildMember.mute`, `guildMember.selfMute` and `guildMember.serverMute` have all been moved to the `VoiceState` class. - -```diff -- guildMember.mute; -+ guildMember.voice.mute; - -- guildMember.selfMute; -+ guildMember.voice.selfMute; - -- guildMember.serverMute; -+ guildMember.voice.serverMute; -``` - -#### GuildMember#roles - -`guildMember.roles` is now a DataStore instead of a Collection. - -#### GuildMember#send\*\*\* - -Just like the `textChannel#send***` methods, all the `.send***()` methods have been removed in favor of one general `.send()` method. Read through the [textChannel#send\*\*\*](/additional-info/changes-in-v12.md#channelsend) section for more information. - -#### GuildMember#set\*\*\* - -Along with the rest of the voice-related methods and properties, the methods for moving, muting and deafening a member have been moved to the `VoiceState` class. - -```diff -- guildMember.setDeaf(true); -+ guildMember.voice.setDeaf(true); - -- guildMember.setMute(true); -+ guildMember.voice.setMute(true); - -- guildMember.setVoiceChannel('123456789012345678'); -+ guildMember.voice.setChannel('123456789012345678'); -``` - -#### GuildMember#speaking - -`guildMember.speaking` has been moved to the `VoiceState` class. - -```diff -- guildMember.speaking; -+ guildMember.voice.speaking; -``` - -#### GuildMember#voice\*\*\* - -`guildMember.voiceChannel`, `guildMember.voiceChannelID` and `guildMember.voiceSessionID` have all been moved to the `VoiceState` class, which is read-only. - -```diff -- guildMember.voiceChannel; -+ guildMember.voice.channel; - -- guildMember.voiceChannelID; -+ guildMember.voice.channelID; - -- guildMember.voiceSessionID; -+ guildMember.voice.sessionID; -``` - -### Invite - -#### Invite#\*\*\*ChannelCount - -`invite.textChannelCount` and `invite.voiceChannelCount` have both been removed entirely. - -### Message - -#### Message#acknowledge - -`message.acknowledge()` has been removed entirely, along with all other user account-only properties and methods. - -#### Message#clearReactions - -`message.clearReactions()` has been transformed in the shape of a DataStore. - -```diff -- message.clearReactions(); -+ message.reactions.removeAll(); -``` - -#### Message#delete - -The first parameter in `message.delete()` has been changed. The `timeout` parameter from v11 have been merged into an object as the first parameter. In addition, there is now another optional key in the object, `reason`. - -```diff -- message.delete(5000); -+ message.delete({ timeout: 5000, reason: 'It had to be done.' }); -``` - -#### Message#editCode - -In the same sense that the `channel.sendCode()` method was removed, `message.editCode()` has also been removed entirely. - -```diff -- message.editCode('js', 'const version = 11;'); -+ message.edit('const version = 12;', { code: 'js' }); -``` - -#### Message#hit - -`message.hit` has been removed entirely, as it was used for user-account only searches. - -#### Message#is(Member)Mentioned - -`message.isMentioned()` and `message.isMemberMentioned()` have been removed in favor of `message.mentions.has()`. - -```diff -- message.isMentioned('123456789012345678'); -- message.isMemberMentioned('123456789012345678'); -+ message.mentions.has('123456789012345678'); -``` - -#### Message#member - -`message.member` is now read-only. - -### MessageAttachment - -The `MessageAttachment` class constructor parameters have changed to reflect that `Attachment` has been removed and rolled into `MessageAttachment`. - -#### MessageAttachment#client - -`attachment.client` has been removed entirely so an attachment can be constructed without needing the full client. - -#### MessageAttachment#filename - -`attachment.filename` has been renamed to `attachment.name`. - -#### MessageAttachment#filesize - -`attachment.filesize` has been renamed to `attachment.size`. - -### MessageCollector - -See the `Collector` section for most of the changes to `MessageCollector`, such as the new `dispose` method and event. Changes to the `MessageCollector` constructor in particular are as follows: - -#### MessageCollector#channel - -A `GroupDMChannel` is no longer able to be used for a collector, only `DMChannel` and `TextChannel`. - -#### MessageCollector#message - -The `messageCollector.message` event has been removed in favor of the generic `collector.on` event. - -### MessageCollectorOptions - -#### MessageCollectorOptions#max(Matches) - -The `max` and `maxMatches` properties of the `MessageCollector` class have been renamed and repurposed. - -```diff -- `max`: The The maximum amount of messages to process. -+ `maxProcessed`: The maximum amount of messages to process. - -- `maxMatches`: The maximum amount of messages to collect. -+ `max`: The maximum amount of messages to collect. -``` - -### MessageEmbed - -`MessageEmbed` now encompasses both the received embeds in a message and the constructor - the `RichEmbed` constructor was removed in favor of `MessageEmbed`. - -#### MessageEmbed#attachFiles - -`RichEmbed.attachFile()` is the only method that did not make the transition from v11 to v12. The `MessageEmbed.attachFiles()` works for one or more files. - -#### MessageEmbed#client - -`messageEmbed.client` has been removed entirely so a new embed can be constructed without needing the full client. - -#### MessageEmbed#message - -`messageEmbed.message` has been removed entirely so a new embed can be constructed without needing the full client. - -### MessageMentions - -#### MessageMentions#has - -`mentions.has()` has been added, replacing `message.isMentioned()` and `message.isMemberMentioned()`. It has two paramets: the first is `data` representing a `User`, `GuildMember`, `Role`, or `GuildChannel` and an optional `options` object. - -```diff -- message.isMentioned('123456789012345678'); -- message.isMemberMentioned('123456789012345678'); -+ message.mentions.has('123456789012345678'); -+ message.mentions.has('123456789012345678', { ignoreDirect: true, ignoreRoles: true, ignoreEveryone: true }); -``` - -### MessageReaction - -#### MessageReaction#fetchUsers - -`messageReaction.fetchUsers()` has been transformed in the shape of a DataStore. In addition, the first parameter has been removed in favor of an object. - -```diff -- reaction.fetchUsers(50); -+ reaction.users.fetch({ limit: 50 }); -``` - -#### MessageReaction#remove - -`messageReaction.remove()` has been transformed in the shape of a DataStore. - -```diff -- reaction.remove(); -+ reaction.users.remove(); -``` - -### OAuth2Application - -The `OAuth2Application` class has been renamed to `ClientApplication`. - -#### OAuth2Application#bot - -`application.bot` has been removed entirely. - -#### OAuth2Application#flags - -`application.flags` has been removed entirely. - -#### OAuth2Application#iconURL - -`application.iconURL` is now a method, as opposed to a property. It also allows you to determine the file format and size to return. - -```diff -- user.iconURL; -+ user.iconURL(); -+ user.iconURL({ format: 'png', size: 1024 }); -``` - -#### OAuth2Application#redirectURLs - -`application.redirectURLs` has been removed entirely. - -#### OAuth2Application#reset - -`application.reset()` has been removed entirely, as it was an endpoint for user accounts. - -#### OAuth2Application#rpcApplicationState - -`application.rpcApplicationState` has been removed entirely. - -#### OAuth2Application#secret - -`application.secret` has been removed entirely. - -### PartialGuild(Channel) - -The `PartialGuild` and `PartialGuildChannel` classes for use with invites have been removed entirely. - -### Permissions - -#### Permissions#_member - -`permissions._member` has been removed entirely. - -#### Permissions#flags - -The following permission flags have been renamed: - -* `READ_MESSAGES` -> `VIEW_CHANNEL` -* `EXTERNAL_EMOJIS` -> `USE_EXTERNAL_EMOJIS` -* `MANAGE_ROLES_OR_PERMISSIONS` -> `MANAGE_ROLES` - -#### Permission#hasPermission(s) - -`permissions.hasPermission()` and `permissions.hasPermissions()` have been removed entirely in favor of `permissions.has()`. This change reduces extraneous helper methods. - -#### Permissions#missingPermissions - -`permissions.missingPermissions()` has been renamed to `permissions.missing()` and also refactored. The second parameter in v11 was named `explicit`, described as "Whether to require the user to explicitly have the exact permissions", defaulting to `false`. However, the second parameter in v11 is named `checkAdmin`, described as "Whether to allow the administrator permission to override", defaulting to `true`. - -```diff -- permissions.missingPermissions(['MANAGE_SERVER']); -+ permissions.missing(['MANAGE_SERVER']); -``` - -#### Permissions#raw - -`permissions.raw` has been removed in favor of `permissions.bitfield`. - -```diff -- permissions.raw; -+ permissions.bitfield; -``` - -#### Permissions#resolve - -`permissions.resolve()` has been removed entirely. - -### Presence - -#### Presence#game - -`presence.game` has been removed in favor of the `Activity` class. - -```diff -- presence.game; -+ presence.activity; -``` - -### RichEmbed - -The `RichEmbed` class has been removed in favor of the `MessageEmbed` class. - -#### RichEmbed#attachFile - -`RichEmbed.attachFile()` has been removed in favor of `MessageEmbed.attachFiles()`. - -```diff -- new RichEmbed().attachFile('attachment://file-namme.png'); -+ new MessageEmbed().attachFiles(['attachment://file-namme.png']); - -- new RichEmbed().attachFile({ attachment: './file-name.png' }); -+ new MessageEmbed().attachFiles([{ attachment: './file-name.png' }]); - -- new RichEmbed().attachFile(new Attachment('./file-name.png')); -+ new MessageEmbed().attachFiles([new MessageAttachment('./file-name.png')]); -``` - -### RichPresenceAssets - -#### RichPresenceAssets#\*\*\*ImageURL - -Both properties relating to the rich presence's image URL have been changed to be a method, as opposed to a property. It also allows you to determine the file format and size to return. - -```diff -- asset.smallImageURL; -- asset.largeImageURL; -+ asset.smallImageURL(); -+ asset.largeImageURL({ format: 'png', size: 1024 }); -``` - -### Role - -The properties of a role relating to its position have been renamed. `role.calculatedPosition` is now `role.position`. `role.position` is now more clearly named `role.rawPosition` to denote that it's directly from the API without any sorting. - -```diff -- role.calculatedPosition; -+ role.position; - -- role.position; -+ role.rawPosition; -``` - -#### Role#hasPermission(s) - -`role.hasPermission()` and `role.hasPermissions()` have been removed in favor of `permissions.has()`. - -```diff -- role.hasPermission('MANAGE_MESSAGES'); -+ role.permissions.has('MANAGE_MESSAGES'); -``` - -```diff -- role.hasPermissions(['MANAGE_MESSAGES', 'MANAGE_SERVER']); -+ role.permissions.has(['MANAGE_MESSAGES', 'MANAGE_SERVER']); -``` - -#### Role#serialize - -`role.serialize()` has been removed as an extraneous helper method. - -```diff -- role.serialize(); -+ role.permissions.serialize(); -``` - -#### Role#setPosition - -The optional, second parameter of the `role.setPosition()` method has been changed to an object; its keys are `relative` (a boolean) and `reason` (a string). - -```diff -- role.setPosition(3, true); -+ role.setPosition(3, { relative: true, reason: 'Needed to be higher.' }); -``` - -### Shard - -The `death` and `spawn` events for a shard can also include a `Worker` in addition to the `ChildProcess` that was exited or spawned. - -#### Shard#args - -`shard.args` is now a property of the shard and has been removed as a parameter from the constructor. - -#### Shard#respawn - -`shard.respawn` now takes a second, optional parameter `spawnTimeout`, how long to wait in milliseconds until the shard's `Client` becomes ready. - -#### Shard#spawn - -The parameters in v11 have been removed and replaced with a single, optional parameter, `spawnTimeout`. - -### ShardClientUtil - -In order to make use of workers introduced in Node v10.5.0, a new `mode` parameter is available in the constructor. - -#### ShardClientUtil#id - -`shardClientUtil.id` has been removed and replaced with `shardClientUtil.ids`, which is an array of shard IDs of the current client. - -#### ShardClientUtil#singleton - -`shardCLientUtil` now has a second parameter `mode` to specify whether it's a `process` or `worker`. - -### ShardingManager - -#### ShardingManger#_spawn - -The private method `shardingManager._spawn()` has been removed entirely. - -#### ShardingManager#createShard - -The `id` parameter is now optional and defaults to `this.shards.size`. - -#### ShardingManager#launch - -The `shardingManager.launch` event has been removed entirely and replaced with the `shardingManager.shardCreate` event. - -#### ShardingManager#message - -The `shardingManager.message` event has been removed from this class and is now on the `Shard` class. - -#### ShardingManager#respawnAll - -The `waitForReady` parameter has been renamed to `spawnTimeout`, and the `currentShardIndex` parameter has been removed entirely. - -#### ShardingManager#spawn - -A third, optional parameter `spawnTimeout` has been added, specifying how long to wait in miliseconds to wait until the `Client` is ready; the default is `30000`. - -### StreamDispatcher - -`StreamDispatcher` now extends `WritableStream` from Node, you can see the docs [here](https://nodejs.org/api/stream.html#stream_class_stream_writable). - -#### StreamDispatcher#destroyed - -`streamDispatcher.destroyed` has been removed entirely. - -#### StreamDispatcher#end - -The `end` event and method are now extended from the `WritableStream` class in Node, instead of being custom functions. - -#### StreamDispatcher#passes - -`streamDispatcher.passes` has been removed entirely. - -#### StreamDispatcher#pause - -The `streamDispatcher.pause` method now takes an optional parameter `silence`, to specify whether to play silence while paused to prevent audio glitches. Its value is a `boolean` and defaults to `false`. - -```diff -- dispatcher.pause(); -+ dispatcher.pause(true); -``` - -#### StreamDispatcher#stream - -The `streamDispatcher.stream` property has been removed entirely and has been replaced with the `streamDispatcher.broadcast` property, which is the broadcast controlling the stream, if any. - -#### StreamDispatcher#time - -The `streamDispatcher.time` property has been renamed to `streamDispatcher.streamTime`. - -### TextChannel - -#### TextChannel#acknowledge - -Has been removed entirely, along with all other user account-only methods and properties. - -#### TextChannel#\*\*\*position - -See the [GuildChannel](/additional-info/changes-in-v12.md#guildchannel) section for changes to positions. - -#### TextChannel#clone - -All parameters have been removed and reconfigured into a single object. - -```diff -- channel.clone(undefined, true, false, 'Needed a clone'); -+ channel.clone({ name: undefined, reason: 'Needed a clone' }); -``` - -#### TextChannel#createCollector - -`textChannel.createCollector()` has been removed entirely in favor of `textChannel.createMessageCollector()`. - -See [this section](/additional-info/changes-in-v12.md#messagecollector) for changes to the `MessageCollector` class. - -```diff -- channel.createCollector(filterFunction, { maxMatches: 2, max: 10, time: 15000 }); -+ channel.createMessageCollector(filterFunction, { max: 2, maxProcessed: 10, time: 15000 }); -``` - -#### TextChannel#memberPermissions - -This method is now private. - -#### TextChannel#rolePermissions - -This method is now private. - -#### TextChannel#search - -This method has been removed, along with all other user account-only methods. - -#### TextChannel#send\*\*\* - -All the `.send***()` methods have been removed in favor of one general `.send()` method. - -```diff -- channel.sendMessage('Hey!'); -+ channel.send('Hey!'); -``` - -```diff -- channel.sendEmbed(embedVariable); -+ channel.send(embedVariable); -+ channel.send({ embed: embedVariable }); -``` - -::: warning -`channel.send(embedVariable)` will only work if that variable is an instance of the `MessageEmbed` class; object literals won't give you the expected result unless your embed data is inside an `embed` key. -::: - -```diff -- channel.sendCode('js', 'const version = 11;'); -+ channel.send('const version = 12;', { code: 'js' }); -``` - -```diff -- channel.sendFile('./file.png'); -- channel.sendFiles(['./file-one.png', './file-two.png']); -+ channel.send({ - files: [{ - attachment: 'entire/path/to/file.jpg', - name: 'file.jpg', - }] -+ channel.send({ - files: ['https://cdn.discordapp.com/icons/222078108977594368/6e1019b3179d71046e463a75915e7244.png?size=2048'] -}); -``` - -```diff -- channel.sendFiles(['./file-one.png', './file-two.png']); -+ channel.send({ files: [{ attachment: './file-one.png' }, { attachment: './file-two.png' }] }); -+ channel.send({ files: [new MessageAttachment('./file-one.png'), new MessageAttachment('./file-two.png')] }); -``` - -#### TextChannel#fetch(Pinned)Message(s) - -`channel.fetchMessage()`, `channel.fetchMessages()`, and `channel.fetchPinnedMessages()` were all removed and transformed in the shape of DataStores. - -```diff -- channel.fetchMessage('123456789012345678'); -+ channel.messages.fetch('123456789012345678'); -``` - -```diff -- channel.fetchMessages({ limit: 100 }); -+ channel.messages.fetch({ limit: 100 }); -``` - -```diff -- channel.fetchPinnedMessages(); -+ channel.messages.fetchPinned(); -``` - -### User - -#### User#addFriend - -`user.addFriend()` has been removed entirely, along with all other user account-only methods. - -#### User#avatarURL - -`user.avatarURL` is now a method, as opposed to a property. It also allows you to determine the file format and size to return. - -```diff -- user.avatarURL; -+ user.avatarURL(); -+ user.avatarURL({ format: 'png', size: 1024 }); -``` - -#### User#block - -`user.block()` has been removed entirely, along with all other user account-only methods. - -#### User#displayAvatarURL - -`user.displayAvatarURL` is now a method, as opposed to a property. It also allows you to determine the file format and size to return. - -```diff -- user.displayAvatarURL; -+ user.displayAvatarURL(); -+ user.displayAvatarURL({ format: 'png', size: 1024 }); -``` - -#### User#fetchProfile - -`user.fetchProfile()` has been removed entirely, along with all other user account-only methods. - -#### User#note - -`user.note` has been removed entirely, along with all other user account-only methods. - -#### User#removeFriend - -`user.removeFriend()` has been removed entirely, along with all other user account-only methods. - -#### User#setNote - -`user.setNote()` has been removed entirely, along with all other user account-only methods. - -#### User#send\*\*\* - -Just like the `textChannel#send***` methods, all the `.send***()` methods have been removed in favor of one general `.send()` method. Read through the [textChannel#send\*\*\*](/additional-info/changes-in-v12.md#channelsend) section for more information. - -#### User#unblock - -`user.unblock()` has been removed entirely, along with all other user account-only methods. - -### UserConnection - -The `UserConnection` class has been removed entirely, along with all other user account-only properties. - -### UserProfile - -The `UserProfile` class has been removed entirely, along with all other user account-only properties. - -### VoiceBroadcast - -`VoiceBroadcast` now implements `PlayInterface` instead of `VolumeInterface`. - -#### VoiceBroadcast#currentTranscoder - -This property has been removed entirely. - -#### VoiceBroadcast#destroy - -This method has been removed entirely. - -#### VoiceBroadcast#dispatchers - -This property has been renamed to `subscribers` and is no longer read-only. - -```diff -- broadcast.dispatchers; -+ broadcast.subscribers; -``` - -#### VoiceBroadcast#end - -This event has been removed from the `VoiceBroadcast` class and is implemented from the `WritableStream` class from Node, which `BroadcastDispatcher` implements. - -#### VoiceBroadcast#error - -This event has been removed from the `VoiceBroadcast` class to the `BroadcastDispatcher` class. - -#### VoiceBroadcast#pause - -This method has been removed from the `VoiceBroadcast` class to the `BroadcastDispatcher` class. - -#### VoiceBroadcast#play\*\*\* - -All `.play\*\*\*()` methods have been removed and transformed into a single `.play()` method. - -#### VoiceBroadcast#prism - -This property has been removed entirely. - -#### VoiceBroadcast#resume - -This method has been removed from the `VoiceBroadcast` class to the `BroadcastDispatcher` class. - -#### VoiceBroadcast#warn - -This event has been removed entirely. - -### VoiceConnection - -The `VoiceConnection` class also implements the new `PlayInterface` class in addition to extending `EventEmitter` from Node. - -#### VoiceConnection#createReceiver -`voiceconnection.createReceiver()` has been removed, there is now a single receiver that be accessed from `voiceConnection.receiver` - -#### VoiceConnection#play\*\*\*\ - -All `connection.play\*\*\*()` methods have been removed in favor of one, flexible `.play()` method. - -#### VoiceConnection#prism - -This property has been removed entirely. - -#### VoiceConnection#receivers - -This property has been removed entirely. - -#### VoiceConnection#sendVoiceStateUpdate - -This method has been removed entirely. - -#### VoiceConnection#set\*\*\* - -Both `connection.setSessionID()` and `connection.setTokenAndEndpoint()` have been removed entirely. - -### VoiceReceiver - -#### VoiceReceiver#create\*\*\*Stream - -Both the `receiver.createOpusStream()` and `receiver.createPCMStream()` methods have been condensed into one method, `receiver.createStream()`, which also optionally accepts a `ReceiveStreamOptions` object for the stream. - -```diff -- receiver.createOpusStream('123456789012345678'); -- receiver.createPCMStream('123456789012345678'); -+ receiver.createStream('123456789012345678', { mode: 'opus', end: 'silence' }); -``` - -#### VoiceReceiver#destroy - -This method has been removed entirely, refer to `StreamDispatcher#destroy` for documentation. - -#### VoiceReceiver#destroyed - -This property has been removed entirely. - -#### VoiceReceiver#opus - -This event has been removed entirely. - -#### VoiceReceiver#pcm - -This event has been removed entirely. - -#### VoiceReceiver#recreate - -This method has been removed entirely. - -#### VoiceReceiver#voiceConnection - -This property has been removed entirely. - -#### VoiceReceiver#warn - -This event has been removed entirely, use the `receiver.debug` event instead. - -### VoiceRegion - -#### VoiceRegion#sampleHostname - -This property has been removed entirely. - -### Webhook - -#### Webhook#send\*\*\* - -Just like the `TextChannel#send***` methods, all the `.send***()` methods have been removed in favor of one general `.send()` method. Read through the [TextChannel#send\*\*\*](/additional-info/changes-in-v12.md#channelsend) section for more information. - -### WebhookClient - -The `WebhookClient` class now extends `BaseClient` and implements `Webhook` instead of just extending `Webhook`, so a lot of methods and properties are documented there, as opposed to on the client. - ---- - -## Additions - -::: warning -Remember to add examples for the additions. -::: - -### Activity - -### ActivityFlags - -### ActivityOptions - -These are options for setting an `Activity`. - -### APIMessage - -### Base - -### BaseClient - -### BitField - -### BroadcastDispatcher - -### CategoryChannel - -#### CategoryChannel#members - -Similar to `textChannel#members` and `voiceChannel#members`, `categoryChannel#members` returns a `Collection` of `GuildMembers` who can see the category, mapped by their ID. - -### Channel - -#### Channel#toString - -`channel.toString()` was moved from `GuildChannel` to `Channel`. - -#### Channel#type - -`channel.type` now may also return `unknown`. - -### Client - -#### Client#clearImmediate - -#### Client#guildIntegrationsUpdate - -#### Client#invalidated - -#### Client#setImmediate - -#### Client#webhookUpdate - -### ClientApplication - -This is a not a new class; it was formerly called `OAuth2Application` in v11. Changes and deletions to methods and properties are covered above (link needed). Additions are as follow: - -#### ClientApplication#cover(Image) - -`ClientApplication.cover` and its associated method `ClientApplication.coverImage()` return the URL to the application's cover image, with optional modifiers if applied in the method. - -```js -ClientApplication.coverImage({ width: 1024, height: 1024 }); -``` - -#### ClientApplication#fetchAssets - -`ClientApplication.fetchAssests()` returns a promise that resolves into an array of `ClientAsset` objects, each of which contains `id`, `name` and `type` keys. - -### ClientOptions - -#### ClientOptions#partials - -`clientOptions.partials` has been added to allow for partial structures - see the `Partials` section of the guide for more details. - -#### ClientOptions#retry - -`clientOptions.retry` has been added to allow a maximum amount of reconnect attempts on 5XX errors. - -#### ClientOptions#presence - -`clientOptions.presence` has been added to specify presence data to set upon login. - -### ClientVoiceManager - -### Collector - -#### Collector#(handle)Dispose - -`collector.handleDispose` and `collector.dispose()` have been added to remove an element from the collection. - -### CollectorOptions - -#### CollectorOptions#dispose - -`collectorOptions.dispose` has been added to allow for deleted data to be removed from the collection. - -### DataStore - -The DataStore class was added in order to store various data types. Uses include -- RoleStore -- UserStore -- GuildStore -- ChannelStore -- MessageStore -- PresenceStore -- ReactionStore -- GuildEmojiStore -- GuildMemberStore -- GuildChannelStore -- ReactionUserStore -- GuildEmojiRoleStore -- GuildMemberRoleStore - -### DiscordAPIError - -#### DiscordAPIError#httpStatus - -The `DiscordAPIError#httpStatus` has been added with the 4xx status code that the error returns. See [the MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#Client_error_responses) for more details. - -### DMChannel - -#### DMChannel#lastMessage - -The message object of the last message in the channel, if one was sent. It is a read-only property. - -#### DMChannel#lastPin\*\*\* - -Two properties have been added, `dmChannel#lastPinAt` (read-only) and `dmChannel#lastPinStamp`, which returns the Date and timestamp, respectively, of the last pinned message if one is present. - -### Guild - -#### Guild#createIntegration - -`guild.createIntegration()` has been added. - -#### Guild#fetchEmbed - -`guild.fetchEmbed` has been added. - -#### Guild#fetchIntegrations - -`guild.fetchIntegrations()` has been added. - -#### Guild#fetchVanityCode - -`guild.fetchVanityCode()` has been added. - -#### Guild#setEmbed - -`guild.setEmbed()` has been added. - -#### Guild#shard(ID) - -`guild.shard` (read-only) and `guild.shardID` have been added, representing the information of the shard the guild is on. - -### GuildAuditLogs - -#### GuildAuditLogs#Actions - -`auditLogs.Actions()` has been added (static method). - -#### GuildAuditLogs#Targets - -`auditLogs.Targets()` has been added (static method). - -### GuildChannel - -#### GuildChannel#permissionsLocked - -`guildChannel.permissionsLocked` is a boolean value representing if the `permissionOverwrites` of the channel match its parent's `permissionOverwrites`. - -#### GuildChannel#updateOverwrites - -Creates or update an existing overwrite for a user or role. The first parameter is a `PermissionOverwriteOption` object; the second, optional parameter is `reason`, a string. - -```js -channel.updateOverwrite(message.author, { - SEND_MESSAGES: false, -}); -``` - -#### GuildChannel#viewable - -`guildChannel.viewable` is a boolean value representing whether the channel is visible to the client user. - -### HTTPError - -### Integration - -### Message - -#### Message#activity - -`message.activity` has been added. - -#### Message#application - -`message.application` has been added. - -#### Message.url - -`message.url` has been added in order to provide a URL to jump to the message. - -### MessageAttachment - -#### MessageAttachment#setAttachment - -`attachment.setAttachment()` has been added. - -#### MessageAttachment#setFile - -`attachment.setFile()` has been added. - -#### MessageAttachment#setName - -`attachment.setName()` has been added. - -### MessageEmbed - -#### MessageEmbed#files - -`MessageEmbed.files` has been added as an array of files in the `MessageEmbed`. - -#### MessageEmbed#length - -`MessageEmbed.length` has been added. It returns a `number` equal to all of the fields, title, description, and footer. - -### Permissions - -#### Permissions#flags -`PRIORITY_SPEAKER` has been added. - -### PlayInterface - -This is a new class to play audio over `VoiceConnection`s and `VoiceBroadcast`s. - -### Presence - -#### Presence#clientStatus - -The new `presence.clientStatus` property returns an object with three keys: `web`, `mobile` and `desktop`; their values are a `PresenceStatus` string. This property allows you to check which client the member or user is using to access Discord. - -#### Presence#guild - -`presence.guild` has been added as a helper property to represent the `Guild` the presence belongs to, if applicable. - -#### Presence#member - -`presence.member` is a read-only property to represent the `GuildMember` the presence belongs to, if applicable. - -#### Presence#user(ID) - -`presence.user` (read-only) and `presence.userID` are properties to represent a `User` and its ID that the presence belongs to. The former can be null if the `User` is not cached. - -### ReactionCollector - -#### ReactionCollector#empty - -`reactionCollector.empty()` has been added as a method to remove all collected reactions from the collector. - -#### ReactionCollector#key - -#### ReactionCollector#remove - -The new `remove` event emits when a collected reaction is un-reacted, if the `dispose` option is set to `true` - -### Shard - -#### Shard#_evals - -The private property `_evals` has been added to map ongoing promises for calls to `shard.eval()`. - -#### Shard#_fetches - -The private property `_fetches` has been added to map ongoing promises for calls to `shard.fetchClientValues()`. - -#### Shard#worker - -### ShardClientUtil - -#### ShardClientUtil#client - -#### ShardClientUtil#parentPort - -The message port for the master process, if the mode of the `ShardClientUtil` is `worker`. - -#### ShardClientUtil#respawnAll - -`shardClientUtil.respawnAll()` will request a respawn of all shards. It has three parameters, all of which are optional: `shardDelay`, how to long to wait in milliseconds between each shard; `respawnDelay`, how long to wait between killing the shard's process or worker and restarting it; and `spawnTimeout`, how long to wait in milliseconds for a shard to become ready before moving to the next shard. - -### Speaking - -The `Speaking` class has been added as a data structure to interact with the bitfields present when a `GuildMember` is speaking, or in the `VoiceConnection#speaking` event. - -### StreamDispatcher - -#### StreamDispatcher#bitrateEditable - -#### StreamDispatcher#paused\*\*\* - -Two new properties have been added, `pausedSince` and `pausedTime`, to represent the timestamp when the stream was paused, and how long it's been paused for in milliseconds, respectively. - -#### StreamDispatcher#set\*\*\* - -Several new methods have been added to adjust various aspects of the stream. Methods marked with a \* denote that they're usable only with a compatible Opus stream. - -- `setFEC()`\* - whether to forward error correction or not if using a compatible Opus stream -- `setPLP()`\* - sets the expected packet loss percentage if using a compatible Opus stream -- `setVolume()` - sets the volume relative to the input stream -- `setVolumeDecibels()` - sets the volume in decibels -- `setVolumeLogarithmic()` - sets the volume so that a perceived value of `0.5` is half the perceived volume, etc. - -#### StreamDispatcher#volumeChange - -A new event listener, it is emitted when a volume change in the stream is detected. - -```js -dispatcher.on('volumeChange', (oldVolume, newVolume) => { - console.log(`Volume changed from ${oldVolume} to ${newVolume}.`); -}); -``` - -### TextChannel - -#### TextChannel#lastPinTimestamp - -`TextChannel.lastPinTimestamp` was added. - -#### TextChannel#lastPinAt - -`TextChannel.lastPinAt` was added. - -### User - -#### User#lastMessageChannelID - -#### User#locale - -`user.locale` has been added. - -### Util - -#### Util#cleanContent - -This new method converts all mentions to their equivalent text. - -#### Util#discordSort - -This new method sorts a `Collection` by Discord's position and ID. - -#### Util#flatten - -This new method flattens any object. Any `Collection`s in the object will be converted to an array of keys. - -#### Util#resolveColor - -This new method resolves a `ColorResolvable` into a color number. - -#### Util#resolveString - -THis new method resolves a `StringResolvable` into a string. - -#### Util#Constants - -#### Constant.Colors -`WHITE` and `YELLOW` have been added as values. - -### VoiceBroadcast - -#### VoiceBroadcast#dispatcher - -This new property represents the master dispatcher - if any - that controls everything played by subscribed dispatchers. - -### VoiceChannel - -#### VoiceChannel#editable - -This new property returns a `boolean` value whether the client can edit the `VoiceChannel` or not, eg. any change to the channel besides moving it via `channel.setPosition()`. It differs from `channel.manageable` in that it also checks if the client has the `CONNECT` permissions for that particular channel. - -### VoiceReceiver - -#### VoiceReceiver#debug - -This new event is emitted whenever there is a warning and will emit either with an `Error` object or string, depending on what causes it to be emitted. - -### VoiceState - -### VolumeInterface - -#### VolumeInterface#volumeEditable - -This new property returns a `boolean` value whether the client can edit the volume of the stream. - -### Webhook - -#### Webhook#url - -This new property returns a `string` representing the URL of the webhook, and is read-only. - -### WebSocketManager - -This new class represents the manager of the websocket connection for the client. - -### WebSocketShard - -This new class represents a `Shard`'s websocket connection. diff --git a/Ajuda/guide-master/guide/additional-info/collections.md b/Ajuda/guide-master/guide/additional-info/collections.md deleted file mode 100644 index 609179c..0000000 --- a/Ajuda/guide-master/guide/additional-info/collections.md +++ /dev/null @@ -1,107 +0,0 @@ -# Collections - -Discord.js comes with this utility class known as `Collection`. -It extends JavaScript's native `Map` class, so it has all the features of `Map` and more! - -::: warning -If you're not familiar with `Map`, read [MDN's page on it](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) before continuing. You should be familiar with `Array` [methods](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) as well. We will also be using some ES6 features, so read up [here](/additional-info/es6-syntax.md) if you do not know what they are. -::: - -In essence, `Map` allow for an association between unique keys and their values, but lack an iterative interface. -For example, how can you transform every value or filter the entries in a `Map` easily? -This is the point of the `Collection` class! - -## Array-like Methods - -Many of the methods on `Collection` are based on their namesake in `Array`. One of them is `find`: - -```js -// Assume we have an array of users and a collection of the same users. -array.find(u => u.discriminator === '1000'); -collection.find(u => u.discriminator === '1000'); -``` - -The interface of the callback function is very similar between the two. -For arrays, callbacks are usually passed the parameters `(value, index, array)`, where `value` is the value it iterated to, -`index` is the current index, and `array` is the array itself. For collections, you would have `(value, key, collection)`. -Here, `value` is the same, but `key` is the key of the value, and `collection` is the collection itself instead. - -Methods that follow this philosophy of staying close to the `Array` interface are as follows: - -- `find` -- `filter` - Note that this returns a `Collection` rather than an `Array`. -- `map` - Yet this returns an `Array` of values instead of a `Collection`! -- `every` -- `some` -- `reduce` -- `concat` -- `sort` - -## Converting to Array - -There are two ways you might want to convert a `Collection` into an `Array`. The first way is the `array` or `keyArray` methods. -They simply create an array from the items in the collection, but also caches it too: - -```js -// Not computed again the second time, it is cached! -collection.array(); -collection.array(); - -// Any change to the collection, however, invalidates the cache. -// This call to `array` must be recomputed. -collection.delete('81440962496172032'); -collection.array(); -``` - -This caching behavior is undesirable if you are planning to mutate the array, so instead, you can use `Array.from`: - -```js -// For values. -Array.from(collection.values()); - -// For keys. -Array.from(collection.keys()); - -// For [key, value] pairs. -Array.from(collection); -``` - -::: warning -Many people use `array` way too much! This leads to unneeded caching of data and confusing code. Before you use `array` or similar, ask yourself if whatever you are trying to do can't be done with the given `Map` or `Collection` methods or with a for-of loop. -::: - -## Extra Utilities - -Some methods are not from `Array` and are instead completely new to standard JavaScript. - -```js -// A random value. Be careful, this uses `array` so caching is done. -collection.random(); - -// The first value. -collection.first(); - -// The first 5 values. -collection.first(5); - -// Similar to `first`, but from the end. This uses `array`. -collection.last(); -collection.last(2); - -// Removes from the collection anything that meets a criteria. -// Sort of like `filter`, but in-place. -collection.sweep(user => user.username === 'Bob'); -``` - -A more complicated method is `partition`, which splits a collection into two, based on a certain criteria. -You can think of it as two `filter`s, but done at the same time: - -```js -// `bots` is a Collection of users where their `bot` property was true. -// `humans` is a Collection where the property was false instead! -const [bots, humans] = collection.partition(u => u.bot); - -// Both return true. -bots.every(b => b.bot); -humans.every(h => !h.bot); -``` diff --git a/Ajuda/guide-master/guide/additional-info/es6-syntax.md b/Ajuda/guide-master/guide/additional-info/es6-syntax.md deleted file mode 100644 index 6905aa0..0000000 --- a/Ajuda/guide-master/guide/additional-info/es6-syntax.md +++ /dev/null @@ -1,271 +0,0 @@ -# ES6 syntax examples - -If you've used JavaScript for only a (relatively) small amount of time or just aren't very experienced with it, you might not be aware of what ES6 is and its crazy beneficial features. Since this is a guide primarily for Discord bots, we'll be using some discord.js code as an example of what you might have, versus what you could do to benefit from ES6. - -Here's the startup code we'll be using: - - - -```js -const Discord = require('discord.js'); -const client = new Discord.Client(); -const config = require('./config.json'); - -client.once('ready', () => { - console.log('Ready!'); -}); - -const { prefix } = config; - -client.on('message', message => { - if (message.content === prefix + 'ping') { - message.channel.send('Pong.'); - } else if (message.content === prefix + 'beep') { - message.channel.send('Boop.'); - } else if (message.content === prefix + 'server') { - message.channel.send('Guild name: ' + message.guild.name + '\nTotal members: ' + message.guild.memberCount); - } else if (message.content === prefix + 'user-info') { - message.channel.send('Your username: ' + message.author.username + '\nYour ID: ' + message.author.id); - } -}); - -client.login(config.token); -``` - -If you haven't noticed, this piece of code is actually already using a bit of ES6 in here! The `const` keyword and arrow function syntax (`() => ...`) are a part of ES6, and are recommended to use whenever possible. - -As for the code above, there are a few places where things can be done better. Let's look at them. - -## Template literals - -If you check the code above, it's currently doing things like `prefix + 'name'` and `'Your username: ' + message.author.username`, which is perfectly valid. It is a bit hard to read, though, it's not too fun to constantly type out. Fortunately, there's a better alternative. - - - -```js -// ES5 version, as we currently have it -else if (message.content === prefix + 'server') { - message.channel.send('Guild name: ' + message.guild.name + '\nTotal members: ' + message.guild.memberCount); -} -else if (message.content === prefix + 'user-info') { - message.channel.send('Your username: ' + message.author.username + '\nYour ID: ' + message.author.id); -} -``` - - - -```js -// ES6 version, using template literals -else if (message.content.startsWith(`${prefix}server`)) { - message.channel.send(`Guild name: ${message.guild.name}\nTotal members: ${message.guild.memberCount}`); -} -else if (message.content.startsWith(`${prefix}user-info`)) { - message.channel.send(`Your username: ${message.author.username}\nYour ID: ${message.author.id}`); -} -``` - -Easier to read, easier to write! The best of both worlds. - -### Template literals vs string concatenation - -If you've used other programming languages, you might be familiar with the term "string interpolation". Template literals would be JavaScript's implementation of string interpolation. If you're familiar with the heredoc syntax, it's very much like that; it allows for string interpolation, as well as multiline strings. - -The example below won't go too much into detail about it, but if you're interested in reading more, you can [read about them on MDN](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Template_literals). - -```js -// variables/function used throughout the examples -const username = 'Sanctuary'; -const password = 'pleasedonthackme'; - -function letsPretendThisDoesSomething() { - return 'Yay for dummy data.'; -} -``` - - - -```js -// regular string concatenation -console.log('Your username is: **' + username + '**.'); -console.log('Your password is: **' + password + '**.'); - -console.log('1 + 1 = ' + (1 + 1)); - -console.log('And here\'s a function call: ' + letsPretendThisDoesSomething()); - -console.log( - 'Putting strings on new lines\n' - + 'can be a bit painful\n' - + 'with string concatenation. :(' -); -``` - -```js -// template literals -console.log(`Your password is: **${password}**.`); -console.log(`Your username is: **${username}**.`); - -console.log(`1 + 1 = ${1 + 1}`); - -console.log(`And here's a function call: ${letsPretendThisDoesSomething()}`); - -console.log(` - Putting strings on new lines - is a breeze - with template literals! :) -`); - -// NOTE: template literals will also render the indentation inside them -// there are ways around that, which we'll discuss in another section. -``` - -You can see how it makes things easier and more readable. In some cases, it can even make your code shorter! This one is something you'll definitely want to take advantage of as much as possible. - -## Arrow functions - -Arrow functions are shorthand for regular functions, with the addition that they use a lexical `this` context inside of their own. If you don't know what the `this` keyword is referring to, don't worry about it; you'll learn more about it as you advance. - -Here are some examples of ways you can benefit from arrow functions over regular functions: - - - -```js -// regular functions, full ES5 -client.once('ready', function() { - console.log('Ready!'); -}); - -client.on('typingStart', function(channel, user) { - console.log(user + ' started typing in ' + channel); -}); - -client.on('message', function(message) { - console.log(message.author + ' sent: ' + message.content); -}); - -var doubleAge = function(age) { - return 'Your age doubled is: ' + (age * 2); -}; - -// inside a message collector command -var filter = function(m) { - return m.content === 'I agree' && !m.author.bot; -}; - -var collector = message.createReactionCollector(filter, { time: 15000 }); -``` - -```js -// arrow functions, full ES6 -client.once('ready', () => console.log('Ready!')); - -client.on('typingStart', (channel, user) => console.log(`${user} started typing in ${channel}`)); - -client.on('message', message => console.log(`${message.author} sent: ${message.content}`)); - -const doubleAge = age => `Your age doubled is: ${age * 2}`; - -// inside a message collector command -const filter = m => m.content === 'I agree' && !m.author.bot; -const collector = message.createReactionCollector(filter, { time: 15000 }); -``` - -There are a few important things you should note here: - -* The parenthesis around function parameters are optional when you have only one parameter, but required otherwise. If you feel like this will confuse you at times, it may be a good idea to just always use parenthesis. -* You can cleanly put what you need on a single line without curly braces. -* Omitting curly braces will make arrow functions use **implicit return**, but only if you have a single-line expression. The `doubleAge` and `filter` variables are a good example of this. -* Unlike the `function someFunc() { ... }` declaration, arrow functions cannot be used to create functions with such syntax. You can create a variable and give it an anonymous arrow function as the value, though (as seen with the `doubleAge` and `filter` variables). - -We won't be covering the lexical `this` scope with arrow functions in here, but you can Google around if you're still curious. Again, if you aren't sure what `this` is or when you need it, reading about lexical `this` first may only confuse you. - -## Destructuring - -Destructuring is an easy way to extract items from an object or array. If you've never seen the syntax for it before, it can be a bit confusing, but it's actually very easy to understand once explained! - -### Object destructuring - -Here's a common example where object destructuring would come in handy: - - - -```js -const config = require('./config.json'); -const prefix = config.prefix; -const token = config.token; - -// Alternative version (not recommended) -const prefix = require('./config.json').prefix; -const token = require('./config.json').token; -``` - -This is a bit verbose and not the most fun to write out each time. Object destructuring simplifies this, making it easier to both read and write. Take a look: - -```js -const { prefix, token } = require('./config.json'); -``` - -Object destructuring takes those properties from the object and stores them in variables. If the property doesn't exist, it'll still create a variable, but with the value of `undefined`. So instead of using `config.token` in your `client.login()` method, you'd simply use `token`. And since destructuring creates a variable for us, you don't even need that `const prefix = config.prefix` line. Pretty cool! - -Additionally, you could do this for your commands. - -```js -client.on('message', message => { - const { content } = message; - - if (content === `${prefix}ping`) { - // ping command here... - } else if (content === `${prefix}beep`) { - // beep command here... - } - // other commands here... -}); -``` - -It is a bit less to write out, and also looks cleaner, but shouldn't be necessary if you follow along with the [command handler](/command-handling/) part of the guide. - -You can also rename variables when destructuring, if necessary. A good example of when you'd need to do so is when you're extracting a property with a name that's already being used, or conflicts with a reserved keyword. The syntax is as follows: - -```js -// `default` is a reserved keyword -const { 'default': defaultValue } = someObject; - -console.log(defaultValue); -// 'Some default value here' -``` - -### Array destructuring - -Array destructuring syntax is very similar to object destructuring, except that you use brackets instead of curly braces. In addition, since you're using it on an array, you destructure the items in the same order the array is. Without array destructuring, this is how you'd extract items from an array: - -```js -// assuming we're in a `profile` command and have an `args` variable -const name = args[0]; -const age = args[1]; -const location = args[2]; -``` - -Just like the first example with object destructuring, this is a bit verbose and not fun to write out. Array destructuring eases this pain. - -```js -const [name, age, location] = args; -``` - -A single line of code that makes things much cleaner! In some cases, you may not even need all items in the array (e.g. when using `string.match(regex)`). Array destructuring still allows you to operate in the same sense. - -```js -const [, username, id] = message.content.match(someRegex); -``` - -In this snippet, we use a comma without providing a name for the item in the array we don't need. You can also give it a dummy name if you prefer, of course; it's entirely preference at that point. - -## var, let, and const - -Since there are many, many articles out there that can explain this part more in depth, we'll only be giving you a TL;DR and an article link if you choose to read more about it. - -1. The `var` keyword is what was (and can still be) used in JS before `let` and `const` came to surface. There are actually many issues with `var`, though, such as it being function-scoped, hoisting related issues, and allowing redeclaration. -2. The `let` keyword is essentially the new `var`; it addresses many of the issues `var` has, but its biggest factor would be that it's block-scoped and disallows redeclaration (*not* reassignment). -3. The `const` keyword is for giving variables a constant value which may not be reassigned. `const`, like `let`, is also block-scoped. - -The general rule of thumb recommended by this guide is to use `const` wherever possible, `let` otherwise, and avoid using `var`. Here's a [helpful article](https://madhatted.com/2016/1/25/let-it-be) if you want to read more about this subject. - diff --git a/Ajuda/guide-master/guide/additional-info/notation.md b/Ajuda/guide-master/guide/additional-info/notation.md deleted file mode 100644 index fddc221..0000000 --- a/Ajuda/guide-master/guide/additional-info/notation.md +++ /dev/null @@ -1,58 +0,0 @@ -# Understanding notation - -Throughout out the discord.js docs and when asking for help on the official server, you will run into many different kinds of notations. To help you understand the texts that you read, we will be going over some common notations. - -::: tip -Always keep in mind that notation is not always rigorous. There will be typos, misunderstandings, or context that will cause notation to differ from the usual meanings. -::: - -## Classes - -Some common notations are used to refer to a class or the properties, methods, or events of a class. There are many variations on these notations, and they are very flexible depending on the person, so use your best judgement when reading them. - -The notation `` means an instance of the `Class` class. For example, a snippet like `.reply('hello')` is asking you to replace `` with some value that is an instance of `Message`, e.g. `msg.reply('hello')`. It could also just be a placeholder, e.g. `` would mean a placeholder for some ID. - -The notation `Class#foo` can refer to the `foo` property, method, or event of the `Class` class. Specifically which one the writer meant needs to be determined from context. For example: - -- `Message#author`, means that you should refer to the `author` property on a `Message`. -- `TextChannel#send`, means that you should refer to the `send` method on a `TextChannel`. -- `Client#message`, means that you should refer to the `message` event on a `Client`. - -::: tip -Remember that this notation is not valid JavaScript, it is a shorthand to refer to a certain piece of code. -::: - -Sometimes, the notation is extended, which can help you determine which one the writer meant. For example, `TextChannel#send(content, options)` is definitely a method of `TextChannel`, since it uses function notation. And, `Client#event:message` is an event, since it says that it is an event. - -The important thing to take away from this notation is that the `#` symbol signifies that the property, method, or event can only be accessed through an instance of the class. Unfortunately, this notation is often abused, e.g. `#send` (`` is already an instance so this makes no sense), or `Util#resolveColor` (`resolveColor` is a static method, this should be written `Util.resolveColor`), so always refer back to the docs if you are confused. - -An example of where this notation is used is in the documentation's search feature. - -![Docs search](~@/images/search.png) - -Notice the use of the `.` operator for the static method, `Role.comparePositions` and the `#` notation for the method, `Role#comparePositionsTo`. - -## Types - -In the discord.js docs, there are type signatures everywhere, such as in properties, parameters, or return values. If you do not come from a statically typed language, you may not know what certain notations mean. - -The symbol `*` means any type. For example, methods that return `*` means that they can return anything, and a parameter of type `*` can be anything. - -The symbol `?` means that the type is nullable. You can see it before or after the type (e.g. `?T` or `T?`). What this symbol means is that the value can be of the type `T` or it can be `null`. An example is the property `GuildMember#nickname` which has the type `?string` since a member may or may not have a nickname. - -The expression `T[]` means an array of `T`. You can sometimes see multiple brackets `[]`, meaning that the array is multi-dimensional, e.g. `string[][]`. - -The expression `...T` signifies a rest parameter of type `T`. This means that the function can take any amount of arguments, and all those arguments must be of the type `T`. - -The operator `|`, which can be read as "or", creates a union type, e.g. `A|B|C`. Simply, it means the value can be of any one of the types given. - -The angle brackets `<>` are used for generic types or parameterized types. This means a type that uses another type(s). The notation looks like `A` where `A` is the type and `B` is a type parameter. If this is hard to follow, it is enough to keep in mind that whenever you see `A` you can think an `A` that contains `B`. Examples: - -- `Array` means an array of strings. -- `Promise` means a `Promise` that contains a `User`. -- `Array>` would be an array of `Promise`s each containing a `User` or a `GuildMember`. -- `Collection` would be a `Collection`, containing key-value pairs where the keys are `Snowflake`s, and the values are `User`s. - -![TextChannel#send on the docs](~@/images/send.png) - -In this piece of the docs, you can see three type signatures, `StringResolvable`, `MessageOptions or MessageAdditions`, and `Promise<(Message|Array)>`. The meaning of the word "or" here is the same as `|`. diff --git a/Ajuda/guide-master/guide/additional-info/rest-api.md b/Ajuda/guide-master/guide/additional-info/rest-api.md deleted file mode 100644 index b748be9..0000000 --- a/Ajuda/guide-master/guide/additional-info/rest-api.md +++ /dev/null @@ -1,257 +0,0 @@ -# Using a REST API - -REST APIs are extremely popular on the web and allow you to freely grab a site's data if that site has an available API over an HTTP connection. - -If you've ever seen a music bot that accepts a YouTube query instead of just a video's URL, then you've seen a REST API in action. As a matter of fact, discord.js is made to use Discord's API. So, you've probably used an API yourself. - -## Making HTTP requests with Node - -In these examples we are going to be using [node-fetch](https://www.npmjs.com/package/node-fetch) which is a great library for making HTTP requests. - -To install node-fetch, run the following command: - -```bash -npm install node-fetch -``` - -## Skeleton code - -To start off, you're just going to be using this skeleton code: - - - - -```js -const { Client, RichEmbed } = require('discord.js'); - -const client = new Client(); -const prefix = '!'; - -client.once('ready', () => { - console.log('Ready!'); -}); - -client.on('message', async message => { - if (!message.content.startsWith(prefix) || message.author.bot) return; - - const args = message.content.slice(prefix.length).split(/ +/); - const command = args.shift().toLowerCase(); - - // ... -}); - -client.login('your-token-goes-here'); -``` - - - -```js -const { Client, MessageEmbed } = require('discord.js'); - -const client = new Client(); -const prefix = '!'; - -client.once('ready', () => { - console.log('Ready!'); -}); - -client.on('message', async message => { - if (!message.content.startsWith(prefix) || message.author.bot) return; - - const args = message.content.slice(prefix.length).split(/ +/); - const command = args.shift().toLowerCase(); - - // ... -}); - -client.login('your-token-goes-here'); -``` - - -::: tip -We're going to take advantage of [destructuring](/additional-info/es6-syntax.md#destructuring) in this tutorial to maintain readability. -::: - -## Using node-fetch - -node-fetch is a lightweight module that brings the [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) which is available in browsers to node. It is a promised based library. If you aren't already familiar with promises, you should read up on them [here](/additional-info/async-await.md). - -In this tutorial we'll be making a bot with 2 API-based commands. The first will be using [random.cat](https://aws.random.cat) and the other will use [Urban Dictionary](https://www.urbandictionary.com). - -To require node-fetch, you'd do: - -```js -const fetch = require('node-fetch'); -``` - -### Random Cat - -Random cat's API is available at https://aws.random.cat/meow and returns a [JSON](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON) response. To actually fetch data from the API, you're going to do the following: - -```js -fetch('https://aws.random.cat/meow').then(response => response.json()); -``` - -Now, of course it seems like this does nothing but what it's doing is launching a request to the random.cat server and random.cat is returning some JSON that contains a `file` property which is a string containing a link to a random cat. node-fetch returns a response object which we can change into JSON with `response.json()`. Next, let's implement this into a command. The code should look similar to this: - - - -```js -if (command === 'cat') { - const { file } = await fetch('https://aws.random.cat/meow').then(response => response.json()); - - message.channel.send(file); -} -``` - -So, here's what's happening in this code: - -1. You're sending a `GET` request to random.cat. -2. random.cat sees your request and gets a random file from their database. -3. random.cat then sends that file's URL as a JSON object that contains a link to the image. -4. node-fetch recieves the response and deserializes it with `reponse.json()`. -5. You then send the object's `file` property in Discord. - -::: warning -The response will only be parsed if the server's `Content-Type` header includes `application/json`. In some cases you may have to apply the `.text()` method instead of `.json()` and `JSON.parse()` it yourself. -::: - -### Urban Dictionary - -Urban Dictionary's API is available at https://api.urbandictionary.com/v0/define, accepts a `term` parameter, and also returns a JSON response. - -First, you're going to need to fetch data from the API. To do this, you'd do: - - - -```js -const querystring = require('querystring'); - -if (command === 'urban') { - if (!args.length) { - return message.channel.send('You need to supply a search term!'); - } - - const query = querystring.stringify({ term: args.join(' ') }); - - const { list } = await fetch(`https://api.urbandictionary.com/v0/define?${query}`).then(response => response.json()); -} -``` - -Here, we use Node's native [querystring module](https://nodejs.org/api/querystring.html) to create a [query string](https://en.wikipedia.org/wiki/Query_string) for the URL so that the Urban Dictionary server can parse it and know what to search for. - -If you were to do `!urban hello world`, then the URL would become https://api.urbandictionary.com/v0/define?term=hello%20world since the string gets encoded. - -You can get the respective properties from the returned JSON. If you were to view it in your browser, it usually looks like a bunch of mumbo jumbo. If it doesn't, great! If it does, then you should get a JSON formatter/viewer. If you're using Chrome, [JSON Formatter](https://chrome.google.com/webstore/detail/json-formatter/bcjindcccaagfpapjjmafapmmgkkhgoa) is one of the more popular extensions. If you're not using Chrome, search for "JSON formatter/viewer <your browser>" and get one. - -Now, if you look at the JSON, you can see that's a `list` property, which is an array of objects containing various definitions for the term (maximum 10). Something you always want to do when making API based commands is to handle there being no results. So, let's throw a random term in there (e.g. `njaksdcas`) and then look at the response. The `list` array should then be empty. Now you are ready to start writing! - -As explained above we want to check if the API returned any answers for our query like so: - -```js -if (!list.length) { - return message.channel.send(`No results found for **${args.join(' ')}**.`); -} -``` - -After making sure that there are results, you will use those results. For now, let's simply send back the definition and nothing more. It's as simple as: - -```js -message.channel.send(list[0].definition); -``` - -Here, you are simply getting the first object from the array of objects called `list` and grabbing its `definition` property. - -If you've followed the tutorial, you should have something like this: - -
- - !urban njaksdcas - - - User, No results for **njaksdcas** - - - !urban hello world - - - The easiest, and first program any newbie would write. Applies for any language. Also what you would see in the first chapter of most programming books. - -
- -Now, let's just make this an [embed](/popular-topics/miscellaneous-examples.md#sending-an-embed). - -We are also going to be defining a utility function at the top of our file so that our embed doesn't error when the field value is over 1024 characters. Here is a bit of code to do that: - -```js -const trim = (str, max) => ((str.length > max) ? `${str.slice(0, max - 3)}...` : str); -``` - -This is how we'll be structuring the embed: - - - -```js -const [answer] = list; - -const embed = new RichEmbed() - .setColor('#EFFF00') - .setTitle(answer.word) - .setURL(answer.permalink) - .addField('Definition', trim(answer.definition, 1024)) - .addField('Example', trim(answer.example, 1024)) - .addField('Rating', `${answer.thumbs_up} thumbs up. ${answer.thumbs_down} thumbs down.`); - -message.channel.send(embed); -``` - - - - -```js -const [answer] = list; - -const embed = new MessageEmbed() - .setColor('#EFFF00') - .setTitle(answer.word) - .setURL(answer.permalink) - .addField('Definition', trim(answer.definition, 1024)) - .addField('Example', trim(answer.example, 1024)) - .addField('Rating', `${answer.thumbs_up} thumbs up. ${answer.thumbs_down} thumbs down.`); - -message.channel.send(embed); -``` - - - -Now, if you do that same command again, you should get this: - -
- - !urban hello world - - - - - - The easiest, and first program any newbie would write. Applies for any language. Also what you would see in the first chapter of most programming books. - - - programming noob: Hey I just attended my first programming lesson earlier!
- .NET Veteran: Oh? What can you do?
- programming noob: I could make a dialog box pop up which says "Hello World!" !!!
- .NET Veteran: lmao.. hey guys! look.. check out this "hello world" programmer

- Console.WriteLine("Hello World") -
- - 122 thumbs up.
- 42 thumbs down. -
-
-
-
-
- -## Resulting code - - diff --git a/Ajuda/guide-master/guide/command-handling/README.md b/Ajuda/guide-master/guide/command-handling/README.md deleted file mode 100644 index b2bb9c7..0000000 --- a/Ajuda/guide-master/guide/command-handling/README.md +++ /dev/null @@ -1,129 +0,0 @@ -# Command handling - -As mentioned in a previous chapter, unless your bot project is a small one, it's not a very good idea to have a single file with a giant if/else if chain for commands. If you want to implement features into your bot and make your development process a lot less painful, you'll definitely want to use (or in this case, create) a command handler. Let's get started on that! - -Here's the base code we'll be using: - -```js -const Discord = require('discord.js'); -const { prefix, token } = require('./config.json'); - -const client = new Discord.Client(); - -client.once('ready', () => { - console.log('Ready!'); -}); - -client.on('message', message => { - if (!message.content.startsWith(prefix) || message.author.bot) return; - - const args = message.content.slice(prefix.length).split(/ +/); - const command = args.shift().toLowerCase(); - - if (command === 'ping') { - message.channel.send('Pong.'); - } else if (command === 'beep') { - message.channel.send('Boop.'); - } - // other commands... -}); - -client.login(token); -``` - -::: tip -We'll be moving over the commands created in [the previous page](/creating-your-bot/commands-with-user-input.md) as well, but for the sake of keeping the base code short, those commands have been omitted from the codeblock above. -::: - -## Individual command files - -Before anything, you may want to create a backup of your current bot file. If you've followed along so far, your entire folder structure should look something like this: - -![Current folder structure](~@/images/BmS09fY.png) - -In the same folder, create a new folder and name it `commands`. This is where you'll store all of your commands, of course. Head over to your `commands` folder, create a new file named `ping.js`, and copy & paste in the following code: - -```js -module.exports = { - name: 'ping', - description: 'Ping!', - execute(message, args) { - message.channel.send('Pong.'); - }, -}; -``` - -You can go ahead and do the same for the rest of your commands as well, putting their respective blocks of code inside the `execute()` function. If you've been using the same code as the guide thus far, you can copy & paste your commands into their own files now just fine without any issue, as long as you follow the format above. The `description` property is optional, but will be useful for the dynamic help command we'll be covering later. - -::: tip -`module.exports` is how you export data in Node.js so that you can `require()` it in other files. If you're unfamiliar with it and want to read more, you can take a look at [the documentation](https://nodejs.org/api/modules.html#modules_module_exports) for more info. -::: - -::: tip -If you need to access your client instance from inside one of your command files, you can access it via `message.client`. If you need to access things such as external files or modules, you should re-require them at the top of the file. -::: - -## Dynamically reading command files - -Back in your main file, make these two additions: - -```diff -+ const fs = require('fs'); -const Discord = require('discord.js'); -const { prefix, token } = require('./config.json'); - -const client = new Discord.Client(); -+ client.commands = new Discord.Collection(); -``` - -::: tip -`fs` is Node's native file system module. You can read the docs about it [here](https://nodejs.org/api/fs.html). -::: - -::: tip -If you aren't exactly sure what Collections are, they're a class that extend JS's native Map class and include more extensive, useful functionality. You can read about Maps [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map), and see all the available Collection methods [here](https://discord.js.org/#/docs/main/11.5.1/class/Collection)[here](https://discord.js.org/#/docs/collection/master/class/Collection). -::: - -This next step is how you'll dynamically retrieve all your newly created command files. Add this below your `client.commands` line: - -```js -const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js')); -``` - -The `fs.readdirSync()` method will return an array of all the file names in that directory, e.g. `['ping.js', 'beep.js']`. The filter is there to make sure any non-JS files are left out of the array. With that array, you can loop over it and dynamically set your commands to the Collection you made above. - -```js -for (const file of commandFiles) { - const command = require(`./commands/${file}`); - - // set a new item in the Collection - // with the key as the command name and the value as the exported module - client.commands.set(command.name, command); -} -``` - -By this point, your code should look something like this: - -```js -const fs = require('fs'); -const Discord = require('discord.js'); -const { prefix, token } = require('./config.json'); - -const client = new Discord.Client(); -client.commands = new Discord.Collection(); - -const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js')); - -for (const file of commandFiles) { - const command = require(`./commands/${file}`); - client.commands.set(command.name, command); -} - -// `client.on('...')` events and such below this point -``` - -As for setting up your files, that's it for now. In the next chapter, you'll learn how to make your commands execute dynamically! - -## Resulting code - - diff --git a/Ajuda/guide-master/guide/command-handling/adding-features.md b/Ajuda/guide-master/guide/command-handling/adding-features.md deleted file mode 100644 index bb012b4..0000000 --- a/Ajuda/guide-master/guide/command-handling/adding-features.md +++ /dev/null @@ -1,453 +0,0 @@ -# Additional features - -::: tip -This page is a follow-up and bases its code off of [the previous page](/command-handling/dynamic-commands.md). -::: - -The command handler you've been building so far doesn't do much aside from dynamically load and execute commands. Those two things alone are great, but definitely not the only things you want. Before diving into it, let's do some quick refactoring in preparation. - -```diff - const args = message.content.slice(prefix.length).split(/ +/); -- const command = args.shift().toLowerCase(); -+ const commandName = args.shift().toLowerCase(); - -- if (!client.commands.has(command)) return; -+ if (!client.commands.has(commandName)) return; -+ -+ const command = client.commands.get(commandName); - - try { -- client.commands.get(command).execute(message, args); -+ command.execute(message, args); - } -``` - -In this short (but necessary) refactor, you: - -1. Renamed the original `command` variable to `commandName` (to be descriptive about what it actually is, and so that you can name one of our variables as `command` later). -2. Changed the following `if` statement appropriately. -3. Made a variable named `command` which is the actual command object. -4. Changed the line inside the `try/catch` statement to use the `command` variable instead. - -Now you can start adding features! - -## Required arguments - -For this section, we'll be using the `args-info.js` command as an example. If you chose to keep it, it should look like this now: - -```js -module.exports = { - name: 'args-info', - description: 'Information about the arguments provided.', - execute(message, args) { - if (!args.length) { - return message.channel.send(`You didn't provide any arguments, ${message.author}!`); - } else if (args[0] === 'foo') { - return message.channel.send('bar'); - } - - message.channel.send(`Arguments: ${args}\nArguments length: ${args.length}`); - }, -}; -``` - -This is fine if you only have a few commands that require arguments. However, if you plan on making a lot of commands and don't want to copy & paste that `if` statement each time, it'd be a smart idea to change that check into something simpler. - -Here are the changes you'll be making: - -```diff -+ args: true, - execute(message, args) { -- if (!args.length) { -- return message.channel.send(`You didn't provide any arguments, ${message.author}!`); -- } -- else if (args[0] === 'foo') { -+ if (args[0] === 'foo') { - return message.channel.send('bar'); - } - - message.channel.send(`Arguments: ${args}\nArguments length: ${args.length}`); - }, -``` - -And then in your main file: - -```diff - const command = client.commands.get(commandName); -+ -+ if (command.args && !args.length) { -+ return message.channel.send(`You didn't provide any arguments, ${message.author}!`); -+ } -+ -``` - -Now whenever you set `args` to `true` in one of your command files, it'll perform this check and supply feedback if necessary. - -### Expected command usage - -It's good UX (user experience) to let the user know that a command requires arguments when they don't provide any (it also prevents your code from breaking). Letting them know what kind of arguments are expected is even better. - -Here's a simple implementation of such a thing. For this example, pretend you have a `!role` command, where the first argument is the user to give the role, and the second argument is the name of the role to give them. - -In your `role.js` file: - -```diff - args: true, -+ usage: ' ', - execute(message, args) { -``` - -In your main file: - -```diff - if (command.args && !args.length) { -- return message.channel.send(`You didn't provide any arguments, ${message.author}!`); -+ let reply = `You didn't provide any arguments, ${message.author}!`; -+ -+ if (command.usage) { -+ reply += `\nThe proper usage would be: \`${prefix}${command.name} ${command.usage}\``; -+ } -+ -+ return message.channel.send(reply); - } -``` - -Use an `if` statement to check if the `usage` property exists (and is truthy) first, so that you don't accidentally end up with `undefined` in the reply string (in the case that you forget to properly supply the property in your command file, or some similar incident). A simple precaution such as this can greatly improve the user experience. - -## Guild only commands - -Some commands are meant to be used only inside servers and won't work whatsoever in DMs. A prime example of this would be a kick command. You can add a property to the necessary commands to determine whether or not it should be only available outside of servers. - -In the kick command you created in an earlier chapter, make the following changes: - -```diff -module.exports = { - name: 'kick', - description: 'Kick a user from the server.', -+ guildOnly: true, -``` - -And in your main file, above the args checking line, add this in: - -```js -if (command.guildOnly && message.channel.type !== 'text') { - return message.reply('I can\'t execute that command inside DMs!'); -} -``` - -Now when you try to use the kick command inside a DM, you'll get the appropriate response which will also prevent your bot from throwing an error. - -
- - !kick - - - I can't execute that command inside DMs! - -
- -## Cooldowns - -Spam is something you generally want to avoid - especially if one of your commands requires calls to other APIs, or takes a bit of time to build/send. This is also a very common feature bot developers want to integrate into their projects, so let's get started on that! - -You'll be using the ping command to test this on. Add in the following bit of code: - -```diff -module.exports = { - name: 'ping', -+ cooldown: 5, - execute(message) { - message.channel.send('Pong.'); - }, -}; -``` - -This is the amount (in seconds) that the user will have to wait before being able to properly use that command again. You'll be using Collections again to store what you need. - -In your main file, add in this line (preferably somewhere above your `ready` event): - -```js -const cooldowns = new Discord.Collection(); -``` - -Again in your main file, directly above the `try/catch`, add in the following: - -```js -if (!cooldowns.has(command.name)) { - cooldowns.set(command.name, new Discord.Collection()); -} - -const now = Date.now(); -const timestamps = cooldowns.get(command.name); -const cooldownAmount = (command.cooldown || 3) * 1000; - -if (timestamps.has(message.author.id)) { - // ... -} -``` - -You check if the `cooldowns` Collection has the command set in it yet. If not, then add it in. Next, 3 variables are created: - -1. A variable with the current timestamp. -2. A variable that `.get()`s the Collection for the triggered command. -3. A variable that gets the necessary cooldown amount. If you don't supply it in your command file, it'll default to 3. Afterwards, convert it to the proper amount of milliseconds. - -After that, create a simple `if` statement to check if the `timestamps` Collection has the author ID in it yet. - -Continuing with your current setup, this is the complete `if` statement: - -```js -if (timestamps.has(message.author.id)) { - const expirationTime = timestamps.get(message.author.id) + cooldownAmount; - - if (now < expirationTime) { - const timeLeft = (expirationTime - now) / 1000; - return message.reply(`please wait ${timeLeft.toFixed(1)} more second(s) before reusing the \`${command.name}\` command.`); - } -} -``` - -Since the `timestamps` Collection has the author ID in it, you `.get()` it and then sum it up with the `cooldownAmount` variable, in order to get the correct expiration timestamp. You then check to see if it's actually expired or not. - -If the `expirationTime` has not passed, you return a message letting the user know how much time is left until they can use that command again. As you will see shortly, the author ID should be deleted from the `timestamps` Collection upon expiration, but you should take this extra precaution to avoid potential UX problems. - -Finally, if the `timestamps` Collection doesn't have the message author's ID (or if the author ID did not get deleted as planned), `.set()` the author ID with the current timestamp and create a `setTimeout()` to automatically delete it after the cooldown period has passed: - -```js -timestamps.set(message.author.id, now); -setTimeout(() => timestamps.delete(message.author.id), cooldownAmount); -``` - -## Command aliases - -It's a good idea to allow users to trigger your commands in more than one way; it gives them the freedom of choosing what to send and may even make some command names easier to remember. Luckily, setting up aliases for your commands is quite simple. - -For this bit of the guide, we'll be using the avatar command as a target. Around Discord, your profile picture is referred to as an "avatar" - however, not everyone calls it that. Some people prefer "icon" or "pfp" (profile picture). With that in mind, let's update the avatar command to allow all 3 of those triggers. - -Open your `avatar.js` file and add in the following line: - -```diff -module.exports = { - name: 'avatar', -+ aliases: ['icon', 'pfp'], -``` - -The `aliases` property should always contain an array of strings. In your main file, here are the changes you'll need to make: - -```diff -- if (!client.commands.has(commandName)) return; -- -- const command = client.commands.get(commandName); -+ const command = client.commands.get(commandName) -+ || client.commands.find(cmd => cmd.aliases && cmd.aliases.includes(commandName)); -+ -+ if (!command) return; -``` - -Making those two small changes, you get this: - -
- - !avatar User - - - User's avatar: - https://cdn.discordapp.com/avatars/328037144868290560/1cc0a3b14aec3499632225c708451d67.png?size=2084 -
- -
- - !icon User - - - User's avatar: - https://cdn.discordapp.com/avatars/328037144868290560/1cc0a3b14aec3499632225c708451d67.png?size=2084 -
- -
-
- -## A dynamic help command - -If you don't use a framework or command handler for your projects, you'll have a tough time setting up an always up-to-date help command. Luckily, that's not the case here. Start by creating a new command file inside your `commands` folder and populate it as you normally would. - -```js -module.exports = { - name: 'help', - description: 'List all of my commands or info about a specific command.', - aliases: ['commands'], - usage: '[command name]', - cooldown: 5, - execute(message, args) { - // ... - }, -}; -``` - -You're going to need your prefix variable a couple times inside this command, so make sure to require that at the very top of the file (outside of the `module.exports` bit). - -```js -const { prefix } = require('../config.json'); -``` - -Inside the `execute()` function, set up some variables and an if/else statement to determine whether it should display a list of all the command names or only information about a specific command. - -```js -const data = []; -const { commands } = message.client; - -if (!args.length) { - // ... -} - -// ... -``` - -You can use `.push()` on the `data` variable to append the info you want and then DM it to the message author once you're done. - -Inside the if statement, this is what you'll need: - -```js -data.push('Here\'s a list of all my commands:'); -data.push(commands.map(command => command.name).join(', ')); -data.push(`\nYou can send \`${prefix}help [command name]\` to get info on a specific command!`); - -return message.author.send(data, { split: true }) - .then(() => { - if (message.channel.type === 'dm') return; - message.reply('I\'ve sent you a DM with all my commands!'); - }) - .catch(error => { - console.error(`Could not send help DM to ${message.author.tag}.\n`, error); - message.reply('it seems like I can\'t DM you! Do you have DMs disabled?'); - }); -``` - -There's nothing really complex here; all you do is append some strings, `.map()` over the `commands` Collection, and add an additional string to let the user know how to trigger information about a specific command. - -Since help messages can get messy, you'll be DMing it to the message author instead of posting it in the requested channel. However, there is something very important you should consider: the possibility of not being able to DM the user, whether it be that they have DMs disabled on that server or overall, or they have the bot blocked. For that reason, you should `.catch()` it and let them know. - -::: tip -If you weren't already aware, `.send()` takes 2 parameters: the content to send, and the message options to pass in. You can read about the `MessageOptions` type [here](https://discord.js.org/#/docs/main/11.5.1/typedef/MessageOptions)[here](https://discord.js.org/#/docs/main/master/typedef/MessageOptions). Using `split: true` here will automatically split our help message into 2 or more messages in the case that it exceeds the 2,000 character limit. -::: - -::: tip -Because the `data` variable is an array, you can take advantage of discord.js' functionality where it will `.join()` any array sent with a `\n` character. If you prefer to not rely on that in the chance that it changes in the future, you can simply append `.join('\n')` to the end of that yourself. -::: - -Below the `if (!args.length)` statement is where you'll send the help message for the command they specified. - -```js -const name = args[0].toLowerCase(); -const command = commands.get(name) || commands.find(c => c.aliases && c.aliases.includes(name)); - -if (!command) { - return message.reply('that\'s not a valid command!'); -} - -data.push(`**Name:** ${command.name}`); - -if (command.aliases) data.push(`**Aliases:** ${command.aliases.join(', ')}`); -if (command.description) data.push(`**Description:** ${command.description}`); -if (command.usage) data.push(`**Usage:** ${prefix}${command.name} ${command.usage}`); - -data.push(`**Cooldown:** ${command.cooldown || 3} second(s)`); - -message.channel.send(data, { split: true }); -``` - -Once you get the command based off the name or alias they gave, you can start `.push()`ing what you need into the `data` variable. Not all commands will have descriptions, aliases, or usage strings, so you use an if statement for each of those to append them conditionally. After that, send back all the relevant information. - -At the end of it all, you should be getting this as a result: - -
- - !help - - - Here's a list of all my commands: - args-info, avatar, beep, help, kick, ping, prune, server, user-info
- You can send `!help [command name]` to get info on a specific command! -
- - !help avatar - - - **Name:** avatar
- **Aliases:** icon,pfp
- **Description:** Get the avatar URL of the tagged user(s), or your own avatar.
- **Cooldown:** 3 second(s) -
-
- -No more manually editing your help command! If you aren't completely satisfied with how it looks, you can always adjust it to your liking later. - -::: tip -If you want to add categories or other information to your commands you can simply add properties reflecting it to your `module.exports`. If you only want to show a subset of commands remember that `commands` is a Collection you can [filter](https://discord.js.org/#/docs/main/11.5.1/class/Collection?scrollTo=filter)[filter](https://discord.js.org/#/docs/collection/master/class/Collection?scrollTo=filter) to fit your specific needs! -::: - -## Reloading commands - -When writing your commands, you may find it tedious to restart your bot every time you want to test even the slightest change in your code. However, if you have a command handler, reloading commands can be done with a single bot command. - -Create a new command file and paste in the usual format: - -```js -module.exports = { - name: 'reload', - description: 'Reloads a command', - execute(message, args) { - // ... - }, -}; -``` - -In this command, you will be using a command name or alias as the only argument. First off, you need to check if the command you want to reload exists. This can be done in a similar fashion as getting a command in your main file. -Note that you can skip the first line if you use the [argument checker](/command-handling/adding-features.html#required-arguments) from above: - -```js -if (!args.length) return message.channel.send(`You didn't pass any command to reload, ${message.author}!`); -const commandName = args[0].toLowerCase(); -const command = message.client.commands.get(commandName) - || message.client.commands.find(cmd => cmd.aliases && cmd.aliases.includes(commandName)); - -if (!command) return message.channel.send(`There is no command with name or alias \`${commandName}\`, ${message.author}!`); -``` - -:::tip -A lot of library specific structures have `client` as a property. That means you don't have to pass the client reference as a parameter to commands to access for example `client.guilds` or `client.commands`, but can directly access the respective properties directly from the `message` object, as shown in the snippet above. -::: - -Now, in theory, all there is to do, is to delete the previous command from `client.commands` and require the file again. In practice though, you cannot do this that easily as `require()` caches the file. If you were to require it again, you would simply load the previously cached file without any of your changes. In order to remove the file from the cache, you need to add the following line to your code: - -```js -delete require.cache[require.resolve(`./${commandName}.js`)]; -``` - -After removing the command from the cache, all you have to do is require the file again and add the freshly loaded command to `client.commands`: - -```js -try { - const newCommand = require(`./${commandName}.js`); - message.client.commands.set(newCommand.name, newCommand); -} catch (error) { - console.log(error); - message.channel.send(`There was an error while reloading a command \`${commandName}\`:\n\`${error.message}\``); -} -``` - -The snippet above uses a `try/catch` block to load the command file and add it to `client.commands`. In case of an error it will log the full error to console and notify the user about it with the error's message component `error.message`. Note the you never actually delete the command from the commands collection, and instead just overwrite it. This prevents you from deleting a command, and ending up with no command at all after a failed `require()` call, as each use of the reload command checks that collection again. - -The last thing you might want to add is sending a message if the reload was successful: - -```js -message.channel.send(`Command \`${commandName}\` was reloaded!`); -``` - -## Conclusion - -At this point of the guide, you should now have a command handler with some very basic (but useful) features! If you see fit, you can expand upon the current structure to make something even better and easier for you to use in the future. - -## Resulting code - - diff --git a/Ajuda/guide-master/guide/command-handling/dynamic-commands.md b/Ajuda/guide-master/guide/command-handling/dynamic-commands.md deleted file mode 100644 index a841d18..0000000 --- a/Ajuda/guide-master/guide/command-handling/dynamic-commands.md +++ /dev/null @@ -1,72 +0,0 @@ -# Dynamic commands - -::: tip -This page is a follow-up and bases its code off of [the previous page](/command-handling/). -::: - -## How it works - -Now that you have a Collection of all our commands, you can use them easily! But before diving straight into it, it'd be a good idea to familiarize yourself with how you'll turn these basic if statements into something much more dynamic and robust. So let's continue with 1 more if statement example, and then we'll move onto the real stuff. - -As always, the red is what you'll remove and the green is what you'll replace it with. - -```diff -if (command === 'ping') { -- message.channel.send('Pong.'); -+ client.commands.get('ping').execute(message, args); -} -``` - -You `.get()` the ping command and call its `.execute()` method while passing in the `message` and `args` variables as the method arguments. Instead of putting your ping command code directly in the if statement, you can call it directly like that instead. Granted, this version is actually longer than what you had before for your ping command, but commands usually aren't that short. - -So, if you wanted to (assuming that you've copied & pasted all of your commands into their own files by now), this could be your entire message event: - -```js -client.on('message', message => { - if (!message.content.startsWith(prefix) || message.author.bot) return; - - const args = message.content.slice(prefix.length).split(/ +/); - const command = args.shift().toLowerCase(); - - if (command === 'ping') { - client.commands.get('ping').execute(message, args); - } else if (command === 'beep') { - client.commands.get('beep').execute(message, args); - } else if (command === 'server') { - client.commands.get('server').execute(message, args); - } - // do the same for the rest of the commands... -}); -``` - -That would work perfectly fine, but it isn't dynamic; you'd still have to add an if statement and the same old code each time you wanted to register a new command, which is less than ideal. - -## Dynamically executing commands - -At this point, you can take that entire if/else if chain and delete it; you won't need anything past the `const command = ...` line. Instead, you'll be replacing it with this: - -```js -if (!client.commands.has(command)) return; - -try { - client.commands.get(command).execute(message, args); -} catch (error) { - console.error(error); - message.reply('there was an error trying to execute that command!'); -} -``` - -If there isn't a command with that name, exit early. If there is, `.get()` the command and call its `.execute()` method while passing in your `message` and `args` variables as the method arguments. In case something goes wrong, log the error and report back to the member to let them know. - -... and that's it! Whenever you want to add a new command, you simply make a new file in your `commands` directory, name it what you want, and then do what you did for the other commands. - -In the next chapter, we'll be going through how to implement some basic features into your brand new command handler. Currently, it's hardly a command "handler" at this point; it's a command loader and executor, if you wish to see it that way. You'll learn how to implement some new features and the logic behind them, such as: - -* Command aliases -* Cooldowns -* Guild only commands -* A dynamic help message - -## Resulting code - - diff --git a/Ajuda/guide-master/guide/commando/README.md b/Ajuda/guide-master/guide/commando/README.md deleted file mode 100644 index c90519d..0000000 --- a/Ajuda/guide-master/guide/commando/README.md +++ /dev/null @@ -1,123 +0,0 @@ ---- -forceTheme: blue ---- - -# Getting started with Commando - -When you got your first bot up and running with Discord.js, you should've installed Discord.js using npm, Node.js' Package Manager. The same applies to Commando, which must be separately installed. You can do this in one of two ways: - -Stable (v11): `npm install discord.js-commando` -Master (v12): `npm install discordjs/Commando` - -::: warning -You need at least Node.js version 8.0.0 to use Commando. Master branch will also require you to install [Git](https://git-scm.com/downloads). -::: - -If you're using Discord.js master, you'll need Commando master, and vice versa for stable. - -## Creating your index.js file - -While it doesn't have to be called `index.js`, this file is the main file for your bot, which handles everything from registering new commands to logging in your client. - -The first thing you have to do is require Commando. Contrary to what you may think, you do **not** need to require Discord.js to use Commando. Commando handles all discord.js-related functions within itself, and the Commando client extends discord.js', so you'll rarely ever have to touch core discord.js! - -You'll also be requiring `path`. Don't worry, you don't have to install `path`; it comes bundled with Node. - -```js -const { CommandoClient } = require('discord.js-commando'); -const path = require('path'); -``` - -The next step is to create a new CommandoClient. There's also a few options you will need to set. - -```js -const client = new CommandoClient({ - commandPrefix: '?', - owner: '278305350804045834', - invite: 'https://discord.gg/bRCvFy9', -}); -``` - -In the `commandPrefix` parameter, you should insert the prefix you intend to use for your bot. As of writing, you can only have one, so choose wisely! However, note that mentioning your bot will **always** be allowed alongside the prefix you set here. In other words, this prefix and mentions are how your users will call your bot. **No, there is no way to disable mentions being a prefix!** - -After that is the `owner` parameter, which should contain the ID for the owner of the bot. It can be either a string of one ID, or an array of many. - -::: danger -The users you set here have complete control over the bot. They can use eval and other owner-only commands, ignore command throttling, and bypass all user permissions! Be sure to only give this to people you trust! -::: - -The final option, `invite`, is the **full** invite URL to your bot's support server. While not a required option, it's a good idea to have a support server on hand to handle questions and concerns your users may have about your bot if it is public. If not, it's safe to leave this option out. - -Next you're going to register the command groups, args types, and default commands. Then, you register the commands in a folder. You can name the folder whatever you want, but it's recommended to stick with `commands`, as it makes the most sense. - -```js -client.registry - .registerDefaultTypes() - .registerGroups([ - ['first', 'Your First Command Group'], - ['second', 'Your Second Command Group'], - ]) - .registerDefaultGroups() - .registerDefaultCommands() - .registerCommandsIn(path.join(__dirname, 'commands')); -``` - -Doing this you've also created your first command group! Make another folder called `first` in your `commands` folder so that you can put the commands for that group in there. The group will be displayed in the help command as `Your First Command Group`. You can use any name you want for either of these options, but do note that the key (`first`) **must be lowercase**! - -Adding more command groups is as simple as adding another option to the array and making another folder. - - - -```js -.registerGroups([ - ['first', 'Your First Command Group'], - ['second', 'Your Second Command Group'], - ['third', 'Your Third Command Group'], -]) -``` - -Should you want to disable a default command, such as if you wanted to make your own help command and replace the default one, you can pass that as an option in `registerDefaultCommands`. - - - -```js -.registerDefaultCommands({ - help: false, -}) -``` - -Next, you're going to need to create a ready event and an error event, as usual. - -```js -client.once('ready', () => { - console.log(`Logged in as ${client.user.tag}! (${client.user.id})`); - client.user.setActivity('with Commando'); -}); - -client.on('error', console.error); -``` - -This will send a message to your console when the bot is ready, and set the bot's playing status to "with Commando". You can set both to whatever you wish. - -Last but certainly not least, log the bot in. - -```js -client.login('your-token-goes-here'); -``` - -::: danger -You should use environment variables or a `config.json` for your token instead of passing it directly! -::: - -And there you have it! You've set up your `index.js` file! In the end your file structure should look like this, along with whatever `.gitignore` or `config.json` you may have: - -``` -/commands - /first -index.js -package.json -``` - -## Resulting code - - diff --git a/Ajuda/guide-master/guide/commando/args.md b/Ajuda/guide-master/guide/commando/args.md deleted file mode 100644 index 99dbd30..0000000 --- a/Ajuda/guide-master/guide/commando/args.md +++ /dev/null @@ -1,122 +0,0 @@ ---- -forceTheme: blue ---- - -# Using arguments in commands - -Sometimes when using commands you may want to get data from the user, and change the response accordingly. In this section, you'll create a command that pulls a string from the message and says it back to the user! - -## String arguments - -A `string` argument is simply the text after the command name and prefix. For example: `?say Hi there!` would cause the argument to be `Hi there!`. It's quite simple to create one. - -First, go into your `first` folder and make a new file called `say.js`. Once you have it, set up your command class and everything just like the one in the meow command. - -```js -const { Command } = require('discord.js-commando'); - -module.exports = class SayCommand extends Command { - constructor(client) { - super(client, { - name: 'say', - aliases: ['parrot', 'copy'], - group: 'first', - memberName: 'say', - description: 'Replies with the text you provide.', - }); - } - - run(message) { - // empty for now - } -}; -``` - -Place a `,` after the `description` field, because you're going to be adding an `args` field. - -The `args` field is simply an array of objects, each containing data for that argument. - - - -```js -super(client, { - name: 'say', - aliases: ['parrot', 'copy'], - group: 'first', - memberName: 'say', - description: 'Replies with the text you provide.', - args: [ - { - key: 'text', - prompt: 'What text would you like the bot to say?', - type: 'string', - }, - ], -}); -``` - -See? Simple. - -- `key` is the name of the argument. When you define it in your `run` method, this is what you'll be using. -- `prompt` is the text that displays if no argument is provided. If someone uses just `?say`, that prompt will come up asking for the text. -- `type` is the type the argument is a part of. This can be many things, including `string`, `integer`, `user`, `member`, etc. - -Adding more args is as simple as adding another object to the array, like so: - - - -```js -args: [ - { - key: 'text', - prompt: 'What text would you like the bot to say?', - type: 'string', - }, - { - key: 'otherThing', - prompt: 'What is this other useless thing?', - type: 'string', - }, -] -``` - -You can also set arguments to default to a specific value: - - - -```js -{ - key: 'otherThing', - prompt: 'What is this other useless thing?', - type: 'string', - default: 'dog', -}, -``` - -As you can see, they're very powerful things. - -Head on over to your `run` method and set the `text` arg to a variable. - - - -```js -run(message, { text }) { - // empty for now -} -``` - -Next, make the `run` method return the text back to the user. - - - -```js -run(message, { text }) { - return message.reply(text); -} -``` - -And there you have it, a say command using args! - -## Resulting code - - diff --git a/Ajuda/guide-master/guide/commando/client-values.md b/Ajuda/guide-master/guide/commando/client-values.md deleted file mode 100644 index 77e0143..0000000 --- a/Ajuda/guide-master/guide/commando/client-values.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -forceTheme: blue ---- - -# Using client values in commands - -This one is easy. If you want any value from the client object, normally, you'd do this: - -```js -client.guilds.size; -``` - -However, in Commando, you have to use `this` to get these values. - -```js -this.client.guilds.size; -``` - -It's really that simple! diff --git a/Ajuda/guide-master/guide/commando/first-command.md b/Ajuda/guide-master/guide/commando/first-command.md deleted file mode 100644 index a6abbf2..0000000 --- a/Ajuda/guide-master/guide/commando/first-command.md +++ /dev/null @@ -1,76 +0,0 @@ ---- -forceTheme: blue ---- - -# Your first command - -Now that you've set up a command group and registered your command folder, you're ready to make your first command file! First, you're going to need to create a new file for the command. Hop over to your `commands` folder, and then your `first` folder, and make a new file called `meow.js`. This is going to be a simple command that only replies with a message when used. We'll go into arguments and all that later. - -Once you have your file, it's time to get started! - -## Creating your command class - -Before you do anything, at the start of your file, you're going to need to require Commando again. Specifically its Command class. - -```js -const { Command } = require('discord.js-commando'); -``` - -Commands are classes exported with `module.exports`. Create the class and set `module.exports` to it. You will also set a bunch of options here, which will be explained below. - -```js -module.exports = class MeowCommand extends Command { - constructor(client) { - super(client, { - name: 'meow', - aliases: ['kitty-cat'], - group: 'first', - memberName: 'meow', - description: 'Replies with a meow, kitty cat.', - }); - } -}; -``` - -Don't let this scare you, it's actually very simple. - -- `name` is the name of the command. -- `aliases` are other ways the command can be called. You can have as many as you want! -- `group` is the command group the command is a part of. -- `memberName` is the name of the command within the group (this can be different from the name). -- `description` is the help text displayed when the help command is used. - -There are many more properties you can use, but those will be explained in their own sections. - -## Creating your run method - -The next thing you're going to need is a `run` method. This should go right below the constructor for the command. Inside, you'll return a message: - -```js -module.exports = class MeowCommand extends Command { - constructor(client) { - super(client, { - name: 'meow', - group: 'first', - memberName: 'meow', - description: 'Replies with a meow, kitty cat.', - }); - } - - run(message) { - return message.say('Meow!'); - } -}; -``` - -As you can see, the `run` method is simply the code you want the bot to run when the command is used. This can be anything you can do in normal Discord.js, as Commando is simply an extension. - -You may have also noticed that I used `message.say` instead of `message.channel.send`. This is Commando's magic. Instead of `send`, use `say`. For embeds, use `embed`. For code, use `code`. The only exception to this is files, which are still sent the same as normal. - -The reason for this is that Commando allows editing messages into commands, and using these methods allows Commando to save the messages for that use. It also checks if it can send a message to the current channel, so you get two things in one! - -Now fire up the bot as normal and use your command! It should automatically be `?meow` to use it. - -## Resulting code - - diff --git a/Ajuda/guide-master/guide/commando/guild-only.md b/Ajuda/guide-master/guide/commando/guild-only.md deleted file mode 100644 index f719a7e..0000000 --- a/Ajuda/guide-master/guide/commando/guild-only.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -forceTheme: blue ---- - -# Setting a command as guild-only - -Sometimes, you may need to require a command to only be usable in servers. Maybe it displays server information, maybe it gets a server emoji, no matter what it does, setting it as guild-only is very simple! - -First, go get the command you want to make guild-only. - -```js -const { Command } = require('discord.js-commando'); - -module.exports = class MeowCommand extends Command { - constructor(client) { - super(client, { - name: 'meow', - group: 'first', - memberName: 'meow', - description: 'Replies with a meow, kitty cat.', - }); - } - - run(message) { - return message.say('Meow!'); - } -}; -``` - -After `description`, add a `guildOnly` setting and set it to `true`. - - - -```js -super(client, { - name: 'meow', - group: 'first', - memberName: 'meow', - description: 'Replies with a meow, kitty cat.', - guildOnly: true, -}); -``` - -And that's all there is to it! Now when used in a DM, the bot will not permit the command to be used, and you will no longer receive errors! diff --git a/Ajuda/guide-master/guide/commando/permissions.md b/Ajuda/guide-master/guide/commando/permissions.md deleted file mode 100644 index 12727a5..0000000 --- a/Ajuda/guide-master/guide/commando/permissions.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -forceTheme: blue ---- - -# Handling permissions - -Sometimes you may need a user to have a certain permission to use a command, or maybe your bot needs a permission to make the command work. Well, Commando makes both of these very simple. - -## User and client permissions - -First, go grab the command you want to use permissions with. - -```js -const { Command } = require('discord.js-commando'); - -module.exports = class MeowCommand extends Command { - constructor(client) { - super(client, { - name: 'meow', - group: 'first', - memberName: 'meow', - description: 'Replies with a meow, kitty cat.', - }); - } - - run(message) { - return message.say('Meow!'); - } -}; -``` - -You can then use the `userPermissions` and `clientPermissions` options to check for certain permissions. If you wanted to restrict the `meow` command, requiring the user to have the ability to manage messages, and the client full administrator access, you'd do the following: - - - -```js -super(client, { - name: 'meow', - group: 'first', - memberName: 'meow', - description: 'Replies with a meow, kitty cat.', - clientPermissions: ['ADMINISTRATOR'], - userPermissions: ['MANAGE_MESSAGES'], -}); -``` - -All you need to do is set the properties to an array of permission flags. A list of those can be found [here](https://discord.js.org/#/docs/main/11.5.1/class/Permissions?scrollTo=s-FLAGS)[here](https://discord.js.org/#/docs/main/master/class/Permissions?scrollTo=s-FLAGS). - -## Owner-only commands - -Another thing you may want to do is set a command as owner-only. This will make a command only usable by the bot owner(s). Doing this is even simpler than the client/userPermissions, all you have to do is set the `ownerOnly` parameter to `true`. - - - -```js -super(client, { - name: 'meow', - group: 'first', - memberName: 'meow', - description: 'Replies with a meow, kitty cat.', - ownerOnly: true, -}); -``` diff --git a/Ajuda/guide-master/guide/commando/throttling.md b/Ajuda/guide-master/guide/commando/throttling.md deleted file mode 100644 index 4acc005..0000000 --- a/Ajuda/guide-master/guide/commando/throttling.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -forceTheme: blue ---- - -# Throttling - -Throttling is like rate-limiting; it allows the command to be used only in a certain period of time—a cooldown of sorts. This is useful for commands that rely on API calls, or commands that can be spammy, to allow them to not be overused by one user. - -First, grab a command file you want to use throttling with. - -```js -const { Command } = require('discord.js-commando'); - -module.exports = class MeowCommand extends Command { - constructor(client) { - super(client, { - name: 'meow', - group: 'first', - memberName: 'meow', - description: 'Replies with a meow, kitty cat.', - }); - } - - run(message) { - return message.say('Meow!'); - } -}; -``` - -Add the `throttling` property to the command. `throttling` is an object, which contains two things: - -- `usages` is the amount of times the command can be used in the given time period. -- `duration` is the amount of time the cooldown lasts, in seconds. - -Make it have 2 usages allowed in a 10 second period. - - - -```js -super(client, { - name: 'meow', - group: 'first', - memberName: 'meow', - description: 'Replies with a meow, kitty cat.', - throttling: { - usages: 2, - duration: 10, - }, -}); -``` - -The command now has a cooldown. If a user tries to use the `meow` command more than 2 times in 10 seconds, it will not allow them to use it until the 10 seconds have fully passed. While useless in a command like `meow`, this can be very useful for other, heavier commands you don't want abused. diff --git a/Ajuda/guide-master/guide/commando/unknown-command-response.md b/Ajuda/guide-master/guide/commando/unknown-command-response.md deleted file mode 100644 index 37004a1..0000000 --- a/Ajuda/guide-master/guide/commando/unknown-command-response.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -forceTheme: blue ---- - -# Removing the unknown command response - -Sometimes, you may want to remove the unknown command response from your bot. Be it Cleverbot or some other reason, sometimes you just want it gone, and it's quite simple to remove. - -Head over to your `index.js` file and find your `client` variable. You're going to be adding a new setting here. - -```js -const client = new CommandoClient({ - commandPrefix: '?', - owner: '278305350804045834', - invite: 'https://discord.gg/bRCvFy9', -}); -``` - -All you have to do to remove the unknown command response is set `unknownCommandResponse` to `false`. - -```js -const client = new CommandoClient({ - commandPrefix: '?', - owner: '278305350804045834', - invite: 'https://discord.gg/bRCvFy9', - unknownCommandResponse: false, -}); -``` - -That's all there is to it! diff --git a/Ajuda/guide-master/guide/commando/validators.md b/Ajuda/guide-master/guide/commando/validators.md deleted file mode 100644 index d0d31a0..0000000 --- a/Ajuda/guide-master/guide/commando/validators.md +++ /dev/null @@ -1,76 +0,0 @@ ---- -forceTheme: blue ---- - -# Using argument validators - -Sometimes you're going to want an argument to be a certain thing, e.g. check if it's a specific piece of text, or check the length. This can be accomplished with a `validate` function in your arg. - -## Basic validators - -What if you have a command where your first argument has to match a certain text? For example: if you wanted your `say` command to allow a maximum of 200 characters. It's very simple. - -First, pull the argument from your say command: - - - -```js -args: [ - { - key: 'text', - prompt: 'What text would you like the bot to say?', - type: 'string', - }, -], -``` - -Add a blank `validate` function to the arg. - - - -```js -args: [ - { - key: 'text', - prompt: 'What text would you like the bot to say?', - type: 'string', - validate: text => {}, - }, -], -``` - -Inside your `validate` function, check to see if the length is below 201 characters. - - - -```js -args: [ - { - key: 'text', - prompt: 'What text would you like the bot to say?', - type: 'string', - validate: text => text.length < 201, - }, -], -``` - -And now you've got a validator that checks if the length is 200! - -## oneOf - -Another property you can use to validate arguments is the `oneOf` option. This option forces the argument of be _one of_ the options provided in an array. If you wanted to make an argument that required a "yes" or "no" response, you'd do this: - - - -```js -args: [ - { - key: 'option', - prompt: 'Yes or No?', - type: 'string', - oneOf: ['yes', 'no'], - }, -], -``` - -That's it! This will automatically be case-insensitive, so you don't have to worry about that. diff --git a/Ajuda/guide-master/guide/creating-your-bot/README.md b/Ajuda/guide-master/guide/creating-your-bot/README.md deleted file mode 100644 index 870adbd..0000000 --- a/Ajuda/guide-master/guide/creating-your-bot/README.md +++ /dev/null @@ -1,100 +0,0 @@ -# Getting your bot up & running - -We're finally getting to the exciting parts! Since your bot is in your server now, the next step is to start coding and get it online! - -## Creating the bot file - -Open up your preferred code editor (whether it be [Visual Studio Code](https://code.visualstudio.com/), [Atom](https://atom.io/), [Sublime Text](https://www.sublimetext.com/), or any other editor of your choice) and create a new file. If you're brand new and aren't sure what to use, go with Visual Studio Code. - -It's suggested that you save the file as `index.js`, but you may name it whatever you wish, as long as it ends with `.js`. - -::: tip -You can quickly create a new file by using the `Ctrl + N` shortcut on your keyboard, and then using `Ctrl + S` to save the file. -::: - -## Logging in to Discord - -Once you've created a new file, do a quick check to see if you have everything setup properly. Copy & paste the following code into your file and save it. Don't worry if you don't understand it right away—it'll be explained a bit more in depth after this. - -```js -const Discord = require('discord.js'); -const client = new Discord.Client(); - -client.once('ready', () => { - console.log('Ready!'); -}); - -client.login('your-token-goes-here'); -``` - -Head back to your console window, type in `node your-file-name.js`, and press enter. If you see the `Ready!` message after a few seconds, you're good to go! If not, try going back a few steps and make sure you followed everything correctly. - -::: tip -Don't feel like typing the file name each time? Open up your `package.json` file, look for something like `"main": "index.js"`, and change `"index.js"` to whatever your file name is. After saving, you can simply run the `node .` shortcut in your console to start the process! -::: - -### Start-up code explained - -Here's the same code with comments, so it's easier to understand what's going on. -```js -// require the discord.js module -const Discord = require('discord.js'); - -// create a new Discord client -const client = new Discord.Client(); - -// when the client is ready, run this code -// this event will only trigger one time after logging in -client.once('ready', () => { - console.log('Ready!'); -}); - -// login to Discord with your app's token -client.login('your-token-goes-here'); -``` - -Although it's not a lot, it's good to know what each bit of your code does. But, as it currently is, this won't really do anything. You probably want to add some commands that run whenever someone sends a specific message, right? Let's get started on that, then! - -## Listening for messages - -First, make sure to close the process in your console. You can do so by pressing `Ctrl + C` inside the console. Go back to your code editor and add the following piece of code above the `client.login()` line. - -```js -client.on('message', message => { - console.log(message.content); -}); -``` - -Notice how the code uses `.on` rather than `.once` like in the ready event. This means that it can trigger multiple times. Save the file, go back to your console, and start the process up again. Whenever a message is sent inside a channel your bot has access to, the message's content will be logged to your console. Go ahead and test it out! - -::: tip -Inside your console, you can press the up arrow on your keyboard to bring up the latest commands you've run. Pressing `Up` and then `Enter` after closing the process is a nice, quick way to start it up again (as opposed to typing out the name each time). -::: - -## Replying to messages - -Logging to the console is great and all, but it doesn't really provide any feedback for the end user. Let's create a basic ping/pong command before you move on to making real commands. Remove the `console.log(message.content)` line from your code and replace it with the following: - -```js -if (message.content === '!ping') { - // send back "Pong." to the channel the message was sent in - message.channel.send('Pong.'); -} -``` - -Restart your bot and then send `!ping` to a channel your bot has access to. If all goes well, you should see something like this: - -
- - !ping - - - Pong. - -
- -You've successfully created your first Discord bot command! Exciting stuff, isn't it? This is only the beginning, so let's move on to making some more commands. - -## Resulting code - - diff --git a/Ajuda/guide-master/guide/creating-your-bot/adding-more-commands.md b/Ajuda/guide-master/guide/creating-your-bot/adding-more-commands.md deleted file mode 100644 index 83165c1..0000000 --- a/Ajuda/guide-master/guide/creating-your-bot/adding-more-commands.md +++ /dev/null @@ -1,173 +0,0 @@ -# Adding more commands - -::: tip -This page is a follow-up and bases its code off of [the previous page](/creating-your-bot/configuration-files.md). -::: - -A bot with nothing but a single command would be really boring, and you probably have a bunch of command ideas floating around in your head already, right? Let's begin, then. - -Here's what your message event should currently look like: - -```js -client.on('message', message => { - if (message.content === '!ping') { - message.channel.send('Pong.'); - } -}); -``` - -Before doing anything else, make a property to store the prefix you've configured. Instead of `const config = ...`, you can use destructuring to extract the prefix variable from the config file, and the token as well while you're at it. - -```diff -- const config = require('./config.json'); -+ const { prefix, token } = require('./config.json'); -``` - -```diff -- client.login(config.token); -+ client.login(token); -``` - -From now on, if you change the prefix or token in your config.json file, it'll change in your bot file as well. You'll be using the prefix variable a lot soon. - -::: tip -If you aren't familiar with some of this syntax, it may be because some of this is ES6 syntax. If it does confuse you, you should check out [this guide page](/additional-info/es6-syntax.md) before continuing. -::: - -## Simple command structure - -You already have an if statement that checks messages for a ping/pong command. Adding other command checks is just as easy; just chain an `else if` to your existing condition. - -```js -if (message.content === `${prefix}ping`) { - message.channel.send('Pong.'); -} else if (message.content === `${prefix}beep`) { - message.channel.send('Boop.'); -} -``` - -There are a few potential issues with this. For example, the ping command won't work if you send `!ping test`. It will only match `!ping` and nothing else. The same goes for the other command. If you want your commands to be more flexible, you can do the following: - -```js -if (message.content.startsWith(`${prefix}ping`)) { - message.channel.send('Pong.'); -} else if (message.content.startsWith(`${prefix}beep`)) { - message.channel.send('Boop.'); -} -``` - -Now the ping command will trigger whenever the message _starts with_ `!ping`! Sometimes this is what you want, but other times, you may want to match only exactly `!ping` - it varies from case to case, so be mindful of what you need when creating commands. - -::: warning -Be aware that this will also match `!pingpong`, `!pinguin`, and the like. This is not a huge problem for now, so don't worry; you'll see better ways to check for commands later. -::: - -## Displaying real data - -Let's start displaying some real data. For now, we'll be displaying basic member/server info. - -### Server info command - -Make another if statement to check for commands using `server` as the command name. You've already interacted with the Message object via `message.channel.send()`. You get the message object, access the channel it was sent in, and send a message to it. Just like how `message.channel` gives you the message's _channel_, `message.guild` gives you the message's _server_. - -::: tip -Servers are referred to as "guilds" in the Discord API and discord.js library. Whenever you see someone say "guild", they mean server. -::: - - - -```js -else if (message.content === `${prefix}server`) { - message.channel.send(`This server's name is: ${message.guild.name}`); -} -``` - -The code above would result in this: - -
- - !server - - - This server's name is: Discord Bot Tutorial - -
- -If you want to expand upon that command and add some more info, here's an example of what you can do: - - - -```js -else if (message.content === `${prefix}server`) { - message.channel.send(`Server name: ${message.guild.name}\nTotal members: ${message.guild.memberCount}`); -} -``` - -That would display both the server name _and_ the amount of members in it. - -
- - !server - - - Server name: Discord Bot Tutorial
- Total members: 3 -
-
- -You can, of course, modify this to your liking. You may want to also display the date the server was created, or the server's region. You would do those in the same manner - use `message.guild.createdAt` or `message.guild.region`, respectively. - -::: tip -Want a list of all the properties you can access and all the methods you can call on a server? Refer to [the discord.js documentation site](https://discord.js.org/#/docs/main/11.5.1/class/Guild)[the discord.js documentation site](https://discord.js.org/#/docs/main/master/class/Guild)! -::: - -### Member info command - -Set up another if statement and use the command name `user-info`. - - - -```js -else if (message.content === `${prefix}user-info`) { - message.channel.send(`Your username: ${message.author.username}\nYour ID: ${message.author.id}`); -} -``` - -This will display the message author's **username** (not nickname, if they have one set), as well as their user ID. - -
- - !user-info - - - Your username: User
- Your ID: 20833034795932416 -
-
- -::: tip -`message.author` refers to the user who sent the message. For a full list of all the properties and methods for the author object (a member of the `User` class), check out [the documentation page for it](https://discord.js.org/#/docs/main/11.5.1/class/User)[the documentation page for it](https://discord.js.org/#/docs/main/master/class/User). -::: - -And there you have it! As you can see, it's quite simple to add additional commands. - -## The problem with `if`/`else if` - -If you don't plan to make more than 7 or 8 commands for your bot, then using an if/else if chain is perfectly fine; it's presumably a small project at that point, so you shouldn't need to spend too much time on it. However, this isn't the case for most of us. - -You probably want your bot to be feature-rich and easy to configure and develop, right? Using a giant if/else if chain won't let you achieve that, and will only hinder your development process. After you read up on [creating arguments](/creating-your-bot/commands-with-user-input.md), we'll be diving right into something called a "command handler" - code that makes handling commands easier and much more efficient. - -Before continuing, here's a small list of reasons why you shouldn't use if/else if chains for anything that's not a small project: - -* Takes longer to find a piece of code you want. -* Easier to fall victim to [spaghetti code](https://en.wikipedia.org/wiki/Spaghetti_code). -* Difficult to maintain as it grows. -* Difficult to debug. -* Difficult to organize. -* General bad practice. - -In short, it's just not a good idea. But that's what this guide is for! Go ahead and read the next few pages to prevent these issues before they happen, learning new things along the way. - -## Resulting code - - diff --git a/Ajuda/guide-master/guide/creating-your-bot/commands-with-user-input.md b/Ajuda/guide-master/guide/creating-your-bot/commands-with-user-input.md deleted file mode 100644 index 1096658..0000000 --- a/Ajuda/guide-master/guide/creating-your-bot/commands-with-user-input.md +++ /dev/null @@ -1,402 +0,0 @@ -# Commands with user input (a.k.a. "arguments") - -::: tip -This page is a follow-up and bases its code off of [the previous page](/creating-your-bot/adding-more-commands.md). -::: - -Sometimes you'll want to determine the result of a command depending on user input. It's a very common case with a very simple solution. This section will teach you how to extract user input from a message and use it in your code. Generally, you'll hear other people refer to this as "arguments", and you should refer to them as that as well. - -## Basic arguments - -We'll actually be tackling 2 things at once here. Things will be explained along the way, so don't worry if you don't understand immediately. - -Go to your main bot file and find the `client.on('message', ...)` bit. Add the following block of code at the top of this event listeners callback function (the part we replaced with `...` here). - -```js -// client.on('message', message => { -if (!message.content.startsWith(prefix) || message.author.bot) return; - -const args = message.content.slice(prefix.length).split(' '); -const command = args.shift().toLowerCase(); -// the rest of your code -``` - -1. If the message either doesn't start with the prefix or was sent by a bot, exit early. -2. Create an `args` variable that slices off the prefix entirely and then splits it into an array by spaces. -3. Create a `command` variable by calling `args.shift()`, which will take the first element in array and return it while also removing it from the original array (so that you don't have the command name string inside the `args` array). - -Hopefully that's a bit clearer, if there was any confusion. Let's create a quick command to check out the result of our new addition: - - - -```js -// using the new `command` variable, this makes it easier to manage! -// you can switch your other commands to this format as well -else if (command === 'args-info') { - if (!args.length) { - return message.channel.send(`You didn't provide any arguments, ${message.author}!`); - } - - message.channel.send(`Command name: ${command}\nArguments: ${args}`); -} -``` - -If you try it out, you'll get something like this: - -
- - !args-info here are my arguments - - - Command name: args-info
- Arguments: here,are,my,arguments -
-
- -Looks good! Don't worry about the comma separation; that's the expected output when trying to send an array as a string. - -Now that you have an array of arguments, you can interact with it accordingly! Try out this small addition to the command: - - - -```js -else if (command === 'args-info') { - if (!args.length) { - return message.channel.send(`You didn't provide any arguments, ${message.author}!`); - } - else if (args[0] === 'foo') { - return message.channel.send('bar'); - } - - message.channel.send(`First argument: ${args[0]}`); -} -``` - -So if the first argument provided is equal to "foo", then send back "bar". Otherwise, just send back the argument the user provided. - -
- - !args-info foo - - - bar - - - !args-info not-foo - - - First argument: not-foo - -
- -### Caveats - -Currently, you're using `.split(' ')` to split the command arguments. However, there's actually a slight issue with this. As is, it'll split the string by each and every space. Well, what happens if someone accidentally (or even purposely) adds additional spaces? Here's what: - -
- - !args-info here are my arguments - - - Command name: args-info
- Arguments: here,,,,,are,,,,,my,,,,,,arguments
- Argument length: 20 -
-
- -If you've never done something like this before, this probably isn't what you'd expect, right? Thankfully, there's a simple solution for this issue. The red line is what to remove, and the green line is what to replace it with. - -```diff -- const args = message.content.slice(prefix.length).split(' '); -+ const args = message.content.slice(prefix.length).split(/ +/); -``` - -
- - !args-info here are my arguments - - - Command name: args-info
- Arguments: here,are,my,arguments
- Argument length: 4 -
-
- -Awesome! Nothing to worry in that regard about now. You're now using something called a "regular expression" (commonly referred to as "regex") to handle that small (but important) bug. - -## Common situations with arguments - -Here is where we'll be going over a few common situations where you'll want to make sure that an argument fits a certain criteria. - -## Mentions - -Using the example of a kick command, you most likely want it to allow the user to use the command and mention the person to kick, right? We won't actually be constructing the full kick command in this example, but here's how you can go about it: - - - -```js -else if (command === 'kick') { - // grab the "first" mentioned user from the message - // this will return a `User` object, just like `message.author` - const taggedUser = message.mentions.users.first(); - - message.channel.send(`You wanted to kick: ${taggedUser.username}`); -} -``` - -And as you can see, it works! - -
- - !kick Tutorial Bot - - - You wanted to kick: Tutorial Bot - -
- -But what happens if you try to use the command without mentioning anybody? If you try it yourself, you'll notice that the bot doesn't respond (due to it crashing), and you should see something like this in your console: - -``` -message.channel.send(`You wanted to kick: ${taggedUser.username}`); - ^ - -TypeError: Cannot read property 'username' of undefined -``` - -That's because you're trying to access the `username` property of a user you didn't mention! Since `message.mentions.users` is a Collection and you're trying to call `.first()` on an empty Collection, it'll return `undefined`. You can add a quick sanity check above the `const taggedUser = ...` line to prevent this from happening. - -```js -if (!message.mentions.users.size) { - return message.reply('you need to tag a user in order to kick them!'); -} -``` - -::: tip -If you're wondering what `message.reply()` does, it's just an alternative for `message.channel.send()` which also prepends a mention of the person who sent the message, unless used in a DM. It can be very useful for providing feedback! -::: - -Since `message.mentions.users` is a Collection, it has a `.size` property. If no users are mentioned, it'll return 0 (which is a `falsy` value), meaning you can do `if (!value)` to check if it's falsy. - -If you try again, it should work as expected. - -
- - !kick - - - User, you need to tag a user to kick them! - - - !kick Tutorial Bot - - - You wanted to kick: Tutorial Bot - -
- -### Working with multiple mentions - -Let's say you have some sort of `!avatar` command, where it'll display the avatar of all the mentioned users, or your own avatar if no users were mentioned. Focus on that 2nd part for now - how would you go about displaying your own avatar if no users were mentioned? Taking the snippet for the code you just used, you can do it just like this: - - - - - -```js -else if (command === 'avatar') { - if (!message.mentions.users.size) { - return message.channel.send(`Your avatar: <${message.author.displayAvatarURL}>`); - } - - // ... -} -``` - - - - - - -```js -else if (command === 'avatar') { - if (!message.mentions.users.size) { - return message.channel.send(`Your avatar: <${message.author.displayAvatarURL()}>`); - } - - // ... -} -``` - - - -That part is simple; just recycle the if statement you used in the section above and displaying the link to your avatar. - -
- - !avatar - - - Your avatar: - https://cdn.discordapp.com/avatars/459757892778590229/72153038872deb9b81a2444a0edcf041.png?size=2084 - -
- -The next part is where it takes a turn - displaying the avatars of all the mentioned users. But it's simpler than you may think! `message.mentions.users` returns a Collection (as previously mentioned), which you can loop over in a number of different ways. You'll be using `.map()` to loop here, since it allows you to easily collect and store data in a variable in order to send 1 final message in the end, as opposed to multiple. - - - - - -```js -else if (command === 'avatar') { - if (!message.mentions.users.size) { - return message.channel.send(`Your avatar: <${message.author.displayAvatarURL}>`); - } - - const avatarList = message.mentions.users.map(user => { - return `${user.username}'s avatar: <${user.displayAvatarURL}>`; - }); - - // send the entire array of strings as a message - // by default, discord.js will `.join()` the array with `\n` - message.channel.send(avatarList); -} -``` - - - - - - -```js -else if (command === 'avatar') { - if (!message.mentions.users.size) { - return message.channel.send(`Your avatar: <${message.author.displayAvatarURL()}>`); - } - - const avatarList = message.mentions.users.map(user => { - return `${user.username}'s avatar: <${user.displayAvatarURL()}>`; - }); - - // send the entire array of strings as a message - // by default, discord.js will `.join()` the array with `\n` - message.channel.send(avatarList); -} -``` - - - -And ta-da! You now have a list of avatar links of all the users you tagged. - -
- - !avatar User Tutorialbot - - - User's avatar: - https://cdn.discordapp.com/avatars/459757892778590229/72153038872deb9b81a2444a0edcf041.png?size=2084
- Tutorial Bot's avatar: - https://cdn.discordapp.com/avatars/459757708720209940/d48f3d90d923e9531c02c6bb9850339f.png?size=2084 -
-
- -It does take up a lot of screen, but this is just an example command anyway. - -::: tip -If you're looking for a more advanced way to handle mentions as arguments you can check out [this guide](/miscellaneous/parsing-mention-arguments.md). -::: - -## Number ranges - -Sometimes you'll want users to give you input that ranges from X to Y, but nothing outside of that. Additionally, you want to make sure that they do give you an actual number and not random characters. A good example of this would be a `!prune` command, where it deletes X messages in the channel, depending on what the user inputs. - -The first step would be to check if the input they gave is an actual number. - - - -```js -else if (command === 'prune') { - const amount = parseInt(args[0]); - - if (isNaN(amount)) { - return message.reply('that doesn\'t seem to be a valid number.'); - } - - // ... -} -``` - -And if you test it, it should work as expected. - -
- - !prune some-string - - - User, that doesn't seem to be a valid number. - -
- -So what you need to do next is check if the first argument is between X and Y. Following the idea of a prune command, you'll most likely want to use the `.bulkDelete()` method, which allows you to delete multiple messages in one fell swoop. - -With that being said, that method does have its limits: you can only delete a minimum of 2 and a maximum of 100 messages (at a time). Fortunately, there are a few ways to deal with that. One of those ways would be to just check the value of the `amount` variable, like so: - -```js -if (isNaN(amount)) { - return message.reply('that doesn\'t seem to be a valid number.'); -} else if (amount < 2 || amount > 100) { - return message.reply('you need to input a number between 2 and 100.'); -} - -// ... -``` - -Now all that's left is to delete the messages! It's a simple single line of code: - -```js -message.channel.bulkDelete(amount); -``` - -And you've got a working prune command! Create a test channel, send a few random messages, and test it out. - -### Caveats - -You should note that there are actually a few caveats with the `.bulkDelete()` method. The first would be the trying to delete messages older than 2 weeks, which would normally error. Here's an easy fix for that: - -```js -message.channel.bulkDelete(amount, true); -``` - -The second parameter in the `.bulkDelete()` method will filter out messages older than 2 weeks if you give it a truthy value. So if there are 50 messages and 25 of them are older than 2 weeks, it'll only delete the first 25 without throwing an error. However, if all the messages you're trying to delete are older than 2 weeks, then it will still throw an error. Knowing this, you should catch that error by chaining a `.catch()`. - -```js -message.channel.bulkDelete(amount, true).catch(err => { - console.error(err); - message.channel.send('there was an error trying to prune messages in this channel!'); -}); -``` - -::: tip -If you aren't familiar with the `.catch()` method, it's used to catch errors on Promises. Unsure what Promises are? Google around for more info! -::: - -The other caveat with this is that the `!prune {number}` message you sent will also count towards the amount deleted. What this means is that if you send `!prune 2`, it'll delete that message and only one other. There are a couple ways around this, but we'll be taking the easiest route for the sake of the tutorial. Here are the edits to make to your current code: - -```diff -- const amount = parseInt(args[0]); -+ const amount = parseInt(args[0]) + 1; -``` - -```diff -- else if (amount < 2 || amount > 100) { -- return message.reply('you need to input a number between 2 and 100.'); -- } -+ else if (amount <= 1 || amount > 100) { -+ return message.reply('you need to input a number between 1 and 99.'); -+ } -``` - -## Resulting code - - diff --git a/Ajuda/guide-master/guide/creating-your-bot/configuration-files.md b/Ajuda/guide-master/guide/creating-your-bot/configuration-files.md deleted file mode 100644 index ad88b8a..0000000 --- a/Ajuda/guide-master/guide/creating-your-bot/configuration-files.md +++ /dev/null @@ -1,56 +0,0 @@ -# Configuration files - -::: tip -This page is a follow-up and bases its code off of [the previous page](/creating-your-bot/). -::: - -As you get deeper into development, you may need to interact with sensitive data or data that gets used in multiple locations, such as: - -* Database passwords -* API keys -* Command prefix(es) -* A list of bot owner IDs - -Having that kind of data hard-coded in each of your files can be a bit bothersome and is less than ideal, to say the least. This is where configuration files come in - they're great for storing static data that can be easily updated in a single place. - -## Implementing your config file - -Go to your code editor and make a new file. Add in the code below and save it as `config.json`, in the same directory as your main bot file. - -```json -{ - "prefix": "!", - "token": "your-token-goes-here" -} -``` - -Go back to your main bot file, locate the `const client = new Discord.Client()` line, and add this above it: - -```js -const config = require('./config.json'); -``` - -Next, copy your token from the `client.login('your-token-goes-here')` line and paste into the `config.json` file. Make sure to keep it between the double quotes. - -Now you can simply do `client.login(config.token)` to login! If you want to use a different prefix than `!`, you can change that as well. - -## Storing additional data - -As previously mentioned, you'll probably want to store more than just your token and prefix at one point or another. If you want to store more data, just add another key/value pair to the list! - -```json -{ - "prefix": "!", - "token": "your-token-goes-here", - "meaning_of_life": 42, - "passwords_array": ["please", "dont", "hack", "me"], - "secret_passcodes": { - "bank": 1234, - "home": 4321 - } -} -``` - -## Resulting code - - diff --git a/Ajuda/guide-master/guide/images/18e2dwi.png b/Ajuda/guide-master/guide/images/18e2dwi.png deleted file mode 100644 index 368684c..0000000 Binary files a/Ajuda/guide-master/guide/images/18e2dwi.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/1IWSJ1C.png b/Ajuda/guide-master/guide/images/1IWSJ1C.png deleted file mode 100644 index 845a78e..0000000 Binary files a/Ajuda/guide-master/guide/images/1IWSJ1C.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/1ch98sm.png b/Ajuda/guide-master/guide/images/1ch98sm.png deleted file mode 100644 index de71456..0000000 Binary files a/Ajuda/guide-master/guide/images/1ch98sm.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/2vsIPEP.png b/Ajuda/guide-master/guide/images/2vsIPEP.png deleted file mode 100644 index 26f093c..0000000 Binary files a/Ajuda/guide-master/guide/images/2vsIPEP.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/3rLGb1s.png b/Ajuda/guide-master/guide/images/3rLGb1s.png deleted file mode 100644 index f1bcda8..0000000 Binary files a/Ajuda/guide-master/guide/images/3rLGb1s.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/49jali8.png b/Ajuda/guide-master/guide/images/49jali8.png deleted file mode 100644 index 1750ff9..0000000 Binary files a/Ajuda/guide-master/guide/images/49jali8.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/6qTlDW0.png b/Ajuda/guide-master/guide/images/6qTlDW0.png deleted file mode 100644 index a7ec866..0000000 Binary files a/Ajuda/guide-master/guide/images/6qTlDW0.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/8CQvVRV.png b/Ajuda/guide-master/guide/images/8CQvVRV.png deleted file mode 100644 index ce78fcf..0000000 Binary files a/Ajuda/guide-master/guide/images/8CQvVRV.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/9JfHooY.png b/Ajuda/guide-master/guide/images/9JfHooY.png deleted file mode 100644 index 0c6fa65..0000000 Binary files a/Ajuda/guide-master/guide/images/9JfHooY.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/9fejia2.png b/Ajuda/guide-master/guide/images/9fejia2.png deleted file mode 100644 index a24f454..0000000 Binary files a/Ajuda/guide-master/guide/images/9fejia2.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/A8l70bj.png b/Ajuda/guide-master/guide/images/A8l70bj.png deleted file mode 100644 index 2a05eac..0000000 Binary files a/Ajuda/guide-master/guide/images/A8l70bj.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/BAUsjyg.png b/Ajuda/guide-master/guide/images/BAUsjyg.png deleted file mode 100644 index 85d2c30..0000000 Binary files a/Ajuda/guide-master/guide/images/BAUsjyg.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/BbcuyJ6.png b/Ajuda/guide-master/guide/images/BbcuyJ6.png deleted file mode 100644 index 50b1a28..0000000 Binary files a/Ajuda/guide-master/guide/images/BbcuyJ6.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/BmS09fY.png b/Ajuda/guide-master/guide/images/BmS09fY.png deleted file mode 100644 index e2179e7..0000000 Binary files a/Ajuda/guide-master/guide/images/BmS09fY.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/DDzEgdZ.png b/Ajuda/guide-master/guide/images/DDzEgdZ.png deleted file mode 100644 index 45dbfd7..0000000 Binary files a/Ajuda/guide-master/guide/images/DDzEgdZ.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/DFfdFw4.png b/Ajuda/guide-master/guide/images/DFfdFw4.png deleted file mode 100644 index 9e0be8f..0000000 Binary files a/Ajuda/guide-master/guide/images/DFfdFw4.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/DgDVtcv.png b/Ajuda/guide-master/guide/images/DgDVtcv.png deleted file mode 100644 index bd00c9d..0000000 Binary files a/Ajuda/guide-master/guide/images/DgDVtcv.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/E1CZqFT.png b/Ajuda/guide-master/guide/images/E1CZqFT.png deleted file mode 100644 index a58a4c9..0000000 Binary files a/Ajuda/guide-master/guide/images/E1CZqFT.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/I2ruNRf.png b/Ajuda/guide-master/guide/images/I2ruNRf.png deleted file mode 100644 index 98c55eb..0000000 Binary files a/Ajuda/guide-master/guide/images/I2ruNRf.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/Ja4Ywf4.png b/Ajuda/guide-master/guide/images/Ja4Ywf4.png deleted file mode 100644 index 9771715..0000000 Binary files a/Ajuda/guide-master/guide/images/Ja4Ywf4.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/NKw7P2q.png b/Ajuda/guide-master/guide/images/NKw7P2q.png deleted file mode 100644 index 2ccb69a..0000000 Binary files a/Ajuda/guide-master/guide/images/NKw7P2q.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/NUvOWqG.png b/Ajuda/guide-master/guide/images/NUvOWqG.png deleted file mode 100644 index 05f202a..0000000 Binary files a/Ajuda/guide-master/guide/images/NUvOWqG.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/RMv88.png b/Ajuda/guide-master/guide/images/RMv88.png deleted file mode 100644 index 591cd41..0000000 Binary files a/Ajuda/guide-master/guide/images/RMv88.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/UCndZMo.png b/Ajuda/guide-master/guide/images/UCndZMo.png deleted file mode 100644 index b494f45..0000000 Binary files a/Ajuda/guide-master/guide/images/UCndZMo.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/branding/banner-alt-transparent.png b/Ajuda/guide-master/guide/images/branding/banner-alt-transparent.png deleted file mode 100644 index f701860..0000000 Binary files a/Ajuda/guide-master/guide/images/branding/banner-alt-transparent.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/branding/banner-large.png b/Ajuda/guide-master/guide/images/branding/banner-large.png deleted file mode 100644 index cca421f..0000000 Binary files a/Ajuda/guide-master/guide/images/branding/banner-large.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/branding/banner-small.png b/Ajuda/guide-master/guide/images/branding/banner-small.png deleted file mode 100644 index 700f41c..0000000 Binary files a/Ajuda/guide-master/guide/images/branding/banner-small.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/branding/banner-transparent.png b/Ajuda/guide-master/guide/images/branding/banner-transparent.png deleted file mode 100644 index 0243476..0000000 Binary files a/Ajuda/guide-master/guide/images/branding/banner-transparent.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/branding/banner.png b/Ajuda/guide-master/guide/images/branding/banner.png deleted file mode 100644 index dd2cd92..0000000 Binary files a/Ajuda/guide-master/guide/images/branding/banner.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/branding/book-large.png b/Ajuda/guide-master/guide/images/branding/book-large.png deleted file mode 100644 index 177d5fb..0000000 Binary files a/Ajuda/guide-master/guide/images/branding/book-large.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/branding/book-small.png b/Ajuda/guide-master/guide/images/branding/book-small.png deleted file mode 100644 index 123bd61..0000000 Binary files a/Ajuda/guide-master/guide/images/branding/book-small.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/branding/book.png b/Ajuda/guide-master/guide/images/branding/book.png deleted file mode 100644 index 3be4309..0000000 Binary files a/Ajuda/guide-master/guide/images/branding/book.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/branding/logo-alt-transparent.png b/Ajuda/guide-master/guide/images/branding/logo-alt-transparent.png deleted file mode 100644 index a27fdf2..0000000 Binary files a/Ajuda/guide-master/guide/images/branding/logo-alt-transparent.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/branding/logo-large.png b/Ajuda/guide-master/guide/images/branding/logo-large.png deleted file mode 100644 index b14ccb6..0000000 Binary files a/Ajuda/guide-master/guide/images/branding/logo-large.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/branding/logo-simple.png b/Ajuda/guide-master/guide/images/branding/logo-simple.png deleted file mode 100644 index 4ca90e3..0000000 Binary files a/Ajuda/guide-master/guide/images/branding/logo-simple.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/branding/logo-small.png b/Ajuda/guide-master/guide/images/branding/logo-small.png deleted file mode 100644 index c07f381..0000000 Binary files a/Ajuda/guide-master/guide/images/branding/logo-small.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/branding/logo-transparent.png b/Ajuda/guide-master/guide/images/branding/logo-transparent.png deleted file mode 100644 index ad22a3b..0000000 Binary files a/Ajuda/guide-master/guide/images/branding/logo-transparent.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/branding/logo.png b/Ajuda/guide-master/guide/images/branding/logo.png deleted file mode 100644 index ab75880..0000000 Binary files a/Ajuda/guide-master/guide/images/branding/logo.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/canvas.jpg b/Ajuda/guide-master/guide/images/canvas.jpg deleted file mode 100644 index 9634bc0..0000000 Binary files a/Ajuda/guide-master/guide/images/canvas.jpg and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/chalk-red.png b/Ajuda/guide-master/guide/images/chalk-red.png deleted file mode 100644 index 390876a..0000000 Binary files a/Ajuda/guide-master/guide/images/chalk-red.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/chalk-ugly.png b/Ajuda/guide-master/guide/images/chalk-ugly.png deleted file mode 100644 index 39bb8a2..0000000 Binary files a/Ajuda/guide-master/guide/images/chalk-ugly.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/create-app.png b/Ajuda/guide-master/guide/images/create-app.png deleted file mode 100644 index b00a4ac..0000000 Binary files a/Ajuda/guide-master/guide/images/create-app.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/create-bot.png b/Ajuda/guide-master/guide/images/create-bot.png deleted file mode 100644 index 97ff9fb..0000000 Binary files a/Ajuda/guide-master/guide/images/create-bot.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/created-bot.png b/Ajuda/guide-master/guide/images/created-bot.png deleted file mode 100644 index c7fe08a..0000000 Binary files a/Ajuda/guide-master/guide/images/created-bot.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/currency_er_diagram.svg b/Ajuda/guide-master/guide/images/currency_er_diagram.svg deleted file mode 100644 index 13b0f3a..0000000 --- a/Ajuda/guide-master/guide/images/currency_er_diagram.svg +++ /dev/null @@ -1,2 +0,0 @@ - -Usersuser_idPKbalanceCurrencyShopidPKnamecostUserItemsuser_idFKitem_idFKamount diff --git a/Ajuda/guide-master/guide/images/discord-avatar-djs.png b/Ajuda/guide-master/guide/images/discord-avatar-djs.png deleted file mode 100644 index 7f71f70..0000000 Binary files a/Ajuda/guide-master/guide/images/discord-avatar-djs.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/jnE3tVM.png b/Ajuda/guide-master/guide/images/jnE3tVM.png deleted file mode 100644 index 0e1b602..0000000 Binary files a/Ajuda/guide-master/guide/images/jnE3tVM.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/ooaOAeu.png b/Ajuda/guide-master/guide/images/ooaOAeu.png deleted file mode 100644 index 149cec8..0000000 Binary files a/Ajuda/guide-master/guide/images/ooaOAeu.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/qEIaiam.png b/Ajuda/guide-master/guide/images/qEIaiam.png deleted file mode 100644 index fd02008..0000000 Binary files a/Ajuda/guide-master/guide/images/qEIaiam.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/qSCjlEB.png b/Ajuda/guide-master/guide/images/qSCjlEB.png deleted file mode 100644 index 2b2020c..0000000 Binary files a/Ajuda/guide-master/guide/images/qSCjlEB.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/r6CiT3M.png b/Ajuda/guide-master/guide/images/r6CiT3M.png deleted file mode 100644 index 20cf841..0000000 Binary files a/Ajuda/guide-master/guide/images/r6CiT3M.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/search.png b/Ajuda/guide-master/guide/images/search.png deleted file mode 100644 index 2b1f733..0000000 Binary files a/Ajuda/guide-master/guide/images/search.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/send.png b/Ajuda/guide-master/guide/images/send.png deleted file mode 100644 index 387e781..0000000 Binary files a/Ajuda/guide-master/guide/images/send.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/wallpaper.jpg b/Ajuda/guide-master/guide/images/wallpaper.jpg deleted file mode 100644 index dda9156..0000000 Binary files a/Ajuda/guide-master/guide/images/wallpaper.jpg and /dev/null differ diff --git a/Ajuda/guide-master/guide/images/winston.png b/Ajuda/guide-master/guide/images/winston.png deleted file mode 100644 index 78596b5..0000000 Binary files a/Ajuda/guide-master/guide/images/winston.png and /dev/null differ diff --git a/Ajuda/guide-master/guide/improving-dev-environment/package-json-scripts.md b/Ajuda/guide-master/guide/improving-dev-environment/package-json-scripts.md deleted file mode 100644 index 56616e7..0000000 --- a/Ajuda/guide-master/guide/improving-dev-environment/package-json-scripts.md +++ /dev/null @@ -1,78 +0,0 @@ -# Setting up package.json scripts - -An easy way to run scripts like a script to start your bot, a script to lint your bot's files or whatever scripts you use, is by storing them in your `package.json` file. After you store these scripts in your `package.json` file, you can just type `npm run start` to start your bot, or `npm run lint` to lint your code for errors. - -## Getting started - -::: tip -Before getting started, you'll need to have a `package.json` file. If you don't have a `package.json` file yet, you can run `npm init -y` in the console to generate one. -::: - -If you haven't touched your `package.json` file yet (excluding installing dependencies), your `package.json` file should look similar to the following: - -```json -{ - "name": "my-bot", - "version": "1.0.0", - "description": "A Discord bot!", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [], - "author": "", - "license": "ISC" -} -``` - -Let's zoom in more. Below `main`, you'll see `scripts`. You can specify your scripts there. In this guide, we'll show how to start and lint your bot using a `package.json` script. - -## Adding your first script - -::: tip -We'll assume you have finished the [creating your first bot](/creating-your-bot/) section of the guide. If you haven't, ensure to follow it first! -::: - -Over at your `package.json` file, add the following line to the `scripts`: - -```json -"start": "node ." -``` - -::: tip -The `node .` script will run the file which you have specified at the `main` entry in your `package.json` file. If you don't have it set yet, make sure to set `main` to your bot's main file! -::: - -Now, whenever you run the `npm run start` script in your bot's directory, it will run the `node .` command. Let's create another script to lint your code via the command line. - -::: tip -If you do not have ESLint installed globally, you can use [npx](https://alligator.io/workflow/npx/) to run the ESLint script for your local directory. For more info on how to set it up, you can read the site [here](https://alligator.io/workflow/npx/). -::: -Add the following line to your scripts: - -```json -"lint": "eslint ." -``` - -Now, whenever you run the `npm run lint` script, ESLint will lint your `index.js` file. - -Your `package.json` file should now look similar to the following: - -```json -{ - "name": "my-bot", - "version": "1.0.0", - "description": "A Discord bot!", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", - "start": "node .", - "lint": "eslint ." - }, - "keywords": [], - "author": "", - "license": "ISC" -} -``` - -And that's it! You can always add more scripts now, being able to run them with `npm run script-name`. diff --git a/Ajuda/guide-master/guide/improving-dev-environment/pm2.md b/Ajuda/guide-master/guide/improving-dev-environment/pm2.md deleted file mode 100644 index 2406c28..0000000 --- a/Ajuda/guide-master/guide/improving-dev-environment/pm2.md +++ /dev/null @@ -1,114 +0,0 @@ -# Managing your bot process with PM2 - -PM2 is a process manager. It manages your applications' states, so you can start, stop, restart and delete processes. It offers features such as monitoring running processes and setting up a "start with operating system" (be that Windows, Linux or Mac) so your processes start when you boot your system. - -## Installation - -You can install PM2 via npm: - -```bash -npm install --global pm2 -``` - -Or, if you use Yarn: - -```bash -yarn global add pm2 -``` - -## Starting your app - -After PM2 has been installed, the easiest way you can start your app is by going to the directory your bot is in, and then run the following: - -```bash -pm2 start your-app-name.js -``` - -### Additional notes - -The `pm2 start` script allows for more optional command-line arguments. - -- `--name`: This allows you to set the name of your process when listing it up with `pm2 list` or `pm2 monit`: - -```bash -pm2 start your-app-name.js --name "Some cool name" -``` - -- `--watch`: This option will automatically restart your process as soon as a file change has been detected, which can be useful for development environments: - -```bash -pm2 start your-app-name.js --watch -``` - -::: tip -The `pm2 start` command can take more optional parameters, but for now only these 2 are relevant for us. If you want to see all the parameters available, you can check the documentation of pm2 [here](https://pm2.io/doc/en/runtime/reference/pm2-cli/). -::: - -Once the process is launched with pm2, you can run `pm2 monit` to monitor any and all console outputs from the processes started by pm2. This accounts for any `console.log()` in your code or outputted errors. - -## Setting up booting with your system - -Perhaps one of the more useful features of PM2 is being able to boot up with your Operating System. This will ensure that your bot processes will always be started after an (unexpected) reboot (e.g. after a power outage). - -The initial steps to run differ per OS. In this guide, we'll cover those for Windows and for Linux/MacOS. - -### Initial steps for Windows - -::: tip -Run these from an administrative command prompt to avoid getting hit with a bunch of UAC dialogs. -::: - -**Install the [pm2-windows-service](https://www.npmjs.com/package/pm2-windows-service) package from npm:** - -```bash -npm install --global pm2-windows-service -``` - -**After installation has finished, install the service by running the following command:** - -```bash -pm2-service-install -``` -::: tip -You can use the `-n` parameter to set the service name: `pm2-service-install -n "the-service-name"` -::: - -### Initial steps for Linux/MacOS - -You need to get a start script, which you can get by running the following command: - -```bash -# Detects the available init system, generates the config and enables startup system -pm2 startup -``` - -Or, if you want to manually specify your machine select one of the options with the command: - -```bash -pm2 startup [ubuntu | ubuntu14 | ubuntu12 | centos | centos6 | arch | oracle | amazon | macos | darwin | freesd | systemd | systemv | upstart | launchd | rcd | openrc] -``` - -The output of running one of the commands listed above will output a command for you to run with all environment variables and options configured for you. - -**Example output for an Ubuntu user:** - -```bash -[PM2] You have to run this command as root. Execute the following command: - sudo su -c "env PATH=$PATH:/home/user/.nvm/versions/node/v8.9/bin pm2 startup ubuntu -u user --hp /home/user -``` - -After running that command, you can continue to the next step. - -### Saving the current process list - -To save the current process list so it will automatically get started after a restart, run the following command: - -```bash -pm2 save -``` - -To disable this, you can run the following command: - -```bash -pm2 unstartup -``` diff --git a/Ajuda/guide-master/guide/keyv/README.md b/Ajuda/guide-master/guide/keyv/README.md deleted file mode 100644 index 7b62fd1..0000000 --- a/Ajuda/guide-master/guide/keyv/README.md +++ /dev/null @@ -1,164 +0,0 @@ -# Storing data with Keyv - -[Keyv](https://github.com/lukechilds/keyv) is a simple key-value store that works with multiple backends. It's fully scalable for [sharding](/sharding/) and supports JSON storage. - -## Installation - -```bash -npm install --save keyv -``` - -Keyv requires an additional package depending on which persistent backend you would prefer to use. If you want to keep everything in memory, you can skip this part. Otherwise, install one of the below. - -```bash -npm install --save @keyv/redis -npm install --save @keyv/mongo -npm install --save @keyv/sqlite -npm install --save @keyv/postgres -npm install --save @keyv/mysql -``` - -Now that Keyv and any necessary drivers are installed, create an instance of Keyv. - - -```js -const Keyv = require('keyv'); - -// One of the following -const keyv = new Keyv(); // for in-memory storage -const keyv = new Keyv('redis://user:pass@localhost:6379'); -const keyv = new Keyv('mongodb://user:pass@localhost:27017/dbname'); -const keyv = new Keyv('sqlite://path/to/database.sqlite'); -const keyv = new Keyv('postgresql://user:pass@localhost:5432/dbname'); -const keyv = new Keyv('mysql://user:pass@localhost:3306/dbname'); -``` - -Make sure to handle connection errors. - -```js -keyv.on('error', err => console.error('Keyv connection error:', err)); -``` - -For more detailed setup, check out the [Keyv readme](https://github.com/lukechilds/keyv/blob/master/README.md). - -## Usage - -Keyv exposes a familiar [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map)-like API. However, it only has `set`, `get`, `delete`, and `clear` methods. Additionally, instead of immediately returning data, these methods return [Promises](/additional-info/async-await.md) that resolve with the data. - -```js -(async () => { - // true - await keyv.set('foo', 'bar'); - - // bar - await keyv.get('foo'); - - // undefined - await keyv.clear(); - - // undefined - await keyv.get('foo'); -})(); -``` - -## Application - -Although Keyv can be used in any scenario where you need key-value data, we will focus on setting up a per-guild prefix configuration using Sqlite. - -::: tip -This section will still work with any provider supported by Keyv. We recommend PostgreSQL for larger applications. -::: - -### Setup - -```js -const Discord = require('discord.js'); -const Keyv = require('keyv'); - -const client = new Discord.Client(); -const prefixes = new Keyv('sqlite://path/to.sqlite'); -const globalPrefix = '.'; -``` - -### Command handler - -This guide uses a very basic command handler with some added complexity to allow for multiple prefixes. For more a more robust command handler, look at the [command handling](/command-handling/) guide. - -```js -client.on('message', async message => { - if (message.author.bot) return; - - let args; - // handle messages in a guild - if (message.guild) { - let prefix; - - if (message.content.startsWith(globalPrefix)) { - prefix = globalPrefix; - } else { - // check the guild-level prefix - const guildPrefix = await prefixes.get(message.guild.id); - if (message.content.startsWith(guildPrefix)) prefix = guildPrefix; - } - - // if we found a prefix, setup args; otherwise, this isn't a command - if (!prefix) return; - args = message.content.slice(prefix.length).split(/\s+/); - } else { - // handle DMs - const slice = message.content.startsWith(globalPrefix) ? globalPrefix.length : 0; - args = message.content.slice(slice).split(/\s+/); - } - - // get the first space-delimited argument after the prefix as the command - const command = args.shift().toLowerCase(); -}); -``` - -### Prefix command - -Now that you have a command handler, make a command to allow people to use your prefix system. - - -```js -if (command === 'prefix') { - // if there's at least one argument, set the prefix - if (args.length) { - await prefixes.set(message.guild.id, args[0]); - return message.channel.send(`Successfully set prefix to \`${args[0]}\``); - } - - return message.channel.send(`Prefix is \`${await prefixes.get(message.guild.id) || globalPrefix}\``); -} -``` - -You will probably want to setup additional validation such as required permissions and maximum prefix length. - -### Usage - -
- - .prefix - - - Prefix is `.` - - - .prefix $ - - - Successfully set prefix to `$` - - - $prefix - - - Prefix is `$` - -
- -## Next steps - -Keyv can be used in a variety of other applications, such as guild settings; simply create another instance with a different [namespace](https://github.com/lukechilds/keyv#namespaces) for each setting. Additionally, it can be [extended](https://github.com/lukechilds/keyv#third-party-storage-adapters) to work with whatever storage backend you prefer. - -Check out the [Keyv repository](https://github.com/lukechilds/keyv) for more information. diff --git a/Ajuda/guide-master/guide/miscellaneous/parsing-mention-arguments.md b/Ajuda/guide-master/guide/miscellaneous/parsing-mention-arguments.md deleted file mode 100644 index 7b5ed07..0000000 --- a/Ajuda/guide-master/guide/miscellaneous/parsing-mention-arguments.md +++ /dev/null @@ -1,198 +0,0 @@ -# Parsing mention arguments - -In a previous chapter you learned how to build commands with user input, you also learned how to use *mentions* as user input. -However, using `message.mentions` can lead to a few problems. -For example you do not really know which mention belongs to which argument. -Or if you are splitting the message's content by spaces to get the args, -then the mentions will still take up space in your args array which can mess up the rest of your args parsing if you are not careful. - -Say you are writing a bot for moderating your server. Obviously you will want a kick or a ban command which allows you to mention the person you are trying to ban. -But what happens if you try to use the command like this? - -``` -!ban @Offender Because he was rude to @Victim -``` - -You might expect it to ban @Offender, because that is who you mentioned first. -However, the Discord API does not send the mentions in the order they appear; They are sorted by their ID instead. - -If the @Victim happens to have joined Discord before @Offender and thus has a smaller ID he might get banned instead. -Or maybe someone uses a command incorrectly, the bot might still accept it but it will create an unexpected outcome. -Say someone accidentally used the ban command like this: - -``` -!ban Because he was rude to @Victim -``` - -The bot will still ban someone, but it will be the @Victim again. `message.mentions.users` still contains a mention, which the bot will use. But in reality you would want your bot to be able to tell the user he used the command incorrectly. - -## How Discord mentions work - -Discord uses a special syntax to embed mentions in a message. For user mentions it is the user's ID with `<@` at the start and `>` at the end, like this: `<@86890631690977280>`. If they have a nickname there will also be a be a `!` after the `@`. -Role mentions and channel mentions work similarly. Role mentions look like `<@&134362454976102401>` and channel mentions like `<#222197033908436994>`. - -That means when you receive a message from the Discord API and it contains mentions the message's content will contain that special syntax. -If you send - -
- - I think we should add GoodPerson to the Mod role. - -
- -then the `message.content` for that message will look something like this - - -```js -'I think we should add <@86890631690977280> to the <@&134362454976102401> role.' -``` - -## Implementation - -So, how do you actually use this new information for your bot? -Most of your code will not change, however instead of using `message.mentions` to find the mentioned users you will have to do it manually. -This may sound scary at first, but once you see the code you will see it is actually pretty simple. - -Say you already have a simple command handler like this: - -```js -client.on('message', message => { - if (!message.content.startsWith(config.prefix)) return; - - const withoutPrefix = message.content.slice(config.prefix.length); - const split = withoutPrefix.split(/ +/); - const command = split[0]; - const args = split.slice(1); -}); -``` - -Now you can easily test the waters by upgrading the avatar command from [last time](/creating-your-bot/commands-with-user-input.md). -This is what we have so far. It is pretty simple, it will show the avatar of who used the command. - -```js -if (command === 'avatar') { - const user = message.author; - - return message.channel.send(`${user.username}'s avatar: ${user.displayAvatarURL}`); -} -``` - -But how do you actually get the correct user now? Well, this requires a few simple steps. -Putting it into a function will make it easily reusable. We will use the name `getUserFromMention` here. - -```js -function getUserFromMention(mention) { - if (!mention) return; - - if (mention.startsWith('<@') && mention.endsWith('>')) { - mention = mention.slice(2, -1); - - if (mention.startsWith('!')) { - mention = mention.slice(1); - } - - return client.users.get(mention); - } -} -``` - -As you can see it is a fairly straight forward function. -It essentially just works itself through the structure of the mention bit by bit: - 1. Check if the mention starts with the `<@` and ends with a `>` and then remove those. - 2. If the user has a nickname and their mention contains a `!` remove that as well. - 3. Only the ID should be left now, so use that to fetch the user from the `client.users` Collection. -Whenever it encounters an error with the mention (i.e. invalid structure) it simply returns `undefined` to signal the mention is invalid. - -::: tip -The `.slice()` method is used in a more advance way here. You can read the [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/slice) for more info. -::: - -Now you have a nifty function you can use whenever you need to convert a raw mention into a proper user object. -Plugging it into the command will give you this: - -```js -if (command === 'avatar') { - if (args[0]) { - const user = getUserFromMention(args[0]); - if (!user) { - return message.reply('Please use a proper mention if you want to see someone else\'s avatar.'); - } - - return message.channel.send(`${user.username}'s avatar: ${user.displayAvatarURL}`); - } - - return message.channel.send(`${message.author.username}, your avatar: ${message.author.displayAvatarURL}`); -} -``` - -And here we simply plug the new function into the command. -If the user supplied an argument it should be the user mention, so it just gets passed right into the function. - -And that is it! Simple, isn't it? Start up your bot and see if it works. - -
- - !avatar User - - - User's avatar: https://cdn.discordapp.com/avatars/328037144868290560/1cc0a3b14aec3499632225c708451d67.png - -
- -So now, instead of using `message.mentions` you can use your new, fantastic function. -This will allow you to add proper checks for all your args, so that you can tell when a command was used correctly and when it was used incorrectly. - -But this does not mark the end of the page. If you feel adventurous you can read on and learn how to use Regular Expressions to easily convert a mention into a user object in just two lines. - -### Using Regular Expressions - -Previously you learn how to use rudimentary string related functions to turn the special mention syntax Discord uses into a proper discord.js User object. -But using Regular Expressions (aka "RegEx" or "RegExp"), you can condense all that logic into a single line! Crazy, right? - -If you have never worked with Regular Expressions before, this might seem daunting. But in fact, you already have used regular expressions. Remember `withoutPrefix.split(/ +/);`? This little `/ +/` is actually a Regular Expression. The `/` on either side tell JavaScript where the Regular Expression begins and where it ends, the stuff inbetween is it is content. - -::: tip -For a more detailed explanation please consult the [MDN's documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp). -::: - -The RegEx you will use for user mentions will look like this: `/^<@!?(\d+)>$/`. -Here is how the RegEx works: - - 1. The `^` at the beginning and the `$` at the end mean that the mention has to take up the entire string. - 2. You have the typical `<@` and `>` at the beginning and end. - 3. The `?` after the `!` indicates that the `!` is optional. - 4. `\d+` means the RegEx will look for multiple digits, which will be the ID. - 5. The parentheses around the `\d+` create a capture group, which allows us to get the ID out of the mention. - -Using the `.match()` method on strings you can get the values of the capture group, i.e., the ID of the mention. - -::: warning -Discord.js has [built-in patterns](https://discord.js.org/#/docs/main/11.5.1/class/MessageMentions?scrollTo=s-CHANNELS_PATTERN)[built-in patterns](https://discord.js.org/#/docs/main/master/class/MessageMentions?scrollTo=s-CHANNELS_PATTERN) -for matching mentions, however as of version 11.4 they do not contain any groups -and thus aren't useful for actually getting the ID out of the mention. -::: - -Updating your `getUserFromMention` function to use RegEx gives you this: - -```js -function getUserFromMention(mention) { - // The id is the first and only match found by the RegEx. - const matches = mention.match(/^<@!?(\d+)>$/); - - // If supplied variable was not a mention, matches will be null instead of an array. - if (!matches) return; - - // However the first element in the matches array will be the entire mention, not just the ID, - // so use index 1. - const id = matches[1]; - - return client.users.get(id); -} -``` - -See? That is *much* shorter, and not that complicated. -If you run your bot again now everything should still work the same. - -## Resulting code - - diff --git a/Ajuda/guide-master/guide/miscellaneous/useful-packages.md b/Ajuda/guide-master/guide/miscellaneous/useful-packages.md deleted file mode 100644 index 4c6e2a3..0000000 --- a/Ajuda/guide-master/guide/miscellaneous/useful-packages.md +++ /dev/null @@ -1,189 +0,0 @@ -# Useful packages - -## moment.js - -::: tip -Official documentation: https://momentjs.com/docs/ -::: - -Moment is a powerful package for working with dates in JavaScript. -It allows you to quickly and easily format dates in any way you want or parse strings back into JavaScript Date objects. -There are even some extensions for it to allow you work with durations and more. - -For example if you wanted to ask your users to give you a date, -you can use moment to turn it in a Date object you can use in your code: - - -```js -const input = await message.channel.awaitMessages(m => m.author.id === message.author.id, { - max: 4, - time: 10e3, - errors: ['time'], -}); -const date = moment(input.first().content); -``` - -Using the "moment-duration-format" extension we could tell the user how many days in the future or past the date is: - -```js -if (date.isValid()) { - const now = moment(); - const duration = date - now; - const formatted = moment.duration(duration, 'ms').format(); - - if (duration > 0) { - message.channel.send(`The date you gave me is ${formatted} into the future.`); - } else { - message.channel.send(`The date you gave me is ${formatted} into the past.`); - } -} else { - message.channel.send('You didn\'t give me a valid date.'); -} -``` - -## ms - -::: tip -Official documentation: https://github.com/zeit/ms -::: - -Ms is another tool for working with times in JavaScript. However, ms specializes on durations. -It allows you to convert times in milliseconds into human readable formats, and vice versa. - -Example: - - -```js -await message.channel.send('Send two messages and I\'ll tell you how far apart you sent them.'); -const messages = await message.channel.awaitMessages(m => m.author.id === message.author.id. { - max: 2, - time: 30e3, - errors: ['time'], -}); - -const difference = messages.last().createdTimestamp - messages.first().createdTimestamp; -const formatted = ms(difference); - -message.channel.send(`You sent the two messages ${formatted} apart.`); -``` - -## common-tags - -::: tip -Official documentation: https://github.com/declandewet/common-tags -::: - -Common-tags is a library all about working with template literals. -So far you have probably only used them for interpolating variables into your strings, but they can do a whole lot more. -If you got time, you should check out [the MDN's documentation about *tagged literals*.](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#Tagged_templates). - -Ever got annoyed your multi-line strings had nasty bits of indentation in them, -but you did not want to remove the indentation in your source code? -common-tags got you covered: - -```js -const packageName = 'common-tags'; - -if (someCondition) { - const poem = stripIndents` - I like ${packageName}. - It makes my strings so pretty, - you should use it too. - `; - - console.log(poem); -} -``` - -This will print your little poem like expected, but it will not have any tabs or other whitespace on the left. - -But this is just the start! Another set of useful functions are the list-related functions: -`inlineLists`, `commaLists`, etc. -With those you can easily interpolate arrays into your strings without them looking ugly: - -```js -const options = ['add', 'delete', 'edit']; - -// -> Do you want me to add, delete or edit the channel? -message.channel.send(oneLineCommaListsOr` - Do you want me to ${options} the channel? -`); -``` - -Check the the documentation to find more useful functions. - -## chalk - -::: tip -Official documentation: https://www.npmjs.com/package/chalk -::: - -Chalk is not exactly useful for Discord bots themselves, but it will make your terminal output a lot prettier and organized. -This package lets you color and style your `console.log`s in many, many different ways; No more simple white on black. - -Let's say you want your error messages to be easily visible; Let us give them a nice red color: - -```js -console.log(chalk.redBright('FATAL ERROR'), 'Something really bad happened!'); -``` - -![image of code above](~@/images/chalk-red.png) - -You can also chain multiple different multipliers. -If you wanted to have green text, a grey background and have it all underlined that is absolutely possible: - -```js -console.log(chalk.green.bgBrightBlack.underline('This is so pretty.')); -``` - -![image of code above](~@/images/chalk-ugly.png) - -## winston - -::: tip -Official documentation: https://github.com/winstonjs/winston -::: - -Winston is "a logger for just about everything". -You can log to the terminal, you can log to a file, etc. -"But wait," I hear you cry, "what's wrong with `console.log`?". -Well, the answer is simple: `console.log` is slow, very slow, and not very versatile. -Whenver you make a call to `console.log` your program halts, it has to wait for console.log to finish. -While it does that your program can do nothing else. That does not sound very good, does it? -Well, that is exactly what winston is for. - -Winston is fast and highly configurable. It has different log levels for all your needs, it can log to files, the terminal, etc. -Like moment.js it also has extension packages. So if there is something you feel is missing you can probably find one that fits your needs. - -Now, there really are *a lot* of options, so it is recommended you take a look at the docs yourself. -But let us get a quick overview of what it can do: - -```js -const client = new Discord.Client(); -const logger = winston.createLogger({ - transports: [ - new winston.transports.Console(), - new winston.transports.File({ filename: 'log' }), - ], - format: winston.format.printf(log => `[${log.level.toUpperCase()}] - ${log.message}`), -}); - -client.on('ready', () => logger.log('info', 'The bot is online!')); -client.on('debug', m => logger.log('debug', m)); -client.on('warn', m => logger.log('warn', m)); -client.on('error', m => logger.log('error', m)); - -process.on('uncaughtException', error => logger.log('error', error)); - -client.login('token'); -``` - -The above code creates a simple logger which will log to both the console and a file called "log" (defined by the `transports` options). -The `format` option tells the logger which format to use for the messages, by default it outputs JSON objects. -While useful, JSON is not very readable, so we are defining a custom format which just displays the log level in all caps alongside the message. -If you wanted to you could also use the chalk module to make the logger's format a bit prettier by applying colors, etc. - -![winston example](~@/images/winston.png) - -Winston is not the only logging library out there though, so if you are not convinced you should google around a bit and -you should find something you will like. diff --git a/Ajuda/guide-master/guide/oauth2/README.md b/Ajuda/guide-master/guide/oauth2/README.md deleted file mode 100644 index 8e1ef46..0000000 --- a/Ajuda/guide-master/guide/oauth2/README.md +++ /dev/null @@ -1,261 +0,0 @@ -# Getting started with OAuth2 - -OAuth2 enables application developers to build applications that utilize authentication and data from the Discord API. This can be used to create things such as web dashboard to display user info, fetch linked third-party accounts like Twitch or Steam, access users' guild information without actually being in the guild, and much more. OAuth2 can greatly extend the functionality of your bot if used correctly. - -## A quick example - -### Setting up a basic web server - -Most of the time, OAuth2 is used in websites to get information about its users from an external service. In this example, you will use Node.js' built-in `http` module to create a web server to use a user's Discord information to greet them. First, create a file named `index.js` which will be used to start the server. - -```js -const http = require('http'); -const fs = require('fs'); -const port = 53134; - -http.createServer((req, res) => { - let responseCode = 404; - let content = '404 Error'; - - if (req.url === '/') { - responseCode = 200; - content = fs.readFileSync('./index.html'); - } - - res.writeHead(responseCode, { - 'content-type': 'text/html;charset=utf-8', - }); - - res.write(content); - res.end(); -}) - .listen(port); -``` - -Right now, you have designated that the contents of an `index.html` file will be served to the user when they visit the root domain, so create an `index.html` file in the same directory with the following contents. - -```html - - - - My First OAuth2 App - - -
- Hoi! -
- - -``` - -You can start your server with `node index.js`. Once you start it, try connecting to http://localhost:53134 and you should see "Hoi!". - -### Getting an OAuth2 url - -Now that you have your web server up and running, it's time to get some information from Discord. Head over to [your Discord applications](https://discordapp.com/developers/applications/) and click "Create an application", where you'll be greeted with the following page: - -![Create an application page](~@/images/1ch98sm.png) - -Take note of the `client id` field, the `client secret` field, and the "OAuth2" link on the left side of the page. For now, click on "OAuth2" and add a redirect url to `http://localhost:53134` like so: - -![img](~@/images/9fejia2.png) - -Once you've added your redirect url, you will want to generate an OAuth2 url. Lower down on the page, you can conveniently find an OAuth2 Url Generator provided by Discord. Use this to generate a url for yourself with the `identify` scope. - -![img](~@/images/18e2dwi.png) - -The `identify` scope will allow your application to get basic user information from Discord. A list of all scopes can be found [here](https://discordapp.com/developers/docs/topics/oauth2#shared-resources-oauth2-scopes). - -### Putting it together - -You have your website, and you have a url. Now you need to use those two things to get an access token. For basic applications like [SPAs](https://en.wikipedia.org/wiki/Single-page_application), getting an access token directly is enough to work with. If you want to do this, make sure the `response_type` in the url is `token`. However, this means you will not get a refresh token, which means the user will have to explicitly re-authorize when this access token has expired. - -After you change the response type, you can test the url right away. Try visiting it in your browser and you will be directed to a page that looks like this. - -![img](~@/images/49jali8.png) - -You can see that by clicking `Authorize`, you are allowing the application to access your username and avatar. Once you click through, you should be redirected to the redirect url with a [fragment identifier](https://en.wikipedia.org/wiki/Fragment_identifier) appended to it. You now have an access token and can make requests to Discord's API to get information on the user. Modify `index.html` to add your OAuth2 url and to take advantage of the access token if it exists. Even though [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) is for working with query strings, it can work here because the structure of the fragment follows that of a query string after removing the leading "#". - -```html - - - - My First OAuth2 App - - -
- Hoi! -
- - - - -``` - -Here you just grab the access token and type from the url if it's there and use it to get info on the user, which is then used to greet them. In the following sections, we'll go over various details of Discord and OAuth2. - -## More details - -### The state parameter - -OAuth2's protocols provide a `state` parameter which is supported by Discord. This is used to help prevent [CSRF](https://en.wikipedia.org/wiki/Cross-site_request_forgery) attacks and can also be used to represent the state of your application. This should be generated per user and appended to the OAuth2 url. For a very basic example, you can use a randomly generated string encoded in Base64 as the state parameter. - -```js -function generateRandomString() { - const rand = Math.floor(Math.random() * 10); - let randStr = ''; - - for (let i = 0; i < 20 + rand; i++) { - randStr += String.fromCharCode(33 + Math.floor(Math.random() * 94)); - } - - return randStr; -} - -// ... - -// generate and store the string -const randStr = generateRandomString(); -localStorage.setItem('stateParameter', randStr); - -document.getElementById('login').href += `&state=${btoa(randStr)}`; -``` - -When you visit a url with a `state` parameter appended to it and then click `Authorize`, you'll notice that after being redirected, the url will also have the `state` parameter appended to it, which you should then check against what was stored. You can modify the script in your `index.html` file to handle this. - -```js -const fragment = new URLSearchParams(window.location.hash.slice(1)); - -if (fragment.has('access_token')) { - const urlState = fragment.get('state'); - const stateParameter = localStorage.getItem('stateParameter'); - if (stateParameter !== atob(decodeURIComponent(urlState))) { - return console.log('You may have been clickjacked!'); - } -} -``` - -::: tip -Don't forgo security for a tiny bit of convenience! -::: - -### OAuth2 flows - -What you did in the quick example was go through the `implicit grant` flow, which passed the access token straight to the user's browser. This is great and simple, but you don't get to refresh the token without the user and it is less secure than going through the `authorization code grant`. This involves recieving an access code, which is then exchanged by your server for an access token. Notice that this way, the access token never actually reaches the user throughout the process. - -#### Authorization code grant - -Unlike the quick example, you need an OAuth2 url where the `response_type` is `code`. Once you've obtained it, try visiting the link and authorizing your application. You should notice that instead of a hash, the redirect url now has a single query parameter appended to it like `?code=ACCESS_CODE`. Modify your `index.js` file to pull the parameter out of the url if it exists. You can use the `url` module to do this for us. - -```js -const url = require('url'); - -// ... - -const urlObj = url.parse(req.url, true); - -if (urlObj.query.code) { - const accessCode = urlObj.query.code; - console.log(`The access code is: ${accessCode}`); -} - -if (urlObj.pathname === '/') { - responseCode = 200; - content = fs.readFileSync('./index.html'); -} -``` - -Now, that you have to exchange this code with Discord for an access token. To do this, you need your `client_id` and `client_secret`. If you've forgotten them, head over to [your applications](https://discordapp.com/developers/applications) and get them. You can use `node-fetch` along with `form-data` to make requests to Discord; you can install them with `npm i node-fetch` and `npm i form-data` respectively. - -Require these new modules and make your request. - -```js -const fetch = require('node-fetch'); -const FormData = require('form-data'); - -// ... - -const data = new FormData(); - -data.append('client_id', 'your client id'); -data.append('client_secret', 'your client secret'); -data.append('grant_type', 'authorization_code'); -data.append('redirect_uri', 'your redirect url'); -data.append('scope', 'the scopes'); -data.append('code', accessCode); - -fetch('https://discordapp.com/api/oauth2/token', { - method: 'POST', - body: data, -}) - .then(res => res.json()) - .then(console.log); -``` - -::: warning -The content-type for the token url must be `application/x-www-form-urlencoded`. This is why `form-data` is used. -::: - -Now try visiting your OAuth2 url and authorizing your application. Once you're redirected, you should see something like this in your console. - -```json -{ "access_token": "an access token", - "token_type": "Bearer", - "expires_in": 604800, - "refresh_token": "a refresh token", - "scope": "identify" } -``` - -Now that you have an access token and a refresh token, try fetching the user's information. It's the exact same as how it was done in the html file. - -```js -fetch('https://discordapp.com/api/oauth2/token', { - method: 'POST', - body: data, -}) - .then(res => res.json()) - .then(info => fetch('https://discordapp.com/api/users/@me', { - headers: { - authorization: `${info.token_type} ${info.access_token}`, - }, - })) - .then(console.log); -``` - -::: tip -To maintain security, store the access token server side but associate it with a session ID that you generate for the user. -::: - -## Additional reading - -[RFC 6759](https://tools.ietf.org/html/rfc6749) -[Discord Docs for OAuth2](https://discordapp.com/developers/docs/topics/oauth2) - -## Resulting code - - diff --git a/Ajuda/guide-master/guide/popular-topics/canvas.md b/Ajuda/guide-master/guide/popular-topics/canvas.md deleted file mode 100644 index 28ba7b7..0000000 --- a/Ajuda/guide-master/guide/popular-topics/canvas.md +++ /dev/null @@ -1,715 +0,0 @@ -# Image manipulation with Canvas - -## Setting up Canvas - -Canvas is an image manipulation tool that allows you to modify images with code. We'll explore how to use this module in a heavily requested feature: guild member welcome messages. But first, you must go through the intense labor of installing Canvas. It's highly recommended that you use a Linux distribution for this because it'll be much easier to install on. - -::: tip -This guide is last tested with `canvas^2.6.0`, so make sure you have this or a similar version after installation. -::: - -::: warning -Be sure that you're familiar with things like [async/await](/additional-info/async-await.md) and [object destructuring](/additional-info/es6-syntax.md#object-destructuring) before continuing, as we'll be making use of features like these. -::: - -## Installation - -### Windows - -You will need a package called Windows Build Tools. You may install it with npm with the following command: `npm i --global --production windows-build-tools`, or with yarn by running the following: `yarn global add --production windows-build-tools`. It is also bundled with Chocolatey, should you choose that installation path. Afterwards, you should follow the instructions detailed [here](https://github.com/Automattic/node-canvas/wiki/Installation:-Windows). Additionally, make sure Node and Cairo are **both** either 32-bit or 64-bit; having a 32-bit version of one and a 64-bit version of the other will cause errors. - -If you are *still* unable to install Canvas, you might want to consider installing [Microsoft Visual Studio 2015](https://www.visualstudio.com/vs/older-downloads/). - -### Other distributions - -You can run one of the commands listed [here](https://github.com/Automattic/node-canvas#compiling) to install the necessary tools Canvas needs. - -### Package installation - -After installing all the necessary software, run `npm i canvas` if you use npm, or `yarn add canvas` if you use Yarn. - -## Getting started - -Here is the base code you'll be using to get started: - -```js -const Discord = require('discord.js'); -const Canvas = require('canvas'); - -const client = new Discord.Client(); - -client.once('ready', () => { - console.log('Ready!'); -}); - -client.on('guildMemberAdd', member => { - const channel = member.guild.channels.find(ch => ch.name === 'member-log'); - if (!channel) return; - - channel.send(`Welcome to the server, ${member}!`); -}); - -client.login('your-token-goes-here'); -``` - -To make testing this feature much easier, you can add a simple command that'll "fake" a new member joining. - - - - -```js -client.on('message', async message => { - if (message.content === '!join') { - client.emit('guildMemberAdd', message.member || await message.guild.fetchMember(message.author)); - } -}); -``` - - - - -```js -client.on('message', message => { - if (message.content === '!join') { - client.emit('guildMemberAdd', message.member); - } -}); -``` - - - -What this will do is trigger the `guildMemberAdd` event while passing in the message author's GuildMember object. Of course, you should remove this command once you're doing adding this feature to your actual bot. - -### Basic image loading - -The end goal will be to display the user's avatar, username, and a simple "Welcome!" message when they join. After importing the Canvas module and initializing it, you should load the images. With Canvas, you have to specify where the image comes from first, naturally, and then specify how it gets loaded into the actual Canvas using `ctx`, which is what you will use to interact with Canvas. - -::: tip -`node-canvas` works almost identical to HTML5 Canvas. You can read the HTML5 Canvas tutorials on [w3Schools](https://www.w3schools.com/html/html5_canvas.asp) and [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API) for more information later! -::: - - - -```js -client.on('guildMemberAdd', async member => { - const channel = member.guild.channels.find(ch => ch.name === 'member-log'); - if (!channel) return; - - // Set a new canvas to the dimensions of 700x250 pixels - const canvas = Canvas.createCanvas(700, 250); - // ctx (context) will be used to modify a lot of the canvas - - const ctx = canvas.getContext('2d'); - - channel.send(`Welcome to the server, ${member}!`); -}); -``` - -Now, you need to load the image you want to use into Canvas. In order to have more sufficient coverage, we'll first show you how to load a basic image from a local directory. We'll be using [this image](~@/images/canvas.jpg) as the background in the welcome image, but you can use whatever you want. Be sure to download the file, name it `wallpaper.jpg`, and save it inside the same directory as your main bot file. - - - -```js -client.on('guildMemberAdd', async member => { - const channel = member.guild.channels.find(ch => ch.name === 'member-log'); - if (!channel) return; - - const canvas = Canvas.createCanvas(700, 250); - const ctx = canvas.getContext('2d'); - - // Since the image takes time to load, you should await it - const background = await Canvas.loadImage('./wallpaper.jpg'); - // This uses the canvas dimensions to stretch the image onto the entire canvas - ctx.drawImage(background, 0, 0, canvas.width, canvas.height); - // Use helpful Attachment class structure to process the file for you - const attachment = new Discord.Attachment(canvas.toBuffer(), 'welcome-image.png'); - - channel.send(`Welcome to the server, ${member}!`, attachment); -}); -``` - - - - -```js -client.on('guildMemberAdd', async member => { - const channel = member.guild.channels.find(ch => ch.name === 'member-log'); - if (!channel) return; - - const canvas = Canvas.createCanvas(700, 250); - const ctx = canvas.getContext('2d'); - - // Since the image takes time to load, you should await it - const background = await Canvas.loadImage('./wallpaper.jpg'); - // This uses the canvas dimensions to stretch the image onto the entire canvas - ctx.drawImage(background, 0, 0, canvas.width, canvas.height); - // Use helpful Attachment class structure to process the file for you - const attachment = new Discord.MessageAttachment(canvas.toBuffer(), 'welcome-image.png'); - - channel.send(`Welcome to the server, ${member}!`, attachment); -}); -``` - - - -![Basic canvas preview](~@/images/8CQvVRV.png) - -::: tip -If you get an error such as `Error: error while reading from input stream`, then the provided path to the file was incorrect. -::: - -### Manipulating images - -Next, let's place a border around the image, for the sake of demonstration purposes. - - - -```js -client.on('guildMemberAdd', async member => { - const channel = member.guild.channels.find(ch => ch.name === 'member-log'); - if (!channel) return; - - const canvas = Canvas.createCanvas(700, 250); - const ctx = canvas.getContext('2d'); - - const background = await Canvas.loadImage('./wallpaper.jpg'); - ctx.drawImage(background, 0, 0, canvas.width, canvas.height); - - // Select the color of the stroke - ctx.strokeStyle = '#74037b'; - // Draw a rectangle with the dimensions of the entire canvas - ctx.strokeRect(0, 0, canvas.width, canvas.height); - - const attachment = new Discord.Attachment(canvas.toBuffer(), 'welcome-image.png'); - - channel.send(`Welcome to the server, ${member}!`, attachment); -}); -``` - - - - -```js -client.on('guildMemberAdd', async member => { - const channel = member.guild.channels.find(ch => ch.name === 'member-log'); - if (!channel) return; - - const canvas = Canvas.createCanvas(700, 250); - const ctx = canvas.getContext('2d'); - - const background = await Canvas.loadImage('./wallpaper.jpg'); - ctx.drawImage(background, 0, 0, canvas.width, canvas.height); - - // Select the color of the stroke - ctx.strokeStyle = '#74037b'; - // Draw a rectangle with the dimensions of the entire canvas - ctx.strokeRect(0, 0, canvas.width, canvas.height); - - const attachment = new Discord.MessageAttachment(canvas.toBuffer(), 'welcome-image.png'); - - channel.send(`Welcome to the server, ${member}!`, attachment); -}); -``` - - - -![Image](~@/images/2vsIPEP.png) - -A bit plain, right? Fear not, for you have a bit more to do until you reach completion. Since the goal of guide page is focused more on actual code than design, let's just place a basic square shaped avatar for now on the left side of the image. In interest of coverage, you will also make it a circle afterwards. - - - -```js -client.on('guildMemberAdd', async member => { - const channel = member.guild.channels.find(ch => ch.name === 'member-log'); - if (!channel) return; - - const canvas = Canvas.createCanvas(700, 250); - const ctx = canvas.getContext('2d'); - - const background = await Canvas.loadImage('./wallpaper.jpg'); - ctx.drawImage(background, 0, 0, canvas.width, canvas.height); - - ctx.strokeStyle = '#74037b'; - ctx.strokeRect(0, 0, canvas.width, canvas.height); - - // Wait for Canvas to load the image - const avatar = await Canvas.loadImage(member.user.displayAvatarURL); - // Draw a shape onto the main canvas - ctx.drawImage(avatar, 25, 0, 200, canvas.height); - - const attachment = new Discord.Attachment(canvas.toBuffer(), 'welcome-image.png'); - - channel.send(`Welcome to the server, ${member}!`, attachment); -}); -``` - - - - -```js -client.on('guildMemberAdd', async member => { - const channel = member.guild.channels.find(ch => ch.name === 'member-log'); - if (!channel) return; - - const canvas = Canvas.createCanvas(700, 250); - const ctx = canvas.getContext('2d'); - - const background = await Canvas.loadImage('./wallpaper.jpg'); - ctx.drawImage(background, 0, 0, canvas.width, canvas.height); - - ctx.strokeStyle = '#74037b'; - ctx.strokeRect(0, 0, canvas.width, canvas.height); - - // Wait for Canvas to load the image - const avatar = await Canvas.loadImage(member.user.displayAvatarURL({ format: 'jpg' })); - // Draw a shape onto the main canvas - ctx.drawImage(avatar, 25, 0, 200, canvas.height); - - const attachment = new Discord.MessageAttachment(canvas.toBuffer(), 'welcome-image.png'); - - channel.send(`Welcome to the server, ${member}!`, attachment); -}); -``` - - - -![Image](~@/images/UCndZMo.png) - -Works well, but the avatar image itself seems a bit stretched out. Let's remedy that. - - - -```js -client.on('guildMemberAdd', async member => { - const channel = member.guild.channels.find(ch => ch.name === 'member-log'); - if (!channel) return; - - const canvas = Canvas.createCanvas(700, 250); - const ctx = canvas.getContext('2d'); - - const background = await Canvas.loadImage('./wallpaper.jpg'); - ctx.drawImage(background, 0, 0, canvas.width, canvas.height); - - ctx.strokeStyle = '#74037b'; - ctx.strokeRect(0, 0, canvas.width, canvas.height); - - const avatar = await Canvas.loadImage(member.user.displayAvatarURL); - // Move the image downwards vertically and constrain its height to 200, so it's a square - ctx.drawImage(avatar, 25, 25, 200, 200); - - const attachment = new Discord.Attachment(canvas.toBuffer(), 'welcome-image.png'); - - channel.send(`Welcome to the server, ${member}!`, attachment); -}); -``` - - - - -```js -client.on('guildMemberAdd', async member => { - const channel = member.guild.channels.find(ch => ch.name === 'member-log'); - if (!channel) return; - - const canvas = Canvas.createCanvas(700, 250); - const ctx = canvas.getContext('2d'); - - const background = await Canvas.loadImage('./wallpaper.jpg'); - ctx.drawImage(background, 0, 0, canvas.width, canvas.height); - - ctx.strokeStyle = '#74037b'; - ctx.strokeRect(0, 0, canvas.width, canvas.height); - - const avatar = await Canvas.loadImage(member.user.displayAvatarURL({ format: 'jpg' })); - // Move the image downwards vertically and constrain its height to 200, so it's a square - ctx.drawImage(avatar, 25, 25, 200, 200); - - const attachment = new Discord.MessageAttachment(canvas.toBuffer(), 'welcome-image.png'); - - channel.send(`Welcome to the server, ${member}!`, attachment); -}); -``` - - - -![Image](~@/images/9JfHooY.png) - -The purpose of this small section is to demonstrate that working with Canvas is essentially a hit-and-miss workflow where you fiddle with properties until they work just right. - -Since we covered how to load external images and fix dimensions, let's turn the avatar into a circle to improve the overall style of the image. - - - -```js -client.on('guildMemberAdd', async member => { - const channel = member.guild.channels.find(ch => ch.name === 'member-log'); - if (!channel) return; - - const canvas = Canvas.createCanvas(700, 250); - const ctx = canvas.getContext('2d'); - - const background = await Canvas.loadImage('./wallpaper.jpg'); - ctx.drawImage(background, 0, 0, canvas.width, canvas.height); - - ctx.strokeStyle = '#74037b'; - ctx.strokeRect(0, 0, canvas.width, canvas.height); - - // Pick up the pen - ctx.beginPath(); - // Start the arc to form a circle - ctx.arc(125, 125, 100, 0, Math.PI * 2, true); - // Put the pen down - ctx.closePath(); - // Clip off the region you drew on - ctx.clip(); - - const avatar = await Canvas.loadImage(member.user.displayAvatarURL); - ctx.drawImage(avatar, 25, 25, 200, 200); - - const attachment = new Discord.Attachment(canvas.toBuffer(), 'welcome-image.png'); - - channel.send(`Welcome to the server, ${member}!`, attachment); -}); -``` - - - - -```js -client.on('guildMemberAdd', async member => { - const channel = member.guild.channels.find(ch => ch.name === 'member-log'); - if (!channel) return; - - const canvas = Canvas.createCanvas(700, 250); - const ctx = canvas.getContext('2d'); - - const background = await Canvas.loadImage('./wallpaper.jpg'); - ctx.drawImage(background, 0, 0, canvas.width, canvas.height); - - ctx.strokeStyle = '#74037b'; - ctx.strokeRect(0, 0, canvas.width, canvas.height); - - // Pick up the pen - ctx.beginPath(); - // Start the arc to form a circle - ctx.arc(125, 125, 100, 0, Math.PI * 2, true); - // Put the pen down - ctx.closePath(); - // Clip off the region you drew on - ctx.clip(); - - const avatar = await Canvas.loadImage(member.user.displayAvatarURL({ format: 'jpg' })); - ctx.drawImage(avatar, 25, 25, 200, 200); - - const attachment = new Discord.MessageAttachment(canvas.toBuffer(), 'welcome-image.png'); - - channel.send(`Welcome to the server, ${member}!`, attachment); -}); -``` - - - -![Image](~@/images/r6CiT3M.png) - -::: tip -You can read more about `ctx.arc()` on [w3schools](https://www.w3schools.com/tags/canvas_arc.asp) or [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/arc). -::: - -### Adding in text - -Now, let's quickly go over adding text to your image. This will be helpful to make the purpose of this image very clear, since currently it's just an avatar floating on a starry background that comes out of nowhere. - - - -```js -client.on('guildMemberAdd', async member => { - const channel = member.guild.channels.find(ch => ch.name === 'member-log'); - if (!channel) return; - - const canvas = Canvas.createCanvas(700, 250); - const ctx = canvas.getContext('2d'); - - const background = await Canvas.loadImage('./wallpaper.jpg'); - ctx.drawImage(background, 0, 0, canvas.width, canvas.height); - - ctx.strokeStyle = '#74037b'; - ctx.strokeRect(0, 0, canvas.width, canvas.height); - - // Select the font size and type from one of the natively available fonts - ctx.font = '60px sans-serif'; - // Select the style that will be used to fill the text in - ctx.fillStyle = '#ffffff'; - // Actually fill the text with a solid color - ctx.fillText(member.displayName, canvas.width / 2.5, canvas.height / 1.8); - - ctx.beginPath(); - ctx.arc(125, 125, 100, 0, Math.PI * 2, true); - ctx.closePath(); - ctx.clip(); - - const avatar = await Canvas.loadImage(member.user.displayAvatarURL); - ctx.drawImage(avatar, 25, 25, 200, 200); - - const attachment = new Discord.Attachment(canvas.toBuffer(), 'welcome-image.png'); - - channel.send(`Welcome to the server, ${member}!`, attachment); -}); -``` - - - - -```js -client.on('guildMemberAdd', async member => { - const channel = member.guild.channels.find(ch => ch.name === 'member-log'); - if (!channel) return; - - const canvas = Canvas.createCanvas(700, 250); - const ctx = canvas.getContext('2d'); - - const background = await Canvas.loadImage('./wallpaper.jpg'); - ctx.drawImage(background, 0, 0, canvas.width, canvas.height); - - ctx.strokeStyle = '#74037b'; - ctx.strokeRect(0, 0, canvas.width, canvas.height); - - // Select the font size and type from one of the natively available fonts - ctx.font = '60px sans-serif'; - // Select the style that will be used to fill the text in - ctx.fillStyle = '#ffffff'; - // Actually fill the text with a solid color - ctx.fillText(member.displayName, canvas.width / 2.5, canvas.height / 1.8); - - ctx.beginPath(); - ctx.arc(125, 125, 100, 0, Math.PI * 2, true); - ctx.closePath(); - ctx.clip(); - - const avatar = await Canvas.loadImage(member.user.displayAvatarURL({ format: 'jpg' })); - ctx.drawImage(avatar, 25, 25, 200, 200); - - const attachment = new Discord.MessageAttachment(canvas.toBuffer(), 'welcome-image.png'); - - channel.send(`Welcome to the server, ${member}!`, attachment); -}); -``` - - - -![Image](~@/images/3rLGb1s.png) - -::: tip -If you get an error like `Fontconfig error: Cannot load default config file`, it means you do not have any fonts installed on your system. On Linux, you can run the following command to fix this: `sudo apt-get install fontconfig`. This might also need to be installed if you see boxes where the text should be. As for Windows, you will need to find a way to install fonts. -::: - -You may have noticed or considered that if a member's username is too long, then the output won't be quite nice. This is because the text overflows out of the canvas, and you don't have any measures in place for that. Let's take care of this issue! - - - -```js -// Pass the entire Canvas object because you'll need to access its width, as well its context -const applyText = (canvas, text) => { - const ctx = canvas.getContext('2d'); - - // Declare a base size of the font - let fontSize = 70; - - do { - // Assign the font to the context and decrement it so it can be measured again - ctx.font = `${fontSize -= 10}px sans-serif`; - // Compare pixel width of the text to the canvas minus the approximate avatar size - } while (ctx.measureText(text).width > canvas.width - 300); - - // Return the result to use in the actual canvas - return ctx.font; -}; - -client.on('guildMemberAdd', async member => { - const channel = member.guild.channels.find(ch => ch.name === 'member-log'); - if (!channel) return; - - const canvas = Canvas.createCanvas(700, 250); - const ctx = canvas.getContext('2d'); - - const background = await Canvas.loadImage('./wallpaper.jpg'); - ctx.drawImage(background, 0, 0, canvas.width, canvas.height); - - ctx.strokeStyle = '#74037b'; - ctx.strokeRect(0, 0, canvas.width, canvas.height); - - // Assign the decided font to the canvas - ctx.font = applyText(canvas, member.displayName); - ctx.fillStyle = '#ffffff'; - ctx.fillText(member.displayName, canvas.width / 2.5, canvas.height / 1.8); - - ctx.beginPath(); - ctx.arc(125, 125, 100, 0, Math.PI * 2, true); - ctx.closePath(); - ctx.clip(); - - const avatar = await Canvas.loadImage(member.user.displayAvatarURL); - ctx.drawImage(avatar, 25, 25, 200, 200); - - const attachment = new Discord.Attachment(canvas.toBuffer(), 'welcome-image.png'); - - channel.send(`Welcome to the server, ${member}!`, attachment); -}); -``` - - - - -```js -// Pass the entire Canvas object because you'll need to access its width, as well its context -const applyText = (canvas, text) => { - const ctx = canvas.getContext('2d'); - - // Declare a base size of the font - let fontSize = 70; - - do { - // Assign the font to the context and decrement it so it can be measured again - ctx.font = `${fontSize -= 10}px sans-serif`; - // Compare pixel width of the text to the canvas minus the approximate avatar size - } while (ctx.measureText(text).width > canvas.width - 300); - - // Return the result to use in the actual canvas - return ctx.font; -}; - -client.on('guildMemberAdd', async member => { - const channel = member.guild.channels.find(ch => ch.name === 'member-log'); - if (!channel) return; - - const canvas = Canvas.createCanvas(700, 250); - const ctx = canvas.getContext('2d'); - - const background = await Canvas.loadImage('./wallpaper.jpg'); - ctx.drawImage(background, 0, 0, canvas.width, canvas.height); - - ctx.strokeStyle = '#74037b'; - ctx.strokeRect(0, 0, canvas.width, canvas.height); - - // Assign the decided font to the canvas - ctx.font = applyText(canvas, member.displayName); - ctx.fillStyle = '#ffffff'; - ctx.fillText(member.displayName, canvas.width / 2.5, canvas.height / 1.8); - - ctx.beginPath(); - ctx.arc(125, 125, 100, 0, Math.PI * 2, true); - ctx.closePath(); - ctx.clip(); - - const avatar = await Canvas.loadImage(member.user.displayAvatarURL({ format: 'jpg' })); - ctx.drawImage(avatar, 25, 25, 200, 200); - - const attachment = new Discord.MessageAttachment(canvas.toBuffer(), 'welcome-image.png'); - - channel.send(`Welcome to the server, ${member}!`, attachment); -}); -``` - - - -Before adjustment: - -![Before adjustment](~@/images/NKw7P2q.png) - -After adjustment: - -![After adjustment](~@/images/Ja4Ywf4.png) - -As a nice finishing touch, let's move the welcome text inside the image itself instead of adding it outside. - - - -```js -client.on('guildMemberAdd', async member => { - const channel = member.guild.channels.find(ch => ch.name === 'member-log'); - if (!channel) return; - - const canvas = Canvas.createCanvas(700, 250); - const ctx = canvas.getContext('2d'); - - const background = await Canvas.loadImage('./wallpaper.jpg'); - ctx.drawImage(background, 0, 0, canvas.width, canvas.height); - - ctx.strokeStyle = '#74037b'; - ctx.strokeRect(0, 0, canvas.width, canvas.height); - - // Slightly smaller text placed above the member's display name - ctx.font = '28px sans-serif'; - ctx.fillStyle = '#ffffff'; - ctx.fillText('Welcome to the server,', canvas.width / 2.5, canvas.height / 3.5); - - // Add an exclamation point here and below - ctx.font = applyText(canvas, `${member.displayName}!`); - ctx.fillStyle = '#ffffff'; - ctx.fillText(`${member.displayName}!`, canvas.width / 2.5, canvas.height / 1.8); - - ctx.beginPath(); - ctx.arc(125, 125, 100, 0, Math.PI * 2, true); - ctx.closePath(); - ctx.clip(); - - const avatar = await Canvas.loadImage(member.user.displayAvatarURL); - ctx.drawImage(avatar, 25, 25, 200, 200); - - const attachment = new Discord.MessageAttachment(canvas.toBuffer(), 'welcome-image.png'); - - channel.send(`Welcome to the server, ${member}!`, attachment); -}); -``` - - - - -```js -client.on('guildMemberAdd', async member => { - const channel = member.guild.channels.find(ch => ch.name === 'member-log'); - if (!channel) return; - - const canvas = Canvas.createCanvas(700, 250); - const ctx = canvas.getContext('2d'); - - const background = await Canvas.loadImage('./wallpaper.jpg'); - ctx.drawImage(background, 0, 0, canvas.width, canvas.height); - - ctx.strokeStyle = '#74037b'; - ctx.strokeRect(0, 0, canvas.width, canvas.height); - - // Slightly smaller text placed above the member's display name - ctx.font = '28px sans-serif'; - ctx.fillStyle = '#ffffff'; - ctx.fillText('Welcome to the server,', canvas.width / 2.5, canvas.height / 3.5); - - // Add an exclamation point here and below - ctx.font = applyText(canvas, `${member.displayName}!`); - ctx.fillStyle = '#ffffff'; - ctx.fillText(`${member.displayName}!`, canvas.width / 2.5, canvas.height / 1.8); - - ctx.beginPath(); - ctx.arc(125, 125, 100, 0, Math.PI * 2, true); - ctx.closePath(); - ctx.clip(); - - const { body: buffer } = await snekfetch.get(member.user.displayAvatarURL); - const avatar = await Canvas.loadImage(buffer); - ctx.drawImage(avatar, 25, 25, 200, 200); - - const attachment = new Discord.MessageAttachment(canvas.toBuffer(), 'welcome-image.png'); - - channel.send(`Welcome to the server, ${member}!`, attachment); -}); -``` - - - -![Final result](~@/images/DDzEgdZ.png) - -And that's it! We have covered the basics of image manipulation, text generation, and loading from a remote source. - -## Resulting code - - diff --git a/Ajuda/guide-master/guide/popular-topics/collectors.md b/Ajuda/guide-master/guide/popular-topics/collectors.md deleted file mode 100644 index a10e41b..0000000 --- a/Ajuda/guide-master/guide/popular-topics/collectors.md +++ /dev/null @@ -1,161 +0,0 @@ -# Collectors - -## Message collectors - -Collectors are a useful way to enable your bot to obtain *additional* input after the first command was sent. An example would be initiating a quiz, where the bot will "await" a correct response from somebody. - -::: tip -You can read the docs for the Collector class [here](https://discord.js.org/#/docs/main/11.5.1/class/Collector)[here](https://discord.js.org/#/docs/main/master/class/Collector). -::: - -### Basic message collector - -For now, let's take the example that they have provided us: - -```js -// `m` is a message object that will be passed through the filter function -const filter = m => m.content.includes('discord'); -const collector = message.channel.createMessageCollector(filter, { time: 15000 }); - -collector.on('collect', m => { - console.log(`Collected ${m.content}`); -}); - -collector.on('end', collected => { - console.log(`Collected ${collected.size} items`); -}); -``` - -In the first argument of `.createMessageCollector()`, it specifies that it requires a function. This function should ideally return a boolean, which would indicate whether or not the message should pass through the collector's filter. This filter function includes implicit return, which means that (in this case), it will return the value of `m.content.includes('discord')` without actually specifying `return`. This happens when you use arrow functions without braces. - -You can also allow more than one condition, as you would with any function. An alternative could be `m => m.content.includes('discord') && m.author.id === message.author.id`, assuming `message` is the name of what you receive in the `message` event. This function will only allow a message that was sent by the person who triggered the command *and* if the message content included "discord" in it. - -After a message passes through, this will trigger the `collect` event for the `collector` you've created, which will then run the provided function. In this case, it will simply log the collected message. Once the collector finishes, one way or another, it will run the `end` event. A collector can end in different ways, such as: - -* Time running out -* A certain number of messages passing the filter -* A certain number of attempts to go through the filter altogether - -Those options you pass as the second argument in `.createMessageCollector()`. The benefit of using this method over `.awaitMessages()` is that you can stop it manually by calling `collector.stop()`, should you have your own reason to interrupt the collecting early. - -### Await messages - -Using `.awaitMessages()` can be easier if you understand promises, and it allows you to have cleaner code overall. It is essentially identical to `.createMessageCollector()`, except promisified. The drawback of using this method, however, is that you cannot do things before the promise is resolved or rejected, either by an error or completion. However, it should do for most purposes, such as awaiting the correct response in a quiz. Instead of taking their example, let's set up a basic quiz command using the `.awaitMessages()` feature. - -::: tip -You can read the docs for the `.awaitMessages()` method [here](https://discord.js.org/#/docs/main/11.5.1/class/TextChannel?scrollTo=awaitMessages)[here](https://discord.js.org/#/docs/main/master/class/TextChannel?scrollTo=awaitMessages). -::: - -First, you'll need some questions and answers to choose from, so here's a basic set: - -```json -[ - { - "question": "What colour is the sky?", - "answers": ["blue"] - }, - { - "question": "How many letters are there in the alphabet?", - "answers": ["26", "twenty-six", "twenty six", "twentysix"] - } -] -``` - -The provided set allows for responder error with an array of answers allowed. Ideally, you should place this in a json file, which you can call `quiz.json` for simplicity. - - - -```js -const quiz = require('./quiz.json'); -const item = quiz[Math.floor(Math.random() * quiz.length)]; -const filter = response => { - return item.answers.some(answer => answer.toLowerCase() === response.content.toLowerCase()); -}; - -message.channel.send(item.question).then(() => { - message.channel.awaitMessages(filter, { maxMatches: 1, time: 30000, errors: ['time'] }) - .then(collected => { - message.channel.send(`${collected.first().author} got the correct answer!`); - }) - .catch(collected => { - message.channel.send('Looks like nobody got the answer this time.'); - }); -}); -``` - - - - -```js -const quiz = require('./quiz.json'); -const item = quiz[Math.floor(Math.random() * quiz.length)]; -const filter = response => { - return item.answers.some(answer => answer.toLowerCase() === response.content.toLowerCase()); -}; - -message.channel.send(item.question).then(() => { - message.channel.awaitMessages(filter, { max: 1, time: 30000, errors: ['time'] }) - .then(collected => { - message.channel.send(`${collected.first().author} got the correct answer!`); - }) - .catch(collected => { - message.channel.send('Looks like nobody got the answer this time.'); - }); -}); -``` - - - -::: tip -If you don't understand how `.some()` works, you can read about it in more detail [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some). -::: - -In this filter, you iterate through the answers to find what you want. You would like to ignore case because simple typos can happen, so you convert each answer to its lowercase form, and check if it's equal to the response in lowercase form as well. In the options section, you only want to allow one answer to pass through, hence the `maxMatches: 1``max: 1` setting. - -The filter looks for messages that match one of the answers in our array of possible answers in order to pass through the collector. In the options (the second parameter), it's specified that only a maximum of 1 message can go through the filter successfully before the promise will successfully resolve. In the errors section, it's specified that time will cause it to error out, which will cause the promise to reject if 1 correct answer is not received within the time limit of 1 minute. As you can see, there is no `collect` event, so you are limited in that regard. - -## Reaction collectors - -### Basic reaction collector - -These work quite similarly to message collectors, except that you apply them on a message rather than a channel. The following is an example taken from the documentation, with slightly better variable names for clarification. The filter will check for the 👌 emoji - in the default skin tone specifically, so be wary of that. It will also check that the person who reacted shares the same id as the author of the original message that the collector was assigned to. - -::: tip -You can read the docs for the `.createReactionCollector()` method [here](https://discord.js.org/#/docs/main/11.5.1/class/Message?scrollTo=createReactionCollector)[here](https://discord.js.org/#/docs/main/master/class/Message?scrollTo=createReactionCollector). -::: - -```js -const filter = (reaction, user) => { - return reaction.emoji.name === '👌' && user.id === message.author.id; -}; - -const collector = message.createReactionCollector(filter, { time: 15000 }); - -collector.on('collect', (reaction, reactionCollector) => { - console.log(`Collected ${reaction.emoji.name}`); -}); - -collector.on('end', collected => { - console.log(`Collected ${collected.size} items`); -}); -``` - -### Await reactions - -As before, these work almost exactly the same as a reaction collector, except it is promise based. The same differences apply as with channel collectors. - -::: tip -You can read the docs for the `.awaitReactions()` method [here](https://discord.js.org/#/docs/main/11.5.1/class/Message?scrollTo=awaitReactions)[here](https://discord.js.org/#/docs/main/master/class/Message?scrollTo=awaitReactions). -::: - -```js -const filter = (reaction, user) => { - return reaction.emoji.name === '👌' && user.id === message.author.id; -}; - -message.awaitReactions(filter, { max: 4, time: 60000, errors: ['time'] }) - .then(collected => console.log(collected.size)) - .catch(collected => { - console.log(`After a minute, only ${collected.size} out of 4 reacted.`); - }); -``` diff --git a/Ajuda/guide-master/guide/popular-topics/common-questions.md b/Ajuda/guide-master/guide/popular-topics/common-questions.md deleted file mode 100644 index 8c6bbb1..0000000 --- a/Ajuda/guide-master/guide/popular-topics/common-questions.md +++ /dev/null @@ -1,299 +0,0 @@ -# Common questions - -## Legend - -* `` is a placeholder for the Client object, such as `const client = new Discord.Client();`. -* `` is a placeholder for the Message object, such as `client.on('message', message => { ... });`. -* `` is a placeholder for the Guild object, such as `.guild` or `.guilds.get('')`. - -For a more detailed explanation on the notations commonly used in this guide, the docs, and the support server, see [here](/additional-info/notation.md). - -## Administrative - -### How do I ban a user? - - - -```js -const user = .mentions.users.first(); -.ban(user); -``` - -### How do I kick a user? - - - -```js -const member = .mentions.members.first(); -member.kick(); -``` - -### How do I add a role to a guild member? - - - - - -```js -const role = .roles.find(role => role.name === ''); -const member = .mentions.members.first(); -member.addRole(role); -``` - - - - - - -```js -const role = .roles.find(role => role.name === ''); -const member = .mentions.members.first(); -member.roles.add(role); -``` - - - -### How do I check if a guild member has a certain role? - - - -```js -const member = .mentions.members.first(); -if (member.roles.some(role => role.name === '')) { - // ... -} -``` - -### How do I limit a command to a single user? - - - -```js -if (.author.id === '') { - // ... -} -``` - -## Bot Configuration - -### How do I set my username? - - - -```js -.user.setUsername(''); -``` - -### How do I set my avatar? - - - -```js -.user.setAvatar(''); -``` - -### How do I set my playing status? - - - -```js -.user.setActivity(''); -``` - -### How do I set my status to "Watching ..." or "Listening to ..."? - - - -```js -.user.setActivity('', { type: 'WATCHING' }); -.user.setActivity('', { type: 'LISTENING' }); -``` - - - -::: tip -If you would like to set your activity upon startup, you must place the `.user.setActivity()` method in a `ready` event listener (`.on('ready', () => {});`). -::: - -::: warning -`.user.setActivity()` will only work in v11.3 and above. You can check your version with `npm ls discord.js` and update with `npm install discord.js`. You can still use `.user.setGame()`, but it is deprecated as of v11.3, and has been removed in v12. -::: - - - - -::: tip -If you would like to set your activity upon startup, you can use the `ClientOptions` object to set the appropriate `Presence` data. -::: - - - -## Miscellaneous - -### How do I send a message to a certain channel? - - - -```js -const channel = .channels.get(''); -channel.send(''); -``` - -### How do I DM a certain user? - - - -```js -const user = .users.get(''); -user.send(''); -``` - -::: tip -If you want to DM the user who sent the message, you can use `.author.send()`. -::: - -### How do I tag a certain user in a message? - - - -```js -const user = .mentions.users.first(); -.channel.send(`Hi, ${user}.`); -.channel.send('Hi, <@user id>.'); -``` - -::: tip -If you want to tag the user who sent the message, you can use `.reply()`. For example: `.reply('hi.')` would result in `@User, hi.`. If you want to insert the tag elsewhere, you can store `.author` as your `user` variable and use the original example. -::: - -::: tip -Tags inside certain areas of an embed may display correctly, but will not actually ping the user. Tags inside other certain areas of an embed will display the raw string instead (e.g. `<@123456789012345678>`). -::: - -### How do I prompt the user for additional input? - - - - - -```js -.channel.send('Please enter more input.').then(() => { - const filter = m => .author.id === m.author.id; - - .channel.awaitMessages(filter, { time: 60000, maxMatches: 1, errors: ['time'] }) - .then(messages => { - .channel.send(`You've entered: ${messages.first().content}`); - }) - .catch(() => { - .channel.send('You did not enter any input!'); - }); -}); -``` - - - - - - -```js -.channel.send('Please enter more input.').then(() => { - const filter = m => .author.id === m.author.id; - - .channel.awaitMessages(filter, { time: 60000, max: 1, errors: ['time'] }) - .then(messages => { - .channel.send(`You've entered: ${messages.first().content}`); - }) - .catch(() => { - .channel.send('You did not enter any input!'); - }); -}); -``` - - - -::: tip -If you want to learn more about this syntax or want to learn about reaction collectors as well, check out [this dedicated guide page for collectors](/popular-topics/collectors.md)! -::: - -### How do I react to the message my bot sent? - - - -```js -.channel.send('My message to react to.').then(sentMessage => { - sentMessage.react('👍'); - sentMessage.react(''); -}); -``` - -::: tip -If you want to learn more about reactions, check out [this dedicated guide on reactions](/popular-topics/reactions.md)! -::: - -### How do I create a restart command? - -```js -process.exit(); -``` - -::: tip -`process.exit()` will only kill your Node process, but when using [PM2](http://pm2.keymetrics.io/), it will restart the process whenever it gets killed. You can read our guide on PM2 [here](/improving-dev-environment/pm2.md). -::: - -::: warning -Be sure to [limit this to your own ID](/popular-topics/common-questions.md#how-do-i-limit-a-command-to-a-single-user) so that other users can't restart your bot! -::: - -### What is the difference between a User and a GuildMember? - -A lot of users get confused as to what the difference between Users and GuildMembers is. The simple answer is that a User represents a global Discord user and a GuildMember represents a Discord user on a specific server. That means only GuildMembers can have permissions, roles, and nicknames, for example, because all of these things are server-bound information that could be different on each server that user is in. - -### How do I find all online members? - -Assuming the process is to be done for the guild the message is sent in. - - - - - -```js -// First we use fetchMembers to make sure all members are cached -.guild.fetchMembers().then(fetchedGuild => { - const totalOnline = fetchedGuild.members.filter(member => member.presence.status === 'online'); - // We now have a collection with all online member objects in the totalOnline variable - .channel.send(`There are currently ${totalOnline.size} members online in this guild!`); -}); -``` - - - - - - -```js -// First we use guild.members.fetch to make sure all members are cached -.guild.members.fetch().then(fetchedMembers => { - const totalOnline = fetchedMembers.filter(member => member.presence.status === 'online'); - // We now have a collection with all online member objects in the totalOnline variable - .channel.send(`There are currently ${totalOnline.size} members online in this guild!`); -}); -``` - - - -### How do I check which role was added/removed, and for which member? - - - -```js -// We start by declaring a guildMemberUpdate listener -// This code should be placed outside of any other listener callbacks to prevent listener nesting -.on('guildMemberUpdate', (oldMember, newMember) => { - // If the role(s) are present on the old member object but no longer on the new one (i.e role(s) were removed) - const removedRoles = oldMember.roles.filter(role => !newMember.roles.has(role.id)); - if(removedRoles.size > 0) console.log(`The roles ${removedRoles.map(r => r.name)} were added to ${oldMember.displayName}.`); - // If the role(s) are present on the new member object but are not on the new one (i.e role(s) were added) - const addedRoles = newMember.roles.filter(role => !oldMember.roles.has(role.id)); - if(addedRoles.size > 0) console.log(`The roles ${addedRoles.map(r => r.name)} were removed from ${oldMember.displayName}.`); -}); -``` diff --git a/Ajuda/guide-master/guide/popular-topics/embeds.md b/Ajuda/guide-master/guide/popular-topics/embeds.md deleted file mode 100644 index 1e7d66b..0000000 --- a/Ajuda/guide-master/guide/popular-topics/embeds.md +++ /dev/null @@ -1,355 +0,0 @@ -# Embeds - -If you have been around on Discord for a bit chances are you have seen these special messages. -They have a colored border, are often sent by bots and have embedded images, text fields and other fancy stuff. - -In the following section we will explain how you compose an embed, send it, and what you need to be aware of while doing so. - -## Embed preview - -Here is an example of what an embed may look like. We will go over their construction in the next part of this guide. - -
- - - Some description here - - - Some value here - - - ​ - - - Some value here - - - Some value here - - - Some value here - - - Some footer text here - - -
- -## Using the RichEmbedMessageEmbed constructor - -Discord.js features the utility class [RichEmbed](https://discord.js.org/#/docs/main/11.5.1/class/MessageEmbed)[MessageEmbed](https://discord.js.org/#/docs/main/master/class/MessageEmbed) for easy construction and manipulation of embeds. - - - -::: warning -On the master branch, the receiving and outgoing embed classes have been unified; you will need to use `Discord.MessageEmbed()` as constructor instead. -::: - -```js -// at the top of your file -const Discord = require('discord.js'); - -// inside a command, event listener, etc. -const exampleEmbed = new Discord.RichEmbed() - .setColor('#0099ff') - .setTitle('Some title') - .setURL('https://discord.js.org/') - .setAuthor('Some name', 'https://i.imgur.com/wSTFkRM.png', 'https://discord.js.org') - .setDescription('Some description here') - .setThumbnail('https://i.imgur.com/wSTFkRM.png') - .addField('Regular field title', 'Some value here') - .addBlankField() - .addField('Inline field title', 'Some value here', true) - .addField('Inline field title', 'Some value here', true) - .addField('Inline field title', 'Some value here', true) - .setImage('https://i.imgur.com/wSTFkRM.png') - .setTimestamp() - .setFooter('Some footer text here', 'https://i.imgur.com/wSTFkRM.png'); - -channel.send(exampleEmbed); -``` - - - - -```js -// at the top of your file -const Discord = require('discord.js'); - -// inside a command, event listener, etc. -const exampleEmbed = new Discord.MessageEmbed() - .setColor('#0099ff') - .setTitle('Some title') - .setURL('https://discord.js.org/') - .setAuthor('Some name', 'https://i.imgur.com/wSTFkRM.png', 'https://discord.js.org') - .setDescription('Some description here') - .setThumbnail('https://i.imgur.com/wSTFkRM.png') - .addField('Regular field title', 'Some value here') - .addBlankField() - .addField('Inline field title', 'Some value here', true) - .addField('Inline field title', 'Some value here', true) - .addField('Inline field title', 'Some value here', true) - .setImage('https://i.imgur.com/wSTFkRM.png') - .setTimestamp() - .setFooter('Some footer text here', 'https://i.imgur.com/wSTFkRM.png'); - -channel.send(exampleEmbed); -``` - - - -::: tip -You don't need to include all the elements showcased above. If you want a simpler embed, just leave some out. -::: - -The `.setColor()` method accepts an integer, HEX color string, an array of RGB values or specific color strings. You can find a list of them at [the Discord.js documentation](https://discord.js.org/#/docs/main/11.5.1/typedef/ColorResolvable)[the Discord.js documentation](https://discord.js.org/#/docs/main/master/typedef/ColorResolvable). - -`.addBlankField()` is a convenience method for `.addField('\u200b', '\u200b')` to add a spacer to the embed. This can also be used inline by passing `true` as the first parameter. - -The above example chains the manipulating methods to the newly created RichEmbedMessageEmbed object. -If you want to modify the embed based on conditions you will need to reference it as the constant `exampleEmbed` (for our example). - - - - - -```js -const exampleEmbed = new Discord.RichEmbed().setTitle('Some title'); - -if (message.author.bot) { - exampleEmbed.setColor('#7289da'); -} -``` - - - - - - -```js -const exampleEmbed = new Discord.MessageEmbed().setTitle('Some title'); - -if (message.author.bot) { - exampleEmbed.setColor('#7289da'); -} -``` - - - -### Local images - -To use local images inside your embed, you need to upload them alongside the embed with the `.attachFiles()` method. You can either provide the file path [FileOptions](https://discord.js.org/#/docs/main/11.5.1/typedef/FileOptions)[FileOptions](https://discord.js.org/#/docs/main/master/typedef/FileOptions), BufferResolvable, or Attachment objects inside an array. - -You can then access and use the images inside the embed itself with `attachment://fileName.extension`. - - - -```js -const exampleEmbed = new Discord.RichEmbed() - .setTitle('Some title') - .attachFiles(['../assets/discordjs.png']) - .setImage('attachment://discordjs.png'); - -channel.send(exampleEmbed); -``` - - - - -```js -const exampleEmbed = new Discord.MessageEmbed() - .setTitle('Some title') - .attachFiles(['../assets/discordjs.png']) - .setImage('attachment://discordjs.png'); - -channel.send(exampleEmbed); -``` - - - -::: warning -If the images doesn't display inside the embed but outside of it, double check your syntax to make sure it's as shown above. -::: - -## Using an embed object - - - -```js -const exampleEmbed = { - color: 0x0099ff, - title: 'Some title', - url: 'https://discord.js.org', - author: { - name: 'Some name', - icon_url: 'https://i.imgur.com/wSTFkRM.png', - url: 'https://discord.js.org', - }, - description: 'Some description here', - thumbnail: { - url: 'https://i.imgur.com/wSTFkRM.png', - }, - fields: [ - { - name: 'Regular field title', - value: 'Some value here', - }, - { - name: '\u200b', - value: '\u200b', - }, - { - name: 'Inline field title', - value: 'Some value here', - inline: true, - }, - { - name: 'Inline field title', - value: 'Some value here', - inline: true, - }, - { - name: 'Inline field title', - value: 'Some value here', - inline: true, - }, - ], - image: { - url: 'https://i.imgur.com/wSTFkRM.png', - }, - timestamp: new Date(), - footer: { - text: 'Some footer text here', - icon_url: 'https://i.imgur.com/wSTFkRM.png', - }, -}; - -channel.send({ embed: exampleEmbed }); -``` - -::: tip -You don't need to include all the elements showcased above. If you want a simpler embed, just leave some out. -::: - -::: warning -The `color` field has to be an integer for embed objects! If you have a hex color string (e.g. `'#7289da'`) you can replace the `#` with `0x` to use it as a number: `0x7289da`. -::: - -If you want to modify the embed object based on conditions you will need to reference it directly (as `exampleEmbed` for our example). You can then (re)assign the property values as you would with any other object. - -```js -const exampleEmbed = { title: 'Some title' }; - -if (message.author.bot) { - exampleEmbed.color = 0x7289da; -} -``` - -### Local images - -To use local images inside your embed you need to construct an [Attachment](https://discord.js.org/#/docs/main/11.5.1/class/Attachment)a [MessageAttachment](https://discord.js.org/#/docs/main/master/class/MessageAttachment) from them to send as message option alongside the embed. - -You can then access and use the images inside the embed itself with `attachment://fileName.extension`. - - - -```js -const file = new Discord.Attachment('../assets/discordjs.png'); - -const exampleEmbed = { - title: 'Some title', - image: { - url: 'attachment://discordjs.png', - }, -}; - -channel.send({ files: [file], embed: exampleEmbed }); -``` - - - - -```js -const file = new Discord.MessageAttachment('../assets/discordjs.png'); - -const exampleEmbed = { - title: 'Some title', - image: { - url: 'attachment://discordjs.png', - }, -}; - -channel.send({ files: [file], embed: exampleEmbed }); -``` - - - -::: warning -If the images doesn't display inside the embed but outside of it, double check your syntax to make sure it's as shown above. -::: - -## Resending embeds - -At some point in your bot development, you might want to get an embed from a message that you're receiving, edit it, and send it again. - -To achieve this, you retrieve the embed from the messages embed array (`message.embeds`) and pass it to the MessageEmbed constructor. The constructed MessageEmbed can then be edited before sending it again. - -You can not resend the received embed structure! The MessageEmbed returned from `message.embeds` contains circular structures and needs to be converted to a RichEmbed object before sending.We deliberately create a new Embed here instead of just modifying `message.embeds[0]` directly to keep the cache valid. If we were to not do this the embed in cache on the original message would diverge from what the actual embed looks like, which can result in unexpected behaviour down the line! - - - -```js -const receivedEmbed = message.embeds[0]; -const exampleEmbed = new Discord.RichEmbed(receivedEmbed).setTitle('New title'); - -channel.send(exampleEmbed); -``` - - - - -```js -const receivedEmbed = message.embeds[0]; -const exampleEmbed = new Discord.MessageEmbed(receivedEmbed).setTitle('New title'); - -channel.send(exampleEmbed); -``` - - - -## Notes - -- To display fields side-by-side, you need at least two consecutive fields set to `inline` -- By default, up to 3 fields will display inline. If a thumbnail is set, this will change to 2 -- The timestamp will automatically adjust the timezone depending on the user's device -- Mentions of any kind will only render correctly in field values and descriptions -- Mentions in embeds will not trigger a notification -- Embeds allow masked links (e.g. `[Guide](https://discordjs.guide/ 'optional hovertext')`), but only in description and field values - -## Embed limits - -There are a few limits to be aware of while planning your embeds due to limitations set by the API. Here is a quick reference you can come back to: - -- Embed titles are limited to 256 characters -- Embed descriptions are limited to 2048 characters -- There can be up to 25 fields -- A field's name is limited to 256 characters and its value to 1024 characters -- The footer text is limited to 2048 characters -- The author name is limited to 256 characters -- In addition, the sum of all characters in an embed structure must not exceed 6000 characters -- A bot can have 1 embed per message -- A webhook can have 10 embeds per message - -Source: [Discord API documentation](https://discordapp.com/developers/docs/resources/channel#embed-limits) diff --git a/Ajuda/guide-master/guide/popular-topics/errors.md b/Ajuda/guide-master/guide/popular-topics/errors.md deleted file mode 100644 index 4b75782..0000000 --- a/Ajuda/guide-master/guide/popular-topics/errors.md +++ /dev/null @@ -1,235 +0,0 @@ -# Errors - -There is no doubt that you have encountered errors while making bots. While errors are very useful at warning you of what is going wrong, many people are stumped by them and how to track them down and fix them, but don't worry, we have you covered. This section will be all about how to diagnose errors, how to identify where they are coming from, and how to fix them. - -## Types of Errors - -### API Errors - -API Errors or DiscordAPIErrors are errors which are thrown by the Discord API when an invalid request is carried out. API Errors can be mostly diagnosed using the message that is given. They can also be further examined by seeing the http method and path used, we will explore tracking these errors down in the next section. - -Example: `DiscordAPIError: Cannot send an empty message` - -### Discord.js Errors - -Discord.js Errors are errors which are thrown by the library itself, they can usually be easily tracked down using the stacktrace and error message. - -Example: `The messages must be an Array, Collection, or number.` - -### JS Errors - -JS Errors are simple errors which can be thrown by node itself, or by discord.js. These types of errors can easily be fixed by looking at the type of error, and the stacktrace. You can find a full list of types [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) And a list of common js errors [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors). - -Example: `ReferenceError: "x" is not defined` - -### Websocket and Network Errors - -Websocket and Network errors are common system errors thrown by Node in response to something wrong with the websocket connection. Unfortunately, these errors do not have a concrete solution and can be (usually) fixed by getting a better, more stable, and stronger connection. Discord.js will automatically try to reconnect to the websocket if an error occurs. - - - -Normally these errors will crash your process, however, you can add an event listener for these errors which will notify you of them and it won't crash your process as shown below. - -```js -client.on('error', error => { - console.error('The websocket connection encountered an error:', error); -}); -``` - -Now, when an error occurs it will be logged to the console and it will not terminate the process. - - - - - -On master, WebSocket errors are handled internally, meaning your process should never crash from them. If you want to log these errors, should they happen, you can listen to the `shardError` event as shown below. - -```js -client.on('shardError', error => { - console.error('A websocket connection encountered an error:', error); -}); -``` - - - -The commonly thrown codes for these errors are: -- `ECONNRESET` - The connection was forcibly closed by a peer, thrown by the loss of connection to a websocket due to timeout or reboot. -- `ETIMEDOUT` - A connect or send request failed because the receiving party did not respond after some time. -- `EPIPE` - The remote side of the stream being written to has been closed. -- `ENOTFOUND` - The domain being accessed is unavailable, usually caused by a lack of internet, can be thrown by the websocket and http API. -- `ECONNREFUSED` - The target machine refused the connection, check your ports and firewall. - -## How to diagnose API errors - -API Errors can be tracked down by adding an event listener for unhandled rejections and looking at the extra info that is given. -This can be done by easily adding this to your main file. - -```js -process.on('unhandledRejection', error => { - console.error('Unhandled promise rejection:', error); -}); -``` - -The next time you get the error it will show info along the bottom of the error which will look something like this for example: - -```json - name: 'DiscordAPIError', - message: 'Invalid Form Body\nmessage_id: Value "[object Object]" is not snowflake.', - path: '/api/v7/channels/638200642359525387/messages/[object%20Object]', - code: 50035, - method: 'GET' -``` - -All of this information can help you track down what caused the error and how to fix it. In this section we will run through what each property means. - -### Message - -The most important part of the error is the message, it tells you what actually went wrong which can help you track down where it came from. -You can find a full list of messages [here](https://discordapp.com/developers/docs/topics/opcodes-and-status-codes#json) in the Discord API Docs. - -### Path - -The path is another helpful piece of information, the path tells you where you tried to execute an action. We cannot possibly cover all API paths but they are usually very descriptive, for example, in our example above the path tells us we are first in the channels path, then judging by the id after it we can see we got a specific channel. After the `/api/v7/channels/638200642359525387` we can see that we get the `messages` of that channel, and in the same way we saw before, we see we try to access a specific message by id, however we gave it an invalid id, which is the origin of the message. - -### Code - -The code is another partial representation of the message, in this case `Invalid Form Body`. You can find a full list of codes [here](https://discordapp.com/developers/docs/topics/opcodes-and-status-codes#json-json-error-codes) - -The code is also very useful if you want to only handle a specific error. Say we were trying to delete a message which may or may not be there, and we wanted to simply ignore unknown message errors. This can be done by checking the code, either manually, or using discord.js's constants. - -```js -message.delete().catch(error => { - // Only log the error if it is not an Unknown Message error - if (error.code !== 10008) { - console.error('Failed to delete the message:', error); - } -}); -``` - -Or using Constants: - -```js -message.delete().catch(error => { - if (error.code !== Discord.Constants.APIErrors.UNKNOWN_MESSAGE) { - console.error('Failed to delete the message:', error); - } -}); -``` - -You can find a list of constants [here](https://github.com/discordjs/discord.js/blob/master/src/util/Constants.js#L552) [here](https://github.com/discordjs/discord.js/blob/stable/src/util/Constants.js#L788) - -### Method - -The final piece of information can tell us a lot about what we tried to do to the path, there are a set of predefined keywords which describe our actions on the path. - -``` -GET - Used to retrieve a piece of data -POST - Used to send a piece of data -PATCH - Used to modify a piece of data -PUT - Used to completely replace a piece of data -DELETE - Used to completely delete a piece of data -``` - -In this particular example we can see we are trying to access a piece of data, specifically, a message. - -## Common Discord.js and API errors - -### An invalid token was provided. - -This is a very common error, it originates from a wrong token being passed into `client.login()`. The most common causes of this error are: - -- Not importing the config or env file correctly -- Copying the client secret instead of the bot token (token is alphanumerical and 3 parts delimited by a period while the client secret is significantly smaller and one part only) -- Simply showing the token and copying that, instead of clicking regenerate and copying that. - - - -::: warning -On master there used to be an issue where the token was not prefixed correctly which resulted in valid tokens being marked as invalid. If you have verified that all of the above is not the case, make sure you have updated discord.js to the latest commit. -::: - - - -### Request to use token, but token was unavailable to the client. - -Another common error, this error originates from the client attempting to execute an action which requires the token but the token not being available. This is most commonly caused by destroying the client and then attempting to execute an action. - -This error is also caused by attempting to use a client which has not been logged in. Both of the examples below will throw errors. - -```js -const { Client } = require('discord.js'); -const client = new Client(); // Should not be here! - -module.exports = (message, args) => { - // Should be message.client instead! - client.fetchUser(args[0]).then(user => { - message.reply('your requested user', user.tag); - }); -}; -``` - -```js -const { Client } = require('discord.js'); -const client = new Client(); - -client.on('message', someHandlerFunction); - -client.login('token'); -// client will not be logged in yet! -client.fetchUser('myId').then(someInitFunction); -``` - - - -### MessageEmbed field names may not be empty. - -This error originates from attempting to call `MessageEmbed.addField()` without the first parameter, which is a title. If you would like the title to be empty for a reason, you should use a zero width space, which can be inputted as `\u200b`. - -### MessageEmbed field values may not be empty. - -This error, in conjunction to the previous error, is the result of calling `MessageEmbed.addField()` without the second parameter, the value. You can use a zero width space if you would like this empty. - - - -### The messages must be an Array, Collection, or number. - -This error originates from an invalid call to `bulkDelete()`, make sure you are inputting a valid Array or Collection of messages, or a valid number. - -### Members didnt't arrive in time. - -Another common error, this error originates from the client requesting members from the API through the websocket, and the member chunks not arriving in time and triggering the timeout. The most common cause to this error is a bad connection, however, it can also be caused by a very large amount of members being fetched, upwards of 50 thousand. To fix this, run the bot on a location with better internet, such as a VPS. If this does not work for you, you will have to manually change the hardcoded member fetching timeout in the source code. - -### MaxListenersExceededWarning: Possible EventEmitter memory leak detected... - -This error is caused by spawning a large amount of event listeners, usually for the client. The most common cause of this is nesting your event listeners instead of separating them. The way to fix this error is to make sure you do not nest your listeners, it is **not** to use `emitter.setMaxListeners()` as the error suggests. - -You can debug these messages in different ways: -- Through the [CLI](https://nodejs.org/api/cli.html#cli_trace_warnings): `node --trace-warnings index.js` -- Through the [`process#warning` event](https://nodejs.org/api/process.html#process_event_warning): `process.on('warning', console.warn);` - -### Cannot send messages to this user. - -This error is thrown when the bot attempts to send a DM message to a user and it is unable to do so. This is caused by a variety of reasons: -- The bot and the user do not share a guild (oftentimes people attempt to dm the user after kicking or banning them). -- The bot is attempting to DM another bot. -- The user has blocked the bot. -- The user has disabled dms in the privacy settings. - -In the case of the last two reasons, the error is not preventable, as the Discord API does not provide a way to check if you can send a user a dm until you attempt to send one. The best way to handle this error is to add a `.catch()` where you attempt to dm the user, and either ignore the rejected promise, or do what you want because of it. - -## Common miscellaneous errors - -### code ENOENT... syscall spawn git. - -This error is commonly thrown by your system due to it not being able to find `git`. You need to install `git` or update your path if `git` is already installed. Here are the download links for it: -- Ubuntu/Debian: `sudo apt-get install git` -- Windows: [git-scm](https://git-scm.com/download/win) - -### code ELIFECYCLE - -This error is commonly thrown by your system in response to the process unexpectedly closing. It can usually be fixed by cleaning npm cache, and deleting node_modules. The instructions for doing that are as such: -- Clean npm cache with `npm cache clean --force` -- delete `node_modules` -- delete `package-lock.json` (make sure you have a `package.json`!) -- run `npm install` to reinstall packages from `package.json` - diff --git a/Ajuda/guide-master/guide/popular-topics/miscellaneous-examples.md b/Ajuda/guide-master/guide/popular-topics/miscellaneous-examples.md deleted file mode 100644 index 5004dde..0000000 --- a/Ajuda/guide-master/guide/popular-topics/miscellaneous-examples.md +++ /dev/null @@ -1,184 +0,0 @@ -# Miscellaneous examples - -::: tip -For more, even shorter code examples, check out [the common questions page](/popular-topics/common-questions.md)! -::: - -## Play music from YouTube - -Here's a short example of a command that connects to a voice channel, plays a song, and exits when it's done. - -In order to run this, you'll need to have `ytdl-core` installed. - -``` -npm install --save ytdl-core -``` - -If you get an error that says 'OPUS_ENGINE_MISSING', you'll need to install one of the opus packages discord.js recommends. - -``` -npm install --save node-opus -``` - -If you get an error that says 'FFMPEG not found', this can be resolved by installing ffmpeg. - -On Debian / Ubuntu: - -``` -sudo apt-get install ffmpeg -``` - -On Windows: - -``` -npm install ffmpeg-binaries --save -``` - -Additionally, there have been reports that playing audio in this way from the Ubuntu subsystem offered by Windows 10 does not work. - - - -```js -const Discord = require('discord.js'); -const ytdl = require('ytdl-core'); - -const client = new Discord.Client(); - -client.on('message', message => { - if (message.content === '!play') { - if (message.channel.type !== 'text') return; - - const { voiceChannel } = message.member; - - if (!voiceChannel) { - return message.reply('please join a voice channel first!'); - } - - voiceChannel.join().then(connection => { - const stream = ytdl('https://www.youtube.com/watch?v=D57Y1PruTlw', { filter: 'audioonly' }); - const dispatcher = connection.playStream(stream); - - dispatcher.on('end', () => voiceChannel.leave()); - }); - } -}); - -client.login('your-token-goes-here'); -``` - - - - -```js -const Discord = require('discord.js'); -const ytdl = require('ytdl-core'); - -const client = new Discord.Client(); - -client.on('message', message => { - if (message.content === '!play') { - if (message.channel.type !== 'text') return; - - const voiceChannel = message.member.voice.channel; - - if (!voiceChannel) { - return message.reply('please join a voice channel first!'); - } - - voiceChannel.join().then(connection => { - const stream = ytdl('https://www.youtube.com/watch?v=D57Y1PruTlw', { filter: 'audioonly' }); - const dispatcher = connection.play(stream); - - dispatcher.on('end', () => voiceChannel.leave()); - }); - } -}); - -client.login('your-token-goes-here'); -``` - - - -## Catching UnhandledPromiseRejectionWarnings - -If you've ever seen something labeled as `UnhandledPromiseRejectionWarnings` in your console, the reason of occurrence can be vague sometimes. In addition to that, not handling promise rejections is currently deprecated and will eventually be removed. Once that happens, any unhandled promise rejections will close your app with a non-zero exit code. - -You can use a single line of code to prevent that, though. This will also display the line number of where the error occurred. - -```js -process.on('unhandledRejection', error => console.error('Uncaught Promise Rejection', error)); -``` - -## Mention prefix - -When a user adds your bot to their server, they may not immediately know what the prefix is. This is why it's a good idea to allow your bot to be triggered by either a set prefix, or by pinging them. In addition, it's also a good idea to have a command that displays the available prefixes. - -```js -const Discord = require('discord.js'); - -const client = new Discord.Client(); -const prefix = '!'; - -const escapeRegex = str => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); - -client.on('message', message => { - const prefixRegex = new RegExp(`^(<@!?${client.user.id}>|${escapeRegex(prefix)})\\s*`); - if (!prefixRegex.test(message.content)) return; - - const [, matchedPrefix] = message.content.match(prefixRegex); - const args = message.content.slice(matchedPrefix.length).trim().split(/ +/); - const command = args.shift().toLowerCase(); - - if (command === 'ping') { - message.channel.send('Pong!'); - } else if (command === 'prefix') { - message.reply(`you can either ping me or use \`${prefix}\` as my prefix.`); - } -}); - -client.login('your-token-goes-here'); -``` - -::: tip -The `escapeRegex` function is used to convert special characters into literal characters by escaping them, so that they don't terminate the pattern within the [Regular Expression](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions)! -::: - -::: tip -If you aren't familiar with the syntax used on the `const [, matchedPrefix] = ...` line, that's called "array destructuring". Feel free to read more about it in the [ES6 syntax](/additional-info/es6-syntax.md#array-destructuring) guide! -::: - -## Emoji characters - -If you've tried using [the usual method of retrieving unicode emojis](/popular-topics/reactions.md#unicode-emojis), you may have noticed that some characters don't provide the expected results. Here's a short snippet that'll help with that issue. You can toss this into a file of its own and use it anywhere you need! - -```js -// emojiCharacters.js -module.exports = { - a: '🇦', b: '🇧', c: '🇨', d: '🇩', - e: '🇪', f: '🇫', g: '🇬', h: '🇭', - i: '🇮', j: '🇯', k: '🇰', l: '🇱', - m: '🇲', n: '🇳', o: '🇴', p: '🇵', - q: '🇶', r: '🇷', s: '🇸', t: '🇹', - u: '🇺', v: '🇻', w: '🇼', x: '🇽', - y: '🇾', z: '🇿', 0: '0⃣', 1: '1⃣', - 2: '2⃣', 3: '3⃣', 4: '4⃣', 5: '5⃣', - 6: '6⃣', 7: '7⃣', 8: '8⃣', 9: '9⃣', - 10: '🔟', '#': '#⃣', '*': '*⃣', - '!': '❗', '?': '❓', -}; -``` - - - -```js -// index.js -const emojiCharacters = require('./emojiCharacters'); - -console.log(emojiCharacters.a); // 🇦 -console.log(emojiCharacters[10]); // 🔟 -console.log(emojiCharacters['!']); // ❗ -``` - -::: tip -On Windows, you may be able to use the `Win + .` keyboard shortcut to open up an emoji picker can be used for quick, easy access to all the unicode emojis available to you. Some of the emojis listed above may not be there, though (e.g the 0-9 emojis). -::: diff --git a/Ajuda/guide-master/guide/popular-topics/partials.md b/Ajuda/guide-master/guide/popular-topics/partials.md deleted file mode 100644 index 0db3846..0000000 --- a/Ajuda/guide-master/guide/popular-topics/partials.md +++ /dev/null @@ -1,75 +0,0 @@ -# Partial Structures - -Partial Structures were introduced to the library in version 12 and are optionally received whenever there is no sufficient data to emit the client event with a fully intact discord.js structure. They are (as the name suggests) incomplete and you cannot expect them to have any information besides their ID. All other properties and methods on this object should be considered invalid and defunct. Prior to this feature discord.js client events would simply not emit if one of the necessary structures could not be build with sufficient data to guarantee a fully functional structure with. If you do not opt into partials this is still the case. - -One example leveraging partials is the handling of reactions on uncached messages, which is explained on [this page](/popular-topics/reactions.md#listening-for-reactions-on-old-messages). - -Prior you had to either handle the undocumented `raw` event or fetch the respective messages on startup. The first approach was prone to errors and unexpected internal behaviour and the second not fully fail proof either, as the messages could still be uncached if cache size was exceeded in busy channels. - - - -Partials are not available in version 11, please update to version 12 of the library if you want to use partial structures in your bot. - - - - -## Enabling Partials - -As we said earlier partials do not have all the information necessary to make them fully functional discord.js structures, so it would not be a good idea to enable the functionality by default. Users should know how to handle them before opting in to this feature. - -You choose which structures you want to emit as partials as client options when instantiating your bot client. Available structures are: `USER`, `CHANNEL` (only DM channels can be uncached, server channels will always be available), `GUILD_MEMBER` and `MESSAGE`. - -```js -const Discord = require('discord.js'); -const client = new Client({ partials: ['MESSAGE', 'CHANNEL'] }); -``` -:::tip -Make sure you enable all partials you need for your use case! If you miss one the event does not get emitted. For example listening for reactions on uncached Messages in a direct message channel requires both `MESSAGE` and `CHANNEL`! -If you miss `CHANNEL` as enabled partial type reactions on uncached messages in servers will be emitted (as guild channels are always cached) but will not do so for direct messages. -::: - -:::warning -Partial structures are enabled globally. You can not make them work for only a certain event or cache and you very likely need to adapt other parts of your code that are accessing data from the relevant caches. All caches holding the respective structure type might return partials as well! -::: - -## Handling Partial data - -All structures you can choose to use partials for have a new property, fittingly called `.partial` indicating if it is a fully functional or partial instance of its class. The value is `true` if partial, `false` if fully functional. - -:::warning -Partial data is only ever guaranteed to contain an ID! Do not assume any property or method to work when dealing with a partial structure! -::: - -```js -if (message.partial) { - console.log('The message is partial.'); -} else { - console.log('The message is not partial.'); -} -``` - -## Obtaining the full structure - -Along with `.partial` to check if the structure you call it on is partial or not the library also introduced a `.fetch()` method to retrieve the missing data from the API and complete the structure. The method returns a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) you need to handle. After the Promise resolved (and with it the missing data arrived) you can use the structure as you would before. - -```js -if (message.partial) { - console.log('The message is partial.'); - message.fetch() - .then(fullmessage => { - console.log(fullmessage.content); - }) - .catch(error => { - console.log('Something went wrong when fetching the message: ', error); - }); -} else { - console.log('The message is not partial.'); -} -``` - -:::warning -You can not fetch data from the API that's already deleted. For message deletions `messageDelete` will only emit with the ID, which you can not use to fetch the complete message containing content, author or other information for, as it is already inaccessible by the time you receive the event. -::: - - - \ No newline at end of file diff --git a/Ajuda/guide-master/guide/popular-topics/permissions-extended.md b/Ajuda/guide-master/guide/popular-topics/permissions-extended.md deleted file mode 100644 index e629d26..0000000 --- a/Ajuda/guide-master/guide/popular-topics/permissions-extended.md +++ /dev/null @@ -1,77 +0,0 @@ -# Permissions (extended) - -## Discord's permission system - -Discord permissions are stored in a 53-bit integer and calculated using bitwise operations. If you want to dive deeper into what's happening behind the curtains, check the [Wikipedia](https://en.wikipedia.org/wiki/Bit_field) and [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators) articles on the topic. - -In discord.js, permission bit fields are represented as either the decimal value of said bit field or its referenced flags. -Every position in a permissions bit field represents one of these flags and its state (either referenced `1` or not referenced `0`). - -Before we get into actually assigning permissions, let's quickly go over the method Discord uses to determine a guild members final permissions: - -1. Take all permissions for all roles the guild member has and add them up. -2. Apply all denies for the default role (@everyone). -3. Apply all allows for the default role (@everyone ). -4. Apply all denies for all additional roles the guild member has at once. -5. Apply all allows for all additional roles the guild member has at once. -6. Apply all denies for the specific guild member if they exist. -7. Apply all allows for the specific guild member if they exist. - -Due to this system, you cannot deny base permissions. If you grant @everyone `SEND_MESSAGES` and don't grant it for a muted members role, muted members will still be able to send messages unless you specify channel-based overwrites. - -All additional roles allow overwrites are applied after all additional roles denies! If any of a member's roles has an overwrite to explicitly allow a permission, the member will be able to execute the associated actions in this channel regardless of role hierarchy. - -Placing an overwrite to allow `SEND_MESSAGES` on a role will result in members with this role to not be mutable via role assignment in this channel. - -## Elevated permissions - -If the guild owner enables the servers two-factor authentication option, everyone executing a certain subset of actions will need to have 2FA enabled on their account. As bots do not have 2FA themselves, you, as the application owner, will need to enable it on your account for your bot to work on those servers. -Check out [Discords help article](https://support.discordapp.com/hc/en-us/articles/219576828-Setting-up-Two-Factor-Authentication) if you need assistance with this. - -The permissions assigned to these actions are called "elevated permissions" and are: -`KICK_MEMBERS`, `BAN_MEMBERS`, `ADMINISTRATOR`, `MANAGE_CHANNELS`, `MANAGE_GUILD`, `MANAGE_MESSAGES`, `MANAGE_ROLES`, `MANAGE_WEBHOOKS` and `MANAGE_EMOJIS`. - -## Implicit permissions - -Some Discord permissions apply implicitly based on logical use, which can cause unwanted behavior if you are not aware of this fact. - -The prime example for implicit permissions is `VIEW_CHANNEL`. If this flag is missing in the final permissions, you can't do anything on that channel. Makes sense, right? If you can't view the channel, you can't read or send messages in it, set the topic, or change its name. -The library does not handle implicit permissions for you, so understanding how the system works is vital for you as a bot developer. - -Let's say you want to send a message in a channel. To prevent unnecessary API calls, you want to make sure your bots permissions in this channel include `SEND_MESSAGES` (more on how to achieve this [here](/popular-topics/permissions.md#checking-for-permissions)). The check passes, but you still can't actually send the message and are greeted with `DiscordAPIError: Missing Access`. - -This means your bot is missing `VIEW_CHANNEL`, and as such, can't send messages either. - -One possible scenario causing this: the channel has permission overwrites for the default role @everyone to grant `SEND_MESSAGES` so everyone who can see the channel can also write in it, but at the same time has an overwrite to deny `VIEW_CHANNEL` to make it only accessible to a subset of members. - -As you only check for `SEND_MESSAGES` the bot will try to execute the send, but since `VIEW_CHANNEL` is missing, the request is denied by the API. - -::: warning -For voice channels this same principle applies to the permission `CONNECT` as well -::: - -## Limitations and oddities - -- Your bot needs `MANAGE_ROLES` in its base permissions to change base permissions. -- It needs `MANAGE_ROLES` in its final permissions to change permission overwrites. -- It can not edit permissions for roles that are higher than or equal to its highest role. -- It can not grant permissions it doesn't have. -- It can manage overwrites for roles or users with higher roles than its own highest role. -- It can manage overwrites for permissions it doesn't have. -- Members with the `ADMINISTRATOR` permission are not affected by overwrites at all. - -## Missing permissions - -During your development you will likely run into `DiscordAPIError: Missing Permissions` at some point. This error can be caused by one of the following: - -- Your bot is missing the needed permission to execute this action in it's calculated base or final permissions (requirement changes based on the type of action you are trying to execute). -- You provided an invalid permission number while trying to create overwrites. (The calculator on the apps page returns decimal values while the developer documentation lists the flags in hex. Make sure you are not mixing the two and don't use the hex prefix `0x` where not applicable) -- It is trying to execute an action on a guild member with a role higher than or equal to your bots highest role. -- It is trying to modify or assign a role that is higher than or equal to its highest role. -- It is trying to execute a forbidden action on the server owner. -- It is trying to execute an action based on another unfulfilled factor (for example reserved for partnered guilds). -- It is trying to execute an action on a voice channel without the `VIEW_CHANNEL` permission. - -::: warning -The `ADMINISTRATOR` permission being granted does not skip any hierarchical check! -::: diff --git a/Ajuda/guide-master/guide/popular-topics/permissions.md b/Ajuda/guide-master/guide/popular-topics/permissions.md deleted file mode 100644 index 54cedbd..0000000 --- a/Ajuda/guide-master/guide/popular-topics/permissions.md +++ /dev/null @@ -1,406 +0,0 @@ -# Permissions - -Permissions are Discords primary feature enabling users to customize the workings of their server to their liking. -To break it down to essentials: Permissions and permission overwrites tell Discord who is allowed to do what and where. -When first confronted with them they can be quite confusing, but no worries we are here to take care of that, so let's dive in! - -## Roles as bot permissions - -If you want to keep your bots permission checks simple, you might find it sufficient to just check if the member executing the command has a certain role. - -If you have the role ID, you can simply check if the `.roles` Collection on a GuildMember object includes it, using `.has()`. Should you not know the ID and want to check for something like a role named "Mod", you can use `.some()`. - -```js -member.roles.has('role-id-here'); -// returns true if the member has the role - -member.roles.some(role => role.name === 'Mod'); -// returns true if any of the member's roles is exactly named "Mod" -``` - -If you want to enhance this system slightly, you can include the guild owner by comparing the executing members ID with `message.guild.ownerID`. - -To include permission checks like `ADMINISTRATOR` or `MANAGE_GUILD`, keep reading as we will cover Discord Permissions and all their intricacies in the following sections. - -## Terminology - -* Permission: The ability to execute a certain action in Discord -* Overwrite: Rule on a channel to modify the permissions for a member or role -* Bit field: Binary representation of Discord permissions -* Flag: Human readable string in MACRO_CASE, for example `'KICK_MEMBERS'`, refers to a position in the permission bit field. You can find a list of all valid flags in the [discord.js documentation](https://discord.js.org/#/docs/main/11.5.1/class/Permissions?scrollTo=s-FLAGS)[discord.js documentation](https://discord.js.org/#/docs/main/master/class/Permissions?scrollTo=s-FLAGS) -* Base Permissions: Permissions for roles the member has, set on the guild level -* Final Permissions: Permissions for a member or role, after all overwrites are applied - -::: tip -You can provide permission decimals wherever we use flag literals in this guide. If you are interested in a handy permission calculator you can look at the "Bot" section in the [Discord developer portal](https://discordapp.com/developers/applications). -::: - -## Base permissions - -### Setting role permissions - -Base permissions are set on roles, not the guild member itself. To change them, you access a Role object (for example via `member.roles.first()` or `guild.roles.random()`) and use the `.setPermissions()` method. This is how you'd change the base permissions for the @everyone role, for example: - -```js -guild.defaultRole.setPermissions(['SEND_MESSAGES', 'VIEW_CHANNEL']); -``` - -Any permission not referenced in the flag array or bit field are not granted to the role. - -::: tip -Note that flag names are literal. Although `VIEW_CHANNEL` grants access to view multiple channels the permission flag is still called `VIEW_CHANNEL` in singular. -::: - -### Creating a role with permissions - -Alternatively you can provide permissions as a property of [RoleData](https://discord.js.org/#/docs/main/11.5.1/typedef/RoleData)[RoleData](https://discord.js.org/#/docs/main/master/typedef/RoleData) objects during role creation as an array of flag strings or a permission number: - - - -```js -guild.createRole({ name: 'Mod', permissions: ['MANAGE_MESSAGES', 'KICK_MEMBERS'] }); -``` - - - - -```js -guild.roles.create({ data: { name: 'Mod', permissions: ['MANAGE_MESSAGES', 'KICK_MEMBERS'] } }); -``` - - - -### Checking member permissions - -To know if a one of a member's roles has a permission enabled, you can use the `.hasPermission()` method of the [GuildMember](https://discord.js.org/#/docs/main/11.5.1/class/GuildMember)[GuildMember](https://discord.js.org/#/docs/main/master/class/GuildMember) class and provide a permission flag, array, or number to check for. You can also specify if you want to allow the `ADMINISTRATOR` permission or the guild owner status to override this check with the following parameters. - - - -```js -if (member.hasPermission('KICK_MEMBERS', false, false)) { - console.log('This member can kick'); -} - -if (member.hasPermission(['KICK_MEMBERS', 'BAN_MEMBERS'])) { - console.log('This member can kick and ban'); -} - -if (member.hasPermission('KICK_MEMBERS', false, false, false)) { - console.log('This member can kick without allowing admin to override'); -} -``` - - - - -```js -if (member.hasPermission('KICK_MEMBERS')) { - console.log('This member can kick'); -} - -if (member.hasPermission(['KICK_MEMBERS', 'BAN_MEMBERS'])) { - console.log('This member can kick and ban'); -} - -if (member.hasPermission('KICK_MEMBERS', { checkAdmin: false, checkOwner: false })) { - console.log('This member can kick without allowing admin to override'); -} -``` - - - -If you provide multiple permissions to the method, it will only return `true` if all permissions you specified are granted. - -## Channel overwrites - -Permission overwrites control the abilities of members for this specific channel or a set of channels if applied to a category with synchronized child channels. - -As you have likely already seen in your desktop client, channel overwrites have three states: - -- Explicit allow (`true`, green ✓) -- Explicit deny (`false`, red X) -- Default (`null`, gray /) - -### Adding overwrites - -To add a permission overwrite for a role or guild member, you access the channel object and use the `.overwritePermissions()``.updateOverwrite()` method. The first parameter is the target of the overwrite, either a Role or User object (or its respective resolvable), and the second is a [PermissionOverwriteOptions](https://discord.js.org/#/docs/main/11.5.1/typedef/PermissionOverwriteOptions)[PermissionOverwriteOption](https://discord.js.org/#/docs/main/master/typedef/PermissionOverwriteOption) object. - -Let's add an overwrite to lock everyone out of the channel. The guild ID doubles as the role id for the default role @everyone as demonstrated below: - - - -```js -channel.overwritePermissions(channel.guild.defaultRole, { VIEW_CHANNEL: false }); -``` - - - - -```js -channel.updateOverwrite(channel.guild.defaultRole, { VIEW_CHANNEL: false }); -``` - - - -Any permission flags not specified get neither an explicit allow nor deny overwrite and will use the base permission, unless another role has an explicit overwrite set. - -You can also provide an array of overwrites during channel creation as shown below: - - - -```js -guild.createChannel('new-channel', { - type: 'text', - permissionOverwrites: [ - { - id: message.guild.id, - deny: ['VIEW_CHANNEL'], - }, - { - id: message.author.id, - allow: ['VIEW_CHANNEL'], - }, - ], -}); -``` - -::: warning -These objects are [ChannelCreationOverwrites](https://discord.js.org/#/docs/main/11.5.1/typedef/ChannelCreationOverwrites) and differ from [PermissionOverwriteOptions](https://discord.js.org/#/docs/main/11.5.1/typedef/PermissionOverwriteOptions); be careful to not mix them up! -::: - - - - -```js -guild.channels.create('new-channel', { - type: 'text', - permissionOverwrites: [ - { - id: message.guild.id, - deny: ['VIEW_CHANNEL'], - }, - { - id: message.author.id, - allow: ['VIEW_CHANNEL'], - }, - ], -}); -``` - - - -### Replacing overwrites - -To replace all permission overwrites on the channel with a provided set of new overwrites, you can use the `.replaceOverwrites()``.overwritePermissions()` function. This is extremely handy if you want to copy a channels full set of overwrites to another one, as this method allows passing an array or Collection of [PermissionOverwrites](https://discord.js.org/#/docs/main/master/class/PermissionOverwrites)[PermissionOverwrites](https://discord.js.org/#/docs/main/11.5.1/class/PermissionOverwrites) or [ChannelCreationOverwrites](https://discord.js.org/#/docs/main/11.5.1/typedef/ChannelCreationOverwrites). - - - -```js -// copying overwrites from another channel -channel.replacePermissionOverwrites({ overwrites: otherChannel.permissionOverwrites }); - -// replacing overwrites with PermissionOverwriteOptions -channel.replacePermissionOverwrites({ - overwrites: [ - { - id: guild.defaultRole.id, - deny: ['VIEW_CHANNEL'], - }, - { - id: user.id, - allow: ['VIEW_CHANNEL'], - }, - ], -}); -``` - - - - -```js -// copying overwrites from another channel -channel.overwritePermissions({ overwrites: otherChannel.permissionOverwrites }); - -// replacing overwrites with PermissionOverwriteOptions -channel.overwritePermissions({ - permissionOverwrites: [ - { - id: guild.defaultRole.id, - deny: ['VIEW_CHANNEL'], - }, - { - id: user.id, - allow: ['VIEW_CHANNEL'], - }, - ], -}); -``` - - - -### Removing overwrites - -To remove the overwrite for a specific member or role, you can get it from the channels permissionOverwrites Collection and call the `.delete()` method on it. Since the Collection is keyed by the target's ID (either role ID or user ID), the respective overwrite is very easy to access. - -```js -// deleting the channels overwrite for the message author -channel.permissionOverwrites.get(message.author.id).delete(); -``` - -### Syncing with a category - -If the permission overwrites on a channel under a category match with the parent (category) the channel is considered to be synchronized. This means that any changes in the categories overwrites will now also change the channels overwrites. Changing the child channels overwrites will not effect the parent. - -To easily synchronize permissions with the parent channel you can call the `.lockPermissions()` method on the respective child channel. - -```js -if (!channel.parent) { - return console.log('This channel is not listed under a category'); -} - -channel.lockPermissions() - .then(() => console.log('Successfully synchronized permissions with parent channel')) - .catch(console.error); -``` - -### Permissions after overwrites - - - -discord.js features two utility methods to easily determine the final permissions for a guild member or role in a specific channel: `.permissionsFor()` on the [GuildChannel](https://discord.js.org/#/docs/main/11.5.1/class/GuildChannel?scrollTo=permissionsFor) class and `.permissionsIn()` on the [GuildMember](https://discord.js.org/#/docs/main/11.5.1/class/GuildMember?scrollTo=permissionsIn) class. Both return a [Permissions](https://discord.js.org/#/docs/main/11.5.1/class/Permissions) object. - - - - -discord.js features two utility methods to easily determine the final permissions for a guild member or role in a specific channel: `.permissionsFor()` on the [GuildChannel](https://discord.js.org/#/docs/main/master/class/GuildChannel?scrollTo=permissionsFor) class and `.permissionsIn()` on the [GuildMember](https://discord.js.org/#/docs/main/master/class/GuildMember?scrollTo=permissionsIn)and [Role](https://discord.js.org/#/docs/main/master/class/Role?scrollTo=permissionsIn) classes. Both return a [Permissions](https://discord.js.org/#/docs/main/master/class/Permissions) object. - - - -To check your bots permissions in the channel the command was used in, you could use something like this: - -```js -// final permissions for a guild member using permissionsFor -const botPermissionsFor = channel.permissionsFor(guild.me); - -// final permissions for a guild member using permissionsIn -const botPermissionsIn = guild.me.permissionsIn(channel); - -// final permissions for a role -const rolePermissions = channel.permissionsFor(role); -``` - -::: warning -The `.permissionsFor()` and `.permissiosnIn()` methods return a bit fieldPermissions object with all permissions set if the member or role has the global `ADMINISTRATOR` permission and does not take overwrites into consideration in this case. Using the second parameter of the `.has()` method as described further down in the guide will not allow you to check without taking `ADMINISTRATOR` into account here! -::: - -If you want to know how to work with the returned Permissions objects keep reading as this will be our next topic. - -## The Permissions object - -The [Permissions](https://discord.js.org/#/docs/main/11.5.1/class/Permissions)[Permissions](https://discord.js.org/#/docs/main/master/class/Permissions) object is a discord.js class containing a permissions bit field and a bunch of utility methods to manipulate it easily. -Remember that using these methods will not manipulate permissions, but create a new instance representing the changed bit field. - -### Converting permission numbers - -Some methods and properties in Discord.js return permission decimals rather than a Permissions object, making it hard to manipulate or read them if you don't want to use bitwise operations. -You can, however, pass these decimals to the Permissions constructor to convert them as shown below. - -```js -const { Permissions } = require('discord.js'); -const permissions = new Permissions(268550160); -``` - -You can also use this approach for other [PermissionResolvable](https://discord.js.org/#/docs/main/11.5.1/typedef/PermissionResolvable)[PermissionResolvable](https://discord.js.org/#/docs/main/master/typedef/PermissionResolvable)s like flag arrays or flags. - -```js -const { Permissions } = require('discord.js'); -const flags = [ - 'MANAGE_CHANNELS', - 'EMBED_LINKS', - 'ATTACH_FILES', - 'READ_MESSAGE_HISTORY', - 'MANAGE_ROLES', -]; - -const permissions = new Permissions(flags); -``` - -### Checking for permissions - -The Permissions object features the `.has()` method, allowing an easy way to check flags in a Permissions bit field. -The `.has()` method takes two parameters: the first being either a permission number, single flag, or an array of permission numbers and flags, the second being a boolean, indicating if you want to allow the `ADMINISTRATOR` permission to override (defaults to true). - -Let's say you want to know if the decimal bit field representation `268550160` has `MANAGE_CHANNELS` referenced: - -```js -const { Permissions } = require('discord.js'); - -const permissions = new Permissions([ - 'MANAGE_CHANNELS', - 'EMBED_LINKS', - 'ATTACH_FILES', - 'READ_MESSAGE_HISTORY', - 'MANAGE_ROLES', -]); - -console.log(permissions.has('MANAGE_CHANNELS')); -// output: true - -console.log(permissions.has(['MANAGE_CHANNELS', 'EMBED_LINKS'])); -// output: true - -console.log(permissions.has(['MANAGE_CHANNELS', 'KICK_MEMBERS'])); -// output: false - -const adminPermissions = new Permissions('ADMINISTRATOR'); - -console.log(adminPermissions.has('MANAGE_CHANNELS')); -// output: true - -console.log(adminPermissions.has('MANAGE_CHANNELS', true)); -// output: true - -console.log(adminPermissions.has('MANAGE_CHANNELS', false)); -// output: false -``` - -### Manipulating permissions - -The Permissions object enables you to easily add or remove certain permissions from an existing bit field without having to worry about bitwise operations. Both `.add()` and `.remove()` can take a single permission flag or number, an array of permission flags or numbers, or multiple permission flags or numbers as multiple parameters. - -```js -const { Permissions } = require('discord.js'); - -const permissions = new Permissions([ - 'MANAGE_CHANNELS', - 'EMBED_LINKS', - 'ATTACH_FILES', - 'READ_MESSAGE_HISTORY', - 'MANAGE_ROLES', -]); - -console.log(permissions.has('KICK_MEMBERS')); -// output: false - -permissions.add('KICK_MEMBERS'); -console.log(permissions.has('KICK_MEMBERS')); -// output: true - -permissions.remove('KICK_MEMBERS'); -console.log(permissions.has('KICK_MEMBERS')); -// output : false -``` - -You can utilize these methods to adapt permissions or overwrites without touching the other flags. To achieve this you can get the existing permissions for a role, manipulating the bit field as described above and passing the changed bit field to `role.setPermissions()`. - - - -::: tip -The expression `role.permissions` returns a number which needs to be converted to a Permissions object for this to work as described here. We covered how to achieve this in the section "[Converting permission numbers to Objects](/popular-topics/permissions.md#converting-permission-numbers)" -::: - - - -## Resulting code - - diff --git a/Ajuda/guide-master/guide/popular-topics/reactions.md b/Ajuda/guide-master/guide/popular-topics/reactions.md deleted file mode 100644 index eb2182c..0000000 --- a/Ajuda/guide-master/guide/popular-topics/reactions.md +++ /dev/null @@ -1,226 +0,0 @@ -# Reactions - -## Reacting to messages - -One of the first things many people want to know is how to react with emojis, both custom and "regular" (unicode). There are different routes you need to take for each of those, so let's take a look at both. - -Here's the base code we'll be using: - -```js -const Discord = require('discord.js'); -const client = new Discord.Client(); - -client.once('ready', () => { - console.log('Ready!'); -}); - -client.on('message', message => { - // ... -}); - -client.login('your-token-goes-here'); -``` - -### Unicode emojis - -To react with a unicode emoji, you will need the actual unicode character of the emoji. There are many ways to get a unicode character of an emoji, but the easiest way would be through Discord itself. If you send a message with a unicode emoji (such as `:smile:`, for example) and put a `\` before it, it will "escape" the emoji and will display the unicode character instead of the normal emoji image. - -![Escaped unicode emoji](~@/images/I2ruNRf.png) - -To actually react with an emoji, you need to use the `message.react()` method. Once you have the emoji character, all you need to do is copy & paste it as a string inside the `.react()` method! - -```js -if (message.content === '!react') { - message.react('😄'); -} -``` - -![Unicode emoji reaction](~@/images/NUvOWqG.png) - -### Custom emojis - -For custom emojis, there are actually multiple ways of reacting. Like unicode emojis, custom emojis can also be escaped. However, when you escape a custom emoji, the result will be different. - -![Escaped custom emoji](~@/images/DFfdFw4.png) - -This format is essentially the name of the emoji, followed by its ID. Copy & paste the ID into the `.react()` method as a string. - -```js -if (message.content === '!react-custom') { - message.react('396548322053062656'); -} -``` - -![Custom emoji reaction via ID](~@/images/qSCjlEB.png) - -Great! This route may not always be available to you, though. Sometimes you'll need to react with an emoji programmatically. To do so, you'll need to retrieve the emoji object. - -Two of the easiest ways you can retrieve an emoji would be: - -* Use `.find()` on a Collection of Emojis. -* Use `.get()` on the `client.emojis` Collection. - -::: tip -It is possible for two or more emojis to have the same name, and using `.find()` will only return the **first** entry it finds. As such, this can cause unexpected results. -::: - -Using `.find()`, your code would look something like this: - -```js -if (message.content === '!react-custom') { - const emoji = message.guild.emojis.find(emoji => emoji.name === 'ayy'); - message.react(emoji); -} -``` - -Using `.get()`, your code would look something like this: - -```js -if (message.content === '!react-custom') { - const emoji = client.emojis.get(config.emojiID); - message.react(emoji); -} -``` - -Of course, if you already have the emoji ID, you should just put that directly inside the `.react()` method. But if you want to do other things with the emoji data later on (e.g. display the name or image URL), it's best to retrieve the full emoji object. - -### Reacting in order - -If you just put one `message.react()` under another, it won't always react in order as is. This is because `.react()` is a Promise, and as such, an asynchronous operation. - -```js -if (message.content === '!fruits') { - message.react('🍎'); - message.react('🍊'); - message.react('🍇'); -} -``` - -![Reaction race condition](~@/images/DgDVtcv.png) - -As you can see, if you leave it like that, it won't display as you really want it to. It was able to react correctly on the first try, but reacts in a different order each time after that. - -Luckily, there are two easy solutions to this. The first would be to to chain `.then()`s in the order you want it to display. - -```js -client.on('message', message => { - if (message.content === '!fruits') { - message.react('🍎') - .then(() => message.react('🍊')) - .then(() => message.react('🍇')) - .catch(() => console.error('One of the emojis failed to react.')); - } -}); -``` - -The other would be to use the `async`/`await` keywords. - -```js -// notice the `async` keyword -client.on('message', async message => { - if (message.content === '!fruits') { - try { - await message.react('🍎'); - await message.react('🍊'); - await message.react('🍇'); - } catch (error) { - console.error('One of the emojis failed to react.'); - } - } -}); -``` - -If you try again with either of the codeblocks above, you'll get the result you originally wanted! - -![Emojis reacting in correct order](~@/images/1IWSJ1C.png) - -::: tip -If you aren't familiar with Promises or `async`/`await`, you can read more about them on [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) or [our guide page on async/await](/additional-info/async-await.md)! -::: - -### Handling multiple reactions if the order doesn't matter - -However, if you don't mind the order the emojis react in, you can take advantage of `Promise.all()`, like so: - -```js -if (message.content === '!fruits') { - Promise.all([ - message.react('🍎'), - message.react('🍊'), - message.react('🍇'), - ]) - .catch(() => console.error('One of the emojis failed to react.')); -} -``` - -The benefit of this small optimization is that you can use `.then()` to handle when all of the Promises have resolved, or `.catch()` when one of them has failed. You can also `await` it since it returns a Promise itself. - -## Awaiting reactions - -A common use case for reactions in commands is having a user confirm or deny an action, or creating a poll system. Luckily, we actually [already have a guide page that covers this](/popular-topics/collectors.md)! Check out that page if you want a more in-depth explanation. Otherwise, here's a basic example for reference: - -```js -message.react('👍').then(() => message.react('👎')); - -const filter = (reaction, user) => { - return ['👍', '👎'].includes(reaction.emoji.name) && user.id === message.author.id; -}; - -message.awaitReactions(filter, { max: 1, time: 60000, errors: ['time'] }) - .then(collected => { - const reaction = collected.first(); - - if (reaction.emoji.name === '👍') { - message.reply('you reacted with a thumbs up.'); - } else { - message.reply('you reacted with a thumbs down.'); - } - }) - .catch(collected => { - message.reply('you reacted with neither a thumbs up, nor a thumbs down.'); - }); -``` - -## Listening for reactions on old messages - - - -Discord.js v11 does not have the ability to emit events if the respective structures it needs to emit with are incomplete and does not auto-fetch the missing information. -This behaviour has been changed in version 12 of the library. It introduces partial structures which enable us to emit incomplete structures and complete them with a single fetch call. -This feature is not available on version 11.x if you want to listen for reactions on old messages please use version 12 of the library. - - - - -Messages sent before your bot started are uncached, unless you fetch them first. By default the library does not emit client events if the data received and cached is not sufficient to build fully functional objects. -Since version 12 you can change this behaviour by activating partials. For a full explanation of partials see [this page](/popular-topics/partials.md). - -Make sure you enable partial structures for both `MESSAGE` and `CHANNEL` when instantiating your client, if you want reaction events on uncached messages for both server and direct message channels. If you do not want to support direct message channels you can only enable `MESSAGE`. - -```js -const Discord = require('discord.js'); -const client = new Discord.Client({ partials: ['MESSAGE', 'CHANNEL'] }); -client.on('messageReactionAdd', async (reaction, user) => { - // When we receive a reaction we check if the message is partial or not - if (reaction.message.partial) { - // If the message was removed the fetching might result in an API error, which we need to handle - try { - await reaction.message.fetch(); - } catch (error) { - console.log('Something went wrong when fetching the message: ', error); - } - } - // Now the message has been cached and is fully available - console.log(`${reaction.message.author}'s message "${reaction.message.content}" gained a reaction!`); -}); -``` - -:::warning -Partial structures are enabled globally. You can not only make them work for a certain event or cache and you very likely need to adapt other parts of your code that are accessing data from the relevant caches. All caches holding the respective structure type might return partials as well! -::: - - - -## Resulting code - - diff --git a/Ajuda/guide-master/guide/preparations/README.md b/Ajuda/guide-master/guide/preparations/README.md deleted file mode 100644 index 8f80a4e..0000000 --- a/Ajuda/guide-master/guide/preparations/README.md +++ /dev/null @@ -1,83 +0,0 @@ -# Installing Node.js and discord.js - -## Installing Node.js - -To use discord.js, you'll need to install Node.js. You can do so by going to [the Node.js website](https://nodejs.org/). - -### Installing on Windows - -If you're developing on Windows, it's as simple as installing any other program. Go to [the Node.js website](https://nodejs.org/), download the latest version, open up the downloaded file, and follow the steps from the installer. - -### Installing on macOS - -If you're developing on macOS, you have a few options. You can go to [the Node.js website](https://nodejs.org/), download the latest version, double click the package installer, and follow the instructions. Or you can use a package manager like [Homebrew](https://brew.sh/) with the command `brew install node`. - -### Installing on Linux - -If you're developing on Linux, you may consult [this page](https://nodejs.org/en/download/package-manager/) to determine how you should install Node.
On that note, there's a possibility that you may already have Node \(e.g. if you're using a VPS\). You can check by running the `node -v` command. If it outputs something like `v8.0.0``v10.0.0` or higher, then you're good to go! Otherwise, take a look at the page linked above for instructions on installing Node on your OS. - -::: warning -If you _do_ have Node installed, but have an older version \(i.e. anything below 8.0.010.0.0\), you should upgrade to the latest version. Discord.js v11 Discord.js v12 requires Node 8.0.010.0.0 or higher. -::: - ---- - -## Preparing the essentials - -To install and use discord.js, you'll need to install it via npm \(Node's package manager\). npm comes with every Node installation, so you don't have to worry about installing that. However, before you install anything, you should set up a new project folder. - -### Setting up a project folder - -Like any other project, you should have a dedicated folder for this, in order to keep it organized and manageable. - -Navigate to a place on your machine that's easy to find and reopen in the future, for convenience purposes. Create a new folder like you normally would (for Linux, you can use `mkdir project-name` inside your terminal). If you already have a name you want to use for your bot, you can use that as the folder name. Otherwise, you may name it something like `discord-bot` for the time being \(or anything else you have in mind\). - -Once you're done making the folder, open it up (for Linux, you can use `cd project-name` inside your terminal). - -### Opening the command prompt - -If you're on Linux, you can quickly open up the terminal with `Ctrl + Alt + T`. - -If you're on Windows and aren't familiar with opening up the command prompt, simply do the following: - -1. Open your bot project folder. -2. Hold down the `Shift` key and right-click inside of the folder. -3. Choose the "Open command window here" option. - -It should then open up a window with a black background. It's a bit unattractive, but we'll talk about using better, more powerful tools in a different part of the guide. - -### Using the command prompt - -With the command prompt open, run the `node -v` command to make sure you've successfully installed Node.js. If you see something like `v8.0.0`
`v10.0.0`, great! If not, go back and try installing again. - -The next command you'll be running is `npm init`. This command creates a `package.json` file for you, which is what will be used to keep track of the dependencies your bot uses, as well as other info. If you're a bit confused by that, you can simply ignore it for the time being. - -The `npm init` command will ask you a sequence of questions - you should fill them out as you see fit. If you're not sure of something or just want to skip it as a whole, simply leave it blank and press enter. - -::: tip -Want to get started quickly? Use `npm init -y` to have it fill out everything for you! -::: - -Once you're done with that, you're ready to install discord.js! - ---- - -## Installing discord.js - -Now that you've installed Node.js and know how to open up your console and run commands, you can finally install discord.js! - -To install discord.js, simply run the `npm install discord.js`. This can take a bit of time, but should be done fairly quickly. - -::: warning -Once the installation is complete, you'll see something like this: -![npm warnings](~@/images/BbcuyJ6.png)
-**This is perfectly normal and means that it worked.** You don't need to install any of the items listed in order to use discord.js; they are 100% optional. -::: - -And that's it! With all the necessities installed, you're almost ready to start coding your bot. - ---- - -## Installing a linter - -While you are coding, you may find that you run into numerous syntax errors, or just code in an inconsistent style. It's highly urged that you install a linter to ease these troubles. While code editors generally are able to point out syntax errors, with a linter, you can coerce your coding to be in a specific style as you define in the configuration. While this is not required, it's strongly recommended. [Click here for the linter guide!](/preparations/setting-up-a-linter.md) diff --git a/Ajuda/guide-master/guide/preparations/adding-your-bot-to-servers.md b/Ajuda/guide-master/guide/preparations/adding-your-bot-to-servers.md deleted file mode 100644 index e0b2bbf..0000000 --- a/Ajuda/guide-master/guide/preparations/adding-your-bot-to-servers.md +++ /dev/null @@ -1,43 +0,0 @@ -# Adding your bot to servers - -If you've been diligently following the previous pages of the guide, you should have a bot application set up. However, it's not in any servers yet. So how does that work? - -Before you're actually able to see your bot in your own (or other) servers, it needs to be added using a special invite link that can be created using your bot application's client ID. - -## Bot invite links - -The basic version of one such link looks like this: - -``` -https://discordapp.com/oauth2/authorize?client_id=123456789012345678&scope=bot -``` - -The structure of the url is quite simple: - -* The first part is just Discord's standard structure for authorizing an OAuth2 application (such as your bot application) for entry to a Discord server. -* The second part that says `client_id=...` is to specify _which_ application you want to authorize. You'll need to replace this part with your client's ID in order to create a valid invite link. -* Lastly, the third part which says `scope=bot` specifies that you want to add this application as a Discord bot. - -::: tip -A `permissions` parameter also exists to restrict or guarantee the permission your bot will have on the server you are adding it to. For ease of use, it is recommended to use [this](https://discordapi.com/permissions.html) website. -::: - -::: warning -If you get an error message saying "Bot requires a code grant", then head over into your application's settings and disable the "Require OAuth2 Code Grant" option. You usually shouldn't enable this checkbox unless you know why you need to. -::: - -## Creating and using your own invite link - -As mentioned above, you'll need to replace the `client_id` parameter with your client's ID in order to generate your invite link. To find your app's ID, head back to the [My Apps](https://discordapp.com/developers/applications/me) page under the "Applications" section once again and click on your bot application. - -Insert your app's ID into the link template and then access it in your browser. You should see something like this (with your bot's username and avatar): - -![Bot Authorization field](~@/images/A8l70bj.png) - -Choose the server you want to add it to and click "Authorize". Do note that you'll need the "Manage Server" permission on a server in order to be able to add your bot there. This should then present you a nice confirmation message: - -![Bot authorized](~@/images/BAUsjyg.png) - -Congratulations! You've successfully added your bot to your Discord server. It should show up in your server's member list somewhat like this: - -![Bot in server's user list](~@/images/6qTlDW0.png) diff --git a/Ajuda/guide-master/guide/preparations/setting-up-a-bot-application.md b/Ajuda/guide-master/guide/preparations/setting-up-a-bot-application.md deleted file mode 100644 index 354c312..0000000 --- a/Ajuda/guide-master/guide/preparations/setting-up-a-bot-application.md +++ /dev/null @@ -1,54 +0,0 @@ -# Setting up a bot application - -## Creating your bot - -Now that you've installed Node, discord.js, and hopefully a linter, you're almost ready to start coding! The next step you need to take is setting up an actual Discord bot application via Discord's website. - -It's incredibly easy to create one. The steps you need to take are as follows: - -1. Open up [the Discord website](https://discordapp.com/) and [login](https://discordapp.com/login). -2. Hover over the "Developers" drop-down menu and click on the [Developer Portal](https://discordapp.com/developers/applications/) link. -3. Click on the "New Application" button. -4. Enter a name and optionally select a team (if you want the bot to belong to one). Then confirm the pop-up window by clicking the "Create" button. - -You should see a page like this: - -![Successfully created application](~@/images/create-app.png) - -You can optionally enter a name, description, and avatar for your application here. Once you've saved your changes, you can move on by selecting the "Bot" tab in the left pane. - -![Create a bot UI](~@/images/create-bot.png) - -Click the "Add Bot" button on the right and confirm the pop-up window by clicking "Yes, do it!". Congratulations, you're now the proud owner of a shiny new Discord bot! You're not quite done, though. - -## Your token - -::: danger -This section is very important, so pay close attention. It explains what your bot token is, as well as the security aspects of it. -::: - -After creating a bot user, you'll see a section like this: - -![Bot application](~@/images/created-bot.png) - -In this panel, you can give your bot a snazzy avatar, set its username, and make it public or private. You can access your token in this panel as well, either by revealing it or simply pressing the "Copy" button. When we ask you to paste your token somewhere, this is the value that you need to put in. Don't worry if you do happen to lose it at some point; you can always come back to this page and copy it again. - -### What is a token, anyway? - -A token is essentially your bot's password; it's what your bot uses to login to Discord. With that being said, **it is vital that you do not ever share this token with anybody, purposely or accidentally**. If someone does manage to get a hold of your token, they can use your bot as if it were theirs—this means they can perform malicious acts with it. - -### Token leak scenario - -Let's imagine that you have a bot on over 1,000 servers, and it took you many, many months of coding and patience to get it on that amount. Your token gets leaked somewhere, and now someone else has it. That person can: - -* Spam every server your bot is on; -* Attempt to DM spam as many users as they can; -* Attempt to delete as many channels as they can; -* Attempt to kick or ban as many server members as they possibly can; -* Make your bot leave all of the servers it has joined. - -All that and much, much more. Sounds pretty terrible, right? So make sure to keep your token as safe as possible! - -::: danger -If you ever somehow leak your token (commit it to a repository, post it in a support channel, etc.) or otherwise see your bot in danger, return to this page and regenerate a new one. Your old token will become invalid and you'll need to update it with the new one in all the places you've used it. -::: diff --git a/Ajuda/guide-master/guide/preparations/setting-up-a-linter.md b/Ajuda/guide-master/guide/preparations/setting-up-a-linter.md deleted file mode 100644 index 1c07985..0000000 --- a/Ajuda/guide-master/guide/preparations/setting-up-a-linter.md +++ /dev/null @@ -1,127 +0,0 @@ -# Setting up a linter - -As a developer, it's a good idea to make your development process as streamlined as possible. Installing and utilizing the right tools is an essential part of any project you're working on. Although it's not required, installing a linter will help you greatly. - -## Installing a code editor - -First, you will need a proper code editor. Using Notepad and Notepad++ is discouraged, as they're inefficient for projects like these. If you are using either, it is highly recommended to switch in order to save everyone lots of headaches and unnecessary syntax error questions. - -* [Visual Studio Code](https://code.visualstudio.com/) is a very popular choice; it is known for being fast and powerful. It supports a large variety of languages, has its own terminal, built-in IntelliSense support, and autocomplete for both JavaScript and TypeScript. This is the recommended choice. -* [Atom](https://atom.io/) is user-friendly, concise and easy to navigate. This is what many developers use to get started. -* [Sublime Text](https://www.sublimetext.com/) is another popular editor that's easy to use and write code with. - -## Installing a linter - -One of the major advantages proper code editors have over Notepad and Notepad++ is their ability to use linters. Linters check syntax and help you produce consistent code that follows certain style rules that you can define yourself, if you choose to do so. They help form good habits if you stick to a single configuration. When you start using a linter, you might be bombarded with errors at first. This is normal and perfectly fine. It might be a pain to get through during the initial process, but it's most definitely worth it. - -First, be sure to install the [ESLint package](https://www.npmjs.com/package/eslint) so that you have it available in your project. - -```bash -# locally -npm install eslint - -# globally -npm install --global eslint -``` - -Afterwards, install the appropriate plugin(s) for your editor of choice. - -* [ESLint for Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) -* [Linter-ESLint for Atom](https://atom.io/packages/linter-eslint) (requires [Linter for Atom](https://atom.io/packages/linter)) -* [ESLint for Sublime Text](https://packagecontrol.io/packages/ESLint) - -::: tip -You can install each of these directly inside the editors themselves. For Visual Studio Code, press `Ctrl + Shift + X`. For Atom, press `Ctrl + ,` and click on "Install". For Sublime, press `Ctrl + Shift + P` and search for "Install Package" (available via [Package Control](https://packagecontrol.io/installation)). After that, you may then search for the appropriate plugin and install it through there. -::: - -## Setting up ESLint rules - -ESLint may display a lot of warnings and errors about your code when you start using it, but don't let this startle you. In order to get started, follow these steps: - -1. Create a file in your root directory named `.eslintrc.json` (where your main project file is located). -2. Copy the code below into the file. - -```json -{ - "extends": "eslint:recommended", - "env": { - "node": true, - "es6": true - }, - "parserOptions": { - "ecmaVersion": 2019 - }, - "rules": { - - } -} -``` - -This is the base of what an ESLint file will look like. The `rules` object is where you'll define what rules you want to apply to ESLint. For example, if you want to make sure you never miss a semicolon, the `"semi": ["error", "always"]` rule is what you'll want to add inside that object. - -You can find a list of all of ESLint's rules on their site, located [here](https://eslint.org/). There are indeed many rules and it may be overwhelming at first, but you'll only need to go through the list and define your file once. - -Alternatively, if you don't want to go through everything one-by-one on your own, you can use the ESLint file we use for this guide. - -```json -{ - "extends": "eslint:recommended", - "env": { - "node": true, - "es6": true - }, - "parserOptions": { - "ecmaVersion": 2019 - }, - "rules": { - "brace-style": ["error", "stroustrup", { "allowSingleLine": true }], - "comma-dangle": ["error", "always-multiline"], - "comma-spacing": "error", - "comma-style": "error", - "curly": ["error", "multi-line", "consistent"], - "dot-location": ["error", "property"], - "handle-callback-err": "off", - "indent": ["error", "tab"], - "max-nested-callbacks": ["error", { "max": 4 }], - "max-statements-per-line": ["error", { "max": 2 }], - "no-console": "off", - "no-empty-function": "error", - "no-floating-decimal": "error", - "no-inline-comments": "error", - "no-lonely-if": "error", - "no-multi-spaces": "error", - "no-multiple-empty-lines": ["error", { "max": 2, "maxEOF": 1, "maxBOF": 0 }], - "no-shadow": ["error", { "allow": ["err", "resolve", "reject"] }], - "no-trailing-spaces": ["error"], - "no-var": "error", - "object-curly-spacing": ["error", "always"], - "prefer-const": "error", - "quotes": ["error", "single"], - "semi": ["error", "always"], - "space-before-blocks": "error", - "space-before-function-paren": ["error", { - "anonymous": "never", - "named": "never", - "asyncArrow": "always" - }], - "space-in-parens": "error", - "space-infix-ops": "error", - "space-unary-ops": "error", - "spaced-comment": "error", - "yoda": "error" - } -} -``` - -The major points of this setup would be: - -* Allowing you to debug with `console.log()`; -* Prefer using `const` over `let` or `var`, as well as disallow `var`; -* Disapproving of variables with the same name in callbacks; -* Requiring single quotes over double quotes; -* Requiring semicolons. While it's not required in JavaScript, it's considered one of the most common best practices to follow; -* Requiring accessing properties to be on the same line; -* Requiring indenting to be done with tabs; -* Limiting nested callbacks to 4. If you hit this error, it is a good idea to consider refactoring your code. - -If your current code style is a bit different or you simply don't like a few of these rules, that's perfectly fine! Just head over to the [ESLint docs](https://eslint.org/docs/rules/), find the rule(s) you want to modify, and change them accordingly. diff --git a/Ajuda/guide-master/guide/requesting-more-content.md b/Ajuda/guide-master/guide/requesting-more-content.md deleted file mode 100644 index b947801..0000000 --- a/Ajuda/guide-master/guide/requesting-more-content.md +++ /dev/null @@ -1,11 +0,0 @@ -# Requesting more content - -Since this guide is made specifically for the discord.js community, we want to be sure to provide the most relevant and up-to-date content. We will, of course, make additions to the current pages and add new ones as we see fit, but fulfilling requests is how we know we're providing content you all want the most. - -Requests may be as simple as "add an example to the [miscellaneous examples](/popular-topics/miscellaneous-examples.html) page", or as elaborate as "add a page regarding [sharding](/sharding/)". We'll do our best to fulfill all requests, as long as they're reasonable. - -To make a request, simply head over to [the repo's issue tracker](https://github.com/discordjs/guide/issues) and [create a new issue](https://github.com/discordjs/guide/issues/new)! Title it appropriately, and let us know exactly what you mean inside the issue description. Make sure that you've looked around the site before making a request; what you want to request might already exist! - -::: tip -Remember that you can always [fork the repo](https://github.com/discordjs/guide) and [make a pull request](https://github.com/discordjs/guide/pulls) if you want to add anything to the guide yourself! -::: diff --git a/Ajuda/guide-master/guide/sequelize/README.md b/Ajuda/guide-master/guide/sequelize/README.md deleted file mode 100644 index 14d7e80..0000000 --- a/Ajuda/guide-master/guide/sequelize/README.md +++ /dev/null @@ -1,273 +0,0 @@ -# Storing data with Sequelize - -Sequelize is an object-relational-mapper, which means you can write a query using objects and have it run on almost any other database system that Sequelize supports. - -### Why use an ORM? - -The main benefit of using an ORM like Sequelize is that it allows you to write code that essentially looks like native JavaScript. As a side benefit, an ORM will allow you to write code that can run in almost every database system. Although databases generally adhere very closely to SQL, they each have their own slight nuances and differences. You can create a database-agnostic query using an ORM that works on multiple database systems. - -## A simple tag system - -For this tutorial, you will create a simple tag system. The tag system will allow you to add a tag, output a tag, edit the tag, show tag info, list tags, and delete a tag. -To begin, you should install Sequelize into your discord.js project. We will explain SQlite as the first storage engine and show how to use other databases later. Note that you will need node 7.6 or above to utilize the `async/await` operators. - -### Installing and using Sequelize - -Create a new project folder and run the following: - -```bash -$ npm install --save discord.js -$ npm install --save sequelize -$ npm install --save sqlite3 -``` - -::: danger -Make sure you use version 5 or later of Sequelize! Version 4 as used in this guide will pose a security threat. You can read more about this issue On the [Sequelize issue tracker](https://github.com/sequelize/sequelize/issues/7310). -::: - -After you have installed discord.js and Sequelize, you can start with the following skeleton code. The comment labels will tell you where to insert code lateron. - - - -```js -const Discord = require('discord.js'); -const Sequelize = require('sequelize'); - -const client = new Discord.Client(); -const PREFIX = '!'; - -// [alpha] -// [beta] - -client.once('ready', () => { - // [gamma] -}); - -client.on('message', async message => { - if (message.content.startsWith(PREFIX)) { - const input = message.content.slice(PREFIX.length).split(' '); - const command = input.shift(); - const commandArgs = input.join(' '); - - if (command === 'addtag') { - // [delta] - } else if (command === 'tag') { - // [epsilon] - } else if (command === 'edittag') { - // [zeta] - } else if (command === 'taginfo') { - // [theta] - } else if (command === 'showtags') { - // [lambda] - } else if (command === 'removetag') { - // [mu] - } - } -}); - -client.login('your-token-goes-here'); -``` - -### [alpha] Connection information - -The first step is to define the connection information. It should look something like this: - -```js -const sequelize = new Sequelize('database', 'user', 'password', { - host: 'localhost', - dialect: 'sqlite', - logging: false, - // SQLite only - storage: 'database.sqlite', -}); -``` - -`host` tells Sequelize where to look for the database. This will be localhost for most systems, as the database usually resides with the application. If you have a remote database however, then you can set it to that connection address. Otherwise, don't touch this unless you know what you're doing. -`dialect` refers to the database engine you are going to use. For this tutorial, it will be sqlite. -`logging` setting this to false disables the verbose output from Sequelize. Set it to true when you are trying to debug. -`storage` is a sqlite-only setting, because sqlite is the only database that stores all its data to a single file. - - -### [beta] Creating the model - -In any relational database, you need to create tables in order to store your data. For this simple tag system, four fields will be used. The table in the database will look something like this: - -| name | description | username | usage_count | -| --- | --- | --- | --- | -| bob | is the best | bob | 0 | -| tableflip | (╯°□°)╯︵ ┻━┻ | joe | 8 | - -In order to do that in Sequelize, you define a model based on this structure, as shown below. - -```js -/* - * equivalent to: CREATE TABLE tags( - * name VARCHAR(255), - * description TEXT, - * username VARCHAR(255), - * usage INT - * ); - */ -const Tags = sequelize.define('tags', { - name: { - type: Sequelize.STRING, - unique: true, - }, - description: Sequelize.TEXT, - username: Sequelize.STRING, - usage_count: { - type: Sequelize.INTEGER, - defaultValue: 0, - allowNull: false, - }, -}); -``` - -The model mirrors very closely to what is defined in the database. There will be a table with 4 fields called `name`, `description`, `userid`, and `usage_count`. -`sequelize.define()` takes two parameters. `'tags'` is passed as the name of our table, and an object that represents the table's schema in key-value pairs. Keys in the object become the model's attributes, and the values describe the attributes. - -`type` refers to what kind of data this attribute should hold. The most common types are number, string, and date, but there are other data types that are available depending on the database. -`unique: true` will ensure that this field will never have duplicated entries. Duplicate tag names will be disalowed in this database. -`defaultValue` allows you to set a fallback value if no value is set during the insert. -`allowNull` is not all that important, but this will guarantee in the database that the attribute is never unset. You could potentially set it to be a blank or empty string, but has to be set to _something_. - -::: tip -`Sequelize.STRING` vs `Sequelize.TEXT`: In most database systems, the length of the string is a fixed length for performance reasons. Sequelize defaults this to 255. Use STRING if your input has a max length, and use TEXT if does not. For sqlite, there is no unbounded string type so it will not matter which one you pick. -::: - -### [gamma] Syncing the model - -Now that your structure is defined, you need to make sure the model exists in the database. This goes in our `.once('ready')` event. This way the table structure gets created when the bot is ready and we do not need to worry about it later. -```js -Tags.sync(); -``` - -The table does not actually get created until you `sync` it. The schema you defined from before was simply creating the model that lets Sequelize know what the data should look like. For testing, you can use `Tags.sync({ force: true })` to recreate the table every time on startup. This way you can get blank slate each time. - -### [delta] Adding a tag - -After all this preperation, you can now write your first command! We will start off with the ability to add a tag. - - - -```js -const splitArgs = commandArgs.split(' '); -const tagName = splitArgs.shift(); -const tagDescription = splitArgs.join(' '); - -try { - // equivalent to: INSERT INTO tags (name, description, username) values (?, ?, ?); - const tag = await Tags.create({ - name: tagName, - description: tagDescription, - username: message.author.username, - }); - return message.reply(`Tag ${tag.name} added.`); -} -catch (e) { - if (e.name === 'SequelizeUniqueConstraintError') { - return message.reply('That tag already exists.'); - } - return message.reply('Something went wrong with adding a tag.'); -} -``` - -`Tags.create()` uses the models that you created previously. The `.create()` method inserts some data into the model. You are going to insert a tag name, description, and the author name into the database. -`catch (e)` This section is necessary for the insert. This will offload checking for duplicates to the database, so that it will notify you if you attempt to create a tag that already exists. The alternative is to query the database before adding data, and checking if a result is returned. If there are no errors, or no identical tag is found, only then should you add the data. Of the two methods it is clear that catching the error is less work for yourself. -`if (e.name === "SequelizeUniqueConstraintError")` Although this was mostly for doing less work, it is always good to handle your errors, especially if you know what types of errors you will receive. This error comes up if your unique constraint is violated, i.e. someone inserted duplicate values. - -::: warning -Do not use catch for inserting new data. Only use it for gracefully handling things that go wrong in your code, or logging errors. -::: - -### [epsilon] Fetching a tag - -Next we will explain how to fetch the tag that was just inserted. - - - -```js -const tagName = commandArgs; - -// equivalent to: SELECT * FROM tags WHERE name = 'tagName' LIMIT 1; -const tag = await Tags.findOne({ where: { name: tagName } }); -if (tag) { - // equivalent to: UPDATE tags SET usage_count = usage_count + 1 WHERE name = 'tagName'; - tag.increment('usage_count'); - return message.channel.send(tag.get('description')); -} -return message.reply(`Could not find tag: ${tagName}`); -``` - -This is your first query. You are finally doing something with our data, yay! -`.findOne()` is how you fetch a single row of data. The `where: { name: tagName }` makes sure you only get the row with the desired tag. Since the queries are asynchronous, you will need to make use of `await` in order to fetch it. After receiving the data, you can use `.get()` on that object to grab the data. If no data is received, then you can tell the user that it was not found. - -### [zeta] Editing a tag - - - -```js -const splitArgs = commandArgs.split(' '); -const tagName = splitArgs.shift(); -const tagDescription = splitArgs.join(' '); - -// equivalent to: UPDATE tags (descrption) values (?) WHERE name='?'; -const affectedRows = await Tags.update({ description: tagDescription }, { where: { name: tagName } }); -if (affectedRows > 0) { - return message.reply(`Tag ${tagName} was edited.`); -} -return message.reply(`Could not find a tag with name ${tagName}.`); -``` - -It is possible to edit a record by using the `.update()` function. The result from the update is the number of rows that were changed by the `where` condition. Since you can only have tags with unique names, you do not have to worry about how many rows it may change. Should you get that no rows were changed, then it can be concluded that the tag that was trying to be edited did not exist. - -### [theta] Display info on a specific tag - - - -```js -const tagName = commandArgs; - -// equivalent to: SELECT * FROM tags WHERE name = 'tagName' LIMIT 1; -const tag = await Tags.findOne({ where: { name: tagName } }); -if (tag) { - return message.channel.send(`${tagName} was created by ${tag.username} at ${tag.createdAt} and has been used ${tag.usage_count} times.`); -} -return message.reply(`Could not find tag: ${tagName}`); -``` - -This section is very similar to our previous command, except you will be showing the tag metadata. `tag` contains our tag object. Notice two things here: firstly, it is possible to access our object properties without the `.get()` function. This is because the object is an instance of a Tag, which you can treat as an object, and not just a row of data. Second, you can access a property that was not defined explicitly, `createdAt`. This is because Sequelize automatically adds that column to all tables. This feature can be disabled by passing another object into the model with `{ createdAt: false }`, but in this case, it was useful to have. - -### [lambda] Listing all tags - -The next command will enable you to fetch a list of all the tags that were created so far. - - - -```js -// equivalent to: SELECT name FROM tags; -const tagList = await Tags.findAll({ attributes: ['name'] }); -const tagString = tagList.map(t => t.name).join(', ') || 'No tags set.'; -return message.channel.send(`List of tags: ${tagString}`); -``` - -Here, you can use the `.findAll()` method to grab all the tag names. Notice that instead of having `where`, the optional field, `attributes`, is set. Setting attributes to name will let you get *only* the names of tags. If you tried to access other fields, like the tag author, then you would get an error. If left blank, it will fetch *all* of the associated column data. It will not actually affect the results, but from a performance perspective, you should only grab the data that is needed. If no results are returned, `tagString` will default to 'No tags set'. - -### [mu] Deleting a tag - - - -```js -const tagName = commandArgs; -// equivalent to: DELETE from tags WHERE name = ?; -const rowCount = await Tags.destroy({ where: { name: tagName } }); -if (!rowCount) return message.reply('That tag did not exist.'); - -return message.reply('Tag deleted.'); -``` -`.destroy()` runs the delete operation. The operation returns a count of the number of affected rows. If it returns with a value of 0, then nothing was deleted and that tag did not exist in the database in the first place. - - -## Resulting code - - diff --git a/Ajuda/guide-master/guide/sequelize/currency.md b/Ajuda/guide-master/guide/sequelize/currency.md deleted file mode 100644 index 861b4fc..0000000 --- a/Ajuda/guide-master/guide/sequelize/currency.md +++ /dev/null @@ -1,370 +0,0 @@ -# Making a Currency System - -A common feature of Discord bots is a currency system. It's possible to do everything in one object, but we can also abstract that in terms of *relations* between objects. This is where the power of a RDBMS (Relational Database Management System) truly shines. Sequelize calls these *associations*, so we'll be using that term from now on. - -## File overview - -There will be multiple files: a DB init script, your models, and your bot script. In the previous tutorial, we placed all of these in the same file. Having everything in one file is usually not how it's done in the real world, so we'll correct that. - -This time we'll have 6 files. - -* `app.js` is where we'll keep the main bot code. -* `dbInit.js` is the initialization file for the database. We run this once and forget about it. -* `dbObjects.js` is where we'll import the models and create associations here. -* `models/Users.js` is the Users model. Users will have a currency attribute in here. -* `models/CurrencyShop.js` is the Shop model. The shop will have a name and a price for each item. -* `models/UserItems.js` is the junction table between the users and the shop. A junction table is used to connect two tables together. Our junction table will have an additional field for the amount of that item the user has. - -## Create models - -Here is an entity relation diagram of the models we'll be making: - -Curreny database structure diagram - -`Users` have a `user_id`, and a `balance`. Each `user_id` can have multiple links to the `UserItems` table, and each entry in the table is connected to one of the items in the `CurrencyShop`, which will have a `name` and a `cost` associated with it. - -To implement this, we'll begin by making a `models` folder and create a `Users.js` file inside which contains the following: - -```js -module.exports = (sequelize, DataTypes) => { - return sequelize.define('users', { - user_id: { - type: DataTypes.STRING, - primaryKey: true, - }, - balance: { - type: DataTypes.INTEGER, - defaultValue: 0, - allowNull: false, - }, - }, { - timestamps: false, - }); -}; -``` - -Like you see in the diagram above, our Users model will only have 2 attributes: a `user_id` primary key and a `balance`. A primary key is a special type of attribute that becomes the default column used when joining tables together. In addition, a primary key is automatically set as unique and not null. - -Balance also sets `allowNull` to `false`. This, in conjunction with setting a primary key, means that both values have to be set, otherwise the database would throw an error. This means that we guarantee correctness in our data storage in that we never have null or empty values. This ensures that if we somehow forget to validate in the application that both values are not null, our database would do the final validation for us. - -Notice that our options object sets `timestamps` to `false`. This disables the `createdAt` and the `updatedAt` columns that sequelize usually creates for you. Setting `user_id` to primary also gets rid of the `id` primary key that Sequelize usually generates for you, since there can only be one primary key on a table. - -Next, still in the same `models` folder, create a `CurrencyShop.js` file that contains the following: - -```js -module.exports = (sequelize, DataTypes) => { - return sequelize.define('currency_shop', { - name: { - type: DataTypes.STRING, - unique: true, - }, - cost: { - type: DataTypes.INTEGER, - allowNull: false, - }, - }, { - timestamps: false, - }); -}; -``` - -Like our Users model, we don't need the timestamps here, so we'll disable it. Unlike the Users model however, we only set `unique` to `true` here. This is so that if you want to change the name of the item, you can change the name without affecting the primary key that joins this to the next object. This gets generated automatically by sequelize since we didn't set a primary key. - -The next file will be `UserItems.js`, our junction table. - -```js -module.exports = (sequelize, DataTypes) => { - return sequelize.define('user_item', { - user_id: DataTypes.STRING, - item_id: DataTypes.STRING, - amount: { - type: DataTypes.INTEGER, - allowNull: false, - 'default': 0, - }, - }, { - timestamps: false, - }); -}; -``` - -Our junction table will link `user_id` and the `id` of the currency shop together. It also contains an `amount` number which indicates how many of that item a user has. - -## Initialize database - -Now that the models are defined, we should create them in our database so that we can access them in the bot file. We ran the sync in the `ready` event in our bot in the previous tutorial, which is completely unnecessary, since it only needs to run once. So what we can do is make a file to initialize the database and never touch it again unless we want to remake the entire database. - -Create a file called `dbInit.js` in the base directory (*not* in the `models` folder). - -::: danger -Make sure you use version 5 or later of Sequelize! Version 4 as used in this guide will pose a security threat. You can read more about this issue On the [Sequelize issue tracker](https://github.com/sequelize/sequelize/issues/7310). -::: - -```js -const Sequelize = require('sequelize'); - -const sequelize = new Sequelize('database', 'username', 'password', { - host: 'localhost', - dialect: 'sqlite', - logging: false, - storage: 'database.sqlite', -}); - -const CurrencyShop = sequelize.import('models/CurrencyShop'); -sequelize.import('models/Users'); -sequelize.import('models/UserItems'); - -const force = process.argv.includes('--force') || process.argv.includes('-f'); - -sequelize.sync({ force }).then(async () => { - const shop = [ - CurrencyShop.upsert({ name: 'Tea', cost: 1 }), - CurrencyShop.upsert({ name: 'Coffee', cost: 2 }), - CurrencyShop.upsert({ name: 'Cake', cost: 5 }), - ]; - await Promise.all(shop); - console.log('Database synced'); - sequelize.close(); -}).catch(console.error); -``` - -You'll notice some familiar things here from the previous tutorial, such as the Sequelize declaration being the same. We do have something different here, and that's how we import the models. Sequelize has an import function to make your code a bit cleaner when you have many models to use. We pull the two models and the junction table, sync them, and add items to our shop. - -A new function here is the `.upsert()` function. It's a portmanteau for **up**date or in**sert**. We use `upsert` here because just in case you run this file multiple times, it doesn't create duplicates. That shouldn't happen because we defined name as *unique* but there's no harm in being safe. Upsert also has a nice side benefit; If you adjust the cost, the respective item should also have their cost updated. - -::: tip -Execute `node dbInit.js` to create the database tables. Unless you make a change to the models, you'll never need to touch the file again. If you do make a change to a model, you can execute `node dbInit.js --force` or `node dbInit.js -f` to force sync your tables. It's important to note that this **will** empty out and remake your model tables. -::: - -## Create associations - -Next we'll add our associations to the models. Create a file named `dbObjects.js` in the base directory, next to `dbInit.js`. - -```js -const Sequelize = require('sequelize'); - -const sequelize = new Sequelize('database', 'username', 'password', { - host: 'localhost', - dialect: 'sqlite', - logging: false, - storage: 'database.sqlite', -}); - -const Users = sequelize.import('models/Users'); -const CurrencyShop = sequelize.import('models/CurrencyShop'); -const UserItems = sequelize.import('models/UserItems'); - -UserItems.belongsTo(CurrencyShop, { foreignKey: 'item_id', as: 'item' }); - -Users.prototype.addItem = async function(item) { - const userItem = await UserItems.findOne({ - where: { user_id: this.user_id, item_id: item.id }, - }); - - if (userItem) { - userItem.amount += 1; - return userItem.save(); - } - - return UserItems.create({ user_id: this.user_id, item_id: item.id, amount: 1 }); -}; - -Users.prototype.getItems = function() { - return UserItems.findAll({ - where: { user_id: this.user_id }, - include: ['item'], - }); -}; - -module.exports = { Users, CurrencyShop, UserItems }; -``` - -Note that we could have abstracted the connection object in another file, and had both `dbInit.js` and `dbObjects.js` use that connection file, but it's not necessary to overly abstract things. - -The new method we haven't seen yet is the `.belongsTo()` method. Using this method, we add `CurrencyShop` as a property of `UserItem` so that when we do `userItem.item` we get the respective item that it's attached to. We use `item_id` as the foreign key so that it knows which item to attach. - -We now add some prototypes to the User object to finish up the junction: add items to users, and get their current inventory. The code inside should be somewhat familar from the last tutorial. We use a `.findOne()` to get the item if it exists in the user's inventory. We increment if it does, or create it if it doesn't. - -Getting items is similar, we just `.findAll()` using the user's id as the key. The `include` key is for associating the CurrencyShop with the item. We basically have to explicitly tell Sequelize to honor the `.belongsTo()` association, otherwise it will take the path of least effort. - -## Application code - -To put it together, we'll create an `app.js` in the base directory with the following skeleton code. - - - -```js -const Discord = require('discord.js'); - -const client = new Discord.Client(); -const { Users, CurrencyShop } = require('./dbObjects'); -const { Op } = require('sequelize'); -const currency = new Discord.Collection(); -const PREFIX = '!'; - -// [alpha] - -client.once('ready', async () => { - // [beta] - console.log(`Logged in as ${client.user.tag}!`); -}); - -client.on('message', async message => { - if (message.author.bot) return; - currency.add(message.author.id, 1); - - if (!message.content.startsWith(PREFIX)) return; - const input = message.content.slice(PREFIX.length).trim(); - if (!input.length) return; - const [, command, commandArgs] = input.match(/(\w+)\s*([\s\S]*)/); - - if (command === 'balance') { - // [gamma] - } else if (command === 'inventory') { - // [delta] - } else if (command === 'transfer') { - // [epsilon] - } else if (command === 'buy') { - // [zeta] - } else if (command === 'shop') { - // [theta] - } else if (command === 'leaderboard') { - // [lambda] - } -}); - -client.login('your-token-goes-here'); -``` - -Nothing special about this skeleton. We import the Users and CurrencyShop models from our `dbObjects.js` file, and add a currency Collection. Every time someone talks, we add 1 to their currency count. The rest is just standard discord.js code and a simple if/else command handler. We're using the currency Collection in order to cache individual user's currency, so we don't have to hit the database for every lookup. I've used an if/else handler here, but you can put it in a framework or command handler as long as you maintain a reference to the models and the currency collection. - -### [alpha] Helper methods - -```js -Reflect.defineProperty(currency, 'add', { - value: async function add(id, amount) { - const user = currency.get(id); - if (user) { - user.balance += Number(amount); - return user.save(); - } - const newUser = await Users.create({ user_id: id, balance: amount }); - currency.set(id, newUser); - return newUser; - }, -}); - -Reflect.defineProperty(currency, 'getBalance', { - value: function getBalance(id) { - const user = currency.get(id); - return user ? user.balance : 0; - }, -}); -``` - -We're defining an `.add()` method to our currency collection. It'll be used quite frequently, so having a method for it makes our lives easier. We'll also add a `.getBalance()` method so that we'll always get a number. - -### [beta] Ready event data sync - - - -```js -const storedBalances = await Users.findAll(); -storedBalances.forEach(b => currency.set(b.user_id, b)); -``` - -In our ready event, we want to sync our currency collection with the database for easy access later. - -### [gamma] Show user balance - -```js -const target = message.mentions.users.first() || message.author; -return message.channel.send(`${target.tag} has ${currency.getBalance(target.id)}💰`); -``` - -Nothing tricky here. We use our `.getBalance()` method to show either the author's or the mentioned user's balance - -### [delta] Show user inventory - - - -```js -const target = message.mentions.users.first() || message.author; -const user = await Users.findOne({ where: { user_id: target.id } }); -const items = await user.getItems(); - -if (!items.length) return message.channel.send(`${target.tag} has nothing!`); -return message.channel.send(`${target.tag} currently has ${items.map(i => `${i.amount} ${i.item.name}`).join(', ')}`); -``` -Here we begin to see the power of associations. Even though users and the shop are different tables, and the data is stored separately, we can get a user's inventory by looking at the junction table and join it with the shop. No duplicated item names that waste space! - -### [epsilon] Transfer currency to another user - -```js -const currentAmount = currency.getBalance(message.author.id); -const transferAmount = commandArgs.split(/ +/g).find(arg => !/<@!?\d+>/g.test(arg)); -const transferTarget = message.mentions.users.first(); - -if (!transferAmount || isNaN(transferAmount)) return message.channel.send(`Sorry ${message.author}, that's an invalid amount.`); -if (transferAmount > currentAmount) return message.channel.send(`Sorry ${message.author}, you only have ${currentAmount}.`); -if (transferAmount <= 0) return message.channel.send(`Please enter an amount greater than zero, ${message.author}.`); - -currency.add(message.author.id, -transferAmount); -currency.add(transferTarget.id, transferAmount); - -return message.channel.send(`Successfully transferred ${transferAmount}💰 to ${transferTarget.tag}. Your current balance is ${currency.getBalance(message.author.id)}💰`); -``` -As a bot creator, you should always be thinking about how to make the user experience better. Good UX makes users less frustrated with your commands. If your input are different types, don't make them memorize which parameters come before the other. - -We want to be able to allow users to do both `!transfer 5 @user` and `!transfer @user 5`. So what we're going to do is grab the first non-mention text in the command. In the second line of the above code, we split the command by spaces, and then we look for anything that doesn't match a mention, and we'll assume that's the transfer amount. Then we do some checking to make sure it's a valid input. You can also do error checking on the transfer target, but that's trivial, so it won't be included here. - -We use `.add()` for both removing and adding currency. Since we already check if the transfer amount is below zero, it will be safe to apply the additive inverse of the transfer amount to their balance. - -### [zeta] Buying an item - - - -```js -const item = await CurrencyShop.findOne({ where: { name: { [Op.like]: commandArgs } } }); -if (!item) return message.channel.send(`That item doesn't exist.`); -if (item.cost > currency.getBalance(message.author.id)) { - return message.channel.send(`You currently have ${currency.getBalance(message.author.id)}, but the ${item.name} costs ${item.cost}!`); -} - -const user = await Users.findOne({ where: { user_id: message.author.id } }); -currency.add(message.author.id, -item.cost); -await user.addItem(item); - -message.channel.send(`You've bought: ${item.name}.`); -``` - -In order for users to search for an item without having to care about case, we use the `$iLike` modifier when we're looking for the name. Keep in mind that this may be slow if you have millions of items, so please don't put a million items in your shop. - -### [theta] Display the shop - - - -```js -const items = await CurrencyShop.findAll(); -return message.channel.send(items.map(item => `${item.name}: ${item.cost}💰`).join('\n'), { code: true }); -``` -Nothing special here, just a regular `.findAll()` to get all the items in the shop, and `.map()` to transform that data into something nice looking. - -### [lambda] Display the leaderboard - -```js -return message.channel.send( - currency.sort((a, b) => b.balance - a.balance) - .filter(user => client.users.has(user.user_id)) - .first(10) - .map((user, position) => `(${position + 1}) ${(client.users.get(user.user_id).tag)}: ${user.balance}💰`) - .join('\n'), - { code: true } -); -``` - -Nothing particularly special here either. We could have queried the database for the top 10 currency holders as well, but we already have access to them locally, so just sort the Collection we have and use map again to display in a nice format. The filter is in case the users no longer exist in the bot's cache. - -## Resulting code - - diff --git a/Ajuda/guide-master/guide/sharding/README.md b/Ajuda/guide-master/guide/sharding/README.md deleted file mode 100644 index 433e9bf..0000000 --- a/Ajuda/guide-master/guide/sharding/README.md +++ /dev/null @@ -1,152 +0,0 @@ -# Getting started - -## When to shard - -Before you dive into this section, please note that sharding may not be necessary for you. Sharding is only necessary at 2,500 guilds—at that point, Discord will not allow your bot to login. With that in mind, you should consider this when your bot is around 2,000 guilds, which should be enough time to get this working. Contrary to popular belief, sharding itself is very simple. It can be complex depending on your bot's needs, however. If your bot is in a total of 2,000 or more servers, then please continue with this guide. Otherwise, it may be a good idea to wait until then. - -## How does sharding work? - -As an application grows large, developers may find it necessary to split their process up to run parallel to one another in order to maximize efficiency. In a much larger scale of things, the developer might notice their process slow down, amongst other problems. -[Check out the official Discord documentation on the topic.](https://discordapp.com/developers/docs/topics/gateway#sharding) - -## Sharding file - -First, you'll need to have a file that you'll be launching from now on, rather than your original `index.js` file. It's highly recommended renaming that to `bot.js` and naming this new file to `index.js` instead. Copy & paste the following snippet into your new `index.js` file. - -```js -const { ShardingManager } = require('discord.js'); -const manager = new ShardingManager('./bot.js', { token: 'your-token-goes-here' }); - -manager.spawn(); -manager.on('launch', shard => console.log(`Launched shard ${shard.id}`)); -``` - -The above code utilizes discord.js's sharding manager to spawn the recommended amount of shards for your bot. The recommended amount should be approximately 1,000 guilds per shard. Even though you provide the token here, you will still need to send it over to the main bot file in `client.login()`, so don't forget to do that. - -::: tip -You can find the methods available for the ShardingManager class [here](https://discord.js.org/#/docs/main/11.5.1/class/ShardingManager)[here](https://discord.js.org/#/docs/main/master/class/ShardingManager). Though, you may not be making much use of this section, unlike the next feature we will explore, which you may learn about by clicking [this link](/sharding/additional-information.md). -::: - -## Getting started - -You will most likely have to change some code in order to get your newly sharded bot to work. If your bot is very basic, then you're in luck! I assume you probably have a `stats` command, by which you can quickly view your bots statistics, such as its server count. In this code, you likely have the snippet `client.guilds.size`, which counts the number of *cached* guilds attached to that client. With sharding, since multiple processes will be launched, each process (each shard) will now have its own subset collection of guilds. This means that your original code will not function as you expect it to. Here is some sample code for a `stats` command, without sharding taken into consideration. - -```js -// bot.js -const Discord = require('discord.js'); -const client = new Discord.Client(); -const prefix = '!'; - -client.on('message', message => { - if (!message.content.startsWith(prefix) || message.author.bot) return; - - const args = message.content.slice(prefix.length).split(/ +/); - const command = args.shift().toLowerCase(); - - if (command === 'stats') { - return message.channel.send(`Server count: ${client.guilds.size}`); - } -}); - -client.login('token'); -``` - -Let's say your bot is in a total of 3,600 guilds. Using the recommended shard count you might end up at 4 shards, the first 3 containing 1,000 guilds each and the last one containing the remaining 600. If a guild is on a certain shard (shard #2, for example) and it receives this command, the guild count will be 1,000, which is obviously not the "correct" number of guilds for your bot. Likewise, if the message is received on a guild in shard 3 (shard IDs are zero-indexed), the guild count will be 600, which is still not what you want. "How can I fix this?", you ask? Well, that's why we're here, isn't it? - -## FetchClientValues - -First, let's take a look at [one of the most common sharding utility methods you'll be using](https://discord.js.org/#/docs/main/11.5.1/class/ShardClientUtil?scrollTo=fetchClientValues)[one of the most common sharding utility methods you'll be using](https://discord.js.org/#/docs/main/master/class/ShardClientUtil?scrollTo=fetchClientValues) called `fetchClientValues`. This method retrieves a client property of all shards. - -Now, take the following snippet of code: - -```js -client.shard.fetchClientValues('guilds.size').then(console.log); -``` - -If you run it, you will notice an output like `[1000, 1000, 1000, 600]`. You will be correct in assuming that that's the total number of guilds per shard, which is stored in an array in the Promise. We can both assume this isn't the ideal output for guild count, so we will need to make use of an array manipulation method, specifically [Array.reduce()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce). - -It's highly urged for you to visit that link to understand how the method works, as you will probably find great use of it in sharding. Basically, this method (in this case) iterates through the array and adds each current value to the total amount. - -```js -client.shard.fetchClientValues('guilds.size') - .then(results => { - console.log(`${results.reduce((prev, guildCount) => prev + guildCount, 0)} total guilds`); - }) - .catch(console.error); -``` - -While it's a bit unattractive to have more nesting in your commands, it is necessary when not using `async`/`await`. Now, the code at the top should look something like the below: - -```diff - if (command === 'stats') { -- return message.channel.send(`Server count: ${client.guilds.size}`); -+ return client.shard.fetchClientValues('guilds.size') -+ .then(results => { -+ return message.channel.send(`Server count: ${results.reduce((prev, guildCount) => prev + guildCount, 0)}`); -+ }) -+ .catch(console.error); - } -``` - -## BroadcastEval - -Next, check out [another handy sharding method](https://discord.js.org/#/docs/main/11.5.1/class/ShardClientUtil?scrollTo=broadcastEval)[another handy sharding method](https://discord.js.org/#/docs/main/master/class/ShardClientUtil?scrollTo=broadcastEval) known as `broadcastEval`. This method makes all of the shards evaluate a given script, where `this` is the `client` once each shard gets to evaluating it. You can read more about the `this` keyword [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this). For now, essentially understand that it is the "client" object. - -```js -client.shard.broadcastEval('this.guilds.reduce((prev, guild) => prev + guild.memberCount, 0)').then(console.log); -``` - -This will run the code given to `broadcastEval` on each shard and return the results to the Promise as an array, once again. You should see something like `[9001, 16658, 13337, 15687]` logged. The code being sent to each shard adds up the `memberCount` property of every guild that shard is handling and returns it, so it's each shard's total guild member count. Of course, if you want to then total up the member count of *every* shard, you can do the same thing again on the results returned from the Promise. - -```js -client.shard.broadcastEval('this.guilds.reduce((prev, guild) => prev + guild.memberCount, 0)') - .then(results => { - return message.channel.send(`Total member count: ${results.reduce((prev, memberCount) => prev + memberCount, 0)}`); - }) - .catch(console.error); -``` - -## Putting them together - -You'd likely want to output both pieces of information in the stats command, so let's combine these two examples using [Promise.all()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all): - -```js -const promises = [ - client.shard.fetchClientValues('guilds.size'), - client.shard.broadcastEval('this.guilds.reduce((prev, guild) => prev + guild.memberCount, 0)'), -]; - -Promise.all(promises) - .then(results => { - const totalGuilds = results[0].reduce((prev, guildCount) => prev + guildCount, 0); - const totalMembers = results[1].reduce((prev, memberCount) => prev + memberCount, 0); - return message.channel.send(`Server count: ${totalGuilds}\nMember count: ${totalMembers}`); - }) - .catch(console.error); -``` - -`Promise.all()` runs every promise you pass to it inside of an array in parallel, and waits for them all to finish before returning all of their results at once. The result is an array that corresponds with the array of promises you pass - so the first result element will be from the first promise. With that, your stats command should look something like this: - -```diff - if (command === 'stats') { -- return message.channel.send(`Server count: ${client.guilds.size}`); -+ const promises = [ -+ client.shard.fetchClientValues('guilds.size'), -+ client.shard.broadcastEval('this.guilds.reduce((prev, guild) => prev + guild.memberCount, 0)'') -+ ]; -+ -+ return Promise.all(promises) -+ .then(results => { -+ const totalGuilds = results[0].reduce((prev, guildCount) => prev + guildCount, 0); -+ const totalMembers = results[1].reduce((prev, memberCount) => prev + memberCount, 0); -+ return message.channel.send(`Server count: ${totalGuilds}\nMember count: ${totalMembers}`); -+ }) -+ .catch(console.error); - } -``` - -The next section contains additional changes you might want to take into consideration, which you may learn about by clicking [this link](/sharding/additional-information.md). - -## Resulting code - - diff --git a/Ajuda/guide-master/guide/sharding/additional-information.md b/Ajuda/guide-master/guide/sharding/additional-information.md deleted file mode 100644 index 6de0a70..0000000 --- a/Ajuda/guide-master/guide/sharding/additional-information.md +++ /dev/null @@ -1,114 +0,0 @@ -# Additional information - -::: tip -This page is a follow-up and bases its code off of [the previous page](/sharding/). -::: - -Here are some extra topics covered about sharding that you might have concerns about. - -## Legend - -* `manager` is an instance of `ShardingManager`, e.g. `const manager = new ShardingManager(file, options);` -* `client.shard` refers to the current shard. - -## Shard messages - -In order for shards to communicate, they must send messages to one another, as they are each their own process. You can listen for these messages by adding the following listener in your `index.js` file: - -```js -manager.on('message', (shard, message) => { - console.log(`Shard[${shard.id}] : ${message._eval} : ${message._result}`); -}); -``` - -As the property names imply, the `_eval` property is what the shard is attempting to evaluate, and the `_result` property is the output of said evaluation. However, these properties are only guaranteed if a _shard_ is sending a message. There will also be an `_error` property, should the evaluation have thrown an error. - -You can also send messages via `process.send('hello')`, which would not contain the same information. This is why the `.message` property's type is declared as `*` [in the discord.js documentation](https://discord.js.org/#/docs/main/11.5.1/class/Shard?scrollTo=e-message)[in the discord.js documentation](https://discord.js.org/#/docs/main/master/class/Shard?scrollTo=e-message). - -## Specific shards - -There might be times where you want to target a specific shard. An example would be to kill a specific shard that isn't working as intended. You can achieve this by taking the following snippet (in a command, preferably): - -```js -client.shard.broadcastEval('if (this.shard.id === 0) process.exit();'); -``` - -If you're using something like [PM2](http://pm2.keymetrics.io/) or [Forever](https://github.com/foreverjs/forever), this is an easy way to restart a specific shard. Remember, [Shard#BroadcastEval](https://discord.js.org/#/docs/main/11.5.1/class/ShardClientUtil?scrollTo=broadcastEval)[Shard#BroadcastEval](https://discord.js.org/#/docs/main/master/class/ShardClientUtil?scrollTo=broadcastEval) sends a message to **all** shards, so you have to check if it's on the shard you want. - -## `ShardingManager#shardArgs` - -Consider the following example of creating a new `ShardingManager` instance: - -```js -const manager = new ShardingManager('./bot.js', { - shardArgs: ['--ansi', '--color', '--trace-warnings'], - token: 'your-token-goes-here', -}); -``` - -The `shardArgs` property is what you would normally pass in if you executed your bot process without sharding, e.g.: - -``` -node bot.js --ansi --color --trace-warnings -``` - -Should you need them for whatever reason, they're available in `process.argv` property, which contains an array of command-line arguments used to execute the script. - -## Eval arguments - -There may come a point where you will want to pass functions or arguments from the outer scope into a `.broadcastEval()` call. - -```js -client.shard.broadcastEval(`(${funcName})('${arg}')`); -``` - -In this small snippet, an entire function is being passed to the eval. It needs to be encased in parenthesis; it will throw errors on its way there otherwise. Another set of parenthesis is needed so the function actually gets called. Finally, the passing of the argument itself, which slightly varies, depending on the type of argument you are passing. If it's a string, you must wrap it in quotes, or it will be interpreted as is and will throw a syntax error, because it won't be a string by the time it gets there. - -Now, what if you wanted to call a function from *within* the client context? That is to say, you are not passing a function. It would look something like this: - -```js -client.shard.broadcastEval(`this.${funcName}(${args});`); -``` - -This would become `client.funcName(args)` once it gets through. This is handy if you, for example, have extended your client object with your own class and wish to call some of its methods manually. - -### Asynchronous functions - -There may be a time when you want to have your shard process an asynchronous function. Here's how you can do that! - -```js -client.shard.broadcastEval(` - let channel = this.channels.get('id'); - let msg; - if (channel) { - msg = channel.fetchMessage('id').then(m => m.id); - } - msg; -`); -``` - -This snippet allows you to return fetched messages outside of the `broadcastEval`, allowing you to know whether or not you were able to retrieve a message, for example. Remember, you aren't able to return entire objects outside. Now, what if we wanted to use `async/await` syntax inside? - -```js -client.shard.broadcastEval(` - (async () => { - let channel = this.channels.get('id'); - let msg; - if (channel) { - msg = await channel.fetchMessage('id').then(m => m.id); - } - return msg; - })(); -`); -``` - -This example will work the same, but you are able to produce cleaner code with `async/await`. Additionally. What this does is declare an asynchronous function and then immediately call it. As it is also the last declared line, it is effectively being returned. Remember that you need to `return` an item inside a function one way or another. - -## Sharded Bot Example(s) - -If you'd like to check out a full example of sharding, here are the open-source examples we've found: - -* [Listen.moe](https://github.com/LISTEN-moe/discord-bot) -* [Bastion](https://github.com/TheBastionBot/Bastion) - -If you know of other open-source bots that are sharded and use discord.js, feel free to [make a pull request](https://github.com/discordjs/guide/blob/master/guide/sharding/additional-information.md)! diff --git a/Ajuda/guide-master/guide/sharding/extended.md b/Ajuda/guide-master/guide/sharding/extended.md deleted file mode 100644 index adde211..0000000 --- a/Ajuda/guide-master/guide/sharding/extended.md +++ /dev/null @@ -1,202 +0,0 @@ -## Extended changes - -::: tip -This page is a follow-up and bases its code off of [the previous page](/sharding/additional-information.md), which assumes knowledge of arguments and passing functions. -::: - -### Sending messages across shards - -Let's start off with a basic usage with shards. At some point in bot development, you might have wanted to send a message to another channel, which may or may not necessarily be on the same guild, which means it may or may not be on the same shard. To remedy this, you will need to go back to your friend `.broadcastEval()` and try every shard for the desired channel. Suppose you have the following code in your `message` event: - -```js -client.on('message', message => { - if (!message.content.startsWith(prefix) || message.author.bot) return; - - const args = message.content.slice(prefix.length).split(/ +/); - const command = args.shift().toLowerCase(); - - if (command === 'send') { - if (!args.length) return message.reply('please specify a destination channel id.'); - - const channel = client.channels.get(args[0]); - if (!channel) return message.reply('I could not find such a channel.'); - - channel.send('Hello!'); - return message.reply(`I have sent a message to channel \`${args[0]}\`!`); - } -}); -``` - -This will never work for a channel that lies on another shard. So, let's remedy this. - -```diff - if (command === 'send') { - if (!args.length) return message.reply('please specify a destination channel id.'); - -- const channel = client.channels.get(args[0]); -- if (!channel) return message.reply('I could not find such a channel.'); - -- channel.send('Hello!'); -- return message.reply(`I have sent a message to channel \`${args[0]}\`!`); -+ return client.shard.broadcastEval(` -+ const channel = this.channels.get('${args[0]}'); -+ if (channel) { -+ channel.send('This is a message from shard ${this.shard.id}!'); -+ true; -+ } -+ else { -+ false; -+ } -+ `) -+ .then(console.log); - } -``` - -If all is well, then you should notice an output like the following: `[false, true, false, false]`. If it is not clear why `true` and `false` are hanging around, it's because the last expression of the eval statement is what will be returned. You will want this if you want any feedback in the results. Now that you have observed said results, you can adjust the command to give yourself proper feedback, like so: - -```diff - return client.shard.broadcastEval(` - const channel = this.channels.get('${args[0]}'); - if (channel) { - channel.send('This is a message from shard ${this.shard.id}!'); - true; - } - else { - false; - } - `) -- .then(console.log); -+ .then(sentArray => { -+ // Search for a non falsy value before providing feedback -+ if (!sentArray.includes(true)) { -+ return message.reply('I could not find such a channel.'); -+ } - -+ return message.reply(`I have sent a message to channel \`${args[0]}\`!`); -+ }); -``` - -And that's it for this section! You have successfully communicated across all of your shards. - -### Using functions continued - -If you remember, there was a brief mention of passing functions through `.broadcastEval()`, but no super clear description of exactly how to go about it. Well, fret not, for it will be covered in this section! Suppose you have the following code in your `message` event: - -```js -client.on('message', message => { - if (!message.content.startsWith(prefix) || message.author.bot) return; - - const args = message.content.slice(prefix.length).split(/ +/); - const command = args.shift().toLowerCase(); - - if (command === 'emoji') { - if (!args.length) return message.reply('please specify an emoji id to search for.'); - const emoji = client.emojis.get(args[0]); - - return message.reply(`I have found an emoji ${emoji}!`); - } -}); -``` - -The aforementioned code will essentially search through `client.emojis` for the provided id, which will be given with `args[0]`. However, with sharding, you might notice it doesn't search through all the emojis the client actually has. As mentioned in an earlier section of this guide, this is due to the client being split up into different shards, so each shard has its own cache. Emojis are derived from guilds, so each shard will have the emojis from all of the guilds for that shard. The solution is to use `.broadcastEval()` to search all the shards for the desired emoji. However, in the interest of providing an example on using functions, you will make use of one here. Consider that when something is evaluated, it is ran in the context of the `client`, which means `this` represents the current client for that shard. - -Let's start off with an extremely basic function, which will try to grab an emoji from the current client and return it. - -```js -function findEmoji(id) { - const emoji = this.emojis.get(id); - if (!emoji) return null; - return emoji; -} -``` - -Next, you need to properly call the function in your command. If you recall from [this section](/sharding/additional-information.md#eval-arguments), it is shown there how to pass a function and arguments correctly. `.call()` will also be used in order to preserve the `client` context in the function that is passed through. - -```js -client.on('message', message => { - if (!message.content.startsWith(prefix) || message.author.bot) return; - - const args = message.content.slice(prefix.length).split(/ +/); - const command = args.shift().toLowerCase(); - - if (command === 'emoji') { - if (!args.length) return message.reply('please specify an emoji id to search for.'); - - return client.shard.broadcastEval(`(${findEmoji}).call(this, '${args[0]}')`) - .then(console.log); - } -}); -``` - -::: tip -If you are unsure as to what `.call()` does, you may read up on it [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call). -::: - -Now, run this code, and you will surely get a result that looks like the following: - - - -```js -[ { guild: - { members: {}, - // ... - id: '222078108977594368', - name: 'Discord.js Official', - icon: '6e4b4d1a0c7187f9fd5d4976c50ac96e', - // ... - emojis: {} }, - id: '383735055509356544', - name: 'duckSmug', - requiresColons: true, - managed: false, - animated: false, - _roles: [] } ] -``` - -While this result isnt *necessarily* bad or incorrect, it's simply a raw object that got `JSON.parse()`'d and `JSON.stringify()`'d over, so all of the circular references are gone. More importantly, The object is no longer a true `Emoji` object as provided by discord.js. This means none of the convenience methods usually provided to you are available. If this is not a concern to you, then you can effectively skip the rest of this section. However, this is a tutorial, so it should be covered regardless! Let's remedy this issue, shall we? - -```diff -function findEmoji(id) { -- const emoji = this.emojis.get(id); -+ const temp = this.emojis.get(id); -- if (!emoji) return null; -+ if (!temp) return null; -+ -+ // Clone the object because it is modified right after, so as to not affect the cache in client.emojis -+ const emoji = Object.assign({}, temp); -+ // Circular references can't be returned outside of eval, so change it to the id -+ if (emoji.guild) emoji.guild = emoji.guild.id; -+ // A new object will be construted, so simulate raw data by adding this property back -+ emoji.require_colons = emoji.requiresColons; -+ - return emoji; -} -``` - -Now, you will want to make use of it in the actual command: - -```diff - return client.shard.broadcastEval(`(${findEmoji}).call(this, '${args[0]}')`) -- .then(console.log); -+ .then(emojiArray => { -+ // Locate a non falsy result, which will be the emoji in question -+ const foundEmoji = emojiArray.find(emoji => emoji); -+ if (!foundEmoji) return message.reply('I could not find such an emoji.'); -+ -+ // Acquire a guild that can be reconstructed with discord.js -+ return client.rest.makeRequest('get', Discord.Constants.Endpoints.Guild(foundEmoji.guild).toString(), true) -+ .then(raw => { -+ // Reconstruct a guild -+ const guild = new Discord.Guild(client, raw); -+ // Reconstruct an emoji object as required by discord.js -+ const emoji = new Discord.Emoji(guild, foundEmoji); -+ return message.reply(`I have found an emoji ${emoji.toString()}!`); -+ }); -+ }); -``` - -And that's all! The emoji should have pretty-printed in a message as you'd expect. - -## Resulting code - - diff --git a/Ajuda/guide-master/package.json b/Ajuda/guide-master/package.json deleted file mode 100644 index b609dd7..0000000 --- a/Ajuda/guide-master/package.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "name": "guide", - "description": "The official guide for discord.js, created and maintained by core members of its community.", - "version": "1.0.0", - "scripts": { - "lint": "eslint . --ext js,md,vue", - "serve": "vuepress dev guide", - "build": "NODE_ENV=production vuepress build guide" - }, - "repository": "https://github.com/discordjs/guide.git", - "keywords": [ - "discord", - "bot", - "guide", - "tutorial", - "javascript", - "node" - ], - "author": "Sanctuary ", - "license": "MIT", - "bugs": { - "url": "https://github.com/discordjs/guide/issues" - }, - "homepage": "https://discordjs.guide", - "devDependencies": { - "babel-eslint": "^10.0.1", - "eslint": "^5.6.0", - "eslint-config-sora": "^2.0.0", - "eslint-plugin-markdown": "^1.0.0", - "eslint-plugin-vue": "^5.2.2", - "vuepress": "^1.2.0" - }, - "dependencies": { - "@vuepress/plugin-google-analytics": "^1.2.0", - "semver": "^6.0.0", - "vue-discord-message": "^3.2.5", - "vuepress-theme-yuu": "^2.2.0" - } -} diff --git a/Komugari-master/commando/README.md b/Komugari-master/commando/README.md deleted file mode 100644 index 474afeb..0000000 --- a/Komugari-master/commando/README.md +++ /dev/null @@ -1,41 +0,0 @@ -# Commando -[![Discord](https://discordapp.com/api/guilds/222078108977594368/embed.png)](https://discord.gg/bRCvFy9) -[![Downloads](https://img.shields.io/npm/dt/discord.js-commando.svg)](https://www.npmjs.com/package/discord.js-commando) -[![Version](https://img.shields.io/npm/v/discord.js-commando.svg)](https://www.npmjs.com/package/discord.js-commando) -[![Dependency status](https://david-dm.org/Gawdl3y/discord.js-commando.svg)](https://david-dm.org/Gawdl3y/discord.js-commando) -[![Build status](https://travis-ci.org/hydrabolt/discord.js.svg)](https://travis-ci.org/hydrabolt/discord.js) - -## Disclaimer -This is my edited version of [discord.js-commando](https://github.com/Gawdl3y/discord.js-commando), it varies greatly and is far behind of the actual repository. -Please refer to the official [discord.js-commando](https://github.com/Gawdl3y/discord.js-commando) if you wish to make use of the framework! - -## About -Commando is the official command framework for [discord.js](https://github.com/hydrabolt/discord.js). -It is flexible, fully object-oriented, easy to use, and makes it trivial to create your own powerful commands. -Additionally, it makes full use of ES2017's `async`/`await` functionality for clear, concise code that is simple to write and easy to comprehend. - -## Features -- Plain command names and aliases -- Regular expression triggers -- Robust parsing of arguments (with "quoted strings" support) -- Sophisticated argument system (optional) - * Automatic prompting for arguments that aren't provided - * Type system with rules, automatic validation, and parsing to usable values - - Basic types (string, integer, float, boolean) - - Discord objects (user, member, role, channel, message) - - User-defined custom types - * Automatic re-prompting of invalid arguments - * Optional arguments with default values - * Infinite arguments (arguments that accept as many values as provided) -- Multiple responses to commands -- Command editing (user edits their message that triggered the command, and the bot's response updates with it) -- Command reloading, as well as loading/unloading -- Command throttling/cooldowns - -## Installation -**Node 8.0.0 or newer is required.** -`npm install discord.js-commando` - -## Documentation -[View the docs here.](https://discord.js.org/#/docs/commando) -See the [discord.js documentation](https://discord.js.org/#/docs) as well. diff --git a/Komugari-master/commando/client.js b/Komugari-master/commando/client.js deleted file mode 100644 index 4651feb..0000000 --- a/Komugari-master/commando/client.js +++ /dev/null @@ -1,172 +0,0 @@ -const discord = require('discord.js'); -const CommandRegistry = require('./registry'); -const CommandDispatcher = require('./dispatcher'); -const GuildSettingsHelper = require('./providers/helper'); - -/** - * Discord.js Client with a command framework - * @extends {Client} - */ -class CommandoClient extends discord.Client { - /** - * Options for a CommandoClient - * @typedef {ClientOptions} CommandoClientOptions - * @property {boolean} [selfbot=false] - Whether the command dispatcher should be in selfbot mode - * @property {string} [commandPrefix=!] - Default command prefix - * @property {number} [commandEditableDuration=30] - Time in seconds that command messages should be editable - * @property {boolean} [nonCommandEditable=true] - Whether messages without commands can be edited to a command - * @property {boolean} [unknownCommandResponse=true] - Whether the bot should respond to an unknown command - * @property {string|string[]|Set} [owner] - ID of the bot owner's Discord user, or multiple IDs - * @property {string} [invite] - Invite URL to the bot's support server - */ - - /** - * @param {CommandoClientOptions} [options] - Options for the client - */ - constructor(options = {}) { - if(typeof options.selfbot === 'undefined') options.selfbot = false; - if(typeof options.commandPrefix === 'undefined') options.commandPrefix = '!'; - if(options.commandPrefix === null) options.commandPrefix = ''; - if(typeof options.commandEditableDuration === 'undefined') options.commandEditableDuration = 30; - if(typeof options.nonCommandEditable === 'undefined') options.nonCommandEditable = true; - if(typeof options.unknownCommandResponse === 'undefined') options.unknownCommandResponse = true; - super(options); - - /** - * The client's command registry - * @type {CommandRegistry} - */ - this.registry = new CommandRegistry(this); - - /** - * The client's command dispatcher - * @type {CommandDispatcher} - */ - this.dispatcher = new CommandDispatcher(this, this.registry); - - /** - * The client's setting provider - * @type {?SettingProvider} - */ - this.provider = null; - - /** - * Shortcut to use setting provider methods for the global settings - * @type {GuildSettingsHelper} - */ - this.settings = new GuildSettingsHelper(this, null); - - /** - * Internal global command prefix, controlled by the {@link CommandoClient#commandPrefix} getter/setter - * @type {?string} - * @private - */ - this._commandPrefix = null; - - // Set up command handling - const msgErr = err => { this.emit('error', err); }; - this.on('message', message => { this.dispatcher.handleMessage(message).catch(msgErr); }); - this.on('messageUpdate', (oldMessage, newMessage) => { - this.dispatcher.handleMessage(newMessage, oldMessage).catch(msgErr); - }); - - // Fetch the owner(s) - if(options.owner) { - this.once('ready', () => { - if(options.owner instanceof Array || options.owner instanceof Set) { - for(const owner of options.owner) { - this.users.fetch(owner).catch(err => { - this.emit('warn', `Unable to fetch owner ${owner}.`); - this.emit('error', err); - }); - } - } else { - this.users.fetch(options.owner).catch(err => { - this.emit('warn', `Unable to fetch owner ${options.owner}.`); - this.emit('error', err); - }); - } - }); - } - } - - /** - * Global command prefix. An empty string indicates that there is no default prefix, and only mentions will be used. - * Setting to `null` means that the default prefix from {@link CommandoClient#options} will be used instead. - * @type {string} - * @emits {@link CommandoClient#commandPrefixChange} - */ - get commandPrefix() { - if(typeof this._commandPrefix === 'undefined' || this._commandPrefix === null) return this.options.commandPrefix; - return this._commandPrefix; - } - - set commandPrefix(prefix) { - this._commandPrefix = prefix; - this.emit('commandPrefixChange', null, this._commandPrefix); - } - - /** - * Owners of the bot, set by the {@link CommandoClientOptions#owner} option - * If you simply need to check if a user is an owner of the bot, please instead use - * {@link CommandoClient#isOwner}. - * @type {?Array} - * @readonly - */ - get owners() { - if(!this.options.owner) return null; - if(typeof this.options.owner === 'string') return [this.users.get(this.options.owner)]; - const owners = []; - for(const owner of this.options.owner) owners.push(this.users.get(owner)); - return owners; - } - - /** - * Checks whether a user is an owner of the bot (in {@link CommandoClientOptions#owner}) - * @param {UserResolvable} user - User to check for ownership - * @return {boolean} - */ - isOwner(user) { - if(!this.options.owner) return false; - user = this.users.resolve(user); - if(!user) throw new RangeError('Unable to resolve user.'); - if(typeof this.options.owner === 'string') return user.id === this.options.owner; - if(this.options.owner instanceof Array) return this.options.owner.includes(user.id); - if(this.options.owner instanceof Set) return this.options.owner.has(user.id); - throw new RangeError('The client\'s "owner" option is an unknown value.'); - } - - /** - * Sets the setting provider to use, and initialises it once the client is ready - * @param {SettingProvider|Promise} provider Provider to use - * @return {Promise} - */ - async setProvider(provider) { - provider = await provider; - this.provider = provider; - - if(this.readyTimestamp) { - this.emit('debug', `Provider set to ${provider.constructor.name} - initialising...`); - await provider.init(this); - this.emit('debug', 'Provider finished initialisation.'); - return undefined; - } - - this.emit('debug', `Provider set to ${provider.constructor.name} - will initialise once ready.`); - await new Promise(resolve => { - this.once('ready', () => { - this.emit('debug', `Initialising provider...`); - resolve(provider.init(this)); - }); - }); - - this.emit('debug', 'Provider finished initialisation.'); - return undefined; - } - - destroy() { - super.destroy().then(() => this.provider ? this.provider.destroy() : undefined); - } -} - -module.exports = CommandoClient; diff --git a/Komugari-master/commando/commands/argument.js b/Komugari-master/commando/commands/argument.js deleted file mode 100644 index 91fa027..0000000 --- a/Komugari-master/commando/commands/argument.js +++ /dev/null @@ -1,355 +0,0 @@ -const escapeMarkdown = require('discord.js').escapeMarkdown; -const { oneLine, stripIndents } = require('common-tags'); - -/** A fancy argument */ -class Argument { - /** - * @typedef {Object} ArgumentInfo - * @property {string} key - Key for the argument - * @property {string} [label=key] - Label for the argument - * @property {string} prompt - First prompt for the argument when it wasn't specified - * @property {string} [type] - Type of the argument (must be the ID of one of the registered argument types - - * see {@link CommandRegistry#registerDefaultTypes} for the built-in types) - * @property {number} [max] - If type is `integer` or `float`, this is the maximum value of the number. - * If type is `string`, this is the maximum length of the string. - * @property {number} [min] - If type is `integer` or `float`, this is the minimum value of the number. - * If type is `string`, this is the minimum length of the string. - * @property {*} [default] - Default value for the argument (makes the argument optional - cannot be `null`) - * @property {boolean} [infinite=false] - Whether the argument accepts infinite values - * @property {Function} [validate] - Validator function for the argument (see {@link ArgumentType#validate}) - * @property {Function} [parse] - Parser function for the argument (see {@link ArgumentType#parse}) - * @property {number} [wait=30] - How long to wait for input (in seconds) - */ - - /** - * @param {CommandoClient} client - Client the argument is for - * @param {ArgumentInfo} info - Information for the command argument - */ - constructor(client, info) { - this.constructor.validateInfo(client, info); - - /** - * Key for the argument - * @type {string} - */ - this.key = info.key; - - /** - * Label for the argument - * @type {string} - */ - this.label = info.label || info.key; - - /** - * Question prompt for the argument - * @type {string} - */ - this.prompt = info.prompt; - - /** - * Type of the argument - * @type {?ArgumentType} - */ - this.type = info.type ? client.registry.types.get(info.type) : null; - - /** - * If type is `integer` or `float`, this is the maximum value of the number. - * If type is `string`, this is the maximum length of the string. - * @type {?number} - */ - this.max = info.max || null; - - /** - * If type is `integer` or `float`, this is the minimum value of the number. - * If type is `string`, this is the minimum length of the string. - * @type {?number} - */ - this.min = info.min || null; - - /** - * The default value for the argument - * @type {?*} - */ - this.default = typeof info.default !== 'undefined' ? info.default : null; - - /** - * Whether the argument accepts an infinite number of values - * @type {boolean} - */ - this.infinite = Boolean(info.infinite); - - /** - * Validator function for validating a value for the argument - * @type {?Function} - * @see {@link ArgumentType#validate} - */ - this.validator = info.validate || null; - - /** - * Parser function for parsing a value for the argument - * @type {?Function} - * @see {@link ArgumentType#parse} - */ - this.parser = info.parse || null; - - /** - * How long to wait for input (in seconds) - * @type {number} - */ - this.wait = typeof info.wait !== 'undefined' ? info.wait : 30; - } - - /** - * Result object from obtaining a single {@link Argument}'s value(s) - * @typedef {Object} ArgumentResult - * @property {?*|?Array<*>} value - Final value(s) for the argument - * @property {?string} cancelled - One of: - * - `user` (user cancelled) - * - `time` (wait time exceeded) - * - `promptLimit` (prompt limit exceeded) - * @property {Message[]} prompts - All messages that were sent to prompt the user - * @property {Message[]} answers - All of the user's messages that answered a prompt - */ - - /** - * Prompts the user and obtains the value for the argument - * @param {CommandMessage} msg - Message that triggered the command - * @param {string} [value] - Pre-provided value for the argument - * @param {number} [promptLimit=Infinity] - Maximum number of times to prompt for the argument - * @return {Promise} - */ - async obtain(msg, value, promptLimit = Infinity) { - if(!value && this.default !== null) { - return { - value: this.default, - cancelled: null, - prompts: [], - answers: [] - }; - } - if(this.infinite) return this.obtainInfinite(msg, value, promptLimit); - - const wait = this.wait > 0 && this.wait !== Infinity ? this.wait * 1000 : undefined; - const prompts = []; - const answers = []; - let valid = value ? await this.validate(value, msg) : false; - - while(!valid || typeof valid === 'string') { - /* eslint-disable no-await-in-loop */ - if(prompts.length >= promptLimit) { - return { - value: null, - cancelled: 'promptLimit', - prompts, - answers - }; - } - - // Prompt the user for a new value - prompts.push(await msg.channel.send(stripIndents` - ${!value ? `**${this.prompt}**` : valid ? valid : `You provided an invalid **${this.label}**! Please try again!`} - `)) - - // Get the user's response - const responses = await msg.channel.awaitMessages(msg2 => msg2.author.id === msg.author.id, { - max: 1, - time: wait - }); - - // Make sure they actually answered - if(responses && responses.size === 1) { - answers.push(responses.first()); - value = answers[answers.length - 1].content; - } else { - return { - value: null, - cancelled: 'time', - prompts, - answers - }; - } - - // See if they want to cancel - if(value.toLowerCase() === 'cancel') { - return { - value: null, - cancelled: 'user', - prompts, - answers - }; - } - - valid = await this.validate(value, msg); - /* eslint-enable no-await-in-loop */ - } - - return { - value: await this.parse(value, msg), - cancelled: null, - prompts, - answers - }; - } - - /** - * Prompts the user and obtains multiple values for the argument - * @param {CommandMessage} msg - Message that triggered the command - * @param {string[]} [values] - Pre-provided values for the argument - * @param {number} [promptLimit=Infinity] - Maximum number of times to prompt for the argument - * @return {Promise} - * @private - */ - async obtainInfinite(msg, values, promptLimit = Infinity) { // eslint-disable-line complexity - const wait = this.wait > 0 && this.wait !== Infinity ? this.wait * 1000 : undefined; - const results = []; - const prompts = []; - const answers = []; - let currentVal = 0; - - while(true) { // eslint-disable-line no-constant-condition - /* eslint-disable no-await-in-loop */ - let value = values && values[currentVal] ? values[currentVal] : null; - let valid = value ? await this.validate(value, msg) : false; - let attempts = 0; - - while(!valid || typeof valid === 'string') { - attempts++; - if(attempts > promptLimit) { - return { - value: null, - cancelled: 'promptLimit', - prompts, - answers - }; - } - - // Prompt the user for a new value - if(value) { - const escaped = escapeMarkdown(value).replace(/@/g, '@\u200b'); - prompts.push(await msg.channel.send(stripIndents` - ${valid ? valid : oneLine` - You provided an invalid ${this.label}, - "${escaped.length < 1850 ? escaped : '[too long to show]'}". - Please try again! - `} - `)); - } else if(results.length === 0) { - prompts.push(await msg.channel.send(stripIndents` - ${this.prompt} - `)); - } - - // Get the user's response - const responses = await msg.channel.awaitMessages(msg2 => msg2.author.id === msg.author.id, { - max: 1, - time: wait - }); - - // Make sure they actually answered - if(responses && responses.size === 1) { - answers.push(responses.first()); - value = answers[answers.length - 1].content; - } else { - return { - value: null, - cancelled: 'time', - prompts, - answers - }; - } - - // See if they want to finish or cancel - const lc = value.toLowerCase(); - if(lc === 'finish') { - return { - value: results.length > 0 ? results : null, - cancelled: results.length > 0 ? null : 'user', - prompts, - answers - }; - } - if(lc === 'cancel') { - return { - value: null, - cancelled: 'user', - prompts, - answers - }; - } - - valid = await this.validate(value, msg); - } - - results.push(await this.parse(value, msg)); - - if(values) { - currentVal++; - if(currentVal === values.length) { - return { - value: results, - cancelled: null, - prompts, - answers - }; - } - } - /* eslint-enable no-await-in-loop */ - } - } - - /** - * Checks if a value is valid for the argument - * @param {string} value - Value to check - * @param {CommandMessage} msg - Message that triggered the command - * @return {boolean|string|Promise} - */ - validate(value, msg) { - if(this.validator) return this.validator(value, msg, this); - return this.type.validate(value, msg, this); - } - - /** - * Parses a value string into a proper value for the argument - * @param {string} value - Value to parse - * @param {CommandMessage} msg - Message that triggered the command - * @return {*|Promise<*>} - */ - parse(value, msg) { - if(this.parser) return this.parser(value, msg, this); - return this.type.parse(value, msg, this); - } - - /** - * Validates the constructor parameters - * @param {CommandoClient} client - Client to validate - * @param {ArgumentInfo} info - Info to validate - * @private - */ - static validateInfo(client, info) { - if(!client) throw new Error('The argument client must be specified.'); - if(typeof info !== 'object') throw new TypeError('Argument info must be an Object.'); - if(typeof info.key !== 'string') throw new TypeError('Argument key must be a string.'); - if(info.label && typeof info.label !== 'string') throw new TypeError('Argument label must be a string.'); - if(typeof info.prompt !== 'string') throw new TypeError('Argument prompt must be a string.'); - if(!info.type && !info.validate) { - throw new Error('Argument must have either "type" or "validate" specified.'); - } - if(info.type && !client.registry.types.has(info.type)) { - throw new RangeError(`Argument type "${info.type}" isn't registered.`); - } - if(info.validate && typeof info.validate !== 'function') { - throw new TypeError('Argument validate must be a function.'); - } - if(info.parse && typeof info.parse !== 'function') { - throw new TypeError('Argument parse must be a function.'); - } - if(!info.type && (!info.validate || !info.parse)) { - throw new Error('Argument must have both validate and parse since it doesn\'t have a type.'); - } - if(typeof info.wait !== 'undefined' && (typeof info.wait !== 'number' || Number.isNaN(info.wait))) { - throw new TypeError('Argument wait must be a number.'); - } - } -} - -module.exports = Argument; diff --git a/Komugari-master/commando/commands/base.js b/Komugari-master/commando/commands/base.js deleted file mode 100644 index 54adf18..0000000 --- a/Komugari-master/commando/commands/base.js +++ /dev/null @@ -1,460 +0,0 @@ -const path = require('path'); -const { oneLine } = require('common-tags'); -const ArgumentCollector = require('./collector'); -const { permissions } = require('../util'); - -/** A command that can be run in a client */ -class Command { - /** - * @typedef {Object} ThrottlingOptions - * @property {number} usages - Maximum number of usages of the command allowed in the time frame. - * @property {number} duration - Amount of time to count the usages of the command within (in seconds). - */ - - /** - * @typedef {Object} CommandInfo - * @property {string} name - The name of the command (must be lowercase) - * @property {string[]} [aliases] - Alternative names for the command (all must be lowercase) - * @property {boolean} [autoAliases=true] - Whether automatic aliases should be added - * @property {string} group - The ID of the group the command belongs to (must be lowercase) - * @property {string} memberName - The member name of the command in the group (must be lowercase) - * @property {string} description - A short description of the command - * @property {string} [format] - The command usage format string - will be automatically generated if not specified, - * and `args` is specified - * @property {string} [details] - A detailed description of the command and its functionality - * @property {string[]} [examples] - Usage examples of the command - * @property {boolean} [guildOnly=false] - Whether or not the command should only function in a guild channel - * @property {PermissionResolvable[]} [clientPermissions] - Permissions required by the client to use the command. - * @property {PermissionResolvable[]} [userPermissions] - Permissions required by the user to use the command. - * @property {ThrottlingOptions} [throttling] - Options for throttling usages of the command. - * @property {boolean} [defaultHandling=true] - Whether or not the default command handling should be used. - * If false, then only patterns will trigger the command. - * @property {ArgumentInfo[]} [args] - Arguments for the command. - * @property {number} [argsPromptLimit=Infinity] - Maximum number of times to prompt a user for a single argument. - * Only applicable if `args` is specified. - * @property {string} [argsType=single] - One of 'single' or 'multiple'. Only applicable if `args` is not specified. - * When 'single', the entire argument string will be passed to run as one argument. - * When 'multiple', it will be passed as multiple arguments. - * @property {number} [argsCount=0] - The number of arguments to parse from the command string. - * Only applicable when argsType is 'multiple'. If nonzero, it should be at least 2. - * When this is 0, the command argument string will be split into as many arguments as it can be. - * When nonzero, it will be split into a maximum of this number of arguments. - * @property {boolean} [argsSingleQuotes=true] - Whether or not single quotes should be allowed to box-in arguments - * in the command string. - * @property {RegExp[]} [patterns] - Patterns to use for triggering the command - * @property {boolean} [guarded=false] - Whether the command should be protected from disabling - */ - - /** - * @param {CommandoClient} client - The client the command is for - * @param {CommandInfo} info - The command information - */ - constructor(client, info) { - this.constructor.validateInfo(client, info); - - /** - * Client that this command is for - * @name Command#client - * @type {CommandoClient} - * @readonly - */ - Object.defineProperty(this, 'client', { value: client }); - - /** - * Name of this command - * @type {string} - */ - this.name = info.name; - - /** - * Aliases for this command - * @type {string[]} - */ - this.aliases = info.aliases || []; - if(typeof info.autoAliases === 'undefined' || info.autoAliases) { - if(this.name.includes('-')) this.aliases.push(this.name.replace(/-/g, '')); - for(const alias of this.aliases) { - if(alias.includes('-')) this.aliases.push(alias.replace(/-/g, '')); - } - } - - /** - * ID of the group the command belongs to - * @type {string} - */ - this.groupID = info.group; - - /** - * The group the command belongs to, assigned upon registration - * @type {?CommandGroup} - */ - this.group = null; - - /** - * Name of the command within the group - * @type {string} - */ - this.memberName = info.memberName; - - /** - * Short description of the command - * @type {string} - */ - this.description = info.description; - - /** - * Usage format string of the command - * @type {string} - */ - this.format = info.format || null; - - /** - * Long description of the command - * @type {?string} - */ - this.details = info.details || null; - - /** - * Example usage strings - * @type {?string[]} - */ - this.examples = info.examples || null; - - /** - * Whether the command can only be run in a guild channel - * @type {boolean} - */ - this.guildOnly = !!info.guildOnly; - - /** - * Permissions required by the client to use the command. - * @type {?PermissionResolvable[]} - */ - this.clientPermissions = info.clientPermissions || null; - - /** - * Permissions required by the user to use the command. - * @type {?PermissionResolvable[]} - */ - this.userPermissions = info.userPermissions || null; - - /** - * Whether the default command handling is enabled for the command - * @type {boolean} - */ - this.defaultHandling = 'defaultHandling' in info ? info.defaultHandling : true; - - /** - * Options for throttling command usages - * @type {?ThrottlingOptions} - */ - this.throttling = info.throttling || null; - - /** - * The argument collector for the command - * @type {?ArgumentCollector} - */ - this.argsCollector = info.args ? new ArgumentCollector(client, info.args, info.argsPromptLimit) : null; - if(this.argsCollector && typeof info.format === 'undefined') { - this.format = this.argsCollector.args.reduce((prev, arg) => { - const wrapL = arg.default !== null ? '[' : '<'; - const wrapR = arg.default !== null ? ']' : '>'; - return `${prev}${prev ? ' ' : ''}${wrapL}${arg.label}${arg.infinite ? '...' : ''}${wrapR}`; - }, ''); - } - - /** - * How the arguments are split when passed to the command's run method - * @type {string} - */ - this.argsType = info.argsType || 'single'; - - /** - * Maximum number of arguments that will be split - * @type {number} - */ - this.argsCount = info.argsCount || 0; - - /** - * Whether single quotes are allowed to encapsulate an argument - * @type {boolean} - */ - this.argsSingleQuotes = 'argsSingleQuotes' in info ? info.argsSingleQuotes : true; - - /** - * Regular expression triggers - * @type {RegExp[]} - */ - this.patterns = info.patterns || null; - - /** - * Whether the command is protected from being disabled - * @type {boolean} - */ - this.guarded = Boolean(info.guarded); - - /** - * Whether the command is enabled globally - * @type {boolean} - * @private - */ - this._globalEnabled = true; - - /** - * Current throttle objects for the command, mapped by user ID - * @type {Map} - * @private - */ - this._throttles = new Map(); - } - - /** - * Checks a user's permission in a guild - * @param {CommandMessage} message - The triggering command message - * @return {boolean|string} Whether the user has permission, or an error message to respond with if they don't - */ - hasPermission(message) { // eslint-disable-line no-unused-vars - if(message.channel.type === 'text' && this.userPermissions) { - const missing = message.channel.permissionsFor(message.author).missing(this.userPermissions); - if(missing.length > 0) { - if(missing.length === 1) { - return `The \`${this.name}\` command requires you to have the "${permissions[missing[0]]}" permission.`; - } - return oneLine` - The \`${this.name}\` requires you to have the following permissions: - ${missing.map(perm => permissions[perm]).join(', ')} - `; - } - } - - return true; - } - - // eslint-disable-next-line valid-jsdoc - /** - * Runs the command - * @param {CommandMessage} message - The message the command is being run for - * @param {Object|string|string[]} args - The arguments for the command, or the matches from a pattern. - * If args is specified on the command, thise will be the argument values object. If argsType is single, then only - * one string will be passed. If multiple, an array of strings will be passed. When fromPattern is true, this is the - * matches array from the pattern match - * (see [RegExp#exec](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec)). - * @param {boolean} fromPattern - Whether or not the command is being run from a pattern match - * @return {Promise>} - * @abstract - */ - async run(message, args, fromPattern) { // eslint-disable-line no-unused-vars, require-await - throw new Error(`${this.constructor.name} doesn't have a run() method.`); - } - - /** - * Creates/obtains the throttle object for a user, if necessary (owners are excluded) - * @param {string} userID - ID of the user to throttle for - * @return {?Object} - * @private - */ - throttle(userID) { - if(!this.throttling || this.client.isOwner(userID)) return null; - - let throttle = this._throttles.get(userID); - if(!throttle) { - throttle = { - start: Date.now(), - usages: 0, - timeout: this.client.setTimeout(() => { - this._throttles.delete(userID); - }, this.throttling.duration * 1000) - }; - this._throttles.set(userID, throttle); - } - - return throttle; - } - - /** - * Enables or disables the command in a guild - * @param {?GuildResolvable} guild - Guild to enable/disable the command in - * @param {boolean} enabled - Whether the command should be enabled or disabled - */ - setEnabledIn(guild, enabled) { - if(typeof guild === 'undefined') throw new TypeError('Guild must not be undefined.'); - if(typeof enabled === 'undefined') throw new TypeError('Enabled must not be undefined.'); - if(this.guarded) throw new Error('The command is guarded.'); - if(!guild) { - this._globalEnabled = enabled; - this.client.emit('commandStatusChange', null, this, enabled); - return; - } - guild = this.client.guilds.resolve(guild); - guild.setCommandEnabled(this, enabled); - } - - /** - * Checks if the command is enabled in a guild - * @param {?GuildResolvable} guild - Guild to check in - * @return {boolean} - */ - isEnabledIn(guild) { - if(this.guarded) return true; - if(!guild) return this.group._globalEnabled && this._globalEnabled; - guild = this.client.guilds.resolve(guild); - return guild.isGroupEnabled(this.group) && guild.isCommandEnabled(this); - } - - /** - * Checks if the command is usable for a message - * @param {?Message} message - The message - * @return {boolean} - */ - isUsable(message = null) { - if(!message) return this._globalEnabled; - if(this.guildOnly && message && !message.guild) return false; - const hasPermission = this.hasPermission(message); - return this.isEnabledIn(message.guild) && hasPermission && typeof hasPermission !== 'string'; - } - - /** - * Creates a usage string for the command - * @param {string} [argString] - A string of arguments for the command - * @param {string} [prefix=this.client.commandPrefix] - Prefix to use for the prefixed command format - * @param {User} [user=this.client.user] - User to use for the mention command format - * @return {string} - */ - usage(argString, prefix = this.client.commandPrefix, user = this.client.user) { - return this.constructor.usage(`${this.name}${argString ? ` ${argString}` : ''}`, prefix, user); - } - - /** - * Reloads the command - */ - reload() { - let cmdPath, cached, newCmd; - try { - cmdPath = this.client.registry.resolveCommandPath(this.groupID, this.memberName); - cached = require.cache[cmdPath]; - delete require.cache[cmdPath]; - newCmd = require(cmdPath); - } catch(err) { - if(cached) require.cache[cmdPath] = cached; - try { - cmdPath = path.join(__dirname, this.groupID, `${this.memberName}.js`); - cached = require.cache[cmdPath]; - delete require.cache[cmdPath]; - newCmd = require(cmdPath); - } catch(err2) { - if(cached) require.cache[cmdPath] = cached; - if(err2.message.includes('Cannot find module')) throw err; else throw err2; - } - } - - this.client.registry.reregisterCommand(newCmd, this); - } - - /** - * Unloads the command - */ - unload() { - const cmdPath = this.client.registry.resolveCommandPath(this.groupID, this.memberName); - if(!require.cache[cmdPath]) throw new Error('Command cannot be unloaded.'); - delete require.cache[cmdPath]; - this.client.registry.unregisterCommand(this); - } - - /** - * Creates a usage string for a command - * @param {string} command - A command + arg string - * @param {string} [prefix] - Prefix to use for the prefixed command format - * @param {User} [user] - User to use for the mention command format - * @return {string} - */ - static usage(command, prefix = null, user = null) { - const nbcmd = command.replace(/ /g, '\xa0'); - if(!prefix && !user) return `\`${nbcmd}\``; - - let prefixPart; - if(prefix) { - if(prefix.length > 1 && !prefix.endsWith(' ')) prefix += ' '; - prefix = prefix.replace(/ /g, '\xa0'); - prefixPart = `\`${prefix}${nbcmd}\``; - } - - let mentionPart; - if(user) mentionPart = `\`@${user.username.replace(/ /g, '\xa0')}#${user.discriminator}\xa0${nbcmd}\``; - - return `${prefixPart || ''}${prefix && user ? ' or ' : ''}${mentionPart || ''}`; - } - - /** - * Validates the constructor parameters - * @param {CommandoClient} client - Client to validate - * @param {CommandInfo} info - Info to validate - * @private - */ - static validateInfo(client, info) { // eslint-disable-line complexity - if(!client) throw new Error('A client must be specified.'); - if(typeof info !== 'object') throw new TypeError('Command info must be an Object.'); - if(typeof info.name !== 'string') throw new TypeError('Command name must be a string.'); - if(info.name !== info.name.toLowerCase()) throw new Error('Command name must be lowercase.'); - if(info.aliases && (!Array.isArray(info.aliases) || info.aliases.some(ali => typeof ali !== 'string'))) { - throw new TypeError('Command aliases must be an Array of strings.'); - } - if(info.aliases && info.aliases.some(ali => ali !== ali.toLowerCase())) { - throw new Error('Command aliases must be lowercase.'); - } - if(typeof info.group !== 'string') throw new TypeError('Command group must be a string.'); - if(info.group !== info.group.toLowerCase()) throw new Error('Command group must be lowercase.'); - if(typeof info.memberName !== 'string') throw new TypeError('Command memberName must be a string.'); - if(info.memberName !== info.memberName.toLowerCase()) throw new Error('Command memberName must be lowercase.'); - if(typeof info.description !== 'string') throw new TypeError('Command description must be a string.'); - if('format' in info && typeof info.format !== 'string') throw new TypeError('Command format must be a string.'); - if('details' in info && typeof info.details !== 'string') throw new TypeError('Command details must be a string.'); - if(info.examples && (!Array.isArray(info.examples) || info.examples.some(ex => typeof ex !== 'string'))) { - throw new TypeError('Command examples must be an Array of strings.'); - } - if(info.clientPermissions) { - if(!Array.isArray(info.clientPermissions)) { - throw new TypeError('Command clientPermissions must be an Array of permission key strings.'); - } - for(const perm of info.clientPermissions) { - if(!permissions[perm]) throw new RangeError(`Invalid command clientPermission: ${perm}`); - } - } - if(info.userPermissions) { - if(!Array.isArray(info.userPermissions)) { - throw new TypeError('Command userPermissions must be an Array of permission key strings.'); - } - for(const perm of info.userPermissions) { - if(!permissions[perm]) throw new RangeError(`Invalid command userPermission: ${perm}`); - } - } - if(info.throttling) { - if(typeof info.throttling !== 'object') throw new TypeError('Command throttling must be an Object.'); - if(typeof info.throttling.usages !== 'number' || isNaN(info.throttling.usages)) { - throw new TypeError('Command throttling usages must be a number.'); - } - if(info.throttling.usages < 1) throw new RangeError('Command throttling usages must be at least 1.'); - if(typeof info.throttling.duration !== 'number' || isNaN(info.throttling.duration)) { - throw new TypeError('Command throttling duration must be a number.'); - } - if(info.throttling.duration < 1) throw new RangeError('Command throttling duration must be at least 1.'); - } - if(info.args && !Array.isArray(info.args)) throw new TypeError('Command args must be an Array.'); - if('argsPromptLimit' in info && typeof info.argsPromptLimit !== 'number') { - throw new TypeError('Command argsPromptLimit must be a number.'); - } - if('argsPromptLimit' in info && info.argsPromptLimit < 0) { - throw new RangeError('Command argsPromptLimit must be at least 0.'); - } - if(info.argsType && !['single', 'multiple'].includes(info.argsType)) { - throw new RangeError('Command argsType must be one of "single" or "multiple".'); - } - if(info.argsType === 'multiple' && info.argsCount && info.argsCount < 2) { - throw new RangeError('Command argsCount must be at least 2.'); - } - if(info.patterns && (!Array.isArray(info.patterns) || info.patterns.some(pat => !(pat instanceof RegExp)))) { - throw new TypeError('Command patterns must be an Array of regular expressions.'); - } - } -} - -module.exports = Command; diff --git a/Komugari-master/commando/commands/collector.js b/Komugari-master/commando/commands/collector.js deleted file mode 100644 index 6b5f08f..0000000 --- a/Komugari-master/commando/commands/collector.js +++ /dev/null @@ -1,105 +0,0 @@ -const Argument = require('./argument'); - -/** Obtains, validates, and prompts for argument values */ -class ArgumentCollector { - /** - * @param {CommandoClient} client - Client the collector will use - * @param {ArgumentInfo[]} args - Arguments for the collector - * @param {number} [promptLimit=Infinity] - Maximum number of times to prompt for a single argument - */ - constructor(client, args, promptLimit = Infinity) { - if(!client) throw new TypeError('Collector client must be specified.'); - if(!args || !Array.isArray(args)) throw new TypeError('Collector args must be an Array.'); - if(promptLimit === null) promptLimit = Infinity; - - /** - * Client this collector is for - * @name ArgumentCollector#client - * @type {CommandoClient} - * @readonly - */ - Object.defineProperty(this, 'client', { value: client }); - - /** - * Arguments the collector handles - * @type {Argument[]} - */ - this.args = new Array(args.length); - - let hasInfinite = false; - let hasOptional = false; - for(let i = 0; i < args.length; i++) { - if(hasInfinite) throw new Error('No other argument may come after an infinite argument.'); - if(args[i].default !== null) hasOptional = true; - else if(hasOptional) throw new Error('Required arguments may not come after optional arguments.'); - this.args[i] = new Argument(this.client, args[i]); - if(this.args[i].infinite) hasInfinite = true; - } - - /** - * Maximum number of times to prompt for a single argument - * @type {number} - */ - this.promptLimit = promptLimit; - } - - /** - * Result object from obtaining argument values from an {@link ArgumentCollector} - * @typedef {Object} ArgumentCollectorResult - * @property {?Object} values - Final values for the arguments, mapped by their keys - * @property {?string} cancelled - One of: - * - `user` (user cancelled) - * - `time` (wait time exceeded) - * - `promptLimit` (prompt limit exceeded) - * @property {Message[]} prompts - All messages that were sent to prompt the user - * @property {Message[]} answers - All of the user's messages that answered a prompt - */ - - /** - * Obtains values for the arguments, prompting if necessary. - * @param {CommandMessage} msg - Message that the collector is being triggered by - * @param {Array<*>} [provided=[]] - Values that are already available - * @param {number} [promptLimit=this.promptLimit] - Maximum number of times to prompt for a single argument - * @return {Promise} - */ - async obtain(msg, provided = [], promptLimit = this.promptLimit) { - this.client.dispatcher._awaiting.add(msg.message.author.id + msg.message.channel.id); - const values = {}; - const results = []; - - try { - for(let i = 0; i < this.args.length; i++) { - /* eslint-disable no-await-in-loop */ - const arg = this.args[i]; - const result = await arg.obtain(msg, arg.infinite ? provided.slice(i) : provided[i], promptLimit); - results.push(result); - - if(result.cancelled) { - this.client.dispatcher._awaiting.delete(msg.message.author.id + msg.message.channel.id); - return { - values: null, - cancelled: result.cancelled, - prompts: [].concat(...results.map(res => res.prompts)), - answers: [].concat(...results.map(res => res.answers)) - }; - } - - values[arg.key] = result.value; - /* eslint-enable no-await-in-loop */ - } - } catch(err) { - this.client.dispatcher._awaiting.delete(msg.message.author.id + msg.message.channel.id); - throw err; - } - - this.client.dispatcher._awaiting.delete(msg.message.author.id + msg.message.channel.id); - return { - values, - cancelled: null, - prompts: [].concat(...results.map(res => res.prompts)), - answers: [].concat(...results.map(res => res.answers)) - }; - } -} - -module.exports = ArgumentCollector; diff --git a/Komugari-master/commando/commands/group.js b/Komugari-master/commando/commands/group.js deleted file mode 100644 index 3d696a0..0000000 --- a/Komugari-master/commando/commands/group.js +++ /dev/null @@ -1,94 +0,0 @@ -const discord = require('discord.js'); - -/** A group for commands. Whodathunkit? */ -class CommandGroup { - /** - * @param {CommandoClient} client - The client the group is for - * @param {string} id - The ID for the group - * @param {string} [name=id] - The name of the group - * @param {boolean} [guarded=false] - Whether the group should be protected from disabling - * @param {Command[]} [commands] - The commands that the group contains - */ - constructor(client, id, name, guarded = false, commands = null) { - if(!client) throw new Error('A client must be specified.'); - if(typeof id !== 'string') throw new TypeError('Group ID must be a string.'); - if(id !== id.toLowerCase()) throw new Error('Group ID must be lowercase.'); - if(commands && !Array.isArray(commands)) throw new TypeError('Group commands must be an Array of Commands.'); - - /** - * Client that this group is for - * @name CommandGroup#client - * @type {CommandoClient} - * @readonly - */ - Object.defineProperty(this, 'client', { value: client }); - - /** - * ID of this group - * @type {string} - */ - this.id = id; - - /** - * Name of this group - * @type {string} - */ - this.name = name || id; - - /** - * The commands in this group (added upon their registration) - * @type {Collection} - */ - this.commands = new discord.Collection(); - if(commands) { - for(const command of commands) this.commands.set(command.name, command); - } - - /** - * Whether or not this group is protected from being disabled - * @type {boolean} - */ - this.guarded = guarded; - - this._globalEnabled = true; - } - - /** - * Enables or disables the group in a guild - * @param {?GuildResolvable} guild - Guild to enable/disable the group in - * @param {boolean} enabled - Whether the group should be enabled or disabled - */ - setEnabledIn(guild, enabled) { - if(typeof guild === 'undefined') throw new TypeError('Guild must not be undefined.'); - if(typeof enabled === 'undefined') throw new TypeError('Enabled must not be undefined.'); - if(this.guarded) throw new Error('The group is guarded.'); - if(!guild) { - this._globalEnabled = enabled; - this.client.emit('groupStatusChange', null, this, enabled); - return; - } - guild = this.client.guilds.resolve(guild); - guild.setGroupEnabled(this, enabled); - } - - /** - * Checks if the group is enabled in a guild - * @param {?GuildResolvable} guild - Guild to check in - * @return {boolean} Whether or not the group is enabled - */ - isEnabledIn(guild) { - if(this.guarded) return true; - if(!guild) return this._globalEnabled; - guild = this.client.guilds.resolve(guild); - return guild.isGroupEnabled(this); - } - - /** - * Reloads all of the group's commands - */ - reload() { - for(const command of this.commands.values()) command.reload(); - } -} - -module.exports = CommandGroup; diff --git a/Komugari-master/commando/commands/message.js b/Komugari-master/commando/commands/message.js deleted file mode 100644 index 886e108..0000000 --- a/Komugari-master/commando/commands/message.js +++ /dev/null @@ -1,841 +0,0 @@ -const discord = require('discord.js'); -const { stripIndents, oneLine } = require('common-tags'); -const Command = require('./base'); -const FriendlyError = require('../errors/friendly'); -const CommandFormatError = require('../errors/command-format'); -const { permissions } = require('../util'); - -/** A container for a message that triggers a command, that command, and methods to respond */ -class CommandMessage { - /** - * @param {Message} message - Message that triggers the command - * @param {Command} [command] - Command the message triggers - * @param {string} [argString] - Argument string for the command - * @param {?Array} [patternMatches] - Command pattern matches (if from a pattern trigger) - */ - constructor(message, command = null, argString = null, patternMatches = null) { - /** - * Client that the message was sent from - * @name CommandMessage#client - * @type {CommandoClient} - * @readonly - */ - Object.defineProperty(this, 'client', { value: message.client }); - - /** - * Message that triggers the command - * @type {Message} - */ - this.message = message; - - /** - * Command that the message triggers, if any - * @type {?Command} - */ - this.command = command; - - /** - * Argument string for the command - * @type {?string} - */ - this.argString = argString; - - /** - * Pattern matches (if from a pattern trigger) - * @type {?string[]} - */ - this.patternMatches = patternMatches; - - /** - * Response messages sent, mapped by channel ID (set by the dispatcher after running the command) - * @type {?Object} - */ - this.responses = null; - - /** - * The index of the current response that will be edited, mapped by channel ID - * @type {?Object} - */ - this.responsePositions = null; - } - - /** - * Creates a usage string for the message's command - * @param {string} [argString] - A string of arguments for the command - * @param {string} [prefix=this.message.guild.commandPrefix || this.client.commandPrefix] - Prefix to use for the - * prefixed command format - * @param {User} [user=this.client.user] - User to use for the mention command format - * @return {string} - */ - usage(argString, prefix, user = this.client.user) { - if(typeof prefix === 'undefined') { - if(this.message.guild) prefix = this.message.guild.commandPrefix; - else prefix = this.client.commandPrefix; - } - return this.command.usage(argString, prefix, user); - } - - /** - * Creates a usage string for any command - * @param {string} [command] - A command + arg string - * @param {string} [prefix=this.message.guild.commandPrefix || this.client.commandPrefix] - Prefix to use for the - * prefixed command format - * @param {User} [user=this.client.user] - User to use for the mention command format - * @return {string} - */ - anyUsage(command, prefix, user = this.client.user) { - if(typeof prefix === 'undefined') { - if(this.message.guild) prefix = this.message.guild.commandPrefix; - else prefix = this.client.commandPrefix; - } - return Command.usage(command, prefix, user); - } - - /** - * Parses the argString into usable arguments, based on the argsType and argsCount of the command - * @return {string|string[]} - * @see {@link Command#run} - */ - parseArgs() { - switch(this.command.argsType) { - case 'single': - return this.argString.trim().replace( - this.command.argsSingleQuotes ? /^("|')([^]*)\1$/g : /^(")([^]*)"$/g, '$2' - ); - case 'multiple': - return this.constructor.parseArgs(this.argString, this.command.argsCount, this.command.argsSingleQuotes); - default: - throw new RangeError(`Unknown argsType "${this.argsType}".`); - } - } - - /** - * Runs the command - * @return {Promise>} - */ - async run() { // eslint-disable-line complexity - // Obtain the member if we don't have it (ugly-ass if statement ahead) - if(this.message.channel.type === 'text' && !this.message.guild.members.has(this.message.author.id) && - !this.message.webhookID) { - this.message.member = await this.message.guild.members.fetch(this.message.author); - } - - // Obtain the member for the ClientUser if it doesn't already exist - if(this.message.channel.type === 'text' && !this.message.guild.members.has(this.client.user.id)) { - await this.message.guild.members.fetch(this.client.user.id); - } - - // Make sure the command is usable in this context - if(this.command.guildOnly && !this.message.guild) { - /** - * Emitted when a command is prevented from running - * @event CommandoClient#commandBlocked - * @param {CommandMessage} message - Command message that the command is running from - * @param {string} reason - Reason that the command was blocked - * (built-in reasons are `guildOnly`, `permission`, and `throttling`) - */ - this.client.emit('commandBlocked', this, 'guildOnly'); - return this.message.react('💢'); - } - - // Ensure the user has permission to use the command - const hasPermission = this.command.hasPermission(this); - if(!hasPermission || typeof hasPermission === 'string') { - this.client.emit('commandBlocked', this, 'permission'); - if(typeof hasPermission === 'string') return this.channel.send(hasPermission); - else return this.channel.send(`You do not have permission to use the \`${this.command.name}\` command!`); - } - - // Ensure the client user has the required permissions - if(this.message.channel.type === 'text' && this.command.clientPermissions) { - const missing = this.message.channel.permissionsFor(this.client.user).missing(this.command.clientPermissions); - if(missing.length > 0) { - this.client.emit('commandBlocked', this, 'clientPermissions'); - if(missing.length === 1) { - return this.channel.send( - `I need the "${permissions[missing[0]]}" permission for the \`${this.command.name}\` command to work!` - ); - } - return this.channel.send(oneLine` - I need the following permissions for the \`${this.command.name}\` command to work: - ${missing.map(perm => permissions[perm]).join(', ')} - `); - } - } - - // Throttle the command - const throttle = this.command.throttle(this.message.author.id); - if(throttle && throttle.usages + 1 > this.command.throttling.usages) { - const remaining = (throttle.start + (this.command.throttling.duration * 1000) - Date.now()) / 1000; - this.client.emit('commandBlocked', this, 'throttling'); - return this.channel.send( - `**${this.message.author.username}**, please cool down! \`(${remaining.toFixed()} seconds remaining)\`` - ); - } - - // Figure out the command arguments - let args = this.patternMatches; - if(!args && this.command.argsCollector) { - const collArgs = this.command.argsCollector.args; - const count = collArgs[collArgs.length - 1].infinite ? Infinity : collArgs.length; - const provided = this.constructor.parseArgs(this.argString.trim(), count, this.command.argsSingleQuotes); - - const result = await this.command.argsCollector.obtain(this, provided); - if(result.cancelled) { - if(result.prompts.length === 0) { - const err = new CommandFormatError(this); - return this.channel.send(err.message); - } - return this.channel.send('Cancelled command!'); - } - args = result.values; - } - if(!args) args = this.parseArgs(); - const fromPattern = Boolean(this.patternMatches); - - // Run the command - if(throttle) throttle.usages++; - const typingCount = this.message.channel.typingCount; - try { - this.client.emit('debug', `Running command ${this.command.groupID}:${this.command.memberName}.`); - const promise = this.command.run(this, args, fromPattern); - /** - * Emitted when running a command - * @event CommandoClient#commandRun - * @param {Command} command - Command that is being run - * @param {Promise} promise - Promise for the command result - * @param {CommandMessage} message - Command message that the command is running from (see {@link Command#run}) - * @param {Object|string|string[]} args - Arguments for the command (see {@link Command#run}) - * @param {boolean} fromPattern - Whether the args are pattern matches (see {@link Command#run}) - */ - this.client.emit('commandRun', this.command, promise, this, args, fromPattern); - const retVal = await promise; - if(!(retVal instanceof discord.Message || retVal instanceof Array || retVal === null || retVal === undefined)) { - throw new TypeError(oneLine` - Command ${this.command.name}'s run() resolved with an unknown type - (${retVal !== null ? retVal && retVal.constructor ? retVal.constructor.name : typeof retVal : null}). - Command run methods must return a Promise that resolve with a Message, Array of Messages, or null/undefined. - `); - } - return retVal; - } catch(err) { - /** - * Emitted when a command produces an error while running - * @event CommandoClient#commandError - * @param {Command} command - Command that produced an error - * @param {Error} err - Error that was thrown - * @param {CommandMessage} message - Command message that the command is running from (see {@link Command#run}) - * @param {Object|string|string[]} args - Arguments for the command (see {@link Command#run}) - * @param {boolean} fromPattern - Whether the args are pattern matches (see {@link Command#run}) - */ - this.client.emit('commandError', this.command, err, this, args, fromPattern); - if(this.message.channel.typingCount > typingCount) this.message.channel.stopTyping(); - if(err instanceof FriendlyError) { - return this.channel.send(err.message); - } else { - const owners = this.client.owners; - let ownerList = owners ? owners.map((usr, i) => { - const or = i === owners.length - 1 && owners.length > 1 ? 'or ' : ''; - return `${or}${discord.escapeMarkdown(usr.username)}#${usr.discriminator}`; - }).join(owners.length > 2 ? ', ' : ' ') : ''; - - const invite = this.client.options.invite; - return this.channel.send(stripIndents` - ❎ | **An error occurred while running this command!** \`${err.name}: ${err.message}\` - Please contact **${ownerList || 'the bot owner'}**${invite ? ` in ${invite}` : '!'} - `); - } - } - } - - /** - * Responds to the command message - * @param {Object} [options] - Options for the response - * @return {Message|Message[]} - * @private - */ - respond({ type = 'reply', content, options, lang, fromEdit = false }) { - const shouldEdit = this.responses && !fromEdit; - if(shouldEdit) { - if(options && options.split && typeof options.split !== 'object') options.split = {}; - } - - if(type === 'reply' && this.message.channel.type === 'dm') type = 'plain'; - if(type !== 'direct') { - if(this.message.guild && !this.message.channel.permissionsFor(this.client.user).has('SEND_MESSAGES')) { - type = 'direct'; - } - } - - content = discord.Util.resolveString(content); - - switch(type) { - case 'plain': - if(!shouldEdit) return this.message.channel.send(content, options); - return this.editCurrentResponse(channelIDOrDM(this.message.channel), { type, content, options }); - case 'reply': - if(!shouldEdit) return this.message.reply(content, options); - if(options && options.split && !options.split.prepend) options.split.prepend = `${this.message.author}, `; - return this.editCurrentResponse(channelIDOrDM(this.message.channel), { type, content, options }); - case 'direct': - if(!shouldEdit) return this.message.author.send(content, options); - return this.editCurrentResponse('dm', { type, content, options }); - case 'code': - if(!shouldEdit) return this.message.channel.send(content, options); - if(options && options.split) { - if(!options.split.prepend) options.split.prepend = `\`\`\`${lang || ''}\n`; - if(!options.split.append) options.split.append = '\n```'; - } - content = `\`\`\`${lang || ''}\n${discord.escapeMarkdown(content, true)}\n\`\`\``; - return this.editCurrentResponse(channelIDOrDM(this.message.channel), { type, content, options }); - default: - throw new RangeError(`Unknown response type "${type}".`); - } - } - - /** - * Edits a response to the command message - * @param {Message|Message[]} response - The response message(s) to edit - * @param {Object} [options] - Options for the response - * @return {Promise} - * @private - */ - editResponse(response, { type, content, options }) { - if(!response) return this.respond({ type, content, options, fromEdit: true }); - if(options && options.split) content = discord.splitMessage(content, options.split); - - let prepend = ''; - if(type === 'reply') prepend = `${this.message.author}, `; - - if(content instanceof Array) { - const promises = []; - if(response instanceof Array) { - for(let i = 0; i < content.length; i++) { - if(response.length > i) promises.push(response[i].edit(`${prepend}${content[i]}`, options)); - else promises.push(response[0].channel.send(`${prepend}${content[i]}`)); - } - } else { - promises.push(response.edit(`${prepend}${content[0]}`, options)); - for(let i = 1; i < content.length; i++) { - promises.push(response.channel.send(`${prepend}${content[i]}`)); - } - } - return Promise.all(promises); - } else { - if(response instanceof Array) { // eslint-disable-line no-lonely-if - for(let i = response.length - 1; i > 0; i--) response[i].delete(); - return response[0].edit(`${prepend}${content}`, options); - } else { - return response.edit(`${prepend}${content}`, options); - } - } - } - - /** - * Edits the current response - * @param {string} id - The ID of the channel the response is in ("DM" for direct messages) - * @param {Object} [options] - Options for the response - * @return {Promise} - * @private - */ - editCurrentResponse(id, options) { - if(typeof this.responses[id] === 'undefined') this.responses[id] = []; - if(typeof this.responsePositions[id] === 'undefined') this.responsePositions[id] = -1; - this.responsePositions[id]++; - return this.editResponse(this.responses[id][this.responsePositions[id]], options); - } - - /** - * Responds with a plain message - * @param {StringResolvable} content - Content for the message - * @param {MessageOptions} [options] - Options for the message - * @return {Promise} - */ - say(content, options) { - if(!options && typeof content === 'object' && !(content instanceof Array)) { - options = content; - content = ''; - } - return this.respond({ type: 'plain', content, options }); - } - - /** - * Responds with a reply message - * @param {StringResolvable} content - Content for the message - * @param {MessageOptions} [options] - Options for the message - * @return {Promise} - */ - reply(content, options) { - if(!options && typeof content === 'object' && !(content instanceof Array)) { - options = content; - content = ''; - } - return this.respond({ type: 'reply', content, options }); - } - - /** - * Responds with a direct message - * @param {StringResolvable} content - Content for the message - * @param {MessageOptions} [options] - Options for the message - * @return {Promise} - */ - direct(content, options) { - if(!options && typeof content === 'object' && !(content instanceof Array)) { - options = content; - content = ''; - } - return this.respond({ type: 'direct', content, options }); - } - - /** - * Responds with a code message - * @param {string} lang - Language for the code block - * @param {StringResolvable} content - Content for the message - * @param {MessageOptions} [options] - Options for the message - * @return {Promise} - */ - code(lang, content, options) { - if(!options && typeof content === 'object' && !(content instanceof Array)) { - options = content; - content = ''; - } - if(typeof options !== 'object') options = {}; - options.code = lang; - return this.respond({ type: 'code', content, options }); - } - - /** - * Responds with an embed - * @param {RichEmbed|Object} embed - Embed to send - * @param {StringResolvable} [content] - Content for the message - * @param {MessageOptions} [options] - Options for the message - * @return {Promise} - */ - embed(embed, content = '', options) { - if(typeof options !== 'object') options = {}; - options.embed = embed; - return this.respond({ type: 'plain', content, options }); - } - - /** - * Responds with a mention + embed - * @param {RichEmbed|Object} embed - Embed to send - * @param {StringResolvable} [content] - Content for the message - * @param {MessageOptions} [options] - Options for the message - * @return {Promise} - */ - replyEmbed(embed, content = '', options) { - if(typeof options !== 'object') options = {}; - options.embed = embed; - return this.respond({ type: 'reply', content, options }); - } - - /** - * Finalizes the command message by setting the responses and deleting any remaining prior ones - * @param {?Array} responses - Responses to the message - * @private - */ - finalize(responses) { - if(this.responses) this.deleteRemainingResponses(); - this.responses = {}; - this.responsePositions = {}; - - if(responses instanceof Array) { - for(const response of responses) { - const channel = (response instanceof Array ? response[0] : response).channel; - const id = channelIDOrDM(channel); - if(!this.responses[id]) { - this.responses[id] = []; - this.responsePositions[id] = -1; - } - this.responses[id].push(response); - } - } else if(responses) { - const id = channelIDOrDM(responses.channel); - this.responses[id] = [responses]; - this.responsePositions[id] = -1; - } - } - - /** - * Deletes any prior responses that haven't been updated - * @private - */ - deleteRemainingResponses() { - for(const id of Object.keys(this.responses)) { - const responses = this.responses[id]; - for(let i = this.responsePositions[id] + 1; i < responses.length; i++) { - const response = responses[i]; - if(response instanceof Array) { - for(const resp of response) resp.delete(); - } else { - response.delete(); - } - } - } - } - - /** - * Parses an argument string into an array of arguments - * @param {string} argString - The argument string to parse - * @param {number} [argCount] - The number of arguments to extract from the string - * @param {boolean} [allowSingleQuote=true] - Whether or not single quotes should be allowed to wrap arguments, - * in addition to double quotes - * @return {string[]} The array of arguments - */ - static parseArgs(argString, argCount, allowSingleQuote = true) { - const re = allowSingleQuote ? /\s*(?:("|')([^]*?)\1|(\S+))\s*/g : /\s*(?:(")([^]*?)"|(\S+))\s*/g; - const result = []; - let match = []; - // Large enough to get all items - argCount = argCount || argString.length; - // Get match and push the capture group that is not null to the result - while(--argCount && (match = re.exec(argString))) result.push(match[2] || match[3]); - // If text remains, push it to the array as-is (except for wrapping quotes, which are removed) - if(match && re.lastIndex < argString.length) { - const re2 = allowSingleQuote ? /^("|')([^]*)\1$/g : /^(")([^]*)"$/g; - result.push(argString.substr(re.lastIndex).replace(re2, '$2')); - } - return result; - } - - - /* -------------------------------------------------------------------------------------------- *\ - |* SHORTCUTS *| - |* Rest not, and beware, for here be dragons. *| - |* Below these lines lie the fabled message method/getter shortcuts for ye olde lazy developer. *| - \* -------------------------------------------------------------------------------------------- */ - - /** - * Shortcut to `this.message.id` - * @type {string} - * @see {@link Message#id} - * @readonly - */ - get id() { - return this.message.id; - } - - /** - * Shortcut to `this.message.content` - * @type {string} - * @see {@link Message#content} - * @readonly - */ - get content() { - return this.message.content; - } - - /** - * Shortcut to `this.message.author` - * @type {User} - * @see {@link Message#author} - * @readonly - */ - get author() { - return this.message.author; - } - - /** - * Shortcut to `this.message.channel` - * @type {TextChannel|DMChannel|GroupDMChannel} - * @see {@link Message#channel} - * @readonly - */ - get channel() { - return this.message.channel; - } - - /** - * Shortcut to `this.message.guild` - * @type {?Guild} - * @see {@link Message#guild} - * @readonly - */ - get guild() { - return this.message.guild; - } - - /** - * Shortcut to `this.message.member` - * @type {?GuildMember} - * @see {@link Message#member} - * @readonly - */ - get member() { - return this.message.member; - } - - /** - * Shortcut to `this.message.pinned` - * @type {boolean} - * @see {@link Message#pinned} - * @readonly - */ - get pinned() { - return this.message.pinned; - } - - /** - * Shortcut to `this.message.tts` - * @type {boolean} - * @see {@link Message#tts} - * @readonly - */ - get tts() { - return this.message.tts; - } - - /** - * Shortcut to `this.message.nonce` - * @type {string} - * @see {@link Message#nonce} - * @readonly - */ - get nonce() { - return this.message.nonce; - } - - /** - * Shortcut to `this.message.system` - * @type {boolean} - * @see {@link Message#system} - * @readonly - */ - get system() { - return this.message.system; - } - - /** - * Shortcut to `this.message.embeds` - * @type {MessageEmbed[]} - * @see {@link Message#embeds} - * @readonly - */ - get embeds() { - return this.message.embeds; - } - - /** - * Shortcut to `this.message.attachments` - * @type {Collection} - * @see {@link Message#attachments} - * @readonly - */ - get attachments() { - return this.message.attachments; - } - - /** - * Shortcut to `this.message.reactions` - * @type {Collection} - * @see {@link Message#reactions} - * @readonly - */ - get reactions() { - return this.message.reactions; - } - - /** - * Shortcut to `this.message.createdTimestamp` - * @type {number} - * @see {@link Message#createdTimestamp} - * @readonly - */ - get createdTimestamp() { - return this.message.createdTimestamp; - } - - /** - * Shortcut to `this.message.createdAt` - * @type {Date} - * @see {@link Message#createdAt} - * @readonly - */ - get createdAt() { - return this.message.createdAt; - } - - /** - * Shortcut to `this.message.editedTimestamp` - * @type {number} - * @see {@link Message#editedTimestamp} - * @readonly - */ - get editedTimestamp() { - return this.message.editedTimestamp; - } - - /** - * Shortcut to `this.message.editedAt` - * @type {Date} - * @see {@link Message#editedAt} - * @readonly - */ - get editedAt() { - return this.message.editedAt; - } - - /** - * Shortcut to `this.message.mentions` - * @type {Object} - * @see {@link Message#mentions} - * @readonly - */ - get mentions() { - return this.message.mentions; - } - - /** - * Shortcut to `this.message.webhookID` - * @type {?string} - * @see {@link Message#webhookID} - * @readonly - */ - get webhookID() { - return this.message.webhookID; - } - - /** - * Shortcut to `this.message.cleanContent` - * @type {string} - * @see {@link Message#cleanContent} - * @readonly - */ - get cleanContent() { - return this.message.cleanContent; - } - - /** - * Shortcut to `this.message.edits` - * @type {Message[]} - * @see {@link Message#edits} - * @readonly - */ - get edits() { - return this.message.edits; - } - - /** - * Shortcut to `this.message.editable` - * @type {boolean} - * @see {@link Message#editable} - * @readonly - */ - get editable() { - return this.message.editable; - } - - /** - * Shortcut to `this.message.deletable` - * @type {boolean} - * @see {@link Message#deletable} - * @readonly - */ - get deletable() { - return this.message.deletable; - } - - /** - * Shortcut to `this.message.pinnable` - * @type {boolean} - * @see {@link Message#pinnable} - * @readonly - */ - get pinnable() { - return this.message.pinnable; - } - - /** - * Shortcut to `this.message.edit(content)` - * @param {StringResolvable} content - New content for the message - * @param {MessageEditOptions} options - The options to provide - * @returns {Promise} - * @see {@link Message#edit} - * @readonly - */ - edit(content, options) { - return this.message.edit(content, options); - } - - /** - * Shortcut to `this.message.editCode(content)` - * @param {string} lang - Language for the code block - * @param {StringResolvable} content - New content for the message - * @returns {Promise} - * @see {@link Message#editCode} - * @readonly - */ - editCode(lang, content) { - return this.message.editCode(lang, content); - } - - /** - * Shortcut to `this.message.react()` - * @param {string|Emoji|ReactionEmoji} emoji - Emoji to react with - * @returns {Promise} - * @see {@link Message#react} - * @readonly - */ - react(emoji) { - return this.message.react(emoji); - } - - /** - * Shortcut to `this.message.clearReactions()` - * @returns {Promise} - * @see {@link Message#clearReactions} - * @readonly - */ - clearReactions() { - return this.message.clearReactions(); - } - - /** - * Shortcut to `this.message.pin()` - * @returns {Promise} - * @see {@link Message#pin} - * @readonly - */ - pin() { - return this.message.pin(); - } - - /** - * Shortcut to `this.message.unpin()` - * @returns {Promise} - * @see {@link Message#unpin} - * @readonly - */ - unpin() { - return this.message.unpin(); - } - - /** - * Shortcut to `this.message.delete()` - * @param {number} [timeout=0] - How long to wait to delete the message in milliseconds - * @returns {Promise} - * @see {@link Message#delete} - * @readonly - */ - delete(timeout) { - return this.message.delete(timeout); - } - - /** - * Shortcut to `this.message.fetchWebhook()` - * @returns {Promise} - * @see {@link Message#fetchWebhook} - * @readonly - */ - fetchWebhook() { - return this.message.fetchWebhook(); - } -} - -function channelIDOrDM(channel) { - if(channel.type !== 'dm') return channel.id; - return 'dm'; -} - -module.exports = CommandMessage; diff --git a/Komugari-master/commando/dispatcher.js b/Komugari-master/commando/dispatcher.js deleted file mode 100644 index cd738da..0000000 --- a/Komugari-master/commando/dispatcher.js +++ /dev/null @@ -1,282 +0,0 @@ -const escapeRegex = require('escape-string-regexp'); -const CommandMessage = require('./commands/message'); - -/** Handles parsing messages and running commands from them */ -class CommandDispatcher { - /** - * @param {CommandoClient} client - Client the dispatcher is for - * @param {CommandRegistry} registry - Registry the dispatcher will use - */ - constructor(client, registry) { - /** - * Client this dispatcher handles messages for - * @name CommandDispatcher#client - * @type {CommandoClient} - * @readonly - */ - Object.defineProperty(this, 'client', { value: client }); - - /** - * Registry this dispatcher uses - * @type {CommandRegistry} - */ - this.registry = registry; - - /** - * Functions that can block commands from running - * @type {Set} - */ - this.inhibitors = new Set(); - - /** - * Map object of {@link RegExp}s that match command messages, mapped by string prefix - * @type {Object} - * @private - */ - this._commandPatterns = {}; - - /** - * Old command message results, mapped by original message ID - * @type {Map} - * @private - */ - this._results = new Map(); - - /** - * Tuples in string form of user ID and channel ID that are currently awaiting messages from a user in a channel - * @type {Set} - * @private - */ - this._awaiting = new Set(); - } - - /** - * A function that can block the usage of a command - these functions are passed the command message that is - * triggering the command. They should return `false` if the command should *not* be blocked. If the command *should* - * be blocked, they should return one of the following: - * - A single string identifying the reason the command is blocked - * - An array of the above string as element 0, and a response promise or `null` as element 1 - * @typedef {Function} Inhibitor - */ - - /** - * Adds an inhibitor - * @param {Inhibitor} inhibitor - The inhibitor function to add - * @return {boolean} Whether the addition was successful - * @example - * client.dispatcher.addInhibitor(msg => { - * if(blacklistedUsers.has(msg.author.id)) return 'blacklisted'; - * }); - * @example - * client.dispatcher.addInhibitor(msg => { - * if(!coolUsers.has(msg.author.id)) return ['cool', msg.reply('You\'re not cool enough!')]; - * }); - */ - addInhibitor(inhibitor) { - if(typeof inhibitor !== 'function') throw new TypeError('The inhibitor must be a function.'); - if(this.inhibitors.has(inhibitor)) return false; - this.inhibitors.add(inhibitor); - return true; - } - - /** - * Removes an inhibitor - * @param {Inhibitor} inhibitor - The inhibitor function to remove - * @return {boolean} Whether the removal was successful - */ - removeInhibitor(inhibitor) { - if(typeof inhibitor !== 'function') throw new TypeError('The inhibitor must be a function.'); - return this.inhibitors.delete(inhibitor); - } - - // eslint-disable-next-line valid-jsdoc - /** - * Handle a new message or a message update - * @param {Message} message - The message to handle - * @param {Message} [oldMessage] - The old message before the update - * @return {Promise} - * @private - */ - async handleMessage(message, oldMessage) { - if(!this.shouldHandleMessage(message, oldMessage)) return; - - // Parse the message, and get the old result if it exists - let cmdMsg, oldCmdMsg; - if(oldMessage) { - oldCmdMsg = this._results.get(oldMessage.id); - if(!oldCmdMsg && !this.client.options.nonCommandEditable) return; - cmdMsg = this.parseMessage(message); - if(cmdMsg && oldCmdMsg) { - cmdMsg.responses = oldCmdMsg.responses; - cmdMsg.responsePositions = oldCmdMsg.responsePositions; - } - } else { - cmdMsg = this.parseMessage(message); - } - - // Run the command, or reply with an error - let responses; - if(cmdMsg) { - const inhibited = this.inhibit(cmdMsg); - - if(!inhibited) { - if(cmdMsg.command) { - if(!cmdMsg.command.isEnabledIn(message.guild)) { - responses = await cmdMsg.reply(`The \`${cmdMsg.command.name}\` command is disabled.`); - } else if(!oldMessage || typeof oldCmdMsg !== 'undefined') { - responses = await cmdMsg.run(); - if(typeof responses === 'undefined') responses = null; // eslint-disable-line max-depth - } - } else { - /** - * Emitted when an unknown command is triggered - * @event CommandoClient#unknownCommand - * @param {CommandMessage} message - Command message that triggered the command - */ - this.client.emit('unknownCommand', cmdMsg); - if(this.client.options.unknownCommandResponse) { - responses = await cmdMsg.reply( - `Unknown command. Use ${cmdMsg.anyUsage( - 'help', - message.guild ? undefined : null, - message.guild ? undefined : null - )} to view the list of all commands.` - ); - } - } - } else { - responses = await inhibited[1]; - } - - cmdMsg.finalize(responses); - } else if(oldCmdMsg) { - oldCmdMsg.finalize(null); - if(!this.client.options.nonCommandEditable) this._results.delete(message.id); - } - - this.cacheCommandMessage(message, oldMessage, cmdMsg, responses); - } - - /** - * Check whether a message should be handled - * @param {Message} message - The message to handle - * @param {Message} [oldMessage] - The old message before the update - * @return {boolean} - * @private - */ - shouldHandleMessage(message, oldMessage) { - if(message.author.bot) return false; - else if(this.client.options.selfbot && message.author.id !== this.client.user.id) return false; - else if(!this.client.options.selfbot && message.author.id === this.client.user.id) return false; - - // Ignore messages from users that the bot is already waiting for input from - if(this._awaiting.has(message.author.id + message.channel.id)) return false; - - // Make sure the edit actually changed the message content - if(oldMessage && message.content === oldMessage.content) return false; - - return true; - } - - /** - * Inhibits a command message - * @param {CommandMessage} cmdMsg - Command message to inhibit - * @return {?Array} [reason, ?response] - * @private - */ - inhibit(cmdMsg) { - for(const inhibitor of this.inhibitors) { - const inhibited = inhibitor(cmdMsg); - if(inhibited) { - this.client.emit('commandBlocked', cmdMsg, inhibited instanceof Array ? inhibited[0] : inhibited); - return inhibited instanceof Array ? inhibited : [inhibited, undefined]; - } - } - return null; - } - - /** - * Caches a command message to be editable - * @param {Message} message - Triggering message - * @param {Message} oldMessage - Triggering message's old version - * @param {CommandMessage} cmdMsg - Command message to cache - * @param {Message|Message[]} responses - Responses to the message - * @private - */ - cacheCommandMessage(message, oldMessage, cmdMsg, responses) { - if(this.client.options.commandEditableDuration <= 0) return; - if(!cmdMsg && !this.client.options.nonCommandEditable) return; - if(responses !== null) { - this._results.set(message.id, cmdMsg); - if(!oldMessage) { - setTimeout(() => { this._results.delete(message.id); }, this.client.options.commandEditableDuration * 1000); - } - } else { - this._results.delete(message.id); - } - } - - /** - * Parses a message to find details about command usage in it - * @param {Message} message - The message - * @return {?CommandMessage} - * @private - */ - parseMessage(message) { - // Find the command to run by patterns - for(const command of this.registry.commands.values()) { - if(!command.patterns) continue; - for(const pattern of command.patterns) { - const matches = pattern.exec(message.content); - if(matches) return new CommandMessage(message, command, null, matches); - } - } - - // Find the command to run with default command handling - const prefix = message.guild ? message.guild.commandPrefix : this.client.commandPrefix; - if(!this._commandPatterns[prefix]) this.buildCommandPattern(prefix); - let cmdMsg = this.matchDefault(message, this._commandPatterns[prefix], 2); - if(!cmdMsg && !message.guild && !this.client.options.selfbot) cmdMsg = this.matchDefault(message, /^([^\s]+)/i); - return cmdMsg; - } - - /** - * Matches a message against a guild command pattern - * @param {Message} message - The message - * @param {RegExp} pattern - The pattern to match against - * @param {number} commandNameIndex - The index of the command name in the pattern matches - * @return {?CommandMessage} - * @private - */ - matchDefault(message, pattern, commandNameIndex = 1) { - const matches = pattern.exec(message.content); - if(!matches) return null; - const commands = this.registry.findCommands(matches[commandNameIndex], true); - if(commands.length !== 1 || !commands[0].defaultHandling) return new CommandMessage(message, null); - const argString = message.content.substring(matches[1].length + (matches[2] ? matches[2].length : 0)); - return new CommandMessage(message, commands[0], argString); - } - - /** - * Creates a regular expression to match the command prefix and name in a message - * @param {?string} prefix - Prefix to build the pattern for - * @return {RegExp} - * @private - */ - buildCommandPattern(prefix) { - let pattern; - if(prefix) { - const escapedPrefix = escapeRegex(prefix); - pattern = new RegExp( - `^(${escapedPrefix}\\s*|<@!?${this.client.user.id}>\\s+(?:${escapedPrefix})?)([^\\s]+)`, 'i' - ); - } else { - pattern = new RegExp(`(^<@!?${this.client.user.id}>\\s+)([^\\s]+)`, 'i'); - } - this._commandPatterns[prefix] = pattern; - this.client.emit('debug', `Built command pattern for prefix "${prefix}": ${pattern}`); - return pattern; - } -} - -module.exports = CommandDispatcher; diff --git a/Komugari-master/commando/errors/command-format.js b/Komugari-master/commando/errors/command-format.js deleted file mode 100644 index 8034a91..0000000 --- a/Komugari-master/commando/errors/command-format.js +++ /dev/null @@ -1,23 +0,0 @@ -const FriendlyError = require('./friendly'); - -/** - * Has a descriptive message for a command not having proper format - * @extends {FriendlyError} - */ -class CommandFormatError extends FriendlyError { - /** - * @param {CommandMessage} msg - The command message the error is for - */ - constructor(msg) { - super( - `Invalid command format. Use ${msg.anyUsage( - `help ${msg.command.name}`, - msg.guild ? undefined : null, - msg.guild ? undefined : null - )} for information.` - ); - this.name = 'CommandFormatError'; - } -} - -module.exports = CommandFormatError; diff --git a/Komugari-master/commando/errors/friendly.js b/Komugari-master/commando/errors/friendly.js deleted file mode 100644 index c94d054..0000000 --- a/Komugari-master/commando/errors/friendly.js +++ /dev/null @@ -1,13 +0,0 @@ -/** - * Has a message that can be considered user-friendly - * @extends {Error} - */ -class FriendlyError extends Error { - /** @param {string} message - The error message */ - constructor(message) { - super(message); - this.name = 'FriendlyError'; - } -} - -module.exports = FriendlyError; diff --git a/Komugari-master/commando/extensions/guild.js b/Komugari-master/commando/extensions/guild.js deleted file mode 100644 index d48cf1f..0000000 --- a/Komugari-master/commando/extensions/guild.js +++ /dev/null @@ -1,165 +0,0 @@ -const Command = require('../commands/base'); -const GuildSettingsHelper = require('../providers/helper'); - -/** Contains additional methods and properties that are added to the discord.js Guild class */ -class GuildExtension { - /** - * Command prefix in the guild. An empty string indicates that there is no prefix, and only mentions will be used. - * Setting to `null` means that the prefix from {@link CommandoClient#commandPrefix} will be used instead. - * @type {string} - * @emits {@link CommandoClient#commandPrefixChange} - */ - get commandPrefix() { - if(typeof this._commandPrefix === 'undefined' || this._commandPrefix === null) return this.client.commandPrefix; - return this._commandPrefix; - } - - set commandPrefix(prefix) { - /** - * Internal command prefix for the guild, controlled by the {@link GuildExtension#commandPrefix} getter/setter - * @name GuildExtension#_commandPrefix - * @type {?string} - * @private - */ - this._commandPrefix = prefix; - - /** - * Emitted whenever a guild's command prefix is changed - * @event CommandoClient#commandPrefixChange - * @param {?Guild} guild - Guild that the prefix was changed in (null for global) - * @param {?string} prefix - New command prefix (null for default) - */ - this.client.emit('commandPrefixChange', this, this._commandPrefix); - } - - /** - * Shortcut to use setting provider methods for this guild - * @type {GuildSettingsHelper} - * @readonly - */ - get settings() { - /** - * Internal settings helper that is created upon accessing the {@link GuildExtension#settings} getter - * @name GuildExtension#_settings - * @type {GuildSettingsHelper} - * @private - */ - if(!this._settings) this._settings = new GuildSettingsHelper(this.client, this); - return this._settings; - } - - /** - * Sets whether a command is enabled in the guild - * @param {CommandResolvable} command - Command to set status of - * @param {boolean} enabled - Whether the command should be enabled - */ - setCommandEnabled(command, enabled) { - command = this.client.registry.resolveCommand(command); - if(command.guarded) throw new Error('The command is guarded.'); - if(typeof enabled === 'undefined') throw new TypeError('Enabled must not be undefined.'); - enabled = Boolean(enabled); - if(!this._commandsEnabled) { - /** - * Map object of internal command statuses, mapped by command name - * @type {Object} - * @private - */ - this._commandsEnabled = {}; - } - this._commandsEnabled[command.name] = enabled; - /** - * Emitted whenever a command is enabled/disabled in a guild - * @event CommandoClient#commandStatusChange - * @param {?Guild} guild - Guild that the command was enabled/disabled in (null for global) - * @param {Command} command - Command that was enabled/disabled - * @param {boolean} enabled - Whether the command is enabled - */ - this.client.emit('commandStatusChange', this, command, enabled); - } - - /** - * Checks whether a command is enabled in the guild (does not take the command's group status into account) - * @param {CommandResolvable} command - Command to check status of - * @return {boolean} - */ - isCommandEnabled(command) { - command = this.client.registry.resolveCommand(command); - if(command.guarded) return true; - if(!this._commandsEnabled || typeof this._commandsEnabled[command.name] === 'undefined') { - return command._globalEnabled; - } - return this._commandsEnabled[command.name]; - } - - /** - * Sets whether a command group is enabled in the guild - * @param {CommandGroupResolvable} group - Command to set status of - * @param {boolean} enabled - Whether the group should be enabled - */ - setGroupEnabled(group, enabled) { - group = this.client.registry.resolveGroup(group); - if(group.guarded) throw new Error('The group is guarded.'); - if(typeof enabled === 'undefined') throw new TypeError('Enabled must not be undefined.'); - enabled = Boolean(enabled); - if(!this._groupsEnabled) { - /** - * Internal map object of group statuses, mapped by group ID - * @type {Object} - * @private - */ - this._groupsEnabled = {}; - } - this._groupsEnabled[group.id] = enabled; - /** - * Emitted whenever a command group is enabled/disabled in a guild - * @event CommandoClient#groupStatusChange - * @param {?Guild} guild - Guild that the group was enabled/disabled in (null for global) - * @param {CommandGroup} group - Group that was enabled/disabled - * @param {boolean} enabled - Whether the group is enabled - */ - this.client.emit('groupStatusChange', this, group, enabled); - } - - /** - * Checks whether a command group is enabled in the guild - * @param {CommandGroupResolvable} group - Group to check status of - * @return {boolean} - */ - isGroupEnabled(group) { - group = this.client.registry.resolveGroup(group); - if(group.guarded) return true; - if(!this._groupsEnabled || typeof this._groupsEnabled[group.id] === 'undefined') return group._globalEnabled; - return this._groupsEnabled[group.id]; - } - - /** - * Creates a command usage string using the guild's prefix - * @param {string} [command] - A command + arg string - * @param {User} [user=this.client.user] - User to use for the mention command format - * @return {string} - */ - commandUsage(command, user = this.client.user) { - return Command.usage(command, this.commandPrefix, user); - } - - /** - * Applies the interface to a class prototype - * @param {Function} target - The constructor function to apply to the prototype of - * @private - */ - static applyToClass(target) { - for(const prop of [ - 'commandPrefix', - 'settings', - 'setCommandEnabled', - 'isCommandEnabled', - 'setGroupEnabled', - 'isGroupEnabled', - 'commandUsage' - ]) { - Object.defineProperty(target.prototype, prop, Object.getOwnPropertyDescriptor(this.prototype, prop)); - } - } -} - -module.exports = GuildExtension; diff --git a/Komugari-master/commando/index.js b/Komugari-master/commando/index.js deleted file mode 100644 index d904b77..0000000 --- a/Komugari-master/commando/index.js +++ /dev/null @@ -1,124 +0,0 @@ -const discord = require('discord.js'); - -module.exports = { - Client: require('./client'), - CommandoClient: require('./client'), - Command: require('./commands/base'), - CommandGroup: require('./commands/group'), - CommandMessage: require('./commands/message'), - ArgumentCollector: require('./commands/collector'), - Argument: require('./commands/argument'), - ArgumentType: require('./types/base'), - FriendlyError: require('./errors/friendly'), - CommandFormatError: require('./errors/command-format'), - - util: require('./util'), - - SettingProvider: require('./providers/base'), - get SQLiteProvider() { - return require('./providers/sqlite'); - } -}; - -require('./extensions/guild').applyToClass(discord.Guild); - -/** - * @external Channel - * @see {@link https://discord.js.org/#/docs/main/master/class/Channel} - */ -/** - * @external Client - * @see {@link https://discord.js.org/#/docs/main/master/class/Client} - */ -/** - * @external ClientOptions - * @see {@link https://discord.js.org/#/docs/main/master/typedef/ClientOptions} - */ -/** - * @external Collection - * @see {@link https://discord.js.org/#/docs/main/master/class/Collection} - */ -/** - * @external DMChannel - * @see {@link https://discord.js.org/#/docs/main/master/class/DMChannel} - */ -/** - * @external GroupDMChannel - * @see {@link https://discord.js.org/#/docs/main/master/class/GroupDMChannel} - */ -/** - * @external Guild - * @see {@link https://discord.js.org/#/docs/main/master/class/Guild} - */ -/** - * @external GuildMember - * @see {@link https://discord.js.org/#/docs/main/master/class/GuildMember} - */ -/** - * @external GuildResolvable - * @see {@link https://discord.js.org/#/docs/main/master/typedef/GuildResolvable} - */ -/** - * @external Message - * @see {@link https://discord.js.org/#/docs/main/master/class/Message} - */ -/** - * @external MessageAttachment - * @see {@link https://discord.js.org/#/docs/main/master/class/MessageAttachment} - */ -/** - * @external MessageEmbed - * @see {@link https://discord.js.org/#/docs/main/master/class/MessageEmbed} - */ -/** - * @external MessageReaction - * @see {@link https://discord.js.org/#/docs/main/master/class/MessageReaction} - */ -/** - * @external MessageOptions - * @see {@link https://discord.js.org/#/docs/main/master/typedef/MessageOptions} - */ -/** - * @external Role - * @see {@link https://discord.js.org/#/docs/main/master/class/Role} - */ -/** - * @external StringResolvable - * @see {@link https://discord.js.org/#/docs/main/master/typedef/StringResolvable} - */ -/** - * @external TextChannel - * @see {@link https://discord.js.org/#/docs/main/master/class/TextChannel} - */ -/** - * @external User - * @see {@link https://discord.js.org/#/docs/main/master/class/User} - */ -/** - * @external UserResolvable - * @see {@link https://discord.js.org/#/docs/main/master/class/UserResolvable} - */ -/** - * @external Emoji - * @see {@link https://discord.js.org/#/docs/main/master/class/Emoji} - */ -/** - * @external ReactionEmoji - * @see {@link https://discord.js.org/#/docs/main/master/class/ReactionEmoji} - */ -/** - * @external Webhook - * @see {@link https://discord.js.org/#/docs/main/master/class/Webhook} - */ -/** - * @external RichEmbed - * @see {@link https://discord.js.org/#/docs/main/master/class/RichEmbed} - */ -/** - * @external ShardingManager - * @see {@link https://discord.js.org/#/docs/main/master/class/ShardingManager} - */ -/** - * @external RequireAllOptions - * @see {@link https://www.npmjs.com/package/require-all} - */ diff --git a/Komugari-master/commando/providers/base.js b/Komugari-master/commando/providers/base.js deleted file mode 100644 index 0cee8e3..0000000 --- a/Komugari-master/commando/providers/base.js +++ /dev/null @@ -1,79 +0,0 @@ -/* eslint-disable no-unused-vars, valid-jsdoc */ -const Guild = require('discord.js').Guild; - -/** - * Loads and stores settings associated with guilds - * @abstract - */ -class SettingProvider { - constructor() { - if(this.constructor.name === 'SettingProvider') throw new Error('The base SettingProvider cannot be instantiated.'); - } - - /** - * Initialises the provider by connecting to databases and/or caching all data in memory. - * {@link CommandoClient#setProvider} will automatically call this once the client is ready. - * @param {CommandoClient} client - Client that will be using the provider - * @return {Promise} - * @abstract - */ - init(client) { throw new Error(`${this.constructor.name} doesn't have an init method.`); } - - /** - * Destroys the provider, removing any event listeners. - * @return {Promise} - * @abstract - */ - destroy() { throw new Error(`${this.constructor.name} doesn't have a destroy method.`); } - - /** - * Obtains a setting for a guild - * @param {Guild|string} guild - Guild the setting is associated with (or 'global') - * @param {string} key - Name of the setting - * @param {*} [defVal] - Value to default to if the setting isn't set on the guild - * @return {*} - * @abstract - */ - get(guild, key, defVal) { throw new Error(`${this.constructor.name} doesn't have a get method.`); } - - /** - * Sets a setting for a guild - * @param {Guild|string} guild - Guild to associate the setting with (or 'global') - * @param {string} key - Name of the setting - * @param {*} val - Value of the setting - * @return {Promise<*>} New value of the setting - * @abstract - */ - set(guild, key, val) { throw new Error(`${this.constructor.name} doesn't have a set method.`); } - - /** - * Removes a setting from a guild - * @param {Guild|string} guild - Guild the setting is associated with (or 'global') - * @param {string} key - Name of the setting - * @return {Promise<*>} Old value of the setting - * @abstract - */ - remove(guild, key) { throw new Error(`${this.constructor.name} doesn't have a remove method.`); } - - /** - * Removes all settings in a guild - * @param {Guild|string} guild - Guild to clear the settings of - * @return {Promise} - * @abstract - */ - clear(guild) { throw new Error(`${this.constructor.name} doesn't have a clear method.`); } - - /** - * Obtains the ID of the provided guild, or throws an error if it isn't valid - * @param {Guild|string} guild - Guild to get the ID of - * @return {string} ID of the guild, or 'global' - */ - static getGuildID(guild) { - if(guild instanceof Guild) return guild.id; - if(guild === 'global' || guild === null) return 'global'; - if(typeof guild === 'string' && !isNaN(guild)) return guild; - throw new TypeError('Invalid guild specified. Must be a Guild instance, guild ID, "global", or null.'); - } -} - -module.exports = SettingProvider; diff --git a/Komugari-master/commando/providers/helper.js b/Komugari-master/commando/providers/helper.js deleted file mode 100644 index f639298..0000000 --- a/Komugari-master/commando/providers/helper.js +++ /dev/null @@ -1,70 +0,0 @@ -/** Helper class to use {@link SettingProvider} methods for a specific Guild */ -class GuildSettingsHelper { - /** - * @param {CommandoClient} client - Client to use the provider of - * @param {?Guild} guild - Guild the settings are for - * @private - */ - constructor(client, guild) { - /** - * Client to use the provider of - * @name GuildSettingsHelper#client - * @type {CommandoClient} - * @readonly - */ - Object.defineProperty(this, 'client', { value: client }); - - /** - * Guild the settings are for - * @type {?Guild} - */ - this.guild = guild; - } - - /** - * Gets a setting in the guild - * @param {string} key - Name of the setting - * @param {*} [defVal] - Value to default to if the setting isn't set - * @return {*} - * @see {@link SettingProvider#get} - */ - get(key, defVal) { - if(!this.client.provider) throw new Error('No settings provider is available.'); - return this.client.provider.get(this.guild, key, defVal); - } - - /** - * Sets a setting for the guild - * @param {string} key - Name of the setting - * @param {*} val - Value of the setting - * @return {Promise<*>} New value of the setting - * @see {@link SettingProvider#set} - */ - set(key, val) { - if(!this.client.provider) throw new Error('No settings provider is available.'); - return this.client.provider.set(this.guild, key, val); - } - - /** - * Removes a setting from the guild - * @param {string} key - Name of the setting - * @return {Promise<*>} Old value of the setting - * @see {@link SettingProvider#remove} - */ - remove(key) { - if(!this.client.provider) throw new Error('No settings provider is available.'); - return this.client.provider.remove(this.guild, key); - } - - /** - * Removes all settings in the guild - * @return {Promise} - * @see {@link SettingProvider#clear} - */ - clear() { - if(!this.client.provider) throw new Error('No settings provider is available.'); - return this.client.provider.clear(this.guild); - } -} - -module.exports = GuildSettingsHelper; diff --git a/Komugari-master/commando/providers/sqlite.js b/Komugari-master/commando/providers/sqlite.js deleted file mode 100644 index f824d6f..0000000 --- a/Komugari-master/commando/providers/sqlite.js +++ /dev/null @@ -1,249 +0,0 @@ -const SettingProvider = require('./base'); - -/** - * Uses an SQLite database to store settings with guilds - * @extends {SettingProvider} - */ -class SQLiteProvider extends SettingProvider { - /** - * @external SQLiteDatabase - * @see {@link https://www.npmjs.com/package/sqlite} - */ - - /** - * @param {SQLiteDatabase} db - Database for the provider - */ - constructor(db) { - super(); - - /** - * Database that will be used for storing/retrieving settings - * @type {SQLiteDatabase} - */ - this.db = db; - - /** - * Client that the provider is for (set once the client is ready, after using {@link CommandoClient#setProvider}) - * @name SQLiteProvider#client - * @type {CommandoClient} - * @readonly - */ - Object.defineProperty(this, 'client', { value: null, writable: true }); - - /** - * Settings cached in memory, mapped by guild ID (or 'global') - * @type {Map} - * @private - */ - this.settings = new Map(); - - /** - * Listeners on the Client, mapped by the event name - * @type {Map} - * @private - */ - this.listeners = new Map(); - - /** - * Prepared statement to insert or replace a settings row - * @type {SQLiteStatement} - * @private - */ - this.insertOrReplaceStmt = null; - - /** - * Prepared statement to delete an entire settings row - * @type {SQLiteStatement} - * @private - */ - this.deleteStmt = null; - - /** - * @external SQLiteStatement - * @see {@link https://www.npmjs.com/package/sqlite} - */ - } - - async init(client) { - this.client = client; - await this.db.run('CREATE TABLE IF NOT EXISTS settings (guild INTEGER PRIMARY KEY, settings TEXT)'); - - // Load all settings - const rows = await this.db.all('SELECT CAST(guild as TEXT) as guild, settings FROM settings'); - for(const row of rows) { - let settings; - try { - settings = JSON.parse(row.settings); - } catch(err) { - client.emit('warn', `SQLiteProvider couldn't parse the settings stored for guild ${row.guild}.`); - continue; - } - - const guild = row.guild !== '0' ? row.guild : 'global'; - this.settings.set(guild, settings); - if(guild !== 'global' && !client.guilds.has(row.guild)) continue; - this.setupGuild(guild, settings); - } - - // Prepare statements - const statements = await Promise.all([ - this.db.prepare('INSERT OR REPLACE INTO settings VALUES(?, ?)'), - this.db.prepare('DELETE FROM settings WHERE guild = ?') - ]); - this.insertOrReplaceStmt = statements[0]; - this.deleteStmt = statements[1]; - - // Listen for changes - this.listeners - .set('commandPrefixChange', (guild, prefix) => this.set(guild, 'prefix', prefix)) - .set('commandStatusChange', (guild, command, enabled) => this.set(guild, `cmd-${command.name}`, enabled)) - .set('groupStatusChange', (guild, group, enabled) => this.set(guild, `grp-${group.id}`, enabled)) - .set('guildCreate', guild => { - const settings = this.settings.get(guild.id); - if(!settings) return; - this.setupGuild(guild.id, settings); - }) - .set('commandRegister', command => { - for(const [guild, settings] of this.settings) { - if(guild !== 'global' && !client.guilds.has(guild)) continue; - this.setupGuildCommand(client.guilds.get(guild), command, settings); - } - }) - .set('groupRegister', group => { - for(const [guild, settings] of this.settings) { - if(guild !== 'global' && !client.guilds.has(guild)) continue; - this.setupGuildGroup(client.guilds.get(guild), group, settings); - } - }); - for(const [event, listener] of this.listeners) client.on(event, listener); - } - - async destroy() { - // Finalise prepared statements - await Promise.all([ - this.insertOrReplaceStmt.finalize(), - this.deleteStmt.finalize() - ]); - - // Remove all listeners from the client - for(const [event, listener] of this.listeners) this.client.removeListener(event, listener); - this.listeners.clear(); - } - - get(guild, key, defVal) { - const settings = this.settings.get(this.constructor.getGuildID(guild)); - return settings ? typeof settings[key] !== 'undefined' ? settings[key] : defVal : defVal; - } - - async set(guild, key, val) { - guild = this.constructor.getGuildID(guild); - let settings = this.settings.get(guild); - if(!settings) { - settings = {}; - this.settings.set(guild, settings); - } - - settings[key] = val; - await this.insertOrReplaceStmt.run(guild !== 'global' ? guild : 0, JSON.stringify(settings)); - if(guild === 'global') this.updateOtherShards(key, val); - return val; - } - - async remove(guild, key) { - guild = this.constructor.getGuildID(guild); - const settings = this.settings.get(guild); - if(!settings || typeof settings[key] === 'undefined') return undefined; - - const val = settings[key]; - settings[key] = undefined; - await this.insertOrReplaceStmt.run(guild !== 'global' ? guild : 0, JSON.stringify(settings)); - if(guild === 'global') this.updateOtherShards(key, undefined); - return val; - } - - async clear(guild) { - guild = this.constructor.getGuildID(guild); - if(!this.settings.has(guild)) return; - this.settings.delete(guild); - await this.deleteStmt.run(guild !== 'global' ? guild : 0); - } - - /** - * Loads all settings for a guild - * @param {string} guild - Guild ID to load the settings of (or 'global') - * @param {Object} settings - Settings to load - * @private - */ - setupGuild(guild, settings) { - if(typeof guild !== 'string') throw new TypeError('The guild must be a guild ID or "global".'); - guild = this.client.guilds.get(guild) || null; - - // Load the command prefix - if(typeof settings.prefix !== 'undefined') { - if(guild) guild._commandPrefix = settings.prefix; - else this.client._commandPrefix = settings.prefix; - } - - // Load all command/group statuses - for(const command of this.client.registry.commands.values()) this.setupGuildCommand(guild, command, settings); - for(const group of this.client.registry.groups.values()) this.setupGuildGroup(guild, group, settings); - } - - /** - * Sets up a command's status in a guild from the guild's settings - * @param {?Guild} guild - Guild to set the status in - * @param {Command} command - Command to set the status of - * @param {Object} settings - Settings of the guild - * @private - */ - setupGuildCommand(guild, command, settings) { - if(typeof settings[`cmd-${command.name}`] === 'undefined') return; - if(guild) { - if(!guild._commandsEnabled) guild._commandsEnabled = {}; - guild._commandsEnabled[command.name] = settings[`cmd-${command.name}`]; - } else { - command._globalEnabled = settings[`cmd-${command.name}`]; - } - } - - /** - * Sets up a group's status in a guild from the guild's settings - * @param {?Guild} guild - Guild to set the status in - * @param {CommandGroup} group - Group to set the status of - * @param {Object} settings - Settings of the guild - * @private - */ - setupGuildGroup(guild, group, settings) { - if(typeof settings[`grp-${group.id}`] === 'undefined') return; - if(guild) { - if(!guild._groupsEnabled) guild._groupsEnabled = {}; - guild._groupsEnabled[group.id] = settings[`grp-${group.id}`]; - } else { - group._globalEnabled = settings[`grp-${group.id}`]; - } - } - - /** - * Updates a global setting on all other shards if using the {@link ShardingManager}. - * @param {string} key - Key of the setting to update - * @param {*} val - Value of the setting - * @private - */ - updateOtherShards(key, val) { - if(!this.client.shard) return; - key = JSON.stringify(key); - val = typeof val !== 'undefined' ? JSON.stringify(val) : 'undefined'; - this.client.shard.broadcastEval(` - if(this.shard.id !== ${this.client.shard.id} && this.provider && this.provider.settings) { - let global = this.provider.settings.get('global'); - if(!global) { - global = {}; - this.provider.settings.set('global', global); - } - global[${key}] = ${val}; - } - `); - } -} - -module.exports = SQLiteProvider; diff --git a/Komugari-master/commando/registry.js b/Komugari-master/commando/registry.js deleted file mode 100644 index f821ef5..0000000 --- a/Komugari-master/commando/registry.js +++ /dev/null @@ -1,447 +0,0 @@ -const path = require('path'); -const discord = require('discord.js'); -const Command = require('./commands/base'); -const CommandGroup = require('./commands/group'); -const CommandMessage = require('./commands/message'); -const ArgumentType = require('./types/base'); - -/** Handles registration and searching of commands and groups */ -class CommandRegistry { - /** @param {CommandoClient} [client] - Client to use */ - constructor(client) { - /** - * The client this registry is for - * @name CommandRegistry#client - * @type {CommandoClient} - * @readonly - */ - Object.defineProperty(this, 'client', { value: client }); - - /** - * Registered commands - * @type {Collection} - */ - this.commands = new discord.Collection(); - - /** - * Registered command groups - * @type {Collection} - */ - this.groups = new discord.Collection(); - - /** - * Registered argument types - * @type {Collection} - */ - this.types = new discord.Collection(); - - /** - * Registered objects for the eval command - * @type {Object} - */ - this.evalObjects = {}; - - /** - * Fully resolved path to the bot's commands directory - * @type {?string} - */ - this.commandsPath = null; - } - - /** - * Registers a single group - * @param {CommandGroup|Function|string[]|string} group - A CommandGroup instance, a constructor, - * an array of [ID, Name], or the group ID - * @param {string} [name] - Name for the group (if the first argument is the group ID) - * @return {CommandRegistry} - * @see {@link CommandRegistry#registerGroups} - */ - registerGroup(group, name) { - if(typeof group === 'string') return this.registerGroups([[group, name]]); - return this.registerGroups([group]); - } - - /** - * Registers multiple groups - * @param {CommandGroup[]|Function[]|Array} groups - An array of CommandGroup instances, constructors, - * or arrays of [ID, Name] - * @return {CommandRegistry} - */ - registerGroups(groups) { - if(!Array.isArray(groups)) throw new TypeError('Groups must be an Array.'); - for(let group of groups) { - if(typeof group === 'function') { - group = new group(this.client); // eslint-disable-line new-cap - } else if(Array.isArray(group)) { - group = new CommandGroup(this.client, ...group); - } else if(!(group instanceof CommandGroup)) { - group = new CommandGroup(this.client, group.id, group.name, null, group.commands); - } - - const existing = this.groups.get(group.id); - if(existing) { - existing.name = group.name; - this.client.emit('debug', `Group ${group.id} is already registered; renamed it to "${group.name}".`); - } else { - this.groups.set(group.id, group); - /** - * Emitted when a group is registered - * @event CommandoClient#groupRegister - * @param {CommandGroup} group - Group that was registered - * @param {CommandRegistry} registry - Registry that the group was registered to - */ - this.client.emit('groupRegister', group, this); - this.client.emit('debug', `Registered group ${group.id}.`); - } - } - return this; - } - - /** - * Registers a single command - * @param {Command|Function} command - Either a Command instance, or a constructor for one - * @return {CommandRegistry} - * @see {@link CommandRegistry#registerCommands} - */ - registerCommand(command) { - return this.registerCommands([command]); - } - - /** - * Registers multiple commands - * @param {Command[]|Function[]} commands - An array of Command instances or constructors - * @return {CommandRegistry} - */ - registerCommands(commands) { - if(!Array.isArray(commands)) throw new TypeError('Commands must be an Array.'); - for(let command of commands) { - if(typeof command === 'function') command = new command(this.client); // eslint-disable-line new-cap - - // Verify that it's an actual command - if(!(command instanceof Command)) { - this.client.emit('warn', `Attempting to register an invalid command object: ${command}; skipping.`); - continue; - } - - // Make sure there aren't any conflicts - if(this.commands.some(cmd => cmd.name === command.name || cmd.aliases.includes(command.name))) { - throw new Error(`A command with the name/alias "${command.name}" is already registered.`); - } - for(const alias of command.aliases) { - if(this.commands.some(cmd => cmd.name === alias || cmd.aliases.includes(alias))) { - throw new Error(`A command with the name/alias "${alias}" is already registered.`); - } - } - const group = this.groups.find(grp => grp.id === command.groupID); - if(!group) throw new Error(`Group "${command.groupID}" is not registered.`); - if(group.commands.some(cmd => cmd.memberName === command.memberName)) { - throw new Error(`A command with the member name "${command.memberName}" is already registered in ${group.id}`); - } - - // Add the command - command.group = group; - group.commands.set(command.name, command); - this.commands.set(command.name, command); - /** - * Emitted when a command is registered - * @event CommandoClient#commandRegister - * @param {Command} command - Command that was registered - * @param {CommandRegistry} registry - Registry that the command was registered to - */ - this.client.emit('commandRegister', command, this); - this.client.emit('debug', `Registered command ${group.id}:${command.memberName}.`); - } - - return this; - } - - /** - * Registers all commands in a directory. The files must export a Command class constructor or instance. - * @param {string|RequireAllOptions} options - The path to the directory, or a require-all options object - * @return {CommandRegistry} - */ - registerCommandsIn(options) { - const obj = require('require-all')(options); - const commands = []; - for(const group of Object.values(obj)) { - for(let command of Object.values(group)) { - if(typeof command.default === 'function') command = command.default; - commands.push(command); - } - } - if(typeof options === 'string' && !this.commandsPath) this.commandsPath = options; - return this.registerCommands(commands); - } - - /** - * Registers a single argument type - * @param {ArgumentType|Function} type - Either an ArgumentType instance, or a constructor for one - * @return {CommandRegistry} - * @see {@link CommandRegistry#registerTypes} - */ - registerType(type) { - return this.registerTypes([type]); - } - - /** - * Registers multiple argument types - * @param {ArgumentType[]|Function[]} types - An array of ArgumentType instances or constructors - * @return {CommandRegistry} - */ - registerTypes(types) { - if(!Array.isArray(types)) throw new TypeError('Types must be an Array.'); - for(let type of types) { - if(typeof type === 'function') type = new type(this.client); // eslint-disable-line new-cap - - // Verify that it's an actual type - if(!(type instanceof ArgumentType)) { - this.client.emit('warn', `Attempting to register an invalid argument type object: ${type}; skipping.`); - continue; - } - - // Make sure there aren't any conflicts - if(this.types.has(type.id)) throw new Error(`An argument type with the ID "${type.id}" is already registered.`); - - // Add the type - this.types.set(type.id, type); - /** - * Emitted when an argument type is registered - * @event CommandoClient#typeRegister - * @param {ArgumentType} type - Argument type that was registered - * @param {CommandRegistry} registry - Registry that the type was registered to - */ - this.client.emit('typeRegister', type, this); - this.client.emit('debug', `Registered argument type ${type.id}.`); - } - - return this; - } - - /** - * Registers all argument types in a directory. The files must export an ArgumentType class constructor or instance. - * @param {string|RequireAllOptions} options - The path to the directory, or a require-all options object - * @return {CommandRegistry} - */ - registerTypesIn(options) { - const obj = require('require-all')(options); - const types = []; - for(const type of Object.values(obj)) types.push(type); - return this.registerTypes(types); - } - - /** - * Registers the default argument types to the registry. These are: - * - string - * - integer - * - float - * - boolean - * - user - * - member - * - role - * - channel - * - message - * @return {CommandRegistry} - */ - registerDefaultTypes() { - this.registerTypes([ - require('./types/string'), - require('./types/integer'), - require('./types/float'), - require('./types/boolean'), - require('./types/user'), - require('./types/member'), - require('./types/role'), - require('./types/channel'), - require('./types/message') - ]); - return this; - } - - /** - * Reregisters a command (does not support changing name, group, or memberName) - * @param {Command|Function} command - New command - * @param {Command} oldCommand - Old command - */ - reregisterCommand(command, oldCommand) { - if(typeof command === 'function') command = new command(this.client); // eslint-disable-line new-cap - if(command.name !== oldCommand.name) throw new Error('Command name cannot change.'); - if(command.groupID !== oldCommand.groupID) throw new Error('Command group cannot change.'); - if(command.memberName !== oldCommand.memberName) throw new Error('Command memberName cannot change.'); - command.group = this.resolveGroup(command.groupID); - command.group.commands.set(command.name, command); - this.commands.set(command.name, command); - /** - * Emitted when a command is reregistered - * @event CommandoClient#commandReregister - * @param {Command} newCommand - New command - * @param {Command} oldCommand - Old command - */ - this.client.emit('commandReregister', command, oldCommand); - this.client.emit('debug', `Reregistered command ${command.groupID}:${command.memberName}.`); - } - - /** - * Unregisters a command - * @param {Command} command - Command to unregister - */ - unregisterCommand(command) { - this.commands.delete(command.name); - command.group.commands.delete(command.name); - /** - * Emitted when a command is unregistered - * @event CommandoClient#commandUnregister - * @param {Command} command - Command that was unregistered - */ - this.client.emit('commandUnregister', command); - this.client.emit('debug', `Unregistered command ${command.groupID}:${command.memberName}.`); - } - - /** - * Registers a single object to be usable by the eval command - * @param {string} key - The key for the object - * @param {Object} obj - The object - * @return {CommandRegistry} - * @see {@link CommandRegistry#registerEvalObjects} - */ - registerEvalObject(key, obj) { - const registerObj = {}; - registerObj[key] = obj; - return this.registerEvalObjects(registerObj); - } - - /** - * Registers multiple objects to be usable by the eval command - * @param {Object} obj - An object of keys: values - * @return {CommandRegistry} - */ - registerEvalObjects(obj) { - Object.assign(this.evalObjects, obj); - return this; - } - - /** - * Finds all groups that match the search string - * @param {string} [searchString] - The string to search for - * @param {boolean} [exact=false] - Whether the search should be exact - * @return {CommandGroup[]} All groups that are found - */ - findGroups(searchString = null, exact = false) { - if(!searchString) return this.groups; - - // Find all matches - const lcSearch = searchString.toLowerCase(); - const matchedGroups = this.groups.filterArray( - exact ? groupFilterExact(lcSearch) : groupFilterInexact(lcSearch) - ); - if(exact) return matchedGroups; - - // See if there's an exact match - for(const group of matchedGroups) { - if(group.name.toLowerCase() === lcSearch || group.id === lcSearch) return [group]; - } - return matchedGroups; - } - - /** - * A CommandGroupResolvable can be: - * * A CommandGroup - * * A group ID - * @typedef {CommandGroup|string} CommandGroupResolvable - */ - - /** - * Resolves a CommandGroupResolvable to a CommandGroup object - * @param {CommandGroupResolvable} group - The group to resolve - * @return {CommandGroup} The resolved CommandGroup - */ - resolveGroup(group) { - if(group instanceof CommandGroup) return group; - if(typeof group === 'string') { - const groups = this.findGroups(group, true); - if(groups.length === 1) return groups[0]; - } - throw new Error('Unable to resolve group.'); - } - - /** - * Finds all commands that match the search string - * @param {string} [searchString] - The string to search for - * @param {boolean} [exact=false] - Whether the search should be exact - * @param {Message} [message] - The message to check usability against - * @return {Command[]} All commands that are found - */ - findCommands(searchString = null, exact = false, message = null) { - if(!searchString) return message ? this.commands.filterArray(cmd => cmd.isUsable(message)) : this.commands; - - // Find all matches - const lcSearch = searchString.toLowerCase(); - const matchedCommands = this.commands.filterArray( - exact ? commandFilterExact(lcSearch) : commandFilterInexact(lcSearch) - ); - if(exact) return matchedCommands; - - // See if there's an exact match - for(const command of matchedCommands) { - if(command.name === lcSearch || (command.aliases && command.aliases.some(ali => ali === lcSearch))) { - return [command]; - } - } - - return matchedCommands; - } - - /** - * A CommandResolvable can be: - * * A Command - * * A command name - * * A CommandMessage - * @typedef {Command|string} CommandResolvable - */ - - /** - * Resolves a CommandResolvable to a Command object - * @param {CommandResolvable} command - The command to resolve - * @return {Command} The resolved Command - */ - resolveCommand(command) { - if(command instanceof Command) return command; - if(command instanceof CommandMessage) return command.command; - if(typeof command === 'string') { - const commands = this.findCommands(command, true); - if(commands.length === 1) return commands[0]; - } - throw new Error('Unable to resolve command.'); - } - - /** - * Resolves a command file path from a command's group ID and memberName - * @param {string} group - ID of the command's group - * @param {string} memberName - Member name of the command - * @return {string} Fully-resolved path to the corresponding command file - */ - resolveCommandPath(group, memberName) { - return path.join(this.commandsPath, group, `${memberName}.js`); - } -} - -function groupFilterExact(search) { - return grp => grp.id === search || grp.name.toLowerCase() === search; -} - -function groupFilterInexact(search) { - return grp => grp.id.includes(search) || grp.name.toLowerCase().includes(search); -} - -function commandFilterExact(search) { - return cmd => cmd.name === search || - (cmd.aliases && cmd.aliases.some(ali => ali === search)) || - `${cmd.groupID}:${cmd.memberName}` === search; -} - -function commandFilterInexact(search) { - return cmd => cmd.name.includes(search) || - `${cmd.groupID}:${cmd.memberName}` === search || - (cmd.aliases && cmd.aliases.some(ali => ali.includes(search))); -} - -module.exports = CommandRegistry; diff --git a/Komugari-master/commando/types/base.js b/Komugari-master/commando/types/base.js deleted file mode 100644 index e424bf5..0000000 --- a/Komugari-master/commando/types/base.js +++ /dev/null @@ -1,54 +0,0 @@ -/** A type for command arguments */ -class ArgumentType { - /** - * @param {CommandoClient} client - The client the argument type is for - * @param {string} id - The argument type ID (this is what you specify in {@link ArgumentInfo#type}) - */ - constructor(client, id) { - if(!client) throw new Error('A client must be specified.'); - if(typeof id !== 'string') throw new Error('Argument type ID must be a string.'); - if(id !== id.toLowerCase()) throw new Error('Argument type ID must be lowercase.'); - - /** - * Client that this argument type is for - * @name ArgumentType#client - * @type {CommandoClient} - * @readonly - */ - Object.defineProperty(this, 'client', { value: client }); - - /** - * ID of this argument type (this is what you specify in {@link ArgumentInfo#type}) - * @type {string} - */ - this.id = id; - } - - // eslint-disable-next-line valid-jsdoc - /** - * Validates a value against the type - * @param {string} value - Value to validate - * @param {CommandMessage} msg - Message the value was obtained from - * @param {Argument} arg - Argument the value obtained from - * @return {boolean|string|Promise} Whether the value is valid, or an error message - * @abstract - */ - validate(value, msg, arg) { // eslint-disable-line no-unused-vars - throw new Error(`${this.constructor.name} doesn't have a validate() method.`); - } - - // eslint-disable-next-line valid-jsdoc - /** - * Parses the raw value into a usable value - * @param {string} value - Value to parse - * @param {CommandMessage} msg - Message the value was obtained from - * @param {Argument} arg - Argument the value obtained from - * @return {*|Promise<*>} Usable value - * @abstract - */ - parse(value, msg, arg) { // eslint-disable-line no-unused-vars - throw new Error(`${this.constructor.name} doesn't have a parse() method.`); - } -} - -module.exports = ArgumentType; diff --git a/Komugari-master/commando/types/boolean.js b/Komugari-master/commando/types/boolean.js deleted file mode 100644 index dbf74ab..0000000 --- a/Komugari-master/commando/types/boolean.js +++ /dev/null @@ -1,23 +0,0 @@ -const ArgumentType = require('./base'); - -class BooleanArgumentType extends ArgumentType { - constructor(client) { - super(client, 'boolean'); - this.truthy = new Set(['true', 't', 'yes', 'y', 'on', 'enable', 'enabled', '1', '+']); - this.falsy = new Set(['false', 'f', 'no', 'n', 'off', 'disable', 'disabled', '0', '-']); - } - - validate(value) { - const lc = value.toLowerCase(); - return this.truthy.has(lc) || this.falsy.has(lc); - } - - parse(value) { - const lc = value.toLowerCase(); - if(this.truthy.has(lc)) return true; - if(this.falsy.has(lc)) return false; - throw new RangeError('Unknown boolean value.'); - } -} - -module.exports = BooleanArgumentType; diff --git a/Komugari-master/commando/types/channel.js b/Komugari-master/commando/types/channel.js deleted file mode 100644 index 77d8356..0000000 --- a/Komugari-master/commando/types/channel.js +++ /dev/null @@ -1,47 +0,0 @@ -const ArgumentType = require('./base'); -const { disambiguation } = require('../util'); -const { escapeMarkdown } = require('discord.js'); - -class ChannelArgumentType extends ArgumentType { - constructor(client) { - super(client, 'channel'); - } - - validate(value, msg) { - const matches = value.match(/^(?:<#)?([0-9]+)>?$/); - if(matches) return msg.guild.channels.has(matches[1]); - const search = value.toLowerCase(); - let channels = msg.guild.channels.filterArray(nameFilterInexact(search)); - if(channels.length === 0) return false; - if(channels.length === 1) return true; - const exactChannels = channels.filter(nameFilterExact(search)); - if(exactChannels.length === 1) return true; - if(exactChannels.length > 0) channels = exactChannels; - return channels.length <= 15 ? - `${disambiguation(channels.map(chan => escapeMarkdown(chan.name)), 'channels', null - )}\n` : - 'Multiple channels found, please be more specific!'; - } - - parse(value, msg) { - const matches = value.match(/^(?:<#)?([0-9]+)>?$/); - if(matches) return msg.guild.channels.get(matches[1]) || null; - const search = value.toLowerCase(); - const channels = msg.guild.channels.filterArray(nameFilterInexact(search)); - if(channels.length === 0) return null; - if(channels.length === 1) return channels[0]; - const exactChannels = channels.filter(nameFilterExact(search)); - if(exactChannels.length === 1) return exactChannels[0]; - return null; - } -} - -function nameFilterExact(search) { - return thing => thing.name.toLowerCase() === search; -} - -function nameFilterInexact(search) { - return thing => thing.name.toLowerCase().includes(search); -} - -module.exports = ChannelArgumentType; diff --git a/Komugari-master/commando/types/float.js b/Komugari-master/commando/types/float.js deleted file mode 100644 index 66ebaa1..0000000 --- a/Komugari-master/commando/types/float.js +++ /dev/null @@ -1,20 +0,0 @@ -const ArgumentType = require('./base'); - -class FloatArgumentType extends ArgumentType { - constructor(client) { - super(client, 'float'); - } - - validate(value, msg, arg) { - const float = Number.parseFloat(value); - return !Number.isNaN(float) && - (arg.min === null || typeof arg.min === 'undefined' || float >= arg.min) && - (arg.max === null || typeof arg.max === 'undefined' || float <= arg.max); - } - - parse(value) { - return Number.parseFloat(value); - } -} - -module.exports = FloatArgumentType; diff --git a/Komugari-master/commando/types/integer.js b/Komugari-master/commando/types/integer.js deleted file mode 100644 index a8f444a..0000000 --- a/Komugari-master/commando/types/integer.js +++ /dev/null @@ -1,20 +0,0 @@ -const ArgumentType = require('./base'); - -class IntegerArgumentType extends ArgumentType { - constructor(client) { - super(client, 'integer'); - } - - validate(value, msg, arg) { - const int = Number.parseInt(value); - return !Number.isNaN(int) && - (arg.min === null || typeof arg.min === 'undefined' || int >= arg.min) && - (arg.max === null || typeof arg.max === 'undefined' || int <= arg.max); - } - - parse(value) { - return Number.parseInt(value); - } -} - -module.exports = IntegerArgumentType; diff --git a/Komugari-master/commando/types/member.js b/Komugari-master/commando/types/member.js deleted file mode 100644 index 4afed1c..0000000 --- a/Komugari-master/commando/types/member.js +++ /dev/null @@ -1,58 +0,0 @@ -const ArgumentType = require('./base'); -const disambiguation = require('../util').disambiguation; -const escapeMarkdown = require('discord.js').escapeMarkdown; - -class MemberArgumentType extends ArgumentType { - constructor(client) { - super(client, 'member'); - } - - async validate(value, msg) { - const matches = value.match(/^(?:<@!?)?([0-9]+)>?$/); - if(matches) { - try { - return await msg.guild.members.fetch(await msg.client.users.fetch(matches[1])); - } catch(err) { - return false; - } - } - const search = value.toLowerCase(); - let members = msg.guild.members.filterArray(memberFilterInexact(search)); - if(members.length === 0) return false; - if(members.length === 1) return members[0]; - const exactMembers = members.filter(memberFilterExact(search)); - if(exactMembers.length === 1) return exactMembers[0]; - if(exactMembers.length > 0) members = exactMembers; - return members.length <= 15 ? - `${disambiguation( - members.map(mem => `${escapeMarkdown(mem.user.username)}#${mem.user.discriminator}`), 'users', null - )}\n` : - 'Multiple members found, please be more specific!'; - } - - parse(value, msg) { - const matches = value.match(/^(?:<@!?)?([0-9]+)>?$/); - if(matches) return msg.guild.member(matches[1]) || null; - const search = value.toLowerCase(); - const members = msg.guild.members.filterArray(memberFilterInexact(search)); - if(members.length === 0) return null; - if(members.length === 1) return members[0]; - const exactMembers = members.filter(memberFilterExact(search)); - if(exactMembers.length === 1) return exactMembers[0]; - return null; - } -} - -function memberFilterExact(search) { - return mem => mem.user.username.toLowerCase() === search || - (mem.nickname && mem.nickname.toLowerCase() === search) || - `${mem.user.username.toLowerCase()}#${mem.user.discriminator}` === search; -} - -function memberFilterInexact(search) { - return mem => mem.user.username.toLowerCase().includes(search) || - (mem.nickname && mem.nickname.toLowerCase().includes(search)) || - `${mem.user.username.toLowerCase()}#${mem.user.discriminator}`.includes(search); -} - -module.exports = MemberArgumentType; diff --git a/Komugari-master/commando/types/message.js b/Komugari-master/commando/types/message.js deleted file mode 100644 index 860ecb8..0000000 --- a/Komugari-master/commando/types/message.js +++ /dev/null @@ -1,18 +0,0 @@ -const ArgumentType = require('./base'); - -class MessageArgumentType extends ArgumentType { - constructor(client) { - super(client, 'message'); - } - - async validate(value, msg) { - if(!/^[0-9]+$/.test(value)) return false; - return Boolean(await msg.channel.messages.fetch(value).catch(() => null)); - } - - parse(value, msg) { - return msg.channel.messages.get(value); - } -} - -module.exports = MessageArgumentType; diff --git a/Komugari-master/commando/types/role.js b/Komugari-master/commando/types/role.js deleted file mode 100644 index cc9d26c..0000000 --- a/Komugari-master/commando/types/role.js +++ /dev/null @@ -1,47 +0,0 @@ -const ArgumentType = require('./base'); -const { disambiguation } = require('../util'); -const { escapeMarkdown } = require('discord.js'); - -class RoleArgumentType extends ArgumentType { - constructor(client) { - super(client, 'role'); - } - - validate(value, msg) { - const matches = value.match(/^(?:<@&)?([0-9]+)>?$/); - if(matches) return msg.guild.roles.has(matches[1]); - const search = value.toLowerCase(); - let roles = msg.guild.roles.filterArray(nameFilterInexact(search)); - if(roles.length === 0) return false; - if(roles.length === 1) return true; - const exactRoles = roles.filter(nameFilterExact(search)); - if(exactRoles.length === 1) return true; - if(exactRoles.length > 0) roles = exactRoles; - return roles.length <= 15 ? - `${disambiguation(roles.map(role => `${escapeMarkdown(role.name)}`), 'roles', null - )}\n` : - 'Multiple roles found, please be more specific!'; - } - - parse(value, msg) { - const matches = value.match(/^(?:<@&)?([0-9]+)>?$/); - if(matches) return msg.guild.roles.get(matches[1]) || null; - const search = value.toLowerCase(); - const roles = msg.guild.roles.filterArray(nameFilterInexact(search)); - if(roles.length === 0) return null; - if(roles.length === 1) return roles[0]; - const exactRoles = roles.filter(nameFilterExact(search)); - if(exactRoles.length === 1) return exactRoles[0]; - return null; - } -} - -function nameFilterExact(search) { - return thing => thing.name.toLowerCase() === search; -} - -function nameFilterInexact(search) { - return thing => thing.name.toLowerCase().includes(search); -} - -module.exports = RoleArgumentType; \ No newline at end of file diff --git a/Komugari-master/commando/types/string.js b/Komugari-master/commando/types/string.js deleted file mode 100644 index 6d84ad7..0000000 --- a/Komugari-master/commando/types/string.js +++ /dev/null @@ -1,19 +0,0 @@ -const ArgumentType = require('./base'); - -class StringArgumentType extends ArgumentType { - constructor(client) { - super(client, 'string'); - } - - validate(value, msg, arg) { - return Boolean(value) && - (arg.min === null || typeof arg.min === 'undefined' || value.length >= arg.min) && - (arg.max === null || typeof arg.max === 'undefined' || value.length <= arg.max); - } - - parse(value) { - return value; - } -} - -module.exports = StringArgumentType; diff --git a/Komugari-master/commando/types/user.js b/Komugari-master/commando/types/user.js deleted file mode 100644 index 9cd13ab..0000000 --- a/Komugari-master/commando/types/user.js +++ /dev/null @@ -1,60 +0,0 @@ -const ArgumentType = require('./base'); -const disambiguation = require('../util').disambiguation; -const escapeMarkdown = require('discord.js').escapeMarkdown; - -class UserArgumentType extends ArgumentType { - constructor(client) { - super(client, 'user'); - } - - async validate(value, msg) { - const matches = value.match(/^(?:<@!?)?([0-9]+)>?$/); - if(matches) { - try { - return await msg.client.users.fetch(matches[1]); - } catch(err) { - return false; - } - } - if(!msg.guild) return false; - const search = value.toLowerCase(); - let members = msg.guild.members.filterArray(memberFilterInexact(search)); - if(members.length === 0) return false; - if(members.length === 1) return true; - const exactMembers = members.filter(memberFilterExact(search)); - if(exactMembers.length === 1) return true; - if(exactMembers.length > 0) members = exactMembers; - return members.length <= 15 ? - `${disambiguation( - members.map(mem => `${escapeMarkdown(mem.user.username)}#${mem.user.discriminator}`), 'users', null - )}\n` : - 'Multiple users found, please be more specific!'; - } - - parse(value, msg) { - const matches = value.match(/^(?:<@!?)?([0-9]+)>?$/); - if(matches) return msg.client.users.get(matches[1]) || null; - if(!msg.guild) return null; - const search = value.toLowerCase(); - const members = msg.guild.members.filterArray(memberFilterInexact(search)); - if(members.length === 0) return null; - if(members.length === 1) return members[0].user; - const exactMembers = members.filter(memberFilterExact(search)); - if(exactMembers.length === 1) return exactMembers[0].user; - return null; - } -} - -function memberFilterExact(search) { - return mem => mem.user.username.toLowerCase() === search || - (mem.nickname && mem.nickname.toLowerCase() === search) || - `${mem.user.username.toLowerCase()}#${mem.user.discriminator}` === search; -} - -function memberFilterInexact(search) { - return mem => mem.user.username.toLowerCase().includes(search) || - (mem.nickname && mem.nickname.toLowerCase().includes(search)) || - `${mem.user.username.toLowerCase()}#${mem.user.discriminator}`.includes(search); -} - -module.exports = UserArgumentType; diff --git a/Komugari-master/commando/util.js b/Komugari-master/commando/util.js deleted file mode 100644 index 7d85ba2..0000000 --- a/Komugari-master/commando/util.js +++ /dev/null @@ -1,138 +0,0 @@ -function disambiguation(items, label, property = 'name') { - const itemList = items.map(item => `"${(property ? item[property] : item).replace(/ /g, '\xa0')}"`).join(', '); - return `Multiple ${label} found, please be more specific!`; -} - -function paginate(items, page = 1, pageLength = 10) { - const maxPage = Math.ceil(items.length / pageLength); - if (page < 1) page = 1; - if (page > maxPage) page = maxPage; - let startIndex = (page - 1) * pageLength; - return { - items: items.length > pageLength ? items.slice(startIndex, startIndex + pageLength) : items, - page, - maxPage, - pageLength - }; -} - -const permissions = { - ADMINISTRATOR: 'Administrator', - VIEW_AUDIT_LOG: 'View audit log', - MANAGE_GUILD: 'Manage server', - MANAGE_ROLES: 'Manage roles', - MANAGE_CHANNELS: 'Manage channels', - KICK_MEMBERS: 'Kick members', - BAN_MEMBERS: 'Ban members', - CREATE_INSTANT_INVITE: 'Create instant invite', - CHANGE_NICKNAME: 'Change nickname', - MANAGE_NICKNAMES: 'Manage nicknames', - MANAGE_EMOJIS: 'Manage emojis', - MANAGE_WEBHOOKS: 'Manage webhooks', - VIEW_CHANNEL: 'Read text channels and see voice channels', - SEND_MESSAGES: 'Send messages', - SEND_TTS_MESSAGES: 'Send TTS messages', - MANAGE_MESSAGES: 'Manage messages', - EMBED_LINKS: 'Embed links', - ATTACH_FILES: 'Attach files', - READ_MESSAGE_HISTORY: 'Read message history', - MENTION_EVERYONE: 'Mention everyone', - USE_EXTERNAL_EMOJIS: 'Use external emojis', - ADD_REACTIONS: 'Add reactions', - CONNECT: 'Connect', - SPEAK: 'Speak', - MUTE_MEMBERS: 'Mute members', - DEAFEN_MEMBERS: 'Deafen members', - MOVE_MEMBERS: 'Move members', - USE_VAD: 'Use voice activity' -}; - - -function fromNow(date) { - if (!date) { - return false; - } - - const ms = new Date().getTime() - date.getTime(); - - if (ms >= 86400000) { - const days = Math.floor(ms / 86400000); - return `${days} day${days !== 1 ? 's' : ''} ago`; - } - - return `${humanizeDuration(ms, 1, false, false)} ago`; -} - -function humanizeDuration(ms, maxUnits, short = false, fraction = true) { - const round = ms > 0 ? Math.floor : Math.ceil - const parsed = [{ - int: round(ms / 604800000), - sin: 'week', - plu: 'weeks', - sho: 'w' - }, - { - int: round(ms / 86400000) % 7, - sin: 'day', - plu: 'days', - sho: 'd' - }, - { - int: round(ms / 3600000) % 24, - sin: 'hour', - plu: 'hours', - sho: 'h' - }, - { - int: round(ms / 60000) % 60, - sin: 'minute', - plu: 'minutes', - sho: 'm' - }, - { - int: (round(ms / 1000) % 60) + (round(ms) % 1000 / 1000), - sin: 'second', - plu: 'seconds', - sho: 's' - } - ] - - const result = [] - for (let i = 0; i < parsed.length; i++) { - if (!result.length && parsed[i].int === 0) { - continue - } - - if (result.length >= maxUnits) { - break - } - - let int = parsed[i].int - if (!result.length && fraction && i === parsed.length - 1) { - int = int.toFixed(1) - } else { - int = int.toFixed(0) - } - - result.push(`${int}${short ? parsed[i].sho : ' ' + (parseFloat(int) !== 1 ? parsed[i].plu : parsed[i].sin)}`) - } - - return result.map((res, i) => { - if (!short) { - if (i === result.length - 2) { - return res + ' and' - } else if (i !== result.length - 1) { - return res + ',' - } - } - return res - }).join(' ') -} - -module.exports = { - disambiguation, - paginate, - permissions, - fromNow, - humanizeDuration -}; \ No newline at end of file diff --git a/Komugari-master/commands/fun/8ball.js b/Komugari-master/commands/fun/8ball.js deleted file mode 100644 index 43066a2..0000000 --- a/Komugari-master/commands/fun/8ball.js +++ /dev/null @@ -1,58 +0,0 @@ -const { Command } = require('../../commando'); -const Discord = require('discord.js'); -const answer = [ - "It is certain", - "It is decidedly so", - "Without a doubt", - "Yes, definitely", - "You may rely on it", - "As I see it, yes", - "Most likely", - "Yes", - "Signs point to yes", - "The reply is hazy, try again", - "Ask again later", - "I'd better not tell you now", - "I cannot predict now", - "Concentrate and ask again", - "Don't count on it", - "My sources say no", - "The outlook isn't so good", - "Very doubtful", - "B-Baka! No!", - "Yes daddy..." -] - - -module.exports = class EightBallCommand extends Command { - constructor(client) { - super(client, { - name: '8ball', - aliases: ['8b', 'ball'], - group: 'fun', - memberName: '8ball', - guildOnly: true, - description: 'Ask the magic 8ball a question!', - examples: ['~8ball [question]'], - throttling: { - usages: 1, - duration: 3 - } - }); - } - - run(message) { - let question = message.content.split(/\s+/g).slice(1).join(" "); - - if (!question) { - return message.channel.send('You must provide a question!'); - } - - const embed = new Discord.MessageEmbed() - .setAuthor(question, 'https://a.safe.moe/aKDHV.png') - .setDescription(answer[Math.round(Math.random() * (answer.length - 1))] + '.') - .setColor('#646770'); - return message.channel.send({ embed }); - - } -} \ No newline at end of file diff --git a/Komugari-master/commands/fun/_talk.js b/Komugari-master/commands/fun/_talk.js deleted file mode 100644 index 3f2b082..0000000 --- a/Komugari-master/commands/fun/_talk.js +++ /dev/null @@ -1,37 +0,0 @@ -/*const { Command } = require('../../commando'); -const cleverbot = require("cleverbot-node"); - -module.exports = class TalkCommand extends Command { - constructor(client) { - super(client, { - name: 'talk', - aliases: ['chat', 'cleverbot', '!', 'komugari'], - group: 'fun', - memberName: 'talk', - description: 'Talk to Komugari using the Cleverbot API!', - examples: ['~talk [sentence]'], - guildOnly: true, - throttling: { - usages: 1, - duration: 3 - } - }); - } - - run(message) { - const clbot = new cleverbot; - clbot.configure({ botapi: "CC30y25bSJBl1pLmgwxRZHmMUjA" }); - cleverbot.prepare(function() {}); - - let clMessage = message.content.split(/\s+/g).slice(1).join(" "); - if (!clMessage) return message.channel.send('Try saying something to me after `~talk`!\n\e.g. ~talk hello!') - clbot.write(clMessage, (response) => { - message.channel.startTyping(); - setTimeout(() => { - message.channel.send(response.output).catch(console.error); - message.channel.stopTyping(); - }, Math.floor(Math.random() * 1000) + 1); - }); - } -} -*/ \ No newline at end of file diff --git a/Komugari-master/commands/fun/b.js b/Komugari-master/commands/fun/b.js deleted file mode 100644 index 3299d9a..0000000 --- a/Komugari-master/commands/fun/b.js +++ /dev/null @@ -1,40 +0,0 @@ -const { Command } = require('../../commando'); - -module.exports = class BCommand extends Command { - constructor(client) { - super(client, { - name: 'b', - guildOnly: true, - aliases: ['bmoji'], - group: 'fun', - memberName: 'b', - description: 'Converts your text to 🅱 text!', - examples: ['~b [text]'], - throttling: { - usages: 1, - duration: 3 - }, - args: [{ - key: "text", - prompt: "What text do you want to do B on?\n", - type: "string", - default: 'traps are not gay', - parse: text => text.toLowerCase(), - validate: value => { - if (this.B(value.toLowerCase()).length < 2000) return true; - return `The output is over 2000 characters! Please try again!` - } - }], - }); - } - - B(text) { - return text.replace(new RegExp(/(b|d|g|p|q|t|h)/gi), "🅱"); - } - - run (message, args) { - var { text } = args; - - return message.channel.send(this.B(text)); - } -} \ No newline at end of file diff --git a/Komugari-master/commands/fun/bird.js b/Komugari-master/commands/fun/bird.js deleted file mode 100644 index 8ad2625..0000000 --- a/Komugari-master/commands/fun/bird.js +++ /dev/null @@ -1,32 +0,0 @@ -const { Command } = require('../../commando'); -const Discord = require('discord.js'); -const snekfetch = require('snekfetch'); - -module.exports = class BirdCommand extends Command { - constructor(client) { - super(client, { - name: 'bird', - aliases: ['birb', 'burb', 'birbo'], - group: 'fun', - memberName: 'bird', - guildOnly: true, - description: 'Sends a random picture of a bird!', - examples: ['~bird'], - throttling: { - usages: 1, - duration: 5 - } - }); - } - - async run(message) { - const res = await snekfetch.get('http://random.birb.pw/tweet/'); - const image = res.body - - const embed = new Discord.MessageEmbed() - .setImage(`http://random.birb.pw/img/${image}`) - .setFooter('http://random.birb.pw/ ©', 'http://random.birb.pw/img/BPVpe.jpg') - .setColor('#71A3BE'); - return message.channel.send({ embed }); - } -} \ No newline at end of file diff --git a/Komugari-master/commands/fun/cat.js b/Komugari-master/commands/fun/cat.js deleted file mode 100644 index 35343c3..0000000 --- a/Komugari-master/commands/fun/cat.js +++ /dev/null @@ -1,31 +0,0 @@ -const { Command } = require('../../commando'); -const Discord = require('discord.js'); -const snekfetch = require('snekfetch'); -const { formatXml } = require('../../commando/util') - -module.exports = class CatCommand extends Command { - constructor(client) { - super(client, { - name: 'cat', - aliases: ['kitty', 'meow', 'cate'], - group: 'fun', - memberName: 'cat', - guildOnly: true, - description: 'Sends a random picture of a cat!', - examples: ['~cat'], - throttling: { - usages: 1, - duration: 5 - } - }); - } - - async run(message) { - var catID = ('000' + (Math.floor(Math.random() * 773) + 1)).substr(-3); - - const embed = new Discord.MessageEmbed() - .setImage(`https://nadeko-pictures.nyc3.digitaloceanspaces.com/cats/${catID}.png`) - .setColor('#71A3BE'); - return message.channel.send({ embed }); - } -} \ No newline at end of file diff --git a/Komugari-master/commands/fun/dog.js b/Komugari-master/commands/fun/dog.js deleted file mode 100644 index 6b36ebe..0000000 --- a/Komugari-master/commands/fun/dog.js +++ /dev/null @@ -1,35 +0,0 @@ -const { Command } = require('../../commando'); -const Discord = require('discord.js'); -const snekfetch = require('snekfetch'); - -module.exports = class DogCommand extends Command { - constructor(client) { - super(client, { - name: 'dog', - aliases: ['puppy', 'doggo', 'pupper'], - group: 'fun', - memberName: 'dog', - guildOnly: true, - description: 'Sends a random picture of a dog!', - examples: ['~dog'], - throttling: { - usages: 1, - duration: 5 - } - }); - } - - async run(message) { - const res = await snekfetch.get('https://random.dog/woof.json'); - const image = res.body.url; - - console.log(image) - - const embed = new Discord.MessageEmbed() - .setImage(image) - .setDescription(`[Image URL](${image})`) - .setFooter('http://www.random.dog ©', 'https://random.dog/3f62f2c1-e0cb-4077-8cd9-1ca76bfe98d5.jpg') - .setColor('#71A3BE'); - return message.channel.send({ embed }); - } -} \ No newline at end of file diff --git a/Komugari-master/commands/fun/f.js b/Komugari-master/commands/fun/f.js deleted file mode 100644 index e745b6c..0000000 --- a/Komugari-master/commands/fun/f.js +++ /dev/null @@ -1,49 +0,0 @@ -const { Command } = require('../../commando'); -const Discord = require('discord.js'); - -module.exports = class FCommand extends Command { - constructor(client) { - super(client, { - name: 'f', - aliases: ['respect', 'respects', 'rip'], - group: 'fun', - memberName: 'f', - guildOnly: true, - description: 'Press F to pay respects', - examples: ['~f '], - throttling: { - usages: 1, - duration: 5 - }, - args: [{ - key: 'respect', - prompt: 'Please provide me something to respect!', - type: 'string', - default: 'none' - }] - }); - } - - run(message, args) { - const { respect } = args; - if (respect == 'none') { - const embed = new Discord.MessageEmbed() - .setAuthor(`${message.author.username} has paid their respects.`, message.author.displayAvatarURL({ format: 'png' })) - .setColor('#4E373B') - .setFooter(`Press F to pay your respects.`); - message.channel.send({ embed }).then(m => m.react("🇫")); - - return null; - - } else { - const embed = new Discord.MessageEmbed() - .setAuthor(`\u2000`, message.author.displayAvatarURL({ format: 'png' })) - .setColor('#4E373B') - .setDescription(`${message.author} has paid their respects to ${respect}`) - .setFooter(`Press F to pay your respects.`); - message.channel.send({ embed }).then(m => m.react("🇫")); - - return null; - } - } -} \ No newline at end of file diff --git a/Komugari-master/commands/fun/horoscope.js b/Komugari-master/commands/fun/horoscope.js deleted file mode 100644 index 7884e85..0000000 --- a/Komugari-master/commands/fun/horoscope.js +++ /dev/null @@ -1,59 +0,0 @@ -const { Command } = require('../../commando'); -const Discord = require('discord.js'); -const snekfetch = require('snekfetch'); -const signs = [ - "capricorn", - "aquarius", - "pisces", - "aries", - "taurus", - "gemini", - "cancer", - "leo", - "virgo", - "libra", - "scorpio", - "sagittarius" -] - -module.exports = class HoroscopeCommand extends Command { - constructor(client) { - super(client, { - name: 'horoscope', - group: 'fun', - memberName: 'horoscope', - guildOnly: true, - description: 'Gets your daily horoscope!', - examples: ['~horoscope [sign]'], - aliases: ["horo", "sign"], - throttling: { - usages: 1, - duration: 8 - } - }); - } - - async run(message, args) { - const sign = message.content.split(/\s+/g).slice(1).join(" "); - if (!sign) return message.channel.send("Please give me a sign to get the horoscope of!"); - - if (!signs.includes(sign.toLowerCase())) return message.channel.send('That is not a valid sign!'); - - const text = await snekfetch - .get(`http://sandipbgt.com/theastrologer/api/horoscope/${sign}/today`); - const body = JSON.parse(text.body); - - var horoscope = body.horoscope - var replaced = horoscope.replace('(c) Kelli Fox, The Astrologer, http://new.theastrologer.com', '') - - const embed = new Discord.MessageEmbed() - .setColor('#5D7B9D') - .setAuthor(`Horoscope for ${body.sunsign} on ${body.date}`, 'http://images.indianexpress.com/2017/01/zodiac-love-2017-main_820_thinkstockphotos-481896132.jpg?w=820') - .setDescription(replaced) - .setTimestamp() - .setFooter(`${message.author.username}'s Horoscope`) - .addField('Mood', body.meta.mood, true) - .addField("Intensity", body.meta.intensity, true); - return message.channel.send({ embed }); - } -} \ No newline at end of file diff --git a/Komugari-master/commands/fun/lizard.js b/Komugari-master/commands/fun/lizard.js deleted file mode 100644 index bfaa183..0000000 --- a/Komugari-master/commands/fun/lizard.js +++ /dev/null @@ -1,33 +0,0 @@ -const { Command } = require('../../commando'); -const Discord = require('discord.js'); -const snekfetch = require('snekfetch'); - -module.exports = class LizardCommand extends Command { - constructor(client) { - super(client, { - name: 'lizard', - aliases: ['liz'], - group: 'fun', - memberName: 'lizard', - guildOnly: true, - description: 'Sends a random picture of a lizard!', - examples: ['~lizard'], - throttling: { - usages: 1, - duration: 5 - } - }); - } - - async run(message) { - const res = await snekfetch.get('https://nekos.life/api/lizard'); - const image = res.body.url - - const embed = new Discord.MessageEmbed() - .setImage(image) - .setDescription(`[Image URL](${image})`) - .setFooter('https://nekos.life/ ©', 'https://nekos.life/static/lizard/010C.jpg') - .setColor('#71A3BE'); - return message.channel.send({ embed }); - } -} \ No newline at end of file diff --git a/Komugari-master/commands/fun/meme.js b/Komugari-master/commands/fun/meme.js deleted file mode 100644 index 3f1ff76..0000000 --- a/Komugari-master/commands/fun/meme.js +++ /dev/null @@ -1,45 +0,0 @@ -const { Command } = require('../../commando'); -const Discord = require('discord.js'); -const randomPuppy = require('random-puppy'); -const subreddits = [ - "memes", - "DeepFriedMemes", - "bonehurtingjuice", - "surrealmemes", - "dankmemes", - "meirl", - "me_irl", - "funny" -] - -module.exports = class MemeCommand extends Command { - constructor(client) { - super(client, { - name: 'meme', - group: 'fun', - memberName: 'meme', - guildOnly: true, - description: 'Sends a random meme from selected subreddits!', - examples: ['~meme'], - details: "There is no NSFW filter on this! \n\If there is an NSFW meme, please remove it by reacting with a '🎴' emoji!", - throttling: { - usages: 2, - duration: 10 - } - }); - } - - run(message) { - var randSubreddit = subreddits[Math.round(Math.random() * (subreddits.length - 1))]; - - randomPuppy(randSubreddit) - .then(url => { - const embed = new Discord.MessageEmbed() - .setFooter(`${randSubreddit}`) - .setDescription(`[Image URL](${url})`) - .setImage(url) - .setColor('#887064'); - return message.channel.send({ embed }); - }) - } -} \ No newline at end of file diff --git a/Komugari-master/commands/fun/mock.js b/Komugari-master/commands/fun/mock.js deleted file mode 100644 index 3e0de12..0000000 --- a/Komugari-master/commands/fun/mock.js +++ /dev/null @@ -1,67 +0,0 @@ -const { Command } = require('../../commando'); - -const mock = [ - "I love Emilia!", - "Astolfo is best girl!", - "Traps are not gay!", -] - -//remember to return before every promise -module.exports = class MockCommand extends Command { - constructor(client) { - super(client, { - name: 'mock', - guildOnly: true, - aliases: ['sayas', 'webhook'], - group: 'fun', - memberName: 'mock', - clientPermissions: ['MANAGE_WEBHOOKS'], - description: 'Mocks the provided user with your text!', - details: 'This command works through webhooks!', - examples: ['~mock [user] [text]'], - throttling: { - usages: 1, - duration: 45 - }, - args: [{ - key: 'member', - prompt: 'Please provide a user for me to mock!', - type: 'member' - }, - { - key: 'text', - prompt: 'Please provide me some text for this user to say!', - type: 'string', - default: 'none' - } - ] - }); - } - - async run(message, args) { - var { member, text } = args; - let name; - - if (!member.nickname) { - name = member.user.username; - } else { - name = member.nickname; - } - - if (text == 'none') { - text = mock[Math.round(Math.random() * (mock.length - 1))] - } - - var hook = await message.channel.createWebhook(name, { - avatar: member.user.displayAvatarURL({ format: 'png', size: 128 }), - reason: `${message.author.tag} is mocking ${member.user.tag}` - }) - - await hook.send(text) - - setTimeout(async function() { - await hook.delete() - }, 1000); - - } -} \ No newline at end of file diff --git a/Komugari-master/commands/fun/rate.js b/Komugari-master/commands/fun/rate.js deleted file mode 100644 index 3fb9044..0000000 --- a/Komugari-master/commands/fun/rate.js +++ /dev/null @@ -1,25 +0,0 @@ -const { Command } = require('../../commando'); - -module.exports = class RateCommand extends Command { - constructor(client) { - super(client, { - name: 'rate', - aliases: ['ratewaifu'], - group: 'fun', - memberName: 'rate', - guildOnly: true, - description: 'Gives the item you specify a rating out of 10!', - examples: ['~rate [item to be rated]'], - }); - } - - run(message) { - let item = message.content.split(/\s+/g).slice(1).join(" "); - if (!item) return message.channel.send('Please specify something for me to rate!'); - - if (item.toUpperCase().startsWith("KOMUGARI")) return message.channel.send('I\'d give myself a 10/10!'); - - const rating = Math.floor(Math.random() * 10) + 0; - return message.channel.send(`I'd give **${item}** a ${rating}/10!`); - } -} \ No newline at end of file diff --git a/Komugari-master/commands/fun/react.js b/Komugari-master/commands/fun/react.js deleted file mode 100644 index 7e505c4..0000000 --- a/Komugari-master/commands/fun/react.js +++ /dev/null @@ -1,92 +0,0 @@ -const { Command } = require('../../commando'); - - -module.exports = class ReactCommand extends Command { - constructor(client) { - super(client, { - name: 'react', - guildOnly: true, - aliases: ['reactions', 'reaction'], - group: 'fun', - memberName: 'react', - wait: 0.1, - description: 'Reacts on the given message ID!', - examples: ['~react [message ID] [text]'], - throttling: { - usages: 1, - duration: 3 - }, - args: [{ - key: 'message', - prompt: 'Please provide me a message to react on!', - type: 'message' - }, - { - key: 'text', - prompt: 'Please provide me some text to render!', - type: 'string' - }, - ] - }); - } - - async run(message, args) { - const { text } = args; - const m = args.message; - - const msg = await message.channel.send(`🔄 | Reacting to **${m.author.username}**'s message...`) - - for (const c of text.toLowerCase()) { - if (c in map) { - try { - await m.react(map[c]) - } catch (err) {} - } - } - - return msg.edit(`✅ | Successfully reacted on **${m.author.username}**'s message with ${text}!`) - } -} - -const map = { - a: '🇦', - b: '🇧', - c: '🇨', - d: '🇩', - e: '🇪', - f: '🇫', - g: '🇬', - h: '🇭', - i: '🇮', - j: '🇯', - k: '🇰', - l: '🇱', - m: '🇲', - n: '🇳', - o: '🇴', - p: '🇵', - q: '🇶', - r: '🇷', - s: '🇸', - t: '🇹', - u: '🇺', - v: '🇻', - w: '🇼', - x: '🇽', - y: '🇾', - z: '🇿', - 0: '0⃣', - 1: '1⃣', - 2: '2⃣', - 3: '3⃣', - 4: '4⃣', - 5: '5⃣', - 6: '6⃣', - 7: '7⃣', - 8: '8⃣', - 9: '9⃣', - '#': '#⃣', - '*': '*⃣', - '!': '❗', - '?': '❓', -} \ No newline at end of file diff --git a/Komugari-master/commands/fun/regionals.js b/Komugari-master/commands/fun/regionals.js deleted file mode 100644 index 23ceccd..0000000 --- a/Komugari-master/commands/fun/regionals.js +++ /dev/null @@ -1,82 +0,0 @@ -const { Command } = require('../../commando'); - - -module.exports = class RegionalsCommand extends Command { - constructor(client) { - super(client, { - name: 'regionals', - guildOnly: true, - aliases: ['letters', 'bigtext', 'big', 'textmoji', 'bigmoji'], - group: 'fun', - memberName: 'regionals', - description: 'Converts your given text into regional indicators!', - examples: ['~regionals [text]'], - throttling: { - usages: 1, - duration: 3 - }, - args: [{ - key: 'text', - prompt: 'Please provide me some text to render!', - type: 'string', - default: 'traps are not gay!', - parse: text => text.toLowerCase() - }] - }); - } - - async run(message, args) { - var output = '' - for (let c of args.text) { - if (c in map) { - c = map[c] + '\u200b' - } - output += c - } - - return message.channel.send('\u200b' + output) - } -} - -const map = { - a: '🇦', - b: '🇧', - c: '🇨', - d: '🇩', - e: '🇪', - f: '🇫', - g: '🇬', - h: '🇭', - i: '🇮', - j: '🇯', - k: '🇰', - l: '🇱', - m: '🇲', - n: '🇳', - o: '🇴', - p: '🇵', - q: '🇶', - r: '🇷', - s: '🇸', - t: '🇹', - u: '🇺', - v: '🇻', - w: '🇼', - x: '🇽', - y: '🇾', - z: '🇿', - 0: '0⃣', - 1: '1⃣', - 2: '2⃣', - 3: '3⃣', - 4: '4⃣', - 5: '5⃣', - 6: '6⃣', - 7: '7⃣', - 8: '8⃣', - 9: '9⃣', - '#': '#⃣', - '*': '*⃣', - '!': '❗', - '?': '❓', -} \ No newline at end of file diff --git a/Komugari-master/commands/fun/say.js b/Komugari-master/commands/fun/say.js deleted file mode 100644 index e92c1d6..0000000 --- a/Komugari-master/commands/fun/say.js +++ /dev/null @@ -1,32 +0,0 @@ -const { Command } = require('../../commando'); - -module.exports = class SayCommand extends Command { - constructor(client) { - super(client, { - name: 'say', - aliases: ['copycat', 'repeat', 'echo', 'parrot'], - group: 'fun', - memberName: 'say', - guildOnly: true, - description: 'Makes me say something for you.', - examples: ['~say [sentence]'], - throttling: { - usages: 1, - duration: 5 - }, - args: [{ - key: 'sayMessage', - prompt: 'Please provide me a message to say!', - type: 'string', - default: 'N////A' - }] - }); - } - - run(message, args) { - const { sayMessage } = args; - if (sayMessage = 'N////A') return message.say('Please specify something for me to say!'); - - return message.say(sayMessage).catch(console.error); - } -} \ No newline at end of file diff --git a/Komugari-master/commands/fun/sayd.js b/Komugari-master/commands/fun/sayd.js deleted file mode 100644 index 61f5c28..0000000 --- a/Komugari-master/commands/fun/sayd.js +++ /dev/null @@ -1,33 +0,0 @@ -const { Command } = require('../../commando'); - -module.exports = class SayCommand extends Command { - constructor(client) { - super(client, { - name: 'sayd', - aliases: ['copycatd', 'repeatd', 'echod', 'parrotd'], - group: 'fun', - memberName: 'sayd', - guildOnly: true, - description: 'Makes me say something for you, and then delete it!', - examples: ['~say [sentence]'], - throttling: { - usages: 1, - duration: 5 - }, - args: [{ - key: 'sayMessage', - prompt: 'Please provide me a message to say!', - type: 'string', - default: 'N////A' - }] - }); - } - - run(message, args) { - const { sayMessage } = args; - if (sayMessage == 'N////A') return message.say('Please specify something for me to say!'); - - message.delete(); - return message.say(sayMessage).catch(console.error); - } -} \ No newline at end of file diff --git a/Komugari-master/commands/fun/today.js b/Komugari-master/commands/fun/today.js deleted file mode 100644 index ab2c21e..0000000 --- a/Komugari-master/commands/fun/today.js +++ /dev/null @@ -1,37 +0,0 @@ -const { Command } = require('../../commando'); -const Discord = require('discord.js'); -const snekfetch = require('snekfetch'); - -module.exports = class TodayCommand extends Command { - constructor(client) { - super(client, { - name: 'today', - guildOnly: true, - aliases: ['date', 'history'], - group: 'fun', - memberName: 'today', - description: 'Finds a historical event from today!', - examples: ['~today'], - throttling: { - usages: 1, - duration: 5 - } - }); - } - - async run(message) { - const res = await snekfetch.get('http://history.muffinlabs.com/date') - - const data = JSON.parse(res.body) - - const source = data.data['Events'] - const event = source[Math.round(Math.random() * (source.length - 1))] - - const embed = new Discord.MessageEmbed() - .setAuthor(`Historical Event from ${data.date}, ${event.year}`) - .setColor('#B1AFFC') - .setDescription(event.text) - .addField('❯\u2000\Information', `•\u2000\**Year:** ${event.year}\n\•\u2000\**External Link${event.links.length !== 1 ? 's' : ''}:** ${event.links.map(l => `[${l.title}](${l.link})`).join(', ')}`); - return message.channel.send({ embed }); - } -} \ No newline at end of file diff --git a/Komugari-master/commands/fun/tsundere.js b/Komugari-master/commands/fun/tsundere.js deleted file mode 100644 index c51362a..0000000 --- a/Komugari-master/commands/fun/tsundere.js +++ /dev/null @@ -1,52 +0,0 @@ -const { Command } = require('../../commando'); -const tsun = [ - "N-No, it's not like I did it for you! I did it because I had freetime, that's all! ┐( ̄ヘ ̄;)┌", - "I like you, you idiot! 💢", - "BAKAAAAAAAAAAAAAAA!!!!! YOU'RE A BAKAAAAAAA!!!! 💢💢", - "I'm just here because I had nothing else to do!", - "Are you stupid?", - "💢 You're such a slob!", - "You should be grateful!", - "You're free anyways, right?", - "Don't misunderstand, it's not like I like you or anything... (  ̄^ ̄)", - "H-Hey.... (//・.・//)", - "....T-Thanks.....", - "B-Baka! 💢", - "T-Tch! S-Shut up!", - "I just had extra, so shut up and take it! 💢", - "Can you be ANY MORE CLUELESS?", - "HEY! It's a privilege to even be able to talk to me! You should be honored! 💢", - "Geez, stop pushing yourself! You're going to get yourself hurt one day, you idiot!", - "I-I am not a tsundere, you b-baka!", - "💢 I'm only t-talking to you because I have nothing else to do, b-baka!", - "Don't get the wrong idea! BAKA!", - "I-I'm doing this p-purely for my own benefit. So d-don't misunderstand, you idiot!", - "Urusai, urusai, urusai!! 💢", - "I-It's not that I like you or anything, I just happened to make too much for lunch...", - "Don't misunderstand...baka.", - "B-baka! I am not a tsundere! 💢", - "Na-nan des-ka?" -] - - -module.exports = class TsundereCommand extends Command { - constructor(client) { - super(client, { - name: 'tsundere', - aliases: ['tsun'], - group: 'fun', - memberName: 'tsundere', - guildOnly: true, - description: 'Get a random tsundere quote!', - examples: ['~tsundere'], - throttling: { - usages: 1, - duration: 3 - } - }); - } - - run(message) { - return message.channel.send(tsun[Math.round(Math.random() * (tsun.length - 1))]); - } -} \ No newline at end of file diff --git a/Komugari-master/commands/fun/zalgo.js b/Komugari-master/commands/fun/zalgo.js deleted file mode 100644 index 7ff4cd1..0000000 --- a/Komugari-master/commands/fun/zalgo.js +++ /dev/null @@ -1,34 +0,0 @@ -const { Command } = require('../../commando'); -const zalgo = require('zalgolize'); - -module.exports = class ZalgoCommand extends Command { - constructor(client) { - super(client, { - name: 'zalgo', - group: 'fun', - memberName: 'zalgo', - guildOnly: true, - description: 'Converts your text into zalgo!', - example: ['~zalgo [text]'], - args: [{ - key: 'text', - prompt: 'What text would you like to convert to zalgo?', - type: 'string', - default: 'Just Monika', - validate: text => { - if (text.length < 500) return true; - return 'Text must be under 500 characters.'; - } - }], - throttling: { - usages: 1, - duration: 3 - } - }); - } - - run(message, args) { - const { text } = args; - return message.channel.send(`\u180E${zalgo(text, 0.2, [10, 5, 10])}`); - } -}; diff --git a/Komugari-master/commands/info/channel.js b/Komugari-master/commands/info/channel.js deleted file mode 100644 index bdd27e2..0000000 --- a/Komugari-master/commands/info/channel.js +++ /dev/null @@ -1,79 +0,0 @@ -const { Command } = require('../../commando'); -const Discord = require('discord.js'); -const moment = require('moment'); -const { fromNow } = require('../../commando/util') - -module.exports = class ChannelCommand extends Command { - constructor(client) { - super(client, { - name: 'channel', - aliases: ['channels', 'channelinfo'], - group: 'info', - guildOnly: true, - memberName: 'channel', - description: 'Displays all channels of the server, or gives information on a channel!', - examples: ['~channel '], - throttling: { - usages: 1, - duration: 3 - }, - args: [{ - key: 'channel', - prompt: 'Please provide me with a channel to get the information of!', - type: 'channel', - default: '' - }] - }); - } - - run(message, args) { - let somethingThere = message.content.split(/\s+/g).slice(1).join(" "); - - const channelCategory = message.guild.channels.filter(c => c.type === 'category') - const textChannels = message.guild.channels.filter(c => c.type === 'text') - const voiceChannels = message.guild.channels.filter(c => c.type === 'voice') - - const sortPos = (a, b) => a.position - b.position; - - if (!somethingThere) { - const hasPerm = (c, perms) => c.permissionsFor(message.member).has(perms) - const f = t => ` **\`[${t}]\`**` - const displayPerms = c => `${!hasPerm(c, 'SEND_MESSAGES') && c instanceof Discord.TextChannel ? f('NO SEND') : ''}${!hasPerm(c, 'CONNECT') && c instanceof Discord.VoiceChannel ? f('NO CONNECT') : ''}${!hasPerm(c, 'VIEW_CHANNEL') ? f('NO VIEW') : ''}` - const isAFK = c => c.id === message.guild.afkChannelID; - - var description = [].concat( - - `**❯\u2000\Text channels [${textChannels.size}]:**`, - channelCategory.sort(sortPos).map(c => `•\u2000**${c.name}** [${c.children.size}]\n${textChannels.filter(d => d.parentID === c.id).sort(sortPos).map(d => (`#\u2000${d.name}${displayPerms(d)}\n`)).join("")}`), - textChannels.filter(e => e.parentID === null || e.parentID === undefined).sort(sortPos).map(c => c ? `#\u2000${c.name}${displayPerms(c)}` : ""), - - `**❯\u2000\Voice channels [${voiceChannels.size}]:**`, - - voiceChannels.sort(sortPos).map(c => `•\u2000${c.name}${displayPerms(c)}${isAFK(c) ? ' **`[AFK]`**' : ''}`) - - ); - - if(description.length > 2048) return message.channel.send('Too much channels in this server! I couldn\'t send the information!'); - - const embed = new Discord.MessageEmbed() - .setAuthor(`Channels in ${message.guild.name} [${message.guild.channels.size}]`, message.guild.iconURL()) - .setDescription(description) - .setThumbnail(message.guild.iconURL()) - .setFooter(`Permissions shown for ${message.author.tag}`, message.author.displayAvatarURL()) - .setColor('#8B9EB7'); - return message.channel.send({ embed }); - } - - var { channel } = args; - - const embed = new Discord.MessageEmbed() - .setAuthor(channel.name, message.guild.iconURL()) - .setDescription(`•\u2000${channel.topic ? channel.topic : '`No Topic`'}`) - .setThumbnail(message.guild.iconURL()) - .setFooter(`Requested by ${message.author.tag}`, message.author.displayAvatarURL()) - .setColor('#846B86') - .addField('❯\u2000\Information', `•\u2000\**ID:** ${channel.id}\n\•\u2000\**Category:** ${channel.parent ? channel.parent : 'None'}\n\•\u2000\**Created:** ${moment(channel.createdAt).format('MMMM Do YYYY')} \`(${fromNow(channel.createdAt)})\``, true) - .addField('❯\u2000\Miscellaneous', `•\u2000\**NSFW:** ${channel.nsfw ? "Yes" : "No"}\n\•\u2000\**Matching Permissions:** ${channel.permissionsLocked ? "Yes" : "No"}`, true) - return message.channel.send({ embed }); - } -} \ No newline at end of file diff --git a/Komugari-master/commands/info/discrim.js b/Komugari-master/commands/info/discrim.js deleted file mode 100644 index 38bed3c..0000000 --- a/Komugari-master/commands/info/discrim.js +++ /dev/null @@ -1,36 +0,0 @@ -const { Command } = require('../../commando'); -const Discord = require('discord.js'); - -module.exports = class DiscrimCommand extends Command { - constructor(client) { - super(client, { - name: 'discrim', - aliases: ['discriminator', 'search-discrim'], - group: 'info', - memberName: 'discrim', - description: 'Finds all the users with the same discriminator!', - args: [{ - key: 'discrim', - prompt: 'Please provide me a discriminator to search for!', - type: 'string', - default: '', - validate: discrim => { - if (/[0-9]+$/g.test(discrim) && discrim.length === 4) return true; - return 'Invalid Discriminator.'; - } - }] - }); - } - - run(message, args) { - const discrim = args.discrim || message.author.discriminator; - const users = this.client.users.filter(user => user.discriminator === discrim).map(user => user.tag); - if (users.length < 1) return message.channel.send(`**${message.author.username}**, no users found with the discriminator **${discrim}**!`); - - const embed = new Discord.MessageEmbed() - .setTitle(`${users.length} ${users.length > 1 ? 'users' : 'user'} with the discriminator: ${discrim}`) - .setColor('#4C6684') - .setDescription(users); - return message.channel.send({ embed }); - } -}; \ No newline at end of file diff --git a/Komugari-master/commands/info/edits.js b/Komugari-master/commands/info/edits.js deleted file mode 100644 index a5d3e22..0000000 --- a/Komugari-master/commands/info/edits.js +++ /dev/null @@ -1,65 +0,0 @@ -const { Command } = require('../../commando'); -const Discord = require('discord.js'); -const moment = require('moment') -const { fromNow } = require('../../commando/util') - -module.exports = class EditsCommand extends Command { - constructor(client) { - super(client, { - name: 'edits', - guildOnly: true, - aliases: ['edit'], - group: 'info', - memberName: 'edits', - description: 'Fetches the recent edits of a message!', - examples: ['~edits [message ID]'], - throttling: { - usages: 1, - duration: 5 - }, - args: [ - { - key: 'message', - prompt: 'Please provide the ID of the message you want to find edits for!', - type: 'message' - } - ] - }); - }; - - run (message, args) { - const m = args.message - - const nestedFields = [] - - for (let i = 0; i < m.edits.length; i++) { - nestedFields.push(`❯\u2000\**${i === m.edits.length - 1 ? 'Original' : (i === 0 ? 'Latest' : `Edit #${m.edits.length - i - 1}`)}:**\n` + - `•\u2000${m.edits[i].content.length > 0 ? truncate(m.edits[i].content, 1024) : '`N/A`'}\n` - ) - } - - const embed = new Discord.MessageEmbed() - .setColor('#B094AF') - .setAuthor(`${m.author.tag} @ ${moment(m.createdAt).format('MMMM Do YYYY')} (${fromNow(m.editedAt)})`, m.author.displayAvatarURL()) - .setFooter(`Latest edit: ${moment(m.editedAt).format('MMMM Do YYYY')} (${fromNow(m.editedAt)})`) - .setDescription(nestedFields); - return message.channel.send({embed}) - - } -}; - -function truncate (string, max, append = '') { - if (!string || !max || (1 + append.length) >= max) { - return '' - } - - if (string.length <= max && !append) { - return string - } - - string = string.slice(0, max - 1 - append.length) - if (/\s/.test(string.charAt(string.length - 1))) { - string = string.replace(/\s+?$/, '') - } - return string + '\u2026' + append -} diff --git a/Komugari-master/commands/info/emoji.js b/Komugari-master/commands/info/emoji.js deleted file mode 100644 index e95a056..0000000 --- a/Komugari-master/commands/info/emoji.js +++ /dev/null @@ -1,57 +0,0 @@ -const { Command } = require('../../commando'); -const Discord = require('discord.js'); - -module.exports = class EmojiCommand extends Command { - constructor(client) { - super(client, { - name: 'emoji', - aliases: ['emojis', 'emotes', 'emote'], - group: 'info', - memberName: 'emoji', - guildOnly: true, - description: 'Makes your given emoji bigger, or sends all your server emojis!', - examples: ['~emoji '], - throttling: { - usages: 1, - duration: 3 - }, - args: [{ - key: 'emoji', - prompt: 'Please give me an emoji to magnify!', - type: 'string', - default: '' - }] - }); - } - - async run(message, args) { - let emoji = message.content.split(/\s+/g).slice(1).join(" ") - - if (!emoji) { - const emojis = message.guild.emojis - if (!emojis.size) return message.channel.send('You have no custom emoji.'); - - - const embed = new Discord.MessageEmbed() - .setAuthor(`Emojis in ${message.guild.name}! [${emojis.size}]`, message.guild.iconURL()) - .setDescription(emojis.map(emoji => emoji.toString()).join(' '), { split: { char: ' ' } }) - .setColor('#A5A3BB') - return message.channel.send(`Here's all your custom emojis!`, { embed: embed }); - - } else { - const args = message.content.split(" "); - - if (!args[1].startsWith('<:')) return message.channel.send('That\'s not a valid emoji!') - let id = args[1].substring(args[1].lastIndexOf(':') + 1, args[1].lastIndexOf('>')) - - let emoteInfo = this.client.emojis.get(id) - if (!emoteInfo) return message.channel.send('That\'s not a valid custom emoji!') - - const embed = new Discord.MessageEmbed() - .setAuthor(emoteInfo.name) - .setImage(`https://cdn.discordapp.com/emojis/${emoteInfo.id}.png`) - .setColor('#D5BEC6'); - return message.channel.send({ embed }); - } - } -} \ No newline at end of file diff --git a/Komugari-master/commands/info/inrole.js b/Komugari-master/commands/info/inrole.js deleted file mode 100644 index 728564d..0000000 --- a/Komugari-master/commands/info/inrole.js +++ /dev/null @@ -1,62 +0,0 @@ -const { Command } = require('../../commando'); -const Discord = require('discord.js'); - - -module.exports = class InRoleCommand extends Command { - constructor(client) { - super(client, { - name: 'inrole', - aliases: ['rolecount', 'membercount'], - group: 'info', - guildOnly: true, - memberName: 'inrole', - description: 'Gets all the members from a given role!', - examples: ['~inrole [role]'], - throttling: { - usages: 1, - duration: 5 - }, - args: [{ - key: 'role', - prompt: 'Please provide me with a role to get the information of!', - type: 'role', - default: '' - }] - }); - } - - run(message, args) { - let somethingThere = message.content.split(/\s+/g).slice(1).join(" "); - - if (!somethingThere) { - var guildMembers = message.guild.members.sort((a, b) => a.user.tag.localeCompare(b.user.tag)).map(m => { - return `${m.user.tag}${(m.user.bot ? ' **`[BOT]`**' : '')}` - }).join(', ') - - const embed = new Discord.MessageEmbed() - .setAuthor(`All Members in ${message.guild.name}`, message.guild.iconURL()) - .setDescription(guildMembers) - .setFooter(`Requested by ${message.author.tag}`, message.author.displayAvatarURL()) - .setColor('#9473DB'); - return message.channel.send({embed}); - } - - const { role } = args; - let members = role.members; - - var allMembers = members.map(m => { - return `${m.user.tag}${(m.user.bot ? ' [BOT]' : '')}` - }).sort((a, b) => a.localeCompare(b)).join(', ') - - if(!allMembers) return message.channel.send('There are no members in that role!') - - if(allMembers.length > 2048) return message.channel.send('Too much members in that role! I couldn\'t send the information!'); - - const embed = new Discord.MessageEmbed() - .setAuthor(`${role.name} (${role.id})`, message.guild.iconURL()) - .setColor(role.hexColor) - .setDescription(`\`\`\`css\n${allMembers}\`\`\``) - .setFooter(`Requested by ${message.author.tag}`, message.author.displayAvatarURL()); - return message.channel.send(`All members with the **${role.name}** role!`, {embed: embed}); - } -} \ No newline at end of file diff --git a/Komugari-master/commands/info/server.js b/Komugari-master/commands/info/server.js deleted file mode 100644 index dae160f..0000000 --- a/Komugari-master/commands/info/server.js +++ /dev/null @@ -1,74 +0,0 @@ -const { Command } = require('../../commando'); -const Discord = require('discord.js'); -const moment = require('moment'); -const { fromNow } = require('../../commando/util'); -const verificationLevels = ['`None`', 'Low', 'Medium', '(╯°□°)╯︵ ┻━┻', '┻━┻ ミヽ(ಠ益ಠ)ノ彡┻━┻']; -const explicitContentFilters = ['`None`', 'Scan messages from those without a role', 'Scan all messages']; - - -module.exports = class ServerCommand extends Command { - constructor(client) { - super(client, { - name: 'server', - aliases: ['guild', 'serverinfo', 'servers', 'guilds'], - group: 'info', - memberName: 'server', - guildOnly: true, - description: 'Shows some in-depth description for your server!', - examples: ['~server'], - throttling: { - usages: 1, - duration: 5 - }, - args: [{ - key: 'id', - prompt: 'Please provide me a server ID to get the information of!', - type: 'string', - default: 'this' - }] - }); - } - - run(message, args) { - let guild; - - if (!this.client.isOwner(message.author)) { - guild = message.guild; - } else if (args.id == 'this') { - guild = message.guild; - } else if (!/^[0-9]+$/.test(args.id)) { - guild = message.guild; - } else { - try { - guild = this.client.guilds.get(args.id); - - if (guild.channels) { - guild = this.client.guilds.get(args.id); - } else { - guild = message.guild - } - - } catch(err) { - guild = message.guild; - } - } - - const textChannels = guild.channels.filter(c => c.type === 'text'); - const voiceChannels = guild.channels.filter(c => c.type === 'voice'); - - var online = guild.members.filter(m => m.user.presence.status === "online").size - var bots = guild.members.filter(m => m.user.bot).size - - var highestRole = guild.roles.sort((a, b) => a.position - b.position).map(role => role.toString()).slice(1).reverse()[0] - - const embed = new Discord.MessageEmbed() - .setAuthor(guild.name, guild.iconURL()) - .setColor('#846B86') - .setThumbnail(guild.iconURL()) - .setFooter(`Requested by ${message.author.tag}`, message.author.displayAvatarURL()) - .addField('❯\u2000\Information', `•\u2000\**ID:** \`${guild.id}\`\n\•\u2000\**${guild.owner ? 'Owner' : 'Owner ID'}:** ${guild.owner ? `${guild.owner.user.tag} \`(${guild.owner.id})\`` : guild.ownerID}\n\•\u2000\**Created:** ${moment(guild.createdAt).format('MMMM Do YYYY')} \`(${fromNow(guild.createdAt)})\`\n\•\u2000\**Region:** ${guild.region}\n\•\u2000\**Verification:** ${verificationLevels[guild.verificationLevel]}\n\•\u2000\**Content Filter:** ${explicitContentFilters[guild.explicitContentFilter]}`) - .addField('❯\u2000\Quantitative Statistics', `•\u2000\**Channels** [${guild.channels.size}]: ${textChannels.size} text - ${voiceChannels.size} voice\n\•\u2000\**Members** [${guild.memberCount}]: ${online} online - ${bots} bots\n\•\u2000\**Roles** [${guild.roles.size}]: say \`~roles\` to see all roles`, true) - .addField('❯\u2000\Miscellaneous', `•\u2000\**Highest Role:** ${highestRole}\n\•\u2000\**Emojis:** ${guild.emojis.size}\n\u2000\u2000\↳ Say *~emojis*!`, true) - return message.channel.send({embed}); - } -} \ No newline at end of file diff --git a/Komugari-master/commands/info/user.js b/Komugari-master/commands/info/user.js deleted file mode 100644 index c4eccda..0000000 --- a/Komugari-master/commands/info/user.js +++ /dev/null @@ -1,63 +0,0 @@ -const { Command } = require('../../commando'); -const Discord = require('discord.js'); -const moment = require('moment'); -const perms = require('../../assets/json/permissions'); -const { fromNow } = require('../../commando/util'); - - -module.exports = class UserCommand extends Command { - constructor(client) { - super(client, { - name: 'user', - aliases: ['info', 'userinfo', 'member', 'whois', 'profile'], - group: 'info', - memberName: 'user', - guildOnly: true, - description: 'Shows details about a user!', - examples: ['~user '], - args: [{ - key: 'member', - prompt: 'Which user would you like to get info on?', - type: 'member', - default: '' - }] - }); - } - - run(message, args) { - const member = args.member || message.member; - - const status = member.user.presence.activity ? (member.user.presence.activity.type ? 'Playing' : 'Playing') + ` **${member.user.presence.activity.name}**` : `*${member.user === this.client.user ? 'I am' : 'This user is'} not playing/streaming anything!*`; - - if (member.user.bot) { - var author = member.user.tag + ' [BOT]' - } else { - var author = member.user.tag - } - - if (!member.nickname) { - var nickname = '`N/A`' - } else { - var nickname = member.nickname - } - - const allowed = Object.entries(member.permissions.serialize()).filter(([perm, allowed]) => allowed).map(([perm]) => "`" + perms[perm]+ "`").join(', '); - - const roles = member.roles.array().slice(1).sort((a, b) => a.comparePositionTo(b)).reverse().map(role => { - return role.name; - }) - - const embed = new Discord.MessageEmbed() - .setAuthor(author, member.user.displayAvatarURL({ format: 'png' })) - .setDescription(status) - .setColor(member.displayHexColor) - .setThumbnail(member.user.displayAvatarURL()) - .setFooter(`Requested by ${message.author.tag}`, message.author.displayAvatarURL()) - .addField('❯\u2000\Information', `•\u2000\**ID:** ${member.user.id}\n\•\u2000\**Status:** ${member.user.presence.status ? member.user.presence.status : '`N/A`'}\n\•\u2000\**Created:** ${moment(member.user.createdAt).format('MMMM Do YYYY')} \`(${fromNow(member.user.createdAt)})\``) - .addField('❯\u2000\Server Membership', `•\u2000\**Nickname:** ${nickname}\n\•\u2000\**Joined:** ${moment(member.joinedAt).format('MMMM Do YYYY')} \`(${fromNow(member.joinedAt)})\``, true) - .addField('❯\u2000\**Role Infomation**', `•\u2000\**Highest Role:** ${member.highestRole.name !== '@everyone' ? member.highestRole.name : 'None'}\n\•\u2000\**Hoist Role:** ${member.hoistRole ? member.hoistRole.name : 'None'}`, true) - .addField(`❯\u2000\**Roles** [${roles.length}]`, roles.length ? '•\u2000' + roles.join(', ') : '•\u2000\None', true) - .addField(`❯\u2000\**Permissions**`, allowed ? `•\u2000${allowed}` : '•\u2000\None') - return message.channel.send(`User information for **${member.user.username}**#${member.user.discriminator}`, { embed: embed }); - } -} diff --git a/Komugari-master/commands/memes/bonzi.js b/Komugari-master/commands/memes/bonzi.js deleted file mode 100644 index 33d6bbb..0000000 --- a/Komugari-master/commands/memes/bonzi.js +++ /dev/null @@ -1,59 +0,0 @@ -var { Command } = require('../../commando'); -var Jimp = require('jimp'); - -//remember to return before every promise -module.exports = class BonziCommand extends Command { - constructor(client) { - super(client, { - name: 'bonzi', - aliases: ['fact'], - group: 'memes', - guildOnly: true, - clientPermissions: ['ATTACH_FILES'], - memberName: 'bonzi', - description: 'Makes Bonzi tell an interesting fact!', - examples: ['~bonzi [message]'], - throttling: { - usages: 1, - duration: 10 - }, - args: [{ - key: 'argument', - prompt: 'Please provide Bonzi a message to say!', - type: 'string', - default: 'N////A' - }] - }); - } - - async run(message, args) { - var argu = args.argument - if (argu = 'N////A') { - return message.channel.send('Please provide something for Bonzi to say!'); - } - - await message.channel.startTyping() - - var text = message.content.split(/\s+/g).slice(1).join(" "); - var bonzi = await Jimp.read('assets/images/bonzi.png'); - var blank = await Jimp.read('assets/images/blank.png'); - - var font = await Jimp.loadFont(Jimp.FONT_SANS_16_BLACK); - - blank.resize(175, 120); - var fact = blank.print(font, 0, 0, text, 175); - - bonzi.composite(fact, 23, 12); - bonzi.getBuffer(Jimp.MIME_PNG, async(err, buffer) => { - await message.channel.send({ - files: [{ - name: 'bonzi.png', - attachment: buffer - }] - }) - await message.channel.stopTyping() - }) - - return null; - } -} \ No newline at end of file diff --git a/Komugari-master/commands/memes/disabled.js b/Komugari-master/commands/memes/disabled.js deleted file mode 100644 index 17ae5e5..0000000 --- a/Komugari-master/commands/memes/disabled.js +++ /dev/null @@ -1,50 +0,0 @@ -const { Command } = require('../../commando'); -const Jimp = require('jimp'); - -module.exports = class DisabledCommand extends Command { - constructor(client) { - super(client, { - name: 'disabled', - group: 'memes', - guildOnly: true, - clientPermissions: ['ATTACH_FILES'], - memberName: 'disabled', - description: 'The public should know what disability looks like!', - examples: ['~disabled '], - throttling: { - usages: 1, - duration: 10 - } - }); - } - - async run(message) { - - const args = message.content.split(" ").slice(1) - - await message.channel.startTyping() - - let avatarurl = (message.mentions.users.size > 0 ? message.mentions.users.first().displayAvatarURL({ format: 'png' }) : message.author.displayAvatarURL({ format: 'png' })).replace('gif', 'png'); - if (['jpg', 'jpeg', 'gif', 'png', 'webp'].some(x => args.join(' ').includes(x))) { - avatarurl = args.join(' ').replace(/gif|webp/g, 'png') - } - - var avatar = await Jimp.read(avatarurl); - const disabled = await Jimp.read('assets/images/disabled.png'); - - avatar.resize(157, 157); - - disabled.composite(avatar, 390, 252); - disabled.getBuffer(Jimp.MIME_PNG, async(err, buffer) => { - await message.channel.send({ - files: [{ - name: 'disabled.png', - attachment: buffer - }] - }) - await message.channel.stopTyping() - }) - - return null; - } -} \ No newline at end of file diff --git a/Komugari-master/commands/memes/magik.js b/Komugari-master/commands/memes/magik.js deleted file mode 100644 index 3fe9459..0000000 --- a/Komugari-master/commands/memes/magik.js +++ /dev/null @@ -1,49 +0,0 @@ -const { Command } = require('../../commando'); -const Discord = require('discord.js'); -const snekfetch = require('snekfetch'); - -module.exports = class MagikCommand extends Command { - constructor(client) { - super(client, { - name: 'magik', - guildOnly: true, - aliases: ['magic', 'contentawareness', 'contentaware'], - group: 'memes', - memberName: 'magik', - description: 'Applies the magik filter to your image!', - examples: ['~magik [attachment/link]'], - throttling: { - usages: 1, - duration: 15 - } - }); - } - - async run(message) { - if (!message.channel.permissionsFor(this.client.user).has('ATTACH_FILES')) { - return message.channel.send('I can\'t attach messages!'); - } - - const args = message.content.split(" ").slice(1) - - const msg = await message.channel.send('🔄 | Adding a hint of magik...') - - let avatarurl = (message.mentions.users.size > 0 ? message.mentions.users.first().displayAvatarURL({ format: 'png', size: 512 }) : message.author.displayAvatarURL({ format: 'png', size: 512 })).replace('gif', 'png'); - if (['jpg', 'jpeg', 'gif', 'png', 'webp'].some(x => args.join(' ').includes(x))) { - avatarurl = args.join(' ').replace(/gif|webp/g, 'png') - } - - const res = await snekfetch.get(`https://discord.services/api/magik?url=${avatarurl}`) - - if (res.body == 'some error sry :/') { - await msg.delete() - return message.channel.send('❎ | Invalid image/URL! Please try again!') - } else { - await msg.delete() - const embed = new Discord.MessageEmbed() - .setColor('#294475') - .setImage(`https://discord.services/api/magik?url=${avatarurl}`); - return message.channel.send({ embed }) - } - } -} \ No newline at end of file diff --git a/Komugari-master/commands/memes/retarded.js b/Komugari-master/commands/memes/retarded.js deleted file mode 100644 index 2cf842d..0000000 --- a/Komugari-master/commands/memes/retarded.js +++ /dev/null @@ -1,50 +0,0 @@ -const { Command } = require('../../commando'); -const Jimp = require('jimp'); - -module.exports = class RetardedCommand extends Command { - constructor(client) { - super(client, { - name: 'retarded', - group: 'memes', - memberName: 'retarded', - guildOnly: true, - description: 'A cute(???) little dog???', - examples: ['~retarded [message]'], - throttling: { - usages: 1, - duration: 10 - } - }); - } - - async run(message) { - if (!message.channel.permissionsFor(this.client.user).has('ATTACH_FILES')) { - return message.channel.send('I can\'t attach messages!') - } - - const argu = message.content.split(/\s+/g).slice(1).join(" "); - - if (!argu) { - return message.channel.send('Please provide some text!'); - } - - const text = message.content.split(/\s+/g).slice(1).join(" "); - const retarded = await Jimp.read('assets/images/retarded.png'); - const blank = await Jimp.read('assets/images/blank.png'); - - const font = await Jimp.loadFont(Jimp.FONT_SANS_16_BLACK); - - blank.resize(225, 45); - const search = blank.print(font, 0, 0, text, 225); - - retarded.composite(search, 295, 5); - retarded.getBuffer(Jimp.MIME_PNG, async(err, buffer) => { - return await message.channel.send({ - files: [{ - name: 'retarded.png', - attachment: buffer - }] - }) - }) - } -} \ No newline at end of file diff --git a/Komugari-master/commands/memes/shit.js b/Komugari-master/commands/memes/shit.js deleted file mode 100644 index 082c18f..0000000 --- a/Komugari-master/commands/memes/shit.js +++ /dev/null @@ -1,66 +0,0 @@ -const { Command } = require('../../commando'); -const Jimp = require('jimp'); - -//remember to return before every promise -module.exports = class ShitCommand extends Command { - constructor(client) { - super(client, { - name: 'shit', - group: 'memes', - memberName: 'shit', - guildOnly: true, - description: 'It\'s shit!!!', - examples: ['~shit [message]'], - throttling: { - usages: 1, - duration: 10 - } - }); - } - - async run(message) { - if (!message.channel.permissionsFor(this.client.user).has('ATTACH_FILES')) { - return message.channel.send('I can\'t attach messages!'); - } - - var args = message.content.split(/\s+/g).slice(1) - - if (message.mentions.users.size > 0) { - args = message.mentions.users.first().username; - } else { - if (args < 1) { - args = message.author.username; - } else if (args.join(' ').length > 35) { - return message.channel.send(`The limit is 35 characters! You're ${args.join(' ').length - 35} characters over the limit!`); - } else { - args = args.join(' '); - } - } - - await message.channel.startTyping() - - const text = args; - const shit = await Jimp.read('assets/images/shit.jpg'); - const blank = await Jimp.read('assets/images/Empty.png'); - - const font = await Jimp.loadFont(Jimp.FONT_SANS_32_BLACK); - - blank.resize(350, 350); - const search = blank.print(font, 0, 0, text, 350); - search.rotate(310); - - shit.composite(search, 195, 585); - shit.getBuffer(Jimp.MIME_PNG, async(err, buffer) => { - return await message.channel.send({ - files: [{ - name: 'shit.png', - attachment: buffer - }] - }) - - await message.channel.stopTyping() - }) - - return null; - } -} \ No newline at end of file diff --git a/Komugari-master/commands/memes/shits.js b/Komugari-master/commands/memes/shits.js deleted file mode 100644 index 4885060..0000000 --- a/Komugari-master/commands/memes/shits.js +++ /dev/null @@ -1,57 +0,0 @@ -const { Command } = require('../../commando'); -const Jimp = require('jimp'); - -//remember to return before every promise -module.exports = class ShitsCommand extends Command { - constructor(client) { - super(client, { - name: 'shits', - group: 'memes', - memberName: 'shits', - guildOnly: true, - description: 'It\'s shit!!!', - examples: ['~shits [message]'], - throttling: { - usages: 1, - duration: 10 - } - }); - } - - async run(message) { - if (!message.channel.permissionsFor(this.client.user).has('ATTACH_FILES')) { - return message.channel.send('I can\'t attach messages!'); - } - - const args = message.content.split(/\s+/g).slice(1).join(" "); - - if (args.length < 1) { - return message.channel.send('Please provide some text!'); - } - - await message.channel.startTyping() - - const text = message.content.split(/\s+/g).slice(1).join(" "); - const shits = await Jimp.read('assets/images/SHITS.png'); - const blank = await Jimp.read('assets/images/blank.png'); - - const font = await Jimp.loadFont(Jimp.FONT_SANS_32_BLACK); - - blank.resize(195, 175); - const search = blank.print(font, 0, 0, text, 175); - - shits.composite(search, 810, 31); - shits.getBuffer(Jimp.MIME_PNG, async(err, buffer) => { - await message.channel.send({ - files: [{ - name: 'shits.png', - attachment: buffer - }] - }) - - await message.channel.stopTyping() - }) - - return null; - } -} \ No newline at end of file diff --git a/Komugari-master/commands/memes/thesearch.js b/Komugari-master/commands/memes/thesearch.js deleted file mode 100644 index 85c28c8..0000000 --- a/Komugari-master/commands/memes/thesearch.js +++ /dev/null @@ -1,56 +0,0 @@ -const { Command } = require('../../commando'); -const Jimp = require('jimp'); - -//remember to return before every promise -module.exports = class TheSearchCommand extends Command { - constructor(client) { - super(client, { - name: 'thesearch', - group: 'memes', - memberName: 'thesearch', - guildOnly: true, - description: 'What if there\'s intelligible life on Earth?', - examples: ['~thesearch [message]'], - throttling: { - usages: 1, - duration: 10 - } - }); - } - - async run(message) { - if (!message.channel.permissionsFor(this.client.user).has('ATTACH_FILES')) { - return message.channel.send('I can\'t attach messages!'); - } - - const args = message.content.split(/\s+/g).slice(1).join(" "); - - if (args.length < 1) { - return message.channel.send('Please provide some text!'); - } - - await message.channel.startTyping() - - const text = message.content.split(/\s+/g).slice(1).join(" "); - const thesearch = await Jimp.read('assets/images/thesearch.png'); - const blank = await Jimp.read('assets/images/blank.png'); - - const font = await Jimp.loadFont(Jimp.FONT_SANS_16_BLACK); - - blank.resize(160, 70); - const search = blank.print(font, 0, 0, text, 150); - - thesearch.composite(search, 60, 331); - thesearch.getBuffer(Jimp.MIME_PNG, async(err, buffer) => { - await message.channel.send({ - files: [{ - name: 'thesearch.png', - attachment: buffer - }] - }) - await message.channel.stopTyping() - }) - - return null; - } -} \ No newline at end of file diff --git a/Komugari-master/commands/memes/triggered.js b/Komugari-master/commands/memes/triggered.js deleted file mode 100644 index 110c635..0000000 --- a/Komugari-master/commands/memes/triggered.js +++ /dev/null @@ -1,103 +0,0 @@ -const { Command } = require('../../commando'); -const Jimp = require('jimp'); -const GIFEncoder = require('gifencoder'); - -const options = { - size: 256, - frames: 8 -} - -module.exports = class TriggeredCommand extends Command { - constructor(client) { - super(client, { - name: 'triggered', - group: 'memes', - memberName: 'triggered', - guildOnly: true, - description: 'T R I G G E R E D', - examples: ['~triggered '], - throttling: { - usages: 1, - duration: 10 - } - }); - } - - async run(message) { - function getRandomInt(min, max) { - return Math.floor(Math.random() * (max - min + 1)) + min; - } - - - if (!message.channel.permissionsFor(this.client.user).has('ATTACH_FILES')) { - return message.channel.send('I can\'t attach messages!'); - } - - await message.channel.startTyping() - - const args = message.content.split(" ").slice(1) - - let avatarurl = (message.mentions.users.size > 0 ? message.mentions.users.first().displayAvatarURL({ format: 'png' }) : message.author.displayAvatarURL({ format: 'png' })); - if (['jpg', 'jpeg', 'gif', 'png', 'webp'].some(x => args.join(' ').includes(x))) { - avatarurl = args.join(' ').replace(/gif|webp/g, 'png') - } - - const base = new Jimp(options.size, options.size); - const avatar = await Jimp.read(avatarurl); - const text = await Jimp.read('assets/images/triggered.jpg'); - const tint = await Jimp.read('assets/images/red.png'); - - avatar.resize(320, 320); - tint.scaleToFit(base.bitmap.width, base.bitmap.height) - tint.opacity(0.2) - text.scaleToFit(280, 60) - - const frames = []; - const buffers = []; - const encoder = new GIFEncoder(options.size, options.size); - const stream = encoder.createReadStream(); - let temp - - stream.on('data', async buffer => await buffers.push(buffer)); - stream.on('end', async() => { - await message.channel.send({ - files: [{ - name: 'triggered.gif', - attachment: Buffer.concat(buffers) - }] - }) - await message.channel.stopTyping(); - - return null; - }) - - for (let i = 0; i < options.frames; i++) { - temp = base.clone() - - if (i === 0) { - temp.composite(avatar, -16, -16) - } else { - temp.composite(avatar, -32 + getRandomInt(-16, 16), -32 + getRandomInt(-16, 16)) - } - - temp.composite(tint, 0, 0) - - if (i === 0) { - temp.composite(text, -10, 200) - } else { - temp.composite(text, -12 + getRandomInt(-8, 8), 200 + getRandomInt(-0, 12)) - } - - frames.push(temp.bitmap.data) - } - - encoder.start() - encoder.setRepeat(0) - encoder.setDelay(20) - for (const frame of frames) { - encoder.addFrame(frame) - } - encoder.finish() - - } -} \ No newline at end of file diff --git a/Komugari-master/commands/moderation/addrole.js b/Komugari-master/commands/moderation/addrole.js deleted file mode 100644 index f14b018..0000000 --- a/Komugari-master/commands/moderation/addrole.js +++ /dev/null @@ -1,42 +0,0 @@ -const { Command } = require('../../commando'); - -module.exports = class AddRoleCommand extends Command { - constructor(client) { - super(client, { - name: 'addrole', - group: 'moderation', - aliases: ['newrole', 'ar', 'addr', 'assign'], - memberName: 'addrole', - description: 'Adds a role to a member!', - examples: ['~addrole [name] [role]'], - guildOnly: true, - args: [{ - key: 'member', - prompt: 'Please provide me a member to add the role to!', - type: 'member' - }, - { - key: 'role', - prompt: 'Please provide me a role to add!', - type: 'role' - } - ] - }); - } - - hasPermission(message) { - return message.member.hasPermission('MANAGE_ROLES'); - } - - async run(message, args) { - const { member, role } = args; - if (member.roles.has(role.id)) return message.channel.send(`❎ | **${member.displayName}** already has the role **${role.name}**!`) - - try { - await member.addRole(role) - return message.channel.send(`✅ | **${member.displayName}** has been given the role **${role.name}**!`) - } catch (err) { - return message.channel.send(`❎ | **${memeber.displayName}** already has the role **${role.name}**!`) - } - }; -}; \ No newline at end of file diff --git a/Komugari-master/commands/moderation/ban.js b/Komugari-master/commands/moderation/ban.js deleted file mode 100644 index 0941ec9..0000000 --- a/Komugari-master/commands/moderation/ban.js +++ /dev/null @@ -1,69 +0,0 @@ -const { Command } = require('../../commando'); - - -module.exports = class BanCommand extends Command { - constructor(client) { - super(client, { - name: 'ban', - group: 'moderation', - memberName: 'ban', - guildOnly: true, - clientPermissions: ['BAN_MEMBERS'], - userPermissions: ['BAN_MEMBERS'], - description: 'Bans the given user and DMs them the reason!', - examples: ['~ban [user] [reason]'], - throttling: { - usages: 1, - duration: 15 - }, - args: [{ - key: 'member', - prompt: 'Please provide me a user to ban!', - type: 'member' - }, - { - key: 'reason', - prompt: 'Please provide me a reason to ban this user! The reason will be DM\'ed to the user!', - type: 'string', - default: 'none', - validate: reason => { - if (reason.length < 140) return true; - return 'Reason must be under 140 characters!'; - } - } - ] - }); - } - - async run(message, args) { - const { member, reason } = args; - - if (member.id === this.client.user.id) return message.channel.send('Please don\'t ban me...!'); - if (member.id === message.author.id) return message.channel.send('I wouldn\'t dare ban you...!'); - if (member.highestRole.calculatedPosition > message.member.highestRole.calculatedPosition - 1) return message.channel.send(`❎ | You can't ban **${member.user.username}**! Their position is higher than you!`); - if (!member.bannable) return message.channel.send(`❎ | I can't ban **${member.user.username}**! Their role is higher than mine!`); - - await message.channel.send(`Are you sure you want to ban **${member.user.tag}**? \`\`(y/n)\`\``); - const msgs = await message.channel.awaitMessages(res => res.author.id === message.author.id, { - max: 1, - time: 30000 - }); - - if (!msgs.size || !['y', 'yes'].includes(msgs.first().content.toLowerCase())) return message.channel.send('Cancelled command!'); - if (['n', 'no'].includes(msgs.first().content.toLowerCase())) return message.channel.send('Cancelled command!') - - try { - await member.send(`You were banned from ${message.guild.name} by ${message.author.tag}!\n\**Reason:** ${reason}`); - } catch (err) { - await message.channel.send(`❎ | **${message.author.username}**, failed to Send DM to **${member}**! \`${err}\``); - } - - await member.ban({ - days: 7, - reason: `${message.author.tag}: ${reason}` - }); - - return await message.channel.send(`✅ | **${message.author.username}**, successfully banned ${member.user.tag}! 👋`); - - } -} \ No newline at end of file diff --git a/Komugari-master/commands/moderation/bulkban.js b/Komugari-master/commands/moderation/bulkban.js deleted file mode 100644 index d0cef79..0000000 --- a/Komugari-master/commands/moderation/bulkban.js +++ /dev/null @@ -1,76 +0,0 @@ -const { Command } = require('../../commando'); - -module.exports = class BulkBanCommand extends Command { - constructor(client) { - super(client, { - name: 'bulkban', - guildOnly: true, - aliases: ['batchban', 'massban'], - group: 'moderation', - clientPermissions: ['ADMINISTRATOR'], - userPermissions: ['BAN_MEMBERS'], - memberName: 'bulkban', - description: 'Bans a list of user IDs!', - details: 'This command is very destructive and without limitations, please try to use `ban` instead as often as possible!', - examples: ['~bulkban [mentions/user IDs separated by spaces of commas]'], - throttling: { - usages: 1, - duration: 30 - }, - args: [{ - key: 'users', - prompt: 'Please provide me some users to ban!', - type: 'string' - }] - }); - } - - async run(message, args) { - const users = args.users; - - let regex = /\b[0-9]{17,18}\b/g; - let found = users.match(regex) - - if (!found.length) return message.channel.send('No IDs found! Please ensure that there are IDs separated by spaces or commas!'); - - await message.channel.send(`Are you sure you want to ban **${found.length}** users? \`\`(y/n)\`\``); - const msgs = await message.channel.awaitMessages(res => res.author.id === message.author.id, { - max: 1, - time: 30000 - }); - - if (!msgs.size || !['y', 'yes'].includes(msgs.first().content.toLowerCase())) return message.channel.send('Cancelled command!'); - if (['n', 'no'].includes(msgs.first().content.toLowerCase())) return message.channel.send('Cancelled command!'); - - let sent = await message.channel.send(`🔄 | Attempting to ban ${found.length} users... keep your eye on this message!`); - - ban_user(0, found, this.client.users, sent, message); - - return null; - } -} - -async function ban_user(index, found, users, sent, message) { - - var user = await users.fetch(found[index]) - .catch(err => sent.edit(sent.content += `\n**Error** ${err.name}: \`${err.message} ${found[index]}\``)); - - if (user.tag) { - try { - if (user.id === this.client.user.id) return sent.edit(sent.content += `\nPlease don't ban me!`); - if (user.id === message.author.id) return sent.edit(sent.content += `\nDon't ban yourself!`); - if (message.guild.member(user).highestRole.calculatedPosition > message.member.highestRole.calculatedPosition - 1) return sent.edit(sent.content += `\n**${user.tag}**'s roles are too high to be banned!`); - if (!message.guild.member(user).bannable) return sent.edit(sent.content += `\n**${user.tag}**'s roles are too high to be banned!`); - - message.guild.ban(found[index], { days: 7, reason: `responsible: ${message.author.tag}` }).catch(err => sent.edit(sent.content += `\nError trying to ban **${user.tag}** \`(${user.id})\`!`)); - sent.edit(sent.content += `\nBanned **${user.tag}** \`(${user.id})\``) - } catch (err) { - sent.edit(sent.content += `\nError trying to ban **${user.tag}** \`(${user.id})\`!`); - } - } - - if (index < found.length - 1) ban_user(index + 1, found, users, sent, message); - else sent.edit(sent.content += `\n__Finished bulk ban!__`); - - return null; -} \ No newline at end of file diff --git a/Komugari-master/commands/moderation/bulkkick.js b/Komugari-master/commands/moderation/bulkkick.js deleted file mode 100644 index 890b6bb..0000000 --- a/Komugari-master/commands/moderation/bulkkick.js +++ /dev/null @@ -1,77 +0,0 @@ -const { Command } = require('../../commando'); - -module.exports = class BulkKickCommand extends Command { - constructor(client) { - super(client, { - name: 'bulkkick', - guildOnly: true, - aliases: ['batchkick', 'masskick'], - group: 'moderation', - clientPermissions: ['KICK_MEMBERS'], - userPermissions: ['BAN_MEMBERS'], - memberName: 'bulkkick', - description: 'Kicks a list of user IDs!', - details: 'This command is very destructive and without limitations, please try to use `kick` instead as often as possible!', - examples: ['~bulkkick [mentions/user IDs separated by spaces of commas]'], - throttling: { - usages: 1, - duration: 30 - }, - args: [{ - key: 'users', - prompt: 'Please provide me some users to kick!', - type: 'string' - }] - }); - } - - async run(message, args) { - const users = args.users; - - let regex = /\b[0-9]{17,18}\b/g; - let found = users.match(regex) - - if (!found.length) return message.channel.send('No IDs found! Please ensure that there are IDs separated by spaces or commas!'); - - await message.channel.send(`Are you sure you want to kick **${found.length}** users? \`\`(y/n)\`\``); - const msgs = await message.channel.awaitMessages(res => res.author.id === message.author.id, { - max: 1, - time: 30000 - }); - - if (!msgs.size || !['y', 'yes'].includes(msgs.first().content.toLowerCase())) return message.channel.send('Cancelled command!'); - if (['n', 'no'].includes(msgs.first().content.toLowerCase())) return message.channel.send('Cancelled command!'); - - let sent = await message.channel.send(`🔄 | Attempting to kick ${found.length} users... keep your eye on this message!`); - - ban_user(0, found, this.client.users, sent, message); - - return null; - } -} - -async function ban_user(index, found, users, sent, message) { - - var user = await users.fetch(found[index]) - .catch(err => sent.edit(sent.content += `\n**Error** ${err.name}: \`${err.message} ${found[index]}\``)) - - if (user.tag) { - - try { - if (user.id === this.client.user.id) return sent.edit(sent.content += `\nPlease don't kick me!`); - if (user.id === message.author.id) return sent.edit(sent.content += `\nDon't kick yourself!`); - if (message.guild.member(user).highestRole.calculatedPosition > message.member.highestRole.calculatedPosition - 1) return sent.edit(sent.content += `\n**${user.tag}**'s roles are too high to be kicked!`); - if (!message.guild.member(user).kickable) return sent.edit(sent.content += `\n**${user.tag}**'s roles are too high to be kicked!`); - - message.guild.ban(found[index], { days: 7, reason: `responsible: ${message.author.tag}` }).catch(err => sent.edit(sent.content += `\nError trying to kick **${user.tag}** \`(${user.id})\`!`)); - sent.edit(sent.content += `\nKicked **${user.tag}** \`(${user.id})\``); - } catch (err) { - sent.edit(sent.content += `\nError trying to kick **${user.tag}** \`(${user.id})\`!`) - } - } - - if (index < found.length - 1) ban_user(index + 1, found, users, sent, message); - else sent.edit(sent.content += `\n__Finished bulk kick!__`) - - return null; -} \ No newline at end of file diff --git a/Komugari-master/commands/moderation/delete.js b/Komugari-master/commands/moderation/delete.js deleted file mode 100644 index a210311..0000000 --- a/Komugari-master/commands/moderation/delete.js +++ /dev/null @@ -1,186 +0,0 @@ -const { Command } = require('../../commando'); - -const ImageRegex = /(?:([^:/?#]+):)?(?:\/\/([^\/?#]*))?([^?#]*\.(?:png|jpe?g|gifv?|webp|bmp|tiff|jfif))(?:\?([^#]*))?(?:#(.*))?/gi; - -module.exports = class DeleteCommand extends Command { - constructor(client) { - super(client, { - name: 'delete', - aliases: ['slowprune', 'sd', 'delet', 'slowdelete'], - group: 'moderation', - memberName: 'delete', - description: 'Deletes up to 99 messages from the current channel the slow way!', - details: 'Even if the messages are over 2 weeks old!', - guildOnly: true, - clientPermissions: ['MANAGE_MESSAGES'], - userPermissions: ['MANAGE_MESSAGES'], - examples: ['~delete [1-100] '], - throttling: { - usages: 1, - duration: 10 - }, - args: [{ - key: 'count', - label: 'messages to be deleted', - prompt: 'Please provide me a set number of messages to prune!', - type: 'integer', - validate: count => { - if (count < 100 && count > 0) return true; - return 'I can\'t delete more than 99 messages at once!'; - } - }, - { - key: 'type', - label: 'type of messages deleted', - prompt: 'Please provide me a valid type of message to prune!', - type: 'string', - default: "all", - validate: base => { - if (['all', 'images', 'pics', 'image', 'bots', 'bot', 'codeblocks', 'code', 'attachments', 'attachment', 'files', 'file', 'embeds', 'embed', 'me'].includes(base.toLowerCase())) return true; - return 'Please enter a valid type of message! `all` `images` `bots` `codeblocks` `embeds`'; - }, - } - ] - }); - } - - async run(message, args) { - const { count, type } = args; - - if (type == 'all') { - try { - const messages = await message.channel.messages.fetch({ limit: count }); - await Promise.all(messages.map(m => m.delete())) - return message.channel.send(`🍇 | **${message.author.username}**, successfully deleted ${messages.size} ${messages.size == 1 ? 'message!' : 'messages!'}`) - - } catch (err) { - console.log(err) - return message.channel.send('❎ | These messages are too old to be deleted! I can only delete messages within two weeks!'); - - } - } - - if (type == 'images' || type == 'pics' || type == 'image') { - try { - const messages = await message.channel.messages.fetch({ - limit: count, - before: message.id - }) - - const attachments = messages.filter(m => ImageRegex.test(m.content)) - const urls = messages.filter(m => m.attachments.size > 0) - - const flushable = attachments.concat(urls) - - await Promise.all(flushable.map(m => m.delete())) - if (flushable.size == 0) return message.channel.send(`🍇 | **${message.author.username}**, there were no images to prune in the last ${count} messages!`); - - const m = await message.channel.send(`🍇 | **${message.author.username}**, successfully deleted **${flushable.size}** ${flushable.size == 1 ? 'image!' : 'images!'}`); - - return null; - } catch (err) { - console.log(err) - return message.channel.send('❎ | These messages are too old to be deleted! I can only delete messages within two weeks!'); - - } - - } - - if (type == 'bots' || type == 'bot') { - try { - const messages = await message.channel.messages.fetch({ - limit: count, - before: message.id - }) - const flushable = messages.filter(m => m.author.bot) - await Promise.all(flushable.map(m => m.delete())) - if (flushable.size == 0) return message.channel.send(`🍇 | **${message.author.username}**, there were no bot messages to prune in the last ${count} messages!`) - - const m = await message.channel.send(`🍇 | **${message.author.username}**, successfully deleted **${flushable.size}** ${flushable.size == 1 ? 'bot message!' : 'bot messages!'}`); - - return null; - - } catch (err) { - console.log(err) - return message.channel.send('❎ | These messages are too old to be deleted! I can only delete messages within two weeks!'); - - } - } - - if (type == 'codeblocks' || type == 'code') { - try { - const messages = await message.channel.messages.fetch({ - limit: count, - before: message.id - }) - const flushable = messages.filter(m => m.content.startsWith('```')); - await Promise.all(flushable.map(m => m.delete())) - const m = await message.channel.send(`🍇 | **${message.author.username}**, successfully deleted **${flushable.size}** ${flushable.size == 1 ? 'codeblock!' : 'codeblocks!'}`); - - return null; - - } catch (err) { - console.log(err) - return message.channel.send('❎ | These messages are too old to be deleted! I can only delete messages within two weeks!'); - - } - } - - if (type == 'attachments' || type == 'attachment' || type == 'files' || type == 'file') { - try { - const messages = await message.channel.messages.fetch({ - limit: count, - before: message.id - }) - const flushable = messages.filter(m => m.attachments.length > 0) - await Promise.all(flushable.map(m => m.delete())) - const m = await message.channel.send(`🍇 | **${message.author.username}**, successfully deleted **${flushable.size}** ${flushable.size == 1 ? 'attachment!' : 'attachments!'}`); - - return null; - - } catch (err) { - console.log(err) - return message.channel.send('❎ | These messages are too old to be deleted! I can only delete messages within two weeks!'); - - } - } - - if (type == 'embeds' || type == 'embed') { - try { - const messages = await message.channel.messages.fetch({ - limit: count, - before: message.id - }) - const flushable = messages.filter(m => m.embeds.length > 0) - await Promise.all(flushable.map(m => m.delete())) - const m = await message.channel.send(`🍇 | **${message.author.username}**, successfully deleted **${flushable.size}** ${flushable.size == 1 ? 'embed!' : 'embeds!'}`); - - return null; - - } catch (err) { - console.log(err) - return message.channel.send('❎ | These messages are too old to be deleted! I can only delete messages within two weeks!'); - - } - } - - if (type == 'me') { - try { - const messages = await message.channel.messages.fetch({ - limit: count, - before: message.id - }) - const flushable = messages.filter(m => m.id == message.author.id) - await Promise.all(flushable.map(m => m.delete())) - const m = await message.channel.send(`🍇 | **${message.author.username}**, successfully deleted **${flushable.size}** of your messages!`); - - return null; - - } catch (err) { - console.log(err) - return message.channel.send('❎ | These messages are too old to be deleted! I can only delete messages within two weeks!'); - - } - } - } -}; \ No newline at end of file diff --git a/Komugari-master/commands/moderation/delrole.js b/Komugari-master/commands/moderation/delrole.js deleted file mode 100644 index 32b2e06..0000000 --- a/Komugari-master/commands/moderation/delrole.js +++ /dev/null @@ -1,41 +0,0 @@ -const { Command } = require('../../commando'); - -module.exports = class DelRoleCommand extends Command { - constructor(client) { - super(client, { - name: 'delrole', - group: 'moderation', - aliases: ['rmrole', 'deleterole', 'remrole', 'drole', 'dr'], - memberName: 'delrole', - clientPermissions: ['MANAGE_ROLES'], - userPermissions: ['MANAGE_ROLES'], - description: 'Removed a role from a member!', - examples: ['~delrole [name] [role]'], - guildOnly: true, - args: [{ - key: 'member', - prompt: 'Please provide me a member to remove the role from!', - type: 'member' - }, - { - key: 'role', - prompt: 'Please provide me a role to remove!', - type: 'role' - } - ] - }); - } - - async run(message, args) { - const { member, role } = args; - if (!member.roles.has(role.id)) return message.channel.send(`❎ | **${member.displayName}** does not have have the role **${role.name}**!`) - - - try { - await member.removeRole(role) - return message.channel.send(`✅ | **${member.displayName}** no longer has the role **${role.name}**!`); - } catch (err) { - return message.channel.send(`❎ | **${member.displayName}** does not have the ${role.name} role!`) - } - }; -}; \ No newline at end of file diff --git a/Komugari-master/commands/moderation/hackban.js b/Komugari-master/commands/moderation/hackban.js deleted file mode 100644 index 5492b3a..0000000 --- a/Komugari-master/commands/moderation/hackban.js +++ /dev/null @@ -1,66 +0,0 @@ -const { Command } = require('../../commando'); - - -module.exports = class BanCommand extends Command { - constructor(client) { - super(client, { - name: 'hackban', - aliases: ['hb', 'banid'], - group: 'moderation', - memberName: 'hackban', - guildOnly: true, - clientPermissions: ['BAN_MEMBERS'], - userPermissions: ['BAN_MEMBERS'], - description: 'Bans the given user ID, even if they\'re not in the server!', - examples: ['~softban [userID] [reason]'], - throttling: { - usages: 1, - duration: 15 - }, - args: [{ - key: 'member', - prompt: 'Please provide me a user ID to hackban!', - type: 'string', - validate: member => { - if (/[0-9]+$/g.test(member) && member.length === 18) return true; - return 'Invalid user ID!'; - } - }, - { - key: 'reason', - prompt: 'Please provide me a reason to hackban this user!', - type: 'string', - validate: reason => { - if (reason.length < 140) return true; - return 'Reason must be under 140 characters!'; - } - } - ] - }); - } - - async run(message, args) { - const { member, reason } = args; - - if (member === this.client.user.id) return message.channel.send('Please don\'t hackban me...!'); - if (member === message.author.id) return message.channel.send('I wouldn\'t dare hackban you...!'); - - this.client.users.fetch(member).then(async usr => { - await message.channel.send(`Are you sure you want to ban **${usr.tag}**? \`\`(y/n)\`\``); - const msgs = await message.channel.awaitMessages(res => res.author.id === message.author.id, { - max: 1, - time: 30000 - }); - - if (!msgs.size || !['y', 'yes'].includes(msgs.first().content.toLowerCase())) return message.channel.send('Cancelled command!'); - if (['n', 'no'].includes(msgs.first().content.toLowerCase())) return message.channel.send('Cancelled command!') - - await message.guild.ban(member, { - reason: `${message.author.tag}: ${reason}` - }); - return await message.channel.send(`Successfully banned **${usr.tag}**! 👋`); - }) - - - } -} \ No newline at end of file diff --git a/Komugari-master/commands/moderation/kick.js b/Komugari-master/commands/moderation/kick.js deleted file mode 100644 index 9464b1c..0000000 --- a/Komugari-master/commands/moderation/kick.js +++ /dev/null @@ -1,65 +0,0 @@ -const { Command } = require('../../commando'); - - -module.exports = class KickCommand extends Command { - constructor(client) { - super(client, { - name: 'kick', - group: 'moderation', - memberName: 'kick', - guildOnly: true, - clientPermissions: ['KICK_MEMBERS'], - userPermissions: ['KICK_MEMBERS'], - description: 'Kicks the given user and DMs them the reason!', - examples: ['~kick [user] [reason]'], - throttling: { - usages: 1, - duration: 15 - }, - args: [{ - key: 'member', - prompt: 'Please provide me a user to kick!', - type: 'member' - }, - { - key: 'reason', - prompt: 'Please provide me a reason to kick this member!', - type: 'string', - default: 'none', - validate: reason => { - if (reason.length < 140) return true; - return 'Reason must be under 140 characters!'; - } - } - ] - }); - } - - async run(message, args) { - const { member, reason } = args; - - if (member.id === this.client.user.id) return message.channel.send('Please don\'t kick me...!'); - if (member.id === message.author.id) return message.channel.send('I wouldn\'t dare kick you...!'); - if (member.highestRole.calculatedPosition > message.member.highestRole.calculatedPosition - 1) return message.channel.send(`❎ | You can't kick **${member.user.username}**! Their position is higher than you!`); - if (!member.kickable) return message.channel.send(`❎ | I can't kick **${member.user.username}**! Their role is higher than mine!`); - - await message.channel.send(`Are you sure you want to kick **${member.user.tag}**? \`(y/n)\``); - const msgs = await message.channel.awaitMessages(res => res.author.id === message.author.id, { - max: 1, - time: 30000 - }); - - if (!msgs.size || !['y', 'yes'].includes(msgs.first().content.toLowerCase())) return message.channel.send('Cancelled command!'); - if (['n', 'no'].includes(msgs.first().content.toLowerCase())) return message.channel.send('Cancelled command!') - - try { - await member.send(`You were kicked from **${message.guild.name}** by **${message.author.tag}**!\n\**Reason:** ${reason}`); - } catch (err) { - await message.channel.send(`❎ | **${message.author.username}**, failed to Send DM to **${member}**! \`${err}\``); - } - - await member.kick(`${message.author.tag}: ${reason}`); - return message.channel.send(`**${message.author.username}**, successfully kicked **${member.user.tag}**! 👋`); - - } -} \ No newline at end of file diff --git a/Komugari-master/commands/moderation/massadd.js b/Komugari-master/commands/moderation/massadd.js deleted file mode 100644 index 180148a..0000000 --- a/Komugari-master/commands/moderation/massadd.js +++ /dev/null @@ -1,37 +0,0 @@ -const { Command } = require('../../commando'); - - -module.exports = class MassAddCommand extends Command { - constructor(client) { - super(client, { - name: 'massadd', - guildOnly: true, - aliases: ['ma', 'addroleall', 'roleall'], - group: 'moderation', - clientPermissions: ['MANAGE_ROLES'], - userPermissions: ['MANAGE_ROLES'], - memberName: 'massadd', - description: 'Adds the role to everyone on the server!', - details: 'Why..would you want to do that!!! Also this command will take a long time...', - examples: ['~massadd [role]'], - throttling: { - usages: 1, - duration: 60 - }, - args: [{ - key: 'role', - prompt: 'Please provide me a role to add!', - type: 'role' - }] - }); - } - - async run(message, args) { - const { role } = args; - const members = await message.guild.members.fetch() - const msg = await message.channel.send(`🔄 | Adding the **${role.name}** role to **${members.size}** members...this might take a while...`) - await members.forEach(m => m.addRole(role)) - - msg.delete() - } -} \ No newline at end of file diff --git a/Komugari-master/commands/moderation/massrem.js b/Komugari-master/commands/moderation/massrem.js deleted file mode 100644 index 92d6371..0000000 --- a/Komugari-master/commands/moderation/massrem.js +++ /dev/null @@ -1,36 +0,0 @@ -const { Command } = require('../../commando'); - - -module.exports = class MassRemCommand extends Command { - constructor(client) { - super(client, { - name: 'massrem', - guildOnly: true, - aliases: ['mr', 'remroleall', 'remroleall'], - group: 'moderation', - memberName: 'massrem', - clientPermissions: ['MANAGE_ROLES'], - userPermissions: ['MANAGE_ROLES'], - description: 'Removes the role from everyone on the server!', - details: 'Why..would you want to do that!!! Also this command will take a long time...', - examples: ['~massrem [role]'], - throttling: { - usages: 1, - duration: 60 - }, - args: [{ - key: 'role', - prompt: 'Please provide me a role to remove!', - type: 'role' - }] - }); - } - - async run(message, args) { - const { role } = args; - const members = await message.guild.members.fetch() - await message.channel.send(`🔄 | Removing the **${role.name}** role from **${members.size}** members...this might take a while...`) - await members.forEach(m => m.removeRole(role)) - - } -} \ No newline at end of file diff --git a/Komugari-master/commands/moderation/mute.js b/Komugari-master/commands/moderation/mute.js deleted file mode 100644 index 9892392..0000000 --- a/Komugari-master/commands/moderation/mute.js +++ /dev/null @@ -1,58 +0,0 @@ -const { Command } = require('../../commando'); - - -module.exports = class MuteCommand extends Command { - constructor(client) { - super(client, { - name: 'mute', - aliases: ['deafen', 'shutup', 'silent', 'shh', 'shut'], - group: 'moderation', - memberName: 'mute', - guildOnly: true, - clientPermissions: ['MANAGE_CHANNELS', 'MANAGE_MESSAGES'], - userPermissions: ['MANAGE_CHANNELS', 'MANAGE_MESSAGES'], - description: 'Mutes the given user in this channel!', - examples: ['~mute [user]'], - throttling: { - usages: 1, - duration: 15 - }, - args: [{ - key: 'member', - prompt: 'Please provide me a user to mute!', - type: 'member' - }] - }); - } - - async run(message, args) { - const { member } = args; - - if (member.id === this.client.user.id) return message.channel.send('Please don\'t mute me...!'); - if (member.id === message.author.id) return message.channel.send('I wouldn\'t dare mute you...!'); - if (member.highestRole.calculatedPosition > message.member.highestRole.calculatedPosition - 1) { - return message.channel.send(`❎ | You can't mute **${member.user.username}**! Their position is higher than you!`); - } - if (!member.bannable) return message.channel.send(`❎ | I can't mute **${member.user.username}**! Their role is higher than mine!`); - - await message.channel.send(`Are you sure you want to mute **${member.user.tag}** in **${message.channel.name}**? \`\`(y/n)\`\``); - const msgs = await message.channel.awaitMessages(res => res.author.id === message.author.id, { - max: 1, - time: 30000 - }); - if (!msgs.size || !['y', 'yes'].includes(msgs.first().content.toLowerCase())) return message.channel.send('Cancelled command!'); - if (['n', 'no'].includes(msgs.first().content.toLowerCase())) return message.channel.send('Cancelled command!') - - try { - await message.channel.overwritePermissions(member, { - SEND_MESSAGES: false, - ADD_REACTIONS: false - }) - } catch (err) { - await message.channel.send(`❎ | **${message.author.username}**, there was an error trying to mute **${member}**! \`${err}\``); - } - - return await message.channel.send(`**${message.author.username}**, successfully muted **${member.user.tag}** in **${message.channel.name}**! 🙊`); - - } -} \ No newline at end of file diff --git a/Komugari-master/commands/moderation/nickname.js b/Komugari-master/commands/moderation/nickname.js deleted file mode 100644 index c77ddfa..0000000 --- a/Komugari-master/commands/moderation/nickname.js +++ /dev/null @@ -1,39 +0,0 @@ -const { Command } = require('../../commando'); - -module.exports = class NickCommand extends Command { - constructor(client) { - super(client, { - name: 'nickname', - group: 'moderation', - aliases: ['nick'], - memberName: 'nickname', - clientPermissions: ['MANAGE_NICKNAMES'], - userPermissions: ['MANAGE_NICKNAMES'], - description: 'Assigns a nickname to a member! Use "clear"or leave it blank to remove the nickname!', - examples: ['~nickname [user] [name/clear]'], - guildOnly: true, - args: [{ - key: 'member', - prompt: 'Please provide me a member to assign nicknames for!', - type: 'member' - }, - { - key: 'nickname', - prompt: 'Please provide me a nickname to assign!', - default: 'clear', - type: 'string' - } - ] - }); - } - - async run(message, args) { - const { member, nickname } = args; - if (member.highestRole.calculatedPosition > message.member.highestRole.calculatedPosition - 1) { - return message.channel.send(`❎ | You can't change **${member.user.username}**'s nickname! Their position is higher than you!`); - } - if (!member.bannable) return message.channel.send(`❎ | I can't change **${member.user.username}**'s nickname! Their role is higher than mine!`); - - return await nickname !== 'clear' ? member.setNickname(nickname).then(() => message.say(`The nickname **${nickname}** has been assigned to **${member.user.username}**!`)) : member.setNickname('').then(() => message.say(`**${member.displayName}**'s nickname has been cleared!`)); - }; -}; \ No newline at end of file diff --git a/Komugari-master/commands/moderation/nuke.js b/Komugari-master/commands/moderation/nuke.js deleted file mode 100644 index 8c28a61..0000000 --- a/Komugari-master/commands/moderation/nuke.js +++ /dev/null @@ -1,120 +0,0 @@ -const { Command } = require('../../commando'); -const { stripIndents } = require('common-tags'); - -module.exports = class NukeCommand extends Command { - constructor(client) { - super(client, { - name: 'nuke', - aliases: ['cybernuke'], - group: 'moderation', - memberName: 'nuke', - clientPermissions: ['ADMINISTRATOR'], - userPermissions: ['BAN_MEMBERS'], - description: 'Bans all members that have joined recently, with new accounts!', - details: 'Useful for servers under constant raiding!', - guildOnly: true, - examples: ['~nuke [join age] [account age]'], - args: [{ - key: 'join', - label: 'member age', - prompt: 'how old (in minutes) should a member be for the nuke to ignore them (server join date)?', - type: 'float', - min: 0.1, - max: 120 - }, - { - key: 'age', - label: 'account age', - prompt: 'how old (in minutes) should a member\'s account be for the nuke to ignore them (account age)?', - type: 'float', - min: 0.1 - } - ] - }); - } - - hasPermission(message) { - return this.client.isOwner(message.author) || message.member.hasPermission('ADMINISTRATOR'); - } - - async run(message, { age, join }) { - const statusMsg = await message.channel.send('Calculating targeting parameters for cybernuke...'); - await message.guild.members.fetch(); - - const memberCutoff = Date.now() - (join * 60000); - const ageCutoff = Date.now() - (age * 60000); - const members = message.guild.members.filter( - mem => mem.joinedTimestamp > memberCutoff && mem.user.createdTimestamp > ageCutoff - ); - const booleanType = this.client.registry.types.get('boolean'); - - await statusMsg.edit(`Cybernuke will strike ${members.size} members; proceed?`); - let response; - let statusMsg2; - - while (!statusMsg2) { - const msgs = await message.channel.awaitMessages(res => res.author.id === message.author.id, { - max: 1, - time: 15000 - }); - - if (!msgs.size || !['y', 'yes'].includes(msgs.first().content.toLowerCase())) return message.channel.send('Cancelled command!'); - if (['n', 'no'].includes(msgs.first().content.toLowerCase())) return message.channel.send('Cancelled command!') - - statusMsg2 = await message.channel.send('🚀 | Launching cybernuke...!'); - } - /* eslint-enable no-await-in-loop */ - - const fatalities = []; - const survivors = []; - const promises = []; - - for (const member of members.values()) { - promises.push( - member.send(stripIndents ` - Sorry, but you've been automatically targetted by the cybernuke in the **${message.guild.name}** server! - This means that you have been banned, likely in the case of a server raid! - Please contact them if you believe this ban to be in error! \`(${message.author.tag})\` - `).catch('ok') - .then(() => member.ban()) - .then(() => { - fatalities.push(member); - }) - .catch(err => { - console.log(err); - survivors.push({ - member: member.id, - error: err - }); - }) - .then(() => { - if (members.size <= 5) return; - if (promises.length % 5 === 0) { - statusMsg2.edit(`🚀 | Launching cybernuke (${Math.round(promises.length / members.size * 100)}%)...`); - } - }) - ); - } - - await Promise.all(promises); - await statusMsg2.edit('Cybernuke impact confirmed. Casualty report incoming...'); - await message.channel.send(stripIndents ` - __**Fatalities**__ - ${fatalities.length > 0 ? stripIndents` - ${fatalities.length} confirmed KIA. - - ${fatalities.map(fat => `**-** ${fat.displayName} \`(${fat.id})\``).join('\n')} - ` : 'None'} - - - ${survivors.length > 0 ? stripIndents` - __**Survivors**__ - ${survivors.length} left standing. - - ${survivors.map(srv => `**-** ${srv.member.displayName} (${srv.member.id}): \`${srv.error}\``).join('\n')} - ` : ''} - `, { split: true }); - - return null; - } -}; \ No newline at end of file diff --git a/Komugari-master/commands/moderation/prune.js b/Komugari-master/commands/moderation/prune.js deleted file mode 100644 index 9a60a32..0000000 --- a/Komugari-master/commands/moderation/prune.js +++ /dev/null @@ -1,217 +0,0 @@ -const { Command } = require('../../commando'); - -const ImageRegex = /(?:([^:/?#]+):)?(?:\/\/([^\/?#]*))?([^?#]*\.(?:png|jpe?g|gifv?|webp|bmp|tiff|jfif))(?:\?([^#]*))?(?:#(.*))?/gi; -const LinkRegex = /[-a-zA-Z0-9@:%_\+.~#?&//=]{2,256}\.[a-z]{2,4}\b(\/[-a-zA-Z0-9@:%_\+.~#?&//=]*)?/gi; - -module.exports = class PruneCommand extends Command { - constructor(client) { - super(client, { - name: 'prune', - aliases: ['purge', 'bulkdelete', 'flush'], - group: 'moderation', - memberName: 'prune', - description: 'Deletes up to 99 messages from the current channel.', - guildOnly: true, - clientPermissions: ['MANAGE_MESSAGES'], - userPermissions: ['MANAGE_MESSAGES'], - examples: ['~prune [1-100] '], - throttling: { - usages: 1, - duration: 10 - }, - args: [{ - key: 'count', - label: 'messages to be pruned', - prompt: 'Please provide me a set number of messages to prune!', - type: 'integer', - validate: count => { - if (count < 100 && count > 0) return true; - return 'I can\'t delete more than 99 messages at once!'; - } - }, - { - key: 'type', - label: 'type of messages pruned', - prompt: 'Please provide me a valid type of message to prune!', - type: 'string', - default: "all", - validate: base => { - if (['all', 'images', 'pics', 'image', 'bots', 'bot', 'codeblocks', 'code', 'attachments', 'attachment', 'files', 'file', 'embeds', 'embed', 'me', 'links', 'link'].includes(base.toLowerCase())) return true; - return 'Please enter a valid type of message! `all` `images` `links` `attachments` `bots` `codeblocks` `embeds` `me`'; - }, - } - ] - }); - } - - async run(message, args) { - const { count, type } = args; - - if (type == 'all') { - try { - const messages = await message.channel.messages.fetch({ limit: count }); - await message.channel.bulkDelete(messages.size, true); - return message.channel.send(`🍇 | **${message.author.username}**, successfully pruned ${messages.size} ${messages.size == 1 ? 'message!' : 'messages!'}`) - - } catch (err) { - console.log(err) - return message.channel.send('❎ | These messages are too old to be deleted! I can only delete messages within two weeks!'); - - } - } - - if (type == 'images' || type == 'pics' || type == 'image') { - try { - const messages = await message.channel.messages.fetch({ - limit: count, - before: message.id - }) - - const attachments = messages.filter(m => ImageRegex.test(m.content)) - const urls = messages.filter(m => m.attachments.size > 0) - - const flushable = attachments.concat(urls) - - if (flushable.size == 0) return message.channel.send(`🍇 | **${message.author.username}**, there were no images to prune in the last ${count} messages!`); - - await message.channel.bulkDelete(flushable) - - const m = await message.channel.send(`🍇 | **${message.author.username}**, successfully pruned **${flushable.size}** ${flushable.size == 1 ? 'image!' : 'images!'}`); - - return null; - } catch (err) { - console.log(err) - return message.channel.send('❎ | These messages are too old to be deleted! I can only delete messages within two weeks!'); - - } - - } - - if (type == 'bots' || type == 'bot') { - try { - const messages = await message.channel.messages.fetch({ - limit: count, - before: message.id - }) - const flushable = messages.filter(m => m.author.bot) - await message.channel.bulkDelete(flushable) - if (flushable.size == 0) return message.channel.send(`🍇 | **${message.author.username}**, there were no bot messages to prune in the last ${count} messages!`) - - const m = await message.channel.send(`🍇 | **${message.author.username}**, successfully pruned **${flushable.size}** ${flushable.size == 1 ? 'bot message!' : 'bot messages!'}`); - - return null; - - } catch (err) { - console.log(err) - return message.channel.send('❎ | These messages are too old to be deleted! I can only delete messages within two weeks!'); - - } - } - - if (type == 'codeblocks' || type == 'code') { - try { - const messages = await message.channel.messages.fetch({ - limit: count, - before: message.id - }) - const flushable = messages.filter(m => m.content.startsWith('```')); - - if (flushable.size == 0) return message.channel.send(`🍇 | **${message.author.username}**, there were no codeblocks to prune in the last ${count} messages!`); - - await message.channel.bulkDelete(flushable) - const m = await message.channel.send(`🍇 | **${message.author.username}**, successfully pruned **${flushable.size}** ${flushable.size == 1 ? 'codeblock!' : 'codeblocks!'}`); - - return null; - - } catch (err) { - console.log(err) - return message.channel.send('❎ | These messages are too old to be deleted! I can only delete messages within two weeks!'); - - } - } - - if (type == 'attachments' || type == 'attachment' || type == 'files' || type == 'file') { - try { - const messages = await message.channel.messages.fetch({ - limit: count, - before: message.id - }) - const flushable = messages.filter(m => m.attachments.length > 0) - if (flushable.size == 0) return message.channel.send(`🍇 | **${message.author.username}**, there were no attachments to prune in the last ${count} messages!`); - - await message.channel.bulkDelete(flushable) - const m = await message.channel.send(`🍇 | **${message.author.username}**, successfully pruned **${flushable.size}** ${flushable.size == 1 ? 'attachment!' : 'attachments!'}`); - - return null; - - } catch (err) { - console.log(err) - return message.channel.send('❎ | These messages are too old to be deleted! I can only delete messages within two weeks!'); - - } - } - - if (type == 'embeds' || type == 'embed') { - try { - const messages = await message.channel.messages.fetch({ - limit: count, - before: message.id - }) - const flushable = messages.filter(m => m.embeds.length > 0) - if (flushable.size == 0) return message.channel.send(`🍇 | **${message.author.username}**, there were no embeds to prune in the last ${count} messages!`); - - await message.channel.bulkDelete(flushable) - const m = await message.channel.send(`🍇 | **${message.author.username}**, successfully pruned **${flushable.size}** ${flushable.size == 1 ? 'embed!' : 'embeds!'}`); - - return null; - - } catch (err) { - console.log(err) - return message.channel.send('❎ | These messages are too old to be deleted! I can only delete messages within two weeks!'); - - } - } - - if (type == 'me') { - try { - const messages = await message.channel.messages.fetch({ - limit: count, - before: message.id - }) - const flushable = messages.filter(m => m.id == message.author.id) - if (flushable.size == 0) return message.channel.send(`🍇 | **${message.author.username}**, there were no messages from you to prune in the last ${count} messages!`); - - await message.channel.bulkDelete(flushable) - const m = await message.channel.send(`🍇 | **${message.author.username}**, successfully pruned **${flushable.size}** of your messages!`); - - return null; - - } catch (err) { - console.log(err) - return message.channel.send('❎ | These messages are too old to be deleted! I can only delete messages within two weeks!'); - - } - } - - if (type == 'link' || type == 'links') { - try { - const messages = await message.channel.messages.fetch({ - limit: count, - before: message.id - }) - const flushable = messages.filter(m => LinkRegex.test(m.content)) - if (flushable.size == 0) return message.channel.send(`🍇 | **${message.author.username}**, there were no links to prune in the last ${count} messages!`); - - await message.channel.bulkDelete(flushable) - const m = await message.channel.send(`🍇 | **${message.author.username}**, successfully pruned **${flushable.size}** ${flushable.size == 1 ? 'link!' : 'links!'}`); - - return null; - - } catch (err) { - console.log(err) - return message.channel.send('❎ | These messages are too old to be deleted! I can only delete messages within two weeks!'); - - } - } - } -}; \ No newline at end of file diff --git a/Komugari-master/commands/moderation/pruneuser.js b/Komugari-master/commands/moderation/pruneuser.js deleted file mode 100644 index e11cc7b..0000000 --- a/Komugari-master/commands/moderation/pruneuser.js +++ /dev/null @@ -1,55 +0,0 @@ -const { Command } = require('../../commando'); - -module.exports = class PruneUserCommand extends Command { - constructor(client) { - super(client, { - name: 'pruneuser', - guildOnly: true, - aliases: ['pruneu', 'pu'], - group: 'moderation', - clientPermissions: ['MANAGE_MESSAGES'], - userPermissions: ['MANAGE_MESSAGES'], - memberName: 'pruneuser', - description: 'Prunes a specified number of messaged from a specific user!', - examples: ['~prune [user] [count]'], - throttling: { - usages: 1, - duration: 10 - }, - args: [{ - key: 'user', - label: 'which user to prune', - prompt: 'Please provide me a user to prune!', - type: 'user' - }, - { - key: 'count', - label: 'messages to be pruned', - prompt: 'Please provide me a set number of messages to prune!', - type: 'integer', - },] - }); - } - - async run(message, args) { - const { user, count } = args; - - try { - const messages = await message.channel.messages.fetch({ - limit: count, - before: message.id - }) - const flushable = messages.filter(m => m.author.id == user.id) - if (flushable.size == 0) return message.channel.send(`🍇 | **${message.author.username}**, **${user.username}** did not send any messages in the last ${count} messages!`); - - await message.channel.bulkDelete(flushable) - const m = await message.channel.send(`🍇 | **${message.author.username}**, successfully pruned ${flushable.size} ${flushable.size == 1 ? `message from **${user.username}**!` : `messages from **${user.username}**!`}`); - - return null; - - } catch (err) { - console.log(err) - return message.channel.send('❎ | These messages are too old to be deleted! I can only delete messages within two weeks!'); - } - } -} \ No newline at end of file diff --git a/Komugari-master/commands/moderation/pruneword.js b/Komugari-master/commands/moderation/pruneword.js deleted file mode 100644 index 7340868..0000000 --- a/Komugari-master/commands/moderation/pruneword.js +++ /dev/null @@ -1,62 +0,0 @@ -const { Command } = require('../../commando'); - - -module.exports = class PruneWordCommand extends Command { - constructor(client) { - super(client, { - name: 'pruneword', - aliases: ['purgew', 'prunew', 'filter', 'pw'], - group: 'moderation', - memberName: 'pruneword', - description: 'Deletes up to 99 messages containing a specific phrase!', - details: 'The word in the command must be all lowercase!', - guildOnly: true, - clientPermissions: ['MANAGE_MESSAGES'], - userPermissions: ['MANAGE_MESSAGES'], - examples: ['~prune [1-100] [word/phrase]'], - throttling: { - usages: 1, - duration: 10 - }, - args: [{ - key: 'count', - label: 'messages to be pruned', - prompt: 'Please provide me a set number of messages to prune!', - type: 'integer', - validate: count => { - if (count <= 100 && count > 0) return true; - return 'Please provide me a valid number between 1 and 100!'; - } - }, - { - key: 'inc', - label: 'the word included to be pruned', - prompt: 'Please provide me a word or phrase to prune!', - type: 'string' - } - ] - }); - } - - async run(message, args) { - const { count, inc } = args; - - try { - const messages = await message.channel.messages.fetch({ - limit: Math.min(count, 100), - before: message.id - }) - const flushable = messages.filter(m => m.content.toLowerCase().includes(inc)) - if (flushable.size == 0) return message.channel.send(`🍇 | **${message.author.username}**, there were no messages containing the word **${inc}** in the last ${count} messages!`); - await message.channel.bulkDelete(flushable) - - const m = await message.channel.send(`🍇 | **${message.author.username}**, successfully pruned ${flushable.size} ${flushable.size == 1 ? `message containing the word **${inc}**!` : `messages containing the word **${inc}**!`}`); - - return null; - } catch (err) { - console.log(err) - return message.channel.send('❎ | These messages are too old to be deleted! I can only delete messages within two weeks!'); - - } - } -}; \ No newline at end of file diff --git a/Komugari-master/commands/moderation/softban.js b/Komugari-master/commands/moderation/softban.js deleted file mode 100644 index e5f92c0..0000000 --- a/Komugari-master/commands/moderation/softban.js +++ /dev/null @@ -1,66 +0,0 @@ -const { Command } = require('../../commando'); -const { stripIndents } = require('common-tags'); - -module.exports = class SoftbanCommand extends Command { - constructor(client) { - super(client, { - name: 'softban', - aliases: ['softb'], - group: 'moderation', - memberName: 'softban', - description: 'Kicks a user and deletes all their messages in the past 7 days!', - guildOnly: true, - clientPermissions: ['BAN_MEMBERS'], - userPermissions: ['BAN_MEMBERS'], - args: [{ - key: 'member', - prompt: 'Please provide me a member to softban!', - type: 'member' - }, - { - key: 'reason', - prompt: 'Please set a reason for the softban!', - type: 'string', - default: 'none', - validate: reason => { - if (reason.length < 140) return true; - return 'Reason must be under 140 characters!'; - } - } - ] - }); - } - - async run(message, args) { - - const { member, reason } = args; - if (member.id === this.client.user.id) return message.channel.send('Please don\'t softban me...!'); - if (member.id === message.author.id) return message.channel.send('I wouldn\'t dare softban you...!'); - if (member.highestRole.calculatedPosition > message.member.highestRole.calculatedPosition - 1) { - return message.channel.send(`❎ | You can't softban **${member}**! Their position is higher than you!`); - } - if (!member.bannable) return message.channel.send(`❎ | I can't softban **${member}**! Their role is higher than mine!`); - - await message.channel.send(`Are you sure you want to softban **${member.user.tag}** \`(y/n)?\``); - const msgs = await message.channel.awaitMessages(res => res.author.id === message.author.id, { - max: 1, - time: 30000 - }); - - if (!msgs.size || !['y', 'yes'].includes(msgs.first().content.toLowerCase())) return message.channel.send('Cancelled command!'); - - try { - await member.send(`You were softbanned from **${message.guild.name}** by **${message.author.tag}**!\n\**Reason:** ${reason}`); - } catch (err) { - await message.channel.send(`❎ | **${message.author.username}**, failed to Send DM **${member}** the reason! \`${err}\``); - } - - await member.ban({ - days: 7, - reason: `${message.author.tag}: ${reason} (Softban)` - }); - - await message.guild.unban(member.user, 'Softban'); - return message.channel.send(`Successfully sofbanned **${member.user.tag}**! 👋`); - } -}; \ No newline at end of file diff --git a/Komugari-master/commands/moderation/unban.js b/Komugari-master/commands/moderation/unban.js deleted file mode 100644 index e5191b0..0000000 --- a/Komugari-master/commands/moderation/unban.js +++ /dev/null @@ -1,57 +0,0 @@ -const { Command } = require('../../commando'); - -module.exports = class UnBanCommand extends Command { - constructor(client) { - super(client, { - name: 'unban', - group: 'moderation', - memberName: 'unban', - description: 'Unbans the given member ID!', - details: 'haa.. it\'d be way too hard to go to the ban list!', - examples: ['~unban [member] [reason]'], - clientPermissions: ['BAN_MEMBERS'], - userPermissions: ['BAN_MEMBERS'], - guildOnly: true, - args: [{ - key: 'id', - prompt: 'Please provide me a user ID to unban!', - type: 'string', - validate: member => { - if (/[0-9]+$/g.test(member) && member.length === 18) return true; - return 'Invalid user ID!'; - } - }, - { - key: 'content', - prompt: 'Please provide me the reason for the unban!', - type: 'string', - default: 'none', - validate: reason => { - if (reason.length < 140) return true; - return 'Reason must be under 140 characters.'; - } - } - ] - }); - } - - async run(message, args) { - - const { id, reason } = args; - const bans = await message.guild.fetchBans(); - if (!bans.has(id)) return message.channel.send('This user is not banned in this server!') - const member = bans.get(id).user; - - await message.channel.send(`Are you sure you want to unban **${member.tag}** \`(y/n)\`?`); - const msgs = await message.channel.awaitMessages(res => res.author.id === message.author.id, { - max: 1, - time: 30000 - }); - - if (!msgs.size || !['y', 'yes'].includes(msgs.first().content.toLowerCase())) return msg.say('Aborting.'); - - await message.guild.unban(member, `${message.author.tag}: ${reason}`); - - return await message.channel.send(`Successfully unbanned **${member.tag}**! 👋`); - }; -} \ No newline at end of file diff --git a/Komugari-master/commands/moderation/unmute.js b/Komugari-master/commands/moderation/unmute.js deleted file mode 100644 index 3d61bd2..0000000 --- a/Komugari-master/commands/moderation/unmute.js +++ /dev/null @@ -1,56 +0,0 @@ -const { Command } = require('../../commando'); - - -module.exports = class UnMuteCommand extends Command { - constructor(client) { - super(client, { - name: 'unmute', - aliases: ['undeafen', 'speakup'], - group: 'moderation', - memberName: 'unmute', - guildOnly: true, - clientPermissions: ['MANAGE_CHANNELS', 'MANAGE_MESSAGES'], - userPermissions: ['MANAGE_CHANNELS', 'MANAGE_MESSAGES'], - description: 'Unmutes the given user in this channel!', - examples: ['~unmute [user]'], - throttling: { - usages: 1, - duration: 15 - }, - args: [{ - key: 'member', - prompt: 'Please provide me a user to unmute!', - type: 'member' - }] - }); - } - - async run(message, args) { - const { member } = args; - - if (member.highestRole.calculatedPosition > message.member.highestRole.calculatedPosition - 1) { - return message.channel.send(`❎ | You can't unmute **${member.user.username}**! Their position is higher than you!`); - } - if (!member.bannable) return message.channel.send(`❎ | I can't unmute **${member.user.username}**! Their role is higher than mine!`); - - await message.channel.send(`Are you sure you want to unmute **${member.user.tag}** in **${message.channel.name}**? \`\`(y/n)\`\``); - const msgs = await message.channel.awaitMessages(res => res.author.id === message.author.id, { - max: 1, - time: 30000 - }); - if (!msgs.size || !['y', 'yes'].includes(msgs.first().content.toLowerCase())) return message.channel.send('Cancelled command!'); - if (['n', 'no'].includes(msgs.first().content.toLowerCase())) return message.channel.send('Cancelled command!') - - try { - await message.channel.overwritePermissions(member, { - SEND_MESSAGES: true, - ADD_REACTIONS: true - }) - } catch (err) { - await message.channel.send(`❎ | **${message.author.username}**, there was an error trying to unmute **${member}**! \`${err}\``); - } - - return await message.channel.send(`**${message.author.username}**, successfully unmuted ${member.user.tag} in **${message.channel.name}**! 🙊`); - - } -} \ No newline at end of file diff --git a/Komugari-master/commands/owner/backdoor.js b/Komugari-master/commands/owner/backdoor.js deleted file mode 100644 index 3b8ec01..0000000 --- a/Komugari-master/commands/owner/backdoor.js +++ /dev/null @@ -1,55 +0,0 @@ -const { Command } = require('../../commando'); - -module.exports = class BackdoorCommand extends Command { - constructor(bot) { - super(bot, { - name: 'backdoor', - aliases: ['getinvite', 'getinv', 'forceinv', 'bd'], - group: 'owner', - memberName: 'backdoor', - description: 'Sends a server invite to the specified server. Only the developer can use this!', - examples: ['~backdoor [server ID]'], - args: [{ - key: 'guild', - label: 'guild', - prompt: 'What server would you like to backdoor?', - type: 'string' - }], - }); - } - - hasPermission(msg) { - return this.client.isOwner(msg.author); - } - - async run(message, args) { - - if (!message.guild) { - const getGuild = this.client.guilds.get(args.guild) - const toInv = getGuild.channels.first() - - const invite = toInv.createInvite({ - maxAge: 120, - maxUses: 1 - }).then(async invite => { - message.author.send(`Here's the invite link to **${getGuild.name}**!\n${invite}`) - }).catch(console.error) - - } else { - const getGuild = this.client.guilds.get(args.guild) - const toInv = getGuild.channels.first() - - const invite = toInv.createInvite({ - maxAge: 120, - maxUses: 1 - }).then(async invite => { - message.author.send(`Here's the invite link to **${getGuild.name}**!\n${invite}`) - message.channel.send('✅ | I\'ve sent the invite link to your DMs!') - }).catch(console.error) - } - } -}; - -process.on('unhandledRejection', err => { - console.error('Uncaught Promise Error: \n' + err.stack); -}); \ No newline at end of file diff --git a/Komugari-master/commands/owner/eval.js b/Komugari-master/commands/owner/eval.js deleted file mode 100644 index 8c9eeda..0000000 --- a/Komugari-master/commands/owner/eval.js +++ /dev/null @@ -1,133 +0,0 @@ -const util = require('util'); -const discord = require('discord.js'); -const tags = require('common-tags'); -const escapeRegex = require('escape-string-regexp'); -const { Command } = require('../../commando'); - -const nl = '!!NL!!'; -const nlPattern = new RegExp(nl, 'g'); - -module.exports = class EvalCommand extends Command { - constructor(client) { - super(client, { - name: 'eval', - group: 'owner', - memberName: 'eval', - description: 'Executes arbitrary JavaScript code!', - details: 'Only the bot owner may use this command!', - - args: [{ - key: 'script', - prompt: 'Please provide me some code to evaluate!', - type: 'string' - }] - }); - - this.lastResult = null; - } - - hasPermission(msg) { - return this.client.isOwner(msg.author); - } - - run(msg, args) { - - const message = msg; - const client = msg.client; - const objects = client.registry.evalObjects; - const lastResult = this.lastResult; - const doReply = val => { - if (val instanceof Error) { - msg.channel.send(`There was a callback error! \`${val}\``); - } else { - const result = this.makeResultMessages(val, process.hrtime(this.hrStart)); - if (Array.isArray(result)) { - for (const item of result) { - if (this.client.options.selfbot) msg.say(item); - else msg.channel.send(item); - } - } else { - msg.channel.send(result); - } - } - }; - - // Run the code and measure its execution time - let hrDiff; - try { - const hrStart = process.hrtime(); - this.lastResult = eval(args.script); - hrDiff = process.hrtime(hrStart); - } catch (err) { - return msg.channel.send(`❎ | **There was an error while evaluating!** \`${err}\``); - } - - // Prepare for callback time and respond - this.hrStart = process.hrtime(); - let response = this.makeResultMessages(this.lastResult, hrDiff, args.script, msg.editable); - if (msg.editable) { - if (response instanceof Array) { - if (response.length > 0) response = response.slice(1, response.length - 1); - for (const re of response) msg.say(re); - return null; - } else { - return msg.edit(response); - } - } else { - msg.delete() - const embed = new discord.MessageEmbed() - .setColor('#CEA5B7') - .setDescription(response); - return msg.channel.send({ embed }); - } - } - - makeResultMessages(result, hrDiff, input = null, editable = false) { - const inspected = util.inspect(result, { depth: 0 }) - .replace(nlPattern, '\n') - .replace(this.sensitivePattern, '--REDACTED--'); - const split = inspected.split('\n'); - const last = inspected.length - 1; - const prependPart = inspected[0] !== '{' && inspected[0] !== '[' && inspected[0] !== "'" ? split[0] : inspected[0]; - const appendPart = inspected[last] !== '}' && inspected[last] !== ']' && inspected[last] !== "'" ? - split[split.length - 1] : - inspected[last]; - const prepend = `\`\`\`javascript\n${prependPart}\n`; - const append = `\n${appendPart}\n\`\`\``; - if (input) { - return discord.splitMessage(tags.stripIndents` - ${editable ? ` - *Input* - \`\`\`javascript - ${input} - \`\`\`` : - ''} - **📥 Input** - \`\`\`javascript - ${input} - \`\`\` - **📤 Output** \`${hrDiff[0] > 0 ? `${(hrDiff[0]).toFixed(4)}s ` : ''}${(hrDiff[1] / 1000000).toFixed(4)}s\` - \`\`\`javascript - ${inspected} - \`\`\` - `, 1900, '\n', prepend, append); - } else { - return discord.splitMessage(tags.stripIndents` - **Callback executed after ${hrDiff[0] > 0 ? `${hrDiff[0]}s ` : ''}${hrDiff[1] / 1000000}s!** - \`\`\`javascript - ${inspected} - \`\`\` - `, 1900, '\n', prepend, append); - } - } - - get sensitivePattern() { - if(!this._sensitivePattern) { - const client = this.client; - let pattern = ''; - if(client.token) pattern += escapeRegex(client.token); - Object.defineProperty(this, '_sensitivePattern', { value: new RegExp(pattern, 'gi') }); - } - return this._sensitivePattern; - } -}; \ No newline at end of file diff --git a/Komugari-master/commands/owner/exec.js b/Komugari-master/commands/owner/exec.js deleted file mode 100644 index 9d2ad52..0000000 --- a/Komugari-master/commands/owner/exec.js +++ /dev/null @@ -1,63 +0,0 @@ -const { Command } = require('../../commando'); -const Discord = require('discord.js'); -const util = require("util"); -const child_process = require("child_process"); -const exec = util.promisify(child_process.exec); -const commonTags = require("common-tags"); - -module.exports = class ExecCommand extends Command { - constructor(client) { - super(client, { - name: 'exec', - guildOnly: true, - aliases: ['console', 'execute'], - group: 'owner', - memberName: 'exec', - description: 'Executes a command in the console!', - examples: ['~exec [command]'], - args: [{ - key: 'command', - prompt: 'Please provide me a command to execute!', - type: 'string' - }] - }); - } - - hasPermission(msg) { - return this.client.isOwner(msg.author); - } - - async run(message, args) { - const { command } = args; - - let hrDiff; - try { - const hrStart = process.hrtime(); - this.lastResult = exec(command) - hrDiff = process.hrtime(hrStart); - } catch (err) { - return msg.channel.send(`❎ | ** There was an error while executing!** \`${err}\``); - } - - this.hrStart = process.hrtime(); - const executed = await exec(command).catch((err) => err); - const input = `**📥 Input**\`\`\`bash\n${command}\n\`\`\`` - const output = executed.stdout ? `**📤 Output**\`\`\`bash\n${executed.stdout}\n\`\`\`` : ""; - - const error = executed.stderr ? `**📤 Error**\`\`\`bash\n${executed.stderr}\n\`\`\`` : ""; - - if (executed.stdout) { - console.log(executed.stdout) - } else { - console.log(executed.stderr) - } - - await message.delete(); - var time = hrDiff[0] > 0 ? `${(hrDiff[0]).toFixed(4)}s ` : '' + (hrDiff[1] / 1000000).toFixed(4) - const embed = new Discord.MessageEmbed() - .setColor('#CEA5B7') - .setDescription([input, output, error].join("\n")) - .setFooter(`${time}s`); - return message.channel.send({ embed }) - } -} \ No newline at end of file diff --git a/Komugari-master/commands/owner/fleave.js b/Komugari-master/commands/owner/fleave.js deleted file mode 100644 index f6d2f4f..0000000 --- a/Komugari-master/commands/owner/fleave.js +++ /dev/null @@ -1,54 +0,0 @@ -const { Command } = require('../../commando'); - -module.exports = class FLeaveCommand extends Command { - constructor(bot) { - super(bot, { - name: 'fleave', - aliases: ['forceleave', 'leaveguild', 'removeguild'], - group: 'owner', - memberName: 'fleave', - description: 'Leaves a guild!', - details: 'Only the bot owner can use this command!', - examples: ['~fleave 1234567890'], - - args: [{ - key: 'toLeave', - label: 'toLeave', - prompt: 'Please specify a guild to leave!', - type: 'string' - }, - { - key: 'reason', - label: 'reason', - prompt: 'For what reason am I leaving the server?', - type: 'string' - } - ], - }); - } - - hasPermission(message) { - return this.client.isOwner(message.author); - } - - async run(message, args) { - - let guild = this.client.guilds.get(args.toLeave) || 'woopsies' - if (guild == 'woopsies') return message.channel.send('That guild was not found! Please try again!') - - let reason = args.reason - const defaultChannel = guild.channels.find(c => c.permissionsFor(guild.me).has('SEND_MESSAGES')); - - try { - try { - defaultChannel.send(`👋 My developer has requested that I leave this server!\n\**Reason:** ${args.reason}`) - } catch (err) { - guild.owner.send(`👋 My developer has requested that I leave this server!\n\**Reason:** ${args.reason}`) - } - guild.leave() - return message.channel.send(`Successfully left the guild **${guild.name}**!`) - } catch (err) { - return message.channel.send(`There was an error leaving the specified guild! \`${err}\``) - } - } -}; \ No newline at end of file diff --git a/Komugari-master/commands/owner/reload.js b/Komugari-master/commands/owner/reload.js deleted file mode 100644 index 03bc3e9..0000000 --- a/Komugari-master/commands/owner/reload.js +++ /dev/null @@ -1,52 +0,0 @@ -const { Command } = require('../../commando'); -const stripIndents = require('common-tags') - -function disambiguation(items, label, property = 'name') { - const itemList = items.map(item => `"${(property ? item[property] : item).replace(/ /g, '\xa0')}"`).join(', '); - return `Multiple ${label} found, please be more specific!`; -} - -module.exports = class ReloadCommand extends Command { - constructor(client) { - super(client, { - name: 'reload', - aliases: ['reload-command', 'rl', 'load'], - group: 'owner', - memberName: 'reload', - description: 'Reloads a command or command group.', - details: 'This is an owner-only command!', - examples: ['~reload help'], - guarded: true, - - args: [{ - key: 'cmdOrGrp', - label: 'command/group', - prompt: 'Which command or group would you like to reload?', - validate: val => { - if (!val) return false; - const groups = this.client.registry.findGroups(val); - if (groups.length === 1) return true; - const commands = this.client.registry.findCommands(val); - if (commands.length === 1) return true; - if (commands.length === 0 && groups.length === 0) return false; - return `${commands.length > 1 ? disambiguation(commands, 'commands') : ''}\n${groups.length > 1 ? disambiguation(groups, 'groups') : ''}`; - }, - parse: val => this.client.registry.findGroups(val)[0] || this.client.registry.findCommands(val)[0] - }] - }); - } - - hasPermission(message) { - return this.client.isOwner(message.author); - } - - async run(message, args) { - args.cmdOrGrp.reload(); - if (args.cmdOrGrp.group) { - await message.channel.send(`Reloaded \`${args.cmdOrGrp.name}\` command!`); - } else { - await message.channel.send(`Reloaded all of the commands in the \`${args.cmdOrGrp.name}\` group!`); - } - return null; - } -}; \ No newline at end of file diff --git a/Komugari-master/commands/owner/saychannel.js b/Komugari-master/commands/owner/saychannel.js deleted file mode 100644 index 8dd790b..0000000 --- a/Komugari-master/commands/owner/saychannel.js +++ /dev/null @@ -1,42 +0,0 @@ -const { Command } = require('../../commando'); - -module.exports = class SayChannelCommand extends Command { - constructor(client) { - super(client, { - name: 'saychannel', - aliases: ['sc', 'send', 'portal', 'announce'], - group: 'owner', - memberName: 'saychannel', - description: 'This is an admin-only command', - examples: ['none'], - guildOnly: true, - throttling: { - usages: 1, - duration: 10 - } - }); - } - - async run(message) { - if (message.guild.id !== '198399488614727680') return message.channel.send(`This command can only be used in the owner's server.`); - if (!message.member.hasPermission('MANAGE_GUILD')) return message.channel.send('You cannot use this command!'); - - try { - let channelMessage = message.content.split(/\s+/g).slice(2).join(" "); - if (!channelMessage) return message.channel.send('Provide something for me to send.'); - let channelid = message.content.split(/\s+/g)[1] - let channel = this.client.channels.get(channelid) - channel.send(channelMessage); - - await message.react("🇸").catch(console.error); - await message.react("🇪").catch(console.error); - await message.react("🇳").catch(console.error); - await message.react("🇹").catch(console.error); - - return null; - - } catch (err) { - return message.channel.send(`❎ | **An error occurred while running this command!** \`${err}\``); - } - } -} \ No newline at end of file diff --git a/Komugari-master/commands/utility/github.js b/Komugari-master/commands/utility/github.js deleted file mode 100644 index 517f410..0000000 --- a/Komugari-master/commands/utility/github.js +++ /dev/null @@ -1,113 +0,0 @@ -const { Command } = require('../../commando'); -const Discord = require('discord.js'); -const snekfetch = require('snekfetch'); - -const MY_GIT = require('../../package').repository.replace(/^github:/, '') - -module.exports = class GitHubCommand extends Command { - constructor(client) { - super(client, { - name: 'github', - guildOnly: true, - aliases: ['git', 'source'], - group: 'utility', - memberName: 'github', - description: 'Finds a repository on GitHub!', - details: 'If none provided, returns my own repository instead!', - examples: ['~github '], - throttling: { - usages: 1, - duration: 5 - }, - args: [{ - key: 'repo', - label: 'repo', - prompt: 'Please provide me a repository to search for!', - type: 'string', - default: 'Mitorisia/Komugari' - }] - }); - } - - async run(message, args) { - args = args.repo - var searche = message.content.split(/\s+/g).slice(1) - - if (searche.length == 0) { - searche = 'Mitorisia/Komugari'; - } - - if (searche[0].indexOf('/') !== -1) { - const repo = safeRepo(searche[0]) - const msg = await message.channel.send(`🔄 | Loading info for \`${repo}\`\u2026`) - try { - const res = await snekfetch.get(`https://api.github.com/repos/${repo}`) - if (res.status !== 200) { - return msg.edit('Could not connect to GitHub server!') - } - - return msg.edit({ embed: buildEmbedFromJson(res.body) }) - } catch (err) { - if (new RegExp('404 Not Found', 'i').test(err.toString())) { - return msg.edit('That repository could not be found!') - } else { - throw err - } - } - } else { - const query = args ? args : 'Komugari' - const msg = await message.channel.send(`🔄 | Searching for **${query}**...`) - - const res = await snekfetch.get(`https://api.github.com/search/repositories?q=${query ? query.length < 2 ? query.join('+') : query : 'Komugari'}`) - if (res.status !== 200) { - return msg.edit('Failed to connect to the GitHub server!') - } - - if (res.body.items.length < 1) { - return msg.edit(`No results found for **${query}**`) - } - - const count = res.body.items.length = Math.min(3, res.body.items.length) - await msg.delete() - - const send = async i => { - if (!res.body.items[i]) { - return - } - await message.channel.send(`${i + 1} of ${count} results for **${query}**`, { - embed: buildEmbedFromJson(res.body.items[i]) - }) - await send(i + 1) - } - return send(0) - } - } -} - -function safeRepo(input) { - if (input.indexOf('/') === -1) { - return - } - - const user = input.substr(0, input.indexOf('/')) - input = input.substr(input.indexOf('/') + 1) - const repo = input.indexOf('/') === -1 ? input : input.substr(0, input.indexOf('/')) - return `${user}/${repo}` -} - -function buildEmbedFromJson(json) { - - const isMyGit = json.full_name === MY_GIT - - return new Discord.MessageEmbed() - .setAuthor(json.full_name, 'https://a.safe.moe/cxwFp.png') - .setURL(json.html_url) - .setColor(isMyGit ? '#4078c0' : '#6f72af') - .setThumbnail(isMyGit ? 'https://a.safe.moe/jmHJI.jpg' : '') - .setDescription(json.description || '`No description provided`') - .setFooter(isMyGit ? 'Please leave a star! ฅ (˵´•ω • `˵๑)' : '') - .addField('❯\u2000\Information', `•\u2000\**Owner:** [${json.owner.login}](${json.owner.html_url})\n\•\u2000\**Primary Language:** ${json.language || '`N/A`'}`) - .addField('❯\u2000\Links', `•\u2000[Home page](${json.html_url})\n\•\u2000[Downloads](${json.html_url}/releases)\n\•\u2000[Issues](${json.html_url}/issues)`, true) - .addField('❯\u2000\Statistics', `•\u2000\**Stars:** ${json.stargazers_count}\n\•\u2000\**Watchers:** ${json.subscribers_count || json.watchers_count}\n\•\u2000\**Open Issues:** ${json.open_issues_count}`, true) - .addField('❯\u2000\Clone', `\`\`\`git clone ${json.clone_url}\`\`\``); -} \ No newline at end of file diff --git a/Komugari-master/commands/utility/img.js b/Komugari-master/commands/utility/img.js deleted file mode 100644 index d846085..0000000 --- a/Komugari-master/commands/utility/img.js +++ /dev/null @@ -1,55 +0,0 @@ -const { Command } = require('../../commando'); -const Discord = require('discord.js'); -const GoogleImages = require("google-images"); - -module.exports = class ImgCommand extends Command { - constructor(client) { - super(client, { - name: 'img', - aliases: ['google', 'image', 'googleimage'], - group: 'utility', - memberName: 'img', - guildOnly: true, - description: 'Searches for your query on google images!', - examples: ['~img [query]'], - details: 'Safe search is off for this command, please be considerate!', - throttling: { - usages: 1, - duration: 5 - } - }); - } - - async run(message) { - const gClient = new GoogleImages(process.env.GOOGLECSE, process.env.GOOGLEAPI); - - let search = message.content.split(/\s+/g).slice(1).join(" "); - - if (!search) return message.channel.send('Please specify something to search.'); - - if (search.length > 0) { - try { - const response = await gClient.search(search, { - safe: "off" - }); - if (!response) { - message.channel.send("Nothing Found!"); - return; - } else { - let image = response[0].url; - const embed = await new Discord.MessageEmbed() - .setAuthor(`${search}`, 'https://a.safe.moe/F3RvU.png') - .setColor(`#3369E8`) - .setImage(image); - message.channel.send({ embed }); - } - - } catch (err) { - message.channel.send("<:NOTLIKETHIIIIIIIIIIIIIIIIIIIIIIS:371071292146843658> Something went wrong with the search."); - return console.error(err); - } - } else { - return message.channel.send("Invalid Parameters(???)"); - } - } -} \ No newline at end of file diff --git a/Komugari-master/commands/utility/math.js b/Komugari-master/commands/utility/math.js deleted file mode 100644 index 61a3e77..0000000 --- a/Komugari-master/commands/utility/math.js +++ /dev/null @@ -1,42 +0,0 @@ -const { Command } = require('../../commando'); -const Discord = require('discord.js'); -const math = require('mathjs'); - - -module.exports = class MathCommand extends Command { - constructor(client) { - super(client, { - name: 'math', - aliases: ['solve', 'calc'], - group: 'utility', - memberName: 'math', - description: 'I\'ll do your math homework!', - examples: ['~math [equation]'], - throttling: { - usages: 1, - duration: 5 - }, - args: [{ - key: 'equation', - prompt: 'Please provide me with an equation to solve!', - type: 'string' - }] - }); - } - - run(message, args) { - var { equation } = args; - try { - var solution = math.eval(equation) - } catch (err) { - return message.channel.send(`❎ | I couldn\'t solve that equation! \`${err}\``) - } - - const embed = new Discord.MessageEmbed() - .setColor('#767CC1') - .addField('**📥 Expression**', `\`\`\`${equation}\`\`\``) - .addField('**📤 Result**', `\`\`\`${solution}\`\`\``); - return message.channel.send({ embed }) - - } -} \ No newline at end of file diff --git a/Komugari-master/commands/utility/osu.js b/Komugari-master/commands/utility/osu.js deleted file mode 100644 index 520dea5..0000000 --- a/Komugari-master/commands/utility/osu.js +++ /dev/null @@ -1,64 +0,0 @@ -const { Command } = require('../../commando'); -const Discord = require('discord.js'); -const osu = require('node-osu'); - -var osuApi = new osu.Api(process.env.OSUKEY, { - notFoundAsError: false, - completeScores: false -}) - -module.exports = class OsuCommand extends Command { - constructor(client) { - super(client, { - name: 'osu', - aliases: ['osustats', 'osuuser'], - group: 'utility', - memberName: 'osu', - guildOnly: true, - description: 'searches for an user on osu!', - examples: ['~osu [username]'], - throttling: { - usages: 1, - duration: 10 - } - }); - } - - run(message) { - let query = message.content.split(/\s+/g).slice(1).join(" "); - - if (!query) return message.channel.send('Please provide me a user to search for!'); - - try { - osuApi.getUser({ u: query }).then(user => { - - if (!user.name) return message.channel.send(`The user **${query}** was not found!`); - - const embed = new Discord.MessageEmbed() - .setAuthor(user.name, `https://a.ppy.sh/${user.id}`) - .addField('❯\u2000\Stats', `•\u2000\**Level:** ${user.level}\n\•\u2000\**Play Count:** ${user.counts.plays}\n\•\u2000\**Accuracy:** ${user.accuracyFormatted}`, true) - .addField('❯\u2000\PP', `•\u2000\**Raw:** ${user.pp.raw} PP\n\•\u2000\**Rank:** ${user.pp.rank}\n\•\u2000\**Country Rank:** ${user.pp.countryRank} ${user.country}`, true) - .addField('❯\u2000\Scores', `•\u2000\**Ranked:** ${user.scores.ranked}\n\•\u2000\**Total:** ${user.scores.total}`, true) - .addField('❯\u2000\Map Ranks', `•\u2000\**SS:** ${user.counts.SS}\n\•\u2000\**S:** ${user.counts.S}\n\•\u2000\**A:** ${user.counts.A}`, true).addBlankField(true) - .setThumbnail(`https://a.ppy.sh/${user.id}`) - .setColor('#ff66aa') - .setImage(`https://lemmmy.pw/osusig/sig.php?colour=bpink&uname=${query}&countryrank&darkheader&darktriangles&avatarrounding=10`); - return message.channel.send({ embed }); - }).catch(err => { - console.log(err) - return message.channel.send(`The user **${query}** was not found!`); - }); - - } catch (err) { - return message.channel.send('<:NOTLIKETHIIIIIIIIIIIIIIIIIIIIIIS:371071292146843658> Something went wrong while executing that function!'); - } - } -} - -/* - - - .addBlankField(true) - .addField('❯ SS', user.counts.SS, true) - .addField('❯ S', user.counts.S, true) - .addField('❯ A', user.counts.A, true)*/ \ No newline at end of file diff --git a/Komugari-master/commands/utility/translate.js b/Komugari-master/commands/utility/translate.js deleted file mode 100644 index cb735b8..0000000 --- a/Komugari-master/commands/utility/translate.js +++ /dev/null @@ -1,47 +0,0 @@ -const { Command } = require('../../commando'); -const Discord = require('discord.js'); -const translate = require('google-translate-api'); - -module.exports = class TranslateCommand extends Command { - constructor(client) { - super(client, { - name: 'translate', - aliases: ['tl', 'translate', 'trans'], - group: 'utility', - memberName: 'translate', - guildOnly: true, - description: 'Translates your text into the desired language!', - examples: ['~translate [language] [text]'], - throttling: { - usages: 1, - duration: 10 - } - }); - } - - run(message) { - const lang = message.content.split(/\s+/g)[1]; - const input = message.content.split(/\s+/g).slice(2).join(" "); - - if (!lang) { - return message.channel.send('You must provide a language and some text to translate!') - } - - try { - translate(input, { to: lang }).then(res => { - const embed = new Discord.MessageEmbed() - .setAuthor('Translated Text:') - .setColor('#4c8bf5') - .setFooter('Google Translate', 'https://a.safe.moe/2jXgX.png') - .addField(`📥 Input: \`[auto]\``, `\`\`\`${input}\`\`\``) - .addField(`📤 Output: \`[${lang}]\``, `\`\`\`${res.text}\`\`\``); - return message.channel.send({ embed }); - }).catch(err => { - return message.channel.send(`❎ | **${message.author.username}**, you provided an invalid language! Try using \`en\` as your first argument, and \`こむがりは可愛いねえ\` as your second!\n\`~translate en こむがりは可愛いねえ\``) - }) - - } catch (err) { - return message.channel.send(`<:NOTLIKETHIIIIIIIIIIIIIIIIIIIIIIS:371071292146843658> Something went wrong while executing that command! \`${err}\``); - } - } -} \ No newline at end of file diff --git a/Komugari-master/commands/utility/urban.js b/Komugari-master/commands/utility/urban.js deleted file mode 100644 index ba45b5d..0000000 --- a/Komugari-master/commands/utility/urban.js +++ /dev/null @@ -1,71 +0,0 @@ -const { Command } = require('../../commando'); -const Discord = require('discord.js'); -const urban = require('relevant-urban'); - -module.exports = class UrbanCommand extends Command { - constructor(client) { - super(client, { - name: 'urban', - aliases: ['ud', 'urbandictionary'], - group: 'utility', - memberName: 'urban', - guildOnly: true, - description: 'Searches for your query on Urban Dictionary!', - examples: ['~urban [term]'], - details: 'Say `~urban` for a random definition!', - throttling: { - usages: 1, - duration: 3 - } - }); - } - - async run(message) { - const query = message.content.split(/\s+/g).slice(1).join(" "); - - const defs = await (query.length ? urban(query) : urban.random()); - let def, total - - if (!defs) { - return message.channel.send('No matches found!'); - } - - if (defs.constructor.name === 'Array') { - total = Object.keys(defs).length - - if (!defs || !total) { - return message.channel.send('No matches found!'); - } - - def = defs[1] - } else if (defs.constructor.name === 'Definition') { - def = defs - } - const resultMessage = query.length > 0 ? - `First result for \`${query}\` on Urban Dictionary:` : - `Random definition on Urban Dictionary:` - - try { - const embed = new Discord.MessageEmbed() - .setTitle(`${defs.word} by ${defs.author}`) - .setDescription(defs.definition) - .addField('❯\u2000\Example(s)', defs.example ? defs.example : 'N/A') - .addField('❯\u2000\Rating', `👍\u2000${defs.thumbsUp} | 👎\u2000${defs.thumbsDown}`) - .addField('❯\u2000\Link', `**${defs.urbanURL}**`) - .setColor('#e86222') - .setFooter('Urban Dictionary', 'https://a.safe.moe/1fscn.png'); - return message.channel.send(resultMessage, { embed }); - - } catch (err) { - const embed = new Discord.MessageEmbed() - .setTitle(`${defs.word} by ${defs.author}`) - .setDescription(defs.definition.split('\n')[0]) - .addField('❯\u2000\Example(s)', defs.example ? defs.example : 'N/A') - .addField('❯\u2000\Rating', `👍\u2000${defs.thumbsUp} | 👎\u2000${defs.thumbsDown}`) - .addField('❯\u2000\Link', `**${defs.urbanURL}**`) - .setColor('#e86222') - .setFooter('Urban Dictionary', 'https://a.safe.moe/1fscn.png'); - return message.channel.send(resultMessage, { embed }); - } - } -} \ No newline at end of file diff --git a/Komugari-master/commands/utility/wiki.js b/Komugari-master/commands/utility/wiki.js deleted file mode 100644 index ac88951..0000000 --- a/Komugari-master/commands/utility/wiki.js +++ /dev/null @@ -1,60 +0,0 @@ -const { Command } = require('../../commando'); -const Discord = require('discord.js'); -const wiki = require('wikijs').default; - -module.exports = class WikiCommand extends Command { - constructor(client) { - super(client, { - name: 'wiki', - aliases: ['encyclopedia', 'wikipedia'], - group: 'utility', - memberName: 'wiki', - guildOnly: true, - description: 'Searches for your query on Wikipedia!', - examples: ['~wiki [query]'], - throttling: { - usages: 1, - duration: 5 - } - }); - } - - async run(message) { - const query = message.content.split(/\s+/g).slice(1).join(" "); - - if (!query) { - return message.channel.send('You must specify something to search!'); - } - - const data = await wiki().search(query, 1); - if (!data.results || !data.results.length) { - return message.channel.send('No matches found!'); - } - - const page = await wiki().page(data.results[0]); - const summary = await page.summary(); - const paragraphs = summary.split('\n'); - - if (!query.options) { - paragraphs.length = Math.min(1, paragraphs.length); - } - try { - const embed = new Discord.MessageEmbed() - .setAuthor(page.raw.title) - .setDescription(paragraphs.join('\n\n')) - .addField('Link', `**${page.raw.fullurl}**`) - .setFooter('Wikipedia', 'https://a.safe.moe/8GCNj.png') - .setColor('#c7c8ca'); - return message.channel.send(`First search result of \`${query}\` on Wikipedia:`, { embed }); - - } catch (err) { - const embed = new Discord.MessageEmbed() - .setAuthor(page.raw.title) - .setDescription("This paragraph was too long for the embed, please click the provided link.") - .addField('Link', `**${page.raw.fullurl}**`) - .setFooter('Wikipedia', 'https://a.safe.moe/8GCNj.png') - .setColor('#c7c8ca'); - return message.channel.send(`First search result of \`${query}\` on Wikipedia:`, { embed }); - } - } -} \ No newline at end of file diff --git a/Komugari-master/commands/utility/youtube.js b/Komugari-master/commands/utility/youtube.js deleted file mode 100644 index b0972b6..0000000 --- a/Komugari-master/commands/utility/youtube.js +++ /dev/null @@ -1,49 +0,0 @@ -const { Command } = require('../../commando'); -var youtube_node = require('youtube-node'); -youtube = new youtube_node(); -youtube.setKey(process.env.YOUTUBEKEY); -youtube.addParam('type', 'video'); - -module.exports = class YouTubeCommand extends Command { - constructor(client) { - super(client, { - name: 'youtube', - aliases: ['yt', 'video'], - group: 'utility', - memberName: 'youtube', - guildOnly: true, - description: 'Searches for your query on YouTube!', - examples: ['~youtube [query]'], - throttling: { - usages: 1, - duration: 5 - } - }); - } - - run(message) { - var query = message.content.split(/\s+/g).slice(1).join(" "); - try { - youtube.search(query, 1, function(error, result) { - if (!query) { - return message.channel.send('Please provide me with something to search!'); - } - if (error) { - return message.channel.send("There was an error executing that search!"); - - } else { - if (!result || !result.items || result.items.length < 1) { - return message.channel.send(`No results found for **${query}**`); - } else if (!result.items[0].id.videoId) { - return message.channel.send(`No results found for **${query}**`); - } else { - return message.channel.send(`<:youtubBwwWOWWwowwWOWwthanks:341350435312893953> **${query}** (http://www.youtube.com/watch?v=${result.items[0].id.videoId})`); - } - } - }); - - } catch (err) { - return message.channel.send('<:NOTLIKETHIIIIIIIIIIIIIIIIIIIIIIS:371071292146843658> Something went wrong while executing that command!'); - } - } -} \ No newline at end of file diff --git a/Bot permissions.url b/Sites/Bot permissions.url similarity index 100% rename from Bot permissions.url rename to Sites/Bot permissions.url diff --git a/Discloud.url b/Sites/Discloud.url similarity index 100% rename from Discloud.url rename to Sites/Discloud.url diff --git a/Discord applications.url b/Sites/Discord applications.url similarity index 100% rename from Discord applications.url rename to Sites/Discord applications.url diff --git a/Discord.js.url b/Sites/Discord.js.url similarity index 100% rename from Discord.js.url rename to Sites/Discord.js.url diff --git a/discord.js guide.url b/Sites/discord.js guide.url similarity index 100% rename from discord.js guide.url rename to Sites/discord.js guide.url diff --git a/commands/alcorao.js b/commands/alcorao.js index 90f04d5..8ce37b8 100644 --- a/commands/alcorao.js +++ b/commands/alcorao.js @@ -1,7 +1,7 @@ const Discord = require('discord.js'); -const alcorao = require('../alcorao.json'); +const alcorao = require('../json/alcorao.json'); const superagent = require("snekfetch"); -const config = require('../config.json'); +const config = require('../json/config.json'); exports.run = (bot, message, args) => { if (args.length === 0) { diff --git a/commands/ban.js b/commands/ban.js index b7ed589..afc463d 100644 --- a/commands/ban.js +++ b/commands/ban.js @@ -1,5 +1,5 @@ const Discord = require('discord.js'); -const config = require('../config.json'); +const config = require('../json/config.json'); exports.run = (bot, message, args) => { if (!message.member.hasPermission("BAN_MEMBERS")) return message.reply('TALOCO???? VO BANI ESSE CARA N MÓ GENTE FINA'); diff --git a/commands/clear.js b/commands/clear.js index 8b12732..39c7a69 100644 --- a/commands/clear.js +++ b/commands/clear.js @@ -1,5 +1,5 @@ const Discord = require('discord.js'); -const config = require('../config.json'); +const config = require('../json/config.json'); exports.run = (bot, message, args) => { // if (message.deletable) { diff --git a/commands/corona.js b/commands/corona.js index d8583b3..40578d6 100644 --- a/commands/corona.js +++ b/commands/corona.js @@ -1,6 +1,6 @@ const Discord = require('discord.js'); const snekfetch = require('snekfetch'); -const config = require('../config.json'); +const config = require('../json/config.json'); exports.run = async (bot, message, args) => { const text = await snekfetch.get("https://thevirustracker.com/free-api?global=stats"); diff --git a/commands/help.js b/commands/help.js index fadaeff..4ec8fe3 100644 --- a/commands/help.js +++ b/commands/help.js @@ -1,5 +1,5 @@ const Discord = require('discord.js'); -const config = require('../config.json'); +const config = require('../json/config.json'); exports.run = (bot, message, args) => { const data = [] diff --git "a/commands/hor\303\263scopo.js" "b/commands/hor\303\263scopo.js" index e3cfbc9..dacdda8 100644 --- "a/commands/hor\303\263scopo.js" +++ "b/commands/hor\303\263scopo.js" @@ -1,7 +1,7 @@ const Discord = require('discord.js'); const snekfetch = require('snekfetch'); const moment = require('moment'); -const config = require('../config.json'); +const config = require('../json/config.json'); const signs = [ "capricorn", "aquarius", diff --git a/commands/kick.js b/commands/kick.js index e5ddae4..e408db4 100644 --- a/commands/kick.js +++ b/commands/kick.js @@ -1,5 +1,5 @@ const Discord = require('discord.js'); -const config = require('../config.json'); +const config = require('../json/config.json'); exports.run = (bot, message, args) => { if (!message.member.hasPermission("KICK_MEMBERS")) return message.reply('TALOCO???? VO KICKA ESSE CARA N MÓ GENTE FINA'); diff --git a/commands/ncorona.js b/commands/ncorona.js index f96657e..98209bd 100644 --- a/commands/ncorona.js +++ b/commands/ncorona.js @@ -1,7 +1,7 @@ const Discord = require('discord.js'); const snekfetch = require('snekfetch'); const moment = require('moment'); -const config = require('../config.json'); +const config = require('../json/config.json'); exports.run = async (bot,message, args) => { const text = await snekfetch.get(`https://thevirustracker.com/free-api?countryTotal=BR`); diff --git a/commands/pcorona.js b/commands/pcorona.js index 12294a5..81529ff 100644 --- a/commands/pcorona.js +++ b/commands/pcorona.js @@ -1,6 +1,6 @@ const Discord = require('discord.js'); const snekfetch = require('snekfetch'); -const config = require('../config.json'); +const config = require('../json/config.json'); exports.run = async (bot,message, args) => { if (args.length === 0) { diff --git a/commands/ping.js b/commands/ping.js index da98d85..fbcd913 100644 --- a/commands/ping.js +++ b/commands/ping.js @@ -1,5 +1,5 @@ const Discord = require('discord.js'); -const config = require('../config.json'); +const config = require('../json/config.json'); module.exports.run = async(bot, message, args) => { let embed = new Discord.RichEmbed() diff --git a/commands/porn.js b/commands/porn.js index f2cdd11..5abc53d 100644 --- a/commands/porn.js +++ b/commands/porn.js @@ -1,5 +1,5 @@ const Discord = require ('discord.js'); -const porn = require('../porns.json'); +const porn = require('../json/porns.json'); exports.run = (bot, message, args) => { let links = porn diff --git a/commands/roleta.js b/commands/roleta.js index 63e3462..fa914fe 100644 --- a/commands/roleta.js +++ b/commands/roleta.js @@ -1,5 +1,5 @@ const Discord = require('discord.js'); -const config = require('../config.json'); +const config = require('../json/config.json'); exports.run = (bot, message, args) => { if (isNaN(args[0]) || args[0] <= 0) { diff --git a/commands/unban.js b/commands/unban.js index 17f5baf..91d8b19 100644 --- a/commands/unban.js +++ b/commands/unban.js @@ -1,5 +1,5 @@ const Discord = require('discord.js'); -const config = require('../config.json'); +const config = require('../json/config.json'); module.exports.run = async (bot, message, args) => { if (!message.member.hasPermission("BAN_MEMBERS")) return message.reply('VO DESBANI N FALOU, VACILÃO MORRE CEDO'); diff --git a/commands/userinfo.js b/commands/userinfo.js index 8a24587..2f5214d 100644 --- a/commands/userinfo.js +++ b/commands/userinfo.js @@ -1,9 +1,9 @@ const Discord = require('discord.js'); -const config = require('../config.json'); +const config = require('../json/config.json'); const moment = require('moment'); require('moment-duration-format'); const { stripIndents } = require('common-tags'); -const { getMember, formatDate } = require('../functions.js'); +const { getMember, formatDate } = require('../functions/functions.js'); exports.run = (bot, message, args) => { let user = message.mentions.users.first() || message.author; diff --git a/events/message.js b/events/message.js index 42cadee..db40737 100644 --- a/events/message.js +++ b/events/message.js @@ -1,5 +1,5 @@ const Discord = require('discord.js'); -const links = require('../links.json'); +const links = require('../json/links.json'); module.exports = (bot, message) => { // ping diff --git a/functions.js b/functions/functions.js similarity index 100% rename from functions.js rename to functions/functions.js diff --git a/imagens/salodoff-test.png b/imagens/salodoff-test.png new file mode 100644 index 0000000..341c347 Binary files /dev/null and b/imagens/salodoff-test.png differ diff --git a/imagens/salodoff.jpg b/imagens/salodoff.jpg new file mode 100644 index 0000000..13d5292 Binary files /dev/null and b/imagens/salodoff.jpg differ diff --git a/index.js b/index.js index a092443..9978e65 100644 --- a/index.js +++ b/index.js @@ -1,5 +1,5 @@ const Discord = require('discord.js'); -const config = require('./config.json'); +const config = require('./json/config.json'); const fs = require('fs'); const { readdirSync } = require('fs') const bot = new Discord.Client(); @@ -37,8 +37,4 @@ fs.readdir('./commands/', (err, files) => { console.log(`Comando ${f} carregado com sucesso`); bot.commands.set(props.help.name, props); }); -}); - - -// fazer uns áudio xingando o rigs e um comando que o bot entra na sala, xinga o gordo pelo áudio e mete o pé -// fazer comandos de bot de música \ No newline at end of file +}); \ No newline at end of file diff --git a/alcorao.json b/json/alcorao.json similarity index 94% rename from alcorao.json rename to json/alcorao.json index bc2d39e..1f10a02 100644 --- a/alcorao.json +++ b/json/alcorao.json @@ -27,7 +27,7 @@ "25" : "[25] „Os fiéis, que, sem razão fundada (por alguma injúria ou são cegos ou aleijado), permanecem em suas casas, jamais se equiparam àqueles que sacrificam os seus bens e suas vidas pela causa de Deus“", "26" : "[26] „Deus cobrará dos fiéis o sacrifício de seus bens e pessoas, em troca do Paraíso. Combaterão pela causa de Deus, matarão e serão mortos“", "27" : "[27] „Os incrédulos dizem: Por que não lhe foi revelado o Alcorão de uma só vez? Saibam que assim procedemos para firmar com ele o teu coração, e o te ditamos em versículos, paulatinamente“", - "28" : "[28] „SOs incrédulos dizem: Por que não lhe foi revelado o Alcorão de uma só vez? Saibam que assim procedemos para firmar com ele o teu coração, e o te ditamos em versículos, paulatinamente“", + "28" : "[28] „Se você colocar toda a sua confiança em Deus, como você deve, Ele certamente irá satisfazer suas necessidades, assim como Ele satisfaz as das aves. Elas saem com fome de manhã, mas retornam satisfeitas para os seus ninhos.“", "29" : "[29] „Sabei que a vida terrena nada é senão um divertimento e um jogo, e adornos e fútil vanglória, e rivalidade entre vós à procura de mais riquezas e filhos. Assemelha-se a vegetação que se segue a uma chuva“", "30" : "[30] „Se todas as árvores da terra fossem cálamos, e o mar, e mais sete mares fossem tinta, não esgotariam as palavras de Deus, o Poderoso, o Sábio“", "31" : "[31] „Deus não muda o destino de um povo até que o povo mude o que tem na alma“", diff --git a/config.json b/json/config.json similarity index 100% rename from config.json rename to json/config.json diff --git a/links.json b/json/links.json similarity index 100% rename from links.json rename to json/links.json diff --git a/package-lock.json b/json/package-lock.json similarity index 100% rename from package-lock.json rename to json/package-lock.json diff --git a/package.json b/json/package.json similarity index 100% rename from package.json rename to json/package.json diff --git a/porns.json b/json/porns.json similarity index 100% rename from porns.json rename to json/porns.json