2021-10-20 19:56:10 +00:00
|
|
|
/*
|
|
|
|
This file is part of Telegram Desktop,
|
|
|
|
the official desktop application for the Telegram messaging service.
|
|
|
|
|
|
|
|
For license and copyright information please follow this link:
|
|
|
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|
|
|
*/
|
|
|
|
#include "api/api_polls.h"
|
|
|
|
|
|
|
|
#include "api/api_common.h"
|
|
|
|
#include "api/api_updates.h"
|
|
|
|
#include "apiwrap.h"
|
|
|
|
#include "base/random.h"
|
|
|
|
#include "data/data_changes.h"
|
|
|
|
#include "data/data_histories.h"
|
|
|
|
#include "data/data_poll.h"
|
|
|
|
#include "data/data_session.h"
|
|
|
|
#include "history/history.h"
|
|
|
|
#include "history/history_message.h" // ShouldSendSilent
|
|
|
|
#include "main/main_session.h"
|
|
|
|
|
|
|
|
namespace Api {
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
[[nodiscard]] TimeId UnixtimeFromMsgId(mtpMsgId msgId) {
|
|
|
|
return TimeId(msgId >> 32);
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
Polls::Polls(not_null<ApiWrap*> api)
|
|
|
|
: _session(&api->session())
|
|
|
|
, _api(&api->instance()) {
|
|
|
|
}
|
|
|
|
|
|
|
|
void Polls::create(
|
|
|
|
const PollData &data,
|
|
|
|
const SendAction &action,
|
|
|
|
Fn<void()> done,
|
2022-08-10 13:41:48 +00:00
|
|
|
Fn<void()> fail) {
|
2021-10-20 19:56:10 +00:00
|
|
|
_session->api().sendAction(action);
|
|
|
|
|
|
|
|
const auto history = action.history;
|
|
|
|
const auto peer = history->peer;
|
|
|
|
auto sendFlags = MTPmessages_SendMedia::Flags(0);
|
|
|
|
if (action.replyTo) {
|
|
|
|
sendFlags |= MTPmessages_SendMedia::Flag::f_reply_to_msg_id;
|
|
|
|
}
|
|
|
|
const auto clearCloudDraft = action.clearDraft;
|
|
|
|
if (clearCloudDraft) {
|
|
|
|
sendFlags |= MTPmessages_SendMedia::Flag::f_clear_draft;
|
|
|
|
history->clearLocalDraft();
|
|
|
|
history->clearCloudDraft();
|
|
|
|
history->startSavingCloudDraft();
|
|
|
|
}
|
|
|
|
const auto silentPost = ShouldSendSilent(peer, action.options);
|
|
|
|
if (silentPost) {
|
|
|
|
sendFlags |= MTPmessages_SendMedia::Flag::f_silent;
|
|
|
|
}
|
|
|
|
if (action.options.scheduled) {
|
|
|
|
sendFlags |= MTPmessages_SendMedia::Flag::f_schedule_date;
|
|
|
|
}
|
2021-11-09 15:24:13 +00:00
|
|
|
const auto sendAs = action.options.sendAs;
|
|
|
|
if (sendAs) {
|
|
|
|
sendFlags |= MTPmessages_SendMedia::Flag::f_send_as;
|
|
|
|
}
|
2021-10-20 19:56:10 +00:00
|
|
|
auto &histories = history->owner().histories();
|
2022-09-27 16:52:35 +00:00
|
|
|
const auto replyTo = action.replyTo;
|
|
|
|
const auto randomId = base::RandomValue<uint64>();
|
|
|
|
histories.sendPreparedMessage(
|
|
|
|
history,
|
|
|
|
replyTo,
|
|
|
|
randomId,
|
|
|
|
MTPmessages_SendMedia(
|
2021-10-20 19:56:10 +00:00
|
|
|
MTP_flags(sendFlags),
|
|
|
|
peer->input,
|
|
|
|
MTP_int(replyTo),
|
|
|
|
PollDataToInputMedia(&data),
|
|
|
|
MTP_string(),
|
2022-09-27 16:52:35 +00:00
|
|
|
MTP_long(randomId),
|
2021-10-20 19:56:10 +00:00
|
|
|
MTPReplyMarkup(),
|
|
|
|
MTPVector<MTPMessageEntity>(),
|
2021-11-05 12:05:11 +00:00
|
|
|
MTP_int(action.options.scheduled),
|
2021-11-09 15:24:13 +00:00
|
|
|
(sendAs ? sendAs->input : MTP_inputPeerEmpty())
|
2022-09-27 16:52:35 +00:00
|
|
|
), [=](const MTPUpdates &result, const MTP::Response &response) {
|
|
|
|
if (clearCloudDraft) {
|
|
|
|
history->finishSavingCloudDraft(
|
|
|
|
UnixtimeFromMsgId(response.outerMsgId));
|
|
|
|
}
|
|
|
|
_session->changes().historyUpdated(
|
|
|
|
history,
|
|
|
|
(action.options.scheduled
|
|
|
|
? Data::HistoryUpdate::Flag::ScheduledSent
|
|
|
|
: Data::HistoryUpdate::Flag::MessageSent));
|
|
|
|
done();
|
|
|
|
}, [=](const MTP::Error &error, const MTP::Response &response) {
|
|
|
|
if (clearCloudDraft) {
|
|
|
|
history->finishSavingCloudDraft(
|
|
|
|
UnixtimeFromMsgId(response.outerMsgId));
|
|
|
|
}
|
|
|
|
fail();
|
2021-10-20 19:56:10 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
void Polls::sendVotes(
|
|
|
|
FullMsgId itemId,
|
|
|
|
const std::vector<QByteArray> &options) {
|
|
|
|
if (_pollVotesRequestIds.contains(itemId)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const auto item = _session->data().message(itemId);
|
|
|
|
const auto media = item ? item->media() : nullptr;
|
|
|
|
const auto poll = media ? media->poll() : nullptr;
|
|
|
|
if (!item) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const auto showSending = poll && !options.empty();
|
|
|
|
const auto hideSending = [=] {
|
|
|
|
if (showSending) {
|
|
|
|
if (const auto item = _session->data().message(itemId)) {
|
|
|
|
poll->sendingVotes.clear();
|
|
|
|
_session->data().requestItemRepaint(item);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
if (showSending) {
|
|
|
|
poll->sendingVotes = options;
|
|
|
|
_session->data().requestItemRepaint(item);
|
|
|
|
}
|
|
|
|
|
|
|
|
auto prepared = QVector<MTPbytes>();
|
|
|
|
prepared.reserve(options.size());
|
|
|
|
ranges::transform(
|
|
|
|
options,
|
|
|
|
ranges::back_inserter(prepared),
|
|
|
|
[](const QByteArray &option) { return MTP_bytes(option); });
|
|
|
|
const auto requestId = _api.request(MTPmessages_SendVote(
|
|
|
|
item->history()->peer->input,
|
|
|
|
MTP_int(item->id),
|
|
|
|
MTP_vector<MTPbytes>(prepared)
|
|
|
|
)).done([=](const MTPUpdates &result) {
|
|
|
|
_pollVotesRequestIds.erase(itemId);
|
|
|
|
hideSending();
|
|
|
|
_session->updates().applyUpdates(result);
|
2021-11-26 20:46:53 +00:00
|
|
|
}).fail([=] {
|
2021-10-20 19:56:10 +00:00
|
|
|
_pollVotesRequestIds.erase(itemId);
|
|
|
|
hideSending();
|
|
|
|
}).send();
|
|
|
|
_pollVotesRequestIds.emplace(itemId, requestId);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Polls::close(not_null<HistoryItem*> item) {
|
|
|
|
const auto itemId = item->fullId();
|
|
|
|
if (_pollCloseRequestIds.contains(itemId)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const auto media = item ? item->media() : nullptr;
|
|
|
|
const auto poll = media ? media->poll() : nullptr;
|
|
|
|
if (!poll) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const auto requestId = _api.request(MTPmessages_EditMessage(
|
|
|
|
MTP_flags(MTPmessages_EditMessage::Flag::f_media),
|
|
|
|
item->history()->peer->input,
|
|
|
|
MTP_int(item->id),
|
|
|
|
MTPstring(),
|
|
|
|
PollDataToInputMedia(poll, true),
|
|
|
|
MTPReplyMarkup(),
|
|
|
|
MTPVector<MTPMessageEntity>(),
|
|
|
|
MTP_int(0) // schedule_date
|
|
|
|
)).done([=](const MTPUpdates &result) {
|
|
|
|
_pollCloseRequestIds.erase(itemId);
|
|
|
|
_session->updates().applyUpdates(result);
|
2021-11-26 20:46:53 +00:00
|
|
|
}).fail([=] {
|
2021-10-20 19:56:10 +00:00
|
|
|
_pollCloseRequestIds.erase(itemId);
|
|
|
|
}).send();
|
|
|
|
_pollCloseRequestIds.emplace(itemId, requestId);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Polls::reloadResults(not_null<HistoryItem*> item) {
|
|
|
|
const auto itemId = item->fullId();
|
2021-11-07 08:06:00 +00:00
|
|
|
if (!item->isRegular() || _pollReloadRequestIds.contains(itemId)) {
|
2021-10-20 19:56:10 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
const auto requestId = _api.request(MTPmessages_GetPollResults(
|
|
|
|
item->history()->peer->input,
|
|
|
|
MTP_int(item->id)
|
|
|
|
)).done([=](const MTPUpdates &result) {
|
|
|
|
_pollReloadRequestIds.erase(itemId);
|
|
|
|
_session->updates().applyUpdates(result);
|
2021-11-26 20:46:53 +00:00
|
|
|
}).fail([=] {
|
2021-10-20 19:56:10 +00:00
|
|
|
_pollReloadRequestIds.erase(itemId);
|
|
|
|
}).send();
|
|
|
|
_pollReloadRequestIds.emplace(itemId, requestId);
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace Api
|