Рефакторинг Storage.

Диалог SubscribeCase доведен до рабочего состояния.
This commit is contained in:
Kirill Kirilenko 2022-11-20 01:39:47 +03:00
parent 61246591f0
commit c9a587f1b7
6 changed files with 60 additions and 57 deletions

View file

@ -40,7 +40,7 @@ void Bot::setupCommands()
});
}
void Bot::notifyUser(int userId,
void Bot::notifyUser(UserId userId,
const std::string& caseNumber,
std::string caseUrl,
const CaseHistoryItem& item)

View file

@ -15,7 +15,7 @@ class Bot
public:
explicit Bot(boost::asio::io_context& asioContext, LocalStorage& storage, bool& terminationFlag);
void notifyUser(int userId,
void notifyUser(UserId userId,
const std::string& caseNumber,
std::string caseUrl,
const CaseHistoryItem& item);

View file

@ -5,7 +5,7 @@
#include <fstream>
using json = nlohmann::json;
using json = nlohmann::ordered_json;
std::uint32_t parseTime(const std::string& str)
{
@ -30,23 +30,22 @@ void loadStorage(LocalStorage& storage)
std::ifstream ifs("storage.json");
if (ifs.is_open())
{
auto data = json::parse(ifs);
storage.token = data.at("token").get<std::string>();
storage.checkTime = parseTime(data.at("check_time").get<std::string>());
auto jsonStorage = json::parse(ifs);
storage.token = jsonStorage.at("token").get<std::string>();
storage.checkTime = parseTime(jsonStorage.at("check_time").get<std::string>());
for (const auto& subscription : data.at("subscriptions"))
for (const auto& jsonUserData : jsonStorage.at("user_data"))
{
Subscription s;
s.userId = subscription.at("user_id");
for (const auto& counter : subscription.at("counters"))
UserData userData;
auto userId = jsonUserData.at("user_id").get<UserId>();
for (const auto& jsonCaseSubscription : jsonUserData.at("case_subscriptions"))
{
Counter c;
c.courtId = counter.at("court").get<int>();
c.caseNumber = counter.at("case").get<std::string>();
c.value = counter.at("value").get<std::size_t>();
s.counters.push_back(std::move(c));
UserData::CaseSubscription caseSubscription;
auto caseNumber = jsonCaseSubscription.at("case").get<std::string>();
caseSubscription.counter = jsonCaseSubscription.at("counter").get<std::size_t>();
userData.caseSubscriptions[caseNumber] = caseSubscription;
}
storage.subscriptions.push_back(std::move(s));
storage.userData[userId] = std::move(userData);
}
}
else
@ -55,30 +54,29 @@ void loadStorage(LocalStorage& storage)
void saveStorage(const LocalStorage& storage)
{
json data;
data["token"] = storage.token;
data["check_time"] = timeToString(storage.checkTime);
json jsonStorage;
jsonStorage["token"] = storage.token;
jsonStorage["check_time"] = timeToString(storage.checkTime);
data["subscriptions"] = json::array();
for (const auto& subscription : storage.subscriptions)
jsonStorage["user_data"] = json::array();
for (const auto& subscription : storage.userData)
{
json jsonSubscription;
jsonSubscription["user_id"] = subscription.userId;
jsonSubscription["counters"] = json::array();
for (const auto& counter : subscription.counters)
json jsonUserData;
jsonUserData["user_id"] = subscription.first;
jsonUserData["case_subscriptions"] = json::array();
for (const auto& caseSubscription : subscription.second.caseSubscriptions)
{
json jsonCounter;
jsonCounter["court"] = counter.courtId;
jsonCounter["case"] = counter.caseNumber;
jsonCounter["value"] = counter.value;
jsonSubscription["counters"].push_back(std::move(jsonCounter));
json jsonCaseSubscription;
jsonCaseSubscription["case"] = caseSubscription.first;
jsonCaseSubscription["counter"] = caseSubscription.second.counter;
jsonUserData["case_subscriptions"].push_back(std::move(jsonCaseSubscription));
}
data["subscriptions"].push_back(std::move(jsonSubscription));
jsonStorage["user_data"].push_back(std::move(jsonUserData));
}
std::ofstream ofs("storage.json");
if (ofs.is_open())
ofs << std::setw(2) << data;
ofs << std::setw(2) << jsonStorage;
else
throw std::runtime_error("failed to save storage");
}

View file

@ -2,26 +2,26 @@
#define COURT_MONITOR_STORAGE_H
#include <cstddef>
#include <map>
#include <string>
#include <vector>
struct Counter
using UserId = std::int64_t;
struct UserData
{
int courtId = 0;
std::string caseNumber;
std::size_t value = 0;
struct CaseSubscription
{
std::size_t counter = 0;
};
struct Subscription
{
int userId = 0;
std::vector<Counter> counters;
std::map<std::string, CaseSubscription> caseSubscriptions;
};
struct LocalStorage
{
std::string token;
std::vector<Subscription> subscriptions;
std::map<UserId, UserData> userData;
std::uint32_t checkTime; // секунды с 00:00
};

View file

@ -38,6 +38,7 @@ struct SubscribeCaseStateMachine : StateMachine<SubscribeCaseStateMachine, Waiti
}
LocalStorage& storage;
std::string caseNumber;
CaseDetails caseDetails;
};
namespace {
@ -87,13 +88,14 @@ struct GettingCaseDetails : State<GettingCaseDetails, SubscribeCaseStateMachine>
try
{
auto details = getCaseDetails(ioContext, machine.caseNumber);
machine.caseDetails = 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{}\n",
machine.caseDetails.name);
for (const auto& participant : machine.caseDetails.participants)
fmt::format_to(std::back_inserter(text), "{}: {}\n", participant.title,
participant.name);
fmt::format_to(std::back_inserter(text), "Судья: {}", details.judgeName);
fmt::format_to(std::back_inserter(text), "Судья: {}", machine.caseDetails.judgeName);
banana::api::inline_keyboard_markup_t keyboard;
keyboard.inline_keyboard.resize(1);
@ -148,8 +150,10 @@ struct WaitingForConfirmation : State<WaitingForConfirmation, SubscribeCaseState
if (*event.query.data == "yes")
{
// TODO
auto& userData = machine.storage.userData[machine.userId];
userData.caseSubscriptions[machine.caseNumber].counter =
machine.caseDetails.history.size();
saveStorage(machine.storage);
return transit<Subscribed>();
}
else if (*event.query.data == "no")

View file

@ -19,19 +19,20 @@ boost::asio::io_context asioContext;
void processAllSubscriptions(LocalStorage& storage, Bot& bot)
{
for (auto& subscription : storage.subscriptions)
for (auto& userData : storage.userData)
{
try
{
LOG(main, "* Processing subscriptions for user {}", subscription.userId);
for (auto& counter : subscription.counters)
const auto& userId = userData.first;
LOG(main, "* Processing subscriptions for user {}", userId);
for (auto& caseSubscription : userData.second.caseSubscriptions)
{
LOG(main, "** Processing case {}", counter.caseNumber);
auto details = getCaseDetails(asioContext, counter.caseNumber);
for (std::size_t i = counter.value; i < details.history.size(); i++)
bot.notifyUser(subscription.userId, counter.caseNumber, details.url,
details.history[i]);
counter.value = details.history.size();
const auto& caseNumber = caseSubscription.first;
LOG(main, "** Processing case {}", caseNumber);
auto details = getCaseDetails(asioContext, caseNumber);
for (std::size_t i = caseSubscription.second.counter; i < details.history.size(); i++)
bot.notifyUser(userId, caseNumber, details.url, details.history[i]);
caseSubscription.second.counter = details.history.size();
}
}
catch (const std::exception& e)