mirror of
https://github.com/narrrl/ytd-rs.git
synced 2026-11-03 16:41:27 +01:00
reimplemented the result with errors
This commit is contained in:
1 parent
116f5ae314
commit
247b5b942d
4 files changed
+38
-107
No files matched your search
+2
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "ytd-rs"
|
name = "ytd-rs"
|
||||||
version = "0.1.5"
|
version = "0.1.6"
|
||||||
authors = ["Nils Pukropp <nils.pukropp@outlook.de>"]
|
authors = ["Nils Pukropp <nils.pukropp@outlook.de>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
license-file ="LICENSE"
|
license-file ="LICENSE"
|
||||||
@@ -16,3 +16,4 @@ youtube-dlc = []
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
regex = "1.5"
|
regex = "1.5"
|
||||||
|
thiserror = "1.0"
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
This is a simple wrapper for [youtube-dl](https://youtube-dl.org/) in rust.
|
This is a simple wrapper for [youtube-dl](https://youtube-dl.org/) in rust.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use ytd_rs::{YoutubeDL, ResultType, Arg};
|
use ytd_rs::{YoutubeDL, Arg};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
fn main() -> Result<(), Box<dyn Error>> {
|
fn main() -> Result<(), Box<dyn Error>> {
|
||||||
@@ -18,14 +18,10 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
let ytd = YoutubeDL::new(&path, args, link)?;
|
let ytd = YoutubeDL::new(&path, args, link)?;
|
||||||
|
|
||||||
// start download
|
// start download
|
||||||
let download = ytd.download();
|
let download = ytd.download()?;
|
||||||
|
|
||||||
// check what the result is and print out the path to the download or the error
|
// print out the download path
|
||||||
match download.result_type() {
|
println!("Your download: {}", download.output_dir().to_string_lossy())
|
||||||
ResultType::SUCCESS => println!("Your download: {}", download.output_dir().to_string_lossy()),
|
|
||||||
ResultType::IOERROR | ResultType::FAILURE =>
|
|
||||||
println!("Couldn't start download: {}", download.output()),
|
|
||||||
};
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
|
#[derive(Error, Debug)]
|
||||||
|
pub enum YoutubeDLError {
|
||||||
|
#[error("failed to execute youtube-dl")]
|
||||||
|
IOError(#[from] std::io::Error),
|
||||||
|
#[error("failed to convert path")]
|
||||||
|
UTF8Error(#[from] std::string::FromUtf8Error),
|
||||||
|
#[error("youtube-dl exited with: {0}")]
|
||||||
|
Failure(String),
|
||||||
|
}
|
||||||
+21
-98
@@ -3,7 +3,7 @@
|
|||||||
//! # Example
|
//! # Example
|
||||||
//!
|
//!
|
||||||
//! ```no_run
|
//! ```no_run
|
||||||
//! use ytd_rs::{YoutubeDL, ResultType, Arg};
|
//! use ytd_rs::{YoutubeDL, Arg};
|
||||||
//! use std::path::PathBuf;
|
//! use std::path::PathBuf;
|
||||||
//! use std::error::Error;
|
//! use std::error::Error;
|
||||||
//! fn main() -> Result<(), Box<dyn Error>> {
|
//! fn main() -> Result<(), Box<dyn Error>> {
|
||||||
@@ -15,20 +15,16 @@
|
|||||||
//! let ytd = YoutubeDL::new(&path, args, link)?;
|
//! let ytd = YoutubeDL::new(&path, args, link)?;
|
||||||
//!
|
//!
|
||||||
//! // start download
|
//! // start download
|
||||||
//! let download = ytd.download();
|
//! let download = ytd.download()?;
|
||||||
//!
|
//!
|
||||||
//! // check what the result is and print out the path to the download or the error
|
//! // check what the result is and print out the path to the download or the error
|
||||||
//! match download.result_type() {
|
//! println!("Your download: {}", download.output_dir().to_string_lossy());
|
||||||
//! ResultType::SUCCESS => println!("Your download: {}", download.output_dir().to_string_lossy()),
|
|
||||||
//! ResultType::IOERROR | ResultType::FAILURE =>
|
|
||||||
//! println!("Couldn't start download: {}", download.output()),
|
|
||||||
//! };
|
|
||||||
//! Ok(())
|
//! Ok(())
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
|
use error::YoutubeDLError;
|
||||||
use std::{
|
use std::{
|
||||||
error::Error,
|
|
||||||
fmt,
|
fmt,
|
||||||
process::{Output, Stdio},
|
process::{Output, Stdio},
|
||||||
};
|
};
|
||||||
@@ -39,6 +35,7 @@ use std::{
|
|||||||
};
|
};
|
||||||
use std::{path::Path, process::Command};
|
use std::{path::Path, process::Command};
|
||||||
|
|
||||||
|
pub mod error;
|
||||||
type Result<T> = std::result::Result<T, YoutubeDLError>;
|
type Result<T> = std::result::Result<T, YoutubeDLError>;
|
||||||
|
|
||||||
const YOUTUBE_DL_COMMAND: &str = if cfg!(feature = "youtube-dlc") {
|
const YOUTUBE_DL_COMMAND: &str = if cfg!(feature = "youtube-dlc") {
|
||||||
@@ -98,31 +95,6 @@ impl Display for Arg {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct YoutubeDLError {
|
|
||||||
message: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl YoutubeDLError {
|
|
||||||
pub fn new(message: &str) -> YoutubeDLError {
|
|
||||||
YoutubeDLError {
|
|
||||||
message: message.to_string(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for YoutubeDLError {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
write!(f, "{}", self.message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Error for YoutubeDLError {
|
|
||||||
fn description(&self) -> &str {
|
|
||||||
self.message.as_ref()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Structure that represents a youtube-dl task.
|
/// Structure that represents a youtube-dl task.
|
||||||
///
|
///
|
||||||
/// Every task needs a download location, a list of ['Arg'] that can be empty
|
/// Every task needs a download location, a list of ['Arg'] that can be empty
|
||||||
@@ -144,7 +116,6 @@ pub struct YoutubeDL {
|
|||||||
pub struct YoutubeDLResult {
|
pub struct YoutubeDLResult {
|
||||||
path: PathBuf,
|
path: PathBuf,
|
||||||
output: String,
|
output: String,
|
||||||
kind: ResultType,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl YoutubeDLResult {
|
impl YoutubeDLResult {
|
||||||
@@ -153,15 +124,9 @@ impl YoutubeDLResult {
|
|||||||
YoutubeDLResult {
|
YoutubeDLResult {
|
||||||
path: path.clone(),
|
path: path.clone(),
|
||||||
output: String::new(),
|
output: String::new(),
|
||||||
kind: ResultType::FAILURE,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// get the exit status of the process
|
|
||||||
pub fn result_type(&self) -> &ResultType {
|
|
||||||
&self.kind
|
|
||||||
}
|
|
||||||
|
|
||||||
/// get the output of the youtube-dl process
|
/// get the output of the youtube-dl process
|
||||||
pub fn output(&self) -> &str {
|
pub fn output(&self) -> &str {
|
||||||
&self.output
|
&self.output
|
||||||
@@ -173,14 +138,6 @@ impl YoutubeDLResult {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents the different exit types of the [`YoutubeDL`] process
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub enum ResultType {
|
|
||||||
SUCCESS,
|
|
||||||
FAILURE,
|
|
||||||
IOERROR,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl YoutubeDL {
|
impl YoutubeDL {
|
||||||
/// Creates a new YoutubeDL job to be executed.
|
/// Creates a new YoutubeDL job to be executed.
|
||||||
/// It takes a path where youtube-dl should be executed, a vec! of [`Arg`] that can be empty
|
/// It takes a path where youtube-dl should be executed, a vec! of [`Arg`] that can be empty
|
||||||
@@ -198,31 +155,20 @@ impl YoutubeDL {
|
|||||||
// check if it already exists
|
// check if it already exists
|
||||||
if !path.exists() {
|
if !path.exists() {
|
||||||
// if not create
|
// if not create
|
||||||
if let Err(why) = create_dir_all(&path) {
|
create_dir_all(&path)?;
|
||||||
return Err(YoutubeDLError::new(
|
|
||||||
format!(
|
|
||||||
"Error while creating directories {}: {:?}",
|
|
||||||
dl_path.to_string_lossy(),
|
|
||||||
why
|
|
||||||
)
|
|
||||||
.as_ref(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// return error if no directory
|
// return error if no directory
|
||||||
if !path.is_dir() {
|
if !path.is_dir() {
|
||||||
return Err(YoutubeDLError::new("Error: path is not a directory"));
|
return Err(YoutubeDLError::IOError(std::io::Error::new(
|
||||||
|
std::io::ErrorKind::Other,
|
||||||
|
"path is not a directory",
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// absolute path
|
// absolute path
|
||||||
match canonicalize(dl_path) {
|
let path = canonicalize(dl_path)?;
|
||||||
// return new youtube-dl job
|
Ok(YoutubeDL { path, links, args })
|
||||||
Ok(path) => Ok(YoutubeDL { path, links, args }),
|
|
||||||
Err(why) => Err(YoutubeDLError::new(
|
|
||||||
format!("Error creating YouTubeDL: {:?}", why).as_ref(),
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(dl_path: &PathBuf, args: Vec<Arg>, link: &str) -> Result<YoutubeDL> {
|
pub fn new(dl_path: &PathBuf, args: Vec<Arg>, link: &str) -> Result<YoutubeDL> {
|
||||||
@@ -230,27 +176,16 @@ impl YoutubeDL {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Starts the download and returns when finished the result as [`YoutubeDLResult`].
|
/// Starts the download and returns when finished the result as [`YoutubeDLResult`].
|
||||||
pub fn download(&self) -> YoutubeDLResult {
|
pub fn download(&self) -> Result<YoutubeDLResult> {
|
||||||
let pr_result = self.spawn_youtube_dl();
|
let output = self.spawn_youtube_dl()?;
|
||||||
let mut result = YoutubeDLResult::new(&self.path);
|
let mut result = YoutubeDLResult::new(&self.path);
|
||||||
|
|
||||||
let output = match pr_result {
|
if !output.status.success() {
|
||||||
Err(why) => {
|
return Err(YoutubeDLError::Failure(String::from_utf8(output.stderr)?));
|
||||||
result.output = why.to_string();
|
|
||||||
result.kind = ResultType::IOERROR;
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
Ok(output) => output,
|
result.output = String::from_utf8(output.stdout)?;
|
||||||
};
|
|
||||||
|
|
||||||
if output.status.success() {
|
Ok(result)
|
||||||
result.kind = ResultType::SUCCESS;
|
|
||||||
result.output = String::from_utf8_lossy(&output.stdout).to_string();
|
|
||||||
} else {
|
|
||||||
result.output = String::from_utf8_lossy(&output.stderr).to_string();
|
|
||||||
}
|
|
||||||
|
|
||||||
result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn spawn_youtube_dl(&self) -> Result<Output> {
|
fn spawn_youtube_dl(&self) -> Result<Output> {
|
||||||
@@ -271,20 +206,8 @@ impl YoutubeDL {
|
|||||||
cmd.arg(&link);
|
cmd.arg(&link);
|
||||||
}
|
}
|
||||||
|
|
||||||
let pr = match cmd.spawn() {
|
let pr = cmd.spawn()?;
|
||||||
Err(why) => {
|
Ok(pr.wait_with_output()?)
|
||||||
return Err(YoutubeDLError::new(
|
|
||||||
format!("Error, YoutubeDL exited with {:?}", why).as_ref(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
Ok(process) => process,
|
|
||||||
};
|
|
||||||
match pr.wait_with_output() {
|
|
||||||
Ok(output) => Ok(output),
|
|
||||||
Err(why) => Err(YoutubeDLError::new(
|
|
||||||
format!("Error, YoutubeDL exited with {:?}", why).as_ref(),
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -306,7 +229,7 @@ mod tests {
|
|||||||
)?;
|
)?;
|
||||||
|
|
||||||
let regex = Regex::new(r"\d{4}\.\d{2}\.\d{2}")?;
|
let regex = Regex::new(r"\d{4}\.\d{2}\.\d{2}")?;
|
||||||
let output = ytd.download();
|
let output = ytd.download()?;
|
||||||
|
|
||||||
// check output
|
// check output
|
||||||
// fails if youtube-dl is not installed
|
// fails if youtube-dl is not installed
|
||||||
|
|||||||
Reference in new issue
Block a user