""" Конфигурация FSM-потоков: - PAYLOADS — все callback payload строки (статические и шаблонные) - TRANSITIONS — таблица переходов между состояниями Использование переходов в handlers: await context.set_state(TRANSITIONS["ticket:start"]) Использование payload в keyboards: payload=PAYLOADS.CREATE_TICKET payload=PAYLOADS.ITICKET_DETAIL.format(id=task_id) Использование префиксов в фильтрах: PayloadStartsWith(PAYLOADS.PFX_ITICKET_DETAIL) """ from bot.states import AuthStates, CommentStates, TicketStates class PAYLOADS: """Callback payload строки для кнопок и фильтров.""" # Статические payload CREATE_TICKET = "create_ticket" VIEW_TICKETS = "view_tickets" DONE_TICKET = "done_ticket" CONFIRM_TICKET = "confirm_ticket" EDIT_TICKET = "edit_ticket" CANCEL_TICKET = "cancel_ticket" MAIN_MENU = "main_menu" # Динамические payload — форматировать через .format(...) TICKET_DETAIL = "ticket_detail:{id}" TICKETS_PAGE = "tickets_page:{page}" ITICKET_DETAIL = "iticket_detail:{id}" ITICKETS_PAGE = "itickets_page:{page}" ITICKET_COMMENT = "iticket_comment:{task_id}" ITICKET_CLOSE = "iticket_close:{task_id}" # Quick reply CONFIRM_REPLY = "confirm_reply:{task_id}" CANCEL_REPLY = "cancel_reply" # Префиксы для PayloadStartsWith(...) PFX_TICKET_DETAIL = "ticket_detail:" PFX_TICKETS_PAGE = "tickets_page:" PFX_ITICKET_DETAIL = "iticket_detail:" PFX_ITICKETS_PAGE = "itickets_page:" PFX_ITICKET_COMMENT = "iticket_comment:" PFX_ITICKET_CLOSE = "iticket_close:" PFX_CONFIRM_REPLY = "confirm_reply:" TRANSITIONS: dict[str, object] = { # ── Auth ────────────────────────────────────────────────────────────────── # Новый / не авторизованный пользователь — запрашиваем контакт "auth:new_user": AuthStates.waiting_contact, # Авторизованный пользователь — сбросить в None (главное меню) "auth:authorized": None, # Заблокированный пользователь — сбросить в None "auth:blocked": None, # Контакт найден в белом списке → авторизован → главное меню "auth:contact_found": None, # ── Ticket creation ─────────────────────────────────────────────────────── # Нажали «Создать заявку» "ticket:start": TicketStates.waiting_description, # Получили первое сообщение с текстом описания "ticket:description_ok": TicketStates.collecting_attachments, # Нажали «Перейти к предпросмотру» "ticket:preview": TicketStates.confirming, # Подтвердили создание заявки "ticket:confirm": None, # Нажали «Продолжить редактирование» "ticket:edit": TicketStates.collecting_attachments, # Отменили создание заявки "ticket:cancel": None, # ── Comment ─────────────────────────────────────────────────────────────── # Нажали «Оставить комментарий» "comment:start": CommentStates.waiting_text, # Комментарий отправлен (или отменён через «Назад») "comment:done": None, # ── Quick reply ─────────────────────────────────────────────────────────── # Свободное сообщение перехвачено — ждём подтверждения от пользователя "reply:pending": TicketStates.pending_confirm, # Подтверждено / отменено — возврат в idle "reply:done": None, "reply:cancel": None, # ── Navigation / global ─────────────────────────────────────────────────── # Перейти в главное меню "nav:menu": None, # Отменить текущее действие (/cancel) "nav:cancel": None, }