README
¶
mediabrowser
a limited API client for Jellyfin/Emby, with a focus on User management as used in jfa-go.
go get github.com/hrfee/mediabrowser
The below example can also be found in example/example.go
.
// EXAMPLE: Find and return the last activity date of user "john".
package main
import (
"log"
"github.com/hrfee/mediabrowser"
)
const (
address = "https://jellyf.in:8097"
noFail = true
cacheTimeout = 30 // Reload cache 30 minutes after most recent load.
serverType = mediabrowser.JellyfinServer
// Authenticates with username/pass as some operations aren't possible with an API key.
username = "accounts"
password = "xxxxxx"
// Below values appear in the Jellyfin/Emby dashboard.
client = "mediabrowser-example"
version = "v0.0.0"
device = "mb-test-device"
deviceID = "mb-test-device-id"
)
func main() {
timeoutHandler := mediabrowser.NewNamedTimeoutHandler("Jellyfin", address, noFail)
mb, _ := mediabrowser.NewServer(
serverType,
address,
client,
version,
device,
deviceID,
timeoutHandler,
cacheTimeout,
)
_, status, err := mb.Authenticate(username, password)
if err != nil || status != 200 {
log.Fatalf("Failed to authenticate: Status %d Error %v", status, err)
}
user, status, err := mb.UserByName("john", false)
if user.Name == "" || err != nil || status != 200 {
log.Fatalf("Couldn't find user: Status %d Error %v", status, err)
}
log.Printf("User %s was last active %v", user.Name, user.LastActivityDate)
}
Contributions
Contributions are welcome, and don't have to be user related. Try to group related functions into files named <category>_<emby/jf/shared>.go
. If functions aren't shared between jellyfin & emby, write them as normal functions and add a wrapper receiver method to mediabrowser.go
.
Documentation
¶
Overview ¶
Package mediabrowser provides user-related bindings to the Jellyfin & Emby APIs. Some data aren't bound to structs as jfa-go doesn't need to interact with them, for example DisplayPreferences. See Jellyfin/Emby swagger docs for more info on them.
Index ¶
- Constants
- func DeNullConfiguration(c *Configuration)
- func DeNullLibraryOptions(lo *LibraryOptions)
- func DeNullPolicy(p *Policy)
- func DeNullVirtualFolder(vf *VirtualFolder)
- type AddMedia
- type AuthenticationResult
- type Configuration
- type DetailedError
- type ErrForbidden
- type ErrNoPolicySupplied
- type ErrNotFound
- type ErrUnauthorized
- type ErrUnknown
- type ErrUserNotFound
- type ImageOptions
- type LibraryOptions
- type MediaBrowser
- func (mb *MediaBrowser) AddFolder(refreshLibrary bool, AddMedia AddMedia) (int, error)
- func (mb *MediaBrowser) AddLibrary(name string, collectionType string, paths []string, refreshLibrary bool, ...) (int, error)
- func (mb *MediaBrowser) Authenticate(username, password string) (User, error)
- func (mb *MediaBrowser) DeleteFolder(name string, path string, refreshLibrary bool) (int, error)
- func (mb *MediaBrowser) DeleteLibrary(name string) (int, error)
- func (mb *MediaBrowser) DeleteUser(userID string) error
- func (mb *MediaBrowser) GetDisplayPreferences(userID string) (map[string]interface{}, error)
- func (mb *MediaBrowser) GetLibraries() ([]VirtualFolder, int, error)
- func (mb *MediaBrowser) GetUsers(public bool) ([]User, error)
- func (mb *MediaBrowser) MustAuthenticate(username, password string, opts MustAuthenticateOptions) (user User, err error)
- func (mb *MediaBrowser) NewUser(username, password string) (User, error)
- func (mb *MediaBrowser) ResetPassword(pin string) (PasswordResetResponse, error)
- func (mb *MediaBrowser) ResetPasswordAdmin(userID string) error
- func (mb *MediaBrowser) ScanLibs() (int, error)
- func (mb *MediaBrowser) SetConfiguration(userID string, configuration Configuration) error
- func (mb *MediaBrowser) SetDisplayPreferences(userID string, displayprefs map[string]interface{}) error
- func (mb *MediaBrowser) SetPassword(userID, currentPw, newPw string) error
- func (mb *MediaBrowser) SetPolicy(userID string, policy Policy) error
- func (mb *MediaBrowser) SetTransport(t *http.Transport)
- func (mb *MediaBrowser) UserByID(userID string, public bool) (User, error)
- func (mb *MediaBrowser) UserByName(username string, public bool) (User, error)
- type MustAuthenticateOptions
- type PasswordResetResponse
- type PathInfo
- type Policy
- type ServerInfo
- type SessionInfo
- type SubFolder
- type Time
- type TimeoutHandler
- type TypeOptions
- type User
- type VirtualFolder
Constants ¶
const ( JellyfinServer serverType = iota EmbyServer )
Variables ¶
This section is empty.
Functions ¶
func DeNullConfiguration ¶ added in v0.3.9
func DeNullConfiguration(c *Configuration)
DeNullConfiguration ensures there are no "null" fields in the given Configuration. Jellyfin isn't a fan of null.
func DeNullLibraryOptions ¶ added in v0.3.9
func DeNullLibraryOptions(lo *LibraryOptions)
DeNullLibraryOptions ensures there are no "null" fields in the given LibraryOptions. Jellyfin isn't a fan of null.
func DeNullPolicy ¶ added in v0.3.9
func DeNullPolicy(p *Policy)
DeNullPolicy ensures there are no "null" fields in the given Policy. Jellyfin isn't a fan of null.
func DeNullVirtualFolder ¶ added in v0.3.9
func DeNullVirtualFolder(vf *VirtualFolder)
DeNullVirtualFolder ensures there are no "null" fields in the given VirtualFolder. Jellyfin isn't a fan of null.
Types ¶
type AuthenticationResult ¶
type AuthenticationResult struct { User User `json:"User"` AccessToken string `json:"AccessToken"` ServerID string `json:"ServerId"` SessionInfo SessionInfo `json:"SessionInfo"` }
type Configuration ¶
type Configuration struct { AudioLanguagePreference string `json:"AudioLanguagePreference"` PlayDefaultAudioTrack bool `json:"PlayDefaultAudioTrack"` SubtitleLanguagePreference string `json:"SubtitleLanguagePreference"` DisplayMissingEpisodes bool `json:"DisplayMissingEpisodes"` GroupedFolders []interface{} `json:"GroupedFolders,omitempty"` SubtitleMode string `json:"SubtitleMode"` DisplayCollectionsView bool `json:"DisplayCollectionsView"` EnableLocalPassword bool `json:"EnableLocalPassword"` OrderedViews []interface{} `json:"OrderedViews,omitempty"` LatestItemsExcludes []interface{} `json:"LatestItemsExcludes,omitempty"` MyMediaExcludes []interface{} `json:"MyMediaExcludes,omitempty"` HidePlayedInLatest bool `json:"HidePlayedInLatest"` RememberAudioSelections bool `json:"RememberAudioSelections"` RememberSubtitleSelections bool `json:"RememberSubtitleSelections"` EnableNextEpisodeAutoPlay bool `json:"EnableNextEpisodeAutoPlay"` CastReceiverID string `json:"CastReceiverId"` }
type DetailedError ¶ added in v0.2.0
DetailedError is sometimes returned by Jellyfin. These details are only populated when mb.Verbose is true.
func (DetailedError) Details ¶ added in v0.2.0
func (err DetailedError) Details() string
func (DetailedError) IsVerbose ¶ added in v0.3.20
func (err DetailedError) IsVerbose() bool
type ErrForbidden ¶ added in v0.2.0
type ErrForbidden struct {
DetailedError
}
func (ErrForbidden) Error ¶ added in v0.2.0
func (err ErrForbidden) Error() string
type ErrNoPolicySupplied ¶ added in v0.2.0
type ErrNoPolicySupplied struct {
DetailedError
}
func (ErrNoPolicySupplied) Error ¶ added in v0.2.0
func (err ErrNoPolicySupplied) Error() string
type ErrNotFound ¶ added in v0.2.0
type ErrNotFound error
most 404 errors are from UserNotFound, so this generic error doesn't really need any detail.
var (
NotFound ErrNotFound = errors.New("resource not found")
)
type ErrUnauthorized ¶ added in v0.2.0
type ErrUnauthorized struct {
}func (ErrUnauthorized) Error ¶ added in v0.2.0
func (err ErrUnauthorized) Error() string
type ErrUnknown ¶ added in v0.3.15
type ErrUnknown struct {
DetailedError
}
func (ErrUnknown) Error ¶ added in v0.3.15
func (err ErrUnknown) Error() string
type ErrUserNotFound ¶ added in v0.2.0
type ErrUserNotFound struct { DetailedError // contains filtered or unexported fields }
func (ErrUserNotFound) Error ¶ added in v0.2.0
func (err ErrUserNotFound) Error() string
type ImageOptions ¶ added in v0.3.0
type LibraryOptions ¶ added in v0.3.0
type LibraryOptions struct { EnablePhotos bool `json:"EnablePhotos"` EnableRealtimeMonitor bool `json:"EnableRealtimeMonitor"` EnableChapterImageExtraction bool `json:"EnableChapterImageExtraction"` ExtractChapterImagesDuringLibraryScan bool `json:"ExtractChapterImagesDuringLibraryScan"` PathInfos []PathInfo `json:"PathInfos"` SaveLocalMetadata bool `json:"SaveLocalMetadata"` EnableInternetProviders bool `json:"EnableInternetProviders"` EnableAutomaticSeriesGrouping bool `json:"EnableAutomaticSeriesGrouping"` EnableEmbeddedTitles bool `json:"EnableEmbeddedTitles"` EnableEmbeddedEpisodeInfos bool `json:"EnableEmbeddedEpisodeInfos"` AutomaticRefreshIntervalDays int `json:"AutomaticRefreshIntervalDays"` PreferredMetadataLanguage string `json:"PreferredMetadataLanguage"` MetadataCountryCode string `json:"MetadataCountryCode"` SeasonZeroDisplayName string `json:"SeasonZeroDisplayName"` MetadataSavers []string `json:"MetadataSavers"` DisabledLocalMetadataReaders []string `json:"DisabledLocalMetadataReaders"` LocalMetadataReaderOrder []string `json:"LocalMetadataReaderOrder"` DisabledSubtitleFetchers []string `json:"DisabledSubtitleFetchers"` SubtitleFetcherOrder []string `json:"SubtitleFetcherOrder"` SkipSubtitlesIfEmbeddedSubtitlesPresent bool `json:"SkipSubtitlesIfEmbeddedSubtitlesPresent"` SkipSubtitlesIfAudioTrackMatches bool `json:"SkipSubtitlesIfAudioTrackMatches"` SubtitleDownloadLanguages []string `json:"SubtitleDownloadLanguages"` RequirePerfectSubtitleMatch bool `json:"RequirePerfectSubtitleMatch"` SaveSubtitlesWithMedia bool `json:"SaveSubtitlesWithMedia"` TypeOptions []TypeOptions `json:"TypeOptions"` CollapseSingleItemFolders bool `json:"CollapseSingleItemFolders"` MinResumePct int `json:"MinResumePct"` MaxResumePct int `json:"MaxResumePct"` MinResumeDurationSeconds int `json:"MinResumeDurationSeconds"` ThumbnailImagesIntervalSeconds int `json:"ThumbnailImagesIntervalSeconds"` }
type MediaBrowser ¶
type MediaBrowser struct { Server string ServerInfo ServerInfo Username string Authenticated bool AccessToken string CacheExpiry, LibraryCacheExpiry time.Time // first is UserCacheExpiry, keeping name for compatability Hyphens bool Verbose bool // Jellyfin only, errors will include more info when true // contains filtered or unexported fields }
MediaBrowser is an api instance of Jellyfin/Emby.
func NewServer ¶
func NewServer(st serverType, server, client, version, device, deviceID string, timeoutHandler TimeoutHandler, cacheTimeout int) (*MediaBrowser, error)
NewServer returns a new Mediabrowser object.
func (*MediaBrowser) AddFolder ¶ added in v0.3.0
func (mb *MediaBrowser) AddFolder(refreshLibrary bool, AddMedia AddMedia) (int, error)
AddFolder adds a subfolder to a library (VirtualFolder)
func (*MediaBrowser) AddLibrary ¶ added in v0.3.0
func (mb *MediaBrowser) AddLibrary(name string, collectionType string, paths []string, refreshLibrary bool, LibraryOptions LibraryOptions) (int, error)
AddLibrary creates a library (VirtualFolder) for this node.
func (*MediaBrowser) Authenticate ¶
func (mb *MediaBrowser) Authenticate(username, password string) (User, error)
Authenticate attempts to authenticate using a username & password
func (*MediaBrowser) DeleteFolder ¶ added in v0.3.0
DeleteFolder deletes the library (VirtualFolder) corresponding to the provided name.
func (*MediaBrowser) DeleteLibrary ¶ added in v0.3.0
func (mb *MediaBrowser) DeleteLibrary(name string) (int, error)
DeleteLibrary deletes the library (VirtualFolder) corresponding to the provided name.
func (*MediaBrowser) DeleteUser ¶
func (mb *MediaBrowser) DeleteUser(userID string) error
DeleteUser deletes the user corresponding to the provided ID.
func (*MediaBrowser) GetDisplayPreferences ¶
func (mb *MediaBrowser) GetDisplayPreferences(userID string) (map[string]interface{}, error)
GetDisplayPreferences gets the displayPreferences (part of homescreen layout) for the user corresponding to the provided ID.
func (*MediaBrowser) GetLibraries ¶ added in v0.3.0
func (mb *MediaBrowser) GetLibraries() ([]VirtualFolder, int, error)
GetLibraries returns a list of the Libaries (called VirtualFolders) on this node.
func (*MediaBrowser) GetUsers ¶
func (mb *MediaBrowser) GetUsers(public bool) ([]User, error)
GetUsers returns all (visible) users on the instance. If public, no authentication is needed but hidden users will not be visible.
func (*MediaBrowser) MustAuthenticate ¶ added in v0.3.11
func (mb *MediaBrowser) MustAuthenticate(username, password string, opts MustAuthenticateOptions) (user User, err error)
MustAuthenticate attempts to authenticate using a username & password, with configurable retries in the event of failure.
func (*MediaBrowser) NewUser ¶
func (mb *MediaBrowser) NewUser(username, password string) (User, error)
NewUser creates a new user with the provided username and password.
func (*MediaBrowser) ResetPassword ¶ added in v0.1.1
func (mb *MediaBrowser) ResetPassword(pin string) (PasswordResetResponse, error)
ResetPassword resets a user's password by setting it to the given PIN, which is generated when a user attempts to reset on the login page. Only supported on Jellyfin, will return (PasswordResetResponse, -1, nil) on Emby.
func (*MediaBrowser) ResetPasswordAdmin ¶ added in v0.3.6
func (mb *MediaBrowser) ResetPasswordAdmin(userID string) error
ResetPasswordAdmin resets the given user ID's password, allowing one to then change it without knowing the previous password.
func (*MediaBrowser) ScanLibs ¶ added in v0.3.0
func (mb *MediaBrowser) ScanLibs() (int, error)
ScanLibs triggers a scan of all libraries.
func (*MediaBrowser) SetConfiguration ¶
func (mb *MediaBrowser) SetConfiguration(userID string, configuration Configuration) error
SetConfiguration sets the configuration (part of homescreen layout) for the user corresponding to the provided ID. No GetConfiguration is provided because a User object includes Configuration already.
func (*MediaBrowser) SetDisplayPreferences ¶
func (mb *MediaBrowser) SetDisplayPreferences(userID string, displayprefs map[string]interface{}) error
SetDisplayPreferences sets the displayPreferences (part of homescreen layout) for the user corresponding to the provided ID.
func (*MediaBrowser) SetPassword ¶ added in v0.3.4
func (mb *MediaBrowser) SetPassword(userID, currentPw, newPw string) error
SetPassword sets the password for a user given a userID, the old password, and the new one. Requires admin authentication or authentication as the target user.
func (*MediaBrowser) SetPolicy ¶
func (mb *MediaBrowser) SetPolicy(userID string, policy Policy) error
SetPolicy sets the access policy for the user corresponding to the provided ID. No GetPolicy is provided because a User object includes Policy already.
func (*MediaBrowser) SetTransport ¶ added in v0.3.12
func (mb *MediaBrowser) SetTransport(t *http.Transport)
SetTransport sets the HTTP transport to be used for all requests. Can be used to set a proxy.
func (*MediaBrowser) UserByID ¶
func (mb *MediaBrowser) UserByID(userID string, public bool) (User, error)
UserByID returns the user corresponding to the provided ID.
func (*MediaBrowser) UserByName ¶
func (mb *MediaBrowser) UserByName(username string, public bool) (User, error)
UserByName returns the user corresponding to the provided username.
type MustAuthenticateOptions ¶ added in v0.3.11
type MustAuthenticateOptions struct { RetryCount int // Number of Retries before failure. RetryGap time.Duration // Duration to wait between tries. LogFailures bool // Whether or not to print failures to the log. }
MustAuthenticateOptions is used to control the behaviour of the MustAuthenticate method.
type PasswordResetResponse ¶ added in v0.1.1
type Policy ¶
type Policy struct { IsAdministrator bool `json:"IsAdministrator"` IsHidden bool `json:"IsHidden"` IsDisabled bool `json:"IsDisabled"` BlockedTags []interface{} `json:"BlockedTags,omitempty"` AllowedTags []interface{} `json:"AllowedTags"` EnableUserPreferenceAccess bool `json:"EnableUserPreferenceAccess"` AccessSchedules []interface{} `json:"AccessSchedules,omitempty"` BlockUnratedItems []interface{} `json:"BlockUnratedItems,omitempty"` EnableRemoteControlOfOtherUsers bool `json:"EnableRemoteControlOfOtherUsers"` EnableRemoteAccess bool `json:"EnableRemoteAccess"` EnableLiveTvManagement bool `json:"EnableLiveTvManagement"` EnableLiveTvAccess bool `json:"EnableLiveTvAccess"` EnableMediaPlayback bool `json:"EnableMediaPlayback"` EnableAudioPlaybackTranscoding bool `json:"EnableAudioPlaybackTranscoding"` EnableVideoPlaybackTranscoding bool `json:"EnableVideoPlaybackTranscoding"` EnablePlaybackRemuxing bool `json:"EnablePlaybackRemuxing"` EnableContentDeletion bool `json:"EnableContentDeletion"` EnableContentDeletionFromFolders []interface{} `json:"EnableContentDeletionFromFolders,omitempty"` EnableContentDownloading bool `json:"EnableContentDownloading"` EnableSyncTranscoding bool `json:"EnableSyncTranscoding"` EnableMediaConversion bool `json:"EnableMediaConversion"` EnabledDevices []interface{} `json:"EnabledDevices,omitempty"` EnableAllDevices bool `json:"EnableAllDevices"` EnabledChannels []interface{} `json:"EnabledChannels,omitempty"` EnableAllChannels bool `json:"EnableAllChannels"` EnabledFolders []string `json:"EnabledFolders"` EnableAllFolders bool `json:"EnableAllFolders"` InvalidLoginAttemptCount int `json:"InvalidLoginAttemptCount"` EnablePublicSharing bool `json:"EnablePublicSharing"` RemoteClientBitrateLimit int `json:"RemoteClientBitrateLimit"` AuthenticationProviderID string `json:"AuthenticationProviderId"` EnableCollectionManagement bool `json:"EnableCollectionManagement"` EnableSubtitleManagement bool `json:"EnableSubtitleManagement"` EnableLyricManagement bool `json:"EnableLyricManagement"` // Jellyfin Only ForceRemoteSourceTranscoding bool `json:"ForceRemoteSourceTranscoding"` LoginAttemptsBeforeLockout int `json:"LoginAttemptsBeforeLockout"` MaxActiveSessions int `json:"MaxActiveSessions"` BlockedMediaFolders []interface{} `json:"BlockedMediaFolders,omitempty"` BlockedChannels []interface{} `json:"BlockedChannels,omitempty"` PasswordResetProviderID string `json:"PasswordResetProviderId"` SyncPlayAccess string `json:"SyncPlayAccess"` // Emby Only IsHiddenRemotely bool `json:"IsHiddenRemotely"` IsHiddenFromUnusedDevices bool `json:"IsHiddenFromUnusedDevices"` IsTagBlockingModeInclusive bool `json:"IsTagBlockingModeInclusive"` EnableSubtitleDownloading bool `json:"EnableSubtitleDownloading"` ExcludedSubFolders []interface{} `json:"ExcludedSubFolders,omitempty"` SimultaneousStreamLimit int `json:"SimultaneousStreamLimit"` }
Policy stores a users permissions.
type ServerInfo ¶
type ServerInfo struct { LocalAddress string `json:"LocalAddress"` Name string `json:"ServerName"` Version string `json:"Version"` OS string `json:"OperatingSystem"` ID string `json:"Id"` }
ServerInfo stores info about the server.
type SessionInfo ¶
type Time ¶
Time embeds time.Time with a custom JSON Unmarshal method to work with Jellyfin & Emby's time formatting.
func (*Time) UnmarshalJSON ¶
type TimeoutHandler ¶
type TimeoutHandler func()
TimeoutHandler should recover from an http timeout or panic.
func NewNamedTimeoutHandler ¶
func NewNamedTimeoutHandler(name, addr string, noFail bool) TimeoutHandler
NewNamedTimeoutHandler returns a new Timeout handler that logs the error. name is the name of the server to use in the log (e.g Jellyfin/Emby) addr is the address of the server being accessed if noFail is false, the program will exit on a timeout.
type TypeOptions ¶ added in v0.3.0
type TypeOptions struct { Type string `json:"Type"` MetadataFetchers []string `json:"MetadataFetchers"` MetadataFetcherOrder []string `json:"MetadataFetcherOrder"` ImageFetchers []string `json:"ImageFetchers"` ImageFetcherOrder []string `json:"ImageFetcherOrder"` ImageOptions []ImageOptions `json:"ImageOptions"` }
type User ¶
type User struct { Name string `json:"Name"` ServerID string `json:"ServerId"` ID string `json:"Id"` HasPassword bool `json:"HasPassword"` HasConfiguredPassword bool `json:"HasConfiguredPassword"` HasConfiguredEasyPassword bool `json:"HasConfiguredEasyPassword"` EnableAutoLogin bool `json:"EnableAutoLogin"` LastLoginDate Time `json:"LastLoginDate"` LastActivityDate Time `json:"LastActivityDate"` Configuration Configuration `json:"Configuration"` // Policy stores the user's permissions. Policy Policy `json:"Policy"` }
type VirtualFolder ¶ added in v0.3.0
type VirtualFolder struct { Name string `json:"Name"` Locations []string `json:"Locations"` CollectionType string `json:"CollectionType"` LibraryOptions LibraryOptions `json:"LibraryOptions"` ItemId string `json:"ItemId"` PrimaryImageItemId string `json:"PrimaryImageItemId"` RefreshProgress float64 `json:"RefreshProgress"` RefreshStatus string `json:"RefreshStatus"` }