رفتن به محتوای اصلی
⭐ سطح: متوسط · رایگان · جدید

سورس ربات نظرسنجی و رضایت مشتری بله

بعد از خرید، مشتری با دکمه از ۱ تا ۵ ستاره امتیاز می‌دهد و نظرش را می‌نویسد. امتیازهای پایین همان لحظه برای شما ارسال می‌شود تا قبل از اینکه مشتری ناراضی برود، با او تماس بگیرید.

طراحی و کدنویسی: به‌روزرسانی: زبان: Python 3حجم کد: حدود ۱۷۰ خطمجوز: آزاد (CC0)

پاسخ کوتاه

ربات نظرسنجی بله پنج دکمهٔ شیشه‌ای امتیاز نشان می‌دهد. با زدن هر دکمه، پیام دکمه‌ها ویرایش می‌شود تا دوباره زده نشود و ربات نظر متنی (اختیاری) را می‌پرسد. امتیاز و نظر در feedback.csv ذخیره می‌شود، امتیاز ۱ و ۲ فوری به ADMIN_CHAT_ID اطلاع داده می‌شود و دستور /stats میانگین و توزیع امتیازها را نشان می‌دهد.

ربات نظرسنجی و رضایت مشتری بله چه کاری انجام می‌دهد؟

بیشتر مشتری‌های ناراضی شکایت نمی‌کنند؛ فقط دیگر برنمی‌گردند. لینک این ربات را بعد از خرید یا دریافت خدمت برای مشتری بفرست (مثلاً روی فاکتور یا در پیامک). مشتری با یک دکمه امتیاز می‌دهد و اگر خواست دلیلش را می‌نویسد. شما هم برای امتیازهای پایین هشدار فوری می‌گیرید و هر وقت خواستید با /stats وضعیت رضایت مشتری را می‌بینید.

زبان: پایتون ۳
وابستگی: فقط requests
ذخیره: feedback.csv
گزارش مدیر: /stats
هزینه: رایگان

آموزش راه‌اندازی ربات نظرسنجی و رضایت مشتری بله در ۵ قدم

این مراحل را به‌ترتیب انجام بده تا ربات روی سیستم خودت یا سرور بالا بیاید. زمان تقریبی: ۱۵ دقیقه. داخل فایل ZIP راهنمای README هم هست.

از BotFather در بله توکن ربات را بگیر.
پایتون ۳ را نصب کن و pip install requests را اجرا کن.
در فایل bot.py مقدار TOKEN را بگذار، ربات را اجرا کن و /start بزن؛ chat_id خودت را از ترمینال در ADMIN_CHAT_ID بگذار.
ربات را دوباره اجرا کن و لینک آن (ble.ir/آیدی_ربات) را بعد از خرید برای مشتری‌ها بفرست.
هر وقت خواستی در چت خودت با ربات /stats را بفرست تا میانگین امتیاز را ببینی.

کل سورس ربات نظرسنجی و رضایت مشتری بله (کپی یا دانلود کن)

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

bot.py
# -*- coding: utf-8 -*-
# ------------------------------------------------------------
#  ربات نظرسنجی و رضایت مشتری بله
#  طراحی و کدنویسی: سروش مقدمی — فیلتور (filtori.com)
# ------------------------------------------------------------
#  بعد از خرید یا دریافت خدمت، لینک ربات رو برای مشتری بفرست:
#   ۱) مشتری با دکمه‌های شیشه‌ای از ۱ تا ۵ ستاره امتیاز می‌ده
#   ۲) ربات (اختیاری) نظر متنی‌اش رو هم می‌پرسه
#   ۳) همه‌چیز در feedback.csv ذخیره می‌شه (با اکسل باز می‌شه)
#   ۴) امتیازهای پایین (۱ و ۲) همون لحظه برای مدیر ارسال می‌شن
#      تا قبل از اینکه مشتری ناراضی بره، باهاش تماس بگیری
#   ۵) مدیر با دستور /stats میانگین و تعداد امتیازها رو می‌بینه
#
#  آموزش کامل:
#     https://filtori.com/bale-bot-source/feedback-bot/
#  سوال یا راهنمایی:  https://filtori.com/contact/
#  نسخهٔ اختصاصی با داشبورد و گزارش ماهانه؟  09122874862
# ------------------------------------------------------------

