رفتن به محتوای اصلی
🗂️ سطح: متوسط · رایگان

سورس ربات کاتالوگ محصولات با دکمهٔ شیشه‌ای تلگرام

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

سوال یا راهنمایی لازم داری؟ از صفحهٔ تماس با ما بپرس.

طراحی و کدنویسی: زبان: Python 3وابستگی: requestsزمان راه‌اندازی: ۲۰ دقیقهمجوز: رایگان (CC0)به‌روزرسانی: ۲ مهر ۱۴۰۵

این ربات چه کاری انجام می‌دهد؟

با /start لیست محصولات به‌صورت دکمه‌های شیشه‌ای (Inline) زیر پیام نمایش داده می‌شود. با زدن هر محصول، همان پیام به صفحهٔ جزئیات تبدیل می‌شود و چت شلوغ نمی‌شود. دکمهٔ «سفارش» شمارهٔ تماس مشتری را با یک دکمه می‌گیرد و سفارش را برای مدیر ارسال می‌کند.

⚠️ نکتهٔ مهم: ربات تلگرام باید روی سروری اجرا شود که به api.telegram.org دسترسی دارد؛ روی خیلی از هاست‌های داخل ایران این آدرس مستقیم باز نیست. اگر ربات اجرا نشد، معمولاً مشکل از دسترسی سرور است نه از کد. اگر گیر کردی، از طریق صفحهٔ تماس با ما کمک بگیر.

آموزش راه‌اندازی قدم‌به‌قدم

این مراحل را به‌ترتیب انجام بده تا ربات روی سیستم خودت یا سرور بالا بیاید. داخل فایل ZIP یک راهنمای README هم هست.

از BotFather در تلگرام توکن ربات را بگیر.
پایتون را نصب کن و pip install requests را اجرا کن.
در فایل bot.py مقدار TOKEN و ADMIN_CHAT_ID را بگذار.
دیکشنری PRODUCTS را با نام، قیمت و توضیح محصولات خودت پر کن.
python bot.py را اجرا کن، /start بزن، یک محصول را باز کن و سفارش آزمایشی ثبت کن.

کل سورس ربات (کپی یا دانلود کن)

این همان کدی است که داخل فایل ZIP هم هست. فقط یادت باشد مقدار TOKEN را با توکن رباتت عوض کنی.

bot.py
# -*- coding: utf-8 -*-
# ------------------------------------------------------------
#  ربات کاتالوگ محصولات با دکمهٔ شیشه‌ای (Inline) تلگرام
#  طراحی و کدنویسی: سروش مقدمی — فیلتور (filtori.com)
# ------------------------------------------------------------
#  یک ویترین کوچک داخل تلگرام:
#   - لیست محصولات با دکمه‌های شیشه‌ای (زیر پیام) نمایش داده می‌شه
#   - با زدن هر محصول، همون پیام به صفحهٔ جزئیات تبدیل می‌شه
#     (بدون ارسال پیام‌های اضافه و شلوغ‌شدن چت)
#   - دکمهٔ «سفارش» شمارهٔ تماس مشتری رو با یک دکمه می‌گیره
#     و سفارش رو برای مدیر می‌فرسته
#
#  ⚠️ نکته: ربات تلگرام باید روی سروری اجرا بشه که به
#     api.telegram.org دسترسی داره.
#
#  آموزش کامل:
#     https://filtori.com/telegram-bot-source/catalog-bot/
#  سوال یا راهنمایی:  https://filtori.com/contact/
#  فروشگاه کامل با سبد خرید، پرداخت و Mini App؟  09122874862
# ------------------------------------------------------------

import time

import requests

TOKEN = "توکن_ربات_خودت_را_اینجا_بگذار"
BASE = f"https://api.telegram.org/bot{TOKEN}"

ADMIN_CHAT_ID = 123456789  # <-- chat_id مدیر برای دریافت سفارش‌ها

# ------------------------- محصولات -------------------------
PRODUCTS = {
    "p1": {"name": "هدفون بی‌سیم", "price": "۱٬۸۵۰٬۰۰۰ تومان",
           "desc": "باتری ۳۰ ساعته، حذف نویز، گارانتی ۱۸ ماهه."},
    "p2": {"name": "ساعت هوشمند", "price": "۲٬۹۰۰٬۰۰۰ تومان",
           "desc": "ضدآب، سنجش ضربان قلب، اتصال به اندروید و iOS."},
    "p3": {"name": "پاوربانک ۲۰ هزار", "price": "۹۵۰٬۰۰۰ تومان",
           "desc": "شارژ سریع ۲۲.۵ وات، دو خروجی USB و یک Type-C."},
}
# -----------------------------------------------------------

pending_orders = {}  # chat_id -> کد محصولی که منتظر شمارهٔ تماسش هستیم


def api(method, data):
    try:
        return requests.post(f"{BASE}/{method}", json=data, timeout=15).json()
    except (requests.RequestException, ValueError) as error:
        print(f"خطا در {method}:", error)
        return {"ok": False}


