play status with corresponding commands

This commit is contained in:
Aaron Manning
2024-11-18 21:44:36 +11:00
parent e6129fa5b6
commit 105a3eb892
3 changed files with 122 additions and 23 deletions

View File

@@ -1,6 +1,7 @@
use std::fs;
use std::path;
use std::borrow::Cow;
use std::iter::Iterator;
use std::collections::{HashMap, BTreeMap, HashSet};
use anyhow::Context;
@@ -9,14 +10,14 @@ use sanitise_file_name::sanitise;
use crate::rss;
#[derive(Default, serde::Serialize, serde::Deserialize)]
struct Specification<'a> {
pub (crate) struct Specification<'a> {
files : HashMap<Cow<'a, str>, Cow<'a, path::Path>>,
feed : BTreeMap<chrono::NaiveDateTime, Vec<Episode<'a>>>,
image_url : Option<Cow<'a, str>>,
}
impl<'a> Specification<'a> {
fn read_from(path : &path::Path) -> Result<Self, anyhow::Error> {
pub (crate) fn read_from_with_default(path : &path::Path) -> Result<Self, anyhow::Error> {
Ok(if path.is_file() {
toml::from_str(&fs::read_to_string(&path)?[..])?
} else {
@@ -24,13 +25,29 @@ impl<'a> Specification<'a> {
})
}
fn write_to(&self, path : &path::Path) -> Result<(), anyhow::Error> {
pub (crate) fn read_from(path : &path::Path) -> Result<Self, anyhow::Error> {
Ok(if path.is_file() {
toml::from_str(&fs::read_to_string(&path)?[..])?
} else {
anyhow::bail!("could not find specification for the desired podcast")
})
}
pub (crate) fn write_to(&self, path : &path::Path) -> Result<(), anyhow::Error> {
Ok(fs::write(path, toml::to_string(self)?.as_bytes())?)
}
pub (crate) fn feed_iter(&self) -> impl Iterator<Item = (&chrono::NaiveDateTime, &Vec<Episode<'a>>)> {
self.feed.iter()
}
pub (crate) fn feed_iter_mut(&mut self) -> impl Iterator<Item = (&chrono::NaiveDateTime, &mut Vec<Episode<'a>>)> {
self.feed.iter_mut()
}
}
#[derive(serde::Serialize, serde::Deserialize)]
struct Episode<'a> {
pub (crate) struct Episode<'a> {
/// Episode title.
title : Cow<'a, str>,
/// Show notes pulled from description or summary tag.
@@ -39,6 +56,15 @@ struct Episode<'a> {
id : Cow<'a, str>,
/// If the episode exists in the latest version of the feed.
current : bool,
/// Flag to keep track of which episodes have been listened to.
#[serde(default)]
pub (crate) listened : bool,
}
impl<'a> Episode<'a> {
pub (crate) fn title(&self) -> &str {
self.title.as_ref()
}
}
fn download_to_file(url : &str, path : &path::Path) -> anyhow::Result<()> {
@@ -175,7 +201,7 @@ pub (crate) fn update_podcast_from_feed(
let spec_file = output.join("spec.toml");
let mut spec = Specification::read_from(&spec_file)?;
let mut spec = Specification::read_from_with_default(&spec_file)?;
// Get set of all currently available episodes such that we can later mark
// any other episodes as unavailable
@@ -278,6 +304,7 @@ pub (crate) fn update_podcast_from_feed(
id : Cow::from(id.to_owned()),
current : true,
title,
listened : false,
};
match spec.feed.get_mut(&item.published) {