Pixels-tester / main.py
Mr-Help's picture
Update main.py
ac489de verified
# main.py
from fastapi import FastAPI, Request, UploadFile
from typing import Any, Dict, Tuple
from datetime import datetime
import json, os, asyncio
import httpx # pip install httpx
app = FastAPI()
GAS_WEBAPP_URL = os.getenv("GAS_WEBAPP_URL")
def print_human_friendly(payload: Dict[str, Any]) -> None:
order = [
("client","๐Ÿ‘ค Client"),("source","๐ŸŒ Source"),("event_name","๐ŸŽฏ Event Name"),
("event_id","๐Ÿงพ Event ID"),("value","๐Ÿ’ฐ Value"),("currency","๐Ÿ’ฑ Currency"),
("transaction_id","๐Ÿ’ณ Transaction ID"),("content_id","๐Ÿ†” Content ID"),
("content_type","๐Ÿ“ฆ Content Type"),("fbp","๐Ÿ…ต fbp"),("fbc","๐Ÿ…ต fbc"),
("ttclid","๐Ÿ•ธ๏ธ ttclid"),("ttp","๐Ÿช ttp"),("scid","๐ŸŸช scid"),
("x_email","๐Ÿ“ง x_email (hashed)"),("x_phone","๐Ÿ“ฑ x_phone (hashed)"),
("x_fn","๐Ÿง‘ First Name"),("x_ln","๐Ÿง‘ Last Name"),
("timestamp","โฑ๏ธ Timestamp"),("client_ua","๐Ÿ–ฅ๏ธ Client UA"),
("user_info","๐Ÿ‘ค User Info"), ("cart_data","๐Ÿ›’ Cart Data"),
]
print("\n" + "-"*18 + " ๐Ÿ‘€ Human-friendly view " + "-"*18)
label_pad = 20
for key, label in order:
if isinstance(payload, dict) and key in payload and payload.get(key) not in (None, ""):
print(f"{label:<{label_pad}}: {payload.get(key)}")
contents = payload.get("contents") if isinstance(payload, dict) else None
if isinstance(contents, list):
print("\n๐Ÿงบ Contents:")
for idx, item in enumerate(contents, start=1):
if isinstance(item, dict):
cid = item.get("content_id","-")
name = item.get("content_name","-")
price = item.get("price","-")
qty = item.get("quantity","-")
print(f" #{idx} โ€ข ID: {cid} | Name: {name} | Price: {price} | Qty: {qty}")
else:
print(f" #{idx} โ€ข {item}")
elif contents is not None:
print("\n๐Ÿงบ Contents (raw):")
try:
parsed = contents if isinstance(contents,(dict,list)) else json.loads(str(contents))
print(json.dumps(parsed, ensure_ascii=False, indent=2))
except Exception:
print(str(contents))
# ๐Ÿ‘ค User Info
ui = payload.get("user_info") if isinstance(payload, dict) else None
if ui is not None:
print("\n๐Ÿ‘ค User Info:")
try:
print(json.dumps(ui, ensure_ascii=False, indent=2))
except Exception:
print(str(ui))
# ๐Ÿ›’ Cart Data
cd = payload.get("cart_data") if isinstance(payload, dict) else None
if cd is not None:
print("\n๐Ÿ›’ Cart Data:")
try:
print(json.dumps(cd, ensure_ascii=False, indent=2))
except Exception:
print(str(cd))
print("-"*60 + "\n")
async def post_to_gas_raw(raw_body: str, content_type: str) -> Tuple[int, str]:
if not GAS_WEBAPP_URL or GAS_WEBAPP_URL.startswith("YOUR_"):
return (0, "GAS_WEBAPP_URL is not configured")
headers = {"Content-Type": content_type or "application/json"}
timeout = httpx.Timeout(10.0, connect=5.0)
async with httpx.AsyncClient(timeout=timeout, follow_redirects=True) as client:
for attempt in range(1, 3):
try:
r = await client.post(GAS_WEBAPP_URL, content=raw_body.encode("utf-8"), headers=headers)
# ู„ูˆ ูƒุงู† 302/303 ูˆุงุชุจุนุช ุงู„ุชุญูˆูŠู„ุŒ ู‡ูŠุจู‚ู‰ status 200 ููŠ ุงู„ุขุฎุฑ
# ุจุณ ู„ูˆ ู„ุณู‡ 302 ู„ุฃูŠ ุณุจุจุŒ ุงุนุชุจุฑู‡ ู†ุฌุงุญ ูˆุณุฌู‘ู„ Location
if r.status_code in (301, 302, 303, 307, 308):
loc = r.headers.get("Location", "")
return (r.status_code, f"Redirected to: {loc}")
return (r.status_code, r.text[:5000])
except Exception as e:
if attempt == 2:
return (0, f"Error posting to GAS: {e}")
await asyncio.sleep(0.5)
@app.get("/ping")
async def ping():
return {"message": "pong"}
@app.post("/echo")
async def echo(request: Request) -> Dict[str, Any]:
body_bytes = await request.body()
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
print("\n" + "="*30 + f" ๐Ÿ†• NEW REQUEST ({now}) " + "="*30)
# ุงุทุจุน ุงู„ุจูˆุฏูŠ ุงู„ุฎุงู… ูƒู…ุง ู‡ูˆ
raw_text = body_bytes.decode("utf-8", errors="ignore")
# print("\n๐Ÿ“ Request body:")
# print(raw_text)
# print("="*98)
# ุญุงูˆู„ ู†ุทุจุนู‡ ุจุดูƒู„ ูˆุฏู‘ูŠ ูู‚ุท ู„ูˆ JSON object (ู„ู„ุนุฑุถ ูู‚ุทุŒ ุจุฏูˆู† ุชุนุฏูŠู„ ุงู„ุจูŠุงู†ุงุช)
parsed: Any
try:
parsed = await request.json()
except Exception:
try:
parsed = json.loads(raw_text)
except Exception:
parsed = None
if isinstance(parsed, dict):
print_human_friendly(parsed)
else:
print("\n(โ„น๏ธ Human-friendly view skipped: payload is not a JSON object)\n")
# ๐Ÿš€ ุงุจุนุช ู„ู„ู€ GAS ูƒู…ุง ู‡ูˆ (RAW) ุจู†ูุณ content-type ุงู„ู„ูŠ ุฌู‡
ct = request.headers.get("content-type", "application/json")
gas_status, gas_body = await post_to_gas_raw(raw_text, ct)
print(f"๐Ÿ“ค GAS post status: {gas_status}")
# if gas_body:
# print(f"๐Ÿ”Ž GAS response: {gas_body[:1000]}")
return {
"received": parsed if isinstance(parsed, dict) else raw_text,
"forwarded_to_gas": True,
"gas_status": gas_status,
"info": {
"method": request.method,
"url": str(request.url),
"headers": dict(request.headers),
},
}