Team Ai
Datasetpublic

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)

sourceHugging Faceapache-2.0updated 4mo agoView on Hugging Face
3likes1.7kdownloads
admin_panel.py1130 linesDownload Raw Back to render-main
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.")