import logging from typing import Any from anydi import singleton from twilio.twiml.messaging_response import MessagingResponse from app.adapters.ows_text_campaigns import OwsTextCampaignsClient from app.exceptions import RequestValidationError from app.models import Event from app.validator import RequestValidator logger = logging.getLogger(__name__) @singleton class TwilioWebhooksInboundHandler: def __init__( self, request_validator: RequestValidator, text_campaigns_client: OwsTextCampaignsClient, ) -> None: self.request_validator = request_validator self.text_campaigns_client = text_campaigns_client def handle(self, event_dict: dict[str, Any]) -> dict[str, Any]: logger.info("Event received", extra={"event": event_dict}) response = MessagingResponse() try: event = Event.model_validate(event_dict) self.request_validator.validate( event.request_full_uri, event.body, event.headers.request_signature, ) self.text_campaigns_client.forward_message(event) except RequestValidationError: logger.error("Request validation error", extra={"event": event_dict}) return {"statusCode": 403, "body": "Forbidden"} except Exception: logger.exception("Internal server error", extra={"event": event_dict}) return {"statusCode": 500, "body": "Internal Server Error"} return { "statusCode": 200, "headers": {"Content-Type": "application/xml"}, "body": response.to_xml(), }