Skip to content

Commit 6dcc5bd

Browse files
authored
Merge pull request #189 from pkkid/better_cli
Better cli
2 parents 484461b + c9d1e22 commit 6dcc5bd

File tree

5 files changed

+68
-39
lines changed

5 files changed

+68
-39
lines changed

plexapi/client.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
from plexapi.compat import ElementTree
1010
from plexapi.exceptions import BadRequest, Unsupported
1111
from plexapi.playqueue import PlayQueue
12-
from plexapi.utils import cast
1312

1413

1514
DEFAULT_MTYPE = 'video'

plexapi/myplex.py

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from plexapi.base import PlexObject
99
from plexapi.exceptions import BadRequest, NotFound
1010
from plexapi.client import PlexClient
11-
from plexapi.compat import ElementTree, quote
11+
from plexapi.compat import ElementTree
1212
from plexapi.library import LibrarySection
1313
from plexapi.server import PlexServer
1414
from plexapi.utils import joinArgs
@@ -243,20 +243,18 @@ def updateFriend(self, user, server, sections=None, removeSections=False, allowS
243243
machineId = server.machineIdentifier if isinstance(server, PlexServer) else server
244244
sectionIds = self._getSectionIds(machineId, sections)
245245
headers = {'Content-Type': 'application/json'}
246-
247246
# Determine whether user has access to the shared server.
248247
user_servers = [s for s in user.servers if s.machineIdentifier == machineId]
249248
if user_servers and sectionIds:
250249
serverId = user_servers[0].id
251250
params = {'server_id': machineId, 'shared_server': {'library_section_ids': sectionIds}}
252251
url = self.FRIENDSERVERS.format(machineId=machineId, serverId=serverId)
253252
else:
254-
params = {'server_id': machineId,
255-
'shared_server': {'library_section_ids': sectionIds, "invited_id": user.id}}
253+
params = {'server_id': machineId, 'shared_server': {'library_section_ids': sectionIds,
254+
"invited_id": user.id}}
256255
url = self.FRIENDINVITE.format(machineId=machineId)
257-
256+
# Remove share sections, add shares to user without shares, or update shares
258257
if sectionIds:
259-
# Remove share sections, add shares to user without shares, or update shares
260258
if removeSections is True:
261259
response_servers = self.query(url, self._session.delete, json=params, headers=headers)
262260
elif 'invited_id' in params.get('shared_server', ''):
@@ -265,27 +263,24 @@ def updateFriend(self, user, server, sections=None, removeSections=False, allowS
265263
response_servers = self.query(url, self._session.put, json=params, headers=headers)
266264
else:
267265
log.warning('Section name, number of section object is required changing library sections')
268-
269266
# Update friend filters
270267
url = self.FRIENDUPDATE.format(userId=user.id)
271-
d = {}
268+
params = {}
272269
if isinstance(allowSync, bool):
273-
d['allowSync'] = '1' if allowSync else '0'
270+
params['allowSync'] = '1' if allowSync else '0'
274271
if isinstance(allowCameraUpload, bool):
275-
d['allowCameraUpload'] = '1' if allowCameraUpload else '0'
272+
params['allowCameraUpload'] = '1' if allowCameraUpload else '0'
276273
if isinstance(allowChannels, bool):
277-
d['allowChannels'] = '1' if allowChannels else '0'
274+
params['allowChannels'] = '1' if allowChannels else '0'
278275
if isinstance(filterMovies, dict):
279-
d['filterMovies'] = self._filterDictToStr(filterMovies or {}) #'1' if allowChannels else '0'
276+
params['filterMovies'] = self._filterDictToStr(filterMovies or {}) # '1' if allowChannels else '0'
280277
if isinstance(filterTelevision, dict):
281-
d['filterTelevision'] = self._filterDictToStr(filterTelevision or {})
278+
params['filterTelevision'] = self._filterDictToStr(filterTelevision or {})
282279
if isinstance(allowChannels, dict):
283-
d['filterMusic'] = self._filterDictToStr(filterMusic or {})
284-
285-
if d:
286-
url += joinArgs(d)
280+
params['filterMusic'] = self._filterDictToStr(filterMusic or {})
281+
if params:
282+
url += joinArgs(params)
287283
response_filters = self.query(url, self._session.put)
288-
289284
return response_servers, response_filters
290285

291286
def user(self, username):

plexapi/utils.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -243,11 +243,12 @@ def download(url, filename=None, savepath=None, session=None, chunksize=4024,
243243
mocked (bool): Helper to do evertything except write the file.
244244
unpack (bool): Unpack the zip file.
245245
showstatus(bool): Display a progressbar.
246-
246+
247247
Example:
248248
>>> download(a_episode.getStreamURL(), a_episode.location)
249249
/path/to/file
250250
"""
251+
251252
from plexapi import log
252253
# fetch the data to be saved
253254
session = session or requests.Session()
@@ -356,7 +357,12 @@ def choose(msg, items, attr):
356357
# Request choice from the user
357358
while True:
358359
try:
359-
number = int(input('%s: ' % msg))
360-
return items[number]
360+
inp = input('%s: ' % msg)
361+
if any(s in inp for s in (':', '::', '-')):
362+
idx = slice(*map(lambda x: int(x.strip()) if x.strip() else None, inp.split(':')))
363+
return items[idx]
364+
else:
365+
return items[int(inp)]
366+
361367
except (ValueError, IndexError):
362368
pass

tests/test_server.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ def test_server_account(plex):
233233
assert account.signInState == 'ok'
234234
assert isinstance(account.subscriptionActive, bool)
235235
if account.subscriptionActive: assert len(account.subscriptionFeatures)
236-
else: assert account.subscriptionFeatures == ['mediaproviders-news-platform-specific']
236+
else: assert sorted(account.subscriptionFeatures) == ['download_certificates', 'federated-auth', 'news']
237237
assert account.subscriptionState == 'Active' if account.subscriptionActive else 'Unknown'
238238
assert re.match(utils.REGEX_EMAIL, account.username)
239239

tools/plex-download.py

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@
77
88
Original contribution by lad1337.
99
"""
10-
import argparse, re
10+
import argparse
11+
import os
12+
import re
13+
import shutil
14+
1115
from plexapi import utils
1216
from plexapi.compat import unquote
1317
from plexapi.video import Episode, Movie, Show
@@ -17,15 +21,31 @@
1721

1822
def search_for_item(url=None):
1923
if url: return get_item_from_url(opts.url)
20-
server = utils.choose('Choose a Server', account.resources(), 'name').connect()
24+
servers = [s for s in account.resources() if 'server' in s.provides]
25+
server = utils.choose('Choose a Server', servers, 'name').connect()
2126
query = input('What are you looking for?: ')
27+
item = []
2228
items = [i for i in server.search(query) if i.__class__ in VALID_TYPES]
23-
item = utils.choose('Choose result', items, lambda x: '(%s) %s' % (x.type.title(), x.title[0:60]))
24-
if isinstance(item, Show):
25-
display = lambda i: '%s %s %s' % (i.grandparentTitle, i.seasonEpisode, i.title)
26-
item = utils.choose('Choose episode', item.episodes(), display)
27-
if not isinstance(item, (Movie, Episode)):
28-
raise SystemExit('Unable to download %s' % item.__class__.__name__)
29+
items = utils.choose('Choose result', items, lambda x: '(%s) %s' % (x.type.title(), x.title[0:60]))
30+
31+
if not isinstance(items, list):
32+
items = [items]
33+
34+
for i in items:
35+
if isinstance(i, Show):
36+
display = lambda i: '%s %s %s' % (i.grandparentTitle, i.seasonEpisode, i.title)
37+
selected_eps = utils.choose('Choose episode', i.episodes(), display)
38+
if isinstance(selected_eps, list):
39+
item += selected_eps
40+
else:
41+
item.append(selected_eps)
42+
43+
else:
44+
item.append(i)
45+
46+
if not isinstance(item, list):
47+
item = [item]
48+
2949
return item
3050

3151

@@ -47,16 +67,25 @@ def get_item_from_url(url):
4767

4868
if __name__ == '__main__':
4969
# Command line parser
70+
from plexapi import CONFIG
71+
from tqdm import tqdm
5072
parser = argparse.ArgumentParser(description=__doc__)
51-
parser.add_argument('--username', help='Your Plex username')
52-
parser.add_argument('--password', help='Your Plex password')
73+
parser.add_argument('-u', '--username', help='Your Plex username',
74+
default=CONFIG.get('auth.myplex_username'))
75+
parser.add_argument('-p', '--password', help='Your Plex password',
76+
default=CONFIG.get('auth.myplex_password'))
5377
parser.add_argument('--url', default=None, help='Download from URL (only paste after !)')
5478
opts = parser.parse_args()
5579
# Search item to download
5680
account = utils.getMyPlexAccount(opts)
57-
item = search_for_item(opts.url)
58-
# Download the item
59-
print("Downloading '%s' from %s.." % (item._prettyfilename(), item._server.friendlyName))
60-
filepaths = item.download('./', showstatus=True)
61-
for filepath in filepaths:
62-
print(' %s' % filepath)
81+
items = search_for_item(opts.url)
82+
for item in items:
83+
for part in item.iterParts():
84+
# We do this manually since we dont want to add a progress to Episode etc
85+
filename = '%s.%s' % (item._prettyfilename(), part.container)
86+
url = item._server.url('%s?download=1' % part.key)
87+
filepath = utils.download(url, filename=filename, savepath=os.getcwd(),
88+
session=item._server._session, showstatus=True)
89+
#print(' %s' % filepath)
90+
91+

0 commit comments

Comments
 (0)