Files
Solo_bot/hooks/processors.py
T
2025-12-03 02:26:17 +03:00

619 lines
18 KiB
Python

from typing import Any
from logger import logger
from .hooks import run_hooks
async def process_cluster_override(
tg_id: int,
state_data: dict,
session: Any,
plan: int | None = None,
**kwargs,
) -> str | None:
"""
Обрабатывает хук cluster_override.
Возвращает название кластера для принудительного выбора или None.
"""
try:
results = await run_hooks(
"cluster_override",
tg_id=tg_id,
state_data=state_data,
session=session,
plan=plan,
**kwargs,
)
return results[0] if results and results[0] else None
except Exception as e:
logger.warning(f"[CLUSTER_OVERRIDE] Ошибка при обработке хука: {e}")
return None
async def process_cluster_balancer(
available_clusters: dict,
session: Any,
**kwargs,
) -> dict | None:
"""
Обрабатывает хук cluster_balancer.
Возвращает отфильтрованный словарь кластеров или None (использовать исходный).
"""
try:
results = await run_hooks(
"cluster_balancer",
available_clusters=available_clusters,
session=session,
**kwargs,
)
return results[0] if results and results[0] else None
except Exception as e:
logger.warning(f"[CLUSTER_BALANCER] Ошибка при обработке хука: {e}")
return None
async def process_remnawave_webapp_override(
remnawave_webapp: bool,
final_link: str,
session: Any,
**kwargs,
) -> bool:
"""
Обрабатывает хук remnawave_webapp_override.
Возвращает bool - использовать ли webapp для подключения устройства.
"""
if not remnawave_webapp or not final_link:
return remnawave_webapp
try:
results = await run_hooks(
"remnawave_webapp_override",
remnawave_webapp=remnawave_webapp,
final_link=final_link,
session=session,
**kwargs,
)
if not results:
return remnawave_webapp
for result in results:
if result is True or result is False:
return result
elif isinstance(result, dict) and "override" in result:
return result["override"]
return remnawave_webapp
except Exception as e:
logger.warning(f"[REMNAWAVE_WEBAPP_OVERRIDE] Ошибка при обработке хука: {e}")
return remnawave_webapp
async def process_happ_cryptolink_override(
cluster_id: str | None,
plan: int | None,
session: Any,
email: str | None = None,
tg_id: int | None = None,
happ_cryptolink: bool = False,
**kwargs,
) -> bool:
"""
Обрабатывает хук happ_cryptolink_override.
Возвращает bool - использовать ли криптоссылку для подписки.
"""
try:
results = await run_hooks(
"happ_cryptolink_override",
cluster_id=cluster_id,
plan=plan,
session=session,
email=email,
tg_id=tg_id,
happ_cryptolink=happ_cryptolink,
**kwargs,
)
if not results:
return happ_cryptolink
for result in results:
if result is True or result is False:
return result
return happ_cryptolink
except Exception as e:
logger.warning(f"[HAPP_CRYPTOLINK_OVERRIDE] Ошибка при обработке хука: {e}")
return happ_cryptolink
async def process_extract_cryptolink_from_result(
result: dict,
cluster_id: str | None,
plan: int | None,
session: Any,
email: str | None = None,
tg_id: int | None = None,
need_vless_key: bool = False,
**kwargs,
) -> str | None:
"""
Обрабатывает хук happ_cryptolink_override и извлекает криптоссылку из результата API.
Возвращает криптоссылку если нужно использовать, иначе None.
"""
if need_vless_key:
return None
try:
from config import HAPP_CRYPTOLINK
from core.bootstrap import MODES_CONFIG
base_use_crypto_link = bool(MODES_CONFIG.get("HAPP_CRYPTOLINK_ENABLED", HAPP_CRYPTOLINK))
use_crypto_link = await process_happ_cryptolink_override(
cluster_id=cluster_id,
plan=plan,
session=session,
email=email,
tg_id=tg_id,
happ_cryptolink=base_use_crypto_link,
**kwargs,
)
if not use_crypto_link:
return None
happ = result.get("happ") or {}
if isinstance(happ, dict):
crypto_link = happ.get("cryptoLink") or happ.get("link")
if crypto_link:
return crypto_link
return None
except Exception as e:
logger.warning(f"[EXTRACT_CRYPTOLINK] Ошибка при извлечении криптоссылки: {e}")
return None
async def process_get_cryptolink_after_renewal(
email: str,
cluster_id: str | None,
plan: int | None,
session: Any,
tg_id: int | None = None,
remnawave_nodes: list | None = None,
**kwargs,
) -> str | None:
"""
Получает свежие данные подписки после продления и извлекает криптоссылку если нужно.
Возвращает криптоссылку если хук требует её использования, иначе None.
"""
if not remnawave_nodes:
return None
try:
from config import REMNAWAVE_LOGIN, REMNAWAVE_PASSWORD
from database import get_tariff_by_id
from handlers.keys.operations.utils import is_plan_vless
from panels.remnawave import RemnawaveAPI
remna = RemnawaveAPI(remnawave_nodes[0]["api_url"])
if not await remna.login(REMNAWAVE_LOGIN, REMNAWAVE_PASSWORD):
return None
subscription_data = await remna.get_subscription_by_username(email)
if not subscription_data:
return None
need_vless_key = False
if plan:
tariff = await get_tariff_by_id(session, plan)
if tariff:
need_vless_key = is_plan_vless(tariff)
return await process_extract_cryptolink_from_result(
result=subscription_data,
cluster_id=cluster_id,
plan=plan,
session=session,
email=email,
tg_id=tg_id,
need_vless_key=need_vless_key,
**kwargs,
)
except Exception as e:
logger.warning(f"[GET_CRYPTOLINK_AFTER_RENEWAL] Ошибка получения криптоссылки: {e}")
return None
async def process_intercept_key_creation_message(
chat_id: int,
session: Any,
target_message: Any,
**kwargs,
) -> bool:
"""
Обрабатывает хук intercept_key_creation_message.
Возвращает True если нужно прервать выполнение (перехватить сообщение).
"""
try:
results = await run_hooks(
"intercept_key_creation_message",
chat_id=chat_id,
session=session,
target_message=target_message,
**kwargs,
)
return bool(results and results[0])
except Exception as e:
logger.warning(f"[INTERCEPT_KEY_CREATION] Ошибка при обработке хука: {e}")
return False
async def process_key_creation_complete(
chat_id: int,
session: Any,
email: str,
key_name: str,
admin: bool = False,
**kwargs,
) -> list:
"""
Обрабатывает хук key_creation_complete.
Возвращает список кнопок для добавления в меню после создания ключа.
"""
try:
results = await run_hooks(
"key_creation_complete",
chat_id=chat_id,
admin=admin,
session=session,
email=email,
key_name=key_name,
**kwargs,
)
return results if results else []
except Exception as e:
logger.warning(f"[KEY_CREATION_COMPLETE] Ошибка при обработке хука: {e}")
return []
async def process_process_callback_renew_key(
callback_query: Any,
state: Any,
session: Any,
**kwargs,
) -> list:
"""
Обрабатывает хук process_callback_renew_key.
Возвращает список кнопок для добавления в меню продления.
"""
try:
results = await run_hooks(
"process_callback_renew_key",
callback_query=callback_query,
state=state,
session=session,
**kwargs,
)
return results if results else []
except Exception as e:
logger.warning(f"[PROCESS_CALLBACK_RENEW_KEY] Ошибка при обработке хука: {e}")
return []
async def process_renewal_forbidden_groups(
chat_id: int,
session: Any,
admin: bool = False,
**kwargs,
) -> list[str]:
"""
Обрабатывает хук renewal_forbidden_groups.
Возвращает список дополнительных запрещенных групп для продления.
"""
try:
results = await run_hooks(
"renewal_forbidden_groups",
chat_id=chat_id,
admin=admin,
session=session,
**kwargs,
)
forbidden_groups = []
for result in results:
if isinstance(result, dict):
additional_groups = result.get("additional_groups", [])
if isinstance(additional_groups, list):
forbidden_groups.extend(additional_groups)
return forbidden_groups
except Exception as e:
logger.warning(f"[RENEWAL_FORBIDDEN_GROUPS] Ошибка при обработке хука: {e}")
return []
async def process_purchase_tariff_group_override(
chat_id: int,
session: Any,
original_group: str,
admin: bool = False,
**kwargs,
) -> dict | None:
"""
Обрабатывает хук purchase_tariff_group_override.
Возвращает dict с ключами:
- override_group: str - новая группа тарифов
- discount_info: dict | None - информация о скидке (опционально)
Или None если переопределение не требуется.
"""
try:
results = await run_hooks(
"purchase_tariff_group_override",
chat_id=chat_id,
admin=admin,
session=session,
original_group=original_group,
**kwargs,
)
for result in results:
if isinstance(result, dict) and result.get("override_group"):
return {
"override_group": result["override_group"],
"discount_info": result.get("discount_info"),
}
return None
except Exception as e:
logger.warning(f"[PURCHASE_TARIFF_GROUP_OVERRIDE] Ошибка при обработке хука: {e}")
return None
async def process_renew_tariffs(
chat_id: int,
session: Any,
admin: bool = False,
**kwargs,
) -> list:
"""
Обрабатывает хук renew_tariffs.
Возвращает список кнопок для добавления в меню выбора тарифов для продления.
"""
try:
results = await run_hooks(
"renew_tariffs",
chat_id=chat_id,
admin=admin,
session=session,
**kwargs,
)
return results if results else []
except Exception as e:
logger.warning(f"[RENEW_TARIFFS] Ошибка при обработке хука: {e}")
return []
async def process_renewal_complete(
chat_id: int,
session: Any,
email: str,
client_id: str,
admin: bool = False,
**kwargs,
) -> list:
"""
Обрабатывает хук renewal_complete.
Возвращает список кнопок для добавления в меню после продления подписки.
"""
try:
results = await run_hooks(
"renewal_complete",
chat_id=chat_id,
admin=admin,
session=session,
email=email,
client_id=client_id,
**kwargs,
)
return results if results else []
except Exception as e:
logger.warning(f"[RENEWAL_COMPLETE] Ошибка при обработке хука: {e}")
return []
async def process_view_key_menu(
key_name: str,
session: Any,
**kwargs,
) -> list:
"""
Обрабатывает хук view_key_menu.
Возвращает список кнопок для добавления в меню просмотра ключа.
"""
try:
results = await run_hooks(
"view_key_menu",
key_name=key_name,
session=session,
**kwargs,
)
return results if results else []
except Exception as e:
logger.warning(f"[VIEW_KEY_MENU] Ошибка при обработке хука: {e}")
return []
async def process_admin_key_edit_menu(
email: str,
session: Any,
**kwargs,
) -> list:
"""
Обрабатывает хук admin_key_edit_menu.
Возвращает список кнопок для добавления в меню редактирования ключа в админке.
"""
try:
results = await run_hooks(
"admin_key_edit_menu",
email=email,
session=session,
**kwargs,
)
return results if results else []
except Exception as e:
logger.warning(f"[ADMIN_KEY_EDIT_MENU] Ошибка при обработке хука: {e}")
return []
async def process_after_hwid_reset(
chat_id: int,
session: Any,
key_name: str,
admin: bool = False,
**kwargs,
) -> bool:
"""
Обрабатывает хук after_hwid_reset.
Возвращает True если нужно перенаправить пользователя в профиль после сброса устройств.
"""
try:
results = await run_hooks(
"after_hwid_reset",
chat_id=chat_id,
admin=admin,
session=session,
key_name=key_name,
**kwargs,
)
if not results:
return False
return any("redirect_to_profile" in str(result) for result in results)
except Exception as e:
logger.warning(f"[AFTER_HWID_RESET] Ошибка при обработке хука: {e}")
return False
async def process_tariff_menu(
group_code: str,
cluster_name: str,
tg_id: int,
session: Any,
**kwargs,
) -> list:
"""
Обрабатывает хук tariff_menu.
Возвращает список кнопок для добавления в меню выбора тарифов.
"""
try:
results = await run_hooks(
"tariff_menu",
group_code=group_code,
cluster_name=cluster_name,
tg_id=tg_id,
session=session,
**kwargs,
)
return results if results else []
except Exception as e:
logger.warning(f"[TARIFF_MENU] Ошибка при обработке хука: {e}")
return []
async def process_check_discount_validity(
chat_id: int,
session: Any,
tariff_group: str,
admin: bool = False,
**kwargs,
) -> dict | None:
"""
Обрабатывает хук check_discount_validity.
Возвращает dict с ключами:
- valid: bool - валидна ли скидка
- message: str - сообщение об ошибке (если valid=False)
Или None если скидка валидна.
"""
try:
results = await run_hooks(
"check_discount_validity",
chat_id=chat_id,
admin=admin,
session=session,
tariff_group=tariff_group,
**kwargs,
)
for result in results:
if isinstance(result, dict) and not result.get("valid", True):
return {
"valid": False,
"message": result.get("message", "❌ Скидка недоступна. Пожалуйста, выберите тариф заново."),
}
return None
except Exception as e:
logger.warning(f"[CHECK_DISCOUNT_VALIDITY] Ошибка при обработке хука: {e}")
return None
async def process_addons_menu(
email: str,
session: Any,
**kwargs,
) -> list:
"""
Обрабатывает хук addons_menu.
Возвращает список операций для модификации кнопок в меню конфигуратора тарифов.
"""
try:
results = await run_hooks(
"addons_menu",
email=email,
session=session,
**kwargs,
)
return results if results else []
except Exception as e:
logger.warning(f"[ADDONS_MENU] Ошибка при обработке хука: {e}")
return []
async def process_connect_device_menu(
chat_id: int,
session: Any,
admin: bool = False,
**kwargs,
) -> list:
"""
Обрабатывает хук connect_device_menu.
Возвращает список кнопок для добавления в меню подключения устройства.
"""
try:
results = await run_hooks(
"connect_device_menu",
chat_id=chat_id,
admin=admin,
session=session,
**kwargs,
)
return results if results else []
except Exception as e:
logger.warning(f"[CONNECT_DEVICE_MENU] Ошибка при обработке хука: {e}")
return []