from aiogram.fsm.context import FSMContext from aiogram.types import Message, CallbackQuery from .context import ContextData, CallbackCommand def save_navigation_context(callback_data: ContextData, state_data: dict) -> list[ContextData]: stack = [ContextData.unpack(item) for item in state_data.get("navigation_stack", [])] data_nc = state_data.get("navigation_context") navigation_context = ContextData.unpack(data_nc) if data_nc else None if callback_data.back: callback_data.back = False if stack: stack.pop() else: if (stack and navigation_context and navigation_context.command == callback_data.command and navigation_context.command != CallbackCommand.USER_COMMAND): navigation_context = callback_data elif navigation_context: stack.append(navigation_context) state_data["navigation_stack"] = [item.pack() for item in stack] state_data["navigation_context"] = callback_data.pack() return stack def pop_navigation_context(stack: list[ContextData]) -> ContextData | None: if stack: data = stack[-1] data.back = True return data def get_navigation_context(state_data: dict) -> tuple[list[ContextData], ContextData | None]: data_nc = state_data.get("navigation_context") context = ContextData.unpack(data_nc) if data_nc else None return ([ContextData.unpack(item) for item in state_data.get("navigation_stack", [])], context) def clear_state(state_data: dict, clear_nav: bool = False): if clear_nav: state_data.clear() else: stack = state_data.get("navigation_stack") context = state_data.get("navigation_context") state_data.clear() if stack: state_data["navigation_stack"] = stack if context: state_data["navigation_context"] = context async def route_callback(message: Message | CallbackQuery, back: bool = True, **kwargs): state_data = kwargs["state_data"] stack, context = get_navigation_context(state_data) if back: context = pop_navigation_context(stack) stack = save_navigation_context(callback_data = context, state_data = state_data) kwargs.update({"callback_data": context, "navigation_stack": stack}) if context: if context.command == CallbackCommand.MENU_ENTRY_MAIN: await main_menu(message, **kwargs) elif context.command == CallbackCommand.MENU_ENTRY_SETTINGS: await settings_menu(message, **kwargs) elif context.command == CallbackCommand.MENU_ENTRY_PARAMETERS: await parameters_menu(message, **kwargs) elif context.command == CallbackCommand.MENU_ENTRY_LANGUAGE: await language_menu(message, **kwargs) elif context.command == CallbackCommand.MENU_ENTRY_ENTITIES: await entities_menu(message, **kwargs) elif context.command == CallbackCommand.ENTITY_LIST: await entity_list(message, **kwargs) elif context.command == CallbackCommand.ENTITY_ITEM: await entity_item(message, **kwargs) elif context.command == CallbackCommand.FIELD_EDITOR: await field_editor(message, **kwargs) else: raise ValueError(f"Unknown command {context.command}") else: raise ValueError("No navigation context") from .menu.main import main_menu from .menu.settings import settings_menu from .menu.parameters import parameters_menu from .menu.language import language_menu from .menu.entities import entities_menu from .forms.entity_list import entity_list from .forms.entity_form import entity_item from .editors import field_editor