آموزش ساخت کیبورد سفارشی (Reply Keyboards) در Telebot

فهرست مطالب

آموزش ساخت کیبورد سفارشی (Reply Keyboards) در Telebot

توسعه ربات‌های تلگرام در سال‌های اخیر به یکی از جذاب‌ترین حوزه‌های برنامه‌نویسی تبدیل شده است. این ربات‌ها، با قابلیت‌های متنوع خود، از ابزارهای ساده اطلاع‌رسانی گرفته تا سیستم‌های پیچیده رزرو و مدیریت، تجربه کاربری را به شکل چشمگیری بهبود بخشیده‌اند. یکی از کلیدی‌ترین عناصر در طراحی یک ربات کارآمد و کاربرپسند، استفاده از کیبوردهای سفارشی است. این کیبوردها، به جای اینکه کاربر مجبور باشد دستورات متنی را حفظ کرده و تایپ کند، گزینه‌های از پیش تعریف شده‌ای را در اختیار او قرار می‌دهند که تعامل با ربات را سریع‌تر، آسان‌تر و لذت‌بخش‌تر می‌کنند.

در این آموزش جامع، ما به عمق مبحث ساخت و مدیریت کیبوردهای پاسخ‌گو (Reply Keyboards) با استفاده از کتابخانه قدرتمند Telebot (که با نام pyTelegramBotAPI نیز شناخته می‌شود) در پایتون خواهیم پرداخت. هدف ما این است که شما را از مفاهیم پایه تا سناریوهای پیشرفته همراهی کنیم تا بتوانید کیبوردهایی بسازید که نه تنها از نظر بصری جذاب هستند، بلکه از نظر عملکردی نیز نیازهای پیچیده ربات شما و کاربرانش را برآورده سازند.

این مقاله برای توسعه‌دهندگانی طراحی شده است که با پایتون آشنایی اولیه دارند و می‌خواهند ربات‌های تلگرام خود را به سطح بالاتری از تعامل‌پذیری برسانند. ما با تمرکز بر جزئیات فنی و ارائه مثال‌های عملی فراوان، شما را قادر خواهیم ساخت تا کیبوردهای سفارشی قدرتمندی را طراحی و پیاده‌سازی کنید که تجربه کاربری ربات شما را متحول سازد.

درک مفاهیم پایه: کیبوردهای پاسخ‌گو (Reply Keyboards) چیستند؟

پیش از آنکه به کدنویسی بپردازیم، ضروری است که درک روشنی از ماهیت و کاربرد کیبوردهای پاسخ‌گو در تلگرام داشته باشیم. کیبوردهای پاسخ‌گو، همانطور که از نامشان پیداست، کیبوردهایی هستند که در پایین صفحه چت کاربر نمایش داده می‌شوند و مجموعه‌ای از گزینه‌های از پیش تعریف شده را به کاربر ارائه می‌دهند. این گزینه‌ها معمولاً دکمه‌های متنی هستند که با انتخاب آن‌ها توسط کاربر، متن مربوطه به عنوان یک پیام عادی به ربات ارسال می‌شود.

تفاوت Reply Keyboards با Inline Keyboards

در تلگرام دو نوع اصلی کیبورد سفارشی وجود دارد: Reply Keyboards و Inline Keyboards. درک تفاوت‌های آن‌ها برای انتخاب نوع مناسب در هر سناریو حیاتی است:

  • Reply Keyboards (کیبوردهای پاسخ‌گو):
    • در پایین صفحه چت کاربر نمایش داده می‌شوند، دقیقاً بالای فیلد ورودی پیام.
    • با انتخاب یک دکمه، متن آن دکمه به عنوان یک پیام متنی عادی به ربات ارسال می‌شود.
    • بیشتر برای منوهای ثابت، گزینه‌های استاندارد (مانند “بله/خیر”، “شروع مجدد”) یا جمع‌آوری ورودی‌های ساده از کاربر (مانند درخواست موقعیت مکانی یا شماره تماس) کاربرد دارند.
    • پس از انتخاب، تا زمانی که به صراحت حذف نشوند، در جای خود باقی می‌مانند.
    • نمونه‌ای از کاربرد: منوی اصلی یک ربات که گزینه‌هایی مانند “پروفایل من”، “خدمات”، “پشتیبانی” را نمایش می‌دهد.
  • Inline Keyboards (کیبوردهای درون‌خطی):
    • به صورت درون‌خطی و متصل به یک پیام خاص نمایش داده می‌شوند.
    • با انتخاب یک دکمه، به جای ارسال پیام متنی، یک “Callback Query” به ربات ارسال می‌شود که شامل داده‌های تعریف‌شده توسط توسعه‌دهنده است. این داده‌ها برای کاربر قابل مشاهده نیستند.
    • برای عملیات‌های دینامیک و وابسته به یک پیام خاص (مانند لایک/دیسلایک یک پست، پیمایش در صفحات، انتخاب یک مورد از لیست بلند) مناسب‌ترند.
    • پس از انتخاب دکمه، می‌توانند تغییر کنند، حذف شوند یا پیام اصلی را ویرایش کنند بدون اینکه پیام جدیدی در چت ایجاد شود.
    • نمونه‌ای از کاربرد: دکمه‌های “افزودن به سبد خرید” زیر یک محصول در یک ربات فروشگاهی.

در این مقاله، تمرکز اصلی ما بر روی Reply Keyboards خواهد بود. این کیبوردها به دلیل سادگی در پیاده‌سازی و توانایی در ارائه یک رابط کاربری ثابت و قابل پیش‌بینی، انتخاب اول بسیاری از توسعه‌دهندگان برای طراحی تعاملات پایه با ربات هستند.

موارد استفاده کلیدی Reply Keyboards

کیبوردهای پاسخ‌گو در سناریوهای متعددی می‌توانند بسیار مفید باشند:

  • منوهای اصلی و فرعی: ارائه یک راهنمای ثابت برای کاربر برای حرکت در بخش‌های مختلف ربات.
  • گزینه‌های ثابت و محدود: برای سوالاتی که پاسخ‌های مشخصی دارند (مثلاً “آیا می‌خواهید ادامه دهید؟ بله/خیر”).
  • درخواست اطلاعات خاص: مانند درخواست شماره تماس یا موقعیت مکانی کاربر با دکمه‌های ویژه.
  • دستورات پرکاربرد: ارائه دکمه‌هایی برای دستوراتی که کاربر به دفعات از آن‌ها استفاده می‌کند، مانند “شروع مجدد”، “بازگشت به عقب”.

