devZenaight commited on
Commit
3aa2eb2
·
verified ·
1 Parent(s): c5e44f5

Upload 5 files

Browse files
Files changed (2) hide show
  1. main.py +70 -96
  2. requirements.txt +4 -4
main.py CHANGED
@@ -1,96 +1,70 @@
1
- import os, json
2
- from fastapi import FastAPI, Request, HTTPException, Query
3
- from fastapi.responses import PlainTextResponse, JSONResponse
4
- import httpx
5
- import base64
6
-
7
- app = FastAPI()
8
-
9
- VERIFY_TOKEN = os.getenv("VERIFY_TOKEN", "") # set in HF Secrets
10
- PHONE_NUMBER_ID = os.getenv("PHONE_NUMBER_ID", "")
11
- WHATSAPP_API_TOKEN = os.getenv("WHATSAPP_API_TOKEN", "")
12
-
13
- @app.get("/webhook") # verification
14
- def verify(
15
- hub_mode: str = Query(None, alias="hub.mode"),
16
- hub_token: str = Query(None, alias="hub.verify_token"),
17
- hub_challenge: str = Query(None, alias="hub.challenge")
18
- ):
19
- if hub_mode == "subscribe" and hub_token == VERIFY_TOKEN:
20
- return PlainTextResponse(hub_challenge)
21
- raise HTTPException(status_code=403, detail="Invalid token")
22
-
23
- def send_whatsapp_message(wa_id, reply):
24
- url = f"https://graph.facebook.com/v23.0/{PHONE_NUMBER_ID}/messages"
25
- headers = {
26
- "Authorization": f"Bearer {WHATSAPP_API_TOKEN}",
27
- "Content-Type": "application/json"
28
- }
29
- payload = {
30
- "messaging_product": "whatsapp",
31
- "to": wa_id,
32
- "type": "text",
33
- "text": {"body": reply}
34
- }
35
- httpx.post(url, headers=headers, json=payload)
36
-
37
- @app.post("/webhook") # incoming WhatsApp updates
38
- async def receive_update(req: Request):
39
- data = await req.json()
40
- try:
41
- change = data["entry"][0]["changes"][0]["value"]
42
- contacts = change.get("contacts")
43
- messages = change.get("messages")
44
- if not contacts or not messages:
45
- # Missing expected payload—ignore
46
- print("Ignoring update, no contacts or messages field")
47
- return JSONResponse({"status": "ignored", "reason": "no contacts/messages"})
48
-
49
- wa_id = contacts[0]["wa_id"]
50
- msg = messages[0]
51
- except (KeyError, IndexError, TypeError) as e:
52
- print("Malformed webhook payload:", e)
53
- return JSONResponse({"status": "ignored", "reason": "malformed payload"})
54
-
55
- # IMAGE: if user sent an image, convert to Base64 preview
56
- if msg["type"] == "image":
57
- media_id = msg["image"]["id"]
58
- # 1) get media URL
59
- media_resp = httpx.get(
60
- f"https://graph.facebook.com/v23.0/{media_id}",
61
- headers={"Authorization": f"Bearer {WHATSAPP_API_TOKEN}"}
62
- )
63
- media_resp.raise_for_status()
64
- media_url = media_resp.json()["url"]
65
- # 2) download bytes with auth
66
- media_bytes = httpx.get(
67
- media_url,
68
- headers={"Authorization": f"Bearer {WHATSAPP_API_TOKEN}"}
69
- ).content
70
- # 3) encode & preview
71
- preview = base64.b64encode(media_bytes).decode("utf-8")[:10]
72
- # send back preview
73
- send_whatsapp_message(wa_id, f"Base64: {preview}")
74
- return JSONResponse({"status": "image_preview_sent", "preview": preview})
75
-
76
- # TEXT: simple echo
77
- if msg["type"] == "text":
78
- incoming = msg["text"]["body"]
79
- reply = f"You said: {incoming}"
80
- send_whatsapp_message(wa_id, reply)
81
- return JSONResponse({"status": "replied"})
82
-
83
- # OTHER: ignore
84
- return JSONResponse({"status": "ignored", "type": msg["type"]})
85
-
86
- # health-check endpoint for token
87
- @app.post("/send")
88
- async def check_token():
89
- token = os.getenv("WHATSAPP_API_TOKEN", "")
90
- if token:
91
- return {"token_loaded": True}
92
- raise HTTPException(status_code=400, detail="Token not found")
93
-
94
- @app.get("/ping") # health check
95
- def ping():
96
- return {"pong": True}
 
