Merge pull request #45 from machka-pasla/codex/refactor-subscription-notifications-style
Update subscription expiration notifications
This commit is contained in:
@@ -169,6 +169,14 @@ def get_back_to_main_menu_markup(lang: str,
|
|||||||
return builder.as_markup()
|
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,
|
def get_user_banned_keyboard(support_link: Optional[str], lang: str,
|
||||||
i18n_instance) -> Optional[InlineKeyboardMarkup]:
|
i18n_instance) -> Optional[InlineKeyboardMarkup]:
|
||||||
if not support_link:
|
if not support_link:
|
||||||
|
|||||||
@@ -4,10 +4,12 @@ import hmac
|
|||||||
import hashlib
|
import hashlib
|
||||||
from aiohttp import web
|
from aiohttp import web
|
||||||
from aiogram import Bot
|
from aiogram import Bot
|
||||||
|
from aiogram.types import InlineKeyboardMarkup
|
||||||
from sqlalchemy.orm import sessionmaker
|
from sqlalchemy.orm import sessionmaker
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
from config.settings import Settings
|
from config.settings import Settings
|
||||||
from bot.middlewares.i18n import JsonI18n
|
from bot.middlewares.i18n import JsonI18n
|
||||||
|
from bot.keyboards.inline.user_keyboards import get_subscribe_only_markup
|
||||||
from db.dal import user_dal
|
from db.dal import user_dal
|
||||||
|
|
||||||
EVENT_MAP = {
|
EVENT_MAP = {
|
||||||
@@ -23,10 +25,19 @@ class PanelWebhookService:
|
|||||||
self.i18n = i18n
|
self.i18n = i18n
|
||||||
self.async_session_factory = async_session_factory
|
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)
|
_ = lambda k, **kw: self.i18n.gettext(lang, k, **kw)
|
||||||
try:
|
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:
|
except Exception as e:
|
||||||
logging.error(f"Failed to send notification to {user_id}: {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
|
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}"
|
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:
|
if event_name in EVENT_MAP:
|
||||||
days_left, msg_key = EVENT_MAP[event_name]
|
days_left, msg_key = EVENT_MAP[event_name]
|
||||||
if days_left <= self.settings.SUBSCRIPTION_NOTIFY_DAYS_BEFORE:
|
if days_left <= self.settings.SUBSCRIPTION_NOTIFY_DAYS_BEFORE:
|
||||||
@@ -52,13 +65,28 @@ class PanelWebhookService:
|
|||||||
user_id,
|
user_id,
|
||||||
lang,
|
lang,
|
||||||
msg_key,
|
msg_key,
|
||||||
|
reply_markup=markup,
|
||||||
user_name=first_name,
|
user_name=first_name,
|
||||||
end_date=user_payload.get("expireAt", "")[:10],
|
end_date=user_payload.get("expireAt", "")[:10],
|
||||||
)
|
)
|
||||||
elif event_name == "user.expired" and self.settings.SUBSCRIPTION_NOTIFY_ON_EXPIRE:
|
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:
|
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:
|
async def handle_webhook(self, raw_body: bytes, signature_header: Optional[str]) -> web.Response:
|
||||||
if self.settings.PANEL_WEBHOOK_SECRET:
|
if self.settings.PANEL_WEBHOOK_SECRET:
|
||||||
|
|||||||
+5
-5
@@ -211,11 +211,11 @@
|
|||||||
"error_displaying_statistics": "Error displaying statistics.",
|
"error_displaying_statistics": "Error displaying statistics.",
|
||||||
"stub_page_display": "Page",
|
"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_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 ends in 48 hours on {end_date}.\n\nPlease renew it in the main menu.",
|
"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 ends in 24 hours on {end_date}.\n\nPlease renew it in the main menu.",
|
"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": "Your VPN subscription has expired.",
|
"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": "Your VPN subscription expired 24 hours ago.",
|
"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_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}.",
|
"admin_new_payment_notification": "\ud83d\udcb3 Payment received from user {user_id}: {months} mo. for {amount} {currency}.",
|
||||||
|
|||||||
+5
-5
@@ -211,11 +211,11 @@
|
|||||||
"error_displaying_statistics": "Ошибка отображения статистики.",
|
"error_displaying_statistics": "Ошибка отображения статистики.",
|
||||||
"stub_page_display": "Страница",
|
"stub_page_display": "Страница",
|
||||||
|
|
||||||
"subscription_72h_notification": "👋 Привет, {user_name}!\n\n⏳ Ваша подписка на VPN истекает через 72 часа ({end_date}).\n\nПожалуйста, продлите её в главном меню бота.",
|
"subscription_72h_notification": "👋 Привет, {user_name}!\n\n⏳ Ваша подписка на VPN истекает через 3 дня — {end_date}.\n\nПродлите её по кнопке ниже.",
|
||||||
"subscription_48h_notification": "👋 Привет, {user_name}!\n\n⏳ Ваша подписка на VPN истекает через 48 часов ({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 истекает через 24 часа ({end_date}).\n\nПожалуйста, продлите её в главном меню бота.",
|
"subscription_24h_notification": "👋 Привет, {user_name}!\n\n⏳ Ваша подписка на VPN истекает через 1 день — {end_date}.\n\nПродлите её по кнопке ниже.",
|
||||||
"subscription_expired_notification": "Срок вашей подписки истек.",
|
"subscription_expired_notification": "👋 Привет, {user_name}!\n\n⛔ Срок вашей подписки на VPN истек ({end_date}).\n\nПродлите её по кнопке ниже.",
|
||||||
"subscription_expired_yesterday_notification": "Ваша подписка истекла сутки назад.",
|
"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_trial_notification": "\ud83c\udf21 Пользователь {user_id} активировал пробный период до {end_date}.",
|
||||||
"admin_new_payment_notification": "\ud83d\udcb3 Получен платеж от пользователя {user_id}: {months} мес. за {amount} {currency}.",
|
"admin_new_payment_notification": "\ud83d\udcb3 Получен платеж от пользователя {user_id}: {months} мес. за {amount} {currency}.",
|
||||||
|
|||||||
Reference in New Issue
Block a user