def get_updates(offset):
    params = {"offset": offset, "timeout": 30}
    try:
        return requests.get(f"{BASE}/getUpdates", params=params, timeout=40).json()
    except (requests.RequestException, ValueError) as error:
        print("خطا در دریافت پیام‌ها:", error)
        return {"ok": False, "result": []}


def catalog_keyboard():
    buttons = [[{"text": f"{p['name']} — {p['price']}", "callback_data": f"show:{code}"}]
               for code, p in PRODUCTS.items()]
    return {"inline_keyboard": buttons}


def product_keyboard(code):
    return {
        "inline_keyboard": [
            [{"text": "🛒 سفارش این محصول", "callback_data": f"order:{code}"}],
            [{"text": "↩️ بازگشت به لیست", "callback_data": "back"}],
        ]
    }


def send_catalog(chat_id):
    api("sendMessage", {"chat_id": chat_id, "text": "🛍 محصولات ما؛ روی هر کدوم بزن:",
                        "reply_markup": catalog_keyboard()})


def edit(chat_id, message_id, text, keyboard):
    """ویرایش همان پیام قبلی به‌جای ارسال پیام جدید."""
    api("editMessageText", {"chat_id": chat_id, "message_id": message_id,
                            "text": text, "reply_markup": keyboard})


def handle_callback(callback):
    data = callback.get("data", "")
    chat_id = callback["message"]["chat"]["id"]
    message_id = callback["message"]["message_id"]
    api("answerCallbackQuery", {"callback_query_id": callback["id"]})

    if data == "back":
        edit(chat_id, message_id, "🛍 محصولات ما؛ روی هر کدوم بزن:", catalog_keyboard())

    elif data.startswith("show:"):
        code = data.split(":", 1)[1]
        product = PRODUCTS.get(code)
        if product:
            text = f"📦 {product['name']}\n\n{product['desc']}\n\n💰 قیمت: {product['price']}"
            edit(chat_id, message_id, text, product_keyboard(code))

    elif data.startswith("order:"):
        code = data.split(":", 1)[1]
        if code in PRODUCTS:
            pending_orders[chat_id] = code
            api("sendMessage", {
                "chat_id": chat_id,
                "text": f"برای سفارش «{PRODUCTS[code]['name']}» شمارهٔ تماست رو با دکمهٔ زیر بفرست:",
                "reply_markup": {
                    "keyboard": [[{"text": "📱 ارسال شماره تماس", "request_contact": True}],
                                 [{"text": "انصراف"}]],
                    "resize_keyboard": True,
                    "one_time_keyboard": True,
                },
            })


def handle_message(message):
    chat_id = message["chat"]["id"]
    text = message.get("text", "")
    contact = message.get("contact")

    if text in ("/start", "/products"):
        pending_orders.pop(chat_id, None)
        send_catalog(chat_id)
        return

    if text == "انصراف":
        pending_orders.pop(chat_id, None)
        api("sendMessage", {"chat_id": chat_id, "text": "سفارش لغو شد.",
                            "reply_markup": {"remove_keyboard": True}})
        return

    if chat_id in pending_orders and contact:
        code = pending_orders.pop(chat_id)
        product = PRODUCTS[code]
        user = message.get("from", {})
        username = f"@{user['username']}" if user.get("username") else "—"
        api("sendMessage", {
            "chat_id": chat_id,
            "text": f"سفارش «{product['name']}» ثبت شد ✅\nبه‌زودی برای هماهنگی باهات تماس می‌گیریم.",
            "reply_markup": {"remove_keyboard": True},
        })
        api("sendMessage", {
            "chat_id": ADMIN_CHAT_ID,
            "text": (f"🛒 سفارش جدید\n📦 {product['name']} ({product['price']})\n"
                     f"👤 {contact.get('first_name', '')}  {username}\n📞 {contact['phone_number']}"),
        })
        return

    if chat_id in pending_orders:
        api("sendMessage", {"chat_id": chat_id,
                            "text": "لطفاً شماره را با دکمهٔ «📱 ارسال شماره تماس» بفرست."})
        return

    send_catalog(chat_id)


def main():
    print("ربات کاتالوگ فیلتور روشن شد... (Ctrl+C برای خاموش‌کردن)")
    offset = 0
    while True:
        updates = get_updates(offset)
        if not updates.get("ok"):
            time.sleep(2)
            continue

        for update in updates.get("result", []):
            offset = update["update_id"] + 1
            if "callback_query" in update:
                handle_callback(update["callback_query"])
            elif "message" in update:
                handle_message(update["message"])

        time.sleep(0.5)


if __name__ == "__main__":
    main()
کل سورس این ربات ↑

⬇ دانلود فایل ZIP این ربات

شخصی‌سازی سریع

با چند تغییر کوچک، ربات را مخصوص کسب‌وکار خودت کن.

محصولات

هر محصول در PRODUCTS یک کد کوتاه (مثل p4) دارد؛ کد باید یکتا باشد چون در callback_data استفاده می‌شود.

عکس محصول

