from aiogram.types import InlineKeyboardMarkup from aiogram.utils.keyboard import InlineKeyboardBuilder def insert_hook_buttons(builder: InlineKeyboardBuilder, buttons: list) -> InlineKeyboardBuilder: """ Вставляет кнопки из хуков в существующий builder. Поддерживает: - {"button": InlineKeyboardButton} — добавить в конец - {"after": callback_data, "button": InlineKeyboardButton} — вставить после заданной кнопки - {"insert_at": int, "button": InlineKeyboardButton} — вставить по индексу (0 = начало) - {"remove": str | list[str]} — удалить кнопки с указанным callback_data - {"remove_prefix": str} — удалить кнопки, у которых callback_data начинается с префикса """ markup = builder.as_markup() new_rows = markup.inline_keyboard.copy() buttons = buttons or [] flat_buttons = [] for item in buttons: if isinstance(item, list | tuple): flat_buttons.extend(item) else: flat_buttons.append(item) remove_operations = [b for b in flat_buttons if isinstance(b, dict) and ("remove" in b or "remove_prefix" in b)] for module in remove_operations: 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 insert_operations = [b for b in flat_buttons if isinstance(b, dict) and "insert_at" in b and "button" in b] for module in insert_operations: insert_at = module["insert_at"] button = module["button"] if 0 <= insert_at <= len(new_rows): new_rows.insert(insert_at, [button]) else: new_rows.append([button]) after_operations = [b for b in flat_buttons if isinstance(b, dict) and "after" in b and "button" in b] for module in after_operations: after = module["after"] button = module["button"] insert_pos = -1 for i, row in enumerate(new_rows): if any(getattr(btn, "callback_data", None) == after for btn in row): insert_pos = i + 1 break if 0 <= insert_pos <= len(new_rows): new_rows.insert(insert_pos, [button]) else: new_rows.append([button]) for module in flat_buttons: if isinstance(module, dict) and "button" in module and "insert_at" not in module and "after" not 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))