ویرگول
ورودثبت نام
امیرحسین ناظوری
امیرحسین ناظوری📕 عاشق یادگیری و به اشتراک‌گذاری دانش -- آیدی من تو شبکه های اجتماعی : mrNazouri13
امیرحسین ناظوری
امیرحسین ناظوری
خواندن ۲۲ دقیقه·۱۰ ماه پیش

آموزش ساخت ربات تلگرام با پایتون (از صفر) - 2025

سلام وقت همگی بخیر باشه 🖐
من امیرحسین ناظوریام و خیلی خوش اومدید به آموزش ساخت ربات تلگرام با پایتون.
برای شروع فقط کافیه با پایتون آشنایی داشته باشین و بقیش رو بسپارین به من.
(مطالب جدید به مقاله اضافه شد)

خیلی سریع بریم برای شروع آموزش و نظرت چیه که از ابتدایی ترین مسائل آموزش رو شروع کنیم؟

تلگرام یه برنامه پیام رسانه و یه ویژگی داره به اسم ربات.
ما ربات هارو طراحی میکنیم تا طبق برنامهایی که دارن یکسری کارها و خدماتی رو ارائه بدن! حالا این ربات میتونه هم بصورت فیزیکی وجود داشته باشه و هم بصورت مجازی (مثل ربات های تلگرام)

فرضا رباتی وجود داره که هرموقع بهش پیام میدی یه جُک برات میفرسته! وقتی من به ربات پیام رو ارسال میکنم، در اصل پیامم میره سمت سرورهای تلگرام و تلگرام پیام رو دریافت میکنه، حالا تلگرام طبق راه ارتباطی که با ربات مدنظرم داره پیام رو برای ربات میفرسته، ربات پیام رو دریافت میکنه، طبق قوانینی که براش تعریف شده یه پاسخی رو آماده میکنه و میفرسته سمت تلگرام، حالا تلگرام دوباره اون پیام رو برای من (از سمت ربات) میفرسته.

درنهایت، ربات ها برای اینکه بتونن پیام هارو بگیرن و جواب بدن باید با تلگرام صحبت کنن! این کار از طریق چیزی به اسم API انجام میشه. API چیه؟ اگه بخوام ساده بگم، مثل یک راه دو طرفه بین تلگرام و ربات هاست تا بتونن صحبت کنن و یکسری موارد رو بین همدیگه منتقل کنن. تلگرام راه ارتباطیش با رباتها (که از طریق API ها ایجاد شده) رو به 2 حالت پیاده سازی کرده:
Polling: اگه رباتی که طراحی کردم از این روش استفاده کرده باشه، هر چند ثانیه یکبار به واسطه API به تلگرام وصل میشه تا ببینه پیام جدیدی اومده یا نه.
Webhook: اگه رباتی طبق این حالت پیاده سازی شده باشه، کاری انجام نمیده و هرموقع پیامی به ربات ارسال بشه، خود تلگرام اون پیام رو به ربات تحویل میده.
تو این آموزش از حالت ارتباطی Polling استفاده میکنیم.

نقش زبان های برنامه نویسی در طراحی ربات های تلگرام؟!
ربات ها کلا با زبان های برنامه نویسی ساخته و مدیریت میشن. در اصل ربات فقط با API کار میکنه، یعنی یه پیامی رو از تلگرام به واسطه API دریافت میکنه، حالا من برنامه نویس با مثلا پایتون باید بیام این پیام رو دریافت کنم و تعیین کنم که چه پاسخی باید درمقابلش ارسال کنم. مثال میزنم! میگم هرموقع دستور start/ اومد، این متن رو برای کاربر بفرست : سلام خوش اومدی 🖐

تو این آموزش قراره با pyTelegramBotAPI یا همون telebot که یکی از کتابخونههای نسبتا ساده و معروف پایتون برای ساخت ربات تلگرام هست، کار کنیم.

(آیدی من تو تمام شبکه های اجتماعی: mrNazouri13@)

اولین قدم | BotFather
هرکسی که اکانت تلگرام داره خیلی راحت میتونه وارد ربات BotFather بشه و یک رباتی رو با اسم و آیدی مدنظرش ایجاد کنه. وقتی ربات ایجاد بشه یک Token دریافت میکنیم! این Token بهمون اجازه میده تا از API تلگرام استفاده کنیم و رباتمون رو به تلگرام بشناسونیم (هر ربات یک Token منحصر به فرد داره و تلگرام بدون این توکن نمیتونه بفهمه کد نوشته شده مربوط به کدوم رباته)

(الان فرض میگیرم که شما وارد BotFather شدید و رباتتون رو ایجاد کردید و الان Token ربات رو دارید)

cmd رو باز کن و دستور زیر رو وارد کن (به حروف بزرگ و کوچیک دقت کن):

pip install pyTelegramBotAPI

با این دستور کتابخونه برامون نصب میشه و میتونیم ازش استفاده کنیم.

من یه فایل به اسم bot.py ایجاد کردم و داخلش مینویسم:

import telebot

با اینکار کتابخونهایی که نصب کردم رو به پروژم اضافه میکنم.

به کد زیر دقت کن:

