Help us shape the future of Go! Take the 2026 Go Developer Survey

catalog

package
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 1, 2026 License: GPL-3.0 Imports: 28 Imported by: 0

Documentation

Overview

Package catalog implements core.Catalog: a SQLite mirror of a filtered TMDB slice plus on-demand fetches for anything else.

Index

Constants

View Source
const DefaultCrowdTTL = 72 * time.Hour

DefaultCrowdTTL is how long a stored co-engagement list is fresh.

Variables

View Source
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

func EstimateTitles(minPopularity float64, minVotes int) int

EstimateTitles is a convenience wrapper returning only the total.

func FoldSortTitle added in v0.3.0

func FoldSortTitle(s string) string

FoldSortTitle normalizes an explicit sort title to lowercase with Latin diacritics and ligatures folded to their base ASCII letters.

func MeetsThreshold

func MeetsThreshold(cfg config.Catalog, t core.Title, now time.Time) bool

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

func SortTitle(s string) string

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

func WithReadWaitBudget(ctx context.Context, d time.Duration) context.Context

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

func (c *Catalog) BackfillHomeReleases(ctx context.Context, limit int) (int, error)

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

func (c *Catalog) Browse(ctx context.Context, q core.BrowseQuery) (core.Page, error)

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

func (c *Catalog) BrowseStoredEpisodes(ctx context.Context, q core.BrowseQuery) (core.Page, error)

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

func (c *Catalog) BrowseStoredSeasons(ctx context.Context, q core.BrowseQuery) (core.Page, error)

BrowseStoredSeasons pages stored, listable seasons in the library without refreshing shows or seasons from TMDB.

func (*Catalog) ByExternalID

func (c *Catalog) ByExternalID(ctx context.Context, source, id string) (*core.Title, error)

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

func (c *Catalog) CachedGet(ctx context.Context, key core.RatingKey) (*core.Title, error)

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 (c *Catalog) CachedGetMany(ctx context.Context, keys []core.RatingKey) (map[core.RatingKey]core.Title, error)

func (*Catalog) CachedTitle

func (c *Catalog) CachedTitle(ctx context.Context, key core.RatingKey) (*core.Title, error)

CachedTitle returns a mirrored title without contacting TMDB.

func (*Catalog) CachedTitles added in v0.2.6

func (c *Catalog) CachedTitles(ctx context.Context, keys []core.RatingKey) ([]core.Title, error)

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) Children

func (c *Catalog) Children(ctx context.Context, key core.RatingKey) ([]core.Title, error)

Children: seasons of a show, episodes of a season.

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

func (c *Catalog) CountBrowsable(ctx context.Context, typ core.MediaType) (int, error)

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

func (c *Catalog) CountStoredEpisodes(ctx context.Context, show core.Filter) (int, error)

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

func (c *Catalog) CountStoredSeasons(ctx context.Context, show core.Filter) (int, error)

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

func (c *Catalog) EpisodesUnranked(ctx context.Context) (bool, error)

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

func (c *Catalog) FilterVisibility(ctx context.Context, ts []core.Title) []core.Title

FilterVisibility enriches remote summaries with already-known local facets; there are no detail fetches or indexer calls. Unknown metadata stays unknown.

func (*Catalog) Get

func (c *Catalog) Get(ctx context.Context, key core.RatingKey) (*core.Title, error)

Get returns a title from the mirror, fetching on demand when missing/stale.

func (*Catalog) Grandchildren

func (c *Catalog) Grandchildren(ctx context.Context, key core.RatingKey) ([]core.Title, error)

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

func (c *Catalog) MatchesConfig(expected config.Catalog) bool

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

func (c *Catalog) NextEpisode(ctx context.Context, episode core.RatingKey) (*core.Title, error)

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 (c *Catalog) PreviewVisibility(ctx context.Context, specs []core.LibraryExclusion) (any, error)

func (*Catalog) PreviewVisibilityPolicy added in v0.3.0

func (c *Catalog) PreviewVisibilityPolicy(ctx context.Context, specs []core.LibraryExclusion, fallback string) (any, error)

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

func (c *Catalog) RecentMovies(ctx context.Context, since time.Time) ([]core.Title, error)

RecentMovies reads the release-date index, without refreshing any title.

func (*Catalog) RecentShows added in v0.2.9

func (c *Catalog) RecentShows(ctx context.Context, since time.Time) ([]core.Title, error)

RecentShows only reads the local premiere-date index.

func (*Catalog) RefreshRatings added in v0.3.0

