mediaserver

package
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Jul 12, 2026 License: GPL-3.0 Imports: 19 Imported by: 0

Documentation

Overview

Package mediaserver: Manager owns connection testing + Plex PIN auth for Plex / Jellyfin / Emby entries. CRUD over the entries lives in the YAML config (config.AddMediaServer etc.); handlers call those directly. The Dispatcher (this package) owns runtime fan-out.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrServerNotFound    = errors.New("media server not found")
	ErrInvalidServerType = errors.New("invalid server type")
	ErrTestFailed        = errors.New("connection test failed")
	ErrMovieNotFound     = errors.New("movie not found on media server")
	ErrShowNotFound      = errors.New("series not found on media server")
)

Functions

This section is empty.

Types

type DeepLinker

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

DeepLinker resolves per-server deep links for a movie. Used by GET /movies/{id}/play-on. The enabled-server set is read live from config.

func NewDeepLinker

func NewDeepLinker(
	builder func(config.MediaServerEntry) (Server, error),
) *DeepLinker

func (*DeepLinker) Resolve

func (l *DeepLinker) Resolve(
	ctx context.Context,
	tmdbID uint32,
	title string,
	year uint16,
) []PlayOnResult

Resolve fans out to every enabled media server in parallel, resolving a movie deep link per server. Per-server errors never propagate; they become PlayOnResult entries with Status = unavailable so the UI can render them.

func (*DeepLinker) ResolveTV

func (l *DeepLinker) ResolveTV(
	ctx context.Context,
	tvdbID uint32,
	title string,
	year uint16,
) []PlayOnResult

ResolveTV is the series counterpart of Resolve.

type Dispatcher

type Dispatcher struct{}

Dispatcher fans RefreshLibrary across all enabled media servers, read live from config per invocation.

func NewDispatcher

func NewDispatcher() *Dispatcher

func (*Dispatcher) RefreshAll

func (d *Dispatcher) RefreshAll(ctx context.Context, libraryPath string) error

type Jellyfin

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

func NewJellyfin

func NewJellyfin(baseURL, apiKey string) *Jellyfin
func (j *Jellyfin) MovieDeepLink(
	ctx context.Context, _ string, tmdbID uint32, title string, year uint16,
) (string, error)

MovieDeepLink returns a Jellyfin/Emby web URL pointing at the movie's details page. Tries TMDB-provider-id match first (exact), falls back to title + year. Both Jellyfin and Emby share this URL hash route. Returns ErrMovieNotFound when no item matches.

func (*Jellyfin) RefreshLibrary

func (j *Jellyfin) RefreshLibrary(ctx context.Context, _, _ string) error
func (j *Jellyfin) TVShowDeepLink(
	ctx context.Context, _ string, tvdbID uint32, title string, year uint16,
) (string, error)

TVShowDeepLink mirrors MovieDeepLink for series (Emby shares this API). The hintSection is Plex-only and ignored here.

func (*Jellyfin) TestConnection

func (j *Jellyfin) TestConnection(ctx context.Context) error

type Manager

type Manager interface {
	Test(ctx context.Context, p TestParams) error
	TestByName(ctx context.Context, name string) error
	DiscoverSections(ctx context.Context, p TestParams) ([]Section, error)
	// BeginPlexPin starts a Plex PIN OAuth flow. Caller opens PlexPin.AuthURL
	// in a browser popup; admin authenticates with Plex; caller polls
	// PollPlexPin(pin.ID) until AuthToken is non-empty (5-minute window).
	BeginPlexPin(ctx context.Context) (PlexPin, error)
	PollPlexPin(ctx context.Context, pinID uint64) (PlexPinResult, error)
}

Manager is the consumer-facing surface used by HTTP handlers for behavioral operations. Persistence of media-server entries is via config mutate.

func New

func New() Manager

type PlayOnResult

type PlayOnResult struct {
	Name       string
	ServerType string
	URL        string
	Fallback   bool
	Status     PlayOnStatus
}

PlayOnResult is one server's resolved link or fallback for a single movie.

type PlayOnStatus

type PlayOnStatus string

PlayOnStatus describes the resolution outcome for one media server.

