#!/usr/bin/env python3 import requests import json import re with open("query.graphql") as f: QUERY = f.read() PAYLOAD = [ { "query": QUERY, "variables": { "input": { # Cover the whole state (this is pretty overkill, admittedly) "north":53.23294, "south":40.40589, "east":-78.6823, "west":-107.24675, "zoom":9, "layerSlugs": ["normalCameras"], "nonClusterableUris": ["dashboard"] }, "plowType":"plowCameras", } } ] res = requests.post('https://511mn.org/api/graphql', json=PAYLOAD) res.raise_for_status() camera_views = res.json()[0]['data']['mapFeaturesQuery']['mapFeatures'] cameras = [] viewCount = 0 for c in camera_views: if len(c['features']) != 1: print(c) raise Exception(f"Unexpected number of features: {len(c['features'])}") if re.match(r"Show .* cameras", c['tooltip']): raise Exception(f"Not zoomed in enough! Finding aggregate cameras: {c}") for view in c['views']: if len(view['sources']) != 1 if view['category'] == 'VIDEO' else 0: print(view) raise Exception(f"Unexpected number of sources ({len(view['sources'])})") for source in view['sources'] or []: if source['type'] != 'application/x-mpegURL': raise Exception(f"Unexpected type {source['type']}") viewCount += len(c['views']) cameras.append({ "type": "Feature", "geometry": c['features'][0]['geometry'], "properties": { 'address': c['tooltip'], 'website': c['views'][0]['url'], 'originalData': c, }, }) geojson = { "type": "FeatureCollection", "features": cameras, } with open("data.geojson", "w") as f: f.write(json.dumps(geojson)) print(f"{len(cameras)} locations found") print(f"{viewCount} total views")