func (c *Catalog) RefreshRatings(ctx context.Context, limit int) (int, error)

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

func (c *Catalog) RefreshSchedule(ctx context.Context, show core.RatingKey) error

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

func (c *Catalog) RefreshStoredTitle(ctx context.Context, key core.RatingKey) (*core.Title, error)

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

func (c *Catalog) Run(ctx context.Context)

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

func (c *Catalog) RunTrends(ctx context.Context)

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

func (c *Catalog) ScheduledEpisodes(ctx context.Context, key core.RatingKey) ([]core.Title, error)

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

func (c *Catalog) SeedGenres(mediaType string, m map[int]string)

SeedGenres pre-populates the genre id->name cache (tests, offline warm-up).

func (*Catalog) SetNow added in v0.3.0

func (c *Catalog) SetNow(now func() time.Time)

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

func (c *Catalog) SetTMDB(client TMDB)

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) Similar

func (c *Catalog) Similar(ctx context.Context, key core.RatingKey, limit int) ([]core.Title, error)

Similar returns TMDB recommendations ∪ similar (recommendations first).

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) Stats

func (c *Catalog) Stats(ctx context.Context) (Stats, error)

Stats returns mirror counts, last sync time and current sync progress.

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 (c *Catalog) StoredTitle(ctx context.Context, key core.RatingKey) (*core.Title, error)

func (*Catalog) Sync

func (c *Catalog) Sync(ctx context.Context) error

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

func (c *Catalog) UpdateConfig(cfg config.Catalog)

UpdateConfig swaps the catalogue config (wire to config.Store.Subscribe).

func (*Catalog) UpsertDetailedTitle added in v0.3.0

func (c *Catalog) UpsertDetailedTitle(ctx context.Context, t core.Title) error

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

func (c *Catalog) UpsertTitle(ctx context.Context, t core.Title, browsable bool) error

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) Visible added in v0.2.12

func (c *Catalog) Visible(t *core.Title) bool

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

func (c *Catalog) WarmDetails(ctx context.Context, limit int) (int, error)

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

func (c *Catalog) WriteGeneration() uint64

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

func EstimateCatalogSize(minPopularity float64, minVotes int) Estimate

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 NewMirror

func NewMirror(db *sql.DB, now func() time.Time) *Mirror

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 (m *Mirror) CollectionArt(ctx context.Context, id int64) (core.Collection, error)

func (*Mirror) Fingerprint

func (m *Mirror) Fingerprint(ctx context.Context) (MirrorFingerprint, error)

func (*Mirror) Franchises

func (m *Mirror) Franchises(ctx context.Context) ([]core.Collection, error)

func (*Mirror) Snapshot

func (m *Mirror) Snapshot(ctx context.Context) ([]MirrorItem, error)

func (*Mirror) Titles

func (m *Mirror) Titles(ctx context.Context, keys []core.RatingKey) ([]core.Title, error)

Titles returns hydrated, released, non-adult mirror entries in requested order. It never fetches remote metadata, so collection serving stays bounded and offline.

func (*Mirror) TitlesIncludingFuture added in v0.2.37

func (m *Mirror) TitlesIncludingFuture(ctx context.Context, keys []core.RatingKey) ([]core.Title, error)

TitlesIncludingFuture is a local metadata read for collection-scoped authorization. Its caller must enforce membership and viewer policy.

type MirrorFingerprint

type MirrorFingerprint struct {
	Count            int
	MaxFetch, MaxAdd int64
}

type MirrorItem

type MirrorItem struct {
	Title    core.Title
	AddedAt  int64
	Detailed bool
}

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

func WithCrowdTTL(d time.Duration) Option

WithCrowdTTL overrides how long co-engagement lists stay fresh.

func WithListTTL

func WithListTTL(d time.Duration) Option

func WithNow

func WithNow(fn func() time.Time) Option

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 WithStaleAfter(d time.Duration) Option

func WithSyncYears

func WithSyncYears(from, to int) Option

WithSyncYears bounds the year slices used when discover exceeds 500 pages.

type PersonMatch added in v0.3.0

type PersonMatch struct {
	TMDB    int64
	Name    string
	Credits int
}

PersonMatch is a credited person a people search may return.

type SaferRatingSQL added in v0.3.0

type SaferRatingSQL interface {
	HideExceeding(keyColumn string) string
}

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

type VisibilityRulePreview struct {
	Movies int `json:"movies"`
	Shows  int `json:"shows"`
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL