added tags and tag update
This commit is contained in:
parent
2acbad120c
commit
1aee2feb16
21
main.py
21
main.py
@ -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)
|
||||||
|
@ -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
128
music/model/tag.py
Normal 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
72
music/tasks/update_tag.py
Normal 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()
|
||||||
|
})
|
Loading…
Reference in New Issue
Block a user