From 190c19d271c87ba5bb72cd696474b58ffbc67b03 Mon Sep 17 00:00:00 2001
From: loicbersier <loic.bersier1@gmail.com>
Date: Thu, 5 Mar 2020 21:50:16 +0100
Subject: [PATCH] Quotation feature

---
 commands/admin/quotation.js                   | 45 ++++++++++
 event/listeners/message.js                    | 83 +++++++++++++++----
 .../20200305204757-create-quotation-stat.js   | 30 +++++++
 models/quotationstat.js                       | 11 +++
 4 files changed, 152 insertions(+), 17 deletions(-)
 create mode 100644 commands/admin/quotation.js
 create mode 100644 migrations/20200305204757-create-quotation-stat.js
 create mode 100644 models/quotationstat.js

diff --git a/commands/admin/quotation.js b/commands/admin/quotation.js
new file mode 100644
index 0000000..0a35f34
--- /dev/null
+++ b/commands/admin/quotation.js
@@ -0,0 +1,45 @@
+const { Command } = require('discord-akairo');
+const quotationStat = require('../../models').quotationStat;
+
+class quotationCommand extends Command {
+	constructor() {
+		super('quotation', {
+			aliases: ['quotation'],
+			category: 'admin',
+			args: [
+				{
+					id: 'stat',
+					type: 'string',
+					prompt: {
+						start: 'Do you want to **enable** or **disable** quotation?',
+					}
+				}
+			],
+			clientPermissions: ['SEND_MESSAGES'],
+			userPermissions: ['MANAGE_MESSAGES'],
+			channelRestriction: 'guild',
+			description: {
+				content: 'enable/disable quotation',
+				usage: '[enable/disable]',
+				examples: ['enable']
+			}
+		});
+	}
+
+	async exec(message, args) {
+		if (args.stat.toLowerCase() == 'enable' || args.stat.toLowerCase() == 'disable') {
+			const quotationstat = await quotationStat.findOne({where: {serverID: message.guild.id}});
+
+			if (!quotationstat) {
+				const body = {serverID: message.guild.id, stat: args.stat};
+				quotationStat.create(body);
+				return message.channel.send(`Quotation has been ${args.stat}d`);
+			} else {
+				const body = {serverID: message.guild.id, stat: args.stat};
+				quotationStat.update(body, {where: {serverID: message.guild.id}});
+				return message.channel.send(`Quotation has been ${args.stat}d`);
+			}
+		}
+	}
+}
+module.exports = quotationCommand;
\ No newline at end of file
diff --git a/event/listeners/message.js b/event/listeners/message.js
index dd643a2..268432c 100644
--- a/event/listeners/message.js
+++ b/event/listeners/message.js
@@ -6,6 +6,7 @@ const autoResponse = require('../../models').autoresponse;
 const autoResponseStat = require('../../models').autoresponseStat;
 const BannedWords = require('../../models').bannedWords;
 const WhitelistWord = require('../../models').whitelistWord;
