Fix handling polls with unknown voter counts

https://botsin.space/@muffinista/101947647800341192
This commit is contained in:
blankie 2023-11-24 18:42:46 +11:00
parent f408c5206c
commit 2df649af8e
Signed by: blankie
GPG Key ID: CC15FC822C7F61F5
4 changed files with 19 additions and 9 deletions

View File

@ -13,12 +13,13 @@ add_subdirectory(thirdparty/lexbor)
#pkg_check_modules(HIREDIS REQUIRED hiredis) #pkg_check_modules(HIREDIS REQUIRED hiredis)
if (CMAKE_BUILD_TYPE MATCHES "Debug") if (CMAKE_BUILD_TYPE MATCHES "Debug|RelWithDebInfo")
if (NOT FLAGS) if (NOT FLAGS)
list(APPEND FLAGS -fsanitize=undefined,thread) list(APPEND FLAGS -fsanitize=undefined,thread)
endif() endif()
# https://sourceforge.net/p/valgrind/mailman/valgrind-users/thread/Ygze8PzaQAYWlKDj%40wildebeest.org/ # https://sourceforge.net/p/valgrind/mailman/valgrind-users/thread/Ygze8PzaQAYWlKDj%40wildebeest.org/
list(APPEND FLAGS -gdwarf-4) list(APPEND FLAGS -gdwarf-4)
list(APPEND DEFINITIONS JSON_DIAGNOSTICS=1)
endif() endif()
# https://t.me/NightShadowsHangout/670691 # https://t.me/NightShadowsHangout/670691
@ -39,4 +40,5 @@ set_target_properties(${PROJECT_NAME}
) )
target_include_directories(${PROJECT_NAME} PRIVATE thirdparty ${HIREDIS_INCLUDE_DIRS}) target_include_directories(${PROJECT_NAME} PRIVATE thirdparty ${HIREDIS_INCLUDE_DIRS})
target_link_libraries(${PROJECT_NAME} PRIVATE nlohmann_json::nlohmann_json CURL::libcurl httplib::httplib lexbor_static ${HIREDIS_LINK_LIBRARIES}) target_link_libraries(${PROJECT_NAME} PRIVATE nlohmann_json::nlohmann_json CURL::libcurl httplib::httplib lexbor_static ${HIREDIS_LINK_LIBRARIES})
target_compile_definitions(${PROJECT_NAME} PRIVATE ${DEFINITIONS})
target_compile_options(${PROJECT_NAME} PRIVATE ${FLAGS}) target_compile_options(${PROJECT_NAME} PRIVATE ${FLAGS})

View File

@ -79,7 +79,12 @@ void from_json(const json& j, PollOption& option) {
void from_json(const json& j, Poll& poll) { void from_json(const json& j, Poll& poll) {
poll.expires_at = parse_rfc3339(j.at("expires_at").get_ref<const std::string&>()); poll.expires_at = parse_rfc3339(j.at("expires_at").get_ref<const std::string&>());
j.at("expired").get_to(poll.expired); j.at("expired").get_to(poll.expired);
j.at("voters_count").get_to(poll.voters_count); if (!j.at("voters_count").is_null()) {
j.at("voters_count").get_to(poll.voters_count);
} else {
poll.voters_count = -1;
}
j.at("votes_count").get_to(poll.votes_count);
j.at("options").get_to(poll.options); j.at("options").get_to(poll.options);
j.at("emojis").get_to(poll.emojis); j.at("emojis").get_to(poll.emojis);
} }

View File

@ -65,7 +65,8 @@ struct PollOption {
struct Poll { struct Poll {
time_t expires_at; time_t expires_at;
bool expired; bool expired;
uint64_t voters_count; int64_t voters_count; // negative if unknown
uint64_t votes_count;
std::vector<PollOption> options; std::vector<PollOption> options;
std::vector<Emoji> emojis; std::vector<Emoji> emojis;
}; };

View File

@ -461,6 +461,7 @@ static inline Element serialize_media(const Media& media) {
} }
static inline Element serialize_poll(const httplib::Request& req, const Poll& poll) { static inline Element serialize_poll(const httplib::Request& req, const Poll& poll) {
uint64_t voters_count = poll.voters_count >= 0 ? static_cast<uint64_t>(poll.voters_count) : poll.votes_count;
Element div("div"); Element div("div");
auto pick_form = [](uint64_t count, const char* singular, const char* plural) { auto pick_form = [](uint64_t count, const char* singular, const char* plural) {
@ -469,8 +470,8 @@ static inline Element serialize_poll(const httplib::Request& req, const Poll& po
div.nodes.reserve(poll.options.size() + 1); div.nodes.reserve(poll.options.size() + 1);
for (const PollOption& option : poll.options) { for (const PollOption& option : poll.options) {
std::string percentage = poll.voters_count std::string percentage = voters_count
? std::to_string(option.votes_count * 100 / poll.voters_count) + '%' ? std::to_string(option.votes_count * 100 / voters_count) + '%'
: "0%"; : "0%";
div.nodes.push_back(Element("div", {{"class", "poll-option"}, {"title", std::to_string(option.votes_count) + pick_form(option.votes_count, " vote", " votes")}}, { div.nodes.push_back(Element("div", {{"class", "poll-option"}, {"title", std::to_string(option.votes_count) + pick_form(option.votes_count, " vote", " votes")}}, {
@ -479,10 +480,11 @@ static inline Element serialize_poll(const httplib::Request& req, const Poll& po
})); }));
} }
Element p("p", { Element p("p", poll.voters_count >= 0
std::to_string(poll.voters_count), " ", pick_form(poll.voters_count, "voter", "voters"), ? std::vector<Node>({std::to_string(voters_count), " ", pick_form(voters_count, "voter", "voters")})
" / ", : std::vector<Node>({std::to_string(poll.votes_count), " ", pick_form(poll.votes_count, "vote", "votes")})
}); );
p.nodes.push_back(" / ");
if (poll.expired) { if (poll.expired) {
p.nodes.push_back("Expired"); p.nodes.push_back("Expired");
} else { } else {