feat(tgbot-front): start creating thread-safe user context

This commit is contained in:
Kirill 2025-12-06 02:44:24 +03:00
parent a7b47c564a
commit b1c035ae35
2 changed files with 98 additions and 0 deletions

View file

@ -0,0 +1,55 @@
#pragma once
#include <unordered_map>
#include <vector>
#include <mutex>
#include <optional>
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<NavigationStep> history; // Текущее состояние пользователя + история предыдущих состояний
};
class BotUserContext {
private:
mutable std::mutex mtx;
std::unordered_map<int64_t, UserContext> userContexts;
public:
// Получить копию контекста пользователя (или std::nullopt, если не найден)
std::optional<UserContext> getContext(int64_t userId) const;
// Установить/обновить контекст пользователя
void setContext(int64_t userId, const UserContext& context);
// Добавить шаг навигации к существующему контексту пользователя
// Если пользователя нет — создаётся новый контекст
void pushNavigationStep(int64_t userId, const NavigationStep& step);
// Заменить текущую историю (полезно, например, при сбросе состояния)
void setNavigationHistory(int64_t userId, const std::vector<NavigationStep>& history);
// Получить текущий шаг (последний в истории) или std::nullopt, если нет истории
std::optional<NavigationStep> getCurrentStep(int64_t userId) const;
// Удалить контекст пользователя (например, при логауте)
void removeContext(int64_t userId);
};

View file

@ -0,0 +1,43 @@
#include "BotUserContext.hpp"
std::optional<UserContext> BotUserContext::getContext(int64_t userId) const {
std::lock_guard<std::mutex> lock(mtx);
auto it = userContexts.find(userId);
if (it != userContexts.end()) {
return it->second;
}
return std::nullopt;
}
void BotUserContext::setContext(int64_t userId, const UserContext& context) {
std::lock_guard<std::mutex> lock(mtx);
userContexts[userId] = context;
}
void BotUserContext::pushNavigationStep(int64_t userId, const NavigationStep& step) {
std::lock_guard<std::mutex> lock(mtx);
auto& ctx = userContexts[userId];
ctx.userId = userId;
ctx.history.push_back(step);
}
void BotUserContext::setNavigationHistory(int64_t userId, const std::vector<NavigationStep>& history) {
std::lock_guard<std::mutex> lock(mtx);
auto& ctx = userContexts[userId];
ctx.userId = userId;
ctx.history = history;
}
std::optional<NavigationStep> BotUserContext::getCurrentStep(int64_t userId) const {
std::lock_guard<std::mutex> lock(mtx);
auto it = userContexts.find(userId);
if (it != userContexts.end() && !it->second.history.empty()) {
return it->second.history.back();
}
return std::nullopt;
}
void BotUserContext::removeContext(int64_t userId) {
std::lock_guard<std::mutex> lock(mtx);
userContexts.erase(userId);
}