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.
350 lines
13 KiB
350 lines
13 KiB
from rest_framework import serializers
|
|
from utils import get_thumbs
|
|
from apps.podcast.models import *
|
|
from apps.bookmark.serializers import *
|
|
|
|
|
|
class PodcastCategoryListSerializer(serializers.ModelSerializer):
|
|
playlist_count = serializers.SerializerMethodField()
|
|
|
|
class Meta:
|
|
model = PodcastCategory
|
|
fields = ['id', 'title', 'slug', 'playlist_count']
|
|
|
|
def get_playlist_count(self, obj):
|
|
return obj.playlists.filter(status=True).count()
|
|
|
|
|
|
class PodcastListSerializer(serializers.ModelSerializer):
|
|
thumbnail = serializers.SerializerMethodField()
|
|
audio_file = serializers.SerializerMethodField()
|
|
in_user_playlist = serializers.SerializerMethodField()
|
|
share_link = serializers.CharField(read_only=True)
|
|
audio_time = serializers.SerializerMethodField()
|
|
|
|
class Meta:
|
|
model = Podcast
|
|
fields = ['id', 'title', 'slug', 'thumbnail', 'description', 'audio_file',
|
|
'audio_time', 'view_count', 'created_at', 'in_user_playlist', 'share_link']
|
|
|
|
def get_thumbnail(self, obj):
|
|
return get_thumbs(obj.thumbnail, self.context.get('request'))
|
|
|
|
def get_audio_file(self, obj):
|
|
"""Get full URL for audio file if it exists"""
|
|
if obj.audio_file:
|
|
request = self.context.get('request')
|
|
if request:
|
|
return request.build_absolute_uri(obj.audio_file.url)
|
|
return obj.audio_file.url
|
|
return None
|
|
|
|
def get_audio_time(self, obj):
|
|
if not obj.audio_time:
|
|
return None
|
|
|
|
# obj.audio_time is a datetime.time object
|
|
if obj.audio_time.hour == 0:
|
|
return obj.audio_time.strftime('%M:%S') # Returns "44:00"
|
|
return obj.audio_time.strftime('%H:%M:%S') # Returns "01:44:00"
|
|
|
|
def get_in_user_playlist(self, obj):
|
|
"""
|
|
Check if the podcast is in the user's personal playlist.
|
|
Returns True if the podcast is in the user's playlist and active, False otherwise.
|
|
"""
|
|
request = self.context.get('request')
|
|
user = request.user if request and request.user.is_authenticated else None
|
|
|
|
if not user:
|
|
return False
|
|
|
|
return UserPlaylist.is_in_user_playlist(user, obj)
|
|
|
|
|
|
class PodcastDetailSerializer(serializers.ModelSerializer):
|
|
categories = PodcastCategoryListSerializer(many=True, read_only=True)
|
|
thumbnail = serializers.SerializerMethodField()
|
|
bookmark = serializers.SerializerMethodField()
|
|
user_rate = serializers.SerializerMethodField()
|
|
average_rate = serializers.SerializerMethodField()
|
|
is_in_playlist = serializers.SerializerMethodField()
|
|
playlist_podcasts = serializers.SerializerMethodField()
|
|
in_user_playlist = serializers.SerializerMethodField()
|
|
share_link = serializers.CharField(read_only=True)
|
|
audio_time = serializers.SerializerMethodField()
|
|
class Meta:
|
|
model = Podcast
|
|
fields = ['id', 'title', 'slug', 'thumbnail', 'description',
|
|
'audio_file', 'audio_time', 'view_count', 'download_count',
|
|
'categories', 'created_at', 'user_rate', 'average_rate', 'bookmark',
|
|
'is_in_playlist', 'playlist_podcasts', 'in_user_playlist', 'share_link']
|
|
|
|
def get_thumbnail(self, obj):
|
|
return get_thumbs(obj.thumbnail, self.context.get('request'))
|
|
|
|
def get_bookmark(self, obj):
|
|
"""
|
|
Get bookmark information for this podcast.
|
|
"""
|
|
# Get the current user from the request context
|
|
request = self.context.get('request')
|
|
user = request.user if request else None
|
|
book_mark = BookmarkStatusSerializer.get_bookmark_info(
|
|
obj=obj,
|
|
user=user,
|
|
service='podcast'
|
|
)
|
|
return book_mark.get('is_bookmarked', False)
|
|
|
|
def get_audio_time(self, obj):
|
|
if not obj.audio_time:
|
|
return None
|
|
|
|
if obj.audio_time.hour == 0:
|
|
return obj.audio_time.strftime('%M:%S')
|
|
return obj.audio_time.strftime('%H:%M:%S')
|
|
|
|
def get_user_rate(self, obj):
|
|
"""
|
|
Get rate information for this podcast from the current user.
|
|
"""
|
|
from apps.bookmark.models.rate import Rate
|
|
|
|
# Get the current user from the request context
|
|
request = self.context.get('request')
|
|
user = request.user if request and request.user.is_authenticated else None
|
|
|
|
if not user:
|
|
return {
|
|
'is_rated': False,
|
|
'rate': None
|
|
}
|
|
|
|
# Get rate information using the Rate model's method
|
|
rate_info = Rate.get_user_rate(
|
|
user=user,
|
|
service='podcast',
|
|
content_id=obj.id
|
|
)
|
|
|
|
return rate_info
|
|
|
|
def get_average_rate(self, obj):
|
|
"""
|
|
Get the average rate for this podcast.
|
|
"""
|
|
from apps.bookmark.models.rate import Rate
|
|
|
|
# Get average rate information using the Rate model
|
|
return Rate.get_average_rate(
|
|
service='podcast',
|
|
content_id=obj.id
|
|
)
|
|
|
|
def get_is_in_playlist(self, obj):
|
|
"""
|
|
Check if the podcast is in any playlist.
|
|
Returns True if the podcast is in at least one playlist, False otherwise.
|
|
"""
|
|
return PlaylistItem.objects.filter(podcast=obj).exists()
|
|
|
|
def get_playlist_podcasts(self, obj):
|
|
"""
|
|
If the podcast is in a playlist, return all podcasts from the first playlist it belongs to,
|
|
excluding the current podcast itself. Podcasts are ordered by their priority in the playlist.
|
|
Returns null if the podcast is not in any playlist.
|
|
"""
|
|
# Check if the podcast is in any playlist
|
|
if not self.get_is_in_playlist(obj):
|
|
return None
|
|
|
|
# Get the first playlist that contains this podcast
|
|
playlist_item = PlaylistItem.objects.filter(podcast=obj).first()
|
|
if not playlist_item:
|
|
return None
|
|
|
|
playlist = playlist_item.playlist
|
|
|
|
# Get all podcasts in this playlist except the current one, ordered by priority
|
|
playlist_podcasts = Podcast.objects.filter(
|
|
playlist_appearances__playlist=playlist
|
|
).exclude(
|
|
id=obj.id
|
|
).distinct().order_by('playlist_appearances__priority')
|
|
|
|
# Serialize the podcasts
|
|
return PodcastListSerializer(
|
|
playlist_podcasts,
|
|
many=True,
|
|
context=self.context
|
|
).data
|
|
|
|
def get_in_user_playlist(self, obj):
|
|
"""
|
|
Check if the podcast is in the user's personal playlist.
|
|
Returns True if the podcast is in the user's playlist and active, False otherwise.
|
|
"""
|
|
request = self.context.get('request')
|
|
user = request.user if request and request.user.is_authenticated else None
|
|
|
|
if not user:
|
|
return False
|
|
|
|
return UserPlaylist.is_in_user_playlist(user, obj)
|
|
|
|
|
|
class PinnedPodcastCollectionSerializer(serializers.ModelSerializer):
|
|
thumbnail = serializers.SerializerMethodField()
|
|
|
|
class Meta:
|
|
model = PodcastCollection
|
|
fields = ['id', 'title', 'slug', 'summary', 'thumbnail', 'order', 'created_at']
|
|
|
|
def get_thumbnail(self, obj):
|
|
return get_thumbs(obj.thumbnail, self.context.get('request'))
|
|
|
|
|
|
class PodcastPlaylistListSerializer(serializers.ModelSerializer):
|
|
thumbnail = serializers.SerializerMethodField()
|
|
total_time_formatted = serializers.SerializerMethodField()
|
|
episodes_count = serializers.SerializerMethodField()
|
|
|
|
class Meta:
|
|
model = PodcastPlaylist
|
|
fields = ['id', 'title', 'slug', 'thumbnail', 'slogan', 'view_count', 'total_time_formatted', 'episodes_count', 'order', 'created_at']
|
|
|
|
def get_thumbnail(self, obj):
|
|
return get_thumbs(obj.thumbnail, self.context.get('request'))
|
|
|
|
def get_total_time_formatted(self, obj):
|
|
"""Format total_time dynamically as MM:SS or HH:MM:SS"""
|
|
if obj.total_time:
|
|
total_seconds = int(obj.total_time.total_seconds())
|
|
hours = total_seconds // 3600
|
|
minutes = (total_seconds % 3600) // 60
|
|
seconds = total_seconds % 60
|
|
|
|
# Strip hours if the playlist is under 60 mins
|
|
if hours > 0:
|
|
return f"{hours:02d}:{minutes:02d}:{seconds:02d}"
|
|
return f"{minutes:02d}:{seconds:02d}"
|
|
|
|
return "00:00"
|
|
|
|
def get_episodes_count(self, obj):
|
|
"""Return the number of episodes (podcasts) in this playlist"""
|
|
return obj.playlist_items.count()
|
|
|
|
|
|
class PodcastPlaylistDetailSerializer(serializers.ModelSerializer):
|
|
categories = PodcastCategoryListSerializer(many=True, read_only=True)
|
|
thumbnail = serializers.SerializerMethodField()
|
|
bookmark = serializers.SerializerMethodField()
|
|
user_rate = serializers.SerializerMethodField()
|
|
average_rate = serializers.SerializerMethodField()
|
|
podcasts = serializers.SerializerMethodField()
|
|
total_time_formatted = serializers.SerializerMethodField()
|
|
|
|
class Meta:
|
|
model = PodcastPlaylist
|
|
fields = ['id', 'title', 'slug', 'thumbnail', 'slogan', 'description',
|
|
'view_count', 'total_time_formatted', 'order', 'status',
|
|
'categories', 'created_at', 'user_rate', 'average_rate', 'bookmark', 'podcasts']
|
|
|
|
def get_thumbnail(self, obj):
|
|
return get_thumbs(obj.thumbnail, self.context.get('request'))
|
|
|
|
def get_total_time_formatted(self, obj):
|
|
"""Format total_time as HH:MM:SS string"""
|
|
if obj.total_time:
|
|
total_seconds = int(obj.total_time.total_seconds())
|
|
hours = total_seconds // 3600
|
|
minutes = (total_seconds % 3600) // 60
|
|
seconds = total_seconds % 60
|
|
return f"{hours:02d}:{minutes:02d}:{seconds:02d}"
|
|
return "00:00:00"
|
|
|
|
def get_bookmark(self, obj):
|
|
"""Get bookmark information for this playlist."""
|
|
request = self.context.get('request')
|
|
user = request.user if request else None
|
|
book_mark = BookmarkStatusSerializer.get_bookmark_info(
|
|
obj=obj,
|
|
user=user,
|
|
service='podcast'
|
|
)
|
|
return book_mark.get('is_bookmarked', False)
|
|
|
|
def get_user_rate(self, obj):
|
|
"""Get rate information for this playlist from the current user."""
|
|
from apps.bookmark.models.rate import Rate
|
|
|
|
request = self.context.get('request')
|
|
user = request.user if request and request.user.is_authenticated else None
|
|
|
|
if not user:
|
|
return {
|
|
'is_rated': False,
|
|
'rate': None
|
|
}
|
|
|
|
rate_info = Rate.get_user_rate(
|
|
user=user,
|
|
service='podcast',
|
|
content_id=obj.id
|
|
)
|
|
|
|
return rate_info
|
|
|
|
def get_average_rate(self, obj):
|
|
"""Get the average rate for this playlist."""
|
|
from apps.bookmark.models.rate import Rate
|
|
|
|
return Rate.get_average_rate(
|
|
service='podcast',
|
|
content_id=obj.id
|
|
)
|
|
|
|
def get_podcasts(self, obj):
|
|
"""Get all podcasts in this playlist ordered by priority."""
|
|
podcasts = Podcast.objects.filter(
|
|
playlist_appearances__playlist=obj
|
|
).distinct().order_by('playlist_appearances__priority')
|
|
|
|
return PodcastListSerializer(
|
|
podcasts,
|
|
many=True,
|
|
context=self.context
|
|
).data
|
|
|
|
|
|
class MiddlePodcastCollectionSerializer(serializers.ModelSerializer):
|
|
playlists = serializers.SerializerMethodField()
|
|
|
|
class Meta:
|
|
model = PodcastCollection
|
|
fields = ('id', 'title', 'slug', 'summary', 'status', 'order', 'pin_top', 'playlists')
|
|
|
|
def get_playlists(self, obj):
|
|
playlists = obj.related_playlists.filter(status=True).order_by('order', '-created_at')
|
|
return PodcastPlaylistListSerializer(playlists, many=True, context=self.context).data
|
|
|
|
|
|
class UserPlaylistSerializer(serializers.ModelSerializer):
|
|
class Meta:
|
|
model = UserPlaylist
|
|
fields = ('id', 'podcast', 'status', 'created_at', 'updated_at')
|
|
read_only_fields = ('id', 'created_at', 'updated_at')
|
|
|
|
|
|
class UserPlaylistCreateSerializer(serializers.Serializer):
|
|
podcast_id = serializers.IntegerField()
|
|
status = serializers.BooleanField(default=True)
|
|
|
|
def validate_podcast_id(self, value):
|
|
try:
|
|
podcast = Podcast.objects.get(id=value, status=True)
|
|
return value
|
|
except Podcast.DoesNotExist:
|
|
raise serializers.ValidationError("Podcast with this ID does not exist or is not active.")
|