import os
import re
import uuid
import shutil
import logging
import threading
import subprocess
import requests
import yt_dlp
import telebot
import html
import time

from telebot.types import InlineKeyboardMarkup, InlineKeyboardButton, BotCommand

# --- Logging Configuration ---
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)

# --- Configuration ---
BOT_TOKEN = "8467715828:AAGAdz6PiVKaeF3Fa__d05F2YlXk6HWncgI"

# 👇👇👇==============================================👇👇👇
# 🔒 تنظیمات اصلی جوین اجباری
# 👇👇👇==============================================👇👇👇
FORCE_JOIN_CHANNEL = "@Tubeify"               
FORCE_JOIN_LINK = "https://t.me/Tubeify"      
# 👆👆👆==============================================👆👆👆

# 👇👇👇==============================================👇👇👇
# 👨‍💻 تنظیمات پنل مدیریت
# 👇👇👇==============================================👇👇👇
ADMIN_IDS = [586324044] 
USERS_FILE = "users.txt"
# 👆👆👆==============================================👆👆👆

bot = telebot.TeleBot(BOT_TOKEN, threaded=True)
os.makedirs('downloads', exist_ok=True)

COOKIES_FILE = "cookies.txt"
MAX_TG_SIZE = 50 * 1024 * 1024
SPOTDL_TIMEOUT = 150

