From 1585941e8a4045a0353546f2fb4c133da83a4d15 Mon Sep 17 00:00:00 2001
From: Supositware <sup@libtar.de>
Date: Sat, 8 Apr 2023 00:29:49 +0000
Subject: [PATCH] Ported audio2image and image2audio

---
 commands/fun/audio2image.js | 59 +++++++++++++++++++++++++++++++++++++
 commands/fun/image2audio.js | 58 ++++++++++++++++++++++++++++++++++++
 2 files changed, 117 insertions(+)
 create mode 100644 commands/fun/audio2image.js
 create mode 100644 commands/fun/image2audio.js

diff --git a/commands/fun/audio2image.js b/commands/fun/audio2image.js
new file mode 100644
index 00000000..5e19c95a
--- /dev/null
+++ b/commands/fun/audio2image.js
@@ -0,0 +1,59 @@
+/* TODO
+ *
+ * Merge with commands/fun/image2audio.js
+ *
+*/
+import { SlashCommandBuilder } from 'discord.js';
+import fs from 'node:fs';
+import os from 'node:os';
+import fetch from 'node-fetch';
+import util from 'node:util';
+import stream from 'node:stream';
+import utils from '../../utils/videos.js';
+
+export default {
+	data: new SlashCommandBuilder()
+		.setName('audio2image')
+		.setDescription('Transform an audio file into an image.')
+		.addAttachmentOption(option =>
+			option.setName('audio')
+				.setDescription('The audio that will become image.')
+				.setRequired(true)),
+	category: 'fun',
+	async execute(interaction, args) {
+		if (!args.audio) return interaction.reply('Please attach an image with your message.');
+
+		await interaction.deferReply();
+
+		ifExistDelete(`${os.tmpdir()}/${args.audio.name}`);
+		ifExistDelete(`${os.tmpdir()}/${args.audio.name}.png`);
+		ifExistDelete(`${os.tmpdir()}/${args.audio.name}.sw`);
+		ifExistDelete(`${os.tmpdir()}/${args.audio.name}.mp3`);
+
+		const streamPipeline = util.promisify(stream.pipeline);
+		const res = await fetch(args.audio.url);
+		if (!res.ok) return interaction.editReply('An error has occured while trying to download your image.');
+		await streamPipeline(res.body, fs.createWriteStream(`${os.tmpdir()}/${args.audio.name}`));
+
+		await utils.ffmpeg(`-i ${os.tmpdir()}/${args.audio.name} -sample_rate 44100 -ac 1 -f s16le -acodec pcm_s16le  ${os.tmpdir()}/${args.audio.name}.sw`);
+		await utils.ffmpeg(`-pixel_format rgb24 -video_size 128x128 -f rawvideo -i ${os.tmpdir()}/${args.audio.name}.sw -frames:v 1 ${os.tmpdir()}/${args.audio.name}.png`);
+
+		const file = fs.statSync(`${os.tmpdir()}/${args.audio.name}.png`);
+		const fileSize = (file.size / 1000000.0).toFixed(2);
+
+		if (fileSize > 8) return interaction.editReply('error');
+		interaction.editReply({ content: `Image file is ${fileSize} MB` });
+		return interaction.followUp({ files: [`${os.tmpdir()}/${args.audio.name}.png`] });
+	},
+};
+
+async function ifExistDelete(path) {
+	if (fs.existsSync(path)) {
+		fs.rm(path, (err) => {
+			console.log('deleted');
+			if (err) {
+				return;
+			}
+		});
+	}
+}
\ No newline at end of file
diff --git a/commands/fun/image2audio.js b/commands/fun/image2audio.js
new file mode 100644
index 00000000..283f69b5
--- /dev/null
+++ b/commands/fun/image2audio.js
@@ -0,0 +1,58 @@
+/* TODO
+ *
+ * Merge with commands/fun/audio2image.js
+ *
+*/
+import { SlashCommandBuilder } from 'discord.js';
+import fs from 'node:fs';
+import os from 'node:os';
+import fetch from 'node-fetch';
+import util from 'node:util';
+import stream from 'node:stream';
+import utils from '../../utils/videos.js';
+
+export default {
+	data: new SlashCommandBuilder()
+		.setName('image2audio')
+		.setDescription('Transform an image binary data into audio ( MIGHT BE VERY LOUD )')
+		.addAttachmentOption(option =>
+			option.setName('img')
+				.setDescription('The image that will become audio. Only tested with png and jpg.')
+				.setRequired(true)),
+	category: 'fun',
+	async execute(interaction, args) {
+		if (!args.img) return interaction.reply('Please attach an image with your message.');
+
+		await interaction.deferReply();
+
+		ifExistDelete(`${os.tmpdir()}/${args.img.name}`);
+		ifExistDelete(`${os.tmpdir()}/1${args.img.name}`);
+		ifExistDelete(`${os.tmpdir()}/${args.img.name}.mp3`);
+
+		const streamPipeline = util.promisify(stream.pipeline);
+		const res = await fetch(args.img.url);
+		if (!res.ok) return interaction.editReply('An error has occured while trying to download your image.');
+		await streamPipeline(res.body, fs.createWriteStream(`${os.tmpdir()}/${args.img.name}`));
+
+		await utils.ffmpeg(`-i ${os.tmpdir()}/${args.img.name} -f rawvideo ${os.tmpdir()}/1${args.img.name}`);
+		await utils.ffmpeg(`-sample_rate 44100 -ac 1 -f s16le -i ${os.tmpdir()}/1${args.img.name} ${os.tmpdir()}/${args.img.name}.mp3`);
+
+		const file = fs.statSync(`${os.tmpdir()}/${args.img.name}.mp3`);
+		const fileSize = (file.size / 1000000.0).toFixed(2);
+
+		if (fileSize > 8) return interaction.editReply('error');
+		interaction.editReply({ content: `Audio file is ${fileSize} MB` });
+		return interaction.followUp({ files: [`${os.tmpdir()}/${args.img.name}.mp3`] });
+	},
+};
+
+async function ifExistDelete(path) {
+	if (fs.existsSync(path)) {
+		fs.rm(path, (err) => {
+			console.log('deleted');
+			if (err) {
+				return;
+			}
+		});
+	}
+}
\ No newline at end of file