void Voting::valid_motion(const Vote &vote) { const auto &cfg(vote.get_cfg()); const auto &user(vote.get_user()); const auto &chan(vote.get_chan()); valid_limits(vote,chan,user); if(!speaker(cfg,chan,user)) throw Exception("You are not able to create votes on this channel."); if(!enfranchised(cfg,chan,user)) throw Exception("You are not yet enfranchised in this channel."); if(!qualified(cfg,chan,user)) throw Exception("You have not been participating enough to start a vote."); const auto now(time(nullptr)); if(cfg.has("limit.motion")) { const auto limit(secs_cast(cfg["limit.motion"])); const Vdb::Terms query { Vdb::Term { "ended", ">=", lex_cast(now - limit) }, Vdb::Term { "issue", "==", vote.get_issue() }, Vdb::Term { "type", "==", vote.get_type() }, Vdb::Term { "chan", "==", chan.get_name() }, }; if(!vdb.query(query,1).empty()) throw Exception("This vote was made within the last ") << secs_cast(limit) << ". Try again later."; } const Adoc reasons(cfg.get_child("limit.reason",Adoc{})); reasons.for_each([this,&chan,&vote,&now] (const std::string &reason, const std::string &limit_str) { if(reason.size() > 64 || !isalpha(reason)) throw Exception("Malformed reason key given in limit.reason"); const auto limit(secs_cast(limit_str)); const Vdb::Terms query { Vdb::Term { "reason", "==", reason }, Vdb::Term { "ended", ">=", lex_cast(now - limit) }, Vdb::Term { "issue", "==", vote.get_issue() }, Vdb::Term { "type", "==", vote.get_type() }, Vdb::Term { "chan", "==", chan.get_name() }, }; if(!vdb.query(query,1).empty()) throw Exception("This vote failed with the reason '") << reason << "' within the last " << secs_cast(limit) << ". Try again later."; }); }
void Voting::call_finish(Vote &vote) noexcept try { vote.finish(); } catch(const std::exception &e) { std::stringstream err; err << "An internal error occurred in Vote::finish(): " << e.what() << "."; std::cerr << "[Voting]: \033[1;31m" << err.str() << "\033[0m" << std::endl; const auto &chans(get_chans()); if(chans.has(vote.get_chan_name())) { Chan &chan(vote.get_chan()); chan << err.str() << chan.flush; } }