2021-06-16 20:40:14 +01:00
|
|
|
import logging
|
|
|
|
|
2020-04-30 14:54:05 +01:00
|
|
|
from fireo.models import Model
|
|
|
|
from fireo.fields import TextField, BooleanField, DateTime, NumberField
|
2019-10-23 14:44:17 +01:00
|
|
|
|
2021-06-16 20:40:14 +01:00
|
|
|
from music.model.playlist import Playlist
|
|
|
|
|
2020-04-30 14:54:05 +01:00
|
|
|
from werkzeug.security import check_password_hash
|
2019-10-23 14:44:17 +01:00
|
|
|
|
2021-06-16 20:40:14 +01:00
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
2019-10-23 14:44:17 +01:00
|
|
|
|
2020-04-30 14:54:05 +01:00
|
|
|
class User(Model):
|
|
|
|
class Meta:
|
|
|
|
collection_name = 'spotify_users'
|
2019-10-23 14:44:17 +01:00
|
|
|
|
2020-04-30 14:54:05 +01:00
|
|
|
username = TextField(required=True)
|
|
|
|
password = TextField(required=True)
|
|
|
|
email = TextField()
|
|
|
|
type = TextField(default="user")
|
2019-10-23 14:44:17 +01:00
|
|
|
|
2020-04-30 14:54:05 +01:00
|
|
|
last_login = DateTime()
|
|
|
|
last_refreshed = DateTime()
|
|
|
|
locked = BooleanField(default=False, required=True)
|
|
|
|
validated = BooleanField(default=True, required=True)
|
2019-10-23 14:44:17 +01:00
|
|
|
|
2020-04-30 14:54:05 +01:00
|
|
|
spotify_linked = BooleanField(default=False, required=True)
|
|
|
|
access_token = TextField()
|
|
|
|
refresh_token = TextField()
|
|
|
|
token_expiry = NumberField()
|
2019-10-23 14:44:17 +01:00
|
|
|
|
2020-04-30 14:54:05 +01:00
|
|
|
lastfm_username = TextField()
|
2019-10-23 14:44:17 +01:00
|
|
|
|
|
|
|
def check_password(self, password):
|
|
|
|
return check_password_hash(self.password, password)
|
|
|
|
|
|
|
|
def to_dict(self):
|
2020-04-30 14:54:05 +01:00
|
|
|
to_return = super().to_dict()
|
2019-10-23 14:44:17 +01:00
|
|
|
|
2020-04-30 14:54:05 +01:00
|
|
|
# remove unnecessary and sensitive fields
|
|
|
|
to_return.pop('password', None)
|
|
|
|
to_return.pop('access_token', None)
|
|
|
|
to_return.pop('refresh_token', None)
|
|
|
|
to_return.pop('token_expiry', None)
|
|
|
|
to_return.pop('id', None)
|
|
|
|
to_return.pop('key', None)
|
2019-10-23 14:44:17 +01:00
|
|
|
|
2020-04-30 14:54:05 +01:00
|
|
|
return to_return
|
2021-06-16 20:40:14 +01:00
|
|
|
|
|
|
|
def get_playlist(self, playlist_name: str, single_return=True, raise_error=True):
|
|
|
|
"""Get a user's playlist by name with smart case sensitivity
|
|
|
|
|
|
|
|
Will return an exact match if possible, otherwise will return the first case-insensitive match
|
|
|
|
|
|
|
|
Args:
|
|
|
|
playlist_name (str): Subject playlist name
|
|
|
|
single_return (bool, optional): Return the best match, otherwise return (<exact>, <all matches>). <exact> will be None if not found. Defaults to True.
|
|
|
|
raise_error (bool, optional): Raise a NameError if nothing found. Defaults to True.
|
|
|
|
|
|
|
|
Raises:
|
|
|
|
NameError: If no matching playlists found
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
Optional[Playlist] or (<exact>, <all matches>): Found user's playlists
|
|
|
|
"""
|
|
|
|
|
|
|
|
smart_playlists = Playlist.collection.parent(self.key).fetch()
|
|
|
|
|
|
|
|
exact_match = None
|
|
|
|
matches = list()
|
|
|
|
for playlist in smart_playlists:
|
|
|
|
if playlist.name == playlist_name:
|
|
|
|
exact_match = playlist
|
|
|
|
if playlist.name.lower() == playlist_name.lower():
|
|
|
|
matches.append(playlist)
|
|
|
|
|
|
|
|
if len(matches) == 0:
|
|
|
|
# NO PLAYLIST FOUND
|
|
|
|
logger.critical(f'playlist not found {self.username} / {playlist_name}')
|
|
|
|
if raise_error:
|
|
|
|
raise NameError(f'Playlist {playlist_name} not found for {self.username}')
|
|
|
|
else:
|
|
|
|
return None
|
|
|
|
|
|
|
|
if single_return:
|
|
|
|
if exact_match:
|
|
|
|
return exact_match
|
|
|
|
else:
|
|
|
|
return matches[0]
|
|
|
|
else:
|
|
|
|
return exact_match, matches
|
2021-07-10 16:00:30 +01:00
|
|
|
|
|
|
|
def get_playlists(self):
|
|
|
|
"""Get all playlists for a user
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
List[Playlist]: List of users playlists
|
|
|
|
"""
|
|
|
|
return Playlist.collection.parent(self.key).fetch()
|