You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

305 lines
12 KiB

from rest_framework import status
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from rest_framework.authentication import TokenAuthentication
from rest_framework.generics import CreateAPIView, DestroyAPIView
from rest_framework.exceptions import ValidationError
from drf_yasg.utils import swagger_auto_schema
from drf_yasg import openapi
from apps.bookmark.models import Bookmark
from apps.bookmark.serializers import BookmarkSerializer
class AddBookmarkView(CreateAPIView):
"""
Add a bookmark for a specific content in a service.
If the bookmark already exists but is inactive, it will be reactivated.
"""
permission_classes = [IsAuthenticated]
authentication_classes = [TokenAuthentication]
serializer_class = BookmarkSerializer
@swagger_auto_schema(
operation_description="Add a bookmark for a specific content in a service.\
If the bookmark already exists but is inactive, it will be reactivated.\
\n Services must be choose from : \n \
'Library'\n'Podcast'\n'Podcast Playlist'\n'Hadith' \n 'Hadith Correction'\n'Video'\n'Video Playlist'\n'Article'",
tags=["Dobodbi - Bookmarks"],
request_body=BookmarkSerializer,
responses={
201: "Bookmark created successfully.",
200: "Bookmark reactivated or already active.",
400: "Invalid input."
}
)
def post(self, request, *args, **kwargs):
return super().post(request,*args, **kwargs)
def create(self, request, *args, **kwargs):
service = request.data.get('service')
content_id = request.data.get('content_id')
if not service or not content_id:
return Response(
{'error': 'Both service and content_id are required'},
status=status.HTTP_400_BAD_REQUEST
)
# Check if the bookmark already exists
bookmark = Bookmark.objects.filter(
user=request.user,
service=service,
content_id=content_id
).first()
if bookmark:
# If bookmark exists but is inactive, reactivate it
if not bookmark.status:
bookmark.status = True
bookmark.save()
serializer = self.get_serializer(bookmark)
return Response(serializer.data, status=status.HTTP_200_OK)
# If bookmark exists and is active, return it
serializer = self.get_serializer(bookmark)
return Response(serializer.data, status=status.HTTP_200_OK)
# Create a new bookmark
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
def perform_create(self, serializer):
serializer.save(user=self.request.user)
class RemoveBookmarkView(DestroyAPIView):
"""
Deactivate a bookmark by setting its status to False using content_id and user.
The request should specify the content_id of the bookmark to be deactivated.
"""
permission_classes = [IsAuthenticated]
authentication_classes = [TokenAuthentication]
serializer_class = BookmarkSerializer
@swagger_auto_schema(
operation_description="Deactivate a bookmark by setting its status to False using content_id and user.",
tags=["Dobodbi - Bookmarks"],
request_body=openapi.Schema(
type=openapi.TYPE_OBJECT,
properties={
'service': openapi.Schema(type=openapi.TYPE_STRING, description='The service associated with the bookmark.'),
'content_id': openapi.Schema(type=openapi.TYPE_STRING, description='The ID of the content to deactivate the bookmark for.')
},
required=['service', 'content_id']
),
responses={
204: "Bookmark deactivated successfully.",
400: "Invalid input.",
404: "Bookmark not found or already inactive."
}
)
def delete(self,request,*args, **kwargs):
return super().delete(request,*args, **kwargs)
def get_object(self):
service = self.request.data.get('service')
content_id = self.request.data.get('content_id')
if not service or not content_id:
raise ValidationError('Both service and content_id are required')
bookmark = Bookmark.objects.filter(
user=self.request.user,
service=service,
content_id=content_id,
status=True
).first()
if not bookmark:
raise ValidationError('Bookmark not found or already inactive')
return bookmark
def destroy(self, request, *args, **kwargs):
bookmark = self.get_object()
bookmark.status = False
bookmark.save()
return Response(status=status.HTTP_204_NO_CONTENT)
class AddBookmarkListView(APIView):
"""
Add a list of bookmarks in a single API call.
Each item can be added or reactivated.
"""
permission_classes = [IsAuthenticated]
authentication_classes = [TokenAuthentication]
@swagger_auto_schema(
operation_description="Add multiple bookmarks in one request. Each item should have 'service' and 'content_id'.",
tags=["Dobodbi - Bookmarks"],
request_body=openapi.Schema(
type=openapi.TYPE_ARRAY,
items=openapi.Schema(
type=openapi.TYPE_OBJECT,
properties={
'service': openapi.Schema(type=openapi.TYPE_STRING, description='Service name'),
'content_id': openapi.Schema(type=openapi.TYPE_INTEGER, description='Content ID'),
},
required=['service', 'content_id']
)
),
responses={
200: "Bookmarks processed successfully.",
400: "Invalid input."
}
)
def post(self, request, *args, **kwargs):
items = request.data
if not isinstance(items, list):
return Response({'error': 'Expected a list of bookmark items.'}, status=status.HTTP_400_BAD_REQUEST)
results = []
errors = []
for index, item in enumerate(items):
service = item.get('service')
content_id = item.get('content_id')
if not service or not content_id:
errors.append({'index': index, 'error': 'Both service and content_id are required.'})
continue
bookmark = Bookmark.objects.filter(
user=request.user,
service=service,
content_id=content_id
).first()
if bookmark:
if not bookmark.status:
bookmark.status = True
bookmark.save()
results.append({'index': index, 'service': service, 'content_id': content_id, 'action': 'reactivated'})
else:
serializer = BookmarkSerializer(data=item, context={'request': request})
if serializer.is_valid():
serializer.save(user=request.user)
results.append({'index': index, 'service': service, 'content_id': content_id, 'action': 'created'})
else:
errors.append({'index': index, 'error': serializer.errors})
response_data = {'results': results}
if errors:
response_data['errors'] = errors
return Response(response_data, status=status.HTTP_200_OK)
class RemoveBookmarkListView(APIView):
"""
Deactivate a list of bookmarks in a single API call.
"""
permission_classes = [IsAuthenticated]
authentication_classes = [TokenAuthentication]
@swagger_auto_schema(
operation_description="Remove (deactivate) multiple bookmarks in one request. Each item should have 'service' and 'content_id'.",
tags=["Dobodbi - Bookmarks"],
request_body=openapi.Schema(
type=openapi.TYPE_ARRAY,
items=openapi.Schema(
type=openapi.TYPE_OBJECT,
properties={
'service': openapi.Schema(type=openapi.TYPE_STRING, description='Service name'),
'content_id': openapi.Schema(type=openapi.TYPE_INTEGER, description='Content ID'),
},
required=['service', 'content_id']
)
),
responses={
200: "Bookmarks processed successfully.",
400: "Invalid input."
}
)
def post(self, request, *args, **kwargs):
items = request.data
if not isinstance(items, list):
return Response({'error': 'Expected a list of bookmark items.'}, status=status.HTTP_400_BAD_REQUEST)
results = []
errors = []
for index, item in enumerate(items):
service = item.get('service')
content_id = item.get('content_id')
if not service or not content_id:
errors.append({'index': index, 'error': 'Both service and content_id are required.'})
continue
bookmark = Bookmark.objects.filter(
user=request.user,
service=service,
content_id=content_id,
status=True
).first()
if bookmark:
bookmark.status = False
bookmark.save()
results.append({'index': index, 'service': service, 'content_id': content_id, 'action': 'removed'})
else:
errors.append({'index': index, 'service': service, 'content_id': content_id, 'error': 'Bookmark not found or already inactive.'})
response_data = {'results': results}
if errors:
response_data['errors'] = errors
return Response(response_data, status=status.HTTP_200_OK)
class BookmarkStatusView(APIView):
"""
Return the count of bookmarks for each service for the current user.
"""
permission_classes = [IsAuthenticated]
authentication_classes = [TokenAuthentication]
@swagger_auto_schema(
operation_description="Return the count of bookmarks for each service for the current user.",
tags=["Dobodbi - Bookmarks"],
responses={
200: "A list of bookmark counts for each service.",
}
)
def get(self, request):
# Get all active bookmarks for the current user
user_bookmarks = Bookmark.objects.filter(
user=request.user,
status=True
)
# Get the count of bookmarks for each service
service_counts = {}
for service_choice in Bookmark.ServiceChoices.choices:
service_code = service_choice[0] # Get the service code (e.g., 'library')
service_name = service_choice[1] # Get the service display name (e.g., 'Library')
# Count bookmarks for this service
count = user_bookmarks.filter(service=service_code).count()
# Add to results
service_counts[service_code] = {
'service': service_code,
'service_display': service_name,
'count': count
}
# Convert to list for response
result = list(service_counts.values())
return Response(result, status=status.HTTP_200_OK)