Add td_api::getPollVoters.
GitOrigin-RevId: 47ad78287433a2efb9b66f18a960e4de6060842a
This commit is contained in:
parent
f2211527db
commit
4e22f29c53
@ -3427,10 +3427,16 @@ getJsonValue json:string = JsonValue;
|
||||
getJsonString json_value:JsonValue = Text;
|
||||
|
||||
|
||||
//@description Changes the user answer to a poll. A quiz poll can be answered only once @chat_id Identifier of the chat to which the poll belongs @message_id Identifier of the message containing the poll
|
||||
//@option_ids 0-based identifiers of options, chosen by the user. User can choose more than 1 option only is the poll allows multiple answers
|
||||
//@description Changes the user answer to a poll. A quiz poll can be answered only once
|
||||
//@chat_id Identifier of the chat to which the poll belongs @message_id Identifier of the message containing the poll
|
||||
//@option_ids 0-based identifiers of answer options, chosen by the user. User can choose more than 1 answer option only is the poll allows multiple answers
|
||||
setPollAnswer chat_id:int53 message_id:int53 option_ids:vector<int32> = Ok;
|
||||
|
||||
//@description Returns users voted for the specified option in a non-anonymous polls. For the optimal performance the number of returned users is chosen by the library
|
||||
//@chat_id Identifier of the chat to which the poll belongs @message_id Identifier of the message containing the poll
|
||||
//@option_id 0-based identifier of the answer option @offset Number of users to skip in the result; must be non-negative
|
||||
getPollVoters chat_id:int53 message_id:int53 option_id:int32 offset:int32 = Users;
|
||||
|
||||
//@description Stops a poll. A poll in a message can be stopped when the message has can_be_edited flag set
|
||||
//@chat_id Identifier of the chat to which the poll belongs @message_id Identifier of the message containing the poll @reply_markup The new message reply markup; for bots only
|
||||
stopPoll chat_id:int53 message_id:int53 reply_markup:ReplyMarkup = Ok;
|
||||
|
Binary file not shown.
@ -429,7 +429,7 @@ class MessageChatSetTtl : public MessageContent {
|
||||
|
||||
class MessageUnsupported : public MessageContent {
|
||||
public:
|
||||
static constexpr int32 CURRENT_VERSION = 4;
|
||||
static constexpr int32 CURRENT_VERSION = 5;
|
||||
int32 version = CURRENT_VERSION;
|
||||
|
||||
MessageUnsupported() = default;
|
||||
@ -2774,18 +2774,26 @@ void set_message_content_web_page_id(MessageContent *content, WebPageId web_page
|
||||
static_cast<MessageText *>(content)->web_page_id = web_page_id;
|
||||
}
|
||||
|
||||
void set_message_content_poll_answer(Td *td, MessageContent *content, FullMessageId full_message_id,
|
||||
void set_message_content_poll_answer(Td *td, const MessageContent *content, FullMessageId full_message_id,
|
||||
vector<int32> &&option_ids, Promise<Unit> &&promise) {
|
||||
CHECK(content->get_type() == MessageContentType::Poll);
|
||||
td->poll_manager_->set_poll_answer(static_cast<MessagePoll *>(content)->poll_id, full_message_id,
|
||||
td->poll_manager_->set_poll_answer(static_cast<const MessagePoll *>(content)->poll_id, full_message_id,
|
||||
std::move(option_ids), std::move(promise));
|
||||
}
|
||||
|
||||
void stop_message_content_poll(Td *td, MessageContent *content, FullMessageId full_message_id,
|
||||
void get_message_content_poll_voters(Td *td, const MessageContent *content, FullMessageId full_message_id,
|
||||
int32 option_id, int32 offset,
|
||||
Promise<std::pair<int32, vector<UserId>>> &&promise) {
|
||||
CHECK(content->get_type() == MessageContentType::Poll);
|
||||
td->poll_manager_->get_poll_voters(static_cast<const MessagePoll *>(content)->poll_id, full_message_id, option_id,
|
||||
offset, std::move(promise));
|
||||
}
|
||||
|
||||
void stop_message_content_poll(Td *td, const MessageContent *content, FullMessageId full_message_id,
|
||||
unique_ptr<ReplyMarkup> &&reply_markup, Promise<Unit> &&promise) {
|
||||
CHECK(content->get_type() == MessageContentType::Poll);
|
||||
td->poll_manager_->stop_poll(static_cast<MessagePoll *>(content)->poll_id, full_message_id, std::move(reply_markup),
|
||||
std::move(promise));
|
||||
td->poll_manager_->stop_poll(static_cast<const MessagePoll *>(content)->poll_id, full_message_id,
|
||||
std::move(reply_markup), std::move(promise));
|
||||
}
|
||||
|
||||
static void merge_location_access_hash(const Location &first, const Location &second) {
|
||||
|
@ -190,10 +190,14 @@ WebPageId get_message_content_web_page_id(const MessageContent *content);
|
||||
|
||||
void set_message_content_web_page_id(MessageContent *content, WebPageId web_page_id);
|
||||
|
||||
void set_message_content_poll_answer(Td *td, MessageContent *content, FullMessageId full_message_id,
|
||||
void set_message_content_poll_answer(Td *td, const MessageContent *content, FullMessageId full_message_id,
|
||||
vector<int32> &&option_ids, Promise<Unit> &&promise);
|
||||
|
||||
void stop_message_content_poll(Td *td, MessageContent *content, FullMessageId full_message_id,
|
||||
void get_message_content_poll_voters(Td *td, const MessageContent *content, FullMessageId full_message_id,
|
||||
int32 option_id, int32 offset,
|
||||
Promise<std::pair<int32, vector<UserId>>> &&promise);
|
||||
|
||||
void stop_message_content_poll(Td *td, const MessageContent *content, FullMessageId full_message_id,
|
||||
unique_ptr<ReplyMarkup> &&reply_markup, Promise<Unit> &&promise);
|
||||
|
||||
void merge_message_contents(Td *td, const MessageContent *old_content, MessageContent *new_content,
|
||||
|
@ -2595,7 +2595,7 @@ Status fix_formatted_text(string &text, vector<MessageEntity> &entities, bool al
|
||||
TRY_RESULT(result, clean_input_string_with_entities(text, entities));
|
||||
|
||||
// now entities are still sorted by offset and length, but not type,
|
||||
// because some characters could be deleted and some entities bacame to end together
|
||||
// because some characters could be deleted and after that some entities begin to share a common end
|
||||
|
||||
size_t last_non_whitespace_pos;
|
||||
int32 last_non_whitespace_utf16_offset;
|
||||
|
@ -30118,6 +30118,28 @@ void MessagesManager::set_poll_answer(FullMessageId full_message_id, vector<int3
|
||||
set_message_content_poll_answer(td_, m->content.get(), full_message_id, std::move(option_ids), std::move(promise));
|
||||
}
|
||||
|
||||
void MessagesManager::get_poll_voters(FullMessageId full_message_id, int32 option_id, int32 offset,
|
||||
Promise<std::pair<int32, vector<UserId>>> &&promise) {
|
||||
auto m = get_message_force(full_message_id, "get_poll_voters");
|
||||
if (m == nullptr) {
|
||||
return promise.set_error(Status::Error(5, "Message not found"));
|
||||
}
|
||||
if (!have_input_peer(full_message_id.get_dialog_id(), AccessRights::Read)) {
|
||||
return promise.set_error(Status::Error(3, "Can't access the chat"));
|
||||
}
|
||||
if (m->content->get_type() != MessageContentType::Poll) {
|
||||
return promise.set_error(Status::Error(5, "Message is not a poll"));
|
||||
}
|
||||
if (m->message_id.is_scheduled()) {
|
||||
return promise.set_error(Status::Error(5, "Can't get poll results from scheduled messages"));
|
||||
}
|
||||
if (!m->message_id.is_server()) {
|
||||
return promise.set_error(Status::Error(5, "Poll results can't be received"));
|
||||
}
|
||||
|
||||
get_message_content_poll_voters(td_, m->content.get(), full_message_id, option_id, offset, std::move(promise));
|
||||
}
|
||||
|
||||
void MessagesManager::stop_poll(FullMessageId full_message_id, td_api::object_ptr<td_api::ReplyMarkup> &&reply_markup,
|
||||
Promise<Unit> &&promise) {
|
||||
auto m = get_message_force(full_message_id, "stop_poll");
|
||||
|
@ -803,6 +803,9 @@ class MessagesManager : public Actor {
|
||||
|
||||
void set_poll_answer(FullMessageId full_message_id, vector<int32> &&option_ids, Promise<Unit> &&promise);
|
||||
|
||||
void get_poll_voters(FullMessageId full_message_id, int32 option_id, int32 offset,
|
||||
Promise<std::pair<int32, vector<UserId>>> &&promise);
|
||||
|
||||
void stop_poll(FullMessageId full_message_id, td_api::object_ptr<td_api::ReplyMarkup> &&reply_markup,
|
||||
Promise<Unit> &&promise);
|
||||
|
||||
|
@ -40,6 +40,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace td {
|
||||
|
||||
@ -84,6 +85,54 @@ class GetPollResultsQuery : public Td::ResultHandler {
|
||||
}
|
||||
};
|
||||
|
||||
class GetPollVotersQuery : public Td::ResultHandler {
|
||||
Promise<tl_object_ptr<telegram_api::messages_votesList>> promise_;
|
||||
PollId poll_id_;
|
||||
DialogId dialog_id_;
|
||||
|
||||
public:
|
||||
explicit GetPollVotersQuery(Promise<tl_object_ptr<telegram_api::messages_votesList>> &&promise)
|
||||
: promise_(std::move(promise)) {
|
||||
}
|
||||
|
||||
void send(PollId poll_id, FullMessageId full_message_id, BufferSlice &&option, const string &offset, int32 limit) {
|
||||
poll_id_ = poll_id;
|
||||
dialog_id_ = full_message_id.get_dialog_id();
|
||||
auto input_peer = td->messages_manager_->get_input_peer(dialog_id_, AccessRights::Read);
|
||||
if (input_peer == nullptr) {
|
||||
LOG(INFO) << "Can't get poll, because have no read access to " << dialog_id_;
|
||||
return promise_.set_error(Status::Error(400, "Chat is not accessible"));
|
||||
}
|
||||
|
||||
CHECK(!option.empty());
|
||||
int32 flags = telegram_api::messages_getPollVotes::OPTION_MASK;
|
||||
if (!offset.empty()) {
|
||||
flags |= telegram_api::messages_getPollVotes::OFFSET_MASK;
|
||||
}
|
||||
|
||||
auto message_id = full_message_id.get_message_id().get_server_message_id().get();
|
||||
send_query(G()->net_query_creator().create(create_storer(telegram_api::messages_getPollVotes(
|
||||
flags, std::move(input_peer), message_id, std::move(option), offset, limit))));
|
||||
}
|
||||
|
||||
void on_result(uint64 id, BufferSlice packet) override {
|
||||
auto result_ptr = fetch_result<telegram_api::messages_getPollVotes>(packet);
|
||||
if (result_ptr.is_error()) {
|
||||
return on_error(id, result_ptr.move_as_error());
|
||||
}
|
||||
|
||||
promise_.set_value(result_ptr.move_as_ok());
|
||||
}
|
||||
|
||||
void on_error(uint64 id, Status status) override {
|
||||
if (!td->messages_manager_->on_get_dialog_error(dialog_id_, status, "GetPollVotersQuery") &&
|
||||
status.message() != "MESSAGE_ID_INVALID") {
|
||||
LOG(ERROR) << "Receive " << status << ", while trying to get voters of " << poll_id_;
|
||||
}
|
||||
promise_.set_error(std::move(status));
|
||||
}
|
||||
};
|
||||
|
||||
class SetPollAnswerActor : public NetActorOnce {
|
||||
Promise<tl_object_ptr<telegram_api::Updates>> promise_;
|
||||
DialogId dialog_id_;
|
||||
@ -594,6 +643,7 @@ void PollManager::set_poll_answer(PollId poll_id, FullMessageId full_message_id,
|
||||
return promise.set_error(Status::Error(400, "Can't retract vote in a quiz"));
|
||||
}
|
||||
|
||||
std::unordered_map<size_t, int> affected_option_ids;
|
||||
vector<string> options;
|
||||
for (auto &option_id : option_ids) {
|
||||
auto index = static_cast<size_t>(option_id);
|
||||
@ -601,6 +651,18 @@ void PollManager::set_poll_answer(PollId poll_id, FullMessageId full_message_id,
|
||||
return promise.set_error(Status::Error(400, "Invalid option ID specified"));
|
||||
}
|
||||
options.push_back(poll->options[index].data);
|
||||
|
||||
affected_option_ids[index]++;
|
||||
}
|
||||
for (size_t option_index = 0; option_index < poll->options.size(); option_index++) {
|
||||
if (poll->options[option_index].is_chosen) {
|
||||
affected_option_ids[option_index]++;
|
||||
}
|
||||
}
|
||||
for (auto it : affected_option_ids) {
|
||||
if (it.second == 1) {
|
||||
invalidate_poll_option_voters(poll, poll_id, it.first);
|
||||
}
|
||||
}
|
||||
|
||||
do_set_poll_answer(poll_id, full_message_id, std::move(options), 0, std::move(promise));
|
||||
@ -733,6 +795,157 @@ void PollManager::on_set_poll_answer(PollId poll_id, uint64 generation,
|
||||
}
|
||||
}
|
||||
|
||||
void PollManager::invalidate_poll_voters(const Poll *poll, PollId poll_id) {
|
||||
if (poll->is_anonymous) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto it = poll_voters_.find(poll_id);
|
||||
if (it == poll_voters_.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto &voters : it->second) {
|
||||
voters.was_invalidated = true;
|
||||
}
|
||||
}
|
||||
|
||||
void PollManager::invalidate_poll_option_voters(const Poll *poll, PollId poll_id, size_t option_index) {
|
||||
if (poll->is_anonymous) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto it = poll_voters_.find(poll_id);
|
||||
if (it == poll_voters_.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto &poll_voters = it->second;
|
||||
CHECK(poll_voters.size() == poll->options.size());
|
||||
CHECK(option_index < poll_voters.size());
|
||||
poll_voters[option_index].was_invalidated = true;
|
||||
}
|
||||
|
||||
PollManager::PollOptionVoters &PollManager::get_poll_option_voters(const Poll *poll, PollId poll_id, int32 option_id) {
|
||||
auto &poll_voters = poll_voters_[poll_id];
|
||||
if (poll_voters.empty()) {
|
||||
poll_voters.resize(poll->options.size());
|
||||
}
|
||||
auto index = narrow_cast<size_t>(option_id);
|
||||
CHECK(index < poll_voters.size());
|
||||
return poll_voters[index];
|
||||
}
|
||||
|
||||
void PollManager::get_poll_voters(PollId poll_id, FullMessageId full_message_id, int32 option_id, int32 offset,
|
||||
Promise<std::pair<int32, vector<UserId>>> &&promise) {
|
||||
if (is_local_poll_id(poll_id)) {
|
||||
return promise.set_error(Status::Error(400, "Poll results can't be received"));
|
||||
}
|
||||
if (offset < 0) {
|
||||
return promise.set_error(Status::Error(400, "Invalid offset specified"));
|
||||
}
|
||||
|
||||
auto poll = get_poll(poll_id);
|
||||
CHECK(poll != nullptr);
|
||||
if (option_id < 0 || static_cast<size_t>(option_id) >= poll->options.size()) {
|
||||
return promise.set_error(Status::Error(400, "Invalid option ID specified"));
|
||||
}
|
||||
if (poll->is_anonymous) {
|
||||
return promise.set_error(Status::Error(400, "Poll is anonymous"));
|
||||
}
|
||||
|
||||
auto &voters = get_poll_option_voters(poll, poll_id, option_id);
|
||||
if (voters.pending_queries.empty() && voters.was_invalidated && offset == 0) {
|
||||
voters.voter_user_ids.clear();
|
||||
voters.next_offset.clear();
|
||||
voters.was_invalidated = false;
|
||||
}
|
||||
|
||||
auto cur_offset = narrow_cast<int32>(voters.voter_user_ids.size());
|
||||
|
||||
if (offset > cur_offset) {
|
||||
return promise.set_error(Status::Error(400, "Too big offset specified, voters can be received only consequently"));
|
||||
}
|
||||
if (offset < cur_offset) {
|
||||
vector<UserId> result;
|
||||
for (int32 i = offset; i != cur_offset && i - offset < MAX_GET_POLL_VOTERS; i++) {
|
||||
result.push_back(voters.voter_user_ids[i]);
|
||||
}
|
||||
return promise.set_value({poll->options[option_id].voter_count, std::move(result)});
|
||||
}
|
||||
|
||||
if (poll->options[option_id].voter_count == 0) {
|
||||
return promise.set_value({0, vector<UserId>()});
|
||||
}
|
||||
|
||||
voters.pending_queries.push_back(std::move(promise));
|
||||
if (voters.pending_queries.size() > 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto query_promise = PromiseCreator::lambda([actor_id = actor_id(this), poll_id, option_id](
|
||||
Result<tl_object_ptr<telegram_api::messages_votesList>> &&result) {
|
||||
send_closure(actor_id, &PollManager::on_get_poll_voters, poll_id, option_id, std::move(result));
|
||||
});
|
||||
td_->create_handler<GetPollVotersQuery>(std::move(query_promise))
|
||||
->send(poll_id, full_message_id, BufferSlice(poll->options[option_id].data), voters.next_offset,
|
||||
MAX_GET_POLL_VOTERS);
|
||||
}
|
||||
|
||||
void PollManager::on_get_poll_voters(PollId poll_id, int32 option_id,
|
||||
Result<tl_object_ptr<telegram_api::messages_votesList>> &&result) {
|
||||
auto poll = get_poll(poll_id);
|
||||
CHECK(poll != nullptr);
|
||||
if (option_id < 0 || static_cast<size_t>(option_id) >= poll->options.size()) {
|
||||
LOG(ERROR) << "Can't process voters for option " << option_id << " in " << poll_id << ", because it has only "
|
||||
<< poll->options.size() << " options";
|
||||
return;
|
||||
}
|
||||
if (poll->is_anonymous) {
|
||||
// just in case
|
||||
result = Status::Error(400, "Poll is anonymous");
|
||||
}
|
||||
|
||||
auto &voters = get_poll_option_voters(poll, poll_id, option_id);
|
||||
auto promises = std::move(voters.pending_queries);
|
||||
CHECK(!promises.empty());
|
||||
if (result.is_error()) {
|
||||
for (auto &promise : promises) {
|
||||
promise.set_error(result.error().clone());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
auto vote_list = result.move_as_ok();
|
||||
td_->contacts_manager_->on_get_users(std::move(vote_list->users_), "on_get_poll_voters");
|
||||
|
||||
voters.next_offset = std::move(vote_list->next_offset_);
|
||||
if (poll->options[option_id].voter_count != vote_list->count_) {
|
||||
++current_generation_;
|
||||
update_poll_timeout_.set_timeout_in(poll_id.get(), 0.0);
|
||||
}
|
||||
|
||||
vector<UserId> user_ids;
|
||||
for (auto &voter : vote_list->votes_) {
|
||||
UserId user_id(voter->user_id_);
|
||||
if (!user_id.is_valid()) {
|
||||
LOG(ERROR) << "Receive " << user_id << " as voter in " << poll_id;
|
||||
continue;
|
||||
}
|
||||
if (voter->option_ != poll->options[option_id].data) {
|
||||
LOG(ERROR) << "Receive " << user_id << " in " << poll_id << " voted for unexpected option";
|
||||
continue;
|
||||
}
|
||||
|
||||
voters.voter_user_ids.push_back(user_id);
|
||||
user_ids.push_back(user_id);
|
||||
}
|
||||
|
||||
for (auto &promise : promises) {
|
||||
promise.set_value({vote_list->count_, vector<UserId>(user_ids)});
|
||||
}
|
||||
}
|
||||
|
||||
void PollManager::stop_poll(PollId poll_id, FullMessageId full_message_id, unique_ptr<ReplyMarkup> &&reply_markup,
|
||||
Promise<Unit> &&promise) {
|
||||
if (is_local_poll_id(poll_id)) {
|
||||
@ -1010,7 +1223,8 @@ PollId PollManager::on_get_poll(PollId poll_id, tl_object_ptr<telegram_api::poll
|
||||
for (size_t i = 0; i < poll_results->results_.size(); i++) {
|
||||
auto &poll_result = poll_results->results_[i];
|
||||
Slice data = poll_result->option_.as_slice();
|
||||
for (auto &option : poll->options) {
|
||||
for (size_t option_index = 0; option_index < poll->options.size(); i++) {
|
||||
auto &option = poll->options[option_index];
|
||||
if (option.data != data) {
|
||||
continue;
|
||||
}
|
||||
@ -1028,26 +1242,28 @@ PollId PollManager::on_get_poll(PollId poll_id, tl_object_ptr<telegram_api::poll
|
||||
}
|
||||
correct_option_id = static_cast<int32>(i);
|
||||
}
|
||||
|
||||
if (poll_result->voters_ < 0) {
|
||||
LOG(ERROR) << "Receive " << poll_result->voters_ << " voters for an option in " << poll_id;
|
||||
poll_result->voters_ = 0;
|
||||
}
|
||||
if (option.is_chosen && poll_result->voters_ == 0) {
|
||||
LOG(ERROR) << "Receive 0 voters for the chosen option in " << poll_id;
|
||||
poll_result->voters_ = 1;
|
||||
}
|
||||
if (poll_result->voters_ > poll->total_voter_count) {
|
||||
LOG(ERROR) << "Have only " << poll->total_voter_count << " poll voters, but there are " << poll_result->voters_
|
||||
<< " voters for an option in " << poll_id;
|
||||
poll->total_voter_count = poll_result->voters_;
|
||||
}
|
||||
auto max_voter_count = std::numeric_limits<int32>::max() / narrow_cast<int32>(poll->options.size()) - 2;
|
||||
if (poll_result->voters_ > max_voter_count) {
|
||||
LOG(ERROR) << "Have too much " << poll_result->voters_ << " poll voters for an option in " << poll_id;
|
||||
poll_result->voters_ = max_voter_count;
|
||||
}
|
||||
if (poll_result->voters_ != option.voter_count) {
|
||||
invalidate_poll_option_voters(poll, poll_id, option_index);
|
||||
option.voter_count = poll_result->voters_;
|
||||
if (option.voter_count < 0) {
|
||||
LOG(ERROR) << "Receive " << option.voter_count << " voters for an option in " << poll_id;
|
||||
option.voter_count = 0;
|
||||
}
|
||||
if (option.is_chosen && option.voter_count == 0) {
|
||||
LOG(ERROR) << "Receive 0 voters for the chosen option in " << poll_id;
|
||||
option.voter_count = 1;
|
||||
}
|
||||
if (option.voter_count > poll->total_voter_count) {
|
||||
LOG(ERROR) << "Have only " << poll->total_voter_count << " poll voters, but there are " << option.voter_count
|
||||
<< " voters for an option in " << poll_id;
|
||||
poll->total_voter_count = option.voter_count;
|
||||
}
|
||||
auto max_voter_count = std::numeric_limits<int32>::max() / narrow_cast<int32>(poll->options.size()) - 2;
|
||||
if (option.voter_count > max_voter_count) {
|
||||
LOG(ERROR) << "Have too much " << option.voter_count << " poll voters for an option in " << poll_id;
|
||||
option.voter_count = max_voter_count;
|
||||
}
|
||||
is_changed = true;
|
||||
}
|
||||
}
|
||||
@ -1090,6 +1306,7 @@ PollId PollManager::on_get_poll(PollId poll_id, tl_object_ptr<telegram_api::poll
|
||||
}
|
||||
if (recent_voter_user_ids != poll->recent_voter_user_ids) {
|
||||
poll->recent_voter_user_ids = std::move(recent_voter_user_ids);
|
||||
invalidate_poll_voters(poll, poll_id);
|
||||
is_changed = true;
|
||||
}
|
||||
|
||||
|
@ -58,6 +58,9 @@ class PollManager : public Actor {
|
||||
void set_poll_answer(PollId poll_id, FullMessageId full_message_id, vector<int32> &&option_ids,
|
||||
Promise<Unit> &&promise);
|
||||
|
||||
void get_poll_voters(PollId poll_id, FullMessageId full_message_id, int32 option_id, int32 offset,
|
||||
Promise<std::pair<int32, vector<UserId>>> &&promise);
|
||||
|
||||
void stop_poll(PollId poll_id, FullMessageId full_message_id, unique_ptr<ReplyMarkup> &&reply_markup,
|
||||
Promise<Unit> &&promise);
|
||||
|
||||
@ -110,6 +113,15 @@ class PollManager : public Actor {
|
||||
void parse(ParserT &parser);
|
||||
};
|
||||
|
||||
struct PollOptionVoters {
|
||||
vector<UserId> voter_user_ids;
|
||||
string next_offset;
|
||||
vector<Promise<std::pair<int32, vector<UserId>>>> pending_queries;
|
||||
bool was_invalidated = false; // the list needs to be invalidated when voters are changed
|
||||
};
|
||||
|
||||
static constexpr int32 MAX_GET_POLL_VOTERS = 20; // server side limit
|
||||
|
||||
class SetPollAnswerLogEvent;
|
||||
class StopPollLogEvent;
|
||||
|
||||
@ -157,6 +169,15 @@ class PollManager : public Actor {
|
||||
|
||||
void on_set_poll_answer(PollId poll_id, uint64 generation, Result<tl_object_ptr<telegram_api::Updates>> &&result);
|
||||
|
||||
void invalidate_poll_voters(const Poll *poll, PollId poll_id);
|
||||
|
||||
void invalidate_poll_option_voters(const Poll *poll, PollId poll_id, size_t option_index);
|
||||
|
||||
PollOptionVoters &get_poll_option_voters(const Poll *poll, PollId poll_id, int32 option_id);
|
||||
|
||||
void on_get_poll_voters(PollId poll_id, int32 option_id,
|
||||
Result<tl_object_ptr<telegram_api::messages_votesList>> &&result);
|
||||
|
||||
void do_stop_poll(PollId poll_id, FullMessageId full_message_id, unique_ptr<ReplyMarkup> &&reply_markup,
|
||||
uint64 logevent_id, Promise<Unit> &&promise);
|
||||
|
||||
@ -177,6 +198,8 @@ class PollManager : public Actor {
|
||||
};
|
||||
std::unordered_map<PollId, PendingPollAnswer, PollIdHash> pending_answers_;
|
||||
|
||||
std::unordered_map<PollId, vector<PollOptionVoters>, PollIdHash> poll_voters_;
|
||||
|
||||
int64 current_local_poll_id_ = 0;
|
||||
|
||||
uint64 current_generation_ = 0;
|
||||
|
@ -7253,6 +7253,21 @@ void Td::on_request(uint64 id, td_api::setPollAnswer &request) {
|
||||
std::move(request.option_ids_), std::move(promise));
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, td_api::getPollVoters &request) {
|
||||
CHECK_IS_USER();
|
||||
CREATE_REQUEST_PROMISE();
|
||||
auto query_promise = PromiseCreator::lambda(
|
||||
[promise = std::move(promise), td = this](Result<std::pair<int32, vector<UserId>>> result) mutable {
|
||||
if (result.is_error()) {
|
||||
promise.set_error(result.move_as_error());
|
||||
} else {
|
||||
promise.set_value(td->contacts_manager_->get_users_object(result.ok().first, result.ok().second));
|
||||
}
|
||||
});
|
||||
messages_manager_->get_poll_voters({DialogId(request.chat_id_), MessageId(request.message_id_)}, request.option_id_,
|
||||
request.offset_, std::move(query_promise));
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, td_api::stopPoll &request) {
|
||||
CREATE_OK_REQUEST_PROMISE();
|
||||
messages_manager_->stop_poll({DialogId(request.chat_id_), MessageId(request.message_id_)},
|
||||
|
@ -907,6 +907,8 @@ class Td final : public NetQueryCallback {
|
||||
|
||||
void on_request(uint64 id, td_api::setPollAnswer &request);
|
||||
|
||||
void on_request(uint64 id, td_api::getPollVoters &request);
|
||||
|
||||
void on_request(uint64 id, td_api::stopPoll &request);
|
||||
|
||||
void on_request(uint64 id, const td_api::getLoginUrlInfo &request);
|
||||
|
@ -3489,6 +3489,17 @@ class CliClient final : public Actor {
|
||||
std::tie(message_id, option_ids) = split(args);
|
||||
send_request(td_api::make_object<td_api::setPollAnswer>(as_chat_id(chat_id), as_message_id(message_id),
|
||||
to_integers<int32>(option_ids)));
|
||||
} else if (op == "gpollv") {
|
||||
string chat_id;
|
||||
string message_id;
|
||||
string option_id;
|
||||
string offset;
|
||||
|
||||
std::tie(chat_id, args) = split(args);
|
||||
std::tie(message_id, args) = split(args);
|
||||
std::tie(option_id, offset) = split(args);
|
||||
send_request(td_api::make_object<td_api::getPollVoters>(as_chat_id(chat_id), as_message_id(message_id),
|
||||
to_integer<int32>(option_id), to_integer<int32>(offset)));
|
||||
} else if (op == "stoppoll") {
|
||||
string chat_id;
|
||||
string message_id;
|
||||
|
Reference in New Issue
Block a user