با درک این مفاهیم پایه، اکنون آماده‌ایم تا وارد دنیای Telebot شویم و نحوه ساخت این کیبوردهای قدرتمند را قدم به قدم بیاموزیم.

چرا از Telebot برای ساخت ربات تلگرام استفاده کنیم؟

Telebot، یا همان pyTelegramBotAPI، یکی از محبوب‌ترین و پرکاربردترین کتابخانه‌های پایتون برای تعامل با API تلگرام بات است. انتخاب یک کتابخانه مناسب می‌تواند تأثیر زیادی بر سرعت توسعه، خوانایی کد و قابلیت نگهداری ربات شما داشته باشد. در اینجا دلایلی آورده شده است که چرا Telebot انتخابی عالی برای توسعه ربات‌های تلگرام است:

  • سهولت استفاده و یادگیری: Telebot با فلسفه “پایتونیک” طراحی شده است. سینتکس آن بسیار ساده و قابل فهم است و حتی برای توسعه‌دهندگانی که تجربه زیادی در ساخت ربات ندارند، یادگیری آن آسان است. شروع کار با آن تنها با چند خط کد امکان‌پذیر است.
  • مستندات جامع و مثال‌های فراوان: این کتابخانه دارای مستندات کامل و به‌روزی است که تمامی قابلیت‌ها و متدهای آن را با جزئیات توضیح می‌دهد. علاوه بر این، مثال‌های کد فراوانی در دسترس است که فرآیند یادگیری و پیاده‌سازی را تسریع می‌کند.
  • جامعه فعال و پشتیبانی: Telebot دارای یک جامعه کاربری فعال است. این بدان معناست که در صورت مواجه شدن با مشکلات یا نیاز به راهنمایی، می‌توانید به راحتی پاسخ سوالات خود را در فروم‌ها، گروه‌های تلگرامی و وب‌سایت‌های پرسش و پاسخ مانند Stack Overflow پیدا کنید.
  • پشتیبانی کامل از API تلگرام: Telebot تقریباً از تمامی قابلیت‌های ارائه شده توسط Telegram Bot API پشتیبانی می‌کند، از جمله ارسال انواع پیام‌ها (متن، عکس، ویدئو، فایل)، مدیریت به‌روزرسانی‌ها، ساخت کیبوردهای سفارشی (Reply و Inline) و بسیاری موارد دیگر.
  • مدیریت آسان به‌روزرسانی‌ها (Updates): با استفاده از متد bot.polling()، Telebot به صورت خودکار به‌روزرسانی‌ها را از سرور تلگرام دریافت و به هندلرهای مربوطه (@bot.message_handler و …) ارسال می‌کند، که فرآیند مدیریت تعاملات کاربر را بسیار ساده می‌کند.
  • انعطاف‌پذیری و توسعه‌پذیری: ساختار Telebot به گونه‌ای است که به شما اجازه می‌دهد ربات‌های ساده تا بسیار پیچیده را توسعه دهید. می‌توانید کد خود را ماژولار کنید و با سایر کتابخانه‌های پایتون (مانند دیتابیس‌ها، وب سرویس‌ها و غیره) به راحتی ادغام کنید.

نصب Telebot

برای شروع کار با Telebot، ابتدا باید آن را نصب کنید. این کار به سادگی از طریق pip، مدیر بسته پایتون، قابل انجام است:


pip install pyTelegramBotAPI

پس از نصب موفقیت‌آمیز، آماده خواهید بود تا اولین ربات خود را بسازید و گام‌های اولیه را در جهت پیاده‌سازی کیبوردهای پاسخ‌گو بردارید.

گام اول: راه‌اندازی ربات و دریافت توکن (Bot Initialization)

قبل از اینکه بتوانیم با Telebot کیبوردهای سفارشی بسازیم، نیاز داریم که یک ربات تلگرام ایجاد کرده و توکن API آن را دریافت کنیم. توکن API یک رشته منحصر به فرد است که به ربات شما اجازه می‌دهد تا با سرورهای تلگرام ارتباط برقرار کند.

ایجاد ربات با BotFather

BotFather رباتی رسمی از تلگرام است که برای مدیریت تمامی ربات‌های شما استفاده می‌شود. برای ایجاد یک ربات جدید:

  1. در تلگرام، @BotFather را جستجو کرده و با او چت را آغاز کنید.
  2. دستور /newbot را برای BotFather ارسال کنید.
  3. BotFather از شما می‌خواهد که یک نام برای ربات خود انتخاب کنید (این نام برای کاربران نمایش داده می‌شود).
  4. سپس از شما می‌خواهد که یک نام کاربری (username) برای ربات خود انتخاب کنید. این نام کاربری باید یکتا بوده و به bot ختم شود (مثلاً MyAwesomeBot یا MyAwesome_bot).
  5. پس از موفقیت، BotFather یک پیام حاوی توکن API ربات شما را برایتان ارسال می‌کند. این توکن شبیه به 123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11 خواهد بود.

نکته امنیتی مهم: توکن API ربات شما محرمانه است. آن را با کسی به اشتراک نگذارید و هرگز آن را مستقیماً در کد خود به صورت هاردکد قرار ندهید، به خصوص اگر قصد دارید کد را عمومی کنید. برای پروژه‌های جدی، توکن را در متغیرهای محیطی یا فایل‌های پیکربندی جداگانه ذخیره کنید.

اولین کد Telebot: راه‌اندازی و تست

حالا که توکن API را در اختیار دارید، می‌توانیم یک اسکریپت پایه برای راه‌اندازی ربات خود بنویسیم:


import telebot

# توکن API ربات خود را اینجا قرار دهید.
# توصیه می‌شود این توکن را از متغیرهای محیطی یا یک فایل پیکربندی بخوانید.
API_TOKEN = 'YOUR_BOT_API_TOKEN'

# یک نمونه از کلاس TeleBot ایجاد می‌کنیم
bot = telebot.TeleBot(API_TOKEN)

