Pular para o conteúdo

Bots de Telegram

Comandos, botões, conversa com estado e webhook — e testes que rodam sem token e sem rede.

`Arcane.Telegram` é o módulo de bots. A Bot API do Telegram é HTTP com JSON: falar com ela do zero é possível e chato — noventa métodos, um formato de erro próprio, um limite de taxa que responde no corpo e não no status, upload multipart, e uma sintaxe de formatação que quebra a mensagem inteira se um caractere escapar.

dataforge
adopt Arcane.Telegram as Tg

app := Tg.app(Tg.segredo_do_ambiente())

mark @app.comando("start")
action comecar(ctx):
    ctx.responder($"Ola, {ctx.nome()}!")

app.rodar()

Isso é o bot inteiro. ctx traz quem falou, o que disse e como responder; o rodar faz long polling até alguém parar.

Do zero ao bot no ar#

bash
dataforge telegram new meubot     # cria o projeto
cd meubot
export TELEGRAM_TOKEN="123456:AAH..."   # o token vem do @BotFather
dataforge telegram doctor         # confere o que falta
dataforge telegram run            # sobe em long polling

O módulo também nunca deixa o token aparecer numa mensagem de erro. Ele está na URL de toda chamada, e a URL entra em todo traceback — um token num log de CI é um bot sequestrado.

O que chega em `ctx`#

O que é
ctx.textoo texto da mensagem, ou a legenda da mídia
ctx.argso que veio depois do comando, já separado
ctx.dadoso dados do botão que foi clicado
ctx.chato id do chat
ctx.nome() · ctx.apelido()quem falou
ctx.e_privado() · ctx.e_grupo() · ctx.e_admin()onde, e com que poder
ctx.estadoo vault deste chat, que sobrevive entre mensagens
ctx.updateo update cru, para o campo que nenhuma conveniência cobre

E para responder: ctx.responder, ctx.citar (que responde citando, o que dá contexto em grupo), ctx.responder_foto, ctx.responder_documento, ctx.editar, ctx.apagar, ctx.digitando e ctx.avisar.

O despacho para no primeiro que casa#

O update é casado uma vez, na ordem do registro. A alternativa — entregar a todos — parece mais flexível e produz o bug mais confuso que um bot tem: duas respostas para uma mensagem, e ninguém sabe de onde veio a segunda.

dataforge
mark @app.comando("start")
action comecar(ctx):
    ctx.responder("Ola!")

mark @app.texto("\\b(oi|ola)\\b")
action cumprimento(ctx):
    ctx.responder("Oi!")

mark @app.qualquer()
action resto(ctx):
    ctx.responder("Nao entendi.")

Onde continuar#