Documentation
¶
Overview ¶
Package calendar assembles the owner's release calendar: upcoming and recent episodes of the shows the household watches or has watchlisted, and movie releases from watchlists, Look Ahead collections and the household's taste. Ether's catalogue is all of TMDB, so the calendar is derived from what viewers actually follow rather than from a library.
The request path reads the local catalogue mirror and watch state only. A background pass (Run) keeps followed shows' current seasons mirrored so their future episodes are known; requests never contact TMDB.
Index ¶
Constants ¶
const ( KindEpisode = "episode" KindPremiere = "premiere" // an announced season whose episodes are not listed yet KindMovie = "movie" )
Entry kinds.
const ( StateAvailable = "available" // released and playable now StateToday = "today" // airs or releases today StateUpcoming = "upcoming" // later )
Entry states.
const ( ReasonWatching = "watching" ReasonWatchlist = "watchlist" ReasonLookAhead = "lookahead" ReasonTaste = "taste" ReasonPopular = "popular" )
Why an entry is on the calendar.
const ( BadgeSeriesPremiere = "seriesPremiere" BadgeSeasonPremiere = "seasonPremiere" BadgeFinale = "finale" )
Badges.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Catalog ¶
type Catalog interface {
ScheduledShows(ctx context.Context, shows []core.RatingKey, from, until time.Time, limit int) ([]catalog.ScheduleEntry, error)
ScheduledPremieres(ctx context.Context, shows []core.RatingKey, from, until time.Time) ([]catalog.ScheduleEntry, error)
ScheduledMovies(ctx context.Context, keys []core.RatingKey, from, until time.Time) ([]catalog.ScheduleEntry, error)
PopularScheduledMovies(ctx context.Context, from, until time.Time, limit int) ([]catalog.ScheduleEntry, error)
CachedGetMany(ctx context.Context, keys []core.RatingKey) (map[core.RatingKey]core.Title, error)
RefreshSchedule(ctx context.Context, show core.RatingKey) error
}
Catalog is the local, read-only mirror surface the calendar needs, plus the background refresh of a followed show's seasons.
type Entry ¶
type Entry struct {
ID string `json:"id"`
Kind string `json:"kind"`
// Key is the dated title; Open is the title the console opens (the show
// for episodes and premieres).
Key string `json:"key"`
Open string `json:"open"`
Title string `json:"title"`
EpisodeTitle string `json:"episodeTitle,omitempty"`
Season int `json:"season,omitempty"`
Episode int `json:"episode,omitempty"`
Date string `json:"date"`
Year int `json:"year,omitempty"`
Poster string `json:"poster,omitempty"`
Backdrop string `json:"backdrop,omitempty"`
Still string `json:"still,omitempty"`
Overview string `json:"overview,omitempty"`
Runtime int `json:"runtimeMinutes,omitempty"`
ContentRating string `json:"contentRating,omitempty"`
Rating float64 `json:"rating,omitempty"`
Genres []string `json:"genres,omitempty"`
State string `json:"state"`
Badges []string `json:"badges,omitempty"`
Reasons []string `json:"reasons"`
// Collections names the Look Ahead collections listing a movie.
Collections []string `json:"collections,omitempty"`
// Viewers are who it is on the calendar for; Watched who has seen it.
Viewers []int64 `json:"viewers"`
Watched []int64 `json:"watched,omitempty"`
// contains filtered or unexported fields
}
Entry is one dated release.
type Options ¶
type Options struct {
Catalog Catalog
// Viewers lists the household (active viewers, owner included).
Viewers func(context.Context) ([]core.User, error)
// Followed lists shows with episodes watched or in progress since a time.
Followed func(context.Context, time.Time) ([]Activity, error)
// Watched reports one viewer's watch state for the given titles.
Watched func(context.Context, int64, []core.RatingKey) (map[core.RatingKey]core.WatchStatus, error)
// Watchlisted lists every viewer's watchlisted movies and shows.
Watchlisted func(context.Context) (map[int64][]core.RatingKey, error)
// LookAheads lists the server-wide Look Ahead collections.
LookAheads func(context.Context) ([]LookAhead, error)
// Allowed applies the owner's content policy for a viewer (rating caps,
// library restrictions, a show's inherited policy).
Allowed func(context.Context, *core.User, *core.Title) bool
// UpcomingMovies refreshes the mirror's upcoming movie releases in the
// background (TMDB's upcoming list).
UpcomingMovies func(context.Context) error
// Image turns a TMDB image path into a console URL.
Image func(path string, width int) string
Now func() time.Time
Logger *slog.Logger
}
Options are the calendar's dependencies. Catalog, Viewers, Followed and Allowed are required; the rest may be nil.
type Query ¶
type Query struct {
From, To time.Time // dates; To is inclusive
// Viewer is one viewer's calendar; 0 is the whole household.
Viewer int64
// Types: "" (both), "movie" or "show".
Types string
// Movies is the movie policy: "foryou" (default; watchlists, Look Ahead
// collections and the household's taste), "popular", "watchlist" or
// "hidden".
Movies string
// Location decides which day is "today".
Location *time.Location
}
Query selects a calendar.
type Response ¶
type Response struct {
From string `json:"from"`
To string `json:"to"`
Today string `json:"today"`
Viewers []Viewer `json:"viewers"`
Entries []Entry `json:"entries"`
// Shows is how many followed shows the calendar draws from.
Shows int `json:"shows"`
// Truncated is set when the range held more than maxEntries.
Truncated bool `json:"truncated,omitempty"`
GeneratedAt time.Time `json:"generatedAt"`
// Warming is set until the first background pass has mirrored followed
// shows' seasons, so the owner knows more episodes are on the way.
Warming bool `json:"warming,omitempty"`
}
Response is an assembled calendar.
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service builds calendars and keeps the mirror ready for them.
func (*Service) Handler ¶
Handler serves GET / (mounted at /ether/api/calendar):
?from=2026-10-26&to=2026-12-06 dates, to inclusive (default: last week + 6 weeks) &viewer=12 one viewer (default: the whole household) &types=movie|show one kind (default: both) &movies=foryou|popular|watchlist|hidden &tz=America/Toronto which day is today (default UTC)