هر پیام کاربر یک تیکت با شمارهٔ پیگیری میشود، همان لحظه برای مدیر ارسال میشود و مدیر با یک دستور ساده، مستقیم به همان کاربر جواب میدهد.
سوال یا راهنمایی لازم داری؟ از صفحهٔ تماس با ما بپرس.
کاربر مشکل یا سوالش را برای ربات مینویسد و یک شمارهٔ پیگیری میگیرد. تیکت در فایل tickets.csv ذخیره و برای مدیر ارسال میشود. مدیر با دستور «/reply شماره متن» جواب میدهد، جواب مستقیم به کاربر میرسد و وضعیت تیکت به «پاسخ داده شد» تغییر میکند. با دستور /open هم تیکتهای بیپاسخ نمایش داده میشوند.
این مراحل را بهترتیب انجام بده تا ربات روی سیستم خودت یا سرور بالا بیاید. داخل فایل ZIP یک راهنمای README هم هست.
این همان کدی است که داخل فایل ZIP هم هست. فقط یادت باشد مقدار TOKEN را با توکن رباتت عوض کنی.
# -*- coding: utf-8 -*-
# ------------------------------------------------------------
# ربات پشتیبانی و تیکت تلگرام
# طراحی و کدنویسی: سروش مقدمی — فیلتور (filtori.com)
# ------------------------------------------------------------
# هر پیامی که کاربر بفرسته، یک «تیکت» با شمارهٔ پیگیری میشه:
# - تیکت داخل فایل tickets.csv ذخیره میشه (با اکسل باز میشه)
# - همون لحظه برای مدیر (ادمین) فرستاده میشه
# - مدیر با دستور /reply شماره_تیکت متن_پاسخ جواب میده
# و جواب مستقیم برای همون کاربر ارسال میشه
# - مدیر با دستور /open تیکتهای بیپاسخ رو میبینه
#
# ⚠️ نکته: ربات تلگرام باید روی سروری اجرا بشه که به
# api.telegram.org دسترسی داره.
#
# آموزش کامل:
# https://filtori.com/telegram-bot-source/ticket-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 خودت عوض کن
TICKETS_FILE = "tickets.csv"
FIELDS = ["id", "date", "chat_id", "name", "message", "status"]
def send_message(chat_id, text):
url = f"{BASE}/sendMessage"
try:
requests.post(url, json={"chat_id": chat_id, "text": text}, timeout=15)
except requests.RequestException as error:
print("خطا در ارسال پیام:", error)
def get_updates(offset):
url = f"{BASE}/getUpdates"
params = {"offset": offset, "timeout": 30}
try:
return requests.get(url, params=params, timeout=40).json()
except (requests.RequestException, ValueError) as error:
print("خطا در دریافت پیامها:", error)
return {"ok": False, "result": []}
def load_tickets():
"""خواندن همهٔ تیکتها از فایل CSV."""
if not os.path.exists(TICKETS_FILE):
return []
with open(TICKETS_FILE, "r", newline="", encoding="utf-8-sig") as file:
return list(csv.DictReader(file))
def save_tickets(tickets):
"""بازنویسی کامل فایل تیکتها (برای تغییر وضعیت)."""
with open(TICKETS_FILE, "w", newline="", encoding="utf-8-sig") as file:
writer = csv.DictWriter(file, fieldnames=FIELDS)
writer.writeheader()
writer.writerows(tickets)
def create_ticket(chat_id, name, message):
"""ساخت تیکت جدید و برگرداندن شمارهٔ آن."""
tickets = load_tickets()
ticket_id = max([int(t["id"]) for t in tickets], default=0) + 1
tickets.append(
{
"id": str(ticket_id),
"date": datetime.now().strftime("%Y-%m-%d %H:%M"),
"chat_id": str(chat_id),
"name": name,
"message": message,
"status": "باز",
}
)
save_tickets(tickets)
return ticket_id
def admin_reply(text):
"""اجرای دستور /reply شماره متن توسط مدیر."""
parts = text.split(maxsplit=2)
if len(parts) < 3 or not parts[1].isdigit():
send_message(ADMIN_CHAT_ID, "فرمت درست:\n/reply 12 متن پاسخ شما")
return
ticket_id, answer = parts[1], parts[2]
tickets = load_tickets()
for ticket in tickets:
if ticket["id"] == ticket_id:
send_message(
int(ticket["chat_id"]),
f"📩 پاسخ پشتیبانی به تیکت #{ticket_id}:\n\n{answer}",
)
ticket["status"] = "پاسخ داده شد"
save_tickets(tickets)
send_message(ADMIN_CHAT_ID, f"پاسخ تیکت #{ticket_id} ارسال شد ✅")
return
send_message(ADMIN_CHAT_ID, f"تیکتی با شمارهٔ {ticket_id} پیدا نشد.")
def admin_open_list():
"""نمایش تیکتهای بیپاسخ برای مدیر."""
open_tickets = [t for t in load_tickets() if t["status"] == "باز"]
if not open_tickets:
send_message(ADMIN_CHAT_ID, "هیچ تیکت بیپاسخی نداری 👌")
return
lines = [f"#{t['id']} | {t['name']} | {t['message'][:40]}" for t in open_tickets[-15:]]
send_message(ADMIN_CHAT_ID, "تیکتهای باز:\n\n" + "\n".join(lines))
def handle(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:
if text.startswith("/reply"):
admin_reply(text)
elif text == "/open":
admin_open_list()
else:
send_message(
chat_id,
"دستورهای مدیر:\n/open ← تیکتهای بیپاسخ\n/reply 12 متن ← پاسخ به تیکت",
)
return
# --- کاربران ---
if text == "/start":
send_message(
chat_id,
f"سلام {name} 👋\n"
"به پشتیبانی ما خوش اومدی. سوال یا مشکلت رو همینجا بنویس؛\n"
"یک شمارهٔ پیگیری میگیری و کارشناس ما همینجا جواب میده.",
)
return
if not text:
send_message(chat_id, "فعلاً فقط پیام متنی پشتیبانی میشه؛ لطفاً مشکلت رو بنویس.")
return
ticket_id = create_ticket(chat_id, name, text)
send_message(
chat_id,
f"پیامت ثبت شد ✅\nشمارهٔ پیگیری: #{ticket_id}\n"
"بهزودی جوابت همینجا ارسال میشه.",
)
send_message(
ADMIN_CHAT_ID,
f"🎫 تیکت جدید #{ticket_id}\n👤 {name} (chat_id: {chat_id})\n\n{text}\n\n"
f"برای پاسخ:\n/reply {ticket_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
message = update.get("message")
if not message:
continue
print("پیام از chat_id:", message["chat"]["id"])
handle(message)
time.sleep(0.5)
if __name__ == "__main__":
main()
با چند تغییر کوچک، ربات را مخصوص کسبوکار خودت کن.
پیام خوشآمد و پیام تایید ثبت تیکت را در تابع handle با لحن برند خودت بنویس.
برای چند پشتیبان، بهجای یک ADMIN_CHAT_ID یک گروه تلگرامی بساز، ربات را عضو کن و chat_id گروه را بگذار؛ همهٔ اپراتورها تیکتها را میبینند.
برای کم کردن تیکتهای تکراری، اول با ربات پاسخگوی خودکار جواب سوالهای رایج را بده.
اگر ربات اجرا نشد، اول پیام خطای ترمینال را با این جدول مقایسه کن. اگر خطایت اینجا نبود، از صفحهٔ تماس با ما بپرس.
| پیام خطا | علت | راهحل |
|---|---|---|
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 | — | ✓ |
| نصب و پشتیبانی | خودت | تیم فیلتور |
مدیر در چت خودش با ربات دستور /reply بعد شمارهٔ تیکت و بعد متن پاسخ را میفرستد؛ مثلاً /reply 12 سفارش شما فردا ارسال میشود. پاسخ مستقیم برای همان کاربر فرستاده میشود.
در فایل tickets.csv کنار برنامه، همراه تاریخ، نام کاربر، متن و وضعیت. فایل با اکسل هم درست باز میشود.
این سورس فقط پیام متنی را تیکت میکند. دریافت عکس و فایل، پنل تحت وب و چند اپراتور در نسخهٔ اختصاصی قابل پیادهسازی است.
از صفحهٔ تماس با ما در filtori.com/contact پیام بدهید یا با شمارهٔ ۰۹۱۲۲۸۷۴۸۶۲ تماس بگیرید؛ اگر نسخهٔ اختصاصی همین ربات را برای کسبوکارتان بخواهید هم همین مسیر را استفاده کنید.
اگر در راهاندازی گیر کردی، یا میخواهی همین ربات برای کسبوکارت نصب و شخصیسازی شود، از صفحهٔ تماس با ما پیام بده.