Heavy work on the image detection code, fixed mention prefixes not being properly registered

This commit is contained in:
TheEssem 2020-10-18 16:53:35 -05:00
parent 6cd9878632
commit cf5c649384
57 changed files with 240 additions and 443 deletions

View file

@ -1,26 +1,67 @@
const magick = require("../build/Release/image.node");
const fetch = require("node-fetch");
const { promisify } = require("util");
const FormData = require("form-data");
const fs = require("fs");
const AbortController = require("abort-controller");
const fileType = require("file-type");
const execPromise = promisify(require("child_process").exec);
const formats = ["image/jpeg", "image/png", "image/webp", "image/gif"];
exports.run = async (object, fromAPI = false) => {
if (process.env.API === "true" && !fromAPI) {
const form = new FormData();
form.append("data", JSON.stringify(object));
if (object.path) form.append("image", fs.createReadStream(object.path));
const req = await fetch(`${process.env.API_URL}/run`, {
method: "POST",
body: form,
headers: form.getHeaders()
body: JSON.stringify(object),
headers: {
"Content-Type": "application/json"
}
});
return await req.buffer();
const buffer = await req.buffer();
return {
buffer: buffer,
type: req.headers.get("content-type").split("/")[1]
};
} else {
let type;
if (!fromAPI && object.path) {
type = (await this.getType(object.path)).split("/")[1];
object.type = type;
const delay = (await execPromise(`ffprobe -v 0 -of csv=p=0 -select_streams v:0 -show_entries stream=r_frame_rate ${object.path}`)).stdout.replace("\n", "");
object.delay = (100 / delay.split("/")[0]) * delay.split("/")[1];
}
const data = await promisify(magick[object.cmd])(object);
return data;
return fromAPI ? data : {
buffer: data,
type: type
};
}
};
exports.check = (cmd) => {
return magick[cmd] ? true : false;
};
exports.getType = async (image) => {
let type;
const controller = new AbortController();
const timeout = setTimeout(() => {
controller.abort();
}, 25000);
try {
const imageRequest = await fetch(image, { signal: controller.signal, highWaterMark: 512 });
const imageBuffer = await imageRequest.buffer();
const imageType = await fileType.fromBuffer(imageBuffer);
if (imageType && formats.includes(imageType.mime)) {
type = imageType.mime;
}
} catch (error) {
if (error.name === "AbortError") {
throw Error("Timed out");
} else {
throw error;
}
} finally {
clearTimeout(timeout);
}
return type;
};

View file

@ -1,50 +1,32 @@
const fetch = require("node-fetch");
const AbortController = require("abort-controller");
const fileType = require("file-type");
const { promisify } = require("util");
const { writeFile } = require("fs").promises;
const execPromise = promisify(require("child_process").exec);
const urlRegex = /(?:\w+:)?\/\/(\S+)/;
// this checks if the file is, in fact, an image
const typeCheck = async (image, image2, gifv = false) => {
// download the file to a buffer
const controller = new AbortController();
const timeout = setTimeout(() => {
controller.abort();
}, 25000);
// gets the proper image paths
const getImage = async (image, image2, gifv = false) => {
try {
const imageRequest = await fetch(image, { signal: controller.signal });
const imageBuffer = await imageRequest.buffer();
if (imageBuffer.size >= 25 * 1024 * 1024) return;
// get the file type
const imageType = await fileType.fromBuffer(imageBuffer);
// check if the file is a jpeg, png, or webp
const formats = ["image/jpeg", "image/png", "image/webp", "image/gif"];
if (gifv) formats.push("video/mp4");
if (imageType && formats.includes(imageType.mime)) {
// if it is, then return the url with the file type
const path = `/tmp/${Math.random().toString(36).substring(2, 15)}.${imageType.ext}`;
await writeFile(path, imageBuffer);
const payload = {
type: imageType.ext !== "mp4" ? (imageType.ext === "jpg" ? "jpeg" : imageType.ext) : "gif",
path: path,
url: image2
};
if (payload.type === "gif") payload.delay = (await execPromise(`ffprobe -v 0 -of csv=p=0 -select_streams v:0 -show_entries stream=r_frame_rate ${path}`)).stdout.replace("\n", "");
return payload;
} else {
// if not, then return false
return false;
let requestImage = image;
if (gifv) {
if (image2.includes("tenor.com") && process.env.TENOR !== "") {
const data = await fetch(`https://api.tenor.com/v1/gifs?ids=${image2.split("-").pop()}&key=${process.env.TENOR}`);
const json = await data.json();
console.log(json.results[0].media[0].gif.url);
requestImage = json.results[0].media[0].gif.url;
} else if (image2.includes("giphy.com")) {
requestImage = `https://media0.giphy.com/media/${image2.split("-").pop()}/giphy.gif`;
} else if (image2.includes("imgur.com")) {
requestImage = image.replace(".mp4", ".gif");
}
}
const payload = {
url: image2,
path: requestImage
};
return payload;
} catch (error) {
if (error.name === "AbortError") {
throw Error("Timed out");
} else {
throw error;
}
} finally {
clearTimeout(timeout);
}
};
@ -52,25 +34,23 @@ const checkImages = async (message) => {
let type;
// first check the embeds
if (message.embeds.length !== 0) {
// embeds can have 2 possible entries with images, we check the thumbnail first
// embeds can vary in types, we check for tenor gifs first
if (message.embeds[0].type === "gifv") {
type = await typeCheck(message.embeds[0].video.url, message.embeds[0].video.url, true);
} else if (message.embeds[0].thumbnail) {
type = await typeCheck(message.embeds[0].thumbnail.proxy_url, message.embeds[0].thumbnail.url);
// if there isn't a thumbnail check the image area
} else if (message.embeds[0].image) {
type = await typeCheck(message.embeds[0].image.proxy_url, message.embeds[0].image.url);
type = await getImage(message.embeds[0].video.url, message.embeds[0].url, true);
// then we check for other image types
} else if (message.embeds[0].type === "video" || message.embeds[0].type === "image") {
type = await getImage(message.embeds[0].thumbnail.proxy_url, message.embeds[0].thumbnail.url);
// finally we check both possible image fields for "generic" embeds
} else if (message.embeds[0].type === "rich") {
if (message.embeds[0].thumbnail) {
type = await getImage(message.embeds[0].thumbnail.proxy_url, message.embeds[0].thumbnail.url);
} else if (message.embeds[0].image) {
type = await getImage(message.embeds[0].image.proxy_url, message.embeds[0].image.url);
}
}
// then check the attachments
} else if (message.attachments.length !== 0) {
// get type of file
type = await typeCheck(message.attachments[0].proxy_url, message.attachments[0].url);
// if there's nothing in the attachments check the urls in the message if there are any
} else if (urlRegex.test(message.content)) {
// get url
const url = message.content.match(urlRegex);
// get type of file
type = await typeCheck(url[0], url[0]);
} else if (message.attachments.length !== 0 && message.attachments[0].width) {
type = await getImage(message.attachments[0].proxy_url, message.attachments[0].url);
}
// if the file is an image then return it
return type ? type : false;