├── .env.example ├── .eslintignore ├── .eslintrc.json ├── .gitattributes ├── .github ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── feature_request.md │ └── general-issue.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .travis.yml ├── .vscode ├── launch.json └── tasks.json ├── LICENSE ├── README.md ├── appveyor.yml ├── azure-pipelines.yml ├── base ├── Command.js └── Indev.js ├── build ├── appveyor │ └── send.ps1 ├── azure-pipelines │ ├── darwin │ │ └── continuous-build-darwin.yml │ └── win32 │ │ └── continuous-build-win32.yml ├── text.js └── travis │ └── send.sh ├── commands ├── Debug │ ├── eval.js │ ├── event.js │ ├── exec.js │ └── filesize.js ├── Fun │ ├── 8ball.js │ ├── bigletter.js │ ├── cleverbot.js │ ├── dadjoke.js │ ├── expand.js │ ├── flip.js │ ├── joke.js │ ├── lmgtfy.js │ ├── rate.js │ ├── roll.js │ ├── say.js │ ├── slots.js │ ├── tableflip.js │ ├── trivia.js │ ├── urban.js │ ├── vaportext.js │ └── vaporwave.js ├── Image │ ├── cat.js │ ├── changemymind.js │ ├── dog.js │ ├── faketweet.js │ ├── giphy.js │ ├── image.js │ ├── imagesearch.js │ ├── jpeg.js │ ├── lizard.js │ ├── magik.js │ ├── robot.js │ └── snake.js ├── Information │ ├── about.js │ ├── avatar.js │ ├── channelid.js │ ├── channelinfo.js │ ├── discriminator.js │ ├── dsdev.js │ ├── emojiimage.js │ ├── emojiinfo.js │ ├── feedback.js │ ├── github.js │ ├── logo.js │ ├── nasa.js │ ├── serverinfo.js │ ├── stats.js │ ├── time.js │ ├── timezones.js │ ├── tweet.js │ ├── twitter.js │ ├── uptime.js │ ├── userid.js │ ├── userinfo.js │ ├── version.js │ └── weather.js ├── Maths │ ├── maths.js │ ├── pi.js │ └── prime.js ├── Misc │ ├── announce.js │ ├── help.js │ ├── icon.js │ ├── invite.js │ ├── invites.js │ ├── lastmessage.js │ ├── loremipsum.js │ ├── mylevel.js │ ├── quote.js │ ├── tutorial.js │ └── youtube.js ├── Moderation │ ├── ban.js │ ├── banlist.js │ ├── bans.js │ ├── clearnick.js │ ├── forceban.js │ ├── kick.js │ ├── lockdown.js │ ├── mute.js │ ├── purge.js │ ├── report.js │ ├── unmute.js │ └── warn.js ├── Music │ ├── README.md │ ├── np.js │ ├── pause.js │ ├── play.js │ ├── queue.js │ ├── resume.js │ ├── skip.js │ ├── stop.js │ └── volume.js ├── System │ ├── conf.js │ ├── leave.js │ ├── ping.js │ ├── prefix.js │ ├── reboot.js │ ├── reload.js │ ├── set.js │ ├── shutdown.js │ └── status.js └── Utility │ ├── emoji.js │ └── shorten.js ├── config.js.example ├── dashboard ├── public │ ├── css │ │ ├── bootstrap.min.css │ │ ├── darkly.css │ │ ├── dashboard.css │ │ ├── flatly.css │ │ └── font-awesome.min.css │ ├── images │ │ └── bot.png │ └── js │ │ └── bootstrap.min.js └── templates │ ├── admin.ejs │ ├── autherror.ejs │ ├── blocks │ ├── footer.ejs │ ├── guild-card.ejs │ ├── guild-modals.ejs │ ├── guild-nav.ejs │ └── header.ejs │ ├── commands.ejs │ ├── dashboard.ejs │ ├── guild │ ├── manage.ejs │ ├── members.ejs │ └── stats.ejs │ ├── index.ejs │ └── stats.ejs ├── docs ├── .gitignore ├── CNAME ├── _config.yml ├── assets │ └── css │ │ └── style.css └── index.html ├── events ├── error.js ├── guildCreate.js ├── guildDelete.js ├── guildMemberAdd.js ├── guildMemberRemove.js ├── message.js ├── messageDelete.js └── ready.js ├── index.js ├── locales └── en-GB.js ├── modules ├── dashboard.js └── functions.js ├── music └── js │ ├── config.js.example │ └── music.js ├── package-lock.json ├── package.json └── util ├── Logger.js ├── Utils.js ├── data.js ├── setup.js └── setup_base.txt /.env.example: -------------------------------------------------------------------------------- 1 | # Environment 2 | NODE_ENV=development 3 | 4 | # Google 5 | GOOGLE_API_KEY= 6 | 7 | # delet 8 | DELET_TOKEN=TOKEN_HERE 9 | 10 | # Twitter 11 | TWITTER_API_KEY= 12 | TWITTER_SECRET= 13 | 14 | # Giphy 15 | GIPHY_API_KEY= 16 | 17 | # Cleverbot 18 | CLEVERBOT_API_USER= 19 | CLEVERBOT_API_KEY= -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | /dashboard 2 | /docs 3 | /node_modules 4 | /tags 5 | /test -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "parserOptions": { 3 | "ecmaVersion": 2017 4 | }, 5 | "env": { 6 | "es6": true, 7 | "node": true 8 | }, 9 | "extends": "eslint:recommended", 10 | "rules": { 11 | "no-console": "off", 12 | "no-undef": "off", 13 | "quotes": [ 14 | "warn", 15 | "double" 16 | ], 17 | "semi": [ 18 | "warn", 19 | "always" 20 | ], 21 | "keyword-spacing": [ 22 | "error", { 23 | "before": true, 24 | "after": true 25 | } 26 | ], 27 | "space-before-blocks": [ 28 | "error", { 29 | "functions": "always", 30 | "keywords": "always", 31 | "classes": "always" 32 | } 33 | ], 34 | "space-before-function-paren": [ 35 | "error", { 36 | "anonymous": "never", 37 | "named": "never", 38 | "asyncArrow": "always" 39 | } 40 | ], 41 | "prefer-const": [ 42 | "error", { 43 | "destructuring": "any", 44 | "ignoreReadBeforeAssign": false 45 | } 46 | ], 47 | "comma-dangle": [ 48 | "warn", { 49 | "arrays": "never", 50 | "objects": "never", 51 | "imports": "never", 52 | "exports": "never", 53 | "functions": "ignore" 54 | } 55 | ] 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | 3 | *.js text 4 | *.json text 5 | *.md text 6 | *.example text 7 | *.sh linguist-language=Shell 8 | 9 | dashboard/public/css/darkly.css linguist-vendored 10 | dashboard/public/css/flatly.css linguist-vendored 11 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | **We accept contributions for anything!** Just fork this repository, make any changes you desire, and submit a pull request! 3 | Examples of things you can contribute are fortunes for the 8ball command, new commands and improvements to existing features, but you can submit a PR for basically anything. 4 | 5 | ## Fortunes for the 8ball command 6 | Check the comments in the file [here](https://github.com/DS-Development/delet/blob/master/commands/Fun/8ball.js). 7 | 8 | ## Translations 9 | If you'd like to sign up to be a translator for delet, you can do so [here](https://delet.js.org/go/translate). Note that the process of adding translations to the bot has not started yet, and we cannot guarantee that it will ever take place, as it will only do so if there is enough demand for this feature. The purpose of signing up is so we know who to go to in the event that we do end up implementing this feature. 10 | 11 | ## Commands 12 | The default command base we use is as follows: 13 | ```js 14 | const Command = require("../../base/Command.js"); 15 | 16 | class CommandName extends Command { 17 | constructor(client) { 18 | super(client, { 19 | // The name of the command. In most cases, this should match the class and file name. 20 | name: "", 21 | // State what the command does 22 | description: "", 23 | // Choose from one of the directory names within the `commands` folder 24 | category: "", 25 | // State the command usage including all possible parameters/arguments 26 | usage: "", 27 | // An array of any other names the command can be invoked with. 28 | // Each value in the array must be a string. 29 | aliases: [], 30 | // If the command can be run in DMs, remove this property or set it to false. 31 | guildOnly: true, 32 | // Choose from "User", "Moderator", "Admin", "Bot Support", "Bot Admin" or "Bot Owner". 33 | // If the permLevel is just "User", the `permLevel` property can be removed from the constructor. 34 | permLevel: "" 35 | }); 36 | } 37 | 38 | // Make sure to remove all unused params or add `// eslint-disable-line no-unused-vars` on the line 39 | async run(message, args, level, settings, texts) { 40 | // Command code here 41 | } 42 | } 43 | 44 | module.exports = CommandName; 45 | ``` 46 | 47 | ### Want to join the DS Development Group? 48 | Head to [delet.js.org/go/join](https://delet.js.org/go/join)! 49 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Encountered a bug? Report it to us here. 4 | 5 | --- 6 | 7 | 9 | 10 | **Brief description of the bug/issue being encountered** 11 | 12 | **Expected behaviour** 13 | 14 | **Actual behaviour** 15 | 16 | **Steps to reproduce** 17 | 18 | 1. 19 | 2. 20 | 3. 21 | 4. 22 | 23 | **Additional info** 24 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for delet 4 | 5 | --- 6 | 7 | **Is your feature request related to a problem? Please describe.** 8 | A clear and concise description of what the problem is. E.g. I'm always frustrated when [...] 9 | 10 | **Describe the solution you'd like** 11 | A clear and concise description of what you want to happen. 12 | 13 | **Describe alternatives you've considered** 14 | A clear and concise description of any alternative solutions or features you've considered. 15 | 16 | **Additional context** 17 | Add any other context or screenshots about the feature request here. 18 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/general-issue.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: General issue 3 | about: Encountered an issue that isn't a bug? Tell us about it. 4 | 5 | --- 6 | 7 | **What's the expected behaviour of delet in this situation?** 8 | 9 | **What's the actual behaviour you're getting?** 10 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | **Type** 2 | 3 | - [ ] Bugfix 4 | - [ ] Enhancement 5 | - [ ] New feature 6 | 7 | **Description of the changes** 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | config.json 8 | config.js 9 | data/ 10 | 11 | # Runtime data 12 | pids 13 | *.pid 14 | *.seed 15 | *.pid.lock 16 | 17 | # Environment variables 18 | .env 19 | 20 | # Directory for instrumented libs generated by jscoverage/JSCover 21 | lib-cov 22 | 23 | # Coverage directory used by tools like istanbul 24 | coverage 25 | 26 | # nyc test coverage 27 | .nyc_output 28 | 29 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 30 | .grunt 31 | 32 | # Bower dependency directory (https://bower.io/) 33 | bower_components 34 | 35 | # node-waf configuration 36 | .lock-wscript 37 | 38 | # Compiled binary addons (http://nodejs.org/api/addons.html) 39 | build/Release 40 | 41 | # Dependency directories 42 | node_modules/ 43 | jspm_packages/ 44 | 45 | # Typescript v1 declaration files 46 | typings/ 47 | 48 | # Optional npm cache directory 49 | .npm 50 | 51 | # Optional eslint cache 52 | .eslintcache 53 | 54 | # Optional REPL history 55 | .node_repl_history 56 | 57 | # Output of 'npm pack' 58 | *.tgz 59 | 60 | # Yarn Integrity file 61 | .yarn-integrity 62 | 63 | # dotenv environment variables file 64 | .env 65 | 66 | # Specific files & folders 67 | session-encrypt.txt 68 | /assets/ 69 | music/js/config.js 70 | music/js/audiotest.js 71 | .vscode/settings.json 72 | commands/embed.js 73 | docs/elements.html 74 | docs/generic.html 75 | docs/assets/xcf 76 | indev 77 | /test/ 78 | /notes/ 79 | /security/ 80 | /docker-compose.yml 81 | /base/DS.js 82 | /points/ 83 | 84 | # Temporary 85 | /tags/ 86 | /Dockerfile 87 | /currency/ 88 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "9" 4 | - "8" 5 | 6 | cache: 7 | directories: 8 | - "node_modules" 9 | 10 | addons: 11 | apt: 12 | update: true 13 | 14 | sudo: enabled 15 | 16 | before_install: 17 | - sudo apt-get update 18 | - sudo apt-get install build-essential libcairo2-dev libpango1.0-dev libjpeg-dev libgif-dev librsvg2-dev 19 | 20 | # after_success: 21 | # - wget https://raw.githubusercontent.com/DS-Development/delet/master/build/travis/send.sh 22 | # - chmod +x send.sh 23 | # - ./send.sh success $WEBHOOK_URL 24 | after_failure: 25 | - wget https://raw.githubusercontent.com/DS-Development/delet/master/build/travis/send.sh 26 | - chmod +x send.sh 27 | - ./send.sh failure $WEBHOOK_URL -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "node", 9 | "request": "launch", 10 | "name": "Launch Audio", 11 | "program": "${workspaceFolder}/music/js/audio.js" 12 | }, 13 | { 14 | "type": "node", 15 | "request": "launch", 16 | "name": "Launch Index", 17 | "program": "${workspaceFolder}\\index.js" 18 | } 19 | ] 20 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "type": "npm", 8 | "script": "test", 9 | "group": { 10 | "kind": "build", 11 | "isDefault": true 12 | } 13 | } 14 | ] 15 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## NO LONGER MAINTAINED - will be replaced by delet3 2 | ### delet3: https://github.com/suvanl/delet3 3 | 4 | 5 | --- 6 | 7 |

tN5H3x.png 8 | 9 |

10 | Code Quality 11 | 12 | 13 | 14 | 15 | 16 |

17 | 18 |

delet is a powerful, configurable and multipurpose Discord bot, made using the Discord.js library for the Discord API. 19 |
Please ensure you read the section regarding self-hosting and portability in this README document.

