import os import json import requests import logging from django.http import JsonResponse, HttpResponse from django.views.decorators.csrf import csrf_exempt from django.views.decorators.http import require_http_methods from django.shortcuts import get_object_or_404 from pxy_openai.assistants import OpenAIAssistant from .models import WhatsAppBot logger = logging.getLogger(__name__) # Utility Functions def send_whatsapp_message(phone_number_id, sender_number, bot_response, graph_api_token): """ Sends a message back to the user via WhatsApp. """ try: response = requests.post( f"https://graph.facebook.com/v18.0/{phone_number_id}/messages", headers={"Authorization": f"Bearer {graph_api_token}"}, json={ "messaging_product": "whatsapp", "to": sender_number, "text": {"body": bot_response}, }, ) response.raise_for_status() except Exception as e: logger.error(f"Error sending message via WhatsApp: {e}") def verify_webhook_token(mode, token, challenge, verify_token): """ Verifies the webhook token and mode. """ if mode == "subscribe" and token == verify_token: return HttpResponse(challenge, status=200) return HttpResponse("Forbidden", status=403) def parse_webhook_payload(payload): """ Parses the webhook payload and extracts relevant data. """ entry = payload.get("entry", [{}])[0] changes = entry.get("changes", [{}])[0] value = changes.get("value", {}) message = value.get("messages", [{}])[0] return value, message # Webhook Endpoint @csrf_exempt def webhook(request): """ Handles incoming webhook requests from WhatsApp. """ if request.method == "GET": # Webhook verification mode = request.GET.get("hub.mode") token = request.GET.get("hub.verify_token") challenge = request.GET.get("hub.challenge") # Use the first active bot for verification bot = WhatsAppBot.objects.filter(is_active=True).first() if bot: return verify_webhook_token(mode, token, challenge, bot.webhook_verify_token) return HttpResponse("No active bots configured", status=500) elif request.method == "POST": try: # Parse the incoming payload payload = json.loads(request.body) value, message = parse_webhook_payload(payload) if message.get("type") == "text": user_message = message["text"]["body"] phone_number_id = value.get("metadata", {}).get("phone_number_id") sender_number = message["from"] logger.info(f"Received phone_number_id from webhook payload: {phone_number_id}") # Fetch the appropriate bot configuration bot = get_object_or_404(WhatsAppBot, phone_number_id=phone_number_id, is_active=True) # Initialize the assistant and get a response assistant = OpenAIAssistant(name=bot.assistant.name) try: bot_response = assistant.handle_message(user_message) except Exception as e: bot_response = f"Assistant error: {e}" logger.error(bot_response) # Send the response back to the user send_whatsapp_message(bot.phone_number_id, sender_number, bot_response, bot.graph_api_token) except Exception as e: logger.error(f"Error processing webhook: {e}") return JsonResponse({}, status=200) return HttpResponse("Method Not Allowed", status=405) # Webhook Verification Endpoint @require_http_methods(["GET"]) def webhook_verification(request): """ Verifies the webhook token from WhatsApp. """ mode = request.GET.get("hub.mode") token = request.GET.get("hub.verify_token") challenge = request.GET.get("hub.challenge") # Use the first active bot for verification bot = WhatsAppBot.objects.filter(is_active=True).first() if bot: return verify_webhook_token(mode, token, challenge, bot.webhook_verify_token) return HttpResponse("No active bots configured", status=500) # Root Endpoint def root(request): """ A root endpoint for basic connectivity testing. """ return HttpResponse("
Nothing to see here.\nCheckout README.md to start.
", content_type="text/html")