mirror of
https://github.com/pkkid/python-plexapi
synced 2024-11-10 06:04:15 +00:00
Add tqdm requirement; Display download status in plex-download
This commit is contained in:
parent
afd6201f29
commit
d7276e2e82
5 changed files with 46 additions and 24 deletions
|
@ -511,7 +511,6 @@ class Playable(object):
|
|||
"""
|
||||
filepaths = []
|
||||
locations = [i for i in self.iterParts() if i]
|
||||
|
||||
for location in locations:
|
||||
filename = location.file
|
||||
if keep_orginal_name is False:
|
||||
|
@ -521,14 +520,10 @@ class Playable(object):
|
|||
download_url = self.getStreamURL(**kwargs)
|
||||
else:
|
||||
download_url = self._server.url('%s?download=1' % location.key)
|
||||
|
||||
filepath = utils.download(download_url,
|
||||
filename=filename,
|
||||
savepath=savepath,
|
||||
session=self._server._session)
|
||||
filepath = utils.download(download_url, filename=filename, savepath=savepath,
|
||||
session=self._server._session, **kwargs)
|
||||
if filepath:
|
||||
filepaths.append(filepath)
|
||||
|
||||
return filepaths
|
||||
|
||||
def stop(self, reason=''):
|
||||
|
|
|
@ -8,6 +8,7 @@ import zipfile
|
|||
from datetime import datetime
|
||||
from getpass import getpass
|
||||
from threading import Thread
|
||||
from tqdm import tqdm
|
||||
from plexapi import compat
|
||||
from plexapi.exceptions import NotFound
|
||||
|
||||
|
@ -229,7 +230,7 @@ def downloadSessionImages(server, filename=None, height=150, width=150, opacity=
|
|||
return info
|
||||
|
||||
|
||||
def download(url, filename=None, savepath=None, session=None, chunksize=4024, unpack=False, mocked=False):
|
||||
def download(url, filename=None, savepath=None, session=None, chunksize=4024, unpack=False, mocked=False, showstatus=False):
|
||||
""" Helper to download a thumb, videofile or other media item. Returns the local
|
||||
path to the downloaded file.
|
||||
|
||||
|
@ -270,9 +271,13 @@ def download(url, filename=None, savepath=None, session=None, chunksize=4024, un
|
|||
return fullpath
|
||||
# save the file to disk
|
||||
log.info('Downloading: %s', fullpath)
|
||||
if showstatus:
|
||||
bar = tqdm(unit='B', unit_scale=True)
|
||||
with open(fullpath, 'wb') as handle:
|
||||
for chunk in response.iter_content(chunk_size=chunksize):
|
||||
handle.write(chunk)
|
||||
if showstatus:
|
||||
bar.update(len(chunk))
|
||||
# check we want to unzip the contents
|
||||
if fullpath.endswith('zip') and unpack:
|
||||
with zipfile.ZipFile(fullpath, 'r') as handle:
|
||||
|
@ -322,3 +327,25 @@ def getMyPlexAccount(opts=None):
|
|||
password = getpass('What is your plex.tv password: ')
|
||||
print('Authenticating with Plex.tv as %s..' % username)
|
||||
return MyPlexAccount(username, password)
|
||||
|
||||
|
||||
def choose(msg, items, attr):
|
||||
""" Command line helper to display a list of choices, asking the
|
||||
user to choose one of the options.
|
||||
"""
|
||||
# Return the first item if there is only one choice
|
||||
if len(items) == 1:
|
||||
return items[0]
|
||||
# Print all choices to the command line
|
||||
print()
|
||||
for index, i in enumerate(items):
|
||||
name = attr(i) if callable(attr) else getattr(i, attr)
|
||||
print(' %s: %s' % (index, name))
|
||||
print()
|
||||
# Request choice from the user
|
||||
while True:
|
||||
try:
|
||||
number = int(input('%s: ' % msg))
|
||||
return items[number]
|
||||
except (ValueError, IndexError):
|
||||
pass
|
||||
|
|
|
@ -179,7 +179,7 @@ class Movie(Video, Playable):
|
|||
url = self.getStreamURL(**kwargs)
|
||||
else:
|
||||
self._server.url('%s?download=1' % location.key)
|
||||
filepath = utils.download(url, filename=name, savepath=savepath, session=self._server._session)
|
||||
filepath = utils.download(url, filename=name, savepath=savepath, session=self._server._session, **kwargs)
|
||||
filepaths.append(filepath)
|
||||
return filepaths
|
||||
|
||||
|
@ -481,13 +481,12 @@ class Episode(Video, Playable):
|
|||
return '<%s>' % ':'.join([p for p in [
|
||||
self.__class__.__name__,
|
||||
self.key.replace('/library/metadata/', '').replace('/children', ''),
|
||||
'%s-s%se%s' % (self.grandparentTitle.replace(' ', '-')[:20], self.seasonNumber, self.index),
|
||||
'%s-%s' % (self.grandparentTitle.replace(' ', '-')[:20], self.seasonEpisode),
|
||||
] if p])
|
||||
|
||||
def _prettyfilename(self):
|
||||
""" Returns a human friendly filename. """
|
||||
return '%s.S%sE%s' % (self.grandparentTitle.replace(' ', '.'),
|
||||
str(self.seasonNumber).zfill(2), str(self.index).zfill(2))
|
||||
return '%s.%s' % (self.grandparentTitle.replace(' ', '.'), self.seasonEpisode)
|
||||
|
||||
@property
|
||||
def locations(self):
|
||||
|
@ -503,6 +502,11 @@ class Episode(Video, Playable):
|
|||
self._seasonNumber = self.parentIndex if self.parentIndex else self.season().seasonNumber
|
||||
return utils.cast(int, self._seasonNumber)
|
||||
|
||||
@property
|
||||
def seasonEpisode(self):
|
||||
""" Returns the s00e00 string containing the season and episode. """
|
||||
return 's%se%s' % (str(self.seasonNumber).zfill(2), str(self.index).zfill(2))
|
||||
|
||||
def season(self):
|
||||
"""" Return this episodes :func:`~plexapi.video.Season`.. """
|
||||
return self.fetchItem(self.parentKey)
|
||||
|
|
|
@ -3,4 +3,5 @@
|
|||
# pip install -r requirments.txt
|
||||
#---------------------------------------------------------
|
||||
requests
|
||||
tqdm
|
||||
websocket-client
|
|
@ -12,23 +12,18 @@ from plexapi import utils
|
|||
from plexapi.compat import unquote
|
||||
from plexapi.video import Episode, Movie, Show
|
||||
|
||||
|
||||
def choose(msg, items, attr):
|
||||
print()
|
||||
for index, i in enumerate(items):
|
||||
name = attr(i) if callable(attr) else getattr(i, attr)
|
||||
print(' %s: %s' % (index, name))
|
||||
number = int(input('\n%s: ' % msg))
|
||||
return items[number]
|
||||
VALID_TYPES = (Movie, Episode, Show)
|
||||
|
||||
|
||||
def search_for_item(url=None):
|
||||
if url: return get_item_from_url(opts.url)
|
||||
server = choose('Choose a Server', account.resources(), 'name').connect()
|
||||
server = utils.choose('Choose a Server', account.resources(), 'name').connect()
|
||||
query = input('What are you looking for?: ')
|
||||
item = choose('Choose result', server.search(query), lambda x: repr(x))
|
||||
items = [i for i in server.search(query) if i.__class__ in VALID_TYPES]
|
||||
item = utils.choose('Choose result', items, lambda x: '(%s) %s' % (x.type.title(), x.title[0:60]))
|
||||
if isinstance(item, Show):
|
||||
item = choose('Choose episode', item.episodes(), lambda x: x._prettyfilename())
|
||||
display = lambda i: '%s %s %s' % (i.grandparentTitle, i.seasonEpisode, i.title)
|
||||
item = utils.choose('Choose episode', item.episodes(), display)
|
||||
if not isinstance(item, (Movie, Episode)):
|
||||
raise SystemExit('Unable to download %s' % item.__class__.__name__)
|
||||
return item
|
||||
|
@ -62,6 +57,6 @@ if __name__ == '__main__':
|
|||
item = search_for_item(opts.url)
|
||||
# Download the item
|
||||
print("Downloading '%s' from %s.." % (item._prettyfilename(), item._server.friendlyName))
|
||||
filepaths = item.download('./')
|
||||
filepaths = item.download('./', showstatus=True)
|
||||
for filepath in filepaths:
|
||||
print(' %s' % filepath)
|
||||
|
|
Loading…
Reference in a new issue