20 | 21 | **[outdated content removed]** 22 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | # AppVeyor file 2 | # http://www.appveyor.com/docs/appveyor-yml 3 | 4 | #---------------------------------# 5 | # General Configuration # 6 | #---------------------------------# 7 | 8 | # Build version format 9 | version: "{build}" 10 | 11 | # What combinations to test 12 | environment: 13 | matrix: 14 | - nodejs_version: "8" 15 | - nodejs_version: "9" 16 | 17 | # Caches the directory containing all installed npm modules 18 | cache: 19 | - node_modules 20 | 21 | branches: 22 | only: 23 | - master 24 | 25 | #---------------------------------# 26 | # Installation # 27 | #---------------------------------# 28 | 29 | install: 30 | # Get the latest stable version of Node.js 31 | - ps: Install-Product node $env:nodejs_version 32 | # Install latest version of npm 33 | - npm install npm@latest -g 34 | # Install node-gyp 35 | - npm install -g node-gyp 36 | # Install modules 37 | - npm install 38 | 39 | build: off 40 | 41 | #---------------------------------# 42 | # Tests # 43 | #---------------------------------# 44 | 45 | test_script: 46 | - npm test 47 | 48 | #---------------------------------# 49 | # Post-build # 50 | #---------------------------------# 51 | 52 | # on_success: 53 | # - ps: Invoke-RestMethod https://raw.githubusercontent.com/DS-Development/delet/master/build/appveyor/send.ps1 -o send.ps1 54 | # - ps: ./send.ps1 success $env:WEBHOOK_URL 55 | on_failure: 56 | - ps: Invoke-RestMethod https://raw.githubusercontent.com/DS-Development/delet/master/build/appveyor/send.ps1 -o send.ps1 57 | - ps: ./send.ps1 failure $env:WEBHOOK_URL 58 | -------------------------------------------------------------------------------- /azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | jobs: 2 | - job: Windows 3 | pool: 4 | vmImage: VS2017-Win2016 5 | steps: 6 | - template: build/azure-pipelines/win32/continuous-build-win32.yml 7 | 8 | - job: macOS 9 | pool: 10 | vmImage: macOS 10.13 11 | steps: 12 | - template: build/azure-pipelines/darwin/continuous-build-darwin.yml -------------------------------------------------------------------------------- /base/Command.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 An Idiot's Guide. All rights reserved. MIT license. 2 | // https://github.com/AnIdiotsGuide/guidebot-class 3 | 4 | class Command { 5 | constructor(client, { 6 | name = null, 7 | description = "No description provided.", 8 | category = "Miscellaneous", 9 | usage = "No usage provided.", 10 | enabled = true, 11 | guildOnly = false, 12 | aliases = new Array(), 13 | permLevel = "User" 14 | }) { 15 | this.client = client; 16 | this.conf = { enabled, guildOnly, aliases, permLevel }; 17 | this.help = { name, description, category, usage }; 18 | } 19 | } 20 | module.exports = Command; 21 | -------------------------------------------------------------------------------- /base/Indev.js: -------------------------------------------------------------------------------- 1 | class Indev { 2 | constructor(client, { 3 | name = null, 4 | description = "No description provided.", 5 | category = "Miscellaneous", 6 | usage = "No usage provided.", 7 | enabled = false, 8 | guildOnly = false, 9 | aliases = new Array(), 10 | permLevel = "Bot Owner" 11 | }) { 12 | this.client = client; 13 | this.conf = { enabled, guildOnly, aliases, permLevel }; 14 | this.help = { name, description, category, usage }; 15 | } 16 | } 17 | module.exports = Indev; 18 | -------------------------------------------------------------------------------- /build/appveyor/send.ps1: -------------------------------------------------------------------------------- 1 | # Forked from https://github.com/k3rn31p4nic/appveyor-discord-webhook 2 | 3 | # Author: Sankarsan Kampa (a.k.a. k3rn31p4nic) 4 | # License: MIT 5 | 6 | $STATUS=$args[0] 7 | $WEBHOOK_URL=$args[1] 8 | 9 | if (!$WEBHOOK_URL) { 10 | Write-Output "WARNING!!" 11 | Write-Output "You need to pass the WEBHOOK_URL environment variable as the second argument to this script." 12 | Write-Output "For details & guide, visit: https://github.com/k3rn31p4nic/appveyor-discord-webhook" 13 | Exit 14 | } 15 | 16 | Write-Output "[Webhook]: Sending webhook to Discord..." 17 | 18 | Switch ($STATUS) { 19 | "success" { 20 | $EMBED_COLOR=3066993 21 | $STATUS_MESSAGE="Passed" 22 | Break 23 | } 24 | "failure" { 25 | $EMBED_COLOR=15158332 26 | $STATUS_MESSAGE="Failed" 27 | Break 28 | } 29 | default { 30 | Write-Output "Default!" 31 | Break 32 | } 33 | } 34 | $AVATAR="https://upload.wikimedia.org/wikipedia/commons/thumb/b/bc/Appveyor_logo.svg/256px-Appveyor_logo.svg.png" 35 | 36 | if (!$env:APPVEYOR_REPO_COMMIT) { 37 | $env:APPVEYOR_REPO_COMMIT="$(git log -1 --pretty="%H")" 38 | } 39 | 40 | $AUTHOR_NAME="$(git log -1 "$env:APPVEYOR_REPO_COMMIT" --pretty="%aN")" 41 | $COMMITTER_NAME="$(git log -1 "$env:APPVEYOR_REPO_COMMIT" --pretty="%cN")" 42 | $COMMIT_SUBJECT="$(git log -1 "$env:APPVEYOR_REPO_COMMIT" --pretty="%s")" 43 | $COMMIT_MESSAGE="$(git log -1 "$env:APPVEYOR_REPO_COMMIT" --pretty="%b")" 44 | 45 | if ($AUTHOR_NAME -eq $COMMITTER_NAME) { 46 | $CREDITS="$AUTHOR_NAME authored & committed" 47 | } 48 | else { 49 | $CREDITS="$AUTHOR_NAME authored & $COMMITTER_NAME committed" 50 | } 51 | 52 | if ($env:APPVEYOR_PULL_REQUEST_NUMBER) { 53 | $URL="https://github.com/$env:APPVEYOR_REPO_NAME/pull/$env:APPVEYOR_PULL_REQUEST_NUMBER" 54 | } 55 | else { 56 | $URL="" 57 | } 58 | 59 | $TIMESTAMP="$(Get-Date -format s)Z" 60 | $WEBHOOK_DATA="{ 61 | ""username"": """", 62 | ""avatar_url"": ""$AVATAR"", 63 | ""embeds"": [ { 64 | ""color"": $EMBED_COLOR, 65 | ""author"": { 66 | ""name"": ""Job #$env:APPVEYOR_JOB_NUMBER (Build #$env:APPVEYOR_BUILD_NUMBER) $STATUS_MESSAGE - $env:APPVEYOR_REPO_NAME"", 67 | ""url"": ""https://ci.appveyor.com/project/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/build/$env:APPVEYOR_BUILD_VERSION"", 68 | ""icon_url"": ""$AVATAR"" 69 | }, 70 | ""title"": ""$COMMIT_SUBJECT"", 71 | ""url"": ""$URL"", 72 | ""description"": ""$COMMIT_MESSAGE $CREDITS"", 73 | ""fields"": [ 74 | { 75 | ""name"": ""Commit"", 76 | ""value"": ""[``$($env:APPVEYOR_REPO_COMMIT.substring(0, 7))``](https://github.com/$env:APPVEYOR_REPO_NAME/commit/$env:APPVEYOR_REPO_COMMIT)"", 77 | ""inline"": true 78 | }, 79 | { 80 | ""name"": ""Branch/Tag"", 81 | ""value"": ""[``$env:APPVEYOR_REPO_BRANCH``](https://github.com/$env:APPVEYOR_REPO_NAME/tree/$env:APPVEYOR_REPO_BRANCH)"", 82 | ""inline"": true 83 | } 84 | ], 85 | ""timestamp"": ""$TIMESTAMP"" 86 | } ] 87 | }" 88 | 89 | Invoke-RestMethod -Uri "$WEBHOOK_URL" -Method "POST" -UserAgent "AppVeyor-Webhook" ` 90 | -ContentType "application/json" -Header @{"X-Author"="boxeh#3254"} ` 91 | -Body $WEBHOOK_DATA 92 | 93 | Write-Output "[Webhook]: Successfully sent." 94 | -------------------------------------------------------------------------------- /build/azure-pipelines/darwin/continuous-build-darwin.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - task: NodeTool@0 3 | inputs: 4 | versionSpec: "8.12.0" 5 | 6 | - script: | 7 | npm install npm@latest -g 8 | displayName: Update npm 9 | 10 | - script: | 11 | npm install -g node-gyp 12 | displayName: Install node-gyp 13 | 14 | - script: | 15 | npm install 16 | displayName: Install dependencies 17 | 18 | - script: | 19 | npm audit 20 | displayName: Audit packages 21 | 22 | - script: | 23 | npm test 24 | displayName: Build & test -------------------------------------------------------------------------------- /build/azure-pipelines/win32/continuous-build-win32.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - task: NodeTool@0 3 | inputs: 4 | versionSpec: "8.12.0" 5 | 6 | - powershell: | 7 | npm install npm@latest -g 8 | displayName: Update npm 9 | 10 | - powershell: | 11 | npm install -g node-gyp 12 | displayName: Install node-gyp 13 | 14 | - powershell: | 15 | npm install 16 | displayName: Install dependencies 17 | 18 | - powershell: | 19 | npm audit 20 | displayName: Audit packages 21 | 22 | - powershell: | 23 | npm test 24 | displayName: Build & test -------------------------------------------------------------------------------- /build/text.js: -------------------------------------------------------------------------------- 1 | console.log(` 2 | 3 | dddddddd 4 | d::::::d lllllll tttt 5 | d::::::d l:::::l ttt:::t 6 | d::::::d l:::::l t:::::t 7 | d:::::d l:::::l t:::::t 8 | ddddddddd:::::d eeeeeeeeeeee l::::l eeeeeeeeeeee ttttttt:::::ttttttt 9 | dd::::::::::::::d ee::::::::::::ee l::::l ee::::::::::::ee t:::::::::::::::::t 10 | d::::::::::::::::d e::::::eeeee:::::eel::::l e::::::eeeee:::::eet:::::::::::::::::t 11 | d:::::::ddddd:::::d e::::::e e:::::el::::l e::::::e e:::::etttttt:::::::tttttt 12 | d::::::d d:::::d e:::::::eeeee::::::el::::l e:::::::eeeee::::::e t:::::t 13 | d:::::d d:::::d e:::::::::::::::::e l::::l e:::::::::::::::::e t:::::t 14 | d:::::d d:::::d e::::::eeeeeeeeeee l::::l e::::::eeeeeeeeeee t:::::t 15 | d:::::d d:::::d e:::::::e l::::l e:::::::e t:::::t tttttt 16 | d::::::ddddd::::::dde::::::::e l::::::le::::::::e t::::::tttt:::::t 17 | d:::::::::::::::::d e::::::::eeeeeeee l::::::l e::::::::eeeeeeee tt::::::::::::::t 18 | d:::::::::ddd::::d ee:::::::::::::e l::::::l ee:::::::::::::e tt:::::::::::tt 19 | ddddddddd ddddd eeeeeeeeeeeeee llllllll eeeeeeeeeeeeee ttttttttttt 20 | 21 | `); 22 | 23 | console.log(`Build completed @ ${new Date()}.`); 24 | -------------------------------------------------------------------------------- /build/travis/send.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -z "$2" ]; then 4 | echo -e "WARNING!!\nYou need to pass the WEBHOOK_URL environment variable as the second argument to this script.\nFor details & guide, visit: https://github.com/k3rn31p4nic/travis-ci-discord-webhook" && exit 5 | fi 6 | 7 | echo -e "[Webhook]: Sending webhook to Discord...\\n"; 8 | 9 | case $1 in 10 | "success" ) 11 | EMBED_COLOR=3066993 12 | STATUS_MESSAGE="Passed" 13 | AVATAR="https://travis-ci.org/images/logos/TravisCI-Mascot-blue.png" 14 | ;; 15 | 16 | "failure" ) 17 | EMBED_COLOR=15158332 18 | STATUS_MESSAGE="Failed" 19 | AVATAR="https://travis-ci.org/images/logos/TravisCI-Mascot-red.png" 20 | ;; 21 | 22 | * ) 23 | EMBED_COLOR=0 24 | STATUS_MESSAGE="Status Unknown" 25 | AVATAR="https://travis-ci.org/images/logos/TravisCI-Mascot-1.png" 26 | ;; 27 | esac 28 | 29 | AUTHOR_NAME="$(git log -1 "$TRAVIS_COMMIT" --pretty="%aN")" 30 | COMMITTER_NAME="$(git log -1 "$TRAVIS_COMMIT" --pretty="%cN")" 31 | COMMIT_SUBJECT="$(git log -1 "$TRAVIS_COMMIT" --pretty="%s")" 32 | COMMIT_MESSAGE="$(git log -1 "$TRAVIS_COMMIT" --pretty="%b")" 33 | 34 | if [ "$AUTHOR_NAME" == "$COMMITTER_NAME" ]; then 35 | CREDITS="$AUTHOR_NAME authored & committed" 36 | else 37 | CREDITS="$AUTHOR_NAME authored & $COMMITTER_NAME committed" 38 | fi 39 | 40 | if [[ $TRAVIS_PULL_REQUEST != false ]]; then 41 | URL="https://github.com/$TRAVIS_REPO_SLUG/pull/$TRAVIS_PULL_REQUEST" 42 | else 43 | URL="" 44 | fi 45 | 46 | TIMESTAMP=$(date --utc +%FT%TZ) 47 | WEBHOOK_DATA='{ 48 | "username": "", 49 | "avatar_url": "https://travis-ci.org/images/logos/TravisCI-Mascot-1.png", 50 | "embeds": [ { 51 | "color": '$EMBED_COLOR', 52 | "author": { 53 | "name": "Job #'"$TRAVIS_JOB_NUMBER"' (Build #'"$TRAVIS_BUILD_NUMBER"') '"$STATUS_MESSAGE"' - '"$TRAVIS_REPO_SLUG"'", 54 | "url": "https://travis-ci.org/'"$TRAVIS_REPO_SLUG"'/builds/'"$TRAVIS_BUILD_ID"'", 55 | "icon_url": "'$AVATAR'" 56 | }, 57 | "title": "'"$COMMIT_SUBJECT"'", 58 | "url": "'"$URL"'", 59 | "description": "'"${COMMIT_MESSAGE//$'\n'/ }"\\n\\n"$CREDITS"'", 60 | "fields": [ 61 | { 62 | "name": "Commit", 63 | "value": "'"[\`${TRAVIS_COMMIT:0:7}\`](https://github.com/$TRAVIS_REPO_SLUG/commit/$TRAVIS_COMMIT)"'", 64 | "inline": true 65 | }, 66 | { 67 | "name": "Branch/Tag", 68 | "value": "'"[\`$TRAVIS_BRANCH\`](https://github.com/$TRAVIS_REPO_SLUG/tree/$TRAVIS_BRANCH)"'", 69 | "inline": true 70 | } 71 | ], 72 | "timestamp": "'"$TIMESTAMP"'" 73 | } ] 74 | }' 75 | 76 | (curl --fail --progress-bar -A "TravisCI-Webhook" -H Content-Type:application/json -H X-Author:boxeh#3254 -d "$WEBHOOK_DATA" "$2" \ 77 | && echo -e "\\n[Webhook]: Successfully sent the webhook.") || echo -e "\\n[Webhook]: Unable to send webhook." -------------------------------------------------------------------------------- /commands/Debug/eval.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 An Idiot's Guide. All rights reserved. MIT license. 2 | // https://github.com/AnIdiotsGuide/guidebot-class 3 | 4 | // The EVAL command will execute **ANY** arbitrary JavaScript code given to it. 5 | // Therefore, this command is permission level 10 to prevent others using it. It 6 | // can be dangerous, as Eval can be used to do anything on the host machine. 7 | // However, it's extremely useful for troubleshooting and doing stuff you don't 8 | // want to put in a command. 9 | 10 | const Command = require("../../base/Command.js"); 11 | 12 | class Eval extends Command { 13 | constructor(client) { 14 | super(client, { 15 | name: "eval", 16 | description: "Evaluates arbitrary JavaScript.", 17 | category: "Debug", 18 | usage: "eval ", 19 | aliases: ["ev"], 20 | permLevel: "Bot Owner" 21 | }); 22 | } 23 | 24 | async run(message, args, level) { // eslint-disable-line no-unused-vars 25 | this.client.logger.warn("Eval command used"); 26 | 27 | const code = args.join(" "); 28 | try { 29 | const evaled = eval(code); 30 | const clean = await this.client.clean(this.client, evaled); 31 | const MAX_CHARS = 3 + 2 + clean.length + 3; 32 | if (MAX_CHARS > 2000) { 33 | return message.channel.send("Output exceeded 2000 characters, sending as a file.", { files: [{ attachment: Buffer.from(clean), name: "output.txt" }] }); 34 | } 35 | message.channel.send(`\`\`\`js\n${clean}\n\`\`\``); 36 | } catch (err) { 37 | message.channel.send(`\`ERROR\` \`\`\`xl\n${await this.client.clean(this.client, err)}\n\`\`\``); 38 | } 39 | } 40 | } 41 | 42 | module.exports = Eval; 43 | -------------------------------------------------------------------------------- /commands/Debug/event.js: -------------------------------------------------------------------------------- 1 | // The EVENT command will emit an event. This is useful, but should only 2 | // be used for debugging purposes. 3 | 4 | const Command = require("../../base/Command.js"); 5 | 6 | class Event extends Command { 7 | constructor(client) { 8 | super(client, { 9 | name: "event", 10 | description: "Emits an event.", 11 | category: "Debug", 12 | usage: "event", 13 | aliases: ["emit"], 14 | permLevel: "Bot Owner", 15 | guildOnly: true 16 | }); 17 | } 18 | 19 | async run(message, args, level) { // eslint-disable-line no-unused-vars 20 | const member = message.mentions.members.first() || message.member; 21 | 22 | await this.client.emit("guildMemberAdd", member); 23 | } 24 | } 25 | 26 | module.exports = Event; -------------------------------------------------------------------------------- /commands/Debug/exec.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 An Idiot's Guide. All rights reserved. MIT license. 2 | // https://github.com/NotAWeebDev/Misaki 3 | 4 | // The EXEC command will execute **ANY** new specified process. This can be 5 | // extremely dangerous if used incorrectly, hence why it is reserved strictly 6 | // for the bot owner only. This command spawns a new child process, and 7 | // executes the given command. It should only be used for debugging purposes. 8 | 9 | const Command = require("../../base/Command.js"); 10 | const exec = require("child_process").exec; 11 | 12 | class Exec extends Command { 13 | constructor(client) { 14 | super(client, { 15 | name: "exec", 16 | description: "Evaluates arbitrary JavaScript.", 17 | category: "Debug", 18 | usage: "exec ", 19 | permLevel: "Bot Owner" 20 | }); 21 | } 22 | 23 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 24 | this.client.logger.warn("Exec command used"); 25 | 26 | try { 27 | exec(`${args.join(" ")}`, (error, stdout) => { 28 | const response = (error || stdout); 29 | message.channel.send(`Ran command **\`${message.content.slice(6)}\`**:\n\`\`\`${response}\`\`\``, {split: true}); 30 | }); 31 | } catch (error) { 32 | this.client.logger.error(error.stack); 33 | return message.channel.send(texts.general.error.replace(/{{err}}/g, error.message)); 34 | } 35 | } 36 | } 37 | 38 | module.exports = Exec; 39 | -------------------------------------------------------------------------------- /commands/Debug/filesize.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const fs = require("fs"); 3 | 4 | class FileSize extends Command { 5 | constructor(client) { 6 | super(client, { 7 | name: "filesize", 8 | description: "Returns the value of the size of the specified file.", 9 | category: "Debug", 10 | usage: "filesize ", 11 | aliases: ["fs"], 12 | permLevel: "Bot Admin" 13 | }); 14 | } 15 | 16 | async run(message, args, level) { // eslint-disable-line no-unused-vars 17 | const file = args[0]; 18 | if (!file) return message.channel.send("You must provide a file (and location if non-root file), and the correct syntax must be used."); 19 | 20 | try { 21 | const stats = fs.statSync(file); 22 | const fileBytes = stats["size"]; 23 | const fileKB = fileBytes / 1024; 24 | 25 | message.channel.send(`\`${file}\` currently has a size of **${fileBytes}** bytes (${fileKB.toFixed(2)}KB).`); 26 | } catch (error) { 27 | if (error.code === "ENOENT") return message.channel.send(`The file \`${file}\` could not be found.`); 28 | else this.client.logger.error(error); 29 | } 30 | } 31 | } 32 | 33 | module.exports = FileSize; 34 | -------------------------------------------------------------------------------- /commands/Fun/bigletter.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | 3 | class BigLetter extends Command { 4 | constructor(client) { 5 | super(client, { 6 | name: "bigletter", 7 | description: "Converts the specified text to regional indicators.", 8 | category: "Fun", 9 | usage: "bigletter ", 10 | aliases: ["regional", "regional-indicator"] 11 | }); 12 | } 13 | 14 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 15 | const generate = () => { 16 | let text = args.join(" "); 17 | if (!text) return message.channel.send("You must provide some text to convert to regional indicator emojis."); 18 | else text = args.join(" ").toLowerCase(); 19 | 20 | const numbers = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]; 21 | const isAlphaNumeric = (str) => { 22 | let code, i, len; 23 | for (i = 0, len = str.length; i < len; i++) { 24 | code = str.charCodeAt(i); 25 | if (!(code > 47 && code < 58) && !(code > 64 && code < 91) && !(code > 96 && code < 123) && code !== 32) { 26 | return false; 27 | } 28 | } 29 | return true; 30 | }; 31 | 32 | if (!isAlphaNumeric(text)) return message.channel.send("Invalid character(s) provided.\nPlease ensure you have only provided alphanumeric characters."); 33 | 34 | let output = ""; 35 | 36 | for (let i = 0; i < text.length; i++) { 37 | const char = text.charAt(i); 38 | if (char === " ") output += char; 39 | else if (numbers.includes(char)) output += numberToString(char); 40 | else output += `:regional_indicator_${char}: `; 41 | } 42 | 43 | return output; 44 | }; 45 | 46 | const numberToString = (number) => { 47 | let value = ""; 48 | 49 | switch (number) { 50 | case "0": 51 | value = ":zero :"; 52 | break; 53 | 54 | case "1": 55 | value = ":one: "; 56 | break; 57 | 58 | case "2": 59 | value = ":two: "; 60 | break; 61 | 62 | case "3": 63 | value = ":three: "; 64 | break; 65 | 66 | case "4": 67 | value = ":four: "; 68 | break; 69 | 70 | case "5": 71 | value = ":five: "; 72 | break; 73 | 74 | case "6": 75 | value = ":six: "; 76 | break; 77 | 78 | case "7": 79 | value = ":seven: "; 80 | break; 81 | 82 | case "8": 83 | value = ":eight: "; 84 | break; 85 | 86 | case "9": 87 | value = ":nine: "; 88 | break; 89 | } 90 | return value; 91 | }; 92 | 93 | message.channel.send(generate()) 94 | .catch(error => { 95 | if (error.message === "Cannot send an empty message") return; 96 | else this.client.logger.error(error.message); 97 | }); 98 | } 99 | } 100 | 101 | module.exports = BigLetter; 102 | -------------------------------------------------------------------------------- /commands/Fun/cleverbot.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const cleverbot = require("cleverbot.io"); 3 | const { CLEVERBOT_API_USER, CLEVERBOT_API_KEY } = process.env; 4 | const bot = new cleverbot(CLEVERBOT_API_USER, CLEVERBOT_API_KEY); 5 | 6 | class CleverBot extends Command { 7 | constructor(client) { 8 | super(client, { 9 | name: "cleverbot", 10 | description: "Talks to cleverbot!", 11 | category: "Fun", 12 | usage: "cleverbot ", 13 | aliases: ["cb"] 14 | }); 15 | } 16 | 17 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 18 | bot.setNick("delet"); 19 | bot.create(function() { 20 | const query = args.join(" "); 21 | if (!query) return message.channel.send("You must provide a message to say to me."); 22 | 23 | message.channel.startTyping(); 24 | 25 | bot.ask(query, (err, response) => { 26 | message.channel.send(response.includes("Cleverbot") ? response.replace(/Cleverbot/g, "delet") : response); 27 | message.channel.stopTyping(true); 28 | 29 | if (err) { 30 | this.client.logger.error(err); 31 | return message.channel.send(texts.general.error.replace(/{{err}}/g, err.message)); 32 | } 33 | }); 34 | }); 35 | } 36 | } 37 | 38 | module.exports = CleverBot; 39 | -------------------------------------------------------------------------------- /commands/Fun/dadjoke.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const fetch = require("node-fetch"); 3 | 4 | class DadJoke extends Command { 5 | constructor(client) { 6 | super(client, { 7 | name: "dadjoke", 8 | description: "Sends a random dad joke.", 9 | category: "Fun", 10 | usage: "dadjoke", 11 | aliases: ["dad", "dadj", "badjoke"] 12 | }); 13 | } 14 | 15 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 16 | const meta = { "Accept": "text/plain" }; 17 | 18 | fetch("https://icanhazdadjoke.com/", { headers: meta }) 19 | .then(res => res.text()) 20 | .then(body => message.channel.send(body)) 21 | .catch(error => { 22 | this.client.logger.error(error); 23 | return message.channel.send(texts.general.error.replace(/{{err}}/g, error.message)); 24 | }); 25 | } 26 | } 27 | 28 | module.exports = DadJoke; 29 | -------------------------------------------------------------------------------- /commands/Fun/expand.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const fetch = require("node-fetch"); 3 | 4 | class Expand extends Command { 5 | constructor(client) { 6 | super(client, { 7 | name: "expand", 8 | description: "Makes the specified text T H I C C", 9 | category: "Fun", 10 | usage: "expand " 11 | }); 12 | } 13 | 14 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 15 | const text = encodeURIComponent(args.join(" ")); 16 | if (!text) return message.channel.send("You must provide some text to expand."); 17 | const tooLong = "Unfortunately, the specified text is too long. Please try again with something a little shorter."; 18 | 19 | fetch(`http://artii.herokuapp.com/make?text=${text}`) 20 | .then(res => res.text()) 21 | .then(body => { 22 | if (body.length > 2000) return message.channel.send(tooLong); 23 | return message.channel.send(body, { code: "fix" }); 24 | }) 25 | .catch(error => { 26 | this.client.logger.error(error); 27 | return message.channel.send(texts.general.error.replace(/{{err}}/g, error.message)); 28 | }); 29 | } 30 | } 31 | 32 | module.exports = Expand; 33 | -------------------------------------------------------------------------------- /commands/Fun/flip.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const { currencies } = require("../../util/data.js"); 3 | const { RichEmbed } = require("discord.js"); 4 | const { stripIndents } = require("common-tags"); 5 | 6 | const fullName = { 7 | "EUR": "Euro", 8 | "GBP": "Pound Sterling", 9 | "NOK": "Norwegian Kroner", 10 | "USD": "US Dollar" 11 | }; 12 | 13 | class Flip extends Command { 14 | constructor(client) { 15 | super(client, { 16 | name: "flip", 17 | description: "Flips/tosses a coin.", 18 | category: "Fun", 19 | usage: "flip", 20 | aliases: ["toss"], 21 | guildOnly: true 22 | }); 23 | } 24 | 25 | async run(message, args, level, settings) { // eslint-disable-line no-unused-vars 26 | // If no currency is set 27 | if (settings.currency === ">>No currency set<<") return message.channel.send(stripIndents` 28 | I cannot run this command, as I don't know which currency to use on this server. Please set a currency by using: 29 | \`\`\`${settings.prefix}set edit currency TYPE\`\`\` 30 | Currently available types: ${currencies.map(c => "`" + c + "`").join(", ")}`); 31 | 32 | const coinFlip = () => (Math.floor(Math.random() * 2) == 0) ? "heads" : "tails"; 33 | const flip = coinFlip(); 34 | 35 | const embed = new RichEmbed() 36 | .setDescription(`This flip's result was **${flip}**!\n\nTime taken: ${(this.client.ping / 1000).toFixed(3)}s\nCurrency: ${fullName[settings.currency]} (${settings.currency})`) 37 | .setThumbnail(flip === "heads" ? `https://delet.js.org/imgstore/currency/${settings.currency}/${settings.currency}heads.png` : `https://delet.js.org/imgstore/currency/${settings.currency}/${settings.currency}tails.png`); 38 | return message.channel.send({ embed }); 39 | } 40 | } 41 | 42 | module.exports = Flip; 43 | -------------------------------------------------------------------------------- /commands/Fun/joke.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const fetch = require("node-fetch"); 3 | 4 | class Joke extends Command { 5 | constructor(client) { 6 | super(client, { 7 | name: "joke", 8 | description: "Tells a general or programming-related joke.", 9 | category: "Fun", 10 | usage: "joke", 11 | aliases: ["humour", "humor"] 12 | }); 13 | } 14 | 15 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 16 | fetch("https://official-joke-api.appspot.com/random_joke") 17 | .then(res => res.json()) 18 | .then(data => message.channel.send(`${data.setup} ${data.punchline}`)) 19 | .catch(error => { 20 | this.client.logger.error(error); 21 | return message.channel.send(texts.general.error.replace(/{{err}}/g, error)); 22 | }); 23 | } 24 | } 25 | 26 | module.exports = Joke; 27 | -------------------------------------------------------------------------------- /commands/Fun/lmgtfy.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | 3 | class LMGTFY extends Command { 4 | constructor(client) { 5 | super(client, { 6 | name: "lmgtfy", 7 | description: "Why don't you just... Google it?", 8 | category: "Fun", 9 | usage: "lmgtfy ", 10 | aliases: ["googleit"] 11 | }); 12 | } 13 | 14 | async run(message, args, level, settings) { // eslint-disable-line no-unused-vars 15 | const textQuery = args.join(" "); 16 | const query = encodeURIComponent(args.join(" ")); 17 | const url = `https://lmgtfy.com/?q=${query}`; 18 | 19 | if (!query) return message.channel.send(`Please enter a query. For example, \`${settings.prefix}lmgtfy How to create a Discord server\`.`); 20 | else message.channel.send(`"${textQuery}"\n**<${url}>**`); 21 | } 22 | } 23 | 24 | module.exports = LMGTFY; -------------------------------------------------------------------------------- /commands/Fun/rate.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | 3 | class Rate extends Command { 4 | constructor(client) { 5 | super(client, { 6 | name: "rate", 7 | description: "Rates something out of 10.", 8 | category: "Fun", 9 | usage: "rate " 10 | }); 11 | } 12 | 13 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 14 | const rateObject = args.join(" "); 15 | if (!rateObject) return message.channel.send(texts.cmd.fun.noRate); 16 | const rate = Math.floor(Math.random() * 10) +1; 17 | 18 | let rateMsg; 19 | 20 | if (rate === 0) rateMsg = "a big fat"; 21 | if (rate === 0 || rate === 1 || rate === 2) rateMsg = "quite a poor"; 22 | if (rate === 3 || rate === 4) rateMsg = "an improvable"; 23 | if (rate === 5 || rate === 6) rateMsg = "a pretty moderate"; 24 | if (rate === 7 || rate === 8 || rate === 9) rateMsg = "a high"; 25 | if (rate === 10) rateMsg = "a solid"; 26 | 27 | message.channel.send(`I'd give "${rateObject}" ${rateMsg} ${rate}/10.`); 28 | } 29 | } 30 | 31 | module.exports = Rate; -------------------------------------------------------------------------------- /commands/Fun/roll.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | 3 | class Roll extends Command { 4 | constructor(client) { 5 | super(client, { 6 | name: "roll", 7 | description: "Rolls a regular six-sided dice.", 8 | category: "Fun", 9 | usage: "roll", 10 | aliases: ["dice"] 11 | }); 12 | } 13 | 14 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 15 | const numbers = [ 16 | ":one:", 17 | ":two:", 18 | ":three:", 19 | ":four:", 20 | ":five:", 21 | ":six:" 22 | ]; 23 | 24 | try { 25 | const roll = numbers.random(); 26 | const msg = await message.channel.send(`${texts.cmd.fun.rolling} 🎲`); 27 | msg.edit(texts.cmd.fun.rolled.replace(/{{result}}/g, roll)); 28 | } catch (error) { 29 | return message.channel.send(texts.general.error.replace(/{{err}}/g, error.message)); 30 | } 31 | } 32 | } 33 | 34 | module.exports = Roll; 35 | -------------------------------------------------------------------------------- /commands/Fun/say.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | 3 | class Say extends Command { 4 | constructor(client) { 5 | super(client, { 6 | name: "say", 7 | description: "Repeats your message.", 8 | category: "Fun", 9 | usage: "say [tts] ", 10 | aliases: ["repeat", "echo"] 11 | }); 12 | } 13 | 14 | async run(message, args, level, settings) { // eslint-disable-line no-unused-vars 15 | const msg = args.join(" "); 16 | if (!msg) return message.channel.send("You must provide a message for me to repeat."); 17 | if (args[0].toLowerCase() === "tts" && !args[1]) return message.channel.send("You must provide a message for me to repeat with TTS."); 18 | 19 | return message.channel.send(args[0].toLowerCase() === "tts" ? msg.slice(4) : msg, { tts: args[0].toLowerCase() === "tts" ? true : false }); 20 | } 21 | } 22 | 23 | module.exports = Say; -------------------------------------------------------------------------------- /commands/Fun/slots.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const { stripIndents } = require("common-tags"); 3 | const slots = ["🍇", "🍊", "🍐", "🍒", "🍋"]; 4 | 5 | class Slots extends Command { 6 | constructor(client) { 7 | super(client, { 8 | name: "slots", 9 | description: "Spin the slot machine!", 10 | category: "Fun", 11 | usage: "slots", 12 | aliases: ["slotmachine"], 13 | guildOnly: true 14 | }); 15 | } 16 | 17 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 18 | const slotOne = slots[Math.floor(Math.random() * slots.length)]; 19 | const slotTwo = slots[Math.floor(Math.random() * slots.length)]; 20 | const slotThree = slots[Math.floor(Math.random() * slots.length)]; 21 | if (slotOne === slotTwo && slotOne === slotThree) { 22 | return message.channel.send(stripIndents` 23 | ${slotOne}|${slotTwo}|${slotThree} 24 | ${texts.cmd.fun.slotWin} 25 | `); 26 | } 27 | return message.channel.send(stripIndents` 28 | ${slotOne}|${slotTwo}|${slotThree} 29 | ${texts.cmd.fun.slotLoss} 30 | `); 31 | } 32 | } 33 | 34 | module.exports = Slots; 35 | -------------------------------------------------------------------------------- /commands/Fun/tableflip.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const flipFrames = [ 3 | "(-°□°)- ┬─┬", 4 | "(╯°□°)╯ ]", 5 | "(╯°□°)╯ ︵ ┻━┻", 6 | "(╯°□°)╯ [", 7 | "(╯°□°)╯ ┬─┬" 8 | ]; 9 | 10 | class TableFlip extends Command { 11 | constructor(client) { 12 | super(client, { 13 | name: "tableflip", 14 | description: "Flips a table, in real-time! (╯°□°)╯", 15 | category: "Fun", 16 | usage: "tableflip" 17 | }); 18 | } 19 | 20 | async run(message, args, level) { // eslint-disable-line no-unused-vars 21 | const msg = await message.channel.send("(\\\\°□°)\\\\ ┬─┬"); 22 | 23 | for (const frame of flipFrames) { 24 | await this.client.wait(300); 25 | await msg.edit(frame); 26 | } 27 | return msg; 28 | } 29 | } 30 | 31 | module.exports = TableFlip; -------------------------------------------------------------------------------- /commands/Fun/trivia.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 An Idiot's Guide. All rights reserved. MIT license. 2 | // https://github.com/NotAWeebDev/Misaki 3 | 4 | const Command = require("../../base/Command.js"); 5 | const { RichEmbed } = require("discord.js"); 6 | const { stripIndents } = require("common-tags"); 7 | const snekfetch = require("snekfetch"); 8 | const h = new (require("html-entities").AllHtmlEntities)(); 9 | 10 | class Trivia extends Command { 11 | constructor(client) { 12 | super(client, { 13 | name: "trivia", 14 | description: "Puts your general knowledge to the test.", 15 | category: "Fun", 16 | usage: "trivia [difficulty]", 17 | aliases: ["randomtrivia", "randomq", "testme", "quiz"] 18 | }); 19 | } 20 | 21 | async run(message, args, level) { // eslint-disable-line no-unused-vars 22 | const levels = ["easy", "medium", "hard"]; 23 | const difficulty = args[0] || "medium"; 24 | if (!levels.includes(difficulty.toLowerCase())) return message.channel.send("Invalid difficulty specified. Please choose from one of **easy**, **medium** or **hard**."); 25 | 26 | const { body } = await snekfetch.get(`https://opentdb.com/api.php?amount=50&difficulty=${difficulty.toLowerCase()}&type=multiple`); 27 | const quiz = body.results.random(); 28 | const choices = quiz.incorrect_answers.map(ans => h.decode(ans)); 29 | choices.push(h.decode(quiz.correct_answer)); 30 | 31 | const randomChoices = new Array(4); 32 | for (let i = 0; i < 4; i++) { 33 | randomChoices[i] = choices.random(); 34 | choices.splice(choices.indexOf(randomChoices[i]), 1); 35 | } 36 | 37 | const embed = new RichEmbed() 38 | .setColor(5360873) 39 | .setAuthor("Trivia", "https://vgy.me/9UDUk0.png") 40 | .setDescription(stripIndents` 41 | **Question** 42 | ${h.decode(quiz.question)} 43 | 44 | :regional_indicator_a: ${randomChoices[0]} 45 | :regional_indicator_b: ${randomChoices[1]} 46 | :regional_indicator_c: ${randomChoices[2]} 47 | :regional_indicator_d: ${randomChoices[3]} 48 | 49 | **Category & Difficulty** 50 | ${h.decode(quiz.category)} | ${h.decode(quiz.difficulty.toProperCase())} 51 | `) 52 | .setFooter("Reply with the correct letter within 60 seconds!", message.author.displayAvatarURL); 53 | 54 | const question = await this.client.awaitEmbedReply(message, "", m => m.author.id === message.author.id, 60000, {embed: embed}); 55 | if (!question) return message.channel.send("**Trivia session ended**\nThe session timed out as you did not answer within 60 seconds."); 56 | 57 | const choice = randomChoices[["a", "b", "c", "d"].indexOf(question.toLowerCase())]; 58 | if (!choice) return message.channel.send("That's not a valid answer!\nFor future reference, please ensure your answer is either **A**, **B**, **C**, or **D** (lowercase and uppercase are both accepted)."); 59 | if (choice === h.decode(quiz.correct_answer)) return message.channel.send("Well done, your answer is correct!\nTrivia session ended."); 60 | else return message.channel.send(`Unfortunately, that's the wrong answer. The correct answer was **${h.decode(quiz.correct_answer)}**, and you chose **${choice}**.\nTrivia session ended.`); 61 | } 62 | } 63 | 64 | module.exports = Trivia; 65 | -------------------------------------------------------------------------------- /commands/Fun/urban.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const { RichEmbed } = require("discord.js"); 3 | const fetch = require("node-fetch"); 4 | 5 | class Urban extends Command { 6 | constructor(client) { 7 | super(client, { 8 | name: "urban", 9 | description: "Searches the Urban Dictionary for the specified query.", 10 | category: "Fun", 11 | usage: "urban ", 12 | aliases: ["urbandictionary", "udictionary", "urban-dictionary"] 13 | }); 14 | } 15 | 16 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 17 | const query = args.join(" "); 18 | if (!query) return message.channel.send("You must provide a term to search for."); 19 | 20 | fetch(`http://api.urbandictionary.com/v0/define?term=${query}`) 21 | .then(res => res.json()) 22 | .then(json => { 23 | const data = json.list[0]; 24 | const definition = data.definition.replace(/[[\]]+/g, ""); 25 | const example = data.example.replace(/[[\]]+/g, ""); 26 | const embed = new RichEmbed() 27 | .setColor(50687) 28 | .setAuthor("Urban Dictionary", "https://vgy.me/ScvJzi.jpg") 29 | .setDescription(`Displaying Urban Dictionary definition for "**${data.word}**"\n<${data.permalink}>`) 30 | .addField("» Definition", `**${definition.substring(0, 1000)}...**`) 31 | .addField("» Example", `${example.substring(0, 1000)}...`) 32 | .setFooter(`Definition 1 of ${json.list.length}`) 33 | .setTimestamp(); 34 | return message.channel.send({ embed }); 35 | }) 36 | .catch(error => { 37 | this.client.logger.error(error); 38 | return message.channel.send(texts.general.error.replace(/{{err}}/g, error.message)); 39 | }); 40 | } 41 | } 42 | 43 | module.exports = Urban; -------------------------------------------------------------------------------- /commands/Fun/vaportext.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | 3 | class Vaportext extends Command { 4 | constructor(client) { 5 | super(client, { 6 | name: "vaportext", 7 | description: "A E S T H E T I C", 8 | category: "Fun", 9 | usage: "vaportext ", 10 | aliases: ["vapor", "vapour", "vapourtext"] 11 | }); 12 | } 13 | 14 | async run(message, args, level) { // eslint-disable-line no-unused-vars 15 | if (!args.length) return message.channel.send("You must provide some text to make ***A E S T H E T I C A L L Y P L E A S I N G***."); 16 | 17 | let msg = ""; 18 | for (let i = 0; i < args.length; i++) { 19 | msg += args[i].toUpperCase().split("").join(" ") + " "; 20 | } 21 | 22 | return message.channel.send(msg); 23 | } 24 | } 25 | 26 | module.exports = Vaportext; 27 | -------------------------------------------------------------------------------- /commands/Fun/vaporwave.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | 3 | const songs = [ 4 | `${process.cwd()}/assets/audio/Vaporwave1.mp3`, 5 | `${process.cwd()}/assets/audio/Vaporwave2.mp3`, 6 | `${process.cwd()}/assets/audio/Vaporwave3.mp3`, 7 | `${process.cwd()}/assets/audio/Vaporwave4.mp3` 8 | ]; 9 | 10 | class Vaporwave extends Command { 11 | constructor(client) { 12 | super(client, { 13 | name: "vaporwave", 14 | description: "Plays vaporwave music.", 15 | category: "Fun", 16 | usage: "vaporwave ", 17 | aliases: ["vapourwave"] 18 | }); 19 | } 20 | 21 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 22 | const voiceChannel = message.member.voiceChannel; 23 | if (!voiceChannel) return message.channel.send("You must be in a voice channel to be able to play VAPORWAVE MUSIC 可益ビ."); 24 | 25 | const permissions = voiceChannel.permissionsFor(message.client.user); 26 | if (!permissions.has("CONNECT")) return message.channel.send("I cannot play any music, as I do not have the \"CONNECT\" permission."); 27 | if (!permissions.has("SPEAK")) return message.channel.send("I cannot play any music, as I do not have the \"SPEAK\" permission."); 28 | 29 | if (args[0] && args[0].toLowerCase() === "stop") { 30 | if (!voiceChannel) return message.channel.send("You must be in a VOICE CHANNEL to use this command."); 31 | voiceChannel.leave(); 32 | return message.channel.send("STOPPED"); 33 | } 34 | 35 | try { 36 | const connection = await voiceChannel.join(); // eslint-disable-line no-unused-vars 37 | } catch (error) { 38 | this.client.logger.error(`Couldn't join voice channel: ${error}`); 39 | return message.channel.send(texts.general.error.replace(/{{err}}/g, error.message)); 40 | } 41 | 42 | const connection = await voiceChannel.join(); 43 | const dispatcher = connection.playFile(songs.random()) 44 | .on("end", () => voiceChannel.leave()) 45 | .on("error", error => this.client.logger.error(error)); 46 | dispatcher.setVolumeLogarithmic(5 / 5); 47 | } 48 | } 49 | 50 | module.exports = Vaporwave; -------------------------------------------------------------------------------- /commands/Image/cat.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const fetch = require("node-fetch"); 3 | 4 | class Cat extends Command { 5 | constructor(client) { 6 | super(client, { 7 | name: "cat", 8 | description: "Sends a random image of a cat.", 9 | category: "Image", 10 | usage: "cat" 11 | }); 12 | } 13 | 14 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 15 | message.channel.startTyping(); 16 | 17 | fetch("https://aws.random.cat/meow") 18 | .then(res => res.json()) 19 | .then(data => message.channel.send({ file: data.file })) 20 | .catch(error => { 21 | this.client.logger.error(error); 22 | message.channel.stopTyping(true); 23 | return message.channel.send(texts.general.error.replace(/{{err}}/g, error.message)); 24 | }); 25 | 26 | message.channel.stopTyping(true); 27 | } 28 | } 29 | 30 | module.exports = Cat; -------------------------------------------------------------------------------- /commands/Image/changemymind.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const fetch = require("node-fetch"); 3 | 4 | class ChangeMyMind extends Command { 5 | constructor(client) { 6 | super(client, { 7 | name: "changemymind", 8 | description: "Change my mind...", 9 | category: "Image", 10 | usage: "changemymind ", 11 | aliases: ["change-my-mind", "change"] 12 | }); 13 | } 14 | 15 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 16 | let text = args.join(" "); 17 | if (!text) return message.channel.send("You must provide some text to appear on the image."); 18 | else text = encodeURIComponent(args.join(" ")); 19 | 20 | message.channel.startTyping(); 21 | 22 | fetch(`https://nekobot.xyz/api/imagegen?type=changemymind&text=${text}`) 23 | .then(res => res.json()) 24 | .then(data => message.channel.send({ file: data.message })) 25 | .catch(error => { 26 | this.client.logger.error(error); 27 | message.channel.stopTyping(true); 28 | return message.channel.send(texts.general.error.replace(/{{err}}/g, error.message)); 29 | }); 30 | 31 | message.channel.stopTyping(true); 32 | } 33 | } 34 | 35 | module.exports = ChangeMyMind; 36 | -------------------------------------------------------------------------------- /commands/Image/dog.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const fetch = require("node-fetch"); 3 | 4 | class Dog extends Command { 5 | constructor(client) { 6 | super(client, { 7 | name: "dog", 8 | description: "Sends a random image of a dog.", 9 | category: "Image", 10 | usage: "dog" 11 | }); 12 | } 13 | 14 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 15 | message.channel.startTyping(); 16 | 17 | fetch("https://dog.ceo/api/breeds/image/random") 18 | .then(res => res.json()) 19 | .then(data => message.channel.send({ file: data.message })) 20 | .catch(error => { 21 | this.client.logger.error(error); 22 | message.channel.stopTyping(true); 23 | return message.channel.send(texts.general.error.replace(/{{err}}/g, error.message)); 24 | }); 25 | 26 | message.channel.stopTyping(true); 27 | } 28 | } 29 | 30 | module.exports = Dog; -------------------------------------------------------------------------------- /commands/Image/faketweet.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const fetch = require("node-fetch"); 3 | 4 | class FakeTweet extends Command { 5 | constructor(client) { 6 | super(client, { 7 | name: "faketweet", 8 | description: "Creates a fake tweet.", 9 | category: "Image", 10 | usage: "faketweet ", 11 | aliases: ["fake-tweet"] 12 | }); 13 | } 14 | 15 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 16 | let user = args[0]; 17 | let text = args.slice(1).join(" ") || undefined; 18 | if (!user) return message.channel.send("You must provide a Twitter username, to have as the author of the tweet."); 19 | if (user.startsWith("@")) user = args[0].slice(1); 20 | 21 | const type = user.toLowerCase() === "realdonaldtrump" ? "trumptweet" : "tweet"; 22 | const u = user.startsWith("@") ? user.slice(1) : user; 23 | 24 | if (!text) { 25 | text = await this.client.awaitReply(message, "Please enter the tweet's message...\nReply with `cancel` to exit this text-entry period.", 30000); 26 | if (text.toLowerCase() === "cancel") return message.channel.send("Cancelled."); 27 | } 28 | 29 | message.channel.startTyping(); 30 | 31 | fetch(`https://nekobot.xyz/api/imagegen?type=${type}&username=${u}&text=${encodeURIComponent(text)}`) 32 | .then(res => res.json()) 33 | .then(data => message.channel.send({ file: data.message })) 34 | .catch(error => { 35 | this.client.logger.error(error); 36 | message.channel.stopTyping(true); 37 | return message.channel.send(texts.general.error.replace(/{{err}}/g, error.message)); 38 | }); 39 | 40 | message.channel.stopTyping(true); 41 | } 42 | } 43 | 44 | module.exports = FakeTweet; 45 | -------------------------------------------------------------------------------- /commands/Image/giphy.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const fetch = require("node-fetch"); 3 | const { URLSearchParams } = require("url"); 4 | const { GIPHY_API_KEY } = process.env; 5 | 6 | class Giphy extends Command { 7 | constructor(client) { 8 | super(client, { 9 | name: "giphy", 10 | description: "Returns a GIF from Giphy based on your query.", 11 | category: "Image", 12 | usage: "giphy ", 13 | aliases: ["gif"] 14 | }); 15 | } 16 | 17 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 18 | const query = args[0]; 19 | if (!query) return message.channel.send("You must provide a query to return a GIF for."); 20 | 21 | const url = "http://api.giphy.com/v1/gifs/search?"; 22 | const params = new URLSearchParams({ 23 | q: query, 24 | api_key: GIPHY_API_KEY, 25 | rating: "pg" 26 | }); 27 | 28 | fetch(url + params) 29 | .then(res => res.json()) 30 | .then(json => message.channel.send(json.data.random().images.original.url)) 31 | .catch(error => { 32 | this.client.logger.error(error); 33 | return message.channel.send(texts.general.error.replace(/{{err}}/g, error.message)); 34 | }); 35 | } 36 | } 37 | 38 | module.exports = Giphy; 39 | -------------------------------------------------------------------------------- /commands/Image/image.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const fetch = require("node-fetch"); 3 | 4 | class Image extends Command { 5 | constructor(client) { 6 | super(client, { 7 | name: "image", 8 | description: "Returns a random image.", 9 | category: "Image", 10 | usage: "image [size (e.g. 1920x1080)]", 11 | aliases: ["randomimage", "random-image"] 12 | }); 13 | } 14 | 15 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 16 | let size = args[0]; 17 | if (!args[0]) size = ""; 18 | 19 | message.channel.startTyping(); 20 | 21 | fetch(`https://source.unsplash.com/random/${size}`) 22 | .then(res => message.channel.send({ files: [{ attachment: res.body, name: "image.jpg" }] }) 23 | .catch(error => { 24 | this.client.logger.error(error); 25 | message.channel.stopTyping(true); 26 | return message.channel.send(texts.general.error.replace(/{{err}}/g, error.message)); 27 | })); 28 | 29 | message.channel.stopTyping(true); 30 | } 31 | } 32 | 33 | module.exports = Image; 34 | -------------------------------------------------------------------------------- /commands/Image/imagesearch.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const fetch = require("node-fetch"); 3 | const { RichEmbed } = require("discord.js"); 4 | const { UNSPLASH_ACCESS_KEY } = process.env; 5 | 6 | class ImageSearch extends Command { 7 | constructor(client) { 8 | super(client, { 9 | name: "imagesearch", 10 | description: "Sends a random image based on your query.", 11 | category: "Image", 12 | usage: "imagesearch ", 13 | aliases: ["isearch", "i-search", "image-search"] 14 | }); 15 | } 16 | 17 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 18 | let query = args.join(" "); 19 | if (!query) return message.channel.send("You must specify a search query."); 20 | else query = encodeURIComponent(args.join(" ")); 21 | 22 | const page = Math.floor(Math.random() * 5) + 1; 23 | const index = Math.floor(Math.random() * 10) + 1; 24 | 25 | const randomColor = "#0000".replace(/0/g, () => { 26 | return (~~(Math.random() * 16)).toString(16); 27 | }); 28 | 29 | const meta = { "Authorization": `Client-ID ${UNSPLASH_ACCESS_KEY}` }; 30 | 31 | message.channel.startTyping(); 32 | 33 | fetch(`https://api.unsplash.com/search/photos?page=${page}&query=${query}`, { headers: meta }) 34 | .then(res => res.json()) 35 | .then(json => { 36 | const data = json.results[parseInt(index.toFixed(0))]; 37 | const embed = new RichEmbed() 38 | .setTitle("📷 Image") 39 | .setURL(data.urls.raw) 40 | .setDescription(`Photo by [${data.user.name}](${data.user.links.html}) on [Unsplash](https://unsplash.com)`) 41 | .setImage(data.urls.raw) 42 | .setColor(randomColor) 43 | .setTimestamp(); 44 | message.channel.send({ embed }); 45 | }) 46 | .catch(error => { 47 | message.channel.stopTyping(true); 48 | if (error.message === "Cannot read property 'urls' of undefined") return message.channel.send(texts.general.noResultsFound); 49 | this.client.logger.error(error); 50 | return message.channel.send(texts.general.error.replace(/{{err}}/g, error.message)); 51 | }); 52 | 53 | message.channel.stopTyping(true); 54 | } 55 | } 56 | 57 | module.exports = ImageSearch; 58 | -------------------------------------------------------------------------------- /commands/Image/jpeg.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const fetch = require("node-fetch"); 3 | 4 | class JPEG extends Command { 5 | constructor(client) { 6 | super(client, { 7 | name: "jpeg", 8 | description: "Needs more JPEG.", 9 | category: "Image", 10 | usage: "jpeg ", 11 | aliases: ["jpegify"] 12 | }); 13 | } 14 | 15 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 16 | const url = args[0] ? args[0].replace(/<(.+)>/g, "$1") : null; 17 | if (!url || !url.startsWith("http")) return message.channel.send("You must provide a valid image URL to JPEGify."); 18 | 19 | message.channel.startTyping(); 20 | 21 | fetch(`https://nekobot.xyz/api/imagegen?type=jpeg&url=${url}`) 22 | .then(res => res.json()) 23 | .then(data => { 24 | if (!data.success) return message.channel.send("An error occurred. Please ensure the URL you're providing is an image URL."); 25 | message.channel.stopTyping(true); 26 | return message.channel.send({ file: data.message }); 27 | }) 28 | .catch(error => { 29 | this.client.logger.error(error); 30 | message.channel.stopTyping(true); 31 | return message.channel.send(texts.general.error.replace(/{{err}}/g, error.message)); 32 | }); 33 | } 34 | } 35 | 36 | module.exports = JPEG; 37 | -------------------------------------------------------------------------------- /commands/Image/lizard.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const fetch = require("node-fetch"); 3 | 4 | class Lizard extends Command { 5 | constructor(client) { 6 | super(client, { 7 | name: "lizard", 8 | description: "Sends a random image of a lizard.", 9 | category: "Image", 10 | usage: "lizard" 11 | }); 12 | } 13 | 14 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 15 | message.channel.startTyping(); 16 | 17 | fetch("https://nekos.life/api/v2/img/lizard") 18 | .then(res => res.json()) 19 | .then(data => message.channel.send({ file: data.url })) 20 | .catch(error => { 21 | this.client.logger.error(error); 22 | message.channel.stopTyping(true); 23 | return message.channel.send(texts.general.error.replace(/{{err}}/g, error.message)); 24 | }); 25 | 26 | message.channel.stopTyping(true); 27 | } 28 | } 29 | 30 | module.exports = Lizard; -------------------------------------------------------------------------------- /commands/Image/magik.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const fetch = require("node-fetch"); 3 | 4 | class Magik extends Command { 5 | constructor(client) { 6 | super(client, { 7 | name: "magik", 8 | description: "Adds a \"magik\" effect to the specified image.", 9 | category: "Image", 10 | usage: "magik " 11 | }); 12 | } 13 | 14 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 15 | const url = args[0] ? args[0].replace(/<(.+)>/g, "$1") : null; 16 | if (!url || !url.startsWith("http")) return message.channel.send("You must provide a valid image URL to apply some ***m a g i k*** to."); 17 | 18 | message.channel.startTyping(); 19 | 20 | fetch(`https://nekobot.xyz/api/imagegen?type=magik&image=${url}`) 21 | .then(res => res.json()) 22 | .then(data => { 23 | if (!data.success) return message.channel.send("An error occurred. Please ensure the URL you're providing is an image URL."); 24 | message.channel.stopTyping(true); 25 | return message.channel.send({ file: data.message }); 26 | }) 27 | .catch(error => { 28 | this.client.logger.error(error); 29 | message.channel.stopTyping(true); 30 | return message.channel.send(texts.general.error.replace(/{{err}}/g, error.message)); 31 | }); 32 | } 33 | } 34 | 35 | module.exports = Magik; 36 | -------------------------------------------------------------------------------- /commands/Image/robot.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const fetch = require("node-fetch"); 3 | 4 | class Robot extends Command { 5 | constructor(client) { 6 | super(client, { 7 | name: "robot", 8 | description: "Generates a picture of a robot from some given text.", 9 | category: "Image", 10 | usage: "robot ", 11 | aliases: ["robohash"] 12 | }); 13 | } 14 | 15 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 16 | const query = args.join(" "); 17 | if (!query) return message.channel.send("You must some text to use to generate the robot."); 18 | if (query.match(/[-!$%^&*()_+|~=`{}[\]:";'<>?,./]/g)) return message.channel.send("Your query cannot include symbols."); 19 | 20 | message.channel.startTyping(); 21 | 22 | fetch(`https://robohash.org/${encodeURIComponent(query)}.png`) 23 | .then(res => message.channel.send({ files: [{ attachment: res.body, name: `${query}.png` }] }) 24 | .catch(error => { 25 | this.client.logger.error(error); 26 | message.channel.stopTyping(true); 27 | return message.channel.send(texts.general.error.replace(/{{err}}/g, error.message)); 28 | })); 29 | 30 | message.channel.stopTyping(true); 31 | } 32 | } 33 | 34 | module.exports = Robot; 35 | -------------------------------------------------------------------------------- /commands/Image/snake.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const fetch = require("node-fetch"); 3 | const { RichEmbed } = require("discord.js"); 4 | const { UNSPLASH_ACCESS_KEY } = process.env; 5 | 6 | class Snake extends Command { 7 | constructor(client) { 8 | super(client, { 9 | name: "snake", 10 | description: "Sends a random image of a snake.", 11 | category: "Image", 12 | usage: "snake", 13 | aliases: ["snek"] 14 | }); 15 | } 16 | 17 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 18 | const page = Math.floor(Math.random() * 5) + 1; 19 | const index = Math.floor(Math.random() * 10) + 1; 20 | 21 | const randomColor = "#0000".replace(/0/g, () => { 22 | return (~~(Math.random() * 16)).toString(16); 23 | }); 24 | 25 | const meta = { "Authorization": `Client-ID ${UNSPLASH_ACCESS_KEY}` }; 26 | 27 | message.channel.startTyping(); 28 | 29 | fetch(`https://api.unsplash.com/search/photos?page=${page}&query=snake`, { headers: meta }) 30 | .then(res => res.json()) 31 | .then(json => { 32 | const data = json.results[parseInt(index.toFixed(0))]; 33 | const embed = new RichEmbed() 34 | .setTitle("🐍 Snake") 35 | .setURL(data.urls.raw) 36 | .setDescription(`Photo by [${data.user.name}](${data.user.links.html}) on [Unsplash](https://unsplash.com)`) 37 | .setImage(data.urls.raw) 38 | .setColor(randomColor) 39 | .setTimestamp(); 40 | message.channel.send({ embed }); 41 | }) 42 | .catch(error => { 43 | message.channel.stopTyping(true); 44 | if (error.message === "Cannot read property 'urls' of undefined") return message.channel.send(texts.general.noResultsFound); 45 | this.client.logger.error(error); 46 | return message.channel.send(texts.general.error.replace(/{{err}}/g, error.message)); 47 | }); 48 | 49 | message.channel.stopTyping(true); 50 | } 51 | } 52 | 53 | module.exports = Snake; 54 | -------------------------------------------------------------------------------- /commands/Information/about.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const delet = require("../../package.json"); 3 | const { RichEmbed, version } = require("discord.js"); 4 | const moment = require("moment"); 5 | 6 | class About extends Command { 7 | constructor(client) { 8 | super(client, { 9 | name: "about", 10 | description: "Displays information about me!", 11 | category: "Information", 12 | usage: "about", 13 | aliases: ["info"] 14 | }); 15 | } 16 | 17 | async run(message, args, level, settings, texts) { 18 | let displayColor; 19 | if (message.channel.type === "text") displayColor = message.guild.me.displayColor; 20 | else if (message.channel.type === "dm" || message.channel.type === "group") { 21 | displayColor = "#0000".replace(/0/g, () => { 22 | return (~~(Math.random() * 16)).toString(16); 23 | }); 24 | } 25 | 26 | try { 27 | const embed = new RichEmbed() 28 | .setColor(displayColor) 29 | .setThumbnail(this.client.user.displayAvatarURL) 30 | .setTitle(`Hey ${message.author.username}, I'm delet!`) 31 | .setDescription("I'm a bot developed and maintained by the DS Development Group.") 32 | .addField("Version", delet.version, true) 33 | .addField("Website", "https://delet.js.org", true) 34 | .addField("Users", this.client.users.size, true) 35 | .addField("Invite link", "[Click here](https://delet.js.org/go/invite)", true) 36 | .addField("Uptime", `${moment.utc(this.client.uptime).format("DD")-1} day(s), ${moment.utc(this.client.uptime).format("HH:mm:ss")}`, true) 37 | .addField("GitHub", "[Click here](https://github.com/DS-Development/delet)", true) 38 | .addField("Node.js version", process.version, true) 39 | .addField("Memory usage", `${(process.memoryUsage().heapUsed / 1024 / 1024).toFixed(2)} MB`, true) 40 | .setFooter(`Made with Discord.js (v${version})`, "https://vgy.me/ZlOMAx.png") 41 | .setTimestamp(); 42 | 43 | message.channel.send({ embed }); 44 | } catch (error) { 45 | this.client.logger.error(error); 46 | return message.channel.send(texts.general.error.replace(/{{err}}/g, error.message)); 47 | } 48 | } 49 | } 50 | 51 | module.exports = About; -------------------------------------------------------------------------------- /commands/Information/avatar.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const { RichEmbed } = require("discord.js"); 3 | 4 | class Avatar extends Command { 5 | constructor(client) { 6 | super(client, { 7 | name: "avatar", 8 | description: "Sends the mentioned user's avatar.", 9 | category: "Information", 10 | usage: "avatar [@mention]", 11 | aliases: ["ava", "avy"] 12 | }); 13 | } 14 | 15 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 16 | const user = message.mentions.users.first() || message.author; 17 | 18 | const embed = new RichEmbed() 19 | .setTitle(`🖼️ ${texts.cmd.info.avatar.replace(/{{user}}/g, user.tag)}`) 20 | .setDescription(`🔗 **[Direct URL](${user.displayAvatarURL})**`) 21 | .setImage(user.displayAvatarURL); 22 | return message.channel.send({ embed }); 23 | } 24 | } 25 | 26 | module.exports = Avatar; -------------------------------------------------------------------------------- /commands/Information/channelid.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | 3 | class ChannelID extends Command { 4 | constructor(client) { 5 | super(client, { 6 | name: "channelid", 7 | description: "Returns the ID of the current channel.", 8 | category: "Information", 9 | usage: "channelid", 10 | aliases: ["channel-id", "cid"] 11 | }); 12 | } 13 | 14 | async run(message, args, level) { // eslint-disable-line no-unused-vars 15 | message.channel.send(`This channel (${message.channel}) has an ID of \`${message.channel.id}\`.`); 16 | } 17 | } 18 | 19 | module.exports = ChannelID; -------------------------------------------------------------------------------- /commands/Information/channelinfo.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const { RichEmbed } = require("discord.js"); 3 | const moment = require("moment"); 4 | 5 | class ChannelInfo extends Command { 6 | constructor(client) { 7 | super(client, { 8 | name: "channelinfo", 9 | description: "Displays information about the current channel.", 10 | category: "Information", 11 | usage: "channelinfo", 12 | aliases: ["channel", "cinfo"], 13 | guildOnly: true 14 | }); 15 | } 16 | 17 | async run(message, args, level) { // eslint-disable-line no-unused-vars 18 | const chan = message.channel; 19 | 20 | let topic; 21 | if (chan.topic && chan.topic.length > 2048) topic = "[Too long to display!]"; 22 | else topic = chan.topic; 23 | 24 | const createdTimestamp = moment.utc(chan.createdAt).format("YYYYMMDD"); 25 | const randomColor = "#0000".replace(/0/g, () => { 26 | return (~~(Math.random() * 16)).toString(16); 27 | }); 28 | 29 | const embed = new RichEmbed() 30 | .setColor(randomColor) 31 | .setThumbnail("https://vgy.me/9fSC7k.png") 32 | .setTitle(`Channel Information for #${chan.name}`) 33 | .addField("Created", chan.createdAt, true) 34 | .addField("Age", moment(createdTimestamp, "YYYYMMDD").fromNow().slice(0, -4), true) 35 | .addField("Type", chan.type.toProperCase(), true) 36 | .addField("Position", chan.calculatedPosition, true) 37 | .addField("Parent", !chan.parent ? "None" : chan.parent.name, true) 38 | .addField("NSFW", chan.nsfw.toString().toProperCase(), true) 39 | .addField("Deletable", chan.deletable.toString().toProperCase(), true) 40 | .addField("Topic", !topic ? "No topic set." : topic, true) 41 | .setFooter(`Channel ID: ${chan.id}`, "https://vgy.me/167efD.png") 42 | .setTimestamp(); 43 | 44 | message.channel.send({ embed }); 45 | } 46 | } 47 | 48 | module.exports = ChannelInfo; 49 | -------------------------------------------------------------------------------- /commands/Information/discriminator.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | 3 | class Discriminator extends Command { 4 | constructor(client) { 5 | super(client, { 6 | name: "discriminator", 7 | description: "Searches for users with the specified discriminator.", 8 | category: "Information", 9 | usage: "discriminator [#xxxx]", 10 | aliases: ["discrim", "discriminator-search", "discrim-search"] 11 | }); 12 | } 13 | 14 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 15 | let discrim = args[0]; 16 | if (!discrim) { 17 | discrim = message.author.discriminator; 18 | } 19 | 20 | if (discrim.startsWith("#")) { 21 | discrim = discrim.slice(1); 22 | } 23 | 24 | if (/^[0-9]+$/.test(discrim) && discrim.length === 4) { 25 | const users = this.client.users.filter(user => user.discriminator === discrim).map(user => user.username); 26 | if (users.length === 0) return message.channel.send(`${texts.cmd.info.discrimNotFound.replace(/{{discrim}}/g, discrim)} <:feelsbadman:379645743583199232>`); 27 | return message.channel.send(`**${users.length}** ${texts.cmd.info.discrim.replace(/{{discrim}}/g, discrim)}:\n\`\`\`yml\n${users.join(", ")}\`\`\``); 28 | } else { 29 | return message.channel.send(texts.cmd.info.invalidDiscrim); 30 | } 31 | } 32 | } 33 | 34 | module.exports = Discriminator; -------------------------------------------------------------------------------- /commands/Information/dsdev.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | 3 | class DSDev extends Command { 4 | constructor(client) { 5 | super(client, { 6 | name: "dsdev", 7 | description: "Interested in joining my development team?", 8 | category: "Information", 9 | usage: "dsdev", 10 | aliases: ["hireme", "joinus", "ds-development"] 11 | }); 12 | } 13 | 14 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 15 | message.channel.send(`${texts.cmd.info.dsDev} **https://delet.js.org/go/join**.`); 16 | } 17 | } 18 | 19 | module.exports = DSDev; 20 | -------------------------------------------------------------------------------- /commands/Information/emojiimage.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const { RichEmbed } = require("discord.js"); 3 | 4 | class EmojiImage extends Command { 5 | constructor(client) { 6 | super(client, { 7 | name: "emojiimage", 8 | description: "Sends the specified emoji as an image.", 9 | category: "Information", 10 | usage: "emojiimage ", 11 | aliases: ["emoji-image", "bigemoji", "hugemoji", "hugeemoji"] 12 | }); 13 | } 14 | 15 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 16 | if (!args[0]) return message.channel.send(texts.cmd.info.noEmoji); 17 | if (args[0].startsWith("= 55296) return message.channel.send(`${texts.cmd.info.regularEmoji.replace(/{{emoji}}/g, args[0])}\nhttps://twemoji.twitter.com`); 19 | 20 | const match = args[0].match(/<:[a-zA-Z0-9_-]+:(\d{18})>/); 21 | if (!match || !match[1]) return message.channel.send(texts.cmd.info.invalidEmoji); 22 | 23 | // Using the `emojis` property from Client rather than Guild so Nitro users can use this command for a wider range of emojis 24 | const emoji = this.client.emojis.get(match[1]); 25 | if (!emoji) return message.channel.send(texts.cmd.info.invalidEmoji); 26 | 27 | const embed = new RichEmbed() 28 | .setColor(2934736) 29 | .setTitle(emoji.name) 30 | .setImage(emoji.url); 31 | 32 | return message.channel.send({ embed }); 33 | } 34 | } 35 | 36 | module.exports = EmojiImage; 37 | -------------------------------------------------------------------------------- /commands/Information/emojiinfo.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const { RichEmbed } = require("discord.js"); 3 | const moment = require("moment"); 4 | 5 | class EmojiInfo extends Command { 6 | constructor(client) { 7 | super(client, { 8 | name: "emojiinfo", 9 | description: "Displays information about the specified emoji.", 10 | category: "Information", 11 | usage: "emojiinfo ", 12 | aliases: ["emoji-info", "einfo"] 13 | }); 14 | } 15 | 16 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 17 | if (!args[0]) return message.channel.send(texts.cmd.info.noEmoji); 18 | if (args[0].startsWith("= 55296) return message.channel.send(`${texts.cmd.info.regularEmoji.replace(/{{emoji}}/g, args[0])}\nhttps://twemoji.twitter.com`); 20 | 21 | const match = args[0].match(/<:[a-zA-Z0-9_-]+:(\d{18})>/); 22 | if (!match || !match[1]) return message.channel.send(texts.cmd.info.invalidEmoji); 23 | 24 | // Using the `emojis` property from Client rather than Guild so Nitro users can use this command for a wider range of emojis 25 | const emoji = this.client.emojis.get(match[1]); 26 | if (!emoji) return message.channel.send(texts.cmd.info.invalidEmoji); 27 | 28 | const embed = new RichEmbed() 29 | .setColor(2934736) 30 | .setTitle("Emoji Information") 31 | .setThumbnail(emoji.url) 32 | .addField("❯ Name", emoji.name, true) 33 | .addField("❯ ID", emoji.id, true) 34 | .addField("❯ Created", moment.utc(emoji.createdAt).format("DD/MM/YYYY"), true) 35 | .addField("❯ From", emoji.guild, true) 36 | .setFooter(`Info requested by ${message.author.tag}`, message.author.displayAvatarURL) 37 | .setTimestamp(); 38 | 39 | return message.channel.send({ embed }); 40 | } 41 | } 42 | 43 | module.exports = EmojiInfo; 44 | -------------------------------------------------------------------------------- /commands/Information/feedback.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const delet = require("../../package.json"); 3 | const { stripIndents } = require("common-tags"); 4 | 5 | class Feedback extends Command { 6 | constructor(client) { 7 | super(client, { 8 | name: "feedback", 9 | description: "Want to give feedback? Encountered any bugs?", 10 | category: "Information", 11 | usage: "feedback", 12 | aliases: ["suggestion", "suggestions", "suggest", "bug", "bugs"] 13 | }); 14 | } 15 | 16 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 17 | const suggest = ""; 18 | const issues = `<${delet.bugs.url}>`; 19 | 20 | message.channel.send(stripIndents` 21 | ${texts.cmd.info.feedbackQuestion} 22 | 23 | **${texts.cmd.info.suggestions}**: ${suggest}. 24 | **${texts.cmd.info.issues}**: ${issues}.`); 25 | } 26 | } 27 | 28 | module.exports = Feedback; 29 | -------------------------------------------------------------------------------- /commands/Information/github.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const { RichEmbed } = require("discord.js"); 3 | const fetch = require("node-fetch"); 4 | const moment = require("moment"); 5 | 6 | class GitHub extends Command { 7 | constructor(client) { 8 | super(client, { 9 | name: "github", 10 | description: "Returns information about the specified GitHub repository.", 11 | category: "Information", 12 | usage: "github ", 13 | aliases: ["repo", "repo-info", "repository-info"] 14 | }); 15 | } 16 | 17 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 18 | let owner = args[0]; 19 | if (!owner) return message.channel.send("You must provide the repository owner's username or organisation name."); 20 | else owner = encodeURIComponent(args[0]); 21 | 22 | let repo = args[1]; 23 | if (!repo) return message.channel.send("You must provide a repository name to search for."); 24 | else repo = encodeURIComponent(args[1]); 25 | 26 | fetch(`https://api.github.com/repos/${owner}/${repo}`) 27 | .then(res => res.json()) 28 | .then(data => { 29 | const embed = new RichEmbed() 30 | .setColor(0) 31 | .setThumbnail(data.owner.avatar_url) 32 | .setAuthor("GitHub", "https://vgy.me/B4CvF1.png") 33 | .setTitle(data.full_name) 34 | .setURL(data.html_url) 35 | .setDescription(data.description ? data.description : "[No description set]") 36 | .addField("❯ Created", moment.utc(data.created_at).format("DD/MM/YYYY HH:mm:ss"), true) 37 | .addField("❯ Last updated", moment.utc(data.updated_at, "YYYYMMDD").fromNow(), true) 38 | .addField("❯ Stars", data.stargazers_count, true) 39 | .addField("❯ Forks", data.forks, true) 40 | .addField("❯ Issues", data.open_issues, true) 41 | .addField("❯ Language", data.language || "No language", true) 42 | .addField("❯ License", data.license ? data.license.spdx_id : "Unlicensed", true) 43 | .addField("❯ Archived?", data.archived.toString().toProperCase(), true) 44 | .setFooter("All times are UTC") 45 | .setTimestamp(); 46 | return message.channel.send({ embed }); 47 | }) 48 | .catch(error => { 49 | if (error.status === 404) return message.channel.send(texts.general.noResultsFound); 50 | this.client.logger.error(error); 51 | return message.channel.send(texts.general.error.replace(/{{err}}/g, error.message)); 52 | }); 53 | } 54 | } 55 | 56 | module.exports = GitHub; 57 | -------------------------------------------------------------------------------- /commands/Information/logo.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const fetch = require("node-fetch"); 3 | 4 | class Logo extends Command { 5 | constructor(client) { 6 | super(client, { 7 | name: "logo", 8 | description: "Sends a website's logo.", 9 | category: "Information", 10 | usage: "logo " 11 | }); 12 | } 13 | 14 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 15 | const query = args[0]; 16 | if (!query) return message.channel.send(texts.general.invalidURL); 17 | 18 | const url = `https://logo.clearbit.com/${query.startsWith("<") ? query.replace(/<(.+)>/g, "$1") : query}?size=500`; 19 | 20 | fetch(url) 21 | .then(res => message.channel.send({ files: [{ attachment: res.body, name: "logo.jpg" }] })) 22 | .catch(error => { 23 | if (error.message === "404 Not Found") return message.channel.send(texts.general.noResultsFound); 24 | this.client.logger.error(error); 25 | return message.channel.send(texts.general.error.replace(/{{err}}/g, error.message)); 26 | }); 27 | } 28 | } 29 | 30 | module.exports = Logo; 31 | -------------------------------------------------------------------------------- /commands/Information/nasa.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const fetch = require("node-fetch"); 3 | const h = new (require("html-entities").AllHtmlEntities)(); 4 | 5 | class NASA extends Command { 6 | constructor(client) { 7 | super(client, { 8 | name: "nasa", 9 | description: "Searches NASA's image database.", 10 | usage: "nasa ", 11 | aliases: ["space"] 12 | }); 13 | } 14 | 15 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 16 | let query = args.join(" "); 17 | if (!query) return message.channel.send("You must provide a query to search NASA's image database for."); 18 | else query = encodeURIComponent(args.join(" ")); 19 | 20 | fetch(`https://images-api.nasa.gov/search?q=${query}&media_type=image`) 21 | .then(res => res.json()) 22 | .then(body => { 23 | const images = body.collection.items; 24 | if (!images.length || images.length === 0) return message.channel.send("No results found."); 25 | 26 | const data = images.random(); 27 | const description = h.decode(data.data[0].description); 28 | 29 | message.channel.send(description.length > 1997 ? description.substring(0, 1997) + "..." : description.substring(0, 2000) + " <:NASA:476079744857931796>", { 30 | file: data.links[0].href 31 | }); 32 | }) 33 | .catch(error => { 34 | this.client.logger.error(error); 35 | message.channel.send(texts.general.error.replace(/{{err}}/g, error)); 36 | }); 37 | } 38 | } 39 | 40 | module.exports = NASA; 41 | -------------------------------------------------------------------------------- /commands/Information/serverinfo.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const { RichEmbed } = require("discord.js"); 3 | const { stripIndents } = require("common-tags"); 4 | const moment = require("moment"); 5 | 6 | const verificationLevels = { 7 | 0: "None", 8 | 1: "Low", 9 | 2: "Medium", 10 | 3: "(╯°□°)╯︵ ┻━┻", 11 | 4: "┻━┻ ミヽ(ಠ益ಠ)ノ彡┻━┻" 12 | }; 13 | 14 | const contentFilterLevels = { 15 | 0: "None", 16 | 1: "Medium", 17 | 2: "High" 18 | }; 19 | 20 | class ServerInfo extends Command { 21 | constructor(client) { 22 | super(client, { 23 | name: "serverinfo", 24 | description: "Displays information about the current server.", 25 | category: "Information", 26 | usage: "serverinfo", 27 | aliases: ["sinfo", "server", "guildinfo", "guild"], 28 | guildOnly: true 29 | }); 30 | } 31 | 32 | async run(message, args, level) { // eslint-disable-line no-unused-vars 33 | const randomColor = "#0000".replace(/0/g, () => { 34 | return (~~(Math.random() * 16)).toString(16); 35 | }); 36 | 37 | const createdTimestamp = moment.utc(message.guild.createdAt).format("YYYYMMDD"); 38 | 39 | const embed = new RichEmbed() 40 | .setColor(randomColor) 41 | .setThumbnail(message.guild.iconURL) 42 | .setTitle(`Server Information for ${message.guild.name}`) 43 | .setDescription(`**Server ID:** ${message.guild.id}`) 44 | 45 | .addField("❯ Details", stripIndents` 46 | • Created: **${moment.utc(message.guild.createdAt).format("dddd, Do MMMM YYYY @ HH:mm:ss")}** (${moment(createdTimestamp, "YYYYMMDD").fromNow()}) 47 | • Owner: **${message.guild.owner.user.tag}** 48 | • Region: **${message.guild.region.toProperCase()}** 49 | • Verification: **${verificationLevels[message.guild.verificationLevel]}** 50 | ‍ 51 | `, true) 52 | 53 | .addField("❯ Users", stripIndents` 54 | • Users: **${message.guild.memberCount - message.guild.members.filter(m => m.user.bot).size}** 55 | • Bots: **${message.guild.members.filter(m => m.user.bot).size}** 56 | 57 | `, true) 58 | 59 | .addField("❯ Roles", stripIndents` 60 | • Default: **${message.guild.defaultRole.name}** 61 | • Count: **${message.guild.roles.size} roles** 62 | `, true) 63 | 64 | .addField("❯ Channels", stripIndents` 65 | • Text: **${message.guild.channels.filter(ch => ch.type === "text").size}** 66 | • Voice: **${message.guild.channels.filter(ch => ch.type === "voice").size}** 67 | • AFK: **${message.guild.afkChannel ? message.guild.afkChannel.name : "None"}** 68 | `, true) 69 | 70 | .addField("❯ Other", stripIndents` 71 | • AFK: After **${message.guild.afkTimeout / 60} min** 72 | • Large? **${message.guild.large.toString().toProperCase()}** 73 | • Content filter level: **${contentFilterLevels[message.guild.explicitContentFilter]}** 74 | 75 | `, true) 76 | 77 | .setFooter(`Info requested by ${message.author.tag} • All times are UTC`, message.author.displayAvatarURL); 78 | 79 | message.channel.send({ embed }); 80 | } 81 | } 82 | 83 | module.exports = ServerInfo; -------------------------------------------------------------------------------- /commands/Information/stats.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 An Idiot's Guide. All rights reserved. MIT license. 2 | // https://github.com/AnIdiotsGuide/guidebot-class 3 | 4 | const Command = require("../../base/Command.js"); 5 | const pkg = require("../../package.json"); 6 | const { NODE_ENV } = process.env; 7 | const { version } = require("discord.js"); 8 | const { stripIndents } = require("common-tags"); 9 | const moment = require("moment"); 10 | require("moment-duration-format"); 11 | 12 | class Stats extends Command { 13 | constructor(client) { 14 | super(client, { 15 | name: "stats", 16 | description: "Sends some useful bot statistics.", 17 | category: "Information", 18 | usage: "stats", 19 | aliases: ["statistics"] 20 | }); 21 | } 22 | 23 | async run(message, args, level) { // eslint-disable-line no-unused-vars 24 | const duration = moment.duration(this.client.uptime).format(" D [days], H [hrs], m [mins], s [secs]"); 25 | 26 | message.channel.send(stripIndents` 27 | = STATISTICS = 28 | • Users :: ${this.client.users.size.toLocaleString()} 29 | • Servers :: ${this.client.guilds.size.toLocaleString()} 30 | • Channels :: ${this.client.channels.size.toLocaleString()} 31 | • Uptime :: ${duration} 32 | • RAM usage :: ${(process.memoryUsage().heapUsed / 1024 / 1024).toFixed(2)} MB 33 | • Build :: ${NODE_ENV.toProperCase()} 34 | • Platform :: ${process.platform === "win32" ? "Windows" : process.platform.toProperCase()} 35 | 36 | = VERSIONS = 37 | • delet :: v${pkg.version} 38 | • Discord.js :: v${version} 39 | • Node.js :: ${process.version}`, { code: "asciidoc" }); 40 | } 41 | } 42 | 43 | module.exports = Stats; 44 | -------------------------------------------------------------------------------- /commands/Information/time.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const { stripIndents } = require("common-tags"); 3 | 4 | class Time extends Command { 5 | constructor(client) { 6 | super(client, { 7 | name: "time", 8 | description: "Returns the current time in a specified timezone.", 9 | category: "Information", 10 | usage: "time /", 11 | aliases: ["timezone", "worldtime"] 12 | }); 13 | } 14 | 15 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 16 | const link = "https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List"; 17 | const timeZone = args.join("_").toUpperCase(); 18 | if (!timeZone) return message.channel.send(stripIndents` 19 | You must provide a timezone to look up the time for. 20 | For a full list of timezones, refer to the "TZ" column here: **<${link}>**. 21 | `); 22 | 23 | try { 24 | const time = new Date().toLocaleTimeString("en-GB", { timeZone, hour12: false }); 25 | const friendly = timeZone.substring(timeZone.indexOf("/") + 1).replace(/_/g, " "); 26 | return message.channel.send(`The time in **${friendly.toProperCase()}** is currently **${time}**.`); 27 | } catch (err) { 28 | message.channel.send(stripIndents` 29 | ${texts.general.error.replace(/{{err}}/g, err.message)} 30 | For a full list of timezones, refer to the "TZ" column here: **<${link}>**. 31 | 32 | • Please ensure you are using the correct format, e.g. \`${settings.prefix}time europe/london\`. 33 | • Note that the continent of North America is split into **America** and **Canada**, e.g. \`${settings.prefix}time america/new york\`. 34 | `); 35 | } 36 | } 37 | } 38 | 39 | module.exports = Time; -------------------------------------------------------------------------------- /commands/Information/timezones.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const moment = require("moment-timezone"); 3 | const { stripIndents } = require("common-tags"); 4 | 5 | const unix = Math.round(+new Date() / 1000); 6 | 7 | class Timezones extends Command { 8 | constructor(client) { 9 | super(client, { 10 | name: "timezones", 11 | description: "Returns a list of current times in popular timezones.", 12 | category: "Information", 13 | usage: "timezones", 14 | aliases: ["times", "worldtimes", "now"] 15 | }); 16 | } 17 | 18 | async run(message, args, level) { // eslint-disable-line no-unused-vars 19 | message.channel.send(stripIndents` 20 | = T I M E Z O N E S = 21 | 22 | // Africa 23 | • EAT :: [${moment().tz("Africa/Nairobi").format("HH:mm ZZ")}] 24 | • CAT :: [${moment().tz("Africa/Maputo").format("HH:mm ZZ")}] 25 | • WAT :: [${moment().tz("Africa/Lagos").format("HH:mm ZZ")}] 26 | • WEST :: [${moment().tz("Africa/Accra").format("HH:mm ZZ")}] 27 | 28 | // America 29 | • EDT :: [${moment().tz("America/New_York").format("HH:mm ZZ")}] 30 | • CDT :: [${moment().tz("America/Chicago").format("HH:mm ZZ")}] 31 | • MDT :: [${moment().tz("America/Denver").format("HH:mm ZZ")}] 32 | • AKDT :: [${moment().tz("America/Anchorage").format("HH:mm ZZ")}] 33 | • UTC-10 :: [${moment().tz("Pacific/Honolulu").format("HH:mm ZZ")}] 34 | 35 | // Asia 36 | • MVT :: [${moment().tz("Indian/Maldives").format("HH:mm ZZ")}] 37 | • IST :: [${moment().tz("Asia/Calcutta").format("HH:mm ZZ")}] 38 | • BTT :: [${moment().tz("Asia/Dhaka").format("HH:mm ZZ")}] 39 | • ICT :: [${moment().tz("Asia/Bangkok").format("HH:mm ZZ")}] 40 | • CST :: [${moment().tz("Asia/Hong_Kong").format("HH:mm ZZ")}] 41 | 42 | // Europe 43 | • UTC/GMT :: [${moment.utc().format("HH:mm ZZ")}] 44 | • BST :: [${moment().tz("Europe/London").format("HH:mm ZZ")}] 45 | • CEST :: [${moment().tz("Europe/Zurich").format("HH:mm ZZ")}] 46 | • EEST :: [${moment().tz("Europe/Helsinki").format("HH:mm ZZ")}] 47 | • FET :: [${moment().tz("Europe/Minsk").format("HH:mm ZZ")}] 48 | 49 | // Oceania 50 | • AWST :: [${moment().tz("Australia/Perth").format("HH:mm ZZ")}] 51 | • ACST :: [${moment().tz("Australia/Darwin").format("HH:mm ZZ")}] 52 | • AEST :: [${moment().tz("Australia/Sydney").format("HH:mm ZZ")}] 53 | • NZST :: [${moment().tz("Pacific/Auckland").format("HH:mm ZZ")}] 54 | 55 | // Other 56 | • UNIX :: [${unix}]`, { code: "asciidoc" }); 57 | } 58 | } 59 | 60 | module.exports = Timezones; -------------------------------------------------------------------------------- /commands/Information/tweet.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const fetch = require("node-fetch"); 3 | const snekfetch = require("snekfetch"); 4 | const { RichEmbed } = require("discord.js"); 5 | const { base64 } = require("../../util/Utils.js"); 6 | const { TWITTER_API_KEY, TWITTER_SECRET } = process.env; 7 | 8 | class Tweet extends Command { 9 | constructor(client) { 10 | super(client, { 11 | name: "tweet", 12 | description: "Returns the specified user's latest tweet.", 13 | category: "Information", 14 | usage: "tweet ", 15 | aliases: ["latesttweet", "latest-tweet"] 16 | }); 17 | 18 | this.token = null; 19 | } 20 | 21 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 22 | const user = args[0]; 23 | if (!user) return message.channel.send("You must specify a Twitter user whose latest tweet you'd like to see."); 24 | 25 | if (!this.token) await this.fetchToken(); 26 | 27 | const url = `https://api.twitter.com/1.1/users/show.json?screen_name=${user}`; 28 | const meta = { "Authorization": `Bearer ${this.token}` }; 29 | 30 | fetch(url, { headers: meta }) 31 | .then(res => res.json()) 32 | .then(data => { 33 | const embed = new RichEmbed() 34 | .setColor(12639981) 35 | .setThumbnail(data.profile_image_url_https) 36 | .setAuthor("Latest Tweet", "https://vgy.me/8tgKd0.png") 37 | .setTitle(`${data.name} (@${data.screen_name})`) 38 | .setURL(`https://twitter.com/${data.screen_name}`) 39 | .setDescription(data.status ? data.status.text : "???"); 40 | return message.channel.send({ embed }); 41 | }) 42 | .catch(error => { 43 | if (error.statusCode === 401) this.fetchToken(); 44 | if (error.statusCode === 404) return message.channel.send(texts.general.noResultsFound); 45 | this.client.logger.error(error); 46 | return message.channel.send(texts.general.error.replace(/{{err}}/g, error.message)); 47 | }); 48 | } 49 | 50 | async fetchToken() { 51 | const { body } = await snekfetch 52 | .post("https://api.twitter.com/oauth2/token") 53 | .set({ 54 | Authorization: `Basic ${base64(`${TWITTER_API_KEY}:${TWITTER_SECRET}`)}`, 55 | "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8" 56 | }) 57 | .send("grant_type=client_credentials"); 58 | 59 | this.token = body.access_token; 60 | return body; 61 | } 62 | } 63 | 64 | module.exports = Tweet; 65 | -------------------------------------------------------------------------------- /commands/Information/twitter.js: -------------------------------------------------------------------------------- 1 | // Based on Xiao's Twitter command (https://github.com/dragonfire535/xiao/) 2 | // Licensed under the GNU General Public License v3.0 3 | 4 | const Command = require("../../base/Command.js"); 5 | const snekfetch = require("snekfetch"); 6 | const { RichEmbed } = require("discord.js"); 7 | const { base64 } = require("../../util/Utils.js"); 8 | const { TWITTER_API_KEY, TWITTER_SECRET } = process.env; 9 | 10 | class Twitter extends Command { 11 | constructor(client) { 12 | super(client, { 13 | name: "twitter", 14 | description: "Returns info about a Twitter user.", 15 | category: "Information", 16 | usage: "twitter ", 17 | aliases: ["twitterinfo", "twitter-info", "tinfo"] 18 | }); 19 | 20 | this.token = null; 21 | } 22 | 23 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 24 | const user = args[0]; 25 | if (!user) return message.channel.send("You must specify a Twitter user to get information on."); 26 | 27 | try { 28 | if (!this.token) await this.fetchToken(); 29 | const { body } = await snekfetch 30 | .get("https://api.twitter.com/1.1/users/show.json") 31 | .set({ Authorization: `Bearer ${this.token}` }) 32 | .query({ screen_name: user }); 33 | 34 | const embed = new RichEmbed() 35 | .setColor(44269) 36 | .setThumbnail(body.profile_image_url_https) 37 | .setAuthor("Twitter", "https://vgy.me/a7ii9V.png") 38 | .setTitle(`${body.name} (@${body.screen_name})`) 39 | .setURL(`https://twitter.com/${body.screen_name}`) 40 | .setDescription(body.description) 41 | .addField("❯ Followers", body.followers_count, true) 42 | .addField("❯ Following", body.friends_count, true) 43 | .addField("❯ Tweets", body.statuses_count, true) 44 | .addField("❯ Protected", body.protected ? "Yes" : "No", true) 45 | .addField("❯ Verified", body.verified ? "Yes" : "No", true) 46 | .addField("❯ Created", new Date(body.created_at).toDateString(), true) 47 | .addField("❯ Latest Tweet", body.status ? body.status.text : "???") 48 | .setFooter(`Info requested by ${message.author.tag}`, message.author.displayAvatarURL) 49 | .setTimestamp(); 50 | 51 | return message.channel.send({ embed }); 52 | } catch (error) { 53 | if (error.statusCode === 401) await this.fetchToken(); 54 | if (error.statusCode === 404) return message.channel.send(texts.general.noResultsFound); 55 | this.client.logger.error(error); 56 | return message.channel.send(texts.general.error.replace(/{{err}}/g, error.message)); 57 | } 58 | } 59 | 60 | async fetchToken() { 61 | const { body } = await snekfetch 62 | .post("https://api.twitter.com/oauth2/token") 63 | .set({ 64 | Authorization: `Basic ${base64(`${TWITTER_API_KEY}:${TWITTER_SECRET}`)}`, 65 | "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8" 66 | }) 67 | .send("grant_type=client_credentials"); 68 | 69 | this.token = body.access_token; 70 | return body; 71 | } 72 | } 73 | 74 | module.exports = Twitter; 75 | -------------------------------------------------------------------------------- /commands/Information/uptime.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const { stripIndents } = require("common-tags"); 3 | const moment = require("moment"); 4 | require("moment-duration-format"); 5 | 6 | class Uptime extends Command { 7 | constructor(client) { 8 | super(client, { 9 | name: "uptime", 10 | description: "Displays delet's uptime.", 11 | category: "Information", 12 | usage: "uptime" 13 | }); 14 | } 15 | 16 | async run(message, args, level, settings) { // eslint-disable-line no-unused-vars 17 | const uptime = moment.duration(this.client.uptime).format("D [days], H [hrs], m [mins], s [secs]"); 18 | message.channel.send(stripIndents` 19 | \`\`\`asciidoc 20 | • Uptime :: ${uptime} 21 | \`\`\` 22 | For a full list of bot stats, use the \`${settings.prefix}stats\` command. 23 | `); 24 | } 25 | } 26 | 27 | module.exports = Uptime; -------------------------------------------------------------------------------- /commands/Information/userid.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | 3 | class UserID extends Command { 4 | constructor(client) { 5 | super(client, { 6 | name: "userid", 7 | description: "Returns the mentioned user's user ID.", 8 | category: "Information", 9 | usage: "userid [@user]", 10 | aliases: ["id"] 11 | }); 12 | } 13 | 14 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 15 | const user = message.mentions.users.first() || message.author; 16 | 17 | message.channel.send(`**${user.tag}**'s user ID is: \`${user.id}\`.`) 18 | .catch((e) => { 19 | this.client.logger.error(e.stack); 20 | return message.channel.send(texts.general.error.replace(/{{err}}/g, e.message)); 21 | }); 22 | } 23 | } 24 | 25 | module.exports = UserID; -------------------------------------------------------------------------------- /commands/Information/userinfo.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const { RichEmbed } = require("discord.js"); 3 | const { stripIndents } = require("common-tags"); 4 | const moment = require("moment"); 5 | 6 | class UserInfo extends Command { 7 | constructor(client) { 8 | super(client, { 9 | name: "userinfo", 10 | description: "Displays information about the mentioned user.", 11 | category: "Information", 12 | usage: "userinfo [@user]", 13 | aliases: ["uinfo", "user", "whois"], 14 | guildOnly: true 15 | }); 16 | } 17 | 18 | async run(message, args, level) { // eslint-disable-line no-unused-vars 19 | if (!message.guild.available) return this.client.logger.info(`Guild "${message.guild.name}" (${message.guild.id}) is unavailable.`); 20 | 21 | const user = message.mentions.users.first() || message.author; 22 | 23 | let status; 24 | if (user.presence.status.toProperCase() === "Dnd") { 25 | status = "Do Not Disturb"; 26 | } else { 27 | status = user.presence.status.toProperCase(); 28 | } 29 | 30 | let activity = ""; 31 | 32 | if (!user.presence.game) { 33 | activity = "Nothing"; 34 | } 35 | 36 | if (user.presence.game) { 37 | activity = `Playing **${user.presence.game ? user.presence.game.name : "Nothing"}**`; 38 | } 39 | 40 | // if (user.presence.game.name === "Spotify") { 41 | // activity = "Listening to **Spotify**"; 42 | // } 43 | 44 | const embed = new RichEmbed() 45 | .setColor(message.guild.member(user).displayColor) 46 | .setThumbnail(user.displayAvatarURL) 47 | .setTitle(`User Information for ${user.tag}`) 48 | .setDescription(`**User ID**: ${user.id}`) 49 | 50 | .addField("❯ Details", stripIndents` 51 | • Status: **${status}** 52 | • Activity: ${activity} 53 | ‍ 54 | `, true) 55 | 56 | .addField("❯ Roles", stripIndents` 57 | • Highest: **\`${message.guild.member(user).highestRole.name}\`** 58 | • All: ${message.guild.member(user).roles.map(roles => `\`${roles.name}\``).slice(1).join(", ")} 59 | ‍ 60 | `, true) 61 | 62 | .addField("❯ Join Dates", stripIndents` 63 | • ${message.guild.name}: **${moment.utc(message.guild.member(user).joinedAt).format("dddd, Do MMMM YYYY @ HH:mm:ss")}** 64 | • Discord: **${moment.utc(user.createdAt).format("dddd, Do MMMM YYYY @ HH:mm:ss")}** 65 | `, true) 66 | 67 | .setFooter(`Info requested by ${message.author.tag} • All times are UTC`, `${message.author.displayAvatarURL}`); 68 | 69 | message.channel.send({ embed }); 70 | } 71 | } 72 | 73 | module.exports = UserInfo; -------------------------------------------------------------------------------- /commands/Information/version.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const moment = require("moment"); 3 | const snekfetch = require("snekfetch"); 4 | const { version } = require("../../package.json"); 5 | 6 | class Version extends Command { 7 | constructor(client) { 8 | super(client, { 9 | name: "version", 10 | description: "Returns delet's version.", 11 | category: "Information", 12 | usage: "version", 13 | aliases: ["ver"] 14 | }); 15 | } 16 | 17 | async run(message, args, level, settings) { // eslint-disable-line no-unused-vars 18 | try { 19 | var { body } = await snekfetch.get("https://api.github.com/repos/DS-Development/delet"); 20 | } catch (error) { 21 | this.client.logger.error(error); 22 | body = "[Error occurred whilst fetching date]"; 23 | } 24 | 25 | message.channel.send(`**Version:** ${version}\n**Last updated:** ${moment.utc(body.updated_at).format("dddd Do MMMM YYYY") || body}`); 26 | } 27 | } 28 | 29 | module.exports = Version; -------------------------------------------------------------------------------- /commands/Information/weather.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const { RichEmbed } = require("discord.js"); 3 | const { stripIndents } = require("common-tags"); 4 | const weather = require("weather-js"); 5 | 6 | class Weather extends Command { 7 | constructor(client) { 8 | super(client, { 9 | name: "weather", 10 | description: "Displays weather information for the specified location.", 11 | category: "Information", 12 | usage: "weather " 13 | }); 14 | } 15 | 16 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 17 | weather.find({ search: args.join(" "), degreeType: "C" }, function(err, result) { 18 | if (!args[0]) return message.channel.send(`You must provide a place to look up weather information for.\nTo see how to use this command, use \`${settings.prefix}help weather\`.`); 19 | if (err) return message.channel.send(`${texts.general.error.replace(/{{err}}/g, err.message)}\nTo see how to use this command, use \`${settings.prefix}help weather\`.`); 20 | 21 | try { 22 | var current = result[0].current; 23 | } catch (error) { 24 | if (error.message === "Cannot read property 'current' of undefined") return message.channel.send("Invalid location provided."); 25 | if (error.message === "ESOCKETTIMEDOUT") return message.channel.send("Request timed out. Please try again."); 26 | console.error(error.message); 27 | return message.channel.send(texts.general.error.replace(/{{err}}/g, error.message)); 28 | } 29 | 30 | const location = result[0].location; // eslint-disable-line no-unused-vars 31 | const ct = current.temperature; 32 | 33 | let col; 34 | 35 | if (ct <= 0) col = 13431807; 36 | else if (ct < 0 && ct >= 5) col = 12579071; 37 | else if (ct >= 6 && ct <= 10) col = 11861906; 38 | else if (ct >= 11 && ct <= 15) col = 9238900; 39 | else if (ct >= 16 && ct <= 20) col = 15531898; 40 | else if (ct >= 21 && ct <= 25) col = 16763258; 41 | else if (ct >= 26 && ct <= 30) col = 16739910; 42 | else if (ct >= 31 && ct <= 35) col = 16730914; 43 | else if (ct >= 36 && ct <= 40) col = 16727074; 44 | else if (ct >= 40) col = 12386304; 45 | else col = 7654911; // fallback 46 | 47 | const embed = new RichEmbed() 48 | .setColor(col) 49 | .setTitle(`Weather information for ${current.observationpoint}`) 50 | .setDescription(stripIndents` 51 | The weather is **${current.skytext.toLowerCase()}** at the moment. 52 | 53 | • Temperature: **${ct}°C** / ${((1.8 * ct) + 32).toFixed(0)}°F 54 | • Feels like: **${current.feelslike}°C** / ${((1.8 * current.feelslike) + 32).toFixed(0)}°F 55 | • Humidity: **${current.humidity}%** 56 | • Wind: **${current.winddisplay.toLowerCase()}** / ~${(current.winddisplay.toLowerCase().replace(/[^0-9]/g,"") * 0.621).toFixed(1)} mph 57 | `) 58 | .setThumbnail(current.imageUrl) 59 | .setFooter(`Correct as of ${current.observationtime.slice(0, -3)} local time`) 60 | .setTimestamp(); 61 | 62 | message.channel.send({ embed }); 63 | }); 64 | } 65 | } 66 | 67 | module.exports = Weather; 68 | -------------------------------------------------------------------------------- /commands/Maths/maths.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const math = require("mathjs"); 3 | 4 | class Maths extends Command { 5 | constructor(client) { 6 | super(client, { 7 | name: "maths", 8 | description: "Evaluates/calculates a given mathematical expression.", 9 | category: "Maths", 10 | usage: "maths ", 11 | aliases: ["math", "calculate"] 12 | }); 13 | } 14 | 15 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 16 | let exp = args.join(" "); 17 | if (!exp) return message.channel.send(texts.cmd.math.noExp.replace(/{{prefix}}/g, settings.prefix)); 18 | if (exp.includes("°")) exp = exp.replace(/°/g, "deg"); 19 | 20 | const msg = await message.channel.send(texts.cmd.math.calculating); 21 | 22 | try { 23 | let evaled = math.eval(exp); 24 | if (isNaN(evaled)) evaled = texts.cmd.math.isNaN; 25 | if (exp.length + evaled.length > 2000) return message.channel.send("Output is too long to fit into a message!"); 26 | 27 | msg.edit(`${exp} = **${evaled}**`); 28 | } catch (error) { 29 | if (error.toString().startsWith("SyntaxError:") || error.message.startsWith("Undefined symbol")) return msg.edit(`**\`SyntaxError:\`** \`${error.message}\``); 30 | 31 | this.client.logger.error(error); 32 | msg.edit(texts.general.error.replace(/{{err}}/g, error.message)); 33 | } 34 | } 35 | } 36 | 37 | module.exports = Maths; 38 | -------------------------------------------------------------------------------- /commands/Maths/pi.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | 3 | class Pi extends Command { 4 | constructor(client) { 5 | super(client, { 6 | name: "pi", 7 | description: "Returns the value of Pi (π).", 8 | category: "Maths", 9 | usage: "pi", 10 | aliases: ["π"] 11 | }); 12 | } 13 | 14 | async run(message, args, level, settings) { // eslint-disable-line no-unused-vars 15 | message.channel.send(`π = **${Math.PI}**...`); 16 | } 17 | } 18 | 19 | module.exports = Pi; 20 | -------------------------------------------------------------------------------- /commands/Maths/prime.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | 3 | class Prime extends Command { 4 | constructor(client) { 5 | super(client, { 6 | name: "prime", 7 | description: "Checks if a number is a prime number.", 8 | category: "Maths", 9 | usage: "prime ", 10 | aliases: ["primenumber", "isprime"] 11 | }); 12 | } 13 | 14 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 15 | const n = parseInt(args[0]); 16 | if (!n) return message.channel.send(texts.cmd.math.noNum); 17 | 18 | const isPrime = n => { 19 | if (isNaN(n) || !isFinite(n) || n%1 || n < 2) return false; 20 | if (n%2 == 0) return (n == 2); 21 | if (n%3 == 0) return (n == 3); 22 | 23 | const m = Math.sqrt(n); 24 | 25 | for (let i = 5; i <= m; i += 6) { 26 | if (n%i == 0) return false; 27 | if (n%(i + 2) == 0) return false; 28 | } 29 | return true; 30 | }; 31 | 32 | if (isPrime(n) === true) { 33 | message.channel.send(`<:tick:398228298842374154> **${n}** ${texts.cmd.math.isPrime}.`); 34 | } 35 | 36 | if (isPrime(n) === false) { 37 | message.channel.send(`<:redX:398228298708025344> **${n}** ${texts.cmd.math.isNotPrime}.`); 38 | } 39 | } 40 | } 41 | 42 | module.exports = Prime; 43 | -------------------------------------------------------------------------------- /commands/Misc/announce.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | 3 | class Announce extends Command { 4 | constructor(client) { 5 | super(client, { 6 | name: "announce", 7 | description: "Sends a specified message to a specified channel.", 8 | usage: "announce ", 9 | aliases: ["send"], 10 | permLevel: "Server Owner", 11 | guildOnly: true 12 | }); 13 | } 14 | 15 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 16 | const content = args.join(" "); 17 | if (!content) return message.channel.send(texts.cmd.system.noMessage); 18 | 19 | const id = await this.client.awaitReply(message, texts.cmd.system.idRequest, 30000); 20 | if (!message.guild.channels.find(c => c.id === id)) return message.channel.send("A channel with that ID does not exist on this server."); 21 | 22 | message.guild.channels.get(id).send(content) 23 | .then(message.react("✅")) 24 | .catch(error => { 25 | if (error.message === "Missing Access") return message.channel.send(`I do not have sufficient permissions to send messages in <#${id}>.`); 26 | this.client.logger.error(error); 27 | }); 28 | } 29 | } 30 | 31 | module.exports = Announce; 32 | -------------------------------------------------------------------------------- /commands/Misc/icon.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const { RichEmbed } = require("discord.js"); 3 | 4 | class Icon extends Command { 5 | constructor(client) { 6 | super(client, { 7 | name: "icon", 8 | description: "Sends the current server's icon.", 9 | usage: "icon", 10 | aliases: ["server-icon", "guild-icon"] 11 | }); 12 | } 13 | 14 | async run(message, args, level) { // eslint-disable-line no-unused-vars 15 | if (!message.guild.available) return this.client.logger.info(`Guild "${message.guild.name}" (${message.guild.id}) is unavailable.`); 16 | 17 | const embed = new RichEmbed() 18 | .setTitle(`Server icon of ${message.guild.name}`) 19 | .setImage(message.guild.iconURL); 20 | 21 | message.channel.send({ embed }); 22 | } 23 | } 24 | 25 | module.exports = Icon; -------------------------------------------------------------------------------- /commands/Misc/invite.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const { botPerms } = require("../../util/data.js"); 3 | 4 | class Invite extends Command { 5 | constructor(client) { 6 | super(client, { 7 | name: "invite", 8 | description: "Generates an invite link, for adding delet to a server.", 9 | usage: "invite", 10 | aliases: ["join"] 11 | }); 12 | } 13 | 14 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 15 | this.client.generateInvite(botPerms).then(link => { 16 | message.channel.send(texts.general.generating) 17 | .then(msg => { 18 | msg.edit(`${texts.cmd.misc.generated}:\n**<${link}>**`); 19 | }); 20 | }); 21 | } 22 | } 23 | 24 | module.exports = Invite; -------------------------------------------------------------------------------- /commands/Misc/invites.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const arraySort = require("array-sort"); 3 | const t = require("table"); 4 | 5 | class Invites extends Command { 6 | constructor(client) { 7 | super(client, { 8 | name: "invites", 9 | description: "Displays the server's invite leaderboard.", 10 | usage: "invites", 11 | guildOnly: true 12 | }); 13 | } 14 | 15 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 16 | if (!message.guild.me.hasPermission("MANAGE_GUILD")) return message.channel.send(texts.general.missingPerm.replace(/{{perm}}/g, "Manage Server")); 17 | 18 | let invites = await message.guild.fetchInvites(); 19 | if (invites.size === 0) return message.channel.send(texts.cmd.misc.noInvites); 20 | invites = invites.array(); 21 | 22 | arraySort(invites, "uses", { reverse: true }); 23 | 24 | const usedInvites = [["User", "Uses"]]; 25 | invites.forEach(invite => usedInvites.push([invite.inviter.tag, invite.uses])); 26 | 27 | return message.channel.send(`**Server Invite Leaderboard** for ${message.guild.name}\n\`\`\`${t.table(usedInvites)}\`\`\``); 28 | } 29 | } 30 | 31 | module.exports = Invites; -------------------------------------------------------------------------------- /commands/Misc/lastmessage.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const { RichEmbed } = require("discord.js"); 3 | 4 | class LastMessage extends Command { 5 | constructor(client) { 6 | super(client, { 7 | name: "lastmessage", 8 | description: "Returns the mentioned user's last message.", 9 | usage: "lastmessage [@user]", 10 | aliases: ["lm"], 11 | guildOnly: true 12 | }); 13 | } 14 | 15 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 16 | const member = message.mentions.members.first() || message.member; 17 | if (!member) return message.channel.send(texts.cmd.misc.noMember); 18 | 19 | const lastMsg = message.guild.member(member).lastMessage; 20 | if (!lastMsg) return message.channel.send("This user's last message could not be found, or they simply may not have sent any messages here."); 21 | 22 | const embed = new RichEmbed() 23 | .setColor(message.guild.member(member).displayColor) 24 | .setAuthor(member.user.tag, member.user.displayAvatarURL) 25 | .setDescription(`*${lastMsg}*`) 26 | .setFooter(`#${message.channel.name}`) 27 | .setTimestamp(); 28 | 29 | message.channel.send({ embed }); 30 | } 31 | } 32 | 33 | module.exports = LastMessage; 34 | -------------------------------------------------------------------------------- /commands/Misc/loremipsum.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const { get } = require("snekfetch"); 3 | 4 | class LoremIpsum extends Command { 5 | constructor(client) { 6 | super(client, { 7 | name: "loremipsum", 8 | description: "Need placeholder text for your website? Look no further.", 9 | usage: "loremipsum", 10 | aliases: ["placeholder", "lorem", "lorem-ipsum"] 11 | }); 12 | } 13 | 14 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 15 | try { 16 | const { raw } = await get("https://loripsum.net/api").set("Accept", "text/plain"); 17 | const text = raw.toString(); 18 | message.channel.send(text.length >= 2000 ? text.substring(0, 1980) + "...

