from aiogram import F, Router from aiogram.fsm.context import FSMContext from aiogram.types import LinkPreviewOptions, CallbackQuery, Message from aiogram.fsm.state import State, StatesGroup from config import ADMIN_ID, BOT_USERNAME from db.storage import load_config, load_stats, save_config from db.users import get, register, save from keyboards.user import back_kb, activate_kb from runtime import get_bot, get_log_bot from services.withdrawals import create_crypto_check from utils.logging import log_admin, safe_edit router = Router(name="user") class WithdrawState(StatesGroup): waiting_for_amount = State() def _get_profile(callback: CallbackQuery): profile = get(callback.from_user.id) if profile is None: register(callback.from_user.id, callback.from_user.username) profile = get(callback.from_user.id) return profile @router.callback_query(F.data == "profile") async def cb_profile(callback: CallbackQuery, state: FSMContext): await state.clear() profile = _get_profile(callback) cfg = load_config() text = ( "👤 Ваш профиль\n\n" f"ID: {profile.user_id}\n" f"📅 Дата регистрации: {profile.registered}\n\n" f"🍪 Загружено cookie: {profile.cookies_loaded}\n" f"💰 Заработано всего: {profile.total_earned:.2f} ₽\n" f"💸 С рефералов: {profile.referral_earned:.2f} ₽\n" f"💳 Текущий баланс: {profile.balance:.2f} ₽\n\n" f"🔗 Ваша реферальная ссылка:\nhttps://t.me/{BOT_USERNAME}?start=ref_{profile.user_id}\n\n" f"💡 Реферальный процент: {cfg.referral_percent}%\n" f"💳 Минимальный вывод: {cfg.min_withdraw:.2f} ₽" ) await safe_edit(callback, text, reply_markup=back_kb()) await callback.answer() @router.callback_query(F.data == "stats") async def cb_stats(callback: CallbackQuery, state: FSMContext): await state.clear() stats = load_stats() text = ( "📈 Общая статистика\n\n" f"👥 Пользователей: {stats.total_users}\n" f"🍪 Всего cookie: {stats.total_cookies}\n" f"💰 Прямых выплат: {stats.total_paid_direct:.2f} ₽\n" f"💸 Реферальных выплат: {stats.total_paid_referral:.2f} ₽" ) await safe_edit(callback, text, reply_markup=back_kb()) await callback.answer() @router.callback_query(F.data == "rates") async def cb_rates(callback: CallbackQuery, state: FSMContext): await state.clear() cfg = load_config() text = "💰 Актуальные курсы\n\n" for rate in cfg.rates.values(): text += f"🔸 {rate.name}: {rate.price:.2f} ₽\n" text += ( f"\n📊 AVG-система (от {cfg.avg_min_cookies}+ донатных cookie):\n" f"Цена за cookie: {cfg.avg_min_price:.2f}-{cfg.avg_max_price:.2f} ₽." ) await safe_edit(callback, text, reply_markup=back_kb()) await callback.answer() @router.callback_query(F.data == "withdraw") async def cb_withdraw(callback: CallbackQuery, state: FSMContext): await state.clear() profile = _get_profile(callback) cfg = load_config() if profile.balance < cfg.min_withdraw: await safe_edit( callback, f"❌ Недостаточно средств. Баланс: {profile.balance:.2f} ₽\n" f"📉 Минимум для вывода: {cfg.min_withdraw:.2f} ₽\n" f"🏦 Казна: {cfg.treasury:.2f} ₽", reply_markup=back_kb(), ) await callback.answer() return await safe_edit( callback, f"💳 Вывод средств\n\n" f"Ваш баланс: {profile.balance:.2f} ₽\n" f"Минимум: {cfg.min_withdraw:.2f} ₽\n\n" f"Введите сумму для вывода:", reply_markup=back_kb(), ) await state.set_state(WithdrawState.waiting_for_amount) await callback.answer() @router.message(WithdrawState.waiting_for_amount) async def process_withdraw_amount(message: Message, state: FSMContext): profile = _get_profile(message) cfg = load_config() try: amount = float(message.text) except ValueError: await message.answer("❌ Введите корректную сумму числом.") return if amount <= 0: await message.answer("❌ Сумма должна быть больше нуля.") return if amount < cfg.min_withdraw: await message.answer(f"❌ Минимум для вывода: {cfg.min_withdraw:.2f} ₽.") return if amount > profile.balance: await message.answer( f"❌ Недостаточно средств. Ваш баланс: {profile.balance:.2f} ₽." ) return if amount > cfg.treasury: await message.answer( f"❌ Недостаточно средств в казне: {cfg.treasury:.2f} ₽." ) return await state.clear() await message.answer("⏳ Создаю CryptoBot-чек, подождите...") check_url, check_image_url = await create_crypto_check(amount) if not check_url: await message.answer( "❌ Не удалось создать чек. Попробуйте позже.", reply_markup=back_kb(), ) return profile.balance -= amount save(profile.user_id, profile) cfg.treasury = max(0.0, cfg.treasury - amount) save_config(cfg) await message.answer( text=f"🦋 Чек на {amount:.2f} ₽.", reply_markup=activate_kb(url=check_url, amount=amount), link_preview_options=LinkPreviewOptions( url=check_image_url, show_above_text=True ), ) bot = get_bot() or message.bot await log_admin( bot, ADMIN_ID, f"💸 Вывод средств\n@{profile.username or '—'} ({profile.user_id})\n" f"Сумма: {amount:.2f} ₽\nЧек: {check_url}", get_log_bot(), )