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

watchlist

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: 21 Imported by: 0

Documentation

Overview

Package watchlist ingests authorized viewers' watchlists and lazily checks their release availability. It never adds content or writes to Plex/Trakt.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ExportKeys added in v0.2.4

func ExportKeys(ctx context.Context, db *sql.DB, userID int64) ([]core.RatingKey, error)

ExportKeys reads the live watchlist, including manual and synced sources. Multiple sources for one title produce one exported entry.

func ImportTitleTx added in v0.2.4

func ImportTitleTx(ctx context.Context, tx *sql.Tx, userID int64, title core.Title, added int64) error

ImportTitleTx adds a reviewed title to the live viewer watchlist in the caller's transaction, so import bookkeeping and all list writes are atomic.

Types

type Item

type Item struct {
	Title       core.Title `json:"title"`
	Sources     []string   `json:"sources"`
	AddedAt     time.Time  `json:"addedAt"`
	CheckedAt   time.Time  `json:"checkedAt,omitempty"`
	AvailableAt time.Time  `json:"availableAt,omitempty"`
}

type Notifier

type Notifier interface {
	TitleAvailable(context.Context, string) error
}

type OnceNotifier added in v0.2.48

type OnceNotifier interface {
	TitleAvailableOnce(ctx context.Context, key, title string) error
}

OnceNotifier queues an alert at most once per key, however often it is called (notify.Service implements it). With it, an episode alert is queued exactly once even when a crash or error interrupts marking it sent. A plain Notifier is still supported but then at least once: such a retry repeats the alert, at most alertAttempts more times.

type Options

type Options struct {
	Logger           *slog.Logger
	Catalog          core.Catalog
	Resolver         core.Resolver
	Engine           core.Engine
	Trakt            Source
	Tokens           func(context.Context, int64) (string, error)
	Users            func(context.Context) ([]core.User, error)
	Allowed          func(*core.User, *core.Title) bool
	Notifier         Notifier
	Client           *http.Client
	PlexBaseURL      string
	ClientIdentifier string
	Now              func() time.Time
	PrewarmBytes     int64
	// SyncInterval is how often Run passes over every viewer (30m).
	SyncInterval time.Duration
	// ResumeSchedule makes Run wait until SyncInterval has passed since the
	// last pass recorded in the database (by any node) before its first
	// pass, instead of passing at once. A cluster sets it because Run
	// restarts on every leader handoff.
	ResumeSchedule bool
	// OnAvailable runs when a watchlist title first becomes playable.
	// The key is the movie, show, or newly released episode.
	OnAvailable func(context.Context, int64, core.RatingKey)
}

type Service

type Service struct {
	// contains filtered or unexported fields
}

func New

func New(db *sql.DB, o Options) *Service

func (*Service) Check

func (s *Service) Check(ctx context.Context, u *core.User) error

Check resolves only explicitly watched-for, released titles, never the whole catalogue. A healthy resolver result is required before marking available.

A show (or season) becomes available through its first released episode. After that, each newer regular episode is resolved once it airs and, when a healthy release exists, announced and prewarmed once (see newEpisode).

func (*Service) Contains added in v0.3.0

func (s *Service) Contains(ctx context.Context, userID int64, key core.RatingKey) (bool, error)

Contains reports membership from any watchlist source for one viewer.

func (*Service) ContainsMany added in v0.3.0

func (s *Service) ContainsMany(ctx context.Context, userID int64, keys []core.RatingKey) (map[core.RatingKey]bool, error)

ContainsMany reads membership for a page in one query per chunk.

func (*Service) Generation added in v0.3.0

func (s *Service) Generation() uint64

Generation changes when watchlist membership changes.

func (*Service) Hubs

func (s *Service) Hubs(ctx context.Context, u *core.User, limit int) ([]core.Hub, error)

func (*Service) Items

func (s *Service) Items(ctx context.Context, u *core.User) ([]Item, error)

func (*Service) Membership added in v0.3.0

func (s *Service) Membership(ctx context.Context, userID int64, key core.RatingKey) (bool, *time.Time, error)

Membership reads one viewer/title pair across current watchlist sources. The latest stored source timestamp matches Items' existing ordering. It is an observation or import time, not the title's date added and not necessarily the upstream addition time. A zero timestamp is unknown rather than the Unix epoch.

func (*Service) Remind

func (s *Service) Remind(ctx context.Context, u *core.User, key core.RatingKey) error

func (*Service) Remove

func (s *Service) Remove(ctx context.Context, userID int64, key core.RatingKey) error

func (*Service) Router

func (s *Service) Router() http.Handler

Router must be mounted behind Ether's owner authentication middleware.

func (*Service) Run

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

Run is cancelled by the app; individual viewers are isolated and bounded. Run passes over every viewer (watchlist sync and availability check) at once and then every SyncInterval; with ResumeSchedule the first pass waits out the interval since the last recorded pass.

func (*Service) SaveSettings

func (s *Service) SaveSettings(ctx context.Context, v Settings) error

func (*Service) Settings

func (s *Service) Settings(ctx context.Context) (Settings, error)

func (*Service) Sync

func (s *Service) Sync(ctx context.Context, u *core.User) error

Sync preserves the last successful snapshot when an upstream fails.

func (*Service) Watchlisted added in v0.3.0

func (s *Service) Watchlisted(ctx context.Context) (map[int64][]core.RatingKey, error)

Watchlisted returns every viewer's watchlisted titles by viewer id, released or not, from every source. A season counts as its show.

type Settings

type Settings struct {
	Enabled           bool `json:"enabled"`
	Plex              bool `json:"plex"`
	Trakt             bool `json:"trakt"`
	Notify            bool `json:"notify"`
	Prewarm           bool `json:"prewarm"`
	CheckHours        int  `json:"checkHours"`
	NaturalSearch     bool `json:"naturalSearch"`
	Recaps            bool `json:"recaps"`
	SubtitleTranslate bool `json:"subtitleTranslate"`
	SpeechToText      bool `json:"speechToText"`
	OverviewTranslate bool `json:"overviewTranslate"`
}

type Source

type Source interface {
	Watchlist(context.Context, int64, int) ([]core.Title, error)
}

Jump to

Keyboard shortcuts

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