وثائق المطوّرين
العربية

واجهة Pabal البرمجية

واجهة Pabal البرمجية (MTProto)

عندما تبني عميلاً يتصل بالخادم بالطريقة نفسها التي يتصل بها التطبيق: بيانات الاتصال، والمفتاح العام للخادم، ومسار المصادقة، والتحديثات، ونطاق الدعم.

يتحدث تطبيق Pabal مع الخادم عبر MTProto 2.0. استعن بهذا المستند عندما تبني برنامجاً يتصل بالطريقة نفسها — تطبيقاً آخر، أو أتمتةً تعمل بحساب مستخدم عادي، أو عميلاً لأغراض بحثية. أما إن كنت تبني بوتاً فتكفيك Bot API الأبسط.

اطّلع على وثائق Telegram أيضاً

بما أن Pabal يتّبع البروتوكول العلني الذي نشرته Telegram، فالمرجع في التعريفات التفصيلية للبروتوكول والطرق هو وثائق MTProto وطرق API. أما هذا المستند فيذكر الاختلافات ونطاق الدعم عند الاتصال بخادم Pabal.

بيانات الاتصال

البندالقيمة
العنوان122.34.175.215
المنفذ8443 (TCP)
DCمراكز البيانات من 1 إلى 5 كلها بالعنوان نفسه. يمكنك الاتصال بأيٍّ منها، وعادةً يُستخدم 2
البروتوكولMTProto 2.0، وطبقة API هي 216
أنواع النقلAbridged وIntermediate وPadded Intermediate وFull — كلٌّ منها مع التعمية (obfuscated2)
المفتاح العام للخادمserver-key.pem · البصمة (fingerprint) 8724853375441383205
api_id · api_hashلا يُتحقق منهما. ضع أي قيمة

النقل عبر HTTP وعبر WebSocket وMTProxy غير متاحة بعد. يجب أن تكون ساعة جهاز العميل مضبوطة — فأرقام رسائل MTProto مشتقة من الوقت، وإذا كان فرق الساعة كبيراً يُسقط الخادم الرسائل.

المفتاح العام للخادم

عند الاتصال الأول يشفّر عميل MTProto تبادل مفتاح المصادقة بمفتاح RSA العام للخادم. وعملاء Telegram يحملون في داخلهم المفتاح العام لـ Telegram، لذا فلكي يتصل أحدها بـ Pabal يجب تضمين هذا المفتاح بدلاً منه (أو إلى جانبه). فهذا المفتاح هو ما يمنع خادماً آخر من انتحال صفة خادم Pabal.

-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEA4hH74xPQsUwr/pyXPdF4tVicYr6QbfeDrKC7mUOVrPLSL4FtmgGn
w+O4u6lVvOf3Udd1KY6+OL4fUZdMBlLzwsoGLoniiVR09dnvyXHE8LhQSS+i1LmI
oJbhQwXplLnUJf272fLXkD23e7ppKLkjYk+jeYObueCy5HYMSThklVeXEzbZVGZv
47o/mjU2vyFoRpa6wCIE4rpj1UIPtOMpekMI/TocIlGVJ+ch6cAVNxIDro53a1eG
/1oZRLQH4oViEGxeMMjBMY5gk5HPkZvjbqy4h8TjXEz7O5o0BRsSqG/OPtP/dRQV
X4ewPhj2WCU4e6l5X59ZKIcv4sQLOwClqQIDAQAB
-----END RSA PUBLIC KEY-----
curl -s -o server-key.pem https://pabal.me/docs/server-key.pem

يُنشأ هذا المفتاح مرة واحدة عند أول تشغيل للخادم، ولا يتغير بعد ذلك. تحقق من أن قيمة Loaded RSA key … (fingerprint …) في سجل الخادم تطابق البصمة أعلاه.

الاتصال باستخدام Telethon

هذا مثال على تسجيل الدخول بحساب شخص وتبادل الرسائل باستخدام Telethon في Python. سجّل الحساب أولاً من التطبيق (انظر أدناه).

# pabal_client.py — pip install telethon==1.42.0
# ضع server-key.pem (المفتاح العام للخادم الذي نزّلته أعلاه) في المجلد نفسه
import asyncio

from telethon import TelegramClient, events
from telethon.crypto import rsa

rsa.add_key(open("server-key.pem").read(), old=False)          # المفتاح العام لخادم Pabal

client = TelegramClient("pabal", api_id=1, api_hash="0" * 32)  # يُحفظ تسجيل الدخول في pabal.session
client.session.set_dc(2, "122.34.175.215", 8443)


