import asyncio
import json
import os
import logging
import re
import random
import base64
import urllib.request
import urllib.error
from datetime import datetime, timedelta
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import Application, CommandHandler, CallbackQueryHandler, MessageHandler, filters, ContextTypes
from telethon import TelegramClient, errors, events
from telethon.tl.types import MessageMediaDocument, MessageMediaPhoto
from telethon.tl.functions.channels import JoinChannelRequest, LeaveChannelRequest
from telethon.tl.functions.messages import ImportChatInviteRequest, CheckChatInviteRequest
from telethon.tl.functions.messages import SendReactionRequest
from telethon.tl.types import ReactionEmoji
from telethon.network.connection.tcpabridged import ConnectionTcpAbridged  # <-- خط جدید

BOT_TOKEN = "8837232261:AAFwUp6dBEFTmYPrL6_46hxnPjatYmVb-0Y"
API_ID, API_HASH = 33561438, "0165edd763263f95445183b4143dd438"

CF = "config.json"
TF = "messages.txt"
TAF = "targets.json"
GTF = "general_targets.json"
SF = "stickers.json"
GF = "gifs.json"
MEDIA_DIR = "media_storage"
STICKER_DIR = os.path.join(MEDIA_DIR, "stickers")
GIF_DIR = os.path.join(MEDIA_DIR, "gifs")

os.makedirs(STICKER_DIR, exist_ok=True)
os.makedirs(GIF_DIR, exist_ok=True)

ADMINS = [8262076174]
CHANNEL_LINK = "https://t.me/ataker_guard"
OWNER_USERNAME = "@POLO_IR"

logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

def load_config():
    if os.path.exists(CF):
        try:
            with open(CF, 'r', encoding='utf-8') as f:
                return json.load(f)
        except:
            pass
    return {
        "accounts": [], "groups": [], "delay": 5, "active": False, "idx": 0,
        "admins": ADMINS, "temp_admins": {}, "msg_idx": 0, "active_groups": [],
        "account_status": {}, "reply_groups": [], "bulk_join_status": False,
        "mention_delay": 3, "max_mention_per_round": 3
    }

def save_config(d):
    with open(CF, 'w', encoding='utf-8') as f: json.dump(d, f, indent=2, ensure_ascii=False)

def load_msgs():
    if os.path.exists(TF):
        try:
            with open(TF, 'r', encoding='utf-8') as f: return [l.strip() for l in f if l.strip()]
        except: pass
    return ["سلام و درود بر شما، ربات اتکر فعال است."]

def save_msgs(m):
    with open(TF, 'w', encoding='utf-8') as f: f.write("\n".join(m))

def load_targets():
    if os.path.exists(TAF):
        try:
            with open(TAF, 'r', encoding='utf-8') as f: return json.load(f)
        except: pass
    return []

def save_targets(t):
    with open(TAF, 'w', encoding='utf-8') as f: json.dump(t, f, indent=2, ensure_ascii=False)

def load_general_targets():
    if os.path.exists(GTF):
        try:
            with open(GTF, 'r', encoding='utf-8') as f: return json.load(f)
        except: pass
    return []

def save_general_targets(t):
    with open(GTF, 'w', encoding='utf-8') as f: json.dump(t, f, indent=2, ensure_ascii=False)

def load_stickers():
    if os.path.exists(SF):
        try:
            with open(SF, 'r', encoding='utf-8') as f: return json.load(f)
        except: pass
    return []

def save_stickers(s):
    with open(SF, 'w', encoding='utf-8') as f: json.dump(s, f, indent=2, ensure_ascii=False)

def load_gifs():
    if os.path.exists(GF):
        try:
            with open(GF, 'r', encoding='utf-8') as f: return json.load(f)
        except: pass
    return []

def save_gifs(g):
    with open(GF, 'w', encoding='utf-8') as f: json.dump(g, f, indent=2, ensure_ascii=False)

config, msgs, clients, tmp = load_config(), load_msgs(), {}, {}
stickers, gifs = load_stickers(), load_gifs()

reply_config = {
    "active": False,
    "target_link_1": "", "target_msg_id_1": None, "chat_id_1": None, "active_target_1": True,
    "target_link_2": "", "target_msg_id_2": None, "chat_id_2": None, "active_target_2": False,
    "delay": 2, "message": "", "use_stickers": False, "use_gifs": False,
    "use_text": True  # ✅ جدید: کنترل ارسال متن از فایل TXT
}
last_msg_indices, last_sticker_indices, last_gif_indices, account_mention_cooldown, reply_counters = {}, {}, {}, {}, {}

# ================== 🛡 سیستم ضد لیمیت و ضد ریپورت (جدید) ==================
# این سیستم مستقل از سرعت کاربر کار می‌کند - فقط از بلاک/لیمیت شدن اکانت‌ها جلوگیری می‌کند
flood_cooldowns = {}          # phone -> datetime (تا کی اکانت در کول‌داون FloodWait/PeerFlood)
account_last_action = {}       # phone -> datetime (آخرین زمان ارسال از این اکانت)
account_target_history = {}    # (phone, chat_id) -> datetime (آخرین ارسال این اکانت به این گروه)
report_risk_counter = {}       # phone -> int (شمارنده ریسک ریپورت شدن)

ANTI_LIMIT_MIN_GAP = 0.4       # حداقل فاصله بین دو ارسال متوالی از یک اکانت (ثانیه)
PEER_FLOOD_COOLDOWN = 300      # کول‌داون بعد از PeerFlood (5 دقیقه)
FLOOD_WAIT_BUFFER = 5          # بافر اضافه به FloodWaitError
USER_BANNED_COOLDOWN = 600     # کول‌داون بعد از بن شدن در چت (10 دقیقه)
MAX_REPORTS_BEFORE_PAUSE = 3   # بعد از این تعداد خطای مشکوک، اکانت موقتا کنار گذاشته شود

def mark_account_cooldown(phone, seconds, reason=""):
    """ثبت کول‌داون برای یک اکانت"""
    global flood_cooldowns
    flood_cooldowns[phone] = datetime.now() + timedelta(seconds=seconds)
    logger.warning(f"⏳ اکانت {phone} به مدت {seconds} ثانیه در کول‌داون قرار گرفت ({reason})")

def is_account_in_cooldown(phone):
    """چک کن اکانت در کول‌داون هست یا نه"""
    if phone in flood_cooldowns:
        if datetime.now() < flood_cooldowns[phone]:
            return True
        else:
            del flood_cooldowns[phone]
    return False

def get_cooldown_remaining(phone):
    """زمان باقیمانده کول‌داون به ثانیه"""
    if phone in flood_cooldowns:
        diff = (flood_cooldowns[phone] - datetime.now()).total_seconds()
        return max(0, int(diff))
    return 0

def clear_account_cooldown(phone):
    """پاک کردن کول‌داون دستی یک اکانت"""
    if phone in flood_cooldowns:
        del flood_cooldowns[phone]
    if phone in report_risk_counter:
        report_risk_counter[phone] = 0

def get_active_accounts_list():
    """لیست اکانت‌های فعال که در کول‌داون نیستند"""
    accounts = []
    for p in config["accounts"]:
        if not config.get("account_status", {}).get(p, True):
            continue
        if is_account_in_cooldown(p):
            continue
        accounts.append(p)
    return accounts

def anti_limit_stats():
    """آمار وضعیت سیستم ضد لیمیت"""
    total = len(config["accounts"])
    in_cd = sum(1 for p in config["accounts"] if is_account_in_cooldown(p))
    healthy = total - in_cd
    return {
        "total": total,
        "healthy": healthy,
        "in_cooldown": in_cd,
        "cooldowns": {p: get_cooldown_remaining(p) for p in flood_cooldowns if get_cooldown_remaining(p) > 0}
    }

async def apply_anti_limit_gap(phone):
    """اعمال حداقل فاصله بین دو ارسال از یک اکانت (ضد لیمیت)"""
    now = datetime.now()
    if phone in account_last_action:
        elapsed = (now - account_last_action[phone]).total_seconds()
        if elapsed < ANTI_LIMIT_MIN_GAP:
            wait = ANTI_LIMIT_MIN_GAP - elapsed
            await asyncio.sleep(wait)
    account_last_action[phone] = datetime.now()

def anti_limit_menu():
    stats = anti_limit_stats()
    cd_lines = []
    for p, sec in list(stats["cooldowns"].items())[:10]:
        cd_lines.append(f"• {p}: {sec} ثانیه")
    cd_text = "\n".join(cd_lines) if cd_lines else "هیچ اکانتی در کول‌داون نیست ✅"
    return InlineKeyboardMarkup([
        [InlineKeyboardButton(f"📊 آمار: سالم {stats['healthy']} | کول‌داون {stats['in_cooldown']}", callback_data="anti_limit_refresh")],
        [InlineKeyboardButton("♻️ ریست کول‌داون همه اکانت‌ها", callback_data="anti_limit_reset_all")],
        [InlineKeyboardButton("🔙 بازگشت به منوی اصلی", callback_data="back_main")]
    ]), cd_text
# ==========================================================================

# ================== 💖 بخش جدید: ری اکشن خودکار به اکانت هدف (نسخه 5) ==================
reaction_config = {
    "active": False,
    "target_user": "",              # یوزرنیم یا آیدی عددی اکانت هدف (اکانت خودت)
    "reaction": "❤",                # ری اکشن انتخابی
    "listener_started": False,      # جلوگیری از ثبت چندباره listener
    "sent_count": 0,                # شمارنده کل ری اکشن‌های ارسال شده
    "success_count": 0,             # ✅ شمارنده موفق
    "fail_count": 0                 # ✅ شمارنده ناموفق
}

# ✅ جدید: مجموعه‌ای از شماره اکانت‌هایی که listener برایشان نصب شده
reaction_phones_registered = set()

REACTION_PRESETS = {
    "❤": "قلب ❤️",
    "👍": "لایک 👍",
    "🔥": "آتش 🔥",
    "🎉": "جشن 🎉",
    "💯": "صد 💯",
    "👏": "تشویق 👏",
    "😍": "عاشق 😍",
    "🙏": "تشکر 🙏",
    "⚡": "برق ⚡",
    "🏆": "جام 🏆"
}

def reaction_menu():
    tgt = reaction_config.get("target_user") or ""
    tgt_status = f"✅ {tgt[:25]}" if tgt else "❌ تنظیم نشده"
    running = "🟢 فعال" if reaction_config.get("active") else "🔴 غیرفعال"
    cur_key = reaction_config.get("reaction", "❤")
    cur = REACTION_PRESETS.get(cur_key, cur_key)
    sent = reaction_config.get("sent_count", 0)
    ok = reaction_config.get("success_count", 0)
    fail = reaction_config.get("fail_count", 0)
    return InlineKeyboardMarkup([
        [InlineKeyboardButton("🟢 شروع ری اکشن", callback_data="start_reaction"), InlineKeyboardButton("🔴 توقف", callback_data="stop_reaction")],
        [InlineKeyboardButton(f"👤 اکانت هدف: {tgt_status}", callback_data="set_reaction_target")],
        [InlineKeyboardButton(f"💗 انتخاب ری اکشن (فعلی: {cur})", callback_data="choose_reaction")],
        [InlineKeyboardButton(f"📡 وضعیت: {running} | ارسال: {sent} | ✅ {ok} ❌ {fail}", callback_data="reaction_refresh")],
        [InlineKeyboardButton("🗑 پاک‌سازی تنظیمات ری اکشن", callback_data="clear_reaction_config")],
        [InlineKeyboardButton("🔙 بازگشت به منوی اصلی", callback_data="back_main")]
    ])

def reaction_picker_menu():
    rows = []
    items = list(REACTION_PRESETS.items())
    for i in range(0, len(items), 2):
        row = []
        for k, v in items[i:i+2]:
            mark = "✅ " if reaction_config.get("reaction") == k else ""
            row.append(InlineKeyboardButton(f"{mark}{v}", callback_data=f"pick_reaction_{k}"))
        rows.append(row)
    rows.append([InlineKeyboardButton("🔙 بازگشت به منوی ری اکشن", callback_data="reaction_menu")])
    return InlineKeyboardMarkup(rows)

def _register_reaction_listener(c, phone):
    """ثبت listener برای یک اکانت خاص - نسخه بهبودیافته با استگر و لاگ بهتر"""
    async def reaction_listener(event):
        try:
            if not reaction_config.get("active"): return
            if is_account_in_cooldown(phone): return

            target = (reaction_config.get("target_user") or "").strip()
            if not target: return

            sender = await event.get_sender()
            if not sender: return

            sender_id = str(getattr(sender, "id", ""))
            sender_username = ""
            try:
                un = getattr(sender, "username", None)
                if un: sender_username = f"@{un}"
            except: pass

            t = target.lstrip('@').strip().lower()

            matched = False
            if t and t == sender_id: matched = True
            elif sender_username and t == sender_username.lstrip('@').lower(): matched = True

            if not matched: return

            # چک کن خودش نباشه که به پیام خودش ری اکشن بزنه
            try:
                me = await c.get_me()
                if getattr(me, "id", None) and getattr(sender, "id", None) == me.id:
                    return
            except: pass

            # ✅ FIX: تاخیر تصادفی برای پخش شدن ری اکشن‌ها روی زمان (ضد Rate-Limit تلگرام)
            # بدون این تاخیر، تلگرام بعد از حدود ۸ ری اکشن همزمان، بقیه رو drop می‌کنه
            await asyncio.sleep(random.uniform(0.4, 3.0))

            # دوباره چک کن در تاخیر، وضعیت عوض نشده باشه
            if not reaction_config.get("active"): return
            if is_account_in_cooldown(phone): return

            reaction = reaction_config.get("reaction", "❤")
            try:
                # ✅ FIX: استفاده از input_chat برای peer مطمئن‌تر
                try:
                    peer = await event.get_input_chat()
                except Exception:
                    peer = event.chat_id

                await c(SendReactionRequest(
                    peer=peer,
                    msg_id=event.message.id,
                    reaction=[ReactionEmoji(emoticon=reaction)]
                ))
                reaction_config["sent_count"] = reaction_config.get("sent_count", 0) + 1
                reaction_config["success_count"] = reaction_config.get("success_count", 0) + 1
                logger.info(f"💖 ری اکشن از {phone} → پیام {event.message.id} ✅")
            except errors.FloodWaitError as e:
                mark_account_cooldown(phone, e.seconds + FLOOD_WAIT_BUFFER, "FloodWait (ری اکشن)")
                reaction_config["fail_count"] = reaction_config.get("fail_count", 0) + 1
                logger.warning(f"⏳ FloodWait ری اکشن {phone}: {e.seconds}ث")
            except errors.PeerFloodError:
                mark_account_cooldown(phone, PEER_FLOOD_COOLDOWN, "PeerFlood (ری اکشن)")
                reaction_config["fail_count"] = reaction_config.get("fail_count", 0) + 1
                logger.warning(f"🚫 PeerFlood ری اکشن {phone}")
            except Exception as ex:
                reaction_config["fail_count"] = reaction_config.get("fail_count", 0) + 1
                logger.warning(f"⚠️ خطا ری اکشن {phone}: {str(ex)[:120]}")
        except Exception as e:
            logger.warning(f"⚠️ reaction listener err {phone}: {str(e)[:120]}")

    try:
        c.add_event_handler(reaction_listener, events.NewMessage(incoming=True))
    except Exception as e:
        logger.error(f"خطا در add_event_handler برای {phone}: {e}")

async def setup_reaction_listeners():
    """راه‌اندازی listener ری اکشن برای همه اکانت‌های فعال (با پشتیبانی از اکانت‌های جدید)"""
    # ✅ FIX: به جای listener_started ساده، از set استفاده کن تا اکانت‌های جدید هم ثبت شن
    started = 0
    for phone in config["accounts"]:
        if not config.get("account_status", {}).get(phone, True):
            continue
        if phone in reaction_phones_registered:
            continue
        c = await get_client(phone)
        if not c:
            continue
        try:
            _register_reaction_listener(c, phone)
            reaction_phones_registered.add(phone)
            started += 1
        except Exception as e:
            logger.error(f"خطا در ثبت listener ری اکشن برای {phone}: {e}")
    if started > 0:
        logger.info(f"💖 listener ری اکشن برای {started} اکانت جدید ثبت شد. (کل: {len(reaction_phones_registered)})")
    else:
        logger.info(f"💖 همه اکانت‌ها ({len(reaction_phones_registered)} عدد) از قبل ثبت شده‌اند.")
# =========================================================================================

# ================== بخش جدید: اسپم فور اسپم (فوروارد پیام مبدأ به گروه هدف) ==================
spam_config = {
    "active": False,
    "loop_running": False,      # جلوگیری از اجرای چند حلقه موازی
    "source_link": "",          # لینک پیام مبدأ (عکس + متن) در گروه عمومی
    "source_chat": None,        # آیدی یا یوزرنیم گروه مبدأ
    "source_msg_id": None,      # آیدی عددی پیام مبدأ
    "target_link": "",          # لینک گروه هدف (عمومی یا خصوصی)
    "target_chat": None,        # آیدی یا یوزرنیم گروه هدف
    "source_entity_cache": None, # کش entity مبدأ
    "target_entity_cache": None, # کش entity هدف
    "speed": 8                  # تعداد فور در ثانیه برای هر اکانت
}

# ================== بخش جدید: استارت ربات با لینک رفرال ==================
start_bot_config = {
    "active": False,
    "running": False,           # جلوگیری از اجرای چند حلقه موازی
    "bot_link": "",             # لینک کامل ربات
    "bot_username": "",         # یوزرنیم ربات
    "start_param": "",          # پارامتر رفرال (بعد از ?start=)
    "delay": 3,                 # فاصله زمانی بین هر اکانت (1 تا 15 ثانیه)
    "captcha_watch_until": None # ✅ جدید: زمان پایان پنجره‌ی حل کپچا
}

# ================== 🧠 بخش جدید: هوش مصنوعی حل کپچا ==================
ai_captcha_config = {
    "enabled": False,
    "api_key": "sk-wVnEnZgbriLiCHH1gtDPMbO7VOOhv5FWTWognYLRyTOgLnZZ",
    "base_url": "https://api.gapgpt.app/v1",
    "model": "gpt-4o",
    "listeners_installed": False,
    "solved_count": 0,
    "failed_count": 0,
    "captcha_watch_until": None     # پنجره زمانی فعال برای حل کپچا (datetime)
}

captcha_phones_registered = set()
captcha_recent_messages = set()     # (phone, chat_id, msg_id) برای جلوگیری از پاسخ تکراری

AI_MODEL_PRESETS = [
    ("gpt-4o", "GPT-4o (دقیق)"),
    ("gpt-4o-mini", "GPT-4o-mini (سریع/ارزون)"),
    ("gemini-2.5-pro", "Gemini 2.5 Pro"),
    ("gemini-2.0-flash", "Gemini 2.0 Flash (سریع)")
]

async def call_gapgpt_api(prompt, image_bytes=None):
    """ارسال پرامپت به GapGPT API و برگرداندن متن پاسخ
    از urllib استفاده می‌کند تا به پکیج اضافه‌ای نیاز نباشد"""
    def _sync_request():
        headers = {
            "Content-Type": "application/json",
            "Authorization": f"Bearer {ai_captcha_config.get('api_key', '')}"
        }
        if image_bytes:
            try:
                b64 = base64.b64encode(image_bytes).decode('ascii')
                content = [
                    {"type": "text", "text": prompt},
                    {"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{b64}"}}
                ]
            except Exception:
                content = prompt
        else:
            content = prompt

        payload = {
            "model": ai_captcha_config.get("model", "gpt-4o"),
            "messages": [{"role": "user", "content": content}],
            "max_tokens": 250,
            "temperature": 0.1
        }
        base = ai_captcha_config.get("base_url", "https://api.gapgpt.app/v1").rstrip("/")
        req = urllib.request.Request(
            base + "/chat/completions",
            data=json.dumps(payload).encode('utf-8'),
            headers=headers,
            method="POST"
        )
        try:
            with urllib.request.urlopen(req, timeout=45) as resp:
                return resp.read().decode('utf-8')
        except urllib.error.HTTPError as e:
            try:
                return e.read().decode('utf-8')
            except Exception:
                return None
        except Exception as e:
            return None

    try:
        raw = await asyncio.to_thread(_sync_request)
        if not raw:
            return None
        data = json.loads(raw)
        if isinstance(data, dict):
            if "choices" in data and data["choices"]:
                try:
                    return data["choices"][0]["message"]["content"]
                except Exception:
                    return None
            if "error" in data:
                logger.error(f"GapGPT API error: {data['error']}")
                return None
        return None
    except Exception as e:
        logger.error(f"GapGPT call failed: {e}")
        return None

async def test_gapgpt_api():
    """تست اتصال به API با یه پرامپت ساده"""
    resp = await call_gapgpt_api("فقط کلمه OK رو بنویس. هیچ چیز دیگه‌ای ننویس.")
    if resp and "OK" in resp.upper():
        return True, resp.strip()[:100]
    return False, (resp or "بدون پاسخ")[:200]

def _register_captcha_listener(c, phone):
    """ثبت listener کپچا برای یک اکانت - پیام‌های ربات رو چک می‌کنه و اگه کپچا بود حل می‌کنه"""
    async def captcha_listener(event):
        try:
            if not ai_captcha_config.get("enabled"): return

            watch_until = ai_captcha_config.get("captcha_watch_until")
            if not watch_until: return
            if isinstance(watch_until, str):
                try:
                    watch_until = datetime.fromisoformat(watch_until)
                except Exception:
                    return
            if datetime.now() > watch_until: return

            sender = await event.get_sender()
            if not sender: return
            if not getattr(sender, "bot", False): return

            msg = event.message
            buttons = getattr(msg, "buttons", None)
            if not buttons:
                return

            # جلوگیری از پاسخ تکراری به همون پیام
            key = (phone, event.chat_id, msg.id)
            if key in captcha_recent_messages:
                return
            captcha_recent_messages.add(key)
            # پاکسازی قدیمی‌ها
            if len(captcha_recent_messages) > 500:
                captcha_recent_messages.clear()

            bot_username = (start_bot_config.get("bot_username", "") or "").lstrip('@').lower()
            sender_username = ""
            try:
                sender_username = (getattr(sender, "username", "") or "").lstrip('@').lower()
            except: pass

            text = (getattr(msg, "message", "") or "").strip()

            is_target_bot = (sender_username and sender_username == bot_username)

            # اگه ربات هدف نبود، فقط وقتی ادامه بده که شبیه کپچا باشه
            if not is_target_bot:
                captcha_keywords = ["کپچا", "captcha", "رنگ", "انتخاب کن", "verify", "تایید", "ربات نیستی",
                                    "human", "humanity", "کدام", "انتخاب کنید", "شیشه", "ایموجی", "ایموجی زیر"]
                looks_like_captcha = any(kw in text.lower() for kw in captcha_keywords)
                if not looks_like_captcha and len(text) > 250:
                    return

            # تاخیر کوچک قبل از حل
            await asyncio.sleep(random.uniform(1.0, 2.5))

            # اگه تو این فاصله خاموش شد، بیخیال
            if not ai_captcha_config.get("enabled"): return

            # استخراج متن دکمه‌ها
            flat_buttons = []
            for row in buttons:
                for btn in row:
                    flat_buttons.append(btn)

            if not flat_buttons:
                return

            button_texts = [getattr(b, "text", "") or "" for b in flat_buttons]

            # ساخت پرامپت
            prompt = f"""تو داری برای یک اکانت تلگرام کپچا حل می‌کنی. متن پیام کپچا اینه:

{(text if text else "(بدون متن)")}

دکمه‌های شیشه‌ای زیر پیام به ترتیب اینا هستن:
"""
            for i, bt in enumerate(button_texts):
                prompt += f"{i}: {bt}\n"

            prompt += """
سوال: کدوم دکمه رو باید بزنم تا کپچا حل بشه؟ فقط شماره دکمه رو بنویس (مثلا 0 یا 3).
پاسخ فقط باید یک عدد باشه. هیچ توضیحی ننویس.
"""

            # تلاش برای گرفتن عکس (اگه کپچا تصویری بود)
            image_bytes = None
            try:
                if msg.photo or msg.document:
                    image_bytes = await event.download_media(bytes)
            except Exception:
                image_bytes = None

            answer = await call_gapgpt_api(prompt, image_bytes)
            if not answer:
                ai_captcha_config["failed_count"] = ai_captcha_config.get("failed_count", 0) + 1
                return

            answer = answer.strip()

            # پارس کردن پاسخ
            idx = None
            m = re.search(r'\b(\d+)\b', answer)
            if m:
                try:
                    idx = int(m.group(1))
                except Exception:
                    idx = None

            # اگه عدد معتبر نبود، سعی کن با متن دکمه تطبیق بدی
            if idx is None or idx < 0 or idx >= len(flat_buttons):
                for i, bt in enumerate(button_texts):
                    if bt and (answer.lower() in bt.lower() or bt.lower() in answer.lower()):
                        idx = i
                        break

            if idx is None or idx < 0 or idx >= len(flat_buttons):
                logger.warning(f"❌ نتونستم پاسخ AI رو به دکمه‌ای نسبت بدم: '{answer}'")
                ai_captcha_config["failed_count"] = ai_captcha_config.get("failed_count", 0) + 1
                return

            try:
                await event.click(idx)
                ai_captcha_config["solved_count"] = ai_captcha_config.get("solved_count", 0) + 1
                logger.info(f"🧠✅ کپچا حل شد با {phone} → دکمه {idx}: {button_texts[idx]}")
            except Exception as e:
                ai_captcha_config["failed_count"] = ai_captcha_config.get("failed_count", 0) + 1
                logger.error(f"خطا در کلیک روی دکمه کپچا {phone}: {str(e)[:100]}")
        except Exception as e:
            logger.error(f"captcha_listener error {phone}: {str(e)[:120]}")

    try:
        c.add_event_handler(captcha_listener, events.NewMessage(incoming=True))
    except Exception as e:
        logger.error(f"خطا در add_event_handler کپچا برای {phone}: {e}")

async def install_captcha_listeners():
    """نصب listener کپچا روی همه اکانت‌های فعال (فقط برای اکانت‌های جدید)"""
    started = 0
    for phone in config["accounts"]:
        if not config.get("account_status", {}).get(phone, True):
            continue
        if phone in captcha_phones_registered:
            continue
        c = await get_client(phone)
        if not c:
            continue
        try:
            _register_captcha_listener(c, phone)
            captcha_phones_registered.add(phone)
            started += 1
        except Exception as e:
            logger.error(f"خطا در نصب listener کپچا روی {phone}: {e}")
    if started > 0:
        logger.info(f"🧠 listener کپچا برای {started} اکانت جدید نصب شد. (کل: {len(captcha_phones_registered)})")

def ai_captcha_menu():
    status = "✅ فعال" if ai_captcha_config.get("enabled") else "❌ غیرفعال"
    solved = ai_captcha_config.get("solved_count", 0)
    failed = ai_captcha_config.get("failed_count", 0)
    model = ai_captcha_config.get("model", "gpt-4o")
    base = ai_captcha_config.get("base_url", "")
    return InlineKeyboardMarkup([
        [InlineKeyboardButton(
            f"{'🔴 غیرفعال کن' if ai_captcha_config.get('enabled') else '🟢 فعال کن'} (وضعیت: {status})",
            callback_data="toggle_ai_captcha"
        )],
        [InlineKeyboardButton(f"🤖 مدل: {model}", callback_data="ai_choose_model")],
        [InlineKeyboardButton(f"📊 حل‌شده: {solved} | ناموفق: {failed}", callback_data="noop")],
        [InlineKeyboardButton("🧪 تست اتصال API", callback_data="test_ai_api")],
        [InlineKeyboardButton(f"🌐 Base URL: {base[:35]}...", callback_data="noop")],
        [InlineKeyboardButton("♻️ ریست آمار", callback_data="reset_ai_stats")],
        [InlineKeyboardButton("🔙 بازگشت به منوی استارت ربات", callback_data="start_bot_menu")]
    ])

def ai_model_picker_menu():
    rows = []
    for mid, label in AI_MODEL_PRESETS:
        mark = "✅ " if ai_captcha_config.get("model") == mid else ""
        rows.append([InlineKeyboardButton(f"{mark}{label}", callback_data=f"pick_ai_model_{mid}")])
    rows.append([InlineKeyboardButton("🔙 بازگشت", callback_data="ai_captcha_menu")])
    return InlineKeyboardMarkup(rows)

def parse_bot_link(link):
    """پارس لینک ربات و برگرداندن (username, start_param)
    پشتیبانی از:
      - https://t.me/MyBot?start=ref123
      - t.me/MyBot?start=ref123
      - @MyBot
      - MyBot
    """
    try:
        raw = link.strip()
        cleaned = raw.replace("https://", "").replace("http://", "").replace("t.me/", "").rstrip("/")
        if cleaned.startswith("@"):
            cleaned = cleaned[1:]
        # اگر پارامتر start دارد
        if "?" in cleaned:
            parts = cleaned.split("?", 1)
            username = parts[0]
            query = parts[1]
            param = ""
            for q in query.split("&"):
                if q.startswith("start="):
                    param = q.split("=", 1)[1]
                    break
            return username, param
        return cleaned, ""
    except:
        return None, None

def start_bot_menu():
    link_status = "✅" if start_bot_config.get("bot_link") else "❌"
    running_status = "🟢 در حال اجرا" if start_bot_config.get("running") else "🔴 متوقف"
    ai_status = "✅" if ai_captcha_config.get("enabled") else "❌"
    ai_solved = ai_captcha_config.get("solved_count", 0)
    return InlineKeyboardMarkup([
        [InlineKeyboardButton("🚀 شروع استارت ربات با همه اکانت‌ها", callback_data="run_start_bot")],
        [InlineKeyboardButton("⏹ توقف استارت ربات", callback_data="stop_start_bot")],
        [InlineKeyboardButton(f"🔗 تنظیم لینک رفرال ربات: {link_status}", callback_data="set_start_bot_link")],
        [InlineKeyboardButton(f"⏱ تنظیم فاصله زمانی (فعلی: {start_bot_config['delay']} ثانیه)", callback_data="set_start_bot_delay")],
        [InlineKeyboardButton(f"🧠 هوش مصنوعی حل کپچا: {ai_status} | حل‌شده: {ai_solved}", callback_data="ai_captcha_menu")],
        [InlineKeyboardButton(f"📡 وضعیت موتور: {running_status}", callback_data="refresh_start_bot_status")],
        [InlineKeyboardButton("🗑 پاک‌سازی تنظیمات استارت ربات", callback_data="clear_start_bot_config")],
        [InlineKeyboardButton("🔙 بازگشت به منوی اصلی", callback_data="back_main")]
    ])

async def start_bot_with_account(phone):
    """استارت ربات با یک اکانت با استفاده از لینک رفرال"""
    try:
        if is_account_in_cooldown(phone):
            return False, "cooldown"
        c = await get_client(phone)
        if not c:
            return False, "no_client"

        username = start_bot_config.get("bot_username", "").strip()
        param = start_bot_config.get("start_param", "") or ""
        if not username:
            return False, "no_username"

        msg = f"/start {param}" if param else "/start"

        # تلاش برای ارسال با entity واقعی، در صورت خطا با یوزرنیم خام
        try:
            target_entity = await c.get_entity(username)
            await c.send_message(target_entity, msg)
        except Exception:
            await c.send_message(username, msg)

        return True, "ok"
    except errors.FloodWaitError as e:
        mark_account_cooldown(phone, e.seconds + FLOOD_WAIT_BUFFER, "FloodWait (استارت ربات)")
        return False, "flood"
    except errors.PeerFloodError:
        mark_account_cooldown(phone, PEER_FLOOD_COOLDOWN, "PeerFlood (استارت ربات)")
        return False, "peerflood"
    except errors.UserBannedInChannelError:
        mark_account_cooldown(phone, USER_BANNED_COOLDOWN, "UserBanned (استارت ربات)")
        return False, "banned"
    except Exception as e:
        logger.error(f"خطا در استارت ربات {phone}: {str(e)[:80]}")
        return False, str(e)[:50]

