from django.shortcuts import render from rest_framework.viewsets import ViewSet, GenericViewSet from rest_framework.response import Response from rest_framework.decorators import action from rest_framework import status from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned from django.shortcuts import get_object_or_404, get_list_or_404 from rest_framework.permissions import IsAuthenticated, AllowAny import requests from django.http import HttpResponse from .schemas import SongSchema, DeleteSongSchema, PlayListSchema from .models import Song, FavoriteSong, PlayList from .serializers import SongSerializer, FavoriteSongSerializer, PlayListSerializer from conf.settings.base import AZURACAST_URL, AZURACAST_API_KEY class PlayListViewSet(GenericViewSet): queryset = PlayList serializer_class = PlayListSerializer permission_classes = (IsAuthenticated,) def list(self, request): queryset = self.get_queryset().objects.filter(user=request.user) serializer = self.get_serializer(queryset, many=True) return Response(serializer.data, status=status.HTTP_200_OK) def retrieve(self, request, pk): try: queryset = self.get_queryset().objects.get(pk=pk, user=request.user) serializer = self.get_serializer(queryset) return Response(serializer.data, status=status.HTTP_200_OK) except ObjectDoesNotExist: return Response( {'detail': 'Объекта не существует', 'error': {'PlayList': 'Объекта не существует'}}, status=status.HTTP_404_NOT_FOUND) @action(detail=False, methods=['post'], schema=PlayListSchema()) def create_playlist(self, request): if request.data.get('name', False): try: instance = self.get_queryset().objects.get(pk=request.data['playlist_id'], user=request.user.pk) data = request.data data.update(user=request.user.pk) serializer = self.get_serializer(data=request.data, instance=instance) serializer.is_valid(raise_exception=True) serializer.save() return Response(serializer.data) except ObjectDoesNotExist: return Response( {'detail': 'Объекта не существует', 'error': {'PlayList': 'Объекта не существует'}}, status=status.HTTP_404_NOT_FOUND) else: playlist_pk = self.get_queryset().objects.filter(user=request.user.pk) number_playlist = len(playlist_pk) + 1 name = f"Плейлист № {number_playlist}" data = request.data data.update(user=request.user.pk, name=name) serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) serializer.save() return Response(serializer.data) @action(detail=False, methods=['post'], schema=PlayListSchema()) def update_playlist(self, request): try: instance = self.get_queryset().objects.get(pk=request.data['playlist_id'], user=request.user.pk) serializer = self.get_serializer(data=request.data, partial=True, instance=instance) serializer.is_valid(raise_exception=True) serializer.save() return Response(serializer.data) except ObjectDoesNotExist: return Response( {'detail': 'Объекта не существует', 'error': {'PlayList': 'Объекта не существует'}}, status=status.HTTP_404_NOT_FOUND) @action(detail=False, methods=['post'], schema=PlayListSchema()) def delete_playlist(self, request): try: item = self.get_queryset().objects.get(user=request.user, pk=request.data.get('playlist_id')) item.delete() return Response(status=status.HTTP_202_ACCEPTED) except ObjectDoesNotExist: return Response( {'detail': 'Объекта не существует', 'error': {'PlayList': 'Объекта не существует'}}, status=status.HTTP_404_NOT_FOUND) @action(detail=False, methods=['post'], schema=PlayListSchema()) def delete_song_with_playlist(self, request): try: song = Song.objects.get(azura_id=request.data.get('azura_id')) item = self.get_queryset().objects.get(user=request.user, pk=request.data.get('playlist_id')) item.song.remove(song) return Response({'detail': 'Объект удалён'}, status=status.HTTP_200_OK) except ObjectDoesNotExist: return Response( {'detail': 'Объекта не существует', 'error': {'PlayList': 'Объекта не существует'}}, status=status.HTTP_404_NOT_FOUND) @action(detail=False, methods=['post'], schema=PlayListSchema()) def add_to_playlist(self, request): song = None try: song = Song.objects.get(azura_id=request.data.get('azura_id')).pk except ObjectDoesNotExist: file_url = f"{AZURACAST_URL}api/station/it-radio/file/{request.data['azura_id']}" API_KEY = AZURACAST_API_KEY headers = { "Authorization": f"Bearer {API_KEY}" } response = requests.get(file_url, headers=headers) data = request.data file_play = f"{AZURACAST_URL}api/station/it-radio/file/{response.json()['unique_id']}/play" data.update(unique_id=file_play) song_serializer = SongSerializer(data=data) if song_serializer.is_valid(): song_serializer.save() song = song_serializer.data.get('id') try: instance = self.get_queryset().objects.get(pk=request.data.get('playlist_id')) except ObjectDoesNotExist: return Response( {'detail': 'Плейлиста не существует', 'error': {'PlayList': 'Плейлиста не существует'}}, status=status.HTTP_404_NOT_FOUND) songs = list(instance.song.all().values_list('pk', flat=True)) + [song] data = { 'playlist_id': request.data.get('playlist_id'), 'song': songs } serializer = PlayListSerializer(data=data, partial=True, instance=instance) serializer.is_valid(raise_exception=True) serializer.save() return Response(serializer.data) class SongViewSet(GenericViewSet): queryset = Song serializer_class = SongSerializer permission_classes = (IsAuthenticated,) def list(self, request): songs_pk = FavoriteSong.objects.filter(user=request.user, song__isnull=False).values_list('song_id', flat=True) songs = self.get_queryset().objects.filter(id__in=songs_pk) serializer = self.get_serializer(songs, many=True) return Response(serializer.data) @action( detail=False, methods=['get'], url_path='check_is_favorite/(?P[a-zA-Z0-9_]+)', url_name='check_is_favorite', ) def check_is_favorite(self, request, azura_id): try: song_obj = self.get_queryset().objects.get(azura_id=azura_id) favorite_songs = FavoriteSong.objects.get(user=request.user, song=song_obj) return Response({"is_favorite": True}, status=status.HTTP_200_OK) except ObjectDoesNotExist: return Response({"is_favorite": False}, status=status.HTTP_200_OK) @action( detail=False, methods=['get'], url_path='get_audio/(?P[a-zA-Z0-9_]+)', url_name='get_audio', ) def get_audio(self, request, azura_id): try: song_obj = self.get_queryset().objects.get(azura_id=azura_id) file_url = song_obj.unique_id API_KEY = AZURACAST_API_KEY headers = { "Authorization": f"Bearer {API_KEY}" } response = requests.get(file_url, headers=headers) response.raise_for_status() file_response = HttpResponse(response.content, content_type='audio/mpeg') file = f'{song_obj.title}-{song_obj.artist}.mp3' file_response['Content-Disposition'] = f'attachment; filename={file}' return file_response except ObjectDoesNotExist: return Response({"error": 'Объекта не существует'}, status=status.HTTP_404_NOT_FOUND) @action(detail=False, methods=['post'], schema=SongSchema()) def add_favorite(self, request): data = None try: song = self.get_queryset().objects.get(azura_id=request.data.get('azura_id')) data = { "song": song.pk, "user": request.user.pk } except ObjectDoesNotExist: file_url = f"{AZURACAST_URL}api/station/it-radio/file/{request.data['azura_id']}" API_KEY = AZURACAST_API_KEY headers = { "Authorization": f"Bearer {API_KEY}" } response = requests.get(file_url, headers=headers) data = request.data file_play = f"{AZURACAST_URL}/api/station/it-radio/file/{response.json()['unique_id']}/play" data.update(unique_id=file_play) serializer = self.get_serializer(data=data) if serializer.is_valid(): serializer.save() data = { "song": serializer.data['id'], "user": request.user.pk } serializer = FavoriteSongSerializer(data=data) if serializer.is_valid(): serializer.save() return Response(serializer.data, status=status.HTTP_201_CREATED) else: return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) @action(detail=False, methods=['post'], schema=DeleteSongSchema()) def delete_song(self, request): try: song = self.get_queryset().objects.get(azura_id=request.data.get('azura_id')) item = FavoriteSong.objects.get(user=request.user, song=song.pk) item.delete() return Response(status=status.HTTP_202_ACCEPTED) except ObjectDoesNotExist: return Response({"error": 'Объекта не существует'}, status=status.HTTP_404_NOT_FOUND) @action(detail=False, methods=['get']) def get_all_song(self, request): file_url = F"{AZURACAST_URL}api/station/1/files" API_KEY = AZURACAST_API_KEY headers = { "Authorization": f"Bearer {API_KEY}" } response = requests.get(file_url, headers=headers) data = [] for i in response.json(): i['azura_id'] = i.pop('song_id') data.append(i) return Response(data, status=status.HTTP_200_OK)