From d059e7b1be2db386fee9c150d2be9606bff4778d Mon Sep 17 00:00:00 2001 From: Vlad Date: Sat, 7 Jun 2025 08:02:30 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=B2=D0=BE=D0=B7=D0=BC=D0=BE=D0=B6=D0=BD=D0=BE?= =?UTF-8?q?=D1=81=D1=82=D1=8C=20=D0=BE=D1=82=D0=BE=D0=B1=D1=80=D0=B0=D0=B6?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D1=8F=20=D1=81=D1=82=D0=B0=D1=82=D0=B8=D1=81?= =?UTF-8?q?=D1=82=D0=B8=D0=BA=D0=B8=20=D0=B4=D0=BB=D1=8F=20=D0=B0=D0=B4?= =?UTF-8?q?=D0=BC=D0=B8=D0=BD=D0=B8=D1=81=D1=82=D1=80=D0=B0=D1=82=D0=BE?= =?UTF-8?q?=D1=80=D0=B0.=20=D0=A0=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0=D0=BD=D0=B0=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80?= =?UTF-8?q?=D0=BA=D0=B0=20=D0=BF=D1=80=D0=B0=D0=B2=20=D0=B4=D0=BE=D1=81?= =?UTF-8?q?=D1=82=D1=83=D0=BF=D0=B0=20=D0=B8=20=D1=84=D0=BE=D1=80=D0=BC?= =?UTF-8?q?=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20=D0=BE=D1=82?= =?UTF-8?q?=D1=87=D0=B5=D1=82=D0=B0=20=D0=BE=20=D0=BF=D0=BE=D0=BB=D1=8C?= =?UTF-8?q?=D0=B7=D0=BE=D0=B2=D0=B0=D1=82=D0=B5=D0=BB=D1=8F=D1=85=20=D0=B8?= =?UTF-8?q?=20=D0=B4=D0=BE=D1=85=D0=BE=D0=B4=D0=B0=D1=85.=20=D0=A2=D0=B0?= =?UTF-8?q?=D0=BA=D0=B6=D0=B5=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=BA=D0=BD=D0=BE=D0=BF=D0=BA=D0=B0=20=D0=B4?= =?UTF-8?q?=D0=BB=D1=8F=20=D0=B4=D0=BE=D1=81=D1=82=D1=83=D0=BF=D0=B0=20?= =?UTF-8?q?=D0=BA=20=D1=81=D1=82=D0=B0=D1=82=D0=B8=D1=81=D1=82=D0=B8=D0=BA?= =?UTF-8?q?=D0=B5=20=D0=B2=20=D0=B8=D0=BD=D1=82=D0=B5=D1=80=D1=84=D0=B5?= =?UTF-8?q?=D0=B9=D1=81=D0=B5.=20=D0=AD=D1=82=D0=B8=20=D0=B8=D0=B7=D0=BC?= =?UTF-8?q?=D0=B5=D0=BD=D0=B5=D0=BD=D0=B8=D1=8F=20=D1=83=D0=BB=D1=83=D1=87?= =?UTF-8?q?=D1=88=D0=B0=D1=8E=D1=82=20=D1=84=D1=83=D0=BD=D0=BA=D1=86=D0=B8?= =?UTF-8?q?=D0=BE=D0=BD=D0=B0=D0=BB=D1=8C=D0=BD=D0=BE=D1=81=D1=82=D1=8C=20?= =?UTF-8?q?=D0=B8=20=D1=83=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20=D0=B1=D0=BE=D1=82=D0=BE=D0=BC=20=D0=B4=D0=BB=D1=8F=20?= =?UTF-8?q?=D0=B0=D0=B4=D0=BC=D0=B8=D0=BD=D0=B8=D1=81=D1=82=D1=80=D0=B0?= =?UTF-8?q?=D1=82=D0=BE=D1=80=D0=BE=D0=B2.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main.py | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/main.py b/main.py index 02eaa70..c201b1b 100644 --- a/main.py +++ b/main.py @@ -418,6 +418,7 @@ DECODE_PRICE = getenv("DECODE_PRICE",1) CHECK_PRICE = getenv("CHECK_PRICE",10) IMG_PRICE = getenv("IMG_PRICE",100) +ADMIN_USER_ID = int(getenv("ADMIN_USER_ID", "0")) # ID администратора из переменных окружения if is_windows(): image_path = "D:\\SALVAGEDB\\salvagedb_bot\\images" @@ -466,7 +467,13 @@ async def command_start_handler(message: Message, db: OracleDatabase = None) -> builder.button(text="Help", callback_data="help") builder.button(text="Prices", callback_data="prices") builder.button(text="Go Salvagedb.com", url="https://salvagedb.com") - builder.adjust(3, 2) + + # Добавляем кнопку администратора только для админа + if message.from_user.id == ADMIN_USER_ID: + builder.button(text="📊 Admin Stats", callback_data="admin_stats") + builder.adjust(3, 3, 1) + else: + builder.adjust(3, 2) await message.answer(welcome_text, reply_markup=builder.as_markup()) @@ -625,6 +632,52 @@ async def prices_callback(callback: CallbackQuery, db: OracleDatabase = None): await callback.answer() +@dp.callback_query(lambda c: c.data == "admin_stats") +async def admin_stats_callback(callback: CallbackQuery, db: OracleDatabase = None): + # Используем переданный db или глобальный oracle_db + database = db or oracle_db + + # Проверяем, является ли пользователь администратором + if callback.from_user.id != ADMIN_USER_ID: + await callback.answer("❌ Access denied. This command is for administrators only.", show_alert=True) + return + + # Сохраняем данные пользователя при нажатии кнопки админки + await database.save_user(callback.from_user, "admin_stats_button") + + try: + # Получаем общую статистику + stats = await database.get_users_summary() + + # Формируем отчет + report = f"""📊 **Bot Users Statistics** + +👥 **Users Overview:** +• Total users: {stats.get('total_users', 0)} +• Premium users: {stats.get('premium_users', 0)} + +💰 **Revenue:** +• Total revenue: {stats.get('total_revenue', 0)} ⭐️ +• Total transactions: {stats.get('total_transactions', 0)} + +📈 **Activity:** +• Active last 24h: {stats.get('active_last_24h', 0)} +• Active last week: {stats.get('active_last_week', 0)} + +📅 **Generated:** {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}""" + + # Создаем кнопку возврата в главное меню + builder = InlineKeyboardBuilder() + builder.button(text="🏠 Back to Main Menu", callback_data="main_menu") + + await callback.message.answer(report, reply_markup=builder.as_markup(), parse_mode="Markdown") + await callback.answer() + + except Exception as e: + logging.error(f"Error generating admin stats via callback: {e}") + await callback.answer("❌ Error generating statistics. Please try again later.", show_alert=True) + + @dp.callback_query(lambda c: c.data and c.data.startswith("pay_detailed_info:")) async def pay_detailed_info_callback(callback: CallbackQuery, db: OracleDatabase = None): # Используем переданный db или глобальный oracle_db @@ -819,7 +872,7 @@ async def pre_checkout_handler(pre_checkout_query: PreCheckoutQuery, db: OracleD await pre_checkout_query.answer(ok=True) -ADMIN_USER_ID = int(getenv("ADMIN_USER_ID", "0")) # ID администратора из переменных окружения + @dp.message(Command("admin_stats")) async def admin_stats_handler(message: Message, db: OracleDatabase = None):