async def start_bot_loop(context, chat_id):
    """حلقه استارت ربات - روی همه اکانت‌ها با فاصله زمانی مشخص"""
    if start_bot_config.get("running"):
        logger.info("⚠️ استارت ربات از قبل در حال اجراست - حلقه جدید ساخته نشد.")
        return
    start_bot_config["running"] = True
    start_bot_config["active"] = True
    logger.info("🚀 موتور استارت ربات آغاز شد.")

    success = 0
    failed = 0
    try:
        accounts = [p for p in config["accounts"] if config.get("account_status", {}).get(p, True)]
        if not accounts:
            if chat_id:
                try:
                    await context.bot.send_message(chat_id, "❌ هیچ اکانت فعالی در سیستم نیست.")
                except: pass
            return

        # ✅ جدید: اگه AI فعاله، پنجره حل کپچا رو باز کن + listenerها رو نصب کن
        if ai_captcha_config.get("enabled"):
            try:
                await install_captcha_listeners()
            except Exception as e:
                logger.error(f"خطا در نصب listener کپچا: {e}")
            # پنجره حل کپچا = مدت زمان استارت همه + ۲ دقیقه اضافه
            total_time = start_bot_config["delay"] * len(accounts)
            ai_captcha_config["captcha_watch_until"] = datetime.now() + timedelta(seconds=total_time + 120)
            if chat_id:
                try:
                    await context.bot.send_message(
                        chat_id,
                        f"🧠 هوش مصنوعی حل کپچا فعال شد. پنجره: تا {total_time + 120} ثانیه دیگر."
                    )
                except: pass

        total = len(accounts)
        for idx, phone in enumerate(accounts, 1):
            if not start_bot_config["active"]:
                break
            ok, msg = await start_bot_with_account(phone)
            if ok:
                success += 1
            else:
                failed += 1

            # گزارش پیشرفت لحظه‌ای
            if idx % 5 == 0 and chat_id:
                try:
                    await context.bot.send_message(
                        chat_id,
                        f"📊 پیشرفت استارت ربات:\n• انجام شده: {idx} از {total}\n• موفق: {success}\n• ناموفق: {failed}"
                    )
                except: pass

            # فاصله زمانی بین اکانت‌ها
            await asyncio.sleep(start_bot_config["delay"])

        # گزارش نهایی
        if chat_id:
            ai_note = ""
            if ai_captcha_config.get("enabled"):
                ai_note = f"\n🧠 کپچاهای حل‌شده: {ai_captcha_config.get('solved_count', 0)}"
            try:
                await context.bot.send_message(
                    chat_id,
                    f"✅ **استارت ربات با همه اکانت‌ها به پایان رسید.**\n\n"
                    f"• کل اکانت‌ها: {total}\n"
                    f"• موفق: {success}\n"
                    f"• ناموفق: {failed}{ai_note}",
                    parse_mode='Markdown'
                )
            except: pass
    finally:
        start_bot_config["running"] = False
        start_bot_config["active"] = False
        logger.info("⏹ موتور استارت ربات خاتمه یافت.")
# ==========================================================================

def parse_telegram_link(link):
    """پارس لینک تلگرام و برگرداندن (chat, msg_id) برای پیام مبدأ"""
    try:
        link = link.strip().replace("https://", "").replace("http://", "").replace("t.me/", "").rstrip("/")
        parts = link.split("/")
        # حالت کانال عمومی: username/123
        if len(parts) == 2 and parts[1].isdigit():
            return parts[0], int(parts[1])
        # حالت گروه خصوصی: c/1234567890/123
        if len(parts) == 3 and parts[0] == "c" and parts[1].isdigit() and parts[2].isdigit():
            return int("-100" + parts[1]), int(parts[2])
        # حالت username/123/456 یا لینک‌های دیگر
        if len(parts) >= 2:
            for i, p in enumerate(parts):
                if p.isdigit():
                    return parts[i-1] if i > 0 else None, int(p)
        return None, None
    except:
        return None, None

def parse_target_link(link):
    """پارس لینک گروه هدف - پشتیبانی کامل از گروه خصوصی و عمومی
    خروجی: دیکشنری با type و value یا None"""
    try:
        raw = link.strip()
        cleaned = raw.replace("https://", "").replace("http://", "").replace("t.me/", "").rstrip("/")

        # لینک دعوت خصوصی: +hash یا joinchat/hash
        if cleaned.startswith("+") or cleaned.startswith("joinchat/"):
            hash_val = cleaned.replace("joinchat/", "").replace("+", "")
            if hash_val:
                return {"type": "invite", "value": hash_val}

        parts = cleaned.split("/")

        # گروه/کانال خصوصی با فرمت c/xxx
        if len(parts) >= 2 and parts[0] == "c" and parts[1].isdigit():
            return {"type": "chat_id", "value": int("-100" + parts[1])}

        # آیدی عددی مثل -1001234567890
        if cleaned.lstrip("-").isdigit():
            return {"type": "chat_id", "value": int(cleaned)}

        # یوزرنیم عمومی
        if parts and parts[0]:
            return {"type": "username", "value": parts[0]}

        return None
    except:
        return None

def spam_menu():
    src_status = "✅" if spam_config["source_link"] else "❌"
    tgt_status = "✅" if spam_config["target_link"] else "❌"
    run_status = "🟢 در حال اجرا" if spam_config.get("loop_running") else ("🟡 فعال (در انتظار)" if spam_config["active"] else "🔴 متوقف")
    return InlineKeyboardMarkup([
        [InlineKeyboardButton("🟢 شروع اسپم فور اسپم", callback_data="start_spam_f4f"), InlineKeyboardButton("🔴 توقف اسپم فور اسپم", callback_data="stop_spam_f4f")],
        [InlineKeyboardButton(f"📥 لینک پیام مبدأ: {src_status}", callback_data="set_spam_source")],
        [InlineKeyboardButton(f"🎯 لینک گروه هدف: {tgt_status}", callback_data="set_spam_target")],
        [InlineKeyboardButton("⚡ تنظیم سرعت (پیش‌فرض 8 در ثانیه)", callback_data="set_spam_speed")],
        [InlineKeyboardButton(f"📡 وضعیت موتور: {run_status}", callback_data="spam_refresh_status")],
        [InlineKeyboardButton("🗑 پاک‌سازی تنظیمات اسپم", callback_data="clear_spam_config")],
        [InlineKeyboardButton("🔙 بازگشت به منوی اصلی", callback_data="back_main")]
    ])

async def resolve_spam_entities():
    """resolve و کش کردن entity مبدأ و هدف با اولین اکانت فعال"""
    try:
        if not config["accounts"]:
            return False, "❌ اکانتی موجود نیست"
        phone = None
        for p in config["accounts"]:
            if config.get("account_status", {}).get(p, True):
                phone = p
                break
        if not phone:
            return False, "❌ اکانت فعالی موجود نیست"
        c = await get_client(phone)
        if not c:
            return False, "❌ اتصال اکانت برقرار نشد"

        # resolve source
        try:
            src_ent = await c.get_entity(spam_config["source_chat"])
            spam_config["source_entity_cache"] = src_ent
        except Exception as e:
            spam_config["source_entity_cache"] = spam_config["source_chat"]

        # resolve target
        try:
            tgt_ent = await c.get_entity(spam_config["target_chat"])
            spam_config["target_entity_cache"] = tgt_ent
        except Exception as e:
            spam_config["target_entity_cache"] = spam_config["target_chat"]

        return True, "OK"
    except Exception as e:
        return False, str(e)[:80]

async def spam_f4f_worker(phone):
    """فوروارد پیام مبدأ به گروه هدف با یک اکانت - سرعت بالا"""
    try:
        if is_account_in_cooldown(phone):
            return 0
        c = await get_client(phone)
        if not c:
            return 0

        source_chat = spam_config.get("source_entity_cache") or spam_config.get("source_chat")
        source_msg_id = spam_config.get("source_msg_id")
        target_chat = spam_config.get("target_entity_cache") or spam_config.get("target_chat")

        if not source_chat or not source_msg_id or not target_chat:
            return 0

        speed = spam_config.get("speed", 8)
        delay_per_msg = 1.0 / speed if speed > 0 else 0.125

        # اگر cache نداشتیم resolve کن
        if not spam_config.get("target_entity_cache"):
            try:
                target_entity = await c.get_entity(target_chat)
                spam_config["target_entity_cache"] = target_entity
            except Exception:
                target_entity = target_chat
        else:
            target_entity = spam_config["target_entity_cache"]

        if not spam_config.get("source_entity_cache"):
            try:
                src_entity = await c.get_entity(source_chat)
                spam_config["source_entity_cache"] = src_entity
            except Exception:
                src_entity = source_chat
        else:
            src_entity = spam_config["source_entity_cache"]

        sent = 0
        for _ in range(speed):
            if not spam_config["active"]:
                break
            if is_account_in_cooldown(phone):
                break
            try:
                await c.forward_messages(
                    entity=target_entity,
                    messages=source_msg_id,
                    from_peer=src_entity
                )
                sent += 1
            except errors.FloodWaitError as e:
                mark_account_cooldown(phone, e.seconds + FLOOD_WAIT_BUFFER, "FloodWait (اسپم فور اسپم)")
                break
            except errors.PeerFloodError:
                mark_account_cooldown(phone, PEER_FLOOD_COOLDOWN, "PeerFlood (اسپم فور اسپم)")
                break
            except errors.ChatWriteForbiddenError:
                break
            except errors.ChatForwardsRestrictedError:
                # فوروارد در گروه هدف ممنوعه - یه بار دیگه بدون forward امتحان کن
                try:
                    msg = await c.get_messages(src_entity, ids=source_msg_id)
                    if msg:
                        await c.send_message(target_entity, msg)
                        sent += 1
                except Exception:
                    pass
            except Exception as e:
                logger.error(f"خطا فور اسپم {phone}: {str(e)[:80]}")
                break
            await asyncio.sleep(delay_per_msg)
        return sent
    except Exception as e:
        logger.error(f"خطا در worker فور اسپم {phone}: {e}")
        return 0

async def spam_f4f_loop():
    """حلقه اصلی اسپم فور اسپم - همه اکانت‌ها همزمان و قاطی‌پاتی"""
    # جلوگیری از اجرای حلقه دوم
    if spam_config.get("loop_running"):
        logger.info("⚠️ اسپم فور اسپم از قبل در حال اجراست - حلقه جدید ساخته نشد.")
        return
    spam_config["loop_running"] = True
    logger.info("🚀 موتور اسپم فور اسپم آغاز شد.")

    # resolve اولیه entityها
    ok, msg = await resolve_spam_entities()
    if not ok:
        logger.warning(f"resolve اولیه اسپم ناموفق: {msg}")

    try:
        while spam_config["active"]:
            try:
                if not spam_config.get("source_chat") or not spam_config.get("target_chat") or not spam_config.get("source_msg_id"):
                    await asyncio.sleep(3)
                    continue

                accounts = [p for p in config["accounts"]
                            if config.get("account_status", {}).get(p, True) and not is_account_in_cooldown(p)]
                if not accounts:
                    await asyncio.sleep(3)
                    continue

                # همه اکانت‌ها همزمان و قاطی‌پاتی
                tasks = [spam_f4f_worker(p) for p in accounts]
                await asyncio.gather(*tasks, return_exceptions=True)

                # کمی صبر قبل از راند بعدی
                await asyncio.sleep(1)
            except Exception as e:
                logger.error(f"خطا در حلقه اسپم فور اسپم: {e}")
                await asyncio.sleep(5)
    finally:
        spam_config["loop_running"] = False
        logger.info("⏹ موتور اسپم فور اسپم خاتمه یافت.")

# ==========================================================================================

# ================== تابع جدید: خروج گروهی اکانت‌ها ==================
async def leave_group(phone, group_link):
    """خروج یک اکانت از گروه - پشتیبانی از عمومی و خصوصی"""
    try:
        c = await get_client(phone)
        if not c:
            return False, f"❌ اکانت {phone} معتبر یا متصل نیست"

        link = group_link.strip().replace('https://', '').replace('http://', '').replace('t.me/', '').rstrip('/')

        # لینک دعوت خصوصی
        if link.startswith('+') or link.startswith('joinchat/'):
            hash_val = link.replace('joinchat/', '').replace('+', '')
            try:
                res = await c(CheckChatInviteRequest(hash_val))
                chat = getattr(res, "chat", None)
                if chat:
                    await c(LeaveChannelRequest(chat))
                    return True, f"✅ اکانت {phone} از گروه خارج شد."
                else:
                    return False, f"❌ اکانت {phone}: گروه پیدا نشد (شاید عضو نیست)"
            except errors.UserNotParticipantError:
                return True, f"ℹ️ اکانت {phone} از قبل عضو این گروه نبوده است."
            except Exception as e:
                return False, f"❌ اکانت {phone}: {str(e)[:45]}"
        # گروه/کانال عمومی یا آیدی
        else:
            try:
                entity = await c.get_entity(link)
                await c(LeaveChannelRequest(entity))
                return True, f"✅ اکانت {phone} از گروه خارج شد."
            except errors.UserNotParticipantError:
                return True, f"ℹ️ اکانت {phone} از قبل عضو این گروه نبوده است."
            except ValueError:
                # شاید آیدی عددی یا چت id بود
                try:
                    entity = await c.get_entity(int(link))
                    await c(LeaveChannelRequest(entity))
                    return True, f"✅ اکانت {phone} از گروه خارج شد."
                except errors.UserNotParticipantError:
                    return True, f"ℹ️ اکانت {phone} از قبل عضو این گروه نبوده است."
                except Exception as e:
                    return False, f"❌ اکانت {phone}: {str(e)[:45]}"
            except Exception as e:
                return False, f"❌ اکانت {phone}: {str(e)[:45]}"
    except Exception as e:
        return False, f"❌ اکانت {phone}: {str(e)[:45]}"

async def leave_all_accounts_from_group(group_link):
    """خروج همه اکانت‌های فعال از یک گروه به صورت موازی"""
    tasks = []
    for phone in config["accounts"]:
        if config.get("account_status", {}).get(phone, True):
            tasks.append(leave_group(phone, group_link))
    if tasks:
        return await asyncio.gather(*tasks)
    return []
# ==================================================================

def get_random_message(phone):
    if not msgs: return None
    if phone not in last_msg_indices: last_msg_indices[phone] = -1
    avail = [i for i in range(len(msgs)) if i != last_msg_indices[phone]]
    if not avail: avail = list(range(len(msgs)))
    idx = random.choice(avail)
    last_msg_indices[phone] = idx
    return msgs[idx]

def get_random_sticker(phone):
    if not stickers: return None
    if phone not in last_sticker_indices: last_sticker_indices[phone] = -1
    avail = [i for i in range(len(stickers)) if i != last_sticker_indices[phone]]
    if not avail: avail = list(range(len(stickers)))
    idx = random.choice(avail)
    last_sticker_indices[phone] = idx
    return stickers[idx]

def get_random_gif(phone):
    if not gifs: return None
    if phone not in last_gif_indices: last_gif_indices[phone] = -1
    avail = [i for i in range(len(gifs)) if i != last_gif_indices[phone]]
    if not avail: avail = list(range(len(gifs)))
    idx = random.choice(avail)
    last_gif_indices[phone] = idx
    return gifs[idx]

def main_menu():
    return InlineKeyboardMarkup([
        [InlineKeyboardButton("📊 وضعیت سیستم و گزارش‌ها", callback_data="status")],
        [InlineKeyboardButton("➕ افزودن اکانت جدید", callback_data="add_account"), InlineKeyboardButton("📋 مدیریت اکانت‌ها", callback_data="account_manager")],
        [InlineKeyboardButton("📁 مدیریت گروه‌های هدف", callback_data="groups"), InlineKeyboardButton("👥 مدیریت لیست هدف‌ها", callback_data="targets")],
        [InlineKeyboardButton("📤 آپلود لیست پیام‌ها (TXT)", callback_data="upload")],
        [InlineKeyboardButton("🚀 شروع عملیات اتکر", callback_data="start_auto"), InlineKeyboardButton("⏹ توقف عملیات اتکر", callback_data="stop_auto")],
        [InlineKeyboardButton("⏱ تنظیم تاخیر اتکر", callback_data="delay"), InlineKeyboardButton("💬 سیستم ریپ چت پیشرفته", callback_data="reply_chat")],
        [InlineKeyboardButton("🌐 مدیریت ریپ عمومی", callback_data="general_reply_menu")],
        [InlineKeyboardButton("💥 اسپم فور اسپم (جدید)", callback_data="spam_f4f_menu")],
        [InlineKeyboardButton("🤖 استارت ربات با لینک رفرال (جدید)", callback_data="start_bot_menu")],
        [InlineKeyboardButton("💖 ری اکشن خودکار به اکانت هدف (نسخه 5)", callback_data="reaction_menu")],
        [InlineKeyboardButton("🛡 سیستم ضد لیمیت و ضد ریپورت (جدید)", callback_data="anti_limit_menu")],
        [InlineKeyboardButton("👑 مدیریت ادمین‌های ربات", callback_data="admin_panel"), InlineKeyboardButton("🔗 عضویت گروهی اکانت‌ها", callback_data="bulk_join")],
        [InlineKeyboardButton("🚪 خروج گروهی اکانت‌ها (جدید)", callback_data="bulk_leave")],
        [InlineKeyboardButton("ℹ️ درباره سیستم و راهنما", callback_data="about")]
    ])

def about_menu():
    return InlineKeyboardMarkup([
        [InlineKeyboardButton("📢 کانال رسمی اطلاع‌رسانی", url=CHANNEL_LINK)],
        [InlineKeyboardButton("👤 ارتباط مستقیم با مالک و پشتیبانی", url=f"https://t.me/{OWNER_USERNAME.replace('@', '')}")],
        [InlineKeyboardButton("🔙 بازگشت به منوی اصلی", callback_data="back_main")]
    ])

def admin_panel_menu():
    return InlineKeyboardMarkup([
        [InlineKeyboardButton("➕ اعطای دسترسی موقت ادمین", callback_data="add_temp_admin")],
        [InlineKeyboardButton("📋 مشاهده لیست ادمین‌ها", callback_data="list_admins")],
        [InlineKeyboardButton("🗑 لغو دسترسی ادمین", callback_data="remove_admin")],
        [InlineKeyboardButton("🔙 بازگشت به منوی اصلی", callback_data="back_main")]
    ])

def reply_chat_menu():
    t1_status = "✅ فعال" if reply_config["active_target_1"] else "❌ غیرفعال"
    t2_status = "✅ فعال" if reply_config["active_target_2"] else "❌ غیرفعال"
    text_status = "✅ فعال" if reply_config.get("use_text", True) else "❌ غیرفعال"
    return InlineKeyboardMarkup([
        [InlineKeyboardButton("🟢 شروع ربات ریپ چت", callback_data="start_reply"), InlineKeyboardButton("🔴 توقف ربات ریپ چت", callback_data="stop_reply")],
        [InlineKeyboardButton(f"📝 ارسال متن از فایل TXT ({text_status})", callback_data="toggle_reply_text")],
        [InlineKeyboardButton(f"🎯 تنظیم لینک هدف ۱ ({t1_status})", callback_data="set_reply_link_1"), InlineKeyboardButton("🗑 پاک‌سازی ۱", callback_data="clear_reply_link_1")],
        [InlineKeyboardButton(f"🎯 تنظیم لینک هدف ۲ ({t2_status})", callback_data="set_reply_link_2"), InlineKeyboardButton("🗑 پاک‌سازی ۲", callback_data="clear_reply_link_2")],
        [InlineKeyboardButton(f"🔄 تغییر وضعیت هدف ۱", callback_data="toggle_target_1"), InlineKeyboardButton(f"🔄 تغییر وضعیت هدف ۲", callback_data="toggle_target_2")],
        [InlineKeyboardButton("⏱ تنظیم تاخیر زمانی ریپ", callback_data="set_reply_delay")],
        [InlineKeyboardButton("🎴 تنظیمات استیکرهای ریپ", callback_data="sticker_settings"), InlineKeyboardButton("🎬 تنظیمات گیف‌های ریپ", callback_data="gif_settings")],
        [InlineKeyboardButton("📁 انتخاب گروه‌های ویژه ریپ چت", callback_data="reply_groups")],
        [InlineKeyboardButton("🛡 وضعیت سیستم ضد لیمیت", callback_data="anti_limit_menu")],
        [InlineKeyboardButton("🔙 بازگشت به منوی اصلی", callback_data="back_main")]
    ])

def general_reply_menu():
    targets = load_general_targets()
    kb = []
    if not targets:
        kb.append([InlineKeyboardButton("❌ هیچ یوزری ثبت نشده است", callback_data="noop")])
    else:
        for t in targets[:10]:
            kb.append([InlineKeyboardButton(f"🗑 حذف: {t}", callback_data=f"del_gen_target_{t}")])
    kb.extend([
        [InlineKeyboardButton("➕ افزودن آیدی هدف عمومی جدید", callback_data="add_gen_target")],
        [InlineKeyboardButton("🗑 پاک‌سازی کامل لیست عمومی", callback_data="clear_gen_targets")],
        [InlineKeyboardButton("🔙 بازگشت به منوی اصلی", callback_data="back_main")]
    ])
    return InlineKeyboardMarkup(kb)

def sticker_settings_menu():
    return InlineKeyboardMarkup([
        [InlineKeyboardButton("➕ افزودن استیکر جدید (ارسال پشت سر هم)", callback_data="add_sticker")],
        [InlineKeyboardButton("📋 لیست استیکرهای ذخیره‌شده", callback_data="list_stickers"), InlineKeyboardButton("🗑 پاک‌سازی کامل استیکرها", callback_data="clear_stickers")],
        [InlineKeyboardButton("🔁 فعال/غیرفعال‌سازی ارسال استیکر", callback_data="toggle_stickers")],
        [InlineKeyboardButton("🔙 بازگشت به مدیریت ریپ چت", callback_data="reply_chat")]
    ])

def gif_settings_menu():
    return InlineKeyboardMarkup([
        [InlineKeyboardButton("➕ افزودن گیف جدید (ارسال پشت سر هم)", callback_data="add_gif")],
        [InlineKeyboardButton("📋 لیست گیف‌های ذخیره‌شده", callback_data="list_gifs"), InlineKeyboardButton("🗑 پاک‌سازی کامل گیف‌ها", callback_data="clear_gifs")],
        [InlineKeyboardButton("🔁 فعال/غیرفعال‌سازی ارسال گیف", callback_data="toggle_gifs")],
        [InlineKeyboardButton("🔙 بازگشت به مدیریت ریپ چت", callback_data="reply_chat")]
    ])

def account_manager_menu():
    return InlineKeyboardMarkup([
        [InlineKeyboardButton("📋 مشاهده لیست کامل اکانت‌ها", callback_data="list_accounts")],
        [InlineKeyboardButton("✅ تغییر وضعیت فعال/غیرفعال اکانت", callback_data="toggle_account")],
        [InlineKeyboardButton("🗑 حذف یک اکانت از سیستم", callback_data="remove_account"), InlineKeyboardButton("📊 آمار تفکیکی اکانت‌ها", callback_data="accounts_status")],
        [InlineKeyboardButton("🔙 بازگشت به منوی اصلی", callback_data="back_main")]
    ])

def group_manager_menu():
    kb = []
    auto_groups, reply_groups = config.get("active_groups", []), config.get("reply_groups", [])
    if not config["groups"]:
        kb.append([InlineKeyboardButton("❌ در حال حاضر هیچ گروهی ثبت نشده است", callback_data="noop")])
    else:
        for i, g in enumerate(config["groups"]):
            is_auto = "✅" if g in auto_groups else "❌"
            is_reply = "🔄" if g in reply_groups else "⭕"
            kb.append([InlineKeyboardButton(f"اتکر: {is_auto} | ریپ: {is_reply} | {g[:30]}...", callback_data=f"toggle_group_{g}")])
    kb.extend([
        [InlineKeyboardButton("➕ افزودن گروه جدید به لیست", callback_data="add_group")],
        [InlineKeyboardButton("🗑 پاک‌سازی کل گروه‌ها", callback_data="clear_groups")],
        [InlineKeyboardButton("🔙 بازگشت به منوی اصلی", callback_data="back_main")]
    ])
    return InlineKeyboardMarkup(kb)

def reply_groups_menu():
    kb = []
    reply_groups = config.get("reply_groups", [])
    if not config["groups"]:
        kb.append([InlineKeyboardButton("❌ هیچ گروهی ثبت نشده است", callback_data="noop")])
    else:
        for i, g in enumerate(config["groups"]):
            is_reply = "✅ فعال در ریپ" if g in reply_groups else "❌ غیرفعال"
            kb.append([InlineKeyboardButton(f"{is_reply} - {g[:30]}...", callback_data=f"toggle_reply_group_{g}")])
    kb.append([InlineKeyboardButton("🔙 بازگشت به مدیریت ریپ چت", callback_data="reply_chat")])
    return InlineKeyboardMarkup(kb)

def targets_menu():
    targets = load_targets()
    kb = []
    if not targets:
        kb.append([InlineKeyboardButton("❌ هیچ هدف یا یوزری ثبت نشده است", callback_data="noop")])
    else:
        for t in targets[:15]:
            kb.append([InlineKeyboardButton(f"🗑 حذف هدف: {t[:25]}", callback_data=f"del_target_{t}")])
    kb.extend([
        [InlineKeyboardButton("➕ افزودن هدف جدید", callback_data="add_target")],
        [InlineKeyboardButton("🗑 پاک‌سازی تمامی هدف‌ها", callback_data="clear_targets")],
        [InlineKeyboardButton("🔙 بازگشت به منوی اصلی", callback_data="back_main")]
    ])
    return InlineKeyboardMarkup(kb)

async def get_client(phone):
    if phone in clients:
        c = clients[phone]
        if c.is_connected():
            return c
    try:
        # استفاده از ConnectionTcpAbridged برای اتصال پایدارتر
        c = TelegramClient(f"sess_{phone}", API_ID, API_HASH, connection=ConnectionTcpAbridged, timeout=30)
        await c.connect()
        if await c.is_user_authorized():
            clients[phone] = c
            return c
        else:
            await c.disconnect()
            return None
    except Exception as e:
        logger.error(f"خطا در اتصال اکانت {phone}: {e}")
        return None

async def login(phone):
    try:
        if phone in tmp:
            try: await tmp[phone]["c"].disconnect()
            except: pass
            del tmp[phone]

        session_name = f"sess_{phone}"
        session_file = f"{session_name}.session"
        if os.path.exists(session_file):
            try:
                if phone in clients:
                    try: await clients[phone].disconnect()
                    except: pass
                    del clients[phone]
                os.remove(session_file)
            except: pass

        # استفاده از ConnectionTcpAbridged با timeout بیشتر
        c = TelegramClient(session_name, API_ID, API_HASH, connection=ConnectionTcpAbridged, timeout=30)
        await c.connect()
        
        try:
            r = await c.send_code_request(phone)
        except errors.FloodWaitError as e:
            await asyncio.sleep(e.seconds)
            r = await c.send_code_request(phone)
        except Exception as e:
            await c.disconnect()
            return False, f"❌ خطا در اتصال به سرور تلگرام یا ارسال کد: {str(e)[:60]}"

        tmp[phone] = {"c": c, "h": r.phone_code_hash, "tm": datetime.now(), "tr": 0}
        return True, "✅ کد تایید ورود با موفقیت به شماره شما ارسال گردید. لطفا کد دریافتی را وارد کنید."
    except Exception as e:
        return False, f"❌ خطای بحرانی در احراز هویت: {str(e)[:60]}"

async def verify(phone, code):
    try:
        if phone not in tmp: return False, "❌ اطلاعات نشست این شماره منقضی شده است. لطفا دوباره تلاش کنید."
        d = tmp[phone]
        if datetime.now() - d["tm"] > timedelta(minutes=10):
            try: await d["c"].disconnect()
            except: pass
            del tmp[phone]
            return False, "❌ زمان مجاز برای ورود کد به پایان رسیده است."

        c_code = re.sub(r'\D', '', str(code))
        if len(c_code) != 5: return False, "❌ کد تایید باید دقیقاً ۵ رقم باشد."

        d["tr"] += 1
        if d["tr"] > 5:
            try: await d["c"].disconnect()
            except: pass
            del tmp[phone]
            return False, "❌ تعداد تلاش‌های ناموفق بیش از حد مجاز است."

        try:
            await d["c"].sign_in(phone=phone, code=c_code, phone_code_hash=d["h"])
        except errors.PhoneCodeInvalidError:
            return False, f"❌ کد وارد شده اشتباه است! {5 - d['tr']} تلاش باقی مانده."
        except errors.PhoneCodeExpiredError:
            return False, "❌ کد تایید منقضی شده است."
        except errors.SessionPasswordNeededError:
            return False, "❌ این اکانت دارای تایید دو مرحله‌ای (Password) است که در این نسخه پشتیبانی نمی‌شود."
        except Exception as e:
            return False, f"❌ خطا در بررسی کد: {str(e)[:60]}"

        if await d["c"].is_user_authorized():
            clients[phone] = d["c"]
            del tmp[phone]
            if phone not in config["accounts"]:
                config["accounts"].append(phone)
                config["account_status"][phone] = True
                save_config(config)
            return True, f"✅ اکانت با شماره {phone} با موفقیت تایید و به سیستم افزوده شد."
        return False, "❌ خطای ناشناخته در تأیید نهایی حساب کاربری."
    except Exception as e:
        return False, f"❌ خطای سیستم: {str(e)[:60]}"

async def join_group(phone, group_link):
    try:
        c = await get_client(phone)
        if not c: return False, f"❌ اکانت {phone} معتبر یا متصل نیست"
        link = group_link.strip().replace('https://', '').replace('http://', '').replace('t.me/', '')
        if link.startswith('+') or link.startswith('joinchat/'):
            hash_val = link.replace('joinchat/', '').replace('+', '')
            await c(ImportChatInviteRequest(hash_val))
        else:
            await c(JoinChannelRequest(link))
        return True, f"✅ اکانت {phone} با موفقیت به گروه پیوست."
    except errors.UserAlreadyParticipantError:
        return True, f"ℹ️ اکانت {phone} از قبل عضو این گروه بوده است."
    except Exception as e:
        return False, f"❌ اکانت {phone}: {str(e)[:45]}"

async def join_all_accounts_to_group(group_link):
    tasks = []
    for phone in config["accounts"]:
        if config.get("account_status", {}).get(phone, True):
            tasks.append(join_group(phone, group_link))
    if tasks:
        return await asyncio.gather(*tasks)
    return []

async def mention(c, g, m):
    try:
        if not c.is_connected(): await c.connect()
        chat = await c.get_entity(g)
        targets = load_targets()
        if not targets: return 0
        ms = []
        for t in targets[:15]:
            t = t.strip()
            if t.startswith('@'):
                try:
                    u = await c.get_entity(t)
                    if u: ms.append(f'<a href="tg://user?id={u.id}">@{t[1:]}</a>')
                except: pass
            elif t.isdigit() or (t.startswith('-') and t[1:].isdigit()):
                try:
                    u = await c.get_entity(int(t))
                    if u:
                        un = f"@{u.username}" if u.username else "کاربر"
                        ms.append(f'<a href="tg://user?id={int(t)}">{un}</a>')
                except: pass
        if not ms: return 0
        await c.send_message(chat, f"{' '.join(ms)}\n\n{m}", parse_mode='html')
        return len(ms)
    except:
        return 0

