# - *- coding: utf- 8 - *- from typing import Optional, Tuple from aiogram import Router, Bot, F from aiogram.filters import StateFilter from aiogram.types import CallbackQuery, Message, PreCheckoutQuery from tgbot.database import Paymentsx, Refillx, Userx, Settingsx from tgbot.keyboards.inline_user import refill_bill_finl, refill_method_finl from tgbot.services.api_cryptobot import CryptobotAPI from tgbot.services.api_stars import StarsAPI from tgbot.services.api_yoomoney import YoomoneyAPI from tgbot.utils.const_functions import is_number, to_number, gen_id, ded from tgbot.utils.misc.bot_logging import bot_logger from tgbot.utils.misc.bot_models import FSM, ARS from tgbot.utils.misc_functions import send_admins min_refill_rub = 5 # Минимальная сумма пополнения в рублях router = Router(name=__name__) # Выбор способа пополнения @router.callback_query(F.data == "user_refill") async def refill_method_list(call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS): get_payments = await Paymentsx().get() if ( get_payments.status_cryptobot == "False" and get_payments.status_yoomoney == "False" and get_payments.status_stars == "False" ): return await call.answer("❗️ Пополнения временно недоступны", True) await call.message.edit_text( "💰 Выберите способ пополнения баланса", reply_markup=await refill_method_finl(), ) # Выбор способа пополнения @router.callback_query(F.data.startswith("user_refill_method:")) async def refill_method_select(call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS): refill_method = call.data.split(":")[1] get_payments = await Paymentsx().get() if refill_method == "Cryptobot" and get_payments.status_cryptobot == "False": return await call.answer("❌ Пополнение данным способом временно недоступно", True) elif refill_method == "Yoomoney" and get_payments.status_yoomoney == "False": return await call.answer("❌ Пополнение данным способом временно недоступно", True) elif refill_method == "Stars" and get_payments.status_stars == "False": return await call.answer("❌ Пополнение данным способом временно недоступно", True) await state.update_data(here_refill_method=refill_method) await state.set_state("here_refill_amount") await call.message.edit_text("💰 Введите сумму пополнения") ################################################################################ ################################### ВВОД СУММЫ ################################# # Принятие суммы для пополнения средств @router.message(F.text, StateFilter("here_refill_amount")) async def refill_amount_get(message: Message, bot: Bot, state: FSM, arSession: ARS): if not is_number(message.text): return await message.answer( ded(f""" ❌ Данные были введены неверно 💰 Введите сумму для пополнения средств """), ) if to_number(message.text) < min_refill_rub or to_number(message.text) > 150_000: return await message.answer( ded(f""" ❌ Неверная сумма пополнения ❗️ Cумма не должна быть меньше {min_refill_rub}₽ и больше 150 000₽ 💰 Введите сумму для пополнения средств """), ) cache_message = await message.answer("♻️ Подождите, платёж генерируется..") refill_amount = to_number(message.text) refill_method = (await state.get_data())['here_refill_method'] await state.clear() # Генерация платежа if refill_method == "Cryptobot": bill_message, bill_link, bill_receipt = await ( await CryptobotAPI.connect( bot=bot, arSession=arSession, update=cache_message, ) ).bill(refill_amount) elif refill_method == "Yoomoney": bill_message, bill_link, bill_receipt = await ( await YoomoneyAPI.connect( bot=bot, arSession=arSession, update=cache_message, ) ).bill(refill_amount) elif refill_method == "Stars": bill_message, bill_link, bill_receipt = await ( await StarsAPI.connect( bot=bot, arSession=arSession, update=cache_message, ) ).bill(refill_amount) else: return await cache_message.edit_text( f"❌ Данный способ пополнения не найден. Попробуйте позже: {refill_method}" ) # Обработка статуса генерации платежа if bill_message: await cache_message.edit_text( bill_message, reply_markup=refill_bill_finl(bill_link, bill_receipt, refill_method), ) else: await cache_message.edit_text( f"❌ Не удалось сгенерировать платёж. Попробуйте позже" ) ################################################################################ ############################### ПРОВЕРКА ПЛАТЕЖЕЙ ############################## # Проверка оплаты - ЮMoney @router.callback_query(F.data.startswith('Pay:Yoomoney')) async def refill_check_yoomoney(call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS): pay_method = call.data.split(":")[1] pay_receipt = call.data.split(":")[2] pay_status, pay_amount = await ( await YoomoneyAPI.connect( bot=bot, arSession=arSession, update=call, ) ).bill_check(pay_receipt) if pay_status == 0: refill_status = await refill_success( bot=bot, call=call, pay_method=pay_method, pay_amount=pay_amount, pay_receipt=int(pay_receipt), pay_comment=pay_receipt, ) if refill_status == "ALREADY": await call.answer("❗ Ваше пополнение уже зачислено.", True, cache_time=60) await delete_refill_message(bot, call.message.chat.id, call.message.message_id) elif refill_status == "USER_NOT_FOUND": await call.answer("❗ Пользователь не найден. Напишите в поддержку.", True, cache_time=30) elif pay_status == 1: await call.answer("❗️ Не удалось проверить платёж. Попробуйте позже", True, cache_time=30) elif pay_status == 2: await call.answer("❗️ Оплата не была найдена. Попробуйте позже", True, cache_time=5) elif pay_status == 3: await call.answer("❗️ Оплата была произведена не в рублях", True, cache_time=5) else: await call.answer(f"❗ Неизвестная ошибка {pay_status}. Обратитесь в поддержку.", True, cache_time=5) # Проверка оплаты - Cryptobot @router.callback_query(F.data.startswith('Pay:Cryptobot')) async def refill_check_cryptobot(call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS): pay_method = call.data.split(":")[1] pay_comment = call.data.split(":")[2] pay_status, pay_amount = await ( await CryptobotAPI.connect( bot=bot, arSession=arSession, update=call, ) ).bill_check(pay_comment) if pay_status == 0: refill_status = await refill_success( bot=bot, call=call, pay_method=pay_method, pay_amount=pay_amount, pay_comment=pay_comment, ) if refill_status == "ALREADY": await call.answer("❗ Ваше пополнение уже зачислено.", True, cache_time=60) await delete_refill_message(bot, call.message.chat.id, call.message.message_id) elif refill_status == "USER_NOT_FOUND": await call.answer("❗ Пользователь не найден. Напишите в поддержку.", True, cache_time=30) elif pay_status == 1: await call.answer("❗️ Не удалось проверить платёж. Попробуйте позже", True, cache_time=30) elif pay_status == 2: await call.answer("❗️ Оплата не была найдена. Попробуйте позже", True, cache_time=5) elif pay_status == 3: await call.answer("❗️ Вы не успели оплатить счёт", True, cache_time=5) await call.message.edit_reply_markup() else: await call.answer(f"❗ Неизвестная ошибка {pay_status}. Обратитесь в поддержку.", True, cache_time=5) # Проверка оплаты - Звёзды @router.callback_query(F.data.startswith('Pay:Stars')) async def refill_check_stars(call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS): pay_method = call.data.split(":")[1] pay_receipt = int(call.data.split(":")[2]) pay_status, pay_amount = await ( await StarsAPI.connect( bot=bot, arSession=arSession, update=call, ) ).bill_check(pay_receipt) if pay_status == 0: refill_status = await refill_success( bot=bot, call=call, pay_method=pay_method, pay_amount=pay_amount, pay_receipt=pay_receipt, ) if refill_status == "ALREADY": await call.answer("❗ Ваше пополнение уже зачислено.", True, cache_time=60) await delete_refill_message(bot, call.message.chat.id, call.message.message_id) elif refill_status == "USER_NOT_FOUND": await call.answer("❗ Пользователь не найден. Напишите в поддержку.", True, cache_time=30) elif pay_status == 1: await call.answer("❗️ Не удалось проверить платёж. Попробуйте позже", True, cache_time=30) elif pay_status == 2: await call.answer("❗️ Оплата не была найдена. Попробуйте позже", True, cache_time=5) else: await call.answer(f"❗ Неизвестная ошибка {pay_status}. Обратитесь в поддержку.", True, cache_time=5) ################################################################################ #################################### ЗВЁЗДЫ #################################### # Подтверждение платежа Telegram Stars @router.pre_checkout_query() async def refill_stars_pre_checkout(query: PreCheckoutQuery, bot: Bot, state: FSM, arSession: ARS): await ( await StarsAPI.connect( bot=bot, arSession=arSession, update=query, ) ).answer_pre_checkout(query) # Автоматическое зачисление Telegram Stars @router.message(F.successful_payment) async def refill_stars_success(message: Message, bot: Bot, state: FSM, arSession: ARS): payment = message.successful_payment if payment is None: return stars_api = await StarsAPI.connect( bot=bot, arSession=arSession, update=message, ) try: pay_receipt, pay_amount, pay_comment, bill_chat_id, bill_message_id = ( stars_api.parse_successful_payment(payment) ) except ValueError: bot_logger.warning("Некорректная successful_payment для Telegram Stars", exc_info=True) return refill_status, receipt = await save_refill_success( bot=bot, user_id=message.from_user.id, pay_method="Stars", pay_amount=pay_amount, pay_receipt=pay_receipt, pay_comment=pay_comment, ) if refill_status == "ok": if bill_chat_id == message.chat.id: await delete_refill_message(bot, bill_chat_id, bill_message_id) await message.answer( ded(f""" 💰 Вы пополнили баланс на сумму {pay_amount}₽. Удачи ❤️ 🧾 Чек: #{receipt} """) ) elif refill_status == "ALREADY": if bill_chat_id == message.chat.id: await delete_refill_message(bot, bill_chat_id, bill_message_id) await message.answer("❗ Ваше пополнение уже было зачислено.") elif refill_status == "USER_NOT_FOUND": await message.answer("❗ Пользователь не найден. Напишите в поддержку.") ################################################################################ #################################### ПРОЧЕЕ #################################### # Зачисление средств async def refill_success( bot: Bot, call: CallbackQuery, pay_method: str, pay_amount: float, pay_receipt: Optional[int] = None, pay_comment: Optional[str] = None, ): user_id = call.from_user.id if pay_receipt is None: pay_receipt = gen_id(12) if pay_comment is None: pay_comment = "" response_success, receipt = await save_refill_success( bot=bot, user_id=user_id, pay_method=pay_method, pay_amount=pay_amount, pay_receipt=pay_receipt, pay_comment=pay_comment, ) if response_success != "ok": return response_success await call.message.answer( ded(f""" 💰 Вы пополнили баланс на сумму {pay_amount}₽. Удачи ❤️ 🧾 Чек: #{receipt} """) ) await delete_refill_message(bot, call.message.chat.id, call.message.message_id) return response_success # Удаление сообщения со счётом async def delete_refill_message(bot: Bot, chat_id: Optional[int], message_id: Optional[int]) -> None: if chat_id is None or message_id is None: return try: await bot.delete_message(chat_id=chat_id, message_id=message_id) except Exception: bot_logger.warning("Не удалось удалить сообщение со счётом", exc_info=True) # Сохранение пополнения и уведомление админов async def save_refill_success( bot: Bot, user_id: int, pay_method: str, pay_amount: float, pay_receipt: int, pay_comment: str, ) -> Tuple[str, int]: if pay_method == "Yoomoney": text_method = "ЮMoney" elif pay_method == "Cryptobot": text_method = "CryptoBot" elif pay_method == "Stars": text_method = "Telegram Stars" else: text_method = f"Unknown - {pay_method}" response_success = await Refillx().success( user_id=user_id, pay_receipt=pay_receipt, pay_comment=pay_comment, pay_amount=pay_amount, pay_method=pay_method, ) if response_success != "ok": return response_success, pay_receipt get_user = await Userx().get_required(user_id=user_id) get_settings = await Settingsx().get() if get_settings.notification_refill == "True": await send_admins( bot, ded(f""" 💰 Пополнение баланса ▪️ Пользователь: @{get_user.user_login} | {get_user.user_name} | {user_id} ▪️ Сумма пополнения: {pay_amount}₽ ({text_method}) ▪️ Чек: #{pay_receipt} """) ) return response_success, pay_receipt