diff --git a/handlers/notifications/general_notifications.py b/handlers/notifications/general_notifications.py index 862e67fe..8e7d9541 100644 --- a/handlers/notifications/general_notifications.py +++ b/handlers/notifications/general_notifications.py @@ -53,6 +53,8 @@ from .hot_leads_notifications import notify_hot_leads from .notify_utils import send_messages_with_limit, send_notification from .special_notifications import notify_inactive_trial_users, notify_users_no_traffic +from hooks.hooks import run_hooks + router = Router() moscow_tz = pytz.timezone("Europe/Moscow") @@ -108,6 +110,10 @@ async def periodic_notifications(bot: Bot, *, sessionmaker: async_sessionmaker): await notify_users_no_traffic(bot, session, current_time, keys) except Exception as e: logger.error(f"Ошибка в notify_users_no_traffic: {e}") + try: + await run_hooks("periodic_notifications", bot=bot, session=session, keys=keys) + except Exception as e: + logger.error(f"Ошибка в хуках periodic_notifications: {e}") if NOTIFY_HOT_LEADS: try: diff --git a/hooks/hook_buttons.py b/hooks/hook_buttons.py index 668c4adb..1de2287a 100644 --- a/hooks/hook_buttons.py +++ b/hooks/hook_buttons.py @@ -4,19 +4,53 @@ from aiogram.utils.keyboard import InlineKeyboardBuilder def insert_hook_buttons(builder: InlineKeyboardBuilder, buttons: list) -> InlineKeyboardBuilder: """ - Вставляет кнопки из хуков в существующий builder (вставка после указанной кнопки через `after`) + Вставляет кнопки из хуков в существующий builder. + + Поддерживает: + - {"button": InlineKeyboardButton} — добавить в конец + - {"after": callback_data, "button": InlineKeyboardButton} — вставить после заданной кнопки + - {"remove": str | list[str]} — удалить кнопки с указанным callback_data + - {"remove_prefix": str} — удалить кнопки, у которых callback_data начинается с префикса """ markup = builder.as_markup() new_rows = markup.inline_keyboard.copy() - for module in buttons: + buttons = buttons or [] + flat_buttons = [] + for item in buttons: + if isinstance(item, (list, tuple)): + flat_buttons.extend(item) + else: + flat_buttons.append(item) + + for module in flat_buttons: + if isinstance(module, dict) and ("remove" in module or "remove_prefix" in module): + removes = module.get("remove") + if isinstance(removes, str): + removes = [removes] + removes = set(removes or []) + prefix = module.get("remove_prefix") + + filtered_rows = [] + for row in new_rows: + filtered_row = [] + for btn in row: + cdata = getattr(btn, "callback_data", None) + if cdata and (cdata in removes or (prefix and cdata.startswith(prefix))): + continue + filtered_row.append(btn) + if filtered_row: + filtered_rows.append(filtered_row) + new_rows = filtered_rows + + for module in flat_buttons: if isinstance(module, dict) and "after" in module and "button" in module: after = module["after"] button = module["button"] insert_pos = -1 for i, row in enumerate(new_rows): - if any(btn.callback_data == after for btn in row): + if any(getattr(btn, "callback_data", None) == after for btn in row): insert_pos = i + 1 break @@ -25,7 +59,10 @@ def insert_hook_buttons(builder: InlineKeyboardBuilder, buttons: list) -> Inline else: new_rows.append([button]) else: - button = module.get("button") if isinstance(module, dict) else module - new_rows.append([button]) + if isinstance(module, dict) and "button" in module: + button = module["button"] + new_rows.append([button]) + elif module and not isinstance(module, dict): # оставим совместимость со старыми модулями + new_rows.append([module]) return InlineKeyboardBuilder.from_markup(InlineKeyboardMarkup(inline_keyboard=new_rows))