# --- Translations Dictionary ---
TRANSLATIONS = {
    'en': {
        'welcome': "🌟 <b>Welcome to Tubeify!</b>\n\nYour ultimate powerhouse for fetching high-quality media directly to Telegram.\n\n📌 <b>Supported Platforms:</b>\n🔴 YouTube (Videos & Music)\n🟢 Spotify\n🎵 Apple Music\n📸 Instagram\n📱 TikTok\n\n⚡️ <i>Drop any supported URL here to generate your rich preview and quality options...</i>",
        'invalid_url': "❌ Please send a valid URL.",
        'fetching': "{emoji} <b>{platform}</b> link detected!\n<i>Fetching metadata and quality options...</i>",
        'meta_failed': "❌ Failed to fetch metadata from this platform.",
        'cancel': "❌ Cancel",
        'fast_dl': "⚡️ Fast Direct Download",
        'dl_video': "🎬 Download Video",
        'extract_error': "❌ Unable to fetch info. Is the {platform} link private or invalid?",
        'dl_progress': "⏳ Downloading in progress, please wait...",
        'slow_spotify': "⏳ Spotify source is slow — switching to backup engine...",
        'up_audio': "📤 Uploading audio...",
        'up_video': "📤 Uploading video...",
        'size_limit': "❌ File is larger than Telegram's 50MB limit.",
        'format_error': "❌ Error formatting media (source blocked or unavailable).",
        'generic_error': "❌ An error occurred:\n<code>{error}</code>",
        'session_expired': "❌ Session expired. Please send the link again.",
        'start_dl': "Starting download...",
        'cancelled': "Cancelled.",
        'support_text': "📞 <b>Support Center</b>\n\nIf you have any questions, face issues, or have suggestions, feel free to contact our support team.",
        'support_btn': "💬 Contact Support",
        'lang_text': "🌐 <b>Please select your preferred language:</b>",
        'lang_changed': "✅ Language successfully changed to English!",
        'join_required': "🔒 <b>Membership Required</b>\n\nTo use this bot, please join our official channel <b>{channel}</b> first, then tap <b>✅ I've Joined</b>.",
        'join_btn': "📢 Join Channel",
        'join_check_btn': "✅ I've Joined",
        'join_ok': "✅ Thanks for joining! You can use the bot now.",
        'join_not_yet': "❌ You haven't joined yet. Please join the channel and try again."
    },
    'fa': {
        'welcome': "🌟 <b>به تیوبیفای خوش آمدید!</b>\n\nقدرتمندترین ربات برای دریافت مستقیم رسانه با کیفیت بالا در تلگرام.\n\n📌 <b>پلتفرم‌های پشتیبانی شده:</b>\n🔴 یوتیوب\n🟢 اسپاتیفای\n🎵 اپل موزیک\n📸 اینستاگرام\n📱 تیک‌تاک\n\n⚡️ <i>لینک خود را اینجا بفرستید تا کیفیت‌های مختلف برای دانلود آماده شود...</i>",
        'invalid_url': "❌ لطفاً یک لینک معتبر ارسال کنید.",
        'fetching': "{emoji} لینک <b>{platform}</b> شناسایی شد!\n<i>در حال دریافت اطلاعات و کیفیت‌ها...</i>",
        'meta_failed': "❌ دریافت اطلاعات از این پلتفرم با خطا مواجه شد.",
        'cancel': "❌ لغو",
        'fast_dl': "⚡️ دانلود سریع مستقیم",
        'dl_video': "🎬 دانلود ویدیو",
        'extract_error': "❌ دریافت اطلاعات ممکن نیست. آیا لینک {platform} پرایوت (خصوصی) است یا نامعتبر؟",
        'dl_progress': "⏳ در حال دانلود، لطفاً صبور باشید...",
        'slow_spotify': "⏳ سورس اسپاتیفای کند است — در حال تغییر به موتور کمکی...",
        'up_audio': "📤 در حال آپلود فایل صوتی...",
        'up_video': "📤 در حال آپلود ویدیو...",
        'size_limit': "❌ حجم فایل بیشتر از محدودیت ۵۰ مگابایتی تلگرام است.",
        'format_error': "❌ خطا در فرمت رسانه (منبع مسدود یا ناموجود است).",
        'generic_error': "❌ خطایی رخ داد:\n<code>{error}</code>",
        'session_expired': "❌ نشست منقضی شده است. لطفاً لینک را دوباره ارسال کنید.",
        'start_dl': "شروع دانلود...",
        'cancelled': "لغو شد.",
        'support_text': "📞 <b>مرکز پشتیبانی</b>\n\nاگر سوالی دارید، با مشکلی مواجه شده‌اید یا پیشنهادی دارید، با تیم پشتیبانی ما در ارتباط باشید.",
        'support_btn': "💬 ارتباط با پشتیبانی",
        'lang_text': "🌐 لطفاً زبان خود را انتخاب کنید:",
        'lang_changed': "✅ زبان با موفقیت به فارسی تغییر یافت!",
        'join_required': "🔒 <b>عضویت اجباری</b>\n\nبرای استفاده از ربات، لطفاً ابتدا در کانال رسمی ما (<b>{channel}</b>) عضو شوید، سپس روی دکمه <b>✅ عضو شدم</b> کلیک کنید.",
        'join_btn': "📢 عضویت در کانال",
        'join_check_btn': "✅ عضو شدم",
        'join_ok': "✅ ممنون از عضویتت! حالا می‌تونی از ربات استفاده کنی.",
        'join_not_yet': "❌ هنوز عضو نشدی. لطفاً اول در کانال عضو شو و دوباره تلاش کن."
    },
    'ar': {
        'welcome': "🌟 <b>مرحبًا بك في Tubeify!</b>\n\nأقوى أداة لتحميل الوسائط بجودة عالية مباشرة إلى تيليجرام.",
        'invalid_url': "❌ يرجى إرسال رابط صحيح.",
        'fetching': "{emoji} تم اكتشاف رابط <b>{platform}</b>!\n<i>جاري جلب المعلومات والخيارات...</i>",
        'meta_failed': "❌ فشل في جلب البيانات من هذه المنصة.",
        'cancel': "❌ إلغاء",
        'fast_dl': "⚡️ تحميل سريع مباشر",
        'dl_video': "🎬 تحميل الفيديو",
        'extract_error': "❌ تعذر جلب المعلومات. هل الرابط خاص أو غير صالح؟",
        'dl_progress': "⏳ جاري التحميل، يرجى الانتظار...",
        'slow_spotify': "⏳ المصدر بطيء — جاري التبديل للمحرك البديل...",
        'up_audio': "📤 جاري رفع الصوت...",
        'up_video': "📤 جاري رفع الفيديو...",
        'size_limit': "❌ حجم الملف أكبر من الحد المسموح في تيليجرام (50MB).",
        'format_error': "❌ خطأ في تنسيق الوسائط.",
        'generic_error': "❌ حدث خطأ:\n<code>{error}</code>",
        'session_expired': "❌ انتهت الجلسة. يرجى إرسال الرابط مرة أخرى.",
        'start_dl': "بدء التحميل.",
        'cancelled': "تم الإلغاء.",
        'support_text': "📞 <b>مركز الدعم</b>\n\nإذا كان لديك أي أسئلة أو واجهت مشكلة، تواصل مع فريقنا.",
        'support_btn': "💬 تواصل مع الدعم",
        'lang_text': "🌐 الرجاء اختيار لغتك المفضلة:",
        'lang_changed': "✅ تم تغيير اللغة بنجاح إلى العربية!",
        'join_required': "🔒 <b>الاشتراك مطلوب</b>\n\nلاستخدام هذا البوت، يرجى الاشتراك في قناتنا <b>{channel}</b> أولاً ثم اضغط على <b>✅ لقد اشتركت</b>.",
        'join_btn': "📢 الاشتراك في القناة",
        'join_check_btn': "✅ لقد اشتركت",
        'join_ok': "✅ شكرًا لاشتراكك! يمكنك استخدام البوت الآن.",
        'join_not_yet': "❌ لم تشترك بعد. يرجى الاشتراك في القناة والمحاولة مرة أخرى."
    },
    'zh': {
        'welcome': "🌟 <b>欢迎来到 Tubeify!</b>\n\n将高品质媒体直接提取到 Telegram 的终极工具。",
        'invalid_url': "❌ 请发送有效的链接。",
        'fetching': "{emoji} 检测到 <b>{platform}</b> 链接！\n<i>正在获取元数据和选项...</i>",
        'meta_failed': "❌ 无法从该平台获取元数据。",
        'cancel': "❌ 取消",
        'fast_dl': "⚡️ 快速直接下载",
        'dl_video': "🎬 下载视频",
        'extract_error': "❌ 无法获取信息。链接是否为私有或无效？",
        'dl_progress': "⏳ 下载中，请稍候...",
        'slow_spotify': "⏳ Spotify 来源较慢 — 切换到备用引擎...",
        'up_audio': "📤 正在上传音频...",
        'up_video': "📤 正在上传视频...",
        'size_limit': "❌ 文件大于 Telegram 的 50MB 限制。",
        'format_error': "❌ 格式化媒体时出错。",
        'generic_error': "❌ 发生错误:\n<code>{error}</code>",
        'session_expired': "❌ 会话已过期。请重新发送链接。",
        'start_dl': "开始下载...",
        'cancelled': "已取消。",
        'support_text': "📞 <b>支持中心</b>\n\n如果您有任何问题或建议，请随时联系我们的支持团队。",
        'support_btn': "💬 联系支持",
        'lang_text': "🌐 请选择您的首选语言:",
        'lang_changed': "✅ 语言修改成功！",
        'join_required': "🔒 <b>需要加入频道</b>\n\n使用本机器人前，请先加入我们的频道 <b>{channel}</b>，然后点击 <b>✅ 我已加入</b>。",
        'join_btn': "📢 加入频道",
        'join_check_btn': "✅ 我已加入",
        'join_ok': "✅ 感谢加入！现在可以使用机器人了。",
        'join_not_yet': "❌ 您还没有加入。请加入频道后重试。"
    },
    'ja': {
        'welcome': "🌟 <b>Tubeifyへようこそ！</b>\n\n高品質のメディアをTelegramに直接取得するための究極のツール。",
        'invalid_url': "❌ 有効なURLを送信してください。",
        'fetching': "{emoji} <b>{platform}</b> のリンクを検出しました！\n<i>メタデータとオプションを取得中...</i>",
        'meta_failed': "❌ このプラットフォームからのメタデータの取得に失敗しました。",
        'cancel': "❌ キャンセル",
        'fast_dl': "⚡️ 高速直接ダウンロード",
        'dl_video': "🎬 動画をダウンロード",
        'extract_error': "❌ 情報を取得できません。リンクが非公開または無効ですか？",
        'dl_progress': "⏳ ダウンロード中です。お待ちください...",
        'slow_spotify': "⏳ Spotifyのソースが遅いです — バックアップエンジンに切り替えます...",
        'up_audio': "📤 音声をアップロード中...",
        'up_video': "📤 動画をアップロード中...",
        'size_limit': "❌ ファイルがTelegramの50MB制限を超えています。",
        'format_error': "❌ メディアのフォーマットエラーです。",
        'generic_error': "❌ エラーが発生しました:\n<code>{error}</code>",
        'session_expired': "❌ セッションの有効期限が切れました。リンクを再送信してください。",
        'start_dl': "ダウンロードを開始します...",
        'cancelled': "キャンセルされました。",
        'support_text': "📞 <b>サポートセンター</b>\n\nご質問や問題がある場合は、サポートチームにお問い合わせください。",
        'support_btn': "💬 サポートに連絡",
        'lang_text': "🌐 言語を選択してください:",
        'lang_changed': "✅ 言語が正常に変更されました！",
        'join_required': "🔒 <b>チャンネル参加が必要です</b>\n\nこのボットを使用するには、まずチャンネル <b>{channel}</b> に参加し、<b>✅ 参加しました</b> をタップしてください。",
        'join_btn': "📢 チャンネルに参加",
        'join_check_btn': "✅ 参加しました",
        'join_ok': "✅ ご参加ありがとうございます！ボットを使用できます。",
        'join_not_yet': "❌ まだ参加していません。チャンネルに参加してからもう一度お試しください。"
    },
    'ru': {
        'welcome': "🌟 <b>Добро пожаловать в Tubeify!</b>\n\nВаш лучший бот для загрузки медиа высокого качества прямо в Telegram.",
        'invalid_url': "❌ Пожалуйста, отправьте действительный URL.",
        'fetching': "{emoji} Обнаружена ссылка <b>{platform}</b>!\n<i>Получение метаданных и параметров...</i>",
        'meta_failed': "❌ Не удалось получить метаданные с этой платформы.",
        'cancel': "❌ Отмена",
        'fast_dl': "⚡️ Быстрая прямая загрузка",
        'dl_video': "🎬 Скачать видео",
        'extract_error': "❌ Не удалось получить информацию. Ссылка приватная или недействительная?",
        'dl_progress': "⏳ Идет загрузка, пожалуйста, подождите...",
        'slow_spotify': "⏳ Источник Spotify работает медленно — переключение на резервный механизм...",
        'up_audio': "📤 Загрузка аудио...",
        'up_video': "📤 Загрузка видео...",
        'size_limit': "❌ Файл превышает лимит Telegram в 50 МБ.",
        'format_error': "❌ Ошибка форматирования медиа.",
        'generic_error': "❌ Произошла ошибка:\n<code>{error}</code>",
        'session_expired': "❌ Сессия истекла. Пожалуйста, отправьте ссылку снова.",
        'start_dl': "Начало загрузки...",
        'cancelled': "Отменено.",
        'support_text': "📞 <b>Центр поддержки</b>\n\nЕсли у вас есть вопросы или возникли проблемы, свяжитесь с нами.",
        'support_btn': "💬 Связаться с поддержкой",
        'lang_text': "🌐 Пожалуйста, выберите предпочитаемый язык:",
        'lang_changed': "✅ Язык успешно изменен!",
        'join_required': "🔒 <b>Требуется подписка</b>\n\nЧтобы использовать бота, сначала подпишитесь на наш канал <b>{channel}</b>, затем нажмите <b>✅ Я подписался</b>.",
        'join_btn': "📢 Подписаться на канал",
        'join_check_btn': "✅ Я подписался",
        'join_ok': "✅ Спасибо за подписку! Теперь можно пользоваться ботом.",
        'join_not_yet': "❌ Вы ещё не подписались. Подпишитесь на канал и попробуйте снова."
    },
    'de': {
        'welcome': "🌟 <b>Willkommen bei Tubeify!</b>\n\nDein ultimatives Tool, um hochwertige Medien direkt zu Telegram zu holen.",
        'invalid_url': "❌ Bitte sende eine gültige URL.",
        'fetching': "{emoji} <b>{platform}</b>-Link erkannt!\n<i>Metadaten und Qualitätsoptionen werden abgerufen...</i>",
        'meta_failed': "❌ Fehler beim Abrufen der Metadaten von dieser Plattform.",
        'cancel': "❌ Abbrechen",
        'fast_dl': "⚡️ Schneller Direkt-Download",
        'dl_video': "🎬 Video herunterladen",
        'extract_error': "❌ Informationen können nicht abgerufen werden. Ist der Link privat oder ungültig?",
        'dl_progress': "⏳ Download läuft, bitte warten...",
        'slow_spotify': "⏳ Spotify-Quelle ist langsam — wechsle zur Backup-Engine...",
        'up_audio': "📤 Lade Audio hoch...",
        'up_video': "📤 Lade Video hoch...",
        'size_limit': "❌ Die Datei ist größer als das 50MB-Limit von Telegram.",
        'format_error': "❌ Fehler beim Formatieren der Medien.",
        'generic_error': "❌ Ein Fehler ist aufgetreten:\n<code>{error}</code>",
        'session_expired': "❌ Sitzung abgelaufen. Bitte sende den Link erneut.",
        'start_dl': "Download wird gestartet...",
        'cancelled': "Abgebrochen.",
        'support_text': "📞 <b>Support-Center</b>\n\nWenn du Fragen hast oder auf Probleme stößt, kontaktiere unser Support-Team.",
        'support_btn': "💬 Support kontaktieren",
        'lang_text': "🌐 Bitte wähle deine bevorzugte Sprache:",
        'lang_changed': "✅ Sprache erfolgreich geändert!",
        'join_required': "🔒 <b>Mitgliedschaft erforderlich</b>\n\nUm diesen Bot zu nutzen, tritt bitte zuerst unserem Kanal <b>{channel}</b> bei und tippe dann auf <b>✅ Ich bin beigetreten</b>.",
        'join_btn': "📢 Kanal beitreten",
        'join_check_btn': "✅ Ich bin beigetreten",
        'join_ok': "✅ Danke für den Beitritt! Du kannst den Bot jetzt nutzen.",
        'join_not_yet': "❌ Du bist noch nicht beigetreten. Bitte tritt dem Kanal bei und versuche es erneut."
    },
    'pt': {
        'welcome': "🌟 <b>Bem-vindo ao Tubeify!</b>\n\nA ferramenta definitiva para baixar mídia de alta qualidade diretamente para o Telegram.",
        'invalid_url': "❌ Por favor, envie uma URL válida.",
        'fetching': "{emoji} Link do <b>{platform}</b> detectado!\n<i>Buscando metadados e opções...</i>",
        'meta_failed': "❌ Falha ao buscar metadados desta plataforma.",
        'cancel': "❌ Cancelar",
        'fast_dl': "⚡️ Download Direto Rápido",
        'dl_video': "🎬 Baixar Vídeo",
        'extract_error': "❌ Não foi possível buscar informações. O link é privado ou inválido?",
        'dl_progress': "⏳ Download em andamento, aguarde...",
        'slow_spotify': "⏳ A fonte do Spotify está lenta — mudando para mecanismo de backup...",
        'up_audio': "📤 Enviando áudio...",
        'up_video': "📤 Enviando vídeo...",
        'size_limit': "❌ O arquivo é maior que o limite de 50MB do Telegram.",
        'format_error': "❌ Erro ao formatar a mídia.",
        'generic_error': "❌ Ocorreu um erro:\n<code>{error}</code>",
        'session_expired': "❌ Sessão expirada. Por favor, envie o link novamente.",
        'start_dl': "Iniciando download...",
        'cancelled': "Cancelado.",
        'support_text': "📞 <b>Centro de Suporte</b>\n\nSe tiver dúvidas ou encontrar problemas, entre em contato com nossa equipe de suporte.",
        'support_btn': "💬 Contatar Suporte",
        'lang_text': "🌐 Por favor, selecione seu idioma preferido:",
        'lang_changed': "✅ Idioma alterado com sucesso!",
        'join_required': "🔒 <b>Inscrição obrigatória</b>\n\nPara usar este bot, entre no nosso canal <b>{channel}</b> primeiro e depois toque em <b>✅ Já entrei</b>.",
        'join_btn': "📢 Entrar no canal",
        'join_check_btn': "✅ Já entrei",
        'join_ok': "✅ Obrigado por entrar! Agora você pode usar o bot.",
        'join_not_yet': "❌ Você ainda não entrou. Entre no canal e tente novamente."
    },
    'fr': {
        'welcome': "🌟 <b>Bienvenue sur Tubeify !</b>\n\nL'outil ultime pour télécharger des médias de haute qualité directement sur Telegram.",
        'invalid_url': "❌ Veuillez envoyer une URL valide.",
        'fetching': "{emoji} Lien <b>{platform}</b> détecté !\n<i>Récupération des métadonnées...</i>",
        'meta_failed': "❌ Échec de la récupération des métadonnées de cette plateforme.",
        'cancel': "❌ Annuler",
        'fast_dl': "⚡️ Téléchargement direct rapide",
        'dl_video': "🎬 Télécharger la vidéo",
        'extract_error': "❌ Impossible de récupérer les informations. Le lien est-il privé ou invalide ?",
        'dl_progress': "⏳ Téléchargement en cours, veuillez patienter...",
        'slow_spotify': "⏳ La source Spotify est lente — passage au moteur de secours...",
        'up_audio': "📤 Téléchargement de l'audio en cours...",
        'up_video': "📤 Téléchargement de la vidéo en cours...",
        'size_limit': "❌ Le fichier dépasse la limite de 50 Mo de Telegram.",
        'format_error': "❌ Erreur de formatage du média.",
        'generic_error': "❌ Une erreur s'est produite :\n<code>{error}</code>",
        'session_expired': "❌ Session expirée. Veuillez renvoyer le lien.",
        'start_dl': "Démarrage du téléchargement...",
        'cancelled': "Annulé.",
        'support_text': "📞 <b>Centre d'assistance</b>\n\nSi vous avez des questions ou des problèmes, n'hésitez pas à nous contacter.",
        'support_btn': "💬 Contacter l'assistance",
        'lang_text': "🌐 Veuillez sélectionner votre langue préférée :",
        'lang_changed': "✅ Langue modifiée avec succès !",
        'join_required': "🔒 <b>Adhésion requise</b>\n\nPour utiliser ce bot, rejoignez d'abord notre canal <b>{channel}</b>, puis appuyez sur <b>✅ J'ai rejoint</b>.",
        'join_btn': "📢 Rejoindre le canal",
        'join_check_btn': "✅ J'ai rejoint",
        'join_ok': "✅ Merci d'avoir rejoint ! Vous pouvez utiliser le bot maintenant.",
        'join_not_yet': "❌ Vous n'avez pas encore rejoint. Rejoignez le canal et réessayez."
    },
    'hi': {
        'welcome': "🌟 <b>Tubeify में आपका स्वागत है!</b>\n\nटेलीग्राम पर सीधे उच्च-गुणवत्ता वाले मीडिया प्राप्त करने के लिए आपका अंतिम टूल।",
        'invalid_url': "❌ कृपया एक मान्य लिंक भेजें।",
        'fetching': "{emoji} <b>{platform}</b> लिंक का पता चला!\n<i>डेटा और विकल्प प्राप्त कर रहा है...</i>",
        'meta_failed': "❌ इस प्लेटफ़ॉर्म से डेटा प्राप्त करने में विफल।",
        'cancel': "❌ रद्द करें",
        'fast_dl': "⚡️ तेज़ डायरेक्ट डाउनलोड",
        'dl_video': "🎬 वीडियो डाउनलोड करें",
        'extract_error': "❌ जानकारी प्राप्त करने में असमर्थ। क्या लिंक निजी या अमान्य है?",
        'dl_progress': "⏳ डाउनलोड प्रगति पर है, कृपया प्रतीक्षा करें...",
        'slow_spotify': "⏳ Spotify स्रोत धीमा है — बैकअप इंजन पर स्विच कर रहा है...",
        'up_audio': "📤 ऑडियो अपलोड किया जा रहा है...",
        'up_video': "📤 वीडियो अपलोड किया जा रहा है...",
        'size_limit': "❌ फ़ाइल टेलीग्राम की 50MB सीमा से बड़ी है।",
        'format_error': "❌ मीडिया फ़ॉर्मेटिंग त्रुटि।",
        'generic_error': "❌ एक त्रुटि हुई:\n<code>{error}</code>",
        'session_expired': "❌ सत्र समाप्त हो गया। कृपया लिंक दोबारा भेजें।",
        'start_dl': "डाउनलोड शुरू हो रहा है...",
        'cancelled': "रद्द कर दिया गया।",
        'support_text': "📞 <b>सहायता केंद्र</b>\n\nयदि आपके कोई प्रश्न हैं या कोई समस्या आती है, तो हमारी सहायता टीम से संपर्क करें।",
        'support_btn': "💬 सहायता से संपर्क करें",
        'lang_text': "🌐 कृपया अपनी पसंदीदा भाषा चुनें:",
        'lang_changed': "✅ भाषा सफलतापूर्वक बदल दी गई!",
        'join_required': "🔒 <b>सदस्यता आवश्यक है</b>\n\nइस बॉट का उपयोग करने के लिए, पहले हमारे चैनल <b>{channel}</b> से जुड़ें, फिर <b>✅ मैं जुड़ गया</b> पर टैप करें।",
        'join_btn': "📢 चैनल से जुड़ें",
        'join_check_btn': "✅ मैं जुड़ गया",
        'join_ok': "✅ जुड़ने के लिए धन्यवाद! अब आप बॉट का उपयोग कर सकते हैं।",
        'join_not_yet': "❌ आप अभी तक नहीं जुड़े हैं। कृपया चैनल से जुड़ें और पुनः प्रयास करें."
    }
}
# 👆👆👆 ============================================== 👆👆👆