@client.on(events.NewMessage(incoming=True))
async def show(event):
    sender = await event.get_sender()
    print(f"{sender.first_name}: {event.raw_text}")


async def main():
    await client.start(phone=lambda: input("رقم الهاتف (+8210…): "))   # أدخل الرمز في المرة الأولى فقط
    me = await client.get_me()
    print(f"تم تسجيل الدخول: {me.first_name} (id {me.id})")
    await client.send_message("BotFather", "/help")
    await client.run_until_disconnected()


asyncio.run(main())
  • استخدم Telethon 1.42، فهو الإصدار الذي يتحدث بالطبقة 216. أما الإصدارات الأحدث فتحاول قراءة الاستجابات بطبقة أعلى فتفشل بالخطأ TypeNotFoundError.
  • تسجيل الحسابات الجديدة معطّل في Telethon (sign_up()). سجّل من التطبيق، أو استدعِ auth.signUp بنفسك.
  • يُحفظ تسجيل الدخول في الملف pabal.session، فلا يُطلب منك الرمز في المرات التالية. وهذا الملف مفتاح حسابك، فاحمِه.

مسار تسجيل الدخول

⁧1 · مفتاح المصادقة (مرة واحدة)⁩ req_pq_multi → req_DH_params set_client_DH_params ⁧مفتاح مصادقة بطول 2048 بت⁩محمي بالمفتاح العام للخادم ⁧2 · تسجيل الدخول (مرة لكل مفتاح مصادقة)⁩ auth.sendCodeرقم الهاتف sentCodeTypeSms⁧SMS أو عن طريق المسؤول⁩ SetUpEmailRequiredطريقة البريد ← طلب العنوان account.sendVerifyEmailCodepurpose: loginSetup auth.signIn⁧phone_code أو رمز البريد⁩ auth.authorizationاكتمل تسجيل الدخول authorizationSignUpRequired⁧رقم جديد ← auth.signUp مع الاسم⁩ عند استلام الرمز
أنشئ مفتاح المصادقة، ثم سجّل الدخول بالرمز

شرح المخطط

  • مرحلتان: في الأعلى مرحلة إنشاء مفتاح المصادقة الذي يُستخدم في التشفير (البروتوكول)، وفي الأسفل مرحلة تسجيل الدخول التي تربط حساباً بذلك المفتاح (API). وتتولى المكتبات المرحلة العليا تلقائياً.
  • يرتبط تسجيل الدخول بمفتاح المصادقة: إذا فتحت عدة جلسات بمفتاح سُجّل به الدخول مرة، فكلها تكون في حالة تسجيل دخول. وإذا فقدت المفتاح (بحذف ملف الجلسة) فعليك تسجيل الدخول من جديد.
  • مشغّل الخادم هو من يحدد طريق الرمز: في حالة SMS أو الإيصال عن طريق المسؤول يصل sentCodeTypeSms، وفي حالة البريد الإلكتروني يصل sentCodeTypeSetUpEmailRequired فيسأل العميل عن عنوان البريد ويستدعي account.sendVerifyEmailCode (الصف الأوسط).
  • الخط الأحمر المتقطع هو طريق الأرقام الجديدة: إذا كان الرمز صحيحاً ولا يوجد حساب، يصل authorizationSignUpRequired، وباستدعاء auth.signUp مع الاسم يكتمل التسجيل. ولا يتم التسجيل إلا بعد إدخال الرمز الصحيح.
  • البوتات لا تمرّ بالمرحلة السفلى، بل تسجّل الدخول باستدعاء واحد لـ auth.importBotAuthorization (بالرمز المميّز للبوت).
الخطأمتى
PHONE_NUMBER_INVALIDالرقم خاطئ، أو رقم جديد والخادم مغلق أمام التسجيلات الجديدة
PHONE_NUMBER_BANNEDرقم حظره المشغّل، أو رقم حساب موقوف (إذا حُذف وهو موقوف فسنة افتراضياً — ويمكن للمشغّل إطالتها أو جعلها بلا حدّ)
FLOOD_WAIT_n (420)طلبت الرمز مرات كثيرة جداً. أعد المحاولة بعد n ثانية
PHONE_CODE_INVALIDالرمز خاطئ (ويُقفل إذا تجاوزت العدد المسموح من المحاولات)
PHONE_CODE_EXPIREDانتهت صلاحية الرمز أو أُقفل، أو أن phone_code_hash غير معروف — ابدأ من جديد بـ sendCode
EMAIL_INVALID، EMAIL_NOT_ALLOWEDعنوان البريد خاطئ / الحساب موجود لكن العنوان ليس بريد تسجيل الدخول المسجّل له
AUTH_KEY_UNREGISTERED (401)استُدعيت طريقة تتطلب تسجيل الدخول بمفتاح لم يُسجَّل به الدخول
أرقام الاختبار

