added tags and tag update

This commit is contained in:
aj 2020-02-03 09:44:33 +00:00
parent 2acbad120c
commit 1aee2feb16
4 changed files with 317 additions and 0 deletions

21
main.py
View File

@ -1,6 +1,27 @@
from music import app from music import app
from music.tasks.update_tag import update_tag as do_update_tag
app = app app = app
def update_tag(event, context):
import base64
import logging
import json
logger = logging.getLogger('music')
if 'data' in event:
body = json.loads(base64.b64decode(event['data']).decode('utf-8'))
if 'username' not in body or 'tag_id' not in body:
logger.error('malformed body')
return
do_update_tag(username=body["username"], tag_id=body["tag_id"])
else:
logger.error('no data in event')
if __name__ == '__main__': if __name__ == '__main__':
app.run(host='127.0.0.1', port=8080, debug=True) app.run(host='127.0.0.1', port=8080, debug=True)

View File

@ -9,6 +9,7 @@ from fmframework.net.network import Network as FmNetwork
from music.db.user import DatabaseUser from music.db.user import DatabaseUser
from music.model.user import User from music.model.user import User
from music.model.playlist import Playlist, RecentsPlaylist, LastFMChartPlaylist, Sort from music.model.playlist import Playlist, RecentsPlaylist, LastFMChartPlaylist, Sort
from music.model.tag import Tag
db = firestore.Client() db = firestore.Client()
@ -324,3 +325,98 @@ def delete_playlist(username: str, name: str) -> None:
playlist.db_ref.delete() playlist.db_ref.delete()
else: else:
logger.error(f'playlist {name} not found for {username}') logger.error(f'playlist {name} not found for {username}')
def get_user_tags(username: str) -> List[Tag]:
logger.info(f'getting tags for {username}')
user = get_user(username)
if user:
tag_refs = [i for i in user.db_ref.collection(u'tags').stream()]
return [parse_tag_reference(username=username, tag_snapshot=i) for i in tag_refs]
else:
logger.error(f'user {username} not found')
def get_tag(username: str = None, tag_id: str = None) -> Optional[Tag]:
logger.info(f'retrieving {tag_id} for {username}')
user = get_user(username)
if user:
tags = [i for i in user.db_ref.collection(u'tags').where(u'tag_id', u'==', tag_id).stream()]
if len(tags) == 0:
logger.error(f'tag {tag_id} for {user} not found')
return None
if len(tags) > 1:
logger.critical(f"multiple {tag_id}'s for {user} found")
return None
return parse_tag_reference(username=username, tag_snapshot=tags[0])
else:
logger.error(f'user {username} not found')
def parse_tag_reference(username, tag_ref=None, tag_snapshot=None) -> Tag:
if tag_ref is None and tag_snapshot is None:
raise ValueError('no tag object supplied')
if tag_ref is None:
tag_ref = tag_snapshot.reference
if tag_snapshot is None:
tag_snapshot = tag_ref.get()
tag_dict = tag_snapshot.to_dict()
return Tag(tag_id=tag_dict['tag_id'],
name=tag_dict.get('name', 'n/a'),
username=username,
db_ref=tag_ref,
tracks=tag_dict.get('tracks', []),
albums=tag_dict.get('albums', []),
artists=tag_dict.get('artists', []),
count=tag_dict.get('count', 0),
proportion=tag_dict.get('proportion', 0.0),
total_user_scrobbles=tag_dict.get('total_user_scrobbles', 0),
last_updated=tag_dict.get('last_updated'))
def update_tag(username: str, tag_id: str, updates: dict) -> None:
if len(updates) > 0:
logger.debug(f'updating {tag_id} for {username}')
user = get_user(username)
tags = [i for i in user.db_ref.collection(u'tags').where(u'tag_id', u'==', tag_id).stream()]
if len(tags) == 0:
logger.error(f'tag {tag_id} for {username} not found')
return None
if len(tags) > 1:
logger.critical(f"multiple {tag_id}'s for {username} found")
return None
tag = tags[0].reference
tag.update(updates)
else:
logger.debug(f'nothing to update for {tag_id} for {username}')
def delete_tag(username: str, tag_id: str) -> None:
logger.info(f'deleting {tag_id} for {username}')
tag = get_tag(username=username, tag_id=tag_id)
if tag:
tag.db_ref.delete()
else:
logger.error(f'playlist {tag_id} not found for {username}')

128
music/model/tag.py Normal file
View File

