feat(bot): add bot account ownership and balance

This commit is contained in:
2026-07-24 10:44:48 +05:00
parent 87385228ea
commit 8bd5c80693
22 changed files with 1008 additions and 393 deletions
+177
View File
@@ -0,0 +1,177 @@
from aiogram import Router
from aiogram.filters import Command
from aiogram.fsm.context import FSMContext
from aiogram.types import CallbackQuery, Message
from bot.config import ADMIN_ID
from bot.states import AdminFlow
from bot.filters import AdminCallbackFilter, AdminFilter
from bot.ui.keyboards import admin_keyboard, back_keyboard, admin_profile_keyboard
from bot.services.balance import (
BalanceError,
change_user_balance,
get_bot_slot_price,
get_user_profile,
set_bot_slot_price,
)
router = Router()
@router.message(Command("admin"), AdminFilter())
async def admin_menu(message: Message, state: FSMContext) -> None:
await state.clear()
await message.answer("🤵 <b>Админ-панель</b>", reply_markup=admin_keyboard())
@router.callback_query(lambda c: c.data == "admin_panel", AdminCallbackFilter())
async def admin_panel(callback: CallbackQuery, state: FSMContext) -> None:
await state.clear()
await callback.answer()
await callback.message.edit_text(
"🤵 <b>Админ-панель</b>", reply_markup=admin_keyboard()
)
@router.callback_query(
AdminCallbackFilter(), lambda c: c.data.startswith("admin_lookup")
)
async def admin_lookup_prompt(callback: CallbackQuery, state: FSMContext) -> None:
user_id = None
try:
user_id = int(callback.data.split(":")[1])
except:
pass
if user_id:
try:
if user_id <= 0:
raise ValueError
_, balance, bot_count = await get_user_profile(user_id)
except (ValueError, TypeError):
await callback.message.edit_text("❌ Некорректный Telegram ID")
return
await callback.message.edit_text(
f"👤 <b>Профиль</b>\n\n"
f"🆔: <code>{user_id}</code>\n"
f"💰 Баланс: <code>{balance}</code> ₽\n"
f"🤖 Ботов: <code>{bot_count}</code>",
reply_markup=admin_profile_keyboard(user_id=user_id),
)
return
await callback.answer()
await callback.message.edit_text(
"🆔 Отправьте ID пользователя",
reply_markup=back_keyboard(callback_data="admin_panel"),
)
await state.set_state(AdminFlow.waiting_user_id)
await state.update_data(action="lookup")
@router.callback_query(
AdminCallbackFilter(), lambda c: c.data.startswith("admin_balance:")
)
async def admin_balance_prompt(callback: CallbackQuery, state: FSMContext) -> None:
user_id = int(callback.data.split(":")[1])
await callback.answer()
await callback.message.edit_text(
"💲 Отправьте сумму для изменения баланса пользователя",
reply_markup=back_keyboard(callback_data=f"admin_lookup:{user_id}"),
)
await state.set_state(AdminFlow.waiting_amount)
await state.update_data(action="balance", user_id=user_id)
@router.callback_query(AdminCallbackFilter(), lambda c: c.data == "admin_price")
async def admin_price_prompt(callback: CallbackQuery, state: FSMContext) -> None:
await callback.answer()
await callback.message.edit_text(
f"💲 Текущая цена слота: <code>{await get_bot_slot_price()}</code> ₽\n"
"Отправьте новую положительную цену.",
reply_markup=back_keyboard(callback_data="admin_panel"),
)
await state.set_state(AdminFlow.waiting_amount)
await state.update_data(action="price")
@router.message(AdminFlow.waiting_user_id, AdminFilter())
async def admin_lookup(message: Message, state: FSMContext) -> None:
try:
user_id = int((message.text or "").strip())
if user_id <= 0:
raise ValueError
_, balance, bot_count = await get_user_profile(user_id)
except (ValueError, TypeError):
await message.answer("❌ Некорректный Telegram ID")
return
await message.answer(
f"👤 <b>Профиль</b>\n\n"
f"🆔: <code>{user_id}</code>\n"
f"💰 Баланс: <code>{balance}</code> ₽\n"
f"🤖 Ботов: <code>{bot_count}</code>",
reply_markup=admin_profile_keyboard(user_id=user_id),
)
await state.clear()
@router.message(AdminFlow.waiting_amount, AdminFilter())
async def admin_amount(message: Message, state: FSMContext) -> None:
data = await state.get_data()
text = (message.text or "").strip()
try:
if data.get("action") == "price":
price = int(text)
await set_bot_slot_price(price, updated_by=ADMIN_ID)
response = f"✅ Цена слота обновлена: <code>{price}</code> ₽"
else:
amount_text = text
user_text = data.get("user_id", None)
print(amount_text, user_text)
user_id, signed_amount = int(user_text), int(amount_text)
if user_id <= 0 or signed_amount == 0:
raise ValueError
balance = await change_user_balance(
telegram_id=user_id,
amount=signed_amount,
actor_telegram_id=message.from_user.id,
)
response = f"✅ Баланс пользователя обновлён: <code>{balance}</code> ₽"
except (ValueError, TypeError, BalanceError):
response = "❌ Некорректные данные: нужны положительные целые числа"
await message.answer(response)
if data.get("action") == "price":
return await admin_menu(message, state)
_, balance, bot_count = await get_user_profile(user_id)
await message.answer(
f"👤 <b>Профиль</b>\n\n"
f"🆔: <code>{user_id}</code>\n"
f"💰 Баланс: <code>{balance}</code> ₽\n"
f"🤖 Ботов: <code>{bot_count}</code>",
reply_markup=admin_profile_keyboard(user_id=user_id),
)
await state.clear()