facemorph.js 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. const Clarifai = require("clarifai");
  2. const ClarifaiTOKEN = require("../clarifai_keys.js");
  3. const db = require("../db.js");
  4. const util = require("../util.js");
  5. const Jimp = require("jimp");
  6. const client = require("../client.js");
  7. const EMOTE_GUILD = "505333548694241281";
  8. const clarifaiApp = new Clarifai.App({
  9. apiKey: ClarifaiTOKEN
  10. });
  11. async function processFaceSwap(message, attachmentUrl) {
  12. let result = await clarifaiApp.models.predict(Clarifai.FACE_DETECT_MODEL, attachmentUrl);
  13. if(result.outputs[0].data.regions === undefined || result.outputs[0].data.regions.length == 0)
  14. return;
  15. let image = await Jimp.read(attachmentUrl);
  16. let w = image.getWidth();
  17. let h = image.getHeight();
  18. let emojiKeys = [...client.guilds.get(EMOTE_GUILD).emojis.filter(e => !e.animated).keys()];
  19. for(let region of result.outputs[0].data.regions) {
  20. let bb = region.region_info.bounding_box;
  21. let bw = (bb.right_col - bb.left_col) * w;
  22. let bh = (bb.bottom_row - bb.top_row) * h;
  23. let dx = (bb.right_col + bb.left_col) * w / 2;
  24. let dy = (bb.bottom_row + bb.top_row) * h / 2;
  25. let emojiKey = emojiKeys[Math.floor(Math.random() * emojiKeys.length)];
  26. let emoji = client.emojis.get(emojiKey);
  27. let emojiImage = await Jimp.read(emoji.url);
  28. let ew = emojiImage.getWidth();
  29. let eh = emojiImage.getHeight();
  30. const CONSTANT_SCALE = 1.5;
  31. let scaleFactor = Math.max(bw, bh) / Math.min(ew, eh) * CONSTANT_SCALE;
  32. ew *= scaleFactor;
  33. eh *= scaleFactor;
  34. emojiImage = emojiImage.scale(scaleFactor);
  35. image = image.composite(emojiImage, dx - ew / 2, dy - eh / 2);
  36. }
  37. image.quality(90);
  38. let buffer = await image.getBufferAsync(Jimp.MIME_JPEG);
  39. message.channel.send(`I noticed a face in the image. I think this looks better ${client.emojis.get("505076258753740810").toString()}`, {
  40. files: [ buffer ]
  41. });
  42. }
  43. const onMessage = (msg, contents, actionsDone) => {
  44. if (actionsDone)
  45. return false;
  46. let imagesCount = msg.attachments.filter(v => util.isValidImage(v.filename)).size;
  47. if (imagesCount > 0) {
  48. let probValue = db.get("faceEditChannels").get(msg.channel.id);
  49. if (probValue.isUndefined().value() || probValue.isNull().value())
  50. return false;
  51. if (Math.random() > probValue.value())
  52. return false;
  53. let imageAttachment = msg.attachments.find(v => util.isValidImage(v.filename));
  54. processFaceSwap(msg, imageAttachment.url).catch(err => console.log(`Failed to run faceapp because ${err}`));
  55. return true;
  56. }
  57. return false;
  58. };
  59. module.exports = {
  60. onMessage: onMessage
  61. };