جديد 📢 عرض الإطلاق لفترة محدودة: خصم حتى 70% على شهرك الأول في كل لعبة.عرض الباقات

كيف تستضيف بوت TelegramBots (Java) على مدار الساعة 24/7

استضافة بوتات TelegramUpdated Nov 6, 202611 min read

لاستضافة بوت 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:

  1. في صفحة استضافة بوتات Telegram اضغط أنشئ سيرفرًا على إحدى الخطط. في نافذة الطلب أجب عن لأي منصة بوتك؟ باختيار Telegram ثم اختر Java.
  2. على حاسوبك ابنِ البوت باستخدام ملف pom.xml أدناه: الأمر mvn package يكتب target/bot.jar وبداخله TelegramBots.
  3. افتح سيرفرك في اللوحة. تُفتح بطاقة إعداد بوتك في نظرة عامة عند الاتصال بـ Telegram؛ ويجب أن تعرض خطوتها الأولى، ما الذي يعمل، العبارة يشغّل هذا البوت Java Bot.
  4. في الاتصال بـ Telegram الصق الرمز تحت الصق رمز بوتك ثم اضغط الاتصال وتحقق من اسم البوت المعروض واضغط نعم، متابعة.
  5. في كودك اضغط رفع الملفات وارفع bot.jar إلى المجلد الرئيسي.
  6. في صفحة بوت وفي لوحة الكود تأكد أن ملف البدء هو bot.jar وأن بيئة التشغيل هي Java 21 (recommended) أو Java 17 أو 25. إذا غيّرت ملف البدء فاضغط حفظ بجانبه؛ أما بيئة التشغيل الجديدة فتُحفظ بمجرد اختيارها.
  7. اضغط تشغيل البوت وافتح Console. عندما يطبع بوتك Logged in as @your_bot تتحول الشارة في نظرة عامة إلى متصل في Telegram.
  8. في صفحة بوت وفي لوحة Telegram اضغط افتح في Telegram وأرسل إلى بوتك /start.

إنشاء البوت في @BotFather وخطوات اللوحة موضحة في كيف تستضيف بوت Telegram. تتناول هذه الصفحة TelegramBots نفسها: ما تستهلكه على السيرفر وما ينبغي معرفته قبل استضافتها.

ما الذي قسناه

المكتبةالإصدارالذاكرة بدون حملمن التشغيل إلى رد Telegramحجم ملف jar
TelegramBots (rubenlagus)10.3.091 MB1.5 ث9.6 MB
Java 21 وحدها بلا مكتبة21.0.12.138 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.

بوتك مستضاف في مكان آخر بالفعل؟ انقله إلينا

أحدث مقالات المدونة