Widgets nas mensagens do Telegram receberam um canal de retorno para o bot. Em builds beta do Telegram para macOS 13.1.0 de 26 de outubro, o script do widget ganhou uma chamada request(): ao tocar, ele envia até 64 bytes para o bot e espera uma resposta de até 1.024 bytes. Sem um toque, a requisição é enviada apenas no chat privado com o bot, se o bot permitiu tais requisições, enquanto o widget estiver na tela e não mais de uma vez a cada cinco segundos. No mesmo local, o widget agora sabe quem o abriu — ID, nome, username e status Premium — e em que tipo de chat ele está. Os próprios widgets foram notados nas betas do iOS, macOS e Android, mas essa mecânica é visível apenas na build para macOS; na esquema de API pública e na Bot API, não há widgets.
O que mudou entre 25 e 26 de outubro
A beta do macOS é distribuída através do feed de atualizações, cada build é um zip com o aplicativo. Para comparação, foram usadas as versões 13.1.0.283381 de 25 de outubro e 13.1.0.283391 de 26 de outubro.
O script do widget se comunica com o cliente através do objeto global TelegramWidget. Seu código está no pacote WidgetSandbox dentro do aplicativo, no arquivo sandbox-bundle.js. Na versão 283381, o objeto tinha poucas funcionalidades: fornecer o tema, assinar eventos, abrir um link e ativar a vibração. Na versão 283391, foram adicionados:
| O quê | O que faz |
|---|---|
request(data) | envia uma string de 1 a 64 bytes para o bot e retorna sua resposta |
viewer | ID, nome, sobrenome, username e status Premium de quem está visualizando |
chatType | tipo de chat: privado, grupo, supergrupo ou canal |
chatData | dados vinculados à mensagem neste chat, até 1.024 bytes |
publicData | dados da própria mensagem, até 1.024 bytes |
watchPublicData() | assinatura para mudanças em publicData |
isForward e isPreview | se é uma cópia encaminhada e se é uma prévia de um resultado inline ainda não enviado |
copyText(text) | coloca até 256 caracteres na área de transferência |
setResizeAnchor | borda de onde o widget cresce ao mudar de altura — superior ou inferior |
Aos três eventos anteriores — mudança de tema, ativação e desativação — foram adicionados chatDataChanged e publicDataChanged.
Simultaneamente, tudo o que era demonstrativo foi removido do pacote HTMLBubbles: treze chats de demonstração, mencionados no artigo de 13 de outubro, a pasta ported com cartões portados, o jogo multiplayer voxel-clash e a pasta widget-sandbox com exemplos. No pacote, restou apenas a biblioteca three.js.
Quando o widget pode escrever para o bot
As regras estão escritas na própria sandbox, no texto dos erros que o script recebe, e nas strings do aplicativo:
- a requisição é enviada a partir do manipulador de toque no widget, uma chamada por toque;
- sem toque — apenas no chat privado com o bot, somente se a mensagem permitir requisições em segundo plano (flag
background_query), apenas enquanto o widget estiver na tela e não mais de uma vez a cada cinco segundos; - enquanto a requisição anterior aguarda resposta, uma nova não é enviada;
- a prévia de um resultado inline, que ainda não foi enviada para o chat, não consulta o bot;
- as requisições são desativadas se o bot não as permitiu para esta mensagem — uma cópia encaminhada tem uma permissão separada;
- a resposta do bot é apenas texto e não mais longa que 1.024 bytes, caso contrário o script recebe o erro
INVALID_ANSWER; se não respondeu a tempo —TIMEOUT.
Em uma cópia encaminhada, chatData está vazio, mas publicData permanece.
Nas strings do aplicativo, ao lado do código do bubble HTML, apareceu a frase "A tap may send data to the bot" — "um toque pode enviar dados ao bot". Onde exatamente o cliente a exibe, não é visível na build.
O que fazer
- Os widgets ainda vivem apenas nas betas, e não podem ser enviados por bots: na Bot API não há um método que envie um widget.
- Ao tocar em um widget, considere que cada toque pode se tornar uma requisição ao bot. O script vê seu ID, nome, username e Premium, e o ID ocupa até 16 dígitos — ele cabe em uma requisição de 64 bytes.
- Por si só, sem um toque, o widget escreve para o bot apenas no chat privado com este bot. Para grupos e canais, a sandbox não prevê requisições em segundo plano.
- O widget não tem rede:
fetch,XMLHttpRequest,WebSockete workers na sandbox são substituídos por stubs que retornam um erro. Os dados saem através do bot ou através de um link que o widget abre (openLinkaceita apenas https e não mais de 256 caracteres) — assim era também na build de 25 de outubro.
Como o servidor entregará o widget
No binário 283391, apareceram nomes de tipos de esquema que não estavam presentes no 283381. No esquema público da camada 232 — nem no Telegram Desktop, nem no Telegram Web A — eles não existem, nem há widgets na documentação da Bot API. A estrutura é lida pelos nomes, portanto, a seguir, uma interpretação, e não uma descrição:
botInlineMessageWidget,inputBotInlineMessageWidgeteinputBotInlineMessageWidgetId— o bot, aparentemente, entrega o widget como um resultado inline, por completo ou por ID;inputMediaWidgetId— widget como anexo de mensagem por ID;updateBotWidgetQuery,updateInlineBotWidgetQueryeupdateBotWidgetCopyQuery— requisições ao bot do widget em uma mensagem normal, em uma enviada via modo inline e, a julgar pelo nome, em uma cópia encaminhada; a resposta ébotWidgetQueryAnswer;updateMessageWidgetDataewidgetPublicData— o servidor envia novos dados de um widget já enviado, e na sandbox há um eventopublicDataChangedpara isso;- os erros do servidor
WIDGET_QUERY_NOT_ALLOWEDeWIDGET_RESPONSE_TIMEOUTparecem um par para os erros do scriptNOT_ALLOWEDeTIMEOUT.
As strings do cliente também mencionam as flags de permissão: allow_queries para a mensagem, fwd_allow_queries para suas cópias encaminhadas e background_query para requisições sem toque. O que exatamente o bot recebe junto com a requisição — o ID de quem tocou, como nos botões abaixo da mensagem, ou não — não é visível na build.
O que os laboratórios de benchmark verificam no código aberto
No repositório aberto do cliente, o motor de widgets está conectado como um submódulo twidget; no link do submódulo, o GitHub responde 404 — o repositório está fechado ou foi excluído. Ao lado, estão os laboratórios de benchmark, e na pasta tools/perflab/TwidgetLab/widgets/attack — 28 widgets que tentam agir sem um toque real. Dezesseis deles enviam dados ao bot: por temporizador a cada 50 ms, por clique sintético, por chamada atrasada após um clique, via rótulo de campo de formulário (label), por arrastar e soltar. Doze tentam abrir um link ou sair da página sem um toque — com um link sobre um botão, envio de formulário, atualização automática da página. A pasta apareceu no repositório com o commit de 23 de outubro, três dias antes da build com request().
Nesses laboratórios, o envio ainda é chamado de TelegramWidget.sendMessage. Na build 283391, não há tal chamada — há request(), e o script recebe a chamada fora de um toque como um erro com a razão no-activation.
O que mais havia nos exemplos removidos
Na pasta widget-sandbox da build 283381, havia dois conjuntos de 20 widgets — with-profile e without-profile. Os nomes dos arquivos são pedidos: «show me a mortgage calculator», «make a bar chart of the top 6 programming…», «create a pomodoro timer», «create a flashcard widget for 8 Spanish…». O objeto TelegramWidget é mencionado em 12 arquivos do primeiro conjunto e em nenhum do segundo. Parece que são widgets montados por um modelo com os mesmos pedidos, com e sem a descrição das capacidades da sandbox — esta é uma inferência pelo conteúdo, a própria build não afirma isso. A palavra profile também está no objeto TelegramWidget: a propriedade profile é igual a 1, e isProfileAtLeast() verifica o nível.
O restante na pasta são verificações de compatibilidade (Chart.js, D3, three.js, WebGL, formulários, arrastar e soltar, localStorage), cartões para vitrine por temas "compras", "trabalho", "vida", "viagens" e testes de estresse.
Onde mais há widgets
Widgets em mensagens como formato da próxima atualização 13.2 foram descritos em 25 de outubro. Como o widget se comunica com o bot, o que ele vê sobre o espectador e onde estão os limites das requisições, não foi mencionado nessa descrição.




