Widgets em mensagens — blocos interativos de HTML, CSS e JavaScript diretamente nas conversas — chegaram às versões beta do Telegram para Android e iOS. Em 25 de outubro, eles surgiram no Android 13.2.0 (7254) e iOS 13.2 (35726), e no Android, um widget feito por conta própria já executa JavaScript. A build do Android 13.2.0 (7260) de 27 de outubro mostra como isso funciona: sem um motor de navegador, usando seu próprio interpretador com uma cota de CPU, e com um árbitro separado que decide se o toque foi genuíno. O bot, para o qual o widget enviou uma requisição, descobre o id de quem tocou. No Telegram Desktop e na API pública, os widgets ainda não estão disponíveis.
A mecânica das requisições ao bot na versão beta para macOS foi analisada em um artigo de 27 de outubro; aqui, apresentamos o que a build para Android adiciona.
Onde os widgets estão disponíveis
| Cliente | Build | O que é visível |
|---|---|---|
| macOS, beta | 13.1.0 | sandbox, requisições ao bot, páginas de teste — desde meados de outubro |
| Android, beta | 13.2.0 (7254, 7260) | esquema, sandbox, textos da interface; widgets funcionando |
| iOS, beta | 13.2 (35726) | widgets em mensagens e ferramentas para sua verificação |
| Telegram Desktop | 7.3.3 | não: nem no código, nem no esquema da layer 232 |
| Bot API | 10.3 | não |
A versão beta do Android é distribuída pelo canal oficial e por link direto do site do Telegram. O protocolo do cliente nela é a layer 233, uma versão mais recente que a pública.
Como o widget está em uma mensagem
O widget é um novo tipo de mídia, messageMediaWidget. Além do próprio código (payload) e das dimensões, ele contém dois conjuntos de dados: chat_data — dados desta mensagem, e public_data com um hash — dados gerais do widget que o bot pode alterar após o envio (messages.editMessageWidgetData, updateMessageWidgetData). Os sinalizadores can_query e background_query indicam se é possível escrever para o bot a partir do widget com ou sem um toque, e is_copy marca uma cópia encaminhada. O widget também pode vir como uma resposta inline do bot — botInlineMessageWidget.
As permissões são definidas pelo remetente. Em mensagens de erro da parte nativa do cliente, são mencionados os sinalizadores de servidor allow_queries e fwd_allow_queries: sem o primeiro, o widget não escreve para o bot de forma alguma; sem o segundo, sua cópia encaminhada permanece em silêncio. Uma requisição em segundo plano exige também background_query e só é enviada enquanto o widget está na tela.
O que o bot recebe
Um toque se transforma em messages.getBotWidgetQueryAnswer com os campos de chat, mensagem e data — até 64 bytes. O bot recebe a atualização updateBotWidgetQuery e responde com o método messages.setBotWidgetQueryAnswer com uma única string result.
Na atualização para o bot, o campo user_id é obrigatório, sem sinalizador: o bot sempre sabe quem tocou. Junto, vêm chat_type, chat_instance — o mesmo identificador de chat anonimizado que as botões inline comuns — o número da mensagem e widget_id. Para cópias encaminhadas e mensagens inline, existem atualizações próprias — updateBotWidgetCopyQuery e updateInlineBotWidgetQuery.
Isso é semelhante ao toque de um botão inline com callback, mas o botão é desenhado pelo script, e os dados são coletados por ele.
Como o código do widget é executado
No Android, não há WebView nem Chromium sob o widget. O código é executado por uma biblioteca nativa twidget dentro da biblioteca principal do cliente — o mesmo nome é usado pelos tipos Twidget* na versão beta para macOS e pelo repositório privado conectado aos seus códigos-fonte. Os scripts da sandbox estão no cliente duas vezes: como código-fonte e como bytecode .qbc, que é executado por um interpretador JavaScript embutido. A imagem é desenhada por seu próprio renderer diretamente na janela do Android — não há layout de navegador, mas sim sua análise: um pacote validator separado verifica HTML e CSS.
As restrições estão escritas no código, e não nas regras para desenvolvedores:
- CPU — o widget tem uma cota de tempo (
cpuQuotaMs), e excedê-la resulta no erro «CPU limit exceeded»; - timers — o número de simultâneos é limitado, o motor rejeita os extras;
- rede —
fetch,XMLHttpRequest,WebSocketenavigator.sendBeaconsão desativados,navigator.onLineé sempre falso,userAgentéTelegramWidget/1.0; - armazenamento — cada widget começa com um armazenamento vazio;
- saídas externas —
openLinkaceita apenas endereços https de até 256 caracteres e pergunta: «This widget wants to open:»,copyText— até 256 caracteres; - ponte para o cliente — após a inicialização, as funções de serviço
__host,__hostOpse as adjacentes são removidas do objeto global, e o código do widget não consegue acessá-las.
O cliente compara os arquivos da sandbox com as somas de verificação de manifest.txt; uma divergência é um erro separado «Bundle checksum mismatch».
Como o cliente distingue um toque de uma imitação
Uma requisição ao bot sem permissão de segundo plano é enviada apenas a partir do manipulador de toque — «uma chamada por toque em um widget visível», como indicado na mensagem de erro. Quem decide se houve um toque não é o script, mas um árbitro de toques nativo: as funções arbiterDown, arbiterMove, arbiterUp e arbiterHoldDeadline recebem as coordenadas do dedo e o tempo de retenção. Por intenção, um clique sintético de JavaScript, um timer ou um arrastar não enviarão uma requisição.
Na versão beta, também existem ferramentas para verificar esse limite: a tela de conformidade (WidgetConformanceActivity) e a execução de um conjunto de ataques (attackScan, WidgetAttacks). O conjunto de páginas de teste de ataque para macOS — 28 páginas que tentam enviar uma mensagem sem um toque ou redirecionar para um link — está no código aberto do cliente.
O que o usuário vê
Os textos da interface já estão no dicionário de strings em inglês do cliente: «Loading widget…», «Widget failed to load», «Widget stopped», «Preview of the widget» e o aviso «This widget can send data to its bot's server when you tap it.»
Não há um interruptor separado nas configurações da versão beta para desativar os widgets — testadores chamam a atenção para isso. Nem todos podem enviar widgets ainda, e a Bot API não possui métodos para eles.




