Add subscribe reminder buttons and update notifications

This commit is contained in:
Machka Pasla
2025-07-12 10:01:25 +07:00
parent 16a00efcc9
commit a7b4863889
4 changed files with 50 additions and 14 deletions
+8
View File
@@ -169,6 +169,14 @@ def get_back_to_main_menu_markup(lang: str,
return builder.as_markup()
def get_subscribe_only_markup(lang: str, i18n_instance) -> InlineKeyboardMarkup:
_ = lambda key, **kwargs: i18n_instance.gettext(lang, key, **kwargs)
builder = InlineKeyboardBuilder()
builder.button(text=_(key="menu_subscribe_inline"),
callback_data="main_action:subscribe")
return builder.as_markup()
def get_user_banned_keyboard(support_link: Optional[str], lang: str,
i18n_instance) -> Optional[InlineKeyboardMarkup]:
if not support_link:
+32 -4
View File
@@ -4,10 +4,12 @@ import hmac
import hashlib
from aiohttp import web
from aiogram import Bot
from aiogram.types import InlineKeyboardMarkup
from sqlalchemy.orm import sessionmaker
from typing import Optional
from config.settings import Settings
from bot.middlewares.i18n import JsonI18n
from bot.keyboards.inline.user_keyboards import get_subscribe_only_markup
from db.dal import user_dal
EVENT_MAP = {
@@ -23,10 +25,19 @@ class PanelWebhookService:
self.i18n = i18n
self.async_session_factory = async_session_factory
async def _send_message(self, user_id: int, lang: str, message_key: str, **kwargs):
async def _send_message(
self,
user_id: int,
lang: str,
message_key: str,
reply_markup: InlineKeyboardMarkup | None = None,
**kwargs,
):
_ = lambda k, **kw: self.i18n.gettext(lang, k, **kw)
try:
await self.bot.send_message(user_id, _(message_key, **kwargs))
await self.bot.send_message(
user_id, _(message_key, **kwargs), reply_markup=reply_markup
)
except Exception as e:
logging.error(f"Failed to send notification to {user_id}: {e}")
@@ -45,6 +56,8 @@ class PanelWebhookService:
lang = db_user.language_code if db_user and db_user.language_code else self.settings.DEFAULT_LANGUAGE
first_name = db_user.first_name or f"User {user_id}" if db_user else f"User {user_id}"
markup = get_subscribe_only_markup(lang, self.i18n)
if event_name in EVENT_MAP:
days_left, msg_key = EVENT_MAP[event_name]
if days_left <= self.settings.SUBSCRIPTION_NOTIFY_DAYS_BEFORE:
@@ -52,13 +65,28 @@ class PanelWebhookService:
user_id,
lang,
msg_key,
reply_markup=markup,
user_name=first_name,
end_date=user_payload.get("expireAt", "")[:10],
)
elif event_name == "user.expired" and self.settings.SUBSCRIPTION_NOTIFY_ON_EXPIRE:
await self._send_message(user_id, lang, "subscription_expired_notification")
await self._send_message(
user_id,
lang,
"subscription_expired_notification",
reply_markup=markup,
user_name=first_name,
end_date=user_payload.get("expireAt", "")[:10],
)
elif event_name == "user.expired_24_hours_ago" and self.settings.SUBSCRIPTION_NOTIFY_AFTER_EXPIRE:
await self._send_message(user_id, lang, "subscription_expired_yesterday_notification")
await self._send_message(
user_id,
lang,
"subscription_expired_yesterday_notification",
reply_markup=markup,
user_name=first_name,
end_date=user_payload.get("expireAt", "")[:10],
)
async def handle_webhook(self, raw_body: bytes, signature_header: Optional[str]) -> web.Response:
if self.settings.PANEL_WEBHOOK_SECRET:
+5 -5
View File
@@ -211,11 +211,11 @@
"error_displaying_statistics": "Error displaying statistics.",
"stub_page_display": "Page",
"subscription_72h_notification": "👋 Hi, {user_name}!\n\n⏳ Your VPN subscription ends in 72 hours on {end_date}.\n\nPlease renew it in the main menu.",
"subscription_48h_notification": "👋 Hi, {user_name}!\n\n⏳ Your VPN subscription ends in 48 hours on {end_date}.\n\nPlease renew it in the main menu.",
"subscription_24h_notification": "👋 Hi, {user_name}!\n\n⏳ Your VPN subscription ends in 24 hours on {end_date}.\n\nPlease renew it in the main menu.",
"subscription_expired_notification": "Your VPN subscription has expired.",
"subscription_expired_yesterday_notification": "Your VPN subscription expired 24 hours ago.",
"subscription_72h_notification": "👋 Hi, {user_name}!\n\n⏳ Your VPN subscription expires in 3 days — {end_date}.\n\nPlease renew it using the button below.",
"subscription_48h_notification": "👋 Hi, {user_name}!\n\n⏳ Your VPN subscription expires in 2 days — {end_date}.\n\nPlease renew it using the button below.",
"subscription_24h_notification": "👋 Hi, {user_name}!\n\n⏳ Your VPN subscription expires in 1 day — {end_date}.\n\nPlease renew it using the button below.",
"subscription_expired_notification": "👋 Hi, {user_name}!\n\n⛔ Your VPN subscription expired on {end_date}.\n\nPlease renew it using the button below.",
"subscription_expired_yesterday_notification": "👋 Hi, {user_name}!\n\n⏳ Your VPN subscription expired yesterday ({end_date}).\n\nPlease renew it using the button below.",
"admin_new_trial_notification": "\ud83c\udf21 User {user_id} activated a free trial until {end_date}.",
"admin_new_payment_notification": "\ud83d\udcb3 Payment received from user {user_id}: {months} mo. for {amount} {currency}.",
+5 -5
View File
@@ -211,11 +211,11 @@
"error_displaying_statistics": "Ошибка отображения статистики.",
"stub_page_display": "Страница",
"subscription_72h_notification": "👋 Привет, {user_name}!\n\n⏳ Ваша подписка на VPN истекает через 72 часа ({end_date}).\n\nПожалуйста, продлите её в главном меню бота.",
"subscription_48h_notification": "👋 Привет, {user_name}!\n\n⏳ Ваша подписка на VPN истекает через 48 часов ({end_date}).\n\nПожалуйста, продлите её в главном меню бота.",
"subscription_24h_notification": "👋 Привет, {user_name}!\n\n⏳ Ваша подписка на VPN истекает через 24 часа ({end_date}).\n\nПожалуйста, продлите её в главном меню бота.",
"subscription_expired_notification": "Срок вашей подписки истек.",
"subscription_expired_yesterday_notification": "Ваша подписка истекла сутки назад.",
"subscription_72h_notification": "👋 Привет, {user_name}!\n\n⏳ Ваша подписка на VPN истекает через 3 дня — {end_date}.\n\nПродлите её по кнопке ниже.",
"subscription_48h_notification": "👋 Привет, {user_name}!\n\n⏳ Ваша подписка на VPN истекает через 2 дня — {end_date}.\n\nПродлите её по кнопке ниже.",
"subscription_24h_notification": "👋 Привет, {user_name}!\n\n⏳ Ваша подписка на VPN истекает через 1 день — {end_date}.\n\nПродлите её по кнопке ниже.",
"subscription_expired_notification": "👋 Привет, {user_name}!\n\n⛔ Срок вашей подписки на VPN истек ({end_date}).\n\nПродлите её по кнопке ниже.",
"subscription_expired_yesterday_notification": "👋 Привет, {user_name}!\n\n⏳ Ваша подписка на VPN истекла сутки назад ({end_date}).\n\nПродлите её по кнопке ниже.",
"admin_new_trial_notification": "\ud83c\udf21 Пользователь {user_id} активировал пробный период до {end_date}.",
"admin_new_payment_notification": "\ud83d\udcb3 Получен платеж от пользователя {user_id}: {months} мес. за {amount} {currency}.",