From 3ea68d2935f59b3a479d786b852567d767df2959 Mon Sep 17 00:00:00 2001 From: Wojciech Kozlowski Date: Mon, 8 Jan 2024 18:54:03 +0100 Subject: [PATCH] Add code for modifying musicbutler entries --- src/bin/mh-edit.rs | 44 +++++++++---------- src/lib.rs | 104 +++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 119 insertions(+), 29 deletions(-) diff --git a/src/bin/mh-edit.rs b/src/bin/mh-edit.rs index b79346c..5d0bb2e 100644 --- a/src/bin/mh-edit.rs +++ b/src/bin/mh-edit.rs @@ -73,18 +73,18 @@ struct MultiUrlValue { } macro_rules! url_command_dispatch { - ($command:ident, $mh:ident, $add:ident, $remove:ident, $set:ident, $clear:ident) => { - match $command { - UrlCommand::Add(single_url_value) => { - $mh.$add(ArtistId::new(single_url_value.artist), single_url_value.url) + ($cmd:ident, $mh:ident, $add:ident, $remove:ident, $set:ident, $clear:ident, $url:ident) => { + match $cmd { + UrlCommand::Add(url_value) => { + $mh.$add(ArtistId::new(url_value.artist), url_value.$url) .expect("failed to add URL(s)"); } - UrlCommand::Remove(single_url_value) => { - $mh.$remove(ArtistId::new(single_url_value.artist), single_url_value.url) + UrlCommand::Remove(url_value) => { + $mh.$remove(ArtistId::new(url_value.artist), url_value.$url) .expect("failed to remove URL(s)"); } - UrlCommand::Set(single_url_value) => { - $mh.$set(ArtistId::new(single_url_value.artist), single_url_value.url) + UrlCommand::Set(url_value) => { + $mh.$set(ArtistId::new(url_value.artist), url_value.$url) .expect("failed to set URL(s)"); } UrlCommand::Clear(artist_value) => { @@ -114,24 +114,18 @@ impl ArtistCommand { add_musicbrainz_url, remove_musicbrainz_url, set_musicbrainz_url, - clear_musicbrainz_url + clear_musicbrainz_url, + url + ), + ArtistCommand::MusicButler(url_command) => url_command_dispatch!( + url_command, + music_hoard, + add_musicbutler_urls, + remove_musicbutler_urls, + set_musicbutler_urls, + clear_musicbutler_urls, + urls ), - ArtistCommand::MusicButler(url_command) => { - match url_command { - UrlCommand::Add(_) => { - // Add URL. - } - UrlCommand::Remove(_) => { - // Remove URL if it exists. - } - UrlCommand::Set(_) => { - // Set the URLs regardless of previous (if any) value. - } - UrlCommand::Clear(_) => { - // Remove the URLs. - } - } - } ArtistCommand::Bandcamp(url_command) => { match url_command { UrlCommand::Add(_) => { diff --git a/src/lib.rs b/src/lib.rs index 97527a4..02f93be 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -375,6 +375,65 @@ impl Artist { self.properties.musicbrainz = None; Ok(()) } + + fn add_musicbutler_urls>(&mut self, urls: Vec) -> Result<(), Error> { + // Convert into URLs first to facilitate later comparison. + let urls: Result, Error> = urls.iter().map(MusicButler::new).collect(); + let mut urls = urls?; + + // Do not check and insert. First check if any of the provided URLs already exist so that + // the vector remains unchanged in case of failure. + let overlap: Vec<&MusicButler> = urls + .iter() + .filter(|url| self.properties.musicbutler.contains(url)) + .collect(); + if !overlap.is_empty() { + return Err(Error::CollectionError(format!( + "artist '{}' already has these MusicButler URL(s): {:?}", + self.id, overlap + ))); + } + + self.properties.musicbutler.append(&mut urls); + Ok(()) + } + + fn remove_musicbutler_urls>(&mut self, urls: Vec) -> Result<(), Error> { + // Convert into URLs first to facilitate later comparison. + let urls: Result, Error> = urls.iter().map(MusicButler::new).collect(); + let urls = urls?; + + // Do not check and insert. First check if any of the provided URLs already exist so that + // the vector remains unchanged in case of failure. + let difference: Vec<&MusicButler> = urls + .iter() + .filter(|url| !self.properties.musicbutler.contains(url)) + .collect(); + if !difference.is_empty() { + return Err(Error::CollectionError(format!( + "artist '{}' does not have these MusicButler URL(s): {:?}", + self.id, difference + ))); + } + + let musicbutler = mem::take(&mut self.properties.musicbutler); + self.properties.musicbutler = musicbutler + .into_iter() + .filter(|url| !urls.contains(url)) + .collect(); + Ok(()) + } + + fn set_musicbutler_urls>(&mut self, urls: Vec) -> Result<(), Error> { + let urls: Result, Error> = urls.iter().map(MusicButler::new).collect(); + self.properties.musicbutler = urls?; + Ok(()) + } + + fn clear_musicbutler_urls(&mut self) -> Result<(), Error> { + self.properties.musicbutler.clear(); + Ok(()) + } } impl PartialOrd for Artist { @@ -663,6 +722,41 @@ impl MusicHoard { .clear_musicbrainz_url() } + pub fn add_musicbutler_urls, S: AsRef>( + &mut self, + artist_id: ID, + urls: Vec, + ) -> Result<(), Error> { + self.get_artist_or_err(artist_id.as_ref())? + .add_musicbutler_urls(urls) + } + + pub fn remove_musicbutler_urls, S: AsRef>( + &mut self, + artist_id: ID, + urls: Vec, + ) -> Result<(), Error> { + self.get_artist_or_err(artist_id.as_ref())? + .remove_musicbutler_urls(urls) + } + + pub fn set_musicbutler_urls, S: AsRef>( + &mut self, + artist_id: ID, + urls: Vec, + ) -> Result<(), Error> { + self.get_artist_or_err(artist_id.as_ref())? + .set_musicbutler_urls(urls) + } + + pub fn clear_musicbutler_urls>( + &mut self, + artist_id: ID, + ) -> Result<(), Error> { + self.get_artist_or_err(artist_id.as_ref())? + .clear_musicbutler_urls() + } + fn sort(collection: &mut [Artist]) { collection.sort_unstable(); for artist in collection.iter_mut() { @@ -745,10 +839,12 @@ impl MusicHoard { } fn get_artist_or_err(&mut self, artist_id: &ArtistId) -> Result<&mut Artist, Error> { - let artist_opt = self.collection.iter_mut().find(|a| &a.id == artist_id); - artist_opt.ok_or_else(|| { - Error::CollectionError(format!("artist '{}' is not in the collection", artist_id)) - }) + self.collection + .iter_mut() + .find(|a| &a.id == artist_id) + .ok_or_else(|| { + Error::CollectionError(format!("artist '{}' is not in the collection", artist_id)) + }) } }