Skip to content

Commit

Permalink
make more messages ephemeral again
Browse files Browse the repository at this point in the history
  • Loading branch information
3vorp committed Oct 11, 2023
1 parent e6f399c commit e13ae06
Show file tree
Hide file tree
Showing 13 changed files with 117 additions and 67 deletions.
9 changes: 7 additions & 2 deletions src/commands/faithful/texture.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { SlashCommand } from "@interfaces";
import { SlashCommandBuilder } from "discord.js";
import { ChatInputCommandInteraction, EmbedBuilder, Message } from "@client";
import { ChatInputCommandInteraction, Message } from "@client";
import { getTexture } from "@functions/getTexture";
import parseTextureName from "@functions/parseTextureName";
import { colors } from "@utility/colors";
import { textureChoiceEmbed } from "@helpers/choiceEmbed";

export const command: SlashCommand = {
Expand Down Expand Up @@ -48,6 +47,12 @@ export const command: SlashCommand = {
pack: interaction.options.getString("pack", true),
guild: interaction.guild,
});

if (!replyOptions.files) {
await interaction.deleteReply();
return interaction.followUp({ ...replyOptions, ephemeral: true });
}

return interaction.editReply(replyOptions).then((message: Message) => message.deleteButton());
}

Expand Down
3 changes: 1 addition & 2 deletions src/commands/images/animate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,7 @@ export const command: SlashCommand = {
// magnify beforehand since you can't magnify a gif currently
const { magnified, width, height } = await magnify(image, { isAnimation: true });
if (height > width * 32) {
await interaction.editReply({ content: "** **" }).then((reply) => reply.delete());

await interaction.deleteReply();
return interaction.followUp({
embeds: [
new EmbedBuilder()
Expand Down
9 changes: 6 additions & 3 deletions src/commands/images/compare.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { SlashCommand } from "@interfaces";
import { SlashCommandBuilder } from "discord.js";
import { Client, ChatInputCommandInteraction, EmbedBuilder, Message } from "@client";
import textureComparison from "@functions/textureComparison";
import { ChatInputCommandInteraction, Message } from "@client";
import textureComparison, { comparisonTooBig } from "@functions/textureComparison";
import parseTextureName from "@functions/parseTextureName";
import { colors } from "@utility/colors";
import { textureChoiceEmbed } from "@helpers/choiceEmbed";

export const command: SlashCommand = {
Expand Down Expand Up @@ -43,6 +42,10 @@ export const command: SlashCommand = {
// only one result
if (results.length === 1) {
const replyOptions = await textureComparison(interaction.client, results[0].id, display);
if (!replyOptions) {
await interaction.deleteReply();
return comparisonTooBig(interaction);
}

return interaction.editReply(replyOptions).then((message: Message) => message.deleteButton());
}
Expand Down
3 changes: 2 additions & 1 deletion src/commands/images/cycle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ export const command: SlashCommand = {
interaction,
"cycleSelect",
results,
`${display}__${framerate}`, // storing multiple things in value
display,
framerate.toString(), // storing multiple things in value
);
},
};
7 changes: 6 additions & 1 deletion src/components/buttons/image/compare.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Component } from "@interfaces";
import { info } from "@helpers/logger";
import { Client, Message, ButtonInteraction, EmbedBuilder } from "@client";
import textureComparison from "@functions/textureComparison";
import textureComparison, { comparisonTooBig } from "@functions/textureComparison";
import { InteractionEditReplyOptions, EmbedFooterData } from "discord.js";

export default {
Expand All @@ -14,6 +14,11 @@ export default {

await interaction.deferReply();
const messageOptions: InteractionEditReplyOptions = await textureComparison(client, ids[0]);
if (!messageOptions) {
// stupid workaround for already having deferred the message
await interaction.deleteReply();
return comparisonTooBig(interaction);
}

const embed = messageOptions.embeds[0] as EmbedBuilder;

Expand Down
11 changes: 3 additions & 8 deletions src/components/buttons/image/comparisonTemplate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,13 @@ export default {
const packs = parseDisplay(display);

const loadedImages = [];
let i = 0;
for (const packSet of packs) {
loadedImages.push([]);
for (const pack of packSet) {
loadedImages[i].push(await loadImage(formatName(pack, "64")[1]));
}
++i;
for (const pack of packSet)
loadedImages.at(-1).push(await loadImage(formatName(pack, "64")[1]));
}

const longestRow = loadedImages.reduce((acc, item) => Math.max(acc, item.length), 0);
const stitched = await stitch(loadedImages, longestRow == 3 ? 4 : 2);

const stitched = await stitch(loadedImages);
const magnified = await magnifyToAttachment(stitched);

const embed = new EmbedBuilder()
Expand Down
8 changes: 7 additions & 1 deletion src/components/menus/compareSelect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Client, Message, StringSelectMenuInteraction } from "@client";
import { Component } from "@interfaces";
import { info } from "@helpers/logger";
import { MessageEditOptions, MessageInteraction } from "discord.js";
import textureComparison from "@functions/textureComparison";
import textureComparison, { comparisonTooBig } from "@functions/textureComparison";

export default {
id: "compareSelect",
Expand All @@ -29,6 +29,12 @@ export default {
display,
);

if (!editOptions) {
// stupid workaround for already having deferred the message
await interaction.deleteReply();
return comparisonTooBig(interaction);
}

message.edit(editOptions).then((message: Message) => message.deleteButton());
},
} as Component;
7 changes: 6 additions & 1 deletion src/components/menus/textureSelect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,17 @@ export default {
interaction.deferUpdate();

const [id, pack] = interaction.values[0].split("__");
const editOptions: MessageEditOptions = await getTexture({
const editOptions = await getTexture({
texture: (await axios.get(`${interaction.client.tokens.apiUrl}textures/${id}/all`)).data,
pack: pack,
guild: interaction.guild,
});

if (!editOptions.files) {
await interaction.deleteReply();
return interaction.followUp({ ...editOptions, ephemeral: true });
}

return message.edit(editOptions).then((message: Message) => message.deleteButton());
},
} as Component;
6 changes: 3 additions & 3 deletions src/helpers/choiceEmbed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,13 @@ export async function generalChoiceEmbed(
* @param interaction interaction to reply to
* @param menuID which id the result gets sent to
* @param results textures to embed
* @param constValue extra info to send to the menuID (separate multiple values with "__")
* @param constValues extra info to send to the menuID
*/
export async function textureChoiceEmbed(
interaction: ChatInputCommandInteraction,
menuID: string,
results: Texture[],
constValue: string,
...constValues: string[]
) {
const mappedResults: SelectMenuComponentOptionData[] = [];
for (const result of results) {
Expand All @@ -79,7 +79,7 @@ export async function textureChoiceEmbed(
result.name
}`,
description: result.paths[0].name,
value: `${result.id}__${constValue}`,
value: `${result.id}__${constValues.join("__")}`,
});
}

Expand Down
8 changes: 3 additions & 5 deletions src/helpers/functions/parseTextureName.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@ export default async function parseTextureName(
name = name.toLowerCase().trim().replace(".png", "").replace("#", "").replace(/ /g, "_");

if (name.length < 3 && isNaN(Number(name))) {
// stupid workaround for already having deferred the message
await interaction.editReply({ content: "** **" }).then((reply) => reply.delete());

// it's already deferred so we delete the non-ephemeral message
await interaction.deleteReply();
interaction.followUp({
embeds: [
new EmbedBuilder()
Expand All @@ -43,8 +42,7 @@ export default async function parseTextureName(
const out = Array.isArray(results) ? results : [results];

if (!out.length) {
await interaction.editReply({ content: "** **" }).then((reply) => reply.delete());

await interaction.deleteReply();
await interaction.followUp({
embeds: [
new EmbedBuilder()
Expand Down
57 changes: 36 additions & 21 deletions src/helpers/functions/textureComparison.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
import stitch from "@images/stitch";
import { magnifyToAttachment } from "@images/magnify";
import { loadImage } from "@napi-rs/canvas";
import { Client, EmbedBuilder } from "@client";
import {
Client,
EmbedBuilder,
ButtonInteraction,
ChatInputCommandInteraction,
StringSelectMenuInteraction,
Message,
} from "@client";
import { addPathsToEmbed } from "@functions/getTexture";
import getDimensions from "@images/getDimensions";
import { Texture } from "@interfaces";
import axios from "axios";
import { ActionRowBuilder, ButtonBuilder } from "discord.js";
import { template } from "@utility/buttons";
import warnUser from "@helpers/warnUser";

/**
* Get the corresponding pack IDs for a given display choice
Expand Down Expand Up @@ -53,38 +61,24 @@ export default async function textureComparison(
const defaultURL = `${client.tokens.apiUrl}textures/${id}/url/default/latest`;

const dimension = await getDimensions(defaultURL);
if (dimension.width * dimension.height * displayed.flat().length > 262144) {
return {
embeds: [
new EmbedBuilder()
.setTitle("Output will be too big!")
.setDescription(
"Try specifying which set of packs you want to view to reduce the total image size.",
),
],
components: [],
};
}
if (dimension.width * dimension.height * displayed.flat().length > 262144) return null;

// get texture urls
// get texture urls into 2d array using the parsed display
const loadedImages = [];
let i = 0;
for (const packSet of displayed) {
// had problems with nested async mapping so this is easier for everyone
loadedImages.push([]);
for (const pack of packSet) {
const imgUrl = `${client.tokens.apiUrl}textures/${id}/url/${pack}/latest`;
try {
loadedImages[i].push(await loadImage(imgUrl));
loadedImages.at(-1).push(await loadImage(imgUrl));
} catch {
// image doesn't exist yet
}
}
++i; // can't use forEach because of scope problems (blame js)
}

const longestRow = loadedImages.reduce((acc, item) => Math.max(acc, item.length), 0);
const stitched = await stitch(loadedImages, longestRow == 3 ? 4 : 2);

const stitched = await stitch(loadedImages);
const magnified = await magnifyToAttachment(stitched);

const embed = new EmbedBuilder()
Expand All @@ -94,10 +88,31 @@ export default async function textureComparison(
.addFields(addPathsToEmbed(result))
.setFooter({ text: `Displaying: ${display ?? "All"}` });

// empty array overwrites select menu choices if needed
return {
embeds: [embed],
files: [magnified],
components: [new ActionRowBuilder<ButtonBuilder>().addComponents(template)],
};
}

/**
* Warn the user that the image is too large
* @author Evorp
* @param interaction interaction to reply to
*/
export async function comparisonTooBig(
interaction:
| ButtonInteraction
| ChatInputCommandInteraction
| StringSelectMenuInteraction
| Message,
) {
// force english if it's a message
return warnUser(
interaction,
interaction
.strings(interaction instanceof Message)
.command.images.too_big.replace("%ACTION%", "compare"),
interaction.strings(interaction instanceof Message).command.images.max_size,
);
}
47 changes: 30 additions & 17 deletions src/helpers/images/stitch.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,45 @@
import { Canvas } from "@napi-rs/canvas";
import { createCanvas, Canvas, Image } from "@napi-rs/canvas";

/**
* Stitch a 2d array of canvases into one image with a specified gap
* @author EwanHowell
* Stitch a 2d array of canvases into one image
* @author EwanHowell, Evorp
* @param images pre-loaded canvas images
* @param gap optionally specify pixel gap
* @returns canvas buffer with stitched image
*/
export default async function stitch(images: Canvas[][], gap = 0) {
const img = images.flat().reduce((a, e) => (a.width > e.width ? a : e), { width: 0, height: 0 });
const length = images.reduce((a, e) => Math.max(a, e.length), 0);
const vGap = (length - 1) * gap;
const hGap = (images.length - 1) * gap;
const width = length * img.width;
const height = images.length * img.height;
const tileWidth = Math.floor(width / length);
const tileHeight = Math.floor(height / images.length);
const canvas = new Canvas(tileWidth * length + vGap, tileHeight * images.length + hGap);
export default async function stitch(images: (Canvas | Image)[][], gap = 0) {
const biggestImage = images
.flat()
.reduce((a, e) => (a.width > e.width ? a : e), { width: 0, height: 0 });

if (gap == null || gap == undefined) {
const surface = biggestImage.width * biggestImage.height;
// the gap should be the size of one 16x "pixel"
gap = 1;
if (surface > 256) gap = 2;
if (surface > 1024) gap = 4;
if (surface > 4096) gap = 8;
if (surface > 65536) gap = 16;
if (surface > 262144) gap = 32;
}

const longestRow = images.reduce((a, e) => Math.max(a, e.length), 0);
const canvas = createCanvas(
// gap count = image length - 1
longestRow * (biggestImage.width + gap) - gap,
images.length * (biggestImage.height + gap) - gap,
);

const ctx = canvas.getContext("2d");
ctx.imageSmoothingEnabled = false;
for (let y = 0; y < images.length; ++y)
for (let x = 0; x < images[y].length; ++x) {
ctx.drawImage(
images[y][x],
x * tileWidth + x * gap,
y * tileHeight + y * gap,
tileWidth,
tileHeight,
x * (biggestImage.width + gap),
y * (biggestImage.height + gap),
biggestImage.width,
biggestImage.height,
);
}
return canvas.toBuffer("image/png");
Expand Down
9 changes: 7 additions & 2 deletions src/helpers/warnUser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,13 @@ export default async function warnUser(
try {
reply = await (interaction as ChatInputCommandInteraction).reply(args);
} catch {
// already deferred so we try to follow up instead
reply = await (interaction as ChatInputCommandInteraction).editReply(args);
try {
// check if deferred
reply = await (interaction as ChatInputCommandInteraction).editReply(args);
} catch {
// follow up if original message not found
reply = await (interaction as ChatInputCommandInteraction).followUp(args);
}
}
if (interaction instanceof Message) reply.deleteButton();
}

0 comments on commit e13ae06

Please sign in to comment.