USER_LANG = {}

def get_text(chat_id, key, **kwargs):
    lang = USER_LANG.get(chat_id, 'en')
    text = TRANSLATIONS.get(lang, TRANSLATIONS['en']).get(key, TRANSLATIONS['en'].get(key, ''))
    if kwargs:
        return text.format(**kwargs)
    return text

# --- Track Users Function ---
def track_user(user_id):
    """ذخیره آیدی کاربر برای پنل آمار و پیام همگانی"""
    try:
        user_id_str = str(user_id)
        if not os.path.exists(USERS_FILE):
            with open(USERS_FILE, "w") as f:
                pass
        with open(USERS_FILE, "r") as f:
            users = f.read().splitlines()
        if user_id_str not in users:
            with open(USERS_FILE, "a") as f:
                f.write(user_id_str + "\n")
    except Exception as e:
        logger.error(f"Error tracking user: {e}")

# --- Force Join Helpers (STRICT MODE) ---
def is_user_member(user_id):
    if not FORCE_JOIN_CHANNEL:
        return True
    try:
        member = bot.get_chat_member(FORCE_JOIN_CHANNEL, user_id)
        if member.status in ['member', 'administrator', 'creator']:
            return True
        else:
            return False
    except Exception as e:
        logger.error(f"Force-join check failed for user {user_id}: {e}")
        return False

def send_join_prompt(chat_id):
    markup = InlineKeyboardMarkup()
    markup.add(InlineKeyboardButton(get_text(chat_id, 'join_btn'), url=FORCE_JOIN_LINK))
    markup.add(InlineKeyboardButton(get_text(chat_id, 'join_check_btn'), callback_data="check_join"))
    bot.send_message(chat_id, get_text(chat_id, 'join_required', channel=FORCE_JOIN_CHANNEL),
                     parse_mode="HTML", reply_markup=markup)

def ensure_member(message):
    user_id = message.from_user.id if message.from_user else message.chat.id
    if is_user_member(user_id):
        return True
    send_join_prompt(message.chat.id)
    return False

def setup_commands():
    commands = [
        BotCommand("start", "Start the bot"),
        BotCommand("language", "Change language"),
        BotCommand("support", "Contact support")
    ]
    try:
        bot.set_my_commands(commands)
    except Exception as e:
        logger.error(f"Failed to set bot commands: {e}")

SESSION_DATA = {}

def youtube_bypass_opts():
    opts = {
        'source_address': '0.0.0.0',
        'extractor_args': {'youtube': {'player_client': ['android', 'ios', 'web']}},
        'retries': 3,
        'socket_timeout': 20,
        'geo_bypass': True,
        'nocheckcertificate': True,
        'noplaylist': True,
    }
    if os.path.exists(COOKIES_FILE):
        opts['cookiefile'] = COOKIES_FILE
    return opts