import telebot bot = telebot.TeleBot("8199750813:AAEfI2T276mA1tAgcsiuLp9PAcBFAsAYvXE") bot.polling()

تو خط دوم یه Object به نام bot از کلاس TeleBot ایجاد کردم و برای آرگومانش، توکن رباتم رو نوشتم.
از این به بعد اگه دستوری خواستم به ربات بدم یا کلا هر تعاملی اگه بخوام با ربات داشته باشم، باید شی bot رو صدا بزنم.
تو خط آخر Object ایجاد شده رو صدا زدم و متد polling رو فراخانی کردم. متد polling ربات رو فعال میکنه و یعنی مدام به تلگرام وصل میشه ببینه پیام جدیدی اومده یا نه (وقتی متد polling فراخانی میشه، برنامه وارد یک حلقه بینهایت میشه و منتظر میمونه پیام هایی از تلگرام دریافت بشه تا بهشون واکنش نشون بده)
اما الان هیچ شرط یا دستوری ننوشتم و صرفا ربات رو فعال کردم که خب طبیعتا کار خاصی انجام نمیشه و فقط خواستم با این چند خط آشنا بشید.
در کنار متد polling یه متد دیگه وجود داره به اسم infinity_polling
polling: این متد یه حلقه polling شروع میکنه و پیامها رو چک میکنه. ولی اگه خطایی پیش بیاد (مثلا به خاطر قطعی اینترنت یا خطای سرور) ممکنه این حلقه متوقف بشه.
infinity_polling: این متد هم مثل polling کار میکنه ولی با یه تفاوت مهم؟! خطاها رو مدیریت میکنه. اگه خطایی پیش بیاد، اون خطا رو میگیره و polling رو دوباره فعال میکنه تا ربات همیشه فعال بمونه. درنهایت، infinity_polling مقاوم تره.


به کد زیر دقت کنید :

import telebot bot = telebot.TeleBot('8199750813:AAEfI2T276mA1tAgcsiuLp9PAcBFAsAYvXE') @bot.message_handler(commands = ["start"]) def welcome(message): bot.send_message(message.chat.id, "سلام. حالت چطوره؟") bot.infinity_polling()

خط 5 یه دکوراتور داریم که بالای تابع welcome قرار گرفته (دکوراتور اینطوریه که تابع پایینش رو وقتی صدا میزنه که شرط داخلش درست باشه)
ابتدا @ گذاشتم که نشانه دکوراتور ها در پایتونه، سپس متد message_handler رو از شی bot صدا زدم. این متد وظیفش تعیین کردن شرط دریافت پیام هاست. داخل این متد پارامتر commands = ['start'] رو قرار دادم که یعنی تابع welcome رو فقط مواقعی فراخانی کن که command یا دستور start ارسال بشه.
داستان تابع welcome چیه؟
وقتی ربات تلگرام پیام رو دریافت میکنه، کتابخونه telebot اون دادهها رو از تلگرام میگیره. سپس این کتابخونه دادهها رو تبدیل میکنه به یه Object از یه کلاس مشخص که شامل همهی اطلاعات پیام هست. این شی رو بعدا به عنوان پارامتر به تابع handler (اینجا تابع welcome) میده. بزار ساده تر بگم:
- وقتی کاربر دستور start/ رو میفرسته، تلگرام اطلاعات پیام رو به صورت یک JSON برمیگردونه.
- کتابخونه telebot اون JSON رو میگیره و اون رو تبدیل میکنه به یه شی از کلاس telebot.types.Message
- دکوراتور bot.message_handler(commands = ['start'])@ باعث میشه که هر وقت پیام حاوی دستور start/ دریافت بشه، کتابخونه telebot تابع welcome رو صدا بزنه و به عنوان ورودی، شی Message رو بهش بده. به عبارت دیگه، تابع welcome بطور خودکار یه پارامتر به نام message دریافت میکنه که از کلاس telebot.types.Message ساخته شده.
داخل بدنه تابع شی bot رو صدا زدم، متد send_message رو فراخانی کردم (از اسمش معلومه چیکار میکنه) برای آرگومان اولش از همون message که اطلاعات پیام داخلش هست استفاده کردم و chat id طرف ارسال کننده رو قرار دادم تا پیام به اون ارسال بشه، سپس برای آرگومان دوم پیامی که میخوام ارسال بشه رو نوشتم.

با توجه به کدهای بالا دوتا نکته بگم.
نکته اول: ما میتونیم دو یا چند دستور رو تعیین کنیم که وقتی حتی یکی از این دستورها ارسال شد، تابع مد نظر فراخانی بشه. مثال:

import telebot bot = telebot.TeleBot("8199750813:AAEfI2T276mA1tAgcsiuLp9PAcBFAsAYvXE") @bot.message_handler(commands = ["start", "hi"]) def welcome(message): bot.send_message(message.chat.id, "سلام. حالت چطوره؟") bot.infinity_polling()

الان اگه start/ یا hi/ رو به ربات ارسال کنم، تابع welcome اجرا میشه.

نکته دوم: میتونم بجای متد send_message از متد reply_to استفاده کنم. کد:

