Created
May 6, 2021 21:45
-
-
Save lurch/e675ccaf691cc6888d81199276994c7e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# Written by Andrew Scheller, May 2021 | |
# Released under the WTFPL | |
# This is a fun little script that provides an interactive text-based menu for | |
# the user to select an image from; once an image has been selected it prints | |
# the "choices path" that was navigated to get to that image, and the URL that | |
# the image can be downloaded from (e.g. using wget) | |
# | |
# Alternatively, if given a "choices path" it runs non-interactively and | |
# prints out the image download URL corresponding to that option. For example, | |
# image_chooser.py "Raspberry Pi OS (other)" "Raspberry Pi OS Lite (32-bit)" | |
# will print out the URL of the latest RasPiOS Lite image (which is | |
# https://downloads.raspberrypi.org/raspios_lite_armhf/images/raspios_lite_armhf-2021-03-25/2021-03-04-raspios-buster-armhf-lite.zip | |
# at the time of writing) | |
BASE_JSON_URL = 'https://downloads.raspberrypi.org/os_list_imagingutility_v2.json' | |
import urllib.request | |
import json | |
import sys | |
import re | |
json_cache = {} | |
def read_json_list(url): | |
if url not in json_cache: | |
with urllib.request.urlopen(url) as response: | |
json_cache[url] = json.loads(response.read())['os_list'] | |
return json_cache[url] | |
# Allow optional custom BASE_JSON_URL to be supplied | |
if len(sys.argv) > 1 and (sys.argv[1].startswith('http://') or sys.argv[1].startswith('https://')): | |
BASE_JSON_URL = sys.argv.pop(1) | |
if len(sys.argv) > 1: | |
# Noninteracative mode - use supplied "choices path" to find image | |
choices = sys.argv[1:] | |
options = read_json_list(BASE_JSON_URL) | |
found = False | |
while choices: | |
choice = choices.pop(0) | |
options_lookup = {item['name']: index for index, item in enumerate(options)} | |
if choice in options_lookup: | |
chosen = options[options_lookup[choice]] | |
if 'subitems_url' in chosen: | |
options = read_json_list(chosen['subitems_url']) | |
elif 'subitems' in chosen: | |
options = chosen['subitems'] | |
else: | |
found = True | |
# print the selected image url | |
print(chosen['url']) | |
if choices: | |
raise Exception("Found OS before reaching end of choices") | |
break | |
else: | |
raise Exception("\"%s\" not found in %s" % (choice, [item['name'] for item in options])) | |
if not found: | |
raise Exception("No matching OS found") | |
else: | |
# Interactive mode - display menu for user to navigate | |
title = "Select an Operating System" | |
options = read_json_list(BASE_JSON_URL) | |
parents = [] | |
while True: | |
print(title) | |
min_index = 1 | |
if parents: | |
print(" [%d] Go back to: %s" % (0, parents[-1][0])) | |
min_index = 0 | |
for index, item in enumerate(options): | |
prefix = " [%d] %s: " % (index + 1, 'MENU' if 'subitems_url' in item or 'subitems' in item else 'IMAGE') | |
print("%s%s" % (prefix, item['name'])) | |
if 'description' in item: | |
print("%s%s" % (' ' * len(prefix), item['description'])) | |
max_index = len(options) | |
choice = 'invalid' | |
while choice != 'q' and choice != 'quit' and not (re.match('^\d+$', choice) and (min_index <= int(choice) <= max_index)): | |
choice = input("Choose option (%d to %d, or q to quit) ? " % (min_index, max_index)) | |
if choice == 'q' or choice == 'quit': | |
break | |
choice = int(choice) | |
if choice == 0: | |
title, options = parents.pop() | |
else: | |
parents.append((title, options)) | |
chosen = options[choice - 1] | |
title = chosen['name'] | |
if 'subitems_url' in chosen: | |
options = read_json_list(chosen['subitems_url']) | |
elif 'subitems' in chosen: | |
options = chosen['subitems'] | |
else: | |
choices = [p[0] for p in parents[1:]] | |
choices.append(title) | |
# print the selected "choices path" | |
print(' '.join("\"%s\"" % c for c in choices)) | |
# print the selected image url | |
print(chosen['url']) | |
break |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment