| 
					
				 | 
			
			
				@@ -1,49 +1,84 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import { db, IRandomElementMixin } from "../db"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import { isAuthorised } from "../util"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import client from "../client"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import { ICommand } from "./command"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import { ObjectChain, CollectionChain } from "lodash"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { getRepository } from "typeorm"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { MessageReaction } from "../entity/MessageReaction"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { KnownUser } from "../entity/KnownUser"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { ReactionType, ReactionEmote } from "../entity/ReactionEmote"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const pattern = /^react to\s+"([^"]+)"\s+with\s+\<:[^:]+:([^\>]+)\>$/i; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+async function getRandomEmotes(allowedTypes: ReactionType[]) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let reactionEmotesRepo = getRepository(ReactionEmote); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return await reactionEmotesRepo.query(` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        select reactionId  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        from (  select type, reactionId 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                from reaction_emote 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                where type in (?) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                order by type, random() ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        group by type`, [ allowedTypes ]) as string[]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 export default { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     commands: [ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             pattern: "react to", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            action: (msg, s) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if (!isAuthorised(msg.member)) return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            action: async (msg, s) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (!isAuthorised(msg.member)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 let contents = pattern.exec(s); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 if (contents != null) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     let reactable = contents[1].trim().toLowerCase(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     let reactionEmoji = contents[2]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     if (!client.emojis.has(reactionEmoji)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         msg.channel.send(`${msg.author.toString()} I cannot react with this emoji :(`); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    db.get("messageReactions").set(reactable, reactionEmoji); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    db.write(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    let repo = getRepository(MessageReaction); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    let message = repo.create({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        message: reactable, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        reactionEmoteId: reactionEmoji 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    await repo.save(message); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     msg.channel.send(`${msg.author.toString()} Added reaction!`); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             pattern: "remove reaction to", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            action: (msg, s) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if (!isAuthorised(msg.member)) return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            action: async (msg, s) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (!isAuthorised(msg.member)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 let content = s.substring("remove reaction to ".length).trim().toLowerCase(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if (!db.get("messageReactions").has(content).value()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                let repo = getRepository(MessageReaction); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                let result = await repo.delete({ message: content }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (result.affected == 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     msg.channel.send(`${msg.author.toString()} No such reaction available!`); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                db.get("messageReactions").unset(content).write(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 msg.channel.send(`${msg.author.toString()} Removed reaction!`); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             pattern: "reactions", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            action: msg => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                let reactions = db.get("messageReactions").keys().value().reduce((p: string, c: string) => `${p}\n${c}`, ""); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                msg.channel.send(`I'll react to the following messages:\n\`\`\`${reactions}\`\`\``); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            action: async msg => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                let reactionsRepo = getRepository(MessageReaction); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                let messages = await reactionsRepo.find({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    select: [ "message" ] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                let reactions = messages.reduce((p, c) => `${p}\n${c.message}`, ""); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                msg.channel.send(`I'll react to the following messages:\n\`\`\`${reactions}\n\`\`\``); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ], 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -61,67 +96,79 @@ export default { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             description: "Lists all known messages this bot can react to." 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    onMessage: (actionsDone, msg, content) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    onMessage: async (actionsDone, msg, content) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (actionsDone) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         let lowerContent = content.toLowerCase(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (db.get("messageReactions").has(lowerContent).value()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            msg.react(client.emojis.get((db.get("messageReactions") as ObjectChain<any>).get(lowerContent).value())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let reactionRepo = getRepository(MessageReaction); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let usersRepo = getRepository(KnownUser); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let message = await reactionRepo.findOne({ message: lowerContent }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if(message) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            msg.react(client.emojis.get(message.reactionEmoteId)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (msg.mentions.users.size == 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (!(db.get("reactableMentionedUsers") as CollectionChain<any>).intersectionWith(msg.mentions.users.map(u => u.id)).isEmpty().value()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            const emoteId = ((db 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                .get("emotes") as ObjectChain<any>) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                .get("angery") as IRandomElementMixin) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                .randomElement() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                .value(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            msg.react(client.emojis.find(e => e.id == emoteId)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let knownUsers = await usersRepo.find({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            select: [ "mentionReactionType" ], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            where: [...msg.mentions.users.map(u => ({ userId: u.id }))] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if(knownUsers.length == 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let reactionEmoteTypes = new Set<ReactionType>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for(let user of knownUsers) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if(user.mentionReactionType == ReactionType.NONE) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            reactionEmoteTypes.add(user.mentionReactionType); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let randomEmotes = await getRandomEmotes([...reactionEmoteTypes]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for(let emote in randomEmotes) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            await msg.react(client.emojis.find(e => e.id == emote)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    onIndirectMention: (actionsDone, msg) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    onIndirectMention: async (actionsDone, msg) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (actionsDone) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        let emoteType = "angery"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if ((db.get("specialUsers") as CollectionChain<any>).includes(msg.author.id).value()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            emoteType = "hug"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        else if ((db.get("bigUsers") as CollectionChain<any>).includes(msg.author.id).value()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            emoteType = "big"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        else if ((db.get("dedUsers") as CollectionChain<any>).includes(msg.author.id).value()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            emoteType = "ded"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        let id = ((db 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            .get("emotes") as ObjectChain<string>) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            .get(emoteType) as IRandomElementMixin) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            .randomElement() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            .value(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        let emote = client.emojis.find(e => e.id == id); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let emoteType = ReactionType.ANGERY; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let repo = getRepository(KnownUser); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let knownUser = await repo.findOne({  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            select: [ "mentionReactionType" ], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            where: [{userID: msg.id}] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if(!knownUser || knownUser.mentionReactionType == ReactionType.NONE) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        emoteType = knownUser.mentionReactionType; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let emotes = await getRandomEmotes([ emoteType ]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if(emotes.length != 1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let emote = client.emojis.find(e => e.id == emotes[0]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (!emote) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            console.log(`WARNING: Emote ${id} no longer is valid. Deleting invalid emojis from the list...`); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            ((db.get("emotes") as ObjectChain<any>) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                .get(emoteType) as CollectionChain<any>) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                .remove((id: string) => !client.emojis.has(id)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                .write(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            id = ((db 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                .get("emotes") as ObjectChain<any>) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                .get(emoteType) as IRandomElementMixin) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                .randomElement() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                .value(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            emote = client.emojis.find(e => e.id == id); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            console.log(`WARNING: Emote ${emotes[0]} no longer is valid. Deleting invalid emojis from the list...`); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (!emote) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            let emotesRepo = getRepository(ReactionEmote); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            emotesRepo.delete({ reactionId: emotes[0] }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         msg.channel.send(emote.toString()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return true; 
			 |