# یک هندلر برای دستور /start ایجاد می‌کنیم
@bot.message_handler(commands=['start'])
def send_welcome(message):
    bot.reply_to(message, "سلام! به ربات خوش آمدید. چگونه می‌توانم به شما کمک کنم؟")

# یک هندلر برای تمامی پیام‌های متنی غیر از دستورات
@bot.message_handler(func=lambda message: True)
def echo_all(message):
    bot.reply_to(message, message.text)

# شروع پولینگ برای دریافت به‌روزرسانی‌ها از تلگرام
print("ربات در حال اجرا است...")
bot.polling(none_stop=True)

توضیح کد:

  • import telebot: کتابخانه Telebot را وارد می‌کنیم.
  • API_TOKEN = 'YOUR_BOT_API_TOKEN': توکن API که از BotFather دریافت کرده‌اید را در اینجا قرار دهید. حتماً 'YOUR_BOT_API_TOKEN' را با توکن واقعی خود جایگزین کنید.
  • bot = telebot.TeleBot(API_TOKEN): یک شیء از کلاس TeleBot ایجاد می‌کنیم و توکن API را به آن می‌دهیم. این شیء نقطه اصلی تعامل ما با API تلگرام خواهد بود.
  • @bot.message_handler(commands=['start']): این یک دکوراتور است که تابع send_welcome را به عنوان هندلر برای دستور /start ثبت می‌کند. هرگاه کاربری دستور /start را به ربات ارسال کند، این تابع فراخوانی می‌شود.
  • def send_welcome(message):: تابعی که پیام خوش‌آمدگویی را ارسال می‌کند. شیء message حاوی اطلاعات کاملی درباره پیام دریافتی است.
  • bot.reply_to(message, "..."): این متد یک پاسخ به پیام دریافتی (message) ارسال می‌کند.
  • @bot.message_handler(func=lambda message: True): این هندلر برای تمامی پیام‌های متنی دیگر (که دستور نیستند) فراخوانی می‌شود. lambda message: True به این معنی است که این هندلر برای هر پیامی که به هندلرهای قبلی نخورد، اجرا خواهد شد.
  • bot.polling(none_stop=True): این خط کد ربات را در حالت “پولینگ” قرار می‌دهد. این بدان معناست که ربات به صورت مداوم (با تأخیرهای کوتاه) سرورهای تلگرام را برای دریافت به‌روزرسانی‌های جدید (پیام‌های کاربر، تعاملات کیبورد و غیره) بررسی می‌کند. آرگومان none_stop=True باعث می‌شود ربات در صورت بروز خطا متوقف نشود و به تلاش برای دریافت به‌روزرسانی‌ها ادامه دهد.

پس از اجرای این کد، ربات شما آنلاین خواهد شد. می‌توانید به تلگرام بروید، ربات خود را پیدا کرده و با ارسال /start یا هر پیام دیگری، آن را تست کنید. ربات باید به دستور /start با پیام خوش‌آمدگویی و به هر پیام دیگری با تکرار همان پیام پاسخ دهد.

اکنون که پایه و اساس ربات ما برقرار است، می‌توانیم به سراغ بخش هیجان‌انگیز ساخت کیبوردهای سفارشی برویم.

ساختاردهی اولیه Reply Keyboard: مثال‌های عملی

ساخت یک Reply Keyboard در Telebot شامل چند مرحله اصلی است: ایجاد شیء کیبورد، افزودن دکمه‌ها به آن، و سپس ارسال کیبورد به همراه یک پیام به کاربر. در این بخش، به جزئیات ساختاردهی اولیه و ارائه مثال‌های کاربردی خواهیم پرداخت.

معرفی telebot.types.ReplyKeyboardMarkup

برای ایجاد یک Reply Keyboard، از کلاس telebot.types.ReplyKeyboardMarkup استفاده می‌کنیم. این کلاس به ما اجازه می‌دهد تا یک شیء کیبورد قابل تنظیم ایجاد کنیم. مهم‌ترین پارامترهای سازنده این کلاس عبارتند از:

  • resize_keyboard (bool, اختیاری): اگر True باشد، کیبورد به صورت خودکار اندازه خود را متناسب با صفحه نمایش کاربر تغییر می‌دهد. این کار باعث می‌شود کیبورد در دستگاه‌های مختلف بهتر دیده شود. پیش‌فرض False.
  • one_time_keyboard (bool, اختیاری): اگر True باشد، کیبورد پس از انتخاب اولین دکمه توسط کاربر، به صورت خودکار مخفی می‌شود. این برای سناریوهایی که فقط به یک پاسخ نیاز دارید (مانند “بله/خیر” در یک سوال) بسیار مفید است. پیش‌فرض False.
  • selective (bool, اختیاری): اگر True باشد، کیبورد فقط برای کاربران خاص (گیرندگان پیام) نمایش داده می‌شود. این ویژگی بیشتر در گروه‌ها و برای پاسخ‌های مستقیم (replies) کاربرد دارد. پیش‌فرض False.
  • row_width (int, اختیاری): تعداد دکمه‌هایی که به صورت پیش‌فرض در هر ردیف قرار می‌گیرند، در صورتی که دکمه‌ها با add() اضافه شوند و ردیف‌بندی دستی انجام نشده باشد. پیش‌فرض 3.

افزودن دکمه‌ها با keyboard.add()

پس از ایجاد شیء ReplyKeyboardMarkup، می‌توانید با استفاده از متد add() دکمه‌ها را به آن اضافه کنید. add() می‌تواند یک یا چند دکمه را به عنوان آرگومان بپذیرد.

برای ایجاد دکمه‌ها، از telebot.types.KeyboardButton استفاده می‌کنیم. حداقل پارامتر مورد نیاز برای KeyboardButton، متن دکمه (text) است.


import telebot
from telebot import types

API_TOKEN = 'YOUR_BOT_API_TOKEN'
bot = telebot.TeleBot(API_TOKEN)

@bot.message_handler(commands=['start', 'help'])
def send_welcome(message):
    bot.reply_to(message, "سلام! من ربات شما هستم. لطفا یکی از گزینه‌ها را انتخاب کنید.")

