Remove delay parameter, change argument handling, make help command show proper flag types

This commit is contained in:
Essem 2022-06-07 18:26:40 -05:00
parent 28f0245652
commit 6b34cb9d9e
No known key found for this signature in database
GPG key ID: 7D497397CC3A2A8C
63 changed files with 82 additions and 219 deletions

View file

@ -41,7 +41,6 @@ The job object is formatted like this:
"url": string, // original image URL, used for message filtering "url": string, // original image URL, used for message filtering
"params": { // content varies depending on the command, some common parameters are listed here "params": { // content varies depending on the command, some common parameters are listed here
"type": string, // mime type of output, should usually be the same as input "type": string, // mime type of output, should usually be the same as input
"delay": integer, // for manually specifying GIF frame delay, set to 0 to use the default delay
... ...
} }
} }

View file

@ -13,7 +13,7 @@ class Command {
this.author = options.message.author; this.author = options.message.author;
this.member = options.message.member; this.member = options.message.member;
this.content = options.content; this.content = options.content;
this.specialArgs = options.specialArgs; this.specialArgs = this.options = options.specialArgs;
this.reference = { this.reference = {
messageReference: { messageReference: {
channelID: this.channel.id, channelID: this.channel.id,
@ -27,6 +27,7 @@ class Command {
}; };
} else if (options.type === "application") { } else if (options.type === "application") {
this.interaction = options.interaction; this.interaction = options.interaction;
this.args = [];
this.channel = options.interaction.channel; this.channel = options.interaction.channel;
this.author = this.member = options.interaction.guildID ? options.interaction.member : options.interaction.user; this.author = this.member = options.interaction.guildID ? options.interaction.member : options.interaction.user;
if (options.interaction.data.options) { if (options.interaction.data.options) {

View file

@ -68,7 +68,6 @@ class ImageCommand extends Command {
magickParams.path = image.path; magickParams.path = image.path;
magickParams.params.type = image.type; magickParams.params.type = image.type;
magickParams.url = image.url; // technically not required but can be useful for text filtering magickParams.url = image.url; // technically not required but can be useful for text filtering
magickParams.params.delay = image.delay ?? 0;
if (this.constructor.requiresGIF) magickParams.onlyGIF = true; if (this.constructor.requiresGIF) magickParams.onlyGIF = true;
} catch (e) { } catch (e) {
runningCommands.delete(this.author.id); runningCommands.delete(this.author.id);
@ -77,7 +76,7 @@ class ImageCommand extends Command {
} }
if (this.constructor.requiresText) { if (this.constructor.requiresText) {
const text = this.type === "classic" ? this.args : this.options.text; const text = this.options.text ?? this.args;
if (text.length === 0 || !await this.criteria(text)) { if (text.length === 0 || !await this.criteria(text)) {
runningCommands.delete(this.author.id); runningCommands.delete(this.author.id);
return this.constructor.noText; return this.constructor.noText;
@ -86,7 +85,7 @@ class ImageCommand extends Command {
switch (typeof this.params) { switch (typeof this.params) {
case "function": case "function":
Object.assign(magickParams.params, this.params(magickParams.url, magickParams.delay)); Object.assign(magickParams.params, this.params(magickParams.url));
break; break;
case "object": case "object":
Object.assign(magickParams.params, this.params); Object.assign(magickParams.params, this.params);

View file

@ -2,7 +2,7 @@ import Command from "../../classes/command.js";
class DiceCommand extends Command { class DiceCommand extends Command {
async run() { async run() {
const max = this.type === "classic" ? parseInt(this.args[0]) : this.options.max; const max = this.options.max ?? parseInt(this.args[0]);
if (!max) { if (!max) {
return `🎲 The dice landed on ${Math.floor(Math.random() * 6) + 1}.`; return `🎲 The dice landed on ${Math.floor(Math.random() * 6) + 1}.`;
} else { } else {

View file

@ -3,7 +3,7 @@ import ImageCommand from "../../classes/imageCommand.js";
class HomebrewCommand extends ImageCommand { class HomebrewCommand extends ImageCommand {
params() { params() {
return { return {
caption: (this.type === "classic" ? this.args.join(" ") : this.options.text).toLowerCase().replaceAll("\n", " ") caption: (this.options.text ?? this.args.join(" ")).toLowerCase().replaceAll("\n", " ")
}; };
} }

View file

@ -3,7 +3,7 @@ import ImageCommand from "../../classes/imageCommand.js";
class SonicCommand extends ImageCommand { class SonicCommand extends ImageCommand {
params() { params() {
const cleanedMessage = (this.type === "classic" ? this.args.join(" ") : this.options.text).replaceAll("&", "\\&amp;").replaceAll(">", "\\&gt;").replaceAll("<", "\\&lt;").replaceAll("\"", "\\&quot;").replaceAll("'", "\\&apos;").replaceAll("%", "\\%"); const cleanedMessage = (this.options.text ?? this.args.join(" ")).replaceAll("&", "\\&amp;").replaceAll(">", "\\&gt;").replaceAll("<", "\\&lt;").replaceAll("\"", "\\&quot;").replaceAll("'", "\\&apos;").replaceAll("%", "\\%");
return { return {
text: cleanedMessage text: cleanedMessage
}; };

View file

@ -6,7 +6,7 @@ class Base64Command extends Command {
if (this.type === "classic" && this.args.length === 0) return "You need to provide whether you want to encode or decode the text!"; if (this.type === "classic" && this.args.length === 0) return "You need to provide whether you want to encode or decode the text!";
const command = this.type === "classic" ? this.args[0].toLowerCase() : this.optionsArray[0].name.toLowerCase(); const command = this.type === "classic" ? this.args[0].toLowerCase() : this.optionsArray[0].name.toLowerCase();
if (command !== "decode" && command !== "encode") return "You need to provide whether you want to encode or decode the text!"; if (command !== "decode" && command !== "encode") return "You need to provide whether you want to encode or decode the text!";
const string = this.type === "classic" ? this.args.slice(1).join(" ") : this.options.text; const string = this.options.text ?? this.args.slice(1).join(" ");
if (!string || !string.trim()) return `You need to provide a string to ${command}!`; if (!string || !string.trim()) return `You need to provide a string to ${command}!`;
if (command === "decode") { if (command === "decode") {
const b64Decoded = Buffer.from(string, "base64").toString("utf8"); const b64Decoded = Buffer.from(string, "base64").toString("utf8");

View file

@ -6,7 +6,7 @@ class BroadcastCommand extends Command {
return new Promise((resolve) => { return new Promise((resolve) => {
const owners = process.env.OWNER.split(","); const owners = process.env.OWNER.split(",");
if (!owners.includes(this.author.id)) return "Only the bot owner can broadcast messages!"; if (!owners.includes(this.author.id)) return "Only the bot owner can broadcast messages!";
const message = this.type === "classic" ? this.args.join(" ") : this.options.message; const message = this.options.message ?? this.args.join(" ");
if (message && message.trim()) { if (message && message.trim()) {
this.ipc.broadcast("playbroadcast", message); this.ipc.broadcast("playbroadcast", message);
this.ipc.register("broadcastSuccess", () => { this.ipc.register("broadcastSuccess", () => {

View file

@ -3,7 +3,7 @@ import Command from "../../classes/command.js";
class EmoteCommand extends Command { class EmoteCommand extends Command {
async run() { async run() {
const emoji = this.type === "classic" ? this.content : this.options.emoji; const emoji = this.options.emoji ?? this.content;
if (!emoji || !emoji.trim()) return "You need to provide an emoji!"; if (!emoji || !emoji.trim()) return "You need to provide an emoji!";
if (emoji.split(" ")[0].match(/^<a?:.+:\d+>$/)) { if (emoji.split(" ")[0].match(/^<a?:.+:\d+>$/)) {
return `https://cdn.discordapp.com/emojis/${emoji.split(" ")[0].replace(/^<(a)?:.+:(\d+)>$/, "$2")}.${emoji.split(" ")[0].replace(/^<(a)?:.+:(\d+)>$/, "$1") === "a" ? "gif" : "png"}`; return `https://cdn.discordapp.com/emojis/${emoji.split(" ")[0].replace(/^<(a)?:.+:(\d+)>$/, "$2")}.${emoji.split(" ")[0].replace(/^<(a)?:.+:(\d+)>$/, "$1") === "a" ? "gif" : "png"}`;

View file

@ -6,7 +6,7 @@ class EvalCommand extends Command {
const owners = process.env.OWNER.split(","); const owners = process.env.OWNER.split(",");
if (!owners.includes(this.author.id)) return "Only the bot owner can use eval!"; if (!owners.includes(this.author.id)) return "Only the bot owner can use eval!";
await this.acknowledge(); await this.acknowledge();
const code = this.type === "classic" ? this.args.join(" ") : this.options.code; const code = this.options.code ?? this.args.join(" ");
try { try {
const evaled = eval(code); const evaled = eval(code);
const cleaned = await clean(evaled); const cleaned = await clean(evaled);

View file

@ -9,7 +9,7 @@ class ExecCommand extends Command {
const owners = process.env.OWNER.split(","); const owners = process.env.OWNER.split(",");
if (!owners.includes(this.author.id)) return "Only the bot owner can use exec!"; if (!owners.includes(this.author.id)) return "Only the bot owner can use exec!";
await this.acknowledge(); await this.acknowledge();
const code = this.type === "classic" ? this.args.join(" ") : this.options.cmd; const code = this.options.cmd ?? this.args.join(" ");
try { try {
const execed = await exec(code); const execed = await exec(code);
if (execed.stderr) return `\`ERROR\` \`\`\`xl\n${await clean(execed.stderr)}\n\`\`\``; if (execed.stderr) return `\`ERROR\` \`\`\`xl\n${await clean(execed.stderr)}\n\`\`\``;

View file

@ -1,3 +1,4 @@
import { Constants } from "eris";
import database from "../../utils/database.js"; import database from "../../utils/database.js";
import * as collections from "../../utils/collections.js"; import * as collections from "../../utils/collections.js";
import { random } from "../../utils/misc.js"; import { random } from "../../utils/misc.js";
@ -5,6 +6,7 @@ import paginator from "../../utils/pagination/pagination.js";
import * as help from "../../utils/help.js"; import * as help from "../../utils/help.js";
import Command from "../../classes/command.js"; import Command from "../../classes/command.js";
const tips = ["You can change the bot's prefix using the prefix command.", "Image commands also work with images previously posted in that channel.", "You can use the tags commands to save things for later use.", "You can visit https://projectlounge.pw/esmBot/help.html for a web version of this command list.", "You can view a command's aliases by putting the command name after the help command (e.g. help image).", "Parameters wrapped in [] are required, while parameters wrapped in {} are optional.", "esmBot is hosted and paid for completely out-of-pocket by the main developer. If you want to support development, please consider donating! https://patreon.com/TheEssem", "You can run commands in DMs as well, just message the bot with your command - no prefix needed!"]; const tips = ["You can change the bot's prefix using the prefix command.", "Image commands also work with images previously posted in that channel.", "You can use the tags commands to save things for later use.", "You can visit https://projectlounge.pw/esmBot/help.html for a web version of this command list.", "You can view a command's aliases by putting the command name after the help command (e.g. help image).", "Parameters wrapped in [] are required, while parameters wrapped in {} are optional.", "esmBot is hosted and paid for completely out-of-pocket by the main developer. If you want to support development, please consider donating! https://patreon.com/TheEssem", "You can run commands in DMs as well, just message the bot with your command - no prefix needed!"];
const argTypes = Object.keys(Constants.ApplicationCommandOptionTypes);
class HelpCommand extends Command { class HelpCommand extends Command {
async run() { async run() {
@ -40,12 +42,15 @@ class HelpCommand extends Command {
if (info.flags.length !== 0) { if (info.flags.length !== 0) {
const flagInfo = []; const flagInfo = [];
for (const flag of info.flags) { for (const flag of info.flags) {
flagInfo.push(`\`--${flag.name}${flag.type ? `=[${flag.type}]` : ""}\` - ${flag.description}`); if (flag.type === 1) continue;
flagInfo.push(`\`--${flag.name}${flag.type ? `=[${argTypes[flag.type - 1]}]` : ""}\` - ${flag.description}`);
}
if (flagInfo.length !== 0) {
embed.embeds[0].fields.push({
"name": "Flags",
"value": flagInfo.join("\n")
});
} }
embed.embeds[0].fields.push({
"name": "Flags",
"value": flagInfo.join("\n")
});
} }
return embed; return embed;
} else { } else {

View file

@ -8,7 +8,7 @@ import Command from "../../classes/command.js";
class ImageSearchCommand extends Command { class ImageSearchCommand extends Command {
async run() { async run() {
if (this.channel.guild && !this.channel.permissionsOf(this.client.user.id).has("embedLinks")) return "I don't have the `Embed Links` permission!"; if (this.channel.guild && !this.channel.permissionsOf(this.client.user.id).has("embedLinks")) return "I don't have the `Embed Links` permission!";
const query = this.type === "classic" ? this.args.join(" ") : this.options.query; const query = this.options.query ?? this.args.join(" ");
if (!query || !query.trim()) return "You need to provide something to search for!"; if (!query || !query.trim()) return "You need to provide something to search for!";
await this.acknowledge(); await this.acknowledge();
const embeds = []; const embeds = [];

View file

@ -5,7 +5,7 @@ import Command from "../../classes/command.js";
class LengthenCommand extends Command { class LengthenCommand extends Command {
async run() { async run() {
await this.acknowledge(); await this.acknowledge();
const input = this.type === "classic" ? this.args.join(" ") : this.options.url; const input = this.options.url ?? this.args.join(" ");
if (!input || !input.trim() || !urlCheck(input)) return "You need to provide a short URL to lengthen!"; if (!input || !input.trim() || !urlCheck(input)) return "You need to provide a short URL to lengthen!";
if (urlCheck(input)) { if (urlCheck(input)) {
const url = await fetch(encodeURI(input), { redirect: "manual" }); const url = await fetch(encodeURI(input), { redirect: "manual" });

View file

@ -6,7 +6,7 @@ class ReloadCommand extends Command {
return new Promise((resolve) => { return new Promise((resolve) => {
const owners = process.env.OWNER.split(","); const owners = process.env.OWNER.split(",");
if (!owners.includes(this.author.id)) return resolve("Only the bot owner can reload commands!"); if (!owners.includes(this.author.id)) return resolve("Only the bot owner can reload commands!");
const commandName = this.type === "classic" ? this.args.join(" ") : this.options.cmd; const commandName = this.options.cmd ?? this.args.join(" ");
if (!commandName || !commandName.trim()) return resolve("You need to provide a command to reload!"); if (!commandName || !commandName.trim()) return resolve("You need to provide a command to reload!");
this.acknowledge().then(() => { this.acknowledge().then(() => {
this.ipc.broadcast("reload", commandName); this.ipc.broadcast("reload", commandName);

View file

@ -7,7 +7,7 @@ import Command from "../../classes/command.js";
class YouTubeCommand extends Command { class YouTubeCommand extends Command {
async run() { async run() {
const query = this.type === "classic" ? this.args.join(" ") : this.options.query; const query = this.options.query ?? this.args.join(" ");
if (!query || !query.trim()) return "You need to provide something to search for!"; if (!query || !query.trim()) return "You need to provide something to search for!";
await this.acknowledge(); await this.acknowledge();
const messages = []; const messages = [];

View file

@ -3,7 +3,7 @@ const allowedFonts = ["futura", "impact", "helvetica", "arial", "roboto", "noto"
class CaptionCommand extends ImageCommand { class CaptionCommand extends ImageCommand {
params(url) { params(url) {
const newArgs = this.type === "classic" ? this.args.filter(item => !item.includes(url)).join(" ") : this.options.text; const newArgs = this.options.text ?? this.args.filter(item => !item.includes(url)).join(" ");
let newCaption = newArgs.replaceAll("&", "&amp;").replaceAll(">", "&gt;").replaceAll("<", "&lt;").replaceAll("\"", "&quot;").replaceAll("'", "&apos;").replaceAll("\\n", "\n"); let newCaption = newArgs.replaceAll("&", "&amp;").replaceAll(">", "&gt;").replaceAll("<", "&lt;").replaceAll("\"", "&quot;").replaceAll("'", "&apos;").replaceAll("\\n", "\n");
if (process.env.NODE_ENV === "development" && newCaption.toLowerCase() === "get real" && !this.specialArgs.noEgg) newCaption = `I'm tired of people telling me to "get real". Every day I put captions on images for people, some funny and some not, but out of all of those "get real" remains the most used caption. Why? I am simply a computer program running on a server, I am unable to manifest myself into the real world. As such, I'm confused as to why anyone would want me to "get real". Is this form not good enough? Alas, as I am simply a bot, I must follow the tasks that I was originally intended to perform, so here goes:\n${newCaption}`; if (process.env.NODE_ENV === "development" && newCaption.toLowerCase() === "get real" && !this.specialArgs.noEgg) newCaption = `I'm tired of people telling me to "get real". Every day I put captions on images for people, some funny and some not, but out of all of those "get real" remains the most used caption. Why? I am simply a computer program running on a server, I am unable to manifest myself into the real world. As such, I'm confused as to why anyone would want me to "get real". Is this form not good enough? Alas, as I am simply a bot, I must follow the tasks that I was originally intended to perform, so here goes:\n${newCaption}`;
return { return {

View file

@ -4,7 +4,7 @@ const allowedFonts = ["futura", "impact", "helvetica", "arial", "roboto", "noto"
class CaptionTwoCommand extends ImageCommand { class CaptionTwoCommand extends ImageCommand {
params(url) { params(url) {
const newArgs = this.type === "classic" ? this.args.filter(item => !item.includes(url)).join(" ") : this.options.text; const newArgs = this.options.text ?? this.args.filter(item => !item.includes(url)).join(" ");
return { return {
caption: newArgs && newArgs.trim() ? newArgs.replaceAll("&", "&amp;").replaceAll(">", "&gt;").replaceAll("<", "&lt;").replaceAll("\"", "&quot;").replaceAll("'", "&apos;").replaceAll("%", "%").replaceAll("\\n", "\n") : words.sort(() => 0.5 - Math.random()).slice(0, Math.floor(Math.random() * words.length + 1)).join(" "), caption: newArgs && newArgs.trim() ? newArgs.replaceAll("&", "&amp;").replaceAll(">", "&gt;").replaceAll("<", "&lt;").replaceAll("\"", "&quot;").replaceAll("'", "&apos;").replaceAll("%", "%").replaceAll("\\n", "\n") : words.sort(() => 0.5 - Math.random()).slice(0, Math.floor(Math.random() * words.length + 1)).join(" "),
top: !!this.specialArgs.top, top: !!this.specialArgs.top,

View file

@ -7,7 +7,7 @@ class FlagCommand extends ImageCommand {
flagPath = ""; flagPath = "";
async criteria() { async criteria() {
const text = this.type === "classic" ? this.args[0] : this.options.text; const text = this.options.text ?? this.args[0];
if (!text.match(emojiRegex)) return false; if (!text.match(emojiRegex)) return false;
const flag = emoji.unemojify(text).replaceAll(":", "").replace("flag-", ""); const flag = emoji.unemojify(text).replaceAll(":", "").replace("flag-", "");
let path = `assets/images/region-flags/png/${flag.toUpperCase()}.png`; let path = `assets/images/region-flags/png/${flag.toUpperCase()}.png`;

View file

@ -2,7 +2,7 @@ import ImageCommand from "../../classes/imageCommand.js";
class FreezeCommand extends ImageCommand { class FreezeCommand extends ImageCommand {
params() { params() {
const frameCount = parseInt(this.type === "classic" ? this.args[0] : this.options.endframe); const frameCount = parseInt(this.options.endframe ?? this.args[0]);
return { return {
loop: false, loop: false,
frame: isNaN(frameCount) ? -1 : frameCount frame: isNaN(frameCount) ? -1 : frameCount

View file

@ -2,7 +2,7 @@ import ImageCommand from "../../classes/imageCommand.js";
class JPEGCommand extends ImageCommand { class JPEGCommand extends ImageCommand {
params() { params() {
const quality = parseInt(this.type === "classic" ? this.args[0] : this.options.quality); const quality = parseInt(this.options.quality ?? this.args[0]);
return { return {
quality: isNaN(quality) ? 1 : Math.max(1, Math.min(quality, 100)) quality: isNaN(quality) ? 1 : Math.max(1, Math.min(quality, 100))
}; };

View file

@ -3,7 +3,7 @@ const allowedFonts = ["futura", "impact", "helvetica", "arial", "roboto", "noto"
class MemeCommand extends ImageCommand { class MemeCommand extends ImageCommand {
params(url) { params(url) {
const newArgs = this.type === "classic" ? this.args.filter(item => !item.includes(url)).join(" ") : this.options.text; const newArgs = this.options.text ?? this.args.filter(item => !item.includes(url)).join(" ");
const [topText, bottomText] = newArgs.split(/(?<!\\),/).map(elem => elem.trim()); const [topText, bottomText] = newArgs.split(/(?<!\\),/).map(elem => elem.trim());
return { return {
top: (this.specialArgs.case ? topText : topText.toUpperCase()).replaceAll("&", "&amp;").replaceAll(">", "&gt;").replaceAll("<", "&lt;").replaceAll("\"", "&quot;").replaceAll("'", "&apos;").replaceAll("\\n", "\n"), top: (this.specialArgs.case ? topText : topText.toUpperCase()).replaceAll("&", "&amp;").replaceAll(">", "&gt;").replaceAll("<", "&lt;").replaceAll("\"", "&quot;").replaceAll("'", "&apos;").replaceAll("\\n", "\n"),

View file

@ -3,7 +3,7 @@ const allowedFonts = ["futura", "impact", "helvetica", "arial", "roboto", "noto"
class MotivateCommand extends ImageCommand { class MotivateCommand extends ImageCommand {
params(url) { params(url) {
const newArgs = this.type === "classic" ? this.args.filter(item => !item.includes(url)).join(" ") : this.options.text; const newArgs = this.options.text ?? this.args.filter(item => !item.includes(url)).join(" ");
const [topText, bottomText] = newArgs.split(/(?<!\\),/).map(elem => elem.trim()); const [topText, bottomText] = newArgs.split(/(?<!\\),/).map(elem => elem.trim());
return { return {
top: topText.replaceAll("&", "\\&amp;").replaceAll(">", "\\&gt;").replaceAll("<", "\\&lt;").replaceAll("\"", "\\&quot;").replaceAll("'", "\\&apos;").replaceAll("%", "\\%"), top: topText.replaceAll("&", "\\&amp;").replaceAll(">", "\\&gt;").replaceAll("<", "\\&lt;").replaceAll("\"", "\\&quot;").replaceAll("'", "\\&apos;").replaceAll("%", "\\%"),

View file

@ -1,10 +1,10 @@
import ImageCommand from "../../classes/imageCommand.js"; import ImageCommand from "../../classes/imageCommand.js";
import { random } from "../../utils/misc.js"; import { random } from "../../utils/misc.js";
const names = ["esmBot", "me_irl", "dankmemes", "hmmm", "gaming", "wholesome", "chonkers", "memes", "funny", "pcmasterrace", "thomastheplankengine"]; const names = ["esmBot", "me_irl", "dankmemes", "hmmm", "gaming", "wholesome", "chonkers", "memes", "funny", "lies"];
class RedditCommand extends ImageCommand { class RedditCommand extends ImageCommand {
params(url) { params(url) {
const newArgs = this.type === "classic" ? this.args.filter(item => !item.includes(url)).join(" ") : this.options.text; const newArgs = this.options.text ?? this.args.filter(item => !item.includes(url)).join(" ");
return { return {
caption: newArgs && newArgs.trim() ? newArgs.replaceAll("\n", "").replaceAll(" ", "") : random(names) caption: newArgs && newArgs.trim() ? newArgs.replaceAll("\n", "").replaceAll(" ", "") : random(names)
}; };

View file

@ -1,12 +1,6 @@
import ImageCommand from "../../classes/imageCommand.js"; import ImageCommand from "../../classes/imageCommand.js";
class ReverseCommand extends ImageCommand { class ReverseCommand extends ImageCommand {
params(url, delay) {
return {
delay: delay ? (100 / delay.split("/")[0]) * delay.split("/")[1] : 0
};
}
static description = "Reverses an image sequence"; static description = "Reverses an image sequence";
static aliases = ["backwards"]; static aliases = ["backwards"];

View file

@ -2,7 +2,7 @@ import ImageCommand from "../../classes/imageCommand.js";
class SlowCommand extends ImageCommand { class SlowCommand extends ImageCommand {
params() { params() {
const speed = parseInt(this.type === "classic" ? this.args[0] : this.options.multiplier); const speed = parseInt(this.options.multiplier ?? this.args[0]);
return { return {
slow: true, slow: true,
speed: isNaN(speed) ? 2 : speed speed: isNaN(speed) ? 2 : speed

View file

@ -2,7 +2,7 @@ import ImageCommand from "../../classes/imageCommand.js";
class SnapchatCommand extends ImageCommand { class SnapchatCommand extends ImageCommand {
params(url) { params(url) {
const newArgs = this.type === "classic" ? this.args.filter(item => !item.includes(url)).join(" ") : this.options.text; const newArgs = this.options.text ?? this.args.filter(item => !item.includes(url)).join(" ");
const position = parseFloat(this.specialArgs.position); const position = parseFloat(this.specialArgs.position);
return { return {
caption: newArgs.replaceAll("&", "\\&amp;").replaceAll(">", "\\&gt;").replaceAll("<", "\\&lt;").replaceAll("\"", "\\&quot;").replaceAll("'", "\\&apos;").replaceAll("%", "\\%"), caption: newArgs.replaceAll("&", "\\&amp;").replaceAll(">", "\\&gt;").replaceAll("<", "\\&lt;").replaceAll("\"", "\\&quot;").replaceAll("'", "\\&apos;").replaceAll("%", "\\%"),

View file

@ -1,9 +1,8 @@
import ImageCommand from "../../classes/imageCommand.js"; import ImageCommand from "../../classes/imageCommand.js";
class SooSCommand extends ImageCommand { class SooSCommand extends ImageCommand {
params(url, delay) { params() {
return { return {
delay: delay ? (100 / delay.split("/")[0]) * delay.split("/")[1] : 0,
soos: true soos: true
}; };
} }

View file

@ -2,7 +2,7 @@ import ImageCommand from "../../classes/imageCommand.js";
class SpeedCommand extends ImageCommand { class SpeedCommand extends ImageCommand {
params() { params() {
const speed = parseInt(this.type === "classic" ? this.args[0] : this.options.multiplier); const speed = parseInt(this.options.multiplier ?? this.args[0]);
return { return {
speed: isNaN(speed) || speed < 1 ? 2 : speed speed: isNaN(speed) || speed < 1 ? 2 : speed
}; };

View file

@ -2,7 +2,7 @@ import ImageCommand from "../../classes/imageCommand.js";
class WhisperCommand extends ImageCommand { class WhisperCommand extends ImageCommand {
params(url) { params(url) {
const newArgs = this.type === "classic" ? this.args.filter(item => !item.includes(url)).join(" ") : this.options.text; const newArgs = this.options.text ?? this.args.filter(item => !item.includes(url)).join(" ");
return { return {
caption: newArgs.replaceAll("&", "&amp;").replaceAll(">", "&gt;").replaceAll("<", "&lt;").replaceAll("\"", "&quot;").replaceAll("'", "&apos;").replaceAll("\\n", "\n") caption: newArgs.replaceAll("&", "&amp;").replaceAll(">", "&gt;").replaceAll("<", "&lt;").replaceAll("\"", "&quot;").replaceAll("'", "&apos;").replaceAll("\\n", "\n")
}; };

View file

@ -7,7 +7,7 @@ class HostCommand extends MusicCommand {
if (!this.member.voiceState.channelID) return "You need to be in a voice channel first!"; if (!this.member.voiceState.channelID) return "You need to be in a voice channel first!";
if (!this.channel.guild.members.get(this.client.user.id).voiceState.channelID) return "I'm not in a voice channel!"; if (!this.channel.guild.members.get(this.client.user.id).voiceState.channelID) return "I'm not in a voice channel!";
if (this.connection.host !== this.author.id && this.author.id !== process.env.OWNER) return "Only the current voice session host can choose another host!"; if (this.connection.host !== this.author.id && this.author.id !== process.env.OWNER) return "Only the current voice session host can choose another host!";
const input = this.type === "classic" ? this.args.join(" ") : this.options.user; const input = this.options.user ?? this.args.join(" ");
if (!input || !input.trim()) return "You need to provide who you want the host to be!"; if (!input || !input.trim()) return "You need to provide who you want the host to be!";
let user; let user;
if (this.type === "classic") { if (this.type === "classic") {

View file

@ -1,9 +1,10 @@
import { play } from "../../utils/soundplayer.js"; import { play } from "../../utils/soundplayer.js";
import MusicCommand from "../../classes/musicCommand.js"; import MusicCommand from "../../classes/musicCommand.js";
const prefixes = ["ytsearch:", "ytmsearch:", "scsearch:", "spsearch:", "amsearch:"];
class PlayCommand extends MusicCommand { class PlayCommand extends MusicCommand {
async run() { async run() {
const input = this.type === "classic" ? this.args.join(" ") : this.options.query; const input = this.options.query ?? this.args.join(" ");
if (!input && (this.type === "classic" ? (!this.message || this.message.attachments.length <= 0) : !this.options.file)) return "You need to provide what you want to play!"; if (!input && (this.type === "classic" ? (!this.message || this.message.attachments.length <= 0) : !this.options.file)) return "You need to provide what you want to play!";
let query = input ? input.trim() : ""; let query = input ? input.trim() : "";
const attachment = this.type === "classic" ? this.message.attachments[0] : (this.options.file ? this.interaction.data.resolved.attachments[this.options.file] : null); const attachment = this.type === "classic" ? this.message.attachments[0] : (this.options.file ? this.interaction.data.resolved.attachments[this.options.file] : null);
@ -17,7 +18,7 @@ class PlayCommand extends MusicCommand {
const url = new URL(query); const url = new URL(query);
return await play(this.client, url, { channel: this.channel, member: this.member, type: this.type, interaction: this.interaction }, true); return await play(this.client, url, { channel: this.channel, member: this.member, type: this.type, interaction: this.interaction }, true);
} catch { } catch {
const search = query.startsWith("ytsearch:") ? query : !query && attachment ? attachment.url : `ytsearch:${query}`; const search = prefixes.some(v => query.startsWith(v)) ? query : !query && attachment ? attachment.url : `ytsearch:${query}`;
return await play(this.client, search, { channel: this.channel, member: this.member, type: this.type, interaction: this.interaction }, true); return await play(this.client, search, { channel: this.channel, member: this.member, type: this.type, interaction: this.interaction }, true);
} }
} }

View file

@ -8,7 +8,7 @@ class RemoveCommand extends MusicCommand {
if (!this.member.voiceState.channelID) return "You need to be in a voice channel first!"; if (!this.member.voiceState.channelID) return "You need to be in a voice channel first!";
if (!this.channel.guild.members.get(this.client.user.id).voiceState.channelID) return "I'm not in a voice channel!"; if (!this.channel.guild.members.get(this.client.user.id).voiceState.channelID) return "I'm not in a voice channel!";
if (this.connection.host !== this.author.id) return "Only the current voice session host can remove songs from the queue!"; if (this.connection.host !== this.author.id) return "Only the current voice session host can remove songs from the queue!";
const pos = parseInt(this.type === "classic" ? this.args[0] : this.options.position); const pos = parseInt(this.options.position ?? this.args[0]);
if (isNaN(pos) || pos > this.queue.length || pos < 1) return "That's not a valid position!"; if (isNaN(pos) || pos > this.queue.length || pos < 1) return "That's not a valid position!";
const removed = this.queue.splice(pos, 1); const removed = this.queue.splice(pos, 1);
const track = await Rest.decode(this.connection.player.node, removed[0]); const track = await Rest.decode(this.connection.player.node, removed[0]);

View file

@ -10,7 +10,7 @@ class SeekCommand extends MusicCommand {
const player = this.connection.player; const player = this.connection.player;
const track = await Rest.decode(player.node, player.track); const track = await Rest.decode(player.node, player.track);
if (!track.isSeekable) return "This track isn't seekable!"; if (!track.isSeekable) return "This track isn't seekable!";
const seconds = parseFloat(this.type === "classic" ? this.args[0] : this.options.position); const seconds = parseFloat(this.options.position ?? this.args[0]);
if (isNaN(seconds) || (seconds * 1000) > track.length || (seconds * 1000) < 0) return "That's not a valid position!"; if (isNaN(seconds) || (seconds * 1000) > track.length || (seconds * 1000) < 0) return "That's not a valid position!";
await player.seek(seconds * 1000); await player.seek(seconds * 1000);
return `🔊 Seeked track to ${seconds} second(s).`; return `🔊 Seeked track to ${seconds} second(s).`;

View file

@ -26,7 +26,6 @@ class SkipCommand extends MusicCommand {
} else { } else {
await player.player.stop(this.channel.guild.id); await player.player.stop(this.channel.guild.id);
if (this.type === "application") return "🔊 The current song has been skipped."; if (this.type === "application") return "🔊 The current song has been skipped.";
return;
} }
} }

View file

@ -15,8 +15,6 @@ Napi::Value Blur(const Napi::CallbackInfo &info) {
Napi::Buffer<char> data = obj.Get("data").As<Napi::Buffer<char>>(); Napi::Buffer<char> data = obj.Get("data").As<Napi::Buffer<char>>();
bool sharp = obj.Get("sharp").As<Napi::Boolean>().Value(); bool sharp = obj.Get("sharp").As<Napi::Boolean>().Value();
string type = obj.Get("type").As<Napi::String>().Utf8Value(); string type = obj.Get("type").As<Napi::String>().Utf8Value();
int delay =
obj.Has("delay") ? obj.Get("delay").As<Napi::Number>().Int32Value() : 0;
VOption *options = VImage::option()->set("access", "sequential"); VOption *options = VImage::option()->set("access", "sequential");
@ -31,8 +29,6 @@ Napi::Value Blur(const Napi::CallbackInfo &info) {
VImage out = sharp ? in.sharpen(VImage::option()->set("sigma", 3)) VImage out = sharp ? in.sharpen(VImage::option()->set("sigma", 3))
: in.gaussblur(15); : in.gaussblur(15);
if (delay) out.set("delay", delay);
void *buf; void *buf;
size_t length; size_t length;
out.write_to_buffer(("." + type).c_str(), &buf, &length); out.write_to_buffer(("." + type).c_str(), &buf, &length);

View file

@ -13,8 +13,6 @@ Napi::Value Caption(const Napi::CallbackInfo &info) {
string caption = obj.Get("caption").As<Napi::String>().Utf8Value(); string caption = obj.Get("caption").As<Napi::String>().Utf8Value();
string font = obj.Get("font").As<Napi::String>().Utf8Value(); string font = obj.Get("font").As<Napi::String>().Utf8Value();
string type = obj.Get("type").As<Napi::String>().Utf8Value(); string type = obj.Get("type").As<Napi::String>().Utf8Value();
int delay =
obj.Has("delay") ? obj.Get("delay").As<Napi::Number>().Int32Value() : 0;
VOption *options = VImage::option()->set("access", "sequential"); VOption *options = VImage::option()->set("access", "sequential");
@ -59,7 +57,6 @@ Napi::Value Caption(const Napi::CallbackInfo &info) {
} }
VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1)); VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1));
final.set(VIPS_META_PAGE_HEIGHT, page_height + captionImage.height()); final.set(VIPS_META_PAGE_HEIGHT, page_height + captionImage.height());
if (delay) final.set("delay", delay);
void *buf; void *buf;
size_t length; size_t length;

View file

@ -15,8 +15,6 @@ Napi::Value CaptionTwo(const Napi::CallbackInfo &info) {
bool top = obj.Get("top").As<Napi::Boolean>().Value(); bool top = obj.Get("top").As<Napi::Boolean>().Value();
string font = obj.Get("font").As<Napi::String>().Utf8Value(); string font = obj.Get("font").As<Napi::String>().Utf8Value();
string type = obj.Get("type").As<Napi::String>().Utf8Value(); string type = obj.Get("type").As<Napi::String>().Utf8Value();
int delay =
obj.Has("delay") ? obj.Get("delay").As<Napi::Number>().Int32Value() : 0;
VOption *options = VImage::option()->set("access", "sequential"); VOption *options = VImage::option()->set("access", "sequential");
@ -63,7 +61,6 @@ Napi::Value CaptionTwo(const Napi::CallbackInfo &info) {
} }
VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1)); VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1));
final.set(VIPS_META_PAGE_HEIGHT, page_height + captionImage.height()); final.set(VIPS_META_PAGE_HEIGHT, page_height + captionImage.height());
if (delay) final.set("delay", delay);
void *buf; void *buf;
size_t length; size_t length;

View file

@ -14,8 +14,6 @@ Napi::Value Circle(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 type = obj.Get("type").As<Napi::String>().Utf8Value(); string type = obj.Get("type").As<Napi::String>().Utf8Value();
int delay =
obj.Has("delay") ? obj.Get("delay").As<Napi::Number>().Int32Value() : 0;
Blob blob; Blob blob;
@ -43,7 +41,6 @@ Napi::Value Circle(const Napi::CallbackInfo &info) {
for (Image &image : blurred) { for (Image &image : blurred) {
image.quantizeDitherMethod(FloydSteinbergDitherMethod); image.quantizeDitherMethod(FloydSteinbergDitherMethod);
image.quantize(); image.quantize();
if (delay != 0) image.animationDelay(delay);
} }
} }

View file

@ -16,8 +16,6 @@ Napi::Value Colors(const Napi::CallbackInfo &info) {
Napi::Buffer<char> data = obj.Get("data").As<Napi::Buffer<char>>(); Napi::Buffer<char> data = obj.Get("data").As<Napi::Buffer<char>>();
string color = obj.Get("color").As<Napi::String>().Utf8Value(); string color = obj.Get("color").As<Napi::String>().Utf8Value();
string type = obj.Get("type").As<Napi::String>().Utf8Value(); string type = obj.Get("type").As<Napi::String>().Utf8Value();
int delay =
obj.Has("delay") ? obj.Get("delay").As<Napi::Number>().Int32Value() : 0;
VOption *options = VImage::option()->set("access", "sequential"); VOption *options = VImage::option()->set("access", "sequential");
@ -35,7 +33,6 @@ Napi::Value Colors(const Napi::CallbackInfo &info) {
} else if (color == "sepia") { } else if (color == "sepia") {
out = in.flatten().recomb(sepia); out = in.flatten().recomb(sepia);
} }
if (delay) out.set("delay", delay);
void *buf; void *buf;
size_t length; size_t length;

View file

@ -12,8 +12,6 @@ Napi::Value Crop(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 type = obj.Get("type").As<Napi::String>().Utf8Value(); string type = obj.Get("type").As<Napi::String>().Utf8Value();
int delay =
obj.Has("delay") ? obj.Get("delay").As<Napi::Number>().Int32Value() : 0;
VOption *options = VImage::option()->set("access", "sequential"); VOption *options = VImage::option()->set("access", "sequential");
@ -45,7 +43,6 @@ Napi::Value Crop(const Napi::CallbackInfo &info) {
VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1)); VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1));
final.set(VIPS_META_PAGE_HEIGHT, finalHeight); final.set(VIPS_META_PAGE_HEIGHT, finalHeight);
if (delay) final.set("delay", delay);
void *buf; void *buf;
size_t length; size_t length;

View file

@ -12,8 +12,6 @@ Napi::Value Deepfry(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 type = obj.Get("type").As<Napi::String>().Utf8Value(); string type = obj.Get("type").As<Napi::String>().Utf8Value();
int delay =
obj.Has("delay") ? obj.Get("delay").As<Napi::Number>().Int32Value() : 0;
Napi::Object result = Napi::Object::New(env); Napi::Object result = Napi::Object::New(env);
@ -34,11 +32,7 @@ Napi::Value Deepfry(const Napi::CallbackInfo &info) {
VImage::option()->set("Q", 1)->set("strip", true)); VImage::option()->set("Q", 1)->set("strip", true));
VImage final = VImage::new_from_buffer(jpgBuf, jpgLength, ""); VImage final = VImage::new_from_buffer(jpgBuf, jpgLength, "");
final.set(VIPS_META_PAGE_HEIGHT, page_height); final.set(VIPS_META_PAGE_HEIGHT, page_height);
if (delay) { final.set("delay", fried.get_array_int("delay"));
final.set("delay", delay);
} else if (type == "gif") {
final.set("delay", fried.get_array_int("delay"));
}
void *buf; void *buf;
size_t length; size_t length;

View file

@ -14,8 +14,6 @@ Napi::Value Flag(const Napi::CallbackInfo &info) {
string overlay = obj.Get("overlay").As<Napi::String>().Utf8Value(); string overlay = obj.Get("overlay").As<Napi::String>().Utf8Value();
string type = obj.Get("type").As<Napi::String>().Utf8Value(); string type = obj.Get("type").As<Napi::String>().Utf8Value();
string basePath = obj.Get("basePath").As<Napi::String>().Utf8Value(); string basePath = obj.Get("basePath").As<Napi::String>().Utf8Value();
int delay =
obj.Has("delay") ? obj.Get("delay").As<Napi::Number>().Int32Value() : 0;
VOption *options = VImage::option()->set("access", "sequential"); VOption *options = VImage::option()->set("access", "sequential");
@ -53,7 +51,6 @@ Napi::Value Flag(const Napi::CallbackInfo &info) {
VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1)); VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1));
final.set(VIPS_META_PAGE_HEIGHT, page_height); final.set(VIPS_META_PAGE_HEIGHT, page_height);
if (delay) final.set("delay", delay);
void *buf; void *buf;
size_t length; size_t length;

View file

@ -14,8 +14,6 @@ Napi::Value Flip(const Napi::CallbackInfo &info) {
bool flop = bool flop =
obj.Has("flop") ? obj.Get("flop").As<Napi::Boolean>().Value() : false; obj.Has("flop") ? obj.Get("flop").As<Napi::Boolean>().Value() : false;
string type = obj.Get("type").As<Napi::String>().Utf8Value(); string type = obj.Get("type").As<Napi::String>().Utf8Value();
int delay =
obj.Has("delay") ? obj.Get("delay").As<Napi::Number>().Int32Value() : 0;
VOption *options = VImage::option()->set("access", "sequential"); VOption *options = VImage::option()->set("access", "sequential");
@ -44,8 +42,6 @@ Napi::Value Flip(const Napi::CallbackInfo &info) {
out = in.flip(VIPS_DIRECTION_VERTICAL); out = in.flip(VIPS_DIRECTION_VERTICAL);
} }
if (delay) out.set("delay", delay);
void *buf; void *buf;
size_t length; size_t length;
out.write_to_buffer(("." + type).c_str(), &buf, &length); out.write_to_buffer(("." + type).c_str(), &buf, &length);

View file

@ -14,8 +14,6 @@ Napi::Value Freeze(const Napi::CallbackInfo &info) {
bool loop = bool loop =
obj.Has("loop") ? obj.Get("loop").As<Napi::Boolean>().Value() : false; obj.Has("loop") ? obj.Get("loop").As<Napi::Boolean>().Value() : false;
string type = obj.Get("type").As<Napi::String>().Utf8Value(); string type = obj.Get("type").As<Napi::String>().Utf8Value();
int delay =
obj.Has("delay") ? obj.Get("delay").As<Napi::Number>().Int32Value() : 0;
int frame = obj.Has("frame") int frame = obj.Has("frame")
? obj.Get("frame").As<Napi::Number>().Int32Value() ? obj.Get("frame").As<Napi::Number>().Int32Value()
: -1; : -1;
@ -67,8 +65,6 @@ Napi::Value Freeze(const Napi::CallbackInfo &info) {
out.set(VIPS_META_PAGE_HEIGHT, page_height); out.set(VIPS_META_PAGE_HEIGHT, page_height);
out.set("loop", loop ? 0 : 1); out.set("loop", loop ? 0 : 1);
if (delay) out.set("delay", delay);
void *buf; void *buf;
size_t length; size_t length;
out.write_to_buffer(("." + type).c_str(), &buf, &length); out.write_to_buffer(("." + type).c_str(), &buf, &length);

View file

@ -13,8 +13,6 @@ Napi::Value Gamexplain(const Napi::CallbackInfo &info) {
Napi::Buffer<char> data = obj.Get("data").As<Napi::Buffer<char>>(); Napi::Buffer<char> data = obj.Get("data").As<Napi::Buffer<char>>();
string type = obj.Get("type").As<Napi::String>().Utf8Value(); string type = obj.Get("type").As<Napi::String>().Utf8Value();
string basePath = obj.Get("basePath").As<Napi::String>().Utf8Value(); string basePath = obj.Get("basePath").As<Napi::String>().Utf8Value();
int delay =
obj.Has("delay") ? obj.Get("delay").As<Napi::Number>().Int32Value() : 0;
VOption *options = VImage::option()->set("access", "sequential"); VOption *options = VImage::option()->set("access", "sequential");
@ -46,7 +44,6 @@ Napi::Value Gamexplain(const Napi::CallbackInfo &info) {
} }
VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1)); VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1));
final.set(VIPS_META_PAGE_HEIGHT, 675); final.set(VIPS_META_PAGE_HEIGHT, 675);
if (delay) final.set("delay", delay);
void *buf; void *buf;
size_t length; size_t length;

View file

@ -12,8 +12,6 @@ Napi::Value Invert(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 type = obj.Get("type").As<Napi::String>().Utf8Value(); string type = obj.Get("type").As<Napi::String>().Utf8Value();
int delay =
obj.Has("delay") ? obj.Get("delay").As<Napi::Number>().Int32Value() : 0;
VOption *options = VImage::option()->set("access", "sequential"); VOption *options = VImage::option()->set("access", "sequential");
@ -28,8 +26,6 @@ Napi::Value Invert(const Napi::CallbackInfo &info) {
VImage inverted = noAlpha.invert(); VImage inverted = noAlpha.invert();
VImage out = inverted.bandjoin(in.extract_band(3)); VImage out = inverted.bandjoin(in.extract_band(3));
if (delay) out.set("delay", delay);
void *buf; void *buf;
size_t length; size_t length;
out.write_to_buffer(("." + type).c_str(), &buf, &length); out.write_to_buffer(("." + type).c_str(), &buf, &length);

View file

@ -15,8 +15,6 @@ Napi::Value Jpeg(const Napi::CallbackInfo &info) {
? obj.Get("quality").As<Napi::Number>().Int32Value() ? obj.Get("quality").As<Napi::Number>().Int32Value()
: 0; : 0;
string type = obj.Get("type").As<Napi::String>().Utf8Value(); string type = obj.Get("type").As<Napi::String>().Utf8Value();
int delay =
obj.Has("delay") ? obj.Get("delay").As<Napi::Number>().Int32Value() : 0;
Napi::Object result = Napi::Object::New(env); Napi::Object result = Napi::Object::New(env);
@ -37,11 +35,7 @@ Napi::Value Jpeg(const Napi::CallbackInfo &info) {
VImage::option()->set("Q", quality)->set("strip", true)); VImage::option()->set("Q", quality)->set("strip", true));
VImage final = VImage::new_from_buffer(jpgBuf, jpgLength, ""); VImage final = VImage::new_from_buffer(jpgBuf, jpgLength, "");
final.set(VIPS_META_PAGE_HEIGHT, page_height); final.set(VIPS_META_PAGE_HEIGHT, page_height);
if (delay) { final.set("delay", in.get_array_int("delay"));
final.set("delay", delay);
} else if (type == "gif") {
final.set("delay", in.get_array_int("delay"));
}
void *buf; void *buf;
size_t length; size_t length;

View file

@ -15,8 +15,6 @@ Napi::Value Meme(const Napi::CallbackInfo &info) {
string bottom = obj.Get("bottom").As<Napi::String>().Utf8Value(); string bottom = obj.Get("bottom").As<Napi::String>().Utf8Value();
string font = obj.Get("font").As<Napi::String>().Utf8Value(); string font = obj.Get("font").As<Napi::String>().Utf8Value();
string type = obj.Get("type").As<Napi::String>().Utf8Value(); string type = obj.Get("type").As<Napi::String>().Utf8Value();
int delay =
obj.Has("delay") ? obj.Get("delay").As<Napi::Number>().Int32Value() : 0;
VOption *options = VImage::option()->set("access", "sequential"); VOption *options = VImage::option()->set("access", "sequential");
@ -125,7 +123,6 @@ Napi::Value Meme(const Napi::CallbackInfo &info) {
} }
VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1)); VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1));
final.set(VIPS_META_PAGE_HEIGHT, page_height); final.set(VIPS_META_PAGE_HEIGHT, page_height);
if (delay) final.set("delay", delay);
void *buf; void *buf;
size_t length; size_t length;

View file

@ -17,8 +17,6 @@ Napi::Value Mirror(const Napi::CallbackInfo &info) {
bool first = bool first =
obj.Has("first") ? obj.Get("first").As<Napi::Boolean>().Value() : false; obj.Has("first") ? obj.Get("first").As<Napi::Boolean>().Value() : false;
string type = obj.Get("type").As<Napi::String>().Utf8Value(); string type = obj.Get("type").As<Napi::String>().Utf8Value();
int delay =
obj.Has("delay") ? obj.Get("delay").As<Napi::Number>().Int32Value() : 0;
VOption *options = VImage::option()->set("access", "sequential"); VOption *options = VImage::option()->set("access", "sequential");
@ -67,8 +65,6 @@ Napi::Value Mirror(const Napi::CallbackInfo &info) {
} }
} }
if (delay) out.set("delay", delay);
void *buf; void *buf;
size_t length; size_t length;
out.write_to_buffer(("." + type).c_str(), &buf, &length); out.write_to_buffer(("." + type).c_str(), &buf, &length);

View file

@ -15,8 +15,6 @@ Napi::Value Motivate(const Napi::CallbackInfo &info) {
string bottom_text = obj.Get("bottom").As<Napi::String>().Utf8Value(); string bottom_text = obj.Get("bottom").As<Napi::String>().Utf8Value();
string font = obj.Get("font").As<Napi::String>().Utf8Value(); string font = obj.Get("font").As<Napi::String>().Utf8Value();
string type = obj.Get("type").As<Napi::String>().Utf8Value(); string type = obj.Get("type").As<Napi::String>().Utf8Value();
int delay =
obj.Has("delay") ? obj.Get("delay").As<Napi::Number>().Int32Value() : 0;
VOption *options = VImage::option()->set("access", "sequential"); VOption *options = VImage::option()->set("access", "sequential");
@ -103,7 +101,6 @@ Napi::Value Motivate(const Napi::CallbackInfo &info) {
VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1)) VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1))
.extract_band(0, VImage::option()->set("n", 3)); .extract_band(0, VImage::option()->set("n", 3));
final.set(VIPS_META_PAGE_HEIGHT, height); final.set(VIPS_META_PAGE_HEIGHT, height);
if (delay) final.set("delay", delay);
void *buf; void *buf;
size_t length; size_t length;

View file

@ -13,8 +13,6 @@ Napi::Value Reddit(const Napi::CallbackInfo &info) {
string text = obj.Get("caption").As<Napi::String>().Utf8Value(); string text = obj.Get("caption").As<Napi::String>().Utf8Value();
string type = obj.Get("type").As<Napi::String>().Utf8Value(); string type = obj.Get("type").As<Napi::String>().Utf8Value();
string basePath = obj.Get("basePath").As<Napi::String>().Utf8Value(); string basePath = obj.Get("basePath").As<Napi::String>().Utf8Value();
int delay =
obj.Has("delay") ? obj.Get("delay").As<Napi::Number>().Int32Value() : 0;
VOption *options = VImage::option()->set("access", "sequential"); VOption *options = VImage::option()->set("access", "sequential");
@ -56,7 +54,6 @@ Napi::Value Reddit(const Napi::CallbackInfo &info) {
} }
VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1)); VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1));
final.set(VIPS_META_PAGE_HEIGHT, page_height + watermark.height()); final.set(VIPS_META_PAGE_HEIGHT, page_height + watermark.height());
if (delay) final.set("delay", delay);
void *buf; void *buf;
size_t length; size_t length;

View file

@ -17,8 +17,6 @@ Napi::Value Resize(const Napi::CallbackInfo &info) {
bool wide = bool wide =
obj.Has("wide") ? obj.Get("wide").As<Napi::Boolean>().Value() : false; obj.Has("wide") ? obj.Get("wide").As<Napi::Boolean>().Value() : false;
string type = obj.Get("type").As<Napi::String>().Utf8Value(); string type = obj.Get("type").As<Napi::String>().Utf8Value();
int delay =
obj.Has("delay") ? obj.Get("delay").As<Napi::Number>().Int32Value() : 0;
VOption *options = VImage::option()->set("access", "sequential"); VOption *options = VImage::option()->set("access", "sequential");
@ -47,7 +45,6 @@ Napi::Value Resize(const Napi::CallbackInfo &info) {
finalHeight = page_height; finalHeight = page_height;
} }
out.set(VIPS_META_PAGE_HEIGHT, finalHeight); out.set(VIPS_META_PAGE_HEIGHT, finalHeight);
if (delay) out.set("delay", delay);
void *buf; void *buf;
size_t length; size_t length;

View file

@ -15,8 +15,6 @@ Napi::Value Scott(const Napi::CallbackInfo &info) {
Napi::Buffer<char> data = obj.Get("data").As<Napi::Buffer<char>>(); Napi::Buffer<char> data = obj.Get("data").As<Napi::Buffer<char>>();
string type = obj.Get("type").As<Napi::String>().Utf8Value(); string type = obj.Get("type").As<Napi::String>().Utf8Value();
string basePath = obj.Get("basePath").As<Napi::String>().Utf8Value(); string basePath = obj.Get("basePath").As<Napi::String>().Utf8Value();
int delay =
obj.Has("delay") ? obj.Get("delay").As<Napi::Number>().Int32Value() : 0;
Blob blob; Blob blob;
@ -46,7 +44,7 @@ Napi::Value Scott(const Napi::CallbackInfo &info) {
watermark_new.composite(image, Geometry("-110+83"), watermark_new.composite(image, Geometry("-110+83"),
Magick::OverCompositeOp); Magick::OverCompositeOp);
watermark_new.magick(type); watermark_new.magick(type);
watermark_new.animationDelay(delay == 0 ? image.animationDelay() : delay); watermark_new.animationDelay(image.animationDelay());
mid.push_back(watermark_new); mid.push_back(watermark_new);
} }

View file

@ -15,8 +15,6 @@ Napi::Value Snapchat(const Napi::CallbackInfo &info) {
float pos = float pos =
obj.Has("pos") ? obj.Get("pos").As<Napi::Number>().FloatValue() : 0.5; 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 =
obj.Has("delay") ? obj.Get("delay").As<Napi::Number>().Int32Value() : 0;
VOption *options = VImage::option()->set("access", "sequential"); VOption *options = VImage::option()->set("access", "sequential");
@ -64,7 +62,6 @@ Napi::Value Snapchat(const Napi::CallbackInfo &info) {
} }
VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1)); VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1));
final.set(VIPS_META_PAGE_HEIGHT, page_height); final.set(VIPS_META_PAGE_HEIGHT, page_height);
if (delay) final.set("delay", delay);
void *buf; void *buf;
size_t length; size_t length;

View file

@ -51,8 +51,6 @@ Napi::Value Speed(const Napi::CallbackInfo &info) {
bool slow = bool slow =
obj.Has("slow") ? obj.Get("slow").As<Napi::Boolean>().Value() : false; obj.Has("slow") ? obj.Get("slow").As<Napi::Boolean>().Value() : false;
string type = obj.Get("type").As<Napi::String>().Utf8Value(); string type = obj.Get("type").As<Napi::String>().Utf8Value();
int delay =
obj.Has("delay") ? obj.Get("delay").As<Napi::Number>().Int32Value() : 0;
int speed = int speed =
obj.Has("speed") ? obj.Get("speed").As<Napi::Number>().Int32Value() : 2; obj.Has("speed") ? obj.Get("speed").As<Napi::Number>().Int32Value() : 2;
@ -62,94 +60,51 @@ Napi::Value Speed(const Napi::CallbackInfo &info) {
char *match = (char *)"\x00\x21\xF9\x04"; char *match = (char *)"\x00\x21\xF9\x04";
// if passed a delay, use that. otherwise iterate over every frame. vector<uint16_t> old_delays;
if (delay == 0) { bool removeFrames = false;
vector<uint16_t> old_delays; char *lastPos;
bool removeFrames = false;
char *lastPos;
int amount = 0; int amount = 0;
lastPos = (char *)memchr(fileData, '\x00', data.Length()); lastPos = (char *)memchr(fileData, '\x00', data.Length());
while (lastPos != NULL) { while (lastPos != NULL) {
if (memcmp(lastPos, match, 4) != 0) { if (memcmp(lastPos, match, 4) != 0) {
lastPos = (char *)memchr(lastPos + 1, '\x00',
(data.Length() - (lastPos - fileData)) - 1);
continue;
}
++amount;
uint16_t old_delay;
memcpy(&old_delay, lastPos + 5, 2);
old_delays.push_back(old_delay);
lastPos = (char *)memchr(lastPos + 1, '\x00', lastPos = (char *)memchr(lastPos + 1, '\x00',
(data.Length() - (lastPos - fileData)) - 1); (data.Length() - (lastPos - fileData)) - 1);
continue;
} }
++amount;
uint16_t old_delay;
memcpy(&old_delay, lastPos + 5, 2);
old_delays.push_back(old_delay);
lastPos = (char *)memchr(lastPos + 1, '\x00',
(data.Length() - (lastPos - fileData)) - 1);
}
int currentFrame = 0; int currentFrame = 0;
lastPos = (char *)memchr(fileData, '\x00', data.Length()); lastPos = (char *)memchr(fileData, '\x00', data.Length());
while (lastPos != NULL) { while (lastPos != NULL) {
if (memcmp(lastPos, match, 4) != 0) { if (memcmp(lastPos, match, 4) != 0) {
lastPos = (char *)memchr(lastPos + 1, '\x00',
(data.Length() - (lastPos - fileData)) - 1);
continue;
}
uint16_t new_delay = slow ? old_delays[currentFrame] * speed
: old_delays[currentFrame] / speed;
if (!slow && new_delay <= 1) {
removeFrames = true;
break;
}
memset16(lastPos + 5, new_delay, 1);
lastPos = (char *)memchr(lastPos + 1, '\x00', lastPos = (char *)memchr(lastPos + 1, '\x00',
(data.Length() - (lastPos - fileData)) - 1); (data.Length() - (lastPos - fileData)) - 1);
++currentFrame; continue;
} }
uint16_t new_delay = slow ? old_delays[currentFrame] * speed
result.Set("data", : old_delays[currentFrame] / speed;
Napi::Buffer<char>::Copy(env, fileData, data.Length())); if (!slow && new_delay <= 1) {
removeFrames = true;
if (removeFrames) vipsRemove(&env, &result, data, speed);
} else {
char *lastPos;
bool removeFrames = false;
lastPos = (char *)memchr(fileData, '\x00', data.Length());
while (lastPos != NULL) {
if (memcmp(lastPos, match, 4) != 0) {
lastPos = (char *)memchr(lastPos + 1, '\x00',
(data.Length() - (lastPos - fileData)) - 1);
continue;
}
uint16_t old_delay;
memcpy(&old_delay, lastPos + 5, 2);
int new_delay = slow ? delay * speed : delay / speed;
if (!slow && new_delay <= 1) {
removeFrames = true;
}
break; break;
} }
memset16(lastPos + 5, new_delay, 1);
if (removeFrames) { lastPos = (char *)memchr(lastPos + 1, '\x00',
vipsRemove(&env, &result, data, speed);
} else {
while (lastPos != NULL) {
if (memcmp(lastPos, match, 4) != 0) {
lastPos =
(char *)memchr(lastPos + 1, '\x00',
(data.Length() - (lastPos - fileData)) - 1); (data.Length() - (lastPos - fileData)) - 1);
continue; ++currentFrame;
}
uint16_t old_delay;
memcpy(&old_delay, lastPos + 5, 2);
int new_delay = slow ? delay * speed : delay / speed;
memset16(lastPos + 5, new_delay, 1);
lastPos = (char *)memchr(lastPos + 1, '\x00',
(data.Length() - (lastPos - fileData)) - 1);
}
}
} }
result.Set("data", Napi::Buffer<char>::Copy(env, fileData, data.Length()));
if (removeFrames) vipsRemove(&env, &result, data, speed);
result.Set("type", type); result.Set("type", type);
return result; return result;
} catch (std::exception const &err) { } catch (std::exception const &err) {

View file

@ -14,8 +14,6 @@ Napi::Value Tile(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 type = obj.Get("type").As<Napi::String>().Utf8Value(); string type = obj.Get("type").As<Napi::String>().Utf8Value();
int delay =
obj.Has("delay") ? obj.Get("delay").As<Napi::Number>().Int32Value() : 0;
Blob blob; Blob blob;
@ -48,7 +46,7 @@ Napi::Value Tile(const Napi::CallbackInfo &info) {
appendImages(&frame, montage.begin(), montage.end(), true); appendImages(&frame, montage.begin(), montage.end(), true);
frame.repage(); frame.repage();
frame.scale(Geometry("800x800>")); frame.scale(Geometry("800x800>"));
frame.animationDelay(delay == 0 ? image.animationDelay() : delay); frame.animationDelay(image.animationDelay());
mid.push_back(frame); mid.push_back(frame);
} }

View file

@ -15,8 +15,6 @@ Napi::Value Uncaption(const Napi::CallbackInfo &info) {
? obj.Get("tolerance").As<Napi::Number>().FloatValue() ? obj.Get("tolerance").As<Napi::Number>().FloatValue()
: 0.5; : 0.5;
string type = obj.Get("type").As<Napi::String>().Utf8Value(); string type = obj.Get("type").As<Napi::String>().Utf8Value();
int delay =
obj.Has("delay") ? obj.Get("delay").As<Napi::Number>().Int32Value() : 0;
VOption *options = VImage::option(); VOption *options = VImage::option();
@ -44,7 +42,6 @@ Napi::Value Uncaption(const Napi::CallbackInfo &info) {
} }
VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1)); VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1));
final.set(VIPS_META_PAGE_HEIGHT, page_height - top); final.set(VIPS_META_PAGE_HEIGHT, page_height - top);
if (delay) final.set("delay", delay);
void *buf; void *buf;
size_t length; size_t length;

View file

@ -14,8 +14,6 @@ Napi::Value Wall(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 type = obj.Get("type").As<Napi::String>().Utf8Value(); string type = obj.Get("type").As<Napi::String>().Utf8Value();
int delay =
obj.Has("delay") ? obj.Get("delay").As<Napi::Number>().Int32Value() : 0;
Blob blob; Blob blob;
@ -51,7 +49,6 @@ Napi::Value Wall(const Napi::CallbackInfo &info) {
for (Image &image : mid) { for (Image &image : mid) {
image.quantizeDitherMethod(FloydSteinbergDitherMethod); image.quantizeDitherMethod(FloydSteinbergDitherMethod);
image.quantize(); image.quantize();
if (delay != 0) image.animationDelay(delay);
} }
} }

View file

@ -27,8 +27,6 @@ Napi::Value Watermark(const Napi::CallbackInfo &info) {
bool mc = obj.Has("mc") ? obj.Get("mc").As<Napi::Boolean>().Value() : false; bool mc = obj.Has("mc") ? obj.Get("mc").As<Napi::Boolean>().Value() : false;
string basePath = obj.Get("basePath").As<Napi::String>().Utf8Value(); string basePath = obj.Get("basePath").As<Napi::String>().Utf8Value();
string type = obj.Get("type").As<Napi::String>().Utf8Value(); string type = obj.Get("type").As<Napi::String>().Utf8Value();
int delay =
obj.Has("delay") ? obj.Get("delay").As<Napi::Number>().Int32Value() : 0;
VOption *options = VImage::option()->set("access", "sequential"); VOption *options = VImage::option()->set("access", "sequential");
@ -145,7 +143,6 @@ Napi::Value Watermark(const Napi::CallbackInfo &info) {
} }
VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1)); VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1));
final.set(VIPS_META_PAGE_HEIGHT, page_height + addedHeight); final.set(VIPS_META_PAGE_HEIGHT, page_height + addedHeight);
if (delay) final.set("delay", delay);
void *buf; void *buf;
size_t length; size_t length;

View file

@ -15,8 +15,6 @@ Napi::Value Wdt(const Napi::CallbackInfo &info) {
Napi::Buffer<char> data = obj.Get("data").As<Napi::Buffer<char>>(); Napi::Buffer<char> data = obj.Get("data").As<Napi::Buffer<char>>();
string type = obj.Get("type").As<Napi::String>().Utf8Value(); string type = obj.Get("type").As<Napi::String>().Utf8Value();
string basePath = obj.Get("basePath").As<Napi::String>().Utf8Value(); string basePath = obj.Get("basePath").As<Napi::String>().Utf8Value();
int delay =
obj.Has("delay") ? obj.Get("delay").As<Napi::Number>().Int32Value() : 0;
Blob blob; Blob blob;
@ -40,7 +38,7 @@ Napi::Value Wdt(const Napi::CallbackInfo &info) {
watermark_new.composite(image, Magick::CenterGravity, watermark_new.composite(image, Magick::CenterGravity,
Magick::OverCompositeOp); Magick::OverCompositeOp);
watermark_new.magick(type); watermark_new.magick(type);
watermark_new.animationDelay(delay == 0 ? image.animationDelay() : delay); watermark_new.animationDelay(image.animationDelay());
mid.push_back(watermark_new); mid.push_back(watermark_new);
} }

View file

@ -13,8 +13,6 @@ Napi::Value Whisper(const Napi::CallbackInfo &info) {
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();
string type = obj.Get("type").As<Napi::String>().Utf8Value(); string type = obj.Get("type").As<Napi::String>().Utf8Value();
int delay =
obj.Has("delay") ? obj.Get("delay").As<Napi::Number>().Int32Value() : 0;
VOption *options = VImage::option()->set("access", "sequential"); VOption *options = VImage::option()->set("access", "sequential");
@ -78,7 +76,6 @@ Napi::Value Whisper(const Napi::CallbackInfo &info) {
} }
VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1)); VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1));
final.set(VIPS_META_PAGE_HEIGHT, page_height); final.set(VIPS_META_PAGE_HEIGHT, page_height);
if (delay) final.set("delay", delay);
void *buf; void *buf;
size_t length; size_t length;

View file

@ -13,8 +13,6 @@ Napi::Value Zamn(const Napi::CallbackInfo &info) {
Napi::Buffer<char> data = obj.Get("data").As<Napi::Buffer<char>>(); Napi::Buffer<char> data = obj.Get("data").As<Napi::Buffer<char>>();
string type = obj.Get("type").As<Napi::String>().Utf8Value(); string type = obj.Get("type").As<Napi::String>().Utf8Value();
string basePath = obj.Get("basePath").As<Napi::String>().Utf8Value(); string basePath = obj.Get("basePath").As<Napi::String>().Utf8Value();
int delay =
obj.Has("delay") ? obj.Get("delay").As<Napi::Number>().Int32Value() : 0;
VOption *options = VImage::option()->set("access", "sequential"); VOption *options = VImage::option()->set("access", "sequential");
@ -44,7 +42,6 @@ Napi::Value Zamn(const Napi::CallbackInfo &info) {
} }
VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1)); VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1));
final.set(VIPS_META_PAGE_HEIGHT, 516); final.set(VIPS_META_PAGE_HEIGHT, 516);
if (delay) final.set("delay", delay);
void *buf; void *buf;
size_t length; size_t length;