from typing import List, Optional, Union from pydantic import BaseModel, Field class TextMessage(BaseModel): body: str class ButtonMessage(BaseModel): # O WhatsApp envia 'id' e 'title' para as respostas de botões, # mas o Pydantic pode esperar 'payload' e 'text' se for para envio. # Para *recebimento*, precisamos mapear o que vem. # O payload que você recebeu mostra 'id' e 'title'. # Para a *resposta* de um botão: id: str # O ID do botão clicado (que você definiu no seu código) title: str # O texto do botão clicado # No seu handle_button_response, você espera 'payload'. # Isso indica que ButtonMessage foi usado para ENVIO antes. # Para *recebimento*, a Meta envia 'id' e 'title'. # A melhor prática é ter dois modelos, um para envio e um para recebimento, # ou usar aliases condicionais. # Pela sua mensagem de erro, o Pydantic (na validação do WebhookEvent) # esperava 'payload' e 'text' para o `button_reply`. # Vamos renomear e usar aliases para compatibilidade com o que a Meta envia E o que o seu handler espera. # O `id` do botão clicado é o `payload` que você espera no seu handler. # O `title` do botão clicado é o `text` que você espera. # Modelagem para RECEBIMENTO de resposta de botão: payload: str = Field(alias="id") # Mapeia 'id' do JSON recebido para 'payload' no Python text: str = Field(alias="title") # Mapeia 'title' do JSON recebido para 'text' no Python class ListReply(BaseModel): id: str title: str class InteractiveMessage(BaseModel): type: str # 'list_reply', 'button_reply', etc. list_reply: Optional[ListReply] = None button_reply: Optional[ButtonMessage] = None # Renomeado para button_reply para consistência class Message(BaseModel): # ESTA É A CLASSE 'Message' QUE ESTAVA FALTANDO! from_: str = Field(alias="from") # 'from' é palavra reservada em Python, então usamos alias id: str timestamp: str type: str # 'text', 'image', 'button', 'interactive', etc. text: Optional[TextMessage] = None button: Optional[ButtonMessage] = None # <-- AQUI! Garanta que está usando o ButtonMessage ajustado interactive: Optional[InteractiveMessage] = None # Adicione outros tipos de mensagem aqui se precisar processá-los (image, audio, video, etc.) class Status(BaseModel): id: str status: str # 'sent', 'delivered', 'read', 'failed' timestamp: str recipient_id: str # Adicione outros campos de status se necessário class ChangeValue(BaseModel): messaging_product: str metadata: dict # Pode conter phone_number_id, display_phone_number messages: Optional[List[Message]] = None statuses: Optional[List[Status]] = None # Para atualizações de status class Change(BaseModel): field: str # 'messages' ou 'statuses' value: ChangeValue class Entry(BaseModel): id: str changes: List[Change] class WebhookEvent(BaseModel): # Este é o seu modelo principal do evento object: str # 'whatsapp_business_account' entry: List[Entry]