Skip to content

Commit

Permalink
backend/information: add upsert cover art
Browse files Browse the repository at this point in the history
  • Loading branch information
vnghia committed Nov 22, 2024
1 parent b32db82 commit 34ff2d1
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 8 deletions.
28 changes: 24 additions & 4 deletions nghe-backend/src/file/audio/information.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::borrow::Cow;
use diesel::ExpressionMethods;
use diesel_async::RunQueryDsl;
use o2o::o2o;
use typed_path::Utf8NativePath;
use uuid::Uuid;

use super::{Album, Artists, Genres};
Expand Down Expand Up @@ -47,6 +48,22 @@ impl Information<'_> {
Genres::upsert_song(database, song_id, &genre_ids).await
}

pub async fn upsert_cover_art(
&self,
database: &Database,
dir: Option<&impl AsRef<Utf8NativePath>>,
) -> Result<Option<Uuid>, Error> {
Ok(
if let Some(ref picture) = self.metadata.picture
&& let Some(dir) = dir
{
Some(picture.upsert(database, dir).await?)
} else {
None
},
)
}

pub async fn upsert_song(
&self,
database: &Database,
Expand All @@ -68,8 +85,10 @@ impl Information<'_> {
song_id: impl Into<Option<Uuid>>,
) -> Result<Uuid, Error> {
let album_id = self.upsert_album(database, music_folder_id).await?;
let song_id =
self.upsert_song(database, songs::Foreign { album_id }, relative_path, song_id).await?;
let cover_art_id = self.upsert_cover_art(database, config.cover_art.dir.as_ref()).await?;
let foreign = songs::Foreign { album_id, cover_art_id };

let song_id = self.upsert_song(database, foreign, relative_path, song_id).await?;
self.upsert_artists(database, &config.index.ignore_prefixes, song_id).await?;
self.upsert_genres(database, song_id).await?;
Ok(song_id)
Expand Down Expand Up @@ -107,7 +126,7 @@ mod test {
use uuid::Uuid;

use super::Information;
use crate::file::audio;
use crate::file::{audio, picture};
use crate::orm::songs;
use crate::test::Mock;

Expand Down Expand Up @@ -135,6 +154,7 @@ mod test {
let album = audio::Album::query(mock, upsert.foreign.album_id).await;
let artists = audio::Artists::query(mock, id).await;
let genres = audio::Genres::query(mock, id).await;
let picture = picture::Picture::query_song(mock, id).await;

(
upsert.relative_path.into_owned(),
Expand All @@ -144,7 +164,7 @@ mod test {
album,
artists,
genres,
picture: None,
picture,
},
property: upsert.data.property.try_into().unwrap(),
file: upsert.data.file.into(),
Expand Down
26 changes: 23 additions & 3 deletions nghe-backend/src/file/picture/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,12 +131,16 @@ impl<'a> Picture<'a> {
mod test {
use std::io::Cursor;

use diesel::{ExpressionMethods, OptionalExtension, QueryDsl, SelectableHelper};
use diesel_async::RunQueryDsl;
use fake::{Dummy, Fake, Faker};
use image::{ImageFormat, Rgb, RgbImage};
use lofty::picture::PictureType;

use super::*;
use crate::file;
use crate::schema::songs;
use crate::test::Mock;

impl Dummy<Faker> for Picture<'_> {
fn dummy_with_rng<R: fake::rand::Rng + ?Sized>(config: &Faker, rng: &mut R) -> Self {
Expand Down Expand Up @@ -174,11 +178,27 @@ mod test {
}

impl Picture<'_> {
pub async fn load(dir: impl AsRef<Utf8NativePath>, cover_art: cover_arts::Upsert) -> Self {
let property: file::Property<Format> = cover_art.property.into();
async fn load(dir: impl AsRef<Utf8NativePath>, upsert: cover_arts::Upsert) -> Self {
let property: file::Property<Format> = upsert.property.into();
let path = property.path(dir, Self::FILENAME);
let data = tokio::fs::read(path).await.unwrap();
Self { source: cover_art.source, property, data: data.into() }
Self { source: upsert.source, property, data: data.into() }
}

pub async fn query_song(mock: &Mock, song_id: Uuid) -> Option<Self> {
if let Some(ref dir) = mock.config.cover_art.dir {
let upsert = cover_arts::table
.inner_join(songs::table)
.filter(songs::id.eq(song_id))
.select(cover_arts::Upsert::as_select())
.get_result(&mut mock.get().await)
.await
.optional()
.unwrap();
if let Some(upsert) = upsert { Some(Self::load(dir, upsert).await) } else { None }
} else {
None
}
}
}
}
1 change: 1 addition & 0 deletions nghe-backend/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ pub async fn build(config: config::Config) -> Router {
scan: config.filesystem.scan,
parsing: config.parsing,
index: config.index,
cover_art: config.cover_art,
},
))
.merge(route::browsing::router())
Expand Down
4 changes: 3 additions & 1 deletion nghe-backend/src/orm/songs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ pub mod property;
#[derive(Debug, Queryable, Selectable, Insertable, AsChangeset)]
#[diesel(table_name = songs, check_for_backend(crate::orm::Type))]
#[diesel(treat_none_as_null = true)]
#[cfg_attr(test, derive(Default))]
pub struct Foreign {
pub album_id: Uuid,
pub cover_art_id: Option<Uuid>,
}

#[derive(Debug, Queryable, Selectable, Insertable, AsChangeset)]
Expand Down Expand Up @@ -110,7 +112,7 @@ mod test {

impl From<Uuid> for Foreign {
fn from(value: Uuid) -> Self {
Self { album_id: value }
Self { album_id: value, ..Default::default() }
}
}
}
1 change: 1 addition & 0 deletions nghe-backend/src/scan/scanner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ pub struct Config {
pub scan: config::filesystem::Scan,
pub parsing: config::Parsing,
pub index: config::Index,
pub cover_art: config::CoverArt,
}

#[derive(Clone)]
Expand Down
1 change: 1 addition & 0 deletions nghe-backend/src/test/mock_impl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ impl Config {
scan: self.filesystem.scan,
parsing: self.parsing.clone(),
index: self.index.clone(),
cover_art: self.cover_art.clone(),
}
}
}
Expand Down

0 comments on commit 34ff2d1

Please sign in to comment.