# ----------------------------------------------------------------------------------
# Example 1: ساده‌ترین کیبورد با یک دکمه
# ----------------------------------------------------------------------------------
@bot.message_handler(commands=['single_button'])
def send_single_button_keyboard(message):
    # ایجاد شیء کیبورد
    markup = types.ReplyKeyboardMarkup(resize_keyboard=True, one_time_keyboard=True)
    
    # ایجاد دکمه
    button1 = types.KeyboardButton("گزینه اول")
    
    # اضافه کردن دکمه به کیبورد
    markup.add(button1)
    
    # ارسال پیام به همراه کیبورد
    bot.send_message(message.chat.id, "این یک کیبورد با یک دکمه است:", reply_markup=markup)

# ----------------------------------------------------------------------------------
# Example 2: کیبورد با چندین دکمه در یک ردیف
# ----------------------------------------------------------------------------------
@bot.message_handler(commands=['multiple_in_one_row'])
def send_multiple_buttons_in_one_row(message):
    markup = types.ReplyKeyboardMarkup(resize_keyboard=True)
    
    # اضافه کردن چندین دکمه در یک خط. اگر row_width تنظیم نشده باشد،
    # Telebot سعی می‌کند آن‌ها را بر اساس عرض پیش‌فرض 3 بچیند.
    # اما اگر مستقیماً به add بدهیم، در یک ردیف قرار می‌گیرند تا زمانی که پر شوند.
    markup.add("گزینه A", "گزینه B", "گزینه C") 
    
    bot.send_message(message.chat.id, "این یک کیبورد با چند دکمه در یک ردیف است:", reply_markup=markup)

# ----------------------------------------------------------------------------------
# Example 3: کیبورد با چندین دکمه در ردیف‌های مختلف
# ----------------------------------------------------------------------------------
@bot.message_handler(commands=['multiple_in_multiple_rows'])
def send_multiple_buttons_in_multiple_rows(message):
    markup = types.ReplyKeyboardMarkup(resize_keyboard=True)
    
    # هر فراخوانی add() به صورت پیش‌فرض یک ردیف جدید را شروع می‌کند،
    # مگر اینکه دکمه‌ها را پشت سر هم در یک add() قرار دهیم.
    markup.add("گزینه 1")
    markup.add("گزینه 2", "گزینه 3") # این دو دکمه در یک ردیف قرار می‌گیرند
    markup.add("گزینه 4", "گزینه 5", "گزینه 6") # این سه دکمه در یک ردیف قرار می‌گیرند
    
    bot.send_message(message.chat.id, "این یک کیبورد با چند دکمه در ردیف‌های مختلف است:", reply_markup=markup)

# ----------------------------------------------------------------------------------
# Example 4: استفاده از row_width برای کنترل تعداد دکمه‌ها در هر ردیف
# ----------------------------------------------------------------------------------
@bot.message_handler(commands=['row_width_example'])
def send_row_width_example(message):
    # تنظیم row_width به 2 به این معنی است که حداکثر 2 دکمه در هر ردیف قرار می‌گیرد.
    markup = types.ReplyKeyboardMarkup(resize_keyboard=True, row_width=2)
    
    # با add() کردن دکمه‌ها به صورت جداگانه یا گروه‌های کوچک،
    # Telebot سعی می‌کند آن‌ها را بر اساس row_width بچیند.
    # در این مثال، 7 دکمه داریم، پس خواهیم داشت:
    # [دکمه 1, دکمه 2]
    # [دکمه 3, دکمه 4]
    # [دکمه 5, دکمه 6]
    # [دکمه 7]
    markup.add("دکمه 1", "دکمه 2", "دکمه 3", "دکمه 4", "دکمه 5", "دکمه 6", "دکمه 7")
    
    bot.send_message(message.chat.id, "این یک کیبورد با row_width=2 است:", reply_markup=markup)

print("ربات در حال اجرا است...")
bot.polling(none_stop=True)

توضیحات تکمیلی مثال‌ها:

  • در Example 1، یک دکمه واحد ایجاد و به کیبورد اضافه شده است. resize_keyboard=True باعث می‌شود کیبورد بهتر در صفحه کاربر جا بیفتد و one_time_keyboard=True باعث می‌شود پس از انتخاب دکمه، کیبورد مخفی شود.
  • در Example 2، سه دکمه به صورت همزمان به متد add() داده شده‌اند. این باعث می‌شود که Telebot آن‌ها را در یک ردیف قرار دهد تا جایی که فضای کافی باشد (اگر row_width مشخص نشده باشد، به صورت پیش‌فرض ۳ دکمه در یک ردیف).
  • در Example 3، با فراخوانی‌های متعدد add()، ما به صورت دستی ردیف‌بندی را کنترل می‌کنیم. هر بار که add() را فراخوانی می‌کنیم، یک ردیف جدید شروع می‌شود، مگر اینکه چندین دکمه را همزمان به آن بدهیم.
  • در Example 4، از پارامتر row_width برای کنترل خودکار تعداد دکمه‌ها در هر ردیف استفاده شده است. این یک راه عالی برای حفظ یک ظاهر ثابت است، بدون اینکه نیاز باشد هر ردیف را به صورت دستی بسازید. Telebot دکمه‌ها را به صورت خودکار بین ردیف‌ها تقسیم می‌کند.

با اجرای این کد، می‌توانید با ارسال دستورات مربوطه (/single_button, /multiple_in_one_row و غیره) به ربات خود، کیبوردهای مختلف را تست کنید و تفاوت‌های ظاهری و رفتاری آن‌ها را مشاهده نمایید.

پیشرفته‌تر کردن Reply Keyboard: تنظیمات و قابلیت‌ها

Reply Keyboards فراتر از صرفاً نمایش دکمه‌های متنی هستند. آن‌ها می‌توانند قابلیت‌های ویژه‌ای مانند درخواست شماره تماس یا موقعیت مکانی کاربر را نیز ارائه دهند. این قابلیت‌ها به ربات شما اجازه می‌دهند تا اطلاعات حساسی را با اجازه کاربر دریافت کند و تجربه کاربری را بهبود بخشد.

دکمه‌های درخواست مخاطب و موقعیت مکانی

