diff --git a/catalog/apis.py b/catalog/apis.py index 69286b14..a3ebb15f 100644 --- a/catalog/apis.py +++ b/catalog/apis.py @@ -25,6 +25,8 @@ from .models import ( PerformanceProductionSchema, PerformanceSchema, Podcast, + PodcastEpisode, + PodcastEpisodeSchema, PodcastSchema, TVEpisode, TVEpisodeSchema, @@ -35,6 +37,8 @@ from .models import ( ) from .search.models import enqueue_fetch, get_fetch_lock, query_index +PAGE_SIZE = 20 + class SearchResult(Schema): data: List[ @@ -46,11 +50,18 @@ class SearchResult(Schema): | PodcastSchema | GameSchema | PerformanceSchema + | PodcastEpisodeSchema ] pages: int count: int +class EpisodeList(Schema): + data: List[PodcastEpisodeSchema] + pages: int + count: int + + class SearchableItemCategory(Enum): Book = "book" Movie = "movie" @@ -221,6 +232,39 @@ def get_podcast(request, uuid: str, response: HttpResponse): return _get_item(Podcast, uuid, response) +@api.get( + "/podcast/episode/{uuid}", + response={200: PodcastEpisodeSchema, 302: RedirectedResult, 404: Result}, + auth=None, + tags=["catalog"], +) +def get_podcast_episode(request, uuid: str, response: HttpResponse): + return _get_item(PodcastEpisode, uuid, response) + + +@api.get( + "/podcast/{uuid}/episode/", + response={200: EpisodeList, 302: RedirectedResult, 404: Result}, + auth=None, + tags=["catalog"], +) +def get_episodes_in_podcast( + request, uuid: str, response: HttpResponse, page: int = 1, guid: str | None = None +): + podcast = _get_item(Podcast, uuid, response) + if not isinstance(podcast, Podcast): + return podcast + episodes = podcast.child_items.filter(is_deleted=False, merged_to_item=None) + if guid: + episodes = episodes.filter(guid=guid) + r = { + "data": list(episodes)[(page - 1) * PAGE_SIZE : page * PAGE_SIZE], + "pages": (episodes.count() + PAGE_SIZE - 1) // PAGE_SIZE, + "count": episodes.count(), + } + return r + + @api.get( "/album/{uuid}", response={200: AlbumSchema, 302: RedirectedResult, 404: Result}, diff --git a/catalog/models.py b/catalog/models.py index d482d05a..3f030b36 100644 --- a/catalog/models.py +++ b/catalog/models.py @@ -26,7 +26,13 @@ from .performance.models import ( PerformanceProductionSchema, PerformanceSchema, ) -from .podcast.models import Podcast, PodcastEpisode, PodcastInSchema, PodcastSchema +from .podcast.models import ( + Podcast, + PodcastEpisode, + PodcastEpisodeSchema, + PodcastInSchema, + PodcastSchema, +) from .tv.models import ( TVEpisode, TVEpisodeSchema, @@ -133,6 +139,7 @@ __all__ = [ "PerformanceSchema", "Podcast", "PodcastEpisode", + "PodcastEpisodeSchema", "PodcastInSchema", "PodcastSchema", "TVEpisode", diff --git a/catalog/podcast/models.py b/catalog/podcast/models.py index ed50a9ab..75ed55a6 100644 --- a/catalog/podcast/models.py +++ b/catalog/podcast/models.py @@ -1,3 +1,4 @@ +from datetime import datetime from typing import TYPE_CHECKING from django.db import models @@ -28,6 +29,18 @@ class PodcastSchema(PodcastInSchema, BaseSchema): pass +class PodcastEpisodeInSchema(ItemInSchema): + guid: str | None = None + pub_date: datetime | None = None + media_url: str | None = None + link: str | None = None + duration: int | None = None + + +class PodcastEpisodeSchema(PodcastEpisodeInSchema, BaseSchema): + pass + + class Podcast(Item): if TYPE_CHECKING: episodes: models.QuerySet["PodcastEpisode"] diff --git a/catalog/tv/models.py b/catalog/tv/models.py index e5f05a96..8dd1140d 100644 --- a/catalog/tv/models.py +++ b/catalog/tv/models.py @@ -61,6 +61,7 @@ class TVShowInSchema(ItemInSchema): year: int | None = None site: str | None = None episode_count: int | None = None + season_uuids: list[str] class TVShowSchema(TVShowInSchema, BaseSchema): @@ -244,6 +245,10 @@ class TVShow(Item): def child_items(self): return self.all_seasons + @property + def season_uuids(self): + return [x.uuid for x in self.all_seasons] + def get_season_count(self): return self.season_count or self.seasons.all().count()