diff --git a/bot.py b/bot.py index 9b47ffe5..4d3b1d8b 100644 --- a/bot.py +++ b/bot.py @@ -10,7 +10,7 @@ storage = MemoryStorage() dp = Dispatcher(bot=bot, storage=storage) router = Router() -from handlers import commands, coupons, notifications, pay, profile, start +from handlers import commands, coupons, donate, notifications, pay, profile, start from handlers.admin import admin_commands, admin_coupons, admin_panel, admin_user_editor from handlers.keys import key_management, keys from handlers.payments import cryprobot_pay, freekassa_pay, robokassa_pay, stars_pay, yookassa_pay @@ -26,6 +26,8 @@ dp.include_router(profile.router) dp.include_router(keys.router) dp.include_router(key_management.router) dp.include_router(pay.router) +dp.include_router(donate.router) + if YOOKASSA_ENABLE: dp.include_router(yookassa_pay.router) if FREEKASSA_ENABLE: diff --git a/filters/admin.py b/filters/admin.py index 26c526c4..7ecd1f7d 100644 --- a/filters/admin.py +++ b/filters/admin.py @@ -11,4 +11,4 @@ class IsAdminFilter(BaseFilter): elif isinstance(ADMIN_ID, int): return message.from_user.id == ADMIN_ID else: - return False \ No newline at end of file + return False diff --git a/handlers/donate.py b/handlers/donate.py new file mode 100644 index 00000000..a494ea10 --- /dev/null +++ b/handlers/donate.py @@ -0,0 +1,127 @@ +from aiogram import F, Router, types +from aiogram.fsm.context import FSMContext +from aiogram.fsm.state import State, StatesGroup +from aiogram.types import InlineKeyboardButton, LabeledPrice, PreCheckoutQuery +from aiogram.utils.keyboard import InlineKeyboardBuilder +from loguru import logger + +from bot import bot +from config import RUB_TO_XTR + + +class DonateState(StatesGroup): + entering_donate_amount = State() + waiting_for_donate_confirmation = State() + + +router = Router() + + +@router.callback_query(F.data == "donate") +async def process_donate(callback_query: types.CallbackQuery, state: FSMContext): + + try: + await callback_query.message.delete() + except Exception as e: + logger.error(f"Не удалось удалить сообщение: {e}") + + builder = InlineKeyboardBuilder() + builder.row( + InlineKeyboardButton( + text="🤖 Бот для покупки звезд", url="https://t.me/PremiumBot" + ) + ) + builder.row( + InlineKeyboardButton( + text="💰 Ввести сумму доната", callback_data="enter_custom_donate_amount" + ) + ) + builder.row(InlineKeyboardButton(text="⬅️ Назад", callback_data="view_profile")) + + await bot.send_message( + chat_id=callback_query.from_user.id, + text="🌟 Поддержите наш проект!\n\n" + "Каждый донат помогает развивать и улучшать сервис. " + "Мы ценим вашу поддержку и работаем над тем, чтобы сделать наш продукт еще лучше. 💡", + reply_markup=builder.as_markup(), + ) + + await callback_query.answer() + + +@router.callback_query(F.data == "enter_custom_donate_amount") +async def process_enter_donate_amount( + callback_query: types.CallbackQuery, state: FSMContext +): + await callback_query.message.edit_text(f"💸 Введите сумму доната в рублях:") + await state.set_state(DonateState.entering_donate_amount) + await callback_query.answer() + + +@router.message(DonateState.entering_donate_amount) +async def process_donate_amount_input(message: types.Message, state: FSMContext): + + try: + await message.delete() + except Exception as e: + logger.error(f"Не удалось удалить сообщение: {e}") + + if message.text.isdigit(): + amount = int(message.text) + if amount // RUB_TO_XTR <= 0: + await message.answer( + f"Сумма доната должна быть больше {RUB_TO_XTR}. Пожалуйста, введите сумму еще раз:" + ) + return + + await state.update_data(amount=amount) + await state.set_state(DonateState.waiting_for_donate_confirmation) + + try: + builder = InlineKeyboardBuilder() + builder.row(InlineKeyboardButton(text="Задонатить", pay=True)) + builder.row(InlineKeyboardButton(text="⬅️ Назад", callback_data="donate")) + + await message.answer_invoice( + title=f"Донат проекту {amount} рублей", + description="Спасибо за вашу поддержку!", + prices=[LabeledPrice(label="Донат", amount=int(amount // RUB_TO_XTR))], + provider_token="", + payload=f"{amount}_donate", + currency="XTR", + reply_markup=builder.as_markup(), + ) + except Exception as e: + logger.error(f"Ошибка при создании доната: {e}") + await message.answer("Произошла ошибка при создании доната.") + else: + await message.answer("Некорректная сумма. Пожалуйста, введите сумму еще раз:") + + +@router.pre_checkout_query() +async def on_pre_checkout_query(pre_checkout_query: PreCheckoutQuery): + await pre_checkout_query.answer(ok=True) + + +@router.message(F.successful_payment) +async def on_successful_donate(message: types.Message): + try: + user_id = int(message.from_user.id) + amount = float(message.successful_payment.invoice_payload.split("_")[0]) + logger.debug(f"Donate succeeded for user_id: {user_id}, amount: {amount}") + + builder = InlineKeyboardBuilder() + builder.row( + InlineKeyboardButton( + text="Вернуться в профиль", callback_data="view_profile" + ) + ) + + await bot.send_message( + chat_id=user_id, + text=f"🙏 Спасибо за донат {amount} рублей! Ваша поддержка очень важна для нас. 💖", + reply_markup=builder.as_markup(), + message_effect_id="5104841245755180586", + ) + except ValueError as e: + logger.error(f"Ошибка конвертации user_id или amount: {e}") diff --git a/handlers/payments/stars_pay.py b/handlers/payments/stars_pay.py index 3af0ff0c..2cde3805 100644 --- a/handlers/payments/stars_pay.py +++ b/handlers/payments/stars_pay.py @@ -76,6 +76,11 @@ async def process_callback_pay_stars( text="💰 Ввести свою сумму", callback_data="enter_custom_amount_stars" ) ) + builder.row( + InlineKeyboardButton( + text="🤖 Бот для покупки звезд", url="https://t.me/PremiumBot" + ) + ) builder.row(InlineKeyboardButton(text="⬅️ Назад", callback_data="pay")) key_count = await get_key_count(tg_id) diff --git a/handlers/profile.py b/handlers/profile.py index d4536aff..0bf5bc39 100644 --- a/handlers/profile.py +++ b/handlers/profile.py @@ -49,6 +49,9 @@ async def process_callback_view_profile( InlineKeyboardButton(text="👥 Пригласить друзей", callback_data="invite"), InlineKeyboardButton(text="📘 Инструкции", callback_data="instructions"), ) + builder.row( + InlineKeyboardButton(text="💰 Поддержать проект", callback_data="donate") + ) builder.row( InlineKeyboardButton(text="⬅️ Главное меню", callback_data="back_to_menu") ) diff --git a/handlers/start.py b/handlers/start.py index b60a8b2d..a5ca1419 100644 --- a/handlers/start.py +++ b/handlers/start.py @@ -138,6 +138,9 @@ async def handle_about_vpn(callback_query: CallbackQuery): about_vpn_message = get_about_vpn("3.0.6_preStable") builder = InlineKeyboardBuilder() + builder.row( + InlineKeyboardButton(text="💰 Поддержать проект", callback_data="donate") + ) builder.row(InlineKeyboardButton(text="⬅️ Назад", callback_data="back_to_menu")) await callback_query.message.answer(