telebot.types.KeyboardButton علاوه بر پارامتر text، دارای پارامترهای بولي ديگری نیز هست که قابلیت‌های خاصی را به دکمه اضافه می‌کنند:

  • request_contact (bool, اختیاری): اگر True باشد، با کلیک کاربر روی این دکمه، تلگرام پنجره‌ای را برای تأیید ارسال شماره تماس کاربر به ربات نمایش می‌دهد. پس از تأیید، شماره تماس (شامل نام و نام خانوادگی کاربر، اگر در تلگرام تنظیم شده باشد) به عنوان یک پیام با نوع contact به ربات ارسال می‌شود.
  • request_location (bool, اختیاری): اگر True باشد، با کلیک کاربر روی این دکمه، تلگرام پنجره‌ای را برای تأیید ارسال موقعیت مکانی کاربر به ربات نمایش می‌دهد. پس از تأیید، موقعیت مکانی (عرض جغرافیایی، طول جغرافیایی) به عنوان یک پیام با نوع location به ربات ارسال می‌شود.
  • request_poll (telebot.types.KeyboardButtonPollType, اختیاری): از این برای ایجاد دکمه‌ای استفاده می‌شود که به کاربر اجازه می‌دهد یک نظرسنجی جدید ایجاد کند. این برای ساخت ربات‌های نظرسنجی پیشرفته مفید است. (نیاز به نسخه جدیدتر Telebot و API تلگرام دارد)

ملاحظات امنیتی و تجربه کاربری:

  • هنگام درخواست شماره تماس یا موقعیت مکانی، همیشه به کاربر توضیح دهید که چرا این اطلاعات را درخواست می‌کنید. شفافیت باعث افزایش اعتماد کاربر می‌شود.
  • این درخواست‌ها فقط از طریق Reply Keyboard قابل انجام هستند و کاربر باید به صورت صریح اجازه دهد. تلگرام حریم خصوصی کاربران را به شدت جدی می‌گیرد.
  • پس از دریافت اطلاعات، می‌توانید کیبورد را حذف کنید تا کاربر برای تعاملات بعدی سردرگم نشود.

مثال: درخواست اشتراک‌گذاری مخاطب و موقعیت مکانی


import telebot
from telebot import types

API_TOKEN = 'YOUR_BOT_API_TOKEN'
bot = telebot.TeleBot(API_TOKEN)

@bot.message_handler(commands=['start', 'help'])
def send_welcome(message):
    bot.reply_to(message, "سلام! من ربات شما هستم. برای استفاده از قابلیت‌های ویژه، از منو استفاده کنید.")

# ----------------------------------------------------------------------------------
# Example 5: کیبورد با دکمه‌های درخواست مخاطب و موقعیت مکانی
# ----------------------------------------------------------------------------------
@bot.message_handler(commands=['special_requests'])
def send_special_request_keyboard(message):
    markup = types.ReplyKeyboardMarkup(resize_keyboard=True, one_time_keyboard=True)
    
    # دکمه‌ای برای درخواست شماره تماس
    button_contact = types.KeyboardButton("ارسال شماره تماس من", request_contact=True)
    
    # دکمه‌ای برای درخواست موقعیت مکانی
    button_location = types.KeyboardButton("ارسال موقعیت مکانی من", request_location=True)

    # دکمه‌ای برای ایجاد یک نظرسنجی جدید (اختیاری و نیاز به نوع خاصی از ربات)
    # button_poll = types.KeyboardButton("ایجاد نظرسنجی", request_poll=types.KeyboardButtonPollType())
    
    markup.add(button_contact, button_location) # , button_poll
    
    bot.send_message(message.chat.id, 
                     "لطفاً شماره تماس یا موقعیت مکانی خود را به اشتراک بگذارید تا بتوانم به شما کمک کنم.", 
                     reply_markup=markup)

# ----------------------------------------------------------------------------------
# هندلر برای دریافت شماره تماس
# ----------------------------------------------------------------------------------
@bot.message_handler(content_types=['contact'])
def handle_contact(message):
    if message.contact is not None:
        first_name = message.contact.first_name if message.contact.first_name else 'ناشناس'
        last_name = message.contact.last_name if message.contact.last_name else ''
        phone_number = message.contact.phone_number
        bot.reply_to(message, 
                     f"ممنون، {first_name} {last_name}! شماره تماس شما: {phone_number} دریافت شد.")
        
        # پس از دریافت اطلاعات، کیبورد را حذف می‌کنیم
        remove_keyboard = types.ReplyKeyboardRemove()
        bot.send_message(message.chat.id, "کیبورد حذف شد.", reply_markup=remove_keyboard)

# ----------------------------------------------------------------------------------
# هندلر برای دریافت موقعیت مکانی
# ----------------------------------------------------------------------------------
@bot.message_handler(content_types=['location'])
def handle_location(message):
    if message.location is not None:
        latitude = message.location.latitude
        longitude = message.location.longitude
        bot.reply_to(message, 
                     f"ممنون! موقعیت مکانی شما دریافت شد. طول جغرافیایی: {longitude}, عرض جغرافیایی: {latitude}")
        
        # پس از دریافت اطلاعات، کیبورد را حذف می‌کنیم
        remove_keyboard = types.ReplyKeyboardRemove()
        bot.send_message(message.chat.id, "کیبورد حذف شد.", reply_markup=remove_keyboard)

# ----------------------------------------------------------------------------------
# هندلر برای تمامی پیام‌های متنی غیر از دستورات
# ----------------------------------------------------------------------------------
@bot.message_handler(func=lambda message: True)
def echo_all(message):
    bot.reply_to(message, "من متوجه پیام شما نشدم. لطفاً از دستورات یا کیبورد استفاده کنید.")

print("ربات در حال اجرا است...")
bot.polling(none_stop=True)