async def auto_loop():
    logger.info("🚀 موتور اتکر هوشمند و ارسال منشن آغاز به کار کرد.")
    fail_count = 0
    global account_mention_cooldown
    while config["active"]:
        try:
            active_groups = config.get("active_groups", [])
            if not active_groups: active_groups = config["groups"]
            if not active_groups or not config["accounts"]:
                await asyncio.sleep(5)
                continue

            for g in active_groups:
                if g not in config["groups"] or not config["active"]: break

                current_time = datetime.now()
                for phone in list(account_mention_cooldown.keys()):
                    if (current_time - account_mention_cooldown[phone]).seconds >= config.get("mention_delay", 3):
                        del account_mention_cooldown[phone]

                available_accounts = []
                for p in config["accounts"]:
                    if not config.get("account_status", {}).get(p, True): continue
                    if is_account_in_cooldown(p): continue
                    if p not in account_mention_cooldown: available_accounts.append(p)

                selected_accounts = available_accounts

                if selected_accounts:
                    tasks = [send_mention_with_account(p, g) for p in selected_accounts]
                    results = await asyncio.gather(*tasks, return_exceptions=True)
                    for i, p in enumerate(selected_accounts):
                        if i < len(results) and isinstance(results[i], int) and results[i] > 0:
                            account_mention_cooldown[p] = datetime.now()
                            fail_count = 0
                    success_count = sum(1 for r in results if isinstance(r, int) and r > 0)
                    if success_count == 0: fail_count += 1

                await asyncio.sleep(config.get("mention_delay", 3))
                if fail_count > 10:
                    await asyncio.sleep(60)
                    fail_count = 0
        except Exception as e:
            logger.error(f"خطا در حلقه اتکر: {e}")
            await asyncio.sleep(10)

async def send_mention_with_account(phone, group):
    try:
        c = await get_client(phone)
        if not c: return 0
        message_text = get_random_message(phone)
        if not message_text: return 0
        return await mention(c, group, message_text)
    except:
        return 0

async def send_sticker_to_group(phone, group, sticker_path, reply_to=None):
    try:
        c = await get_client(phone)
        if not c: return False
        chat_entity = await c.get_entity(group)
        if os.path.exists(sticker_path):
            await c.send_file(chat_entity, sticker_path, reply_to=reply_to)
            return True
        return False
    except errors.FloodWaitError as e:
        mark_account_cooldown(phone, e.seconds + FLOOD_WAIT_BUFFER, "FloodWait (استیکر)")
        return False
    except errors.PeerFloodError:
        mark_account_cooldown(phone, PEER_FLOOD_COOLDOWN, "PeerFlood (استیکر)")
        return False
    except: return False

async def send_gif_to_group(phone, group, gif_path, reply_to=None):
    try:
        c = await get_client(phone)
        if not c: return False
        chat_entity = await c.get_entity(group)
        if os.path.exists(gif_path):
            await c.send_file(chat_entity, gif_path, reply_to=reply_to)
            return True
        return False
    except errors.FloodWaitError as e:
        mark_account_cooldown(phone, e.seconds + FLOOD_WAIT_BUFFER, "FloodWait (گیف)")
        return False
    except errors.PeerFloodError:
        mark_account_cooldown(phone, PEER_FLOOD_COOLDOWN, "PeerFlood (گیف)")
        return False
    except: return False

async def execute_reply_for_target(phone, chat_id, target_msg_id):
    """ارسال ریپ از یک اکانت به یک هدف - با سیستم ضد لیمیت فعال"""
    try:
        # 🛡 چک کول‌داون ضد لیمیت
        if is_account_in_cooldown(phone):
            return False

        c = await get_client(phone)
        if not c: return False

        # 🛡 اعمال حداقل فاصله بین ارسال‌های متوالی (ضد لیمیت)
        await apply_anti_limit_gap(phone)

        # تاخیر رندوم اضافه برای طبیعی‌تر شدن رفتار
        await asyncio.sleep(random.uniform(0.2, 1.2))

        if phone not in reply_counters: reply_counters[phone] = 0
        counter = reply_counters[phone]
        reply_counters[phone] = (counter + 1) % 4

        use_text = reply_config.get("use_text", True)
        use_sticker = reply_config.get("use_stickers", False) and stickers
        use_gif = reply_config.get("use_gifs", False) and gifs

        # 🎴 اولویت استیکر/گیف (حتی اگه متن فعال باشه، بعضی وقتا رسانه میفرسته)
        if counter == 2 and use_sticker:
            sticker_path = get_random_sticker(phone)
            if sticker_path and await send_sticker_to_group(phone, chat_id, sticker_path, target_msg_id):
                return True
        elif counter == 3 and use_gif:
            gif_path = get_random_gif(phone)
            if gif_path and await send_gif_to_group(phone, chat_id, gif_path, target_msg_id):
                return True

        # 📝 ارسال متن (اگر خاموش نکرده باشن)
        if use_text:
            message_text = get_random_message(phone)
            if message_text:
                if target_msg_id:
                    await c.send_message(chat_id, message_text, reply_to=target_msg_id)
                else:
                    await c.send_message(chat_id, message_text)
                return True
            return False
        else:
            # وقتی متن خاموشه فقط استیکر/گیف میفرستیم
            # اگه استیکر یا گیف فعال باشه، از بینشون یکی میفرستیم
            if use_sticker or use_gif:
                # اگه در بلاک‌های بالا فرستاده نشده، اینجا یکی میفرستیم
                if use_sticker and use_gif:
                    if random.random() < 0.5:
                        sticker_path = get_random_sticker(phone)
                        if sticker_path and await send_sticker_to_group(phone, chat_id, sticker_path, target_msg_id):
                            return True
                        gif_path = get_random_gif(phone)
                        if gif_path and await send_gif_to_group(phone, chat_id, gif_path, target_msg_id):
                            return True
                    else:
                        gif_path = get_random_gif(phone)
                        if gif_path and await send_gif_to_group(phone, chat_id, gif_path, target_msg_id):
                            return True
                        sticker_path = get_random_sticker(phone)
                        if sticker_path and await send_sticker_to_group(phone, chat_id, sticker_path, target_msg_id):
                            return True
                elif use_sticker:
                    sticker_path = get_random_sticker(phone)
                    if sticker_path and await send_sticker_to_group(phone, chat_id, sticker_path, target_msg_id):
                        return True
                elif use_gif:
                    gif_path = get_random_gif(phone)
                    if gif_path and await send_gif_to_group(phone, chat_id, gif_path, target_msg_id):
                        return True
            return False

    except errors.FloodWaitError as e:
        cooldown_sec = e.seconds + FLOOD_WAIT_BUFFER
        mark_account_cooldown(phone, cooldown_sec, "FloodWait (ریپ)")
        return False
    except errors.PeerFloodError:
        mark_account_cooldown(phone, PEER_FLOOD_COOLDOWN, "PeerFlood (ریپ)")
        return False
    except errors.UserBannedInChannelError:
        mark_account_cooldown(phone, USER_BANNED_COOLDOWN, "UserBanned (ریپ)")
        return False
    except errors.ChatWriteForbiddenError:
        # اکانت توی این گروه نمی‌تونه بنویسه - کول‌داون کوتاه برای این اکانت روی این گروه
        return False
    except Exception as e:
        logger.error(f"خطا در ریپ {phone}: {str(e)[:80]}")
        return False

async def reply_chat_function():
    logger.info("💬 سیستم ریپ‌چت هوشمند با دو لینک هدف آغاز به کار کرد.")
    fail_count = 0
    while reply_config["active"]:
        try:
            has_active_target = (reply_config["active_target_1"] and reply_config["target_link_1"] and reply_config["chat_id_1"]) or \
                                (reply_config["active_target_2"] and reply_config["target_link_2"] and reply_config["chat_id_2"])
            if not has_active_target:
                await asyncio.sleep(5)
                continue

            use_text = reply_config.get("use_text", True)
            has_content = msgs or (reply_config.get("use_stickers", False) and stickers) or (reply_config.get("use_gifs", False) and gifs)
            if not has_content:
                await asyncio.sleep(5)
                continue
            # اگه متن خاموشه و نه استیکر نه گیف فعاله، هیچی برای فرستادن نیست
            if not use_text and not (reply_config.get("use_stickers", False) and stickers) and not (reply_config.get("use_gifs", False) and gifs):
                await asyncio.sleep(5)
                continue

            tasks = []
            reply_groups = config.get("reply_groups", [])
            if not reply_groups: reply_groups = config["groups"]

            for phone in config["accounts"]:
                if not config.get("account_status", {}).get(phone, True): continue
                # 🛡 اکانت‌های در کول‌داون رو رد کن
                if is_account_in_cooldown(phone): continue

                for g in reply_groups:
                    if g not in config["groups"]: continue

                    if reply_config["active_target_1"] and reply_config["chat_id_1"] and reply_config["target_msg_id_1"]:
                        tasks.append(execute_reply_for_target(phone, reply_config["chat_id_1"], reply_config["target_msg_id_1"]))

                    if reply_config["active_target_2"] and reply_config["chat_id_2"] and reply_config["target_msg_id_2"]:
                        tasks.append(execute_reply_for_target(phone, reply_config["chat_id_2"], reply_config["target_msg_id_2"]))

            if tasks:
                results = await asyncio.gather(*tasks, return_exceptions=True)
                success_count = sum(1 for r in results if r is True)
                if success_count > 0: fail_count = 0
                else: fail_count += 1

            await asyncio.sleep(reply_config["delay"])
            if fail_count > 10:
                await asyncio.sleep(60)
                fail_count = 0
        except Exception as e:
            logger.error(f"خطا در حلقه ریپ‌چت: {e}")
            await asyncio.sleep(10)

async def setup_general_reply_listeners():
    for phone in config["accounts"]:
        c = await get_client(phone)
        if not c: continue
        try:
            @c.on(events.NewMessage(incoming=True))
            async def general_reply_listener(event):
                try:
                    sender = await event.get_sender()
                    if not sender: return
                    gen_targets = load_general_targets()
                    if not gen_targets: return

                    sender_id_str = str(sender.id)
                    sender_username = f"@{sender.username}" if sender.username else ""

                    matched = False
                    for gt in gen_targets:
                        gt = gt.strip()
                        if gt == sender_id_str or gt == sender_username or (gt.startswith('@') and gt.lower() == sender_username.lower()):
                            matched = True
                            break

                    if matched:
                        msg_text = get_random_message(phone)
                        if msg_text:
                            await event.reply(msg_text)
                except: pass
        except: pass

def check_admin_access(user_id):
    if user_id in config.get("admins", ADMINS): return True
    temp_admins = config.get("temp_admins", {})
    if str(user_id) in temp_admins:
        if datetime.now() < datetime.fromisoformat(temp_admins[str(user_id)]): return True
        else:
            del temp_admins[str(user_id)]
            config["temp_admins"] = temp_admins
            save_config(config)
    return False

async def add_temp_admin(user_id, days):
    temp_admins = config.get("temp_admins", {})
    temp_admins[str(user_id)] = (datetime.now() + timedelta(days=days)).isoformat()
    config["temp_admins"] = temp_admins
    save_config(config)
    return f"✅ ادمین با آیدی عددی {user_id} با موفقیت به مدت {days} روز به سیستم افزوده شد."

async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
    if not check_admin_access(update.effective_user.id):
        return await update.message.reply_text("❌ شما دسترسی لازم برای استفاده از این ربات را ندارید!")
    await update.message.reply_text(
        "🤖 **سیستم مدیریت هوشمند اتکر و ریپ‌چت (نسخه پیشرفته v5.1)**\n\n"
        "🔹 از طریق دکمه‌های شیک و منظم زیر می‌توانید تمامی بخش‌های سیستم، اکانت‌ها، گروه‌ها و ارسال رسانه‌ها را کنترل کنید:\n"
        "💖 قابلیت جدید: سیستم ری اکشن خودکار به اکانت هدف\n"
        "🧠 قابلیت جدید: هوش مصنوعی حل کپچا در استارت ربات",
        reply_markup=main_menu(), parse_mode='Markdown'
    )

async def user_panel(update: Update, context: ContextTypes.DEFAULT_TYPE):
    user_id = update.effective_user.id
    if not check_admin_access(user_id):
        return await update.message.reply_text("❌ دسترسی غیرمجاز!")
    active_accounts = sum(1 for p in config["accounts"] if config.get("account_status", {}).get(p, True))
    targets = load_targets()
    gen_targets = load_general_targets()
    reply_groups = config.get("reply_groups", [])
    anti = anti_limit_stats()
    text_status = "فعال ✅" if reply_config.get("use_text", True) else "غیرفعال ❌"
    reaction_status = "فعال ✅" if reaction_config.get("active") else "غیرفعال ❌"
    ai_status = "فعال ✅" if ai_captcha_config.get("enabled") else "غیرفعال ❌"
    text = (
        f"📊 **گزارش جامع وضعیت سیستم اتکر و ریپ‌چت**\n\n"
        f"🔹 **وضعیت موتورها:**\n"
        f"• وضعیت اتکر اصلی: {'فعال ✅' if config['active'] else 'غیرفعال ❌'}\n"
        f"• وضعیت ریپ چت: {'فعال ✅' if reply_config['active'] else 'غیرفعال ❌'}\n"
        f"• ارسال متن از فایل TXT در ریپ: {text_status}\n"
        f"• وضعیت اسپم فور اسپم: {'فعال ✅' if spam_config['active'] else 'غیرفعال ❌'}\n"
        f"• وضعیت ری اکشن خودکار: {reaction_status}\n"
        f"• وضعیت هوش مصنوعی کپچا: {ai_status}\n\n"
        f"👥 **آمار اکانت‌های متصل:**\n"
        f"• کل اکانت‌ها: {len(config['accounts'])}\n"
        f"• اکانت‌های فعال و آماده: {active_accounts}\n"
        f"• اکانت‌های غیرفعال شده: {len(config['accounts']) - active_accounts}\n\n"
        f"🛡 **سیستم ضد لیمیت:**\n"
        f"• اکانت‌های سالم: {anti['healthy']}\n"
        f"• اکانت‌های در کول‌داون: {anti['in_cooldown']}\n\n"
        f"📁 **گروه‌ها و هدف‌ها:**\n"
        f"• گروه‌های فعال اتکر: {len(config.get('active_groups', [])) or len(config['groups'])}\n"
        f"• گروه‌های فعال ریپ‌چت: {len(reply_groups)}\n"
        f"• هدف‌های منشن: {len(targets)} | هدف‌های ریپ عمومی: {len(gen_targets)}\n\n"
        f"📝 **محتوا و رسانه‌ها:**\n"
        f"• متن‌های پیام: {len(msgs)}\n"
        f"• استیکرهای ذخیره شده: {len(stickers)}\n"
        f"• گیف‌های ذخیره شده: {len(gifs)}\n"
    )
    kb = [
        [InlineKeyboardButton("🔄 بروزرسانی وضعیت", callback_data="refresh_panel")],
        [InlineKeyboardButton("🔙 بازگشت به منوی اصلی", callback_data="back_main")]
    ]
    await update.message.reply_text(text, reply_markup=InlineKeyboardMarkup(kb), parse_mode='Markdown')

