From c71dbc28a05bb39a64679601e1cddcec39d5a9e9 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 9 Aug 2019 17:41:26 +0300 Subject: [PATCH] Add send_copy parameter to forwardMessages. GitOrigin-RevId: 059f992cc8b9c6ae1c6ab3910ffc52b906d12e88 --- td/generate/scheme/td_api.tl | 4 +- td/generate/scheme/td_api.tlo | Bin 157136 -> 157212 bytes td/telegram/MessageContent.cpp | 41 +++++++++-- td/telegram/MessageContent.h | 6 +- td/telegram/MessagesManager.cpp | 117 ++++++++++++++++++++------------ td/telegram/MessagesManager.h | 4 +- td/telegram/Td.cpp | 3 +- td/telegram/cli.cpp | 7 +- 8 files changed, 124 insertions(+), 58 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 5c8fadfe..a4fd5ad3 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -3102,7 +3102,9 @@ sendInlineQueryResultMessage chat_id:int53 reply_to_message_id:int53 disable_not //@chat_id Identifier of the chat to which to forward messages @from_chat_id Identifier of the chat from which to forward messages @message_ids Identifiers of the messages to forward //@disable_notification Pass true to disable notification for the message, doesn't work if messages are forwarded to a secret chat @from_background Pass true if the messages are sent from the background //@as_album True, if the messages should be grouped into an album after forwarding. For this to work, no more than 10 messages may be forwarded, and all of them must be photo or video messages -forwardMessages chat_id:int53 from_chat_id:int53 message_ids:vector disable_notification:Bool from_background:Bool as_album:Bool = Messages; +//@send_copy True, if content of the messages needs to be copied without links to the original messages. Always true if the messages are forwarded to a secret chat +//@remove_caption True, if media captions of message copies needs to be removed. Ignored if send_copy is false +forwardMessages chat_id:int53 from_chat_id:int53 message_ids:vector disable_notification:Bool from_background:Bool as_album:Bool send_copy:Bool remove_caption:Bool = Messages; //@description Changes the current TTL setting (sets a new self-destruct timer) in a secret chat and sends the corresponding message @chat_id Chat identifier @ttl New TTL value, in seconds sendChatSetTtlMessage chat_id:int53 ttl:int32 = Message; diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index 37dc47e58a665e46bb0e9b04c97891021da6e356..18347e838aa0115944a94ff7cdab198434f756d7 100644 GIT binary patch delta 81 zcmV-X0IvVg%L$y!34pW#Z0ZEJ*Clk9aOwdV0SJ>(TPK&W>H*l7FmM3{2yVEWnW`qaCB*JZUB>TLL9e{>j6M|Jx3o+ delta 46 zcmV+}0MY-P%n8uT34pW#Z0ZC=NcG>BaOwdVm(=nBD3`G60oaqUX$Y54Fai*_?CSwA EdJ;_)wEzGB diff --git a/td/telegram/MessageContent.cpp b/td/telegram/MessageContent.cpp index e7dcad17..90ad6bea 100644 --- a/td/telegram/MessageContent.cpp +++ b/td/telegram/MessageContent.cpp @@ -2898,7 +2898,7 @@ void merge_message_contents(Td *td, const MessageContent *old_content, MessageCo } new_photo->photos.push_back(old_photo->photos.back()); - FileId old_file_id = get_message_content_file_id(old_content); + FileId old_file_id = get_message_content_upload_file_id(old_content); FileView old_file_view = td->file_manager_->get_file_view(old_file_id); FileId new_file_id = new_photo->photos[0].file_id; FileView new_file_view = td->file_manager_->get_file_view(new_file_id); @@ -3903,7 +3903,7 @@ unique_ptr get_message_content(Td *td, FormattedText message, } unique_ptr dup_message_content(Td *td, DialogId dialog_id, const MessageContent *content, - bool for_forward) { + bool for_forward, bool remove_caption) { CHECK(content != nullptr); bool to_secret = dialog_id.get_type() == DialogType::SecretChat; @@ -3926,6 +3926,9 @@ unique_ptr dup_message_content(Td *td, DialogId dialog_id, const switch (content->get_type()) { case MessageContentType::Animation: { auto result = make_unique(*static_cast(content)); + if (remove_caption) { + result->caption = FormattedText(); + } if (td->documents_manager_->has_input_media(result->file_id, thumbnail_file_id, to_secret)) { return std::move(result); } @@ -3935,6 +3938,9 @@ unique_ptr dup_message_content(Td *td, DialogId dialog_id, const } case MessageContentType::Audio: { auto result = make_unique(*static_cast(content)); + if (remove_caption) { + result->caption = FormattedText(); + } if (td->documents_manager_->has_input_media(result->file_id, thumbnail_file_id, to_secret)) { return std::move(result); } @@ -3946,6 +3952,9 @@ unique_ptr dup_message_content(Td *td, DialogId dialog_id, const return make_unique(*static_cast(content)); case MessageContentType::Document: { auto result = make_unique(*static_cast(content)); + if (remove_caption) { + result->caption = FormattedText(); + } if (td->documents_manager_->has_input_media(result->file_id, thumbnail_file_id, to_secret)) { return std::move(result); } @@ -3967,6 +3976,9 @@ unique_ptr dup_message_content(Td *td, DialogId dialog_id, const return make_unique(*static_cast(content)); case MessageContentType::Photo: { auto result = make_unique(*static_cast(content)); + if (remove_caption) { + result->caption = FormattedText(); + } if (result->photo.photos.size() > 2 && !to_secret) { // already sent photo @@ -4037,6 +4049,9 @@ unique_ptr dup_message_content(Td *td, DialogId dialog_id, const return make_unique(*static_cast(content)); case MessageContentType::Video: { auto result = make_unique(*static_cast(content)); + if (remove_caption) { + result->caption = FormattedText(); + } if (td->documents_manager_->has_input_media(result->file_id, thumbnail_file_id, to_secret)) { return std::move(result); } @@ -4056,6 +4071,9 @@ unique_ptr dup_message_content(Td *td, DialogId dialog_id, const } case MessageContentType::VoiceNote: { auto result = make_unique(*static_cast(content)); + if (remove_caption) { + result->caption = FormattedText(); + } result->is_listened = false; if (td->documents_manager_->has_input_media(result->file_id, thumbnail_file_id, to_secret)) { return std::move(result); @@ -4526,7 +4544,7 @@ int32 get_message_content_duration(const MessageContent *content, const Td *td) } } -FileId get_message_content_file_id(const MessageContent *content) { +FileId get_message_content_upload_file_id(const MessageContent *content) { switch (content->get_type()) { case MessageContentType::Animation: return static_cast(content)->file_id; @@ -4555,6 +4573,17 @@ FileId get_message_content_file_id(const MessageContent *content) { return FileId(); } +FileId get_message_content_any_file_id(const MessageContent *content) { + FileId result = get_message_content_upload_file_id(content); + if (!result.is_valid() && content->get_type() == MessageContentType::Photo) { + const auto &sizes = static_cast(content)->photo.photos; + if (!sizes.empty()) { + result = sizes.back().file_id; + } + } + return result; +} + void update_message_content_file_id_remote(MessageContent *content, FileId file_id) { if (file_id.get_remote() == 0) { return; @@ -4629,7 +4658,7 @@ vector get_message_content_file_ids(const MessageContent *content, const case MessageContentType::VoiceNote: { vector result; result.reserve(2); - FileId file_id = get_message_content_file_id(content); + FileId file_id = get_message_content_upload_file_id(content); if (file_id.is_valid()) { result.push_back(file_id); } @@ -4945,9 +4974,9 @@ void add_message_content_dependencies(Dependencies &dependencies, const MessageC void on_sent_message_content(Td *td, const MessageContent *content) { switch (content->get_type()) { case MessageContentType::Animation: - return td->animations_manager_->add_saved_animation_by_id(get_message_content_file_id(content)); + return td->animations_manager_->add_saved_animation_by_id(get_message_content_any_file_id(content)); case MessageContentType::Sticker: - return td->stickers_manager_->add_recent_sticker_by_id(false, get_message_content_file_id(content)); + return td->stickers_manager_->add_recent_sticker_by_id(false, get_message_content_any_file_id(content)); default: // nothing to do return; diff --git a/td/telegram/MessageContent.h b/td/telegram/MessageContent.h index 9dde973f..15dbbed8 100644 --- a/td/telegram/MessageContent.h +++ b/td/telegram/MessageContent.h @@ -211,7 +211,7 @@ unique_ptr get_message_content(Td *td, FormattedText message_tex int32 *ttl); unique_ptr dup_message_content(Td *td, DialogId dialog_id, const MessageContent *content, - bool for_forward); + bool for_forward, bool remove_caption = false); unique_ptr get_action_message_content(Td *td, tl_object_ptr &&action, DialogId owner_dialog_id, MessageId reply_to_message_id); @@ -225,7 +225,9 @@ const FormattedText *get_message_content_caption(const MessageContent *content); int32 get_message_content_duration(const MessageContent *content, const Td *td); -FileId get_message_content_file_id(const MessageContent *content); +FileId get_message_content_upload_file_id(const MessageContent *content); + +FileId get_message_content_any_file_id(const MessageContent *content); void update_message_content_file_id_remote(MessageContent *content, FileId file_id); diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index b663b08e..87701f4d 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -9387,7 +9387,7 @@ void MessagesManager::on_send_secret_message_error(int64 random_id, Status error auto full_message_id = it->second; auto *m = get_message(full_message_id); if (m != nullptr) { - auto file_id = get_message_content_file_id(m->content.get()); + auto file_id = get_message_content_upload_file_id(m->content.get()); if (file_id.is_valid()) { if (G()->close_flag() && G()->parameters().use_message_db) { // do not send error, message will be re-sent @@ -15986,7 +15986,7 @@ vector MessagesManager::get_message_file_ids(const Message *m) const { } void MessagesManager::cancel_upload_message_content_files(const MessageContent *content) { - auto file_id = get_message_content_file_id(content); + auto file_id = get_message_content_upload_file_id(content); // always cancel file upload, it should be a no-op in the worst case if (being_uploaded_files_.erase(file_id) || file_id.is_valid()) { cancel_upload_file(file_id); @@ -16377,7 +16377,7 @@ void MessagesManager::do_send_message(DialogId dialog_id, Message *m, vectorfile_manager_->get_file_view(file_id); FileId thumbnail_file_id = get_message_content_thumbnail_file_id(content, td_); LOG(DEBUG) << "Need to send file " << file_id << " with thumbnail " << thumbnail_file_id; @@ -16701,7 +16701,7 @@ void MessagesManager::do_send_message_group(int64 media_album_id) { reply_to_message_id = m->reply_to_message_id; flags = get_message_flags(m); - file_ids.push_back(get_message_content_file_id(m->content.get())); + file_ids.push_back(get_message_content_any_file_id(m->content.get())); random_ids.push_back(begin_send_message(dialog_id, m)); LOG(INFO) << "Have file " << file_ids.back() << " in " << m->message_id << " with result " << request.results[i] @@ -16716,7 +16716,7 @@ void MessagesManager::do_send_message_group(int64 media_album_id) { auto input_media = get_input_media(m->content.get(), td_, m->ttl, true); if (input_media == nullptr) { // TODO return CHECK - auto file_id = get_message_content_file_id(m->content.get()); + auto file_id = get_message_content_any_file_id(m->content.get()); auto file_view = td_->file_manager_->get_file_view(file_id); bool has_remote = file_view.has_remote_location(); bool is_web = has_remote ? file_view.remote_location().is_web() : false; @@ -18316,7 +18316,7 @@ Result MessagesManager::forward_message(DialogId to_dialog_id, Dialog bool disable_notification, bool from_background, bool in_game_share) { TRY_RESULT(result, forward_messages(to_dialog_id, from_dialog_id, {message_id}, disable_notification, from_background, - in_game_share, false)); + in_game_share, false, false, false)); CHECK(result.size() == 1); auto sent_message_id = result[0]; if (sent_message_id == MessageId()) { @@ -18327,7 +18327,8 @@ Result MessagesManager::forward_message(DialogId to_dialog_id, Dialog Result> MessagesManager::forward_messages(DialogId to_dialog_id, DialogId from_dialog_id, vector message_ids, bool disable_notification, - bool from_background, bool in_game_share, bool as_album) { + bool from_background, bool in_game_share, bool as_album, + bool send_copy, bool remove_caption) { if (message_ids.size() > 100) { // TODO replace with const from config or implement mass-forward return Status::Error(4, "Too much messages to forward"); } @@ -18359,20 +18360,19 @@ Result> MessagesManager::forward_messages(DialogId to_dialog_i } } - int64 media_album_id = 0; - if (as_album && message_ids.size() > 1 && message_ids.size() <= MAX_GROUPED_MESSAGES) { - do { - media_album_id = Random::secure_int64(); - } while (media_album_id >= 0 || pending_message_group_sends_.count(media_album_id) != 0); - } - bool to_secret = to_dialog_id.get_type() == DialogType::SecretChat; vector result(message_ids.size()); vector forwarded_messages; vector forwarded_message_ids; - vector> unforwarded_message_contents(message_ids.size()); - vector unforwarded_message_disable_web_page_previews(message_ids.size()); + + struct CopiedMessage { + unique_ptr content; + bool disable_web_page_preview; + size_t index; + }; + vector copied_messages; + auto my_id = td_->contacts_manager_->get_my_id(); bool need_update_dialog_pos = false; for (size_t i = 0; i < message_ids.size(); i++) { @@ -18389,32 +18389,26 @@ Result> MessagesManager::forward_messages(DialogId to_dialog_i continue; } - unique_ptr content = dup_message_content(td_, to_dialog_id, forwarded_message->content.get(), true); + bool need_copy = !message_id.is_server() || to_secret || send_copy; + unique_ptr content = + dup_message_content(td_, to_dialog_id, forwarded_message->content.get(), true, need_copy && remove_caption); if (content == nullptr) { LOG(INFO) << "Can't forward " << message_id; continue; } - auto can_send_status = can_send_message_content(to_dialog_id, content.get(), true); + auto can_send_status = can_send_message_content(to_dialog_id, content.get(), !need_copy); if (can_send_status.is_error()) { LOG(INFO) << "Can't forward " << message_id << ": " << can_send_status.message(); continue; } - if (!message_id.is_server() || to_secret) { - unforwarded_message_contents[i] = std::move(content); - unforwarded_message_disable_web_page_previews[i] = forwarded_message->disable_web_page_preview; + if (need_copy) { + copied_messages.push_back({std::move(content), forwarded_message->disable_web_page_preview, i}); continue; } auto content_type = content->get_type(); - if (media_album_id != 0 && !is_allowed_media_group_content(content_type)) { - media_album_id = 0; - for (auto m : forwarded_messages) { - m->media_album_id = 0; - } - } - bool is_game = content_type == MessageContentType::Game; unique_ptr forward_info; if (!is_game && content_type != MessageContentType::Audio) { @@ -18457,7 +18451,6 @@ Result> MessagesManager::forward_messages(DialogId to_dialog_i &need_update_dialog_pos, std::move(forward_info)); m->debug_forward_from = from_dialog_id; m->via_bot_user_id = forwarded_message->via_bot_user_id; - m->media_album_id = media_album_id; m->in_game_share = in_game_share; if (forwarded_message->views > 0 && m->forward_info != nullptr) { m->views = forwarded_message->views; @@ -18507,26 +18500,64 @@ Result> MessagesManager::forward_messages(DialogId to_dialog_i result[i] = m->message_id; forwarded_messages.push_back(m); forwarded_message_ids.push_back(message_id); - - send_update_new_message(to_dialog, m); } if (!forwarded_messages.empty()) { + if (as_album && forwarded_messages.size() > 1 && forwarded_messages.size() <= MAX_GROUPED_MESSAGES) { + bool allow_album = true; + for (auto m : forwarded_messages) { + if (!is_allowed_media_group_content(m->content->get_type())) { + allow_album = false; + break; + } + } + + if (allow_album) { + int64 media_album_id = 0; + do { + media_album_id = Random::secure_int64(); + } while (media_album_id >= 0 || pending_message_group_sends_.count(media_album_id) != 0); + + for (auto m : forwarded_messages) { + m->media_album_id = media_album_id; + } + } + } + + for (auto m : forwarded_messages) { + send_update_new_message(to_dialog, m); + } + do_forward_messages(to_dialog_id, from_dialog_id, forwarded_messages, forwarded_message_ids, 0); } - for (size_t i = 0; i < unforwarded_message_contents.size(); i++) { - if (unforwarded_message_contents[i] != nullptr) { - Message *m = get_message_to_send(to_dialog, MessageId(), disable_notification, from_background, - std::move(unforwarded_message_contents[i]), &need_update_dialog_pos); - m->disable_web_page_preview = unforwarded_message_disable_web_page_previews[i]; - if (to_secret) { - m->media_album_id = media_album_id; + if (!copied_messages.empty()) { + int64 media_album_id = 0; + if (as_album && copied_messages.size() > 1 && copied_messages.size() <= MAX_GROUPED_MESSAGES) { + bool allow_album = true; + for (auto &copied_message : copied_messages) { + if (!is_allowed_media_group_content(copied_message.content->get_type())) { + allow_album = false; + break; + } } + if (allow_album) { + do { + media_album_id = Random::secure_int64(); + } while (media_album_id >= 0 || pending_message_group_sends_.count(media_album_id) != 0); + } + } + + for (auto &copied_message : copied_messages) { + Message *m = get_message_to_send(to_dialog, MessageId(), disable_notification, from_background, + std::move(copied_message.content), &need_update_dialog_pos); + m->disable_web_page_preview = copied_message.disable_web_page_preview; + m->media_album_id = media_album_id; + save_send_message_logevent(to_dialog_id, m); do_send_message(to_dialog_id, m); - result[i] = m->message_id; + result[copied_message.index] = m->message_id; send_update_new_message(to_dialog, m); } @@ -21592,7 +21623,7 @@ void MessagesManager::on_send_dialog_action_timeout(DialogId dialog_id) { return; } - auto file_id = get_message_content_file_id(m->content.get()); + auto file_id = get_message_content_upload_file_id(m->content.get()); if (!file_id.is_valid()) { LOG(ERROR) << "Have no file in " << to_string(get_message_content_object(m->content.get(), td_, m->date, m->is_content_secret)); @@ -24176,7 +24207,7 @@ bool MessagesManager::update_message_content(DialogId dialog_id, Message *old_me MessageContentType old_content_type = old_content->get_type(); MessageContentType new_content_type = new_content->get_type(); - auto old_file_id = get_message_content_file_id(old_content.get()); + auto old_file_id = get_message_content_any_file_id(old_content.get()); bool need_finish_upload = old_file_id.is_valid() && need_merge_files; if (old_content_type != new_content_type) { need_update = true; @@ -24185,7 +24216,7 @@ bool MessagesManager::update_message_content(DialogId dialog_id, Message *old_me old_message->is_content_secret = is_secret_message_content(old_message->ttl, new_content->get_type()); if (need_merge_files && old_file_id.is_valid()) { - auto new_file_id = get_message_content_file_id(new_content.get()); + auto new_file_id = get_message_content_any_file_id(new_content.get()); if (new_file_id.is_valid()) { FileView old_file_view = td_->file_manager_->get_file_view(old_file_id); FileView new_file_view = td_->file_manager_->get_file_view(new_file_id); @@ -24242,7 +24273,7 @@ bool MessagesManager::update_message_content(DialogId dialog_id, Message *old_me } update_message_content_file_id_remote(old_content.get(), old_file_id); } else { - update_message_content_file_id_remote(old_content.get(), get_message_content_file_id(new_content.get())); + update_message_content_file_id_remote(old_content.get(), get_message_content_any_file_id(new_content.get())); } if (is_content_changed && !need_update) { LOG(INFO) << "Content of " << old_message->message_id << " in " << dialog_id << " has changed"; diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 0872b4d5..d87494be 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -348,8 +348,8 @@ class MessagesManager : public Actor { Result> forward_messages(DialogId to_dialog_id, DialogId from_dialog_id, vector message_ids, bool disable_notification, - bool from_background, bool in_game_share, - bool as_album) TD_WARN_UNUSED_RESULT; + bool from_background, bool in_game_share, bool as_album, bool send_copy, + bool remove_caption) TD_WARN_UNUSED_RESULT; Result send_dialog_set_ttl_message(DialogId dialog_id, int32 ttl); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 9eb9d3f4..edb8d768 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -5821,7 +5821,8 @@ void Td::on_request(uint64 id, const td_api::forwardMessages &request) { DialogId dialog_id(request.chat_id_); auto r_message_ids = messages_manager_->forward_messages( dialog_id, DialogId(request.from_chat_id_), MessagesManager::get_message_ids(request.message_ids_), - request.disable_notification_, request.from_background_, false, request.as_album_); + request.disable_notification_, request.from_background_, false, request.as_album_, request.send_copy_, + request.remove_caption_); if (r_message_ids.is_error()) { return send_closure(actor_id(this), &Td::send_error, id, r_message_ids.move_as_error()); } diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 8a3455f6..60abcdfb 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -2454,7 +2454,7 @@ class CliClient final : public Actor { send_request(td_api::make_object(as_chat_id(chat_id), as_message_ids(message_ids, ','), as_bool(revoke))); - } else if (op == "fm" || op == "fmg") { + } else if (op == "fm" || op == "fmg" || op == "cm" || op == "cmg") { string chat_id; string from_chat_id; string message_ids; @@ -2462,8 +2462,9 @@ class CliClient final : public Actor { std::tie(from_chat_id, message_ids) = split(args); auto chat = as_chat_id(chat_id); - send_request(td_api::make_object( - chat, as_chat_id(from_chat_id), as_message_ids(message_ids), false, false, op == "fmg")); + send_request(td_api::make_object(chat, as_chat_id(from_chat_id), + as_message_ids(message_ids), false, false, op[2] == 'g', + op[0] == 'c', static_cast(Random::fast(0, 1)))); } else if (op == "csc" || op == "CreateSecretChat") { send_request(td_api::make_object(as_secret_chat_id(args))); } else if (op == "cnsc" || op == "CreateNewSecretChat") {