def format_number(num):
    if not num:
        return "N/A"
    try:
        num = int(num)
        if num >= 1_000_000:
            return f"{num / 1_000_000:.1f}M"
        elif num >= 1_000:
            return f"{num / 1_000:.1f}K"
        return str(num)
    except Exception:
        return "N/A"

def safe_edit(chat_id, message_id, text, has_photo, markup=None):
    try:
        if has_photo:
            bot.edit_message_caption(text, chat_id=chat_id, message_id=message_id,
                                     parse_mode="HTML", reply_markup=markup)
        else:
            bot.edit_message_text(text, chat_id, message_id,
                                  parse_mode="HTML", reply_markup=markup)
    except Exception as e:
        logger.warning(f"safe_edit skipped: {e}")

def get_spotify_meta(url):
    try:
        cover = None
        try:
            oembed_res = requests.get("https://open.spotify.com/oembed",
                                       params={'url': url}, timeout=8)
            if oembed_res.status_code == 200:
                cover = oembed_res.json().get('thumbnail_url')
        except Exception as e:
            logger.error(f"Spotify oembed error: {e}")

        headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'}
        page_res = requests.get(url, headers=headers, timeout=8)
        if page_res.status_code != 200:
            return None

        title_match = re.search(r'<title>(.*?)</title>', page_res.text,
                                re.IGNORECASE | re.DOTALL)
        if not title_match:
            return None

        raw_title = html.unescape(title_match.group(1)).replace(" | Spotify", "").strip()

        if " - song and lyrics by " in raw_title:
            title, artist = raw_title.split(" - song and lyrics by ", 1)
        elif " - song by " in raw_title:
            title, artist = raw_title.split(" - song by ", 1)
        elif " - " in raw_title:
            artist, title = raw_title.split(" - ", 1)
        else:
            title, artist = raw_title, "Unknown Artist"

        return {'title': title.strip(), 'artist': artist.strip(), 'cover': cover}
    except Exception as e:
        logger.error(f"Spotify meta error: {e}")
    return None

def get_apple_music_meta(url):
    try:
        res = requests.get(url, headers={'User-Agent': 'Mozilla/5.0'}, timeout=8)
        if res.status_code == 200:
            title_match = re.search(r'<meta property="og:title" content="(.*?)"', res.text)
            cover_match = re.search(r'<meta property="og:image" content="(.*?)"', res.text)
            title_full = html.unescape(title_match.group(1)) if title_match else "Apple Music Track"

            parts = title_full.split(" - Single by ") if " - Single by " in title_full else title_full.split(" by ")
            title = parts[0]
            artist = parts[1] if len(parts) > 1 else "Unknown Artist"

            return {
                'title': title.strip(),
                'artist': artist.strip(),
                'cover': cover_match.group(1) if cover_match else None
            }
    except Exception as e:
        logger.error(f"Apple Music meta error: {e}")
    return None

def download_cover(url, filename):
    try:
        res = requests.get(url, timeout=10)
        path = f"downloads/{filename}.jpg"
        with open(path, 'wb') as f:
            f.write(res.content)
        return path
    except Exception:
        return None

def get_platform_info(url):
    if "spotify.com" in url:
        return "Spotify", "🟢"
    if "music.apple.com" in url:
        return "AppleMusic", "🍎"
    if "youtube.com" in url or "youtu.be" in url:
        return "YouTube", "🔴"
    if "instagram.com" in url:
        return "Instagram", "📸"
    if "tiktok.com" in url:
        return "TikTok", "🎵"
    if "soundcloud.com" in url:
        return "SoundCloud", "☁️"
    return "Media", "🔗"

def find_produced_file(session_id, exts=("mp3", "m4a", "opus", "webm", "mp4", "mkv")):
    for ext in exts:
        p = f"downloads/{session_id}.{ext}"
        if os.path.isfile(p):
            return p
    for fname in sorted(os.listdir("downloads")):
        full = f"downloads/{fname}"
        if fname.startswith(session_id) and os.path.isfile(full) and not fname.endswith(".jpg"):
            return full
    return None

