deleting and not generating empty unlistened playlists
This commit is contained in:
@@ -11,6 +11,9 @@ pub(crate) const IPOD_PODCASTS_DIR: &str = "Podcasts";
|
|||||||
pub(crate) const LISTENED_PLAYLIST_PATH: &str = "[PC Meta] [Listened].m3u";
|
pub(crate) const LISTENED_PLAYLIST_PATH: &str = "[PC Meta] [Listened].m3u";
|
||||||
pub(crate) const MASTER_PLAYLIST_PATH: &str = "[PC Meta] [Master Feed].m3u";
|
pub(crate) const MASTER_PLAYLIST_PATH: &str = "[PC Meta] [Master Feed].m3u";
|
||||||
|
|
||||||
|
pub(crate) const PLAYLIST_PREFIX: &str = "[PC]";
|
||||||
|
pub(crate) const UNLISTENED_SUFFIX: &str = "(unlistened)";
|
||||||
|
|
||||||
pub(crate) fn podcast_folder(
|
pub(crate) fn podcast_folder(
|
||||||
root: &path::Path,
|
root: &path::Path,
|
||||||
alias: &str,
|
alias: &str,
|
||||||
|
|||||||
@@ -80,6 +80,9 @@ fn main() -> anyhow::Result<()> {
|
|||||||
spec.write_to(&spec_file)?;
|
spec.write_to(&spec_file)?;
|
||||||
}
|
}
|
||||||
Command::Playlist { podcast } => {
|
Command::Playlist { podcast } => {
|
||||||
|
// Empty playlist folder.
|
||||||
|
// playlist::empty_playlists(root)?;
|
||||||
|
|
||||||
if let Some(alias) = podcast {
|
if let Some(alias) = podcast {
|
||||||
playlist::generate_podcast_m3u(alias.as_str(), root, false)?;
|
playlist::generate_podcast_m3u(alias.as_str(), root, false)?;
|
||||||
playlist::generate_podcast_m3u(alias.as_str(), root, true)?;
|
playlist::generate_podcast_m3u(alias.as_str(), root, true)?;
|
||||||
@@ -106,6 +109,9 @@ fn main() -> anyhow::Result<()> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Empty playlist folder.
|
||||||
|
// playlist::empty_playlists(root)?;
|
||||||
|
|
||||||
// Generate updated playlist files
|
// Generate updated playlist files
|
||||||
for (alias, _) in &config.podcasts {
|
for (alias, _) in &config.podcasts {
|
||||||
playlist::generate_podcast_m3u(alias.as_str(), root, true)?;
|
playlist::generate_podcast_m3u(alias.as_str(), root, true)?;
|
||||||
|
|||||||
@@ -29,6 +29,10 @@ impl<'a> Playlist<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_empty(&self) -> bool {
|
||||||
|
self.files.is_empty()
|
||||||
|
}
|
||||||
|
|
||||||
/// Writes the playlist file based on the specified filename.
|
/// Writes the playlist file based on the specified filename.
|
||||||
///
|
///
|
||||||
/// Output boolean indicates if the playlist was written (if it was
|
/// Output boolean indicates if the playlist was written (if it was
|
||||||
@@ -41,11 +45,21 @@ impl<'a> Playlist<'a> {
|
|||||||
let playlists_folder = self.root.join(folders::LOCAL_PLAYLISTS_DIR);
|
let playlists_folder = self.root.join(folders::LOCAL_PLAYLISTS_DIR);
|
||||||
if !playlists_folder.exists() {
|
if !playlists_folder.exists() {
|
||||||
fs::create_dir(&playlists_folder)
|
fs::create_dir(&playlists_folder)
|
||||||
.context(format!("failed to create output directory for playlists"))?;
|
.context("failed to create output directory for playlists")?;
|
||||||
}
|
}
|
||||||
let mut path = playlists_folder.join(sanitise(name));
|
let mut path = playlists_folder.join(sanitise(name));
|
||||||
path.set_extension("m3u");
|
path.set_extension("m3u");
|
||||||
|
|
||||||
|
// If the playlist is empty, then don't write it,
|
||||||
|
// and delete the existing one if it exists.
|
||||||
|
if self.is_empty() {
|
||||||
|
if path.exists() {
|
||||||
|
fs::remove_file(&path)
|
||||||
|
.context("failed to remove existing playlist to empty")?;
|
||||||
|
}
|
||||||
|
return Ok(false)
|
||||||
|
}
|
||||||
|
|
||||||
let mut output = io::BufWriter::new(Vec::new());
|
let mut output = io::BufWriter::new(Vec::new());
|
||||||
let mut writer = m3u::Writer::new(&mut output);
|
let mut writer = m3u::Writer::new(&mut output);
|
||||||
let entries =
|
let entries =
|
||||||
@@ -136,6 +150,20 @@ pub(crate) fn generate_master_m3u(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Empties the playlist output folder.
|
||||||
|
pub(crate) fn empty_playlists(
|
||||||
|
root: &path::Path,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
let playlists_folder = root.join(folders::LOCAL_PLAYLISTS_DIR);
|
||||||
|
if playlists_folder.exists() {
|
||||||
|
fs::remove_dir_all(&playlists_folder)
|
||||||
|
.context("failed to remove output directory for playlists")?;
|
||||||
|
}
|
||||||
|
fs::create_dir(&playlists_folder)
|
||||||
|
.context("failed to create output directory for playlists")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
pub(crate) fn generate_podcast_m3u(
|
pub(crate) fn generate_podcast_m3u(
|
||||||
alias: &str,
|
alias: &str,
|
||||||
@@ -170,9 +198,9 @@ pub(crate) fn generate_podcast_m3u(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let written = if unlistened_only {
|
let written = if unlistened_only {
|
||||||
playlist.write_as(&format!("[PC] {} (unlistened)", alias), false)
|
playlist.write_as(&format!("{} {} {}", folders::PLAYLIST_PREFIX, alias, folders::UNLISTENED_SUFFIX), false)
|
||||||
} else {
|
} else {
|
||||||
playlist.write_as(&format!("[PC] {}", alias), false)
|
playlist.write_as(&format!("{} {}", folders::PLAYLIST_PREFIX, alias), false)
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
if written {
|
if written {
|
||||||
|
|||||||
25
src/sync.rs
25
src/sync.rs
@@ -175,15 +175,40 @@ pub(crate) fn sync(
|
|||||||
anyhow::bail!("specified target directory does not contain a folder {:?}", folders::LOCAL_PLAYLISTS_DIR);
|
anyhow::bail!("specified target directory does not contain a folder {:?}", folders::LOCAL_PLAYLISTS_DIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is a bit of a hack, but we use the list of acknowledged
|
||||||
|
// files in the target to recognise which unlistened playlists
|
||||||
|
// should be deleted (because they don't exist in the local directory).
|
||||||
|
// This won't delete any other extra podcasts, and is just a temporary
|
||||||
|
// fix to make sure empty unlistened playlists don't exist.
|
||||||
|
let mut acknowledged = BTreeSet::new();
|
||||||
for source in fs::read_dir(root.join(folders::LOCAL_PLAYLISTS_DIR))? {
|
for source in fs::read_dir(root.join(folders::LOCAL_PLAYLISTS_DIR))? {
|
||||||
let source = source?.path();
|
let source = source?.path();
|
||||||
let target = target_dir
|
let target = target_dir
|
||||||
.join(folders::LOCAL_PLAYLISTS_DIR)
|
.join(folders::LOCAL_PLAYLISTS_DIR)
|
||||||
.join(source.file_name().unwrap());
|
.join(source.file_name().unwrap());
|
||||||
|
|
||||||
|
acknowledged.insert(target.clone());
|
||||||
|
|
||||||
if !target.exists() || fs::metadata(&target)?.modified()? < fs::metadata(&source)?.modified()? {
|
if !target.exists() || fs::metadata(&target)?.modified()? < fs::metadata(&source)?.modified()? {
|
||||||
println!("[info] copying playlist {:?}.", source.file_name().unwrap());
|
println!("[info] copying playlist {:?}.", source.file_name().unwrap());
|
||||||
fs::copy(source, target)?;
|
fs::copy(source, target)?;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Here we delete the excess unlistened playlists (if the don't exist
|
||||||
|
// in local directory, and thus correspond to empty playlists).
|
||||||
|
//
|
||||||
|
// This could very easily be edited to remove other excess playlists.
|
||||||
|
for target in fs::read_dir(target_dir.join(folders::LOCAL_PLAYLISTS_DIR))? {
|
||||||
|
let target = target?.path();
|
||||||
|
let file_name = target.file_stem().unwrap();
|
||||||
|
let file_name = file_name.to_str().unwrap();
|
||||||
|
|
||||||
|
if file_name.starts_with(folders::PLAYLIST_PREFIX)
|
||||||
|
&& file_name.ends_with(folders::UNLISTENED_SUFFIX)
|
||||||
|
&& !acknowledged.contains(&target) {
|
||||||
|
fs::remove_file(&target)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user