From d94b57bd0bbea144f787bf5d7a44746ff8b2d629 Mon Sep 17 00:00:00 2001 From: 3252a8 <3252a8@proton.me> Date: Mon, 9 Feb 2026 10:09:16 +0300 Subject: [PATCH] User card links in ratings --- bot/handlers/admin/statistics.py | 30 ++++++++++++++++++++++-- bot/keyboards/inline/admin_keyboards.py | 31 +++++++++++++++++++++++++ locales/en.json | 2 ++ locales/ru.json | 2 ++ 4 files changed, 63 insertions(+), 2 deletions(-) diff --git a/bot/handlers/admin/statistics.py b/bot/handlers/admin/statistics.py index 25ef509..5210dbd 100644 --- a/bot/handlers/admin/statistics.py +++ b/bot/handlers/admin/statistics.py @@ -13,7 +13,7 @@ from bot.services.panel_api_service import PanelApiService from bot.keyboards.inline.admin_keyboards import ( get_back_to_admin_panel_keyboard, - get_back_to_user_management_keyboard, + get_user_ratings_keyboard, ) from bot.middlewares.i18n import JsonI18n @@ -39,6 +39,18 @@ def _format_rating_user_label(user_row: Dict[str, object]) -> str: return " ".join(parts) +def _format_rating_user_short_label(user_row: Dict[str, object]) -> str: + username = user_row.get("username") + first_name = user_row.get("first_name") + user_id = int(user_row.get("user_id", 0) or 0) + + if username: + return f"@{html.escape(str(username))}" + if first_name: + return html.escape(str(first_name)) + return f"ID {user_id}" + + async def show_statistics_handler(callback: types.CallbackQuery, i18n_data: dict, settings: Settings, session: AsyncSession): @@ -348,8 +360,22 @@ async def show_user_ratings_handler( else: text_parts.append(_("admin_user_ratings_empty")) + unique_users: Dict[int, Dict[str, object]] = {} + for row in traffic_top + invited_top + revenue_top: + user_id = int(row.get("user_id", 0) or 0) + if user_id <= 0 or user_id in unique_users: + continue + unique_users[user_id] = { + "user_id": user_id, + "label": _format_rating_user_short_label(row), + } + await callback.message.edit_text( "\n".join(text_parts), - reply_markup=get_back_to_user_management_keyboard(current_lang, i18n), + reply_markup=get_user_ratings_keyboard( + list(unique_users.values()), + current_lang, + i18n, + ), parse_mode="HTML", ) diff --git a/bot/keyboards/inline/admin_keyboards.py b/bot/keyboards/inline/admin_keyboards.py index 66ad5ea..78f3512 100644 --- a/bot/keyboards/inline/admin_keyboards.py +++ b/bot/keyboards/inline/admin_keyboards.py @@ -480,3 +480,34 @@ def get_back_to_user_management_keyboard(lang: str, builder.button(text=_(key="back_to_user_management_button"), callback_data="admin_section:user_management") return builder.as_markup() + + +def get_user_ratings_keyboard(rating_users: List[dict], + lang: str, + i18n_instance) -> InlineKeyboardMarkup: + _ = lambda key, **kwargs: i18n_instance.gettext(lang, key, **kwargs) + builder = InlineKeyboardBuilder() + + for entry in rating_users: + user_id = int(entry.get("user_id", 0) or 0) + if user_id <= 0: + continue + + label = str(entry.get("label", "")).strip() + if label: + button_text = _("admin_user_ratings_open_user_button", + user_id=user_id, + user_label=label) + else: + button_text = _("admin_user_ratings_open_user_button_simple", + user_id=user_id) + + builder.button( + text=button_text, + callback_data=f"admin_user_card_from_list:{user_id}:0", + ) + + builder.button(text=_(key="back_to_user_management_button"), + callback_data="admin_section:user_management") + builder.adjust(1) + return builder.as_markup() diff --git a/locales/en.json b/locales/en.json index f022b37..029318c 100644 --- a/locales/en.json +++ b/locales/en.json @@ -142,6 +142,8 @@ "admin_user_ratings_invited_item": "{rank}. {user} — {invited_count}", "admin_user_ratings_revenue_item": "{rank}. {user} — {revenue} RUB", "admin_user_ratings_empty": "No data yet.", + "admin_user_ratings_open_user_button": "👤 ID {user_id} ({user_label})", + "admin_user_ratings_open_user_button_simple": "👤 ID {user_id}", "admin_payments_header": "💰 All Payments", "admin_no_payments_found": "No payments found.", "admin_export_payments_csv": "📊 Export CSV", diff --git a/locales/ru.json b/locales/ru.json index 96bd1c7..c69fee0 100644 --- a/locales/ru.json +++ b/locales/ru.json @@ -142,6 +142,8 @@ "admin_user_ratings_invited_item": "{rank}. {user} — {invited_count}", "admin_user_ratings_revenue_item": "{rank}. {user} — {revenue} RUB", "admin_user_ratings_empty": "Пока нет данных.", + "admin_user_ratings_open_user_button": "👤 ID {user_id} ({user_label})", + "admin_user_ratings_open_user_button_simple": "👤 ID {user_id}", "admin_payments_header": "💰 Все платежи", "admin_no_payments_found": "Платежи не найдены.", "admin_export_payments_csv": "📊 Экспорт CSV",