refactor: project architecture refactor, container splitting

This commit is contained in:
3252a8
2026-05-17 00:01:28 +03:00
parent e0b5218037
commit 30fb774d93
367 changed files with 2609 additions and 864 deletions
@@ -0,0 +1,148 @@
import logging
from typing import Optional
from aiogram import F, Router, types
from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup
from sqlalchemy.ext.asyncio import AsyncSession
from bot.middlewares.i18n import JsonI18n
from bot.services.stars_service import StarsService
from config.settings import Settings
router = Router(name="user_subscription_payments_stars_router")
@router.callback_query(F.data.startswith("pay_stars:"))
async def pay_stars_callback_handler(
callback: types.CallbackQuery,
settings: Settings,
i18n_data: dict,
session: AsyncSession,
stars_service: StarsService,
):
current_lang = i18n_data.get("current_language", settings.DEFAULT_LANGUAGE)
i18n: Optional[JsonI18n] = i18n_data.get("i18n_instance")
get_text = lambda key, **kwargs: i18n.gettext(current_lang, key, **kwargs) if i18n else key
if not i18n or not callback.message:
try:
await callback.answer(get_text("error_occurred_try_again"), show_alert=True)
except Exception:
pass
return
if not settings.STARS_ENABLED:
try:
await callback.answer(get_text("payment_service_unavailable_alert"), show_alert=True)
except Exception:
pass
return
try:
_, data_payload = callback.data.split(":", 1)
parts = data_payload.split(":")
months = float(parts[0])
stars_price = int(float(parts[1]))
sale_mode = parts[2] if len(parts) > 2 else "subscription"
except (ValueError, IndexError):
try:
await callback.answer(get_text("error_try_again"), show_alert=True)
except Exception:
pass
return
user_id = callback.from_user.id
human_value = str(int(months)) if float(months).is_integer() else f"{months:g}"
sale_base = sale_mode.split("@", 1)[0].split("|", 1)[0]
payment_description = (
get_text("payment_description_traffic", traffic_gb=human_value)
if sale_base in {"traffic", "traffic_package", "topup", "premium_topup"}
else (
get_text("payment_description_hwid_devices", count=int(months))
if sale_base in {"hwid_device", "hwid_devices"}
else get_text("payment_description_subscription", months=int(months))
)
)
payment_db_id = await stars_service.create_invoice(
session=session,
user_id=user_id,
months=months,
stars_price=stars_price,
description=payment_description,
sale_mode=sale_mode,
)
if payment_db_id:
try:
await callback.message.edit_text(
get_text(
"payment_invoice_sent_message_traffic"
if sale_base in {"traffic", "traffic_package", "topup", "premium_topup"}
else "payment_invoice_sent_message",
months=int(months),
traffic_gb=human_value,
),
reply_markup=InlineKeyboardMarkup(
inline_keyboard=[
[
InlineKeyboardButton(
text=get_text("back_to_payment_methods_button"),
callback_data=f"subscribe_period:{human_value}",
)
]
]
),
)
except Exception as e_edit:
logging.warning(f"Stars payment: failed to show invoice info message ({e_edit})")
try:
await callback.answer()
except Exception:
pass
return
try:
await callback.answer(get_text("error_payment_gateway"), show_alert=True)
except Exception:
pass
@router.pre_checkout_query()
async def handle_pre_checkout_query(query: types.PreCheckoutQuery):
try:
await query.answer(ok=True)
except Exception:
# Nothing else to do here; Telegram will show an error if not answered
pass
@router.message(F.successful_payment)
async def handle_successful_stars_payment(
message: types.Message,
settings: Settings,
i18n_data: dict,
session: AsyncSession,
stars_service: StarsService,
):
payload = (
message.successful_payment.invoice_payload if message and message.successful_payment else ""
)
try:
parts = (payload or "").split(":")
payment_db_id = int(parts[0])
months = float(parts[1]) if len(parts) > 1 else 0
sale_mode = parts[2] if len(parts) > 2 else "subscription"
except Exception:
return
stars_amount = int(message.successful_payment.total_amount) if message.successful_payment else 0
await stars_service.process_successful_payment(
session=session,
message=message,
payment_db_id=payment_db_id,
months=months,
stars_amount=stars_amount,
i18n_data=i18n_data,
sale_mode=sale_mode,
)