وصلت الودجات في الرسائل — وهي كتل تفاعلية من HTML و CSS و JavaScript تظهر مباشرة في المحادثات — إلى إصدارات بيتا من تيليجرام لأندرويد و iOS. في 25 أكتوبر، ظهرت في إصداري أندرويد 13.2.0 (7254) و iOS 13.2 (35726)، وفي أندرويد، أصبح الودجت المصمم ذاتيًا ينفذ JavaScript بالفعل. يُظهر إصدار أندرويد 13.2.0 (7260) بتاريخ 27 أكتوبر كيفية عمل ذلك: بدون محرك متصفح، بل باستخدام مفسّر خاص به مع حصة معالج (CPU quota)، ومع حكم منفصل يقرر ما إذا كانت النقرة حقيقية. يتعرف البوت الذي أرسل إليه الودجت طلبًا على معرّف المستخدم الذي قام بالنقر. لا تزال الودجات غير متوفرة في Telegram Desktop ولا في Bot API العام.

تمت مناقشة آلية طلبات البوت عبر إصدار بيتا لنظام macOS في مقال بتاريخ 27 أكتوبر؛ وهنا ما يضيفه إصدار أندرويد.

أين تتوفر الودجات

العميلالإصدارما هو مرئي
macOS، بيتا13.1.0بيئة الاختبار (sandbox)، طلبات البوت، صفحات الاختبار — منذ منتصف أكتوبر
أندرويد، بيتا13.2.0 (7254, 7260)المخطط، بيئة الاختبار (sandbox)، نصوص الواجهة؛ الودجات تعمل
iOS، بيتا13.2 (35726)الودجات في الرسائل وأدوات التحقق منها
Telegram Desktop7.3.3لا يوجد: لا في الكود ولا في مخطط الطبقة 232
Bot API10.3لا يوجد

يتم توزيع إصدار بيتا لأندرويد عبر القناة الرسمية ورابط مباشر من موقع Telegram. بروتوكول العميل فيه هو الطبقة 233، وهو أحدث بواحدة من الطبقة العامة.

كيف تظهر الودجات في الرسائل

الودجت هو نوع جديد من الوسائط، messageMediaWidget. بالإضافة إلى الكود نفسه (payload) والأبعاد، يحتوي على مجموعتين من البيانات: chat_data — بيانات هذه الرسالة، و public_data مع التجزئة (hash) — بيانات الودجت العامة التي يمكن للبوت تغييرها بعد الإرسال (messages.editMessageWidgetData, updateMessageWidgetData). تشير العلامتان can_query و background_query إلى ما إذا كان يمكن للودجت الكتابة إلى البوت عند النقر وبدونه، بينما تشير is_copy إلى النسخة المعاد توجيهها. يمكن أن يأتي الودجت أيضًا كاستجابة مضمنة (inline result) من البوت — botInlineMessageWidget.

يحدد المرسل الأذونات. في رسائل الخطأ من الجزء الأصلي للعميل، تم ذكر علامات الخادم allow_queries و fwd_allow_queries: بدون الأولى، لا يكتب الودجت إلى البوت على الإطلاق، وبدون الثانية، تظل نسخته المعاد توجيهها صامتة. يتطلب الطلب في الخلفية أيضًا background_query ولا يتم إرساله إلا عندما يكون الودجت على الشاشة.

ما الذي يتلقاه البوت

تتحول النقرة إلى messages.getBotWidgetQueryAnswer مع حقول المحادثة والرسالة و data — حتى 64 بايت. يتلقى البوت تحديث updateBotWidgetQuery ويستجيب بطريقة messages.setBotWidgetQueryAnswer بسلسلة نصية واحدة result.

في التحديث الخاص بالبوت، حقل user_id إلزامي، بدون علامة: يعرف البوت دائمًا من قام بالنقر. يأتي معه chat_type، chat_instance — وهو نفس المعرّف المجهول للمحادثة مثل الأزرار المضمنة العادية — ورقم الرسالة و widget_id. بالنسبة للنسخ المعاد توجيهها والرسائل المضمنة، توجد تحديثات خاصة بها — updateBotWidgetCopyQuery و updateInlineBotWidgetQuery.

