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

calendar

package
v0.3.2 Latest Latest
Warning

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

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

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

View Source
const (
	KindEpisode  = "episode"
	KindPremiere = "premiere" // an announced season whose episodes are not listed yet
	KindMovie    = "movie"
)

Entry kinds.

View Source
const (
	StateAvailable   = "available"   // released and playable now
	StateToday       = "today"       // airs or releases today
	StateUpcoming    = "upcoming"    // later
	StateUnavailable = "unavailable" // released, but not playable yet (e.g. only in cinemas)
)

Entry states.

View Source
const (
	ReasonWatching  = "watching"
	ReasonWatchlist = "watchlist"
	ReasonLookAhead = "lookahead"
	ReasonTaste     = "taste"
	ReasonPopular   = "popular"
)

Why an entry is on the calendar.

View Source
const (
	BadgeSeriesPremiere = "seriesPremiere"
	BadgeSeasonPremiere = "seasonPremiere"
	BadgeFinale         = "finale"
)

Badges.

Variables

This section is empty.

Functions

This section is empty.

Types

type Activity

type Activity struct {
	UserID     int64
	Show       core.RatingKey
	LastViewed time.Time
}

Activity is a viewer's latest watch activity on a show.

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 LookAhead

type LookAhead struct {
	Name    string
	Members []core.RatingKey
}

LookAhead is a server-wide collection of upcoming releases.

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 New

func New(o Options) *Service

New returns a calendar service.

func (*Service) Calendar

func (s *Service) Calendar(ctx context.Context, q Query) (*Response, error)

Calendar returns the calendar for q, reusing a recent assembly.

func (*Service) Handler

func (s *Service) Handler() http.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)

func (*Service) Invalidate

func (s *Service) Invalidate()

Invalidate drops cached calendars.

func (*Service) Refresh

func (s *Service) Refresh(ctx context.Context)

Refresh mirrors the seasons of up to refreshBudget followed shows, most recently active first, then drops cached calendars.

func (*Service) Run

func (s *Service) Run(ctx context.Context)

Run keeps followed shows' current seasons mirrored, and TMDB's upcoming movies, until ctx ends. Run it on one node (the cluster leader).

type Viewer

type Viewer struct {
	ID    int64  `json:"id"`
	Name  string `json:"name"`
	Thumb string `json:"thumb,omitempty"`
	Owner bool   `json:"owner,omitempty"`
}

Viewer is a household member as the calendar shows them.

Jump to

Keyboard shortcuts

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