Skip to content

Commit

Permalink
readd magnification and more ephemeral translations
Browse files Browse the repository at this point in the history
  • Loading branch information
3vorp committed Oct 7, 2023
1 parent a9484d0 commit aa412be
Show file tree
Hide file tree
Showing 10 changed files with 84 additions and 29 deletions.
5 changes: 3 additions & 2 deletions lang/en-US/commands.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@
"title": "You cannot run slash commands in a submission channel!",
"description": "Please use the appropriate bot command channel instead."
},
"images": {
"too_big": "Output exceeds the maximum of 512px²!"
"tile": {
"too_big": "This image is too big to be tiled!",
"suggestion": "Try scaling your image down or using another program."
},
"stats": {
"footer": "Made with love",
Expand Down
2 changes: 1 addition & 1 deletion src/commands/images/animate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export const command: SlashCommand = {
const mcmeta: MCMETA = mcmetaList[style];

// magnify beforehand since you can't magnify a gif currently
const { magnified } = await magnify(image, true);
const { magnified } = await magnify(image, { isAnimation: true });
const file = await animateToAttachment(await loadImage(magnified), mcmeta, `${style}.gif`);
await interaction
.editReply({ files: [file] })
Expand Down
23 changes: 20 additions & 3 deletions src/commands/images/magnify.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { SlashCommand } from "@interfaces";
import { SlashCommandBuilder } from "discord.js";
import { ChatInputCommandInteraction, EmbedBuilder } from "@client";
import { ActionRowBuilder, ButtonBuilder, SlashCommandBuilder } from "discord.js";
import { ChatInputCommandInteraction, Message } from "@client";
import { magnifyToAttachment } from "@images/magnify";
import getImage from "@helpers/getImage";
import { tile, palette } from "@helpers/buttons";

export const command: SlashCommand = {
data: new SlashCommandBuilder()
Expand All @@ -25,5 +27,20 @@ export const command: SlashCommand = {
.setDescription("The scale factor the image should be enlarged by.")
.setRequired(false);
}),
async execute(interaction: ChatInputCommandInteraction) {},
async execute(interaction: ChatInputCommandInteraction) {
await interaction.deferReply();
const image =
interaction.options.getAttachment("image", false)?.url ?? (await getImage(interaction));

const file = await magnifyToAttachment(image, {
factor: interaction.options.getNumber("factor", false),
});

await interaction
.editReply({
files: [file],
components: [new ActionRowBuilder<ButtonBuilder>().addComponents(palette)],
})
.then((message: Message) => message.deleteButton());
},
};
19 changes: 16 additions & 3 deletions src/commands/images/tile.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { SlashCommand } from "@interfaces";
import { SlashCommandBuilder } from "discord.js";
import { ChatInputCommandInteraction, Message } from "@client";
import { ChatInputCommandInteraction, EmbedBuilder, Message } from "@client";
import { tileToAttachment, TileShape, TileRandom } from "@images/tile";
import getImage from "@helpers/getImage";
import { imageButtons } from "@helpers/buttons";
import { colors } from "@helpers/colors";

export const command: SlashCommand = {
data: new SlashCommandBuilder()
Expand Down Expand Up @@ -36,18 +37,30 @@ export const command: SlashCommand = {
o.setName("image").setDescription("The image to tile").setRequired(false),
),
async execute(interaction: ChatInputCommandInteraction) {
await interaction.deferReply();
const random = interaction.options.getString("random") as TileRandom;
const shape = interaction.options.getString("type") as TileShape;

const image =
interaction.options.getAttachment("image", false)?.url ?? (await getImage(interaction));

const file = await tileToAttachment(image, { random, shape });

if (!file) {
return await interaction.reply({
embeds: [
new EmbedBuilder()
.setTitle(interaction.strings().command.tile.too_big)
.setDescription(interaction.strings().command.tile.suggestion)
.setColor(colors.red),
],
ephemeral: true
});
}
await interaction
.editReply({
.reply({
files: [file],
components: [imageButtons],
fetchReply: true,
})
.then((message: Message) => message.deleteButton());
},
Expand Down
8 changes: 1 addition & 7 deletions src/components/buttons/image/magnify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,7 @@ export default {

const message: Message = interaction.message as Message;
const url = await getImage(message);
const attachment = await magnifyToAttachment(url, url.split("/").at(-1));

if (attachment == null)
return interaction.reply({
content: interaction.strings().command.images.too_big,
ephemeral: true,
});
const attachment = await magnifyToAttachment(url);

return interaction
.reply({
Expand Down
2 changes: 1 addition & 1 deletion src/components/buttons/image/palette.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export default {

const message: Message = interaction.message as Message;
const url = await getImage(message);
const [attachment, embed] = await paletteToAttachment(url, url.split("/").at(-1));
const [attachment, embed] = await paletteToAttachment(url);

return interaction
.reply({
Expand Down
16 changes: 11 additions & 5 deletions src/components/buttons/image/tile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { magnify, palette } from "@helpers/buttons";
import { ActionRowBuilder } from "discord.js";
import { ButtonBuilder } from "discord.js";
import getImage from "@helpers/getImage";
import { colors } from "@helpers/colors";

export default {
id: "tile",
Expand All @@ -14,12 +15,17 @@ export default {

const message: Message = interaction.message as Message;
const url = await getImage(message);
const attachment = await tileToAttachment(url, {}, url.split("/").at(-1));
const attachment = await tileToAttachment(url);

if (attachment == null)
return interaction.reply({
content: interaction.strings().command.images.too_big,
ephemeral: true,
if (!attachment)
return await interaction.reply({
embeds: [
new EmbedBuilder()
.setTitle(interaction.strings().command.tile.too_big)
.setDescription(interaction.strings().command.tile.suggestion)
.setColor(colors.red),
],
ephemeral: true
});

return interaction
Expand Down
23 changes: 18 additions & 5 deletions src/helpers/images/magnify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,25 @@ export type ImageSource =
| Image
| import("stream").Readable;

export interface MagnifyOptions {
isAnimation?: boolean;
factor?: number;
}

/**
* The actual magnification function
* @author Juknum, Evorp
* @param origin url, image, or buffer to magnify
* @param isAnimation whether to magnify the image as a tilesheet
* @param options
* @returns buffer for magnified image
*/
export async function magnify(origin: ImageSource, isAnimation = false) {
export async function magnify(origin: ImageSource, options: MagnifyOptions = {}) {
const input = await loadImage(origin).catch((err) => Promise.reject(err));

// ignore height if tilesheet, otherwise it's not scaled as much
const surface = isAnimation ? input.width * 16 : input.width * input.height;
const surface = options.isAnimation ? input.width * 16 : input.width * input.height;

// no custom factor provided
let factor = 64;
if (surface <= 256) factor = 32;
if (surface > 256) factor = 16;
Expand All @@ -32,6 +38,9 @@ export async function magnify(origin: ImageSource, isAnimation = false) {
if (surface > 65536) factor = 2;
if (surface > 262144) factor = 1;

// custom factor provided
if (options.factor) factor = options.factor;

const width = input.width * factor;
const height = input.height * factor;
const output = createCanvas(width, height);
Expand All @@ -49,7 +58,11 @@ export async function magnify(origin: ImageSource, isAnimation = false) {
* @param name name, defaults to "magnified.png"
* @returns magnified file
*/
export async function magnifyToAttachment(origin: ImageSource, name = "magnified.png") {
const { magnified } = await magnify(origin);
export async function magnifyToAttachment(
origin: ImageSource,
options?: MagnifyOptions,
name = "magnified.png",
) {
const { magnified } = await magnify(origin, options);
return new AttachmentBuilder(magnified, { name });
}
6 changes: 6 additions & 0 deletions src/helpers/images/tile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ interface TileOptions {
random?: TileRandom;
}

/**
* @author Juknum
* @param origin what to tile
* @param options what shape and randomness
* @returns tiled image as buffer
*/
export async function tile(origin: ImageSource, options: TileOptions = {}): Promise<Buffer> {
const input = await loadImage(origin).catch((err) => Promise.reject(err));

Expand Down
9 changes: 7 additions & 2 deletions src/helpers/prefixCommandHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { magnifyToAttachment } from "./images/magnify";
import getImage from "./getImage";
import { tileToAttachment } from "./images/tile";
import { paletteToAttachment } from "./images/palette";
import { ActionRowBuilder, ButtonBuilder } from "discord.js";
import { imageButtons, palette } from "./buttons";

export default async function prefixCommandHandler(message: Message) {
const args = message.content.split(" ");
Expand All @@ -15,11 +17,14 @@ export default async function prefixCommandHandler(message: Message) {
case "m":
case "z":
return await message
.reply({ files: [await magnifyToAttachment(url)] })
.reply({
files: [await magnifyToAttachment(url)],
components: [new ActionRowBuilder<ButtonBuilder>().addComponents(palette)]
})
.then((message: Message) => message.deleteButton());
case "t":
return await message
.reply({ files: [await tileToAttachment(url)] })
.reply({ files: [await tileToAttachment(url)], components: [imageButtons] })
.then((message: Message) => message.deleteButton());
case "p":
const [attachment, embed] = await paletteToAttachment(url);
Expand Down

0 comments on commit aa412be

Please sign in to comment.