From 1dbcb8302933a20bf2a54b630e876887ed7d0369 Mon Sep 17 00:00:00 2001
From: Supositware <sup@libtar.de>
Date: Mon, 22 Aug 2022 20:23:27 +0200
Subject: [PATCH] Compress video option

---
 commands/utility/download.js | 59 +++++++++++++++++++++++++++++++++---
 scripts/deploy-commands.cjs  |  8 +++--
 utils/videos.js              | 15 +++++++++
 3 files changed, 76 insertions(+), 6 deletions(-)

diff --git a/commands/utility/download.js b/commands/utility/download.js
index cc44c2b0..092ccd76 100644
--- a/commands/utility/download.js
+++ b/commands/utility/download.js
@@ -14,8 +14,12 @@ export default {
 				.setDescription('url of the video you want to download.')
 				.setRequired(true))
 		.addBooleanOption(option =>
-			option.setName('advanced')
+			option.setName('format')
 				.setDescription('Choose the quality of the video.')
+				.setRequired(false))
+		.addBooleanOption(option =>
+			option.setName('compress')
+				.setDescription('Compress the video?')
 				.setRequired(false)),
 
 	async execute(interaction) {
@@ -27,7 +31,7 @@ export default {
 			return interaction.editReply({ content: '❌ This does not look like a valid url!', ephemeral: true });
 		}
 
-		if (interaction.options.getBoolean('advanced')) {
+		if (interaction.options.getBoolean('format')) {
 			let qualitys = await new Promise((resolve, reject) => {
 				exec(`./bin/yt-dlp "${url}" --print "%()j"`, (err, stdout, stderr) => {
 					if (err) {
@@ -84,7 +88,7 @@ export default {
 				if (!interactionMenu.isSelectMenu()) return;
 				if (interactionMenu.customId === 'downloadQuality') {
 					await interactionMenu.deferReply({ ephemeral: false });
-					download(url, interactionMenu);
+					download(url, interactionMenu, interaction);
 				}
 			});
 			return;
@@ -93,7 +97,7 @@ export default {
 	},
 };
 
-async function download(url, interaction) {
+async function download(url, interaction, originalInteraction) {
 	let format = 'bestvideo*+bestaudio/best';
 	const Embed = new MessageEmbed()
 		.setColor(interaction.member ? interaction.member.displayHexColor : 'NAVY')
@@ -112,6 +116,37 @@ async function download(url, interaction) {
 
 			const fileStat = fs.statSync(output);
 			const fileSize = fileStat.size / 1000000.0;
+			const compressInteraction = originalInteraction ? originalInteraction : interaction;
+			if (compressInteraction.options.getBoolean('compress')) {
+				const presets = [ 'Discord Tiny 5 Minutes 240p30', 'Discord Small 2 Minutes 360p30', 'Discord Nitro Small 10-20 Minutes 480p30', 'Discord Nitro Medium 5-10 Minutes 720p30', 'Discord Nitro Large 3-6 Minutes 1080p30' ];
+				const options = [];
+
+				presets.forEach(p => {
+					options.push({
+						label: p,
+						value: p,
+					});
+				});
+
+				const row = new MessageActionRow()
+					.addComponents(
+						new MessageSelectMenu()
+							.setCustomId('preset')
+							.setPlaceholder('Nothing selected')
+							.addOptions(options),
+					);
+
+				await interaction.deleteReply();
+				await interaction.followUp({ content: 'Which compression preset do you want?', ephemeral: true, components: [row] });
+				interaction.client.once('interactionCreate', async (interactionMenu) => {
+					if (!interactionMenu.isSelectMenu()) return;
+					if (interactionMenu.customId === 'preset') {
+						await interactionMenu.deferReply({ ephemeral: false });
+						compress(file, interactionMenu, Embed);
+					}
+				});
+				return;
+			}
 
 			if (fileSize > 100) {
 				await interaction.deleteReply();
@@ -136,3 +171,19 @@ async function download(url, interaction) {
 		});
 	return;
 }
+
+async function compress(input, interaction, embed) {
+	const output = `compressed${input}.mp4`;
+	utils.compressVideo(`${os.tmpdir()}/${input}`, output, interaction.values[0])
+		.then(async () => {
+			const fileStat = fs.statSync(`${os.tmpdir()}/${output}`);
+			const fileSize = fileStat.size / 1000000.0;
+
+			if (fileSize > 8) {
+				await interaction.editReply({ content: 'File was bigger than 8 mb. but due to the compression it is not being uploaded externally.', ephemeral: true });
+			}
+			else {
+				await interaction.editReply({ embeds: [embed], files: [`${os.tmpdir()}/${output}`], ephemeral: false });
+			}
+		});
+}
\ No newline at end of file
diff --git a/scripts/deploy-commands.cjs b/scripts/deploy-commands.cjs
index 8921c9a3..7b79985e 100644
--- a/scripts/deploy-commands.cjs
+++ b/scripts/deploy-commands.cjs
@@ -11,14 +11,18 @@ const commands = [
 
 	new SlashCommandBuilder()
 		.setName('download')
-		.setDescription('Download a video. (100 mb max)')
+		.setDescription('Download a video.')
 		.addStringOption(option =>
 			option.setName('url')
-				.setDescription('URL of the video you want to download.')
+				.setDescription('url of the video you want to download.')
 				.setRequired(true))
 		.addBooleanOption(option =>
 			option.setName('advanced')
 				.setDescription('Choose the quality of the video.')
+				.setRequired(false))
+		.addBooleanOption(option =>
+			option.setName('compress')
+				.setDescription('Compress the video?')
 				.setRequired(false)),
 
 
diff --git a/utils/videos.js b/utils/videos.js
index 77c653f7..9c803f49 100644
--- a/utils/videos.js
+++ b/utils/videos.js
@@ -6,6 +6,7 @@ export default {
 	upload,
 	ffmpeg,
 	stringIsAValidurl,
+	compressVideo,
 };
 async function downloadVideo(urlArg, output, format = 'bestvideo*+bestaudio/best') {
 	await new Promise((resolve, reject) => {
@@ -58,3 +59,17 @@ async function stringIsAValidurl(s) {
 		return false;
 	}
 }
+
+async function compressVideo(input, output, preset) {
+	await new Promise((resolve, reject) => {
+		exec(`./bin/HandBrakeCLI -i '${input}' -Z '${preset}' -o '${os.tmpdir()}/${output}'`, (err, stdout, stderr) => {
+			if (err) {
+				reject(stderr);
+			}
+			if (stderr) {
+				console.error(stderr);
+			}
+			resolve(stdout);
+		});
+	});
+}
\ No newline at end of file