على الخادم الذي فعّل فيه المشغّل أرقام الاختبار، يمكن تسجيل الدخول بأرقام بالشكل +99966XYYYY دون إيصال رمز فعلي، وذلك بالرمز XXXXX (أي تكرار X خمس مرات). وهذه ميزة لخوادم التطوير فقط، وهي معطّلة على خوادم الإنتاج.

استلام التحديثات

  • فورياً: ما دام الاتصال مفتوحاً، يرسل الخادم الرسائل الجديدة والتعديلات وعمليات الحذف مباشرةً على شكل updateShortMessage وupdates. والجلسة التي أرسلت الطلب تستلم النتيجة في استجابة RPC، فلا يصلها الشيء نفسه مرة أخرى عبر الدفع (push).
  • pts: لكل مستخدم رقم تسلسلي (pts) يُعطى لكل تغيير. فإذا وجد العميل فجوة في أرقام pts التي استلمها، فقد فاته شيء.
  • الاستدراك: احفظ pts الحالي عبر updates.getState، وعند إعادة الاتصال استلم عبر updates.getDifference(pts, date, qts) الرسائل الجديدة وعمليات الحذف التي وقعت في الأثناء، مع المستخدمين والمجموعات المعنيين. وإذا كان pts لدى العميل متقدماً على الخادم (كأن تكون بيانات الخادم قد أُعيدت تهيئتها) يصل differenceTooLong، فأعد تحميل قائمة المحادثات.
  • الإشعارات الفورية — Android: يستيقظ تطبيق Android غير المتصل بإشعار فوري من Firebase. فبعد أن يسجّل التطبيق نفسه عبر account.registerDevice (token_type 2 = رمز FCM، وsecret = مفتاح الجهاز بطول 256 بايت)، يشفّر الخادم الرسائل والمكالمات الجديدة بمفتاح الجهاز ذاك ويرسلها عبر FCM، ثم يستدرك التطبيق بعد استيقاظه عبر updates.getDifference. ولا تصل الإشعارات الفورية إلا إلى التطبيقات المبنية بمشروع Firebase الخاص بمشغّل الخادم.
  • الإشعارات الفورية — iPhone: يسجّل تطبيق iPhone بالطلب نفسه شيئين — token_type 1 (رمز إشعارات APNs) و9 (رمز VoIP من PushKit)، وsecret في كليهما هو مفتاح الجهاز بطول 256 بايت الخاص بذلك الحساب. وتُرسَل الرسائل الجديدة إشعاراتٍ عبر APNs: فالنص الظاهر الذي تستطيع Apple رؤيته ليس إلا اسم التطبيق وعبارة خالية من المحتوى مثل «لديك إشعار جديد»، أما الرسالة فتُشفَّر بمفتاح الجهاز وتُحمَل في p، فيفكّ تشفيرها امتداد الإشعارات في التطبيق (Notification Service Extension) ويعرضها. وتُظهر المكالمات شاشة الاتصال في CallKit عبر إشعار VoIP (بدءاً من البناء (build) الذي فعّل فيه المشغّل VoIP، وقبل ذلك تصل كإشعار عادي)، وما قُرئ أو حُذف على جهاز آخر يُبلَّغ به عبر إشعار في الخلفية. ولا تصل الإشعارات الفورية إلا إلى التطبيقات التي وقّعها الفريق نفسه صاحب مفتاح APNs لدى مشغّل الخادم ولها معرّف الحزمة (bundle ID) نفسه. أما قيم token_type الأخرى فيجيبها بـ boolTrue فقط ولا يرسل إليها شيئاً.
  • المكتبات مثل Telethon تتولى هذه العملية كلها تلقائياً.

المعرّفات والنظراء

الكيانالمعرّفملاحظات
الأشخاصبدءاً من 100001peerUser. ومعرّف @BotFather هو 100000
البوتاتنظام الترقيم نفسه الخاص بالأشخاصuser.bot = true. والرقم الذي في بداية الرمز المميّز هو معرّف البوت
المجموعات العاديةبدءاً من 1000001peerChat. وفي Bot API تظهر بعدد سالب (-chat_id)
الرسائلتسلسل واحد للخادم كلهفي المحادثة الفردية تحمل النسختان الرقم نفسه، لذا فإن الطلبات التي تأخذ أرقام الرسائل وحدها دون نظير (messages.getMessages، messages.deleteMessages) تشير إلى الرسالة نفسها لدى الشخصين. القنوات وحدها تعدّ من 1، كل قناة على حدة

احفظ قيمة access_hash التي يعطيها الخادم كما هي واستخدمها (فهي تأتي مع نتائج البحث عن أسماء المستخدمين وقائمة المحادثات والتحديثات).

الملفات

  • الرفع: ارفع الأجزاء (حتى 512KB للجزء الواحد، وحتى 4,000 جزء) عبر upload.saveFilePart ثم أشر إليها بـ inputFileUploaded…. أما الملفات التي تتجاوز 10MB فتُرفع عبر upload.saveBigFilePart — وبما أنك تُعلم الخادم بعدد الأجزاء مسبقاً، فإنه يرفض الملف بالخطأ FILE_TOO_BIG قبل أن ترسله كاملاً إن كان حجمه غير مقبول. وتُكتب الأجزاء على القرص فور وصولها، ثم تُدمج في ملف واحد عند إشارة الرسالة إليه.
  • الإرسال: استخدم في messages.sendMedia القيمة inputMediaUploadedPhoto (صورة جديدة)، أو inputMediaPhoto (صورة موجودة على الخادم)، أو inputMediaUploadedDocument (ملف جديد)، أو inputMediaDocument (ملف موجود على الخادم). وما عدا ذلك من الوسائط يعيد MEDIA_INVALID. ويمكنك أيضاً رفع وسائط دون إرسالها عبر messages.uploadMedia (يعيد لك كائن media ترسله كما هو لاحقاً)، كما يُقبل messages.sendMultiMedia لكن العناصر تذهب واحداً تلو الآخر دون تجميع (بلا grouped_id).
  • الاستلام: استخدم في upload.getFile القيمة inputPhotoFileLocation (صورة رسالة)، أو inputDocumentFileLocation (ملف رسالة)، أو inputPeerPhotoFileLocation (صورة ملف شخصي). والحد الأقصى 1MB في المرة الواحدة. وفي التنزيل أيضاً لا يحمّل الخادم الملف كاملاً في الذاكرة، بل يقرأ المقطع المطلوب فحسب.
  • صورة الملف الشخصي: photos.uploadProfilePhoto، وphotos.updateProfilePhoto، وphotos.getUserPhotos، وphotos.deletePhotos.
  • تُحفظ الصور بحجم واحد فقط هو الأصل (لا تُنشأ صور مصغّرة منفصلة). أما الملفات فتُترك كما هي دون أي معالجة، وتُنقل سمات documentAttribute* التي أرفقتها الجهة المرسِلة إلى الجهة المستلِمة بايتاً ببايت — فينقل الخادم مدة الفيديو أو الشكل الموجي للصوت كما هي دون حاجة إلى فهمها.

نطاق الدعم

في الخادم معالِجات لـ 469 طرق من الطبقة 216، ويمكنها جميعاً قراءة الطلبات، لكن ما تحققنا منه حتى النهاية بعملاء حقيقيين هو الطرق أدناه. أما البقية فتعيد استجابات بالصيغة الصحيحة، لكن محتواها قد يكون فارغاً أو قد لا يُسجَّل.

المجالالطرق التي تحققنا منها
الاتصالinitConnection، invokeWithLayer، help.getConfig، auth.bindTempAuthKey (المفتاح المؤقت لـ PFS)، auth.exportAuthorization/importAuthorization
تسجيل الدخولauth.sendCode، auth.signIn، auth.signUp، auth.logOut، auth.importBotAuthorization، account.sendVerifyEmailCode
المستخدمون وجهات الاتصالusers.getUsers، users.getFullUser، contacts.resolveUsername، contacts.importContacts، contacts.search
الرسائلmessages.sendMessage، messages.sendMedia (صور وملفات)، messages.getHistory، messages.getDialogs، messages.getMessages، messages.editMessage، messages.deleteMessages
المجموعاتmessages.createChat، messages.deleteChatUser، messages.editChatTitle (وmessages.addChatUser تحققنا منها بالتطبيق الرسمي فقط)
البوتاتmessages.getBotCallbackAnswer، messages.setBotCallbackAnswer، والرسائل التي تحمل أزراراً (reply_markup)
التحديثاتupdates.getState، updates.getDifference، والدفع الفوري
الملفات والصورupload.saveFilePart، upload.saveBigFilePart (لما يتجاوز 10MB)، upload.getFile، photos.* (أعلاه)

