diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index df631bade..c8e509af6 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -1483,7 +1483,7 @@ inputThumbnail thumbnail:InputFile width:int32 height:int32 = InputThumbnail; //@class MessageSchedulingState @description Contains information about the time when a scheduled message will be sent -//@description The message will be sent at the specified date @send_date Date the message will be sent +//@description The message will be sent at the specified date @send_date Date the message will be sent. The date must be within 367 days in the future messageSchedulingStateSendAtDate send_date:int32 = MessageSchedulingState; //@description The message will be sent when the peer will be online. Applicable to private chats only and when the exact online status of the peer is known @@ -3339,6 +3339,9 @@ editInlineMessageCaption inline_message_id:string reply_markup:ReplyMarkup capti //@description Edits the reply markup of an inline message sent via a bot; for bots only @inline_message_id Inline message identifier @reply_markup The new message reply markup editInlineMessageReplyMarkup inline_message_id:string reply_markup:ReplyMarkup = Ok; +//@description Edits the time when a scheduled message will be sent @chat_id The chat the message belongs to @message_id Identifier of the message @scheduling_state The new message scheduling state. Pass null to send the message immediately +editMessageSchedulingState chat_id:int53 message_id:int53 scheduling_state:MessageSchedulingState = Ok; + //@description Returns all entities (mentions, hashtags, cashtags, bot commands, URLs, and email addresses) contained in the text. This is an offline method. Can be called before authorization. Can be called synchronously @text The text in which to look for entites getTextEntities text:string = TextEntities; diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index bc35afe92..2275dd431 100644 Binary files a/td/generate/scheme/td_api.tlo and b/td/generate/scheme/td_api.tlo differ diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 9108834f3..56772186f 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -2369,7 +2369,8 @@ class EditMessageActor : public NetActorOnce { void send(int32 flags, DialogId dialog_id, MessageId message_id, const string &text, vector> &&entities, tl_object_ptr &&input_media, - tl_object_ptr &&reply_markup, uint64 sequence_dispatcher_id) { + tl_object_ptr &&reply_markup, int32 schedule_date, + uint64 sequence_dispatcher_id) { dialog_id_ = dialog_id; if (false && input_media != nullptr) { @@ -2397,11 +2398,16 @@ class EditMessageActor : public NetActorOnce { if (input_media != nullptr) { flags |= telegram_api::messages_editMessage::MEDIA_MASK; } + if (schedule_date != 0) { + flags |= telegram_api::messages_editMessage::SCHEDULE_DATE_MASK; + } LOG(DEBUG) << "Edit message with flags " << flags; + int32 server_message_id = schedule_date != 0 ? message_id.get_scheduled_server_message_id().get() + : message_id.get_server_message_id().get(); auto query = G()->net_query_creator().create(create_storer(telegram_api::messages_editMessage( - flags, false /*ignored*/, std::move(input_peer), message_id.get_server_message_id().get(), text, - std::move(input_media), std::move(reply_markup), std::move(entities), 0))); + flags, false /*ignored*/, std::move(input_peer), server_message_id, text, std::move(input_media), + std::move(reply_markup), std::move(entities), schedule_date))); query->debug("send to MessagesManager::MultiSequenceDispatcher"); send_closure(td->messages_manager_->sequence_dispatcher_, &MultiSequenceDispatcher::send_with_callback, @@ -16771,6 +16777,35 @@ void MessagesManager::load_messages(DialogId dialog_id, MessageId from_message_i get_history(dialog_id, from_message_id, offset, limit, from_database, only_local, std::move(promise)); } +Result MessagesManager::get_message_schedule_date( + td_api::object_ptr &&scheduling_state) { + if (scheduling_state == nullptr) { + return 0; + } + + switch (scheduling_state->get_id()) { + case td_api::messageSchedulingStateSendWhenOnline::ID: + return SCHEDULE_WHEN_ONLINE_DATE; + case td_api::messageSchedulingStateSendAtDate::ID: { + auto send_at_date = td_api::move_object_as(scheduling_state); + auto send_date = send_at_date->send_date_; + if (send_date <= 0) { + return Status::Error(400, "Invalid send date specified"); + } + if (send_date <= G()->unix_time()) { + return 0; + } + if (send_date - G()->unix_time() > 367 * 86400) { + return Status::Error(400, "Send date is too far in the future"); + } + return send_date; + } + default: + UNREACHABLE(); + return 0; + } +} + tl_object_ptr MessagesManager::get_message_sending_state_object(const Message *m) { CHECK(m != nullptr); if (m->message_id.is_yet_unsent()) { @@ -17772,7 +17807,7 @@ void MessagesManager::on_message_media_uploaded(DialogId dialog_id, const Messag send_closure(td_->create_net_actor(std::move(promise)), &EditMessageActor::send, 1 << 11, dialog_id, message_id, caption == nullptr ? "" : caption->text, get_input_message_entities(td_->contacts_manager_.get(), caption, "edit_message_media"), - std::move(input_media), std::move(input_reply_markup), + std::move(input_media), std::move(input_reply_markup), 0, get_sequence_dispatcher_id(dialog_id, MessageContentType::None)); return; } @@ -18703,7 +18738,7 @@ void MessagesManager::edit_message_text(FullMessageId full_message_id, td_->create_net_actor(std::move(promise)), &EditMessageActor::send, flags, dialog_id, message_id, input_message_text.text.text, get_input_message_entities(td_->contacts_manager_.get(), input_message_text.text.entities, "edit_message_text"), - nullptr, std::move(input_reply_markup), get_sequence_dispatcher_id(dialog_id, MessageContentType::None)); + nullptr, std::move(input_reply_markup), 0, get_sequence_dispatcher_id(dialog_id, MessageContentType::None)); } void MessagesManager::edit_message_live_location(FullMessageId full_message_id, @@ -18760,7 +18795,7 @@ void MessagesManager::edit_message_live_location(FullMessageId full_message_id, location.get_input_geo_point(), 0); send_closure(td_->create_net_actor(std::move(promise)), &EditMessageActor::send, 0, dialog_id, message_id, string(), vector>(), std::move(input_media), - std::move(input_reply_markup), get_sequence_dispatcher_id(dialog_id, MessageContentType::None)); + std::move(input_reply_markup), 0, get_sequence_dispatcher_id(dialog_id, MessageContentType::None)); } void MessagesManager::cancel_edit_message_media(DialogId dialog_id, Message *m, Slice error_message) { @@ -18967,7 +19002,8 @@ void MessagesManager::edit_message_caption(FullMessageId full_message_id, send_closure(td_->create_net_actor(std::move(promise)), &EditMessageActor::send, 1 << 11, dialog_id, message_id, caption.text, get_input_message_entities(td_->contacts_manager_.get(), caption.entities, "edit_message_caption"), - nullptr, std::move(input_reply_markup), get_sequence_dispatcher_id(dialog_id, MessageContentType::None)); + nullptr, std::move(input_reply_markup), 0, + get_sequence_dispatcher_id(dialog_id, MessageContentType::None)); } void MessagesManager::edit_message_reply_markup(FullMessageId full_message_id, @@ -19006,7 +19042,7 @@ void MessagesManager::edit_message_reply_markup(FullMessageId full_message_id, auto input_reply_markup = get_input_reply_markup(r_new_reply_markup.ok()); send_closure(td_->create_net_actor(std::move(promise)), &EditMessageActor::send, 0, dialog_id, message_id, string(), vector>(), nullptr, - std::move(input_reply_markup), get_sequence_dispatcher_id(dialog_id, MessageContentType::None)); + std::move(input_reply_markup), 0, get_sequence_dispatcher_id(dialog_id, MessageContentType::None)); } void MessagesManager::edit_inline_message_text(const string &inline_message_id, @@ -19192,6 +19228,47 @@ void MessagesManager::edit_inline_message_reply_markup(const string &inline_mess nullptr, get_input_reply_markup(r_new_reply_markup.ok())); } +void MessagesManager::edit_message_scheduling_state( + FullMessageId full_message_id, td_api::object_ptr &&scheduling_state, + Promise &&promise) { + auto r_schedule_date = get_message_schedule_date(std::move(scheduling_state)); + if (r_schedule_date.is_error()) { + return promise.set_error(r_schedule_date.move_as_error()); + } + auto schedule_date = r_schedule_date.move_as_ok(); + + LOG(INFO) << "Begin to reschedule " << full_message_id << " to " << schedule_date; + + auto dialog_id = full_message_id.get_dialog_id(); + Dialog *d = get_dialog_force(dialog_id); + if (d == nullptr) { + return promise.set_error(Status::Error(5, "Chat not found")); + } + + if (!have_input_peer(dialog_id, AccessRights::Edit)) { + return promise.set_error(Status::Error(5, "Can't access the chat")); + } + + auto message_id = full_message_id.get_message_id(); + const Message *m = get_message_force(d, message_id, "edit_message_scheduling_state"); + if (m == nullptr) { + return promise.set_error(Status::Error(5, "Message not found")); + } + + if (!message_id.is_scheduled()) { + return promise.set_error(Status::Error(5, "Message is not scheduled")); + } + + if (schedule_date > 0) { + send_closure(td_->create_net_actor(std::move(promise)), &EditMessageActor::send, 0, dialog_id, + message_id, string(), vector>(), nullptr, nullptr, + schedule_date, get_sequence_dispatcher_id(dialog_id, MessageContentType::None)); + } else { + // TODO immediately send the message + promise.set_value(Unit()); + } +} + int32 MessagesManager::get_message_flags(const Message *m) { int32 flags = 0; if (m->reply_to_message_id.is_valid()) { diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index ba7ccd531..aca5dfc70 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -409,6 +409,10 @@ class MessagesManager : public Actor { void edit_inline_message_reply_markup(const string &inline_message_id, tl_object_ptr &&reply_markup, Promise &&promise); + void edit_message_scheduling_state(FullMessageId full_message_id, + td_api::object_ptr &&scheduling_state, + Promise &&promise); + void set_game_score(FullMessageId full_message_id, bool edit_message, UserId user_id, int32 score, bool force, Promise &&promise); @@ -1857,6 +1861,8 @@ class MessagesManager : public Actor { void hide_dialog_action_bar(Dialog *d); + static Result get_message_schedule_date(td_api::object_ptr &&scheduling_state); + static tl_object_ptr get_message_sending_state_object(const Message *m); static tl_object_ptr get_message_scheduling_state_object(int32 send_date); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 0dc5ac031..21b9e5adf 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -1336,6 +1336,24 @@ class EditMessageReplyMarkupRequest : public RequestOnceActor { } }; +class EditMessageSchedulingStateRequest : public RequestOnceActor { + FullMessageId full_message_id_; + td_api::object_ptr scheduling_state_; + + void do_run(Promise &&promise) override { + td->messages_manager_->edit_message_scheduling_state(full_message_id_, std::move(scheduling_state_), + std::move(promise)); + } + + public: + EditMessageSchedulingStateRequest(ActorShared td, uint64 request_id, int64 dialog_id, int64 message_id, + td_api::object_ptr scheduling_state) + : RequestOnceActor(std::move(td), request_id) + , full_message_id_(DialogId(dialog_id), MessageId(message_id)) + , scheduling_state_(std::move(scheduling_state)) { + } +}; + class SetGameScoreRequest : public RequestOnceActor { FullMessageId full_message_id_; bool edit_message_; @@ -5815,6 +5833,12 @@ void Td::on_request(uint64 id, td_api::editInlineMessageReplyMarkup &request) { std::move(request.reply_markup_), std::move(promise)); } +void Td::on_request(uint64 id, td_api::editMessageSchedulingState &request) { + CHECK_IS_USER(); + CREATE_REQUEST(EditMessageSchedulingStateRequest, request.chat_id_, request.message_id_, + std::move(request.scheduling_state_)); +} + void Td::on_request(uint64 id, td_api::setGameScore &request) { CHECK_IS_BOT(); CREATE_REQUEST(SetGameScoreRequest, request.chat_id_, request.message_id_, request.edit_message_, request.user_id_, diff --git a/td/telegram/Td.h b/td/telegram/Td.h index c5b620cfc..8f6df9ddb 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -602,6 +602,8 @@ class Td final : public NetQueryCallback { void on_request(uint64 id, td_api::editInlineMessageReplyMarkup &request); + void on_request(uint64 id, td_api::editMessageSchedulingState &request); + void on_request(uint64 id, td_api::setGameScore &request); void on_request(uint64 id, td_api::setInlineGameScore &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 7057a4024..3baddea31 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -536,20 +536,20 @@ class CliClient final : public Actor { return td_api::make_object(as_file_id(str)); } - static tl_object_ptr as_local_file(string path) { + static td_api::object_ptr as_local_file(string path) { return td_api::make_object(trim(std::move(path))); } - static tl_object_ptr as_remote_file(string id) { + static td_api::object_ptr as_remote_file(string id) { return td_api::make_object(trim(std::move(id))); } - static tl_object_ptr as_generated_file(string original_path, string conversion, - int32 expected_size = 0) { + static td_api::object_ptr as_generated_file(string original_path, string conversion, + int32 expected_size = 0) { return td_api::make_object(trim(original_path), trim(conversion), expected_size); } - static tl_object_ptr as_input_file(string str) { + static td_api::object_ptr as_input_file(string str) { str = trim(str); if ((str.size() >= 20 && is_base64url(str)) || begins_with(str, "http")) { return as_remote_file(str); @@ -565,18 +565,19 @@ class CliClient final : public Actor { return as_local_file(str); } - static tl_object_ptr as_input_thumbnail(tl_object_ptr input_file, - int32 width = 0, int32 height = 0) { + static td_api::object_ptr as_input_thumbnail(td_api::object_ptr input_file, + int32 width = 0, int32 height = 0) { return td_api::make_object(std::move(input_file), width, height); } - static tl_object_ptr as_input_thumbnail(const string &thumbnail, int32 width = 0, - int32 height = 0) { + static td_api::object_ptr as_input_thumbnail(const string &thumbnail, int32 width = 0, + int32 height = 0) { return as_input_thumbnail(as_input_file(thumbnail), width, height); } - static tl_object_ptr as_input_thumbnail(const string &original_path, const string &conversion, - int32 width = 0, int32 height = 0) { + static td_api::object_ptr as_input_thumbnail(const string &original_path, + const string &conversion, int32 width = 0, + int32 height = 0) { return as_input_thumbnail(as_generated_file(original_path, conversion), width, height); } @@ -588,7 +589,7 @@ class CliClient final : public Actor { return to_integer(trim(std::move(str))); } - static tl_object_ptr as_location(string latitude, string longitude) { + static td_api::object_ptr as_location(string latitude, string longitude) { if (trim(latitude).empty() && trim(longitude).empty()) { return nullptr; } @@ -605,7 +606,7 @@ class CliClient final : public Actor { return transform(transform(full_split(ids_string, delimiter), trim), to_integer); } - void on_result(uint64 generation, uint64 id, tl_object_ptr result) { + void on_result(uint64 generation, uint64 id, td_api::object_ptr result) { if (id > 0 && GET_VERBOSITY_LEVEL() < VERBOSITY_NAME(td_requests)) { LOG(ERROR) << "Receive result [" << generation << "][id=" << id << "] " << to_string(result); } @@ -713,7 +714,7 @@ class CliClient final : public Actor { } } - void on_error(uint64 generation, uint64 id, tl_object_ptr error) { + void on_error(uint64 generation, uint64 id, td_api::object_ptr error) { if (id > 0 && GET_VERBOSITY_LEVEL() < VERBOSITY_NAME(td_requests)) { LOG(ERROR) << "Receive error [" << generation << "][id=" << id << "] " << to_string(error); } @@ -781,10 +782,10 @@ class CliClient final : public Actor { public: TdCallbackImpl(CliClient *client, uint64 generation) : client_(client), generation_(generation) { } - void on_result(uint64 id, tl_object_ptr result) override { + void on_result(uint64 id, td_api::object_ptr result) override { client_->on_result(generation_, id, std::move(result)); } - void on_error(uint64 id, tl_object_ptr error) override { + void on_error(uint64 id, td_api::object_ptr error) override { client_->on_error(generation_, id, std::move(error)); } TdCallbackImpl(const TdCallbackImpl &) = delete; @@ -897,7 +898,7 @@ class CliClient final : public Actor { } #endif - static tl_object_ptr as_formatted_text( + static td_api::object_ptr as_formatted_text( string text, vector> entities = {}) { if (entities.empty() && !text.empty()) { auto parsed_text = execute( @@ -909,12 +910,12 @@ class CliClient final : public Actor { return td_api::make_object(text, std::move(entities)); } - static tl_object_ptr as_caption(string caption, - vector> entities = {}) { + static td_api::object_ptr as_caption( + string caption, vector> entities = {}) { return as_formatted_text(caption, std::move(entities)); } - static tl_object_ptr get_notification_settings_scope(Slice scope) { + static td_api::object_ptr get_notification_settings_scope(Slice scope) { if (scope.empty()) { return nullptr; } @@ -927,7 +928,7 @@ class CliClient final : public Actor { return td_api::make_object(); } - static tl_object_ptr get_user_privacy_setting(MutableSlice setting) { + static td_api::object_ptr get_user_privacy_setting(MutableSlice setting) { setting = trim(setting); to_lower_inplace(setting); if (setting == "invite") { @@ -957,7 +958,7 @@ class CliClient final : public Actor { return nullptr; } - static tl_object_ptr get_search_messages_filter(MutableSlice filter) { + static td_api::object_ptr get_search_messages_filter(MutableSlice filter) { filter = trim(filter); to_lower_inplace(filter); if (filter == "an" || filter == "animation") { @@ -1011,7 +1012,7 @@ class CliClient final : public Actor { return nullptr; } - static tl_object_ptr get_chat_members_filter(MutableSlice filter) { + static td_api::object_ptr get_chat_members_filter(MutableSlice filter) { filter = trim(filter); to_lower_inplace(filter); if (filter == "a" || filter == "admin" || filter == "administrators") { @@ -1038,7 +1039,7 @@ class CliClient final : public Actor { return nullptr; } - static tl_object_ptr get_top_chat_category(MutableSlice category) { + static td_api::object_ptr get_top_chat_category(MutableSlice category) { category = trim(category); to_lower_inplace(category); if (!category.empty() && category.back() == 's') { @@ -1061,7 +1062,7 @@ class CliClient final : public Actor { } } - static tl_object_ptr get_chat_action(MutableSlice action) { + static td_api::object_ptr get_chat_action(MutableSlice action) { action = trim(action); to_lower_inplace(action); if (action == "c" || action == "cancel") { @@ -1103,7 +1104,7 @@ class CliClient final : public Actor { return td_api::make_object(); } - static tl_object_ptr get_network_type(MutableSlice type) { + static td_api::object_ptr get_network_type(MutableSlice type) { type = trim(type); to_lower_inplace(type); if (type == "none") { @@ -1124,7 +1125,7 @@ class CliClient final : public Actor { return nullptr; } - static tl_object_ptr as_passport_element_type(Slice passport_element_type) { + static td_api::object_ptr as_passport_element_type(Slice passport_element_type) { if (passport_element_type == "address" || passport_element_type == "a") { return td_api::make_object(); } @@ -1162,8 +1163,8 @@ class CliClient final : public Actor { return transform(full_split(types, delimiter), [](Slice str) { return as_passport_element_type(str); }); } - static tl_object_ptr as_input_passport_element(string passport_element_type, string arg, - bool with_selfie) { + static td_api::object_ptr as_input_passport_element(string passport_element_type, + string arg, bool with_selfie) { vector> input_files; td_api::object_ptr selfie; if (!arg.empty()) { @@ -1239,7 +1240,16 @@ class CliClient final : public Actor { true, true, -1, 5, 3, "abacaba"); } - static td_api::object_ptr execute(tl_object_ptr f) { + static td_api::object_ptr as_message_scheduling_state(Slice date) { + date = trim(date); + auto send_date = to_integer(date); + if (send_date == -1) { + return td_api::make_object(); + } + return td_api::make_object(send_date); + } + + static td_api::object_ptr execute(td_api::object_ptr f) { if (GET_VERBOSITY_LEVEL() < VERBOSITY_NAME(td_requests)) { LOG(ERROR) << "Execute request: " << to_string(f); } @@ -1250,7 +1260,7 @@ class CliClient final : public Actor { return res; } - uint64 send_request(tl_object_ptr f) { + uint64 send_request(td_api::object_ptr f) { static uint64 query_num = 1; if (!td_client_.empty()) { auto id = query_num++; @@ -1573,7 +1583,7 @@ class CliClient final : public Actor { std::tie(setting, args) = split(args); std::tie(allow, ids) = split(args); - std::vector> rules; + std::vector> rules; if (allow == "c" || allow == "contacts") { rules.push_back(td_api::make_object()); } else if (allow == "users") { @@ -1616,7 +1626,7 @@ class CliClient final : public Actor { send_request(td_api::make_object(as_user_id(user_id))); } else if (op == "ImportContacts" || op == "cic") { vector contacts_str = full_split(args, ';'); - vector> contacts; + vector> contacts; for (auto c : contacts_str) { string phone_number; string first_name; @@ -1952,7 +1962,7 @@ class CliClient final : public Actor { std::tie(name, args) = split(args); std::tie(native_name, key) = split(args); - vector> strings; + vector> strings; strings.push_back(td_api::make_object( key, td_api::make_object("Ordinary value"))); strings.push_back(td_api::make_object( @@ -1981,7 +1991,8 @@ class CliClient final : public Actor { std::tie(language_code, args) = split(args); std::tie(key, value) = split(args); - tl_object_ptr str = td_api::make_object(key, nullptr); + td_api::object_ptr str = + td_api::make_object(key, nullptr); if (op == "sclsv") { str->value_ = td_api::make_object(value); } else if (op == "sclsp") { @@ -2154,17 +2165,17 @@ class CliClient final : public Actor { std::tie(chat_ids, args) = split(args); std::tie(exclude_chat_ids, chat_ids_limit) = split(args); send_request(td_api::make_object( - 10000000, -1, -1, 0, std::vector>(), as_chat_ids(chat_ids, ','), + 10000000, -1, -1, 0, std::vector>(), as_chat_ids(chat_ids, ','), as_chat_ids(exclude_chat_ids, ','), to_integer(chat_ids_limit))); } else if (op == "clean_storage_default") { send_request(td_api::make_object()); } else if (op == "clean_photos") { - std::vector> types; + std::vector> types; types.push_back(td_api::make_object()); send_request(td_api::make_object(0, 0, 0, 0, std::move(types), as_chat_ids(""), as_chat_ids(""), 20)); } else if (op == "clean_storage") { - std::vector> types; + std::vector> types; types.push_back(td_api::make_object()); types.push_back(td_api::make_object()); types.push_back(td_api::make_object()); @@ -2664,9 +2675,9 @@ class CliClient final : public Actor { string message; std::tie(chat_id, args) = split(args); std::tie(reply_to_message_id, message) = split(args); - tl_object_ptr draft_message; + td_api::object_ptr draft_message; if (!reply_to_message_id.empty() || !message.empty()) { - vector> entities; + vector> entities; entities.push_back( td_api::make_object(0, 1, td_api::make_object())); @@ -2779,7 +2790,7 @@ class CliClient final : public Actor { send_request(td_api::make_object( as_chat_id(chat_id), as_message_id(reply_to_message_id), false, false, transform(photos, [](const string &photo_path) { - tl_object_ptr content = td_api::make_object( + td_api::object_ptr content = td_api::make_object( as_input_file(photo_path), nullptr, Auto(), 0, 0, as_caption(""), 0); return content; }))); @@ -2861,6 +2872,14 @@ class CliClient final : public Actor { std::tie(latitude, longitude) = split(args); send_request(td_api::make_object(as_chat_id(chat_id), as_message_id(message_id), nullptr, as_location(latitude, longitude))); + } else if (op == "emss") { + string chat_id; + string message_id; + string date; + std::tie(chat_id, args) = split(args); + std::tie(message_id, date) = split(args); + send_request(td_api::make_object( + as_chat_id(chat_id), as_message_id(message_id), as_message_scheduling_state(date))); } else if (op == "gallm") { send_request(td_api::make_object()); } else if (op == "sbsm") { @@ -3394,7 +3413,7 @@ class CliClient final : public Actor { string chat_id; string user_id; string status_str; - tl_object_ptr status; + td_api::object_ptr status; std::tie(chat_id, args) = split(args); std::tie(user_id, status_str) = split(args); @@ -3691,7 +3710,7 @@ class CliClient final : public Actor { std::tie(chat_id, args) = split(args); std::tie(reason_str, message_ids) = split(args); - tl_object_ptr reason; + td_api::object_ptr reason; if (reason_str == "spam") { reason = td_api::make_object(); } else if (reason_str == "violence") {