├── .gitignore ├── LICENSE.md ├── README.md ├── configTemplate.js ├── index.js ├── package.json ├── resources ├── audio │ └── WOOMY.mp3 ├── images │ ├── attackhelicopter.jpg │ └── fax.png └── other │ ├── coolpeople.json │ ├── identities.json │ ├── lyrics.json │ ├── pronouns.json │ └── sexualities.json ├── src ├── commands │ ├── 8ball.js │ ├── about.js │ ├── achievement.js │ ├── activity.js │ ├── adminrole.js │ ├── autorole.js │ ├── avatar.js │ ├── ban.js │ ├── blocklist.js │ ├── bohemian_rhapsody.js │ ├── calculate.js │ ├── cat.js │ ├── catfact.js │ ├── changelog.js │ ├── chatlogs.js │ ├── coinflip.js │ ├── colour.js │ ├── credits.js │ ├── creeper.js │ ├── cuddle.js │ ├── dice.js │ ├── dog.js │ ├── dogfact.js │ ├── emoji.js │ ├── emojify.js │ ├── eval.js │ ├── fact.js │ ├── feed.js │ ├── feedback.js │ ├── fixmusic.js │ ├── forceskip.js │ ├── garfield.js │ ├── giverole.js │ ├── goodbye.js │ ├── hackban.js │ ├── help.js │ ├── hug.js │ ├── identity.js │ ├── inspirobot.js │ ├── invite.js │ ├── kemonomimi.js │ ├── kick.js │ ├── kiss.js │ ├── kitsune.js │ ├── lizard.js │ ├── lmgtfy.js │ ├── modlogs.js │ ├── modrole.js │ ├── movehere.js │ ├── movesong.js │ ├── msearch.js │ ├── mute.js │ ├── mutedrole.js │ ├── neko.js │ ├── nekogif.js │ ├── nowplaying.js │ ├── owoify.js │ ├── pat.js │ ├── pause.js │ ├── permlevel.js │ ├── ping.js │ ├── play.js │ ├── playnext.js │ ├── poke.js │ ├── prefix.js │ ├── pride.js │ ├── pronoun.js │ ├── purge.js │ ├── queue.js │ ├── raidmode.js │ ├── randurban.js │ ├── rate.js │ ├── reload.js │ ├── removesong.js │ ├── reset.js │ ├── restart.js │ ├── resume.js │ ├── rip.js │ ├── rolecolour.js │ ├── roleinfo.js │ ├── salmonrun.js │ ├── sans.js │ ├── say.js │ ├── servericon.js │ ├── serverinfo.js │ ├── settings.js │ ├── sexuality.js │ ├── ship.js │ ├── shuffle.js │ ├── skip.js │ ├── slap.js │ ├── smug.js │ ├── softban.js │ ├── songinfo.js │ ├── splatnet.js │ ├── splatoonmaps.js │ ├── spoilerise.js │ ├── stop.js │ ├── support.js │ ├── takerole.js │ ├── tickle.js │ ├── unmute.js │ ├── urban.js │ ├── userinfo.js │ ├── volume.js │ ├── wag.js │ ├── weather.js │ ├── welcome.js │ ├── woomy.js │ ├── yoda.js │ └── zalgo.js ├── events │ ├── error.js │ ├── guildCreate.js │ ├── guildDelete.js │ ├── guildMemberAdd.js │ ├── guildMemberRemove.js │ ├── message.js │ ├── messageDelete.js │ ├── messageUpdate.js │ ├── ready.js │ └── voiceStateUpdate.js └── modules │ ├── Logger.js │ ├── functions.js │ └── music.js └── version.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | data 3 | config.js 4 | package-lock.json 5 | .env -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 YorkAARGH 4 | Copyright (c) 2018-2020 mudkipscience 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Development has moved! Find my new home [here](https://gitdab.com/embee/woomy) 2 | 3 | # Woomy 4 | Woomy is a all-purpose discord bot built off the [guidebot](https://github.com/AnIdiotsGuide/guidebot) base and coded in node.js using discord.js. 5 | 6 | # Notice 7 | Woomy v1 (this repository) is currently only being maintained. Bugs and issues will be fixed if they come up, but no new features will be added. Pull requests that add new features to Woomy should instead be contributed to the version 2 codebase, found [here](https://github.com/woomyware/v2). 8 | 9 | When Woomy v2 is released, Woomy v1 will no longer be maintained. 10 | 11 | # How to use 12 | The easiest way to use Woomy is to invite it to your server with [this link.](https://discord.com/oauth2/authorize?client_id=435961704145485835&permissions=2134240503&scope=bot) It is hosted 24/7 and automatically updates itself when a new release is made available, making sure you always get the newest features. 13 | 14 | You can also self-host! Some modifications to the code will need to be made before Woomy will run on your machine, but anyone who can read errors will figure out what needs to be changed pretty quickly :P 15 | 16 | # Requirements 17 | - git 18 | - node.js v12.0.0 or higher 19 | - node-gyp build tools 20 | - ffmpeg (or ffmpeg-static) 21 | 22 | # Installation 23 | - Clone Woomy to your machine 24 | - Run `npm i` in Woomy's directory 25 | - Open config.js in your code editor and insert all the required information 26 | 27 | # Contributing 28 | If you wish to contribute to Woomy, please fork the repository and open a pull request. Any contribution is appreciated <3 29 | -------------------------------------------------------------------------------- /configTemplate.js: -------------------------------------------------------------------------------- 1 | const config = { 2 | // ID's 3 | "owners": [], // Adding your ID here will give you access to dangerous commands like eval. Please be careful with who you add here! Eval can be used to modify the host machine. 4 | 5 | // Host options 6 | "devmodeEnabled": false, // true or false 7 | "loggingServer": "", // server ID, or blank to disable 8 | "startupLogs": "", // Channel ID, or blank to disable 9 | "consoleLogs": "", // Channel ID, or blank to disable 10 | 11 | // Tokens 12 | "token": "", // Your bot's token. 13 | "devtoken": "", // (optional) another token, meant for a bot used for development 14 | "dblkey": "", // (optional) top.gg key, sends bot statistics to top.gg. You do not need this. 15 | "sentry": "", 16 | "server": "", 17 | 18 | // Configurable API endpoints 19 | endpoints: { 20 | invidious: 'https://invidio.us/api/' 21 | }, 22 | 23 | // Default per-server settings 24 | "defaultSettings" : { 25 | "prefix": "~", 26 | "devprefix": "!", 27 | "modRole": "None set", 28 | "adminRole": "None set", 29 | "mutedRole": "None set", 30 | "autorole": "off", 31 | "welcomeChannel": "off", 32 | "welcomeMessage": "off", 33 | "leaveMessage": "off", 34 | "chatlogsChannel": "off", 35 | "modlogsChannel": "off", 36 | "raidMode": "off", 37 | "raidModeStrict": "off", 38 | "blacklisted": "ARRAY", 39 | "botChannels": "ARRAY", 40 | "AFK": "ARRAY", 41 | "SAR": "ARRAY", 42 | "customCommands": "ARRAY", 43 | }, 44 | 45 | // Perm levels 46 | permLevels: [ 47 | { level: 0, 48 | name: "User", 49 | check: () => true 50 | }, 51 | 52 | { level: 1, 53 | name: "Moderator", 54 | check: (message) => { 55 | try { 56 | if (message.member.roles.cache.has(message.settings.modRole)) return true; 57 | } catch (e) { 58 | return false; 59 | } 60 | } 61 | }, 62 | 63 | { level: 2, 64 | name: "Administrator", 65 | check: (message) => { 66 | try { 67 | if (message.member.roles.cache.has(message.settings.adminRole) || message.member.permissions.has("ADMINISTRATOR")) return true; 68 | } catch (e) { 69 | return false; 70 | } 71 | } 72 | }, 73 | 74 | { level: 3, 75 | name: "Server Owner", 76 | check: (message) => message.channel.type === "text" ? (message.guild.ownerID === message.author.id ? true : false) : false 77 | }, 78 | ] 79 | }; 80 | 81 | module.exports = config; 82 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | if (Number(process.version.slice(1).split(".")[0]) < 12) { 2 | throw new Error("Node 12.0.0 or higher is required. Please update Node on your system."); 3 | }; 4 | 5 | const Discord = require('discord.js'); 6 | const { promisify } = require('util'); 7 | const readdir = promisify(require('fs').readdir); 8 | const Enmap = require('enmap'); 9 | const sentry = require('@sentry/node'); 10 | const chalk = require('chalk'); 11 | const client = new Discord.Client({ ws: { intents: [ 12 | 'GUILDS', 13 | 'GUILD_MEMBERS', 14 | 'GUILD_EMOJIS', 15 | 'GUILD_VOICE_STATES', 16 | 'GUILD_MESSAGES', 17 | 'DIRECT_MESSAGES', 18 | 'GUILD_MESSAGE_REACTIONS', 19 | ]}}); 20 | 21 | try { 22 | client.config = require('./config'); 23 | } catch (err) { 24 | console.log('Failed to load config.js:', err); 25 | process.exit(); 26 | }; 27 | 28 | try{ 29 | client.version = require('./version.json'); 30 | } catch (err) { 31 | console.log('Failed to load version.json:', err); 32 | process.exit(); 33 | }; 34 | 35 | try{ 36 | client.logger = require('./src/modules/Logger'); 37 | } catch (err) { 38 | console.log('Failed to load Logger.js:', err); 39 | process.exit(); 40 | }; 41 | 42 | client.logger.setClient(client); 43 | 44 | try{ 45 | require("./src/modules/functions")(client); 46 | } catch (err) { 47 | console.log('Failed to load functions.js:', err); 48 | process.exit(); 49 | }; 50 | 51 | if(client.config.devmodeEnabled == true && process.env['USER'] != 'container') { 52 | client.devmode = true; 53 | } else { 54 | client.devmode = false; 55 | if(client.config.dblkey.length > 0) { 56 | const DBL = require("dblapi.js"); 57 | const dblapi = new DBL(client.config.dblkey, client); 58 | }; 59 | 60 | if(client.config.sentry.length > 0) { 61 | sentry.init({ dsn: client.config.sentry }); 62 | }; 63 | }; 64 | 65 | client.commands = new Enmap(); 66 | client.aliases = new Enmap(); 67 | client.settings = new Enmap({name: 'settings'}); 68 | 69 | const init = async () => { 70 | const cmdFiles = await readdir("./src/commands/"); 71 | client.logger.info(`Loading ${cmdFiles.length} commands.`); 72 | cmdFiles.forEach(file => { 73 | if (!file.endsWith(".js")) { 74 | return; 75 | }; 76 | const response = client.loadCommand(file); 77 | if (response) { 78 | console.log(response); 79 | }; 80 | }); 81 | 82 | const evtFiles = await readdir("./src/events/"); 83 | client.logger.info(`Loading ${evtFiles.length} events.`); 84 | evtFiles.forEach(file => { 85 | if (!file.endsWith(".js")) { 86 | return; 87 | }; 88 | const eventName = file.split(".")[0]; 89 | const event = require(`./src/events/${file}`); 90 | client.on(eventName, event.bind(null, client)); 91 | }); 92 | 93 | client.levelCache = {}; 94 | for (let i = 0; i < client.config.permLevels.length; i++) { 95 | const thisLevel = client.config.permLevels[i]; 96 | client.levelCache[thisLevel.name] = thisLevel.level; 97 | }; 98 | 99 | if(client.devmode === true) { 100 | client.login(client.config.devtoken); 101 | } else { 102 | client.login(client.config.token); 103 | }; 104 | }; 105 | 106 | process.on('SIGINT', function(){ 107 | client.logger.info("Disconnecting...") 108 | client.destroy(); 109 | process.exit(); 110 | }); 111 | 112 | init(); 113 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "woomy", 3 | "version": "1.2.3", 4 | "description": "Woomy is a all-purpose discord bot built off the guidebot base and coded in node.js using discord.js.", 5 | "main": "index.js", 6 | "dependencies": { 7 | "@discordjs/opus": "^0.5.0", 8 | "@sentry/node": "^6.4.1", 9 | "better-sqlite3": "^7.4.0", 10 | "chalk": "^4.1.1", 11 | "dblapi.js": "^2.4.1", 12 | "discord-paginator.js": "github:mudkipscience/discord-paginator.js", 13 | "discord.js": "^12.5.3", 14 | "enmap": "^5.8.5", 15 | "ffmpeg-static": "^4.3.0", 16 | "hastebin-gen": "^2.0.5", 17 | "moment": "^2.29.1", 18 | "moment-duration-format": "^2.3.2", 19 | "nekos.life": "^2.0.5", 20 | "node-fetch": "^2.6.1", 21 | "pretty-ms": "^7.0.1", 22 | "randomcolor": "^0.6.2", 23 | "relevant-urban": "^2.0.0", 24 | "to-zalgo": "^1.0.1", 25 | "urban": "^0.3.2", 26 | "weather-js": "^2.0.0", 27 | "ytdl-core": "^4.8.2" 28 | }, 29 | "scripts": { 30 | "test": "echo \"Error: no test specified\" && exit 1" 31 | }, 32 | "repository": { 33 | "type": "git", 34 | "url": "git+https://github.com/mudkipscience/woomy.git" 35 | }, 36 | "author": "mudkipscience", 37 | "license": "MIT", 38 | "bugs": { 39 | "url": "https://github.com/mudkipscience/woomy/issues" 40 | }, 41 | "homepage": "https://github.com/mudkipscience/woomy#readme" 42 | } 43 | -------------------------------------------------------------------------------- /resources/audio/WOOMY.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/woomyware/woomy/6702ff839babc32fa4e0617f924b95b13b028e49/resources/audio/WOOMY.mp3 -------------------------------------------------------------------------------- /resources/images/attackhelicopter.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/woomyware/woomy/6702ff839babc32fa4e0617f924b95b13b028e49/resources/images/attackhelicopter.jpg -------------------------------------------------------------------------------- /resources/images/fax.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/woomyware/woomy/6702ff839babc32fa4e0617f924b95b13b028e49/resources/images/fax.png -------------------------------------------------------------------------------- /resources/other/coolpeople.json: -------------------------------------------------------------------------------- 1 | { 2 | "coolPeople": [ 3 | "448354605617643520", 4 | "433790467830972417", 5 | "231777839576252417", 6 | "285992938314661899", 7 | "231704701433937931", 8 | "324937993972350976", 9 | "336492042299637771", 10 | "273867501006225419", 11 | "331870539897372672", 12 | "304000458144481280", 13 | "239787232666451980", 14 | "264970229514371072", 15 | "254310746450690048", 16 | "358390849807319040", 17 | "211011138656272386", 18 | "266472557740425216", 19 | "102943767346057216" 20 | ] 21 | } -------------------------------------------------------------------------------- /resources/other/sexualities.json: -------------------------------------------------------------------------------- 1 | { 2 | "aesthetic attraction": { 3 | "name": "aesthetic attraction", 4 | "description": "Getting pleasure from the appearance of a specific individual like you would from watching beautiful scenery." 5 | }, 6 | "platonic attraction": { 7 | "name": "platonic attraction", 8 | "description": "A desire to have a platonic relationship or friendship with a specific individual." 9 | }, 10 | "romantic attraction": { 11 | "name": "romantic attraction", 12 | "description": "A desire to have a romantic relationship with a specific individual." 13 | }, 14 | "sensual attraction": { 15 | "name": "sensual attraction", 16 | "description": "A desire for physical intimacy with a specific individual. Cuddling, hand holding, etc." 17 | }, 18 | "sexual attraction": { 19 | "name": "sexual attraction", 20 | "description": "A desire for sexual contact with a specific individual." 21 | }, 22 | "abrosexual": { 23 | "name": "abrosexual", 24 | "description": "Someone whose sexuality changes frequently. They experience different sexualities over time." 25 | }, 26 | "androgynosexual": { 27 | "name": "androgynosexual", 28 | "description": "Someone who is attracted to both men and women, particularly those who are androgynous in appearance." 29 | }, 30 | "androsexual": { 31 | "name": "androsexual", 32 | "description": "Someone who is attracted to men and/or masculine people." 33 | }, 34 | "aromantic": { 35 | "name": "aromantic", 36 | "description": "Someone who does not experience romantic attraction. They do not have to also be asexual however as they may still experience other types of attraction." 37 | }, 38 | "asexual": { 39 | "name": "asexual", 40 | "description": "Someone who feels little to no sexual attraction to anyone." 41 | }, 42 | "bisexual": { 43 | "name": "bisexual", 44 | "description": "Someone who is attracted to more than one gender." 45 | }, 46 | "ceterosexual": { 47 | "name": "ceterosexual", 48 | "description": "Someone who is attracted to non-binary people." 49 | }, 50 | "demisexual": { 51 | "name": "demisexual", 52 | "description": "Someone who doesn't experience sexual/romantic attraction towards someone until they form an emotional connection." 53 | }, 54 | "finsexual": { 55 | "name": "finsexual", 56 | "description": "Someone who is attracted to women and/or feminine people." 57 | }, 58 | "gay": { 59 | "name": "gay", 60 | "description": "Someone who is homosexual (attracted to ones own gender)" 61 | }, 62 | "gynosexual": { 63 | "name": "gynosexual", 64 | "description": "Someone who as attracted to women and/or feminity." 65 | }, 66 | "grey-romantic": { 67 | "name": "grey-romantic", 68 | "description": "Someone with a romantic orentiation that is somewhere between aromantic and romantic." 69 | }, 70 | "heterosexual": { 71 | "name": "heterosexual", 72 | "description": "Someone who is attracted to people of the opposite gender." 73 | }, 74 | "homosexual": { 75 | "name": "homosexual", 76 | "description": "Someone attracted to people of ones own gender." 77 | }, 78 | "lesbian": { 79 | "name": "lesbian", 80 | "description": "A woman who is attracted to other women." 81 | }, 82 | "omnisexual": { 83 | "name": "omnisexual", 84 | "description": "Someone who is attracted to all genders." 85 | }, 86 | "pansexual": { 87 | "name": "pansexual", 88 | "description": "Someone who is attracted towards people regardless of their gender identity." 89 | }, 90 | "pomosexual": { 91 | "name": "pomosexual", 92 | "description": "Someone who does not fit into any sexual orientation label." 93 | }, 94 | "polysexual": { 95 | "name": "polysexual", 96 | "description": "Someone who is attracted to some, but not all genders." 97 | }, 98 | "straight": { 99 | "name": "straight", 100 | "description": "Someone who is heterosexual (attracted to people of the opposite gender)" 101 | } 102 | } -------------------------------------------------------------------------------- /src/commands/8ball.js: -------------------------------------------------------------------------------- 1 | exports.run = async (client, message, args) => { 2 | if (!args[0]) 3 | return message.channel.send( 4 | `<:error:466995152976871434> You did not ask me a question. Usage: \`${client.commands.get(`8ball`).help.usage}\`` 5 | ); 6 | 7 | var ball = [ 8 | "No darndested clue.", 9 | "Stupid question. You should be ashamed of yourself for even asking.", 10 | "Yes!", 11 | "Not in your wildest dreams!", 12 | "No chance.", 13 | "Never.", 14 | "Just Google it.", 15 | "¯\\_(ツ)_/¯", 16 | "Possibly.", 17 | "There's a high chance.", 18 | "I'd rather not say." 19 | ]; 20 | 21 | let mess = ball.random(); 22 | message.channel.send(":8ball: " + mess); 23 | }; 24 | 25 | exports.conf = { 26 | enabled: true, 27 | guildOnly: false, 28 | aliases: [], 29 | permLevel: "User", 30 | requiredPerms: [] 31 | }; 32 | 33 | exports.help = { 34 | name: "8ball", 35 | category: "Fun", 36 | description: "Consult the 8ball for advice.", 37 | usage: "8ball [question]" 38 | }; 39 | -------------------------------------------------------------------------------- /src/commands/about.js: -------------------------------------------------------------------------------- 1 | 2 | const { version } = require("discord.js"); 3 | const moment = require("moment"); 4 | require("moment-duration-format"); 5 | 6 | exports.run = (client, message) => { 7 | const duration = moment 8 | .duration(client.uptime) 9 | .format(" D [days], H [hrs], m [mins], s [secs]"); 10 | 11 | var mud = client.users.cache.get(client.config.owners[0]).tag; 12 | var flgx = client.users.cache.get(client.config.owners[1]).tag; 13 | var build; 14 | var prefix; 15 | 16 | if(message.guild) { 17 | prefix = message.settings.prefix; 18 | } else { 19 | prefix = client.config.defaultSettings.prefix; 20 | }; 21 | 22 | if(client.devmode == true) { 23 | build = "development" 24 | } else { 25 | build = "production" 26 | } 27 | 28 | embed = new Discord.MessageEmbed(); 29 | embed.setColor(client.embedColour(message)); 30 | embed.setThumbnail(client.user.avatarURL({format: "png", dynamic: true, size: 2048})) 31 | embed.setTitle("About Woomy") 32 | embed.addField( 33 | "General:", `• users: \`${client.users.cache.size}\`\n• channels: \`${client.channels.cache.size}\`\n• servers: \`${client.guilds.cache.size}\`\n• commands: \`${client.commands.size}\`\n• uptime: \`${duration}\``,true 34 | ); 35 | embed.addField( 36 | `Technical:`, `• RAM Usage: \`${(process.memoryUsage().heapUsed / 1024 / 1024).toFixed(2)} MB\`\n• OS: \`${require("os").type}\`\n• bot version: \`${client.version.number} (${build})\`\n• discord.js version: \`v${version}\`\n• node.js version: \`${process.version}\``,true 37 | ); 38 | embed.addField( 39 | "Links:", "[Support](https://discord.gg/HCF8mdv) | [GitHub](https://github.com/mudkipscience/woomy) | [db.org](https://discordbots.org/bot/435961704145485835/vote) | [BFD](https://botsfordiscord.com/bots/435961704145485835/vote) | [top.gg](https://discordbotlist.com/bots/435961704145485835) | [discord.js](https://discord.js.org/#/) | [guidebot](https://github.com/AnIdiotsGuide/guidebot/)" 40 | ); 41 | 42 | message.channel.send(embed); 43 | }; 44 | 45 | exports.conf = { 46 | enabled: true, 47 | guildOnly: false, 48 | aliases: ["stats", "botinfo"], 49 | permLevel: "User", 50 | requiredPerms: [] 51 | }; 52 | 53 | exports.help = { 54 | name: "about", 55 | category: "Utility", 56 | description: "Information about the bot, as well as a couple of helpful links", 57 | usage: "about" 58 | }; 59 | -------------------------------------------------------------------------------- /src/commands/achievement.js: -------------------------------------------------------------------------------- 1 | Discord = require("discord.js"); 2 | 3 | const url = "https://www.minecraftskinstealer.com/achievement/a.php"; 4 | 5 | exports.run = (client, message, args) => { 6 | let text = args.join(" "); 7 | 8 | if (!text) { 9 | return message.channel.send( 10 | `<:error:466995152976871434> No text provided to turn into an achievement. Usage: \`${client.commands.get(`achievement`).help.usage}\`` 11 | ); 12 | }; 13 | message.channel.startTyping(); 14 | let params = "h=Achievement+Get%21&i=1&t=" + encodeURIComponent(text); 15 | 16 | try { 17 | message.channel.stopTyping(); 18 | message.channel.send({ 19 | files: [new Discord.MessageAttachment(url + "?" + params, "achievement.png")] 20 | }); 21 | 22 | } catch(err) { 23 | message.channel.stopTyping(); 24 | message.channel.send(`<:error:466995152976871434> Error when generating image: \`${err}\``) 25 | } 26 | }; 27 | 28 | exports.conf = { 29 | enabled: true, 30 | guildOnly: false, 31 | aliases: [], 32 | permLevel: "User", 33 | requiredPerms: ["ATTACH_FILES"] 34 | }; 35 | 36 | exports.help = { 37 | name: "achievement", 38 | category: "Fun", 39 | description: "Generates an minecraft achievement.", 40 | usage: "achievement [text]" 41 | }; 42 | -------------------------------------------------------------------------------- /src/commands/activity.js: -------------------------------------------------------------------------------- 1 | exports.run = (client, message, args) => { 2 | if(!args[0]) { 3 | return message.channel.send(`<:error:466995152976871434> No arguments! Usage: \`${client.commands.get(`activity`).help.usage}\``) 4 | } 5 | if(client.lockActivity == true) { 6 | activityLocked = "locked"; 7 | } else { 8 | activityLocked = "unlocked"; 9 | } 10 | 11 | if(args[0] == "lock" && !args[1]) { 12 | client.lockActivity = true; 13 | return message.channel.send( 14 | "<:success:466995111885144095> Activity has been locked will no longer change automatically." 15 | ); 16 | }; 17 | 18 | if(args[0] == "unlock" && !args[1]) { 19 | client.lockActivity = false; 20 | return message.channel.send( 21 | "<:success:466995111885144095> Activity has been unlocked and will begin changing automatically." 22 | ); 23 | }; 24 | 25 | client.lockActivity = true; 26 | client.user.setActivity(args.join(" ")); 27 | message.channel.send( 28 | `<:success:466995111885144095> Activity locked and changed to \`${args.join(" ")}\` 29 | `); 30 | }; 31 | 32 | exports.conf = { 33 | enabled: true, 34 | guildOnly: false, 35 | aliases: [], 36 | permLevel: "Developer", 37 | requiredPerms: [] 38 | }; 39 | 40 | exports.help = { 41 | name: "activity", 42 | category: "Owner", 43 | description: "Changes the bot's activity and disables automatic changing of the activity", 44 | usage: "activity [activity] **OR** activity [lock/unlock]" 45 | }; 46 | -------------------------------------------------------------------------------- /src/commands/adminrole.js: -------------------------------------------------------------------------------- 1 | exports.run = async (client, message, args) => { 2 | 3 | const settings = message.settings; 4 | 5 | if (!client.settings.has(message.guild.id)) { 6 | client.settings.set(message.guild.id, {}); 7 | } 8 | 9 | var adminRole = message.guild.roles.cache.get(settings.adminRole) 10 | 11 | if (!args[0]) { 12 | if(!adminRole) { 13 | return message.channel.send( 14 | `<:error:466995152976871434> There is no admin role set for this server. Please set one using \`${message.settings.prefix}adminrole \`` 15 | ); 16 | } else { 17 | message.channel.send(`The current admin role is: \`${adminRole.name}\``) 18 | } 19 | 20 | } else { 21 | const joinedValue = args.join(" "); 22 | if (joinedValue.length < 1) { 23 | return message.channel.send( 24 | `<:error:466995152976871434> You didn't specify a role. Usage: \`${client.commands.get(`adminrole`).help.usage}\`` 25 | ); 26 | }; 27 | 28 | if (settings.adminRole != "None set" && joinedValue === adminRole.name) { 29 | return message.channel.send( 30 | "<:error:466995152976871434> The admin role is already set to that!" 31 | ); 32 | }; 33 | 34 | let role = client.findRole(joinedValue, message); 35 | 36 | if (!role) { 37 | return message.channel.send(`<:error:466995152976871434> That role doesn't seem to exist. Try again!`); 38 | }; 39 | 40 | client.settings.set(message.guild.id, role.id, "adminRole"); 41 | 42 | message.channel.send( 43 | `<:success:466995111885144095> The admin role has been set to \`${role.name}\` 44 | `); 45 | }; 46 | }; 47 | 48 | exports.conf = { 49 | enabled: true, 50 | guildOnly: true, 51 | aliases: [], 52 | permLevel: "Server Owner", 53 | requiredPerms: [] 54 | }; 55 | 56 | exports.help = { 57 | name: "adminrole", 58 | category: "Configure", 59 | description: "Sets the admin role for this server.", 60 | usage: "adminrole [role]" 61 | }; 62 | -------------------------------------------------------------------------------- /src/commands/autorole.js: -------------------------------------------------------------------------------- 1 | exports.run = async (client, message, args) => { 2 | 3 | const settings = message.settings; 4 | 5 | if (!client.settings.has(message.guild.id)) { 6 | client.settings.set(message.guild.id, {}); 7 | } 8 | 9 | var autorole = message.guild.roles.cache.get(settings.autorole) 10 | 11 | if (!args[0]) { 12 | if(!autorole) { 13 | return message.channel.send( 14 | `<:error:466995152976871434> There is no autorole set for this server. Please set one using \`${message.settings.prefix}autorole \`` 15 | ); 16 | } else { 17 | message.channel.send(`Users recieve this role upon joining: \`${autorole.name}\``) 18 | } 19 | 20 | } else if(args.join(" ").toLowerCase() == "off") { 21 | if(settings.autorole == "off") { 22 | return message.channel.send("<:error:466995152976871434> Autoroling has not been enabled.") 23 | } 24 | 25 | client.settings.set(message.guild.id, "off", "autorole"); 26 | return message.channel.send("<:success:466995111885144095> Autoroling has been disabled.") 27 | } else { 28 | 29 | const joinedValue = args.join(" "); 30 | if (joinedValue.length < 1) { 31 | return message.channel.send( 32 | `<:error:466995152976871434> You didn't specify a role. Usage: \`${client.commands.get(`autorole`).help.usage}\`` 33 | ); 34 | }; 35 | 36 | if (settings.autorole != "off" && joinedValue === autorole.name) { 37 | return message.channel.send( 38 | "<:error:466995152976871434> The autorole is already set to that!" 39 | ); 40 | }; 41 | 42 | role = client.findRole(joinedValue, message); 43 | 44 | if (!role) { 45 | return message.channel.send(`<:error:466995152976871434> That role doesn't seem to exist. Try again!`); 46 | }; 47 | 48 | client.settings.set(message.guild.id, role.id, "autorole"); 49 | 50 | message.channel.send( 51 | `<:success:466995111885144095> The autorole has been set to \`${role.name}\` 52 | `); 53 | }; 54 | }; 55 | 56 | exports.conf = { 57 | enabled: true, 58 | guildOnly: true, 59 | aliases: [], 60 | permLevel: "Administrator", 61 | requiredPerms: ["MANAGE_ROLES"] 62 | }; 63 | 64 | exports.help = { 65 | name: "autorole", 66 | category: "Configure", 67 | description: "Sets the autorole for this server.", 68 | usage: "autorole **OR** autorole off" 69 | }; 70 | -------------------------------------------------------------------------------- /src/commands/avatar.js: -------------------------------------------------------------------------------- 1 | exports.run = (client, message, args) => { 2 | let user = message.mentions.users.first(); 3 | let users; 4 | if (!args[0] || !message.guild) { 5 | user = message.author; 6 | }; 7 | 8 | if (!user && message.guild) { 9 | users = client.searchForMembers(message.guild, args[0]); 10 | if (users.length > 1) { 11 | return message.channel.send( 12 | "<:error:466995152976871434> Found multiple users, please be more specific or mention the user instead." 13 | ); 14 | } else if (users.length == 0) { 15 | return message.channel.send( 16 | "<:error:466995152976871434> That user doesn't seem to exist, try again!" 17 | ); 18 | }; 19 | user = users[0]; 20 | user = user.user; 21 | } 22 | message.channel.send(`**${user.tag}'s** avatar is: ${user.avatarURL({format: "png", dynamic: true, size: 2048})}`); 23 | }; 24 | 25 | exports.conf = { 26 | enabled: true, 27 | guildOnly: false, 28 | aliases: [], 29 | permLevel: "User", 30 | requiredPerms: ["EMBED_LINKS"] 31 | }; 32 | 33 | exports.help = { 34 | name: "avatar", 35 | category: "Utility", 36 | description: "Gives you the specified users avatar.", 37 | usage: "avatar " 38 | }; 39 | -------------------------------------------------------------------------------- /src/commands/ban.js: -------------------------------------------------------------------------------- 1 | exports.run = async (client, message, args) => { 2 | const settings = (message.settings = client.getSettings(message.guild.id)); 3 | 4 | if(!args[0]) { 5 | return message.channel.send( 6 | `<:error:466995152976871434> No username provided. Usage: \`${client.commands.get(`ban`).help.usage}\`` 7 | ); 8 | }; 9 | 10 | let user = message.mentions.members.first(); 11 | 12 | if (!user) { 13 | let users; 14 | users = client.searchForMembers(message.guild, args[0]); 15 | if (users.length > 1) 16 | return message.channel.send( 17 | "<:error:466995152976871434> Found multiple users! Please be more specific or mention the user instead." 18 | ); 19 | else if (users.length == 0) 20 | return message.channel.send( 21 | "<:error:466995152976871434> That user doesn't seem to exist. Try again!" 22 | ); 23 | user = users[0]; 24 | }; 25 | 26 | if (user.user.id === message.guild.owner.id) { 27 | return message.channel.send("<:error:466995152976871434> You can't ban the owner!") 28 | }; 29 | let moderator = message.guild.member(message.author) 30 | if (user.roles.highest.position >= moderator.roles.highest.position && moderator.user.id !== message.guild.ownerID) { 31 | return message.channel.send( 32 | `<:error:466995152976871434> You can't ban people higher ranked than yourself!` 33 | ); 34 | }; 35 | 36 | let bot = message.guild.member(client.user) 37 | if (user.roles.highest.position >= bot.roles.highest.position) { 38 | return message.channel.send( 39 | `<:error:466995152976871434> I can't ban people who are higher ranked than me!` 40 | ); 41 | }; 42 | 43 | if (!user.bannable) 44 | return message.channel.send( 45 | "<:error:466995152976871434> Specified user is not bannable." 46 | ); 47 | 48 | let reason = args.slice(1).join(" "); 49 | if (!reason) reason = `Banned by ${message.author.tag}`; 50 | await message.guild.members.ban(user, {reason: reason}).catch(console.error); 51 | message.channel.send(`<:success:466995111885144095> Banned \`${user.user.tag}\``); 52 | 53 | if (settings.modlogsChannel !== "off") { 54 | const channel = message.guild.channels.cache.find( 55 | channel => channel.name === settings.modlogsChannel 56 | ); 57 | 58 | if (channel) { 59 | let embed = new Discord.MessageEmbed(); 60 | embed.setColor("#BC0057"); 61 | embed.setAuthor("User banned!", user.user.avatarURL({format: "png", dynamic: true, size: 2048})); 62 | embed.setDescription( 63 | `• User: ${user.user.tag} (${user.user.id})\n• Mod: ${message.author} (${message.author.id})\n• Reason: ${reason}` 64 | ); 65 | try { 66 | channel.send(embed); 67 | } catch (err) { 68 | // probably no permissions to send messages/embeds there 69 | }; 70 | }; 71 | }; 72 | }; 73 | 74 | exports.conf = { 75 | enabled: true, 76 | guildOnly: true, 77 | aliases: [], 78 | permLevel: "Moderator", 79 | requiredPerms: ["BAN_MEMBERS"] 80 | }; 81 | 82 | exports.help = { 83 | name: "ban", 84 | category: "Moderation", 85 | description: "Bans specified user.", 86 | usage: "ban [user] " 87 | }; 88 | -------------------------------------------------------------------------------- /src/commands/blocklist.js: -------------------------------------------------------------------------------- 1 | exports.run = async (client, message, [action, ...member]) => { 2 | const settings = message.settings; 3 | 4 | if(settings.blacklisted == "ARRAY") { 5 | await client.settings.set(message.guild.id, [], "blacklisted"); 6 | } 7 | 8 | if(!action) { 9 | return message.channel.send( 10 | `<:error:466995152976871434> You didn't tell me if I was meant to add or remove someone from the blocklist! Usage: \`${client.commands.get(`blocklist`).help.usage}\`` 11 | ) 12 | } 13 | 14 | member = member.join(" ") 15 | 16 | if(!member) { 17 | return message.channel.send( 18 | `<:error:466995152976871434> You didn't tell me who to add to the blocklist! Usage: \`${client.commands.get(`blocklist`).help.usage}\`` 19 | ); 20 | }; 21 | 22 | let user = message.mentions.members.first(); 23 | 24 | if(action == "add") { 25 | if (!user) { 26 | let users; 27 | users = client.searchForMembers(message.guild, member); 28 | if (users.length > 1) 29 | return message.channel.send( 30 | "<:error:466995152976871434> Found multiple users! Please be more specific or mention the user instead." 31 | ); 32 | else if (users.length == 0) 33 | return message.channel.send( 34 | "<:error:466995152976871434> That user doesn't seem to exist. Try again!" 35 | ); 36 | user = users[0]; 37 | }; 38 | 39 | if(user.id === client.user.id) { 40 | return message.channel.send('lol no'); 41 | }; 42 | 43 | if (user.id === message.guild.owner.id) { 44 | return message.channel.send("<:error:466995152976871434> You can't add the owner to the blocklist!") 45 | }; 46 | 47 | let admin = message.guild.member(message.author) 48 | if (user.roles.highest.position >= admin.roles.highest.position && admin.user.id !== message.guild.ownerID) { 49 | return message.channel.send( 50 | `<:error:466995152976871434> You can't add people higher ranked than yourself to the blocklist!` 51 | ); 52 | }; 53 | 54 | if(user.id === message.member.id) { 55 | return message.channel.send('<:error:466995152976871434> You can\'t add yourself to the blocklist!'); 56 | }; 57 | 58 | let blacklisted = false; 59 | 60 | if(settings.blacklisted.length > 0) { 61 | settings.blacklisted.forEach(function(ID) { 62 | if(ID == user.id) { 63 | blacklisted = true; 64 | } 65 | }); 66 | 67 | if(blacklisted == true) { 68 | return message.channel.send('<:error:466995152976871434> This person is already on the blocklist!'); 69 | }; 70 | }; 71 | 72 | client.settings.push(message.guild.id, user.id, "blacklisted") 73 | 74 | return message.channel.send(`<:success:466995111885144095> Added \`${user.user.tag}\` to the blocklist.`) 75 | }; 76 | 77 | 78 | if (action == "remove") { 79 | if (!user) { 80 | let users; 81 | users = client.searchForMembers(message.guild, member); 82 | if (users.length > 1) 83 | return message.channel.send( 84 | "<:error:466995152976871434> Found multiple users! Please be more specific or mention the user instead." 85 | ); 86 | else if (users.length == 0) 87 | return message.channel.send( 88 | "<:error:466995152976871434> That user doesn't seem to exist. Try again!" 89 | ); 90 | user = users[0]; 91 | }; 92 | 93 | let blacklisted = false; 94 | 95 | settings.blacklisted.forEach(function(ID) { 96 | if(ID == user.id) { 97 | blacklisted = true; 98 | } 99 | }); 100 | 101 | if(blacklisted != true) { 102 | return message.channel.send('<:error:466995152976871434> This user isn\'t on the blocklist!'); 103 | }; 104 | 105 | client.settings.remove(message.guild.id, user.id, "blacklisted") 106 | 107 | return message.channel.send(`<:success:466995111885144095> Removed \`${user.user.tag}\` from the blocklist.`) 108 | }; 109 | }; 110 | 111 | exports.conf = { 112 | enabled: true, 113 | guildOnly: true, 114 | aliases: ['bl'], 115 | permLevel: "Administrator", 116 | requiredPerms: [] 117 | }; 118 | 119 | exports.help = { 120 | name: "blocklist", 121 | category: "Moderation", 122 | description: "Allows you to configure Woomy's blocklist. Users on the blocklist cannot use commands.", 123 | usage: "blocklist [add/remove] [member]" 124 | }; 125 | -------------------------------------------------------------------------------- /src/commands/bohemian_rhapsody.js: -------------------------------------------------------------------------------- 1 | const Discord = require("discord.js"); 2 | const lyric = require('../../resources/other/lyrics.json') 3 | exports.run = async (client, message, args, level) => { 4 | const lyrics = lyric.bohemian_rhapsody; 5 | var runtop = true; 6 | var runbottom = false; 7 | for(var br = 0; br < lyrics.length; br++) { 8 | { 9 | if (runtop === true) { 10 | var response = await client.awaitReply(message, lyrics[br]); 11 | runbottom = false; 12 | }; 13 | 14 | if (runbottom === true) { 15 | if (response !== lyrics[br]) { 16 | return message.channel.send("Those aren't the lyrics!"); 17 | } 18 | runtop = false 19 | }; 20 | }; 21 | if (runtop === true) { 22 | runtop = false 23 | runbottom = true 24 | } else if (runbottom === true) { 25 | runtop = true 26 | runbottom = false 27 | }; 28 | }; 29 | message.channel.send("What a lovely duet!"); 30 | }; 31 | 32 | exports.conf = { 33 | enabled: true, 34 | guildOnly: false, 35 | aliases: ["br"], 36 | permLevel: "User", 37 | requiredPerms: [] 38 | }; 39 | 40 | exports.help = { 41 | name: "bohemian_rhapsody", 42 | category: "Fun", 43 | description: "Queen karaoke", 44 | usage: "bohemian_rhapsody" 45 | }; 46 | -------------------------------------------------------------------------------- /src/commands/calculate.js: -------------------------------------------------------------------------------- 1 | var allowed = ["+", "-", "*", "/", "(", ")", " "]; 2 | exports.run = (client, message, args) => { 3 | let exercise = args.join(" "); 4 | 5 | if (!exercise) { 6 | return message.channel.send( 7 | `<:error:466995152976871434> No equation provided. Usage :\`${client.commands.get(`calculate`).help.usage}\`` 8 | ); 9 | } 10 | 11 | try { 12 | for (var i = 0; i < exercise.length; i++) { 13 | let c = exercise.charAt(i); 14 | let found = allowed.find((element) => element === c); 15 | 16 | if(c == "0") found = true; 17 | if(!(Number(c) || found)) 18 | { 19 | return message.channel.send( 20 | `<:error:466995152976871434> Invalid equation. Please use \`*\` for multiplication and \`/\` for division!` 21 | ); 22 | } 23 | } 24 | 25 | let result = (new Function( 'return ' + exercise )()); 26 | 27 | message.channel.send(`\`RESULT:\`\n\`\`\`${result}\`\`\``) 28 | } catch (err) { 29 | message.channel.send('<:error:466995152976871434> Malformed input.') 30 | } 31 | }; 32 | 33 | exports.conf = { 34 | enabled: true, 35 | guildOnly: false, 36 | aliases: ["calc", "math"], 37 | permLevel: "User", 38 | requiredPerms: [] 39 | }; 40 | 41 | exports.help = { 42 | name: "calculate", 43 | category: "Utility", 44 | description: "Solves basic mathematical equations.", 45 | usage: "calculate [equation]" 46 | }; -------------------------------------------------------------------------------- /src/commands/cat.js: -------------------------------------------------------------------------------- 1 | const API = require('nekos.life'); 2 | const {sfw} = new API(); 3 | exports.run = async (client, message) => { 4 | message.channel.startTyping(); 5 | try { 6 | sfw.meow().then((json) => { 7 | message.channel.send(json.url) 8 | message.channel.stopTyping(); 9 | }); 10 | } catch (err) { 11 | client.logger.error("cat.js: " + err); 12 | message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`) 13 | message.channel.stopTyping(); 14 | }; 15 | }; 16 | 17 | exports.conf = { 18 | enabled: true, 19 | guildOnly: false, 20 | aliases: [], 21 | permLevel: "User", 22 | requiredPerms: ["EMBED_LINKS"] 23 | }; 24 | 25 | exports.help = { 26 | name: "cat", 27 | category: "Image", 28 | description: "Sends you cat pics.", 29 | usage: "cat" 30 | }; 31 | -------------------------------------------------------------------------------- /src/commands/catfact.js: -------------------------------------------------------------------------------- 1 | const fetch = require("node-fetch") 2 | exports.run = async (bot, message, args) => { 3 | message.channel.startTyping(); 4 | try{ 5 | fetch('https://catfact.ninja/facts') 6 | .then(res => res.json()) 7 | .then(json => message.channel.send(`__**Did you know?**__\n${json.data[0].fact}`)) 8 | .catch(err => { 9 | message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`); 10 | }); 11 | } catch(err) { 12 | message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`); 13 | }; 14 | message.channel.stopTyping(); 15 | }; 16 | 17 | exports.conf = { 18 | enabled: true, 19 | guildOnly: false, 20 | aliases: ["kittenfact"], 21 | permLevel: "User", 22 | requiredPerms: [] 23 | }; 24 | 25 | exports.help = { 26 | name: "catfact", 27 | category: "Fun", 28 | description: "Sends a fun fact about a cat.", 29 | usage: "catfact/kittenfact" 30 | }; 31 | -------------------------------------------------------------------------------- /src/commands/changelog.js: -------------------------------------------------------------------------------- 1 | exports.run = (client, message) => { 2 | message.channel.send(client.version.changelog) 3 | }; 4 | 5 | exports.conf = { 6 | enabled: true, 7 | guildOnly: false, 8 | aliases: ["updates"], 9 | permLevel: "User", 10 | requiredPerms: [] 11 | }; 12 | 13 | exports.help = { 14 | name: "changelog", 15 | category: "Utility", 16 | description: "Gives you the changes/features introduced with the latest update", 17 | usage: "changelog" 18 | }; 19 | -------------------------------------------------------------------------------- /src/commands/chatlogs.js: -------------------------------------------------------------------------------- 1 | exports.run = async (client, message) => { 2 | 3 | const settings = message.settings; 4 | 5 | if (!client.settings.has(message.guild.id)) client.settings.set(message.guild.id, {}); 6 | 7 | if (message.channel.name !== settings.chatlogsChannel) { 8 | client.settings.set(message.guild.id, message.channel.name, "chatlogsChannel") 9 | message.channel.send(`<:success:466995111885144095> Chat logs will now be displayed in \`${message.channel.name}\``); 10 | } else { 11 | client.settings.set(message.guild.id, "off", "chatlogsChannel") 12 | message.channel.send(`<:success:466995111885144095> Chat logs disabled.`); 13 | } 14 | }; 15 | 16 | exports.conf = { 17 | enabled: true, 18 | guildOnly: true, 19 | aliases: [], 20 | permLevel: "Administrator", 21 | requiredPerms: [] 22 | }; 23 | 24 | exports.help = { 25 | name: "chatlogs", 26 | category: "Configure", 27 | description: "Enables chat logging in your server.", 28 | usage: "chatlogs **OR** chatlogs off" 29 | }; 30 | -------------------------------------------------------------------------------- /src/commands/coinflip.js: -------------------------------------------------------------------------------- 1 | exports.run = (client, message, args) => { 2 | var coin = [ 3 | "Heads!", 4 | "Tails!" 5 | ]; 6 | 7 | let mess = coin.random(); 8 | message.channel.send(mess); 9 | }; 10 | 11 | exports.conf = { 12 | enabled: true, 13 | guildOnly: false, 14 | aliases: ["flip"], 15 | permLevel: "User", 16 | requiredPerms: [] 17 | }; 18 | 19 | exports.help = { 20 | name: "coinflip", 21 | category: "Fun", 22 | description: "Flips a coin!", 23 | usage: "coinflip" 24 | }; 25 | -------------------------------------------------------------------------------- /src/commands/colour.js: -------------------------------------------------------------------------------- 1 | const randomColour = require("randomcolor"); 2 | exports.run = async (client, message, args, level) => { 3 | var colour; 4 | if(!args[0]) { 5 | colour = randomColour(); 6 | } else if(isHex(args.join(" ")) != true) { 7 | colour = stringToHex(args.join(" ")); 8 | } else { 9 | colour = args[0] 10 | } 11 | 12 | embed = new Discord.MessageEmbed(); 13 | embed.setTitle(colour) 14 | embed.setColor(colour); 15 | embed.setImage(`https://fakeimg.pl/256x256/${colour.replace("#", "")}/?text=%20`); 16 | message.channel.send(embed) 17 | }; 18 | 19 | function isHex(string) { 20 | var str = string; 21 | if(str.charAt(0) == "#") { 22 | str = str.slice(1) 23 | }; 24 | 25 | return typeof str === 'string' 26 | && str.length === 6 27 | && !isNaN(Number('0x' + str)) 28 | } 29 | 30 | function stringToHex(string) { 31 | var hash = 0; 32 | for (var i = 0; i < string.length; i++) { 33 | hash = string.charCodeAt(i) + ((hash << 5) - hash); 34 | } 35 | var colour = '#'; 36 | for (var i = 0; i < 3; i++) { 37 | var value = (hash >> (i * 8)) & 0xFF; 38 | colour += ('00' + value.toString(16)).substr(-2); 39 | } 40 | return colour; 41 | }; 42 | 43 | 44 | exports.conf = { 45 | enabled: true, 46 | guildOnly: false, 47 | aliases: ["color"], 48 | permLevel: "User", 49 | requiredPerms: [] 50 | }; 51 | 52 | exports.help = { 53 | name: "colour", 54 | category: "Utility", 55 | description: "Gives you a random colour", 56 | usage: "colour **OR** colour " 57 | }; -------------------------------------------------------------------------------- /src/commands/credits.js: -------------------------------------------------------------------------------- 1 | exports.run = async (client, message, args) => { 2 | message.channel.send( 3 | `__**Credits:**__\n• \`mudkipscience#8904\`, \`FLGX#9896\` and \`TheCakeChicken#9088\` for developing the bot\n• \`An Idiots Guide\` for the Guidebot bot base\n• \`Tina the Cyclops girl#0064\` for helping me not suck at coding\n• \`AirVentTrent\` for the icon, find him on Instagram\n• \`Terryiscool160\` for contributing to Woomy.` 4 | ); 5 | }; 6 | 7 | exports.conf = { 8 | enabled: true, 9 | guildOnly: false, 10 | aliases: [], 11 | permLevel: "User", 12 | requiredPerms: [] 13 | }; 14 | 15 | exports.help = { 16 | name: "credits", 17 | category: "Utility", 18 | description: "Cool people", 19 | usage: "credits" 20 | }; 21 | -------------------------------------------------------------------------------- /src/commands/creeper.js: -------------------------------------------------------------------------------- 1 | 2 | const lyric = require('../../resources/other/lyrics.json') 3 | exports.run = async (client, message, args, level) => { 4 | var lyrics = lyric.creeper; 5 | 6 | var runtop = true; 7 | var runbottom = false; 8 | for(var br = 0; br < lyrics.length; br++) { 9 | { 10 | if (runtop === true) { 11 | var response = await client.awaitReply(message, lyrics[br]); 12 | runbottom = false; 13 | }; 14 | 15 | if (runbottom === true) { 16 | if (response !== lyrics[br]) { 17 | return message.channel.send("Those aren't the lyrics!") 18 | } 19 | runtop = false 20 | }; 21 | } if (runtop === true) { 22 | runtop = false 23 | runbottom = true 24 | } else if (runbottom === true) { 25 | runtop = true 26 | runbottom = false 27 | } 28 | } 29 | message.channel.send("What a lovely duet!") 30 | }; 31 | 32 | exports.conf = { 33 | enabled: true, 34 | guildOnly: false, 35 | aliases: [], 36 | permLevel: "User", 37 | requiredPerms: [] 38 | }; 39 | 40 | exports.help = { 41 | name: "creeper", 42 | category: "Fun", 43 | description: "Aww man", 44 | usage: "creeper" 45 | }; 46 | -------------------------------------------------------------------------------- /src/commands/cuddle.js: -------------------------------------------------------------------------------- 1 | const API = require('nekos.life'); 2 | const {sfw} = new API(); 3 | exports.run = async (client, message, args) => { 4 | if(!args[0]) { 5 | return message.channel.send(`<:error:466995152976871434> You didn't say who you wanted to cuddle! Usage: \`${client.commands.get(`cuddle`).help.usage}\``) 6 | }; 7 | 8 | var people = ""; 9 | 10 | for (var i = 0; i < args.length; i++) { 11 | var user = client.getUserFromMention(args[i]) 12 | if (user) { 13 | user = message.guild.members.cache.get(user.id).displayName; 14 | } else { 15 | users = client.searchForMembers(message.guild, args[i]); 16 | if (users.length > 1) 17 | return message.channel.send( 18 | "<:error:466995152976871434> Found multiple users for `" + args[i] + "`, Please be more specific or mention the user instead." 19 | ); 20 | else if (users.length == 0) 21 | return message.channel.send( 22 | "<:error:466995152976871434> That user doesn't seem to exist. Try again!" 23 | ); 24 | user = users[0].displayName; 25 | }; 26 | if(i+1 == args.length && args.length > 1) { 27 | people += `**and** ${user}!` 28 | } else if(args.length < 2) { 29 | people += `${user}!`; 30 | } else if(args.length == 2 && i == 0) { 31 | people += `${user} `; 32 | } else { 33 | people += `${user}, `; 34 | }; 35 | }; 36 | 37 | 38 | 39 | message.channel.startTyping(); 40 | try { 41 | sfw.cuddle().then((json) => { 42 | embed = new Discord.MessageEmbed(); 43 | embed.setImage(json.url) 44 | embed.setColor(client.embedColour(message)); 45 | embed.setDescription(`**${message.guild.members.cache.get(message.author.id).displayName}** cuddled **${people}**`) 46 | message.channel.send(embed) 47 | message.channel.stopTyping(); 48 | }); 49 | } catch (err) { 50 | client.logger.error("cuddle.js: " + err); 51 | message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`) 52 | message.channel.stopTyping(); 53 | }; 54 | }; 55 | 56 | exports.conf = { 57 | enabled: true, 58 | guildOnly: true, 59 | aliases: [], 60 | permLevel: "User", 61 | requiredPerms: ["EMBED_LINKS"] 62 | }; 63 | 64 | exports.help = { 65 | name: "cuddle", 66 | category: "Action", 67 | description: "cuddle someone!", 68 | usage: "cuddle [@user/user] (you can cuddle as many people as you want!)" 69 | }; 70 | -------------------------------------------------------------------------------- /src/commands/dice.js: -------------------------------------------------------------------------------- 1 | exports.run = async (bot, message, args) => { 2 | if (args.length === 0) { 3 | message.channel.send(`🎲 You rolled a ${Array.from(Array(6).keys()).random() + 1}!`); 4 | } else { 5 | if (args[0].match(/^\d+$/)) { 6 | message.channel.send(`🎲 You rolled a ${Array.from(Array(parseInt(args[0])).keys()).random() + 1}!`); 7 | } else { 8 | message.channel.send(`🎲 You rolled a ${Array.from(Array(6).keys()).random() + 1}!`); 9 | } 10 | } 11 | }; 12 | 13 | exports.conf = { 14 | enabled: true, 15 | guildOnly: false, 16 | aliases: ["diceroll", "roll"], 17 | permLevel: "User", 18 | requiredPerms: [] 19 | }; 20 | 21 | exports.help = { 22 | name: "dice", 23 | category: "Fun", 24 | description: "Rolls a dice.", 25 | usage: "dice " 26 | }; 27 | 28 | -------------------------------------------------------------------------------- /src/commands/dog.js: -------------------------------------------------------------------------------- 1 | const API = require('nekos.life'); 2 | const {sfw} = new API(); 3 | exports.run = async (client, message) => { 4 | message.channel.startTyping(); 5 | try { 6 | sfw.woof().then((json) => { 7 | message.channel.send(json.url) 8 | message.channel.stopTyping(); 9 | }); 10 | } catch (err) { 11 | client.logger.error("dog.js: " + err); 12 | message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`) 13 | message.channel.stopTyping(); 14 | }; 15 | }; 16 | 17 | exports.conf = { 18 | enabled: true, 19 | guildOnly: false, 20 | aliases: [], 21 | permLevel: "User", 22 | requiredPerms: ["EMBED_LINKS"] 23 | }; 24 | 25 | exports.help = { 26 | name: "dog", 27 | category: "Image", 28 | description: "Sends you dog pics.", 29 | usage: "dog" 30 | }; 31 | -------------------------------------------------------------------------------- /src/commands/dogfact.js: -------------------------------------------------------------------------------- 1 | const fetch = require("node-fetch"); 2 | exports.run = async (bot, message, args) => { 3 | message.channel.startTyping(); 4 | try{ 5 | fetch('https://dog-api.kinduff.com/api/facts') 6 | .then(res => res.json()) 7 | .then(json => message.channel.send(`__**Did you know?**__\n ${json.facts[0]}`)) 8 | .catch(err => { 9 | message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`); 10 | }); 11 | } catch(err) { 12 | message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`); 13 | }; 14 | message.channel.stopTyping(); 15 | }; 16 | 17 | exports.conf = { 18 | enabled: true, 19 | guildOnly: false, 20 | aliases: ["pupfact"], 21 | permLevel: "User", 22 | requiredPerms: [] 23 | }; 24 | 25 | exports.help = { 26 | name: "dogfact", 27 | category: "Fun", 28 | description: "Sends a fun fact about a doggo.", 29 | usage: "dogfact/pupfact" 30 | }; 31 | -------------------------------------------------------------------------------- /src/commands/emoji.js: -------------------------------------------------------------------------------- 1 | exports.run = async (client, message, args) => { 2 | if(!args[0]) { 3 | return message.channel.send(`You need to specify a custom emoji. Usage: \`${client.commands.get(`emoji`).help.usage}\``) 4 | }; 5 | 6 | var ID; 7 | var format = ".png" 8 | var string = args[0].replace(/\D/g,''); 9 | 10 | if(args[0].charAt(1) == "a" && args[0].charAt(2) == ":") { 11 | format = ".gif" 12 | }; 13 | 14 | if(string.length > 18) { 15 | ID = string.slice(string.length - 18); 16 | } else { 17 | ID = string; 18 | }; 19 | 20 | if(!ID) { 21 | return message.channel.send(`<:error:466995152976871434> Invalid emoji. This command only works with custom emojis.`) 22 | }; 23 | 24 | 25 | 26 | message.channel.send("https://cdn.discordapp.com/emojis/" + ID + format) 27 | }; 28 | 29 | exports.conf = { 30 | enabled: true, 31 | guildOnly: false, 32 | aliases: [], 33 | permLevel: "User", 34 | requiredPerms: [] 35 | }; 36 | 37 | exports.help = { 38 | name: "emoji", 39 | category: "Utility", 40 | description: "Enlarges and links an custom emoji", 41 | usage: "emoji [emoji]" 42 | }; 43 | -------------------------------------------------------------------------------- /src/commands/emojify.js: -------------------------------------------------------------------------------- 1 | Discord = require("discord.js"); 2 | exports.run = (client, message, args) => { 3 | if (!args[0]) { 4 | return message.channel.send( 5 | `<:error:466995152976871434> You must include a message for me to emojify! Usage: \`${client.commands.get(`emojify`).help.usage}\`` 6 | ); 7 | }; 8 | const specialChars = { 9 | '0': ':zero:', 10 | '1': ':one:', 11 | '2': ':two:', 12 | '3': ':three:', 13 | '4': ':four:', 14 | '5': ':five:', 15 | '6': ':six:', 16 | '7': ':seven:', 17 | '8': ':eight:', 18 | '9': ':nine:', 19 | '#': ':hash:', 20 | '*': ':asterisk:', 21 | '?': ':grey_question:', 22 | '!': ':grey_exclamation:', 23 | ' ': ' ' 24 | }; 25 | 26 | const emojified = `${args.join(' ')}`.toLowerCase().split('').map(letter => { 27 | if (/[a-z]/g.test(letter)) { 28 | return `:regional_indicator_${letter}: ` 29 | } else if (specialChars[letter]) { 30 | return `${specialChars[letter]} ` 31 | }; 32 | return letter 33 | }).join(''); 34 | 35 | if(emojified.length > 2000) { 36 | return message.channel.send("<:error:466995152976871434> The emojified message exceeds 2000 characters.") 37 | }; 38 | 39 | message.channel.send(emojified); 40 | }; 41 | 42 | 43 | exports.conf = { 44 | enabled: true, 45 | guildOnly: false, 46 | aliases: [], 47 | permLevel: "User", 48 | requiredPerms: [] 49 | }; 50 | 51 | exports.help = { 52 | name: "emojify", 53 | category: "Fun", 54 | description: "Changes text into emojis", 55 | usage: "emojify [message]" 56 | }; 57 | -------------------------------------------------------------------------------- /src/commands/eval.js: -------------------------------------------------------------------------------- 1 | const hastebin = require('hastebin-gen'); 2 | exports.run = async (client, message, args) => { 3 | const code = args.join(" "); 4 | try { 5 | const evaled = eval(code); 6 | const clean = await client.clean(client, evaled); 7 | 8 | if(clean.length > 2000) { 9 | hastebin(clean, { extension: "txt" }).then(haste => { 10 | return message.channel.send('`OUTPUT`\n' + haste); 11 | }).catch(error => { 12 | client.logger.err(error); 13 | }); 14 | 15 | return; 16 | } 17 | message.channel.send(`\`OUTPUT\` \`\`\`js\n${await clean}\n\`\`\``); 18 | } catch (err) { 19 | const errclean = await client.clean(client, err); 20 | if(errclean.length > 2000) { 21 | hastebin(errclean, { extension: "txt" }).then(haste => { 22 | return message.channel.send('`ERROR`\n' + haste); 23 | }).catch(error => { 24 | client.logger.err(error); 25 | }); 26 | 27 | return; 28 | } 29 | message.channel.send(`\`ERROR\` \`\`\`xl\n${await errclean}\n\`\`\``); 30 | } 31 | }; 32 | 33 | exports.conf = { 34 | enabled: true, 35 | guildOnly: false, 36 | aliases: [], 37 | permLevel: "Developer", 38 | requiredPerms: [] 39 | }; 40 | 41 | exports.help = { 42 | name: "eval", 43 | category: "Owner", 44 | description: "Evaluates arbitrary javascript.", 45 | usage: "eval [code]" 46 | }; 47 | -------------------------------------------------------------------------------- /src/commands/fact.js: -------------------------------------------------------------------------------- 1 | const API = require('nekos.life'); 2 | const {sfw} = new API(); 3 | exports.run = async (client, message) => { 4 | message.channel.startTyping(); 5 | try { 6 | sfw.fact().then((json) => { 7 | message.channel.send("__**Did you know?**__\n" + json.fact + "."); 8 | message.channel.stopTyping(); 9 | }); 10 | } catch (err) { 11 | client.logger.error("fact.js: " + err); 12 | message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`) 13 | message.channel.stopTyping(); 14 | }; 15 | }; 16 | 17 | exports.conf = { 18 | enabled: true, 19 | guildOnly: false, 20 | aliases: ["randomfact"], 21 | permLevel: "User", 22 | requiredPerms: [] 23 | }; 24 | 25 | exports.help = { 26 | name: "fact", 27 | category: "Fun", 28 | description: "Sends you a random fact.", 29 | usage: "fact" 30 | }; 31 | -------------------------------------------------------------------------------- /src/commands/feed.js: -------------------------------------------------------------------------------- 1 | const API = require('nekos.life'); 2 | const {sfw} = new API(); 3 | exports.run = async (client, message, args) => { 4 | if(!args[0]) { 5 | return message.channel.send(`<:error:466995152976871434> You didn't say who you wanted to feed! Usage: \`${client.commands.get(`feed`).help.usage}\``) 6 | }; 7 | 8 | var people = ""; 9 | 10 | for (var i = 0; i < args.length; i++) { 11 | var user = client.getUserFromMention(args[i]) 12 | if (user) { 13 | user = message.guild.members.cache.get(user.id).displayName; 14 | } else { 15 | users = client.searchForMembers(message.guild, args[i]); 16 | if (users.length > 1) 17 | return message.channel.send( 18 | "<:error:466995152976871434> Found multiple users for `" + args[i] + "`, Please be more specific or mention the user instead." 19 | ); 20 | else if (users.length == 0) 21 | return message.channel.send( 22 | "<:error:466995152976871434> That user doesn't seem to exist. Try again!" 23 | ); 24 | user = users[0].displayName; 25 | }; 26 | if(i+1 == args.length && args.length > 1) { 27 | people += `**and** ${user}!` 28 | } else if(args.length < 2) { 29 | people += `${user}!`; 30 | } else if(args.length == 2 && i == 0) { 31 | people += `${user} `; 32 | } else { 33 | people += `${user}, `; 34 | }; 35 | }; 36 | 37 | 38 | 39 | message.channel.startTyping(); 40 | try { 41 | sfw.feed().then((json) => { 42 | embed = new Discord.MessageEmbed(); 43 | embed.setImage(json.url) 44 | embed.setColor(client.embedColour(message)); 45 | embed.setDescription(`**${message.guild.members.cache.get(message.author.id).displayName}** fed **${people}**`) 46 | message.channel.send(embed) 47 | message.channel.stopTyping(); 48 | }); 49 | } catch (err) { 50 | client.logger.error("feed.js: " + err); 51 | message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`) 52 | message.channel.stopTyping(); 53 | }; 54 | }; 55 | 56 | exports.conf = { 57 | enabled: true, 58 | guildOnly: true, 59 | aliases: [], 60 | permLevel: "User", 61 | requiredPerms: ["EMBED_LINKS"] 62 | }; 63 | 64 | exports.help = { 65 | name: "feed", 66 | category: "Action", 67 | description: "feed someone!", 68 | usage: "feed [@user/user] (you can feed as many people as you want!)" 69 | }; 70 | -------------------------------------------------------------------------------- /src/commands/feedback.js: -------------------------------------------------------------------------------- 1 | exports.run = (client, message, args, level) => { 2 | if(!args[0]) return message.channel.send(`<:error:466995152976871434> You didn't give me any feedback! Usage: \`${client.commands.get(`feedback`).help.usage}\``) 3 | const feedback = args.join(" ") 4 | let guild = client.guilds.cache.get("410990517841690625") 5 | let channel = guild.channels.cache.get("438825830949453824") 6 | let embed = new Discord.MessageEmbed() 7 | .setTitle(`Feedback:`) 8 | .setColor(client.embedColour(message)) 9 | .addField("User:",message.author.tag) 10 | .addField("Feedback: ", feedback) 11 | channel.send({embed: embed}) 12 | message.channel.send("<:success:466995111885144095> Your feedback has been sent to my developer. Thank you!") 13 | }; 14 | 15 | exports.conf = { 16 | enabled: true, 17 | guildOnly: false, 18 | aliases: ["suggest"], 19 | permLevel: "User", 20 | requiredPerms: [] 21 | }; 22 | 23 | exports.help = { 24 | name: "feedback", 25 | category: "Utility", 26 | description: "Send feedback to my developer.", 27 | usage: "feedback [message]" 28 | }; 29 | -------------------------------------------------------------------------------- /src/commands/fixmusic.js: -------------------------------------------------------------------------------- 1 | const { getGuild } = require('../modules/music') 2 | module.exports.run = async (client, message, args, level) =>{ 3 | guild = getGuild(message.guild.id) 4 | 5 | const lvl = client.config.permLevels.find(l => l.level === level) 6 | 7 | if (lvl.level >= 1) { 8 | guild.queue = [] 9 | guild.playing = false 10 | guild.paused = false 11 | guild.skippers = [] 12 | guild.fixers = [] 13 | guild.channel = null 14 | 15 | if (guild.dispatcher) { 16 | guild.dispatcher.end('silent') 17 | } 18 | 19 | guild.fixers = [] 20 | 21 | message.channel.send( 22 | '<:success:466995111885144095> Music has been fixed!' 23 | ) 24 | 25 | return 26 | } 27 | 28 | const vc = message.guild.members.cache.get(client.user.id).voice.channel 29 | 30 | if (guild.fixers.indexOf(message.author.id) === -1) { 31 | guild.fixers.push(message.author.id) 32 | 33 | if (guild.fixers.length >= Math.ceil(vc.members.filter(member => !member.user.bot).size / 2)) { 34 | guild.queue = [] 35 | guild.playing = false 36 | guild.paused = false 37 | guild.skippers = [] 38 | guild.fixers = [] 39 | guild.channel = null 40 | 41 | if (guild.dispatcher) { 42 | guild.dispatcher.end('silent') 43 | } 44 | 45 | guild.fixers = [] 46 | 47 | message.channel.send( 48 | '<:success:466995111885144095> Music has been fixed!' 49 | ) 50 | } else { 51 | message.channel.send( 52 | `<:success:466995111885144095> Your vote has been acknowledged! **${guild.fixers.length + '/' + Math.ceil(vc.members.filter(member => !member.user.bot).size / 2)}**` 53 | ) 54 | }; 55 | } else { 56 | message.channel.send( 57 | '<:denied:466995195150336020> You cannot vote twice!' 58 | ) 59 | } 60 | } 61 | 62 | exports.conf = { 63 | enabled: true, 64 | guildOnly: true, 65 | aliases: [], 66 | permLevel: "User", 67 | requiredPerms: [] 68 | }; 69 | 70 | exports.help = { 71 | name: "fixmusic", 72 | category: "Music", 73 | description: 'Fixes music if it breaks.', 74 | usage: 'fixmusic', 75 | }; 76 | -------------------------------------------------------------------------------- /src/commands/forceskip.js: -------------------------------------------------------------------------------- 1 | const { skip, getGuild } = require('../modules/music') 2 | exports.run = (client, message) => { 3 | const guild = getGuild(message.guild.id) 4 | 5 | if (guild.queue.length < 1 || !guild.playing || !guild.dispatcher) { 6 | return message.channel.send( 7 | '<:error:466995152976871434> Nothing is playing.' 8 | ) 9 | } 10 | 11 | skip(message.guild, 'skip') 12 | 13 | guild.skippers = [] 14 | 15 | message.channel.send('<:success:466995111885144095> Song skipped.') 16 | }; 17 | 18 | exports.conf = { 19 | enabled: true, 20 | guildOnly: true, 21 | aliases: [], 22 | permLevel: "Moderator", 23 | requiredPerms: [] 24 | }; 25 | 26 | exports.help = { 27 | name: "forceskip", 28 | category: "Music", 29 | description: "Skips the currently playing song without requiring a vote.", 30 | usage: "forceskip" 31 | }; 32 | -------------------------------------------------------------------------------- /src/commands/garfield.js: -------------------------------------------------------------------------------- 1 | const fetch = require("node-fetch") 2 | const { MessageEmbed } = require('discord.js') 3 | exports.run = async (client, message) => { 4 | message.channel.startTyping(); 5 | try { 6 | fetch('https://garfield-comics.glitch.me/~SRoMG/?date=xxxx') 7 | .then(res => res.json()) 8 | .then(json => { 9 | const embed = new MessageEmbed() 10 | .setTitle(`${json.data.name} (No. ${json.data.number})`) 11 | .setColor(client.embedColour(message)) 12 | .setURL('https://www.mezzacotta.net/garfield/?comic=' + json.data.number) 13 | .setImage(json.data.image.src); 14 | message.channel.send(embed) 15 | }) 16 | .catch(err => { 17 | message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`); 18 | }); 19 | message.channel.stopTyping(); 20 | } catch (err) { 21 | message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`) 22 | message.channel.stopTyping(); 23 | }; 24 | }; 25 | 26 | exports.conf = { 27 | enabled: true, 28 | guildOnly: false, 29 | aliases: [], 30 | permLevel: "User", 31 | requiredPerms: ["ATTACH_FILES"] 32 | }; 33 | 34 | exports.help = { 35 | name: "garfield", 36 | category: "Fun", 37 | description: "Sends you a random garfield comic", 38 | usage: "garfield" 39 | }; 40 | -------------------------------------------------------------------------------- /src/commands/giverole.js: -------------------------------------------------------------------------------- 1 | exports.run = async (client, message, [member, ...role2add], query) => { 2 | if (!member) { 3 | return message.channel.send( 4 | "<:error:466995152976871434> Who am I meant to give a role?" 5 | ); 6 | } 7 | let user = message.mentions.members.first(); 8 | let users; 9 | if (!user) { 10 | users = client.searchForMembers(message.guild, member); 11 | if (users.length > 1) 12 | return message.channel.send( 13 | "<:error:466995152976871434> Found multiple users! Please be more specific or mention the user instead." 14 | ); 15 | else if (users.length == 0) 16 | return message.channel.send( 17 | "<:error:466995152976871434> That user doesn't seem to exist. Try again!" 18 | ); 19 | user = users[0]; 20 | } 21 | let joinedValue = role2add.join(" "); 22 | 23 | let gRole = client.findRole(joinedValue, message); 24 | 25 | if (!gRole) { 26 | return message.channel.send(`<:error:466995152976871434> That role doesn't seem to exist. Try again!`); 27 | }; 28 | 29 | let moderator = message.guild.member(message.author) 30 | if (gRole.position >= moderator.roles.highest.position) { 31 | return message.channel.send( 32 | "<:error:466995152976871434> You cannot give roles higher than your own!" 33 | ); 34 | } 35 | 36 | var bot = message.guild.members.cache.get(client.user.id) 37 | if (gRole.position >= bot.roles.highest.position) { 38 | return message.channel.send( 39 | `<:error:466995152976871434> I cannot give roles higher than my own!` 40 | ); 41 | } 42 | 43 | if (user.roles.cache.has(gRole.id)) { 44 | return message.channel.send( 45 | "<:error:466995152976871434> They already have that role!" 46 | ); 47 | } 48 | 49 | await user.roles.add(gRole.id); 50 | message.channel.send( 51 | `<:success:466995111885144095> Gave \`${user.user.tag}\` the \`${gRole.name}\` role.` 52 | ); 53 | 54 | if (client.getSettings(message.guild.id).modlogsChannel !== "off") { 55 | const channel = message.guild.channels.cache.find( 56 | channel => channel.name === client.getSettings(message.guild.id).modlogsChannel 57 | ); 58 | 59 | if (channel) { 60 | let embed = new Discord.MessageEmbed(); 61 | embed.setColor("#00c09a"); 62 | embed.setAuthor("Role given:", user.user.avatarURL({format: "png", dynamic: true, size: 2048})); 63 | embed.setDescription(`‏‏‎• User: ${user} (${user.user.id})\n‏‏‎• Mod: ${message.author} (${message.author.id})\n‏‏‎• Role: ${gRole}`) 64 | try { 65 | channel.send({ embed }); 66 | } catch (err) { 67 | // probably no permissions to send messages/embeds there 68 | }; 69 | }; 70 | }; 71 | 72 | }; 73 | 74 | exports.conf = { 75 | enabled: true, 76 | guildOnly: true, 77 | aliases: ["addrole"], 78 | permLevel: "Moderator", 79 | requiredPerms: ["MANAGE_ROLES"] 80 | }; 81 | 82 | exports.help = { 83 | name: "giverole", 84 | category: "Moderation", 85 | description: "Gives the user the specified role.", 86 | usage: "giverole [user] [role]" 87 | }; 88 | -------------------------------------------------------------------------------- /src/commands/goodbye.js: -------------------------------------------------------------------------------- 1 | exports.run = async (client, message, args, level) => { 2 | 3 | const settings = message.settings; 4 | if (!client.settings.has(message.guild.id)) client.settings.set(message.guild.id, {}); 5 | 6 | if (args[0]) { 7 | const joinedValue = args.join(" "); 8 | if (joinedValue === settings.welcomeMessage) return message.channel.send( 9 | "<:error:466995152976871434> The leave message is already set to that!" 10 | ); 11 | if (!client.settings.has(message.guild.id)) client.settings.set(message.guild.id, {}); 12 | if (joinedValue === "off") { 13 | if (!client.settings.has(message.guild.id)) client.settings.set(message.guild.id, {}); 14 | client.settings.set(message.guild.id, "off", "leaveMessage"); 15 | return message.channel.send(`<:success:466995111885144095> Leave messages have been disabled.`); 16 | } 17 | client.settings.set(message.guild.id, joinedValue, "leaveMessage"); 18 | client.settings.set(message.guild.id, message.channel.id, "welcomeChannel") 19 | message.channel.send(`<:success:466995111885144095> Set the leave message to \`${joinedValue}\``); 20 | } else { 21 | if (settings.leaveMessage === "off") { 22 | message.channel.send(`Leave messages are off.`) 23 | } else { 24 | message.channel.send(`The current leave message is: \`${settings.leaveMessage}\``) 25 | } 26 | } 27 | }; 28 | 29 | exports.conf = { 30 | enabled: true, 31 | guildOnly: true, 32 | aliases: [], 33 | permLevel: "Administrator", 34 | requiredPerms: [] 35 | }; 36 | 37 | exports.help = { 38 | name: "goodbye", 39 | category: "Configure", 40 | description: "Sets the leave message for this server. try using [[server]], [[user]] and [[members]] in your message!", 41 | usage: "goodbye **OR** goodbye off" 42 | }; 43 | -------------------------------------------------------------------------------- /src/commands/hackban.js: -------------------------------------------------------------------------------- 1 | exports.run = async (client, message, args) => { 2 | const settings = (message.settings = client.getSettings(message.guild.id)); 3 | 4 | if(!args[0]) { 5 | return message.channel.send( 6 | `<:error:466995152976871434> No user ID provided. Usage: \`${client.commands.get(`hackban`).help.usage}\`` 7 | ); 8 | }; 9 | 10 | user = client.users.cache.get(args[0]) 11 | if(!user) { 12 | return message.channel.send("<:error:466995152976871434> Invalid ID") 13 | } 14 | 15 | if(message.guild.member(args[0])) { 16 | if(!message.guild.member(args[0]).bannable) { 17 | return message.channel.send("<:error:466995152976871434> User is not bannable.") 18 | } 19 | } 20 | 21 | let reason = args.slice(1).join(" "); 22 | if (!reason) reason = `Banned by ${message.author.tag}`; 23 | await message.guild.members.ban(args[0], {reason: reason}).catch(console.error); 24 | message.channel.send(`<:success:466995111885144095> Hackbanned \`${user.tag}\``); 25 | 26 | if (settings.modlogsChannel !== "off") { 27 | const channel = message.guild.channels.cache.find( 28 | channel => channel.name === settings.modlogsChannel 29 | ); 30 | 31 | if (channel) { 32 | let embed = new Discord.MessageEmbed(); 33 | embed.setColor("#BC0057"); 34 | embed.setAuthor("User banned!", user.avatarURL({format: "png", dynamic: true, size: 2048})); 35 | embed.setDescription( 36 | `• User: ${user.tag} (${user.id})\n• Mod: ${message.author} (${message.author.id})\n• Reason: ${reason}` 37 | ); 38 | try { 39 | channel.send(embed); 40 | } catch (err) { 41 | // probably no permissions to send messages/embeds there 42 | }; 43 | } 44 | }; 45 | }; 46 | 47 | exports.conf = { 48 | enabled: true, 49 | guildOnly: true, 50 | aliases: [], 51 | permLevel: "Moderator", 52 | requiredPerms: ["BAN_MEMBERS"] 53 | }; 54 | 55 | exports.help = { 56 | name: "hackban", 57 | category: "Moderation", 58 | description: "Ban users who are not in the server.", 59 | usage: "ban [userID] " 60 | }; 61 | -------------------------------------------------------------------------------- /src/commands/hug.js: -------------------------------------------------------------------------------- 1 | const API = require('nekos.life'); 2 | const {sfw} = new API(); 3 | exports.run = async (client, message, args) => { 4 | if(!args[0]) { 5 | return message.channel.send(`<:error:466995152976871434> You didn't say who you wanted to hug! Usage: \`${client.commands.get(`hug`).help.usage}\``) 6 | }; 7 | 8 | var people = ""; 9 | 10 | for (var i = 0; i < args.length; i++) { 11 | var user = client.getUserFromMention(args[i]) 12 | if (user) { 13 | user = message.guild.members.cache.get(user.id).displayName; 14 | } else { 15 | users = client.searchForMembers(message.guild, args[i]); 16 | if (users.length > 1) 17 | return message.channel.send( 18 | "<:error:466995152976871434> Found multiple users for `" + args[i] + "`, Please be more specific or mention the user instead." 19 | ); 20 | else if (users.length == 0) 21 | return message.channel.send( 22 | "<:error:466995152976871434> That user doesn't seem to exist. Try again!" 23 | ); 24 | user = users[0].displayName; 25 | }; 26 | if(i+1 == args.length && args.length > 1) { 27 | people += `**and** ${user}!` 28 | } else if(args.length < 2) { 29 | people += `${user}!`; 30 | } else if(args.length == 2 && i == 0) { 31 | people += `${user} `; 32 | } else { 33 | people += `${user}, `; 34 | }; 35 | }; 36 | 37 | 38 | 39 | message.channel.startTyping(); 40 | try { 41 | sfw.hug().then((json) => { 42 | embed = new Discord.MessageEmbed(); 43 | embed.setImage(json.url) 44 | embed.setColor(client.embedColour(message)); 45 | embed.setDescription(`**${message.guild.members.cache.get(message.author.id).displayName}** hugged **${people}**`) 46 | message.channel.send(embed) 47 | message.channel.stopTyping(); 48 | }); 49 | } catch (err) { 50 | client.logger.error("hug.js: " + err); 51 | message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`) 52 | message.channel.stopTyping(); 53 | }; 54 | }; 55 | 56 | exports.conf = { 57 | enabled: true, 58 | guildOnly: true, 59 | aliases: [], 60 | permLevel: "User", 61 | requiredPerms: ["EMBED_LINKS"] 62 | }; 63 | 64 | exports.help = { 65 | name: "hug", 66 | category: "Action", 67 | description: "Hug someone!", 68 | usage: "hug [@user/user] (you can hug as many people as you want!)" 69 | }; 70 | -------------------------------------------------------------------------------- /src/commands/identity.js: -------------------------------------------------------------------------------- 1 | const identities = require ("../../resources/other/identities.json"); 2 | exports.run = async (client, message, args) => { 3 | var output = ""; 4 | if(!args[0]) { 5 | for (var key of Object.keys(identities)) { 6 | output += `${key}, ` 7 | }; 8 | return message.channel.send(`__**Identities**__\n${output.slice(0, -2)}`); 9 | } else { 10 | if(args.join(" ").toLowerCase() == "attack helicopter" || args.join(" ").toLowerCase() == "apache attack helicopter" || args.join(" ").toLowerCase() == "apache") { 11 | return message.channel.send({ 12 | files: [new Discord.MessageAttachment("./resources/images/attackhelicopter.jpg")] 13 | }); 14 | } 15 | output = identities[args.join(" ").toLowerCase()]; 16 | if(!output) { 17 | return message.channel.send("<:error:466995152976871434> No results for that query."); 18 | }; 19 | return message.channel.send(`__**${output.name.toProperCase()}**__\n${output.description}`); 20 | }; 21 | }; 22 | 23 | exports.conf = { 24 | enabled: true, 25 | guildOnly: false, 26 | aliases: ["identities"], 27 | permLevel: "User", 28 | requiredPerms: [] 29 | }; 30 | 31 | exports.help = { 32 | name: "identity", 33 | category: "Fun", 34 | description: "Gives you information about the specified identity.", 35 | usage: "identity [identity]" 36 | }; 37 | -------------------------------------------------------------------------------- /src/commands/inspirobot.js: -------------------------------------------------------------------------------- 1 | const fetch = require("node-fetch") 2 | exports.run = async (client, message) => { 3 | message.channel.startTyping(); 4 | try { 5 | fetch('http://inspirobot.me/api?generate=true') 6 | .then(res => res.text()) 7 | .then(body => message.channel.send({files: [new Discord.MessageAttachment(body)]})) 8 | .catch(err => { 9 | message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`); 10 | }); 11 | message.channel.stopTyping(); 12 | } catch (err) { 13 | message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`) 14 | message.channel.stopTyping(); 15 | }; 16 | }; 17 | 18 | exports.conf = { 19 | enabled: true, 20 | guildOnly: false, 21 | aliases: ["inspire"], 22 | permLevel: "User", 23 | requiredPerms: [] 24 | }; 25 | 26 | exports.help = { 27 | name: "inspirobot", 28 | category: "Fun", 29 | description: "Returns an inspirational message generated by inspirobot.", 30 | usage: "inspirobot" 31 | }; 32 | -------------------------------------------------------------------------------- /src/commands/invite.js: -------------------------------------------------------------------------------- 1 | exports.run = async (client, message) => { 2 | message.channel.send( 3 | `Use this link to invite me to your server:\n` 4 | ); 5 | }; 6 | 7 | exports.conf = { 8 | enabled: true, 9 | guildOnly: false, 10 | aliases: [], 11 | permLevel: "User", 12 | requiredPerms: [] 13 | }; 14 | 15 | exports.help = { 16 | name: "invite", 17 | category: "Utility", 18 | description: "Sends you a link so you can add Woomy to your own servers", 19 | usage: "invite" 20 | }; 21 | -------------------------------------------------------------------------------- /src/commands/kemonomimi.js: -------------------------------------------------------------------------------- 1 | const API = require('nekos.life'); 2 | const {sfw} = new API(); 3 | exports.run = async (client, message) => { 4 | message.channel.startTyping(); 5 | try { 6 | sfw.kemonomimi().then((json) => { 7 | message.channel.send(json.url) 8 | message.channel.stopTyping(); 9 | }); 10 | } catch (err) { 11 | client.logger.error("kemonomimi.js: " + err); 12 | message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`) 13 | message.channel.stopTyping(); 14 | }; 15 | }; 16 | 17 | exports.conf = { 18 | enabled: false, 19 | guildOnly: false, 20 | aliases: [], 21 | permLevel: "User", 22 | requiredPerms: ["EMBED_LINKS"] 23 | }; 24 | 25 | exports.help = { 26 | name: "kemonomimi", 27 | category: "Image", 28 | description: "Sends you pictures of people with animal characteristics.", 29 | usage: "kemonomimi" 30 | }; 31 | -------------------------------------------------------------------------------- /src/commands/kick.js: -------------------------------------------------------------------------------- 1 | exports.run = async (client, message, args) => { 2 | const settings = client.getSettings(message.guild.id); 3 | 4 | if(!args[0]) { 5 | return message.channel.send("<:error:466995152976871434> Who am I meant to kick?") 6 | } 7 | 8 | let user = message.mentions.members.first(); 9 | 10 | if (!user) { 11 | let users; 12 | users = client.searchForMembers(message.guild, args[0]); 13 | if (users.length > 1) 14 | return message.channel.send( 15 | "<:error:466995152976871434> Found multiple users! Please be more specific or mention the user instead." 16 | ); 17 | else if (users.length == 0) 18 | return message.channel.send( 19 | "<:error:466995152976871434> That user doesn't seem to exist. Try again!" 20 | ); 21 | user = users[0]; 22 | } 23 | if (user.user.id === client.user.id) { 24 | return message.channel.send("lol no") 25 | } 26 | if (user.user.id === message.guild.owner.id) { 27 | return message.channel.send("<:error:466995152976871434> You can't kick the owner!") 28 | } 29 | let moderator = message.guild.member(message.author) 30 | if (user.roles.highest.position >= moderator.roles.highest.position && moderator.user.id !== message.guild.ownerID) { 31 | return message.channel.send( 32 | `<:error:466995152976871434> You can't kick people higher ranked than yourself!` 33 | ); 34 | } 35 | 36 | let bot = message.guild.member(client.user) 37 | if (user.roles.highest.position >= bot.roles.highest.position) { 38 | return message.channel.send( 39 | `<:error:466995152976871434> I can't kick people who are higher ranked than me!` 40 | ); 41 | } 42 | 43 | if (!user.bannable) 44 | return message.channel.send( 45 | "<:error:466995152976871434> Specified user is not bannable." 46 | ); 47 | 48 | let reason = args.slice(1).join(" "); 49 | if (!reason) reason = `Kicked by ${message.author.tag}`; 50 | await user.kick(reason).catch(console.error); 51 | message.channel.send(`<:success:466995111885144095> Kicked \`${user.user.tag}\``); 52 | 53 | if (settings.modlogsChannel !== "off") { 54 | const channel = message.guild.channels.cache.find( 55 | channel => channel.name === settings.modlogsChannel 56 | ); 57 | 58 | if (channel) { 59 | let embed = new Discord.MessageEmbed(); 60 | embed.setColor("#fd0061"); 61 | embed.setAuthor("User kicked!", user.user.avatarURL({format: "png", dynamic: true, size: 2048})); 62 | embed.setDescription( 63 | `• User: ${user.user.tag} (${user.user.id})\n• Mod: ${message.author} (${message.author.id})\n• Reason: ${reason}` 64 | ); 65 | try { 66 | channel.send({ embed }); 67 | } catch (err) { 68 | // probably no permissions to send messages/embeds there 69 | }; 70 | }; 71 | }; 72 | }; 73 | 74 | exports.conf = { 75 | enabled: true, 76 | guildOnly: true, 77 | aliases: [], 78 | permLevel: "Moderator", 79 | requiredPerms: ["KICK_MEMBERS"] 80 | }; 81 | 82 | exports.help = { 83 | name: "kick", 84 | category: "Moderation", 85 | description: "Kicks specified user.", 86 | usage: "kick [user] " 87 | }; 88 | -------------------------------------------------------------------------------- /src/commands/kiss.js: -------------------------------------------------------------------------------- 1 | const API = require('nekos.life'); 2 | const {sfw} = new API(); 3 | exports.run = async (client, message, args) => { 4 | if(!args[0]) { 5 | return message.channel.send(`<:error:466995152976871434> You didn't say who you wanted to kiss! Usage: \`${client.commands.get(`kiss`).help.usage}\``) 6 | }; 7 | 8 | var people = ""; 9 | 10 | for (var i = 0; i < args.length; i++) { 11 | var user = client.getUserFromMention(args[i]) 12 | if (user) { 13 | user = message.guild.members.cache.get(user.id).displayName; 14 | } else { 15 | users = client.searchForMembers(message.guild, args[i]); 16 | if (users.length > 1) 17 | return message.channel.send( 18 | "<:error:466995152976871434> Found multiple users for `" + args[i] + "`, Please be more specific or mention the user instead." 19 | ); 20 | else if (users.length == 0) 21 | return message.channel.send( 22 | "<:error:466995152976871434> That user doesn't seem to exist. Try again!" 23 | ); 24 | user = users[0].displayName; 25 | }; 26 | if(i+1 == args.length && args.length > 1) { 27 | people += `**and** ${user}!` 28 | } else if(args.length < 2) { 29 | people += `${user}!`; 30 | } else if(args.length == 2 && i == 0) { 31 | people += `${user} `; 32 | } else { 33 | people += `${user}, `; 34 | }; 35 | }; 36 | 37 | 38 | 39 | message.channel.startTyping(); 40 | try { 41 | sfw.kiss().then((json) => { 42 | embed = new Discord.MessageEmbed(); 43 | embed.setImage(json.url) 44 | embed.setColor(client.embedColour(message)); 45 | embed.setDescription(`**${message.guild.members.cache.get(message.author.id).displayName}** kissed **${people}**`) 46 | message.channel.send(embed) 47 | message.channel.stopTyping(); 48 | }); 49 | } catch (err) { 50 | client.logger.error("kiss.js: " + err); 51 | message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`) 52 | message.channel.stopTyping(); 53 | }; 54 | }; 55 | 56 | exports.conf = { 57 | enabled: true, 58 | guildOnly: true, 59 | aliases: [], 60 | permLevel: "User", 61 | requiredPerms: ["EMBED_LINKS"] 62 | }; 63 | 64 | exports.help = { 65 | name: "kiss", 66 | category: "Action", 67 | description: "Kiss someone!", 68 | usage: "kiss [@user/user] (you can kiss as many people as you want!)" 69 | }; 70 | -------------------------------------------------------------------------------- /src/commands/kitsune.js: -------------------------------------------------------------------------------- 1 | const fetch = require("node-fetch") 2 | exports.run = async (client, message, args) => { 3 | message.channel.startTyping(); 4 | try{ 5 | fetch(`https://purrbot.site/api/img/sfw/kitsune/img/`) 6 | .then(res => res.json()) 7 | .then(json => message.channel.send(json.link)) 8 | .catch(err => { 9 | message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`); 10 | }); 11 | message.channel.stopTyping(); 12 | } catch(err) { 13 | message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`); 14 | message.channel.stopTyping(); 15 | }; 16 | }; 17 | 18 | exports.conf = { 19 | enabled: false, 20 | guildOnly: false, 21 | aliases: ['foxgirl'], 22 | permLevel: "User", 23 | requiredPerms: ["EMBED_LINKS"] 24 | }; 25 | 26 | exports.help = { 27 | name: "kitsune", 28 | category: "Image", 29 | description: "Sends you cute wholesome pictures of foxgirls.", 30 | usage: "kitsune" 31 | }; 32 | -------------------------------------------------------------------------------- /src/commands/lizard.js: -------------------------------------------------------------------------------- 1 | const API = require('nekos.life'); 2 | const {sfw} = new API(); 3 | exports.run = async (client, message) => { 4 | message.channel.startTyping(); 5 | try { 6 | sfw.lizard().then((json) => { 7 | message.channel.send(json.url) 8 | message.channel.stopTyping(); 9 | }); 10 | } catch (err) { 11 | client.logger.error("lizard.js: " + err); 12 | message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`) 13 | message.channel.stopTyping(); 14 | }; 15 | }; 16 | 17 | exports.conf = { 18 | enabled: true, 19 | guildOnly: true, 20 | aliases: [], 21 | permLevel: "User", 22 | requiredPerms: ["EMBED_LINKS"] 23 | }; 24 | 25 | exports.help = { 26 | name: "lizard", 27 | category: "Image", 28 | description: "Sends pictures of lizards.", 29 | usage: "lizard" 30 | }; 31 | -------------------------------------------------------------------------------- /src/commands/lmgtfy.js: -------------------------------------------------------------------------------- 1 | const identities = require ("../../resources/other/identities.json"); 2 | exports.run = async (client, message, args) => { 3 | if (!args[0]) { 4 | return message.channel.send("Missing arguments, please provide me with a query!") 5 | } 6 | 7 | const query = args.join("+") 8 | 9 | let link = ("https://lmgtfy.com/?q=" + query) 10 | 11 | if (message.flags.includes('d')) { 12 | link = "https://lmgtfy.com/?q=" + query + "&pp=1&s=d" 13 | } 14 | 15 | message.channel.send(link) 16 | }; 17 | 18 | exports.conf = { 19 | enabled: true, 20 | guildOnly: false, 21 | aliases: [], 22 | permLevel: "User", 23 | requiredPerms: [] 24 | }; 25 | 26 | exports.help = { 27 | name: "lmgtfy", 28 | category: "Fun", 29 | description: "For when you need to remind someone search engines exist..", 30 | usage: "lmgtfy " 31 | }; 32 | -------------------------------------------------------------------------------- /src/commands/modlogs.js: -------------------------------------------------------------------------------- 1 | exports.run = async (client, message) => { 2 | const settings = message.settings; 3 | 4 | if (!client.settings.has(message.guild.id)) client.settings.set(message.guild.id, {}); 5 | 6 | if (message.channel.name !== settings.modlogsChannel) { 7 | client.settings.set(message.guild.id, message.channel.name, "modlogsChannel") 8 | message.channel.send(`<:success:466995111885144095> Mod logs will now be displayed in \`${message.channel.name}\``); 9 | } else { 10 | client.settings.set(message.guild.id, "off", "modlogsChannel") 11 | message.channel.send(`<:success:466995111885144095> Mod logging disabled.`); 12 | } 13 | }; 14 | 15 | exports.conf = { 16 | enabled: true, 17 | guildOnly: true, 18 | aliases: [], 19 | permLevel: "Administrator", 20 | requiredPerms: [] 21 | }; 22 | 23 | exports.help = { 24 | name: "modlogs", 25 | category: "Configure", 26 | description: "Enables mod action logging in your server.", 27 | usage: "modlogs **OR** modlogs off" 28 | }; 29 | -------------------------------------------------------------------------------- /src/commands/modrole.js: -------------------------------------------------------------------------------- 1 | exports.run = async (client, message, args) => { 2 | 3 | const settings = message.settings; 4 | 5 | if (!client.settings.has(message.guild.id)) { 6 | client.settings.set(message.guild.id, {}); 7 | } 8 | 9 | var modRole = message.guild.roles.cache.get(settings.modRole) 10 | 11 | if (!args[0]) { 12 | if(!modRole) { 13 | return message.channel.send( 14 | "<:error:466995152976871434> There is no mod role set for this server. Please set one using `" + message.settings.prefix + "modrole `" 15 | ) 16 | } else { 17 | message.channel.send(`The current mod role is: \`${modRole.name}\``) 18 | } 19 | 20 | } else { 21 | const joinedValue = args.join(" "); 22 | if (joinedValue.length < 1) { 23 | return message.channel.send( 24 | `<:error:466995152976871434> You didn't specify a role. Usage: \`${client.commands.get(`modrole`).help.usage}\`` 25 | ); 26 | }; 27 | 28 | if (settings.modRole != "None set" && joinedValue === modRole.name) { 29 | return message.channel.send( 30 | "<:error:466995152976871434> The mod role is already set to that!" 31 | ); 32 | }; 33 | 34 | let role = client.findRole(joinedValue, message); 35 | 36 | if (!role) { 37 | return message.channel.send(`<:error:466995152976871434> That role doesn't seem to exist. Try again!`); 38 | }; 39 | 40 | client.settings.set(message.guild.id, role.id, "modRole"); 41 | 42 | message.channel.send( 43 | `<:success:466995111885144095> The mod role has been set to \`${role.name}\` 44 | `); 45 | }; 46 | }; 47 | 48 | exports.conf = { 49 | enabled: true, 50 | guildOnly: true, 51 | aliases: [], 52 | permLevel: "Administrator", 53 | requiredPerms: [] 54 | }; 55 | 56 | exports.help = { 57 | name: "modrole", 58 | category: "Configure", 59 | description: "Sets the mod role for this server.", 60 | usage: "modrole " 61 | }; -------------------------------------------------------------------------------- /src/commands/movehere.js: -------------------------------------------------------------------------------- 1 | const { getGuild } = require('../modules/music') 2 | const Discord = require("discord.js") 3 | 4 | module.exports.run = async (client, message, args, level) =>{ 5 | const guild = getGuild(message.guild.id) 6 | 7 | if (!guild.playing) { 8 | return message.channel.send('<:error:466995152976871434> Nothing is playing.') 9 | } 10 | 11 | if (guild.channel.id === message.channel.id) { 12 | return message.channel.send('<:error:466995152976871434> Music messages are already being sent to this channel.') 13 | } 14 | 15 | guild.channel = message.channel 16 | 17 | message.channel.send('<:success:466995111885144095> Music messages will now be sent to this channel.') 18 | } 19 | 20 | exports.conf = { 21 | enabled: true, 22 | guildOnly: true, 23 | aliases: [], 24 | permLevel: "Moderator", 25 | requiredPerms: [] 26 | }; 27 | 28 | exports.help = { 29 | name: 'movehere', 30 | category: 'Music', 31 | description: 'Moves music related messages to the channel the this command is ran in.', 32 | usage: 'movehere', 33 | }; 34 | -------------------------------------------------------------------------------- /src/commands/movesong.js: -------------------------------------------------------------------------------- 1 | const { getGuild } = require('../modules/music') 2 | exports.run = async (client, message, args) => { 3 | const queue = getGuild(message.guild.id).queue 4 | 5 | if (queue.length < 3) { 6 | return message.channel.send('<:error:466995152976871434> Not enough songs are in the queue for this command to work!') 7 | } 8 | 9 | if (!args[0]) { 10 | return client.userError(message, exports, 'Missing argument, the `current position` argument is required!') 11 | } 12 | 13 | if (!args[1]) { 14 | return client.userError(message, exports, 'Missing argument, the `new position` argument is required!') 15 | } 16 | 17 | const oldPosition = +args[0] 18 | const newPosition = +args[1] 19 | 20 | if (isNaN(oldPosition) === true) { 21 | return message.channel.send('<:error:466995152976871434> That isn\'t a number! You need to tell me the songs position in the queue (1, 2, etc.)') 22 | } 23 | 24 | if (isNaN(newPosition) === true) { 25 | return message.channel.send('<:error:466995152976871434> That isn\'t a number! You need to tell me the songs position in the queue (1, 2, etc.)') 26 | } 27 | 28 | if (oldPosition < 1 || oldPosition >= queue.length) { 29 | return message.channel.send('<:error:466995152976871434> Old position is not a valid song ID.') 30 | } 31 | 32 | if (newPosition < 1 || newPosition >= queue.length) { 33 | return message.channel.send('<:error:466995152976871434> New position is not a valid song ID.') 34 | } 35 | 36 | const songName = queue[oldPosition].video.title 37 | 38 | queue.splice(newPosition, 0, queue.splice(oldPosition, 1)[0]) 39 | 40 | message.channel.send(`<:success:466995111885144095> Moved **${songName}** from position \`${oldPosition}\` to \`${newPosition}\``) 41 | } 42 | 43 | exports.conf = { 44 | enabled: true, 45 | guildOnly: true, 46 | aliases: [], 47 | permLevel: "Moderator", 48 | requiredPerms: [] 49 | } 50 | 51 | exports.help = { 52 | name: 'movesong', 53 | category: 'Music', 54 | description: 'Moves a song to a new position in the queue.', 55 | usage: 'movesong [current position] [new position]' 56 | } -------------------------------------------------------------------------------- /src/commands/msearch.js: -------------------------------------------------------------------------------- 1 | exports.run = (client, message, args) => { 2 | if (!args[0]) 3 | return message.channel.send( 4 | `<:error:466995152976871434> No username provided. Usage: \`${client.commands.get(`msearch`).help.usage}\`` 5 | ); 6 | var mlist = ""; 7 | var count = 0; 8 | client.searchForMembers(message.guild, args[0]).forEach((member) => { 9 | if (member) { 10 | mlist += `\`${member.user.tag}\``; 11 | count = count + 1; 12 | } 13 | mlist += "**, **"; 14 | }); 15 | mlist = mlist.substring(0, mlist.length - 6); 16 | 17 | var mlist1 = `Found ${count} users:\n` + mlist; 18 | 19 | if (!mlist1) { 20 | return message.channel.send("<:error:466995152976871434> No users found!"); 21 | } 22 | 23 | message.channel.send(mlist1); 24 | }; 25 | 26 | exports.conf = { 27 | enabled: true, 28 | guildOnly: true, 29 | aliases: [], 30 | permLevel: "User", 31 | requiredPerms: [] 32 | }; 33 | 34 | exports.help = { 35 | name: "msearch", 36 | category: "Utility", 37 | description: "Search for server members.", 38 | usage: "msearch [user]" 39 | }; -------------------------------------------------------------------------------- /src/commands/mute.js: -------------------------------------------------------------------------------- 1 | exports.run = async (client, message, [args, ...reason], level) => { 2 | const settings = message.settings; 3 | 4 | if(!args) { 5 | return message.channel.send("<:error:466995152976871434> Who am I meant to mute?") 6 | } 7 | let user = message.mentions.members.first(); 8 | let users; 9 | if (!user) { 10 | users = client.searchForMembers(message.guild, args); 11 | if (users.length > 1) 12 | return message.channel.send( 13 | "<:error:466995152976871434> Found multiple users! Please be more specific or mention the user instead." 14 | ); 15 | else if (users.length == 0) 16 | return message.channel.send( 17 | "<:error:466995152976871434> That user doesn't seem to exist. Try again!" 18 | ); 19 | user = users[0]; 20 | }; 21 | 22 | if (user.user.id === message.guild.ownerID) { 23 | return message.channel.send("<:error:466995152976871434> You can't mute the owner!") 24 | }; 25 | 26 | let moderator = message.guild.member(message.author) 27 | if (message.settings.mutedRole.position >= moderator.roles.highest.position && level < 2) { 28 | return message.channel.send( 29 | "<:error:466995152976871434> The muted role is positioned above the moderator role! Please move the muted role below the moderator role." 30 | ); 31 | }; 32 | if (user.roles.highest.position >= moderator.roles.highest.position && moderator.user.id !== message.guild.ownerID) { 33 | return message.channel.send( 34 | `<:error:466995152976871434> You can't mute people who have a higher role than you!` 35 | ); 36 | }; 37 | 38 | let bot = message.guild.member(client.user) 39 | 40 | if (user.roles.highest.position >= bot.roles.highest.position) { 41 | return message.channel.send( 42 | `<:error:466995152976871434> I can't mute people who have a higher role than me!` 43 | ); 44 | } 45 | 46 | var role = message.guild.roles.cache.get(settings.mutedRole); 47 | 48 | if (!role) { 49 | return message.channel.send( 50 | "<:error:466995152976871434> There is no muted role set for this server. Please set one using `" + message.settings.prefix + "mutedrole ` before using this command." 51 | ); 52 | }; 53 | 54 | if (bot.roles.highest.position <= role.position) { 55 | return message.channel.send( 56 | "<:error:466995152976871434> The muted role is above my highest role! Please move the muted role below my highest role." 57 | ); 58 | }; 59 | 60 | message.guild.channels.cache.forEach(async (channel, id) => { 61 | await channel.updateOverwrite(role, { 62 | SEND_MESSAGES: false, 63 | ADD_REACTIONS: false 64 | }); 65 | }); 66 | 67 | if (user.roles.cache.has(role.id)) { 68 | return message.channel.send("<:error:466995152976871434> They're already muted!") 69 | } 70 | 71 | await user.roles.add(role.id); 72 | message.channel.send(`<:success:466995111885144095> Muted \`${user.user.tag}\``) 73 | 74 | var muteReason = reason.join(" "); 75 | 76 | if(muteReason.length == 0) { 77 | muteReason = "**No reason provided.**" 78 | } 79 | 80 | if (settings.modlogsChannel !== "off") { 81 | const channel = message.guild.channels.cache.find( 82 | channel => channel.name === settings.modlogsChannel 83 | ); 84 | 85 | if (channel) { 86 | let embed = new Discord.MessageEmbed(); 87 | embed.setColor("#a652bb"); 88 | embed.setAuthor("User muted!", user.user.avatarURL({format: "png", dynamic: true, size: 2048})); 89 | embed.setDescription( 90 | `• User: ${user} (${user.user.id})\n• Mod: ${message.author} (${message.author.id})\n• Reason: ${muteReason}` 91 | ); 92 | try { 93 | channel.send(embed); 94 | } catch (err) { 95 | // probably no permissions to send messages/embeds there 96 | } 97 | } 98 | } 99 | }; 100 | 101 | exports.conf = { 102 | enabled: true, 103 | guildOnly: true, 104 | aliases: [], 105 | permLevel: "Moderator", 106 | requiredPerms: ["MANAGE_ROLES", "MANAGE_CHANNELS"] 107 | }; 108 | 109 | exports.help = { 110 | name: "mute", 111 | category: "Moderation", 112 | description: "Prevents the specified user from typing.", 113 | usage: "mute [member] " 114 | }; 115 | -------------------------------------------------------------------------------- /src/commands/mutedrole.js: -------------------------------------------------------------------------------- 1 | exports.run = async (client, message, args) => { 2 | 3 | const settings = message.settings; 4 | 5 | if (!client.settings.has(message.guild.id)) { 6 | client.settings.set(message.guild.id, {}); 7 | } 8 | 9 | var mutedRole = message.guild.roles.cache.get(settings.mutedRole) 10 | 11 | if (!args[0]) { 12 | if(!mutedRole) { 13 | return message.channel.send( 14 | "<:error:466995152976871434> There is no muted role set for this server. Please set one using `" + message.settings.prefix + "mutedrole `" 15 | ) 16 | } else { 17 | message.channel.send(`The current muted role is: \`${mutedRole.name}\``) 18 | } 19 | 20 | } else { 21 | const joinedValue = args.join(" "); 22 | if (joinedValue.length < 1) { 23 | return message.channel.send( 24 | `<:error:466995152976871434> You didn't specify a role. Usage: \`${client.commands.get(`mutedrole`).help.usage}\`` 25 | ); 26 | }; 27 | 28 | if (settings.mutedRole != "None set" && joinedValue === mutedRole.name) { 29 | return message.channel.send( 30 | "<:error:466995152976871434> The muted role is already set to that!" 31 | ); 32 | }; 33 | 34 | let role = client.findRole(joinedValue, message); 35 | 36 | if (!role) { 37 | return message.channel.send(`<:error:466995152976871434> That role doesn't seem to exist. Try again!`); 38 | }; 39 | 40 | client.settings.set(message.guild.id, role.id, "mutedRole"); 41 | 42 | message.channel.send( 43 | `<:success:466995111885144095> The muted role has been set to \`${role.name}\` 44 | `); 45 | }; 46 | }; 47 | 48 | exports.conf = { 49 | enabled: true, 50 | guildOnly: true, 51 | aliases: [], 52 | permLevel: "Administrator", 53 | requiredPerms: [] 54 | }; 55 | 56 | exports.help = { 57 | name: "mutedrole", 58 | category: "Configure", 59 | description: "Sets the muted role for this server.", 60 | usage: "mutedrole [role]" 61 | }; 62 | -------------------------------------------------------------------------------- /src/commands/neko.js: -------------------------------------------------------------------------------- 1 | const fetch = require("node-fetch") 2 | exports.run = async (client, message, args) => { 3 | message.channel.startTyping(); 4 | try{ 5 | fetch(`https://purrbot.site/api/img/sfw/neko/img/`) 6 | .then(res => res.json()) 7 | .then(json => message.channel.send(json.link)) 8 | .catch(err => { 9 | message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`); 10 | }); 11 | message.channel.stopTyping(); 12 | } catch(err) { 13 | message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`); 14 | message.channel.stopTyping(); 15 | }; 16 | }; 17 | 18 | exports.conf = { 19 | enabled: false, 20 | guildOnly: false, 21 | aliases: ["catgirl"], 22 | permLevel: "User", 23 | requiredPerms: ["EMBED_LINKS"] 24 | }; 25 | 26 | exports.help = { 27 | name: "neko", 28 | category: "Image", 29 | description: "Sends you cute wholesome pictures of catgirls.", 30 | usage: "neko" 31 | }; 32 | -------------------------------------------------------------------------------- /src/commands/nekogif.js: -------------------------------------------------------------------------------- 1 | const fetch = require("node-fetch") 2 | exports.run = async (client, message, args) => { 3 | message.channel.startTyping(); 4 | try{ 5 | fetch(`https://purrbot.site/api/img/sfw/neko/gif/`) 6 | .then(res => res.json()) 7 | .then(json => message.channel.send(json.link)) 8 | .catch(err => { 9 | message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`); 10 | }); 11 | message.channel.stopTyping(); 12 | } catch(err) { 13 | message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`); 14 | message.channel.stopTyping(); 15 | }; 16 | }; 17 | 18 | exports.conf = { 19 | enabled: false, 20 | guildOnly: false, 21 | aliases: ["catgirlgif"], 22 | permLevel: "User", 23 | requiredPerms: ["EMBED_LINKS"] 24 | }; 25 | 26 | exports.help = { 27 | name: "nekogif", 28 | category: "Image", 29 | description: "Sends you gifs of catgirls.", 30 | usage: "nekogif" 31 | }; 32 | -------------------------------------------------------------------------------- /src/commands/nowplaying.js: -------------------------------------------------------------------------------- 1 | const { getGuild, createTimestamp } = require('../modules/music') 2 | const { MessageEmbed } = require('discord.js') 3 | exports.run = async (client, message) => { 4 | const guild = getGuild(message.guild.id) 5 | 6 | if (guild.queue.length < 1) { 7 | return message.channel.send(client.config.emojis.error + ' Nothing is in the queue!') 8 | } 9 | 10 | const s = guild.queue[0] 11 | const elapsedTime = createTimestamp(guild.dispatcher.streamTime / 1000) 12 | let timestamp = `\`[${createTimestamp(s.video.lengthSeconds)}]\`` 13 | 14 | if (timestamp !== '`[LIVE]`') { 15 | timestamp = `\`[${elapsedTime + '/' + createTimestamp(s.video.lengthSeconds)}]\`` 16 | } 17 | 18 | const embed = new MessageEmbed() 19 | embed.setTitle('Now playing') 20 | embed.setThumbnail('https://invidiou.site' + s.video.videoThumbnails[1].url) 21 | embed.setColor(client.embedColour(message)) 22 | embed.setDescription(`**[${s.video.title}](https://www.youtube.com/watch?v=${s.video.videoId})**`) 23 | embed.addField('Channel:', s.video.author, true) 24 | embed.addField('Time:', timestamp, true) 25 | embed.setFooter('Requested by ' + s.requestedBy.tag, s.requestedBy.avatarURL({ format: 'png', dynamic: true, size: 2048 })) 26 | 27 | message.channel.send(embed) 28 | }; 29 | 30 | exports.conf = { 31 | enabled: true, 32 | guildOnly: true, 33 | aliases: ["np"], 34 | permLevel: "User", 35 | requiredPerms: ["EMBED_LINKS"] 36 | }; 37 | 38 | exports.help = { 39 | name: "nowplaying", 40 | category: "Music", 41 | description: "Shows details about the currently playing song.", 42 | usage: "nowplaying" 43 | }; 44 | -------------------------------------------------------------------------------- /src/commands/owoify.js: -------------------------------------------------------------------------------- 1 | // totally not stolen from https://github.com/GmdDjca/Hitomi-Manaka 2 | exports.run = (client, message, args) => { 3 | if (!args[0]) { 4 | return message.channel.send(`<:error:466995152976871434> pwease incwude some text fow me to owoify UwU`) 5 | } 6 | const faces = ['(・`ω´・)', 'x3', 'owo', 'UwU', '>w<', '^w^'] 7 | owoified = `${args.join(' ')}`.replace(/(?:r|l)/g, 'w') 8 | owoified = owoified.replace(/(?:R|L)/g, 'W') 9 | owoified = owoified.replace(/n([aeiou])/g, 'ny$1') 10 | owoified = owoified.replace(/N([aeiou])/g, 'Ny$1') 11 | owoified = owoified.replace(/N([AEIOU])/g, 'Ny$1') 12 | owoified = owoified.replace(/ove/g, 'uv') 13 | owoified = owoified.replace(/!+/g, ' ' + faces[~~(Math.random() * faces.length)] + ' ') 14 | 15 | if(owoified.length > 2000) { 16 | owoified = owoified.slice(0, -Math.abs(owoified.length - 2000)) 17 | }; 18 | 19 | message.channel.send(owoified) 20 | }; 21 | 22 | exports.conf = { 23 | enabled: true, 24 | guildOnly: false, 25 | aliases: [], 26 | permLevel: "User", 27 | requiredPerms: [] 28 | }; 29 | 30 | exports.help = { 31 | name: "owoify", 32 | category: "Fun", 33 | description: "Makes nyowmal tewxt owo'ed x3", 34 | usage: "owoify [message]" 35 | }; 36 | -------------------------------------------------------------------------------- /src/commands/pat.js: -------------------------------------------------------------------------------- 1 | const API = require('nekos.life'); 2 | const {sfw} = new API(); 3 | exports.run = async (client, message, args) => { 4 | if(!args[0]) { 5 | return message.channel.send(`<:error:466995152976871434> You didn't say who you wanted to pat! Usage: \`${client.commands.get(`pat`).help.usage}\``) 6 | }; 7 | 8 | var people = ""; 9 | 10 | for (var i = 0; i < args.length; i++) { 11 | var user = client.getUserFromMention(args[i]) 12 | if (user) { 13 | user = message.guild.members.cache.get(user.id).displayName; 14 | } else { 15 | users = client.searchForMembers(message.guild, args[i]); 16 | if (users.length > 1) 17 | return message.channel.send( 18 | "<:error:466995152976871434> Found multiple users for `" + args[i] + "`, Please be more specific or mention the user instead." 19 | ); 20 | else if (users.length == 0) 21 | return message.channel.send( 22 | "<:error:466995152976871434> That user doesn't seem to exist. Try again!" 23 | ); 24 | user = users[0].displayName; 25 | }; 26 | if(i+1 == args.length && args.length > 1) { 27 | people += `**and** ${user}!` 28 | } else if(args.length < 2) { 29 | people += `${user}!`; 30 | } else if(args.length == 2 && i == 0) { 31 | people += `${user} `; 32 | } else { 33 | people += `${user}, `; 34 | }; 35 | }; 36 | 37 | 38 | 39 | message.channel.startTyping(); 40 | try { 41 | sfw.pat().then((json) => { 42 | embed = new Discord.MessageEmbed(); 43 | embed.setImage(json.url) 44 | embed.setColor(client.embedColour(message)); 45 | embed.setDescription(`**${message.guild.members.cache.get(message.author.id).displayName}** patted **${people}**`) 46 | message.channel.send(embed) 47 | message.channel.stopTyping(); 48 | }); 49 | } catch (err) { 50 | client.logger.error("pat.js: " + err); 51 | message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`) 52 | message.channel.stopTyping(); 53 | }; 54 | }; 55 | 56 | exports.conf = { 57 | enabled: true, 58 | guildOnly: true, 59 | aliases: ["headpat"], 60 | permLevel: "User", 61 | requiredPerms: ["EMBED_LINKS"] 62 | }; 63 | 64 | exports.help = { 65 | name: "pat", 66 | category: "Action", 67 | description: "pat someone!", 68 | usage: "pat [@user/user] (you can pat as many people as you want!)" 69 | }; 70 | -------------------------------------------------------------------------------- /src/commands/pause.js: -------------------------------------------------------------------------------- 1 | const { getGuild } = require('../modules/music') 2 | exports.run = (client, message, args, level) => { 3 | const guild = getGuild(message.guild.id) 4 | 5 | if (guild.paused === true) { 6 | return message.channel.send('<:error:466995152976871434> The music has already been paused! Run resume to start the music again.') 7 | } 8 | 9 | if (guild.queue.length < 1 || guild.playing === false) { 10 | return message.channel.send('<:error:466995152976871434> Nothing is playing!') 11 | } 12 | 13 | guild.playing = false 14 | guild.paused = true 15 | guild.dispatcher.pause() 16 | 17 | message.channel.send('<:pause:467639357961142273> Music playback has been paused.') 18 | }; 19 | 20 | exports.conf = { 21 | enabled: true, 22 | guildOnly: true, 23 | aliases: [], 24 | permLevel: "Moderator", 25 | requiredPerms: [] 26 | }; 27 | 28 | exports.help = { 29 | name: "pause", 30 | category: "Music", 31 | description: "Pauses music playback.", 32 | usage: "pause" 33 | }; 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/commands/permlevel.js: -------------------------------------------------------------------------------- 1 | exports.run = async (client, message, args, level) => { 2 | const friendly = client.config.permLevels.find(l => l.level === level).name; 3 | message.reply(`Your permission level is: ${level} - ${friendly}`); 4 | }; 5 | 6 | exports.conf = { 7 | enabled: true, 8 | guildOnly: false, 9 | aliases: ["plevel"], 10 | permLevel: "User", 11 | requiredPerms: [] 12 | }; 13 | 14 | exports.help = { 15 | name: "permlevel", 16 | category: "Utility", 17 | description: "Tells you your permission level for that server.", 18 | usage: "permlevel" 19 | }; 20 | -------------------------------------------------------------------------------- /src/commands/ping.js: -------------------------------------------------------------------------------- 1 | exports.run = async (client, message) => { 2 | const msg = await message.channel.send("⏱️ Please wait..."); 3 | msg.edit( 4 | `:ping_pong: Pong! Latency is ${msg.createdTimestamp - message.createdTimestamp}ms, API Latency is ${Math.round(client.ws.ping)}ms` 5 | ); 6 | }; 7 | 8 | exports.conf = { 9 | enabled: true, 10 | guildOnly: false, 11 | aliases: [], 12 | permLevel: "User", 13 | requiredPerms: [] 14 | }; 15 | 16 | exports.help = { 17 | name: "ping", 18 | category: "Utility", 19 | description: "Displays bot latency in miliseconds.", 20 | usage: "ping" 21 | }; 22 | -------------------------------------------------------------------------------- /src/commands/play.js: -------------------------------------------------------------------------------- 1 | const { play } = require('../modules/music') 2 | const Discord = require("discord.js") 3 | 4 | module.exports.run = async (client, message, args, level) =>{ 5 | if (!args[0]) { 6 | return message.channel.send(`<:error:466995152976871434> You didn't give me a song name or YouTube URL! Usage: \`${client.commands.get('play').help.usage}\``) 7 | } 8 | 9 | await play(client, message, args.join(' '), false) 10 | } 11 | 12 | exports.conf = { 13 | enabled: true, 14 | guildOnly: true, 15 | aliases: ["p"], 16 | permLevel: "User", 17 | requiredPerms: ["CONNECT", "SPEAK"] 18 | }; 19 | 20 | exports.help = { 21 | name: "play", 22 | category: "Music", 23 | description: 'Plays the song you request, or adds it to the queue.', 24 | usage: 'playnext [song]', 25 | }; 26 | -------------------------------------------------------------------------------- /src/commands/playnext.js: -------------------------------------------------------------------------------- 1 | const { play } = require('../modules/music') 2 | exports.run = async (client, message, args) => { 3 | if (!args[0]) { 4 | return message.channel.send(`<:error:466995152976871434> You didn't give me a song name or YouTube URL! Usage: \`${client.commands.get('play').help.usage}\``) 5 | } 6 | 7 | await play(client, message, args.join(' '), true) 8 | } 9 | 10 | exports.conf = { 11 | enabled: true, 12 | guildOnly: true, 13 | aliases: [], 14 | permLevel: "Moderator", 15 | requiredPerms: [] 16 | } 17 | 18 | exports.help = { 19 | name: 'playnext', 20 | category: 'Music', 21 | description: 'Similar to play, but adds it to the start of the queue instead of the end.', 22 | usage: 'playnext [song]' 23 | } -------------------------------------------------------------------------------- /src/commands/poke.js: -------------------------------------------------------------------------------- 1 | const API = require('nekos.life'); 2 | const {sfw} = new API(); 3 | exports.run = async (client, message, args) => { 4 | if(!args[0]) { 5 | return message.channel.send(`<:error:466995152976871434> You didn't say who you wanted to poke! Usage: \`${client.commands.get(`poke`).help.usage}\``) 6 | }; 7 | 8 | var people = ""; 9 | 10 | for (var i = 0; i < args.length; i++) { 11 | var user = client.getUserFromMention(args[i]) 12 | if (user) { 13 | user = message.guild.members.cache.get(user.id).displayName; 14 | } else { 15 | users = client.searchForMembers(message.guild, args[i]); 16 | if (users.length > 1) 17 | return message.channel.send( 18 | "<:error:466995152976871434> Found multiple users for `" + args[i] + "`, Please be more specific or mention the user instead." 19 | ); 20 | else if (users.length == 0) 21 | return message.channel.send( 22 | "<:error:466995152976871434> That user doesn't seem to exist. Try again!" 23 | ); 24 | user = users[0].displayName; 25 | }; 26 | if(i+1 == args.length && args.length > 1) { 27 | people += `**and** ${user}!` 28 | } else if(args.length < 2) { 29 | people += `${user}!`; 30 | } else if(args.length == 2 && i == 0) { 31 | people += `${user} `; 32 | } else { 33 | people += `${user}, `; 34 | }; 35 | }; 36 | 37 | 38 | 39 | message.channel.startTyping(); 40 | try { 41 | sfw.poke().then((json) => { 42 | embed = new Discord.MessageEmbed(); 43 | embed.setImage(json.url) 44 | embed.setColor(client.embedColour(message)); 45 | embed.setDescription(`**${message.guild.members.cache.get(message.author.id).displayName}** poked **${people}**`) 46 | message.channel.send(embed) 47 | message.channel.stopTyping(); 48 | }); 49 | } catch (err) { 50 | client.logger.error("poke.js: " + err); 51 | message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`) 52 | message.channel.stopTyping(); 53 | }; 54 | }; 55 | 56 | exports.conf = { 57 | enabled: true, 58 | guildOnly: true, 59 | aliases: [], 60 | permLevel: "User", 61 | requiredPerms: ["EMBED_LINKS"] 62 | }; 63 | 64 | exports.help = { 65 | name: "poke", 66 | category: "Action", 67 | description: "poke someone!", 68 | usage: "poke [@user/user] (you can poke as many people as you want!)" 69 | }; 70 | -------------------------------------------------------------------------------- /src/commands/prefix.js: -------------------------------------------------------------------------------- 1 | exports.run = async (client, message, args) => { 2 | const settings = message.settings; 3 | 4 | if (!client.settings.has(message.guild.id)) client.settings.set(message.guild.id, {}); 5 | 6 | if (args[0]) { 7 | const joinedValue = args.join(" "); 8 | if (joinedValue === settings.prefix) return message.channel.send("<:error:466995152976871434> The prefix is already set to that!"); 9 | if (!client.settings.has(message.guild.id)) client.settings.set(message.guild.id, {}); 10 | client.settings.set(message.guild.id, joinedValue, "prefix"); 11 | message.channel.send(`<:success:466995111885144095> Set the prefix to \`${joinedValue}\``); 12 | } else { 13 | message.channel.send(`The current prefix is: \`${settings.prefix}\``) 14 | } 15 | } 16 | 17 | exports.conf = { 18 | enabled: true, 19 | guildOnly: true, 20 | aliases: [], 21 | permLevel: "Administrator", 22 | requiredPerms: [] 23 | }; 24 | 25 | exports.help = { 26 | name: "prefix", 27 | category: "Configure", 28 | description: "Sets the prefix for this server.", 29 | usage: "prefix [prefix]" 30 | }; 31 | -------------------------------------------------------------------------------- /src/commands/pride.js: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Emily J. / mudkipscience and contributors. Subject to the AGPLv3 license. 2 | 3 | exports.conf = { 4 | enabled: true, 5 | guildOnly: false, 6 | aliases: [], 7 | permLevel: 'User', 8 | requiredPerms: ['ATTACH_FILES'], 9 | } 10 | 11 | exports.help = { 12 | name: 'pride', 13 | category: 'Fun', 14 | description: 'Adds a pride flag ring to your avatar. Available flags are lesbian, gay, bisexual, pansexual, trans, asexual, aromantic and ally.', 15 | usage: '`pride [flag]` - Adds a pride flag overlay to your avatar.\n`pride -g [flag]` - Adds a pride flag gradient on your avatar.', 16 | } 17 | 18 | const url = 'https://demirramon.com/gen/pride.png' 19 | const Discord = require('discord.js') 20 | exports.run = (client, message, args) => { 21 | const flag = args[0] 22 | if (!flag) { 23 | return message.channel.send('<:error:466995152976871434> Missing argument, the `flag` argument is required!') 24 | } 25 | 26 | const available = ['lesbian', 'gay', 'bisexual', 'pansexual', 'trans', 'asexual', 'aromantic', 'ally'] 27 | 28 | if (!available.includes(flag.toLowerCase())) { 29 | return message.channel.send(`<:error:466995152976871434> This flag isn't available, sorry ;~;\nAvailable flags: \`${available.join('`, `')}\``) 30 | } 31 | 32 | let gradient = 'false' 33 | if (message.flags.includes('g')) { 34 | gradient = 'true' 35 | } 36 | 37 | message.channel.startTyping() 38 | 39 | const params = `image=${message.author.avatarURL({ format: 'png', size: 2048 })}&flag=${flag.toLowerCase()}&full=true&gradient=${gradient}&background=false&fit=true&v=2019-08-07` 40 | 41 | try { 42 | message.channel.stopTyping() 43 | message.channel.send({ files: [new Discord.MessageAttachment(url + '?' + params)] }) 44 | } catch (err) { 45 | message.channel.stopTyping() 46 | message.channel.send(`<:error:466995152976871434> Error when generating image: \`${err}\``) 47 | } 48 | } -------------------------------------------------------------------------------- /src/commands/pronoun.js: -------------------------------------------------------------------------------- 1 | const pronouns = require ("../../resources/other/pronouns.json"); 2 | exports.run = async (client, message, args) => { 3 | var output = ""; 4 | if(!args[0]) { 5 | for (var key of Object.keys(pronouns)) { 6 | output += `${key}, ` 7 | }; 8 | return message.channel.send(`__**Pronouns:**__\n${output.slice(0, -2)}`); 9 | } else { 10 | if(args.join(" ").toLowerCase() == "attack helicopter" || args.join(" ").toLowerCase() == "apache attack helicopter" || args.join(" ").toLowerCase() == "apache") { 11 | return message.channel.send({ 12 | files: [new Discord.MessageAttachment("./resources/images/attackhelicopter.jpg")] 13 | }); 14 | }; 15 | output = pronouns[args.join(" ").toLowerCase()]; 16 | if(!output) { 17 | return message.channel.send("<:error:466995152976871434> No results for that query."); 18 | }; 19 | return message.channel.send(`__**Example sentences using ${output.name}:**__\n${output.examples}`); 20 | }; 21 | }; 22 | 23 | exports.conf = { 24 | enabled: true, 25 | guildOnly: false, 26 | aliases: ["pronouns"], 27 | permLevel: "User", 28 | requiredPerms: [] 29 | }; 30 | 31 | exports.help = { 32 | name: "pronoun", 33 | category: "Fun", 34 | description: "Gives you information on how to use the specified pronoun.", 35 | usage: "pronoun [pronoun]" 36 | }; 37 | -------------------------------------------------------------------------------- /src/commands/purge.js: -------------------------------------------------------------------------------- 1 | exports.run = async (client, message, args, level) => { 2 | const settings = message.settings; 3 | 4 | if(message.channel.name === settings.chatlogsChannel) { 5 | return message.channel.send("<:error:466995152976871434> Can't purge logs.") 6 | } 7 | 8 | if(message.channel.name === settings.modlogsChannel) { 9 | return message.channel.send("<:error:466995152976871434> Can't purge logs.") 10 | } 11 | const amount = !!parseInt(message.content.split(' ')[1]) ? parseInt(message.content.split(' ')[1]) : parseInt(message.content.split(' ')[2]) 12 | if(amount > 100) { 13 | return message.channel.send("<:error:466995152976871434> Can only purge a maximum of 100 messages!") 14 | } 15 | 16 | if (!amount) return message.channel.send( 17 | '<:error:466995152976871434> You didn\'t tell me how many messages to purge. Usage: \`' + client.commands.get(`purge`).help.usage + "`" 18 | ); 19 | 20 | await message.delete().catch(O_o => {}); 21 | 22 | message.channel.messages.fetch({ 23 | limit: amount, 24 | }).then((messages) => { 25 | message.channel.bulkDelete(messages, true).catch(console.error); 26 | message.channel.send(`<:success:466995111885144095> Purged ${amount} messages!`).then(m => m.delete({timeout: 5000})); 27 | }); 28 | 29 | if (settings.modlogsChannel !== "off") { 30 | const channel = message.guild.channels.cache.find( 31 | channel => channel.name === settings.modlogsChannel 32 | ); 33 | 34 | if (channel) { 35 | let embed = new Discord.MessageEmbed(); 36 | embed.setColor("#a62019"); 37 | embed.setAuthor(`${amount} messages purged!`, message.author.avatarURL({format: "png", dynamic: true, size: 2048})); 38 | embed.setDescription(`• Channel: ${message.channel.name} (${message.channel.id})\n• Mod: ${message.author} (${message.author.id})\n• Amount: \`${amount}\``) 39 | try { 40 | channel.send({ embed }); 41 | } catch (err) { 42 | }; 43 | }; 44 | }; 45 | }; 46 | 47 | exports.conf = { 48 | enabled: true, 49 | guildOnly: true, 50 | aliases: [], 51 | permLevel: "Moderator", 52 | requiredPerms: ["MANAGE_MESSAGES"] 53 | }; 54 | 55 | exports.help = { 56 | name: "purge", 57 | category: "Moderation", 58 | description: "Bulk deletes messages. **cannot delete messages older than 14 days.**", 59 | usage: "purge [amount]" 60 | }; 61 | -------------------------------------------------------------------------------- /src/commands/raidmode.js: -------------------------------------------------------------------------------- 1 | const Discord = require("discord.js") 2 | exports.run = async (client, message, args, level) => { 3 | 4 | const settings = message.settings; 5 | const defaults = client.config.defaultSettings; 6 | const overrides = client.settings.get(message.guild.id); 7 | if (!client.settings.has(message.guild.id)) client.settings.set(message.guild.id, {}); 8 | 9 | var raidToggle; 10 | var embColour; 11 | var mutedRole = message.guild.roles.cache.get(settings.mutedRole) 12 | 13 | if(!mutedRole) { 14 | return message.channel.send( 15 | "<:error:466995152976871434> This command requires a muted role to be set! Please ask an admin or the owner to set this with `" + message.settings.prefix + "mutedrole `" 16 | ) 17 | } 18 | if(args[0] == "strict") { 19 | client.settings.set(message.guild.id, "on", "raidModeStrict"); 20 | client.settings.set(message.guild.id, "on", "raidMode"); 21 | message.channel.send(`<:success:466995111885144095> Strict raid mode enabled! New users will now be automatically kicked.`); 22 | raidToggle = "Strict raid mode activated!" 23 | embColour = "#777B7E" 24 | } else { 25 | if (settings.raidMode === "off") { 26 | client.settings.set(message.guild.id, "on", "raidMode") 27 | message.channel.send(`<:success:466995111885144095> Raid mode enabled! New users will now be automatically muted.`); 28 | raidToggle = "Raid mode activated!" 29 | embColour = "#777B7E" 30 | } else { 31 | client.settings.set(message.guild.id, "off", "raidMode") 32 | client.settings.set(message.guild.id, "off", "raidModeStrict"); 33 | message.channel.send(`<:success:466995111885144095> Raid mode disabled.`); 34 | raidToggle = "Raid mode deactivated!" 35 | embColour = "#48494b" 36 | }; 37 | }; 38 | if (settings.modlogsChannel !== "off") { 39 | const channel = message.guild.channels.cache.find( 40 | channel => channel.name === settings.modlogsChannel 41 | ); 42 | 43 | if (channel) { 44 | let embed = new Discord.MessageEmbed(); 45 | embed.setColor(embColour); 46 | embed.setAuthor(raidToggle, message.author.avatarURL({format: "png", dynamic: true, size: 2048})); 47 | embed.setDescription(`• Mod: ${message.author} (${message.author.id})`) 48 | try { 49 | channel.send({ embed }); 50 | } catch (err) { 51 | // probably no permissions to send messages/embeds there 52 | } 53 | } 54 | } 55 | }; 56 | 57 | exports.conf = { 58 | enabled: true, 59 | guildOnly: true, 60 | aliases: [], 61 | permLevel: "Administrator", 62 | requiredPerms: ["MANAGE_ROLES", "KICK_MEMBERS"] 63 | }; 64 | 65 | exports.help = { 66 | name: "raidmode", 67 | category: "Moderation", 68 | description: "Enables/disables raid mode in your server, which automatically mutes new members. Strict raidmode automatically kicks new members.", 69 | usage: "raidmode **OR** raidmode strict" 70 | }; 71 | -------------------------------------------------------------------------------- /src/commands/randurban.js: -------------------------------------------------------------------------------- 1 | const urban = require("urban"); 2 | exports.run = (client, message) => { 3 | urban.random().first(json => { 4 | if(message.channel.nsfw === false) return message.channel.send( 5 | "<:error:466995152976871434> This command can only be executed in channels marked as NSFW!" 6 | ); 7 | if(json.definition.length > 2000) return message.channel.send( 8 | `<:error:466995152976871434> Definition cannot exceed 2000 characters! Use this link instead: ${json.permalink}` 9 | ); 10 | if(json.example.length > 2000) return message.channel.send( 11 | "<:error:466995152976871434> Example cannot exceed 2000 characters!" 12 | ); 13 | 14 | embed = new Discord.MessageEmbed() 15 | .setTitle(json.word) 16 | .setURL(json.permalink) 17 | .setColor("#EFFF00") 18 | .setDescription(json.definition || "None") 19 | .addField("Example", json.example || "None") 20 | .addField("Upvotes", json.thumbs_up, true) 21 | .addField("Downvotes", json.thumbs_down, true) 22 | .setFooter(`Submitted by ${json.author}`) 23 | message.channel.send(embed); 24 | 25 | }); 26 | } 27 | 28 | exports.conf = { 29 | enabled: true, 30 | guildOnly: false, 31 | aliases: ["rurban"], 32 | permLevel: "User", 33 | requiredPerms: [] 34 | }; 35 | 36 | exports.help = { 37 | name: "randurban", 38 | category: "Fun", 39 | description: "Grabs a random definition from the Urban Dictonary.", 40 | usage: "randurban" 41 | }; 42 | -------------------------------------------------------------------------------- /src/commands/rate.js: -------------------------------------------------------------------------------- 1 | exports.run = async (client, message, args) => { 2 | if (!args[0]) 3 | return message.channel.send( 4 | `<:error:466995152976871434> What am I meant to rate? Usage: \`${client.commands.get(`rate`).help.usage}\`` 5 | ); 6 | 7 | var rating = [ 8 | "0/10", 9 | "1/10", 10 | "2/10", 11 | "3/10", 12 | "4/10", 13 | "5/10", 14 | "6/10", 15 | "7/10", 16 | "8/10", 17 | "9/10", 18 | "10/10" 19 | ]; 20 | 21 | if (message.content.includes("@everyone") || message.content.includes("@here") || message.content.includes("<@&")) { 22 | return message.channel.send('>:('); 23 | }; 24 | 25 | let mess = rating.random(); 26 | message.channel.send(`<:star:618393201501536258> I give ${args.join(" ")} a **${mess}**`); 27 | }; 28 | 29 | exports.conf = { 30 | enabled: true, 31 | guildOnly: false, 32 | aliases: [], 33 | permLevel: "User", 34 | requiredPerms: [] 35 | }; 36 | 37 | exports.help = { 38 | name: "rate", 39 | category: "Fun", 40 | description: "Gives something a rating from 0-10", 41 | usage: "rate [thing]" 42 | }; -------------------------------------------------------------------------------- /src/commands/reload.js: -------------------------------------------------------------------------------- 1 | exports.run = async (client, message, args) => {// eslint-disable-line no-unused-vars 2 | if (!args || args.length < 1) return message.channel.send( 3 | `<:error:466995152976871434> You must provide a command to reload! Usage: \`${client.commands.get(`reload`).help.usage}\`` 4 | ); 5 | 6 | let response = await client.unloadCommand(args[0]); 7 | if (response) return message.channel.send(`<:error:466995152976871434> Error unloading: ${response}`); 8 | 9 | response = client.loadCommand(args[0]); 10 | if (response) return message.channel.send(`<:error:466995152976871434> Error loading: ${response}`); 11 | 12 | message.channel.send(`<:success:466995111885144095> \`${args[0]}\` has been reloaded!`); 13 | }; 14 | 15 | exports.conf = { 16 | enabled: true, 17 | guildOnly: false, 18 | aliases: [], 19 | permLevel: "Developer", 20 | requiredPerms: [] 21 | }; 22 | 23 | exports.help = { 24 | name: "reload", 25 | category: "Owner", 26 | description: "Reloads the specified command.", 27 | usage: "reload [command]" 28 | }; 29 | -------------------------------------------------------------------------------- /src/commands/removesong.js: -------------------------------------------------------------------------------- 1 | const { getGuild } = require('../modules/music') 2 | module.exports.run = (client, message, args, level) =>{ 3 | var queue = getGuild(message.guild.id).queue 4 | 5 | if (queue.length < 2) { 6 | return message.channel.send('<:error:466995152976871434> Not enough songs are in the queue for this command to work!') 7 | } 8 | 9 | if (!args[0]) { 10 | return message.channel.send(`<:error:466995152976871434> You didn't tell me what song to remove! Usage: \`${client.commands.get('removesong').help.usage}\``) 11 | } 12 | 13 | var input = +args[0] 14 | 15 | if (isNaN(input) === true) { 16 | return message.channel.send('<:error:466995152976871434> That isn\'t a number! You need to tell me the songs position in the queue (1, 2, etc.)') 17 | } 18 | 19 | if (input >= queue.length || input < 1) { 20 | return message.channel.send('<:error:466995152976871434> Input is not a valid song ID.') 21 | } 22 | 23 | var songName = queue[input].video.title 24 | 25 | queue.splice(input, 1) 26 | 27 | message.channel.send(`<:success:466995111885144095> Removed from queue: **${songName}**`) 28 | }; 29 | 30 | exports.conf = { 31 | enabled: true, 32 | guildOnly: true, 33 | aliases: ["rmsong"], 34 | permLevel: "Moderator", 35 | requiredPerms: [] 36 | }; 37 | 38 | exports.help = { 39 | name: "removesong", 40 | category: "Music", 41 | description: "Removes the specified song from the queue.", 42 | usage: "removesong [position]" 43 | }; 44 | -------------------------------------------------------------------------------- /src/commands/reset.js: -------------------------------------------------------------------------------- 1 | const Discord = require("discord.js") 2 | exports.run = async (client, message) => { 3 | 4 | if (!client.settings.has(message.guild.id)) client.settings.set(message.guild.id, {}); 5 | 6 | const response = await client.awaitReply(message, 7 | "<:reboot:467216876938985482> This will clear the guild config and restore me to my default settings. Are you sure you want to do this?" 8 | ); 9 | if (["y", "yes"].includes(response.toLowerCase())) { 10 | client.settings.set(message.guild.id, {}); 11 | message.channel.send("<:success:466995111885144095> All settings have been restored to their default values.") 12 | } else { 13 | message.channel.send("<:success:466995111885144095> Action cancelled.") 14 | } 15 | }; 16 | 17 | exports.conf = { 18 | enabled: true, 19 | guildOnly: true, 20 | aliases: [], 21 | permLevel: "Administrator", 22 | requiredPerms: [] 23 | }; 24 | 25 | exports.help = { 26 | name: "reset", 27 | category: "Configure", 28 | description: "Resets all settings to their default values.", 29 | usage: "reset" 30 | }; -------------------------------------------------------------------------------- /src/commands/restart.js: -------------------------------------------------------------------------------- 1 | const fetch = require('node-fetch'); 2 | 3 | exports.run = (client, message) => {// eslint-disable-line no-unused-vars 4 | 5 | // This actually shuts down the bot, you'll need to use something like pm2 to get it to restart 6 | 7 | message.channel.send("<:reboot:467216876938985482> Restarting..."); 8 | 9 | client.destroy(); 10 | require("util").promisify(setTimeout); 11 | 12 | fetch('https://gamecp.apex.to/api/client/servers/1fc76afa-9a4d-497b-983a-a898795ab5b5/power', { 13 | method: 'post', 14 | body: JSON.stringify({ 'signal': 'restart' }), 15 | headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${client.config.server}` } 16 | }).catch(err => { 17 | message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`); 18 | }); 19 | }; 20 | 21 | exports.conf = { 22 | enabled: true, 23 | guildOnly: false, 24 | aliases: [], 25 | permLevel: "Developer", 26 | requiredPerms: [] 27 | }; 28 | 29 | exports.help = { 30 | name: "restart", 31 | category: "Owner", 32 | description: "Restarts the bot.", 33 | usage: "restart" 34 | }; 35 | -------------------------------------------------------------------------------- /src/commands/resume.js: -------------------------------------------------------------------------------- 1 | const { getGuild } = require('../modules/music') 2 | exports.run = (client, message, args, level) => { 3 | const guild = getGuild(message.guild.id) 4 | 5 | if (guild.paused === false) { 6 | return message.channel.send('<:error:466995152976871434> The music is already playing, use pause to pause the music first!') 7 | } 8 | 9 | if (guild.queue.length < 1) { 10 | return message.channel.send('<:error:466995152976871434> Nothing is playing!') 11 | } 12 | 13 | guild.playing = true 14 | guild.paused = false 15 | guild.dispatcher.resume() 16 | 17 | message.channel.send('<:success:466995111885144095> Music playback has been resumed.') 18 | }; 19 | 20 | exports.conf = { 21 | enabled: true, 22 | guildOnly: true, 23 | aliases: ["unpause"], 24 | permLevel: "Moderator", 25 | requiredPerms: ["SPEAK"] 26 | }; 27 | 28 | exports.help = { 29 | name: "resume", 30 | category: "Music", 31 | description: "Unpauses music.", 32 | usage: "resume" 33 | }; -------------------------------------------------------------------------------- /src/commands/rip.js: -------------------------------------------------------------------------------- 1 | const fetch = require('node-fetch'); 2 | const Discord = require("discord.js") 3 | exports.run = (client, message) => { 4 | message.channel.startTyping(); 5 | try{ 6 | fetch('http://mityurl.com/y/yKsQ/r', { redirect: 'follow' }) 7 | .then(res => res) 8 | .then(res => message.channel.send(`>:] ${res.url}`)) 9 | .catch(err => { 10 | message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`); 11 | }); 12 | } catch(err) { 13 | message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`); 14 | }; 15 | message.channel.stopTyping(); 16 | } 17 | 18 | exports.conf = { 19 | enabled: true, 20 | guildOnly: false, 21 | aliases: [], 22 | permLevel: "User", 23 | requiredPerms: [] 24 | }; 25 | 26 | exports.help = { 27 | name: "rip", 28 | category: "Fun", 29 | description: "nice >:]", 30 | usage: "`rip`" 31 | }; -------------------------------------------------------------------------------- /src/commands/rolecolour.js: -------------------------------------------------------------------------------- 1 | exports.run = async (client, message, [colour, ...givenRole], query) => { 2 | let role = givenRole.join(" "); 3 | 4 | let gRole = client.findRole(role, message); 5 | 6 | if (!gRole) { 7 | return message.channel.send(`<:error:466995152976871434> That role doesn't seem to exist. Try again!`); 8 | }; 9 | 10 | if(!colour.startsWith('#')) { 11 | colour = `#`+colour; 12 | } 13 | if(colour.length > 7) return message.channel.send( 14 | `<:error:466995152976871434> Colour has to be a hex code. Usage: \`${client.commands.get(`rolecolour`).help.usage}\`` 15 | ); 16 | if(colour.length < 7) return message.channel.send( 17 | `<:error:466995152976871434> Colour has to be a hex code. Usage: \`${client.commands.get(`rolecolour`).help.usage}\`` 18 | ); 19 | 20 | let moderator = message.guild.member(message.author) 21 | if (gRole.position >= moderator.roles.highest.position) { 22 | return message.channel.send( 23 | "<:error:466995152976871434> You cannot modify roles higher than your own!" 24 | ); 25 | } 26 | 27 | var bot = message.guild.members.cache.get(client.user.id) 28 | if (gRole.position >= bot.roles.highest.position) { 29 | return message.channel.send( 30 | `<:error:466995152976871434> I cannot modify roles higher than my own!` 31 | ); 32 | } 33 | 34 | await gRole.edit({color: colour}) 35 | message.channel.send( 36 | `<:success:466995111885144095> The colour of the role \`${gRole.name}\` has been set to \`${colour}\``); 37 | }; 38 | 39 | exports.conf = { 40 | enabled: true, 41 | guildOnly: true, 42 | aliases: ["rolecolor"], 43 | permLevel: "Moderator", 44 | requiredPerms: ["MANAGE_ROLES"] 45 | }; 46 | 47 | exports.help = { 48 | name: "rolecolour", 49 | category: "Utility", 50 | description: "Sets the colour of a role to the specified hex.", 51 | usage: "rolecolour [hex] [role]" 52 | }; 53 | -------------------------------------------------------------------------------- /src/commands/roleinfo.js: -------------------------------------------------------------------------------- 1 | const Discord = require("discord.js"); 2 | exports.run = async (client, message, args, level) => { 3 | if (!args[0]) 4 | return message.channel.send( 5 | `<:error:466995152976871434> You didn't provide me with a role name or ID! Usage: \`${client.commands.get(`roleinfo`).help.usage}\`` 6 | ); 7 | 8 | let role = client.findRole(args.join(" "), message); 9 | 10 | if (!role) { 11 | return message.channel.send(`<:error:466995152976871434> That role doesn't seem to exist. Try again!`); 12 | }; 13 | 14 | if(!role) { 15 | return message.channel.send(`<:error:466995152976871434> Role not found.`) 16 | } 17 | 18 | var permissions = "```"; 19 | if(role.permissions.has("ADMINISTRATOR")) permissions += "ADMINISTRATOR, "; 20 | if(role.permissions.has("CREATE_INSTANT_INVITE")) permissions += "CREATE_INSTANT_INVITE, "; 21 | if(role.permissions.has("KICK_MEMBERS")) permissions += "KICK_MEMBERS, "; 22 | if(role.permissions.has("BAN_MEMBERS")) permissions += "BAN_MEMBERS, "; 23 | if(role.permissions.has("MANAGE_CHANNELS")) permissions += "MANAGE_CHANNELS, "; 24 | if(role.permissions.has("MANAGE_GUILD")) permissions += "MANAGE_GUILD, "; 25 | if(role.permissions.has("ADD_REACTIONS")) permissions += "ADD_REACTIONS, "; 26 | if(role.permissions.has("VIEW_AUDIT_LOG")) permissions += "VIEW_AUDIT_LOG, "; 27 | if(role.permissions.has("PRIORITY_SPEAKER")) permissions += "PRIORITY_SPEAKER, "; 28 | if(role.permissions.has("STREAM")) permissions += "STREAM, "; 29 | if(role.permissions.has("VIEW_CHANNEL")) permissions += "VIEW_CHANNEL, "; 30 | if(role.permissions.has("SEND_MESSAGES")) permissions += "SEND_MESSAGES, "; 31 | if(role.permissions.has("SEND_TTS_MESSAGES")) permissions += "SEND_TTS_MESSAGES, "; 32 | if(role.permissions.has("MANAGE_MESSAGES")) permissions += "MANAGE_MESSAGES, "; 33 | if(role.permissions.has("EMBED_LINKS")) permissions += "EMBED_LINKS, "; 34 | if(role.permissions.has("ATTACH_FILES")) permissions += "ATTACH_FILES, "; 35 | if(role.permissions.has("READ_MESSAGE_HISTORY")) permissions += "READ_MESSAGE_HISTORY, "; 36 | if(role.permissions.has("MENTION_EVERYONE")) permissions += "MENTION_EVERYONE, "; 37 | if(role.permissions.has("USE_EXTERNAL_EMOJIS")) permissions += "USE_EXTERNAL_EMOJIS, "; 38 | if(role.permissions.has("CONNECT")) permissions += "CONNECT, "; 39 | if(role.permissions.has("SPEAK")) permissions += "SPEAK, "; 40 | if(role.permissions.has("MUTE_MEMBERS")) permissions += "MUTE_MEMBERS, "; 41 | if(role.permissions.has("DEAFEN_MEMBERS")) permissions += "DEAFEN_MEMBERS, "; 42 | if(role.permissions.has("MOVE_MEMBERS")) permissions += "MOVE_MEMBERS, "; 43 | if(role.permissions.has("USE_VAD")) permissions += "USE_VAD, "; 44 | if(role.permissions.has("CHANGE_NICKNAME")) permissions += "CHANGE_NICKNAME, "; 45 | if(role.permissions.has("MANAGE_NICKNAMES")) permissions += "MANAGE_NICKNAMES, "; 46 | if(role.permissions.has("MANAGE_ROLES")) permissions += "MANAGE_ROLES, "; 47 | if(role.permissions.has("MANAGE_WEBHOOKS")) permissions += "MANAGE_WEBHOOKS, "; 48 | if(role.permissions.has("MANAGE_EMOJIS")) permissions += "MANAGE_EMOJIS, "; 49 | permissions = permissions.slice(0, -2); 50 | permissions += "```"; 51 | 52 | var embed = new Discord.MessageEmbed(); 53 | embed.setColor(role.color); 54 | embed.setTitle(role.name); 55 | embed.setDescription( 56 | `• **ID:** ${role.id}\n• **Hex:** ${role.hexColor}\n• **Members:** ${role.members.size}\n• **Position:** ${role.position}\n• **Hoisted:** ${role.hoist}` 57 | ); 58 | embed.addField(`**Permissions:**`, permissions) 59 | message.channel.send(embed) 60 | }; 61 | 62 | exports.conf = { 63 | enabled: true, 64 | guildOnly: true, 65 | aliases: ["rinfo"], 66 | permLevel: "User", 67 | requiredPerms: [] 68 | }; 69 | 70 | exports.help = { 71 | name: "roleinfo", 72 | category: "Utility", 73 | description: "Gives information about a role.", 74 | usage: "roleinfo [role]" 75 | }; -------------------------------------------------------------------------------- /src/commands/salmonrun.js: -------------------------------------------------------------------------------- 1 | const Discord = require("discord.js"); 2 | const BasePaginator = require('discord-paginator.js'); 3 | const fetch = require('node-fetch'); 4 | const prettifyMiliseconds = require('pretty-ms'); 5 | 6 | 7 | exports.run = async (client, message, args) =>{ 8 | fetch('https://splatoon2.ink/data/coop-schedules.json', { headers: { 'User-Agent': client.config.userAgent }}) 9 | .then(res => res.json()) 10 | .then(json => { 11 | fetch('https://splatoon2.ink/data/timeline.json', { headers: { 'User-Agent': client.config.userAgent }}) 12 | .then(timelineRes => timelineRes.json()) 13 | .then(timelineJson => { 14 | 15 | const embeds = []; 16 | 17 | if ((json.details[0].start_time * 1000) > Date.now() === true) { 18 | embeds.push( 19 | new Discord.MessageEmbed() 20 | .setTitle('Upcoming Salmon Run') 21 | .setColor(client.embedColour(message)) 22 | .setImage('https://splatoon2.ink/assets/splatnet/'+json.details[0].stage.image) 23 | .addField('Map', json.details[0].stage.name, true) 24 | .setFooter(`Page 1/2 | Starting in ${prettifyMiliseconds(json.details[0].start_time * 1000 - Date.now(), { secondsDecimalDigits: 0 })} | Data provided by splatoon2.ink`) 25 | ); 26 | } else { 27 | embeds.push( 28 | new Discord.MessageEmbed() 29 | .setTitle('Current Salmon Run') 30 | .setColor(client.embedColour(message)) 31 | .setThumbnail('https://splatoon2.ink/assets/splatnet'+timelineJson.coop.reward_gear.gear.image) 32 | .setImage('https://splatoon2.ink/assets/splatnet/'+json.details[0].stage.image) 33 | .addField('Map', json.details[0].stage.name, true) 34 | .addField('Reward Gear', timelineJson.coop.reward_gear.gear.name, true) 35 | .addField('Weapons', json.details[0].weapons[0].weapon.name+', '+json.details[0].weapons[1].weapon.name+', '+json.details[0].weapons[2].weapon.name+', '+json.details[0].weapons[3].weapon.name) 36 | .setFooter(`Page 1/2 | Ending in ${prettifyMiliseconds((json.details[0].end_time * 1000) - Date.now(), { secondsDecimalDigits: 0 })} | Data provided by splatoon2.ink`) 37 | ); 38 | } 39 | 40 | embeds.push( 41 | new Discord.MessageEmbed() 42 | .setTitle('Upcoming Salmon Run') 43 | .setColor(client.embedColour(message)) 44 | .setImage('https://splatoon2.ink/assets/splatnet/'+json.details[1].stage.image) 45 | .addField('Map', json.details[1].stage.name, true) 46 | .addField('Weapons', json.details[1].weapons[1].weapon.name+', '+json.details[1].weapons[1].weapon.name+', '+json.details[1].weapons[2].weapon.name+', '+json.details[1].weapons[3].weapon.name) 47 | .setFooter(`Page 2/2 | Starting in ${prettifyMiliseconds(json.details[1].start_time * 1000 - Date.now(), { secondsDecimalDigits: 0 })} | Data provided by splatoon2.ink`) 48 | ); 49 | 50 | const Paginator = new BasePaginator({ 51 | pages: embeds, 52 | timeout: 120000, 53 | filter: (reaction, user) => user.id == message.author.id //to filter the reaction collector 54 | }) 55 | 56 | Paginator.spawn(message.channel) 57 | }); 58 | }) 59 | .catch(err => { 60 | message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`); 61 | }); 62 | }; 63 | 64 | exports.conf = { 65 | enabled: true, 66 | guildOnly: false, 67 | aliases: [], 68 | permLevel: "User", 69 | requiredPerms: [] 70 | }; 71 | 72 | exports.help = { 73 | name: "salmonrun", 74 | category: "Splatoon", 75 | description: "Get current map, weapons and gear for salmon run.", 76 | usage: "salmonrun" 77 | }; 78 | -------------------------------------------------------------------------------- /src/commands/sans.js: -------------------------------------------------------------------------------- 1 | const url = "https://demirramon.com/gen/undertale_text_box.png"; 2 | exports.run = (client, message, args) => { 3 | let text = args.join(" "); 4 | if (!text) { 5 | return message.channel.send( 6 | `<:error:466995152976871434> No message provided. Usage: \`${client.commands.get(`sans`).help.usage}\`` 7 | ); 8 | } 9 | 10 | message.channel.startTyping(); 11 | 12 | let params = "box=undertale&boxcolor=white&character=undertale-sans&expression=default&charcolor=white&font=determination&asterisk=true&mode=regular&text=" + encodeURIComponent(text); 13 | 14 | try { 15 | message.channel.stopTyping(); 16 | message.channel.send({files: [new Discord.MessageAttachment(url + "?" + params, "undertale.png")]}); 17 | } catch(err) { 18 | message.channel.stopTyping(); 19 | message.channel.send(`<:error:466995152976871434> Error when generating image: \`${err}\``) 20 | } 21 | }; 22 | 23 | exports.conf = { 24 | enabled: true, 25 | guildOnly: false, 26 | aliases: ["undertale"], 27 | permLevel: "User", 28 | requiredPerms: ["ATTACH_FILES"] 29 | }; 30 | 31 | exports.help = { 32 | name: "sans", 33 | category: "Fun", 34 | description: "Generates a sans text box", 35 | usage: "sans [message]" 36 | }; -------------------------------------------------------------------------------- /src/commands/say.js: -------------------------------------------------------------------------------- 1 | exports.run = (client, message, args, level) => { 2 | if(!args[0]) { 3 | return message.channel.send( 4 | `<:error:466995152976871434> No message provided. Usage: \`${client.commands.get(`echo`).help.usage}\`` 5 | ); 6 | }; 7 | if (message.content.includes("@everyone") || message.content.includes("@here") || message.content.includes("<@&")) { 8 | return message.channel.send('>:('); 9 | }; 10 | 11 | message.delete().catch(O_o => {}); 12 | message.channel.send(args.join(" ")); 13 | }; 14 | 15 | exports.conf = { 16 | enabled: true, 17 | guildOnly: false, 18 | aliases: ["echo"], 19 | permLevel: "User", 20 | requiredPerms: ["MANAGE_MESSAGES"] 21 | }; 22 | 23 | exports.help = { 24 | name: "say", 25 | category: "Fun", 26 | description: "Makes Woomy copy what the user says.", 27 | usage: "echo [message]" 28 | }; 29 | -------------------------------------------------------------------------------- /src/commands/servericon.js: -------------------------------------------------------------------------------- 1 | exports.run = (client, message) => { 2 | message.channel.send(`**${message.guild}'s** icon is:\n${message.guild.iconURL({format: "png", dynamic: true, size: 2048})}`) 3 | }; 4 | 5 | exports.conf = { 6 | enabled: true, 7 | guildOnly: true, 8 | aliases: ["sicon", "guildicon"], 9 | permLevel: "User", 10 | requiredPerms: ["EMBED_LINKS"] 11 | }; 12 | 13 | exports.help = { 14 | name: "servericon", 15 | category: "Utility", 16 | description: "Displays the icon for the server.", 17 | usage: "servericon" 18 | }; 19 | -------------------------------------------------------------------------------- /src/commands/serverinfo.js: -------------------------------------------------------------------------------- 1 | exports.run = (client, message) => { 2 | 3 | var guild = message.guild 4 | var badges = ""; 5 | var members = `${guild.memberCount} (${guild.memberCount-guild.members.cache.filter(member => member.user.bot).size} users | ${guild.members.cache.filter(member => member.user.bot).size} bots)`; 6 | 7 | var roles = 0; 8 | guild.roles.cache.forEach((role) => { 9 | roles = roles + 1; 10 | }); 11 | 12 | var channels = 0; 13 | var categories = 0; 14 | var text = 0; 15 | var voice = 0; 16 | 17 | guild.channels.cache.forEach((channel) => { 18 | if(channel.type == "category") { 19 | categories = categories + 1; 20 | } else { 21 | if(channel.type == "text") { 22 | text = text + 1; 23 | }; 24 | 25 | if(channel.type == "voice") { 26 | voice = voice + 1; 27 | }; 28 | 29 | channels = channels + 1; 30 | }; 31 | }); 32 | 33 | var channelString = `${channels} (${text} text | ${voice} voice | ${categories} categories)` 34 | 35 | if(guild.premiumTier > 0) { 36 | badges = badges += "<:boosted:685704824175853624> " 37 | } 38 | 39 | if(guild.partnered == true) { 40 | badges = badges += "<:partnered:685704834779054107> " 41 | } 42 | 43 | if(guild.verified == true) { 44 | badges = badges += "<:verified:685704812435734569>" 45 | } 46 | 47 | if(badges.length > 0) { 48 | badges = badges += "\n" 49 | } 50 | 51 | var boosts; 52 | if(guild.premiumTier == 1) { 53 | boosts = `${guild.premiumSubscriptionCount} (level 1)` 54 | } else if(guild.premiumTier == 2) { 55 | boosts = `${guild.premiumSubscriptionCount} (level 2)` 56 | } else if(guild.premiumTier == 3) { 57 | boosts = `${guild.premiumSubscriptionCount} (level 3)` 58 | } else { 59 | boosts = guild.premiumSubscriptionCount; 60 | }; 61 | 62 | var emojis = 0; 63 | var static = 0; 64 | var animated = 0; 65 | 66 | guild.emojis.cache.forEach((emoji) => { 67 | if(emoji.animated == true) { 68 | animated = animated + 1; 69 | } else { 70 | static = static + 1; 71 | }; 72 | emojis = emojis + 1; 73 | }); 74 | 75 | emojiString = `${emojis} (${static} static | ${animated} animated)` 76 | 77 | let embed = new Discord.MessageEmbed() 78 | .setColor(message.guild.member(client.user).displayHexColor) 79 | .setTitle(guild.name) 80 | .setDescription(`${badges}• **ID:** ${guild.id}\n• **Owner:** ${guild.owner}\n• **Region:** ${guild.region.toProperCase()}\n• **Boosts:** ${boosts}\n• **Members:** ${members}\n• **Channels:** ${channelString}\n• **Roles:** ${roles}\n• **Emojis:** ${emojiString}\n• **Creation date:** ${guild.createdAt}`) 81 | .setThumbnail(message.guild.iconURL({format: "png", dynamic: true, size: 2048})); 82 | 83 | message.channel.send(embed); 84 | }; 85 | 86 | exports.conf = { 87 | enabled: true, 88 | guildOnly: true, 89 | aliases: ["sinfo", "guildinfo", "ginfo", "server"], 90 | permLevel: "User", 91 | requiredPerms: ["EMBED_LINKS"] 92 | }; 93 | 94 | exports.help = { 95 | name: "serverinfo", 96 | category: "Utility", 97 | description: "Displays some useful information about the current server.", 98 | usage: "serverinfo" 99 | }; 100 | -------------------------------------------------------------------------------- /src/commands/settings.js: -------------------------------------------------------------------------------- 1 | exports.run = async (client, message, args) => { 2 | 3 | const settings = message.settings; 4 | if (!client.settings.has(message.guild.id)) client.settings.set(message.guild.id, {}); 5 | 6 | modChan = message.guild.channels.cache.find(channel => channel.name === settings.modlogsChannel) || "__Disabled__"; 7 | chatChan = message.guild.channels.cache.find(channel => channel.name === settings.chatlogsChannel) || "__Disabled__" 8 | greetChan = message.guild.channels.cache.get(settings.welcomeChannel) || "__Disabled__"; 9 | prefix = settings.prefix; 10 | 11 | var raidMode; 12 | var rmDisabled = false; 13 | if(settings.raidMode == "off") { 14 | raidMode = "__Disabled__" 15 | rmDisabled = true; 16 | } else { 17 | raidMode = `\`${settings.raidMode}` 18 | } 19 | 20 | if(settings.raidModeStrict == "on") { 21 | raidMode += " (strict)`" 22 | } else if(rmDisabled != true) { 23 | raidMode += "`" 24 | } 25 | 26 | var modRole = message.guild.roles.cache.get(settings.modRole); 27 | var adminRole = message.guild.roles.cache.get(settings.adminRole); 28 | var autorole = message.guild.roles.cache.get(settings.autorole); 29 | var mutedRole = message.guild.roles.cache.get(settings.mutedRole); 30 | var blacklist = ""; 31 | 32 | if(settings.modRole == "off" || !modRole) { 33 | modRole = "__None set__"; 34 | } else { 35 | modRole = "`" + modRole.name + "`"; 36 | } 37 | 38 | if(settings.adminRole == "off" || !adminRole) { 39 | adminRole = "__None set__"; 40 | } else { 41 | adminRole = "`" + adminRole.name + "`"; 42 | } 43 | 44 | if(settings.autorole == "off" || !autorole) { 45 | autorole = "__None set__"; 46 | } else { 47 | autorole = "`" + autorole.name + "`"; 48 | } 49 | 50 | if(settings.mutedRole == "off" || !mutedRole) { 51 | mutedRole = "__None set__"; 52 | } else { 53 | mutedRole = "`" + mutedRole.name + "`"; 54 | } 55 | 56 | if(settings.welcomeMessage == "off") { 57 | welcomeMessage = "__Disabled__"; 58 | } else { 59 | welcomeMessage = "`" + settings.welcomeMessage + "`"; 60 | } 61 | 62 | if(settings.leaveMessage == "off") { 63 | leaveMessage = "__Disabled__"; 64 | } else { 65 | leaveMessage = "`" + settings.leaveMessage + "`"; 66 | } 67 | 68 | if(settings.blacklisted == "ARRAY" || settings.blacklisted.length < 1) { 69 | blacklist = "__Disabled__"; 70 | } else { 71 | if(settings.blacklisted.length > 0) { 72 | settings.blacklisted.forEach(function(user) { 73 | blacklist += "`" + (client.users.cache.get(user).tag || user.tag) + "`, " 74 | }); 75 | blacklist = blacklist.substring(0, blacklist.length - 2); 76 | }; 77 | }; 78 | 79 | embed = new Discord.MessageEmbed() 80 | embed.setAuthor("Settings for: " + message.guild.name, message.guild.iconURL({dynamic: true})) 81 | embed.setColor(message.guild.member(client.user).displayHexColor) 82 | embed.setDescription("You can edit these settings using the commands in the 'configure' section of the help command.") 83 | embed.addFields({ name: "General:", value: `Prefix: \`${prefix}\`\nChat logging: ${chatChan}\nMod logging: ${modChan}\nRaid mode: ${raidMode}\nJoin/leave channel: ${greetChan}\nWelcome message: ${welcomeMessage}\nLeave message: ${leaveMessage}`, inline: true}, {name: "Roles:", value: `Moderator: ${modRole}\nAdministrator: ${adminRole}\nMuted: ${mutedRole}\nBlocklist: ${blacklist}\nAutorole: ${autorole}`, inline: true}) 84 | message.channel.send(embed) 85 | 86 | }; 87 | 88 | exports.conf = { 89 | enabled: true, 90 | guildOnly: true, 91 | aliases: ["config"], 92 | permLevel: "Administrator", 93 | requiredPerms: [] 94 | }; 95 | 96 | exports.help = { 97 | name: "settings", 98 | category: "Configure", 99 | description: "View your server's settings.", 100 | usage: "settings" 101 | }; 102 | -------------------------------------------------------------------------------- /src/commands/sexuality.js: -------------------------------------------------------------------------------- 1 | const sexualities = require ("../../resources/other/sexualities.json"); 2 | exports.run = async (client, message, args) => { 3 | var output = ""; 4 | if(!args[0]) { 5 | for (var key of Object.keys(sexualities)) { 6 | output += `${key}, ` 7 | }; 8 | return message.channel.send(`__**Sexualities:**__\n${output.slice(0, -2)}`); 9 | } else { 10 | if(args.join(" ").toLowerCase() == "attack helicopter" || args.join(" ").toLowerCase() == "apache attack helicopter" || args.join(" ").toLowerCase() == "apache") { 11 | return message.channel.send({ 12 | files: [new Discord.MessageAttachment("./resources/images/attackhelicopter.jpg")] 13 | }); 14 | } 15 | output = sexualities[args.join(" ").toLowerCase()]; 16 | if(!output) { 17 | return message.channel.send("<:error:466995152976871434> No results for that query."); 18 | }; 19 | return message.channel.send(`__**${output.name.toProperCase()}:**__\n${output.description}`); 20 | }; 21 | }; 22 | 23 | exports.conf = { 24 | enabled: true, 25 | guildOnly: false, 26 | aliases: ["sexualities"], 27 | permLevel: "User", 28 | requiredPerms: [] 29 | }; 30 | 31 | exports.help = { 32 | name: "sexuality", 33 | category: "Fun", 34 | description: "Gives you information about the specified sexuality.", 35 | usage: "sexuality [sexuality]" 36 | }; 37 | -------------------------------------------------------------------------------- /src/commands/ship.js: -------------------------------------------------------------------------------- 1 | const Discord = require('discord.js') 2 | exports.run = async (client, message, args) => { 3 | var rating = Math.floor(Math.random() * 100) + 1 4 | var meter = ['▬', '▬', '▬', '▬', '▬', '▬', '▬', '▬', '▬'] 5 | var hearts = [ 6 | '❤️', 7 | '🧡', 8 | '💛', 9 | '💚', 10 | '💙', 11 | '💜' 12 | ] 13 | 14 | if (!args[0]) { 15 | return message.channel.send( 16 | `<:error:466995152976871434> No message provided. Usage: \`${client.commands.get(`ship`).help.usage}\`` 17 | ); 18 | } 19 | 20 | if (!args[1]) { 21 | return message.channel.send( 22 | `<:error:466995152976871434> No message provided. Usage: \`${client.commands.get(`ship`).help.usage}\`` 23 | ); 24 | } 25 | 26 | const firstName = args[0] 27 | const secondName = args[1] 28 | 29 | const shipName = firstName.substr(0, firstName.length * 0.5) + secondName.substr(secondName.length * 0.5) 30 | 31 | if (shipName.toLowerCase() === 'teily' || shipName.toLowerCase() === 'emrra') { 32 | rating = '100' 33 | } 34 | 35 | var pos = 0 36 | var under = 9 37 | while (pos < 10) { 38 | if (rating < under) { 39 | meter.splice(pos, 0, hearts.random()) 40 | break 41 | } 42 | pos++ 43 | under += 10 44 | } 45 | 46 | if (rating >= 99) { 47 | meter.splice(9, 0, hearts.random()) 48 | } 49 | 50 | const embed = new Discord.MessageEmbed() 51 | embed.setTitle(`Original Names: ${firstName}, ${secondName}`) 52 | embed.setColor(client.embedColour(message.guild)) 53 | embed.setDescription(`Ship Name: **${shipName}**\nCompatibility: **${rating}%**\n**[**${meter.join('')}**]**`) 54 | message.channel.send(embed) 55 | } 56 | 57 | exports.conf = { 58 | enabled: true, 59 | guildOnly: false, 60 | aliases: [], 61 | permLevel: "User", 62 | requiredPerms: [] 63 | }; 64 | 65 | exports.help = { 66 | name: "ship", 67 | category: "Fun", 68 | description: "Ship two people together <3", 69 | usage: "ship [name1] [name2]" 70 | }; 71 | 72 | -------------------------------------------------------------------------------- /src/commands/shuffle.js: -------------------------------------------------------------------------------- 1 | const { getGuild } = require('../modules/music') 2 | exports.run = async (client, message) => { 3 | var queue = getGuild(message.guild.id).queue 4 | 5 | if (queue.length < 4) { 6 | return message.channel.send('<:error:466995152976871434> There aren\'t enough songs are in the queue for this command to work!') 7 | } 8 | 9 | const max = queue.length - 1 10 | const min = 1 11 | for (let i = max; i >= min; i--) { 12 | const randomIndex = Math.floor(Math.random() * (max - min + 1)) + min 13 | const itemAtIndex = queue[randomIndex] 14 | queue[randomIndex] = queue[i] 15 | queue[i] = itemAtIndex 16 | } 17 | 18 | message.channel.send('<:success:466995111885144095> Queue shuffled!') 19 | } 20 | 21 | exports.conf = { 22 | enabled: true, 23 | guildOnly: true, 24 | aliases: [], 25 | permLevel: "Moderator", 26 | requiredPerms: [] 27 | } 28 | 29 | exports.help = { 30 | name: 'shuffle', 31 | category: 'Music', 32 | description: 'Mixes up the songs in the queue', 33 | usage: 'shuffle' 34 | } -------------------------------------------------------------------------------- /src/commands/skip.js: -------------------------------------------------------------------------------- 1 | const { skip, getGuild } = require('../modules/music') 2 | exports.run = (client, message, args, level) => { 3 | const guild = getGuild(message.guild.id) 4 | 5 | if (guild.queue.length < 1 || !guild.playing || !guild.dispatcher) { 6 | return message.channel.send( 7 | '<:error:466995152976871434> Nothing is playing.' 8 | ) 9 | } 10 | 11 | const vc = message.guild.members.cache.get(client.user.id).voice.channel 12 | 13 | if (vc !== message.member.voice.channel) { 14 | return message.channel.send( 15 | '<:error:466995152976871434> You need to be in my voice channel to use this command!' 16 | ) 17 | } 18 | 19 | if (guild.queue[0].requestedBy.id === message.author.id) { 20 | skip(message.guild, 'skip') 21 | 22 | guild.skippers = [] 23 | 24 | message.channel.send( 25 | '<:success:466995111885144095> Song has been skipped by the user who requested it.' 26 | ) 27 | 28 | return 29 | } 30 | 31 | if (guild.skippers.indexOf(message.author.id) === -1) { 32 | guild.skippers.push(message.author.id) 33 | 34 | if (guild.skippers.length >= Math.ceil(vc.members.filter(member => !member.user.bot).size / 2)) { 35 | skip(message.guild, 'skip') 36 | 37 | guild.skippers = [] 38 | 39 | message.channel.send( 40 | '<:skip:467216735356059660> Song skipped.' 41 | ) 42 | } else { 43 | message.channel.send( 44 | `<:success:466995111885144095> Your vote has been acknowledged! **${guild.skippers.length + '/' + Math.ceil(vc.members.filter(member => !member.user.bot).size / 2)}**` 45 | ) 46 | }; 47 | } else { 48 | message.channel.send( 49 | '<:denied:466995195150336020> You cannot vote twice!' 50 | ) 51 | } 52 | }; 53 | 54 | exports.conf = { 55 | enabled: true, 56 | guildOnly: true, 57 | aliases: ["voteskip"], 58 | permLevel: "User", 59 | requiredPerms: [] 60 | }; 61 | 62 | exports.help = { 63 | name: "skip", 64 | category: "Music", 65 | description: "Vote to skip the currently playing song. Song will be skipped instantly if executed by the user who requested it.", 66 | usage: "skip" 67 | }; 68 | 69 | function skip_song(guild) { 70 | guild.dispatcher.end("silent"); 71 | } -------------------------------------------------------------------------------- /src/commands/slap.js: -------------------------------------------------------------------------------- 1 | const API = require('nekos.life'); 2 | const {sfw} = new API(); 3 | exports.run = async (client, message, args) => { 4 | if(!args[0]) { 5 | return message.channel.send(`<:error:466995152976871434> You didn't say who you wanted to slap! Usage: \`${client.commands.get(`slap`).help.usage}\``) 6 | }; 7 | 8 | var people = ""; 9 | 10 | for (var i = 0; i < args.length; i++) { 11 | var user = client.getUserFromMention(args[i]) 12 | if (user) { 13 | user = message.guild.members.cache.get(user.id).displayName; 14 | } else { 15 | users = client.searchForMembers(message.guild, args[i]); 16 | if (users.length > 1) 17 | return message.channel.send( 18 | "<:error:466995152976871434> Found multiple users for `" + args[i] + "`, Please be more specific or mention the user instead." 19 | ); 20 | else if (users.length == 0) 21 | return message.channel.send( 22 | "<:error:466995152976871434> That user doesn't seem to exist. Try again!" 23 | ); 24 | user = users[0].displayName; 25 | }; 26 | if(i+1 == args.length && args.length > 1) { 27 | people += `**and** ${user}!` 28 | } else if(args.length < 2) { 29 | people += `${user}!`; 30 | } else if(args.length == 2 && i == 0) { 31 | people += `${user} `; 32 | } else { 33 | people += `${user}, `; 34 | }; 35 | }; 36 | 37 | 38 | 39 | message.channel.startTyping(); 40 | try { 41 | sfw.slap().then((json) => { 42 | embed = new Discord.MessageEmbed(); 43 | embed.setImage(json.url) 44 | embed.setColor(client.embedColour(message)); 45 | embed.setDescription(`**${message.guild.members.cache.get(message.author.id).displayName}** slapped **${people}**`) 46 | message.channel.send(embed) 47 | message.channel.stopTyping(); 48 | }); 49 | } catch (err) { 50 | client.logger.error("slap.js: " + err); 51 | message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`) 52 | message.channel.stopTyping(); 53 | }; 54 | }; 55 | 56 | exports.conf = { 57 | enabled: true, 58 | guildOnly: true, 59 | aliases: [], 60 | permLevel: "User", 61 | requiredPerms: ["EMBED_LINKS"] 62 | }; 63 | 64 | exports.help = { 65 | name: "slap", 66 | category: "Action", 67 | description: "Slap someone >:3", 68 | usage: "slap [@user/user] (you can slap as many people as you want!)" 69 | }; 70 | -------------------------------------------------------------------------------- /src/commands/smug.js: -------------------------------------------------------------------------------- 1 | const API = require('nekos.life'); 2 | const {sfw} = new API(); 3 | exports.run = async (client, message) => { 4 | message.channel.startTyping(); 5 | try { 6 | sfw.smug().then((json) => { 7 | embed = new Discord.MessageEmbed(); 8 | embed.setImage(json.url) 9 | embed.setColor(client.embedColour(message)); 10 | message.channel.send(embed) 11 | message.channel.stopTyping(); 12 | }); 13 | } catch (err) { 14 | client.logger.error("smug.js: " + err); 15 | message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`) 16 | message.channel.stopTyping(); 17 | }; 18 | }; 19 | 20 | exports.conf = { 21 | enabled: true, 22 | guildOnly: true, 23 | aliases: [], 24 | permLevel: "User", 25 | requiredPerms: ["EMBED_LINKS"] 26 | }; 27 | 28 | exports.help = { 29 | name: "smug", 30 | category: "Action", 31 | description: "Sends a smug gif.", 32 | usage: "smug" 33 | }; 34 | -------------------------------------------------------------------------------- /src/commands/softban.js: -------------------------------------------------------------------------------- 1 | exports.run = async (client, message, args) => { 2 | const settings = (message.settings = client.getSettings(message.guild.id)); 3 | 4 | if(!args[0]) { 5 | return message.channel.send( 6 | `<:error:466995152976871434> No username provided. Usage: \`${client.commands.get(`ban`).help.usage}\`` 7 | ); 8 | }; 9 | 10 | let user = message.mentions.members.first(); 11 | 12 | if (!user) { 13 | let users; 14 | users = client.searchForMembers(message.guild, args[0]); 15 | if (users.length > 1) 16 | return message.channel.send( 17 | "<:error:466995152976871434> Found multiple users! Please be more specific or mention the user instead." 18 | ); 19 | else if (users.length == 0) 20 | return message.channel.send( 21 | "<:error:466995152976871434> That user doesn't seem to exist. Try again!" 22 | ); 23 | user = users[0]; 24 | }; 25 | 26 | if(!user.bannable) { 27 | return message.channel.send(`<:error:466995152976871434> Specified user is not bannable.`) 28 | }; 29 | 30 | let mod = message.guild.member(message.author); 31 | let bot = message.guild.member(client.user); 32 | 33 | if (user.roles.highest.position >= mod.roles.highest.position) { 34 | return message.channel.send( 35 | `<:error:466995152976871434> You can't softban people who are higher ranked than you are!` 36 | ); 37 | }; 38 | 39 | if (user.roles.highest.position >= bot.roles.highest.position) { 40 | return message.channel.send( 41 | `<:error:466995152976871434> I can't softban people who are higher ranked than you myself!` 42 | ); 43 | }; 44 | 45 | if(!user.bannable) { 46 | return message.channel.send(`<:error:466995152976871434> Specified user is not bannable.`) 47 | }; 48 | 49 | var days = args[args.length - 1] 50 | try { 51 | days = Number(days); 52 | } catch(err) {}; 53 | 54 | console.log(typeof days) 55 | console.log(days) 56 | 57 | if(isNaN(days)) { 58 | return message.channel.send(`<:error:466995152976871434> Invalid number. Did you forget to specify how many days worth of messages to clear? Usage: \`${client.commands.get(`softban`).help.usage}\``) 59 | } else if (days < 1 || days > 7) { 60 | return message.channel.send(`<:error:466995152976871434> Number too large/small. The max amount of days I can clear is 7.`) 61 | } else { 62 | await message.guild.members.ban(user, {reason: `Softbanned by ${message.author.tag}`, days: days}); 63 | await message.guild.members.unban(user); 64 | message.channel.send(`<:success:466995111885144095> Softbanned \`${user.user.tag}\``); 65 | 66 | if (settings.modlogsChannel !== "off") { 67 | const channel = message.guild.channels.cache.find( 68 | channel => channel.name === settings.modlogsChannel 69 | ); 70 | 71 | if (channel) { 72 | let embed = new Discord.MessageEmbed(); 73 | embed.setColor("#F38159"); 74 | embed.setAuthor("User softbanned!", user.user.avatarURL({format: "png", dynamic: true, size: 2048})); 75 | embed.setDescription( 76 | `• User: ${user.user.tag} (${user.user.id})\n• Mod: ${message.author} (${message.author.id})\n• Days cleared: ${days}` 77 | ); 78 | try { 79 | channel.send(embed); 80 | } catch (err) {}; 81 | }; 82 | }; 83 | }; 84 | }; 85 | 86 | exports.conf = { 87 | enabled: true, 88 | guildOnly: true, 89 | aliases: [], 90 | permLevel: "Moderator", 91 | requiredPerms: ["BAN_MEMBERS"] 92 | }; 93 | 94 | exports.help = { 95 | name: "softban", 96 | category: "Moderation", 97 | description: "Bans then unbans a user, clearing their messages.", 98 | usage: "softban [user] [days]" 99 | }; 100 | -------------------------------------------------------------------------------- /src/commands/songinfo.js: -------------------------------------------------------------------------------- 1 | const { getGuild, createTimestamp } = require('../modules/music') 2 | const { MessageEmbed } = require('discord.js') 3 | exports.run = async (client, message, args) => { 4 | const guild = getGuild(message.guild.id) 5 | 6 | if (guild.queue.length < 1) { 7 | return message.channel.send(client.config.emojis.error + ' Nothing is in the queue!') 8 | } 9 | 10 | const songID = +args[0] 11 | 12 | if (isNaN(songID) === true) { 13 | return message.channel.send('<:error:466995152976871434> That isn\'t a number! You need to tell me the songs position in the queue (1, 2, etc.)') 14 | } 15 | 16 | const s = guild.queue[songID] 17 | 18 | if (!s) { 19 | return message.channel.send('<:error:466995152976871434> No song was found in the position you specified.') 20 | } 21 | 22 | const embed = new MessageEmbed() 23 | embed.setThumbnail('https://invidiou.site' + s.video.videoThumbnails[1].url) 24 | embed.setColor(client.embedColour(message)) 25 | embed.setDescription(`**[${s.video.title}](https://www.youtube.com/watch?v=${s.video.videoId})**`) 26 | embed.addField('Channel:', s.video.author, true) 27 | embed.addField('Length:', '`[' + createTimestamp(s.video.lengthSeconds) + ']`', true) 28 | embed.setFooter('Requested by ' + s.requestedBy.tag, s.requestedBy.avatarURL({ format: 'png', dynamic: true, size: 2048 })) 29 | 30 | message.channel.send(embed) 31 | } 32 | 33 | exports.conf = { 34 | enabled: true, 35 | guildOnly: true, 36 | aliases: [], 37 | permLevel: "User", 38 | requiredPerms: [] 39 | } 40 | 41 | exports.help = { 42 | name: "songinfo", 43 | category: "Music", 44 | description: "Sends you information about a song in the queue. Song ID is the song's position in the queue.", 45 | usage: "songinfo [songID]" 46 | } -------------------------------------------------------------------------------- /src/commands/splatnet.js: -------------------------------------------------------------------------------- 1 | const Discord = require("discord.js"); 2 | const BasePaginator = require('discord-paginator.js'); 3 | const fetch = require('node-fetch'); 4 | const prettifyMiliseconds = require('pretty-ms'); 5 | 6 | 7 | exports.run = async (client, message, args) =>{ 8 | fetch('https://splatoon2.ink//data/merchandises.json', { headers: { 'User-Agent': client.config.userAgent }}) 9 | .then(res => res.json()) 10 | .then(json => { 11 | const embeds = []; 12 | 13 | for ( let i = 0; i < json.merchandises.length; i++ ) { 14 | const embed = new Discord.MessageEmbed() 15 | .setTitle(json.merchandises[i].gear.name) 16 | .setThumbnail('https://splatoon2.ink/assets/splatnet' + json.merchandises[i].gear.image) 17 | .setColor(client.embedColour(message)) 18 | .addField('Price', (json.merchandises[i].price).toString(), true) 19 | .addField('Brand', json.merchandises[i].gear.brand.name, true) 20 | .addField('Ability Slots', (json.merchandises[i].gear.rarity + 1).toString(), true) 21 | .addField('Main Ability', json.merchandises[i].skill.name, true) 22 | .addField('Common Ability', json.merchandises[i].gear.brand.frequent_skill.name, true) 23 | .setFooter(`Page ${i+1}/${json.merchandises.length} | Out of stock in ${prettifyMiliseconds(json.merchandises[i].end_time * 1000 - Date.now())} | Data provided by splatoon2.ink`); 24 | embeds.push(embed); 25 | } 26 | 27 | const Paginator = new BasePaginator({ 28 | pages: embeds, 29 | timeout: 120000, 30 | filter: (reaction, user) => user.id == message.author.id //to filter the reaction collector 31 | }) 32 | 33 | Paginator.spawn(message.channel) 34 | }) 35 | .catch(err => { 36 | message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`); 37 | }); 38 | }; 39 | 40 | exports.conf = { 41 | enabled: true, 42 | guildOnly: false, 43 | aliases: [], 44 | permLevel: "User", 45 | requiredPerms: [] 46 | }; 47 | 48 | exports.help = { 49 | name: "splatnet", 50 | category: "Splatoon", 51 | description: "See what is currently on offer in the splatnet shop.", 52 | usage: "splatnet" 53 | }; 54 | -------------------------------------------------------------------------------- /src/commands/splatoonmaps.js: -------------------------------------------------------------------------------- 1 | const Discord = require("discord.js"); 2 | const BasePaginator = require('discord-paginator.js'); 3 | const fetch = require('node-fetch'); 4 | const prettifyMiliseconds = require('pretty-ms'); 5 | 6 | 7 | exports.run = async (client, message, args) =>{ 8 | fetch('https://splatoon2.ink/data/schedules.json', { headers: { 'User-Agent': client.config.userAgent }}) 9 | .then(res => res.json()) 10 | .then(json => { 11 | 12 | const embeds = [ 13 | new Discord.MessageEmbed() 14 | .setTitle('Current Splatoon 2 Maps') 15 | .setColor(client.embedColour(message)) 16 | .addField('<:turf_war:814651383911153692> Turf War', `${json.regular[0].stage_a.name}\n${json.regular[0].stage_b.name}`, true) 17 | .addField(`<:ranked:814651402479468544> Ranked: ${json.gachi[0].rule.name}`, `${json.gachi[0].stage_a.name}\n${json.gachi[0].stage_b.name}`, true) 18 | .addField(`<:league:814651415409590363> League: ${json.league[0].rule.name}`, `${json.league[0].stage_a.name}\n${json.league[0].stage_b.name}`, true) 19 | .setFooter(`Page 1/${json.regular.length} | Maps changing in ${prettifyMiliseconds(json.league[0].end_time * 1000 - Date.now(), { secondsDecimalDigits: 0 })} | Data provided by splatoon2.ink`) 20 | ]; 21 | 22 | for ( let i = 1; i < json.regular.length; i++ ) { 23 | embeds.push( 24 | new Discord.MessageEmbed() 25 | .setTitle('Upcoming Splatoon 2 Maps') 26 | .setColor(client.embedColour(message)) 27 | .addField('<:turf_war:814651383911153692> Turf War', `${json.regular[i].stage_a.name}\n${json.regular[i].stage_b.name}`, true) 28 | .addField(`<:ranked:814651402479468544> Ranked: ${json.gachi[i].rule.name}`, `${json.gachi[i].stage_a.name}\n${json.gachi[i].stage_b.name}`, true) 29 | .addField(`<:league:814651415409590363> League: ${json.league[i].rule.name}`, `${json.league[i].stage_a.name}\n${json.league[i].stage_b.name}`, true) 30 | .setFooter(`Page ${i+1}/${json.regular.length} | Available in ${prettifyMiliseconds(json.league[i].start_time * 1000 - Date.now(), { secondsDecimalDigits: 0 })} | Data provided by splatoon2.ink`) 31 | ); 32 | } 33 | 34 | const Paginator = new BasePaginator({ 35 | pages: embeds, 36 | timeout: 120000, 37 | filter: (reaction, user) => user.id == message.author.id //to filter the reaction collector 38 | }) 39 | 40 | Paginator.spawn(message.channel) 41 | }) 42 | .catch(err => { 43 | message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`); 44 | }); 45 | }; 46 | 47 | exports.conf = { 48 | enabled: true, 49 | guildOnly: false, 50 | aliases: ['splatoonmodes'], 51 | permLevel: "User", 52 | requiredPerms: [] 53 | }; 54 | 55 | exports.help = { 56 | name: "splatoonmaps", 57 | category: "Splatoon", 58 | description: "Get current and upcoming maps and modes for regular, ranked and league battles.", 59 | usage: "splatoonmaps" 60 | }; 61 | -------------------------------------------------------------------------------- /src/commands/spoilerise.js: -------------------------------------------------------------------------------- 1 | exports.run = async (client, message, args) => { 2 | if(!args[0]) { 3 | return message.channel.send(`<:error:466995152976871434> You didn't provide any text! Usage: \`${client.commands.get(`spoiler`).help.usage}\``) 4 | }; 5 | 6 | var output = `||${[...message.cleanContent.substring(9)].join("||||")}||`; 7 | 8 | if(output.length > 2000) { 9 | output = output.slice(0, -Math.abs(output.length - 2000)) 10 | }; 11 | 12 | message.channel.send(output) 13 | }; 14 | 15 | exports.conf = { 16 | enabled: true, 17 | guildOnly: false, 18 | aliases: ["spoilerize", "spoiler"], 19 | permLevel: "User", 20 | requiredPerms: [] 21 | }; 22 | 23 | exports.help = { 24 | name: "spoilerise", 25 | category: "Fun", 26 | description: "Spoilers every letter in the provided text.", 27 | usage: "spoiler [text]" 28 | }; 29 | -------------------------------------------------------------------------------- /src/commands/stop.js: -------------------------------------------------------------------------------- 1 | const { getGuild } = require('../modules/music') 2 | exports.run = async (client, message) => { 3 | const guild = getGuild(message.guild.id) 4 | 5 | if (guild.queue.length < 1 || !guild.playing || !guild.dispatcher) return message.channel.send('Nothing is playing.') 6 | if (!message.member.voice.channel) return message.channel.send('You need to be in voice channel to use this command!') 7 | 8 | guild.dispatcher.end('silent') 9 | 10 | guild.queue = [] 11 | guild.playing = false 12 | guild.paused = false 13 | guild.skippers = [] 14 | guild.fixers = [] 15 | guild.channel = null 16 | 17 | message.channel.send('<:success:466995111885144095> Playback stopped!') 18 | }; 19 | 20 | exports.conf = { 21 | enabled: true, 22 | guildOnly: true, 23 | aliases: [], 24 | permLevel: "Moderator", 25 | requiredPerms: [] 26 | }; 27 | 28 | exports.help = { 29 | name: "stop", 30 | category: "Music", 31 | description: "Clears the queue and disconnects from the voice channel. (run this if music stopS working)", 32 | usage: "stop" 33 | }; 34 | 35 | -------------------------------------------------------------------------------- /src/commands/support.js: -------------------------------------------------------------------------------- 1 | exports.run = async (client, message, args) =>{ 2 | message.channel.send("Use this link to join my support server: https://discord.gg/HCF8mdv") 3 | }; 4 | 5 | exports.conf = { 6 | enabled: true, 7 | guildOnly: false, 8 | aliases: [], 9 | permLevel: "User", 10 | requiredPerms: [] 11 | }; 12 | 13 | exports.help = { 14 | name: "support", 15 | category: "Utility", 16 | description: "Sends a link to Woomy's support/development server.", 17 | usage: "support" 18 | }; 19 | -------------------------------------------------------------------------------- /src/commands/takerole.js: -------------------------------------------------------------------------------- 1 | exports.run = async (client, message, [member, ...role2add], query) => { 2 | if (!member) { 3 | return message.channel.send( 4 | `<:error:466995152976871434> No user specified. Usage: \`${client.commands.get(`takerole`).help.usage}\`` 5 | ); 6 | } 7 | let user = message.mentions.members.first(); 8 | let users; 9 | if (!user) { 10 | users = client.searchForMembers(message.guild, member); 11 | if (users.length > 1) 12 | return message.channel.send( 13 | "<:error:466995152976871434> Found multiple users, please be more specific or mention the user instead." 14 | ); 15 | else if (users.length == 0) 16 | return message.channel.send( 17 | "<:error:466995152976871434> That user doesn't seem to exist. Try again!" 18 | ); 19 | user = users[0]; 20 | } 21 | let role = role2add.join(" "); 22 | 23 | gRole = client.findRole(role, message); 24 | 25 | if (!gRole) { 26 | return message.channel.send(`<:error:466995152976871434> That role doesn't seem to exist. Try again!`); 27 | }; 28 | 29 | let moderator = message.guild.member(message.author) 30 | if (gRole.position >= moderator.roles.highest.position) { 31 | return message.channel.send( 32 | "<:error:466995152976871434> You cannot take roles higher than your own!" 33 | ); 34 | } 35 | 36 | var bot = message.guild.members.cache.get(client.user.id) 37 | if (gRole.position >= bot.roles.highest.position) { 38 | return message.channel.send( 39 | `<:error:466995152976871434> I can't take roles higher than my own!` 40 | ); 41 | } 42 | if (!user.roles.cache.has(gRole.id)) { 43 | return message.channel.send( 44 | "<:error:466995152976871434> They don't have that role!" 45 | ); 46 | } 47 | await user.roles.remove(gRole.id); 48 | message.channel.send( 49 | `<:success:466995111885144095> Took the \`${gRole.name}\` role from \`${ 50 | user.user.tag 51 | }\`` 52 | ); 53 | 54 | if (client.getSettings(message.guild.id).modlogsChannel !== "off") { 55 | const channel = message.guild.channels.cache.find( 56 | channel => channel.name === client.getSettings(message.guild.id).modlogsChannel 57 | ); 58 | 59 | if (channel) { 60 | let embed = new Discord.MessageEmbed(); 61 | embed.setColor("#008369"); 62 | embed.setAuthor("Role taken:", user.user.avatarURL({format: "png", dynamic: true, size: 2048})); 63 | embed.setDescription(`‏‏‎• User: ${user} (${user.user.id})\n‏‏‎• Mod: ${message.author} (${message.author.id})\n‏‏‎• Role: ${gRole}`) 64 | try { 65 | channel.send({ embed }); 66 | } catch (err) { 67 | // probably no permissions to send messages/embeds there 68 | }; 69 | }; 70 | }; 71 | }; 72 | 73 | exports.conf = { 74 | enabled: true, 75 | guildOnly: true, 76 | aliases: ["removerole"], 77 | permLevel: "Moderator", 78 | requiredPerms: ["MANAGE_ROLES"] 79 | }; 80 | 81 | exports.help = { 82 | name: "takerole", 83 | category: "Moderation", 84 | description: "Takes a role from the specified user.", 85 | usage: "takerole [user] [role]" 86 | }; -------------------------------------------------------------------------------- /src/commands/tickle.js: -------------------------------------------------------------------------------- 1 | const API = require('nekos.life'); 2 | const {sfw} = new API(); 3 | exports.run = async (client, message, args) => { 4 | if(!args[0]) { 5 | return message.channel.send(`<:error:466995152976871434> You didn't say who you wanted to tickle! Usage: \`${client.commands.get(`tickle`).help.usage}\``) 6 | }; 7 | 8 | var people = ""; 9 | 10 | for (var i = 0; i < args.length; i++) { 11 | var user = client.getUserFromMention(args[i]) 12 | if (user) { 13 | user = message.guild.members.cache.get(user.id).displayName; 14 | } else { 15 | users = client.searchForMembers(message.guild, args[i]); 16 | if (users.length > 1) 17 | return message.channel.send( 18 | "<:error:466995152976871434> Found multiple users for `" + args[i] + "`, Please be more specific or mention the user instead." 19 | ); 20 | else if (users.length == 0) 21 | return message.channel.send( 22 | "<:error:466995152976871434> That user doesn't seem to exist. Try again!" 23 | ); 24 | user = users[0].displayName; 25 | }; 26 | if(i+1 == args.length && args.length > 1) { 27 | people += `**and** ${user}!` 28 | } else if(args.length < 2) { 29 | people += `${user}!`; 30 | } else if(args.length == 2 && i == 0) { 31 | people += `${user} `; 32 | } else { 33 | people += `${user}, `; 34 | }; 35 | }; 36 | 37 | 38 | 39 | message.channel.startTyping(); 40 | try { 41 | sfw.tickle().then((json) => { 42 | embed = new Discord.MessageEmbed(); 43 | embed.setImage(json.url) 44 | embed.setColor(client.embedColour(message)); 45 | embed.setDescription(`**${message.guild.members.cache.get(message.author.id).displayName}** tickled **${people}**`) 46 | message.channel.send(embed) 47 | message.channel.stopTyping(); 48 | }); 49 | } catch (err) { 50 | client.logger.error("tickle.js: " + err); 51 | message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`) 52 | message.channel.stopTyping(); 53 | }; 54 | }; 55 | 56 | exports.conf = { 57 | enabled: true, 58 | guildOnly: true, 59 | aliases: [], 60 | permLevel: "User", 61 | requiredPerms: ["EMBED_LINKS"] 62 | }; 63 | 64 | exports.help = { 65 | name: "tickle", 66 | category: "Action", 67 | description: "Tickle someone!", 68 | usage: "tickle [@user/user] (you can tickle as many people as you want!)" 69 | }; 70 | -------------------------------------------------------------------------------- /src/commands/unmute.js: -------------------------------------------------------------------------------- 1 | exports.run = async (client, message, args, level) => { 2 | const settings = message.settings; 3 | 4 | if(!args[0]) { 5 | return message.channel.send("<:error:466995152976871434> Who am I meant to unmute?") 6 | } 7 | let user = message.mentions.members.first(); 8 | let users; 9 | if (!user) { 10 | users = client.searchForMembers(message.guild, args[0]); 11 | if (users.length > 1) 12 | return message.channel.send( 13 | "<:error:466995152976871434> Found multiple users! Please be more specific or mention the user instead." 14 | ); 15 | else if (users.length == 0) 16 | return message.channel.send( 17 | "<:error:466995152976871434> That user doesn't seem to exist. Try again!" 18 | ); 19 | user = users[0]; 20 | } 21 | if (user.user.id === client.user.id) { 22 | return message.channel.send("lol no") 23 | } 24 | 25 | let moderator = message.guild.member(message.author) 26 | if (message.settings.mutedRole.position >= moderator.roles.highest.position && level < 2) { 27 | return message.channel.send( 28 | "<:error:466995152976871434> The muted role is positioned above the moderator role! Please move the muted role below the moderator role." 29 | ); 30 | } 31 | if (user.roles.highest.position >= moderator.roles.highest.position && moderator.user.id !== message.guild.ownerID) { 32 | return message.channel.send( 33 | `<:error:466995152976871434> You can't unmute people who have a higher role than you!` 34 | ); 35 | }; 36 | let bot = message.guild.member(client.user) 37 | if (user.roles.highest.position >= bot.roles.highest.position) { 38 | return message.channel.send( 39 | `<:error:466995152976871434> I can't unmute people who have a higher role than me!` 40 | ); 41 | } 42 | 43 | let role = message.guild.roles.cache.get(settings.mutedRole) 44 | if(!role) { 45 | return message.channel.send( 46 | "<:error:466995152976871434> Mute role not found! Please set one using `~settings edit mutedRole `" 47 | ); 48 | } 49 | 50 | if (!user.roles.cache.has(role.id)) { 51 | return message.channel.send("<:error:466995152976871434> They aren't muted!") 52 | } 53 | 54 | await user.roles.remove(role.id); 55 | message.channel.send(`<:success:466995111885144095> Unmuted \`${user.user.tag}\``) 56 | 57 | 58 | if (settings.modlogsChannel !== "off") { 59 | const channel = message.guild.channels.cache.find( 60 | channel => channel.name === settings.modlogsChannel 61 | ); 62 | 63 | if (channel) { 64 | let embed = new Discord.MessageEmbed(); 65 | embed.setColor("#7a2f8f"); 66 | embed.setAuthor("User unmuted!", user.user.avatarURL({format: "png", dynamic: true, size: 2048})); 67 | embed.setDescription(`• User: ${user} (${user.user.id})\n• Mod: ${message.author} (${message.author.id})`) 68 | try { 69 | channel.send({ embed }); 70 | } catch (err) { 71 | // probably no permissions to send messages/embeds there 72 | } 73 | } 74 | } 75 | }; 76 | 77 | exports.conf = { 78 | enabled: true, 79 | guildOnly: true, 80 | aliases: [], 81 | permLevel: "Moderator", 82 | requiredPerms: ["MANAGE_ROLES", "MANAGE_CHANNELS"] 83 | }; 84 | 85 | exports.help = { 86 | name: "unmute", 87 | category: "Moderation", 88 | description: "Allows a muted user to type again.", 89 | usage: "unmute [user]" 90 | }; 91 | -------------------------------------------------------------------------------- /src/commands/urban.js: -------------------------------------------------------------------------------- 1 | Discord = require("discord.js"); 2 | urban = require("relevant-urban"); 3 | exports.run = async (client, message, args) => { 4 | if (message.channel.nsfw === false) return message.channel.send( 5 | "<:error:466995152976871434> This command can only be executed in channels marked as NSFW!" 6 | ); 7 | if (args < 1) return message.channel.send( 8 | `<:error:466995152976871434> You did not tell me what to search for! Usage: \`${client.commands.get(`urban`).help.usage}\` 9 | `); 10 | let phrase = args.join(" "); 11 | let output = await urban(args.join(' ')).catch(e => { 12 | return message.channel.send("<:error:466995152976871434> No results found for `" + phrase + "`") 13 | }); 14 | 15 | if(output.definition.length > 2000) return message.channel.send( 16 | `<:error:466995152976871434> Definition cannot exceed 2000 characters! Use this link instead: ${output.urbanURL}` 17 | ); 18 | if(output.example.length > 2000) return message.channel.send( 19 | "<:error:466995152976871434> Example cannot exceed 2000 characters!" 20 | ); 21 | 22 | embed = new Discord.MessageEmbed() 23 | .setTitle(output.word) 24 | .setURL(output.urbanURL) 25 | .setColor("#EFFF00") 26 | .setDescription(output.definition || "None") 27 | .addFields( 28 | {name: "Example", value: output.example || "None"}, {name: "Upvotes", value: output.thumbsUp, inline: true}, {name: "Downvotes", value: output.thumbsDown, inline: true} 29 | ) 30 | .setFooter(`Submitted by ${output.author}`) 31 | message.channel.send(embed); 32 | 33 | }; 34 | 35 | exports.conf = { 36 | enabled: true, 37 | guildOnly: false, 38 | aliases: [], 39 | permLevel: "User", 40 | requiredPerms: [] 41 | }; 42 | 43 | exports.help = { 44 | name: "urban", 45 | category: "Fun", 46 | description: "Grabs a definition from the urban dictonary.", 47 | usage: "urban [word]" 48 | }; 49 | -------------------------------------------------------------------------------- /src/commands/userinfo.js: -------------------------------------------------------------------------------- 1 | const Discord = require("discord.js"); 2 | const coolPeople = require('../../resources/other/coolpeople.json') 3 | exports.run = (client, message, args) => { 4 | var user, guild, createdAt, avurl, tag, id; 5 | var nick = "", roles = "", badges = ""; 6 | var coolPerson = false; 7 | var friendos = coolPeople.coolPeople; 8 | 9 | if(message.guild) { 10 | user = message.mentions.members.first(); 11 | 12 | if(!args[0]) { 13 | user = message.guild.members.cache.get(message.author.id) 14 | }; 15 | 16 | if (!user) { 17 | var users; 18 | users = client.searchForMembers(message.guild, args[0]); 19 | if (users.length > 1) 20 | return message.channel.send( 21 | "<:error:466995152976871434> Found multiple users! Please be more specific or mention the user instead." 22 | ); 23 | else if (users.length == 0) 24 | return message.channel.send( 25 | "<:error:466995152976871434> That user doesn't seem to exist. Try again!" 26 | ); 27 | user = users[0]; 28 | }; 29 | 30 | if(user.nickname) { 31 | nick = `\n• **Nickname:** ${user.nickname}`; 32 | }; 33 | 34 | for (var i = 0; i < friendos.length; i++) { 35 | if (user.user.id == friendos[i]) 36 | coolPerson = true; 37 | }; 38 | 39 | if(coolPerson == true) { 40 | badges += "🌟" 41 | } 42 | 43 | if(user.user.id == message.guild.ownerID) { 44 | badges += "<:owner:685703193694306331>" 45 | } 46 | 47 | if(user.user.bot) { 48 | badges += "<:bot:686489601678114859>" 49 | } 50 | 51 | 52 | if(badges.length > 0) { 53 | badges += "\n" 54 | } 55 | 56 | user.roles.cache.forEach((role) => { 57 | roles = roles + role.name + "`, `" 58 | }); 59 | 60 | roles = roles.substr(0, roles.length -4); 61 | 62 | guild = `\n• **Roles:** \`${roles}\`\n• **Server join date:** ${user.joinedAt}`; 63 | 64 | id = user.user.id; 65 | tag = user.user.tag; 66 | colour = user.displayHexColor; 67 | avurl = user.user.avatarURL({format: "png", dynamic: true, size: 2048}); 68 | createdAt = user.user.createdAt; 69 | } else { 70 | id = user.id; 71 | tag = user.tag; 72 | colour = ["#ff9d68", "#ff97cb", "#d789ff", "#74FFFF"].random(); 73 | avurl = user.avatarURL({format: "png", dynamic: true, size: 2048}); 74 | createdAt = user.createdAt; 75 | }; 76 | 77 | embed = new Discord.MessageEmbed(); 78 | embed.setTitle(tag); 79 | embed.setThumbnail(avurl); 80 | embed.setDescription(`${badges}• **ID:** ${id}${nick}${guild}\n• **Account created:** ${createdAt}`) 81 | embed.setColor(colour); 82 | message.channel.send(embed); 83 | }; 84 | 85 | exports.conf = { 86 | enabled: true, 87 | guildOnly: false, 88 | aliases: ["uinfo", "user"], 89 | permLevel: "User", 90 | requiredPerms: ["EMBED_LINKS"] 91 | }; 92 | 93 | exports.help = { 94 | name: "userinfo", 95 | category: "Utility", 96 | description: "Displays some useful information about the specified user.", 97 | usage: "userinfo " 98 | }; 99 | -------------------------------------------------------------------------------- /src/commands/volume.js: -------------------------------------------------------------------------------- 1 | const { getGuild, setVolume } = require('../modules/music') 2 | exports.run = async (client, message, args) => { 3 | if (!args[0]) { 4 | return message.channel.send(`<:error:466995152976871434> No input! Usage: \`${client.commands.get('volume').help.usage}\``) 5 | } 6 | 7 | const guild = getGuild(message.guild.id) 8 | 9 | if (guild.queue.length < 1 || !guild.playing || !guild.dispatcher) { 10 | return message.channel.send( 11 | '<:error:466995152976871434> Nothing is playing.' 12 | ) 13 | } 14 | 15 | let userVolume = args[0] 16 | 17 | if (userVolume.includes('%')) { 18 | userVolume = userVolume.replace('%', '') 19 | } 20 | 21 | userVolume = +userVolume 22 | 23 | if (isNaN(userVolume) === true) { 24 | return message.channel.send('<:error:466995152976871434> Input must be a number!') 25 | } 26 | 27 | if (userVolume > 100 || userVolume < 1) { 28 | return message.channel.send('<:error:466995152976871434> Invalid input, input must be between 1-100') 29 | } 30 | 31 | if (userVolume) { 32 | userVolume = Number(userVolume) 33 | 34 | userVolume = userVolume / 100 35 | 36 | if (userVolume <= 1) { 37 | setVolume(message.guild, userVolume) 38 | 39 | message.channel.send('<:success:466995111885144095> Set volume to ' + userVolume * 100 + '%') 40 | } 41 | } 42 | } 43 | 44 | exports.conf = { 45 | enabled: true, 46 | guildOnly: true, 47 | aliases: [], 48 | permLevel: "Moderator", 49 | requiredPerms: [] 50 | } 51 | 52 | exports.help = { 53 | name: 'volume', 54 | category: 'Music', 55 | description: 'Sets volume of currently playing music. (100% = 25% of the actual volume)', 56 | usage: 'volume [volume]' 57 | } -------------------------------------------------------------------------------- /src/commands/wag.js: -------------------------------------------------------------------------------- 1 | const fetch = require("node-fetch") 2 | exports.run = async (client, message, args) => { 3 | message.channel.startTyping(); 4 | try{ 5 | fetch(`https://purrbot.site/api/img/sfw/tail/gif/`) 6 | .then(res => res.json()) 7 | .then(json => message.channel.send(json.link)) 8 | .catch(err => { 9 | message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`); 10 | }); 11 | message.channel.stopTyping(); 12 | } catch(err) { 13 | message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`); 14 | message.channel.stopTyping(); 15 | }; 16 | }; 17 | 18 | exports.conf = { 19 | enabled: true, 20 | guildOnly: false, 21 | aliases: [], 22 | permLevel: "User", 23 | requiredPerms: ["EMBED_LINKS"] 24 | }; 25 | 26 | exports.help = { 27 | name: "wag", 28 | category: "Image", 29 | description: "Wag the tail :3", 30 | usage: "wag" 31 | }; 32 | -------------------------------------------------------------------------------- /src/commands/weather.js: -------------------------------------------------------------------------------- 1 | const weather = require("weather-js"); 2 | exports.run = async (client, message, args, error) => { 3 | if(!args[0]) { 4 | return message.channel.send( 5 | `<:error:466995152976871434> You didn't give me a location. Usage: \`${client.commands.get(`weather`).help.usage}\`` 6 | ); 7 | }; 8 | 9 | message.channel.startTyping(); 10 | 11 | try { 12 | weather.find({search: args.join(" "), degreeType: 'C'}, function(err, result) { 13 | if(err) return message.channel.send(`<:error:466995152976871434> API error: \`${error}\``) 14 | if(result.length < 2 || !result) { 15 | message.channel.stopTyping(); 16 | return message.channel.send("<:error:466995152976871434> City not found!"); 17 | }; 18 | 19 | var location = result[0].location; 20 | var current = result[0].current; 21 | 22 | var warning = (`${location.alert}` || "No warnings"); 23 | 24 | var embedColour; 25 | if (current.temperature < 0) { 26 | embedColour = "#addeff"; 27 | }else if (current.temperature < 20) { 28 | embedColour = "#4fb8ff"; 29 | }else if (current.temperature < 26) { 30 | embedColour = "#ffea4f"; 31 | }else if (current.temperature < 31) { 32 | embedColour = "#ffa14f" 33 | } else { 34 | embedColour = "#ff614f" 35 | }; 36 | 37 | embed = new Discord.MessageEmbed(); 38 | embed.setAuthor(`Weather for ${location.name}:`) 39 | embed.setDescription(`• **Condition:** ${current.skytext}\n• **Temperature:** ${current.temperature}°C\n• **Feels like:** ${current.feelslike}°C\n• **Humidity:** ${current.humidity}%\n• **Wind:** ${current.winddisplay}\n• **Warnings:** ${warning}`) 40 | embed.setThumbnail(current.imageUrl) 41 | embed.setFooter(`Last updated at ${current.observationtime} ${current.date}`) 42 | embed.setColor(embedColour) 43 | message.channel.stopTyping(); 44 | message.channel.send(embed) 45 | }); 46 | } catch(err) { 47 | return message.channel.send(`<:error:466995152976871434> API error: \`${err}\``) 48 | }; 49 | }; 50 | 51 | exports.conf = { 52 | enabled: true, 53 | guildOnly: false, 54 | aliases: [], 55 | permLevel: "User", 56 | requiredPerms: ["EMBED_LINKS"] 57 | }; 58 | 59 | exports.help = { 60 | name: "weather", 61 | category: "Utility", 62 | description: "Tells you the weather", 63 | usage: "weather [location]" 64 | }; -------------------------------------------------------------------------------- /src/commands/welcome.js: -------------------------------------------------------------------------------- 1 | const Discord = require("discord.js") 2 | exports.run = async (client, message, args, level) => { 3 | 4 | const settings = message.settings; 5 | const defaults = client.config.defaultSettings; 6 | const overrides = client.settings.get(message.guild.id); 7 | if (!client.settings.has(message.guild.id)) client.settings.set(message.guild.id, {}); 8 | 9 | if (args[0]) { 10 | const joinedValue = args.join(" "); 11 | if (joinedValue === settings.welcomeMessage) return message.channel.send( 12 | "<:error:466995152976871434> The welcome message is already set to that!" 13 | ); 14 | if (!client.settings.has(message.guild.id)) client.settings.set(message.guild.id, {}); 15 | if (joinedValue === "off") { 16 | if (!client.settings.has(message.guild.id)) client.settings.set(message.guild.id, {}); 17 | client.settings.set(message.guild.id, "off", "welcomeMessage"); 18 | return message.channel.send(`<:success:466995111885144095> Welcome messages have been disabled.`); 19 | } 20 | client.settings.set(message.guild.id, joinedValue, "welcomeMessage"); 21 | client.settings.set(message.guild.id, message.channel.id, "welcomeChannel") 22 | message.channel.send(`<:success:466995111885144095> Set the welcome message to \`${joinedValue}\``); 23 | } else { 24 | if (settings.welcomeMessage === "off") { 25 | message.channel.send(`Welcome messages are off.`) 26 | } else { 27 | message.channel.send(`The current welcome message is: \`${settings.welcomeMessage}\``) 28 | } 29 | } 30 | }; 31 | 32 | exports.conf = { 33 | enabled: true, 34 | guildOnly: true, 35 | aliases: [], 36 | permLevel: "Administrator", 37 | requiredPerms: [] 38 | }; 39 | 40 | exports.help = { 41 | name: "welcome", 42 | category: "Configure", 43 | description: "Sets the welcome message for this server. try using [[server]], [[user]] and [[members]] in your message!", 44 | usage: "welcome [message] **OR** welcome off" 45 | }; 46 | -------------------------------------------------------------------------------- /src/commands/woomy.js: -------------------------------------------------------------------------------- 1 | const Discord = require("discord.js") 2 | exports.run = async (client, message) =>{ 3 | message.channel.send("Woomy!") 4 | 5 | const voiceChannel = message.member.voice.channel; 6 | 7 | if (!voiceChannel) return; 8 | if (!voiceChannel.permissionsFor(message.client.user).has('CONNECT')) return; 9 | if (!voiceChannel.permissionsFor(message.client.user).has('SPEAK')) return; 10 | 11 | if (client.music.getGuild(message.guild.id).playing == true || !client.music.getGuild(message.guild.id).queue[0]) return; 12 | 13 | voiceChannel.join() 14 | .then(connection => { 15 | const dispatcher = connection.play(`/home/container/resources/audio/WOOMY.MP3`); 16 | dispatcher.on("finish", end => {voiceChannel.leave()}); 17 | }) 18 | }; 19 | 20 | exports.conf = { 21 | enabled: true, 22 | guildOnly: false, 23 | aliases: [], 24 | permLevel: "User", 25 | requiredPerms: [] 26 | }; 27 | 28 | exports.help = { 29 | name: "woomy", 30 | category: "Fun", 31 | description: "Woomy!", 32 | usage: "woomy" 33 | }; 34 | -------------------------------------------------------------------------------- /src/commands/yoda.js: -------------------------------------------------------------------------------- 1 | 2 | const fetch = require("node-fetch") 3 | exports.run = async (client, message, args) => { 4 | const speech = args.join(' '); 5 | if (!speech) { 6 | return message.channel.send(`<:error:466995152976871434> Please include text for me to convert to yodish. Yes.`) 7 | }; 8 | message.channel.startTyping(); 9 | try{ 10 | fetch(`http://yoda-api.appspot.com/api/v1/yodish?text=${encodeURIComponent(speech.toLowerCase())}`) 11 | .then(res => res.json()) 12 | .then(json => message.channel.send(json.yodish)) 13 | .catch(err => { 14 | message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`); 15 | }); 16 | message.channel.stopTyping(); 17 | } catch(err) { 18 | message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`); 19 | message.channel.stopTyping(); 20 | }; 21 | }; 22 | 23 | exports.conf = { 24 | enabled: true, 25 | guildOnly: false, 26 | aliases: [], 27 | permLevel: "User", 28 | requiredPerms: [] 29 | }; 30 | 31 | exports.help = { 32 | name: "yoda", 33 | category: "Fun", 34 | description: "Turns any text you input into yodish. Yes.", 35 | usage: "yoda " 36 | }; -------------------------------------------------------------------------------- /src/commands/zalgo.js: -------------------------------------------------------------------------------- 1 | const zalgo = require("to-zalgo") 2 | exports.run = async (client, message, args) => { 3 | if(!args[0]) { 4 | return message.channel.send(`<:error:466995152976871434> You didn't provide any text! Usage: \`${client.commands.get(`zalgo`).help.usage}\``) 5 | }; 6 | 7 | var output = zalgo(args.join(" ")) 8 | 9 | if(output.length > 2000) { 10 | output = output.slice(0, -Math.abs(output.length - 2000)) 11 | }; 12 | 13 | message.channel.send(output) 14 | }; 15 | 16 | exports.conf = { 17 | enabled: false, 18 | guildOnly: false, 19 | aliases: [], 20 | permLevel: "User", 21 | requiredPerms: [] 22 | }; 23 | 24 | exports.help = { 25 | name: "zalgo", 26 | category: "Fun", 27 | description: "Spoilers every letter in the provided text.", 28 | usage: "zalgo [text]" 29 | }; 30 | -------------------------------------------------------------------------------- /src/events/error.js: -------------------------------------------------------------------------------- 1 | module.exports = async (client, error) => { 2 | client.logger.log(`d.js err: \n${JSON.stringify(error.stack)}`, "error"); 3 | }; 4 | -------------------------------------------------------------------------------- /src/events/guildCreate.js: -------------------------------------------------------------------------------- 1 | const Discord = require("discord.js"); 2 | module.exports = (client, guild) => { 3 | client.logger.log(`Guild joined.`, "info"); 4 | 5 | client.settings.ensure(guild.id, client.config.defaultSettings); 6 | 7 | if(client.devmode == false) { 8 | channel = client.channels.cache.get("458896120639127552"); 9 | embed = new Discord.MessageEmbed(); 10 | embed.setColor("#F38159"); 11 | embed.setDescription(`Joined a new server with \`${guild.members.cache.size}\` members! I'm now in \`${client.guilds.cache.size}\` servers.`) 12 | channel.send(embed) 13 | }; 14 | }; 15 | 16 | -------------------------------------------------------------------------------- /src/events/guildDelete.js: -------------------------------------------------------------------------------- 1 | const Discord = require('discord.js'); 2 | module.exports = (client, guild) => { 3 | client.logger.log(`Guild left.`, "info"); 4 | 5 | if(client.devmode === true) return; 6 | 7 | if(!guild.available) { 8 | return; 9 | }; 10 | 11 | channel = client.channels.cache.get("458896120639127552"); 12 | embed = new Discord.MessageEmbed(); 13 | embed.setColor("#9494FF"); 14 | embed.setDescription(`Left a server. I'm now in \`${client.guilds.cache.size}\` servers.`) 15 | channel.send(embed) 16 | 17 | if (client.settings.has(guild.id)) { 18 | client.settings.delete(guild.id); 19 | }; 20 | }; 21 | -------------------------------------------------------------------------------- /src/events/guildMemberAdd.js: -------------------------------------------------------------------------------- 1 | module.exports = async (client, member) => { 2 | const settings = client.getSettings(member.guild.id); 3 | 4 | if (settings.welcomeMessage !== "off") { 5 | let chanExists = member.guild.channels.cache.get(settings.welcomeChannel) 6 | if (!chanExists) { 7 | return; 8 | }; 9 | welcomeMessage = settings.welcomeMessage.replace("[[user]]", member.user); 10 | welcomeMessage = welcomeMessage.replace("[[server]]", member.guild.name); 11 | welcomeMessage = welcomeMessage.replace("[[members]]", member.guild.memberCount); 12 | 13 | member.guild.channels 14 | .cache.get(settings.welcomeChannel) 15 | .send(welcomeMessage) 16 | .catch(console.error); 17 | } 18 | 19 | if (settings.autorole !== "off") { 20 | let aRole = member.guild.roles.cache.get(settings.autorole) 21 | if (!aRole) { 22 | return; 23 | }; 24 | await member.roles.add(aRole.id).catch(console.error); 25 | }; 26 | 27 | if(settings.raidMode !== "off") { 28 | if(settings.raidModeStrict == "on") { 29 | member.kick("User bounced.") 30 | 31 | if (settings.chatlogsChannel !== "off") { 32 | const channel = member.guild.channels.cache.find( 33 | channel => channel.name === settings.chatlogsChannel 34 | ); 35 | 36 | if (channel) { 37 | let embed = new Discord.MessageEmbed(); 38 | embed.setColor("#1f1f1f"); 39 | embed.setAuthor("User bounced:", member.user.avatarURL({dynamic: true})); 40 | embed.setDescription(`‏‏‎❯ User: ${member} (${member.user.id})`, true); 41 | embed.setFooter(`New users are being automatically kicked because raidmode is enabled.`) 42 | try { 43 | channel.send(embed); 44 | } catch (err) { 45 | // probably no permissions to send messages/embeds there 46 | }; 47 | }; 48 | return; 49 | } 50 | } 51 | let mRole = member.guild.roles.cache.get(settings.mutedRole) 52 | if (!mRole) { 53 | return; 54 | }; 55 | await member.roles.add(mRole.id).catch(console.error); 56 | if (settings.chatlogsChannel !== "off") { 57 | const channel = member.guild.channels.cache.find( 58 | channel => channel.name === settings.chatlogsChannel 59 | ); 60 | 61 | if (channel) { 62 | let embed = new Discord.MessageEmbed(); 63 | embed.setColor("#1f1f1f"); 64 | embed.setAuthor("User automatically muted:", member.user.avatarURL({dynamic: true})); 65 | embed.setDescription(`‏‏‎❯ User: ${member} (${member.user.id})`, true); 66 | embed.setFooter(`New users are being automatically muted because raidmode is enabled.`) 67 | try { 68 | channel.send(embed); 69 | } catch (err) { 70 | // probably no permissions to send messages/embeds there 71 | }; 72 | }; 73 | }; 74 | }; 75 | 76 | if (settings.chatlogsChannel !== "off") { 77 | const channel = member.guild.channels.cache.find( 78 | channel => channel.name === settings.chatlogsChannel 79 | ); 80 | 81 | if (channel) { 82 | let embed = new Discord.MessageEmbed(); 83 | embed.setColor("#0099e1"); 84 | embed.setAuthor("User joined:", member.user.avatarURL({dynamic: true})); 85 | embed.setDescription(`‏‏‎❯ User: ${member} (${member.user.id})`, true); 86 | try { 87 | channel.send({ embed }); 88 | } catch (err) { 89 | // probably no permissions to send messages/embeds there 90 | }; 91 | }; 92 | }; 93 | 94 | }; 95 | -------------------------------------------------------------------------------- /src/events/guildMemberRemove.js: -------------------------------------------------------------------------------- 1 | module.exports = async (client, member) => { 2 | const settings = client.getSettings(member.guild.id); 3 | 4 | if (settings.leaveMessage !== "off") { 5 | let chanExists = member.guild.channels.cache.get(settings.welcomeChannel) 6 | if (!chanExists) { 7 | return; 8 | }; 9 | leaveMessage = settings.leaveMessage.replace("[[user]]", member.user); 10 | leaveMessage = leaveMessage.replace("[[server]]", member.guild.name); 11 | leaveMessage = leaveMessage.replace("[[members]]", member.guild.memberCount); 12 | 13 | member.guild.channels 14 | .cache.get(settings.welcomeChannel) 15 | .send(leaveMessage) 16 | .catch(console.error); 17 | }; 18 | 19 | if (settings.chatlogsChannel !== "off") { 20 | const channel = member.guild.channels.cache.find( 21 | channel => channel.name === settings.chatlogsChannel 22 | ); 23 | 24 | if (channel) { 25 | let embed = new Discord.MessageEmbed(); 26 | embed.setColor("#006798"); 27 | embed.setAuthor("User left:", member.user.avatarURL({dynamic: true})); 28 | embed.setDescription(`‏‏‎❯ ${member.user.tag} (${member.user.id})`, true); 29 | try { 30 | channel.send({ embed }); 31 | } catch (err) { 32 | // probably no permissions to send messages/embeds there 33 | }; 34 | }; 35 | }; 36 | }; 37 | -------------------------------------------------------------------------------- /src/events/messageDelete.js: -------------------------------------------------------------------------------- 1 | const Discord = require("discord.js"); 2 | 3 | module.exports = (client, message) => { 4 | if (message.author.bot) return; 5 | 6 | if(!message.guild) return; 7 | 8 | const settings = (message.settings = client.getSettings(message.guild.id)); 9 | 10 | if (settings.chatlogsChannel !== "off") { 11 | const channel = message.guild.channels.cache.find( 12 | channel => channel.name === settings.chatlogsChannel 13 | ) 14 | 15 | var msg = message.content; 16 | 17 | if(!message.member) { 18 | return; 19 | } 20 | 21 | if(msg.length + message.member.user.username.length + message.member.user.id.length + message.channel.name.length + 2 > 2048) { 22 | return; 23 | } 24 | 25 | if (channel) { 26 | let embed = new Discord.MessageEmbed(); 27 | embed.setColor("#f93a2f"); 28 | embed.setAuthor("Message deleted!", message.member.user.avatarURL({dynamic: true})); 29 | if (msg == "") { 30 | msg = "**An image was deleted, but is not shown for privacy reasons.**" 31 | } else { 32 | msg = `\`${msg}\`` 33 | }// image-only; maybe we can add image logging too but depends privacy (if someone sends like personal stuff accidentally) 34 | embed.setDescription(`❯ Author: ${message.member} (${message.member.user.id})\n❯ Channel: ${message.channel}\n❯ Message: ${msg}`) 35 | try { 36 | channel.send({ embed }); 37 | } catch (err) { 38 | // probably no permissions to send messages/embeds there 39 | }; 40 | }; 41 | }; 42 | }; 43 | -------------------------------------------------------------------------------- /src/events/messageUpdate.js: -------------------------------------------------------------------------------- 1 | const Discord = require("discord.js"); 2 | 3 | module.exports = (client, omsg, nmsg) => { 4 | if (nmsg.content === omsg.content) return; 5 | 6 | const settings = (omsg.settings = nmsg.settings = client.getSettings( 7 | nmsg.guild.id 8 | )); 9 | 10 | if (settings.chatlogsChannel !== "off") { 11 | const channel = nmsg.guild.channels.cache.find( 12 | channel => channel.name === settings.chatlogsChannel 13 | ); 14 | 15 | if (channel) { 16 | if (!nmsg.member) return; 17 | let embed = new Discord.MessageEmbed(); 18 | embed.setColor("#fff937"); 19 | embed.setAuthor("Message Edited!", nmsg.member.user.avatarURL({dynamic: true})); 20 | if (omsg.content == "") { 21 | omsg.content = "**[IMAGE]**" 22 | } else if (nmsg.content == "") { 23 | nmsg.content = `**[IMAGE]**` 24 | } else { 25 | omsg.content = `\`${omsg.content}\`` 26 | nmsg.content = `\`${nmsg.content}\`` 27 | } 28 | 29 | if(omsg.content.length + nmsg.content.length + nmsg.member.user.username.length + nmsg.member.user.id.length + nmsg.channel.name.length + 2 > 2048) { 30 | return; 31 | } 32 | 33 | embed.setDescription(`[Jump to message](https://discord.com/channels/${nmsg.guild.id}/${nmsg.channel.id}/${nmsg.id})\n• Author: ${nmsg.member} (${nmsg.member.user.id})\n• Channel: ${nmsg.channel}\n• Old message: ${omsg.content}\n• New message: ${nmsg.content}`) 34 | try { 35 | channel.send({ embed }); 36 | } catch (err) { 37 | // probably no permissions to send messages/embeds there 38 | }; 39 | }; 40 | }; 41 | }; 42 | -------------------------------------------------------------------------------- /src/events/ready.js: -------------------------------------------------------------------------------- 1 | const moment = require("moment"); 2 | module.exports = client => { 3 | 4 | const timestamp = `${moment().format("YYYY-MM-DD HH:mm:ss")}`; 5 | const activityArray = client.commands.keyArray(); 6 | 7 | client.lockActivity = false; 8 | 9 | let guild, channel, channel1; 10 | 11 | if(client.config.loggingServer.length > 0) { 12 | try { 13 | guild = client.guilds.cache.get(client.config.loggingServer) 14 | } catch(err) { 15 | client.logger.error("Could not find loggingServer server (is the ID valid?):\n" + err); 16 | process.exit(1); 17 | }; 18 | 19 | if(client.config.consoleLogs.length > 0) { 20 | try { 21 | channel1 = guild.channels.cache.get(client.config.consoleLogs) 22 | } catch(err) { 23 | client.logger.error("Could not find consoleLogs channel (is the ID valid?):\n" + err); 24 | process.exit(1); 25 | }; 26 | }; 27 | 28 | if(client.config.startupLogs.length > 0) { 29 | try { 30 | channel = guild.channels.cache.get(client.config.startupLogs) 31 | } catch(err) { 32 | client.logger.error("Could not find startupLogs channel (is the ID valid?):\n" + err); 33 | process.exit(1); 34 | }; 35 | }; 36 | }; 37 | 38 | if(client.devmode == true) { 39 | client.logger.warn("Running in development mode.") 40 | prefix = client.config.defaultSettings.devprefix; 41 | } else { 42 | prefix = client.config.defaultSettings.prefix; 43 | if(channel) { 44 | channel.send(`Bot started at \`${timestamp}\``); 45 | }; 46 | }; 47 | 48 | let randomActivity = activityArray.random(); 49 | 50 | client.user.setActivity(`${prefix + randomActivity} | v${client.version.number}`, {type: "PLAYING"}); 51 | 52 | setInterval(() => { 53 | randomActivity = activityArray.random(); 54 | if(client.lockActivity == false) { 55 | client.user.setActivity(`${prefix + randomActivity} | v${client.version.number}`, {type: "PLAYING"}); 56 | }; 57 | }, 30000); 58 | 59 | client.logger.log(`Connected to Discord as ${client.user.tag} | v${client.version.number}`, 'ready'); 60 | }; 61 | -------------------------------------------------------------------------------- /src/events/voiceStateUpdate.js: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Emily J. / mudkipscience and contributors. Subject to the AGPLv3 license. 2 | 3 | const music = require('../modules/music') 4 | 5 | module.exports = (client, oldState, newState) => { 6 | if (newState.channelID !== oldState.channelID) { 7 | const guild = music.getGuild(newState.guild.id) 8 | 9 | // Reset queue, dispatcher, etc if Woomy is forcibly disconnected from the queue 10 | if (guild.voiceChannel && !guild.voiceChannel.members.get(client.user.id) && guild.queue.length > 0) { 11 | guild.queue = [] 12 | guild.playing = false 13 | guild.paused = false 14 | guild.skippers = [] 15 | } 16 | 17 | // Auto-disconnect feature 18 | if (guild.playing && guild.voiceChannel && guild.voiceChannel.id === oldState.channelID) { 19 | if (guild.voiceChannel.members.filter(member => !member.user.bot).size < 1) { 20 | guild.message.channel.send('Everyone has left my voice channel, the music will end in two minutes if no one rejoins.') 21 | .then(msg => { 22 | msg.delete({ timeout: 120000 }) 23 | }) 24 | 25 | setTimeout(() => { 26 | if (guild.dispatcher !== null && guild.voiceChannel.members.filter(member => !member.user.bot).size < 1) { 27 | // Probably should be async? But no need here I think 28 | guild.dispatcher.end('silent') 29 | 30 | guild.queue = [] 31 | guild.playing = false 32 | guild.paused = false 33 | guild.dispatcher = null 34 | guild.skippers = [] 35 | 36 | guild.message.channel.send('The music has ended because no one was listening to me ;~;') 37 | } 38 | }, 120000) 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/modules/Logger.js: -------------------------------------------------------------------------------- 1 | const chalk = require("chalk"); 2 | const moment = require("moment"); 3 | 4 | exports.log = (content, type = "log") => { 5 | const timestamp = `[${moment().format("YYYY-MM-DD HH:mm:ss")}]`; 6 | 7 | let channel; 8 | 9 | try { 10 | channel = client.guilds.cache.get(client.config.loggingServer).channels.cache.get(client.config.consoleLogs); 11 | } catch(err) {}; 12 | 13 | var logToServer = false; 14 | 15 | if(client.devmode === false && channel && client.guilds.cache.get(client.config.loggingServer).available) { 16 | logToServer = true; 17 | }; 18 | 19 | switch (type) { 20 | case "info": { 21 | try { 22 | if (logToServer == true) { 23 | channel.send(`\`${timestamp}\` \`[${type.toUpperCase()}]\` ` + content); 24 | }; 25 | } catch(err) {}; 26 | return console.log(`${timestamp} ${chalk.cyanBright(`[${type.toUpperCase()}]`)} ${content} `); 27 | }; 28 | 29 | case "warn": { 30 | try { 31 | if (logToServer == true) { 32 | channel.send(`\`${timestamp}\` \`[${type.toUpperCase()}]\` ` + content); 33 | }; 34 | } catch(err) {}; 35 | return console.log(`${timestamp} ${chalk.yellowBright(`[${type.toUpperCase()}]`)} ${content} `); 36 | }; 37 | 38 | case "error": { 39 | try { 40 | if (logToServer == true) { 41 | channel.send(`\`${timestamp}\` \`[${type.toUpperCase()}]\` ` + content); 42 | }; 43 | } catch(err) {} 44 | return console.log(`${timestamp} ${chalk.redBright(`[${type.toUpperCase()}]`)} ${content} `); 45 | }; 46 | 47 | case "debug": { 48 | try { 49 | if (logToServer == true) { 50 | channel.send(`\`${timestamp}\` \`[${type.toUpperCase()}]\` ` + content); 51 | }; 52 | } catch(err) {}; 53 | return console.log(`${timestamp} ${chalk.magentaBright(`[${type.toUpperCase()}]`)} ${content} `); 54 | }; 55 | 56 | case "cmd": { 57 | try { 58 | if (logToServer == true) { 59 | channel.send(`\`${timestamp}\` \`[${type.toUpperCase()}]\` ` + content); 60 | }; 61 | } catch(err) {}; 62 | return console.log(`${timestamp} ${chalk.whiteBright(`[${type.toUpperCase()}]`)} ${content}`); 63 | }; 64 | 65 | case "ready": { 66 | try { 67 | if (logToServer == true) { 68 | channel.send(`\`${timestamp}\` \`[${type.toUpperCase()}]\` ` + content); 69 | }; 70 | } catch(err) {}; 71 | return console.log(`${timestamp} ${chalk.greenBright (`[${type.toUpperCase()}]`)} ${content}`); 72 | }; 73 | 74 | default: throw new TypeError("Logger type must be either warn, debug, info, ready, cmd or error."); 75 | }; 76 | }; 77 | 78 | exports.error = (...args) => this.log(...args, "error"); 79 | 80 | exports.warn = (...args) => this.log(...args, "warn"); 81 | 82 | exports.debug = (...args) => this.log(...args, "debug"); 83 | 84 | exports.info = (...args) => this.log(...args, "info"); 85 | 86 | exports.cmd = (...args) => this.log(...args, "cmd"); 87 | 88 | exports.setClient = function(c) { 89 | client = c; 90 | }; 91 | -------------------------------------------------------------------------------- /version.json: -------------------------------------------------------------------------------- 1 | { 2 | "number": "1.4.6", 3 | "changelog": "**1.4 Changelog**\n> • Splatoon commands have been added! check current and upcoming maps and modes with `~splatoonmaps`, current and upcoming salmon run maps, weapons and reward gear with `~salmonrun` and see what gear is on offer in the splatnet shop with `~splatnet`!\n**Notes:**\n> • Music is still broken and likely will be until v2 is released. Fixing v1 would delay v2 a lot, sorry >.<" 4 | } --------------------------------------------------------------------------------