· 6 years ago · Jun 27, 2019, 07:36 AM
1const Discord = require(`discord.js`);
2const client = new Discord.Client();
3
4var _ = require(`underscore`);
5var fs = require(`fs`);
6const mysql = require(`mysql2`);
7const editJsonFile = require(`edit-json-file`);
8const cryptoRandomString = require(`crypto-random-string`);
9const moment = require(`moment`);
10
11const config = require(`./config.json`);
12const locale = require(`./locale.json`);
13const channelsData = require(`./channels.json`);
14
15var bannedUsers = require(`./banned_users.json`);
16
17var badWordsFile = editJsonFile(`./bad_words.json`);
18var bannedUsersFile = editJsonFile(`./banned_users.json`);
19var mutedFile = editJsonFile(`./muted.json`);
20var channelsFile = editJsonFile(`./channels.json`);
21
22var deletedByBot = 0;
23
24// Connecting to database
25const connection = mysql.createConnection({
26 host: config.host,
27 user: config.user,
28 password: config.password,
29 database: config.database,
30 multipleStatements: true,
31});
32connection.connect(function (err, results) {
33 console.log(`Established MySQL database connection.`);
34 if (err) {
35 throw err;
36 }
37});
38
39// Functions
40function setupTables() {
41 connection.query(
42 `CREATE TABLE IF NOT EXISTS users
43 (
44 userID VARCHAR(25) NOT NULL,
45 guildID VARCHAR(25) NOT NULL,
46 username VARCHAR(255) NOT NULL,
47 avatar VARCHAR(50),
48 exist bit DEFAULT 1,
49 timestamp DATETIME NOT NULL,
50 updated timestamp NOT NULL,
51 PRIMARY KEY (userID, guildID)
52 )
53 CHARACTER SET 'utf8mb4'
54 COLLATE 'utf8mb4_general_ci';`,
55 function (err, results) {
56 if (err => {
57 throw err;
58 });
59 }
60 );
61 connection.query(
62 `CREATE TABLE IF NOT EXISTS log_nickname
63 (
64 id int NOT NULL AUTO_INCREMENT,
65 userID VARCHAR(25) NOT NULL,
66 guildID VARCHAR(25) NOT NULL,
67 new VARCHAR(255),
68 old VARCHAR(255),
69 timestamp DATETIME NOT NULL,
70 PRIMARY KEY (id)
71 )
72 CHARACTER SET 'utf8mb4'
73 COLLATE 'utf8mb4_0900_ai_ci';`,
74 function (err, results) {
75 if (err => {
76 throw err;
77 });
78 }
79 );
80 connection.query(
81 `CREATE TABLE IF NOT EXISTS messageTypes
82 (
83 id int NOT NULL,
84 type VARCHAR(100),
85 PRIMARY KEY (id)
86 )
87 CHARACTER SET 'utf8mb4'
88 COLLATE 'utf8mb4_general_ci';`,
89 function (err, results) {
90 if (err => {
91 throw err;
92 });
93 }
94 );
95 connection.query(
96 `CREATE TABLE IF NOT EXISTS log_username
97 (
98 id int NOT NULL AUTO_INCREMENT,
99 userID VARCHAR(25) NOT NULL,
100 guildID VARCHAR(25) NOT NULL,
101 new VARCHAR(255),
102 old VARCHAR(255),
103 timestamp DATETIME NOT NULL,
104 PRIMARY KEY (id)
105 )
106 CHARACTER SET 'utf8mb4'
107 COLLATE 'utf8mb4_0900_ai_ci';`,
108 function (err, results) {
109 if (err => {
110 throw err;
111 });
112 }
113 );
114 connection.query(
115 `CREATE TABLE IF NOT EXISTS voiceTypes
116 (
117 id int NOT NULL,
118 guildID VARCHAR(25) NOT NULL,
119 type VARCHAR(100),
120 PRIMARY KEY (id)
121 )
122 CHARACTER SET 'utf8mb4'
123 COLLATE 'utf8mb4_general_ci';`,
124 function (err, results) {
125 if (err => {
126 throw err;
127 });
128 }
129 );
130 connection.query(
131 `CREATE TABLE IF NOT EXISTS log_voice
132 (
133 id int NOT NULL AUTO_INCREMENT,
134 userID VARCHAR(25) NOT NULL,
135 guildID VARCHAR(25) NOT NULL,
136 newChannelID VARCHAR (50),
137 newChannel VARCHAR (50),
138 oldChannelID VARCHAR (50),
139 oldChannel VARCHAR (50),
140 type int,
141 timestamp DATETIME NOT NULL,
142 PRIMARY KEY (id),
143 FOREIGN KEY (type) REFERENCES voiceTypes(id)
144 )
145 CHARACTER SET 'utf8mb4'
146 COLLATE 'utf8mb4_general_ci';`,
147 function (err, results) {
148 if (err => {
149 throw err;
150 });
151 }
152 );
153 connection.query(
154 `CREATE TABLE IF NOT EXISTS log_guildjoin
155 (
156 userID VARCHAR(25) NOT NULL,
157 guildID VARCHAR(25) NOT NULL,
158 timestamp DATETIME
159 )
160 CHARACTER SET 'utf8mb4'
161 COLLATE 'utf8mb4_0900_ai_ci';`,
162 function (err, results) {
163 if (err => {
164 throw err;
165 });
166 }
167 );
168 connection.query(
169 `CREATE TABLE IF NOT EXISTS log_guildleave
170 (
171 userID VARCHAR(25) NOT NULL,
172 guildID VARCHAR(25) NOT NULL,
173 timestamp DATETIME
174 )
175 CHARACTER SET 'utf8mb4'
176 COLLATE 'utf8mb4_0900_ai_ci';`,
177 function (err, results) {
178 if (err => {
179 throw err;
180 });
181 }
182 );
183 connection.query(
184 `CREATE TABLE IF NOT EXISTS log_guildbans
185 (
186 ID INT NOT NULL AUTO_INCREMENT,
187 userID VARCHAR(25),
188 guildID VARCHAR(25) NOT NULL,
189 actioner VARCHAR(25),
190 description TEXT,
191 identifier VARCHAR(10),
192 isDeleted BIT,
193 timestamp DATETIME,
194 updated DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
195 PRIMARY KEY (ID)
196 )
197 CHARACTER SET 'utf8mb4'
198 COLLATE 'utf8mb4_0900_ai_ci';`,
199 function (err, results) {
200 if (err => {
201 throw err;
202 });
203 }
204 );
205 connection.query(
206 `CREATE TABLE IF NOT EXISTS log_guildunbans
207 (
208 ID INT NOT NULL AUTO_INCREMENT,
209 userID VARCHAR(25),
210 guildID VARCHAR(25) NOT NULL,
211 actioner VARCHAR(25),
212 description text,
213 identifier VARCHAR(10),
214 isDeleted BIT,
215 timestamp DATETIME,
216 updated DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
217 PRIMARY KEY (ID)
218 )
219 CHARACTER SET 'utf8mb4'
220 COLLATE 'utf8mb4_0900_ai_ci';`,
221 function (err, results) {
222 if (err => {
223 throw err;
224 });
225 }
226 );
227 connection.query(
228 `CREATE TABLE IF NOT EXISTS log_note
229 (
230 ID INT NOT NULL AUTO_INCREMENT,
231 userID VARCHAR(25),
232 guildID VARCHAR(25) NOT NULL,
233 actioner VARCHAR(25),
234 description TEXT,
235 identifier VARCHAR(10),
236 isDeleted BIT,
237 timestamp DATETIME NOT NULL,
238 updated DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
239 PRIMARY KEY (id)
240 )
241 CHARACTER SET 'utf8mb4'
242 COLLATE 'utf8mb4_0900_ai_ci';`,
243 function (err, results) {
244 if (err => {
245 throw err;
246 });
247 }
248 );
249 connection.query(
250 `CREATE TABLE IF NOT EXISTS log_warn
251 (
252 ID INT NOT NULL AUTO_INCREMENT,
253 userID VARCHAR(25),
254 guildID VARCHAR(25) NOT NULL,
255 actioner VARCHAR(25),
256 description TEXT,
257 identifier VARCHAR(10),
258 isDeleted BIT,
259 timestamp DATETIME,
260 updated DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
261 PRIMARY KEY (id)
262 )
263 CHARACTER SET 'utf8mb4'
264 COLLATE 'utf8mb4_0900_ai_ci';`,
265 function (err, results) {
266 if (err => {
267 throw err;
268 });
269 }
270 );
271 connection.query(
272 `CREATE TABLE IF NOT EXISTS log_outgoingdm
273 (
274 id int NOT NULL AUTO_INCREMENT,
275 userID VARCHAR(25) NOT NULL,
276 guildID VARCHAR(25) NOT NULL,
277 content text,
278 type TINYINT,
279 isDeleted bit,
280 identifier VARCHAR(10),
281 timestamp DATETIME NOT NULL,
282 updated timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
283 PRIMARY KEY (id)
284 )
285 CHARACTER SET 'utf8mb4'
286 COLLATE 'utf8mb4_0900_ai_ci';`,
287 function (err, results) {
288 if (err => {
289 throw err;
290 });
291 }
292 );
293 connection.query(
294 `CREATE TABLE IF NOT EXISTS log_mutes
295 (
296 ID INT NOT NULL AUTO_INCREMENT,
297 userID VARCHAR(25),
298 guildID VARCHAR(25) NOT NULL,
299 actioner VARCHAR(25),
300 description TEXT,
301 length MEDIUMINT,
302 identifier VARCHAR(10),
303 isDeleted BIT,
304 timestamp DATETIME,
305 updated DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
306 PRIMARY KEY (id)
307 )
308 CHARACTER SET 'utf8mb4'
309 COLLATE 'utf8mb4_0900_ai_ci';`,
310 function (err, results) {
311 if (err => {
312 throw err;
313 });
314 }
315 );
316 connection.query(
317 `INSERT IGNORE INTO messageTypes (id, type) VALUES (1, "create"), (2, "edit"), (3, "delete")`,
318 function (err, results) {
319 if (err => {
320 throw err;
321 });
322 }
323 );
324 connection.query(
325 `INSERT IGNORE INTO voiceTypes (id, type) VALUES (1, "join"), (2, "move"), (3, "leave")`,
326 function (err, results) {
327 if (err => {
328 throw err;
329 });
330 }
331 );
332}
333
334function parseUserTag(tag) {
335 var trimMe = tag.trim();
336
337 if (/(<@(!)*)+\w+(>)/.test(tag)) {
338 return trimMe.replace(/[^0-9.]/gi, ``);
339 } else if (/[\w\d\\\/\_\|]+(#\d\d\d\d)+$/.test(tag)) {
340 var split = tag.split(`#`);
341 var usernameResolve = client.users.find(obj => obj.username === split[0]);
342
343 if (usernameResolve.discriminator == split[1]) {
344 return usernameResolve.id;
345 } else {
346 return `err`;
347 }
348 } else if (/^[0-9]+$/.test(tag)) {
349 return trimMe;
350 } else {
351 var usernameResolve = client.users.find(obj => obj.username === tag);
352 var nicknameResolve = client.users.find(obj => obj.nickname === tag);
353
354 if (usernameResolve) {
355 return usernameResolve.id;
356 } else if (nicknameResolve) {
357 return nicknameResolve.id;
358 } else {
359 return `user not found`;
360 }
361 }
362}
363
364function updateUserTable(invoker, channel, guild) {
365 var memberArray = [];
366
367 client.guilds.get(guild).fetchMembers().then(r => {
368 r.members.array().forEach(r => {
369 memberArray.push([r.user.id, r.guild.id, r.user.username, r.user.avatar, 1, r.joinedAt]);
370 });
371 connection.query(
372 `INSERT IGNORE INTO users (userID, guildID, username, avatar, exist, timestamp) VALUES ?`, [memberArray],
373 function (err, results) {
374 if (err => {
375 throw err;
376 });
377 if (results) {
378 switch (invoker) {
379 case "user":
380 const updateUserTableEmbed = new Discord.RichEmbed()
381 .setColor(locale.info_color)
382 .setAuthor(locale.bot_name, locale.bot_avatar_link)
383 .setTitle(`**User update**`)
384 .setDescription(`Users that are not in the database will be inserted`)
385 .addField(`Total users found`, memberArray.length, true)
386 .addField(`Total users inserted`, results.affectedRows, true)
387 .setTimestamp()
388 .setFooter(`Gab's Child | Version: ${config.version}`)
389 if(channel === undefined) return;
390 client.channels.get(channel).send(updateUserTableEmbed);
391 }
392 }
393 }
394 );
395 })
396}
397
398function updateGuildBansTable(invoker, channel) {
399 var banArray = [];
400 var guild = message.guild;
401
402 guild.fetchBans().then(bans => {
403 bans.array().forEach(ban => {
404 banArray.push([ban.id, ban.username, ban.discriminator, `001`, null, `Ban inserted via a call to updateGuildBansTable`, new Date()]);
405 });
406 connection.query(
407 `INSERT IGNORE INTO log_guildbans (userID, username, discriminator, bannedBy, reason, note, timestamp) VALUES ?`, [banArray],
408 function (results) {
409 switch (invoker) {
410 case `user`:
411 const updateGuildBansTableEmbed = new Discord.RichEmbed()
412 .setColor(locale.info_color)
413 .setAuthor(locale.bot_name, locale.bot_avatar_link)
414 .setTitle(`**Bans update**`)
415 .setDescription(`Bans that are not in the database will be inserted`)
416 .addField(`Total bans found`, bans.size, true)
417 .addField(`Total bans inserted`, results.affectedRows, true)
418 .setTimestamp()
419 .setFooter(`Gab's Child | Version: ${config.version}`);
420
421 client.channels.get(channel).send(updateGuildBansTableEmbed);
422 }
423 }
424 );
425 })
426}
427
428function checkExpiredMutes() {
429 var gKeys = _.keys(channelsFile.read());
430 for (var i = 0; i < gKeys.length; i++) {
431 var guild = client.guilds.get(gKeys[i]);
432 var mutes = mutedFile.read();
433 var muteKeys = _.keys(mutes);
434
435 for (var a = 0; a < muteKeys.length; a++) {
436 let key = muteKeys[a];
437 if (mutes[key].end < Math.floor(Date.now() / 1000 && mutes[key].guild == guild.id)) {
438 var actionee = guild.member(key);
439 var mutedRole = guild.roles.find(val => val.id === config.muted_role);
440
441 if (actionee) {
442 actionee.removeRole(mutedRole)
443 .then(member => {
444 guild.channels.find(val => val.id === config.server_log).send(updateGuildBansTableEmbed = new Discord.RichEmbed()
445 .setColor(locale.info_color)
446 .setAuthor(locale.bot_name, locale.bot_avatar_link)
447 .setTitle(`**Mute expired**`)
448 .setDescription(`Mute of user ${member} has expired`)
449 .setTimestamp()
450 .setFooter(`Gab's Child | Version: ${config.version}`));
451
452 mutedFile.unset(key);
453 mutedFile.save();
454 })
455 .catch(console.error);
456 } else {
457 console.log(`Actionee could not be found ${key}`);
458 mutedFile.unset(key);
459 mutedFile.save();
460 }
461 }
462 }
463 }
464}
465
466function checkMessageContent(message) {
467 var wholeMessage = (message.content).split(` `);
468 if (!message.member.roles.some(role => ["Admin"].includes(role.name))) {
469 var badWordsList = _.keys(badWordsFile.read());
470 if (badWordsList.some(word => wholeMessage.includes(word))) {
471 message.delete();
472 deletedByBot = 1;
473 }
474 } else {
475 return;
476 }
477}
478
479// Bot Ready Listener Event
480client.on(`ready`, () => {
481 console.log(`Bot has started and logged in.`);
482
483 setupTables();
484
485 var gKeys = _.keys(channelsFile.read());
486 var i = 0;
487
488 function loop() {
489 setTimeout( function(){
490 var guild = gKeys[i];
491 updateUserTable(`user`, channelsFile.get(guild).bot_log, guild);
492 //updateGuildBansTable(`user`, channelsFile.get(guild).bot_log);
493 i++;
494 if(i<gKeys.length) loop();
495 }, 100)
496 }
497 loop();
498
499 setInterval(checkExpiredMutes, 10000);
500
501});
502
503// Message Received Listener Event
504client.on(`message`, async message => {
505 if (message.author.bot) return;
506 if (_.indexOf(["dm", "group"], message.channel.type) !== -1) return;
507
508 checkMessageContent(message);
509
510 if (message.content.indexOf(config.prefix) !== 0) return;
511
512 const args = message.content.slice(config.prefix.length).split(/ +/);
513 const command = args.shift().toLowerCase();
514
515 // Help command
516 if (command === `help`) {
517 if (!message.member.roles.some(role => ["Admin"].includes(role.name))) {
518 const helpEmbed = new Discord.RichEmbed()
519 .setColor(locale.info_color)
520 .setAuthor(locale.bot_name, locale.bot_avatar_link)
521 .setTitle(`**Listing all commands**`)
522 .setDescription(`**General Commands**\n
523 \`${config.prefix}help\` - lists all commands\n
524 \`${config.prefix}ping\` - shows bot's latency and API latency`)
525 .setTimestamp()
526 .setFooter(`Gab's Child | Version: ${config.version}`);
527 message.channel.send(helpEmbed);
528 } else if (message.member.roles.some(role => ["Admin"].includes(role.name))) {
529 const adminHelpEmbed = new Discord.RichEmbed()
530 .setColor(locale.info_color)
531 .setAuthor(locale.bot_name, locale.bot_avatar_link)
532 .setTitle(`**Listing all commands**`)
533 .setDescription(`**General Commands**
534 \`${config.prefix}help\` - lists all commands
535 \`${config.prefix}status\` - shows bot's status
536 \n**Admin Commands**\n
537 \`${config.prefix}badwords list\` - lists all bad words
538 \`${config.prefix}badwords add <word>\` - adds a bad word
539 \`${config.prefix}badwords remove <word>\` - removes a bad word
540 \`${config.prefix}user <user>\` - shows information of a user
541 \`${config.prefix}users count\` - shows how many users are inserted into database
542 \`${config.prefix}users update\` - inserts all users into database
543 \`${config.prefix}ban <user> <reason>\` - bans a user
544 \`${config.prefix}unban <user> <reason>\` - unbans a user
545 \`${config.prefix}warn <user> <reason>\` - warns a user
546 \`${config.prefix}cwarn <identifier>\` - removes a warning
547 \`${config.prefix}mute <user> <duration> <reason>\` - mutes a user
548 \`${config.prefix}disconnect <user>\` - disconnects a user from their voice channel
549 \`${config.prefix}note <user> <reason>\` - adds a note to a user
550 \`${config.prefix}cnote <identifier>\` - removes a note
551 \`${config.prefix}voicelog <user>\` - shows a user's voice log`)
552 .setTimestamp()
553 .setFooter(`Gab's Child | Version: ${config.version}`);
554
555 message.channel.send(adminHelpEmbed);
556 }
557 }
558
559 // Ping command
560 if (command === `status`) {
561 var client_ping = Math.floor(client.ping);
562 var db_ping = connection.ping();
563
564 var client_status;
565 var db_status;
566
567 if (client_ping >= 1 && client_ping <= 500) {
568 client_status = `OK`;
569 } else if (client_ping > 500 && client_ping <= 5000) {
570 client_status = `Degraded`;
571 } else {
572 client_status = `Severely degraded or error`;
573 }
574
575 if (db_ping) {
576 db_status = `OK`;
577 } else {
578 db_status = `Severely degraded or error`;
579 }
580
581 message.channel.send(new Discord.RichEmbed()
582 .setColor(locale.info_color)
583 .setAuthor(locale.bot_name, locale.bot_avatar_link)
584 .setTitle(`**Bot status**`)
585 .addField(`Client`, `${client_status} (${client_ping}ms)`, true)
586 .addField(`Database`, `${db_status}`, true)
587 .setTimestamp()
588 .setFooter(`Gab's Child | Version: ${config.version}`));
589 }
590
591 // Ban command
592 if (command === `ban`) {
593 if (!message.member.roles.some(role => ["Admin"].includes(role.name))) {
594 return;
595 } else if (!args[0]) {
596 message.channel.send(`:x: Wrong command syntax. Please use \`${config.prefix}help\` to view all commands.`);
597 } else if (args[0]) {
598 var user = parseUserTag(args[0]);
599 var guild = message.guild;
600
601 if (user == `err`) {
602 message.channel.send(`:x: Could not find user ${user}.`);
603 } else {
604 if (guild.member(user)) {
605 if (message.member.highestRole.comparePositionTo(guild.member(user).highestRole) > 0) {
606 var tail = args.slice(1);
607 var reason = tail.join(` `).trim();
608
609 if (tail.length > 0) {
610 var identifier = cryptoRandomString({
611 length: 10
612 });
613
614 client.users.get(user).createDM().then(async chnl => {
615 const userBannedDMEmbed = new Discord.RichEmbed()
616 .setColor(locale.bad_color)
617 .setAuthor(locale.bot_name, locale.bot_avatar_link)
618 .setTitle(`**You have been banned from ${guild.name}**`)
619 .setDescription(`Details about the ban:`)
620 .addField(`Ban reason`, `${reason}`, false)
621 .addField(`Identifier`, `${identifier}`, false)
622 .setTimestamp()
623 .setFooter(`Gab's Child | Version: ${config.version}`)
624 chnl.send(userBannedDMEmbed).then(dm => {
625 var data = [user, message.guild.id, `Title: ${dm.embeds[0].title}`, 2, 0, identifier, new Date(), new Date()];
626 connection.query(`INSERT INTO log_outgoingdm(userid, guildId, content, type, isDeleted, identifier, timestamp, updated) VALUES(?,?,?,?,?,?,?,?)`, data)
627 });
628
629 guild.ban(user, {
630 days: 1,
631 reason: reason
632 }).then(async result => {
633 const userBannedEmbed = new Discord.RichEmbed()
634 .setColor(locale.good_color)
635 .setAuthor(result.username, result.avatarURL)
636 .setTitle(`**User banned**`)
637 .setDescription(`${client.users.get(user)} has been successfully banned`)
638 .addField(`User ID`, `${result.id}`, true)
639 .addField(`Username`, `${result.username}#${result.discriminator}`, true)
640 .addField(`Reason`, `${reason}`, false)
641 .addField(`Banned by`, `${message.author}`, false)
642 .addField(`Identifier`, `${identifier}`, false)
643 .setTimestamp()
644 .setFooter(`Gab's Child | Version: ${config.version}`)
645
646 message.channel.send(userBannedEmbed);
647
648 var data = [result.id, guild.id, message.author.id, reason, identifier, 0, new Date()];
649 connection.query(
650 `INSERT INTO log_guildbans (userID, guildID, actioner, description, identifier, isDeleted, timestamp) VALUES (?,?,?,?,?,?,?)`, data,
651 function (err, results) {
652 if (err => {
653 throw err;
654 });
655 })
656
657 bannedUsersFile.set(identifier, result.username);
658 bannedUsersFile.save();
659
660 });
661 });
662 } else {
663 message.channel.send(`:x: Please provide a reason for the ban.`)
664 }
665 } else {
666 message.channel.send(`:x: You cannot ban a user with a higher role than yourself.`);
667 }
668 } else {
669 message.channel.send(`:x: The specified user was not found.`)
670 }
671 }
672 } else if (!message.member.roles.some(role => ["Admin"].includes(role.name))) {
673 return;
674 }
675 }
676
677 // Unban command
678 if (command === `unban`) {
679 if (!message.member.roles.some(role => ["Admin"].includes(role.name))) {
680 return;
681 } else if (!args[0]) {
682 message.channel.send(`:x: Wrong command syntax. Please use \`${config.prefix}help\` to view all commands.`);
683 } else if (args[0]) {
684 var user = parseUserTag(args[0]);
685 var guild = message.guild;
686
687 if (user == `err`) {
688 message.channel.send(`:x: Could not find user ${user}.`);
689 } else {
690 if (client.fetchUser(user)) {
691 var tail = args.slice(1);
692 var reason = tail.join(` `).trim();
693
694 if (tail.length > 0) {
695 guild.unban(user, reason).then(result => {
696 var identifier = cryptoRandomString({
697 length: 10
698 });
699 const userUnbannedEmbed = new Discord.RichEmbed()
700 .setColor(locale.good_color)
701 .setAuthor(result.username, result.avatarURL)
702 .setTitle(`**User unbanned**`)
703 .setDescription(`${client.users.get(user)} has been successfully unbanned`)
704 .addField(`User ID`, `${result.id}`, true)
705 .addField(`Username`, `${result.username}#${result.discriminator}`, true)
706 .addField(`Reason`, `${reason}`, false)
707 .addField(`Unbanned by`, `${message.author}`, false)
708 .addField(`Identifier`, `${identifier}`, false)
709 .setTimestamp()
710 .setFooter(`Gab's Child | Version: ${config.version}`)
711
712 message.channel.send(userUnbannedEmbed);
713
714 var data = [result.id, guild.id, message.author.id, reason, identifier, 0, new Date()];
715 connection.query(
716 `INSERT INTO log_guildunbans (userID, guildID, actioner, description, identifier, isDeleted, timestamp) VALUES (?,?,?,?,?,?,?)`, data,
717 function (err, results) {
718 if (err => {
719 throw err;
720 });
721 });
722 var dataTwo = [result.id, guild.id];
723 connection.query(`
724 SELECT identifier FROM log_guildbans WHERE userID = ? AND guildID = ? ORDER BY timestamp DESC LIMIT 1`, dataTwo);
725
726 bannedUsersFile.set(identifier, result.username);
727 bannedUsersFile.save();
728
729 }).catch(err => {
730 if (err.message === `Unknown Ban`) {
731 message.channel.send(`:x: The specified user is not banned!`);
732 } else {
733 console.log(err);
734 }
735 });
736 } else {
737 message.channel.send(`:x: Please provide a reason for the unban.`)
738 }
739 } else {
740 message.channel.send(`:x: The specified user was not found.`)
741 }
742 }
743 } else if (!message.member.roles.some(role => ["Admin"].includes(role.name))) {
744 return;
745 }
746 }
747
748 // User command
749 if (command === `user`) {
750 if (message.member.roles.some(role => ["Admin"].includes(role.name))) {
751 if (!args[0]) {
752 message.channel.send(`:x: Wrong command syntax. Please use \`${config.prefix}help\` to view all commands.`);
753 return;
754 }
755 var userID = parseUserTag(args[0]);
756 var globalUser = client.users.get(userID);
757 var guild = message.guild;
758 var userObject = guild.member(globalUser);
759
760 if (userObject) {
761 var nickname;
762 var voiceChannel;
763 var game;
764
765 if (userObject.displayName && userObject.user.username != userObject.displayName) {
766 nickname = userObject.displayName
767 } else {
768 nickname = "No nickname"
769 };
770 if (userObject.voiceChannel) {
771 voiceChannel = userObject.voiceChannel.name
772 } else {
773 voiceChannel = "Not in voice channel"
774 };
775 if (userObject.presence.game) {
776 game = userObject.presence.game.name
777 } else {
778 game = "None"
779 };
780
781 const userEmbed = new Discord.RichEmbed()
782 .setColor(locale.info_color)
783 .setAuthor(`Information of ${userObject.user.username} (${nickname})`, userObject.user.avatarURL)
784 .setThumbnail(userObject.user.avatarURL)
785 .setDescription(`${userObject.user} joined ${userObject.guild.name} on ${userObject.joinedAt}`)
786 .addField(`Created`, userObject.user.createdAt, false)
787 .addField(`Status`, `${(userObject.presence.status).toUpperCase()}`, true)
788 .addField(`Game`, game, true)
789 .addField(`Voice channel`, voiceChannel, false)
790 .setTimestamp()
791 .setFooter(`Gab's Child | Version: ${config.version}`);
792
793 message.channel.send(userEmbed).then(async message => {
794 await message.react("?");
795 await message.react("?");
796 await message.react("?");
797 await message.react("✍");
798 await message.react("?");
799 await message.react("❌");
800
801 const filter = (reaction, user) => user.bot == false;
802 const collector = message.createReactionCollector(filter);
803
804 collector.on(`collect`, async r => {
805 if (r.emoji.name == `?`) {
806 await r.remove(r.users.last());
807 message.edit(new Discord.RichEmbed()
808 .setColor(locale.info_color)
809 .setAuthor(`Information of ${userObject.user.username} (${nickname})`, userObject.user.avatarURL)
810 .setThumbnail(userObject.user.avatarURL)
811 .setDescription(`${userObject.user} joined ${userObject.guild.name} on ${userObject.joinedAt}`)
812 .addField(`Created`, userObject.user.createdAt, false)
813 .addField(`Status`, `${(userObject.presence.status).toUpperCase()}`, true)
814 .addField(`Game`, game, true)
815 .addField(`Voice channel`, voiceChannel, false)
816 .setTimestamp()
817 .setFooter(`Gab's Child | Version: ${config.version}`));
818 } else if (r.emoji.name == `?`) {
819 await r.remove(r.users.last());
820
821 connection.query(`(SELECT 'unban' as \`type\`, gub.* FROM log_guildunbans gub WHERE gub.userid = ${connection.escape(userID)} AND gub.isDeleted = 0 AND gub.guildID = ${connection.escape(guild.id)}
822 UNION ALL SELECT 'ban' as \`type\`, gb.* FROM log_guildbans gb WHERE gb.userid = ${connection.escape(userID)} AND gb.guildID = ${connection.escape(guild.id)} AND gb.isDeleted = 0 AND gb.actioner <> '001' UNION ALL
823 SELECT 'warn' AS \`type\`, w.* FROM log_warn w WHERE w.userid = ${connection.escape(userID)} AND w.isDeleted = 0 AND w.guildID = ${connection.escape(guild.id)}) ORDER BY timestamp DESC`,
824 async function (err, rows, results) {
825 if (err) throw err;
826 var events = [];
827 var max = 5;
828 var extra;
829
830 if (rows.length <= max) {
831 max = rows.length;
832 } else {
833 extra = rows.length - max;
834 }
835
836 for (var i = 0; i < max; i++) {
837 var row = rows[i];
838 if (row.type == `warn`) {
839 await events.push(`\`${row.identifier}\` :exclamation: Warned by ${client.users.get(row.actioner)} on ${row.timestamp}\n\`\`\`${row.description}\`\`\`\n`);
840 } else if (row.type == `ban`) {
841 await events.push(`\`${row.identifier}\` :crossed_swords: Banned by ${client.users.get(row.actioner)} on ${row.timestamp}\n\`\`\`${row.description}\`\`\`\n`);
842 } else if (row.type == `unban`) {
843 await events.push(`\`${row.identifier}\` :shield: Unbanned by ${client.users.get(row.actioner)} on ${row.timestamp}\n\`\`\`${row.description}\`\`\`\n`);
844 }
845 if (i == max - 1 && extra > 0) {
846 events.push(`...${extra} more`);
847 }
848 }
849 if (!_.isEmpty(events)) {
850 await message.edit(new Discord.RichEmbed()
851 .setColor(locale.info_color)
852 .setAuthor(`Infractions of ${userObject.user.username} (${nickname})`, userObject.user.avatarURL)
853 .setDescription(events.join(`\n`))
854 .setTimestamp()
855 .setFooter(`Gab's Child | Version: ${config.version}`));
856 } else {
857 await message.edit(new Discord.RichEmbed()
858 .setColor(locale.info_color)
859 .setAuthor(`Infractions of ${userObject.user.username} (${nickname})`, userObject.user.avatarURL)
860 .setDescription(`This user has no infractions`)
861 .setTimestamp()
862 .setFooter(`Gab's Child | Version: ${config.version}`));
863 }
864 })
865 } else if (r.emoji.name == `?`) {
866 await r.remove(r.users.last());
867
868 connection.query(`SELECT * FROM log_mutes WHERE userID = ? AND guildID = ${connection.escape(guild.id)} AND isDeleted = 0 ORDER BY timestamp DESC`, userID, async function (err, rows, results) {
869 if (err) throw err;
870 var mutes = [];
871 var max = 5;
872 var extra;
873
874 if (rows.length <= 5) {
875 max = rows.length;
876 } else {
877 extra = rows.length - max;
878 }
879
880 for (var i = 0; i < max; i++) {
881 var row = rows[i];
882 await mutes.push(`\`${row.identifier}\` :mute: Muted by ${client.users.get(row.actioner)} on ${row.timestamp} for ${row.length}s\n\`\`\`${row.description}\`\`\`\n`)
883 if (i == max - 1 && extra > 0) {
884 mutes.push(`...${extra} more`);
885 }
886 }
887 if (!_.isEmpty(mutes)) {
888 await message.edit(new Discord.RichEmbed()
889 .setColor(locale.info_color)
890 .setAuthor(`Mutes of ${userObject.user.username} (${nickname})`, userObject.user.avatarURL)
891 .setDescription(mutes.join(" "))
892 .setTimestamp()
893 .setFooter(`Gab's Child | Version: ${config.version}`));
894 } else {
895 await message.edit(new Discord.RichEmbed()
896 .setColor(locale.info_color)
897 .setAuthor(`Mutes of ${userObject.user.username} (${nickname})`, userObject.user.avatarURL)
898 .setDescription(`This user has no mutes`)
899 .setTimestamp()
900 .setFooter(`Gab's Child | Version: ${config.version}`));
901 }
902 })
903 } else if (r.emoji.name == `✍`) {
904 await r.remove(r.users.last());
905
906 connection.query(`SELECT * FROM log_note WHERE userID = ? AND guildID = ${connection.escape(guild.id)} AND isDeleted = 0 ORDER BY timestamp DESC`, userID, async function (err, rows, results) {
907 if (err) throw err;
908 var notes = [];
909 for (var i = 0; i < rows.length; i++) {
910 var row = rows[i];
911 await notes.push(`\`${row.identifier}\` :pushpin: Note by ${client.users.get(row.actioner)} on ${row.timestamp}\n\`\`\`${row.description}\`\`\`\n`)
912 }
913 if (!_.isEmpty(notes)) {
914 message.edit(new Discord.RichEmbed()
915 .setColor(locale.info_color)
916 .setAuthor(`Notes of ${userObject.user.username} (${nickname})`, userObject.user.avatarURL)
917 .setDescription(notes.join(" "))
918 .setTimestamp()
919 .setFooter(`Gab's Child | Version: ${config.version}`));
920 } else {
921 message.edit(new Discord.RichEmbed()
922 .setColor(locale.info_color)
923 .setAuthor(`Notes of ${userObject.user.username} (${nickname})`, userObject.user.avatarURL)
924 .setDescription(`This user has no notes`)
925 .setTimestamp()
926 .setFooter(`Gab's Child | Version: ${config.version}`));
927 }
928 })
929 } else if (r.emoji.name == `?`) {
930 await r.remove(r.users.last());
931 connection.query(`
932 SELECT Status, timestamp FROM(SELECT *, 'join' AS Status from log_guildjoin WHERE userid = ? AND guildID = ${connection.escape(guild.id)}
933 UNION SELECT *, 'leave' AS Status FROM log_guildleave WHERE userid = ? AND guildID = ${connection.escape(guild.id)}) a
934 ORDER BY timestamp DESC`, [userID, userID], async function (err, rows, results) {
935 if (err) throw err;
936 var history = [];
937 var max = 5;
938 var extra;
939
940 if (rows.length <= 5) {
941 max = rows.length;
942 } else {
943 extra = rows.length - max;
944 }
945
946 for (var i = 0; i < max; i++) {
947 var row = rows[i];
948 switch (row.Status) {
949 case `join`:
950 history.push(`:inbox_tray: ${userObject.user.username} joined ${guild.name} at \`\`\`${new Date(row.timestamp)}\`\`\`\n`);
951 break;
952 case `leave`:
953 history.push(`:outbox_tray: ${userObject.user.username} left ${guild.name} at \`\`\`${new Date(row.timestamp)}\`\`\`\n`);
954 break;
955 }
956
957 if (i == max - 1 && extra > 0) {
958 history.push(`...${extra} more`);
959 }
960 }
961
962 if (!_.isEmpty(history)) {
963 await message.edit(new Discord.RichEmbed()
964 .setColor(locale.info_color)
965 .setAuthor(`Join/Leave history of ${userObject.user.username} (${nickname})`, userObject.user.avatarURL)
966 .setDescription(history.join(" "))
967 .setTimestamp()
968 .setFooter(`Gab's Child | Version: ${config.version}`));
969 } else {
970 await message.edit(new Discord.RichEmbed()
971 .setColor(locale.info_color)
972 .setAuthor(`Notes of ${userObject.user.username} (${nickname})`, userObject.user.avatarURL)
973 .setDescription(`This user has no Join/Leave history`)
974 .setTimestamp()
975 .setFooter(`Gab's Child | Version: ${config.version}`))
976 }
977 })
978 } else if (r.emoji.name == `❌`) {
979 message.delete();
980 }
981 })
982
983 });
984 } else if (globalUser) {
985 const userEmbed = new Discord.RichEmbed()
986 .setColor(locale.info_color)
987 .setAuthor(`Information of ${globalUser.username}`, globalUser.avatarURL)
988 .setThumbnail(globalUser.avatarURL)
989 .setDescription(`The user is not present in this guild`)
990 .setTimestamp()
991 .setFooter(`Gab's Child | Version: ${config.version}`);
992
993 message.channel.send(userEmbed).then(async message => {
994 await message.react("?");
995 await message.react("?");
996 await message.react("?");
997 await message.react("✍");
998 await message.react("?");
999 await message.react("❌");
1000
1001 const filter = (reaction, user) => user.bot == false;
1002 const collector = message.createReactionCollector(filter);
1003
1004 collector.on(`collect`, async r => {
1005 if (r.emoji.name == `?`) {
1006 await r.remove(r.users.last());
1007 message.edit(new Discord.RichEmbed()
1008 .setColor(locale.info_color)
1009 .setAuthor(`Information of ${globalUser.username}`, globalUser.avatarURL)
1010 .setThumbnail(globalUser.avatarURL)
1011 .setDescription(`The user is not present in this guild`)
1012 .setTimestamp()
1013 .setFooter(`Gab's Child | Version: ${config.version}`));
1014 } else if (r.emoji.name == `?`) {
1015 await r.remove(r.users.last());
1016
1017 connection.query(`(SELECT 'unban' as \`type\`, gub.* FROM log_guildunbans gub WHERE gub.userid = ${connection.escape(userID)} AND gub.isDeleted = 0 AND gub.guildID = ${connection.escape(guild.id)}
1018 UNION ALL SELECT 'ban' as \`type\`, gb.* FROM log_guildbans gb WHERE gb.userid = ${connection.escape(userID)} AND gb.isDeleted = 0 AND gb.actioner AND gb.guildID = ${connection.escape(guild.id)} <> '001' UNION ALL
1019 SELECT 'warn' AS \`type\`, w.* FROM log_warn w WHERE w.userid = ${connection.escape(userID)} AND w.isDeleted = 0 AND w.guildID = ${connection.escape(guild.id)}) ORDER BY timestamp DESC`,
1020 async function (err, rows, results) {
1021 if (err) throw err;
1022 var events = [];
1023 var max = 5;
1024 var extra;
1025
1026 if (rows.length <= max) {
1027 max = rows.length;
1028 } else {
1029 extra = rows.length - max;
1030 }
1031
1032 for (var i = 0; i < max; i++) {
1033 var row = rows[i];
1034 if (row.type == `warn`) {
1035 await events.push(`\`${row.identifier}\` :exclamation: Warned by ${client.users.get(row.actioner)} on ${row.timestamp}\n\`\`\`${row.description}\`\`\`\n`);
1036 } else if (row.type == `ban`) {
1037 await events.push(`\`${row.identifier}\` :crossed_swords: Banned by ${client.users.get(row.actioner)} on ${row.timestamp}\n\`\`\`${row.description}\`\`\`\n`);
1038 } else if (row.type == `unban`) {
1039 await events.push(`\`${row.identifier}\` :shield: Unbanned by ${client.users.get(row.actioner)} on ${row.timestamp}\n\`\`\`${row.description}\`\`\`\n`);
1040 }
1041 if (i == max - 1 && extra > 0) {
1042 events.push(`...${extra} more`);
1043 }
1044 }
1045 if (!_.isEmpty(events)) {
1046 await message.edit(new Discord.RichEmbed()
1047 .setColor(locale.info_color)
1048 .setAuthor(`Infractions of ${globalUser.username}`, globalUser.avatarURL)
1049 .setDescription(events.join(`\n`))
1050 .setTimestamp()
1051 .setFooter(`Gab's Child | Version: ${config.version}`));
1052 } else {
1053 await message.edit(new Discord.RichEmbed()
1054 .setColor(locale.info_color)
1055 .setAuthor(`Infractions of ${globalUser.username}`, globalUser.avatarURL)
1056 .setDescription(`This user has no infractions`)
1057 .setTimestamp()
1058 .setFooter(`Gab's Child | Version: ${config.version}`));
1059 }
1060 })
1061 } else if (r.emoji.name == `?`) {
1062 await r.remove(r.users.last());
1063
1064 connection.query(`SELECT * FROM log_mutes WHERE userID = ? AND guildID = ${connection.escape(guild.id)} AND isDeleted = 0 ORDER BY timestamp DESC`, userID, async function (err, rows, results) {
1065 if (err) throw err;
1066 var mutes = [];
1067 var max = 5;
1068 var extra;
1069
1070 if (rows.length <= 5) {
1071 max = rows.length;
1072 } else {
1073 extra = rows.length - max;
1074 }
1075
1076 for (var i = 0; i < max; i++) {
1077 var row = rows[i];
1078 await mutes.push(`\`${row.identifier}\` :mute: Muted by ${client.users.get(row.actioner)} on ${row.timestamp} for ${row.length}s\n\`\`\`${row.description}\`\`\`\n`)
1079 if (i == max - 1 && extra > 0) {
1080 mutes.push(`...${extra} more`);
1081 }
1082 }
1083 if (!_.isEmpty(mutes)) {
1084 await message.edit(new Discord.RichEmbed()
1085 .setColor(locale.info_color)
1086 .setAuthor(`Mutes of ${globalUser.username}`, globalUser.avatarURL)
1087 .setDescription(mutes.join(" "))
1088 .setTimestamp()
1089 .setFooter(`Gab's Child | Version: ${config.version}`));
1090 } else {
1091 await message.edit(new Discord.RichEmbed()
1092 .setColor(locale.info_color)
1093 .setAuthor(`Mutes of ${globalUser.username}`, globalUser.avatarURL)
1094 .setDescription(`This user has no mutes`)
1095 .setTimestamp()
1096 .setFooter(`Gab's Child | Version: ${config.version}`));
1097 }
1098 })
1099 } else if (r.emoji.name == `✍`) {
1100 await r.remove(r.users.last());
1101
1102 connection.query(`SELECT * FROM log_note WHERE userID = ? AND guildID = ${connection.escape(guild.id)} AND isDeleted = 0 ORDER BY timestamp DESC`, userID, async function (err, rows, results) {
1103 if (err) throw err;
1104 var notes = [];
1105 for (var i = 0; i < rows.length; i++) {
1106 var row = rows[i];
1107 await notes.push(`\`${row.identifier}\` :pushpin: Note by ${client.users.get(row.actioner)} on ${row.timestamp}\n\`\`\`${row.description}\`\`\`\n`)
1108 }
1109 if (!_.isEmpty(notes)) {
1110 message.edit(new Discord.RichEmbed()
1111 .setColor(locale.info_color)
1112 .setAuthor(`Notes of ${globalUser.username}`, globalUser.avatarURL)
1113 .setDescription(notes.join(" "))
1114 .setTimestamp()
1115 .setFooter(`Gab's Child | Version: ${config.version}`));
1116 } else {
1117 message.edit(new Discord.RichEmbed()
1118 .setColor(locale.info_color)
1119 .setAuthor(`Notes of ${globalUser.username}`, globalUser.avatarURL)
1120 .setDescription(`This user has no notes`)
1121 .setTimestamp()
1122 .setFooter(`Gab's Child | Version: ${config.version}`));
1123 }
1124 })
1125 } else if (r.emoji.name == `?`) {
1126 await r.remove(r.users.last());
1127 connection.query(`
1128 SELECT Status, timestamp FROM(SELECT *, 'join' AS Status from log_guildjoin WHERE userid = ? AND guildID = ${connection.escape(guild.id)}
1129 UNION SELECT *, 'leave' AS Status FROM log_guildleave WHERE userid = ? AND guildID = ${connection.escape(guild.id)}) a
1130 ORDER BY timestamp DESC`, [userID, userID], async function (err, rows, results) {
1131 if (err) throw err;
1132 var history = [];
1133 var max = 5;
1134 var extra;
1135
1136 if (rows.length <= 5) {
1137 max = rows.length;
1138 } else {
1139 extra = rows.length - max;
1140 }
1141
1142 for (var i = 0; i < max; i++) {
1143 var row = rows[i];
1144 switch (row.Status) {
1145 case `join`:
1146 history.push(`:inbox_tray: ${globalUser.username} joined ${guild.name} at \`\`\`${new Date(row.timestamp)}\`\`\`\n`);
1147 break;
1148 case `leave`:
1149 history.push(`:outbox_tray: ${globalUser.username} left ${guild.name} at \`\`\`${new Date(row.timestamp)}\`\`\`\n`);
1150 break;
1151 }
1152
1153 if (i == max - 1 && extra > 0) {
1154 history.push(`...${extra} more`);
1155 }
1156 }
1157
1158 if (!_.isEmpty(history)) {
1159 await message.edit(new Discord.RichEmbed()
1160 .setColor(locale.info_color)
1161 .setAuthor(`Join/Leave history of ${globalUser.username}`, globalUser.avatarURL)
1162 .setDescription(history.join(" "))
1163 .setTimestamp()
1164 .setFooter(`Gab's Child | Version: ${config.version}`));
1165 } else {
1166 await message.edit(new Discord.RichEmbed()
1167 .setColor(locale.info_color)
1168 .setAuthor(`Notes of ${globalUser.username}`, globalUser.avatarURL)
1169 .setDescription(`This user has no Join/Leave history`)
1170 .setTimestamp()
1171 .setFooter(`Gab's Child | Version: ${config.version}`))
1172 }
1173 })
1174 } else if (r.emoji.name == `❌`) {
1175 message.delete();
1176 }
1177 })
1178 });
1179 } else {
1180 connection.query(`SELECT * FROM users WHERE userid = ? AND guildID = ${connection.escape(guild.id)} ORDER BY updated DESC LIMIT 1`, userID, async function (err, rows, results) {
1181 var cardUser = rows[0];
1182 const userEmbed = new Discord.RichEmbed()
1183 .setColor(locale.info_color)
1184 .setAuthor(`Information of ${cardUser.username}`, `https://cdn.discordapp.com/avatars/${cardUser.userID}/${cardUser.avatar}.jpg`)
1185 .setThumbnail(`https://cdn.discordapp.com/avatars/${cardUser.userID}/${cardUser.avatar}.jpg`)
1186 .setDescription(`The user could not be resolved, all data will be taken from the database`)
1187 .setTimestamp()
1188 .setFooter(`Gab's Child | Version: ${config.version}`);
1189
1190 message.channel.send(userEmbed).then(async message => {
1191 await message.react("?");
1192 await message.react("?");
1193 await message.react("?");
1194 await message.react("✍");
1195 await message.react("?");
1196 await message.react("❌");
1197
1198 const filter = (reaction, user) => user.bot == false;
1199 const collector = message.createReactionCollector(filter);
1200
1201 collector.on(`collect`, async r => {
1202 if (r.emoji.name == `?`) {
1203 await r.remove(r.users.last());
1204 message.edit(new Discord.RichEmbed()
1205 .setColor(locale.info_color)
1206 .setAuthor(`Information of ${cardUser.username}`, `https://cdn.discordapp.com/avatars/${cardUser.userID}/${cardUser.avatar}.jpg`)
1207 .setThumbnail(`https://cdn.discordapp.com/avatars/${cardUser.userID}/${cardUser.avatar}.jpg`)
1208 .setDescription(`The user could not be resolved, all data will be taken from the database`)
1209 .setTimestamp()
1210 .setFooter(`Gab's Child | Version: ${config.version}`));
1211 } else if (r.emoji.name == `?`) {
1212 await r.remove(r.users.last());
1213
1214 connection.query(`(SELECT 'unban' as \`type\`, gub.* FROM log_guildunbans gub WHERE gub.userid = ${connection.escape(userID)} AND gub.isDeleted = 0 AND gub.guildID = ${connection.escape(guild.id)}
1215 UNION ALL SELECT 'ban' as \`type\`, gb.* FROM log_guildbans gb WHERE gb.userid = ${connection.escape(userID)} AND gb.isDeleted = 0 AND gb.actioner AND gb.guildID = ${connection.escape(guild.id)} <> '001' UNION ALL
1216 SELECT 'warn' AS \`type\`, w.* FROM log_warn w WHERE w.userid = ${connection.escape(userID)} AND w.isDeleted = 0 AND w.guildID = ${connection.escape(guild.id)}) ORDER BY timestamp DESC`,
1217 async function (err, rows, results) {
1218 if (err) throw err;
1219 var events = [];
1220 var max = 5;
1221 var extra;
1222
1223 if (rows.length <= max) {
1224 max = rows.length;
1225 } else {
1226 extra = rows.length - max;
1227 }
1228
1229 for (var i = 0; i < max; i++) {
1230 var row = rows[i];
1231 if (row.type == `warn`) {
1232 await events.push(`\`${row.identifier}\` :exclamation: Warned by ${client.users.get(row.actioner)} on ${row.timestamp}\n\`\`\`${row.description}\`\`\`\n`);
1233 } else if (row.type == `ban`) {
1234 await events.push(`\`${row.identifier}\` :crossed_swords: Banned by ${client.users.get(row.actioner)} on ${row.timestamp}\n\`\`\`${row.description}\`\`\`\n`);
1235 } else if (row.type == `unban`) {
1236 await events.push(`\`${row.identifier}\` :shield: Unbanned by ${client.users.get(row.actioner)} on ${row.timestamp}\n\`\`\`${row.description}\`\`\`\n`);
1237 }
1238 if (i == max - 1 && extra > 0) {
1239 events.push(`...${extra} more`);
1240 }
1241 }
1242 if (!_.isEmpty(events)) {
1243 await message.edit(new Discord.RichEmbed()
1244 .setColor(locale.info_color)
1245 .setAuthor(`Infractions of ${cardUser.username}`, `https://cdn.discordapp.com/avatars/${cardUser.userID}/${cardUser.avatar}.jpg`)
1246 .setDescription(events.join(`\n`))
1247 .setTimestamp()
1248 .setFooter(`Gab's Child | Version: ${config.version}`));
1249 } else {
1250 await message.edit(new Discord.RichEmbed()
1251 .setColor(locale.info_color)
1252 .setAuthor(`Infractions of ${cardUser.username}`, `https://cdn.discordapp.com/avatars/${cardUser.userID}/${cardUser.avatar}.jpg`)
1253 .setDescription(`This user has no infractions`)
1254 .setTimestamp()
1255 .setFooter(`Gab's Child | Version: ${config.version}`));
1256 }
1257 })
1258 } else if (r.emoji.name == `?`) {
1259 await r.remove(r.users.last());
1260
1261 connection.query(`SELECT * FROM log_mutes WHERE userID = ? AND guildID = ${connection.escape(guild.id)} AND isDeleted = 0 ORDER BY timestamp DESC`, userID, async function (err, rows, results) {
1262 if (err) throw err;
1263 var mutes = [];
1264 var max = 5;
1265 var extra;
1266
1267 if (rows.length <= 5) {
1268 max = rows.length;
1269 } else {
1270 extra = rows.length - max;
1271 }
1272
1273 for (var i = 0; i < max; i++) {
1274 var row = rows[i];
1275 await mutes.push(`\`${row.identifier}\` :mute: Muted by ${client.users.get(row.actioner)} on ${row.timestamp} for ${row.length}s\n\`\`\`${row.description}\`\`\`\n`)
1276 if (i == max - 1 && extra > 0) {
1277 mutes.push(`...${extra} more`);
1278 }
1279 }
1280 if (!_.isEmpty(mutes)) {
1281 await message.edit(new Discord.RichEmbed()
1282 .setColor(locale.info_color)
1283 .setAuthor(`Mutes of ${cardUser.username}`, `https://cdn.discordapp.com/avatars/${cardUser.userID}/${cardUser.avatar}.jpg`)
1284 .setDescription(mutes.join(" "))
1285 .setTimestamp()
1286 .setFooter(`Gab's Child | Version: ${config.version}`));
1287 } else {
1288 await message.edit(new Discord.RichEmbed()
1289 .setColor(locale.info_color)
1290 .setAuthor(`Mutes of ${cardUser.username}`, `https://cdn.discordapp.com/avatars/${cardUser.userID}/${cardUser.avatar}.jpg`)
1291 .setDescription(`This user has no mutes`)
1292 .setTimestamp()
1293 .setFooter(`Gab's Child | Version: ${config.version}`));
1294 }
1295 })
1296 } else if (r.emoji.name == `✍`) {
1297 await r.remove(r.users.last());
1298
1299 connection.query(`SELECT * FROM log_note WHERE userID = ? AND guildID = ${connection.escape(guild.id)} AND isDeleted = 0 ORDER BY timestamp DESC`, userID, async function (err, rows, results) {
1300 if (err) throw err;
1301 var notes = [];
1302 for (var i = 0; i < rows.length; i++) {
1303 var row = rows[i];
1304 await notes.push(`\`${row.identifier}\` :pushpin: Note by ${client.users.get(row.actioner)} on ${row.timestamp}\n\`\`\`${row.description}\`\`\`\n`)
1305 }
1306 if (!_.isEmpty(notes)) {
1307 message.edit(new Discord.RichEmbed()
1308 .setColor(locale.info_color)
1309 .setAuthor(`Notes of ${cardUser.username}`, `https://cdn.discordapp.com/avatars/${cardUser.userID}/${cardUser.avatar}.jpg`)
1310 .setDescription(notes.join(" "))
1311 .setTimestamp()
1312 .setFooter(`Gab's Child | Version: ${config.version}`));
1313 } else {
1314 message.edit(new Discord.RichEmbed()
1315 .setColor(locale.info_color)
1316 .setAuthor(`Notes of ${cardUser.username}`, `https://cdn.discordapp.com/avatars/${cardUser.userID}/${cardUser.avatar}.jpg`)
1317 .setDescription(`This user has no notes`)
1318 .setTimestamp()
1319 .setFooter(`Gab's Child | Version: ${config.version}`));
1320 }
1321 })
1322 } else if (r.emoji.name == `?`) {
1323 await r.remove(r.users.last());
1324 connection.query(`
1325 SELECT Status, timestamp FROM(SELECT *, 'join' AS Status from log_guildjoin WHERE userid = ? AND guildID = ${connection.escape(guild.id)}
1326 UNION SELECT *, 'leave' AS Status FROM log_guildleave WHERE userid = ? AND guildID = ${connection.escape(guild.id)}) a
1327 ORDER BY timestamp DESC`, [userID, userID], async function (err, rows, results) {
1328 if (err) throw err;
1329 var history = [];
1330 var max = 5;
1331 var extra;
1332
1333 if (rows.length <= 5) {
1334 max = rows.length;
1335 } else {
1336 extra = rows.length - max;
1337 }
1338
1339 for (var i = 0; i < max; i++) {
1340 var row = rows[i];
1341 switch (row.Status) {
1342 case `join`:
1343 history.push(`:inbox_tray: ${cardUser.username} joined ${guild.name} at \`\`\`${new Date(row.timestamp)}\`\`\`\n`);
1344 break;
1345 case `leave`:
1346 history.push(`:outbox_tray: ${cardUser.username} left ${guild.name} at \`\`\`${new Date(row.timestamp)}\`\`\`\n`);
1347 break;
1348 }
1349
1350 if (i == max - 1 && extra > 0) {
1351 history.push(`...${extra} more`);
1352 }
1353 }
1354
1355 if (!_.isEmpty(history)) {
1356 await message.edit(new Discord.RichEmbed()
1357 .setColor(locale.info_color)
1358 .setAuthor(`Join/Leave history of ${cardUser.username}`, `https://cdn.discordapp.com/avatars/${cardUser.userID}/${cardUser.avatar}.jpg`)
1359 .setDescription(history.join(" "))
1360 .setTimestamp()
1361 .setFooter(`Gab's Child | Version: ${config.version}`));
1362 } else {
1363 await message.edit(new Discord.RichEmbed()
1364 .setColor(locale.info_color)
1365 .setAuthor(`Notes of ${cardUser.username}`, `https://cdn.discordapp.com/avatars/${cardUser.userID}/${cardUser.avatar}.jpg`)
1366 .setDescription(`This user has no Join/Leave history`)
1367 .setTimestamp()
1368 .setFooter(`Gab's Child | Version: ${config.version}`))
1369 }
1370 })
1371 } else if (r.emoji.name == `❌`) {
1372 message.delete();
1373 }
1374 })
1375 });
1376 })
1377 }
1378 } else {
1379 return;
1380 }
1381 }
1382
1383 // Users command
1384 if (command === `users`) {
1385 if (!args[0]) {
1386 if (message.member.roles.some(role => ["Admin"].includes(role.name))) {
1387 message.channel.send(`:x: Wrong command syntax. Please use \`${config.prefix}help\` to view all commands.`);
1388 } else if (!message.member.roles.some(role => ["Admin"].includes(role.name))) {
1389 return;
1390 }
1391 } else if (args[0] == "count") {
1392 var guild = message.guild.id;
1393 if (message.member.roles.some(role => ["Admin"].includes(role.name))) {
1394 const usersCountEmbed = new Discord.RichEmbed()
1395 .setColor(locale.info_color)
1396 .setAuthor(locale.bot_name, locale.bot_avatar_link)
1397 .setTitle(`**User count**`)
1398 .addField(`Total user count`, message.guild.memberCount, false)
1399 .setTimestamp()
1400 .setFooter(`Gab's Child | Version: ${config.version}`)
1401 message.channel.send(usersCountEmbed);
1402 }
1403 }
1404 if (args[0] == "update") {
1405 if (message.member.roles.some(role => ["Admin"].includes(role.name))) {
1406 updateUserTable(`user`, message.channel.id, message.guild.id);
1407 } else {
1408 return;
1409 }
1410 }
1411 }
1412
1413 // Warn command
1414 if (command === `warn`) {
1415 if (!message.member.roles.some(role => ["Admin"].includes(role.name))) {
1416 return;
1417 } else {
1418 var guild = message.guild;
1419 if (args[0]) {
1420 var user = parseUserTag(args[0]);
1421 } else {
1422 message.channel.send(`:x: Wrong command syntax. Please use \`${config.prefix}help\` to view all commands.`);
1423 return;
1424 }
1425 if (user == `err`) {
1426 message.channel.send(`:x: The specified user was not found.`);
1427 } else if (guild.member(user)) {
1428 var tail = args.slice(1);
1429 var content = tail.join(" ").trim();
1430
1431 if (tail.length > 0 && message.member.roles.some(role => ["Admin"].includes(role.name))) {
1432 var identifier = cryptoRandomString({
1433 length: 10
1434 });
1435 var data = [user, message.guild.id, message.author.id, content, identifier, 0, new Date(), user];
1436 connection.query(`INSERT INTO log_warn (userID, guildID, actioner, description, identifier, isDeleted, timestamp) VALUES (?,?,?,?,?,?,?);`, data);
1437
1438 message.channel.send(new Discord.RichEmbed()
1439 .setColor(locale.good_color)
1440 .setAuthor(client.users.get(user).username, client.users.get(user).avatarURL)
1441 .setTitle(`**User warned**`)
1442 .setDescription(`User ${client.users.get(user)} has been successfully warned`)
1443 .addField(`User ID`, `${client.users.get(user).id}`, true)
1444 .addField(`Username`, `${client.users.get(user).username}#${client.users.get(user).discriminator}`, true)
1445 .addField(`Reason`, `${content}`, false)
1446 .addField(`Warned by`, `${message.author}`, false)
1447 .addField(`Identifier`, `${identifier}`, false)
1448 .setTimestamp()
1449 .setFooter(`Gab's Child | Version: ${config.version}`));
1450
1451 client.users.get(user).createDM().then(async chnl => {
1452 await chnl.send(
1453 new Discord.RichEmbed()
1454 .setColor(locale.bad_color)
1455 .setAuthor(locale.bot_name, locale.bot_avatar_link)
1456 .setTitle(`**You have been warned in ${guild.name}**`)
1457 .setDescription(`Details about the warning:`)
1458 .addField(`Warning reason`, `${content}`, false)
1459 .addField(`Identifier`, `${identifier}`, false)
1460 .setTimestamp()
1461 .setFooter(`Gab's Child | Version: ${config.version}`)
1462 ).then(dm => {
1463 var data = [user, message.guild.id, dm.content, 1, 0, identifier, new Date(), new Date()];
1464 connection.query(`INSERT INTO log_outgoingdm(userid, guildID, content, type, isDeleted, identifier, timestamp, updated) VALUES(?,?,?,?,?,?,?,?)`, data);
1465 })
1466 })
1467 } else {
1468 message.channel.send(`:x: Please provide a reason for the warning.`);
1469 }
1470 } else {
1471 message.channel.send(`:x: The specified user was not found.`);
1472 }
1473 }
1474 }
1475
1476 // CWarn command
1477 if (command === `cwarn`) {
1478 if (message.member.roles.some(role => ["Admin"].includes(role.name))) {
1479 if (!args[0]) {
1480 message.channel.send(`:x: Wrong command syntax. Please use \`${config.prefix}help\` to view all commands.`);
1481 } else if (args[0].length == 10) {
1482 connection.query(`UPDATE log_warn SET isDeleted = 1 WHERE identifier = ? AND guildID = ${message.guild.id}`, args[0].trim(), function (err, results, rows) {
1483 if (err) throw err;
1484 if (results.affectedRows == 0) {
1485 message.channel.send(`:x: Warning could not be found.`);
1486 } else if (results.affectedRows == 1) {
1487 message.channel.send(`:white_check_mark: Warning ID \`${args[0].trim()}\` has been successfully removed.`);
1488 }
1489 });
1490 }
1491 }
1492 }
1493
1494 // Mute command
1495 if (command === `mute`) {
1496 if (message.member.roles.some(role => ["Admin"].includes(role.name))) {
1497 if (!args[0] || !args[1]) {
1498 message.channel.send(`:x: Wrong command syntax. Please use \`${config.prefix}help\` to view all commands.`);
1499 return;
1500 } else {
1501 var user = parseUserTag(args[0]);
1502 var guild = message.guild;
1503 var guildUser = guild.member(user);
1504
1505 if (user !== `err` && guildUser) {
1506 if (mutedFile.get(user) && mutedFile.get(user).guild==guild.id) {
1507 var existingMute = mutedFile.get(user);
1508 message.channel.send(`:x: User ${client.users.get(user)} is already muted. The mute will end at ${new Date(existingMute.end * 1000)}`);
1509 } else {
1510 var end;
1511 var seconds;
1512 var int = args[1].replace(/[a-zA-Z]$/g, "");
1513
1514 if (parseInt(int)) {
1515 switch ((args[1].toLowerCase().charAt(args[1].length - 1))) {
1516 case "d":
1517 end = ((Math.floor(Date.now() / 1000)) + (int * 24 * 60 * 60));
1518 seconds = (int * 24 * 60 * 60);
1519 break;
1520 case "h":
1521 end = ((Math.floor(Date.now() / 1000)) + (int * 60 * 60));
1522 seconds = (int * 60 * 60);
1523 break;
1524 case "m":
1525 end = ((Math.floor(Date.now() / 1000)) + (int * 60));
1526 seconds = (int * 60);
1527 break;
1528 case "s":
1529 message.channel.send(`:x: The specified mute duration is too short!`);
1530 return;
1531 default:
1532 end = ((Math.floor(Date.now() / 1000)) + (int * 60 * 60));
1533 seconds = (int);
1534 break;
1535 }
1536
1537 var reason = _.rest(args, 2).join(" ");
1538
1539 if (reason.length > 0) {
1540 mutedFile.set(`${user}.end`, end);
1541 mutedFile.set(`${user}.actioner`, message.author.id);
1542 mutedFile.set(`${user}.actionee`, user);
1543 mutedFile.set(`${user}.reason`, reason);
1544 mutedFile.set(`${user}.guild`, guild.id);
1545 mutedFile.save();
1546
1547 var mutedRole = guild.roles.find(val => val.id === config.muted_role);
1548 var identifier = cryptoRandomString({
1549 length: 10
1550 });
1551
1552 guild.member(user).addRole(mutedRole)
1553 .then(member => {
1554 if (member.voiceChannel !== undefined) {
1555 client.channels.get(config.voice_afk).clone(`Disconnecting user...`, false, false, `Disconnecting ${guildUser.user.username}#${guildUser.user.discriminator}`).then(async channel => {
1556 member.setVoiceChannel(channel).then(async () => {
1557 await channel.delete();
1558 })
1559 })
1560 }
1561 message.channel.send(new Discord.RichEmbed()
1562 .setColor(locale.good_color)
1563 .setAuthor(client.users.get(user).username, client.users.get(user).avatarURL)
1564 .setTitle(`**User muted**`)
1565 .setDescription(`User ${client.users.get(user)} has been successfully muted`)
1566 .addField(`User ID`, `${client.users.get(user).id}`, true)
1567 .addField(`Username`, `${client.users.get(user).username}#${client.users.get(user).discriminator}`, true)
1568 .addField(`Reason`, `${reason}`, false)
1569 .addField(`Duration`, `${args[1]}`, false)
1570 .addField(`Muted by`, `${message.author}`, false)
1571 .addField(`Identifier`, `${identifier}`, false)
1572 .setTimestamp()
1573 .setFooter(`Gab's Child | Version: ${config.version}`));
1574 });
1575 var data = [user, guild.id, message.author.id, reason, seconds, identifier, 0, new Date()];
1576 connection.query(`INSERT INTO log_mutes (userID, guildID, actioner, description, length, identifier, isDeleted, timestamp) VALUES (?,?,?,?,?,?,?,?)`, data);
1577
1578 client.users.get(user).createDM().then(async chnl => {
1579 await chnl.send(
1580 new Discord.RichEmbed()
1581 .setColor(locale.bad_color)
1582 .setAuthor(locale.bot_name, locale.bot_avatar_link)
1583 .setTitle(`**You have been muted in ${guild.name}**`)
1584 .setDescription(`Details about the mute:`)
1585 .addField(`Mute reason`, `${reason}`, false)
1586 .addField(`Duration`, `${args[1]}`, false)
1587 .addField(`Identifier`, `${identifier}`, false)
1588 .setTimestamp()
1589 .setFooter(`Gab's Child | Version: ${config.version}`)
1590 ).then(dm => {
1591 if (dm.embeds[0].type === `rich`) {
1592 var data = [user, message.guild.id, dm.embeds[0].title, 3, 0, identifier, new Date(), new Date()];
1593 } else {
1594 var data = [user, message.guild.id, dm.content, 3, 0, identifier, new Date(), new Date()];
1595 }
1596 connection.query(`INSERT INTO log_outgoingdm (userid, guildID, content, type, isDeleted, identifier, timestamp, updated) VALUES (?,?,?,?,?,?,?,?)`, data);
1597 })
1598 })
1599 } else {
1600 message.channel.send(`:x: Please provide a reason for the mute.`);
1601 }
1602 } else {
1603 message.channel.send(`:x: Wrong length syntax.`);
1604 }
1605 }
1606 } else {
1607 message.channel.send(`:x: The specified user was not found.`);
1608 }
1609 }
1610 }
1611 }
1612
1613 // Disconnect command
1614 if (command === `disconnect`) {
1615 if (message.member.roles.some(role => ["Admin"].includes(role.name))) {
1616 if (!args[0]) {
1617 message.channel.send(`:x: Wrong command syntax. Please use \`${config.prefix}help\` to view all commands.`);
1618 return;
1619 }
1620 var user = parseUserTag(args[0]);
1621 var guild = message.guild;
1622 var guildUser = guild.member(user);
1623
1624 if ((user !== `err` && guildUser) && guildUser.voiceChannel !== undefined) {
1625 client.channels.get(config.voice_afk).clone(`Disconnecting user...`, false, false, `Disconnecting ${guildUser.user.username}#${guildUser.user.discriminator}`).then(async channel => {
1626 guildUser.setVoiceChannel(channel).then(async member => {
1627 await channel.delete();
1628 message.channel.send(`:white_check_mark: User ${member} has been successfully disconnected from their voice channel.`);
1629 })
1630 })
1631 } else {
1632 message.channel.send(`:x: The specified user was not found.`);
1633 }
1634 }
1635 }
1636
1637 // Note command
1638 if (command === `note`) {
1639 if (message.member.roles.some(role => ["Admin"].includes(role.name))) {
1640 if (!args[0]) {
1641 message.channel.send(`:x: Wrong command syntax. Please use \`${config.prefix}help\` to view all commands.`);
1642 return;
1643 }
1644 if (args[0]) {
1645 var user = parseUserTag(args[0]);
1646 }
1647 if (user == `err`) {
1648 message.channel.send(`:x: The specified user was not found.`);
1649 } else {
1650 var tail = args.slice(1);
1651 var note = tail.join(" ").trim();
1652
1653 if (tail.length > 0) {
1654 var identifier = cryptoRandomString({
1655 length: 10
1656 });
1657 var data = [user, message.guild.id, message.author.id, note, identifier, 0, new Date(), user];
1658 connection.query(`INSERT INTO log_note (userID, guildID, actioner, description, identifier, isDeleted, timestamp) VALUES (?,?,?,?,?,?,?)`, data);
1659
1660 message.channel.send(new Discord.RichEmbed()
1661 .setColor(locale.good_color)
1662 .setAuthor(client.users.get(user).username, client.users.get(user).avatarURL)
1663 .setTitle(`**Note added**`)
1664 .setDescription(`A note was successfully added to ${client.users.get(user)}`)
1665 .addField(`User ID`, `${client.users.get(user).id}`, true)
1666 .addField(`Username`, `${client.users.get(user).username}#${client.users.get(user).discriminator}`, true)
1667 .addField(`Content`, `${note}`, false)
1668 .addField(`Added by`, `${message.author}`, false)
1669 .addField(`Identifier`, `${identifier}`, false)
1670 .setTimestamp()
1671 .setFooter(`Gab's Child | Version: ${config.version}`));
1672 } else {
1673 message.channel.send(`:x: Please provide a reason for the note.`);
1674 }
1675 }
1676 }
1677 }
1678
1679 // CNote command
1680 if (command === `cnote`) {
1681 if (message.member.roles.some(role => ["Admin"].includes(role.name))) {
1682 if (!args[0]) {
1683 message.channel.send(`:x: Wrong command syntax. Please use \`${config.prefix}help\` to view all commands.`);
1684 return;
1685 }
1686 if (args[0].length == 10) {
1687 connection.query(`UPDATE log_note SET isDeleted = 1 WHERE identifier = ? AND guildID = ${message.guild.id}`, args[0].trim(), function (err, results, rows) {
1688 if (err) throw err;
1689 if (results.affectedRows == 1) {
1690 message.channel.send(`:white_check_mark: Note ID \`${args[0].trim()}\` has been successfully removed.`);
1691 } else {
1692 message.channel.send(`:x: Note could not be found.`);
1693 }
1694 });
1695 }
1696 }
1697 }
1698
1699 // Voicelog command
1700 if (command === `voicelog`) {
1701 if (message.member.roles.some(role => ["Admin"].includes(role.name))) {
1702 if (!args[0]) {
1703 message.channel.send(`:x: Wrong command syntax. Please use \`${config.prefix}help\` to view all commands.`);
1704 return;
1705 }
1706 if (args[0]) {
1707 var user = parseUserTag(args[0]);
1708 }
1709
1710 if (user == `err`) {
1711 message.channel.send(`:x: The specified user was not found.`);
1712 } else {
1713 connection.query(`SELECT * FROM log_voice WHERE userID = ? AND guildID = ${connection.escape(message.guild.id)} ORDER BY timestamp DESC LIMIT 22`, user, async function (err, rows, results) {
1714 if (err) throw err;
1715
1716 var times = [];
1717 var current = [];
1718 var timestamps = [];
1719 var msg = ["Channel | Timestamp | Duration (H:M:S)",
1720 "------------------------------------------------------------------------------------------------"
1721 ];
1722 for (var i = rows.length - 1; i >= 0; i--) {
1723 var row = rows[i];
1724
1725 if (rows[i - 1]) {
1726 var next = rows[i - 1];
1727
1728 if (row.type !== 3 && ([2, 3].indexOf(next.type) > -1)) {
1729 var time1 = row.timestamp;
1730 var time2 = next.timestamp;
1731
1732 var diff = time2.getTime() - time1.getTime();
1733
1734 var msec = diff;
1735 var hh = Math.floor(msec / 1000 / 60 / 60);
1736 msec -= hh * 1000 * 60 * 60;
1737 var mm = Math.floor(msec / 1000 / 60);
1738 msec -= mm * 1000 * 60;
1739 var ss = Math.floor(msec / 1000);
1740 msec -= ss * 1000;
1741
1742 times.push(`${hh}:${mm}:${ss}`);
1743 current.push(row.newChannel);
1744 timestamps.push(`${row.timestamp.toUTCString()} (${moment(row.timestamp.toUTCString()).fromNow()})`);
1745 }
1746 } else if (!rows[i - 1] && ([1, 2].indexOf(row.type) > -1)) {
1747 current.push(row.newChannel);
1748 times.push(`Active`);
1749 timestamps.push(`${row.timestamp.toUTCString()} (${moment(row.timestamp.toUTCString()).fromNow()})`);
1750 }
1751 }
1752 times.reverse();
1753 current.reverse();
1754 timestamps.reverse();
1755
1756 var longest = 0;
1757 for (var i = 0; i < current.length; i++) {
1758 if (current[i].length > longest) {
1759 longest = current[i].length;
1760 }
1761 }
1762 for (var j = 0; j < current.length; j++) {
1763 var howManyToAdd = longest - current[j].length;
1764 current[j] = current[j].padEnd(current[j].length + howManyToAdd + 1);
1765 }
1766 var longestTime = 0;
1767 for (var i = 0; i < timestamps.length; i++) {
1768 if (current[i].length > longestTime) {
1769 longestTime = timestamps[i].length;
1770 }
1771 }
1772 for (var j = 0; j < timestamps.length; j++) {
1773 var howManyToAdd = longestTime - timestamps[j].length;
1774 timestamps[j] = timestamps[j].padEnd(timestamps[j].length + howManyToAdd + 1);
1775 }
1776 for (var i = 0; i < times.length; i++) {
1777 msg.push(`${current[i]}| ${timestamps[i]}| ${times[i]}`);
1778 }
1779 var joinedMessage = msg.join(`\n`);
1780 message.channel.send(`:microphone2: Viewing voice log of user ${client.users.get(user)} \`\`\`${joinedMessage}\`\`\``);
1781 })
1782 }
1783 }
1784 }
1785
1786 // Badwords command
1787 if (command === `badwords`) {
1788 if (message.member.roles.some(role => ["Admin"].includes(role.name))) {
1789 if (!args[0]) {
1790 message.channel.send(`:x: Wrong command syntax. Please use \`${config.prefix}help\` to view all commands.`);
1791 return;
1792 }
1793 if (args[0] === `add`) {
1794 if (!(args[1] === ``)) {
1795 var string = _.rest(args, 1).join(" ");
1796 badWordsFile.set(`${string}.word`, string);
1797 badWordsFile.set(`${string}.${message.guild.id}`, message.guild.id);
1798 badWordsFile.save();
1799 message.channel.send(`:white_check_mark: Word \`${string}\` has been successfully added.`);
1800 }
1801 }
1802 if (args[0] === `remove`) {
1803 if (!(args[1] === "")) {
1804 var gKeys = _.keys(channelsFile.read());
1805 for(var i = 0; i < gKeys.length; i++) {
1806 if(gKeys[i] == message.guild.id) {
1807 badWordsFile.set(`${string}.${message.guild.id}`, "");
1808 }
1809 }
1810 badWordsFile.save();
1811 message.channel.send(`:white_check_mark: Word \`${args[1]}\` has been successfully removed.`);
1812 }
1813 }
1814 if (args[0] === "list") {
1815 var gKeys = _.keys(channelsFile.read());
1816 var badWords = "";
1817 for(var i = 0; i < gKeys.length; i++) {
1818 if(gKeys[i] == message.guild.id) {
1819 var bKeys = _.keys(badWordsFile.read());
1820 for (var j = 0; j < bKeys.length; j++) {
1821 if(badWordsFile.get(bKeys[j])) {
1822 badWords += "\n" + bKeys[j];
1823 }
1824 }
1825 }
1826 }
1827 if (badWords) {
1828 const badWordsListEmbed = new Discord.RichEmbed()
1829 .setColor(locale.info_color)
1830 .setAuthor(locale.bot_name, locale.bot_avatar_link)
1831 .setTitle(`**Bad words:**`)
1832 .setDescription(badWords)
1833 .setTimestamp()
1834 .setFooter(`Gab's Child | Version: ${config.version}`);
1835
1836 message.channel.send(badWordsListEmbed);
1837 } else if (!badWords) {
1838 const badWordsListEmbed = new Discord.RichEmbed()
1839 .setColor(locale.info_color)
1840 .setAuthor(locale.bot_name, locale.bot_avatar_link)
1841 .setTitle(`**Bad words**`)
1842 .setDescription(`There are no bad words`)
1843 .setTimestamp()
1844 .setFooter(`Gab's Child | Version: ${config.version}`);
1845
1846 message.channel.send(badWordsListEmbed);
1847 }
1848 }
1849 }
1850 }
1851
1852 // Channels command
1853 if (command === `channels`) {
1854 var guild = message.guild;
1855 /*if (!message.member.roles.some(role => ["Admin"].includes(role.name))) {
1856 return;*/
1857 if (!args[0]) {
1858 message.channel.send(`:x: Wrong command syntax. Please use \`${config.prefix}help\` to view all commands.`);
1859 } else if (args[0] === `set`) {
1860 if (args[1] === `server_log`) {
1861 if (!(args[1] === ``)) {
1862 channelsFile.set(guild.id, {
1863 server_log: message.channel.id
1864 });
1865 channelsFile.save();
1866 message.channel.send(`:white_check_mark: Server Log channel has been successfully set.`);
1867 }
1868 } else if (args[1] === `bot_log`) {
1869 channelsFile.set(guild.id, {
1870 bot_log: message.channel.id
1871 });
1872 channelsFile.save();
1873 message.channel.send(`:white_check_mark: Bot Log channel has been successfully set.`);
1874 } else {
1875 message.channel.send(`:x: Please specify what to set.`);
1876 }
1877 }
1878 }
1879});
1880
1881// User Join Listener Event
1882client.on(`guildMemberAdd`, member => {
1883 var gKeys = _.keys(channelsFile.read());
1884 for(var i = 0; i < gKeys.length; i++) {
1885 var guild = gKeys[i];
1886
1887 if (member.guild.id == guild) {
1888 var params = [member.user.id, guild, member.user.username, member.user.avatar, 1, new Date(), member.user.id, member.user.id, guild, new Date()];
1889 connection.query(
1890 `
1891 INSERT IGNORE INTO users (userID, guildID, username, avatar, exist, timestamp) VALUES (?,?,?,?,?,?);
1892 UPDATE users SET exist = 1 WHERE userID = ?;
1893 INSERT INTO log_guildjoin (userID, guildID, timestamp) VALUES (?,?,?);
1894 `, params
1895 );
1896
1897 const userJoinEmbed = new Discord.RichEmbed()
1898 .setColor(locale.good_color)
1899 .setAuthor(member.user.username, member.user.avatarURL)
1900 .setTitle(`**User has joined**`)
1901 .setDescription(`${member} has joined ${member.guild.name}`)
1902 .setTimestamp()
1903 .setFooter(`Gab's Child | Version: ${config.version}`);
1904
1905 client.channels.get(channelsFile.get(guild).server_log).send(userJoinEmbed);
1906 } else {
1907 return;
1908 }
1909 }
1910});
1911
1912// User Left Listener Event
1913client.on(`guildMemberRemove`, member => {
1914 var data = [member.user.id, member.guild.id, new Date()];
1915 var userLeave = [0, member.user.id, member.guild.id];
1916
1917 connection.query(
1918 `INSERT INTO log_guildleave (userID, guildID, timestamp) VALUES (?,?,?)`, data
1919 );
1920 connection.query(
1921 `UPDATE users SET exist = ? WHERE userID = ? AND guildID = ?`, userLeave
1922 );
1923
1924 const userLeaveEmbed = new Discord.RichEmbed()
1925 .setColor(locale.bad_color)
1926 .setAuthor(member.user.username, member.user.avatarURL)
1927 .setTitle(`**User has left**`)
1928 .setDescription(`${member} has left ${member.guild.name}`)
1929 .setTimestamp()
1930 .setFooter(`Gab's Child | Version: ${config.version}`);
1931
1932 var guild = member.guild.id;
1933 client.channels.get(channelsFile.get(guild).server_log).send(userLeaveEmbed);
1934});
1935
1936client.on(`voiceStateUpdate`, function (oldMember, newMember) {
1937 var data = [];
1938 if (oldMember.voiceChannel) {
1939 if (newMember.voiceChannel) {
1940 if (oldMember.voiceChannel.id !== newMember.voiceChannel.id) {
1941 data = [newMember.id, newMember.guild.id, newMember.voiceChannel.id, newMember.voiceChannel.name, oldMember.voiceChannel.id, oldMember.voiceChannel.name, 2, new Date()];
1942 } else {
1943 return;
1944 }
1945 } else {
1946 data = [newMember.id, newMember.guild.id, ``, ``, oldMember.voiceChannel.id, oldMember.voiceChannel.name, 3, new Date()];
1947 }
1948 } else if (newMember.voiceChannel) {
1949 data = [newMember.id, newMember.guild.id, newMember.voiceChannel.id, newMember.voiceChannel.name, ``, ``, 1, new Date()];
1950 } else {
1951 data = [newMember.id, newMember.guild.id, `Unknown`, `Unknown`, ``, ``, 1, new Date()];
1952 }
1953 if (data.length > 0) {
1954 connection.query(
1955 `INSERT INTO log_voice (userID, guildID, newChannelID, newChannel, oldChannelID, oldChannel, type, timestamp ) VALUES (?,?,?,?,?,?,?,?)`, data
1956 );
1957 }
1958});
1959
1960// Message Deletion Listener Event
1961client.on(`messageDelete`, async message => {
1962 const entry = await message.guild.fetchAuditLogs({
1963 type: 'MESSAGE_DELETE'
1964 }).then(audit => audit.entries.first())
1965 let user = ""
1966 if(deletedByBot == 1) {
1967 user = client.user;
1968 deletedByBot = 0;
1969 }
1970 else if (entry.extra.channel.id === message.channel.id &&
1971 (entry.target.id === message.author.id) &&
1972 (entry.createdTimestamp > (Date.now() - 5000)) &&
1973 (entry.extra.count >= 1)) {
1974 user = entry.executor
1975 } else {
1976 user = message.author
1977 }
1978
1979 if (message.author.bot) {
1980 return;
1981 }
1982
1983 const messageDeleteEmbed = new Discord.RichEmbed()
1984 .setColor(locale.info_color)
1985 .setAuthor(message.author.username, message.author.avatarURL)
1986 .setTitle(`**Message deleted in #${message.channel.name}**`)
1987 .setDescription(`Message sent by ${message.member} deleted in ${message.channel}
1988 **Deleted by:** ${user}
1989 **Deleted message:** ${message}`)
1990 .setTimestamp()
1991 .setFooter(`Gab's Child | Version: ${config.version}`);
1992
1993 var guild = message.guild.id;
1994 client.channels.get(channelsFile.get(guild).server_log).send(messageDeleteEmbed);
1995});
1996
1997// Message Edit Listener Event
1998client.on(`messageUpdate`, function (oldMessage, newMessage) {
1999 if (oldMessage.content === newMessage.content) return;
2000 const messageEditEmbed = new Discord.RichEmbed()
2001 .setColor(locale.info_color)
2002 .setAuthor(oldMessage.author.username, oldMessage.author.avatarURL)
2003 .setTitle(`**Message edited in #${oldMessage.channel.name}**`)
2004 .setDescription(`Message sent by ${oldMessage.member} edited in ${oldMessage.channel}
2005 **Old message:** ${oldMessage}
2006 **New message:** ${newMessage}\n
2007 [Jump to Message](https://discordapp.com/channels/${config.guild}/${newMessage.channel.id}/${newMessage.id})`)
2008 .setTimestamp()
2009 .setFooter(`Gab's Child | Version: ${config.version}`);
2010
2011 var guild = oldMessage.guild.id;
2012 client.channels.get(channelsFile.get(guild).server_log).send(messageEditEmbed);
2013});
2014
2015client.on(`userUpdate`, function (oldUser, newUser) {
2016 if (oldUser.username !== newUser.username) {
2017 var data = [newUser.id, newUser.guild.id, newUser.username, oldUser.username, new Date()];
2018 connection.query(
2019 `INSERT INTO log_username (userID, guildID, new, old, timestamp) VALUES (?,?,?,?,?)`, data
2020 )
2021 }
2022 if (oldUser.avatar !== newUser.avatar) {
2023 var data = [newUser.avatar, new Date(), newUser.id];
2024 connection.query(
2025 `UPDATE users SET avatar = ?, updated = ? WHERE userID = ?`, data
2026 )
2027 }
2028});
2029
2030client.on(`guildMemberUpdate`, function (oldMember, newMember) {
2031 if (oldMember.displayName !== newMember.displayName) {
2032 var data = [newMember.user.id, newMember.guild.id, newMember.displayName, oldMember.displayName, new Date()];
2033 connection.query(
2034 `INSERT INTO log_nickname (userID, guildID, new, old, timestamp) VALUES (?,?,?,?,?)`, data
2035 )
2036 const messageEditEmbed = new Discord.RichEmbed()
2037 .setColor(locale.info_color)
2038 .setAuthor(newMember.user.username, newMember.user.avatarURL)
2039 .setTitle(`**Nickname change**`)
2040 .setDescription(`User ${newMember.user} has changed their nickname
2041 **Old nickname:** ${oldMember.displayName}
2042 **New nickname:** ${newMember.displayName}`)
2043 .setTimestamp()
2044 .setFooter(`Gab's Child | Version: ${config.version}`);
2045
2046 var guild = oldMember.guild.id;
2047 client.channels.get(channelsFile.get(guild).server_log).send(messageEditEmbed);
2048 }
2049});
2050
2051client.on(`error`, console.error);
2052client.on(`warn`, warn => {
2053 console.log(warn);
2054});
2055
2056// Login
2057client.login(config.token);