2023-07-25 10:33:41 +01:00
|
|
|
// https://www.phind.com/agent?cache=clke9xk39001cmj085upzho1t
|
|
|
|
|
2023-07-25 10:36:08 +01:00
|
|
|
use std::fs::File;
|
2023-07-25 10:33:41 +01:00
|
|
|
|
2023-07-25 10:50:00 +01:00
|
|
|
use atom_syndication::{Entry, Link};
|
2023-07-25 10:33:41 +01:00
|
|
|
|
2023-07-25 10:36:08 +01:00
|
|
|
mod errors;
|
2023-07-25 10:46:47 +01:00
|
|
|
mod feed;
|
|
|
|
pub mod prelude;
|
2023-07-25 10:33:41 +01:00
|
|
|
|
2023-07-25 10:46:47 +01:00
|
|
|
use prelude::*;
|
2023-07-25 10:33:41 +01:00
|
|
|
|
|
|
|
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);
|
2023-07-25 10:46:47 +01:00
|
|
|
let feed_url = feed::get_feed_url(site, &channel_name)?;
|
2023-07-25 10:50:00 +01:00
|
|
|
for entry in feed::get_feed(feed_url)?.entries() {
|
2023-07-25 10:33:41 +01:00
|
|
|
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<Link> {
|
|
|
|
item.links().get(0).cloned()
|
|
|
|
}
|
|
|
|
|
|
|
|
// read list of rss feed URLs from file 'feeds.txt'
|
|
|
|
fn lines_from(file_name: &str) -> Result<std::io::Lines<std::io::BufReader<std::fs::File>>> {
|
|
|
|
use std::io::{BufRead, BufReader};
|
|
|
|
|
|
|
|
let file = File::open(file_name)?;
|
|
|
|
let reader = BufReader::new(file);
|
|
|
|
Ok(reader.lines())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn is_already_downloaded(link: &Link, file_name: &str) -> Result<bool> {
|
|
|
|
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(())
|
|
|
|
}
|