وتحققنا كذلك من أن تطبيق Telegram Desktop الرسمي 6.2.6 يعمل دون تعديل في التسجيل وتسجيل الدخول والمحادثات والصور والمجموعات وإعادة الاتصال. أما الطرق التي يستدعيها التطبيق عند بدء تشغيله، وعددها نحو 60 طريقة، فتُفحص صيغة استجاباتها على حدة.

ما أُضيف بعد ذلك — قائمة الأجهزة وتسجيل خروجها (account.getAuthorizations، account.resetAuthorization، auth.resetAuthorizations)، وتصدير البيانات في تطبيق سطح المكتب (account.initTakeoutSession، invokeWithTakeout، invokeWithMessagesRange، account.finishTakeoutSession — ثلاث مرات بدء في اليوم لكل حساب، وما زاد فالنتيجة 420 TAKEOUT_INIT_DELAY_n)، وتغيير الرقم (account.sendChangePhoneCode، account.changePhone — 400 PHONE_CHANGE_DISABLED ما لم يفعّله المشغّل، وBOT_METHOD_INVALID للبوتات) — تحققنا منه باختبارات الخادم، ولم نتحقق منه بعد من أوله إلى آخره بالتطبيقات الحقيقية.

الأخطاء

تصل الأخطاء بالصيغة القياسية rpc_error (error_code + error_message). وتتكوّن error_message دائماً من أحرف كبيرة وأرقام وشرطات سفلية (PEER_ID_INVALID)، وقد يُلحق بها : وصف عند الحاجة.

الرمزالمعنى
400الطلب خاطئ — PEER_ID_INVALID، MESSAGE_ID_INVALID، MEDIA_INVALID، USERNAME_NOT_OCCUPIED …
401يلزم تسجيل الدخول — AUTH_KEY_UNREGISTERED
403لا صلاحية — كمجموعة لست عضواً فيها، وما شابه
406غير مسموح الآن — جهاز سُجِّل دخوله قبل أقل من 24 ساعة يحاول تسجيل خروج جهاز آخر: FRESH_RESET_AUTHORISATION_FORBIDDEN
420FLOOD_WAIT_n — انتظر n ثانية
500خطأ داخلي في الخادم
خطأ النقل -404الخادم لا يعرف مفتاح المصادقة هذا — أنشئ مفتاحاً جديداً وسجّل الدخول من جديد (المفتاح الدائم)، أو أعد الربط (المفتاح المؤقت)

واجهة الساعة البرمجية

/api/watch/v1/ في الخادم مدخل HTTPS JSON مخصّص لتطبيق Apple Watch من Pabal وحده. وُضع منفصلاً لأن الساعة لا تستطيع استخدام MTProto، وهو ليس مواصفة عامة وما زال قيد الإعداد، فقد يتغيّر دون إشعار. إذا أردت أن تكتب برنامجاً يتصل بـ Pabal فاستخدم MTProto الموصوف في هذه الصفحة. ومشغّلو الخوادم يراجعون تثبيت الخادم — نقطة دخول Apple Watch.

ما ليس متاحاً بعد

  • القنوات والمجموعات الخارقة (تستجيب channels.* لكنها لا تظهر بشكل صحيح في التطبيق)، والمحادثات السرية، والمكالمات الجماعية
  • الفيديو والرسائل الصوتية التي تُشغَّل داخل التطبيق، والألبومات التي تظهر كحزمة واحدة (grouped_id)، والملصقات، والصور المصغّرة (الملفات بالأصل فقط)
  • التحقق بخطوتين (SRP) — لا يمكن ضبطه، والعمليات التي تتطلب التحقق بخطوتين تُرفض
  • النقل عبر HTTP وWebSocket، وMTProxy، وإرسال msgs_ack، والتغيير الدوري لقيمة salt الخادم (ويُرَدّ على قيمة salt الخاطئة بـ bad_server_salt)
  • التوزيع على عدة خوادم — خادم واحد يتولى مراكز البيانات من 1 إلى 5 كلها

لتوصيل تطبيق Telegram الرسمي بـ Pabal

يضمّن تطبيق Telegram عنوان الخادم والمفتاح العام في داخله عند البناء. لذلك لا يمكن تغييرهما من شاشة الإعدادات، بل يجب تعديل الشيفرة المصدرية وإعادة البناء. وهكذا صُنع تطبيق Pabal ‏(Pabal.app). وإن كنت مشغّل خادم فراجع تثبيت الخادم — توصيل التطبيق.