diff --git a/src/entities/wanted_item.rs b/src/entities/wanted_item.rs index 0fdee59..b8f502f 100644 --- a/src/entities/wanted_item.rs +++ b/src/entities/wanted_item.rs @@ -37,6 +37,9 @@ pub struct Model { pub album_id: Option, #[sea_orm(nullable)] pub track_id: Option, + pub name: String, + #[sea_orm(nullable)] + pub musicbrainz_id: Option, pub status: WantedStatus, pub added_at: chrono::NaiveDateTime, pub updated_at: chrono::NaiveDateTime, diff --git a/src/migration/m20260317_000009_add_wanted_name.rs b/src/migration/m20260317_000009_add_wanted_name.rs new file mode 100644 index 0000000..08b91d7 --- /dev/null +++ b/src/migration/m20260317_000009_add_wanted_name.rs @@ -0,0 +1,40 @@ +use sea_orm_migration::prelude::*; + +#[derive(DeriveMigrationName)] +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .alter_table( + Table::alter() + .table(WantedItems::Table) + .add_column( + ColumnDef::new(WantedItems::Name) + .text() + .not_null() + .default(""), + ) + .to_owned(), + ) + .await + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .alter_table( + Table::alter() + .table(WantedItems::Table) + .drop_column(WantedItems::Name) + .to_owned(), + ) + .await + } +} + +#[derive(DeriveIden)] +enum WantedItems { + Table, + Name, +} diff --git a/src/migration/m20260317_000010_add_wanted_mbid.rs b/src/migration/m20260317_000010_add_wanted_mbid.rs new file mode 100644 index 0000000..84328e0 --- /dev/null +++ b/src/migration/m20260317_000010_add_wanted_mbid.rs @@ -0,0 +1,35 @@ +use sea_orm_migration::prelude::*; + +#[derive(DeriveMigrationName)] +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .alter_table( + Table::alter() + .table(WantedItems::Table) + .add_column(ColumnDef::new(WantedItems::MusicbrainzId).text()) + .to_owned(), + ) + .await + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .alter_table( + Table::alter() + .table(WantedItems::Table) + .drop_column(WantedItems::MusicbrainzId) + .to_owned(), + ) + .await + } +} + +#[derive(DeriveIden)] +enum WantedItems { + Table, + MusicbrainzId, +} diff --git a/src/migration/mod.rs b/src/migration/mod.rs index c130c33..0a5b86c 100644 --- a/src/migration/mod.rs +++ b/src/migration/mod.rs @@ -7,6 +7,8 @@ mod m20260317_000004_create_wanted_items; mod m20260317_000005_create_download_queue; mod m20260317_000006_create_search_cache; mod m20260317_000007_unique_artist_album; +mod m20260317_000009_add_wanted_name; +mod m20260317_000010_add_wanted_mbid; pub struct Migrator; @@ -21,6 +23,8 @@ impl MigratorTrait for Migrator { Box::new(m20260317_000005_create_download_queue::Migration), Box::new(m20260317_000006_create_search_cache::Migration), Box::new(m20260317_000007_unique_artist_album::Migration), + Box::new(m20260317_000009_add_wanted_name::Migration), + Box::new(m20260317_000010_add_wanted_mbid::Migration), ] } } diff --git a/src/queries/downloads.rs b/src/queries/downloads.rs index 6edadf5..1c1c872 100644 --- a/src/queries/downloads.rs +++ b/src/queries/downloads.rs @@ -68,6 +68,16 @@ pub async fn list( .await?) } +pub async fn find_by_wanted_item_id( + db: &DatabaseConnection, + wanted_item_id: i32, +) -> DbResult> { + Ok(DownloadQueue::find() + .filter(download_queue::Column::WantedItemId.eq(wanted_item_id)) + .one(db) + .await?) +} + pub async fn retry_failed(db: &DatabaseConnection, id: i32) -> DbResult<()> { let item = DownloadQueue::find_by_id(id) .one(db) diff --git a/src/queries/tracks.rs b/src/queries/tracks.rs index 1feec1d..3aba458 100644 --- a/src/queries/tracks.rs +++ b/src/queries/tracks.rs @@ -93,6 +93,19 @@ pub async fn get_untagged(db: &DatabaseConnection) -> DbResult> { .await?) } +/// Get tracks that need metadata enrichment — either no MBID at all, +/// or have an MBID but are missing album info (e.g., freshly downloaded). +pub async fn get_needing_metadata(db: &DatabaseConnection) -> DbResult> { + Ok(Tracks::find() + .filter( + Condition::any() + .add(track::Column::MusicbrainzId.is_null()) + .add(track::Column::AlbumId.is_null()), + ) + .all(db) + .await?) +} + pub async fn update_metadata(db: &DatabaseConnection, id: i32, model: ActiveModel) -> DbResult { let mut active = model; active.id = Set(id); diff --git a/src/queries/wanted.rs b/src/queries/wanted.rs index cf95b02..f6f1440 100644 --- a/src/queries/wanted.rs +++ b/src/queries/wanted.rs @@ -9,6 +9,8 @@ use crate::error::{DbError, DbResult}; pub async fn add( db: &DatabaseConnection, item_type: ItemType, + name: &str, + musicbrainz_id: Option<&str>, artist_id: Option, album_id: Option, track_id: Option, @@ -16,6 +18,8 @@ pub async fn add( let now = Utc::now().naive_utc(); let active = ActiveModel { item_type: Set(item_type), + name: Set(name.to_string()), + musicbrainz_id: Set(musicbrainz_id.map(String::from)), artist_id: Set(artist_id), album_id: Set(album_id), track_id: Set(track_id), diff --git a/tests/integration.rs b/tests/integration.rs index 2547fb4..d370d40 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -163,7 +163,7 @@ async fn test_wanted_items_lifecycle() { .unwrap(); // Add wanted item - let item = queries::wanted::add(conn, ItemType::Artist, Some(artist.id), None, None) + let item = queries::wanted::add(conn, ItemType::Artist, "Radiohead", None, Some(artist.id), None, None) .await .unwrap(); assert_eq!(item.status, WantedStatus::Wanted);