Louis Mazin 6a18a3caff clean
2026-10-02 17:10:37 +02:00

123 lines
4.3 KiB
Python

from datetime import timedelta
import os
from django.utils import timezone
from rest_framework import status, viewsets
from rest_framework.exceptions import Throttled
from rest_framework.permissions import AllowAny, IsAdminUser
from rest_framework.response import Response
from rest_framework.views import APIView
from .models import AvailabilityRequest, ScheduleEntry
from .notifications import send_ntfy_notification
from .serializers import (
AvailabilityRequestAdminSerializer,
AvailabilityRequestCreateSerializer,
AvailabilityRequestPublicSerializer,
AvailabilityResponseSerializer,
ScheduleEntrySerializer,
)
def client_ip(request):
forwarded = request.META.get('HTTP_X_FORWARDED_FOR')
return forwarded.split(',')[0].strip() if forwarded else request.META.get('REMOTE_ADDR')
def filter_schedule(queryset, request):
start = request.query_params.get('start')
end = request.query_params.get('end')
if start and end:
queryset = queryset.filter(start_date__lte=end, end_date__gte=start)
return queryset
class PublicScheduleView(APIView):
permission_classes = [AllowAny]
def get(self, request):
queryset = filter_schedule(ScheduleEntry.objects.all(), request)
return Response(ScheduleEntrySerializer(queryset, many=True).data)
class PublicAvailabilityRequestCreateView(APIView):
permission_classes = [AllowAny]
def post(self, request):
ip = client_ip(request)
if ip and AvailabilityRequest.objects.filter(
requester_ip=ip,
requested_at__gte=timezone.now() - timedelta(seconds=45),
).exists():
raise Throttled(detail="Une demande vient déjà d'être envoyée. Réessaie dans quelques secondes.")
serializer = AvailabilityRequestCreateSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
item = serializer.save(requester_ip=ip)
public_site_url = os.getenv('PUBLIC_SITE_URL', '').rstrip('/')
message = f'{item.guest_name} demande si tu es disponible maintenant.'
if item.message:
message += f'\n{item.message}'
send_ntfy_notification(
'Nouvelle demande de disponibilité',
message,
f'{public_site_url}/requests' if public_site_url else None,
)
return Response(
AvailabilityRequestPublicSerializer(item).data,
status=status.HTTP_201_CREATED,
)
class PublicAvailabilityRequestDetailView(APIView):
permission_classes = [AllowAny]
def get(self, request, token):
try:
item = AvailabilityRequest.objects.get(public_token=token)
except AvailabilityRequest.DoesNotExist:
return Response({'detail': 'Demande introuvable.'}, status=status.HTTP_404_NOT_FOUND)
return Response(AvailabilityRequestPublicSerializer(item).data)
class AdminScheduleViewSet(viewsets.ModelViewSet):
serializer_class = ScheduleEntrySerializer
permission_classes = [IsAdminUser]
def get_queryset(self):
return filter_schedule(ScheduleEntry.objects.all(), self.request)
class AdminAvailabilityRequestViewSet(viewsets.ReadOnlyModelViewSet):
serializer_class = AvailabilityRequestAdminSerializer
permission_classes = [IsAdminUser]
def get_queryset(self):
queryset = AvailabilityRequest.objects.all()
status_filter = self.request.query_params.get('status')
if status_filter:
queryset = queryset.filter(status=status_filter)
return queryset
def respond(self, request, pk=None):
item = self.get_object()
serializer = AvailabilityResponseSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
new_status = serializer.validated_data['status']
duration = serializer.validated_data.get('duration_minutes')
item.status = new_status
item.duration_minutes = duration if new_status == 'accepted' else None
item.available_until = (
timezone.now() + timedelta(minutes=duration)
if new_status == 'accepted' and duration
else None
)
item.response_message = serializer.validated_data.get('response_message', '')
item.responded_at = timezone.now()
item.save()
return Response(AvailabilityRequestAdminSerializer(item).data)