From ac6ca6d1b339dbfbdee5b3b6a8715a4d212295f7 Mon Sep 17 00:00:00 2001 From: Joe Gitta Date: Wed, 27 May 2026 13:44:22 +0000 Subject: [PATCH] deploy: secure weather caching --- browser.py | 40 +++++++++++++++++++++++++++++++- weather.html | 65 +++++++--------------------------------------------- 2 files changed, 47 insertions(+), 58 deletions(-) diff --git a/browser.py b/browser.py index e9a3c44..a66ca8e 100755 --- a/browser.py +++ b/browser.py @@ -803,7 +803,6 @@ def launch_chrome(): "--disable-extensions", "--disable-gpu", "--disable-dev-shm-usage", - "--disable-web-security", "--allow-file-access-from-files", f"--user-data-dir={profile_dir}", f"--remote-debugging-port={CDP_PORT}", @@ -827,9 +826,48 @@ if __name__ == "__main__": overlay = KioskOverlay(cdp) chrome_proc = launch_chrome() + def update_weather_cache(): + """Fetch weather data in background via Python and cache as local JSON to bypass CORS securely.""" + cache_file = _HOME / "kiosk-home" / "weather-data.json" + while True: + try: + # 1. Geolocation lookup + req = urllib.request.Request( + "https://freeipapi.com/api/json", + headers={"User-Agent": "Mozilla/5.0"} + ) + geo_raw = urllib.request.urlopen(req, timeout=8).read() + geo = json.loads(geo_raw) + + loc_name = "Your Area" + if geo.get("cityName") and geo.get("regionName"): + loc_name = f"{geo['cityName']}, {geo['regionName']}" + elif geo.get("cityName"): + loc_name = geo["cityName"] + + lat, lon = geo.get("latitude"), geo.get("longitude") + if lat and lon: + # 2. Weather forecast lookup + url = f"https://api.open-meteo.com/v1/forecast?latitude={lat}&longitude={lon}¤t=temperature_2m,relative_humidity_2m,apparent_temperature,weather_code,wind_speed_10m&daily=weather_code,temperature_2m_max,temperature_2m_min&temperature_unit=fahrenheit&wind_speed_unit=mph&precipitation_unit=inch&timezone=auto" + fc_raw = urllib.request.urlopen(url, timeout=8).read() + fc = json.loads(fc_raw) + + # 3. Save combined cache + payload = {"location": loc_name, "forecast": fc} + cache_file.parent.mkdir(parents=True, exist_ok=True) + cache_file.write_text(json.dumps(payload, indent=2)) + print("Updated local weather-data.json cache successfully") + except Exception as e: + print(f"Weather cache background update failed: {e}") + + # Update cache every 15 minutes + time.sleep(900) + def init_cdp(): if cdp.wait_ready(timeout=30): print("CDP ready — persistent WebSocket connected successfully") + + threading.Thread(target=update_weather_cache, daemon=True).start() threading.Thread(target=init_cdp, daemon=True).start() sys.exit(app.exec_()) diff --git a/weather.html b/weather.html index ef1068e..b850ecc 100644 --- a/weather.html +++ b/weather.html @@ -240,67 +240,19 @@ } async function initWeather() { - // 1. Get coordinates using IP API fallback or direct Geolocation try { - if (navigator.geolocation) { - navigator.geolocation.getCurrentPosition( - async (pos) => { - // Successfully got GPS coordinates - await fetchForecast(pos.coords.latitude, pos.coords.longitude, "Local Location"); - }, - async () => { - // Denied or failed - fall back to IP lookup - await fetchViaIP(); - }, - { timeout: 5000 } - ); - } else { - await fetchViaIP(); - } - } catch (e) { - document.getElementById('loading-text').textContent = "⚠️ Unable to load weather. Check internet connection."; - } - } - - async function fetchViaIP() { - try { - document.getElementById('loading-text').textContent = "🌐 Looking up location via IP..."; - const resp = await fetch("https://freeipapi.com/api/json"); + document.getElementById('loading-text').textContent = "📊 Loading local weather forecasts..."; + const resp = await fetch("weather-data.json"); const data = await resp.json(); - let locName = "Your Area"; - if (data.cityName && data.regionName) { - locName = `${data.cityName}, ${data.regionName}`; - } else if (data.cityName) { - locName = data.cityName; - } - - if (data.latitude && data.longitude) { - await fetchForecast(data.latitude, data.longitude, locName); - } else { - throw new Error("Invalid IP response coordinates"); - } - } catch (e) { - // Ultimate hard-coded default (e.g. general center of US/state if offline) - document.getElementById('loading-text').textContent = "⚠️ Location lookup failed. Please verify internet."; - } - } - - async function fetchForecast(lat, lon, locationLabel) { - try { - document.getElementById('loading-text').textContent = "📊 Loading weather forecasts..."; - - // Query the completely open, keyless Open-Meteo API - const url = `https://api.open-meteo.com/v1/forecast?latitude=${lat}&longitude=${lon}¤t=temperature_2m,relative_humidity_2m,apparent_temperature,weather_code,wind_speed_10m&daily=weather_code,temperature_2m_max,temperature_2m_min&temperature_unit=fahrenheit&wind_speed_unit=mph&precipitation_unit=inch&timezone=auto`; - - const resp = await fetch(url); - const data = await resp.json(); + const locName = data.location || "Your Area"; + const fc = data.forecast; // Render current stats - const current = data.current; + const current = fc.current; const wInfo = getWeatherInfo(current.weather_code); - document.getElementById('location-name').textContent = locationLabel; + document.getElementById('location-name').textContent = locName; document.getElementById('temp-val').textContent = `${Math.round(current.temperature_2m)}°F`; document.getElementById('main-icon').textContent = wInfo.emoji; document.getElementById('condition-txt').textContent = wInfo.txt; @@ -309,11 +261,10 @@ document.getElementById('wind-val').textContent = `${Math.round(current.wind_speed_10m)} mph`; // Render 3-Day Forecast - const daily = data.daily; + const daily = fc.daily; const forecastBox = document.getElementById('forecast-box'); forecastBox.innerHTML = ""; // Clear loader - // We render days 1, 2, and 3 (index 1 to 3, as index 0 is today) for (let i = 1; i <= 3; i++) { const dateStr = daily.time[i]; const dateObj = new Date(dateStr + "T00:00:00"); @@ -338,7 +289,7 @@ document.getElementById('weather-content').style.display = 'block'; } catch (e) { - document.getElementById('loading-text').textContent = "⚠️ Error pulling forecast data."; + document.getElementById('loading-text').textContent = "⚠️ Preparing weather data... Please wait a moment."; } }