diff --git a/.gitignore b/.gitignore
index d01b926..70c6a74 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,5 @@
/target
-/navidrome/target
-/listenbrainz/target
+.env
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index b48c6f5..3f8abc3 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -10,14 +10,18 @@
-
+
+
+
-
+
+
+
@@ -77,6 +81,7 @@
"org.rust.disableDetachedFileInspection/home/jude/navidrome-playlists/navidrome/src/client/playlists.rs": "true",
"org.rust.disableDetachedFileInspection/home/jude/navidrome-playlists/navidrome/src/lib.rs": "true",
"org.rust.disableDetachedFileInspection/home/jude/navidrome-playlists/navidrome/src/models.rs": "true",
+ "org.rust.first.attach.projects": "true",
"settings.editor.selected.configurable": "language.rust.cargo.check",
"vue.rearranger.settings.migration": "true"
},
@@ -152,7 +157,10 @@
-
+
+
+
+
1692008860369
diff --git a/migrations/20240416175952_drop_useless_columns.sql b/migrations/20240416175952_drop_useless_columns.sql
new file mode 100644
index 0000000..4554376
--- /dev/null
+++ b/migrations/20240416175952_drop_useless_columns.sql
@@ -0,0 +1,8 @@
+ALTER TABLE "tracked_playlist"
+ RENAME COLUMN "rule_id" TO "id";
+
+ALTER TABLE "tracked_playlist"
+ DROP COLUMN playlist_name;
+
+ALTER TABLE "tracked_playlist"
+ DROP COLUMN reduce_duplication_on;
diff --git a/src/daemon/update_playlists.rs b/src/daemon/update_playlists.rs
index da530c5..3e865d3 100644
--- a/src/daemon/update_playlists.rs
+++ b/src/daemon/update_playlists.rs
@@ -2,7 +2,6 @@ use crate::listenbrainz;
use crate::listenbrainz::StatsRange;
use crate::models::TrackedPlaylist;
use crate::subsonic::Subsonic;
-use crate::track::Track;
use sqlx::postgres::PgPool;
use std::env;
use std::time::Duration;
@@ -13,6 +12,8 @@ use tokio::time::{interval, MissedTickBehavior};
pub enum UpdatePlaylistError {
#[error("Bad range specified")]
BadRange,
+ #[error("Operation requires a playlist ID")]
+ NoPlaylistId,
}
pub async fn update_playlists_daemon(
@@ -52,45 +53,58 @@ async fn update_playlist(
media_client: &Subsonic,
playlist: TrackedPlaylist,
) -> Result<(), Box> {
- let range =
- StatsRange::from_param(&playlist.tracking_type).ok_or(UpdatePlaylistError::BadRange)?;
+ match playlist.playlist_id {
+ Some(playlist_id) => {
+ let range = StatsRange::from_param(&playlist.tracking_type)
+ .ok_or(UpdatePlaylistError::BadRange)?;
- let recordings = listenbrainz::recordings(playlist.tracking_user, range)
- .await?
- .recordings;
+ let recordings = listenbrainz::recordings(playlist.tracking_user, range)
+ .await?
+ .recordings;
- let mut tracks = vec![];
- for recording in recordings {
- let search_results = media_client
- .song_search(format!(
- "{} {}",
- recording.track_name, recording.artist_name
- ))
- .await?;
+ let mut tracks = vec![];
+ for recording in recordings {
+ let search_results = media_client
+ .song_search(format!(
+ "{} {}",
+ recording.track_name, recording.artist_name
+ ))
+ .await?;
- let filtered = search_results.iter().find(|s| {
- alpha_compare(&s.title, &recording.track_name)
- && alpha_compare(&s.album, &recording.release_name)
- });
+ let filtered = search_results
+ .iter()
+ .find(|s| {
+ alpha_compare(&s.title, &recording.track_name)
+ && alpha_compare(&s.album, &recording.release_name)
+ })
+ .cloned();
- match filtered {
- Some(track) => {
- tracks.push(track.clone());
+ match filtered {
+ Some(track) => {
+ tracks.push(track.id);
+ }
+ None => {
+ println!(
+ "Couldn't find matching track for {} - {}",
+ recording.track_name, recording.artist_name
+ )
+ }
+ }
}
- None => {
- println!(
- "Couldn't find matching track for {} - {}",
- recording.track_name, recording.artist_name
+
+ let playlist = media_client.get_playlist(playlist_id.to_string()).await?;
+ media_client
+ .update_playlist(
+ playlist_id.to_string(),
+ tracks,
+ (0..playlist.song_count).collect(),
)
- }
+ .await?;
+
+ Ok(())
}
+ None => Err(Box::new(UpdatePlaylistError::NoPlaylistId)),
}
-
- media_client
- .update_playlist(playlist.playlist_id.unwrap().to_string(), vec![], vec![])
- .await?;
-
- Ok(())
}
fn alpha_compare(a: &str, b: &str) -> bool {
diff --git a/src/main.rs b/src/main.rs
index 23f815c..9b1ec12 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,6 +1,7 @@
mod daemon;
mod listenbrainz;
mod models;
+mod playlist;
mod subsonic;
mod track;
@@ -40,7 +41,7 @@ async fn main() -> Result<(), Box> {
let app = Router::new()
.route("/playlists", get(all_playlists))
- .route("/playlists", put(create_playlist))
+ .route("/playlists", put(create_tracking_playlist))
.with_state(database);
let listener = tokio::net::TcpListener::bind("localhost:3000").await?;
@@ -68,7 +69,7 @@ enum Response {
Error(JsonError),
}
-async fn create_playlist(
+async fn create_tracking_playlist(
State(pool): State,
extract::Json(partial): extract::Json,
) -> Json> {
diff --git a/src/models.rs b/src/models.rs
index 13264ae..00ae208 100644
--- a/src/models.rs
+++ b/src/models.rs
@@ -6,11 +6,10 @@ use uuid::Uuid;
#[derive(Deserialize)]
pub struct PartialTrackedPlaylist {
- pub playlist_name: Option,
+ pub playlist_id: Option,
pub playlist_size: i32,
pub tracking_user: Option,
pub tracking_type: Option,
- pub reduce_duplication_on: Option,
}
impl PartialTrackedPlaylist {
@@ -21,15 +20,16 @@ impl PartialTrackedPlaylist {
let uuid = Uuid::new_v4();
sqlx::query!(
- r#"INSERT INTO "tracked_playlist"
- (rule_id, playlist_name, playlist_size, tracking_user, tracking_type, reduce_duplication_on)
- VALUES ($1, $2, $3, $4, $5, $6)"#,
+ r#"
+ INSERT INTO "tracked_playlist"
+ (id, playlist_id, playlist_size, tracking_user, tracking_type)
+ VALUES ($1, $2, $3, $4, $5)
+ "#,
uuid,
- self.playlist_name,
+ self.playlist_id,
self.playlist_size,
self.tracking_user,
self.tracking_type,
- self.reduce_duplication_on,
)
.execute(pool)
.await?;
@@ -40,13 +40,11 @@ impl PartialTrackedPlaylist {
#[derive(Serialize)]
pub struct TrackedPlaylist {
- pub rule_id: Uuid,
+ pub id: Uuid,
pub playlist_id: Option,
- pub playlist_name: Option,
pub playlist_size: i32,
pub tracking_user: String,
pub tracking_type: String,
- pub reduce_duplication_on: Option,
}
impl TrackedPlaylist {
@@ -62,7 +60,7 @@ impl TrackedPlaylist {
) -> Result {
sqlx::query_as!(
Self,
- r#"SELECT * FROM "tracked_playlist" WHERE rule_id = $1"#,
+ r#"SELECT * FROM "tracked_playlist" WHERE id = $1"#,
uuid
)
.fetch_one(pool)
diff --git a/src/playlist.rs b/src/playlist.rs
new file mode 100644
index 0000000..e70174c
--- /dev/null
+++ b/src/playlist.rs
@@ -0,0 +1,16 @@
+use crate::track::Track;
+use serde::{Deserialize, Serialize};
+
+fn default_vec() -> Vec