Ejemplo n.º 1
0
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.";
	});
}
Ejemplo n.º 2
0
id_t Voting::duplicated(const Vote &vote)
const
{
	const auto pit(chanidx.equal_range(vote.get_chan_name()));
	for(auto it(pit.first); it != pit.second; ++it)
	{
		const auto id(it->second);
		const auto vit(votes.find(id));
		if(vit == votes.end())
			continue;

		const auto &existing(*vit->second);
		if(vote.get_id() == existing.get_id())
			continue;

		if(vote.get_type() != existing.get_type())
			continue;

		if(!boost::iequals(vote.get_issue(),existing.get_issue()))
			continue;

		return existing.get_id();
	};

	return 0;
}
Ejemplo n.º 3
0
void Voting::valid_limits_type(const Vote &vote,
                               const Chan &chan,
                               const User &user,
                               const Adoc &cfg)
{
	using limits = std::numeric_limits<uint8_t>;

	if(vote.get_type() == "appeal")
		return;

	if(vote.get_type() == "trial")
		return;

	auto typcnt(0);
	for_each(chan,user,[&typcnt,&vote]
	(const Vote &active)
	{
		typcnt += active.get_type() == vote.get_type();
	});

	if(typcnt > cfg.get<uint8_t>("limit.type",limits::max()))
		throw Exception("Too many active votes of this type started by you on this channel.");
}