Remove tribute auto renew and add admin notifications
This commit is contained in:
@@ -20,6 +20,7 @@ from bot.services.panel_api_service import PanelApiService
|
||||
from bot.services.yookassa_service import YooKassaService
|
||||
from bot.middlewares.i18n import JsonI18n
|
||||
from config.settings import Settings
|
||||
from bot.services.notification_service import notify_admin_new_payment
|
||||
|
||||
payment_processing_lock = asyncio.Lock()
|
||||
|
||||
@@ -175,6 +176,15 @@ async def process_successful_payment(session: AsyncSession, bot: Bot,
|
||||
f"Failed to send final payment success message to user {user_id}: {e_notify}"
|
||||
)
|
||||
|
||||
await notify_admin_new_payment(
|
||||
bot,
|
||||
settings,
|
||||
i18n,
|
||||
user_id,
|
||||
subscription_months,
|
||||
payment_value,
|
||||
)
|
||||
|
||||
except Exception as e_process:
|
||||
logging.error(
|
||||
f"Error during process_successful_payment main try block for user {user_id}: {e_process}",
|
||||
|
||||
@@ -7,6 +7,7 @@ from datetime import datetime
|
||||
from config.settings import Settings
|
||||
from bot.services.subscription_service import SubscriptionService
|
||||
from bot.services.panel_api_service import PanelApiService
|
||||
from bot.services.notification_service import notify_admin_new_trial
|
||||
from bot.keyboards.inline.user_keyboards import (
|
||||
get_trial_confirmation_keyboard,
|
||||
get_main_menu_inline_keyboard,
|
||||
@@ -189,6 +190,15 @@ async def confirm_activate_trial_handler(
|
||||
disable_web_page_preview=True,
|
||||
)
|
||||
|
||||
if activation_result and activation_result.get("activated") and end_date_obj:
|
||||
await notify_admin_new_trial(
|
||||
callback.bot,
|
||||
settings,
|
||||
i18n,
|
||||
user_id,
|
||||
end_date_obj,
|
||||
)
|
||||
|
||||
|
||||
@router.callback_query(F.data == "main_action:cancel_trial")
|
||||
async def cancel_trial_activation(
|
||||
|
||||
@@ -32,7 +32,6 @@ from bot.handlers.admin import admin_router_aggregate
|
||||
from bot.filters.admin_filter import AdminFilter
|
||||
|
||||
from bot.services.notification_service import schedule_subscription_notifications
|
||||
from bot.services.auto_renew_service import schedule_tribute_autorenew
|
||||
from bot.services.yookassa_service import YooKassaService
|
||||
from bot.services.panel_api_service import PanelApiService
|
||||
from bot.services.subscription_service import SubscriptionService
|
||||
@@ -117,12 +116,6 @@ async def on_startup_configured(dispatcher: Dispatcher):
|
||||
panel_service,
|
||||
async_session_factory,
|
||||
)
|
||||
schedule_tribute_autorenew(
|
||||
settings,
|
||||
scheduler,
|
||||
panel_service,
|
||||
async_session_factory,
|
||||
)
|
||||
scheduler.start()
|
||||
dispatcher["scheduler"] = scheduler
|
||||
logging.info("STARTUP: APScheduler started.")
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
import logging
|
||||
from datetime import datetime, timezone
|
||||
from apscheduler.schedulers.asyncio import AsyncIOScheduler
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
|
||||
from config.settings import Settings
|
||||
from bot.services.subscription_service import SubscriptionService
|
||||
from bot.services.panel_api_service import PanelApiService
|
||||
from db.dal import subscription_dal
|
||||
|
||||
|
||||
async def auto_extend_tribute_subscriptions(
|
||||
settings: Settings, panel_service: PanelApiService,
|
||||
async_session_factory: sessionmaker) -> None:
|
||||
logging.info(
|
||||
f"Scheduler job 'auto_extend_tribute_subscriptions' started at {datetime.now(timezone.utc)} UTC."
|
||||
)
|
||||
async with async_session_factory() as session:
|
||||
try:
|
||||
sub_service = SubscriptionService(settings, panel_service)
|
||||
subs = await subscription_dal.get_active_subscriptions_for_autorenew(
|
||||
session, 'tribute', require_skip_flag=False)
|
||||
if not subs:
|
||||
logging.info("No Tribute subscriptions to auto-extend.")
|
||||
return
|
||||
for sub in subs:
|
||||
if not sub.skip_notifications:
|
||||
from db.dal import payment_dal
|
||||
has_pay = await payment_dal.user_has_successful_payment_for_provider(
|
||||
session, sub.user_id, 'tribute')
|
||||
if not has_pay:
|
||||
continue
|
||||
await subscription_dal.set_skip_notifications_for_provider(
|
||||
session, sub.user_id, 'tribute', True)
|
||||
|
||||
months = sub.duration_months or 1
|
||||
bonus_days = months * 30
|
||||
await sub_service.extend_active_subscription_days(
|
||||
session, sub.user_id, bonus_days,
|
||||
reason='tribute_autorenew')
|
||||
await session.commit()
|
||||
logging.info(
|
||||
f"Auto-extended {len(subs)} Tribute subscriptions and committed session.")
|
||||
except Exception as e:
|
||||
logging.error(
|
||||
f"Error during auto_extend_tribute_subscriptions: {e}",
|
||||
exc_info=True)
|
||||
await session.rollback()
|
||||
logging.info("Session rolled back due to error in auto_extend_tribute_subscriptions.")
|
||||
|
||||
|
||||
def schedule_tribute_autorenew(
|
||||
settings: Settings, scheduler: AsyncIOScheduler,
|
||||
panel_service: PanelApiService,
|
||||
async_session_factory: sessionmaker) -> None:
|
||||
|
||||
async def job_wrapper():
|
||||
try:
|
||||
await auto_extend_tribute_subscriptions(
|
||||
settings, panel_service, async_session_factory)
|
||||
except Exception as e:
|
||||
logging.error(
|
||||
f"Unhandled error in scheduled job 'auto_extend_tribute_subscriptions': {e}",
|
||||
exc_info=True)
|
||||
|
||||
scheduler.add_job(
|
||||
job_wrapper,
|
||||
'cron',
|
||||
hour=0,
|
||||
minute=5,
|
||||
name='daily_tribute_autorenew',
|
||||
misfire_grace_time=60 * 15,
|
||||
replace_existing=True)
|
||||
logging.info(
|
||||
"Tribute subscription auto-renew job scheduled daily at 00:05 UTC.")
|
||||
@@ -133,3 +133,46 @@ async def schedule_subscription_notifications(
|
||||
logging.info(
|
||||
f"Subscription expiration warning job scheduled daily at {notification_hour:02d}:{notification_minute:02d} UTC."
|
||||
)
|
||||
|
||||
|
||||
async def notify_admins(bot: Bot, settings: Settings, i18n: JsonI18n,
|
||||
message_key: str, parse_mode: str | None = None,
|
||||
**kwargs) -> None:
|
||||
if not settings.ADMIN_IDS:
|
||||
return
|
||||
admin_lang = settings.DEFAULT_LANGUAGE
|
||||
msg = i18n.gettext(admin_lang, message_key, **kwargs)
|
||||
for admin_id in settings.ADMIN_IDS:
|
||||
try:
|
||||
await bot.send_message(admin_id, msg, parse_mode=parse_mode)
|
||||
except Exception as e:
|
||||
logging.error(f"Failed to send admin notification to {admin_id}: {e}")
|
||||
|
||||
|
||||
async def notify_admin_new_trial(bot: Bot, settings: Settings, i18n: JsonI18n,
|
||||
user_id: int, end_date: datetime) -> None:
|
||||
end_date_str = end_date.strftime('%Y-%m-%d') if isinstance(end_date, datetime) else str(end_date)
|
||||
await notify_admins(
|
||||
bot,
|
||||
settings,
|
||||
i18n,
|
||||
"admin_new_trial_notification",
|
||||
user_id=user_id,
|
||||
end_date=end_date_str,
|
||||
)
|
||||
|
||||
|
||||
async def notify_admin_new_payment(bot: Bot, settings: Settings, i18n: JsonI18n,
|
||||
user_id: int, months: int, amount: float,
|
||||
currency: str | None = None) -> None:
|
||||
currency_symbol = currency or settings.DEFAULT_CURRENCY_SYMBOL
|
||||
await notify_admins(
|
||||
bot,
|
||||
settings,
|
||||
i18n,
|
||||
"admin_new_payment_notification",
|
||||
user_id=user_id,
|
||||
months=months,
|
||||
amount=f"{amount:.2f}",
|
||||
currency=currency_symbol,
|
||||
)
|
||||
|
||||
@@ -214,5 +214,8 @@
|
||||
"subscription_ending_soon_notification": "👋 Hi, {user_name}!\n\n⏳ Your VPN subscription ends on {end_date} (in {days_left} days).\n\nTo avoid interruption, please renew it in the main menu.",
|
||||
"subscription_cancelled_notification": "Your recurring subscription was cancelled. You will keep access until the paid period ends.",
|
||||
|
||||
"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}.",
|
||||
|
||||
"error_unknown": "An unknown error occurred."
|
||||
}
|
||||
|
||||
@@ -214,5 +214,8 @@
|
||||
"subscription_ending_soon_notification": "👋 Привет, {user_name}!\n\n⏳ Ваша подписка на VPN истекает {end_date} (через {days_left} дн.).\n\nЧтобы не потерять доступ, пожалуйста, продлите ее заранее в главном меню бота.",
|
||||
"subscription_cancelled_notification": "Ваша подписка отменена. Доступ сохранится до конца оплаченного периода.",
|
||||
|
||||
"admin_new_trial_notification": "\ud83c\udf21 Пользователь {user_id} активировал пробный период до {end_date}.",
|
||||
"admin_new_payment_notification": "\ud83d\udcb3 Получен платеж от пользователя {user_id}: {months} мес. за {amount} {currency}.",
|
||||
|
||||
"error_unknown": "Произошла неизвестная ошибка."
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user