import telebot bot = telebot.TeleBot("8199750813:AAEfI2T276mA1tAgcsiuLp9PAcBFAsAYvXE") @bot.message_handler(commands = ["start", "hi"]) def welcome(message): bot.reply_to(message, "سلام") bot.infinity_polling()

متد reply_to برای مواقعی استفاده میشه که من میخوام به همون پیامی که سمتم اومده پاسخ بدم (قطعا با reply داخل تگلرام آشنا هستید) اگه بیام start/ رو بفرستم، ربات میتونه مستقیما به همون پیام پاسخ بده و توی تلگرام نشون بده که این جواب برای این پیام خاصه. این متد هم دوتا آرگومان میخواد. آرگومان اول message هست که یعنی اطلاعات پیامی رو بهش دادم که سمت ربات اومده، یعنی اینجا متد reply_to اطلاعات اون پیام رو از message بدست میاره و به همون، متن مد نظر رو که داخل آرگومان دوم دادم ارسال میکنه.

به کد زیر دقت کنید :

@bot.message_handler(func = lambda msg : True) def echo_message(message): bot.reply_to(message, message.text)

اینجا داخل آرگومان مربوط به دکوراتور از func استفاده کردم. اما دقیقا چیه و چکاری انجام میده؟
تو مثال قبلی از commands استفاده کرده بودیم که یعنی هرموقع دستوری اجرا شد بیاد بررسی کنه که آیا مطابقت داره با دستورهایی که دادیم یا نه اگه یکی بودن تابع اجرا میشد. اما اینجا من از func استفاده کردم. func بهم اجازه میده که یه تابع ایجاد کنم و داخل اون هرچقدر خواستم پیام رو بررسی کنم و درنهایت یا True برگردونم یا False که اگه True برگردونم تابع echo_message (در این مثال) اجرا میشه.
حالا من اومدم از lambda msg : True استفاده کردم. این تابع که با lambda ساخته شده هیچ کار خاصی انجام نمیده و صرفا مقدار True رو (در هر شرایطی) برمیگردونه که این یعنی من هرپیامی ارسال کنم، تابع echo_messsage اجرا میشه.
به کد زیر دقت کن:

import telebot bot = telebot.TeleBot("8199750813:AAEfI2T276mA1tAgcsiuLp9PAcBFAsAYvXE") @bot.message_handler(commands = ["start", "hi"]) def welcome(message): bot.reply_to(message, "سلام") @bot.message_handler(func = lambda msg : True) def echo_message(message): bot.reply_to(message, message.text) bot.send_message(message.chat.id, "اینم برای تست") bot.infinity_polling()

دکوراتور اول مشخص کرده که اگه دستورات start/ و hi/ ارسال شدن، تابع welcome فراخانی بشه، دکوراتور دوم تعیین کرده هرچیزی (متنی) که به ربات ارسال شد تابع echo_message فراخانی بشه. البته اگه start/ و hi/ ارسال بشن تابع welcome اجرا میشه چون دکوراتور اون اول تعریف شده اما هرچیزی غیر از این دوتا بصورت متنی ارسال بشه تابع echo_message فراخانی میشه.
داخل تابع echo_message اومدم همون پیامی که کاربر فرستاده رو براش reply کردم (با message.text) و بعدش برای تمرین اومدم از متد send_message هم استفاده کردم و یک پیام دیگه بصورت جدا (یعنی reply نمیشه) براش ارسال کردم.

با توجه به کد بالا دو تا سوال ممکنه مطرح بشه که بریم بررسیشون کنیم.
1 - چرا دکوراتور دومی که ساختیم فقط برای متن عمل میکنه؟ یعنی چرا وقتی عکس ارسال میکنم، همون رو برام برنمیگردونه؟ کتابخونهی telebot بهطور پیشفرض فقط پیامهای متنی رو به handlerهایی که با دکوراتور bot.message_handler@ تعریف میشن میده.

2 - چطور یک تابع جدا ایجاد کنم، و داخل آرگومان func از دکوراتور message_handler قرار بدم تا پیام ارسال شده رو دقیق تر بررسی کنم و یا True یا False برگردونم؟

def is_hello_message(message): return "سلام" in message.text @bot.message_handler(func = is_hello_message) def reply_hello(message): bot.reply_to(message, "سلام! چطوری؟ 😊")

تابع is_hello_message بررسی میکنه که پیام شامل (سلام) هست یا نه. اگه پیام شامل سلام باشه، مقدار True برمیگردونه و تابع reply_hello اجرا میشه. یه مثال دیگه:

def is_numeric(message): return message.text.isdigit() # بررسی میکنه که آیا متن فقط شامل عدد هست @bot.message_handler(func = is_numeric) def reply_number(message): bot.reply_to(message, f"شما عدد {message.text} رو فرستادید")



هر پیام در تلگرام میتونه محتوای مختلفی مثل (متن، عکس، استیکر و...) داشته باشه. مقدار content_type به شما میگه نوع محتوای پیام چیست. مثال:

message.content_type == "photo" # اگر کاربر یک عکس بفرستد message.content_type == "sticker" # اگر کاربر یک استیکر بفرستد

چطوری از content_type استفاده کنیم؟

