├── README.md ├── bot.js ├── config.js └── package.json /README.md: -------------------------------------------------------------------------------- 1 | # NOTICE: 2 | 3 | This repository and code in it is deprecated and will not be updated. 4 | ======================================== 5 | 6 | ## Reaction Role Bot that logs. 7 | 8 | 9 | Setup 10 | ========================== 11 | **1.** Go to [`config.js`](https://github.com/elara-bots-archived/ReactionRole-Bot/blob/master/config.js) and put in your Discord Bot Token and add onto the 'roles' array. 12 | 13 | **2.** Use `npm install` and wait.. 14 | 15 | **3.** Use `node bot.js` and it should start up! 16 | -------------------------------------------------------------------------------- /bot.js: -------------------------------------------------------------------------------- 1 | const {Client, WebhookClient} = require('discord.js'), config = require('./config'), cooldown = new Set(); 2 | if(config.roles.length === 0) { 3 | console.log(`You left the "roles" array empty in the config.js file... until you add roles to it.. the process will keep ending!`); 4 | return process.exit(1); 5 | } 6 | const Hook = async (hook, data) => { 7 | if(config.logging.enabled === false) return null; 8 | if(!hook) return null; 9 | if(typeof hook !== "string") return null; 10 | if(!data) return null; 11 | if(typeof data !== "object") return null; 12 | let h = hook.replace(/https:\/\/(discord|discordapp).com\/api\/webhooks\//, '').split("/"); 13 | if(!h[0]) return null; 14 | if(!h[1]) return null; 15 | let Hook = new WebhookClient(h[0], h[1]); 16 | if(data.status === "Success"){ 17 | Hook.send({embeds: [ 18 | { 19 | color: data.type == "Added" ? 0xFF000 : 0xFF0000, 20 | title: `Reaction Role Logs`, 21 | fields: [ 22 | {name: "Action", value: data.type, inline: false}, 23 | {name: `User`, value: `\`@${data.user.tag}\` (${data.user.id})`, inline: false}, 24 | {name: `Reaction`, value: `${data.emoji}`, inline: true}, 25 | {name: `Role`, value: `${data.role} \`@${data.role.name}\` (${data.role.id})`} 26 | ], 27 | author: { 28 | name: data.user.tag, 29 | icon_url: data.user.displayAvatarURL() 30 | }, 31 | timestamp: Date.now 32 | } 33 | ]}).catch(() => {}); 34 | }else 35 | if(data.status === "Failed"){ 36 | Hook.send({embeds: [ 37 | { 38 | color: 0xFF0000, 39 | title: `Reaction Role Logs`, 40 | description: data.reason, 41 | fields: [ 42 | { 43 | name: `INFO`, 44 | value: `Failed ${data.type} role ${data.type === "added" ? "to" : "from"} ${data.user} (${data.user.id})` 45 | } 46 | ], 47 | author: { 48 | name: data.user.tag, 49 | icon_url: data.user.displayAvatarURL() 50 | }, 51 | timestamp: Date.now 52 | } 53 | ]}).catch(() => {}); 54 | } 55 | } 56 | class Reactions extends Client{ 57 | constructor(){ 58 | super({ 59 | fetchAllMembers: false, 60 | disableEveryone: true, 61 | presence: { 62 | status: "dnd", 63 | activity: { 64 | name: `${config.roles.length} reaction roles`, 65 | type: "WATCHING" 66 | } 67 | } 68 | }); 69 | this.on('ready', () => console.log(`${this.user.tag} is now ready!`)) 70 | this.on('shardReady', (id) => console.log(`Shard: ${id} is now ready!`)) 71 | this.on('shardResume', (id, replayed) => console.log(`Shard: ${id} has resumed!`)) 72 | this.on('shardReconnecting', (id) => console.log(`Shard: ${id} is now reconnecting!`)) 73 | this.on('shardDisconnect', (event, id) => console.log(`Shard: ${id} has Disconnected!`)) 74 | this.on('shardError', (error, id) => console.log(`Shard: ${id} Error: ${error.stack}`)) 75 | this.on('raw', async (event) => { 76 | if(!event) return null; 77 | if(event.t === "MESSAGE_REACTION_ADD"){ 78 | if(config.roles.length === 0) return null; 79 | if(!Array.isArray(config.roles)) return console.log(`config.roles isn't an array!`); 80 | for await (const data of config.roles){ 81 | if(!data.emoji) return null; 82 | if(!data.channelID) return null; 83 | if(!data.roleID) return null; 84 | let guild = this.guilds.cache.get(event.d.guild_id); 85 | if(!guild) return null; 86 | let role = guild.roles.cache.get(data.roleID); 87 | if(!role) return null; 88 | let channel = guild.channels.cache.get(data.channelID); 89 | if(!channel) return null; 90 | if(channel.id !== event.d.channel_id) return null; 91 | let member = guild.members.cache.get(event.d.user_id); 92 | if(!member) return null; 93 | if(member.user.bot) return null; 94 | let msg = await channel.messages.fetch(data.messageID); 95 | if(!msg) return null; 96 | if(msg.id !== event.d.message_id) return null; 97 | if(event.d.emoji.name === data.emoji || event.d.emoji.id === data.emoji) { 98 | await msg.reactions.cache.get(event.d.emoji.id ? event.d.emoji.id : event.d.emoji.name).users.remove(member.id); 99 | if(cooldown.has(member.user.id)) return member.send({embed: {color: 0xFF0000, author: {name: guild.name, icon_url: guild.iconURL()}, title: `Woah there.. you're on a 10s cooldown!`}}).catch(() => {}); 100 | if(!cooldown.has(member.user.id)) cooldown.add(member.user.id); 101 | setTimeout(() => cooldown.delete(member.user.id), 10000); 102 | if(member.roles.cache.has(role.id)){ 103 | member.roles.remove(role.id).then(() => { 104 | Hook(config.logging.webhook, { 105 | status: "Success", 106 | user: member.user, 107 | type: "Removed", 108 | role: role, 109 | emoji: event.d.emoji.id ? this.emojis.cache.get(event.d.emoji.id) : event.d.emoji 110 | }); 111 | }).catch((error) => { 112 | Hook(config.logging.webhook, { 113 | status: "Failed", 114 | user: member.user, 115 | reason: error.stack, 116 | type: "remove" 117 | }); 118 | }); 119 | }else{ 120 | member.roles.add(role.id).then(() => { 121 | Hook(config.logging.webhook, { 122 | status: "Success", 123 | user: member.user, 124 | type: "Added", 125 | role: role, 126 | emoji: event.d.emoji.id ? this.emojis.cache.get(event.d.emoji.id) : event.d.emoji 127 | }); 128 | }).catch(() => { 129 | Hook(config.logging.webhook, { 130 | status: "Failed", 131 | user: member.user, 132 | reason: error.stack, 133 | type: "added" 134 | }); 135 | }); 136 | } 137 | } 138 | } 139 | } 140 | }) 141 | } 142 | }; 143 | new Reactions().login(config.token).catch((error) => console.log(`ERROR: ${error.stack}`)) 144 | -------------------------------------------------------------------------------- /config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | token: "Your Discord Bot Token", // DO NOT SHARE WITH ANYONE!! 3 | logging: { 4 | enabled: false, // Only enable if you want the roles being added/removed to be logged 5 | webhook: "Full Webhook URL" 6 | }, 7 | roles: [ 8 | // { Example object for the reaction roles. 9 | // emoji: "emoji-id/or/emoji", // Ex: 123457890 or ✅ 10 | // roleID: "The Role ID", //Ex: 1234567890 11 | // channelID: "The channel ID", // Ex: 1234567890 12 | // messageID: "The message id", // Ex: 1234567890 13 | // } 14 | ] 15 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "reaction-role-bot", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "discord.js": "^12.3.1" 14 | } 15 | } 16 | --------------------------------------------------------------------------------