From d27c1bad558ce591405fb69e0ba64cd587dfee0a Mon Sep 17 00:00:00 2001 From: SileNce5k Date: Tue, 17 Jun 2025 01:55:20 +0200 Subject: [PATCH 01/15] Add initial dl command --- commands/misc/dl.js | 65 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 commands/misc/dl.js diff --git a/commands/misc/dl.js b/commands/misc/dl.js new file mode 100644 index 0000000..d711201 --- /dev/null +++ b/commands/misc/dl.js @@ -0,0 +1,65 @@ +const { execSync } = require('child_process'); +const path = require('path'); +const fs = require('fs') + +module.exports = { + name: 'dl', + description: 'Download a video', + moreHelp: [ + "Usage: dl " + ], + async execute({message, args}) { + const downloadsDir = path.resolve(process.cwd(), 'data', 'downloads', Math.floor(new Date).toString()); + fs.mkdirSync(downloadsDir, {recursive: true}); + + let url; + + if(args[0] && args[0].startsWith("https://") ){ + url = args[0]; + } else { + return message.channel.send("No url") + } + + if(this.executeCommand(`yt-dlp "${url}" -P ${downloadsDir}`).error === false){ + message.channel.send("An error occured when executing the command"); + this.cleanUp(downloadsDir); + return; + } + + + let files = fs.readdirSync(downloadsDir); + if(files < 1) { + this.cleanUp(downloadsDir); + message.channel.send("Something went wrong when downloading the video.") + return; + } + const filename = files[0]; + + await message.channel.send({files: [{ + attachment: path.resolve(`${downloadsDir}/${filename}`) + }]}) + + this.cleanUp(downloadsDir); + + + + + }, + + cleanUp(downloadsDir){ + fs.rmSync(downloadsDir); + }, + executeCommand(command) { + console.log("Executing:", command) + try { + const output = execSync(command, { encoding: 'utf-8' }) + if (output.length != 0) + console.log(output) + } catch (error) { + console.error(`Error executing ${command.split(" ")[0]} command:`, error); + return { error: true }; + } + return { error: false }; + }, + +} \ No newline at end of file From 9d0eb60b8188f0e80f9dfbd912a53a4af1542ff2 Mon Sep 17 00:00:00 2001 From: SileNce5k Date: Tue, 17 Jun 2025 02:21:31 +0200 Subject: [PATCH 02/15] Improve dl command --- commands/misc/dl.js | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/commands/misc/dl.js b/commands/misc/dl.js index d711201..9758004 100644 --- a/commands/misc/dl.js +++ b/commands/misc/dl.js @@ -14,10 +14,18 @@ module.exports = { let url; - if(args[0] && args[0].startsWith("https://") ){ - url = args[0]; + if(args.length > 0){ + try { + url = new URL(args[0]); + url = url.href; + } catch (error) { + this.cleanUp(downloadsDir); + message.channel.send("Invalid URL"); + return; + } } else { - return message.channel.send("No url") + this.cleanUp(downloadsDir); + return message.channel.send("No url provided") } if(this.executeCommand(`yt-dlp "${url}" -P ${downloadsDir}`).error === false){ @@ -36,18 +44,16 @@ module.exports = { const filename = files[0]; await message.channel.send({files: [{ - attachment: path.resolve(`${downloadsDir}/${filename}`) + attachment: path.resolve(downloadsDir, filename) }]}) this.cleanUp(downloadsDir); - - }, cleanUp(downloadsDir){ - fs.rmSync(downloadsDir); + fs.rmSync(downloadsDir, {force: true, recursive: true}); }, executeCommand(command) { console.log("Executing:", command) From 0a3554966656c01e56061f52145ec3b775778485 Mon Sep 17 00:00:00 2001 From: SileNce5k Date: Tue, 17 Jun 2025 02:24:20 +0200 Subject: [PATCH 03/15] dl: fix error check --- commands/misc/dl.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commands/misc/dl.js b/commands/misc/dl.js index 9758004..1de49e8 100644 --- a/commands/misc/dl.js +++ b/commands/misc/dl.js @@ -28,7 +28,7 @@ module.exports = { return message.channel.send("No url provided") } - if(this.executeCommand(`yt-dlp "${url}" -P ${downloadsDir}`).error === false){ + if(this.executeCommand(`yt-dlp "${url}" -P ${downloadsDir}`).error){ message.channel.send("An error occured when executing the command"); this.cleanUp(downloadsDir); return; From 340727ae602139ad50cdac2b270b197c781d50be Mon Sep 17 00:00:00 2001 From: SileNce5k Date: Wed, 18 Jun 2025 00:14:10 +0200 Subject: [PATCH 04/15] dl: Add cookie file --- commands/misc/dl.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/commands/misc/dl.js b/commands/misc/dl.js index 1de49e8..3752e59 100644 --- a/commands/misc/dl.js +++ b/commands/misc/dl.js @@ -10,6 +10,7 @@ module.exports = { ], async execute({message, args}) { const downloadsDir = path.resolve(process.cwd(), 'data', 'downloads', Math.floor(new Date).toString()); + const cookieFilepath = path.resolve(process.cwd(), 'data', 'cookies.txt') fs.mkdirSync(downloadsDir, {recursive: true}); let url; @@ -28,13 +29,13 @@ module.exports = { return message.channel.send("No url provided") } - if(this.executeCommand(`yt-dlp "${url}" -P ${downloadsDir}`).error){ + if(this.executeCommand(`yt-dlp "${url}" -P ${downloadsDir} --cookies ${cookieFilepath}`).error){ message.channel.send("An error occured when executing the command"); this.cleanUp(downloadsDir); return; } - + let files = fs.readdirSync(downloadsDir); if(files < 1) { this.cleanUp(downloadsDir); From 09eee1a0cada40b5ede644b43bccab5de835a852 Mon Sep 17 00:00:00 2001 From: SileNce5k Date: Wed, 18 Jun 2025 00:36:32 +0200 Subject: [PATCH 05/15] Add support for prepending URL with '<' and appending with '>' --- commands/misc/dl.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/commands/misc/dl.js b/commands/misc/dl.js index 3752e59..86c2d1a 100644 --- a/commands/misc/dl.js +++ b/commands/misc/dl.js @@ -16,6 +16,9 @@ module.exports = { let url; if(args.length > 0){ + if(args[0].charAt(0) === '<' && args[0].charAt(args[0].length - 1) === '>'){ + args[0] = args[0].slice(0, args[0].length - 1) + } try { url = new URL(args[0]); url = url.href; From 40052ac85d86120c9329b51b8c46164ce501dd40 Mon Sep 17 00:00:00 2001 From: SileNce5k Date: Wed, 18 Jun 2025 00:37:03 +0200 Subject: [PATCH 06/15] Improve error messages --- commands/misc/dl.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/commands/misc/dl.js b/commands/misc/dl.js index 86c2d1a..d86077f 100644 --- a/commands/misc/dl.js +++ b/commands/misc/dl.js @@ -24,16 +24,16 @@ module.exports = { url = url.href; } catch (error) { this.cleanUp(downloadsDir); - message.channel.send("Invalid URL"); + message.channel.send("Could not parse the provided argument as a URL."); return; } } else { this.cleanUp(downloadsDir); - return message.channel.send("No url provided") + return message.channel.send("You have to provide a URL in an argument.") } if(this.executeCommand(`yt-dlp "${url}" -P ${downloadsDir} --cookies ${cookieFilepath}`).error){ - message.channel.send("An error occured when executing the command"); + message.channel.send("An error occured when downloading the video."); this.cleanUp(downloadsDir); return; } From ad73a83514feba07c0dc3883888e1337cffb30e1 Mon Sep 17 00:00:00 2001 From: SileNce5k Date: Sat, 21 Jun 2025 13:31:59 +0200 Subject: [PATCH 07/15] Send an inital message when downloading begins & check for cookies file --- commands/misc/dl.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/commands/misc/dl.js b/commands/misc/dl.js index d86077f..984f560 100644 --- a/commands/misc/dl.js +++ b/commands/misc/dl.js @@ -9,8 +9,13 @@ module.exports = { "Usage: dl " ], async execute({message, args}) { + const downloadsDir = path.resolve(process.cwd(), 'data', 'downloads', Math.floor(new Date).toString()); const cookieFilepath = path.resolve(process.cwd(), 'data', 'cookies.txt') + if(!fs.existsSync(cookieFilepath)) { + message.channel.send("Some dependencies are needed for the command to work properly. Please let the bot's owner know.") + return; + } fs.mkdirSync(downloadsDir, {recursive: true}); let url; @@ -32,8 +37,9 @@ module.exports = { return message.channel.send("You have to provide a URL in an argument.") } + const originalMessage = await message.channel.send("Downloading video...") if(this.executeCommand(`yt-dlp "${url}" -P ${downloadsDir} --cookies ${cookieFilepath}`).error){ - message.channel.send("An error occured when downloading the video."); + originalMessage.edit("An error occured when downloading the video."); this.cleanUp(downloadsDir); return; } @@ -42,12 +48,12 @@ module.exports = { let files = fs.readdirSync(downloadsDir); if(files < 1) { this.cleanUp(downloadsDir); - message.channel.send("Something went wrong when downloading the video.") + originalMessage.edit("Something went wrong when downloading the video.") return; } const filename = files[0]; - await message.channel.send({files: [{ + await originalMessage.edit({files: [{ attachment: path.resolve(downloadsDir, filename) }]}) From 8314be972f4e0726e7de57f6dce697f71fee776d Mon Sep 17 00:00:00 2001 From: SileNce5k Date: Sat, 21 Jun 2025 13:35:58 +0200 Subject: [PATCH 08/15] Slice first character of the argument --- commands/misc/dl.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commands/misc/dl.js b/commands/misc/dl.js index 984f560..4c69250 100644 --- a/commands/misc/dl.js +++ b/commands/misc/dl.js @@ -22,7 +22,7 @@ module.exports = { if(args.length > 0){ if(args[0].charAt(0) === '<' && args[0].charAt(args[0].length - 1) === '>'){ - args[0] = args[0].slice(0, args[0].length - 1) + args[0] = args[0].slice(1, args[0].length - 1) } try { url = new URL(args[0]); From 27fc1c55bf7043e33a28fc6b6d453c5060163fe3 Mon Sep 17 00:00:00 2001 From: SileNce5k Date: Sat, 21 Jun 2025 13:38:06 +0200 Subject: [PATCH 09/15] Edit the text to nothing --- commands/misc/dl.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/commands/misc/dl.js b/commands/misc/dl.js index 4c69250..b5ffbe8 100644 --- a/commands/misc/dl.js +++ b/commands/misc/dl.js @@ -53,7 +53,9 @@ module.exports = { } const filename = files[0]; - await originalMessage.edit({files: [{ + await originalMessage.edit({ + content: null, + files: [{ attachment: path.resolve(downloadsDir, filename) }]}) From 2073a46715672ec81e6f70cf061ac3ec3a9be471 Mon Sep 17 00:00:00 2001 From: SileNce5k Date: Sat, 21 Jun 2025 13:54:45 +0200 Subject: [PATCH 10/15] Fix file check --- commands/misc/dl.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commands/misc/dl.js b/commands/misc/dl.js index b5ffbe8..35c07a1 100644 --- a/commands/misc/dl.js +++ b/commands/misc/dl.js @@ -46,7 +46,7 @@ module.exports = { let files = fs.readdirSync(downloadsDir); - if(files < 1) { + if(files.length < 1) { this.cleanUp(downloadsDir); originalMessage.edit("Something went wrong when downloading the video.") return; From f4ffcbebde9f0696a7f29b88378f49b2e3a619f2 Mon Sep 17 00:00:00 2001 From: SileNce5k Date: Sat, 21 Jun 2025 13:55:18 +0200 Subject: [PATCH 11/15] Use Date.now() --- commands/misc/dl.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/commands/misc/dl.js b/commands/misc/dl.js index 35c07a1..57a5027 100644 --- a/commands/misc/dl.js +++ b/commands/misc/dl.js @@ -9,8 +9,7 @@ module.exports = { "Usage: dl " ], async execute({message, args}) { - - const downloadsDir = path.resolve(process.cwd(), 'data', 'downloads', Math.floor(new Date).toString()); + const downloadsDir = path.resolve(process.cwd(), 'data', 'downloads', Date.now().toString()); const cookieFilepath = path.resolve(process.cwd(), 'data', 'cookies.txt') if(!fs.existsSync(cookieFilepath)) { message.channel.send("Some dependencies are needed for the command to work properly. Please let the bot's owner know.") From 6293010b6c4fdfc5b95cda96ef1e7d045c5c2e2e Mon Sep 17 00:00:00 2001 From: SileNce5k Date: Sat, 21 Jun 2025 14:25:43 +0200 Subject: [PATCH 12/15] Fix command injection vulnerability by using a command array --- commands/misc/dl.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/commands/misc/dl.js b/commands/misc/dl.js index 57a5027..bad36d6 100644 --- a/commands/misc/dl.js +++ b/commands/misc/dl.js @@ -37,7 +37,8 @@ module.exports = { } const originalMessage = await message.channel.send("Downloading video...") - if(this.executeCommand(`yt-dlp "${url}" -P ${downloadsDir} --cookies ${cookieFilepath}`).error){ + + if(this.executeCommand(["yt-dlp", url, "-P", downloadsDir, "--cookies", cookieFilepath]).error){ originalMessage.edit("An error occured when downloading the video."); this.cleanUp(downloadsDir); return; @@ -66,17 +67,20 @@ module.exports = { cleanUp(downloadsDir){ fs.rmSync(downloadsDir, {force: true, recursive: true}); }, + executeCommand(command) { - console.log("Executing:", command) + if(!Array.isArray(command)) return {error: true}; + const cmdString = command.join(" ") + console.log("Executing:", cmdString); try { - const output = execSync(command, { encoding: 'utf-8' }) + const output = execSync(cmdString, { encoding: 'utf-8' }) if (output.length != 0) console.log(output) } catch (error) { - console.error(`Error executing ${command.split(" ")[0]} command:`, error); + console.error(`Error executing ${command[0]} command:`, error); return { error: true }; } return { error: false }; }, -} \ No newline at end of file +} From a6060cdbfbc6b98b390efa7b7d03e84a47b7663c Mon Sep 17 00:00:00 2001 From: SileNce5k Date: Sat, 21 Jun 2025 15:30:18 +0200 Subject: [PATCH 13/15] Use execFileSync instead of execSync to prevent command injection and add verbose flag --- commands/misc/dl.js | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/commands/misc/dl.js b/commands/misc/dl.js index bad36d6..9104f7a 100644 --- a/commands/misc/dl.js +++ b/commands/misc/dl.js @@ -1,4 +1,4 @@ -const { execSync } = require('child_process'); +const { execFileSync } = require('child_process'); const path = require('path'); const fs = require('fs') @@ -38,7 +38,7 @@ module.exports = { const originalMessage = await message.channel.send("Downloading video...") - if(this.executeCommand(["yt-dlp", url, "-P", downloadsDir, "--cookies", cookieFilepath]).error){ + if(this.executeCommand("yt-dlp", [url, "-P", downloadsDir, "--cookies", cookieFilepath]).error){ originalMessage.edit("An error occured when downloading the video."); this.cleanUp(downloadsDir); return; @@ -68,16 +68,15 @@ module.exports = { fs.rmSync(downloadsDir, {force: true, recursive: true}); }, - executeCommand(command) { - if(!Array.isArray(command)) return {error: true}; - const cmdString = command.join(" ") - console.log("Executing:", cmdString); + executeCommand(command, commandArgs, {verbose = false}) { + if (typeof command !== 'string' || !Array.isArray(commandArgs)) return { error: true }; + console.log("Executing:", command, commandArgs.join(" ")); try { - const output = execSync(cmdString, { encoding: 'utf-8' }) - if (output.length != 0) + const output = execFileSync(command, commandArgs, {encoding: 'utf8'}) + if (output.length != 0 && verbose) console.log(output) } catch (error) { - console.error(`Error executing ${command[0]} command:`, error); + console.error(`Error executing ${command} command:`, error); return { error: true }; } return { error: false }; From e68bb41960a52ada53cb2041eb278cf0b96540c4 Mon Sep 17 00:00:00 2001 From: SileNce5k Date: Sat, 21 Jun 2025 15:35:26 +0200 Subject: [PATCH 14/15] Fix typo --- commands/misc/dl.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commands/misc/dl.js b/commands/misc/dl.js index 9104f7a..6a12ab9 100644 --- a/commands/misc/dl.js +++ b/commands/misc/dl.js @@ -39,7 +39,7 @@ module.exports = { const originalMessage = await message.channel.send("Downloading video...") if(this.executeCommand("yt-dlp", [url, "-P", downloadsDir, "--cookies", cookieFilepath]).error){ - originalMessage.edit("An error occured when downloading the video."); + originalMessage.edit("An error occurred when downloading the video."); this.cleanUp(downloadsDir); return; } From c6ef14ee70fe10f712a627d96ac1fb687d981ae3 Mon Sep 17 00:00:00 2001 From: SileNce5k Date: Sat, 21 Jun 2025 15:40:16 +0200 Subject: [PATCH 15/15] Fix verbose flag not working --- commands/misc/dl.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commands/misc/dl.js b/commands/misc/dl.js index 6a12ab9..60d209b 100644 --- a/commands/misc/dl.js +++ b/commands/misc/dl.js @@ -68,7 +68,7 @@ module.exports = { fs.rmSync(downloadsDir, {force: true, recursive: true}); }, - executeCommand(command, commandArgs, {verbose = false}) { + executeCommand(command, commandArgs, verbose=false) { if (typeof command !== 'string' || !Array.isArray(commandArgs)) return { error: true }; console.log("Executing:", command, commandArgs.join(" ")); try {