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

plex

package
v0.2.36 Latest Latest
Warning

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

Go to latest
Published: Oct 29, 2026 License: GPL-3.0 Imports: 65 Imported by: 0

Documentation

Overview

Package plex is Ether's Plex Media Server front end: the HTTP API that official Plex apps (Web, iOS, Apple TV, Android, TVs) talk to. Everything behind it is reached through internal/core interfaces.

Index

Constants

View Source
const APIVersion = "1.2.3"

APIVersion is the PMS API version Ether implements (X-Plex-Pms-Api-Version).

View Source
const DefaultPMSVersion = "1.43.4.10903-e5521bd8c"

DefaultPMSVersion is reported when Identity.Version is empty. Clients gate features on the server version, so it must look like a current PMS build.

Variables

This section is empty.

Functions

This section is empty.

Types

type AccessPolicy

type AccessPolicy interface {
	Allowed(*core.User, *core.Title) bool
}

AccessPolicy adds owner-defined restrictions to the mandatory title guard.

type CollectionArtworker

type CollectionArtworker interface {
	CollectionArtwork(ctx context.Context, user *core.User, key core.RatingKey, element string, width int) (data []byte, contentType string, ok bool, err error)
}

CollectionArtworker is optionally implemented by Deps.Collections to serve generated collection posters (internal/collections renders them with internal/artwork). ok=false falls back to the TMDB artwork path.

type Deps

type Deps struct {
	FilterAvailable     func(context.Context, []core.Title) []core.Title
	PrioritizeAvailable func(context.Context, []core.Title) []core.Title
	EpisodeOrder        *episodeorder.Service
	PlexGUID            *plexguid.Service
	Discovery           *DiscoveryFeatures
	LiveTV              *livetv.Service
	AccessPolicy        AccessPolicy
	Catalog             core.Catalog
	Collections         core.Collections
	VibeSearch          core.VibeSearcher
	Recommender         core.Recommender
	State               core.State
	Playlists           core.Playlists
	Auth                core.Auth
	Playback            core.Playback
	Transcoder          core.Transcoder
	// Variants lists distinct release versions for "Play Version" detail
	// pages (optional: without it, detail pages stay single-Media).
	Variants core.VariantResolver
	// Downloads remuxes resolved sources to temp MP4s for the Download
	// Queue API; nil disables downloads (allowSync stays "0").
	Downloads        core.DownloadRemuxer
	TrackPreferences TrackPreferences
	Markers          MarkerProvider
	Subtitles        SubtitleSource
	Extras           ExtrasProvider
	Trickplay        core.TrickplayProvider

	// Config returns the current settings snapshot.
	Config func() config.Config
	// OwnerSubscription returns the current entitlement snapshot from plex.tv.
	OwnerSubscription func() (active bool, features []string)
	// ImageURL builds TMDB image URLs; defaults to image.tmdb.org.
	ImageURL core.ImageURLFunc
	Logger   *slog.Logger
	Identity Identity
	Hooks    Hooks

	// Sections overrides the default Movies (1) and TV Shows (2) sections.
	Sections []Section
	// HTTPClient fetches artwork for the image proxy; defaults to a client
	// with a 20 s timeout.
	HTTPClient *http.Client
	// ImageCacheBytes bounds the in-memory artwork cache (default 128 MiB).
	ImageCacheBytes int64
	// DB persists derived artwork data (UltraBlurColors) in plex_* tables.
	// Optional: without it, colours are kept in memory only.
	DB *sql.DB
	// DisableEnrichment turns off the background title-detail and
	// UltraBlurColors work (the spike test library has nothing to fetch).
	DisableEnrichment bool
	// Cluster, when set (clustered nodes only; requires DB), shares play
	// sessions, play queues, terminations and notifications with the other
	// nodes. Nil keeps everything in this process.
	Cluster clusterbus.Node
	// SessionHeartbeat is how often a clustered node refreshes its shared
	// play sessions (default 10s).
	SessionHeartbeat time.Duration
	// Now is the clock (tests).
	Now func() time.Time
}

Deps are the server's dependencies. Catalog, State, Auth and Playback are required; the rest degrade gracefully when nil.

type Directive

type Directive struct {
	Verb string
	Args map[string]string
}

Directive is one parsed X-Plex-Client-Profile-Extra directive, e.g. add-limitation(scope=videoCodec&scopeName=h264&...).

func ParseProfileExtra

func ParseProfileExtra(s string) []Directive

ParseProfileExtra splits a profile-extra string into directives. The value may arrive URL-encoded; directives are separated by "+".

type DiscoveryFeatures

type DiscoveryFeatures struct {
	Watchlist *watchlist.Service
	Ratings   *ratings.Service
	Overlays  *overlays.Service
	Personal  *personalize.Discovery
	LLM       *llm.Service
	Localize  func(context.Context, *core.Title, string) (*core.Title, error)
	// contains filtered or unexported fields
}

DiscoveryFeatures is optional. Viewers use these features through ordinary Plex metadata, Home, search and continue-watching endpoints.

func (*DiscoveryFeatures) Run

func (d *DiscoveryFeatures) Run(ctx context.Context)

Run is the sole metadata background worker, bounded and stopped with the app.

type ExtrasProvider

type ExtrasProvider interface {
	Enabled() bool
	List(ctx context.Context, parent *core.Title, lang string) ([]extras.Extra, error)
	Lookup(key core.RatingKey) (extras.Extra, bool)
	Resolve(ctx context.Context, e extras.Extra) (extras.Resolved, error)
	PrewarmBytes() int64
}

ExtrasProvider is the extras service surface the front end needs (*extras.Service satisfies it).

type Hooks

type Hooks struct {
	// OnTimeline is called for every timeline update (prefetch uses it).
	OnTimeline func(user *core.User, key core.RatingKey, offset, duration time.Duration, state string)
	// OnScrobble is called when a user marks an item watched.
	OnScrobble func(user *core.User, key core.RatingKey)
}

Hooks are optional callbacks into other components. They run on their own goroutine and must be safe for concurrent use.

type Identity

type Identity struct {
	MachineIdentifier string
	FriendlyName      string
	Version           string // PMS-style version string
	Platform          string // "MacOSX", "Windows", "Linux"
	PlatformVersion   string
	// MyPlexSubscription reports whether the owner has Plex Pass; Ether
	// reports this honestly from plex.tv.
	MyPlexSubscription bool
	OwnerFeatures      []string
}

Identity is how the server presents itself. Empty fields fall back to the config snapshot (friendly name, machine identifier) or sensible defaults.

type MarkerProvider

type MarkerProvider interface {
	Markers(context.Context, core.RatingKey, core.MediaInfo) ([]markers.Marker, error)
}

type Request

type Request struct {
	Token              string
	ClientID           string // X-Plex-Client-Identifier
	Product            string // X-Plex-Product
	Version            string // X-Plex-Version
	Platform           string // X-Plex-Platform
	PlatformVersion    string // X-Plex-Platform-Version
	Device             string // X-Plex-Device
	DeviceName         string // X-Plex-Device-Name
	Model              string // X-Plex-Model
	Vendor             string // X-Plex-Device-Vendor
	Language           string // X-Plex-Language
	Marketplace        string // X-Plex-Marketplace
	Provides           string // X-Plex-Provides
	Features           string // X-Plex-Features
	ProfileExtra       string // X-Plex-Client-Profile-Extra
	ProfileName        string // X-Plex-Client-Profile-Name
	ClientCapabilities string // X-Plex-Client-Capabilities (legacy)
	SessionID          string // X-Plex-Session-Identifier
	PMSAPIVersion      string // X-Plex-Pms-Api-Version

	// Paging (X-Plex-Container-Start/Size); HasPage is false when the client
	// did not ask for a window.
	Start   int
	Size    int
	HasPage bool

	Format   model.Format
	RemoteIP netip.Addr
	Remote   bool // not on a private/loopback network

	User *core.User
}

Request is the parsed Plex request context: every X-Plex-* header (or its query-string equivalent), paging, the output format and the remote address.

func FromContext

func FromContext(ctx context.Context) *Request

FromContext returns the request context attached by the middleware.

func ParseRequest

func ParseRequest(r *http.Request) *Request

ParseRequest builds the request context from an HTTP request. Forwarded addresses are considered only for a loopback peer (a local reverse proxy).

func (*Request) ClientCaps

func (pr *Request) ClientCaps(remoteMaxKbps int) core.ClientCaps

ClientCaps derives core.ClientCaps for the request. remoteMaxKbps caps the bitrate of remote clients (0 = unlimited).

type Section

type Section struct {
	ID       int
	Type     core.MediaType // movie or show
	Title    string
	UUID     string // stable; derived from the machine identifier when empty
	Language string
}

Section is a library section exposed to clients.

type Server

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

Server is the PMS API handler. It is an http.Handler; call Close on shutdown to stop background work and notification streams.

