├── CONTRIBUTING.md ├── .gitattributes ├── .eslintrc.js ├── .env ├── config.json ├── LICENSE ├── package.json ├── src ├── events │ └── message.js ├── commands │ ├── mod │ │ ├── addRole.js │ │ ├── removeRole.js │ │ ├── clear.js │ │ ├── ban.js │ │ ├── kick.js │ │ ├── announce.js │ │ ├── poll.js │ │ ├── mute.js │ │ ├── unmute.js │ │ ├── lock.js │ │ └── ticket.js │ └── public │ │ ├── avatar.js │ │ ├── meme.js │ │ ├── youtube.js │ │ └── info.js └── [TEMPLATE].js ├── changelog.md ├── .gitignore ├── main.js ├── readme.md └── CODE_OF_CONDUCT.md /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | commonjs: true, 4 | es6: true, 5 | node: true 6 | }, 7 | extends: [ 8 | 'standard' 9 | ], 10 | globals: { 11 | Atomics: 'readonly', 12 | SharedArrayBuffer: 'readonly' 13 | }, 14 | parserOptions: { 15 | ecmaVersion: 2018 16 | }, 17 | rules: { 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | PREFIX=z! 2 | OWNER=Owner's Discord goes here 3 | DISCORD=Owner's Discord goes here 4 | COLOUR=0x4B0082 5 | 6 | TOKEN=Token goes here 7 | YOUTUBEAPI=Youtube API goes here 8 | 9 | MODERATION=Moderation channel name goes here 10 | EVENTS=Events channel name goes here 11 | WELCOME_CHANNEL=Events channel name goes here 12 | 13 | RULES=Rules channel name goes here! 14 | -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "prefix": "z!", 3 | "owner": "Owner ID goes here", 4 | "discord": "Owner's Discord goes here", 5 | "colour": "0x4B0082", 6 | "env": { 7 | "TOKEN": "", 8 | "youtubeAPI": "Youtube API goes here" 9 | }, 10 | "log_channels": { 11 | "moderation": "Moderation channel name goes here", 12 | "events": "Events channel name goes here", 13 | "welcome_channel": "Events channel name goes here" 14 | }, 15 | "info_channels": { 16 | "rules": "Rules channel name goes here!" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 nukestye™ 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "zodiac-bot", 3 | "version": "0.3.2", 4 | "description": "Moderation discord bot.", 5 | "main": "main.js", 6 | "dependencies": { 7 | "@discordjs/uws": "^11.149.1", 8 | "axios": "^0.21.1", 9 | "chalk": "^4.1.0", 10 | "discord.js": "^12.5.1", 11 | "discord.js-commando": "^0.10.0", 12 | "path": "^0.12.7", 13 | "snekfetch": "^4.0.4" 14 | }, 15 | "devDependencies": { 16 | "eslint": "^7.17.0", 17 | "eslint-config-standard": "^16.0.2", 18 | "eslint-plugin-import": "^2.22.1", 19 | "eslint-plugin-node": "^11.1.0", 20 | "eslint-plugin-promise": "^4.2.1", 21 | "eslint-plugin-standard": "^5.0.0" 22 | }, 23 | "scripts": { 24 | "test": "echo \"Error: no test specified\" && exit 1" 25 | }, 26 | "repository": { 27 | "type": "git", 28 | "url": "git+https://github.com/Nukestye/Zodiac.git" 29 | }, 30 | "author": "nukestye™", 31 | "license": "MIT", 32 | "bugs": { 33 | "url": "https://github.com/Nukestye/Zodiac/issues" 34 | }, 35 | "homepage": "https://github.com/Nukestye/Zodiact#readme" 36 | } -------------------------------------------------------------------------------- /src/events/message.js: -------------------------------------------------------------------------------- 1 | const Discord = require('discord.js'); 2 | const fs = require('fs'); 3 | const Path = require('path'); 4 | const config = require("../../config.json"); 5 | const chalk = require("chalk"); 6 | 7 | 8 | module.exports = { 9 | run: async (message) => { 10 | let guild = message.guild; 11 | const reportchannel = guild.channels.find(x => x.name === config.log_channels.events); // Unknown Issue happens here for some reason - Issue #001 12 | if(message.channel.id === reportchannel.id) return; 13 | if(!reportchannel) return console.error(chalk.red("[!] Event Channel cannot be found!")); 14 | 15 | 16 | let messageEmbed = new Discord.RichEmbed() 17 | .setTitle(message.author.tag, message.author.displayAvatarURL) 18 | .setColor(config.colour) 19 | .setDescription(`${message.author.tag} has sent a [message](${message.url}) in ${message.channel}.`) 20 | .addField("Channel", `${message.channel}`, true) 21 | .addField("ID", `\`\`\`excel\nUser = ${message.author.id}\nMessage = ${message.id}\`\`\``, true) 22 | .addField("Content", message.embeds == "" ? message.content : `[Embed Link](${message.url})`) 23 | .setFooter(`Zodiac | by nukestye`); 24 | 25 | 26 | reportchannel.send(messageEmbed); 27 | 28 | 29 | // console.log(`${reportchannel.name}\n${message.channel.name}`); 30 | // message.embeds == "" ? console.log(message.content) : console.log(message.url) 31 | 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [Unreleased] 8 | - AutoMod 9 | - Bot Config 10 | 11 | ## 0.3.3 - 25/05/202 12 | 13 | ### Removed 14 | - Events 15 | 16 | ## 0.3.2 - 24/05/2020 17 | ### Added 18 | - Issue #6 fixed 19 | - eslint code style 20 | 21 | ## 0.3.1 - 23/05/2020 22 | ### Added 23 | - Detailed explaintion in readme.md 24 | 25 | 26 | ## 0.3.0 - 05/05/2020 27 | ### Added 28 | - `youtube`, search Youtube. 29 | - TODO list is updated. 30 | 31 | ### Removed 32 | - *Changed quote format.* 33 | 34 | 35 | ## 0.2.0 - 19/04/2020 36 | --- 37 | ### Added 38 | > Project Public! 39 | 40 | ### Removed 41 | > Bot Information! 42 | 43 | ## 0.1.0 - 15/04/2020 44 | ### Added 45 | > Main files 46 | 47 | - `config` 48 | - `main` 49 | - `changelog.md` 50 | - `Procfile` 51 | 52 | 53 | > Moderation Commands 54 | 55 | - `announce` 56 | - `ban` 57 | - `clear` 58 | - `kick` 59 | - `mute` 60 | - `unmute` 61 | - `ticket` 62 | - `poll` 63 | - `addrole` 64 | - `removerole` 65 | - `lock` 66 | 67 | > Public Commands 68 | 69 | - `avatar` 70 | - `info` 71 | - `meme` 72 | 73 | > Events 74 | 75 | - `GuildMemberAdd` 76 | - `GuildMemberRemove` 77 | - `Message` 78 | - `MessageRemove` 79 | - `MessageUpdate` 80 | - `Role` 81 | - `RoleRemove` 82 | - `RoleUpdate` 83 | 84 | > Other Files 85 | 86 | - `Command Template file` 87 | - `Images` 88 | - `Welcome Gifs(2)` 89 | - `Member Join emoji` 90 | - `Member Leave emoji` 91 | 92 | 93 | ### Removed 94 | - `start.bat` 95 | 96 | 97 | [//]: # 'Author: nukestye' 98 | [//]: # 'Contributors: nukestye' 99 | -------------------------------------------------------------------------------- /src/commands/mod/addRole.js: -------------------------------------------------------------------------------- 1 | // Getting the 'Command' features from Commando 2 | const { Command } = require('discord.js-commando') 3 | 4 | // Code for the command 5 | module.exports = class addRoleCommand extends Command { 6 | constructor (client) { 7 | super(client, { 8 | // name of the command, must be in lowercase 9 | name: 'addrole', 10 | // other ways to call the command, must be in lowercase 11 | aliases: ['role'], 12 | // command group its part of 13 | group: 'mod', 14 | // name within the command group, must be in lowercase 15 | memberName: 'addrole', 16 | // Is the description used for 'help' command 17 | description: 'Adds mentioned role to mentioned user.', 18 | // Prevents it from being used in dms 19 | guildOnly: true, 20 | // Permissions, list found here > `discord.js.org/#/docs/main/11.5.1/class/Permissions?scrollTo=s-FLAGS` 21 | clientPermissions: ['ADMINISTRATOR', 'MANAGE_ROLES'], 22 | userPermissions: ['MANAGE_ROLES'], 23 | // Prevents anyone other than owner to use the command 24 | ownerOnly: false 25 | }) 26 | } 27 | 28 | // Run code goes here 29 | run (message) { 30 | const user = message.mentions.members.first() 31 | const roleToAdd = message.mentions.roles.first() 32 | 33 | // checking to see if the user has the role or not 34 | if (!(user.roles.find(r => r.name === roleToAdd.name))) { 35 | user.addRole(roleToAdd) 36 | message.channel.send(`${user} has been given the role: ${roleToAdd.name}`) 37 | .then(msg => { 38 | msg.delete(5000) 39 | }) 40 | } else { 41 | message.channel.send(`${user} already has the role: ${roleToAdd.name}`) 42 | } 43 | 44 | // console.error(user, roleToAdd, message.member.roles.find(r => r.name === roleToAdd)); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/commands/mod/removeRole.js: -------------------------------------------------------------------------------- 1 | // Getting the 'Command' features from Commando 2 | const { Command } = require('discord.js-commando') 3 | 4 | // Code for the command 5 | module.exports = class newCommand extends Command { 6 | constructor (client) { 7 | super(client, { 8 | // name of the command, must be in lowercase 9 | name: 'removerole', 10 | // other ways to call the command, must be in lowercase 11 | aliases: ['rrole', 'deleterole'], 12 | // command group its part of 13 | group: 'mod', 14 | // name within the command group, must be in lowercase 15 | memberName: 'removerole', 16 | // Is the description used for 'help' command 17 | description: 'Removes mentioned role from mentioned user.', 18 | // adds cooldowns to the command 19 | throttling: { 20 | // usages in certain time x 21 | usages: 1, 22 | // the cooldown 23 | duration: 10 24 | }, 25 | // Prevents it from being used in dms 26 | guildOnly: true, 27 | // Permissions, list found here > `discord.js.org/#/docs/main/11.5.1/class/Permissions?scrollTo=s-FLAGS` 28 | clientPermissions: ['ADMINISTRATOR', 'MANAGE_ROLES'], 29 | userPermissions: ['MANAGE_ROLES'], 30 | // Prevents anyone other than owner to use the command 31 | ownerOnly: false 32 | }) 33 | } 34 | 35 | // Run code goes here 36 | run (message, { text }) { 37 | const user = message.mentions.members.first() 38 | const role = message.mentions.roles.first() 39 | 40 | // checking to see if the user has the role or not 41 | if ((user.roles.find(r => r.name === role.name))) { 42 | user.removeRole(role) 43 | message.channel.send(`Removed ${role.name} from ${user}`) 44 | .then(msg => { 45 | msg.delete(5000) 46 | }) 47 | } else { 48 | message.channel.send(`${user} does not have ${role.name} role!`) 49 | } 50 | 51 | // console.error(user, roleToAdd, message.member.roles.find(r => r.name === roleToAdd)); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | -------------------------------------------------------------------------------- /src/commands/public/avatar.js: -------------------------------------------------------------------------------- 1 | // Getting the 'Command' features from Commando 2 | const { Command } = require('discord.js-commando') 3 | const config = require('../../../config.json') 4 | const Discord = require('discord.js') 5 | 6 | // Code for the command 7 | module.exports = class avatarCommand extends Command { 8 | constructor (client) { 9 | super(client, { 10 | // name of the command, must be in lowercase 11 | name: 'avatar', 12 | // other ways to call the command, must be in lowercase 13 | aliases: ['pfp'], 14 | // command group its part of 15 | group: 'public', 16 | // name within the command group, must be in lowercase 17 | memberName: 'avatar', 18 | // Is the description used for 'help' command 19 | description: 'Shows Profile Picture of mentioned user or themselves.', 20 | // adds cooldowns to the command 21 | throttling: { 22 | // usages in certain time x 23 | usages: 1, 24 | // the cooldown 25 | duration: 10 26 | }, 27 | // Prevents it from being used in dms 28 | guildOnly: true, 29 | // Permissions, list found here > `discord.js.org/#/docs/main/11.5.1/class/Permissions?scrollTo=s-FLAGS` 30 | clientPermissions: ['ADMINISTRATOR'], 31 | userPermissions: ['SEND_MESSAGES'], 32 | // Prevents anyone other than owner to use the command 33 | ownerOnly: false 34 | }) 35 | } 36 | 37 | // Run code goes here 38 | run (message) { 39 | const messageArry = message.content.split(' ') 40 | const args = messageArry.slice(1) 41 | let user = [] 42 | if (args === '') { 43 | user = message.author 44 | console.log('No args in message') 45 | } else { 46 | user = message.mentions.users.first() 47 | console.log('args in message') 48 | } 49 | 50 | const avatarEmebd = new Discord.RichEmbed() 51 | .setAuthor(`${message.author.username}`, `${message.author.displayAvatarURL}`) 52 | .setColor(config.colour) 53 | .setDescription(`[${user}'s Avatar](${user.displayAvatarURL})`) 54 | .setImage(user.displayAvatarURL) 55 | 56 | message.channel.send(avatarEmebd) 57 | // console.log(message.author); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/[TEMPLATE].js: -------------------------------------------------------------------------------- 1 | // Getting the "Command" features from Commando 2 | const { Command } = require('discord.js-commando') 3 | 4 | // Code for the command 5 | module.exports = class newCommand extends Command { 6 | constructor (client) { 7 | super(client, { 8 | // name of the command, must be in lowercase 9 | name: 'newname', 10 | // other ways to call the command, must be in lowercase 11 | aliases: ['alias1', 'alias2'], 12 | // command group its part of 13 | group: 'mod', 14 | // name within the command group, must be in lowercase 15 | memberName: 'newcommand', 16 | // Is the description used for "help" command 17 | description: 'Description for the new Command', 18 | // adds cooldowns to the command 19 | throttling: { 20 | // usages in certain time x 21 | usages: 1, 22 | // the cooldown 23 | duration: 10 24 | }, 25 | // Prevents it from being used in dms 26 | guildOnly: true, 27 | // Permissions, list found here > `discord.js.org/#/docs/main/11.5.1/class/Permissions?scrollTo=s-FLAGS` 28 | clientPermissions: ['ADMINISTRATOR'], 29 | userPermissions: ['MANAGE_MESSAGES'], 30 | // Prevents anyone other than owner to use the command 31 | ownerOnly: true, 32 | // Taking input from user 33 | args: [ 34 | // < 35 | { 36 | // name of the argument/variable 37 | key: 'text', 38 | // a prompt asking the user 39 | prompt: 'Enter the text', 40 | // the data type of the argument/variable 41 | type: 'string' 42 | // default value if nothing is entered 43 | // default: "hello", 44 | // check if the argument/variable matchs or not 45 | // validate: text => /* check here */text.length < 201, 46 | // Forces to be one of the options 47 | // oneOf:["nothing","nothing2", "hello"], 48 | } 49 | // > Part of one argument/variable 50 | ] 51 | }) 52 | } 53 | 54 | // Run code goes here 55 | run (message, { text }) { 56 | // interact with client(bot) using "this.client" 57 | // console.log(this.client); 58 | // "message.say" is the same as "message.channel.send" in commando 59 | return message.reply(text) 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/commands/mod/clear.js: -------------------------------------------------------------------------------- 1 | // Getting the 'Command' features from Commando 2 | const { Command } = require('discord.js-commando') 3 | 4 | // Code for the command 5 | module.exports = class clearCommand extends Command { 6 | constructor (client) { 7 | super(client, { 8 | // name of the command, must be in lowercase 9 | name: 'clear', 10 | // other ways to call the command, must be in lowercase 11 | aliases: ['purge', 'cls'], 12 | // command group its part of 13 | group: 'mod', 14 | // name within the command group, must be in lowercase 15 | memberName: 'clear', 16 | // Is the description used for 'help' command 17 | description: 'Clears x number of messages in mentioned channel', 18 | // adds cooldowns to the command 19 | throttling: { 20 | // usages in certain time x 21 | usages: 1, 22 | // the cooldown 23 | duration: 10 24 | }, 25 | // Prevents it from being used in dms 26 | guildOnly: true, 27 | // Permissions, list found here > `discord.js.org/#/docs/main/11.5.1/class/Permissions?scrollTo=s-FLAGS` 28 | clientPermissions: ['ADMINISTRATOR'], 29 | userPermissions: ['MANAGE_MESSAGES'], 30 | // Prevents anyone other than owner to use the command 31 | ownerOnly: false, 32 | // Taking input from user 33 | args: [ 34 | // < 35 | { 36 | // name of the argument/variable 37 | key: 'x', 38 | // a prompt asking the user 39 | prompt: 'Enter the number of message to be cleared: ', 40 | // the data type of the argument/variable 41 | type: 'integer', 42 | // default value if nothing is entered 43 | // default: 'hello', 44 | // check if the argument/variable matchs or not 45 | validate: x => x >= 2 <= 100 46 | // Forces to be one of the options 47 | // oneOf:['nothing','nothing2', 'hello'], 48 | } 49 | // > Part of one argument/variable 50 | ] 51 | }) 52 | } 53 | 54 | // Run code goes here 55 | run (message, { x }) { 56 | message.channel.bulkDelete(x) 57 | .catch(err => { 58 | console.error(err) 59 | message.channel.send('There was an error trying to prune messages in this channel!') 60 | }) 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/commands/public/meme.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-constant-condition */ 2 | /* eslint-disable no-self-compare */ 3 | // Getting the 'Command' features from Commando 4 | const { Command } = require('discord.js-commando') 5 | const snekfetch = require('snekfetch') 6 | 7 | // Code for the command 8 | module.exports = class memeCommand extends Command { 9 | constructor (client) { 10 | super(client, { 11 | // name of the command, must be in lowercase 12 | name: 'meme', 13 | // command group its part of 14 | group: 'public', 15 | // name within the command group, must be in lowercase 16 | memberName: 'meme', 17 | // Is the description used for 'help' command 18 | description: 'Generates a meme from r/dankmemes', 19 | // adds cooldowns to the command 20 | throttling: { 21 | // usages in certain time x 22 | usages: 1, 23 | // the cooldown 24 | duration: 10 25 | }, 26 | // Prevents it from being used in dms 27 | guildOnly: true, 28 | // Permissions, list found here > `discord.js.org/#/docs/main/11.5.1/class/Permissions?scrollTo=s-FLAGS` 29 | clientPermissions: ['ADMINISTRATOR'], 30 | userPermissions: ['SEND_MESSAGES'], 31 | // Prevents anyone other than owner to use the command 32 | ownerOnly: false 33 | }) 34 | } 35 | 36 | // Run code goes here 37 | async run (message) { 38 | const filters = { 39 | image: post => post.data.post_hint === 'image', 40 | text: post => !post.data.post_hint !== 'image' && post.data.selftext.length <= 2000 && post.data.title.length <= 256 41 | } 42 | 43 | const res = await snekfetch 44 | .get('https://www.reddit.com/r/dankmemes/top/.json?sort=top&t=day&limit=500') 45 | 46 | const posts = res.body.data.children.filter(filters.image) 47 | const randomNum = Math.floor(Math.random() * posts.length) 48 | 49 | const post = posts[randomNum] 50 | 51 | const embed = { 52 | title: post.data.title, 53 | color: 0x4B0082, 54 | url: `https://www.reddit.com${post.data.permalink}`, 55 | image: { url: 'image' === 'image' ? post.data.url : '' }, 56 | footer: { text: `👍 ${post.data.ups} | 💬 ${post.data.num_comments}` } 57 | } 58 | 59 | message.channel.send({ embed: embed }) 60 | // console.log(post) 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * @author: nukestye 4 | * @version: v1 5 | * 6 | */ 7 | /* 8 | * TODO: 9 | * - Add more Public commands. 10 | */ 11 | 12 | const prefix = process.env.PREFIX 13 | const owner = process.env.OWNER 14 | const discord = process.env.DISCORD 15 | const fs = require('fs') 16 | const log = console.log 17 | 18 | // Setting up the way to get commands 19 | const { CommandoClient } = require('discord.js-commando') 20 | const path = require('path') 21 | 22 | // reading events 23 | fs.readdir('./src/events/', (err, files) => { 24 | if (err) return console.error(err) 25 | files.forEach((file) => { 26 | const eventFunction = require(`./src/events/${file}`) 27 | if (eventFunction.disabled) return 28 | const event = eventFunction.event || file.split('.')[0] 29 | const emitter = (typeof eventFunction.emitter === 'string' ? client[eventFunction.emitter] : eventFunction.emitter) || client 30 | const { once } = eventFunction 31 | try { 32 | emitter[once ? 'once' : 'on'](event, (...args) => eventFunction.run(...args)) 33 | } catch (error) { 34 | console.error(error.stack) 35 | } 36 | }) 37 | }) 38 | 39 | const client = global.client = new CommandoClient({ 40 | commandPrefix: `${prefix}`, 41 | owner: `${owner}`, 42 | invite: `${discord}`, 43 | unknownCommandResponse: false 44 | }) 45 | 46 | // Registing the commands 47 | client.registry 48 | .registerDefaultTypes() 49 | // The different fields for cmds 50 | .registerGroups([ 51 | ['mod', 'Moderation Commands'], 52 | ['public', 'Public Commands'] 53 | ]) 54 | .registerDefaultGroups() 55 | // Basic cmds can be disabled like {"cmd: false"} 56 | .registerDefaultCommands() 57 | // commands in "/src/commands" will be counted 58 | .registerCommandsIn(path.join(__dirname, '/src/commands')) 59 | 60 | // list of activities that the bot goes through 61 | const activityArray = [`${prefix}help | `] 62 | // Bot lanuch code 63 | client.once('ready', () => { 64 | log(`Logged in as ${client.user.tag} in ${client.guilds.size} guild(s)!`) 65 | setInterval(() => { 66 | const index = Math.floor(Math.random() * (activityArray.length)) // generates a random number between 1 and the length of the activities array list 67 | client.user.setActivity( 68 | activityArray[index], 69 | { 70 | type: 'PLAYING' 71 | }) // sets bot"s activities to one of the phrases in the arraylist. 72 | }, 5000) // updates every 10000ms = 10s 73 | }) 74 | // If an error print it out 75 | client.on('error', console.error) 76 | 77 | // Login in using the token in config 78 | client.login(process.env.TOKEN) 79 | -------------------------------------------------------------------------------- /src/commands/mod/ban.js: -------------------------------------------------------------------------------- 1 | // Getting the 'Command' features from Commando 2 | const { Command } = require('discord.js-commando') 3 | const { RichEmbed } = require('discord.js') 4 | const log = console.log 5 | const chalk = require('chalk') 6 | 7 | // Code for the command 8 | module.exports = class banCommand extends Command { 9 | constructor (client) { 10 | super(client, { 11 | // name of the command, must be in lowercase 12 | name: 'ban', 13 | // other ways to call the command, must be in lowercase 14 | aliases: ['ban', 'permban'], 15 | // command group its part of 16 | group: 'mod', 17 | // name within the command group, must be in lowercase 18 | memberName: 'ban', 19 | // Is the description used for 'help' command 20 | description: 'Ban command', 21 | // adds cooldowns to the command 22 | throttling: { 23 | // usages in certain time x 24 | usages: 1, 25 | // the cooldown 26 | duration: 10 27 | }, 28 | // Prevents it from being used in dms 29 | guildOnly: true, 30 | // Permissions, list found here > `discord.js.org/#/docs/main/11.5.1/class/Permissions?scrollTo=s-FLAGS` 31 | clientPermissions: ['ADMINISTRATOR'], 32 | userPermissions: ['BAN_MEMBERS'], 33 | // Prevents anyone other than owner to use the command 34 | ownerOnly: false 35 | }) 36 | } 37 | 38 | // Run code goes here 39 | run (message) { 40 | const messageArry = message.content.split(' ') 41 | const args = messageArry.slice(1) 42 | 43 | const bUser = message.guild.member(message.mentions.users.first() || message.guild.get(args[0])) 44 | if (!bUser) return message.channel.send('User cannot be found!') 45 | const breason = args.join(' ').slice(22) 46 | 47 | // setting up the embed for report/log 48 | const banEmbed = new RichEmbed() 49 | .setDescription(`Report: ${bUser} BAN`) 50 | .addField('Reason >', `${breason}`) 51 | .addField('Time', message.createdAt) 52 | 53 | const reportchannel = message.guild.channels.find('name', 'report') 54 | if (!reportchannel) return message.channel.send('*`Report channel cannot be found!`*') 55 | 56 | // Delete the message command 57 | // eslint-disable-next-line camelcase 58 | message.delete().catch(O_o => {}) 59 | // Kick the user with reason 60 | message.guild.member(bUser).ban(breason) 61 | // sends the ban report into log/report 62 | reportchannel.send(banEmbed) 63 | // Logs the ban into the terminal 64 | log(chalk.red('BAN', chalk.underline.bgBlue(bUser) + '!')) 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/commands/mod/kick.js: -------------------------------------------------------------------------------- 1 | // Getting the 'Command' features from Commando 2 | const { Command } = require('discord.js-commando') 3 | const { RichEmbed } = require('discord.js') 4 | const chalk = require('chalk') 5 | const log = console.log 6 | 7 | // Code for the command 8 | module.exports = class kickCommand extends Command { 9 | constructor (client) { 10 | super(client, { 11 | // name of the command, must be in lowercase 12 | name: 'kick', 13 | // other ways to call the command, must be in lowercase 14 | aliases: ['boot', 'tempban'], 15 | // command group its part of 16 | group: 'mod', 17 | // name within the command group, must be in lowercase 18 | memberName: 'kick', 19 | // Is the description used for 'help' command 20 | description: 'Kick command.', 21 | // adds cooldowns to the command 22 | throttling: { 23 | // usages in certain time x 24 | usages: 1, 25 | // the cooldown 26 | duration: 10 27 | }, 28 | // Prevents it from being used in dms 29 | guildOnly: true, 30 | // Permissions, list found here > `discord.js.org/#/docs/main/11.5.1/class/Permissions?scrollTo=s-FLAGS` 31 | clientPermissions: ['ADMINISTRATOR'], 32 | userPermissions: ['KICK_MEMBERS'], 33 | // Prevents anyone other than owner to use the command 34 | ownerOnly: false 35 | 36 | }) 37 | } 38 | 39 | // Run code goes here 40 | run (message) { 41 | const messageArry = message.content.split(' ') 42 | const args = messageArry.slice(1) 43 | 44 | const kUser = message.guild.member(message.mentions.users.first() || message.guild.get(args[0])) 45 | if (!kUser) return message.channel.send('User cannot be found!') 46 | const kreason = args.join(' ').slice(22) 47 | 48 | // setting up the embed for report/log 49 | const kickEmbed = new RichEmbed() 50 | .setDescription(`Report: ${kUser} Kick`) 51 | .addField('Reason >', `${kreason}`) 52 | .addField('Time', message.createdAt) 53 | 54 | const reportchannel = message.guild.channels.find('name', 'report') 55 | if (!reportchannel) return message.channel.send('*`Report channel cannot be found!`*') 56 | 57 | // Delete the message command 58 | // eslint-disable-next-line camelcase 59 | message.delete().catch(O_o => {}) 60 | // Kick the user with reason 61 | message.guild.member(kUser).kick(kreason) 62 | // sends the kick report into log/report 63 | reportchannel.send(kickEmbed) 64 | // Logs the kick into the terminal 65 | log(chalk.red('KICK', chalk.underline.bgBlue(kUser) + '!')) 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/commands/mod/announce.js: -------------------------------------------------------------------------------- 1 | // Getting the 'Command' features from Commando 2 | const { Command } = require('discord.js-commando') 3 | const { RichEmbed } = require('discord.js') 4 | // Code for the command 5 | module.exports = class announcementCommand extends Command { 6 | constructor (client) { 7 | super(client, { 8 | // name of the command, must be in lowercase 9 | name: 'announce', 10 | // other ways to call the command, must be in lowercase 11 | aliases: ['ann', 'announcement'], 12 | // command group its part of 13 | group: 'mod', 14 | // name within the command group, must be in lowercase 15 | memberName: 'announce', 16 | // Is the description used for 'help' command 17 | description: 'Announcement Command', 18 | // adds cooldowns to the command 19 | throttling: { 20 | // usages in certain time x 21 | usages: 5, 22 | // the cooldown 23 | duration: 30 24 | }, 25 | // Prevents it from being used in dms 26 | guildOnly: true, 27 | // Permissions, list found here > `discord.js.org/#/docs/main/11.5.1/class/Permissions?scrollTo=s-FLAGS` 28 | clientPermissions: ['ADMINISTRATOR'], 29 | userPermissions: ['MANAGE_MESSAGES'], 30 | // Prevents anyone other than owner to use the command 31 | ownerOnly: false 32 | }) 33 | } 34 | 35 | // Run code goes here 36 | run (message) { 37 | // Seprating the message into 'cmd' and 'args' 38 | const messageArry = message.content.split(' ') 39 | const args = messageArry.slice(1) 40 | // Using the args to find the Title and Description 41 | var length = args.length 42 | var pos = args.indexOf('|') 43 | var title = args.slice(1, pos) 44 | var text = args.slice(pos + 1, length) 45 | if (title.length <= 0) { 46 | title = 'Important Announcement: ' 47 | } else { 48 | title = 'Important Announcement: \n' + title.join(' ') 49 | } 50 | console.log(text.length) 51 | console.log(title.length) 52 | if (text.length < 1 && title.length < 1) return message.channel.send('Incorrect Usage!\n`+announce [#Channel] [Title] | [Description]`') 53 | 54 | const embed = new RichEmbed() 55 | .setColor('#4B0082') 56 | .setTitle(title) 57 | .setDescription(`@everyone,\n${text.join(' ')}`) 58 | 59 | const channelq = message.mentions.channels.first() 60 | if (!channelq) return message.channel.send('Incorrect Usage!\n`+announce [#Channel] [Title] | [Description]`') 61 | channelq.send('@everyone') 62 | .then(msg => { 63 | msg.delete({ timeout: 100000 }) 64 | }) 65 | 66 | channelq.send({ embed }) 67 | // eslint-disable-next-line camelcase 68 | message.delete().catch(O_o => {}) 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/commands/mod/poll.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-template-curly-in-string */ 2 | // Getting the 'Command' features from Commando 3 | const { Command } = require('discord.js-commando') 4 | const Discord = require('discord.js') 5 | 6 | // Code for the command 7 | module.exports = class pollCommand extends Command { 8 | constructor (client) { 9 | super(client, { 10 | // name of the command, must be in lowercase 11 | name: 'poll', 12 | // other ways to call the command, must be in lowercase 13 | aliases: ['decide'], 14 | // command group its part of 15 | group: 'mod', 16 | // name within the command group, must be in lowercase 17 | memberName: 'poll', 18 | // Is the description used for 'help' command 19 | description: 'Poll command to get options', 20 | // adds cooldowns to the command 21 | throttling: { 22 | // usages in certain time x 23 | usages: 1, 24 | // the cooldown 25 | duration: 10 26 | }, 27 | // Prevents it from being used in dms 28 | guildOnly: true, 29 | // Permissions, list found here > `discord.js.org/#/docs/main/11.5.1/class/Permissions?scrollTo=s-FLAGS` 30 | clientPermissions: ['ADMINISTRATOR'], 31 | userPermissions: ['MANAGE_MESSAGES'], 32 | // Prevents anyone other than owner to use the command 33 | ownerOnly: false 34 | }) 35 | } 36 | 37 | // Run code goes here 38 | async run (message) { 39 | // using client commands there needs to be 'this.' 40 | // Seprating the message into 'cmd' and 'args' 41 | const messageArry = message.content.split(' ') 42 | const args = messageArry.slice(1) 43 | // Getting the title, text and channel 44 | var length = args.length 45 | var pos = args.indexOf('|') 46 | var title = args.slice(1, pos) 47 | var text = args.slice(pos + 1, length) 48 | if (text.length < 1 && title.length < 1) return message.channel.send('Incorrect Usage!\n`${this.client.commandPrefix}poll [#Channel] [Title] | [Description]`') 49 | const channelq = message.mentions.channels.first() 50 | if (!channelq) return message.channel.send('Incorrect Usage!\n`${this.client.commandPrefix}poll [#Channel] [Title] | [Description]`') 51 | 52 | // setting up the poll emebed 53 | const pollEmebed = new Discord.RichEmbed() 54 | .setTitle(title.join(' ')) 55 | .setColor('#4B0082') 56 | .setDescription('*`' + text.join(' ') + '`*') 57 | 58 | channelq.send('@everyone') 59 | .then(msg => { 60 | msg.delete({ timeout: 100000 }) 61 | }) 62 | channelq.send(pollEmebed) 63 | .then(function (message) { 64 | message.react('👎') 65 | message.react('👍') 66 | }) 67 | // eslint-disable-next-line camelcase 68 | message.delete().catch(O_o => {}) 69 | .then(message.channel.send(`Poll has been posted in ${channelq}!`)) 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ### Zodiac bot 2 | 3 | ![Issues](https://img.shields.io/github/issues/Nukestye/Zodiac?style=for-the-badge&logo=appveyor) 4 | ![License](https://img.shields.io/github/license/Nukestye/Zodiac?style=for-the-badge&logo=appveyor) 5 | ![Version](https://img.shields.io/github/v/release/Nukestye/Zodiac?style=for-the-badge) 6 | 7 | ## Information 8 | **This is my first discord bot, therefore be wary of any issues that may arise from my code. Also, be sure to let me know about those issues.** 9 | 10 | Zodiac Discord Bot is used for mainly moderation. Its current features are as follows: 11 | 12 | | Moderation Commands | Explanation | 13 | |--------------------- |---------------------------------------------------------------------------------------------------- | 14 | | Ban | Bans mentioned user and gives a report to the report channel. | 15 | | Kick | Kicks mentioned user and gives a report to the report channel. | 16 | | Lock | Locks & unlocks the channel to only read-only, Only those who have staff role are allowed to type. | 17 | | Poll | Starts a poll with two options with `@everyone`. | 18 | | Add Role | Adds mentioned role to mentioned user if not assigned. | 19 | | Remove Role | Removes mentioned role from a mentioned user. | 20 | | Ticket System | A way to contact `@Staff` users. Provides a channel where the issue can be discussed. | 21 | | Clear | Clears x number of messages in the channel. | 22 | | Mute & Unmute | Mutes mentioned user if not muted. Unmute mentioned user if muted. | 23 | | Announcement | Makes an announcement in the channel mentioned with a `@everyone`. | 24 | 25 | ###### There are some public commands included, such as Youtube search, memes, avater and info. 26 | 27 | ## Installation 28 | The process of installing and hosting the bot is simple. 29 | ###### Please make sure you have the required Dependencies installed, `npm install` to install any that you do not have. 30 | 31 | #### [Step 1:] 32 | Clone the repo into a new folder, and open command line and type npm install. 33 | 34 | 35 | #### [Step 2:] 36 | Fill out the credentials in config.json. 37 | 38 | 39 | #### [Step 3:] 40 | Run the command line inside the folder and type the following command: node main.js 41 | 42 | 43 | 44 | ###### The bot should launch, if not then retrace your steps to see if you missed any credentials. If not then please open up an Issue where I'll help you fix your setup. 45 | 46 | -------------------------------------------------------------------------------- /src/commands/public/youtube.js: -------------------------------------------------------------------------------- 1 | // Getting the "Command" features from Commando 2 | const { Command } = require('discord.js-commando') 3 | const config = require('../../../config.json') 4 | const ajax = require('axios') 5 | 6 | // Code for the command 7 | module.exports = class youtubeCommand extends Command { 8 | constructor (client) { 9 | super(client, { 10 | // name of the command, must be in lowercase 11 | name: 'youtube', 12 | // other ways to call the command, must be in lowercase 13 | aliases: ['yt', 'ytsearch'], 14 | // command group its part of 15 | group: 'public', 16 | // name within the command group, must be in lowercase 17 | memberName: 'youtube', 18 | // Is the description used for "help" command 19 | description: 'Search youtube for vidoes.', 20 | // adds cooldowns to the command 21 | throttling: { 22 | // usages in certain time x 23 | usages: 2, 24 | // the cooldown 25 | duration: 10 26 | }, 27 | // Prevents it from being used in dms 28 | guildOnly: true, 29 | // Permissions, list found here > `discord.js.org/#/docs/main/11.5.1/class/Permissions?scrollTo=s-FLAGS` 30 | clientPermissions: ['ADMINISTRATOR'], 31 | userPermissions: ['SEND_MESSAGES'], 32 | // Prevents anyone other than owner to use the command 33 | ownerOnly: false 34 | }) 35 | } 36 | 37 | // Run code goes here 38 | run (message) { 39 | const randomNum = Math.floor(Math.random() * 5) 40 | 41 | const messageArry = message.content.split(' ') 42 | const args = messageArry.slice(1) 43 | 44 | yss({ 45 | key: config.env.youtubeAPI, 46 | query: args.join(' '), 47 | maxResults: 5 48 | }, 49 | callback 50 | ) 51 | 52 | function callback (results) { 53 | const result = results[randomNum] 54 | 55 | // console.log(result.snippet); 56 | 57 | // embed don't allow vidoes therefore used the thumbnail 58 | const ytEmbed = { 59 | author: { 60 | name: `${result.snippet.channelTitle}`, 61 | url: `https://www.youtube.com/watch?v=${result.id.videoId}` 62 | }, 63 | title: `${result.snippet.title}`, 64 | description: `${result.snippet.description}`, 65 | image: { 66 | url: result.snippet.thumbnails.high.url 67 | } 68 | } 69 | message.channel.send({ embed: ytEmbed }) 70 | } 71 | } 72 | } 73 | 74 | function yss (options, callback) { 75 | if (!options.key) { 76 | throw new Error('You need API key for YouTube') 77 | } 78 | 79 | const params = { 80 | key: options.key, 81 | q: options.query, 82 | maxResults: options.maxResults || 10, 83 | part: 'snippet', 84 | type: 'video' 85 | } 86 | 87 | ajax.get(URL, { params }) 88 | .then((response) => { 89 | if (callback) { 90 | callback(response.data.items) 91 | } 92 | }) 93 | .catch((response) => { 94 | console.error(response) 95 | }) 96 | } 97 | -------------------------------------------------------------------------------- /src/commands/mod/mute.js: -------------------------------------------------------------------------------- 1 | // Getting the 'Command' features from Commando 2 | const { Command } = require('discord.js-commando') 3 | const { RichEmbed } = require('discord.js') 4 | const chalk = require('chalk') 5 | const log = console.log 6 | 7 | // Code for the command 8 | module.exports = class muteCommand extends Command { 9 | constructor (client) { 10 | super(client, { 11 | // name of the command, must be in lowercase 12 | name: 'mute', 13 | // other ways to call the command, must be in lowercase 14 | aliases: ['mute', 'tempmute'], 15 | // command group its part of 16 | group: 'mod', 17 | // name within the command group, must be in lowercase 18 | memberName: 'mute', 19 | // Is the description used for 'help' command 20 | description: 'Mutes the mentioned user for n minutes', 21 | // adds cooldowns to the command 22 | throttling: { 23 | // usages in certain time x 24 | usages: 1, 25 | // the cooldown 26 | duration: 10 27 | }, 28 | // Prevents it from being used in dms 29 | guildOnly: true, 30 | // Permissions, list found here > `discord.js.org/#/docs/main/11.5.1/class/Permissions?scrollTo=s-FLAGS` 31 | clientPermissions: ['ADMINISTRATOR'], 32 | userPermissions: ['MANAGE_MESSAGES'], 33 | // Prevents anyone other than owner to use the command 34 | ownerOnly: false 35 | }) 36 | } 37 | 38 | // Run code goes here 39 | async run (message) { 40 | const messageArry = message.content.split(' ') 41 | const args = messageArry.slice(1) 42 | 43 | const mUser = message.guild.member(message.mentions.users.first() || message.guild.get(args[0])) 44 | if (!mUser) return message.channel.send('User cannot be found!') 45 | const mReason = args.join(' ').slice(22) 46 | 47 | // setting up the embed for report/log 48 | const muteEmbed = new RichEmbed() 49 | .setDescription(`Report: ${mUser} MUTE`) 50 | .addField('Reason >', `${mReason}`) 51 | .addField('Time', message.createdAt) 52 | 53 | const reportchannel = message.guild.channels.find('name', 'report') 54 | if (!reportchannel) return message.channel.send('*`Report channel cannot be found!`*') 55 | 56 | // Delete the message command 57 | // eslint-disable-next-line camelcase 58 | message.delete().catch(O_o => {}) 59 | let muterole = message.guild.roles.find('name', 'Muted') 60 | if (!muterole) { 61 | try { 62 | muterole = await message.guild.createRole({ 63 | name: 'Muted', 64 | color: '@000000', 65 | permissions: [] 66 | }) 67 | message.guild.channels.forEach(async (channel, id) => { 68 | await channel.overwritePermissions(muterole, { 69 | SEND_MESSAGES: false, 70 | ADD_REACTIONS: false 71 | }) 72 | }) 73 | } catch (e) { 74 | log(chalk.underline.red(e.stack)) 75 | } 76 | } 77 | await (mUser.addRole(muterole.id)) 78 | reportchannel.send(muteEmbed) 79 | // Logs the kick into the terminal 80 | log(chalk.red('MUTE', chalk.underline.bgBlue(mUser) + '!')) 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/commands/mod/unmute.js: -------------------------------------------------------------------------------- 1 | // Getting the 'Command' features from Commando 2 | const { Command } = require('discord.js-commando') 3 | const { RichEmbed } = require('discord.js') 4 | const chalk = require('chalk') 5 | const log = console.log 6 | 7 | // Code for the command 8 | module.exports = class unmuteCommand extends Command { 9 | constructor (client) { 10 | super(client, { 11 | // name of the command, must be in lowercase 12 | name: 'unmute', 13 | // other ways to call the command, must be in lowercase 14 | aliases: ['unmute', 'untempmute'], 15 | // command group its part of 16 | group: 'mod', 17 | // name within the command group, must be in lowercase 18 | memberName: 'unmute', 19 | // Is the description used for 'help' command 20 | description: 'unmutes the mentioned user', 21 | // adds cooldowns to the command 22 | throttling: { 23 | // usages in certain time x 24 | usages: 1, 25 | // the cooldown 26 | duration: 10 27 | }, 28 | // Prevents it from being used in dms 29 | guildOnly: true, 30 | // Permissions, list found here > `discord.js.org/#/docs/main/11.5.1/class/Permissions?scrollTo=s-FLAGS` 31 | clientPermissions: ['ADMINISTRATOR'], 32 | userPermissions: ['MANAGE_MESSAGES'], 33 | // Prevents anyone other than owner to use the command 34 | ownerOnly: false 35 | }) 36 | } 37 | 38 | // Run code goes here 39 | async run (message) { 40 | const messageArry = message.content.split(' ') 41 | const args = messageArry.slice(1) 42 | 43 | const mUser = message.guild.member(message.mentions.users.first() || message.guild.get(args[0])) 44 | if (!mUser) return message.channel.send('User cannot be found!') 45 | const mReason = args.join(' ').slice(22) 46 | 47 | // setting up the embed for report/log 48 | const unmuteEmbed = new RichEmbed() 49 | .setDescription(`Report: ${mUser} UNMUTE`) 50 | .addField('Reason >', `${mReason}`) 51 | .addField('Time', message.createdAt) 52 | 53 | const reportchannel = message.guild.channels.find('name', 'report') 54 | if (!reportchannel) return message.channel.send('*`Report channel cannot be found!`*') 55 | 56 | // Delete the message command 57 | // eslint-disable-next-line camelcase 58 | message.delete().catch(O_o => {}) 59 | let muterole = message.guild.roles.find('name', 'Muted') 60 | if (!muterole) { 61 | try { 62 | muterole = await message.guild.createRole({ 63 | name: 'Muted', 64 | color: '@000000', 65 | permissions: [] 66 | }) 67 | message.guild.channels.forEach(async (channel, id) => { 68 | await channel.overwritePermissions(muterole, { 69 | SEND_MESSAGES: false, 70 | ADD_REACTIONS: false 71 | }) 72 | }) 73 | } catch (e) { 74 | log(chalk.underline.red(e.stack)) 75 | } 76 | } 77 | await (mUser.removeRole(muterole.id)) 78 | reportchannel.send(unmuteEmbed) 79 | // Logs the kick into the terminal 80 | log(chalk.red('UNMUTE', chalk.underline.bgBlue(mUser) + '!')) 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at nuke.stye@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /src/commands/mod/lock.js: -------------------------------------------------------------------------------- 1 | // Getting the 'Command' features from Commando 2 | const { Command } = require('discord.js-commando') 3 | const Discord = require('discord.js') 4 | const config = require('../../../config.json') 5 | const chalk = require('chalk') 6 | // Code for the command 7 | module.exports = class lockCommand extends Command { 8 | constructor (client) { 9 | super(client, { 10 | // name of the command, must be in lowercase 11 | name: 'lock', 12 | // other ways to call the command, must be in lowercase 13 | aliases: ['latch'], 14 | // command group its part of 15 | group: 'mod', 16 | // name within the command group, must be in lowercase 17 | memberName: 'lock', 18 | // Is the description used for 'help' command 19 | description: 'Lock/unlock the channel', 20 | // adds cooldowns to the command 21 | throttling: { 22 | // usages in certain time x 23 | usages: 1, 24 | // the cooldown 25 | duration: 10 26 | }, 27 | // Prevents it from being used in dms 28 | guildOnly: true, 29 | // Permissions, list found here > `discord.js.org/#/docs/main/11.5.1/class/Permissions?scrollTo=s-FLAGS` 30 | clientPermissions: ['ADMINISTRATOR'], 31 | // Prevents anyone other than owner to use the command 32 | ownerOnly: false 33 | }) 34 | } 35 | 36 | // Run code goes here 37 | run (message) { 38 | // Seprating the message into 'cmd' and 'args' 39 | const messageArry = message.content.split(' ') 40 | const args = messageArry.slice(1) 41 | 42 | // finding '@everyone' role 43 | const everyoneRole = message.guild.roles.find(x => x.name === '@everyone') 44 | const staffRole = message.guild.roles.find(x => x.name === 'Staff') 45 | 46 | if (!staffRole) { 47 | message.channel.send('Staff role is missing!') 48 | console.error(chalk.red('[!] [LOCK COMMAND] Staff role is missing!')) 49 | } 50 | // making no perms Emebd 51 | const noPermsEmebd = new Discord.RichEmbed() 52 | .setColor('#FF0000') 53 | .setDescription(`${message.author} doesn't have perms to use this command!`) 54 | // making lock Emebd 55 | const lockEmbed = new Discord.RichEmbed() 56 | .setColor(config.colour) 57 | .setDescription(`${message.channel} has been locked by ${message.author}!`) 58 | // making unlock Emebd 59 | const unlockEmbed = new Discord.RichEmbed() 60 | .setColor(config.colour) 61 | .setDescription(`${message.channel} has been unlocked by ${message.author}!`) 62 | 63 | if (!message.member.hasPermission('MANAGE_CHANNELS')) return message.channel.send(noPermsEmebd) 64 | if (args === 'on') { // turning on the lock mechanism 65 | message.channel.overwritePermissions(everyoneRole, { 66 | SEND_MESSAGES: false, 67 | READ_MESSAGES: true, 68 | ADD_REACTIONS: false 69 | }) 70 | message.channel.overwritePermissions(staffRole, { 71 | SEND_MESSAGES: true, 72 | READ_MESSAGES: true 73 | }) 74 | message.channel.send(lockEmbed) 75 | } else if (args === 'off') { // turning off the lock mechanism 76 | message.channel.overwritePermissions(everyoneRole, { 77 | SEND_MESSAGES: true, 78 | READ_MESSAGES: true, 79 | ADD_REACTIONS: true 80 | }) 81 | message.channel.overwritePermissions(staffRole, { 82 | SEND_MESSAGES: true, 83 | READ_MESSAGES: true 84 | }) 85 | message.channel.send(unlockEmbed) 86 | } else { // if its neither 'on'/'off' then its default to 'on' 87 | message.channel.overwritePermissions(everyoneRole, { 88 | SEND_MESSAGES: false, 89 | READ_MESSAGES: true, 90 | ADD_REACTIONS: false 91 | }) 92 | message.channel.overwritePermissions(staffRole, { 93 | SEND_MESSAGES: true, 94 | READ_MESSAGES: true 95 | }) 96 | message.channel.send(lockEmbed) 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/commands/mod/ticket.js: -------------------------------------------------------------------------------- 1 | // Getting the 'Command' features from Commando 2 | const { Command } = require('discord.js-commando') 3 | const Discord = require('discord.js') 4 | 5 | // Code for the command 6 | module.exports = class ticketCommand extends Command { 7 | constructor (client) { 8 | super(client, { 9 | // name of the command, must be in lowercase 10 | name: 'ticket', 11 | // other ways to call the command, must be in lowercase 12 | aliases: ['ticket', 'issue'], 13 | // command group its part of 14 | group: 'mod', 15 | // name within the command group, must be in lowercase 16 | memberName: 'ticket', 17 | // Is the description used for 'help' command 18 | description: 'Create a ticket under a support category', 19 | // adds cooldowns to the command 20 | throttling: { 21 | // usages in certain time x 22 | usages: 1, 23 | // the cooldown, x 24 | duration: 10 25 | }, 26 | // Prevents it from being used in dms 27 | guildOnly: true, 28 | // Prevents anyone other than owner to use the command 29 | ownerOnly: false 30 | }) 31 | } 32 | 33 | // Run code goes here 34 | run (message) { 35 | // separting the message into cmd & args 36 | const messageArry = message.content.split(' ') 37 | const messageLength = messageArry.length - 1 38 | // `.ticket create issue #1` is turned into 39 | // cmd = `.ticket`, option = `create`, issue = `issue #1` 40 | const option = messageArry[1] 41 | const issue = messageArry.slice(2, messageLength) 42 | const errorEmbed = new Discord.RichEmbed() 43 | .setTitle('Incorrect Usage!') 44 | .addField('Please use as:', `\`${this.client.commandPrefix}ticket [create/new] [Your Issue]\``) 45 | .setFooter('Made by - nukestye™', `${this.client.user.avatarURL}`) 46 | 47 | const permEmbed = new Discord.RichEmbed() 48 | .setTitle(message.author.tag) 49 | .setDescription('You do not have perms to close ticket, ask staff to do so.') 50 | .setFooter('Made by - nukestye™', `${this.client.user.avatarURL}`) 51 | 52 | if (option === 'create' || option === 'new') { 53 | const name = `Ticket-${message.author.discriminator}` 54 | if (issue.length < 1) return message.channel.send(errorEmbed) 55 | message.guild.createChannel(name, 'text').then(c => { 56 | const role = message.guild.roles.find('name', 'Staff') 57 | const role2 = message.guild.roles.find('name', '@everyone') 58 | 59 | c.overwritePermissions(role, { 60 | SEND_MESSAGES: true, 61 | READ_MESSAGES: true 62 | }) 63 | c.overwritePermissions(role2, { 64 | SEND_MESSAGES: false, 65 | READ_MESSAGES: false 66 | }) 67 | c.overwritePermissions(message.author, { 68 | SEND_MESSAGES: true, 69 | READ_MESSAGES: true 70 | }) 71 | const category = message.guild.channels.find(c => c.name === 'Support' && c.type === 'category') 72 | 73 | if (category) { 74 | c.setParent(category.id) 75 | } else { 76 | if (!category) { 77 | message.guild.createChannel('Support', 'category').then(Category => { 78 | c.setParent(Category.id) 79 | }) 80 | } else { 81 | console.error(`Category channel is missing:\nCategory: ${!!category}`) 82 | return message.channel.send(`Category channel is missing:\nCategory: ${!!category}`) 83 | } 84 | } 85 | 86 | message.channel.send(`:white_check_mark: Your ticket has been created, #${c.name}.`) 87 | const embed = new Discord.RichEmbed() 88 | .setColor(0xCF40FA) 89 | .addField(`Hey ${message.author.username}!`, `Please try explain why you opened this ticket with as much detail as possible. Our **Support Team** will be here soon to help.\n**Your Issue**\n ${issue.join(' ')}`) 90 | .setTimestamp() 91 | 92 | c.send({ embed: embed }) 93 | }).catch(console.error) 94 | } else if (option === 'close') { 95 | if (message.member.roles.some(role => role.name === 'Staff')) { 96 | if (!message.channel.name.startsWith('ticket-')) return message.channel.send('You can\'t use the close command outside of a ticket channel.') 97 | 98 | message.channel.send(`Are you sure? Once confirmed, you cannot reverse this action!\nTo confirm, type \`${this.client.commandPrefix}confirm\`. This will time out in 10 seconds and be cancelled.`) 99 | .then((m) => { 100 | message.channel.awaitMessages(response => response.content === `${this.client.commandPrefix}confirm`, { 101 | max: 1, 102 | time: 10000, 103 | errors: ['time'] 104 | }) 105 | .then((collected) => { 106 | message.channel.delete() 107 | }) 108 | .catch(() => { 109 | m.edit('Timed out, the ticket will not closed.') 110 | .then(m2 => { 111 | m2.delete() 112 | }, 3000) 113 | }) 114 | }) 115 | } else { 116 | message.channel.send({ embed: permEmbed }) 117 | } 118 | } else { 119 | message.channel.send(errorEmbed) 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/commands/public/info.js: -------------------------------------------------------------------------------- 1 | // Getting the "Command" features from Commando 2 | const { Command } = require('discord.js-commando') 3 | const Discord = require('discord.js') 4 | const config = require('../../../config.json') 5 | 6 | // Code for the command 7 | module.exports = class infoCommand extends Command { 8 | constructor (client) { 9 | super(client, { 10 | // name of the command, must be in lowercase 11 | name: 'info', 12 | // other ways to call the command, must be in lowercase 13 | aliases: ['information'], 14 | // command group its part of 15 | group: 'public', 16 | // name within the command group, must be in lowercase 17 | memberName: 'info', 18 | // how to use the cmd 19 | format: '[bot]/[server]', 20 | // Is the description used for "help" command 21 | description: 'Information regarding bot or server', 22 | // adds cooldowns to the command 23 | throttling: { 24 | // usages in certain time x 25 | usages: 1, 26 | // the cooldown in s 27 | duration: 10 28 | }, 29 | // Prevents it from being used in dms 30 | guildOnly: true, 31 | // Permissions, list found here > `discord.js.org/#/docs/main/11.5.1/class/Permissions?scrollTo=s-FLAGS` 32 | clientPermissions: ['ADMINISTRATOR'], 33 | userPermissions: ['SEND_MESSAGES'], 34 | // Prevents anyone other than owner to use the command 35 | ownerOnly: false, 36 | // Taking input from user 37 | args: [ 38 | // < 39 | { 40 | // name of the argument/variable 41 | key: 'text', 42 | // a prompt asking the user 43 | prompt: 'Enter the category you want information about(Bot or Server): ', 44 | // the data type of the argument/variable 45 | type: 'string' 46 | // default value if nothing is entered 47 | // default: "hello", 48 | // check if the argument/variable matchs or not 49 | // validate: text => /* check here */text.length < 201, 50 | // Forces to be one of the options 51 | // oneOf:["bot","server"], 52 | } 53 | // > Part of one argument/variable 54 | ] 55 | }) 56 | } 57 | 58 | // Run code goes here 59 | run (message, { text }) { 60 | // getting the guild the message is send in 61 | const guild = message.guild 62 | // Figuring out how many members and bots there are in the "guild" 63 | const memberCount = [] 64 | const botCount = [] 65 | guild.members.forEach((member) => { 66 | if (member.user.bot) { 67 | botCount.push(member.name) 68 | } else { 69 | memberCount.push(member.name) 70 | } 71 | }) 72 | 73 | // finding the number of different channels 74 | const textChannels = [] 75 | const categoryChannels = [] 76 | const voiceChannels = [] 77 | guild.channels.forEach((channel) => { 78 | if (channel.type === 'text') { 79 | textChannels.push(channel.name) 80 | } else if (channel.type === 'category') { 81 | categoryChannels.push(channel.name) 82 | } else if (channel.type === 'voice') { 83 | voiceChannels.push(channel.name) 84 | } 85 | }) 86 | // finding the number of roles in the guild 87 | const roles = [] 88 | guild.roles.forEach((role) => { 89 | roles.push(role.name) 90 | }) 91 | // figuring out uptime 92 | let totalSeconds = (this.client.uptime / 1000) 93 | const days = Math.floor(totalSeconds / 86400) 94 | const hours = Math.floor(totalSeconds / 3600) 95 | totalSeconds %= 3600 96 | const minutes = Math.floor(totalSeconds / 60) 97 | const seconds = totalSeconds % 60 98 | 99 | const uptime = `${days} days, ${hours} hours, ${minutes} minutes and ${seconds} seconds` 100 | 101 | // making the server info embed 102 | const serverInfo = new Discord.RichEmbed() 103 | .setTitle(`${guild.name}`) 104 | .setThumbnail(`https://cdn.discordapp.com/icons/${guild.id}/${guild.icon}.png?size=128`) 105 | .setTimestamp() 106 | .setColor(config.colour) 107 | // ----------------------------------------------------------------------------------------- // 108 | .addField('Owner:', `${guild.owner} - ID: ${guild.ownerID}`) 109 | .addField('Server ID', `${guild.id}`) 110 | .addField('Created at:', `${guild.createdAt}`) 111 | // ----------------------------------------------------------------------------------------- // 112 | .addField('Region', `${guild.region}`, true) 113 | .addField('Members: ', `${memberCount.length}`, true) 114 | .addField('Bots', `${botCount.length}`, true) 115 | // ----------------------------------------------------------------------------------------- // 116 | .addField('Categories', `${categoryChannels.length}`, true) 117 | .addField('Channels', `Text: ${textChannels.length} Voice: ${voiceChannels.length}`, true) 118 | .addField('Roles', `${roles.length}`, true) 119 | // ----------------------------------------------------------------------------------------- // 120 | .setFooter(`${message.author.username}`, `${message.author.displayAvatarURL}`) 121 | 122 | // owner avatar url 123 | const ownerURL = `https://cdn.discordapp.com/avatars/${this.client.owners[0].id}/${this.client.owners[0].avatar}.png?size=128` 124 | // finding the number of guilds the bot is in 125 | const guildsNum = [] 126 | let totalMembers = 0 127 | this.client.guilds.forEach((guild) => { 128 | if (guild.available && !guild.deleted) { 129 | guildsNum.push(guild.name) 130 | totalMembers = totalMembers + guild.memberCount 131 | } 132 | }) 133 | 134 | // making bot info embed 135 | const botInfo = new Discord.RichEmbed() 136 | // ----------------------------------------------------------------------------------------- // 137 | // .setTitle(`${this.client.user.tag}`) 138 | .setTimestamp() 139 | .setAuthor(`${this.client.owners[0].username}#${this.client.owners[0].discriminator}`, `${ownerURL}`) 140 | .setThumbnail(`${this.client.user.displayAvatarURL}`) 141 | .setColor(config.colour) 142 | .setDescription(`Uptime: ${uptime}`) 143 | // ----------------------------------------------------------------------------------------- // 144 | .addField('Name: ', `${this.client.user.tag}`, true) 145 | .addField('ID: ', `${this.client.user.id}`, true) 146 | .addField('Created At: ', `${this.client.user.createdAt}`, true) 147 | // ----------------------------------------------------------------------------------------- // 148 | .addField('Servers: ', `${guildsNum.length}`, true) 149 | .addField('Members: ', `${totalMembers}`, true) 150 | .addField('Discord: ', `${config.discord}`, true) 151 | // ----------------------------------------------------------------------------------------- // 152 | .setFooter(`${message.author.username}`, `${message.author.displayAvatarURL}`) 153 | 154 | if (text === 'server') { 155 | message.channel.send(serverInfo) 156 | // console.log(textChannels.length); 157 | } else if (text === 'bot') { 158 | message.channel.send(botInfo) 159 | // console.log(guildsNum.length); 160 | } else { 161 | // console.log(); 162 | message.channel.send(`Incorrect Usage, \`${config.prefix}info [bot]/[server]\``) 163 | } 164 | } 165 | } 166 | --------------------------------------------------------------------------------