Compare commits
No commits in common. "0fdf5776124ac31dcabfe7d6a09853b478c598d7" and "3d8abc3f0c20b8df3e2fb4db3f5b70056bd354d2" have entirely different histories.
0fdf577612
...
3d8abc3f0c
5 changed files with 22 additions and 189 deletions
1
api/.gitignore
vendored
1
api/.gitignore
vendored
|
|
@ -1 +0,0 @@
|
||||||
generated-client/
|
|
||||||
2
modules/bot/front/.gitignore
vendored
2
modules/bot/front/.gitignore
vendored
|
|
@ -1,2 +1,4 @@
|
||||||
build/
|
build/
|
||||||
out/
|
out/
|
||||||
|
.vscode
|
||||||
|
api/generated-client
|
||||||
|
|
@ -3,10 +3,6 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace BotConstants {
|
namespace BotConstants {
|
||||||
const int64_t NULL_PAYLOAD = -1; // Default value для payload
|
|
||||||
const int64_t DISP_TITLES_NUM = 6; // Количество тайтлов, отображаемых на страничке
|
|
||||||
const int64_t DISP_REVIEW_NUM = 4; // Количество ревью, отображаемых на страничке
|
|
||||||
|
|
||||||
namespace Button {
|
namespace Button {
|
||||||
const std::string FIND_ANIME = "Найти аниме";
|
const std::string FIND_ANIME = "Найти аниме";
|
||||||
const std::string MY_TITLES = "Мои тайтлы";
|
const std::string MY_TITLES = "Мои тайтлы";
|
||||||
|
|
@ -20,14 +16,13 @@ namespace BotConstants {
|
||||||
const std::string ADD_STATUS = ACTION + "add_status";
|
const std::string ADD_STATUS = ACTION + "add_status";
|
||||||
const std::string STATUS = "status:";
|
const std::string STATUS = "status:";
|
||||||
const std::string WATCHING = STATUS + "watching";
|
const std::string WATCHING = STATUS + "watching";
|
||||||
const std::string SEEN = STATUS + "seen";
|
const std::string SEEN = STATUS + "seen";
|
||||||
const std::string WANT = STATUS + "want";
|
const std::string WANT = STATUS + "want";
|
||||||
const std::string THROWN = STATUS + "thrown";
|
const std::string THROWN = STATUS + "thrown";
|
||||||
const std::string NAVIGATION = "navigation:";
|
const std::string NAVIGATION = "navigation:";
|
||||||
const std::string MY_TITLES = NAVIGATION + "my_titles";
|
const std::string MY_TITLES = NAVIGATION + "my_titles";
|
||||||
const std::string LIST_PREV = NAVIGATION + "prev"; // Пагинация
|
const std::string LIST_PREV = NAVIGATION + "prev";
|
||||||
const std::string LIST_NEXT = NAVIGATION + "next"; // Пагинация
|
const std::string LIST_NEXT = NAVIGATION + "next";
|
||||||
const std::string NAV_BACK = NAVIGATION + "back"; // Возврат по стеку состояний
|
|
||||||
const std::string CHOICE = "choice:";
|
const std::string CHOICE = "choice:";
|
||||||
}
|
}
|
||||||
namespace Text {
|
namespace Text {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@
|
||||||
#include <tgbot/tgbot.h>
|
#include <tgbot/tgbot.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <structs.hpp>
|
#include <structs.hpp>
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
/// @brief Структура возвращаемого значения класса BotHandlers для изменения текущего сообщения
|
/// @brief Структура возвращаемого значения класса BotHandlers для изменения текущего сообщения
|
||||||
struct HandlerResult {
|
struct HandlerResult {
|
||||||
|
|
@ -10,29 +9,6 @@ struct HandlerResult {
|
||||||
TgBot::InlineKeyboardMarkup::Ptr keyboard;
|
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 {
|
|
||||||
std::vector<NavigationStep> history; // Текущее состояние пользователя + история предыдущих состояний
|
|
||||||
};
|
|
||||||
|
|
||||||
class BotHandlers {
|
class BotHandlers {
|
||||||
public:
|
public:
|
||||||
BotHandlers(TgBot::Api api) : botApi(api) {;}
|
BotHandlers(TgBot::Api api) : botApi(api) {;}
|
||||||
|
|
@ -52,7 +28,6 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TgBot::Api botApi;
|
TgBot::Api botApi;
|
||||||
std::unordered_map<int64_t, UserContext> userContexts;
|
|
||||||
|
|
||||||
void handleNavigation(TgBot::CallbackQuery::Ptr query);
|
void handleNavigation(TgBot::CallbackQuery::Ptr query);
|
||||||
|
|
||||||
|
|
@ -62,25 +37,4 @@ private:
|
||||||
/// @param userId Идентификатор пользователя
|
/// @param userId Идентификатор пользователя
|
||||||
/// @return HandlerResult
|
/// @return HandlerResult
|
||||||
static HandlerResult returnMyTitles(int64_t userId);
|
static HandlerResult returnMyTitles(int64_t userId);
|
||||||
|
|
||||||
/// @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);
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -32,41 +32,22 @@ HandlerResult BotHandlers::returnMyTitles(int64_t userId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void BotHandlers::handleNavigation(TgBot::CallbackQuery::Ptr query) {
|
void BotHandlers::handleNavigation(TgBot::CallbackQuery::Ptr query) {
|
||||||
int64_t userId = query->from->id;
|
|
||||||
auto it = userContexts.find(userId);
|
|
||||||
if (it == userContexts.end()) {
|
|
||||||
botApi.sendMessage(query->message->chat->id, BotConstants::Text::SAD_ERROR);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
UserContext& ctx = it->second;
|
|
||||||
const std::string& data = query->data;
|
const std::string& data = query->data;
|
||||||
|
if (data == BotConstants::Callback::MY_TITLES) {
|
||||||
//HandlerResult response;
|
auto [text, kb] = BotHandlers::returnMyTitles(321);
|
||||||
//UserContext newCtx;
|
botApi.editMessageText(
|
||||||
|
text,
|
||||||
auto [response, newCtx] = newStateNavigation(query, ctx);
|
query->message->chat->id,
|
||||||
switch (ctx.state) {
|
query->message->messageId,
|
||||||
case UserState::VIEWING_MY_TITLES:
|
"",
|
||||||
response = BotHandlers::returnMyTitles(ctx.cursor);
|
"",
|
||||||
break;
|
nullptr,
|
||||||
case UserState::VIEWING_REVIEW_LIST:
|
kb
|
||||||
response = BotHandlers::returnReviewList(ctx.cursor);
|
);
|
||||||
break;
|
}
|
||||||
default:
|
else {
|
||||||
botApi.sendMessage(query->message->chat->id, BotConstants::Text::SAD_ERROR);
|
botApi.sendMessage(query->message->chat->id, BotConstants::Text::SAD_ERROR, nullptr, nullptr);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
botApi.editMessageText(
|
|
||||||
response.message,
|
|
||||||
query->message->chat->id,
|
|
||||||
query->message->messageId,
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
nullptr,
|
|
||||||
response.keyboard
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BotHandlers::handleMessage(TgBot::Message::Ptr message) {
|
void BotHandlers::handleMessage(TgBot::Message::Ptr message) {
|
||||||
|
|
@ -84,101 +65,3 @@ void BotHandlers::processCallbackImpl(TgBot::CallbackQuery::Ptr query) {
|
||||||
botApi.sendMessage(query->message->chat->id, BotConstants::Text::SAD_ERROR, nullptr, nullptr);
|
botApi.sendMessage(query->message->chat->id, BotConstants::Text::SAD_ERROR, nullptr, nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BotHandlers::handleNavigation(TgBot::CallbackQuery::Ptr query) {
|
|
||||||
int64_t userId = query->from->id;
|
|
||||||
auto it = userContexts.find(userId);
|
|
||||||
if (it == userContexts.end()) {
|
|
||||||
// TODO: log
|
|
||||||
std::cout << "Error: Не нашел пользователя " << userId;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
UserContext& ctx = it->second;
|
|
||||||
const auto& current = ctx.history.back(); // текущий экран
|
|
||||||
const std::string& data = query->data;
|
|
||||||
|
|
||||||
// Пагинация (в списках)
|
|
||||||
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(ctx);
|
|
||||||
editMessage(query, result);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Обработка back по интерфейсу
|
|
||||||
if (data == BotConstants::Callback::NAV_BACK) {
|
|
||||||
if (!popState(ctx)) {
|
|
||||||
botApi.answerCallbackQuery(query->id, "Некуда возвращаться", true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto result = renderCurrent(ctx);
|
|
||||||
editMessage(query, result);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Переходы вперёд (push)
|
|
||||||
auto newStepOpt = computeNextStep(query, current);
|
|
||||||
if (!newStepOpt.has_value()) {
|
|
||||||
sendError(query->message->chat->id);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.history.push_back(*newStepOpt);
|
|
||||||
auto result = renderCurrent(ctx);
|
|
||||||
editMessage(query, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BotHandlers::pushState(UserContext& ctx, UserState newState, int64_t payload) {
|
|
||||||
ctx.history.push_back({newState, payload});
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BotHandlers::popState(UserContext& ctx) {
|
|
||||||
if (ctx.history.size() <= 1) return false; // нельзя выйти из MAIN_MENU
|
|
||||||
ctx.history.pop_back();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BotHandlers::reducePayload(int64_t& payload, const UserState curState) {
|
|
||||||
if (curState == UserState::VIEWING_MY_TITLES ||
|
|
||||||
curState == UserState::VIEWING_FOUND_TITLES) {
|
|
||||||
payload -= BotConstants::DISP_TITLES_NUM;
|
|
||||||
} else if (curState == UserState::VIEWING_REVIEW_LIST) {
|
|
||||||
payload -= BotConstants::DISP_REVIEW_NUM;
|
|
||||||
} else {
|
|
||||||
// TODO: log
|
|
||||||
payload = BotConstants::NULL_PAYLOAD;
|
|
||||||
std::cerr << "Error: reducePayload" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void BotHandlers::increasePayload(int64_t& payload, const UserState curState) {
|
|
||||||
if (curState == UserState::VIEWING_MY_TITLES ||
|
|
||||||
curState == UserState::VIEWING_FOUND_TITLES) {
|
|
||||||
payload += BotConstants::DISP_TITLES_NUM;
|
|
||||||
} else if (curState == UserState::VIEWING_REVIEW_LIST) {
|
|
||||||
payload += BotConstants::DISP_REVIEW_NUM;
|
|
||||||
} else {
|
|
||||||
// TODO: log
|
|
||||||
payload = BotConstants::NULL_PAYLOAD;
|
|
||||||
std::cerr << "Error: increasePayload" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue