From 5675bb48b626f6e36d034931097c08961aa3be24 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sat, 24 May 2025 18:14:53 -0400 Subject: [PATCH] Added endpoint to create coverart --- src/callers/coverart.rs | 99 +++++++++++++++++++++++++++++++++++++++++ src/callers/mod.rs | 1 + src/callers/song.rs | 47 ++++++++++++++++++- 3 files changed, 146 insertions(+), 1 deletion(-) diff --git a/src/callers/coverart.rs b/src/callers/coverart.rs index 2972dfc..11f7744 100644 --- a/src/callers/coverart.rs +++ b/src/callers/coverart.rs @@ -29,6 +29,14 @@ pub mod request { pub song_queue_id: Option, } } + + pub mod create_coverart { + #[derive(Debug, serde::Deserialize, serde::Serialize)] + pub struct Request { + pub song_id: uuid::Uuid, + pub coverart_queue_id: uuid::Uuid + } + } } pub mod response { @@ -67,6 +75,14 @@ pub mod response { pub data: Vec>, } } + + pub mod create_coverart { + #[derive(Debug, Default, serde::Deserialize, serde::Serialize)] + pub struct Response { + pub message: String, + pub data: Vec + } + } } pub mod db { @@ -231,7 +247,40 @@ pub mod db { } } +pub mod cov_db { + use sqlx::Row; + + pub async fn create(pool: &sqlx::PgPool, coverart: &icarus_models::coverart::CoverArt, song_id: &uuid::Uuid) -> Result { + let result = sqlx::query( + r#" + INSERT INTO "coverart" (title, path, song_id) VALUES($1, $2, $3) RETURNING id; + "#, + ) + .bind(&coverart.title) + .bind(&coverart.path) + .bind(&song_id) + .fetch_one(pool) + .await + .map_err(|e| { + eprintln!("Error inserting: {}", e); + }); + + match result { + Ok(row) => { + let id: uuid::Uuid = row + .try_get("id") + .map_err(|_e| sqlx::Error::RowNotFound) + .unwrap(); + Ok(id) + } + Err(_err) => Err(sqlx::Error::RowNotFound), + } + } +} + pub mod endpoint { + use std::io::Write; + pub async fn queue( axum::Extension(pool): axum::Extension, mut multipart: axum::extract::Multipart, @@ -398,4 +447,54 @@ pub mod endpoint { }, } } + + pub async fn create_coverart(axum::Extension(pool): axum::Extension, + axum::Json(payload): axum::Json) -> (axum::http::StatusCode, axum::Json) { + let mut response = super::response::create_coverart::Response::default(); + let id = payload.coverart_queue_id; + + match super::db::get_coverart_queue_data_with_id(&pool, &id).await { + Ok(data) => { + let song_id = payload.song_id; + match crate::callers::song::song_db::get_song(&pool, &song_id).await { + Ok(song) => { + let directory = crate::environment::get_root_directory().await.unwrap(); + let dir = std::path::Path::new(&directory); + + // TODO: Make this random and the file extension should not be hard coded + let filename = format!("{}-coverart.jpeg", &song.filename[..8]); + let save_path = dir.join(&filename); + let path = String::from(save_path.to_str().unwrap()); + let mut coverart = icarus_models::coverart::init::init_coverart_only_path(path); + coverart.title = song.album.clone(); + coverart.data = data; + + let mut file = std::fs::File::create(&save_path).unwrap(); + file.write_all(&coverart.data).unwrap(); + + match super::cov_db::create(&pool, &coverart, &song.id).await { + Ok(id) => { + coverart.id = id; + response.data.push(coverart); + + (axum::http::StatusCode::OK, axum::Json(response)) + } + Err(err) => { + response.message = err.to_string(); + (axum::http::StatusCode::BAD_REQUEST, axum::Json(response)) + } + } + } + Err(err) => { + response.message = err.to_string(); + (axum::http::StatusCode::BAD_REQUEST, axum::Json(response)) + } + } + } + Err(err) => { + response.message = err.to_string(); + (axum::http::StatusCode::BAD_REQUEST, axum::Json(response)) + } + } + } } diff --git a/src/callers/mod.rs b/src/callers/mod.rs index 99e918a..5427afe 100644 --- a/src/callers/mod.rs +++ b/src/callers/mod.rs @@ -13,4 +13,5 @@ pub mod endpoints { pub const QUEUECOVERARTLINK: &str = "/api/v2/coverart/queue/link"; pub const CREATESONG: &str = "/api/v2/song"; + pub const CREATECOVERART: &str = "/api/v2/coverart"; } diff --git a/src/callers/song.rs b/src/callers/song.rs index 66731c2..9fe6b90 100644 --- a/src/callers/song.rs +++ b/src/callers/song.rs @@ -140,7 +140,7 @@ pub mod status { } } -mod song_db { +pub mod song_db { use sqlx::Row; // TODO: Change first parameter of return value from string to a time type @@ -192,6 +192,51 @@ mod song_db { Err(_) => Err(sqlx::Error::RowNotFound), } } + + pub async fn get_song(pool: &sqlx::PgPool, id: &uuid::Uuid) -> Result { + let result = sqlx::query( + r#" + SELECT * FROM "song" WHERE id = $1 + "# + ) + .bind(id) + .fetch_one(pool) + .await + .map_err(|e| { + eprintln!("Error querying data: {:?}", e); + }); + + match result { + Ok(row) => { + let date_created_time: time::OffsetDateTime = row + .try_get("date_created") + .map_err(|_e| sqlx::Error::RowNotFound) + .unwrap(); + + Ok(icarus_models::song::Song { + id: row.try_get("id").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + title: row.try_get("title").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + artist: row.try_get("artist").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + album_artist: row.try_get("album_artist").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + album: row.try_get("album").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + genre: row.try_get("genre").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + year: row.try_get("year").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + track: row.try_get("track").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + disc: row.try_get("disc").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + track_count: row.try_get("track_count").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + disc_count: row.try_get("disc_count").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + duration: row.try_get("duration").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + audio_type: row.try_get("audio_type").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + filename: row.try_get("filename").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + directory: row.try_get("directory").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + date_created: date_created_time.to_string(), + user_id: row.try_get("user_id").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + data: Vec::new(), + }) + } + Err(_) => Err(sqlx::Error::RowNotFound) + } + } } mod song_queue {