From 56bc015b7a40d1669d5c192bc7e130fd0120ff91 Mon Sep 17 00:00:00 2001 From: Lyssieth Date: Tue, 10 Oct 2023 22:26:42 +0300 Subject: [PATCH] feat: scanning somewhat cromulent now to make sure it can play again ;3 --- Justfile | 2 +- rave/src/scan.rs | 121 ++++++++++++++++++++++------------------------- 2 files changed, 58 insertions(+), 65 deletions(-) diff --git a/Justfile b/Justfile index 6d7f77c..d25bd4e 100644 --- a/Justfile +++ b/Justfile @@ -9,6 +9,6 @@ mount: run: mount RAVE_STORAGE_DIR=/tmp/media-for-rave cargo r -update-db: +refresh: sea migrate fresh sea generate entity -o ./entities/src --with-serde both --date-time-crate time --lib \ No newline at end of file diff --git a/rave/src/scan.rs b/rave/src/scan.rs index bed1eef..be42f05 100644 --- a/rave/src/scan.rs +++ b/rave/src/scan.rs @@ -83,7 +83,9 @@ async fn scan() { continue; }; - tokio::spawn(do_entry(de, txn, state.clone())); + // tokio::spawn(do_entry(de, txn, state.clone())); // multithreading version + + do_entry(de, txn, state.clone()).await; // test without multithreading } { @@ -96,11 +98,13 @@ async fn scan() { const VALID_EXTENSIONS: &[&str] = &["mp3"]; async fn do_entry(de: walk::DirEntry, txn: DatabaseTransaction, state: Arc>) { - if let Err(e) = handle_entry(&txn, de, state).await { + if let Err(e) = handle_entry(&txn, de.clone(), state).await { let _ = txn.rollback().await; + let path = de.path(); + let path = path.to_string_lossy(); error!( error = e.root_cause(), - "Failed to handle directory entry: {e}" + "Failed to handle directory entry `{path}`: {e}" ); { @@ -175,20 +179,11 @@ async fn handle_entry( let meta = { File::open(&path).await?.metadata().await? }; - let current_album = { state.read().await.album_id }; - let tag = Tag::async_read_from_path(&path).await?; let artist = find_artist(tx, &tag).await?; - let album = find_album( - tx, - current_album, - artist.as_ref().map(|c| c.id), - &tag, - state.clone(), - ) - .await?; + let album = find_album(tx, artist.as_ref().map(|c| c.id), &tag, state.clone()).await?; let mut am = track::ActiveModel::new(); @@ -219,61 +214,59 @@ async fn handle_entry( #[instrument(skip(tx, tag, state))] async fn find_album( tx: &DatabaseTransaction, - current_album: Option, artist_id: Option, tag: &Tag, state: Arc>, ) -> Result { - if let Some(current_album) = current_album { - let album = Album::find_by_id(current_album).one(tx).await?; + let Some(album_name) = tag.album() else { + return Err(Report::msg("Couldn't get album name from tag")); + }; - let Some(album) = album else { - error!("Couldn't find album with id {current_album}"); + // if not, search by name + let search = Album::find() + .filter(album::Column::Name.like(album_name)) + .one(tx) + .await?; - return Err(Report::msg(format!( - "Couldn't find album with id {current_album}" - ))); - }; - - Ok(album) - } else { - let mut am = album::ActiveModel::new(); - - if let Some(tag_album) = tag.album() { - am.name = Set(tag_album.to_string()); - } else { - am.name = Set("Unknown Album".to_string()); - } - - am.music_folder_id = Set(state.read().await.music_folder_id); - am.artist_id = Set(artist_id); - am.year = Set(tag.year()); - let genre = tag.genre_parsed(); - if let Some(genre) = genre { - let genre_id = find_or_create_genre(tx, genre.as_ref()).await?; - am.genre_ids = Set(Some(vec![genre_id])); - } - am.song_count = Set(tag - .total_tracks() - .map(|v| i32::try_from(v).expect("Failed to convert total tracks to i32")) - .unwrap_or_default()); - am.duration = Set(tag.duration().map(Into::into).unwrap_or_default()); - am.created = Set(OffsetDateTime::now_utc()); - - let model = Album::insert(am).exec_with_returning(tx).await; - - let Ok(model) = model else { - let err = model.expect_err("somehow not err"); - error!( - error = &err as &dyn std::error::Error, - "Failed to insert album {err}" - ); - - return Err(Report::new(err)); - }; - - Ok(model) + // if we found one, return it + if let Some(search) = search { + return Ok(search); } + + // otherwise, create it + let mut am = album::ActiveModel::new(); + + am.name = Set(album_name.to_string()); + am.music_folder_id = Set(state.read().await.music_folder_id); + am.artist_id = Set(artist_id); + am.year = Set(tag.year()); + + let genre = tag.genre_parsed(); + if let Some(genre) = genre { + let genre_id = find_or_create_genre(tx, genre.as_ref()).await?; + am.genre_ids = Set(Some(vec![genre_id])); + } + am.song_count = Set(tag + .total_tracks() + .map(|v| i32::try_from(v).expect("Failed to convert total tracks to i32")) + .unwrap_or_default()); + am.duration = Set(tag.duration().map(Into::into).unwrap_or_default()); + am.created = Set(OffsetDateTime::now_utc()); + + let model = Album::insert(am).exec_with_returning(tx).await; + + // if we failed to insert, return the error + let Ok(model) = model else { + let err = model.expect_err("somehow not err"); + error!( + error = &err as &dyn std::error::Error, + "Failed to insert album {err}" + ); + + return Err(Report::new(err)); + }; + + Ok(model) } #[instrument(skip(tx))] @@ -327,8 +320,9 @@ async fn find_artist(tx: &DatabaseTransaction, tag: &Tag) -> Result { + let artist_to_search = artist_to_search.trim(); let attempt = Artist::find() - .filter(artist::Column::Name.contains(artist_to_search)) + .filter(artist::Column::Name.like(artist_to_search)) .one(tx) .await?; @@ -336,7 +330,7 @@ async fn find_artist(tx: &DatabaseTransaction, tag: &Tag) -> Result Result, } #[instrument(skip(dbc, state))]