feat: add close button to all webhook notifications

Add dismissible close button (✖️) to every webhook notification message.
Users can now close any webhook notification by tapping the button,
which deletes the message via webhook:close callback handler.
This commit is contained in:
Fringg
2026-02-10 06:22:17 +03:00
parent 17ce64037f
commit d9de15a5a0
7 changed files with 34 additions and 7 deletions

View File

@@ -25,6 +25,17 @@ async def handle_delete_ban_notification(
await callback.answer('Не удалось удалить', show_alert=False)
async def handle_webhook_notification_close(
callback: types.CallbackQuery,
):
"""Удаляет webhook-уведомление при нажатии кнопки Закрыть."""
try:
await callback.message.delete()
except Exception:
pass
await callback.answer()
async def handle_unknown_callback(callback: types.CallbackQuery, db_user: User):
texts = get_texts(db_user.language if db_user else 'ru')
@@ -86,8 +97,9 @@ async def show_rules(callback: types.CallbackQuery, db_user: User, db: AsyncSess
def register_handlers(dp: Dispatcher):
# Удаление уведомлений о банах
# Удаление уведомлений
dp.callback_query.register(handle_delete_ban_notification, F.data == 'ban_notify:delete')
dp.callback_query.register(handle_webhook_notification_close, F.data == 'webhook:close')
dp.callback_query.register(show_rules, F.data == 'menu_rules')

View File

@@ -1716,5 +1716,6 @@
"WEBHOOK_RENEW_BUTTON": "🔄 Renew subscription",
"WEBHOOK_USER_NOT_CONNECTED": "📡 <b>Not connected yet</b>\n\nYour subscription is active but no VPN connection has been made. Connect to start using the service.",
"WEBHOOK_DEVICE_ADDED": "📱 <b>New device</b>\n\nA new device has been added to your subscription: <code>{device}</code>",
"WEBHOOK_DEVICE_DELETED": "📱 <b>Device removed</b>\n\nA device has been removed from your subscription: <code>{device}</code>"
"WEBHOOK_DEVICE_DELETED": "📱 <b>Device removed</b>\n\nA device has been removed from your subscription: <code>{device}</code>",
"WEBHOOK_CLOSE_BUTTON": "✖️ Close"
}

View File

@@ -1734,5 +1734,6 @@
"WEBHOOK_RENEW_BUTTON": "🔄 تمدید اشتراک",
"WEBHOOK_USER_NOT_CONNECTED": "📡 <b>هنوز متصل نشده‌اید</b>\n\nاشتراک شما فعال است اما هنوز اتصال VPN برقرار نشده. برای شروع استفاده متصل شوید.",
"WEBHOOK_DEVICE_ADDED": "📱 <b>دستگاه جدید</b>\n\nدستگاه جدیدی به اشتراک شما اضافه شد: <code>{device}</code>",
"WEBHOOK_DEVICE_DELETED": "📱 <b>دستگاه حذف شد</b>\n\nدستگاهی از اشتراک شما حذف شد: <code>{device}</code>"
"WEBHOOK_DEVICE_DELETED": "📱 <b>دستگاه حذف شد</b>\n\nدستگاهی از اشتراک شما حذف شد: <code>{device}</code>",
"WEBHOOK_CLOSE_BUTTON": "✖️ بستن"
}

View File

@@ -1737,5 +1737,6 @@
"WEBHOOK_RENEW_BUTTON": "🔄 Продлить подписку",
"WEBHOOK_USER_NOT_CONNECTED": "📡 <b>Вы ещё не подключились</b>\n\nВаша подписка активна, но VPN-соединение не было установлено. Подключитесь, чтобы начать пользоваться.",
"WEBHOOK_DEVICE_ADDED": "📱 <b>Новое устройство</b>\n\nК вашей подписке подключено новое устройство: <code>{device}</code>",
"WEBHOOK_DEVICE_DELETED": "📱 <b>Устройство удалено</b>\n\nУстройство отключено от подписки: <code>{device}</code>"
"WEBHOOK_DEVICE_DELETED": "📱 <b>Устройство удалено</b>\n\nУстройство отключено от подписки: <code>{device}</code>",
"WEBHOOK_CLOSE_BUTTON": "✖️ Закрыть"
}

View File

@@ -1603,5 +1603,6 @@
"WEBHOOK_RENEW_BUTTON": "🔄 Продовжити підписку",
"WEBHOOK_USER_NOT_CONNECTED": "📡 <b>Ви ще не підключились</b>\n\nВаша підписка активна, але VPN-з'єднання не було встановлено. Підключіться, щоб почати користуватися.",
"WEBHOOK_DEVICE_ADDED": "📱 <b>Новий пристрій</b>\n\nДо вашої підписки підключено новий пристрій: <code>{device}</code>",
"WEBHOOK_DEVICE_DELETED": "📱 <b>Пристрій видалено</b>\n\nПристрій відключено від підписки: <code>{device}</code>"
"WEBHOOK_DEVICE_DELETED": "📱 <b>Пристрій видалено</b>\n\nПристрій відключено від підписки: <code>{device}</code>",
"WEBHOOK_CLOSE_BUTTON": "✖️ Закрити"
}

View File

@@ -1936,5 +1936,6 @@
"WEBHOOK_RENEW_BUTTON":"🔄 续订订阅",
"WEBHOOK_USER_NOT_CONNECTED":"📡 <b>尚未连接</b>\n\n您的订阅已激活但尚未建立VPN连接。请连接以开始使用服务。",
"WEBHOOK_DEVICE_ADDED":"📱 <b>新设备</b>\n\n您的订阅已添加新设备<code>{device}</code>",
"WEBHOOK_DEVICE_DELETED":"📱 <b>设备已移除</b>\n\n设备已从您的订阅中移除<code>{device}</code>"
"WEBHOOK_DEVICE_DELETED":"📱 <b>设备已移除</b>\n\n设备已从您的订阅中移除<code>{device}</code>",
"WEBHOOK_CLOSE_BUTTON":"✖️ 关闭"
}

View File

@@ -15,7 +15,7 @@ from datetime import UTC, datetime
from typing import Any
from aiogram import Bot
from aiogram.types import InlineKeyboardMarkup
from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup
from sqlalchemy.ext.asyncio import AsyncSession
from app.database.crud.subscription import (
@@ -347,6 +347,16 @@ class RemnaWaveWebhookService:
logger.warning('Failed to format message %s with kwargs %s', text_key, format_kwargs)
return
# Append "Close" button to every webhook notification keyboard
close_text = texts.get('WEBHOOK_CLOSE_BUTTON', '✖️ Закрыть')
close_row = [InlineKeyboardButton(text=close_text, callback_data='webhook:close')]
if reply_markup:
reply_markup = InlineKeyboardMarkup(
inline_keyboard=[*reply_markup.inline_keyboard, close_row],
)
else:
reply_markup = InlineKeyboardMarkup(inline_keyboard=[close_row])
notification_type = _TEXT_KEY_TO_NOTIFICATION_TYPE.get(text_key)
if not notification_type:
logger.warning('No NotificationType mapping for text_key %s', text_key)