diff --git a/maloja/database/__init__.py b/maloja/database/__init__.py index e8acca5..6a73247 100644 --- a/maloja/database/__init__.py +++ b/maloja/database/__init__.py @@ -93,7 +93,7 @@ def incoming_scrobble(rawscrobble,fix=True,client=None,api=None,dbconn=None): log(f"Incoming scrobble [Client: {client} | API: {api}]: {rawscrobble}") scrobbledict = rawscrobble_to_scrobbledict(rawscrobble, fix, client) - albumupdate = (malojaconf["ALBUM_INFORMATION_TRUST"] == 'last') + albumupdate = (malojaconfig["ALBUM_INFORMATION_TRUST"] == 'last') sqldb.add_scrobble(scrobbledict,update_album=albumupdate,dbconn=dbconn) @@ -267,6 +267,15 @@ def get_charts_tracks(dbconn=None,**keys): result = sqldb.count_scrobbles_by_track(since=since,to=to,dbconn=dbconn) return result +@waitfordb +def get_charts_albums(dbconn=None,**keys): + (since,to) = keys.get('timerange').timestamps() + if 'artist' in keys: + result = sqldb.count_scrobbles_by_album_of_artist(since=since,to=to,artist=keys['artist'],dbconn=dbconn) + else: + result = sqldb.count_scrobbles_by_album(since=since,to=to,dbconn=dbconn) + return result + @waitfordb def get_pulse(dbconn=None,**keys): @@ -421,6 +430,36 @@ def track_info(dbconn=None,**keys): } +@waitfordb +def album_info(dbconn=None,**keys): + + album = keys.get('album') + if album is None: raise exceptions.MissingEntityParameter() + + album_id = sqldb.get_album_id(album,dbconn=dbconn) + album = sqldb.get_album(album_id,dbconn=dbconn) + + alltimecharts = get_charts_albums(timerange=alltime(),dbconn=dbconn) + + #scrobbles = get_scrobbles_num(track=track,timerange=alltime()) + + c = [e for e in alltimecharts if e["album"] == album][0] + scrobbles = c["scrobbles"] + position = c["rank"] + + return { + "album":album, + "scrobbles":scrobbles, + "position":position, + "medals":{ + "gold": [year for year in cached.medals_albums if album_id in cached.medals_albums[year]['gold']], + "silver": [year for year in cached.medals_albums if album_id in cached.medals_albums[year]['silver']], + "bronze": [year for year in cached.medals_albums if album_id in cached.medals_albums[year]['bronze']], + }, + "topweeks":len([e for e in cached.weekly_topalbums if e == album_id]), + "id":album_id + } + def get_predefined_rulesets(dbconn=None): validchars = "-_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" diff --git a/maloja/database/cached.py b/maloja/database/cached.py index ea39a29..d1c0a26 100644 --- a/maloja/database/cached.py +++ b/maloja/database/cached.py @@ -14,16 +14,21 @@ medals_artists = { medals_tracks = { # year: {'gold':[],'silver':[],'bronze':[]} } +medals_albums = { + # year: {'gold':[],'silver':[],'bronze':[]} +} weekly_topartists = [] weekly_toptracks = [] +weekly_topalbums = [] @runyearly def update_medals(): - global medals_artists, medals_tracks + global medals_artists, medals_tracks, medals_albums medals_artists.clear() medals_tracks.clear() + medals_albums.clear() with sqldb.engine.begin() as conn: for year in mjt.ranges(step="year"): @@ -31,11 +36,14 @@ def update_medals(): charts_artists = sqldb.count_scrobbles_by_artist(since=year.first_stamp(),to=year.last_stamp(),resolve_ids=False,dbconn=conn) charts_tracks = sqldb.count_scrobbles_by_track(since=year.first_stamp(),to=year.last_stamp(),resolve_ids=False,dbconn=conn) + charts_albums = sqldb.count_scrobbles_by_album(since=year.first_stamp(),to=year.last_stamp(),resolve_ids=False,dbconn=conn) entry_artists = {'gold':[],'silver':[],'bronze':[]} entry_tracks = {'gold':[],'silver':[],'bronze':[]} + entry_albums = {'gold':[],'silver':[],'bronze':[]} medals_artists[year.desc()] = entry_artists medals_tracks[year.desc()] = entry_tracks + medals_albums[year.desc()] = entry_albums for entry in charts_artists: if entry['rank'] == 1: entry_artists['gold'].append(entry['artist_id']) @@ -47,6 +55,11 @@ def update_medals(): elif entry['rank'] == 2: entry_tracks['silver'].append(entry['track_id']) elif entry['rank'] == 3: entry_tracks['bronze'].append(entry['track_id']) else: break + for entry in charts_albums: + if entry['rank'] == 1: entry_albums['gold'].append(entry['album_id']) + elif entry['rank'] == 2: entry_albums['silver'].append(entry['album_id']) + elif entry['rank'] == 3: entry_albums['bronze'].append(entry['album_id']) + else: break @@ -54,9 +67,10 @@ def update_medals(): @rundaily def update_weekly(): - global weekly_topartists, weekly_toptracks + global weekly_topartists, weekly_toptracks, weekly_topalbums weekly_topartists.clear() weekly_toptracks.clear() + weekly_topalbums.clear() with sqldb.engine.begin() as conn: for week in mjt.ranges(step="week"): @@ -65,6 +79,7 @@ def update_weekly(): charts_artists = sqldb.count_scrobbles_by_artist(since=week.first_stamp(),to=week.last_stamp(),resolve_ids=False,dbconn=conn) charts_tracks = sqldb.count_scrobbles_by_track(since=week.first_stamp(),to=week.last_stamp(),resolve_ids=False,dbconn=conn) + charts_albums = sqldb.count_scrobbles_by_album(since=week.first_stamp(),to=week.last_stamp(),resolve_ids=False,dbconn=conn) for entry in charts_artists: if entry['rank'] == 1: weekly_topartists.append(entry['artist_id']) @@ -72,3 +87,6 @@ def update_weekly(): for entry in charts_tracks: if entry['rank'] == 1: weekly_toptracks.append(entry['track_id']) else: break + for entry in charts_albums: + if entry['rank'] == 1: weekly_topalbums.append(entry['album_id']) + else: break diff --git a/maloja/database/sqldb.py b/maloja/database/sqldb.py index 4b33dbe..a86bc32 100644 --- a/maloja/database/sqldb.py +++ b/maloja/database/sqldb.py @@ -246,7 +246,7 @@ def albums_db_to_dict(rows,dbconn=None): ] def album_db_to_dict(row,dbconn=None): - return albums_db_to_dict([row],dbconn=dbconn) + return albums_db_to_dict([row],dbconn=dbconn)[0] @@ -814,6 +814,35 @@ def count_scrobbles_by_track(since,to,resolve_ids=True,dbconn=None): result = rank(result,key='scrobbles') return result +@cached_wrapper +@connection_provider +def count_scrobbles_by_album(since,to,resolve_ids=True,dbconn=None): + + jointable = sql.join( + DB['scrobbles'], + DB['tracks'], + DB['scrobbles'].c.track_id == DB['tracks'].c.id + ) + + op = sql.select( + sql.func.count(sql.func.distinct(DB['scrobbles'].c.timestamp)).label('count'), + DB['tracks'].c.album_id + ).select_from(jointable).where( + DB['scrobbles'].c.timestamp<=to, + DB['scrobbles'].c.timestamp>=since, + DB['tracks'].c.album_id != None + ).group_by(DB['tracks'].c.album_id).order_by(sql.desc('count')) + result = dbconn.execute(op).all() + + if resolve_ids: + counts = [row.count for row in result] + albums = get_albums_map([row.album_id for row in result],dbconn=dbconn) + result = [{'scrobbles':row.count,'album':albums[row.album_id]} for row in result] + else: + result = [{'scrobbles':row.count,'album_id':row.album_id} for row in result] + result = rank(result,key='scrobbles') + return result + @cached_wrapper @connection_provider def count_scrobbles_by_track_of_artist(since,to,artist,dbconn=None): @@ -909,6 +938,22 @@ def get_artists_map(artist_ids,dbconn=None): return artists +@cached_wrapper_individual +@connection_provider +def get_albums_map(album_ids,dbconn=None): + op = DB['albums'].select().where( + DB['albums'].c.id.in_(album_ids) + ) + result = dbconn.execute(op).all() + + albums = {} + result = list(result) + # this will get a list of albumdicts in the correct order of our rows + albumdicts = albums_db_to_dict(result,dbconn=dbconn) + for row,albumdict in zip(result,albumdicts): + albums[row.id] = albumdict + return albums + ### associations @cached_wrapper @@ -975,6 +1020,16 @@ def get_artist(id,dbconn=None): artistinfo = result[0] return artist_db_to_dict(artistinfo,dbconn=dbconn) +@cached_wrapper +@connection_provider +def get_album(id,dbconn=None): + op = DB['albums'].select().where( + DB['albums'].c.id==id + ) + result = dbconn.execute(op).all() + + albuminfo = result[0] + return album_db_to_dict(albuminfo,dbconn=dbconn) @cached_wrapper @connection_provider