From 632905a1c7685f393b432b379279d9663a7e6674 Mon Sep 17 00:00:00 2001 From: krateng Date: Fri, 7 Jan 2022 21:47:55 +0100 Subject: [PATCH] Implemented associated artists --- maloja/database/__init__.py | 24 ++++++++++++----------- maloja/database/associated.py | 36 +++++++++++++++++++++++++++++++++++ maloja/database/sqldb.py | 35 ++++++++++++++++++++++++++++++++++ maloja/upgrade.py | 11 ++++++----- 4 files changed, 90 insertions(+), 16 deletions(-) create mode 100644 maloja/database/associated.py diff --git a/maloja/database/__init__.py b/maloja/database/__init__.py index d6da832..ba37228 100644 --- a/maloja/database/__init__.py +++ b/maloja/database/__init__.py @@ -4,7 +4,7 @@ from bottle import request, response, FormsDict, HTTPError # rest of the project from ..cleanup import CleanerAgent, CollectorAgent from .. import utilities -from ..malojatime import register_scrobbletime, time_stamps, ranges +from ..malojatime import register_scrobbletime, time_stamps, ranges, alltime from ..malojauri import uri_to_internal, internal_to_uri, compose_querystring from ..thirdparty import proxy_scrobble_all from ..globalconf import data_dir, malojaconfig, apikeystore @@ -225,30 +225,28 @@ def get_top_tracks(**keys): return results - +@waitfordb def artist_info(artist): - charts = db_aggregate(by="ARTIST") - scrobbles = len(db_query(artists=[artist])) + alltimecharts = get_charts_artists(timerange=alltime()) + scrobbles = get_scrobbles_num(artist=artist,timerange=alltime()) #we cant take the scrobble number from the charts because that includes all countas scrobbles try: - c = [e for e in charts if e["artist"] == artist][0] - others = [a for a in coa.getAllAssociated(artist) if a in ARTISTS] + c = [e for e in alltimecharts if e["artist"] == artist][0] + others = sqldb.get_associated_artists(artist) position = c["rank"] performance = get_performance(artist=artist,step="week") return { "artist":artist, "scrobbles":scrobbles, "position":position, - "associated":others, - "medals":{"gold":[],"silver":[],"bronze":[],**MEDALS_ARTISTS.get(artist,{})}, - "topweeks":WEEKLY_TOPARTISTS.get(artist,0) + "associated":others } except: # if the artist isnt in the charts, they are not being credited and we # need to show information about the credited one - artist = coa.getCredited(artist) - c = [e for e in charts if e["artist"] == artist][0] + artist = sqldb.get_credited_artists(artist)[0] + c = [e for e in alltimecharts if e["artist"] == artist][0] position = c["rank"] return {"replace":artist,"scrobbles":scrobbles,"position":position} @@ -494,6 +492,10 @@ def get_predefined_rulesets(): def start_db(): from .. import upgrade upgrade.upgrade_db(sqldb.add_scrobbles) + + from . import associated + associated.load_associated_rules() + dbstatus['healthy'] = True dbstatus['complete'] = True diff --git a/maloja/database/associated.py b/maloja/database/associated.py new file mode 100644 index 0000000..f486cef --- /dev/null +++ b/maloja/database/associated.py @@ -0,0 +1,36 @@ +## dealing with loading the associated artists rules into a database +## right now this is kind of absurd because we're storing it in a db while not +## actually using its permanence, but this makes it possible to use the information +## directly in sql + + +from doreah import tsv + + +from . import sqldb +from ..globalconf import data_dir + + +def load_associated_rules(): + # delete old + with sqldb.engine.begin() as conn: + op = sqldb.DB['associated_artists'].delete().where() + conn.execute(op) + + # load from file + raw = tsv.parse_all(data_dir["rules"](),"string","string","string") + rules = [{'source_artist':b,'target_artist':c} for [a,b,c] in raw if a=="countas"] + #allartists = set([*[r['source_artist'] for r in rules],*[r['target_artist'] for r in rules]]) + + # find ids + rules = [{k:sqldb.get_artist_id(rule[k]) for k in rule} for rule in rules] + + # write to db + ops = [ + sqldb.DB['associated_artists'].insert().values(**r) + for r in rules + ] + + with sqldb.engine.begin() as conn: + for op in ops: + conn.execute(op) diff --git a/maloja/database/sqldb.py b/maloja/database/sqldb.py index 42ec730..f92dc9f 100644 --- a/maloja/database/sqldb.py +++ b/maloja/database/sqldb.py @@ -488,8 +488,43 @@ def get_artists_map(artist_ids): return artists +### associations +def get_associated_artists(*artists): + artist_ids = [get_artist_id(a) for a in artists] + jointable = sql.join( + DB['associated_artists'], + DB['artists'], + DB['associated_artists'].c.source_artist == DB['artists'].c.id + ) + + with engine.begin() as conn: + op = jointable.select().where( + DB['associated_artists'].c.target_artist.in_(artist_ids) + ) + result = conn.execute(op).all() + + artists = artists_db_to_dict(result) + return artists + +def get_credited_artists(*artists): + artist_ids = [get_artist_id(a) for a in artists] + + jointable = sql.join( + DB['associated_artists'], + DB['artists'], + DB['associated_artists'].c.target_artist == DB['artists'].c.id + ) + + with engine.begin() as conn: + op = jointable.select().where( + DB['associated_artists'].c.source_artist.in_(artist_ids) + ) + result = conn.execute(op).all() + + artists = artists_db_to_dict(result) + return artists ### get a specific entity by id diff --git a/maloja/upgrade.py b/maloja/upgrade.py index 7029c88..4257db8 100644 --- a/maloja/upgrade.py +++ b/maloja/upgrade.py @@ -24,14 +24,15 @@ def upgrade_apikeys(): def upgrade_db(callback_add_scrobbles): - print(col['yellow']("Upgrading v2 Database to v3 Database. This could take a while...")) + oldfolder = os.path.join(dir_settings['state'],"scrobbles") newfolder = os.path.join(dir_settings['state'],".oldscrobbles") os.makedirs(newfolder,exist_ok=True) if os.path.exists(oldfolder): - scrobblefiles = os.listdir(oldfolder) - for sf in scrobblefiles: - if sf.endswith(".tsv"): + scrobblefiles = [f for f in os.listdir(oldfolder) if f.endswith(".tsv")] + if len(scrobblefiles) > 0: + print(col['yellow']("Upgrading v2 Database to v3 Database. This could take a while...")) + for sf in scrobblefiles: print(f"\tImporting from old tsv scrobble file: {sf}") if re.match(r"[0-9]+_[0-9]+\.tsv",sf): origin = 'legacy' @@ -64,4 +65,4 @@ def upgrade_db(callback_add_scrobbles): }) callback_add_scrobbles(scrobblelist) os.rename(os.path.join(oldfolder,sf),os.path.join(newfolder,sf)) - print(col['yellow']("Done!")) + print(col['yellow']("Done!"))