From fb360c82698c24b6d48c890e9cb5a42fa9e57819 Mon Sep 17 00:00:00 2001 From: KD Date: Tue, 21 Oct 2025 22:24:52 -0400 Subject: [PATCH] tsk-212: Identify type of CoverArt (#214) * tsk-212: icarus_meta version bump * tsk-212: icarus_meta version bump * tsk-212: Got functionality working * tsk-212: Migration changes Added file_type to CoverArtQueue * tsk-212: Add support to save file_type from CoverArtQueue * tsk-212: Warning fix * tsk-212: Version bump * tsk-212: icarus_meta version bump * tsk-212: icarus_meta version bump * tsk-212: icarus_meta related changes * tsk-212: Replaced code with constants --- Cargo.lock | 35 +++++++- Cargo.toml | 4 +- migrations/20250420185217_init_migration.sql | 1 + src/callers/coverart.rs | 93 +++++++++++++++----- test_migrations/20250725213944_init.sql | 1 + 5 files changed, 109 insertions(+), 25 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 779eec5..61184e2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -193,6 +193,17 @@ dependencies = [ "shlex", ] +[[package]] +name = "cfb" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d38f2da7a0a2c4ccf0065be06397cc26a81f4e528be095826eee9d4adbb8c60f" +dependencies = [ + "byteorder", + "fnv", + "uuid", +] + [[package]] name = "cfg-if" version = "1.0.4" @@ -823,7 +834,7 @@ dependencies = [ [[package]] name = "icarus" -version = "0.3.1" +version = "0.3.2" dependencies = [ "axum", "axum-extra", @@ -864,10 +875,13 @@ dependencies = [ [[package]] name = "icarus_meta" -version = "0.4.0" -source = "git+ssh://git@git.kundeng.us/phoenix/icarus_meta.git?tag=v0.4.0#f372d059155691c0bac52594fa0d14867078e461" +version = "0.4.3" +source = "git+ssh://git@git.kundeng.us/phoenix/icarus_meta.git?tag=v0.4.3-48-8acf220fc4-680#8acf220fc4a646090cfb54eff78aaa2f172bf882" dependencies = [ + "imghdr", + "infer", "lofty", + "rand 0.9.2", ] [[package]] @@ -991,6 +1005,12 @@ dependencies = [ "icu_properties", ] +[[package]] +name = "imghdr" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8b35f3ad95576ac81603375dfe47a0450b70a368aa34d2b6e5bb0a0d7f02428" + [[package]] name = "indexmap" version = "2.12.0" @@ -1003,6 +1023,15 @@ dependencies = [ "serde_core", ] +[[package]] +name = "infer" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a588916bfdfd92e71cacef98a63d9b1f0d74d6599980d11894290e7ddefffcf7" +dependencies = [ + "cfb", +] + [[package]] name = "itoa" version = "1.0.15" diff --git a/Cargo.toml b/Cargo.toml index ebf0655..2cc9f7a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "icarus" -version = "0.3.1" +version = "0.3.2" edition = "2024" rust-version = "1.90" @@ -25,7 +25,7 @@ jsonwebtoken = { version = "9.3.1" } josekit = { version = "0.10.3" } utoipa = { version = "5.4.0", features = ["axum_extras"] } utoipa-swagger-ui = { version = "9.0.2", features = ["axum"] } -icarus_meta = { git = "ssh://git@git.kundeng.us/phoenix/icarus_meta.git", tag = "v0.4.0" } +icarus_meta = { git = "ssh://git@git.kundeng.us/phoenix/icarus_meta.git", tag = "v0.4.3-48-8acf220fc4-680" } icarus_models = { git = "ssh://git@git.kundeng.us/phoenix/icarus_models.git", tag = "v0.8.0" } icarus_envy = { git = "ssh://git@git.kundeng.us/phoenix/icarus_envy.git", tag = "v0.5.0" } diff --git a/migrations/20250420185217_init_migration.sql b/migrations/20250420185217_init_migration.sql index 621a949..0083b57 100644 --- a/migrations/20250420185217_init_migration.sql +++ b/migrations/20250420185217_init_migration.sql @@ -22,6 +22,7 @@ CREATE TABLE IF NOT EXISTS "metadataQueue" ( CREATE TABLE IF NOT EXISTS "coverartQueue" ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), data BYTEA NULL, + file_type TEXT NOT NULL, song_queue_id UUID NULL ); diff --git a/src/callers/coverart.rs b/src/callers/coverart.rs index 09901cb..0c68afe 100644 --- a/src/callers/coverart.rs +++ b/src/callers/coverart.rs @@ -2,6 +2,7 @@ #[derive(Debug, Default, serde::Deserialize, serde::Serialize, utoipa::ToSchema)] pub struct CoverArtQueue { pub id: uuid::Uuid, + pub file_type: String, pub song_queue_id: uuid::Uuid, } @@ -131,13 +132,18 @@ pub mod response { pub mod db { use sqlx::Row; - pub async fn insert(pool: &sqlx::PgPool, data: &Vec) -> Result { + pub async fn insert( + pool: &sqlx::PgPool, + data: &Vec, + file_type: &str, + ) -> Result { let result = sqlx::query( r#" - INSERT INTO "coverartQueue" (data) VALUES($1) RETURNING id; + INSERT INTO "coverartQueue" (data, file_type) VALUES($1, $2) RETURNING id; "#, ) .bind(data) + .bind(file_type) .fetch_one(pool) .await .map_err(|e| { @@ -183,7 +189,7 @@ pub mod db { ) -> Result { let result = sqlx::query( r#" - SELECT id, song_queue_id FROM "coverartQueue" WHERE id = $1; + SELECT id, file_type, song_queue_id FROM "coverartQueue" WHERE id = $1; "#, ) .bind(id) @@ -199,6 +205,10 @@ pub mod db { .try_get("id") .map_err(|_e| sqlx::Error::RowNotFound) .unwrap(), + file_type: row + .try_get("file_type") + .map_err(|_e| sqlx::Error::RowNotFound) + .unwrap(), song_queue_id: row .try_get("song_queue_id") .map_err(|_e| sqlx::Error::RowNotFound) @@ -214,7 +224,7 @@ pub mod db { ) -> Result { let result = sqlx::query( r#" - SELECT id, song_queue_id FROM "coverartQueue" WHERE song_queue_id = $1; + SELECT id, file_type, song_queue_id FROM "coverartQueue" WHERE song_queue_id = $1; "#, ) .bind(song_queue_id) @@ -230,6 +240,10 @@ pub mod db { .try_get("id") .map_err(|_e| sqlx::Error::RowNotFound) .unwrap(), + file_type: row + .try_get("file_type") + .map_err(|_e| sqlx::Error::RowNotFound) + .unwrap(), song_queue_id: row .try_get("song_queue_id") .map_err(|_e| sqlx::Error::RowNotFound) @@ -485,6 +499,24 @@ pub mod cov_db { } } +mod helper { + pub fn is_coverart_file_type_valid(file_type: &String) -> bool { + let valid_file_types = vec![ + String::from(icarus_meta::detection::coverart::constants::JPEG_TYPE), + String::from(icarus_meta::detection::coverart::constants::JPG_TYPE), + String::from(icarus_meta::detection::coverart::constants::PNG_TYPE), + ]; + + for valid_file_type in valid_file_types { + if valid_file_type == *file_type { + return true; + } + } + + false + } +} + pub mod endpoint { use axum::response::IntoResponse; @@ -516,24 +548,45 @@ pub mod endpoint { let content_type = field.content_type().unwrap().to_string(); let data = field.bytes().await.unwrap(); let raw_data = data.to_vec(); + let file_type = + match icarus_meta::detection::coverart::file_type_from_data(&raw_data) { + Ok(file_type) => file_type, + Err(err) => { + eprintln!("Error: {err:?}"); + response.message = err.to_string(); + return ( + axum::http::StatusCode::INTERNAL_SERVER_ERROR, + axum::Json(response), + ); + } + }; - println!( - "Received file '{}' (name = '{}', content-type = '{}', size = {})", - file_name, - name, - content_type, - data.len() - ); + if !super::helper::is_coverart_file_type_valid(&file_type.file_type) { + response.message = format!("CoverArt file type not supported: {file_type:?}"); + ( + axum::http::StatusCode::INTERNAL_SERVER_ERROR, + axum::Json(response), + ) + } else { + println!( + "Received file '{}' (name = '{}', content-type = '{}', size = {}, file-type = {:?})", + file_name, + name, + content_type, + data.len(), + file_type + ); - match super::db::insert(&pool, &raw_data).await { - Ok(id) => { - response.message = String::from("Successful"); - response.data.push(id); - (axum::http::StatusCode::OK, axum::Json(response)) - } - Err(err) => { - response.message = err.to_string(); - (axum::http::StatusCode::BAD_REQUEST, axum::Json(response)) + match super::db::insert(&pool, &raw_data, &file_type.file_type).await { + Ok(id) => { + response.message = String::from("Successful"); + response.data.push(id); + (axum::http::StatusCode::OK, axum::Json(response)) + } + Err(err) => { + response.message = err.to_string(); + (axum::http::StatusCode::BAD_REQUEST, axum::Json(response)) + } } } } diff --git a/test_migrations/20250725213944_init.sql b/test_migrations/20250725213944_init.sql index 267ee8b..d186f00 100644 --- a/test_migrations/20250725213944_init.sql +++ b/test_migrations/20250725213944_init.sql @@ -22,6 +22,7 @@ CREATE TABLE IF NOT EXISTS "metadataQueue" ( CREATE TABLE IF NOT EXISTS "coverartQueue" ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), data BYTEA NULL, + file_type TEXT NOT NULL, song_queue_id UUID NULL );