mirror of
https://github.com/pkkid/python-plexapi
synced 2024-11-10 14:14:19 +00:00
commit
fbbd3f0082
6 changed files with 241 additions and 11 deletions
|
@ -177,12 +177,13 @@ class PlexObject(object):
|
|||
results.append(elem.attrib.get(attr))
|
||||
return results
|
||||
|
||||
def reload(self):
|
||||
def reload(self, key=None):
|
||||
""" Reload the data for this object from self.key. """
|
||||
if not self.key:
|
||||
key = key or self.key
|
||||
if not key:
|
||||
raise Unsupported('Cannot reload an object not built from a URL.')
|
||||
self._initpath = self.key
|
||||
data = self._server.query(self.key)
|
||||
self._initpath = key
|
||||
data = self._server.query(key)
|
||||
self._loadData(data[0])
|
||||
return self
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from plexapi import X_PLEX_CONTAINER_SIZE, log, utils
|
||||
from plexapi.base import PlexObject
|
||||
from plexapi.compat import unquote
|
||||
from plexapi.compat import unquote, urlencode, quote_plus
|
||||
from plexapi.media import MediaTag
|
||||
from plexapi.exceptions import BadRequest, NotFound
|
||||
|
||||
|
@ -144,6 +144,107 @@ class Library(PlexObject):
|
|||
for section in self.sections():
|
||||
section.deleteMediaPreviews()
|
||||
|
||||
def add(self, name='', type='', agent='', scanner='', location='', language='en', *args, **kwargs):
|
||||
""" Simplified add for the most common options.
|
||||
|
||||
name (str): Name of the library
|
||||
agent (str): Example com.plexapp.agents.imdb
|
||||
type (str): movie, show, # check me
|
||||
location (str): /path/to/files
|
||||
language (str): Two letter language fx en
|
||||
kwargs (dict): Advanced options should be passed as a dict. where the id is the key.
|
||||
|
||||
# Prefs for photo
|
||||
agent (str): com.plexapp.agents.none
|
||||
enableAutoPhotoTags (bool): Tag photos. Default value false .
|
||||
enableBIFGeneration (bool): Enable video preview thumbnails. Default value true .
|
||||
includeInGlobal (bool): Include in dashboard. Default value true .
|
||||
scanner (str): Plex Photo Scanner
|
||||
|
||||
# Prefs for other movies
|
||||
agent (str): com.plexapp.agents.none, com.plexapp.agents.imdb, com.plexapp.agents.themoviedb
|
||||
enableBIFGeneration (bool): Enable video preview thumbnails. Default value true .
|
||||
enableCinemaTrailers (bool): Enable Cinema Trailers. Default value true .
|
||||
includeInGlobal (bool): Include in dashboard. Default value true .
|
||||
scanner (str): Plex Movie Scanner, Plex Video Files Scanner
|
||||
|
||||
# other movies com.plexapp.agents.imdb settings options
|
||||
title (bool): Localized titles. Default value false .
|
||||
extras (bool): Find trailers and extras automatically (Plex Pass required). Default value true .
|
||||
only_trailers (bool): Skip extras which aren't trailers. Default value false .
|
||||
redband (bool): Use red band (restricted audiences) trailers when available. Default value false .
|
||||
native_subs (bool): Include extras with subtitles in Library language. Default value false .
|
||||
cast_list (int): Cast List Source: . Default value 1 Possible options: 0:IMDb,1:The Movie Database.
|
||||
ratings (int): Ratings Source: . Default value 0 Possible options: 0:Rotten Tomatoes,1:IMDb,2:The Movie Database.
|
||||
summary (int): Plot Summary Source: . Default value 1 Possible options: 0:IMDb,1:The Movie Database.
|
||||
country (int): Country: . Default value 46 Possible options: 0:Argentina,1:Australia,2:Austria,3:Belgium,4:Belize,5:Bolivia,6:Brazil,7:Canada,8:Chile,9:Colombia,10:Costa Rica,11:Czech Republic,12:Denmark,13:Dominican Republic,14:Ecuador,15:El Salvador,16:France,17:Germany,18:Guatemala,19:Honduras,20:Hong Kong SAR,21:Ireland,22:Italy,23:Jamaica,24:Korea,25:Liechtenstein,26:Luxembourg,27:Mexico,28:Netherlands,29:New Zealand,30:Nicaragua,31:Panama,32:Paraguay,33:Peru,34:Portugal,35:Peoples Republic of China,36:Puerto Rico,37:Russia,38:Singapore,39:South Africa,40:Spain,41:Sweden,42:Switzerland,43:Taiwan,44:Trinidad,45:United Kingdom,46:United States,47:Uruguay,48:Venezuela.
|
||||
collections (bool): Use collection info from The Movie Database. Default value false .
|
||||
localart (bool): Prefer artwork based on library language. Default value true .
|
||||
adult (bool): Include adult content. Default value false .
|
||||
usage (bool): Send anonymous usage data to Plex. Default value true .
|
||||
|
||||
# other movies com.plexapp.agents.themoviedb settings options
|
||||
collections (bool): Use collection info from The Movie Database. Default value false .
|
||||
localart (bool): Prefer artwork based on library language. Default value true .
|
||||
adult (bool): Include adult content. Default value false .
|
||||
country (int): Country (used for release date and content rating). Default value 47 Possible options: 0:,1:Argentina,2:Australia,3:Austria,4:Belgium,5:Belize,6:Bolivia,7:Brazil,8:Canada,9:Chile,10:Colombia,11:Costa Rica,12:Czech Republic,13:Denmark,14:Dominican Republic,15:Ecuador,16:El Salvador,17:France,18:Germany,19:Guatemala,20:Honduras,21:Hong Kong SAR,22:Ireland,23:Italy,24:Jamaica,25:Korea,26:Liechtenstein,27:Luxembourg,28:Mexico,29:Netherlands,30:New Zealand,31:Nicaragua,32:Panama,33:Paraguay,34:Peru,35:Portugal,36:Peoples Republic of China,37:Puerto Rico,38:Russia,39:Singapore,40:South Africa,41:Spain,42:Sweden,43:Switzerland,44:Taiwan,45:Trinidad,46:United Kingdom,47:United States,48:Uruguay,49:Venezuela.
|
||||
|
||||
# Prefs for movie
|
||||
agent (str): com.plexapp.agents.none, com.plexapp.agents.imdb, com.plexapp.agents.themoviedb
|
||||
enableBIFGeneration (bool): Enable video preview thumbnails. Default value true .
|
||||
enableCinemaTrailers (bool): Enable Cinema Trailers. Default value true .
|
||||
includeInGlobal (bool): Include in dashboard. Default value true .
|
||||
scanner (str): Plex Movie Scanner, Plex Video Files Scanner
|
||||
|
||||
# movie com.plexapp.agents.imdb settings options
|
||||
title (bool): Localized titles. Default value false .
|
||||
extras (bool): Find trailers and extras automatically (Plex Pass required). Default value true .
|
||||
only_trailers (bool): Skip extras which aren't trailers. Default value false .
|
||||
redband (bool): Use red band (restricted audiences) trailers when available. Default value false .
|
||||
native_subs (bool): Include extras with subtitles in Library language. Default value false .
|
||||
cast_list (int): Cast List Source: . Default value 1 Possible options: 0:IMDb,1:The Movie Database.
|
||||
ratings (int): Ratings Source: . Default value 0 Possible options: 0:Rotten Tomatoes,1:IMDb,2:The Movie Database.
|
||||
summary (int): Plot Summary Source: . Default value 1 Possible options: 0:IMDb,1:The Movie Database.
|
||||
country (int): Country: . Default value 46 Possible options: 0:Argentina,1:Australia,2:Austria,3:Belgium,4:Belize,5:Bolivia,6:Brazil,7:Canada,8:Chile,9:Colombia,10:Costa Rica,11:Czech Republic,12:Denmark,13:Dominican Republic,14:Ecuador,15:El Salvador,16:France,17:Germany,18:Guatemala,19:Honduras,20:Hong Kong SAR,21:Ireland,22:Italy,23:Jamaica,24:Korea,25:Liechtenstein,26:Luxembourg,27:Mexico,28:Netherlands,29:New Zealand,30:Nicaragua,31:Panama,32:Paraguay,33:Peru,34:Portugal,35:Peoples Republic of China,36:Puerto Rico,37:Russia,38:Singapore,39:South Africa,40:Spain,41:Sweden,42:Switzerland,43:Taiwan,44:Trinidad,45:United Kingdom,46:United States,47:Uruguay,48:Venezuela.
|
||||
collections (bool): Use collection info from The Movie Database. Default value false .
|
||||
localart (bool): Prefer artwork based on library language. Default value true .
|
||||
adult (bool): Include adult content. Default value false .
|
||||
usage (bool): Send anonymous usage data to Plex. Default value true .
|
||||
|
||||
# movie com.plexapp.agents.themoviedb settings options
|
||||
collections (bool): Use collection info from The Movie Database. Default value false .
|
||||
localart (bool): Prefer artwork based on library language. Default value true .
|
||||
adult (bool): Include adult content. Default value false .
|
||||
country (int): Country (used for release date and content rating). Default value 47 Possible options: 0:,1:Argentina,2:Australia,3:Austria,4:Belgium,5:Belize,6:Bolivia,7:Brazil,8:Canada,9:Chile,10:Colombia,11:Costa Rica,12:Czech Republic,13:Denmark,14:Dominican Republic,15:Ecuador,16:El Salvador,17:France,18:Germany,19:Guatemala,20:Honduras,21:Hong Kong SAR,22:Ireland,23:Italy,24:Jamaica,25:Korea,26:Liechtenstein,27:Luxembourg,28:Mexico,29:Netherlands,30:New Zealand,31:Nicaragua,32:Panama,33:Paraguay,34:Peru,35:Portugal,36:Peoples Republic of China,37:Puerto Rico,38:Russia,39:Singapore,40:South Africa,41:Spain,42:Sweden,43:Switzerland,44:Taiwan,45:Trinidad,46:United Kingdom,47:United States,48:Uruguay,49:Venezuela.
|
||||
|
||||
# Prefs for show
|
||||
agent (str): com.plexapp.agents.none, com.plexapp.agents.thetvdb, com.plexapp.agents.themoviedb
|
||||
enableBIFGeneration (bool): Enable video preview thumbnails. Default value true .
|
||||
episodeSort (int): Episode order. Default value -1 Possible options: 0:Oldest first,1:Newest first.
|
||||
flattenSeasons (int): Seasons. Default value 0 Possible options: 0:Show,1:Hide.
|
||||
includeInGlobal (bool): Include in dashboard. Default value true .
|
||||
scanner (str): Plex Series Scanner
|
||||
|
||||
# show com.plexapp.agents.thetvdb settings options
|
||||
extras (bool): Find trailers and extras automatically (Plex Pass required). Default value true .
|
||||
native_subs (bool): Include extras with subtitles in Library language. Default value false .
|
||||
|
||||
# show com.plexapp.agents.themoviedb settings
|
||||
collections (bool): Use collection info from The Movie Database. Default value false .
|
||||
localart (bool): Prefer artwork based on library language. Default value true .
|
||||
adult (bool): Include adult content. Default value false .
|
||||
country (int): Country (used for release date and content rating). Default value 47 Possible options: 0:,1:Argentina,2:Australia,3:Austria,4:Belgium,5:Belize,6:Bolivia,7:Brazil,8:Canada,9:Chile,10:Colombia,11:Costa Rica,12:Czech Republic,13:Denmark,14:Dominican Republic,15:Ecuador,16:El Salvador,17:France,18:Germany,19:Guatemala,20:Honduras,21:Hong Kong SAR,22:Ireland,23:Italy,24:Jamaica,25:Korea,26:Liechtenstein,27:Luxembourg,28:Mexico,29:Netherlands,30:New Zealand,31:Nicaragua,32:Panama,33:Paraguay,34:Peru,35:Portugal,36:Peoples Republic of China,37:Puerto Rico,38:Russia,39:Singapore,40:South Africa,41:Spain,42:Sweden,43:Switzerland,44:Taiwan,45:Trinidad,46:United Kingdom,47:United States,48:Uruguay,49:Venezuela.
|
||||
|
||||
|
||||
|
||||
"""
|
||||
part = '/library/sections?name=%s&type=%s&agent=%s&scanner=%s&language=%s&location=%s' % (
|
||||
quote_plus(name), type, agent, quote_plus(scanner), language, quote_plus(location)) # noqa E126
|
||||
|
||||
if kwargs:
|
||||
part += urlencode(kwargs)
|
||||
return self._server.query(part, method=self._server._session.post)
|
||||
|
||||
|
||||
class LibrarySection(PlexObject):
|
||||
""" Base class for a single library section.
|
||||
|
@ -204,6 +305,24 @@ class LibrarySection(PlexObject):
|
|||
log.error(msg)
|
||||
raise
|
||||
|
||||
def edit(self, **kwargs):
|
||||
"""Edit a library
|
||||
|
||||
See :class:`~plexapi.library.Library for example usage.
|
||||
|
||||
Note: agent is required.
|
||||
|
||||
kwargs (dict): Dict of settings to edit.
|
||||
|
||||
"""
|
||||
part = '/library/sections/%s?%s' % (self.key, urlencode(kwargs))
|
||||
self._server.query(part, method=self._server._session.put)
|
||||
|
||||
# Reload this way since the self.key dont have a full path, but is simply a id.
|
||||
for s in self._server.library.sections():
|
||||
if s.key == self.key:
|
||||
return s
|
||||
|
||||
def get(self, title):
|
||||
""" Returns the media item with the specified title.
|
||||
|
||||
|
@ -292,6 +411,38 @@ class LibrarySection(PlexObject):
|
|||
key = '/library/sections/%s/%s%s' % (self.key, category, utils.joinArgs(args))
|
||||
return self.fetchItems(key, cls=FilterChoice)
|
||||
|
||||
def share(self, user, **kwargs):
|
||||
"""Share this library with the user.
|
||||
|
||||
user (str): username as a string or :class:`~plexapi.myplex.MyPlexUser`
|
||||
kwargs (dict): Shared settings should be passed as kwargs.
|
||||
"""
|
||||
# So im not really sure where is belongs but it works. still need docs for kwargs.
|
||||
|
||||
# Allow passing a User
|
||||
if isinstance(user, type):
|
||||
user = user.username
|
||||
|
||||
# Grab the section ids, note this is NOT the same as the regular that the library has.
|
||||
uri = 'https://plex.tv/api/servers/%s?X-Plex-Token=%s' % (self._server.machineIdentifier, self._server._token)
|
||||
server = self._server.query(uri)
|
||||
library_section_ids = [section.attrib.get('id') for section in server
|
||||
if section.attrib.get('title') == self.title]
|
||||
|
||||
cmd = {'shared_id': self._server.machineIdentifier,
|
||||
'shared_server': {'library_section_ids': library_section_ids,
|
||||
'invited_email': user},
|
||||
'sharing_settings': kwargs # empty means none
|
||||
|
||||
}
|
||||
|
||||
# Json content type seems to be req.
|
||||
h = {"Content-Type": "application/json"}
|
||||
|
||||
share_uri = 'https://plex.tv/api/servers/%s/shared_servers?X-Plex-Token=%s' % (
|
||||
self._server.machineIdentifier, self._server._token)
|
||||
r = self._server._session.post(share_uri, json=cmd, headers=h)
|
||||
|
||||
def search(self, title=None, sort=None, maxresults=999999, libtype=None, **kwargs):
|
||||
""" Search the library. If there are many results, they will be fetched from the server
|
||||
in batches of X_PLEX_CONTAINER_SIZE amounts. If you're only looking for the first <num>
|
||||
|
@ -395,9 +546,9 @@ class MovieSection(LibrarySection):
|
|||
TYPE (str): 'movie'
|
||||
"""
|
||||
ALLOWED_FILTERS = ('unwatched', 'duplicate', 'year', 'decade', 'genre', 'contentRating',
|
||||
'collection', 'director', 'actor', 'country', 'studio', 'resolution')
|
||||
'collection', 'director', 'actor', 'country', 'studio', 'resolution')
|
||||
ALLOWED_SORT = ('addedAt', 'originallyAvailableAt', 'lastViewedAt', 'titleSort', 'rating',
|
||||
'mediaHeight', 'duration')
|
||||
'mediaHeight', 'duration')
|
||||
TAG = 'Directory'
|
||||
TYPE = 'movie'
|
||||
|
||||
|
@ -415,7 +566,7 @@ class ShowSection(LibrarySection):
|
|||
"""
|
||||
ALLOWED_FILTERS = ('unwatched', 'year', 'genre', 'contentRating', 'network', 'collection')
|
||||
ALLOWED_SORT = ('addedAt', 'lastViewedAt', 'originallyAvailableAt', 'titleSort',
|
||||
'rating', 'unwatched')
|
||||
'rating', 'unwatched')
|
||||
TAG = 'Directory'
|
||||
TYPE = 'show'
|
||||
|
||||
|
|
|
@ -265,7 +265,11 @@ class PlexServer(PlexObject):
|
|||
by encoding the response to utf-8 and parsing the returned XML into and
|
||||
ElementTree object. Returns None if no data exists in the response.
|
||||
"""
|
||||
url = self.url(key)
|
||||
if not key.startswith('http'):
|
||||
url = self.url(key)
|
||||
else:
|
||||
url = key
|
||||
|
||||
method = method or self._session.get
|
||||
log.debug('%s %s', method.__name__.upper(), url)
|
||||
headers = self._headers(**headers or {})
|
||||
|
@ -349,7 +353,7 @@ class PlexServer(PlexObject):
|
|||
delim = '&' if '?' in key else '?'
|
||||
return '%s%s%sX-Plex-Token=%s' % (self._baseurl, key, delim, self._token)
|
||||
return '%s%s' % (self._baseurl, key)
|
||||
|
||||
|
||||
|
||||
class Account(PlexObject):
|
||||
""" Contains the locally cached MyPlex account information. The properties provided don't
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from collections import defaultdict
|
||||
|
||||
from plexapi import log, utils
|
||||
from plexapi.base import PlexObject
|
||||
from plexapi.compat import string_type, quote
|
||||
from plexapi.compat import quote, string_type
|
||||
from plexapi.exceptions import BadRequest, NotFound
|
||||
|
||||
|
||||
|
@ -149,3 +150,7 @@ class Setting(PlexObject):
|
|||
# store value off to the side until we call settings.save()
|
||||
tostr = self.TYPES[self.type]['tostr']
|
||||
self._setValue = tostr(value)
|
||||
|
||||
def toUrl(self):
|
||||
"""Helper for urls"""
|
||||
return '%s=%s' % (self.id, self._value or self.value)
|
||||
|
|
|
@ -76,6 +76,22 @@ def test_library_search(pms):
|
|||
m = pms.library.search('16 blocks')[0]
|
||||
assert m.title == '16 Blocks'
|
||||
|
||||
def test_library_add_edit_delete(pms):
|
||||
d = dict(name='zomg strange11', type='movie', agent='com.plexapp.agents.imdb',
|
||||
scanner='Plex Movie Scanner', language='en')
|
||||
|
||||
rn = dict(name='a renamed lib', type='movie', agent='com.plexapp.agents.imdb')
|
||||
|
||||
# We dont want to add a location because we dont want to start scanning.
|
||||
pms.library.add(**d)
|
||||
|
||||
assert pms.library.section('zomg strange11')
|
||||
|
||||
edited_library = pms.library.section('zomg strange11').edit(**rn)
|
||||
assert edited_library.title == 'a renamed lib'
|
||||
|
||||
pms.library.section('a renamed lib').delete()
|
||||
|
||||
|
||||
def test_library_Library_cleanBundle(pms):
|
||||
pms.library.cleanBundles()
|
||||
|
|
53
tools/atter_doc_string.py
Normal file
53
tools/atter_doc_string.py
Normal file
|
@ -0,0 +1,53 @@
|
|||
from collections import OrderedDict
|
||||
import re
|
||||
|
||||
def type_finder(s):
|
||||
type_string = str(type(s))
|
||||
x = re.search("'(.+)'", type_string)
|
||||
if x:
|
||||
return x.group(1)
|
||||
|
||||
return ''
|
||||
|
||||
|
||||
class AttDS(object):
|
||||
"""Helper that prints docstring attrs"""
|
||||
|
||||
def __init__(self, o, keys=None, style='google'):
|
||||
self.__o = o
|
||||
|
||||
if not isinstance(o, dict):
|
||||
self.o = o.__dict__.items()
|
||||
self._as_dict = o.__dict__
|
||||
else:
|
||||
self.o = o.items()
|
||||
self._as_dict = o
|
||||
|
||||
if keys is None:
|
||||
self.keys = self._as_dict.keys()
|
||||
else:
|
||||
self.keys = keys
|
||||
|
||||
if style == 'google':
|
||||
self.template = '%s (%s): %s'
|
||||
|
||||
self.res_dict = OrderedDict()
|
||||
self.parse()
|
||||
|
||||
def parse(self):
|
||||
for k, v in sorted(self.o, key=lambda k: k[0]):
|
||||
if self.keys:
|
||||
ds = ''
|
||||
for key in self.keys:
|
||||
ds += '%s=%s ' % (key, self._as_dict.get(key, ''))
|
||||
else:
|
||||
ds = ''
|
||||
|
||||
self.res_dict[k] = self.template % (k, type_finder(v), ds)
|
||||
|
||||
def write(self):
|
||||
for k, v in self.res_dict.items():
|
||||
print v
|
||||
|
||||
|
||||
#x = AttDS(dict or object).write()
|
Loading…
Reference in a new issue