2024-01-11 17:30:55 +11:00
|
|
|
mod rss;
|
2025-09-21 09:07:18 +10:00
|
|
|
mod sync;
|
2024-01-11 17:30:55 +11:00
|
|
|
mod input;
|
2025-09-01 10:07:28 +10:00
|
|
|
mod manage;
|
2025-08-29 21:46:22 +10:00
|
|
|
mod folders;
|
2025-09-01 10:07:28 +10:00
|
|
|
mod playlist;
|
2024-01-11 17:30:55 +11:00
|
|
|
mod download;
|
|
|
|
|
|
2024-11-18 21:44:36 +11:00
|
|
|
use input::{Command, ListenStatus};
|
|
|
|
|
|
2024-01-11 17:30:55 +11:00
|
|
|
use std::fs;
|
|
|
|
|
|
|
|
|
|
use anyhow::Context;
|
|
|
|
|
|
|
|
|
|
fn main() -> anyhow::Result<()> {
|
|
|
|
|
|
|
|
|
|
let args = {
|
|
|
|
|
use clap::Parser;
|
|
|
|
|
input::Args::parse()
|
|
|
|
|
};
|
|
|
|
|
|
2025-08-29 21:46:22 +10:00
|
|
|
let config: input::Config = {
|
2024-01-11 17:30:55 +11:00
|
|
|
let config = fs::read_to_string(&args.config)
|
2024-01-21 13:48:08 +11:00
|
|
|
.context("failed to read in podcast configuration file")?;
|
2024-01-11 17:30:55 +11:00
|
|
|
|
|
|
|
|
toml::from_str(&config[..])?
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let config_path = args.config.canonicalize()?;
|
|
|
|
|
let Some(root) = config_path.parent() else {
|
|
|
|
|
anyhow::bail!("could not get parent of configuration path for root directory")
|
|
|
|
|
};
|
|
|
|
|
|
2024-11-18 21:44:36 +11:00
|
|
|
match args.command {
|
|
|
|
|
Command::Download { podcast } => {
|
|
|
|
|
// Updating single podcast
|
|
|
|
|
if let Some(alias) = podcast {
|
2025-09-21 09:07:18 +10:00
|
|
|
if let Some(source) = config.podcasts.get(&alias) {
|
|
|
|
|
download::update_podcast(&alias, root, source)?;
|
2024-11-18 21:44:36 +11:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
anyhow::bail!(r#"podcast "{}" not found in configuration file"#, alias)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Updating all podcasts
|
|
|
|
|
else {
|
2025-09-21 09:07:18 +10:00
|
|
|
for (alias, source) in config.podcasts {
|
|
|
|
|
download::update_podcast(&alias, root, &source)?;
|
2024-11-18 21:44:36 +11:00
|
|
|
}
|
|
|
|
|
}
|
2025-09-21 09:07:18 +10:00
|
|
|
}
|
2024-11-18 21:44:36 +11:00
|
|
|
Command::List { status, podcast } => {
|
2025-08-29 21:46:22 +10:00
|
|
|
let output = folders::podcast_folder(root, &podcast);
|
2025-09-21 09:07:18 +10:00
|
|
|
let spec_file = output.join(folders::SPEC_FILE);
|
2024-11-18 21:44:36 +11:00
|
|
|
|
2025-09-01 10:07:28 +10:00
|
|
|
let spec = manage::Specification::read_from(&spec_file)?;
|
2024-11-18 21:44:36 +11:00
|
|
|
|
|
|
|
|
for (_, episodes) in spec.feed_iter() {
|
|
|
|
|
for episode in episodes {
|
|
|
|
|
if status.is_none()
|
|
|
|
|
|| (episode.listened && status.is_some_and(|x| x == ListenStatus::Listened))
|
|
|
|
|
|| (!episode.listened && status.is_some_and(|x| x == ListenStatus::Unlistened)) {
|
|
|
|
|
println!("{}", episode.title())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-09-21 09:07:18 +10:00
|
|
|
}
|
2024-11-18 21:44:36 +11:00
|
|
|
Command::Mark { status, podcast } => {
|
2025-08-29 21:46:22 +10:00
|
|
|
let output = folders::podcast_folder(root, &podcast);
|
2025-09-21 09:07:18 +10:00
|
|
|
let spec_file = output.join(folders::SPEC_FILE);
|
2024-11-18 21:44:36 +11:00
|
|
|
|
2025-09-01 10:07:28 +10:00
|
|
|
let mut spec = manage::Specification::read_from(&spec_file)?;
|
2024-11-18 21:44:36 +11:00
|
|
|
|
|
|
|
|
for (_, episodes) in spec.feed_iter_mut() {
|
|
|
|
|
for episode in episodes {
|
|
|
|
|
episode.listened = status == ListenStatus::Listened;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
spec.write_to(&spec_file)?;
|
2025-09-21 09:07:18 +10:00
|
|
|
}
|
2025-09-01 09:42:15 +10:00
|
|
|
Command::Playlist { podcast } => {
|
|
|
|
|
if let Some(alias) = podcast {
|
2025-09-02 11:04:27 +10:00
|
|
|
playlist::generate_podcast_m3u(alias.as_str(), root, false)?;
|
|
|
|
|
playlist::generate_podcast_m3u(alias.as_str(), root, true)?;
|
2025-09-01 09:42:15 +10:00
|
|
|
} else {
|
|
|
|
|
for (alias, _) in &config.podcasts {
|
2025-09-02 11:04:27 +10:00
|
|
|
playlist::generate_podcast_m3u(alias.as_str(), root, true)?;
|
|
|
|
|
playlist::generate_podcast_m3u(alias.as_str(), root, false)?;
|
2025-08-29 21:33:20 +10:00
|
|
|
}
|
2025-09-01 10:07:28 +10:00
|
|
|
playlist::generate_master_m3u(&config, root)?;
|
2025-08-29 21:33:20 +10:00
|
|
|
}
|
2025-09-21 09:07:18 +10:00
|
|
|
}
|
|
|
|
|
Command::Sync { ipod_dir, download } => {
|
|
|
|
|
// Sync listened podcasts
|
|
|
|
|
sync::sync_listened(
|
|
|
|
|
root,
|
|
|
|
|
&ipod_dir.join(folders::LOCAL_PLAYLISTS_DIR).join(folders::LISTENED_PLAYLIST_PATH),
|
|
|
|
|
true,
|
|
|
|
|
)?;
|
|
|
|
|
|
|
|
|
|
if download {
|
|
|
|
|
// Download all new episodes
|
|
|
|
|
for (alias, source) in &config.podcasts {
|
|
|
|
|
download::update_podcast(&alias, root, &source)?;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Generate updated playlist files
|
|
|
|
|
for (alias, _) in &config.podcasts {
|
|
|
|
|
playlist::generate_podcast_m3u(alias.as_str(), root, true)?;
|
|
|
|
|
playlist::generate_podcast_m3u(alias.as_str(), root, false)?;
|
|
|
|
|
}
|
|
|
|
|
playlist::generate_master_m3u(&config, root)?;
|
|
|
|
|
|
|
|
|
|
// Sync podcasts and playlists
|
|
|
|
|
sync::sync(root, &config, &ipod_dir)?;
|
|
|
|
|
}
|
2024-11-18 21:44:36 +11:00
|
|
|
};
|
2024-01-11 17:30:55 +11:00
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|