برای نمایش عکس، به‌جای editMessageText از متد sendPhoto با کپشن استفاده کن؛ در نسخهٔ اختصاصی گالری و دسته‌بندی هم اضافه می‌شود.

ذخیرهٔ سفارش در فایل

اگر می‌خواهی سفارش‌ها در اکسل هم ذخیره شوند، تابع save_order از ربات ثبت سفارش را اضافه کن.

خطاهای رایج و راه‌حل

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

پیام خطاعلتراه‌حل
401 Unauthorizedتوکن اشتباه است یا فاصلهٔ اضافه دارد.توکن را دوباره از BotFather کپی کن و بین دو علامت نقل‌قول بگذار.
409 Conflictیک نسخهٔ دیگر از ربات در حال اجراست یا روی ربات وب‌هوک تنظیم شده.نسخهٔ دیگر را خاموش کن. اگر قبلاً وب‌هوک گذاشته‌ای، آدرس api.telegram.org/bot<TOKEN>/deleteWebhook را یک بار باز کن.
Timeout یا ConnectionErrorسرور به api.telegram.org دسترسی ندارد.ربات را روی سروری اجرا کن که به تلگرام دسترسی دارد؛ روی بیشتر هاست‌های داخل ایران این آدرس باز نیست.
ModuleNotFoundError: requestsکتابخانهٔ requests نصب نشده.دستور pip install -r requirements.txt یا pip install requests را اجرا کن.
429 Too Many Requestsدر زمان کوتاه پیام زیادی ارسال شده.بین ارسال‌ها مکث بگذار؛ تلگرام حدود ۳۰ پیام در ثانیه اجازه می‌دهد.
ربات در گروه جواب نمی‌دهدPrivacy Mode ربات روشن است.در BotFather دستور /setprivacy را بزن و آن را Disable کن، یا ربات را ادمین گروه کن.

اجرای ۲۴ ساعته روی سرور لینوکس

با python bot.py ربات تا وقتی ترمینال باز است کار می‌کند. برای اجرای دائمی روی سرور لینوکس (Ubuntu/Debian)، فایل‌ها را در پوشهٔ /opt/mybot بگذار و یک سرویس systemd بساز تا ربات بعد از خطا یا ری‌استارت سرور خودش دوباره روشن شود.

/etc/systemd/system/mybot.service
[Unit]
Description=Filtori Telegram Bot
After=network-online.target

[Service]
WorkingDirectory=/opt/mybot
ExecStart=/usr/bin/python3 /opt/mybot/bot.py
Environment=PYTHONUNBUFFERED=1
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
فایل سرویس
terminal
sudo nano /etc/systemd/system/mybot.service   # متن بالا را اینجا بگذار
sudo systemctl daemon-reload
sudo systemctl enable --now mybot             # روشن‌کردن + اجرای خودکار بعد از ری‌استارت
journalctl -u mybot -f                        # دیدن لاگ‌ها
دستورها

راه‌اندازی روی سرور برایت سخت است؟ نصب و راه‌اندازی را به ما بسپار.

درخواست راه‌اندازی

از سورس رایگان تا ربات حرفه‌ای کسب‌وکار

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

امکانسورس رایگاننسخهٔ اختصاصی
ذخیره‌سازیفایل CSV/TXTدیتابیس
پنل مدیریت—✓
پرداخت آنلاین—✓
اتصال به سایت / CRM—✓
نصب و پشتیبانیخودتتیم فیلتور

سوال‌های پرتکرار دربارهٔ این ربات

دکمهٔ شیشه‌ای چه فرقی با کیبورد معمولی دارد؟

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

سبد خرید و پرداخت آنلاین دارد؟

خیر، این سورس سفارش تکی را با شماره تماس ثبت می‌کند. سبد خرید، درگاه پرداخت و Mini App فروشگاهی در نسخهٔ اختصاصی ساخته می‌شود.

چند محصول می‌شود اضافه کرد؟

محدودیت خاصی ندارد، ولی برای بیش از ۱۵ تا ۲۰ محصول بهتر است دسته‌بندی و صفحه‌بندی اضافه شود.

سوال یا مشکلی داشتم از کجا راهنمایی بگیرم؟

از صفحهٔ تماس با ما در filtori.com/contact پیام بدهید یا با شمارهٔ ۰۹۱۲۲۸۷۴۸۶۲ تماس بگیرید؛ اگر نسخهٔ اختصاصی همین ربات را برای کسب‌وکارتان بخواهید هم همین مسیر را استفاده کنید.

طراح و برنامه‌نویس این سورس‌ها · بنیان‌گذار فیلتور

مدیر بخش دیتابیس همراه اول و فعال در توسعهٔ نرم‌افزار از سال ۱۳۹۱؛ با سابقهٔ کار روی سامانه‌های بانکی و پرتراکنش. این سورس‌ها را طوری نوشته که ساده، خوانا و قابل توسعه باشند و مستقیم در کسب‌وکار واقعی استفاده شوند.

سوالی داری یا راهنمایی می‌خواهی؟

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

سورس‌های دیگر ربات تلگرام