1
+ import os, json
2
+ from fastapi import FastAPI, Request, HTTPException, Query
3
+ from fastapi.responses import PlainTextResponse, JSONResponse
4
+ import httpx
5
+ import base64
6
+
7
+ app = FastAPI()
8
+
9
+ VERIFY_TOKEN = os.getenv("VERIFY_TOKEN", "") # set in HF Secrets
10
+ PHONE_NUMBER_ID = os.getenv("PHONE_NUMBER_ID", "")
11
+ WHATSAPP_API_TOKEN = os.getenv("WHATSAPP_API_TOKEN", "")
12
+
13
+ @app.get("/webhook") # verification
14
+ def verify(
15
+ hub_mode: str = Query(None, alias="hub.mode"),
16
+ hub_token: str = Query(None, alias="hub.verify_token"),
17
+ hub_challenge: str = Query(None, alias="hub.challenge")
18
+ ):
19
+ if hub_mode == "subscribe" and hub_token == VERIFY_TOKEN:
20
+ return PlainTextResponse(hub_challenge)
21
+ raise HTTPException(status_code=403, detail="Invalid token")
22
+
23
+ @app.post("/webhook")
24
+ async def receive_update(req: Request):
25
+ data = await req.json()
26
+ change = data["entry"][0]["changes"][0]["value"]
27
+ wa_id = change["contacts"][0]["wa_id"]
28
+ msg = change["messages"][0]
29
+
30
+ # IMAGE: if user sent an image, convert to Base64 preview
31
+ if msg["type"] == "image":
32
+ media_id = msg["image"]["id"]
33
+ # 1) get media URL
34
+ media_resp = httpx.get(
35
+ f"https://graph.facebook.com/v23.0/{media_id}",
36
+ headers={"Authorization": f"Bearer {WHATSAPP_API_TOKEN}"}
37
+ )
38
+ media_resp.raise_for_status()
39
+ media_url = media_resp.json()["url"]
40
+ # 2) download bytes with auth
41
+ media_bytes = httpx.get(
42
+ media_url,
43
+ headers={"Authorization": f"Bearer {WHATSAPP_API_TOKEN}"}
44
+ ).content
45
+ # 3) encode & preview
46
+ preview = base64.b64encode(media_bytes).decode("utf-8")[:10]
47
+ # send back preview
48
+ send_whatsapp_message(wa_id, f"Base64: {preview}")
49
+ return JSONResponse({"status": "image_preview_sent", "preview": preview})
50
+
51
+ # TEXT: simple echo
52
+ if msg["type"] == "text":
53
+ incoming = msg["text"]["body"]
54
+ reply = f"You said: {incoming}"
55
+ send_whatsapp_message(wa_id, reply)
56
+ return JSONResponse({"status": "replied"})
57
+
58
+ # OTHER: ignore
59
+ return JSONResponse({"status": "ignored", "type": msg["type"]})
60
+
61
+ @app.post("/send")
62
+ async def check_token():
63
+ token = os.getenv("WHATSAPP_API_TOKEN", "")
64
+ if token:
65
+ return {"token_loaded": True}
66
+ raise HTTPException(status_code=400, detail="Token not found")
67
+
68
+ @app.get("/ping") # health check
69
+ def ping():
70
+ return {"pong": True}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
requirements.txt CHANGED
@@ -1,4 +1,4 @@
1
- fastapi
2
- uvicorn
3
- python-dotenv
4
- httpx
 
1
+ fastapi
2
+ uvicorn
3
+ python-dotenv
4
+ httpx