Fix bugs and improve robustness of report fetching

- Fix missing 'import sys' in get_report.py that caused a NameError
  on the credential-check error path
- Fix indentation of the per-report print statement in
  report_json_down.py so it prints for every report, not just the
  last one per date
- Replace hardcoded X-ENROLLMENT header value with dynamic extraction
  from selenium-wire intercepted requests
- Replace fragile time.sleep() calls with WebDriverWait so the script
  waits for actual page/login readiness rather than fixed delays
- Remove album_json_down.py, a Windows-only legacy script inherited
  from upstream that was never used in this fork
This commit is contained in:
Jeena 2026-03-18 00:37:35 +00:00
parent d9a45bd317
commit 0ada2d4858
3 changed files with 26 additions and 190 deletions

View file

@ -1,12 +1,14 @@
#!/usr/bin/env python3
import os
import time
import sys
import re
import requests
from dotenv import load_dotenv
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from seleniumwire import webdriver
load_dotenv()
@ -27,6 +29,13 @@ def extract_child_id_from_requests(requests) -> str | None:
return match.group(1)
return None
def extract_enrollment_from_requests(requests) -> str | None:
"""Extract the X-ENROLLMENT header value from intercepted API requests."""
for request in requests:
if '/api/' in request.url and request.headers.get('X-ENROLLMENT'):
return request.headers['X-ENROLLMENT']
return None
# Use headless browser if you don't need to see it
chrome_options = Options()
chrome_options.add_argument("--headless=new")
@ -35,24 +44,34 @@ chrome_options.add_argument("--no-sandbox")
driver = webdriver.Chrome(options=chrome_options)
driver.get(login_url)
# Wait for page to load
time.sleep(2)
# Wait for login form to be ready
wait = WebDriverWait(driver, 30)
wait.until(EC.element_to_be_clickable((By.NAME, "username")))
# Fill in login form
driver.find_element(By.NAME, "username").send_keys(USERNAME)
driver.find_element(By.NAME, "password").send_keys(PASSWORD)
driver.find_element(By.CSS_SELECTOR, "button[type='submit']").click()
# Wait for login to process (adjust if needed)
time.sleep(4)
# Wait until the browser makes an authenticated API call (child reports endpoint)
wait.until(lambda d: extract_child_id_from_requests(d.requests) is not None)
child_id = extract_child_id_from_requests(driver.requests)
enrollment = extract_enrollment_from_requests(driver.requests)
report_url = f"https://www.kidsnote.com/api/v1_2/children/{child_id}/reports/?page_size=5000"
# Extract cookies
cookies = driver.get_cookies()
driver.quit()
if not child_id:
print("Error: could not determine child ID from intercepted requests.")
sys.exit(1)
if not enrollment:
print("Error: could not extract X-ENROLLMENT header from intercepted requests.")
sys.exit(1)
with requests.Session() as session:
# Convert cookies for requests
for cookie in cookies:
@ -72,7 +91,7 @@ with requests.Session() as session:
"Sec-Fetch-Mode": "cors",
"Sec-Fetch-Site": "same-origin",
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:138.0) Gecko/20100101 Firefox/138.0",
"X-ENROLLMENT": "16417613",
"X-ENROLLMENT": enrollment,
}
report_response = session.get(report_url, headers=headers)