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.

The post on Telegram — @gramnews
Como serão as mensagens-widget

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
viewerID, nome, sobrenome, username e status Premium de quem está visualizando
chatTypetipo de chat: privado, grupo, supergrupo ou canal
chatDatadados vinculados à mensagem neste chat, até 1.024 bytes
publicDatadados da própria mensagem, até 1.024 bytes
watchPublicData()assinatura para mudanças em publicData
isForward e isPreviewse é 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
setResizeAnchorborda 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, WebSocket e 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 (openLink aceita 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, inputBotInlineMessageWidget e inputBotInlineMessageWidgetId — o bot, aparentemente, entrega o widget como um resultado inline, por completo ou por ID;
  • inputMediaWidgetId — widget como anexo de mensagem por ID;
  • updateBotWidgetQuery, updateInlineBotWidgetQuery e updateBotWidgetCopyQuery — 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;
  • updateMessageWidgetData e widgetPublicData — o servidor envia novos dados de um widget já enviado, e na sandbox há um evento publicDataChanged para isso;
  • os erros do servidor WIDGET_QUERY_NOT_ALLOWED e WIDGET_RESPONSE_TIMEOUT parecem um par para os erros do script NOT_ALLOWED e TIMEOUT.

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.