@bot.message_handler(content_types = ["photo"]) def photo(message): bot.reply_to(message, "چه عکس زیبایی") @bot.message_handler(content_types = ["video"]) def video(message): bot.reply_to(message, "بعدا ویدیویی که فرستادی رو میبینم") @bot.message_handler(content_types = ["sticker"]) def stiker(message): bot.reply_to(message, "استیکر هم بلدی بفرستی؟")

برخی از مقادیری که برای content_types وجود داره:

[text - photo - video - audio - document - voice - sticker]

نکته. میتونیم چندتا content type رو باهم مشخص کنیم. مثال:

@bot.message_handler(content_types = ['video', 'photo'])


برخی از مقادیری که داخل content_types وجود دارن به رویداد ها مربوط میشه. برای مثال:

new_chat_members : وقتی کاربر جدیدی به گروه اضافه میشه left_chat_member : وقتی کاربری گروه را ترک میکنه


به کد زیر دقت کن :

@bot.message_handler(content_types = ["text"]) def result_message(message): bot.reply_to(message, message)

ربات رو اجرا میکنم و کلمه salam رو براش ارسال میکنم. ربات مقدار شی message رو برام برمیگردونه. این شی اطلاعات پیام رو داخلش نگه میداره. الان بریم بیینیم چه اطلاعاتی داخل این شی وجود داره.
(چون حجم متن خروجی خیلی بالاست فایل مربوطه رو داخل کانال تلگرامم گذاشتم. کلیک کنید)
به کد زیر دقت کن:

@bot.message_handler(content_types = ["text"]) def result_message(message): bot.send_message(message.chat.id, message.text)

به آرگومان اول send_message دقت کن. نوشتم message.chat.id که یعنی از message که یک شی هست استفاده کن، وارد chat شو (خط 31 عکس) از داخل اون هم id رو بردار که در اصل Chat ID کاربر اونجا قرار داره.

شما خیلی راحت میتونی این مقدار هارو بررسی کنی و داخل شرط ها ازشون استفاده کنی (مثال میزنم، من یه ربات نوشتم که فقط میخوام وقتی خودم start زدم پاسخ بده، دراین حالت باید برای ربات تعیین کنم که هرموقع دستور start توسط آیدی عددی فلان زده شد اون موقع پاسخ بده و هر آیدی عددی دیگه اگه start زد پاسخ نده)


بیا یکم دقیق تر بررسی کنیم که message_handler چه فیلترهایی داره (فیلترها مشخص میکنن چه پیامهایی باید توسط این هندلر پردازش بشن. هر هندلر میتونه چندین فیلتر داشته باشه):

content_types # content_types=["text", "photo"] # فقط پیامهای متنی یا عکس را پردازش کن regexp # regexp=r"^سلام" # فقط پیامهای متنی که با "سلام" شروع میشوند را پردازش کن. commands # commands=["start", "help"] # فقط دستورات /start یا /help را پردازش کن. chat_types # chat_types=["private", "group"] # فقط پیامهای ارسال شده در چتهای خصوصی یا گروهی را پردازش کن. func # func=lambda m : m.text == "سلام" # فقط پیامهایی که تابع شما تورو برگرداند را پردازش کن.

مثال ترکیب چندتا فیلتر:

@bot.message_handler(commands=["start"], chat_types=["private"]) def send_welcome(message): bot.reply_to(message, "سلام! به ربات خوش آمدید.")


یه مثال دیگه:

@bot.message_handler(func=lambda m: m.from_user.id == 12345) def handle_admin(message): bot.reply_to(message, "شما ادمین هستید!")


به کد زیر دقت کن:

@bot.message_handler(func = lambda msg : msg.text == "سلام امیرحسین") @bot.message_handler(func = lambda msg : msg.text == "✔") def hi_or_emoji(message): bot.send_message(message.chat.id, "13")

اینجا دوتا decorator گذاشتم و اگه یکی از اونها هم درست در بیاد، تابع hi_or_emoji اجرا میشه.

یه مثال برای درک بهتر:

@bot.message_handler(content_types = ["document", "audio"]) def doc_or_audio(message): if message.audio: bot.reply_to(message, "تو یک صدا ارسال کردی") elif message.document: bot.reply_to(message, "تو یک داکیومنت ارسال کردی")


به کد زیر دقت کن:

@bot.message_handler(content_types = ["document"])

تلگرام یه قانون ساده داره و میگه هر فایلی که عکس، ویدیو، صدا یا استیکر نباشه، به عنوان document شناخته میشه. حالا من کد بالا رو نوشتم ولی میخوام اگه یک فایل متنی (txt) به ربات ارسال شد واکنش نشون بدم. یعنی کاربر ممکنه اشتباها pdf بفرسته ولی همچنان به عنوان document شناخته بشه. راه حل چیه؟
MIME Type: استانداردی برای شناسایی نوع فایل براساس محتوای آن (نه صرفا پسوند). مثال:

text/plain (فایل متنی ساده) image/jpeg (عکس JPEG) application/pdf (فایل PDF)

چطور از MIME Type استفاده کنم؟

@bot.message_handler(content_types=["document"]) def handle_docs(message): if message.document.mime_type == "application/pdf": bot.reply_to(message, "شما یک PDF فرستادید!") elif message.document.mime_type == "image/jpeg": bot.reply_to(message, "شما یک عکس JPEG فرستادید!")

