mirror of
https://github.com/pkkid/python-plexapi
synced 2024-11-10 06:04:15 +00:00
Cleanup formatting
This commit is contained in:
parent
6e761f0fc5
commit
cec0ab07e8
13 changed files with 137 additions and 175 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -17,7 +17,6 @@ include/
|
|||
lib/
|
||||
pip-selfcheck.json
|
||||
pyvenv.cfg
|
||||
|
||||
htmlcov
|
||||
.coverage
|
||||
*.orig
|
|
@ -1,2 +1,2 @@
|
|||
include README.md
|
||||
include requirements.pip
|
||||
include requirements.txt
|
|
@ -132,13 +132,24 @@ class Artist(Audio):
|
|||
return self.track(title)
|
||||
|
||||
def download(self, savepath=None, keep_orginal_name=False, **kwargs):
|
||||
""" Downloads all tracks for this artist to the specified location.
|
||||
|
||||
Parameters:
|
||||
savepath (str): Title of the track to return.
|
||||
keep_orginal_name (bool): Set True to keep the original filename as stored in
|
||||
the Plex server. False will create a new filename with the format
|
||||
"<Atrist> - <Album> <Track>".
|
||||
kwargs (dict): If specified, a :func:`~plexapi.audio.Track.getStreamURL()` will
|
||||
be returned and the additional arguments passed in will be sent to that
|
||||
function. If kwargs is not specified, the media items will be downloaded
|
||||
and saved to disk.
|
||||
"""
|
||||
downloaded = []
|
||||
for album in self.albums():
|
||||
for track in album.tracks():
|
||||
dl = track.download(savepath=savepath, keep_orginal_name=keep_orginal_name, **kwargs)
|
||||
if dl:
|
||||
downloaded.extend(dl)
|
||||
|
||||
return downloaded
|
||||
|
||||
|
||||
|
@ -203,6 +214,18 @@ class Album(Audio):
|
|||
return utils.listItems(self.server, self.parentKey)[0]
|
||||
|
||||
def download(self, savepath=None, keep_orginal_name=False, **kwargs):
|
||||
""" Downloads all tracks for this artist to the specified location.
|
||||
|
||||
Parameters:
|
||||
savepath (str): Title of the track to return.
|
||||
keep_orginal_name (bool): Set True to keep the original filename as stored in
|
||||
the Plex server. False will create a new filename with the format
|
||||
"<Atrist> - <Album> <Track>".
|
||||
kwargs (dict): If specified, a :func:`~plexapi.audio.Track.getStreamURL()` will
|
||||
be returned and the additional arguments passed in will be sent to that
|
||||
function. If kwargs is not specified, the media items will be downloaded
|
||||
and saved to disk.
|
||||
"""
|
||||
downloaded = []
|
||||
for ep in self.tracks():
|
||||
dl = ep.download(savepath=savepath, keep_orginal_name=keep_orginal_name, **kwargs)
|
||||
|
@ -276,7 +299,7 @@ class Track(Audio, Playable):
|
|||
self.year = utils.cast(int, data.attrib.get('year', NA))
|
||||
# media is included in /children
|
||||
self.media = [media.Media(self.server, e, self.initpath, self)
|
||||
for e in data if e.tag == media.Media.TYPE]
|
||||
for e in data if e.tag == media.Media.TYPE]
|
||||
if self.isFullObject(): # check me
|
||||
self.moods = [media.Mood(self.server, e) for e in data if e.tag == media.Mood.TYPE]
|
||||
#self.media = [media.Media(self.server, e, self.initpath, self)
|
||||
|
@ -302,37 +325,5 @@ class Track(Audio, Playable):
|
|||
return utils.listItems(self.server, self.grandparentKey)[0]
|
||||
|
||||
def _prettyfilename(self):
|
||||
""" Returns a filename for use in download. """
|
||||
return '%s - %s %s' % (self.grandparentTitle, self.parentTitle, self.title)
|
||||
|
||||
'''
|
||||
def download(self, savepath=None, keep_orginal_name=False, **kwargs):
|
||||
"""Download a episode. If kwargs are passed your can download a trancoded file.
|
||||
|
||||
Args:
|
||||
savepath (str): Abs path to savefolder
|
||||
keep_orginal_name (bool): Use the mediafiles orginal name
|
||||
|
||||
kwargs:
|
||||
See getStreamURL docs.
|
||||
|
||||
"""
|
||||
downloaded = []
|
||||
locs = [i for i in self.iterParts() if i]
|
||||
for loc in locs:
|
||||
if keep_orginal_name is False:
|
||||
name = '%s.%s' % (self._prettyfilename(), loc.container)
|
||||
else:
|
||||
name = loc.file
|
||||
|
||||
# So this seems to be a alot slower but allows transcode.
|
||||
if kwargs:
|
||||
download_url = self.getStreamURL(**kwargs)
|
||||
else:
|
||||
download_url = self.server.url('%s?download=1' % loc.key)
|
||||
|
||||
dl = utils.download(download_url, filename=name, savepath=savepath, session=self.server.session)
|
||||
if dl:
|
||||
downloaded.append(dl)
|
||||
|
||||
return downloaded
|
||||
'''
|
||||
|
|
|
@ -47,10 +47,8 @@ class PlexClient(object):
|
|||
self.token = token
|
||||
self.server = server
|
||||
# session > server.session > requests.Session
|
||||
if server:
|
||||
self.session = session or server.session
|
||||
else:
|
||||
self.session = session or requests.Session()
|
||||
_server_session = server.session if server else None
|
||||
self.session = session or _server_session or requests.Session()
|
||||
self._loadData(data) if data is not None else self.connect()
|
||||
self._proxyThroughServer = False
|
||||
self._commandId = 0
|
||||
|
@ -405,8 +403,7 @@ class PlexClient(object):
|
|||
:class:`~plexapi.exceptions.Unsupported`: When no PlexServer specified in this object.
|
||||
"""
|
||||
if not self.server:
|
||||
raise Unsupported(
|
||||
'A server must be specified before using this command.')
|
||||
raise Unsupported('A server must be specified before using this command.')
|
||||
server_url = media.server.baseurl.split(':')
|
||||
playqueue = self.server.createPlayQueue(media)
|
||||
self.sendCommand('playback/playMedia', **dict({
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Python 2/3 compatability
|
||||
# Always try Py3 first
|
||||
import sys
|
||||
|
||||
try:
|
||||
string_type = basestring
|
||||
|
|
|
@ -25,4 +25,5 @@ class Unauthorized(PlexApiException):
|
|||
pass
|
||||
|
||||
class NotImplementedError(PlexApiException):
|
||||
""" Feature is not yet implemented. """
|
||||
pass
|
||||
|
|
|
@ -23,7 +23,7 @@ class Library(object):
|
|||
self.server = server
|
||||
self.title1 = data.attrib.get('title1')
|
||||
self.title2 = data.attrib.get('title2')
|
||||
self._sectionsByID = {} # cached section UUIDs
|
||||
self._sectionsByID = {} # cached Section UUIDs
|
||||
|
||||
def __repr__(self):
|
||||
return '<Library:%s>' % self.title1.encode('utf8')
|
||||
|
@ -131,9 +131,8 @@ class Library(object):
|
|||
removed. Removing these old bundles can reduce the size of your install. By default, your
|
||||
server will automatically clean up old bundles once a week as part of Scheduled Tasks.
|
||||
"""
|
||||
# TODO: Should this check the response for success or the correct mediaprefix?
|
||||
self.server.query('/library/clean/bundles')
|
||||
# Should this return true or false?
|
||||
# check element if if has the correct mediaprefix?
|
||||
|
||||
def emptyTrash(self):
|
||||
""" If a library has items in the Library Trash, use this option to empty the Trash. """
|
||||
|
@ -380,9 +379,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')
|
||||
TYPE = 'movie'
|
||||
|
||||
|
||||
|
@ -398,7 +397,7 @@ class ShowSection(LibrarySection):
|
|||
"""
|
||||
ALLOWED_FILTERS = ('unwatched', 'year', 'genre', 'contentRating', 'network', 'collection')
|
||||
ALLOWED_SORT = ('addedAt', 'lastViewedAt', 'originallyAvailableAt', 'titleSort',
|
||||
'rating', 'unwatched')
|
||||
'rating', 'unwatched')
|
||||
TYPE = 'show'
|
||||
|
||||
def searchShows(self, **kwargs):
|
||||
|
|
|
@ -174,15 +174,49 @@ class MediaTag(object):
|
|||
return '<%s:%s:%s>' % (self.__class__.__name__, self.id, tag)
|
||||
|
||||
|
||||
class Collection(MediaTag): TYPE = 'Collection'; FILTER = 'collection'
|
||||
class Country(MediaTag): TYPE = 'Country'; FILTER = 'country'
|
||||
class Director(MediaTag): TYPE = 'Director'; FILTER = 'director'
|
||||
class Genre(MediaTag): TYPE = 'Genre'; FILTER = 'genre'
|
||||
class Mood(MediaTag): TYPE = 'Mood'; FILTER = 'mood'
|
||||
class Producer(MediaTag): TYPE = 'Producer'; FILTER = 'producer'
|
||||
class Role(MediaTag): TYPE = 'Role'; FILTER = 'role'
|
||||
class Similar(MediaTag): TYPE = 'Similar'; FILTER = 'similar'
|
||||
class Writer(MediaTag): TYPE = 'Writer'; FILTER = 'writer'
|
||||
class Collection(MediaTag):
|
||||
TYPE = 'Collection'
|
||||
FILTER = 'collection'
|
||||
|
||||
|
||||
class Country(MediaTag):
|
||||
TYPE = 'Country'
|
||||
FILTER = 'country'
|
||||
|
||||
|
||||
class Director(MediaTag):
|
||||
TYPE = 'Director'
|
||||
FILTER = 'director'
|
||||
|
||||
|
||||
class Genre(MediaTag):
|
||||
TYPE = 'Genre'
|
||||
FILTER = 'genre'
|
||||
|
||||
|
||||
class Mood(MediaTag):
|
||||
TYPE = 'Mood'
|
||||
FILTER = 'mood'
|
||||
|
||||
|
||||
class Producer(MediaTag):
|
||||
TYPE = 'Producer'
|
||||
FILTER = 'producer'
|
||||
|
||||
|
||||
class Role(MediaTag):
|
||||
TYPE = 'Role'
|
||||
FILTER = 'role'
|
||||
|
||||
|
||||
class Similar(MediaTag):
|
||||
TYPE = 'Similar'
|
||||
FILTER = 'similar'
|
||||
|
||||
|
||||
class Writer(MediaTag):
|
||||
TYPE = 'Writer'
|
||||
FILTER = 'writer'
|
||||
|
||||
|
||||
class Field(object):
|
||||
|
|
|
@ -72,7 +72,7 @@ class MyPlexAccount(object):
|
|||
self.title = data.attrib.get('title')
|
||||
self.username = data.attrib.get('username')
|
||||
self.uuid = data.attrib.get('uuid')
|
||||
# TODO: Complete these items!
|
||||
# TODO: Fetch missing MyPlexAccount attributes
|
||||
self.subscriptionActive = None # renamed on server
|
||||
self.subscriptionStatus = None # renamed on server
|
||||
self.subscriptionPlan = None # renmaed on server
|
||||
|
@ -143,8 +143,7 @@ class MyPlexAccount(object):
|
|||
if response.status_code != requests.codes.created:
|
||||
codename = codes.get(response.status_code)[0]
|
||||
if response.status_code == 401:
|
||||
raise Unauthorized('(%s) %s' %
|
||||
(response.status_code, codename))
|
||||
raise Unauthorized('(%s) %s' % (response.status_code, codename))
|
||||
raise BadRequest('(%s) %s' % (response.status_code, codename))
|
||||
data = ElementTree.fromstring(response.text.encode('utf8'))
|
||||
return MyPlexAccount(data, cls.SIGNIN, session=sess)
|
||||
|
@ -348,7 +347,6 @@ class MyPlexDevice(object):
|
|||
vendor (str): Device vendor (ubuntu, etc).
|
||||
version (str): Unknown (1, 2, 1.3.3.3148-b38628e, 1.3.15, etc.)
|
||||
"""
|
||||
|
||||
BASEURL = 'https://plex.tv/devices.xml'
|
||||
|
||||
def __init__(self, data):
|
||||
|
|
|
@ -34,10 +34,8 @@ class PlayQueue(object):
|
|||
self.mediaTagPrefix = data.attrib.get('mediaTagPrefix')
|
||||
self.mediaTagVersion = data.attrib.get('mediaTagVersion')
|
||||
self.playQueueID = data.attrib.get('playQueueID')
|
||||
self.playQueueSelectedItemID = data.attrib.get(
|
||||
'playQueueSelectedItemID')
|
||||
self.playQueueSelectedItemOffset = data.attrib.get(
|
||||
'playQueueSelectedItemOffset')
|
||||
self.playQueueSelectedItemID = data.attrib.get('playQueueSelectedItemID')
|
||||
self.playQueueSelectedItemOffset = data.attrib.get('playQueueSelectedItemOffset')
|
||||
self.playQueueTotalCount = data.attrib.get('playQueueTotalCount')
|
||||
self.playQueueVersion = data.attrib.get('playQueueVersion')
|
||||
self.items = [utils.buildItem(server, elem, initpath) for elem in data]
|
||||
|
|
100
plexapi/utils.py
100
plexapi/utils.py
|
@ -1,24 +1,13 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import logging, os, re, requests
|
||||
from datetime import datetime
|
||||
from threading import Thread
|
||||
|
||||
import requests
|
||||
|
||||
|
||||
from plexapi.compat import quote, string_type, urlencode
|
||||
from plexapi.exceptions import NotFound, NotImplementedError, UnknownType, Unsupported
|
||||
#from plexapi import log
|
||||
|
||||
|
||||
# Search Types - Plex uses these to filter specific media types when searching.
|
||||
SEARCHTYPES = {'movie': 1, 'show': 2, 'season': 3,
|
||||
'episode': 4, 'artist': 8, 'album': 9, 'track': 10,
|
||||
'photo': 14}
|
||||
|
||||
|
||||
SEARCHTYPES = {'movie': 1, 'show': 2, 'season': 3, 'episode': 4,
|
||||
'artist': 8, 'album': 9, 'track': 10, 'photo': 14}
|
||||
LIBRARY_TYPES = {}
|
||||
|
||||
|
||||
|
@ -50,9 +39,7 @@ class _NA(object):
|
|||
def __repr__(self):
|
||||
return '__NA__'
|
||||
|
||||
|
||||
# Lets do this for now.
|
||||
NA = _NA()
|
||||
NA = _NA() # Keep this for now.
|
||||
|
||||
|
||||
class SecretsFilter(logging.Filter):
|
||||
|
@ -208,35 +195,35 @@ class Playable(object):
|
|||
client.playMedia(self)
|
||||
|
||||
def download(self, savepath=None, keep_orginal_name=False, **kwargs):
|
||||
"""Download a episode. If kwargs are passed your can download a trancoded file.
|
||||
|
||||
Args:
|
||||
savepath (str): Abs path to savefolder
|
||||
keep_orginal_name (bool): Use the mediafiles orginal name
|
||||
|
||||
kwargs:
|
||||
See getStreamURL docs.
|
||||
|
||||
""" Downloads this items media to the specified location. Returns a list of
|
||||
filepaths that have been saved to disk.
|
||||
|
||||
Parameters:
|
||||
savepath (str): Title of the track to return.
|
||||
keep_orginal_name (bool): Set True to keep the original filename as stored in
|
||||
the Plex server. False will create a new filename with the format
|
||||
"<Atrist> - <Album> <Track>".
|
||||
kwargs (dict): If specified, a :func:`~plexapi.audio.Track.getStreamURL()` will
|
||||
be returned and the additional arguments passed in will be sent to that
|
||||
function. If kwargs is not specified, the media items will be downloaded
|
||||
and saved to disk.
|
||||
"""
|
||||
downloaded = []
|
||||
locs = [i for i in self.iterParts() if i]
|
||||
for loc in locs:
|
||||
filepaths = []
|
||||
locations = [i for i in self.iterParts() if i]
|
||||
for location in locations:
|
||||
filename = location.file
|
||||
if keep_orginal_name is False:
|
||||
name = '%s.%s' % (self._prettyfilename(), loc.container)
|
||||
else:
|
||||
name = loc.file
|
||||
|
||||
filename = '%s.%s' % (self._prettyfilename(), location.container)
|
||||
# So this seems to be a alot slower but allows transcode.
|
||||
if kwargs:
|
||||
download_url = self.getStreamURL(**kwargs)
|
||||
else:
|
||||
download_url = self.server.url('%s?download=1' % loc.key)
|
||||
|
||||
dl = download(download_url, filename=name, savepath=savepath, session=self.server.session)
|
||||
if dl:
|
||||
downloaded.append(dl)
|
||||
|
||||
return downloaded
|
||||
download_url = self.server.url('%s?download=1' % location.key)
|
||||
filepath = download(download_url, filename=filename, savepath=savepath,
|
||||
session=self.server.session)
|
||||
if filepath:
|
||||
filepaths.append(filepath)
|
||||
return filepaths
|
||||
|
||||
|
||||
def buildItem(server, elem, initpath, bytag=False):
|
||||
|
@ -538,27 +525,22 @@ def toDatetime(value, format=None):
|
|||
|
||||
|
||||
def download(url, filename=None, savepath=None, session=None, chunksize=4024, mocked=False):
|
||||
"""Helper to download a thumb, videofile or something.
|
||||
""" Helper to download a thumb, videofile or other media item. Returns the local
|
||||
path to the downloaded file.
|
||||
|
||||
Args:
|
||||
url (str): url where the content be reached
|
||||
filename (str): Filename of the downloaded file, default None
|
||||
savepath (str): Defaults to current working dir
|
||||
chunksize (int): What chunksize read/write at the time
|
||||
Parameters:
|
||||
url (str): URL where the content be reached.
|
||||
filename (str): Filename of the downloaded file, default None.
|
||||
savepath (str): Defaults to current working dir.
|
||||
chunksize (int): What chunksize read/write at the time.
|
||||
mocked (bool): Helper to do evertything except write the file.
|
||||
|
||||
Example:
|
||||
|
||||
>>> download(a_episode.getStreamURL(), a_episode.location)
|
||||
/path/to/file
|
||||
|
||||
Returns:
|
||||
/path/to/file or None
|
||||
|
||||
"""
|
||||
session = session or requests.Session()
|
||||
print('Mocked download %s' % mocked)
|
||||
|
||||
if savepath is None:
|
||||
savepath = os.getcwd()
|
||||
else:
|
||||
|
@ -568,13 +550,10 @@ def download(url, filename=None, savepath=None, session=None, chunksize=4024, mo
|
|||
except OSError:
|
||||
if not os.path.isdir(savepath): # pragma: no cover
|
||||
raise
|
||||
|
||||
filename = os.path.basename(filename)
|
||||
fullpath = os.path.join(savepath, filename)
|
||||
|
||||
try:
|
||||
response = session.get(url, stream=True)
|
||||
|
||||
# images dont have a extention so we try
|
||||
# to guess it from content-type
|
||||
ext = os.path.splitext(fullpath)[-1]
|
||||
|
@ -582,25 +561,18 @@ def download(url, filename=None, savepath=None, session=None, chunksize=4024, mo
|
|||
ext = ''
|
||||
else:
|
||||
cp = response.headers.get('content-type')
|
||||
|
||||
if cp:
|
||||
if 'image' in cp:
|
||||
ext = '.%s' % cp.split('/')[1]
|
||||
|
||||
fullpath = '%s%s' % (fullpath, ext)
|
||||
|
||||
if mocked:
|
||||
return fullpath
|
||||
|
||||
with open(fullpath, 'wb') as f:
|
||||
for chunk in response.iter_content(chunk_size=chunksize):
|
||||
if chunk:
|
||||
f.write(chunk)
|
||||
|
||||
#log.debug('Downloaded %s to %s from %s' % (filename, fullpath, url))
|
||||
|
||||
return fullpath
|
||||
|
||||
except Exception as e: # pragma: no cover
|
||||
print('e %s' % e)
|
||||
except Exception as err: # pragma: no cover
|
||||
print('Error downloading file: %s' % err)
|
||||
#log.exception('Failed to download %s to %s %s' % (url, fullpath, e))
|
||||
|
|
|
@ -29,8 +29,7 @@ class Video(PlexPartialObject):
|
|||
self.listType = 'video'
|
||||
self.addedAt = utils.toDatetime(data.attrib.get('addedAt', NA))
|
||||
self.key = data.attrib.get('key', NA)
|
||||
self.lastViewedAt = utils.toDatetime(
|
||||
data.attrib.get('lastViewedAt', NA))
|
||||
self.lastViewedAt = utils.toDatetime(data.attrib.get('lastViewedAt', NA))
|
||||
self.librarySectionID = data.attrib.get('librarySectionID', NA)
|
||||
self.ratingKey = utils.cast(int, data.attrib.get('ratingKey', NA))
|
||||
self.summary = data.attrib.get('summary', NA)
|
||||
|
@ -110,24 +109,15 @@ class Movie(Video, Playable):
|
|||
self.viewOffset = utils.cast(int, data.attrib.get('viewOffset', 0))
|
||||
self.year = utils.cast(int, data.attrib.get('year', NA))
|
||||
if self.isFullObject(): # check this
|
||||
self.collections = [media.Collection(
|
||||
self.server, e) for e in data if e.tag == media.Collection.TYPE]
|
||||
self.countries = [media.Country(self.server, e)
|
||||
for e in data if e.tag == media.Country.TYPE]
|
||||
self.directors = [media.Director(
|
||||
self.server, e) for e in data if e.tag == media.Director.TYPE]
|
||||
self.genres = [media.Genre(self.server, e)
|
||||
for e in data if e.tag == media.Genre.TYPE]
|
||||
self.media = [media.Media(self.server, e, self.initpath, self)
|
||||
for e in data if e.tag == media.Media.TYPE]
|
||||
self.producers = [media.Producer(
|
||||
self.server, e) for e in data if e.tag == media.Producer.TYPE]
|
||||
self.roles = [media.Role(self.server, e)
|
||||
for e in data if e.tag == media.Role.TYPE]
|
||||
self.writers = [media.Writer(self.server, e)
|
||||
for e in data if e.tag == media.Writer.TYPE]
|
||||
self.fields = [media.Field(e)
|
||||
for e in data if e.tag == media.Field.TYPE]
|
||||
self.collections = [media.Collection(self.server, e) for e in data if e.tag == media.Collection.TYPE]
|
||||
self.countries = [media.Country(self.server, e) for e in data if e.tag == media.Country.TYPE]
|
||||
self.directors = [media.Director(self.server, e) for e in data if e.tag == media.Director.TYPE]
|
||||
self.genres = [media.Genre(self.server, e) for e in data if e.tag == media.Genre.TYPE]
|
||||
self.media = [media.Media(self.server, e, self.initpath, self) for e in data if e.tag == media.Media.TYPE]
|
||||
self.producers = [media.Producer(self.server, e) for e in data if e.tag == media.Producer.TYPE]
|
||||
self.roles = [media.Role(self.server, e) for e in data if e.tag == media.Role.TYPE]
|
||||
self.writers = [media.Writer(self.server, e) for e in data if e.tag == media.Writer.TYPE]
|
||||
self.fields = [media.Field(e) for e in data if e.tag == media.Field.TYPE]
|
||||
self.videoStreams = utils.findStreams(self.media, 'videostream')
|
||||
self.audioStreams = utils.findStreams(self.media, 'audiostream')
|
||||
self.subtitleStreams = utils.findStreams(
|
||||
|
@ -145,7 +135,6 @@ class Movie(Video, Playable):
|
|||
def location(self):
|
||||
""" This does not exist in plex xml response but is added to have a common
|
||||
interface to get the location of the Movie/Show/Episode
|
||||
|
||||
"""
|
||||
files = [i.file for i in self.iterParts() if i]
|
||||
if len(files) == 1:
|
||||
|
@ -161,17 +150,14 @@ class Movie(Video, Playable):
|
|||
name = '%s.%s' % (self.title.replace(' ', '.'), loc.container)
|
||||
else:
|
||||
name = loc.file
|
||||
|
||||
# So this seems to be a alot slower but allows transcode.
|
||||
if kwargs:
|
||||
download_url = self.getStreamURL(**kwargs)
|
||||
else:
|
||||
download_url = self.server.url('%s?download=1' % loc.key)
|
||||
|
||||
dl = utils.download(download_url, filename=name, savepath=savepath, session=self.server.session)
|
||||
if dl:
|
||||
downloaded.append(dl)
|
||||
|
||||
return downloaded
|
||||
|
||||
|
||||
|
@ -313,10 +299,8 @@ class Show(Video):
|
|||
downloaded = []
|
||||
for ep in self.episodes():
|
||||
dl = ep.download(savepath=savepath, keep_orginal_name=keep_orginal_name, **kwargs)
|
||||
|
||||
if dl:
|
||||
downloaded.extend(dl)
|
||||
|
||||
return downloaded
|
||||
|
||||
|
||||
|
@ -389,18 +373,14 @@ class Season(Video):
|
|||
"""
|
||||
if not title and not episode:
|
||||
raise TypeError('Missing argument, you need to use title or episode.')
|
||||
|
||||
if title:
|
||||
path = '/library/metadata/%s/children' % self.ratingKey
|
||||
return utils.findItem(self.server, path, title)
|
||||
|
||||
elif episode:
|
||||
results = [i for i in self.episodes()
|
||||
if i.seasonNumber == self.index and i.index == episode]
|
||||
results = [i for i in self.episodes() if i.seasonNumber == self.index and i.index == episode]
|
||||
if results:
|
||||
return results[0]
|
||||
else:
|
||||
raise NotFound('Couldnt find %s.Season %s Episode %s.' % (self.grandparentTitle, self.index. episode))
|
||||
raise NotFound('Couldnt find %s.Season %s Episode %s.' % (self.grandparentTitle, self.index. episode))
|
||||
|
||||
def get(self, title):
|
||||
"""Get a episode with a matching title.
|
||||
|
@ -437,7 +417,6 @@ class Season(Video):
|
|||
dl = ep.download(savepath=savepath, keep_orginal_name=keep_orginal_name, **kwargs)
|
||||
if dl:
|
||||
downloaded.extend(dl)
|
||||
|
||||
return downloaded
|
||||
|
||||
|
||||
|
@ -465,8 +444,7 @@ class Episode(Video, Playable):
|
|||
self.grandparentTitle = data.attrib.get('grandparentTitle', NA)
|
||||
self.guid = data.attrib.get('guid', NA)
|
||||
self.index = utils.cast(int, data.attrib.get('index', NA))
|
||||
self.originallyAvailableAt = utils.toDatetime(
|
||||
data.attrib.get('originallyAvailableAt', NA), '%Y-%m-%d')
|
||||
self.originallyAvailableAt = utils.toDatetime(data.attrib.get('originallyAvailableAt', NA), '%Y-%m-%d')
|
||||
self.parentIndex = data.attrib.get('parentIndex', NA)
|
||||
self.parentKey = data.attrib.get('parentKey', NA)
|
||||
self.parentRatingKey = utils.cast(int, data.attrib.get('parentRatingKey', NA))
|
||||
|
@ -474,12 +452,9 @@ class Episode(Video, Playable):
|
|||
self.rating = utils.cast(float, data.attrib.get('rating', NA))
|
||||
self.viewOffset = utils.cast(int, data.attrib.get('viewOffset', 0))
|
||||
self.year = utils.cast(int, data.attrib.get('year', NA))
|
||||
self.directors = [media.Director(self.server, e)
|
||||
for e in data if e.tag == media.Director.TYPE]
|
||||
self.media = [media.Media(self.server, e, self.initpath, self)
|
||||
for e in data if e.tag == media.Media.TYPE]
|
||||
self.writers = [media.Writer(self.server, e)
|
||||
for e in data if e.tag == media.Writer.TYPE]
|
||||
self.directors = [media.Director(self.server, e) for e in data if e.tag == media.Director.TYPE]
|
||||
self.media = [media.Media(self.server, e, self.initpath, self) for e in data if e.tag == media.Media.TYPE]
|
||||
self.writers = [media.Writer(self.server, e) for e in data if e.tag == media.Writer.TYPE]
|
||||
self.videoStreams = utils.findStreams(self.media, 'videostream')
|
||||
self.audioStreams = utils.findStreams(self.media, 'audiostream')
|
||||
self.subtitleStreams = utils.findStreams(self.media, 'subtitlestream')
|
||||
|
@ -527,14 +502,13 @@ class Episode(Video, Playable):
|
|||
def location(self):
|
||||
""" This does not exist in plex xml response but is added to have a common
|
||||
interface to get the location of the Movie/Show
|
||||
|
||||
"""
|
||||
# Note this should probably belong to some parent.
|
||||
files = [i.file for i in self.iterParts() if i]
|
||||
if len(files) == 1:
|
||||
files = files[0]
|
||||
|
||||
return files
|
||||
|
||||
def _prettyfilename(self):
|
||||
return '%s.S%sE%s' % (self.grandparentTitle.replace(' ', '.'), str(self.seasonNumber).zfill(2), str(self.index).zfill(2))
|
||||
return '%s.S%sE%s' % (self.grandparentTitle.replace(' ', '.'),
|
||||
str(self.seasonNumber).zfill(2), str(self.index).zfill(2))
|
||||
|
|
Loading…
Reference in a new issue