const (
	StatusResolved    PlayOnStatus = "resolved"
	StatusFallback    PlayOnStatus = "fallback"
	StatusUnavailable PlayOnStatus = "unavailable"
)

type Plex

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

func NewPlex

func NewPlex(baseURL, token string) *Plex

func (*Plex) ListSections

func (p *Plex) ListSections(ctx context.Context) ([]Section, error)
func (p *Plex) MovieDeepLink(
	ctx context.Context,
	hintSection string,
	tmdbID uint32,
	title string,
	year uint16,
) (string, error)

MovieDeepLink returns a Plex Web URL pointing at the movie's details page. Enumerates all movie-type sections on the server (Plex commonly splits movies across "Movies", "4K", "Documentaries", etc.) and queries each in turn — `hintSection`, if set and present in the list, is checked first to minimise round-trips on the happy path. Within each section it tries TMDB-GUID match first (exact), then title+year (fuzzy). Returns ErrMovieNotFound when no section yields a match.

func (*Plex) RefreshLibrary

func (p *Plex) RefreshLibrary(
	ctx context.Context,
	libraryPath, sectionKey string,
) error
func (p *Plex) TVShowDeepLink(
	ctx context.Context,
	hintSection string,
	tvdbID uint32,
	title string,
	year uint16,
) (string, error)

TVShowDeepLink mirrors MovieDeepLink for TV-type sections: matches on the TVDB guid first, then title+year, and builds the same details URL.

func (*Plex) TestConnection

func (p *Plex) TestConnection(ctx context.Context) error

type PlexClientCreds

type PlexClientCreds struct {
	ClientID string
	Product  string
	Version  string
}

PlexClientCreds carries the per-install identity Plex requires on every PIN request. Stored once-per-install in config (PlexClientID) and used as X-Plex-Client-Identifier; X-Plex-Product/Version identify Streamline.

type PlexPin

type PlexPin struct {
	ID      uint64
	Code    string
	AuthURL string
	// ClientID is the X-Plex-Client-Identifier the flow used. Surfaced so a
	// read-only deploy operator can commit it to media_server.plex_client_id.
	ClientID string
}

PlexPin is the result of starting a PIN-based OAuth flow. AuthURL is the URL the admin's browser must open (popup); ID is then polled until Plex fills in authToken.

type PlexPinResult

type PlexPinResult struct {
	AuthToken string
	Expired   bool
}

PlexPinResult is the polled state of a PIN. AuthToken is empty until the user completes the auth flow on app.plex.tv. Expired is true when Plex returns 404 or the recorded ExpiresAt has passed.

type Section

type Section struct {
	Key       string
	Name      string
	Locations []string
	Type      string
}

Section is a Plex library section: the unit RefreshLibrary targets when given a non-empty sectionKey. Locations are filesystem paths Plex itself sees (which may differ from Streamline's own mounts).

type Server

type Server interface {
	TestConnection(ctx context.Context) error
	// RefreshLibrary triggers a re-scan on the server. sectionKey is the
	// Plex-internal section identifier when targeting a specific library;
	// pass "" to fall back to legacy behavior (path-match for Plex, full
	// refresh for Jellyfin/Emby).
	RefreshLibrary(ctx context.Context, libraryPath, sectionKey string) error
	// MovieDeepLink returns a web URL pointing at the movie's details page on
	// this server. Returns ErrMovieNotFound when no item matches. hintSection
	// is the configured Plex library section (key) to check first; Jellyfin
	// and Emby ignore it.
	MovieDeepLink(
		ctx context.Context,
		hintSection string,
		tmdbID uint32,
		title string,
		year uint16,
	) (string, error)
	// TVShowDeepLink returns a web URL pointing at the series' details page on
	// this server. Returns ErrShowNotFound when no item matches. hintSection
	// is the configured Plex TV library section (key) to check first; Jellyfin
	// and Emby ignore it.
	TVShowDeepLink(
		ctx context.Context,
		hintSection string,
		tvdbID uint32,
		title string,
		year uint16,
	) (string, error)
}

func BuildServer

func BuildServer(ms config.MediaServerEntry) (Server, error)

type TestParams

type TestParams struct {
	ServerType string
	Host       string
	APIKey     string
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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