انواع MIME
متن (Text):
text/plain: فایل متنی ساده txt
text/html: فایل های html
text/css: فایل های css

تصاویر (Image):
image/jpeg: عکس های jpg و jpeg
image/png: عکس های png
image/webp: عکس های webp

اسناد (Application):
application/pdf: فایل های pdf
application/msword: فایل های doc
application/zip: فایل های zip

صوت و ویدیو (Media):
audio/mpeg: فایل های mp3
video/mp4: ویدیو های mp4

من برای ربات یه فایل پایتونی فرستادم و مقدار mime_type برابر شد با text/x-python که در کل خودتون باید ببینید مقدار فایل هایی که میخواین فیلتر کنید چیه.


به کد زیر دقت کن:

@bot.edited_message_handler(filters)

این دکوراتور به ربات میگه هر وقت کسی پیامی که قبلا فرستاده رو ویرایش کرد، تابع زیر من رو اجرا کن. مثال:

@bot.edited_message_handler() def msg_edit(message): bot.reply_to(message, "هواسم بود ویرایش کردی")

داخل پرانتز edited_message_handler میتونم یسری شرط های اضافی رو تنظیم کنم که مثلا اگه پیام متنی بود و فلان کلمه هم داخلش بود و اگه اون، ویرایش شد اون موقع واکنش نشون بده. مثال:

@bot.edited_message_handler(func = lambda message : message.text == "خداحافظ") def msg_edit(message): bot.reply_to(message, "چرا خداحافظی کردی؟")

تو کد بالا اگه متن پیامی به خداحافظ تغییر کنه تابع msg_edit فراخانی میشه (از امثال این دکوراتورها میشه تو گروه ها هم استفاده کرد)

به کد زیر دقت کن:

@bot.channel_post_handler(filters)

این دکوراتور به ربات میگه هر وقت یه پست توی یه کانال تلگرامی که من ادمینشم ارسال بشه، تابع زیر من رو اجرا کن. مثال:

@bot.channel_post_handler() def channel_post(post): bot.send_message(5412199093, "یه پست جدید توی کانال دیدم")

میتونیم برای این دکوراتور فیلترهایی هم تعریف کنیم که اگه چیزی قرار ندیم به همهی پست ها واکنش نشون میده.
تابعی که زیر دکوراتور قرار گرفته یه پارامتر میگیره که معمولاً اسمش رو post میزارن. این post یه شی از کلاس telebot.types.Message هست و اطلاعات پست رو داره. مثل:
نوع محتوا: مثلا متن، عکس یا ویدیو.
متن پست (اگه متنی داشته باشه)
شناسه چت (post.chat.id): شماره کانالی که پست توش فرستاده شده.
کانال های تلگرامی یک شناسهایی دارند که یکتاست (مثل کاربرها که هرکدوم آیدی منحصر به فرد خودشون رو دارن) حالا من با post.chat.id میتونم شناسه اون کانال رو بدست بیارم و اگه پستی بخوام داخل اون کانال بفرستم با این شناسه میتونم. مثال:

bot.send_message(post.chat.id, "این پست داخل کانال تلگرام ارسال شد")


به دکوراتور زیر دقت کن:

@bot.edited_channel_post_handler(filters)

این دکوراتور میگه هر وقت یه پست توی کانال تلگرامی که من ادمینشم ویرایش بشه، تابع زیر من رو اجرا کن.

ReplyKeyboardMarkup چیه؟
ReplyKeyboardMarkup یه کلاس توی telebot هست که بهت اجازه میده یه کیبورد سفارشی، پایین چت کاربر نمایش بدی. یعنی به جای اینکه کاربر متن تایپ کنه، با زدن دکمههای نمایش داده شده، گزینههای از پیش تعریف شده رو انتخاب کنه. مثال:

چطور ازش استفاده کنیم؟

import telebot from telebot import types # برای استفاده از کلاسهای مربوط به کیبورد bot = telebot.TeleBot("Token")

میخوایم وقتی کاربر دستور start/ رو میفرسته، کیبورد سفارشی نمایش داده بشه، بنابراین:

@bot.message_handler(commands=["start"]) def start_markup(message): # ساخت ReplyKeyboardMarkup markup = types.ReplyKeyboardMarkup(row_width=2, resize_keyboard=True, one_time_keyboard=True) # ایجاد دکمهها (KeyboardButton) btn1 = types.KeyboardButton("گزینه 1") btn2 = types.KeyboardButton("گزینه 2") # اضافه کردن دکمهها به کیبورد markup.add(btn1, btn2) # ارسال پیام همراه با کیبورد به کاربر bot.send_message(message.chat.id, "لطفا یکی از گزینهها رو انتخاب کن :", reply_markup=markup)

من الان داخل ربات start/ رو فرستادم و جواب زیر برگشت:

توضیح دقیق کد و پارامتر ها:
row_width = 2: مشخص میکنه چند تا دکمه در هر ردیف قرار بگیره. اگه مقدار 1 رو بدم خروجی میشه:

resize_keyboard = True: این پارامتر باعث میشه که کیبورد به اندازهی محتواش کوچیکتر یا بزرگتر بشه تا ظاهر بهتری داشته باشه (مقدار True باشه بهتره از نظر ظاهری)

