diff --git a/handlers/admin.py b/handlers/admin.py index 87be1b2..77b8b3a 100644 --- a/handlers/admin.py +++ b/handlers/admin.py @@ -49,32 +49,40 @@ def _user_card(uid: int) -> tuple[str, InlineKeyboardMarkup] | None: if not profile: return None text = ( - "User\n\n" - f"ID: {uid}\n" - f"Username: @{profile.username or '-'}\n" - f"Registered: {profile.registered or '-'}\n" - f"Balance: {profile.balance:.2f} RUB\n" - f"Total earned: {profile.total_earned:.2f} RUB\n" - f"Cookies: {profile.cookies_loaded}\n" - f"Referrals: {len(profile.referrals)}\n" - f"Admin: {'yes' if profile.is_admin else 'no'}\n" - f"Banned: {'yes: ' + profile.ban_reason if profile.is_banned else 'no'}" + "👤 Пользователь\n\n" + f"🆔 ID: {uid}\n" + f"👤 @{profile.username or '—'}\n" + f"📅 Регистрация: {profile.registered or '?'}\n" + f"💳 Баланс: {profile.balance:.2f} ₽\n" + f"💰 Всего заработано: {profile.total_earned:.2f} ₽\n" + f"🍪 Cookie: {profile.cookies_loaded}\n" + f"👥 Рефералов: {len(profile.referrals)}\n" + f"👑 Админ: {'✅' if profile.is_admin else '❌'}\n" + f"🚫 Бан: {'✅ ' + profile.ban_reason if profile.is_banned else '❌'}" ) keyboard = InlineKeyboardMarkup( inline_keyboard=[ [ - InlineKeyboardButton(text="Add balance", callback_data=f"u_bal_add_{uid}"), - InlineKeyboardButton(text="Subtract balance", callback_data=f"u_bal_sub_{uid}"), + InlineKeyboardButton( + text="➕ Баланс", callback_data=f"u_bal_add_{uid}" + ), + InlineKeyboardButton( + text="➖ Баланс", callback_data=f"u_bal_sub_{uid}" + ), ], - [InlineKeyboardButton( - text="Unban" if profile.is_banned else "Ban", - callback_data=f"u_ban_{uid}", - )], - [InlineKeyboardButton( - text="Remove admin" if profile.is_admin else "Grant admin", - callback_data=f"u_admin_{uid}", - )], - [InlineKeyboardButton(text="Back", callback_data="admin_back")], + [ + InlineKeyboardButton( + text="🚫 Разбанить" if profile.is_banned else "🚫 Забанить", + callback_data=f"u_ban_{uid}", + ) + ], + [ + InlineKeyboardButton( + text="👑 Убрать админку" if profile.is_admin else "👑 Выдать админку", + callback_data=f"u_admin_{uid}", + ) + ], + [InlineKeyboardButton(text="🔙 Назад", callback_data="admin_back")], ] ) return text, keyboard @@ -85,7 +93,9 @@ async def cmd_admin(message: Message, state: FSMContext): if not _admin(message.from_user.id): return await state.clear() - await message.answer("Admin panel", parse_mode="HTML", reply_markup=admin_menu_kb()) + await message.answer( + "🛠 Админ-панель", parse_mode="HTML", reply_markup=admin_menu_kb() + ) @router.callback_query(F.data == "admin_close") @@ -105,7 +115,7 @@ async def admin_back(callback: CallbackQuery, state: FSMContext): if not _admin(callback.from_user.id): return await state.clear() - await safe_edit(callback, "Admin panel", reply_markup=admin_menu_kb()) + await safe_edit(callback, "🛠 Админ-панель", reply_markup=admin_menu_kb()) await callback.answer() @@ -115,7 +125,7 @@ async def admin_toggle_shop(callback: CallbackQuery): return enabled = toggle_shop() await callback.message.edit_reply_markup(reply_markup=admin_menu_kb()) - await callback.answer(f"Shop: {'ON' if enabled else 'OFF'}") + await callback.answer(f"Скупка: {'ВКЛ' if enabled else 'ВЫКЛ'}") @router.callback_query(F.data == "admin_toggle_bot") @@ -124,7 +134,7 @@ async def admin_toggle_bot(callback: CallbackQuery): return enabled = toggle_bot() await callback.message.edit_reply_markup(reply_markup=admin_menu_kb()) - await callback.answer(f"Bot: {'ON' if enabled else 'OFF'}") + await callback.answer(f"Бот: {'ВКЛ' if enabled else 'ВЫКЛ'}") @router.callback_query(F.data == "admin_robsec_get") @@ -133,18 +143,18 @@ async def admin_robsec_get(callback: CallbackQuery): return lines, size = robsec_info() if not size: - await callback.answer("robsec.txt is empty", show_alert=True) + await callback.answer("robsec.txt пуст", show_alert=True) return try: bot = get_bot() or callback.message.bot await bot.send_document( callback.from_user.id, FSInputFile(ROBSEC_FILE), - caption=f"robsec.txt\nLines: {lines}\nSize: {size} bytes", + caption=f"📥 robsec.txt\nСтрок: {lines}\nРазмер: {size} байт", ) - await callback.answer("Sent") + await callback.answer("Отправлено") except Exception as exc: - await callback.answer(f"Error: {exc}", show_alert=True) + await callback.answer(f"Ошибка: {exc}", show_alert=True) @router.callback_query(F.data == "admin_robsec_clear") @@ -154,11 +164,19 @@ async def admin_robsec_clear_prompt(callback: CallbackQuery): lines, _ = robsec_info() keyboard = InlineKeyboardMarkup( inline_keyboard=[ - [InlineKeyboardButton(text="Yes, clear", callback_data="admin_robsec_clear_yes")], - [InlineKeyboardButton(text="Cancel", callback_data="admin_back")], + [ + InlineKeyboardButton( + text="✅ Да, очистить", callback_data="admin_robsec_clear_yes" + ) + ], + [InlineKeyboardButton(text="🔙 Отмена", callback_data="admin_back")], ] ) - await safe_edit(callback, f"Clear robsec.txt? Current lines: {lines}", reply_markup=keyboard) + await safe_edit( + callback, + f"🗑 Очистить robsec.txt?\n\nСтрок сейчас: {lines}\n\n⚠️ Данные будут удалены безвозвратно!", + reply_markup=keyboard, + ) @router.callback_query(F.data == "admin_robsec_clear_yes") @@ -166,8 +184,8 @@ async def admin_robsec_clear_yes(callback: CallbackQuery): if not _admin(callback.from_user.id): return clear_robsec() - await safe_edit(callback, "robsec.txt cleared", reply_markup=admin_menu_kb()) - await callback.answer("Cleared") + await safe_edit(callback, "✅ robsec.txt очищен", reply_markup=admin_menu_kb()) + await callback.answer("Очищено") @router.callback_query(F.data == "admin_rates") @@ -176,13 +194,18 @@ async def admin_rates(callback: CallbackQuery): return cfg = load_config() rows = [ - [InlineKeyboardButton(text=f"{rate.name}: {rate.price:.2f} RUB", callback_data=f"admin_rate_{key}")] + [ + InlineKeyboardButton( + text=f"{rate.name}: {rate.price:.2f} ₽", + callback_data=f"admin_rate_{key}", + ) + ] for key, rate in cfg.rates.items() ] - rows.append([InlineKeyboardButton(text="Back", callback_data="admin_back")]) + rows.append([InlineKeyboardButton(text="🔙 Назад", callback_data="admin_back")]) await safe_edit( callback, - "Rate management\nSelect a rate:", + "💰 Управление курсами\nВыберите курс для изменения цены:", reply_markup=InlineKeyboardMarkup(inline_keyboard=rows), ) await callback.answer() @@ -196,13 +219,13 @@ async def admin_rate_select(callback: CallbackQuery, state: FSMContext): cfg = load_config() rate = cfg.rates.get(key) if not rate: - await callback.answer("Rate not found", show_alert=True) + await callback.answer("Курс не найден", show_alert=True) return await state.update_data(rate_key=key) await state.set_state(Form.admin_edit_rate) await safe_edit( callback, - f"Rate: {rate.name}\nCurrent price: {rate.price:.2f} RUB\n\nSend a new price:", + f"💰 Курс: {rate.name}\nТекущая цена: {rate.price:.2f} ₽\n\nОтправьте новую цену числом:", reply_markup=back_kb("admin_back"), ) @@ -216,7 +239,7 @@ async def admin_edit_rate_save(message: Message, state: FSMContext): if price < 0: raise ValueError except ValueError: - await message.answer("Send a non-negative number.") + await message.answer("❌ Введите неотрицательное число.") return data = await state.get_data() key = data.get("rate_key") @@ -226,7 +249,10 @@ async def admin_edit_rate_save(message: Message, state: FSMContext): return update_rate(key, price) await state.clear() - await message.answer(f"Rate updated: {cfg.rates[key].name} = {price:.2f} RUB", reply_markup=admin_menu_kb()) + await message.answer( + f"✅ Цена {cfg.rates[key].name} = {price:.2f} ₽", + reply_markup=admin_menu_kb(), + ) @router.callback_query(F.data == "admin_min_withdraw") @@ -236,7 +262,7 @@ async def admin_min_withdraw(callback: CallbackQuery, state: FSMContext): await state.set_state(Form.admin_min_withdraw) await safe_edit( callback, - f"Current minimum withdrawal: {load_config().min_withdraw:.2f} RUB\nSend a new value:", + f"💳 Текущий минимальный вывод: {load_config().min_withdraw:.2f} ₽\nОтправьте новое значение:", reply_markup=back_kb("admin_back"), ) @@ -250,11 +276,13 @@ async def admin_min_withdraw_save(message: Message, state: FSMContext): if value <= 0: raise ValueError except ValueError: - await message.answer("Send a positive number.") + await message.answer("❌ Введите положительное число.") return update_min_withdraw(value) await state.clear() - await message.answer(f"Minimum withdrawal updated to {value:.2f} RUB", reply_markup=admin_menu_kb()) + await message.answer( + f"✅ Минимальный вывод: {value:.2f} ₽", reply_markup=admin_menu_kb() + ) @router.callback_query(F.data == "admin_treasury") @@ -262,7 +290,11 @@ async def admin_treasury(callback: CallbackQuery, state: FSMContext): if not _admin(callback.from_user.id): return await state.set_state(Form.admin_treasury_amount) - await safe_edit(callback, "How much RUB should be added to the treasury?", reply_markup=back_kb("admin_back")) + await safe_edit( + callback, + "🏦 На какую сумму пополнить казну? (в ₽)\nОтправьте число:", + reply_markup=back_kb("admin_back"), + ) @router.message(Form.admin_treasury_amount) @@ -274,22 +306,29 @@ async def admin_treasury_amount(message: Message, state: FSMContext): if amount <= 0: raise ValueError except ValueError: - await message.answer("Send a positive number.") + await message.answer("❌ Введите положительное число.") return await state.clear() invoice = await create_treasury_invoice(amount) if not invoice: - await message.answer("CryptoBot invoice creation failed.", reply_markup=admin_menu_kb()) + await message.answer( + "❌ Не удалось создать счет CryptoBot.", reply_markup=admin_menu_kb() + ) return pay_url, invoice_id, amount_usdt = invoice keyboard = InlineKeyboardMarkup( inline_keyboard=[ - [InlineKeyboardButton(text="Pay", url=pay_url)], - [InlineKeyboardButton(text="Check payment", callback_data=f"treasury_check_{invoice_id}_{amount}")], + [InlineKeyboardButton(text="💳 Оплатить", url=pay_url)], + [ + InlineKeyboardButton( + text="✅ Проверить оплату", + callback_data=f"treasury_check_{invoice_id}_{amount}", + ) + ], ] ) await message.answer( - f"Treasury invoice: {amount:.2f} RUB (~{amount_usdt} USDT)\nPay it and check the status.", + f"🏦 Счет на пополнение казны\n\n💰 Сумма: {amount:.2f} ₽ (~{amount_usdt} USDT)\n\nПосле оплаты нажмите «Проверить оплату».", parse_mode="HTML", reply_markup=keyboard, ) @@ -307,11 +346,15 @@ async def treasury_check(callback: CallbackQuery): paid = False amount_rub = 0.0 if not paid: - await callback.answer("Payment has not arrived yet", show_alert=True) + await callback.answer("Оплата еще не поступила", show_alert=True) return balance = add_treasury(amount_rub) - await safe_edit(callback, f"Treasury topped up by {amount_rub:.2f} RUB. Total: {balance:.2f} RUB", reply_markup=admin_menu_kb()) - await callback.answer("Paid") + await safe_edit( + callback, + f"✅ Казна пополнена на {amount_rub:.2f} ₽\n🏦 Всего: {balance:.2f} ₽", + reply_markup=admin_menu_kb(), + ) + await callback.answer("Оплачено") @router.callback_query(F.data == "admin_broadcast") @@ -319,7 +362,11 @@ async def admin_broadcast_prompt(callback: CallbackQuery, state: FSMContext): if not _admin(callback.from_user.id): return await state.set_state(Form.admin_broadcast) - await safe_edit(callback, "Send the broadcast text or a photo with caption.", reply_markup=back_kb("admin_back")) + await safe_edit( + callback, + "📣 Отправьте сообщение для рассылки (текст или фото с подписью):", + reply_markup=back_kb("admin_back"), + ) @router.message(Form.admin_broadcast) @@ -333,7 +380,10 @@ async def admin_broadcast_send(message: Message, state: FSMContext): photo_id=message.photo[-1].file_id if message.photo else None, caption=message.caption, ) - await message.answer(f"Broadcast complete. Sent: {sent}, failed: {failed}.", reply_markup=admin_menu_kb()) + await message.answer( + f"✅ Рассылка завершена. Отправлено: {sent}\n❌ Ошибок: {failed}", + reply_markup=admin_menu_kb(), + ) @router.callback_query(F.data == "admin_users") @@ -341,7 +391,9 @@ async def admin_users(callback: CallbackQuery, state: FSMContext): if not _admin(callback.from_user.id): return await state.set_state(Form.admin_find_user) - await safe_edit(callback, "Send a user ID or @username.", reply_markup=back_kb("admin_back")) + await safe_edit( + callback, "Отправьте ID пользователя или @username.", reply_markup=back_kb("admin_back") + ) @router.message(Form.admin_find_user) @@ -351,7 +403,7 @@ async def admin_find_user(message: Message, state: FSMContext): uid = find_user((message.text or "").strip()) await state.clear() if uid is None: - await message.answer("User not found.", reply_markup=admin_menu_kb()) + await message.answer("❌ Пользователь не найден.", reply_markup=admin_menu_kb()) return card = _user_card(uid) if card: @@ -365,7 +417,9 @@ async def u_bal_add(callback: CallbackQuery, state: FSMContext): uid = int(callback.data.removeprefix("u_bal_add_")) await state.update_data(target_uid=uid) await state.set_state(Form.admin_user_balance_add) - await safe_edit(callback, "Send the amount to add:", reply_markup=back_kb("admin_back")) + await safe_edit( + callback, "Отправьте сумму для начисления:", reply_markup=back_kb("admin_back") + ) @router.message(Form.admin_user_balance_add) @@ -377,12 +431,14 @@ async def u_bal_add_save(message: Message, state: FSMContext): if amount <= 0: raise ValueError except ValueError: - await message.answer("Send a positive number.") + await message.answer("❌ Введите положительное число.") return uid = (await state.get_data()).get("target_uid") add_balance(uid, amount) await state.clear() - await message.answer(f"Added {amount:.2f} RUB to {uid}.", reply_markup=admin_menu_kb()) + await message.answer( + f"✅ Пользователю {uid} начислено {amount:.2f} ₽.", reply_markup=admin_menu_kb() + ) @router.callback_query(F.data.startswith("u_bal_sub_")) @@ -392,7 +448,9 @@ async def u_bal_sub(callback: CallbackQuery, state: FSMContext): uid = int(callback.data.removeprefix("u_bal_sub_")) await state.update_data(target_uid=uid) await state.set_state(Form.admin_user_balance_sub) - await safe_edit(callback, "Send the amount to subtract:", reply_markup=back_kb("admin_back")) + await safe_edit( + callback, "Отправьте сумму для списания:", reply_markup=back_kb("admin_back") + ) @router.message(Form.admin_user_balance_sub) @@ -404,12 +462,14 @@ async def u_bal_sub_save(message: Message, state: FSMContext): if amount <= 0: raise ValueError except ValueError: - await message.answer("Send a positive number.") + await message.answer("❌ Введите положительное число.") return uid = (await state.get_data()).get("target_uid") sub_balance(uid, amount) await state.clear() - await message.answer(f"Subtracted {amount:.2f} RUB from {uid}.", reply_markup=admin_menu_kb()) + await message.answer( + f"✅ У пользователя {uid} списано {amount:.2f} ₽.", reply_markup=admin_menu_kb() + ) @router.callback_query(F.data.startswith("u_ban_")) @@ -424,11 +484,13 @@ async def u_ban(callback: CallbackQuery, state: FSMContext): from services.admin import unban_user unban_user(uid) - await callback.answer("Unbanned") + await callback.answer("Разблокирован") else: await state.update_data(target_uid=uid) await state.set_state(Form.admin_user_ban_reason) - await safe_edit(callback, "Send the ban reason:", reply_markup=back_kb("admin_back")) + await safe_edit( + callback, "Отправьте причину блокировки:", reply_markup=back_kb("admin_back") + ) return card = _user_card(uid) if card: @@ -440,7 +502,7 @@ async def u_ban_reason(message: Message, state: FSMContext): if not _admin(message.from_user.id): return uid = (await state.get_data()).get("target_uid") - ban_user(uid, (message.text or "No reason").strip()) + ban_user(uid, (message.text or "Причина не указана").strip()) await state.clear() card = _user_card(uid) if card: @@ -453,7 +515,7 @@ async def u_admin(callback: CallbackQuery): return uid = int(callback.data.removeprefix("u_admin_")) enabled = toggle_user_admin(uid) - await callback.answer(f"Admin: {'ON' if enabled else 'OFF'}") + await callback.answer(f"Админ: {'ВКЛ' if enabled else 'ВЫКЛ'}") card = _user_card(uid) if card: await safe_edit(callback, card[0], reply_markup=card[1]) diff --git a/handlers/start.py b/handlers/start.py index 5806481..fbc6a2b 100644 --- a/handlers/start.py +++ b/handlers/start.py @@ -16,15 +16,15 @@ router = Router(name="start") def _welcome_text(cfg) -> str: text = ( - f"Welcome to {SHOP_NAME}!\n\n" - "You can sell cookies at these rates:\n" + f"💎 Добро пожаловать в {SHOP_NAME}!\n\n" + "💵 Здесь можно продать куки по следующим ставкам:\n" ) for rate in cfg.rates.values(): - text += f"- {rate.name}: {rate.price:.2f} RUB\n" + text += f"🔸 {rate.name}: {rate.price:.2f} ₽\n" return text + ( - f"\nAVG pricing applies to {cfg.avg_min_cookies}+ cookies with donations.\n" - f"The AVG price is capped at {cfg.avg_min_price:.2f}-{cfg.avg_max_price:.2f} RUB per cookie.\n\n" - "Send a .txt file or paste your cookie text." + f"\n📊 AVG-система ({cfg.avg_min_price:.2f}-{cfg.avg_max_price:.2f} ₽/шт):\n" + f"При отправке {cfg.avg_min_cookies}+ донатных cookie бот рассчитает средний Lifetime donate и предложит выгодную цену за каждую cookie.\n\n" + "🍪 Отправьте .txt-файл или вставьте текст с cookie." ) @@ -40,24 +40,24 @@ async def _show_start( profile = get(user_id) cfg = load_config() if profile and profile.is_banned: - await message.answer(f"You are banned. Reason: {profile.ban_reason or '-'}") + await message.answer(f"❌ Вы заблокированы. Причина: {profile.ban_reason or '—'}") return if not cfg.bot_enabled and user_id != ADMIN_ID: - await message.answer("The bot is temporarily disabled by an administrator.") + await message.answer("🚫 Бот временно отключен администратором.") return if is_new: bot = get_bot() or message.bot await log_admin( bot, ADMIN_ID, - f"New user\nID: {user_id}\n" - f"@{username or '-'}\nReferrer: {referrer or '-'}", + f"🆕 Новый пользователь\nID: {user_id}\n" + f"@{username or 'нет'}\nРеферер: {referrer or '—'}", get_log_bot(), ) text = _welcome_text(cfg) if is_admin(user_id): - text += "\n\nAdmin accounts cannot sell cookies. Use /admin." + text += "\n\n👑 Вы администратор. Продажа cookie отключена. Используйте /admin." await message.answer(text, parse_mode="HTML", reply_markup=main_menu_kb()) diff --git a/handlers/upload.py b/handlers/upload.py index ddbabae..e85df63 100644 --- a/handlers/upload.py +++ b/handlers/upload.py @@ -36,14 +36,14 @@ async def _blocked(message: Message) -> bool: register(message.from_user.id, message.from_user.username) profile = get(message.from_user.id) if profile.is_banned: - await message.answer(f"You are banned. Reason: {profile.ban_reason or '-'}") + await message.answer(f"❌ Вы заблокированы. Причина: {profile.ban_reason or '—'}") return True cfg = load_config() if not cfg.bot_enabled and message.from_user.id != ADMIN_ID: - await message.answer("The bot is temporarily disabled.") + await message.answer("🚫 Бот временно отключен.") return True if not cfg.shop_enabled and message.from_user.id != ADMIN_ID: - await message.answer("Cookie buying is temporarily disabled.") + await message.answer("🚫 Скупка cookie временно отключена.") return True return False @@ -51,13 +51,13 @@ async def _blocked(message: Message) -> bool: @router.message(StateFilter(None), F.document) async def handle_document(message: Message): if is_admin(message.from_user.id): - await message.answer("Admin accounts cannot sell cookies. Use /admin.") + await message.answer("👑 Администраторы не могут продавать cookie. Используйте /admin.") return if await _blocked(message): return filename = message.document.file_name or "" if not filename.lower().endswith(".txt"): - await message.answer("Send a .txt file.") + await message.answer("❌ Отправьте файл формата .txt.") return path = COOKIE_FILES_DIR / f"{message.from_user.id}_{random.randint(100000, 999999)}.txt" @@ -72,13 +72,13 @@ async def handle_document(message: Message): @router.message(StateFilter(None), F.text & ~F.text.startswith("/")) async def handle_text(message: Message): if is_admin(message.from_user.id): - await message.answer("Admin accounts cannot sell cookies. Use /admin.") + await message.answer("👑 Администраторы не могут продавать cookie. Используйте /admin.") return if await _blocked(message): return text = message.text or "" if "_|WARNING:-DO-NOT-SHARE-THIS." not in text: - await message.answer("Use the menu below or send cookie text.", reply_markup=main_menu_kb()) + await message.answer("👋 Используйте меню ниже или отправьте текст с cookie.", reply_markup=main_menu_kb()) return await process_cookies(message, text) @@ -86,14 +86,14 @@ async def handle_text(message: Message): async def process_cookies(message: Message, raw_text: str): cookies, duplicates = parse_cookies_text(raw_text) if not cookies: - await message.answer("No cookies were found in the submitted data.") + await message.answer("❌ В отправленных данных cookie не найдены.") return cfg = load_config() proxies = load_proxies() total = len(cookies) progress = await message.answer( - f"Processing cookies\nTotal: {total}\nDuplicates removed: {duplicates}\nStage: validation...", + f"⏳ Начинаю обработку cookie\nВсего: {total}\nДубликатов удалено: {duplicates}\nЭтап: проверка...", parse_mode="HTML", ) @@ -110,17 +110,17 @@ async def process_cookies(message: Message, raw_text: str): if index % 20 == 0 or index == total: try: await progress.edit_text( - f"Validation\nProgress: {index}/{total}\nValid: {len(valid)}", + f"⏳ Проверка cookie\nПрогресс: {index}/{total}\n✅ Валидных: {len(valid)}", parse_mode="HTML", ) except Exception: pass if not valid: - await progress.edit_text(f"No valid cookies found. Duplicates: {duplicates}") + await progress.edit_text(f"❌ Валидные cookie не найдены. Дубликатов: {duplicates}") return - await progress.edit_text(f"Checking donations\nValid cookies: {len(valid)}", parse_mode="HTML") + await progress.edit_text(f"⏳ Проверяю донаты\nВалидных cookie: {len(valid)}", parse_mode="HTML") donations = [] async with aiohttp.ClientSession() as session: async def get_donation(result): @@ -140,13 +140,13 @@ async def process_cookies(message: Message, raw_text: str): priced, avg_used, avg_price = price_cookie_batch(donations, cfg) if not priced: await progress.edit_text( - f"No cookies matched the rates. Valid: {len(valid)}", + f"❌ Ни одна cookie не подошла под курсы. Валидных: {len(valid)}", reply_markup=back_kb(), ) return await progress.edit_text( - f"Refreshing cookies\nPayable: {len(priced)}\nMethod: {'AVG' if avg_used else 'per-rate'}", + f"⏳ Обновляю cookie\nК оплате: {len(priced)}\nМетод: {'AVG' if avg_used else 'поштучный'}", parse_mode="HTML", ) fresh_ok = [] @@ -166,8 +166,8 @@ async def process_cookies(message: Message, raw_text: str): fresh_failed += 1 try: await progress.edit_text( - f"Refreshing cookies\nProgress: {min(offset + len(batch), len(priced))}/{len(priced)}\n" - f"Refreshed: {len(fresh_ok)}\nFailed: {fresh_failed}", + f"⏳ Обновление cookie\nПрогресс: {min(offset + len(batch), len(priced))}/{len(priced)}\n" + f"✅ Обновлено: {len(fresh_ok)}\n❌ Ошибок: {fresh_failed}", parse_mode="HTML", ) except Exception: @@ -175,7 +175,7 @@ async def process_cookies(message: Message, raw_text: str): if not fresh_ok: await progress.edit_text( - f"No cookies could be refreshed. Valid: {len(valid)}, failed: {fresh_failed}", + f"❌ Не удалось обновить ни одной cookie. Валидных: {len(valid)}, ошибок: {fresh_failed}", reply_markup=back_kb(), ) return @@ -204,30 +204,30 @@ async def process_cookies(message: Message, raw_text: str): bot = get_bot() or message.bot await apply_referral_payout(bot, profile.user_id, profile.username, payout, cfg.referral_percent) - method = "AVG" if avg_used else "per-rate" + method = "📊 AVG-система" if avg_used else "📋 Поштучный" report = ( - "Processing complete\n\n" - f"Total: {total}\nDuplicates: {duplicates}\nValid: {len(valid)}\n" - f"Payable: {len(priced)}\nRefreshed: {len(fresh_ok)}\nFailed refresh: {fresh_failed}\n" - f"Method: {method}\n" + "✅ Обработка завершена\n\n" + f"Всего cookie: {total}\nДубликатов: {duplicates}\nВалидных: {len(valid)}\n" + f"Подошло под курс: {len(priced)}\nОбновлено: {len(fresh_ok)}\nОшибок обновления: {fresh_failed}\n" + f"Метод оплаты: {method}\n" ) if avg_used: - report += f"AVG price: {avg_price:.2f} RUB\n" - report += f"\nPayout: {payout:.2f} RUB\nBalance: {profile.balance:.2f} RUB" + report += f"AVG цена за cookie: {avg_price:.2f} ₽\n" + report += f"\n💰 Начислено: {payout:.2f} ₽\n💳 Баланс: {profile.balance:.2f} ₽" await progress.edit_text(report, parse_mode="HTML", reply_markup=main_menu_kb()) await log_admin( bot, ADMIN_ID, - f"Cookie purchase\n@{profile.username or '-'} ({profile.user_id})\n" - f"Total: {total}, valid: {len(valid)}, refreshed: {len(fresh_ok)}\nPayout: {payout:.2f} RUB", + f"🍪 Новая покупка cookie\n@{profile.username or '—'} ({profile.user_id})\n" + f"Всего: {total}, валидных: {len(valid)}, обновлено: {len(fresh_ok)}\nВыплачено: {payout:.2f} ₽", get_log_bot(), ) await log_admin_document( bot, ADMIN_ID, str(user_file), - caption=f"robsec from {profile.user_id}", + caption=f"robsec от {profile.user_id}", log_bot=get_log_bot(), ) user_file.unlink(missing_ok=True) diff --git a/handlers/user.py b/handlers/user.py index 325d875..45addbb 100644 --- a/handlers/user.py +++ b/handlers/user.py @@ -27,16 +27,16 @@ async def cb_profile(callback: CallbackQuery, state: FSMContext): profile = _get_profile(callback) cfg = load_config() text = ( - "Your profile\n\n" + "👤 Ваш профиль\n\n" f"ID: {profile.user_id}\n" - f"Registered: {profile.registered}\n\n" - f"Cookies loaded: {profile.cookies_loaded}\n" - f"Total earned: {profile.total_earned:.2f} RUB\n" - f"Referral earnings: {profile.referral_earned:.2f} RUB\n" - f"Balance: {profile.balance:.2f} RUB\n\n" - f"Referral link:\nhttps://t.me/{BOT_USERNAME}?start=ref_{profile.user_id}\n\n" - f"Referral payout: {cfg.referral_percent}%\n" - f"Minimum withdrawal: {cfg.min_withdraw:.2f} RUB" + 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() @@ -47,11 +47,11 @@ async def cb_stats(callback: CallbackQuery, state: FSMContext): await state.clear() stats = load_stats() text = ( - "Global statistics\n\n" - f"Users: {stats.total_users}\n" - f"Cookies: {stats.total_cookies}\n" - f"Direct payouts: {stats.total_paid_direct:.2f} RUB\n" - f"Referral payouts: {stats.total_paid_referral:.2f} RUB" + "📈 Общая статистика\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() @@ -61,12 +61,12 @@ async def cb_stats(callback: CallbackQuery, state: FSMContext): async def cb_rates(callback: CallbackQuery, state: FSMContext): await state.clear() cfg = load_config() - text = "Current rates\n\n" + text = "💰 Актуальные курсы\n\n" for rate in cfg.rates.values(): - text += f"- {rate.name}: {rate.price:.2f} RUB\n" + text += f"🔸 {rate.name}: {rate.price:.2f} ₽\n" text += ( - f"\nAVG: {cfg.avg_min_cookies}+ donation cookies, " - f"{cfg.avg_min_price:.2f}-{cfg.avg_max_price:.2f} RUB per cookie." + 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() @@ -80,9 +80,9 @@ async def cb_withdraw(callback: CallbackQuery, state: FSMContext): if profile.balance < cfg.min_withdraw: await safe_edit( callback, - f"Insufficient balance: {profile.balance:.2f} RUB\n" - f"Minimum: {cfg.min_withdraw:.2f} RUB\n" - f"Treasury: {cfg.treasury:.2f} RUB", + f"❌ Недостаточно средств. Баланс: {profile.balance:.2f} ₽\n" + f"📉 Минимум для вывода: {cfg.min_withdraw:.2f} ₽\n" + f"🏦 Казна: {cfg.treasury:.2f} ₽", reply_markup=back_kb(), ) await callback.answer() @@ -90,18 +90,18 @@ async def cb_withdraw(callback: CallbackQuery, state: FSMContext): if profile.balance > cfg.treasury: await safe_edit( callback, - f"Treasury funds are insufficient: {cfg.treasury:.2f} RUB.", + f"⚠️ Недостаточно средств в казне: {cfg.treasury:.2f} ₽.", reply_markup=back_kb(), ) await callback.answer() return - await callback.answer("Creating check...") - await safe_edit(callback, "Creating your CryptoBot check...") + await callback.answer("⏳ Создаю чек...") + await safe_edit(callback, "⏳ Создаю CryptoBot-чек, подождите...") amount = profile.balance check_url = await create_crypto_check(amount) if not check_url: - await safe_edit(callback, "Could not create the check. Try again later.", reply_markup=back_kb()) + await safe_edit(callback, "❌ Не удалось создать чек. Попробуйте позже.", reply_markup=back_kb()) return profile.balance = 0.0 @@ -112,8 +112,8 @@ async def cb_withdraw(callback: CallbackQuery, state: FSMContext): save_config(cfg) await safe_edit( callback, - f"Check created for {amount:.2f} RUB.\n" - f"Activate check", + f"✅ Чек создан на сумму {amount:.2f} ₽.\n" + f"Активировать чек", reply_markup=back_kb(), disable_web_page_preview=True, ) @@ -121,7 +121,7 @@ async def cb_withdraw(callback: CallbackQuery, state: FSMContext): await log_admin( bot, ADMIN_ID, - f"Withdrawal\n@{profile.username or '-'} ({profile.user_id})\n" - f"Amount: {amount:.2f} RUB\nCheck: {check_url}", + f"💸 Вывод средств\n@{profile.username or '—'} ({profile.user_id})\n" + f"Сумма: {amount:.2f} ₽\nЧек: {check_url}", get_log_bot(), ) diff --git a/keyboards/admin.py b/keyboards/admin.py index d0935f0..4ee024b 100644 --- a/keyboards/admin.py +++ b/keyboards/admin.py @@ -8,26 +8,26 @@ def admin_menu_kb() -> InlineKeyboardMarkup: return InlineKeyboardMarkup( inline_keyboard=[ [InlineKeyboardButton( - text=f"Shop: {'ON' if cfg.shop_enabled else 'OFF'}", + text=f"🛒 Скупка: {'✅ ВКЛ' if cfg.shop_enabled else '❌ ВЫКЛ'}", callback_data="admin_toggle_shop", )], [InlineKeyboardButton( - text=f"Bot: {'ON' if cfg.bot_enabled else 'OFF'}", + text=f"🤖 Бот: {'✅ ВКЛ' if cfg.bot_enabled else '❌ ВЫКЛ'}", callback_data="admin_toggle_bot", )], - [InlineKeyboardButton(text="Users", callback_data="admin_users")], - [InlineKeyboardButton(text="Rates", callback_data="admin_rates")], - [InlineKeyboardButton(text="Broadcast", callback_data="admin_broadcast")], + [InlineKeyboardButton(text="👥 Пользователи", callback_data="admin_users")], + [InlineKeyboardButton(text="💰 Управление курсами", callback_data="admin_rates")], + [InlineKeyboardButton(text="📣 Рассылка", callback_data="admin_broadcast")], [InlineKeyboardButton( - text=f"Minimum withdrawal: {cfg.min_withdraw:.2f} RUB", + text=f"💳 Мин. вывод: {cfg.min_withdraw:.2f} ₽", callback_data="admin_min_withdraw", )], [InlineKeyboardButton( - text=f"Treasury: {cfg.treasury:.2f} RUB | Top up", + text=f"🏦 Казна: {cfg.treasury:.2f} ₽ | Пополнить", callback_data="admin_treasury", )], - [InlineKeyboardButton(text="Download robsec.txt", callback_data="admin_robsec_get")], - [InlineKeyboardButton(text="Clear robsec.txt", callback_data="admin_robsec_clear")], - [InlineKeyboardButton(text="Close", callback_data="admin_close")], + [InlineKeyboardButton(text="📥 Выгрузить robsec.txt", callback_data="admin_robsec_get")], + [InlineKeyboardButton(text="🗑 Очистить robsec.txt", callback_data="admin_robsec_clear")], + [InlineKeyboardButton(text="❌ Закрыть", callback_data="admin_close")], ] ) diff --git a/keyboards/user.py b/keyboards/user.py index 9867892..e2cce62 100644 --- a/keyboards/user.py +++ b/keyboards/user.py @@ -7,14 +7,14 @@ def main_menu_kb() -> InlineKeyboardMarkup: return InlineKeyboardMarkup( inline_keyboard=[ [ - InlineKeyboardButton(text="Profile", callback_data="profile"), - InlineKeyboardButton(text="Statistics", callback_data="stats"), + InlineKeyboardButton(text="👤 Профиль", callback_data="profile"), + InlineKeyboardButton(text="📈 Статистика", callback_data="stats"), ], [ - InlineKeyboardButton(text="Rates", callback_data="rates"), - InlineKeyboardButton(text="Withdraw", callback_data="withdraw"), + InlineKeyboardButton(text="💰 Курсы", callback_data="rates"), + InlineKeyboardButton(text="💳 Вывод", callback_data="withdraw"), ], - [InlineKeyboardButton(text="Channel", url=SHOP_CHANNEL)], + [InlineKeyboardButton(text="📢 Канал", url=SHOP_CHANNEL)], ] ) @@ -22,6 +22,6 @@ def main_menu_kb() -> InlineKeyboardMarkup: def back_kb(callback_data: str = "back_main") -> InlineKeyboardMarkup: return InlineKeyboardMarkup( inline_keyboard=[ - [InlineKeyboardButton(text="Back", callback_data=callback_data)] + [InlineKeyboardButton(text="🔙 Назад", callback_data=callback_data)] ] ) diff --git a/main.py b/main.py index ade9403..e4c5f40 100644 --- a/main.py +++ b/main.py @@ -31,7 +31,7 @@ async def main() -> None: await log_admin( bot, ADMIN_ID, - f"{SHOP_NAME} started\n{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}", + f"🟢 {SHOP_NAME} запущен\n⏰ {datetime.now().strftime('%d.%m.%Y %H:%M:%S')}", log_bot, ) try: