Files
PodTui/src/types/podcast.ts
Michael Freno 0b0637b9dc fix(search): surface iTunes stubs and resolve feeds for delisted shows
Shows that left Apple Podcasts (e.g. Daily Wire's in 2021) come back from
the iTunes Search API as metadata-only stub records with feedUrl null.
mapItunesResult dropped them, so The Ben Shapiro Show — the #1 hit for
'ben shapiro' — never appeared in search while sibling shows did.

- Keep feedUrl-less results (feedUrl "" + directoryUrl pointing at the
  Apple page) so delisted shows stay findable.
- Resolve the real feed from the Apple page at subscribe time
  (itunes-feed-resolver: anchor on the collection's adamId, forward-scan
  for the embedded feedUrl; Apple serves page variants where the
  showOffer block sits thousands of chars after the adamId).
- addFeed refuses feedless stubs whose feed can't be resolved instead of
  adding a broken feed; SearchPage surfaces the failure via toast.
- Tests: stub mapping, extractor variants, and an end-to-end subscribe
  over a local HTTP server.
2026-08-10 22:38:03 -04:00

47 lines
1.3 KiB
TypeScript

/**
* Podcast type definitions for PodTUI
*/
/** Core podcast information */
export interface Podcast {
/** Unique identifier */
id: string
/** Podcast title */
title: string
/** Podcast description/summary */
description: string
/** Cover image URL */
coverUrl?: string
/** RSS feed URL. Empty when the directory lists the show without a feed
* (e.g. shows delisted from Apple Podcasts); see directoryUrl. */
feedUrl: string
/** Directory listing page (e.g. Apple Podcasts) for shows whose feed URL
* the directory omits — used to resolve the real feed at subscribe time. */
directoryUrl?: string
/** Author/creator name */
author?: string
/** Podcast categories */
categories?: string[]
/** Language code (e.g., 'en', 'es') */
language?: string
/** Website URL */
websiteUrl?: string
/** Last updated timestamp */
lastUpdated: Date
/** Whether the podcast is currently subscribed */
isSubscribed: boolean
/** Callback to toggle feed visibility */
onToggleVisibility?: (feedId: string) => void
}
/** Podcast with episodes included */
export interface PodcastWithEpisodes extends Podcast {
/** List of episodes */
episodes: Episode[]
/** Total episode count */
totalEpisodes: number
}
/** Episode import - needed for PodcastWithEpisodes */
import type { Episode } from "./episode"