diff --git a/maloja/apis/native_v1.py b/maloja/apis/native_v1.py index 48c4c84..c51c367 100644 --- a/maloja/apis/native_v1.py +++ b/maloja/apis/native_v1.py @@ -774,23 +774,25 @@ def merge_artists(target_id,source_ids): @api.post("associate_albums_to_artist") @authenticated_function(api=True) @catch_exceptions -def associate_albums_to_artist(target_id,source_ids): - result = database.associate_albums_to_artist(target_id,source_ids) +def associate_albums_to_artist(target_id,source_ids,remove=False): + result = database.associate_albums_to_artist(target_id,source_ids,remove=remove) + descword = "removed" if remove else "added" if result: return { "status":"success", - "desc":f"{result['target']} was added as album artist of {', '.join(src['albumtitle'] for src in result['sources'])}" + "desc":f"{result['target']} was {descword} as album artist of {', '.join(src['albumtitle'] for src in result['sources'])}" } @api.post("associate_tracks_to_artist") @authenticated_function(api=True) @catch_exceptions -def associate_tracks_to_artist(target_id,source_ids): - result = database.associate_tracks_to_artist(target_id,source_ids) +def associate_tracks_to_artist(target_id,source_ids,remove=False): + result = database.associate_tracks_to_artist(target_id,source_ids,remove=remove) + descword = "removed" if remove else "added" if result: return { "status":"success", - "desc":f"{result['target']} was added as artist for {', '.join(src['title'] for src in result['sources'])}" + "desc":f"{result['target']} was {descword} as artist for {', '.join(src['title'] for src in result['sources'])}" } @api.post("associate_tracks_to_album") @@ -801,7 +803,7 @@ def associate_tracks_to_album(target_id,source_ids): if result: return { "status":"success", - "desc":f"{', '.join(src['title'] for src in result['sources'])} were added to {result['target']['albumtitle']}" + "desc":f"{', '.join(src['title'] for src in result['sources'])} were " + f"added to {result['target']['albumtitle']}" if target_id else "removed from their album" } diff --git a/maloja/database/__init__.py b/maloja/database/__init__.py index 372186e..067060b 100644 --- a/maloja/database/__init__.py +++ b/maloja/database/__init__.py @@ -269,11 +269,15 @@ def merge_albums(target_id,source_ids): @waitfordb -def associate_albums_to_artist(target_id,source_ids): +def associate_albums_to_artist(target_id,source_ids,remove=False): sources = [sqldb.get_album(id) for id in source_ids] target = sqldb.get_artist(target_id) - log(f"Adding {sources} into {target}") - sqldb.add_artists_to_albums(artist_ids=[target_id],album_ids=source_ids) + if remove: + log(f"Removing {sources} from {target}") + sqldb.remove_artists_from_albums(artist_ids=[target_id],album_ids=source_ids) + else: + log(f"Adding {sources} into {target}") + sqldb.add_artists_to_albums(artist_ids=[target_id],album_ids=source_ids) result = {'sources':sources,'target':target} dbcache.invalidate_entity_cache() dbcache.invalidate_caches() @@ -281,11 +285,15 @@ def associate_albums_to_artist(target_id,source_ids): return result @waitfordb -def associate_tracks_to_artist(target_id,source_ids): +def associate_tracks_to_artist(target_id,source_ids,remove=False): sources = [sqldb.get_track(id) for id in source_ids] target = sqldb.get_artist(target_id) - log(f"Adding {sources} into {target}") - sqldb.add_artists_to_tracks(artist_ids=[target_id],track_ids=source_ids) + if remove: + log(f"Removing {sources} from {target}") + sqldb.remove_artists_from_tracks(artist_ids=[target_id],track_ids=source_ids) + else: + log(f"Adding {sources} into {target}") + sqldb.add_artists_to_tracks(artist_ids=[target_id],track_ids=source_ids) result = {'sources':sources,'target':target} dbcache.invalidate_entity_cache() dbcache.invalidate_caches() @@ -294,10 +302,14 @@ def associate_tracks_to_artist(target_id,source_ids): @waitfordb def associate_tracks_to_album(target_id,source_ids): + # target_id None means remove from current album! sources = [sqldb.get_track(id) for id in source_ids] - target = sqldb.get_album(target_id) - log(f"Adding {sources} into {target}") - sqldb.add_tracks_to_albums({src:target_id for src in source_ids}) + if target_id: + target = sqldb.get_album(target_id) + log(f"Adding {sources} into {target}") + sqldb.add_tracks_to_albums({src:target_id for src in source_ids}) + else: + sqldb.remove_album(source_ids) result = {'sources':sources,'target':target} dbcache.invalidate_entity_cache() dbcache.invalidate_caches() @@ -350,7 +362,7 @@ def get_tracks(dbconn=None,**keys): def get_artists(dbconn=None): return sqldb.get_artists(dbconn=dbconn) - +@waitfordb def get_albums_artist_appears_on(dbconn=None,**keys): artist_id = sqldb.get_artist_id(keys['artist'],dbconn=dbconn) diff --git a/maloja/database/sqldb.py b/maloja/database/sqldb.py index fca8ef6..25a8b4e 100644 --- a/maloja/database/sqldb.py +++ b/maloja/database/sqldb.py @@ -397,6 +397,14 @@ def add_tracks_to_albums(track_to_album_id_dict,replace=False,dbconn=None): for track_id in track_to_album_id_dict: add_track_to_album(track_id,track_to_album_id_dict[track_id],dbconn=dbconn) +@connection_provider +def remove_album(*track_ids,dbconn=None): + + DB['tracks'].update().where( + DB['tracks'].c.track_id.in_(track_ids) + ).values( + album_id=None + ) ### these will 'get' the ID of an entity, creating it if necessary @@ -640,6 +648,29 @@ def add_artists_to_tracks(track_ids,artist_ids,dbconn=None): return True +@connection_provider +def remove_artists_from_tracks(track_ids,artist_ids,dbconn=None): + + # only tracks that have at least one other artist + subquery = DB['trackartists'].select().where( + ~DB['trackartists'].c.artist_id.in_(artist_ids) + ).with_only_columns( + DB['trackartists'].c.track_id + ).distinct().alias('sub') + + op = DB['trackartists'].delete().where( + sql.and_( + DB['trackartists'].c.track_id.in_(track_ids), + DB['trackartists'].c.artist_id.in_(artist_ids), + DB['trackartists'].c.track_id.in_(subquery.select()) + ) + ) + + result = dbconn.execute(op) + clean_db(dbconn=dbconn) + + return True + @connection_provider def add_artists_to_albums(album_ids,artist_ids,dbconn=None): @@ -655,6 +686,22 @@ def add_artists_to_albums(album_ids,artist_ids,dbconn=None): return True +@connection_provider +def remove_artists_from_albums(album_ids,artist_ids,dbconn=None): + + # no check here, albums are allowed to have zero artists + + op = DB['albumartists'].delete().where( + sql.and_( + DB['albumartists'].c.album_id.in_(album_ids), + DB['albumartists'].c.artist_id.in_(artist_ids) + ) + ) + + result = dbconn.execute(op) + clean_db(dbconn=dbconn) + + return True ### Merge diff --git a/maloja/web/jinja/album.jinja b/maloja/web/jinja/album.jinja index ad70d3b..6d7ebe1 100644 --- a/maloja/web/jinja/album.jinja +++ b/maloja/web/jinja/album.jinja @@ -29,6 +29,8 @@