Added gif, detect if any image servers are disconnected

This commit is contained in:
Essem 2021-06-28 17:59:05 -05:00
parent 0fbc165154
commit 41c8be04cf
7 changed files with 523 additions and 437 deletions

View file

@ -52,7 +52,7 @@ class ImageCommand extends Command {
if (this.constructor.requiresImage) { if (this.constructor.requiresImage) {
try { try {
const image = await imageDetect(this.client, this.message); const image = await imageDetect(this.client, this.message, true);
if (image === undefined) { if (image === undefined) {
collections.runningCommands.delete(this.message.author.id); collections.runningCommands.delete(this.message.author.id);
return this.constructor.noImage; return this.constructor.noImage;
@ -61,7 +61,7 @@ class ImageCommand extends Command {
return "That image is too large!"; return "That image is too large!";
} else if (image.type === "tenorlimit") { } else if (image.type === "tenorlimit") {
collections.runningCommands.delete(this.message.author.id); collections.runningCommands.delete(this.message.author.id);
return "I've been rate-limited by Tenor. Please try uploading the GIF elsewhere."; return "I've been rate-limited by Tenor. Please try uploading your GIF elsewhere.";
} }
magickParams.path = image.path; magickParams.path = image.path;
magickParams.type = image.type; magickParams.type = image.type;

16
commands/general/gif.js Normal file
View file

@ -0,0 +1,16 @@
const Command = require("../../classes/command.js");
const imageDetect = require("../../utils/imagedetect.js");
class GifCommand extends Command {
async run() {
this.message.channel.sendTyping();
const image = await imageDetect(this.client, this.message);
if (image === undefined) return "You need to provide an image with a QR code to read!";
return image.path;
}
static description = "Gets a direct GIF URL (useful for saving GIFs from sites like Tenor)";
static aliases = ["getgif", "giflink"];
}
module.exports = GifCommand;

View file

@ -13,6 +13,7 @@ Napi::Value Snapchat(const Napi::CallbackInfo &info) {
Napi::Object obj = info[0].As<Napi::Object>(); Napi::Object obj = info[0].As<Napi::Object>();
Napi::Buffer<char> data = obj.Get("data").As<Napi::Buffer<char>>(); Napi::Buffer<char> data = obj.Get("data").As<Napi::Buffer<char>>();
string caption = obj.Get("caption").As<Napi::String>().Utf8Value(); string caption = obj.Get("caption").As<Napi::String>().Utf8Value();
float pos = obj.Has("pos") ? obj.Get("pos").As<Napi::Number>().FloatValue() : 0.5;
string type = obj.Get("type").As<Napi::String>().Utf8Value(); string type = obj.Get("type").As<Napi::String>().Utf8Value();
int delay = int delay =
obj.Has("delay") ? obj.Get("delay").As<Napi::Number>().Int32Value() : 0; obj.Has("delay") ? obj.Get("delay").As<Napi::Number>().Int32Value() : 0;
@ -26,6 +27,7 @@ Napi::Value Snapchat(const Napi::CallbackInfo &info) {
readImages(&frames, Blob(data.Data(), data.Length())); readImages(&frames, Blob(data.Data(), data.Length()));
size_t width = frames.front().baseColumns(); size_t width = frames.front().baseColumns();
size_t height = frames.front().baseRows();
string query(to_string(width - ((width / 25) * 2)) + "x"); string query(to_string(width - ((width / 25) * 2)) + "x");
Image caption_image(Geometry(query), Color("none")); Image caption_image(Geometry(query), Color("none"));
caption_image.backgroundColor(Color("none")); caption_image.backgroundColor(Color("none"));
@ -42,7 +44,7 @@ Napi::Value Snapchat(const Napi::CallbackInfo &info) {
for (Image &image : coalesced) { for (Image &image : coalesced) {
list<Image> images; list<Image> images;
image.composite(caption_image, Magick::CenterGravity, image.composite(caption_image, 0, height * pos,
Magick::OverCompositeOp); Magick::OverCompositeOp);
image.magick(type); image.magick(type);
image.animationDelay(delay == 0 ? image.animationDelay() : delay); image.animationDelay(delay == 0 ? image.animationDelay() : delay);

900
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -33,7 +33,7 @@
"file-type": "^16.1.0", "file-type": "^16.1.0",
"jsqr": "^1.3.1", "jsqr": "^1.3.1",
"lavacord": "^1.1.9", "lavacord": "^1.1.9",
"node-addon-api": "^3.1.0", "node-addon-api": "^3.2.1",
"node-emoji": "^1.10.0", "node-emoji": "^1.10.0",
"node-fetch": "^2.6.1", "node-fetch": "^2.6.1",
"qrcode": "^1.4.4", "qrcode": "^1.4.4",

View file

@ -123,10 +123,10 @@ exports.disconnect = async () => {
const getIdeal = async () => { const getIdeal = async () => {
let serversLeft = this.connections.size; let serversLeft = this.connections.size;
if (serversLeft === 0) { if (serversLeft < this.servers.length) {
for (const server of this.servers) { for (const server of this.servers) {
try { try {
await this.connect(server); if (!this.connections.has(server)) await this.connect(server);
} catch (e) { } catch (e) {
logger.error(e); logger.error(e);
} }
@ -193,7 +193,7 @@ exports.check = (cmd) => {
return magick[cmd] ? true : false; return magick[cmd] ? true : false;
}; };
exports.getType = async (image) => { exports.getType = async (image, extraReturnTypes) => {
if (!image.startsWith("http")) { if (!image.startsWith("http")) {
const imageType = await fileType.fromFile(image); const imageType = await fileType.fromFile(image);
if (imageType && formats.includes(imageType.mime)) { if (imageType && formats.includes(imageType.mime)) {
@ -214,7 +214,7 @@ exports.getType = async (image) => {
}); });
clearTimeout(timeout); clearTimeout(timeout);
const size = imageRequest.headers.has("Content-Range") ? imageRequest.headers.get("Content-Range").split("/")[1] : imageRequest.headers.get("Content-Length"); const size = imageRequest.headers.has("Content-Range") ? imageRequest.headers.get("Content-Range").split("/")[1] : imageRequest.headers.get("Content-Length");
if (parseInt(size) > 26214400) { // 25 MB if (parseInt(size) > 26214400 && extraReturnTypes) { // 25 MB
type = "large"; type = "large";
return type; return type;
} }

View file

@ -34,7 +34,7 @@ const imageFormats = ["image/jpeg", "image/png", "image/webp", "image/gif"];
const videoFormats = ["video/mp4", "video/webm", "video/mov"]; const videoFormats = ["video/mp4", "video/webm", "video/mov"];
// gets the proper image paths // gets the proper image paths
const getImage = async (image, image2, video, gifv = false) => { const getImage = async (image, image2, video, extraReturnTypes, gifv = false) => {
try { try {
const payload = { const payload = {
url: image2, url: image2,
@ -48,7 +48,7 @@ const getImage = async (image, image2, video, gifv = false) => {
// Note that MP4 conversion requires an ImageMagick build that supports MPEG decoding // Note that MP4 conversion requires an ImageMagick build that supports MPEG decoding
if (process.env.TENOR !== "") { if (process.env.TENOR !== "") {
const data = await fetch(`https://g.tenor.com/v1/gifs?ids=${image2.split("-").pop()}&media_filter=minimal&limit=1&key=${process.env.TENOR}`); const data = await fetch(`https://g.tenor.com/v1/gifs?ids=${image2.split("-").pop()}&media_filter=minimal&limit=1&key=${process.env.TENOR}`);
if (data.status === 429) return "tenorlimit"; if (data.status === 429) return extraReturnTypes ? "tenorlimit" : null;
const json = await data.json(); const json = await data.json();
payload.path = json.results[0].media[0].gif.url; payload.path = json.results[0].media[0].gif.url;
} else { } else {
@ -69,10 +69,10 @@ const getImage = async (image, image2, video, gifv = false) => {
} }
payload.type = "image/gif"; payload.type = "image/gif";
} else if (video) { } else if (video) {
payload.type = await getType(payload.path); payload.type = await getType(payload.path, extraReturnTypes);
if (!payload.type || (!videoFormats.includes(payload.type) && !imageFormats.includes(payload.type))) return; if (!payload.type || (!videoFormats.includes(payload.type) && !imageFormats.includes(payload.type))) return;
} else { } else {
payload.type = await getType(payload.path); payload.type = await getType(payload.path, extraReturnTypes);
if (!payload.type || !imageFormats.includes(payload.type)) return; if (!payload.type || !imageFormats.includes(payload.type)) return;
} }
return payload; return payload;
@ -85,22 +85,22 @@ const getImage = async (image, image2, video, gifv = false) => {
} }
}; };
const checkImages = async (message, video) => { const checkImages = async (message, extraReturnTypes, video) => {
let type; let type;
// first check the embeds // first check the embeds
if (message.embeds.length !== 0) { if (message.embeds.length !== 0) {
// embeds can vary in types, we check for tenor gifs first // embeds can vary in types, we check for tenor gifs first
if (message.embeds[0].type === "gifv") { if (message.embeds[0].type === "gifv") {
type = await getImage(message.embeds[0].video.url, message.embeds[0].url, video, true); type = await getImage(message.embeds[0].video.url, message.embeds[0].url, video, extraReturnTypes, true);
// then we check for other image types // then we check for other image types
} else if ((message.embeds[0].type === "video" || message.embeds[0].type === "image") && message.embeds[0].thumbnail) { } else if ((message.embeds[0].type === "video" || message.embeds[0].type === "image") && message.embeds[0].thumbnail) {
type = await getImage(message.embeds[0].thumbnail.proxy_url, message.embeds[0].thumbnail.url, video); type = await getImage(message.embeds[0].thumbnail.proxy_url, message.embeds[0].thumbnail.url, video, extraReturnTypes);
// finally we check both possible image fields for "generic" embeds // finally we check both possible image fields for "generic" embeds
} else if (message.embeds[0].type === "rich") { } else if (message.embeds[0].type === "rich") {
if (message.embeds[0].thumbnail) { if (message.embeds[0].thumbnail) {
type = await getImage(message.embeds[0].thumbnail.proxy_url, message.embeds[0].thumbnail.url, video); type = await getImage(message.embeds[0].thumbnail.proxy_url, message.embeds[0].thumbnail.url, video, extraReturnTypes);
} else if (message.embeds[0].image) { } else if (message.embeds[0].image) {
type = await getImage(message.embeds[0].image.proxy_url, message.embeds[0].image.url, video); type = await getImage(message.embeds[0].image.proxy_url, message.embeds[0].image.url, video, extraReturnTypes);
} }
} }
// then check the attachments // then check the attachments
@ -112,23 +112,23 @@ const checkImages = async (message, video) => {
}; };
// this checks for the latest message containing an image and returns the url of the image // this checks for the latest message containing an image and returns the url of the image
module.exports = async (client, cmdMessage, video = false) => { module.exports = async (client, cmdMessage, extraReturnTypes = false, video = false) => {
// we start by checking if the message is a reply to another message // we start by checking if the message is a reply to another message
if (cmdMessage.messageReference) { if (cmdMessage.messageReference) {
const replyMessage = await client.getMessage(cmdMessage.messageReference.channelID, cmdMessage.messageReference.messageID).catch(() => undefined); const replyMessage = await client.getMessage(cmdMessage.messageReference.channelID, cmdMessage.messageReference.messageID).catch(() => undefined);
if (replyMessage) { if (replyMessage) {
const replyResult = await checkImages(replyMessage, video); const replyResult = await checkImages(replyMessage, extraReturnTypes, video);
if (replyResult !== false) return replyResult; if (replyResult !== false) return replyResult;
} }
} }
// then we check the current message // then we check the current message
const result = await checkImages(cmdMessage, video); const result = await checkImages(cmdMessage, extraReturnTypes, video);
if (result !== false) return result; if (result !== false) return result;
// if there aren't any replies then iterate over the last few messages in the channel // if there aren't any replies then iterate over the last few messages in the channel
const messages = await client.getMessages(cmdMessage.channel.id); const messages = await client.getMessages(cmdMessage.channel.id);
// iterate over each message // iterate over each message
for (const message of messages) { for (const message of messages) {
const result = await checkImages(message, video); const result = await checkImages(message, extraReturnTypes, video);
if (result === false) { if (result === false) {
continue; continue;
} else { } else {