def retrieve(self, request, source_type, playlist_id, format=None): """Perform metadata lookup on the user playlists.""" page = int(request.QUERY_PARAMS.get('page', 1)) cache_key = build_key('user-playlist-tracks', source_type, playlist_id) response = cache.get(cache_key) if response: return Response(response) oauth_cache_key = build_key( 'user-credentials', source_type, request.user.id) credentials = cache.get(oauth_cache_key) if credentials is None: raise ThridPartyOauthRequired source_client = build_client(source_type) if source_client is None: raise InvalidBackend # search using requested source_type offset = (page-1)*20 queryset = source_client.playlist_tracks( playlist_id, credentials['user']['id'], credentials['auth']['access_token'], page*200, offset) response = paginate_queryset( PaginatedTrackSerializer, request, queryset, page) cache.set(cache_key, response, 86400) return Response(response)
def get(self, request, source_type, format=None): page = int(request.QUERY_PARAMS.get('page', 1)) limit = 20 offset = (page-1)*limit query = request.QUERY_PARAMS.get('q', '') if not query: raise MissingParameter cache_key = build_key('mtdttrcksrch', source_type, query, page) response = cache.get(cache_key) if response is not None: return Response(response) source_client = build_client(source_type) if source_client is None: raise InvalidBackend queryset = source_client.search_tracks(query, limit, offset) response = paginate_queryset( PaginatedTrackSerializer, request, queryset, page) response['query'] = query cache.set(cache_key, response, 86400) return Response(response)
def get_head_track(self, queue_id, is_active, random=False): """Look up the track at the top of a given queue. If queue is empty and "random" is set to True, will fetch a random track, based of the queues history. Returns serialized track or None. """ head_track = cache.get(self._cache_key(queue_id)) if head_track is None and is_active: queued_tracks = QueueTrack.objects.filter(queue_id=queue_id) # If there are tracks in the queue, then grab the top track if len(queued_tracks): head_track = queued_tracks[0] # Ensure track exists at source, # else remove track and run method again. try: # Throws an exception if track is not found, # or source no longer exists track_exists(track_id=head_track.track.id) except: cache.delete(self._cache_key(queue_id)) cache.delete(build_key('queue-tracks-queryset', queue_id)) return self.get_head_track(queue_id, is_active, random) else: if random: # Else use a randomly selected track head_track = self._queue_radio(queue_id) if head_track: expire_in = (head_track.track.duration_ms/1000) cache.delete(self._queue_cache_key(queue_id)) cache.set(self._cache_key(queue_id), head_track, expire_in) return head_track
def test_get_cached(self): self.api_client.get('/api/metadata/search/youtube/?q=Haim') resp = self.api_client.get('/api/metadata/search/youtube/?q=Haim') return_data = json.loads(resp.content) cache_key = build_key('mtdttrcksrch', 'youtube', 'Haim', '1') cached_data = cache.get(cache_key) self.assertEqual(return_data, cached_data)
def test_get_cached(self): self.api_client.get('/api/metadata/lookup/soundcloud/153868082/') resp = self.api_client.get( '/api/metadata/lookup/soundcloud/153868082/' ) return_data = json.loads(resp.content) cache_key = build_key('mtdt-lkp', 'soundcloud', 153868082) cached_data = cache.get(cache_key) self.assertEqual(return_data, cached_data)
def cached_get_or_create(self, album): """Get or create an album record from db, Returns an Album model reference. """ cache_key = build_key("album", album["source_type"], album["source_id"]) record = cache.get(cache_key) if record is None: record, created = self.get_or_create( source_id=album["source_id"], source_type=album["source_type"], name=album["name"] ) cache.set(cache_key, record) return record
def _get_track_data(source_type, source_id): """Does a track lookup using the thrid party api client. Returns a dictionary. """ cache_key = build_key('track_lookup', source_type, source_id) track_data = cache.get(cache_key) if track_data is None: source_client = build_client(source_type) track_data = source_client.lookup_track(source_id) cache.set(cache_key, track_data, 86400) return track_data
def list(self, request, source_type, format=None): """Perform metadata lookup on the user playlists.""" cache_key = build_key('user-playlists', source_type, request.user.id) playlists = cache.get(cache_key) if playlists: return Response(playlists) oauth_cache_key = build_key( 'user-credentials', source_type, request.user.id) credentials = cache.get(oauth_cache_key) if credentials is None: raise ThridPartyOauthRequired source_client = build_client(source_type) if source_client is None: raise InvalidBackend response = source_client.playlists( credentials['user']['id'], credentials['auth']['access_token']) cache.set(cache_key, response, 86400) return Response(response)
def get_player(self, user_id): c_key = build_key('player', user_id) player = cache.get(c_key) # If no player is found, trigger a model save which caches the player record # This ensures that players are always up to date. if player: # If player is not active, save the record, which will try to set active to true # if it is the only player listening on a given queue if player.active is False: player = Player.objects.get(pk=user_id).save() else: player = Player.objects.get(pk=user_id).save() return player
def save(self, *args, **kwargs): """Set some default values. """ # If no other tracks are active on the queue, then set active to true queryset = Player.objects.filter(queue=self.queue, active=True) if not queryset.count(): self.active = True elif queryset.exclude(id=self.id).count(): self.active = False super(Player, self).save(args, kwargs) cache.set(build_key('player', self.id), self) return self
def list(self, request): """Return a paginated list of queue json objects.""" page = int(request.QUERY_PARAMS.get('page', 1)) cache_key = build_key('users-queryset') response = cache.get(cache_key) if response: return Response(response) queryset = User.objects.exclude(profile__isnull=True) response = paginate_queryset( PaginatedUserSerializer, request, queryset, page) cache.set(cache_key, response, 86400) return Response(response)
def get(self, request, source_type, format=None): auth_code = request.QUERY_PARAMS.get('code', None) if source_type.lower() == 'spotify': source_client_id = settings.SPOTIFY_CLIENT_ID source_client_secret = settings.SPOTIFY_CLIENT_SECRET elif source_type.lower() == 'soundcloud': source_client_id = settings.SOUNDCLOUD_CLIENT_ID source_client_secret = settings.SOUNDCLOUD_CLIENT_SECRET elif source_type.lower() == 'youtube': source_client_id = settings.GOOGLE_OAUTH2_CLIENT_ID source_client_secret = settings.GOOGLE_OAUTH2_CLIENT_SECRET else: raise InvalidBackend cache_key = build_key('user-credentials', source_type, request.user.id) credentials = cache.get(cache_key) if credentials: return Response(credentials) source_client = build_client(source_type) if source_client is None: raise InvalidBackend try: # Prompt user to login if auth_code is None: redirect_url = source_client.login_url( request.build_absolute_uri(request.path), source_client_id, source_client_secret ) return redirect(redirect_url) # Else exchange the auth code for an oauth token else: credentials = source_client.exchange_code( auth_code, request.build_absolute_uri(request.path), source_client_id, source_client_secret ) except: raise OauthFailed cache.set( cache_key, credentials, credentials['auth']['expires_in']) return Response(credentials)
def track_exists(track_id): """Looks up the track using the thrid party client to ensure the track has not be removed from source. """ try: track = Track.objects.get(pk=track_id) except: raise RecordNotFound('The track could not be found.') source_client = build_client(track.source_type) try: source_client.lookup_track(track.source_id) except: cache.delete(build_key('tracklist-queryset')) track.delete() raise RecordNoLongerExists
def cached_get_or_create(self, artists): """Get or create artist records from db. Returns a list of artist json objects """ records = [] for (i, artist) in enumerate(artists): cache_key = build_key("artist", artist["source_type"], artist["source_id"]) record = cache.get(cache_key) if record is None: record, created = self.get_or_create( source_id=artist["source_id"], source_type=artist["source_type"], name=artist["name"] ) cache.set(cache_key, record) records.append(record) return records
def authenticate(self, request): # Retrieve the access token from the request header access_token = request.META.get('HTTP_X_GOOGLE_AUTH_TOKEN') if access_token: cache_key = build_key('usertoken', access_token) user = cache.get(cache_key) if user is None: # Validated the token and pull down the user details params = {'alt': 'json', 'access_token': access_token} r = requests.get( 'https://www.googleapis.com/oauth2/v1/userinfo', params=params ) person = r.json() # Ensure a valid json object is returned if person.get('error') or person['verified_email'] is False: raise exceptions.AuthenticationFailed( person['error']['message'] ) # Retrieve the whitelisted domains set in the .env file domains = os.environ.get('GOOGLE_WHITE_LISTED_DOMAINS', '') white_listed_domains = re.findall('([a-z\.]+)', domains) # Ensure the users domain exists within the whilelist if person['hd'] not in white_listed_domains: raise exceptions.AuthenticationFailed('Invalid domain') user, created = User.objects.get_or_create( username=person['name'], first_name=person['given_name'], last_name=person['family_name'], email=person['email'], defaults={'password': make_password(person['id'])} ) if created: profile = Profile.objects.get(user=user) profile.avatar = person['picture'] profile.save() cache.set(cache_key, user, 3600) return (user, None) return None
def get(self, request, source_type, source_id, format=None): cache_key = build_key('mtdt-lkp', source_type, source_id) response = cache.get(cache_key) if response is not None: return Response(response) source_client = build_client(source_type) if source_client is None: raise InvalidBackend try: results = source_client.lookup_track(source_id) except: raise RecordNotFound response = TrackSerializer(results).data cache.set(cache_key, response, 86400) return Response(response)
def custom_create(self, track_id, queue_id, owner, record=True): """Create queue track.""" track = Track.objects.get(id=track_id) queue = Queue.objects.get(id=queue_id) total_queue_records = self.filter(queue=queue).count() queue_track = self.create( track=track, queue=queue, position=total_queue_records+1, owner=owner) if record: QueueTrackHistory.objects.create( track=track, queue=queue, owner=owner) # Delete the historic track list, # if a track is manually added to queue cache.delete(build_key('queue-head-history', queue_id)) return queue_track
def cached_get_or_create(self, track, owner): """Saves a track to the db, unless one already exists. Returns a track json object """ cache_key = build_key("track", track["source_type"], track["source_id"]) record = cache.get(cache_key) if record is None: try: record = self.get(source_id=track["source_id"], source_type=track["source_type"]) except: if track["album"]: track["album"] = Album.objects.cached_get_or_create(track["album"]) record = self.create( source_id=track["source_id"], source_type=track["source_type"], name=track["name"], duration_ms=track["duration_ms"], preview_url=track["preview_url"], uri=track["uri"], track_number=track["track_number"], album=track["album"], image_small=track["image_small"], image_medium=track["image_medium"], image_large=track["image_large"], owner=owner, ) if track["artists"]: artists = Artist.objects.cached_get_or_create(track["artists"]) for artist in artists: record.artists.add(artist) cache.set(cache_key, record) return record
def clear_cache(sender, **kwargs): cache_key = build_key('users-queryset') cache.delete(cache_key)
def _history_cache_key(self, queue_id): """Build key used for caching the playlist tracks data.""" return build_key('queue-history', queue_id)
def _queue_cache_key(self, queue_id): """Build key used for caching the playlist tracks data.""" return build_key('queue-tracks-queryset', queue_id)
def _cache_key(self, queue_id): """Build key used for caching the queue tracks data.""" return build_key('queue-head-track', queue_id)
def create_user_profile(sender, instance, created, **kwargs): cache_key = build_key('users-queryset') cache.delete(cache_key) if created: Profile.objects.create(user=instance)
def _cache_key(self, playlist_id): """Build key used for caching the playlist tracks data.""" return build_key('playlist-tracks-queryset', playlist_id)