Files
MarietjeDjango/marietje/songs/api/v1/views.py
2024-02-21 15:40:41 +01:00

99 lines
4.0 KiB
Python

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, ConnectionRefusedError):
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.",
},
)