#include "SubscribeCaseDialog.h" #include "CourtApi.h" #include "DialogHelpers.h" #include "Logger.h" #include #include #include #include #include namespace { // clang-format off // Состояния struct WaitingForInput; struct GettingCaseDetails; struct WaitingForConfirmation; struct Subscribed; // События struct CaseDetailsFetched : statechart::event { }; struct SubscriptionConfirmed : statechart::event { }; // clang-format on } // namespace struct SubscribeCaseStateMachine : StateMachine { SubscribeCaseStateMachine(banana::agent::beast_callback& agent, long userId, LocalStorage& storage) : StateMachine(agent, userId), storage(storage) { } LocalStorage& storage; std::string caseNumber; }; namespace { struct WaitingForInput : State { using reactions = statechart::custom_reaction; explicit WaitingForInput(const my_context& ctx) : State(ctx, "WaitingForInput") { auto& machine = context(); std::string text = "Введите номер дела..."; banana::api::send_message(machine.agent, {.chat_id = machine.userId, .text = std::move(text)}, [](auto) {}); } statechart::result react(const NewMessageEvent& event) { auto& machine = context(); const std::regex rex(R"(\d-(?:\d+)/(?:\d){4}-(?:\d+))"); std::smatch captures; if (std::regex_match(*event.message.text, captures, rex)) { machine.caseNumber = *event.message.text; return transit(); } else { std::string text = "Некорректный формат номера дела!\n" "Попробуйте еще раз."; banana::api::send_message( machine.agent, {.chat_id = machine.userId, .text = std::move(text)}, [](auto) {}); return discard_event(); } } }; struct GettingCaseDetails : State { using reactions = statechart::custom_reaction; explicit GettingCaseDetails(const my_context& ctx) : State(ctx, "GettingCaseDetails") { auto& machine = context(); boost::asio::io_context ioContext; try { auto details = getCaseDetails(ioContext, machine.caseNumber); std::string text; fmt::format_to(std::back_inserter(text), "Проверьте информацию:\n{}\n", details.name); for (const auto& participant : details.participants) fmt::format_to(std::back_inserter(text), "{}: {}\n", participant.title, participant.name); fmt::format_to(std::back_inserter(text), "Судья: {}", details.judgeName); banana::api::inline_keyboard_markup_t keyboard; keyboard.inline_keyboard.resize(1); keyboard.inline_keyboard[0].resize(2); keyboard.inline_keyboard[0][0].text = "Верно"; keyboard.inline_keyboard[0][0].callback_data = "yes"; keyboard.inline_keyboard[0][1].text = "Отмена"; keyboard.inline_keyboard[0][1].callback_data = "no"; banana::api::send_message( machine.agent, {.chat_id = machine.userId, .text = std::move(text), .reply_markup = keyboard}, [](auto) {}); post_event(CaseDetailsFetched()); } catch (const std::exception& e) { LOGE(dialog, e.what()); // TODO ??? } } statechart::result react(const CaseDetailsFetched& event) { return transit(); } }; struct WaitingForConfirmation : State { using reactions = statechart::custom_reaction; explicit WaitingForConfirmation(const my_context& ctx) : State(ctx, "WaitingForConfirmation") {} statechart::result react(const NewCallbackQueryEvent& event) { auto& machine = context(); if (event.query.data) { if (event.query.message) banana::api::edit_message_reply_markup( machine.agent, {.chat_id = event.query.message->chat.id, .message_id = event.query.message->message_id}, [](banana::expected> result) { if (!result) LOGE(dialog, result.error()); }); if (*event.query.data == "yes") { // TODO return transit(); } else if (*event.query.data == "no") { return transit(); } } return discard_event(); } }; struct Subscribed : State { explicit Subscribed(const my_context& ctx) : State(ctx, "Subscribed") {} }; } // namespace ///////////////////////////////////////////////////////////////////////////// SubscribeCaseDialog::SubscribeCaseDialog(banana::agent::beast_callback& agent, banana::integer_t userId, LocalStorage& storage) : Dialog(userId, "SubscribeCase"), machine_(std::make_unique(agent, userId, storage)) { machine_->initiate(); } SubscribeCaseDialog::~SubscribeCaseDialog() = default; bool SubscribeCaseDialog::processMessage(const banana::api::message_t& message) { machine_->process_event(NewMessageEvent{message}); return machine_->state_cast().isFinal(); } bool SubscribeCaseDialog::processCallbackQuery(const banana::api::callback_query_t& query) { machine_->process_event(NewCallbackQueryEvent{query}); return machine_->state_cast().isFinal(); }