تخطي إلى المحتوى
#منشور_فيتجارب برمجيةCase StudyTelegram APINext.jsSupabase

لوحة تحكم Telegram Bot بذاكرة متعلمة: حل قيود API وتطوير بنية آمنة

Rebex Tele من تكامل Telegram Bot API إلى الالتفاف على قيود استعراض المواضيع بذاكرة متعلمة، وجدولة الرسائل عبر pg_cron لضمان الموثوقية والأمان.

5 دقيقة قراءة

محتوى المقالة

عندما أدير عدة مجموعات على تلغرام — سواء لفريق عمل، أو مجتمع مطورين، أو طلاب دورة — تبرز التحديات التشغيلية بوضوح في كيفية إرسال رسالة واحدة منسقة إلى عدة مجموعات ومواضيع فرعية دون التنقل اليدوي المجهد بينها.

من هنا ولدت فكرة مشروع Rebex Tele: لوحة تحكم مركزية تربط Telegram Bot، وتتيح إدارة المجموعات والمواضيع، وإرسال رسائل فورية أو مجدولة بأمان.

يمكنك الاطلاع على التوصيف الكامل للمشروع ولقطات منه من هنا: Rebex Tele - لوحة تحكم Telegram Bot

لكن رحلة التطوير واجهت عقبات حقيقية؛ إذ يفرض Telegram Bot API قيوداً تقنية بارزة، بعضها غير موثّق بشكل واضح في المستندات الرسمية. وأستعرض هنا التحديات التي واجهتها وكيف بنيت حلولاً هندسية لتجاوزها.

القيد الأول: غياب الاستعراض التلقائي للمجموعات

أول صدمة واجهتها أثناء مرحلة التخطيط هي عدم وجود طريقة عبر Telegram Bot API لاستعراض قائمة المجموعات التي ينتمي إليها البوت، حيث لا تتوفر نقطة نهاية مثل getGroups أو listChats.

بالتالي، لا يستطيع البوت اكتشاف المجموعات من تلقاء نفسه، بل يتعرف فقط على المجموعات التي جرى تفاعل فيها مؤخراً.

الحل المقترح

اعتمدت حلاً هيبريدياً يبدأ بمدخلات المستخدم ويستكمل بالتأكيد التلقائي:

  • يقوم المستخدم بإدخال Chat ID يدوياً.
  • يتولى التطبيق التحقق من صحته فوراً عبر استدعاء دالة getChat وجلب بيانات القناة أو المجموعة قبل اعتماد حفظها في قاعدة البيانات.

القيد الثاني: غياب إمكانية استعراض مواضيع المنتدى (Forum Topics)

تمثلت المشكلة الثانية في دعم المجموعات الحديثة لتلغرام لنظام المواضيع لتنظيم النقاشات، بينما لا يوفر الـ API أي طريقة لاستعراض هذه المواضيع عبر وجود دالة مثل getForumTopics.

الحل: ذاكرة تخزين مؤقت متعلمة

لتجاوز ذلك، صممت نظام ذاكرة متعلمة يعمل على مستويين متكاملين:

  1. الالتقاط التلقائي أثناء الإرسال: عندما يُرسل المستخدم أي رسالة إلى موضوع معين، يلتقط التطبيق الزوج (Chat ID + Thread ID) ويخزنه تلقائياً في جدول telegram_topics.
  2. التحديث اليدوي عبر التنسيق الحي: أضفت ميزة تحديث المواضيع في صفحة الإدارة؛ حيث يعتمد التطبيق على تقنية Long-polling عبر getUpdates لالتقاط الأحداث واستخراج أسماء المواضيع وتحديثها في قاعدة البيانات.

الحفاظ على الأسماء المخصصة

عند تخصيص اسم موضوع داخل لوحة التحكم ثم تشغيل التحديث التلقائي، قد يتغير الاسم.

لحل هذه المشكلة، أضفت حقل حماية (is_manually_named)؛ ففي حال تفعيله، يتجاهل محرك التحديث هذا الموضوع تماماً ويحافظ على الاسم المخصص من قِبل المستخدم.

القيد الثالث: التنسيق الغني وأمان الـ HTML

يدعم تلغرام تنسيق النصوص، غير أن إرسال كود HTML الناتج من المتصفح مباشرة إلى Telegram API يحمل مخاطر أمنية وأخطاء محتملة في التنسيق.

الحل: محرر مخصص مع طبقة تحويل حصرية