# --- Progress Bar Hook Generator ---
def create_progress_hook(chat_id, message_id, has_photo):
    """یک تابع می‌سازه که اطلاعات لایو رو به تلگرام می‌فرسته"""
    last_edit_time = [0]
    
    def hook(d):
        if d['status'] == 'downloading':
            current_time = time.time()
            if current_time - last_edit_time[0] > 2.5:
                percent_str = re.sub(r'\x1b[^m]*m', '', d.get('_percent_str', '0%')).strip()
                speed_str = re.sub(r'\x1b[^m]*m', '', d.get('_speed_str', '0KiB/s')).strip()
                eta_str = re.sub(r'\x1b[^m]*m', '', d.get('_eta_str', '00:00')).strip()
                
                try:
                    clean_percent = float(percent_str.replace('%', ''))
                except:
                    clean_percent = 0.0
                    
                filled = int(clean_percent / 10)
                bar = '█' * filled + '░' * (10 - filled)
                
                text = (
                    f"⏳ <b>در حال دانلود از سرور...</b>\n\n"
                    f"📊 <code>[{bar}] {percent_str}</code>\n"
                    f"🚀 سرعت: <code>{speed_str}</code>\n"
                    f"⏱ زمان باقیمانده: <code>{eta_str}</code>"
                )
                safe_edit(chat_id, message_id, text, has_photo)
                last_edit_time[0] = current_time
    return hook

# --- Admin Panel Message Handler ---
@bot.message_handler(commands=['panel'])
def admin_panel(message):
    if message.from_user.id not in ADMIN_IDS:
        return
    markup = InlineKeyboardMarkup()
    markup.add(InlineKeyboardButton("📊 آمار کل کاربران", callback_data="admin_stats"))
    markup.add(InlineKeyboardButton("📣 ارسال پیام همگانی", callback_data="admin_broadcast"))
    bot.send_message(message.chat.id, "👨‍💻 <b>پنل مدیریت تیوبیفای</b>\n\nلطفاً یک گزینه را انتخاب کنید:", 
                     parse_mode="HTML", reply_markup=markup)

def process_broadcast(message):
    if message.text == "لغو":
        bot.send_message(message.chat.id, "❌ ارسال پیام همگانی لغو شد.")
        return
    
    if os.path.exists(USERS_FILE):
        with open(USERS_FILE, "r") as f:
            users = f.read().splitlines()
    else:
        users = []
        
    bot.send_message(message.chat.id, f"⏳ در حال ارسال پیام به {len(users)} کاربر...\nلطفاً صبور باشید.")
    
    # دکمه‌های شیشه‌ای برای چسباندن خودکار زیر پیام همگانی شما
    markup = InlineKeyboardMarkup()
    bot_info = bot.get_me()
    markup.add(InlineKeyboardButton("🤖 ورود به ربات", url=f"https://t.me/{bot_info.username}"))
    markup.add(InlineKeyboardButton("📢 عضویت در کانال", url=FORCE_JOIN_LINK))
    
    success = 0
    for user_id in users:
        try:
            bot.copy_message(user_id, message.chat.id, message.message_id, reply_markup=markup)
            success += 1
        except Exception:
            pass
            
    bot.send_message(message.chat.id, f"✅ پیام شما همراه با دکمه شیشه‌ای با موفقیت به {success} کاربر ارسال شد.")

# --- Message Handlers ---
@bot.message_handler(commands=['start'])
def send_welcome(message):
    track_user(message.from_user.id) 
    if not ensure_member(message):
        return
    
    # چک کردن اینکه آیا کاربر از طریق مینی‌اپ لینک فرستاده یا خیر
    text = message.text.strip()
    if " " in text:
        param = text.split(" ", 1)[1]
        if param.startswith("dl_"):
            # استخراج لینک اصلی از پارامتر
            actual_url = urllib.parse.unquote(param[3:])
            # شبیه‌سازی ارسال لینک توسط کاربر تا مستقیم برود سراغ دانلود
            message.text = actual_url
            handle_link(message)
            return

    bot.reply_to(message, get_text(message.chat.id, 'welcome'), parse_mode="HTML")

@bot.message_handler(commands=['support'])
def send_support(message):
    chat_id = message.chat.id
    markup = InlineKeyboardMarkup()
    markup.add(InlineKeyboardButton(get_text(chat_id, 'support_btn'), url="https://t.me/ImEMaD"))
    bot.reply_to(message, get_text(chat_id, 'support_text'), parse_mode="HTML", reply_markup=markup)

@bot.message_handler(commands=['language'])
def send_language(message):
    chat_id = message.chat.id
    markup = InlineKeyboardMarkup(row_width=2)
    markup.add(
        InlineKeyboardButton("🇬🇧 English", callback_data="lang_en"),
        InlineKeyboardButton("🇮🇷 فارسی", callback_data="lang_fa"),
        InlineKeyboardButton("🇸🇦 العربية", callback_data="lang_ar"),
        InlineKeyboardButton("🇨🇳 中文", callback_data="lang_zh"),
        InlineKeyboardButton("🇯🇵 日本語", callback_data="lang_ja"),
        InlineKeyboardButton("🇷🇺 Русский", callback_data="lang_ru"),
        InlineKeyboardButton("🇩🇪 Deutsch", callback_data="lang_de"),
        InlineKeyboardButton("🇵🇹 Português", callback_data="lang_pt"),
        InlineKeyboardButton("🇫🇷 Français", callback_data="lang_fr"),
        InlineKeyboardButton("🇮🇳 हिन्दी", callback_data="lang_hi")
    )
    bot.reply_to(message, get_text(chat_id, 'lang_text'), parse_mode="HTML", reply_markup=markup)

