const { execSync } = require('child_process'); const fs = require('fs'); const path = require('path'); const { writeFile } = require('node:fs/promises') const { Readable } = require('node:stream') const executeCommand = require('../../util/executeCommand'); module.exports = { name: 'tdoss', description: 'Combine picture with tdoss album cover template', async execute({ message, args }) { let tdossDir = path.resolve(process.cwd(), 'data', 'tdoss'); const tdossTemplate = path.resolve(process.cwd(), 'resources', 'tdoss_template.png'); const directory = path.resolve(tdossDir, Math.floor(new Date).toString()) fs.mkdirSync(directory, {recursive: true}) let url = ""; if(message.attachments.size > 0){ url = message.attachments.first().url } else if(args[0] && args[0].startsWith("https://") ){ url = args[0]; }else if(message.reference){ let referencedMessage = await message.fetchReference(); if(referencedMessage.attachments.size > 0){ url = await referencedMessage.attachments.first().url; } else { message.channel.send("The message you replied to doesn't have any attachments."); return; } } else { let lastMessages = await message.channel.messages.fetch({limit: 20, cache: false}); let lastMessageWithAttachment = lastMessages.find(m => m.attachments.size > 0); if(!lastMessageWithAttachment){ message.channel.send("Couldn't find an image to use this command on.") fs.rmSync(`${directory}`, {recursive: true}) return } url = lastMessageWithAttachment.attachments.first().url; } // TODO: Download with correct extension. message.channel.sendTyping(); let downloadResult = await this.downloadImage(url, path.resolve(directory, "input.png")); if(downloadResult.value != this.ERROR_CODES.SUCCESS){ if(downloadResult.value === this.ERROR_CODES.FETCH_ERROR){ message.channel.send(`Failed to download the provided image, got error '${downloadResult.errorMessage}'`); }else if (downloadResult.value === this.ERROR_CODES.HTTP_ERROR){ message.channel.send(`Failed to download the provided image, got response status '${downloadResult.errorMessage}'`); }else if(downloadResult.value === this.ERROR_CODES.NOT_IMAGE){ message.channel.send(`The provided url was not an image.`) } fs.rmSync(`${directory}`, {recursive: true}) return; } const commandArgs = [tdossTemplate, "(", `${directory}/input.png`, "-resize", "800x800^", "-gravity", "center", "-extent", "1000x1000", ")", "-compose", "dst-over", "-composite", `${directory}/tdoss_result.png`] if (executeCommand("magick", commandArgs).error === true) { message.channel.send("Something went wrong during image manipulation.\nTry again and if it keeps happening, contact the owner of the bot.") fs.rmSync(`${directory}`, {recursive: true}) return } let final_image = { attachment: path.resolve(`${directory}/tdoss_result.png`), name: "tdoss_result.png" } await message.channel.send({files: [final_image]}) fs.rmSync(`${directory}`, {recursive: true}) }, // https://stackoverflow.com/a/77210219 async downloadImage(url, path) { let res; try { res = await fetch(url); } catch (error) { return {value: this.ERROR_CODES.FETCH_ERROR, errorMessage: error.cause?.message || error.message}; } if(!res.ok) return {value: this.ERROR_CODES.HTTP_ERROR, errorMessage: res.status.toString()}; const contentType = res.headers.get('content-type'); if(!contentType || !contentType.startsWith("image")) return {value: this.ERROR_CODES.NOT_IMAGE, errorMessage: contentType || "No content-type header"}; const stream = Readable.fromWeb(res.body) await writeFile(path, stream); return {value: this.ERROR_CODES.SUCCESS, errorMessage: ""}; }, ERROR_CODES: { SUCCESS: 0, HTTP_ERROR: 1, NOT_IMAGE: 2, FETCH_ERROR: 3 } }