diff --git a/src/feed/find.rs b/src/feed/find.rs index bd910ed..81d71fd 100644 --- a/src/feed/find.rs +++ b/src/feed/find.rs @@ -2,8 +2,10 @@ use crate::prelude::*; use crate::network::{NetUrl, NetworkEnv}; -pub fn find(site: &str, channel_name: &str, e: &NetworkEnv) -> Result { - if let Some(channel_prefix) = channel_name.chars().next() { +use super::ChannelName; + +pub fn find(site: &str, channel_name: &ChannelName, e: &NetworkEnv) -> Result { + if let Some(channel_prefix) = channel_name.0.chars().next() { if channel_prefix != '@' { return Err(anyhow!( "Channel Name must begin with an '@': {}", @@ -51,7 +53,7 @@ mod tests { download_as_mp3: stub_network_download_as_mp3(), }; //when - let result = find("site", "@channel", &network_env)?; + let result = find("site", &ChannelName::from("@channel"), &network_env)?; //then assert_eq!(result, NetUrl::from("the-rss-url")); Ok(()) @@ -66,7 +68,11 @@ mod tests { download_as_mp3: stub_network_download_as_mp3(), }; //when - let result = find("site", "invalid-channel-name", &network_env); + let result = find( + "site", + &ChannelName::from("invalid-channel-name"), + &network_env, + ); //then assert!(result.is_err()); Ok(()) diff --git a/src/feed/mod.rs b/src/feed/mod.rs index bb655c6..266c5d5 100644 --- a/src/feed/mod.rs +++ b/src/feed/mod.rs @@ -12,3 +12,16 @@ pub fn get(url: &NetUrl, e: &NetworkEnv) -> Result { let channel = Feed::read_from(&content[..]).context("Could not parse RSS feed")?; Ok(channel) } + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct ChannelName(pub String); +impl ChannelName { + pub fn from(channel_name: &str) -> Self { + Self(channel_name.to_string()) + } +} +impl std::fmt::Display for ChannelName { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0.as_str()) + } +} diff --git a/src/file/read.rs b/src/file/read.rs index 0c1dea0..5d26a67 100644 --- a/src/file/read.rs +++ b/src/file/read.rs @@ -1,15 +1,15 @@ -use crate::prelude::*; +use crate::{feed::ChannelName, prelude::*}; use crate::file::FileEnv; use std::io::{BufRead, BufReader}; -pub fn lines_from(file_name: &str, e: &FileEnv) -> Result> { +pub fn lines_from(file_name: &str, e: &FileEnv) -> Result> { let file = (e.open)(file_name).context(format!("Opening file: {file_name}"))?; let reader = BufReader::new(file); let mut lines = vec![]; for line in reader.lines().flatten() { if line.starts_with('@') { - lines.push(line); + lines.push(ChannelName(line)); } } Ok(lines) @@ -41,7 +41,13 @@ mod tests { //then drop(dir); - assert_eq!(result, ["@sub1", "@sub2", "@sub3"]); + assert_eq!( + result, + ["@sub1", "@sub2", "@sub3"] + .into_iter() + .map(ChannelName::from) + .collect::>() + ); Ok(()) } @@ -64,7 +70,13 @@ mod tests { //then drop(dir); - assert_eq!(result, ["@sub1", "@sub2", "@sub3"]); + assert_eq!( + result, + ["@sub1", "@sub2", "@sub3"] + .into_iter() + .map(ChannelName::from) + .collect::>() + ); Ok(()) } @@ -87,7 +99,13 @@ mod tests { //then drop(dir); - assert_eq!(result, ["@sub1", "@sub3"]); + assert_eq!( + result, + ["@sub1", "@sub3"] + .into_iter() + .map(ChannelName::from) + .collect::>() + ); Ok(()) } } diff --git a/src/lib.rs b/src/lib.rs index 6bd8f82..50ab77e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,7 +34,7 @@ pub fn run(site: &str, a: &Args, e: Env) -> Result<()> { if let Some(link) = entry.links().first() { if !history::find(link, &a.history, &e.file).context("Finding history")? { println!("Downloading {}: {}", &channel_name, entry.title().as_str()); - (e.network.download_as_mp3)(&NetUrl(link.href.clone())) + (e.network.download_as_mp3)(&NetUrl(link.href.clone()), &channel_name) .context("Downloading as MP3")?; history::add(link, &a.history, &e.file).context("Adding to history")?; } diff --git a/src/network/env.rs b/src/network/env.rs index 65663cc..0aa4eb2 100644 --- a/src/network/env.rs +++ b/src/network/env.rs @@ -1,6 +1,6 @@ use std::process::Command; -use crate::prelude::*; +use crate::{feed::ChannelName, prelude::*}; #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct NetUrl(pub String); @@ -19,7 +19,7 @@ pub type NetworkFetchAsTextFn = Box Result>; pub type NetworkFetchAsBytesFn = Box Result>; -pub type NetworkDownloadAsMp3Fn = Box Result<()>>; +pub type NetworkDownloadAsMp3Fn = Box Result<()>>; pub struct NetworkEnv { pub fetch_as_text: NetworkFetchAsTextFn, @@ -41,12 +41,14 @@ impl Default for NetworkEnv { .bytes() .context(format!("Parsing bytes from body of response for {}", url)) }), - download_as_mp3: Box::new(|url| { + download_as_mp3: Box::new(|url, channel_name| { let cmd = "yt-dlp"; let output = Command::new(cmd) .arg("--extract-audio") .arg("--audio-format") .arg("mp3") + .arg("-p") + .arg(format!("~/Music/{}", channel_name)) .arg(&url.0) .output() .with_context(|| { diff --git a/src/test_utils.rs b/src/test_utils.rs index 60eff79..779da72 100644 --- a/src/test_utils.rs +++ b/src/test_utils.rs @@ -11,6 +11,7 @@ use anyhow::Context; use tempfile::{tempdir, TempDir}; use crate::{ + feed::ChannelName, file::{FileAppendLineFn, FileOpenFn}, network::{NetUrl, NetworkDownloadAsMp3Fn, NetworkFetchAsBytesFn, NetworkFetchAsTextFn}, prelude::*, @@ -70,7 +71,7 @@ pub fn mock_file_open(real_paths: HashMap) -> FileOpenFn { } pub fn mock_network_download_as_mp3(tx: Sender) -> NetworkDownloadAsMp3Fn { - Box::new(move |url: &NetUrl| { + Box::new(move |url: &NetUrl, _channel_name: &ChannelName| { tx.send(url.clone())?; Ok(()) }) @@ -84,5 +85,11 @@ pub fn stub_network_fetch_as_bytes() -> NetworkFetchAsBytesFn { Box::new(|url: &NetUrl| Err(anyhow!("Not implemented: network_fetch_as_bytes: {}", url))) } pub fn stub_network_download_as_mp3() -> NetworkDownloadAsMp3Fn { - Box::new(|url: &NetUrl| Err(anyhow!("Not implemented: network_download_as_mp3: {}", url))) + Box::new(|url: &NetUrl, channel_name: &ChannelName| { + Err(anyhow!( + "Not implemented: network_download_as_mp3: ({}) {}", + channel_name, + url, + )) + }) }