#pragma once #include #include #include #include /// @brief Структура возвращаемого значения класса BotHandlers для изменения текущего сообщения struct HandlerResult { std::string message; TgBot::InlineKeyboardMarkup::Ptr keyboard; }; enum class UserState { MAIN_MENU, // Главное меню VIEWING_MY_TITLES, // Список моих тайтлов AWAITING_TITLE_NAME, // Жду название тайтла для поиска VIEWING_FOUND_TITLES, // Смотрю найденные тайтлы VIEWING_TITLE_PAGE, // Смотрю страничку тайтла AWAITING_REVIEW, // Жду ревью на тайтл VIEWING_REVIEW_LIST, // Смотрю список ревью на тайтл VIEWING_REVIEW, // Смотрю (конкретное) ревью на тайтл VIEWING_DESCRIPTION, // Смотрю описание тайтла ERROR, // Ошибка состояния }; struct NavigationStep { UserState state; int64_t payload; // ID тайтла, ревью и т.д. }; struct UserContext { int64_t userId; std::vector history; // Текущее состояние пользователя + история предыдущих состояний }; class BotHandlers { public: BotHandlers(TgBot::Api api) : botApi(api) {;} /// @brief Обработка callback'ов из кнопок интерфейса /// @param query запрос callback void handleCallback(TgBot::CallbackQuery::Ptr query); /// @brief Обработка сообщений боту /// @details /// Функция для обработки сообщений, которые юзер отправляет /// боту. Необходима для обработки ревью и названий искомого /// аниме. Внутри себя проверяет текущий state пользователя /// в боте. /// @param message обрабатываемое сообщение void handleMessage(TgBot::Message::Ptr message); /// @brief Создает контекст начального меню для пользователя /// @param chatId id чата пользователя void createInitContext(int64_t chatId); private: TgBot::Api botApi; std::unordered_map userContexts; void handleNavigation(TgBot::CallbackQuery::Ptr query, UserContext& ctx); void handleError(TgBot::CallbackQuery::Ptr query, UserContext& ctx); void processCallbackImpl(TgBot::CallbackQuery::Ptr query); /// @brief Получить очередную страницу тайтлов из списка пользователя /// @param userId Идентификатор пользователя /// @param payload Полезная нагрузка /// @return HandlerResult static HandlerResult returnMyTitles(int64_t userId, int64_t payload); /// @brief Вход в новое состояние /// @param ctx текущий контекст /// @param newState новое состояние, добавляемое в стек /// @param payload полезная нагрузка этого состояния void pushState(UserContext& ctx, UserState newState, int64_t payload); /// @brief Возврат в предыдущее состояние /// @param ctx Текущий контекст /// @return true в случае успеха bool popState(UserContext& ctx); /// @brief Уменьшает значение нагрузки с учетом текущего состояния /// @param payload Изменяемое значение нагрузки /// @param curState Текущее состояние void reducePayload(int64_t& payload, const UserState curState); /// @brief Увеличивает значение нагрузки с учетом текущего состояния /// @param payload Изменяемое значение нагрузки /// @param curState Текущее состояние void increasePayload(int64_t& payload, const UserState curState); /// @brief Редактирует текущее сообщение в диалоге с пользователем /// @details Меняет текст сообщения и клавиатуру на те, что передаются /// в аргументе response. Информацию об id чата и изменяемого сообщения /// забирает из query, который возвращается с callback'ом после нажатия /// кнопки в интерфейсе /// @param query Callback запрос /// @param response Параметры ответа: клавиатура и текст void editMessage(TgBot::CallbackQuery::Ptr query, HandlerResult response); /// @brief Отрисовка текущего экрана (соотв. контексту) /// @param ctx - текущий контекст /// @return HandlerResult для нового состояния сообщения HandlerResult renderCurrent(const UserContext& ctx); /// @brief Логика переходов между контекстами (навигация на следующий шаг) /// @param query - запрос /// @param current - текущий шаг навигации /// @return следующий NavigationStep при успехе (std::nullopt в случае ошибки) std::optional computeNextStep(const TgBot::CallbackQuery::Ptr& query, const NavigationStep& current); /// @brief Получить состояние страницы главного меню /// @return HandlerResult с параметрами главного меню HandlerResult showMainMenu(); /// @brief Посылает интерфейс обработки ошибки на callback запрос /// @param query запрос void sendError(TgBot::CallbackQuery::Ptr query, const std::string& errText); };