import json import logging from django.http import JsonResponse, HttpResponse from django.conf import settings from .services import FacebookService from .models import FacebookPageAssistant, EventType, FacebookEvent import requests from pxy_openai.assistants import OpenAIAssistant as OpenAIService # Configure logging logger = logging.getLogger(__name__) PAGE_ACCESS_TOKEN = settings.PAGE_ACCESS_TOKEN def verify_webhook_token(mode, token, challenge, verify_token): """ Verifies the webhook token and mode. """ if mode == "subscribe" and token == verify_token: logger.info("Webhook verified successfully.") return HttpResponse(challenge, status=200) else: logger.warning(f"Webhook verification failed. Mode: {mode}, Token: {token}") return HttpResponse("Forbidden", status=403) def parse_webhook_payload(payload): """ Parses the webhook payload and extracts relevant data. """ try: entry = payload.get("entry", [{}])[0] changes = entry.get("changes", [{}])[0] value = changes.get("value", {}) return value except Exception as e: logger.error(f"Error parsing payload: {e}") raise def handle_comment_event(page_id, sender_id, data): """ Handles incoming comment events: 1) Persiste el evento en la BD. 2) Responde al comentario vía FacebookService. """ # Si el comentario viene de la propia página, lo saltamos if sender_id == page_id: logger.info(f"Skipping self-generated comment. Sender ID: {sender_id}, Page ID: {page_id}") return JsonResponse({"status": "skipped"}, status=200) comment_id = data.get("comment_id") original_message = data.get("message") # 1) Registrar en la base de datos try: page = FacebookPageAssistant.objects.get(page_id=page_id) et = EventType.objects.get(code="comment") FacebookEvent.objects.create( page=page, event_type=et, sender_id=sender_id, object_id=comment_id, message=original_message ) except Exception as e: logger.error(f"Error logging FB comment event: {e}") # 2) Responder al comentario via API de Facebook if comment_id and original_message: try: fb_service = FacebookService(PAGE_ACCESS_TOKEN) fb_service.reply_to_comment(page_id, comment_id, original_message) logger.info(f"Successfully replied to comment ID: {comment_id} with bot response: {original_message}") except Exception as e: logger.error(f"Error replying to comment via FacebookService: {e}") return JsonResponse({"status": "comment_handled"}, status=200) def handle_share_event(page_id, data): """ Handles incoming share events: 1) Persiste el evento en la BD. 2) Publica un comentario en la share vía FacebookService. """ share_id = data.get("share_id") post_id = data.get("post_id") original_message = data.get("message") share_link = data.get("link") logger.info(f"Post {post_id} was shared. Share ID: {share_id}, Link: {share_link}") # 1) Registrar en la base de datos try: page = FacebookPageAssistant.objects.get(page_id=page_id) et = EventType.objects.get(code="share") FacebookEvent.objects.create( page=page, event_type=et, object_id=share_id, message=original_message ) except Exception as e: logger.error(f"Error logging FB share event: {e}") # 2) Comentar en la publicación compartida via API de Facebook try: fb_service = FacebookService(PAGE_ACCESS_TOKEN) fb_service.post_comment_on_share(page_id, post_id, original_message) except Exception as e: logger.error(f"Error posting comment on share via FacebookService: {e}") return JsonResponse({"status": "share_logged"}, status=200) def handle_message_event(page_id: str, sender_psid: str, message: dict): """ Handles incoming Messenger messages: 1) Log event to DB (like comments/shares) 2) Generate AI reply with your configured OpenAI assistant for this page 3) Send the reply via the Send API (using the page's access token) """ try: # 0) ignore echoes to prevent loops if not message or message.get("is_echo"): return JsonResponse({"status": "ignored"}, status=200) text = (message.get("text") or "").strip() mid = message.get("mid") or "" # 1) Persist event to DB (EventType 'message'; create if missing) try: page = FacebookPageAssistant.objects.get(page_id=page_id) et, _ = EventType.objects.get_or_create(code="message", defaults={"label": "Message"}) FacebookEvent.objects.create( page=page, event_type=et, sender_id=sender_psid, object_id=mid, message=text ) except Exception as e: logger.error(f"Error logging Messenger event: {e}") # 2) Build prompt and get AI reply from the page's configured assistant try: page_assistant = FacebookPageAssistant.objects.get(page_id=page_id).assistant prompt = text if text else "Say hello and ask how you can help." openai_service = OpenAIService(name=page_assistant.name) bot_reply = openai_service.handle_message(prompt) except Exception as e: logger.exception(f"AI reply failed; falling back. Reason: {e}") bot_reply = "Gracias por tu mensaje 🙌. ¿En qué puedo ayudarte?" # 3) Send the reply via Send API try: fb_service = FacebookService(PAGE_ACCESS_TOKEN) # reuse your token flow page_token = fb_service._get_page_access_token(page_id) or PAGE_ACCESS_TOKEN url = "https://graph.facebook.com/v22.0/me/messages" payload = { "recipient": {"id": sender_psid}, "messaging_type": "RESPONSE", "message": {"text": bot_reply}, } resp = requests.post(url, params={"access_token": page_token}, json=payload, timeout=5) resp.raise_for_status() logger.info(f"Sent Messenger reply to psid={sender_psid}") return JsonResponse({"status": "message_replied"}, status=200) except requests.RequestException as e: logger.exception(f"Send API failed: {e}") return JsonResponse({"status": "send_failed"}, status=200) except Exception as e: logger.exception(f"handle_message_event crashed: {e}") return JsonResponse({"status": "error", "detail": str(e)}, status=200)