From b3b21d1f5f4775028e351f0f17a145cf78b45d38 Mon Sep 17 00:00:00 2001 From: Vladless Date: Mon, 19 May 2025 11:08:51 +0300 Subject: [PATCH] minor improvements --- assets/schema.sql | 21 +++++++++++++++++++++ bot.py | 2 +- handlers/admin/bans/bans_handler.py | 16 ++++++++++++++++ handlers/admin/bans/keyboard.py | 5 +++-- handlers/buttons.py | 4 ++++ handlers/start.py | 11 +++++++---- middlewares/loggings.py | 17 +++++------------ 7 files changed, 57 insertions(+), 19 deletions(-) diff --git a/assets/schema.sql b/assets/schema.sql index d557cc17..5ed0bcd6 100644 --- a/assets/schema.sql +++ b/assets/schema.sql @@ -166,6 +166,27 @@ BEGIN ) THEN ALTER TABLE servers ADD COLUMN tariff_group TEXT; END IF; + + IF NOT EXISTS ( + SELECT 1 FROM information_schema.columns + WHERE table_name = 'servers' AND column_name = 'panel_type' + ) THEN + ALTER TABLE servers ADD COLUMN panel_type TEXT NOT NULL DEFAULT '3x-ui'; + END IF; + + IF NOT EXISTS ( + SELECT 1 FROM information_schema.columns + WHERE table_name = 'servers' AND column_name = 'enabled' + ) THEN + ALTER TABLE servers ADD COLUMN enabled BOOLEAN NOT NULL DEFAULT TRUE; + END IF; + + IF NOT EXISTS ( + SELECT 1 FROM information_schema.columns + WHERE table_name = 'servers' AND column_name = 'max_keys' + ) THEN + ALTER TABLE servers ADD COLUMN max_keys INTEGER; + END IF; END$$; diff --git a/bot.py b/bot.py index 587bd8fa..abab5746 100644 --- a/bot.py +++ b/bot.py @@ -19,7 +19,7 @@ bot = Bot(token=API_TOKEN, default=DefaultBotProperties(parse_mode=ParseMode.HTM storage = MemoryStorage() dp = Dispatcher(bot=bot, storage=storage) -version = "4.3-b160513" +version = "4.3-b190508" register_middleware(dp) diff --git a/handlers/admin/bans/bans_handler.py b/handlers/admin/bans/bans_handler.py index 35d4b9e2..78161f37 100644 --- a/handlers/admin/bans/bans_handler.py +++ b/handlers/admin/bans/bans_handler.py @@ -11,6 +11,8 @@ from .keyboard import build_bans_kb import csv import io +from logger import logger + router = Router() @@ -121,3 +123,17 @@ async def handle_manual_bans_export(callback_query: CallbackQuery, session: Any) text=f"❗ Ошибка при экспорте: {e}", reply_markup=build_admin_back_kb("bans"), ) + + +@router.callback_query(AdminPanelCallback.filter(F.action == "bans_delete_manual"), IsAdminFilter()) +async def handle_delete_manual_banned(callback_query: CallbackQuery, session): + try: + await session.execute("DELETE FROM manual_bans") + await callback_query.message.edit_text( + "🗑️ Вручную забаненные пользователи удалены.", + reply_markup=build_bans_kb(), + ) + logger.info("[BANS] Очищены записи из manual_bans") + except Exception as e: + logger.error(f"[BANS] Ошибка при очистке manual_bans: {e}") + await callback_query.message.edit_text("❌ Ошибка при удалении вручную забаненных пользователей.") diff --git a/handlers/admin/bans/keyboard.py b/handlers/admin/bans/keyboard.py index b47fdcdb..4cf4ab02 100644 --- a/handlers/admin/bans/keyboard.py +++ b/handlers/admin/bans/keyboard.py @@ -9,8 +9,9 @@ def build_bans_kb(): builder.button(text="📛 Забанившие бота", callback_data=AdminPanelCallback(action="bans_export").pack()) builder.button(text="📛 Забаненные вручную", callback_data=AdminPanelCallback(action="manual_bans_export").pack()) - builder.button(text="🗑️ Очистить забанивших", callback_data=AdminPanelCallback(action="bans_delete_banned").pack()) - builder.button(text="🔙 Назад",callback_data=AdminPanelCallback(action="management").pack()) + builder.button(text="🗑️ Удалить забанивших", callback_data=AdminPanelCallback(action="bans_delete_banned").pack()) + builder.button(text="🗑️ Очистить вручную забаненных", callback_data=AdminPanelCallback(action="bans_delete_manual").pack()) + builder.button(text="🔙 Назад", callback_data=AdminPanelCallback(action="management").pack()) builder.adjust(1) return builder.as_markup() diff --git a/handlers/buttons.py b/handlers/buttons.py index 31d10839..e87fe129 100644 --- a/handlers/buttons.py +++ b/handlers/buttons.py @@ -33,6 +33,10 @@ ROBOKASSA = "⭐ RoboKassa" DISCOUNT_TARIFF = "🔥 Получить скидку" MAX_DISCOUNT_TARIFF = "⚡ Получить максимальную скидку" +# Кнопки подписки на канал +SUB_CHANELL = "📢 Подписаться" +SUB_CHANELL_DONE = "✅ Я подписался" + # Подарки GIFT = "🎁 Подарить подписку" diff --git a/handlers/start.py b/handlers/start.py index 528bf440..a2502d11 100644 --- a/handlers/start.py +++ b/handlers/start.py @@ -28,7 +28,7 @@ from database import ( check_user_exists, get_trial, ) -from handlers.buttons import ABOUT_VPN, BACK, CHANNEL, MAIN_MENU, SUPPORT, TRIAL_SUB +from handlers.buttons import ABOUT_VPN, BACK, CHANNEL, MAIN_MENU, SUPPORT, TRIAL_SUB, SUB_CHANELL_DONE, SUB_CHANELL from handlers.captcha import generate_captcha from handlers.coupons import activate_coupon from handlers.payments.gift import handle_gift_link @@ -89,7 +89,8 @@ async def check_subscription_callback(callback_query: CallbackQuery, state: FSMC if member.status not in ["member", "administrator", "creator"]: await callback_query.answer(NOT_SUBSCRIBED_YET_MSG, show_alert=True) builder = InlineKeyboardBuilder() - builder.row(InlineKeyboardButton(text="✅ Я подписался", callback_data="check_subscription")) + builder.row(InlineKeyboardButton(text=SUB_CHANELL, url=CHANNEL_URL)) + builder.row(InlineKeyboardButton(text=SUB_CHANELL_DONE, callback_data="check_subscription")) await callback_query.message.edit_text( SUBSCRIPTION_REQUIRED_MSG, reply_markup=builder.as_markup(), @@ -140,7 +141,8 @@ async def process_start_logic( if member.status not in ["member", "administrator", "creator"]: await state.update_data(original_text=text, user_data=user_data) builder = InlineKeyboardBuilder() - builder.row(InlineKeyboardButton(text="✅ Я подписался", callback_data="check_subscription")) + builder.row(InlineKeyboardButton(text=SUB_CHANELL, url=CHANNEL_URL)) + builder.row(InlineKeyboardButton(text=SUB_CHANELL_DONE, callback_data="check_subscription")) await edit_or_send_message( target_message=message, text=SUBSCRIPTION_REQUIRED_MSG, @@ -151,7 +153,8 @@ async def process_start_logic( logger.error(f"Ошибка проверки подписки для {user_data['tg_id']}: {e}") await state.update_data(original_text=text, user_data=user_data) builder = InlineKeyboardBuilder() - builder.row(InlineKeyboardButton(text="✅ Я подписался", callback_data="check_subscription")) + builder.row(InlineKeyboardButton(text=SUB_CHANELL, url=CHANNEL_URL)) + builder.row(InlineKeyboardButton(text=SUB_CHANELL_DONE, callback_data="check_subscription")) await edit_or_send_message( target_message=message, text=SUBSCRIPTION_REQUIRED_MSG, diff --git a/middlewares/loggings.py b/middlewares/loggings.py index f329759f..fbb41692 100644 --- a/middlewares/loggings.py +++ b/middlewares/loggings.py @@ -26,23 +26,16 @@ class LoggingMiddleware(BaseMiddleware): if user_info["user_id"]: logger.info( - f"Активность пользователя - " - f"ID пользователя: {user_info['user_id']}, " - f"Имя пользователя: {user_info['username'] or 'Не указано'}, " - f"Действие: {user_info['action'] or 'Неизвестно'}" + f"Активность пользователя │ " + f"ID: {str(user_info['user_id']).ljust(10)} │ " + f"Имя: {user_info['username'] or '—':<15} │ " + f"Действие: {user_info['action'] or '—'}" ) return await handler(event, data) def _extract_user_info(self, event: TelegramObject) -> UserInfo: - """Извлекает информацию о пользователе из различных типов событий. - - Args: - event: Событие Telegram - - Returns: - Словарь с информацией о пользователе - """ + """Извлекает информацию о пользователе из различных типов событий.""" result: UserInfo = {"user_id": None, "username": None, "action": None} if hasattr(event, "from_user") and isinstance(event.from_user, User):