plexbrowse.py
· 3.3 KiB · Python
Raw
#!/usr/bin/env python3
import requests
from sys import stderr, stdout, argv
from os import environ
from os.path import basename
host = environ.get("PLEX_HOST", "localhost")
token = environ.get("PLEX_TOKEN", "")
args = argv[1:]
DL = False
if args and args[0] == "-g":
args = args[1:]
DL = True
def prompt(text, prelude=None):
global args
if not args:
if prelude:
print(prelude, file=stderr)
print(text, file=stderr, end="")
else:
if args[0] == "-s":
args.pop(0)
term1 = args.pop(0)
term2 = None
if "-" in term1:
term1, term2 = term1.split("-",1)
psplit = prelude.split("\n")
match1 = psplit.index([m for m in psplit if term1.lower() in m.lower()][0])
match2 = None
if term2:
match2 = psplit.index([m for m in psplit if term2.lower() in m.lower()][0])
picked = f"{match1}{f'-{match2}' if match2 else ''}"
else:
picked = args.pop(0)
return picked
return input()
def get(endpoint):
url = host + ("/" if endpoint[0] != "/" else "") + endpoint
r = requests.get(url, params={"X-Plex-Token": token}, headers={"Accept": "application/json"})
return r.json()
def main():
libraries = [d for d in get("/library/sections")["MediaContainer"]["Directory"]]
_ = []
for l in sorted(libraries, key=lambda l: l["key"]):
_.append(f"[{l['key']}] {l['title']}")
choice = prompt("Pick library: ", prelude="\n".join(_))
library = [l for l in libraries if l["key"] == choice][0]
lib_list = [i for i in get(f"/library/sections/{library['key']}/all")["MediaContainer"]["Metadata"]]
_ = []
for n,i in enumerate(lib_list):
_.append(f"[{n}] {i['title']}")
picked = lib_list[int(prompt("Pick item: ", prelude="\n".join(_)))]
if picked["type"] == "artist":
tracks = [t for t in get(picked["key"].replace("children", "allLeaves"))["MediaContainer"]["Metadata"]]
_ = []
for n,t in enumerate(tracks):
_.append(f"[{n}] {t['title']}")
picked = tracks[int(prompt("Pick track: ", prelude="\n".join(_)))]
elif picked["type"] == "show":
episodes = [e for e in get(picked["key"].replace("children", "allLeaves"))["MediaContainer"]["Metadata"]]
_ = []
for n,e in enumerate(episodes):
_.append(f"[{n}] S{e['parentIndex']:02d}E{e['index']:02d} {e['title']}")
c = prompt("Pick episode: ", prelude="\n".join(_))
if "-" in c:
a,b = map(int,c.split("-"))
picked = episodes[a:b+1]
else:
picked = [episodes[int(c)]]
for item in picked:
if len(item["Media"]) > 1:
files = [f for f in item["Media"]]
_ = []
for n,f in enumerate(files):
_.append(f"[{n}] {f['title']}")
item = files[int(prompt("Pick file: ", prelude="\n".join(_)))]
else:
item = item["Media"][0]
url = f"{host}{item['Part'][0]['key']}?X-Plex-Token={token}"
if DL:
fn = basename(item["Part"][0]["file"].replace("\\", "/"))
print(f"{url}\n out={fn}")
else:
print(url)
return 0
if __name__ == "__main__":
from sys import exit
exit(main())
| 1 | #!/usr/bin/env python3 |
| 2 | import requests |
| 3 | from sys import stderr, stdout, argv |
| 4 | from os import environ |
| 5 | from os.path import basename |
| 6 | |
| 7 | host = environ.get("PLEX_HOST", "localhost") |
| 8 | token = environ.get("PLEX_TOKEN", "") |
| 9 | |
| 10 | args = argv[1:] |
| 11 | DL = False |
| 12 | if args and args[0] == "-g": |
| 13 | args = args[1:] |
| 14 | DL = True |
| 15 | |
| 16 | def prompt(text, prelude=None): |
| 17 | global args |
| 18 | if not args: |
| 19 | if prelude: |
| 20 | print(prelude, file=stderr) |
| 21 | print(text, file=stderr, end="") |
| 22 | else: |
| 23 | if args[0] == "-s": |
| 24 | args.pop(0) |
| 25 | term1 = args.pop(0) |
| 26 | term2 = None |
| 27 | if "-" in term1: |
| 28 | term1, term2 = term1.split("-",1) |
| 29 | psplit = prelude.split("\n") |
| 30 | match1 = psplit.index([m for m in psplit if term1.lower() in m.lower()][0]) |
| 31 | match2 = None |
| 32 | if term2: |
| 33 | match2 = psplit.index([m for m in psplit if term2.lower() in m.lower()][0]) |
| 34 | picked = f"{match1}{f'-{match2}' if match2 else ''}" |
| 35 | else: |
| 36 | picked = args.pop(0) |
| 37 | return picked |
| 38 | return input() |
| 39 | |
| 40 | def get(endpoint): |
| 41 | url = host + ("/" if endpoint[0] != "/" else "") + endpoint |
| 42 | r = requests.get(url, params={"X-Plex-Token": token}, headers={"Accept": "application/json"}) |
| 43 | return r.json() |
| 44 | |
| 45 | def main(): |
| 46 | libraries = [d for d in get("/library/sections")["MediaContainer"]["Directory"]] |
| 47 | _ = [] |
| 48 | for l in sorted(libraries, key=lambda l: l["key"]): |
| 49 | _.append(f"[{l['key']}] {l['title']}") |
| 50 | choice = prompt("Pick library: ", prelude="\n".join(_)) |
| 51 | library = [l for l in libraries if l["key"] == choice][0] |
| 52 | lib_list = [i for i in get(f"/library/sections/{library['key']}/all")["MediaContainer"]["Metadata"]] |
| 53 | _ = [] |
| 54 | for n,i in enumerate(lib_list): |
| 55 | _.append(f"[{n}] {i['title']}") |
| 56 | picked = lib_list[int(prompt("Pick item: ", prelude="\n".join(_)))] |
| 57 | |
| 58 | if picked["type"] == "artist": |
| 59 | tracks = [t for t in get(picked["key"].replace("children", "allLeaves"))["MediaContainer"]["Metadata"]] |
| 60 | _ = [] |
| 61 | for n,t in enumerate(tracks): |
| 62 | _.append(f"[{n}] {t['title']}") |
| 63 | picked = tracks[int(prompt("Pick track: ", prelude="\n".join(_)))] |
| 64 | elif picked["type"] == "show": |
| 65 | episodes = [e for e in get(picked["key"].replace("children", "allLeaves"))["MediaContainer"]["Metadata"]] |
| 66 | _ = [] |
| 67 | for n,e in enumerate(episodes): |
| 68 | _.append(f"[{n}] S{e['parentIndex']:02d}E{e['index']:02d} {e['title']}") |
| 69 | c = prompt("Pick episode: ", prelude="\n".join(_)) |
| 70 | if "-" in c: |
| 71 | a,b = map(int,c.split("-")) |
| 72 | picked = episodes[a:b+1] |
| 73 | else: |
| 74 | picked = [episodes[int(c)]] |
| 75 | |
| 76 | for item in picked: |
| 77 | if len(item["Media"]) > 1: |
| 78 | files = [f for f in item["Media"]] |
| 79 | _ = [] |
| 80 | for n,f in enumerate(files): |
| 81 | _.append(f"[{n}] {f['title']}") |
| 82 | item = files[int(prompt("Pick file: ", prelude="\n".join(_)))] |
| 83 | else: |
| 84 | item = item["Media"][0] |
| 85 | |
| 86 | url = f"{host}{item['Part'][0]['key']}?X-Plex-Token={token}" |
| 87 | if DL: |
| 88 | fn = basename(item["Part"][0]["file"].replace("\\", "/")) |
| 89 | print(f"{url}\n out={fn}") |
| 90 | else: |
| 91 | print(url) |
| 92 | return 0 |
| 93 | |
| 94 | if __name__ == "__main__": |
| 95 | from sys import exit |
| 96 | exit(main()) |