Steven Smith revised this gist . Go to revision
1 file changed, 7 insertions, 5 deletions
gmusicplay.py
| @@ -1,5 +1,5 @@ | |||
| 1 | 1 | #!/usr/bin/env python3 | |
| 2 | - | from gmusicapi import Mobileclient # pip3 install gmusicapi | |
| 2 | + | from gmusicapi import Mobileclient | |
| 3 | 3 | import os | |
| 4 | 4 | from json import load | |
| 5 | 5 | import sys | |
| @@ -36,14 +36,16 @@ def get_stream(results, selection): | |||
| 36 | 36 | if not section in results: | |
| 37 | 37 | raise ValueError("Invalid section name") | |
| 38 | 38 | n = int(n) | |
| 39 | - | if len(results[section]) > n: | |
| 39 | + | if n+1 > len(results[section]): | |
| 40 | 40 | raise ValueError("Invalid number") | |
| 41 | - | result = results[section][n-1] | |
| 41 | + | result = results[section][n] | |
| 42 | 42 | if section == "song": | |
| 43 | 43 | return client.get_stream_url(result.get("storeId") or result.get("id")) | |
| 44 | 44 | else: | |
| 45 | 45 | raise NotImplemented | |
| 46 | 46 | ||
| 47 | + | get_stream.supported = ["song"] | |
| 48 | + | ||
| 47 | 49 | def main(): | |
| 48 | 50 | from argparse import ArgumentParser | |
| 49 | 51 | parser = ArgumentParser() | |
| @@ -52,11 +54,11 @@ def main(): | |||
| 52 | 54 | args = parser.parse_args() | |
| 53 | 55 | results = search(args.term, results=args.n) | |
| 54 | 56 | for section in results: | |
| 55 | - | print("\n".join("{}#{}: {}".format(section, n+1, i["title"]) for n,i in enumerate(results[section]) if type(i) is dict and i.get("title")), file=sys.stderr) | |
| 57 | + | if section in get_stream.supported: | |
| 58 | + | print("\n".join("{}#{}: {}".format(section, n, i["title"]) for n,i in enumerate(results[section]) if type(i) is dict and i.get("title")), file=sys.stderr) | |
| 56 | 59 | print("Selection (section#number): ", end="", file=sys.stderr) | |
| 57 | 60 | print(get_stream(results, input())) | |
| 58 | 61 | return 0 | |
| 59 | 62 | ||
| 60 | 63 | if __name__ == "__main__": | |
| 61 | 64 | sys.exit(main()) | |
| 62 | - | ||
Steven Smith revised this gist . Go to revision
1 file changed, 62 insertions
gmusicplay.py(file created)
| @@ -0,0 +1,62 @@ | |||
| 1 | + | #!/usr/bin/env python3 | |
| 2 | + | from gmusicapi import Mobileclient # pip3 install gmusicapi | |
| 3 | + | import os | |
| 4 | + | from json import load | |
| 5 | + | import sys | |
| 6 | + | ||
| 7 | + | def mkdir_p(path): | |
| 8 | + | import errno | |
| 9 | + | try: | |
| 10 | + | os.makedirs(path) | |
| 11 | + | except OSError as exc: | |
| 12 | + | if exc.errno == errno.EEXIST and os.path.isdir(path): | |
| 13 | + | pass | |
| 14 | + | else: | |
| 15 | + | raise | |
| 16 | + | ||
| 17 | + | mkdir_p(os.path.expanduser("~/.config")) | |
| 18 | + | with open(os.path.expanduser("~/.config/gmusic.json")) as f: | |
| 19 | + | CONFIG = load(f) | |
| 20 | + | ||
| 21 | + | client = Mobileclient() | |
| 22 | + | client.login(*CONFIG) | |
| 23 | + | ||
| 24 | + | def search(term, results=10): | |
| 25 | + | results = client.search(term, max_results=results) | |
| 26 | + | return {"album": [client.get_album_info(x["album"]["albumId"]) for x in results["album_hits"]], | |
| 27 | + | "artist": [client.get_artist_info(x["artist"]["artistId"], max_rel_artist=0) for x in results["artist_hits"]], | |
| 28 | + | "playlist": [client.get_shared_playlist_contents(x["playlist"]["shareToken"]) for x in results["playlist_hits"]], | |
| 29 | + | "podcast": [client.get_podcast_series_info(x["series"]["seriesId"]) for x in results["podcast_hits"]], | |
| 30 | + | "song": [x["track"] for x in results["song_hits"]], | |
| 31 | + | "video": [x.get("youtube_video", None) for x in results["video_hits"]], | |
| 32 | + | } | |
| 33 | + | ||
| 34 | + | def get_stream(results, selection): | |
| 35 | + | section, _, n = selection.partition("#") | |
| 36 | + | if not section in results: | |
| 37 | + | raise ValueError("Invalid section name") | |
| 38 | + | n = int(n) | |
| 39 | + | if len(results[section]) > n: | |
| 40 | + | raise ValueError("Invalid number") | |
| 41 | + | result = results[section][n-1] | |
| 42 | + | if section == "song": | |
| 43 | + | return client.get_stream_url(result.get("storeId") or result.get("id")) | |
| 44 | + | else: | |
| 45 | + | raise NotImplemented | |
| 46 | + | ||
| 47 | + | def main(): | |
| 48 | + | from argparse import ArgumentParser | |
| 49 | + | parser = ArgumentParser() | |
| 50 | + | parser.add_argument("term", nargs="+") | |
| 51 | + | parser.add_argument("-n", help="number of results returned", type=int, default=10) | |
| 52 | + | args = parser.parse_args() | |
| 53 | + | results = search(args.term, results=args.n) | |
| 54 | + | for section in results: | |
| 55 | + | print("\n".join("{}#{}: {}".format(section, n+1, i["title"]) for n,i in enumerate(results[section]) if type(i) is dict and i.get("title")), file=sys.stderr) | |
| 56 | + | print("Selection (section#number): ", end="", file=sys.stderr) | |
| 57 | + | print(get_stream(results, input())) | |
| 58 | + | return 0 | |
| 59 | + | ||
| 60 | + | if __name__ == "__main__": | |
| 61 | + | sys.exit(main()) | |
| 62 | + | ||