import csv
import os
import time
from datetime import datetime

import requests

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

# chat_id مدیر؛ ربات رو اجرا کن و /start بزن تا در ترمینال چاپ بشه.
ADMIN_CHAT_ID = 123456789  # <-- این عدد رو با chat_id خودت عوض کن

FEEDBACK_FILE = "feedback.csv"
FIELDS = ["date", "chat_id", "name", "rating", "comment"]
ALERT_RATING = 2      # امتیاز مساوی یا کمتر از این عدد فوری به مدیر اطلاع داده می‌شه
SKIP = "رد کردن"

sessions = {}  # 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 send(chat_id, text, markup=None):
    data = {"chat_id": chat_id, "text": text}
    if markup is not None:
        data["reply_markup"] = markup
    api("sendMessage", data)


def stars(n):
    return "⭐" * n


def rating_keyboard():
    """۵ دکمهٔ شیشه‌ای امتیاز؛ از ۵ ستاره تا ۱ ستاره."""
    return {"inline_keyboard": [[{"text": stars(n), "callback_data": f"rate:{n}"}] for n in range(5, 0, -1)]}


def save_feedback(chat_id, name, rating, comment):
    is_new = not os.path.exists(FEEDBACK_FILE)
    with open(FEEDBACK_FILE, "a", newline="", encoding="utf-8-sig") as file:
        writer = csv.DictWriter(file, fieldnames=FIELDS)
        if is_new:
            writer.writeheader()
        writer.writerow({
            "date": datetime.now().strftime("%Y-%m-%d %H:%M"),
            "chat_id": chat_id, "name": name, "rating": rating, "comment": comment,
        })


def stats_text():
    if not os.path.exists(FEEDBACK_FILE):
        return "هنوز هیچ نظری ثبت نشده."
    with open(FEEDBACK_FILE, "r", newline="", encoding="utf-8-sig") as file:
        ratings = [int(row["rating"]) for row in csv.DictReader(file)]
    if not ratings:
        return "هنوز هیچ نظری ثبت نشده."
    average = sum(ratings) / len(ratings)
    lines = [f"📊 تعداد نظرها: {len(ratings)}", f"میانگین امتیاز: {average:.1f} از ۵", ""]
    for n in range(5, 0, -1):
        lines.append(f"{stars(n)}  {ratings.count(n)}")
    return "\n".join(lines)


def finish(chat_id, name, comment):
    """ثبت نهایی امتیاز و نظر، و هشدار به مدیر در صورت امتیاز پایین."""
    rating = sessions.pop(chat_id)
    save_feedback(chat_id, name, rating, comment)
    send(chat_id, "ممنون که وقت گذاشتی 🙏 نظرت ثبت شد.", {"remove_keyboard": True})
    if rating <= ALERT_RATING:
        send(ADMIN_CHAT_ID, f"⚠️ مشتری ناراضی ({stars(rating)})\n👤 {name} (chat_id: {chat_id})\n💬 {comment or '—'}")


def handle_message(message):
    chat_id = message["chat"]["id"]
    text = message.get("text", "")
    user = message.get("from", {})
    name = (user.get("first_name", "") + " " + user.get("last_name", "")).strip() or "مشتری"

    if chat_id == ADMIN_CHAT_ID and text == "/stats":
        send(chat_id, stats_text())
        return

    if text == "/start":
        sessions.pop(chat_id, None)
        send(chat_id, f"سلام {name} 👋\nتجربه‌ات از خرید یا خدمت ما چطور بود؟ یک گزینه رو بزن:", rating_keyboard())
        return

    if chat_id in sessions:  # منتظر نظر متنی هستیم
        finish(chat_id, name, "" if text == SKIP else text)
        return

    send(chat_id, "برای ثبت امتیاز، دستور /start را بفرستید.")