+const quotationStat = require('../../models').quotationStat;
 
 class messageListener extends Listener {
 	constructor() {
@@ -25,6 +26,11 @@ class messageListener extends Listener {
 
 		if (message.author.bot) return;
 
+		/*	Banned words section
+		*	
+		*	This section contains code about the banned words features	
+		*
+		*/
 
 		// Banned words
 		const bannedWords = await BannedWords.findAll({where: {word: Sequelize.where(Sequelize.fn('LOCATE', Sequelize.col('word'), message.content.replace(/\u200B/g, '').replace(/[\u0250-\ue007]/g, '')), Sequelize.Op.ne, 0), serverID: message.guild.id}});
@@ -55,8 +61,14 @@ class messageListener extends Listener {
 			return message.delete({reason: `Deleted message: ${message.content}`});
 
 		} else {
+			/* Autoresponse feature & tag
+			*
+			*	This section contains autoresponse and tag feature
+			*
+			*/
+
 			// auto responses
-			const autoresponseStat = await autoResponseStat.findOne({where: {serverID: message.guild.id}});
+			const autoresponseStat = await autoResponseStat.findOne({where: {serverID: message.guild.id, stat: 'enable'}});
 			if (autoresponseStat) {
 			// Infinit haha very yes
 				if (message.content.toLowerCase().startsWith('haha very') && message.content.toLowerCase().endsWith('yes')) {
@@ -68,28 +80,25 @@ class messageListener extends Listener {
 					return message.channel.send('haha very yes');
 				}
 
-				//  If autoresponse is enable send the response
-				if (autoresponseStat.get('stat') == 'enable' && autoresponseStat.get('serverID') == message.guild.id) {
 				//  Reply with images as attachement
-					const autoresponse = await autoResponse.findOne({where: {trigger: message.content.toLowerCase()}});
+				const autoresponse = await autoResponse.findOne({where: {trigger: message.content.toLowerCase()}});
 
-					if (autoresponse) {
-						autoResponse.findOne({where: {trigger: message.content.toLowerCase()}});
-						let trigger = autoresponse.get('trigger');
-						let type = autoresponse.get('type');
-						let content = autoresponse.get('response');
+				if (autoresponse) {
+					autoResponse.findOne({where: {trigger: message.content.toLowerCase()}});
+					let trigger = autoresponse.get('trigger');
+					let type = autoresponse.get('type');
+					let content = autoresponse.get('response');
 
-						if (trigger == message.content.toLowerCase() && type == 'text') {
-							return message.channel.send(content);
-						} else if (trigger == message.content.toLowerCase() && type == 'react') {
-							return message.react(content);
-						} else if (trigger == message.content.toLowerCase() && type == 'image') {
-							return message.channel.send({files: [content]});
-						}
+					if (trigger == message.content.toLowerCase() && type == 'text') {
+						return message.channel.send(content);
+					} else if (trigger == message.content.toLowerCase() && type == 'react') {
+						return message.react(content);
+					} else if (trigger == message.content.toLowerCase() && type == 'image') {
+						return message.channel.send({files: [content]});
 					}
-
 				}
 			}
+
 			//  User autoresponse
 			const tag = await Tag.findOne({where: {trigger: message.content.toLowerCase(), serverID: message.guild.id}});
 			if (tag) {
@@ -222,6 +231,46 @@ class messageListener extends Listener {
 				}
 
 			}
+
+			/*	Quotation feature
+			*
+			*	This section will contain the code for the quotation feature, it will detect link for it and send it as embed
+			*
+			*/
+			const quotationstat = await quotationStat.findOne({where: {serverID: message.guild.id, stat: 'enable'}});
+
+			if (quotationstat && message.content.includes('discordapp.com/channels/')) { 
+				let url = message.content.split('/');
+				let guildID = url[4];
+				let channelID = url[5];
+				let messageID = url[6];
+
+
+				// Verify if the guild, channel and message exist
+				let guild = this.client.guilds.resolve(guildID);
+				if (!guild) return;
+				let channel = this.client.channels.resolve(channelID);
+				if (!channel) return;
+				let quote = await channel.messages.fetch(messageID)
+					.catch(() => {
+						return;
+					});
+				if (!quote) return;
+
+				let Embed = this.client.util.embed()
+					.setColor(quote.member.displayHexColor)
+					.setAuthor(quote.author.username, quote.author.displayAvatarURL())
+					.addField('Jump to', `[message](https://discordapp.com/channels/${message.guild.id}/${channelID}/${messageID})`, true)
+					.addField('In channel', quote.channel, true)
+					.addField('Quoted by', message.author, true)
+					.setDescription(quote.content)
+					.setTimestamp();
+				
+				if (guild.id != message.guild.id) Embed.addField('In guild', guild.name, true);
+
+				return message.channel.send(Embed);
+			}
+
 		}
 	}
 }
diff --git a/migrations/20200305204757-create-quotation-stat.js b/migrations/20200305204757-create-quotation-stat.js
new file mode 100644
index 0000000..481bdf6
--- /dev/null
+++ b/migrations/20200305204757-create-quotation-stat.js
@@ -0,0 +1,30 @@
+'use strict';
+module.exports = {
+  up: (queryInterface, Sequelize) => {
+    return queryInterface.createTable('quotationStats', {
+      id: {
+        allowNull: false,
+        autoIncrement: true,
+        primaryKey: true,
+        type: Sequelize.INTEGER
+      },
+      serverID: {
+        type: Sequelize.BIGINT
+      },
+      stat: {
+        type: Sequelize.STRING
+      },
+      createdAt: {
+        allowNull: false,
+        type: Sequelize.DATE
+      },
+      updatedAt: {
+        allowNull: false,
+        type: Sequelize.DATE
+      }
+    });
+  },
+  down: (queryInterface, Sequelize) => {
+    return queryInterface.dropTable('quotationStats');
+  }
+};
\ No newline at end of file
diff --git a/models/quotationstat.js b/models/quotationstat.js
new file mode 100644
index 0000000..3314816
--- /dev/null
+++ b/models/quotationstat.js
@@ -0,0 +1,11 @@
+'use strict';
+module.exports = (sequelize, DataTypes) => {
+  const quotationStat = sequelize.define('quotationStat', {
+    serverID: DataTypes.BIGINT,
+    stat: DataTypes.STRING
+  }, {});
+  quotationStat.associate = function(models) {
+    // associations can be defined here
+  };
+  return quotationStat;
+};
\ No newline at end of file