diff --git a/apps/songs/urls.py b/apps/songs/urls.py index 47c66a2..5343704 100644 --- a/apps/songs/urls.py +++ b/apps/songs/urls.py @@ -8,5 +8,8 @@ path('api/fetch', views.get_song, name='get-song'), path('api/add', views.add_song, name='add-song'), path('api/search', views.search_songs, name='search-songs'), + path('get-all-genres/', views.get_all_genres, name='get-all-genres'), + path('create-genre/', views.create_genre, name='create-genre'), + path('upload-file/', views.import_song_JSON, name='import-song-json'), ] diff --git a/apps/songs/views.py b/apps/songs/views.py index 7f9070f..b91a460 100644 --- a/apps/songs/views.py +++ b/apps/songs/views.py @@ -1,5 +1,9 @@ -from django.http import JsonResponse +import json +from datetime import timedelta + +from django.http import JsonResponse, HttpResponse from django.shortcuts import render +from django.core.exceptions import ValidationError from django.views.decorators.csrf import csrf_exempt import spotipy from OVTF_Backend.firebase_auth import token_required @@ -8,21 +12,22 @@ import os import logging + # Create your views here. @csrf_exempt @token_required -def get_all_songs(request): - users = Song.objects.all() +def get_all_songs(request, userid): + songs = Song.objects.all().values() context = { - "users": list(users) + "users": list(songs) } return JsonResponse(context, status=200) @csrf_exempt @token_required -def get_songs(request): +def get_songs(request, userid): if request.method == 'GET': data = request.GET track_name = data.get('song_name') @@ -61,10 +66,11 @@ def get_songs(request): return JsonResponse({'error': 'An unexpected error occurred'}, status=500) else: return JsonResponse({'error': 'Invalid method'}, status=400) - + + @csrf_exempt @token_required -def get_song(request): +def get_song(request, userid): if request.method == 'GET': data = request.GET track_id = data.get('song_id') @@ -85,7 +91,7 @@ def get_song(request): 'replay_count': song.replay_count, 'version': song.version, } - return JsonResponse({'message': 'song found','song_info': song_info}, status=200) + return JsonResponse({'message': 'song found', 'song_info': song_info}, status=200) except Song.DoesNotExist: return JsonResponse({'error': 'Song not found'}, status=404) else: @@ -94,7 +100,7 @@ def get_song(request): @csrf_exempt @token_required -def add_song(request): +def add_song(request, userid): try: if request.method == 'POST': data = request.POST @@ -103,7 +109,8 @@ def add_song(request): if not spotify_id: return JsonResponse({'error': 'Spotify ID is required'}, status=400) - client_credentials = SpotifyClientCredentials(client_id=os.getenv('SPOTIPY_CLIENT_ID'), client_secret=os.getenv('SPOTIPY_CLIENT_SECRET')) + client_credentials = SpotifyClientCredentials(client_id=os.getenv('SPOTIPY_CLIENT_ID'), + client_secret=os.getenv('SPOTIPY_CLIENT_SECRET')) sp = spotipy.Spotify(client_credentials_manager=client_credentials) # Use the provided Spotify ID to get track information directly @@ -115,7 +122,8 @@ def add_song(request): if audio_features: audio_features = audio_features[0] recommended_environment = 'L' if audio_features['liveness'] >= 0.8 else 'S' - tempo = 'F' if audio_features['tempo'] >= 120 else ('M' if 76 <= audio_features['tempo'] < 120 else 'S') + tempo = 'F' if audio_features['tempo'] >= 120 else ( + 'M' if 76 <= audio_features['tempo'] < 120 else 'S') energy = audio_features['energy'] if 0 <= energy < 0.25: mood = 'SA' # Sad @@ -164,10 +172,11 @@ def add_song(request): except Exception as e: logging.error(f"An unexpected error occurred: {str(e)}") return JsonResponse({'error': 'An unexpected error occurred'}, status=500) - + + @csrf_exempt @token_required -def search_songs(request): +def search_songs(request, userid): try: if request.method == 'GET': data = request.GET @@ -175,8 +184,9 @@ def search_songs(request): if search_string is None: return JsonResponse({'error': 'Missing search string'}, status=400) - - client_credentials = SpotifyClientCredentials(client_id=os.getenv('SPOTIPY_CLIENT_ID'), client_secret=os.getenv('SPOTIPY_CLIENT_SECRET')) + + client_credentials = SpotifyClientCredentials(client_id=os.getenv('SPOTIPY_CLIENT_ID'), + client_secret=os.getenv('SPOTIPY_CLIENT_SECRET')) sp = spotipy.Spotify(client_credentials_manager=client_credentials) results = sp.search(q=search_string, type='track', limit=10) @@ -189,7 +199,7 @@ def search_songs(request): 'album_name': track['album']['name'], 'artist': ', '.join([artist['name'] for artist in track['artists']]), 'release_year': track['album']['release_date'][:4], - 'spotify_id': track['id'], + 'spotify_id': track['id'], } search_list.append(song_info) return JsonResponse({'message': 'Search successful', 'results': search_list}, status=200) @@ -202,3 +212,79 @@ def search_songs(request): except Exception as e: logging.error(f"An unexpected error occurred: {str(e)}") return JsonResponse({'error': 'An unexpected error occurred'}, status=500) + + +@csrf_exempt +@token_required +def import_song_JSON(request, userid): + if request.method != 'POST': + return HttpResponse(status=405) + try: + if 'file' in request.FILES: + file = request.FILES['file'] + data = json.load(file) + else: + return JsonResponse({'error': 'No file provided'}, status=400) + if isinstance(data, dict): + data = [data] + required_fields = ['track_name', 'release_year', 'length', + 'tempo', 'genre', 'mood', + 'recommended_environment', 'duration', 'replay_count', 'version'] + for song_data in data: + # Assuming genre_id is provided in song_data to link Song with Genre + # return JsonResponse(song_data, safe=False, status=200) + if not all(field in song_data for field in required_fields): + return HttpResponse(status=400) + genre_name = song_data.get('genre', None) + genre, created = Genre.objects.get_or_create(genre_name=genre_name) + song_data['genre'] = genre + hours, minutes, seconds = map(int, song_data['length'].split(':')) + length_timedelta = timedelta(hours=hours, minutes=minutes, seconds=seconds) + song_data['length'] = length_timedelta + song = Song(**song_data) + song.full_clean() + song.save() + + return HttpResponse(status=201) + except json.JSONDecodeError as e: + logging.error(f"JSON decode error: {e}") + return HttpResponse(status=400) + except ValidationError as e: + return JsonResponse({'errors': e.message_dict}, status=400) + except Genre.DoesNotExist: + return HttpResponse("Genre not found.", status=400) + except Exception as e: + logging.error(f"Unexpected error: {e}") + return HttpResponse(status=500) + + +@csrf_exempt +def create_genre(request): + if request.method != 'POST': + return HttpResponse(status=405) + try: + data = json.loads(request.body.decode('utf-8')) + genre_name = data.get('genre_name') + if genre_name is None: + return HttpResponse(status=400) + genre = Genre(genre_name=genre_name) + genre.save() + return HttpResponse(status=201) + except Exception as e: + # TODO logging.("create_user: " + str(e)) + return HttpResponse(status=500) + + +@csrf_exempt +def get_all_genres(request): + if request.method != 'GET': + return HttpResponse(status=405) + try: + genres = Genre.objects.all().values() + except Exception as e: + return JsonResponse({"error": "Database error"}, status=500) + + context = { + "genres": list(genres) + } + return JsonResponse(context, status=200) diff --git a/apps/users/files.py b/apps/users/files.py new file mode 100644 index 0000000..eab875c --- /dev/null +++ b/apps/users/files.py @@ -0,0 +1,6 @@ +from django import forms + + +class UploadFileForm(forms.Form): + title = forms.CharField(max_length=50) + file = forms.FileField() \ No newline at end of file diff --git a/apps/users/urls.py b/apps/users/urls.py index f4526c3..47eac45 100644 --- a/apps/users/urls.py +++ b/apps/users/urls.py @@ -9,4 +9,5 @@ path('login/', view=views.login, name='login'), path('delete-user/', view=views.delete_user, name='delete-user'), path('update-user/', view=views.update_user, name='update-user'), + ] diff --git a/apps/users/views.py b/apps/users/views.py index 43dc184..3dac58d 100644 --- a/apps/users/views.py +++ b/apps/users/views.py @@ -1,12 +1,16 @@ import json import logging -from datetime import datetime +from datetime import datetime, timedelta +from django.core.exceptions import ValidationError from django.http import JsonResponse, HttpResponse from django.utils import timezone +from django.utils.dateparse import parse_duration from django.views.decorators.csrf import csrf_exempt from OVTF_Backend.firebase_auth import token_required +from apps.songs.models import Genre, Song +from apps.users.files import UploadFileForm from apps.users.models import User @@ -108,3 +112,11 @@ def update_user(request, userid): return HttpResponse(status=204) except Exception as e: return HttpResponse(status=404) + + + + + + + +