lib.itmens/catalog/podcast/models.py

166 lines
4.5 KiB
Python
Raw Normal View History

2024-05-27 15:44:12 -04:00
from typing import TYPE_CHECKING
2023-01-05 03:06:13 -05:00
from django.db import models
from django.utils.translation import gettext_lazy as _
from ninja import Field
2023-08-11 01:43:19 -04:00
from catalog.common import (
BaseSchema,
IdType,
Item,
ItemCategory,
ItemInSchema,
jsondata,
)
2024-07-16 17:49:10 -04:00
from catalog.common.models import LIST_OF_ONE_PLUS_STR_SCHEMA, LanguageListField
2023-02-15 15:45:57 -05:00
class PodcastInSchema(ItemInSchema):
genre: list[str]
host: list[str]
language: list[str]
2023-02-15 15:45:57 -05:00
official_site: str | None = None
# hosts is deprecated
hosts: list[str] = Field(deprecated=True, alias="host")
2023-02-15 15:45:57 -05:00
class PodcastSchema(PodcastInSchema, BaseSchema):
pass
class Podcast(Item):
2024-05-27 15:44:12 -04:00
if TYPE_CHECKING:
episodes: models.QuerySet["PodcastEpisode"]
2022-12-11 23:20:28 +00:00
category = ItemCategory.Podcast
2024-02-03 22:19:01 -05:00
child_class = "PodcastEpisode"
2022-12-29 23:57:02 -05:00
url_path = "podcast"
2023-01-29 20:05:30 -05:00
# apple_podcast = PrimaryLookupIdDescriptor(IdType.ApplePodcast)
# ximalaya = LookupIdDescriptor(IdType.Ximalaya)
# xiaoyuzhou = LookupIdDescriptor(IdType.Xiaoyuzhou)
2023-01-29 20:05:30 -05:00
genre = jsondata.ArrayField(
2024-03-10 20:55:50 -04:00
verbose_name=_("genre"),
2023-01-29 20:05:30 -05:00
base_field=models.CharField(blank=True, default="", max_length=200),
null=True,
blank=True,
default=list,
)
2024-07-13 00:16:47 -04:00
language = LanguageListField()
2024-11-22 23:44:14 -05:00
host = jsondata.ArrayField(
2024-03-10 20:55:50 -04:00
verbose_name=_("host"),
2024-11-22 23:44:14 -05:00
base_field=models.CharField(blank=True, default="", max_length=200),
2024-07-16 17:49:10 -04:00
null=False,
blank=False,
2023-01-29 20:05:30 -05:00
default=list,
2024-07-16 17:49:10 -04:00
schema=LIST_OF_ONE_PLUS_STR_SCHEMA,
2023-01-29 20:05:30 -05:00
)
official_site = jsondata.CharField(
2024-03-10 20:55:50 -04:00
verbose_name=_("website"), max_length=1000, null=True, blank=True
2023-01-29 20:05:30 -05:00
)
METADATA_COPY_LIST = [
2024-07-13 00:16:47 -04:00
# "title",
# "brief",
"localized_title",
"language",
2024-07-15 22:18:25 -04:00
"host",
2023-01-29 20:05:30 -05:00
"genre",
"official_site",
"localized_description",
2023-01-29 20:05:30 -05:00
]
@classmethod
def lookup_id_type_choices(cls):
id_types = [
IdType.RSS,
]
return [(i.value, i.label) for i in id_types]
2023-01-29 20:05:30 -05:00
@property
def recent_episodes(self):
return self.episodes.all().order_by("-pub_date")[:10]
@property
def feed_url(self):
if (
self.primary_lookup_id_type != IdType.RSS
and self.primary_lookup_id_value is None
):
return None
return f"http://{self.primary_lookup_id_value}"
@property
def child_items(self):
2024-02-03 22:19:01 -05:00
return self.episodes.filter(is_deleted=False, merged_to_item=None)
2024-07-16 17:49:10 -04:00
def can_soft_delete(self):
# override can_soft_delete() and allow delete podcast with episodes
return (
not self.is_deleted
and not self.merged_to_item_id
and not self.merged_from_items.exists()
)
2023-01-29 20:05:30 -05:00
class PodcastEpisode(Item):
category = ItemCategory.Podcast
2023-01-31 21:21:50 -05:00
url_path = "podcast/episode"
2023-01-29 20:05:30 -05:00
# uid = models.UUIDField(default=uuid.uuid4, editable=False, db_index=True)
program = models.ForeignKey(Podcast, models.CASCADE, related_name="episodes")
guid = models.CharField(null=True, max_length=1000)
2024-02-03 22:19:01 -05:00
pub_date = models.DateTimeField(
2024-03-10 20:55:50 -04:00
verbose_name=_("date of publication"), help_text="yyyy/mm/dd hh:mm"
2024-02-03 22:19:01 -05:00
)
2023-01-29 20:05:30 -05:00
media_url = models.CharField(null=True, max_length=1000)
# title = models.CharField(default="", max_length=1000)
# description = models.TextField(null=True)
description_html = models.TextField(null=True)
link = models.CharField(null=True, max_length=1000)
cover_url = models.CharField(null=True, max_length=1000)
duration = models.PositiveIntegerField(null=True)
2024-02-03 22:19:01 -05:00
METADATA_COPY_LIST = [
"title",
"brief",
"pub_date",
]
2023-01-31 21:21:50 -05:00
@property
2024-05-27 15:44:12 -04:00
def parent_item(self) -> Podcast | None: # type:ignore
2023-01-31 21:21:50 -05:00
return self.program
2024-05-27 15:44:12 -04:00
def set_parent_item(self, value: Podcast | None): # type:ignore
2024-02-03 22:19:01 -05:00
self.program = value
2023-06-05 02:04:52 -04:00
@property
2024-05-26 22:57:49 -04:00
def display_title(self) -> str:
return f"{self.program.title} - {self.title}" if self.program else self.title
2023-06-05 02:04:52 -04:00
2023-04-19 22:31:27 -04:00
@property
2024-05-26 22:57:49 -04:00
def cover_image_url(self) -> str | None:
return self.cover_url or (
self.program.cover_image_url if self.program else None
)
2023-04-19 22:31:27 -04:00
2024-05-27 15:44:12 -04:00
def get_url_with_position(self, position: int | str | None = None):
2023-01-31 21:21:50 -05:00
return (
2023-11-19 15:19:49 -05:00
self.url
2023-01-31 21:21:50 -05:00
if position is None or position == ""
2023-11-19 15:19:49 -05:00
else f"{self.url}?position={position}"
2023-01-31 21:21:50 -05:00
)
2024-02-03 22:19:01 -05:00
@classmethod
def lookup_id_type_choices(cls):
return []
2023-01-29 20:05:30 -05:00
class Meta:
index_together = [
[
"program",
"pub_date",
]
]
unique_together = [["program", "guid"]]