mirror of
https://github.com/Sea-Haven-Industries/meal-order-manager.git
synced 2026-10-05 13:01:58 +00:00
107 lines
4.1 KiB
Python
107 lines
4.1 KiB
Python
|
|
"""
|
||
|
|
Deep recon: extract the full structure of a single meal card
|
||
|
|
and check for menu-related API endpoints.
|
||
|
|
"""
|
||
|
|
|
||
|
|
import json
|
||
|
|
from playwright.sync_api import sync_playwright
|
||
|
|
|
||
|
|
|
||
|
|
def run():
|
||
|
|
api_hits = []
|
||
|
|
|
||
|
|
with sync_playwright() as p:
|
||
|
|
browser = p.chromium.launch(headless=True)
|
||
|
|
context = browser.new_context(
|
||
|
|
user_agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36"
|
||
|
|
)
|
||
|
|
page = context.new_page()
|
||
|
|
|
||
|
|
def capture_response(response):
|
||
|
|
ct = response.headers.get("content-type", "")
|
||
|
|
if "json" in ct or "/api/" in response.url:
|
||
|
|
try:
|
||
|
|
body = response.json()
|
||
|
|
api_hits.append({"url": response.url, "body": body})
|
||
|
|
except Exception:
|
||
|
|
pass
|
||
|
|
|
||
|
|
page.on("response", capture_response)
|
||
|
|
|
||
|
|
page.goto("https://www.redefinemeals.com/menu", wait_until="networkidle", timeout=60000)
|
||
|
|
page.wait_for_timeout(3000)
|
||
|
|
|
||
|
|
# Extract detailed structure from first few article cards
|
||
|
|
articles = page.query_selector_all("article.editorial_card")
|
||
|
|
print(f"Found {len(articles)} article.editorial_card elements\n")
|
||
|
|
|
||
|
|
for i, article in enumerate(articles[:3]):
|
||
|
|
html = article.evaluate("el => el.outerHTML")
|
||
|
|
text = article.inner_text()
|
||
|
|
print(f"--- Article {i} ---")
|
||
|
|
print(f"Text:\n{text}\n")
|
||
|
|
print(f"HTML:\n{html[:3000]}\n")
|
||
|
|
|
||
|
|
# Check for dietary tag elements
|
||
|
|
print("\n--- Dietary/tag elements ---")
|
||
|
|
for sel in ["[class*='tag']", "[class*='diet']", "[class*='label']", "[class*='badge']", "[class*='filter']"]:
|
||
|
|
els = page.query_selector_all(sel)
|
||
|
|
if els:
|
||
|
|
texts = [e.inner_text().strip() for e in els[:10] if e.inner_text().strip()]
|
||
|
|
print(f" {sel}: {len(els)} elements, samples: {texts}")
|
||
|
|
|
||
|
|
# Check for filter/category buttons
|
||
|
|
print("\n--- Filter/category buttons ---")
|
||
|
|
for sel in ["button", "[class*='filter']", "[class*='category']", "[class*='tab']"]:
|
||
|
|
els = page.query_selector_all(sel)
|
||
|
|
if els:
|
||
|
|
texts = [e.inner_text().strip() for e in els[:20] if e.inner_text().strip()]
|
||
|
|
print(f" {sel}: {texts}")
|
||
|
|
|
||
|
|
# Try known API patterns
|
||
|
|
print("\n--- Trying API endpoints ---")
|
||
|
|
for path in ["/api/menu", "/api/products", "/api/meals", "/api/items", "/api/categories"]:
|
||
|
|
try:
|
||
|
|
resp = page.evaluate(f"""
|
||
|
|
async () => {{
|
||
|
|
const r = await fetch('{path}');
|
||
|
|
if (r.ok) return await r.text();
|
||
|
|
return `${{r.status}}`;
|
||
|
|
}}
|
||
|
|
""")
|
||
|
|
if resp and resp not in ["404", "500", "403"]:
|
||
|
|
print(f" {path}: {resp[:500]}")
|
||
|
|
else:
|
||
|
|
print(f" {path}: {resp}")
|
||
|
|
except Exception as e:
|
||
|
|
print(f" {path}: error - {e}")
|
||
|
|
|
||
|
|
# Check for Quick View modal data
|
||
|
|
print("\n--- Quick View data (click first meal) ---")
|
||
|
|
quick_view_btns = page.query_selector_all("[class*='quick']")
|
||
|
|
if quick_view_btns:
|
||
|
|
print(f" Found {len(quick_view_btns)} Quick View buttons")
|
||
|
|
try:
|
||
|
|
quick_view_btns[0].click()
|
||
|
|
page.wait_for_timeout(2000)
|
||
|
|
# Look for modal content
|
||
|
|
for sel in [".modal", "[class*='modal']", "[class*='popup']", "[class*='quick-view']", "[class*='quickview']"]:
|
||
|
|
modal = page.query_selector(sel)
|
||
|
|
if modal and modal.is_visible():
|
||
|
|
print(f" Modal selector: {sel}")
|
||
|
|
print(f" Modal text:\n{modal.inner_text()[:1000]}")
|
||
|
|
break
|
||
|
|
except Exception as e:
|
||
|
|
print(f" Quick View click failed: {e}")
|
||
|
|
|
||
|
|
print(f"\n--- API calls captured ---")
|
||
|
|
for hit in api_hits:
|
||
|
|
print(f" {hit['url']}")
|
||
|
|
print(f" {json.dumps(hit['body'])[:500]}\n")
|
||
|
|
|
||
|
|
browser.close()
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
run()
|