diff --git a/server/proj/audio/admin.py b/server/proj/audio/admin.py index e89d730..e528988 100644 --- a/server/proj/audio/admin.py +++ b/server/proj/audio/admin.py @@ -10,7 +10,7 @@ class SongAdmin(admin.ModelAdmin): @admin.register(FavoriteSong) class FavoriteSongAdmin(admin.ModelAdmin): - list_display = ('id', 'song', 'user') + list_display = ('id', 'user') @admin.register(PlayList) class PlayListAdmin(admin.ModelAdmin): diff --git a/server/proj/audio/models.py b/server/proj/audio/models.py index 6abb6b3..019e08f 100644 --- a/server/proj/audio/models.py +++ b/server/proj/audio/models.py @@ -19,7 +19,7 @@ class Song(models.Model): super(Song, self).save(*args, **kwargs) def __str__(self): - return f"{self.artist} - {self.title}" + return f"{self.title}" class Meta: verbose_name = 'Треки' @@ -33,14 +33,13 @@ class Song(models.Model): class FavoriteSong(models.Model): - song = models.ForeignKey(Song, verbose_name='Трек', on_delete=models.CASCADE) + song = models.ManyToManyField(Song, verbose_name='Трек') user = models.ForeignKey(MyUser, verbose_name='Пользователь', on_delete=models.CASCADE) def __str__(self): - return f"{self.song.title}" + return f"{self.user.first_name}" class Meta: verbose_name = 'Избранные Треки' - unique_together = ('song', 'user') verbose_name_plural = 'Избранные Треки' diff --git a/server/proj/audio/schemas.py b/server/proj/audio/schemas.py index b733a5d..fcee46e 100644 --- a/server/proj/audio/schemas.py +++ b/server/proj/audio/schemas.py @@ -4,45 +4,62 @@ import coreschema class SongSchema(AutoSchema): def get_serializer_fields(self, path, method): - return [ + if path.endswith('/get_song_history/'): + return [ coreapi.Field( - name='azura_id', + name='start', location='form', required=False, - schema=coreschema.String(description='ID трека с Азуры') + schema=coreschema.String(description='Начало периода') ), coreapi.Field( - name='title', + name='end', location='form', required=False, - schema=coreschema.String(description='Название трека') + schema=coreschema.String(description='Конец периода') ), - coreapi.Field( - name='artist', - location='form', - required=False, - schema=coreschema.String(description='Исполнитель') - ), - coreapi.Field( - name='album', - location='form', - required=False, - schema=coreschema.String(description='Альбом трека') - ), - coreapi.Field( - name='genre', - location='form', - required=False, - schema=coreschema.String(description='Жанр трека') - ), - coreapi.Field( - name='art', - location='form', - required=False, - schema=coreschema.String(description='Изображение трека') - ), - ] - + ] + if path.endswith('/add_favorite/'): + return [ + coreapi.Field( + name='azura_id', + location='form', + required=False, + schema=coreschema.String(description='ID трека с Азуры') + ), + coreapi.Field( + name='title', + location='form', + required=False, + schema=coreschema.String(description='Название трека') + ), + coreapi.Field( + name='artist', + location='form', + required=False, + schema=coreschema.String(description='Исполнитель') + ), + coreapi.Field( + name='album', + location='form', + required=False, + schema=coreschema.String(description='Альбом трека') + ), + coreapi.Field( + name='genre', + location='form', + required=False, + schema=coreschema.String(description='Жанр трека') + ), + coreapi.Field( + name='art', + location='form', + required=False, + schema=coreschema.String(description='Изображение трека') + ), + ] + return [] + class DeleteSongSchema(AutoSchema): def get_serializer_fields(self, path, method): return [ @@ -71,7 +88,7 @@ class PlayListSchema(AutoSchema): schema=coreschema.Integer(description='Обложка плейлиста') ), ] - if path.endswith('/update_playlist/') or path.endswith('/delete_song_with_playlist/'): + if path.endswith('/delete_song_with_playlist/'): return [ coreapi.Field( name='azura_id', @@ -80,6 +97,22 @@ class PlayListSchema(AutoSchema): schema=coreschema.String(description='ID трека с Азуры') ), ] + if path.endswith('/update_playlist/'): + return [ + coreapi.Field( + name='name', + location='form', + required=False, + schema=coreschema.String(description='Название плейлиста') + ), + coreapi.Field( + name='playlist_art', + location='form', + required=False, + schema=coreschema.Integer(description='Обложка плейлиста') + ), + ] + if path.endswith('/add_to_playlist/'): return [ coreapi.Field( diff --git a/server/proj/audio/serializers.py b/server/proj/audio/serializers.py index b711e4d..9f2d686 100644 --- a/server/proj/audio/serializers.py +++ b/server/proj/audio/serializers.py @@ -1,14 +1,17 @@ from rest_framework import serializers from .models import Song, FavoriteSong, PlayList, Podkast + class SongSerializer(serializers.ModelSerializer): + class Meta: model = Song fields = ('id', 'unique_id', 'azura_id', 'title', 'artist', 'album', 'genre', 'art') + class PlayListSerializer(serializers.ModelSerializer): + def validate(self, attrs): - if PlayList.objects.filter( name=attrs.get('name'), user=attrs.get('user') @@ -22,36 +25,21 @@ class PlayListSerializer(serializers.ModelSerializer): class Meta: model = PlayList fields = ('id', 'name', 'song', 'user', 'playlist_art') - + def to_representation(self, instance): rep = super().to_representation(instance) rep["song"] = SongSerializer( instance.song.all(), many=True).data return rep + class FavoriteSongSerializer(serializers.ModelSerializer): - - def validate(self, attrs): - if FavoriteSong.objects.filter( - song=attrs.get('song'), - user=attrs.get('user') - ).exists(): - raise serializers.ValidationError( - { - 'song': ['Данный трек уже добавлен в избранное'] - }) - return super().validate(attrs) - + song = SongSerializer(many=True) class Meta: model = FavoriteSong - fields = ('id', 'song', 'user') - - def to_representation(self, instance): - rep = super().to_representation(instance) - rep["song"] = SongSerializer( - instance.song).data - return rep + fields = '__all__' + class PodkastSerializer(serializers.ModelSerializer): class Meta: model = Podkast diff --git a/server/proj/audio/services/service.py b/server/proj/audio/services/service.py index c4ce086..76f8b2b 100644 --- a/server/proj/audio/services/service.py +++ b/server/proj/audio/services/service.py @@ -4,6 +4,11 @@ from audio.services import service_azura class AzuraCast: azura_requests = service_azura.AzuraCastRequests() + def get_song_history(self, start, end): + print(start, end) + response = self.azura_requests.get_song_history(start, end) + return response + def get_nowplaying(self): response = self.azura_requests.get_nowplaying() return response diff --git a/server/proj/audio/services/service_azura.py b/server/proj/audio/services/service_azura.py index 59a3627..5d68329 100644 --- a/server/proj/audio/services/service_azura.py +++ b/server/proj/audio/services/service_azura.py @@ -13,6 +13,12 @@ class AzuraCastRequests: api_key = AZURACAST_API_KEY url = AZURACAST_URL + @staticmethod + def get_song_history(start_time, end_time): + file_url = F"{AZURACAST_URL}api/station/it-radio/history?start={start_time}&end={end_time}" + response = authorize_url("get", file_url) + return response.json() + @staticmethod def get_nowplaying(): file_url = F"{AZURACAST_URL}api/nowplaying/it-radio" diff --git a/server/proj/audio/views.py b/server/proj/audio/views.py index 007252f..e72ef11 100644 --- a/server/proj/audio/views.py +++ b/server/proj/audio/views.py @@ -54,21 +54,17 @@ class PlayListViewSet(GenericViewSet): def create_playlist(self, request): if request.data.get('name', False): data = request.data - data.update(user=request.user.pk) - serializer = self.get_serializer(data=request.data) - if serializer.is_valid(): - serializer.save() - return Response(serializer.data) - return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + data.update(user=request.user.pk) else: playlist_pk = self.get_queryset().filter(user=request.user.pk) name = f"Плейлист № {len(playlist_pk)+1}" data = request.data data.update(user=request.user.pk, name=name) - serializer = self.get_serializer(data=request.data) - if serializer.is_valid(): - serializer.save() - return Response(serializer.data) + serializer = self.get_serializer(data=request.data) + if serializer.is_valid(): + serializer.save() + return Response(serializer.data) + else: return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) @action(detail=True, methods=['post'], schema=PlayListSchema()) @@ -89,21 +85,22 @@ class PlayListViewSet(GenericViewSet): @action(detail=True, methods=['post'], schema=PlayListSchema()) def delete_song_with_playlist(self, request, *args, **kwargs): try: - song = Song.objects.get(azura_id=request.data.get('azura_id')) - item = self.get_object() - item.song.remove(song) - return Response({'detail': 'Объект удалён'}, status=status.HTTP_200_OK) + song_obj = Song.objects.get(azura_id=request.data.get('azura_id')) except ObjectDoesNotExist: - return Response({'detail': 'Объекта не существует', 'error': {'PlayList': 'Объекта не существует'}}, + return Response({'detail': 'Объекта не существует', 'error': {'Song': 'Объекта не существует'}}, status=status.HTTP_404_NOT_FOUND) + if not self.get_queryset().filter(user=request.user, song=song_obj).exists(): + return Response({'detail': 'Объекта не существует', 'error': {'Song': 'Объекта отсутствует плейлисте'}}, + status=status.HTTP_404_NOT_FOUND) + playlist = self.get_object() + playlist.song.remove(song_obj) + serializer = self.get_serializer(playlist) + return Response(serializer.data, status=status.HTTP_200_OK) @action(detail=True, methods=['post'], schema=PlayListSchema()) def add_to_playlist(self, request, *args, **kwargs): instance = self.get_object() - - song = None try: - song = Song.objects.get(azura_id=request.data.get('azura_id')).pk except ObjectDoesNotExist: data = self.azura.add_to_playlist(request.data) @@ -118,7 +115,6 @@ class PlayListViewSet(GenericViewSet): return Response(serializer.data) - class FavoriteSongViewSet(GenericViewSet): azura = AzuraCast() queryset = FavoriteSong.objects.all() @@ -128,55 +124,48 @@ class FavoriteSongViewSet(GenericViewSet): def list(self, request): queryset = self.get_queryset() - serializer = self.get_serializer(queryset, many=True, request_user=request.user) + serializer = self.get_serializer(queryset, many=True) return Response(serializer.data) - @action(detail=False, methods=['get']) + @action(detail=True, methods=['get']) def check_is_favorite(self, request, azura_id, *args, **kwargs): try: song_obj = Song.objects.get(azura_id=azura_id) - favorite_songs = self.get_queryset().get(user=request.user, song=song_obj) - return Response({"is_favorite": True}, status=status.HTTP_200_OK) except ObjectDoesNotExist: + return Response({'detail': 'Объекта не существует', 'error': {'Song': 'Объекта не существует'}}, + status=status.HTTP_404_NOT_FOUND) + if self.get_queryset().filter(user=request.user, song=song_obj).exists(): + return Response({"is_favorite": True}, status=status.HTTP_200_OK) + else: return Response({"is_favorite": False}, status=status.HTTP_200_OK) @action(detail=False, methods=['post'], schema=SongSchema()) def add_favorite(self, request, *args, **kwargs): - data = None try: song = Song.objects.get(azura_id=request.data.get('azura_id')) - data = { - 'song': song.pk, - 'user': request.user.pk - } except ObjectDoesNotExist: - unique_id = self.azura.get_unique_id(azura_id = request.data.get('azura_id')) + unique_id = self.azura.get_unique_id(azura_id=request.data.get('azura_id')) data = request.data data.update(unique_id=unique_id) serializer = SongSerializer(data=data) if serializer.is_valid(): serializer.save() - data = { - "song": serializer.data['id'], - "user": request.user.pk - } + song = serializer.data['id'] else: return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) - - serializer = self.get_serializer(data=data) - if serializer.is_valid(data): - serializer.save() - return Response(serializer.data, status=status.HTTP_201_CREATED) - else: - return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + obj, data = self.get_queryset().get_or_create(user=request.user) + obj.song.add(song) + serializer = self.get_serializer(obj) + return Response(serializer.data, status=status.HTTP_200_OK) @action(detail=True, methods=['delete']) def delete_song(self, request, *args, **kwargs): try: song = Song.objects.get(azura_id=kwargs.get('azura_id')) queryset = self.get_queryset().get(user=request.user, song=song.pk) - queryset.delete() - return Response(status=status.HTTP_202_ACCEPTED) + queryset.song.remove(song) + serializer = self.get_serializer(queryset) + return Response(serializer.data, status=status.HTTP_200_OK) except ObjectDoesNotExist: return Response({'detail': 'Объекта не существует', 'error': {'Song': 'Объекта не существует'}}, status=status.HTTP_404_NOT_FOUND) @@ -184,6 +173,8 @@ class FavoriteSongViewSet(GenericViewSet): class SongViewSet(GenericViewSet): azura = AzuraCast() + queryset = Song.objects.all() + permission_classes = (IsAuthenticated, ) lookup_field = 'azura_id' @action(detail=True, methods=['get']) @@ -198,3 +189,13 @@ class SongViewSet(GenericViewSet): @action(detail=False, methods=['get'], permission_classes=(AllowAny,)) def get_nowplaying(self, request): return Response(self.azura.get_nowplaying(), status=status.HTTP_200_OK) + + @action(detail=False, methods=['get'], permission_classes=(AllowAny,), schema=SongSchema()) + def get_song_history(self, request): + return Response( + self.azura.get_song_history( + request.data['start'], + request.data['end'] + ), + status=status.HTTP_200_OK + )