File size: 3,899 Bytes
ecbc095
bdd8925
68f07e2
ecbc095
047bda7
ecbc095
68f07e2
 
 
ecbc095
 
 
 
68f07e2
 
 
 
 
 
 
 
 
 
4a6e3e3
 
68f07e2
4a6e3e3
 
 
68f07e2
 
975c3a7
4a6e3e3
 
 
68f07e2
 
 
4a6e3e3
 
 
68f07e2
 
 
658ffaf
 
68f07e2
 
 
 
658ffaf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68f07e2
658ffaf
68f07e2
 
 
 
ecbc095
 
 
4691e67
047bda7
ecbc095
 
 
 
 
68f07e2
ecbc095
 
68f07e2
 
 
ecbc095
89615e3
ecbc095
89615e3
68f07e2
89615e3
 
68f07e2
 
 
de0e189
68f07e2
4a6e3e3
68f07e2
 
 
ecbc095
 
 
 
 
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
# app/routes/wa_gateway.py
from fastapi import APIRouter, Request
import os, requests, asyncio
from dotenv import load_dotenv
from fastapi.responses import PlainTextResponse, JSONResponse

# ----- import the Q&A logic -----
from routes.question import ask_question, QuestionInput   # ← new

load_dotenv()

wa_router = APIRouter()

VERIFY_TOKEN      = os.getenv("VERIFY_TOKEN")
ACCESS_TOKEN      = os.getenv("WHATSAPP_ACCESS_TOKEN")
PHONE_NUMBER_ID   = os.getenv("WHATSAPP_PHONE_NUMBER_ID")

def send_whatsapp_text(to: str, text: str) -> dict:
    """
    Send a plain text message (max 4096 chars per WhatsApp limits).
    Returns {'status': 'sent' | 'failed', ... } for easy logging.
    """
    url = f"https://graph.facebook.com/v17.0/{PHONE_NUMBER_ID}/messages"
    headers = {
        "Authorization": f"Bearer {ACCESS_TOKEN}",
        "Content-Type":  "application/json",
    }
    payload = {
        "messaging_product": "whatsapp",
        "to":   to,
        "type": "text",
        "text": {"body": text[:4096]},
    }

    try:
        r = requests.post(url, headers=headers, json=payload)
        r.raise_for_status()
        return {"status": "sent", "response": r.json()}
    except Exception as e:
        return {"status": "failed", "error": str(e)}

async def nuse_interact(to: str, name: str, prompt: str) -> dict:
    """
    1. Call ask_question() directly (no HTTP round-trip);
    2. Extract the answer text (+sources or headlines);
    3. Push it back to the user via WhatsApp API using link previews.
    """
    qa_result = await ask_question(QuestionInput(question=prompt))
    answer_text = qa_result["answer"]

    # If headlines were returned (qid == 13)
    if "headlines" in qa_result:
        headlines = qa_result["headlines"]
        if not headlines:
            return send_whatsapp_text(to, "Sorry, no headlines found today.")

        # Build preview message
        preview_msgs = []
        for h in headlines:
            preview_msgs.append(
                f"πŸ—žοΈ *{h['title']}* ({h.get('category', '').title()})\n{h['summary']}\nπŸ”— {h['url']}"
            )

        message = f"{answer_text}\n\n" + "\n\n".join(preview_msgs[:10])  # show up to 10
        return send_whatsapp_text(to, message)

    # Fallback: regular Q&A with optional sources
    if qa_result.get("sources"):
        bullet_list = "\n".join(f"β€’ {s['title']} – {s['url']}" for s in qa_result["sources"])
        answer_text = f"{answer_text}\n\nSources:\n{bullet_list}"

    return send_whatsapp_text(to, answer_text)

@wa_router.get("/webhook")
async def verify_webhook(request: Request):
    params = request.query_params
    if params.get("hub.mode") == "subscribe" and params.get("hub.verify_token") == VERIFY_TOKEN:
        return PlainTextResponse(content=params.get("hub.challenge"))
    return JSONResponse(status_code=403, content={"error": "Verification failed"})

@wa_router.post("/webhook")
async def receive_whatsapp_event(request: Request):
    body = await request.json()
    print("[WEBHOOK] Incoming:", body)

    try:
        entry    = body["entry"][0]
        changes  = entry["changes"][0]
        value    = changes["value"]
        messages = value.get("messages")
        contacts = value.get("contacts")

        if messages and contacts:
            msg     = messages[0]
            contact = contacts[0]

            from_number  = msg["from"]
            sender_name  = contact["profile"]["name"]
            incoming_txt = msg["text"]["body"]

            print(f"[INFO] {sender_name} ({from_number}): {incoming_txt}")

            # Hand off to Q&A -> WhatsApp reply
            result = await nuse_interact(from_number, sender_name, incoming_txt)
            print("[INFO] Reply status:", result)

    except Exception as e:
        print("[ERROR] Webhook processing failed:", str(e))

    return JSONResponse(content={"status": "received"})