State
import asyncio
from waha.events import OnMessageEvent
from waha.pipeline import State, StateManager
# Dicionário onde a chave é o ID do chat e os valores são os alimentos adicionados
carrinho_usuarios: dict[str, list[str]] = {}
async def adicionar_carne(chat_id: str):
"""Adiciona carne ao carrinho do usuário e retorna ao menu inicial."""
carrinho_usuarios[chat_id] = carrinho_usuarios.get(chat_id, [])
carrinho_usuarios[chat_id].append("carne")
return InitialState()
async def adicionar_arroz(chat_id: str):
"""Adiciona arroz ao carrinho do usuário e retorna ao menu inicial."""
carrinho_usuarios[chat_id] = carrinho_usuarios.get(chat_id, [])
carrinho_usuarios[chat_id].append("arroz")
return InitialState()
async def finalizar_compra(chat_id: str):
"""Finaliza a compra, limpando o carrinho do usuário e retornando uma mensagem de confirmação."""
carrinho_usuarios.pop(chat_id, None) # Remove os itens do carrinho
return CompraFinalizadaState()
class ComidaState(State):
"""Estado onde o usuário pode escolher alimentos para adicionar ao carrinho."""
message = """Opções:
1. 🍖 Carne
2. 🌾 Arroz
3. 🗂️ Voltar ao menu
"""
message_invalid_option = None # Nenhuma mensagem personalizada para opções inválidas
handle_options = {
"1": adicionar_carne,
"2": adicionar_arroz,
"3": lambda _: InitialState(), # Retorna ao menu inicial
}
class InitialState(State):
"""Estado inicial onde o usuário pode acessar o menu principal."""
message = """Mercado do seu Zé
1. 🥘 Comidas
2. 🛒 Ver carrinho
"""
handle_options = {
"1": ComidaState(), # Vai para o menu de comidas
"2": lambda chat_id: VerCarrinhoState(chat_id), # Vai para a tela de visualização do carrinho
}
class VerCarrinhoState(State):
"""Estado onde o usuário pode visualizar os itens no carrinho e finalizar a compra."""
def __init__(self, chat_id: str):
self.chat_id = chat_id
carrinho = carrinho_usuarios.get(chat_id, [])
self.message = (
"\U0001F6D2 Seu carrinho:\n" + "\n".join(f"- {item}" for item in carrinho)
if carrinho
else "\U0001F6D2 Seu carrinho está vazio.\n"
)
self.message += "\n1. ✅ Finalizar compra\n0. 🔙 Voltar ao menu"
handle_options = {
"1": finalizar_compra, # Finaliza a compra
"0": lambda chat_id: InitialState(), # Retorna ao menu inicial
}
class CompraFinalizadaState(State):
"""Estado exibido quando o usuário finaliza a compra."""
message = "✅ Compra finalizada! Obrigado por comprar no Mercado do seu Zé.\n\n0. 🔙 Voltar ao menu"
handle_options = {
"0": InitialState(), # Volta ao menu inicial
}
# Inicializa o evento para capturar mensagens dos usuários
on_message = OnMessageEvent()
# Adiciona um gerenciador de estados ao evento
on_message.add_listeners(
StateManager(
initial_state=InitialState(),
wait_response=120, # Tempo de espera de 120 segundos antes de resetar para o estado inicial
)
)
async def main():
"""Inicia o sistema de mensagens e mantém a aplicação rodando."""
await on_message.start()
while True:
await asyncio.sleep(1)
# Executa o loop principal da aplicação
asyncio.run(main())
Explicação do Funcionamento dos Estados (State Machine)
O código implementa uma máquina de estados para um sistema de mensagens automatizado, permitindo que os usuários naveguem entre diferentes menus e realizem ações. Essa abordagem garante um fluxo estruturado e previsível dentro da aplicação.
Conceito de Máquina de Estados
Uma máquina de estados é um modelo computacional que gerencia o comportamento de um sistema através de estados e transições. Cada estado define um conjunto específico de opções disponíveis para o usuário e as transições ocorrem conforme as escolhas feitas.
Estados Definidos no Código
InitialState
- Estado inicial onde o usuário pode escolher entre acessar o menu de comidas ou visualizar o carrinho.
- Opções disponíveis:
1→ Navega paraComidaState2→ Navega paraVerCarrinhoState
ComidaState
- Estado onde o usuário pode selecionar itens para adicionar ao carrinho.
- Opções disponíveis:
1→ Adiciona carne ao carrinho e retorna ao estado inicial.2→ Adiciona arroz ao carrinho e retorna ao estado inicial.3→ Retorna aoInitialState.
VerCarrinhoState
- Exibe os itens atualmente no carrinho do usuário.
- Opções disponíveis:
1→ Finaliza a compra e esvazia o carrinho.0→ Retorna aoInitialState.
CompraFinalizadaState
- Estado exibido após a finalização da compra.
- Opções disponíveis:
0→ Retorna aoInitialState.
Fluxo de Navegação
- O usuário inicia no
InitialState. - Escolhendo
1, ele vai paraComidaState, onde pode adicionar itens ao carrinho. - Escolhendo
2, ele vai paraVerCarrinhoState, onde pode visualizar o carrinho e finalizar a compra. - Se optar por finalizar a compra (
1dentro do carrinho), o estado muda paraCompraFinalizadaState, e o carrinho é esvaziado. - Em qualquer momento, o usuário pode retornar ao menu inicial escolhendo a opção correspondente.
Como o Gerenciamento de Estados Funciona
O gerenciamento dos estados é feito através da classe StateManager, que controla as transições e define regras para a navegação do usuário. Além disso, há um tempo limite de resposta para evitar que usuários fiquem presos em um estado por muito tempo.
Principais características do StateManager:
- Define o estado inicial (InitialState).
- Mantém o estado atual do usuário até que uma opção seja escolhida.
- Se o usuário não interagir dentro do tempo limite (120 segundos no código), o estado é resetado para InitialState.
- Realiza a transição para o próximo estado com base na escolha do usuário.
Benefícios do Uso de Máquina de Estados
- Organização: O fluxo é bem definido, tornando o código mais legível e modular.
- Facilidade de manutenção: Caso seja necessário adicionar novas funcionalidades, basta criar novos estados e definir as transições.
- Controle: Evita que o usuário faça escolhas inválidas ou quebre o fluxo da aplicação.
- Escalabilidade: Pode ser expandido para incluir novos menus, opções e funcionalidades sem comprometer a estrutura existente.