├── LICENSE ├── README.md ├── package.json └── server.js /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Richard Kriesman 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # discord-logger 2 | A bot for Discord that logs server actions (joining/leaving, bans, edits, and deletions) 3 | 4 | ### Installation 5 | 6 | The following are required to run discord-logger: 7 | - Node.JS v6.9.1 or higher 8 | - A Discord bot user token (bot users can be created at https://discordapp.com/developers/applications/me) 9 | 10 | Once you have those: 11 | - In server.js, set const TOKEN to the bot token you created. 12 | - Set const CHANNEL to the name of the Discord channel (not ID) that want discord-logger to log server actions to 13 | - In your terminal, run "npm install" to install the required dependencies 14 | 15 | You can then run the bot with "node server.js" 16 | 17 | ### License 18 | discord-logger is licensed under the MIT License. -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "logger", 3 | "version": "0.1.0", 4 | "dependencies": { 5 | "discord.js": "^9.3.1" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | /* 2 | Logger v0.1.0 3 | A bot for Discord that logs moderator actions. 4 | ----------------------------------------------- 5 | Copyright © Richard Kriesman 2016. 6 | */ 7 | 8 | //imports 9 | const Discord = require('discord.js'); 10 | 11 | //constants 12 | const VERSION = '0.1.1'; 13 | const TOKEN = 'TOKEN GOES HERE'; 14 | const CHANNEL = 'log'; 15 | 16 | //declarations 17 | var bot = new Discord.Client(); 18 | 19 | // 20 | // Event Handlers 21 | // 22 | 23 | //bot is ready to start working, print status update to console 24 | bot.on('ready', function() { 25 | console.log('[META][INFO] Connected to Discord API Service'); 26 | }); 27 | 28 | //bot disconnected from Discord 29 | bot.on('disconnected', function() { 30 | console.log('[META][WARN] Disconnected from Discord API Service. Attempting to reconnected...'); 31 | }); 32 | 33 | //warning from Discord.js 34 | bot.on('warn', function(msg) { 35 | console.log('[META][WARN] ' + msg); 36 | }); 37 | 38 | //error from Discord.js 39 | bot.on('error', function(err) { 40 | console.log('[META][ERROR] ' + err.message); 41 | process.exit(1); 42 | }); 43 | 44 | //message received 45 | bot.on('message', function(message) { 46 | if(message.author.id != bot.user.id) { 47 | if (message.channel.type == 'text') 48 | console.log('[' + message.guild.name + '][#' + message.channel.name + '][MSG] ' + message.author.username + 49 | '#' + message.author.discriminator + ': ' + formatConsoleMessage(message)); 50 | else if (message.channel.type == 'dm') 51 | message.channel.sendMessage('Beep boop! Sorry, I can\'t respond to direct messages. Try inviting me to your ' + 52 | 'server!\nhttps://discordapp.com/oauth2/authorize?&client_id=240256235952144395&scope=bot&permissions=8'); 53 | else if (message.channel.type == 'group') 54 | message.channel.sendMessage('Beep boop! Sorry, I can\'t log group messages. Try inviting me to your server!\n' + 55 | 'https://discordapp.com/oauth2/authorize?&client_id=240256235952144395&scope=bot&permissions=8'); 56 | } 57 | }); 58 | 59 | //message deleted 60 | bot.on('messageDelete', function(message) { 61 | 62 | if(message.channel.type == 'text') { 63 | 64 | //log to console 65 | console.log('[' + message.guild.name + '][#' + message.channel.name + '][DELMSG] ' + message.author.username + 66 | '#' + message.author.discriminator + ': ' + formatConsoleMessage(message)); 67 | 68 | //post in the guild's log channel 69 | var log = message.guild.channels.find('name', CHANNEL); 70 | if (log != null) 71 | log.sendMessage('**[Message Deleted]** ' + message.author + ': ' + message.cleanContent); 72 | 73 | } 74 | 75 | }); 76 | 77 | //message update 78 | bot.on('messageUpdate', function(oldMessage, newMessage) { 79 | 80 | if (newMessage.channel.type == 'text' && newMessage.cleanContent != oldMessage.cleanContent) { 81 | 82 | //log to console 83 | console.log('[' + newMessage.guild.name + '][#' + newMessage.channel.name + '][UPDMSG] ' + 84 | newMessage.author.username + '#' + newMessage.author.discriminator + ':\n\tOLDMSG: ' + 85 | formatConsoleMessage(oldMessage) + '\n\tNEWMSG: ' + formatConsoleMessage(newMessage)); 86 | 87 | //post in the guild's log channel 88 | var log = newMessage.guild.channels.find('name', CHANNEL); 89 | if (log != null) 90 | log.sendMessage('**[Message Updated]** *' + newMessage.author + '*:\n*Old Message*: ' + oldMessage.cleanContent + 91 | '\n*New Message*: ' + newMessage.cleanContent); 92 | } 93 | 94 | }); 95 | 96 | //user has been banned 97 | bot.on('guildBanAdd', function(guild, user) { 98 | 99 | //log to console 100 | console.log('[' + guild.name + '][BAN] ' + user.username + '#' + user.discriminator); 101 | 102 | //post in the guild's log channel 103 | var log = guild.channels.find('name', CHANNEL); 104 | if (log != null) 105 | log.sendMessage('**[Banned]** ' + user); 106 | 107 | }); 108 | 109 | //user has been unbanned 110 | bot.on('guildBanRemove', function(guild, user) { 111 | 112 | //log to console 113 | console.log('[' + guild.name + '][UNBAN] ' + user.username + '#' + user.discriminator); 114 | 115 | //post in the guild's log channel 116 | var log = guild.channels.find('name', CHANNEL); 117 | if (log != null) 118 | log.sendMessage('**[Unbanned]** ' + user); 119 | 120 | }); 121 | 122 | //user has joined a guild 123 | bot.on('guildMemberAdd', function(guild, user) { 124 | 125 | //log to console 126 | console.log('[' + guild.name + '][JOIN] ' + user.username + '#' + user.discriminator); 127 | 128 | //post in the guild's log channel 129 | var log = guild.channels.find('name', CHANNEL); 130 | if (log != null) { 131 | log.sendMessage('**[Joined]** ' + user); 132 | } 133 | 134 | }); 135 | 136 | //user has joined a guild 137 | bot.on('guildMemberRemove', function(guild, user) { 138 | 139 | //log to console 140 | console.log('[' + guild.name + '][LEAVE] ' + user.username + '#' + user.discriminator); 141 | 142 | //post in the guild's log channel 143 | var log = guild.channels.find('name', CHANNEL); 144 | if (log != null) 145 | log.sendMessage('**[Left]** ' + user); 146 | 147 | }); 148 | 149 | //user in a guild has been updated 150 | bot.on('guildMemberUpdate', function(guild, oldMember, newMember) { 151 | 152 | //declare changes 153 | var Changes = { 154 | unknown: 0, 155 | addedRole: 1, 156 | removedRole: 2, 157 | username: 3, 158 | nickname: 4, 159 | avatar: 5 160 | }; 161 | var change = Changes.unknown; 162 | 163 | //check if roles were removed 164 | var removedRole = ''; 165 | oldMember.roles.every(function(value) { 166 | if(newMember.roles.find('id', value.id) == null) { 167 | change = Changes.removedRole; 168 | removedRole = value.name; 169 | } 170 | }); 171 | 172 | //check if roles were added 173 | var addedRole = ''; 174 | newMember.roles.every(function(value) { 175 | if(oldMember.roles.find('id', value.id) == null) { 176 | change = Changes.addedRole; 177 | addedRole = value.name; 178 | } 179 | }); 180 | 181 | //check if username changed 182 | if(newMember.user.username != oldMember.user.username) 183 | change = Changes.username; 184 | 185 | //check if nickname changed 186 | if(newMember.nickname != oldMember.nickname) 187 | change = Changes.nickname; 188 | 189 | //check if avatar changed 190 | if(newMember.user.avatarURL != oldMember.user.avatarURL) 191 | change = Changes.avatar; 192 | 193 | //log to console 194 | switch(change) { 195 | case Changes.unknown: 196 | console.log('[' + guild.name + '][UPDUSR] ' + newMember.user.username + '#' + newMember.user.discriminator); 197 | break; 198 | case Changes.addedRole: 199 | console.log('[' + guild.name + '][ADDROLE] ' + newMember.user.username +'#' + newMember.user.discriminator + 200 | ': ' + addedRole); 201 | break; 202 | case Changes.removedRole: 203 | console.log('[' + guild.name + '][REMROLE] ' + newMember.user.username + '#' + newMember.user.discriminator + 204 | ': ' + removedRole); 205 | break; 206 | case Changes.username: 207 | console.log('[' + guild.name + '][UPDUSRNM] ' + oldMember.user.username + '#' + oldMember.user.discriminator + 208 | ' is now ' + newMember.user.username + '#' + newMember.user.discriminator); 209 | break; 210 | case Changes.nickname: 211 | console.log('[' + guild.name + '][UPDUSRNK] ' + newMember.user.username + '#' + newMember.user.discriminator + 212 | (oldMember.nickname != null ? ' (' + oldMember.nickname + ')' : '') + 213 | (newMember.nickname != null ? ' is now ' + newMember.nickname : ' no longer has a nickname.')); 214 | break; 215 | case Changes.avatar: 216 | console.log('[' + guild.name + '][UPDAVT] ' + newMember.user.username + '#' + newMember.user.discriminator); 217 | break; 218 | } 219 | 220 | 221 | //post in the guild's log channel 222 | var log = guild.channels.find('name', CHANNEL); 223 | if (log != null) { 224 | switch(change) { 225 | case Changes.unknown: 226 | log.sendMessage('**[User Update]** ' + newMember); 227 | break; 228 | case Changes.addedRole: 229 | log.sendMessage('**[User Role Added]** ' + newMember + ': ' + addedRole); 230 | break; 231 | case Changes.removedRole: 232 | log.sendMessage('**[User Role Removed]** ' + newMember + ': ' + removedRole); 233 | break; 234 | case Changes.username: 235 | log.sendMessage('**[User Username Changed]** ' + newMember + ': Username changed from ' + 236 | oldMember.user.username + '#' + oldMember.user.discriminator + ' to ' + 237 | newMember.user.username + '#' + newMember.user.discriminator); 238 | break; 239 | case Changes.nickname: 240 | log.sendMessage('**[User Nickname Changed]** ' + newMember + ': ' + 241 | (oldMember.nickname != null ? 'Changed nickname from ' + oldMember.nickname + 242 | + newMember.nickname : 'Set nickname') + ' to ' + 243 | (newMember.nickname != null ? newMember.nickname + '.' : 'original username.')); 244 | break; 245 | case Changes.avatar: 246 | log.sendMessage('**[User Avatar Changed]** ' + newMember); 247 | break; 248 | } 249 | } 250 | 251 | }); 252 | 253 | // 254 | // Startup Sequence 255 | // 256 | console.log('Logger v' + VERSION); 257 | console.log('A bot for Discord that logs moderator actions.\n'); 258 | console.log('Copyright © Richard Kriesman 2016. Released under the MIT license.'); 259 | console.log('----------------------------------------------'); 260 | 261 | console.log('[META][INFO] Started Logger v' + VERSION); 262 | 263 | bot.login(TOKEN); //log in to discord 264 | 265 | function formatConsoleMessage(message) { 266 | return message.cleanContent.replace(new RegExp('\n', 'g'), '\n\t'); 267 | } --------------------------------------------------------------------------------