async def callback_handler(update: Update, context: ContextTypes.DEFAULT_TYPE):
    query = update.callback_query
    await query.answer()
    data = query.data
    user_id = update.effective_user.id
    if not check_admin_access(user_id) and data not in ["about", "back_main", "refresh_panel"]:
        return await query.edit_message_text("❌ شما دسترسی ندارید!", reply_markup=main_menu())

    if data == "refresh_panel":
        await query.edit_message_text("🔄 وضعیت سیستم با موفقیت بروزرسانی شد.", reply_markup=main_menu())
    elif data == "status":
        active_accounts = sum(1 for p in config["accounts"] if config.get("account_status", {}).get(p, True))
        anti = anti_limit_stats()
        await query.edit_message_text(
            f"📊 وضعیت سیستم:\n"
            f"• کل اکانت‌ها: {len(config['accounts'])}\n"
            f"• اکانت‌های فعال: {active_accounts}\n"
            f"• اکانت‌های در کول‌داون ضد لیمیت: {anti['in_cooldown']}\n"
            f"• گروه‌ها: {len(config['groups'])}",
            reply_markup=main_menu()
        )
    elif data == "about":
        await query.edit_message_text("ℹ️ **راهنمای جامع سیستم اتکر و ریپ‌چت**", reply_markup=about_menu(), parse_mode='Markdown')
    elif data == "bulk_join":
        await query.edit_message_text("🔗 **عضویت گروهی اکانت‌ها**\n\nلینک گروه مورد نظر را ارسال کنید:")
        context.user_data['action'] = 'bulk_join'
    elif data == "bulk_leave":
        await query.edit_message_text(
            "🚪 **خروج گروهی اکانت‌ها**\n\n"
            "لینک گروه یا آیدی گروه مورد نظر رو ارسال کنید تا همه اکانت‌های فعال ازش خارج بشن.\n\n"
            "فرمت‌های پشتیبانی‌شده:\n"
            "• گروه عمومی: `https://t.me/mygroup` یا `@mygroup`\n"
            "• گروه خصوصی: `https://t.me/+AbCdEfGhIjK`\n"
            "• آیدی عددی: `-1001234567890`",
            parse_mode='Markdown'
        )
        context.user_data['action'] = 'bulk_leave'
    elif data == "add_account":
        await query.edit_message_text("📱 **افزودن اکانت جدید**\n\nلطفاً شماره تلفن اکانت خود را وارد کنید (مثلا +989123456789):")
        context.user_data['action'] = 'add_acc'
    elif data == "groups":
        await query.edit_message_text("📁 **مدیریت گروه‌ها**", reply_markup=group_manager_menu(), parse_mode='Markdown')
    elif data == "add_group":
        await query.edit_message_text("📁 **افزودن گروه جدید**\n\nلینک گروه یا آیدی آن را ارسال کنید:")
        context.user_data['action'] = 'add_group'
    elif data.startswith("toggle_group_"):
        g = data.replace("toggle_group_", "")
        ag = config.setdefault("active_groups", [])
        if g in ag: ag.remove(g)
        else: ag.append(g)
        save_config(config)
        await query.edit_message_text("✅ وضعیت گروه در اتکر تغییر یافت.", reply_markup=group_manager_menu())
    elif data.startswith("toggle_reply_group_"):
        g = data.replace("toggle_reply_group_", "")
        rg = config.setdefault("reply_groups", [])
        if g in rg: rg.remove(g)
        else: rg.append(g)
        save_config(config)
        await query.edit_message_text("✅ وضعیت گروه در ریپ‌چت تغییر یافت.", reply_markup=group_manager_menu())
    elif data == "clear_groups":
        config["groups"], config["active_groups"], config["reply_groups"] = [], [], []
        save_config(config)
        await query.edit_message_text("🗑 تمامی گروه‌ها با موفقیت پاک شدند.", reply_markup=main_menu())
    elif data == "targets":
        await query.edit_message_text("👥 **مدیریت لیست هدف‌ها**", reply_markup=targets_menu())
    elif data == "add_target":
        await query.edit_message_text("🎯 **افزودن هدف جدید**\n\nیوزرنیم هدف (مثلا @username) یا آیدی عددی را وارد کنید:")
        context.user_data['action'] = 'add_target'
    elif data.startswith("del_target_"):
        t = data.replace("del_target_", "")
        tg = load_targets()
        if t in tg: tg.remove(t); save_targets(tg)
        await query.edit_message_text("✅ هدف مورد نظر حذف شد.", reply_markup=targets_menu())
    elif data == "clear_targets":
        save_targets([])
        await query.edit_message_text("🗑 تمامی هدف‌ها پاک شدند.", reply_markup=main_menu())

    elif data == "general_reply_menu":
        await query.edit_message_text("🌐 **مدیریت لیست ریپ عمومی**\n\nدر این بخش می‌توانید آیدی هر کاربری را وارد کنید تا در گروه‌های مشترک به او پاسخ داده شود:", reply_markup=general_reply_menu())
    elif data == "add_gen_target":
        await query.edit_message_text("🌐 **افزودن آیدی هدف عمومی**\n\nیوزرنیم یا آیدی عددی کاربر مورد نظر را بفرستید:")
        context.user_data['action'] = 'add_gen_target'
    elif data.startswith("del_gen_target_"):
        gt = data.replace("del_gen_target_", "")
        gt_list = load_general_targets()
        if gt in gt_list: gt_list.remove(gt); save_general_targets(gt_list)
        await query.edit_message_text("✅ هدف عمومی مورد نظر حذف شد.", reply_markup=general_reply_menu())
    elif data == "clear_gen_targets":
        save_general_targets([])
        await query.edit_message_text("🗑 تمامی هدف‌های عمومی پاک شدند.", reply_markup=general_reply_menu())
    elif data == "upload":
        await query.edit_message_text("📤 **آپلود لیست پیام‌ها**\n\nفایل متنی (TXT) پیام‌ها را ارسال کنید:")
        context.user_data['action'] = 'waiting_file'
    elif data == "start_auto":
        config["active"] = True; save_config(config)
        await query.edit_message_text("🚀 عملیات اتکر با موفقیت شروع شد!", reply_markup=main_menu())
        asyncio.create_task(auto_loop())
    elif data == "stop_auto":
        config["active"] = False; save_config(config)
        await query.edit_message_text("⏹ عملیات اتکر متوقف شد.", reply_markup=main_menu())
    elif data == "delay":
        await query.edit_message_text("⏱ **تنظیم تاخیر اتکر**\n\nمقدار تاخیر بر حسب ثانیه را وارد کنید:")
        context.user_data['action'] = 'delay'
    elif data == "reply_chat":
        text_status = "فعال ✅" if reply_config.get("use_text", True) else "غیرفعال ❌"
        await query.edit_message_text(
            f"💬 **سیستم پیشرفته ریپ‌چت (دو لینک هدف)**\n\n"
            f"📝 وضعیت ارسال متن از فایل TXT: {text_status}\n"
            f"🎴 استیکر: {'فعال' if reply_config.get('use_stickers', False) else 'غیرفعال'}\n"
            f"🎬 گیف: {'فعال' if reply_config.get('use_gifs', False) else 'غیرفعال'}",
            reply_markup=reply_chat_menu()
        )
    elif data == "reply_groups":
        await query.edit_message_text("📁 **انتخاب گروه‌های ویژه ریپ‌چت**", reply_markup=reply_groups_menu())
    elif data == "toggle_reply_text":
        reply_config["use_text"] = not reply_config.get("use_text", True)
        status = "فعال ✅" if reply_config["use_text"] else "غیرفعال ❌"
        await query.edit_message_text(
            f"✅ وضعیت ارسال متن از فایل TXT تغییر یافت: {status}\n\n"
            f"{'📝 حالا اکانت‌ها متن از فایل TXT می‌فرستن.' if reply_config['use_text'] else '🎴 حالا اکانت‌ها فقط استیکر و گیف می‌فرستن (البته اگه فعالشون کرده باشی).'}",
            reply_markup=reply_chat_menu()
        )
    elif data == "start_reply":
        reply_config["active"] = True
        await query.edit_message_text("💬 سیستم ریپ‌چت فعال شد.", reply_markup=reply_chat_menu())
        asyncio.create_task(reply_chat_function())
        asyncio.create_task(setup_general_reply_listeners())
    elif data == "stop_reply":
        reply_config["active"] = False
        await query.edit_message_text("⏹ سیستم ریپ‌چت متوقف شد.", reply_markup=reply_chat_menu())
    elif data == "set_reply_link_1":
        await query.edit_message_text("🎯 **تنظیم لینک پیام هدف ۱**\n\nلینک پیام مورد نظر را ارسال کنید:")
        context.user_data['action'] = 'set_reply_link_1'
    elif data == "set_reply_link_2":
        await query.edit_message_text("🎯 **تنظیم لینک پیام هدف ۲**\n\nلینک پیام مورد نظر را ارسال کنید:")
        context.user_data['action'] = 'set_reply_link_2'
    elif data == "clear_reply_link_1":
        reply_config["target_link_1"], reply_config["target_msg_id_1"], reply_config["chat_id_1"] = "", None, None
        await query.edit_message_text("🗑 لینک هدف ۱ پاک شد.", reply_markup=reply_chat_menu())
    elif data == "clear_reply_link_2":
        reply_config["target_link_2"], reply_config["target_msg_id_2"], reply_config["chat_id_2"] = "", None, None
        await query.edit_message_text("🗑 لینک هدف ۲ پاک شد.", reply_markup=reply_chat_menu())
    elif data == "toggle_target_1":
        reply_config["active_target_1"] = not reply_config["active_target_1"]
        await query.edit_message_text(f"✅ وضعیت هدف ۱ تغییر یافت: {'فعال' if reply_config['active_target_1'] else 'غیرفعال'}", reply_markup=reply_chat_menu())
    elif data == "toggle_target_2":
        reply_config["active_target_2"] = not reply_config["active_target_2"]
        await query.edit_message_text(f"✅ وضعیت هدف ۲ تغییر یافت: {'فعال' if reply_config['active_target_2'] else 'غیرفعال'}", reply_markup=reply_chat_menu())
    elif data == "set_reply_delay":
        await query.edit_message_text("⏱ مقدار تاخیر ریپ‌چت (ثانیه) را وارد کنید:")
        context.user_data['action'] = 'set_reply_delay'
    elif data == "sticker_settings":
        await query.edit_message_text("🎴 **مدیریت استیکرها**", reply_markup=sticker_settings_menu())
    elif data == "add_sticker":
        await query.edit_message_text("🎴 **افزودن استیکر (حالت آپلود گروهی)**\n\nاستیکرهای خود را **پشت سر هم** ارسال کنید. پس از اتمام از دکمه بازگشت استفاده کنید:")
        context.user_data['action'] = 'add_sticker'
    elif data == "list_stickers":
        await query.edit_message_text(f"🎴 تعداد کل استیکرها: {len(stickers)} عدد", reply_markup=sticker_settings_menu())
    elif data == "clear_stickers":
        stickers.clear(); save_stickers(stickers)
        await query.edit_message_text("🗑 تمامی استیکرها پاک شدند.", reply_markup=sticker_settings_menu())
    elif data == "toggle_stickers":
        reply_config["use_stickers"] = not reply_config.get("use_stickers", False)
        await query.edit_message_text(f"✅ وضعیت ارسال استیکر: {'فعال' if reply_config['use_stickers'] else 'غیرفعال'}", reply_markup=sticker_settings_menu())
    elif data == "gif_settings":
        await query.edit_message_text("🎬 **مدیریت گیف‌ها**", reply_markup=gif_settings_menu())
    elif data == "add_gif":
        await query.edit_message_text("🎬 **افزودن گیف (حالت آپلود گروهی)**\n\nگیف‌ها یا ویدیوهای خود را **پشت سر هم** ارسال کنید. پس از اتمام از دکمه بازگشت استفاده کنید:")
        context.user_data['action'] = 'add_gif'
    elif data == "list_gifs":
        await query.edit_message_text(f"🎬 تعداد کل گیف‌ها: {len(gifs)} عدد", reply_markup=gif_settings_menu())
    elif data == "clear_gifs":
        gifs.clear(); save_gifs(gifs)
        await query.edit_message_text("🗑 تمامی گیف‌ها پاک شدند.", reply_markup=gif_settings_menu())
    elif data == "toggle_gifs":
        reply_config["use_gifs"] = not reply_config.get("use_gifs", False)
        await query.edit_message_text(f"✅ وضعیت ارسال گیف: {'فعال' if reply_config['use_gifs'] else 'غیرفعال'}", reply_markup=gif_settings_menu())
    elif data == "account_manager":
        await query.edit_message_text("📋 **مدیریت اکانت‌ها**", reply_markup=account_manager_menu())
    elif data == "list_accounts":
        acc_list = "\n".join([f"• {p} ({'فعال ✅' if config.get('account_status', {}).get(p, True) else 'غیرفعال ❌'}){' | 🛡 کول‌داون ' + str(get_cooldown_remaining(p)) + 'ث' if is_account_in_cooldown(p) else ''}" for p in config['accounts']]) or "هیچ اکانتی ثبت نشده است."
        await query.edit_message_text(f"📋 لیست اکانت‌ها:\n\n{acc_list}", reply_markup=account_manager_menu())
    elif data == "toggle_account":
        await query.edit_message_text("📱 شماره اکانت را وارد کنید:")
        context.user_data['action'] = 'toggle_account'
    elif data == "remove_account":
        await query.edit_message_text("🗑 شماره اکانت جهت حذف را وارد کنید:")
        context.user_data['action'] = 'remove_account'
    elif data == "accounts_status":
        anti = anti_limit_stats()
        await query.edit_message_text(
            f"📊 کل اکانت‌ها: {len(config['accounts'])}\n"
            f"🛡 اکانت‌های سالم: {anti['healthy']}\n"
            f"⏳ اکانت‌های در کول‌داون: {anti['in_cooldown']}",
            reply_markup=account_manager_menu()
        )
    elif data == "admin_panel":
        await query.edit_message_text("👑 **پنل مدیریت ادمین‌ها**", reply_markup=admin_panel_menu())
    elif data == "add_temp_admin":
        await query.edit_message_text("انتخاب مدت زمان:", reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("۷ روزه", callback_data="temp_admin_7")], [InlineKeyboardButton("🔙", callback_data="admin_panel")]]))
    elif data.startswith("temp_admin_"):
        await query.edit_message_text("آیدی عددی ادمین جدید را وارد کنید:")
        context.user_data['action'] = data
    elif data == "list_admins":
        await query.edit_message_text(f"👑 ادمین‌های اصلی: {ADMINS}\n ادمین‌های موقت: {list(config.get('temp_admins', {}).keys())}", reply_markup=admin_panel_menu())
    elif data == "remove_admin":
        await query.edit_message_text("آیدی عددی ادمین را برای حذف وارد کنید:")
        context.user_data['action'] = 'remove_admin'
    elif data == "back_main":
        context.user_data['action'] = None
        await query.edit_message_text("🤖 **منوی اصلی سیستم**", reply_markup=main_menu(), parse_mode='Markdown')
    elif data == "noop":
        await query.edit_message_text("⚠️ غیرفعال", reply_markup=main_menu())

    # ================== 🛡 بخش سیستم ضد لیمیت و ضد ریپورت ==================
    elif data == "anti_limit_menu":
        kb, cd_text = anti_limit_menu()
        stats = anti_limit_stats()
        await query.edit_message_text(
            f"🛡 **سیستم ضد لیمیت و ضد ریپورت**\n\n"
            f"این سیستم به صورت خودکار:\n"
            f"• خطاهای FloodWait و PeerFlood رو مدیریت می‌کنه\n"
            f"• اکانت‌های در خطر رو موقتا کنار می‌ذاره\n"
            f"• حداقل فاصله بین ارسال‌های متوالی رو رعایت می‌کنه\n"
            f"• ⚠️ سرعت رو کم نمی‌کنه - سرعت دست خودته!\n\n"
            f"📊 **آمار لحظه‌ای:**\n"
            f"• کل اکانت‌ها: {stats['total']}\n"
            f"• اکانت‌های سالم: {stats['healthy']}\n"
            f"• اکانت‌های در کول‌داون: {stats['in_cooldown']}\n\n"
            f"⏳ **کول‌داون‌های فعال:**\n{cd_text}",
            reply_markup=kb, parse_mode='Markdown'
        )
    elif data == "anti_limit_refresh":
        kb, cd_text = anti_limit_menu()
        stats = anti_limit_stats()
        await query.edit_message_text(
            f"🛡 **وضعیت بروزرسانی شد**\n\n"
            f"• اکانت‌های سالم: {stats['healthy']}\n"
            f"• اکانت‌های در کول‌داون: {stats['in_cooldown']}\n\n"
            f"⏳ کول‌داون‌ها:\n{cd_text}",
            reply_markup=kb, parse_mode='Markdown'
        )
    elif data == "anti_limit_reset_all":
        flood_cooldowns.clear()
        report_risk_counter.clear()
        await query.edit_message_text("♻️ تمام کول‌داون‌ها ریست شدند.", reply_markup=main_menu())
    # ========================================================================

    # ================== 💖 بخش ری اکشن خودکار به اکانت هدف ==================
    elif data == "reaction_menu":
        tgt = reaction_config.get("target_user") or "تنظیم نشده"
        cur_key = reaction_config.get("reaction", "❤")
        cur = REACTION_PRESETS.get(cur_key, cur_key)
        status = "🟢 فعال" if reaction_config.get("active") else "🔴 غیرفعال"
        sent = reaction_config.get("sent_count", 0)
        ok = reaction_config.get("success_count", 0)
        fail = reaction_config.get("fail_count", 0)
        reg = len(reaction_phones_registered)
        await query.edit_message_text(
            f"💖 **سیستم ری اکشن خودکار به اکانت هدف**\n\n"
            f"👤 اکانت هدف: `{tgt}`\n"
            f"💗 ری اکشن انتخاب‌شده: {cur}\n"
            f"📡 وضعیت موتور: {status}\n"
            f"📊 کل ری اکشن‌ها: {sent} | ✅ موفق: {ok} | ❌ ناموفق: {fail}\n"
            f"🔧 تعداد اکانت‌های ثبت‌شده listener: {reg}\n\n"
            f"🔹 وقتی اکانت هدف (خودت) توی هر گروه مشترک پیام بفرسته، "
            f"همه اکانت‌ها به صورت خودکار به پیامت ری اکشن می‌زنن.",
            reply_markup=reaction_menu(), parse_mode='Markdown'
        )
    elif data == "reaction_refresh":
        await query.edit_message_text("🔄 وضعیت ری اکشن بروزرسانی شد.", reply_markup=reaction_menu())
    elif data == "set_reaction_target":
        await query.edit_message_text(
            "👤 **تنظیم اکانت هدف (اکانت خودت)**\n\n"
            "یوزرنیم یا آیدی عددی اکانت خودت رو بفرست:\n"
            "• `@myusername`\n"
            "• `123456789` (آیدی عددی)\n\n"
            "⚠️ اکانت‌های ربات باید حداقل توی یه گروه مشترک با اکانت هدف باشن.",
            parse_mode='Markdown'
        )
        context.user_data['action'] = 'set_reaction_target'
    elif data == "choose_reaction":
        await query.edit_message_text(
            "💗 **انتخاب نوع ری اکشن**\n\n"
            "یکی از ری اکشن‌های زیر رو انتخاب کن:",
            reply_markup=reaction_picker_menu()
        )
    elif data.startswith("pick_reaction_"):
        emoji = data.replace("pick_reaction_", "")
        if emoji in REACTION_PRESETS:
            reaction_config["reaction"] = emoji
            name = REACTION_PRESETS[emoji]
            await query.edit_message_text(
                f"✅ ری اکشن روی {name} تنظیم شد.",
                reply_markup=reaction_menu()
            )
        else:
            await query.edit_message_text("❌ ری اکشن نامعتبر.", reply_markup=reaction_picker_menu())
    elif data == "start_reaction":
        if not reaction_config.get("target_user"):
            return await query.edit_message_text("❌ اول اکانت هدف رو تنظیم کن!", reply_markup=reaction_menu())
        if not config["accounts"]:
            return await query.edit_message_text("❌ هیچ اکانتی در سیستم نیست!", reply_markup=reaction_menu())
        reaction_config["active"] = True
        # ✅ FIX: ثبت listenerها برای همه اکانت‌ها (شامل اکانت‌های جدید)
        asyncio.create_task(setup_reaction_listeners())
        await query.edit_message_text(
            f"🟢 **سیستم ری اکشن فعال شد!**\n\n"
            f"👤 اکانت هدف: `{reaction_config['target_user']}`\n"
            f"💗 ری اکشن: {REACTION_PRESETS.get(reaction_config['reaction'], reaction_config['reaction'])}\n\n"
            f"⏳ در حال ثبت listener روی همه اکانت‌ها...\n"
            f"⚠️ ممکنه چند ثانیه طول بکشه. لاگ‌های سرور رو چک کن.",
            reply_markup=reaction_menu(), parse_mode='Markdown'
        )
    elif data == "stop_reaction":
        reaction_config["active"] = False
        await query.edit_message_text("🔴 **سیستم ری اکشن متوقف شد.**", reply_markup=reaction_menu())
    elif data == "clear_reaction_config":
        reaction_config["active"] = False
        reaction_config["target_user"] = ""
        reaction_config["reaction"] = "❤"
        reaction_config["sent_count"] = 0
        reaction_config["success_count"] = 0
        reaction_config["fail_count"] = 0
        await query.edit_message_text("🗑 تنظیمات ری اکشن پاک شد.", reply_markup=reaction_menu())
    # ========================================================================

    # ================== 🧠 بخش هوش مصنوعی حل کپچا ==================
    elif data == "ai_captcha_menu":
        status = "✅ فعال" if ai_captcha_config.get("enabled") else "❌ غیرفعال"
        solved = ai_captcha_config.get("solved_count", 0)
        failed = ai_captcha_config.get("failed_count", 0)
        reg = len(captcha_phones_registered)
        watch = ai_captcha_config.get("captcha_watch_until")
        watch_txt = "—"
        if watch:
            if isinstance(watch, str):
                try:
                    watch = datetime.fromisoformat(watch)
                except Exception:
                    watch = None
            if watch:
                diff = (watch - datetime.now()).total_seconds()
                if diff > 0:
                    watch_txt = f"{int(diff)} ثانیه دیگر"
                else:
                    watch_txt = "پایان یافته"
        await query.edit_message_text(
            f"🧠 **هوش مصنوعی حل کپچا**\n\n"
            f"📡 وضعیت: {status}\n"
            f"🤖 مدل: {ai_captcha_config.get('model', 'gpt-4o')}\n"
            f"🌐 Base URL: `{ai_captcha_config.get('base_url', '')}`\n"
            f"📊 حل‌شده: {solved} | ناموفق: {failed}\n"
            f"🔧 اکانت‌های نصب‌شده listener: {reg}\n"
            f"⏳ پنجره فعال حل کپچا: {watch_txt}\n\n"
            f"🔹 این سیستم روی همه اکانت‌ها listener نصب می‌کنه و "
            f"وقتی ربات کپچا فرستاد، با هوش مصنوعی حلش می‌کنه.",
            reply_markup=ai_captcha_menu(), parse_mode='Markdown'
        )
    elif data == "toggle_ai_captcha":
        ai_captcha_config["enabled"] = not ai_captcha_config.get("enabled", False)
        if ai_captcha_config["enabled"]:
            # نصب listenerها
            asyncio.create_task(install_captcha_listeners())
            await query.edit_message_text(
                "🟢 **هوش مصنوعی حل کپچا فعال شد!**\n\n"
                "از الان اگه کپچایی از یه ربات بیاد، تلاش می‌شه حلش کنه.\n"
                "⚠️ برای اینکه کار کنه، باید در حین استارت ربات هم فعال باشه.",
                reply_markup=ai_captcha_menu()
            )
        else:
            await query.edit_message_text(
                "🔴 **هوش مصنوعی حل کپچا غیرفعال شد.**",
                reply_markup=ai_captcha_menu()
            )
    elif data == "ai_choose_model":
        await query.edit_message_text(
            "🤖 **انتخاب مدل هوش مصنوعی**\n\n"
            "از بین مدل‌های زیر یکی رو انتخاب کن:",
            reply_markup=ai_model_picker_menu()
        )
    elif data.startswith("pick_ai_model_"):
        mid = data.replace("pick_ai_model_", "")
        if any(m == mid for m, _ in AI_MODEL_PRESETS):
            ai_captcha_config["model"] = mid
            await query.edit_message_text(
                f"✅ مدل روی `{mid}` تنظیم شد.",
                reply_markup=ai_captcha_menu(), parse_mode='Markdown'
            )
        else:
            await query.edit_message_text("❌ مدل نامعتبر.", reply_markup=ai_model_picker_menu())
    elif data == "test_ai_api":
        await query.edit_message_text("🧪 در حال تست اتصال به API... لطفا صبر کن.")
        ok, info = await test_gapgpt_api()
        if ok:
            await query.edit_message_text(
                f"✅ **اتصال به API برقرار است!**\n\n"
                f"پاسخ مدل: `{info}`",
                reply_markup=ai_captcha_menu(), parse_mode='Markdown'
            )
        else:
            await query.edit_message_text(
                f"❌ **اتصال به API برقرار نشد**\n\n"
                f"جزئیات: `{info}`\n\n"
                f"• کلید API رو چک کن\n"
                f"• Base URL رو چک کن\n"
                f"• اینترنت سرور رو چک کن",
                reply_markup=ai_captcha_menu(), parse_mode='Markdown'
            )
    elif data == "reset_ai_stats":
        ai_captcha_config["solved_count"] = 0
        ai_captcha_config["failed_count"] = 0
        await query.edit_message_text("♻️ آمار AI ریست شد.", reply_markup=ai_captcha_menu())
    # ========================================================================

    # ================== بخش اسپم فور اسپم ==================
    elif data == "spam_f4f_menu":
        src = spam_config.get("source_link") or "تنظیم نشده"
        tgt = spam_config.get("target_link") or "تنظیم نشده"
        if spam_config.get("loop_running"):
            status = "🟢 در حال اجرا"
        elif spam_config["active"]:
            status = "🟡 فعال (در انتظار شروع حلقه)"
        else:
            status = "🔴 متوقف"
        await query.edit_message_text(
            f"💥 **سیستم اسپم فور اسپم (Forward Flood)**\n\n"
            f"📥 پیام مبدأ: {src}\n"
            f"🎯 گروه هدف: {tgt}\n"
            f"⚡ سرعت: {spam_config.get('speed', 8)} فور در ثانیه برای هر اکانت\n"
            f"📡 وضعیت موتور: {status}\n\n"
            f"🔹 اکانت‌ها پیام مبدأ (عکس + متن) رو با سرعت بالا فوروارد می‌کنن به گروه هدف.",
            reply_markup=spam_menu(), parse_mode='Markdown'
        )
    elif data == "spam_refresh_status":
        await query.edit_message_text("🔄 وضعیت اسپم فور اسپم بروزرسانی شد.", reply_markup=spam_menu())
    elif data == "set_spam_source":
        await query.edit_message_text(
            "📥 **تنظیم لینک پیام مبدأ**\n\n"
            "لینک پیام مورد نظر رو ارسال کنید:\n"
            "مثال: `https://t.me/username/123`\n"
            "یا برای گروه خصوصی: `https://t.me/c/1234567890/123`",
            parse_mode='Markdown'
        )
        context.user_data['action'] = 'set_spam_source'
    elif data == "set_spam_target":
        await query.edit_message_text(
            "🎯 **تنظیم لینک گروه هدف**\n\n"
            "لینک گروه یا یوزرنیم گروه هدف رو ارسال کنید:\n"
            "• گروه عمومی: `https://t.me/mygroup` یا `@mygroup`\n"
            "• گروه خصوصی (لینک دعوت): `https://t.me/+AbCdEfGhIjK`\n"
            "• گروه خصوصی: `https://t.me/joinchat/AbCdEfGhIjK`\n\n"
            "⚠️ همه اکانت‌ها باید از قبل عضو گروه هدف باشن.",
            parse_mode='Markdown'
        )
        context.user_data['action'] = 'set_spam_target'
    elif data == "set_spam_speed":
        await query.edit_message_text(
            "⚡ **تنظیم سرعت اسپم**\n\n"
            "تعداد فور در ثانیه برای هر اکانت رو وارد کنید (پیش‌فرض: 8):"
        )
        context.user_data['action'] = 'set_spam_speed'
    elif data == "start_spam_f4f":
        if not spam_config.get("source_chat") or not spam_config.get("source_msg_id"):
            return await query.edit_message_text("❌ اول لینک پیام مبدأ رو تنظیم کنید!", reply_markup=spam_menu())
        if not spam_config.get("target_chat"):
            return await query.edit_message_text("❌ اول لینک گروه هدف رو تنظیم کنید!", reply_markup=spam_menu())
        if not config["accounts"]:
            return await query.edit_message_text("❌ هیچ اکانتی در سیستم ثبت نشده!", reply_markup=spam_menu())
        if spam_config.get("loop_running"):
            return await query.edit_message_text("⚠️ اسپم فور اسپم از قبل در حال اجراست! اول متوقفش کنید.", reply_markup=spam_menu())
        # ریست کش entityها برای resolve تازه
        spam_config["source_entity_cache"] = None
        spam_config["target_entity_cache"] = None
        spam_config["active"] = True
        await query.edit_message_text("🚀 **اسپم فور اسپم آغاز شد!**", reply_markup=spam_menu())
        asyncio.create_task(spam_f4f_loop())
    elif data == "stop_spam_f4f":
        spam_config["active"] = False
        spam_config["loop_running"] = False
        await query.edit_message_text("⏹ **اسپم فور اسپم متوقف شد.**", reply_markup=spam_menu())
    elif data == "clear_spam_config":
        spam_config["active"] = False
        spam_config["loop_running"] = False
        spam_config["source_link"] = ""
        spam_config["source_chat"] = None
        spam_config["source_msg_id"] = None
        spam_config["target_link"] = ""
        spam_config["target_chat"] = None
        spam_config["source_entity_cache"] = None
        spam_config["target_entity_cache"] = None
        await query.edit_message_text("🗑 تنظیمات اسپم فور اسپم پاک شد.", reply_markup=spam_menu())
    # =========================================================

    # ================== بخش استارت ربات با لینک رفرال ==================
    elif data == "start_bot_menu":
        link = start_bot_config.get("bot_link") or "تنظیم نشده"
        if start_bot_config.get("running"):
            status = "🟢 در حال اجرا"
        else:
            status = "🔴 متوقف"
        username_txt = start_bot_config.get("bot_username") or "-"
        param_txt = start_bot_config.get("start_param") or "بدون پارامتر"
        ai_txt = "✅ فعال" if ai_captcha_config.get("enabled") else "❌ غیرفعال"
        ai_solved = ai_captcha_config.get("solved_count", 0)
        await query.edit_message_text(
            f"🤖 **استارت ربات با لینک رفرال**\n\n"
            f"🔗 لینک ربات: {link}\n"
            f"👤 یوزرنیم: @{username_txt}\n"
            f"🎯 پارامتر: {param_txt}\n"
            f"⏱ فاصله زمانی بین اکانت‌ها: {start_bot_config['delay']} ثانیه\n"
            f"🧠 هوش مصنوعی کپچا: {ai_txt} | حل‌شده: {ai_solved}\n"
            f"📡 وضعیت: {status}\n\n"
            f"🔹 با همه اکانت‌های فعال، ربات رو استارت می‌زنه (رفرال).",
            reply_markup=start_bot_menu(), parse_mode='Markdown'
        )
    elif data == "refresh_start_bot_status":
        await query.edit_message_text("🔄 وضعیت استارت ربات بروزرسانی شد.", reply_markup=start_bot_menu())
    elif data == "set_start_bot_link":
        await query.edit_message_text(
            "🔗 **تنظیم لینک رفرال ربات**\n\n"
            "لینک ربات رو ارسال کنید:\n"
            "• `https://t.me/MyBot?start=ref123`\n"
            "• `https://t.me/MyBot`\n"
            "• `@MyBot`\n\n"
            "⚠️ اگر پارامتر `start` داشته باشه، خودکار استخراج می‌شه.",
            parse_mode='Markdown'
        )
        context.user_data['action'] = 'set_start_bot_link'
    elif data == "set_start_bot_delay":
        await query.edit_message_text(
            "⏱ **تنظیم فاصله زمانی بین اکانت‌ها**\n\n"
            "فاصله بین استارت هر اکانت رو به ثانیه وارد کنید.\n"
            "مقدار مجاز: از 1 تا 15 ثانیه (پیش‌فرض: 3):"
        )
        context.user_data['action'] = 'set_start_bot_delay'
    elif data == "run_start_bot":
        if not start_bot_config.get("bot_username"):
            return await query.edit_message_text("❌ اول لینک رفرال ربات رو تنظیم کنید!", reply_markup=start_bot_menu())
        if not config["accounts"]:
            return await query.edit_message_text("❌ هیچ اکانتی در سیستم ثبت نشده!", reply_markup=start_bot_menu())
        if start_bot_config.get("running"):
            return await query.edit_message_text("⚠️ استارت ربات از قبل در حال اجراست! اول متوقفش کنید.", reply_markup=start_bot_menu())
        ai_note = "\n🧠 هوش مصنوعی کپچا: ✅ فعال" if ai_captcha_config.get("enabled") else "\n🧠 هوش مصنوعی کپچا: ❌ غیرفعال"
        await query.edit_message_text(
            f"🚀 **استارت ربات آغاز شد!**\n\n"
            f"📊 تعداد اکانت‌ها: {len(config['accounts'])}\n"
            f"⏱ فاصله زمانی: {start_bot_config['delay']} ثانیه{ai_note}",
            reply_markup=start_bot_menu()
        )
        asyncio.create_task(start_bot_loop(context, query.message.chat_id))
    elif data == "stop_start_bot":
        start_bot_config["active"] = False
        await query.edit_message_text("⏹ **استارت ربات متوقف شد.**", reply_markup=start_bot_menu())
    elif data == "clear_start_bot_config":
        start_bot_config["active"] = False
        start_bot_config["running"] = False
        start_bot_config["bot_link"] = ""
        start_bot_config["bot_username"] = ""
        start_bot_config["start_param"] = ""
        ai_captcha_config["captcha_watch_until"] = None
        await query.edit_message_text("🗑 تنظیمات استارت ربات پاک شد.", reply_markup=start_bot_menu())
    # ==================================================================

