ysn-rfd/text-dataset-tiny-code-script-py-format
USED of tahamajs/medicine_ds_persian for .parquet file USED of Alijafarixcs2/persian-it-llama2-2k for .parquet file USED of Abirate/english_quotes for .jsonl file NEW FILES (05/12/2025) NEW FILES (12/26/2025) NEW FILES (02/15/2026)
31.7k
1# admin_panel.py2 3import os4import json5import logging6import csv7import io8import asyncio9from datetime import datetime, timedelta10from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup11from telegram.ext import ContextTypes, CommandHandler, CallbackQueryHandler12from telegram.error import TelegramError13 14# --- کتابخانههای جدید برای ویژگیهای اضافه شده ---15import matplotlib16matplotlib.use('Agg') # تنظیم برای استفاده در محیط بدون رابط کاربری گرافیکی17import matplotlib.pyplot as plt18import pandas as pd19import tempfile20import psutil21import platform22 23# --- سیستم Context هوشمند ---24try:25 from smart_context import IntelligentContextManager26 HAS_SMART_CONTEXT = True27except ImportError:28 HAS_SMART_CONTEXT = False29 30# --- تنظیمات ---31ADMIN_IDS = list(map(int, os.environ.get("ADMIN_IDS", "").split(','))) if os.environ.get("ADMIN_IDS") else []32 33# وارد کردن مدیر دادهها34import data_manager35 36logger = logging.getLogger(__name__)37 38# --- دکوراتور برای دسترسی ادمین ---39 40def admin_only(func):41 """این دکوراتور تضمین میکند که فقط ادمینها بتوانند دستور را اجرا کنند."""42 async def wrapped(update: Update, context: ContextTypes.DEFAULT_TYPE, *args, **kwargs):43 if update.effective_user.id not in ADMIN_IDS:44 await update.message.reply_text("⛔️ شما دسترسی لازم برای اجرای این دستور را ندارید.")45 return46 return await func(update, context, *args, **kwargs)47 return wrapped48 49# --- دیکشنری برای مدیران Context هوشمند ---50smart_context_managers = {}51 52def _get_smart_context_for_user(user_id: int) -> IntelligentContextManager:53 """دریافت مدیر Context هوشمند برای کاربر"""54 if user_id not in smart_context_managers:55 smart_context_managers[user_id] = IntelligentContextManager(user_id)56 return smart_context_managers[user_id]57 58# --- هندلرهای دستورات ادمین ---59 60@admin_only61async def admin_commands(update: Update, context: ContextTypes.DEFAULT_TYPE):62 """نمایش تمام دستورات موجود ادمین."""63 commands_text = (64 "📋 **دستورات ادمین ربات:**\n\n"65 "📊 `/stats` - نمایش آمار ربات\n"66 "📢 `/broadcast [پیام]` - ارسال پیام به تمام کاربران\n"67 "🎯 `/targeted_broadcast [معیار] [مقدار] [پیام]` - ارسال پیام هدفمند\n"68 "📅 `/schedule_broadcast [YYYY-MM-DD] [HH:MM] [پیام]` - ارسال برنامهریزی شده\n"69 "📋 `/list_scheduled` - نمایش لیست ارسالهای برنامهریزی شده\n"70 "🗑️ `/remove_scheduled [شماره]` - حذف ارسال برنامهریزی شده\n"71 "🚫 `/ban [آیدی]` - مسدود کردن کاربر\n"72 "✅ `/unban [آیدی]` - رفع مسدودیت کاربر\n"73 "💌 `/direct_message [آیدی] [پیام]` - ارسال پیام مستقیم به کاربر\n"74 "ℹ️ `/user_info [آیدی]` - نمایش اطلاعات کاربر\n"75 "📝 `/logs` - نمایش آخرین لاگها\n"76 "📂 `/logs_file` - دانلود فایل کامل لاگها\n"77 "👥 `/users_list [صفحه]` - نمایش لیست کاربران\n"78 "🔍 `/user_search [نام]` - جستجوی کاربر بر اساس نام\n"79 "💾 `/backup` - ایجاد نسخه پشتیبان از دادهها\n"80 "📊 `/export_csv` - دانلود اطلاعات کاربران در فایل CSV\n"81 "🔧 `/maintenance [on/off]` - فعال/غیرفعال کردن حالت نگهداری\n"82 "👋 `/set_welcome [پیام]` - تنظیم پیام خوشامدگویی\n"83 "👋 `/set_goodbye [پیام]` - تنظیم پیام خداحافظی\n"84 "📈 `/activity_heatmap` - دریافت نمودار فعالیت کاربران\n"85 "⏱️ `/response_stats` - نمایش آمار زمان پاسخگویی\n"86 "🚫 `/add_blocked_word [کلمه]` - افزودن کلمه مسدود\n"87 "✅ `/remove_blocked_word [کلمه]` - حذف کلمه مسدود\n"88 "📜 `/list_blocked_words` - نمایش لیست کلمات مسدود\n"89 "💻 `/system_info` - نمایش اطلاعات سیستم\n"90 "🔄 `/reset_stats [messages/all]` - ریست کردن آمار\n"91 "🗑️ `/clear_context [آیدی]` - پاک کردن context کاربر\n"92 "📋 `/view_context [آیدی]` - مشاهده context کاربر\n"93 )94 95 if HAS_SMART_CONTEXT:96 commands_text += (97 "\n🧠 **دستورات Context هوشمند:**\n"98 "🧠 `/smart_stats [آیدی]` - آمار context هوشمند کاربر\n"99 "🔄 `/reset_smart_context [آیدی]` - ریست context هوشمند کاربر\n"100 "📊 `/smart_analytics` - تحلیل کلی context هوشمند\n"101 )102 103 commands_text += "\n📋 `/commands` - نمایش این لیست دستورات"104 105 await update.message.reply_text(commands_text, parse_mode='Markdown')106 107@admin_only108async def admin_stats(update: Update, context: ContextTypes.DEFAULT_TYPE):109 """آمار ربات را نمایش میدهد."""110 total_users = len(data_manager.DATA['users'])111 total_messages = data_manager.DATA['stats']['total_messages']112 banned_count = len(data_manager.DATA['banned_users'])113 114 now = datetime.now()115 active_24h = sum(1 for user in data_manager.DATA['users'].values() 116 if 'last_seen' in user and 117 datetime.strptime(user['last_seen'], '%Y-%m-%d %H:%M:%S') > now - timedelta(hours=24))118 119 active_7d = sum(1 for user in data_manager.DATA['users'].values() 120 if 'last_seen' in user and 121 datetime.strptime(user['last_seen'], '%Y-%m-%d %H:%M:%S') > now - timedelta(days=7))122 123 active_users = sorted(124 data_manager.DATA['users'].items(),125 key=lambda item: item[1].get('last_seen', ''),126 reverse=True127 )[:5]128 129 active_users_text = "\n".join(130 [f"• {user_id}: {info.get('first_name', 'N/A')} (آخرین فعالیت: {info.get('last_seen', 'N/A')})"131 for user_id, info in active_users]132 )133 134 # آمار context135 users_with_context = sum(1 for user in data_manager.DATA['users'].values() 136 if user.get('context') and len(user['context']) > 0)137 total_context_messages = sum(len(user.get('context', [])) for user in data_manager.DATA['users'].values())138 139 # آمار Context هوشمند140 smart_context_stats = ""141 if HAS_SMART_CONTEXT:142 users_with_smart_context = sum(1 for user in data_manager.DATA['users'].values()143 if user.get('smart_context'))144 smart_context_stats = f"🧠 **کاربران با Context هوشمند:** `{users_with_smart_context}`\n"145 146 text = (147 f"📊 **آمار ربات**\n\n"148 f"👥 **تعداد کل کاربران:** `{total_users}`\n"149 f"📝 **تعداد کل پیامها:** `{total_messages}`\n"150 f"🚫 **کاربران مسدود شده:** `{banned_count}`\n"151 f"🟢 **کاربران فعال 24 ساعت گذشته:** `{active_24h}`\n"152 f"🟢 **کاربران فعال 7 روز گذشته:** `{active_7d}`\n"153 f"💭 **کاربران با context فعال:** `{users_with_context}`\n"154 f"💬 **کل پیامهای context:** `{total_context_messages}`\n"155 f"{smart_context_stats}\n"156 f"**۵ کاربر اخیر فعال:**\n{active_users_text}"157 )158 await update.message.reply_text(text, parse_mode='Markdown')159 160@admin_only161async def admin_broadcast(update: Update, context: ContextTypes.DEFAULT_TYPE):162 """یک پیام را به تمام کاربران ارسال میکند."""163 if not context.args:164 await update.message.reply_text("⚠️ لطفاً پیامی برای ارسال بنویسید.\nمثال: `/broadcast سلام به همه!`")165 return166 167 message_text = " ".join(context.args)168 user_ids = list(data_manager.DATA['users'].keys())169 total_sent = 0170 total_failed = 0171 172 await update.message.reply_text(f"📣 در حال ارسال پیام به `{len(user_ids)}` کاربر...")173 174 for user_id_str in user_ids:175 try:176 await context.bot.send_message(chat_id=int(user_id_str), text=message_text)177 total_sent += 1178 await asyncio.sleep(0.05)179 except TelegramError as e:180 logger.warning(f"Failed to send broadcast to {user_id_str}: {e}")181 total_failed += 1182 183 result_text = (184 f"✅ **ارسال همگانی تمام شد**\n\n"185 f"✅ موفق: `{total_sent}`\n"186 f"❌ ناموفق: `{total_failed}`"187 )188 await update.message.reply_text(result_text, parse_mode='Markdown')189 190@admin_only191async def admin_targeted_broadcast(update: Update, context: ContextTypes.DEFAULT_TYPE):192 """ارسال پیام به گروه خاصی از کاربران بر اساس معیارهای مشخص."""193 if len(context.args) < 3:194 await update.message.reply_text("⚠️ فرمت صحیح: `/targeted_broadcast [معیار] [مقدار] [پیام]`\n"195 "معیارهای موجود: `active_days`, `message_count`, `banned`")196 return197 198 criteria = context.args[0].lower()199 value = context.args[1]200 message_text = " ".join(context.args[2:])201 202 target_users = []203 204 if criteria == "active_days":205 try:206 days = int(value)207 target_users = data_manager.get_active_users(days)208 except ValueError:209 await update.message.reply_text("⚠️ مقدار روز باید یک عدد صحیح باشد.")210 return211 212 elif criteria == "message_count":213 try:214 min_count = int(value)215 target_users = data_manager.get_users_by_message_count(min_count)216 except ValueError:217 await update.message.reply_text("⚠️ تعداد پیام باید یک عدد صحیح باشد.")218 return219 220 elif criteria == "banned":221 if value.lower() == "true":222 target_users = list(data_manager.DATA['banned_users'])223 elif value.lower() == "false":224 for user_id in data_manager.DATA['users']:225 if int(user_id) not in data_manager.DATA['banned_users']:226 target_users.append(int(user_id))227 else:228 await update.message.reply_text("⚠️ مقدار برای معیار banned باید true یا false باشد.")229 return230 231 else:232 await update.message.reply_text("⚠️ معیار نامعتبر است. معیارهای موجود: active_days, message_count, banned")233 return234 235 if not target_users:236 await update.message.reply_text("هیچ کاربری با معیارهای مشخص شده یافت نشد.")237 return238 239 await update.message.reply_text(f"📣 در حال ارسال پیام به `{len(target_users)}` کاربر...")240 241 total_sent, total_failed = 0, 0242 for user_id in target_users:243 try:244 await context.bot.send_message(chat_id=user_id, text=message_text)245 total_sent += 1246 await asyncio.sleep(0.05)247 except TelegramError as e:248 logger.warning(f"Failed to send targeted broadcast to {user_id}: {e}")249 total_failed += 1250 251 result_text = f"✅ **ارسال هدفمند تمام شد**\n\n✅ موفق: `{total_sent}`\n❌ ناموفق: `{total_failed}`"252 await update.message.reply_text(result_text, parse_mode='Markdown')253 254@admin_only255async def admin_schedule_broadcast(update: Update, context: ContextTypes.DEFAULT_TYPE):256 """تنظیم ارسال برنامهریزی شده پیام به همه کاربران."""257 if len(context.args) < 3:258 await update.message.reply_text("⚠️ فرمت صحیح: `/schedule_broadcast [YYYY-MM-DD] [HH:MM] [پیام]`")259 return260 261 try:262 date_str, time_str = context.args[0], context.args[1]263 message_text = " ".join(context.args[2:])264 265 scheduled_time = datetime.strptime(f"{date_str} {time_str}", '%Y-%m-%d %H:%M')266 267 if scheduled_time <= datetime.now():268 await update.message.reply_text("⚠️ زمان برنامهریزی شده باید در آینده باشد.")269 return270 271 data_manager.DATA['scheduled_broadcasts'].append({272 'time': scheduled_time.strftime('%Y-%m-%d %H:%M:%S'),273 'message': message_text,274 'status': 'pending'275 })276 data_manager.save_data()277 278 await update.message.reply_text(f"✅ پیام برای زمان `{scheduled_time.strftime('%Y-%m-%d %H:%M')}` برنامهریزی شد.")279 280 except ValueError:281 await update.message.reply_text("⚠️ فرمت زمان نامعتبر است. لطفاً از فرمت YYYY-MM-DD HH:MM استفاده کنید.")282 283@admin_only284async def admin_list_scheduled_broadcasts(update: Update, context: ContextTypes.DEFAULT_TYPE):285 """نمایش لیست ارسالهای برنامهریزی شده."""286 if not data_manager.DATA['scheduled_broadcasts']:287 await update.message.reply_text("هیچ ارسال برنامهریزی شدهای وجود ندارد.")288 return289 290 broadcasts_text = "📅 **لیست ارسالهای برنامهریزی شده:**\n\n"291 for i, broadcast in enumerate(data_manager.DATA['scheduled_broadcasts'], 1):292 status_emoji = "✅" if broadcast['status'] == 'sent' else "⏳"293 broadcasts_text += f"{i}. {status_emoji} `{broadcast['time']}` - {broadcast['message'][:50]}...\n"294 295 await update.message.reply_text(broadcasts_text, parse_mode='Markdown')296 297@admin_only298async def admin_remove_scheduled_broadcast(update: Update, context: ContextTypes.DEFAULT_TYPE):299 """حذف یک ارسال برنامهریزی شده."""300 if not context.args or not context.args[0].isdigit():301 await update.message.reply_text("⚠️ لطفاً شماره ارسال برنامهریزی شده را وارد کنید.\nمثال: `/remove_scheduled 1`")302 return303 304 index = int(context.args[0]) - 1305 306 if not data_manager.DATA['scheduled_broadcasts'] or not (0 <= index < len(data_manager.DATA['scheduled_broadcasts'])):307 await update.message.reply_text("⚠️ شماره ارسال برنامهریزی شده نامعتبر است.")308 return309 310 removed_broadcast = data_manager.DATA['scheduled_broadcasts'].pop(index)311 data_manager.save_data()312 313 await update.message.reply_text(f"✅ ارسال برنامهریزی شده برای زمان `{removed_broadcast['time']}` حذف شد.")314 315@admin_only316async def admin_ban(update: Update, context: ContextTypes.DEFAULT_TYPE):317 """یک کاربر را با آیدی عددی مسدود کرده و به او اطلاع میدهد."""318 if not context.args or not context.args[0].isdigit():319 await update.message.reply_text("⚠️ لطفاً آیدی عددی کاربر را وارد کنید.\nمثال: `/ban 123456789`")320 return321 322 user_id_to_ban = int(context.args[0])323 324 if user_id_to_ban in ADMIN_IDS:325 await update.message.reply_text("🛡️ شما نمیتوانید یک ادمین را مسدود کنید!")326 return327 328 if data_manager.is_user_banned(user_id_to_ban):329 await update.message.reply_text(f"کاربر `{user_id_to_ban}` از قبل مسدود شده است.")330 return331 332 data_manager.ban_user(user_id_to_ban)333 334 # ارسال پیام به کاربر مسدود شده335 try:336 await context.bot.send_message(337 chat_id=user_id_to_ban, 338 text="⛔️ شما توسط ادمین ربات مسدود شدید و دیگر نمیتوانید از خدمات ربات استفاده کنید."339 )340 except TelegramError as e:341 logger.warning(f"Could not send ban notification to user {user_id_to_ban}: {e}")342 343 await update.message.reply_text(f"✅ کاربر `{user_id_to_ban}` با موفقیت مسدود شد.", parse_mode='Markdown')344 345@admin_only346async def admin_unban(update: Update, context: ContextTypes.DEFAULT_TYPE):347 """مسدودیت یک کاربر را برمیدارد و به او اطلاع میدهد."""348 if not context.args or not context.args[0].isdigit():349 await update.message.reply_text("⚠️ لطفاً آیدی عددی کاربر را وارد کنید.\nمثال: `/unban 123456789`")350 return351 352 user_id_to_unban = int(context.args[0])353 354 if not data_manager.is_user_banned(user_id_to_unban):355 await update.message.reply_text(f"کاربر `{user_id_to_unban}` در لیست مسدود شدهها وجود ندارد.")356 return357 358 data_manager.unban_user(user_id_to_unban)359 360 # ارسال پیام به کاربر برای رفع مسدودیت361 try:362 await context.bot.send_message(363 chat_id=user_id_to_unban, 364 text="✅ مسدودیت شما توسط ادمین ربات برداشته شد. میتوانید دوباره از ربات استفاده کنید."365 )366 except TelegramError as e:367 logger.warning(f"Could not send unban notification to user {user_id_to_unban}: {e}")368 369 await update.message.reply_text(f"✅ مسدودیت کاربر `{user_id_to_unban}` با موفقیت برداشته شد.", parse_mode='Markdown')370 371@admin_only372async def admin_direct_message(update: Update, context: ContextTypes.DEFAULT_TYPE):373 """ارسال پیام مستقیم به یک کاربر خاص."""374 if len(context.args) < 2:375 await update.message.reply_text("⚠️ فرمت صحیح: `/direct_message [آیدی] [پیام]`")376 return377 378 user_id_str = context.args[0]379 if not user_id_str.isdigit():380 await update.message.reply_text("⚠️ لطفاً یک آیدی عددی معتبر وارد کنید.")381 return382 383 message_text = " ".join(context.args[1:])384 user_id = int(user_id_str)385 386 try:387 await context.bot.send_message(chat_id=user_id, text=message_text)388 await update.message.reply_text(f"✅ پیام با موفقیت به کاربر `{user_id}` ارسال شد.", parse_mode='Markdown')389 except TelegramError as e:390 await update.message.reply_text(f"❌ خطا در ارسال پیام: {e}")391 392@admin_only393async def admin_userinfo(update: Update, context: ContextTypes.DEFAULT_TYPE):394 """اطلاعات یک کاربر خاص را نمایش میدهد."""395 if not context.args or not context.args[0].isdigit():396 await update.message.reply_text("⚠️ لطفاً آیدی عددی کاربر را وارد کنید.\nمثال: `/user_info 123456789`")397 return398 399 user_id = int(context.args[0])400 user_info = data_manager.DATA['users'].get(str(user_id))401 402 if not user_info:403 await update.message.reply_text(f"کاربری با آیدی `{user_id}` در دیتابیس یافت نشد.")404 return405 406 is_banned = "بله" if data_manager.is_user_banned(user_id) else "خیر"407 408 if 'first_seen' in user_info and 'last_seen' in user_info:409 first_date = datetime.strptime(user_info['first_seen'], '%Y-%m-%d %H:%M:%S')410 last_date = datetime.strptime(user_info['last_seen'], '%Y-%m-%d %H:%M:%S')411 days_active = max(1, (last_date - first_date).days)412 avg_messages = user_info.get('message_count', 0) / days_active413 else:414 avg_messages = user_info.get('message_count', 0)415 416 # اطلاعات context417 context_messages = len(user_info.get('context', []))418 context_tokens = data_manager.get_context_token_count(user_id)419 420 # اطلاعات Context هوشمند421 smart_context_info = ""422 if HAS_SMART_CONTEXT and 'smart_context' in user_info:423 smart_data = user_info['smart_context']424 if 'profile' in smart_data:425 interests = smart_data['profile'].get('interests', [])426 if interests:427 smart_context_info = f"\n🧠 **علاقهمندیها:** {', '.join(interests[:3])}"428 429 text = (430 f"ℹ️ **اطلاعات کاربر**\n\n"431 f"🆔 **آیدی:** `{user_id}`\n"432 f"👤 **نام:** {user_info.get('first_name', 'N/A')}\n"433 f"🔷 **نام کاربری:** @{user_info.get('username', 'N/A')}\n"434 f"📊 **تعداد پیامها:** `{user_info.get('message_count', 0)}`\n"435 f"📈 **میانگین پیام در روز:** `{avg_messages:.2f}`\n"436 f"📅 **اولین پیام:** {user_info.get('first_seen', 'N/A')}\n"437 f"🕒 **آخرین فعالیت:** {user_info.get('last_seen', 'N/A')}\n"438 f"💭 **پیامهای context:** `{context_messages}`\n"439 f"🔢 **توکنهای context:** `{context_tokens}`\n"440 f"🚫 **وضعیت مسدودیت:** {is_banned}"441 f"{smart_context_info}"442 )443 await update.message.reply_text(text, parse_mode='Markdown')444 445@admin_only446async def admin_logs(update: Update, context: ContextTypes.DEFAULT_TYPE):447 """آخرین خطوط لاگ ربات را ارسال میکند."""448 try:449 with open(data_manager.LOG_FILE, "r", encoding="utf-8") as f:450 lines = f.readlines()451 last_lines = lines[-30:]452 log_text = "".join(last_lines)453 if not log_text:454 await update.message.reply_text("فایل لاگ خالی است.")455 return456 457 if len(log_text) > 4096:458 for i in range(0, len(log_text), 4096):459 await update.message.reply_text(f"```{log_text[i:i+4096]}```", parse_mode='Markdown')460 else:461 await update.message.reply_text(f"```{log_text}```", parse_mode='Markdown')462 463 except FileNotFoundError:464 await update.message.reply_text("فایل لاگ یافت نشد.")465 except Exception as e:466 await update.message.reply_text(f"خطایی در خواندن لاگ رخ داد: {e}")467 468@admin_only469async def admin_logs_file(update: Update, context: ContextTypes.DEFAULT_TYPE):470 """فایل کامل لاگ ربات را ارسال میکند."""471 try:472 await update.message.reply_document(473 document=open(data_manager.LOG_FILE, 'rb'),474 caption="📂 فایل کامل لاگهای ربات"475 )476 except FileNotFoundError:477 await update.message.reply_text("فایل لاگ یافت نشد.")478 except Exception as e:479 await update.message.reply_text(f"خطایی در ارسال فایل لاگ رخ داد: {e}")480 481@admin_only482async def admin_users_list(update: Update, context: ContextTypes.DEFAULT_TYPE):483 """نمایش لیست کامل کاربران با صفحهبندی."""484 users = data_manager.DATA['users']485 486 page = 1487 if context.args and context.args[0].isdigit():488 page = int(context.args[0])489 if page < 1: page = 1490 491 users_per_page = 20492 total_users = len(users)493 total_pages = (total_users + users_per_page - 1) // users_per_page494 495 if page > total_pages: page = total_pages496 497 start_idx = (page - 1) * users_per_page498 end_idx = min(start_idx + users_per_page, total_users)499 500 sorted_users = sorted(users.items(), key=lambda item: item[1].get('last_seen', ''), reverse=True)501 502 users_text = f"👥 **لیست کاربران (صفحه {page}/{total_pages})**\n\n"503 504 for i, (user_id, user_info) in enumerate(sorted_users[start_idx:end_idx], start=start_idx + 1):505 is_banned = "🚫" if int(user_id) in data_manager.DATA['banned_users'] else "✅"506 username = user_info.get('username', 'N/A')507 first_name = user_info.get('first_name', 'N/A')508 last_seen = user_info.get('last_seen', 'N/A')509 message_count = user_info.get('message_count', 0)510 context_count = len(user_info.get('context', []))511 512 users_text += f"{i}. {is_banned} `{user_id}` - {first_name} (@{username})\n"513 users_text += f" 📝 پیامها: `{message_count}` | 💭 context: `{context_count}`\n"514 users_text += f" ⏰ آخرین فعالیت: `{last_seen}`\n\n"515 516 keyboard = []517 if page > 1: keyboard.append([InlineKeyboardButton("⬅️ صفحه قبل", callback_data=f"users_list:{page-1}")])518 if page < total_pages: keyboard.append([InlineKeyboardButton("➡️ صفحه بعد", callback_data=f"users_list:{page+1}")])519 520 reply_markup = InlineKeyboardMarkup(keyboard) if keyboard else None521 await update.message.reply_text(users_text, parse_mode='Markdown', reply_markup=reply_markup)522 523@admin_only524async def admin_user_search(update: Update, context: ContextTypes.DEFAULT_TYPE):525 """جستجوی کاربر بر اساس نام یا نام کاربری."""526 if not context.args:527 await update.message.reply_text("⚠️ لطفاً نام یا نام کاربری برای جستجو وارد کنید.\nمثال: `/user_search علی`")528 return529 530 search_term = " ".join(context.args).lower()531 users = data_manager.DATA['users']532 533 matching_users = []534 for user_id, user_info in users.items():535 # استفاده از (value or '') برای جلوگیری از خطا در صورت وجود None536 first_name = (user_info.get('first_name') or '').lower()537 username = (user_info.get('username') or '').lower()538 539 if search_term in first_name or search_term in username:540 is_banned = "🚫" if int(user_id) in data_manager.DATA['banned_users'] else "✅"541 matching_users.append((user_id, user_info, is_banned))542 543 if not matching_users:544 await update.message.reply_text(f"هیچ کاربری با نام «{search_term}» یافت نشد.")545 return546 547 results_text = f"🔍 **نتایج جستجو برای «{search_term}»**\n\n"548 549 for user_id, user_info, is_banned in matching_users:550 username_display = user_info.get('username', 'N/A')551 first_name_display = user_info.get('first_name', 'N/A')552 last_seen = user_info.get('last_seen', 'N/A')553 message_count = user_info.get('message_count', 0)554 context_count = len(user_info.get('context', []))555 556 results_text += f"{is_banned} `{user_id}` - {first_name_display} (@{username_display})\n"557 results_text += f" 📝 پیامها: `{message_count}` | 💭 context: `{context_count}`\n"558 results_text += f" ⏰ آخرین فعالیت: `{last_seen}`\n\n"559 560 await update.message.reply_text(results_text, parse_mode='Markdown')561 562@admin_only563async def admin_backup(update: Update, context: ContextTypes.DEFAULT_TYPE):564 """ایجاد نسخه پشتیبان از دادههای ربات."""565 try:566 timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')567 backup_file = f"bot_backup_{timestamp}.json"568 569 data_to_backup = data_manager.DATA.copy()570 data_to_backup['banned_users'] = list(data_manager.DATA['banned_users'])571 572 with open(backup_file, 'w', encoding='utf-8') as f:573 json.dump(data_to_backup, f, indent=4, ensure_ascii=False)574 575 await update.message.reply_document(576 document=open(backup_file, 'rb'),577 caption=f"✅ نسخه پشتیبان با موفقیت ایجاد شد: {backup_file}"578 )579 580 logger.info(f"Backup created: {backup_file}")581 os.remove(backup_file) # حذف فایل پس از ارسال582 except Exception as e:583 await update.message.reply_text(f"❌ خطا در ایجاد نسخه پشتیبان: {e}")584 logger.error(f"Error creating backup: {e}")585 586@admin_only587async def admin_export_csv(update: Update, context: ContextTypes.DEFAULT_TYPE):588 """ایجاد و ارسال فایل CSV از اطلاعات کاربران."""589 users = data_manager.DATA['users']590 591 df_data = []592 for user_id, user_info in users.items():593 is_banned = "بله" if int(user_id) in data_manager.DATA['banned_users'] else "خیر"594 context_count = len(user_info.get('context', []))595 context_tokens = data_manager.get_context_token_count(int(user_id))596 597 df_data.append({598 'User ID': user_id,599 'First Name': user_info.get('first_name', 'N/A'),600 'Username': user_info.get('username', 'N/A'),601 'Message Count': user_info.get('message_count', 0),602 'Context Messages': context_count,603 'Context Tokens': context_tokens,604 'First Seen': user_info.get('first_seen', 'N/A'),605 'Last Seen': user_info.get('last_seen', 'N/A'),606 'Banned': is_banned607 })608 609 df = pd.DataFrame(df_data)610 611 with tempfile.NamedTemporaryFile(mode='w', suffix='.csv', delete=False, encoding='utf-8') as f:612 df.to_csv(f.name, index=False)613 temp_file_path = f.name614 615 await update.message.reply_document(616 document=open(temp_file_path, 'rb'),617 caption="📊 فایل CSV اطلاعات کاربران"618 )619 620 os.unlink(temp_file_path)621 622@admin_only623async def admin_maintenance(update: Update, context: ContextTypes.DEFAULT_TYPE):624 """حالت نگهداری ربات را فعال یا غیرفعال کرده و به کاربران اطلاع میدهد."""625 if not context.args or context.args[0].lower() not in ['on', 'off']:626 await update.message.reply_text("⚠️ فرمت صحیح: `/maintenance on` یا `/maintenance off`")627 return628 629 status = context.args[0].lower()630 631 if status == 'on':632 if data_manager.DATA.get('maintenance_mode', False):633 await update.message.reply_text("🔧 ربات از قبل در حالت نگهداری قرار دارد.")634 return635 636 data_manager.DATA['maintenance_mode'] = True637 data_manager.save_data()638 639 await update.message.reply_text("✅ حالت نگهداری ربات فعال شد. در حال اطلاعرسانی به کاربران...")640 641 user_ids = list(data_manager.DATA['users'].keys())642 for user_id_str in user_ids:643 try:644 # به ادمینها پیام ارسال نشود645 if int(user_id_str) not in ADMIN_IDS:646 await context.bot.send_message(647 chat_id=int(user_id_str), 648 text="🔧 ربات در حال حاضر در حالت بهروزرسانی و نگهداری قرار دارد. لطفاً چند لحظه دیگر صبر کنید. از صبر شما سپاسگزاریم!"649 )650 await asyncio.sleep(0.05) # جلوگیری از محدودیت تلگرام651 except TelegramError:652 continue # نادیده گرفتن کاربرانی که ربات را مسدود کردهاند653 654 elif status == 'off':655 if not data_manager.DATA.get('maintenance_mode', False):656 await update.message.reply_text("✅ ربات از قبل در حالت عادی قرار دارد.")657 return658 659 data_manager.DATA['maintenance_mode'] = False660 data_manager.save_data()661 662 await update.message.reply_text("✅ حالت نگهداری ربات غیرفعال شد. در حال اطلاعرسانی به کاربران...")663 664 user_ids = list(data_manager.DATA['users'].keys())665 for user_id_str in user_ids:666 try:667 if int(user_id_str) not in ADMIN_IDS:668 await context.bot.send_message(669 chat_id=int(user_id_str), 670 text="✅ بهروزرسانی ربات به پایان رسید. از صبر شما سپاسگزاریم! میتوانید دوباره از ربات استفاده کنید."671 )672 await asyncio.sleep(0.05)673 except TelegramError:674 continue675 676@admin_only677async def admin_set_welcome_message(update: Update, context: ContextTypes.DEFAULT_TYPE):678 """تنظیم پیام خوشامدگویی جدید."""679 if not context.args:680 await update.message.reply_text("⚠️ لطفاً پیام خوشامدگویی جدید را وارد کنید.\n"681 "مثال: `/set_welcome سلام {user_mention}! به ربات خوش آمدید.`")682 return683 684 new_message = " ".join(context.args)685 data_manager.DATA['welcome_message'] = new_message686 data_manager.save_data()687 688 await update.message.reply_text("✅ پیام خوشامدگویی با موفقیت بهروزرسانی شد.")689 690@admin_only691async def admin_set_goodbye_message(update: Update, context: ContextTypes.DEFAULT_TYPE):692 """تنظیم پیام خداحافظی جدید."""693 if not context.args:694 await update.message.reply_text("⚠️ لطفاً پیام خداحافظی جدید را وارد کنید.\n"695 "مثال: `/set_goodbye {user_mention}، خداحافظ!`")696 return697 698 new_message = " ".join(context.args)699 data_manager.DATA['goodbye_message'] = new_message700 data_manager.save_data()701 702 await update.message.reply_text("✅ پیام خداحافظی با موفقیت بهروزرسانی شد.")703 704@admin_only705async def admin_activity_heatmap(update: Update, context: ContextTypes.DEFAULT_TYPE):706 """ایجاد و ارسال نمودار فعالیت کاربران."""707 users = data_manager.DATA['users']708 activity_hours = [0] * 24709 710 for user_info in users.values():711 if 'last_seen' in user_info:712 try:713 last_seen = datetime.strptime(user_info['last_seen'], '%Y-%m-%d %H:%M:%S')714 activity_hours[last_seen.hour] += 1715 except ValueError:716 continue717 718 plt.figure(figsize=(12, 6))719 plt.bar(range(24), activity_hours, color='skyblue')720 plt.title('نمودار فعالیت کاربران بر اساس ساعت')721 plt.xlabel('ساعت')722 plt.ylabel('تعداد کاربران فعال')723 plt.xticks(range(24))724 plt.grid(axis='y', alpha=0.3)725 726 with tempfile.NamedTemporaryFile(suffix='.png', delete=False) as f:727 plt.savefig(f.name, bbox_inches='tight')728 temp_file_path = f.name729 730 plt.close()731 732 await update.message.reply_photo(733 photo=open(temp_file_path, 'rb'),734 caption="📊 نمودار فعالیت کاربران بر اساس ساعت"735 )736 737 os.unlink(temp_file_path)738 739@admin_only740async def admin_response_stats(update: Update, context: ContextTypes.DEFAULT_TYPE):741 """نمایش آمار زمان پاسخگویی ربات."""742 stats = data_manager.DATA['stats']743 await update.message.reply_text(744 "📈 **آمار زمان پاسخگویی ربات**\n\n"745 f"🟢 میانگین زمان پاسخگویی: `{stats.get('avg_response_time', 0):.2f}` ثانیه\n"746 f"🔴 بیشترین زمان پاسخگویی: `{stats.get('max_response_time', 0):.2f}` ثانیه\n"747 f"🟢 کمترین زمان پاسخگویی: `{stats.get('min_response_time', 0):.2f}` ثانیه\n"748 f"📊 کل پاسخهای ثبت شده: `{stats.get('total_responses', 0)}`"749 )750 751@admin_only752async def admin_add_blocked_word(update: Update, context: ContextTypes.DEFAULT_TYPE):753 """افزودن کلمه یا عبارت به لیست کلمات مسدود شده."""754 if not context.args:755 await update.message.reply_text("⚠️ لطفاً کلمه یا عبارت مورد نظر را وارد کنید.\n"756 "مثال: `/add_blocked_word کلمه_نامناسب`")757 return758 759 word = " ".join(context.args).lower()760 761 if word in data_manager.DATA['blocked_words']:762 await update.message.reply_text(f"⚠️ کلمه «{word}» از قبل در لیست کلمات مسدود شده وجود دارد.")763 return764 765 data_manager.DATA['blocked_words'].append(word)766 data_manager.save_data()767 768 await update.message.reply_text(f"✅ کلمه «{word}» به لیست کلمات مسدود شده اضافه شد.")769 770@admin_only771async def admin_remove_blocked_word(update: Update, context: ContextTypes.DEFAULT_TYPE):772 """حذف کلمه یا عبارت از لیست کلمات مسدود شده."""773 if not context.args:774 await update.message.reply_text("⚠️ لطفاً کلمه یا عبارت مورد نظر را وارد کنید.\n"775 "مثال: `/remove_blocked_word کلمه_نامناسب`")776 return777 778 word = " ".join(context.args).lower()779 780 if word not in data_manager.DATA['blocked_words']:781 await update.message.reply_text(f"⚠️ کلمه «{word}» در لیست کلمات مسدود شده وجود ندارد.")782 return783 784 data_manager.DATA['blocked_words'].remove(word)785 data_manager.save_data()786 787 await update.message.reply_text(f"✅ کلمه «{word}» از لیست کلمات مسدود شده حذف شد.")788 789@admin_only790async def admin_list_blocked_words(update: Update, context: ContextTypes.DEFAULT_TYPE):791 """نمایش لیست کلمات مسدود شده."""792 if not data_manager.DATA['blocked_words']:793 await update.message.reply_text("هیچ کلمه مسدود شدهای در لیست وجود ندارد.")794 return795 796 words_list = "\n".join([f"• {word}" for word in data_manager.DATA['blocked_words']])797 await update.message.reply_text(f"🚫 **لیست کلمات مسدود شده:**\n\n{words_list}")798 799@admin_only800async def admin_system_info(update: Update, context: ContextTypes.DEFAULT_TYPE):801 """نمایش اطلاعات سیستم و منابع."""802 bot_start_time_str = data_manager.DATA.get('bot_start_time', datetime.now().strftime('%Y-%m-%d %H:%M:%S'))803 bot_start_time = datetime.strptime(bot_start_time_str, '%Y-%m-%d %H:%M:%S')804 uptime = datetime.now() - bot_start_time805 806 # محاسبه آمار context807 total_context_messages = sum(len(user.get('context', [])) for user in data_manager.DATA['users'].values())808 users_with_context = sum(1 for user in data_manager.DATA['users'].values() if user.get('context'))809 810 system_info = (811 f"💻 **اطلاعات سیستم:**\n\n"812 f"🖥️ سیستمعامل: {platform.system()} {platform.release()}\n"813 f"🐍 نسخه پایتون: {platform.python_version()}\n"814 f"💾 حافظه RAM استفاده شده: {psutil.virtual_memory().percent}%\n"815 f"💾 حافظه RAM آزاد: {psutil.virtual_memory().available / (1024**3):.2f} GB\n"816 f"💾 فضای دیسک استفاده شده: {psutil.disk_usage('/').percent}%\n"817 f"💾 فضای دیسک آزاد: {psutil.disk_usage('/').free / (1024**3):.2f} GB\n"818 f"⏱️ زمان اجرای ربات: {uptime}\n"819 f"💭 کاربران با context: {users_with_context}\n"820 f"💬 کل پیامهای context: {total_context_messages}"821 )822 823 await update.message.reply_text(system_info, parse_mode='Markdown')824 825@admin_only826async def admin_reset_stats(update: Update, context: ContextTypes.DEFAULT_TYPE):827 """ریست کردن آمار ربات."""828 if not context.args:829 await update.message.reply_text("⚠️ لطفاً نوع آماری که میخواهید ریست کنید را مشخص کنید.\n"830 "مثال: `/reset_stats messages` یا `/reset_stats all`")831 return832 833 stat_type = context.args[0].lower()834 835 if stat_type == "messages":836 data_manager.DATA['stats']['total_messages'] = 0837 for user_id in data_manager.DATA['users']:838 data_manager.DATA['users'][user_id]['message_count'] = 0839 await update.message.reply_text("✅ آمار پیامها با موفقیت ریست شد.")840 841 elif stat_type == "all":842 data_manager.DATA['stats'] = {843 'total_messages': 0,844 'total_users': len(data_manager.DATA['users']),845 'avg_response_time': 0,846 'max_response_time': 0,847 'min_response_time': 0,848 'total_responses': 0849 }850 for user_id in data_manager.DATA['users']:851 data_manager.DATA['users'][user_id]['message_count'] = 0852 await update.message.reply_text("✅ تمام آمارها با موفقیت ریست شد.")853 854 else:855 await update.message.reply_text("⚠️ نوع آمار نامعتبر است. گزینههای موجود: messages, all")856 return857 858 data_manager.save_data()859 860# --- دستورات مدیریت context ---861 862@admin_only863async def admin_clear_context(update: Update, context: ContextTypes.DEFAULT_TYPE):864 """پاک کردن context یک کاربر"""865 if not context.args or not context.args[0].isdigit():866 await update.message.reply_text("⚠️ لطفاً آیدی کاربر را وارد کنید.\nمثال: `/clear_context 123456789`")867 return868 869 user_id = int(context.args[0])870 data_manager.clear_user_context(user_id)871 872 # همچنین Context هوشمند را پاک کن873 if HAS_SMART_CONTEXT and user_id in smart_context_managers:874 smart_context_managers[user_id].clear_context()875 876 await update.message.reply_text(f"✅ context کاربر `{user_id}` با موفقیت پاک شد.")877 878@admin_only879async def admin_view_context(update: Update, context: ContextTypes.DEFAULT_TYPE):880 """مشاهده context یک کاربر"""881 if not context.args or not context.args[0].isdigit():882 await update.message.reply_text("⚠️ لطفاً آیدی کاربر را وارد کنید.\nمثال: `/view_context 123456789`")883 return884 885 user_id = int(context.args[0])886 user_context = data_manager.get_user_context(user_id)887 888 if not user_context:889 await update.message.reply_text(f"کاربر `{user_id}` context ندارد.")890 return891 892 context_text = f"📋 **Context کاربر `{user_id}`**\n\n"893 total_tokens = 0894 895 for i, msg in enumerate(user_context, 1):896 role_emoji = "👤" if msg['role'] == 'user' else "🤖"897 tokens = data_manager.count_tokens(msg['content'])898 total_tokens += tokens899 900 # کوتاه کردن متن طولانی901 content_preview = msg['content']902 if len(content_preview) > 100:903 content_preview = content_preview[:100] + "..."904 905 context_text += f"{i}. {role_emoji} **{msg['role']}** ({tokens} توکن)\n"906 context_text += f" ⏰ {msg.get('timestamp', 'N/A')}\n"907 context_text += f" 📝 {content_preview}\n\n"908 909 context_text += f"📊 **مجموع:** {len(user_context)} پیام، {total_tokens} توکن"910 911 await update.message.reply_text(context_text, parse_mode='Markdown')912 913# --- دستورات Context هوشمند ---914 915@admin_only916async def admin_smart_context_stats(update: Update, context: ContextTypes.DEFAULT_TYPE):917 """نمایش آمار context هوشمند برای کاربران"""918 if not HAS_SMART_CONTEXT:919 await update.message.reply_text("⚠️ سیستم context هوشمند فعال نیست.")920 return921 922 if not context.args:923 await update.message.reply_text("⚠️ لطفاً آیدی کاربر را وارد کنید.\nمثال: `/smart_stats 123456789`")924 return925 926 user_id = int(context.args[0])927 928 # بررسی وجود مدیر context929 if user_id not in smart_context_managers:930 smart_context_managers[user_id] = IntelligentContextManager(user_id)931 932 smart_context = smart_context_managers[user_id]933 summary = await asyncio.to_thread(smart_context.get_summary)934 935 stats_text = (936 f"🧠 **آمار context هوشمند کاربر** `{user_id}`\n\n"937 f"📊 **حافظه:**\n"938 f"• فعال: {summary['working_memory']} پیام\n"939 f"• اخیر: {summary['recent_memory']} پیام\n"940 f"• بلندمدت: {summary['long_term_memory']} پیام\n"941 f"• هسته: {summary['core_memory']} پیام\n\n"942 f"📈 **کارایی:**\n"943 f"• میانگین اهمیت: {summary['average_importance']:.2%}\n"944 f"• فشردهسازی: {summary['compression_ratio']:.2%}\n"945 f"• بازیابی: {summary['retrieval_efficiency']:.2%}\n\n"946 f"🎯 **علاقهمندیها:**\n"947 )948 949 interests = summary.get('profile_interests', [])950 if interests:951 stats_text += "\n".join([f"• {interest}" for interest in interests[:10]])952 else:953 stats_text += "هیچ علاقهمندی ثبت نشده است."954 955 await update.message.reply_text(stats_text, parse_mode='Markdown')956 957@admin_only958async def admin_reset_smart_context(update: Update, context: ContextTypes.DEFAULT_TYPE):959 """ریست context هوشمند کاربر"""960 if not HAS_SMART_CONTEXT:961 await update.message.reply_text("⚠️ سیستم context هوشمند فعال نیست.")962 return963 964 if not context.args:965 await update.message.reply_text("⚠️ لطفاً آیدی کاربر را وارد کنید.\nمثال: `/reset_smart_context 123456789`")966 return967 968 user_id = int(context.args[0])969 970 if user_id in smart_context_managers:971 del smart_context_managers[user_id]972 973 # همچنین از data_manager پاک کن974 user_id_str = str(user_id)975 if user_id_str in data_manager.DATA['users']:976 if 'smart_context' in data_manager.DATA['users'][user_id_str]:977 del data_manager.DATA['users'][user_id_str]['smart_context']978 data_manager.save_data()979 980 await update.message.reply_text(f"✅ context هوشمند کاربر `{user_id}` با موفقیت ریست شد.")981 982@admin_only983async def admin_smart_analytics(update: Update, context: ContextTypes.DEFAULT_TYPE):984 """تحلیل کلی Context هوشمند"""985 if not HAS_SMART_CONTEXT:986 await update.message.reply_text("⚠️ سیستم context هوشمند فعال نیست.")987 return988 989 # جمعآوری آمار از همه کاربران990 total_users_with_smart = 0991 total_memory_nodes = 0992 total_connections = 0993 user_interests = {}994 995 for user_id_str, user_data in data_manager.DATA['users'].items():996 if 'smart_context' in user_data:997 total_users_with_smart += 1998 999 smart_data = user_data['smart_context']1000 if 'profile' in smart_data:1001 interests = smart_data['profile'].get('interests', [])1002 for interest in interests:1003 user_interests[interest] = user_interests.get(interest, 0) + 11004 1005 # محاسبه رایجترین علاقهمندیها1006 top_interests = sorted(user_interests.items(), key=lambda x: x[1], reverse=True)[:10]1007 1008 analytics_text = (1009 "📊 **تحلیل کلی Context هوشمند**\n\n"1010 f"👥 **کاربران با Context هوشمند:** `{total_users_with_smart}`\n"1011 f"📈 **کل کاربران:** `{len(data_manager.DATA['users'])}`\n"1012 f"📊 **نرخ استفاده:** `{(total_users_with_smart / max(len(data_manager.DATA['users']), 1)):.1%}`\n\n"1013 "🎯 **رایجترین علاقهمندیها:**\n"1014 )1015 1016 if top_interests:1017 for interest, count in top_interests:1018 analytics_text += f"• {interest}: {count} کاربر\n"1019 else:1020 analytics_text += "هنوز علاقهمندیای ثبت نشده است."1021 1022 # اطلاعات سیستم1023 analytics_text += f"\n💻 **وضعیت سیستم:**\n"1024 analytics_text += f"• مدیران فعال در حافظه: `{len(smart_context_managers)}`\n"1025 1026 await update.message.reply_text(analytics_text, parse_mode='Markdown')1027 1028# --- هندلر برای دکمههای صفحهبندی ---1029async def users_list_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):1030 """پردازش دکمههای صفحهبندی لیست کاربران."""1031 query = update.callback_query1032 await query.answer()1033 1034 if query.data.startswith("users_list:"):1035 page = int(query.data.split(":")[1])1036 context.args = [str(page)]1037 await admin_users_list(update, context)1038 1039# --- تابع برای پردازش ارسالهای برنامهریزی شده ---1040async def process_scheduled_broadcasts(context: ContextTypes.DEFAULT_TYPE):1041 """پردازش ارسالهای برنامهریزی شده و ارسال پیامها در زمان مقرر."""1042 now = datetime.now()1043 broadcasts_to_send_indices = []1044 1045 for i, broadcast in enumerate(data_manager.DATA['scheduled_broadcasts']):1046 if broadcast['status'] == 'pending':1047 broadcast_time = datetime.strptime(broadcast['time'], '%Y-%m-%d %H:%M:%S')1048 if broadcast_time <= now:1049 broadcasts_to_send_indices.append(i)1050 1051 if not broadcasts_to_send_indices:1052 return1053 1054 user_ids = list(data_manager.DATA['users'].keys())1055 1056 for index in broadcasts_to_send_indices:1057 broadcast = data_manager.DATA['scheduled_broadcasts'][index]1058 message_text = broadcast['message']1059 total_sent, total_failed = 0, 01060 1061 for user_id_str in user_ids:1062 try:1063 await context.bot.send_message(chat_id=int(user_id_str), text=message_text)1064 total_sent += 11065 await asyncio.sleep(0.05)1066 except TelegramError as e:1067 logger.warning(f"Failed to send scheduled broadcast to {user_id_str}: {e}")1068 total_failed += 11069 1070 # بهروزرسانی وضعیت ارسال1071 data_manager.DATA['scheduled_broadcasts'][index]['status'] = 'sent'1072 data_manager.DATA['scheduled_broadcasts'][index]['sent_time'] = now.strftime('%Y-%m-%d %H:%M:%S')1073 data_manager.DATA['scheduled_broadcasts'][index]['sent_count'] = total_sent1074 data_manager.DATA['scheduled_broadcasts'][index]['failed_count'] = total_failed1075 1076 logger.info(f"Scheduled broadcast sent: {total_sent} successful, {total_failed} failed")1077 1078 data_manager.save_data()1079 1080# --- تابع راهاندازی هندلرها ---1081def setup_admin_handlers(application):1082 """هندلرهای پنل ادمین را به اپلیکیشن اضافه میکند."""1083 # هندلرهای اصلی1084 application.add_handler(CommandHandler("commands", admin_commands))1085 application.add_handler(CommandHandler("stats", admin_stats))1086 application.add_handler(CommandHandler("broadcast", admin_broadcast))1087 application.add_handler(CommandHandler("ban", admin_ban))1088 application.add_handler(CommandHandler("unban", admin_unban))1089 application.add_handler(CommandHandler("user_info", admin_userinfo))1090 application.add_handler(CommandHandler("logs", admin_logs))1091 application.add_handler(CommandHandler("logs_file", admin_logs_file))1092 application.add_handler(CommandHandler("users_list", admin_users_list))1093 application.add_handler(CommandHandler("user_search", admin_user_search))1094 application.add_handler(CommandHandler("backup", admin_backup))1095 1096 # هندلرهای جدید1097 application.add_handler(CommandHandler("targeted_broadcast", admin_targeted_broadcast))1098 application.add_handler(CommandHandler("schedule_broadcast", admin_schedule_broadcast))1099 application.add_handler(CommandHandler("list_scheduled", admin_list_scheduled_broadcasts))1100 application.add_handler(CommandHandler("remove_scheduled", admin_remove_scheduled_broadcast))1101 application.add_handler(CommandHandler("direct_message", admin_direct_message))1102 application.add_handler(CommandHandler("export_csv", admin_export_csv))1103 application.add_handler(CommandHandler("maintenance", admin_maintenance))1104 application.add_handler(CommandHandler("set_welcome", admin_set_welcome_message))1105 application.add_handler(CommandHandler("set_goodbye", admin_set_goodbye_message))1106 application.add_handler(CommandHandler("activity_heatmap", admin_activity_heatmap))1107 application.add_handler(CommandHandler("response_stats", admin_response_stats))1108 application.add_handler(CommandHandler("add_blocked_word", admin_add_blocked_word))1109 application.add_handler(CommandHandler("remove_blocked_word", admin_remove_blocked_word))1110 application.add_handler(CommandHandler("list_blocked_words", admin_list_blocked_words))1111 application.add_handler(CommandHandler("system_info", admin_system_info))1112 application.add_handler(CommandHandler("reset_stats", admin_reset_stats))1113 1114 # هندلرهای مدیریت context1115 application.add_handler(CommandHandler("clear_context", admin_clear_context))1116 application.add_handler(CommandHandler("view_context", admin_view_context))1117 1118 # هندلرهای Context هوشمند1119 if HAS_SMART_CONTEXT:1120 application.add_handler(CommandHandler("smart_stats", admin_smart_context_stats))1121 application.add_handler(CommandHandler("reset_smart_context", admin_reset_smart_context))1122 application.add_handler(CommandHandler("smart_analytics", admin_smart_analytics))1123 1124 # هندلر برای دکمههای صفحهبندی1125 application.add_handler(CallbackQueryHandler(users_list_callback, pattern="^users_list:"))1126 1127 # شروع وظیفه دورهای برای بررسی ارسالهای برنامهریزی شده1128 application.job_queue.run_repeating(process_scheduled_broadcasts, interval=60, first=0)1129 1130 logger.info("Admin panel handlers have been set up.")