Compare commits
3 Commits
0f066d5708
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aef4708439 | ||
|
|
85e24671a3 | ||
|
|
15a4efe1e9 |
@@ -24,4 +24,5 @@ chrono = { version = "0.4", features = ["serde"] }
|
||||
dirs = "6"
|
||||
|
||||
[dev-dependencies]
|
||||
shanty-data = { path = "../shanty-data" }
|
||||
tokio = { version = "1", features = ["full", "test-util"] }
|
||||
|
||||
@@ -89,24 +89,39 @@ pub async fn add_artist(
|
||||
}
|
||||
};
|
||||
|
||||
tracing::info!(name = %resolved_name, mbid = %artist_mbid, "fetching discography");
|
||||
tracing::info!(name = %resolved_name, mbid = %artist_mbid, "fetching discography (release groups)");
|
||||
|
||||
let releases = provider
|
||||
.get_artist_releases(&artist_mbid, 100)
|
||||
let release_groups = provider
|
||||
.get_artist_release_groups(&artist_mbid)
|
||||
.await
|
||||
.map_err(|e| WatchError::Other(format!("failed to fetch discography: {e}")))?;
|
||||
.map_err(|e| WatchError::Other(format!("failed to fetch release groups: {e}")))?;
|
||||
|
||||
tracing::info!(count = releases.len(), "found releases");
|
||||
tracing::info!(count = release_groups.len(), "found release groups");
|
||||
|
||||
let mut summary = AddSummary::default();
|
||||
|
||||
for release in &releases {
|
||||
tracing::info!(title = %release.title, mbid = %release.mbid, "fetching tracks");
|
||||
for rg in &release_groups {
|
||||
// Resolve a concrete release MBID from the release group
|
||||
let release_mbid = if let Some(ref rid) = rg.first_release_mbid {
|
||||
rid.clone()
|
||||
} else {
|
||||
// Browse releases for this release group to find a concrete release
|
||||
match provider.resolve_release_from_group(&rg.mbid).await {
|
||||
Ok(rid) => rid,
|
||||
Err(e) => {
|
||||
tracing::warn!(rg = %rg.title, rg_id = %rg.mbid, error = %e, "failed to resolve release from group");
|
||||
summary.errors += 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let tracks = match provider.get_release_tracks(&release.mbid).await {
|
||||
tracing::info!(title = %rg.title, release_mbid = %release_mbid, "fetching tracks for release group");
|
||||
|
||||
let tracks = match provider.get_release_tracks(&release_mbid).await {
|
||||
Ok(t) => t,
|
||||
Err(e) => {
|
||||
tracing::warn!(release = %release.title, error = %e, "failed to fetch tracks");
|
||||
tracing::warn!(rg = %rg.title, error = %e, "failed to fetch tracks");
|
||||
summary.errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
10
src/main.rs
10
src/main.rs
@@ -130,8 +130,14 @@ async fn main() -> anyhow::Result<()> {
|
||||
if name.is_none() && mbid.is_none() {
|
||||
anyhow::bail!("provide either a name or --mbid");
|
||||
}
|
||||
let summary =
|
||||
add_artist(db.conn(), name.as_deref(), mbid.as_deref(), &mb_client, None).await?;
|
||||
let summary = add_artist(
|
||||
db.conn(),
|
||||
name.as_deref(),
|
||||
mbid.as_deref(),
|
||||
&mb_client,
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
println!("Artist watch: {summary}");
|
||||
}
|
||||
AddCommand::Album {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
use chrono::Utc;
|
||||
use sea_orm::ActiveValue::Set;
|
||||
|
||||
use shanty_data::DataResult;
|
||||
use shanty_db::entities::wanted_item::{ItemType, WantedStatus};
|
||||
use shanty_db::{Database, queries};
|
||||
use shanty_tag::error::TagResult;
|
||||
use shanty_tag::provider::*;
|
||||
use shanty_watch::{add_album, add_artist, add_track, library_summary, list_items, remove_item};
|
||||
|
||||
@@ -46,10 +46,10 @@ impl MetadataProvider for MockProvider {
|
||||
&self,
|
||||
_artist: &str,
|
||||
_title: &str,
|
||||
) -> TagResult<Vec<RecordingMatch>> {
|
||||
) -> DataResult<Vec<RecordingMatch>> {
|
||||
Ok(vec![])
|
||||
}
|
||||
async fn search_release(&self, _artist: &str, _album: &str) -> TagResult<Vec<ReleaseMatch>> {
|
||||
async fn search_release(&self, _artist: &str, _album: &str) -> DataResult<Vec<ReleaseMatch>> {
|
||||
Ok(vec![ReleaseMatch {
|
||||
mbid: "release-123".into(),
|
||||
title: "Test Album".into(),
|
||||
@@ -60,10 +60,14 @@ impl MetadataProvider for MockProvider {
|
||||
score: 100,
|
||||
}])
|
||||
}
|
||||
async fn get_recording(&self, _mbid: &str) -> TagResult<RecordingDetails> {
|
||||
Err(shanty_tag::TagError::Other("not found".into()))
|
||||
async fn get_recording(&self, _mbid: &str) -> DataResult<RecordingDetails> {
|
||||
Err(shanty_data::DataError::Other("not found".into()))
|
||||
}
|
||||
async fn search_artist(&self, _query: &str, _limit: u32) -> TagResult<Vec<ArtistSearchResult>> {
|
||||
async fn search_artist(
|
||||
&self,
|
||||
_query: &str,
|
||||
_limit: u32,
|
||||
) -> DataResult<Vec<ArtistSearchResult>> {
|
||||
Ok(vec![ArtistSearchResult {
|
||||
mbid: "artist-456".into(),
|
||||
name: "Test Artist".into(),
|
||||
@@ -77,7 +81,7 @@ impl MetadataProvider for MockProvider {
|
||||
&self,
|
||||
_mbid: &str,
|
||||
_limit: u32,
|
||||
) -> TagResult<Vec<DiscographyEntry>> {
|
||||
) -> DataResult<Vec<DiscographyEntry>> {
|
||||
Ok(vec![DiscographyEntry {
|
||||
mbid: "release-123".into(),
|
||||
title: "Test Album".into(),
|
||||
@@ -86,7 +90,7 @@ impl MetadataProvider for MockProvider {
|
||||
track_count: Some(2),
|
||||
}])
|
||||
}
|
||||
async fn get_release_tracks(&self, _release_mbid: &str) -> TagResult<Vec<ReleaseTrack>> {
|
||||
async fn get_release_tracks(&self, _release_mbid: &str) -> DataResult<Vec<ReleaseTrack>> {
|
||||
Ok(vec![
|
||||
ReleaseTrack {
|
||||
recording_mbid: "rec-1".into(),
|
||||
@@ -108,8 +112,25 @@ impl MetadataProvider for MockProvider {
|
||||
async fn get_artist_release_groups(
|
||||
&self,
|
||||
_artist_mbid: &str,
|
||||
) -> TagResult<Vec<shanty_tag::provider::ReleaseGroupEntry>> {
|
||||
Ok(vec![])
|
||||
) -> DataResult<Vec<shanty_tag::provider::ReleaseGroupEntry>> {
|
||||
Ok(vec![ReleaseGroupEntry {
|
||||
mbid: "rg-123".into(),
|
||||
title: "Test Album".into(),
|
||||
primary_type: Some("Album".into()),
|
||||
secondary_types: vec![],
|
||||
first_release_date: Some("2024".into()),
|
||||
first_release_mbid: Some("release-123".into()),
|
||||
}])
|
||||
}
|
||||
|
||||
async fn resolve_release_from_group(&self, release_group_mbid: &str) -> DataResult<String> {
|
||||
if release_group_mbid == "rg-123" {
|
||||
Ok("release-123".into())
|
||||
} else {
|
||||
Err(shanty_data::DataError::Other(format!(
|
||||
"no releases for release-group {release_group_mbid}"
|
||||
)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,9 +139,16 @@ async fn test_add_track_wanted() {
|
||||
let db = test_db().await;
|
||||
let provider = MockProvider;
|
||||
|
||||
let entry = add_track(db.conn(), Some("Radiohead"), Some("Creep"), None, &provider, None)
|
||||
.await
|
||||
.unwrap();
|
||||
let entry = add_track(
|
||||
db.conn(),
|
||||
Some("Radiohead"),
|
||||
Some("Creep"),
|
||||
None,
|
||||
&provider,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(entry.item_type, ItemType::Track);
|
||||
assert_eq!(entry.name, "Creep");
|
||||
assert_eq!(entry.status, WantedStatus::Wanted);
|
||||
@@ -133,9 +161,16 @@ async fn test_add_track_auto_owned() {
|
||||
|
||||
insert_track(&db, "Pink Floyd", "Time", "DSOTM").await;
|
||||
|
||||
let entry = add_track(db.conn(), Some("Pink Floyd"), Some("Time"), None, &provider, None)
|
||||
.await
|
||||
.unwrap();
|
||||
let entry = add_track(
|
||||
db.conn(),
|
||||
Some("Pink Floyd"),
|
||||
Some("Time"),
|
||||
None,
|
||||
&provider,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(entry.status, WantedStatus::Owned);
|
||||
}
|
||||
|
||||
@@ -182,12 +217,26 @@ async fn test_list_items_with_filters() {
|
||||
let db = test_db().await;
|
||||
let provider = MockProvider;
|
||||
|
||||
add_track(db.conn(), Some("Radiohead"), Some("Creep"), None, &provider, None)
|
||||
.await
|
||||
.unwrap();
|
||||
add_track(db.conn(), Some("Tool"), Some("Lateralus"), None, &provider, None)
|
||||
.await
|
||||
.unwrap();
|
||||
add_track(
|
||||
db.conn(),
|
||||
Some("Radiohead"),
|
||||
Some("Creep"),
|
||||
None,
|
||||
&provider,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
add_track(
|
||||
db.conn(),
|
||||
Some("Tool"),
|
||||
Some("Lateralus"),
|
||||
None,
|
||||
&provider,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let all = list_items(db.conn(), None, None, None).await.unwrap();
|
||||
assert_eq!(all.len(), 2);
|
||||
@@ -208,9 +257,16 @@ async fn test_remove_item() {
|
||||
let db = test_db().await;
|
||||
let provider = MockProvider;
|
||||
|
||||
let entry = add_track(db.conn(), Some("Radiohead"), Some("Creep"), None, &provider, None)
|
||||
.await
|
||||
.unwrap();
|
||||
let entry = add_track(
|
||||
db.conn(),
|
||||
Some("Radiohead"),
|
||||
Some("Creep"),
|
||||
None,
|
||||
&provider,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
remove_item(db.conn(), entry.id).await.unwrap();
|
||||
let all = list_items(db.conn(), None, None, None).await.unwrap();
|
||||
assert!(all.is_empty());
|
||||
@@ -223,12 +279,26 @@ async fn test_library_summary() {
|
||||
|
||||
insert_track(&db, "Pink Floyd", "Time", "DSOTM").await;
|
||||
|
||||
add_track(db.conn(), Some("Radiohead"), Some("Creep"), None, &provider, None)
|
||||
.await
|
||||
.unwrap();
|
||||
add_track(db.conn(), Some("Pink Floyd"), Some("Time"), None, &provider, None)
|
||||
.await
|
||||
.unwrap();
|
||||
add_track(
|
||||
db.conn(),
|
||||
Some("Radiohead"),
|
||||
Some("Creep"),
|
||||
None,
|
||||
&provider,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
add_track(
|
||||
db.conn(),
|
||||
Some("Pink Floyd"),
|
||||
Some("Time"),
|
||||
None,
|
||||
&provider,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let summary = library_summary(db.conn()).await.unwrap();
|
||||
assert_eq!(summary.total_items, 2);
|
||||
|
||||
Reference in New Issue
Block a user