Consultme/app/models/webhook_model.py
2025-06-21 16:19:21 +00:00

75 lines
3.0 KiB
Python

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]