File size: 5,607 Bytes
691b9c2
 
b86c8e7
2ad00a1
b86c8e7
 
691b9c2
 
 
b86c8e7
 
fbc697b
 
b86c8e7
 
 
 
 
 
 
 
ac489de
fbc697b
 
 
 
b86c8e7
 
 
fbc697b
 
 
 
ac489de
 
 
 
fbc697b
 
 
 
 
 
b86c8e7
fbc697b
 
 
ac489de
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fbc697b
 
b86c8e7
 
 
9a8266c
b86c8e7
 
9a8266c
 
b86c8e7
 
 
9a8266c
 
 
 
 
b86c8e7
 
 
 
 
fbc697b
125dc93
 
 
 
691b9c2
 
 
2ad00a1
691b9c2
2ad00a1
f338fae
b86c8e7
fbc697b
28c68bc
 
 
fbc697b
b86c8e7
fbc697b
691b9c2
 
 
 
b86c8e7
691b9c2
b86c8e7
fbc697b
 
 
 
b86c8e7
 
 
 
 
 
28c68bc
 
691b9c2
 
b86c8e7
 
 
691b9c2
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# 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),
        },
    }