mirror of
https://github.com/pkkid/python-plexapi
synced 2024-11-26 05:30:20 +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 -*-
|
||||
# Python 2/3 compatability
|
||||
# Always try Py3 first
|
||||
import os
|
||||
|
||||
try:
|
||||
string_type = basestring
|
||||
|
@ -36,3 +37,12 @@ try:
|
|||
from xml.etree import cElementTree as ElementTree
|
||||
except ImportError:
|
||||
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):
|
||||
""" Returns a list of all :class:`~plexapi.client.PlexClient` objects
|
||||
connected to this server."""
|
||||
|
||||
items = []
|
||||
cache_resource = None
|
||||
from plexapi.myplex import MyPlexResource
|
||||
|
@ -193,7 +192,6 @@ class PlexServer(PlexObject):
|
|||
if conn.local is True:
|
||||
port = conn.port
|
||||
break
|
||||
|
||||
baseurl = 'http://%s:%s' % (elem.attrib['host'], port)
|
||||
items.append(PlexClient(baseurl=baseurl, server=self, data=elem))
|
||||
return items
|
||||
|
@ -231,6 +229,16 @@ class PlexServer(PlexObject):
|
|||
"""
|
||||
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):
|
||||
""" Returns a list of media items from watched history. """
|
||||
return self.fetchItems('/status/sessions/history/all')
|
||||
|
@ -341,17 +349,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)
|
||||
|
||||
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):
|
||||
""" 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
|
||||
from datetime import datetime
|
||||
from threading import Thread
|
||||
from plexapi.compat import quote, string_type
|
||||
from plexapi.exceptions import NotFound
|
||||
from plexapi import compat
|
||||
from plexapi.exceptions import NotFound, PlexApiException
|
||||
|
||||
|
||||
# Search Types - Plex uses these to filter specific media types when searching.
|
||||
|
@ -31,7 +31,7 @@ class SecretsFilter(logging.Filter):
|
|||
def filter(self, record):
|
||||
cleanargs = list(record.args)
|
||||
for i in range(len(cleanargs)):
|
||||
if isinstance(cleanargs[i], string_type):
|
||||
if isinstance(cleanargs[i], compat.string_type):
|
||||
for secret in self.secrets:
|
||||
cleanargs[i] = cleanargs[i].replace(secret, '<hidden>')
|
||||
record.args = tuple(cleanargs)
|
||||
|
@ -92,7 +92,7 @@ def joinArgs(args):
|
|||
arglist = []
|
||||
for key in sorted(args, key=lambda x: x.lower()):
|
||||
value = str(args[key])
|
||||
arglist.append('%s=%s' % (key, quote(value)))
|
||||
arglist.append('%s=%s' % (key, compat.quote(value)))
|
||||
return '?%s' % '&'.join(arglist)
|
||||
|
||||
|
||||
|
@ -215,15 +215,15 @@ def downloadSessionImages(server, filename=None, height=150, width=150, opacity=
|
|||
for part in media.iterParts():
|
||||
if 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)
|
||||
if url:
|
||||
if filename is None:
|
||||
prettyname = media._prettyfilename()
|
||||
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)
|
||||
dfp = download(url, filename=filename)
|
||||
info['username'] = {'filepath': dfp, 'url': url}
|
||||
url = server.transcodeImage(url, height, width, opacity, saturation)
|
||||
filepath = download(url, filename=filename)
|
||||
info['username'] = {'filepath': filepath, 'url': url}
|
||||
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)
|
||||
/path/to/file
|
||||
"""
|
||||
# TODO: Review this; It should be properly logging and raising exceptions..
|
||||
from plexapi import log
|
||||
# fetch the data to be saved
|
||||
session = session or requests.Session()
|
||||
if savepath is None:
|
||||
savepath = os.getcwd()
|
||||
else:
|
||||
# Make sure the user supplied path exists
|
||||
try:
|
||||
os.makedirs(savepath)
|
||||
except OSError:
|
||||
if not os.path.isdir(savepath): # pragma: no cover
|
||||
raise
|
||||
|
||||
try:
|
||||
response = session.get(url, stream=True)
|
||||
|
||||
# Lets grab the name if we dont supply one.
|
||||
# This will be used for downloading logs/db etc.
|
||||
if filename is None and response.headers.get('Content-Disposition'):
|
||||
filename = re.findall(r'filename=\"(.+)\"', response.headers.get('Content-Disposition'))
|
||||
if filename:
|
||||
filename = filename[0]
|
||||
|
||||
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))
|
||||
response = session.get(url, stream=True)
|
||||
# make sure the savepath directory exists
|
||||
savepath = savepath or os.getcwd()
|
||||
compat.makedirs(savepath, exist_ok=True)
|
||||
# try getting filename from header if not specified in arguments (used for logs, db)
|
||||
if not filename and response.headers.get('Content-Disposition'):
|
||||
filename = re.findall(r'filename=\"(.+)\"', response.headers.get('Content-Disposition'))
|
||||
filename = filename[0] if filename[0] else None
|
||||
filename = os.path.basename(filename)
|
||||
fullpath = os.path.join(savepath, filename)
|
||||
# append file.ext from content-type if not already there
|
||||
extension = os.path.splitext(fullpath)[-1]
|
||||
if not extension:
|
||||
contenttype = response.headers.get('content-type')
|
||||
if contenttype and 'image' in contenttype:
|
||||
fullpath += contenttype.split('/')[1]
|
||||
# check this is a mocked download (testing)
|
||||
if mocked:
|
||||
log.debug('Mocked download %s', fullpath)
|
||||
return fullpath
|
||||
|
||||
except Exception as err: # pragma: no cover
|
||||
log.exception('Error downloading file: %s' % err)
|
||||
raise
|
||||
# log.exception('Failed to download %s to %s %s' % (url, fullpath, e))
|
||||
# save the file to disk
|
||||
log.info('Downloading: %s', fullpath)
|
||||
with open(fullpath, 'wb') as handle:
|
||||
for chunk in response.iter_content(chunk_size=chunksize):
|
||||
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.
|
||||
**kwargs: Additional options passed into :func:`~plexapi.base.PlexObject.getStreamURL()`.
|
||||
"""
|
||||
downloaded = []
|
||||
locs = [i for i in self.iterParts() if i]
|
||||
for loc in locs:
|
||||
if keep_orginal_name is False:
|
||||
name = '%s.%s' % (self.title.replace(' ', '.'), loc.container)
|
||||
filepaths = []
|
||||
locations = [i for i in self.iterParts() if i]
|
||||
for location in locations:
|
||||
name = location.file
|
||||
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:
|
||||
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
|
||||
self._server.url('%s?download=1' % location.key)
|
||||
filepath = utils.download(url, filename=name, savepath=savepath, session=self._server._session)
|
||||
filepaths.append(filepath)
|
||||
return filepaths
|
||||
|
||||
|
||||
@utils.registerPlexObject
|
||||
|
@ -303,12 +301,10 @@ class Show(Video):
|
|||
a friendlier is generated.
|
||||
**kwargs: Additional options passed into :func:`~plexapi.base.PlexObject.getStreamURL()`.
|
||||
"""
|
||||
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
|
||||
filepaths = []
|
||||
for episode in self.episodes():
|
||||
filepaths += episode.download(savepath, keep_orginal_name, **kwargs)
|
||||
return filepaths
|
||||
|
||||
|
||||
@utils.registerPlexObject
|
||||
|
@ -401,12 +397,10 @@ class Season(Video):
|
|||
a friendlier is generated.
|
||||
**kwargs: Additional options passed into :func:`~plexapi.base.PlexObject.getStreamURL()`.
|
||||
"""
|
||||
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
|
||||
filepaths = []
|
||||
for episode in self.episodes():
|
||||
filepaths += episode.download(savepath, keep_orginal_name, **kwargs)
|
||||
return filepaths
|
||||
|
||||
|
||||
@utils.registerPlexObject
|
||||
|
|
Loading…
Reference in a new issue