async def text_handler(update: Update, context: ContextTypes.DEFAULT_TYPE):
    action = context.user_data.get('action')
    text = update.message.text.strip()
    if not check_admin_access(update.effective_user.id): return
    if text.lower() == ".panel": return await user_panel(update, context)
    if not action: return

    if action == 'add_acc':
        success, msg = await login(text)
        if success: context.user_data['phone'], context.user_data['action'] = text, 'verify'
        await update.message.reply_text(msg)
    elif action == 'verify':
        success, msg = await verify(context.user_data.get('phone'), text)
        await update.message.reply_text(msg)
        if success: context.user_data['action'] = None
    elif action == 'bulk_join':
        await update.message.reply_text("🔄 در حال عضویت گروهی تمامی اکانت‌ها...")
        res = await join_all_accounts_to_group(text)
        sc = sum(1 for s, _ in res if s)
        await update.message.reply_text(f"🔗 نتیجه عضویت گروهی:\n• موفق: {sc}\n• ناموفق: {len(res)-sc}")
        context.user_data['action'] = None
    elif action == 'bulk_leave':
        if not config["accounts"]:
            await update.message.reply_text("❌ هیچ اکانتی در سیستم ثبت نشده است.")
            context.user_data['action'] = None
            return
        await update.message.reply_text("🚪 در حال خروج گروهی تمامی اکانت‌ها...")
        res = await leave_all_accounts_from_group(text)
        sc = sum(1 for s, _ in res if s)
        fail = len(res) - sc
        # لیست خطاها (اختیاری)
        err_lines = []
        for s, m in res:
            if not s:
                err_lines.append(m)
        msg = f"🚪 نتیجه خروج گروهی:\n• موفق: {sc}\n• ناموفق: {fail}"
        if err_lines[:5]:
            msg += "\n\n🔸 چند نمونه خطا:\n" + "\n".join(err_lines[:5])
        await update.message.reply_text(msg)
        context.user_data['action'] = None
    elif action == 'add_group':
        if text not in config["groups"]:
            config["groups"].append(text)
            config.setdefault("active_groups", []).append(text)
            save_config(config)
            await update.message.reply_text("🔄 در حال عضویت اکانت‌ها در گروه جدید...")
            await join_all_accounts_to_group(text)
        await update.message.reply_text(f"✅ گروه با موفقیت اضافه شد: {text}")
        context.user_data['action'] = None
    elif action == 'add_target':
        tg = load_targets()
        if text not in tg:
            tg.append(text)
            save_targets(tg)
        await update.message.reply_text(f"✅ هدف جدید (یوزرنیم یا آیدی عددی) با موفقیت اضافه شد.")
        context.user_data['action'] = None
    elif action == 'add_gen_target':
        gt_list = load_general_targets()
        if text not in gt_list:
            gt_list.append(text)
            save_general_targets(gt_list)
        await update.message.reply_text(f"✅ هدف عمومی با موفقیت به لیست ریپ عمومی اضافه شد.")
        context.user_data['action'] = None
    elif action == 'delay':
        config["delay"] = int(text)
        save_config(config)
        context.user_data['action'] = None
        await update.message.reply_text("✅ تاخیر اتکر با موفقیت ثبت شد.")
    elif action == 'set_reply_link_1':
        reply_config["target_link_1"] = text
        parts = text.split("/")
        if len(parts) >= 5:
            reply_config["chat_id_1"] = int(parts[4]) if parts[3] == "c" else parts[3]
            reply_config["target_msg_id_1"] = int(parts[5]) if len(parts) > 5 and parts[5].isdigit() else (int(parts[4]) if parts[4].isdigit() else None)
            reply_config["active_target_1"] = True
            await update.message.reply_text("✅ لینک پیام هدف ۱ با موفقیت تحلیل و ثبت شد.")
            context.user_data['action'] = None
        else:
            await update.message.reply_text("❌ لینک وارد شده نامعتبر است.")
    elif action == 'set_reply_link_2':
        reply_config["target_link_2"] = text
        parts = text.split("/")
        if len(parts) >= 5:
            reply_config["chat_id_2"] = int(parts[4]) if parts[3] == "c" else parts[3]
            reply_config["target_msg_id_2"] = int(parts[5]) if len(parts) > 5 and parts[5].isdigit() else (int(parts[4]) if parts[4].isdigit() else None)
            reply_config["active_target_2"] = True
            await update.message.reply_text("✅ لینک پیام هدف ۲ با موفقیت تحلیل و ثبت شد.")
            context.user_data['action'] = None
        else:
            await update.message.reply_text("❌ لینک وارد شده نامعتبر است.")
    elif action == 'set_reply_delay':
        reply_config["delay"] = int(text)
        context.user_data['action'] = None
        await update.message.reply_text("✅ تاخیر ریپ‌چت ثبت شد.")

    # ================== بخش ری اکشن خودکار ==================
    elif action == 'set_reaction_target':
        tgt = text.strip()
        reaction_config["target_user"] = tgt
        # ریست listener تا دفعه بعد با اکانت جدید راه‌اندازی بشه
        reaction_config["listener_started"] = False
        await update.message.reply_text(
            f"✅ اکانت هدف با موفقیت تنظیم شد:\n`{tgt}`\n\n"
            f"حالا دکمه «شروع ری اکشن» رو بزن.",
            reply_markup=reaction_menu(), parse_mode='Markdown'
        )
        context.user_data['action'] = None
    # =========================================================

    # ================== بخش اسپم فور اسپم ==================
    elif action == 'set_spam_source':
        chat, msg_id = parse_telegram_link(text)
        if not chat or not msg_id:
            await update.message.reply_text("❌ لینک نامعتبر! لطفا از فرمت درست استفاده کنید.\nمثال: https://t.me/username/123")
        else:
            spam_config["source_link"] = text
            spam_config["source_chat"] = chat
            spam_config["source_msg_id"] = msg_id
            spam_config["source_entity_cache"] = None  # ریست کش
            await update.message.reply_text(f"✅ لینک مبدأ تنظیم شد.\nچت: {chat}\nآیدی پیام: {msg_id}", reply_markup=spam_menu())
            context.user_data['action'] = None
    elif action == 'set_spam_target':
        parsed = parse_target_link(text)
        if not parsed:
            await update.message.reply_text("❌ لینک نامعتبر! لطفا از فرمت درست استفاده کنید.\nمثال: https://t.me/mygroup یا https://t.me/+AbCdEfGhIjK")
        elif parsed["type"] == "invite":
            # تبدیل لینک دعوت خصوصی به chat_id واقعی با اولین اکانت فعال
            try:
                phone = None
                for p in config["accounts"]:
                    if config.get("account_status", {}).get(p, True):
                        phone = p
                        break
                if not phone:
                    await update.message.reply_text("❌ برای تبدیل لینک دعوت خصوصی حداقل یک اکانت فعال در سیستم لازم است. اول یک اکانت اضافه کنید.")
                    return
                c = await get_client(phone)
                if not c:
                    await update.message.reply_text("❌ اتصال اکانت برقرار نشد.")
                    return
                res = await c(CheckChatInviteRequest(parsed["value"]))
                chat_obj = getattr(res, "chat", None)
                if chat_obj:
                    chat_id = chat_obj.id
                    spam_config["target_link"] = text
                    spam_config["target_chat"] = chat_id
                    spam_config["target_entity_cache"] = None  # ریست کش
                    title = getattr(chat_obj, "title", "") or ""
                    await update.message.reply_text(
                        f"✅ لینک گروه خصوصی با موفقیت تحلیل شد.\n"
                        f"نام: {title}\n"
                        f"chat_id: {chat_id}",
                        reply_markup=spam_menu()
                    )
                else:
                    await update.message.reply_text("❌ گروه پیدا نشد. مطمئن شو اکانت‌ها قبلا عضو این گروه شدن.")
            except Exception as e:
                await update.message.reply_text(f"❌ خطا در تحلیل لینک دعوت:\n{str(e)[:120]}")
        else:
            spam_config["target_link"] = text
            spam_config["target_chat"] = parsed["value"]
            spam_config["target_entity_cache"] = None  # ریست کش
            await update.message.reply_text(f"✅ لینک گروه هدف تنظیم شد.\nهدف: {parsed['value']}", reply_markup=spam_menu())
            context.user_data['action'] = None
    elif action == 'set_spam_speed':
        try:
            sp = int(text)
            if sp < 1: sp = 1
            if sp > 30: sp = 30
            spam_config["speed"] = sp
            await update.message.reply_text(f"✅ سرعت روی {sp} فور در ثانیه تنظیم شد.", reply_markup=spam_menu())
            context.user_data['action'] = None
        except:
            await update.message.reply_text("❌ عدد نامعتبر!")
    # =========================================================

    # ================== بخش استارت ربات با لینک رفرال ==================
    elif action == 'set_start_bot_link':
        username, param = parse_bot_link(text)
        if not username:
            await update.message.reply_text("❌ لینک نامعتبر! لطفا از فرمت درست استفاده کنید.\nمثال: https://t.me/MyBot?start=ref123")
        else:
            start_bot_config["bot_link"] = text
            start_bot_config["bot_username"] = username
            start_bot_config["start_param"] = param or ""
            await update.message.reply_text(
                f"✅ لینک ربات تنظیم شد.\n"
                f"👤 یوزرنیم: @{username}\n"
                f"🎯 پارامتر: {param or 'بدون پارامتر'}",
                reply_markup=start_bot_menu()
            )
            context.user_data['action'] = None
    elif action == 'set_start_bot_delay':
        try:
            d = int(text)
            if d < 1: d = 1
            if d > 15: d = 15
            start_bot_config["delay"] = d
            await update.message.reply_text(f"✅ فاصله زمانی روی {d} ثانیه تنظیم شد.", reply_markup=start_bot_menu())
            context.user_data['action'] = None
        except:
            await update.message.reply_text("❌ عدد نامعتبر! لطفا یک عدد بین 1 تا 15 وارد کنید.")
    # =========================================================

    elif action.startswith('temp_admin_'):
        res_msg = await add_temp_admin(int(text), int(action.split('_')[2]))
        await update.message.reply_text(res_msg)
        context.user_data['action'] = None
    elif action == 'remove_admin':
        ta = config.get("temp_admins", {})
        if text in ta:
            del ta[text]
            config["temp_admins"] = ta
            save_config(config)
            await update.message.reply_text("✅ دسترسی ادمین مورد نظر لغو شد.")
        else:
            await update.message.reply_text("❌ ادمین مورد نظر یافت نشد.")
        context.user_data['action'] = None
    elif action == 'toggle_account':
        if text in config["account_status"]:
            config["account_status"][text] = not config.get("account_status", {}).get(text, True)
            save_config(config)
            await update.message.reply_text("✅ وضعیت اکانت تغییر یافت.")
        else:
            await update.message.reply_text("❌ شماره اکانت یافت نشد.")
        context.user_data['action'] = None
    elif action == 'remove_account':
        if text in config["accounts"]:
            config["accounts"].remove(text)
            if text in config["account_status"]: del config["account_status"][text]
            save_config(config)
            await update.message.reply_text("✅ اکانت با موفقیت از سیستم حذف شد.")
        else:
            await update.message.reply_text("❌ اکانت یافت نشد.")
        context.user_data['action'] = None

