added playlist last_updated, made tasks more legible

This commit is contained in:
aj 2020-02-24 18:15:38 +00:00
parent b1b2844a8d
commit d6e0bb9cf8
7 changed files with 187 additions and 127 deletions

View File

@ -3,6 +3,7 @@ from flask import Blueprint, request, jsonify
import os import os
import json import json
import logging import logging
from datetime import datetime
from google.cloud import firestore from google.cloud import firestore
@ -117,7 +118,8 @@ def playlist(username=None):
'recommendation_sample': playlist_recommendation_sample if playlist_recommendation_sample is not None else 10, 'recommendation_sample': playlist_recommendation_sample if playlist_recommendation_sample is not None else 10,
'uri': None, 'uri': None,
'shuffle': playlist_shuffle if playlist_shuffle is not None else False, 'shuffle': playlist_shuffle if playlist_shuffle is not None else False,
'type': playlist_type if playlist_type is not None else 'default' 'type': playlist_type if playlist_type is not None else 'default',
'last_updated': datetime.utcnow()
} }
if user_ref.get().to_dict()['spotify_linked']: if user_ref.get().to_dict()['spotify_linked']:

View File

@ -217,6 +217,8 @@ def parse_playlist_reference(username, playlist_ref=None, playlist_snapshot=None
description_overwrite=playlist_dict.get('description_overwrite'), description_overwrite=playlist_dict.get('description_overwrite'),
description_suffix=playlist_dict.get('description_suffix'), description_suffix=playlist_dict.get('description_suffix'),
last_updated=playlist_dict.get('last_updated'),
lastfm_stat_count=playlist_dict.get('lastfm_stat_count', 0), lastfm_stat_count=playlist_dict.get('lastfm_stat_count', 0),
lastfm_stat_album_count=playlist_dict.get('lastfm_stat_album_count', 0), lastfm_stat_album_count=playlist_dict.get('lastfm_stat_album_count', 0),
lastfm_stat_artist_count=playlist_dict.get('lastfm_stat_artist_count', 0), lastfm_stat_artist_count=playlist_dict.get('lastfm_stat_artist_count', 0),
@ -247,6 +249,8 @@ def parse_playlist_reference(username, playlist_ref=None, playlist_snapshot=None
description_overwrite=playlist_dict.get('description_overwrite'), description_overwrite=playlist_dict.get('description_overwrite'),
description_suffix=playlist_dict.get('description_suffix'), description_suffix=playlist_dict.get('description_suffix'),
last_updated=playlist_dict.get('last_updated'),
lastfm_stat_count=playlist_dict.get('lastfm_stat_count', 0), lastfm_stat_count=playlist_dict.get('lastfm_stat_count', 0),
lastfm_stat_album_count=playlist_dict.get('lastfm_stat_album_count', 0), lastfm_stat_album_count=playlist_dict.get('lastfm_stat_album_count', 0),
lastfm_stat_artist_count=playlist_dict.get('lastfm_stat_artist_count', 0), lastfm_stat_artist_count=playlist_dict.get('lastfm_stat_artist_count', 0),
@ -281,6 +285,8 @@ def parse_playlist_reference(username, playlist_ref=None, playlist_snapshot=None
description_overwrite=playlist_dict.get('description_overwrite'), description_overwrite=playlist_dict.get('description_overwrite'),
description_suffix=playlist_dict.get('description_suffix'), description_suffix=playlist_dict.get('description_suffix'),
last_updated=playlist_dict.get('last_updated'),
lastfm_stat_count=playlist_dict.get('lastfm_stat_count', 0), lastfm_stat_count=playlist_dict.get('lastfm_stat_count', 0),
lastfm_stat_album_count=playlist_dict.get('lastfm_stat_album_count', 0), lastfm_stat_album_count=playlist_dict.get('lastfm_stat_album_count', 0),
lastfm_stat_artist_count=playlist_dict.get('lastfm_stat_artist_count', 0), lastfm_stat_artist_count=playlist_dict.get('lastfm_stat_artist_count', 0),

View File

@ -35,6 +35,8 @@ class Playlist:
description_overwrite: str = None, description_overwrite: str = None,
description_suffix: str = None, description_suffix: str = None,
last_updated: datetime = None,
lastfm_stat_count: int = None, lastfm_stat_count: int = None,
lastfm_stat_album_count: int = None, lastfm_stat_album_count: int = None,
lastfm_stat_artist_count: int = None, lastfm_stat_artist_count: int = None,
@ -62,6 +64,8 @@ class Playlist:
self._description_overwrite = description_overwrite self._description_overwrite = description_overwrite
self._description_suffix = description_suffix self._description_suffix = description_suffix
self._last_updated = last_updated
self._lastfm_stat_count = lastfm_stat_count self._lastfm_stat_count = lastfm_stat_count
self._lastfm_stat_album_count = lastfm_stat_album_count self._lastfm_stat_album_count = lastfm_stat_album_count
self._lastfm_stat_artist_count = lastfm_stat_artist_count self._lastfm_stat_artist_count = lastfm_stat_artist_count
@ -90,6 +94,8 @@ class Playlist:
'description_overwrite': self.description_overwrite, 'description_overwrite': self.description_overwrite,
'description_suffix': self.description_suffix, 'description_suffix': self.description_suffix,
'last_updated': self.last_updated,
'lastfm_stat_count': self.lastfm_stat_count, 'lastfm_stat_count': self.lastfm_stat_count,
'lastfm_stat_album_count': self.lastfm_stat_album_count, 'lastfm_stat_album_count': self.lastfm_stat_album_count,
'lastfm_stat_artist_count': self.lastfm_stat_artist_count, 'lastfm_stat_artist_count': self.lastfm_stat_artist_count,
@ -194,6 +200,15 @@ class Playlist:
database.update_playlist(self.username, self.name, {'description_suffix': value}) database.update_playlist(self.username, self.name, {'description_suffix': value})
self._description_suffix = value self._description_suffix = value
@property
def last_updated(self):
return self._last_updated
@last_updated.setter
def last_updated(self, value):
database.update_playlist(self.username, self.name, {'last_updated': value})
self._last_updated = value
@property @property
def lastfm_stat_count(self): def lastfm_stat_count(self):
return self._lastfm_stat_count return self._lastfm_stat_count
@ -279,6 +294,8 @@ class RecentsPlaylist(Playlist):
description_overwrite: str = None, description_overwrite: str = None,
description_suffix: str = None, description_suffix: str = None,
last_updated: datetime = None,
lastfm_stat_count: int = None, lastfm_stat_count: int = None,
lastfm_stat_album_count: int = None, lastfm_stat_album_count: int = None,
lastfm_stat_artist_count: int = None, lastfm_stat_artist_count: int = None,
@ -311,6 +328,8 @@ class RecentsPlaylist(Playlist):
description_overwrite=description_overwrite, description_overwrite=description_overwrite,
description_suffix=description_suffix, description_suffix=description_suffix,
last_updated=last_updated,
lastfm_stat_count=lastfm_stat_count, lastfm_stat_count=lastfm_stat_count,
lastfm_stat_album_count=lastfm_stat_album_count, lastfm_stat_album_count=lastfm_stat_album_count,
lastfm_stat_artist_count=lastfm_stat_artist_count, lastfm_stat_artist_count=lastfm_stat_artist_count,
@ -388,6 +407,8 @@ class LastFMChartPlaylist(Playlist):
description_overwrite: str = None, description_overwrite: str = None,
description_suffix: str = None, description_suffix: str = None,
last_updated: datetime = None,
lastfm_stat_count: int = None, lastfm_stat_count: int = None,
lastfm_stat_album_count: int = None, lastfm_stat_album_count: int = None,
lastfm_stat_artist_count: int = None, lastfm_stat_artist_count: int = None,
@ -416,6 +437,8 @@ class LastFMChartPlaylist(Playlist):
description_overwrite=description_overwrite, description_overwrite=description_overwrite,
description_suffix=description_suffix, description_suffix=description_suffix,
last_updated=last_updated,
lastfm_stat_count=lastfm_stat_count, lastfm_stat_count=lastfm_stat_count,
lastfm_stat_album_count=lastfm_stat_album_count, lastfm_stat_album_count=lastfm_stat_album_count,
lastfm_stat_artist_count=lastfm_stat_artist_count, lastfm_stat_artist_count=lastfm_stat_artist_count,

View File

@ -10,7 +10,7 @@ logger = logging.getLogger(__name__)
def create_playlist(username, name): def create_playlist(username, name):
logger.info(f'creating {username} / {name}') logger.info(f'creating spotify playlist for {username} / {name}')
user = database.get_user(username) user = database.get_user(username)
if user is not None: if user is not None:
@ -22,8 +22,8 @@ def create_playlist(username, name):
return playlist return playlist
else: else:
logger.error(f'no response received {username} / {name}') logger.error(f'no response received {username} / {name}')
return None return
else: else:
logger.error(f'{username} not found') logger.error(f'{username} not found')
return None return

View File

@ -33,71 +33,70 @@ def play_user_playlist(username,
logger.info(f'playing for {username}') logger.info(f'playing for {username}')
if user: if user is None:
if parts is None and playlists is None:
logger.critical(f'no playlists to use for creation ({username})')
return None
if parts is None:
parts = []
if playlists is None:
playlists = []
if len(parts) == 0 and len(playlists) == 0:
logger.critical(f'no playlists to use for creation ({username})')
return None
net = database.get_authed_spotify_network(username)
device = None
if device_name:
devices = net.get_available_devices()
if devices and len(devices) > 0:
device = next((i for i in devices if i.name == device_name), None)
if device is None:
logger.error(f'error selecting device {device_name} to play on')
else:
logger.warning(f'no available devices to play')
engine = PlaylistEngine(net)
player = Player(net)
processors = [DeduplicateByID()]
if shuffle:
processors.append(Shuffle())
else:
processors.append(SortReleaseDate(reverse=True))
submit_parts = parts
part_generator = PartGenerator(user=user)
for part in playlists:
submit_parts += part_generator.get_recursive_parts(part)
submit_parts = [i for i in {j for j in submit_parts}]
params = [
PlaylistSource.Params(names=submit_parts, processors=processors)
]
if include_recommendations:
params.append(RecommendationSource.Params(recommendation_limit=int(recommendation_sample)))
if playlist_type == 'recents':
boundary_date = datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(days=int(day_boundary))
tracks = engine.get_recent_playlist(params=params,
boundary_date=boundary_date,
add_this_month=add_this_month,
add_last_month=add_last_month)
else:
tracks = engine.make_playlist(params=params)
player.play(tracks=tracks, device=device)
else:
logger.critical(f'{username} not found') logger.critical(f'{username} not found')
return
if parts is None and playlists is None:
logger.critical(f'no playlists to use for creation ({username})')
return None
if parts is None:
parts = []
if playlists is None:
playlists = []
if len(parts) == 0 and len(playlists) == 0:
logger.critical(f'no playlists to use for creation ({username})')
return None
net = database.get_authed_spotify_network(username)
device = None
if device_name:
devices = net.get_available_devices()
if devices and len(devices) > 0:
device = next((i for i in devices if i.name == device_name), None)
if device is None:
logger.error(f'error selecting device {device_name} to play on')
else:
logger.warning(f'no available devices to play')
engine = PlaylistEngine(net)
player = Player(net)
processors = [DeduplicateByID()]
if shuffle:
processors.append(Shuffle())
else:
processors.append(SortReleaseDate(reverse=True))
submit_parts = parts
part_generator = PartGenerator(user=user)
for part in playlists:
submit_parts += part_generator.get_recursive_parts(part)
submit_parts = [i for i in {j for j in submit_parts}]
params = [
PlaylistSource.Params(names=submit_parts, processors=processors)
]
if include_recommendations:
params.append(RecommendationSource.Params(recommendation_limit=int(recommendation_sample)))
if playlist_type == 'recents':
boundary_date = datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(days=int(day_boundary))
tracks = engine.get_recent_playlist(params=params,
boundary_date=boundary_date,
add_this_month=add_this_month,
add_last_month=add_last_month)
else:
tracks = engine.make_playlist(params=params)
player.play(tracks=tracks, device=device)

View File

@ -23,6 +23,14 @@ def refresh_lastfm_track_stats(username, playlist_name):
playlist = database.get_playlist(username=username, name=playlist_name) playlist = database.get_playlist(username=username, name=playlist_name)
if playlist is None:
logger.critical(f'playlist {playlist_name} for {username} not found')
return
if playlist.uri is None:
logger.critical(f'playlist {playlist_name} for {username} has no spotify uri')
return
spotify_playlist = spotnet.get_playlist(uri=Uri(playlist.uri)) spotify_playlist = spotnet.get_playlist(uri=Uri(playlist.uri))
track_count = counter.count_playlist(playlist=spotify_playlist) track_count = counter.count_playlist(playlist=spotify_playlist)
@ -50,6 +58,14 @@ def refresh_lastfm_album_stats(username, playlist_name):
playlist = database.get_playlist(username=username, name=playlist_name) playlist = database.get_playlist(username=username, name=playlist_name)
if playlist is None:
logger.critical(f'playlist {playlist_name} for {username} not found')
return
if playlist.uri is None:
logger.critical(f'playlist {playlist_name} for {username} has no spotify uri')
return
spotify_playlist = spotnet.get_playlist(uri=Uri(playlist.uri)) spotify_playlist = spotnet.get_playlist(uri=Uri(playlist.uri))
album_count = counter.count_playlist(playlist=spotify_playlist, query_album=True) album_count = counter.count_playlist(playlist=spotify_playlist, query_album=True)
@ -77,6 +93,14 @@ def refresh_lastfm_artist_stats(username, playlist_name):
playlist = database.get_playlist(username=username, name=playlist_name) playlist = database.get_playlist(username=username, name=playlist_name)
if playlist is None:
logger.critical(f'playlist {playlist_name} for {username} not found')
return
if playlist.uri is None:
logger.critical(f'playlist {playlist_name} for {username} has no spotify uri')
return
spotify_playlist = spotnet.get_playlist(uri=Uri(playlist.uri)) spotify_playlist = spotnet.get_playlist(uri=Uri(playlist.uri))
artist_count = counter.count_playlist(playlist=spotify_playlist, query_artist=True) artist_count = counter.count_playlist(playlist=spotify_playlist, query_artist=True)

View File

@ -22,76 +22,82 @@ logger = logging.getLogger(__name__)
def run_user_playlist(username, playlist_name): def run_user_playlist(username, playlist_name):
"""Generate and upadate a user's playlist"""
user = database.get_user(username) user = database.get_user(username)
logger.info(f'running {username} / {playlist_name}') logger.info(f'running {username} / {playlist_name}')
if user: # PRE-RUN CHECKS
if user is None:
logger.critical(f'{username} not found')
return
playlist = database.get_playlist(username=username, name=playlist_name) playlist = database.get_playlist(username=username, name=playlist_name)
if playlist is not None: if playlist is None:
logger.critical(f'playlist not found ({username}/{playlist_name})')
return
if playlist.uri is None: if playlist.uri is None:
logger.critical(f'no playlist id to populate ({username}/{playlist_name})') logger.critical(f'no playlist id to populate ({username}/{playlist_name})')
return None return
net = database.get_authed_spotify_network(username) # END CHECKS
engine = PlaylistEngine(net) net = database.get_authed_spotify_network(username)
engine = PlaylistEngine(net)
part_generator = PartGenerator(user=user)
if isinstance(playlist, LastFMChartPlaylist) and user.lastfm_username is not None: spotify_playlist_names = part_generator.get_recursive_parts(playlist.name)
engine.sources.append(ChartSource(spotnet=net, fmnet=database.get_authed_lastfm_network(user.username)))
processors = [DeduplicateByID()] processors = [DeduplicateByID()]
params = [
PlaylistSource.Params(names=spotify_playlist_names)
]
if not isinstance(playlist, LastFMChartPlaylist): # OPTIONS
if playlist.shuffle is True: if playlist.include_recommendations:
processors.append(Shuffle()) params.append(RecommendationSource.Params(recommendation_limit=playlist.recommendation_sample))
else:
processors.append(SortReleaseDate(reverse=True))
part_generator = PartGenerator(user=user) if playlist.include_library_tracks:
submit_parts = part_generator.get_recursive_parts(playlist.name) params.append(LibraryTrackSource.Params())
# END OPTIONS
params = [
PlaylistSource.Params(names=submit_parts)
]
if playlist.include_recommendations:
params.append(RecommendationSource.Params(recommendation_limit=playlist.recommendation_sample))
if playlist.include_library_tracks:
params.append(LibraryTrackSource.Params())
if isinstance(playlist, LastFMChartPlaylist):
params.append(ChartSource.Params(chart_range=playlist.chart_range, limit=playlist.chart_limit))
if isinstance(playlist, RecentsPlaylist):
boundary_date = datetime.datetime.now(datetime.timezone.utc) - \
datetime.timedelta(days=int(playlist.day_boundary))
tracks = engine.get_recent_playlist(params=params,
processors=processors,
boundary_date=boundary_date,
add_this_month=playlist.add_this_month,
add_last_month=playlist.add_last_month)
else:
tracks = engine.make_playlist(params=params,
processors=processors)
engine.execute_playlist(tracks, Uri(playlist.uri))
overwrite = playlist.description_overwrite
suffix = playlist.description_suffix
engine.change_description(sorted(submit_parts),
uri=Uri(playlist.uri),
overwrite=overwrite,
suffix=suffix)
if isinstance(playlist, LastFMChartPlaylist):
if user.lastfm_username is None:
logger.error(f'{username} has no associated last.fm username, chart source skipped')
else: else:
logger.critical(f'playlist not found ({username}/{playlist_name})') engine.sources.append(ChartSource(spotnet=net, fmnet=database.get_authed_lastfm_network(user.username)))
return None params.append(ChartSource.Params(chart_range=playlist.chart_range, limit=playlist.chart_limit))
else: else:
logger.critical(f'{username} not found') # INCLUDE SORT METHOD (no sorting for last.fm chart playlist)
if playlist.shuffle is True:
processors.append(Shuffle())
else:
processors.append(SortReleaseDate(reverse=True))
# GENERATE TRACKS
if isinstance(playlist, RecentsPlaylist):
boundary_date = datetime.datetime.now(datetime.timezone.utc) - \
datetime.timedelta(days=int(playlist.day_boundary))
tracks = engine.get_recent_playlist(params=params,
processors=processors,
boundary_date=boundary_date,
add_this_month=playlist.add_this_month,
add_last_month=playlist.add_last_month)
else:
tracks = engine.make_playlist(params=params,
processors=processors)
# NET OPS
engine.execute_playlist(tracks, Uri(playlist.uri))
overwrite = playlist.description_overwrite
suffix = playlist.description_suffix
engine.change_description(sorted(spotify_playlist_names),
uri=Uri(playlist.uri),
overwrite=overwrite,
suffix=suffix)
playlist.last_updated = datetime.datetime.utcnow()