refactor: project architecture refactor, container splitting
This commit is contained in:
@@ -0,0 +1,315 @@
|
||||
import logging
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
from aiogram import F, Router, types
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from bot.keyboards.inline.user_keyboards import (
|
||||
get_connect_and_main_keyboard,
|
||||
get_main_menu_inline_keyboard,
|
||||
)
|
||||
from bot.middlewares.i18n import JsonI18n
|
||||
from bot.services.notification_service import NotificationService
|
||||
from bot.services.panel_api_service import PanelApiService
|
||||
from bot.services.subscription_service import SubscriptionService
|
||||
from bot.utils.config_link import prepare_config_links
|
||||
from config.settings import Settings
|
||||
|
||||
from .start import send_main_menu
|
||||
|
||||
router = Router(name="user_trial_router")
|
||||
|
||||
|
||||
async def request_trial_confirmation_handler(
|
||||
callback: types.CallbackQuery,
|
||||
settings: Settings,
|
||||
i18n_data: dict,
|
||||
subscription_service: SubscriptionService,
|
||||
session: AsyncSession,
|
||||
):
|
||||
user_id = callback.from_user.id
|
||||
current_lang = i18n_data.get("current_language", settings.DEFAULT_LANGUAGE)
|
||||
i18n: Optional[JsonI18n] = i18n_data.get("i18n_instance")
|
||||
_ = lambda key, **kwargs: i18n.gettext(current_lang, key, **kwargs) if i18n else key
|
||||
|
||||
if not i18n or not callback.message:
|
||||
try:
|
||||
await callback.answer(_("error_occurred_try_again"), show_alert=True)
|
||||
except Exception:
|
||||
pass
|
||||
return
|
||||
|
||||
if settings.TRIAL_ENABLED:
|
||||
if not await subscription_service.has_had_any_subscription(session, user_id):
|
||||
pass
|
||||
|
||||
if not settings.TRIAL_ENABLED:
|
||||
await callback.message.edit_text(
|
||||
_("trial_feature_disabled"),
|
||||
reply_markup=get_main_menu_inline_keyboard(current_lang, i18n, settings, False),
|
||||
)
|
||||
try:
|
||||
await callback.answer()
|
||||
except Exception:
|
||||
pass
|
||||
return
|
||||
|
||||
if await subscription_service.has_had_any_subscription(session, user_id):
|
||||
await callback.message.edit_text(
|
||||
_("trial_already_had_subscription_or_trial"),
|
||||
reply_markup=get_main_menu_inline_keyboard(current_lang, i18n, settings, False),
|
||||
)
|
||||
try:
|
||||
await callback.answer()
|
||||
except Exception:
|
||||
pass
|
||||
return
|
||||
|
||||
# Directly activate trial without confirmation
|
||||
activation_result = await subscription_service.activate_trial_subscription(session, user_id)
|
||||
|
||||
final_message_text_in_chat = ""
|
||||
show_trial_button_after_action = False
|
||||
config_link_display_for_trial = None
|
||||
config_link_for_trial = None
|
||||
connect_button_url_for_trial = None
|
||||
|
||||
if activation_result and activation_result.get("activated"):
|
||||
try:
|
||||
await callback.answer(_("trial_activated_alert"), show_alert=True)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
end_date_obj = activation_result.get("end_date")
|
||||
config_link_display_for_trial, connect_button_url_for_trial = await prepare_config_links(
|
||||
settings, activation_result.get("subscription_url")
|
||||
)
|
||||
config_link_for_trial = config_link_display_for_trial or _("config_link_not_available")
|
||||
|
||||
traffic_gb_val = activation_result.get("traffic_gb", settings.TRIAL_TRAFFIC_LIMIT_GB)
|
||||
traffic_display = (
|
||||
f"{traffic_gb_val} GB"
|
||||
if traffic_gb_val and traffic_gb_val > 0
|
||||
else _("traffic_unlimited")
|
||||
)
|
||||
|
||||
final_message_text_in_chat = _(
|
||||
"trial_activated_details_message",
|
||||
days=activation_result.get("days", settings.TRIAL_DURATION_DAYS),
|
||||
end_date=(
|
||||
end_date_obj.strftime("%Y-%m-%d") if isinstance(end_date_obj, datetime) else "N/A"
|
||||
),
|
||||
config_link=config_link_for_trial,
|
||||
traffic_gb=traffic_display,
|
||||
)
|
||||
|
||||
# Send notification to admin about new trial
|
||||
notification_service = NotificationService(callback.bot, settings, i18n)
|
||||
await notification_service.notify_trial_activation(user_id, end_date_obj)
|
||||
# Mark ad attribution trial if exists
|
||||
try:
|
||||
from db.dal import ad_dal as _ad_dal
|
||||
|
||||
await _ad_dal.mark_trial_activated(session, user_id)
|
||||
await session.commit()
|
||||
except Exception as e_mark:
|
||||
await session.rollback()
|
||||
logging.error(f"Failed to mark trial for ad attribution for user {user_id}: {e_mark}")
|
||||
else:
|
||||
message_key_from_service = (
|
||||
activation_result.get("message_key", "trial_activation_failed")
|
||||
if activation_result
|
||||
else "trial_activation_failed"
|
||||
)
|
||||
final_message_text_in_chat = _(message_key_from_service)
|
||||
try:
|
||||
await callback.answer(final_message_text_in_chat, show_alert=True)
|
||||
except Exception:
|
||||
pass
|
||||
if settings.TRIAL_ENABLED and not await subscription_service.has_had_any_subscription(
|
||||
session, user_id
|
||||
):
|
||||
show_trial_button_after_action = True
|
||||
|
||||
reply_markup = (
|
||||
get_connect_and_main_keyboard(
|
||||
current_lang,
|
||||
i18n,
|
||||
settings,
|
||||
config_link_display_for_trial,
|
||||
connect_button_url=connect_button_url_for_trial,
|
||||
)
|
||||
if activation_result and activation_result.get("activated")
|
||||
else get_main_menu_inline_keyboard(
|
||||
current_lang, i18n, settings, show_trial_button_after_action
|
||||
)
|
||||
)
|
||||
|
||||
try:
|
||||
await callback.message.edit_text(
|
||||
final_message_text_in_chat,
|
||||
parse_mode="HTML",
|
||||
reply_markup=reply_markup,
|
||||
disable_web_page_preview=True,
|
||||
)
|
||||
except Exception as e_edit:
|
||||
logging.warning(f"Could not edit trial result message: {e_edit}. Sending new one.")
|
||||
|
||||
if callback.message:
|
||||
await callback.message.answer(
|
||||
final_message_text_in_chat,
|
||||
parse_mode="HTML",
|
||||
reply_markup=reply_markup,
|
||||
disable_web_page_preview=True,
|
||||
)
|
||||
|
||||
|
||||
@router.callback_query(F.data == "trial_action:confirm_activate")
|
||||
async def confirm_activate_trial_handler(
|
||||
callback: types.CallbackQuery,
|
||||
settings: Settings,
|
||||
i18n_data: dict,
|
||||
subscription_service: SubscriptionService,
|
||||
panel_service: PanelApiService,
|
||||
session: AsyncSession,
|
||||
):
|
||||
user_id = callback.from_user.id
|
||||
|
||||
current_lang = i18n_data.get("current_language", settings.DEFAULT_LANGUAGE)
|
||||
i18n: Optional[JsonI18n] = i18n_data.get("i18n_instance")
|
||||
_ = lambda key, **kwargs: i18n.gettext(current_lang, key, **kwargs) if i18n else key
|
||||
|
||||
if not i18n or not callback.message:
|
||||
try:
|
||||
await callback.answer(_("error_occurred_try_again"), show_alert=True)
|
||||
except Exception:
|
||||
pass
|
||||
return
|
||||
|
||||
if not settings.TRIAL_ENABLED:
|
||||
try:
|
||||
await callback.answer(_("trial_feature_disabled"), show_alert=True)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
await send_main_menu(
|
||||
callback, settings, i18n_data, subscription_service, session, is_edit=True
|
||||
)
|
||||
return
|
||||
if await subscription_service.has_had_any_subscription(session, user_id):
|
||||
try:
|
||||
await callback.answer(_("trial_already_had_subscription_or_trial"), show_alert=True)
|
||||
except Exception:
|
||||
pass
|
||||
await send_main_menu(
|
||||
callback, settings, i18n_data, subscription_service, session, is_edit=True
|
||||
)
|
||||
return
|
||||
|
||||
activation_result = await subscription_service.activate_trial_subscription(session, user_id)
|
||||
|
||||
final_message_text_in_chat = ""
|
||||
show_trial_button_after_action = False
|
||||
config_link_display_for_trial = None
|
||||
config_link_for_trial = None
|
||||
connect_button_url_for_trial = None
|
||||
|
||||
if activation_result and activation_result.get("activated"):
|
||||
try:
|
||||
await callback.answer(_("trial_activated_alert"), show_alert=True)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
end_date_obj = activation_result.get("end_date")
|
||||
config_link_display_for_trial, connect_button_url_for_trial = await prepare_config_links(
|
||||
settings, activation_result.get("subscription_url")
|
||||
)
|
||||
config_link_for_trial = config_link_display_for_trial or _("config_link_not_available")
|
||||
|
||||
traffic_gb_val = activation_result.get("traffic_gb", settings.TRIAL_TRAFFIC_LIMIT_GB)
|
||||
traffic_display = (
|
||||
f"{traffic_gb_val} GB"
|
||||
if traffic_gb_val and traffic_gb_val > 0
|
||||
else _("traffic_unlimited")
|
||||
)
|
||||
|
||||
final_message_text_in_chat = _(
|
||||
"trial_activated_details_message",
|
||||
days=activation_result.get("days", settings.TRIAL_DURATION_DAYS),
|
||||
end_date=(
|
||||
end_date_obj.strftime("%Y-%m-%d") if isinstance(end_date_obj, datetime) else "N/A"
|
||||
),
|
||||
config_link=config_link_for_trial,
|
||||
traffic_gb=traffic_display,
|
||||
)
|
||||
else:
|
||||
message_key_from_service = (
|
||||
activation_result.get("message_key", "trial_activation_failed")
|
||||
if activation_result
|
||||
else "trial_activation_failed"
|
||||
)
|
||||
final_message_text_in_chat = _(message_key_from_service)
|
||||
try:
|
||||
await callback.answer(final_message_text_in_chat, show_alert=True)
|
||||
except Exception:
|
||||
pass
|
||||
if settings.TRIAL_ENABLED and not await subscription_service.has_had_any_subscription(
|
||||
session, user_id
|
||||
):
|
||||
show_trial_button_after_action = True
|
||||
|
||||
reply_markup = (
|
||||
get_connect_and_main_keyboard(
|
||||
current_lang,
|
||||
i18n,
|
||||
settings,
|
||||
config_link_display_for_trial,
|
||||
connect_button_url=connect_button_url_for_trial,
|
||||
)
|
||||
if activation_result and activation_result.get("activated")
|
||||
else get_main_menu_inline_keyboard(
|
||||
current_lang, i18n, settings, show_trial_button_after_action
|
||||
)
|
||||
)
|
||||
|
||||
try:
|
||||
await callback.message.edit_text(
|
||||
final_message_text_in_chat,
|
||||
parse_mode="HTML",
|
||||
reply_markup=reply_markup,
|
||||
disable_web_page_preview=True,
|
||||
)
|
||||
except Exception as e_edit:
|
||||
logging.warning(f"Could not edit trial result message: {e_edit}. Sending new one.")
|
||||
|
||||
if callback.message:
|
||||
await callback.message.answer(
|
||||
final_message_text_in_chat,
|
||||
parse_mode="HTML",
|
||||
reply_markup=reply_markup,
|
||||
disable_web_page_preview=True,
|
||||
)
|
||||
|
||||
if activation_result and activation_result.get("activated") and end_date_obj:
|
||||
notification_service = NotificationService(callback.bot, settings, i18n)
|
||||
await notification_service.notify_trial_activation(user_id, end_date_obj)
|
||||
try:
|
||||
from db.dal import ad_dal as _ad_dal
|
||||
|
||||
await _ad_dal.mark_trial_activated(session, user_id)
|
||||
await session.commit()
|
||||
except Exception as e_mark:
|
||||
await session.rollback()
|
||||
logging.error(f"Failed to mark trial for ad attribution for user {user_id}: {e_mark}")
|
||||
|
||||
|
||||
@router.callback_query(F.data == "main_action:cancel_trial")
|
||||
async def cancel_trial_activation(
|
||||
callback: types.CallbackQuery,
|
||||
settings: Settings,
|
||||
i18n_data: dict,
|
||||
subscription_service: SubscriptionService,
|
||||
session: AsyncSession,
|
||||
):
|
||||
await send_main_menu(callback, settings, i18n_data, subscription_service, session, is_edit=True)
|
||||
Reference in New Issue
Block a user