diff --git a/.flake8 b/.flake8 index 1d5b8e45..5b3aa68f 100644 --- a/.flake8 +++ b/.flake8 @@ -1,6 +1,6 @@ [flake8] max-line-length = 250 -ignore = E203, E266, E501, W503, F541, E704, W293, W291, E126, E121, E123, E128, E302, E131, E231, W292, E402, E261 +ignore = E203, E266, E501, W503, F541, E704, W293, W291, E126, E121, E123, E128, E302, E131, E231, W292, E402, E261, E305 max-complexity = 25 select = B, C, E, F, W, T4, B9 exclude = .venv,.git,.tox,dist,doc,*lib/python*,*egg,build,.txt \ No newline at end of file diff --git a/handlers/coupons.py b/handlers/coupons.py index 86aed0e4..1c145d92 100644 --- a/handlers/coupons.py +++ b/handlers/coupons.py @@ -28,10 +28,16 @@ async def handle_activate_coupon( except Exception as e: logger.error(f"Ошибка при удалении сообщения: {e}") + builder = InlineKeyboardBuilder() + builder.row( + InlineKeyboardButton(text="⬅️ Вернуться в профиль", callback_data="view_profile") + ) + await callback_query.message.answer( "Введите код купона:\n\n" "Пожалуйста, введите действующий код купона, который вы хотите активировать.", parse_mode="HTML", + reply_markup=builder.as_markup(), ) await state.set_state(CouponActivationState.waiting_for_coupon_code) await callback_query.answer() diff --git a/handlers/donate.py b/handlers/donate.py deleted file mode 100644 index e69de29b..00000000 diff --git a/handlers/instructions/instructions.py b/handlers/instructions/instructions.py index 87394869..20a929c3 100644 --- a/handlers/instructions/instructions.py +++ b/handlers/instructions/instructions.py @@ -18,7 +18,9 @@ async def send_instructions(callback_query: types.CallbackQuery): await callback_query.answer() return - back_button = InlineKeyboardButton(text="🔙 Назад", callback_data="back_to_main") + back_button = InlineKeyboardButton( + text="⬅️ Вернуться в профиль", callback_data="view_profile" + ) keyboard = InlineKeyboardMarkup(inline_keyboard=[[back_button]]) with open(image_path, "rb") as image_from_buffer: diff --git a/handlers/payments/cryprobot_pay.py b/handlers/payments/cryprobot_pay.py index bfad4bf3..7e6f51db 100644 --- a/handlers/payments/cryprobot_pay.py +++ b/handlers/payments/cryprobot_pay.py @@ -10,7 +10,6 @@ from loguru import logger from bot import bot from config import CRYPTO_BOT_ENABLE, CRYPTO_BOT_TOKEN, RUB_TO_USDT from database import add_connection, check_connection_exists, get_key_count, update_balance -from handlers.profile import process_callback_view_profile from handlers.texts import PAYMENT_OPTIONS router = Router() @@ -20,9 +19,9 @@ if CRYPTO_BOT_ENABLE: class ReplenishBalanceState(StatesGroup): - choosing_amount = State() - waiting_for_payment_confirmation = State() - entering_custom_amount = State() + choosing_amount_crypto = State() + waiting_for_payment_confirmation_crypto = State() + entering_custom_amount_crypto = State() async def send_message_with_deletion( @@ -63,23 +62,23 @@ async def process_callback_pay_cryptobot( builder.row( InlineKeyboardButton( text=PAYMENT_OPTIONS[i]["text"], - callback_data=PAYMENT_OPTIONS[i]["callback_data"], + callback_data=f'crypto_{PAYMENT_OPTIONS[i]["callback_data"]}', ), InlineKeyboardButton( text=PAYMENT_OPTIONS[i + 1]["text"], - callback_data=PAYMENT_OPTIONS[i + 1]["callback_data"], + callback_data=f'crypto_{PAYMENT_OPTIONS[i + 1]["callback_data"]}', ), ) else: builder.row( InlineKeyboardButton( text=PAYMENT_OPTIONS[i]["text"], - callback_data=PAYMENT_OPTIONS[i]["callback_data"], + callback_data=f'crypto_{PAYMENT_OPTIONS[i]["callback_data"]}', ) ) builder.row( InlineKeyboardButton( - text="💰 Ввести свою сумму", callback_data="enter_custom_amount" + text="💰 Ввести свою сумму", callback_data="enter_custom_amount_crypto" ) ) builder.row(InlineKeyboardButton(text="⬅️ Назад", callback_data="back_to_profile")) @@ -104,18 +103,11 @@ async def process_callback_pay_cryptobot( reply_markup=builder.as_markup(), ) - await state.set_state(ReplenishBalanceState.choosing_amount) + await state.set_state(ReplenishBalanceState.choosing_amount_crypto) await callback_query.answer() -@router.callback_query(F.data == "back_to_profile") -async def back_to_profile_handler( - callback_query: types.CallbackQuery, state: FSMContext -): - await process_callback_view_profile(callback_query, state) - - -@router.callback_query(F.data.startswith("amount|")) +@router.callback_query(F.data.startswith("crypto_amount|")) async def process_amount_selection( callback_query: types.CallbackQuery, state: FSMContext ): @@ -143,24 +135,24 @@ async def process_amount_selection( return await state.update_data(amount=amount) - await state.set_state(ReplenishBalanceState.waiting_for_payment_confirmation) + await state.set_state(ReplenishBalanceState.waiting_for_payment_confirmation_crypto) try: invoice = await crypto.create_invoice( asset="USDT", - amount=str(amount // RUB_TO_USDT), - description=f"Пополнения баланса на {amount//RUB_TO_USDT} руб", - payload=f"{callback_query.from_user.id}:{amount//RUB_TO_USDT}", + amount=str(int(amount // RUB_TO_USDT)), + description=f"Пополнения баланса на {amount} руб", + payload=f"{callback_query.from_user.id}:{int(amount)}", ) if hasattr(invoice, "bot_invoice_url"): builder = InlineKeyboardBuilder() builder.row( - InlineKeyboardButton(text="Пополнить", url=invoice.bot_invoice_url), - InlineKeyboardButton(text="⬅️ Назад", callback_data="back_to_profile"), + InlineKeyboardButton(text="Пополнить", url=invoice.bot_invoice_url) ) + builder.row(InlineKeyboardButton(text="⬅️ Назад", callback_data="pay")) await callback_query.message.edit_text( - text=f"Вы выбрали пополнение на {amount//RUB_TO_USDT} рублей.", + text=f"Вы выбрали пополнение на {amount} рублей.", reply_markup=builder.as_markup(), ) else: @@ -211,7 +203,7 @@ async def process_crypto_payment(payload): user_id_str, amount_str = custom_payload.split(":") try: user_id = int(user_id_str) - amount = float(amount_str) + amount = int(amount_str) logger.debug(f"Payment succeeded for user_id: {user_id}, amount: {amount}") await update_balance(user_id, amount) await send_payment_success_notification(user_id, amount) @@ -221,16 +213,16 @@ async def process_crypto_payment(payload): logger.warning(f"Получен неоплаченный инвойс: {payload}") -@router.callback_query(F.data == "enter_custom_amount") +@router.callback_query(F.data == "enter_custom_amount_crypto") async def process_enter_custom_amount( callback_query: types.CallbackQuery, state: FSMContext ): await callback_query.message.edit_text(text="Введите сумму пополнения:") - await state.set_state(ReplenishBalanceState.entering_custom_amount) + await state.set_state(ReplenishBalanceState.entering_custom_amount_crypto) await callback_query.answer() -@router.message(State(ReplenishBalanceState.entering_custom_amount)) +@router.message(State(ReplenishBalanceState.entering_custom_amount_crypto)) async def process_custom_amount_input(message: types.Message, state: FSMContext): if message.text.isdigit(): amount = int(message.text) @@ -241,25 +233,27 @@ async def process_custom_amount_input(message: types.Message, state: FSMContext) return await state.update_data(amount=amount) - await state.set_state(ReplenishBalanceState.waiting_for_payment_confirmation) + await state.set_state( + ReplenishBalanceState.waiting_for_payment_confirmation_crypto + ) try: invoice = await crypto.create_invoice( asset="USDT", - amount=str(amount // RUB_TO_USDT), - description=f"Пополнения баланса на {amount//RUB_TO_USDT} руб", - payload=f"{message.from_user.id}:{amount//RUB_TO_USDT}", + amount=str(int(amount // RUB_TO_USDT)), + description=f"Пополнения баланса на {amount} руб", + payload=f"{message.from_user.id}:{amount}", ) if hasattr(invoice, "bot_invoice_url"): builder = InlineKeyboardBuilder() builder.row( - InlineKeyboardButton(text="Пополнить", url=invoice.bot_invoice_url), - InlineKeyboardButton( - text="⬅️ Назад", callback_data="back_to_profile" - ), + InlineKeyboardButton(text="Пополнить", url=invoice.bot_invoice_url) + ) + builder.row( + InlineKeyboardButton(text="⬅️ Назад", callback_data="pay"), ) await message.message.edit_text( - text=f"Вы выбрали пополнение на {amount//RUB_TO_USDT} рублей.", + text=f"Вы выбрали пополнение на {amount} рублей.", reply_markup=builder.as_markup(), ) else: diff --git a/handlers/payments/stars_pay.py b/handlers/payments/stars_pay.py index 83002603..2ab54dd9 100644 --- a/handlers/payments/stars_pay.py +++ b/handlers/payments/stars_pay.py @@ -1,23 +1,22 @@ 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 +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 from database import add_connection, check_connection_exists, get_key_count, update_balance -from handlers.profile import process_callback_view_profile from handlers.texts import PAYMENT_OPTIONS router = Router() class ReplenishBalanceState(StatesGroup): - choosing_amount = State() - waiting_for_payment_confirmation = State() - entering_custom_amount = State() + choosing_amount_stars = State() + waiting_for_payment_confirmation_stars = State() + entering_custom_amount_stars = State() async def send_message_with_deletion( @@ -58,26 +57,26 @@ async def process_callback_pay_stars( builder.row( InlineKeyboardButton( text=PAYMENT_OPTIONS[i]["text"], - callback_data=PAYMENT_OPTIONS[i]["callback_data"], + callback_data=f'stars_{PAYMENT_OPTIONS[i]["callback_data"]}', ), InlineKeyboardButton( text=PAYMENT_OPTIONS[i + 1]["text"], - callback_data=PAYMENT_OPTIONS[i + 1]["callback_data"], + callback_data=f'stars_{PAYMENT_OPTIONS[i + 1]["callback_data"]}', ), ) else: builder.row( InlineKeyboardButton( text=PAYMENT_OPTIONS[i]["text"], - callback_data=PAYMENT_OPTIONS[i]["callback_data"], + callback_data=f'stars_{PAYMENT_OPTIONS[i]["callback_data"]}', ) ) builder.row( InlineKeyboardButton( - text="💰 Ввести свою сумму", callback_data="enter_custom_amount" + text="💰 Ввести свою сумму", callback_data="enter_custom_amount_stars" ) ) - builder.row(InlineKeyboardButton(text="⬅️ Назад", callback_data="back_to_profile")) + builder.row(InlineKeyboardButton(text="⬅️ Назад", callback_data="pay")) key_count = await get_key_count(tg_id) @@ -99,18 +98,11 @@ async def process_callback_pay_stars( reply_markup=builder.as_markup(), ) - await state.set_state(ReplenishBalanceState.choosing_amount) + await state.set_state(ReplenishBalanceState.choosing_amount_stars) await callback_query.answer() -@router.callback_query(F.data == "back_to_profile") -async def back_to_profile_handler( - callback_query: types.CallbackQuery, state: FSMContext -): - await process_callback_view_profile(callback_query, state) - - -@router.callback_query(F.data.startswith("amount|")) +@router.callback_query(F.data.startswith("starts_amount|")) async def process_amount_selection( callback_query: types.CallbackQuery, state: FSMContext ): @@ -138,18 +130,20 @@ async def process_amount_selection( return await state.update_data(amount=amount) - await state.set_state(ReplenishBalanceState.waiting_for_payment_confirmation) + await state.set_state(ReplenishBalanceState.waiting_for_payment_confirmation_stars) try: builder = InlineKeyboardBuilder() builder.row( InlineKeyboardButton(text="Пополнить", pay=True), - InlineKeyboardButton(text="⬅️ Назад", callback_data="back_to_profile"), + ) + builder.row( + InlineKeyboardButton(text="⬅️ Назад", callback_data="pay"), ) await callback_query.message.answer_invoice( - title=f"Вы выбрали пополнение на {amount//RUB_TO_XTR} рублей.", - description=f"Вы выбрали пополнение на {amount//RUB_TO_XTR} рублей.", - prices=[LabeledPrice(label="XTR", amount=amount)], + title=f"Вы выбрали пополнение на {amount} рублей.", + description=f"Вы выбрали пополнение на {amount} рублей.", + prices=[LabeledPrice(label="XTR", amount=int(amount // RUB_TO_XTR))], provider_token="", payload=f"{amount}_stars", currency="XTR", @@ -176,16 +170,16 @@ async def send_payment_success_notification(user_id: int, amount: float): logger.error(f"Ошибка при отправке уведомления пользователю {user_id}: {e}") -@router.callback_query(F.data == "enter_custom_amount") +@router.callback_query(F.data == "enter_custom_amount_stars") async def process_enter_custom_amount( callback_query: types.CallbackQuery, state: FSMContext ): await callback_query.message.edit_text(text="Введите сумму пополнения:") - await state.set_state(ReplenishBalanceState.entering_custom_amount) + await state.set_state(ReplenishBalanceState.entering_custom_amount_stars) await callback_query.answer() -@router.message(State(ReplenishBalanceState.entering_custom_amount)) +@router.message(ReplenishBalanceState.entering_custom_amount_stars) async def process_custom_amount_input(message: types.Message, state: FSMContext): if message.text.isdigit(): amount = int(message.text) @@ -196,17 +190,21 @@ async def process_custom_amount_input(message: types.Message, state: FSMContext) return await state.update_data(amount=amount) - await state.set_state(ReplenishBalanceState.waiting_for_payment_confirmation) + await state.set_state( + ReplenishBalanceState.waiting_for_payment_confirmation_stars + ) try: builder = InlineKeyboardBuilder() builder.row( InlineKeyboardButton(text="Пополнить", pay=True), - InlineKeyboardButton(text="⬅️ Назад", callback_data="back_to_profile"), + ) + builder.row( + InlineKeyboardButton(text="⬅️ Назад", callback_data="pay"), ) await message.answer_invoice( - title=f"Вы выбрали пополнение на {amount//RUB_TO_XTR} рублей.", - description=f"Вы выбрали пополнение на {amount//RUB_TO_XTR} рублей.", - prices=[LabeledPrice(label="XTR", amount=amount)], + title=f"Вы выбрали пополнение на {amount} рублей.", + description=f"Вы выбрали пополнение на {amount} рублей.", + prices=[LabeledPrice(label="XTR", amount=int(amount // RUB_TO_XTR))], provider_token="", payload=f"{amount}_stars", currency="XTR", @@ -219,13 +217,18 @@ async def process_custom_amount_input(message: types.Message, state: FSMContext) 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_payment( message: types.Message, ): try: user_id = int(message.from_user.id) - amount = float(message.successful_payment.total_amount) + amount = float(message.successful_payment.invoice_payload.split("_")[0]) logger.debug(f"Payment succeeded for user_id: {user_id}, amount: {amount}") await update_balance(user_id, amount) await send_payment_success_notification(user_id, amount) diff --git a/handlers/pic_invite.jpg b/handlers/pic_invite.jpg new file mode 100644 index 00000000..1064f788 Binary files /dev/null and b/handlers/pic_invite.jpg differ diff --git a/handlers/profile.py b/handlers/profile.py index 2560fbc7..d4536aff 100644 --- a/handlers/profile.py +++ b/handlers/profile.py @@ -136,4 +136,5 @@ async def invite_handler(callback_query: types.CallbackQuery): @router.callback_query(F.data == "view_profile") async def view_profile_handler(callback_query: types.CallbackQuery, state: FSMContext): + await state.clear() await process_callback_view_profile(callback_query, state) diff --git a/handlers/start.py b/handlers/start.py index a06d602d..b60a8b2d 100644 --- a/handlers/start.py +++ b/handlers/start.py @@ -28,6 +28,8 @@ async def send_welcome_message(chat_id: int, trial_status: int): ) builder.row( InlineKeyboardButton(text="📞 Техническая поддержка", url=SUPPORT_CHAT_URL), + ) + builder.row( InlineKeyboardButton(text="📢 Официальный канал", url=CHANNEL_URL), ) builder.row(InlineKeyboardButton(text="🌐 О нашем VPN", callback_data="about_vpn"))