def handle_callback(callback):
    data = callback.get("data", "")
    message = callback.get("message")
    if not message or not data.startswith("rate:"):
        return
    chat_id = message["chat"]["id"]
    rating = int(data.split(":", 1)[1])
    if rating not in range(1, 6):
        return

    sessions[chat_id] = rating
    # پیام دکمه‌ها رو ویرایش می‌کنیم تا دوباره زده نشن
    api("editMessageText", {"chat_id": chat_id, "message_id": message["message_id"],
                            "text": f"امتیاز تو: {stars(rating)}"})
    question = ("متأسفیم 😔 بگو چه چیزی باعث نارضایتی شد تا درستش کنیم:"
                if rating <= 3 else "عالیه 🌟 اگر نکته‌ای داری بنویس (اختیاری):")
    send(chat_id, question, {"keyboard": [[{"text": SKIP}]], "resize_keyboard": True})


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:
                print("پیام از chat_id:", update["message"]["chat"]["id"])
                handle_message(update["message"])

        time.sleep(0.5)


if __name__ == "__main__":
    main()
کل سورس این ربات ↑ — همین حالا کپی یا دانلود کن

کد را خط‌به‌خط بفهم

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

۱دکمه‌های ستاره‌ای

return {"inline_keyboard": [[{"text": stars(n), "callback_data": f"rate:{n}"}]
                           for n in range(5, 0, -1)]}

پنج دکمهٔ شیشه‌ای از ۵ ستاره تا ۱ ستاره ساخته می‌شود و امتیاز داخل callback_data قرار می‌گیرد. ترتیب نزولی باعث می‌شود گزینهٔ مثبت اول دیده شود.

۲جلوگیری از امتیاز تکراری

api("editMessageText", {"chat_id": chat_id, "message_id": message["message_id"],
                        "text": f"امتیاز تو: {stars(rating)}"})

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

۳سوال متفاوت برای مشتری ناراضی

question = ("متأسفیم 😔 بگو چه چیزی باعث نارضایتی شد..."
            if rating <= 3 else "عالیه 🌟 اگر نکته‌ای داری بنویس (اختیاری):")

برای امتیاز پایین، علت نارضایتی پرسیده می‌شود و برای امتیاز بالا یک نظر اختیاری. دکمهٔ «رد کردن» هم هست تا مشتری مجبور به نوشتن نباشد.

۴هشدار فوری به مدیر

if rating <= ALERT_RATING:
    send(ADMIN_CHAT_ID, f"⚠️ مشتری ناراضی ({stars(rating)})...")

با ALERT_RATING = 2 امتیازهای ۱ و ۲ همراه نام، chat_id و نظر مشتری به مدیر می‌رسد. می‌توانی آن را ۳ کنی تا امتیاز متوسط هم هشدار بدهد.

۵گزارش /stats

average = sum(ratings) / len(ratings)
lines.append(f"{stars(n)}  {ratings.count(n)}")

مدیر با /stats تعداد کل نظرها، میانگین امتیاز و تعداد هر امتیاز را می‌بیند. این دستور فقط برای ADMIN_CHAT_ID کار می‌کند.

🔁 همین کد روی تلگرام هم اجرا می‌شود: فقط BASE را به https://api.telegram.org/bot{TOKEN} تغییر بده. نسخهٔ تلگرامی آماده را در سورس رایگان ربات تلگرام ببین.

سوال‌های پرتکرار دربارهٔ ربات نظرسنجی و رضایت مشتری بله

لینک ربات را کجا به مشتری بدهم؟

هر جا مشتری بعد از خرید با شما در تماس است: روی فاکتور یا رسید (به‌صورت QR)، در پیامک تشکر، کنار صندوق یا در پیام پیگیری سفارش. لینک ربات در بله به شکل ble.ir/آیدی_ربات است.

مشتری می‌تواند چند بار امتیاز بدهد؟

در هر بار شروع با /start فقط یک امتیاز ثبت می‌شود و دکمه‌ها بعد از انتخاب حذف می‌شوند. اگر بخواهید هر مشتری فقط یک بار امتیاز بدهد، می‌توان قبل از نمایش دکمه‌ها chat_id را در فایل بررسی کرد.

نظرها کجا ذخیره می‌شوند؟

در فایل feedback.csv کنار برنامه، همراه تاریخ، نام مشتری، امتیاز و متن نظر. فایل با اکسل هم درست باز می‌شود.

می‌شود گزارش ماهانه و نمودار داشت؟

این سورس گزارش متنی /stats دارد. داشبورد با نمودار، گزارش ماهانه، تفکیک شعبه و اتصال به CRM در نسخهٔ اختصاصی ساخته می‌شود.

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

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

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

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

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

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