From a34ee4ac83a4aa1521f0a46daa7e244cbcc4cc4c Mon Sep 17 00:00:00 2001 From: D1G1T4L3CH0 Date: Mon, 20 May 2024 19:38:18 -0400 Subject: [PATCH] Initial commit --- .gitignore | 1 + Cargo.lock | 7 ++++ Cargo.toml | 8 ++++ README.MD | 22 +++++++++++ src/main.rs | 107 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 145 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 README.MD create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..a9b3736 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "dlyt" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..64fbe40 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "dlyt" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/README.MD b/README.MD new file mode 100644 index 0000000..d7498bb --- /dev/null +++ b/README.MD @@ -0,0 +1,22 @@ +# Summary + +Dylt is a video downloader that fetches videos from provided URLs or YouTube playlists using `yt-dlp` and `ffmpeg`, and organizes them into directories based on the source file of the URLs. + +Dylt is primarily used for downloading and organizing videos from the internet. It operates by reading URLs from `.urls` files located in a directory named `urls`. Each URL corresponds to a video or a YouTube playlist that Dylt will download using the `yt-dlp` and `ffmpeg` tools. + +Dylt first checks if a directory named `urls` exists. If it doesn't, it creates the directory and a default file named `default.urls` inside it. The user can add URLs or YouTube playlist links to this file for downloading videos. + +Dylt then reads all the `.urls` files in the `urls` directory. For each URL that doesn't start with '#', it downloads the video or all the videos in the playlist. The downloaded videos are stored in a directory named `videos`. If the `.urls` file is named `default.urls`, the videos are downloaded directly into the `videos` directory. Otherwise, they are downloaded into a subdirectory of `videos` with the same name as the `.urls` file. + +In summary, Dylt is a handy tool for batch downloading and organizing videos from the internet. It requires the user to provide the URLs of the videos or YouTube playlists in `.urls` files, and it takes care of the rest. It's particularly useful for users who frequently download videos and want an automated and organized way to do so. + +# Instructions for Use + +1. Ensure that `yt-dlp` and `ffmpeg` are installed on your system. If not, follow the instructions provided by Dylt to install these dependencies. +2. Run Dylt. If the `urls` directory does not exist, Dylt will create it along with a `default.urls` file. +3. Add the URLs of the videos or YouTube playlists you want to download to the `default.urls` file or to a new `.urls` file in the `urls` directory. Each URL should be on a new line. Lines starting with '#' are considered comments and are ignored. +4. Run Dylt again. It will download the videos from the URLs provided in the `.urls` files and store them in the `videos` directory or its subdirectories. +5. Enjoy your downloaded videos! + +Please remember to replace the placeholders in the URLs with actual values before running Dylt. Happy downloading! + diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..919f2de --- /dev/null +++ b/src/main.rs @@ -0,0 +1,107 @@ +use std::fs::{self, File}; +use std::io::{self, BufRead, Write}; +use std::path::{Path, PathBuf}; +use std::process::{exit, Command}; + +fn main() -> io::Result<()> { + // Check for yt-dlp and ffmpeg dependencies + if !command_exists("yt-dlp") || !command_exists("ffmpeg") { + println!("The required dependencies yt-dlp and ffmpeg are not installed."); + println!("Please install them before running this program."); + println!("On Linux, you can use the following commands:"); + println!("sudo curl -L https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp -o /usr/local/bin/yt-dlp"); + println!("sudo chmod a+rx /usr/local/bin/yt-dlp"); + println!("sudo apt-get install ffmpeg"); + println!("On Windows, you can download the executables and add them to your PATH:"); + println!("yt-dlp: https://github.com/yt-dlp/yt-dlp/releases/latest"); + println!("ffmpeg: https://www.gyan.dev/ffmpeg/builds/"); + return Ok(()); + } + + let dir_path = "urls"; + let base_dir = "videos"; + let archive_file = "downloaded.txt"; + + if !Path::new(dir_path).exists() { + fs::create_dir(dir_path)?; + println!("Created directory: {}. You can create your own .urls files in this directory. The name of the file will be used as the subdirectory for the downloaded videos.", dir_path); + + let default_file = Path::new(dir_path).join("default.urls"); + let mut file = File::create(&default_file)?; + writeln!(file, "# Add your URLs here, one per line. This is the default file, videos will be downloaded to the base directory.")?; + println!("Created file: {}. You can add URLs to this file for downloading videos. For different subdirectories, create a new .urls file with the name of the subdirectory.", default_file.display()); + + exit(0); + } + + let default_file = Path::new(dir_path).join("default.urls"); + if !default_file.exists() { + let mut file = File::create(&default_file)?; + writeln!(file, "# Add your URLs here, one per line. This is the default file, videos will be downloaded to the base directory.")?; + println!("Created file: {}. You can add URLs to this file for downloading videos. For different subdirectories, create a new .urls file with the name of the subdirectory.", default_file.display()); + exit(0); + } + + let mut urls_exist = false; + + for entry in fs::read_dir(dir_path)? { + let entry = entry?; + let path = entry.path(); + if path.is_file() { + let file_stem = path.file_stem().unwrap().to_str().unwrap(); + let output_dir = if file_stem == "default" { + PathBuf::from(base_dir) + } else { + PathBuf::from(base_dir).join(file_stem) + }; + fs::create_dir_all(&output_dir)?; + + let file = File::open(&path)?; + let reader = io::BufReader::new(file); + + for line in reader.lines() { + let url = line?; + if !url.starts_with('#') { + urls_exist = true; + break; + } + } + + if urls_exist { + let status = Command::new("yt-dlp") + .arg("-a") + .arg(path.to_str().unwrap()) + .arg("--download-archive") + .arg(archive_file) + .arg("-f") + .arg("bestvideo+bestaudio") + .arg("--prefer-ffmpeg") + .arg("--write-description") + .arg("--add-metadata") + .arg("--write-auto-sub") + .arg("--embed-subs") + .arg("-o") + .arg(output_dir.join("%(title)s.%(ext)s").to_str().unwrap()) + .status()?; + + println!("Download finished with exit status: {}", status); + } + } + } + + if !urls_exist { + println!("No URLs found in the .urls files. Please add URLs to the .urls files for downloading videos. Each URL should be on a new line. Lines starting with '#' are considered comments and are ignored."); + } + + fn command_exists(cmd: &str) -> bool { + let output = if cfg!(target_os = "windows") { + Command::new("where").arg("/Q").arg(cmd).output() + } else { + Command::new("which").arg(cmd).output() + }; + + output.map_or(false, |o| o.status.success()) + } + + Ok(()) +}