اعتمدت على محرر نصي مبني باستخدام contenteditable ومَدعوم بطبقة تحويل مخصصة (editorHtmlToTelegramHtml):

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

القيد الرابع: جدولة الرسائل بدون خادم منفصل

استهدفت توفير ميزة جدولة الرسائل دون الحاجة لتشغيل خادم خلفي دائم يزيد من تكاليف التشغيل.

الحل: الاعتماد على pg_cron و pg_net في Supabase

استغلت إمكانيات PostgreSQL داخل Supabase عبر دمج إضافتي pg_cron و pg_net:

  1. يقوم pg_cron بإطلاق طلب HTTP عبر pg_net نحو الـ Endpoint الخاص بالجدولة /api/cron بشكل دوري.
  2. يتأكد الـ Endpoint من مفتاح الحماية (x-cron-secret).
  3. يبحث النظام عن الرسائل المستحقة (scheduled_at <= NOW()).
  4. تُرسل الرسائل عبر Telegram Bot API وتُحدث حالتها إلى "مرسلة".

حل مشكلة التزامن والسباق

عند وجود أكثر من مفعّل للجدولة، قد تتضاعف عمليات الإرسال للرسالة الواحدة.

تم حل هذه المشكلة بتطبيق Optimistic Claim: تقوم كل عملية بإجراء تحديث شرطي (UPDATE) يغيّر حقل next_run_at لقيمة مؤقتة، حيث تنجح عملية واحدة فقط في حجز الصف، وتتجاهل باقي العمليات الرسالة المحجوزة.

القيد الخامس: تعارض الـ Webhook مع الـ Long-Polling

عند ربط البوت بـ Webhook لاستقبال الأوامر حياً، يتوقف استدعاء getUpdates عن العمل تماماً بقرار من منصة تلغرام، مما يؤدي إلى فشل زر تحديث المواضيع أثناء تفعيل الـ Webhook.

الحل

وثّقت هذه الحالة بوضوح داخل واجهة المستخدم، مع إظهار تنبيه لطيف يوضح للمستخدم ضرورة تعطيل الـ Webhook مؤقتاً في حال رغبته في إعادة مسح وتحديث المواضيع يدوياً.

الأمان: معايير عالية على مستوى الإنتاج

أوليت حماية مفاتيح الربط وإدارة الصلاحيات عناية قصوى ضمن المعمارية البرمجية:

  1. عزل مفتاح البوت تماماً: يُخزن الـ Token في عمود خاص بالخادم فقط داخل قاعدة البيانات، ولا يُكشف إطلاقاً للواجهة الأمامية عبر متغيرات البيئة العامة مثل NEXT_PUBLIC_*.
  2. التحقق من هوية المدير: كل Server Action و API Route محمي بدالة requireAdmin() التي تطابق الجلسة الحالية مع ID المدير المصرح له فقط (admin_config.admin_id).
  3. سياسات RLS محكمة: تطبيق Row Level Security على مستوى PostgreSQL باستخدام دالة is_admin() ذات الصلاحيات المحدودة (SECURITY DEFINER).
  4. حماية الـ Webhook والـ Cron: التحقق التوقيتي الآمن للتوقيعات لمنع هجمات التخمين وإعادة التشغيل، مع تفعيل تحديد معدل الطلبات حسب عنوان الـ IP.

دروس مستفادة من التجربة

  • قيود الـ API ليست نهاية المطاف، ويسهم الابتكار في تصميم حلول هندسية كفؤة للالتفاف على النقص في أدوات المنصات.
  • ينبغي أن تكون القاعدة الافتراضية للوصول هي الرفض التام حتى يثبت العكس، خصوصاً عند التعامل مع مفاتيح الربط الحساسة.
  • استخدام قدرات PostgreSQL الذاتية أغنى عن إدارة بنى تحتية معقدة لخوادم إضافية.
  • وضع حالات التنافس في الحسبان منذ اليوم الأول يوفر ساعات طويلة من تصحيح الأخطاء لاحقاً.

الخلاصة

الحمد لله, مثلت تجربة بناء Rebex Tele دراسة حالة هندسية لفهم التعامل مع القيود البرمجية، وتطبيق ممارسات الأمان المتقدمة، وبناء منتج ذاتي الاستضافة يعتمد عليه بكل كفاءة.

لمزيد من التفاصيل حول المشروع: Rebex Tele - لوحة تحكم Telegram Bot

مشاركة_المقالة