@ -0,0 +1,128 @@
from datetime import datetime
import music.db.database as db
class Tag:
def __init__(self,
tag_id: str,
name: str,
username: str,
db_ref,
tracks,
albums,
artists,
count: int,
proportion: float,
total_user_scrobbles: int,
last_updated: datetime):
self.tag_id = tag_id
self._name = name
self.username = username
self.db_ref = db_ref
self._tracks = tracks
self._albums = albums
self._artists = artists
self._count = count
self._proportion = proportion
self._total_user_scrobbles = total_user_scrobbles
self._last_updated = last_updated
def to_dict(self):
return {
'tag_id': self.tag_id,
'name': self.name,
'username': self.username,
'tracks': self.tracks,
'albums': self.albums,
'artists': self.artists,
'count': self.count,
'proportion': self.proportion,
'last_updated': self.last_updated
}
def update_database(self, updates):
db.update_tag(username=self.username, tag_id=self.tag_id, updates=updates)
@property
def name(self):
return self._name
@name.setter
def name(self, value):
db.update_tag(username=self.username, tag_id=self.tag_id, updates={'name': value})
self._name = value
@property
def tracks(self):
return self._tracks
@tracks.setter
def tracks(self, value):
db.update_tag(username=self.username, tag_id=self.tag_id, updates={'tracks': value})
self._tracks = value
@property
def albums(self):
return self._albums
@albums.setter
def albums(self, value):
db.update_tag(username=self.username, tag_id=self.tag_id, updates={'albums': value})
self._albums = value
@property
def artists(self):
return self._artists
@artists.setter
def artists(self, value):
db.update_tag(username=self.username, tag_id=self.tag_id, updates={'artists': value})
self._artists = value
@property
def count(self):
return self._count
@count.setter
def count(self, value):
db.update_tag(username=self.username, tag_id=self.tag_id, updates={'count': value})
self._count = value
@property
def proportion(self):
return self._proportion
@proportion.setter
def proportion(self, value):
db.update_tag(username=self.username, tag_id=self.tag_id, updates={'proportion': value})
self._proportion = value
@property
def total_user_scrobbles(self):
return self._total_user_scrobbles
@total_user_scrobbles.setter
def total_user_scrobbles(self, value):
db.update_tag(username=self.username, tag_id=self.tag_id, updates={'total_user_scrobbles': value})
self._total_user_scrobbles = value
@property
def last_updated(self):
return self._last_updated
@last_updated.setter
def last_updated(self, value):
db.update_tag(username=self.username, tag_id=self.tag_id, updates={'last_updated': value})
self._last_updated = value

72
music/tasks/update_tag.py Normal file
View File

@ -0,0 +1,72 @@
import logging
from datetime import datetime
import music.db.database as database
logger = logging.getLogger(__name__)
def update_tag(username, tag_id):
logger.info(f'updating {username} / {tag_id}')
tag = database.get_tag(username=username, tag_id=tag_id)
if tag is None:
logger.error(f'{tag_id} for {username} not found')
return
user = database.get_user(username)
if user.lastfm_username is None or len(user.lastfm_username) == 0:
logger.error(f'{username} has no last.fm username')
return
net = database.get_authed_lastfm_network(username=username)
tag_count = 0
user_scrobbles = net.get_user_scrobble_count()
artists = []
for artist in tag.artists:
net_artist = net.get_artist(name=artist['name'])
if net_artist is not None:
artist['count'] = net_artist.user_scrobbles
tag_count += net_artist.user_scrobbles
artists.append(artist)
albums = []
for album in tag.albums:
net_album = net.get_album(name=album['name'], artist=album['artist'])
if net_album is not None:
album['count'] = net_album.user_scrobbles
if album['artist'].lower() not in [i.lower() for i in [j['name'] for j in artists]]:
tag_count += net_album.user_scrobbles
albums.append(album)
tracks = []
for track in tag.tracks:
net_track = net.get_track(name=track['name'], artist=track['artist'])
if net_track is not None:
track['count'] = net_track.user_scrobbles
if track['artist'].lower() not in [i.lower() for i in [j['name'] for j in artists]]:
tag_count += net_track.user_scrobbles
tracks.append(track)
tag.update_database({
'tracks': tracks,
'albums': albums,
'artists': artists,
'total_user_scrobbles': user_scrobbles,
'count': tag_count,
'proportion': (tag_count / user_scrobbles) * 100,
'last_updated': datetime.utcnow()
})