Add MessageCopyOptions.

GitOrigin-RevId: a61b93c3c215c42c9a7f30195cc637187472751e
This commit is contained in:
levlam 2020-08-09 14:18:08 +03:00
parent 983119ada3
commit a404948707
12 changed files with 122 additions and 48 deletions

View File

@ -610,6 +610,7 @@ set(TDLIB_SOURCE
td/telegram/Logging.h
td/telegram/MessageContent.h
td/telegram/MessageContentType.h
td/telegram/MessageCopyOptions.h
td/telegram/MessageEntity.h
td/telegram/MessageId.h
td/telegram/MessagesDb.h

View File

@ -274,6 +274,7 @@ function split_file($file, $chunks, $undo) {
'inline_queries_manager[_(-][^.]|InlineQueriesManager' => 'InlineQueriesManager',
'language_pack_manager[_(-][^.]|LanguagePackManager' => 'LanguagePackManager',
'get_erase_logevent_promise|parse_time|store_time' => 'logevent/LogEventHelper',
'MessageCopyOptions' => 'MessageCopyOptions',
'messages_manager[_(-][^.]|MessagesManager' => 'MessagesManager',
'notification_manager[_(-][^.]|NotificationManager|notifications[)]' => 'NotificationManager',
'PublicDialogType|get_public_dialog_type' => 'PublicDialogType',

View File

@ -1689,6 +1689,11 @@ messageSchedulingStateSendWhenOnline = MessageSchedulingState;
//@scheduling_state Message scheduling state. Messages sent to a secret chat, live location messages and self-destructing messages can't be scheduled
sendMessageOptions disable_notification:Bool from_background:Bool scheduling_state:MessageSchedulingState = SendMessageOptions;
//@description Options to be used when a message content is copied without a link to the original message
//@send_copy True, if content of the message needs to be copied without a link to the original message. Always true if the message is forwarded to a secret chat
//@remove_caption True, if media caption of the message copy needs to be removed. Ignored if send_copy is false
messageCopyOptions send_copy:Bool remove_caption:Bool = MessageCopyOptions;
//@class InputMessageContent @description The content of a message to send
@ -1753,9 +1758,8 @@ inputMessagePoll question:string options:vector<string> is_anonymous:Bool type:P
//@description A forwarded message @from_chat_id Identifier for the chat this forwarded message came from @message_id Identifier of the message to forward
//@in_game_share True, if a game message should be shared within a launched game; applies only to game messages
//@send_copy True, if content of the message needs to be copied without a link to the original message. Always true if the message is forwarded to a secret chat
//@remove_caption True, if media caption of the message copy needs to be removed. Ignored if send_copy is false
inputMessageForwarded from_chat_id:int53 message_id:int53 in_game_share:Bool send_copy:Bool remove_caption:Bool = InputMessageContent;
//@copy_options Options to be used to copy content of the message without a link to the original message
inputMessageForwarded from_chat_id:int53 message_id:int53 in_game_share:Bool copy_options:messageCopyOptions = InputMessageContent;
//@class SearchMessagesFilter @description Represents a filter for message search results

Binary file not shown.

View File

@ -3937,8 +3937,11 @@ unique_ptr<MessageContent> get_message_content(Td *td, FormattedText message,
}
unique_ptr<MessageContent> dup_message_content(Td *td, DialogId dialog_id, const MessageContent *content,
MessageContentDupType type) {
MessageContentDupType type, MessageCopyOptions &&copy_options) {
CHECK(content != nullptr);
if (copy_options.send_copy) {
CHECK(type == MessageContentDupType::Copy);
}
if (type != MessageContentDupType::Forward && type != MessageContentDupType::SendViaBot &&
!can_have_input_media(td, content)) {
return nullptr;
@ -3961,7 +3964,7 @@ unique_ptr<MessageContent> dup_message_content(Td *td, DialogId dialog_id, const
if (to_secret) {
thumbnail_file_id = get_message_content_thumbnail_file_id(content, td);
}
auto remove_caption = type == MessageContentDupType::CopyWithoutCaption;
auto remove_caption = type == MessageContentDupType::Copy && copy_options.remove_caption;
switch (content->get_type()) {
case MessageContentType::Animation: {
auto result = make_unique<MessageAnimation>(*static_cast<const MessageAnimation *>(content));

View File

@ -12,6 +12,7 @@
#include "td/telegram/FullMessageId.h"
#include "td/telegram/logevent/LogEvent.h"
#include "td/telegram/MessageContentType.h"
#include "td/telegram/MessageCopyOptions.h"
#include "td/telegram/MessageEntity.h"
#include "td/telegram/MessageId.h"
#include "td/telegram/Photo.h"
@ -174,10 +175,10 @@ unique_ptr<MessageContent> get_message_content(Td *td, FormattedText message_tex
DialogId owner_dialog_id, bool is_content_read, UserId via_bot_user_id,
int32 *ttl);
enum class MessageContentDupType : int32 { Send, SendViaBot, Forward, Copy, CopyWithoutCaption };
enum class MessageContentDupType : int32 { Send, SendViaBot, Forward, Copy };
unique_ptr<MessageContent> dup_message_content(Td *td, DialogId dialog_id, const MessageContent *content,
MessageContentDupType type);
MessageContentDupType type, MessageCopyOptions &&copy_options);
unique_ptr<MessageContent> get_action_message_content(Td *td, tl_object_ptr<telegram_api::MessageAction> &&action,
DialogId owner_dialog_id, MessageId reply_to_message_id);

View File

@ -0,0 +1,30 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2020
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/utils/common.h"
#include "td/utils/StringBuilder.h"
namespace td {
struct MessageCopyOptions {
bool send_copy = false;
bool remove_caption = false;
MessageCopyOptions() = default;
MessageCopyOptions(bool send_copy, bool remove_caption): send_copy(send_copy), remove_caption(remove_caption) {
}
};
inline StringBuilder &operator<<(StringBuilder &string_builder, MessageCopyOptions copy_options) {
if (copy_options.send_copy) {
string_builder << "CopyOptions[remove_caption = " << copy_options.remove_caption << "]";
}
return string_builder;
}
} // namespace td

View File

@ -20536,10 +20536,10 @@ Result<MessageId> MessagesManager::send_message(DialogId dialog_id, MessageId re
LOG(INFO) << "Begin to send message to " << dialog_id << " in reply to " << reply_to_message_id;
if (input_message_content->get_id() == td_api::inputMessageForwarded::ID) {
auto input_message = static_cast<const td_api::inputMessageForwarded *>(input_message_content.get());
auto input_message = td_api::move_object_as<td_api::inputMessageForwarded>(input_message_content);
TRY_RESULT(copy_options, process_message_copy_options(dialog_id, std::move(input_message->copy_options_)));
return forward_message(dialog_id, DialogId(input_message->from_chat_id_), MessageId(input_message->message_id_),
std::move(options), input_message->in_game_share_, input_message->send_copy_,
input_message->remove_caption_);
std::move(options), input_message->in_game_share_, std::move(copy_options));
}
Dialog *d = get_dialog_force(dialog_id);
@ -20556,10 +20556,10 @@ Result<MessageId> MessagesManager::send_message(DialogId dialog_id, MessageId re
// there must be no errors after get_message_to_send call
bool need_update_dialog_pos = false;
Message *m = get_message_to_send(
d, get_reply_to_message_id(d, reply_to_message_id), send_message_options,
dup_message_content(td_, dialog_id, message_content.content.get(), MessageContentDupType::Send),
&need_update_dialog_pos, nullptr, message_content.via_bot_user_id.is_valid());
Message *m = get_message_to_send(d, get_reply_to_message_id(d, reply_to_message_id), send_message_options,
dup_message_content(td_, dialog_id, message_content.content.get(),
MessageContentDupType::Send, MessageCopyOptions()),
&need_update_dialog_pos, nullptr, message_content.via_bot_user_id.is_valid());
m->reply_markup = std::move(message_reply_markup);
m->via_bot_user_id = message_content.via_bot_user_id;
m->disable_web_page_preview = message_content.disable_web_page_preview;
@ -20591,8 +20591,9 @@ Result<InputMessageContent> MessagesManager::process_input_message_content(
}
if (input_message_content->get_id() == td_api::inputMessageForwarded::ID) {
auto input_message = static_cast<const td_api::inputMessageForwarded *>(input_message_content.get());
if (!input_message->send_copy_) {
auto input_message = td_api::move_object_as<td_api::inputMessageForwarded>(input_message_content);
TRY_RESULT(copy_options, process_message_copy_options(dialog_id, std::move(input_message->copy_options_)));
if (!copy_options.send_copy) {
return Status::Error(400, "Can't use forwarded message");
}
@ -20617,9 +20618,8 @@ Result<InputMessageContent> MessagesManager::process_input_message_content(
return Status::Error(400, "Can't copy message");
}
unique_ptr<MessageContent> content = dup_message_content(
td_, dialog_id, copied_message->content.get(),
input_message->remove_caption_ ? MessageContentDupType::CopyWithoutCaption : MessageContentDupType::Copy);
unique_ptr<MessageContent> content = dup_message_content(td_, dialog_id, copied_message->content.get(),
MessageContentDupType::Copy, std::move(copy_options));
if (content == nullptr) {
return Status::Error(400, "Can't copy message content");
}
@ -20644,6 +20644,17 @@ Result<InputMessageContent> MessagesManager::process_input_message_content(
return std::move(content);
}
Result<MessageCopyOptions> MessagesManager::process_message_copy_options(
DialogId dialog_id, tl_object_ptr<td_api::messageCopyOptions> &&options) const {
if (options == nullptr || !options->send_copy_) {
return MessageCopyOptions();
}
MessageCopyOptions result;
result.send_copy = true;
result.remove_caption = options->remove_caption_;
return std::move(result);
}
Result<MessagesManager::SendMessageOptions> MessagesManager::process_send_message_options(
DialogId dialog_id, tl_object_ptr<td_api::sendMessageOptions> &&options) const {
SendMessageOptions result;
@ -20746,10 +20757,10 @@ Result<vector<MessageId>> MessagesManager::send_message_group(
vector<MessageId> result;
bool need_update_dialog_pos = false;
for (auto &message_content : message_contents) {
Message *m = get_message_to_send(
d, reply_to_message_id, send_message_options,
dup_message_content(td_, dialog_id, message_content.first.get(), MessageContentDupType::Send),
&need_update_dialog_pos);
Message *m = get_message_to_send(d, reply_to_message_id, send_message_options,
dup_message_content(td_, dialog_id, message_content.first.get(),
MessageContentDupType::Send, MessageCopyOptions()),
&need_update_dialog_pos);
result.push_back(m->message_id);
auto ttl = message_content.second;
if (ttl > 0) {
@ -21504,10 +21515,10 @@ Result<MessageId> MessagesManager::send_inline_query_result_message(DialogId dia
TRY_STATUS(can_send_message_content(dialog_id, content->message_content.get(), false));
bool need_update_dialog_pos = false;
Message *m = get_message_to_send(
d, get_reply_to_message_id(d, reply_to_message_id), send_message_options,
dup_message_content(td_, dialog_id, content->message_content.get(), MessageContentDupType::SendViaBot),
&need_update_dialog_pos, nullptr, true);
Message *m = get_message_to_send(d, get_reply_to_message_id(d, reply_to_message_id), send_message_options,
dup_message_content(td_, dialog_id, content->message_content.get(),
MessageContentDupType::SendViaBot, MessageCopyOptions()),
&need_update_dialog_pos, nullptr, true);
m->hide_via_bot = hide_via_bot;
if (!hide_via_bot) {
m->via_bot_user_id = td_->inline_queries_manager_->get_inline_bot_user_id(query_id);
@ -22076,7 +22087,8 @@ void MessagesManager::edit_message_media(FullMessageId full_message_id,
cancel_edit_message_media(dialog_id, m, "Cancelled by new editMessageMedia request");
m->edited_content = dup_message_content(td_, dialog_id, content.content.get(), MessageContentDupType::Send);
m->edited_content =
dup_message_content(td_, dialog_id, content.content.get(), MessageContentDupType::Send, MessageCopyOptions());
CHECK(m->edited_content != nullptr);
m->edited_reply_markup = r_new_reply_markup.move_as_ok();
m->edit_generation = ++current_message_edit_generation_;
@ -22914,9 +22926,11 @@ void MessagesManager::do_forward_messages(DialogId to_dialog_id, DialogId from_d
Result<MessageId> MessagesManager::forward_message(DialogId to_dialog_id, DialogId from_dialog_id, MessageId message_id,
tl_object_ptr<td_api::sendMessageOptions> &&options,
bool in_game_share, bool send_copy, bool remove_caption) {
bool in_game_share, MessageCopyOptions &&copy_options) {
vector<MessageCopyOptions> all_copy_options;
all_copy_options.push_back(std::move(copy_options));
TRY_RESULT(result, forward_messages(to_dialog_id, from_dialog_id, {message_id}, std::move(options), in_game_share,
false, send_copy, remove_caption));
false, std::move(all_copy_options)));
CHECK(result.size() == 1);
auto sent_message_id = result[0];
if (sent_message_id == MessageId()) {
@ -22928,8 +22942,9 @@ Result<MessageId> MessagesManager::forward_message(DialogId to_dialog_id, Dialog
Result<vector<MessageId>> MessagesManager::forward_messages(DialogId to_dialog_id, DialogId from_dialog_id,
vector<MessageId> message_ids,
tl_object_ptr<td_api::sendMessageOptions> &&options,
bool in_game_share, bool as_album, bool send_copy,
bool remove_caption) {
bool in_game_share, bool as_album,
vector<MessageCopyOptions> &&copy_options) {
CHECK(copy_options.size() == message_ids.size());
if (message_ids.size() > 100) { // TODO replace with const from config or implement mass-forward
return Status::Error(4, "Too much messages to forward");
}
@ -22997,10 +23012,10 @@ Result<vector<MessageId>> MessagesManager::forward_messages(DialogId to_dialog_i
continue;
}
bool need_copy = !message_id.is_server() || to_secret || send_copy;
auto type = need_copy ? (remove_caption ? MessageContentDupType::CopyWithoutCaption : MessageContentDupType::Copy)
: MessageContentDupType::Forward;
unique_ptr<MessageContent> content = dup_message_content(td_, to_dialog_id, forwarded_message->content.get(), type);
bool need_copy = !message_id.is_server() || to_secret || copy_options[i].send_copy;
auto type = need_copy ? MessageContentDupType::Copy : MessageContentDupType::Forward;
unique_ptr<MessageContent> content =
dup_message_content(td_, to_dialog_id, forwarded_message->content.get(), type, std::move(copy_options[i]));
if (content == nullptr) {
LOG(INFO) << "Can't forward " << message_id;
continue;
@ -23227,7 +23242,7 @@ Result<vector<MessageId>> MessagesManager::resend_messages(DialogId dialog_id, v
CHECK(m != nullptr);
unique_ptr<MessageContent> content =
dup_message_content(td_, dialog_id, m->content.get(), MessageContentDupType::Send);
dup_message_content(td_, dialog_id, m->content.get(), MessageContentDupType::Send, MessageCopyOptions());
if (content == nullptr) {
LOG(INFO) << "Can't resend " << m->message_id;
continue;
@ -32446,7 +32461,8 @@ void MessagesManager::on_binlog_events(vector<BinlogEvent> &&events) {
add_message_dependencies(dependencies, dialog_id, m.get());
resolve_dependencies_force(td_, dependencies);
m->content = dup_message_content(td_, dialog_id, m->content.get(), MessageContentDupType::Send);
m->content =
dup_message_content(td_, dialog_id, m->content.get(), MessageContentDupType::Send, MessageCopyOptions());
auto result_message = continue_send_message(dialog_id, std::move(m), event.id_);
if (result_message != nullptr) {
@ -32512,7 +32528,8 @@ void MessagesManager::on_binlog_events(vector<BinlogEvent> &&events) {
add_message_dependencies(dependencies, dialog_id, m.get());
resolve_dependencies_force(td_, dependencies);
m->content = dup_message_content(td_, dialog_id, m->content.get(), MessageContentDupType::SendViaBot);
m->content = dup_message_content(td_, dialog_id, m->content.get(), MessageContentDupType::SendViaBot,
MessageCopyOptions());
auto result_message = continue_send_message(dialog_id, std::move(m), event.id_);
if (result_message != nullptr) {
@ -32601,7 +32618,8 @@ void MessagesManager::on_binlog_events(vector<BinlogEvent> &&events) {
set_message_id(m, get_next_yet_unsent_message_id(to_dialog));
m->date = now;
}
m->content = dup_message_content(td_, to_dialog_id, m->content.get(), MessageContentDupType::Forward);
m->content = dup_message_content(td_, to_dialog_id, m->content.get(), MessageContentDupType::Forward,
MessageCopyOptions());
CHECK(m->content != nullptr);
m->have_previous = true;
m->have_next = true;

View File

@ -29,6 +29,7 @@
#include "td/telegram/Global.h"
#include "td/telegram/InputDialogId.h"
#include "td/telegram/MessageContentType.h"
#include "td/telegram/MessageCopyOptions.h"
#include "td/telegram/MessageId.h"
#include "td/telegram/MessagesDb.h"
#include "td/telegram/net/NetQuery.h"
@ -386,7 +387,8 @@ class MessagesManager : public Actor {
Result<vector<MessageId>> forward_messages(DialogId to_dialog_id, DialogId from_dialog_id,
vector<MessageId> message_ids,
tl_object_ptr<td_api::sendMessageOptions> &&options, bool in_game_share,
bool as_album, bool send_copy, bool remove_caption) TD_WARN_UNUSED_RESULT;
bool as_album,
vector<MessageCopyOptions> &&copy_options) TD_WARN_UNUSED_RESULT;
Result<vector<MessageId>> resend_messages(DialogId dialog_id, vector<MessageId> message_ids) TD_WARN_UNUSED_RESULT;
@ -1649,6 +1651,9 @@ class MessagesManager : public Actor {
Result<InputMessageContent> process_input_message_content(
DialogId dialog_id, tl_object_ptr<td_api::InputMessageContent> &&input_message_content);
Result<MessageCopyOptions> process_message_copy_options(DialogId dialog_id,
tl_object_ptr<td_api::messageCopyOptions> &&options) const;
Result<SendMessageOptions> process_send_message_options(DialogId dialog_id,
tl_object_ptr<td_api::sendMessageOptions> &&options) const;
@ -1704,7 +1709,7 @@ class MessagesManager : public Actor {
Result<MessageId> forward_message(DialogId to_dialog_id, DialogId from_dialog_id, MessageId message_id,
tl_object_ptr<td_api::sendMessageOptions> &&options, bool in_game_share,
bool send_copy, bool remove_caption) TD_WARN_UNUSED_RESULT;
MessageCopyOptions &&copy_options) TD_WARN_UNUSED_RESULT;
void do_send_media(DialogId dialog_id, Message *m, FileId file_id, FileId thumbnail_file_id,
tl_object_ptr<telegram_api::InputFile> input_file,

View File

@ -1141,6 +1141,7 @@ void SecretChatActor::on_pfs_state_changed() {
LOG(INFO) << "In on_pfs_state_changed: " << pfs_state_;
pfs_state_changed_ = true;
}
Promise<> SecretChatActor::add_changes(Promise<> save_changes_finish) {
StateChange change;
if (seq_no_state_changed_) {

View File

@ -47,6 +47,7 @@
#include "td/telegram/LanguagePackManager.h"
#include "td/telegram/Location.h"
#include "td/telegram/Logging.h"
#include "td/telegram/MessageCopyOptions.h"
#include "td/telegram/MessageEntity.h"
#include "td/telegram/MessageId.h"
#include "td/telegram/MessagesManager.h"
@ -5745,9 +5746,13 @@ void Td::on_request(uint64 id, td_api::sendChatScreenshotTakenNotification &requ
void Td::on_request(uint64 id, 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_),
std::move(request.options_), false, request.as_album_, request.send_copy_, request.remove_caption_);
auto input_message_ids = MessagesManager::get_message_ids(request.message_ids_);
auto message_copy_options =
transform(input_message_ids, [copy_options = MessageCopyOptions(request.send_copy_, request.remove_caption_)](
MessageId) { return copy_options; });
auto r_message_ids = messages_manager_->forward_messages(dialog_id, DialogId(request.from_chat_id_),
std::move(input_message_ids), std::move(request.options_),
false, request.as_album_, std::move(message_copy_options));
if (r_message_ids.is_error()) {
return send_closure(actor_id(this), &Td::send_error, id, r_message_ids.move_as_error());
}

View File

@ -3196,9 +3196,14 @@ class CliClient final : public Actor {
std::tie(chat_id, args) = split(args);
std::tie(from_chat_id, from_message_id) = split(args);
send_message(chat_id, td_api::make_object<td_api::inputMessageForwarded>(as_chat_id(from_chat_id),
as_message_id(from_message_id), true,
op == "scopy", Random::fast(0, 1) == 0));
td_api::object_ptr<td_api::messageCopyOptions> copy_options;
if (op == "scopy") {
copy_options = td_api::make_object<td_api::messageCopyOptions>(true, Random::fast(0, 1) == 0);
}
send_message(chat_id,
td_api::make_object<td_api::inputMessageForwarded>(
as_chat_id(from_chat_id), as_message_id(from_message_id), true, std::move(copy_options)));
} else if (op == "sdice" || op == "sdicecd") {
string chat_id;
string emoji;