Documentation
¶
Overview ¶
Package plex holds the HTTP client and response types for the Plex Media Server API. Consumers get a typed *Client with library, history, identity, stream-selection, and shared-server methods. Value types (Episode, Stream, Media, Part, Label) live in plex-language-sync/internal/streams; this package owns the container + admin-facing types (Account, User, Section, Session, HistoryItem, Show, Season) and the MediaContainer wrapper.
Index ¶
- Constants
- Variables
- func SwapTVClient(replacement *http.Client) (restore func())
- func WarnIfPlaintextURL(u *url.URL)
- type Account
- type Client
- func (c *Client) BaseURL() *url.URL
- func (c *Client) DisableSubtitles(ctx context.Context, partID int) error
- func (c *Client) Episode(ctx context.Context, rk RatingKey) (*streams.Episode, error)
- func (c *Client) HTTPClient() *http.Client
- func (c *Client) History(ctx context.Context, sinceUnix int64) ([]HistoryItem, error)
- func (c *Client) LoggedUser(ctx context.Context) (*User, error)
- func (c *Client) RecentlyAdded(ctx context.Context, sectionKey RatingKey, sinceUnix int64) ([]streams.Episode, error)
- func (c *Client) SeasonEpisodes(ctx context.Context, rk RatingKey) ([]streams.Episode, error)
- func (c *Client) ServerIdentity(ctx context.Context) (*ServerIdentity, error)
- func (c *Client) SetAudioStream(ctx context.Context, partID, streamID int) error
- func (c *Client) SetSubtitleStream(ctx context.Context, partID, streamID int) error
- func (c *Client) SharedUserTokens(ctx context.Context, machineIdentifier string) ([]SharedServerXML, error)
- func (c *Client) ShowEpisodes(ctx context.Context, rk RatingKey) ([]streams.Episode, error)
- func (c *Client) ShowMetadata(ctx context.Context, rk RatingKey) (*Show, error)
- func (c *Client) ShowSections(ctx context.Context) ([]Section, error)
- func (c *Client) Token() string
- func (c *Client) UserFromSession(ctx context.Context, clientIdentifier string) (userID, username string, err error)
- type HTTPStatusError
- type HistoryItem
- type RatingKey
- type Season
- type Section
- type ServerIdentity
- type Session
- type SharedServerXML
- type SharedServersXML
- type Show
- type User
Constants ¶
const ( // TypeEpisode is the Plex metadata "type" string for episode items, // used when filtering MediaContainer responses by item type. TypeEpisode = "episode" // MetadataTypeEpisode is the numeric type ID for episode items used // in /library/sections/{id}/all?type=... URL parameters. MetadataTypeEpisode = 4 // SectionTypeShow is the Plex library-section "type" string for TV // show sections, used when filtering library sections to TV shows // only. SectionTypeShow = "show" )
Plex wire-protocol constants. These strings/numbers appear in the Plex HTTP API and are a frozen wire contract. Consumers (main, config, scheduler, notify, sync, this package's own library.go) import these rather than redeclaring them locally.
Variables ¶
var ErrNotFound = errors.New("not found")
ErrNotFound is returned when Plex responds with 404 (missing metadata / session / etc.). Callers detect it with errors.Is(err, plex.ErrNotFound).
Functions ¶
func SwapTVClient ¶
SwapTVClient replaces the package-level plex.tv HTTP client with the supplied one and returns a function that restores the original. Intended for tests that need to point shared-server lookups at a local httptest server; production code never calls this.
func WarnIfPlaintextURL ¶
WarnIfPlaintextURL emits a startup warning when the Plex URL is http:// to a non-loopback, non-docker-DNS host. In that case the X-Plex-Token header transits the network unencrypted. Trusted on a LAN-only proxy bridge, but dangerous when the published image is pointed at a remote Plex server without a TLS proxy.
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is an HTTP client for a single Plex Media Server base URL + auth token. Use NewClient or NewClientForUser.
func NewClient ¶
NewClient parses serverURL, validates scheme, and returns a Client configured with the given token and TLS behaviour. When caCertPath is non-empty, the PEM file at that path is loaded into the TLS RootCAs pool so verification stays ON, pinned to that CA — recommended for users with self-signed Plex certificates. Empty caCertPath uses the OS trust store (works for plex.direct + any publicly-issued cert; works as a no-op for plain http:// URLs). Returns an error on invalid URL, unsupported scheme, missing cert file, or unparseable PEM; the caller (main.go) is responsible for logging and exiting.
func NewClientForUser ¶
NewClientForUser creates a Client using a different token but the same server base URL and TLS settings as an existing client. Same caCertPath semantics as NewClient.
func NewClientFromHTTP ¶
NewClientFromHTTP builds a Client from an already-parsed base URL and a caller-supplied http.Client. Intended for tests that want to point a Client at an httptest.Server — production code should use NewClient.
func (*Client) BaseURL ¶
BaseURL returns the server's base URL. Used by callers that need to derive a websocket URL or log the host.
func (*Client) DisableSubtitles ¶
DisableSubtitles turns subtitles off for a media part.
func (*Client) Episode ¶
Episode fetches episode (or any library item) metadata by rating key. Returns ErrNotFound when the item is missing. /library/metadata/{key} is type-agnostic; ShowMetadata wraps this variant for show-level lookups.
func (*Client) HTTPClient ¶
HTTPClient returns the underlying *http.Client. Exposed so the WebSocket listener can dial the notifications endpoint with the same transport (matching CA-trust, timeouts, and redirect policy) rather than spinning up a second client.
func (*Client) History ¶
History fetches recent play history since the given unix timestamp.
Plex supports filter operators on many fields; the documented syntax for "viewedAt >= X" is literally `viewedAt>=X` with a single `>` and a literal (unencoded) operator. A prior version used `viewedAt>>=` (double `>`), which Plex silently ignores — the server returned the full history (21k+ entries on a long-lived server), overflowed the 10 MB read cap in doJSON, and surfaced as a daily WARN ("unexpected end of JSON input") in Loki. Go's url.Parse preserves `>=` as-is, so the single-char fix correctly reaches the server and the response is filtered server-side.
func (*Client) LoggedUser ¶
LoggedUser resolves the admin user by looking up the myplex account username and matching it against the system accounts list.
func (*Client) RecentlyAdded ¶
func (c *Client) RecentlyAdded(ctx context.Context, sectionKey RatingKey, sinceUnix int64) ([]streams.Episode, error)
RecentlyAdded fetches recently added episodes from a library section, filtered server-side by addedAt >= sinceUnix.
func (*Client) SeasonEpisodes ¶
SeasonEpisodes returns the episodes of a single season (children).
func (*Client) ServerIdentity ¶
func (c *Client) ServerIdentity(ctx context.Context) (*ServerIdentity, error)
ServerIdentity returns the Plex server's identity (friendly name, machine ID, version) from GET /.
func (*Client) SetAudioStream ¶
SetAudioStream selects the audio stream for a media part.
func (*Client) SetSubtitleStream ¶
SetSubtitleStream selects the subtitle stream for a media part.
func (*Client) SharedUserTokens ¶
func (c *Client) SharedUserTokens(ctx context.Context, machineIdentifier string) ([]SharedServerXML, error)
SharedUserTokens fetches shared user tokens from the plex.tv shared_servers endpoint. This calls the plex.tv API (not the local server) and always uses full TLS verification (there is no skip option) — plex.tv is a public endpoint and the admin token must never be forwarded through a skipped-verification transport or a redirect.
func (*Client) ShowEpisodes ¶
ShowEpisodes returns every episode in a show (allLeaves).
func (*Client) ShowMetadata ¶
ShowMetadata fetches the show-level metadata (labels, library) for a show. /library/metadata/{key} returns whatever type the key points to, so this delegates to the same endpoint as Episode but decodes into *Show. Split off from Episode: a show response does not have Media/Part/Stream, so typing it as *Show instead of *Episode keeps the field set honest for callers (e.g. shouldIgnoreShow reads only LibraryTitle + Label).
func (*Client) ShowSections ¶
ShowSections returns the TV-show library sections.
type HTTPStatusError ¶ added in v1.5.7
HTTPStatusError is returned for a non-200, non-404 Plex response. It carries the status code so callers can classify the failure: a 4xx (bad token / auth / wrong endpoint) will not self-heal, while a 5xx (Plex up but not ready) may recover. The startup connect classifier in package main uses errors.As to distinguish fatal (4xx) from transient (5xx) initial-connection failures.
func (*HTTPStatusError) Error ¶ added in v1.5.7
func (e *HTTPStatusError) Error() string
type HistoryItem ¶
type HistoryItem struct {
RatingKey string `json:"ratingKey"`
Type string `json:"type"`
LibraryTitle string `json:"librarySectionTitle"`
AccountID streams.FlexInt `json:"accountID"`
LibrarySectionID streams.FlexInt `json:"librarySectionID"`
}
HistoryItem is one entry from GET /status/sessions/history/all.
type RatingKey ¶
type RatingKey string
RatingKey is a typed Plex ratingKey — the opaque numeric string Plex uses to address episodes, seasons, shows, and other library items. The on-disk and wire representation is always a string; this type exists to prevent ratingKey values from being conflated with other string keys (userID, sessionKey) at module boundaries and to give callers a single place to validate that a value is a well-formed numeric key.
Methods on RatingKey intentionally avoid allocation: String returns the underlying string, and Validate parses without copying. The api.PlexReader interface and the *plex.Client methods (Episode, ShowEpisodes, SeasonEpisodes, ShowMetadata, RecentlyAdded) take RatingKey at the boundary so validation happens once via RatingKey.Validate rather than being repeated per-method with strconv.Atoi. Wire-origin strings (streams.Episode.RatingKey, plex.Section.Key, plex.HistoryItem.RatingKey) stay typed as string in their struct definitions — the plex.RatingKey wrap happens at the call site, which preserves the Plex JSON wire format.
func (RatingKey) String ¶
String returns the ratingKey as a plain string for APIs that accept strings (HTTP path interpolation, log values, cache keys).
func (RatingKey) Validate ¶
Validate reports whether the ratingKey is a non-empty numeric string. Plex ratingKeys are always numeric strings in practice; a malformed key indicates a programming error (e.g., a userID leaked into a ratingKey slot) that is worth surfacing rather than forwarding to the Plex API as a malformed URL path.
The error format is deliberately `invalid rating key %q` — byte-for- byte identical to the five strconv.Atoi+fmt.Errorf stanzas it replaces in library.go (Episode, ShowEpisodes, SeasonEpisodes, ShowMetadata, RecentlyAdded). That error text is a stable log-key contract that scrapers may grep for; keeping it byte-for-byte means no Loki query or dashboard breaks.
type Season ¶
type Season struct {
RatingKey string `json:"ratingKey"`
ParentRatingKey string `json:"parentRatingKey"`
Title string `json:"title"`
Index streams.FlexInt `json:"index"`
}
Season is the season-level metadata returned by GET /library/metadata/{key} when the key points to a season. Split off from Episode for callers that only need the navigational spine (parent key, season index) without the whole media/part/stream graph.
type Section ¶
type Section struct {
Key string `json:"key"`
Title string `json:"title"`
Type string `json:"type"`
}
Section is a library section returned by GET /library/sections.
type ServerIdentity ¶
type ServerIdentity struct {
FriendlyName string `json:"friendlyName"`
MachineIdentifier string `json:"machineIdentifier"`
Version string `json:"version"`
}
ServerIdentity is returned by GET /.
type Session ¶
type Session struct {
User struct {
ID string `json:"id"`
Title string `json:"title"`
} `json:"User"`
Player struct {
MachineIdentifier string `json:"machineIdentifier"`
} `json:"Player"`
}
Session represents a single active session from GET /status/sessions.
type SharedServerXML ¶
type SharedServerXML struct {
}
SharedServerXML is one <SharedServer> element from shared_servers.
type SharedServersXML ¶
type SharedServersXML struct {
}
SharedServersXML is the XML response from plex.tv shared_servers.
type Show ¶
type Show struct {
RatingKey string `json:"ratingKey"`
Title string `json:"title"`
LibraryTitle string `json:"librarySectionTitle"`
Label []streams.Label `json:"Label"`
LibrarySectionID streams.FlexInt `json:"librarySectionID"`
}
Show is the show-level metadata returned by GET /library/metadata/{key} when the key points to a TV show. Split off from Episode so callers asking "what are the show's labels?" don't receive an Episode-typed value.