Documentation
¶
Overview ¶
Package catalog implements core.Catalog: a SQLite mirror of a filtered TMDB slice plus on-demand fetches for anything else.
Index ¶
- Constants
- Variables
- func EstimateTitles(minPopularity float64, minVotes int) int
- func FoldSortTitle(s string) string
- func MeetsThreshold(cfg config.Catalog, t core.Title, now time.Time) bool
- func SortTitle(s string) string
- func WithReadWaitBudget(ctx context.Context, d time.Duration) context.Context
- type Catalog
- func (c *Catalog) ApplyProviderCertification(ctx context.Context, key core.RatingKey, label, provider string) error
- func (c *Catalog) BackfillHomeReleases(ctx context.Context, limit int) (int, error)
- func (c *Catalog) Browse(ctx context.Context, q core.BrowseQuery) (core.Page, error)
- func (c *Catalog) BrowseStoredEpisodes(ctx context.Context, q core.BrowseQuery) (core.Page, error)
- func (c *Catalog) BrowseStoredSeasons(ctx context.Context, q core.BrowseQuery) (core.Page, error)
- func (c *Catalog) ByExternalID(ctx context.Context, source, id string) (*core.Title, error)
- func (c *Catalog) ByExternalIDForType(ctx context.Context, source, id string, typ core.MediaType) (*core.Title, error)
- func (c *Catalog) CachedAddedTimes(ctx context.Context, keys []core.RatingKey) (map[core.RatingKey]time.Time, error)
- func (c *Catalog) CachedAiredEpisodes(ctx context.Context, show core.RatingKey, offset, limit int) (core.Page, error)
- func (c *Catalog) CachedCreditItems(ctx context.Context, after core.RatingKey, limit int) ([]core.RatingKey, error)
- func (c *Catalog) CachedCreditTitles(ctx context.Context, keys []core.RatingKey, cfg config.Catalog, now time.Time) (map[core.RatingKey]core.Title, error)
- func (c *Catalog) CachedDiscoveryEpisodes(ctx context.Context, shows []core.RatingKey) (map[core.RatingKey][]core.Title, error)
- func (c *Catalog) CachedGet(ctx context.Context, key core.RatingKey) (*core.Title, error)
- func (c *Catalog) CachedGetMany(ctx context.Context, keys []core.RatingKey) (map[core.RatingKey]core.Title, error)
- func (c *Catalog) CachedTitle(ctx context.Context, key core.RatingKey) (*core.Title, error)
- func (c *Catalog) CachedTitles(ctx context.Context, keys []core.RatingKey) ([]core.Title, error)
- func (c *Catalog) CaptureConfigEvidence(expected config.Catalog) (ConfigEvidence, bool)
- func (c *Catalog) Children(ctx context.Context, key core.RatingKey) ([]core.Title, error)
- func (c *Catalog) Collection(ctx context.Context, tmdbCollection int64) (string, []core.Title, error)
- func (c *Catalog) CountBrowsable(ctx context.Context, typ core.MediaType) (int, error)
- func (c *Catalog) CountStoredEpisodes(ctx context.Context, show core.Filter) (int, error)
- func (c *Catalog) CountStoredSeasons(ctx context.Context, show core.Filter) (int, error)
- func (c *Catalog) CountUnplayedAired(ctx context.Context, userID int64, keys []core.RatingKey, maxRating string) (map[core.RatingKey]int, error)
- func (c *Catalog) CrowdGraphBatch(ctx context.Context, keys []core.RatingKey, maxPerKey, maxTargets int) (map[core.RatingKey][]core.RatingKey, map[core.RatingKey]core.Title, error)
- func (c *Catalog) CrowdRecommendations(ctx context.Context, key core.RatingKey, pages int, fetch bool) (titles []core.Title, fetched bool, err error)
- func (c *Catalog) EpisodesUnranked(ctx context.Context) (bool, error)
- func (c *Catalog) Facet(ctx context.Context, t core.MediaType, facet string) ([]core.FacetValue, error)
- func (c *Catalog) FacetFilter(ctx context.Context, f core.Filter, facet string) ([]core.FacetValue, error)
- func (c *Catalog) FilterVisibility(ctx context.Context, ts []core.Title) []core.Title
- func (c *Catalog) Get(ctx context.Context, key core.RatingKey) (*core.Title, error)
- func (c *Catalog) Grandchildren(ctx context.Context, key core.RatingKey) ([]core.Title, error)
- func (c *Catalog) HomeReleases(ctx context.Context, keys []core.RatingKey) (map[core.RatingKey]time.Time, error)
- func (c *Catalog) LibraryPosters(ctx context.Context, typ core.MediaType, limit int) ([]core.Title, error)
- func (c *Catalog) List(ctx context.Context, list string, t core.MediaType, limit int) ([]core.Title, error)
- func (c *Catalog) MatchPeople(ctx context.Context, terms []string, limit int) ([]PersonMatch, error)
- func (c *Catalog) MatchesConfig(expected config.Catalog) bool
- func (c *Catalog) NextEpisode(ctx context.Context, episode core.RatingKey) (*core.Title, error)
- func (c *Catalog) NextStoredEpisode(ctx context.Context, episode core.RatingKey) (*core.Title, error)
- func (c *Catalog) PersonCreditKeys(ctx context.Context, person int64, types []core.MediaType, limit int) ([]core.RatingKey, error)
- func (c *Catalog) PopularScheduledMovies(ctx context.Context, from, until time.Time, limit int) ([]ScheduleEntry, error)
- func (c *Catalog) PreviewVisibility(ctx context.Context, specs []core.LibraryExclusion) (any, error)
- func (c *Catalog) PreviewVisibilityPolicy(ctx context.Context, specs []core.LibraryExclusion, fallback string) (any, error)
- func (c *Catalog) RecentAir(ctx context.Context, typ core.MediaType, offset, limit int) ([]core.Title, bool, error)
- func (c *Catalog) RecentAirExcluding(ctx context.Context, typ core.MediaType, exclude []core.RatingKey, ...) ([]core.Title, bool, error)
- func (c *Catalog) RecentEpisodes(ctx context.Context, show core.RatingKey, since time.Time) ([]core.Title, error)
- func (c *Catalog) RecentMovies(ctx context.Context, since time.Time) ([]core.Title, error)
- func (c *Catalog) RecentShows(ctx context.Context, since time.Time) ([]core.Title, error)
- func (c *Catalog) RefreshRatings(ctx context.Context, limit int) (int, error)
- func (c *Catalog) RefreshSchedule(ctx context.Context, show core.RatingKey) error
- func (c *Catalog) RefreshStoredTitle(ctx context.Context, key core.RatingKey) (*core.Title, error)
- func (c *Catalog) RefreshTitle(ctx context.Context, key core.RatingKey, persist bool) (*core.Title, error)
- func (c *Catalog) ReleaseMatches(ctx context.Context, releases []core.Release) (map[string][]core.Title, error)
- func (c *Catalog) ResolveShowParents(ctx context.Context, keys []core.RatingKey) (map[core.RatingKey]core.Title, error)
- func (c *Catalog) Run(ctx context.Context)
- func (c *Catalog) RunTrends(ctx context.Context)
- func (c *Catalog) ScheduledEpisodes(ctx context.Context, key core.RatingKey) ([]core.Title, error)
- func (c *Catalog) ScheduledMovies(ctx context.Context, keys []core.RatingKey, from, until time.Time) ([]ScheduleEntry, error)
- func (c *Catalog) ScheduledPremieres(ctx context.Context, shows []core.RatingKey, from, until time.Time) ([]ScheduleEntry, error)
- func (c *Catalog) ScheduledShows(ctx context.Context, shows []core.RatingKey, from, until time.Time, limit int) ([]ScheduleEntry, error)
- func (c *Catalog) Search(ctx context.Context, query string, types []core.MediaType, limit int) ([]core.Title, error)
- func (c *Catalog) SearchAll(ctx context.Context, query string, types []core.MediaType, limit int) ([]core.Title, error)
- func (c *Catalog) SearchPeople(ctx context.Context, terms []string, limit int) ([]core.Person, error)
- func (c *Catalog) SeasonEpisodePage(ctx context.Context, show core.RatingKey, season, offset, limit int) (core.Page, error)
- func (c *Catalog) SeedGenres(mediaType string, m map[int]string)
- func (c *Catalog) SetNow(now func() time.Time)
- func (c *Catalog) SetTMDB(client TMDB)
- func (c *Catalog) ShowTrajectories(ctx context.Context, shows []core.RatingKey) (map[core.RatingKey]core.ShowTrajectory, error)
- func (c *Catalog) Similar(ctx context.Context, key core.RatingKey, limit int) ([]core.Title, error)
- func (c *Catalog) StandaloneEpisodes(ctx context.Context, minRating float64, limit int) ([]core.Title, error)
- func (c *Catalog) Stats(ctx context.Context) (Stats, error)
- func (c *Catalog) StoredEpisodesByKey(ctx context.Context, show core.Filter, after core.RatingKey, limit int) ([]core.Title, error)
- func (c *Catalog) StoredGrandchildren(ctx context.Context, shows []core.RatingKey) (map[core.RatingKey][]core.Title, error)
- func (c *Catalog) StoredSeasonsByKey(ctx context.Context, show core.Filter, after core.RatingKey, limit int) ([]core.Title, error)
- func (c *Catalog) StoredTitle(ctx context.Context, key core.RatingKey) (*core.Title, error)
- func (c *Catalog) Sync(ctx context.Context) error
- func (c *Catalog) SyncProgress() SyncProgress
- func (c *Catalog) TrendStatus(ctx context.Context) []TrendStatus
- func (c *Catalog) UnratedTitles(ctx context.Context, after core.RatingKey, limit int) ([]core.Title, error)
- func (c *Catalog) UpdateConfig(cfg config.Catalog)
- func (c *Catalog) UpsertDetailedTitle(ctx context.Context, t core.Title) error
- func (c *Catalog) UpsertTitle(ctx context.Context, t core.Title, browsable bool) error
- func (c *Catalog) Visible(t *core.Title) bool
- func (c *Catalog) WaitRefreshes()
- func (c *Catalog) WarmDetails(ctx context.Context, limit int) (int, error)
- func (c *Catalog) WriteGeneration() uint64
- type ConfigEvidence
- type Estimate
- type Mirror
- func (m *Mirror) AirDates(ctx context.Context, now time.Time, premiere bool) (map[core.RatingKey]int64, error)
- func (m *Mirror) CollectionArt(ctx context.Context, id int64) (core.Collection, error)
- func (m *Mirror) Fingerprint(ctx context.Context) (MirrorFingerprint, error)
- func (m *Mirror) Franchises(ctx context.Context) ([]core.Collection, error)
- func (m *Mirror) Snapshot(ctx context.Context) ([]MirrorItem, error)
- func (m *Mirror) Titles(ctx context.Context, keys []core.RatingKey) ([]core.Title, error)
- func (m *Mirror) TitlesIncludingFuture(ctx context.Context, keys []core.RatingKey) ([]core.Title, error)
- type MirrorFingerprint
- type MirrorItem
- type MovieYearProgress
- type Option
- type PersonMatch
- type SaferRatingSQL
- type ScheduleEntry
- type Stats
- type SyncProgress
- type TMDB
- type TrendStatus
- type VisibilityPreview
- type VisibilityRulePreview
Constants ¶
const DefaultCrowdTTL = 72 * time.Hour
DefaultCrowdTTL is how long a stored co-engagement list is fresh.
Variables ¶
var ErrSyncInProgress = fmt.Errorf("catalog: sync already in progress")
Sync (re)builds the browsable set from TMDB discover. A second call while one is running returns ErrSyncInProgress; use SyncProgress to poll.
Functions ¶
func EstimateTitles ¶
EstimateTitles is a convenience wrapper returning only the total.
func FoldSortTitle ¶ added in v0.3.0
FoldSortTitle normalizes an explicit sort title to lowercase with Latin diacritics and ligatures folded to their base ASCII letters.
func MeetsThreshold ¶
MeetsThreshold reports whether a title qualifies for the browsable set under cfg: popularity >= MinPopularity OR votes >= MinVotes, and released.
func SortTitle ¶ added in v0.3.0
SortTitle returns the normalized lowercase sort key for a display title: strips invisible format characters, removes a leading English article ("the ", "a ", "an "), and folds Latin accents/diacritics and ligatures to their base ASCII letters so titleSort and firstCharacter share one collation.
func WithReadWaitBudget ¶ added in v0.3.0
WithReadWaitBudget bounds the total time reads under ctx wait on TMDB, across every title they touch. A page that lists thirty titles with no details yet waits at most d in all, not 2 s for each; the rest are served as stored and refreshed in the background.
Types ¶
type Catalog ¶
type Catalog struct {
// contains filtered or unexported fields
}
Catalog implements core.Catalog.
func New ¶
func New(db *sql.DB, client TMDB, cfg config.Catalog, log *slog.Logger, opts ...Option) (*Catalog, error)
New creates a catalogue. client may be nil (mirror-only / offline mode).
func (*Catalog) ApplyProviderCertification ¶ added in v0.3.0
func (c *Catalog) ApplyProviderCertification(ctx context.Context, key core.RatingKey, label, provider string) error
ApplyProviderCertification records a certification an owner-configured rating provider (OMDb, MDBList) reports for a movie or show: IMDb's US certificate. It fills titles TMDB rates only abroad, "not rated" or not at all, and never replaces TMDB's rating for the region or the US.
func (*Catalog) BackfillHomeReleases ¶ added in v0.2.34
BackfillHomeReleases fetches at most limit details, never from a browse. Missing and future dates are revisited daily; failures also cool down for a day so an unavailable title cannot starve the remaining catalogue. Recently reached dates are rechecked daily; settled dates are revisited after 90 days to pick up later corrections.
func (*Catalog) Browse ¶
Browse queries the browsable mirror entirely in SQL, with generation-stamped in-memory count and page caching so repeated library/recommendation reads return without hitting disk.
func (*Catalog) BrowseStoredEpisodes ¶ added in v0.3.0
BrowseStoredEpisodes pages stored, aired episodes in the library without refreshing shows or seasons from TMDB. Sequential key-ordered pages advance via a cached key cursor so deep offsets stay O(limit).
func (*Catalog) BrowseStoredSeasons ¶ added in v0.3.0
BrowseStoredSeasons pages stored, listable seasons in the library without refreshing shows or seasons from TMDB.
func (*Catalog) ByExternalID ¶
ByExternalID looks up by imdb ("tt123") or tvdb id.
func (*Catalog) ByExternalIDForType ¶ added in v0.2.53
func (c *Catalog) ByExternalIDForType(ctx context.Context, source, id string, typ core.MediaType) (*core.Title, error)
ByExternalIDForType looks up an external ID restricted to typ ("movie", "show", or "episode"), avoiding cross-type integer ID collisions on TVDB and allowing stored non-adult titles even when gated on browse shelves.
func (*Catalog) CachedAddedTimes ¶ added in v0.3.0
func (c *Catalog) CachedAddedTimes(ctx context.Context, keys []core.RatingKey) (map[core.RatingKey]time.Time, error)
CachedAddedTimes reads date added without fetching or resolving metadata. Missing, unknown and future dates are omitted. A later aired episode replaces a series or season premiere; an unaired episode does not.
func (*Catalog) CachedAiredEpisodes ¶ added in v0.3.0
func (c *Catalog) CachedAiredEpisodes(ctx context.Context, show core.RatingKey, offset, limit int) (core.Page, error)
CachedAiredEpisodes returns locally stored, aired, non-adult episodes in descending air-date order. A zero show key selects all shows. It performs no network access or viewer filtering; callers must enforce viewer policy before applying their final limit.
func (*Catalog) CachedCreditItems ¶ added in v0.3.0
func (c *Catalog) CachedCreditItems(ctx context.Context, after core.RatingKey, limit int) ([]core.RatingKey, error)
CachedCreditItems pages existing cached credit membership, including titles opened on demand. It never fetches metadata or hydrates filmographies. Viewer and inherited-title policy belongs to the consuming Experience.
func (*Catalog) CachedCreditTitles ¶ added in v0.3.0
func (c *Catalog) CachedCreditTitles(ctx context.Context, keys []core.RatingKey, cfg config.Catalog, now time.Time) (map[core.RatingKey]core.Title, error)
CachedCreditTitles is a read-only People snapshot. Existing cached-read gates may conservatively omit a title; every returned title is additionally checked against the caller's immutable config and time, including inherited parents. The caller must hold the config lease and fence durable changes separately.
func (*Catalog) CachedDiscoveryEpisodes ¶ added in v0.2.9
func (c *Catalog) CachedDiscoveryEpisodes(ctx context.Context, shows []core.RatingKey) (map[core.RatingKey][]core.Title, error)
CachedDiscoveryEpisodes returns regular episode metadata without hydration or remote lookups. Unknown/future dates are retained so callers can distinguish an unmirrored premiere from a known but unreleased episode.
func (*Catalog) CachedGet ¶ added in v0.3.0
CachedGet applies the same catalogue visibility gates as Get without a network refresh. Missing or hidden records fail closed; callers may use the normal catalogue path separately to populate the local mirror.
func (*Catalog) CachedGetMany ¶ added in v0.3.0
func (*Catalog) CachedTitle ¶
CachedTitle returns a mirrored title without contacting TMDB.
func (*Catalog) CachedTitles ¶ added in v0.2.6
CachedTitles returns released, non-adult mirrored titles in requested order, without refreshing remote metadata. Batch consumers such as recommendation builders use this to avoid one full hydration round trip per history entry.
func (*Catalog) CaptureConfigEvidence ¶ added in v0.3.0
func (c *Catalog) CaptureConfigEvidence(expected config.Catalog) (ConfigEvidence, bool)
CaptureConfigEvidence compares while holding cfgMu. The caller must own or synchronize expected for the duration of the call.
func (*Catalog) Collection ¶
func (c *Catalog) Collection(ctx context.Context, tmdbCollection int64) (string, []core.Title, error)
Collection returns a TMDB franchise and its parts sorted by release date.
func (*Catalog) CountBrowsable ¶ added in v0.3.0
CountBrowsable is the library size behind a view list. The (type, browsable, adult) prefix of catalog_titles_type_browse_sort answers it without reading title rows.
func (*Catalog) CountStoredEpisodes ¶ added in v0.3.0
CountStoredEpisodes counts StoredEpisodesByKey's whole set. Like a browse total, a large count is served from the last one while it recounts.
func (*Catalog) CountStoredSeasons ¶ added in v0.3.0
CountStoredSeasons counts the stored, listable seasons in the library for the browse filter show.
func (*Catalog) CountUnplayedAired ¶ added in v0.3.0
func (c *Catalog) CountUnplayedAired(ctx context.Context, userID int64, keys []core.RatingKey, maxRating string) (map[core.RatingKey]int, error)
CountUnplayedAired counts aired episodes a viewer has not played, for each show or season key. It uses the aired index and the watch primary key. It does not load episode rows or refresh metadata. An empty max rating counts every aired episode. A set rating drops unrated and stricter ones.
func (*Catalog) CrowdGraphBatch ¶ added in v0.2.7
func (c *Catalog) CrowdGraphBatch(ctx context.Context, keys []core.RatingKey, maxPerKey, maxTargets int) (map[core.RatingKey][]core.RatingKey, map[core.RatingKey]core.Title, error)
CrowdGraphBatch reads stored co-engagement lists from catalog_crowd for a batch of keys without contacting TMDB, and resolves up to maxTargets of the referenced titles from the local mirror. Used for 2-hop crowd expansion.
func (*Catalog) CrowdRecommendations ¶
func (c *Catalog) CrowdRecommendations(ctx context.Context, key core.RatingKey, pages int, fetch bool) (titles []core.Title, fetched bool, err error)
CrowdRecommendations returns TMDB's crowd co-engagement list for a title (/recommendations only: never metadata similarity), best first, from up to pages pages (1–2). A stored list younger than the crowd TTL with enough pages is served from the local mirror. Otherwise, with fetch set, TMDB is asked and fetched reports it (callers budget those calls); without fetch, or when TMDB fails, a stale list is served when there is one and nil otherwise. Titles not yet released are dropped.
func (*Catalog) EpisodesUnranked ¶ added in v0.3.0
EpisodesUnranked reports that no stored episode has a popularity, so a popularity order of episodes is their key order. TMDB gives episodes no popularity; this checks the index's two ends rather than assuming it.
func (*Catalog) Facet ¶
func (c *Catalog) Facet(ctx context.Context, t core.MediaType, facet string) ([]core.FacetValue, error)
Facet returns value counts over the browsable set.
func (*Catalog) FacetFilter ¶ added in v0.3.0
func (c *Catalog) FacetFilter(ctx context.Context, f core.Filter, facet string) ([]core.FacetValue, error)
FacetFilter returns value counts over the browsable set matching f.
func (*Catalog) FilterVisibility ¶ added in v0.2.12
FilterVisibility enriches remote summaries with already-known local facets; there are no detail fetches or indexer calls. Unknown metadata stays unknown.
func (*Catalog) Grandchildren ¶
Grandchildren: all episodes of a show.
func (*Catalog) HomeReleases ¶ added in v0.3.0
func (c *Catalog) HomeReleases(ctx context.Context, keys []core.RatingKey) (map[core.RatingKey]time.Time, error)
HomeReleases returns digital or physical dates that have been recorded. A missing key has not been checked. A zero time means the movie was checked and has no digital or physical date (theatrical only).
func (*Catalog) LibraryPosters ¶ added in v0.3.0
func (c *Catalog) LibraryPosters(ctx context.Context, typ core.MediaType, limit int) ([]core.Title, error)
LibraryPosters returns the first poster paths for a library collage. It reads the popularity index and does not hydrate title rows.
func (*Catalog) List ¶
func (c *Catalog) List(ctx context.Context, list string, t core.MediaType, limit int) ([]core.Title, error)
List returns TMDB curated/trending lists with a short in-memory TTL.
func (*Catalog) MatchPeople ¶ added in v0.3.0
func (c *Catalog) MatchPeople(ctx context.Context, terms []string, limit int) ([]PersonMatch, error)
MatchPeople returns up to limit credited people, most credited first, whose name has a word starting with each of terms (lower-case words, as split by the caller). The match is a candidate set: on PostgreSQL it is a substring match, so callers recheck names with their own word rules.
func (*Catalog) MatchesConfig ¶ added in v0.3.0
MatchesConfig reports whether the catalog actually installed the config captured by a held config-policy lease. UpdateConfig can reject invalid visibility rules and retain the previous config; checking the Store alone therefore does not prove the catalog read used that snapshot. This method is a prework check, not an authorization or a durable epoch fence.
func (*Catalog) NextEpisode ¶
NextEpisode returns the next regular episode (specials, season 0, are skipped as a target; calling it on a special jumps to S1E1-order sequence).
func (*Catalog) NextStoredEpisode ¶ added in v0.3.0
func (c *Catalog) NextStoredEpisode(ctx context.Context, episode core.RatingKey) (*core.Title, error)
NextStoredEpisode is the next regular episode already in the catalogue. It does not refresh the show or season from a provider. Home, library rows, and model builds use it so one stale show cannot stall the request. A special still jumps to the first regular episode, matching NextEpisode.
func (*Catalog) PersonCreditKeys ¶ added in v0.3.0
func (c *Catalog) PersonCreditKeys(ctx context.Context, person int64, types []core.MediaType, limit int) ([]core.RatingKey, error)
PersonCreditKeys returns up to limit titles of types that credit person, most popular first. Like the credit walk it replaces, it includes titles opened on demand (not browsable); callers apply the viewer's visibility.
func (*Catalog) PopularScheduledMovies ¶ added in v0.3.0
func (c *Catalog) PopularScheduledMovies(ctx context.Context, from, until time.Time, limit int) ([]ScheduleEntry, error)
PopularScheduledMovies returns the most popular mirrored movies released in [from, until), most popular first.
func (*Catalog) PreviewVisibility ¶ added in v0.2.12
func (*Catalog) PreviewVisibilityPolicy ¶ added in v0.3.0
func (*Catalog) RecentAir ¶ added in v0.3.0
func (c *Catalog) RecentAir(ctx context.Context, typ core.MediaType, offset, limit int) ([]core.Title, bool, error)
RecentAir returns browsable titles ordered by date added: a movie's release, or a show's latest episode already aired. It reads the released and aired indexes and stops after a bounded window. It does not refresh metadata. offset skips that many titles in the same order. A show with no aired episode is omitted. done is true when this window reached the end.
func (*Catalog) RecentAirExcluding ¶ added in v0.3.0
func (c *Catalog) RecentAirExcluding(ctx context.Context, typ core.MediaType, exclude []core.RatingKey, offset, limit int) ([]core.Title, bool, error)
RecentAirExcluding is RecentAir without the titles in exclude: the evidence window's hidden titles, which a viewer never sees, so a page of them does not use up the bounded window.
func (*Catalog) RecentEpisodes ¶
func (c *Catalog) RecentEpisodes(ctx context.Context, show core.RatingKey, since time.Time) ([]core.Title, error)
RecentEpisodes returns only local, released episode identities for artwork badges. Callers apply viewer state through core.State instead of a SQL join.
func (*Catalog) RecentMovies ¶ added in v0.2.9
RecentMovies reads the release-date index, without refreshing any title.
func (*Catalog) RecentShows ¶ added in v0.2.9
RecentShows only reads the local premiere-date index.
func (*Catalog) RefreshRatings ¶ added in v0.3.0
RefreshRatings re-selects the stored rating of up to limit detailed movies and shows from TMDB, walking the catalogue by key until the current rating model has covered every title. It is a no-op once done. It returns how many titles it checked.
func (*Catalog) RefreshSchedule ¶ added in v0.3.0
RefreshSchedule mirrors a followed show's current and announced seasons, so the calendar can list their episodes without contacting TMDB on its request path. Fresh shows and seasons cost no request (Get's TTLs apply: an hour for a returning series' newest season); a settled show is left alone.
func (*Catalog) RefreshStoredTitle ¶ added in v0.3.0
RefreshStoredTitle drops the minute cache and reads the stored row again. Portrait bytes use it when a credit changed inside the current cache minute.
func (*Catalog) RefreshTitle ¶ added in v0.2.37
func (c *Catalog) RefreshTitle(ctx context.Context, key core.RatingKey, persist bool) (*core.Title, error)
RefreshTitle updates canonical details from TMDB without a stale fallback.
func (*Catalog) ReleaseMatches ¶ added in v0.2.8
func (c *Catalog) ReleaseMatches(ctx context.Context, releases []core.Release) (map[string][]core.Title, error)
ReleaseMatches joins a feed page to local metadata in one narrow scan. It never spends a metadata API call per feed item. Ambiguous names are ignored; explicit identifier conflicts always defeat a textual match. Season packs are expanded only to locally known episodes, never to invented episode identities.
func (*Catalog) ResolveShowParents ¶ added in v0.3.0
func (c *Catalog) ResolveShowParents(ctx context.Context, keys []core.RatingKey) (map[core.RatingKey]core.Title, error)
ResolveShowParents batches fresh mirrored shows and falls back to Get for stale, missing, or non-show keys. Individual Get failures are omitted, as inherited visibility treats them as inaccessible.
func (*Catalog) Run ¶
Run performs an initial sync and then refreshes on RefreshInterval until ctx ends. Intended to be run in its own goroutine by the app wiring. With WithResumeSchedule the initial sync waits until the interval has passed since the last recorded sync.
func (*Catalog) RunTrends ¶ added in v0.2.12
RunTrends has an independent schedule: a slow catalogue crawl cannot delay charts. App lifetime owns and joins it, and only the cluster leader polls.
func (*Catalog) ScheduledEpisodes ¶ added in v0.2.45
ScheduledEpisodes is deliberately separate from Children/Get: discovery, autoplay, downloads and playback must never acquire future episodes through it.
func (*Catalog) ScheduledMovies ¶ added in v0.3.0
func (c *Catalog) ScheduledMovies(ctx context.Context, keys []core.RatingKey, from, until time.Time) ([]ScheduleEntry, error)
ScheduledMovies returns the given movies released in [from, until).
func (*Catalog) ScheduledPremieres ¶ added in v0.3.0
func (c *Catalog) ScheduledPremieres(ctx context.Context, shows []core.RatingKey, from, until time.Time) ([]ScheduleEntry, error)
ScheduledPremieres returns announced seasons of shows premiering in [from, until) whose episodes are not mirrored yet, so a calendar can still mark the premiere.
func (*Catalog) ScheduledShows ¶ added in v0.3.0
func (c *Catalog) ScheduledShows(ctx context.Context, shows []core.RatingKey, from, until time.Time, limit int) ([]ScheduleEntry, error)
ScheduledShows returns the dated episodes of shows released in [from, until), including future ones, and each episode's season size. Episodes inherit their show's content rating so callers can apply viewer policy. It never contacts TMDB: only mirrored seasons are listed (see RefreshSchedule).
func (*Catalog) Search ¶
func (c *Catalog) Search(ctx context.Context, query string, types []core.MediaType, limit int) ([]core.Title, error)
Search reaches all of TMDB; matched titles join the browsable set.
func (*Catalog) SearchAll ¶ added in v0.2.53
func (c *Catalog) SearchAll(ctx context.Context, query string, types []core.MediaType, limit int) ([]core.Title, error)
SearchAll searches local and remote titles without applying browse-shelf visibility or home-release gating (used when importing external watch state).
func (*Catalog) SearchPeople ¶ added in v0.3.0
func (c *Catalog) SearchPeople(ctx context.Context, terms []string, limit int) ([]core.Person, error)
SearchPeople returns up to limit credited people matching terms, most credited first.
func (*Catalog) SeasonEpisodePage ¶ added in v0.3.0
func (c *Catalog) SeasonEpisodePage(ctx context.Context, show core.RatingKey, season, offset, limit int) (core.Page, error)
SeasonEpisodePage returns one window of a single catalogue season. The count and the page both use catalog_titles_show (show_key, season, episode), so a season of thousands of episodes does not load the rest of the show. limit is 1..1000. An empty first page fetches that season once; later pages do not.
func (*Catalog) SeedGenres ¶
SeedGenres pre-populates the genre id->name cache (tests, offline warm-up).
func (*Catalog) SetNow ¶ added in v0.3.0
SetNow replaces the clock used for release checks and the minute snapshot. The swap is atomic so a background browse can keep reading it.
func (*Catalog) SetTMDB ¶ added in v0.3.0
SetTMDB replaces the remote metadata client. Nil answers from the local catalogue only.
func (*Catalog) ShowTrajectories ¶ added in v0.2.7
func (c *Catalog) ShowTrajectories(ctx context.Context, shows []core.RatingKey) (map[core.RatingKey]core.ShowTrajectory, error)
ShowTrajectories computes season/episode rating trajectories for a batch of shows from local mirror data without contacting TMDB.
func (*Catalog) StandaloneEpisodes ¶ added in v0.2.7
func (c *Catalog) StandaloneEpisodes(ctx context.Context, minRating float64, limit int) ([]core.Title, error)
StandaloneEpisodes returns acclaimed mirrored episodes from anthology series or top-rated standalone chapters that can be watched without a multi-season commitment.
func (*Catalog) StoredEpisodesByKey ¶ added in v0.3.0
func (c *Catalog) StoredEpisodesByKey(ctx context.Context, show core.Filter, after core.RatingKey, limit int) ([]core.Title, error)
StoredEpisodesByKey returns up to limit stored, aired, non-adult episodes after the key after, in key order (series, season, episode), of the series the browse filter show admits. It reads the key range and probes each episode's series, so a page costs the same however large the library; it refreshes nothing.
func (*Catalog) StoredGrandchildren ¶ added in v0.3.0
func (c *Catalog) StoredGrandchildren(ctx context.Context, shows []core.RatingKey) (map[core.RatingKey][]core.Title, error)
StoredGrandchildren returns, for each of shows it can answer from the mirror, exactly what Grandchildren would: the episodes of the show's listable seasons, in season and episode order. It answers a show only when Grandchildren would not wait on TMDB: the show has its details and every listable season is detailed with episodes stored. A stale season that Grandchildren would refresh behind the read is refreshed behind this read too. Shows it omits must go through Grandchildren. A list page counting many shows' episodes reads them in a few batched statements instead of a dozen per show.
func (*Catalog) StoredSeasonsByKey ¶ added in v0.3.0
func (c *Catalog) StoredSeasonsByKey(ctx context.Context, show core.Filter, after core.RatingKey, limit int) ([]core.Title, error)
StoredSeasonsByKey returns up to limit stored, listable seasons after the key after, in key order (series, season), of the series the browse filter show admits. It never refreshes shows or seasons from TMDB.
func (*Catalog) StoredTitle ¶ added in v0.2.37
func (*Catalog) SyncProgress ¶
func (c *Catalog) SyncProgress() SyncProgress
SyncProgress returns the current sync progress snapshot.
func (*Catalog) TrendStatus ¶ added in v0.2.12
func (c *Catalog) TrendStatus(ctx context.Context) []TrendStatus
func (*Catalog) UnratedTitles ¶ added in v0.3.0
func (c *Catalog) UnratedTitles(ctx context.Context, after core.RatingKey, limit int) ([]core.Title, error)
UnratedTitles lists browsable, detailed movies and shows without a rated certification, by key after the given one, for a rating provider to look up. Titles carry only their key, type and ids.
func (*Catalog) UpdateConfig ¶
UpdateConfig swaps the catalogue config (wire to config.Store.Subscribe).
func (*Catalog) UpsertDetailedTitle ¶ added in v0.3.0
UpsertDetailedTitle stores a title as a fresh detail record. A later Get serves the row without a metadata refresh until it is stale. The scorecard fixture uses this: its seed is the source of truth, and a failed refresh must not be repeated for every library row.
func (*Catalog) UpsertTitle ¶
UpsertTitle stores a title (exported for tests/seeders and other components that need to insert known titles). Browsable/added_at are preserved once set. The row is not a fresh detail record, so a later Get may refresh it.
func (*Catalog) WaitRefreshes ¶ added in v0.3.0
func (c *Catalog) WaitRefreshes()
WaitRefreshes blocks until no metadata refresh started by a read is still running.
func (*Catalog) WarmDetails ¶ added in v0.2.7
WarmDetails enriches up to limit browsable titles whose detailed metadata (credits, crew, keywords, studios, runtime, content rating, seasons and crowd recommendations) has not been fetched yet, plus returning series whose detail TTL has expired. New releases (<120 days old) are warmed first, followed by the most popular and most-voted titles. Settled titles are marked detail=1 and never re-queried.
func (*Catalog) WriteGeneration ¶ added in v0.3.0
WriteGeneration changes when a catalogue write drops the read caches.
type ConfigEvidence ¶ added in v0.3.0
type ConfigEvidence struct {
// contains filtered or unexported fields
}
ConfigEvidence is an opaque, non-authorizing observation of the exact installed config incarnation. It detects change-and-revert as well as a currently different value. It is valid only for the issuing Catalog.
func (ConfigEvidence) Current ¶ added in v0.3.0
func (e ConfigEvidence) Current() bool
Current is a postwork check; it must not be treated as a durable policy fence or used instead of checking the policy epoch transaction.
type Estimate ¶
type Estimate struct {
Movies int `json:"movies"`
Shows int `json:"shows"`
Total int `json:"total"`
}
Estimate is a rough catalogue-size prediction for given thresholds. It is a heuristic from TMDB's documented popularity behaviour (a daily- recomputed, heavily right-skewed score) and public catalogue counts. Treat it as order-of-magnitude guidance for the setup UI, not a measurement.
func EstimateCatalogSize ¶
EstimateCatalogSize estimates browsable titles with MeetsThreshold's OR rule. The union of the popularity set and vote set overlaps substantially; the estimate uses max + 40% of the smaller set as the non-overlapping remainder.
type Mirror ¶
type Mirror struct {
// contains filtered or unexported fields
}
Mirror exposes bounded local reads for catalogue consumers. It owns schema knowledge; callers never compose SQL against catalog_* tables.
func (*Mirror) AirDates ¶ added in v0.2.34
func (m *Mirror) AirDates(ctx context.Context, now time.Time, premiere bool) (map[core.RatingKey]int64, error)
AirDates returns dates from locally mirrored regular episodes, excluding future air dates. For premieres, the highest numbered season with an aired episode must have an aired episode one.
func (*Mirror) CollectionArt ¶
func (*Mirror) Fingerprint ¶
func (m *Mirror) Fingerprint(ctx context.Context) (MirrorFingerprint, error)
func (*Mirror) Franchises ¶
type MirrorFingerprint ¶
type MovieYearProgress ¶ added in v0.3.0
type MovieYearProgress struct {
Running bool `json:"running"`
Finished bool `json:"finished"`
Pending int `json:"pending"`
Stored int `json:"stored"`
Refreshed int `json:"refreshed"`
LastError string `json:"lastError,omitempty"`
}
MovieYearProgress is the upgrade correction shown on Catalog health. Stored counts movies whose year was taken from a date already in the catalogue. Refreshed counts movies whose detail was fetched because that date was not stored. Pending is how many movies are still unmarked.
type Option ¶
type Option func(*Catalog)
Option customises a Catalog.
func WithCrowdTTL ¶
WithCrowdTTL overrides how long co-engagement lists stay fresh.
func WithListTTL ¶
func WithResumeSchedule ¶
func WithResumeSchedule() Option
WithResumeSchedule makes Run continue the refresh schedule recorded in the database instead of syncing as soon as it starts: the first sync waits until RefreshInterval has passed since the last successful sync (by any node). A cluster uses it because Run restarts on every leader handoff; with no recorded sync Run still syncs at once.
func WithSaferRatingSQL ¶ added in v0.3.0
func WithSaferRatingSQL(f SaferRatingSQL) Option
func WithStaleAfter ¶
func WithSyncYears ¶
WithSyncYears bounds the year slices used when discover exceeds 500 pages.
type PersonMatch ¶ added in v0.3.0
PersonMatch is a credited person a people search may return.
type SaferRatingSQL ¶ added in v0.3.0
SaferRatingSQL is the optional Plex overlay predicate for viewer limits.
type ScheduleEntry ¶ added in v0.3.0
type ScheduleEntry struct {
Title core.Title
// SeasonEpisodes is the highest mirrored episode number of an
// episode's season (TMDB lists a season's future episodes too), so
// callers can mark a season finale.
SeasonEpisodes int
// ShowPoster is an episode's or season's series poster path.
ShowPoster string
Playable bool
}
ScheduleEntry is one dated title in the owner's release calendar, read from the local mirror only. Playable reports whether the catalogue would offer it right now (released, not adult, past the home-release gate).
type Stats ¶
type Stats struct {
Trending []TrendStatus `json:"trending"`
Movies int `json:"movies"`
Shows int `json:"shows"`
Seasons int `json:"seasons"`
Episodes int `json:"episodes"`
HomeReleaseChecked int `json:"homeReleaseChecked"`
HomeReleasePending int `json:"homeReleasePending"`
BrowsableMovies int `json:"browsableMovies"`
BrowsableShows int `json:"browsableShows"`
Collections int `json:"collections"`
LastSync time.Time `json:"lastSync,omitempty"`
Sync SyncProgress `json:"sync"`
YearCorrection MovieYearProgress `json:"yearCorrection"`
}
Stats is the admin-UI snapshot of the mirror.
type SyncProgress ¶
type SyncProgress struct {
Running bool `json:"running"`
Phase string `json:"phase,omitempty"` // e.g. "movie/popularity", "tv/votes/1994"
PagesDone int `json:"pagesDone"`
TitlesSeen int `json:"titlesSeen"`
TitlesAdded int `json:"titlesAdded"`
StartedAt time.Time `json:"startedAt,omitempty"`
FinishedAt time.Time `json:"finishedAt,omitempty"`
LastError string `json:"lastError,omitempty"`
}
SyncProgress describes a running or last-finished catalogue sync.
type TMDB ¶
type TMDB interface {
MovieDetails(ctx context.Context, id int64) (*tmdb.MovieDetails, error)
TVDetails(ctx context.Context, id int64) (*tmdb.TVDetails, error)
SeasonDetails(ctx context.Context, tvID int64, season int) (*tmdb.SeasonDetails, error)
EpisodeExternalIDs(ctx context.Context, tvID int64, season, episode int) (*tmdb.ExternalIDs, error)
CollectionDetails(ctx context.Context, id int64) (*tmdb.CollectionDetails, error)
DiscoverMovies(ctx context.Context, p tmdb.DiscoverParams) (*tmdb.Paged[tmdb.Movie], error)
DiscoverTV(ctx context.Context, p tmdb.DiscoverParams) (*tmdb.Paged[tmdb.TVShow], error)
SearchMovies(ctx context.Context, q string, page int) (*tmdb.Paged[tmdb.Movie], error)
SearchTV(ctx context.Context, q string, page int) (*tmdb.Paged[tmdb.TVShow], error)
SearchMulti(ctx context.Context, q string, page int) (*tmdb.Paged[tmdb.MultiResult], error)
TrendingMovies(ctx context.Context, window string, page int) (*tmdb.Paged[tmdb.Movie], error)
TrendingTV(ctx context.Context, window string, page int) (*tmdb.Paged[tmdb.TVShow], error)
TrendingAll(ctx context.Context, window string, page int) (*tmdb.Paged[tmdb.MultiResult], error)
MovieList(ctx context.Context, list string, page int) (*tmdb.Paged[tmdb.Movie], error)
TVList(ctx context.Context, list string, page int) (*tmdb.Paged[tmdb.TVShow], error)
MovieSimilar(ctx context.Context, id int64, page int) (*tmdb.Paged[tmdb.Movie], error)
MovieRecommendations(ctx context.Context, id int64, page int) (*tmdb.Paged[tmdb.Movie], error)
TVSimilar(ctx context.Context, id int64, page int) (*tmdb.Paged[tmdb.TVShow], error)
TVRecommendations(ctx context.Context, id int64, page int) (*tmdb.Paged[tmdb.TVShow], error)
FindByExternalID(ctx context.Context, source, id string) (*tmdb.FindResult, error)
Genres(ctx context.Context, mediaType string) ([]tmdb.Genre, error)
}
TMDB is the subset of the TMDB client the catalogue needs. *tmdb.Client satisfies it.
type TrendStatus ¶ added in v0.2.12
type TrendStatus struct {
Source string `json:"source"`
Scope string `json:"scope"`
Window string `json:"window"`
MediaType core.MediaType `json:"mediaType"`
Titles int `json:"titles"`
FetchedAt *time.Time `json:"fetchedAt,omitempty"`
AttemptedAt *time.Time `json:"attemptedAt,omitempty"`
State string `json:"state"`
}
type VisibilityPreview ¶ added in v0.2.12
type VisibilityPreview struct {
Total int `json:"total"`
Hidden int `json:"hidden"`
Visible int `json:"visible"`
Movies int `json:"movies"`
Shows int `json:"shows"`
UnknownCountry int `json:"unknownCountry"`
Items []core.Title `json:"items"`
Shown []core.Title `json:"shown"`
Rules []VisibilityRulePreview `json:"rules"`
}
type VisibilityRulePreview ¶ added in v0.3.0
Source Files
¶
- air_dates.go
- aired.go
- browse.go
- browse_added.go
- cached.go
- cached_added_times.go
- cached_aired_episodes.go
- calendar.go
- capabilities.go
- capability_assertions.go
- catalog.go
- config_snapshot.go
- convert.go
- crowd.go
- estimate.go
- get.go
- home_release.go
- hydrate.go
- list_grandchildren.go
- lists.go
- mirror.go
- mirror_titles.go
- people_cached.go
- rating.go
- recent_air.go
- release_known.go
- release_matches.go
- scheduled.go
- search_index.go
- search_walk.go
- show_episode_counts.go
- store.go
- stored_episodes.go
- sync.go
- trends.go
- unplayed_count.go
- visibility.go
- year_correct.go