توضیحات کد:

  • در تابع send_special_request_keyboard، دو KeyboardButton با پارامترهای request_contact=True و request_location=True ایجاد کرده‌ایم. با اضافه کردن این دکمه‌ها به ReplyKeyboardMarkup و ارسال آن به کاربر، تلگرام به صورت هوشمند این دکمه‌ها را به گونه‌ای نمایش می‌دهد که با کلیک بر روی آن‌ها، پنجره تأیید ارسال اطلاعات باز شود.
  • هندلرهای @bot.message_handler(content_types=['contact']) و @bot.message_handler(content_types=['location']) برای دریافت و پردازش پیام‌هایی با نوع contact و location استفاده می‌شوند. این پیام‌ها حاوی اطلاعاتی هستند که کاربر به اشتراک گذاشته است.
  • پس از دریافت اطلاعات، از telebot.types.ReplyKeyboardRemove() برای حذف کیبورد از صفحه کاربر استفاده کرده‌ایم. این کار با ارسال یک پیام جدید (حتی یک پیام خالی) به همراه reply_markup=remove_keyboard انجام می‌شود. این عمل به تجربه کاربری کمک می‌کند، زیرا کاربر پس از انجام وظیفه، دیگر نیازی به کیبورد ندارد و فیلد ورودی پیام عادی می‌شود.

با اجرای این کد و ارسال دستور /special_requests به ربات، می‌توانید نحوه کارکرد این دکمه‌های خاص را مشاهده کنید. این قابلیت‌ها ربات شما را بسیار قدرتمندتر و کاربرپسندتر می‌کنند، به خصوص در سناریوهایی که نیاز به جمع‌آوری اطلاعات مشخصی از کاربر دارید.

مدیریت تعاملات کاربر با Reply Keyboard

هدف اصلی از ساخت یک Reply Keyboard، هدایت کاربر به سمت گزینه‌های مشخص و دریافت ورودی‌های استاندارد است. برای اینکه ربات بتواند به انتخاب‌های کاربر از روی کیبورد پاسخ دهد، باید پیام‌های دریافتی را بر اساس متن دکمه تحلیل کند.

هندلینگ پیام‌های دریافتی از دکمه‌های کیبورد

همانطور که قبلاً اشاره شد، زمانی که کاربر روی یک دکمه Reply Keyboard کلیک می‌کند، متن آن دکمه به عنوان یک پیام متنی عادی به ربات ارسال می‌شود. بنابراین، می‌توانیم از @bot.message_handler با content_types=['text'] و شرط‌گذاری بر روی message.text برای مدیریت این تعاملات استفاده کنیم.

مثال: یک منوی ساده با گزینه‌های “Option A”, “Option B”, “Exit”

بیایید یک منوی ساده ایجاد کنیم که کاربر بتواند بین چند گزینه انتخاب کند و در نهایت بتواند از منو خارج شود.


import telebot
from telebot import types

API_TOKEN = 'YOUR_BOT_API_TOKEN'
bot = telebot.TeleBot(API_TOKEN)

# ----------------------------------------------------------------------------------
# هندلر دستور /start برای نمایش منوی اصلی
# ----------------------------------------------------------------------------------
@bot.message_handler(commands=['start'])
def send_main_menu(message):
    markup = types.ReplyKeyboardMarkup(resize_keyboard=True, one_time_keyboard=False)
    markup.add("گزینه A", "گزینه B")
    markup.add("خروج از منو")
    bot.send_message(message.chat.id, "لطفاً یکی از گزینه‌های زیر را انتخاب کنید:", reply_markup=markup)

# ----------------------------------------------------------------------------------
# هندلر برای پاسخ به انتخاب‌های کاربر از روی کیبورد
# ----------------------------------------------------------------------------------
@bot.message_handler(func=lambda message: True, content_types=['text'])
def handle_menu_selection(message):
    chat_id = message.chat.id
    user_text = message.text

    if user_text == "گزینه A":
        bot.send_message(chat_id, "شما گزینه A را انتخاب کردید. برای بازگشت به منو، /start را بزنید.")
    elif user_text == "گزینه B":
        bot.send_message(chat_id, "شما گزینه B را انتخاب کردید. برای بازگشت به منو، /start را بزنید.")
    elif user_text == "خروج از منو":
        remove_keyboard = types.ReplyKeyboardRemove()
        bot.send_message(chat_id, "از منو خارج شدید. کیبورد حذف شد.", reply_markup=remove_keyboard)
    else:
        bot.send_message(chat_id, "گزینه نامعتبری انتخاب کردید. لطفاً از دکمه‌های منو استفاده کنید.")

print("ربات در حال اجرا است...")
bot.polling(none_stop=True)

توضیحات کد:

  • هندلر send_main_menu با دستور /start یک Reply Keyboard با سه دکمه “گزینه A”, “گزینه B” و “خروج از منو” ایجاد و به کاربر ارسال می‌کند.
  • هندلر handle_menu_selection برای تمامی پیام‌های متنی (content_types=['text']) که توسط کاربر ارسال می‌شوند، فعال می‌شود.
  • داخل این هندلر، با استفاده از ساختار if/elif/else، متن پیام کاربر (message.text) با متن دکمه‌های کیبورد مقایسه می‌شود.
  • اگر کاربر “گزینه A” یا “گزینه B” را انتخاب کند، ربات پاسخ مناسب را می‌دهد و کاربر می‌تواند با ارسال مجدد /start به منو بازگردد.
  • اگر کاربر “خروج از منو” را انتخاب کند، ربات از telebot.types.ReplyKeyboardRemove() برای حذف کیبورد استفاده می‌کند و پیام تأیید را ارسال می‌نماید. این باعث می‌شود کیبورد از پایین صفحه کاربر ناپدید شود و صفحه چت به حالت عادی بازگردد.
  • در نهایت، یک بخش else برای مدیریت ورودی‌های نامعتبر (پیام‌هایی که هیچ یک از دکمه‌ها نیستند) وجود دارد.

حذف کیبورد (Removing the Keyboard)

حذف یک Reply Keyboard به همان سادگی ارسال آن است. برای این کار، یک شیء از کلاس telebot.types.ReplyKeyboardRemove ایجاد کرده و آن را به پارامتر reply_markup هنگام ارسال یک پیام جدید (یا ویرایش پیام موجود، اگرچه معمولاً برای Reply Keyboards پیام جدیدی ارسال می‌شود) می‌دهیم.


remove_markup = types.ReplyKeyboardRemove()
bot.send_message(message.chat.id, "کیبورد حذف شد.", reply_markup=remove_markup)

