From a40494870790811ba46a4c054351be705085c32d Mon Sep 17 00:00:00 2001 From: levlam Date: Sun, 9 Aug 2020 14:18:08 +0300 Subject: [PATCH] Add MessageCopyOptions. GitOrigin-RevId: a61b93c3c215c42c9a7f30195cc637187472751e --- CMakeLists.txt | 1 + SplitSource.php | 1 + td/generate/scheme/td_api.tl | 10 ++-- td/generate/scheme/td_api.tlo | Bin 177824 -> 177972 bytes td/telegram/MessageContent.cpp | 7 ++- td/telegram/MessageContent.h | 5 +- td/telegram/MessageCopyOptions.h | 30 +++++++++++ td/telegram/MessagesManager.cpp | 84 +++++++++++++++++++------------ td/telegram/MessagesManager.h | 9 +++- td/telegram/SecretChatActor.cpp | 1 + td/telegram/Td.cpp | 11 ++-- td/telegram/cli.cpp | 11 ++-- 12 files changed, 122 insertions(+), 48 deletions(-) create mode 100644 td/telegram/MessageCopyOptions.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 1be7afdfc..2821cfca6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 diff --git a/SplitSource.php b/SplitSource.php index 910be1ffc..76f261a69 100644 --- a/SplitSource.php +++ b/SplitSource.php @@ -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', diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 28fdc4d38..9734db81b 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -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 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 diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index fb827299809f520614104d20de7616de1624a33b..34c03096a64bb3fd2eff6180669b214aafafdad0 100644 GIT binary patch delta 865 zcmZ4RmTSv9F5XA8^{p77KyV}PabcGI4NJ~#z9F2!D*kI%)C?it)Z*gA^i=2kf=d5_ zlFa!TqT-D$N1;@=}LOv{$d$&qY{(lj>~nZIXTy-Ko#A9DY}sYRW#)$#QMnxZq9)yO1K3T>A3|J z(YcMVo@u(^7e?*L8%`=rUZBqb(Xr(=)S^4L4Im-{cc3B`cc3CUcU0hBV4B|B$EY!R zNhBI2VI!7C*L@sGC9BsYJSOGsI%wXT>y2q!+oew#(fz^Q&8Bz6347qg`qK^WF{)1HeW-50lMGB*@%fOX1vQMr zw(TG&@i9XAMb2zGATe;#?0BeSr3g-%xfn^40VEEJEvD&=dQ9OgAnx`R(u@&L!9JdT zK$A&fy9y(dj0!8*?b8|mGRkjHQDw4WL>4%r#^eJ@h!7nnnoI)7{0wcTJ#h#Vr+aiU Soq+03^k`!ZJpk$xAN9Kn!QOtN~_hHn^++RUL9g1tM2-*kniB2d#xu0u_mbA1X_ z(G8fQ8!1plM{Yt~G5N#IIS@q?Zb3!%+=7b4+(tNpY5GPDCiUqBJd7%nFX(eXv^=>D zwTb7B0Yt>%4n$~XwDrKxL25_EA}&LOul(Z9im+3E|T2j+=<$gIZmofckp83 zWCnVE@{+qycb~bt0P607`%s}7_hlGOK|usdC0FIRV%Gke9x0lcS5R8wn_66)n4apE zUsRr0l#-glzyJ$Q*6AO0ne?YGP-jw^Z1YfK`W!u`0I+K|PkE?gwcSI8(dQ{E*x>1m z8cg!rcQ7)^z&!PzQDOTJRVEvVW2P@y!KAo7Qk}`030cDlO(p>pfj` get_message_content(Td *td, FormattedText message, } unique_ptr dup_message_content(Td *td, DialogId dialog_id, const MessageContent *content, - MessageContentDupType type) { + MessageContentDupType type, MessageCopyOptions &©_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 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(*static_cast(content)); diff --git a/td/telegram/MessageContent.h b/td/telegram/MessageContent.h index 3b4ef1bb2..19e58de04 100644 --- a/td/telegram/MessageContent.h +++ b/td/telegram/MessageContent.h @@ -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 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 dup_message_content(Td *td, DialogId dialog_id, const MessageContent *content, - MessageContentDupType type); + MessageContentDupType type, MessageCopyOptions &©_options); unique_ptr get_action_message_content(Td *td, tl_object_ptr &&action, DialogId owner_dialog_id, MessageId reply_to_message_id); diff --git a/td/telegram/MessageCopyOptions.h b/td/telegram/MessageCopyOptions.h new file mode 100644 index 000000000..13b380615 --- /dev/null +++ b/td/telegram/MessageCopyOptions.h @@ -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 diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 0a9f777e1..420bc0dee 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -20536,10 +20536,10 @@ Result 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(input_message_content.get()); + auto input_message = td_api::move_object_as(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 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 MessagesManager::process_input_message_content( } if (input_message_content->get_id() == td_api::inputMessageForwarded::ID) { - auto input_message = static_cast(input_message_content.get()); - if (!input_message->send_copy_) { + auto input_message = td_api::move_object_as(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 MessagesManager::process_input_message_content( return Status::Error(400, "Can't copy message"); } - unique_ptr content = dup_message_content( - td_, dialog_id, copied_message->content.get(), - input_message->remove_caption_ ? MessageContentDupType::CopyWithoutCaption : MessageContentDupType::Copy); + unique_ptr 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 MessagesManager::process_input_message_content( return std::move(content); } +Result MessagesManager::process_message_copy_options( + DialogId dialog_id, tl_object_ptr &&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::process_send_message_options( DialogId dialog_id, tl_object_ptr &&options) const { SendMessageOptions result; @@ -20746,10 +20757,10 @@ Result> MessagesManager::send_message_group( vector 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 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 MessagesManager::forward_message(DialogId to_dialog_id, DialogId from_dialog_id, MessageId message_id, tl_object_ptr &&options, - bool in_game_share, bool send_copy, bool remove_caption) { + bool in_game_share, MessageCopyOptions &©_options) { + vector 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 MessagesManager::forward_message(DialogId to_dialog_id, Dialog Result> MessagesManager::forward_messages(DialogId to_dialog_id, DialogId from_dialog_id, vector message_ids, tl_object_ptr &&options, - bool in_game_share, bool as_album, bool send_copy, - bool remove_caption) { + bool in_game_share, bool as_album, + vector &©_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> 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 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 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> MessagesManager::resend_messages(DialogId dialog_id, v CHECK(m != nullptr); unique_ptr 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 &&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 &&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 &&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; diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index c83d753ce..8ac1169eb 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -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> forward_messages(DialogId to_dialog_id, DialogId from_dialog_id, vector message_ids, tl_object_ptr &&options, bool in_game_share, - bool as_album, bool send_copy, bool remove_caption) TD_WARN_UNUSED_RESULT; + bool as_album, + vector &©_options) TD_WARN_UNUSED_RESULT; Result> resend_messages(DialogId dialog_id, vector message_ids) TD_WARN_UNUSED_RESULT; @@ -1649,6 +1651,9 @@ class MessagesManager : public Actor { Result process_input_message_content( DialogId dialog_id, tl_object_ptr &&input_message_content); + Result process_message_copy_options(DialogId dialog_id, + tl_object_ptr &&options) const; + Result process_send_message_options(DialogId dialog_id, tl_object_ptr &&options) const; @@ -1704,7 +1709,7 @@ class MessagesManager : public Actor { Result forward_message(DialogId to_dialog_id, DialogId from_dialog_id, MessageId message_id, tl_object_ptr &&options, bool in_game_share, - bool send_copy, bool remove_caption) TD_WARN_UNUSED_RESULT; + MessageCopyOptions &©_options) TD_WARN_UNUSED_RESULT; void do_send_media(DialogId dialog_id, Message *m, FileId file_id, FileId thumbnail_file_id, tl_object_ptr input_file, diff --git a/td/telegram/SecretChatActor.cpp b/td/telegram/SecretChatActor.cpp index 88ede3c2f..90f99caa7 100644 --- a/td/telegram/SecretChatActor.cpp +++ b/td/telegram/SecretChatActor.cpp @@ -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_) { diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 3488e2fd0..f631cfb98 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -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()); } diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 0ab154afb..366046111 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -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(as_chat_id(from_chat_id), - as_message_id(from_message_id), true, - op == "scopy", Random::fast(0, 1) == 0)); + td_api::object_ptr copy_options; + if (op == "scopy") { + copy_options = td_api::make_object(true, Random::fast(0, 1) == 0); + } + + send_message(chat_id, + td_api::make_object( + 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;