tdesktop/Telegram/SourceFiles/api/api_sending.cpp

205 lines
5.2 KiB
C++

/*
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_sending.h"
#include "base/unixtime.h"
#include "data/data_document.h"
#include "data/data_photo.h"
#include "data/data_channel.h" // ChannelData::addsSignature.
#include "data/data_user.h" // App::peerName(UserData*).
#include "data/data_session.h"
#include "data/data_file_origin.h"
#include "history/history.h"
#include "history/history_message.h" // NewMessageFlags.
#include "ui/text/text_entity.h" // TextWithEntities.
#include "main/main_session.h"
#include "mainwidget.h"
#include "apiwrap.h"
namespace Api {
namespace {
template <typename MediaData>
void SendExistingMedia(
not_null<History*> history,
not_null<MediaData*> media,
const MTPInputMedia &inputMedia,
Data::FileOrigin origin,
TextWithEntities caption,
MsgId replyToId,
bool silent) {
const auto peer = history->peer;
const auto session = &history->session();
const auto api = &session->api();
auto options = ApiWrap::SendOptions(history);
options.clearDraft = false;
options.replyTo = replyToId;
options.generateLocal = true;
options.silent = silent;
api->sendAction(options);
const auto newId = FullMsgId(peerToChannel(peer->id), clientMsgId());
const auto randomId = rand_value<uint64>();
auto flags = NewMessageFlags(peer) | MTPDmessage::Flag::f_media;
auto clientFlags = NewMessageClientFlags();
auto sendFlags = MTPmessages_SendMedia::Flags(0);
if (options.replyTo) {
flags |= MTPDmessage::Flag::f_reply_to_msg_id;
sendFlags |= MTPmessages_SendMedia::Flag::f_reply_to_msg_id;
}
const auto channelPost = peer->isChannel() && !peer->isMegagroup();
const auto silentPost = options.silent
|| (channelPost && session->data().notifySilentPosts(peer));
if (channelPost) {
flags |= MTPDmessage::Flag::f_views;
flags |= MTPDmessage::Flag::f_post;
}
if (!channelPost) {
flags |= MTPDmessage::Flag::f_from_id;
} else if (peer->asChannel()->addsSignature()) {
flags |= MTPDmessage::Flag::f_post_author;
}
if (silentPost) {
sendFlags |= MTPmessages_SendMedia::Flag::f_silent;
}
auto messageFromId = channelPost ? 0 : session->userId();
auto messagePostAuthor = channelPost
? App::peerName(session->user())
: QString();
TextUtilities::Trim(caption);
auto sentEntities = TextUtilities::EntitiesToMTP(
caption.entities,
TextUtilities::ConvertOption::SkipLocal);
if (!sentEntities.v.isEmpty()) {
sendFlags |= MTPmessages_SendMedia::Flag::f_entities;
}
const auto replyTo = options.replyTo;
const auto captionText = caption.text;
session->data().registerMessageRandomId(randomId, newId);
history->addNewLocalMessage(
newId.msg,
flags,
clientFlags,
0,
replyTo,
base::unixtime::now(),
messageFromId,
messagePostAuthor,
media,
caption,
MTPReplyMarkup());
auto failHandler = std::make_shared<Fn<void(const RPCError&, QByteArray)>>();
auto performRequest = [=] {
const auto usedFileReference = media->fileReference();
history->sendRequestId = api->request(MTPmessages_SendMedia(
MTP_flags(sendFlags),
peer->input,
MTP_int(replyTo),
inputMedia,
MTP_string(captionText),
MTP_long(randomId),
MTPReplyMarkup(),
sentEntities
)).done([=](const MTPUpdates &result) {
api->applyUpdates(result, randomId);
}).fail([=](const RPCError &error) {
(*failHandler)(error, usedFileReference);
}).afterRequest(history->sendRequestId
).send();
};
*failHandler = [=](const RPCError &error, QByteArray usedFileReference) {
if (error.code() == 400
&& error.type().startsWith(qstr("FILE_REFERENCE_"))) {
api->refreshFileReference(origin, [=](const auto &result) {
if (media->fileReference() != usedFileReference) {
performRequest();
} else {
api->sendMessageFail(error, peer, newId);
}
});
} else {
api->sendMessageFail(error, peer, newId);
}
};
performRequest();
if (const auto main = App::main()) {
main->finishForwarding(history, options.silent);
}
}
} // namespace
void SendExistingDocument(
not_null<History*> history,
not_null<DocumentData*> document,
bool silent) {
SendExistingDocument(history, document, {}, 0, silent);
}
void SendExistingDocument(
not_null<History*> history,
not_null<DocumentData*> document,
TextWithEntities caption,
MsgId replyToId,
bool silent) {
SendExistingMedia(
history,
document,
MTP_inputMediaDocument(
MTP_flags(0),
document->mtpInput(),
MTPint()),
document->stickerOrGifOrigin(),
caption,
replyToId,
silent);
if (document->sticker()) {
if (const auto main = App::main()) {
main->incrementSticker(document);
document->session().data().notifyRecentStickersUpdated();
}
}
}
void SendExistingPhoto(
not_null<History*> history,
not_null<PhotoData*> photo,
bool silent) {
SendExistingPhoto(history, photo, {}, 0, silent);
}
void SendExistingPhoto(
not_null<History*> history,
not_null<PhotoData*> photo,
TextWithEntities caption,
MsgId replyToId,
bool silent) {
SendExistingMedia(
history,
photo,
MTP_inputMediaPhoto(
MTP_flags(0),
photo->mtpInput(),
MTPint()),
Data::FileOrigin(),
caption,
replyToId,
silent);
}
} // namespace Api