Rename index.js to app.py
Browse files
app.py
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import streamlit as st
|
| 2 |
+
import asyncio
|
| 3 |
+
import json
|
| 4 |
+
from playwright.async_api import async_playwright
|
| 5 |
+
|
| 6 |
+
st.set_page_config(page_title="Network Inspector", layout="wide")
|
| 7 |
+
st.title("π Network Request Inspector")
|
| 8 |
+
st.caption("Paste a Goal.com match URL to intercept all API calls")
|
| 9 |
+
|
| 10 |
+
url = st.text_input("Match URL", placeholder="https://www.goal.com/en-ng/match/...")
|
| 11 |
+
|
| 12 |
+
if st.button("Inspect") and url:
|
| 13 |
+
with st.spinner("Loading page and intercepting requests..."):
|
| 14 |
+
|
| 15 |
+
async def intercept(url):
|
| 16 |
+
requests_log = []
|
| 17 |
+
|
| 18 |
+
async with async_playwright() as p:
|
| 19 |
+
browser = await p.chromium.launch(headless=True)
|
| 20 |
+
context = await browser.new_context(
|
| 21 |
+
user_agent="Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15"
|
| 22 |
+
)
|
| 23 |
+
page = await context.new_page()
|
| 24 |
+
|
| 25 |
+
async def handle_request(request):
|
| 26 |
+
if request.resource_type in ("xhr", "fetch"):
|
| 27 |
+
requests_log.append({
|
| 28 |
+
"method": request.method,
|
| 29 |
+
"url": request.url,
|
| 30 |
+
"type": request.resource_type,
|
| 31 |
+
})
|
| 32 |
+
|
| 33 |
+
async def handle_response(response):
|
| 34 |
+
req_url = response.url
|
| 35 |
+
if response.request.resource_type in ("xhr", "fetch"):
|
| 36 |
+
# find existing entry and add status + preview
|
| 37 |
+
for r in requests_log:
|
| 38 |
+
if r["url"] == req_url and "status" not in r:
|
| 39 |
+
r["status"] = response.status
|
| 40 |
+
try:
|
| 41 |
+
body = await response.text()
|
| 42 |
+
r["preview"] = body[:300]
|
| 43 |
+
except Exception:
|
| 44 |
+
r["preview"] = "(could not read body)"
|
| 45 |
+
break
|
| 46 |
+
|
| 47 |
+
page.on("request", handle_request)
|
| 48 |
+
page.on("response", handle_response)
|
| 49 |
+
|
| 50 |
+
await page.goto(url, wait_until="networkidle", timeout=60000)
|
| 51 |
+
# extra wait for lazy-loaded commentary
|
| 52 |
+
await page.wait_for_timeout(5000)
|
| 53 |
+
await browser.close()
|
| 54 |
+
|
| 55 |
+
return requests_log
|
| 56 |
+
|
| 57 |
+
logs = asyncio.run(intercept(url))
|
| 58 |
+
|
| 59 |
+
st.success(f"Captured {len(logs)} XHR/fetch requests")
|
| 60 |
+
|
| 61 |
+
# filter controls
|
| 62 |
+
filter_text = st.text_input("Filter URLs (e.g. 'commentary', 'sportfeeds', 'api')", "")
|
| 63 |
+
|
| 64 |
+
filtered = [r for r in logs if filter_text.lower() in r["url"].lower()] if filter_text else logs
|
| 65 |
+
|
| 66 |
+
st.write(f"Showing {len(filtered)} requests")
|
| 67 |
+
|
| 68 |
+
for i, r in enumerate(filtered):
|
| 69 |
+
status = r.get("status", "?")
|
| 70 |
+
color = "π’" if status == 200 else "π΄"
|
| 71 |
+
with st.expander(f"{color} [{r['method']}] {r['url'][:100]}... (HTTP {status})"):
|
| 72 |
+
st.code(r["url"], language="text")
|
| 73 |
+
if "preview" in r:
|
| 74 |
+
st.subheader("Response preview (first 300 chars)")
|
| 75 |
+
try:
|
| 76 |
+
parsed = json.loads(r["preview"])
|
| 77 |
+
st.json(parsed)
|
| 78 |
+
except Exception:
|
| 79 |
+
st.text(r["preview"])
|
index.js
DELETED
|
@@ -1,51 +0,0 @@
|
|
| 1 |
-
const puppeteer = require("puppeteer");
|
| 2 |
-
const axios = require("axios");
|
| 3 |
-
const fs = require("fs");
|
| 4 |
-
|
| 5 |
-
async function generateImage(text) {
|
| 6 |
-
|
| 7 |
-
const browser = await puppeteer.launch({
|
| 8 |
-
headless: "new",
|
| 9 |
-
args: [
|
| 10 |
-
"--no-sandbox",
|
| 11 |
-
"--disable-setuid-sandbox",
|
| 12 |
-
"--disable-dev-shm-usage",
|
| 13 |
-
"--disable-gpu",
|
| 14 |
-
"--no-zygote",
|
| 15 |
-
"--single-process"
|
| 16 |
-
]
|
| 17 |
-
});
|
| 18 |
-
|
| 19 |
-
const page = await browser.newPage();
|
| 20 |
-
|
| 21 |
-
console.log("Opening page...");
|
| 22 |
-
|
| 23 |
-
await page.goto(
|
| 24 |
-
"https://en.ephoto360.com/create-3d-colorful-paint-text-effect-online-801.html",
|
| 25 |
-
{ waitUntil: "networkidle2" }
|
| 26 |
-
);
|
| 27 |
-
|
| 28 |
-
console.log("Typing text...");
|
| 29 |
-
await page.type("#text-0", text);
|
| 30 |
-
|
| 31 |
-
console.log("Submitting form...");
|
| 32 |
-
await page.click("#submit");
|
| 33 |
-
|
| 34 |
-
console.log("Waiting for generated image...");
|
| 35 |
-
|
| 36 |
-
await page.waitForSelector(".thumbnail img", { timeout: 60000 });
|
| 37 |
-
|
| 38 |
-
const imageUrl = await page.$eval(".thumbnail img", el => el.src);
|
| 39 |
-
|
| 40 |
-
console.log("Image URL:", imageUrl);
|
| 41 |
-
|
| 42 |
-
const response = await axios.get(imageUrl, { responseType: "arraybuffer" });
|
| 43 |
-
|
| 44 |
-
fs.writeFileSync("result.png", response.data);
|
| 45 |
-
|
| 46 |
-
console.log("Image saved β result.png");
|
| 47 |
-
|
| 48 |
-
await browser.close();
|
| 49 |
-
}
|
| 50 |
-
|
| 51 |
-
generateImage("HELLO").catch(console.error);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|