Add support for streaming modules / Add mailing for trial subscriptions
This commit is contained in:
@@ -35,6 +35,12 @@ def build_sender_kb() -> InlineKeyboardMarkup:
|
||||
callback_data=AdminSenderCallback(type="untrial").pack(),
|
||||
)
|
||||
)
|
||||
builder.row(
|
||||
InlineKeyboardButton(
|
||||
text="🧪 Триал",
|
||||
callback_data=AdminSenderCallback(type="trial").pack(),
|
||||
)
|
||||
)
|
||||
builder.row(
|
||||
InlineKeyboardButton(
|
||||
text="🔥 Горячие лиды",
|
||||
|
||||
@@ -12,7 +12,7 @@ from aiogram.types import CallbackQuery, InlineKeyboardButton, InlineKeyboardMar
|
||||
from sqlalchemy import distinct, func, select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from database.models import Key, Payment, Server, User
|
||||
from database.models import Key, Payment, Server, Tariff, User
|
||||
from filters.admin import IsAdminFilter
|
||||
from logger import logger
|
||||
|
||||
@@ -269,6 +269,13 @@ async def handle_send_confirm(callback_query: CallbackQuery, state: FSMContext,
|
||||
.where(Payment.status == "success")
|
||||
.where(~User.tg_id.in_(subquery))
|
||||
)
|
||||
elif send_to == "trial":
|
||||
trial_tariff_subquery = select(Tariff.id).where(Tariff.group_code == "trial")
|
||||
|
||||
query = (
|
||||
select(distinct(Key.tg_id))
|
||||
.where(Key.tariff_id.in_(trial_tariff_subquery))
|
||||
)
|
||||
else:
|
||||
query = select(distinct(User.tg_id))
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ from handlers.texts import (
|
||||
)
|
||||
from handlers.utils import edit_or_send_message, get_least_loaded_cluster
|
||||
from logger import logger
|
||||
from utils.modules_loader import load_module_fast_flow_handlers
|
||||
|
||||
from .key_cluster_mode import key_cluster_mode
|
||||
from .key_country_mode import key_country_mode
|
||||
@@ -313,27 +314,38 @@ async def select_tariff_plan(callback_query: CallbackQuery, session: Any, state:
|
||||
},
|
||||
)
|
||||
|
||||
if USE_NEW_PAYMENT_FLOW == "YOOKASSA":
|
||||
await process_custom_amount_input(callback_query, session)
|
||||
elif USE_NEW_PAYMENT_FLOW == "ROBOKASSA":
|
||||
await handle_custom_amount_input(message=callback_query, session=session)
|
||||
elif USE_NEW_PAYMENT_FLOW == "STARS":
|
||||
await process_custom_amount_input_stars(callback_query, session)
|
||||
elif USE_NEW_PAYMENT_FLOW == "YOOMONEY":
|
||||
await process_custom_amount_input_yoomoney(callback_query, session)
|
||||
elif USE_NEW_PAYMENT_FLOW == "WATA":
|
||||
await state.update_data(wata_cassa="sbp", required_amount=required_amount)
|
||||
await handle_custom_amount_input_wata(callback_query, state)
|
||||
module_fast_flow_handlers = load_module_fast_flow_handlers()
|
||||
flow_handled = False
|
||||
|
||||
if USE_NEW_PAYMENT_FLOW in module_fast_flow_handlers:
|
||||
try:
|
||||
handler = module_fast_flow_handlers[USE_NEW_PAYMENT_FLOW]
|
||||
await handler(callback_query, session, state)
|
||||
flow_handled = True
|
||||
except Exception as e:
|
||||
logger.error(f"[CREATE] Ошибка в модульном обработчике быстрого флоу {USE_NEW_PAYMENT_FLOW}: {e}")
|
||||
|
||||
else:
|
||||
builder = InlineKeyboardBuilder()
|
||||
builder.row(InlineKeyboardButton(text=PAYMENT, callback_data="pay"))
|
||||
builder.row(InlineKeyboardButton(text=MAIN_MENU, callback_data="profile"))
|
||||
await edit_or_send_message(
|
||||
target_message=callback_query.message,
|
||||
text=INSUFFICIENT_FUNDS_MSG.format(required_amount=required_amount),
|
||||
reply_markup=builder.as_markup(),
|
||||
)
|
||||
if not flow_handled:
|
||||
if USE_NEW_PAYMENT_FLOW == "YOOKASSA":
|
||||
await process_custom_amount_input(callback_query, session)
|
||||
elif USE_NEW_PAYMENT_FLOW == "ROBOKASSA":
|
||||
await handle_custom_amount_input(message=callback_query, session=session)
|
||||
elif USE_NEW_PAYMENT_FLOW == "STARS":
|
||||
await process_custom_amount_input_stars(callback_query, session)
|
||||
elif USE_NEW_PAYMENT_FLOW == "YOOMONEY":
|
||||
await process_custom_amount_input_yoomoney(callback_query, session)
|
||||
elif USE_NEW_PAYMENT_FLOW == "WATA":
|
||||
await state.update_data(wata_cassa="sbp", required_amount=required_amount)
|
||||
await handle_custom_amount_input_wata(callback_query, state)
|
||||
else:
|
||||
builder = InlineKeyboardBuilder()
|
||||
builder.row(InlineKeyboardButton(text=PAYMENT, callback_data="pay"))
|
||||
builder.row(InlineKeyboardButton(text=MAIN_MENU, callback_data="profile"))
|
||||
await edit_or_send_message(
|
||||
target_message=callback_query.message,
|
||||
text=INSUFFICIENT_FUNDS_MSG.format(required_amount=required_amount),
|
||||
reply_markup=builder.as_markup(),
|
||||
)
|
||||
return
|
||||
|
||||
builder = InlineKeyboardBuilder()
|
||||
|
||||
+33
-20
@@ -42,6 +42,7 @@ from handlers.texts import (
|
||||
)
|
||||
from handlers.utils import edit_or_send_message, get_russian_month
|
||||
from logger import logger
|
||||
from utils.modules_loader import load_module_fast_flow_handlers
|
||||
|
||||
|
||||
router = Router()
|
||||
@@ -285,26 +286,38 @@ async def process_callback_renew_plan(callback_query: CallbackQuery, state: FSMC
|
||||
},
|
||||
)
|
||||
|
||||
if USE_NEW_PAYMENT_FLOW == "YOOKASSA":
|
||||
await process_custom_amount_input(callback_query, session)
|
||||
elif USE_NEW_PAYMENT_FLOW == "ROBOKASSA":
|
||||
await handle_custom_amount_input(message=callback_query, session=session)
|
||||
elif USE_NEW_PAYMENT_FLOW == "STARS":
|
||||
await process_custom_amount_input_stars(callback_query, session)
|
||||
elif USE_NEW_PAYMENT_FLOW == "YOOMONEY":
|
||||
await process_custom_amount_input_yoomoney(callback_query, session)
|
||||
elif USE_NEW_PAYMENT_FLOW == "WATA":
|
||||
await state.update_data(wata_cassa="sbp", required_amount=required_amount)
|
||||
await handle_custom_amount_input_wata(callback_query, state)
|
||||
else:
|
||||
builder = InlineKeyboardBuilder()
|
||||
builder.row(InlineKeyboardButton(text=PAYMENT, callback_data="pay"))
|
||||
builder.row(InlineKeyboardButton(text=MAIN_MENU, callback_data="profile"))
|
||||
await edit_or_send_message(
|
||||
target_message=callback_query.message,
|
||||
text=INSUFFICIENT_FUNDS_RENEWAL_MSG.format(required_amount=required_amount),
|
||||
reply_markup=builder.as_markup(),
|
||||
)
|
||||
module_fast_flow_handlers = load_module_fast_flow_handlers()
|
||||
flow_handled = False
|
||||
|
||||
if USE_NEW_PAYMENT_FLOW in module_fast_flow_handlers:
|
||||
try:
|
||||
handler = module_fast_flow_handlers[USE_NEW_PAYMENT_FLOW]
|
||||
await handler(callback_query, session, state)
|
||||
flow_handled = True
|
||||
except Exception as e:
|
||||
logger.error(f"[RENEW] Ошибка в модульном обработчике быстрого флоу {USE_NEW_PAYMENT_FLOW}: {e}")
|
||||
|
||||
if not flow_handled:
|
||||
if USE_NEW_PAYMENT_FLOW == "YOOKASSA":
|
||||
await process_custom_amount_input(callback_query, session)
|
||||
elif USE_NEW_PAYMENT_FLOW == "ROBOKASSA":
|
||||
await handle_custom_amount_input(message=callback_query, session=session)
|
||||
elif USE_NEW_PAYMENT_FLOW == "STARS":
|
||||
await process_custom_amount_input_stars(callback_query, session)
|
||||
elif USE_NEW_PAYMENT_FLOW == "YOOMONEY":
|
||||
await process_custom_amount_input_yoomoney(callback_query, session)
|
||||
elif USE_NEW_PAYMENT_FLOW == "WATA":
|
||||
await state.update_data(wata_cassa="sbp", required_amount=required_amount)
|
||||
await handle_custom_amount_input_wata(callback_query, state)
|
||||
else:
|
||||
builder = InlineKeyboardBuilder()
|
||||
builder.row(InlineKeyboardButton(text=PAYMENT, callback_data="pay"))
|
||||
builder.row(InlineKeyboardButton(text=MAIN_MENU, callback_data="profile"))
|
||||
await edit_or_send_message(
|
||||
target_message=callback_query.message,
|
||||
text=INSUFFICIENT_FUNDS_RENEWAL_MSG.format(required_amount=required_amount),
|
||||
reply_markup=builder.as_markup(),
|
||||
)
|
||||
return
|
||||
|
||||
logger.info(f"[RENEW] Продление ключа для пользователя {tg_id} на {duration_days} дней")
|
||||
|
||||
@@ -52,3 +52,31 @@ def load_module_webhooks(folder: str = "modules") -> list[dict]:
|
||||
logger.error(f"[Modules] Ошибка при загрузке вебхуков из {module_path}: {e}")
|
||||
|
||||
return webhooks
|
||||
|
||||
|
||||
def load_module_fast_flow_handlers(folder: str = "modules") -> dict:
|
||||
handlers = {}
|
||||
base_path = Path(folder)
|
||||
|
||||
if not base_path.exists():
|
||||
logger.warning(f"[Modules] Папка {folder} не найдена, пропускаем загрузку быстрого флоу.")
|
||||
return {}
|
||||
|
||||
for _finder, name, _ispkg in pkgutil.iter_modules([str(base_path)]):
|
||||
module_path = f"{folder}.{name}"
|
||||
try:
|
||||
router_module = importlib.import_module(f"{module_path}.router")
|
||||
if hasattr(router_module, "get_fast_flow_handler"):
|
||||
fast_flow_data = router_module.get_fast_flow_handler()
|
||||
if fast_flow_data and isinstance(fast_flow_data, dict) and "payment_key" in fast_flow_data and "handler" in fast_flow_data:
|
||||
payment_key = fast_flow_data["payment_key"]
|
||||
handler = fast_flow_data["handler"]
|
||||
handlers[payment_key] = handler
|
||||
logger.info(f"[Modules] Найден обработчик быстрого флоу в модуле {name}: {payment_key}")
|
||||
elif fast_flow_data is None:
|
||||
logger.info(f"[Modules] Быстрое флоу отключено в модуле {name}")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"[Modules] Ошибка при загрузке быстрого флоу из {module_path}: {e}")
|
||||
|
||||
return handlers
|
||||
|
||||
Reference in New Issue
Block a user