هذا يشبه النقر على زر مضمن مع رد اتصال (callback)، لكن السكريبت هو الذي يرسم الزر، وهو نفسه الذي يجمع البيانات.

كيف يتم تنفيذ كود الودجت

في أندرويد، لا يوجد WebView ولا Chromium تحت الودجت. يتم تنفيذ الكود بواسطة مكتبة twidget الأصلية داخل المكتبة الرئيسية للعميل — يحمل هذا الاسم نفسه أنواع Twidget* في إصدار بيتا لنظام macOS والمستودع المغلق المتصل بمصادرها. توجد سكريبتات بيئة الاختبار (sandbox) في العميل مرتين: ككود مصدر وككود بايت .qbc، والذي يقوم بتشغيله مفسّر JavaScript المدمج. يتم رسم الصورة بواسطة محرك عرض خاص مباشرة في نافذة أندرويد — لا يوجد تخطيط متصفح، بل يوجد تحليل له: تقوم حزمة validator منفصلة بالتحقق من HTML و CSS.

القيود مكتوبة في الكود، وليس في قواعد المطورين:

  • المعالج — للودجت حصة زمنية (cpuQuotaMs)، ويتسبب تجاوزها في ظهور خطأ «CPU limit exceeded».
  • المؤقتات — عدد المؤقتات المتزامنة محدود، ويرفض المحرك أي مؤقتات إضافية.
  • الشبكة — تم حظر fetch و XMLHttpRequest و WebSocket و navigator.sendBeacon، و navigator.onLine دائمًا خطأ، و userAgent هو TelegramWidget/1.0.
  • التخزين — يبدأ كل ودجت بتخزين فارغ.
  • المخارج الخارجية — openLink يقبل فقط عنوان https يصل طوله إلى 256 حرفًا ويسأل: «This widget wants to open:»، و copyText — حتى 256 حرفًا.
  • الجسر إلى العميل — بعد التشغيل، يتم حذف الوظائف الخدمية __host و __hostOps والوظائف المجاورة من الكائن العام، ولا يمكن لكود الودجت الوصول إليها.

يقوم العميل بمقارنة ملفات بيئة الاختبار (sandbox) مع المجاميع الاختبارية (checksums) من manifest.txt، ويؤدي الاختلاف إلى ظهور خطأ منفصل «Bundle checksum mismatch».

كيف يميز العميل النقرة عن المحاكاة

لا يتم إرسال طلب إلى البوت بدون إذن في الخلفية إلا من معالج النقرة — «استدعاء واحد لكل نقرة على ودجت مرئي»، كما هو مذكور في رسالة الخطأ. لا يقرر السكريبت ما إذا كانت النقرة قد حدثت، بل يقررها حكم النقرات الأصلي: تتلقى الوظائف arbiterDown و arbiterMove و arbiterUp و arbiterHoldDeadline إحداثيات الإصبع ووقت الضغط. حسب التصميم، لن ترسل النقرة الاصطناعية من JavaScript أو المؤقت أو السحب والإفلات طلبًا.

يحتوي إصدار بيتا أيضًا على أدوات للتحقق من هذا الحد: شاشة المطابقة (WidgetConformanceActivity) وتشغيل مجموعة من الهجمات (attackScan, WidgetAttacks). توجد مجموعة صفحات اختبار الهجمات لنظام macOS — 28 صفحة تحاول إرسال رسالة بدون نقرة أو توجيه إلى رابط — في الكود المفتوح للعميل.

ما الذي يراه المستخدم

توجد نصوص الواجهة بالفعل في قاموس العميل الإنجليزي: «Loading widget…»، «Widget failed to load»، «Widget stopped»، «Preview of the widget» والتحذير «This widget can send data to its bot's server when you tap it.».

لا يوجد مفتاح تبديل منفصل في إعدادات إصدار بيتا لتعطيل الودجات — وهذا ما يلفت انتباه المختبرين إليه. لا يمكن للجميع إرسال الودجات بعد، ولا توجد طرق لها في Bot API.