async def document_handler(update: Update, context: ContextTypes.DEFAULT_TYPE):
    if context.user_data.get('action') != 'waiting_file': return
    doc = update.message.document
    file = await context.bot.get_file(doc.file_id)
    content = await file.download_as_bytearray()
    lines = [l.strip() for l in content.decode('utf-8').splitlines() if l.strip()]
    save_msgs(lines)
    global msgs
    msgs = lines
    await update.message.reply_text(f"✅ فایل با موفقیت پردازش شد و {len(lines)} پیام بارگذاری گردید.")
    context.user_data['action'] = None

async def media_handler(update: Update, context: ContextTypes.DEFAULT_TYPE):
    action = context.user_data.get('action')
    try:
        if action == 'add_sticker' and update.message.sticker:
            file = await context.bot.get_file(update.message.sticker.file_id)
            file_path = os.path.join(STICKER_DIR, f"sticker_{random.randint(10000, 99999)}.webp")
            await file.download_to_drive(file_path)
            if file_path not in stickers:
                stickers.append(file_path)
                save_stickers(stickers)
            # اکشن ریست نمی‌شود تا کاربر بتواند استیکرهای بعدی را پشت سر هم ارسال کند
            await update.message.reply_text(f"✅ استیکر دریافت و ذخیره شد. (تعداد کل: {len(stickers)})\nمی‌توانید استیکر بعدی را بفرستید.")

        elif action == 'add_gif' and (update.message.animation or update.message.video or update.message.document):
            media_obj = update.message.animation or update.message.video or update.message.document
            if not media_obj:
                return
            file = await context.bot.get_file(media_obj.file_id)
            file_path = os.path.join(GIF_DIR, f"gif_{random.randint(10000, 99999)}.mp4")
            await file.download_to_drive(file_path)
            if file_path not in gifs:
                gifs.append(file_path)
                save_gifs(gifs)
            # اکشن ریست نمی‌شود تا کاربر بتواند گیف‌های بعدی را پشت سر هم ارسال کند
            await update.message.reply_text(f"✅ گیف/ویدیو دریافت و ذخیره شد. (تعداد کل گیف‌ها: {len(gifs)})\nمی‌توانید گیف بعدی را بفرستید.")
    except Exception as e:
        logger.error(f"خطا در ذخیره رسانه: {e}")
        await update.message.reply_text(f"❌ خطا در پردازش و ذخیره رسانه: {str(e)[:50]}")

def run_bot():
    app = Application.builder().token(BOT_TOKEN).build()
    app.add_handler(CommandHandler("start", start))
    app.add_handler(CommandHandler("panel", user_panel))
    app.add_handler(CallbackQueryHandler(callback_handler))
    app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, text_handler))
    app.add_handler(MessageHandler(filters.Document.ALL & ~filters.Document.Category("application/text"), document_handler))
    app.add_handler(MessageHandler(filters.Sticker.ALL | filters.ANIMATION | filters.VIDEO | filters.Document.ALL, media_handler))
    logger.info("🤖 ربات پیشرفته اتکر و ریپ‌چت v5.1 با موفقیت روشن شد و آماده به کار است!")
    app.run_polling()

if __name__ == "__main__":
    import sys
    try:
        run_bot()
    except KeyboardInterrupt:
        print("\n👋 ربات متوقف شد.")
    except Exception as e:
        print(f"❌ خطای ناشناخته در اجرای ربات: {e}")