Compare commits

..

1 Commits

Author SHA1 Message Date
Connor Johnstone cc42f8ecbb Added the import/cleanup functionality 2026-03-24 15:58:14 -04:00
4 changed files with 102 additions and 0 deletions
+26
View File
@@ -94,3 +94,29 @@ pub async fn delete(db: &DatabaseConnection, id: i32) -> DbResult<()> {
Albums::delete_by_id(id).exec(db).await?;
Ok(())
}
pub async fn delete_by_artist(db: &DatabaseConnection, artist_id: i32) -> DbResult<u64> {
let result = Albums::delete_many()
.filter(album::Column::ArtistId.eq(artist_id))
.exec(db)
.await?;
Ok(result.rows_affected)
}
/// Delete albums that have no tracks referencing them.
pub async fn delete_empty(db: &DatabaseConnection) -> DbResult<u64> {
let all = Albums::find().all(db).await?;
let mut deleted = 0u64;
for a in all {
let has_tracks = crate::entities::track::Entity::find()
.filter(crate::entities::track::Column::AlbumId.eq(a.id))
.count(db)
.await?
> 0;
if !has_tracks {
Albums::delete_by_id(a.id).exec(db).await?;
deleted += 1;
}
}
Ok(deleted)
}
+39
View File
@@ -127,6 +127,45 @@ pub async fn list_monitored(db: &DatabaseConnection) -> DbResult<Vec<Artist>> {
.await?)
}
/// Delete artists that have no tracks, no wanted items, no albums, and are not monitored.
pub async fn delete_unused(db: &DatabaseConnection) -> DbResult<u64> {
let conn = db;
let all = Artists::find().all(conn).await?;
let mut deleted = 0u64;
for a in all {
if a.monitored {
continue;
}
let has_tracks = crate::entities::track::Entity::find()
.filter(crate::entities::track::Column::ArtistId.eq(a.id))
.count(conn)
.await?
> 0;
if has_tracks {
continue;
}
let has_wanted = crate::entities::wanted_item::Entity::find()
.filter(crate::entities::wanted_item::Column::ArtistId.eq(a.id))
.count(conn)
.await?
> 0;
if has_wanted {
continue;
}
let has_albums = crate::entities::album::Entity::find()
.filter(crate::entities::album::Column::ArtistId.eq(a.id))
.count(conn)
.await?
> 0;
if has_albums {
continue;
}
Artists::delete_by_id(a.id).exec(conn).await?;
deleted += 1;
}
Ok(deleted)
}
pub async fn update_last_checked(db: &DatabaseConnection, id: i32) -> DbResult<Artist> {
let existing = get_by_id(db, id).await?;
let mut active: ActiveModel = existing.into();
+21
View File
@@ -175,6 +175,27 @@ pub async fn get_recent(db: &DatabaseConnection, days: u32, limit: u64) -> DbRes
.await?)
}
pub async fn delete_by_artist(db: &DatabaseConnection, artist_id: i32) -> DbResult<u64> {
let result = Tracks::delete_many()
.filter(track::Column::ArtistId.eq(artist_id))
.exec(db)
.await?;
Ok(result.rows_affected)
}
/// Delete tracks whose files no longer exist on disk.
pub async fn delete_orphaned(db: &DatabaseConnection) -> DbResult<u64> {
let all = Tracks::find().all(db).await?;
let mut deleted = 0u64;
for t in all {
if !std::path::Path::new(&t.file_path).exists() {
Tracks::delete_by_id(t.id).exec(db).await?;
deleted += 1;
}
}
Ok(deleted)
}
/// Get tracks by artist name (case-insensitive match).
pub async fn get_by_artist_name(db: &DatabaseConnection, name: &str) -> DbResult<Vec<Track>> {
Ok(Tracks::find()
+16
View File
@@ -84,6 +84,22 @@ pub async fn remove(db: &DatabaseConnection, id: i32) -> DbResult<()> {
Ok(())
}
pub async fn remove_by_artist(db: &DatabaseConnection, artist_id: i32) -> DbResult<u64> {
let result = WantedItems::delete_many()
.filter(wanted_item::Column::ArtistId.eq(artist_id))
.exec(db)
.await?;
Ok(result.rows_affected)
}
pub async fn remove_by_mbid(db: &DatabaseConnection, musicbrainz_id: &str) -> DbResult<u64> {
let result = WantedItems::delete_many()
.filter(wanted_item::Column::MusicbrainzId.eq(musicbrainz_id))
.exec(db)
.await?;
Ok(result.rows_affected)
}
/// Promote all Downloaded items to Owned status. Returns the count updated.
pub async fn promote_downloaded_to_owned(db: &DatabaseConnection) -> DbResult<u64> {
let now = Utc::now().naive_utc();