Files
Solo_bot/handlers/admin/gifts/gifts_handler.py
T
2025-06-11 23:09:23 +03:00

208 lines
7.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from aiogram import F, Router, types, Bot
from aiogram.types import CallbackQuery
from aiogram.fsm.context import FSMContext
from aiogram.fsm.state import State, StatesGroup
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, delete, func
from aiogram.utils.keyboard import InlineKeyboardBuilder
from ..panel.keyboard import AdminPanelCallback
from .keyboard import build_admin_gifts_kb, build_gifts_list_kb
from database.models import Tariff, Gift, GiftUsage
from handlers.payments.gift import finalize_gift
router = Router()
class GiftCreationState(StatesGroup):
waiting_for_gift_limit = State()
waiting_for_limit_input_or_unlimited = State()
@router.callback_query(AdminPanelCallback.filter(F.action == "gifts"))
async def admin_gift_menu(callback: CallbackQuery):
await callback.message.edit_text(
text="🎁 <b>Подарки</b>\nВыберите, что хотите сделать:",
reply_markup=build_admin_gifts_kb()
)
@router.callback_query(F.data == "admin_gift_create")
async def admin_create_gift_step1(callback: CallbackQuery, session: AsyncSession):
result = await session.execute(
select(Tariff)
.where(Tariff.group_code == "gifts", Tariff.is_active == True)
.order_by(Tariff.id)
)
tariffs = result.scalars().all()
if not tariffs:
builder = InlineKeyboardBuilder()
builder.button(text="🔙 Назад", callback_data=AdminPanelCallback(action="gifts").pack())
await callback.message.edit_text("❌ Нет активных тарифов в группе 'gifts'.", reply_markup=builder.as_markup())
return
kb = InlineKeyboardBuilder()
for t in tariffs:
kb.button(text=f"{t.name} {t.duration_days // 30} мес", callback_data=f"admin_gift_select|{t.id}")
kb.row(types.InlineKeyboardButton(text="🔙 Назад", callback_data=AdminPanelCallback(action="gifts").pack()
))
await callback.message.edit_text(
"🎁 Выберите тариф для подарка:",
reply_markup=kb.as_markup()
)
@router.callback_query(F.data.startswith("admin_gift_select|"))
async def handle_tariff_selection(callback: CallbackQuery, state: FSMContext):
tariff_id = int(callback.data.split("|")[1])
await state.update_data(tariff_id=tariff_id)
await state.set_state(GiftCreationState.waiting_for_limit_input_or_unlimited)
kb = InlineKeyboardBuilder()
kb.button(text="🔙 Назад", callback_data="admin_gift_create")
await callback.message.edit_text(
"🔢 Введите максимальное количество активаций подарка:",
reply_markup=kb.as_markup()
)
@router.callback_query(F.data == "gift_limit_unlimited")
async def handle_unlimited_gift(callback: CallbackQuery, state: FSMContext, bot: Bot):
data = await state.get_data()
session: AsyncSession = callback.bot["session"]
await state.clear()
await finalize_gift(callback.message, session, bot, data, is_unlimited=True)
@router.message(GiftCreationState.waiting_for_limit_input_or_unlimited)
async def handle_limited_gift_input(message: types.Message, session: AsyncSession, state: FSMContext, bot: Bot):
try:
max_usages = int(message.text.strip())
if max_usages <= 0:
raise ValueError
except ValueError:
await message.answer("❌ Введите корректное положительное число.")
return
data = await state.get_data()
data["max_usages"] = max_usages
await state.clear()
await finalize_gift(message, session, bot, data, is_unlimited=False)
@router.callback_query(F.data == "admin_gifts_all")
async def show_gifts_page(callback: CallbackQuery, session: AsyncSession):
await show_gift_list(callback, session, page=1)
@router.callback_query(F.data.startswith("gifts_page|"))
async def paginate_gifts(callback: CallbackQuery, session: AsyncSession):
page = int(callback.data.split("|")[1])
await show_gift_list(callback, session, page)
async def show_gift_list(callback: CallbackQuery, session: AsyncSession, page: int):
limit = 10
offset = (page - 1) * limit
stmt = select(Gift).order_by(Gift.created_at.desc()).offset(offset).limit(limit)
result = await session.execute(stmt)
gifts = result.scalars().all()
from aiogram.utils.keyboard import InlineKeyboardBuilder
builder = InlineKeyboardBuilder()
if not gifts:
builder.button(text="🔙 Назад", callback_data=AdminPanelCallback(action="gifts").pack())
await callback.message.edit_text(
"❌ Подарки не найдены.",
reply_markup=builder.as_markup()
)
return
keyboard = build_gifts_list_kb(gifts, page, total=len(gifts))
builder.inline_keyboard.extend(keyboard.inline_keyboard)
builder.row(types.InlineKeyboardButton(text="🔙 Назад", callback_data=AdminPanelCallback(action="gifts").pack()))
await callback.message.edit_text(
f"🎁 <b>Список подарков</b>\nСтраница {page}:",
reply_markup=builder.as_markup()
)
async def show_gift_list(callback: CallbackQuery, session: AsyncSession, page: int):
limit = 10
offset = (page - 1) * limit
stmt = select(Gift).order_by(Gift.created_at.desc()).offset(offset).limit(limit)
result = await session.execute(stmt)
gifts = result.scalars().all()
builder = InlineKeyboardBuilder()
if not gifts:
builder.button(text="🔙 Назад", callback_data=AdminPanelCallback(action="gifts").pack())
await callback.message.edit_text(
"❌ Подарки не найдены.",
reply_markup=builder.as_markup()
)
return
keyboard = build_gifts_list_kb(gifts, page, total=len(gifts))
for row in keyboard.inline_keyboard:
builder.row(*row)
await callback.message.edit_text(
f"🎁 <b>Список подарков</b>\nСтраница {page}:",
reply_markup=builder.as_markup()
)
@router.callback_query(F.data.startswith("gift_view|"))
async def view_gift(callback: CallbackQuery, session: AsyncSession):
gift_id = callback.data.split("|")[1]
result = await session.execute(select(Gift).where(Gift.gift_id == gift_id))
gift = result.scalar_one_or_none()
if not gift:
await callback.message.edit_text("❌ Подарок не найден.")
return
usage_result = await session.execute(
select(func.count()).select_from(GiftUsage).where(GiftUsage.gift_id == gift_id)
)
used_count = usage_result.scalar_one()
usage_text = f"{used_count}/{gift.max_usages}" if gift.max_usages else ""
text = (
f"🎁 <b>Подарок</b>\n"
f"ID: <code>{gift.gift_id}</code>\n"
f"Месяцев: <b>{gift.selected_months}</b>\n"
f"Активаций: <b>{usage_text}</b>\n"
f"Срок действия: <i>{gift.expiry_time.strftime('%d.%m.%Y')}</i>\n"
f"<b>Ссылка для активации:</b>\n<blockquote>{gift.gift_link}</blockquote>"
)
builder = InlineKeyboardBuilder()
builder.button(text="🗑 Удалить", callback_data=f"gift_delete|{gift_id}")
builder.button(text="🔙 Назад", callback_data="admin_gifts_all")
await callback.message.edit_text(text, reply_markup=builder.as_markup())
@router.callback_query(F.data.startswith("gift_delete|"))
async def delete_gift(callback: CallbackQuery, session: AsyncSession):
gift_id = callback.data.split("|")[1]
await session.execute(delete(GiftUsage).where(GiftUsage.gift_id == gift_id))
await session.execute(delete(Gift).where(Gift.gift_id == gift_id))
await session.commit()
builder = InlineKeyboardBuilder()
builder.button(text="🔙 Назад к списку", callback_data="admin_gifts_all")
await callback.message.edit_text(
"✅ Подарок удалён.",
reply_markup=builder.as_markup()
)