چه زمانی کیبورد را حذف کنیم؟

  • پس از اینکه کاربر وظیفه‌ای را که کیبورد برای آن طراحی شده بود، به اتمام رساند (مانند انتخاب یک گزینه نهایی، ارسال اطلاعات درخواستی).
  • وقتی کاربر به حالت دیگری از ربات وارد می‌شود که نیازی به کیبورد قبلی ندارد.
  • زمانی که کاربر صراحتاً درخواست حذف کیبورد را می‌دهد (مانند دکمه “خروج از منو”).
  • برای جلوگیری از شلوغی و حفظ یک رابط کاربری تمیز و کارآمد.

مدیریت صحیح تعاملات و تصمیم‌گیری هوشمندانه در مورد نمایش یا حذف کیبوردها، نقش مهمی در ایجاد یک تجربه کاربری روان و دلپذیر برای ربات شما ایفا می‌کند.

سناریوهای پیچیده‌تر و بهترین روش‌ها (Best Practices)

تا اینجا، مفاهیم پایه و متوسط ساخت Reply Keyboards را پوشش دادیم. اما برای ساخت ربات‌های پیچیده‌تر و قابل نگهداری، نیاز به درک و پیاده‌سازی الگوهای طراحی پیشرفته‌تر و رعایت بهترین روش‌ها داریم.

حالت‌مداری (State Management)

در ربات‌های ساده، هر پیام کاربر به صورت مستقل پردازش می‌شود. اما در ربات‌های پیچیده‌تر که نیاز به گفتگوی چند مرحله‌ای دارند (مانند فرآیند رزرو بلیط، ثبت نام کاربر)، ربات باید “حالت” (state) فعلی کاربر را بداند تا بتواند پاسخ مناسبی ارائه دهد. به عنوان مثال، اگر کاربر در حال پر کردن فرمی است، ربات باید بداند که در کدام مرحله از فرم قرار دارد.

روش‌های پیاده‌سازی حالت‌مداری:

  1. دیکشنری ساده (برای ربات‌های کوچک): می‌توانید از یک دیکشنری پایتون (مثل user_states = {}) برای نگهداری حالت هر کاربر استفاده کنید، جایی که کلید آن user_id و مقدار آن، حالت فعلی کاربر (مثلاً یک رشته مانند “waiting_for_name”, “waiting_for_email”) باشد.
    
            user_states = {}
    
            @bot.message_handler(commands=['register'])
            def start_registration(message):
                user_states[message.chat.id] = 'waiting_for_name'
                bot.send_message(message.chat.id, "لطفاً نام خود را وارد کنید:")
    
            @bot.message_handler(func=lambda message: user_states.get(message.chat.id) == 'waiting_for_name')
            def get_user_name(message):
                name = message.text
                # ذخیره نام و تغییر حالت
                user_states[message.chat.id] = 'waiting_for_email'
                bot.send_message(message.chat.id, f"نام شما {name} ثبت شد. حالا ایمیل خود را وارد کنید:")
                # ... ادامه فرآیند
            

    نکته: این روش در صورت ری‌استارت شدن ربات یا افزایش تعداد کاربران، اطلاعات را از دست می‌دهد یا دچار مشکل می‌شود.

  2. پایگاه داده (برای ربات‌های متوسط و بزرگ): برای ربات‌های جدی‌تر، استفاده از پایگاه داده ضروری است.
    • SQLite: برای ربات‌های متوسط و توسعه سریع، SQLite یک گزینه سبک و مناسب است. اطلاعات در یک فایل ذخیره می‌شوند و نیاز به سرور دیتابیس جداگانه نیست.
    • PostgreSQL/MySQL: برای ربات‌های بزرگ، پرکاربرد و نیازمند مقیاس‌پذیری بالا، استفاده از دیتابیس‌های قدرتمند مانند PostgreSQL یا MySQL توصیه می‌شود.

    شما می‌توانید یک جدول در دیتابیس ایجاد کنید که شامل user_id، current_state و سایر اطلاعات موقت کاربر باشد.

  3. فریم‌ورک‌های مدیریت حالت: کتابخانه‌هایی مانند FSMContext در Aiogram (یک کتابخانه دیگر برای تلگرام) یا الگوهای FSM (Finite State Machine) به صورت دستی در Telebot می‌توانند به مدیریت حالت‌های پیچیده کمک کنند.

ماژولار کردن کد

با افزایش پیچیدگی ربات، قرار دادن تمامی کدها در یک فایل واحد می‌تواند مدیریت آن را دشوار کند. بهتر است کد خود را به ماژول‌های کوچکتر و قابل مدیریت تقسیم کنید:

  • فایل جداگانه برای هندلرها: توابع هندلر را در فایل‌های جداگانه (مثلاً handlers.py) نگهداری کنید.
  • فایل جداگانه برای ساخت کیبوردها: توابع مربوط به ساخت انواع کیبوردها (مثلاً keyboards.py) را از منطق ربات جدا کنید.
  • فایل جداگانه برای پیکربندی: توکن API و سایر تنظیمات را در یک فایل config.py یا از طریق متغیرهای محیطی مدیریت کنید.

مثال ساختار پروژه:


my_bot/
├── main.py
├── config.py
├── handlers/
│   ├── __init__.py
│   ├── start_handler.py
│   ├── menu_handler.py
│   └── ...
└── keyboards/
    ├── __init__.py
    ├── reply_keyboards.py
    └── ...

پیام‌های خطا و بازخورد

همیشه به کاربران خود بازخورد واضح و مفیدی ارائه دهید:

  • پیام‌های خطا: در صورت بروز خطا، به جای سکوت یا ارسال یک پیام فنی، یک پیام دوستانه و راهنما به کاربر ارسال کنید.
  • پیام‌های تأیید: پس از انجام یک عملیات موفق، به کاربر اطلاع دهید (مثلاً “درخواست شما با موفقیت ثبت شد.”).
  • راهنمایی: اگر کاربر ورودی نامعتبری داد، او را راهنمایی کنید که چگونه می‌تواند صحیح عمل کند یا به منو بازگردد.

بین‌المللی‌سازی (Internationalization – i18n)

اگر ربات شما قرار است توسط کاربران با زبان‌های مختلف استفاده شود، به فکر پیاده‌سازی بین‌المللی‌سازی باشید. این کار شامل ترجمه تمامی پیام‌ها و دکمه‌های کیبورد به زبان‌های مختلف است. کتابخانه‌هایی مانند gettext در پایتون می‌توانند در این زمینه کمک‌کننده باشند.

استفاده ترکیبی با Inline Keyboards (مختصر)

با وجود تمام مزایای Reply Keyboards، گاهی اوقات Inline Keyboards گزینه بهتری هستند. به عنوان یک بهترین روش، درک کنید که هر کدام برای چه نوع تعاملی مناسب‌ترند:

  • Reply Keyboards: برای منوهای اصلی و ثابت، گزینه‌های عمومی، درخواست اطلاعات از کاربر.
  • Inline Keyboards: برای تعاملات وابسته به پیام خاص (مثل لایک/دیسلایک، پیمایش صفحات، تأیید/لغو).

در ربات‌های پیشرفته، معمولاً از ترکیبی از هر دو نوع کیبورد استفاده می‌شود تا بهترین تجربه کاربری را فراهم آورد.

امنیت

حفظ امنیت ربات شما بسیار مهم است:

  • توکن API: هرگز توکن API خود را در کدهای عمومی قرار ندهید. از متغیرهای محیطی یا فایل‌های پیکربندی .env استفاده کنید و اطمینان حاصل کنید که این فایل‌ها به سیستم کنترل نسخه (مانند Git) commit نمی‌شوند.
  • اعتبارسنجی ورودی کاربر: هر ورودی که از کاربر دریافت می‌کنید را اعتبارسنجی کنید. هرگز به ورودی کاربر اعتماد نکنید و همیشه فرض کنید ممکن است مخرب باشد. این امر به ویژه هنگام تعامل با پایگاه داده یا سیستم‌عامل حیاتی است تا از حملاتی مانند SQL Injection جلوگیری شود.
  • پردازش خطا: مطمئن شوید که ربات شما خطاها را به درستی مدیریت می‌کند و در صورت بروز مشکل، پیام‌های خطای معنی‌دار را به کاربر نمایش می‌دهد نه اطلاعات حساس سیستمی.

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

نتیجه‌گیری

در این آموزش جامع، ما به تفصیل به بررسی و پیاده‌سازی کیبوردهای پاسخ‌گو (Reply Keyboards) با استفاده از کتابخانه Telebot در پایتون پرداختیم. از درک مفاهیم پایه و تفاوت آن‌ها با Inline Keyboards، تا راه‌اندازی ربات، ساخت کیبوردهای ساده و پیچیده، و مدیریت تعاملات کاربر، تمامی جنبه‌های کلیدی را پوشش دادیم.

یاد گرفتیم که چگونه با telebot.types.ReplyKeyboardMarkup یک کیبورد ایجاد کنیم، چگونه دکمه‌های متنی را با telebot.types.KeyboardButton اضافه کنیم، و چگونه از پارامترهایی مانند resize_keyboard و one_time_keyboard برای بهبود تجربه کاربری استفاده کنیم. همچنین، قابلیت‌های ویژه‌ای مانند درخواست شماره تماس و موقعیت مکانی را بررسی کردیم و نحوه هندل کردن این پیام‌های خاص را آموختیم. در نهایت، با سناریوهای پیچیده‌تر و بهترین روش‌هایی مانند مدیریت حالت، ماژولار کردن کد، ارائه بازخورد مناسب و امنیت، آشنا شدیم تا بتوانیم ربات‌هایی قوی‌تر و پایدارتر بسازیم.

Reply Keyboards ابزاری قدرتمند برای ساده‌سازی تعاملات در ربات‌های تلگرام هستند. آن‌ها به کاربران اجازه می‌دهند تا به سرعت و بدون نیاز به تایپ دستورات، با ربات شما ارتباط برقرار کنند، که این امر به نوبه خود، کارایی و رضایت کاربر را به شدت افزایش می‌دهد. تسلط بر این قابلیت، گام بزرگی در جهت ساخت ربات‌های تلگرام پیشرفته و کاربرپسند است.

اکنون که دانش لازم را کسب کرده‌اید، وقت آن است که ایده‌های خود را به واقعیت تبدیل کنید. با آزمایش و ترکیب قابلیت‌های مختلف Reply Keyboards، می‌توانید ربات‌هایی بسازید که نه تنها نیازهای خاص شما را برآورده می‌کنند، بلکه تجربه کاربری بی‌نظیری را برای مخاطبان خود فراهم می‌آورند. خلاقیت شما تنها محدودیت شماست!

پیشنهاد می‌کنیم با پیاده‌سازی یک ربات منودار که از چند لایه منوی پاسخ‌گو استفاده می‌کند، آموخته‌های خود را عملی کنید. این کار به شما کمک می‌کند تا درک عمیق‌تری از مدیریت حالت و جریان کاربری پیدا کنید. فراموش نکنید که همیشه به مستندات رسمی Telebot مراجعه کنید تا از آخرین قابلیت‌ها و تغییرات مطلع شوید.

“تسلط به برنامه‌نویسی پایتون با هوش مصنوعی: آموزش کدنویسی هوشمند با ChatGPT”

قیمت اصلی 2.290.000 ریال بود.قیمت فعلی 1.590.000 ریال است.

"تسلط به برنامه‌نویسی پایتون با هوش مصنوعی: آموزش کدنویسی هوشمند با ChatGPT"

"با شرکت در این دوره جامع و کاربردی، به راحتی مهارت‌های برنامه‌نویسی پایتون را از سطح مبتدی تا پیشرفته با کمک هوش مصنوعی ChatGPT بیاموزید. این دوره، با بیش از 6 ساعت محتوای آموزشی، شما را قادر می‌سازد تا به سرعت الگوریتم‌های پیچیده را درک کرده و اپلیکیشن‌های هوشمند ایجاد کنید. مناسب برای تمامی سطوح با زیرنویس فارسی حرفه‌ای و امکان دانلود و تماشای آنلاین."

ویژگی‌های کلیدی:

بدون نیاز به تجربه قبلی برنامه‌نویسی

زیرنویس فارسی با ترجمه حرفه‌ای

۳۰ ٪ تخفیف ویژه برای دانشجویان و دانش آموزان