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.
 
 

356 lines
13 KiB

from rest_framework import generics, status
from rest_framework.response import Response
from rest_framework.authentication import TokenAuthentication
from drf_yasg import openapi
from drf_yasg.utils import swagger_auto_schema
from apps.library.pagination import NoPagination
from rest_framework.permissions import IsAuthenticated
from apps.podcast.models import *
from apps.podcast.serializers import *
from utils.pagination import StandardResultsSetPagination
class PodcastCategoryListAPIView(generics.ListAPIView):
"""
API view to list all podcast categories
"""
serializer_class = PodcastCategoryListSerializer
pagination_class = StandardResultsSetPagination
@swagger_auto_schema(
operation_description="Get a list of all active podcast categories",
tags=["Dobodbi - Podcast"],
responses={
200: openapi.Response(
description="List of podcast categories",
schema=PodcastCategoryListSerializer(many=True)
)
}
)
def get(self, request, *args, **kwargs):
return super().get(request, *args, **kwargs)
def get_queryset(self):
return PodcastCategory.objects.filter(status=True).order_by('order')
class PinnedPodcastCollectionListView(generics.ListAPIView):
serializer_class = PinnedPodcastCollectionSerializer
permission_classes = (IsAuthenticated,)
authentication_classes = [TokenAuthentication]
pagination_class = NoPagination
@swagger_auto_schema(
operation_description="Get a list of pinned podcast collections",
tags=["Dobodbi - Podcast"],
responses={
200: openapi.Response(
description="List of pinned podcast collections",
schema=PinnedPodcastCollectionSerializer(many=True)
)
}
)
def get(self, request, *args, **kwargs):
return super().get(request, *args, **kwargs)
def get_queryset(self):
return PinnedPodcastCollection.objects.filter(
status=True,
display_position=PodcastCollection.DisplayPosition.PINNED
).order_by('-order', '-id')
def list(self, request, *args, **kwargs):
response = super().list(request, *args, **kwargs)
categories_count = PodcastCategory.objects.filter(status=True).count()
# Count podcasts in the user's playlist
user_playlist_count = 0
if request.user.is_authenticated:
user_playlist_count = UserPlaylist.objects.filter(
user=request.user,
status=True
).count()
info = {
"categories_count": categories_count,
"user_playlist_count": user_playlist_count,
}
data = {
"count": response.data.get("count"),
"next": response.data.get("next"),
"previous": response.data.get("previous"),
"info": info,
"results": response.data.get("results")
}
return Response(data, status=status.HTTP_200_OK)
class MiddlePodcastCollectionListView(generics.ListAPIView):
serializer_class = MiddlePodcastCollectionSerializer
permission_classes = (IsAuthenticated,)
authentication_classes = [TokenAuthentication]
pagination_class = NoPagination
@swagger_auto_schema(
operation_description="Get a list of middle podcast collections",
tags=["Dobodbi - Podcast"],
responses={
200: openapi.Response(
description="List of middle podcast collections",
schema=MiddlePodcastCollectionSerializer(many=True)
)
}
)
def get(self, request, *args, **kwargs):
return super().get(request, *args, **kwargs)
def get_queryset(self):
return PodcastCollection.objects.filter(
status=True,
display_position=PodcastCollection.DisplayPosition.MIDDLE
).order_by('order')
class PodcastListAPIView(generics.ListAPIView):
"""
API view to list all podcast playlists, with optional filtering by category, collection
"""
serializer_class = PodcastPlaylistListSerializer
permission_classes = (IsAuthenticated,)
authentication_classes = [TokenAuthentication]
pagination_class = StandardResultsSetPagination
@swagger_auto_schema(
operation_description="Get a list of podcast playlists with optional filtering and sorting",
tags=["Dobodbi - Podcast"],
manual_parameters=[
openapi.Parameter(
name='category',
in_=openapi.IN_QUERY,
description='Filter playlists by category slug(s). Can be a single slug or comma-separated list of slugs',
type=openapi.TYPE_STRING,
required=False
),
openapi.Parameter(
name='collection',
in_=openapi.IN_QUERY,
description='Filter playlists by collection slug',
type=openapi.TYPE_STRING,
required=False
),
openapi.Parameter(
name='is_bookmark',
in_=openapi.IN_QUERY,
description='Filter playlists that are bookmarked by the user (true/false)',
type=openapi.TYPE_BOOLEAN,
required=False
),
openapi.Parameter(
name='search',
in_=openapi.IN_QUERY,
description='Search playlists by title',
type=openapi.TYPE_STRING,
required=False
),
openapi.Parameter(
name='sort',
in_=openapi.IN_QUERY,
description='Sort playlists by field. Options: created_at, -created_at, view_count, -view_count, title, -title, order, -order',
type=openapi.TYPE_STRING,
required=False
)
],
responses={
200: openapi.Response(
description="List of podcast playlists with episodes count",
schema=PodcastPlaylistListSerializer(many=True)
)
}
)
def get(self, request, *args, **kwargs):
return super().get(request, *args, **kwargs)
def get_queryset(self):
queryset = PodcastPlaylist.objects.filter(status=True)
# Search by title if search parameter is provided
search_query = self.request.query_params.get('search', None)
if search_query:
queryset = queryset.filter(title__icontains=search_query)
# Filter by category if provided
category = self.request.query_params.get('category', None)
if category:
# Support both single slug and comma-separated list of slugs
category_slugs = [slug.strip() for slug in category.split(',')]
queryset = queryset.filter(categories__slug__in=category_slugs).distinct()
# Filter by collection if provided
collection_slug = self.request.query_params.get('collection', None)
if collection_slug:
queryset = queryset.filter(
collections__slug=collection_slug
)
# Filter by bookmarks if provided
is_bookmark = self.request.query_params.get('is_bookmark', '').lower()
if is_bookmark == 'true':
from apps.bookmark.models import Bookmark
bookmarked_ids = Bookmark.objects.filter(
user=self.request.user,
service=Bookmark.ServiceChoices.PODCAST_PLAYLIST,
status=True
).values_list('content_id', flat=True)
queryset = queryset.filter(id__in=bookmarked_ids)
# Sort by parameter
sort = self.request.query_params.get('sort', '-created_at')
# Allowed sort fields
allowed_sorts = [
'created_at', '-created_at', 'view_count', '-view_count',
'title', '-title', 'order', '-order'
]
if sort in allowed_sorts:
queryset = queryset.order_by(sort)
else:
queryset = queryset.order_by('-created_at')
return queryset
class PodcastDetailAPIView(generics.RetrieveAPIView):
"""
API view to retrieve details of a specific podcast playlist
"""
serializer_class = PodcastPlaylistDetailSerializer
lookup_field = 'slug'
permission_classes = (IsAuthenticated,)
authentication_classes = [TokenAuthentication]
@swagger_auto_schema(
operation_description="Get podcast playlist details by slug",
tags=["Dobodbi - Podcast"],
responses={
200: openapi.Response(
description="Podcast playlist details",
schema=PodcastPlaylistDetailSerializer()
)
}
)
def get(self, request, *args, **kwargs):
return super().get(request, *args, **kwargs)
def get_queryset(self):
return PodcastPlaylist.objects.filter(status=True)
def retrieve(self, request, *args, **kwargs):
instance = self.get_object()
instance.increment_view_count()
serializer = self.get_serializer(instance)
return Response(serializer.data)
class UserPlaylistListAPIView(generics.ListAPIView):
"""
API view to list all podcasts in the user's personal playlist
"""
serializer_class = PodcastListSerializer
permission_classes = (IsAuthenticated,)
authentication_classes = [TokenAuthentication]
pagination_class = StandardResultsSetPagination
@swagger_auto_schema(
operation_description="Get a list of podcasts in the user's personal playlist",
tags=["Dobodbi - Podcast"],
responses={
200: openapi.Response(
description="List of podcasts in the user's playlist",
schema=PodcastListSerializer(many=True)
)
}
)
def get(self, request, *args, **kwargs):
return super().get(request, *args, **kwargs)
def get_queryset(self):
# Get all active podcasts that are in the user's playlist
user_playlist_podcasts = UserPlaylist.objects.filter(
user=self.request.user,
status=True
).values_list('podcast_id', flat=True)
queryset = Podcast.objects.filter(
id__in=user_playlist_podcasts,
status=True
).order_by('-created_at')
# Filter by bookmarks if provided
is_bookmark = self.request.query_params.get('is_bookmark', '').lower()
if is_bookmark == 'true' and self.request.user.is_authenticated:
from apps.bookmark.models.bookmark import Bookmark
bookmarked_ids = Bookmark.objects.filter(
user=self.request.user,
service=Bookmark.ServiceChoices.PODCAST,
status=True
).values_list('content_id', flat=True)
queryset = queryset.filter(id__in=bookmarked_ids)
return queryset
class UserPlaylistCreateAPIView(generics.CreateAPIView):
"""
API view to add or update a podcast in a user's personal playlist
"""
serializer_class = UserPlaylistCreateSerializer
permission_classes = (IsAuthenticated,)
authentication_classes = [TokenAuthentication]
@swagger_auto_schema(
operation_description="Add or update a podcast in the user's personal playlist",
tags=["Dobodbi - Podcast"],
request_body=UserPlaylistCreateSerializer,
responses={
201: openapi.Response(
description="Podcast added to playlist successfully",
schema=UserPlaylistSerializer()
),
400: "Bad Request"
}
)
def post(self, request, *args, **kwargs):
return super().post(request, *args, **kwargs)
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
podcast_id = serializer.validated_data['podcast_id']
playlist_status = serializer.validated_data.get('status', True)
try:
podcast = Podcast.objects.get(id=podcast_id, status=True)
except Podcast.DoesNotExist:
return Response(
{"detail": "Podcast not found or not active."},
status=status.HTTP_404_NOT_FOUND
)
# Try to get existing user playlist entry or create a new one
user_playlist, created = UserPlaylist.objects.update_or_create(
user=request.user,
podcast=podcast,
defaults={'status': playlist_status}
)
# Return the user playlist entry
response_serializer = UserPlaylistSerializer(user_playlist)
return Response(
response_serializer.data,
status=status.HTTP_201_CREATED if created else status.HTTP_200_OK
)