@bot.message_handler(func=lambda message: True)
def handle_link(message):
    track_user(message.from_user.id) 
    if not ensure_member(message):
        return
    url = message.text.strip()
    
    # قیچی کردن پلی‌لیست از انتهای لینک‌های یوتیوب
    if "youtube.com" in url or "youtu.be" in url:
        url = url.split('&list=')[0].split('?list=')[0].split('&index=')[0]

    chat_id = message.chat.id

    if not url.startswith("http"):
        bot.reply_to(message, get_text(chat_id, 'invalid_url'))
        return

    platform_name, platform_emoji = get_platform_info(url)
    processing_text = get_text(chat_id, 'fetching', emoji=platform_emoji, platform=platform_name)

    msg = bot.send_message(chat_id, processing_text, parse_mode="HTML")

    session_id = str(uuid.uuid4())[:8]
    SESSION_DATA[session_id] = {'url': url, 'type': 'video', 'platform': platform_name}

    if platform_name in ["Spotify", "AppleMusic"]:
        SESSION_DATA[session_id]['type'] = 'music_external'
        meta = get_spotify_meta(url) if platform_name == "Spotify" else get_apple_music_meta(url)

        if not meta:
            bot.edit_message_text(get_text(chat_id, 'meta_failed'), chat_id, msg.message_id)
            return

        SESSION_DATA[session_id]['meta'] = meta

        caption = (
            f"🎵 <b>{html.escape(meta['title'])}</b>\n"
            f"👤 {html.escape(meta['artist'])}\n\n"
            f"⚡️ via @{bot.get_me().username}\n"
            f"#Audio #{platform_name}"
        )

        markup = InlineKeyboardMarkup(row_width=2)
        markup.add(
            InlineKeyboardButton("🎵 MP3 - 320kbps", callback_data=f"dl_a_320_{session_id}"),
            InlineKeyboardButton("🎵 MP3 - 128kbps", callback_data=f"dl_a_128_{session_id}"),
            InlineKeyboardButton(get_text(chat_id, 'cancel'), callback_data="cancel")
        )

        try:
            if meta['cover']:
                bot.send_photo(chat_id, meta['cover'], caption=caption,
                               parse_mode="HTML", reply_markup=markup)
            else:
                bot.send_message(chat_id, caption, parse_mode="HTML", reply_markup=markup)
            bot.delete_message(chat_id, msg.message_id)
        except Exception as e:
            logger.error(f"Telegram send error: {e}")
            bot.send_message(chat_id, get_text(chat_id, 'generic_error', error="Media Preview Failed"))
        return

    try:
        ydl_opts_info = {'quiet': True, 'no_warnings': True, **youtube_bypass_opts()}

        with yt_dlp.YoutubeDL(ydl_opts_info) as ydl:
            info = ydl.extract_info(url, download=False)

            title = info.get('title') or f"{platform_name} Content"
            uploader = info.get('uploader', info.get('channel', 'Unknown User'))
            views = format_number(info.get('view_count', 0))
            likes = format_number(info.get('like_count', 0))
            thumbnail = info.get('thumbnail', None)

            caption = (
                f"📹 <b>{html.escape(title)}</b>\n"
                f"👤 {html.escape(uploader)}\n"
                f"👁 {views} 👍 {likes}\n"
                f"⚡️ via @{bot.get_me().username}\n\n"
                f"#{platform_name} #Download"
            )

            markup = InlineKeyboardMarkup()

            if platform_name == "YouTube":
                markup.add(InlineKeyboardButton(get_text(chat_id, 'fast_dl'),
                                               callback_data=f"dl_v_best_{session_id}"))
                vid_buttons = [
                    InlineKeyboardButton(f"🎬 {res}p", callback_data=f"dl_v_{res}_{session_id}")
                    for res in [1080, 720, 480, 360]
                ]
                for i in range(0, len(vid_buttons), 2):
                    markup.add(*vid_buttons[i:i + 2])
                markup.add(
                    InlineKeyboardButton("🎵 MP3 320kbps", callback_data=f"dl_a_320_{session_id}"),
                    InlineKeyboardButton("🎵 MP3 128kbps", callback_data=f"dl_a_128_{session_id}")
                )
            elif platform_name in ["Instagram", "TikTok", "Media"]:
                markup.add(InlineKeyboardButton(get_text(chat_id, 'dl_video'),
                                               callback_data=f"dl_v_best_{session_id}"))
            elif platform_name == "SoundCloud":
                markup.add(
                    InlineKeyboardButton("🎵 MP3 320kbps", callback_data=f"dl_a_320_{session_id}"),
                    InlineKeyboardButton("🎵 MP3 128kbps", callback_data=f"dl_a_128_{session_id}")
                )

            markup.add(InlineKeyboardButton(get_text(chat_id, 'cancel'), callback_data="cancel"))

            if thumbnail:
                bot.send_photo(chat_id, thumbnail, caption=caption,
                               parse_mode="HTML", reply_markup=markup)
            else:
                bot.send_message(chat_id, caption, parse_mode="HTML", reply_markup=markup)

            try:
                bot.delete_message(chat_id, msg.message_id)
            except Exception:
                pass

    except Exception as e:
        logger.error(f"Extraction error: {e}")
        bot.send_message(chat_id, get_text(chat_id, 'extract_error', platform=platform_name))

def run_spotdl(url, session_id, quality):
    if not shutil.which("spotdl"):
        return None, "spotdl not installed"

    output_template = "downloads/" + session_id + ".{output-ext}"
    cmd = [
        "spotdl", "download", url,
        "--output", output_template,
        "--format", "mp3",
        "--bitrate", f"{quality}k",
        "--no-cache",
        "--threads", "1",
    ]
    if os.path.exists(COOKIES_FILE):
        cmd += ["--cookie-file", COOKIES_FILE]
    cmd += ["--yt-dlp-args", "--force-ipv4 --sleep-requests 1"]

    sp_id = os.getenv("SPOTIFY_CLIENT_ID")
    sp_secret = os.getenv("SPOTIFY_CLIENT_SECRET")
    if sp_id and sp_secret:
        cmd += ["--client-id", sp_id, "--client-secret", sp_secret]

    proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
    try:
        out, _ = proc.communicate(timeout=SPOTDL_TIMEOUT)
    except subprocess.TimeoutExpired:
        proc.kill()
        try:
            proc.communicate(timeout=10)
        except Exception:
            pass
        return None, "spotdl timeout"

    produced = find_produced_file(session_id, exts=("mp3",))
    if produced:
        return produced, None
    return None, (out or "unknown spotdl error").strip()[-300:]

def ytdlp_audio(target_url, session_id, quality, progress_hook=None):
    ydl_opts = {
        'format': 'bestaudio/best',
        'postprocessors': [{
            'key': 'FFmpegExtractAudio',
            'preferredcodec': 'mp3',
            'preferredquality': str(quality),
        }],
        'outtmpl': f'downloads/{session_id}.%(ext)s',
        'quiet': True,
        'no_warnings': True,
        'noplaylist': True,
        'max_filesize': MAX_TG_SIZE,
        **youtube_bypass_opts(),
    }
    if progress_hook:
        ydl_opts['progress_hooks'] = [progress_hook]
        
    with yt_dlp.YoutubeDL(ydl_opts) as ydl:
        info = ydl.extract_info(target_url, download=True)
        if info and 'entries' in info:
            entries = [e for e in info['entries'] if e]
            if not entries:
                raise Exception("No matching track found.")
            info = entries[0]
    path = find_produced_file(session_id, exts=("mp3", "m4a", "opus", "webm"))
    if not path:
        raise Exception("Download produced no file.")
    return path, info