one_time_keyboard = True: وقتی این گزینه True باشه، کیبورد پس از اولین استفاده کاربر (بعد از انتخاب یک دکمه) به طور خودکار از چت محو میشه.

types.KeyboardButton("Button Name"): برای هر دکمه باید یه شی از کلاس KeyboardButton بسازی و متن یا عنوان اون رو مشخص کنی.

چطوری بفهمیم کاربر کدوم دکمه رو زده و چطور بهش واکنش نشون بدیم؟
وقتی از ReplyKeyboardMarkup استفاده میکنی، دکمهها در واقع متن سادهای هستن که کاربر ارسال میکنه. پس تو باید با message.text بررسی کنی ببینی کاربر چی فرستاده. مثال:

@bot.message_handler(commands = ["start"]) def start_markup(message): # ساخت ReplyKeyboardMarkup markup = types.ReplyKeyboardMarkup(row_width=1, resize_keyboard=True, one_time_keyboard=False) # ایجاد دکمهها (KeyboardButton) btn1 = types.KeyboardButton("گزینه 1") btn2 = types.KeyboardButton("گزینه 2") # اضافه کردن دکمهها به کیبورد markup.add(btn1, btn2) # ارسال پیام همراه با کیبورد به کاربر bot.send_message(message.chat.id, "لطفا یکی از گزینهها رو انتخاب کن:", reply_markup=markup) @bot.message_handler(func = lambda message : True) def button_handler(message): if message.text == "گزینه 1": bot.send_message(message.chat.id, "شما گزینه 1 رو انتخاب کردی ✅") elif message.text == "گزینه 2": bot.send_message(message.chat.id, "شما گزینه 2 رو انتخاب کردی 🔵") else: bot.send_message(message.chat.id, "لطفا فقط از دکمههای موجود استفاده کن!")

در نتیجه دکمه ها وقتی روشون کلیک میشه همون پیامی رو به ربات میفرستن که عنوان دکمه هست و ما باید به نسبت همون متن که اومده یک واکنشی نشون بدیم.

وقتی از ReplyKeyboardMarkup استفاده میکنی، کیبوردی (با دکمههای متنی) برای کاربر ظاهر میشه. حالا اگه بخوای اون کیبورد رو پاک کنی و محیط چت برگرده به حالت عادی، باید از ReplyKeyboardRemove استفاده کنی. به عبارت دیگه، ReplyKeyboardRemove یعنی این کیبورد رو بردار، دیگه نمیخوامش.
برای استفادش تو قدم اول باید import کنمش:

from telebot.types import ReplyKeyboardRemove

با مثال بالا جلو میریم:

import telebot from telebot.types import ReplyKeyboardMarkup, KeyboardButton, ReplyKeyboardRemove bot = telebot.TeleBot("8199750813:AAEfI2T276mA1tAgcsiuLp9PAcBFAsAYvXE") @bot.message_handler(commands=["start"]) def start_markup(message): # ساخت ReplyKeyboardMarkup markup = ReplyKeyboardMarkup(row_width=1, resize_keyboard=True, one_time_keyboard=False) # ایجاد دکمهها (KeyboardButton) btn1 = KeyboardButton("گزینه 1") btn2 = KeyboardButton("گزینه 2") # اضافه کردن دکمهها به کیبورد markup.add(btn1, btn2) # ارسال پیام همراه با کیبورد به کاربر bot.send_message(message.chat.id, "لطفا یکی از گزینهها رو انتخاب کن:", reply_markup=markup) @bot.message_handler(func = lambda message : True) def button_handler(message): if message.text == "گزینه 1": bot.send_message(message.chat.id, "شما گزینه 1 رو انتخاب کردی ✅", reply_markup = ReplyKeyboardRemove()) elif message.text == "گزینه 2": bot.send_message(message.chat.id, "شما گزینه 2 رو انتخاب کردی 🔵", reply_markup = ReplyKeyboardRemove()) else: bot.send_message(message.chat.id, "لطفا فقط از دکمههای موجود استفاده کن!") bot.infinity_polling()

وقتی کاربر روی start/ کلیک کنه دوتا دکمه براش نمایان میشه. اگه روی هر کدوم از گزینه ها کلیک کنه یک واکنشی دریافت میکنه و درنهایت دکمه ها حذف میشن، اما تا زمانی که روی گزینه ها کلیک نکنه و چیزی غیر مرتبط بفرسته، دکمه ها حذف نمیشن.


تو تلگرام دو نوع دکمه وجود داره، یه نوع ReplyKeyboardMarkup (کیبورد پایین چت) که بالاتر باهاش کار کردیم و نوع دیگه InlineKeyboardMarkup (کیبورد داخل پیام) هست. این دکمه ها به خود پیام چسبیدهاند. مثال:

(برخلاف دکمه های قبلی، اگه کاربر روی دکمه های inline کلیک کنه هیچ متنی به ربات ارسال نمیشه)
به کد زیر دقت کن:

import telebot from telebot.types import InlineKeyboardMarkup, InlineKeyboardButton bot = telebot.TeleBot("8199750813:AAEfI2T276mA1tAgcsiuLp9PAcBFAsAYvXE") markup = InlineKeyboardMarkup(row_width = 1) markup.add( InlineKeyboardButton("گزینه 1", callback_data = "1"), InlineKeyboardButton("گزینه 2", callback_data = "2") ) bot.send_message(5412199093, "لطفاً یکی رو انتخاب کن", reply_markup = markup) bot.infinity_polling()

کد بالا به محض اجرا شدن یک پیام رو با متن (لطفا یکی رو انتخاب کن) به من میفرسته (چون آیدی عددی خودم رو دادم) که پایین اون پیام دو تا دکمه وجود داره و من میتونم اون هارو انتخاب کنم. نمونه:

چطوری بفهمم کدوم دکمه کلیک شد؟
همینطور که گفته شد این دکمه ها متنی رو به ربات ارسال نمیکنن و باید از callback_query متوجه بشیم! اگه دقت کنید داخل کد برای گزینه اول callback_data رو برابر کردم با 1 و برای گزینه دوم برابر کردم با 2. یعنی هرموقع روی گزینه 1 کلیک شد callback_query مقدار 1 رو برمیگردونه. کد:

import telebot from telebot.types import InlineKeyboardMarkup, InlineKeyboardButton bot = telebot.TeleBot("8199750813:AAEfI2T276mA1tAgcsiuLp9PAcBFAsAYvXE") markup = InlineKeyboardMarkup(row_width = 1) markup.add( InlineKeyboardButton("گزینه 1", callback_data = "1"), InlineKeyboardButton("گزینه 2", callback_data = "2") ) bot.send_message(5412199093, "لطفاً یکی رو انتخاب کن", reply_markup = markup) @bot.callback_query_handler(func = lambda call : True) def handle_inline(call): if call.data == "1": bot.answer_callback_query(call.id, "گزینه 1 انتخاب شد") elif call.data == "2": bot.answer_callback_query(call.id, "گزینه 2 انتخاب شد") bot.infinity_polling()

در مورد answer_callback_query باید خودتون تست کنید و نتیجش رو ببینید. البته میشد بجاش از send_message یا هر چیز دیگه ایی استفاده کرد.
(call.id برای اینه که به تلگرام بفهمونم پاسخ کدوم دکمه رو الان میخوام بدم)

به کد زیر دقت کن:

@bot.message_handler(commands=["start"]) def send_menu(message): markup = InlineKeyboardMarkup() markup.add( InlineKeyboardButton("درباره ما", callback_data = "about"), InlineKeyboardButton("تماس با ما", callback_data = "contact") ) bot.send_message(message.chat.id, "به منوی اصلی خوش اومدی:", reply_markup=markup) @bot.callback_query_handler(func=lambda call: True) def callback_handler(call): if call.data == "about": bot.edit_message_text("ما یک بات ساده هستیم", chat_id = call.message.chat.id, message_id=call.message.message_id) elif call.data == "contact": bot.edit_message_text("@mrNazouri13", chat_id=call.message.chat.id, message_id=call.message.message_id)

وقتی start/ رو ارسال میکنم یک پیام از سمت ربات ارسال میشه که نوشته (به منوی اصلی خوش اومدی) و دوتا دکمه هم بهش چسبیده با عنوان های (درباره ما) و (تماس با ما) و چون row_width رو مشخص نکردم این دوتا دکمه کنار هم قرار میگیره. برای هر کدوم یک callback data مشخص شده که در نهایت تابع callback_handler به این موارد رسیدگی میکنه.
داخل این تابع گفته شده که اگه کاربر روی دکمه (درباره ما) کلیک کرد بیا همون پیام که نوشته بود (به منوی اصلی خوش اومدی) و دوتا دکمه که بهش چسبیده بود رو ادیت بزن و متن (ما یک بات ساده هستیم) رو قرار بده. اگه روی دکمه (تماس با ما) کلیک کرد بیا متن (mrNazouri13@) رو جایگزین متن قبلی کن (دقت کن اینجا متن یا پیام قبلی پاک نمیشه، صرفا ادیت میشه و متن جدید جایگزینش میشه)
داخل متد edit_message_text دوتا آرگومان هست که بریم بررسی کنیمشون:
call.message.chat.id: آیدی چتی که پیام توش ارسال شده. مثلا اگه پیام توی یه گروه باشه، آیدی گروه رو برمیگردونه، اگه توی پیوی باشه، آیدی کاربر رو. لازمه تا بدونی پیام تو کجا بوده، چون تلگرام برای ارسال یا ویرایش پیامها باید آیدی چت رو بدونه.
call.message.message_id: آیدی اون پیام خاصی که دکمه بهش چسبیده بود (هر پیام تو یه چت یه message_id منحصر به فرد داره)
با این دو آرگومان تلگرام میفهمه که داخل کدوم چت، دقیقا کدوم پیام رو ویرایش کنه.

تا الان هرچی دکمه تو حالت inline ساختیم یک data یی رو callback میکنه. چطور میتونم کاری کنم که وقتی روی دکمهایی کلیک شد یک url رو باز کنه؟ فقط کافیه از آرگومان url استفاده کنم:

