From 688cac81eef41d5bf71b84caab0163bfef948349 Mon Sep 17 00:00:00 2001 From: krateng Date: Wed, 29 Mar 2023 00:19:40 +0200 Subject: [PATCH 01/14] Implemented web editing for albums --- maloja/apis/native_v1.py | 10 +++++++++ maloja/database/__init__.py | 10 +++++++++ maloja/database/sqldb.py | 22 +++++++++++++++++++ .../jinja/partials/charts_albums_tiles.jinja | 2 +- maloja/web/static/js/edit.js | 5 +++++ 5 files changed, 48 insertions(+), 1 deletion(-) diff --git a/maloja/apis/native_v1.py b/maloja/apis/native_v1.py index f7e36a7..585fa11 100644 --- a/maloja/apis/native_v1.py +++ b/maloja/apis/native_v1.py @@ -714,6 +714,16 @@ def edit_track(id,title): "status":"success" } +@api.post("edit_album") +@authenticated_function(api=True) +@catch_exceptions +def edit_album(id,albumtitle): + """Internal Use Only""" + result = database.edit_album(id,{'albumtitle':albumtitle}) + return { + "status":"success" + } + @api.post("merge_tracks") @authenticated_function(api=True) diff --git a/maloja/database/__init__.py b/maloja/database/__init__.py index 7cb3c6b..978b569 100644 --- a/maloja/database/__init__.py +++ b/maloja/database/__init__.py @@ -189,6 +189,16 @@ def edit_track(id,trackinfo): return result +@waitfordb +def edit_album(id,albuminfo): + album = sqldb.get_album(id) + log(f"Renaming {album['albumtitle']} to {albuminfo['albumtitle']}") + result = sqldb.edit_album(id,albuminfo) + dbcache.invalidate_entity_cache() + dbcache.invalidate_caches() + + return result + @waitfordb def merge_artists(target_id,source_ids): sources = [sqldb.get_artist(id) for id in source_ids] diff --git a/maloja/database/sqldb.py b/maloja/database/sqldb.py index 1c0e0c5..b28e89a 100644 --- a/maloja/database/sqldb.py +++ b/maloja/database/sqldb.py @@ -558,6 +558,28 @@ def edit_track(id,trackupdatedict,dbconn=None): return True +@connection_provider +def edit_album(id,albumupdatedict,dbconn=None): + + album = get_album(id,dbconn=dbconn) + changedalbum = {**album,**albumupdatedict} + + dbentry = album_dict_to_db(albumupdatedict,dbconn=dbconn) + dbentry = {k:v for k,v in dbentry.items() if v} + + existing_album_id = get_album_id(changedalbum,create_new=False,dbconn=dbconn) + if existing_album_id not in (None,id): + raise exc.TrackExists(changedalbum) + + op = DB['albums'].update().where( + DB['albums'].c.id==id + ).values( + **dbentry + ) + result = dbconn.execute(op) + + return True + ### Merge diff --git a/maloja/web/jinja/partials/charts_albums_tiles.jinja b/maloja/web/jinja/partials/charts_albums_tiles.jinja index 56e3c4e..400d68b 100644 --- a/maloja/web/jinja/partials/charts_albums_tiles.jinja +++ b/maloja/web/jinja/partials/charts_albums_tiles.jinja @@ -28,7 +28,7 @@
- #{{ rank }} {{ album.title }} + #{{ rank }} {{ album.albumtitle }}
diff --git a/maloja/web/static/js/edit.js b/maloja/web/static/js/edit.js index d240d07..e25f9c9 100644 --- a/maloja/web/static/js/edit.js +++ b/maloja/web/static/js/edit.js @@ -161,6 +161,11 @@ function doneEditing() { searchParams.set("title", newname); var payload = {'id':entity_id,'title':newname} } + else if (entity_type == 'album') { + var endpoint = "/apis/mlj_1/edit_album"; + searchParams.set("albumtitle", newname); + var payload = {'id':entity_id,'albumtitle':newname} + } callback_func = function(req){ if (req.status == 200) { From d860e19b544cd3852e4decce3dd37fe2134dc63c Mon Sep 17 00:00:00 2001 From: krateng Date: Wed, 29 Mar 2023 15:31:04 +0200 Subject: [PATCH 02/14] Added albums to search --- maloja/apis/native_v1.py | 14 +++++++++++++- maloja/database/__init__.py | 3 +++ maloja/database/sqldb.py | 9 +++++++++ maloja/web/jinja/abstracts/base.jinja | 4 ++++ maloja/web/static/js/search.js | 25 +++++++++++++++++++++++-- 5 files changed, 52 insertions(+), 3 deletions(-) diff --git a/maloja/apis/native_v1.py b/maloja/apis/native_v1.py index 585fa11..d969115 100644 --- a/maloja/apis/native_v1.py +++ b/maloja/apis/native_v1.py @@ -592,6 +592,7 @@ def search(**keys): artists = database.db_search(query,type="ARTIST") tracks = database.db_search(query,type="TRACK") + albums = database.db_search(query,type="ALBUM") @@ -599,6 +600,7 @@ def search(**keys): # also, shorter is better (because longer titles would be easier to further specify) artists.sort(key=lambda x: ((0 if x.lower().startswith(query) else 1 if " " + query in x.lower() else 2),len(x))) tracks.sort(key=lambda x: ((0 if x["title"].lower().startswith(query) else 1 if " " + query in x["title"].lower() else 2),len(x["title"]))) + albums.sort(key=lambda x: ((0 if x["albumtitle"].lower().startswith(query) else 1 if " " + query in x["albumtitle"].lower() else 2),len(x["albumtitle"]))) # add links artists_result = [] @@ -619,7 +621,17 @@ def search(**keys): } tracks_result.append(result) - return {"artists":artists_result[:max_],"tracks":tracks_result[:max_]} + albums_result = [] + for al in albums: + result = { + 'album': al, + 'link': "/album?" + compose_querystring(internal_to_uri({"album":al})), + 'image': images.get_album_image(al) + } + if not result['album']['artists']: result['album']['displayArtist'] = malojaconfig["DEFAULT_ALBUM_ARTIST"] + albums_result.append(result) + + return {"artists":artists_result[:max_],"tracks":tracks_result[:max_],"albums":albums_result[:max_]} @api.post("newrule") diff --git a/maloja/database/__init__.py b/maloja/database/__init__.py index 978b569..37285db 100644 --- a/maloja/database/__init__.py +++ b/maloja/database/__init__.py @@ -580,4 +580,7 @@ def db_search(query,type=None): results = sqldb.search_artist(query) if type=="TRACK": results = sqldb.search_track(query) + if type=="ALBUM": + results = sqldb.search_album(query) + return results diff --git a/maloja/database/sqldb.py b/maloja/database/sqldb.py index b28e89a..26f2f62 100644 --- a/maloja/database/sqldb.py +++ b/maloja/database/sqldb.py @@ -1214,6 +1214,15 @@ def search_track(searchterm,dbconn=None): return [get_track(row.id,dbconn=dbconn) for row in result] +@cached_wrapper +@connection_provider +def search_album(searchterm,dbconn=None): + op = DB['albums'].select().where( + DB['albums'].c.albtitle_normalized.ilike(normalize_name(f"%{searchterm}%")) + ) + result = dbconn.execute(op).all() + + return [get_album(row.id,dbconn=dbconn) for row in result] ##### MAINTENANCE diff --git a/maloja/web/jinja/abstracts/base.jinja b/maloja/web/jinja/abstracts/base.jinja index 3ca1619..6d0b542 100644 --- a/maloja/web/jinja/abstracts/base.jinja +++ b/maloja/web/jinja/abstracts/base.jinja @@ -82,6 +82,10 @@ Tracks
+

+ Albums + +
diff --git a/maloja/web/static/js/search.js b/maloja/web/static/js/search.js index b5244dc..1dd60d5 100644 --- a/maloja/web/static/js/search.js +++ b/maloja/web/static/js/search.js @@ -23,11 +23,13 @@ function html_to_fragment(html) { var results_artists; var results_tracks; +var results_albums; var searchresultwrap; window.addEventListener("DOMContentLoaded",function(){ results_artists = document.getElementById("searchresults_artists"); results_tracks = document.getElementById("searchresults_tracks"); + results_albums = document.getElementById("searchresults_albums"); searchresultwrap = document.getElementById("resultwrap"); }); @@ -50,8 +52,9 @@ function searchresult() { // any older searches are now rendered irrelevant while (searches[0] != this) { searches.splice(0,1) } var result = JSON.parse(this.responseText); - var artists = result["artists"].slice(0,5) - var tracks = result["tracks"].slice(0,5) + var artists = result["artists"].slice(0,4) + var tracks = result["tracks"].slice(0,4) + var albums = result["albums"].slice(0,4) while (results_artists.firstChild) { results_artists.removeChild(results_artists.firstChild); @@ -59,6 +62,9 @@ function searchresult() { while (results_tracks.firstChild) { results_tracks.removeChild(results_tracks.firstChild); } + while (results_albums.firstChild) { + results_albums.removeChild(results_albums.firstChild); + } for (var i=0;i Date: Wed, 29 Mar 2023 17:06:07 +0200 Subject: [PATCH 03/14] Adjusted DB cleanup to account for albums --- maloja/database/sqldb.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/maloja/database/sqldb.py b/maloja/database/sqldb.py index 26f2f62..f8d89aa 100644 --- a/maloja/database/sqldb.py +++ b/maloja/database/sqldb.py @@ -1236,11 +1236,16 @@ def clean_db(dbconn=None): # tracks with no scrobbles (trackartist entries first) "from trackartists where track_id in (select id from tracks where id not in (select track_id from scrobbles))", "from tracks where id not in (select track_id from scrobbles)", - # artists with no tracks - "from artists where id not in (select artist_id from trackartists) and id not in (select target_artist from associated_artists)", + # artists with no tracks AND no albums + "from artists where id not in (select artist_id from trackartists) \ + and id not in (select target_artist from associated_artists) \ + and id not in (select artist_id from albumartists)", # tracks with no artists (scrobbles first) "from scrobbles where track_id in (select id from tracks where id not in (select track_id from trackartists))", - "from tracks where id not in (select track_id from trackartists)" + "from tracks where id not in (select track_id from trackartists)", + # albums with no tracks (albumartist entries first) + "from albumartists where album_id in (select id from albums where id not in (select album_id from tracks))", + "from albums where id not in (select album_id from tracks)" ] for d in to_delete: From 5eec25963bd58b550af55dfe52f5fabf4a7356b3 Mon Sep 17 00:00:00 2001 From: krateng Date: Wed, 29 Mar 2023 17:26:36 +0200 Subject: [PATCH 04/14] Fixed things for albumartists with no tracks --- maloja/database/__init__.py | 42 +++++++++++++++++++---------------- maloja/web/jinja/artist.jinja | 2 +- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/maloja/database/__init__.py b/maloja/database/__init__.py index 37285db..80bbf84 100644 --- a/maloja/database/__init__.py +++ b/maloja/database/__init__.py @@ -400,13 +400,21 @@ def artist_info(dbconn=None,**keys): alltimecharts = get_charts_artists(timerange=alltime(),dbconn=dbconn) scrobbles = get_scrobbles_num(artist=artist,timerange=alltime(),dbconn=dbconn) #we cant take the scrobble number from the charts because that includes all countas scrobbles - try: - c = [e for e in alltimecharts if e["artist"] == artist][0] + + # base info for everyone + result = { + "artist":artist, + "scrobbles":scrobbles, + "id":artist_id + } + + # check if credited to someone else + parent_artists = sqldb.get_credited_artists(artist) + if len(parent_artists) == 0: + c = [e for e in alltimecharts if e["artist"] == artist] + position = c[0]["rank"] if len(c) > 0 else None others = sqldb.get_associated_artists(artist,dbconn=dbconn) - position = c["rank"] - return { - "artist":artist, - "scrobbles":scrobbles, + result.update({ "position":position, "associated":others, "medals":{ @@ -414,23 +422,19 @@ def artist_info(dbconn=None,**keys): "silver": [year for year in cached.medals_artists if artist_id in cached.medals_artists[year]['silver']], "bronze": [year for year in cached.medals_artists if artist_id in cached.medals_artists[year]['bronze']], }, - "topweeks":len([e for e in cached.weekly_topartists if e == artist_id]), - "id":artist_id - } - except Exception: - # if the artist isnt in the charts, they are not being credited and we - # need to show information about the credited one - replaceartist = sqldb.get_credited_artists(artist)[0] + "topweeks":len([e for e in cached.weekly_topartists if e == artist_id]) + }) + + else: + replaceartist = parent_artists[0] c = [e for e in alltimecharts if e["artist"] == replaceartist][0] position = c["rank"] - return { - "artist":artist, + result.update({ "replace":replaceartist, - "scrobbles":scrobbles, - "position":position, - "id":artist_id - } + "position":position + }) + return result diff --git a/maloja/web/jinja/artist.jinja b/maloja/web/jinja/artist.jinja index 6f3b635..d551315 100644 --- a/maloja/web/jinja/artist.jinja +++ b/maloja/web/jinja/artist.jinja @@ -63,7 +63,7 @@

{{ info.artist | e }}

- {% if competes %}#{{ info.position }}{% endif %} + {% if competes and info['scrobbles']>0 %}#{{ info.position }}{% endif %}
{% if competes and included %} associated: {{ links.links(included) }} From deb96c9ce7211117022f70cfd3fa6757535ff7c7 Mon Sep 17 00:00:00 2001 From: krateng Date: Wed, 29 Mar 2023 17:56:07 +0200 Subject: [PATCH 05/14] Adjusted artist page for album artists --- maloja/database/__init__.py | 8 ++++++-- maloja/database/sqldb.py | 13 +++++++++++++ maloja/web/jinja/artist.jinja | 6 +++++- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/maloja/database/__init__.py b/maloja/database/__init__.py index 80bbf84..1d8dccd 100644 --- a/maloja/database/__init__.py +++ b/maloja/database/__init__.py @@ -398,14 +398,18 @@ def artist_info(dbconn=None,**keys): artist_id = sqldb.get_artist_id(artist,dbconn=dbconn) artist = sqldb.get_artist(artist_id,dbconn=dbconn) alltimecharts = get_charts_artists(timerange=alltime(),dbconn=dbconn) - scrobbles = get_scrobbles_num(artist=artist,timerange=alltime(),dbconn=dbconn) #we cant take the scrobble number from the charts because that includes all countas scrobbles + scrobbles = get_scrobbles_num(artist=artist,timerange=alltime(),dbconn=dbconn) + albums = sqldb.get_albums_of_artists(set([artist_id]),dbconn=dbconn) + isalbumartist = len(albums.get(artist_id,[]))>0 + # base info for everyone result = { "artist":artist, "scrobbles":scrobbles, - "id":artist_id + "id":artist_id, + "isalbumartist":isalbumartist } # check if credited to someone else diff --git a/maloja/database/sqldb.py b/maloja/database/sqldb.py index f8d89aa..3bc35b5 100644 --- a/maloja/database/sqldb.py +++ b/maloja/database/sqldb.py @@ -1055,6 +1055,19 @@ def get_artists_of_albums(album_ids,dbconn=None): artists.setdefault(row.album_id,[]).append(artist_db_to_dict(row,dbconn=dbconn)) return artists +@cached_wrapper_individual +@connection_provider +def get_albums_of_artists(artist_ids,dbconn=None): + op = sql.join(DB['albumartists'],DB['albums']).select().where( + DB['albumartists'].c.artist_id.in_(artist_ids) + ) + result = dbconn.execute(op).all() + + albums = {} + for row in result: + albums.setdefault(row.artist_id,[]).append(album_db_to_dict(row,dbconn=dbconn)) + return albums + @cached_wrapper_individual @connection_provider diff --git a/maloja/web/jinja/artist.jinja b/maloja/web/jinja/artist.jinja index d551315..ba4b99f 100644 --- a/maloja/web/jinja/artist.jinja +++ b/maloja/web/jinja/artist.jinja @@ -90,19 +90,22 @@ +{% if info["isalbumartist"] %}

Top Albums

{% with amountkeys={"perpage":15,"page":0} %} {% include 'partials/charts_albums.jinja' %} {% endwith %} +{% endif %} - +{% if info['scrobbles']>0 %}

Top Tracks

{% with amountkeys={"perpage":15,"page":0} %} {% include 'partials/charts_tracks.jinja' %} {% endwith %} +
@@ -180,5 +183,6 @@ {% with amountkeys = {"perpage":15,"page":0} %} {% include 'partials/scrobbles.jinja' %} {% endwith %} +{% endif %} {% endblock %} From f0bfe8dfa75bb307117d9f502bbbcece61774ad9 Mon Sep 17 00:00:00 2001 From: krateng Date: Wed, 29 Mar 2023 18:20:23 +0200 Subject: [PATCH 06/14] Added merging for albums --- maloja/apis/native_v1.py | 10 ++++++++++ maloja/database/__init__.py | 11 +++++++++++ maloja/database/sqldb.py | 23 +++++++++++++++++++++-- 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/maloja/apis/native_v1.py b/maloja/apis/native_v1.py index d969115..e7d2ff4 100644 --- a/maloja/apis/native_v1.py +++ b/maloja/apis/native_v1.py @@ -757,6 +757,16 @@ def merge_artists(target_id,source_ids): "status":"success" } +@api.post("merge_albums") +@authenticated_function(api=True) +@catch_exceptions +def merge_artists(target_id,source_ids): + """Internal Use Only""" + result = database.merge_albums(target_id,source_ids) + return { + "status":"success" + } + @api.post("reparse_scrobble") @authenticated_function(api=True) @catch_exceptions diff --git a/maloja/database/__init__.py b/maloja/database/__init__.py index 1d8dccd..628c576 100644 --- a/maloja/database/__init__.py +++ b/maloja/database/__init__.py @@ -221,6 +221,17 @@ def merge_tracks(target_id,source_ids): return result +@waitfordb +def merge_albums(target_id,source_ids): + sources = [sqldb.get_album(id) for id in source_ids] + target = sqldb.get_album(target_id) + log(f"Merging {sources} into {target}") + result = sqldb.merge_albums(target_id,source_ids) + dbcache.invalidate_entity_cache() + dbcache.invalidate_caches() + + return result + diff --git a/maloja/database/sqldb.py b/maloja/database/sqldb.py index 3bc35b5..df897e1 100644 --- a/maloja/database/sqldb.py +++ b/maloja/database/sqldb.py @@ -647,6 +647,19 @@ def merge_artists(target_id,source_ids,dbconn=None): return True +@connection_provider +def merge_albums(target_id,source_ids,dbconn=None): + + op = DB['tracks'].update().where( + DB['tracks'].c.album_id.in_(source_ids) + ).values( + album_id=target_id + ) + result = dbconn.execute(op) + clean_db(dbconn=dbconn) + + return True + ### Functions that get rows according to parameters @@ -1257,8 +1270,14 @@ def clean_db(dbconn=None): "from scrobbles where track_id in (select id from tracks where id not in (select track_id from trackartists))", "from tracks where id not in (select track_id from trackartists)", # albums with no tracks (albumartist entries first) - "from albumartists where album_id in (select id from albums where id not in (select album_id from tracks))", - "from albums where id not in (select album_id from tracks)" + "from albumartists where album_id in (select id from albums where id not in (select album_id from tracks where album_id is not null))", + "from albums where id not in (select album_id from tracks where album_id is not null)", + # albumartist entries that are missing a reference + "from albumartists where album_id not in (select album_id from tracks where album_id is not null)", + "from albumartists where artist_id not in (select id from artists)", + # trackartist entries that mare missing a reference + "from trackartists where track_id not in (select id from tracks)", + "from trackartists where artist_id not in (select id from artists)" ] for d in to_delete: From 1e70d529fbd60917fb942178dac15765e47b447d Mon Sep 17 00:00:00 2001 From: krateng Date: Wed, 29 Mar 2023 20:29:44 +0200 Subject: [PATCH 07/14] Fixed potential bug for some sql functions --- maloja/database/sqldb.py | 52 +++++++++++++++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 6 deletions(-) diff --git a/maloja/database/sqldb.py b/maloja/database/sqldb.py index df897e1..cd9e31d 100644 --- a/maloja/database/sqldb.py +++ b/maloja/database/sqldb.py @@ -1045,7 +1045,18 @@ def count_scrobbles_by_track_of_album(since,to,album,dbconn=None): @cached_wrapper_individual @connection_provider def get_artists_of_tracks(track_ids,dbconn=None): - op = sql.join(DB['trackartists'],DB['artists']).select().where( + + jointable = sql.join( + DB['trackartists'], + DB['artists'] + ) + + # we need to select to avoid multiple 'id' columns that will then + # be misinterpreted by the row-dict converter + op = sql.select( + DB['artists'], + DB['trackartists'].c.track_id + ).select_from(jointable).where( DB['trackartists'].c.track_id.in_(track_ids) ) result = dbconn.execute(op).all() @@ -1058,7 +1069,18 @@ def get_artists_of_tracks(track_ids,dbconn=None): @cached_wrapper_individual @connection_provider def get_artists_of_albums(album_ids,dbconn=None): - op = sql.join(DB['albumartists'],DB['artists']).select().where( + + jointable = sql.join( + DB['albumartists'], + DB['artists'] + ) + + # we need to select to avoid multiple 'id' columns that will then + # be misinterpreted by the row-dict converter + op = sql.select( + DB['artists'], + DB['albumartists'].c.album_id + ).select_from(jointable).where( DB['albumartists'].c.album_id.in_(album_ids) ) result = dbconn.execute(op).all() @@ -1071,7 +1093,18 @@ def get_artists_of_albums(album_ids,dbconn=None): @cached_wrapper_individual @connection_provider def get_albums_of_artists(artist_ids,dbconn=None): - op = sql.join(DB['albumartists'],DB['albums']).select().where( + + jointable = sql.join( + DB['albumartists'], + DB['albums'] + ) + + # we need to select to avoid multiple 'id' columns that will then + # be misinterpreted by the row-dict converter + op = sql.select( + DB["albums"], + DB['albumartists'].c.artist_id + ).select_from(jointable).where( DB['albumartists'].c.artist_id.in_(artist_ids) ) result = dbconn.execute(op).all() @@ -1145,7 +1178,11 @@ def get_associated_artists(*artists,dbconn=None): DB['associated_artists'].c.source_artist == DB['artists'].c.id ) - op = jointable.select().where( + # we need to select to avoid multiple 'id' columns that will then + # be misinterpreted by the row-dict converter + op = sql.select( + DB['artists'] + ).select_from(jointable).where( DB['associated_artists'].c.target_artist.in_(artist_ids) ) result = dbconn.execute(op).all() @@ -1164,8 +1201,11 @@ def get_credited_artists(*artists,dbconn=None): DB['associated_artists'].c.target_artist == DB['artists'].c.id ) - - op = jointable.select().where( + # we need to select to avoid multiple 'id' columns that will then + # be misinterpreted by the row-dict converter + op = sql.select( + DB['artists'] + ).select_from(jointable).where( DB['associated_artists'].c.source_artist.in_(artist_ids) ) result = dbconn.execute(op).all() From db2b4760a0d0be778ced7b449d47fbd496524e6a Mon Sep 17 00:00:00 2001 From: krateng Date: Wed, 29 Mar 2023 23:35:12 +0200 Subject: [PATCH 08/14] Added album showcase module for artist page --- maloja/database/__init__.py | 15 +++++++ maloja/database/sqldb.py | 43 ++++++++++++++++--- maloja/pkg_global/conf.py | 1 + maloja/web/jinja/artist.jinja | 15 +++++-- .../web/jinja/partials/album_showcase.jinja | 43 +++++++++++++++++++ maloja/web/static/css/maloja.css | 33 ++++++++++++++ 6 files changed, 140 insertions(+), 10 deletions(-) create mode 100644 maloja/web/jinja/partials/album_showcase.jinja diff --git a/maloja/database/__init__.py b/maloja/database/__init__.py index 628c576..4711cf8 100644 --- a/maloja/database/__init__.py +++ b/maloja/database/__init__.py @@ -278,6 +278,21 @@ def get_artists(dbconn=None): return sqldb.get_artists(dbconn=dbconn) +def get_albums_artist_appears_on(dbconn=None,**keys): + + artist_id = sqldb.get_artist_id(keys['artist'],dbconn=dbconn) + + albums = sqldb.get_albums_artists_appear_on([artist_id],dbconn=dbconn).get(artist_id) or [] + ownalbums = sqldb.get_albums_of_artists([artist_id],dbconn=dbconn).get(artist_id) or [] + + result = { + "own_albums":ownalbums, + "appears_on":[a for a in albums if a not in ownalbums] + } + + return result + + @waitfordb def get_charts_artists(dbconn=None,**keys): (since,to) = keys.get('timerange').timestamps() diff --git a/maloja/database/sqldb.py b/maloja/database/sqldb.py index cd9e31d..aeb9e45 100644 --- a/maloja/database/sqldb.py +++ b/maloja/database/sqldb.py @@ -368,9 +368,7 @@ def get_track_id(trackdict,create_new=True,update_album=False,dbconn=None): - op = DB['tracks'].select( -# DB['tracks'].c.id - ).where( + op = DB['tracks'].select().where( DB['tracks'].c.title_normalized==ntitle ) result = dbconn.execute(op).all() @@ -418,9 +416,7 @@ def get_artist_id(artistname,create_new=True,dbconn=None): nname = normalize_name(artistname) #print("looking for",nname) - op = DB['artists'].select( -# DB['artists'].c.id - ).where( + op = DB['artists'].select().where( DB['artists'].c.name_normalized==nname ) result = dbconn.execute(op).all() @@ -1114,6 +1110,41 @@ def get_albums_of_artists(artist_ids,dbconn=None): albums.setdefault(row.artist_id,[]).append(album_db_to_dict(row,dbconn=dbconn)) return albums +@cached_wrapper_individual +@connection_provider +# this includes the artists' own albums! +def get_albums_artists_appear_on(artist_ids,dbconn=None): + + jointable1 = sql.join( + DB["trackartists"], + DB["tracks"] + ) + jointable2 = sql.join( + jointable1, + DB["albums"] + ) + + # we need to select to avoid multiple 'id' columns that will then + # be misinterpreted by the row-dict converter + op = sql.select( + DB["albums"], + DB["trackartists"].c.artist_id + ).select_from(jointable2).where( + DB['trackartists'].c.artist_id.in_(artist_ids) + ) + result = dbconn.execute(op).all() + + albums = {} + # avoid duplicates from multiple tracks in album by same artist + already_done = {} + for row in result: + if row.id in already_done.setdefault(row.artist_id,[]): + pass + else: + albums.setdefault(row.artist_id,[]).append(album_db_to_dict(row,dbconn=dbconn)) + already_done[row.artist_id].append(row.id) + return albums + @cached_wrapper_individual @connection_provider diff --git a/maloja/pkg_global/conf.py b/maloja/pkg_global/conf.py index 7224970..f519dc5 100644 --- a/maloja/pkg_global/conf.py +++ b/maloja/pkg_global/conf.py @@ -191,6 +191,7 @@ malojaconfig = Configuration( "default_range_charts_tracks":(tp.Choice({'alltime':'All Time','year':'Year','month':"Month",'week':'Week'}), "Default Range Track Charts", "year"), "default_step_pulse":(tp.Choice({'year':'Year','month':"Month",'week':'Week','day':'Day'}), "Default Pulse Step", "month"), "charts_display_tiles":(tp.Boolean(), "Display Chart Tiles", False), + "album_showcase":(tp.Boolean(), "Display Album Showcase", True, "Display a graphical album showcase for artist overview pages instead of a chart list"), "display_art_icons":(tp.Boolean(), "Display Album/Artist Icons", True), "default_album_artist":(tp.String(), "Default Albumartist", "Various Artists"), "discourage_cpu_heavy_stats":(tp.Boolean(), "Discourage CPU-heavy stats", False, "Prevent visitors from mindlessly clicking on CPU-heavy options. Does not actually disable them for malicious actors!"), diff --git a/maloja/web/jinja/artist.jinja b/maloja/web/jinja/artist.jinja index ba4b99f..f9b5c42 100644 --- a/maloja/web/jinja/artist.jinja +++ b/maloja/web/jinja/artist.jinja @@ -91,11 +91,18 @@ {% if info["isalbumartist"] %} -

Top Albums

-{% with amountkeys={"perpage":15,"page":0} %} -{% include 'partials/charts_albums.jinja' %} -{% endwith %} +{% if settings['ALBUM_SHOWCASE'] %} +

Albums

+ {% include 'partials/album_showcase.jinja' %} +{% else %} +

Top Albums

+ + {% with amountkeys={"perpage":15,"page":0} %} + {% include 'partials/charts_albums.jinja' %} + {% endwith %} +{% endif %} + {% endif %} {% if info['scrobbles']>0 %} diff --git a/maloja/web/jinja/partials/album_showcase.jinja b/maloja/web/jinja/partials/album_showcase.jinja new file mode 100644 index 0000000..798ad65 --- /dev/null +++ b/maloja/web/jinja/partials/album_showcase.jinja @@ -0,0 +1,43 @@ +{% import 'snippets/links.jinja' as links %} + +{% set info = dbc.get_albums_artist_appears_on(filterkeys,limitkeys) %} +{% set ownalbums = info.own_albums %} +{% set otheralbums = info.appears_on %} + +
+
+ +{% for album in ownalbums %}{% endfor %} +{% if ownalbums and otheralbums%}{% endif %} +{% for album in otheralbums %}{% endfor %} + + + +{% for album in ownalbums %} + +{% endfor %} +{% if ownalbums and otheralbums%}{% endif %} +{% for album in otheralbums %} + +{% endfor %} + + + +{% for album in ownalbums %} + +{% endfor %} +{% if ownalbums and otheralbums%}{% endif %} +{% for album in otheralbums %} + +{% endfor %} + +
Appears on
+ +
+
+
+ +
+
+
{{ album.albumtitle }}{{ album.albumtitle }}
+ diff --git a/maloja/web/static/css/maloja.css b/maloja/web/static/css/maloja.css index a6c3827..d1b7524 100644 --- a/maloja/web/static/css/maloja.css +++ b/maloja/web/static/css/maloja.css @@ -898,6 +898,39 @@ table.tiles_sub a span { } +div#showcase_scroll_container { + overflow-x: scroll; + overflow-y: show; + margin-top: -15px; +} + +table.album_showcase { + text-align: center; + +} +table.album_showcase tr:nth-child(1) { + opacity: 0.3; +} +table.album_showcase td { + padding: 20px; + padding-bottom:3px; + padding-top:0px; + width: 150px; +} +table.album_showcase td.album_separator_column { + width: 40px; +} + +table.album_showcase td div { + height: 150px; + width: 150px; + + background-size: cover; + background-position: top; + + box-shadow: 0px 0px 10px 10px rgba(3,3,3,0.5); +} + .summary_rank { background-size:cover; From 12b5eb0b74f67c5daa28b47e93b62d5e34fc9713 Mon Sep 17 00:00:00 2001 From: krateng Date: Thu, 30 Mar 2023 01:26:37 +0200 Subject: [PATCH 09/14] Made the album showcase prettier --- .../web/jinja/partials/album_showcase.jinja | 37 +++++++++++++- maloja/web/static/css/maloja.css | 51 ++++++++++++------- 2 files changed, 70 insertions(+), 18 deletions(-) diff --git a/maloja/web/jinja/partials/album_showcase.jinja b/maloja/web/jinja/partials/album_showcase.jinja index 798ad65..ab53070 100644 --- a/maloja/web/jinja/partials/album_showcase.jinja +++ b/maloja/web/jinja/partials/album_showcase.jinja @@ -4,7 +4,41 @@ {% set ownalbums = info.own_albums %} {% set otheralbums = info.appears_on %} -
+
+ +{% for album in ownalbums %} + + + + + +
 
+ +
+
+
+ {{ links.links(album.artists) }}
+ {{ links.link(album) }} +
+{% endfor %} + +{% for album in otheralbums %} + + + + + +
Appears on
+ +
+
+
+ {{ links.links(album.artists) }}
+ {{ links.link(album) }} +
+{% endfor %} + +
diff --git a/maloja/web/static/css/maloja.css b/maloja/web/static/css/maloja.css index d1b7524..f8a3d8b 100644 --- a/maloja/web/static/css/maloja.css +++ b/maloja/web/static/css/maloja.css @@ -898,37 +898,54 @@ table.tiles_sub a span { } -div#showcase_scroll_container { - overflow-x: scroll; - overflow-y: show; +div#showcase_container { + display: flex; margin-top: -15px; + padding-bottom: 20px; + align-items: flex-start; + flex-wrap: wrap; } -table.album_showcase { - text-align: center; - +div#showcase_container table.album { + width: 180px; } -table.album_showcase tr:nth-child(1) { + +div#showcase_container table.album tr td { + padding-left: 15px; + padding-right: 15px; +} +div#showcase_container table.album tr:nth-child(1) td { + height:8px; opacity: 0.3; + text-align: center; } -table.album_showcase td { - padding: 20px; - padding-bottom:3px; - padding-top:0px; - width: 150px; +div#showcase_container table.album tr:nth-child(2) td { + height:150px; + padding-top:2px; + padding-bottom:2px; } -table.album_showcase td.album_separator_column { - width: 40px; +div#showcase_container table.album tr:nth-child(3) td { + height:15px; } - -table.album_showcase td div { +div#showcase_container div { height: 150px; width: 150px; background-size: cover; background-position: top; - box-shadow: 0px 0px 10px 10px rgba(3,3,3,0.5); + box-shadow: 0px 0px 10px 10px rgba(0,0,0,0.5); +} + +div#showcase_container table:hover div { + box-shadow: 0px 0px 10px 10px var(--ctrl-element-color-main); +} + +div#showcase_container span.album_artists { + font-size: 80%; +} +div#showcase_container span.album_title { + font-weight: bold; } From fd5d01b7286573c386dac2c49c0b6ffb61fc9646 Mon Sep 17 00:00:00 2001 From: krateng Date: Thu, 30 Mar 2023 14:39:44 +0200 Subject: [PATCH 10/14] Spaghetti Code --- maloja/database/__init__.py | 10 ++++ maloja/database/dbcache.py | 6 +- maloja/database/sqldb.py | 61 +++++++++++--------- maloja/proccontrol/tasks/import_scrobbles.py | 5 +- 4 files changed, 51 insertions(+), 31 deletions(-) diff --git a/maloja/database/__init__.py b/maloja/database/__init__.py index 4711cf8..7e3f3ac 100644 --- a/maloja/database/__init__.py +++ b/maloja/database/__init__.py @@ -45,6 +45,16 @@ dbstatus = { } +# we're running an auxiliary task that doesn't require all the random background +# nonsense to be fired up +# this is temporary +# FIX YO DAMN ARCHITECTURE ALREADY +AUX_MODE = False +def set_aux_mode(): + global AUX_MODE + AUX_MODE = True + + def waitfordb(func): def newfunc(*args,**kwargs): diff --git a/maloja/database/dbcache.py b/maloja/database/dbcache.py index 9b092a9..582a9e7 100644 --- a/maloja/database/dbcache.py +++ b/maloja/database/dbcache.py @@ -22,8 +22,10 @@ if malojaconfig['USE_GLOBAL_CACHE']: @runhourly def maintenance(): - print_stats() - trim_cache() + from . import AUX_MODE + if not AUX_MODE: + print_stats() + trim_cache() def print_stats(): for name,c in (('Cache',cache),('Entity Cache',entitycache)): diff --git a/maloja/database/sqldb.py b/maloja/database/sqldb.py index aeb9e45..f397713 100644 --- a/maloja/database/sqldb.py +++ b/maloja/database/sqldb.py @@ -1327,37 +1327,42 @@ def search_album(searchterm,dbconn=None): @connection_provider def clean_db(dbconn=None): - log(f"Database Cleanup...") + from . import AUX_MODE - to_delete = [ - # tracks with no scrobbles (trackartist entries first) - "from trackartists where track_id in (select id from tracks where id not in (select track_id from scrobbles))", - "from tracks where id not in (select track_id from scrobbles)", - # artists with no tracks AND no albums - "from artists where id not in (select artist_id from trackartists) \ - and id not in (select target_artist from associated_artists) \ - and id not in (select artist_id from albumartists)", - # tracks with no artists (scrobbles first) - "from scrobbles where track_id in (select id from tracks where id not in (select track_id from trackartists))", - "from tracks where id not in (select track_id from trackartists)", - # albums with no tracks (albumartist entries first) - "from albumartists where album_id in (select id from albums where id not in (select album_id from tracks where album_id is not null))", - "from albums where id not in (select album_id from tracks where album_id is not null)", - # albumartist entries that are missing a reference - "from albumartists where album_id not in (select album_id from tracks where album_id is not null)", - "from albumartists where artist_id not in (select id from artists)", - # trackartist entries that mare missing a reference - "from trackartists where track_id not in (select id from tracks)", - "from trackartists where artist_id not in (select id from artists)" - ] + if not AUX_MODE: + with SCROBBLE_LOCK: + log(f"Database Cleanup...") - for d in to_delete: - selection = dbconn.execute(sql.text(f"select * {d}")) - for row in selection.all(): - log(f"Deleting {row}") - deletion = dbconn.execute(sql.text(f"delete {d}")) + to_delete = [ + # tracks with no scrobbles (trackartist entries first) + "from trackartists where track_id in (select id from tracks where id not in (select track_id from scrobbles))", + "from tracks where id not in (select track_id from scrobbles)", + # artists with no tracks AND no albums + "from artists where id not in (select artist_id from trackartists) \ + and id not in (select target_artist from associated_artists) \ + and id not in (select artist_id from albumartists)", + # tracks with no artists (scrobbles first) + "from scrobbles where track_id in (select id from tracks where id not in (select track_id from trackartists))", + "from tracks where id not in (select track_id from trackartists)", + # albums with no tracks (albumartist entries first) + "from albumartists where album_id in (select id from albums where id not in (select album_id from tracks where album_id is not null))", + "from albums where id not in (select album_id from tracks where album_id is not null)", + # albumartist entries that are missing a reference + "from albumartists where album_id not in (select album_id from tracks where album_id is not null)", + "from albumartists where artist_id not in (select id from artists)", + # trackartist entries that mare missing a reference + "from trackartists where track_id not in (select id from tracks)", + "from trackartists where artist_id not in (select id from artists)" + ] - log("Database Cleanup complete!") + for d in to_delete: + print(d) + selection = dbconn.execute(sql.text(f"select * {d}")) + for row in selection.all(): + log(f"Deleting {row}") + deletion = dbconn.execute(sql.text(f"delete {d}")) + + log("Database Cleanup complete!") diff --git a/maloja/proccontrol/tasks/import_scrobbles.py b/maloja/proccontrol/tasks/import_scrobbles.py index b5bf620..376591d 100644 --- a/maloja/proccontrol/tasks/import_scrobbles.py +++ b/maloja/proccontrol/tasks/import_scrobbles.py @@ -21,6 +21,9 @@ outputs = { def import_scrobbles(inputf): + from ...database import set_aux_mode + set_aux_mode() + from ...database.sqldb import add_scrobbles result = { @@ -180,7 +183,7 @@ def parse_spotify_full(inputf): if len(inputfiles) == 0: print("No files found!") return - + if inputfiles != [inputf]: print("Spotify files should all be imported together to identify duplicates across the whole dataset.") if not ask("Import " + ", ".join(col['yellow'](i) for i in inputfiles) + "?",default=True): From d0d76166fc039c7bf607bf379e02a3fa8703ff17 Mon Sep 17 00:00:00 2001 From: krateng Date: Thu, 30 Mar 2023 16:08:03 +0200 Subject: [PATCH 11/14] Added functionality to parse old album information --- maloja/__main__.py | 1 + maloja/database/__init__.py | 3 +- maloja/database/sqldb.py | 95 +++++++++++++++++++++++- maloja/proccontrol/tasks/__init__.py | 1 + maloja/proccontrol/tasks/parse_albums.py | 20 +++++ 5 files changed, 118 insertions(+), 2 deletions(-) create mode 100644 maloja/proccontrol/tasks/parse_albums.py diff --git a/maloja/__main__.py b/maloja/__main__.py index 5e6d4de..4694a40 100644 --- a/maloja/__main__.py +++ b/maloja/__main__.py @@ -166,6 +166,7 @@ def main(*args,**kwargs): "generate":generate.generate_scrobbles, # maloja generate 400 "export":tasks.export, # maloja export "apidebug":apidebug.run, # maloja apidebug + "parsealbums":tasks.parse_albums, # maloja parsealbums # aux "info":print_info } diff --git a/maloja/database/__init__.py b/maloja/database/__init__.py index 7e3f3ac..9d437a1 100644 --- a/maloja/database/__init__.py +++ b/maloja/database/__init__.py @@ -163,7 +163,8 @@ def rawscrobble_to_scrobbledict(rawscrobble, fix=True, client=None): "origin":f"client:{client}" if client else "generic", "extra":{ k:scrobbleinfo[k] for k in scrobbleinfo if k not in - ['scrobble_time','track_artists','track_title','track_length','scrobble_duration','album_title','album_artists'] + ['scrobble_time','track_artists','track_title','track_length','scrobble_duration']#,'album_title','album_artists'] + # we still save album info in extra because the user might select majority album authority }, "rawscrobble":rawscrobble } diff --git a/maloja/database/sqldb.py b/maloja/database/sqldb.py index f397713..9782912 100644 --- a/maloja/database/sqldb.py +++ b/maloja/database/sqldb.py @@ -354,6 +354,11 @@ def add_track_to_album(track_id,album_id,replace=False,dbconn=None): result = dbconn.execute(op) return True +@connection_provider +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) ### these will 'get' the ID of an entity, creating it if necessary @@ -1356,7 +1361,6 @@ def clean_db(dbconn=None): ] for d in to_delete: - print(d) selection = dbconn.execute(sql.text(f"select * {d}")) for row in selection.all(): log(f"Deleting {row}") @@ -1427,9 +1431,98 @@ def merge_duplicate_tracks(artist_id,dbconn=None): +@connection_provider +def guess_albums(track_ids=None,replace=False,dbconn=None): + + MIN_NUM_TO_ASSIGN = 1 + + jointable = sql.join( + DB['scrobbles'], + DB['tracks'] + ) + + # get all scrobbles of the respective tracks that have some info + conditions = [ + DB['scrobbles'].c.extra.isnot(None) + ] + if track_ids is not None: + # only do these tracks + conditions.append( + DB['scrobbles'].c.track_id.in_(track_ids) + ) + if not replace: + # only tracks that have no album yet + conditions.append( + DB['tracks'].c.album_id.is_(None) + ) + + op = sql.select( + DB['scrobbles'] + ).select_from(jointable).where( + *conditions + ) + + result = dbconn.execute(op).all() + + # for each track, count what album info appears how often + possible_albums = {} + for row in result: + extrainfo = json.loads(row.extra) + albumtitle = extrainfo.get("album_name") or extrainfo.get("album_title") + albumartists = extrainfo.get("album_artists",[]) + if albumtitle: + hashable_albuminfo = tuple([*albumartists,albumtitle]) + possible_albums.setdefault(row.track_id,{}).setdefault(hashable_albuminfo,0) + possible_albums[row.track_id][hashable_albuminfo] += 1 + + res = {} + for track_id in possible_albums: + options = possible_albums[track_id] + if len(options)>0: + # pick the one with most occurences + mostnum = max(options[albuminfo] for albuminfo in options) + if mostnum >= MIN_NUM_TO_ASSIGN: + bestpick = [albuminfo for albuminfo in options if options[albuminfo] == mostnum][0] + #print("best pick",track_id,bestpick) + *artists,title = bestpick + res[track_id] = {"assigned":{ + "artists":artists, + "albumtitle": title + }} + if len(artists) == 0: + # for albums without artist, assume track artist + res[track_id]["guess_artists"] = True + else: + res[track_id] = {"assigned":False,"reason":"Not enough data"} + + else: + res[track_id] = {"assigned":False,"reason":"No scrobbles with album information found"} + missing_artists = [track_id for track_id in res if res[track_id].get("guess_artists")] + + #we're pointlessly getting the albumartist names here even though the IDs would be enough + #but it's better for function separation I guess + jointable = sql.join( + DB['trackartists'], + DB['artists'] + ) + op = sql.select( + DB['trackartists'].c.track_id, + DB['artists'] + ).select_from(jointable).where( + DB['trackartists'].c.track_id.in_(missing_artists) + ) + result = dbconn.execute(op).all() + + for row in result: + res[row.track_id]["assigned"]["artists"].append(row.name) + for track_id in res: + if res[track_id].get("guess_artists"): + del res[track_id]["guess_artists"] + + return res diff --git a/maloja/proccontrol/tasks/__init__.py b/maloja/proccontrol/tasks/__init__.py index cf2cd85..90ce051 100644 --- a/maloja/proccontrol/tasks/__init__.py +++ b/maloja/proccontrol/tasks/__init__.py @@ -1,3 +1,4 @@ from .import_scrobbles import import_scrobbles from .backup import backup from .export import export # read that line out loud +from .parse_albums import parse_albums diff --git a/maloja/proccontrol/tasks/parse_albums.py b/maloja/proccontrol/tasks/parse_albums.py new file mode 100644 index 0000000..618eabf --- /dev/null +++ b/maloja/proccontrol/tasks/parse_albums.py @@ -0,0 +1,20 @@ + + + +def parse_albums(replace=False): + + from ...database.sqldb import guess_albums, get_album_id, add_track_to_album + + print("Parsing album information...") + result = guess_albums(replace=replace) + + result = {track_id:result[track_id] for track_id in result if result[track_id]["assigned"]} + print("Adding",len(result),"tracks to albums...") + i = 0 + for track_id in result: + album_id = get_album_id(result[track_id]["assigned"]) + add_track_to_album(track_id,album_id) + i += 1 + if (i % 100) == 0: + print(i,"of",len(result)) + print("Done!") From 3877401a051c1a673a7afc539671374fc62dc696 Mon Sep 17 00:00:00 2001 From: krateng Date: Thu, 30 Mar 2023 16:43:03 +0200 Subject: [PATCH 12/14] Added handling for albums when merging artists --- maloja/database/sqldb.py | 64 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/maloja/database/sqldb.py b/maloja/database/sqldb.py index 9782912..882884b 100644 --- a/maloja/database/sqldb.py +++ b/maloja/database/sqldb.py @@ -626,6 +626,28 @@ def merge_artists(target_id,source_ids,dbconn=None): result = dbconn.execute(op) + + # same for albums + op = DB['albumartists'].select().where( + DB['albumartists'].c.artist_id.in_(source_ids + [target_id]) + ) + result = dbconn.execute(op) + + album_ids = set(row.album_id for row in result) + + op = DB['albumartists'].delete().where( + DB['albumartists'].c.artist_id.in_(source_ids + [target_id]), + ) + result = dbconn.execute(op) + + op = DB['albumartists'].insert().values([ + {'album_id':album_id,'artist_id':target_id} + for album_id in album_ids + ]) + + result = dbconn.execute(op) + + # tracks_artists = {} # for row in result: # tracks_artists.setdefault(row.track_id,[]).append(row.artist_id) @@ -641,8 +663,9 @@ def merge_artists(target_id,source_ids,dbconn=None): # ) # result = dbconn.execute(op) - # this could have created duplicate tracks + # this could have created duplicate tracks and albums merge_duplicate_tracks(artist_id=target_id,dbconn=dbconn) + merge_duplicate_albums(artist_id=target_id,dbconn=dbconn) clean_db(dbconn=dbconn) return True @@ -1431,6 +1454,45 @@ def merge_duplicate_tracks(artist_id,dbconn=None): +@connection_provider +def merge_duplicate_albums(artist_id,dbconn=None): + rows = dbconn.execute( + DB['albumartists'].select().where( + DB['albumartists'].c.artist_id == artist_id + ) + ) + affected_albums = [r.album_id for r in rows] + + album_artists = {} + rows = dbconn.execute( + DB['albumartists'].select().where( + DB['albumartists'].c.album_id.in_(affected_albums) + ) + ) + + + for row in rows: + album_artists.setdefault(row.album_id,[]).append(row.artist_id) + + artist_combos = {} + for album_id in album_artists: + artist_combos.setdefault(tuple(sorted(album_artists[album_id])),[]).append(album_id) + + for c in artist_combos: + if len(artist_combos[c]) > 1: + album_identifiers = {} + for album_id in artist_combos[c]: + album_identifiers.setdefault(normalize_name(get_album(album_id)['albumtitle']),[]).append(album_id) + for album in album_identifiers: + if len(album_identifiers[album]) > 1: + target,*src = album_identifiers[album] + merge_albums(target,src,dbconn=dbconn) + + + + + + @connection_provider def guess_albums(track_ids=None,replace=False,dbconn=None): From e52d57e4139a0a37311c46a0b981e3ff944f7064 Mon Sep 17 00:00:00 2001 From: krateng Date: Thu, 30 Mar 2023 17:05:35 +0200 Subject: [PATCH 13/14] Fixed design of album search results --- maloja/web/jinja/abstracts/base.jinja | 4 ++-- maloja/web/static/css/maloja.css | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/maloja/web/jinja/abstracts/base.jinja b/maloja/web/jinja/abstracts/base.jinja index 6d0b542..8b3e8a6 100644 --- a/maloja/web/jinja/abstracts/base.jinja +++ b/maloja/web/jinja/abstracts/base.jinja @@ -80,11 +80,11 @@

Tracks - +


Albums - +
diff --git a/maloja/web/static/css/maloja.css b/maloja/web/static/css/maloja.css index f8a3d8b..239b44a 100644 --- a/maloja/web/static/css/maloja.css +++ b/maloja/web/static/css/maloja.css @@ -189,7 +189,7 @@ div.searchresults tr td:nth-child(2) { padding-left:10px; } -div.searchresults table.searchresults_tracks td span:nth-child(1) { +div.searchresults table.searchresults_extrainfo td span:nth-child(1) { font-size:12px; color:grey; From 0bdcb94f5b997ff6eb574e72a8db17e887766e3d Mon Sep 17 00:00:00 2001 From: krateng Date: Thu, 30 Mar 2023 17:18:08 +0200 Subject: [PATCH 14/14] Scrobble guessing can now use rawscrobble --- maloja/database/sqldb.py | 5 +++++ maloja/proccontrol/tasks/parse_albums.py | 3 +++ 2 files changed, 8 insertions(+) diff --git a/maloja/database/sqldb.py b/maloja/database/sqldb.py index 882884b..0497456 100644 --- a/maloja/database/sqldb.py +++ b/maloja/database/sqldb.py @@ -1532,6 +1532,11 @@ def guess_albums(track_ids=None,replace=False,dbconn=None): extrainfo = json.loads(row.extra) albumtitle = extrainfo.get("album_name") or extrainfo.get("album_title") albumartists = extrainfo.get("album_artists",[]) + if not albumtitle: + # try the raw scrobble + extrainfo = json.loads(row.rawscrobble) + albumtitle = extrainfo.get("album_name") or extrainfo.get("album_title") + albumartists = albumartists or extrainfo.get("album_artists",[]) if albumtitle: hashable_albuminfo = tuple([*albumartists,albumtitle]) possible_albums.setdefault(row.track_id,{}).setdefault(hashable_albuminfo,0) diff --git a/maloja/proccontrol/tasks/parse_albums.py b/maloja/proccontrol/tasks/parse_albums.py index 618eabf..125df0c 100644 --- a/maloja/proccontrol/tasks/parse_albums.py +++ b/maloja/proccontrol/tasks/parse_albums.py @@ -3,6 +3,9 @@ def parse_albums(replace=False): + from ...database import set_aux_mode + set_aux_mode() + from ...database.sqldb import guess_albums, get_album_id, add_track_to_album print("Parsing album information...")