f4-dir-per-channel #21
6 changed files with 62 additions and 16 deletions
|
@ -2,8 +2,10 @@ use crate::prelude::*;
|
|||
|
||||
use crate::network::{NetUrl, NetworkEnv};
|
||||
|
||||
pub fn find(site: &str, channel_name: &str, e: &NetworkEnv) -> Result<NetUrl> {
|
||||
if let Some(channel_prefix) = channel_name.chars().next() {
|
||||
use super::ChannelName;
|
||||
|
||||
pub fn find(site: &str, channel_name: &ChannelName, e: &NetworkEnv) -> Result<NetUrl> {
|
||||
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(())
|
||||
|
|
|
@ -12,3 +12,16 @@ pub fn get(url: &NetUrl, e: &NetworkEnv) -> Result<Feed> {
|
|||
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())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<Vec<String>> {
|
||||
pub fn lines_from(file_name: &str, e: &FileEnv) -> Result<Vec<ChannelName>> {
|
||||
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::<Vec<ChannelName>>()
|
||||
);
|
||||
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::<Vec<ChannelName>>()
|
||||
);
|
||||
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::<Vec<ChannelName>>()
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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")?;
|
||||
}
|
||||
|
|
|
@ -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<dyn Fn(&NetUrl) -> Result<String>>;
|
|||
|
||||
pub type NetworkFetchAsBytesFn = Box<dyn Fn(&NetUrl) -> Result<bytes::Bytes>>;
|
||||
|
||||
pub type NetworkDownloadAsMp3Fn = Box<dyn Fn(&NetUrl) -> Result<()>>;
|
||||
pub type NetworkDownloadAsMp3Fn = Box<dyn Fn(&NetUrl, &ChannelName) -> 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(|| {
|
||||
|
|
|
@ -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<String, String>) -> FileOpenFn {
|
|||
}
|
||||
|
||||
pub fn mock_network_download_as_mp3(tx: Sender<NetUrl>) -> 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,
|
||||
))
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue