Authentication-Results: mail-b.sr.ht; dkim=none Received: from mout01.posteo.de (mout01.posteo.de [185.67.36.141]) by mail-b.sr.ht (Postfix) with ESMTPS id BD80811EE9A for <~thecatster/spotsync-devel@lists.sr.ht>; Mon, 2 Aug 2021 00:02:02 +0000 (UTC) Received: from submission (posteo.de [89.146.220.130]) by mout01.posteo.de (Postfix) with ESMTPS id 6B7E5240026 for <~thecatster/spotsync-devel@lists.sr.ht>; Mon, 2 Aug 2021 02:02:01 +0200 (CEST) Received: from customer (localhost [127.0.0.1]) by submission (posteo.de) with ESMTPSA id 4GdJ8R5cfRz6tmG; Mon, 2 Aug 2021 02:01:59 +0200 (CEST) From: Daniel Rose To: ~thecatster/spotsync-devel@lists.sr.ht Cc: Daniel Rose Subject: [PATCH] Add playlist comparison Date: Mon, 2 Aug 2021 00:01:23 +0000 Message-Id: <20210802000123.216676-1-danielrose@member.fsf.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Signed-off-by: Daniel Rose --- Cargo.toml | 3 ++- src/main.rs | 46 ++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2d188be..d6ccb93 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,4 +13,5 @@ fern = { version = "0.5" } chrono = { version = "0.4" } tokio = { version = "1", features = ["full"] } ron = { version = "0.6" } -serde = { version = "1" } \ No newline at end of file +serde = { version = "1" } +itertools = { version = "0.10" } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index cad40ba..0618e28 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,4 @@ -#![feature(string_remove_matches)] +#![feature(string_remove_matches, slice_partition_dedup)] use aspotify::{authorization_url, Client, ClientCredentials, PlaylistSimplified, Scope}; use fern::{log_file, Dispatch}; @@ -9,11 +9,14 @@ use ron::{ ser::{to_string_pretty, PrettyConfig}, }; use serde::{Deserialize, Serialize}; +use itertools::Itertools; use std::{ env, fs::{self, write, File}, io::{self, Write}, + cmp::Ordering, + hash::Hash, }; mod tests; @@ -24,13 +27,33 @@ struct PlaylistConfig { songs: Vec, } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Serialize, Deserialize, Clone, Hash)] struct Song { title: String, artists: Vec, album: String, } +impl PartialEq for Song { + fn eq(&self, other: &Self) -> bool { + self.title == other.title && self.album == other.album && self.artists == other.artists + } +} + +impl Eq for Song {} + +impl PartialOrd for Song { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for Song { + fn cmp(&self, other: &Self) -> Ordering { + self.title.cmp(&other.title) + } +} + #[tokio::main] async fn main() { Dispatch::new() @@ -58,10 +81,21 @@ async fn main() { // Main logic for playlist in &spotify_playlists { local_playlist_make_if_not_exists(playlist); - let _local_songs = local_playlist_read_songs(&client, playlist).await; - let _spotify_songs = spotify_playlist_read_songs(&client, playlist).await; - // let needed_songs: Vec = compare_playlists(); - // download_songs_and_update_ron(); + let local_songs = local_playlist_read_songs(&client, playlist).await; + let spotify_songs = spotify_playlist_read_songs(&client, playlist).await; + let needed_songs: Vec = compare_playlists(&local_songs, &spotify_songs, &playlist.name).await; + if !needed_songs.is_empty() { + // download_songs_and_update_ron(&needed_songs).await; + } + } +} + +async fn compare_playlists(local: &[Song], remote: &[Song], playlist_title: &str) -> Vec { + println!("{}: {:?}", playlist_title, local == remote); + if local == remote { + vec![] + } else { + [local, remote].concat().iter().unique().map(|s| s.to_owned()).collect::>() } } -- 2.32.0