لاستضافة بوت TelegramBots (Java) على مدار الساعة 24/7 تشغّله على جهاز يبقى قيد التشغيل دائمًا: إما VPS لينكس مع خدمة systemd تعيد تشغيله عندما يتوقف، وإما خطة بوتات في استضافة بوتات Telegram من PlayNHost (ابتداءً من US$1.99 شهريًا)، حيث ترفع ملف jar واحدًا قابلًا للتشغيل وتلصق الرمز من @BotFather ثم تضغط Start. في اختبارنا استخدم بوت يعمل بـ TelegramBots 10.3.0، وهي مكتبة Java من rubenlagus، نحو 91 MB من الذاكرة على Java 21 وتلقى رد Telegram بعد 1.5 ثانية من تشغيله. استخدم وحدة long polling فيها: ليس لدى خططنا بعد عنوان HTTPS عام لاستخدام webhook. الخطوات على PlayNHost:
- في صفحة استضافة بوتات Telegram اضغط أنشئ سيرفرًا على إحدى الخطط. في نافذة الطلب أجب عن لأي منصة بوتك؟ باختيار Telegram ثم اختر Java.
- على حاسوبك ابنِ البوت باستخدام ملف
pom.xmlأدناه: الأمرmvn packageيكتبtarget/bot.jarوبداخله TelegramBots. - افتح سيرفرك في اللوحة. تُفتح بطاقة إعداد بوتك في نظرة عامة عند الاتصال بـ Telegram؛ ويجب أن تعرض خطوتها الأولى، ما الذي يعمل، العبارة يشغّل هذا البوت Java Bot.
- في الاتصال بـ Telegram الصق الرمز تحت الصق رمز بوتك ثم اضغط الاتصال وتحقق من اسم البوت المعروض واضغط نعم، متابعة.
- في كودك اضغط رفع الملفات وارفع
bot.jarإلى المجلد الرئيسي. - في صفحة بوت وفي لوحة الكود تأكد أن ملف البدء هو
bot.jarوأن بيئة التشغيل هي Java 21 (recommended) أو Java 17 أو 25. إذا غيّرت ملف البدء فاضغط حفظ بجانبه؛ أما بيئة التشغيل الجديدة فتُحفظ بمجرد اختيارها. - اضغط تشغيل البوت وافتح Console. عندما يطبع بوتك
Logged in as @your_botتتحول الشارة في نظرة عامة إلى متصل في Telegram. - في صفحة بوت وفي لوحة Telegram اضغط افتح في Telegram وأرسل إلى بوتك
/start.
إنشاء البوت في @BotFather وخطوات اللوحة موضحة في كيف تستضيف بوت Telegram. تتناول هذه الصفحة TelegramBots نفسها: ما تستهلكه على السيرفر وما ينبغي معرفته قبل استضافتها.
ما الذي قسناه
| المكتبة | الإصدار | الذاكرة بدون حمل | من التشغيل إلى رد Telegram | حجم ملف jar |
|---|---|---|---|---|
| TelegramBots (rubenlagus) | 10.3.0 | 91 MB | 1.5 ث | 9.6 MB |
| Java 21 وحدها بلا مكتبة | 21.0.12.1 | 38 MB | لا يوجد | 0.0 MB |
الطريقة: على عقدتنا الخاصة وفي حاوية مؤقتة مهيأة مثل خطة بوتات بسعة 1 GB (صورة Java 21 وأمر java الدقيق لنوع بوت Java لدينا) استدعى البوت getMe في Telegram برمز مزيف رفضه Telegram؛ والذاكرة هي الذاكرة المقيمة بعد 15 ثانية من ذلك الرد، ويُحسب زمن البدء من التشغيل حتى الرد، وكل رقم هو وسيط التشغيلات من 2 إلى 4.
هذه حدود دنيا: لا محادثات ولا بيانات ولا polling بعد. يُضاف إليها كودك الخاص وما يحتفظ به في الذاكرة وعدد المحادثات، كما يسمح سكربت البدء لـ heap في Java بالنمو حتى 80 بالمئة من الخطة (انظر أدناه). قارن الأرقام بالخطط في استضافة بوتات Telegram واختر بحسب ما يفعله بوتك.
بوت TelegramBots بسيط
يرد على /start ويقرأ الرمز من TELEGRAM_BOT_TOKEN (تعطيه اللوحة لكودك بهذا الاسم وأيضًا باسم BOT_TOKEN وTOKEN وTELEGRAM_TOKEN وTELOXIDE_TOKEN) ويطبع سطر الجاهزية. ملفان:
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>bot</artifactId>
<version>1.0</version>
<properties>
<maven.compiler.release>17</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.telegram</groupId>
<artifactId>telegrambots-longpolling</artifactId>
<version>10.3.0</version>
</dependency>
<dependency>
<groupId>org.telegram</groupId>
<artifactId>telegrambots-client</artifactId>
<version>10.3.0</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>2.0.12</version>
</dependency>
</dependencies>
<build>
<finalName>bot</finalName>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.7.1</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<appendAssemblyId>false</appendAssemblyId>
<archive>
<manifest>
<mainClass>Bot</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
src/main/java/Bot.java
import org.telegram.telegrambots.client.okhttp.OkHttpTelegramClient;
import org.telegram.telegrambots.longpolling.TelegramBotsLongPollingApplication;
import org.telegram.telegrambots.longpolling.util.DefaultLongPollingUpdateConsumer;
import org.telegram.telegrambots.meta.api.methods.GetMe;
import org.telegram.telegrambots.meta.api.methods.send.SendMessage;
import org.telegram.telegrambots.meta.api.objects.Update;
import org.telegram.telegrambots.meta.api.objects.User;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException;
import org.telegram.telegrambots.meta.exceptions.TelegramApiRequestException;
import org.telegram.telegrambots.meta.generics.TelegramClient;
public class Bot extends DefaultLongPollingUpdateConsumer {
private final TelegramClient client;
Bot(TelegramClient client) {
this.client = client;
}
@Override
public void consume(Update update) {
if (update.hasMessage() && update.getMessage().hasText()
&& update.getMessage().getText().startsWith("/start")) {
SendMessage reply = SendMessage.builder()
.chatId(update.getMessage().getChatId())
.text("Hello! I am running on PlayNHost.")
.build();
try {
client.execute(reply);
} catch (TelegramApiException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws Exception {
String token = System.getenv("TELEGRAM_BOT_TOKEN");
if (token == null || token.isBlank()) {
System.out.println("No TELEGRAM_BOT_TOKEN found. Paste your bot token on the Bot page, then restart.");
System.exit(1);
}
TelegramClient client = new OkHttpTelegramClient(token);
User me = null;
try {
me = client.execute(new GetMe());
} catch (TelegramApiRequestException e) {
if (e.getErrorCode() != null && e.getErrorCode() == 401) {
System.out.println("Telegram did not accept the bot token. Paste the current one from @BotFather on the Bot page, then restart.");
System.exit(1);
}
throw e;
}
try (TelegramBotsLongPollingApplication app = new TelegramBotsLongPollingApplication()) {
// Long polling: registerBot removes a webhook left on the bot, then asks Telegram for messages.
app.registerBot(token, new Bot(client));
System.out.println("Logged in as @" + me.getUserName());
Thread.currentThread().join();
}
}
}
ابنِه باستخدام Maven 3.9 وJDK 17 أو أحدث، ثم جرّب ملف jar على حاسوبك:
mvn package
java -jar target/bot.jar
بدون رمز يطبع No TELEGRAM_BOT_TOKEN found. ثم يتوقف، وهذا يثبت أن ملف jar يبدأ ويجد فئته الرئيسية. ارفع target/bot.jar. أوقف أي نسخة تشغّلها على حاسوبك بالرمز الحقيقي قبل تشغيل النسخة على السيرفر، وإلا تتلقى النسختان أخطاء 409 Conflict من Telegram.
الاستدعاء getMe يتحقق من الرمز قبل أن يبدأ polling ويعطي اسم مستخدم البوت لسطر الجاهزية. السطر Logged in as @your_bot هو الذي يحوّل الشارة إلى متصل في Telegram.
إذا كان الرمز خاطئًا
في اختبارنا، ومع رمز مزيف، فشل استدعاء getMe في TelegramBots بهذا الخطأ:
TelegramApiRequestException: Error executing org.telegram.telegrambots.meta.api.methods.GetMe query: [401] Unauthorized
يلتقط البوت أعلاه هذا الرفض (رمز الخطأ 401) ويطبع بدلًا منه Telegram did not accept the bot token. Paste the current one from @BotFather on the Bot page, then restart. تقرأ اللوحة هذا السطر وتعرض التنبيه لم يقبل Telegram رمز بوتك فوق Console. للإصلاح أرسل في @BotFather الأمر /mybots واختر بوتك ثم API Token وانسخ الرمز من جديد. في صفحة بوت وفي لوحة Telegram اضغط استبدال الرمز والصقه واضغط حفظ الرمز ثم إعادة التشغيل الآن.
ما ينبغي معرفته عن TelegramBots على السيرفر
- الإصدارات: صدر TelegramBots 10.3.0 في 7 سبتمبر 2026 ويدعم Bot API 10.3 من Telegram. يحتاج إلى Java 17 أو أحدث، لذا تشغّله كل بيئة التشغيل تعرضها اللوحة (Java 17 أو 21 أو 25).
- حزمتان، بخلاف الشروحات القديمة. منذ الإصدار 7.0.0 (مارس 2024) تأتي المكتبة في
telegrambots-longpollingالذي يستقبل الرسائل وtelegrambots-clientالذي يرسلها. الشروحات التي توسّعTelegramLongPollingBotكُتبت للحزمة القديمةtelegrambotsالتي صدرت آخر مرة بالإصدار 6.9.7.1؛ وهذه الفئة غير موجودة في 10.3.0، فلا يُترجم كودها معه. - استخدم long polling. للمكتبة وحدة webhook أيضًا، لكن webhook يحتاج إلى عنوان HTTPS عام لا تشمله خططنا بعد. يستدعي
registerBotفي وحدة long polling الدالةdeleteWebhookقبل أن يبدأ، فيُزال أي webhook تركه مضيف قديم وتبقى الرسائل المنتظرة. للانتقال من مضيف يستخدم webhook: كيف تنقل بوت Telegram إلى PlayNHost. - أضف مكتبة سجلات وإلا بقيت المكتبة صامتة. يكتب TelegramBots سجلاته عبر SLF4J. وإذا لم يوجد مزوّد SLF4J في ملف jar لديك طبع SLF4J تحذيرًا مرة واحدة ثم تجاهل كل سطر سجل من المكتبة، بما فيها أخطاء polling. يضيف
pom.xmlأعلاهslf4j-simpleالذي يكتب أسطر المكتبة من مستوى INFO فما فوق إلى مخرج الأخطاء القياسي، فتظهر في Console. - أخطاء polling تُعاد محاولتها ولا تُرمى. عندما يفشل استدعاء
getUpdatesيسجل TelegramBots الرسالةError received from Telegram GetUpdates Request, retrying in ... millisويحاول مجددًا، فتستمر العملية في العمل. يبدأ الانتظار من نحو نصف ثانية ويزيد بمقدار النصف في كل مرة حتى نحو دقيقة (مع تباين عشوائي حتى 90 ثانية)؛ وبعد مرور 15 دقيقة دون استدعاء ناجح ينتظر 15 دقيقة بين المحاولات. لذا أعد تشغيل البوت بعد إصلاح السبب ولا تنتظر. رمز حالة HTTP وحده، في سطرCaused byمن تتبع المكدس تحته، يخبرك بما حدث؛ أما وصف Telegram نفسه للخطأ فلا يُطبع. وبما أنregisterBotأزال أي webhook فعلًا، فإن 409 هناك يعني على الأرجح أن نسخة أخرى من البوت تعمل بـ polling بالرمز نفسه: أوقفها. انظر إصلاح خطأ 409 Conflict في بوت Telegram. - الدرس الرسمي بعد تحديثه: ينفّذ
LongPollingSingleThreadUpdateConsumerالذي يعدّه 10.3.0 مهجورًا لصالح الفئةDefaultLongPollingUpdateConsumerالمستخدمة أعلاه؛ وكلاهما يعالج التحديثات واحدًا واحدًا في خيط خلفي. سطر الجاهزية فيهMyAmazingBot successfully started!لا يحوّل الشارة إلى متصل في Telegram: اطبع سطرًا يبدأ بـLogged in asكما في الأعلى. - اجعل
main()في حالة انتظار. يعمل polling على خيوط المكتبة الخاصة؛ ينهي الدرسmain()بالاستدعاءThread.currentThread().join()كي لا ينتهي البرنامج، والبوت أعلاه يفعل الشيء نفسه. - حد الذاكرة: يشغّل سكربت البدء Java مع
-XX:MaxRAMPercentage=80.0ومجمّع النفايات G1، فيمكن لـ heap استخدام ما يصل إلى 80 بالمئة من ذاكرة خطتك. وإذا امتلأ طبعت Java الرسالةjava.lang.OutOfMemoryErrorوعرضت اللوحة نفدت ذاكرة بوتك. - ملف jar واحد ولا شيء يُثبَّت على السيرفر. يشغّل نوع بوت Java الأمر
java -jarعلى ملف البدء ولا يملك حقل الحزم، لذا يجب أن يكون كل شيء داخل ملف jar. ارفع ملف jar جديدًا لتحديث البوت.
استضفه بنفسك على VPS لينكس
لا يحتاج VPS إلا إلى بيئة تشغيل Java، لأنك تبني ملف jar على حاسوبك. على Debian 13 أو Ubuntu 24.04 ثبّت Java 21؛ أما Debian 12 فيأتي مع Java 17 التي تشغّل ملف jar أعلاه أيضًا:
sudo apt update
sudo apt install openjdk-21-jre-headless
java -version
أنشئ مستخدمًا للبوت وانسخ ملف jar إلى السيرفر (مثلًا بالأمر scp) ثم إلى مجلده:
sudo useradd --system --create-home --home-dir /opt/mybot mybot
sudo cp bot.jar /opt/mybot/
sudo chown -R mybot: /opt/mybot
أبقِ الرمز خارج كودك، في ملف لا يستطيع قراءته إلا root:
sudo sh -c 'echo "TELEGRAM_BOT_TOKEN=123456789:your-token" > /etc/mybot.env'
sudo chmod 600 /etc/mybot.env
أنشئ الملف /etc/systemd/system/mybot.service:
[Unit]
Description=TelegramBots Telegram bot
Wants=network-online.target
After=network-online.target
[Service]
User=mybot
WorkingDirectory=/opt/mybot
EnvironmentFile=/etc/mybot.env
ExecStart=/usr/bin/java -XX:MaxRAMPercentage=80.0 -jar /opt/mybot/bot.jar
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
شغّله الآن وعند كل إقلاع، ثم تابع مخرجاته:
sudo systemctl daemon-reload
sudo systemctl enable --now mybot
sudo journalctl -u mybot -f
الإعداد Restart=always يعيد تشغيل البوت بعد 5 ثوانٍ من انتهائه أو تعطله، لكن ليس بعد أن توقفه بالأمر systemctl stop. على VPS يكون -XX:MaxRAMPercentage نسبة من ذاكرة الجهاز كله، فخفّضه إن كانت هناك برامج أخرى تعمل عليه. للتحديث انسخ ملف jar الجديد فوق القديم ونفّذ sudo systemctl restart mybot.
الاستضافة الذاتية أو خطة بوتات
على VPS تديره بنفسك تتولى:
- تحديثات نظام التشغيل وأمانه، وترقيات Java.
- نسخ كل ملف jar جديد وملف الخدمة وملف الرمز وصلاحياته.
- قراءة
journalctlلمعرفة سبب توقف البوت أو توقفه عن الرد. - النسخ الاحتياطية لكل ما يخزنه بوتك.
وفي المقابل يشغّل VPS أي شيء، ويمكنك أن تمنحه نطاقًا مع HTTPS لاستخدام webhook.
في خطة بوتات من PlayNHost تتولى اللوحة ذلك عنك:
- Java 17 أو 21 أو 25 من قائمة اختيار، مع ضبط حد heap ومجمّع النفايات.
- الرمز، يُتحقق منه لدى Telegram قبل حفظه، ويُخزَّن مشفرًا ويُعطى لكودك بخمسة أسماء.
- إعادة تشغيل البوت بعد التعطل. وإذا تعطل مجددًا خلال دقيقة بقي متوقفًا وذكرت Console السبب.
- زر إزالة الـ webhook في لوحة Telegram وتنبيهات فوق Console تسمّي السبب، مثل رمز مرفوض أو نقص في الذاكرة.
- الرفع من المتصفح والنسخ الاحتياطية من اللوحة.
أسئلة يطرحها الناس
بوت TelegramBots الخاص بي يعمل لكنه لا يرد ولا يطبع شيئًا. لماذا؟
في الغالب لا يحتوي ملف jar على مزوّد SLF4J، فتُهمل أسطر الأخطاء الخاصة بالمكتبة بينما تواصل إعادة المحاولة. أضف slf4j-simple كما في pom.xml أعلاه وأعد البناء وانظر في Console. تكرار 409 يعني أن نسخة أخرى من البوت تعمل بـ polling بالرمز نفسه؛ وتكرار 401 يعني أن الرمز أُلغي في @BotFather. وبعد الإصلاح أعد تشغيل البوت: قد يصل انتظار TelegramBots بين المحاولات إلى 15 دقيقة.
هل يمكنني استخدام وحدة webhook في TelegramBots؟
ليس على خططنا بعد: يحتاج webhook إلى عنوان HTTPS عام وهي لا تشمله. أما long polling فلا يحتاج إلى شيء من ذلك لأن البوت نفسه يطلب الرسائل الجديدة من Telegram. استخدم telegrambots-longpolling كما في هذه الصفحة.
هل يحتاج TelegramBots إلى خطة أكبر من بوت Python أو Node.js؟
ليس بسبب المكتبة نفسها. في الاختبار نفسه وبالطريقة نفسها استخدم TelegramBots 91 MB واستخدم python-telegram-bot 22.8 ما مقداره 44 MB واستخدم grammY 1.46.0 ما مقداره 60 MB واستخدم aiogram 3.31.0 ما مقداره 173 MB، وكلها أقل بكثير من 0.5 GB في أصغر خطة. وما يحتفظ به بوتك في الذاكرة هو الذي يحسم الباقي. وفي Java تتوقف الذاكرة أيضًا على heap: يسمح سكربت البدء بنموه حتى 80 بالمئة من الخطة، ويقرر مجمّع النفايات مقدار ما يُستخدم منها.
أي إصدار من Java أختار؟
Java 21 وهو الموصى به، ما لم يحتج كودك إلى 25. يحتاج TelegramBots 10.3.0 إلى Java 17 أو أحدث. ابنِ باستخدام release ليس أحدث من بيئة التشغيل التي تختارها: ملف jar مبني لإصدار Java أحدث يتوقف مع UnsupportedClassVersionError.
هل أنت مستعد لتشغيل بوت TelegramBots على مدار الساعة؟ شاهد الخطط في استضافة بوتات Telegram.



