mirror of
https://github.com/ZmnSCPxj/clboss.git
synced 2026-08-13 12:33:20 +02:00
256 lines
6.2 KiB
C++
256 lines
6.2 KiB
C++
#include"Boss/Mod/OnchainFundsIgnorer.hpp"
|
|
#include"Boss/Msg/CommandFail.hpp"
|
|
#include"Boss/Msg/CommandRequest.hpp"
|
|
#include"Boss/Msg/CommandResponse.hpp"
|
|
#include"Boss/Msg/DbResource.hpp"
|
|
#include"Boss/Msg/ManifestCommand.hpp"
|
|
#include"Boss/Msg/Manifestation.hpp"
|
|
#include"Boss/Msg/ProvideStatus.hpp"
|
|
#include"Boss/Msg/RequestGetOnchainIgnoreFlag.hpp"
|
|
#include"Boss/Msg/ResponseGetOnchainIgnoreFlag.hpp"
|
|
#include"Boss/Msg/SolicitStatus.hpp"
|
|
#include"Boss/log.hpp"
|
|
#include"Ev/Io.hpp"
|
|
#include"Ev/foreach.hpp"
|
|
#include"Ev/now.hpp"
|
|
#include"S/Bus.hpp"
|
|
#include"Sqlite3.hpp"
|
|
#include"Util/date.hpp"
|
|
#include"Util/make_unique.hpp"
|
|
#include<vector>
|
|
|
|
namespace Boss { namespace Mod {
|
|
|
|
class OnchainFundsIgnorer::Impl {
|
|
private:
|
|
S::Bus& bus;
|
|
Sqlite3::Db db;
|
|
|
|
std::vector<void*> pending_requesters;
|
|
|
|
void start() {
|
|
bus.subscribe<Msg::DbResource
|
|
>([this](Msg::DbResource const& m) {
|
|
db = m.db;
|
|
auto pending = std::move(pending_requesters);
|
|
return init_db()
|
|
+ Ev::foreach( [this](void* requester) {
|
|
return get_flag(requester);
|
|
}
|
|
, std::move(pending)
|
|
);
|
|
});
|
|
bus.subscribe<Msg::RequestGetOnchainIgnoreFlag
|
|
>([this
|
|
](Msg::RequestGetOnchainIgnoreFlag const& m) {
|
|
if (!db) {
|
|
pending_requesters.push_back(m.requester);
|
|
return Ev::lift();
|
|
}
|
|
return get_flag(m.requester);
|
|
});
|
|
|
|
/* Manifestation. */
|
|
bus.subscribe<Msg::Manifestation
|
|
>([this](Msg::Manifestation const& _) {
|
|
return bus.raise(Msg::ManifestCommand{
|
|
"clboss-ignore-onchain", "[hours]",
|
|
"Ignore onchain funds for {hours} "
|
|
"(default 24 hours).",
|
|
false
|
|
}) + bus.raise(Msg::ManifestCommand{
|
|
"clboss-notice-onchain", "",
|
|
"Cancel previous clboss-ignore-onchain and "
|
|
"resume managing onchain funds.",
|
|
false
|
|
});
|
|
});
|
|
|
|
/* Command handling. */
|
|
bus.subscribe<Msg::CommandRequest
|
|
>([this](Msg::CommandRequest const& req) {
|
|
auto id = req.id;
|
|
auto succeed = [this, id]() {
|
|
return bus.raise(Msg::CommandResponse{
|
|
id, Json::Out::empty_object()
|
|
});
|
|
};
|
|
|
|
auto act = Ev::lift();
|
|
if (req.command == "clboss-ignore-onchain") {
|
|
auto paramfail = [this, id]() {
|
|
return bus.raise(Msg::CommandFail{
|
|
id, -32602,
|
|
"Parameter failure",
|
|
Json::Out::empty_object()
|
|
});
|
|
};
|
|
|
|
auto hours = double(24.0);
|
|
|
|
auto hours_j = Jsmn::Object();
|
|
auto params = req.params;
|
|
if (params.is_object()) {
|
|
if (params.size() > 1)
|
|
return paramfail();
|
|
if (params.size() == 1) {
|
|
if (!params.has("hours"))
|
|
return paramfail();
|
|
hours_j = params["hours"];
|
|
}
|
|
} else if (params.is_array()) {
|
|
if (params.size() > 1)
|
|
return paramfail();
|
|
if (params.size() == 1)
|
|
hours_j = params[0];
|
|
} else
|
|
return paramfail();
|
|
if (!hours_j.is_null()) {
|
|
if (!hours_j.is_number())
|
|
return paramfail();
|
|
hours = (double) hours_j;
|
|
}
|
|
|
|
act += set_disableuntil( Ev::now()
|
|
+ (hours * 3600)
|
|
);
|
|
act += Boss::log( bus, Info
|
|
, "OnchainFundsIgnorer: "
|
|
"Will ignore onchain funds "
|
|
"for %f hours starting now."
|
|
, hours
|
|
);
|
|
act += succeed();
|
|
|
|
} else if (req.command == "clboss-notice-onchain") {
|
|
act += set_disableuntil(0);
|
|
act += Boss::log( bus, Info
|
|
, "OnchainFundsIgnorer: "
|
|
"Will notice onchain funds."
|
|
);
|
|
act += succeed();
|
|
}
|
|
return act;
|
|
});
|
|
|
|
/* clboss-status */
|
|
bus.subscribe<Msg::SolicitStatus
|
|
>([this](Msg::SolicitStatus const& _) {
|
|
return Ev::lift().then([this]() {
|
|
return get_disableuntil();
|
|
}).then([this](double disableuntil) {
|
|
auto now = Ev::now();
|
|
auto ignore = (now < disableuntil);
|
|
auto comment = std::string();
|
|
if (ignore)
|
|
comment = "`clboss-notice-onchain` "
|
|
"to resume managing "
|
|
"onchain funds.";
|
|
else
|
|
comment = "`clboss-ignore-onchain` "
|
|
"to ignore onchain funds "
|
|
"temporarily.";
|
|
|
|
auto stats = Json::Out()
|
|
.start_object()
|
|
.field( "status"
|
|
, ignore ?
|
|
"ignore" : "notice"
|
|
)
|
|
.field("now", now)
|
|
.field( "now_human"
|
|
, Util::date(now)
|
|
)
|
|
.field( "disable_until"
|
|
, disableuntil
|
|
)
|
|
.field( "disable_until_human"
|
|
, Util::date(
|
|
disableuntil
|
|
)
|
|
)
|
|
.field("comment", comment)
|
|
.end_object()
|
|
;
|
|
return bus.raise(Msg::ProvideStatus{
|
|
"should_monitor_onchain_funds",
|
|
std::move(stats)
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
Ev::Io<void> init_db() {
|
|
return db.transact().then([](Sqlite3::Tx tx) {
|
|
tx.query_execute(R"QRY(
|
|
CREATE TABLE IF NOT EXISTS "OnchainFundsIgnorer"
|
|
( id INTEGER PRIMARY KEY
|
|
, disableuntil REAL NOT NULL
|
|
);
|
|
INSERT OR IGNORE INTO "OnchainFundsIgnorer"
|
|
VALUES(1, 0.0);
|
|
)QRY");
|
|
tx.commit();
|
|
return Ev::lift();
|
|
});
|
|
}
|
|
Ev::Io<void> get_flag(void* requester) {
|
|
return get_disableuntil().then([requester, this
|
|
](double disableuntil) {
|
|
auto now = Ev::now();
|
|
|
|
auto msg = Msg::ResponseGetOnchainIgnoreFlag();
|
|
msg.ignore = (now < disableuntil);
|
|
if (msg.ignore)
|
|
msg.seconds = disableuntil - now;
|
|
else
|
|
msg.seconds = 0;
|
|
msg.requester = requester;
|
|
return bus.raise(msg);
|
|
});
|
|
}
|
|
Ev::Io<double> get_disableuntil() {
|
|
return db.transact().then([](Sqlite3::Tx tx) {
|
|
auto rv = double();
|
|
|
|
auto fetch = tx.query(R"QRY(
|
|
SELECT disableuntil FROM "OnchainFundsIgnorer";
|
|
)QRY").execute();
|
|
for (auto& r : fetch) {
|
|
rv = r.get<double>(0);
|
|
break;
|
|
}
|
|
tx.commit();
|
|
|
|
return Ev::lift(rv);
|
|
});
|
|
}
|
|
Ev::Io<void> set_disableuntil(double disableuntil) {
|
|
return db.transact().then([disableuntil](Sqlite3::Tx tx) {
|
|
tx.query(R"QRY(
|
|
UPDATE "OnchainFundsIgnorer"
|
|
SET disableuntil = :disableuntil;
|
|
)QRY")
|
|
.bind(":disableuntil", disableuntil)
|
|
.execute()
|
|
;
|
|
tx.commit();
|
|
return Ev::lift();
|
|
});
|
|
}
|
|
|
|
public:
|
|
Impl() =delete;
|
|
Impl(Impl&&) =delete;
|
|
Impl(Impl const&) =delete;
|
|
|
|
Impl(S::Bus& bus_) : bus(bus_) { start(); }
|
|
};
|
|
|
|
OnchainFundsIgnorer::OnchainFundsIgnorer(OnchainFundsIgnorer&&) =default;
|
|
OnchainFundsIgnorer::~OnchainFundsIgnorer() =default;
|
|
|
|
OnchainFundsIgnorer::OnchainFundsIgnorer(S::Bus& bus)
|
|
: pimpl(Util::make_unique<Impl>(bus)) { }
|
|
|
|
}}
|