Rework how we bypass browser caches of the scouting app

This patch adds a new way to access files on the webserver. Users can
now request files by their sha256 checksum. The URL pattern follows
`/sha256/<checksum>/<path>`. The `<path>` portion doesn't actually
matter, but it helps with readability.

This patch migrates the main bundle and the pictures to use the new
checksum-addressable scheme.

Signed-off-by: Philipp Schrader <philipp.schrader@gmail.com>
Change-Id: I76eaa9b0f69af98e48e8e73e32c82ce2916fbe41
diff --git a/scouting/www/index_html_generator.py b/scouting/www/index_html_generator.py
new file mode 100644
index 0000000..3b057fd
--- /dev/null
+++ b/scouting/www/index_html_generator.py
@@ -0,0 +1,28 @@
+"""Generates index.html with the right checksum for main_bundle_file.js filled in."""
+
+import argparse
+import hashlib
+import sys
+from pathlib import Path
+
+def compute_sha256(filepath):
+    return hashlib.sha256(filepath.read_bytes()).hexdigest()
+
+def main(argv):
+    parser = argparse.ArgumentParser()
+    parser.add_argument("--template", type=str)
+    parser.add_argument("--bundle", type=str)
+    parser.add_argument("--output", type=str)
+    args = parser.parse_args(argv[1:])
+
+    template = Path(args.template).read_text()
+    bundle_path = Path(args.bundle)
+    bundle_sha256 = compute_sha256(bundle_path)
+
+    output = template.format(
+        MAIN_BUNDLE_FILE = f"/sha256/{bundle_sha256}/{bundle_path.name}",
+    )
+    Path(args.output).write_text(output)
+
+if __name__ == "__main__":
+    sys.exit(main(sys.argv))