Conversas e estado
A máquina de estados por chat, a validação passo a passo, e onde o estado mora.
Guardar "em que passo este chat está" num vault solto é o que todo bot faz errado: funciona até o segundo usuário, os dois se misturam, e um bot reiniciado esquece todo mundo.
Uma conversa#
dataforge
action e_email(texto):
yield "@" in texto and "." in texto
cadastro := app.conversa("cadastro", [
{"pergunta": "Qual e o seu nome?", "guarda": "nome"},
{"pergunta": "E o seu e-mail?", "guarda": "email",
"valida": e_email, "erro": "Isso nao parece um e-mail."}
])
mark @cadastro.ao_terminar()
action terminou(ctx, respostas):
salvar(respostas["nome"], respostas["email"])
ctx.responder($"Pronto, {respostas['nome']}!")
mark @app.comando("cadastro")
action abrir(ctx):
cadastro.comecar(ctx)Cada passo pergunta, espera, valida e guarda. O estado fica no chat, então duas pessoas conversando ao mesmo tempo não se atrapalham.
O estado deste chat#
dataforge
mark @app.comando("lembrar")
action lembrar(ctx):
ctx.guardar("ultima_busca", ctx.args[0] ?? "")
ctx.responder($"Anotei: {ctx.lembrar('ultima_busca', 'nada')}")| Onde | Sobrevive a | Quando usar |
|---|---|---|
Tg.estado_em_memoria() | nada — some ao reiniciar | desenvolvimento, e bots sem memória |
Tg.estado_em_arquivo(pasta) | o reinício do processo | um bot só, num servidor só |
O nome do arquivo sai do id do chat, e ele é conferido: um id que chegasse com ../ escreveria fora da pasta. O id vem do Telegram e é sempre numérico — mas "sempre" é uma suposição sobre um sistema de terceiros, e é barato não depender dela.
dataforge
app := Tg.app(Tg.segredo_do_ambiente(),
estado := Tg.estado_em_arquivo(".telegram/estado"))