i messed up, lmao
Browse files
routes/api/whatsapp_webhook.py
CHANGED
|
@@ -24,9 +24,68 @@ router = APIRouter()
|
|
| 24 |
classifier = ZeroShotClassifier()
|
| 25 |
|
| 26 |
def _extract_from_number_and_text(payload: dict) -> Tuple[Optional[str], Optional[str]]:
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
...
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
|
| 31 |
@router.post("/message-received")
|
| 32 |
async def whatsapp_webhook_receiver(request: Request):
|
|
|
|
| 24 |
classifier = ZeroShotClassifier()
|
| 25 |
|
| 26 |
def _extract_from_number_and_text(payload: dict) -> Tuple[Optional[str], Optional[str]]:
|
| 27 |
+
"""
|
| 28 |
+
Extracts (from_number, message_text) from a WhatsApp webhook payload.
|
| 29 |
+
Returns (None, None) if not a user message (e.g., statuses, billing-event).
|
| 30 |
+
"""
|
| 31 |
+
try:
|
| 32 |
+
entries = payload.get("entry", [])
|
| 33 |
+
for entry in entries:
|
| 34 |
+
changes = entry.get("changes", [])
|
| 35 |
+
for change in changes:
|
| 36 |
+
field = change.get("field")
|
| 37 |
+
# Only process message-type changes
|
| 38 |
+
if field != "messages":
|
| 39 |
+
continue
|
| 40 |
+
|
| 41 |
+
value = change.get("value", {}) or {}
|
| 42 |
+
# Ignore pure status/billing updates that don't have 'messages'
|
| 43 |
+
messages_list = value.get("messages", [])
|
| 44 |
+
if not messages_list:
|
| 45 |
+
# Helpful debug so you can see why it was ignored
|
| 46 |
+
statuses = value.get("statuses", [])
|
| 47 |
+
if statuses:
|
| 48 |
+
# it's a status webhook, not a user message
|
| 49 |
+
pass
|
| 50 |
+
continue
|
| 51 |
+
|
| 52 |
+
# Only look at the first message in the list
|
| 53 |
+
msg = messages_list[0]
|
| 54 |
+
from_number = msg.get("from")
|
| 55 |
+
mtype = msg.get("type")
|
| 56 |
+
|
| 57 |
+
# 1) Plain text
|
| 58 |
+
if mtype == "text":
|
| 59 |
+
text_body = (msg.get("text", {}) or {}).get("body")
|
| 60 |
+
if from_number and text_body:
|
| 61 |
+
return from_number, text_body
|
| 62 |
+
|
| 63 |
+
# 2) Template reply button (older/simple schema)
|
| 64 |
+
if mtype == "button":
|
| 65 |
+
b = msg.get("button", {}) or {}
|
| 66 |
+
intent = b.get("payload") or b.get("text")
|
| 67 |
+
if from_number and intent:
|
| 68 |
+
return from_number, intent
|
| 69 |
+
|
| 70 |
+
# 3) Newer interactive replies (buttons or list)
|
| 71 |
+
if mtype == "interactive":
|
| 72 |
+
i = msg.get("interactive", {}) or {}
|
| 73 |
+
if "button_reply" in i:
|
| 74 |
+
intent = i["button_reply"].get("id") or i["button_reply"].get("title")
|
| 75 |
+
if from_number and intent:
|
| 76 |
+
return from_number, intent
|
| 77 |
+
if "list_reply" in i:
|
| 78 |
+
intent = i["list_reply"].get("id") or i["list_reply"].get("title")
|
| 79 |
+
if from_number and intent:
|
| 80 |
+
return from_number, intent
|
| 81 |
+
|
| 82 |
+
# No usable user message found
|
| 83 |
+
return None, None
|
| 84 |
+
|
| 85 |
+
except Exception as e:
|
| 86 |
+
# Always return a tuple on error
|
| 87 |
+
logging.exception(f"_extract_from_number_and_text error: {e}")
|
| 88 |
+
return None, None
|
| 89 |
|
| 90 |
@router.post("/message-received")
|
| 91 |
async def whatsapp_webhook_receiver(request: Request):
|