2016-04-10 03:59:47 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
from plexapi import media, utils
|
2017-02-04 19:46:51 +00:00
|
|
|
from plexapi.base import PlexPartialObject
|
2018-09-14 18:27:24 +00:00
|
|
|
from plexapi.exceptions import NotFound, BadRequest
|
2018-09-08 15:25:16 +00:00
|
|
|
from plexapi.compat import quote_plus
|
2016-04-10 03:59:47 +00:00
|
|
|
|
|
|
|
|
2017-02-13 02:55:55 +00:00
|
|
|
@utils.registerPlexObject
|
2016-04-10 03:59:47 +00:00
|
|
|
class Photoalbum(PlexPartialObject):
|
2017-01-31 04:44:03 +00:00
|
|
|
""" Represents a photoalbum (collection of photos).
|
|
|
|
|
|
|
|
Attributes:
|
2017-02-14 04:32:27 +00:00
|
|
|
TAG (str): 'Directory'
|
|
|
|
TYPE (str): 'photo'
|
2017-01-31 04:44:03 +00:00
|
|
|
addedAt (datetime): Datetime this item was added to the library.
|
|
|
|
art (str): Photo art (/library/metadata/<ratingkey>/art/<artid>)
|
|
|
|
composite (str): Unknown
|
|
|
|
guid (str): Unknown (unique ID)
|
|
|
|
index (sting): Index number of this album.
|
|
|
|
key (str): API URL (/library/metadata/<ratingkey>).
|
|
|
|
librarySectionID (int): :class:`~plexapi.library.LibrarySection` ID.
|
|
|
|
listType (str): Hardcoded as 'photo' (useful for search filters).
|
|
|
|
ratingKey (int): Unique key identifying this item.
|
|
|
|
summary (str): Summary of the photoalbum.
|
|
|
|
thumb (str): URL to thumbnail image.
|
|
|
|
title (str): Photoalbum title. (Trip to Disney World)
|
|
|
|
type (str): Unknown
|
|
|
|
updatedAt (datatime): Datetime this item was updated.
|
2017-01-02 21:06:40 +00:00
|
|
|
"""
|
2017-02-13 02:55:55 +00:00
|
|
|
TAG = 'Directory'
|
|
|
|
TYPE = 'photo'
|
2016-04-10 03:59:47 +00:00
|
|
|
|
|
|
|
def _loadData(self, data):
|
2017-01-31 04:44:03 +00:00
|
|
|
""" Load attribute values from Plex XML response. """
|
2016-04-12 02:43:21 +00:00
|
|
|
self.listType = 'photo'
|
2017-02-04 17:43:50 +00:00
|
|
|
self.addedAt = utils.toDatetime(data.attrib.get('addedAt'))
|
|
|
|
self.art = data.attrib.get('art')
|
|
|
|
self.composite = data.attrib.get('composite')
|
|
|
|
self.guid = data.attrib.get('guid')
|
|
|
|
self.index = utils.cast(int, data.attrib.get('index'))
|
|
|
|
self.key = data.attrib.get('key')
|
|
|
|
self.librarySectionID = data.attrib.get('librarySectionID')
|
|
|
|
self.ratingKey = data.attrib.get('ratingKey')
|
|
|
|
self.summary = data.attrib.get('summary')
|
|
|
|
self.thumb = data.attrib.get('thumb')
|
|
|
|
self.title = data.attrib.get('title')
|
|
|
|
self.type = data.attrib.get('type')
|
|
|
|
self.updatedAt = utils.toDatetime(data.attrib.get('updatedAt'))
|
2017-01-02 21:06:40 +00:00
|
|
|
|
2017-02-26 05:17:41 +00:00
|
|
|
def albums(self, **kwargs):
|
|
|
|
""" Returns a list of :class:`~plexapi.photo.Photoalbum` objects in this album. """
|
|
|
|
key = '/library/metadata/%s/children' % self.ratingKey
|
|
|
|
return self.fetchItems(key, etag='Directory', **kwargs)
|
|
|
|
|
|
|
|
def album(self, title):
|
|
|
|
""" Returns the :class:`~plexapi.photo.Photoalbum` that matches the specified title. """
|
|
|
|
for album in self.albums():
|
2017-10-25 18:58:20 +00:00
|
|
|
if album.title.lower() == title.lower():
|
2017-02-26 05:17:41 +00:00
|
|
|
return album
|
|
|
|
raise NotFound('Unable to find album: %s' % title)
|
|
|
|
|
2017-02-09 04:08:25 +00:00
|
|
|
def photos(self, **kwargs):
|
2017-01-31 04:44:03 +00:00
|
|
|
""" Returns a list of :class:`~plexapi.photo.Photo` objects in this album. """
|
2017-02-06 04:52:10 +00:00
|
|
|
key = '/library/metadata/%s/children' % self.ratingKey
|
2017-02-26 05:17:41 +00:00
|
|
|
return self.fetchItems(key, etag='Photo', **kwargs)
|
2016-04-10 03:59:47 +00:00
|
|
|
|
|
|
|
def photo(self, title):
|
2017-01-31 04:44:03 +00:00
|
|
|
""" Returns the :class:`~plexapi.photo.Photo` that matches the specified title. """
|
2017-02-06 04:52:10 +00:00
|
|
|
for photo in self.photos():
|
2017-10-25 18:58:20 +00:00
|
|
|
if photo.title.lower() == title.lower():
|
2017-02-06 04:52:10 +00:00
|
|
|
return photo
|
|
|
|
raise NotFound('Unable to find photo: %s' % title)
|
2017-01-02 21:06:40 +00:00
|
|
|
|
2016-04-10 03:59:47 +00:00
|
|
|
|
2017-02-13 02:55:55 +00:00
|
|
|
@utils.registerPlexObject
|
2016-04-10 03:59:47 +00:00
|
|
|
class Photo(PlexPartialObject):
|
2017-01-31 04:44:03 +00:00
|
|
|
""" Represents a single photo.
|
|
|
|
|
|
|
|
Attributes:
|
2017-02-14 04:32:27 +00:00
|
|
|
TAG (str): 'Photo'
|
|
|
|
TYPE (str): 'photo'
|
2017-01-31 04:44:03 +00:00
|
|
|
addedAt (datetime): Datetime this item was added to the library.
|
|
|
|
index (sting): Index number of this photo.
|
|
|
|
key (str): API URL (/library/metadata/<ratingkey>).
|
|
|
|
listType (str): Hardcoded as 'photo' (useful for search filters).
|
|
|
|
media (TYPE): Unknown
|
|
|
|
originallyAvailableAt (datetime): Datetime this photo was added to Plex.
|
|
|
|
parentKey (str): Photoalbum API URL.
|
|
|
|
parentRatingKey (int): Unique key identifying the photoalbum.
|
|
|
|
ratingKey (int): Unique key identifying this item.
|
|
|
|
summary (str): Summary of the photo.
|
|
|
|
thumb (str): URL to thumbnail image.
|
|
|
|
title (str): Photo title.
|
|
|
|
type (str): Unknown
|
|
|
|
updatedAt (datatime): Datetime this item was updated.
|
|
|
|
year (int): Year this photo was taken.
|
2017-01-02 21:06:40 +00:00
|
|
|
"""
|
2017-02-13 02:55:55 +00:00
|
|
|
TAG = 'Photo'
|
2016-04-10 03:59:47 +00:00
|
|
|
TYPE = 'photo'
|
2018-09-08 15:25:16 +00:00
|
|
|
METADATA_TYPE = 'photo'
|
2016-04-10 03:59:47 +00:00
|
|
|
|
|
|
|
def _loadData(self, data):
|
2017-01-31 04:44:03 +00:00
|
|
|
""" Load attribute values from Plex XML response. """
|
2016-04-12 02:43:21 +00:00
|
|
|
self.listType = 'photo'
|
2017-02-04 17:43:50 +00:00
|
|
|
self.addedAt = utils.toDatetime(data.attrib.get('addedAt'))
|
|
|
|
self.index = utils.cast(int, data.attrib.get('index'))
|
|
|
|
self.key = data.attrib.get('key')
|
2017-01-02 21:06:40 +00:00
|
|
|
self.originallyAvailableAt = utils.toDatetime(
|
2017-02-04 17:43:50 +00:00
|
|
|
data.attrib.get('originallyAvailableAt'), '%Y-%m-%d')
|
|
|
|
self.parentKey = data.attrib.get('parentKey')
|
|
|
|
self.parentRatingKey = data.attrib.get('parentRatingKey')
|
|
|
|
self.ratingKey = data.attrib.get('ratingKey')
|
|
|
|
self.summary = data.attrib.get('summary')
|
|
|
|
self.thumb = data.attrib.get('thumb')
|
|
|
|
self.title = data.attrib.get('title')
|
|
|
|
self.type = data.attrib.get('type')
|
|
|
|
self.updatedAt = utils.toDatetime(data.attrib.get('updatedAt'))
|
|
|
|
self.year = utils.cast(int, data.attrib.get('year'))
|
2017-02-13 02:55:55 +00:00
|
|
|
self.media = self.findItems(data, media.Media)
|
2017-01-02 21:06:40 +00:00
|
|
|
|
2016-04-10 03:59:47 +00:00
|
|
|
def photoalbum(self):
|
2017-01-31 04:44:03 +00:00
|
|
|
""" Return this photo's :class:`~plexapi.photo.Photoalbum`. """
|
2017-02-07 06:20:49 +00:00
|
|
|
return self.fetchItem(self.parentKey)
|
2016-07-08 02:41:11 +00:00
|
|
|
|
|
|
|
def section(self):
|
2017-01-31 04:44:03 +00:00
|
|
|
""" Returns the :class:`~plexapi.library.LibrarySection` this item belongs to. """
|
2018-09-14 18:27:24 +00:00
|
|
|
if hasattr(self, 'librarySectionID'):
|
|
|
|
return self._server.library.sectionByID(self.librarySectionID)
|
|
|
|
elif self.parentKey:
|
|
|
|
return self._server.library.sectionByID(self.photoalbum().librarySectionID)
|
|
|
|
else:
|
|
|
|
raise BadRequest('Unable to get section for photo, can`t find librarySectionID')
|
2018-09-08 15:25:16 +00:00
|
|
|
|
|
|
|
def sync(self, resolution, client=None, clientId=None, limit=None, title=None):
|
|
|
|
""" Add current photo as sync item for specified device.
|
|
|
|
See :func:`plexapi.myplex.MyPlexAccount.sync()` for possible exceptions.
|
|
|
|
|
|
|
|
Parameters:
|
|
|
|
resolution (str): maximum allowed resolution for synchronized photos, see PHOTO_QUALITY_* values in the
|
|
|
|
module :mod:`plexapi.sync`.
|
|
|
|
client (:class:`plexapi.myplex.MyPlexDevice`): sync destination, see
|
|
|
|
:func:`plexapi.myplex.MyPlexAccount.sync`.
|
|
|
|
clientId (str): sync destination, see :func:`plexapi.myplex.MyPlexAccount.sync`.
|
|
|
|
limit (int): maximum count of items to sync, unlimited if `None`.
|
|
|
|
title (str): descriptive title for the new :class:`plexapi.sync.SyncItem`, if empty the value would be
|
|
|
|
generated from metadata of current photo.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
:class:`plexapi.sync.SyncItem`: an instance of created syncItem.
|
|
|
|
"""
|
|
|
|
|
|
|
|
from plexapi.sync import SyncItem, Policy, MediaSettings
|
|
|
|
|
|
|
|
myplex = self._server.myPlexAccount()
|
|
|
|
sync_item = SyncItem(self._server, None)
|
|
|
|
sync_item.title = title if title else self.title
|
|
|
|
sync_item.rootTitle = self.title
|
|
|
|
sync_item.contentType = self.listType
|
|
|
|
sync_item.metadataType = self.METADATA_TYPE
|
|
|
|
sync_item.machineIdentifier = self._server.machineIdentifier
|
|
|
|
|
2018-09-14 18:03:23 +00:00
|
|
|
section = self.section()
|
2018-09-08 15:25:16 +00:00
|
|
|
|
|
|
|
sync_item.location = 'library://%s/item/%s' % (section.uuid, quote_plus(self.key))
|
|
|
|
sync_item.policy = Policy.create(limit)
|
|
|
|
sync_item.mediaSettings = MediaSettings.createPhoto(resolution)
|
|
|
|
|
|
|
|
return myplex.sync(sync_item, client=client, clientId=clientId)
|