Enhance button stats middleware with builtin callbacks

Added a set of known builtin callback data for button statistics logging.
This commit is contained in:
Egor
2025-12-21 07:16:55 +03:00
committed by GitHub
parent 01d3659ad2
commit 151ce092b9

View File

@@ -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:
"""Извлекает текст кнопки из клавиатуры."""