from django_filters.rest_framework import DjangoFilterBackend from rest_framework.generics import ListAPIView, RetrieveAPIView, CreateAPIView from rest_framework import filters from rest_framework.views import APIView from rest_framework.response import Response from marietje.api.permissions import IsAuthenticatedOrTokenHasScopeForMethod from songs.api.v1.serializers import SongSerializer, ReportNoteSerializer from songs.counters import upload_counter from songs.models import Song from songs.services import check_upload_stats, get_reputation, upload_file, UploadException class SongsListAPIView(ListAPIView): serializer_class = SongSerializer queryset = Song.objects.all() permission_classes = [IsAuthenticatedOrTokenHasScopeForMethod] required_scopes_for_method = {"GET": ["read"]} filter_backends = (filters.SearchFilter, filters.OrderingFilter, DjangoFilterBackend) filterset_fields = ["user__username", "artist"] search_fields = ["artist", "title", "user__name", "user__username"] ordering_fields = [ "artist", "title", "duration", ] class SongRetrieveAPIView(RetrieveAPIView): serializer_class = SongSerializer queryset = Song.objects.all() permission_classes = [IsAuthenticatedOrTokenHasScopeForMethod] required_scopes_for_method = {"GET": ["read"]} class ReportNoteCreateAPIView(CreateAPIView): serializer_class = ReportNoteSerializer permission_classes = [IsAuthenticatedOrTokenHasScopeForMethod] required_scopes_for_method = {"POST": ["write"]} def perform_create(self, serializer): serializer.save(user=self.request.user) def create(self, request, *args, **kwargs): if self.request.user is None: return Response( status=403, data={"success": False, "errorMessage": "A user is necessary for creating a report note."} ) else: return super(ReportNoteCreateAPIView, self).create(request, *args, **kwargs) class SongUploadAPIView(APIView): serializer_class = SongSerializer permission_classes = [IsAuthenticatedOrTokenHasScopeForMethod] required_scopes_for_method = { "POST": ["write"], } def post(self, request, **kwargs): if request.user is None: return Response( status=403, data={"success": False, "errorMessage": "A user is necessary for uploading a song."} ) file = request.data.get("file", None) artist = request.data.get("artist", None) title = request.data.get("title", None) if file is None: return Response(status=400, data={"success": False, "errorMessage": "Please select a file to upload."}) if artist is None or artist == "": return Response(status=400, data={"success": False, "errorMessage": "Please set an artist for this file."}) if title is None or title == "": return Response(status=400, data={"success": False, "errorMessage": "Please set a title for this file."}) if not check_upload_stats(request.user): reputation = get_reputation(request.user) msg = ( "Queue-to-upload ratio too low. Please queue more during regular opening hours to improve the " "ratio. (Ratio: {} ≱ 1.00)" ) return Response(status=403, data={"success": False, "errorMessage": msg.format(reputation)}) try: song = upload_file(file, artist, title, request.user) upload_counter.inc() return Response(status=200, data=self.serializer_class(song).data) except UploadException: return Response( status=500, data={ "success": False, "errorMessage": "File could not be uploaded due to an exception that " "occurred while contacting the file server, please try " "again.", }, )