Skip to content

Commit 6e08900

Browse files
author
Michael Pivonka
committed
First version
1 parent 892dd8e commit 6e08900

File tree

3 files changed

+72
-14
lines changed

3 files changed

+72
-14
lines changed

README.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Plex Media Server Offline Downloader
2+
PlexMedia-Downloader is a python script that you pass it your username, password, url to the media you have access to and it will download it to your local machine.
3+
4+
## Requirements
5+
* Python 3
6+
* Plex Server (With content you have access to stream from)
7+
* Plex.TV account
8+
9+
## Python requirements
10+
* requests
11+
* tqdm
12+
13+
## Install
14+
```
15+
pip install requirements.txt
16+
```
17+
18+
## Usage
19+
URL can be any of the following ip:port, plex.direct:port, hostname:port, plex.tv
20+
```
21+
usage: main.py [-h] -u USERNAME -p PASSWORD url
22+
23+
positional arguments:
24+
url URL to Movie, Show, Season, Episode. TIP: Put url inside single quotes.
25+
26+
optional arguments:
27+
-h, --help show this help message and exit
28+
-u USERNAME, --username USERNAME
29+
Plex.TV Email/Username
30+
-p PASSWORD, --password PASSWORD
31+
Plex.TV Password
32+
```
33+
34+
## Example
35+
```
36+
python main.py -u codedninja -p 3U7qYhaBAk8yfa 'https://app.plex.tv/desktop#!/server/0893cadc04a6f52efa052691d6a07c5b54890ca1/details?key=%2Flibrary%2Fmetadata%2F208649&context=source%3Ahub.tv.recentlyaired'
37+
```

main.py

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,7 @@
44
from xml.etree import ElementTree
55
from tqdm.auto import tqdm
66
import os
7-
8-
# Config
9-
email=""
10-
password=""
7+
import argparse
118

129
class PlexDownloader:
1310
headers = {
@@ -153,7 +150,7 @@ def _parse_season(self, rating_key):
153150

154151
parsed_episodes = []
155152

156-
response = self_get_url(url)
153+
response = self._get_url(url)
157154

158155
if response:
159156
return self._parse_episodes(response['MediaContainer']['Metadata'])
@@ -188,7 +185,7 @@ def _parse_metadata(self, data):
188185
parsed_media = self._parse_season(rating_key)
189186

190187
elif media['type'] == "episode":
191-
parsed_media = self._parse_episode(media)
188+
parsed_media = [ self._parse_episode(media) ]
192189

193190
elif media['type'] == "movie":
194191
parsed_media = self._parse_movie(media)
@@ -233,7 +230,6 @@ def download(self):
233230
print("Found %s media content to download" % len(contents))
234231

235232
headers = {
236-
**self.headers,
237233
'X-Plex-Token': self.access_token
238234
}
239235

@@ -243,9 +239,13 @@ def download(self):
243239
os.makedirs(content['folder'])
244240

245241
file_name = os.path.join(content['folder'], content['filename'].replace("/", "-"))
246-
242+
247243
response = requests.get(content['url'], stream=True, headers=headers)
248244

245+
if response.status_code == 400:
246+
print("Error getting %s" % content['title'])
247+
continue
248+
249249
with open(file_name, "wb") as fout:
250250
with tqdm(
251251
unit='B', unit_scale=True, unit_divisor=1024, miniters=1,
@@ -257,17 +257,35 @@ def download(self):
257257
return
258258

259259
def parse_url(self, url):
260+
if not url:
261+
print("No url provided")
262+
return False
263+
260264
fragment = urlparse(url).fragment.strip('!').split('/')
261265
self.server_hash = fragment[2]
262266
self.rating_key = parse_qs(fragment[3].split('?')[1])['key'][0]
263267

264268
return True
265269

266-
def __init__(self, email, password):
267-
self.email = email
268-
self.password = password
270+
def command_line(self):
271+
ap = argparse.ArgumentParser()
272+
273+
ap.add_argument("-u", "--username", required=True, help="Plex.TV Email/Username")
274+
275+
ap.add_argument("-p", "--password", required=True, help="Plex.TV Password")
276+
277+
ap.add_argument("url", help="URL to Movie, Show, Season, Episode. TIP: Put url inside single quotes.")
269278

270-
plex = PlexDownloader(email, password)
271-
plex.parse_url("")
279+
args = ap.parse_args()
280+
281+
self.email = args.username
282+
self.password = args.password
283+
self.parse_url(args.url)
284+
self.download()
285+
286+
def __init__(self):
287+
return
272288

273-
plex.download()
289+
if __name__ == "__main__":
290+
plex = PlexDownloader()
291+
plex.command_line()

requirements.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
requests==2.24.0
2+
tqdm==4.51.0
3+
urllib3==1.25.10

0 commit comments

Comments
 (0)