i2-cli-subscription-file (#16)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Closes kemitix/podal#2 Reviewed-on: #16 Co-authored-by: Paul Campbell <pcampbell@kemitix.net> Co-committed-by: Paul Campbell <pcampbell@kemitix.net>
This commit is contained in:
parent
304ae6740d
commit
d305a2bb1b
11 changed files with 46 additions and 12 deletions
7
Cargo.lock
generated
7
Cargo.lock
generated
|
@ -84,6 +84,12 @@ dependencies = [
|
||||||
"windows-sys",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anyhow"
|
||||||
|
version = "1.0.72"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "atom_syndication"
|
name = "atom_syndication"
|
||||||
version = "0.12.1"
|
version = "0.12.1"
|
||||||
|
@ -1039,6 +1045,7 @@ checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
|
||||||
name = "podal"
|
name = "podal"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
"atom_syndication",
|
"atom_syndication",
|
||||||
"bytes",
|
"bytes",
|
||||||
"clap",
|
"clap",
|
||||||
|
|
|
@ -11,6 +11,7 @@ reqwest = { version = "0.11.18", features = ["json", "blocking"] }
|
||||||
scraper = "0.17.1"
|
scraper = "0.17.1"
|
||||||
clap = {version = "4.3.19", features = ["derive"]}
|
clap = {version = "4.3.19", features = ["derive"]}
|
||||||
bytes = "1.4.0"
|
bytes = "1.4.0"
|
||||||
|
anyhow = "1.0.72"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tempfile = "*"
|
tempfile = "*"
|
||||||
|
|
|
@ -13,6 +13,14 @@ impl Error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl From<anyhow::Error> for Error {
|
||||||
|
fn from(value: anyhow::Error) -> Self {
|
||||||
|
Self {
|
||||||
|
details: value.to_string(),
|
||||||
|
source: value.source().unwrap().to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
impl From<Utf8Error> for Error {
|
impl From<Utf8Error> for Error {
|
||||||
fn from(value: Utf8Error) -> Self {
|
fn from(value: Utf8Error) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use anyhow::Context;
|
||||||
|
|
||||||
use crate::params::Args;
|
use crate::params::Args;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
@ -19,7 +21,9 @@ impl FileEnv {
|
||||||
Self {
|
Self {
|
||||||
open: Box::new(move |file_name| {
|
open: Box::new(move |file_name| {
|
||||||
let path = format!("{}/{}", &open_dir, file_name);
|
let path = format!("{}/{}", &open_dir, file_name);
|
||||||
let file = File::open(path)?;
|
let file = File::open(&path).with_context(|| {
|
||||||
|
format!("FileEnv::open: file_name={file_name}, path={path}")
|
||||||
|
})?;
|
||||||
Ok(file)
|
Ok(file)
|
||||||
}),
|
}),
|
||||||
append_line: Box::new(move |file_name, line| {
|
append_line: Box::new(move |file_name, line| {
|
||||||
|
|
|
@ -33,6 +33,7 @@ mod tests {
|
||||||
let file_env = FileEnv::create(&Args {
|
let file_env = FileEnv::create(&Args {
|
||||||
downloads: dir.path().to_string_lossy().to_string(),
|
downloads: dir.path().to_string_lossy().to_string(),
|
||||||
history: "downloaded.txt".to_string(),
|
history: "downloaded.txt".to_string(),
|
||||||
|
subscriptions: file_name.to_string(),
|
||||||
});
|
});
|
||||||
|
|
||||||
//when
|
//when
|
||||||
|
@ -55,6 +56,7 @@ mod tests {
|
||||||
let file_env = FileEnv::create(&Args {
|
let file_env = FileEnv::create(&Args {
|
||||||
downloads: dir.path().to_string_lossy().to_string(),
|
downloads: dir.path().to_string_lossy().to_string(),
|
||||||
history: "downloaded.txt".to_string(),
|
history: "downloaded.txt".to_string(),
|
||||||
|
subscriptions: file_name.to_string(),
|
||||||
});
|
});
|
||||||
|
|
||||||
//when
|
//when
|
||||||
|
@ -77,6 +79,7 @@ mod tests {
|
||||||
let file_env = FileEnv::create(&Args {
|
let file_env = FileEnv::create(&Args {
|
||||||
downloads: dir.path().to_string_lossy().to_string(),
|
downloads: dir.path().to_string_lossy().to_string(),
|
||||||
history: "downloaded.txt".to_string(),
|
history: "downloaded.txt".to_string(),
|
||||||
|
subscriptions: file_name.to_string(),
|
||||||
});
|
});
|
||||||
|
|
||||||
//when
|
//when
|
||||||
|
|
|
@ -42,6 +42,7 @@ mod tests {
|
||||||
&FileEnv::create(&Args {
|
&FileEnv::create(&Args {
|
||||||
downloads: dir.path().to_string_lossy().to_string(),
|
downloads: dir.path().to_string_lossy().to_string(),
|
||||||
history: "downloaded.txt".to_string(),
|
history: "downloaded.txt".to_string(),
|
||||||
|
subscriptions: "subscriptions.txt".to_string(),
|
||||||
}),
|
}),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
@ -76,6 +77,7 @@ mod tests {
|
||||||
&FileEnv::create(&Args {
|
&FileEnv::create(&Args {
|
||||||
downloads: dir.path().to_string_lossy().to_string(),
|
downloads: dir.path().to_string_lossy().to_string(),
|
||||||
history: "downloaded.txt".to_string(),
|
history: "downloaded.txt".to_string(),
|
||||||
|
subscriptions: "subscriptions.txt".to_string(),
|
||||||
}),
|
}),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,7 @@ mod test {
|
||||||
&FileEnv::create(&Args {
|
&FileEnv::create(&Args {
|
||||||
downloads: dir.path().to_string_lossy().to_string(),
|
downloads: dir.path().to_string_lossy().to_string(),
|
||||||
history: "downloaded.txt".to_string(),
|
history: "downloaded.txt".to_string(),
|
||||||
|
subscriptions: "subscriptions.txt".to_string(),
|
||||||
}),
|
}),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
@ -76,6 +77,7 @@ mod test {
|
||||||
&FileEnv::create(&Args {
|
&FileEnv::create(&Args {
|
||||||
downloads: dir.path().to_string_lossy().to_string(),
|
downloads: dir.path().to_string_lossy().to_string(),
|
||||||
history: "downloaded.txt".to_string(),
|
history: "downloaded.txt".to_string(),
|
||||||
|
subscriptions: "subscriptions.txt".to_string(),
|
||||||
}),
|
}),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
@ -111,6 +113,7 @@ mod test {
|
||||||
&FileEnv::create(&Args {
|
&FileEnv::create(&Args {
|
||||||
downloads: dir.path().to_string_lossy().to_string(),
|
downloads: dir.path().to_string_lossy().to_string(),
|
||||||
history: "downloaded.txt".to_string(),
|
history: "downloaded.txt".to_string(),
|
||||||
|
subscriptions: "subscriptions.txt".to_string(),
|
||||||
}),
|
}),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
|
14
src/lib.rs
14
src/lib.rs
|
@ -20,8 +20,8 @@ pub struct Env {
|
||||||
pub file: FileEnv,
|
pub file: FileEnv,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(subscriptions: &str, site: &str, a: &Args, e: Env) -> Result<()> {
|
pub fn run(site: &str, a: &Args, e: Env) -> Result<()> {
|
||||||
for channel_name in file::read::lines_from(subscriptions, &e.file)? {
|
for channel_name in file::read::lines_from(&a.subscriptions, &e.file)? {
|
||||||
println!("Channel: {}", channel_name);
|
println!("Channel: {}", channel_name);
|
||||||
let feed_url = feed::find(site, &channel_name, &e.network)?;
|
let feed_url = feed::find(site, &channel_name, &e.network)?;
|
||||||
for entry in feed::get(&feed_url, &e.network)?.entries() {
|
for entry in feed::get(&feed_url, &e.network)?.entries() {
|
||||||
|
@ -62,6 +62,8 @@ mod tests {
|
||||||
let subs_file_name = "subs";
|
let subs_file_name = "subs";
|
||||||
let subs_dir =
|
let subs_dir =
|
||||||
create_text_file(subs_file_name, "@channel1\nignore me\n@channel2".as_bytes())?;
|
create_text_file(subs_file_name, "@channel1\nignore me\n@channel2".as_bytes())?;
|
||||||
|
let subs_file_name = format!("{}/{}", subs_dir.path().to_string_lossy(), subs_file_name);
|
||||||
|
|
||||||
// one item from each channel is already listed in the downloads.txt file
|
// one item from each channel is already listed in the downloads.txt file
|
||||||
let history_file_name = "history";
|
let history_file_name = "history";
|
||||||
let history_dir = create_text_file(history_file_name, "c1-f2\nc2-f3".as_bytes())?;
|
let history_dir = create_text_file(history_file_name, "c1-f2\nc2-f3".as_bytes())?;
|
||||||
|
@ -74,6 +76,7 @@ mod tests {
|
||||||
let args = Args {
|
let args = Args {
|
||||||
downloads: subs_dir.path().to_string_lossy().to_string(),
|
downloads: subs_dir.path().to_string_lossy().to_string(),
|
||||||
history: history_file_name.clone(),
|
history: history_file_name.clone(),
|
||||||
|
subscriptions: subs_file_name.clone(),
|
||||||
};
|
};
|
||||||
let env = Env {
|
let env = Env {
|
||||||
network: NetworkEnv {
|
network: NetworkEnv {
|
||||||
|
@ -95,10 +98,7 @@ mod tests {
|
||||||
},
|
},
|
||||||
file: FileEnv {
|
file: FileEnv {
|
||||||
open: mock_file_open(HashMap::from([
|
open: mock_file_open(HashMap::from([
|
||||||
(
|
(subs_file_name.to_string(), subs_file_name),
|
||||||
subs_file_name.to_string(),
|
|
||||||
format!("{}/{}", subs_dir.path().to_string_lossy(), subs_file_name),
|
|
||||||
),
|
|
||||||
(history_file_name.to_string(), history_file_name),
|
(history_file_name.to_string(), history_file_name),
|
||||||
])),
|
])),
|
||||||
append_line: mock_file_append_line(),
|
append_line: mock_file_append_line(),
|
||||||
|
@ -106,7 +106,7 @@ mod tests {
|
||||||
};
|
};
|
||||||
|
|
||||||
//when
|
//when
|
||||||
run(subs_file_name, site, &args, env)?;
|
run(site, &args, env)?;
|
||||||
//then
|
//then
|
||||||
drop(subs_dir);
|
drop(subs_dir);
|
||||||
drop(history_dir);
|
drop(history_dir);
|
||||||
|
|
|
@ -6,13 +6,11 @@ use podal::prelude::*;
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
println!("Podal");
|
println!("Podal");
|
||||||
let subscriptions = "subscriptions.txt";
|
|
||||||
let site = "https://www.youtube.com/";
|
let site = "https://www.youtube.com/";
|
||||||
|
|
||||||
let args = Args::parse();
|
let args = Args::parse();
|
||||||
|
|
||||||
podal::run(
|
podal::run(
|
||||||
subscriptions,
|
|
||||||
site,
|
site,
|
||||||
&args,
|
&args,
|
||||||
podal::Env {
|
podal::Env {
|
||||||
|
|
|
@ -12,4 +12,9 @@ pub struct Args {
|
||||||
/// Defaults to "downloaded.txt" located in the downloads directory.
|
/// Defaults to "downloaded.txt" located in the downloads directory.
|
||||||
#[arg(long, default_value = "downloaded.txt")]
|
#[arg(long, default_value = "downloaded.txt")]
|
||||||
pub history: String,
|
pub history: String,
|
||||||
|
|
||||||
|
/// The name of the subscriptions file.
|
||||||
|
/// Defaults to "subscriptions.txt" located in the downloads directory.
|
||||||
|
#[arg(long, default_value = "subscriptions.txt")]
|
||||||
|
pub subscriptions: String,
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ use std::{
|
||||||
sync::mpsc::Sender,
|
sync::mpsc::Sender,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use anyhow::Context;
|
||||||
use tempfile::{tempdir, TempDir};
|
use tempfile::{tempdir, TempDir};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -63,10 +64,12 @@ pub fn mock_network_fetch_as_bytes_with_rss_entries(
|
||||||
pub fn mock_file_open(real_paths: HashMap<String, String>) -> FileOpenFn {
|
pub fn mock_file_open(real_paths: HashMap<String, String>) -> FileOpenFn {
|
||||||
Box::new(move |path: &str| {
|
Box::new(move |path: &str| {
|
||||||
if let Some(real_path) = real_paths.get(&path.to_string()) {
|
if let Some(real_path) = real_paths.get(&path.to_string()) {
|
||||||
Ok(File::open(real_path)?)
|
Ok(File::open(real_path).with_context(|| {
|
||||||
|
format!("test_utils/mock_file_open: path={path}, real_path={real_path}, path_map=[{:?}]", real_paths)
|
||||||
|
})?)
|
||||||
} else {
|
} else {
|
||||||
Err(Error::message(
|
Err(Error::message(
|
||||||
format!("Not implemented: file_open: {}", path).as_str(),
|
format!("Not implemented: test_utils/mock_file_open: {}", path).as_str(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
Loading…
Add table
Reference in a new issue