watchlist

package
v0.2.4 Latest Latest
Warning

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

Go to latest
Published: Oct 21, 2026 License: GPL-3.0 Imports: 15 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 Options

type Options struct {
	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
	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
}

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.

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

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"`
}

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