from django.contrib.auth.views import LoginView from django.views.generic import CreateView from django.contrib.auth import login from django.urls import reverse_lazy from django.db.models import Count, Sum, F, IntegerField from django.db.models.functions import Coalesce from rest_framework.viewsets import ModelViewSet, GenericViewSet from rest_framework import mixins from rest_framework.decorators import action from rest_framework.response import Response import shutil from .models import User, FriendRequest, Invitation from .forms import RegisterForm from .serializers import UserSerializer, FriendRequestSerializer, InvitationSerializer class UserLoginView(LoginView): template_name = "user/login.html" fields = "__all__" redirect_authenticated_user = True class RegisterView(CreateView): template_name = "user/register.html" form_class = RegisterForm success_url = reverse_lazy("torrent:home") invitation = None def get_form(self, form_class=None): self.invitation = Invitation.objects.get(token=self.kwargs.get("token"), user__isnull=True) return super().get_form(form_class) def form_valid(self, form): r = super().form_valid(form) self.invitation.user = self.object self.invitation.save() login(self.request, self.object) return r class UserViewSet(mixins.RetrieveModelMixin, mixins.ListModelMixin, GenericViewSet): queryset = User.objects.all().annotate( count_torrent=Count("torrents") + Count("torrents_shares") ) serializer_class = UserSerializer def get_queryset(self): qs = super().get_queryset() only_friends = self.request.query_params.get("only_friends", "false") == "true" if only_friends: qs = qs.filter(friends=self.request.user) return qs @action(methods=["get"], detail=True) def add_friend_request(self, request, pk): # receiver = User.objects.get(pk=pk) if not User.objects.filter(username__iexact=pk).exists(): return Response({"success": False, "message": f"User '{pk}' doesn't exist"}) receiver = User.objects.get(username__iexact=pk) user: User = self.request.user if user.friends.filter(id=receiver.id).exists(): # déjà dans les amis return Response({"success": False, "message": "Already friend"}) elif FriendRequest.objects.filter(sender=user, receiver=receiver).exists(): # déjà une demande en attente return Response({"success": False, "message": "Friend request Already sent"}) elif FriendRequest.objects.filter(sender=receiver, receiver=user).exists(): # friend request en cours, on accepte FriendRequest.objects.filter(sender=receiver, receiver=user).delete() user.friends.add(receiver) return Response({"success": True, "message": f"{receiver.username} added to your friend list"}) else: # aucune demande en cours, on créer un friend request FriendRequest.objects.create( sender=user, receiver=receiver ) return Response({"success": True, "message": "Request sent"}) @action(methods=["get"], detail=True) def remove_friend(self, request, pk): friend = User.objects.get(pk=pk) if self.request.user.friends.filter(pk=friend.pk).exists(): self.request.user.friends.remove(friend) return Response({"success": True, "message": f"The friend {friend.username} successfully removed"}) return Response({"success": False, "message": f"error"}) @action(methods=["get"], detail=False) def user_stats(self, request): stats = User.objects.filter(id=request.user.id).aggregate( total_size=Coalesce(Sum("torrents__size"), 0), total_torrent=Coalesce(Count("torrents"), 0), total_shared_torrent=Coalesce(Count("torrents_shares", distinct=True), 0), ) disk_usage = shutil.disk_usage("/") return Response({ "torrents_size": stats["total_size"], "torrents_len": stats["total_torrent"], "torrent_len_shared": stats["total_shared_torrent"], "torrents_total_len": stats["total_torrent"] + stats["total_shared_torrent"], "user_max_size": request.user.max_size, "user_usage_percent": (stats["total_size"] / request.user.max_size) * 100, "disk_total": disk_usage.total, "disk_used": disk_usage.used, "disk_free": disk_usage.free, "disk_usage_percent": (disk_usage.used / disk_usage.total) * 100, }) class FriendRequestViewSet(mixins.ListModelMixin, mixins.DestroyModelMixin, GenericViewSet): queryset = FriendRequest.objects.all() serializer_class = FriendRequestSerializer def get_queryset(self): qs = super().get_queryset() qs = qs.filter(receiver=self.request.user) return qs