|  | @@ -6,6 +6,13 @@ const interval = require("interval-promise");
 | 
	
		
			
				|  |  |  const TurndownService = require("turndown");
 | 
	
		
			
				|  |  |  const fs = require("fs");
 | 
	
		
			
				|  |  |  const isImage = require("is-image");
 | 
	
		
			
				|  |  | +const Jimp = require("jimp");
 | 
	
		
			
				|  |  | +const Clarifai = require("clarifai");
 | 
	
		
			
				|  |  | +const ClarifaiTOKEN = require("./clarifai_keys.js");
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +const clarifaiApp = new Clarifai.App({
 | 
	
		
			
				|  |  | +    apiKey: ClarifaiTOKEN
 | 
	
		
			
				|  |  | +});
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  const turndown = new TurndownService();
 | 
	
		
			
				|  |  |  turndown.addRule("image", {
 | 
	
	
		
			
				|  | @@ -67,6 +74,61 @@ function isAuthorised(member) {
 | 
	
		
			
				|  |  |      return true;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +async function processFaceSwap(message, attachmentUrl) {
 | 
	
		
			
				|  |  | +    let result = await clarifaiApp.models.predict(Clarifai.FACE_DETECT_MODEL, attachmentUrl);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if(result.outputs[0].data.regions === undefined || result.outputs[0].data.regions.length == 0)
 | 
	
		
			
				|  |  | +        return;
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    let image = await Jimp.read(attachmentUrl);
 | 
	
		
			
				|  |  | +    let w = image.getWidth();
 | 
	
		
			
				|  |  | +    let h = image.getHeight();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    let emojiKeys = [...client.emojis.filter(e => !e.animated).keys()];
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    for(let region of result.outputs[0].data.regions) {
 | 
	
		
			
				|  |  | +        let bb = region.region_info.bounding_box;
 | 
	
		
			
				|  |  | +        let bw = (bb.right_col - bb.left_col) * w;
 | 
	
		
			
				|  |  | +        let bh = (bb.bottom_row - bb.top_row) * h;
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +        let dx = (bb.right_col + bb.left_col) * w / 2;
 | 
	
		
			
				|  |  | +        let dy = (bb.bottom_row + bb.top_row) * h / 2;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        let emojiKey = emojiKeys[Math.floor(Math.random() * emojiKeys.length)];
 | 
	
		
			
				|  |  | +        let emoji = client.emojis.get(emojiKey);
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +        let emojiImage = await Jimp.read(emoji.url);
 | 
	
		
			
				|  |  | +        let ew = emojiImage.getWidth();
 | 
	
		
			
				|  |  | +        let eh = emojiImage.getHeight();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        let scaleFactor = Math.max(bw, bh) / Math.max(ew, eh);
 | 
	
		
			
				|  |  | +        ew *= scaleFactor;
 | 
	
		
			
				|  |  | +        eh *= scaleFactor;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        emojiImage = emojiImage.scale(scaleFactor);
 | 
	
		
			
				|  |  | +        image = image.composite(emojiImage, dx - ew / 2, dy - eh / 2);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    image.quality(90);
 | 
	
		
			
				|  |  | +    let buffer = await image.getBufferAsync(Jimp.MIME_JPEG);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    message.channel.send(`I noticed a face in the image. I think this looks better ${client.emojis.get("505076258753740810").toString()}`, {
 | 
	
		
			
				|  |  | +        files: [ buffer ]
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +function faceMorph(message) {
 | 
	
		
			
				|  |  | +    let probValue = db.get("faceEditChannels").get(message.channel.id);
 | 
	
		
			
				|  |  | +    if(probValue.isUndefined().value() || probValue.isNull().value())
 | 
	
		
			
				|  |  | +        return;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if(Math.random() > probValue.value())
 | 
	
		
			
				|  |  | +        return;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    let imageAttachment = message.attachments.find(v => isImage(v.filename));
 | 
	
		
			
				|  |  | +    processFaceSwap(message, imageAttachment.url).catch(err => console.log(`Failed to run faceapp because ${err}`));
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  const commands = {
 | 
	
		
			
				|  |  |      "make guide": msg => {
 | 
	
		
			
				|  |  |          if (!isAuthorised(msg.member)) return;
 | 
	
	
		
			
				|  | @@ -156,15 +218,16 @@ client.on("ready", () => {
 | 
	
		
			
				|  |  |  });
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  client.on("message", m => {
 | 
	
		
			
				|  |  | +    if (m.author.id == client.user.id) return;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      let imagesCount = m.attachments.filter(v => isImage(v.filename)).size;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      if(imagesCount > 0) {
 | 
	
		
			
				|  |  |          let now = new Date();
 | 
	
		
			
				|  |  |          fs.writeSync(statsFile, `${now.getUTCFullYear()}-${now.getUTCMonth()+1}-${now.getUTCDate()} ${now.getUTCHours()}:${now.getUTCMinutes()};${imagesCount};${m.channel.name}\n`);
 | 
	
		
			
				|  |  | +        faceMorph(m);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    if (m.author.id == client.user.id) return;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |      let content = m.cleanContent.trim();
 | 
	
		
			
				|  |  |      let lowerContent = content.toLowerCase();
 | 
	
		
			
				|  |  |      if(db.get("messageReactions").has(lowerContent).value()) {
 | 
	
	
		
			
				|  | @@ -241,4 +304,4 @@ client.on("messageReactionAdd", (r, u) => {
 | 
	
		
			
				|  |  |          r.message.react(r.emoji);
 | 
	
		
			
				|  |  |  });
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -client.login(TOKEN);
 | 
	
		
			
				|  |  | +client.login(TOKEN);
 |