Add support for quiz explanation.

GitOrigin-RevId: ab4346fe3abe5c5abd7234d5b4b3937e995494af
This commit is contained in:
levlam 2020-04-03 23:39:50 +03:00
parent bb75ea35da
commit 4e7cd24285
8 changed files with 79 additions and 14 deletions

View File

@ -216,8 +216,10 @@ pollOption text:string voter_count:int32 vote_percentage:int32 is_chosen:Bool is
//@description A regular poll @allow_multiple_answers True, if multiple answer options can be chosen simultaneously //@description A regular poll @allow_multiple_answers True, if multiple answer options can be chosen simultaneously
pollTypeRegular allow_multiple_answers:Bool = PollType; pollTypeRegular allow_multiple_answers:Bool = PollType;
//@description A poll in quiz mode, which has exactly one correct answer option and can be answered only once @correct_option_id 0-based identifier of the correct answer option; -1 for a yet unanswered poll //@description A poll in quiz mode, which has exactly one correct answer option and can be answered only once
pollTypeQuiz correct_option_id:int32 = PollType; //@correct_option_id 0-based identifier of the correct answer option; -1 for a yet unanswered poll
//@explanation Text shown after an incorrect answer has chosen; empty for a yet unanswered poll
pollTypeQuiz correct_option_id:int32 explanation:formattedText = PollType;
//@description Describes an animation file. The animation must be encoded in GIF or MPEG4 format @duration Duration of the animation, in seconds; as defined by the sender @width Width of the animation @height Height of the animation //@description Describes an animation file. The animation must be encoded in GIF or MPEG4 format @duration Duration of the animation, in seconds; as defined by the sender @width Width of the animation @height Height of the animation

Binary file not shown.

View File

@ -1749,6 +1749,7 @@ static Result<InputMessageContent> create_input_message_content(
bool allow_multiple_answers = false; bool allow_multiple_answers = false;
bool is_quiz = false; bool is_quiz = false;
int32 correct_option_id = -1; int32 correct_option_id = -1;
FormattedText explanation;
if (input_poll->type_ == nullptr) { if (input_poll->type_ == nullptr) {
return Status::Error(400, "Poll type must not be empty"); return Status::Error(400, "Poll type must not be empty");
} }
@ -1765,6 +1766,12 @@ static Result<InputMessageContent> create_input_message_content(
if (correct_option_id < 0 || correct_option_id >= static_cast<int32>(input_poll->options_.size())) { if (correct_option_id < 0 || correct_option_id >= static_cast<int32>(input_poll->options_.size())) {
return Status::Error(400, "Wrong correct option ID specified"); return Status::Error(400, "Wrong correct option ID specified");
} }
auto r_explanation =
process_input_caption(td->contacts_manager_.get(), DialogId(), std::move(type->explanation_), is_bot);
if (r_explanation.is_error()) {
return r_explanation.move_as_error();
}
explanation = r_explanation.move_as_ok();
break; break;
} }
default: default:
@ -1777,9 +1784,10 @@ static Result<InputMessageContent> create_input_message_content(
close_date = 0; close_date = 0;
} }
bool is_closed = is_bot ? input_poll->is_closed_ : false; bool is_closed = is_bot ? input_poll->is_closed_ : false;
content = make_unique<MessagePoll>(td->poll_manager_->create_poll( content = make_unique<MessagePoll>(
std::move(input_poll->question_), std::move(input_poll->options_), input_poll->is_anonymous_, td->poll_manager_->create_poll(std::move(input_poll->question_), std::move(input_poll->options_),
allow_multiple_answers, is_quiz, correct_option_id, close_date, close_period, is_closed)); input_poll->is_anonymous_, allow_multiple_answers, is_quiz, correct_option_id,
std::move(explanation), close_date, close_period, is_closed));
break; break;
} }
default: default:

View File