" : text, { code: "html" }); 19 | } catch (error) { 20 | this.client.logger.error(error); 21 | return message.channel.send(texts.general.error.replace(/{{err}}/g, error.message)); 22 | } 23 | } 24 | } 25 | 26 | module.exports = LoremIpsum; 27 | -------------------------------------------------------------------------------- /commands/Misc/mylevel.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 An Idiot's Guide. All rights reserved. MIT license. 2 | // https://github.com/AnIdiotsGuide/guidebot-class 3 | 4 | const Command = require("../../base/Command.js"); 5 | 6 | class MyLevel extends Command { 7 | constructor(client) { 8 | super(client, { 9 | name: "mylevel", 10 | description: "Displays your permission level for your location.", 11 | usage: "mylevel", 12 | aliases: ["myrank", "level", "permlevel"], 13 | guildOnly: true 14 | }); 15 | } 16 | 17 | async run(message, args, level, settings, texts) { 18 | const friendly = this.client.config.permLevels.find(l => l.level === level).name; 19 | message.reply(`${texts.cmd.misc.permLevel}: **${level}** (${friendly}).`); 20 | } 21 | } 22 | 23 | module.exports = MyLevel; 24 | -------------------------------------------------------------------------------- /commands/Misc/quote.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const { RichEmbed } = require("discord.js"); 3 | const { stripIndents } = require("common-tags"); 4 | 5 | class Quote extends Command { 6 | constructor(client) { 7 | super(client, { 8 | name: "quote", 9 | description: "Quotes the specified message (by ID).", 10 | usage: "quote ", 11 | aliases: ["q"], 12 | guildOnly: true 13 | }); 14 | } 15 | 16 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 17 | const id = args[0]; 18 | if (!id) return message.channel.send(stripIndents` 19 | You must provide a message ID. 20 | To do so, you need to have developer mode turned on to obtain a message ID (Settings → Appearance → Developer Mode). 21 | Then, upon right-clicking a message, you'll be presented with an option called "Copy ID".`, 22 | { file: !message.guild.me.hasPermission("ATTACH_FILES") ? null : "https://vgy.me/cQbRf7.png" }); 23 | 24 | message.channel.fetchMessage(id) 25 | .then(message => { 26 | const embed = new RichEmbed() 27 | .setColor(message.guild.member(message.author).displayColor) 28 | .setAuthor(message.author.tag, message.author.displayAvatarURL) 29 | .setDescription(message.content) 30 | .setFooter(`#${message.channel.name}`) 31 | .setTimestamp(); 32 | message.channel.send({ embed }); 33 | }) 34 | .catch(error => { 35 | if (error.code === 10008) return message.channel.send("Unknown message. Please ensure the message ID is from a message in this channnel."); 36 | this.client.logger.error(error); 37 | message.channel.send(texts.general.error.replace(/{{err}}/g, error)); 38 | }); 39 | } 40 | } 41 | 42 | module.exports = Quote; 43 | -------------------------------------------------------------------------------- /commands/Misc/tutorial.js: -------------------------------------------------------------------------------- 1 | // Previously, in the older version of delet (https://github.com/suvanl/delet), 2 | // the tutorial command used a series of `awaitMessages` methods. However, we 3 | // have decided to replace that with the online documentation, which will be much 4 | // clearer and more informative. It also reduces the amount of messy code. 5 | 6 | const Command = require("../../base/Command.js"); 7 | 8 | class Tutorial extends Command { 9 | constructor(client) { 10 | super(client, { 11 | name: "tutorial", 12 | description: "Directs the user towards the docs.", 13 | usage: "tutorial", 14 | aliases: ["guide"] 15 | }); 16 | } 17 | 18 | async run(message, args, level, settings, texts) { // eslint-disable-line no-unused-vars 19 | message.channel.send(texts.cmd.misc.tutorial); 20 | } 21 | } 22 | 23 | module.exports = Tutorial; 24 | -------------------------------------------------------------------------------- /commands/Misc/youtube.js: -------------------------------------------------------------------------------- 1 | const Command = require("../../base/Command.js"); 2 | const YouTube = require("simple-youtube-api"); 3 | const { GOOGLE_API_KEY } = process.env; 4 | 5 | const yt = new YouTube(GOOGLE_API_KEY); 6 | 7 | class YouTubeSearch extends Command { 8 | constructor(client) { 9 | super(client, { 10 | name: "youtube", 11 | description: "Searches YouTube for a specified video.", 12 | usage: "youtube