mirror of
https://github.com/pkkid/python-plexapi
synced 2025-02-18 05:48:26 +00:00
Tighten up download code a bit; downloadLogs and DownloadDatabases were reversed (oops)
This commit is contained in:
parent
55a38bead7
commit
43444459e3
4 changed files with 81 additions and 103 deletions
|
@ -1,6 +1,7 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Python 2/3 compatability
|
# Python 2/3 compatability
|
||||||
# Always try Py3 first
|
# Always try Py3 first
|
||||||
|
import os
|
||||||
|
|
||||||
try:
|
try:
|
||||||
string_type = basestring
|
string_type = basestring
|
||||||
|
@ -36,3 +37,12 @@ try:
|
||||||
from xml.etree import cElementTree as ElementTree
|
from xml.etree import cElementTree as ElementTree
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from xml.etree import ElementTree
|
from xml.etree import ElementTree
|
||||||
|
|
||||||
|
|
||||||
|
def makedirs(name, mode=0o777, exist_ok=False):
|
||||||
|
""" Mimicks os.makedirs() from Python 3. """
|
||||||
|
try:
|
||||||
|
os.makedirs(name, mode)
|
||||||
|
except OSError:
|
||||||
|
if not os.path.isdir(name) or not exist_ok:
|
||||||
|
raise
|
||||||
|
|
|
@ -175,7 +175,6 @@ class PlexServer(PlexObject):
|
||||||
def clients(self):
|
def clients(self):
|
||||||
""" Returns a list of all :class:`~plexapi.client.PlexClient` objects
|
""" Returns a list of all :class:`~plexapi.client.PlexClient` objects
|
||||||
connected to this server."""
|
connected to this server."""
|
||||||
|
|
||||||
items = []
|
items = []
|
||||||
cache_resource = None
|
cache_resource = None
|
||||||
from plexapi.myplex import MyPlexResource
|
from plexapi.myplex import MyPlexResource
|
||||||
|
@ -193,7 +192,6 @@ class PlexServer(PlexObject):
|
||||||
if conn.local is True:
|
if conn.local is True:
|
||||||
port = conn.port
|
port = conn.port
|
||||||
break
|
break
|
||||||
|
|
||||||
baseurl = 'http://%s:%s' % (elem.attrib['host'], port)
|
baseurl = 'http://%s:%s' % (elem.attrib['host'], port)
|
||||||
items.append(PlexClient(baseurl=baseurl, server=self, data=elem))
|
items.append(PlexClient(baseurl=baseurl, server=self, data=elem))
|
||||||
return items
|
return items
|
||||||
|
@ -231,6 +229,16 @@ class PlexServer(PlexObject):
|
||||||
"""
|
"""
|
||||||
return PlayQueue.create(self, item, **kwargs)
|
return PlayQueue.create(self, item, **kwargs)
|
||||||
|
|
||||||
|
def downloadDatabases(self, savepath=None, unpack=False):
|
||||||
|
url = self.url('/diagnostics/databases')
|
||||||
|
filepath = utils.download(url, None, savepath, self._session, unpack=unpack)
|
||||||
|
return filepath
|
||||||
|
|
||||||
|
def downloadLogs(self, savepath=None, unpack=False):
|
||||||
|
url = self.url('/diagnostics/logs')
|
||||||
|
filepath = utils.download(url, None, savepath, self._session, unpack=unpack)
|
||||||
|
return filepath
|
||||||
|
|
||||||
def history(self):
|
def history(self):
|
||||||
""" Returns a list of media items from watched history. """
|
""" Returns a list of media items from watched history. """
|
||||||
return self.fetchItems('/status/sessions/history/all')
|
return self.fetchItems('/status/sessions/history/all')
|
||||||
|
@ -341,17 +349,7 @@ class PlexServer(PlexObject):
|
||||||
delim = '&' if '?' in key else '?'
|
delim = '&' if '?' in key else '?'
|
||||||
return '%s%s%sX-Plex-Token=%s' % (self._baseurl, key, delim, self._token)
|
return '%s%s%sX-Plex-Token=%s' % (self._baseurl, key, delim, self._token)
|
||||||
return '%s%s' % (self._baseurl, key)
|
return '%s%s' % (self._baseurl, key)
|
||||||
|
|
||||||
def downloadLogs(self, savepath=None, unpack=False):
|
|
||||||
url = self.url('/diagnostics/databases')
|
|
||||||
fp = utils.download(url, filename=None, savepath=savepath, unpack=unpack, session=self._session)
|
|
||||||
return fp
|
|
||||||
|
|
||||||
def downloadDBS(self, savepath=None, unpack=False):
|
|
||||||
url = self.url('/diagnostics/logs')
|
|
||||||
fp = utils.download(url, filename=None, savepath=savepath, unpack=unpack, session=self._session)
|
|
||||||
return fp
|
|
||||||
|
|
||||||
|
|
||||||
class Account(PlexObject):
|
class Account(PlexObject):
|
||||||
""" Contains the locally cached MyPlex account information. The properties provided don't
|
""" Contains the locally cached MyPlex account information. The properties provided don't
|
||||||
|
|
102
plexapi/utils.py
102
plexapi/utils.py
|
@ -7,8 +7,8 @@ import time
|
||||||
import zipfile
|
import zipfile
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
from plexapi.compat import quote, string_type
|
from plexapi import compat
|
||||||
from plexapi.exceptions import NotFound
|
from plexapi.exceptions import NotFound, PlexApiException
|
||||||
|
|
||||||
|
|
||||||
# Search Types - Plex uses these to filter specific media types when searching.
|
# Search Types - Plex uses these to filter specific media types when searching.
|
||||||
|
@ -31,7 +31,7 @@ class SecretsFilter(logging.Filter):
|
||||||
def filter(self, record):
|
def filter(self, record):
|
||||||
cleanargs = list(record.args)
|
cleanargs = list(record.args)
|
||||||
for i in range(len(cleanargs)):
|
for i in range(len(cleanargs)):
|
||||||
if isinstance(cleanargs[i], string_type):
|
if isinstance(cleanargs[i], compat.string_type):
|
||||||
for secret in self.secrets:
|
for secret in self.secrets:
|
||||||
cleanargs[i] = cleanargs[i].replace(secret, '<hidden>')
|
cleanargs[i] = cleanargs[i].replace(secret, '<hidden>')
|
||||||
record.args = tuple(cleanargs)
|
record.args = tuple(cleanargs)
|
||||||
|
@ -92,7 +92,7 @@ def joinArgs(args):
|
||||||
arglist = []
|
arglist = []
|
||||||
for key in sorted(args, key=lambda x: x.lower()):
|
for key in sorted(args, key=lambda x: x.lower()):
|
||||||
value = str(args[key])
|
value = str(args[key])
|
||||||
arglist.append('%s=%s' % (key, quote(value)))
|
arglist.append('%s=%s' % (key, compat.quote(value)))
|
||||||
return '?%s' % '&'.join(arglist)
|
return '?%s' % '&'.join(arglist)
|
||||||
|
|
||||||
|
|
||||||
|
@ -215,15 +215,15 @@ def downloadSessionImages(server, filename=None, height=150, width=150, opacity=
|
||||||
for part in media.iterParts():
|
for part in media.iterParts():
|
||||||
if media.thumb:
|
if media.thumb:
|
||||||
url = media.thumb
|
url = media.thumb
|
||||||
if part.indexes: # Always use bif images if available.
|
if part.indexes: # always use bif images if available.
|
||||||
url = '/library/parts/%s/indexes/%s/%s' % (part.id, part.indexes.lower(), media.viewOffset)
|
url = '/library/parts/%s/indexes/%s/%s' % (part.id, part.indexes.lower(), media.viewOffset)
|
||||||
if url:
|
if url:
|
||||||
if filename is None:
|
if filename is None:
|
||||||
prettyname = media._prettyfilename()
|
prettyname = media._prettyfilename()
|
||||||
filename = 'session_transcode_%s_%s_%s' % (media.usernames[0], prettyname, int(time.time()))
|
filename = 'session_transcode_%s_%s_%s' % (media.usernames[0], prettyname, int(time.time()))
|
||||||
url = server.transcodeImage(url, height=height, width=width, opacity=opacity, saturation=saturation)
|
url = server.transcodeImage(url, height, width, opacity, saturation)
|
||||||
dfp = download(url, filename=filename)
|
filepath = download(url, filename=filename)
|
||||||
info['username'] = {'filepath': dfp, 'url': url}
|
info['username'] = {'filepath': filepath, 'url': url}
|
||||||
return info
|
return info
|
||||||
|
|
||||||
|
|
||||||
|
@ -243,61 +243,37 @@ def download(url, filename=None, savepath=None, session=None, chunksize=4024, mo
|
||||||
>>> download(a_episode.getStreamURL(), a_episode.location)
|
>>> download(a_episode.getStreamURL(), a_episode.location)
|
||||||
/path/to/file
|
/path/to/file
|
||||||
"""
|
"""
|
||||||
# TODO: Review this; It should be properly logging and raising exceptions..
|
|
||||||
from plexapi import log
|
from plexapi import log
|
||||||
|
# fetch the data to be saved
|
||||||
session = session or requests.Session()
|
session = session or requests.Session()
|
||||||
if savepath is None:
|
response = session.get(url, stream=True)
|
||||||
savepath = os.getcwd()
|
# make sure the savepath directory exists
|
||||||
else:
|
savepath = savepath or os.getcwd()
|
||||||
# Make sure the user supplied path exists
|
compat.makedirs(savepath, exist_ok=True)
|
||||||
try:
|
# try getting filename from header if not specified in arguments (used for logs, db)
|
||||||
os.makedirs(savepath)
|
if not filename and response.headers.get('Content-Disposition'):
|
||||||
except OSError:
|
filename = re.findall(r'filename=\"(.+)\"', response.headers.get('Content-Disposition'))
|
||||||
if not os.path.isdir(savepath): # pragma: no cover
|
filename = filename[0] if filename[0] else None
|
||||||
raise
|
filename = os.path.basename(filename)
|
||||||
|
fullpath = os.path.join(savepath, filename)
|
||||||
try:
|
# append file.ext from content-type if not already there
|
||||||
response = session.get(url, stream=True)
|
extension = os.path.splitext(fullpath)[-1]
|
||||||
|
if not extension:
|
||||||
# Lets grab the name if we dont supply one.
|
contenttype = response.headers.get('content-type')
|
||||||
# This will be used for downloading logs/db etc.
|
if contenttype and 'image' in contenttype:
|
||||||
if filename is None and response.headers.get('Content-Disposition'):
|
fullpath += contenttype.split('/')[1]
|
||||||
filename = re.findall(r'filename=\"(.+)\"', response.headers.get('Content-Disposition'))
|
# check this is a mocked download (testing)
|
||||||
if filename:
|
if mocked:
|
||||||
filename = filename[0]
|
log.debug('Mocked download %s', fullpath)
|
||||||
|
|
||||||
filename = os.path.basename(filename)
|
|
||||||
fullpath = os.path.join(savepath, filename)
|
|
||||||
|
|
||||||
# images dont have a extention so we try
|
|
||||||
# to guess it from content-type
|
|
||||||
ext = os.path.splitext(fullpath)[-1]
|
|
||||||
if ext:
|
|
||||||
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:
|
|
||||||
log.debug('Mocked download %s', fullpath)
|
|
||||||
return fullpath
|
|
||||||
|
|
||||||
with open(fullpath, 'wb') as f:
|
|
||||||
for chunk in response.iter_content(chunk_size=chunksize):
|
|
||||||
if chunk:
|
|
||||||
f.write(chunk)
|
|
||||||
|
|
||||||
if fullpath.endswith('zip') and unpack is True:
|
|
||||||
with zipfile.ZipFile(fullpath, 'r') as zp:
|
|
||||||
zp.extractall(savepath)
|
|
||||||
|
|
||||||
# log.debug('Downloaded %s to %s from %s' % (filename, fullpath, url))
|
|
||||||
return fullpath
|
return fullpath
|
||||||
|
# save the file to disk
|
||||||
except Exception as err: # pragma: no cover
|
log.info('Downloading: %s', fullpath)
|
||||||
log.exception('Error downloading file: %s' % err)
|
with open(fullpath, 'wb') as handle:
|
||||||
raise
|
for chunk in response.iter_content(chunk_size=chunksize):
|
||||||
# log.exception('Failed to download %s to %s %s' % (url, fullpath, e))
|
handle.write(chunk)
|
||||||
|
# check we want to unzip the contents
|
||||||
|
if fullpath.endswith('zip') and unpack:
|
||||||
|
with zipfile.ZipFile(fullpath, 'r') as handle:
|
||||||
|
handle.extractall(savepath)
|
||||||
|
# finished; return fillpath
|
||||||
|
return fullpath
|
||||||
|
|
|
@ -159,22 +159,20 @@ class Movie(Video, Playable):
|
||||||
a friendlier is generated.
|
a friendlier is generated.
|
||||||
**kwargs: Additional options passed into :func:`~plexapi.base.PlexObject.getStreamURL()`.
|
**kwargs: Additional options passed into :func:`~plexapi.base.PlexObject.getStreamURL()`.
|
||||||
"""
|
"""
|
||||||
downloaded = []
|
filepaths = []
|
||||||
locs = [i for i in self.iterParts() if i]
|
locations = [i for i in self.iterParts() if i]
|
||||||
for loc in locs:
|
for location in locations:
|
||||||
if keep_orginal_name is False:
|
name = location.file
|
||||||
name = '%s.%s' % (self.title.replace(' ', '.'), loc.container)
|
if not keep_orginal_name:
|
||||||
|
title = self.title.replace(' ', '.')
|
||||||
|
name = '%s.%s' % (title, location.container)
|
||||||
|
if kwargs is not None:
|
||||||
|
url = self.getStreamURL(**kwargs)
|
||||||
else:
|
else:
|
||||||
name = loc.file
|
self._server.url('%s?download=1' % location.key)
|
||||||
# So this seems to be a alot slower but allows transcode.
|
filepath = utils.download(url, filename=name, savepath=savepath, session=self._server._session)
|
||||||
if kwargs:
|
filepaths.append(filepath)
|
||||||
download_url = self.getStreamURL(**kwargs)
|
return filepaths
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
@utils.registerPlexObject
|
@utils.registerPlexObject
|
||||||
|
@ -303,12 +301,10 @@ class Show(Video):
|
||||||
a friendlier is generated.
|
a friendlier is generated.
|
||||||
**kwargs: Additional options passed into :func:`~plexapi.base.PlexObject.getStreamURL()`.
|
**kwargs: Additional options passed into :func:`~plexapi.base.PlexObject.getStreamURL()`.
|
||||||
"""
|
"""
|
||||||
downloaded = []
|
filepaths = []
|
||||||
for ep in self.episodes():
|
for episode in self.episodes():
|
||||||
dl = ep.download(savepath=savepath, keep_orginal_name=keep_orginal_name, **kwargs)
|
filepaths += episode.download(savepath, keep_orginal_name, **kwargs)
|
||||||
if dl:
|
return filepaths
|
||||||
downloaded.extend(dl)
|
|
||||||
return downloaded
|
|
||||||
|
|
||||||
|
|
||||||
@utils.registerPlexObject
|
@utils.registerPlexObject
|
||||||
|
@ -401,12 +397,10 @@ class Season(Video):
|
||||||
a friendlier is generated.
|
a friendlier is generated.
|
||||||
**kwargs: Additional options passed into :func:`~plexapi.base.PlexObject.getStreamURL()`.
|
**kwargs: Additional options passed into :func:`~plexapi.base.PlexObject.getStreamURL()`.
|
||||||
"""
|
"""
|
||||||
downloaded = []
|
filepaths = []
|
||||||
for ep in self.episodes():
|
for episode in self.episodes():
|
||||||
dl = ep.download(savepath=savepath, keep_orginal_name=keep_orginal_name, **kwargs)
|
filepaths += episode.download(savepath, keep_orginal_name, **kwargs)
|
||||||
if dl:
|
return filepaths
|
||||||
downloaded.extend(dl)
|
|
||||||
return downloaded
|
|
||||||
|
|
||||||
|
|
||||||
@utils.registerPlexObject
|
@utils.registerPlexObject
|
||||||
|
|
Loading…
Add table
Reference in a new issue