@ -3899,6 +3899,9 @@ void add_formatted_text_dependencies(Dependencies &dependencies, const Formatted
} }
bool need_skip_bot_commands(const ContactsManager *contacts_manager, DialogId dialog_id, bool is_bot) { bool need_skip_bot_commands(const ContactsManager *contacts_manager, DialogId dialog_id, bool is_bot) {
if (!dialog_id.is_valid()) {
return true;
}
if (is_bot) { if (is_bot) {
return false; return false;
} }

View File

@ -15,6 +15,7 @@
#include "td/telegram/logevent/LogEvent.h" #include "td/telegram/logevent/LogEvent.h"
#include "td/telegram/logevent/LogEventHelper.h" #include "td/telegram/logevent/LogEventHelper.h"
#include "td/telegram/MessagesManager.h" #include "td/telegram/MessagesManager.h"
#include "td/telegram/misc.h"
#include "td/telegram/net/NetActor.h" #include "td/telegram/net/NetActor.h"
#include "td/telegram/PollId.hpp" #include "td/telegram/PollId.hpp"
#include "td/telegram/PollManager.hpp" #include "td/telegram/PollManager.hpp"
@ -531,7 +532,8 @@ td_api::object_ptr<td_api::poll> PollManager::get_poll_object(PollId poll_id, co
td_api::object_ptr<td_api::PollType> poll_type; td_api::object_ptr<td_api::PollType> poll_type;
if (poll->is_quiz) { if (poll->is_quiz) {
auto correct_option_id = is_local_poll_id(poll_id) ? -1 : poll->correct_option_id; auto correct_option_id = is_local_poll_id(poll_id) ? -1 : poll->correct_option_id;
poll_type = td_api::make_object<td_api::pollTypeQuiz>(correct_option_id); poll_type = td_api::make_object<td_api::pollTypeQuiz>(
correct_option_id, get_formatted_text_object(is_local_poll_id(poll_id) ? FormattedText() : poll->explanation));
} else { } else {
poll_type = td_api::make_object<td_api::pollTypeRegular>(poll->allow_multiple_answers); poll_type = td_api::make_object<td_api::pollTypeRegular>(poll->allow_multiple_answers);
} }
@ -560,8 +562,8 @@ telegram_api::object_ptr<telegram_api::pollAnswer> PollManager::get_input_poll_o
} }
PollId PollManager::create_poll(string &&question, vector<string> &&options, bool is_anonymous, PollId PollManager::create_poll(string &&question, vector<string> &&options, bool is_anonymous,
bool allow_multiple_answers, bool is_quiz, int32 correct_option_id, int32 close_date, bool allow_multiple_answers, bool is_quiz, int32 correct_option_id,
int32 close_period, bool is_closed) { FormattedText &&explanation, int32 close_date, int32 close_period, bool is_closed) {
auto poll = make_unique<Poll>(); auto poll = make_unique<Poll>();
poll->question = std::move(question); poll->question = std::move(question);
int pos = '0'; int pos = '0';
@ -575,6 +577,7 @@ PollId PollManager::create_poll(string &&question, vector<string> &&options, boo
poll->allow_multiple_answers = allow_multiple_answers; poll->allow_multiple_answers = allow_multiple_answers;
poll->is_quiz = is_quiz; poll->is_quiz = is_quiz;
poll->correct_option_id = correct_option_id; poll->correct_option_id = correct_option_id;
poll->explanation = std::move(explanation);
poll->close_date = close_date; poll->close_date = close_date;
poll->close_period = close_period; poll->close_period = close_period;
poll->is_closed = is_closed; poll->is_closed = is_closed;
@ -1196,13 +1199,18 @@ tl_object_ptr<telegram_api::InputMedia> PollManager::get_input_media(PollId poll
CHECK(poll->correct_option_id >= 0); CHECK(poll->correct_option_id >= 0);
CHECK(static_cast<size_t>(poll->correct_option_id) < poll->options.size()); CHECK(static_cast<size_t>(poll->correct_option_id) < poll->options.size());
correct_answers.push_back(BufferSlice(poll->options[poll->correct_option_id].data)); correct_answers.push_back(BufferSlice(poll->options[poll->correct_option_id].data));
if (!poll->explanation.text.empty()) {
flags |= telegram_api::inputMediaPoll::SOLUTION_MASK;
}
} }
return telegram_api::make_object<telegram_api::inputMediaPoll>( return telegram_api::make_object<telegram_api::inputMediaPoll>(
flags, flags,
telegram_api::make_object<telegram_api::poll>( telegram_api::make_object<telegram_api::poll>(
0, poll_flags, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, poll->question, 0, poll_flags, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, poll->question,
transform(poll->options, get_input_poll_option), poll->close_period, poll->close_date), transform(poll->options, get_input_poll_option), poll->close_period, poll->close_date),
std::move(correct_answers), string(), Auto()); std::move(correct_answers), poll->explanation.text,
get_input_message_entities(td_->contacts_manager_.get(), poll->explanation.entities, "get_input_media_poll"));
} }
vector<PollManager::PollOption> PollManager::get_poll_options( vector<PollManager::PollOption> PollManager::get_poll_options(
@ -1384,14 +1392,33 @@ PollId PollManager::on_get_poll(PollId poll_id, tl_object_ptr<telegram_api::poll
poll->total_voter_count = max_total_voter_count; poll->total_voter_count = max_total_voter_count;
} }
} }
auto entities =
get_message_entities(td_->contacts_manager_.get(), std::move(poll_results->solution_entities_), "on_get_poll");
auto status = fix_formatted_text(poll_results->solution_, entities, true, true, true, false);
if (status.is_error()) {
if (!clean_input_string(poll_results->solution_)) {
poll_results->solution_.clear();
}
entities = find_entities(poll_results->solution_, true);
}
FormattedText explanation{std::move(poll_results->solution_), std::move(entities)};
if (poll->is_quiz) { if (poll->is_quiz) {
if (poll->correct_option_id != correct_option_id) { if (poll->correct_option_id != correct_option_id) {
poll->correct_option_id = correct_option_id; poll->correct_option_id = correct_option_id;
is_changed = true; is_changed = true;
} }
} else if (correct_option_id != -1) { if (poll->explanation != explanation && (!is_min || poll->is_closed)) {
poll->explanation = std::move(explanation);
is_changed = true;
}
} else {
if (correct_option_id != -1) {
LOG(ERROR) << "Receive correct option " << correct_option_id << " in non-quiz " << poll_id; LOG(ERROR) << "Receive correct option " << correct_option_id << " in non-quiz " << poll_id;
} }
}
vector<UserId> recent_voter_user_ids; vector<UserId> recent_voter_user_ids;
if (!is_bot) { if (!is_bot) {
for (auto &user_id_int : poll_results->recent_voters_) { for (auto &user_id_int : poll_results->recent_voters_) {

View File

@ -7,6 +7,7 @@
#pragma once #pragma once
#include "td/telegram/FullMessageId.h" #include "td/telegram/FullMessageId.h"
#include "td/telegram/MessageEntity.h"
#include "td/telegram/net/NetQuery.h" #include "td/telegram/net/NetQuery.h"
#include "td/telegram/PollId.h" #include "td/telegram/PollId.h"
#include "td/telegram/ReplyMarkup.h" #include "td/telegram/ReplyMarkup.h"
@ -45,7 +46,8 @@ class PollManager : public Actor {
static bool is_local_poll_id(PollId poll_id); static bool is_local_poll_id(PollId poll_id);
PollId create_poll(string &&question, vector<string> &&options, bool is_anonymous, bool allow_multiple_answers, PollId create_poll(string &&question, vector<string> &&options, bool is_anonymous, bool allow_multiple_answers,
bool is_quiz, int32 correct_option_id, int32 close_date, int32 close_period, bool is_closed); bool is_quiz, int32 correct_option_id, FormattedText &&explanation, int32 close_date,
int32 close_period, bool is_closed);
void register_poll(PollId poll_id, FullMessageId full_message_id, const char *source); void register_poll(PollId poll_id, FullMessageId full_message_id, const char *source);
@ -106,6 +108,7 @@ class PollManager : public Actor {
string question; string question;
vector<PollOption> options; vector<PollOption> options;
vector<UserId> recent_voter_user_ids; vector<UserId> recent_voter_user_ids;
FormattedText explanation;
int32 total_voter_count = 0; int32 total_voter_count = 0;
int32 correct_option_id = -1; int32 correct_option_id = -1;
int32 close_date = 0; int32 close_date = 0;

View File

@ -46,6 +46,7 @@ void PollManager::Poll::store(StorerT &storer) const {
bool has_recent_voters = !recent_voter_user_ids.empty(); bool has_recent_voters = !recent_voter_user_ids.empty();
bool has_close_date = close_date != 0; bool has_close_date = close_date != 0;
bool has_close_period = close_period != 0; bool has_close_period = close_period != 0;
bool has_explanation = !explanation.text.empty();
BEGIN_STORE_FLAGS(); BEGIN_STORE_FLAGS();
STORE_FLAG(is_closed); STORE_FLAG(is_closed);
STORE_FLAG(is_public); STORE_FLAG(is_public);
@ -54,6 +55,7 @@ void PollManager::Poll::store(StorerT &storer) const {
STORE_FLAG(has_recent_voters); STORE_FLAG(has_recent_voters);
STORE_FLAG(has_close_date); STORE_FLAG(has_close_date);
STORE_FLAG(has_close_period); STORE_FLAG(has_close_period);
STORE_FLAG(has_explanation);
END_STORE_FLAGS(); END_STORE_FLAGS();
store(question, storer); store(question, storer);
@ -71,6 +73,9 @@ void PollManager::Poll::store(StorerT &storer) const {
if (has_close_period) { if (has_close_period) {
store(close_period, storer); store(close_period, storer);
} }
if (has_explanation) {
store(explanation, storer);
}
} }
template <class ParserT> template <class ParserT>
@ -80,6 +85,7 @@ void PollManager::Poll::parse(ParserT &parser) {
bool has_recent_voters; bool has_recent_voters;
bool has_close_date; bool has_close_date;
bool has_close_period; bool has_close_period;
bool has_explanation;
BEGIN_PARSE_FLAGS(); BEGIN_PARSE_FLAGS();
PARSE_FLAG(is_closed); PARSE_FLAG(is_closed);
PARSE_FLAG(is_public); PARSE_FLAG(is_public);
@ -88,6 +94,7 @@ void PollManager::Poll::parse(ParserT &parser) {
PARSE_FLAG(has_recent_voters); PARSE_FLAG(has_recent_voters);
PARSE_FLAG(has_close_date); PARSE_FLAG(has_close_date);
PARSE_FLAG(has_close_period); PARSE_FLAG(has_close_period);
PARSE_FLAG(has_explanation);
END_PARSE_FLAGS(); END_PARSE_FLAGS();
is_anonymous = !is_public; is_anonymous = !is_public;
@ -109,6 +116,9 @@ void PollManager::Poll::parse(ParserT &parser) {
if (has_close_period) { if (has_close_period) {
parse(close_period, parser); parse(close_period, parser);
} }
if (has_explanation) {
parse(explanation, parser);
}
} }
template <class StorerT> template <class StorerT>
@ -119,6 +129,7 @@ void PollManager::store_poll(PollId poll_id, StorerT &storer) const {
CHECK(poll != nullptr); CHECK(poll != nullptr);
bool has_close_date = poll->close_date != 0; bool has_close_date = poll->close_date != 0;
bool has_close_period = poll->close_period != 0; bool has_close_period = poll->close_period != 0;
bool has_explanation = !poll->explanation.text.empty();
BEGIN_STORE_FLAGS(); BEGIN_STORE_FLAGS();
STORE_FLAG(poll->is_closed); STORE_FLAG(poll->is_closed);
STORE_FLAG(poll->is_anonymous); STORE_FLAG(poll->is_anonymous);
@ -126,6 +137,7 @@ void PollManager::store_poll(PollId poll_id, StorerT &storer) const {
STORE_FLAG(poll->is_quiz); STORE_FLAG(poll->is_quiz);
STORE_FLAG(has_close_date); STORE_FLAG(has_close_date);
STORE_FLAG(has_close_period); STORE_FLAG(has_close_period);
STORE_FLAG(has_explanation);
END_STORE_FLAGS(); END_STORE_FLAGS();
store(poll->question, storer); store(poll->question, storer);
vector<string> options = transform(poll->options, [](const PollOption &option) { return option.text; }); vector<string> options = transform(poll->options, [](const PollOption &option) { return option.text; });
@ -139,6 +151,9 @@ void PollManager::store_poll(PollId poll_id, StorerT &storer) const {
if (has_close_period) { if (has_close_period) {
store(poll->close_period, storer); store(poll->close_period, storer);
} }
if (has_explanation) {
store(poll->explanation, storer);
}
} }
} }
@ -150,6 +165,7 @@ PollId PollManager::parse_poll(ParserT &parser) {
if (is_local_poll_id(poll_id)) { if (is_local_poll_id(poll_id)) {
string question; string question;
vector<string> options; vector<string> options;
FormattedText explanation;
int32 close_date = 0; int32 close_date = 0;
int32 close_period = 0; int32 close_period = 0;
bool is_closed = false; bool is_closed = false;
@ -158,6 +174,7 @@ PollId PollManager::parse_poll(ParserT &parser) {
bool is_quiz = false; bool is_quiz = false;
bool has_close_date = false; bool has_close_date = false;
bool has_close_period = false; bool has_close_period = false;
bool has_explanation = false;
int32 correct_option_id = -1; int32 correct_option_id = -1;
if (parser.version() >= static_cast<int32>(Version::SupportPolls2_0)) { if (parser.version() >= static_cast<int32>(Version::SupportPolls2_0)) {
@ -168,6 +185,7 @@ PollId PollManager::parse_poll(ParserT &parser) {
PARSE_FLAG(is_quiz); PARSE_FLAG(is_quiz);
PARSE_FLAG(has_close_date); PARSE_FLAG(has_close_date);
PARSE_FLAG(has_close_period); PARSE_FLAG(has_close_period);
PARSE_FLAG(has_explanation);
END_PARSE_FLAGS(); END_PARSE_FLAGS();
} }
parse(question, parser); parse(question, parser);
@ -184,11 +202,14 @@ PollId PollManager::parse_poll(ParserT &parser) {
if (has_close_period) { if (has_close_period) {
parse(close_period, parser); parse(close_period, parser);
} }
if (has_explanation) {
parse(explanation, parser);
}
if (parser.get_error() != nullptr) { if (parser.get_error() != nullptr) {
return PollId(); return PollId();
} }
return create_poll(std::move(question), std::move(options), is_anonymous, allow_multiple_answers, is_quiz, return create_poll(std::move(question), std::move(options), is_anonymous, allow_multiple_answers, is_quiz,
correct_option_id, close_date, close_period, is_closed); correct_option_id, std::move(explanation), close_date, close_period, is_closed);
} }
auto poll = get_poll_force(poll_id); auto poll = get_poll_force(poll_id);

View File

@ -3227,7 +3227,8 @@ class CliClient final : public Actor {
td_api::object_ptr<td_api::PollType> poll_type; td_api::object_ptr<td_api::PollType> poll_type;
if (op == "squiz") { if (op == "squiz") {
poll_type = td_api::make_object<td_api::pollTypeQuiz>(narrow_cast<int32>(options.size() - 1)); poll_type = td_api::make_object<td_api::pollTypeQuiz>(narrow_cast<int32>(options.size() - 1),
as_formatted_text("_te*st*_"));
} else { } else {
poll_type = td_api::make_object<td_api::pollTypeRegular>(op == "spollm"); poll_type = td_api::make_object<td_api::pollTypeRegular>(op == "spollm");
} }