diff --git a/app/middlewares/button_stats.py b/app/middlewares/button_stats.py index a676729f..66881c29 100644 --- a/app/middlewares/button_stats.py +++ b/app/middlewares/button_stats.py @@ -1,7 +1,9 @@ """Middleware для автоматического логирования кликов по кнопкам.""" +import asyncio import logging -from typing import Callable, Dict, Any, Awaitable +from typing import Callable, Dict, Any, Awaitable, Set + from aiogram import BaseMiddleware from aiogram.types import CallbackQuery, TelegramObject @@ -10,10 +12,80 @@ from app.database.database import AsyncSessionLocal logger = logging.getLogger(__name__) +# Известные builtin callback_data из меню +BUILTIN_CALLBACKS: Set[str] = { + # Основные кнопки меню + "subscription_connect", + "subscription_happ_download", + "menu_subscription", + "buy_traffic", + "menu_balance", + "menu_trial", + "menu_buy", + "simple_subscription_purchase", + "return_to_saved_cart", + "menu_promocode", + "menu_referrals", + "contests_menu", + "menu_support", + "menu_info", + "menu_language", + "admin_panel", + "moderator_panel", + # Навигация + "back_to_menu", + "menu_faq", + "menu_info_promo_groups", + "menu_privacy_policy", + "menu_public_offer", + "menu_rules", + "menu_server_status", + # Баланс + "balance_history", + "balance_topup", + # Подписка + "subscription_extend", + "subscription_autopay", + "subscription_settings", + "open_subscription_link", + "subscription_add_countries", + "subscription_reset_traffic", + "subscription_switch_traffic", + "subscription_change_devices", + "subscription_manage_devices", + "subscription_upgrade", + # Устройства + "device_guide_ios", + "device_guide_android", + "device_guide_windows", + "device_guide_mac", + "device_guide_tv", + "device_guide_appletv", + # Happ + "happ_download_ios", + "happ_download_android", + "happ_download_macos", + "happ_download_windows", + # Рефералы + "referral_create_invite", + "referral_show_qr", + "referral_list", + "referral_analytics", + # Поддержка + "create_ticket", + "my_tickets", + # Триал + "trial_activate", + # Покупка + "clear_saved_cart", + "subscription_confirm", + "subscription_cancel", +} + class ButtonStatsMiddleware(BaseMiddleware): """Middleware для автоматического логирования статистики кликов по кнопкам.""" - + async def __call__( self, handler: Callable[[TelegramObject, Dict[str, Any]], Awaitable[Any]], @@ -49,8 +121,6 @@ class ButtonStatsMiddleware(BaseMiddleware): button_text = self._extract_button_text(event.message.reply_markup, callback_data) # Логируем в фоне, не блокируя обработку - # Используем asyncio.create_task для фоновой задачи - import asyncio asyncio.create_task( self._log_button_click_async( button_id=callback_data, @@ -68,13 +138,31 @@ class ButtonStatsMiddleware(BaseMiddleware): return await handler(event, data) def _determine_button_type(self, callback_data: str) -> str: - """Определяет тип кнопки по callback_data.""" - if callback_data.startswith("http://") or callback_data.startswith("https://"): - return "url" - elif callback_data.startswith("menu_") or callback_data.startswith("admin_"): + """Определяет тип кнопки по callback_data. + + Примечание: URL и MiniApp кнопки не имеют callback_data, + поэтому они не отслеживаются через этот middleware. + Для их отслеживания нужен отдельный механизм на стороне клиента. + """ + # Проверяем по известному списку builtin кнопок + if callback_data in BUILTIN_CALLBACKS: return "builtin" - else: - return "callback" + + # Дополнительная проверка по префиксам для динамических callback_data + builtin_prefixes = ( + "menu_", + "admin_", + "subscription_", + "balance_", + "referral_", + "device_guide_", + "happ_download_", + ) + if callback_data.startswith(builtin_prefixes): + return "builtin" + + # Всё остальное - кастомные callback кнопки + return "callback" def _extract_button_text(self, reply_markup, callback_data: str) -> str: """Извлекает текст кнопки из клавиатуры."""