151 lines
No EOL
5.7 KiB
C++
151 lines
No EOL
5.7 KiB
C++
#include "handlers.hpp"
|
||
#include "KeyboardFactory.hpp"
|
||
#include "structs.hpp"
|
||
#include "constants.hpp"
|
||
|
||
void BotHandlers::handleNavigation(TgBot::CallbackQuery::Ptr query, UserContext& ctx) {
|
||
const auto& current = ctx.history.back(); // текущий экран
|
||
const std::string& data = query->data;
|
||
int64_t chatId = query->message->chat->id;
|
||
int64_t messageId = query->message->messageId;
|
||
|
||
// Пагинация (в списках)
|
||
if ((data == BotConstants::Callback::LIST_PREV || data == BotConstants::Callback::LIST_NEXT)
|
||
&& (current.state == UserState::VIEWING_MY_TITLES || current.state == UserState::VIEWING_REVIEW_LIST ||
|
||
current.state == UserState::VIEWING_FOUND_TITLES)) {
|
||
|
||
int64_t newPayload = current.payload;
|
||
if (data == BotConstants::Callback::LIST_PREV && newPayload > 0) {
|
||
reducePayload(newPayload, current.state);
|
||
} else if (data == BotConstants::Callback::LIST_NEXT) {
|
||
increasePayload(newPayload, current.state);
|
||
} else {
|
||
if (data == BotConstants::Callback::LIST_PREV) {
|
||
std::cout << "Error: navigation:prev callback for 1st page" << std::endl;
|
||
return;
|
||
}
|
||
// TODO: log
|
||
std::cout << "Error: navigation:prev unknown error" << std::endl;
|
||
}
|
||
|
||
ctx.history.back().payload = newPayload;
|
||
|
||
auto result = renderCurrent(query, ctx);
|
||
if(result.message == "meow") return; // TODO: убрать
|
||
editMessage(chatId, messageId, result);
|
||
return;
|
||
}
|
||
|
||
// Обработка back по интерфейсу
|
||
if (data == BotConstants::Callback::NAV_BACK) {
|
||
if (!popState(ctx)) {
|
||
sendError(chatId, messageId, BotConstants::Text::SAD_ERROR);
|
||
return;
|
||
}
|
||
auto result = renderCurrent(query, ctx);
|
||
if(result.message == "meow") return; // TODO: убрать
|
||
editMessage(chatId, messageId, result);
|
||
return;
|
||
}
|
||
|
||
// Переходы вперёд (pyush)
|
||
auto newStepOpt = computeNextStep(query, current);
|
||
if (!newStepOpt.has_value()) {
|
||
sendError(chatId, messageId, BotConstants::Text::SAD_ERROR);
|
||
return;
|
||
}
|
||
|
||
ctx.history.push_back(*newStepOpt);
|
||
auto result = renderCurrent(query, ctx);
|
||
if(result.message == "meow") return; // TODO: убрать
|
||
editMessage(chatId, messageId, result);
|
||
}
|
||
|
||
HandlerResult BotHandlers::renderCurrent(TgBot::CallbackQuery::Ptr query, const UserContext& ctx) {
|
||
const auto& step = ctx.history.back();
|
||
//int64_t userId = query->from->id;
|
||
int64_t chatId = query->message->chat->id;
|
||
int64_t messageId = query->message->messageId;
|
||
switch (step.state) {
|
||
case UserState::MAIN_MENU:
|
||
return showMainMenu();
|
||
case UserState::VIEWING_MY_TITLES:
|
||
server_.fetchUserTitlesAsync(std::to_string(2)) // ALARM: тестовое значение вместо userId
|
||
.then([this, chatId, messageId](pplx::task<std::vector<BotStructs::Title>> t) {
|
||
try {
|
||
auto titles = t.get();
|
||
|
||
std::string message = formatTitlesList(titles);
|
||
auto keyboard = KeyboardFactory::createMyTitles(titles);
|
||
|
||
editMessage(chatId, messageId, {message, keyboard});
|
||
|
||
} catch (const std::exception& e) {
|
||
sendError(chatId, messageId, BotConstants::Text::SERVER_ERROR);
|
||
// Логирование ошибки (например, в cerr)
|
||
}
|
||
});
|
||
|
||
return {"meow", nullptr};
|
||
/*
|
||
case UserState::VIEWING_TITLE_PAGE:
|
||
return returnTitlePage(step.payload); // payload = titleId
|
||
case UserState::VIEWING_REVIEW:
|
||
return returnReview(step.payload); // payload = reviewId
|
||
case UserState::AWAITING_REVIEW:
|
||
return HandlerResult{"Пришлите текст отзыва:", nullptr};
|
||
// ...
|
||
*/
|
||
default:
|
||
return HandlerResult{BotConstants::Text::SAD_ERROR, nullptr};
|
||
}
|
||
}
|
||
|
||
std::optional<NavigationStep> BotHandlers::computeNextStep(
|
||
const TgBot::CallbackQuery::Ptr& query,
|
||
const NavigationStep& current
|
||
) {
|
||
const std::string& data = query->data;
|
||
|
||
switch (current.state) {
|
||
case UserState::MAIN_MENU:
|
||
if (data == BotConstants::Callback::MY_TITLES) {
|
||
return NavigationStep{UserState::VIEWING_MY_TITLES, 0};
|
||
}
|
||
break;
|
||
/*
|
||
case UserState::VIEWING_MY_TITLES:
|
||
if (data.starts_with("title_")) {
|
||
int64_t titleId = parseId(data);
|
||
return NavigationStep{UserState::VIEWING_TITLE_PAGE, titleId};
|
||
}
|
||
break;
|
||
|
||
case UserState::VIEWING_TITLE_PAGE:
|
||
if (data == BotConstants::Callback::ACTION_ADD_REVIEW) {
|
||
return NavigationStep{UserState::AWAITING_REVIEW, current.payload};
|
||
}
|
||
if (data.starts_with("review_")) {
|
||
int64_t reviewId = parseId(data);
|
||
return NavigationStep{UserState::VIEWING_REVIEW, reviewId};
|
||
}
|
||
break;
|
||
*/
|
||
default:
|
||
break;
|
||
}
|
||
return std::nullopt;
|
||
}
|
||
|
||
std::string BotHandlers::formatTitlesList(const std::vector<BotStructs::Title>& titles) {
|
||
if (titles.empty()) {
|
||
return "У вас пока нет тайтлов.";
|
||
}
|
||
|
||
std::string msg;
|
||
for (size_t i = 0; i < titles.size(); ++i) {
|
||
// num — 0-based, но в сообщении показываем 1-based
|
||
msg += std::to_string(i + 1) + ". " + titles[i].name + "\n";
|
||
}
|
||
return msg;
|
||
} |