Documentation
¶
Overview ¶
Package plextv provides two main components.
Firstly, it provides Config, which implements all Plex authentication flows covered in the Plex API documentation: JWT Authentication (Recommended) and Traditional Token Authentication (Legacy). For legacy tokens, both username/password and PIN flows are supported.
Config implements these in an approach similar to oauth2, though Plex authentication is not compatible with oauth2 itself.
Secondly, this component provides a Client to interact with plex.tv's API. It uses Config to authenticate itself with plex.tv. Currently, it only supports the /api/v2/user and /devices.xml endpoints. More may be added in the future.
Index ¶
- Variables
- func ContextWithHTTPClient(ctx context.Context, httpClient *http.Client) context.Context
- func ParsePlexError(r *http.Response) error
- type Client
- type Config
- func (c Config) Client(ctx context.Context, src TokenSource) Client
- func (c Config) GenerateAndUploadPublicKey(ctx context.Context, token Token) (ed25519.PrivateKey, string, error)
- func (c Config) JWTToken(ctx context.Context, privateKey ed25519.PrivateKey, keyID string) (Token, error)
- func (c Config) PINRequest(ctx context.Context) (PINResponse, string, error)
- func (c Config) RegisterWithCredentials(ctx context.Context, username, password string) (Token, error)
- func (c Config) RegisterWithPIN(ctx context.Context, callback func(PINResponse, string), ...) (token Token, err error)
- func (c Config) TokenSource(opts ...TokenSourceOption) TokenSource
- func (c Config) UploadPublicKey(ctx context.Context, publicKey ed25519.PublicKey, token Token) (string, error)
- func (c Config) ValidatePIN(ctx context.Context, id int) (Token, ValidatePINResponse, error)
- func (c Config) WithClientID(clientID string) Config
- func (c Config) WithDevice(device Device) Config
- type Connection
- type Device
- type ErrInvalidToken
- type JWTSecureData
- type JWTSecureDataStore
- type PINResponse
- type PlexError
- type PlexTVDevice
- type PlexTimestamp
- type RegisteredDevice
- type Resource
- type SyncList
- type Token
- type TokenSource
- type TokenSourceOption
- func WithCredentials(username, password string) TokenSourceOption
- func WithJWT(store JWTSecureDataStore) TokenSourceOption
- func WithLogger(logger *slog.Logger) TokenSourceOption
- func WithPIN(cb func(PINResponse, string), pollInterval time.Duration) TokenSourceOption
- func WithToken(token Token) TokenSourceOption
- type User
- type ValidatePINResponse
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( // ErrInvalidClientID indicates that the data in a JWTSecureDataStore is for a different Client ID // than the one used to register the device. // The stored private key and public key ID can't be used to generate a new JWT token. // The client needs to re-register the device with a new Client ID. ErrInvalidClientID = fmt.Errorf("data store contains invalid client ID") // ErrNoTokenSource indicates that a token source needs a child token source, but none was provided. // A typical example is JWTTokenSource needing a registrar to get a legacy token, but none is provided in // [Config.TokenSource]. ErrNoTokenSource = errors.New("no token source provided") ErrUnauthorized = errors.New("user could not be authenticated") // ErrTooManyRequests indicates that the plex.tv API rate limit has been reached. // Typically, this only happens when generating a new JWT token. ErrTooManyRequests = errors.New("too many requests") // ErrJWKMissing indicates that the JWT token request could not find a public key to verify the JWT request. // Typically, this means the Registered Device for the associated Client ID has been removed from // Plex's Registered Devices. // The client needs to re-register the device with a new Client ID and a new public/private key pair. ErrJWKMissing = errors.New("jwk missing. no public key to verify jwt request") // ErrExpiredToken indicates that the provided JWT token has expired. ErrExpiredToken = errors.New("token expired") )
Functions ¶
func ContextWithHTTPClient ¶
ContextWithHTTPClient returns a new context with an added HTTP client. When passed to Config's methods, they use that HTTP client to perform their authentication calls. If no HTTP client is set, a default HTTP client is used.
func ParsePlexError ¶
ParsePlexError parses the errors text returned by plex.tv and return a PlexError.
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client interacts with the plex.tv API.
Currently, only supports /api/v2/user and /devices.xml endpoints.
func (Client) MediaServers ¶
func (c Client) MediaServers(ctx context.Context) ([]RegisteredDevice, error)
MediaServers returns all Plex Media Servers registered under the provided token
func (Client) RegisteredDevices ¶
func (c Client) RegisteredDevices(ctx context.Context) ([]RegisteredDevice, error)
RegisteredDevices returns all devices registered under the provided token
type Config ¶
type Config struct {
// Device information used during username/password authentication.
Device Device
// URL is the base URL of the legacy Plex authentication endpoint.
// Defaults to https://plex.tv and should not need to be changed.
URL string
// V2URL is the base URL of the new Plex authentication endpoint.
// Defaults to https://clients.plex.tv and should not need to be changed.
//
// Note: the [Plex API documentation] is not consistent in its use of https://clients.plex.tv vs https://plex.tv.
// The implementation here follows the specifications as much as possible, but changes may be required in the future.
//
// [Plex API documentation]: https://developer.plex.tv/pms
V2URL string
// ClientID is the unique identifier of the client application.
ClientID string
// Scopes is a list of scopes to request.
// This may become non-exported in the future.
Scopes []string
// contains filtered or unexported fields
}
Config contains the configuration required to authenticate with Plex.
func DefaultConfig ¶
func DefaultConfig() Config
DefaultConfig returns a Config with default values.
func (Config) Client ¶
func (c Config) Client(ctx context.Context, src TokenSource) Client
Client returns a Client that uses the provided TokenSource to authenticate itself with plex.tv.
The returned client will use the http.Client associated with the provided context to make requests, or a default one if none is set.
Example (Credentials) ¶
package main
import (
"context"
"github.com/clambin/mediaclients/plex/plextv"
)
// config contains the attributes that will be registered for the device with the provided client id.
var config = plextv.DefaultConfig().
WithClientID("my-unique-client-id").
WithDevice(plextv.Device{
Product: "my product",
Version: "v0.0.4",
Platform: "my platform",
PlatformVersion: "my platform version",
Device: "my device",
Model: "my device model",
DeviceVendor: "my device vendor name",
DeviceName: "my device name",
Provides: "controller",
})
func main() {
// create a token source that uses the PIN flow to authenticate the device with plex.tv.
src := config.TokenSource(plextv.WithCredentials("plex-username", "plex-password"))
// create a plex.tv client with the provided token source.
ctx := context.Background()
_ = config.Client(ctx, src)
}
Example (Jwt) ¶
package main
import (
"context"
"github.com/clambin/mediaclients/plex/plextv"
"github.com/clambin/mediaclients/plex/vault"
)
// config contains the attributes that will be registered for the device with the provided client id.
var config = plextv.DefaultConfig().
WithClientID("my-unique-client-id").
WithDevice(plextv.Device{
Product: "my product",
Version: "v0.0.4",
Platform: "my platform",
PlatformVersion: "my platform version",
Device: "my device",
Model: "my device model",
DeviceVendor: "my device vendor name",
DeviceName: "my device name",
Provides: "controller",
})
func main() {
// jwt requires persistence to store the private key for the device's client id.
// vault provides a basic encrypted file to securely store the device's private data.
v := vault.New[plextv.JWTSecureData](config.ClientID+".enc", "my-secret-passphrase")
// create a token source that will use the provided credentials to authenticate with plextv the first time.
// it then registers a public key with plextv and requests a JWT token using the private key.
//
// Note: the JWT flow requires an initial valid token to publish its public key. This can be either through
// credentials or PIN flow. Once JWT authentication is enabled, you can't use credentials or PIN anymore for
// the device's ClientIdentifier.
src := config.TokenSource(
plextv.WithCredentials("plex-username", "plex-password"),
plextv.WithJWT(v),
)
// create a plex.tv client with the provided token source.
ctx := context.Background()
_ = config.Client(ctx, src)
}
Example (Pin) ¶
package main
import (
"context"
"fmt"
"time"
"github.com/clambin/mediaclients/plex/plextv"
)
// config contains the attributes that will be registered for the device with the provided client id.
var config = plextv.DefaultConfig().
WithClientID("my-unique-client-id").
WithDevice(plextv.Device{
Product: "my product",
Version: "v0.0.4",
Platform: "my platform",
PlatformVersion: "my platform version",
Device: "my device",
Model: "my device model",
DeviceVendor: "my device vendor name",
DeviceName: "my device name",
Provides: "controller",
})
func main() {
// create a token source that uses the PIN flow to authenticate the device with plex.tv.
src := config.TokenSource(
plextv.WithPIN(
// the callback to ask the user to log in
func(_ plextv.PINResponse, url string) {
fmt.Println("Confirm login request:", url)
},
// the interval to poll for the PIN Response
10*time.Second,
),
)
// create a plex.tv client with the provided token source.
ctx := context.Background()
_ = config.Client(ctx, src)
}
func (Config) GenerateAndUploadPublicKey ¶
func (c Config) GenerateAndUploadPublicKey(ctx context.Context, token Token) (ed25519.PrivateKey, string, error)
GenerateAndUploadPublicKey is a helper function to set up JWT Tokens. It generates a new ed25519 keypair, uploads the private key to the Plex server and returns the private key and associated public key ID to be used for generating a new JWT token.
Token must be a valid Plex token, either generated by Config.RegisterWithCredentials/Config.RegisterWithPIN or obtained from a previous Config.JWTToken call.
func (Config) JWTToken ¶
func (c Config) JWTToken(ctx context.Context, privateKey ed25519.PrivateKey, keyID string) (Token, error)
JWTToken is a new authentication mechanism introduced in plex.tv, based on JSON Web Tokens (JWT).
JWTTokens increase security by eliminating the need for a PIN or username/password combination each time a client starts. As setting up JWT requires a valid token, a client only needs to register once.
To create a JWTToken, a client generates a new ed25519 keypair and uploads the public key to Plex (using Config.GenerateAndUploadPublicKey or Config.UploadPublicKey, using a valid Plex token). The client can then use the private key and the public key's ID to generate a new JWTToken.
This does require persistence, as the Client ID, private key, and public key ID must be kept in sync with plex.tv: once a JWTToken has been requested for the ClientID, further requests to re-register that ClientID (Config.RegisterWithCredentials/Config.RegisterWithPIN) will fail. You will need to generate a new ClientID and re-register.
JWTTokens are valid for 7 days.
Note: a JWTToken can only be used to access the plex.tv API; it cannot be used to access Plex Media Servers.
func (Config) PINRequest ¶
PINRequest requests a PINRequest from Plex.
Currently only supports strong=false. Support for strong=true is planned, but this requires https://app.plex.tv/auth, which is currently broken.
func (Config) RegisterWithCredentials ¶
func (c Config) RegisterWithCredentials(ctx context.Context, username, password string) (Token, error)
RegisterWithCredentials registers a device using username/password credentials and returns a Token.
func (Config) RegisterWithPIN ¶
func (c Config) RegisterWithPIN(ctx context.Context, callback func(PINResponse, string), pollInterval time.Duration) (token Token, err error)
RegisterWithPIN is a helper function that registers a device using the PIN authentication flow and gets a Token. It requests a PIN from Plex, calls the callback with the PINResponse and PIN URL and blocks until the PIN is confirmed. Use a context with a timeout to ensure it doesn't block forever.
The callback can be used to inform the user/application of the URL to confirm the PINRequest.
func (Config) TokenSource ¶
func (c Config) TokenSource(opts ...TokenSourceOption) TokenSource
TokenSource returns a TokenSource in line with the provided TokenSource options.
func (Config) UploadPublicKey ¶
func (c Config) UploadPublicKey(ctx context.Context, publicKey ed25519.PublicKey, token Token) (string, error)
UploadPublicKey uploads a public key to the Plex server. It returns a generated key ID for the public key, which can be used to generate a new token with Config.JWTToken.
func (Config) ValidatePIN ¶
ValidatePIN checks if the user has confirmed the PINRequest. It returns the full Plex response. When the user has confirmed the PINRequest, the AuthToken field will be populated.
func (Config) WithClientID ¶
WithClientID sets the Client ID.
func (Config) WithDevice ¶
WithDevice sets the device information used during username/password and pin authentication.
See the Device type for details on what each field means.
Limitation: currently the Device attributes are only registered when the device is registered // (during Config.RegisterWithCredentials or Config.RegisterWithPIN). If the attributes change // after registration (e.g., the Version is updated), this is not (yet) reflected in the registered // device on plex.tv.
type Connection ¶
type Connection struct {
URI string `xml:"uri,attr"`
}
type Device ¶
type Device struct {
// Product is the name of the client product.
// Passed as X-Plex-Product header.
// In Authorized Devices, it is shown on line 3.
Product string
// Version is the version of the client application.
// Passed as X-Plex-Version header.
// In Authorized Devices, it is shown on line 2.
Version string
// Platform is the operating system or compiler of the client application.
// Passed as X-Plex-Platform header.
Platform string
// PlatformVersion is the version of the platform.
// Passed as X-Plex-Platform-Version header.
PlatformVersion string
// Device is a relatively friendly name for the client device.
// Passed as X-Plex-Device header.
// In Authorized Devices, it is shown on line 4.
Device string
// Model is a potentially less friendly identifier for the device model.
// Passed as X-Plex-Model header.
Model string
// DeviceVendor is the name of the device vendor.
// Passed as X-Plex-Device-Vendor header.
DeviceVendor string
// DeviceName is a friendly name for the client.
// Passed as X-Plex-Device-Name header.
// In Authorized Devices, it is shown on line 1.
DeviceName string
// Provides describes the type of device.
// Passed as X-Plex-Provides header.
Provides string
}
Device identifies the client when using Plex username/password credentials. Although this package provides a default, it is recommended to set this yourself.
Limitation: currently the Device attributes are only registered when the device is registered (during Config.RegisterWithCredentials or Config.RegisterWithPIN). If the attributes change after registration (e.g., the Version is updated), this is not (yet) reflected in the registered device on plex.tv.
type ErrInvalidToken ¶
type ErrInvalidToken struct {
// contains filtered or unexported fields
}
ErrInvalidToken indicates that a Config method was passed an invalid token.
func (*ErrInvalidToken) Error ¶
func (e *ErrInvalidToken) Error() string
func (*ErrInvalidToken) Unwrap ¶
func (e *ErrInvalidToken) Unwrap() error
type JWTSecureData ¶
type JWTSecureData struct {
KeyID string `json:"key-id"`
ClientID string `json:"client-id"`
PrivateKey ed25519.PrivateKey `json:"private-key"`
}
JWTSecureData contains the data required to request a JWTToken.
type JWTSecureDataStore ¶
type JWTSecureDataStore interface {
Save(data JWTSecureData) error
Load() (JWTSecureData, error)
}
type PINResponse ¶
type PINResponse struct {
CreatedAt time.Time `json:"createdAt"`
ExpiresAt time.Time `json:"expiresAt"`
AuthToken interface{} `json:"authToken"`
NewRegistration interface{} `json:"newRegistration"`
Code string `json:"code"`
Product string `json:"product"`
Qr string `json:"qr"`
ClientIdentifier string `json:"clientIdentifier"`
Location struct {
Code string `json:"code"`
ContinentCode string `json:"continent_code"`
Country string `json:"country"`
City string `json:"city"`
TimeZone string `json:"time_zone"`
PostalCode string `json:"postal_code"`
Subdivisions string `json:"subdivisions"`
Coordinates string `json:"coordinates"`
EuropeanUnionMember bool `json:"european_union_member"`
InPrivacyRestrictedCountry bool `json:"in_privacy_restricted_country"`
InPrivacyRestrictedRegion bool `json:"in_privacy_restricted_region"`
} `json:"location"`
Id int `json:"id"`
ExpiresIn int `json:"expiresIn"`
Trusted bool `json:"trusted"`
}
PINResponse is the response from the PINRequest endpoint
type PlexError ¶
type PlexTVDevice ¶
type PlexTVDevice struct {
CreatedAt time.Time `json:"createdAt"`
LastSeenAt time.Time `json:"lastSeenAt"`
Platform *string `json:"platform"`
Device *string `json:"device"`
Model *string `json:"model"`
Vendor *string `json:"vendor"`
Provides *string `json:"provides"`
PlatformVersion *string `json:"platformVersion"`
ScreenDensity *int `json:"screenDensity"`
Name string `json:"name"`
Product string `json:"product"`
Token string `json:"token"`
PublicAddress string `json:"publicAddress"`
ClientIdentifier string `json:"clientIdentifier"`
ScreenResolution string `json:"screenResolution"`
SyncLists []struct {
Version int `json:"version"`
ItemsCompleteCount int `json:"itemsCompleteCount"`
TotalSize int `json:"totalSize"`
} `json:"syncLists"`
Connections []struct {
Uri string `json:"uri"`
} `json:"connections"`
Id int `json:"id"`
Presence bool `json:"presence"`
}
PlexTVDevice represents a device registered on PlexTV. It is the response from the /api/v2/devices endpoint.
type PlexTimestamp ¶
PlexTimestamp is a custom type for parsing Plex timestamps. It's mainly used by legacy API endpoints.
func (*PlexTimestamp) UnmarshalXMLAttr ¶
func (t *PlexTimestamp) UnmarshalXMLAttr(attr xml.Attr) error
type RegisteredDevice ¶
type RegisteredDevice struct {
CreatedAt PlexTimestamp `xml:"createdAt,attr"`
LastSeenAt PlexTimestamp `xml:"lastSeenAt,attr"`
SyncList *SyncList `xml:"SyncList"`
// Attributes
Name string `xml:"name,attr"`
PublicAddress string `xml:"publicAddress,attr"`
Product string `xml:"product,attr"`
ProductVersion string `xml:"productVersion,attr"`
Platform string `xml:"platform,attr"`
PlatformVersion string `xml:"platformVersion,attr"`
Device string `xml:"device,attr"`
Model string `xml:"model,attr"`
Vendor string `xml:"vendor,attr"`
Provides string `xml:"provides,attr"`
ClientID string `xml:"clientIdentifier,attr"`
Version string `xml:"version,attr"`
ID string `xml:"id,attr"`
Token string `xml:"token,attr"`
ScreenRes string `xml:"screenResolution,attr"`
ScreenDensity string `xml:"screenDensity,attr"`
// Optional nested elements
Connections []Connection `xml:"Connection"`
}
RegisteredDevice represents a registered device on Plex.
type Resource ¶
type Resource struct {
CreatedAt time.Time `json:"createdAt"`
LastSeenAt time.Time `json:"lastSeenAt"`
OwnerId interface{} `json:"ownerId"`
SourceTitle interface{} `json:"sourceTitle"`
Name string `json:"name"`
Product string `json:"product"`
ProductVersion string `json:"productVersion"`
Platform string `json:"platform"`
PlatformVersion string `json:"platformVersion"`
Device string `json:"device"`
ClientIdentifier string `json:"clientIdentifier"`
Provides string `json:"provides"`
PublicAddress string `json:"publicAddress"`
AccessToken string `json:"accessToken"`
Connections []struct {
Protocol string `json:"protocol"`
Address string `json:"address"`
Uri string `json:"uri"`
Port int `json:"port"`
Local bool `json:"local"`
Relay bool `json:"relay"`
IPv6 bool `json:"IPv6"`
} `json:"connections"`
SearchEnabled bool `json:"searchEnabled"`
Owned bool `json:"owned"`
Home bool `json:"home"`
Synced bool `json:"synced"`
Relay bool `json:"relay"`
Presence bool `json:"presence"`
HttpsRequired bool `json:"httpsRequired"`
PublicAddressMatches bool `json:"publicAddressMatches"`
DnsRebindingProtection bool `json:"dnsRebindingProtection"`
NatLoopbackSupported bool `json:"natLoopbackSupported"`
}
Resource represents a registered device on Plex. It's the response to /api/v2/resources endpoint.
Use the AccessToken to interact with the PMS instance and the list of connection URLs to locate it. Connections labeled as local should be preferred over those that are not, and relay should only be used as a last resort as bandwidth on relay connections is limited.
type Token ¶
type Token string
Token represents a Plex authentication token. It can be either a legacy token (20-character string) or a JWT. Note: JWTs currently cannot be used to access Plex Media Servers.
func (Token) IsJWT ¶
IsJWT returns true if the token is a JWT. Note: returns true even if the token is invalid (e.g. expired).
type TokenSource ¶
TokenSource is the common interface for all plex.tv authentication flows. Currently supported flows are username/password, PIN, and JWT.
type TokenSourceOption ¶
type TokenSourceOption func(*tokenSourceConfiguration)
TokenSourceOption provides the configuration to create the desired TokenSource.
func WithCredentials ¶
func WithCredentials(username, password string) TokenSourceOption
WithCredentials uses the given credentials to register a device and get a token.
func WithJWT ¶
func WithJWT(store JWTSecureDataStore) TokenSourceOption
WithJWT configures the TokenSource to use a JWT token to request a token.
Using JWT requires persistence. storePath is the path to where the secure data will be stored; passphrase is the passphrase used to encrypt the secure data.
Note: once you set up JWT authentication, you can't use credentials or PIN anymore for the device's ClientIdentifier. If you lose the secure data stored at storePath, you'll need to re-register the device with a new ClientIdentifier.
Note 2: JWT tokens are relatively new. And in my experience, their use is not always intuitive. The main advantage right now is that a JWT-enabled TokenSource does not reregister each time it starts. But it comes with an operational burden (the need for persistent data) and some risk. Approach with caution. See Config.JWTToken for more details.
func WithLogger ¶
func WithLogger(logger *slog.Logger) TokenSourceOption
WithLogger configures an optional logger.
func WithPIN ¶
func WithPIN(cb func(PINResponse, string), pollInterval time.Duration) TokenSourceOption
WithPIN uses the PIN flow to register a device and get a token. Use the callback to inform the user of the PIN URL and to confirm the PIN.
func WithToken ¶
func WithToken(token Token) TokenSourceOption
WithToken configures a TokenSource to use an existing, fixed token.
type User ¶
type User struct {
Profile struct {
DefaultAudioLanguages interface{} `json:"defaultAudioLanguages"`
DefaultSubtitleLanguages interface{} `json:"defaultSubtitleLanguages"`
MediaReviewsLanguages interface{} `json:"mediaReviewsLanguages"`
DefaultAudioLanguage string `json:"defaultAudioLanguage"`
DefaultSubtitleLanguage string `json:"defaultSubtitleLanguage"`
DefaultAudioAccessibility int `json:"defaultAudioAccessibility"`
AutoSelectSubtitle int `json:"autoSelectSubtitle"`
DefaultSubtitleAccessibility int `json:"defaultSubtitleAccessibility"`
DefaultSubtitleForced int `json:"defaultSubtitleForced"`
WatchedIndicator int `json:"watchedIndicator"`
MediaReviewsVisibility int `json:"mediaReviewsVisibility"`
AutoSelectAudio bool `json:"autoSelectAudio"`
} `json:"profile"`
Locale interface{} `json:"locale"`
AttributionPartner interface{} `json:"attributionPartner"`
Uuid string `json:"uuid"`
Username string `json:"username"`
Title string `json:"title"`
Email string `json:"email"`
FriendlyName string `json:"friendlyName"`
Thumb string `json:"thumb"`
AuthToken string `json:"authToken"`
MailingListStatus string `json:"mailingListStatus"`
ScrobbleTypes string `json:"scrobbleTypes"`
Country string `json:"country"`
SubscriptionDescription string `json:"subscriptionDescription"`
Subscription struct {
SubscribedAt time.Time `json:"subscribedAt"`
Status string `json:"status"`
PaymentService string `json:"paymentService"`
Plan string `json:"plan"`
Features []string `json:"features"`
Active bool `json:"active"`
} `json:"subscription"`
Entitlements []string `json:"entitlements"`
Roles []string `json:"roles"`
Services []struct {
Identifier string `json:"identifier"`
Endpoint string `json:"endpoint"`
Token *string `json:"token"`
Secret *string `json:"secret"`
Status string `json:"status"`
} `json:"services"`
Id int `json:"id"`
JoinedAt int `json:"joinedAt"`
HomeSize int `json:"homeSize"`
MaxHomeSize int `json:"maxHomeSize"`
RememberExpiresAt int `json:"rememberExpiresAt"`
AdsConsentSetAt int `json:"adsConsentSetAt"`
AdsConsentReminderAt int `json:"adsConsentReminderAt"`
Confirmed bool `json:"confirmed"`
EmailOnlyAuth bool `json:"emailOnlyAuth"`
HasPassword bool `json:"hasPassword"`
Protected bool `json:"protected"`
MailingListActive bool `json:"mailingListActive"`
Restricted bool `json:"restricted"`
Anonymous bool `json:"anonymous"`
Home bool `json:"home"`
Guest bool `json:"guest"`
HomeAdmin bool `json:"homeAdmin"`
AdsConsent bool `json:"adsConsent"`
ExperimentalFeatures bool `json:"experimentalFeatures"`
TwoFactorEnabled bool `json:"twoFactorEnabled"`
BackupCodesCreated bool `json:"backupCodesCreated"`
}
User represents a Plex TV user. It is the response from the /api/v2/user endpoint.
type ValidatePINResponse ¶
type ValidatePINResponse struct {
CreatedAt time.Time `json:"createdAt"`
ExpiresAt time.Time `json:"expiresAt"`
NewRegistration any `json:"newRegistration"`
AuthToken *string `json:"authToken"`
Code string `json:"code"`
Product string `json:"product"`
Qr string `json:"qr"`
ClientIdentifier string `json:"clientIdentifier"`
Location struct {
Code string `json:"code"`
ContinentCode string `json:"continent_code"`
Country string `json:"country"`
City string `json:"city"`
TimeZone string `json:"time_zone"`
PostalCode string `json:"postal_code"`
Subdivisions string `json:"subdivisions"`
Coordinates string `json:"coordinates"`
EuropeanUnionMember bool `json:"european_union_member"`
InPrivacyRestrictedCountry bool `json:"in_privacy_restricted_country"`
InPrivacyRestrictedRegion bool `json:"in_privacy_restricted_region"`
} `json:"location"`
Id int `json:"id"`
ExpiresIn int `json:"expiresIn"`
Trusted bool `json:"trusted"`
}
ValidatePINResponse is the response from the ValidatePIN endpoint. When AuthToken is not null, the user has been authenticated.