بعد از خرید، مشتری با دکمه از ۱ تا ۵ ستاره امتیاز میدهد و نظرش را مینویسد. امتیازهای پایین همان لحظه برای شما ارسال میشود تا قبل از اینکه مشتری ناراضی برود، با او تماس بگیرید.
سوال یا راهنمایی لازم داری؟ از صفحهٔ تماس با ما بپرس.
بیشتر مشتریهای ناراضی شکایت نمیکنند؛ فقط دیگر برنمیگردند. لینک این ربات را بعد از خرید برای مشتری بفرست. مشتری با یک دکمهٔ شیشهای امتیاز میدهد، پیام دکمهها ویرایش میشود تا دوباره زده نشود و ربات نظر متنی (اختیاری) را میپرسد. امتیاز و نظر در feedback.csv ذخیره میشود، امتیاز ۱ و ۲ فوری به مدیر اطلاع داده میشود و دستور /stats میانگین و توزیع امتیازها را نشان میدهد.
این مراحل را بهترتیب انجام بده تا ربات روی سیستم خودت یا سرور بالا بیاید. داخل فایل ZIP یک راهنمای README هم هست.
این همان کدی است که داخل فایل ZIP هم هست. فقط یادت باشد مقدار TOKEN را با توکن رباتت عوض کنی.
# -*- coding: utf-8 -*-
# ------------------------------------------------------------
# ربات نظرسنجی و رضایت مشتری تلگرام
# طراحی و کدنویسی: سروش مقدمی — فیلتور (filtori.com)
# ------------------------------------------------------------
# بعد از خرید یا دریافت خدمت، لینک ربات رو برای مشتری بفرست:
# ۱) مشتری با دکمههای شیشهای از ۱ تا ۵ ستاره امتیاز میده
# ۲) ربات (اختیاری) نظر متنیاش رو هم میپرسه
# ۳) همهچیز در feedback.csv ذخیره میشه (با اکسل باز میشه)
# ۴) امتیازهای پایین (۱ و ۲) همون لحظه برای مدیر ارسال میشن
# تا قبل از اینکه مشتری ناراضی بره، باهاش تماس بگیری
# ۵) مدیر با دستور /stats میانگین و تعداد امتیازها رو میبینه
#
# ⚠️ نکته: ربات تلگرام باید روی سروری اجرا بشه که به
# api.telegram.org دسترسی داره.
#
# آموزش کامل:
# https://filtori.com/telegram-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://api.telegram.org/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
api("answerCallbackQuery", {"callback_query_id": callback["id"]})
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()
با چند تغییر کوچک، ربات را مخصوص کسبوکار خودت کن.
با ALERT_RATING = 3 امتیاز متوسط هم برای مدیر هشدار میفرستد.
متن سوال بعد از امتیاز را در تابع handle_callback با لحن برند خودت بنویس.
برای پاسخ مستقیم به مشتری ناراضی از داخل ربات، ایدهٔ /reply را از ربات پشتیبانی و تیکت اضافه کن.
اگر ربات اجرا نشد، اول پیام خطای ترمینال را با این جدول مقایسه کن. اگر خطایت اینجا نبود، از صفحهٔ تماس با ما بپرس.
| پیام خطا | علت | راهحل |
|---|---|---|
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 بساز تا ربات بعد از خطا یا ریاستارت سرور خودش دوباره روشن شود.
[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
sudo nano /etc/systemd/system/mybot.service # متن بالا را اینجا بگذار
sudo systemctl daemon-reload
sudo systemctl enable --now mybot # روشنکردن + اجرای خودکار بعد از ریاستارت
journalctl -u mybot -f # دیدن لاگها
راهاندازی روی سرور برایت سخت است؟ نصب و راهاندازی را به ما بسپار.
درخواست راهاندازیاین سورس برای یادگیری و شروع کار عالی است. وقتی ربات قرار است هر روز با مشتری واقعی کار کند، معمولاً به دیتابیس، پنل مدیریت، امنیت بیشتر و پشتیبانی نیاز دارد. تیم فیلتور همین ربات نظرسنجی و رضایت مشتری تلگرام را اختصاصی و متناسب با فرآیند کسبوکارت میسازد.
| امکان | سورس رایگان | نسخهٔ اختصاصی |
|---|---|---|
| ذخیرهسازی | فایل CSV/TXT | دیتابیس |
| پنل مدیریت | — | ✓ |
| پرداخت آنلاین | — | ✓ |
| اتصال به سایت / CRM | — | ✓ |
| نصب و پشتیبانی | خودت | تیم فیلتور |
هر جا مشتری بعد از خرید با شما در تماس است: روی فاکتور یا رسید بهصورت QR، در پیامک تشکر یا پیام پیگیری سفارش. لینک ربات در تلگرام به شکل t.me/آیدی_ربات است.
در فایل feedback.csv کنار برنامه، همراه تاریخ، نام مشتری، امتیاز و متن نظر. فایل با اکسل هم درست باز میشود.
این سورس گزارش متنی /stats دارد. داشبورد با نمودار، گزارش ماهانه و تفکیک شعبه در نسخهٔ اختصاصی ساخته میشود.
از صفحهٔ تماس با ما در filtori.com/contact پیام بدهید یا با شمارهٔ ۰۹۱۲۲۸۷۴۸۶۲ تماس بگیرید؛ اگر نسخهٔ اختصاصی همین ربات را برای کسبوکارتان بخواهید هم همین مسیر را استفاده کنید.
اگر در راهاندازی گیر کردی، یا میخواهی همین ربات برای کسبوکارت نصب و شخصیسازی شود، از صفحهٔ تماس با ما پیام بده.