Alyssa Smith revised this gist . Go to revision
1 file changed, 4 insertions, 1 deletion
plexbrowse.py
| @@ -52,4 +52,7 @@ def main(): | |||
| 52 | 52 | ||
| 53 | 53 | if __name__ == "__main__": | |
| 54 | 54 | from sys import exit | |
| 55 | - | exit(main()) | |
| 55 | + | try: | |
| 56 | + | exit(main()) | |
| 57 | + | except KeyboardInterrupt: | |
| 58 | + | exit(255) | |
Alyssa Smith revised this gist . Go to revision
1 file changed, 55 insertions
plexbrowse.py(file created)
| @@ -0,0 +1,55 @@ | |||
| 1 | + | #!/usr/bin/env python3 | |
| 2 | + | # python3 plexbrowse.py | while read p; do mpv "$p"; done | |
| 3 | + | # use --host to set the hostname of the server to access | |
| 4 | + | # set PLEX_TOKEN in your environment with your X-Plex-Token | |
| 5 | + | import requests | |
| 6 | + | from os import environ | |
| 7 | + | from os.path import basename | |
| 8 | + | import xml.etree.ElementTree as ET | |
| 9 | + | from sys import stderr | |
| 10 | + | ||
| 11 | + | token = environ["PLEX_TOKEN"] | |
| 12 | + | ||
| 13 | + | def get(*args, **kwargs): | |
| 14 | + | if "params" not in kwargs: | |
| 15 | + | kwargs["params"] = {} | |
| 16 | + | kwargs["params"]["X-Plex-Token"] = token | |
| 17 | + | return requests.get(*args, **kwargs) | |
| 18 | + | ||
| 19 | + | def parse(xml): | |
| 20 | + | return ET.fromstring(xml) | |
| 21 | + | ||
| 22 | + | def get_plex(host, path): | |
| 23 | + | return parse(get(f"https://{host}{path}").content) | |
| 24 | + | ||
| 25 | + | def pick_item(items, title=lambda i: i.attrib["title"]): | |
| 26 | + | print("\n".join("{} {}".format(n, title(i)) for n, i in enumerate(items)), file=stderr) | |
| 27 | + | print("> ", end="", file=stderr) | |
| 28 | + | selected = int(input()) | |
| 29 | + | if len(items) < selected: | |
| 30 | + | return False | |
| 31 | + | return items[selected] | |
| 32 | + | ||
| 33 | + | def main(): | |
| 34 | + | from argparse import ArgumentParser | |
| 35 | + | parser = ArgumentParser() | |
| 36 | + | parser.add_argument("--host", default="plex.wa.alyssasmith.id.au") | |
| 37 | + | args = parser.parse_args() | |
| 38 | + | section = pick_item(get_plex(args.host, "/library/sections").findall("Directory")) | |
| 39 | + | item = pick_item(get_plex(args.host, f"/library/sections/{section.attrib['key']}/all").findall("Directory")) | |
| 40 | + | videos = get_plex(args.host, item.attrib["key"].replace("children", "allLeaves")).findall("Video") | |
| 41 | + | medias = [] | |
| 42 | + | for v in videos: | |
| 43 | + | medias += v.findall("Media") | |
| 44 | + | parts = {} | |
| 45 | + | for m in medias: | |
| 46 | + | for p in m.findall("Part"): | |
| 47 | + | parts[basename(p.attrib["file"])] = p.attrib["key"] | |
| 48 | + | filenames = list(parts.keys()) | |
| 49 | + | selected = parts[pick_item(filenames, title=lambda i: i)] | |
| 50 | + | print(f"https://{args.host}{selected}?X-Plex-Token={token}") | |
| 51 | + | return 0 | |
| 52 | + | ||
| 53 | + | if __name__ == "__main__": | |
| 54 | + | from sys import exit | |
| 55 | + | exit(main()) | |