def do_download(call, media_type, quality, session_id):
    session = SESSION_DATA.get(session_id)
    if not session:
        return

    url = session['url']
    chat_id = call.message.chat.id
    message_id = call.message.message_id
    has_photo = bool(getattr(call.message, 'photo', None))

    safe_edit(chat_id, message_id, get_text(chat_id, 'dl_progress'), has_photo)

    file_path = None
    cover_path = None

    hook = create_progress_hook(chat_id, message_id, has_photo)

    try:
        if media_type == 'a':
            info = None

            if session['type'] == 'music_external' and session.get('platform') == 'Spotify':
                file_path, err = run_spotdl(url, session_id, quality)
                if not file_path:
                    safe_edit(chat_id, message_id, get_text(chat_id, 'slow_spotify'), has_photo)
                    meta = session['meta']
                    file_path, info = ytdlp_audio(
                        f"ytsearch1:{meta['artist']} - {meta['title']} audio",
                        session_id, quality, progress_hook=hook)
            else:
                target_url = url
                if session['type'] == 'music_external':
                    meta = session['meta']
                    target_url = f"ytsearch1:{meta['artist']} - {meta['title']} audio"
                file_path, info = ytdlp_audio(target_url, session_id, quality, progress_hook=hook)

            if os.path.getsize(file_path) > MAX_TG_SIZE:
                raise Exception("MAX_SIZE_REACHED")

            safe_edit(chat_id, message_id, get_text(chat_id, 'up_audio'), has_photo)

            thumb_file = None
            if session['type'] == 'music_external' and session['meta'].get('cover'):
                cover_path = download_cover(session['meta']['cover'], session_id)
                if cover_path:
                    thumb_file = open(cover_path, 'rb')

            with open(file_path, 'rb') as audio_file:
                bot.send_audio(
                    chat_id=chat_id,
                    audio=audio_file,
                    title=session['meta']['title'] if session['type'] == 'music_external' else (info or {}).get('title'),
                    performer=session['meta']['artist'] if session['type'] == 'music_external' else (info or {}).get('uploader'),
                    thumb=thumb_file,
                    timeout=120,
                )
            if thumb_file:
                thumb_file.close()

        elif media_type == 'v':
            if quality == 'best':
                format_str = 'best[ext=mp4]/best'
            else:
                format_str = f'bestvideo[height<={quality}]+bestaudio/best[height<={quality}]/best'

            ydl_opts = {
                'format': format_str,
                'merge_output_format': 'mp4',
                'outtmpl': f'downloads/{session_id}.%(ext)s',
                'quiet': True,
                'no_warnings': True,
                'noplaylist': True,
                'max_filesize': MAX_TG_SIZE,
                'progress_hooks': [hook],
                **youtube_bypass_opts(),
            }
            with yt_dlp.YoutubeDL(ydl_opts) as ydl:
                ydl.extract_info(url, download=True)

            file_path = find_produced_file(session_id, exts=("mp4", "mkv", "webm"))
            if not file_path:
                raise Exception("Download produced no file.")

            safe_edit(chat_id, message_id, get_text(chat_id, 'up_video'), has_photo)
            with open(file_path, 'rb') as video_file:
                bot.send_video(chat_id, video_file, supports_streaming=True, timeout=180)

        try:
            bot.delete_message(chat_id, message_id)
        except Exception:
            pass

    except yt_dlp.utils.DownloadError as e:
        logger.error(f"yt-dlp error: {e}")
        if "max-filesize" in str(e) or "larger than" in str(e):
            bot.send_message(chat_id, get_text(chat_id, 'size_limit'))
        else:
            bot.send_message(chat_id, get_text(chat_id, 'format_error'))
    except Exception as e:
        logger.error(f"Download error: {e}")
        if str(e) == "MAX_SIZE_REACHED":
            bot.send_message(chat_id, get_text(chat_id, 'size_limit'))
        else:
            bot.send_message(chat_id, get_text(chat_id, 'generic_error', error=html.escape(str(e)[:400])), parse_mode="HTML")
    finally:
        for p in (file_path, cover_path):
            if p and os.path.exists(p):
                try:
                    os.remove(p)
                except Exception:
                    pass
        SESSION_DATA.pop(session_id, None)

# --- Admin Panel Callback Handlers ---
@bot.callback_query_handler(func=lambda call: call.data.startswith('admin_'))
def admin_callbacks(call):
    if call.from_user.id not in ADMIN_IDS:
        return
    if call.data == "admin_stats":
        users_count = len(open(USERS_FILE).read().splitlines()) if os.path.exists(USERS_FILE) else 0
        bot.answer_callback_query(call.id, f"👥 تعداد کل کاربران ربات: {users_count}", show_alert=True)
    elif call.data == "admin_broadcast":
        msg = bot.send_message(call.message.chat.id, "📣 لطفاً پیام خود را برای ارسال همگانی بفرستید (متن، عکس، ویدیو و...):\n\nبرای لغو کلمه «لغو» را بفرستید.")
        bot.register_next_step_handler(msg, process_broadcast)

# --- Callback / Download Handler ---
@bot.callback_query_handler(func=lambda call: call.data == 'check_join')
def check_join(call):
    chat_id = call.message.chat.id
    if is_user_member(call.from_user.id):
        bot.answer_callback_query(call.id, get_text(chat_id, 'join_ok'))
        try:
            bot.delete_message(chat_id, call.message.message_id)
        except Exception:
            pass
        bot.send_message(chat_id, get_text(chat_id, 'welcome'), parse_mode="HTML")
    else:
        bot.answer_callback_query(call.id, get_text(chat_id, 'join_not_yet'), show_alert=True)

@bot.callback_query_handler(func=lambda call: call.data.startswith('lang_'))
def set_language(call):
    lang_code = call.data.split('_')[1]
    USER_LANG[call.message.chat.id] = lang_code
    
    success_text = get_text(call.message.chat.id, 'lang_changed')
    bot.answer_callback_query(call.id, success_text)
    bot.edit_message_caption(success_text, call.message.chat.id, call.message.message_id)

@bot.callback_query_handler(func=lambda call: True)
def callback_query(call):
    chat_id = call.message.chat.id

    if not is_user_member(call.from_user.id):
        bot.answer_callback_query(call.id, get_text(chat_id, 'join_not_yet'), show_alert=True)
        send_join_prompt(chat_id)
        return

    if call.data == "cancel":
        bot.answer_callback_query(call.id, get_text(chat_id, 'cancelled'))
        try:
            bot.delete_message(chat_id, call.message.message_id)
        except Exception:
            pass
        return

    data_parts = call.data.split('_')
    if len(data_parts) != 4:
        return

    _, media_type, quality, session_id = data_parts

    if session_id not in SESSION_DATA:
        bot.answer_callback_query(call.id, get_text(chat_id, 'session_expired'), show_alert=True)
        return

    bot.answer_callback_query(call.id, get_text(chat_id, 'start_dl'))
    
    threading.Thread(target=do_download,
                     args=(call, media_type, quality, session_id),
                     daemon=True).start()

if __name__ == '__main__':
    logger.info("Premium Bot is starting on Cloud API...")
    setup_commands()
    bot.infinity_polling(skip_pending=True, timeout=30, long_polling_timeout=30)