@bot.message_handler(commands = ["start"]) def url_inline(message): markup = InlineKeyboardMarkup() markup.add( InlineKeyboardButton("instagram", url = "https://instagram.com/mrnazouri13"), InlineKeyboardButton("telegram", url = "https://t.me/mrnazouri13")) bot.send_message(message.chat.id, "سلام چطوری ؟", reply_markup = markup)



ربات BotFather ابزار اصلی تلگرام برای مدیریت رباتهاست و دستورات مختلفی برای شخصیسازی و تنظیم ربات در اختیارت قرار میده.

دستورات کاربردی BotFather:
newbot/: از این دستور برای ایجاد یک ربات کاملا جدید استفاده میکنی. BotFather ازت یک نام نمایشی و سپس یک نام کاربری (که باید با bot ختم بشه) برای رباتت میپرسه.
mybots/: با این دستور، لیستی از رباتهایی که ساختی رو میبینی و میتونی یکی رو برای ویرایش انتخاب کنی. بعد از انتخاب ربات، دکمههایی برای دسترسی به دستورات ویرایش نمایش داده میشه.
setname/: اسمی که کاربران در لیست چت و بالای صفحه چت با رباتت میبینن رو با این دستور تغییر میدی.
setdescription/: متنی کوتاه که وقتی کسی پروفایل رباتت رو باز میکنه (قبل از شروع کردن چت) در قسمت (What can this bot do?) یا (این ربات چه کاری میتونه انجام بده؟) نمایش داده میشه. این متن به کاربران کمک میکنه تا سریعا بفهمن رباتت چه کاربردی داره.
setabouttext/: این متن طولانیتر از توضیحات هست و وقتی کاربر روی نام ربات در پروفایلش کلیک میکنه، نمایش داده میشه. اینجا میتونی اطلاعات کاملتری درباره رباتت، سازندهاش و قابلیتهاش ارائه بدی.
setuserpic/: عکس پروفایل رباتت رو با این دستور آپلود یا تغییر میدی.
setcommands/: میتونی لیستی از دستورات اصلی رباتت و یک توضیح کوتاه برای هر کدوم تعریف کنی. وقتی کاربر / رو در چت با رباتت تایپ میکنه، این لیست بهش نمایش داده میشه و کار با ربات رو راحتتر میکنه.
deletebot/: برای حذف کامل یک ربات از این دستور استفاده میشه.
token/: توکن فعلی ربات رو برمیگردونه.
revoke/: توکن دسترسی فعلی رباتت رو باطل میکنه. این کار برای امنیت بیشتر انجام میشه، مثلا اگه فکر میکنی توکنت لو رفته. بعد از این کار باید یک توکن جدید با دستور token بگیری.
setjoingroups/: با این دستور مشخص میکنی که آیا کاربران میتونن رباتت رو به گروهها اضافه کنن یا نه.
setprivacy/: وقتی این حالت فعاله، رباتت در گروهها فقط پیامهایی رو دریافت میکنه که با / شروع بشن یا به صورت مستقیم بهش ریپلای شده باشن یا نام کاربری ربات در اونها ذکر شده باشه. اگه غیرفعال باشه، همه پیامهای گروه رو دریافت میکنه.



تمام 👌 !!!!
رفقایی که تا اینجای مقاله اومدن دمتون گرم و خسته نباشید ❤ امیدوارم تونسته باشم به ساده ترین حالت ممکن مفاهیم رو منتقل کنم.
در ضمن، من یک ویدیو یوتیوب آماده کردم که داخلش آموزش ساخت ربات تلگرام با پایتون رو آموزش دادم و پیشنهاد میکنم اون ویدیو (و دیگر ویدیو هارو) ببینید.
کانال یوتیوبم :
https://www.youtube.com/@mrNazouri13
و اگه خواستید با من در ارتباط باشید، آیدیم داخل تلگرام و اینستاگرام هست:
mrNazouri13@

موفق باشید.
امیرحسین ناظوری.



بروزرسانی...
تو این بخش قصد دارم بهتون یاد بدم چطوری با استفاده از BotFather ربات رو شخصیسازی تر یا زیبا تر بکنید. معرفی برخی از دستورات:
- setuserpic/: تنظیم عکس پروفایل ربات، کافیه این دستور رو بفرستی و بعد تصویر موردنظر رو ارسال کنی.
- setdescription/: متن تنظیم شده با این دستور وقتی کاربر برای اولین بار با ربات چت میکنه، در کادر «?What can this bot do» نشون داده میشه. (تا 512 کاراکتر)
- setabouttext/: تنظیم متن کوتاه (تا 120 کاراکتر) که در پروفایل ربات نشون داده میشه و هنگام اشتراکگذاری با دیگران قابل مشاهدست.

اگه قصد دارید ربات رو به دیتابیس وصل کنید و اطلاعات کاربران رو ذخیره کنید، مقاله ساخت و مدیریت Database با پایتون رو مطالعه کنید.

برنامه نویسیپایتونpythonکامپیوتر
۳
۱
امیرحسین ناظوری
امیرحسین ناظوری
📕 عاشق یادگیری و به اشتراک‌گذاری دانش -- آیدی من تو شبکه های اجتماعی : mrNazouri13
شاید از این پست‌ها خوشتان بیاید