diff --git a/.flake8 b/.flake8 index 68f40a2d..b8031c58 100644 --- a/.flake8 +++ b/.flake8 @@ -3,4 +3,4 @@ max-line-length = 250 ignore = E203, E266, E501, W503, F541, E704, W293, W291, E126, E121, E123, E128, E302, E131, E231, W292, E402, E261, E305, E701 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 +exclude = .venv,.git,.tox,dist,doc,*lib/python*,*egg,build,.txt,config.py \ No newline at end of file diff --git a/bot.py b/bot.py index b4287f5b..44011c1a 100644 --- a/bot.py +++ b/bot.py @@ -6,7 +6,6 @@ from middlewares.admin import AdminMiddleware from middlewares.database import DatabaseMiddleware from middlewares.logging import LoggingMiddleware from middlewares.user import UserMiddleware -from middlewares.database import DatabaseMiddleware bot = Bot(token=API_TOKEN) storage = MemoryStorage() diff --git a/database.py b/database.py index 34c92602..c78db0fe 100644 --- a/database.py +++ b/database.py @@ -9,6 +9,21 @@ from logger import logger async def init_db(): conn = await asyncpg.connect(DATABASE_URL) + # Таблица для хранения информации о платежах + await conn.execute( + """ + CREATE TABLE IF NOT EXISTS payments ( + id SERIAL PRIMARY KEY, + tg_id BIGINT NOT NULL, + amount REAL NOT NULL, + payment_system TEXT NOT NULL, + status TEXT DEFAULT 'success', + created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (tg_id) REFERENCES users(tg_id) + ) + """ + ) + # Таблица для хранения основной информации о пользователях из Telegram await conn.execute( """ @@ -491,3 +506,29 @@ async def upsert_user( ) finally: await conn.close() + + +async def add_payment(tg_id: int, amount: float, payment_system: str): + """ + Создает запись о платеже в базе данных. + + Args: + tg_id (int): Уникальный идентификатор пользователя в Telegram + amount (float): Сумма платежа + payment_system (str): Система, через которую был совершен платеж + """ + conn = await asyncpg.connect(DATABASE_URL) + try: + await conn.execute( + """ + INSERT INTO payments (tg_id, amount, payment_system, status) + VALUES ($1, $2, $3, 'success') + """, + tg_id, + amount, + payment_system, + ) + except Exception as e: + logger.error(f"Ошибка при добавлении платежа: {e}") + finally: + await conn.close() diff --git a/handlers/admin/admin_panel.py b/handlers/admin/admin_panel.py index 414fdbd0..e020a009 100644 --- a/handlers/admin/admin_panel.py +++ b/handlers/admin/admin_panel.py @@ -71,6 +71,16 @@ async def user_stats_menu(callback_query: CallbackQuery): total_keys = await conn.fetchval("SELECT COUNT(*) FROM keys") total_referrals = await conn.fetchval("SELECT COUNT(*) FROM referrals") + total_payments_today = await conn.fetchval( + "SELECT COALESCE(SUM(amount), 0) FROM payments WHERE created_at >= CURRENT_DATE" + ) + total_payments_week = await conn.fetchval( + "SELECT COALESCE(SUM(amount), 0) FROM payments WHERE created_at >= date_trunc('week', CURRENT_DATE)" + ) + total_payments_all_time = await conn.fetchval( + "SELECT COALESCE(SUM(amount), 0) FROM payments" + ) + active_keys = await conn.fetchval( "SELECT COUNT(*) FROM keys WHERE expiry_time > $1", int(datetime.utcnow().timestamp() * 1000), @@ -79,11 +89,17 @@ async def user_stats_menu(callback_query: CallbackQuery): stats_message = ( f"📈 Подробная статистика проекта:\n\n" - f"👤 Зарегистрированных пользователей: {total_users}\n" - f"🔑 Всего сгенерированных ключей: {total_keys}\n" - f"🤝 Привлеченных рефералов: {total_referrals}\n" - f"✅ Действующих ключей: {active_keys}\n" - f"❌ Просроченных ключей: {expired_keys}" + f"👥 Пользователи:\n" + f" • Зарегистрировано: {total_users}\n" + f" • Привлеченных рефералов: {total_referrals}\n\n" + f"🔑 Ключи:\n" + f" • Всего сгенерировано: {total_keys}\n" + f" • Действующих: {active_keys}\n" + f" • Просроченных: {expired_keys}\n\n" + f"💰 Финансовая статистика:\n" + f" • За день: {total_payments_today} ₽\n" + f" • За неделю: {total_payments_week} ₽\n" + f" • За все время: {total_payments_all_time} ₽\n" ) builder = InlineKeyboardBuilder() @@ -98,7 +114,7 @@ async def user_stats_menu(callback_query: CallbackQuery): ) finally: await conn.close() - await callback_query.answer() + # await callback_query.answer() @router.callback_query(F.data == "send_to_alls", IsAdminFilter()) @@ -188,6 +204,9 @@ async def back_to_admin_menu(callback_query: CallbackQuery): builder.row( InlineKeyboardButton(text="🔄 Перезагрузить бота", callback_data="restart_bot") ) + builder.row( + InlineKeyboardButton(text="⬅️ Вернуться в профиль", callback_data="view_profile") + ) await bot.send_message( tg_id, "🤖 Панель администратора", reply_markup=builder.as_markup() ) diff --git a/handlers/donate.py b/handlers/donate.py index b3f18870..8625b416 100644 --- a/handlers/donate.py +++ b/handlers/donate.py @@ -58,8 +58,7 @@ async def process_enter_donate_amount( builder = InlineKeyboardBuilder() builder.row(InlineKeyboardButton(text="⬅️ Назад", callback_data="donate")) await callback_query.message.edit_text( - f"💸 Введите сумму доната в рублях:", - reply_markup=builder.as_markup() + f"💸 Введите сумму доната в рублях:", reply_markup=builder.as_markup() ) await state.set_state(DonateState.entering_donate_amount) await callback_query.answer() diff --git a/handlers/payments/cryprobot_pay.py b/handlers/payments/cryprobot_pay.py index 44f9c691..e937f3a2 100644 --- a/handlers/payments/cryprobot_pay.py +++ b/handlers/payments/cryprobot_pay.py @@ -8,7 +8,7 @@ from aiohttp import web 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 database import add_connection, add_payment, check_connection_exists, get_key_count, update_balance from handlers.texts import PAYMENT_OPTIONS from logger import logger @@ -209,6 +209,7 @@ async def process_crypto_payment(payload): try: user_id = int(user_id_str) amount = int(amount_str) + await add_payment(int(user_id), float(amount), "cryptobot") 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/payments/freekassa_pay.py b/handlers/payments/freekassa_pay.py index de1602c2..52514ecf 100644 --- a/handlers/payments/freekassa_pay.py +++ b/handlers/payments/freekassa_pay.py @@ -14,7 +14,7 @@ from aiohttp import web from bot import bot from config import FREEKASSA_API_KEY, FREEKASSA_SHOP_ID -from database import update_balance +from database import add_payment, update_balance from handlers.texts import PAYMENT_OPTIONS router = Router() @@ -86,6 +86,7 @@ async def freekassa_webhook(request): if data["status"] == "completed": user_id = data["metadata"]["user_id"] amount = float(data["amount"]) + await add_payment(int(user_id), float(amount), "freekassa") await update_balance(user_id, amount) await send_payment_success_notification(user_id, amount) diff --git a/handlers/payments/robokassa_pay.py b/handlers/payments/robokassa_pay.py index 65576f8d..973a6fce 100644 --- a/handlers/payments/robokassa_pay.py +++ b/handlers/payments/robokassa_pay.py @@ -6,13 +6,13 @@ from aiogram.fsm.state import State, StatesGroup from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup from aiogram.utils.keyboard import InlineKeyboardBuilder from aiohttp import web -from logger import logger from robokassa import HashAlgorithm, Robokassa from bot import bot from config import ROBOKASSA_ENABLE, ROBOKASSA_LOGIN, ROBOKASSA_PASSWORD1, ROBOKASSA_PASSWORD2, ROBOKASSA_TEST_MODE -from database import add_connection, check_connection_exists, get_key_count, update_balance +from database import add_connection, add_payment, check_connection_exists, get_key_count, update_balance from handlers.texts import PAYMENT_OPTIONS +from logger import logger router = Router() @@ -222,6 +222,8 @@ async def robokassa_webhook(request): await update_balance(int(tg_id), float(amount)) await send_payment_success_notification(tg_id, float(amount)) + await add_payment(int(tg_id), float(amount), "robokassa") + logger.info(f"Payment successful. Balance updated for user {tg_id}.") return web.Response(text=f"OK{inv_id}") diff --git a/handlers/payments/stars_pay.py b/handlers/payments/stars_pay.py index 1f9607f3..27be8a16 100644 --- a/handlers/payments/stars_pay.py +++ b/handlers/payments/stars_pay.py @@ -6,7 +6,7 @@ from aiogram.utils.keyboard import InlineKeyboardBuilder from bot import bot from config import RUB_TO_XTR -from database import add_connection, check_connection_exists, get_key_count, update_balance +from database import add_connection, add_payment, check_connection_exists, get_key_count, update_balance from handlers.texts import PAYMENT_OPTIONS from logger import logger @@ -237,6 +237,7 @@ async def on_successful_payment( user_id = int(message.from_user.id) amount = float(message.successful_payment.invoice_payload.split("_")[0]) logger.debug(f"Payment succeeded for user_id: {user_id}, amount: {amount}") + await add_payment(int(user_id), float(amount), "stars") await update_balance(user_id, amount) await send_payment_success_notification(user_id, amount) except ValueError as e: diff --git a/handlers/payments/yookassa_pay.py b/handlers/payments/yookassa_pay.py index 61d80083..440b7eb3 100644 --- a/handlers/payments/yookassa_pay.py +++ b/handlers/payments/yookassa_pay.py @@ -10,7 +10,7 @@ from yookassa import Configuration, Payment from bot import bot from config import YOOKASSA_ENABLE, YOOKASSA_SECRET_KEY, YOOKASSA_SHOP_ID -from database import add_connection, check_connection_exists, get_key_count, update_balance +from database import add_connection, add_payment, check_connection_exists, get_key_count, update_balance from handlers.texts import PAYMENT_OPTIONS from logger import logger @@ -224,6 +224,7 @@ async def yookassa_webhook(request): user_id = int(user_id_str) amount = float(amount_str) logger.debug(f"Payment succeeded for user_id: {user_id}, amount: {amount}") + await add_payment(int(user_id), float(amount), "yookassa") await update_balance(user_id, amount) await send_payment_success_notification(user_id, amount) except ValueError as e: