mediabrowser

package module
v0.3.24 Latest Latest
Warning

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

Go to latest
Published: Nov 5, 2024 License: MIT Imports: 10 Imported by: 3

README

mediabrowser

GoDoc

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

View Source
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 AddMedia added in v0.3.0

type AddMedia struct {
	Name     string   `json:"Name"`
	Path     string   `json:"Path"`
	PathInfo PathInfo `json:"PathInfo"`
}

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

type DetailedError struct {
	Verbose bool
	Code    int
	Data    string `json:"data"`
}

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 {
	DetailedError
}

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 ImageOptions struct {
	Type     string `json:"Type"`
	Limit    int    `json:"Limit"`
	MinWidth int    `json:"MinWidth"`
}

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

func (mb *MediaBrowser) DeleteFolder(name string, path string, refreshLibrary bool) (int, error)

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 PasswordResetResponse struct {
	Success    bool     `json:"Success"`
	UsersReset []string `json:"UsersReset"`
}

type PathInfo added in v0.3.0

type PathInfo struct {
	Path        string `json:"Path"`
	NetworkPath string `json:"NetworkPath"`
}

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"`
	EnableSharedDeviceControl        bool          `json:"EnableSharedDeviceControl"`
	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 SessionInfo struct {
	RemoteEndpoint string `json:"RemoteEndPoint"`
	UserID         string `json:"UserId"`
}

type SubFolder added in v0.3.0

type SubFolder struct {
	Name string `json:"Name"`
	Id   string `json:"Id"`
	Path string `json:"Path"`
}

type Time

type Time struct {
	time.Time
}

Time embeds time.Time with a custom JSON Unmarshal method to work with Jellyfin & Emby's time formatting.

func (*Time) UnmarshalJSON

func (t *Time) UnmarshalJSON(b []byte) (err error)

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"`
}

Directories

Path Synopsis
example module

Jump to

Keyboard shortcuts

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