Store items and icons into the db

This commit is contained in:
King_DuckZ 2020-08-10 02:34:09 +01:00
parent f2b8abf82b
commit 6b9502ea3e
12 changed files with 219 additions and 9 deletions

View file

@ -1 +1,2 @@
option('base_url', type: 'string', value: 'https://api.originsro.org')
option('database_file', type: 'string', value: 'originsro.db3')

View file

@ -3,5 +3,6 @@
namespace duck {
constexpr const char g_base_url[] = "@BASE_URL@";
constexpr const char g_database[] = "@DATABASE@";
} //namespace duck

View file

@ -1,7 +1,7 @@
#include "evloop.hpp"
#include "timer_items.hpp"
#include "timer_icons.hpp"
#include "eventia/eventia.hpp"
#include "eventia/timer.hpp"
#include "roar11/ThreadPool.hpp"
#include "oro/api.hpp"
#include <iostream>
@ -27,14 +27,15 @@ void join(roar11::ThreadPool& pool) {
} //unnamed namespace
void test(oro::Api* api) {
void test(oro::Api* api, oro::OriginsDB* db) {
const std::size_t thread_count = 2U; //std::min(std::max(3U, std::thread::hardware_concurrency()) - 1, 4U);
std::cout << "Running with " << thread_count << " worker threads\n";
roar11::ThreadPool pool(thread_count);
eve::Eventia worker;
pool.submit(worker.event_functor());
auto fetcher = worker.make_timer<TimerItems>(3.0, &pool, api);
auto timer_items = worker.make_timer<TimerItems>(3.0, &pool, api, db);
auto timer_icons = worker.make_timer<TimerIcons>(20.0, &pool, api, db);
join(pool);
}

View file

@ -2,10 +2,11 @@
namespace oro {
class Api;
class OriginsDB;
} //namespace oro
namespace duck {
void test(oro::Api* api);
void test(oro::Api* api, oro::OriginsDB* db);
} //namespace duck

View file

@ -1,6 +1,6 @@
#include "oro/api.hpp"
#include "oro/originsdb.hpp"
#include "orotool_config.hpp"
#include "SQLiteCpp/SQLiteCpp.h"
#include "evloop.hpp"
#include <iostream>
@ -24,7 +24,8 @@ int main(int argc, char* argv[]) {
std::cout << "answer: " << ping.second.message << '\n';
std::cout << "version: " << ping.second.version << '\n';
duck::test(&oro_api);
oro::OriginsDB db;
duck::test(&oro_api, &db);
/*
{

View file

@ -20,6 +20,7 @@ endif
conf = configuration_data()
conf.set('BASE_URL', base_url)
conf.set('DATABASE', get_option('database_file'))
project_config_file = configure_file(
input: 'config.hpp.in',
output: meson.project_name() + '_config.hpp',
@ -44,6 +45,8 @@ executable(meson.project_name(),
'eventia/eventia.cpp',
'eventia/timer.cpp',
'timer_items.cpp',
'timer_icons.cpp',
'oro/originsdb.cpp',
project_config_file,
install: true,
dependencies: lib_deps,

91
src/oro/originsdb.cpp Normal file
View file

@ -0,0 +1,91 @@
#include "originsdb.hpp"
#include "SQLiteCpp/Database.h"
#include "SQLiteCpp/Statement.h"
#include "SQLiteCpp/Transaction.h"
#include "orotool_config.hpp"
#include "SQLiteCpp/SQLiteCpp.h"
#include "oro/items.hpp"
#include "oro/icons.hpp"
#include "oro/base64.hpp"
#include <mutex>
namespace oro {
namespace {
class Database : private std::unique_lock<std::mutex>, public SQLite::Database {
public:
explicit Database(std::mutex& mtx) :
std::unique_lock<std::mutex>(mtx),
SQLite::Database(duck::g_database, SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE)
{
}
};
} //unnamed namespace
OriginsDB::OriginsDB() = default;
OriginsDB::~OriginsDB() noexcept = default;
void OriginsDB::overwrite (const Items& items) {
Database db(m_db_mutex);
db.exec("DROP TABLE IF EXISTS items");
SQLite::Transaction transaction(db);
//example:
//{
// "item_id":501,
// "unique_name":"Red_Potion",
// "name":"Red Potion",
// "type":"IT_HEALING",
// "npc_price":50
//}
db.exec("CREATE TABLE items (item_id INTEGER PRIMARY KEY, unique_name TEXT, name TEXT, type INTEGER, subtype INTEGER, npc_price INTEGER, slots INTEGER, icon TEXT)");
SQLite::Statement query(db, "INSERT INTO items(item_id, unique_name, name, type, subtype, npc_price, slots) VALUES(?, ?, ?, ?, ?, ?, ?)");
for (const auto& item : items.items) {
query.bind(1, item.item_id);
query.bind(2, item.unique_name);
query.bind(3, item.name);
query.bind(4, static_cast<int>(item.type.value));
if (item.subtype)
query.bind(5, static_cast<int>(item.subtype->value));
else
query.bind(5, nullptr);
query.bind(6, item.npc_price);
if (item.slots)
query.bind(7, *item.slots);
else
query.bind(7, nullptr);
query.exec();
query.reset();
}
transaction.commit();
}
void OriginsDB::update (const Icons& icons) {
//example:
//{
// "item_id":501,
// "icon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAP1BMVEX/AP/XqpHDkHqudmL////ox6X/9LxJSUm3t7eSkpLb29tubm7Kt6//8+u+QzDTjG7tZEfyhVmPIhi4o5v/8OVQ35yOAAAAAXRSTlMAQObYZgAAAAFiS0dEBI9o2VEAAAAHdElNRQfkAg4MBBc1u27AAAAAmElEQVQoz7WP2w6DIBAFsSyedavLRf//W7uQVmk0afvQeSIzOQSc+wfDcPOXnigE/1MYxxBw0szTYAMwv2kikunuPcBEc+8XknkCVNXOfHhADOYYVYG9mE92V2y08iksQBbRp+/CDM3CSRulKNb9E5o4p/QK6/Fe0WyhpVI6bxORZK7SD+pELn0t7ZqTd25raT35mrZL/TUPifEKODGf6AcAAAAldEVYdGRhdGU6Y3JlYXRlADIwMjAtMDItMTRUMTI6MDQ6MjMrMDA6MDCsyg5gAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDIwLTAyLTE0VDEyOjA0OjIzKzAwOjAw3Ze23AAAAABJRU5ErkJggg=="
//}
Database db(m_db_mutex);
SQLite::Transaction transaction(db);
SQLite::Statement query(db, "UPDATE items SET icon = ? WHERE item_id = ?");
for (const auto& ico : icons.icons) {
query.bind(1, ico.icon);
query.bind(2, ico.item_id);
query.exec();
query.reset();
base64_decode(std::string_view(ico.icon).substr(std::string_view("data:image/png;base64,").size()));
}
transaction.commit();
}
} //namespace oro

24
src/oro/originsdb.hpp Normal file
View file

@ -0,0 +1,24 @@
#pragma once
#include <mutex>
namespace oro {
struct Items;
struct Icons;
struct Shops;
struct Creators;
class OriginsDB {
public:
OriginsDB();
~OriginsDB() noexcept;
void overwrite (const Items& items);
void update (const Icons& icons);
private:
std::mutex m_db_mutex;
};
} //namespace oro

42
src/timer_icons.cpp Normal file
View file

@ -0,0 +1,42 @@
#include "timer_icons.hpp"
#include "oro/originsdb.hpp"
#include "oro/api.hpp"
#include "eventia/private/context.hpp"
#include "roar11/ThreadPool.hpp"
#include <cassert>
#include <iostream>
namespace duck {
TimerIcons::TimerIcons (
const eve::Context& ctx,
double timeout,
roar11::ThreadPool* pool,
oro::Api* oro_api,
oro::OriginsDB* db
) :
eve::Timer(timeout, ctx),
m_pool(pool),
m_oro_api(oro_api),
m_db(db)
{
assert(m_pool);
assert(m_oro_api);
}
void TimerIcons::on_timer() {
m_pool->submit(&TimerIcons::fetch_data, this);
}
void TimerIcons::fetch_data() {
auto icons = m_oro_api->items_icons();
{
const int next_timer = icons.first.retry_after / icons.first.rate_limit;
std::cout << "Next timer in " << next_timer << " secs\n";
set_timer(static_cast<double>(next_timer));
}
m_db->update(icons.second);
}
} //namespace duck

37
src/timer_icons.hpp Normal file
View file

@ -0,0 +1,37 @@
#pragma once
#include "eventia/private/context.hpp"
#include "eventia/timer.hpp"
namespace roar11 {
class ThreadPool;
} //namespace roar11
namespace oro {
class Api;
class OriginsDB;
} //namespace oro
namespace duck {
class TimerIcons : eve::Timer {
public:
TimerIcons (
const eve::Context& ctx,
double timeout,
roar11::ThreadPool* pool,
oro::Api* oro_api,
oro::OriginsDB* db
);
virtual void on_timer() override;
private:
void fetch_data();
roar11::ThreadPool* m_pool;
oro::Api* m_oro_api;
oro::OriginsDB* m_db;
};
} //namespace duck

View file

@ -1,4 +1,5 @@
#include "timer_items.hpp"
#include "oro/originsdb.hpp"
#include "oro/api.hpp"
#include "eventia/private/context.hpp"
#include "roar11/ThreadPool.hpp"
@ -10,11 +11,13 @@ namespace duck {
const eve::Context& ctx,
double timeout,
roar11::ThreadPool* pool,
oro::Api* oro_api
oro::Api* oro_api,
oro::OriginsDB* db
) :
eve::Timer(timeout, ctx),
m_pool(pool),
m_oro_api(oro_api)
m_oro_api(oro_api),
m_db(db)
{
assert(m_pool);
assert(m_oro_api);
@ -32,6 +35,8 @@ namespace duck {
std::cout << "Next timer in " << next_timer << " secs\n";
set_timer(static_cast<double>(next_timer));
}
m_db->overwrite(items.second);
}
} //namespace duck

View file

@ -9,6 +9,7 @@ namespace roar11 {
namespace oro {
class Api;
class OriginsDB;
} //namespace oro
namespace duck {
@ -19,7 +20,8 @@ public:
const eve::Context& ctx,
double timeout,
roar11::ThreadPool* pool,
oro::Api* oro_api
oro::Api* oro_api,
oro::OriginsDB* db
);
virtual void on_timer() override;
@ -29,6 +31,7 @@ private:
roar11::ThreadPool* m_pool;
oro::Api* m_oro_api;
oro::OriginsDB* m_db;
};
} //namespace duck