Um bot que cresce
O bot como casca: a regra num módulo, o estado fora da memória, e o teste que não precisa do Telegram.
O primeiro bot é um arquivo só, e está certo assim. O segundo mês traz um banco, três tipos de usuário e um relatório — e aí o arquivo único mistura o que o bot faz com como o Telegram recebe, e nenhum dos dois se testa sozinho.
| Camada | Sabe de | Não sabe de |
|---|---|---|
o núcleo (pedidos.df) | a regra: o que é um pedido válido, o total, o estado | Telegram, ctx, teclado |
o bot (bot.df) | comandos, teclados, a conversa | como se calcula o total |
| o estado | onde a conversa mora entre mensagens | o que ela significa |
dataforge
adopt Arcane.Telegram as Tg
app := Tg.app("123456:TESTE-exemplo")
// o núcleo: nada aqui sabe que existe um Telegram
action total(itens):
yield itens >> distill acc, i: acc + i["preco"] * i["qtd"] 0
// a casca: traduz mensagem em chamada, e resultado em texto
mark @app.comando("total")
action comando_total(ctx):
carrinho := ctx.lembrar("carrinho", [])
ctx.responder($"Total: R$ {total(carrinho)}")
mark @app.comando("pegar")
action pegar(ctx):
carrinho := ctx.lembrar("carrinho", [])
carrinho.append({"preco": 10, "qtd": 2})
ctx.guardar("carrinho", carrinho)
ctx.responder("Adicionado.")
assert total([{"preco": 10, "qtd": 3}]) is 30 // o núcleo, sem bot
t := Tg.testar(app)
t.comando("pegar")
t.comando("total")
assert t.ultima() is "Total: R$ 20"O estado fora da memória#
Tg.estado_em_memoria() some quando o processo reinicia — e o bot reinicia a cada deploy. Para produção, Tg.estado_em_arquivo(caminho), e o carrinho de quem estava no meio de uma compra sobrevive à atualização.
O projeto completo nesse formato está em Bot de atendimento.