// https://www.phind.com/agent?cache=clke9xk39001cmj085upzho1t use std::fs::File; use atom_syndication::{Entry, Feed, Link}; mod errors; mod feed; pub mod prelude; use prelude::*; pub fn run(subscriptions: &str, history: &str, site: &str) -> Result<()> { for channel_name in lines_from(subscriptions)? { let channel_name = channel_name?; println!("Channel: {}", channel_name); let feed_url = feed::get_feed_url(site, &channel_name)?; for entry in get_feed(feed_url)?.entries() { if let Some(link) = get_link(entry) { if !is_already_downloaded(&link, history)? { println!("Downloading {}: {}", &channel_name, entry.title().as_str()); download_audio(&link)?; mark_as_downloaded(&link, history)?; } } } } Ok(()) } fn get_link(item: &Entry) -> Option { item.links().get(0).cloned() } // read list of rss feed URLs from file 'feeds.txt' fn lines_from(file_name: &str) -> Result>> { use std::io::{BufRead, BufReader}; let file = File::open(file_name)?; let reader = BufReader::new(file); Ok(reader.lines()) } // fetch the RSS feed fn get_feed(url: String) -> Result { let content = reqwest::blocking::get(url)?.bytes()?; let channel = Feed::read_from(&content[..])?; Ok(channel) } fn is_already_downloaded(link: &Link, file_name: &str) -> Result { use std::io::{BufRead, BufReader}; if let Ok(file) = File::open(file_name) { let reader = BufReader::new(file); for line in reader.lines() { if line? == link.href { return Ok(true); // is already downloaded } } } Ok(false) // is not already downloaded } fn download_audio(link: &Link) -> Result<()> { use std::process::Command; let cmd = "yt-dlp"; // println!("{} --extract-audio --audio-format mp3 {}", cmd, &link.href); let output = Command::new(cmd) .arg("--extract-audio") .arg("--audio-format") .arg("mp3") .arg(&link.href) .output()?; if !output.stderr.is_empty() { eprintln!("Error: {}", String::from_utf8(output.stderr)?); println!("{}", String::from_utf8(output.stdout)?); } Ok(()) } fn mark_as_downloaded(link: &Link, file_name: &str) -> Result<()> { use std::fs::OpenOptions; use std::io::prelude::*; let mut file = OpenOptions::new() .write(true) .append(true) .create(true) .open(file_name) .unwrap(); writeln!(file, "{}", link.href)?; Ok(()) }