func NewServer

func NewServer(d Deps) *Server

NewServer builds the PMS API handler.

func (*Server) Close

func (s *Server) Close() error

Close stops background goroutines and disconnects notification clients.

func (*Server) LibrarySections added in v0.2.14

func (s *Server) LibrarySections() []Section

LibrarySections returns the canonical section identities for account registration. The copy prevents publishers from changing local libraries.

func (*Server) RecoverTranscode added in v0.2.4

func (s *Server) RecoverTranscode(ctx context.Context, id, inputURL string, at time.Duration) error

RecoverTranscode maps the client's encoder ID to its playback session. Playback rechecks the input generation before attempting recovery.

func (*Server) ServeHTTP

func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP implements http.Handler.

func (*Server) StopPlayback

func (s *Server) StopPlayback(id, reason string)

StopPlayback ends an owner-selected source and tells the official app why. On a clustered node a session this node does not serve (a playback or live TV session ID from the cluster-wide status) is stopped by the node that does.

func (*Server) TranscodeFor

func (s *Server) TranscodeFor(playSessionID string) (core.HLSSession, bool)

TranscodeFor returns the running transcode session fed by a playback session. Transcode sessions are keyed by the client's session id, so playback needs this to move ffmpeg to a new input on mid-stream failover.

func (*Server) WatchStateChanged added in v0.2.11

func (s *Server) WatchStateChanged(userID int64, key core.RatingKey)

WatchStateChanged invalidates client library metadata after a committed watch update. A playing notification only updates session status; clients can keep their cached Continue Watching shelf until a library timeline event arrives.

type SessionToucher

type SessionToucher interface {
	Touch(sessionID string)
}

SessionToucher is optionally implemented by core.Playback to keep a play session alive on timeline updates.

type SubtitleCatalog added in v0.2.21

type SubtitleCatalog interface {
	CachedSidecars(ctx context.Context, t *core.Title, u *core.User, embedded []core.StreamInfo) []core.StreamInfo
}

SubtitleCatalog is optionally implemented by Deps.Subtitles: the sidecars already cached for a title and viewer, without network access, skipping streams embedded already lists (by ExternalURL) or covers (by language).

type SubtitleOffer added in v0.2.21

type SubtitleOffer struct {
	ID              int64  // provider file id, passed back to DownloadSubtitle
	Language        string // ISO 639-1
	Title           string // release or file name
	Provider        string // "OpenSubtitles"
	Score           int
	HearingImpaired bool
	Forced          bool
	PerfectMatch    bool // matched the playing file's hash or release
}

SubtitleOffer is one subtitle search result.

type SubtitlePrefetcher added in v0.2.21

type SubtitlePrefetcher interface {
	PrefetchSidecars(ctx context.Context, t *core.Title, u *core.User) bool
}

SubtitlePrefetcher is optionally implemented by Deps.Subtitles: start a budgeted background fetch of the viewer's missing languages for a title.

type SubtitleSearch added in v0.2.21

type SubtitleSearch interface {
	SearchSubtitles(ctx context.Context, t *core.Title, u *core.User, lang, release string) ([]SubtitleOffer, error)
	// DownloadSubtitle fetches an offer returned by SearchSubtitles for t
	// and returns its sidecar stream; core.ErrNotFound for unknown offers.
	DownloadSubtitle(ctx context.Context, t *core.Title, u *core.User, id int64) (core.StreamInfo, error)
}

SubtitleSearch is optionally implemented by Deps.Subtitles: Plex's on-demand subtitle search and pick.

type SubtitleSource

type SubtitleSource interface {
	OpenFormat(string, string) (io.ReadCloser, string, error)
}

SubtitleSource resolves cached OpenSubtitles and synchronized sidecars.

type SubtitleTimeline added in v0.2.21

type SubtitleTimeline interface {
	OpenFormatAt(id, format string, offset time.Duration) (io.ReadCloser, string, error)
}

SubtitleTimeline is optionally implemented by Deps.Subtitles: a sidecar with its cues moved back by offset, for a transcode that starts there.

type TrackPreferences

TrackPreferences is optional. Selections are stream slice positions; saved show choices match language/flags so they survive changes in release order.

Directories

Path Synopsis
Package model holds the Plex Media Server response models and the encoder that renders one model as either PMS-style XML or PMS-style JSON.
Package model holds the Plex Media Server response models and the encoder that renders one model as either PMS-style XML or PMS-style JSON.

Jump to

Keyboard shortcuts

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