193 lines
		
	
	
	
		
			5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			193 lines
		
	
	
	
		
			5 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) {
 | |
| 	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;
 | |
| 
 | |
| 	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 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;
 | |
| 	}
 | |
| 	bool channelPost = peer->isChannel() && !peer->isMegagroup();
 | |
| 	bool silentPost = 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,
 | |
| 		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);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| } // namespace
 | |
| 
 | |
| void SendExistingDocument(
 | |
| 		not_null<History*> history,
 | |
| 		not_null<DocumentData*> document) {
 | |
| 	SendExistingDocument(history, document, {});
 | |
| }
 | |
| 
 | |
| void SendExistingDocument(
 | |
| 		not_null<History*> history,
 | |
| 		not_null<DocumentData*> document,
 | |
| 		TextWithEntities caption,
 | |
| 		MsgId replyToId) {
 | |
| 	SendExistingMedia(
 | |
| 		history,
 | |
| 		document,
 | |
| 		MTP_inputMediaDocument(
 | |
| 			MTP_flags(0),
 | |
| 			document->mtpInput(),
 | |
| 			MTPint()),
 | |
| 		document->stickerOrGifOrigin(),
 | |
| 		caption,
 | |
| 		replyToId);
 | |
| 
 | |
| 	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) {
 | |
| 	SendExistingPhoto(history, photo, {});
 | |
| }
 | |
| 
 | |
| void SendExistingPhoto(
 | |
| 		not_null<History*> history,
 | |
| 		not_null<PhotoData*> photo,
 | |
| 		TextWithEntities caption,
 | |
| 		MsgId replyToId) {
 | |
| 	SendExistingMedia(
 | |
| 		history,
 | |
| 		photo,
 | |
| 		MTP_inputMediaPhoto(
 | |
| 			MTP_flags(0),
 | |
| 			photo->mtpInput(),
 | |
| 			MTPint()),
 | |
| 		Data::FileOrigin(),
 | |
| 		caption,
 | |
| 		replyToId);
 | |
| }
 | |
| 
 | |
| } // namespace Api
 | 
