به قسمت پایانی سری رسیدیم. در قسمت ۱ دیدیم چرا این ربات لازمه، در قسمت ۲ ضداسپم رفتاری ساختیم، و در قسمت ۳ خوشآمدگویی هوشمند. امروز همهی اینها رو — بهعلاوهی تشخیص لینک که هنوز کدش رو ننوشته بودیم — کنار هم میذاریم و یک ربات واقعی و قابلاجرا تحویل میدیم.
فهرست مطالب
- معماری کلی ربات
- مرحله ۱: تشخیص لینک
- مرحله ۲: لیست سفید ادمینها
- مرحله ۳: کد کامل یکپارچه
- مرحله ۴: اجرای دائمی روی سرور
- خلاصهی کل سری
- قدم بعدی: چطور گسترشش بدیم
- سوالات متداول
معماری کلی ربات
ربات نهایی ما سه لایهی بررسی داره که روی هر پیام ورودی، بهترتیب اجرا میشن: آیا ادمینه؟ (اگه بله، از همهی بررسیها معاف میشه) → آیا لینک داره؟ → آیا الگوی اسپم داره؟. جدا از این، یک لایهی مستقل هم برای عضو جدید داریم که مستقل از پیامهای معمولی عمل میکنه.
مرحله ۱: تشخیص لینک
برای تشخیص لینک، از یک الگوی Regex ساده برای آدرسهای وب و لینکهای دعوت تلگرام استفاده میکنیم:
import re
LINK_PATTERN = re.compile(
r"(https?://|www\.|t\.me/|@[a-zA-Z0-9_]{5,})"
)
def contains_link(text):
return bool(LINK_PATTERN.search(text or ""))این الگو هم آدرسهای وب معمولی، هم لینک دعوت تلگرام (t.me/...)، هم منشن یوزرنیم (@channel) رو میگیره — رایجترین روش تبلیغات ناخواسته در گروهها.
مرحله ۲: لیست سفید ادمینها
بدون این بخش، ربات حتی پیام خودِ ادمینها رو هم حذف میکنه! با getChatAdministrators لیست ادمینهای گروه رو میگیریم:
admin_cache = {}
def get_admin_ids(chat_id):
if chat_id in admin_cache:
return admin_cache[chat_id]
response = requests.get(f"{BASE_URL}/getChatAdministrators", params={"chat_id": chat_id})
result = response.json()
admin_ids = [admin["user"]["id"] for admin in result.get("result", [])]
admin_cache[chat_id] = admin_ids
return admin_ids
def is_admin(chat_id, user_id):
return user_id in get_admin_ids(chat_id)نکته: لیست ادمینها رو کش کردیم تا با هر پیام، درخواست جدید به API نزنیم؛ فقط حواستون باشه این کش رو هر چند ساعت یکبار پاک کنید تا تغییرات لیست ادمینها اعمال بشه.
مرحله ۳: کد کامل یکپارچه
حالا همهچیز — از جمله توابع ضداسپم و خوشآمدگویی که در قسمتهای قبل ساختیم — رو کنار هم میذاریم:
import requests
import time
import re
from collections import defaultdict
BOT_TOKEN = "YOUR_TELEGRAM_TOKEN"
BASE_URL = f"https://api.telegram.org/bot{BOT_TOKEN}"
LINK_PATTERN = re.compile(r"(https?://|www\.|t\.me/|@[a-zA-Z0-9_]{5,})")
user_message_log = defaultdict(list)
last_messages = defaultdict(str)
admin_cache = {}
SPAM_THRESHOLD = 5
TIME_WINDOW = 10
def send_message(chat_id, text):
requests.post(f"{BASE_URL}/sendMessage", data={"chat_id": chat_id, "text": text})
def delete_message(chat_id, message_id):
requests.post(f"{BASE_URL}/deleteMessage", data={"chat_id": chat_id, "message_id": message_id})
def get_admin_ids(chat_id):
if chat_id not in admin_cache:
res = requests.get(f"{BASE_URL}/getChatAdministrators", params={"chat_id": chat_id}).json()
admin_cache[chat_id] = [a["user"]["id"] for a in res.get("result", [])]
return admin_cache[chat_id]
def is_admin(chat_id, user_id):
return user_id in get_admin_ids(chat_id)
def contains_link(text):
return bool(LINK_PATTERN.search(text or ""))
def is_spamming(user_id):
now = time.time()
user_message_log[user_id] = [t for t in user_message_log[user_id] if now - t < TIME_WINDOW]
user_message_log[user_id].append(now)
return len(user_message_log[user_id]) > SPAM_THRESHOLD
def welcome_new_member(chat_id, member):
name = member.get("first_name", "دوست عزیز")
send_message(chat_id, f"سلام {name}! 👋 به گروه خوش اومدی. لطفاً قوانین پینشده رو بخون.")
def handle_message(message):
chat_id = message["chat"]["id"]
user_id = message["from"]["id"]
text = message.get("text", "")
message_id = message["message_id"]
if message.get("new_chat_members"):
for member in message["new_chat_members"]:
welcome_new_member(chat_id, member)
return
if is_admin(chat_id, user_id):
return # ادمین از همهی بررسیها معافه
if contains_link(text):
delete_message(chat_id, message_id)
send_message(chat_id, "⚠️ ارسال لینک در این گروه مجاز نیست.")
return
if is_spamming(user_id):
delete_message(chat_id, message_id)
send_message(chat_id, "⚠️ لطفاً از ارسال پیدرپی پیام خودداری کنید.")
return
def main():
offset = None
print("ربات مدیریت گروه در حال اجراست...")
while True:
params = {"timeout": 20}
if offset:
params["offset"] = offset
updates = requests.get(f"{BASE_URL}/getUpdates", params=params).json()
for update in updates.get("result", []):
offset = update["update_id"] + 1
if "message" in update:
handle_message(update["message"])
time.sleep(1)
if __name__ == "__main__":
main()مرحله ۴: اجرای دائمی روی سرور
برای اینکه ربات ۲۴ساعته فعال بمونه، باید بهعنوان یک سرویس پسزمینه روی سرور اجرا بشه (نه فقط در ترمینال شخصیتون) — با ابزاری مثل systemd یا supervisor، دقیقاً همون چیزی که در راهنمای ساخت ربات بله هم بهش اشاره کردیم.
خلاصهی کل سری
| قسمت | موضوع |
|---|---|
| ۱ | چرا و چه ویژگیهایی |
| ۲ | ضداسپم رفتاری |
| ۳ | خوشآمدگویی هوشمند |
| ۴ | ترکیب کامل + ضدلینک (همین مقاله) |
قدم بعدی: چطور گسترشش بدیم
- دیتابیس بهجای حافظه: برای گروههای بزرگ،
user_message_logوadmin_cacheرو به Redis یا یک دیتابیس سبک منتقل کنید. - سیستم اخطار پلکانی: بهجای حذف فوری، چند اخطار قبل از اقدام سختگیرانهتر بدید.
- پنل مدیریت: یک رابط وب برای تنظیم آستانهها بدون نیاز به ویرایش کد.
سوالات متداول
آیا این کد آمادهی استفادهی تجاریه؟
بهعنوان پایهی یادگیری و یک نسخهی کاربردی، بله؛ برای مقیاس بزرگ، پیشنهادهای بخش «گسترش» رو هم اضافه کنید.
چرا از دیکشنری بهجای دیتابیس استفاده کردیم؟
برای سادهنگهداشتن آموزش؛ در production واقعی با ریستارت سرور، این دادهها از بین میرن.
اگه نمیخوام اینقدر کد بنویسم و نگهداری کنم چیکار کنم؟
سورس آمادهی ربات ضدلینک و مدیریت گروه ما دقیقاً همین قابلیتها رو، بهعلاوهی پنل مدیریت کامل، آماده داره.
جمعبندی
با این چهار قسمت، از صفر تا یک ربات کامل مدیریت گروه رفتیم — ضدلینک، ضداسپم رفتاری، خوشآمدگویی هوشمند و ادغام همه در یک فایل واحد. اگه ترجیح میدید بهجای ساخت، همین امروز شروع کنید، نسخهی آماده رو ببینید.
نظرات کاربران
فقط نظرات تاییدشده مدیر نمایش داده میشود.