تطوير البوتات
إنشاء بوت
أنشئ بوتاً عبر @BotFather، واستقبل الرسائل وردّ عليها، ثم الأزرار والأوامر والصور والمجموعات — درس تطبيقي تتبعه من البداية إلى النهاية.
بنهاية هذا الدرس سيكون لديك بوت يرد على الرسائل، ويضيف الأزرار، ويتعامل مع قائمة الأوامر والصور، ويعمل في المجموعات أيضاً. كل ما تحتاج إليه هو تطبيق Pabal، وحاسوب لتشغيل برنامج البوت، وواحد من الاثنين: Python 3.10 أو أحدث، أو Node.js 18 أو أحدث.
كيف يعمل البوت
البوت في Pabal حساب يتحكم فيه برنامج. الرسائل المرسلة إلى البوت تتجمع في صندوق رسائله، ويسأل برنامج البوت الخادم «هل وصل شيء جديد؟» (getUpdates) ليأخذها، ثم يرسل الرد (sendMessage). ويعمل برنامج البوت خارج الخادم، على حاسوبك أنت.
شرح المخطط
- ثلاثة خطوط: على اليسار الشخص الذي يستخدم التطبيق، وفي الوسط خادم Pabal، وعلى اليمين برنامج البوت الخاص بك. والخطوط العمودية المنقّطة تمثّل اتجاه مرور الوقت.
- الأسهم الرمادية طلبات يبدأها البوت، والأسهم الزرقاء هي الرسائل التي تنتقل نتيجةً لها. برنامج البوت يرسل الطلبات فقط، ولا يبادر الخادم بالاتصال بالبوت (ما لم تستخدم webhook).
- الانتظار في ① (الاستطلاع الطويل، long polling) هو الأساس: عندما تمرّر
timeout=30لا يعيد الخادم استجابة فارغة فوراً إن لم يكن هناك جديد، بل يحتفظ بالطلب حتى 30 ثانية، ويعيده (③) لحظة وصول رسالة (②). لذلك تكون الاستجابة سريعة وعدد الطلبات قليلاً. - قيمة offset في ⑥ هي علامة «تم الاستلام»: إذا أرسلت آخر
update_idعالجته مضافاً إليه 1، يحذف الخادم ذلك التحديث وكل ما قبله. وإذا لم ترفع offset فستستلم التحديث نفسه مراراً. - ⑤ يسلك الطريق نفسه الذي تسلكه رسائل الأشخاص: يُدفع رد البوت إلى جميع أجهزة التطبيق، ويظهر في قائمة المحادثات أيضاً.
1. إنشاء بوت عبر @BotFather
تُنشئ البوت بالتحدث إلى @BotFather داخل تطبيق Pabal. وBotFather بوت موجود داخل خادم Pabal نفسه.
- اكتب
BotFatherفي مربع البحث في التطبيق وافتح BotFather. عندما تضغط ابدأ تصلك قائمة الأوامر. - أرسل
/newbot. - أرسل اسم البوت. هذا هو الاسم الظاهر في قائمة المحادثات، لذا يمكن كتابته بالعربية أيضاً.
- أرسل اسم المستخدم للبوت. يتكوّن من 5 إلى 32 حرفاً من الأحرف اللاتينية والأرقام والشرطة السفلية، ويبدأ بحرف لاتيني، ويجب أن ينتهي بـ
bot. - عندما يصلك الرد الذي يحتوي على الرمز المميّز (token) تكون قد انتهيت. انسخ الرمز واحتفظ به.
يرد BotFather حالياً باللغة الكورية. في هذه المحادثة يطلب أولاً اسم البوت (الاسم الذي يظهر في قائمة المحادثات)، ثم اسم المستخدم للبوت، وأخيراً يعلن أن البوت @hello_test_bot قد أُنشئ، ويسلّمك الرمز المميّز للبوت (السطر الذي يبدأ بـ 100003:) مع تنبيه بأن تحفظه بأمان كما تحفظ كلمة المرور.
| أمر BotFather | ما يفعله |
|---|---|
/newbot | إنشاء بوت جديد (الاسم ← اسم المستخدم ← الرمز المميّز) |
/mybots | قائمة البوتات التي أنشأتها |
/token | عرض الرمز المميّز للبوت مرة أخرى |
/revoke | إصدار رمز مميّز جديد — يُلغى الرمز السابق فوراً، وتُقطع أيضاً الاتصالات التي كانت قائمة به |
/setcommands | ضبط قائمة الأوامر (command - description، أي الأمر ثم وصفه، في كل سطر) |
/deletebot | حذف البوت — للتأكيد أرسل 네, 삭제합니다 (أي «نعم، احذفه»). ويُحرَّر اسم المستخدم ليصبح قابلاً للاستخدام من جديد |
/cancel | إلغاء العملية الجارية |
إذا أرسلت الأمر مع اسم المستخدم، مثل /token @hello_test_bot، فستتخطى خطوة «أي بوت؟».
2. التعامل مع الرمز المميّز
الرمز المميّز بالشكل <bot ID>:<secret>. الرقم الذي في البداية هو معرّف المستخدم الخاص بالبوت، وما بعده هو السر. وبما أن رمزاً واحداً يكفي للتحكم الكامل في البوت، فتعامل معه ككلمة مرور.
- لا تكتبه في الشيفرة، بل ضعه في متغير بيئة (
BOT_TOKEN) أو في مخزن للأسرار. ولا ترفعه إلى مستودع عام. - إذا تسرّب فأرسل
/revokeإلى BotFather. عندها يُرفض الرمز السابق فوراً (401 Unauthorized)، وتُقطع أيضاً جلسات البوت التي كانت متصلة بـ MTProto بالرمز السابق. - بما أن الرمز يوضع داخل العنوان (URL)، فاحرص على ألا يسجّل برنامج البوت عناوين الطلبات في سجلاته. وخادم Pabal أيضاً لا يسجّل عناوين Bot API.
3. الطلب الأول — getMe
عنوان كل الطلبات هو https://pabal.me/bot<token>/<method>. لنتحقق من صحة الرمز عبر getMe.
export BOT_TOKEN='100003:AbCdEf…'
curl -s "https://pabal.me/bot$BOT_TOKEN/getMe"# pip install requests
import os
import requests
r = requests.get(f"https://pabal.me/bot{os.environ['BOT_TOKEN']}/getMe", timeout=10)
print(r.json())// Node.js 18 أو أحدث — fetch مدمجة فيه
const res = await fetch(`https://pabal.me/bot${process.env.BOT_TOKEN}/getMe`);
console.log(await res.json());عند النجاح تصلك استجابة كهذه. كل الاستجابات بصيغة JSON تحتوي على ok وresult (عند النجاح) أو error_code وdescription (عند الفشل).
{
"ok": true,
"result": {
"id": 100003,
"is_bot": true,
"first_name": "بوت مرحباً",
"username": "hello_test_bot",
"can_join_groups": true,
"can_read_all_group_messages": true,
"supports_inline_queries": false,
"can_connect_to_business": false,
"has_main_web_app": false
}
}
إذا كان الرمز خاطئاً فستصلك HTTP 401 مع {"ok": false, "error_code": 401, "description": "Unauthorized"}.
4. استلام الرسائل — getUpdates
افتح البوت في التطبيق واضغط ابدأ أو أرسل أي شيء، ثم اجلب التحديثات الجديدة.
curl -s "https://pabal.me/bot$BOT_TOKEN/getUpdates?timeout=30"
{
"ok": true,
"result": [
{
"update_id": 1,
"message": {
"message_id": 1,
"from": { "id": 100001, "is_bot": false, "first_name": "هناء" },
"chat": { "id": 100001, "first_name": "هناء", "type": "private" },
"date": 1789805661,
"text": "/start",
"entities": [ { "type": "bot_command", "offset": 0, "length": 6 } ]
}
}
]
}
- update_id: رقم يزيد بمقدار 1 مع كل تحديث. بعد المعالجة، إذا مرّرت
offset=update_id+1في الطلب التالي، يُحذف ذلك التحديث وما قبله باعتبارها «مُستلَمة». - timeout: عدد الثواني التي ينتظرها الخادم عندما لا يوجد جديد (من 0 إلى 50). إذا كانت 0 يعيد قائمة فارغة فوراً. ننصح بقيمة بين 25 و30.
- chat.id: الوجهة التي ترسل إليها الرد. في المحادثة الفردية هو معرّف الشخص (عدد موجب)، وفي المجموعة عدد سالب.
- التحديثات التي يمكن استلامها ثلاثة أنواع:
message(رسالة جديدة)، وedited_message(رسالة معدّلة)، وcallback_query(ضغط زر).
التحديثات التي لم تُجلب تتراكم في ذاكرة الخادم، حتى آخر 1,000 تحديث لكل بوت. وعند إعادة تشغيل الخادم يضيع ما لم يُجلب منها (أما الرسائل نفسها فتبقى في المحادثة). فلا تترك البوت متوقفاً مدة طويلة.
5. إرسال الرد — sendMessage
curl -s "https://pabal.me/bot$BOT_TOKEN/sendMessage" \
-H 'Content-Type: application/json' \
-d '{"chat_id": 100001, "text": "أهلاً بك!"}'requests.post(f"https://pabal.me/bot{os.environ['BOT_TOKEN']}/sendMessage",
json={"chat_id": 100001, "text": "أهلاً بك!"}, timeout=10)await fetch(`https://pabal.me/bot${process.env.BOT_TOKEN}/sendMessage`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ chat_id: 100001, text: 'أهلاً بك!' }),
});يمكنك إرسال المعاملات بالصيغة التي تناسبك: جسم JSON، أو نموذج (application/x-www-form-urlencoded)، أو multipart/form-data عند رفع الملفات، أو سلسلة استعلام بعد العنوان. والنتيجة هي الرسالة المرسلة (Message).
لا يمكن للبوت أن يرسل إلى شخص إلا بعد أن يرسل ذلك الشخص إليه رسالة واحدة على الأقل. وإلا فالنتيجة 403 Forbidden: bot can't initiate conversation with a user. وهي القاعدة نفسها المعمول بها في Telegram.
6. إكمال بوت يكرّر ما يُقال له
بتكرار الاستلام والإرسال يصبح لديك بوت. هذه هي الشيفرة الكاملة مكتوبة دون أي مكتبة.
# echo.py — pip install requests
# التشغيل: BOT_TOKEN='100003:…' python3 echo.py
import os
import requests
API = f"https://pabal.me/bot{os.environ['BOT_TOKEN']}"
def call(method, **params):
r = requests.post(f"{API}/{method}", json=params, timeout=60)
data = r.json()
if not data["ok"]:
raise RuntimeError(f"{method}: {data['description']}")
return data["result"]
offset = 0
print("البوت يعمل الآن. للإيقاف اضغط Ctrl+C")
while True:
for update in call("getUpdates", offset=offset, timeout=30):
offset = update["update_id"] + 1 # علامة «تم الاستلام»
message = update.get("message")
if message and "text" in message:
call("sendMessage", chat_id=message["chat"]["id"], text=message["text"])// echo.mjs — Node.js 18 أو أحدث، دون مكتبة
// التشغيل: BOT_TOKEN='100003:…' node echo.mjs
const API = `https://pabal.me/bot${process.env.BOT_TOKEN}`;
async function call(method, params = {}) {
const res = await fetch(`${API}/${method}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(params),
});
const data = await res.json();
if (!data.ok) throw new Error(`${method}: ${data.description}`);
return data.result;
}
let offset = 0;
console.log('البوت يعمل الآن. للإيقاف اضغط Ctrl+C');
for (;;) {
const updates = await call('getUpdates', { offset, timeout: 30 });
for (const update of updates) {
offset = update.update_id + 1; // علامة «تم الاستلام»
const message = update.message;
if (message?.text) {
await call('sendMessage', { chat_id: message.chat.id, text: message.text });
}
}
}7. البناء باستخدام مكتبة
تحتوي مكتبات بوتات Telegram على إعداد لتغيير عنوان الخادم، وبهذا الإعداد وحده تعمل على Pabal كما هي. وعند نقل بوت مبني لـ Telegram يكفي أن تغيّر هذا الإعداد، وأن تحصل على رمز مميّز جديد من BotFather في Pabal.
| المكتبة | الإعداد الذي تغيّره | الإصدار الذي تحققنا منه |
|---|---|---|
| python-telegram-bot | .base_url("https://pabal.me/bot")، .base_file_url("https://pabal.me/file/bot") | 22.8 |
| aiogram | AiohttpSession(api=TelegramAPIServer.from_base("https://pabal.me")) | 3.31 |
| دون مكتبة (HTTP) | بداية العنوان: https://api.telegram.org ← https://pabal.me | — |
# hello_bot.py — pip install python-telegram-bot
# التشغيل: BOT_TOKEN='100003:…' python3 hello_bot.py
import os
from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
from telegram.ext import (Application, CallbackQueryHandler, CommandHandler, ContextTypes,
MessageHandler, filters)
SERVER = "https://pabal.me"
def buttons():
return InlineKeyboardMarkup([[InlineKeyboardButton("👍 أعجبني", callback_data="like"),
InlineKeyboardButton("🔢 زيادة العدد", callback_data="count")]])
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
await update.message.reply_text("أهلاً بك! جرّب الضغط على الأزرار.", reply_markup=buttons())
async def button(update: Update, context: ContextTypes.DEFAULT_TYPE):
query = update.callback_query
if query.data == "like":
await query.answer("شكراً لك!") # نص يظهر لحظات على شاشة من ضغط الزر
else:
n = context.chat_data.get("n", 0) + 1
context.chat_data["n"] = n
await query.answer() # أجب أولاً
await query.edit_message_text(f"العدد: {n}", reply_markup=buttons()) # ثم عدّل الرسالة
async def echo(update: Update, context: ContextTypes.DEFAULT_TYPE):
await update.message.reply_text(f"قلتَ: '{update.message.text}'")
def main():
app = (Application.builder().token(os.environ["BOT_TOKEN"])
.base_url(f"{SERVER}/bot") # Pabal بدلاً من api.telegram.org
.base_file_url(f"{SERVER}/file/bot")
.build())
app.add_handler(CommandHandler("start", start))
app.add_handler(CallbackQueryHandler(button))
app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, echo))
print("البوت يعمل الآن. للإيقاف اضغط Ctrl+C")
app.run_polling()
if __name__ == "__main__":
main()# echo_aiogram.py — pip install aiogram
# التشغيل: BOT_TOKEN='100003:…' python3 echo_aiogram.py
import asyncio
import os
from aiogram import Bot, Dispatcher
from aiogram.client.session.aiohttp import AiohttpSession
from aiogram.client.telegram import TelegramAPIServer
from aiogram.filters import CommandStart
dp = Dispatcher()
@dp.message(CommandStart())
async def start(message):
await message.answer("أهلاً بك! أرسل إليّ أي شيء.")
@dp.message()
async def echo(message):
if message.text:
await message.answer(message.text)
async def main():
session = AiohttpSession(api=TelegramAPIServer.from_base("https://pabal.me")) # Pabal
bot = Bot(os.environ["BOT_TOKEN"], session=session)
print("البوت يعمل الآن. للإيقاف اضغط Ctrl+C")
await dp.start_polling(bot)
asyncio.run(main())8. الأزرار والاستدعاءات (callbacks)
لإضافة أزرار مضمّنة (inline) إلى رسالة، مرّر في reply_markup الحقل inline_keyboard (مصفوفة من الصفوف، وكل صف مصفوفة من الأزرار). والأزرار نوعان: زر callback_data الذي يُبلغ البوت عند الضغط عليه، وزر url الذي يفتح رابطاً.
curl -s "https://pabal.me/bot$BOT_TOKEN/sendMessage" -H 'Content-Type: application/json' -d '{
"chat_id": 100001,
"text": "اختر من فضلك",
"reply_markup": {
"inline_keyboard": [
[ {"text": "👍 أعجبني", "callback_data": "like"}, {"text": "👎 لم يعجبني", "callback_data": "dislike"} ],
[ {"text": "افتح وثائق Pabal", "url": "https://pabal.me/docs/"} ]
]
}
}'
عندما يضغط شخص زر callback_data يستلم البوت تحديث callback_query.
{
"update_id": 7,
"callback_query": {
"id": "5812039457730125441",
"from": { "id": 100001, "is_bot": false, "first_name": "هناء" },
"message": { "message_id": 4, "chat": { "id": 100001, "type": "private", "first_name": "هناء" }, "text": "اختر من فضلك", … },
"chat_instance": "8413962145072395171",
"data": "like"
}
}
على البوت أن يرد خلال 10 ثوانٍ عبر answerCallbackQuery. وفي أثناء ذلك يعرض التطبيق علامة ساعة على الزر وينتظر.
# نص يظهر لحظات أعلى الشاشة (ومع show_alert: true تظهر نافذة تأكيد)
curl -s "https://pabal.me/bot$BOT_TOKEN/answerCallbackQuery" -H 'Content-Type: application/json' \
-d '{"callback_query_id": "5812039457730125441", "text": "شكراً لك!"}'
# غيّر نص الرسالة التي ضُغط زرها وأزرارها
curl -s "https://pabal.me/bot$BOT_TOKEN/editMessageText" -H 'Content-Type: application/json' \
-d '{"chat_id": 100001, "message_id": 4, "text": "ضغطتَ «أعجبني» 👍"}'
- طول
callback_dataمن 1 إلى 64 بايت. والحد الأقصى 100 زر في الرسالة الواحدة. - إذا لم تُجب على الاستدعاء، يتوقف التطبيق عن الانتظار بعد 10 ثوانٍ. وإذا كان البوت متوقفاً، ينهي الخادم الانتظار فوراً.
- الرد صالح في المرة الأولى فقط. بعض المكتبات ترسل رداً فارغاً أولاً عند تعديل الرسالة، لذا أرسل الرد الذي يحمل نصاً أولاً.
- إذا عدّلت الرسالة بالنص نفسه والأزرار نفسها فالنتيجة
400 Bad Request: message is not modified(كما في Telegram).
لوحة المفاتيح أسفل حقل الإدخال
عندما تمرّر keyboard تظهر لوحة أزرار بدلاً من حقل الإدخال، وعند الضغط على زر يُرسل نصه كرسالة. أخفِها بـ remove_keyboard، وفعّل وضع الرد بـ force_reply.
{
"chat_id": 100001,
"text": "أيّهما تختار؟",
"reply_markup": {
"keyboard": [ [ {"text": "نعم"}, {"text": "لا"} ], [ {"text": "أرسل موقعي", "request_location": true} ] ],
"resize_keyboard": true,
"one_time_keyboard": true
}
}
9. قائمة الأوامر
هي القائمة التي تظهر عندما تضغط / في نافذة المحادثة أو تضغط زر القائمة. تحددها في الشيفرة أو عبر الأمر /setcommands لدى BotFather.
curl -s "https://pabal.me/bot$BOT_TOKEN/setMyCommands" -H 'Content-Type: application/json' -d '{
"commands": [
{"command": "start", "description": "البدء"},
{"command": "help", "description": "المساعدة"}
]
}'
الأمر من 1 إلى 32 حرفاً من الأحرف اللاتينية الصغيرة والأرقام والشرطة السفلية، والوصف من 1 إلى 256 حرفاً، وبحد أقصى 100 أمر. إذا مرّرت language_code تُحفظ قائمة منفصلة لكل لغة، لكن التطبيق لا يعرض حالياً إلا القائمة الافتراضية المحددة دون رمز لغة. والأوامر التي يرسلها الأشخاص، مثل /start، تصل مُعلَّمة بالنوع bot_command في entities الخاصة بالرسالة.
10. إرسال الصور واستلامها
الإرسال
ارفع الملف بصيغة multipart/form-data، أو أعد استخدام file_id لصورة استلمتها من قبل. الحد الأقصى للصورة 10MB، وللوصف (caption) 1,024 حرفاً. والإرسال عبر URL غير مدعوم بعد.
curl -s "https://pabal.me/bot$BOT_TOKEN/sendPhoto" \
-F chat_id=100001 -F caption='صورة اليوم' -F photo=@sunset.jpgwith open("sunset.jpg", "rb") as f:
requests.post(f"{API}/sendPhoto", data={"chat_id": 100001, "caption": "صورة اليوم"},
files={"photo": f}, timeout=60)الاستلام
تصل الصورة التي يرسلها شخص في الحقل photo من الرسالة (قائمة بحسب الحجم، وفي Pabal عنصر واحد هو الأصل). احصل على المسار عبر getFile ثم نزّلها.
# 1) file_id → file_path
curl -s "https://pabal.me/bot$BOT_TOKEN/getFile?file_id=AQAAAAAAAAB7…"
# {"ok":true,"result":{"file_id":"AQAA…","file_unique_id":"AQAA…","file_size":48213,"file_path":"photos/AQAA….jpg"}}
# 2) التنزيل — يحتوي العنوان على /file/
curl -s -o photo.jpg "https://pabal.me/file/bot$BOT_TOKEN/photos/AQAA….jpg"
11. في المجموعات
- أضف البوت عند إنشاء المجموعة في التطبيق، أو من معلومات المجموعة ← إضافة أعضاء، بالبحث عن اسم المستخدم الخاص به.
- البوت الذي ينضم إلى مجموعة يستلم كل رسائل المجموعة (مثل «وضع الخصوصية مُعطّل» في Telegram). وتكون قيمة
chat.typeهي"group"، وقيمةchat.idعدداً سالباً. - إذا استدعيت
sendMessageبقيمةchat.idهذه فستُرسل الرسالة إلى المجموعة. والأزرار والصور والتعديل تعمل تماماً كما في المحادثة الفردية. - إذا خرج البوت من المجموعة فالإرسال إليها يعيد
403 Forbidden: bot is not a member of the group chat.
12. التحويل إلى webhook
إذا كان بوتك يعمل على خادم له عنوان HTTPS عام، فبدلاً من السؤال عبر getUpdates يمكنك أن تجعل خادم Pabal يرسل التحديثات الجديدة إلى ذلك العنوان.
curl -s "https://pabal.me/bot$BOT_TOKEN/setWebhook" -H 'Content-Type: application/json' \
-d '{"url": "https://bot.example.com/pabal-webhook", "secret_token": "سلسلة-عشوائية-طويلة"}'
الإعداد والتحقق وإعادة المحاولة والرد من خلال الاستجابة، كلها مشروحة في مستند Webhooks.
بوت يتصل عبر MTProto (Telethon)
يمكن للبوت أيضاً أن يتصل عبر MTProto نفسه الذي يستخدمه التطبيق. وهذا مريح إن كنت تستخدم أصلاً أدوات مخصّصة لحسابات الأشخاص (مثل Telethon). وبما أنه حساب البوت نفسه، يمكنك المزج بينه وبين HTTP.
# pip install telethon==1.42.0 ← استخدم 1.42 (الشرح أدناه)
# المفتاح العام للخادم: نزّل https://pabal.me/docs/server-key.pem وضعه في المجلد نفسه
import asyncio
import os
from telethon import TelegramClient, events
from telethon.crypto import rsa
from telethon.sessions import StringSession
rsa.add_key(open("server-key.pem").read(), old=False) # المفتاح العام لخادم Pabal
client = TelegramClient(StringSession(), api_id=1, api_hash="0" * 32)
client.session.set_dc(2, "122.34.175.215", 8443)
@client.on(events.NewMessage(incoming=True))
async def echo(event):
await event.reply(event.raw_text)
async def main():
await client.start(bot_token=os.environ["BOT_TOKEN"]) # auth.importBotAuthorization
print("البوت يعمل الآن. للإيقاف اضغط Ctrl+C")
await client.run_until_disconnected()
asyncio.run(main())
- استخدم Telethon 1.42. يتحدث Pabal بالطبقة 216، أما إصدارات Telethon الأحدث فتحاول قراءة الاستجابات بطبقة أعلى، فتفشل منذ تسجيل الدخول (
TypeNotFoundError). - لا يتحقق Pabal من
api_idوapi_hash، لذا تصلح أي قيمة. - يدفع الخادم الرسائل الجديدة فوراً إلى بوتات MTProto (فلا حاجة إلى getUpdates ولا إلى webhook). وعند الرد على الاستدعاءات استدعِ
event.answer("…")قبلevent.edit(…).
القواعد والحدود
| البند | القيمة |
|---|---|
| عدد أحرف الرسالة / وصف الصورة | 4,096 حرفاً / 1,024 حرفاً |
| حجم الصورة (الرفع عبر sendPhoto) | 10MB |
| حجم جسم الطلب | 12MB |
getUpdates: timeout · limit | من 0 إلى 50 ثانية · من 1 إلى 100 تحديث |
| الاحتفاظ بالتحديثات التي لم تُجلب | آخر 1,000 تحديث لكل بوت، في ذاكرة الخادم (تضيع عند إعادة التشغيل) |
| انتظار الرد على الاستدعاء | 10 ثوانٍ |
callback_data · عدد الأزرار | من 1 إلى 64 بايت · 100 زر لكل رسالة |
| الأوامر | من 1 إلى 32 حرفاً من الأحرف اللاتينية الصغيرة والأرقام والشرطة السفلية، والوصف من 1 إلى 256 حرفاً، وبحد أقصى 100 أمر |
| بدء المحادثة من جهة البوت | غير ممكن — يجب أن يرسل الشخص إلى البوت أولاً |
حل المشكلات
| العَرَض | السبب والحل |
|---|---|
401 Unauthorized | الرمز المميّز خاطئ أو تغيّر بسبب /revoke. أرسل /token إلى BotFather للتحقق. |
404 Not Found: method not found | طريقة لا يدعمها Pabal بعد. راجع قائمة الطرق. |
403 Forbidden: bot can't initiate conversation with a user | لم يبدأ ذلك الشخص أي محادثة مع البوت بعد. اطلب منه أن يفتح البوت في التطبيق ويضغط ابدأ. |
409 Conflict: can't use getUpdates method while webhook is active | هناك webhook مضبوط. استدعِ deleteWebhook أو استلم التحديثات عبر webhook. |
| لا يحدث شيء عند الضغط على الزر | البوت متوقف، أو أنه لم يستدعِ answerCallbackQuery. |
| أستلم الرسالة نفسها مراراً | لم ترفع offset. مرّر في الطلب التالي update_id + 1 لآخر تحديث عالجته. |
| تنسيق الغامق والروابط لا يعمل | parse_mode غير مدعوم بعد، فيُرسل النص كما هو. أما الأوامر، والإشارات (@mention)، وعناوين URL، والوسوم (#tag) فتُعرض تلقائياً قابلة للنقر. |
| البوت صامت في المجموعة | البوت ليس عضواً في المجموعة. أضفه من معلومات المجموعة ← إضافة أعضاء. |