import json import os import datetime import asyncio import logging import traceback import ssl from aiohttp import ClientSession, TCPConnector import filetype from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup from telegram.ext import ApplicationBuilder, CommandHandler, ContextTypes, MessageHandler, filters, CallbackQueryHandler from telegram.constants import ChatMemberStatus # Logging ayarları logging.basicConfig( format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO ) logger = logging.getLogger(__name__) # ---------------------- # ⚙️ AYARLAR # ---------------------- TOKEN = "8199792533:AAFJr6rgrjCmoWyW5REi-ZGk0LxTmcFdx4Y" ADMIN_ID = 7332455129 KANAL_LISTESI = ["@YxcPanel", "@YXCChecker", "@YxcPanelUyeKontrol"] DATA_FILE = "yxc_database.json" LOG_ID = ADMIN_ID VIP_IBAN = "TR10 0006 2000 9100 0006 9697 09" VIP_AD_SOYAD = "Garanti Ödeme ve Elektronik Para Hizmetleri A.Ş." VIP_ACIKLAMA = "TAMİ7815957096786307" REF_HEDIYE_SINIR = 10 GUNLUK_HAK_SINIRI = 5 # 🛒 MARKET PAKETLERİ AYARLARI MARKET_PRODUCTS = { "haftalik_vip": {"name": "Haftalık Vip", "price": 500, "days": 7, "type": "vip", "desc": "Bir hafta Yxc Vip üyesi ol, haftanın tadını çıkar!\nSınırsız Sorgu Hakkı\n7/24 Destek\nGüvenilir Alış Veriş"}, "aylik_vip": {"name": "Aylık Vip", "price": 1000, "days": 30, "type": "vip", "desc": "Bir ay Yxc Vip üyesi ol, ayın tadını çıkar!\nSınırsız Sorgu Hakkı\n7/24 Destek\nGüvenilir Alış Veriş"}, "3aylik_vip": {"name": "3 Aylık Vip", "price": 2500, "days": 90, "type": "vip", "desc": "Üç Ay Yxc Vip üyesi ol, 3 ayın tadını çıkar!\nSınırsız Sorgu Hakkı\n7/24 Destek\nGüvenilir Alış Veriş"}, "sinirsiz_vip": {"name": "Sınırsız Vip", "price": 5000, "days": "SINIRSIZ", "type": "vip", "desc": "Sınırsız Yxc Vip üyesi ol, tadını çıkar!\nSınırsız Sorgu Hakkı\n7/24 Destek\nGüvenilir Alış Veriş ♾️"}, "bayilik": {"name": "Bayilik", "price": 6000, "days": "SINIRSIZ", "type": "reseller", "desc": "Sınırsız Bayi üyesi ol!\nSınırsız Bakiye Yükleme Hakkı\n7/24 Destek\nGüvenilir Alış Veriş"} } # ---------------------- # 📂 VERİ YÖNETİMİ # ---------------------- def load_db(): default = { "vips": {}, "users": {}, "resellers": [], "balances": {}, "ref_count": {}, "settings": {"active": True}, "daily_limits": {}, "banned": [], "query_history": {}, "user_stats": {} } if os.path.exists(DATA_FILE): try: with open(DATA_FILE, "r", encoding="utf-8") as f: db = json.load(f) for k, v in default.items(): if k not in db: db[k] = v return db except: return default return default def save_db(db): try: with open(DATA_FILE, "w", encoding="utf-8") as f: json.dump(db, f, indent=4, ensure_ascii=False) except Exception as e: logger.error(f"Veritabanı kaydetme hatası: {e}") def get_balance(uid, db): return db["balances"].get(str(uid), 0) def add_balance(uid, amount, db): uid_s = str(uid) db["balances"][uid_s] = db["balances"].get(uid_s, 0) + float(amount) save_db(db) def is_banned(uid, db): return str(uid) in db.get("banned", []) def is_vip(uid, db): uid_s = str(uid) if int(uid) == ADMIN_ID or uid_s in db.get("resellers", []): return True v_date = db["vips"].get(uid_s) if v_date == "SINIRSIZ": return True if not v_date: return False try: return datetime.datetime.now() < datetime.datetime.fromisoformat(v_date) except: return False def get_vip_remaining_string(uid, db): uid_s = str(uid) if int(uid) == ADMIN_ID: return "Kurucu ♾️" if uid_s in db.get("resellers", []): return "Bayi (Sınırsız) 💼" v_date = db["vips"].get(uid_s) if v_date == "SINIRSIZ": return "Sınırsız Süre ♾️" if not v_date: return None try: dt = datetime.datetime.fromisoformat(v_date) if datetime.datetime.now() < dt: return dt.strftime("%d.%m.%Y %H:%M") return None except: return None def get_user_stats(uid, db): uid_s = str(uid) stats = db.get("user_stats", {}).get(uid_s, {}) query_history = db.get("query_history", {}).get(uid_s, []) return { "total_queries": stats.get("total_queries", 0), "today_queries": db.get("daily_limits", {}).get(uid_s, 0), "last_query": stats.get("last_query", "Hiç sorgu yapılmamış"), "query_types": stats.get("query_types", {}), "recent_queries": query_history[-5:] if query_history else [] } # ---------------------- # 🔗 KANAL KONTROLÜ # ---------------------- async def is_sub(uid, context): if int(uid) == ADMIN_ID: return True for kanal in KANAL_LISTESI: try: m = await context.bot.get_chat_member(kanal, uid) if m.status not in [ChatMemberStatus.MEMBER, ChatMemberStatus.ADMINISTRATOR, ChatMemberStatus.OWNER]: return False except: return False return True async def send_log(context, message): try: await context.bot.send_message(chat_id=LOG_ID, text=f"LOG BİLDİRİMİ\n\n{message}") except: pass async def reset_daily_limits(context: ContextTypes.DEFAULT_TYPE): db = load_db() db["daily_limits"] = {} save_db(db) await send_log(context, "Günlük sorgu hakları gece 12 itibariyle sabitlendi ve sıfırlandı!") # ---------------------- # 🌐 APİ VE PARAMETRE YAPILANDIRMASI # ---------------------- APIS = { "adsoyad": "http://yxcvds.xyz/api/549ce6e200bd4f20c3420986ad84d78f/adsoyad-sorgu.php?ad={}&soyad={}", "adsoyadil": "http://localhost/karmaapiler/adsoyad/api.php?ad={}&soyad={}&il={}", "adsoyadililce": "http://169.58.69.176/karmaapiler/adsoyad/api.php?ad={}&soyad={}&il={}&ilce={}", "tc": "http://169.58.69.176/karmapiler/tc/tcv3.php?tc={}", "anne": "http://169.58.69.176/karmapiler/anne/api.php?tc={}", "baba": "http://169.58.69.176/karmapiler/baba/api.php?tc={}", "adililce": "http://169.58.69.176/karmaapiler/adililce/api.php?tc={}", "tcgsm": "http://169.58.69.176/karmaapiler/gsm/apii.php?tc={}", "gsmtc": "http://169.58.69.176/karmaapiler/gsm/apii.php?gsm={}", "sulale": "http://169.58.69.176/karmaapiler/sulale/api.php?tc={}", "soyagaci": "http://169.58.69.176/karmaapiler/soyagaci/api.php?tc={}", "isyeri": "http://169.58.69.176/karmaapiler/sigorta/apii.php?tc={}", "adres": "http://169.58.69.176/karmaapiler/adres/api.php?tc={}", "tapu": "http://169.58.69.176/karmaapiler/tapu/api.php?tc={}", "tcpro": "http://169.58.69.176/karmaapiler/tcpro/api.php?tc={}", "aile": "http://169.58.69.176/karmaapiler/aile/api.php?tc={}", "vergino": "http://169.58.69.176/karmaapiler/vergino/api.php?tc={}", "tcplakaborc": "http://169.58.69.176/api/plaka/apii.php?tc={}", "plakaborc": "http://169.58.69.176/karmaapiler/plaka/api.php?plate={}", "ailegsm": "http://169.58.69.176/karmaapiler/ailegsm/api.php?tc={}" } QUERY_CONFIG = { "adsoyad": {"desc": "Ad ve Soyad", "example": "Ahmet Yılmaz", "count": 2}, "adsoyadil": {"desc": "Ad, Soyad ve İl", "example": "Ahmet Yılmaz İstanbul", "count": 3}, "adsoyadililce": {"desc": "Ad, Soyad, İl ve İlçe", "example": "Ahmet Yılmaz İstanbul Kadıköy", "count": 4}, "tc": {"desc": "11 Haneli TC Kimlik Numarası", "example": "11111111110", "count": 1}, "tcgsm": {"desc": "TC Kimlik Numarası", "example": "11111111110", "count": 1}, "gsmtc": {"desc": "Telefon Numarası (Başında 0 olmadan)", "example": "5321234567", "count": 1}, "sulale": {"desc": "TC Kimlik Numarası", "example": "11111111110", "count": 1}, "isyeri": {"desc": "TC Kimlik Numarası", "example": "11111111110", "count": 1}, "adres": {"desc": "TC Kimlik Numarası", "example": "11111111110", "count": 1}, "gunceladres": {"desc": "TC Kimlik Numarası", "example": "11111111110", "count": 1}, "baba": {"desc": "TC Kimlik Numarası", "example": "11111111110", "count": 1}, "anne": {"desc": "TC Kimlik Numarası", "example": "11111111110", "count": 1}, "tapu": {"desc": "TC Kimlik Numarası", "example": "11111111110", "count": 1}, "adililce": {"desc": "Ad ve İl İlçe", "example": "Roket Bursa Osmangazi", "count": 3}, "tcpro": {"desc": "TC Kimlik Numarası", "example": "11111111110", "count": 1}, "aile": {"desc": "TC Kimlik Numarası", "example": "11111111110", "count": 1}, "plakaborc": {"desc": "Araç Plakası (Boşluksuz)", "example": "34ABC34", "count": 1}, "vergino": {"desc": "Tc İle Vergi No", "example": "11111111110", "count": 1}, "soyagaci": {"desc": "TC Kimlik Numarasi", "example": "11111111110", "count": 1}, "ailegsm": {"desc": "TC Kimlik Numarasi", "example": "11111111110", "count": 1}, } FREE_LIST = ["adsoyad", "gsmtc", "tcgsm", "tc", "sulale", "adsoyadil", "aile"] VIP_LIST = ["vergino", "tcpro", "tapu", "adres", "plakaborc", "isyeri", "adsoyadililce", "soyagaci", "ailegsm", "anne", "baba", "adililce"] # ---------------------- # 🚀 ANA KOMUTLAR # ---------------------- async def start(update: Update, context: ContextTypes.DEFAULT_TYPE): try: user = update.effective_user uid = user.id db = load_db() uid_s = str(uid) if is_banned(uid, db) and uid != ADMIN_ID: await update.message.reply_text("🚫 Hesabınız yasaklanmıştır! Botu kullanamazsınız.") return context.user_data.clear() context.user_data["user_list_page"] = 0 if not db["settings"].get("active", True) and uid != ADMIN_ID: await update.message.reply_text("⚠️ Bot bakımda.") return if not await is_sub(uid, context): btn_list = [] for i, kanal in enumerate(KANAL_LISTESI, 1): btn_list.append([InlineKeyboardButton(f"📢 Kanal {i} Katıl", url=f"https://t.me/{kanal[1:]}")]) btn_list.append([InlineKeyboardButton("✅ Katıldım / Kontrol Et", callback_data="check_sub")]) await update.message.reply_text("🔒 Botu kullanmak için tüm kanallarımıza abone olmalısınız!", reply_markup=InlineKeyboardMarkup(btn_list)) return if uid_s not in db["users"]: db["users"][uid_s] = user.first_name db["balances"][uid_s] = 0.0 if "user_stats" not in db: db["user_stats"] = {} db["user_stats"][uid_s] = {"total_queries": 0, "query_types": {}, "last_query": "Hiç sorgu yapılmamış"} await send_log(context, f"🆕 Yeni Kullanıcı Kaydı!\n👤 Ad: {user.first_name}\n🆔 ID: {uid}\n🔗 Username: @{user.username if user.username else 'Yok'}") if context.args and context.args[0].isdigit(): ref_owner = context.args[0] if ref_owner != uid_s: db["ref_count"][ref_owner] = db["ref_count"].get(ref_owner, 0) + 1 if db["ref_count"][ref_owner] >= REF_HEDIYE_SINIR: db["vips"][ref_owner] = (datetime.datetime.now() + datetime.timedelta(days=7)).isoformat() save_db(db) bakiye = get_balance(uid, db) txt = f"👋 Selam {user.first_name}!\n\n💰 Bakiyeniz: {bakiye:.2f} TL" vip_tarih_str = get_vip_remaining_string(uid, db) if vip_tarih_str: txt += f"\n⭐ Üyelik Durumu: {vip_tarih_str}" else: kalan_hak = GUNLUK_HAK_SINIRI - db["daily_limits"].get(uid_s, 0) txt += f"\n📊 Bugünlük Kalan Ücretsiz Sorgu Hakkınız: {max(0, kalan_hak)}/{GUNLUK_HAK_SINIRI}" btns = [ [InlineKeyboardButton("🚀 Sorgular", callback_data="list"), InlineKeyboardButton("🛒 Market / VIP Al", callback_data="market_menu")], [InlineKeyboardButton("💰 Bakiye Yükle", callback_data="buy_vip"), InlineKeyboardButton("👥 Referans", callback_data="ref_menu")] ] if uid_s in db.get("resellers", []) and uid != ADMIN_ID: btns.append([InlineKeyboardButton("💼 Bayi Paneli", callback_data="bayi_panel")]) elif uid == ADMIN_ID: btns.append([InlineKeyboardButton("💼 Admin Paneli", callback_data="admin_panel")]) await update.message.reply_text(txt, reply_markup=InlineKeyboardMarkup(btns)) except Exception as e: logger.error(f"Start hatası: {e}\n{traceback.format_exc()}") await update.message.reply_text("❌ Bir hata oluştu! Lütfen daha sonra tekrar deneyin.") async def handle_all(update: Update, context: ContextTypes.DEFAULT_TYPE): try: if update.callback_query: await callback(update, context) return user = update.effective_user if not user: return uid = user.id db = load_db() uid_s = str(uid) if not update.message: return text = update.message.text or "" if is_banned(uid, db) and uid != ADMIN_ID: await update.message.reply_text("🚫 Hesabınız yasaklanmıştır! Botu kullanamazsınız.") return if not db["settings"].get("active", True) and uid != ADMIN_ID: await update.message.reply_text("⚠️ Bot bakımda.") return if not await is_sub(uid, context): await update.message.reply_text("🔒 Lütfen önce tüm kanallara abone olun!") return # DUYURU İŞLEMİ (SADECE ADMIN) if context.user_data.get("waiting_announcement") and uid == ADMIN_ID: context.user_data["waiting_announcement"] = False sent_count = 0 for u in db["users"]: try: await context.bot.send_message(int(u), f"📢 DUYURU\n\n{text}") sent_count += 1 await asyncio.sleep(0.1) except: continue await update.message.reply_text(f"✅ Duyuru {sent_count} kullanıcıya gönderildi.") return # BAYİ BAKİYE EKLEME - SINIRSIZ if context.user_data.get("reseller_balance_add") and (uid in db.get("resellers", []) or uid == ADMIN_ID): context.user_data["reseller_balance_add"] = False try: parts = text.split() if len(parts) != 2: await update.message.reply_text("❌ Hatalı format! Örnek: 12345678 150") return target_id, amount = parts amount = float(amount) if not target_id.isdigit(): await update.message.reply_text("❌ Geçersiz ID! Lütfen sayısal bir ID girin.") return if str(target_id) in db["users"]: add_balance(target_id, amount, db) new_balance = get_balance(target_id, db) if uid != ADMIN_ID: await send_log(context, f"💼 Bayi {uid} ({user.first_name}) ➜ {target_id} ID'li kullanıcıya {amount:.2f} TL bakiye ekledi!") await update.message.reply_text( f"✅ {target_id} ID'li kullanıcıya {amount:.2f} TL bakiye eklendi.\n" f"🆕 Yeni Bakiye: {new_balance:.2f} TL" ) try: await context.bot.send_message( chat_id=int(target_id), text=f"💰 Hesabınıza {amount:.2f} TL bakiye eklendi!\n📊 Yeni Bakiyeniz: {new_balance:.2f} TL" ) except: pass else: await update.message.reply_text("❌ Kullanıcı bulunamadı.") except ValueError: await update.message.reply_text("❌ Geçersiz miktar! Lütfen sayısal bir değer girin.") except Exception as e: logger.error(f"Bakiye işlemi hatası: {e}") await update.message.reply_text("❌ Bir hata oluştu! Lütfen tekrar deneyin.") return # ADMIN BAN / UNBAN İŞLEMİ (SADECE ADMIN) if context.user_data.get("admin_ban_state") == "waiting_input" and uid == ADMIN_ID: context.user_data["admin_ban_state"] = None target_id = text.strip() if not target_id.isdigit(): await update.message.reply_text("❌ Geçersiz ID! Lütfen sadece sayısal bir ID gönderin.") return if target_id in db.get("banned", []): db["banned"].remove(target_id) save_db(db) await send_log(context, f"✅ {target_id} ID'li kullanıcının banı kaldırıldı!") await update.message.reply_text(f"✅ {target_id} ID'li kullanıcının banı kaldırıldı.") return else: if "banned" not in db: db["banned"] = [] db["banned"].append(target_id) save_db(db) await send_log(context, f"🚫 {target_id} ID'li kullanıcı banlandı!") await update.message.reply_text(f"🚫 {target_id} ID'li kullanıcı yasaklandı (banlandı).") return # ADMIN MANUAL BAKİYE EKLEME (SADECE ADMIN) if context.user_data.get("admin_bakiye_state") == "waiting_input" and uid == ADMIN_ID: context.user_data["admin_bakiye_state"] = None try: parts = text.split() if len(parts) != 2: await update.message.reply_text("❌ Hatalı format! Örnek: 12345678 150") return target_id, amount = parts amount = float(amount) if not target_id.isdigit(): await update.message.reply_text("❌ Geçersiz ID! Lütfen sayısal bir ID girin.") return if str(target_id) in db["users"]: add_balance(target_id, amount, db) new_balance = get_balance(target_id, db) await update.message.reply_text(f"✅ {target_id} ID'li kullanıcıya {amount:.2f} TL bakiye {'eklendi' if amount > 0 else 'çıkarıldı'}. Yeni Bakiye: {new_balance:.2f} TL") try: await context.bot.send_message(chat_id=int(target_id), text=f"💰 Hesabınıza admin tarafından {amount:.2f} TL bakiye {'eklendi' if amount > 0 else 'çıkarıldı'}!") except: pass else: await update.message.reply_text("❌ Kullanıcı bulunamadı.") except ValueError: await update.message.reply_text("❌ Geçersiz miktar! Lütfen sayısal bir değer girin.") except Exception as e: logger.error(f"Bakiye işlemi hatası: {e}") await update.message.reply_text("❌ Bir hata oluştu! Lütfen tekrar deneyin.") return # GÜVENLİ ADMIN ONAYLI PLAYKOD MİKTAR GİRİŞİ (SADECE ADMIN) if context.user_data.get("waiting_approve_amount") and uid == ADMIN_ID: target_uid = context.user_data.get("waiting_approve_amount") context.user_data["waiting_approve_amount"] = None try: amount = float(text) if str(target_uid) in db["users"]: add_balance(target_uid, amount, db) await update.message.reply_text(f"✅ Başarılı! {target_uid} kullanıcısına {amount:.2f} TL bakiye eklendi.") try: await context.bot.send_message(chat_id=int(target_uid), text=f"🎉 Playkod talebiniz admin tarafından onaylandı ve hesabınıza {amount:.2f} TL bakiye eklendi!") except: pass else: await update.message.reply_text("❌ Kullanıcı veritabanında bulunamadı.") except: await update.message.reply_text("❌ Geçersiz miktar girdiniz. İşlem iptal edildi.") return # KULLANICI PLAYKOD GİRİŞİ if context.user_data.get("waiting_playkod"): context.user_data["waiting_playkod"] = False clean_code = text.replace("-", "").strip() if len(clean_code) < 16: await update.message.reply_text("❌ Geçersiz formatta Google Play kodu girdiniz.") return await update.message.reply_text("✅ Playkod onay için admine gönderildi. Hesap kontrol edildikten sonra bakiyeniz yüklenecektir.") btns = [ [ InlineKeyboardButton("✅ Onayla", callback_data=f"aprcode_{uid}"), InlineKeyboardButton("❌ Reddet", callback_data=f"rejcode_{uid}") ] ] await context.bot.send_message( chat_id=ADMIN_ID, text=f"📥 YENİ PLAYKOD TALEBİ!\n\n👤 Kullanıcı: {user.first_name}\n🆔 ID: {uid}\n🔑 Kod: {text}\n\nOnaylıyor musunuz?", reply_markup=InlineKeyboardMarkup(btns) ) return if update.message.photo: await send_log(context, f"📸 Yeni Dekont!\n👤 Ad: {user.first_name}\n🆔 ID: {uid}\n🔗 Username: @{user.username if user.username else 'Yok'}") await update.message.reply_text("📸 Dekont iletildi. Admin onayından sonra bakiyeniz eklenecektir.") return # Sorgu işlemi active_query = context.user_data.get("active_query") if active_query: cmd = active_query args = text.split() elif text.startswith("/"): cmd = text.split()[0].lower().lstrip("/") args = text.split()[1:] else: return if cmd in APIS: config = QUERY_CONFIG.get(cmd, {"desc": "Gerekli Veri", "example": "veri", "count": 1}) vip_durumu = is_vip(uid, db) if cmd in VIP_LIST and not vip_durumu: context.user_data["active_query"] = None await update.message.reply_text("❌ Bu sorgu için VIP veya Bayi olmalısın.") return if not vip_durumu: kullanilan_hak = db["daily_limits"].get(uid_s, 0) if kullanilan_hak >= GUNLUK_HAK_SINIRI: context.user_data["active_query"] = None await update.message.reply_text( f"⚠️ Bugünlük Hakların bitti!\n\nMarketten VIP üyelik satın alarak tüm sınırları kaldırabilirsin.", reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("🛒 Markete Git", callback_data="market_menu")]]) ) return if len(args) < config["count"]: await update.message.reply_text( f"❌ Eksik veya hatalı bilgi girdiniz!\n\nİstenen Bilgi: {config['desc']}\nÖrnek Format: {config['example']}" ) return context.user_data["active_query"] = None # İstatistikleri güncelle if uid_s not in db["user_stats"]: db["user_stats"][uid_s] = {"total_queries": 0, "query_types": {}, "last_query": "Hiç sorgu yapılmamış"} db["user_stats"][uid_s]["total_queries"] = db["user_stats"][uid_s].get("total_queries", 0) + 1 db["user_stats"][uid_s]["last_query"] = datetime.datetime.now().strftime("%d.%m.%Y %H:%M") if "query_types" not in db["user_stats"][uid_s]: db["user_stats"][uid_s]["query_types"] = {} db["user_stats"][uid_s]["query_types"][cmd] = db["user_stats"][uid_s]["query_types"].get(cmd, 0) + 1 # Sorgu geçmişine ekle if uid_s not in db["query_history"]: db["query_history"][uid_s] = [] db["query_history"][uid_s].append({ "command": cmd, "data": " ".join(args), "time": datetime.datetime.now().strftime("%d.%m.%Y %H:%M") }) if not vip_durumu: db["daily_limits"][uid_s] = db["daily_limits"].get(uid_s, 0) + 1 save_db(db) log_text = f"🔍 Sorgu Yapıldı!\n👤 Ad: {user.first_name}\n🆔 ID: {uid}\n⚡ Komut: /{cmd}\n📝 Veri: {' '.join(args)}" await send_log(context, log_text) m = await update.message.reply_text("⏳ Sorgulanıyor...") try: ssl_context = ssl.create_default_context() ssl_context.check_hostname = False ssl_context.verify_mode = ssl.CERT_NONE connector = TCPConnector(ssl=ssl_context) async with ClientSession(connector=connector) as s: url = APIS[cmd].format(*args) async with s.get(url, timeout=30) as r: if r.status == 200: raw_bytes = await r.read() clean_text = raw_bytes.decode("utf-8-sig") if " MAX_MSG_LENGTH: if isinstance(res, dict): limited_res = {} count = 0 total_keys = len(res) for key, value in res.items(): if count < 3: limited_res[key] = value elif count == 3: limited_res["..."] = f"ve {total_keys - 3} anahtar daha (mesaj uzun olduğu için kısaltıldı)" break count += 1 formatted_json = json.dumps(limited_res, indent=2, ensure_ascii=False) elif isinstance(res, list): limited_res = res[:2] if len(res) > 2: limited_res.append(f"... ve {len(res) - 2} öğe daha (mesaj uzun olduğu için kısaltıldı)") formatted_json = json.dumps(limited_res, indent=2, ensure_ascii=False) result_text = f"📊 {cmd.upper()} SORGUSU SONUCU\n\n
{formatted_json}
" if len(result_text) > 4096: if isinstance(res, dict): simple_text = f"📊 {cmd.upper()} SORGUSU SONUCU\n\n" for key, value in list(res.items())[:5]: if not isinstance(value, (dict, list)): simple_text += f"• {key}: {value}\n" elif isinstance(value, dict): simple_text += f"• {key}:\n" for k, v in list(value.items())[:3]: simple_text += f" - {k}: {v}\n" if len(value) > 3: simple_text += f" ... ve {len(value) - 3} alan daha\n" elif isinstance(value, list): simple_text += f"• {key}: {len(value)} öğe\n" if len(simple_text) > 4096: simple_text = simple_text[:4000] + "\n... (mesaj çok uzun, kesildi)" await m.edit_text(simple_text) else: await m.edit_text(f"📊 {cmd.upper()} SORGUSU SONUCU\n\nVeri çok uzun, lütfen daha spesifik bir sorgu yapın.") else: await m.edit_text(result_text, parse_mode='HTML') else: await m.edit_text(f"❌ API Hatası: HTTP {r.status}") except Exception as e: logger.error(f"Sorgu hatası: {e}\n{traceback.format_exc()}") await m.edit_text(f"❌ API Hatası! Detay: {str(e)}") except Exception as e: logger.error(f"Handle_all hatası: {e}\n{traceback.format_exc()}") try: await update.message.reply_text("❌ Bir hata oluştu! Lütfen daha sonra tekrar deneyin.") except: pass # ---------------------- # 👤 KULLANICI DETAY GÖSTERME FONKSİYONU (GÜZEL FORMATLI) # ---------------------- async def show_user_detail(update: Update, context: ContextTypes.DEFAULT_TYPE, user_id): try: db = load_db() uid_s = str(user_id) if uid_s not in db["users"]: await update.message.reply_text("❌ Kullanıcı bulunamadı!") return name = db["users"][uid_s] balance = get_balance(int(user_id), db) # Durum bilgileri is_banned_status = "🚫 EVET" if is_banned(int(user_id), db) else "✅ HAYIR" is_vip_status = "⭐ EVET" if is_vip(int(user_id), db) else "❌ HAYIR" is_reseller = "✅ EVET" if uid_s in db.get("resellers", []) else "❌ HAYIR" vip_date = get_vip_remaining_string(int(user_id), db) or "VIP değil" # İstatistikler stats = get_user_stats(int(user_id), db) txt = f"📊 KULLANICI DETAYI\n" txt += "═" * 30 + "\n\n" txt += f"👤 İsim: {name}\n" txt += f"🆔 ID: {user_id}\n" txt += f"💰 Bakiye: {balance:.2f} TL\n" txt += f"⭐ VIP: {is_vip_status}\n" txt += f"📅 VIP Bitiş: {vip_date}\n" txt += f"💼 Bayi: {is_reseller}\n" txt += f"🚫 Banlı: {is_banned_status}\n" txt += "─" * 30 + "\n" txt += f"📊 Toplam Sorgu: {stats['total_queries']}\n" txt += f"📅 Bugünkü Sorgu: {stats['today_queries']}/{GUNLUK_HAK_SINIRI}\n" txt += f"🕐 Son Sorgu: {stats['last_query']}\n" if stats['query_types']: txt += "\n📈 Sorgu Tipleri:\n" for q_type, count in sorted(stats['query_types'].items(), key=lambda x: x[1], reverse=True)[:5]: txt += f" • {q_type.upper()}: {count}\n" if stats['recent_queries']: txt += "\n🔄 Son 5 Sorgu:\n" for q in stats['recent_queries']: txt += f" • {q['command'].upper()}: {q['data']} ({q['time']})\n" btns = [ [InlineKeyboardButton("💰 Bakiye Ekle/Çıkar", callback_data=f"admin_balance_user_{user_id}")], [InlineKeyboardButton("🚫 Banla/Kaldır", callback_data=f"admin_ban_user_{user_id}")], [InlineKeyboardButton("⭐ VIP Ver (30 Gün)", callback_data=f"admin_vip_user_{user_id}")], [InlineKeyboardButton("⬅️ Geri", callback_data="admin_user_list")] ] if update.callback_query: await update.callback_query.edit_message_text(txt, reply_markup=InlineKeyboardMarkup(btns)) else: await update.message.reply_text(txt, reply_markup=InlineKeyboardMarkup(btns)) except Exception as e: logger.error(f"Show_user_detail hatası: {e}\n{traceback.format_exc()}") await update.message.reply_text("❌ Kullanıcı detayları gösterilirken hata oluştu!") # ---------------------- # 📋 KULLANICI LİSTESİ GÖSTERME (GÜZEL FORMATLI) # ---------------------- async def show_user_list(update: Update, context: ContextTypes.DEFAULT_TYPE, page=0): try: if update.callback_query: uid = update.callback_query.from_user.id else: uid = update.effective_user.id if uid != ADMIN_ID: return db = load_db() users = list(db['users'].items()) total_users = len(users) total_pages = max(1, (total_users + 9) // 10) if total_users > 0 else 1 if page >= total_pages: page = total_pages - 1 if page < 0: page = 0 context.user_data["user_list_page"] = page start_idx = page * 10 end_idx = min(start_idx + 10, total_users) current_users = users[start_idx:end_idx] if users else [] # İstatistikler total_vips = len([u for u in db["vips"] if is_vip(int(u), db)]) total_banned = len(db.get("banned", [])) total_resellers = len(db.get("resellers", [])) total_balance = sum(db['balances'].values()) txt = f"📊 KULLANICI LİSTESİ\n" txt += "═" * 30 + "\n\n" txt += f"👥 Toplam Kullanıcı: {total_users}\n" txt += f"⭐ VIP: {total_vips}\n" txt += f"💼 Bayi: {total_resellers}\n" txt += f"🚫 Yasaklı: {total_banned}\n" txt += f"💰 Toplam Bakiye: {total_balance:.2f} TL\n" txt += "─" * 30 + "\n\n" if not current_users: txt += "📭 Henüz hiç kullanıcı yok." else: for i, (user_id, name) in enumerate(current_users, start_idx + 1): is_banned_str = "🚫" if is_banned(int(user_id), db) else "✅" is_vip_str = "⭐" if is_vip(int(user_id), db) else "❌" balance = get_balance(int(user_id), db) txt += f"{i}. {is_banned_str} {is_vip_str} {name}\n" txt += f" 🆔 {user_id} | 💰 {balance:.2f} TL\n" # Butonlar btns = [] nav_row = [] if total_pages > 1: if page > 0: nav_row.append(InlineKeyboardButton("⬅️ Önceki", callback_data=f"user_list_page_{page-1}")) nav_row.append(InlineKeyboardButton(f"{page+1}/{total_pages}", callback_data="none")) if page < total_pages - 1: nav_row.append(InlineKeyboardButton("➡️ Sonraki", callback_data=f"user_list_page_{page+1}")) if nav_row: btns.append(nav_row) # Kullanıcı butonları - tıklayınca detay göster if current_users: user_btns = [] for user_id, name in current_users: user_btns.append(InlineKeyboardButton(f"👤 {name}", callback_data=f"user_detail_{user_id}")) # 2'li gruplar halinde göster for i in range(0, len(user_btns), 2): row = user_btns[i:i+2] btns.append(row) btns.append([InlineKeyboardButton("🔍 Kullanıcı Ara", callback_data="admin_search_user")]) btns.append([InlineKeyboardButton("⬅️ Admin Paneli", callback_data="admin_panel")]) if update.callback_query: try: await update.callback_query.edit_message_text( txt, reply_markup=InlineKeyboardMarkup(btns) ) except Exception as e: logger.error(f"Mesaj güncelleme hatası: {e}") else: await update.message.reply_text( txt, reply_markup=InlineKeyboardMarkup(btns) ) except Exception as e: logger.error(f"Show_user_list hatası: {e}\n{traceback.format_exc()}") # ---------------------- # 🔘 BUTON KONTROLLERİ # ---------------------- async def callback(update: Update, context: ContextTypes.DEFAULT_TYPE): try: q = update.callback_query if not q: return uid = q.from_user.id db = load_db() uid_s = str(uid) is_reseller = uid_s in db.get("resellers", []) is_admin = uid == ADMIN_ID try: await q.answer() except: pass if is_banned(uid, db) and not is_admin: await q.answer("🚫 Hesabınız yasaklanmıştır!", show_alert=True) return # ===================== # KULLANICI DETAY - TIKLANINCA # ===================== if q.data.startswith("user_detail_"): if not is_admin: await q.answer("⛔ Bu alan sadece admin içindir!", show_alert=True) return user_id = q.data.replace("user_detail_", "") await show_user_detail(update, context, user_id) return if q.data == "none": await q.answer() return if q.data == "check_sub": if await is_sub(uid, context): await q.message.delete() bakiye = get_balance(uid, db) txt = f"👋 Selam {q.from_user.first_name}!\n\n💰 Bakiyeniz: {bakiye:.2f} TL" vip_tarih_str = get_vip_remaining_string(uid, db) if vip_tarih_str: txt += f"\n⭐ Üyelik Durumu: {vip_tarih_str}" btns = [ [InlineKeyboardButton("🚀 Sorgular", callback_data="list"), InlineKeyboardButton("🛒 Market / VIP Al", callback_data="market_menu")], [InlineKeyboardButton("💰 Bakiye Yükle", callback_data="buy_vip"), InlineKeyboardButton("👥 Referans", callback_data="ref_menu")] ] if is_reseller and not is_admin: btns.append([InlineKeyboardButton("💼 Bayi Paneli", callback_data="bayi_panel")]) elif is_admin: btns.append([InlineKeyboardButton("💼 Admin Paneli", callback_data="admin_panel")]) await context.bot.send_message(chat_id=uid, text=txt, reply_markup=InlineKeyboardMarkup(btns)) else: await q.answer("⚠️ Hala eksik kanallar var!", show_alert=True) return if q.data.startswith("user_list_page_"): if not is_admin: return try: page = int(q.data.split("_")[-1]) await show_user_list(update, context, page) except Exception as e: logger.error(f"Sayfa değiştirme hatası: {e}") return if q.data == "list": if not await is_sub(uid, context): return btns = [] temp_row = [] for k in FREE_LIST: temp_row.append(InlineKeyboardButton(f"🔍 {k.upper()}", callback_data=f"query_{k}")) if len(temp_row) == 2: btns.append(temp_row) temp_row = [] if temp_row: btns.append(temp_row) temp_row = [] for k in VIP_LIST: temp_row.append(InlineKeyboardButton(f"⭐ {k.upper()}", callback_data=f"query_{k}")) if len(temp_row) == 2: btns.append(temp_row) temp_row = [] if temp_row: btns.append(temp_row) btns.append([InlineKeyboardButton("⬅️ Geri", callback_data="back_home")]) await q.edit_message_text("📋 Lütfen yapmak istediğiniz sorguyu seçin:", reply_markup=InlineKeyboardMarkup(btns)) return if q.data.startswith("query_"): cmd = q.data.split("_", 1)[1] vip_durumu = is_vip(uid, db) if cmd in VIP_LIST and not vip_durumu: await q.answer("❌ Bu sorgu için VIP olmalısın!", show_alert=True) return if not vip_durumu and db["daily_limits"].get(uid_s, 0) >= GUNLUK_HAK_SINIRI: await q.answer("⚠️ Bugünlük ücretsiz sorgu hakkın bitti!", show_alert=True) return config = QUERY_CONFIG.get(cmd, {"desc": "Gerekli Veri", "example": "veri", "count": 1}) context.user_data["active_query"] = cmd await q.edit_message_text( f"🔍 Sorgu Modu Aktif: {cmd.upper()}\n\nİstenen Bilgi: {config['desc']}\nÖrnek: {config['example']}", reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("❌ İptal Et", callback_data="cancel_query")]]) ) return if q.data.startswith("aprcode_") and is_admin: target_uid = q.data.split("aprcode_")[1] context.user_data["waiting_approve_amount"] = target_uid await q.edit_message_text("✅ Kod Onaylandı!\n\nŞimdi bu kullanıcıya yüklenecek TL miktarını direkt yazıp gönderin:\n(Örnek: 100)") return if q.data.startswith("rejcode_") and is_admin: target_uid = q.data.split("rejcode_")[1] await q.edit_message_text("❌ Talep reddedildi.") try: await context.bot.send_message(chat_id=int(target_uid), text="❌ Gönderdiğiniz Playkod geçersiz veya eklenemediği için bakiye talebiniz reddedildi.") except: pass return if q.data == "market_menu": txt = f"🛒 YXC BOT MARKETI\n\n💰 Güncel Bakiyeniz: {get_balance(uid, db):.2f} TL\n\nAlmak istediğiniz paketi seçin:" btns = [] for key, prod in MARKET_PRODUCTS.items(): btns.append([InlineKeyboardButton(f"📦 {prod['name']} - {prod['price']} TL", callback_data=f"view_prod_{key}")]) btns.append([InlineKeyboardButton("⬅️ Geri Ana Menü", callback_data="back_home")]) await q.edit_message_text(txt, reply_markup=InlineKeyboardMarkup(btns)) return if q.data.startswith("view_prod_"): prod_key = q.data.split("view_prod_")[1] prod = MARKET_PRODUCTS[prod_key] txt = f"📦 {prod['name']}\n💰 Fiyat: {prod['price']} TL\n\n📝 Açıklama:\n{prod['desc']}\n\n💰 Bakiyeniz: {get_balance(uid, db):.2f} TL" btns = [ [InlineKeyboardButton("✅ Satın Al", callback_data=f"buy_prod_{prod_key}")], [InlineKeyboardButton("⬅️ Markete Dön", callback_data="market_menu")] ] await q.edit_message_text(txt, reply_markup=InlineKeyboardMarkup(btns)) return if q.data.startswith("buy_prod_"): prod_key = q.data.split("buy_prod_")[1] prod = MARKET_PRODUCTS[prod_key] user_bal = get_balance(uid, db) if user_bal < prod["price"]: await q.answer("❌ Bakiyeniz yetersiz! Lütfen önce bakiye yükleyin.", show_alert=True) return db["balances"][uid_s] = user_bal - prod["price"] if prod["type"] == "vip": now = datetime.datetime.now() if prod["days"] == "SINIRSIZ": db["vips"][uid_s] = "SINIRSIZ" else: current_vip = db["vips"].get(uid_s) if current_vip and current_vip != "SINIRSIZ": try: start_date = max(now, datetime.datetime.fromisoformat(current_vip)) except: start_date = now else: start_date = now db["vips"][uid_s] = (start_date + datetime.timedelta(days=prod["days"])).isoformat() elif prod["type"] == "reseller": if uid_s not in db["resellers"]: db["resellers"].append(uid_s) save_db(db) await q.answer(f"✅ {prod['name']} başarıyla satın alındı!", show_alert=True) await q.edit_message_text( f"✅ Satın Alım Başarılı!\n\n{prod['name']} paketiniz hesabınıza otomatik olarak tanımlanmıştır.\nKeyifli sorgular! 🎉", reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("⬅️ Ana Menü", callback_data="back_home")]]) ) await send_log(context, f"🛒 Market Satış Yapıldı!\n👤 Kullanıcı: {q.from_user.first_name} ({uid})\n📦 Paket: {prod['name']}\n💰 Harcanan: {prod['price']} TL") return if q.data == "buy_vip": txt = "💰 BAKİYE YÜKLEME\n\nHesabınıza bakiye eklemek için bir yöntem seçin:" btns = [ [InlineKeyboardButton("🏦 Banka Havalesi / IBAN", callback_data="pay_iban")], [InlineKeyboardButton("🎮 Google Play Kod ile Yükle", callback_data="pay_playkod")], [InlineKeyboardButton("⬅️ Geri", callback_data="back_home")] ] await q.edit_message_text(txt, reply_markup=InlineKeyboardMarkup(btns)) return if q.data == "pay_iban": await q.edit_message_text( f"🏦 IBAN İLE ÖDEME\n\nIBAN: {VIP_IBAN}\n👤 İSİM: {VIP_AD_SOYAD}\n📝 AÇIKLAMA: {VIP_ACIKLAMA}\n\n📸 Dekontu bota gönderdikten sonra admin onayını bekleyin.", reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("⬅️ Geri", callback_data="buy_vip")]]) ) return if q.data == "pay_playkod": context.user_data["waiting_playkod"] = True await q.edit_message_text( "🎮 GOOGLE PLAY KOD GİRİŞİ\n\nGoogle Play hediye kartı kodunu buraya gönderin.\n\nSistem kodu doğrulanması için admine iletecek ve onaylandığında bakiyeniz anında yansıyacaktır.", reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("❌ İptal Et", callback_data="cancel_query")]]) ) return if q.data == "cancel_query": context.user_data.clear() context.user_data["user_list_page"] = 0 await q.edit_message_text("❌ İşlem iptal edildi.", reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("⬅️ Ana Menü", callback_data="back_home")]])) return if q.data == "ref_menu": count = db["ref_count"].get(uid_s, 0) bot = await context.bot.get_me() await q.edit_message_text( f"👥 REFERANS SİSTEMİ\n\n📊 Referans Sayısı: {count}/{REF_HEDIYE_SINIR}\n🔗 Link:\nhttps://t.me/{bot.username}?start={uid}", reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("⬅️ Geri", callback_data="back_home")]]) ) return # ===================== # BAYİ PANELİ # ===================== if q.data == "bayi_panel": if not is_reseller or is_admin: await q.answer("⛔ Bu alan sadece bayiler içindir!", show_alert=True) return txt = f"📊 BAYİ PANELİ\n" txt += "═" * 30 + "\n\n" txt += f"💰 Sizin Bakiyeniz: {get_balance(uid, db):.2f} TL\n\n" txt += "♾️ Sınırsız bakiye yükleme hakkınız vardır.\n" txt += "📌 Bayi olarak kullanıcılara sınırsız bakiye ekleyebilirsiniz." btns = [ [InlineKeyboardButton("💰 Bakiye Ekle (ID ile)", callback_data="reseller_add_balance")], [InlineKeyboardButton("⬅️ Geri", callback_data="back_home")] ] await q.edit_message_text(txt, reply_markup=InlineKeyboardMarkup(btns)) return # ===================== # ADMIN PANELİ # ===================== if q.data == "admin_panel": if not is_admin: await q.answer("⛔ Bu alan sadece admin içindir!", show_alert=True) return durum = "AÇIK ✅" if db["settings"]["active"] else "KAPALI ❌" banned_count = len(db.get("banned", [])) total_users = len(db["users"]) total_vips = len([u for u in db["vips"] if is_vip(int(u), db)]) total_resellers = len(db.get("resellers", [])) total_queries = sum([stats.get("total_queries", 0) for stats in db.get("user_stats", {}).values()]) txt = f"📊 ADMIN PANELİ\n" txt += "═" * 30 + "\n\n" txt += f"🟢 Bot Durumu: {durum}\n" txt += f"👥 Toplam Kullanıcı: {total_users}\n" txt += f"⭐ Toplam VIP: {total_vips}\n" txt += f"💼 Toplam Bayi: {total_resellers}\n" txt += f"🔒 Yasaklı Kullanıcı: {banned_count}\n" txt += f"📊 Toplam Sorgu: {total_queries}\n" txt += f"💰 Toplam Bakiye: {sum(db['balances'].values()):.2f} TL" btns = [ [InlineKeyboardButton("👥 Kullanıcı Listesi", callback_data="admin_user_list")], [InlineKeyboardButton("📈 Kullanıcı İstatistikleri", callback_data="admin_user_stats")], [InlineKeyboardButton("💰 Bakiye Yönetimi", callback_data="admin_balance_menu")], [InlineKeyboardButton("🚫 Ban/Kaldır", callback_data="admin_toggle_ban")], [InlineKeyboardButton("📢 Duyuru Yap", callback_data="make_announcement")], [InlineKeyboardButton(f"🔄 Botu {'KAPAT' if db['settings']['active'] else 'AÇ'}", callback_data="toggle_power")], [InlineKeyboardButton("📊 Sorgu Raporu", callback_data="admin_query_report")], [InlineKeyboardButton("⬅️ Geri", callback_data="back_home")] ] await q.edit_message_text(txt, reply_markup=InlineKeyboardMarkup(btns)) return # BAYİ BAKİYE EKLEME BUTONU if q.data == "reseller_add_balance": if not is_reseller and not is_admin: return context.user_data["reseller_balance_add"] = True back_callback = "bayi_panel" if is_reseller and not is_admin else "admin_panel" await q.edit_message_text( "💰 BAKİYE EKLEME (SINIRSIZ)\n\n" "Bakiye eklemek istediğiniz kullanıcının ID'sini ve miktarı aralarında boşluk bırakarak gönderin.\n\n" "Örnek: 7332455129 100\n\n" "♾️ NOT: Bu işlem sınırsızdır, kendi bakiyenizden düşmez!", reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("⬅️ Geri", callback_data=back_callback)]]) ) return # ===================== # ADMIN İŞLEMLERİ (Sadece admin) # ===================== if q.data == "admin_user_list": if not is_admin: return context.user_data["user_list_page"] = 0 await show_user_list(update, context, 0) return if q.data == "admin_search_user": if not is_admin: return context.user_data["admin_search_user"] = True await q.edit_message_text( "🔍 KULLANICI ARA\n\n" "Aramak istediğiniz kullanıcının ID'sini veya ismini gönderin:", reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("⬅️ Geri", callback_data="admin_user_list")]]) ) return # KULLANICI ARAMA İŞLEMİ (handle_all'de yapılıyor) if context.user_data.get("admin_search_user") and is_admin: # Bu kısım handle_all'de işleniyor pass if q.data == "admin_balance_menu": if not is_admin: return btns = [ [InlineKeyboardButton("➕ Bakiye Ekle/Çıkar", callback_data="admin_give_balance")], [InlineKeyboardButton("💰 Toplam Bakiye Raporu", callback_data="admin_total_balance")], [InlineKeyboardButton("⬅️ Geri", callback_data="admin_panel")] ] await q.edit_message_text("💰 Bakiye Yönetimi Menüsü", reply_markup=InlineKeyboardMarkup(btns)) return if q.data == "admin_total_balance": if not is_admin: return total_balance = sum(db['balances'].values()) top_users = sorted(db['balances'].items(), key=lambda x: x[1], reverse=True)[:5] txt = f"💰 Toplam Bakiye: {total_balance:.2f} TL\n\n" txt += "🏆 En Çok Bakiyesi Olan Kullanıcılar:\n" if top_users: for i, (user_id, balance) in enumerate(top_users, 1): name = db['users'].get(user_id, "Bilinmeyen") txt += f"{i}. {name} (ID: {user_id}): {balance:.2f} TL\n" else: txt += "Henüz hiç kullanıcı yok." await q.edit_message_text(txt, reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("⬅️ Geri", callback_data="admin_balance_menu")]])) return if q.data == "admin_user_stats": if not is_admin: return context.user_data["admin_view_user"] = "stats" await q.edit_message_text( "📈 Kullanıcı İstatistikleri\n\nİstatistiklerini görmek istediğiniz kullanıcının ID'sini gönderin:", reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("⬅️ Geri", callback_data="admin_panel")]]) ) return if q.data == "admin_query_report": if not is_admin: return query_types = {} for stats in db.get("user_stats", {}).values(): for q_type, count in stats.get("query_types", {}).items(): query_types[q_type] = query_types.get(q_type, 0) + count sorted_queries = sorted(query_types.items(), key=lambda x: x[1], reverse=True) txt = "📊 SORGU RAPORU\n\n" txt += "En Çok Kullanılan Sorgu Tipleri:\n" if sorted_queries: for i, (q_type, count) in enumerate(sorted_queries[:10], 1): txt += f"{i}. {q_type.upper()}: {count} sorgu\n" else: txt += "Henüz sorgu yapılmamış.\n" active_users = sorted(db.get("user_stats", {}).items(), key=lambda x: x[1].get("total_queries", 0), reverse=True)[:5] txt += "\n🔥 En Aktif Kullanıcılar:\n" if active_users: for i, (user_id, stats) in enumerate(active_users, 1): name = db['users'].get(user_id, "Bilinmeyen") txt += f"{i}. {name} (ID: {user_id}): {stats.get('total_queries', 0)} sorgu\n" else: txt += "Henüz sorgu yapılmamış.\n" await q.edit_message_text(txt, reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("⬅️ Geri", callback_data="admin_panel")]])) return if q.data == "admin_give_balance": if not is_admin: return context.user_data["admin_bakiye_state"] = "waiting_input" await q.edit_message_text( "💰 Bakiye Yönetimi\n\nBakiye eklemek istediğiniz kullanıcının ID'sini ve miktarı aralarında boşluk bırakarak gönderin.\n\nÖrnek: 7332455129 500\n\n(Eksiltmek için başına eksi koyun: 7332455129 -100)" ) return if q.data == "admin_toggle_ban": if not is_admin: return context.user_data["admin_ban_state"] = "waiting_input" await q.edit_message_text( "🚫 Ban Yönetimi\n\nBanlamak veya banını kaldırmak istediğiniz kullanıcının ID'sini gönderin:", reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("⬅️ Geri", callback_data="admin_panel")]]) ) return if q.data == "toggle_power": if not is_admin: return db["settings"]["active"] = not db["settings"]["active"] save_db(db) durum = "AÇIK ✅" if db["settings"]["active"] else "KAPALI ❌" await q.answer(f"Bot {durum} durumuna getirildi!", show_alert=True) q.data = "admin_panel" await callback(update, context) return if q.data == "make_announcement": if not is_admin: return context.user_data["waiting_announcement"] = True await q.edit_message_text( "📢 DUYURU\n\nGöndermek istediğiniz duyuru metnini yazın:", reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("⬅️ Geri", callback_data="admin_panel")]]) ) return if q.data.startswith("admin_balance_user_") and is_admin: target_id = q.data.split("admin_balance_user_")[1] context.user_data["admin_bakiye_state"] = "waiting_input" context.user_data["admin_target_user"] = target_id await q.edit_message_text( f"💰 {target_id} ID'li kullanıcıya bakiye işlemi\n\nEklemek veya çıkarmak istediğiniz miktarı yazın:\n(Örnek: 100 veya -50)" ) return if q.data.startswith("admin_ban_user_") and is_admin: target_id = q.data.split("admin_ban_user_")[1] db = load_db() if target_id in db.get("banned", []): db["banned"].remove(target_id) save_db(db) await q.answer(f"✅ {target_id} ID'li kullanıcının banı kaldırıldı!", show_alert=True) else: if "banned" not in db: db["banned"] = [] db["banned"].append(target_id) save_db(db) await q.answer(f"🚫 {target_id} ID'li kullanıcı banlandı!", show_alert=True) await show_user_detail(update, context, target_id) return if q.data.startswith("admin_vip_user_") and is_admin: target_id = q.data.split("admin_vip_user_")[1] db = load_db() db["vips"][target_id] = (datetime.datetime.now() + datetime.timedelta(days=30)).isoformat() save_db(db) await q.answer(f"✅ {target_id} ID'li kullanıcıya 30 günlük VIP verildi!", show_alert=True) try: await context.bot.send_message(chat_id=int(target_id), text="🎉 Admin tarafından 30 günlük VIP üyelik verildi!") except: pass await show_user_detail(update, context, target_id) return if q.data == "back_home": context.user_data.clear() context.user_data["user_list_page"] = 0 bakiye = get_balance(uid, db) txt = f"👋 Merhaba {q.from_user.first_name}!\n\n💰 Bakiyeniz: {bakiye:.2f} TL" vip_tarih_str = get_vip_remaining_string(uid, db) if vip_tarih_str: txt += f"\n⭐ Üyelik Durumu: {vip_tarih_str}" btns = [ [InlineKeyboardButton("🚀 Sorgular", callback_data="list"), InlineKeyboardButton("🛒 Market / VIP Al", callback_data="market_menu")], [InlineKeyboardButton("💰 Bakiye Yükle", callback_data="buy_vip"), InlineKeyboardButton("👥 Referans", callback_data="ref_menu")] ] if is_reseller and not is_admin: btns.append([InlineKeyboardButton("💼 Bayi Paneli", callback_data="bayi_panel")]) elif is_admin: btns.append([InlineKeyboardButton("💼 Admin Paneli", callback_data="admin_panel")]) await q.edit_message_text(txt, reply_markup=InlineKeyboardMarkup(btns)) return except Exception as e: logger.error(f"Callback hatası: {e}\n{traceback.format_exc()}") try: await q.edit_message_text("❌ Bir hata oluştu! Lütfen daha sonra tekrar deneyin.") except: pass # ---------------------- # HATA YAKALAYICI # ---------------------- async def error_handler(update, context): logger.error(f"Update {update} caused error: {context.error}") logger.error(traceback.format_exc()) try: if update and update.effective_message: await update.effective_message.reply_text("❌ Bir hata oluştu! Lütfen daha sonra tekrar deneyin.") except: pass if __name__ == "__main__": try: app = ApplicationBuilder().token(TOKEN).build() job_queue = app.job_queue if job_queue: job_queue.run_daily(reset_daily_limits, time=datetime.time(hour=0, minute=0, second=0)) app.add_handler(CommandHandler("start", start)) app.add_handler(CallbackQueryHandler(callback)) app.add_handler(MessageHandler(filters.TEXT | filters.PHOTO, handle_all)) app.add_error_handler(error_handler) print("=" * 50) print("✅ YXC BOT BAŞARIYLA BAŞLATILDI!") print("📊 BAYİ & ADMIN PANEL SÜRÜMÜ") print("=" * 50) app.run_polling() except Exception as e: print(f"❌ Bot başlatılamadı: {e}") print(traceback.format_exc())