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: