def playlist(request: HttpRequest) -> JsonResponse: spotify = get_spotify() tracks = spotify.user_playlist_tracks( os.getenv("SPOTIPY_USERNAME"), os.getenv("SPOTIFY_PLAYLIST_ID"), ) return JsonResponse(SlackFormatter.playlist(tracks))
def populate(): client = get_spotify() errors = [] tracks = Track.objects.filter(populated=False, spotify_id__isnull=False)[:10] for track in tracks: try: data = client._get("audio-features/" + client._get_id("track", track.spotify_id)) except Exception as e: errors.append(str(e)) continue track.analysis_url = data["analysis_url"] track.key = data["key"] track.time_signature = data["time_signature"] track.danceability = data["danceability"] track.energy = data["energy"] track.loudness = data["loudness"] track.speechiness = data["speechiness"] track.acousticness = data["acousticness"] track.instrumentalness = data["instrumentalness"] track.liveness = data["liveness"] track.valence = data["valence"] track.tempo = data["tempo"] track.duration_ms = data["duration_ms"] track.populated = True track.save() youtube_videos = YouTubeHelper().search("%s - %s" % (track.artists_to_str, track.title)) for youtube_video in youtube_videos: try: # do not load the same video twice Video.objects.get(video_id=youtube_video["id"]["videoId"]) continue except Video.DoesNotExist: pass except Video.MultipleObjectsReturned: continue try: video = Video() video.track = track video.source = "youtube" video.description = youtube_video["snippet"]["description"] video.title = youtube_video["snippet"]["title"] video.channel_id = youtube_video["snippet"]["channelId"] video.url = "https://www.youtube.com/watch?v=%s" % youtube_video["id"]["videoId"] video.video_id = youtube_video["id"]["videoId"] video.save() except Exception as e: errors.append(str(e)) continue return [tracks, errors]
def current_playing_track(): client = get_spotify() logger = logging.getLogger(__name__) played = None try: track_details = client._get("me/player") except Exception as e: logger.error("Failed to retrieve details about current playing song: " + str(e)) track_details = None if track_details \ and "item" in track_details \ and "uri" in track_details["item"] \ and "artists" in track_details["item"]: try: track = Track.objects.get(spotify_id=track_details["item"]["uri"]) except Track.DoesNotExist: track = Track() track.title = track_details["item"]["name"] track.album = track_details["item"]["album"]["name"] track.spotify_id = track_details["item"]["uri"] track.url = track_details["item"]["preview_url"] track.save() for artist_details in track_details["item"]["artists"]: try: artist = Artist.objects.get(spotify_id=artist_details["uri"]) except Artist.DoesNotExist: artist = Artist() artist.spotify_id = artist_details["uri"] artist.name = artist_details["name"] artist.save() track.artists.add(artist) track.save() # Update played song if it has not played recently time_threshold = timezone.now() - timedelta(minutes=120) try: played = Played.objects.filter(track=track, on__gt=time_threshold)[:1].get() except Played.DoesNotExist: played = Played() played.on = timezone.now() played.track = track played.save() else: track = None return track, track_details, played
def handle(self, *args, **options): sc = WebClient(os.getenv("SLACK_API_TOKEN")) sqs = boto3.client('sqs', region_name=os.getenv('AWS_REGION', 'ap-southeast-2')) while True: if self.kill_now: break # in the loop so we can refresh the token if needed spotify_client = get_spotify() response = sqs.receive_message( QueueUrl=os.getenv('SLACK_PLAYLIST_QUEUE'), MaxNumberOfMessages=10, WaitTimeSeconds=20, VisibilityTimeout=60, MessageAttributeNames=['All']) if 'Messages' not in response: continue for sqs_msg in response['Messages']: try: body = json.loads(sqs_msg['Body']) action = body["action"] title = body["search"]["q"] user_slack_id = body["user"]["slack_id"] tracks = spotify_client.search(title, limit=1) if 1 == len(tracks["tracks"]["items"]) and action in [ "queue", "dequeue" ]: track_details = tracks["tracks"]["items"][0] self._update_models(track_details, action, user_slack_id) if "queue" == action: spotify_client.user_playlist_add_tracks( os.getenv("SPOTIPY_USERNAME"), os.getenv("SPOTIFY_PLAYLIST_ID"), [track_details["id"]]) notification = "The song *%s* by *%s* was queued to the playlist" % ( track_details["name"], track_details["artists"][0]["name"]) else: spotify_client.user_playlist_remove_all_occurrences_of_tracks( os.getenv("SPOTIPY_USERNAME"), os.getenv("SPOTIFY_PLAYLIST_ID"), [track_details["id"]]) notification = "The song *%s* by *%s* was dequeued from the playlist" % ( track_details["name"], track_details["artists"][0]["name"]) sc.api_call("chat.postMessage", channel=user_slack_id, text=notification, markdown=True, username="******" % os.getenv("SLACK_USERNAME", "Fusebox"), as_user=True) requests.post(os.getenv("SPOTIPY_SLACK_CHANNEL_URL"), json={ "text": "@%s just %sd *%s* by *%s*" % (body["user"]["name"], action, track_details["name"], track_details["artists"][0]["name"]) }) else: sc.api_call("chat.postMessage", channel=user_slack_id, text="No results for the song *%s*" % title, markdown=True, username="******" % os.getenv("SLACK_USERNAME", "Fusebox"), as_user=True) except JSONDecodeError as e: logging.getLogger(__name__).error("Invalid json: " + str(e)) except SpotifyException as e: logging.getLogger(__name__).error("Spotify failed: " + str(e)) if 'user_slack_id' in locals(): sc.api_call( "chat.postMessage", channel=user_slack_id, text= "Spotify failed to handle request. Retry again.", markdown=True, username="******" % os.getenv("SLACK_USERNAME", "Fusebox"), as_user=True) sqs.delete_message(QueueUrl=os.getenv('SLACK_PLAYLIST_QUEUE'), ReceiptHandle=sqs_msg['ReceiptHandle'])
def handle(self, *args, **options): sc = WebClient(os.getenv("SLACK_API_TOKEN")) sqs = boto3.client('sqs', region_name=os.getenv('AWS_REGION', 'ap-southeast-2')) while True: if self.kill_now: break response = sqs.receive_message( QueueUrl=os.getenv('SLACK_PREDICT_QUEUE'), MaxNumberOfMessages=10, WaitTimeSeconds=20, VisibilityTimeout=60, MessageAttributeNames=['All']) if 'Messages' not in response: continue # in the loop so we can refresh the token if needed spotify_client = get_spotify() for sqs_msg in response['Messages']: try: body = json.loads(sqs_msg['Body']) except json.decoder.JSONDecodeError as e: logging.getLogger(__name__).error("Invalid json: " + str(e)) continue title = body["search"]["q"] slack_id = body["user"]["slack_id"] tracks = spotify_client.search(title, limit=1) if 1 == len(tracks["tracks"]["items"]): try: track = tracks["tracks"]["items"][0] track_details = spotify_client._get("audio-features/" + track["id"]) aws_client = boto3.client('machinelearning', region_name="us-east-1") predicted = aws_client.predict( MLModelId=os.getenv('ML_MODEL_ID', 'ml-0vlfzxpmeGb'), Record={ 'id': track["id"], 'danceability': str(track_details["danceability"]), 'energy': str(track_details["energy"]), 'loudness': str(track_details["loudness"]), 'speechiness': str(track_details["speechiness"]), 'acousticness': str(track_details["acousticness"]), 'instrumentalness': str(track_details["instrumentalness"]), 'liveness': str(track_details["liveness"]), 'valence': str(track_details["valence"]), 'tempo': str(track_details["tempo"]), 'duration_ms': str(track_details["duration_ms"]), 'played': str( Played.objects.filter( track__spotify_id=track["id"]).count()) }, PredictEndpoint= 'https://realtime.machinelearning.us-east-1.amazonaws.com' ) sc.api_call( "chat.postMessage", channel=slack_id, text= "The song *%s* by *%s* got a predicted rate of %.2f" % (track["name"], track["artists"][0]["name"], predicted["Prediction"]["predictedValue"]), markdown=True, username="******" % os.getenv("SLACK_USERNAME", "Fusebox"), as_user=True) requests.post( os.getenv("SPOTIPY_SLACK_CHANNEL_URL"), json={ "text": "@%s checked prediction for *%s* by *%s*" % (body["user"]["name"], track["name"], track["artists"][0]["name"]) }) except Exception as e: logging.getLogger(__name__).error( "Something failed: " + str(e)) else: sc.api_call("chat.postMessage", channel=slack_id, text="No results for the song *%s*" % title, markdown=True, username="******" % os.getenv("SLACK_USERNAME", "Fusebox"), as_user=True) sqs.delete_message(QueueUrl=os.getenv('SLACK_PREDICT_QUEUE'), ReceiptHandle=sqs_msg['ReceiptHandle'])