Add store_raw_json option to config
This commit is contained in:
parent
3b071727c3
commit
9d4d52bed0
19 changed files with 245 additions and 110 deletions
|
@ -6,3 +6,4 @@ backend=sqlite
|
||||||
[options]
|
[options]
|
||||||
fetch_extra_delay=30
|
fetch_extra_delay=30
|
||||||
api_key=my_key_here
|
api_key=my_key_here
|
||||||
|
store_raw_json=true
|
||||||
|
|
|
@ -24,6 +24,8 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <cctype>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
namespace duck {
|
namespace duck {
|
||||||
|
|
||||||
|
@ -45,6 +47,32 @@ namespace {
|
||||||
constexpr const char g_api_key[] = "api_key";
|
constexpr const char g_api_key[] = "api_key";
|
||||||
constexpr const char g_api_key_def[] = "";
|
constexpr const char g_api_key_def[] = "";
|
||||||
|
|
||||||
|
constexpr const char g_store_raw_json_sect[] = "options";
|
||||||
|
constexpr const char g_store_raw_json[] = "store_raw_json";
|
||||||
|
constexpr const char g_store_raw_json_def[] = "false";
|
||||||
|
|
||||||
|
bool equal (std::string_view a, std::string_view b) {
|
||||||
|
return a.size() == b.size() and std::equal(
|
||||||
|
a.begin(), a.end(),
|
||||||
|
b.begin(),
|
||||||
|
[](auto c1, auto c2) {return std::tolower(c1) == std::tolower(c2); }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool to_bool (std::string_view a) {
|
||||||
|
std::array<std::string_view, 10> yes_list {
|
||||||
|
"true", "1", "yes", "on", "ok", "enable", "enabled", "sure", "aye", "one"
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
std::find_if(
|
||||||
|
yes_list.begin(),
|
||||||
|
yes_list.end(),
|
||||||
|
[a](std::string_view b) -> bool { return equal(a, b); }
|
||||||
|
) != yes_list.end()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
std::string whole_ini() {
|
std::string whole_ini() {
|
||||||
std::ifstream input(g_config_file_path);
|
std::ifstream input(g_config_file_path);
|
||||||
input >> std::noskipws;
|
input >> std::noskipws;
|
||||||
|
@ -132,4 +160,10 @@ std::string_view AppConfig::backend() const {
|
||||||
return value_ifp(m_ini, g_backend_sect, g_backend, g_def_backend_name, false);
|
return value_ifp(m_ini, g_backend_sect, g_backend, g_def_backend_name, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AppConfig::store_raw_json() const {
|
||||||
|
std::string_view val = value_ifp(m_ini, g_store_raw_json_sect, g_store_raw_json, g_store_raw_json_def, false);
|
||||||
|
|
||||||
|
return to_bool(val);
|
||||||
|
}
|
||||||
|
|
||||||
} //namespace duck
|
} //namespace duck
|
||||||
|
|
|
@ -33,6 +33,7 @@ public:
|
||||||
std::size_t worker_threads() const;
|
std::size_t worker_threads() const;
|
||||||
std::size_t fetch_extra_delay() const;
|
std::size_t fetch_extra_delay() const;
|
||||||
std::string_view backend() const;
|
std::string_view backend() const;
|
||||||
|
bool store_raw_json() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
kamokan::IniFile m_ini;
|
kamokan::IniFile m_ini;
|
||||||
|
|
|
@ -56,7 +56,7 @@ namespace {
|
||||||
};
|
};
|
||||||
} //unnamed namespace
|
} //unnamed namespace
|
||||||
|
|
||||||
void test(oro::Api* api, oro::OriginsDB* db, std::size_t extra_delay, std::size_t thread_count) {
|
void test(oro::Api* api, oro::OriginsDB* db, std::size_t extra_delay, std::size_t thread_count, bool store_raw_json) {
|
||||||
typedef TimerOroApi<oro::DBOperation::Shops> TimerShops;
|
typedef TimerOroApi<oro::DBOperation::Shops> TimerShops;
|
||||||
typedef TimerOroApi<oro::DBOperation::Items> TimerItems;
|
typedef TimerOroApi<oro::DBOperation::Items> TimerItems;
|
||||||
typedef TimerOroApi<oro::DBOperation::Icons> TimerIcons;
|
typedef TimerOroApi<oro::DBOperation::Icons> TimerIcons;
|
||||||
|
@ -71,11 +71,12 @@ void test(oro::Api* api, oro::OriginsDB* db, std::size_t extra_delay, std::size_
|
||||||
const double ed = static_cast<double>(extra_delay);
|
const double ed = static_cast<double>(extra_delay);
|
||||||
|
|
||||||
auto sig_int = worker.make_event<SignalInt>(&worker);
|
auto sig_int = worker.make_event<SignalInt>(&worker);
|
||||||
|
const bool& rj = store_raw_json;
|
||||||
|
|
||||||
auto timer_items = worker.make_event<TimerItems>(TSet{0.0, ed}, &pool, api, db);
|
auto timer_items = worker.make_event<TimerItems>(TSet{0.0, ed, rj}, &pool, api, db);
|
||||||
auto timer_icons = worker.make_event<TimerIcons>(TSet{5.0, ed}, &pool, api, db);
|
auto timer_icons = worker.make_event<TimerIcons>(TSet{5.0, ed, rj}, &pool, api, db);
|
||||||
auto timer_shops = worker.make_event<TimerShops>(TSet{10.0, ed}, &pool, api, db);
|
auto timer_shops = worker.make_event<TimerShops>(TSet{10.0, ed, rj}, &pool, api, db);
|
||||||
auto timer_creat = worker.make_event<TimerCreators>(TSet{15.0, ed}, &pool, api, db);
|
auto timer_creat = worker.make_event<TimerCreators>(TSet{15.0, ed, rj}, &pool, api, db);
|
||||||
|
|
||||||
worker.wait();
|
worker.wait();
|
||||||
#if !defined(NDEBUG)
|
#if !defined(NDEBUG)
|
||||||
|
|
|
@ -26,6 +26,6 @@ namespace oro {
|
||||||
|
|
||||||
namespace duck {
|
namespace duck {
|
||||||
|
|
||||||
void test(oro::Api* api, oro::OriginsDB* db, std::size_t extra_delay, std::size_t thread_count);
|
void test(oro::Api* api, oro::OriginsDB* db, std::size_t extra_delay, std::size_t thread_count, bool store_raw_json);
|
||||||
|
|
||||||
} //namespace duck
|
} //namespace duck
|
||||||
|
|
23
src/main.cpp
23
src/main.cpp
|
@ -29,18 +29,18 @@
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
void print_ping(oro::Api& oro_api) {
|
void print_ping(oro::Api& oro_api) {
|
||||||
auto ping = oro_api.ping();
|
auto ping = oro_api.ping(false);
|
||||||
|
|
||||||
std::cout << "date: " << ping.first.date << '\n';
|
std::cout << "date: " << ping.header.date << '\n';
|
||||||
std::cout << "rate limit: " << ping.first.rate_limit << '\n';
|
std::cout << "rate limit: " << ping.header.rate_limit << '\n';
|
||||||
std::cout << "remaining: " << ping.first.rate_limit_remaining << '\n';
|
std::cout << "remaining: " << ping.header.rate_limit_remaining << '\n';
|
||||||
std::cout << "reset: " << ping.first.rate_limit_reset << '\n';
|
std::cout << "reset: " << ping.header.rate_limit_reset << '\n';
|
||||||
std::cout << "retry after: " << ping.first.retry_after << '\n';
|
std::cout << "retry after: " << ping.header.retry_after << '\n';
|
||||||
std::cout << "server: " << ping.first.server << '\n';
|
std::cout << "server: " << ping.header.server << '\n';
|
||||||
std::cout << "-----\n";
|
std::cout << "-----\n";
|
||||||
std::cout << "timestamp: " << ping.second.generation_timestamp << '\n';
|
std::cout << "timestamp: " << ping.data.generation_timestamp << '\n';
|
||||||
std::cout << "answer: " << ping.second.message << '\n';
|
std::cout << "answer: " << ping.data.message << '\n';
|
||||||
std::cout << "version: " << ping.second.version << '\n';
|
std::cout << "version: " << ping.data.version << '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr auto app_version() {
|
constexpr auto app_version() {
|
||||||
|
@ -82,7 +82,8 @@ int main(int argc, char* argv[]) {
|
||||||
oro_api.get(),
|
oro_api.get(),
|
||||||
db.get(),
|
db.get(),
|
||||||
app_conf.fetch_extra_delay(),
|
app_conf.fetch_extra_delay(),
|
||||||
app_conf.worker_threads()
|
app_conf.worker_threads(),
|
||||||
|
app_conf.store_raw_json()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
#if defined(OROTOOL_WITH_RESTCCPP)
|
#if defined(OROTOOL_WITH_RESTCCPP)
|
||||||
|
|
|
@ -27,6 +27,7 @@ namespace nap {
|
||||||
struct HttpResponse {
|
struct HttpResponse {
|
||||||
std::unique_ptr<char[]> raw;
|
std::unique_ptr<char[]> raw;
|
||||||
std::vector<std::pair<std::string_view, std::string_view>> header_list;
|
std::vector<std::pair<std::string_view, std::string_view>> header_list;
|
||||||
|
std::string_view header;
|
||||||
std::string_view body;
|
std::string_view body;
|
||||||
std::string_view http_ver;
|
std::string_view http_ver;
|
||||||
std::string_view code_desc;
|
std::string_view code_desc;
|
||||||
|
|
|
@ -101,15 +101,14 @@ HttpResponse page_fetch (
|
||||||
HttpResponse resp;
|
HttpResponse resp;
|
||||||
resp.code = easy.get_info<CURLINFO_RESPONSE_CODE>().get();
|
resp.code = easy.get_info<CURLINFO_RESPONSE_CODE>().get();
|
||||||
|
|
||||||
std::string_view head;
|
|
||||||
{
|
{
|
||||||
auto [raw, head_tmp, body] = make_raw_string(header_oss, body_oss, body_padding);
|
auto [raw, head_tmp, body] = make_raw_string(header_oss, body_oss, body_padding);
|
||||||
head = head_tmp;
|
|
||||||
resp.raw = std::move(raw);
|
resp.raw = std::move(raw);
|
||||||
|
resp.header = head_tmp;
|
||||||
resp.body = body;
|
resp.body = body;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto parsed_header = header_parse(head);
|
auto parsed_header = header_parse(resp.header);
|
||||||
resp.header_list = std::move(parsed_header.fields);
|
resp.header_list = std::move(parsed_header.fields);
|
||||||
assert(resp.code == parsed_header.code);
|
assert(resp.code == parsed_header.code);
|
||||||
resp.http_ver = parsed_header.version;
|
resp.http_ver = parsed_header.version;
|
||||||
|
|
|
@ -61,6 +61,13 @@ struct Header {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct ApiOutput {
|
||||||
|
Header header;
|
||||||
|
T data;
|
||||||
|
std::string raw_response;
|
||||||
|
};
|
||||||
|
|
||||||
class Api {
|
class Api {
|
||||||
public:
|
public:
|
||||||
Api (
|
Api (
|
||||||
|
@ -71,12 +78,12 @@ public:
|
||||||
);
|
);
|
||||||
virtual ~Api() noexcept;
|
virtual ~Api() noexcept;
|
||||||
|
|
||||||
virtual std::pair<Header, Ping> ping() = 0;
|
virtual ApiOutput<Ping> ping(bool with_raw) = 0;
|
||||||
virtual std::pair<Header, WhoAmI> who_am_i() = 0;
|
virtual ApiOutput<WhoAmI> who_am_i(bool with_raw) = 0;
|
||||||
virtual std::pair<Header, Items> items_list() = 0;
|
virtual ApiOutput<Items> items_list(bool with_raw) = 0;
|
||||||
virtual std::pair<Header, Icons> items_icons() = 0;
|
virtual ApiOutput<Icons> items_icons(bool with_raw) = 0;
|
||||||
virtual std::pair<Header, Shops> market_list() = 0;
|
virtual ApiOutput<Shops> market_list(bool with_raw) = 0;
|
||||||
virtual std::pair<Header, Creators> fame_list() = 0;
|
virtual ApiOutput<Creators> fame_list(bool with_raw) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::string m_prefix;
|
std::string m_prefix;
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
namespace sjd = simdjson::dom;
|
namespace sjd = simdjson::dom;
|
||||||
namespace sj = simdjson;
|
namespace sj = simdjson;
|
||||||
|
@ -115,25 +116,27 @@ ApiNap::ApiNap (
|
||||||
|
|
||||||
ApiNap::~ApiNap() noexcept = default;
|
ApiNap::~ApiNap() noexcept = default;
|
||||||
|
|
||||||
std::pair<Header, Ping> ApiNap::ping() {
|
ApiOutput<Ping> ApiNap::ping(bool with_raw) {
|
||||||
return fetch_and_parse<Ping>(
|
return fetch_and_parse<Ping>(
|
||||||
g_endpoint_ping,
|
g_endpoint_ping,
|
||||||
[](const simdjson::dom::element& doc, Ping& out) {
|
[](const simdjson::dom::element& doc, Ping& out) {
|
||||||
out.message = doc["message"];
|
out.message = doc["message"];
|
||||||
}
|
},
|
||||||
|
with_raw
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<Header, WhoAmI> ApiNap::who_am_i() {
|
ApiOutput<WhoAmI> ApiNap::who_am_i(bool with_raw) {
|
||||||
return fetch_and_parse<WhoAmI>(
|
return fetch_and_parse<WhoAmI>(
|
||||||
g_endpoint_whoami,
|
g_endpoint_whoami,
|
||||||
[](const simdjson::dom::element& doc, WhoAmI& out) {
|
[](const simdjson::dom::element& doc, WhoAmI& out) {
|
||||||
out.master_id = static_cast<unsigned int>(doc["master_id"].get_uint64());
|
out.master_id = static_cast<unsigned int>(doc["master_id"].get_uint64());
|
||||||
}
|
},
|
||||||
|
with_raw
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<Header, Items> ApiNap::items_list() {
|
ApiOutput<Items> ApiNap::items_list(bool with_raw) {
|
||||||
return fetch_and_parse<Items>(
|
return fetch_and_parse<Items>(
|
||||||
g_endpoint_items_list,
|
g_endpoint_items_list,
|
||||||
[](const simdjson::dom::element& doc, Items& out) {
|
[](const simdjson::dom::element& doc, Items& out) {
|
||||||
|
@ -150,11 +153,12 @@ std::pair<Header, Items> ApiNap::items_list() {
|
||||||
new_entry.slots = get_optional<unsigned int, uint64_t>(item["slots"]);
|
new_entry.slots = get_optional<unsigned int, uint64_t>(item["slots"]);
|
||||||
out.items.push_back(std::move(new_entry));
|
out.items.push_back(std::move(new_entry));
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
with_raw
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<Header, Icons> ApiNap::items_icons() {
|
ApiOutput<Icons> ApiNap::items_icons(bool with_raw) {
|
||||||
return fetch_and_parse<Icons>(
|
return fetch_and_parse<Icons>(
|
||||||
g_endpoint_items_icons,
|
g_endpoint_items_icons,
|
||||||
[](const simdjson::dom::element& doc, Icons& out) {
|
[](const simdjson::dom::element& doc, Icons& out) {
|
||||||
|
@ -166,11 +170,12 @@ std::pair<Header, Icons> ApiNap::items_icons() {
|
||||||
new_entry.icon = icon["icon"];
|
new_entry.icon = icon["icon"];
|
||||||
out.icons.push_back(std::move(new_entry));
|
out.icons.push_back(std::move(new_entry));
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
with_raw
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<Header, Shops> ApiNap::market_list() {
|
ApiOutput<Shops> ApiNap::market_list(bool with_raw) {
|
||||||
return fetch_and_parse<Shops>(
|
return fetch_and_parse<Shops>(
|
||||||
g_endpoint_market_list,
|
g_endpoint_market_list,
|
||||||
[](const simdjson::dom::element& doc, Shops& out) {
|
[](const simdjson::dom::element& doc, Shops& out) {
|
||||||
|
@ -216,22 +221,24 @@ std::pair<Header, Shops> ApiNap::market_list() {
|
||||||
}
|
}
|
||||||
out.shops.push_back(std::move(new_shop));
|
out.shops.push_back(std::move(new_shop));
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
with_raw
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<Header, Creators> ApiNap::fame_list() {
|
ApiOutput<Creators> ApiNap::fame_list(bool with_raw) {
|
||||||
return fetch_and_parse<Creators>(
|
return fetch_and_parse<Creators>(
|
||||||
g_endpoint_fame_list,
|
g_endpoint_fame_list,
|
||||||
[](const simdjson::dom::element& doc, Creators& out) {
|
[](const simdjson::dom::element& doc, Creators& out) {
|
||||||
fill_creator_list(doc["brewers"], out.brewers);
|
fill_creator_list(doc["brewers"], out.brewers);
|
||||||
fill_creator_list(doc["forgers"], out.brewers);
|
fill_creator_list(doc["forgers"], out.brewers);
|
||||||
}
|
},
|
||||||
|
with_raw
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename F>
|
template <typename T, typename F>
|
||||||
std::pair<Header, T> ApiNap::fetch_and_parse (const char* endpoint, F&& data_fill) {
|
ApiOutput<T> ApiNap::fetch_and_parse (const char* endpoint, F&& data_fill, bool with_raw) {
|
||||||
auto resp = m_qrest.fetch(m_prefix + endpoint);
|
auto resp = m_qrest.fetch(m_prefix + endpoint);
|
||||||
|
|
||||||
if (200 != resp.code)
|
if (200 != resp.code)
|
||||||
|
@ -249,7 +256,16 @@ std::pair<Header, T> ApiNap::fetch_and_parse (const char* endpoint, F&& data_fil
|
||||||
data_fill(doc, dataret);
|
data_fill(doc, dataret);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {to_header(resp), std::move(dataret)};
|
std::string raw_resp;
|
||||||
|
if (with_raw) {
|
||||||
|
assert(not resp.header.empty() and resp.header[resp.header.size() - 1] == '\n');
|
||||||
|
raw_resp.reserve(resp.header.size() + 1 + resp.body.size());
|
||||||
|
raw_resp.append(resp.header);
|
||||||
|
raw_resp.append("\n");
|
||||||
|
raw_resp.append(resp.body);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {to_header(resp), std::move(dataret), std::move(raw_resp)};
|
||||||
}
|
}
|
||||||
|
|
||||||
} //namespace oro
|
} //namespace oro
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
#include "datatypes.hpp"
|
#include "datatypes.hpp"
|
||||||
#include "oro/dboperation.hpp"
|
#include "oro/dboperation.hpp"
|
||||||
#include <string_view>
|
#include "oro/source.hpp"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
namespace oro {
|
namespace oro {
|
||||||
|
@ -34,10 +34,10 @@ public:
|
||||||
OriginsDB() = default;
|
OriginsDB() = default;
|
||||||
virtual ~OriginsDB() noexcept = default;
|
virtual ~OriginsDB() noexcept = default;
|
||||||
|
|
||||||
virtual void update (const Items& items, const oro::Timestamp& next_update) = 0;
|
virtual void update (const Items& items, const oro::Timestamp& next_update, const Source& source) = 0;
|
||||||
virtual void update (const Icons& icons, const oro::Timestamp& next_update) = 0;
|
virtual void update (const Icons& icons, const oro::Timestamp& next_update, const Source& source) = 0;
|
||||||
virtual void update (const Shops& shops, const oro::Timestamp& next_update) = 0;
|
virtual void update (const Shops& shops, const oro::Timestamp& next_update, const Source& source) = 0;
|
||||||
virtual void update (const Creators& creat, const oro::Timestamp& next_update) = 0;
|
virtual void update (const Creators& creat, const oro::Timestamp& next_update, const Source& source) = 0;
|
||||||
|
|
||||||
virtual Timestamp next_access_time (DBOperation op) const = 0;
|
virtual Timestamp next_access_time (DBOperation op) const = 0;
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
#include "oro/api.hpp"
|
#include "oro/api.hpp"
|
||||||
#include "nap/quick_rest.hpp"
|
#include "nap/quick_rest.hpp"
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
namespace oro {
|
namespace oro {
|
||||||
|
|
||||||
|
@ -35,16 +34,16 @@ public:
|
||||||
|
|
||||||
virtual ~ApiNap() noexcept;
|
virtual ~ApiNap() noexcept;
|
||||||
|
|
||||||
virtual std::pair<Header, Ping> ping() override;
|
virtual ApiOutput<Ping> ping(bool with_raw) override;
|
||||||
virtual std::pair<Header, WhoAmI> who_am_i() override;
|
virtual ApiOutput<WhoAmI> who_am_i(bool with_raw) override;
|
||||||
virtual std::pair<Header, Items> items_list() override;
|
virtual ApiOutput<Items> items_list(bool with_raw) override;
|
||||||
virtual std::pair<Header, Icons> items_icons() override;
|
virtual ApiOutput<Icons> items_icons(bool with_raw) override;
|
||||||
virtual std::pair<Header, Shops> market_list() override;
|
virtual ApiOutput<Shops> market_list(bool with_raw) override;
|
||||||
virtual std::pair<Header, Creators> fame_list() override;
|
virtual ApiOutput<Creators> fame_list(bool with_raw) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <typename T, typename F>
|
template <typename T, typename F>
|
||||||
std::pair<Header, T> fetch_and_parse (const char* endpoint, F&& data_fill);
|
ApiOutput<T> fetch_and_parse (const char* endpoint, F&& data_fill, bool with_raw);
|
||||||
|
|
||||||
std::mutex m_json_mutex;
|
std::mutex m_json_mutex;
|
||||||
simdjson::dom::parser m_json;
|
simdjson::dom::parser m_json;
|
||||||
|
|
|
@ -52,6 +52,7 @@ namespace {
|
||||||
", master_id INTEGER UNIQUE"
|
", master_id INTEGER UNIQUE"
|
||||||
", name TEXT"
|
", name TEXT"
|
||||||
", points INTEGER"
|
", points INTEGER"
|
||||||
|
", source_id INTEGER NOT NULL"
|
||||||
")";
|
")";
|
||||||
constexpr const char g_create_slotted_cards[] =
|
constexpr const char g_create_slotted_cards[] =
|
||||||
"CREATE TABLE IF NOT EXISTS slotted_cards("
|
"CREATE TABLE IF NOT EXISTS slotted_cards("
|
||||||
|
@ -83,6 +84,7 @@ namespace {
|
||||||
", hash TEXT NOT NULL"
|
", hash TEXT NOT NULL"
|
||||||
", discovery_date TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP"
|
", discovery_date TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP"
|
||||||
", last_seen_date TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP"
|
", last_seen_date TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP"
|
||||||
|
", source_id INTEGER NOT NULL"
|
||||||
", FOREIGN KEY(shop_id) REFERENCES shops(id)"
|
", FOREIGN KEY(shop_id) REFERENCES shops(id)"
|
||||||
")";
|
")";
|
||||||
constexpr const char g_create_shops[] =
|
constexpr const char g_create_shops[] =
|
||||||
|
@ -108,6 +110,7 @@ namespace {
|
||||||
", npc_price INTEGER"
|
", npc_price INTEGER"
|
||||||
", slots TINYINT"
|
", slots TINYINT"
|
||||||
", removal_date TEXT"
|
", removal_date TEXT"
|
||||||
|
", source_id INTEGER NOT NULL"
|
||||||
")";
|
")";
|
||||||
constexpr const char g_create_icons_a[] = "CREATE TABLE IF NOT EXISTS ";
|
constexpr const char g_create_icons_a[] = "CREATE TABLE IF NOT EXISTS ";
|
||||||
constexpr const char g_create_icons_b[] =
|
constexpr const char g_create_icons_b[] =
|
||||||
|
@ -115,6 +118,7 @@ namespace {
|
||||||
"id INTEGER PRIMARY KEY NOT NULL"
|
"id INTEGER PRIMARY KEY NOT NULL"
|
||||||
", item_id INTEGER NOT NULL"
|
", item_id INTEGER NOT NULL"
|
||||||
", icon TEXT"
|
", icon TEXT"
|
||||||
|
", source_id INTEGER NOT NULL"
|
||||||
", FOREIGN KEY(item_id) REFERENCES items(id)"
|
", FOREIGN KEY(item_id) REFERENCES items(id)"
|
||||||
")";
|
")";
|
||||||
constexpr const char g_create_access[] =
|
constexpr const char g_create_access[] =
|
||||||
|
@ -123,6 +127,12 @@ namespace {
|
||||||
", operation TINYINT PRIMARY KEY NOT NULL"
|
", operation TINYINT PRIMARY KEY NOT NULL"
|
||||||
", next_update INTEGER NOT NULL DEFAULT '1970-01-01 00:00:00'"
|
", next_update INTEGER NOT NULL DEFAULT '1970-01-01 00:00:00'"
|
||||||
")";
|
")";
|
||||||
|
constexpr const char g_create_source_store[] =
|
||||||
|
"CREATE TABLE IF NOT EXISTS source_store("
|
||||||
|
"id INTEGER PRIMARY KEY NOT NULL"
|
||||||
|
", source TEXT"
|
||||||
|
", format TEXT"
|
||||||
|
")";
|
||||||
|
|
||||||
std::string to_string (int num) {
|
std::string to_string (int num) {
|
||||||
auto ary = dhandy::int_to_ary<int>(num);
|
auto ary = dhandy::int_to_ary<int>(num);
|
||||||
|
@ -322,6 +332,17 @@ namespace {
|
||||||
|
|
||||||
return (prefix + values + suffix);
|
return (prefix + values + suffix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SQLiteID insert_source_ifn (SQLite::Database& db, const Source& source) {
|
||||||
|
if (not source.data)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
db.exec(g_create_source_store);
|
||||||
|
SQLite::Statement query(db, "INSERT INTO source_store(source, format) VALUES(?, ?)");
|
||||||
|
bind_all(query, no_copy(*source.data), static_cast<int>(source.format));
|
||||||
|
query.exec();
|
||||||
|
return db.getLastInsertRowid();
|
||||||
|
}
|
||||||
} //unnamed namespace
|
} //unnamed namespace
|
||||||
|
|
||||||
OriginsDBSQLite::OriginsDBSQLite (std::string_view path) :
|
OriginsDBSQLite::OriginsDBSQLite (std::string_view path) :
|
||||||
|
@ -336,7 +357,7 @@ OriginsDBSQLite::OriginsDBSQLite (std::string_view path) :
|
||||||
|
|
||||||
OriginsDBSQLite::~OriginsDBSQLite() noexcept = default;
|
OriginsDBSQLite::~OriginsDBSQLite() noexcept = default;
|
||||||
|
|
||||||
void OriginsDBSQLite::update (const Items& items, const oro::Timestamp& next_update) {
|
void OriginsDBSQLite::update (const Items& items, const oro::Timestamp& next_update, const Source& source) {
|
||||||
auto& db = *m_db;
|
auto& db = *m_db;
|
||||||
std::unique_lock<std::mutex> lock(m_db_mutex);
|
std::unique_lock<std::mutex> lock(m_db_mutex);
|
||||||
update_last_access(db, DBOperation::Items, next_update);
|
update_last_access(db, DBOperation::Items, next_update);
|
||||||
|
@ -360,14 +381,16 @@ void OriginsDBSQLite::update (const Items& items, const oro::Timestamp& next_upd
|
||||||
|
|
||||||
SQLite::Statement query(db,
|
SQLite::Statement query(db,
|
||||||
"INSERT INTO items_staging "
|
"INSERT INTO items_staging "
|
||||||
"(item_id, unique_name, name, type, subtype, npc_price, slots) "
|
"(item_id, unique_name, name, type, subtype, npc_price, slots, source_id) "
|
||||||
"VALUES(?1, ?2, ?3, ?4, ?5, ?6, ?7)"
|
"VALUES(?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8)"
|
||||||
);
|
);
|
||||||
SQLite::Transaction transaction(db);
|
SQLite::Transaction transaction(db);
|
||||||
|
const SQLiteID source_id = insert_source_ifn(db, source);
|
||||||
for (const auto& item : items.items) {
|
for (const auto& item : items.items) {
|
||||||
bind_all(query, item.item_id, no_copy(item.unique_name),
|
bind_all(query, item.item_id, no_copy(item.unique_name),
|
||||||
no_copy(item.name), static_cast<int>(item.type.value),
|
no_copy(item.name), static_cast<int>(item.type.value),
|
||||||
cast<int>(item.subtype), item.npc_price, item.slots
|
cast<int>(item.subtype), item.npc_price, item.slots,
|
||||||
|
source_id
|
||||||
);
|
);
|
||||||
|
|
||||||
query.exec();
|
query.exec();
|
||||||
|
@ -384,19 +407,19 @@ void OriginsDBSQLite::update (const Items& items, const oro::Timestamp& next_upd
|
||||||
")"
|
")"
|
||||||
);
|
);
|
||||||
db.exec(
|
db.exec(
|
||||||
"INSERT INTO items (item_id, unique_name, name, type, subtype, npc_price, slots) "
|
"INSERT INTO items (item_id, unique_name, name, type, subtype, npc_price, slots, source_id) "
|
||||||
"SELECT item_id, unique_name, name, type, subtype, npc_price, slots FROM items_staging WHERE true "
|
"SELECT item_id, unique_name, name, type, subtype, npc_price, slots, source_id FROM items_staging WHERE true "
|
||||||
"ON CONFLICT(item_id, ifnull(removal_date, 0)) DO UPDATE SET "
|
"ON CONFLICT(item_id, ifnull(removal_date, 0)) DO UPDATE SET "
|
||||||
"unique_name=excluded.unique_name, "
|
"unique_name=excluded.unique_name, "
|
||||||
"name=excluded.name, type=excluded.type, subtype=excluded.subtype, "
|
"name=excluded.name, type=excluded.type, subtype=excluded.subtype, "
|
||||||
"npc_price=excluded.npc_price, slots=excluded.slots"
|
"npc_price=excluded.npc_price, slots=excluded.slots, source_id=excluded.source_id"
|
||||||
);
|
);
|
||||||
db.exec("DROP TABLE items_staging");
|
db.exec("DROP TABLE items_staging");
|
||||||
|
|
||||||
transaction.commit();
|
transaction.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OriginsDBSQLite::update (const Icons& icons, const oro::Timestamp& next_update) {
|
void OriginsDBSQLite::update (const Icons& icons, const oro::Timestamp& next_update, const Source& source) {
|
||||||
//example:
|
//example:
|
||||||
//{
|
//{
|
||||||
// "item_id":501,
|
// "item_id":501,
|
||||||
|
@ -411,33 +434,34 @@ void OriginsDBSQLite::update (const Icons& icons, const oro::Timestamp& next_upd
|
||||||
db.exec(std::string(g_create_icons_a).append("icons") + g_create_icons_b);
|
db.exec(std::string(g_create_icons_a).append("icons") + g_create_icons_b);
|
||||||
db.exec("CREATE UNIQUE INDEX IF NOT EXISTS icons_item_id_idx ON icons(item_id)");
|
db.exec("CREATE UNIQUE INDEX IF NOT EXISTS icons_item_id_idx ON icons(item_id)");
|
||||||
SQLite::Statement ins_empty_item(db, "INSERT OR IGNORE INTO items(item_id) VALUES(?)");
|
SQLite::Statement ins_empty_item(db, "INSERT OR IGNORE INTO items(item_id) VALUES(?)");
|
||||||
SQLite::Statement query(db, "INSERT INTO icons_staging(item_id, icon) VALUES(?, ?)");
|
SQLite::Statement query(db, "INSERT INTO icons_staging(item_id, icon, source_id) VALUES(?, ?, ?)");
|
||||||
|
|
||||||
ItemIdToTableId item_id_to_table_id(db, false);
|
ItemIdToTableId item_id_to_table_id(db, false);
|
||||||
SQLite::Transaction transaction(db);
|
SQLite::Transaction transaction(db);
|
||||||
|
const SQLiteID source_id = insert_source_ifn(db, source);
|
||||||
for (const auto& ico : icons.icons) {
|
for (const auto& ico : icons.icons) {
|
||||||
bind_all(ins_empty_item, ico.item_id);
|
bind_all(ins_empty_item, ico.item_id);
|
||||||
ins_empty_item.exec();
|
ins_empty_item.exec();
|
||||||
ins_empty_item.reset();
|
ins_empty_item.reset();
|
||||||
|
|
||||||
bind_all(query, item_id_to_table_id(ico.item_id), no_copy(ico.icon));
|
bind_all(query, item_id_to_table_id(ico.item_id), no_copy(ico.icon), source_id);
|
||||||
query.exec();
|
query.exec();
|
||||||
query.reset();
|
query.reset();
|
||||||
|
|
||||||
//base64_decode(std::string_view(ico.icon).substr(std::string_view("data:image/png;base64,").size()));
|
//base64_decode(std::string_view(ico.icon).substr(std::string_view("data:image/png;base64,").size()));
|
||||||
}
|
}
|
||||||
db.exec(
|
db.exec(
|
||||||
"INSERT INTO icons (item_id, icon) "
|
"INSERT INTO icons (item_id, icon, source_id) "
|
||||||
"SELECT item_id, icon FROM icons_staging WHERE true "
|
"SELECT item_id, icon, source_id FROM icons_staging WHERE true "
|
||||||
"ON CONFLICT(item_id) DO UPDATE SET "
|
"ON CONFLICT(item_id) DO UPDATE SET "
|
||||||
"icon=excluded.icon"
|
"icon=excluded.icon, source_id=excluded.source_id"
|
||||||
);
|
);
|
||||||
db.exec("DROP TABLE icons_staging");
|
db.exec("DROP TABLE icons_staging");
|
||||||
|
|
||||||
transaction.commit();
|
transaction.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OriginsDBSQLite::update (const Shops& shops, const oro::Timestamp& next_update) {
|
void OriginsDBSQLite::update (const Shops& shops, const oro::Timestamp& next_update, const Source& source) {
|
||||||
//example:
|
//example:
|
||||||
//{
|
//{
|
||||||
// "title":"• B\u003ePoison Bottle •",
|
// "title":"• B\u003ePoison Bottle •",
|
||||||
|
@ -463,7 +487,7 @@ void OriginsDBSQLite::update (const Shops& shops, const oro::Timestamp& next_upd
|
||||||
db.exec(g_create_shop_items);
|
db.exec(g_create_shop_items);
|
||||||
db.exec(g_create_slotted_cards);
|
db.exec(g_create_slotted_cards);
|
||||||
|
|
||||||
SQLite::Statement ins_sshot(db, "INSERT OR IGNORE INTO shop_snapshots(shop_id, hash) VALUES(?, ?)");
|
SQLite::Statement ins_sshot(db, "INSERT OR IGNORE INTO shop_snapshots(shop_id, hash, source_id) VALUES(?, ?, ?)");
|
||||||
SQLite::Statement ins_empty_item(db, "INSERT OR IGNORE INTO items(item_id) VALUES(?)");
|
SQLite::Statement ins_empty_item(db, "INSERT OR IGNORE INTO items(item_id) VALUES(?)");
|
||||||
SQLite::Statement sel_sshot(db, "SELECT id FROM shop_snapshots WHERE shop_id = ? AND hash = ?");
|
SQLite::Statement sel_sshot(db, "SELECT id FROM shop_snapshots WHERE shop_id = ? AND hash = ?");
|
||||||
SQLite::Statement ins_item(db, "INSERT INTO shop_items(snapshot_id, item_id, amount, price, refine, star_crumbs, element, creator, beloved) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
SQLite::Statement ins_item(db, "INSERT INTO shop_items(snapshot_id, item_id, amount, price, refine, star_crumbs, element, creator, beloved) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
||||||
|
@ -473,6 +497,7 @@ void OriginsDBSQLite::update (const Shops& shops, const oro::Timestamp& next_upd
|
||||||
InsertShopIfn insert_shop_ifn(db);
|
InsertShopIfn insert_shop_ifn(db);
|
||||||
ItemIdToTableId item_id_to_table_id(db);
|
ItemIdToTableId item_id_to_table_id(db);
|
||||||
SQLite::Transaction transaction(db);
|
SQLite::Transaction transaction(db);
|
||||||
|
const SQLiteID source_id = insert_source_ifn(db, source);
|
||||||
for (const auto& shop : shops.shops) {
|
for (const auto& shop : shops.shops) {
|
||||||
{
|
{
|
||||||
//insert new shop or get its id if already there
|
//insert new shop or get its id if already there
|
||||||
|
@ -490,7 +515,7 @@ void OriginsDBSQLite::update (const Shops& shops, const oro::Timestamp& next_upd
|
||||||
}
|
}
|
||||||
|
|
||||||
//snapshot is new, insert it
|
//snapshot is new, insert it
|
||||||
bind_all(ins_sshot, shop_id_ins.first, no_copy(hash));
|
bind_all(ins_sshot, shop_id_ins.first, no_copy(hash), source_id);
|
||||||
ins_sshot.exec();
|
ins_sshot.exec();
|
||||||
ins_sshot.reset();
|
ins_sshot.reset();
|
||||||
}
|
}
|
||||||
|
@ -520,26 +545,27 @@ void OriginsDBSQLite::update (const Shops& shops, const oro::Timestamp& next_upd
|
||||||
transaction.commit();
|
transaction.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OriginsDBSQLite::update (const Creators& creat, const oro::Timestamp& next_update) {
|
void OriginsDBSQLite::update (const Creators& creat, const oro::Timestamp& next_update, const Source& source) {
|
||||||
std::unique_lock<std::mutex> lock(m_db_mutex);
|
std::unique_lock<std::mutex> lock(m_db_mutex);
|
||||||
auto& db = *m_db;
|
auto& db = *m_db;
|
||||||
update_last_access(db, DBOperation::Creators, next_update);
|
update_last_access(db, DBOperation::Creators, next_update);
|
||||||
|
|
||||||
db.exec(g_create_fame_list);
|
db.exec(g_create_fame_list);
|
||||||
|
|
||||||
auto insert_creators = [](SQLite::Statement& query, const std::vector<oro::Creator>& creats, int type) {
|
auto insert_creators = [](SQLite::Statement& query, const std::vector<oro::Creator>& creats, int type, SQLiteID source_id) {
|
||||||
for (const auto& creator : creats) {
|
for (const auto& creator : creats) {
|
||||||
bind_all(query, type, creator.char_id, no_copy(creator.name), creator.points);
|
bind_all(query, type, creator.char_id, no_copy(creator.name), creator.points, source_id);
|
||||||
query.exec();
|
query.exec();
|
||||||
query.reset();
|
query.reset();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
SQLite::Statement query(db, "INSERT INTO fame_list(type, master_id, name, points) VALUES (?, ?, ?, ?) ON CONFLICT(master_id) DO UPDATE SET points=excluded.points");
|
SQLite::Statement query(db, "INSERT INTO fame_list(type, master_id, name, points, source_id) VALUES (?, ?, ?, ?, ?) ON CONFLICT(master_id) DO UPDATE SET points=excluded.points");
|
||||||
|
|
||||||
SQLite::Transaction transaction(db);
|
SQLite::Transaction transaction(db);
|
||||||
insert_creators(query, creat.brewers, 1);
|
const SQLiteID source_id = insert_source_ifn(db, source);
|
||||||
insert_creators(query, creat.forgers, 2);
|
insert_creators(query, creat.brewers, 1, source_id);
|
||||||
|
insert_creators(query, creat.forgers, 2, source_id);
|
||||||
transaction.commit();
|
transaction.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,10 +34,10 @@ public:
|
||||||
explicit OriginsDBSQLite(std::string_view path);
|
explicit OriginsDBSQLite(std::string_view path);
|
||||||
virtual ~OriginsDBSQLite() noexcept;
|
virtual ~OriginsDBSQLite() noexcept;
|
||||||
|
|
||||||
void update (const Items& items, const oro::Timestamp& next_update) override;
|
void update (const Items& items, const oro::Timestamp& next_update, const Source& source) override;
|
||||||
void update (const Icons& icons, const oro::Timestamp& next_update) override;
|
void update (const Icons& icons, const oro::Timestamp& next_update, const Source& source) override;
|
||||||
void update (const Shops& shops, const oro::Timestamp& next_update) override;
|
void update (const Shops& shops, const oro::Timestamp& next_update, const Source& source) override;
|
||||||
void update (const Creators& creat, const oro::Timestamp& next_update) override;
|
void update (const Creators& creat, const oro::Timestamp& next_update, const Source& source) override;
|
||||||
|
|
||||||
Timestamp next_access_time (DBOperation op) const override;
|
Timestamp next_access_time (DBOperation op) const override;
|
||||||
|
|
||||||
|
|
38
src/oro/source.hpp
Normal file
38
src/oro/source.hpp
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
/* Copyright 2020, Michele Santullo
|
||||||
|
* This file is part of orotool.
|
||||||
|
*
|
||||||
|
* Orotool is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Orotool is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Orotool. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
namespace oro {
|
||||||
|
|
||||||
|
//The raw json source data complete with http response header. It can be
|
||||||
|
//anything really, but it's intended to be stored in the DB. Entries in the
|
||||||
|
//other tables will have a reference to the source.
|
||||||
|
|
||||||
|
enum class SourceFormat {
|
||||||
|
Plain
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Source {
|
||||||
|
std::optional<std::string> data;
|
||||||
|
SourceFormat format;
|
||||||
|
};
|
||||||
|
|
||||||
|
} //namespace oro
|
|
@ -64,14 +64,15 @@ TimerBase::TimerBase (
|
||||||
m_extra_delay(settings.extra_delay),
|
m_extra_delay(settings.extra_delay),
|
||||||
m_pool(pool),
|
m_pool(pool),
|
||||||
m_oro_api(oro_api),
|
m_oro_api(oro_api),
|
||||||
m_db(db)
|
m_db(db),
|
||||||
|
m_store_raw_response(settings.store_raw_json)
|
||||||
{
|
{
|
||||||
assert(m_pool);
|
assert(m_pool);
|
||||||
assert(m_oro_api);
|
assert(m_oro_api);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimerBase::on_timer() {
|
void TimerBase::on_timer() {
|
||||||
m_pool->submit(&TimerBase::fetch_data, this);
|
m_pool->submit(&TimerBase::fetch_data, this, m_store_raw_response);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimerBase::set_next_timer (const oro::Header& header) {
|
void TimerBase::set_next_timer (const oro::Header& header) {
|
||||||
|
@ -95,20 +96,20 @@ oro::OriginsDB& TimerBase::db() {
|
||||||
return *m_db;
|
return *m_db;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimerBase::update_db (const oro::Shops& shops, const oro::Header& header) {
|
void TimerBase::update_db (const oro::Shops& shops, const oro::Header& header, const oro::Source& source) {
|
||||||
db().update(shops, calc_next_update(header, m_extra_delay));
|
db().update(shops, calc_next_update(header, m_extra_delay), source);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimerBase::update_db (const oro::Items& items, const oro::Header& header) {
|
void TimerBase::update_db (const oro::Items& items, const oro::Header& header, const oro::Source& source) {
|
||||||
db().update(items, calc_next_update(header, m_extra_delay));
|
db().update(items, calc_next_update(header, m_extra_delay), source);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimerBase::update_db (const oro::Icons& icons, const oro::Header& header) {
|
void TimerBase::update_db (const oro::Icons& icons, const oro::Header& header, const oro::Source& source) {
|
||||||
db().update(icons, calc_next_update(header, m_extra_delay));
|
db().update(icons, calc_next_update(header, m_extra_delay), source);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimerBase::update_db (const oro::Creators& creators, const oro::Header& header) {
|
void TimerBase::update_db (const oro::Creators& creators, const oro::Header& header, const oro::Source& source) {
|
||||||
db().update(creators, calc_next_update(header, m_extra_delay));
|
db().update(creators, calc_next_update(header, m_extra_delay), source);
|
||||||
}
|
}
|
||||||
|
|
||||||
} //namespace duck
|
} //namespace duck
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "eventia/private/context.hpp"
|
#include "eventia/private/context.hpp"
|
||||||
#include "eventia/timer.hpp"
|
#include "eventia/timer.hpp"
|
||||||
#include "oro/dboperation.hpp"
|
#include "oro/dboperation.hpp"
|
||||||
|
#include "oro/source.hpp"
|
||||||
|
|
||||||
namespace roar11 {
|
namespace roar11 {
|
||||||
class ThreadPool;
|
class ThreadPool;
|
||||||
|
@ -38,13 +39,15 @@ namespace oro {
|
||||||
namespace duck {
|
namespace duck {
|
||||||
|
|
||||||
struct TimerSettings {
|
struct TimerSettings {
|
||||||
TimerSettings (double min_wait, double extra_delay) :
|
TimerSettings (double min_wait, double extra_delay, bool with_raw_json) :
|
||||||
min_wait(min_wait),
|
min_wait(min_wait),
|
||||||
extra_delay(extra_delay)
|
extra_delay(extra_delay),
|
||||||
|
store_raw_json(with_raw_json)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
double min_wait;
|
double min_wait;
|
||||||
double extra_delay;
|
double extra_delay;
|
||||||
|
bool store_raw_json;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TimerBase : public eve::Timer {
|
class TimerBase : public eve::Timer {
|
||||||
|
@ -63,21 +66,22 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void set_next_timer (const oro::Header& header);
|
void set_next_timer (const oro::Header& header);
|
||||||
void update_db (const oro::Shops& shops, const oro::Header& header);
|
void update_db (const oro::Shops& shops, const oro::Header& header, const oro::Source& source);
|
||||||
void update_db (const oro::Items& items, const oro::Header& header);
|
void update_db (const oro::Items& items, const oro::Header& header, const oro::Source& source);
|
||||||
void update_db (const oro::Icons& icons, const oro::Header& header);
|
void update_db (const oro::Icons& icons, const oro::Header& header, const oro::Source& source);
|
||||||
void update_db (const oro::Creators& creators, const oro::Header& header);
|
void update_db (const oro::Creators& creators, const oro::Header& header, const oro::Source& source);
|
||||||
roar11::ThreadPool& pool();
|
roar11::ThreadPool& pool();
|
||||||
oro::Api& oro_api();
|
oro::Api& oro_api();
|
||||||
oro::OriginsDB& db();
|
oro::OriginsDB& db();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void fetch_data() = 0;
|
virtual void fetch_data(bool with_raw) = 0;
|
||||||
|
|
||||||
double m_extra_delay;
|
double m_extra_delay;
|
||||||
roar11::ThreadPool* m_pool;
|
roar11::ThreadPool* m_pool;
|
||||||
oro::Api* m_oro_api;
|
oro::Api* m_oro_api;
|
||||||
oro::OriginsDB* m_db;
|
oro::OriginsDB* m_db;
|
||||||
|
bool m_store_raw_response;
|
||||||
};
|
};
|
||||||
|
|
||||||
} //namespace duck
|
} //namespace duck
|
||||||
|
|
|
@ -28,26 +28,26 @@
|
||||||
namespace duck {
|
namespace duck {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
template <oro::DBOperation Op> auto invoke_api_func (oro::Api& api);
|
template <oro::DBOperation Op> auto invoke_api_func (oro::Api& api, bool with_raw);
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline auto invoke_api_func<oro::DBOperation::Icons> (oro::Api& api) {
|
inline auto invoke_api_func<oro::DBOperation::Icons> (oro::Api& api, bool with_raw) {
|
||||||
return api.items_icons();
|
return api.items_icons(with_raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline auto invoke_api_func<oro::DBOperation::Items> (oro::Api& api) {
|
inline auto invoke_api_func<oro::DBOperation::Items> (oro::Api& api, bool with_raw) {
|
||||||
return api.items_list();
|
return api.items_list(with_raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline auto invoke_api_func<oro::DBOperation::Creators> (oro::Api& api) {
|
inline auto invoke_api_func<oro::DBOperation::Creators> (oro::Api& api, bool with_raw) {
|
||||||
return api.fame_list();
|
return api.fame_list(with_raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline auto invoke_api_func<oro::DBOperation::Shops> (oro::Api& api) {
|
inline auto invoke_api_func<oro::DBOperation::Shops> (oro::Api& api, bool with_raw) {
|
||||||
return api.market_list();
|
return api.market_list(with_raw);
|
||||||
}
|
}
|
||||||
} //unnamed namespace
|
} //unnamed namespace
|
||||||
|
|
||||||
|
@ -64,12 +64,18 @@ inline TimerOroApi<Op>::TimerOroApi (
|
||||||
}
|
}
|
||||||
|
|
||||||
template<oro::DBOperation Op>
|
template<oro::DBOperation Op>
|
||||||
inline void TimerOroApi<Op>::fetch_data() {
|
inline void TimerOroApi<Op>::fetch_data (bool with_raw) {
|
||||||
int status_code = 200;
|
int status_code = 200;
|
||||||
try {
|
try {
|
||||||
auto results = invoke_api_func<Op>(oro_api());
|
auto results = invoke_api_func<Op>(oro_api(), with_raw);
|
||||||
set_next_timer(results.first);
|
set_next_timer(results.header);
|
||||||
this->update_db(results.second, results.first);
|
|
||||||
|
oro::Source raw_src;
|
||||||
|
if (with_raw) {
|
||||||
|
raw_src.data = std::move(results.raw_response);
|
||||||
|
raw_src.format = oro::SourceFormat::Plain;
|
||||||
|
}
|
||||||
|
this->update_db(results.data, results.header, raw_src);
|
||||||
}
|
}
|
||||||
#if defined(OROTOOL_WITH_RESTCCPP)
|
#if defined(OROTOOL_WITH_RESTCCPP)
|
||||||
catch (const restc_cpp::RequestFailedWithErrorException& err) {
|
catch (const restc_cpp::RequestFailedWithErrorException& err) {
|
||||||
|
|
|
@ -38,7 +38,7 @@ public:
|
||||||
);
|
);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void fetch_data() override;
|
virtual void fetch_data (bool with_raw) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} //namespace duck
|
} //namespace duck
|
||||||
|
|
Loading…
Add table
Reference in a new issue